diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/bios/command_table2.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 813 |
1 files changed, 813 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c new file mode 100644 index 000000000000..36d158249182 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -0,0 +1,813 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "ObjectID.h" +#include "atomfirmware.h" +#include "atomfirmwareid.h" + +#include "include/bios_parser_interface.h" + +#include "command_table2.h" +#include "command_table_helper2.h" +#include "bios_parser_helper.h" +#include "bios_parser_types_internal2.h" + +#define GET_INDEX_INTO_MASTER_TABLE(MasterOrData, FieldName)\ + (((char *)(&((\ + struct atom_master_list_of_##MasterOrData##_functions_v2_1 *)0)\ + ->FieldName)-(char *)0)/sizeof(uint16_t)) + +#define EXEC_BIOS_CMD_TABLE(fname, params)\ + (cgs_atom_exec_cmd_table(bp->base.ctx->cgs_device, \ + GET_INDEX_INTO_MASTER_TABLE(command, fname), \ + ¶ms) == 0) + +#define BIOS_CMD_TABLE_REVISION(fname, frev, crev)\ + cgs_atom_get_cmd_table_revs(bp->base.ctx->cgs_device, \ + GET_INDEX_INTO_MASTER_TABLE(command, fname), &frev, &crev) + +#define BIOS_CMD_TABLE_PARA_REVISION(fname)\ + bios_cmd_table_para_revision(bp->base.ctx->cgs_device, \ + GET_INDEX_INTO_MASTER_TABLE(command, fname)) + +static void init_dig_encoder_control(struct bios_parser *bp); +static void init_transmitter_control(struct bios_parser *bp); +static void init_set_pixel_clock(struct bios_parser *bp); + +static void init_set_crtc_timing(struct bios_parser *bp); + +static void init_select_crtc_source(struct bios_parser *bp); +static void init_enable_crtc(struct bios_parser *bp); + +static void init_external_encoder_control(struct bios_parser *bp); +static void init_enable_disp_power_gating(struct bios_parser *bp); +static void init_set_dce_clock(struct bios_parser *bp); +static void init_get_smu_clock_info(struct bios_parser *bp); + +void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) +{ + init_dig_encoder_control(bp); + init_transmitter_control(bp); + init_set_pixel_clock(bp); + + init_set_crtc_timing(bp); + + init_select_crtc_source(bp); + init_enable_crtc(bp); + + init_external_encoder_control(bp); + init_enable_disp_power_gating(bp); + init_set_dce_clock(bp); + init_get_smu_clock_info(bp); +} + +static uint32_t bios_cmd_table_para_revision(void *cgs_device, + uint32_t index) +{ + uint8_t frev, crev; + + if (cgs_atom_get_cmd_table_revs(cgs_device, + index, + &frev, &crev) != 0) + return 0; + return crev; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** D I G E N C O D E R C O N T R O L + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result encoder_control_digx_v1_5( + struct bios_parser *bp, + struct bp_encoder_control *cntl); + +static void init_dig_encoder_control(struct bios_parser *bp) +{ + uint32_t version = + BIOS_CMD_TABLE_PARA_REVISION(digxencodercontrol); + + switch (version) { + case 5: + bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5; + break; + default: + bp->cmd_tbl.dig_encoder_control = NULL; + break; + } +} + +static enum bp_result encoder_control_digx_v1_5( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + struct dig_encoder_stream_setup_parameters_v1_5 params = {0}; + + params.digid = (uint8_t)(cntl->engine_id); + params.action = bp->cmd_helper->encoder_action_to_atom(cntl->action); + + params.pclk_10khz = cntl->pixel_clock / 10; + params.digmode = + (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, + cntl->enable_dp_audio)); + params.lanenum = (uint8_t)(cntl->lanes_number); + + switch (cntl->color_depth) { + case COLOR_DEPTH_888: + params.bitpercolor = PANEL_8BIT_PER_COLOR; + break; + case COLOR_DEPTH_101010: + params.bitpercolor = PANEL_10BIT_PER_COLOR; + break; + case COLOR_DEPTH_121212: + params.bitpercolor = PANEL_12BIT_PER_COLOR; + break; + case COLOR_DEPTH_161616: + params.bitpercolor = PANEL_16BIT_PER_COLOR; + break; + default: + break; + } + + if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) + switch (cntl->color_depth) { + case COLOR_DEPTH_101010: + params.pclk_10khz = + (params.pclk_10khz * 30) / 24; + break; + case COLOR_DEPTH_121212: + params.pclk_10khz = + (params.pclk_10khz * 36) / 24; + break; + case COLOR_DEPTH_161616: + params.pclk_10khz = + (params.pclk_10khz * 48) / 24; + break; + default: + break; + } + + if (EXEC_BIOS_CMD_TABLE(digxencodercontrol, params)) + result = BP_RESULT_OK; + + return result; +} + +/***************************************************************************** + ****************************************************************************** + ** + ** TRANSMITTER CONTROL + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result transmitter_control_v1_6( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); + +static void init_transmitter_control(struct bios_parser *bp) +{ + uint8_t frev; + uint8_t crev; + + if (BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev) != 0) + BREAK_TO_DEBUGGER(); + switch (crev) { + case 6: + bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; + break; + default: + bp->cmd_tbl.transmitter_control = NULL; + break; + } +} + +static enum bp_result transmitter_control_v1_6( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + const struct command_table_helper *cmd = bp->cmd_helper; + struct dig_transmitter_control_ps_allocation_v1_6 ps = { { 0 } }; + + ps.param.phyid = cmd->phy_id_to_atom(cntl->transmitter); + ps.param.action = (uint8_t)cntl->action; + + if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) + ps.param.mode_laneset.dplaneset = (uint8_t)cntl->lane_settings; + else + ps.param.mode_laneset.digmode = + cmd->signal_type_to_atom_dig_mode(cntl->signal); + + ps.param.lanenum = (uint8_t)cntl->lanes_number; + ps.param.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel); + ps.param.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id); + ps.param.connobj_id = (uint8_t)cntl->connector_obj_id.id; + ps.param.symclk_10khz = cntl->pixel_clock/10; + + + if (cntl->action == TRANSMITTER_CONTROL_ENABLE || + cntl->action == TRANSMITTER_CONTROL_ACTIAVATE || + cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) { + dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,\ + "************************%s:ps.param.symclk_10khz = %d\n",\ + __func__, ps.param.symclk_10khz); + } + + +/*color_depth not used any more, driver has deep color factor in the Phyclk*/ + if (EXEC_BIOS_CMD_TABLE(dig1transmittercontrol, ps)) + result = BP_RESULT_OK; + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** SET PIXEL CLOCK + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result set_pixel_clock_v7( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + +static void init_set_pixel_clock(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)) { + case 7: + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; + break; + default: + bp->cmd_tbl.set_pixel_clock = NULL; + break; + } +} + + + +static enum bp_result set_pixel_clock_v7( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + struct set_pixel_clock_parameter_v1_7 clk; + uint8_t controller_id; + uint32_t pll_id; + + memset(&clk, 0, sizeof(clk)); + + if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id) + && bp->cmd_helper->controller_id_to_atom(bp_params-> + controller_id, &controller_id)) { + /* Note: VBIOS still wants to use ucCRTC name which is now + * 1 byte in ULONG + *typedef struct _CRTC_PIXEL_CLOCK_FREQ + *{ + * target the pixel clock to drive the CRTC timing. + * ULONG ulPixelClock:24; + * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to + * previous version. + * ATOM_CRTC1~6, indicate the CRTC controller to + * ULONG ucCRTC:8; + * drive the pixel clock. not used for DCPLL case. + *}CRTC_PIXEL_CLOCK_FREQ; + *union + *{ + * pixel clock and CRTC id frequency + * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; + * ULONG ulDispEngClkFreq; dispclk frequency + *}; + */ + clk.crtc_id = controller_id; + clk.pll_id = (uint8_t) pll_id; + clk.encoderobjid = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + + clk.encoder_mode = (uint8_t) bp-> + cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false); + + /* We need to convert from KHz units into 10KHz units */ + clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock * + 10); + + clk.deep_color_ratio = + (uint8_t) bp->cmd_helper-> + transmitter_color_depth_to_atom( + bp_params->color_depth); + dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,\ + "************************%s:program display clock = %d"\ + "colorDepth = %d\n", __func__,\ + bp_params->target_pixel_clock, bp_params->color_depth); + + if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL; + + if (bp_params->flags.PROGRAM_PHY_PLL_ONLY) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL; + + if (bp_params->flags.SUPPORT_YUV_420) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE; + + if (bp_params->flags.SET_XTALIN_REF_SRC) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN; + + if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK; + + if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN; + + if (EXEC_BIOS_CMD_TABLE(setpixelclock, clk)) + result = BP_RESULT_OK; + } + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** SET CRTC TIMING + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result set_crtc_using_dtd_timing_v3( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params); + +static void init_set_crtc_timing(struct bios_parser *bp) +{ + uint32_t dtd_version = + BIOS_CMD_TABLE_PARA_REVISION(setcrtc_usingdtdtiming); + + switch (dtd_version) { + case 3: + bp->cmd_tbl.set_crtc_timing = + set_crtc_using_dtd_timing_v3; + break; + default: + bp->cmd_tbl.set_crtc_timing = NULL; + break; + } +} + +static enum bp_result set_crtc_using_dtd_timing_v3( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + struct set_crtc_using_dtd_timing_parameters params = {0}; + uint8_t atom_controller_id; + + if (bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &atom_controller_id)) + params.crtc_id = atom_controller_id; + + /* bios usH_Size wants h addressable size */ + params.h_size = cpu_to_le16((uint16_t)bp_params->h_addressable); + /* bios usH_Blanking_Time wants borders included in blanking */ + params.h_blanking_time = + cpu_to_le16((uint16_t)(bp_params->h_total - + bp_params->h_addressable)); + /* bios usV_Size wants v addressable size */ + params.v_size = cpu_to_le16((uint16_t)bp_params->v_addressable); + /* bios usV_Blanking_Time wants borders included in blanking */ + params.v_blanking_time = + cpu_to_le16((uint16_t)(bp_params->v_total - + bp_params->v_addressable)); + /* bios usHSyncOffset is the offset from the end of h addressable, + * our horizontalSyncStart is the offset from the beginning + * of h addressable + */ + params.h_syncoffset = + cpu_to_le16((uint16_t)(bp_params->h_sync_start - + bp_params->h_addressable)); + params.h_syncwidth = cpu_to_le16((uint16_t)bp_params->h_sync_width); + /* bios usHSyncOffset is the offset from the end of v addressable, + * our verticalSyncStart is the offset from the beginning of + * v addressable + */ + params.v_syncoffset = + cpu_to_le16((uint16_t)(bp_params->v_sync_start - + bp_params->v_addressable)); + params.v_syncwidth = cpu_to_le16((uint16_t)bp_params->v_sync_width); + + /* we assume that overscan from original timing does not get bigger + * than 255 + * we will program all the borders in the Set CRTC Overscan call below + */ + + if (bp_params->flags.HSYNC_POSITIVE_POLARITY == 0) + params.modemiscinfo = + cpu_to_le16(le16_to_cpu(params.modemiscinfo) | + ATOM_HSYNC_POLARITY); + + if (bp_params->flags.VSYNC_POSITIVE_POLARITY == 0) + params.modemiscinfo = + cpu_to_le16(le16_to_cpu(params.modemiscinfo) | + ATOM_VSYNC_POLARITY); + + if (bp_params->flags.INTERLACE) { + params.modemiscinfo = + cpu_to_le16(le16_to_cpu(params.modemiscinfo) | + ATOM_INTERLACE); + + /* original DAL code has this condition to apply this + * for non-TV/CV only + * due to complex MV testing for possible impact + * if ( pACParameters->signal != SignalType_YPbPr && + * pACParameters->signal != SignalType_Composite && + * pACParameters->signal != SignalType_SVideo) + */ + { + /* HW will deduct 0.5 line from 2nd feild. + * i.e. for 1080i, it is 2 lines for 1st field, + * 2.5 lines for the 2nd feild. we need input as 5 + * instead of 4. + * but it is 4 either from Edid data (spec CEA 861) + * or CEA timing table. + */ + params.v_syncoffset = + cpu_to_le16(le16_to_cpu(params.v_syncoffset) + + 1); + + } + } + + if (bp_params->flags.HORZ_COUNT_BY_TWO) + params.modemiscinfo = + cpu_to_le16(le16_to_cpu(params.modemiscinfo) | + 0x100); /* ATOM_DOUBLE_CLOCK_MODE */ + + if (EXEC_BIOS_CMD_TABLE(setcrtc_usingdtdtiming, params)) + result = BP_RESULT_OK; + + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** SELECT CRTC SOURCE + ** + ****************************************************************************** + *****************************************************************************/ + + +static enum bp_result select_crtc_source_v3( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); + +static void init_select_crtc_source(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source)) { + case 3: + bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; + break; + default: + bp->cmd_tbl.select_crtc_source = NULL; + break; + } +} + + +static enum bp_result select_crtc_source_v3( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params) +{ + bool result = BP_RESULT_FAILURE; + struct select_crtc_source_parameters_v2_3 params; + uint8_t atom_controller_id; + uint32_t atom_engine_id; + enum signal_type s = bp_params->signal; + + memset(¶ms, 0, sizeof(params)); + + if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, + &atom_controller_id)) + params.crtc_id = atom_controller_id; + else + return result; + + if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id, + &atom_engine_id)) + params.encoder_id = (uint8_t)atom_engine_id; + else + return result; + + if (s == SIGNAL_TYPE_EDP || + (s == SIGNAL_TYPE_DISPLAY_PORT && bp_params->sink_signal == + SIGNAL_TYPE_LVDS)) + s = SIGNAL_TYPE_LVDS; + + params.encode_mode = + bp->cmd_helper->encoder_mode_bp_to_atom( + s, bp_params->enable_dp_audio); + /* Needed for VBIOS Random Spatial Dithering feature */ + params.dst_bpc = (uint8_t)(bp_params->display_output_bit_depth); + + if (EXEC_BIOS_CMD_TABLE(selectcrtc_source, params)) + result = BP_RESULT_OK; + + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** ENABLE CRTC + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result enable_crtc_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + +static void init_enable_crtc(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)) { + case 1: + bp->cmd_tbl.enable_crtc = enable_crtc_v1; + break; + default: + bp->cmd_tbl.enable_crtc = NULL; + break; + } +} + +static enum bp_result enable_crtc_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable) +{ + bool result = BP_RESULT_FAILURE; + struct enable_crtc_parameters params = {0}; + uint8_t id; + + if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) + params.crtc_id = id; + else + return BP_RESULT_BADINPUT; + + if (enable) + params.enable = ATOM_ENABLE; + else + params.enable = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(enablecrtc, params)) + result = BP_RESULT_OK; + + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** DISPLAY PLL + ** + ****************************************************************************** + *****************************************************************************/ + + + +/****************************************************************************** + ****************************************************************************** + ** + ** EXTERNAL ENCODER CONTROL + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result external_encoder_control_v3( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl); + +static void init_external_encoder_control( + struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(externalencodercontrol)) { + case 3: + bp->cmd_tbl.external_encoder_control = + external_encoder_control_v3; + break; + default: + bp->cmd_tbl.external_encoder_control = NULL; + break; + } +} + +static enum bp_result external_encoder_control_v3( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl) +{ + /* TODO */ + return BP_RESULT_OK; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** ENABLE DISPLAY POWER GATING + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result enable_disp_power_gating_v2_1( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action); + +static void init_enable_disp_power_gating( + struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating)) { + case 1: + bp->cmd_tbl.enable_disp_power_gating = + enable_disp_power_gating_v2_1; + break; + default: + bp->cmd_tbl.enable_disp_power_gating = NULL; + break; + } +} + +static enum bp_result enable_disp_power_gating_v2_1( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action) +{ + enum bp_result result = BP_RESULT_FAILURE; + + + struct enable_disp_power_gating_ps_allocation ps = { { 0 } }; + uint8_t atom_crtc_id; + + if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id)) + ps.param.disp_pipe_id = atom_crtc_id; + else + return BP_RESULT_BADINPUT; + + ps.param.enable = + bp->cmd_helper->disp_power_gating_action_to_atom(action); + + if (EXEC_BIOS_CMD_TABLE(enabledisppowergating, ps.param)) + result = BP_RESULT_OK; + + return result; +} + +/****************************************************************************** +******************************************************************************* + ** + ** SET DCE CLOCK + ** +******************************************************************************* +*******************************************************************************/ + +static enum bp_result set_dce_clock_v2_1( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params); + +static void init_set_dce_clock(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(setdceclock)) { + case 1: + bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; + break; + default: + bp->cmd_tbl.set_dce_clock = NULL; + break; + } +} + +static enum bp_result set_dce_clock_v2_1( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + + struct set_dce_clock_ps_allocation_v2_1 params; + uint32_t atom_pll_id; + uint32_t atom_clock_type; + const struct command_table_helper *cmd = bp->cmd_helper; + + memset(¶ms, 0, sizeof(params)); + + if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) || + !cmd->dc_clock_type_to_atom(bp_params->clock_type, + &atom_clock_type)) + return BP_RESULT_BADINPUT; + + params.param.dceclksrc = atom_pll_id; + params.param.dceclktype = atom_clock_type; + + if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) { + if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK) + params.param.dceclkflag |= + DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK; + + if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK) + params.param.dceclkflag |= + DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE; + + if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK) + params.param.dceclkflag |= + DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN; + + if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK) + params.param.dceclkflag |= + DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA; + } else + /* only program clock frequency if display clock is used; + * VBIOS will program DPREFCLK + * We need to convert from KHz units into 10KHz units + */ + params.param.dceclk_10khz = cpu_to_le32( + bp_params->target_clock_frequency / 10); + dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE, + "************************%s:target_clock_frequency = %d"\ + "clock_type = %d \n", __func__,\ + bp_params->target_clock_frequency,\ + bp_params->clock_type); + + if (EXEC_BIOS_CMD_TABLE(setdceclock, params)) { + /* Convert from 10KHz units back to KHz */ + bp_params->target_clock_frequency = le32_to_cpu( + params.param.dceclk_10khz) * 10; + result = BP_RESULT_OK; + } + + return result; +} + + +/****************************************************************************** + ****************************************************************************** + ** + ** GET SMU CLOCK INFO + ** + ****************************************************************************** + *****************************************************************************/ + +static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp); + +static void init_get_smu_clock_info(struct bios_parser *bp) +{ + /* TODO add switch for table vrsion */ + bp->cmd_tbl.get_smu_clock_info = get_smu_clock_info_v3_1; + +} + +static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp) +{ + struct atom_get_smu_clock_info_parameters_v3_1 smu_input = {0}; + struct atom_get_smu_clock_info_output_parameters_v3_1 smu_output; + + smu_input.command = GET_SMU_CLOCK_INFO_V3_1_GET_PLLVCO_FREQ; + + /* Get Specific Clock */ + if (EXEC_BIOS_CMD_TABLE(getsmuclockinfo, smu_input)) { + memmove(&smu_output, &smu_input, sizeof( + struct atom_get_smu_clock_info_parameters_v3_1)); + return smu_output.atom_smu_outputclkfreq.syspllvcofreq_10khz; + } + + return 0; +} + |