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