File Index
Files and directories
Sign in
FILE

command_table.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dc/bios/command_table.c C
   1/*
   2 * Copyright 2012-15 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: AMD
  23 *
  24 */
  25
  26#include "dm_services.h"
  27#include "amdgpu.h"
  28#include "atom.h"
  29
  30#include "include/bios_parser_interface.h"
  31
  32#include "command_table.h"
  33#include "command_table_helper.h"
  34#include "bios_parser_helper.h"
  35#include "bios_parser_types_internal.h"
  36
  37#define EXEC_BIOS_CMD_TABLE(command, params)\
  38	(amdgpu_atom_execute_table(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \
  39		GetIndexIntoMasterTable(COMMAND, command), \
  40		(uint32_t *)&params, sizeof(params)) == 0)
  41
  42#define BIOS_CMD_TABLE_REVISION(command, frev, crev)\
  43	amdgpu_atom_parse_cmd_header(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \
  44		GetIndexIntoMasterTable(COMMAND, command), &frev, &crev)
  45
  46#define BIOS_CMD_TABLE_PARA_REVISION(command)\
  47	bios_cmd_table_para_revision(bp->base.ctx->driver_context, \
  48		GetIndexIntoMasterTable(COMMAND, command))
  49
  50static void init_dig_encoder_control(struct bios_parser *bp);
  51static void init_transmitter_control(struct bios_parser *bp);
  52static void init_set_pixel_clock(struct bios_parser *bp);
  53static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp);
  54static void init_adjust_display_pll(struct bios_parser *bp);
  55static void init_select_crtc_source(struct bios_parser *bp);
  56static void init_dac_encoder_control(struct bios_parser *bp);
  57static void init_dac_load_detection(struct bios_parser *bp);
  58static void init_dac_output_control(struct bios_parser *bp);
  59static void init_set_crtc_timing(struct bios_parser *bp);
  60static void init_enable_crtc(struct bios_parser *bp);
  61static void init_enable_crtc_mem_req(struct bios_parser *bp);
  62static void init_external_encoder_control(struct bios_parser *bp);
  63static void init_enable_disp_power_gating(struct bios_parser *bp);
  64static void init_program_clock(struct bios_parser *bp);
  65static void init_set_dce_clock(struct bios_parser *bp);
  66
  67void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
  68{
  69	init_dig_encoder_control(bp);
  70	init_transmitter_control(bp);
  71	init_set_pixel_clock(bp);
  72	init_enable_spread_spectrum_on_ppll(bp);
  73	init_adjust_display_pll(bp);
  74	init_select_crtc_source(bp);
  75	init_dac_encoder_control(bp);
  76	init_dac_load_detection(bp);
  77	init_dac_output_control(bp);
  78	init_set_crtc_timing(bp);
  79	init_enable_crtc(bp);
  80	init_enable_crtc_mem_req(bp);
  81	init_program_clock(bp);
  82	init_external_encoder_control(bp);
  83	init_enable_disp_power_gating(bp);
  84	init_set_dce_clock(bp);
  85}
  86
  87static uint32_t bios_cmd_table_para_revision(void *dev,
  88					     uint32_t index)
  89{
  90	struct amdgpu_device *adev = dev;
  91	uint8_t frev, crev;
  92
  93	if (amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context,
  94					index,
  95					&frev, &crev))
  96		return crev;
  97	else
  98		return 0;
  99}
 100
 101/*******************************************************************************
 102 ********************************************************************************
 103 **
 104 **                  D I G E N C O D E R C O N T R O L
 105 **
 106 ********************************************************************************
 107 *******************************************************************************/
 108static enum bp_result encoder_control_digx_v3(
 109	struct bios_parser *bp,
 110	struct bp_encoder_control *cntl);
 111
 112static enum bp_result encoder_control_digx_v4(
 113	struct bios_parser *bp,
 114	struct bp_encoder_control *cntl);
 115
 116static enum bp_result encoder_control_digx_v5(
 117	struct bios_parser *bp,
 118	struct bp_encoder_control *cntl);
 119
 120static void init_encoder_control_dig_v1(struct bios_parser *bp);
 121
 122static void init_dig_encoder_control(struct bios_parser *bp)
 123{
 124	uint32_t version =
 125		BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl);
 126
 127	switch (version) {
 128	case 2:
 129		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3;
 130		break;
 131	case 4:
 132		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4;
 133		break;
 134
 135	case 5:
 136		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5;
 137		break;
 138
 139	default:
 140		init_encoder_control_dig_v1(bp);
 141		break;
 142	}
 143}
 144
 145static enum bp_result encoder_control_dig_v1(
 146	struct bios_parser *bp,
 147	struct bp_encoder_control *cntl);
 148static enum bp_result encoder_control_dig1_v1(
 149	struct bios_parser *bp,
 150	struct bp_encoder_control *cntl);
 151static enum bp_result encoder_control_dig2_v1(
 152	struct bios_parser *bp,
 153	struct bp_encoder_control *cntl);
 154
 155static void init_encoder_control_dig_v1(struct bios_parser *bp)
 156{
 157	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
 158
 159	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl))
 160		cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1;
 161	else
 162		cmd_tbl->encoder_control_dig1 = NULL;
 163
 164	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl))
 165		cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1;
 166	else
 167		cmd_tbl->encoder_control_dig2 = NULL;
 168
 169	cmd_tbl->dig_encoder_control = encoder_control_dig_v1;
 170}
 171
 172static enum bp_result encoder_control_dig_v1(
 173	struct bios_parser *bp,
 174	struct bp_encoder_control *cntl)
 175{
 176	enum bp_result result = BP_RESULT_FAILURE;
 177	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
 178
 179	if (cntl != NULL)
 180		switch (cntl->engine_id) {
 181		case ENGINE_ID_DIGA:
 182			if (cmd_tbl->encoder_control_dig1 != NULL)
 183				result =
 184					cmd_tbl->encoder_control_dig1(bp, cntl);
 185			break;
 186		case ENGINE_ID_DIGB:
 187			if (cmd_tbl->encoder_control_dig2 != NULL)
 188				result =
 189					cmd_tbl->encoder_control_dig2(bp, cntl);
 190			break;
 191
 192		default:
 193			break;
 194		}
 195
 196	return result;
 197}
 198
 199static enum bp_result encoder_control_dig1_v1(
 200	struct bios_parser *bp,
 201	struct bp_encoder_control *cntl)
 202{
 203	enum bp_result result = BP_RESULT_FAILURE;
 204	DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
 205
 206	bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
 207
 208	if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params))
 209		result = BP_RESULT_OK;
 210
 211	return result;
 212}
 213
 214static enum bp_result encoder_control_dig2_v1(
 215	struct bios_parser *bp,
 216	struct bp_encoder_control *cntl)
 217{
 218	enum bp_result result = BP_RESULT_FAILURE;
 219	DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
 220
 221	bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
 222
 223	if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params))
 224		result = BP_RESULT_OK;
 225
 226	return result;
 227}
 228
 229static enum bp_result encoder_control_digx_v3(
 230	struct bios_parser *bp,
 231	struct bp_encoder_control *cntl)
 232{
 233	enum bp_result result = BP_RESULT_FAILURE;
 234	DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0};
 235
 236	if (LANE_COUNT_FOUR < cntl->lanes_number)
 237		params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
 238	else
 239		params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
 240
 241	params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
 242
 243	/* We need to convert from KHz units into 10KHz units */
 244	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
 245	params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
 246	params.ucEncoderMode =
 247			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
 248					cntl->signal,
 249					cntl->enable_dp_audio);
 250	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
 251
 252	switch (cntl->color_depth) {
 253	case COLOR_DEPTH_888:
 254		params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
 255		break;
 256	case COLOR_DEPTH_101010:
 257		params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
 258		break;
 259	case COLOR_DEPTH_121212:
 260		params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
 261		break;
 262	case COLOR_DEPTH_161616:
 263		params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
 264		break;
 265	default:
 266		break;
 267	}
 268
 269	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
 270		result = BP_RESULT_OK;
 271
 272	return result;
 273}
 274
 275static enum bp_result encoder_control_digx_v4(
 276	struct bios_parser *bp,
 277	struct bp_encoder_control *cntl)
 278{
 279	enum bp_result result = BP_RESULT_FAILURE;
 280	DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0};
 281
 282	if (LANE_COUNT_FOUR < cntl->lanes_number)
 283		params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
 284	else
 285		params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
 286
 287	params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
 288
 289	/* We need to convert from KHz units into 10KHz units */
 290	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
 291	params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
 292	params.ucEncoderMode =
 293			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
 294					cntl->signal,
 295					cntl->enable_dp_audio));
 296	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
 297
 298	switch (cntl->color_depth) {
 299	case COLOR_DEPTH_888:
 300		params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
 301		break;
 302	case COLOR_DEPTH_101010:
 303		params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
 304		break;
 305	case COLOR_DEPTH_121212:
 306		params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
 307		break;
 308	case COLOR_DEPTH_161616:
 309		params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
 310		break;
 311	default:
 312		break;
 313	}
 314
 315	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
 316		result = BP_RESULT_OK;
 317
 318	return result;
 319}
 320
 321static enum bp_result encoder_control_digx_v5(
 322	struct bios_parser *bp,
 323	struct bp_encoder_control *cntl)
 324{
 325	enum bp_result result = BP_RESULT_FAILURE;
 326	ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0};
 327
 328	params.ucDigId = (uint8_t)(cntl->engine_id);
 329	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
 330
 331	params.ulPixelClock = cntl->pixel_clock / 10;
 332	params.ucDigMode =
 333			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
 334					cntl->signal,
 335					cntl->enable_dp_audio));
 336	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
 337
 338	switch (cntl->color_depth) {
 339	case COLOR_DEPTH_888:
 340		params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
 341		break;
 342	case COLOR_DEPTH_101010:
 343		params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
 344		break;
 345	case COLOR_DEPTH_121212:
 346		params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
 347		break;
 348	case COLOR_DEPTH_161616:
 349		params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
 350		break;
 351	default:
 352		break;
 353	}
 354
 355	if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
 356		switch (cntl->color_depth) {
 357		case COLOR_DEPTH_101010:
 358			params.ulPixelClock =
 359				(params.ulPixelClock * 30) / 24;
 360			break;
 361		case COLOR_DEPTH_121212:
 362			params.ulPixelClock =
 363				(params.ulPixelClock * 36) / 24;
 364			break;
 365		case COLOR_DEPTH_161616:
 366			params.ulPixelClock =
 367				(params.ulPixelClock * 48) / 24;
 368			break;
 369		default:
 370			break;
 371		}
 372
 373	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
 374		result = BP_RESULT_OK;
 375
 376	return result;
 377}
 378
 379/*******************************************************************************
 380 ********************************************************************************
 381 **
 382 **                  TRANSMITTER CONTROL
 383 **
 384 ********************************************************************************
 385 *******************************************************************************/
 386
 387static enum bp_result transmitter_control_v2(
 388	struct bios_parser *bp,
 389	struct bp_transmitter_control *cntl);
 390static enum bp_result transmitter_control_v3(
 391	struct bios_parser *bp,
 392	struct bp_transmitter_control *cntl);
 393static enum bp_result transmitter_control_v4(
 394	struct bios_parser *bp,
 395	struct bp_transmitter_control *cntl);
 396static enum bp_result transmitter_control_v1_5(
 397	struct bios_parser *bp,
 398	struct bp_transmitter_control *cntl);
 399static enum bp_result transmitter_control_v1_6(
 400	struct bios_parser *bp,
 401	struct bp_transmitter_control *cntl);
 402
 403static void init_transmitter_control(struct bios_parser *bp)
 404{
 405	uint8_t frev;
 406	uint8_t crev = 0;
 407
 408	if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl,
 409			frev, crev) == false)
 410		BREAK_TO_DEBUGGER();
 411	switch (crev) {
 412	case 2:
 413		bp->cmd_tbl.transmitter_control = transmitter_control_v2;
 414		break;
 415	case 3:
 416		bp->cmd_tbl.transmitter_control = transmitter_control_v3;
 417		break;
 418	case 4:
 419		bp->cmd_tbl.transmitter_control = transmitter_control_v4;
 420		break;
 421	case 5:
 422		bp->cmd_tbl.transmitter_control = transmitter_control_v1_5;
 423		break;
 424	case 6:
 425		bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;
 426		break;
 427	default:
 428		dm_output_to_console("Don't have transmitter_control for v%d\n", crev);
 429		bp->cmd_tbl.transmitter_control = NULL;
 430		break;
 431	}
 432}
 433
 434static enum bp_result transmitter_control_v2(
 435	struct bios_parser *bp,
 436	struct bp_transmitter_control *cntl)
 437{
 438	enum bp_result result = BP_RESULT_FAILURE;
 439	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params;
 440	enum connector_id connector_id =
 441		dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
 442
 443	memset(&params, 0, sizeof(params));
 444
 445	switch (cntl->transmitter) {
 446	case TRANSMITTER_UNIPHY_A:
 447	case TRANSMITTER_UNIPHY_B:
 448	case TRANSMITTER_UNIPHY_C:
 449	case TRANSMITTER_UNIPHY_D:
 450	case TRANSMITTER_UNIPHY_E:
 451	case TRANSMITTER_UNIPHY_F:
 452	case TRANSMITTER_TRAVIS_LCD:
 453		break;
 454	default:
 455		return BP_RESULT_BADINPUT;
 456	}
 457
 458	switch (cntl->action) {
 459	case TRANSMITTER_CONTROL_INIT:
 460		if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) ||
 461				(CONNECTOR_ID_DUAL_LINK_DVID == connector_id))
 462			/* on INIT this bit should be set according to the
 463			 * physical connector
 464			 * Bit0: dual link connector flag
 465			 * =0 connector is single link connector
 466			 * =1 connector is dual link connector
 467			 */
 468			params.acConfig.fDualLinkConnector = 1;
 469
 470		/* connector object id */
 471		params.usInitInfo =
 472				cpu_to_le16((uint8_t)cntl->connector_obj_id.id);
 473		break;
 474	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
 475		/* voltage swing and pre-emphsis */
 476		params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
 477		params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
 478		break;
 479	default:
 480		/* if dual-link */
 481		if (LANE_COUNT_FOUR < cntl->lanes_number) {
 482			/* on ENABLE/DISABLE this bit should be set according to
 483			 * actual timing (number of lanes)
 484			 * Bit0: dual link connector flag
 485			 * =0 connector is single link connector
 486			 * =1 connector is dual link connector
 487			 */
 488			params.acConfig.fDualLinkConnector = 1;
 489
 490			/* link rate, half for dual link
 491			 * We need to convert from KHz units into 20KHz units
 492			 */
 493			params.usPixelClock =
 494					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
 495		} else
 496			/* link rate, half for dual link
 497			 * We need to convert from KHz units into 10KHz units
 498			 */
 499			params.usPixelClock =
 500					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
 501		break;
 502	}
 503
 504	/* 00 - coherent mode
 505	 * 01 - incoherent mode
 506	 */
 507
 508	params.acConfig.fCoherentMode = cntl->coherent;
 509
 510	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
 511			|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
 512			|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
 513		/* Bit2: Transmitter Link selection
 514		 * =0 when bit0=0, single link A/C/E, when bit0=1,
 515		 * master link A/C/E
 516		 * =1 when bit0=0, single link B/D/F, when bit0=1,
 517		 * master link B/D/F
 518		 */
 519		params.acConfig.ucLinkSel = 1;
 520
 521	if (ENGINE_ID_DIGB == cntl->engine_id)
 522		/* Bit3: Transmitter data source selection
 523		 * =0 DIGA is data source.
 524		 * =1 DIGB is data source.
 525		 * This bit is only useful when ucAction= ATOM_ENABLE
 526		 */
 527		params.acConfig.ucEncoderSel = 1;
 528
 529	if (CONNECTOR_ID_DISPLAY_PORT == connector_id ||
 530	    CONNECTOR_ID_USBC == connector_id)
 531		/* Bit4: DP connector flag
 532		 * =0 connector is none-DP connector
 533		 * =1 connector is DP connector
 534		 */
 535		params.acConfig.fDPConnector = 1;
 536
 537	/* Bit[7:6]: Transmitter selection
 538	 * =0 UNIPHY_ENCODER: UNIPHYA/B
 539	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
 540	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
 541	 * =3 reserved
 542	 */
 543	params.acConfig.ucTransmitterSel =
 544			(uint8_t)bp->cmd_helper->transmitter_bp_to_atom(
 545					cntl->transmitter);
 546
 547	params.ucAction = (uint8_t)cntl->action;
 548
 549	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
 550		result = BP_RESULT_OK;
 551
 552	return result;
 553}
 554
 555static enum bp_result transmitter_control_v3(
 556	struct bios_parser *bp,
 557	struct bp_transmitter_control *cntl)
 558{
 559	enum bp_result result = BP_RESULT_FAILURE;
 560	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 params;
 561	uint32_t pll_id;
 562	enum connector_id conn_id =
 563			dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
 564	const struct command_table_helper *cmd = bp->cmd_helper;
 565	bool dual_link_conn = (CONNECTOR_ID_DUAL_LINK_DVII == conn_id)
 566					|| (CONNECTOR_ID_DUAL_LINK_DVID == conn_id);
 567
 568	memset(&params, 0, sizeof(params));
 569
 570	switch (cntl->transmitter) {
 571	case TRANSMITTER_UNIPHY_A:
 572	case TRANSMITTER_UNIPHY_B:
 573	case TRANSMITTER_UNIPHY_C:
 574	case TRANSMITTER_UNIPHY_D:
 575	case TRANSMITTER_UNIPHY_E:
 576	case TRANSMITTER_UNIPHY_F:
 577	case TRANSMITTER_TRAVIS_LCD:
 578		break;
 579	default:
 580		return BP_RESULT_BADINPUT;
 581	}
 582
 583	if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id))
 584		return BP_RESULT_BADINPUT;
 585
 586	/* fill information based on the action */
 587	switch (cntl->action) {
 588	case TRANSMITTER_CONTROL_INIT:
 589		if (dual_link_conn) {
 590			/* on INIT this bit should be set according to the
 591			 * phisycal connector
 592			 * Bit0: dual link connector flag
 593			 * =0 connector is single link connector
 594			 * =1 connector is dual link connector
 595			 */
 596			params.acConfig.fDualLinkConnector = 1;
 597		}
 598
 599		/* connector object id */
 600		params.usInitInfo =
 601				cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
 602		break;
 603	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
 604		/* votage swing and pre-emphsis */
 605		params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
 606		params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
 607		break;
 608	default:
 609		if (dual_link_conn && cntl->multi_path)
 610			/* on ENABLE/DISABLE this bit should be set according to
 611			 * actual timing (number of lanes)
 612			 * Bit0: dual link connector flag
 613			 * =0 connector is single link connector
 614			 * =1 connector is dual link connector
 615			 */
 616			params.acConfig.fDualLinkConnector = 1;
 617
 618		/* if dual-link */
 619		if (LANE_COUNT_FOUR < cntl->lanes_number) {
 620			/* on ENABLE/DISABLE this bit should be set according to
 621			 * actual timing (number of lanes)
 622			 * Bit0: dual link connector flag
 623			 * =0 connector is single link connector
 624			 * =1 connector is dual link connector
 625			 */
 626			params.acConfig.fDualLinkConnector = 1;
 627
 628			/* link rate, half for dual link
 629			 * We need to convert from KHz units into 20KHz units
 630			 */
 631			params.usPixelClock =
 632					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
 633		} else {
 634			/* link rate, half for dual link
 635			 * We need to convert from KHz units into 10KHz units
 636			 */
 637			params.usPixelClock =
 638					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
 639		}
 640		break;
 641	}
 642
 643	/* 00 - coherent mode
 644	 * 01 - incoherent mode
 645	 */
 646
 647	params.acConfig.fCoherentMode = cntl->coherent;
 648
 649	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
 650		|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
 651		|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
 652		/* Bit2: Transmitter Link selection
 653		 * =0 when bit0=0, single link A/C/E, when bit0=1,
 654		 * master link A/C/E
 655		 * =1 when bit0=0, single link B/D/F, when bit0=1,
 656		 * master link B/D/F
 657		 */
 658		params.acConfig.ucLinkSel = 1;
 659
 660	if (ENGINE_ID_DIGB == cntl->engine_id)
 661		/* Bit3: Transmitter data source selection
 662		 * =0 DIGA is data source.
 663		 * =1 DIGB is data source.
 664		 * This bit is only useful when ucAction= ATOM_ENABLE
 665		 */
 666		params.acConfig.ucEncoderSel = 1;
 667
 668	/* Bit[7:6]: Transmitter selection
 669	 * =0 UNIPHY_ENCODER: UNIPHYA/B
 670	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
 671	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
 672	 * =3 reserved
 673	 */
 674	params.acConfig.ucTransmitterSel =
 675			(uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter);
 676
 677	params.ucLaneNum = (uint8_t)cntl->lanes_number;
 678
 679	params.acConfig.ucRefClkSource = (uint8_t)pll_id;
 680
 681	params.ucAction = (uint8_t)cntl->action;
 682
 683	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
 684		result = BP_RESULT_OK;
 685
 686	return result;
 687}
 688
 689static enum bp_result transmitter_control_v4(
 690	struct bios_parser *bp,
 691	struct bp_transmitter_control *cntl)
 692{
 693	enum bp_result result = BP_RESULT_FAILURE;
 694	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 params;
 695	uint32_t ref_clk_src_id;
 696	enum connector_id conn_id =
 697			dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
 698	const struct command_table_helper *cmd = bp->cmd_helper;
 699
 700	memset(&params, 0, sizeof(params));
 701
 702	switch (cntl->transmitter) {
 703	case TRANSMITTER_UNIPHY_A:
 704	case TRANSMITTER_UNIPHY_B:
 705	case TRANSMITTER_UNIPHY_C:
 706	case TRANSMITTER_UNIPHY_D:
 707	case TRANSMITTER_UNIPHY_E:
 708	case TRANSMITTER_UNIPHY_F:
 709	case TRANSMITTER_TRAVIS_LCD:
 710		break;
 711	default:
 712		return BP_RESULT_BADINPUT;
 713	}
 714
 715	if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id))
 716		return BP_RESULT_BADINPUT;
 717
 718	switch (cntl->action) {
 719	case TRANSMITTER_CONTROL_INIT:
 720	{
 721		if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
 722				(CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
 723			/* on INIT this bit should be set according to the
 724			 * phisycal connector
 725			 * Bit0: dual link connector flag
 726			 * =0 connector is single link connector
 727			 * =1 connector is dual link connector
 728			 */
 729			params.acConfig.fDualLinkConnector = 1;
 730
 731		/* connector object id */
 732		params.usInitInfo =
 733				cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
 734	}
 735	break;
 736	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
 737		/* votage swing and pre-emphsis */
 738		params.asMode.ucLaneSel = (uint8_t)(cntl->lane_select);
 739		params.asMode.ucLaneSet = (uint8_t)(cntl->lane_settings);
 740		break;
 741	default:
 742		if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
 743				(CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
 744			/* on ENABLE/DISABLE this bit should be set according to
 745			 * actual timing (number of lanes)
 746			 * Bit0: dual link connector flag
 747			 * =0 connector is single link connector
 748			 * =1 connector is dual link connector
 749			 */
 750			params.acConfig.fDualLinkConnector = 1;
 751
 752		/* if dual-link */
 753		if (LANE_COUNT_FOUR < cntl->lanes_number)
 754			/* link rate, half for dual link
 755			 * We need to convert from KHz units into 20KHz units
 756			 */
 757			params.usPixelClock =
 758					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
 759		else {
 760			/* link rate, half for dual link
 761			 * We need to convert from KHz units into 10KHz units
 762			 */
 763			params.usPixelClock =
 764					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
 765		}
 766		break;
 767	}
 768
 769	/* 00 - coherent mode
 770	 * 01 - incoherent mode
 771	 */
 772
 773	params.acConfig.fCoherentMode = cntl->coherent;
 774
 775	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
 776		|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
 777		|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
 778		/* Bit2: Transmitter Link selection
 779		 * =0 when bit0=0, single link A/C/E, when bit0=1,
 780		 * master link A/C/E
 781		 * =1 when bit0=0, single link B/D/F, when bit0=1,
 782		 * master link B/D/F
 783		 */
 784		params.acConfig.ucLinkSel = 1;
 785
 786	if (ENGINE_ID_DIGB == cntl->engine_id)
 787		/* Bit3: Transmitter data source selection
 788		 * =0 DIGA is data source.
 789		 * =1 DIGB is data source.
 790		 * This bit is only useful when ucAction= ATOM_ENABLE
 791		 */
 792		params.acConfig.ucEncoderSel = 1;
 793
 794	/* Bit[7:6]: Transmitter selection
 795	 * =0 UNIPHY_ENCODER: UNIPHYA/B
 796	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
 797	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
 798	 * =3 reserved
 799	 */
 800	params.acConfig.ucTransmitterSel =
 801		(uint8_t)(cmd->transmitter_bp_to_atom(cntl->transmitter));
 802	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
 803	params.acConfig.ucRefClkSource = (uint8_t)(ref_clk_src_id);
 804	params.ucAction = (uint8_t)(cntl->action);
 805
 806	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
 807		result = BP_RESULT_OK;
 808
 809	return result;
 810}
 811
 812static enum bp_result transmitter_control_v1_5(
 813	struct bios_parser *bp,
 814	struct bp_transmitter_control *cntl)
 815{
 816	enum bp_result result = BP_RESULT_FAILURE;
 817	const struct command_table_helper *cmd = bp->cmd_helper;
 818	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 params;
 819
 820	memset(&params, 0, sizeof(params));
 821	params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
 822	params.ucAction = (uint8_t)cntl->action;
 823	params.ucLaneNum = (uint8_t)cntl->lanes_number;
 824	params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
 825
 826	params.ucDigMode =
 827		cmd->signal_type_to_atom_dig_mode(cntl->signal);
 828	params.asConfig.ucPhyClkSrcId =
 829		cmd->clock_source_id_to_atom_phy_clk_src_id(cntl->pll_id);
 830	/* 00 - coherent mode */
 831	params.asConfig.ucCoherentMode = cntl->coherent;
 832	params.asConfig.ucHPDSel =
 833		cmd->hpd_sel_to_atom(cntl->hpd_sel);
 834	params.ucDigEncoderSel =
 835		cmd->dig_encoder_sel_to_atom(cntl->engine_id);
 836	params.ucDPLaneSet = (uint8_t) cntl->lane_settings;
 837	params.usSymClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10));
 838	/*
 839	 * In SI/TN case, caller have to set usPixelClock as following:
 840	 * DP mode: usPixelClock = DP_LINK_CLOCK/10
 841	 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
 842	 * DVI single link mode: usPixelClock = pixel clock
 843	 * DVI dual link mode: usPixelClock = pixel clock
 844	 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
 845	 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
 846	 * LVDS mode: usPixelClock = pixel clock
 847	 */
 848	if  (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
 849		switch (cntl->color_depth) {
 850		case COLOR_DEPTH_101010:
 851			params.usSymClock =
 852				cpu_to_le16((le16_to_cpu(params.usSymClock) * 30) / 24);
 853			break;
 854		case COLOR_DEPTH_121212:
 855			params.usSymClock =
 856				cpu_to_le16((le16_to_cpu(params.usSymClock) * 36) / 24);
 857			break;
 858		case COLOR_DEPTH_161616:
 859			params.usSymClock =
 860				cpu_to_le16((le16_to_cpu(params.usSymClock) * 48) / 24);
 861			break;
 862		default:
 863			break;
 864		}
 865	}
 866
 867	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
 868		result = BP_RESULT_OK;
 869
 870	return result;
 871}
 872
 873static enum bp_result transmitter_control_v1_6(
 874	struct bios_parser *bp,
 875	struct bp_transmitter_control *cntl)
 876{
 877	enum bp_result result = BP_RESULT_FAILURE;
 878	const struct command_table_helper *cmd = bp->cmd_helper;
 879	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params;
 880
 881	memset(&params, 0, sizeof(params));
 882	params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
 883	params.ucAction = (uint8_t)cntl->action;
 884
 885	if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
 886		params.ucDPLaneSet = (uint8_t)cntl->lane_settings;
 887	else
 888		params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal);
 889
 890	params.ucLaneNum = (uint8_t)cntl->lanes_number;
 891	params.ucHPDSel = cmd->hpd_sel_to_atom(cntl->hpd_sel);
 892	params.ucDigEncoderSel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);
 893	params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
 894	params.ulSymClock = cntl->pixel_clock/10;
 895
 896	/*
 897	 * In SI/TN case, caller have to set usPixelClock as following:
 898	 * DP mode: usPixelClock = DP_LINK_CLOCK/10
 899	 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
 900	 * DVI single link mode: usPixelClock = pixel clock
 901	 * DVI dual link mode: usPixelClock = pixel clock
 902	 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
 903	 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
 904	 * LVDS mode: usPixelClock = pixel clock
 905	 */
 906	switch (cntl->signal) {
 907	case SIGNAL_TYPE_HDMI_TYPE_A:
 908		switch (cntl->color_depth) {
 909		case COLOR_DEPTH_101010:
 910			params.ulSymClock =
 911				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24);
 912			break;
 913		case COLOR_DEPTH_121212:
 914			params.ulSymClock =
 915				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24);
 916			break;
 917		case COLOR_DEPTH_161616:
 918			params.ulSymClock =
 919				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24);
 920			break;
 921		default:
 922			break;
 923		}
 924		break;
 925		default:
 926			break;
 927	}
 928
 929	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
 930		result = BP_RESULT_OK;
 931	return result;
 932}
 933
 934/*******************************************************************************
 935 ********************************************************************************
 936 **
 937 **                  SET PIXEL CLOCK
 938 **
 939 ********************************************************************************
 940 *******************************************************************************/
 941
 942static enum bp_result set_pixel_clock_v3(
 943	struct bios_parser *bp,
 944	struct bp_pixel_clock_parameters *bp_params);
 945static enum bp_result set_pixel_clock_v5(
 946	struct bios_parser *bp,
 947	struct bp_pixel_clock_parameters *bp_params);
 948static enum bp_result set_pixel_clock_v6(
 949	struct bios_parser *bp,
 950	struct bp_pixel_clock_parameters *bp_params);
 951static enum bp_result set_pixel_clock_v7(
 952	struct bios_parser *bp,
 953	struct bp_pixel_clock_parameters *bp_params);
 954
 955static void init_set_pixel_clock(struct bios_parser *bp)
 956{
 957	switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
 958	case 3:
 959		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3;
 960		break;
 961	case 5:
 962		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5;
 963		break;
 964	case 6:
 965		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6;
 966		break;
 967	case 7:
 968		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
 969		break;
 970	default:
 971		dm_output_to_console("Don't have set_pixel_clock for v%d\n",
 972			 BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
 973		bp->cmd_tbl.set_pixel_clock = NULL;
 974		break;
 975	}
 976}
 977
 978static enum bp_result set_pixel_clock_v3(
 979	struct bios_parser *bp,
 980	struct bp_pixel_clock_parameters *bp_params)
 981{
 982	enum bp_result result = BP_RESULT_FAILURE;
 983	PIXEL_CLOCK_PARAMETERS_V3 *params;
 984	SET_PIXEL_CLOCK_PS_ALLOCATION allocation;
 985
 986	memset(&allocation, 0, sizeof(allocation));
 987
 988	if (CLOCK_SOURCE_ID_PLL1 == bp_params->pll_id)
 989		allocation.sPCLKInput.ucPpll = ATOM_PPLL1;
 990	else if (CLOCK_SOURCE_ID_PLL2 == bp_params->pll_id)
 991		allocation.sPCLKInput.ucPpll = ATOM_PPLL2;
 992	else
 993		return BP_RESULT_BADINPUT;
 994
 995	allocation.sPCLKInput.usRefDiv =
 996			cpu_to_le16((uint16_t)bp_params->reference_divider);
 997	allocation.sPCLKInput.usFbDiv =
 998			cpu_to_le16((uint16_t)bp_params->feedback_divider);
 999	allocation.sPCLKInput.ucFracFbDiv =
1000			(uint8_t)(bp_params->fractional_feedback_divider / 100000);
1001	allocation.sPCLKInput.ucPostDiv =
1002			(uint8_t)bp_params->pixel_clock_post_divider;
1003
1004	/* We need to convert from 100Hz units into 10KHz units */
1005	allocation.sPCLKInput.usPixelClock =
1006			cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
1007
1008	params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput;
1009	params->ucTransmitterId =
1010			bp->cmd_helper->encoder_id_to_atom(
1011					dal_graphics_object_id_get_encoder_id(
1012							bp_params->encoder_object_id));
1013	params->ucEncoderMode =
1014			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
1015					bp_params->signal_type, false));
1016
1017	if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1018		params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
1019
1020	if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK)
1021		params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK;
1022
1023	if (CONTROLLER_ID_D1 != bp_params->controller_id)
1024		params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;
1025
1026	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation))
1027		result = BP_RESULT_OK;
1028
1029	return result;
1030}
1031
1032#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V5
1033/* video bios did not define this: */
1034typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V5 {
1035	PIXEL_CLOCK_PARAMETERS_V5 sPCLKInput;
1036	/* Caller doesn't need to init this portion */
1037	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
1038} SET_PIXEL_CLOCK_PS_ALLOCATION_V5;
1039#endif
1040
1041#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V6
1042/* video bios did not define this: */
1043typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V6 {
1044	PIXEL_CLOCK_PARAMETERS_V6 sPCLKInput;
1045	/* Caller doesn't need to init this portion */
1046	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
1047} SET_PIXEL_CLOCK_PS_ALLOCATION_V6;
1048#endif
1049
1050static enum bp_result set_pixel_clock_v5(
1051	struct bios_parser *bp,
1052	struct bp_pixel_clock_parameters *bp_params)
1053{
1054	enum bp_result result = BP_RESULT_FAILURE;
1055	SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk;
1056	uint8_t controller_id;
1057	uint32_t pll_id;
1058
1059	memset(&clk, 0, sizeof(clk));
1060
1061	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1062			&& bp->cmd_helper->controller_id_to_atom(
1063					bp_params->controller_id, &controller_id)) {
1064		clk.sPCLKInput.ucCRTC = controller_id;
1065		clk.sPCLKInput.ucPpll = (uint8_t)pll_id;
1066		clk.sPCLKInput.ucRefDiv =
1067				(uint8_t)(bp_params->reference_divider);
1068		clk.sPCLKInput.usFbDiv =
1069				cpu_to_le16((uint16_t)(bp_params->feedback_divider));
1070		clk.sPCLKInput.ulFbDivDecFrac =
1071				cpu_to_le32(bp_params->fractional_feedback_divider);
1072		clk.sPCLKInput.ucPostDiv =
1073				(uint8_t)(bp_params->pixel_clock_post_divider);
1074		clk.sPCLKInput.ucTransmitterID =
1075				bp->cmd_helper->encoder_id_to_atom(
1076						dal_graphics_object_id_get_encoder_id(
1077								bp_params->encoder_object_id));
1078		clk.sPCLKInput.ucEncoderMode =
1079				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1080						bp_params->signal_type, false);
1081
1082		/* We need to convert from 100Hz units into 10KHz units */
1083		clk.sPCLKInput.usPixelClock =
1084				cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
1085
1086		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1087			clk.sPCLKInput.ucMiscInfo |=
1088					PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
1089
1090		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1091			clk.sPCLKInput.ucMiscInfo |=
1092					PIXEL_CLOCK_MISC_REF_DIV_SRC;
1093
1094		/* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp
1095		 * =1:30bpp, =2:32bpp
1096		 * driver choose program it itself, i.e. here we program it
1097		 * to 888 by default.
1098		 */
1099		if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
1100			switch (bp_params->color_depth) {
1101			case TRANSMITTER_COLOR_DEPTH_30:
1102				/* yes this is correct, the atom define is wrong */
1103				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP;
1104				break;
1105			case TRANSMITTER_COLOR_DEPTH_36:
1106				/* yes this is correct, the atom define is wrong */
1107				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
1108				break;
1109			default:
1110				break;
1111			}
1112
1113		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1114			result = BP_RESULT_OK;
1115	}
1116
1117	return result;
1118}
1119
1120static enum bp_result set_pixel_clock_v6(
1121	struct bios_parser *bp,
1122	struct bp_pixel_clock_parameters *bp_params)
1123{
1124	enum bp_result result = BP_RESULT_FAILURE;
1125	SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk;
1126	uint8_t controller_id;
1127	uint32_t pll_id;
1128
1129	memset(&clk, 0, sizeof(clk));
1130
1131	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1132			&& bp->cmd_helper->controller_id_to_atom(
1133					bp_params->controller_id, &controller_id)) {
1134		/* Note: VBIOS still wants to use ucCRTC name which is now
1135		 * 1 byte in ULONG
1136		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1137		 *{
1138		 * target the pixel clock to drive the CRTC timing.
1139		 * ULONG ulPixelClock:24;
1140		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1141		 * previous version.
1142		 * ATOM_CRTC1~6, indicate the CRTC controller to
1143		 * ULONG ucCRTC:8;
1144		 * drive the pixel clock. not used for DCPLL case.
1145		 *}CRTC_PIXEL_CLOCK_FREQ;
1146		 *union
1147		 *{
1148		 * pixel clock and CRTC id frequency
1149		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1150		 * ULONG ulDispEngClkFreq; dispclk frequency
1151		 *};
1152		 */
1153		clk.sPCLKInput.ulCrtcPclkFreq.ucCRTC = controller_id;
1154		clk.sPCLKInput.ucPpll = (uint8_t) pll_id;
1155		clk.sPCLKInput.ucRefDiv =
1156				(uint8_t) bp_params->reference_divider;
1157		clk.sPCLKInput.usFbDiv =
1158				cpu_to_le16((uint16_t) bp_params->feedback_divider);
1159		clk.sPCLKInput.ulFbDivDecFrac =
1160				cpu_to_le32(bp_params->fractional_feedback_divider);
1161		clk.sPCLKInput.ucPostDiv =
1162				(uint8_t) bp_params->pixel_clock_post_divider;
1163		clk.sPCLKInput.ucTransmitterID =
1164				bp->cmd_helper->encoder_id_to_atom(
1165						dal_graphics_object_id_get_encoder_id(
1166								bp_params->encoder_object_id));
1167		clk.sPCLKInput.ucEncoderMode =
1168				(uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(
1169						bp_params->signal_type, false);
1170
1171		/* We need to convert from 100 Hz units into 10KHz units */
1172		clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock =
1173				cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
1174
1175		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {
1176			clk.sPCLKInput.ucMiscInfo |=
1177					PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL;
1178		}
1179
1180		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) {
1181			clk.sPCLKInput.ucMiscInfo |=
1182					PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
1183		}
1184
1185		/* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0:
1186		 * 24bpp =1:30bpp, =2:32bpp
1187		 * driver choose program it itself, i.e. here we pass required
1188		 * target rate that includes deep color.
1189		 */
1190		if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
1191			switch (bp_params->color_depth) {
1192			case TRANSMITTER_COLOR_DEPTH_30:
1193				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6;
1194				break;
1195			case TRANSMITTER_COLOR_DEPTH_36:
1196				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6;
1197				break;
1198			case TRANSMITTER_COLOR_DEPTH_48:
1199				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
1200				break;
1201			default:
1202				break;
1203			}
1204
1205		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1206			result = BP_RESULT_OK;
1207	}
1208
1209	return result;
1210}
1211
1212static enum bp_result set_pixel_clock_v7(
1213	struct bios_parser *bp,
1214	struct bp_pixel_clock_parameters *bp_params)
1215{
1216	enum bp_result result = BP_RESULT_FAILURE;
1217	PIXEL_CLOCK_PARAMETERS_V7 clk;
1218	uint8_t controller_id;
1219	uint32_t pll_id;
1220
1221	memset(&clk, 0, sizeof(clk));
1222
1223	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1224			&& bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &controller_id)) {
1225		/* Note: VBIOS still wants to use ucCRTC name which is now
1226		 * 1 byte in ULONG
1227		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1228		 *{
1229		 * target the pixel clock to drive the CRTC timing.
1230		 * ULONG ulPixelClock:24;
1231		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1232		 * previous version.
1233		 * ATOM_CRTC1~6, indicate the CRTC controller to
1234		 * ULONG ucCRTC:8;
1235		 * drive the pixel clock. not used for DCPLL case.
1236		 *}CRTC_PIXEL_CLOCK_FREQ;
1237		 *union
1238		 *{
1239		 * pixel clock and CRTC id frequency
1240		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1241		 * ULONG ulDispEngClkFreq; dispclk frequency
1242		 *};
1243		 */
1244		clk.ucCRTC = controller_id;
1245		clk.ucPpll = (uint8_t) pll_id;
1246		clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id));
1247		clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false);
1248
1249		clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock_100hz);
1250
1251		clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);
1252
1253		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1254			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
1255
1256		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1257			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC;
1258
1259		if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)
1260			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;
1261
1262		if (bp_params->flags.SUPPORT_YUV_420)
1263			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;
1264
1265		if (bp_params->flags.SET_XTALIN_REF_SRC)
1266			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;
1267
1268		if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)
1269			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;
1270
1271		if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1272			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
1273
1274		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1275			result = BP_RESULT_OK;
1276	}
1277	return result;
1278}
1279
1280/*******************************************************************************
1281 ********************************************************************************
1282 **
1283 **                  ENABLE PIXEL CLOCK SS
1284 **
1285 ********************************************************************************
1286 *******************************************************************************/
1287static enum bp_result enable_spread_spectrum_on_ppll_v1(
1288	struct bios_parser *bp,
1289	struct bp_spread_spectrum_parameters *bp_params,
1290	bool enable);
1291static enum bp_result enable_spread_spectrum_on_ppll_v2(
1292	struct bios_parser *bp,
1293	struct bp_spread_spectrum_parameters *bp_params,
1294	bool enable);
1295static enum bp_result enable_spread_spectrum_on_ppll_v3(
1296	struct bios_parser *bp,
1297	struct bp_spread_spectrum_parameters *bp_params,
1298	bool enable);
1299
1300static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp)
1301{
1302	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) {
1303	case 1:
1304		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1305				enable_spread_spectrum_on_ppll_v1;
1306		break;
1307	case 2:
1308		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1309				enable_spread_spectrum_on_ppll_v2;
1310		break;
1311	case 3:
1312		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1313				enable_spread_spectrum_on_ppll_v3;
1314		break;
1315	default:
1316		dm_output_to_console("Don't have enable_spread_spectrum_on_ppll for v%d\n",
1317			 BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL));
1318		bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL;
1319		break;
1320	}
1321}
1322
1323static enum bp_result enable_spread_spectrum_on_ppll_v1(
1324	struct bios_parser *bp,
1325	struct bp_spread_spectrum_parameters *bp_params,
1326	bool enable)
1327{
1328	enum bp_result result = BP_RESULT_FAILURE;
1329	ENABLE_SPREAD_SPECTRUM_ON_PPLL params;
1330
1331	memset(&params, 0, sizeof(params));
1332
1333	if ((enable == true) && (bp_params->percentage > 0))
1334		params.ucEnable = ATOM_ENABLE;
1335	else
1336		params.ucEnable = ATOM_DISABLE;
1337
1338	params.usSpreadSpectrumPercentage =
1339			cpu_to_le16((uint16_t)bp_params->percentage);
1340	params.ucSpreadSpectrumStep =
1341			(uint8_t)bp_params->ver1.step;
1342	params.ucSpreadSpectrumDelay =
1343			(uint8_t)bp_params->ver1.delay;
1344	/* convert back to unit of 10KHz */
1345	params.ucSpreadSpectrumRange =
1346			(uint8_t)(bp_params->ver1.range / 10000);
1347
1348	if (bp_params->flags.EXTERNAL_SS)
1349		params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK;
1350
1351	if (bp_params->flags.CENTER_SPREAD)
1352		params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE;
1353
1354	if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1355		params.ucPpll = ATOM_PPLL1;
1356	else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1357		params.ucPpll = ATOM_PPLL2;
1358	else
1359		BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1360
1361	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1362		result = BP_RESULT_OK;
1363
1364	return result;
1365}
1366
1367static enum bp_result enable_spread_spectrum_on_ppll_v2(
1368	struct bios_parser *bp,
1369	struct bp_spread_spectrum_parameters *bp_params,
1370	bool enable)
1371{
1372	enum bp_result result = BP_RESULT_FAILURE;
1373	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params;
1374
1375	memset(&params, 0, sizeof(params));
1376
1377	if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1378		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P1PLL;
1379	else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1380		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P2PLL;
1381	else
1382		BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1383
1384	if ((enable == true) && (bp_params->percentage > 0)) {
1385		params.ucEnable = ATOM_ENABLE;
1386
1387		params.usSpreadSpectrumPercentage =
1388				cpu_to_le16((uint16_t)(bp_params->percentage));
1389		params.usSpreadSpectrumStep =
1390				cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1391
1392		if (bp_params->flags.EXTERNAL_SS)
1393			params.ucSpreadSpectrumType |=
1394					ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD;
1395
1396		if (bp_params->flags.CENTER_SPREAD)
1397			params.ucSpreadSpectrumType |=
1398					ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD;
1399
1400		/* Both amounts need to be left shifted first before bit
1401		 * comparison. Otherwise, the result will always be zero here
1402		 */
1403		params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1404				((bp_params->ds.feedback_amount <<
1405						ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT) &
1406						ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK) |
1407						((bp_params->ds.nfrac_amount <<
1408								ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
1409								ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK)));
1410	} else
1411		params.ucEnable = ATOM_DISABLE;
1412
1413	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1414		result = BP_RESULT_OK;
1415
1416	return result;
1417}
1418
1419static enum bp_result enable_spread_spectrum_on_ppll_v3(
1420	struct bios_parser *bp,
1421	struct bp_spread_spectrum_parameters *bp_params,
1422	bool enable)
1423{
1424	enum bp_result result = BP_RESULT_FAILURE;
1425	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params;
1426
1427	memset(&params, 0, sizeof(params));
1428
1429	switch (bp_params->pll_id) {
1430	case CLOCK_SOURCE_ID_PLL0:
1431		/* ATOM_PPLL_SS_TYPE_V3_P0PLL; this is pixel clock only,
1432		 * not for SI display clock.
1433		 */
1434		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1435		break;
1436	case CLOCK_SOURCE_ID_PLL1:
1437		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL;
1438		break;
1439
1440	case CLOCK_SOURCE_ID_PLL2:
1441		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL;
1442		break;
1443
1444	case CLOCK_SOURCE_ID_DCPLL:
1445		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1446		break;
1447
1448	default:
1449		BREAK_TO_DEBUGGER();
1450		/* Unexpected PLL value!! */
1451		return result;
1452	}
1453
1454	if (enable == true) {
1455		params.ucEnable = ATOM_ENABLE;
1456
1457		params.usSpreadSpectrumAmountFrac =
1458				cpu_to_le16((uint16_t)(bp_params->ds_frac_amount));
1459		params.usSpreadSpectrumStep =
1460				cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1461
1462		if (bp_params->flags.EXTERNAL_SS)
1463			params.ucSpreadSpectrumType |=
1464					ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD;
1465		if (bp_params->flags.CENTER_SPREAD)
1466			params.ucSpreadSpectrumType |=
1467					ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD;
1468
1469		/* Both amounts need to be left shifted first before bit
1470		 * comparison. Otherwise, the result will always be zero here
1471		 */
1472		params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1473				((bp_params->ds.feedback_amount <<
1474						ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT) &
1475						ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK) |
1476						((bp_params->ds.nfrac_amount <<
1477								ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT) &
1478								ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK)));
1479	} else
1480		params.ucEnable = ATOM_DISABLE;
1481
1482	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1483		result = BP_RESULT_OK;
1484
1485	return result;
1486}
1487
1488/*******************************************************************************
1489 ********************************************************************************
1490 **
1491 **                  ADJUST DISPLAY PLL
1492 **
1493 ********************************************************************************
1494 *******************************************************************************/
1495
1496static enum bp_result adjust_display_pll_v2(
1497	struct bios_parser *bp,
1498	struct bp_adjust_pixel_clock_parameters *bp_params);
1499static enum bp_result adjust_display_pll_v3(
1500	struct bios_parser *bp,
1501	struct bp_adjust_pixel_clock_parameters *bp_params);
1502
1503static void init_adjust_display_pll(struct bios_parser *bp)
1504{
1505	switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) {
1506	case 2:
1507		bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2;
1508		break;
1509	case 3:
1510		bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3;
1511		break;
1512	default:
1513		dm_output_to_console("Don't have adjust_display_pll for v%d\n",
1514			 BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll));
1515		bp->cmd_tbl.adjust_display_pll = NULL;
1516		break;
1517	}
1518}
1519
1520static enum bp_result adjust_display_pll_v2(
1521	struct bios_parser *bp,
1522	struct bp_adjust_pixel_clock_parameters *bp_params)
1523{
1524	enum bp_result result = BP_RESULT_FAILURE;
1525	ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 };
1526
1527	/* We need to convert from KHz units into 10KHz units and then convert
1528	 * output pixel clock back 10KHz-->KHz */
1529	uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10;
1530
1531	params.usPixelClock = cpu_to_le16((uint16_t)(pixel_clock_10KHz_in));
1532	params.ucTransmitterID =
1533			bp->cmd_helper->encoder_id_to_atom(
1534					dal_graphics_object_id_get_encoder_id(
1535							bp_params->encoder_object_id));
1536	params.ucEncodeMode =
1537			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1538					bp_params->signal_type, false);
1539
1540	if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
1541		/* Convert output pixel clock back 10KHz-->KHz: multiply
1542		 * original pixel clock in KHz by ratio
1543		 * [output pxlClk/input pxlClk] */
1544		uint64_t pixel_clk_10_khz_out =
1545				(uint64_t)le16_to_cpu(params.usPixelClock);
1546		uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
1547
1548		if (pixel_clock_10KHz_in != 0) {
1549			bp_params->adjusted_pixel_clock =
1550					div_u64(pixel_clk * pixel_clk_10_khz_out,
1551							pixel_clock_10KHz_in);
1552		} else {
1553			bp_params->adjusted_pixel_clock = 0;
1554			BREAK_TO_DEBUGGER();
1555		}
1556
1557		result = BP_RESULT_OK;
1558	}
1559
1560	return result;
1561}
1562
1563static enum bp_result adjust_display_pll_v3(
1564	struct bios_parser *bp,
1565	struct bp_adjust_pixel_clock_parameters *bp_params)
1566{
1567	enum bp_result result = BP_RESULT_FAILURE;
1568	ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 params;
1569	uint32_t pixel_clk_10_kHz_in = bp_params->pixel_clock / 10;
1570
1571	memset(&params, 0, sizeof(params));
1572
1573	/* We need to convert from KHz units into 10KHz units and then convert
1574	 * output pixel clock back 10KHz-->KHz */
1575	params.sInput.usPixelClock = cpu_to_le16((uint16_t)pixel_clk_10_kHz_in);
1576	params.sInput.ucTransmitterID =
1577			bp->cmd_helper->encoder_id_to_atom(
1578					dal_graphics_object_id_get_encoder_id(
1579							bp_params->encoder_object_id));
1580	params.sInput.ucEncodeMode =
1581			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1582					bp_params->signal_type, false);
1583
1584	if (bp_params->ss_enable == true)
1585		params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
1586
1587	if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1588		params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
1589
1590	if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
1591		/* Convert output pixel clock back 10KHz-->KHz: multiply
1592		 * original pixel clock in KHz by ratio
1593		 * [output pxlClk/input pxlClk] */
1594		uint64_t pixel_clk_10_khz_out =
1595				(uint64_t)le32_to_cpu(params.sOutput.ulDispPllFreq);
1596		uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
1597
1598		if (pixel_clk_10_kHz_in != 0) {
1599			bp_params->adjusted_pixel_clock =
1600					div_u64(pixel_clk * pixel_clk_10_khz_out,
1601							pixel_clk_10_kHz_in);
1602		} else {
1603			bp_params->adjusted_pixel_clock = 0;
1604			BREAK_TO_DEBUGGER();
1605		}
1606
1607		bp_params->reference_divider = params.sOutput.ucRefDiv;
1608		bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv;
1609
1610		result = BP_RESULT_OK;
1611	}
1612
1613	return result;
1614}
1615
1616/*******************************************************************************
1617 ********************************************************************************
1618 **
1619 **                  SELECT CRTC SOURCE
1620 **
1621 ********************************************************************************
1622 *******************************************************************************/
1623
1624static enum bp_result select_crtc_source_v1(
1625	struct bios_parser *bp,
1626	struct bp_crtc_source_select *bp_params);
1627static enum bp_result select_crtc_source_v2(
1628	struct bios_parser *bp,
1629	struct bp_crtc_source_select *bp_params);
1630static enum bp_result select_crtc_source_v3(
1631	struct bios_parser *bp,
1632	struct bp_crtc_source_select *bp_params);
1633
1634static void init_select_crtc_source(struct bios_parser *bp)
1635{
1636	switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) {
1637	case 1:
1638		bp->cmd_tbl.select_crtc_source = select_crtc_source_v1;
1639		break;
1640	case 2:
1641		bp->cmd_tbl.select_crtc_source = select_crtc_source_v2;
1642		break;
1643	case 3:
1644		bp->cmd_tbl.select_crtc_source = select_crtc_source_v3;
1645		break;
1646	default:
1647		bp->cmd_tbl.select_crtc_source = NULL;
1648		break;
1649	}
1650}
1651
1652static enum bp_result select_crtc_source_v1(
1653	struct bios_parser *bp,
1654	struct bp_crtc_source_select *bp_params)
1655{
1656	enum bp_result result = BP_RESULT_FAILURE;
1657	SELECT_CRTC_SOURCE_PS_ALLOCATION params;
1658
1659	if (!bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &params.ucCRTC))
1660		return BP_RESULT_BADINPUT;
1661
1662	switch (bp_params->engine_id) {
1663	case ENGINE_ID_DACA:
1664		params.ucDevice = ATOM_DEVICE_CRT1_INDEX;
1665		break;
1666	case ENGINE_ID_DACB:
1667		params.ucDevice = ATOM_DEVICE_CRT2_INDEX;
1668		break;
1669	default:
1670		return BP_RESULT_BADINPUT;
1671	}
1672
1673	if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
1674		result = BP_RESULT_OK;
1675
1676	return result;
1677}
1678
1679static bool select_crtc_source_v2_encoder_id(
1680	enum engine_id engine_id, uint8_t *out_encoder_id)
1681{
1682	uint8_t encoder_id = 0;
1683
1684	switch (engine_id) {
1685	case ENGINE_ID_DIGA:
1686		encoder_id = ASIC_INT_DIG1_ENCODER_ID;
1687		break;
1688	case ENGINE_ID_DIGB:
1689		encoder_id = ASIC_INT_DIG2_ENCODER_ID;
1690		break;
1691	case ENGINE_ID_DIGC:
1692		encoder_id = ASIC_INT_DIG3_ENCODER_ID;
1693		break;
1694	case ENGINE_ID_DIGD:
1695		encoder_id = ASIC_INT_DIG4_ENCODER_ID;
1696		break;
1697	case ENGINE_ID_DIGE:
1698		encoder_id = ASIC_INT_DIG5_ENCODER_ID;
1699		break;
1700	case ENGINE_ID_DIGF:
1701		encoder_id = ASIC_INT_DIG6_ENCODER_ID;
1702		break;
1703	case ENGINE_ID_DIGG:
1704		encoder_id = ASIC_INT_DIG7_ENCODER_ID;
1705		break;
1706	case ENGINE_ID_DACA:
1707		encoder_id = ASIC_INT_DAC1_ENCODER_ID;
1708		break;
1709	case ENGINE_ID_DACB:
1710		encoder_id = ASIC_INT_DAC2_ENCODER_ID;
1711		break;
1712	default:
1713		return false;
1714	}
1715
1716	*out_encoder_id = encoder_id;
1717	return true;
1718}
1719
1720static bool select_crtc_source_v2_encoder_mode(
1721	enum signal_type signal_type, uint8_t *out_encoder_mode)
1722{
1723	uint8_t encoder_mode = 0;
1724
1725	switch (signal_type) {
1726	case SIGNAL_TYPE_DVI_SINGLE_LINK:
1727	case SIGNAL_TYPE_DVI_DUAL_LINK:
1728		encoder_mode = ATOM_ENCODER_MODE_DVI;
1729		break;
1730	case SIGNAL_TYPE_HDMI_TYPE_A:
1731		encoder_mode = ATOM_ENCODER_MODE_HDMI;
1732		break;
1733	case SIGNAL_TYPE_LVDS:
1734		encoder_mode = ATOM_ENCODER_MODE_LVDS;
1735		break;
1736	case SIGNAL_TYPE_RGB:
1737		encoder_mode = ATOM_ENCODER_MODE_CRT;
1738		break;
1739	case SIGNAL_TYPE_DISPLAY_PORT:
1740		encoder_mode = ATOM_ENCODER_MODE_DP;
1741		break;
1742	case SIGNAL_TYPE_DISPLAY_PORT_MST:
1743		encoder_mode = ATOM_ENCODER_MODE_DP_MST;
1744		break;
1745	case SIGNAL_TYPE_EDP:
1746		encoder_mode = ATOM_ENCODER_MODE_DP;
1747		break;
1748	default:
1749		return false;
1750	}
1751
1752	*out_encoder_mode = encoder_mode;
1753	return true;
1754}
1755
1756static enum bp_result select_crtc_source_v2(
1757	struct bios_parser *bp,
1758	struct bp_crtc_source_select *bp_params)
1759{
1760	enum bp_result result = BP_RESULT_FAILURE;
1761	SELECT_CRTC_SOURCE_PARAMETERS_V3 params;
1762
1763	if (!bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &params.ucCRTC))
1764		return BP_RESULT_BADINPUT;
1765
1766	if (!select_crtc_source_v2_encoder_id(
1767		bp_params->engine_id,
1768		&params.ucEncoderID))
1769		return BP_RESULT_BADINPUT;
1770	if (!select_crtc_source_v2_encoder_mode(
1771		bp_params->sink_signal,
1772		&params.ucEncodeMode))
1773		return BP_RESULT_BADINPUT;
1774
1775	if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
1776		result = BP_RESULT_OK;
1777
1778	return result;
1779}
1780
1781static enum bp_result select_crtc_source_v3(
1782	struct bios_parser *bp,
1783	struct bp_crtc_source_select *bp_params)
1784{
1785	enum bp_result result = BP_RESULT_FAILURE;
1786	SELECT_CRTC_SOURCE_PARAMETERS_V3 params;
1787
1788	if (!bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &params.ucCRTC))
1789		return BP_RESULT_BADINPUT;
1790
1791	if (!select_crtc_source_v2_encoder_id(
1792		bp_params->engine_id,
1793		&params.ucEncoderID))
1794		return BP_RESULT_BADINPUT;
1795	if (!select_crtc_source_v2_encoder_mode(
1796		bp_params->sink_signal,
1797		&params.ucEncodeMode))
1798		return BP_RESULT_BADINPUT;
1799
1800	switch (bp_params->color_depth) {
1801	case COLOR_DEPTH_UNDEFINED:
1802		params.ucDstBpc = PANEL_BPC_UNDEFINE;
1803		break;
1804	case COLOR_DEPTH_666:
1805		params.ucDstBpc = PANEL_6BIT_PER_COLOR;
1806		break;
1807	default:
1808	case COLOR_DEPTH_888:
1809		params.ucDstBpc = PANEL_8BIT_PER_COLOR;
1810		break;
1811	case COLOR_DEPTH_101010:
1812		params.ucDstBpc = PANEL_10BIT_PER_COLOR;
1813		break;
1814	case COLOR_DEPTH_121212:
1815		params.ucDstBpc = PANEL_12BIT_PER_COLOR;
1816		break;
1817	case COLOR_DEPTH_141414:
1818		dm_error("14-bit color not supported by SelectCRTC_Source v3\n");
1819		break;
1820	case COLOR_DEPTH_161616:
1821		params.ucDstBpc = PANEL_16BIT_PER_COLOR;
1822		break;
1823	}
1824
1825	if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
1826		result = BP_RESULT_OK;
1827
1828	return result;
1829}
1830
1831/*******************************************************************************
1832 ********************************************************************************
1833 **
1834 **                  DAC ENCODER CONTROL
1835 **
1836 ********************************************************************************
1837 *******************************************************************************/
1838
1839static enum bp_result dac1_encoder_control_v1(
1840	struct bios_parser *bp,
1841	enum bp_encoder_control_action action,
1842	uint32_t pixel_clock,
1843	uint8_t dac_standard);
1844static enum bp_result dac2_encoder_control_v1(
1845	struct bios_parser *bp,
1846	enum bp_encoder_control_action action,
1847	uint32_t pixel_clock,
1848	uint8_t dac_standard);
1849
1850static void init_dac_encoder_control(struct bios_parser *bp)
1851{
1852	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) {
1853	case 1:
1854		bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1;
1855		break;
1856	default:
1857		bp->cmd_tbl.dac1_encoder_control = NULL;
1858		break;
1859	}
1860	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) {
1861	case 1:
1862		bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1;
1863		break;
1864	default:
1865		bp->cmd_tbl.dac2_encoder_control = NULL;
1866		break;
1867	}
1868}
1869
1870static void dac_encoder_control_prepare_params(
1871	DAC_ENCODER_CONTROL_PS_ALLOCATION *params,
1872	enum bp_encoder_control_action action,
1873	uint32_t pixel_clock,
1874	uint8_t dac_standard)
1875{
1876	params->ucDacStandard = dac_standard;
1877	if (action == ENCODER_CONTROL_INIT)
1878		params->ucAction = ATOM_ENCODER_INIT;
1879	else if (action == ENCODER_CONTROL_ENABLE)
1880		params->ucAction = ATOM_ENABLE;
1881	else
1882		params->ucAction = ATOM_DISABLE;
1883
1884	/* We need to convert from KHz units into 10KHz units
1885	 * it looks as if the TvControl do not care about pixel clock
1886	 */
1887	params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10));
1888}
1889
1890static enum bp_result dac1_encoder_control_v1(
1891	struct bios_parser *bp,
1892	enum bp_encoder_control_action action,
1893	uint32_t pixel_clock,
1894	uint8_t dac_standard)
1895{
1896	enum bp_result result = BP_RESULT_FAILURE;
1897	DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1898
1899	dac_encoder_control_prepare_params(
1900		&params,
1901		action,
1902		pixel_clock,
1903		dac_standard);
1904
1905	if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params))
1906		result = BP_RESULT_OK;
1907
1908	return result;
1909}
1910
1911static enum bp_result dac2_encoder_control_v1(
1912	struct bios_parser *bp,
1913	enum bp_encoder_control_action action,
1914	uint32_t pixel_clock,
1915	uint8_t dac_standard)
1916{
1917	enum bp_result result = BP_RESULT_FAILURE;
1918	DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1919
1920	dac_encoder_control_prepare_params(
1921		&params,
1922		action,
1923		pixel_clock,
1924		dac_standard);
1925
1926	if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params))
1927		result = BP_RESULT_OK;
1928
1929	return result;
1930}
1931
1932/*******************************************************************************
1933 ********************************************************************************
1934 **
1935 **                  DAC LOAD DETECTION
1936 **
1937 ********************************************************************************
1938 *******************************************************************************/
1939
1940static enum bp_result dac_load_detection_v1(
1941	struct bios_parser *bp,
1942	struct bp_load_detection_parameters *bp_params);
1943
1944static enum bp_result dac_load_detection_v3(
1945	struct bios_parser *bp,
1946	struct bp_load_detection_parameters *bp_params);
1947
1948static void init_dac_load_detection(struct bios_parser *bp)
1949{
1950	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC_LoadDetection)) {
1951	case 1:
1952	case 2:
1953		bp->cmd_tbl.dac_load_detection = dac_load_detection_v1;
1954		break;
1955	case 3:
1956	default:
1957		bp->cmd_tbl.dac_load_detection = dac_load_detection_v3;
1958		break;
1959	}
1960}
1961
1962static void dac_load_detect_prepare_params(
1963	struct _DAC_LOAD_DETECTION_PS_ALLOCATION *params,
1964	enum engine_id engine_id,
1965	uint16_t device_id,
1966	uint8_t misc)
1967{
1968	uint8_t dac_type = ENGINE_ID_DACA;
1969
1970	if (engine_id == ENGINE_ID_DACB)
1971		dac_type = ATOM_DAC_B;
1972
1973	params->sDacload.usDeviceID = cpu_to_le16(device_id);
1974	params->sDacload.ucDacType = dac_type;
1975	params->sDacload.ucMisc = misc;
1976}
1977
1978static enum bp_result dac_load_detection_v1(
1979	struct bios_parser *bp,
1980	struct bp_load_detection_parameters *bp_params)
1981{
1982	enum bp_result result = BP_RESULT_FAILURE;
1983	DAC_LOAD_DETECTION_PS_ALLOCATION params;
1984
1985	dac_load_detect_prepare_params(
1986		&params,
1987		bp_params->engine_id,
1988		bp_params->device_id,
1989		0);
1990
1991	if (EXEC_BIOS_CMD_TABLE(DAC_LoadDetection, params))
1992		result = BP_RESULT_OK;
1993
1994	return result;
1995}
1996
1997static enum bp_result dac_load_detection_v3(
1998	struct bios_parser *bp,
1999	struct bp_load_detection_parameters *bp_params)
2000{
2001	enum bp_result result = BP_RESULT_FAILURE;
2002	DAC_LOAD_DETECTION_PS_ALLOCATION params;
2003
2004	uint8_t misc = 0;
2005
2006	if (bp_params->device_id == ATOM_DEVICE_CV_SUPPORT ||
2007	    bp_params->device_id == ATOM_DEVICE_TV1_SUPPORT)
2008		misc = DAC_LOAD_MISC_YPrPb;
2009
2010	dac_load_detect_prepare_params(
2011		&params,
2012		bp_params->engine_id,
2013		bp_params->device_id,
2014		misc);
2015
2016	if (EXEC_BIOS_CMD_TABLE(DAC_LoadDetection, params))
2017		result = BP_RESULT_OK;
2018
2019	return result;
2020}
2021
2022/*******************************************************************************
2023 ********************************************************************************
2024 **
2025 **                  DAC OUTPUT CONTROL
2026 **
2027 ********************************************************************************
2028 *******************************************************************************/
2029static enum bp_result dac1_output_control_v1(
2030	struct bios_parser *bp,
2031	bool enable);
2032static enum bp_result dac2_output_control_v1(
2033	struct bios_parser *bp,
2034	bool enable);
2035
2036static void init_dac_output_control(struct bios_parser *bp)
2037{
2038	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) {
2039	case 1:
2040		bp->cmd_tbl.dac1_output_control = dac1_output_control_v1;
2041		break;
2042	default:
2043		bp->cmd_tbl.dac1_output_control = NULL;
2044		break;
2045	}
2046	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) {
2047	case 1:
2048		bp->cmd_tbl.dac2_output_control = dac2_output_control_v1;
2049		break;
2050	default:
2051		bp->cmd_tbl.dac2_output_control = NULL;
2052		break;
2053	}
2054}
2055
2056static enum bp_result dac1_output_control_v1(
2057	struct bios_parser *bp, bool enable)
2058{
2059	enum bp_result result = BP_RESULT_FAILURE;
2060	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
2061
2062	if (enable)
2063		params.ucAction = ATOM_ENABLE;
2064	else
2065		params.ucAction = ATOM_DISABLE;
2066
2067	if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params))
2068		result = BP_RESULT_OK;
2069
2070	return result;
2071}
2072
2073static enum bp_result dac2_output_control_v1(
2074	struct bios_parser *bp, bool enable)
2075{
2076	enum bp_result result = BP_RESULT_FAILURE;
2077	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
2078
2079	if (enable)
2080		params.ucAction = ATOM_ENABLE;
2081	else
2082		params.ucAction = ATOM_DISABLE;
2083
2084	if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params))
2085		result = BP_RESULT_OK;
2086
2087	return result;
2088}
2089
2090/*******************************************************************************
2091 ********************************************************************************
2092 **
2093 **                  SET CRTC TIMING
2094 **
2095 ********************************************************************************
2096 *******************************************************************************/
2097
2098static enum bp_result set_crtc_using_dtd_timing_v3(
2099	struct bios_parser *bp,
2100	struct bp_hw_crtc_timing_parameters *bp_params);
2101static enum bp_result set_crtc_timing_v1(
2102	struct bios_parser *bp,
2103	struct bp_hw_crtc_timing_parameters *bp_params);
2104
2105static void init_set_crtc_timing(struct bios_parser *bp)
2106{
2107	uint32_t dtd_version =
2108			BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming);
2109	if (dtd_version > 2)
2110		switch (dtd_version) {
2111		case 3:
2112			bp->cmd_tbl.set_crtc_timing =
2113					set_crtc_using_dtd_timing_v3;
2114			break;
2115		default:
2116			dm_output_to_console("Don't have set_crtc_timing for dtd v%d\n",
2117				 dtd_version);
2118			bp->cmd_tbl.set_crtc_timing = NULL;
2119			break;
2120		}
2121	else
2122		switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) {
2123		case 1:
2124			bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1;
2125			break;
2126		default:
2127			dm_output_to_console("Don't have set_crtc_timing for v%d\n",
2128				 BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing));
2129			bp->cmd_tbl.set_crtc_timing = NULL;
2130			break;
2131		}
2132}
2133
2134static enum bp_result set_crtc_timing_v1(
2135	struct bios_parser *bp,
2136	struct bp_hw_crtc_timing_parameters *bp_params)
2137{
2138	enum bp_result result = BP_RESULT_FAILURE;
2139	SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0};
2140	uint8_t atom_controller_id;
2141
2142	if (bp->cmd_helper->controller_id_to_atom(
2143			bp_params->controller_id, &atom_controller_id))
2144		params.ucCRTC = atom_controller_id;
2145
2146	params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total));
2147	params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable));
2148	params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start));
2149	params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width));
2150	params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total));
2151	params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable));
2152	params.usV_SyncStart =
2153			cpu_to_le16((uint16_t)(bp_params->v_sync_start));
2154	params.usV_SyncWidth =
2155			cpu_to_le16((uint16_t)(bp_params->v_sync_width));
2156
2157	/* VBIOS does not expect any value except zero into this call, for
2158	 * underscan use another entry ProgramOverscan call but when mode
2159	 * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok,
2160	 * but when same ,but 60 Hz there is corruption
2161	 * DAL1 does not allow the mode 1776x1000@60
2162	 */
2163	params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right;
2164	params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left;
2165	params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom;
2166	params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top;
2167
2168	if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
2169		params.susModeMiscInfo.usAccess =
2170				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
2171
2172	if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
2173		params.susModeMiscInfo.usAccess =
2174				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
2175
2176	if (bp_params->flags.INTERLACE) {
2177		params.susModeMiscInfo.usAccess =
2178				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
2179
2180		/* original DAL code has this condition to apply tis for
2181		 * non-TV/CV only due to complex MV testing for possible
2182		 * impact
2183		 * if (pACParameters->signal != SignalType_YPbPr &&
2184		 *  pACParameters->signal != SignalType_Composite &&
2185		 *  pACParameters->signal != SignalType_SVideo)
2186		 */
2187		/* HW will deduct 0.5 line from 2nd feild.
2188		 * i.e. for 1080i, it is 2 lines for 1st field, 2.5
2189		 * lines for the 2nd feild. we need input as 5 instead
2190		 * of 4, but it is 4 either from Edid data
2191		 * (spec CEA 861) or CEA timing table.
2192		 */
2193		params.usV_SyncStart =
2194				cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1));
2195	}
2196
2197	if (bp_params->flags.HORZ_COUNT_BY_TWO)
2198		params.susModeMiscInfo.usAccess =
2199				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
2200
2201	if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params))
2202		result = BP_RESULT_OK;
2203
2204	return result;
2205}
2206
2207static enum bp_result set_crtc_using_dtd_timing_v3(
2208	struct bios_parser *bp,
2209	struct bp_hw_crtc_timing_parameters *bp_params)
2210{
2211	enum bp_result result = BP_RESULT_FAILURE;
2212	SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0};
2213	uint8_t atom_controller_id;
2214
2215	if (bp->cmd_helper->controller_id_to_atom(
2216			bp_params->controller_id, &atom_controller_id))
2217		params.ucCRTC = atom_controller_id;
2218
2219	/* bios usH_Size wants h addressable size */
2220	params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable);
2221	/* bios usH_Blanking_Time wants borders included in blanking */
2222	params.usH_Blanking_Time =
2223			cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable));
2224	/* bios usV_Size wants v addressable size */
2225	params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable);
2226	/* bios usV_Blanking_Time wants borders included in blanking */
2227	params.usV_Blanking_Time =
2228			cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable));
2229	/* bios usHSyncOffset is the offset from the end of h addressable,
2230	 * our horizontalSyncStart is the offset from the beginning
2231	 * of h addressable */
2232	params.usH_SyncOffset =
2233			cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable));
2234	params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);
2235	/* bios usHSyncOffset is the offset from the end of v addressable,
2236	 * our verticalSyncStart is the offset from the beginning of
2237	 * v addressable */
2238	params.usV_SyncOffset =
2239			cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable));
2240	params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);
2241
2242	/* we assume that overscan from original timing does not get bigger
2243	 * than 255
2244	 * we will program all the borders in the Set CRTC Overscan call below
2245	 */
2246
2247	if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
2248		params.susModeMiscInfo.usAccess =
2249				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
2250
2251	if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
2252		params.susModeMiscInfo.usAccess =
2253				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
2254
2255	if (bp_params->flags.INTERLACE)	{
2256		params.susModeMiscInfo.usAccess =
2257				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
2258
2259		/* original DAL code has this condition to apply this
2260		 * for non-TV/CV only
2261		 * due to complex MV testing for possible impact
2262		 * if ( pACParameters->signal != SignalType_YPbPr &&
2263		 *  pACParameters->signal != SignalType_Composite &&
2264		 *  pACParameters->signal != SignalType_SVideo)
2265		 */
2266		{
2267			/* HW will deduct 0.5 line from 2nd feild.
2268			 * i.e. for 1080i, it is 2 lines for 1st field,
2269			 * 2.5 lines for the 2nd feild. we need input as 5
2270			 * instead of 4.
2271			 * but it is 4 either from Edid data (spec CEA 861)
2272			 * or CEA timing table.
2273			 */
2274			le16_add_cpu(&params.usV_SyncOffset, 1);
2275		}
2276	}
2277
2278	if (bp_params->flags.HORZ_COUNT_BY_TWO)
2279		params.susModeMiscInfo.usAccess =
2280				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
2281
2282	if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params))
2283		result = BP_RESULT_OK;
2284
2285	return result;
2286}
2287
2288/*******************************************************************************
2289 ********************************************************************************
2290 **
2291 **                  ENABLE CRTC
2292 **
2293 ********************************************************************************
2294 *******************************************************************************/
2295
2296static enum bp_result enable_crtc_v1(
2297	struct bios_parser *bp,
2298	enum controller_id controller_id,
2299	bool enable);
2300
2301static void init_enable_crtc(struct bios_parser *bp)
2302{
2303	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) {
2304	case 1:
2305		bp->cmd_tbl.enable_crtc = enable_crtc_v1;
2306		break;
2307	default:
2308		dm_output_to_console("Don't have enable_crtc for v%d\n",
2309			 BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC));
2310		bp->cmd_tbl.enable_crtc = NULL;
2311		break;
2312	}
2313}
2314
2315static enum bp_result enable_crtc_v1(
2316	struct bios_parser *bp,
2317	enum controller_id controller_id,
2318	bool enable)
2319{
2320	bool result = BP_RESULT_FAILURE;
2321	ENABLE_CRTC_PARAMETERS params = {0};
2322	uint8_t id;
2323
2324	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))
2325		params.ucCRTC = id;
2326	else
2327		return BP_RESULT_BADINPUT;
2328
2329	if (enable)
2330		params.ucEnable = ATOM_ENABLE;
2331	else
2332		params.ucEnable = ATOM_DISABLE;
2333
2334	if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params))
2335		result = BP_RESULT_OK;
2336
2337	return result;
2338}
2339
2340/*******************************************************************************
2341 ********************************************************************************
2342 **
2343 **                  ENABLE CRTC MEM REQ
2344 **
2345 ********************************************************************************
2346 *******************************************************************************/
2347
2348static enum bp_result enable_crtc_mem_req_v1(
2349	struct bios_parser *bp,
2350	enum controller_id controller_id,
2351	bool enable);
2352
2353static void init_enable_crtc_mem_req(struct bios_parser *bp)
2354{
2355	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) {
2356	case 1:
2357		bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1;
2358		break;
2359	default:
2360		bp->cmd_tbl.enable_crtc_mem_req = NULL;
2361		break;
2362	}
2363}
2364
2365static enum bp_result enable_crtc_mem_req_v1(
2366	struct bios_parser *bp,
2367	enum controller_id controller_id,
2368	bool enable)
2369{
2370	bool result = BP_RESULT_BADINPUT;
2371	ENABLE_CRTC_PARAMETERS params = {0};
2372	uint8_t id;
2373
2374	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) {
2375		params.ucCRTC = id;
2376
2377		if (enable)
2378			params.ucEnable = ATOM_ENABLE;
2379		else
2380			params.ucEnable = ATOM_DISABLE;
2381
2382		if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params))
2383			result = BP_RESULT_OK;
2384		else
2385			result = BP_RESULT_FAILURE;
2386	}
2387
2388	return result;
2389}
2390
2391/*******************************************************************************
2392 ********************************************************************************
2393 **
2394 **                  DISPLAY PLL
2395 **
2396 ********************************************************************************
2397 *******************************************************************************/
2398
2399static enum bp_result program_clock_v5(
2400	struct bios_parser *bp,
2401	struct bp_pixel_clock_parameters *bp_params);
2402static enum bp_result program_clock_v6(
2403	struct bios_parser *bp,
2404	struct bp_pixel_clock_parameters *bp_params);
2405
2406static void init_program_clock(struct bios_parser *bp)
2407{
2408	switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
2409	case 5:
2410		bp->cmd_tbl.program_clock = program_clock_v5;
2411		break;
2412	case 6:
2413		bp->cmd_tbl.program_clock = program_clock_v6;
2414		break;
2415	default:
2416		dm_output_to_console("Don't have program_clock for v%d\n",
2417			 BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
2418		bp->cmd_tbl.program_clock = NULL;
2419		break;
2420	}
2421}
2422
2423static enum bp_result program_clock_v5(
2424	struct bios_parser *bp,
2425	struct bp_pixel_clock_parameters *bp_params)
2426{
2427	enum bp_result result = BP_RESULT_FAILURE;
2428
2429	SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params;
2430	uint32_t atom_pll_id;
2431
2432	memset(&params, 0, sizeof(params));
2433	if (!bp->cmd_helper->clock_source_id_to_atom(
2434			bp_params->pll_id, &atom_pll_id)) {
2435		BREAK_TO_DEBUGGER(); /* Invalid Input!! */
2436		return BP_RESULT_BADINPUT;
2437	}
2438
2439	/* We need to convert from KHz units into 10KHz units */
2440	params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id;
2441	params.sPCLKInput.usPixelClock =
2442			cpu_to_le16((uint16_t) (bp_params->target_pixel_clock_100hz / 100));
2443	params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID;
2444
2445	if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2446		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2447
2448	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params))
2449		result = BP_RESULT_OK;
2450
2451	return result;
2452}
2453
2454static enum bp_result program_clock_v6(
2455	struct bios_parser *bp,
2456	struct bp_pixel_clock_parameters *bp_params)
2457{
2458	enum bp_result result = BP_RESULT_FAILURE;
2459
2460	SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params;
2461	uint32_t atom_pll_id;
2462
2463	memset(&params, 0, sizeof(params));
2464
2465	if (!bp->cmd_helper->clock_source_id_to_atom(
2466			bp_params->pll_id, &atom_pll_id)) {
2467		BREAK_TO_DEBUGGER(); /*Invalid Input!!*/
2468		return BP_RESULT_BADINPUT;
2469	}
2470
2471	/* We need to convert from KHz units into 10KHz units */
2472	params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id;
2473	params.sPCLKInput.ulDispEngClkFreq =
2474			cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
2475
2476	if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2477		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2478
2479	if (bp_params->flags.SET_DISPCLK_DFS_BYPASS)
2480		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_DPREFCLK_BYPASS;
2481
2482	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) {
2483		/* True display clock is returned by VBIOS if DFS bypass
2484		 * is enabled. */
2485		bp_params->dfs_bypass_display_clock =
2486				(uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10);
2487		result = BP_RESULT_OK;
2488	}
2489
2490	return result;
2491}
2492
2493/*******************************************************************************
2494 ********************************************************************************
2495 **
2496 **                  EXTERNAL ENCODER CONTROL
2497 **
2498 ********************************************************************************
2499 *******************************************************************************/
2500
2501static enum bp_result external_encoder_control_v3(
2502	struct bios_parser *bp,
2503	struct bp_external_encoder_control *cntl);
2504
2505static void init_external_encoder_control(
2506	struct bios_parser *bp)
2507{
2508	switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) {
2509	case 3:
2510		bp->cmd_tbl.external_encoder_control =
2511				external_encoder_control_v3;
2512		break;
2513	default:
2514		bp->cmd_tbl.external_encoder_control = NULL;
2515		break;
2516	}
2517}
2518
2519static enum bp_result external_encoder_control_v3(
2520	struct bios_parser *bp,
2521	struct bp_external_encoder_control *cntl)
2522{
2523	enum bp_result result = BP_RESULT_FAILURE;
2524
2525	/* we need use _PS_Alloc struct */
2526	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 params;
2527	EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 *cntl_params;
2528	struct graphics_object_id encoder;
2529	bool is_input_signal_dp = false;
2530
2531	memset(&params, 0, sizeof(params));
2532
2533	cntl_params = &params.sExtEncoder;
2534
2535	encoder = cntl->encoder_id;
2536
2537	/* check if encoder supports external encoder control table */
2538	switch (dal_graphics_object_id_get_encoder_id(encoder)) {
2539	case ENCODER_ID_EXTERNAL_NUTMEG:
2540	case ENCODER_ID_EXTERNAL_TRAVIS:
2541		is_input_signal_dp = true;
2542		break;
2543
2544	default:
2545		BREAK_TO_DEBUGGER();
2546		return BP_RESULT_BADINPUT;
2547	}
2548
2549	/* Fill information based on the action
2550	 *
2551	 * Bit[6:4]: indicate external encoder, applied to all functions.
2552	 * =0: external encoder1, mapped to external encoder enum id1
2553	 * =1: external encoder2, mapped to external encoder enum id2
2554	 *
2555	 * enum ObjectEnumId
2556	 * {
2557	 *  EnumId_Unknown = 0,
2558	 *  EnumId_1,
2559	 *  EnumId_2,
2560	 * };
2561	 */
2562	cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4);
2563
2564	switch (cntl->action) {
2565	case EXTERNAL_ENCODER_CONTROL_INIT:
2566		/* output display connector type. Only valid in encoder
2567		 * initialization */
2568		cntl_params->usConnectorId =
2569				cpu_to_le16((uint16_t)cntl->connector_obj_id.id);
2570		break;
2571	case EXTERNAL_ENCODER_CONTROL_SETUP:
2572		/* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in
2573		 * 10KHz
2574		 * output display device pixel clock frequency in unit of 10KHz.
2575		 * Only valid in setup and enableoutput
2576		 */
2577		cntl_params->usPixelClock =
2578				cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2579		/* Indicate display output signal type drive by external
2580		 * encoder, only valid in setup and enableoutput */
2581		cntl_params->ucEncoderMode =
2582				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2583						cntl->signal, false);
2584
2585		if (is_input_signal_dp) {
2586			/* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz,
2587			 * only valid in encoder setup with DP mode. */
2588			if (LINK_RATE_HIGH == cntl->link_rate)
2589				cntl_params->ucConfig |= 1;
2590			/* output color depth Indicate encoder data bpc format
2591			 * in DP mode, only valid in encoder setup in DP mode.
2592			 */
2593			cntl_params->ucBitPerColor =
2594					(uint8_t)(cntl->color_depth);
2595		}
2596		/* Indicate how many lanes used by external encoder, only valid
2597		 * in encoder setup and enableoutput. */
2598		cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);
2599		break;
2600	case EXTERNAL_ENCODER_CONTROL_ENABLE:
2601		cntl_params->usPixelClock =
2602				cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2603		cntl_params->ucEncoderMode =
2604				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2605						cntl->signal, false);
2606		cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number;
2607		break;
2608	default:
2609		break;
2610	}
2611
2612	cntl_params->ucAction = (uint8_t)cntl->action;
2613
2614	if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params))
2615		result = BP_RESULT_OK;
2616
2617	return result;
2618}
2619
2620/*******************************************************************************
2621 ********************************************************************************
2622 **
2623 **                  ENABLE DISPLAY POWER GATING
2624 **
2625 ********************************************************************************
2626 *******************************************************************************/
2627
2628static enum bp_result enable_disp_power_gating_v2_1(
2629	struct bios_parser *bp,
2630	enum controller_id crtc_id,
2631	enum bp_pipe_control_action action);
2632
2633static void init_enable_disp_power_gating(
2634	struct bios_parser *bp)
2635{
2636	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) {
2637	case 1:
2638		bp->cmd_tbl.enable_disp_power_gating =
2639				enable_disp_power_gating_v2_1;
2640		break;
2641	default:
2642		dm_output_to_console("Don't enable_disp_power_gating enable_crtc for v%d\n",
2643			 BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating));
2644		bp->cmd_tbl.enable_disp_power_gating = NULL;
2645		break;
2646	}
2647}
2648
2649static enum bp_result enable_disp_power_gating_v2_1(
2650	struct bios_parser *bp,
2651	enum controller_id crtc_id,
2652	enum bp_pipe_control_action action)
2653{
2654	enum bp_result result = BP_RESULT_FAILURE;
2655
2656	ENABLE_DISP_POWER_GATING_PS_ALLOCATION params = {0};
2657	uint8_t atom_crtc_id;
2658
2659	if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))
2660		params.ucDispPipeId = atom_crtc_id;
2661	else
2662		return BP_RESULT_BADINPUT;
2663
2664	params.ucEnable =
2665			bp->cmd_helper->disp_power_gating_action_to_atom(action);
2666
2667	if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params))
2668		result = BP_RESULT_OK;
2669
2670	return result;
2671}
2672
2673/*******************************************************************************
2674 ********************************************************************************
2675 **
2676 **                  SET DCE CLOCK
2677 **
2678 ********************************************************************************
2679 *******************************************************************************/
2680static enum bp_result set_dce_clock_v2_1(
2681	struct bios_parser *bp,
2682	struct bp_set_dce_clock_parameters *bp_params);
2683
2684static void init_set_dce_clock(struct bios_parser *bp)
2685{
2686	switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) {
2687	case 1:
2688		bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
2689		break;
2690	default:
2691		dm_output_to_console("Don't have set_dce_clock for v%d\n",
2692			 BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock));
2693		bp->cmd_tbl.set_dce_clock = NULL;
2694		break;
2695	}
2696}
2697
2698static enum bp_result set_dce_clock_v2_1(
2699	struct bios_parser *bp,
2700	struct bp_set_dce_clock_parameters *bp_params)
2701{
2702	enum bp_result result = BP_RESULT_FAILURE;
2703
2704	SET_DCE_CLOCK_PS_ALLOCATION_V2_1 params;
2705	uint32_t atom_pll_id;
2706	uint32_t atom_clock_type;
2707	const struct command_table_helper *cmd = bp->cmd_helper;
2708
2709	memset(&params, 0, sizeof(params));
2710
2711	if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||
2712			!cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type))
2713		return BP_RESULT_BADINPUT;
2714
2715	params.asParam.ucDCEClkSrc  = atom_pll_id;
2716	params.asParam.ucDCEClkType = atom_clock_type;
2717
2718	if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {
2719		if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)
2720			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;
2721
2722		if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)
2723			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;
2724
2725		if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)
2726			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;
2727
2728		if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)
2729			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;
2730	}
2731	else
2732		/* only program clock frequency if display clock is used; VBIOS will program DPREFCLK */
2733		/* We need to convert from KHz units into 10KHz units */
2734		params.asParam.ulDCEClkFreq = cpu_to_le32(bp_params->target_clock_frequency / 10);
2735
2736	if (EXEC_BIOS_CMD_TABLE(SetDCEClock, params)) {
2737		/* Convert from 10KHz units back to KHz */
2738		bp_params->target_clock_frequency = le32_to_cpu(params.asParam.ulDCEClkFreq) * 10;
2739		result = BP_RESULT_OK;
2740	}
2741
2742	return result;
2743}
~/ Read-only file preview.