Linux Audio

Check our new training course

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