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