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