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 (cgs_atom_exec_cmd_table(bp->base.ctx->cgs_device, \
39 GetIndexIntoMasterTable(COMMAND, command), \
42 #define BIOS_CMD_TABLE_REVISION(command, frev, crev)\
43 cgs_atom_get_cmd_table_revs(bp->base.ctx->cgs_device, \
44 GetIndexIntoMasterTable(COMMAND, command), &frev, &crev)
46 #define BIOS_CMD_TABLE_PARA_REVISION(command)\
47 bios_cmd_table_para_revision(bp->base.ctx->cgs_device, \
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_select_crtc_source(struct bios_parser *bp);
59 static void init_enable_crtc(struct bios_parser *bp);
60 static void init_enable_crtc_mem_req(struct bios_parser *bp);
61 static void init_external_encoder_control(struct bios_parser *bp);
62 static void init_enable_disp_power_gating(struct bios_parser *bp);
63 static void init_program_clock(struct bios_parser *bp);
64 static void init_set_dce_clock(struct bios_parser *bp);
66 void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
68 init_dig_encoder_control(bp);
69 init_transmitter_control(bp);
70 init_set_pixel_clock(bp);
71 init_enable_spread_spectrum_on_ppll(bp);
72 init_adjust_display_pll(bp);
73 init_dac_encoder_control(bp);
74 init_dac_output_control(bp);
75 init_set_crtc_timing(bp);
76 init_select_crtc_source(bp);
78 init_enable_crtc_mem_req(bp);
79 init_program_clock(bp);
80 init_external_encoder_control(bp);
81 init_enable_disp_power_gating(bp);
82 init_set_dce_clock(bp);
85 static uint32_t bios_cmd_table_para_revision(void *cgs_device,
90 if (cgs_atom_get_cmd_table_revs(cgs_device,
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 if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
249 result = BP_RESULT_OK;
254 static enum bp_result encoder_control_digx_v4(
255 struct bios_parser *bp,
256 struct bp_encoder_control *cntl)
258 enum bp_result result = BP_RESULT_FAILURE;
259 DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0};
261 if (LANE_COUNT_FOUR < cntl->lanes_number)
262 params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
264 params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
266 params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
268 /* We need to convert from KHz units into 10KHz units */
269 params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
270 params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
271 params.ucEncoderMode =
272 (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
274 cntl->enable_dp_audio));
275 params.ucLaneNum = (uint8_t)(cntl->lanes_number);
277 if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
278 result = BP_RESULT_OK;
283 static enum bp_result encoder_control_digx_v5(
284 struct bios_parser *bp,
285 struct bp_encoder_control *cntl)
287 enum bp_result result = BP_RESULT_FAILURE;
288 ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0};
290 params.ucDigId = (uint8_t)(cntl->engine_id);
291 params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
293 params.ulPixelClock = cntl->pixel_clock / 10;
295 (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
297 cntl->enable_dp_audio));
298 params.ucLaneNum = (uint8_t)(cntl->lanes_number);
300 switch (cntl->color_depth) {
301 case COLOR_DEPTH_888:
302 params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
304 case COLOR_DEPTH_101010:
305 params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
307 case COLOR_DEPTH_121212:
308 params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
310 case COLOR_DEPTH_161616:
311 params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
317 if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
318 switch (cntl->color_depth) {
319 case COLOR_DEPTH_101010:
320 params.ulPixelClock =
321 (params.ulPixelClock * 30) / 24;
323 case COLOR_DEPTH_121212:
324 params.ulPixelClock =
325 (params.ulPixelClock * 36) / 24;
327 case COLOR_DEPTH_161616:
328 params.ulPixelClock =
329 (params.ulPixelClock * 48) / 24;
335 if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
336 result = BP_RESULT_OK;
341 /*******************************************************************************
342 ********************************************************************************
344 ** TRANSMITTER CONTROL
346 ********************************************************************************
347 *******************************************************************************/
349 static enum bp_result transmitter_control_v2(
350 struct bios_parser *bp,
351 struct bp_transmitter_control *cntl);
352 static enum bp_result transmitter_control_v3(
353 struct bios_parser *bp,
354 struct bp_transmitter_control *cntl);
355 static enum bp_result transmitter_control_v4(
356 struct bios_parser *bp,
357 struct bp_transmitter_control *cntl);
358 static enum bp_result transmitter_control_v1_5(
359 struct bios_parser *bp,
360 struct bp_transmitter_control *cntl);
361 static enum bp_result transmitter_control_v1_6(
362 struct bios_parser *bp,
363 struct bp_transmitter_control *cntl);
365 static void init_transmitter_control(struct bios_parser *bp)
370 if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl,
375 bp->cmd_tbl.transmitter_control = transmitter_control_v2;
378 bp->cmd_tbl.transmitter_control = transmitter_control_v3;
381 bp->cmd_tbl.transmitter_control = transmitter_control_v4;
384 bp->cmd_tbl.transmitter_control = transmitter_control_v1_5;
387 bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;
390 dm_output_to_console("Don't have transmitter_control for v%d\n", crev);
391 bp->cmd_tbl.transmitter_control = NULL;
396 static enum bp_result transmitter_control_v2(
397 struct bios_parser *bp,
398 struct bp_transmitter_control *cntl)
400 enum bp_result result = BP_RESULT_FAILURE;
401 DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params;
402 enum connector_id connector_id =
403 dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
405 memset(¶ms, 0, sizeof(params));
407 switch (cntl->transmitter) {
408 case TRANSMITTER_UNIPHY_A:
409 case TRANSMITTER_UNIPHY_B:
410 case TRANSMITTER_UNIPHY_C:
411 case TRANSMITTER_UNIPHY_D:
412 case TRANSMITTER_UNIPHY_E:
413 case TRANSMITTER_UNIPHY_F:
414 case TRANSMITTER_TRAVIS_LCD:
417 return BP_RESULT_BADINPUT;
420 switch (cntl->action) {
421 case TRANSMITTER_CONTROL_INIT:
422 if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) ||
423 (CONNECTOR_ID_DUAL_LINK_DVID == connector_id))
424 /* on INIT this bit should be set according to the
426 * Bit0: dual link connector flag
427 * =0 connector is single link connector
428 * =1 connector is dual link connector
430 params.acConfig.fDualLinkConnector = 1;
432 /* connector object id */
434 cpu_to_le16((uint8_t)cntl->connector_obj_id.id);
436 case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
437 /* votage swing and pre-emphsis */
438 params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
439 params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
443 if (LANE_COUNT_FOUR < cntl->lanes_number) {
444 /* on ENABLE/DISABLE this bit should be set according to
445 * actual timing (number of lanes)
446 * Bit0: dual link connector flag
447 * =0 connector is single link connector
448 * =1 connector is dual link connector
450 params.acConfig.fDualLinkConnector = 1;
452 /* link rate, half for dual link
453 * We need to convert from KHz units into 20KHz units
455 params.usPixelClock =
456 cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
458 /* link rate, half for dual link
459 * We need to convert from KHz units into 10KHz units
461 params.usPixelClock =
462 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
466 /* 00 - coherent mode
467 * 01 - incoherent mode
470 params.acConfig.fCoherentMode = cntl->coherent;
472 if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
473 || (TRANSMITTER_UNIPHY_D == cntl->transmitter)
474 || (TRANSMITTER_UNIPHY_F == cntl->transmitter))
475 /* Bit2: Transmitter Link selection
476 * =0 when bit0=0, single link A/C/E, when bit0=1,
478 * =1 when bit0=0, single link B/D/F, when bit0=1,
481 params.acConfig.ucLinkSel = 1;
483 if (ENGINE_ID_DIGB == cntl->engine_id)
484 /* Bit3: Transmitter data source selection
485 * =0 DIGA is data source.
486 * =1 DIGB is data source.
487 * This bit is only useful when ucAction= ATOM_ENABLE
489 params.acConfig.ucEncoderSel = 1;
491 if (CONNECTOR_ID_DISPLAY_PORT == connector_id)
492 /* Bit4: DP connector flag
493 * =0 connector is none-DP connector
494 * =1 connector is DP connector
496 params.acConfig.fDPConnector = 1;
498 /* Bit[7:6]: Transmitter selection
499 * =0 UNIPHY_ENCODER: UNIPHYA/B
500 * =1 UNIPHY1_ENCODER: UNIPHYC/D
501 * =2 UNIPHY2_ENCODER: UNIPHYE/F
504 params.acConfig.ucTransmitterSel =
505 (uint8_t)bp->cmd_helper->transmitter_bp_to_atom(
508 params.ucAction = (uint8_t)cntl->action;
510 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
511 result = BP_RESULT_OK;
516 static enum bp_result transmitter_control_v3(
517 struct bios_parser *bp,
518 struct bp_transmitter_control *cntl)
520 enum bp_result result = BP_RESULT_FAILURE;
521 DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 params;
523 enum connector_id conn_id =
524 dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
525 const struct command_table_helper *cmd = bp->cmd_helper;
526 bool dual_link_conn = (CONNECTOR_ID_DUAL_LINK_DVII == conn_id)
527 || (CONNECTOR_ID_DUAL_LINK_DVID == conn_id);
529 memset(¶ms, 0, sizeof(params));
531 switch (cntl->transmitter) {
532 case TRANSMITTER_UNIPHY_A:
533 case TRANSMITTER_UNIPHY_B:
534 case TRANSMITTER_UNIPHY_C:
535 case TRANSMITTER_UNIPHY_D:
536 case TRANSMITTER_UNIPHY_E:
537 case TRANSMITTER_UNIPHY_F:
538 case TRANSMITTER_TRAVIS_LCD:
541 return BP_RESULT_BADINPUT;
544 if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id))
545 return BP_RESULT_BADINPUT;
547 /* fill information based on the action */
548 switch (cntl->action) {
549 case TRANSMITTER_CONTROL_INIT:
550 if (dual_link_conn) {
551 /* on INIT this bit should be set according to the
553 * Bit0: dual link connector flag
554 * =0 connector is single link connector
555 * =1 connector is dual link connector
557 params.acConfig.fDualLinkConnector = 1;
560 /* connector object id */
562 cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
564 case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
565 /* votage swing and pre-emphsis */
566 params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
567 params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
570 if (dual_link_conn && cntl->multi_path)
571 /* on ENABLE/DISABLE this bit should be set according to
572 * actual timing (number of lanes)
573 * Bit0: dual link connector flag
574 * =0 connector is single link connector
575 * =1 connector is dual link connector
577 params.acConfig.fDualLinkConnector = 1;
580 if (LANE_COUNT_FOUR < cntl->lanes_number) {
581 /* on ENABLE/DISABLE this bit should be set according to
582 * actual timing (number of lanes)
583 * Bit0: dual link connector flag
584 * =0 connector is single link connector
585 * =1 connector is dual link connector
587 params.acConfig.fDualLinkConnector = 1;
589 /* link rate, half for dual link
590 * We need to convert from KHz units into 20KHz units
592 params.usPixelClock =
593 cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
595 /* link rate, half for dual link
596 * We need to convert from KHz units into 10KHz units
598 params.usPixelClock =
599 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
604 /* 00 - coherent mode
605 * 01 - incoherent mode
608 params.acConfig.fCoherentMode = cntl->coherent;
610 if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
611 || (TRANSMITTER_UNIPHY_D == cntl->transmitter)
612 || (TRANSMITTER_UNIPHY_F == cntl->transmitter))
613 /* Bit2: Transmitter Link selection
614 * =0 when bit0=0, single link A/C/E, when bit0=1,
616 * =1 when bit0=0, single link B/D/F, when bit0=1,
619 params.acConfig.ucLinkSel = 1;
621 if (ENGINE_ID_DIGB == cntl->engine_id)
622 /* Bit3: Transmitter data source selection
623 * =0 DIGA is data source.
624 * =1 DIGB is data source.
625 * This bit is only useful when ucAction= ATOM_ENABLE
627 params.acConfig.ucEncoderSel = 1;
629 /* Bit[7:6]: Transmitter selection
630 * =0 UNIPHY_ENCODER: UNIPHYA/B
631 * =1 UNIPHY1_ENCODER: UNIPHYC/D
632 * =2 UNIPHY2_ENCODER: UNIPHYE/F
635 params.acConfig.ucTransmitterSel =
636 (uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter);
638 params.ucLaneNum = (uint8_t)cntl->lanes_number;
640 params.acConfig.ucRefClkSource = (uint8_t)pll_id;
642 params.ucAction = (uint8_t)cntl->action;
644 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
645 result = BP_RESULT_OK;
650 static enum bp_result transmitter_control_v4(
651 struct bios_parser *bp,
652 struct bp_transmitter_control *cntl)
654 enum bp_result result = BP_RESULT_FAILURE;
655 DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 params;
656 uint32_t ref_clk_src_id;
657 enum connector_id conn_id =
658 dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
659 const struct command_table_helper *cmd = bp->cmd_helper;
661 memset(¶ms, 0, sizeof(params));
663 switch (cntl->transmitter) {
664 case TRANSMITTER_UNIPHY_A:
665 case TRANSMITTER_UNIPHY_B:
666 case TRANSMITTER_UNIPHY_C:
667 case TRANSMITTER_UNIPHY_D:
668 case TRANSMITTER_UNIPHY_E:
669 case TRANSMITTER_UNIPHY_F:
670 case TRANSMITTER_TRAVIS_LCD:
673 return BP_RESULT_BADINPUT;
676 if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id))
677 return BP_RESULT_BADINPUT;
679 switch (cntl->action) {
680 case TRANSMITTER_CONTROL_INIT:
682 if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
683 (CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
684 /* on INIT this bit should be set according to the
686 * Bit0: dual link connector flag
687 * =0 connector is single link connector
688 * =1 connector is dual link connector
690 params.acConfig.fDualLinkConnector = 1;
692 /* connector object id */
694 cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
697 case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
698 /* votage swing and pre-emphsis */
699 params.asMode.ucLaneSel = (uint8_t)(cntl->lane_select);
700 params.asMode.ucLaneSet = (uint8_t)(cntl->lane_settings);
703 if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
704 (CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
705 /* on ENABLE/DISABLE this bit should be set according to
706 * actual timing (number of lanes)
707 * Bit0: dual link connector flag
708 * =0 connector is single link connector
709 * =1 connector is dual link connector
711 params.acConfig.fDualLinkConnector = 1;
714 if (LANE_COUNT_FOUR < cntl->lanes_number)
715 /* link rate, half for dual link
716 * We need to convert from KHz units into 20KHz units
718 params.usPixelClock =
719 cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
721 /* link rate, half for dual link
722 * We need to convert from KHz units into 10KHz units
724 params.usPixelClock =
725 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
730 /* 00 - coherent mode
731 * 01 - incoherent mode
734 params.acConfig.fCoherentMode = cntl->coherent;
736 if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
737 || (TRANSMITTER_UNIPHY_D == cntl->transmitter)
738 || (TRANSMITTER_UNIPHY_F == cntl->transmitter))
739 /* Bit2: Transmitter Link selection
740 * =0 when bit0=0, single link A/C/E, when bit0=1,
742 * =1 when bit0=0, single link B/D/F, when bit0=1,
745 params.acConfig.ucLinkSel = 1;
747 if (ENGINE_ID_DIGB == cntl->engine_id)
748 /* Bit3: Transmitter data source selection
749 * =0 DIGA is data source.
750 * =1 DIGB is data source.
751 * This bit is only useful when ucAction= ATOM_ENABLE
753 params.acConfig.ucEncoderSel = 1;
755 /* Bit[7:6]: Transmitter selection
756 * =0 UNIPHY_ENCODER: UNIPHYA/B
757 * =1 UNIPHY1_ENCODER: UNIPHYC/D
758 * =2 UNIPHY2_ENCODER: UNIPHYE/F
761 params.acConfig.ucTransmitterSel =
762 (uint8_t)(cmd->transmitter_bp_to_atom(cntl->transmitter));
763 params.ucLaneNum = (uint8_t)(cntl->lanes_number);
764 params.acConfig.ucRefClkSource = (uint8_t)(ref_clk_src_id);
765 params.ucAction = (uint8_t)(cntl->action);
767 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
768 result = BP_RESULT_OK;
773 static enum bp_result transmitter_control_v1_5(
774 struct bios_parser *bp,
775 struct bp_transmitter_control *cntl)
777 enum bp_result result = BP_RESULT_FAILURE;
778 const struct command_table_helper *cmd = bp->cmd_helper;
779 DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 params;
781 memset(¶ms, 0, sizeof(params));
782 params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
783 params.ucAction = (uint8_t)cntl->action;
784 params.ucLaneNum = (uint8_t)cntl->lanes_number;
785 params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
788 cmd->signal_type_to_atom_dig_mode(cntl->signal);
789 params.asConfig.ucPhyClkSrcId =
790 cmd->clock_source_id_to_atom_phy_clk_src_id(cntl->pll_id);
791 /* 00 - coherent mode */
792 params.asConfig.ucCoherentMode = cntl->coherent;
793 params.asConfig.ucHPDSel =
794 cmd->hpd_sel_to_atom(cntl->hpd_sel);
795 params.ucDigEncoderSel =
796 cmd->dig_encoder_sel_to_atom(cntl->engine_id);
797 params.ucDPLaneSet = (uint8_t) cntl->lane_settings;
798 params.usSymClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10));
800 * In SI/TN case, caller have to set usPixelClock as following:
801 * DP mode: usPixelClock = DP_LINK_CLOCK/10
802 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
803 * DVI single link mode: usPixelClock = pixel clock
804 * DVI dual link mode: usPixelClock = pixel clock
805 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
806 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
807 * LVDS mode: usPixelClock = pixel clock
810 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
811 result = BP_RESULT_OK;
816 static enum bp_result transmitter_control_v1_6(
817 struct bios_parser *bp,
818 struct bp_transmitter_control *cntl)
820 enum bp_result result = BP_RESULT_FAILURE;
821 const struct command_table_helper *cmd = bp->cmd_helper;
822 DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params;
824 memset(¶ms, 0, sizeof(params));
825 params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
826 params.ucAction = (uint8_t)cntl->action;
828 if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
829 params.ucDPLaneSet = (uint8_t)cntl->lane_settings;
831 params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal);
833 params.ucLaneNum = (uint8_t)cntl->lanes_number;
834 params.ucHPDSel = cmd->hpd_sel_to_atom(cntl->hpd_sel);
835 params.ucDigEncoderSel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);
836 params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
837 params.ulSymClock = cntl->pixel_clock/10;
840 * In SI/TN case, caller have to set usPixelClock as following:
841 * DP mode: usPixelClock = DP_LINK_CLOCK/10
842 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
843 * DVI single link mode: usPixelClock = pixel clock
844 * DVI dual link mode: usPixelClock = pixel clock
845 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
846 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
847 * LVDS mode: usPixelClock = pixel clock
849 switch (cntl->signal) {
850 case SIGNAL_TYPE_HDMI_TYPE_A:
851 switch (cntl->color_depth) {
852 case COLOR_DEPTH_101010:
854 cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24);
856 case COLOR_DEPTH_121212:
858 cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24);
860 case COLOR_DEPTH_161616:
862 cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24);
872 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
873 result = BP_RESULT_OK;
877 /*******************************************************************************
878 ********************************************************************************
882 ********************************************************************************
883 *******************************************************************************/
885 static enum bp_result set_pixel_clock_v3(
886 struct bios_parser *bp,
887 struct bp_pixel_clock_parameters *bp_params);
888 static enum bp_result set_pixel_clock_v5(
889 struct bios_parser *bp,
890 struct bp_pixel_clock_parameters *bp_params);
891 static enum bp_result set_pixel_clock_v6(
892 struct bios_parser *bp,
893 struct bp_pixel_clock_parameters *bp_params);
894 static enum bp_result set_pixel_clock_v7(
895 struct bios_parser *bp,
896 struct bp_pixel_clock_parameters *bp_params);
898 static void init_set_pixel_clock(struct bios_parser *bp)
900 switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
902 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3;
905 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5;
908 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6;
911 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
914 dm_output_to_console("Don't have set_pixel_clock for v%d\n",
915 BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
916 bp->cmd_tbl.set_pixel_clock = NULL;
921 static enum bp_result set_pixel_clock_v3(
922 struct bios_parser *bp,
923 struct bp_pixel_clock_parameters *bp_params)
925 enum bp_result result = BP_RESULT_FAILURE;
926 PIXEL_CLOCK_PARAMETERS_V3 *params;
927 SET_PIXEL_CLOCK_PS_ALLOCATION allocation;
929 memset(&allocation, 0, sizeof(allocation));
931 if (CLOCK_SOURCE_ID_PLL1 == bp_params->pll_id)
932 allocation.sPCLKInput.ucPpll = ATOM_PPLL1;
933 else if (CLOCK_SOURCE_ID_PLL2 == bp_params->pll_id)
934 allocation.sPCLKInput.ucPpll = ATOM_PPLL2;
936 return BP_RESULT_BADINPUT;
938 allocation.sPCLKInput.usRefDiv =
939 cpu_to_le16((uint16_t)bp_params->reference_divider);
940 allocation.sPCLKInput.usFbDiv =
941 cpu_to_le16((uint16_t)bp_params->feedback_divider);
942 allocation.sPCLKInput.ucFracFbDiv =
943 (uint8_t)bp_params->fractional_feedback_divider;
944 allocation.sPCLKInput.ucPostDiv =
945 (uint8_t)bp_params->pixel_clock_post_divider;
947 /* We need to convert from KHz units into 10KHz units */
948 allocation.sPCLKInput.usPixelClock =
949 cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
951 params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput;
952 params->ucTransmitterId =
953 bp->cmd_helper->encoder_id_to_atom(
954 dal_graphics_object_id_get_encoder_id(
955 bp_params->encoder_object_id));
956 params->ucEncoderMode =
957 (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
958 bp_params->signal_type, false));
960 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
961 params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
963 if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK)
964 params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK;
966 if (CONTROLLER_ID_D1 != bp_params->controller_id)
967 params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;
969 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation))
970 result = BP_RESULT_OK;
975 #ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V5
976 /* video bios did not define this: */
977 typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V5 {
978 PIXEL_CLOCK_PARAMETERS_V5 sPCLKInput;
979 /* Caller doesn't need to init this portion */
980 ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
981 } SET_PIXEL_CLOCK_PS_ALLOCATION_V5;
984 #ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V6
985 /* video bios did not define this: */
986 typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V6 {
987 PIXEL_CLOCK_PARAMETERS_V6 sPCLKInput;
988 /* Caller doesn't need to init this portion */
989 ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
990 } SET_PIXEL_CLOCK_PS_ALLOCATION_V6;
993 static enum bp_result set_pixel_clock_v5(
994 struct bios_parser *bp,
995 struct bp_pixel_clock_parameters *bp_params)
997 enum bp_result result = BP_RESULT_FAILURE;
998 SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk;
999 uint8_t controller_id;
1002 memset(&clk, 0, sizeof(clk));
1004 if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1005 && bp->cmd_helper->controller_id_to_atom(
1006 bp_params->controller_id, &controller_id)) {
1007 clk.sPCLKInput.ucCRTC = controller_id;
1008 clk.sPCLKInput.ucPpll = (uint8_t)pll_id;
1009 clk.sPCLKInput.ucRefDiv =
1010 (uint8_t)(bp_params->reference_divider);
1011 clk.sPCLKInput.usFbDiv =
1012 cpu_to_le16((uint16_t)(bp_params->feedback_divider));
1013 clk.sPCLKInput.ulFbDivDecFrac =
1014 cpu_to_le32(bp_params->fractional_feedback_divider);
1015 clk.sPCLKInput.ucPostDiv =
1016 (uint8_t)(bp_params->pixel_clock_post_divider);
1017 clk.sPCLKInput.ucTransmitterID =
1018 bp->cmd_helper->encoder_id_to_atom(
1019 dal_graphics_object_id_get_encoder_id(
1020 bp_params->encoder_object_id));
1021 clk.sPCLKInput.ucEncoderMode =
1022 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1023 bp_params->signal_type, false);
1025 /* We need to convert from KHz units into 10KHz units */
1026 clk.sPCLKInput.usPixelClock =
1027 cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
1029 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1030 clk.sPCLKInput.ucMiscInfo |=
1031 PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
1033 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1034 clk.sPCLKInput.ucMiscInfo |=
1035 PIXEL_CLOCK_MISC_REF_DIV_SRC;
1037 /* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp
1038 * =1:30bpp, =2:32bpp
1039 * driver choose program it itself, i.e. here we program it
1040 * to 888 by default.
1043 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1044 result = BP_RESULT_OK;
1050 static enum bp_result set_pixel_clock_v6(
1051 struct bios_parser *bp,
1052 struct bp_pixel_clock_parameters *bp_params)
1054 enum bp_result result = BP_RESULT_FAILURE;
1055 SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk;
1056 uint8_t controller_id;
1059 memset(&clk, 0, sizeof(clk));
1061 if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1062 && bp->cmd_helper->controller_id_to_atom(
1063 bp_params->controller_id, &controller_id)) {
1064 /* Note: VBIOS still wants to use ucCRTC name which is now
1066 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1068 * target the pixel clock to drive the CRTC timing.
1069 * ULONG ulPixelClock:24;
1070 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1072 * ATOM_CRTC1~6, indicate the CRTC controller to
1074 * drive the pixel clock. not used for DCPLL case.
1075 *}CRTC_PIXEL_CLOCK_FREQ;
1078 * pixel clock and CRTC id frequency
1079 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1080 * ULONG ulDispEngClkFreq; dispclk frequency
1083 clk.sPCLKInput.ulCrtcPclkFreq.ucCRTC = controller_id;
1084 clk.sPCLKInput.ucPpll = (uint8_t) pll_id;
1085 clk.sPCLKInput.ucRefDiv =
1086 (uint8_t) bp_params->reference_divider;
1087 clk.sPCLKInput.usFbDiv =
1088 cpu_to_le16((uint16_t) bp_params->feedback_divider);
1089 clk.sPCLKInput.ulFbDivDecFrac =
1090 cpu_to_le32(bp_params->fractional_feedback_divider);
1091 clk.sPCLKInput.ucPostDiv =
1092 (uint8_t) bp_params->pixel_clock_post_divider;
1093 clk.sPCLKInput.ucTransmitterID =
1094 bp->cmd_helper->encoder_id_to_atom(
1095 dal_graphics_object_id_get_encoder_id(
1096 bp_params->encoder_object_id));
1097 clk.sPCLKInput.ucEncoderMode =
1098 (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(
1099 bp_params->signal_type, false);
1101 /* We need to convert from KHz units into 10KHz units */
1102 clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock =
1103 cpu_to_le32(bp_params->target_pixel_clock / 10);
1105 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {
1106 clk.sPCLKInput.ucMiscInfo |=
1107 PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL;
1110 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) {
1111 clk.sPCLKInput.ucMiscInfo |=
1112 PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
1115 /* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0:
1116 * 24bpp =1:30bpp, =2:32bpp
1117 * driver choose program it itself, i.e. here we pass required
1118 * target rate that includes deep color.
1121 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1122 result = BP_RESULT_OK;
1128 static enum bp_result set_pixel_clock_v7(
1129 struct bios_parser *bp,
1130 struct bp_pixel_clock_parameters *bp_params)
1132 enum bp_result result = BP_RESULT_FAILURE;
1133 PIXEL_CLOCK_PARAMETERS_V7 clk;
1134 uint8_t controller_id;
1137 memset(&clk, 0, sizeof(clk));
1139 if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1140 && bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &controller_id)) {
1141 /* Note: VBIOS still wants to use ucCRTC name which is now
1143 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1145 * target the pixel clock to drive the CRTC timing.
1146 * ULONG ulPixelClock:24;
1147 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1149 * ATOM_CRTC1~6, indicate the CRTC controller to
1151 * drive the pixel clock. not used for DCPLL case.
1152 *}CRTC_PIXEL_CLOCK_FREQ;
1155 * pixel clock and CRTC id frequency
1156 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1157 * ULONG ulDispEngClkFreq; dispclk frequency
1160 clk.ucCRTC = controller_id;
1161 clk.ucPpll = (uint8_t) pll_id;
1162 clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id));
1163 clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false);
1165 /* We need to convert from KHz units into 10KHz units */
1166 clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock * 10);
1168 clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);
1170 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1171 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
1173 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1174 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC;
1176 if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)
1177 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;
1179 if (bp_params->flags.SUPPORT_YUV_420)
1180 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;
1182 if (bp_params->flags.SET_XTALIN_REF_SRC)
1183 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;
1185 if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)
1186 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;
1188 if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1189 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
1191 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1192 result = BP_RESULT_OK;
1197 /*******************************************************************************
1198 ********************************************************************************
1200 ** ENABLE PIXEL CLOCK SS
1202 ********************************************************************************
1203 *******************************************************************************/
1204 static enum bp_result enable_spread_spectrum_on_ppll_v1(
1205 struct bios_parser *bp,
1206 struct bp_spread_spectrum_parameters *bp_params,
1208 static enum bp_result enable_spread_spectrum_on_ppll_v2(
1209 struct bios_parser *bp,
1210 struct bp_spread_spectrum_parameters *bp_params,
1212 static enum bp_result enable_spread_spectrum_on_ppll_v3(
1213 struct bios_parser *bp,
1214 struct bp_spread_spectrum_parameters *bp_params,
1217 static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp)
1219 switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) {
1221 bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1222 enable_spread_spectrum_on_ppll_v1;
1225 bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1226 enable_spread_spectrum_on_ppll_v2;
1229 bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1230 enable_spread_spectrum_on_ppll_v3;
1233 dm_output_to_console("Don't have enable_spread_spectrum_on_ppll for v%d\n",
1234 BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL));
1235 bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL;
1240 static enum bp_result enable_spread_spectrum_on_ppll_v1(
1241 struct bios_parser *bp,
1242 struct bp_spread_spectrum_parameters *bp_params,
1245 enum bp_result result = BP_RESULT_FAILURE;
1246 ENABLE_SPREAD_SPECTRUM_ON_PPLL params;
1248 memset(¶ms, 0, sizeof(params));
1250 if ((enable == true) && (bp_params->percentage > 0))
1251 params.ucEnable = ATOM_ENABLE;
1253 params.ucEnable = ATOM_DISABLE;
1255 params.usSpreadSpectrumPercentage =
1256 cpu_to_le16((uint16_t)bp_params->percentage);
1257 params.ucSpreadSpectrumStep =
1258 (uint8_t)bp_params->ver1.step;
1259 params.ucSpreadSpectrumDelay =
1260 (uint8_t)bp_params->ver1.delay;
1261 /* convert back to unit of 10KHz */
1262 params.ucSpreadSpectrumRange =
1263 (uint8_t)(bp_params->ver1.range / 10000);
1265 if (bp_params->flags.EXTERNAL_SS)
1266 params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK;
1268 if (bp_params->flags.CENTER_SPREAD)
1269 params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE;
1271 if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1272 params.ucPpll = ATOM_PPLL1;
1273 else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1274 params.ucPpll = ATOM_PPLL2;
1276 BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1278 if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1279 result = BP_RESULT_OK;
1284 static enum bp_result enable_spread_spectrum_on_ppll_v2(
1285 struct bios_parser *bp,
1286 struct bp_spread_spectrum_parameters *bp_params,
1289 enum bp_result result = BP_RESULT_FAILURE;
1290 ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params;
1292 memset(¶ms, 0, sizeof(params));
1294 if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1295 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P1PLL;
1296 else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1297 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P2PLL;
1299 BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1301 if ((enable == true) && (bp_params->percentage > 0)) {
1302 params.ucEnable = ATOM_ENABLE;
1304 params.usSpreadSpectrumPercentage =
1305 cpu_to_le16((uint16_t)(bp_params->percentage));
1306 params.usSpreadSpectrumStep =
1307 cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1309 if (bp_params->flags.EXTERNAL_SS)
1310 params.ucSpreadSpectrumType |=
1311 ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD;
1313 if (bp_params->flags.CENTER_SPREAD)
1314 params.ucSpreadSpectrumType |=
1315 ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD;
1317 /* Both amounts need to be left shifted first before bit
1318 * comparison. Otherwise, the result will always be zero here
1320 params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1321 ((bp_params->ds.feedback_amount <<
1322 ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT) &
1323 ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK) |
1324 ((bp_params->ds.nfrac_amount <<
1325 ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
1326 ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK)));
1328 params.ucEnable = ATOM_DISABLE;
1330 if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1331 result = BP_RESULT_OK;
1336 static enum bp_result enable_spread_spectrum_on_ppll_v3(
1337 struct bios_parser *bp,
1338 struct bp_spread_spectrum_parameters *bp_params,
1341 enum bp_result result = BP_RESULT_FAILURE;
1342 ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params;
1344 memset(¶ms, 0, sizeof(params));
1346 switch (bp_params->pll_id) {
1347 case CLOCK_SOURCE_ID_PLL0:
1348 /* ATOM_PPLL_SS_TYPE_V3_P0PLL; this is pixel clock only,
1349 * not for SI display clock.
1351 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1353 case CLOCK_SOURCE_ID_PLL1:
1354 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL;
1357 case CLOCK_SOURCE_ID_PLL2:
1358 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL;
1361 case CLOCK_SOURCE_ID_DCPLL:
1362 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1366 BREAK_TO_DEBUGGER();
1367 /* Unexpected PLL value!! */
1371 if (enable == true) {
1372 params.ucEnable = ATOM_ENABLE;
1374 params.usSpreadSpectrumAmountFrac =
1375 cpu_to_le16((uint16_t)(bp_params->ds_frac_amount));
1376 params.usSpreadSpectrumStep =
1377 cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1379 if (bp_params->flags.EXTERNAL_SS)
1380 params.ucSpreadSpectrumType |=
1381 ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD;
1382 if (bp_params->flags.CENTER_SPREAD)
1383 params.ucSpreadSpectrumType |=
1384 ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD;
1386 /* Both amounts need to be left shifted first before bit
1387 * comparison. Otherwise, the result will always be zero here
1389 params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1390 ((bp_params->ds.feedback_amount <<
1391 ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT) &
1392 ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK) |
1393 ((bp_params->ds.nfrac_amount <<
1394 ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT) &
1395 ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK)));
1397 params.ucEnable = ATOM_DISABLE;
1399 if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1400 result = BP_RESULT_OK;
1405 /*******************************************************************************
1406 ********************************************************************************
1408 ** ADJUST DISPLAY PLL
1410 ********************************************************************************
1411 *******************************************************************************/
1413 static enum bp_result adjust_display_pll_v2(
1414 struct bios_parser *bp,
1415 struct bp_adjust_pixel_clock_parameters *bp_params);
1416 static enum bp_result adjust_display_pll_v3(
1417 struct bios_parser *bp,
1418 struct bp_adjust_pixel_clock_parameters *bp_params);
1420 static void init_adjust_display_pll(struct bios_parser *bp)
1422 switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) {
1424 bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2;
1427 bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3;
1430 dm_output_to_console("Don't have adjust_display_pll for v%d\n",
1431 BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll));
1432 bp->cmd_tbl.adjust_display_pll = NULL;
1437 static enum bp_result adjust_display_pll_v2(
1438 struct bios_parser *bp,
1439 struct bp_adjust_pixel_clock_parameters *bp_params)
1441 enum bp_result result = BP_RESULT_FAILURE;
1442 ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 };
1444 /* We need to convert from KHz units into 10KHz units and then convert
1445 * output pixel clock back 10KHz-->KHz */
1446 uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10;
1448 params.usPixelClock = cpu_to_le16((uint16_t)(pixel_clock_10KHz_in));
1449 params.ucTransmitterID =
1450 bp->cmd_helper->encoder_id_to_atom(
1451 dal_graphics_object_id_get_encoder_id(
1452 bp_params->encoder_object_id));
1453 params.ucEncodeMode =
1454 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1455 bp_params->signal_type, false);
1459 static enum bp_result adjust_display_pll_v3(
1460 struct bios_parser *bp,
1461 struct bp_adjust_pixel_clock_parameters *bp_params)
1463 enum bp_result result = BP_RESULT_FAILURE;
1464 ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 params;
1465 uint32_t pixel_clk_10_kHz_in = bp_params->pixel_clock / 10;
1467 memset(¶ms, 0, sizeof(params));
1469 /* We need to convert from KHz units into 10KHz units and then convert
1470 * output pixel clock back 10KHz-->KHz */
1471 params.sInput.usPixelClock = cpu_to_le16((uint16_t)pixel_clk_10_kHz_in);
1472 params.sInput.ucTransmitterID =
1473 bp->cmd_helper->encoder_id_to_atom(
1474 dal_graphics_object_id_get_encoder_id(
1475 bp_params->encoder_object_id));
1476 params.sInput.ucEncodeMode =
1477 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1478 bp_params->signal_type, false);
1480 if (bp_params->ss_enable == true)
1481 params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
1483 if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1484 params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
1486 if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
1487 /* Convert output pixel clock back 10KHz-->KHz: multiply
1488 * original pixel clock in KHz by ratio
1489 * [output pxlClk/input pxlClk] */
1490 uint64_t pixel_clk_10_khz_out =
1491 (uint64_t)le32_to_cpu(params.sOutput.ulDispPllFreq);
1492 uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
1494 if (pixel_clk_10_kHz_in != 0) {
1495 bp_params->adjusted_pixel_clock =
1496 div_u64(pixel_clk * pixel_clk_10_khz_out,
1497 pixel_clk_10_kHz_in);
1499 bp_params->adjusted_pixel_clock = 0;
1500 BREAK_TO_DEBUGGER();
1503 bp_params->reference_divider = params.sOutput.ucRefDiv;
1504 bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv;
1506 result = BP_RESULT_OK;
1512 /*******************************************************************************
1513 ********************************************************************************
1515 ** DAC ENCODER CONTROL
1517 ********************************************************************************
1518 *******************************************************************************/
1520 static enum bp_result dac1_encoder_control_v1(
1521 struct bios_parser *bp,
1523 uint32_t pixel_clock,
1524 uint8_t dac_standard);
1525 static enum bp_result dac2_encoder_control_v1(
1526 struct bios_parser *bp,
1528 uint32_t pixel_clock,
1529 uint8_t dac_standard);
1531 static void init_dac_encoder_control(struct bios_parser *bp)
1533 switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) {
1535 bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1;
1538 bp->cmd_tbl.dac1_encoder_control = NULL;
1541 switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) {
1543 bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1;
1546 bp->cmd_tbl.dac2_encoder_control = NULL;
1551 static void dac_encoder_control_prepare_params(
1552 DAC_ENCODER_CONTROL_PS_ALLOCATION *params,
1554 uint32_t pixel_clock,
1555 uint8_t dac_standard)
1557 params->ucDacStandard = dac_standard;
1559 params->ucAction = ATOM_ENABLE;
1561 params->ucAction = ATOM_DISABLE;
1563 /* We need to convert from KHz units into 10KHz units
1564 * it looks as if the TvControl do not care about pixel clock
1566 params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10));
1569 static enum bp_result dac1_encoder_control_v1(
1570 struct bios_parser *bp,
1572 uint32_t pixel_clock,
1573 uint8_t dac_standard)
1575 enum bp_result result = BP_RESULT_FAILURE;
1576 DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1578 dac_encoder_control_prepare_params(
1584 if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params))
1585 result = BP_RESULT_OK;
1590 static enum bp_result dac2_encoder_control_v1(
1591 struct bios_parser *bp,
1593 uint32_t pixel_clock,
1594 uint8_t dac_standard)
1596 enum bp_result result = BP_RESULT_FAILURE;
1597 DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1599 dac_encoder_control_prepare_params(
1605 if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params))
1606 result = BP_RESULT_OK;
1611 /*******************************************************************************
1612 ********************************************************************************
1614 ** DAC OUTPUT CONTROL
1616 ********************************************************************************
1617 *******************************************************************************/
1618 static enum bp_result dac1_output_control_v1(
1619 struct bios_parser *bp,
1621 static enum bp_result dac2_output_control_v1(
1622 struct bios_parser *bp,
1625 static void init_dac_output_control(struct bios_parser *bp)
1627 switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) {
1629 bp->cmd_tbl.dac1_output_control = dac1_output_control_v1;
1632 bp->cmd_tbl.dac1_output_control = NULL;
1635 switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) {
1637 bp->cmd_tbl.dac2_output_control = dac2_output_control_v1;
1640 bp->cmd_tbl.dac2_output_control = NULL;
1645 static enum bp_result dac1_output_control_v1(
1646 struct bios_parser *bp, bool enable)
1648 enum bp_result result = BP_RESULT_FAILURE;
1649 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
1652 params.ucAction = ATOM_ENABLE;
1654 params.ucAction = ATOM_DISABLE;
1656 if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params))
1657 result = BP_RESULT_OK;
1662 static enum bp_result dac2_output_control_v1(
1663 struct bios_parser *bp, bool enable)
1665 enum bp_result result = BP_RESULT_FAILURE;
1666 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
1669 params.ucAction = ATOM_ENABLE;
1671 params.ucAction = ATOM_DISABLE;
1673 if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params))
1674 result = BP_RESULT_OK;
1679 /*******************************************************************************
1680 ********************************************************************************
1684 ********************************************************************************
1685 *******************************************************************************/
1687 static enum bp_result set_crtc_using_dtd_timing_v3(
1688 struct bios_parser *bp,
1689 struct bp_hw_crtc_timing_parameters *bp_params);
1690 static enum bp_result set_crtc_timing_v1(
1691 struct bios_parser *bp,
1692 struct bp_hw_crtc_timing_parameters *bp_params);
1694 static void init_set_crtc_timing(struct bios_parser *bp)
1696 uint32_t dtd_version =
1697 BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming);
1698 if (dtd_version > 2)
1699 switch (dtd_version) {
1701 bp->cmd_tbl.set_crtc_timing =
1702 set_crtc_using_dtd_timing_v3;
1705 dm_output_to_console("Don't have set_crtc_timing for dtd v%d\n",
1707 bp->cmd_tbl.set_crtc_timing = NULL;
1711 switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) {
1713 bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1;
1716 dm_output_to_console("Don't have set_crtc_timing for v%d\n",
1717 BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing));
1718 bp->cmd_tbl.set_crtc_timing = NULL;
1723 static enum bp_result set_crtc_timing_v1(
1724 struct bios_parser *bp,
1725 struct bp_hw_crtc_timing_parameters *bp_params)
1727 enum bp_result result = BP_RESULT_FAILURE;
1728 SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0};
1729 uint8_t atom_controller_id;
1731 if (bp->cmd_helper->controller_id_to_atom(
1732 bp_params->controller_id, &atom_controller_id))
1733 params.ucCRTC = atom_controller_id;
1735 params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total));
1736 params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable));
1737 params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start));
1738 params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width));
1739 params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total));
1740 params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable));
1741 params.usV_SyncStart =
1742 cpu_to_le16((uint16_t)(bp_params->v_sync_start));
1743 params.usV_SyncWidth =
1744 cpu_to_le16((uint16_t)(bp_params->v_sync_width));
1746 /* VBIOS does not expect any value except zero into this call, for
1747 * underscan use another entry ProgramOverscan call but when mode
1748 * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok,
1749 * but when same ,but 60 Hz there is corruption
1750 * DAL1 does not allow the mode 1776x1000@60
1752 params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right;
1753 params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left;
1754 params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom;
1755 params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top;
1757 if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
1758 params.susModeMiscInfo.usAccess =
1759 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
1761 if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
1762 params.susModeMiscInfo.usAccess =
1763 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
1765 if (bp_params->flags.INTERLACE) {
1766 params.susModeMiscInfo.usAccess =
1767 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
1769 /* original DAL code has this condition to apply tis for
1770 * non-TV/CV only due to complex MV testing for possible
1772 * if (pACParameters->signal != SignalType_YPbPr &&
1773 * pACParameters->signal != SignalType_Composite &&
1774 * pACParameters->signal != SignalType_SVideo)
1776 /* HW will deduct 0.5 line from 2nd feild.
1777 * i.e. for 1080i, it is 2 lines for 1st field, 2.5
1778 * lines for the 2nd feild. we need input as 5 instead
1779 * of 4, but it is 4 either from Edid data
1780 * (spec CEA 861) or CEA timing table.
1782 params.usV_SyncStart =
1783 cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1));
1786 if (bp_params->flags.HORZ_COUNT_BY_TWO)
1787 params.susModeMiscInfo.usAccess =
1788 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
1790 if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params))
1791 result = BP_RESULT_OK;
1796 static enum bp_result set_crtc_using_dtd_timing_v3(
1797 struct bios_parser *bp,
1798 struct bp_hw_crtc_timing_parameters *bp_params)
1800 enum bp_result result = BP_RESULT_FAILURE;
1801 SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0};
1802 uint8_t atom_controller_id;
1804 if (bp->cmd_helper->controller_id_to_atom(
1805 bp_params->controller_id, &atom_controller_id))
1806 params.ucCRTC = atom_controller_id;
1808 /* bios usH_Size wants h addressable size */
1809 params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable);
1810 /* bios usH_Blanking_Time wants borders included in blanking */
1811 params.usH_Blanking_Time =
1812 cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable));
1813 /* bios usV_Size wants v addressable size */
1814 params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable);
1815 /* bios usV_Blanking_Time wants borders included in blanking */
1816 params.usV_Blanking_Time =
1817 cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable));
1818 /* bios usHSyncOffset is the offset from the end of h addressable,
1819 * our horizontalSyncStart is the offset from the beginning
1820 * of h addressable */
1821 params.usH_SyncOffset =
1822 cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable));
1823 params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);
1824 /* bios usHSyncOffset is the offset from the end of v addressable,
1825 * our verticalSyncStart is the offset from the beginning of
1827 params.usV_SyncOffset =
1828 cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable));
1829 params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);
1831 /* we assume that overscan from original timing does not get bigger
1833 * we will program all the borders in the Set CRTC Overscan call below
1836 if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
1837 params.susModeMiscInfo.usAccess =
1838 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
1840 if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
1841 params.susModeMiscInfo.usAccess =
1842 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
1844 if (bp_params->flags.INTERLACE) {
1845 params.susModeMiscInfo.usAccess =
1846 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
1848 /* original DAL code has this condition to apply this
1849 * for non-TV/CV only
1850 * due to complex MV testing for possible impact
1851 * if ( pACParameters->signal != SignalType_YPbPr &&
1852 * pACParameters->signal != SignalType_Composite &&
1853 * pACParameters->signal != SignalType_SVideo)
1856 /* HW will deduct 0.5 line from 2nd feild.
1857 * i.e. for 1080i, it is 2 lines for 1st field,
1858 * 2.5 lines for the 2nd feild. we need input as 5
1860 * but it is 4 either from Edid data (spec CEA 861)
1861 * or CEA timing table.
1863 params.usV_SyncOffset =
1864 cpu_to_le16(le16_to_cpu(params.usV_SyncOffset) + 1);
1869 if (bp_params->flags.HORZ_COUNT_BY_TWO)
1870 params.susModeMiscInfo.usAccess =
1871 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
1873 if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params))
1874 result = BP_RESULT_OK;
1879 /*******************************************************************************
1880 ********************************************************************************
1882 ** SELECT CRTC SOURCE
1884 ********************************************************************************
1885 *******************************************************************************/
1887 static enum bp_result select_crtc_source_v2(
1888 struct bios_parser *bp,
1889 struct bp_crtc_source_select *bp_params);
1890 static enum bp_result select_crtc_source_v3(
1891 struct bios_parser *bp,
1892 struct bp_crtc_source_select *bp_params);
1894 static void init_select_crtc_source(struct bios_parser *bp)
1896 switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) {
1898 bp->cmd_tbl.select_crtc_source = select_crtc_source_v2;
1901 bp->cmd_tbl.select_crtc_source = select_crtc_source_v3;
1904 dm_output_to_console("Don't select_crtc_source enable_crtc for v%d\n",
1905 BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source));
1906 bp->cmd_tbl.select_crtc_source = NULL;
1911 static enum bp_result select_crtc_source_v2(
1912 struct bios_parser *bp,
1913 struct bp_crtc_source_select *bp_params)
1915 enum bp_result result = BP_RESULT_FAILURE;
1916 SELECT_CRTC_SOURCE_PARAMETERS_V2 params;
1917 uint8_t atom_controller_id;
1918 uint32_t atom_engine_id;
1919 enum signal_type s = bp_params->signal;
1921 memset(¶ms, 0, sizeof(params));
1923 /* set controller id */
1924 if (bp->cmd_helper->controller_id_to_atom(
1925 bp_params->controller_id, &atom_controller_id))
1926 params.ucCRTC = atom_controller_id;
1928 return BP_RESULT_FAILURE;
1930 /* set encoder id */
1931 if (bp->cmd_helper->engine_bp_to_atom(
1932 bp_params->engine_id, &atom_engine_id))
1933 params.ucEncoderID = (uint8_t)atom_engine_id;
1935 return BP_RESULT_FAILURE;
1937 if (SIGNAL_TYPE_EDP == s ||
1938 (SIGNAL_TYPE_DISPLAY_PORT == s &&
1939 SIGNAL_TYPE_LVDS == bp_params->sink_signal))
1940 s = SIGNAL_TYPE_LVDS;
1942 params.ucEncodeMode =
1943 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1944 s, bp_params->enable_dp_audio);
1946 if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
1947 result = BP_RESULT_OK;
1952 static enum bp_result select_crtc_source_v3(
1953 struct bios_parser *bp,
1954 struct bp_crtc_source_select *bp_params)
1956 bool result = BP_RESULT_FAILURE;
1957 SELECT_CRTC_SOURCE_PARAMETERS_V3 params;
1958 uint8_t atom_controller_id;
1959 uint32_t atom_engine_id;
1960 enum signal_type s = bp_params->signal;
1962 memset(¶ms, 0, sizeof(params));
1964 if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
1965 &atom_controller_id))
1966 params.ucCRTC = atom_controller_id;
1970 if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id,
1972 params.ucEncoderID = (uint8_t)atom_engine_id;
1976 if (SIGNAL_TYPE_EDP == s ||
1977 (SIGNAL_TYPE_DISPLAY_PORT == s &&
1978 SIGNAL_TYPE_LVDS == bp_params->sink_signal))
1979 s = SIGNAL_TYPE_LVDS;
1981 params.ucEncodeMode =
1982 bp->cmd_helper->encoder_mode_bp_to_atom(
1983 s, bp_params->enable_dp_audio);
1984 /* Needed for VBIOS Random Spatial Dithering feature */
1985 params.ucDstBpc = (uint8_t)(bp_params->display_output_bit_depth);
1987 if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
1988 result = BP_RESULT_OK;
1993 /*******************************************************************************
1994 ********************************************************************************
1998 ********************************************************************************
1999 *******************************************************************************/
2001 static enum bp_result enable_crtc_v1(
2002 struct bios_parser *bp,
2003 enum controller_id controller_id,
2006 static void init_enable_crtc(struct bios_parser *bp)
2008 switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) {
2010 bp->cmd_tbl.enable_crtc = enable_crtc_v1;
2013 dm_output_to_console("Don't have enable_crtc for v%d\n",
2014 BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC));
2015 bp->cmd_tbl.enable_crtc = NULL;
2020 static enum bp_result enable_crtc_v1(
2021 struct bios_parser *bp,
2022 enum controller_id controller_id,
2025 bool result = BP_RESULT_FAILURE;
2026 ENABLE_CRTC_PARAMETERS params = {0};
2029 if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))
2032 return BP_RESULT_BADINPUT;
2035 params.ucEnable = ATOM_ENABLE;
2037 params.ucEnable = ATOM_DISABLE;
2039 if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params))
2040 result = BP_RESULT_OK;
2045 /*******************************************************************************
2046 ********************************************************************************
2048 ** ENABLE CRTC MEM REQ
2050 ********************************************************************************
2051 *******************************************************************************/
2053 static enum bp_result enable_crtc_mem_req_v1(
2054 struct bios_parser *bp,
2055 enum controller_id controller_id,
2058 static void init_enable_crtc_mem_req(struct bios_parser *bp)
2060 switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) {
2062 bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1;
2065 bp->cmd_tbl.enable_crtc_mem_req = NULL;
2070 static enum bp_result enable_crtc_mem_req_v1(
2071 struct bios_parser *bp,
2072 enum controller_id controller_id,
2075 bool result = BP_RESULT_BADINPUT;
2076 ENABLE_CRTC_PARAMETERS params = {0};
2079 if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) {
2083 params.ucEnable = ATOM_ENABLE;
2085 params.ucEnable = ATOM_DISABLE;
2087 if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params))
2088 result = BP_RESULT_OK;
2090 result = BP_RESULT_FAILURE;
2096 /*******************************************************************************
2097 ********************************************************************************
2101 ********************************************************************************
2102 *******************************************************************************/
2104 static enum bp_result program_clock_v5(
2105 struct bios_parser *bp,
2106 struct bp_pixel_clock_parameters *bp_params);
2107 static enum bp_result program_clock_v6(
2108 struct bios_parser *bp,
2109 struct bp_pixel_clock_parameters *bp_params);
2111 static void init_program_clock(struct bios_parser *bp)
2113 switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
2115 bp->cmd_tbl.program_clock = program_clock_v5;
2118 bp->cmd_tbl.program_clock = program_clock_v6;
2121 dm_output_to_console("Don't have program_clock for v%d\n",
2122 BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
2123 bp->cmd_tbl.program_clock = NULL;
2128 static enum bp_result program_clock_v5(
2129 struct bios_parser *bp,
2130 struct bp_pixel_clock_parameters *bp_params)
2132 enum bp_result result = BP_RESULT_FAILURE;
2134 SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params;
2135 uint32_t atom_pll_id;
2137 memset(¶ms, 0, sizeof(params));
2138 if (!bp->cmd_helper->clock_source_id_to_atom(
2139 bp_params->pll_id, &atom_pll_id)) {
2140 BREAK_TO_DEBUGGER(); /* Invalid Inpute!! */
2141 return BP_RESULT_BADINPUT;
2144 /* We need to convert from KHz units into 10KHz units */
2145 params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id;
2146 params.sPCLKInput.usPixelClock =
2147 cpu_to_le16((uint16_t) (bp_params->target_pixel_clock / 10));
2148 params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID;
2150 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2151 params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2153 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params))
2154 result = BP_RESULT_OK;
2159 static enum bp_result program_clock_v6(
2160 struct bios_parser *bp,
2161 struct bp_pixel_clock_parameters *bp_params)
2163 enum bp_result result = BP_RESULT_FAILURE;
2165 SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params;
2166 uint32_t atom_pll_id;
2168 memset(¶ms, 0, sizeof(params));
2170 if (!bp->cmd_helper->clock_source_id_to_atom(
2171 bp_params->pll_id, &atom_pll_id)) {
2172 BREAK_TO_DEBUGGER(); /*Invalid Input!!*/
2173 return BP_RESULT_BADINPUT;
2176 /* We need to convert from KHz units into 10KHz units */
2177 params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id;
2178 params.sPCLKInput.ulDispEngClkFreq =
2179 cpu_to_le32(bp_params->target_pixel_clock / 10);
2181 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2182 params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2184 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) {
2185 /* True display clock is returned by VBIOS if DFS bypass
2187 bp_params->dfs_bypass_display_clock =
2188 (uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10);
2189 result = BP_RESULT_OK;
2195 /*******************************************************************************
2196 ********************************************************************************
2198 ** EXTERNAL ENCODER CONTROL
2200 ********************************************************************************
2201 *******************************************************************************/
2203 static enum bp_result external_encoder_control_v3(
2204 struct bios_parser *bp,
2205 struct bp_external_encoder_control *cntl);
2207 static void init_external_encoder_control(
2208 struct bios_parser *bp)
2210 switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) {
2212 bp->cmd_tbl.external_encoder_control =
2213 external_encoder_control_v3;
2216 bp->cmd_tbl.external_encoder_control = NULL;
2221 static enum bp_result external_encoder_control_v3(
2222 struct bios_parser *bp,
2223 struct bp_external_encoder_control *cntl)
2225 enum bp_result result = BP_RESULT_FAILURE;
2227 /* we need use _PS_Alloc struct */
2228 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 params;
2229 EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 *cntl_params;
2230 struct graphics_object_id encoder;
2231 bool is_input_signal_dp = false;
2233 memset(¶ms, 0, sizeof(params));
2235 cntl_params = ¶ms.sExtEncoder;
2237 encoder = cntl->encoder_id;
2239 /* check if encoder supports external encoder control table */
2240 switch (dal_graphics_object_id_get_encoder_id(encoder)) {
2241 case ENCODER_ID_EXTERNAL_NUTMEG:
2242 case ENCODER_ID_EXTERNAL_TRAVIS:
2243 is_input_signal_dp = true;
2247 BREAK_TO_DEBUGGER();
2248 return BP_RESULT_BADINPUT;
2251 /* Fill information based on the action
2253 * Bit[6:4]: indicate external encoder, applied to all functions.
2254 * =0: external encoder1, mapped to external encoder enum id1
2255 * =1: external encoder2, mapped to external encoder enum id2
2259 * EnumId_Unknown = 0,
2264 cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4);
2266 switch (cntl->action) {
2267 case EXTERNAL_ENCODER_CONTROL_INIT:
2268 /* output display connector type. Only valid in encoder
2270 cntl_params->usConnectorId =
2271 cpu_to_le16((uint16_t)cntl->connector_obj_id.id);
2273 case EXTERNAL_ENCODER_CONTROL_SETUP:
2274 /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in
2276 * output display device pixel clock frequency in unit of 10KHz.
2277 * Only valid in setup and enableoutput
2279 cntl_params->usPixelClock =
2280 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2281 /* Indicate display output signal type drive by external
2282 * encoder, only valid in setup and enableoutput */
2283 cntl_params->ucEncoderMode =
2284 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2285 cntl->signal, false);
2287 if (is_input_signal_dp) {
2288 /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz,
2289 * only valid in encoder setup with DP mode. */
2290 if (LINK_RATE_HIGH == cntl->link_rate)
2291 cntl_params->ucConfig |= 1;
2292 /* output color depth Indicate encoder data bpc format
2293 * in DP mode, only valid in encoder setup in DP mode.
2295 cntl_params->ucBitPerColor =
2296 (uint8_t)(cntl->color_depth);
2298 /* Indicate how many lanes used by external encoder, only valid
2299 * in encoder setup and enableoutput. */
2300 cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);
2302 case EXTERNAL_ENCODER_CONTROL_ENABLE:
2303 cntl_params->usPixelClock =
2304 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2305 cntl_params->ucEncoderMode =
2306 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2307 cntl->signal, false);
2308 cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number;
2314 cntl_params->ucAction = (uint8_t)cntl->action;
2316 if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params))
2317 result = BP_RESULT_OK;
2322 /*******************************************************************************
2323 ********************************************************************************
2325 ** ENABLE DISPLAY POWER GATING
2327 ********************************************************************************
2328 *******************************************************************************/
2330 static enum bp_result enable_disp_power_gating_v2_1(
2331 struct bios_parser *bp,
2332 enum controller_id crtc_id,
2333 enum bp_pipe_control_action action);
2335 static void init_enable_disp_power_gating(
2336 struct bios_parser *bp)
2338 switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) {
2340 bp->cmd_tbl.enable_disp_power_gating =
2341 enable_disp_power_gating_v2_1;
2344 dm_output_to_console("Don't enable_disp_power_gating enable_crtc for v%d\n",
2345 BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating));
2346 bp->cmd_tbl.enable_disp_power_gating = NULL;
2351 static enum bp_result enable_disp_power_gating_v2_1(
2352 struct bios_parser *bp,
2353 enum controller_id crtc_id,
2354 enum bp_pipe_control_action action)
2356 enum bp_result result = BP_RESULT_FAILURE;
2358 ENABLE_DISP_POWER_GATING_PS_ALLOCATION params = {0};
2359 uint8_t atom_crtc_id;
2361 if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))
2362 params.ucDispPipeId = atom_crtc_id;
2364 return BP_RESULT_BADINPUT;
2367 bp->cmd_helper->disp_power_gating_action_to_atom(action);
2369 if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params))
2370 result = BP_RESULT_OK;
2375 /*******************************************************************************
2376 ********************************************************************************
2380 ********************************************************************************
2381 *******************************************************************************/
2382 static enum bp_result set_dce_clock_v2_1(
2383 struct bios_parser *bp,
2384 struct bp_set_dce_clock_parameters *bp_params);
2386 static void init_set_dce_clock(struct bios_parser *bp)
2388 switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) {
2390 bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
2393 dm_output_to_console("Don't have set_dce_clock for v%d\n",
2394 BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock));
2395 bp->cmd_tbl.set_dce_clock = NULL;
2400 static enum bp_result set_dce_clock_v2_1(
2401 struct bios_parser *bp,
2402 struct bp_set_dce_clock_parameters *bp_params)
2404 enum bp_result result = BP_RESULT_FAILURE;
2406 SET_DCE_CLOCK_PS_ALLOCATION_V2_1 params;
2407 uint32_t atom_pll_id;
2408 uint32_t atom_clock_type;
2409 const struct command_table_helper *cmd = bp->cmd_helper;
2411 memset(¶ms, 0, sizeof(params));
2413 if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||
2414 !cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type))
2415 return BP_RESULT_BADINPUT;
2417 params.asParam.ucDCEClkSrc = atom_pll_id;
2418 params.asParam.ucDCEClkType = atom_clock_type;
2420 if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {
2421 if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)
2422 params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;
2424 if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)
2425 params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;
2427 if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)
2428 params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;
2430 if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)
2431 params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;
2434 /* only program clock frequency if display clock is used; VBIOS will program DPREFCLK */
2435 /* We need to convert from KHz units into 10KHz units */
2436 params.asParam.ulDCEClkFreq = cpu_to_le32(bp_params->target_clock_frequency / 10);
2438 if (EXEC_BIOS_CMD_TABLE(SetDCEClock, params)) {
2439 /* Convert from 10KHz units back to KHz */
2440 bp_params->target_clock_frequency = le32_to_cpu(params.asParam.ulDCEClkFreq) * 10;
2441 result = BP_RESULT_OK;