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 28 #include "ObjectID.h" 29 #include "atomfirmware.h" 30 31 #include "include/bios_parser_interface.h" 32 33 #include "command_table2.h" 34 #include "command_table_helper2.h" 35 #include "bios_parser_helper.h" 36 #include "bios_parser_types_internal2.h" 37 38 #define GET_INDEX_INTO_MASTER_TABLE(MasterOrData, FieldName)\ 39 (((char *)(&((\ 40 struct atom_master_list_of_##MasterOrData##_functions_v2_1 *)0)\ 41 ->FieldName)-(char *)0)/sizeof(uint16_t)) 42 43 #define EXEC_BIOS_CMD_TABLE(fname, params)\ 44 (cgs_atom_exec_cmd_table(bp->base.ctx->cgs_device, \ 45 GET_INDEX_INTO_MASTER_TABLE(command, fname), \ 46 ¶ms) == 0) 47 48 #define BIOS_CMD_TABLE_REVISION(fname, frev, crev)\ 49 cgs_atom_get_cmd_table_revs(bp->base.ctx->cgs_device, \ 50 GET_INDEX_INTO_MASTER_TABLE(command, fname), &frev, &crev) 51 52 #define BIOS_CMD_TABLE_PARA_REVISION(fname)\ 53 bios_cmd_table_para_revision(bp->base.ctx->cgs_device, \ 54 GET_INDEX_INTO_MASTER_TABLE(command, fname)) 55 56 static void init_dig_encoder_control(struct bios_parser *bp); 57 static void init_transmitter_control(struct bios_parser *bp); 58 static void init_set_pixel_clock(struct bios_parser *bp); 59 60 static void init_set_crtc_timing(struct bios_parser *bp); 61 62 static void init_select_crtc_source(struct bios_parser *bp); 63 static void init_enable_crtc(struct bios_parser *bp); 64 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_set_dce_clock(struct bios_parser *bp); 68 static void init_get_smu_clock_info(struct bios_parser *bp); 69 70 void dal_firmware_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 76 init_set_crtc_timing(bp); 77 78 init_select_crtc_source(bp); 79 init_enable_crtc(bp); 80 81 init_external_encoder_control(bp); 82 init_enable_disp_power_gating(bp); 83 init_set_dce_clock(bp); 84 init_get_smu_clock_info(bp); 85 } 86 87 static uint32_t bios_cmd_table_para_revision(void *cgs_device, 88 uint32_t index) 89 { 90 uint8_t frev, crev; 91 92 if (cgs_atom_get_cmd_table_revs(cgs_device, 93 index, 94 &frev, &crev) != 0) 95 return 0; 96 return crev; 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 107 static enum bp_result encoder_control_digx_v1_5( 108 struct bios_parser *bp, 109 struct bp_encoder_control *cntl); 110 111 static void init_dig_encoder_control(struct bios_parser *bp) 112 { 113 uint32_t version = 114 BIOS_CMD_TABLE_PARA_REVISION(digxencodercontrol); 115 116 switch (version) { 117 case 5: 118 bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5; 119 break; 120 default: 121 bp->cmd_tbl.dig_encoder_control = NULL; 122 break; 123 } 124 } 125 126 static enum bp_result encoder_control_digx_v1_5( 127 struct bios_parser *bp, 128 struct bp_encoder_control *cntl) 129 { 130 enum bp_result result = BP_RESULT_FAILURE; 131 struct dig_encoder_stream_setup_parameters_v1_5 params = {0}; 132 133 params.digid = (uint8_t)(cntl->engine_id); 134 params.action = bp->cmd_helper->encoder_action_to_atom(cntl->action); 135 136 params.pclk_10khz = cntl->pixel_clock / 10; 137 params.digmode = 138 (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( 139 cntl->signal, 140 cntl->enable_dp_audio)); 141 params.lanenum = (uint8_t)(cntl->lanes_number); 142 143 switch (cntl->color_depth) { 144 case COLOR_DEPTH_888: 145 params.bitpercolor = PANEL_8BIT_PER_COLOR; 146 break; 147 case COLOR_DEPTH_101010: 148 params.bitpercolor = PANEL_10BIT_PER_COLOR; 149 break; 150 case COLOR_DEPTH_121212: 151 params.bitpercolor = PANEL_12BIT_PER_COLOR; 152 break; 153 case COLOR_DEPTH_161616: 154 params.bitpercolor = PANEL_16BIT_PER_COLOR; 155 break; 156 default: 157 break; 158 } 159 160 if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) 161 switch (cntl->color_depth) { 162 case COLOR_DEPTH_101010: 163 params.pclk_10khz = 164 (params.pclk_10khz * 30) / 24; 165 break; 166 case COLOR_DEPTH_121212: 167 params.pclk_10khz = 168 (params.pclk_10khz * 36) / 24; 169 break; 170 case COLOR_DEPTH_161616: 171 params.pclk_10khz = 172 (params.pclk_10khz * 48) / 24; 173 break; 174 default: 175 break; 176 } 177 178 if (EXEC_BIOS_CMD_TABLE(digxencodercontrol, params)) 179 result = BP_RESULT_OK; 180 181 return result; 182 } 183 184 /***************************************************************************** 185 ****************************************************************************** 186 ** 187 ** TRANSMITTER CONTROL 188 ** 189 ****************************************************************************** 190 *****************************************************************************/ 191 192 static enum bp_result transmitter_control_v1_6( 193 struct bios_parser *bp, 194 struct bp_transmitter_control *cntl); 195 196 static void init_transmitter_control(struct bios_parser *bp) 197 { 198 uint8_t frev; 199 uint8_t crev; 200 201 if (BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev) != 0) 202 BREAK_TO_DEBUGGER(); 203 switch (crev) { 204 case 6: 205 bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; 206 break; 207 default: 208 bp->cmd_tbl.transmitter_control = NULL; 209 break; 210 } 211 } 212 213 static enum bp_result transmitter_control_v1_6( 214 struct bios_parser *bp, 215 struct bp_transmitter_control *cntl) 216 { 217 enum bp_result result = BP_RESULT_FAILURE; 218 const struct command_table_helper *cmd = bp->cmd_helper; 219 struct dig_transmitter_control_ps_allocation_v1_6 ps = { { 0 } }; 220 221 ps.param.phyid = cmd->phy_id_to_atom(cntl->transmitter); 222 ps.param.action = (uint8_t)cntl->action; 223 224 if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) 225 ps.param.mode_laneset.dplaneset = (uint8_t)cntl->lane_settings; 226 else 227 ps.param.mode_laneset.digmode = 228 cmd->signal_type_to_atom_dig_mode(cntl->signal); 229 230 ps.param.lanenum = (uint8_t)cntl->lanes_number; 231 ps.param.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel); 232 ps.param.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id); 233 ps.param.connobj_id = (uint8_t)cntl->connector_obj_id.id; 234 ps.param.symclk_10khz = cntl->pixel_clock/10; 235 236 237 if (cntl->action == TRANSMITTER_CONTROL_ENABLE || 238 cntl->action == TRANSMITTER_CONTROL_ACTIAVATE || 239 cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) { 240 dm_logger_write(bp->base.ctx->logger, LOG_BIOS,\ 241 "%s:ps.param.symclk_10khz = %d\n",\ 242 __func__, ps.param.symclk_10khz); 243 } 244 245 246 /*color_depth not used any more, driver has deep color factor in the Phyclk*/ 247 if (EXEC_BIOS_CMD_TABLE(dig1transmittercontrol, ps)) 248 result = BP_RESULT_OK; 249 return result; 250 } 251 252 /****************************************************************************** 253 ****************************************************************************** 254 ** 255 ** SET PIXEL CLOCK 256 ** 257 ****************************************************************************** 258 *****************************************************************************/ 259 260 static enum bp_result set_pixel_clock_v7( 261 struct bios_parser *bp, 262 struct bp_pixel_clock_parameters *bp_params); 263 264 static void init_set_pixel_clock(struct bios_parser *bp) 265 { 266 switch (BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)) { 267 case 7: 268 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; 269 break; 270 default: 271 bp->cmd_tbl.set_pixel_clock = NULL; 272 break; 273 } 274 } 275 276 277 278 static enum bp_result set_pixel_clock_v7( 279 struct bios_parser *bp, 280 struct bp_pixel_clock_parameters *bp_params) 281 { 282 enum bp_result result = BP_RESULT_FAILURE; 283 struct set_pixel_clock_parameter_v1_7 clk; 284 uint8_t controller_id; 285 uint32_t pll_id; 286 287 memset(&clk, 0, sizeof(clk)); 288 289 if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id) 290 && bp->cmd_helper->controller_id_to_atom(bp_params-> 291 controller_id, &controller_id)) { 292 /* Note: VBIOS still wants to use ucCRTC name which is now 293 * 1 byte in ULONG 294 *typedef struct _CRTC_PIXEL_CLOCK_FREQ 295 *{ 296 * target the pixel clock to drive the CRTC timing. 297 * ULONG ulPixelClock:24; 298 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to 299 * previous version. 300 * ATOM_CRTC1~6, indicate the CRTC controller to 301 * ULONG ucCRTC:8; 302 * drive the pixel clock. not used for DCPLL case. 303 *}CRTC_PIXEL_CLOCK_FREQ; 304 *union 305 *{ 306 * pixel clock and CRTC id frequency 307 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; 308 * ULONG ulDispEngClkFreq; dispclk frequency 309 *}; 310 */ 311 clk.crtc_id = controller_id; 312 clk.pll_id = (uint8_t) pll_id; 313 clk.encoderobjid = 314 bp->cmd_helper->encoder_id_to_atom( 315 dal_graphics_object_id_get_encoder_id( 316 bp_params->encoder_object_id)); 317 318 clk.encoder_mode = (uint8_t) bp-> 319 cmd_helper->encoder_mode_bp_to_atom( 320 bp_params->signal_type, false); 321 322 /* We need to convert from KHz units into 10KHz units */ 323 clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock * 324 10); 325 326 clk.deep_color_ratio = 327 (uint8_t) bp->cmd_helper-> 328 transmitter_color_depth_to_atom( 329 bp_params->color_depth); 330 dm_logger_write(bp->base.ctx->logger, LOG_BIOS,\ 331 "%s:program display clock = %d"\ 332 "colorDepth = %d\n", __func__,\ 333 bp_params->target_pixel_clock, bp_params->color_depth); 334 335 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) 336 clk.miscinfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL; 337 338 if (bp_params->flags.PROGRAM_PHY_PLL_ONLY) 339 clk.miscinfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL; 340 341 if (bp_params->flags.SUPPORT_YUV_420) 342 clk.miscinfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE; 343 344 if (bp_params->flags.SET_XTALIN_REF_SRC) 345 clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN; 346 347 if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC) 348 clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK; 349 350 if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK) 351 clk.miscinfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN; 352 353 if (EXEC_BIOS_CMD_TABLE(setpixelclock, clk)) 354 result = BP_RESULT_OK; 355 } 356 return result; 357 } 358 359 /****************************************************************************** 360 ****************************************************************************** 361 ** 362 ** SET CRTC TIMING 363 ** 364 ****************************************************************************** 365 *****************************************************************************/ 366 367 static enum bp_result set_crtc_using_dtd_timing_v3( 368 struct bios_parser *bp, 369 struct bp_hw_crtc_timing_parameters *bp_params); 370 371 static void init_set_crtc_timing(struct bios_parser *bp) 372 { 373 uint32_t dtd_version = 374 BIOS_CMD_TABLE_PARA_REVISION(setcrtc_usingdtdtiming); 375 376 switch (dtd_version) { 377 case 3: 378 bp->cmd_tbl.set_crtc_timing = 379 set_crtc_using_dtd_timing_v3; 380 break; 381 default: 382 bp->cmd_tbl.set_crtc_timing = NULL; 383 break; 384 } 385 } 386 387 static enum bp_result set_crtc_using_dtd_timing_v3( 388 struct bios_parser *bp, 389 struct bp_hw_crtc_timing_parameters *bp_params) 390 { 391 enum bp_result result = BP_RESULT_FAILURE; 392 struct set_crtc_using_dtd_timing_parameters params = {0}; 393 uint8_t atom_controller_id; 394 395 if (bp->cmd_helper->controller_id_to_atom( 396 bp_params->controller_id, &atom_controller_id)) 397 params.crtc_id = atom_controller_id; 398 399 /* bios usH_Size wants h addressable size */ 400 params.h_size = cpu_to_le16((uint16_t)bp_params->h_addressable); 401 /* bios usH_Blanking_Time wants borders included in blanking */ 402 params.h_blanking_time = 403 cpu_to_le16((uint16_t)(bp_params->h_total - 404 bp_params->h_addressable)); 405 /* bios usV_Size wants v addressable size */ 406 params.v_size = cpu_to_le16((uint16_t)bp_params->v_addressable); 407 /* bios usV_Blanking_Time wants borders included in blanking */ 408 params.v_blanking_time = 409 cpu_to_le16((uint16_t)(bp_params->v_total - 410 bp_params->v_addressable)); 411 /* bios usHSyncOffset is the offset from the end of h addressable, 412 * our horizontalSyncStart is the offset from the beginning 413 * of h addressable 414 */ 415 params.h_syncoffset = 416 cpu_to_le16((uint16_t)(bp_params->h_sync_start - 417 bp_params->h_addressable)); 418 params.h_syncwidth = cpu_to_le16((uint16_t)bp_params->h_sync_width); 419 /* bios usHSyncOffset is the offset from the end of v addressable, 420 * our verticalSyncStart is the offset from the beginning of 421 * v addressable 422 */ 423 params.v_syncoffset = 424 cpu_to_le16((uint16_t)(bp_params->v_sync_start - 425 bp_params->v_addressable)); 426 params.v_syncwidth = cpu_to_le16((uint16_t)bp_params->v_sync_width); 427 428 /* we assume that overscan from original timing does not get bigger 429 * than 255 430 * we will program all the borders in the Set CRTC Overscan call below 431 */ 432 433 if (bp_params->flags.HSYNC_POSITIVE_POLARITY == 0) 434 params.modemiscinfo = 435 cpu_to_le16(le16_to_cpu(params.modemiscinfo) | 436 ATOM_HSYNC_POLARITY); 437 438 if (bp_params->flags.VSYNC_POSITIVE_POLARITY == 0) 439 params.modemiscinfo = 440 cpu_to_le16(le16_to_cpu(params.modemiscinfo) | 441 ATOM_VSYNC_POLARITY); 442 443 if (bp_params->flags.INTERLACE) { 444 params.modemiscinfo = 445 cpu_to_le16(le16_to_cpu(params.modemiscinfo) | 446 ATOM_INTERLACE); 447 448 /* original DAL code has this condition to apply this 449 * for non-TV/CV only 450 * due to complex MV testing for possible impact 451 * if ( pACParameters->signal != SignalType_YPbPr && 452 * pACParameters->signal != SignalType_Composite && 453 * pACParameters->signal != SignalType_SVideo) 454 */ 455 { 456 /* HW will deduct 0.5 line from 2nd feild. 457 * i.e. for 1080i, it is 2 lines for 1st field, 458 * 2.5 lines for the 2nd feild. we need input as 5 459 * instead of 4. 460 * but it is 4 either from Edid data (spec CEA 861) 461 * or CEA timing table. 462 */ 463 params.v_syncoffset = 464 cpu_to_le16(le16_to_cpu(params.v_syncoffset) + 465 1); 466 467 } 468 } 469 470 if (bp_params->flags.HORZ_COUNT_BY_TWO) 471 params.modemiscinfo = 472 cpu_to_le16(le16_to_cpu(params.modemiscinfo) | 473 0x100); /* ATOM_DOUBLE_CLOCK_MODE */ 474 475 if (EXEC_BIOS_CMD_TABLE(setcrtc_usingdtdtiming, params)) 476 result = BP_RESULT_OK; 477 478 return result; 479 } 480 481 /****************************************************************************** 482 ****************************************************************************** 483 ** 484 ** SELECT CRTC SOURCE 485 ** 486 ****************************************************************************** 487 *****************************************************************************/ 488 489 490 static enum bp_result select_crtc_source_v3( 491 struct bios_parser *bp, 492 struct bp_crtc_source_select *bp_params); 493 494 static void init_select_crtc_source(struct bios_parser *bp) 495 { 496 switch (BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source)) { 497 case 3: 498 bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; 499 break; 500 default: 501 bp->cmd_tbl.select_crtc_source = NULL; 502 break; 503 } 504 } 505 506 507 static enum bp_result select_crtc_source_v3( 508 struct bios_parser *bp, 509 struct bp_crtc_source_select *bp_params) 510 { 511 bool result = BP_RESULT_FAILURE; 512 struct select_crtc_source_parameters_v2_3 params; 513 uint8_t atom_controller_id; 514 uint32_t atom_engine_id; 515 enum signal_type s = bp_params->signal; 516 517 memset(¶ms, 0, sizeof(params)); 518 519 if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, 520 &atom_controller_id)) 521 params.crtc_id = atom_controller_id; 522 else 523 return result; 524 525 if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id, 526 &atom_engine_id)) 527 params.encoder_id = (uint8_t)atom_engine_id; 528 else 529 return result; 530 531 if (s == SIGNAL_TYPE_EDP || 532 (s == SIGNAL_TYPE_DISPLAY_PORT && bp_params->sink_signal == 533 SIGNAL_TYPE_LVDS)) 534 s = SIGNAL_TYPE_LVDS; 535 536 params.encode_mode = 537 bp->cmd_helper->encoder_mode_bp_to_atom( 538 s, bp_params->enable_dp_audio); 539 /* Needed for VBIOS Random Spatial Dithering feature */ 540 params.dst_bpc = (uint8_t)(bp_params->display_output_bit_depth); 541 542 if (EXEC_BIOS_CMD_TABLE(selectcrtc_source, params)) 543 result = BP_RESULT_OK; 544 545 return result; 546 } 547 548 /****************************************************************************** 549 ****************************************************************************** 550 ** 551 ** ENABLE CRTC 552 ** 553 ****************************************************************************** 554 *****************************************************************************/ 555 556 static enum bp_result enable_crtc_v1( 557 struct bios_parser *bp, 558 enum controller_id controller_id, 559 bool enable); 560 561 static void init_enable_crtc(struct bios_parser *bp) 562 { 563 switch (BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)) { 564 case 1: 565 bp->cmd_tbl.enable_crtc = enable_crtc_v1; 566 break; 567 default: 568 bp->cmd_tbl.enable_crtc = NULL; 569 break; 570 } 571 } 572 573 static enum bp_result enable_crtc_v1( 574 struct bios_parser *bp, 575 enum controller_id controller_id, 576 bool enable) 577 { 578 bool result = BP_RESULT_FAILURE; 579 struct enable_crtc_parameters params = {0}; 580 uint8_t id; 581 582 if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) 583 params.crtc_id = id; 584 else 585 return BP_RESULT_BADINPUT; 586 587 if (enable) 588 params.enable = ATOM_ENABLE; 589 else 590 params.enable = ATOM_DISABLE; 591 592 if (EXEC_BIOS_CMD_TABLE(enablecrtc, params)) 593 result = BP_RESULT_OK; 594 595 return result; 596 } 597 598 /****************************************************************************** 599 ****************************************************************************** 600 ** 601 ** DISPLAY PLL 602 ** 603 ****************************************************************************** 604 *****************************************************************************/ 605 606 607 608 /****************************************************************************** 609 ****************************************************************************** 610 ** 611 ** EXTERNAL ENCODER CONTROL 612 ** 613 ****************************************************************************** 614 *****************************************************************************/ 615 616 static enum bp_result external_encoder_control_v3( 617 struct bios_parser *bp, 618 struct bp_external_encoder_control *cntl); 619 620 static void init_external_encoder_control( 621 struct bios_parser *bp) 622 { 623 switch (BIOS_CMD_TABLE_PARA_REVISION(externalencodercontrol)) { 624 case 3: 625 bp->cmd_tbl.external_encoder_control = 626 external_encoder_control_v3; 627 break; 628 default: 629 bp->cmd_tbl.external_encoder_control = NULL; 630 break; 631 } 632 } 633 634 static enum bp_result external_encoder_control_v3( 635 struct bios_parser *bp, 636 struct bp_external_encoder_control *cntl) 637 { 638 /* TODO */ 639 return BP_RESULT_OK; 640 } 641 642 /****************************************************************************** 643 ****************************************************************************** 644 ** 645 ** ENABLE DISPLAY POWER GATING 646 ** 647 ****************************************************************************** 648 *****************************************************************************/ 649 650 static enum bp_result enable_disp_power_gating_v2_1( 651 struct bios_parser *bp, 652 enum controller_id crtc_id, 653 enum bp_pipe_control_action action); 654 655 static void init_enable_disp_power_gating( 656 struct bios_parser *bp) 657 { 658 switch (BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating)) { 659 case 1: 660 bp->cmd_tbl.enable_disp_power_gating = 661 enable_disp_power_gating_v2_1; 662 break; 663 default: 664 bp->cmd_tbl.enable_disp_power_gating = NULL; 665 break; 666 } 667 } 668 669 static enum bp_result enable_disp_power_gating_v2_1( 670 struct bios_parser *bp, 671 enum controller_id crtc_id, 672 enum bp_pipe_control_action action) 673 { 674 enum bp_result result = BP_RESULT_FAILURE; 675 676 677 struct enable_disp_power_gating_ps_allocation ps = { { 0 } }; 678 uint8_t atom_crtc_id; 679 680 if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id)) 681 ps.param.disp_pipe_id = atom_crtc_id; 682 else 683 return BP_RESULT_BADINPUT; 684 685 ps.param.enable = 686 bp->cmd_helper->disp_power_gating_action_to_atom(action); 687 688 if (EXEC_BIOS_CMD_TABLE(enabledisppowergating, ps.param)) 689 result = BP_RESULT_OK; 690 691 return result; 692 } 693 694 /****************************************************************************** 695 ******************************************************************************* 696 ** 697 ** SET DCE CLOCK 698 ** 699 ******************************************************************************* 700 *******************************************************************************/ 701 702 static enum bp_result set_dce_clock_v2_1( 703 struct bios_parser *bp, 704 struct bp_set_dce_clock_parameters *bp_params); 705 706 static void init_set_dce_clock(struct bios_parser *bp) 707 { 708 switch (BIOS_CMD_TABLE_PARA_REVISION(setdceclock)) { 709 case 1: 710 bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; 711 break; 712 default: 713 bp->cmd_tbl.set_dce_clock = NULL; 714 break; 715 } 716 } 717 718 static enum bp_result set_dce_clock_v2_1( 719 struct bios_parser *bp, 720 struct bp_set_dce_clock_parameters *bp_params) 721 { 722 enum bp_result result = BP_RESULT_FAILURE; 723 724 struct set_dce_clock_ps_allocation_v2_1 params; 725 uint32_t atom_pll_id; 726 uint32_t atom_clock_type; 727 const struct command_table_helper *cmd = bp->cmd_helper; 728 729 memset(¶ms, 0, sizeof(params)); 730 731 if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) || 732 !cmd->dc_clock_type_to_atom(bp_params->clock_type, 733 &atom_clock_type)) 734 return BP_RESULT_BADINPUT; 735 736 params.param.dceclksrc = atom_pll_id; 737 params.param.dceclktype = atom_clock_type; 738 739 if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) { 740 if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK) 741 params.param.dceclkflag |= 742 DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK; 743 744 if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK) 745 params.param.dceclkflag |= 746 DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE; 747 748 if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK) 749 params.param.dceclkflag |= 750 DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN; 751 752 if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK) 753 params.param.dceclkflag |= 754 DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA; 755 } else 756 /* only program clock frequency if display clock is used; 757 * VBIOS will program DPREFCLK 758 * We need to convert from KHz units into 10KHz units 759 */ 760 params.param.dceclk_10khz = cpu_to_le32( 761 bp_params->target_clock_frequency / 10); 762 dm_logger_write(bp->base.ctx->logger, LOG_BIOS, 763 "%s:target_clock_frequency = %d"\ 764 "clock_type = %d \n", __func__,\ 765 bp_params->target_clock_frequency,\ 766 bp_params->clock_type); 767 768 if (EXEC_BIOS_CMD_TABLE(setdceclock, params)) { 769 /* Convert from 10KHz units back to KHz */ 770 bp_params->target_clock_frequency = le32_to_cpu( 771 params.param.dceclk_10khz) * 10; 772 result = BP_RESULT_OK; 773 } 774 775 return result; 776 } 777 778 779 /****************************************************************************** 780 ****************************************************************************** 781 ** 782 ** GET SMU CLOCK INFO 783 ** 784 ****************************************************************************** 785 *****************************************************************************/ 786 787 static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp); 788 789 static void init_get_smu_clock_info(struct bios_parser *bp) 790 { 791 /* TODO add switch for table vrsion */ 792 bp->cmd_tbl.get_smu_clock_info = get_smu_clock_info_v3_1; 793 794 } 795 796 static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp) 797 { 798 struct atom_get_smu_clock_info_parameters_v3_1 smu_input = {0}; 799 struct atom_get_smu_clock_info_output_parameters_v3_1 smu_output; 800 801 smu_input.command = GET_SMU_CLOCK_INFO_V3_1_GET_PLLVCO_FREQ; 802 803 /* Get Specific Clock */ 804 if (EXEC_BIOS_CMD_TABLE(getsmuclockinfo, smu_input)) { 805 memmove(&smu_output, &smu_input, sizeof( 806 struct atom_get_smu_clock_info_parameters_v3_1)); 807 return smu_output.atom_smu_outputclkfreq.syspllvcofreq_10khz; 808 } 809 810 return 0; 811 } 812 813