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