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