1049 lines · c
1/*2 * Copyright 2012-15 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *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->logger45 46#define GET_INDEX_INTO_MASTER_TABLE(MasterOrData, FieldName)\47 (offsetof(struct atom_master_list_of_##MasterOrData##_functions_v2_1, FieldName) / sizeof(uint16_t))48 49#define EXEC_BIOS_CMD_TABLE(fname, params)\50 (amdgpu_atom_execute_table(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \51 GET_INDEX_INTO_MASTER_TABLE(command, fname), \52 (uint32_t *)¶ms, sizeof(params)) == 0)53 54#define BIOS_CMD_TABLE_REVISION(fname, frev, crev)\55 amdgpu_atom_parse_cmd_header(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \56 GET_INDEX_INTO_MASTER_TABLE(command, fname), &frev, &crev)57 58#define BIOS_CMD_TABLE_PARA_REVISION(fname)\59 bios_cmd_table_para_revision(bp->base.ctx->driver_context, \60 GET_INDEX_INTO_MASTER_TABLE(command, fname))61 62 63 64static uint32_t bios_cmd_table_para_revision(void *dev,65 uint32_t index)66{67 struct amdgpu_device *adev = dev;68 uint8_t frev, crev;69 70 if (amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context,71 index,72 &frev, &crev))73 return crev;74 else75 return 0;76}77 78/******************************************************************************79 ******************************************************************************80 **81 ** D I G E N C O D E R C O N T R O L82 **83 ******************************************************************************84 *****************************************************************************/85 86static enum bp_result encoder_control_digx_v1_5(87 struct bios_parser *bp,88 struct bp_encoder_control *cntl);89 90static enum bp_result encoder_control_fallback(91 struct bios_parser *bp,92 struct bp_encoder_control *cntl);93 94static void init_dig_encoder_control(struct bios_parser *bp)95{96 uint32_t version =97 BIOS_CMD_TABLE_PARA_REVISION(digxencodercontrol);98 99 switch (version) {100 case 5:101 bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5;102 break;103 default:104 dm_output_to_console("Don't have dig_encoder_control for v%d\n", version);105 bp->cmd_tbl.dig_encoder_control = encoder_control_fallback;106 break;107 }108}109 110static void encoder_control_dmcub(111 struct dc_dmub_srv *dmcub,112 struct dig_encoder_stream_setup_parameters_v1_5 *dig)113{114 union dmub_rb_cmd cmd;115 116 memset(&cmd, 0, sizeof(cmd));117 118 cmd.digx_encoder_control.header.type = DMUB_CMD__VBIOS;119 cmd.digx_encoder_control.header.sub_type =120 DMUB_CMD__VBIOS_DIGX_ENCODER_CONTROL;121 cmd.digx_encoder_control.header.payload_bytes =122 sizeof(cmd.digx_encoder_control) -123 sizeof(cmd.digx_encoder_control.header);124 cmd.digx_encoder_control.encoder_control.dig.stream_param = *dig;125 126 dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);127}128 129static enum bp_result encoder_control_digx_v1_5(130 struct bios_parser *bp,131 struct bp_encoder_control *cntl)132{133 enum bp_result result = BP_RESULT_FAILURE;134 struct dig_encoder_stream_setup_parameters_v1_5 params = {0};135 136 params.digid = (uint8_t)(cntl->engine_id);137 params.action = bp->cmd_helper->encoder_action_to_atom(cntl->action);138 139 params.pclk_10khz = cntl->pixel_clock / 10;140 params.digmode =141 (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(142 cntl->signal,143 cntl->enable_dp_audio));144 params.lanenum = (uint8_t)(cntl->lanes_number);145 146 switch (cntl->color_depth) {147 case COLOR_DEPTH_888:148 params.bitpercolor = PANEL_8BIT_PER_COLOR;149 break;150 case COLOR_DEPTH_101010:151 params.bitpercolor = PANEL_10BIT_PER_COLOR;152 break;153 case COLOR_DEPTH_121212:154 params.bitpercolor = PANEL_12BIT_PER_COLOR;155 break;156 case COLOR_DEPTH_161616:157 params.bitpercolor = PANEL_16BIT_PER_COLOR;158 break;159 default:160 break;161 }162 163 if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)164 switch (cntl->color_depth) {165 case COLOR_DEPTH_101010:166 params.pclk_10khz =167 (params.pclk_10khz * 30) / 24;168 break;169 case COLOR_DEPTH_121212:170 params.pclk_10khz =171 (params.pclk_10khz * 36) / 24;172 break;173 case COLOR_DEPTH_161616:174 params.pclk_10khz =175 (params.pclk_10khz * 48) / 24;176 break;177 default:178 break;179 }180 181 if (bp->base.ctx->dc->ctx->dmub_srv &&182 bp->base.ctx->dc->debug.dmub_command_table) {183 encoder_control_dmcub(bp->base.ctx->dmub_srv, ¶ms);184 return BP_RESULT_OK;185 }186 187 if (EXEC_BIOS_CMD_TABLE(digxencodercontrol, params))188 result = BP_RESULT_OK;189 190 return result;191}192 193static enum bp_result encoder_control_fallback(194 struct bios_parser *bp,195 struct bp_encoder_control *cntl)196{197 if (bp->base.ctx->dc->ctx->dmub_srv &&198 bp->base.ctx->dc->debug.dmub_command_table) {199 return encoder_control_digx_v1_5(bp, cntl);200 }201 202 return BP_RESULT_FAILURE;203}204 205/*****************************************************************************206 ******************************************************************************207 **208 ** TRANSMITTER CONTROL209 **210 ******************************************************************************211 *****************************************************************************/212 213static enum bp_result transmitter_control_v1_6(214 struct bios_parser *bp,215 struct bp_transmitter_control *cntl);216 217static enum bp_result transmitter_control_v1_7(218 struct bios_parser *bp,219 struct bp_transmitter_control *cntl);220 221static enum bp_result transmitter_control_fallback(222 struct bios_parser *bp,223 struct bp_transmitter_control *cntl);224 225static void init_transmitter_control(struct bios_parser *bp)226{227 uint8_t frev;228 uint8_t crev = 0;229 230 if (!BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev) && (bp->base.ctx->dc->ctx->dce_version <= DCN_VERSION_2_0))231 BREAK_TO_DEBUGGER();232 233 switch (crev) {234 case 6:235 bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;236 break;237 case 7:238 bp->cmd_tbl.transmitter_control = transmitter_control_v1_7;239 break;240 default:241 dm_output_to_console("Don't have transmitter_control for v%d\n", crev);242 bp->cmd_tbl.transmitter_control = transmitter_control_fallback;243 break;244 }245}246 247static void transmitter_control_dmcub(248 struct dc_dmub_srv *dmcub,249 struct dig_transmitter_control_parameters_v1_6 *dig)250{251 union dmub_rb_cmd cmd;252 253 memset(&cmd, 0, sizeof(cmd));254 255 cmd.dig1_transmitter_control.header.type = DMUB_CMD__VBIOS;256 cmd.dig1_transmitter_control.header.sub_type =257 DMUB_CMD__VBIOS_DIG1_TRANSMITTER_CONTROL;258 cmd.dig1_transmitter_control.header.payload_bytes =259 sizeof(cmd.dig1_transmitter_control) -260 sizeof(cmd.dig1_transmitter_control.header);261 cmd.dig1_transmitter_control.transmitter_control.dig = *dig;262 263 dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);264}265 266static enum bp_result transmitter_control_v1_6(267 struct bios_parser *bp,268 struct bp_transmitter_control *cntl)269{270 enum bp_result result = BP_RESULT_FAILURE;271 const struct command_table_helper *cmd = bp->cmd_helper;272 struct dig_transmitter_control_ps_allocation_v1_6 ps = { { 0 } };273 274 ps.param.phyid = cmd->phy_id_to_atom(cntl->transmitter);275 ps.param.action = (uint8_t)cntl->action;276 277 if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)278 ps.param.mode_laneset.dplaneset = (uint8_t)cntl->lane_settings;279 else280 ps.param.mode_laneset.digmode =281 cmd->signal_type_to_atom_dig_mode(cntl->signal);282 283 ps.param.lanenum = (uint8_t)cntl->lanes_number;284 ps.param.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel);285 ps.param.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);286 ps.param.connobj_id = (uint8_t)cntl->connector_obj_id.id;287 ps.param.symclk_10khz = cntl->pixel_clock/10;288 289 290 if (cntl->action == TRANSMITTER_CONTROL_ENABLE ||291 cntl->action == TRANSMITTER_CONTROL_ACTIAVATE ||292 cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) {293 DC_LOG_BIOS("%s:ps.param.symclk_10khz = %d\n",\294 __func__, ps.param.symclk_10khz);295 }296 297 if (bp->base.ctx->dc->ctx->dmub_srv &&298 bp->base.ctx->dc->debug.dmub_command_table) {299 transmitter_control_dmcub(bp->base.ctx->dmub_srv, &ps.param);300 return BP_RESULT_OK;301 }302 303/*color_depth not used any more, driver has deep color factor in the Phyclk*/304 if (EXEC_BIOS_CMD_TABLE(dig1transmittercontrol, ps))305 result = BP_RESULT_OK;306 return result;307}308 309static void transmitter_control_dmcub_v1_7(310 struct dc_dmub_srv *dmcub,311 struct dmub_dig_transmitter_control_data_v1_7 *dig)312{313 union dmub_rb_cmd cmd;314 315 memset(&cmd, 0, sizeof(cmd));316 317 cmd.dig1_transmitter_control.header.type = DMUB_CMD__VBIOS;318 cmd.dig1_transmitter_control.header.sub_type =319 DMUB_CMD__VBIOS_DIG1_TRANSMITTER_CONTROL;320 cmd.dig1_transmitter_control.header.payload_bytes =321 sizeof(cmd.dig1_transmitter_control) -322 sizeof(cmd.dig1_transmitter_control.header);323 cmd.dig1_transmitter_control.transmitter_control.dig_v1_7 = *dig;324 325 dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);326}327 328static enum bp_result transmitter_control_v1_7(329 struct bios_parser *bp,330 struct bp_transmitter_control *cntl)331{332 enum bp_result result = BP_RESULT_FAILURE;333 const struct command_table_helper *cmd = bp->cmd_helper;334 struct dmub_dig_transmitter_control_data_v1_7 dig_v1_7 = {0};335 336 uint8_t hpo_instance = (uint8_t)cntl->hpo_engine_id - ENGINE_ID_HPO_0;337 338 if (dc_is_dp_signal(cntl->signal))339 hpo_instance = (uint8_t)cntl->hpo_engine_id - ENGINE_ID_HPO_DP_0;340 341 dig_v1_7.phyid = cmd->phy_id_to_atom(cntl->transmitter);342 dig_v1_7.action = (uint8_t)cntl->action;343 344 if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)345 dig_v1_7.mode_laneset.dplaneset = (uint8_t)cntl->lane_settings;346 else347 dig_v1_7.mode_laneset.digmode =348 cmd->signal_type_to_atom_dig_mode(cntl->signal);349 350 dig_v1_7.lanenum = (uint8_t)cntl->lanes_number;351 dig_v1_7.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel);352 dig_v1_7.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);353 dig_v1_7.connobj_id = (uint8_t)cntl->connector_obj_id.id;354 dig_v1_7.HPO_instance = hpo_instance;355 dig_v1_7.symclk_units.symclk_10khz = cntl->pixel_clock/10;356 357 if (cntl->action == TRANSMITTER_CONTROL_ENABLE ||358 cntl->action == TRANSMITTER_CONTROL_ACTIAVATE ||359 cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) {360 DC_LOG_BIOS("%s:dig_v1_7.symclk_units.symclk_10khz = %d\n",361 __func__, dig_v1_7.symclk_units.symclk_10khz);362 }363 364 if (bp->base.ctx->dc->ctx->dmub_srv &&365 bp->base.ctx->dc->debug.dmub_command_table) {366 transmitter_control_dmcub_v1_7(bp->base.ctx->dmub_srv, &dig_v1_7);367 return BP_RESULT_OK;368 }369 370/*color_depth not used any more, driver has deep color factor in the Phyclk*/371 if (EXEC_BIOS_CMD_TABLE(dig1transmittercontrol, dig_v1_7))372 result = BP_RESULT_OK;373 return result;374}375 376static enum bp_result transmitter_control_fallback(377 struct bios_parser *bp,378 struct bp_transmitter_control *cntl)379{380 if (bp->base.ctx->dc->ctx->dmub_srv &&381 bp->base.ctx->dc->debug.dmub_command_table) {382 return transmitter_control_v1_7(bp, cntl);383 }384 385 return BP_RESULT_FAILURE;386}387 388/******************************************************************************389 ******************************************************************************390 **391 ** SET PIXEL CLOCK392 **393 ******************************************************************************394 *****************************************************************************/395 396static enum bp_result set_pixel_clock_v7(397 struct bios_parser *bp,398 struct bp_pixel_clock_parameters *bp_params);399 400static enum bp_result set_pixel_clock_fallback(401 struct bios_parser *bp,402 struct bp_pixel_clock_parameters *bp_params);403 404static void init_set_pixel_clock(struct bios_parser *bp)405{406 switch (BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)) {407 case 7:408 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;409 break;410 default:411 dm_output_to_console("Don't have set_pixel_clock for v%d\n",412 BIOS_CMD_TABLE_PARA_REVISION(setpixelclock));413 bp->cmd_tbl.set_pixel_clock = set_pixel_clock_fallback;414 break;415 }416}417 418static void set_pixel_clock_dmcub(419 struct dc_dmub_srv *dmcub,420 struct set_pixel_clock_parameter_v1_7 *clk)421{422 union dmub_rb_cmd cmd;423 424 memset(&cmd, 0, sizeof(cmd));425 426 cmd.set_pixel_clock.header.type = DMUB_CMD__VBIOS;427 cmd.set_pixel_clock.header.sub_type = DMUB_CMD__VBIOS_SET_PIXEL_CLOCK;428 cmd.set_pixel_clock.header.payload_bytes =429 sizeof(cmd.set_pixel_clock) -430 sizeof(cmd.set_pixel_clock.header);431 cmd.set_pixel_clock.pixel_clock.clk = *clk;432 433 dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);434}435 436static enum bp_result set_pixel_clock_v7(437 struct bios_parser *bp,438 struct bp_pixel_clock_parameters *bp_params)439{440 enum bp_result result = BP_RESULT_FAILURE;441 struct set_pixel_clock_parameter_v1_7 clk;442 uint8_t controller_id;443 uint32_t pll_id;444 445 memset(&clk, 0, sizeof(clk));446 447 if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)448 && bp->cmd_helper->controller_id_to_atom(bp_params->449 controller_id, &controller_id)) {450 /* Note: VBIOS still wants to use ucCRTC name which is now451 * 1 byte in ULONG452 *typedef struct _CRTC_PIXEL_CLOCK_FREQ453 *{454 * target the pixel clock to drive the CRTC timing.455 * ULONG ulPixelClock:24;456 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to457 * previous version.458 * ATOM_CRTC1~6, indicate the CRTC controller to459 * ULONG ucCRTC:8;460 * drive the pixel clock. not used for DCPLL case.461 *}CRTC_PIXEL_CLOCK_FREQ;462 *union463 *{464 * pixel clock and CRTC id frequency465 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;466 * ULONG ulDispEngClkFreq; dispclk frequency467 *};468 */469 clk.crtc_id = controller_id;470 clk.pll_id = (uint8_t) pll_id;471 clk.encoderobjid =472 bp->cmd_helper->encoder_id_to_atom(473 dal_graphics_object_id_get_encoder_id(474 bp_params->encoder_object_id));475 476 clk.encoder_mode = (uint8_t) bp->477 cmd_helper->encoder_mode_bp_to_atom(478 bp_params->signal_type, false);479 480 clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock_100hz);481 482 clk.deep_color_ratio =483 (uint8_t) bp->cmd_helper->484 transmitter_color_depth_to_atom(485 bp_params->color_depth);486 487 DC_LOG_BIOS("%s:program display clock = %d, tg = %d, pll = %d, "\488 "colorDepth = %d\n", __func__,489 bp_params->target_pixel_clock_100hz, (int)controller_id,490 pll_id, bp_params->color_depth);491 492 if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)493 clk.miscinfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;494 495 if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)496 clk.miscinfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;497 498 if (bp_params->flags.SUPPORT_YUV_420)499 clk.miscinfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;500 501 if (bp_params->flags.SET_XTALIN_REF_SRC)502 clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;503 504 if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)505 clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;506 507 if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)508 clk.miscinfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;509 510 if (bp->base.ctx->dc->ctx->dmub_srv &&511 bp->base.ctx->dc->debug.dmub_command_table) {512 set_pixel_clock_dmcub(bp->base.ctx->dmub_srv, &clk);513 return BP_RESULT_OK;514 }515 516 if (EXEC_BIOS_CMD_TABLE(setpixelclock, clk))517 result = BP_RESULT_OK;518 }519 return result;520}521 522static enum bp_result set_pixel_clock_fallback(523 struct bios_parser *bp,524 struct bp_pixel_clock_parameters *bp_params)525{526 if (bp->base.ctx->dc->ctx->dmub_srv &&527 bp->base.ctx->dc->debug.dmub_command_table) {528 return set_pixel_clock_v7(bp, bp_params);529 }530 531 return BP_RESULT_FAILURE;532}533 534/******************************************************************************535 ******************************************************************************536 **537 ** SET CRTC TIMING538 **539 ******************************************************************************540 *****************************************************************************/541 542static enum bp_result set_crtc_using_dtd_timing_v3(543 struct bios_parser *bp,544 struct bp_hw_crtc_timing_parameters *bp_params);545 546static void init_set_crtc_timing(struct bios_parser *bp)547{548 uint32_t dtd_version =549 BIOS_CMD_TABLE_PARA_REVISION(setcrtc_usingdtdtiming);550 551 switch (dtd_version) {552 case 3:553 bp->cmd_tbl.set_crtc_timing =554 set_crtc_using_dtd_timing_v3;555 break;556 default:557 dm_output_to_console("Don't have set_crtc_timing for v%d\n", dtd_version);558 bp->cmd_tbl.set_crtc_timing = NULL;559 break;560 }561}562 563static enum bp_result set_crtc_using_dtd_timing_v3(564 struct bios_parser *bp,565 struct bp_hw_crtc_timing_parameters *bp_params)566{567 enum bp_result result = BP_RESULT_FAILURE;568 struct set_crtc_using_dtd_timing_parameters params = {0};569 uint8_t atom_controller_id;570 571 if (bp->cmd_helper->controller_id_to_atom(572 bp_params->controller_id, &atom_controller_id))573 params.crtc_id = atom_controller_id;574 575 /* bios usH_Size wants h addressable size */576 params.h_size = cpu_to_le16((uint16_t)bp_params->h_addressable);577 /* bios usH_Blanking_Time wants borders included in blanking */578 params.h_blanking_time =579 cpu_to_le16((uint16_t)(bp_params->h_total -580 bp_params->h_addressable));581 /* bios usV_Size wants v addressable size */582 params.v_size = cpu_to_le16((uint16_t)bp_params->v_addressable);583 /* bios usV_Blanking_Time wants borders included in blanking */584 params.v_blanking_time =585 cpu_to_le16((uint16_t)(bp_params->v_total -586 bp_params->v_addressable));587 /* bios usHSyncOffset is the offset from the end of h addressable,588 * our horizontalSyncStart is the offset from the beginning589 * of h addressable590 */591 params.h_syncoffset =592 cpu_to_le16((uint16_t)(bp_params->h_sync_start -593 bp_params->h_addressable));594 params.h_syncwidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);595 /* bios usHSyncOffset is the offset from the end of v addressable,596 * our verticalSyncStart is the offset from the beginning of597 * v addressable598 */599 params.v_syncoffset =600 cpu_to_le16((uint16_t)(bp_params->v_sync_start -601 bp_params->v_addressable));602 params.v_syncwidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);603 604 /* we assume that overscan from original timing does not get bigger605 * than 255606 * we will program all the borders in the Set CRTC Overscan call below607 */608 609 if (bp_params->flags.HSYNC_POSITIVE_POLARITY == 0)610 params.modemiscinfo =611 cpu_to_le16(le16_to_cpu(params.modemiscinfo) |612 ATOM_HSYNC_POLARITY);613 614 if (bp_params->flags.VSYNC_POSITIVE_POLARITY == 0)615 params.modemiscinfo =616 cpu_to_le16(le16_to_cpu(params.modemiscinfo) |617 ATOM_VSYNC_POLARITY);618 619 if (bp_params->flags.INTERLACE) {620 params.modemiscinfo =621 cpu_to_le16(le16_to_cpu(params.modemiscinfo) |622 ATOM_INTERLACE);623 624 /* original DAL code has this condition to apply this625 * for non-TV/CV only626 * due to complex MV testing for possible impact627 * if ( pACParameters->signal != SignalType_YPbPr &&628 * pACParameters->signal != SignalType_Composite &&629 * pACParameters->signal != SignalType_SVideo)630 */631 {632 /* HW will deduct 0.5 line from 2nd feild.633 * i.e. for 1080i, it is 2 lines for 1st field,634 * 2.5 lines for the 2nd feild. we need input as 5635 * instead of 4.636 * but it is 4 either from Edid data (spec CEA 861)637 * or CEA timing table.638 */639 le16_add_cpu(¶ms.v_syncoffset, 1);640 }641 }642 643 if (bp_params->flags.HORZ_COUNT_BY_TWO)644 params.modemiscinfo =645 cpu_to_le16(le16_to_cpu(params.modemiscinfo) |646 0x100); /* ATOM_DOUBLE_CLOCK_MODE */647 648 if (EXEC_BIOS_CMD_TABLE(setcrtc_usingdtdtiming, params))649 result = BP_RESULT_OK;650 651 return result;652}653 654/******************************************************************************655 ******************************************************************************656 **657 ** ENABLE CRTC658 **659 ******************************************************************************660 *****************************************************************************/661 662static enum bp_result enable_crtc_v1(663 struct bios_parser *bp,664 enum controller_id controller_id,665 bool enable);666 667static void init_enable_crtc(struct bios_parser *bp)668{669 switch (BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)) {670 case 1:671 bp->cmd_tbl.enable_crtc = enable_crtc_v1;672 break;673 default:674 dm_output_to_console("Don't have enable_crtc for v%d\n",675 BIOS_CMD_TABLE_PARA_REVISION(enablecrtc));676 bp->cmd_tbl.enable_crtc = NULL;677 break;678 }679}680 681static enum bp_result enable_crtc_v1(682 struct bios_parser *bp,683 enum controller_id controller_id,684 bool enable)685{686 bool result = BP_RESULT_FAILURE;687 struct enable_crtc_parameters params = {0};688 uint8_t id;689 690 if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))691 params.crtc_id = id;692 else693 return BP_RESULT_BADINPUT;694 695 if (enable)696 params.enable = ATOM_ENABLE;697 else698 params.enable = ATOM_DISABLE;699 700 if (EXEC_BIOS_CMD_TABLE(enablecrtc, params))701 result = BP_RESULT_OK;702 703 return result;704}705 706/******************************************************************************707 ******************************************************************************708 **709 ** DISPLAY PLL710 **711 ******************************************************************************712 *****************************************************************************/713 714 715 716/******************************************************************************717 ******************************************************************************718 **719 ** EXTERNAL ENCODER CONTROL720 **721 ******************************************************************************722 *****************************************************************************/723 724static enum bp_result external_encoder_control_v3(725 struct bios_parser *bp,726 struct bp_external_encoder_control *cntl);727 728static void init_external_encoder_control(729 struct bios_parser *bp)730{731 switch (BIOS_CMD_TABLE_PARA_REVISION(externalencodercontrol)) {732 case 3:733 bp->cmd_tbl.external_encoder_control =734 external_encoder_control_v3;735 break;736 default:737 bp->cmd_tbl.external_encoder_control = NULL;738 break;739 }740}741 742static enum bp_result external_encoder_control_v3(743 struct bios_parser *bp,744 struct bp_external_encoder_control *cntl)745{746 /* TODO */747 return BP_RESULT_OK;748}749 750/******************************************************************************751 ******************************************************************************752 **753 ** ENABLE DISPLAY POWER GATING754 **755 ******************************************************************************756 *****************************************************************************/757 758static enum bp_result enable_disp_power_gating_v2_1(759 struct bios_parser *bp,760 enum controller_id crtc_id,761 enum bp_pipe_control_action action);762 763static enum bp_result enable_disp_power_gating_fallback(764 struct bios_parser *bp,765 enum controller_id crtc_id,766 enum bp_pipe_control_action action);767 768static void init_enable_disp_power_gating(769 struct bios_parser *bp)770{771 switch (BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating)) {772 case 1:773 bp->cmd_tbl.enable_disp_power_gating =774 enable_disp_power_gating_v2_1;775 break;776 default:777 dm_output_to_console("Don't enable_disp_power_gating enable_crtc for v%d\n",778 BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating));779 bp->cmd_tbl.enable_disp_power_gating = enable_disp_power_gating_fallback;780 break;781 }782}783 784static void enable_disp_power_gating_dmcub(785 struct dc_dmub_srv *dmcub,786 struct enable_disp_power_gating_parameters_v2_1 *pwr)787{788 union dmub_rb_cmd cmd;789 790 memset(&cmd, 0, sizeof(cmd));791 792 cmd.enable_disp_power_gating.header.type = DMUB_CMD__VBIOS;793 cmd.enable_disp_power_gating.header.sub_type =794 DMUB_CMD__VBIOS_ENABLE_DISP_POWER_GATING;795 cmd.enable_disp_power_gating.header.payload_bytes =796 sizeof(cmd.enable_disp_power_gating) -797 sizeof(cmd.enable_disp_power_gating.header);798 cmd.enable_disp_power_gating.power_gating.pwr = *pwr;799 800 dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);801}802 803static enum bp_result enable_disp_power_gating_v2_1(804 struct bios_parser *bp,805 enum controller_id crtc_id,806 enum bp_pipe_control_action action)807{808 enum bp_result result = BP_RESULT_FAILURE;809 810 811 struct enable_disp_power_gating_ps_allocation ps = { { 0 } };812 uint8_t atom_crtc_id;813 814 if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))815 ps.param.disp_pipe_id = atom_crtc_id;816 else817 return BP_RESULT_BADINPUT;818 819 ps.param.enable =820 bp->cmd_helper->disp_power_gating_action_to_atom(action);821 822 if (bp->base.ctx->dc->ctx->dmub_srv &&823 bp->base.ctx->dc->debug.dmub_command_table) {824 enable_disp_power_gating_dmcub(bp->base.ctx->dmub_srv,825 &ps.param);826 return BP_RESULT_OK;827 }828 829 if (EXEC_BIOS_CMD_TABLE(enabledisppowergating, ps.param))830 result = BP_RESULT_OK;831 832 return result;833}834 835static enum bp_result enable_disp_power_gating_fallback(836 struct bios_parser *bp,837 enum controller_id crtc_id,838 enum bp_pipe_control_action action)839{840 if (bp->base.ctx->dc->ctx->dmub_srv &&841 bp->base.ctx->dc->debug.dmub_command_table) {842 return enable_disp_power_gating_v2_1(bp, crtc_id, action);843 }844 845 return BP_RESULT_FAILURE;846}847 848/******************************************************************************849*******************************************************************************850 **851 ** SET DCE CLOCK852 **853*******************************************************************************854*******************************************************************************/855 856static enum bp_result set_dce_clock_v2_1(857 struct bios_parser *bp,858 struct bp_set_dce_clock_parameters *bp_params);859 860static void init_set_dce_clock(struct bios_parser *bp)861{862 switch (BIOS_CMD_TABLE_PARA_REVISION(setdceclock)) {863 case 1:864 bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;865 break;866 default:867 dm_output_to_console("Don't have set_dce_clock for v%d\n",868 BIOS_CMD_TABLE_PARA_REVISION(setdceclock));869 bp->cmd_tbl.set_dce_clock = NULL;870 break;871 }872}873 874static enum bp_result set_dce_clock_v2_1(875 struct bios_parser *bp,876 struct bp_set_dce_clock_parameters *bp_params)877{878 enum bp_result result = BP_RESULT_FAILURE;879 880 struct set_dce_clock_ps_allocation_v2_1 params;881 uint32_t atom_pll_id;882 uint32_t atom_clock_type;883 const struct command_table_helper *cmd = bp->cmd_helper;884 885 memset(¶ms, 0, sizeof(params));886 887 if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||888 !cmd->dc_clock_type_to_atom(bp_params->clock_type,889 &atom_clock_type))890 return BP_RESULT_BADINPUT;891 892 params.param.dceclksrc = atom_pll_id;893 params.param.dceclktype = atom_clock_type;894 895 if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {896 if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)897 params.param.dceclkflag |=898 DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;899 900 if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)901 params.param.dceclkflag |=902 DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;903 904 if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)905 params.param.dceclkflag |=906 DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;907 908 if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)909 params.param.dceclkflag |=910 DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;911 } else912 /* only program clock frequency if display clock is used;913 * VBIOS will program DPREFCLK914 * We need to convert from KHz units into 10KHz units915 */916 params.param.dceclk_10khz = cpu_to_le32(917 bp_params->target_clock_frequency / 10);918 DC_LOG_BIOS("%s:target_clock_frequency = %d"\919 "clock_type = %d \n", __func__,\920 bp_params->target_clock_frequency,\921 bp_params->clock_type);922 923 if (EXEC_BIOS_CMD_TABLE(setdceclock, params)) {924 /* Convert from 10KHz units back to KHz */925 bp_params->target_clock_frequency = le32_to_cpu(926 params.param.dceclk_10khz) * 10;927 result = BP_RESULT_OK;928 }929 930 return result;931}932 933 934/******************************************************************************935 ******************************************************************************936 **937 ** GET SMU CLOCK INFO938 **939 ******************************************************************************940 *****************************************************************************/941 942static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id);943 944static void init_get_smu_clock_info(struct bios_parser *bp)945{946 /* TODO add switch for table vrsion */947 bp->cmd_tbl.get_smu_clock_info = get_smu_clock_info_v3_1;948 949}950 951static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id)952{953 struct atom_get_smu_clock_info_parameters_v3_1 smu_input = {0};954 struct atom_get_smu_clock_info_output_parameters_v3_1 smu_output;955 956 smu_input.command = GET_SMU_CLOCK_INFO_V3_1_GET_PLLVCO_FREQ;957 smu_input.syspll_id = id;958 959 /* Get Specific Clock */960 if (EXEC_BIOS_CMD_TABLE(getsmuclockinfo, smu_input)) {961 memmove(&smu_output, &smu_input, sizeof(962 struct atom_get_smu_clock_info_parameters_v3_1));963 return smu_output.atom_smu_outputclkfreq.syspllvcofreq_10khz;964 }965 966 return 0;967}968 969/******************************************************************************970 ******************************************************************************971 **972 ** LVTMA CONTROL973 **974 ******************************************************************************975 *****************************************************************************/976 977static enum bp_result enable_lvtma_control(978 struct bios_parser *bp,979 uint8_t uc_pwr_on,980 uint8_t pwrseq_instance,981 uint8_t bypass_panel_control_wait);982 983static void init_enable_lvtma_control(struct bios_parser *bp)984{985 /* TODO add switch for table vrsion */986 bp->cmd_tbl.enable_lvtma_control = enable_lvtma_control;987 988}989 990static void enable_lvtma_control_dmcub(991 struct dc_dmub_srv *dmcub,992 uint8_t uc_pwr_on,993 uint8_t pwrseq_instance,994 uint8_t bypass_panel_control_wait)995{996 997 union dmub_rb_cmd cmd;998 999 memset(&cmd, 0, sizeof(cmd));1000 1001 cmd.lvtma_control.header.type = DMUB_CMD__VBIOS;1002 cmd.lvtma_control.header.sub_type =1003 DMUB_CMD__VBIOS_LVTMA_CONTROL;1004 cmd.lvtma_control.data.uc_pwr_action =1005 uc_pwr_on;1006 cmd.lvtma_control.data.pwrseq_inst =1007 pwrseq_instance;1008 cmd.lvtma_control.data.bypass_panel_control_wait =1009 bypass_panel_control_wait;1010 dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);1011}1012 1013static enum bp_result enable_lvtma_control(1014 struct bios_parser *bp,1015 uint8_t uc_pwr_on,1016 uint8_t pwrseq_instance,1017 uint8_t bypass_panel_control_wait)1018{1019 enum bp_result result = BP_RESULT_FAILURE;1020 1021 if (bp->base.ctx->dc->ctx->dmub_srv &&1022 bp->base.ctx->dc->debug.dmub_command_table) {1023 enable_lvtma_control_dmcub(bp->base.ctx->dmub_srv,1024 uc_pwr_on,1025 pwrseq_instance,1026 bypass_panel_control_wait);1027 return BP_RESULT_OK;1028 }1029 return result;1030}1031 1032void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp)1033{1034 init_dig_encoder_control(bp);1035 init_transmitter_control(bp);1036 init_set_pixel_clock(bp);1037 1038 init_set_crtc_timing(bp);1039 1040 init_enable_crtc(bp);1041 1042 init_external_encoder_control(bp);1043 init_enable_disp_power_gating(bp);1044 init_set_dce_clock(bp);1045 init_get_smu_clock_info(bp);1046 1047 init_enable_lvtma_control(bp);1048}1049