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