2433 lines · c
1/*2 * Copyright 2012-15 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include "dm_services.h"27#include "amdgpu.h"28#include "atom.h"29 30#include "include/bios_parser_interface.h"31 32#include "command_table.h"33#include "command_table_helper.h"34#include "bios_parser_helper.h"35#include "bios_parser_types_internal.h"36 37#define EXEC_BIOS_CMD_TABLE(command, params)\38 (amdgpu_atom_execute_table(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \39 GetIndexIntoMasterTable(COMMAND, command), \40 (uint32_t *)¶ms, sizeof(params)) == 0)41 42#define BIOS_CMD_TABLE_REVISION(command, frev, crev)\43 amdgpu_atom_parse_cmd_header(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \44 GetIndexIntoMasterTable(COMMAND, command), &frev, &crev)45 46#define BIOS_CMD_TABLE_PARA_REVISION(command)\47 bios_cmd_table_para_revision(bp->base.ctx->driver_context, \48 GetIndexIntoMasterTable(COMMAND, command))49 50static void init_dig_encoder_control(struct bios_parser *bp);51static void init_transmitter_control(struct bios_parser *bp);52static void init_set_pixel_clock(struct bios_parser *bp);53static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp);54static void init_adjust_display_pll(struct bios_parser *bp);55static void init_dac_encoder_control(struct bios_parser *bp);56static void init_dac_output_control(struct bios_parser *bp);57static void init_set_crtc_timing(struct bios_parser *bp);58static void init_enable_crtc(struct bios_parser *bp);59static void init_enable_crtc_mem_req(struct bios_parser *bp);60static void init_external_encoder_control(struct bios_parser *bp);61static void init_enable_disp_power_gating(struct bios_parser *bp);62static void init_program_clock(struct bios_parser *bp);63static void init_set_dce_clock(struct bios_parser *bp);64 65void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)66{67 init_dig_encoder_control(bp);68 init_transmitter_control(bp);69 init_set_pixel_clock(bp);70 init_enable_spread_spectrum_on_ppll(bp);71 init_adjust_display_pll(bp);72 init_dac_encoder_control(bp);73 init_dac_output_control(bp);74 init_set_crtc_timing(bp);75 init_enable_crtc(bp);76 init_enable_crtc_mem_req(bp);77 init_program_clock(bp);78 init_external_encoder_control(bp);79 init_enable_disp_power_gating(bp);80 init_set_dce_clock(bp);81}82 83static uint32_t bios_cmd_table_para_revision(void *dev,84 uint32_t index)85{86 struct amdgpu_device *adev = dev;87 uint8_t frev, crev;88 89 if (amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context,90 index,91 &frev, &crev))92 return crev;93 else94 return 0;95}96 97/*******************************************************************************98 ********************************************************************************99 **100 ** D I G E N C O D E R C O N T R O L101 **102 ********************************************************************************103 *******************************************************************************/104static enum bp_result encoder_control_digx_v3(105 struct bios_parser *bp,106 struct bp_encoder_control *cntl);107 108static enum bp_result encoder_control_digx_v4(109 struct bios_parser *bp,110 struct bp_encoder_control *cntl);111 112static enum bp_result encoder_control_digx_v5(113 struct bios_parser *bp,114 struct bp_encoder_control *cntl);115 116static void init_encoder_control_dig_v1(struct bios_parser *bp);117 118static void init_dig_encoder_control(struct bios_parser *bp)119{120 uint32_t version =121 BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl);122 123 switch (version) {124 case 2:125 bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3;126 break;127 case 4:128 bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4;129 break;130 131 case 5:132 bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5;133 break;134 135 default:136 init_encoder_control_dig_v1(bp);137 break;138 }139}140 141static enum bp_result encoder_control_dig_v1(142 struct bios_parser *bp,143 struct bp_encoder_control *cntl);144static enum bp_result encoder_control_dig1_v1(145 struct bios_parser *bp,146 struct bp_encoder_control *cntl);147static enum bp_result encoder_control_dig2_v1(148 struct bios_parser *bp,149 struct bp_encoder_control *cntl);150 151static void init_encoder_control_dig_v1(struct bios_parser *bp)152{153 struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;154 155 if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl))156 cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1;157 else158 cmd_tbl->encoder_control_dig1 = NULL;159 160 if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl))161 cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1;162 else163 cmd_tbl->encoder_control_dig2 = NULL;164 165 cmd_tbl->dig_encoder_control = encoder_control_dig_v1;166}167 168static enum bp_result encoder_control_dig_v1(169 struct bios_parser *bp,170 struct bp_encoder_control *cntl)171{172 enum bp_result result = BP_RESULT_FAILURE;173 struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;174 175 if (cntl != NULL)176 switch (cntl->engine_id) {177 case ENGINE_ID_DIGA:178 if (cmd_tbl->encoder_control_dig1 != NULL)179 result =180 cmd_tbl->encoder_control_dig1(bp, cntl);181 break;182 case ENGINE_ID_DIGB:183 if (cmd_tbl->encoder_control_dig2 != NULL)184 result =185 cmd_tbl->encoder_control_dig2(bp, cntl);186 break;187 188 default:189 break;190 }191 192 return result;193}194 195static enum bp_result encoder_control_dig1_v1(196 struct bios_parser *bp,197 struct bp_encoder_control *cntl)198{199 enum bp_result result = BP_RESULT_FAILURE;200 DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};201 202 bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms);203 204 if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params))205 result = BP_RESULT_OK;206 207 return result;208}209 210static enum bp_result encoder_control_dig2_v1(211 struct bios_parser *bp,212 struct bp_encoder_control *cntl)213{214 enum bp_result result = BP_RESULT_FAILURE;215 DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};216 217 bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms);218 219 if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params))220 result = BP_RESULT_OK;221 222 return result;223}224 225static enum bp_result encoder_control_digx_v3(226 struct bios_parser *bp,227 struct bp_encoder_control *cntl)228{229 enum bp_result result = BP_RESULT_FAILURE;230 DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0};231 232 if (LANE_COUNT_FOUR < cntl->lanes_number)233 params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */234 else235 params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */236 237 params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);238 239 /* We need to convert from KHz units into 10KHz units */240 params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);241 params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));242 params.ucEncoderMode =243 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(244 cntl->signal,245 cntl->enable_dp_audio);246 params.ucLaneNum = (uint8_t)(cntl->lanes_number);247 248 switch (cntl->color_depth) {249 case COLOR_DEPTH_888:250 params.ucBitPerColor = PANEL_8BIT_PER_COLOR;251 break;252 case COLOR_DEPTH_101010:253 params.ucBitPerColor = PANEL_10BIT_PER_COLOR;254 break;255 case COLOR_DEPTH_121212:256 params.ucBitPerColor = PANEL_12BIT_PER_COLOR;257 break;258 case COLOR_DEPTH_161616:259 params.ucBitPerColor = PANEL_16BIT_PER_COLOR;260 break;261 default:262 break;263 }264 265 if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))266 result = BP_RESULT_OK;267 268 return result;269}270 271static enum bp_result encoder_control_digx_v4(272 struct bios_parser *bp,273 struct bp_encoder_control *cntl)274{275 enum bp_result result = BP_RESULT_FAILURE;276 DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0};277 278 if (LANE_COUNT_FOUR < cntl->lanes_number)279 params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */280 else281 params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */282 283 params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);284 285 /* We need to convert from KHz units into 10KHz units */286 params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);287 params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));288 params.ucEncoderMode =289 (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(290 cntl->signal,291 cntl->enable_dp_audio));292 params.ucLaneNum = (uint8_t)(cntl->lanes_number);293 294 switch (cntl->color_depth) {295 case COLOR_DEPTH_888:296 params.ucBitPerColor = PANEL_8BIT_PER_COLOR;297 break;298 case COLOR_DEPTH_101010:299 params.ucBitPerColor = PANEL_10BIT_PER_COLOR;300 break;301 case COLOR_DEPTH_121212:302 params.ucBitPerColor = PANEL_12BIT_PER_COLOR;303 break;304 case COLOR_DEPTH_161616:305 params.ucBitPerColor = PANEL_16BIT_PER_COLOR;306 break;307 default:308 break;309 }310 311 if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))312 result = BP_RESULT_OK;313 314 return result;315}316 317static enum bp_result encoder_control_digx_v5(318 struct bios_parser *bp,319 struct bp_encoder_control *cntl)320{321 enum bp_result result = BP_RESULT_FAILURE;322 ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0};323 324 params.ucDigId = (uint8_t)(cntl->engine_id);325 params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);326 327 params.ulPixelClock = cntl->pixel_clock / 10;328 params.ucDigMode =329 (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(330 cntl->signal,331 cntl->enable_dp_audio));332 params.ucLaneNum = (uint8_t)(cntl->lanes_number);333 334 switch (cntl->color_depth) {335 case COLOR_DEPTH_888:336 params.ucBitPerColor = PANEL_8BIT_PER_COLOR;337 break;338 case COLOR_DEPTH_101010:339 params.ucBitPerColor = PANEL_10BIT_PER_COLOR;340 break;341 case COLOR_DEPTH_121212:342 params.ucBitPerColor = PANEL_12BIT_PER_COLOR;343 break;344 case COLOR_DEPTH_161616:345 params.ucBitPerColor = PANEL_16BIT_PER_COLOR;346 break;347 default:348 break;349 }350 351 if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)352 switch (cntl->color_depth) {353 case COLOR_DEPTH_101010:354 params.ulPixelClock =355 (params.ulPixelClock * 30) / 24;356 break;357 case COLOR_DEPTH_121212:358 params.ulPixelClock =359 (params.ulPixelClock * 36) / 24;360 break;361 case COLOR_DEPTH_161616:362 params.ulPixelClock =363 (params.ulPixelClock * 48) / 24;364 break;365 default:366 break;367 }368 369 if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))370 result = BP_RESULT_OK;371 372 return result;373}374 375/*******************************************************************************376 ********************************************************************************377 **378 ** TRANSMITTER CONTROL379 **380 ********************************************************************************381 *******************************************************************************/382 383static enum bp_result transmitter_control_v2(384 struct bios_parser *bp,385 struct bp_transmitter_control *cntl);386static enum bp_result transmitter_control_v3(387 struct bios_parser *bp,388 struct bp_transmitter_control *cntl);389static enum bp_result transmitter_control_v4(390 struct bios_parser *bp,391 struct bp_transmitter_control *cntl);392static enum bp_result transmitter_control_v1_5(393 struct bios_parser *bp,394 struct bp_transmitter_control *cntl);395static enum bp_result transmitter_control_v1_6(396 struct bios_parser *bp,397 struct bp_transmitter_control *cntl);398 399static void init_transmitter_control(struct bios_parser *bp)400{401 uint8_t frev;402 uint8_t crev = 0;403 404 if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl,405 frev, crev) == false)406 BREAK_TO_DEBUGGER();407 switch (crev) {408 case 2:409 bp->cmd_tbl.transmitter_control = transmitter_control_v2;410 break;411 case 3:412 bp->cmd_tbl.transmitter_control = transmitter_control_v3;413 break;414 case 4:415 bp->cmd_tbl.transmitter_control = transmitter_control_v4;416 break;417 case 5:418 bp->cmd_tbl.transmitter_control = transmitter_control_v1_5;419 break;420 case 6:421 bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;422 break;423 default:424 dm_output_to_console("Don't have transmitter_control for v%d\n", crev);425 bp->cmd_tbl.transmitter_control = NULL;426 break;427 }428}429 430static enum bp_result transmitter_control_v2(431 struct bios_parser *bp,432 struct bp_transmitter_control *cntl)433{434 enum bp_result result = BP_RESULT_FAILURE;435 DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params;436 enum connector_id connector_id =437 dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);438 439 memset(¶ms, 0, sizeof(params));440 441 switch (cntl->transmitter) {442 case TRANSMITTER_UNIPHY_A:443 case TRANSMITTER_UNIPHY_B:444 case TRANSMITTER_UNIPHY_C:445 case TRANSMITTER_UNIPHY_D:446 case TRANSMITTER_UNIPHY_E:447 case TRANSMITTER_UNIPHY_F:448 case TRANSMITTER_TRAVIS_LCD:449 break;450 default:451 return BP_RESULT_BADINPUT;452 }453 454 switch (cntl->action) {455 case TRANSMITTER_CONTROL_INIT:456 if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) ||457 (CONNECTOR_ID_DUAL_LINK_DVID == connector_id))458 /* on INIT this bit should be set according to the459 * physical connector460 * Bit0: dual link connector flag461 * =0 connector is single link connector462 * =1 connector is dual link connector463 */464 params.acConfig.fDualLinkConnector = 1;465 466 /* connector object id */467 params.usInitInfo =468 cpu_to_le16((uint8_t)cntl->connector_obj_id.id);469 break;470 case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:471 /* voltage swing and pre-emphsis */472 params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;473 params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;474 break;475 default:476 /* if dual-link */477 if (LANE_COUNT_FOUR < cntl->lanes_number) {478 /* on ENABLE/DISABLE this bit should be set according to479 * actual timing (number of lanes)480 * Bit0: dual link connector flag481 * =0 connector is single link connector482 * =1 connector is dual link connector483 */484 params.acConfig.fDualLinkConnector = 1;485 486 /* link rate, half for dual link487 * We need to convert from KHz units into 20KHz units488 */489 params.usPixelClock =490 cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));491 } else492 /* link rate, half for dual link493 * We need to convert from KHz units into 10KHz units494 */495 params.usPixelClock =496 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));497 break;498 }499 500 /* 00 - coherent mode501 * 01 - incoherent mode502 */503 504 params.acConfig.fCoherentMode = cntl->coherent;505 506 if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)507 || (TRANSMITTER_UNIPHY_D == cntl->transmitter)508 || (TRANSMITTER_UNIPHY_F == cntl->transmitter))509 /* Bit2: Transmitter Link selection510 * =0 when bit0=0, single link A/C/E, when bit0=1,511 * master link A/C/E512 * =1 when bit0=0, single link B/D/F, when bit0=1,513 * master link B/D/F514 */515 params.acConfig.ucLinkSel = 1;516 517 if (ENGINE_ID_DIGB == cntl->engine_id)518 /* Bit3: Transmitter data source selection519 * =0 DIGA is data source.520 * =1 DIGB is data source.521 * This bit is only useful when ucAction= ATOM_ENABLE522 */523 params.acConfig.ucEncoderSel = 1;524 525 if (CONNECTOR_ID_DISPLAY_PORT == connector_id ||526 CONNECTOR_ID_USBC == connector_id)527 /* Bit4: DP connector flag528 * =0 connector is none-DP connector529 * =1 connector is DP connector530 */531 params.acConfig.fDPConnector = 1;532 533 /* Bit[7:6]: Transmitter selection534 * =0 UNIPHY_ENCODER: UNIPHYA/B535 * =1 UNIPHY1_ENCODER: UNIPHYC/D536 * =2 UNIPHY2_ENCODER: UNIPHYE/F537 * =3 reserved538 */539 params.acConfig.ucTransmitterSel =540 (uint8_t)bp->cmd_helper->transmitter_bp_to_atom(541 cntl->transmitter);542 543 params.ucAction = (uint8_t)cntl->action;544 545 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))546 result = BP_RESULT_OK;547 548 return result;549}550 551static enum bp_result transmitter_control_v3(552 struct bios_parser *bp,553 struct bp_transmitter_control *cntl)554{555 enum bp_result result = BP_RESULT_FAILURE;556 DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 params;557 uint32_t pll_id;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);563 564 memset(¶ms, 0, sizeof(params));565 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:574 break;575 default:576 return BP_RESULT_BADINPUT;577 }578 579 if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id))580 return BP_RESULT_BADINPUT;581 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 the587 * phisycal connector588 * Bit0: dual link connector flag589 * =0 connector is single link connector590 * =1 connector is dual link connector591 */592 params.acConfig.fDualLinkConnector = 1;593 }594 595 /* connector object id */596 params.usInitInfo =597 cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));598 break;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;603 break;604 default:605 if (dual_link_conn && cntl->multi_path)606 /* on ENABLE/DISABLE this bit should be set according to607 * actual timing (number of lanes)608 * Bit0: dual link connector flag609 * =0 connector is single link connector610 * =1 connector is dual link connector611 */612 params.acConfig.fDualLinkConnector = 1;613 614 /* if dual-link */615 if (LANE_COUNT_FOUR < cntl->lanes_number) {616 /* on ENABLE/DISABLE this bit should be set according to617 * actual timing (number of lanes)618 * Bit0: dual link connector flag619 * =0 connector is single link connector620 * =1 connector is dual link connector621 */622 params.acConfig.fDualLinkConnector = 1;623 624 /* link rate, half for dual link625 * We need to convert from KHz units into 20KHz units626 */627 params.usPixelClock =628 cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));629 } else {630 /* link rate, half for dual link631 * We need to convert from KHz units into 10KHz units632 */633 params.usPixelClock =634 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));635 }636 break;637 }638 639 /* 00 - coherent mode640 * 01 - incoherent mode641 */642 643 params.acConfig.fCoherentMode = cntl->coherent;644 645 if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)646 || (TRANSMITTER_UNIPHY_D == cntl->transmitter)647 || (TRANSMITTER_UNIPHY_F == cntl->transmitter))648 /* Bit2: Transmitter Link selection649 * =0 when bit0=0, single link A/C/E, when bit0=1,650 * master link A/C/E651 * =1 when bit0=0, single link B/D/F, when bit0=1,652 * master link B/D/F653 */654 params.acConfig.ucLinkSel = 1;655 656 if (ENGINE_ID_DIGB == cntl->engine_id)657 /* Bit3: Transmitter data source selection658 * =0 DIGA is data source.659 * =1 DIGB is data source.660 * This bit is only useful when ucAction= ATOM_ENABLE661 */662 params.acConfig.ucEncoderSel = 1;663 664 /* Bit[7:6]: Transmitter selection665 * =0 UNIPHY_ENCODER: UNIPHYA/B666 * =1 UNIPHY1_ENCODER: UNIPHYC/D667 * =2 UNIPHY2_ENCODER: UNIPHYE/F668 * =3 reserved669 */670 params.acConfig.ucTransmitterSel =671 (uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter);672 673 params.ucLaneNum = (uint8_t)cntl->lanes_number;674 675 params.acConfig.ucRefClkSource = (uint8_t)pll_id;676 677 params.ucAction = (uint8_t)cntl->action;678 679 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))680 result = BP_RESULT_OK;681 682 return result;683}684 685static enum bp_result transmitter_control_v4(686 struct bios_parser *bp,687 struct bp_transmitter_control *cntl)688{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;695 696 memset(¶ms, 0, sizeof(params));697 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:706 break;707 default:708 return BP_RESULT_BADINPUT;709 }710 711 if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id))712 return BP_RESULT_BADINPUT;713 714 switch (cntl->action) {715 case TRANSMITTER_CONTROL_INIT:716 {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 the720 * phisycal connector721 * Bit0: dual link connector flag722 * =0 connector is single link connector723 * =1 connector is dual link connector724 */725 params.acConfig.fDualLinkConnector = 1;726 727 /* connector object id */728 params.usInitInfo =729 cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));730 }731 break;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);736 break;737 default: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 to741 * actual timing (number of lanes)742 * Bit0: dual link connector flag743 * =0 connector is single link connector744 * =1 connector is dual link connector745 */746 params.acConfig.fDualLinkConnector = 1;747 748 /* if dual-link */749 if (LANE_COUNT_FOUR < cntl->lanes_number)750 /* link rate, half for dual link751 * We need to convert from KHz units into 20KHz units752 */753 params.usPixelClock =754 cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));755 else {756 /* link rate, half for dual link757 * We need to convert from KHz units into 10KHz units758 */759 params.usPixelClock =760 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));761 }762 break;763 }764 765 /* 00 - coherent mode766 * 01 - incoherent mode767 */768 769 params.acConfig.fCoherentMode = cntl->coherent;770 771 if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)772 || (TRANSMITTER_UNIPHY_D == cntl->transmitter)773 || (TRANSMITTER_UNIPHY_F == cntl->transmitter))774 /* Bit2: Transmitter Link selection775 * =0 when bit0=0, single link A/C/E, when bit0=1,776 * master link A/C/E777 * =1 when bit0=0, single link B/D/F, when bit0=1,778 * master link B/D/F779 */780 params.acConfig.ucLinkSel = 1;781 782 if (ENGINE_ID_DIGB == cntl->engine_id)783 /* Bit3: Transmitter data source selection784 * =0 DIGA is data source.785 * =1 DIGB is data source.786 * This bit is only useful when ucAction= ATOM_ENABLE787 */788 params.acConfig.ucEncoderSel = 1;789 790 /* Bit[7:6]: Transmitter selection791 * =0 UNIPHY_ENCODER: UNIPHYA/B792 * =1 UNIPHY1_ENCODER: UNIPHYC/D793 * =2 UNIPHY2_ENCODER: UNIPHYE/F794 * =3 reserved795 */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);801 802 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))803 result = BP_RESULT_OK;804 805 return result;806}807 808static enum bp_result transmitter_control_v1_5(809 struct bios_parser *bp,810 struct bp_transmitter_control *cntl)811{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;815 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;821 822 params.ucDigMode =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));834 /*835 * In SI/TN case, caller have to set usPixelClock as following:836 * DP mode: usPixelClock = DP_LINK_CLOCK/10837 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)838 * DVI single link mode: usPixelClock = pixel clock839 * DVI dual link mode: usPixelClock = pixel clock840 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio841 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)842 * LVDS mode: usPixelClock = pixel clock843 */844 if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) {845 switch (cntl->color_depth) {846 case COLOR_DEPTH_101010:847 params.usSymClock =848 cpu_to_le16((le16_to_cpu(params.usSymClock) * 30) / 24);849 break;850 case COLOR_DEPTH_121212:851 params.usSymClock =852 cpu_to_le16((le16_to_cpu(params.usSymClock) * 36) / 24);853 break;854 case COLOR_DEPTH_161616:855 params.usSymClock =856 cpu_to_le16((le16_to_cpu(params.usSymClock) * 48) / 24);857 break;858 default:859 break;860 }861 }862 863 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))864 result = BP_RESULT_OK;865 866 return result;867}868 869static enum bp_result transmitter_control_v1_6(870 struct bios_parser *bp,871 struct bp_transmitter_control *cntl)872{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;876 877 memset(¶ms, 0, sizeof(params));878 params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);879 params.ucAction = (uint8_t)cntl->action;880 881 if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)882 params.ucDPLaneSet = (uint8_t)cntl->lane_settings;883 else884 params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal);885 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;891 892 /*893 * In SI/TN case, caller have to set usPixelClock as following:894 * DP mode: usPixelClock = DP_LINK_CLOCK/10895 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)896 * DVI single link mode: usPixelClock = pixel clock897 * DVI dual link mode: usPixelClock = pixel clock898 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio899 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)900 * LVDS mode: usPixelClock = pixel clock901 */902 switch (cntl->signal) {903 case SIGNAL_TYPE_HDMI_TYPE_A:904 switch (cntl->color_depth) {905 case COLOR_DEPTH_101010:906 params.ulSymClock =907 cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24);908 break;909 case COLOR_DEPTH_121212:910 params.ulSymClock =911 cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24);912 break;913 case COLOR_DEPTH_161616:914 params.ulSymClock =915 cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24);916 break;917 default:918 break;919 }920 break;921 default:922 break;923 }924 925 if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))926 result = BP_RESULT_OK;927 return result;928}929 930/*******************************************************************************931 ********************************************************************************932 **933 ** SET PIXEL CLOCK934 **935 ********************************************************************************936 *******************************************************************************/937 938static enum bp_result set_pixel_clock_v3(939 struct bios_parser *bp,940 struct bp_pixel_clock_parameters *bp_params);941static enum bp_result set_pixel_clock_v5(942 struct bios_parser *bp,943 struct bp_pixel_clock_parameters *bp_params);944static enum bp_result set_pixel_clock_v6(945 struct bios_parser *bp,946 struct bp_pixel_clock_parameters *bp_params);947static enum bp_result set_pixel_clock_v7(948 struct bios_parser *bp,949 struct bp_pixel_clock_parameters *bp_params);950 951static void init_set_pixel_clock(struct bios_parser *bp)952{953 switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {954 case 3:955 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3;956 break;957 case 5:958 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5;959 break;960 case 6:961 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6;962 break;963 case 7:964 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;965 break;966 default: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;970 break;971 }972}973 974static enum bp_result set_pixel_clock_v3(975 struct bios_parser *bp,976 struct bp_pixel_clock_parameters *bp_params)977{978 enum bp_result result = BP_RESULT_FAILURE;979 PIXEL_CLOCK_PARAMETERS_V3 *params;980 SET_PIXEL_CLOCK_PS_ALLOCATION allocation;981 982 memset(&allocation, 0, sizeof(allocation));983 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;988 else989 return BP_RESULT_BADINPUT;990 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;999 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));1003 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));1012 1013 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)1014 params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;1015 1016 if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK)1017 params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK;1018 1019 if (CONTROLLER_ID_D1 != bp_params->controller_id)1020 params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;1021 1022 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation))1023 result = BP_RESULT_OK;1024 1025 return result;1026}1027 1028#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V51029/* video bios did not define this: */1030typedef 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;1035#endif1036 1037#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V61038/* video bios did not define this: */1039typedef 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;1044#endif1045 1046static enum bp_result set_pixel_clock_v5(1047 struct bios_parser *bp,1048 struct bp_pixel_clock_parameters *bp_params)1049{1050 enum bp_result result = BP_RESULT_FAILURE;1051 SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk;1052 uint8_t controller_id;1053 uint32_t pll_id;1054 1055 memset(&clk, 0, sizeof(clk));1056 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);1077 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));1081 1082 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)1083 clk.sPCLKInput.ucMiscInfo |=1084 PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;1085 1086 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)1087 clk.sPCLKInput.ucMiscInfo |=1088 PIXEL_CLOCK_MISC_REF_DIV_SRC;1089 1090 /* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp1091 * =1:30bpp, =2:32bpp1092 * driver choose program it itself, i.e. here we program it1093 * to 888 by default.1094 */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;1100 break;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;1104 break;1105 default:1106 break;1107 }1108 1109 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))1110 result = BP_RESULT_OK;1111 }1112 1113 return result;1114}1115 1116static enum bp_result set_pixel_clock_v6(1117 struct bios_parser *bp,1118 struct bp_pixel_clock_parameters *bp_params)1119{1120 enum bp_result result = BP_RESULT_FAILURE;1121 SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk;1122 uint8_t controller_id;1123 uint32_t pll_id;1124 1125 memset(&clk, 0, sizeof(clk));1126 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 now1131 * 1 byte in ULONG1132 *typedef struct _CRTC_PIXEL_CLOCK_FREQ1133 *{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 to1137 * previous version.1138 * ATOM_CRTC1~6, indicate the CRTC controller to1139 * ULONG ucCRTC:8;1140 * drive the pixel clock. not used for DCPLL case.1141 *}CRTC_PIXEL_CLOCK_FREQ;1142 *union1143 *{1144 * pixel clock and CRTC id frequency1145 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;1146 * ULONG ulDispEngClkFreq; dispclk frequency1147 *};1148 */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);1166 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);1170 1171 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {1172 clk.sPCLKInput.ucMiscInfo |=1173 PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL;1174 }1175 1176 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) {1177 clk.sPCLKInput.ucMiscInfo |=1178 PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;1179 }1180 1181 /* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0:1182 * 24bpp =1:30bpp, =2:32bpp1183 * driver choose program it itself, i.e. here we pass required1184 * target rate that includes deep color.1185 */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;1190 break;1191 case TRANSMITTER_COLOR_DEPTH_36:1192 clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6;1193 break;1194 case TRANSMITTER_COLOR_DEPTH_48:1195 clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;1196 break;1197 default:1198 break;1199 }1200 1201 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))1202 result = BP_RESULT_OK;1203 }1204 1205 return result;1206}1207 1208static enum bp_result set_pixel_clock_v7(1209 struct bios_parser *bp,1210 struct bp_pixel_clock_parameters *bp_params)1211{1212 enum bp_result result = BP_RESULT_FAILURE;1213 PIXEL_CLOCK_PARAMETERS_V7 clk;1214 uint8_t controller_id;1215 uint32_t pll_id;1216 1217 memset(&clk, 0, sizeof(clk));1218 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 now1222 * 1 byte in ULONG1223 *typedef struct _CRTC_PIXEL_CLOCK_FREQ1224 *{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 to1228 * previous version.1229 * ATOM_CRTC1~6, indicate the CRTC controller to1230 * ULONG ucCRTC:8;1231 * drive the pixel clock. not used for DCPLL case.1232 *}CRTC_PIXEL_CLOCK_FREQ;1233 *union1234 *{1235 * pixel clock and CRTC id frequency1236 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;1237 * ULONG ulDispEngClkFreq; dispclk frequency1238 *};1239 */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);1244 1245 clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock_100hz);1246 1247 clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);1248 1249 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)1250 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;1251 1252 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)1253 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC;1254 1255 if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)1256 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;1257 1258 if (bp_params->flags.SUPPORT_YUV_420)1259 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;1260 1261 if (bp_params->flags.SET_XTALIN_REF_SRC)1262 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;1263 1264 if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)1265 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;1266 1267 if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)1268 clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;1269 1270 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))1271 result = BP_RESULT_OK;1272 }1273 return result;1274}1275 1276/*******************************************************************************1277 ********************************************************************************1278 **1279 ** ENABLE PIXEL CLOCK SS1280 **1281 ********************************************************************************1282 *******************************************************************************/1283static enum bp_result enable_spread_spectrum_on_ppll_v1(1284 struct bios_parser *bp,1285 struct bp_spread_spectrum_parameters *bp_params,1286 bool enable);1287static enum bp_result enable_spread_spectrum_on_ppll_v2(1288 struct bios_parser *bp,1289 struct bp_spread_spectrum_parameters *bp_params,1290 bool enable);1291static enum bp_result enable_spread_spectrum_on_ppll_v3(1292 struct bios_parser *bp,1293 struct bp_spread_spectrum_parameters *bp_params,1294 bool enable);1295 1296static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp)1297{1298 switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) {1299 case 1:1300 bp->cmd_tbl.enable_spread_spectrum_on_ppll =1301 enable_spread_spectrum_on_ppll_v1;1302 break;1303 case 2:1304 bp->cmd_tbl.enable_spread_spectrum_on_ppll =1305 enable_spread_spectrum_on_ppll_v2;1306 break;1307 case 3:1308 bp->cmd_tbl.enable_spread_spectrum_on_ppll =1309 enable_spread_spectrum_on_ppll_v3;1310 break;1311 default: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;1315 break;1316 }1317}1318 1319static enum bp_result enable_spread_spectrum_on_ppll_v1(1320 struct bios_parser *bp,1321 struct bp_spread_spectrum_parameters *bp_params,1322 bool enable)1323{1324 enum bp_result result = BP_RESULT_FAILURE;1325 ENABLE_SPREAD_SPECTRUM_ON_PPLL params;1326 1327 memset(¶ms, 0, sizeof(params));1328 1329 if ((enable == true) && (bp_params->percentage > 0))1330 params.ucEnable = ATOM_ENABLE;1331 else1332 params.ucEnable = ATOM_DISABLE;1333 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);1343 1344 if (bp_params->flags.EXTERNAL_SS)1345 params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK;1346 1347 if (bp_params->flags.CENTER_SPREAD)1348 params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE;1349 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;1354 else1355 BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */1356 1357 if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))1358 result = BP_RESULT_OK;1359 1360 return result;1361}1362 1363static enum bp_result enable_spread_spectrum_on_ppll_v2(1364 struct bios_parser *bp,1365 struct bp_spread_spectrum_parameters *bp_params,1366 bool enable)1367{1368 enum bp_result result = BP_RESULT_FAILURE;1369 ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params;1370 1371 memset(¶ms, 0, sizeof(params));1372 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;1377 else1378 BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */1379 1380 if ((enable == true) && (bp_params->percentage > 0)) {1381 params.ucEnable = ATOM_ENABLE;1382 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));1387 1388 if (bp_params->flags.EXTERNAL_SS)1389 params.ucSpreadSpectrumType |=1390 ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD;1391 1392 if (bp_params->flags.CENTER_SPREAD)1393 params.ucSpreadSpectrumType |=1394 ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD;1395 1396 /* Both amounts need to be left shifted first before bit1397 * comparison. Otherwise, the result will always be zero here1398 */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)));1406 } else1407 params.ucEnable = ATOM_DISABLE;1408 1409 if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))1410 result = BP_RESULT_OK;1411 1412 return result;1413}1414 1415static enum bp_result enable_spread_spectrum_on_ppll_v3(1416 struct bios_parser *bp,1417 struct bp_spread_spectrum_parameters *bp_params,1418 bool enable)1419{1420 enum bp_result result = BP_RESULT_FAILURE;1421 ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params;1422 1423 memset(¶ms, 0, sizeof(params));1424 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.1429 */1430 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;1431 break;1432 case CLOCK_SOURCE_ID_PLL1:1433 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL;1434 break;1435 1436 case CLOCK_SOURCE_ID_PLL2:1437 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL;1438 break;1439 1440 case CLOCK_SOURCE_ID_DCPLL:1441 params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;1442 break;1443 1444 default:1445 BREAK_TO_DEBUGGER();1446 /* Unexpected PLL value!! */1447 return result;1448 }1449 1450 if (enable == true) {1451 params.ucEnable = ATOM_ENABLE;1452 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));1457 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;1464 1465 /* Both amounts need to be left shifted first before bit1466 * comparison. Otherwise, the result will always be zero here1467 */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)));1475 } else1476 params.ucEnable = ATOM_DISABLE;1477 1478 if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))1479 result = BP_RESULT_OK;1480 1481 return result;1482}1483 1484/*******************************************************************************1485 ********************************************************************************1486 **1487 ** ADJUST DISPLAY PLL1488 **1489 ********************************************************************************1490 *******************************************************************************/1491 1492static enum bp_result adjust_display_pll_v2(1493 struct bios_parser *bp,1494 struct bp_adjust_pixel_clock_parameters *bp_params);1495static enum bp_result adjust_display_pll_v3(1496 struct bios_parser *bp,1497 struct bp_adjust_pixel_clock_parameters *bp_params);1498 1499static void init_adjust_display_pll(struct bios_parser *bp)1500{1501 switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) {1502 case 2:1503 bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2;1504 break;1505 case 3:1506 bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3;1507 break;1508 default: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;1512 break;1513 }1514}1515 1516static enum bp_result adjust_display_pll_v2(1517 struct bios_parser *bp,1518 struct bp_adjust_pixel_clock_parameters *bp_params)1519{1520 enum bp_result result = BP_RESULT_FAILURE;1521 ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 };1522 1523 /* We need to convert from KHz units into 10KHz units and then convert1524 * output pixel clock back 10KHz-->KHz */1525 uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10;1526 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);1535 1536 if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {1537 /* Convert output pixel clock back 10KHz-->KHz: multiply1538 * original pixel clock in KHz by ratio1539 * [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;1543 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);1548 } else {1549 bp_params->adjusted_pixel_clock = 0;1550 BREAK_TO_DEBUGGER();1551 }1552 1553 result = BP_RESULT_OK;1554 }1555 1556 return result;1557}1558 1559static enum bp_result adjust_display_pll_v3(1560 struct bios_parser *bp,1561 struct bp_adjust_pixel_clock_parameters *bp_params)1562{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;1566 1567 memset(¶ms, 0, sizeof(params));1568 1569 /* We need to convert from KHz units into 10KHz units and then convert1570 * 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);1579 1580 if (bp_params->ss_enable == true)1581 params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;1582 1583 if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)1584 params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;1585 1586 if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {1587 /* Convert output pixel clock back 10KHz-->KHz: multiply1588 * original pixel clock in KHz by ratio1589 * [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;1593 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);1598 } else {1599 bp_params->adjusted_pixel_clock = 0;1600 BREAK_TO_DEBUGGER();1601 }1602 1603 bp_params->reference_divider = params.sOutput.ucRefDiv;1604 bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv;1605 1606 result = BP_RESULT_OK;1607 }1608 1609 return result;1610}1611 1612/*******************************************************************************1613 ********************************************************************************1614 **1615 ** DAC ENCODER CONTROL1616 **1617 ********************************************************************************1618 *******************************************************************************/1619 1620static enum bp_result dac1_encoder_control_v1(1621 struct bios_parser *bp,1622 bool enable,1623 uint32_t pixel_clock,1624 uint8_t dac_standard);1625static enum bp_result dac2_encoder_control_v1(1626 struct bios_parser *bp,1627 bool enable,1628 uint32_t pixel_clock,1629 uint8_t dac_standard);1630 1631static void init_dac_encoder_control(struct bios_parser *bp)1632{1633 switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) {1634 case 1:1635 bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1;1636 break;1637 default:1638 bp->cmd_tbl.dac1_encoder_control = NULL;1639 break;1640 }1641 switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) {1642 case 1:1643 bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1;1644 break;1645 default:1646 bp->cmd_tbl.dac2_encoder_control = NULL;1647 break;1648 }1649}1650 1651static void dac_encoder_control_prepare_params(1652 DAC_ENCODER_CONTROL_PS_ALLOCATION *params,1653 bool enable,1654 uint32_t pixel_clock,1655 uint8_t dac_standard)1656{1657 params->ucDacStandard = dac_standard;1658 if (enable)1659 params->ucAction = ATOM_ENABLE;1660 else1661 params->ucAction = ATOM_DISABLE;1662 1663 /* We need to convert from KHz units into 10KHz units1664 * it looks as if the TvControl do not care about pixel clock1665 */1666 params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10));1667}1668 1669static enum bp_result dac1_encoder_control_v1(1670 struct bios_parser *bp,1671 bool enable,1672 uint32_t pixel_clock,1673 uint8_t dac_standard)1674{1675 enum bp_result result = BP_RESULT_FAILURE;1676 DAC_ENCODER_CONTROL_PS_ALLOCATION params;1677 1678 dac_encoder_control_prepare_params(1679 ¶ms,1680 enable,1681 pixel_clock,1682 dac_standard);1683 1684 if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params))1685 result = BP_RESULT_OK;1686 1687 return result;1688}1689 1690static enum bp_result dac2_encoder_control_v1(1691 struct bios_parser *bp,1692 bool enable,1693 uint32_t pixel_clock,1694 uint8_t dac_standard)1695{1696 enum bp_result result = BP_RESULT_FAILURE;1697 DAC_ENCODER_CONTROL_PS_ALLOCATION params;1698 1699 dac_encoder_control_prepare_params(1700 ¶ms,1701 enable,1702 pixel_clock,1703 dac_standard);1704 1705 if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params))1706 result = BP_RESULT_OK;1707 1708 return result;1709}1710 1711/*******************************************************************************1712 ********************************************************************************1713 **1714 ** DAC OUTPUT CONTROL1715 **1716 ********************************************************************************1717 *******************************************************************************/1718static enum bp_result dac1_output_control_v1(1719 struct bios_parser *bp,1720 bool enable);1721static enum bp_result dac2_output_control_v1(1722 struct bios_parser *bp,1723 bool enable);1724 1725static void init_dac_output_control(struct bios_parser *bp)1726{1727 switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) {1728 case 1:1729 bp->cmd_tbl.dac1_output_control = dac1_output_control_v1;1730 break;1731 default:1732 bp->cmd_tbl.dac1_output_control = NULL;1733 break;1734 }1735 switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) {1736 case 1:1737 bp->cmd_tbl.dac2_output_control = dac2_output_control_v1;1738 break;1739 default:1740 bp->cmd_tbl.dac2_output_control = NULL;1741 break;1742 }1743}1744 1745static enum bp_result dac1_output_control_v1(1746 struct bios_parser *bp, bool enable)1747{1748 enum bp_result result = BP_RESULT_FAILURE;1749 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;1750 1751 if (enable)1752 params.ucAction = ATOM_ENABLE;1753 else1754 params.ucAction = ATOM_DISABLE;1755 1756 if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params))1757 result = BP_RESULT_OK;1758 1759 return result;1760}1761 1762static enum bp_result dac2_output_control_v1(1763 struct bios_parser *bp, bool enable)1764{1765 enum bp_result result = BP_RESULT_FAILURE;1766 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;1767 1768 if (enable)1769 params.ucAction = ATOM_ENABLE;1770 else1771 params.ucAction = ATOM_DISABLE;1772 1773 if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params))1774 result = BP_RESULT_OK;1775 1776 return result;1777}1778 1779/*******************************************************************************1780 ********************************************************************************1781 **1782 ** SET CRTC TIMING1783 **1784 ********************************************************************************1785 *******************************************************************************/1786 1787static enum bp_result set_crtc_using_dtd_timing_v3(1788 struct bios_parser *bp,1789 struct bp_hw_crtc_timing_parameters *bp_params);1790static enum bp_result set_crtc_timing_v1(1791 struct bios_parser *bp,1792 struct bp_hw_crtc_timing_parameters *bp_params);1793 1794static void init_set_crtc_timing(struct bios_parser *bp)1795{1796 uint32_t dtd_version =1797 BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming);1798 if (dtd_version > 2)1799 switch (dtd_version) {1800 case 3:1801 bp->cmd_tbl.set_crtc_timing =1802 set_crtc_using_dtd_timing_v3;1803 break;1804 default:1805 dm_output_to_console("Don't have set_crtc_timing for dtd v%d\n",1806 dtd_version);1807 bp->cmd_tbl.set_crtc_timing = NULL;1808 break;1809 }1810 else1811 switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) {1812 case 1:1813 bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1;1814 break;1815 default: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;1819 break;1820 }1821}1822 1823static enum bp_result set_crtc_timing_v1(1824 struct bios_parser *bp,1825 struct bp_hw_crtc_timing_parameters *bp_params)1826{1827 enum bp_result result = BP_RESULT_FAILURE;1828 SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0};1829 uint8_t atom_controller_id;1830 1831 if (bp->cmd_helper->controller_id_to_atom(1832 bp_params->controller_id, &atom_controller_id))1833 params.ucCRTC = atom_controller_id;1834 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));1845 1846 /* VBIOS does not expect any value except zero into this call, for1847 * underscan use another entry ProgramOverscan call but when mode1848 * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok,1849 * but when same ,but 60 Hz there is corruption1850 * DAL1 does not allow the mode 1776x1000@601851 */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;1856 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);1860 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);1864 1865 if (bp_params->flags.INTERLACE) {1866 params.susModeMiscInfo.usAccess =1867 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);1868 1869 /* original DAL code has this condition to apply tis for1870 * non-TV/CV only due to complex MV testing for possible1871 * impact1872 * if (pACParameters->signal != SignalType_YPbPr &&1873 * pACParameters->signal != SignalType_Composite &&1874 * pACParameters->signal != SignalType_SVideo)1875 */1876 /* HW will deduct 0.5 line from 2nd feild.1877 * i.e. for 1080i, it is 2 lines for 1st field, 2.51878 * lines for the 2nd feild. we need input as 5 instead1879 * of 4, but it is 4 either from Edid data1880 * (spec CEA 861) or CEA timing table.1881 */1882 params.usV_SyncStart =1883 cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1));1884 }1885 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);1889 1890 if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params))1891 result = BP_RESULT_OK;1892 1893 return result;1894}1895 1896static enum bp_result set_crtc_using_dtd_timing_v3(1897 struct bios_parser *bp,1898 struct bp_hw_crtc_timing_parameters *bp_params)1899{1900 enum bp_result result = BP_RESULT_FAILURE;1901 SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0};1902 uint8_t atom_controller_id;1903 1904 if (bp->cmd_helper->controller_id_to_atom(1905 bp_params->controller_id, &atom_controller_id))1906 params.ucCRTC = atom_controller_id;1907 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 beginning1920 * 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 of1926 * v addressable */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);1930 1931 /* we assume that overscan from original timing does not get bigger1932 * than 2551933 * we will program all the borders in the Set CRTC Overscan call below1934 */1935 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);1939 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);1943 1944 if (bp_params->flags.INTERLACE) {1945 params.susModeMiscInfo.usAccess =1946 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);1947 1948 /* original DAL code has this condition to apply this1949 * for non-TV/CV only1950 * due to complex MV testing for possible impact1951 * if ( pACParameters->signal != SignalType_YPbPr &&1952 * pACParameters->signal != SignalType_Composite &&1953 * pACParameters->signal != SignalType_SVideo)1954 */1955 {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 51959 * instead of 4.1960 * but it is 4 either from Edid data (spec CEA 861)1961 * or CEA timing table.1962 */1963 le16_add_cpu(¶ms.usV_SyncOffset, 1);1964 }1965 }1966 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);1970 1971 if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params))1972 result = BP_RESULT_OK;1973 1974 return result;1975}1976 1977/*******************************************************************************1978 ********************************************************************************1979 **1980 ** ENABLE CRTC1981 **1982 ********************************************************************************1983 *******************************************************************************/1984 1985static enum bp_result enable_crtc_v1(1986 struct bios_parser *bp,1987 enum controller_id controller_id,1988 bool enable);1989 1990static void init_enable_crtc(struct bios_parser *bp)1991{1992 switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) {1993 case 1:1994 bp->cmd_tbl.enable_crtc = enable_crtc_v1;1995 break;1996 default: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;2000 break;2001 }2002}2003 2004static enum bp_result enable_crtc_v1(2005 struct bios_parser *bp,2006 enum controller_id controller_id,2007 bool enable)2008{2009 bool result = BP_RESULT_FAILURE;2010 ENABLE_CRTC_PARAMETERS params = {0};2011 uint8_t id;2012 2013 if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))2014 params.ucCRTC = id;2015 else2016 return BP_RESULT_BADINPUT;2017 2018 if (enable)2019 params.ucEnable = ATOM_ENABLE;2020 else2021 params.ucEnable = ATOM_DISABLE;2022 2023 if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params))2024 result = BP_RESULT_OK;2025 2026 return result;2027}2028 2029/*******************************************************************************2030 ********************************************************************************2031 **2032 ** ENABLE CRTC MEM REQ2033 **2034 ********************************************************************************2035 *******************************************************************************/2036 2037static enum bp_result enable_crtc_mem_req_v1(2038 struct bios_parser *bp,2039 enum controller_id controller_id,2040 bool enable);2041 2042static void init_enable_crtc_mem_req(struct bios_parser *bp)2043{2044 switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) {2045 case 1:2046 bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1;2047 break;2048 default:2049 bp->cmd_tbl.enable_crtc_mem_req = NULL;2050 break;2051 }2052}2053 2054static enum bp_result enable_crtc_mem_req_v1(2055 struct bios_parser *bp,2056 enum controller_id controller_id,2057 bool enable)2058{2059 bool result = BP_RESULT_BADINPUT;2060 ENABLE_CRTC_PARAMETERS params = {0};2061 uint8_t id;2062 2063 if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) {2064 params.ucCRTC = id;2065 2066 if (enable)2067 params.ucEnable = ATOM_ENABLE;2068 else2069 params.ucEnable = ATOM_DISABLE;2070 2071 if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params))2072 result = BP_RESULT_OK;2073 else2074 result = BP_RESULT_FAILURE;2075 }2076 2077 return result;2078}2079 2080/*******************************************************************************2081 ********************************************************************************2082 **2083 ** DISPLAY PLL2084 **2085 ********************************************************************************2086 *******************************************************************************/2087 2088static enum bp_result program_clock_v5(2089 struct bios_parser *bp,2090 struct bp_pixel_clock_parameters *bp_params);2091static enum bp_result program_clock_v6(2092 struct bios_parser *bp,2093 struct bp_pixel_clock_parameters *bp_params);2094 2095static void init_program_clock(struct bios_parser *bp)2096{2097 switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {2098 case 5:2099 bp->cmd_tbl.program_clock = program_clock_v5;2100 break;2101 case 6:2102 bp->cmd_tbl.program_clock = program_clock_v6;2103 break;2104 default: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;2108 break;2109 }2110}2111 2112static enum bp_result program_clock_v5(2113 struct bios_parser *bp,2114 struct bp_pixel_clock_parameters *bp_params)2115{2116 enum bp_result result = BP_RESULT_FAILURE;2117 2118 SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params;2119 uint32_t atom_pll_id;2120 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;2126 }2127 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;2133 2134 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)2135 params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;2136 2137 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params))2138 result = BP_RESULT_OK;2139 2140 return result;2141}2142 2143static enum bp_result program_clock_v6(2144 struct bios_parser *bp,2145 struct bp_pixel_clock_parameters *bp_params)2146{2147 enum bp_result result = BP_RESULT_FAILURE;2148 2149 SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params;2150 uint32_t atom_pll_id;2151 2152 memset(¶ms, 0, sizeof(params));2153 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;2158 }2159 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);2164 2165 if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)2166 params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;2167 2168 if (bp_params->flags.SET_DISPCLK_DFS_BYPASS)2169 params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_DPREFCLK_BYPASS;2170 2171 if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) {2172 /* True display clock is returned by VBIOS if DFS bypass2173 * is enabled. */2174 bp_params->dfs_bypass_display_clock =2175 (uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10);2176 result = BP_RESULT_OK;2177 }2178 2179 return result;2180}2181 2182/*******************************************************************************2183 ********************************************************************************2184 **2185 ** EXTERNAL ENCODER CONTROL2186 **2187 ********************************************************************************2188 *******************************************************************************/2189 2190static enum bp_result external_encoder_control_v3(2191 struct bios_parser *bp,2192 struct bp_external_encoder_control *cntl);2193 2194static void init_external_encoder_control(2195 struct bios_parser *bp)2196{2197 switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) {2198 case 3:2199 bp->cmd_tbl.external_encoder_control =2200 external_encoder_control_v3;2201 break;2202 default:2203 bp->cmd_tbl.external_encoder_control = NULL;2204 break;2205 }2206}2207 2208static enum bp_result external_encoder_control_v3(2209 struct bios_parser *bp,2210 struct bp_external_encoder_control *cntl)2211{2212 enum bp_result result = BP_RESULT_FAILURE;2213 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;2219 2220 memset(¶ms, 0, sizeof(params));2221 2222 cntl_params = ¶ms.sExtEncoder;2223 2224 encoder = cntl->encoder_id;2225 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;2231 break;2232 2233 default:2234 BREAK_TO_DEBUGGER();2235 return BP_RESULT_BADINPUT;2236 }2237 2238 /* Fill information based on the action2239 *2240 * Bit[6:4]: indicate external encoder, applied to all functions.2241 * =0: external encoder1, mapped to external encoder enum id12242 * =1: external encoder2, mapped to external encoder enum id22243 *2244 * enum ObjectEnumId2245 * {2246 * EnumId_Unknown = 0,2247 * EnumId_1,2248 * EnumId_2,2249 * };2250 */2251 cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4);2252 2253 switch (cntl->action) {2254 case EXTERNAL_ENCODER_CONTROL_INIT:2255 /* output display connector type. Only valid in encoder2256 * initialization */2257 cntl_params->usConnectorId =2258 cpu_to_le16((uint16_t)cntl->connector_obj_id.id);2259 break;2260 case EXTERNAL_ENCODER_CONTROL_SETUP:2261 /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in2262 * 10KHz2263 * output display device pixel clock frequency in unit of 10KHz.2264 * Only valid in setup and enableoutput2265 */2266 cntl_params->usPixelClock =2267 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));2268 /* Indicate display output signal type drive by external2269 * 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);2273 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 format2280 * in DP mode, only valid in encoder setup in DP mode.2281 */2282 cntl_params->ucBitPerColor =2283 (uint8_t)(cntl->color_depth);2284 }2285 /* Indicate how many lanes used by external encoder, only valid2286 * in encoder setup and enableoutput. */2287 cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);2288 break;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;2296 break;2297 default:2298 break;2299 }2300 2301 cntl_params->ucAction = (uint8_t)cntl->action;2302 2303 if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params))2304 result = BP_RESULT_OK;2305 2306 return result;2307}2308 2309/*******************************************************************************2310 ********************************************************************************2311 **2312 ** ENABLE DISPLAY POWER GATING2313 **2314 ********************************************************************************2315 *******************************************************************************/2316 2317static 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);2321 2322static void init_enable_disp_power_gating(2323 struct bios_parser *bp)2324{2325 switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) {2326 case 1:2327 bp->cmd_tbl.enable_disp_power_gating =2328 enable_disp_power_gating_v2_1;2329 break;2330 default: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;2334 break;2335 }2336}2337 2338static 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)2342{2343 enum bp_result result = BP_RESULT_FAILURE;2344 2345 ENABLE_DISP_POWER_GATING_PS_ALLOCATION params = {0};2346 uint8_t atom_crtc_id;2347 2348 if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))2349 params.ucDispPipeId = atom_crtc_id;2350 else2351 return BP_RESULT_BADINPUT;2352 2353 params.ucEnable =2354 bp->cmd_helper->disp_power_gating_action_to_atom(action);2355 2356 if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params))2357 result = BP_RESULT_OK;2358 2359 return result;2360}2361 2362/*******************************************************************************2363 ********************************************************************************2364 **2365 ** SET DCE CLOCK2366 **2367 ********************************************************************************2368 *******************************************************************************/2369static enum bp_result set_dce_clock_v2_1(2370 struct bios_parser *bp,2371 struct bp_set_dce_clock_parameters *bp_params);2372 2373static void init_set_dce_clock(struct bios_parser *bp)2374{2375 switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) {2376 case 1:2377 bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;2378 break;2379 default: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;2383 break;2384 }2385}2386 2387static enum bp_result set_dce_clock_v2_1(2388 struct bios_parser *bp,2389 struct bp_set_dce_clock_parameters *bp_params)2390{2391 enum bp_result result = BP_RESULT_FAILURE;2392 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;2397 2398 memset(¶ms, 0, sizeof(params));2399 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;2403 2404 params.asParam.ucDCEClkSrc = atom_pll_id;2405 params.asParam.ucDCEClkType = atom_clock_type;2406 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;2410 2411 if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)2412 params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;2413 2414 if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)2415 params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;2416 2417 if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)2418 params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;2419 }2420 else2421 /* 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);2424 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;2429 }2430 2431 return result;2432}2433