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