2 * Copyright 2012-15 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 #include "dm_services.h"
30 #include "include/bios_parser_interface.h"
32 #include "command_table.h"
33 #include "command_table_helper.h"
34 #include "bios_parser_helper.h"
35 #include "bios_parser_types_internal.h"
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 *)¶ms) == 0)
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)
46 #define BIOS_CMD_TABLE_PARA_REVISION(command)\
47 bios_cmd_table_para_revision(bp->base.ctx->driver_context, \
48 GetIndexIntoMasterTable(COMMAND, command))
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);
65 void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
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);
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);
83 static uint32_t bios_cmd_table_para_revision(void *dev,
86 struct amdgpu_device *adev = dev;
89 if (amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context,
97 /*******************************************************************************
98 ********************************************************************************
100 ** D I G E N C O D E R C O N T R O L
102 ********************************************************************************
103 *******************************************************************************/
104 static enum bp_result encoder_control_digx_v3(
105 struct bios_parser *bp,
106 struct bp_encoder_control *cntl);
108 static enum bp_result encoder_control_digx_v4(
109 struct bios_parser *bp,
110 struct bp_encoder_control *cntl);
112 static enum bp_result encoder_control_digx_v5(
113 struct bios_parser *bp,
114 struct bp_encoder_control *cntl);
116 static void init_encoder_control_dig_v1(struct bios_parser *bp);
118 static void init_dig_encoder_control(struct bios_parser *bp)
121 BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl);
125 bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3;
128 bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4;
132 bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5;
136 init_encoder_control_dig_v1(bp);
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);
151 static void init_encoder_control_dig_v1(struct bios_parser *bp)
153 struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
155 if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl))
156 cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1;
158 cmd_tbl->encoder_control_dig1 = NULL;
160 if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl))
161 cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1;
163 cmd_tbl->encoder_control_dig2 = NULL;
165 cmd_tbl->dig_encoder_control = encoder_control_dig_v1;
168 static enum bp_result encoder_control_dig_v1(
169 struct bios_parser *bp,
170 struct bp_encoder_control *cntl)
172 enum bp_result result = BP_RESULT_FAILURE;
173 struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
176 switch (cntl->engine_id) {
178 if (cmd_tbl->encoder_control_dig1 != NULL)
180 cmd_tbl->encoder_control_dig1(bp, cntl);
183 if (cmd_tbl->encoder_control_dig2 != NULL)
185 cmd_tbl->encoder_control_dig2(bp, cntl);
195 static enum bp_result encoder_control_dig1_v1(
196 struct bios_parser *bp,
197 struct bp_encoder_control *cntl)
199 enum bp_result result = BP_RESULT_FAILURE;
200 DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
202 bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms);
204 if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params))
205 result = BP_RESULT_OK;
210 static enum bp_result encoder_control_dig2_v1(
211 struct bios_parser *bp,
212 struct bp_encoder_control *cntl)
214 enum bp_result result = BP_RESULT_FAILURE;
215 DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
217 bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms);
219 if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params))
220 result = BP_RESULT_OK;
225 static enum bp_result encoder_control_digx_v3(
226 struct bios_parser *bp,
227 struct bp_encoder_control *cntl)
229 enum bp_result result = BP_RESULT_FAILURE;
230 DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0};
232 if (LANE_COUNT_FOUR < cntl->lanes_number)
233 params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
235 params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
237 params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
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(
245 cntl->enable_dp_audio);
246 params.ucLaneNum = (uint8_t)(cntl->lanes_number);
248 switch (cntl->color_depth) {
249 case COLOR_DEPTH_888:
250 params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
252 case COLOR_DEPTH_101010:
253 params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
255 case COLOR_DEPTH_121212:
256 params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
258 case COLOR_DEPTH_161616:
259 params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
265 if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
266 result = BP_RESULT_OK;
271 static enum bp_result encoder_control_digx_v4(
272 struct bios_parser *bp,
273 struct bp_encoder_control *cntl)
275 enum bp_result result = BP_RESULT_FAILURE;
276 DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0};
278 if (LANE_COUNT_FOUR < cntl->lanes_number)
279 params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
281 params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
283 params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
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(
291 cntl->enable_dp_audio));
292 params.ucLaneNum = (uint8_t)(cntl->lanes_number);
294 switch (cntl->color_depth) {
295 case COLOR_DEPTH_888:
296 params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
298 case COLOR_DEPTH_101010:
299 params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
301 case COLOR_DEPTH_121212:
302 params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
304 case COLOR_DEPTH_161616:
305 params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
311 if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
312 result = BP_RESULT_OK;
317 static enum bp_result encoder_control_digx_v5(
318 struct bios_parser *bp,
319 struct bp_encoder_control *cntl)
321 enum bp_result result = BP_RESULT_FAILURE;
322 ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0};
324 params.ucDigId = (uint8_t)(cntl->engine_id);
325 params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
327 params.ulPixelClock = cntl->pixel_clock / 10;
329 (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
331 cntl->enable_dp_audio));
332 params.ucLaneNum = (uint8_t)(cntl->lanes_number);
334 switch (cntl->color_depth) {
335 case COLOR_DEPTH_888:
336 params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
338 case COLOR_DEPTH_101010:
339 params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
341 case COLOR_DEPTH_121212:
342 params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
344 case COLOR_DEPTH_161616:
345 params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
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;
357 case COLOR_DEPTH_121212:
358 params.ulPixelClock =
359 (params.ulPixelClock * 36) / 24;
361 case COLOR_DEPTH_161616:
362 params.ulPixelClock =
363 (params.ulPixelClock * 48) / 24;
369 if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
370 result = BP_RESULT_OK;
375 /*******************************************************************************
376 ********************************************************************************
378 ** TRANSMITTER CONTROL
380 ********************************************************************************
381 *******************************************************************************/
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);
399 static void init_transmitter_control(struct bios_parser *bp)
404 if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl,
405 frev, crev) == false)
409 bp->cmd_tbl.transmitter_control = transmitter_control_v2;
412 bp->cmd_tbl.transmitter_control = transmitter_control_v3;
415 bp->cmd_tbl.transmitter_control = transmitter_control_v4;
418 bp->cmd_tbl.transmitter_control = transmitter_control_v1_5;
421 bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;
424 dm_output_to_console("Don't have transmitter_control for v%d\n", crev);
425 bp->cmd_tbl.transmitter_control = NULL;
430 static enum bp_result transmitter_control_v2(
431 struct bios_parser *bp,
432 struct bp_transmitter_control *cntl)
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);
439 memset(¶ms, 0, sizeof(params));
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:
451 return BP_RESULT_BADINPUT;
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
460 * Bit0: dual link connector flag
461 * =0 connector is single link connector
462 * =1 connector is dual link connector
464 params.acConfig.fDualLinkConnector = 1;
466 /* connector object id */
468 cpu_to_le16((uint8_t)cntl->connector_obj_id.id);
470 case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
471 /* voltage swing and pre-emphsis */
472 params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
473 params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
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
484 params.acConfig.fDualLinkConnector = 1;
486 /* link rate, half for dual link
487 * We need to convert from KHz units into 20KHz units
489 params.usPixelClock =
490 cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
492 /* link rate, half for dual link
493 * We need to convert from KHz units into 10KHz units
495 params.usPixelClock =
496 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
500 /* 00 - coherent mode
501 * 01 - incoherent mode
504 params.acConfig.fCoherentMode = cntl->coherent;
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,
512 * =1 when bit0=0, single link B/D/F, when bit0=1,
515 params.acConfig.ucLinkSel = 1;
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
523 params.acConfig.ucEncoderSel = 1;
525 if (CONNECTOR_ID_DISPLAY_PORT == connector_id ||
526 CONNECTOR_ID_USBC == connector_id)
527 /* Bit4: DP connector flag
528 * =0 connector is none-DP connector
529 * =1 connector is DP connector
531 params.acConfig.fDPConnector = 1;
533 /* Bit[7:6]: Transmitter selection
534 * =0 UNIPHY_ENCODER: UNIPHYA/B
535 * =1 UNIPHY1_ENCODER: UNIPHYC/D
536 * =2 UNIPHY2_ENCODER: UNIPHYE/F
539 params.acConfig.ucTransmitterSel =
540 (uint8_t)bp->cmd_helper->transmitter_bp_to_atom(
543 params.ucAction = (uint8_t)cntl->action;
545 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
546 result = BP_RESULT_OK;
551 static enum bp_result transmitter_control_v3(
552 struct bios_parser *bp,
553 struct bp_transmitter_control *cntl)
555 enum bp_result result = BP_RESULT_FAILURE;
556 DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 params;
558 enum connector_id conn_id =
559 dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
560 const struct command_table_helper *cmd = bp->cmd_helper;
561 bool dual_link_conn = (CONNECTOR_ID_DUAL_LINK_DVII == conn_id)
562 || (CONNECTOR_ID_DUAL_LINK_DVID == conn_id);
564 memset(¶ms, 0, sizeof(params));
566 switch (cntl->transmitter) {
567 case TRANSMITTER_UNIPHY_A:
568 case TRANSMITTER_UNIPHY_B:
569 case TRANSMITTER_UNIPHY_C:
570 case TRANSMITTER_UNIPHY_D:
571 case TRANSMITTER_UNIPHY_E:
572 case TRANSMITTER_UNIPHY_F:
573 case TRANSMITTER_TRAVIS_LCD:
576 return BP_RESULT_BADINPUT;
579 if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id))
580 return BP_RESULT_BADINPUT;
582 /* fill information based on the action */
583 switch (cntl->action) {
584 case TRANSMITTER_CONTROL_INIT:
585 if (dual_link_conn) {
586 /* on INIT this bit should be set according to the
588 * Bit0: dual link connector flag
589 * =0 connector is single link connector
590 * =1 connector is dual link connector
592 params.acConfig.fDualLinkConnector = 1;
595 /* connector object id */
597 cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
599 case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
600 /* votage swing and pre-emphsis */
601 params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
602 params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
605 if (dual_link_conn && cntl->multi_path)
606 /* on ENABLE/DISABLE this bit should be set according to
607 * actual timing (number of lanes)
608 * Bit0: dual link connector flag
609 * =0 connector is single link connector
610 * =1 connector is dual link connector
612 params.acConfig.fDualLinkConnector = 1;
615 if (LANE_COUNT_FOUR < cntl->lanes_number) {
616 /* on ENABLE/DISABLE this bit should be set according to
617 * actual timing (number of lanes)
618 * Bit0: dual link connector flag
619 * =0 connector is single link connector
620 * =1 connector is dual link connector
622 params.acConfig.fDualLinkConnector = 1;
624 /* link rate, half for dual link
625 * We need to convert from KHz units into 20KHz units
627 params.usPixelClock =
628 cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
630 /* link rate, half for dual link
631 * We need to convert from KHz units into 10KHz units
633 params.usPixelClock =
634 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
639 /* 00 - coherent mode
640 * 01 - incoherent mode
643 params.acConfig.fCoherentMode = cntl->coherent;
645 if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
646 || (TRANSMITTER_UNIPHY_D == cntl->transmitter)
647 || (TRANSMITTER_UNIPHY_F == cntl->transmitter))
648 /* Bit2: Transmitter Link selection
649 * =0 when bit0=0, single link A/C/E, when bit0=1,
651 * =1 when bit0=0, single link B/D/F, when bit0=1,
654 params.acConfig.ucLinkSel = 1;
656 if (ENGINE_ID_DIGB == cntl->engine_id)
657 /* Bit3: Transmitter data source selection
658 * =0 DIGA is data source.
659 * =1 DIGB is data source.
660 * This bit is only useful when ucAction= ATOM_ENABLE
662 params.acConfig.ucEncoderSel = 1;
664 /* Bit[7:6]: Transmitter selection
665 * =0 UNIPHY_ENCODER: UNIPHYA/B
666 * =1 UNIPHY1_ENCODER: UNIPHYC/D
667 * =2 UNIPHY2_ENCODER: UNIPHYE/F
670 params.acConfig.ucTransmitterSel =
671 (uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter);
673 params.ucLaneNum = (uint8_t)cntl->lanes_number;
675 params.acConfig.ucRefClkSource = (uint8_t)pll_id;
677 params.ucAction = (uint8_t)cntl->action;
679 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
680 result = BP_RESULT_OK;
685 static enum bp_result transmitter_control_v4(
686 struct bios_parser *bp,
687 struct bp_transmitter_control *cntl)
689 enum bp_result result = BP_RESULT_FAILURE;
690 DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 params;
691 uint32_t ref_clk_src_id;
692 enum connector_id conn_id =
693 dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
694 const struct command_table_helper *cmd = bp->cmd_helper;
696 memset(¶ms, 0, sizeof(params));
698 switch (cntl->transmitter) {
699 case TRANSMITTER_UNIPHY_A:
700 case TRANSMITTER_UNIPHY_B:
701 case TRANSMITTER_UNIPHY_C:
702 case TRANSMITTER_UNIPHY_D:
703 case TRANSMITTER_UNIPHY_E:
704 case TRANSMITTER_UNIPHY_F:
705 case TRANSMITTER_TRAVIS_LCD:
708 return BP_RESULT_BADINPUT;
711 if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id))
712 return BP_RESULT_BADINPUT;
714 switch (cntl->action) {
715 case TRANSMITTER_CONTROL_INIT:
717 if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
718 (CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
719 /* on INIT this bit should be set according to the
721 * Bit0: dual link connector flag
722 * =0 connector is single link connector
723 * =1 connector is dual link connector
725 params.acConfig.fDualLinkConnector = 1;
727 /* connector object id */
729 cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
732 case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
733 /* votage swing and pre-emphsis */
734 params.asMode.ucLaneSel = (uint8_t)(cntl->lane_select);
735 params.asMode.ucLaneSet = (uint8_t)(cntl->lane_settings);
738 if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
739 (CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
740 /* on ENABLE/DISABLE this bit should be set according to
741 * actual timing (number of lanes)
742 * Bit0: dual link connector flag
743 * =0 connector is single link connector
744 * =1 connector is dual link connector
746 params.acConfig.fDualLinkConnector = 1;
749 if (LANE_COUNT_FOUR < cntl->lanes_number)
750 /* link rate, half for dual link
751 * We need to convert from KHz units into 20KHz units
753 params.usPixelClock =
754 cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
756 /* link rate, half for dual link
757 * We need to convert from KHz units into 10KHz units
759 params.usPixelClock =
760 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
765 /* 00 - coherent mode
766 * 01 - incoherent mode
769 params.acConfig.fCoherentMode = cntl->coherent;
771 if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
772 || (TRANSMITTER_UNIPHY_D == cntl->transmitter)
773 || (TRANSMITTER_UNIPHY_F == cntl->transmitter))
774 /* Bit2: Transmitter Link selection
775 * =0 when bit0=0, single link A/C/E, when bit0=1,
777 * =1 when bit0=0, single link B/D/F, when bit0=1,
780 params.acConfig.ucLinkSel = 1;
782 if (ENGINE_ID_DIGB == cntl->engine_id)
783 /* Bit3: Transmitter data source selection
784 * =0 DIGA is data source.
785 * =1 DIGB is data source.
786 * This bit is only useful when ucAction= ATOM_ENABLE
788 params.acConfig.ucEncoderSel = 1;
790 /* Bit[7:6]: Transmitter selection
791 * =0 UNIPHY_ENCODER: UNIPHYA/B
792 * =1 UNIPHY1_ENCODER: UNIPHYC/D
793 * =2 UNIPHY2_ENCODER: UNIPHYE/F
796 params.acConfig.ucTransmitterSel =
797 (uint8_t)(cmd->transmitter_bp_to_atom(cntl->transmitter));
798 params.ucLaneNum = (uint8_t)(cntl->lanes_number);
799 params.acConfig.ucRefClkSource = (uint8_t)(ref_clk_src_id);
800 params.ucAction = (uint8_t)(cntl->action);
802 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
803 result = BP_RESULT_OK;
808 static enum bp_result transmitter_control_v1_5(
809 struct bios_parser *bp,
810 struct bp_transmitter_control *cntl)
812 enum bp_result result = BP_RESULT_FAILURE;
813 const struct command_table_helper *cmd = bp->cmd_helper;
814 DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 params;
816 memset(¶ms, 0, sizeof(params));
817 params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
818 params.ucAction = (uint8_t)cntl->action;
819 params.ucLaneNum = (uint8_t)cntl->lanes_number;
820 params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
823 cmd->signal_type_to_atom_dig_mode(cntl->signal);
824 params.asConfig.ucPhyClkSrcId =
825 cmd->clock_source_id_to_atom_phy_clk_src_id(cntl->pll_id);
826 /* 00 - coherent mode */
827 params.asConfig.ucCoherentMode = cntl->coherent;
828 params.asConfig.ucHPDSel =
829 cmd->hpd_sel_to_atom(cntl->hpd_sel);
830 params.ucDigEncoderSel =
831 cmd->dig_encoder_sel_to_atom(cntl->engine_id);
832 params.ucDPLaneSet = (uint8_t) cntl->lane_settings;
833 params.usSymClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10));
835 * In SI/TN case, caller have to set usPixelClock as following:
836 * DP mode: usPixelClock = DP_LINK_CLOCK/10
837 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
838 * DVI single link mode: usPixelClock = pixel clock
839 * DVI dual link mode: usPixelClock = pixel clock
840 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
841 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
842 * LVDS mode: usPixelClock = pixel clock
844 if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
845 switch (cntl->color_depth) {
846 case COLOR_DEPTH_101010:
848 cpu_to_le16((le16_to_cpu(params.usSymClock) * 30) / 24);
850 case COLOR_DEPTH_121212:
852 cpu_to_le16((le16_to_cpu(params.usSymClock) * 36) / 24);
854 case COLOR_DEPTH_161616:
856 cpu_to_le16((le16_to_cpu(params.usSymClock) * 48) / 24);
863 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
864 result = BP_RESULT_OK;
869 static enum bp_result transmitter_control_v1_6(
870 struct bios_parser *bp,
871 struct bp_transmitter_control *cntl)
873 enum bp_result result = BP_RESULT_FAILURE;
874 const struct command_table_helper *cmd = bp->cmd_helper;
875 DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params;
877 memset(¶ms, 0, sizeof(params));
878 params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
879 params.ucAction = (uint8_t)cntl->action;
881 if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
882 params.ucDPLaneSet = (uint8_t)cntl->lane_settings;
884 params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal);
886 params.ucLaneNum = (uint8_t)cntl->lanes_number;
887 params.ucHPDSel = cmd->hpd_sel_to_atom(cntl->hpd_sel);
888 params.ucDigEncoderSel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);
889 params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
890 params.ulSymClock = cntl->pixel_clock/10;
893 * In SI/TN case, caller have to set usPixelClock as following:
894 * DP mode: usPixelClock = DP_LINK_CLOCK/10
895 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
896 * DVI single link mode: usPixelClock = pixel clock
897 * DVI dual link mode: usPixelClock = pixel clock
898 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
899 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
900 * LVDS mode: usPixelClock = pixel clock
902 switch (cntl->signal) {
903 case SIGNAL_TYPE_HDMI_TYPE_A:
904 switch (cntl->color_depth) {
905 case COLOR_DEPTH_101010:
907 cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24);
909 case COLOR_DEPTH_121212:
911 cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24);
913 case COLOR_DEPTH_161616:
915 cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24);
925 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
926 result = BP_RESULT_OK;
930 /*******************************************************************************
931 ********************************************************************************
935 ********************************************************************************
936 *******************************************************************************/
938 static enum bp_result set_pixel_clock_v3(
939 struct bios_parser *bp,
940 struct bp_pixel_clock_parameters *bp_params);
941 static enum bp_result set_pixel_clock_v5(
942 struct bios_parser *bp,
943 struct bp_pixel_clock_parameters *bp_params);
944 static enum bp_result set_pixel_clock_v6(
945 struct bios_parser *bp,
946 struct bp_pixel_clock_parameters *bp_params);
947 static enum bp_result set_pixel_clock_v7(
948 struct bios_parser *bp,
949 struct bp_pixel_clock_parameters *bp_params);
951 static void init_set_pixel_clock(struct bios_parser *bp)
953 switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
955 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3;
958 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5;
961 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6;
964 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
967 dm_output_to_console("Don't have set_pixel_clock for v%d\n",
968 BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
969 bp->cmd_tbl.set_pixel_clock = NULL;
974 static enum bp_result set_pixel_clock_v3(
975 struct bios_parser *bp,
976 struct bp_pixel_clock_parameters *bp_params)
978 enum bp_result result = BP_RESULT_FAILURE;
979 PIXEL_CLOCK_PARAMETERS_V3 *params;
980 SET_PIXEL_CLOCK_PS_ALLOCATION allocation;
982 memset(&allocation, 0, sizeof(allocation));
984 if (CLOCK_SOURCE_ID_PLL1 == bp_params->pll_id)
985 allocation.sPCLKInput.ucPpll = ATOM_PPLL1;
986 else if (CLOCK_SOURCE_ID_PLL2 == bp_params->pll_id)
987 allocation.sPCLKInput.ucPpll = ATOM_PPLL2;
989 return BP_RESULT_BADINPUT;
991 allocation.sPCLKInput.usRefDiv =
992 cpu_to_le16((uint16_t)bp_params->reference_divider);
993 allocation.sPCLKInput.usFbDiv =
994 cpu_to_le16((uint16_t)bp_params->feedback_divider);
995 allocation.sPCLKInput.ucFracFbDiv =
996 (uint8_t)bp_params->fractional_feedback_divider;
997 allocation.sPCLKInput.ucPostDiv =
998 (uint8_t)bp_params->pixel_clock_post_divider;
1000 /* We need to convert from 100Hz units into 10KHz units */
1001 allocation.sPCLKInput.usPixelClock =
1002 cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
1004 params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput;
1005 params->ucTransmitterId =
1006 bp->cmd_helper->encoder_id_to_atom(
1007 dal_graphics_object_id_get_encoder_id(
1008 bp_params->encoder_object_id));
1009 params->ucEncoderMode =
1010 (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
1011 bp_params->signal_type, false));
1013 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1014 params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
1016 if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK)
1017 params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK;
1019 if (CONTROLLER_ID_D1 != bp_params->controller_id)
1020 params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;
1022 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation))
1023 result = BP_RESULT_OK;
1028 #ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V5
1029 /* video bios did not define this: */
1030 typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V5 {
1031 PIXEL_CLOCK_PARAMETERS_V5 sPCLKInput;
1032 /* Caller doesn't need to init this portion */
1033 ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
1034 } SET_PIXEL_CLOCK_PS_ALLOCATION_V5;
1037 #ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V6
1038 /* video bios did not define this: */
1039 typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V6 {
1040 PIXEL_CLOCK_PARAMETERS_V6 sPCLKInput;
1041 /* Caller doesn't need to init this portion */
1042 ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
1043 } SET_PIXEL_CLOCK_PS_ALLOCATION_V6;
1046 static enum bp_result set_pixel_clock_v5(
1047 struct bios_parser *bp,
1048 struct bp_pixel_clock_parameters *bp_params)
1050 enum bp_result result = BP_RESULT_FAILURE;
1051 SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk;
1052 uint8_t controller_id;
1055 memset(&clk, 0, sizeof(clk));
1057 if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1058 && bp->cmd_helper->controller_id_to_atom(
1059 bp_params->controller_id, &controller_id)) {
1060 clk.sPCLKInput.ucCRTC = controller_id;
1061 clk.sPCLKInput.ucPpll = (uint8_t)pll_id;
1062 clk.sPCLKInput.ucRefDiv =
1063 (uint8_t)(bp_params->reference_divider);
1064 clk.sPCLKInput.usFbDiv =
1065 cpu_to_le16((uint16_t)(bp_params->feedback_divider));
1066 clk.sPCLKInput.ulFbDivDecFrac =
1067 cpu_to_le32(bp_params->fractional_feedback_divider);
1068 clk.sPCLKInput.ucPostDiv =
1069 (uint8_t)(bp_params->pixel_clock_post_divider);
1070 clk.sPCLKInput.ucTransmitterID =
1071 bp->cmd_helper->encoder_id_to_atom(
1072 dal_graphics_object_id_get_encoder_id(
1073 bp_params->encoder_object_id));
1074 clk.sPCLKInput.ucEncoderMode =
1075 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1076 bp_params->signal_type, false);
1078 /* We need to convert from 100Hz units into 10KHz units */
1079 clk.sPCLKInput.usPixelClock =
1080 cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
1082 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1083 clk.sPCLKInput.ucMiscInfo |=
1084 PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
1086 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1087 clk.sPCLKInput.ucMiscInfo |=
1088 PIXEL_CLOCK_MISC_REF_DIV_SRC;
1090 /* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp
1091 * =1:30bpp, =2:32bpp
1092 * driver choose program it itself, i.e. here we program it
1093 * to 888 by default.
1095 if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
1096 switch (bp_params->color_depth) {
1097 case TRANSMITTER_COLOR_DEPTH_30:
1098 /* yes this is correct, the atom define is wrong */
1099 clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP;
1101 case TRANSMITTER_COLOR_DEPTH_36:
1102 /* yes this is correct, the atom define is wrong */
1103 clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
1109 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1110 result = BP_RESULT_OK;
1116 static enum bp_result set_pixel_clock_v6(
1117 struct bios_parser *bp,
1118 struct bp_pixel_clock_parameters *bp_params)
1120 enum bp_result result = BP_RESULT_FAILURE;
1121 SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk;
1122 uint8_t controller_id;
1125 memset(&clk, 0, sizeof(clk));
1127 if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1128 && bp->cmd_helper->controller_id_to_atom(
1129 bp_params->controller_id, &controller_id)) {
1130 /* Note: VBIOS still wants to use ucCRTC name which is now
1132 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1134 * target the pixel clock to drive the CRTC timing.
1135 * ULONG ulPixelClock:24;
1136 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1138 * ATOM_CRTC1~6, indicate the CRTC controller to
1140 * drive the pixel clock. not used for DCPLL case.
1141 *}CRTC_PIXEL_CLOCK_FREQ;
1144 * pixel clock and CRTC id frequency
1145 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1146 * ULONG ulDispEngClkFreq; dispclk frequency
1149 clk.sPCLKInput.ulCrtcPclkFreq.ucCRTC = controller_id;
1150 clk.sPCLKInput.ucPpll = (uint8_t) pll_id;
1151 clk.sPCLKInput.ucRefDiv =
1152 (uint8_t) bp_params->reference_divider;
1153 clk.sPCLKInput.usFbDiv =
1154 cpu_to_le16((uint16_t) bp_params->feedback_divider);
1155 clk.sPCLKInput.ulFbDivDecFrac =
1156 cpu_to_le32(bp_params->fractional_feedback_divider);
1157 clk.sPCLKInput.ucPostDiv =
1158 (uint8_t) bp_params->pixel_clock_post_divider;
1159 clk.sPCLKInput.ucTransmitterID =
1160 bp->cmd_helper->encoder_id_to_atom(
1161 dal_graphics_object_id_get_encoder_id(
1162 bp_params->encoder_object_id));
1163 clk.sPCLKInput.ucEncoderMode =
1164 (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(
1165 bp_params->signal_type, false);
1167 /* We need to convert from 100 Hz units into 10KHz units */
1168 clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock =
1169 cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
1171 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {
1172 clk.sPCLKInput.ucMiscInfo |=
1173 PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL;
1176 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) {
1177 clk.sPCLKInput.ucMiscInfo |=
1178 PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
1181 /* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0:
1182 * 24bpp =1:30bpp, =2:32bpp
1183 * driver choose program it itself, i.e. here we pass required
1184 * target rate that includes deep color.
1186 if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
1187 switch (bp_params->color_depth) {
1188 case TRANSMITTER_COLOR_DEPTH_30:
1189 clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6;
1191 case TRANSMITTER_COLOR_DEPTH_36:
1192 clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6;
1194 case TRANSMITTER_COLOR_DEPTH_48:
1195 clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
1201 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1202 result = BP_RESULT_OK;
1208 static enum bp_result set_pixel_clock_v7(
1209 struct bios_parser *bp,
1210 struct bp_pixel_clock_parameters *bp_params)
1212 enum bp_result result = BP_RESULT_FAILURE;
1213 PIXEL_CLOCK_PARAMETERS_V7 clk;
1214 uint8_t controller_id;
1217 memset(&clk, 0, sizeof(clk));
1219 if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1220 && bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &controller_id)) {
1221 /* Note: VBIOS still wants to use ucCRTC name which is now
1223 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1225 * target the pixel clock to drive the CRTC timing.
1226 * ULONG ulPixelClock:24;
1227 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1229 * ATOM_CRTC1~6, indicate the CRTC controller to
1231 * drive the pixel clock. not used for DCPLL case.
1232 *}CRTC_PIXEL_CLOCK_FREQ;
1235 * pixel clock and CRTC id frequency
1236 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1237 * ULONG ulDispEngClkFreq; dispclk frequency
1240 clk.ucCRTC = controller_id;
1241 clk.ucPpll = (uint8_t) pll_id;
1242 clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id));
1243 clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false);
1245 clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock_100hz);
1247 clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);
1249 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1250 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
1252 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1253 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC;
1255 if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)
1256 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;
1258 if (bp_params->flags.SUPPORT_YUV_420)
1259 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;
1261 if (bp_params->flags.SET_XTALIN_REF_SRC)
1262 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;
1264 if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)
1265 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;
1267 if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1268 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
1270 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1271 result = BP_RESULT_OK;
1276 /*******************************************************************************
1277 ********************************************************************************
1279 ** ENABLE PIXEL CLOCK SS
1281 ********************************************************************************
1282 *******************************************************************************/
1283 static enum bp_result enable_spread_spectrum_on_ppll_v1(
1284 struct bios_parser *bp,
1285 struct bp_spread_spectrum_parameters *bp_params,
1287 static enum bp_result enable_spread_spectrum_on_ppll_v2(
1288 struct bios_parser *bp,
1289 struct bp_spread_spectrum_parameters *bp_params,
1291 static enum bp_result enable_spread_spectrum_on_ppll_v3(
1292 struct bios_parser *bp,
1293 struct bp_spread_spectrum_parameters *bp_params,
1296 static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp)
1298 switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) {
1300 bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1301 enable_spread_spectrum_on_ppll_v1;
1304 bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1305 enable_spread_spectrum_on_ppll_v2;
1308 bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1309 enable_spread_spectrum_on_ppll_v3;
1312 dm_output_to_console("Don't have enable_spread_spectrum_on_ppll for v%d\n",
1313 BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL));
1314 bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL;
1319 static enum bp_result enable_spread_spectrum_on_ppll_v1(
1320 struct bios_parser *bp,
1321 struct bp_spread_spectrum_parameters *bp_params,
1324 enum bp_result result = BP_RESULT_FAILURE;
1325 ENABLE_SPREAD_SPECTRUM_ON_PPLL params;
1327 memset(¶ms, 0, sizeof(params));
1329 if ((enable == true) && (bp_params->percentage > 0))
1330 params.ucEnable = ATOM_ENABLE;
1332 params.ucEnable = ATOM_DISABLE;
1334 params.usSpreadSpectrumPercentage =
1335 cpu_to_le16((uint16_t)bp_params->percentage);
1336 params.ucSpreadSpectrumStep =
1337 (uint8_t)bp_params->ver1.step;
1338 params.ucSpreadSpectrumDelay =
1339 (uint8_t)bp_params->ver1.delay;
1340 /* convert back to unit of 10KHz */
1341 params.ucSpreadSpectrumRange =
1342 (uint8_t)(bp_params->ver1.range / 10000);
1344 if (bp_params->flags.EXTERNAL_SS)
1345 params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK;
1347 if (bp_params->flags.CENTER_SPREAD)
1348 params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE;
1350 if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1351 params.ucPpll = ATOM_PPLL1;
1352 else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1353 params.ucPpll = ATOM_PPLL2;
1355 BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1357 if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1358 result = BP_RESULT_OK;
1363 static enum bp_result enable_spread_spectrum_on_ppll_v2(
1364 struct bios_parser *bp,
1365 struct bp_spread_spectrum_parameters *bp_params,
1368 enum bp_result result = BP_RESULT_FAILURE;
1369 ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params;
1371 memset(¶ms, 0, sizeof(params));
1373 if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1374 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P1PLL;
1375 else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1376 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P2PLL;
1378 BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1380 if ((enable == true) && (bp_params->percentage > 0)) {
1381 params.ucEnable = ATOM_ENABLE;
1383 params.usSpreadSpectrumPercentage =
1384 cpu_to_le16((uint16_t)(bp_params->percentage));
1385 params.usSpreadSpectrumStep =
1386 cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1388 if (bp_params->flags.EXTERNAL_SS)
1389 params.ucSpreadSpectrumType |=
1390 ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD;
1392 if (bp_params->flags.CENTER_SPREAD)
1393 params.ucSpreadSpectrumType |=
1394 ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD;
1396 /* Both amounts need to be left shifted first before bit
1397 * comparison. Otherwise, the result will always be zero here
1399 params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1400 ((bp_params->ds.feedback_amount <<
1401 ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT) &
1402 ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK) |
1403 ((bp_params->ds.nfrac_amount <<
1404 ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
1405 ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK)));
1407 params.ucEnable = ATOM_DISABLE;
1409 if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1410 result = BP_RESULT_OK;
1415 static enum bp_result enable_spread_spectrum_on_ppll_v3(
1416 struct bios_parser *bp,
1417 struct bp_spread_spectrum_parameters *bp_params,
1420 enum bp_result result = BP_RESULT_FAILURE;
1421 ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params;
1423 memset(¶ms, 0, sizeof(params));
1425 switch (bp_params->pll_id) {
1426 case CLOCK_SOURCE_ID_PLL0:
1427 /* ATOM_PPLL_SS_TYPE_V3_P0PLL; this is pixel clock only,
1428 * not for SI display clock.
1430 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1432 case CLOCK_SOURCE_ID_PLL1:
1433 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL;
1436 case CLOCK_SOURCE_ID_PLL2:
1437 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL;
1440 case CLOCK_SOURCE_ID_DCPLL:
1441 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1445 BREAK_TO_DEBUGGER();
1446 /* Unexpected PLL value!! */
1450 if (enable == true) {
1451 params.ucEnable = ATOM_ENABLE;
1453 params.usSpreadSpectrumAmountFrac =
1454 cpu_to_le16((uint16_t)(bp_params->ds_frac_amount));
1455 params.usSpreadSpectrumStep =
1456 cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1458 if (bp_params->flags.EXTERNAL_SS)
1459 params.ucSpreadSpectrumType |=
1460 ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD;
1461 if (bp_params->flags.CENTER_SPREAD)
1462 params.ucSpreadSpectrumType |=
1463 ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD;
1465 /* Both amounts need to be left shifted first before bit
1466 * comparison. Otherwise, the result will always be zero here
1468 params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1469 ((bp_params->ds.feedback_amount <<
1470 ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT) &
1471 ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK) |
1472 ((bp_params->ds.nfrac_amount <<
1473 ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT) &
1474 ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK)));
1476 params.ucEnable = ATOM_DISABLE;
1478 if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1479 result = BP_RESULT_OK;
1484 /*******************************************************************************
1485 ********************************************************************************
1487 ** ADJUST DISPLAY PLL
1489 ********************************************************************************
1490 *******************************************************************************/
1492 static enum bp_result adjust_display_pll_v2(
1493 struct bios_parser *bp,
1494 struct bp_adjust_pixel_clock_parameters *bp_params);
1495 static enum bp_result adjust_display_pll_v3(
1496 struct bios_parser *bp,
1497 struct bp_adjust_pixel_clock_parameters *bp_params);
1499 static void init_adjust_display_pll(struct bios_parser *bp)
1501 switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) {
1503 bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2;
1506 bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3;
1509 dm_output_to_console("Don't have adjust_display_pll for v%d\n",
1510 BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll));
1511 bp->cmd_tbl.adjust_display_pll = NULL;
1516 static enum bp_result adjust_display_pll_v2(
1517 struct bios_parser *bp,
1518 struct bp_adjust_pixel_clock_parameters *bp_params)
1520 enum bp_result result = BP_RESULT_FAILURE;
1521 ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 };
1523 /* We need to convert from KHz units into 10KHz units and then convert
1524 * output pixel clock back 10KHz-->KHz */
1525 uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10;
1527 params.usPixelClock = cpu_to_le16((uint16_t)(pixel_clock_10KHz_in));
1528 params.ucTransmitterID =
1529 bp->cmd_helper->encoder_id_to_atom(
1530 dal_graphics_object_id_get_encoder_id(
1531 bp_params->encoder_object_id));
1532 params.ucEncodeMode =
1533 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1534 bp_params->signal_type, false);
1536 if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
1537 /* Convert output pixel clock back 10KHz-->KHz: multiply
1538 * original pixel clock in KHz by ratio
1539 * [output pxlClk/input pxlClk] */
1540 uint64_t pixel_clk_10_khz_out =
1541 (uint64_t)le16_to_cpu(params.usPixelClock);
1542 uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
1544 if (pixel_clock_10KHz_in != 0) {
1545 bp_params->adjusted_pixel_clock =
1546 div_u64(pixel_clk * pixel_clk_10_khz_out,
1547 pixel_clock_10KHz_in);
1549 bp_params->adjusted_pixel_clock = 0;
1550 BREAK_TO_DEBUGGER();
1553 result = BP_RESULT_OK;
1559 static enum bp_result adjust_display_pll_v3(
1560 struct bios_parser *bp,
1561 struct bp_adjust_pixel_clock_parameters *bp_params)
1563 enum bp_result result = BP_RESULT_FAILURE;
1564 ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 params;
1565 uint32_t pixel_clk_10_kHz_in = bp_params->pixel_clock / 10;
1567 memset(¶ms, 0, sizeof(params));
1569 /* We need to convert from KHz units into 10KHz units and then convert
1570 * output pixel clock back 10KHz-->KHz */
1571 params.sInput.usPixelClock = cpu_to_le16((uint16_t)pixel_clk_10_kHz_in);
1572 params.sInput.ucTransmitterID =
1573 bp->cmd_helper->encoder_id_to_atom(
1574 dal_graphics_object_id_get_encoder_id(
1575 bp_params->encoder_object_id));
1576 params.sInput.ucEncodeMode =
1577 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1578 bp_params->signal_type, false);
1580 if (bp_params->ss_enable == true)
1581 params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
1583 if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1584 params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
1586 if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
1587 /* Convert output pixel clock back 10KHz-->KHz: multiply
1588 * original pixel clock in KHz by ratio
1589 * [output pxlClk/input pxlClk] */
1590 uint64_t pixel_clk_10_khz_out =
1591 (uint64_t)le32_to_cpu(params.sOutput.ulDispPllFreq);
1592 uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
1594 if (pixel_clk_10_kHz_in != 0) {
1595 bp_params->adjusted_pixel_clock =
1596 div_u64(pixel_clk * pixel_clk_10_khz_out,
1597 pixel_clk_10_kHz_in);
1599 bp_params->adjusted_pixel_clock = 0;
1600 BREAK_TO_DEBUGGER();
1603 bp_params->reference_divider = params.sOutput.ucRefDiv;
1604 bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv;
1606 result = BP_RESULT_OK;
1612 /*******************************************************************************
1613 ********************************************************************************
1615 ** DAC ENCODER CONTROL
1617 ********************************************************************************
1618 *******************************************************************************/
1620 static enum bp_result dac1_encoder_control_v1(
1621 struct bios_parser *bp,
1623 uint32_t pixel_clock,
1624 uint8_t dac_standard);
1625 static enum bp_result dac2_encoder_control_v1(
1626 struct bios_parser *bp,
1628 uint32_t pixel_clock,
1629 uint8_t dac_standard);
1631 static void init_dac_encoder_control(struct bios_parser *bp)
1633 switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) {
1635 bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1;
1638 bp->cmd_tbl.dac1_encoder_control = NULL;
1641 switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) {
1643 bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1;
1646 bp->cmd_tbl.dac2_encoder_control = NULL;
1651 static void dac_encoder_control_prepare_params(
1652 DAC_ENCODER_CONTROL_PS_ALLOCATION *params,
1654 uint32_t pixel_clock,
1655 uint8_t dac_standard)
1657 params->ucDacStandard = dac_standard;
1659 params->ucAction = ATOM_ENABLE;
1661 params->ucAction = ATOM_DISABLE;
1663 /* We need to convert from KHz units into 10KHz units
1664 * it looks as if the TvControl do not care about pixel clock
1666 params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10));
1669 static enum bp_result dac1_encoder_control_v1(
1670 struct bios_parser *bp,
1672 uint32_t pixel_clock,
1673 uint8_t dac_standard)
1675 enum bp_result result = BP_RESULT_FAILURE;
1676 DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1678 dac_encoder_control_prepare_params(
1684 if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params))
1685 result = BP_RESULT_OK;
1690 static enum bp_result dac2_encoder_control_v1(
1691 struct bios_parser *bp,
1693 uint32_t pixel_clock,
1694 uint8_t dac_standard)
1696 enum bp_result result = BP_RESULT_FAILURE;
1697 DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1699 dac_encoder_control_prepare_params(
1705 if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params))
1706 result = BP_RESULT_OK;
1711 /*******************************************************************************
1712 ********************************************************************************
1714 ** DAC OUTPUT CONTROL
1716 ********************************************************************************
1717 *******************************************************************************/
1718 static enum bp_result dac1_output_control_v1(
1719 struct bios_parser *bp,
1721 static enum bp_result dac2_output_control_v1(
1722 struct bios_parser *bp,
1725 static void init_dac_output_control(struct bios_parser *bp)
1727 switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) {
1729 bp->cmd_tbl.dac1_output_control = dac1_output_control_v1;
1732 bp->cmd_tbl.dac1_output_control = NULL;
1735 switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) {
1737 bp->cmd_tbl.dac2_output_control = dac2_output_control_v1;
1740 bp->cmd_tbl.dac2_output_control = NULL;
1745 static enum bp_result dac1_output_control_v1(
1746 struct bios_parser *bp, bool enable)
1748 enum bp_result result = BP_RESULT_FAILURE;
1749 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
1752 params.ucAction = ATOM_ENABLE;
1754 params.ucAction = ATOM_DISABLE;
1756 if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params))
1757 result = BP_RESULT_OK;
1762 static enum bp_result dac2_output_control_v1(
1763 struct bios_parser *bp, bool enable)
1765 enum bp_result result = BP_RESULT_FAILURE;
1766 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
1769 params.ucAction = ATOM_ENABLE;
1771 params.ucAction = ATOM_DISABLE;
1773 if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params))
1774 result = BP_RESULT_OK;
1779 /*******************************************************************************
1780 ********************************************************************************
1784 ********************************************************************************
1785 *******************************************************************************/
1787 static enum bp_result set_crtc_using_dtd_timing_v3(
1788 struct bios_parser *bp,
1789 struct bp_hw_crtc_timing_parameters *bp_params);
1790 static enum bp_result set_crtc_timing_v1(
1791 struct bios_parser *bp,
1792 struct bp_hw_crtc_timing_parameters *bp_params);
1794 static void init_set_crtc_timing(struct bios_parser *bp)
1796 uint32_t dtd_version =
1797 BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming);
1798 if (dtd_version > 2)
1799 switch (dtd_version) {
1801 bp->cmd_tbl.set_crtc_timing =
1802 set_crtc_using_dtd_timing_v3;
1805 dm_output_to_console("Don't have set_crtc_timing for dtd v%d\n",
1807 bp->cmd_tbl.set_crtc_timing = NULL;
1811 switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) {
1813 bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1;
1816 dm_output_to_console("Don't have set_crtc_timing for v%d\n",
1817 BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing));
1818 bp->cmd_tbl.set_crtc_timing = NULL;
1823 static enum bp_result set_crtc_timing_v1(
1824 struct bios_parser *bp,
1825 struct bp_hw_crtc_timing_parameters *bp_params)
1827 enum bp_result result = BP_RESULT_FAILURE;
1828 SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0};
1829 uint8_t atom_controller_id;
1831 if (bp->cmd_helper->controller_id_to_atom(
1832 bp_params->controller_id, &atom_controller_id))
1833 params.ucCRTC = atom_controller_id;
1835 params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total));
1836 params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable));
1837 params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start));
1838 params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width));
1839 params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total));
1840 params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable));
1841 params.usV_SyncStart =
1842 cpu_to_le16((uint16_t)(bp_params->v_sync_start));
1843 params.usV_SyncWidth =
1844 cpu_to_le16((uint16_t)(bp_params->v_sync_width));
1846 /* VBIOS does not expect any value except zero into this call, for
1847 * underscan use another entry ProgramOverscan call but when mode
1848 * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok,
1849 * but when same ,but 60 Hz there is corruption
1850 * DAL1 does not allow the mode 1776x1000@60
1852 params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right;
1853 params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left;
1854 params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom;
1855 params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top;
1857 if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
1858 params.susModeMiscInfo.usAccess =
1859 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
1861 if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
1862 params.susModeMiscInfo.usAccess =
1863 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
1865 if (bp_params->flags.INTERLACE) {
1866 params.susModeMiscInfo.usAccess =
1867 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
1869 /* original DAL code has this condition to apply tis for
1870 * non-TV/CV only due to complex MV testing for possible
1872 * if (pACParameters->signal != SignalType_YPbPr &&
1873 * pACParameters->signal != SignalType_Composite &&
1874 * pACParameters->signal != SignalType_SVideo)
1876 /* HW will deduct 0.5 line from 2nd feild.
1877 * i.e. for 1080i, it is 2 lines for 1st field, 2.5
1878 * lines for the 2nd feild. we need input as 5 instead
1879 * of 4, but it is 4 either from Edid data
1880 * (spec CEA 861) or CEA timing table.
1882 params.usV_SyncStart =
1883 cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1));
1886 if (bp_params->flags.HORZ_COUNT_BY_TWO)
1887 params.susModeMiscInfo.usAccess =
1888 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
1890 if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params))
1891 result = BP_RESULT_OK;
1896 static enum bp_result set_crtc_using_dtd_timing_v3(
1897 struct bios_parser *bp,
1898 struct bp_hw_crtc_timing_parameters *bp_params)
1900 enum bp_result result = BP_RESULT_FAILURE;
1901 SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0};
1902 uint8_t atom_controller_id;
1904 if (bp->cmd_helper->controller_id_to_atom(
1905 bp_params->controller_id, &atom_controller_id))
1906 params.ucCRTC = atom_controller_id;
1908 /* bios usH_Size wants h addressable size */
1909 params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable);
1910 /* bios usH_Blanking_Time wants borders included in blanking */
1911 params.usH_Blanking_Time =
1912 cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable));
1913 /* bios usV_Size wants v addressable size */
1914 params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable);
1915 /* bios usV_Blanking_Time wants borders included in blanking */
1916 params.usV_Blanking_Time =
1917 cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable));
1918 /* bios usHSyncOffset is the offset from the end of h addressable,
1919 * our horizontalSyncStart is the offset from the beginning
1920 * of h addressable */
1921 params.usH_SyncOffset =
1922 cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable));
1923 params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);
1924 /* bios usHSyncOffset is the offset from the end of v addressable,
1925 * our verticalSyncStart is the offset from the beginning of
1927 params.usV_SyncOffset =
1928 cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable));
1929 params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);
1931 /* we assume that overscan from original timing does not get bigger
1933 * we will program all the borders in the Set CRTC Overscan call below
1936 if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
1937 params.susModeMiscInfo.usAccess =
1938 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
1940 if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
1941 params.susModeMiscInfo.usAccess =
1942 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
1944 if (bp_params->flags.INTERLACE) {
1945 params.susModeMiscInfo.usAccess =
1946 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
1948 /* original DAL code has this condition to apply this
1949 * for non-TV/CV only
1950 * due to complex MV testing for possible impact
1951 * if ( pACParameters->signal != SignalType_YPbPr &&
1952 * pACParameters->signal != SignalType_Composite &&
1953 * pACParameters->signal != SignalType_SVideo)
1956 /* HW will deduct 0.5 line from 2nd feild.
1957 * i.e. for 1080i, it is 2 lines for 1st field,
1958 * 2.5 lines for the 2nd feild. we need input as 5
1960 * but it is 4 either from Edid data (spec CEA 861)
1961 * or CEA timing table.
1963 le16_add_cpu(¶ms.usV_SyncOffset, 1);
1967 if (bp_params->flags.HORZ_COUNT_BY_TWO)
1968 params.susModeMiscInfo.usAccess =
1969 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
1971 if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params))
1972 result = BP_RESULT_OK;
1977 /*******************************************************************************
1978 ********************************************************************************
1982 ********************************************************************************
1983 *******************************************************************************/
1985 static enum bp_result enable_crtc_v1(
1986 struct bios_parser *bp,
1987 enum controller_id controller_id,
1990 static void init_enable_crtc(struct bios_parser *bp)
1992 switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) {
1994 bp->cmd_tbl.enable_crtc = enable_crtc_v1;
1997 dm_output_to_console("Don't have enable_crtc for v%d\n",
1998 BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC));
1999 bp->cmd_tbl.enable_crtc = NULL;
2004 static enum bp_result enable_crtc_v1(
2005 struct bios_parser *bp,
2006 enum controller_id controller_id,
2009 bool result = BP_RESULT_FAILURE;
2010 ENABLE_CRTC_PARAMETERS params = {0};
2013 if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))
2016 return BP_RESULT_BADINPUT;
2019 params.ucEnable = ATOM_ENABLE;
2021 params.ucEnable = ATOM_DISABLE;
2023 if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params))
2024 result = BP_RESULT_OK;
2029 /*******************************************************************************
2030 ********************************************************************************
2032 ** ENABLE CRTC MEM REQ
2034 ********************************************************************************
2035 *******************************************************************************/
2037 static enum bp_result enable_crtc_mem_req_v1(
2038 struct bios_parser *bp,
2039 enum controller_id controller_id,
2042 static void init_enable_crtc_mem_req(struct bios_parser *bp)
2044 switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) {
2046 bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1;
2049 bp->cmd_tbl.enable_crtc_mem_req = NULL;
2054 static enum bp_result enable_crtc_mem_req_v1(
2055 struct bios_parser *bp,
2056 enum controller_id controller_id,
2059 bool result = BP_RESULT_BADINPUT;
2060 ENABLE_CRTC_PARAMETERS params = {0};
2063 if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) {
2067 params.ucEnable = ATOM_ENABLE;
2069 params.ucEnable = ATOM_DISABLE;
2071 if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params))
2072 result = BP_RESULT_OK;
2074 result = BP_RESULT_FAILURE;
2080 /*******************************************************************************
2081 ********************************************************************************
2085 ********************************************************************************
2086 *******************************************************************************/
2088 static enum bp_result program_clock_v5(
2089 struct bios_parser *bp,
2090 struct bp_pixel_clock_parameters *bp_params);
2091 static enum bp_result program_clock_v6(
2092 struct bios_parser *bp,
2093 struct bp_pixel_clock_parameters *bp_params);
2095 static void init_program_clock(struct bios_parser *bp)
2097 switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
2099 bp->cmd_tbl.program_clock = program_clock_v5;
2102 bp->cmd_tbl.program_clock = program_clock_v6;
2105 dm_output_to_console("Don't have program_clock for v%d\n",
2106 BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
2107 bp->cmd_tbl.program_clock = NULL;
2112 static enum bp_result program_clock_v5(
2113 struct bios_parser *bp,
2114 struct bp_pixel_clock_parameters *bp_params)
2116 enum bp_result result = BP_RESULT_FAILURE;
2118 SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params;
2119 uint32_t atom_pll_id;
2121 memset(¶ms, 0, sizeof(params));
2122 if (!bp->cmd_helper->clock_source_id_to_atom(
2123 bp_params->pll_id, &atom_pll_id)) {
2124 BREAK_TO_DEBUGGER(); /* Invalid Input!! */
2125 return BP_RESULT_BADINPUT;
2128 /* We need to convert from KHz units into 10KHz units */
2129 params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id;
2130 params.sPCLKInput.usPixelClock =
2131 cpu_to_le16((uint16_t) (bp_params->target_pixel_clock_100hz / 100));
2132 params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID;
2134 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2135 params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2137 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params))
2138 result = BP_RESULT_OK;
2143 static enum bp_result program_clock_v6(
2144 struct bios_parser *bp,
2145 struct bp_pixel_clock_parameters *bp_params)
2147 enum bp_result result = BP_RESULT_FAILURE;
2149 SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params;
2150 uint32_t atom_pll_id;
2152 memset(¶ms, 0, sizeof(params));
2154 if (!bp->cmd_helper->clock_source_id_to_atom(
2155 bp_params->pll_id, &atom_pll_id)) {
2156 BREAK_TO_DEBUGGER(); /*Invalid Input!!*/
2157 return BP_RESULT_BADINPUT;
2160 /* We need to convert from KHz units into 10KHz units */
2161 params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id;
2162 params.sPCLKInput.ulDispEngClkFreq =
2163 cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
2165 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2166 params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2168 if (bp_params->flags.SET_DISPCLK_DFS_BYPASS)
2169 params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_DPREFCLK_BYPASS;
2171 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) {
2172 /* True display clock is returned by VBIOS if DFS bypass
2174 bp_params->dfs_bypass_display_clock =
2175 (uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10);
2176 result = BP_RESULT_OK;
2182 /*******************************************************************************
2183 ********************************************************************************
2185 ** EXTERNAL ENCODER CONTROL
2187 ********************************************************************************
2188 *******************************************************************************/
2190 static enum bp_result external_encoder_control_v3(
2191 struct bios_parser *bp,
2192 struct bp_external_encoder_control *cntl);
2194 static void init_external_encoder_control(
2195 struct bios_parser *bp)
2197 switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) {
2199 bp->cmd_tbl.external_encoder_control =
2200 external_encoder_control_v3;
2203 bp->cmd_tbl.external_encoder_control = NULL;
2208 static enum bp_result external_encoder_control_v3(
2209 struct bios_parser *bp,
2210 struct bp_external_encoder_control *cntl)
2212 enum bp_result result = BP_RESULT_FAILURE;
2214 /* we need use _PS_Alloc struct */
2215 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 params;
2216 EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 *cntl_params;
2217 struct graphics_object_id encoder;
2218 bool is_input_signal_dp = false;
2220 memset(¶ms, 0, sizeof(params));
2222 cntl_params = ¶ms.sExtEncoder;
2224 encoder = cntl->encoder_id;
2226 /* check if encoder supports external encoder control table */
2227 switch (dal_graphics_object_id_get_encoder_id(encoder)) {
2228 case ENCODER_ID_EXTERNAL_NUTMEG:
2229 case ENCODER_ID_EXTERNAL_TRAVIS:
2230 is_input_signal_dp = true;
2234 BREAK_TO_DEBUGGER();
2235 return BP_RESULT_BADINPUT;
2238 /* Fill information based on the action
2240 * Bit[6:4]: indicate external encoder, applied to all functions.
2241 * =0: external encoder1, mapped to external encoder enum id1
2242 * =1: external encoder2, mapped to external encoder enum id2
2246 * EnumId_Unknown = 0,
2251 cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4);
2253 switch (cntl->action) {
2254 case EXTERNAL_ENCODER_CONTROL_INIT:
2255 /* output display connector type. Only valid in encoder
2257 cntl_params->usConnectorId =
2258 cpu_to_le16((uint16_t)cntl->connector_obj_id.id);
2260 case EXTERNAL_ENCODER_CONTROL_SETUP:
2261 /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in
2263 * output display device pixel clock frequency in unit of 10KHz.
2264 * Only valid in setup and enableoutput
2266 cntl_params->usPixelClock =
2267 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2268 /* Indicate display output signal type drive by external
2269 * encoder, only valid in setup and enableoutput */
2270 cntl_params->ucEncoderMode =
2271 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2272 cntl->signal, false);
2274 if (is_input_signal_dp) {
2275 /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz,
2276 * only valid in encoder setup with DP mode. */
2277 if (LINK_RATE_HIGH == cntl->link_rate)
2278 cntl_params->ucConfig |= 1;
2279 /* output color depth Indicate encoder data bpc format
2280 * in DP mode, only valid in encoder setup in DP mode.
2282 cntl_params->ucBitPerColor =
2283 (uint8_t)(cntl->color_depth);
2285 /* Indicate how many lanes used by external encoder, only valid
2286 * in encoder setup and enableoutput. */
2287 cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);
2289 case EXTERNAL_ENCODER_CONTROL_ENABLE:
2290 cntl_params->usPixelClock =
2291 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2292 cntl_params->ucEncoderMode =
2293 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2294 cntl->signal, false);
2295 cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number;
2301 cntl_params->ucAction = (uint8_t)cntl->action;
2303 if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params))
2304 result = BP_RESULT_OK;
2309 /*******************************************************************************
2310 ********************************************************************************
2312 ** ENABLE DISPLAY POWER GATING
2314 ********************************************************************************
2315 *******************************************************************************/
2317 static enum bp_result enable_disp_power_gating_v2_1(
2318 struct bios_parser *bp,
2319 enum controller_id crtc_id,
2320 enum bp_pipe_control_action action);
2322 static void init_enable_disp_power_gating(
2323 struct bios_parser *bp)
2325 switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) {
2327 bp->cmd_tbl.enable_disp_power_gating =
2328 enable_disp_power_gating_v2_1;
2331 dm_output_to_console("Don't enable_disp_power_gating enable_crtc for v%d\n",
2332 BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating));
2333 bp->cmd_tbl.enable_disp_power_gating = NULL;
2338 static enum bp_result enable_disp_power_gating_v2_1(
2339 struct bios_parser *bp,
2340 enum controller_id crtc_id,
2341 enum bp_pipe_control_action action)
2343 enum bp_result result = BP_RESULT_FAILURE;
2345 ENABLE_DISP_POWER_GATING_PS_ALLOCATION params = {0};
2346 uint8_t atom_crtc_id;
2348 if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))
2349 params.ucDispPipeId = atom_crtc_id;
2351 return BP_RESULT_BADINPUT;
2354 bp->cmd_helper->disp_power_gating_action_to_atom(action);
2356 if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params))
2357 result = BP_RESULT_OK;
2362 /*******************************************************************************
2363 ********************************************************************************
2367 ********************************************************************************
2368 *******************************************************************************/
2369 static enum bp_result set_dce_clock_v2_1(
2370 struct bios_parser *bp,
2371 struct bp_set_dce_clock_parameters *bp_params);
2373 static void init_set_dce_clock(struct bios_parser *bp)
2375 switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) {
2377 bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
2380 dm_output_to_console("Don't have set_dce_clock for v%d\n",
2381 BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock));
2382 bp->cmd_tbl.set_dce_clock = NULL;
2387 static enum bp_result set_dce_clock_v2_1(
2388 struct bios_parser *bp,
2389 struct bp_set_dce_clock_parameters *bp_params)
2391 enum bp_result result = BP_RESULT_FAILURE;
2393 SET_DCE_CLOCK_PS_ALLOCATION_V2_1 params;
2394 uint32_t atom_pll_id;
2395 uint32_t atom_clock_type;
2396 const struct command_table_helper *cmd = bp->cmd_helper;
2398 memset(¶ms, 0, sizeof(params));
2400 if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||
2401 !cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type))
2402 return BP_RESULT_BADINPUT;
2404 params.asParam.ucDCEClkSrc = atom_pll_id;
2405 params.asParam.ucDCEClkType = atom_clock_type;
2407 if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {
2408 if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)
2409 params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;
2411 if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)
2412 params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;
2414 if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)
2415 params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;
2417 if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)
2418 params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;
2421 /* only program clock frequency if display clock is used; VBIOS will program DPREFCLK */
2422 /* We need to convert from KHz units into 10KHz units */
2423 params.asParam.ulDCEClkFreq = cpu_to_le32(bp_params->target_clock_frequency / 10);
2425 if (EXEC_BIOS_CMD_TABLE(SetDCEClock, params)) {
2426 /* Convert from 10KHz units back to KHz */
2427 bp_params->target_clock_frequency = le32_to_cpu(params.asParam.ulDCEClkFreq) * 10;
2428 result = BP_RESULT_OK;