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 
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 	(cgs_atom_exec_cmd_table(bp->base.ctx->cgs_device, \
39 		GetIndexIntoMasterTable(COMMAND, command), \
40 		&params) == 0)
41 
42 #define BIOS_CMD_TABLE_REVISION(command, frev, crev)\
43 	cgs_atom_get_cmd_table_revs(bp->base.ctx->cgs_device, \
44 		GetIndexIntoMasterTable(COMMAND, command), &frev, &crev)
45 
46 #define BIOS_CMD_TABLE_PARA_REVISION(command)\
47 	bios_cmd_table_para_revision(bp->base.ctx->cgs_device, \
48 		GetIndexIntoMasterTable(COMMAND, command))
49 
50 static void init_dig_encoder_control(struct bios_parser *bp);
51 static void init_transmitter_control(struct bios_parser *bp);
52 static void init_set_pixel_clock(struct bios_parser *bp);
53 static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp);
54 static void init_adjust_display_pll(struct bios_parser *bp);
55 static void init_dac_encoder_control(struct bios_parser *bp);
56 static void init_dac_output_control(struct bios_parser *bp);
57 static void init_set_crtc_timing(struct bios_parser *bp);
58 static void init_select_crtc_source(struct bios_parser *bp);
59 static void init_enable_crtc(struct bios_parser *bp);
60 static void init_enable_crtc_mem_req(struct bios_parser *bp);
61 static void init_external_encoder_control(struct bios_parser *bp);
62 static void init_enable_disp_power_gating(struct bios_parser *bp);
63 static void init_program_clock(struct bios_parser *bp);
64 static void init_set_dce_clock(struct bios_parser *bp);
65 
66 void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
67 {
68 	init_dig_encoder_control(bp);
69 	init_transmitter_control(bp);
70 	init_set_pixel_clock(bp);
71 	init_enable_spread_spectrum_on_ppll(bp);
72 	init_adjust_display_pll(bp);
73 	init_dac_encoder_control(bp);
74 	init_dac_output_control(bp);
75 	init_set_crtc_timing(bp);
76 	init_select_crtc_source(bp);
77 	init_enable_crtc(bp);
78 	init_enable_crtc_mem_req(bp);
79 	init_program_clock(bp);
80 	init_external_encoder_control(bp);
81 	init_enable_disp_power_gating(bp);
82 	init_set_dce_clock(bp);
83 }
84 
85 static uint32_t bios_cmd_table_para_revision(void *cgs_device,
86 					     uint32_t index)
87 {
88 	uint8_t frev, crev;
89 
90 	if (cgs_atom_get_cmd_table_revs(cgs_device,
91 					index,
92 					&frev, &crev) != 0)
93 		return 0;
94 	return crev;
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  *******************************************************************************/
104 static enum bp_result encoder_control_digx_v3(
105 	struct bios_parser *bp,
106 	struct bp_encoder_control *cntl);
107 
108 static enum bp_result encoder_control_digx_v4(
109 	struct bios_parser *bp,
110 	struct bp_encoder_control *cntl);
111 
112 static enum bp_result encoder_control_digx_v5(
113 	struct bios_parser *bp,
114 	struct bp_encoder_control *cntl);
115 
116 static void init_encoder_control_dig_v1(struct bios_parser *bp);
117 
118 static 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 
141 static enum bp_result encoder_control_dig_v1(
142 	struct bios_parser *bp,
143 	struct bp_encoder_control *cntl);
144 static enum bp_result encoder_control_dig1_v1(
145 	struct bios_parser *bp,
146 	struct bp_encoder_control *cntl);
147 static enum bp_result encoder_control_dig2_v1(
148 	struct bios_parser *bp,
149 	struct bp_encoder_control *cntl);
150 
151 static 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 
168 static 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 
195 static 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 
210 static 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 
225 static 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 
254 static 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 
283 static 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 
349 static enum bp_result transmitter_control_v2(
350 	struct bios_parser *bp,
351 	struct bp_transmitter_control *cntl);
352 static enum bp_result transmitter_control_v3(
353 	struct bios_parser *bp,
354 	struct bp_transmitter_control *cntl);
355 static enum bp_result transmitter_control_v4(
356 	struct bios_parser *bp,
357 	struct bp_transmitter_control *cntl);
358 static enum bp_result transmitter_control_v1_5(
359 	struct bios_parser *bp,
360 	struct bp_transmitter_control *cntl);
361 static enum bp_result transmitter_control_v1_6(
362 	struct bios_parser *bp,
363 	struct bp_transmitter_control *cntl);
364 
365 static 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) != 0)
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 
396 static 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 
516 static 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 
650 static 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 
773 static 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 
810 	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
811 		result = BP_RESULT_OK;
812 
813 	return result;
814 }
815 
816 static enum bp_result transmitter_control_v1_6(
817 	struct bios_parser *bp,
818 	struct bp_transmitter_control *cntl)
819 {
820 	enum bp_result result = BP_RESULT_FAILURE;
821 	const struct command_table_helper *cmd = bp->cmd_helper;
822 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params;
823 
824 	memset(&params, 0, sizeof(params));
825 	params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
826 	params.ucAction = (uint8_t)cntl->action;
827 
828 	if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
829 		params.ucDPLaneSet = (uint8_t)cntl->lane_settings;
830 	else
831 		params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal);
832 
833 	params.ucLaneNum = (uint8_t)cntl->lanes_number;
834 	params.ucHPDSel = cmd->hpd_sel_to_atom(cntl->hpd_sel);
835 	params.ucDigEncoderSel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);
836 	params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
837 	params.ulSymClock = cntl->pixel_clock/10;
838 
839 	/*
840 	 * In SI/TN case, caller have to set usPixelClock as following:
841 	 * DP mode: usPixelClock = DP_LINK_CLOCK/10
842 	 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
843 	 * DVI single link mode: usPixelClock = pixel clock
844 	 * DVI dual link mode: usPixelClock = pixel clock
845 	 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
846 	 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
847 	 * LVDS mode: usPixelClock = pixel clock
848 	 */
849 	switch (cntl->signal) {
850 	case SIGNAL_TYPE_HDMI_TYPE_A:
851 		switch (cntl->color_depth) {
852 		case COLOR_DEPTH_101010:
853 			params.ulSymClock =
854 				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24);
855 			break;
856 		case COLOR_DEPTH_121212:
857 			params.ulSymClock =
858 				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24);
859 			break;
860 		case COLOR_DEPTH_161616:
861 			params.ulSymClock =
862 				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24);
863 			break;
864 		default:
865 			break;
866 		}
867 		break;
868 		default:
869 			break;
870 	}
871 
872 	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
873 		result = BP_RESULT_OK;
874 	return result;
875 }
876 
877 /*******************************************************************************
878  ********************************************************************************
879  **
880  **                  SET PIXEL CLOCK
881  **
882  ********************************************************************************
883  *******************************************************************************/
884 
885 static enum bp_result set_pixel_clock_v3(
886 	struct bios_parser *bp,
887 	struct bp_pixel_clock_parameters *bp_params);
888 static enum bp_result set_pixel_clock_v5(
889 	struct bios_parser *bp,
890 	struct bp_pixel_clock_parameters *bp_params);
891 static enum bp_result set_pixel_clock_v6(
892 	struct bios_parser *bp,
893 	struct bp_pixel_clock_parameters *bp_params);
894 static enum bp_result set_pixel_clock_v7(
895 	struct bios_parser *bp,
896 	struct bp_pixel_clock_parameters *bp_params);
897 
898 static void init_set_pixel_clock(struct bios_parser *bp)
899 {
900 	switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
901 	case 3:
902 		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3;
903 		break;
904 	case 5:
905 		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5;
906 		break;
907 	case 6:
908 		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6;
909 		break;
910 	case 7:
911 		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
912 		break;
913 	default:
914 		dm_output_to_console("Don't have set_pixel_clock for v%d\n",
915 			 BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
916 		bp->cmd_tbl.set_pixel_clock = NULL;
917 		break;
918 	}
919 }
920 
921 static enum bp_result set_pixel_clock_v3(
922 	struct bios_parser *bp,
923 	struct bp_pixel_clock_parameters *bp_params)
924 {
925 	enum bp_result result = BP_RESULT_FAILURE;
926 	PIXEL_CLOCK_PARAMETERS_V3 *params;
927 	SET_PIXEL_CLOCK_PS_ALLOCATION allocation;
928 
929 	memset(&allocation, 0, sizeof(allocation));
930 
931 	if (CLOCK_SOURCE_ID_PLL1 == bp_params->pll_id)
932 		allocation.sPCLKInput.ucPpll = ATOM_PPLL1;
933 	else if (CLOCK_SOURCE_ID_PLL2 == bp_params->pll_id)
934 		allocation.sPCLKInput.ucPpll = ATOM_PPLL2;
935 	else
936 		return BP_RESULT_BADINPUT;
937 
938 	allocation.sPCLKInput.usRefDiv =
939 			cpu_to_le16((uint16_t)bp_params->reference_divider);
940 	allocation.sPCLKInput.usFbDiv =
941 			cpu_to_le16((uint16_t)bp_params->feedback_divider);
942 	allocation.sPCLKInput.ucFracFbDiv =
943 			(uint8_t)bp_params->fractional_feedback_divider;
944 	allocation.sPCLKInput.ucPostDiv =
945 			(uint8_t)bp_params->pixel_clock_post_divider;
946 
947 	/* We need to convert from KHz units into 10KHz units */
948 	allocation.sPCLKInput.usPixelClock =
949 			cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
950 
951 	params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput;
952 	params->ucTransmitterId =
953 			bp->cmd_helper->encoder_id_to_atom(
954 					dal_graphics_object_id_get_encoder_id(
955 							bp_params->encoder_object_id));
956 	params->ucEncoderMode =
957 			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
958 					bp_params->signal_type, false));
959 
960 	if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
961 		params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
962 
963 	if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK)
964 		params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK;
965 
966 	if (CONTROLLER_ID_D1 != bp_params->controller_id)
967 		params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;
968 
969 	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation))
970 		result = BP_RESULT_OK;
971 
972 	return result;
973 }
974 
975 #ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V5
976 /* video bios did not define this: */
977 typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V5 {
978 	PIXEL_CLOCK_PARAMETERS_V5 sPCLKInput;
979 	/* Caller doesn't need to init this portion */
980 	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
981 } SET_PIXEL_CLOCK_PS_ALLOCATION_V5;
982 #endif
983 
984 #ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V6
985 /* video bios did not define this: */
986 typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V6 {
987 	PIXEL_CLOCK_PARAMETERS_V6 sPCLKInput;
988 	/* Caller doesn't need to init this portion */
989 	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
990 } SET_PIXEL_CLOCK_PS_ALLOCATION_V6;
991 #endif
992 
993 static enum bp_result set_pixel_clock_v5(
994 	struct bios_parser *bp,
995 	struct bp_pixel_clock_parameters *bp_params)
996 {
997 	enum bp_result result = BP_RESULT_FAILURE;
998 	SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk;
999 	uint8_t controller_id;
1000 	uint32_t pll_id;
1001 
1002 	memset(&clk, 0, sizeof(clk));
1003 
1004 	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1005 			&& bp->cmd_helper->controller_id_to_atom(
1006 					bp_params->controller_id, &controller_id)) {
1007 		clk.sPCLKInput.ucCRTC = controller_id;
1008 		clk.sPCLKInput.ucPpll = (uint8_t)pll_id;
1009 		clk.sPCLKInput.ucRefDiv =
1010 				(uint8_t)(bp_params->reference_divider);
1011 		clk.sPCLKInput.usFbDiv =
1012 				cpu_to_le16((uint16_t)(bp_params->feedback_divider));
1013 		clk.sPCLKInput.ulFbDivDecFrac =
1014 				cpu_to_le32(bp_params->fractional_feedback_divider);
1015 		clk.sPCLKInput.ucPostDiv =
1016 				(uint8_t)(bp_params->pixel_clock_post_divider);
1017 		clk.sPCLKInput.ucTransmitterID =
1018 				bp->cmd_helper->encoder_id_to_atom(
1019 						dal_graphics_object_id_get_encoder_id(
1020 								bp_params->encoder_object_id));
1021 		clk.sPCLKInput.ucEncoderMode =
1022 				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1023 						bp_params->signal_type, false);
1024 
1025 		/* We need to convert from KHz units into 10KHz units */
1026 		clk.sPCLKInput.usPixelClock =
1027 				cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
1028 
1029 		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1030 			clk.sPCLKInput.ucMiscInfo |=
1031 					PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
1032 
1033 		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1034 			clk.sPCLKInput.ucMiscInfo |=
1035 					PIXEL_CLOCK_MISC_REF_DIV_SRC;
1036 
1037 		/* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp
1038 		 * =1:30bpp, =2:32bpp
1039 		 * driver choose program it itself, i.e. here we program it
1040 		 * to 888 by default.
1041 		 */
1042 
1043 		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1044 			result = BP_RESULT_OK;
1045 	}
1046 
1047 	return result;
1048 }
1049 
1050 static enum bp_result set_pixel_clock_v6(
1051 	struct bios_parser *bp,
1052 	struct bp_pixel_clock_parameters *bp_params)
1053 {
1054 	enum bp_result result = BP_RESULT_FAILURE;
1055 	SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk;
1056 	uint8_t controller_id;
1057 	uint32_t pll_id;
1058 
1059 	memset(&clk, 0, sizeof(clk));
1060 
1061 	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1062 			&& bp->cmd_helper->controller_id_to_atom(
1063 					bp_params->controller_id, &controller_id)) {
1064 		/* Note: VBIOS still wants to use ucCRTC name which is now
1065 		 * 1 byte in ULONG
1066 		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1067 		 *{
1068 		 * target the pixel clock to drive the CRTC timing.
1069 		 * ULONG ulPixelClock:24;
1070 		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1071 		 * previous version.
1072 		 * ATOM_CRTC1~6, indicate the CRTC controller to
1073 		 * ULONG ucCRTC:8;
1074 		 * drive the pixel clock. not used for DCPLL case.
1075 		 *}CRTC_PIXEL_CLOCK_FREQ;
1076 		 *union
1077 		 *{
1078 		 * pixel clock and CRTC id frequency
1079 		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1080 		 * ULONG ulDispEngClkFreq; dispclk frequency
1081 		 *};
1082 		 */
1083 		clk.sPCLKInput.ulCrtcPclkFreq.ucCRTC = controller_id;
1084 		clk.sPCLKInput.ucPpll = (uint8_t) pll_id;
1085 		clk.sPCLKInput.ucRefDiv =
1086 				(uint8_t) bp_params->reference_divider;
1087 		clk.sPCLKInput.usFbDiv =
1088 				cpu_to_le16((uint16_t) bp_params->feedback_divider);
1089 		clk.sPCLKInput.ulFbDivDecFrac =
1090 				cpu_to_le32(bp_params->fractional_feedback_divider);
1091 		clk.sPCLKInput.ucPostDiv =
1092 				(uint8_t) bp_params->pixel_clock_post_divider;
1093 		clk.sPCLKInput.ucTransmitterID =
1094 				bp->cmd_helper->encoder_id_to_atom(
1095 						dal_graphics_object_id_get_encoder_id(
1096 								bp_params->encoder_object_id));
1097 		clk.sPCLKInput.ucEncoderMode =
1098 				(uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(
1099 						bp_params->signal_type, false);
1100 
1101 		/* We need to convert from KHz units into 10KHz units */
1102 		clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock =
1103 				cpu_to_le32(bp_params->target_pixel_clock / 10);
1104 
1105 		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {
1106 			clk.sPCLKInput.ucMiscInfo |=
1107 					PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL;
1108 		}
1109 
1110 		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) {
1111 			clk.sPCLKInput.ucMiscInfo |=
1112 					PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
1113 		}
1114 
1115 		/* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0:
1116 		 * 24bpp =1:30bpp, =2:32bpp
1117 		 * driver choose program it itself, i.e. here we pass required
1118 		 * target rate that includes deep color.
1119 		 */
1120 
1121 		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1122 			result = BP_RESULT_OK;
1123 	}
1124 
1125 	return result;
1126 }
1127 
1128 static enum bp_result set_pixel_clock_v7(
1129 	struct bios_parser *bp,
1130 	struct bp_pixel_clock_parameters *bp_params)
1131 {
1132 	enum bp_result result = BP_RESULT_FAILURE;
1133 	PIXEL_CLOCK_PARAMETERS_V7 clk;
1134 	uint8_t controller_id;
1135 	uint32_t pll_id;
1136 
1137 	memset(&clk, 0, sizeof(clk));
1138 
1139 	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1140 			&& bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &controller_id)) {
1141 		/* Note: VBIOS still wants to use ucCRTC name which is now
1142 		 * 1 byte in ULONG
1143 		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1144 		 *{
1145 		 * target the pixel clock to drive the CRTC timing.
1146 		 * ULONG ulPixelClock:24;
1147 		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1148 		 * previous version.
1149 		 * ATOM_CRTC1~6, indicate the CRTC controller to
1150 		 * ULONG ucCRTC:8;
1151 		 * drive the pixel clock. not used for DCPLL case.
1152 		 *}CRTC_PIXEL_CLOCK_FREQ;
1153 		 *union
1154 		 *{
1155 		 * pixel clock and CRTC id frequency
1156 		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1157 		 * ULONG ulDispEngClkFreq; dispclk frequency
1158 		 *};
1159 		 */
1160 		clk.ucCRTC = controller_id;
1161 		clk.ucPpll = (uint8_t) pll_id;
1162 		clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id));
1163 		clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false);
1164 
1165 		/* We need to convert from KHz units into 10KHz units */
1166 		clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock * 10);
1167 
1168 		clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);
1169 
1170 		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1171 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
1172 
1173 		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1174 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC;
1175 
1176 		if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)
1177 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;
1178 
1179 		if (bp_params->flags.SUPPORT_YUV_420)
1180 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;
1181 
1182 		if (bp_params->flags.SET_XTALIN_REF_SRC)
1183 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;
1184 
1185 		if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)
1186 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;
1187 
1188 		if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1189 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
1190 
1191 		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1192 			result = BP_RESULT_OK;
1193 	}
1194 	return result;
1195 }
1196 
1197 /*******************************************************************************
1198  ********************************************************************************
1199  **
1200  **                  ENABLE PIXEL CLOCK SS
1201  **
1202  ********************************************************************************
1203  *******************************************************************************/
1204 static enum bp_result enable_spread_spectrum_on_ppll_v1(
1205 	struct bios_parser *bp,
1206 	struct bp_spread_spectrum_parameters *bp_params,
1207 	bool enable);
1208 static enum bp_result enable_spread_spectrum_on_ppll_v2(
1209 	struct bios_parser *bp,
1210 	struct bp_spread_spectrum_parameters *bp_params,
1211 	bool enable);
1212 static enum bp_result enable_spread_spectrum_on_ppll_v3(
1213 	struct bios_parser *bp,
1214 	struct bp_spread_spectrum_parameters *bp_params,
1215 	bool enable);
1216 
1217 static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp)
1218 {
1219 	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) {
1220 	case 1:
1221 		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1222 				enable_spread_spectrum_on_ppll_v1;
1223 		break;
1224 	case 2:
1225 		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1226 				enable_spread_spectrum_on_ppll_v2;
1227 		break;
1228 	case 3:
1229 		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1230 				enable_spread_spectrum_on_ppll_v3;
1231 		break;
1232 	default:
1233 		dm_output_to_console("Don't have enable_spread_spectrum_on_ppll for v%d\n",
1234 			 BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL));
1235 		bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL;
1236 		break;
1237 	}
1238 }
1239 
1240 static enum bp_result enable_spread_spectrum_on_ppll_v1(
1241 	struct bios_parser *bp,
1242 	struct bp_spread_spectrum_parameters *bp_params,
1243 	bool enable)
1244 {
1245 	enum bp_result result = BP_RESULT_FAILURE;
1246 	ENABLE_SPREAD_SPECTRUM_ON_PPLL params;
1247 
1248 	memset(&params, 0, sizeof(params));
1249 
1250 	if ((enable == true) && (bp_params->percentage > 0))
1251 		params.ucEnable = ATOM_ENABLE;
1252 	else
1253 		params.ucEnable = ATOM_DISABLE;
1254 
1255 	params.usSpreadSpectrumPercentage =
1256 			cpu_to_le16((uint16_t)bp_params->percentage);
1257 	params.ucSpreadSpectrumStep =
1258 			(uint8_t)bp_params->ver1.step;
1259 	params.ucSpreadSpectrumDelay =
1260 			(uint8_t)bp_params->ver1.delay;
1261 	/* convert back to unit of 10KHz */
1262 	params.ucSpreadSpectrumRange =
1263 			(uint8_t)(bp_params->ver1.range / 10000);
1264 
1265 	if (bp_params->flags.EXTERNAL_SS)
1266 		params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK;
1267 
1268 	if (bp_params->flags.CENTER_SPREAD)
1269 		params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE;
1270 
1271 	if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1272 		params.ucPpll = ATOM_PPLL1;
1273 	else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1274 		params.ucPpll = ATOM_PPLL2;
1275 	else
1276 		BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1277 
1278 	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1279 		result = BP_RESULT_OK;
1280 
1281 	return result;
1282 }
1283 
1284 static enum bp_result enable_spread_spectrum_on_ppll_v2(
1285 	struct bios_parser *bp,
1286 	struct bp_spread_spectrum_parameters *bp_params,
1287 	bool enable)
1288 {
1289 	enum bp_result result = BP_RESULT_FAILURE;
1290 	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params;
1291 
1292 	memset(&params, 0, sizeof(params));
1293 
1294 	if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1295 		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P1PLL;
1296 	else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1297 		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P2PLL;
1298 	else
1299 		BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1300 
1301 	if ((enable == true) && (bp_params->percentage > 0)) {
1302 		params.ucEnable = ATOM_ENABLE;
1303 
1304 		params.usSpreadSpectrumPercentage =
1305 				cpu_to_le16((uint16_t)(bp_params->percentage));
1306 		params.usSpreadSpectrumStep =
1307 				cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1308 
1309 		if (bp_params->flags.EXTERNAL_SS)
1310 			params.ucSpreadSpectrumType |=
1311 					ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD;
1312 
1313 		if (bp_params->flags.CENTER_SPREAD)
1314 			params.ucSpreadSpectrumType |=
1315 					ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD;
1316 
1317 		/* Both amounts need to be left shifted first before bit
1318 		 * comparison. Otherwise, the result will always be zero here
1319 		 */
1320 		params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1321 				((bp_params->ds.feedback_amount <<
1322 						ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT) &
1323 						ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK) |
1324 						((bp_params->ds.nfrac_amount <<
1325 								ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
1326 								ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK)));
1327 	} else
1328 		params.ucEnable = ATOM_DISABLE;
1329 
1330 	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1331 		result = BP_RESULT_OK;
1332 
1333 	return result;
1334 }
1335 
1336 static enum bp_result enable_spread_spectrum_on_ppll_v3(
1337 	struct bios_parser *bp,
1338 	struct bp_spread_spectrum_parameters *bp_params,
1339 	bool enable)
1340 {
1341 	enum bp_result result = BP_RESULT_FAILURE;
1342 	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params;
1343 
1344 	memset(&params, 0, sizeof(params));
1345 
1346 	switch (bp_params->pll_id) {
1347 	case CLOCK_SOURCE_ID_PLL0:
1348 		/* ATOM_PPLL_SS_TYPE_V3_P0PLL; this is pixel clock only,
1349 		 * not for SI display clock.
1350 		 */
1351 		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1352 		break;
1353 	case CLOCK_SOURCE_ID_PLL1:
1354 		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL;
1355 		break;
1356 
1357 	case CLOCK_SOURCE_ID_PLL2:
1358 		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL;
1359 		break;
1360 
1361 	case CLOCK_SOURCE_ID_DCPLL:
1362 		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1363 		break;
1364 
1365 	default:
1366 		BREAK_TO_DEBUGGER();
1367 		/* Unexpected PLL value!! */
1368 		return result;
1369 	}
1370 
1371 	if (enable == true) {
1372 		params.ucEnable = ATOM_ENABLE;
1373 
1374 		params.usSpreadSpectrumAmountFrac =
1375 				cpu_to_le16((uint16_t)(bp_params->ds_frac_amount));
1376 		params.usSpreadSpectrumStep =
1377 				cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1378 
1379 		if (bp_params->flags.EXTERNAL_SS)
1380 			params.ucSpreadSpectrumType |=
1381 					ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD;
1382 		if (bp_params->flags.CENTER_SPREAD)
1383 			params.ucSpreadSpectrumType |=
1384 					ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD;
1385 
1386 		/* Both amounts need to be left shifted first before bit
1387 		 * comparison. Otherwise, the result will always be zero here
1388 		 */
1389 		params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1390 				((bp_params->ds.feedback_amount <<
1391 						ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT) &
1392 						ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK) |
1393 						((bp_params->ds.nfrac_amount <<
1394 								ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT) &
1395 								ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK)));
1396 	} else
1397 		params.ucEnable = ATOM_DISABLE;
1398 
1399 	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1400 		result = BP_RESULT_OK;
1401 
1402 	return result;
1403 }
1404 
1405 /*******************************************************************************
1406  ********************************************************************************
1407  **
1408  **                  ADJUST DISPLAY PLL
1409  **
1410  ********************************************************************************
1411  *******************************************************************************/
1412 
1413 static enum bp_result adjust_display_pll_v2(
1414 	struct bios_parser *bp,
1415 	struct bp_adjust_pixel_clock_parameters *bp_params);
1416 static enum bp_result adjust_display_pll_v3(
1417 	struct bios_parser *bp,
1418 	struct bp_adjust_pixel_clock_parameters *bp_params);
1419 
1420 static void init_adjust_display_pll(struct bios_parser *bp)
1421 {
1422 	switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) {
1423 	case 2:
1424 		bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2;
1425 		break;
1426 	case 3:
1427 		bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3;
1428 		break;
1429 	default:
1430 		dm_output_to_console("Don't have adjust_display_pll for v%d\n",
1431 			 BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll));
1432 		bp->cmd_tbl.adjust_display_pll = NULL;
1433 		break;
1434 	}
1435 }
1436 
1437 static enum bp_result adjust_display_pll_v2(
1438 	struct bios_parser *bp,
1439 	struct bp_adjust_pixel_clock_parameters *bp_params)
1440 {
1441 	enum bp_result result = BP_RESULT_FAILURE;
1442 	ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 };
1443 
1444 	/* We need to convert from KHz units into 10KHz units and then convert
1445 	 * output pixel clock back 10KHz-->KHz */
1446 	uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10;
1447 
1448 	params.usPixelClock = cpu_to_le16((uint16_t)(pixel_clock_10KHz_in));
1449 	params.ucTransmitterID =
1450 			bp->cmd_helper->encoder_id_to_atom(
1451 					dal_graphics_object_id_get_encoder_id(
1452 							bp_params->encoder_object_id));
1453 	params.ucEncodeMode =
1454 			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1455 					bp_params->signal_type, false);
1456 	return result;
1457 }
1458 
1459 static enum bp_result adjust_display_pll_v3(
1460 	struct bios_parser *bp,
1461 	struct bp_adjust_pixel_clock_parameters *bp_params)
1462 {
1463 	enum bp_result result = BP_RESULT_FAILURE;
1464 	ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 params;
1465 	uint32_t pixel_clk_10_kHz_in = bp_params->pixel_clock / 10;
1466 
1467 	memset(&params, 0, sizeof(params));
1468 
1469 	/* We need to convert from KHz units into 10KHz units and then convert
1470 	 * output pixel clock back 10KHz-->KHz */
1471 	params.sInput.usPixelClock = cpu_to_le16((uint16_t)pixel_clk_10_kHz_in);
1472 	params.sInput.ucTransmitterID =
1473 			bp->cmd_helper->encoder_id_to_atom(
1474 					dal_graphics_object_id_get_encoder_id(
1475 							bp_params->encoder_object_id));
1476 	params.sInput.ucEncodeMode =
1477 			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1478 					bp_params->signal_type, false);
1479 
1480 	if (bp_params->ss_enable == true)
1481 		params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
1482 
1483 	if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1484 		params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
1485 
1486 	if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
1487 		/* Convert output pixel clock back 10KHz-->KHz: multiply
1488 		 * original pixel clock in KHz by ratio
1489 		 * [output pxlClk/input pxlClk] */
1490 		uint64_t pixel_clk_10_khz_out =
1491 				(uint64_t)le32_to_cpu(params.sOutput.ulDispPllFreq);
1492 		uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
1493 
1494 		if (pixel_clk_10_kHz_in != 0) {
1495 			bp_params->adjusted_pixel_clock =
1496 					div_u64(pixel_clk * pixel_clk_10_khz_out,
1497 							pixel_clk_10_kHz_in);
1498 		} else {
1499 			bp_params->adjusted_pixel_clock = 0;
1500 			BREAK_TO_DEBUGGER();
1501 		}
1502 
1503 		bp_params->reference_divider = params.sOutput.ucRefDiv;
1504 		bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv;
1505 
1506 		result = BP_RESULT_OK;
1507 	}
1508 
1509 	return result;
1510 }
1511 
1512 /*******************************************************************************
1513  ********************************************************************************
1514  **
1515  **                  DAC ENCODER CONTROL
1516  **
1517  ********************************************************************************
1518  *******************************************************************************/
1519 
1520 static enum bp_result dac1_encoder_control_v1(
1521 	struct bios_parser *bp,
1522 	bool enable,
1523 	uint32_t pixel_clock,
1524 	uint8_t dac_standard);
1525 static enum bp_result dac2_encoder_control_v1(
1526 	struct bios_parser *bp,
1527 	bool enable,
1528 	uint32_t pixel_clock,
1529 	uint8_t dac_standard);
1530 
1531 static void init_dac_encoder_control(struct bios_parser *bp)
1532 {
1533 	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) {
1534 	case 1:
1535 		bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1;
1536 		break;
1537 	default:
1538 		bp->cmd_tbl.dac1_encoder_control = NULL;
1539 		break;
1540 	}
1541 	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) {
1542 	case 1:
1543 		bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1;
1544 		break;
1545 	default:
1546 		bp->cmd_tbl.dac2_encoder_control = NULL;
1547 		break;
1548 	}
1549 }
1550 
1551 static void dac_encoder_control_prepare_params(
1552 	DAC_ENCODER_CONTROL_PS_ALLOCATION *params,
1553 	bool enable,
1554 	uint32_t pixel_clock,
1555 	uint8_t dac_standard)
1556 {
1557 	params->ucDacStandard = dac_standard;
1558 	if (enable)
1559 		params->ucAction = ATOM_ENABLE;
1560 	else
1561 		params->ucAction = ATOM_DISABLE;
1562 
1563 	/* We need to convert from KHz units into 10KHz units
1564 	 * it looks as if the TvControl do not care about pixel clock
1565 	 */
1566 	params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10));
1567 }
1568 
1569 static enum bp_result dac1_encoder_control_v1(
1570 	struct bios_parser *bp,
1571 	bool enable,
1572 	uint32_t pixel_clock,
1573 	uint8_t dac_standard)
1574 {
1575 	enum bp_result result = BP_RESULT_FAILURE;
1576 	DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1577 
1578 	dac_encoder_control_prepare_params(
1579 		&params,
1580 		enable,
1581 		pixel_clock,
1582 		dac_standard);
1583 
1584 	if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params))
1585 		result = BP_RESULT_OK;
1586 
1587 	return result;
1588 }
1589 
1590 static enum bp_result dac2_encoder_control_v1(
1591 	struct bios_parser *bp,
1592 	bool enable,
1593 	uint32_t pixel_clock,
1594 	uint8_t dac_standard)
1595 {
1596 	enum bp_result result = BP_RESULT_FAILURE;
1597 	DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1598 
1599 	dac_encoder_control_prepare_params(
1600 		&params,
1601 		enable,
1602 		pixel_clock,
1603 		dac_standard);
1604 
1605 	if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params))
1606 		result = BP_RESULT_OK;
1607 
1608 	return result;
1609 }
1610 
1611 /*******************************************************************************
1612  ********************************************************************************
1613  **
1614  **                  DAC OUTPUT CONTROL
1615  **
1616  ********************************************************************************
1617  *******************************************************************************/
1618 static enum bp_result dac1_output_control_v1(
1619 	struct bios_parser *bp,
1620 	bool enable);
1621 static enum bp_result dac2_output_control_v1(
1622 	struct bios_parser *bp,
1623 	bool enable);
1624 
1625 static void init_dac_output_control(struct bios_parser *bp)
1626 {
1627 	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) {
1628 	case 1:
1629 		bp->cmd_tbl.dac1_output_control = dac1_output_control_v1;
1630 		break;
1631 	default:
1632 		bp->cmd_tbl.dac1_output_control = NULL;
1633 		break;
1634 	}
1635 	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) {
1636 	case 1:
1637 		bp->cmd_tbl.dac2_output_control = dac2_output_control_v1;
1638 		break;
1639 	default:
1640 		bp->cmd_tbl.dac2_output_control = NULL;
1641 		break;
1642 	}
1643 }
1644 
1645 static enum bp_result dac1_output_control_v1(
1646 	struct bios_parser *bp, bool enable)
1647 {
1648 	enum bp_result result = BP_RESULT_FAILURE;
1649 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
1650 
1651 	if (enable)
1652 		params.ucAction = ATOM_ENABLE;
1653 	else
1654 		params.ucAction = ATOM_DISABLE;
1655 
1656 	if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params))
1657 		result = BP_RESULT_OK;
1658 
1659 	return result;
1660 }
1661 
1662 static enum bp_result dac2_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(DAC2OutputControl, params))
1674 		result = BP_RESULT_OK;
1675 
1676 	return result;
1677 }
1678 
1679 /*******************************************************************************
1680  ********************************************************************************
1681  **
1682  **                  SET CRTC TIMING
1683  **
1684  ********************************************************************************
1685  *******************************************************************************/
1686 
1687 static enum bp_result set_crtc_using_dtd_timing_v3(
1688 	struct bios_parser *bp,
1689 	struct bp_hw_crtc_timing_parameters *bp_params);
1690 static enum bp_result set_crtc_timing_v1(
1691 	struct bios_parser *bp,
1692 	struct bp_hw_crtc_timing_parameters *bp_params);
1693 
1694 static void init_set_crtc_timing(struct bios_parser *bp)
1695 {
1696 	uint32_t dtd_version =
1697 			BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming);
1698 	if (dtd_version > 2)
1699 		switch (dtd_version) {
1700 		case 3:
1701 			bp->cmd_tbl.set_crtc_timing =
1702 					set_crtc_using_dtd_timing_v3;
1703 			break;
1704 		default:
1705 			dm_output_to_console("Don't have set_crtc_timing for dtd v%d\n",
1706 				 dtd_version);
1707 			bp->cmd_tbl.set_crtc_timing = NULL;
1708 			break;
1709 		}
1710 	else
1711 		switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) {
1712 		case 1:
1713 			bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1;
1714 			break;
1715 		default:
1716 			dm_output_to_console("Don't have set_crtc_timing for v%d\n",
1717 				 BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing));
1718 			bp->cmd_tbl.set_crtc_timing = NULL;
1719 			break;
1720 		}
1721 }
1722 
1723 static enum bp_result set_crtc_timing_v1(
1724 	struct bios_parser *bp,
1725 	struct bp_hw_crtc_timing_parameters *bp_params)
1726 {
1727 	enum bp_result result = BP_RESULT_FAILURE;
1728 	SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0};
1729 	uint8_t atom_controller_id;
1730 
1731 	if (bp->cmd_helper->controller_id_to_atom(
1732 			bp_params->controller_id, &atom_controller_id))
1733 		params.ucCRTC = atom_controller_id;
1734 
1735 	params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total));
1736 	params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable));
1737 	params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start));
1738 	params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width));
1739 	params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total));
1740 	params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable));
1741 	params.usV_SyncStart =
1742 			cpu_to_le16((uint16_t)(bp_params->v_sync_start));
1743 	params.usV_SyncWidth =
1744 			cpu_to_le16((uint16_t)(bp_params->v_sync_width));
1745 
1746 	/* VBIOS does not expect any value except zero into this call, for
1747 	 * underscan use another entry ProgramOverscan call but when mode
1748 	 * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok,
1749 	 * but when same ,but 60 Hz there is corruption
1750 	 * DAL1 does not allow the mode 1776x1000@60
1751 	 */
1752 	params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right;
1753 	params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left;
1754 	params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom;
1755 	params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top;
1756 
1757 	if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
1758 		params.susModeMiscInfo.usAccess =
1759 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
1760 
1761 	if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
1762 		params.susModeMiscInfo.usAccess =
1763 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
1764 
1765 	if (bp_params->flags.INTERLACE) {
1766 		params.susModeMiscInfo.usAccess =
1767 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
1768 
1769 		/* original DAL code has this condition to apply tis for
1770 		 * non-TV/CV only due to complex MV testing for possible
1771 		 * impact
1772 		 * if (pACParameters->signal != SignalType_YPbPr &&
1773 		 *  pACParameters->signal != SignalType_Composite &&
1774 		 *  pACParameters->signal != SignalType_SVideo)
1775 		 */
1776 		/* HW will deduct 0.5 line from 2nd feild.
1777 		 * i.e. for 1080i, it is 2 lines for 1st field, 2.5
1778 		 * lines for the 2nd feild. we need input as 5 instead
1779 		 * of 4, but it is 4 either from Edid data
1780 		 * (spec CEA 861) or CEA timing table.
1781 		 */
1782 		params.usV_SyncStart =
1783 				cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1));
1784 	}
1785 
1786 	if (bp_params->flags.HORZ_COUNT_BY_TWO)
1787 		params.susModeMiscInfo.usAccess =
1788 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
1789 
1790 	if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params))
1791 		result = BP_RESULT_OK;
1792 
1793 	return result;
1794 }
1795 
1796 static enum bp_result set_crtc_using_dtd_timing_v3(
1797 	struct bios_parser *bp,
1798 	struct bp_hw_crtc_timing_parameters *bp_params)
1799 {
1800 	enum bp_result result = BP_RESULT_FAILURE;
1801 	SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0};
1802 	uint8_t atom_controller_id;
1803 
1804 	if (bp->cmd_helper->controller_id_to_atom(
1805 			bp_params->controller_id, &atom_controller_id))
1806 		params.ucCRTC = atom_controller_id;
1807 
1808 	/* bios usH_Size wants h addressable size */
1809 	params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable);
1810 	/* bios usH_Blanking_Time wants borders included in blanking */
1811 	params.usH_Blanking_Time =
1812 			cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable));
1813 	/* bios usV_Size wants v addressable size */
1814 	params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable);
1815 	/* bios usV_Blanking_Time wants borders included in blanking */
1816 	params.usV_Blanking_Time =
1817 			cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable));
1818 	/* bios usHSyncOffset is the offset from the end of h addressable,
1819 	 * our horizontalSyncStart is the offset from the beginning
1820 	 * of h addressable */
1821 	params.usH_SyncOffset =
1822 			cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable));
1823 	params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);
1824 	/* bios usHSyncOffset is the offset from the end of v addressable,
1825 	 * our verticalSyncStart is the offset from the beginning of
1826 	 * v addressable */
1827 	params.usV_SyncOffset =
1828 			cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable));
1829 	params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);
1830 
1831 	/* we assume that overscan from original timing does not get bigger
1832 	 * than 255
1833 	 * we will program all the borders in the Set CRTC Overscan call below
1834 	 */
1835 
1836 	if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
1837 		params.susModeMiscInfo.usAccess =
1838 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
1839 
1840 	if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
1841 		params.susModeMiscInfo.usAccess =
1842 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
1843 
1844 	if (bp_params->flags.INTERLACE)	{
1845 		params.susModeMiscInfo.usAccess =
1846 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
1847 
1848 		/* original DAL code has this condition to apply this
1849 		 * for non-TV/CV only
1850 		 * due to complex MV testing for possible impact
1851 		 * if ( pACParameters->signal != SignalType_YPbPr &&
1852 		 *  pACParameters->signal != SignalType_Composite &&
1853 		 *  pACParameters->signal != SignalType_SVideo)
1854 		 */
1855 		{
1856 			/* HW will deduct 0.5 line from 2nd feild.
1857 			 * i.e. for 1080i, it is 2 lines for 1st field,
1858 			 * 2.5 lines for the 2nd feild. we need input as 5
1859 			 * instead of 4.
1860 			 * but it is 4 either from Edid data (spec CEA 861)
1861 			 * or CEA timing table.
1862 			 */
1863 			params.usV_SyncOffset =
1864 					cpu_to_le16(le16_to_cpu(params.usV_SyncOffset) + 1);
1865 
1866 		}
1867 	}
1868 
1869 	if (bp_params->flags.HORZ_COUNT_BY_TWO)
1870 		params.susModeMiscInfo.usAccess =
1871 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
1872 
1873 	if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params))
1874 		result = BP_RESULT_OK;
1875 
1876 	return result;
1877 }
1878 
1879 /*******************************************************************************
1880  ********************************************************************************
1881  **
1882  **                  SELECT CRTC SOURCE
1883  **
1884  ********************************************************************************
1885  *******************************************************************************/
1886 
1887 static enum bp_result select_crtc_source_v2(
1888 	struct bios_parser *bp,
1889 	struct bp_crtc_source_select *bp_params);
1890 static enum bp_result select_crtc_source_v3(
1891 	struct bios_parser *bp,
1892 	struct bp_crtc_source_select *bp_params);
1893 
1894 static void init_select_crtc_source(struct bios_parser *bp)
1895 {
1896 	switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) {
1897 	case 2:
1898 		bp->cmd_tbl.select_crtc_source = select_crtc_source_v2;
1899 		break;
1900 	case 3:
1901 		bp->cmd_tbl.select_crtc_source = select_crtc_source_v3;
1902 		break;
1903 	default:
1904 		dm_output_to_console("Don't select_crtc_source enable_crtc for v%d\n",
1905 			 BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source));
1906 		bp->cmd_tbl.select_crtc_source = NULL;
1907 		break;
1908 	}
1909 }
1910 
1911 static enum bp_result select_crtc_source_v2(
1912 	struct bios_parser *bp,
1913 	struct bp_crtc_source_select *bp_params)
1914 {
1915 	enum bp_result result = BP_RESULT_FAILURE;
1916 	SELECT_CRTC_SOURCE_PARAMETERS_V2 params;
1917 	uint8_t atom_controller_id;
1918 	uint32_t atom_engine_id;
1919 	enum signal_type s = bp_params->signal;
1920 
1921 	memset(&params, 0, sizeof(params));
1922 
1923 	/* set controller id */
1924 	if (bp->cmd_helper->controller_id_to_atom(
1925 			bp_params->controller_id, &atom_controller_id))
1926 		params.ucCRTC = atom_controller_id;
1927 	else
1928 		return BP_RESULT_FAILURE;
1929 
1930 	/* set encoder id */
1931 	if (bp->cmd_helper->engine_bp_to_atom(
1932 			bp_params->engine_id, &atom_engine_id))
1933 		params.ucEncoderID = (uint8_t)atom_engine_id;
1934 	else
1935 		return BP_RESULT_FAILURE;
1936 
1937 	if (SIGNAL_TYPE_EDP == s ||
1938 			(SIGNAL_TYPE_DISPLAY_PORT == s &&
1939 					SIGNAL_TYPE_LVDS == bp_params->sink_signal))
1940 		s = SIGNAL_TYPE_LVDS;
1941 
1942 	params.ucEncodeMode =
1943 			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1944 					s, bp_params->enable_dp_audio);
1945 
1946 	if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
1947 		result = BP_RESULT_OK;
1948 
1949 	return result;
1950 }
1951 
1952 static enum bp_result select_crtc_source_v3(
1953 	struct bios_parser *bp,
1954 	struct bp_crtc_source_select *bp_params)
1955 {
1956 	bool result = BP_RESULT_FAILURE;
1957 	SELECT_CRTC_SOURCE_PARAMETERS_V3 params;
1958 	uint8_t atom_controller_id;
1959 	uint32_t atom_engine_id;
1960 	enum signal_type s = bp_params->signal;
1961 
1962 	memset(&params, 0, sizeof(params));
1963 
1964 	if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
1965 			&atom_controller_id))
1966 		params.ucCRTC = atom_controller_id;
1967 	else
1968 		return result;
1969 
1970 	if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id,
1971 			&atom_engine_id))
1972 		params.ucEncoderID = (uint8_t)atom_engine_id;
1973 	else
1974 		return result;
1975 
1976 	if (SIGNAL_TYPE_EDP == s ||
1977 			(SIGNAL_TYPE_DISPLAY_PORT == s &&
1978 					SIGNAL_TYPE_LVDS == bp_params->sink_signal))
1979 		s = SIGNAL_TYPE_LVDS;
1980 
1981 	params.ucEncodeMode =
1982 			bp->cmd_helper->encoder_mode_bp_to_atom(
1983 					s, bp_params->enable_dp_audio);
1984 	/* Needed for VBIOS Random Spatial Dithering feature */
1985 	params.ucDstBpc = (uint8_t)(bp_params->display_output_bit_depth);
1986 
1987 	if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
1988 		result = BP_RESULT_OK;
1989 
1990 	return result;
1991 }
1992 
1993 /*******************************************************************************
1994  ********************************************************************************
1995  **
1996  **                  ENABLE CRTC
1997  **
1998  ********************************************************************************
1999  *******************************************************************************/
2000 
2001 static enum bp_result enable_crtc_v1(
2002 	struct bios_parser *bp,
2003 	enum controller_id controller_id,
2004 	bool enable);
2005 
2006 static void init_enable_crtc(struct bios_parser *bp)
2007 {
2008 	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) {
2009 	case 1:
2010 		bp->cmd_tbl.enable_crtc = enable_crtc_v1;
2011 		break;
2012 	default:
2013 		dm_output_to_console("Don't have enable_crtc for v%d\n",
2014 			 BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC));
2015 		bp->cmd_tbl.enable_crtc = NULL;
2016 		break;
2017 	}
2018 }
2019 
2020 static enum bp_result enable_crtc_v1(
2021 	struct bios_parser *bp,
2022 	enum controller_id controller_id,
2023 	bool enable)
2024 {
2025 	bool result = BP_RESULT_FAILURE;
2026 	ENABLE_CRTC_PARAMETERS params = {0};
2027 	uint8_t id;
2028 
2029 	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))
2030 		params.ucCRTC = id;
2031 	else
2032 		return BP_RESULT_BADINPUT;
2033 
2034 	if (enable)
2035 		params.ucEnable = ATOM_ENABLE;
2036 	else
2037 		params.ucEnable = ATOM_DISABLE;
2038 
2039 	if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params))
2040 		result = BP_RESULT_OK;
2041 
2042 	return result;
2043 }
2044 
2045 /*******************************************************************************
2046  ********************************************************************************
2047  **
2048  **                  ENABLE CRTC MEM REQ
2049  **
2050  ********************************************************************************
2051  *******************************************************************************/
2052 
2053 static enum bp_result enable_crtc_mem_req_v1(
2054 	struct bios_parser *bp,
2055 	enum controller_id controller_id,
2056 	bool enable);
2057 
2058 static void init_enable_crtc_mem_req(struct bios_parser *bp)
2059 {
2060 	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) {
2061 	case 1:
2062 		bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1;
2063 		break;
2064 	default:
2065 		bp->cmd_tbl.enable_crtc_mem_req = NULL;
2066 		break;
2067 	}
2068 }
2069 
2070 static enum bp_result enable_crtc_mem_req_v1(
2071 	struct bios_parser *bp,
2072 	enum controller_id controller_id,
2073 	bool enable)
2074 {
2075 	bool result = BP_RESULT_BADINPUT;
2076 	ENABLE_CRTC_PARAMETERS params = {0};
2077 	uint8_t id;
2078 
2079 	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) {
2080 		params.ucCRTC = id;
2081 
2082 		if (enable)
2083 			params.ucEnable = ATOM_ENABLE;
2084 		else
2085 			params.ucEnable = ATOM_DISABLE;
2086 
2087 		if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params))
2088 			result = BP_RESULT_OK;
2089 		else
2090 			result = BP_RESULT_FAILURE;
2091 	}
2092 
2093 	return result;
2094 }
2095 
2096 /*******************************************************************************
2097  ********************************************************************************
2098  **
2099  **                  DISPLAY PLL
2100  **
2101  ********************************************************************************
2102  *******************************************************************************/
2103 
2104 static enum bp_result program_clock_v5(
2105 	struct bios_parser *bp,
2106 	struct bp_pixel_clock_parameters *bp_params);
2107 static enum bp_result program_clock_v6(
2108 	struct bios_parser *bp,
2109 	struct bp_pixel_clock_parameters *bp_params);
2110 
2111 static void init_program_clock(struct bios_parser *bp)
2112 {
2113 	switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
2114 	case 5:
2115 		bp->cmd_tbl.program_clock = program_clock_v5;
2116 		break;
2117 	case 6:
2118 		bp->cmd_tbl.program_clock = program_clock_v6;
2119 		break;
2120 	default:
2121 		dm_output_to_console("Don't have program_clock for v%d\n",
2122 			 BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
2123 		bp->cmd_tbl.program_clock = NULL;
2124 		break;
2125 	}
2126 }
2127 
2128 static enum bp_result program_clock_v5(
2129 	struct bios_parser *bp,
2130 	struct bp_pixel_clock_parameters *bp_params)
2131 {
2132 	enum bp_result result = BP_RESULT_FAILURE;
2133 
2134 	SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params;
2135 	uint32_t atom_pll_id;
2136 
2137 	memset(&params, 0, sizeof(params));
2138 	if (!bp->cmd_helper->clock_source_id_to_atom(
2139 			bp_params->pll_id, &atom_pll_id)) {
2140 		BREAK_TO_DEBUGGER(); /* Invalid Inpute!! */
2141 		return BP_RESULT_BADINPUT;
2142 	}
2143 
2144 	/* We need to convert from KHz units into 10KHz units */
2145 	params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id;
2146 	params.sPCLKInput.usPixelClock =
2147 			cpu_to_le16((uint16_t) (bp_params->target_pixel_clock / 10));
2148 	params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID;
2149 
2150 	if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2151 		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2152 
2153 	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params))
2154 		result = BP_RESULT_OK;
2155 
2156 	return result;
2157 }
2158 
2159 static enum bp_result program_clock_v6(
2160 	struct bios_parser *bp,
2161 	struct bp_pixel_clock_parameters *bp_params)
2162 {
2163 	enum bp_result result = BP_RESULT_FAILURE;
2164 
2165 	SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params;
2166 	uint32_t atom_pll_id;
2167 
2168 	memset(&params, 0, sizeof(params));
2169 
2170 	if (!bp->cmd_helper->clock_source_id_to_atom(
2171 			bp_params->pll_id, &atom_pll_id)) {
2172 		BREAK_TO_DEBUGGER(); /*Invalid Input!!*/
2173 		return BP_RESULT_BADINPUT;
2174 	}
2175 
2176 	/* We need to convert from KHz units into 10KHz units */
2177 	params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id;
2178 	params.sPCLKInput.ulDispEngClkFreq =
2179 			cpu_to_le32(bp_params->target_pixel_clock / 10);
2180 
2181 	if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2182 		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2183 
2184 	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) {
2185 		/* True display clock is returned by VBIOS if DFS bypass
2186 		 * is enabled. */
2187 		bp_params->dfs_bypass_display_clock =
2188 				(uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10);
2189 		result = BP_RESULT_OK;
2190 	}
2191 
2192 	return result;
2193 }
2194 
2195 /*******************************************************************************
2196  ********************************************************************************
2197  **
2198  **                  EXTERNAL ENCODER CONTROL
2199  **
2200  ********************************************************************************
2201  *******************************************************************************/
2202 
2203 static enum bp_result external_encoder_control_v3(
2204 	struct bios_parser *bp,
2205 	struct bp_external_encoder_control *cntl);
2206 
2207 static void init_external_encoder_control(
2208 	struct bios_parser *bp)
2209 {
2210 	switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) {
2211 	case 3:
2212 		bp->cmd_tbl.external_encoder_control =
2213 				external_encoder_control_v3;
2214 		break;
2215 	default:
2216 		bp->cmd_tbl.external_encoder_control = NULL;
2217 		break;
2218 	}
2219 }
2220 
2221 static enum bp_result external_encoder_control_v3(
2222 	struct bios_parser *bp,
2223 	struct bp_external_encoder_control *cntl)
2224 {
2225 	enum bp_result result = BP_RESULT_FAILURE;
2226 
2227 	/* we need use _PS_Alloc struct */
2228 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 params;
2229 	EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 *cntl_params;
2230 	struct graphics_object_id encoder;
2231 	bool is_input_signal_dp = false;
2232 
2233 	memset(&params, 0, sizeof(params));
2234 
2235 	cntl_params = &params.sExtEncoder;
2236 
2237 	encoder = cntl->encoder_id;
2238 
2239 	/* check if encoder supports external encoder control table */
2240 	switch (dal_graphics_object_id_get_encoder_id(encoder)) {
2241 	case ENCODER_ID_EXTERNAL_NUTMEG:
2242 	case ENCODER_ID_EXTERNAL_TRAVIS:
2243 		is_input_signal_dp = true;
2244 		break;
2245 
2246 	default:
2247 		BREAK_TO_DEBUGGER();
2248 		return BP_RESULT_BADINPUT;
2249 	}
2250 
2251 	/* Fill information based on the action
2252 	 *
2253 	 * Bit[6:4]: indicate external encoder, applied to all functions.
2254 	 * =0: external encoder1, mapped to external encoder enum id1
2255 	 * =1: external encoder2, mapped to external encoder enum id2
2256 	 *
2257 	 * enum ObjectEnumId
2258 	 * {
2259 	 *  EnumId_Unknown = 0,
2260 	 *  EnumId_1,
2261 	 *  EnumId_2,
2262 	 * };
2263 	 */
2264 	cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4);
2265 
2266 	switch (cntl->action) {
2267 	case EXTERNAL_ENCODER_CONTROL_INIT:
2268 		/* output display connector type. Only valid in encoder
2269 		 * initialization */
2270 		cntl_params->usConnectorId =
2271 				cpu_to_le16((uint16_t)cntl->connector_obj_id.id);
2272 		break;
2273 	case EXTERNAL_ENCODER_CONTROL_SETUP:
2274 		/* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in
2275 		 * 10KHz
2276 		 * output display device pixel clock frequency in unit of 10KHz.
2277 		 * Only valid in setup and enableoutput
2278 		 */
2279 		cntl_params->usPixelClock =
2280 				cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2281 		/* Indicate display output signal type drive by external
2282 		 * encoder, only valid in setup and enableoutput */
2283 		cntl_params->ucEncoderMode =
2284 				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2285 						cntl->signal, false);
2286 
2287 		if (is_input_signal_dp) {
2288 			/* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz,
2289 			 * only valid in encoder setup with DP mode. */
2290 			if (LINK_RATE_HIGH == cntl->link_rate)
2291 				cntl_params->ucConfig |= 1;
2292 			/* output color depth Indicate encoder data bpc format
2293 			 * in DP mode, only valid in encoder setup in DP mode.
2294 			 */
2295 			cntl_params->ucBitPerColor =
2296 					(uint8_t)(cntl->color_depth);
2297 		}
2298 		/* Indicate how many lanes used by external encoder, only valid
2299 		 * in encoder setup and enableoutput. */
2300 		cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);
2301 		break;
2302 	case EXTERNAL_ENCODER_CONTROL_ENABLE:
2303 		cntl_params->usPixelClock =
2304 				cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2305 		cntl_params->ucEncoderMode =
2306 				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2307 						cntl->signal, false);
2308 		cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number;
2309 		break;
2310 	default:
2311 		break;
2312 	}
2313 
2314 	cntl_params->ucAction = (uint8_t)cntl->action;
2315 
2316 	if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params))
2317 		result = BP_RESULT_OK;
2318 
2319 	return result;
2320 }
2321 
2322 /*******************************************************************************
2323  ********************************************************************************
2324  **
2325  **                  ENABLE DISPLAY POWER GATING
2326  **
2327  ********************************************************************************
2328  *******************************************************************************/
2329 
2330 static enum bp_result enable_disp_power_gating_v2_1(
2331 	struct bios_parser *bp,
2332 	enum controller_id crtc_id,
2333 	enum bp_pipe_control_action action);
2334 
2335 static void init_enable_disp_power_gating(
2336 	struct bios_parser *bp)
2337 {
2338 	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) {
2339 	case 1:
2340 		bp->cmd_tbl.enable_disp_power_gating =
2341 				enable_disp_power_gating_v2_1;
2342 		break;
2343 	default:
2344 		dm_output_to_console("Don't enable_disp_power_gating enable_crtc for v%d\n",
2345 			 BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating));
2346 		bp->cmd_tbl.enable_disp_power_gating = NULL;
2347 		break;
2348 	}
2349 }
2350 
2351 static enum bp_result enable_disp_power_gating_v2_1(
2352 	struct bios_parser *bp,
2353 	enum controller_id crtc_id,
2354 	enum bp_pipe_control_action action)
2355 {
2356 	enum bp_result result = BP_RESULT_FAILURE;
2357 
2358 	ENABLE_DISP_POWER_GATING_PS_ALLOCATION params = {0};
2359 	uint8_t atom_crtc_id;
2360 
2361 	if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))
2362 		params.ucDispPipeId = atom_crtc_id;
2363 	else
2364 		return BP_RESULT_BADINPUT;
2365 
2366 	params.ucEnable =
2367 			bp->cmd_helper->disp_power_gating_action_to_atom(action);
2368 
2369 	if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params))
2370 		result = BP_RESULT_OK;
2371 
2372 	return result;
2373 }
2374 
2375 /*******************************************************************************
2376  ********************************************************************************
2377  **
2378  **                  SET DCE CLOCK
2379  **
2380  ********************************************************************************
2381  *******************************************************************************/
2382 static enum bp_result set_dce_clock_v2_1(
2383 	struct bios_parser *bp,
2384 	struct bp_set_dce_clock_parameters *bp_params);
2385 
2386 static void init_set_dce_clock(struct bios_parser *bp)
2387 {
2388 	switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) {
2389 	case 1:
2390 		bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
2391 		break;
2392 	default:
2393 		dm_output_to_console("Don't have set_dce_clock for v%d\n",
2394 			 BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock));
2395 		bp->cmd_tbl.set_dce_clock = NULL;
2396 		break;
2397 	}
2398 }
2399 
2400 static enum bp_result set_dce_clock_v2_1(
2401 	struct bios_parser *bp,
2402 	struct bp_set_dce_clock_parameters *bp_params)
2403 {
2404 	enum bp_result result = BP_RESULT_FAILURE;
2405 
2406 	SET_DCE_CLOCK_PS_ALLOCATION_V2_1 params;
2407 	uint32_t atom_pll_id;
2408 	uint32_t atom_clock_type;
2409 	const struct command_table_helper *cmd = bp->cmd_helper;
2410 
2411 	memset(&params, 0, sizeof(params));
2412 
2413 	if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||
2414 			!cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type))
2415 		return BP_RESULT_BADINPUT;
2416 
2417 	params.asParam.ucDCEClkSrc  = atom_pll_id;
2418 	params.asParam.ucDCEClkType = atom_clock_type;
2419 
2420 	if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {
2421 		if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)
2422 			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;
2423 
2424 		if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)
2425 			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;
2426 
2427 		if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)
2428 			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;
2429 
2430 		if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)
2431 			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;
2432 	}
2433 	else
2434 		/* only program clock frequency if display clock is used; VBIOS will program DPREFCLK */
2435 		/* We need to convert from KHz units into 10KHz units */
2436 		params.asParam.ulDCEClkFreq = cpu_to_le32(bp_params->target_clock_frequency / 10);
2437 
2438 	if (EXEC_BIOS_CMD_TABLE(SetDCEClock, params)) {
2439 		/* Convert from 10KHz units back to KHz */
2440 		bp_params->target_clock_frequency = le32_to_cpu(params.asParam.ulDCEClkFreq) * 10;
2441 		result = BP_RESULT_OK;
2442 	}
2443 
2444 	return result;
2445 }
2446