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