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