/* * 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 "amdgpu.h"#include "atom.h" #include "include/bios_parser_interface.h" #include "command_table.h"#include "command_table_helper.h"#include "bios_parser_helper.h"#include "bios_parser_types_internal.h" #define EXEC_BIOS_CMD_TABLE(command, params)\ (amdgpu_atom_execute_table(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \ GetIndexIntoMasterTable(COMMAND, command), \ (uint32_t *)¶ms, sizeof(params)) == 0) #define BIOS_CMD_TABLE_REVISION(command, frev, crev)\ amdgpu_atom_parse_cmd_header(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \ GetIndexIntoMasterTable(COMMAND, command), &frev, &crev) #define BIOS_CMD_TABLE_PARA_REVISION(command)\ bios_cmd_table_para_revision(bp->base.ctx->driver_context, \ GetIndexIntoMasterTable(COMMAND, command)) 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_enable_spread_spectrum_on_ppll(struct bios_parser *bp);static void init_adjust_display_pll(struct bios_parser *bp);static void init_select_crtc_source(struct bios_parser *bp);static void init_dac_encoder_control(struct bios_parser *bp);static void init_dac_load_detection(struct bios_parser *bp);static void init_dac_output_control(struct bios_parser *bp);static void init_set_crtc_timing(struct bios_parser *bp);static void init_enable_crtc(struct bios_parser *bp);static void init_enable_crtc_mem_req(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_program_clock(struct bios_parser *bp);static void init_set_dce_clock(struct bios_parser *bp); void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp){ init_dig_encoder_control(bp); init_transmitter_control(bp); init_set_pixel_clock(bp); init_enable_spread_spectrum_on_ppll(bp); init_adjust_display_pll(bp); init_select_crtc_source(bp); init_dac_encoder_control(bp); init_dac_load_detection(bp); init_dac_output_control(bp); init_set_crtc_timing(bp); init_enable_crtc(bp); init_enable_crtc_mem_req(bp); init_program_clock(bp); init_external_encoder_control(bp); init_enable_disp_power_gating(bp); init_set_dce_clock(bp);} static uint32_t bios_cmd_table_para_revision(void *dev, uint32_t index){ struct amdgpu_device *adev = dev; uint8_t frev, crev; if (amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev)) return crev; else return 0;} /******************************************************************************* ******************************************************************************** ** ** D I G E N C O D E R C O N T R O L ** ******************************************************************************** *******************************************************************************/static enum bp_result encoder_control_digx_v3( struct bios_parser *bp, struct bp_encoder_control *cntl); static enum bp_result encoder_control_digx_v4( struct bios_parser *bp, struct bp_encoder_control *cntl); static enum bp_result encoder_control_digx_v5( struct bios_parser *bp, struct bp_encoder_control *cntl); static void init_encoder_control_dig_v1(struct bios_parser *bp); static void init_dig_encoder_control(struct bios_parser *bp){ uint32_t version = BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl); switch (version) { case 2: bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3; break; case 4: bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4; break; case 5: bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5; break; default: init_encoder_control_dig_v1(bp); break; }} static enum bp_result encoder_control_dig_v1( struct bios_parser *bp, struct bp_encoder_control *cntl);static enum bp_result encoder_control_dig1_v1( struct bios_parser *bp, struct bp_encoder_control *cntl);static enum bp_result encoder_control_dig2_v1( struct bios_parser *bp, struct bp_encoder_control *cntl); static void init_encoder_control_dig_v1(struct bios_parser *bp){ struct cmd_tbl *cmd_tbl = &bp->cmd_tbl; if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl)) cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1; else cmd_tbl->encoder_control_dig1 = NULL; if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl)) cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1; else cmd_tbl->encoder_control_dig2 = NULL; cmd_tbl->dig_encoder_control = encoder_control_dig_v1;} static enum bp_result encoder_control_dig_v1( struct bios_parser *bp, struct bp_encoder_control *cntl){ enum bp_result result = BP_RESULT_FAILURE; struct cmd_tbl *cmd_tbl = &bp->cmd_tbl; if (cntl != NULL) switch (cntl->engine_id) { case ENGINE_ID_DIGA: if (cmd_tbl->encoder_control_dig1 != NULL) result = cmd_tbl->encoder_control_dig1(bp, cntl); break; case ENGINE_ID_DIGB: if (cmd_tbl->encoder_control_dig2 != NULL) result = cmd_tbl->encoder_control_dig2(bp, cntl); break; default: break; } return result;} static enum bp_result encoder_control_dig1_v1( struct bios_parser *bp, struct bp_encoder_control *cntl){ enum bp_result result = BP_RESULT_FAILURE; DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0}; bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms); if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params)) result = BP_RESULT_OK; return result;} static enum bp_result encoder_control_dig2_v1( struct bios_parser *bp, struct bp_encoder_control *cntl){ enum bp_result result = BP_RESULT_FAILURE; DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0}; bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms); if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params)) result = BP_RESULT_OK; return result;} static uint8_t dc_color_depth_to_atom(enum dc_color_depth color_depth){ switch (color_depth) { case COLOR_DEPTH_UNDEFINED: return PANEL_BPC_UNDEFINE; case COLOR_DEPTH_666: return PANEL_6BIT_PER_COLOR; default: case COLOR_DEPTH_888: return PANEL_8BIT_PER_COLOR; case COLOR_DEPTH_101010: return PANEL_10BIT_PER_COLOR; case COLOR_DEPTH_121212: return PANEL_12BIT_PER_COLOR; case COLOR_DEPTH_141414: dm_error("14-bit color not supported by ATOMBIOS\n"); return PANEL_BPC_UNDEFINE; case COLOR_DEPTH_161616: return PANEL_16BIT_PER_COLOR; }} static enum bp_result encoder_control_digx_v3( struct bios_parser *bp, struct bp_encoder_control *cntl){ enum bp_result result = BP_RESULT_FAILURE; DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0}; if (LANE_COUNT_FOUR < cntl->lanes_number) params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */ else params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */ params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id); /* We need to convert from KHz units into 10KHz units */ params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); params.ucEncoderMode = (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( cntl->signal, cntl->enable_dp_audio); params.ucLaneNum = (uint8_t)(cntl->lanes_number); params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) result = BP_RESULT_OK; return result;} static enum bp_result encoder_control_digx_v4( struct bios_parser *bp, struct bp_encoder_control *cntl){ enum bp_result result = BP_RESULT_FAILURE; DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0}; if (LANE_COUNT_FOUR < cntl->lanes_number) params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */ else params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */ params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id); /* We need to convert from KHz units into 10KHz units */ params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); params.ucEncoderMode = (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( cntl->signal, cntl->enable_dp_audio)); params.ucLaneNum = (uint8_t)(cntl->lanes_number); params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) result = BP_RESULT_OK; return result;} static enum bp_result encoder_control_digx_v5( struct bios_parser *bp, struct bp_encoder_control *cntl){ enum bp_result result = BP_RESULT_FAILURE; ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0}; params.ucDigId = (uint8_t)(cntl->engine_id); params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); params.ulPixelClock = cntl->pixel_clock / 10; params.ucDigMode = (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( cntl->signal, cntl->enable_dp_audio)); params.ucLaneNum = (uint8_t)(cntl->lanes_number); params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) switch (cntl->color_depth) { case COLOR_DEPTH_101010: params.ulPixelClock = (params.ulPixelClock * 30) / 24; break; case COLOR_DEPTH_121212: params.ulPixelClock = (params.ulPixelClock * 36) / 24; break; case COLOR_DEPTH_161616: params.ulPixelClock = (params.ulPixelClock * 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_v2( struct bios_parser *bp, struct bp_transmitter_control *cntl);static enum bp_result transmitter_control_v3( struct bios_parser *bp, struct bp_transmitter_control *cntl);static enum bp_result transmitter_control_v4( struct bios_parser *bp, struct bp_transmitter_control *cntl);static enum bp_result transmitter_control_v1_5( struct bios_parser *bp, struct bp_transmitter_control *cntl);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 = 0; if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl, frev, crev) == false) BREAK_TO_DEBUGGER(); switch (crev) { case 2: bp->cmd_tbl.transmitter_control = transmitter_control_v2; break; case 3: bp->cmd_tbl.transmitter_control = transmitter_control_v3; break; case 4: bp->cmd_tbl.transmitter_control = transmitter_control_v4; break; case 5: bp->cmd_tbl.transmitter_control = transmitter_control_v1_5; break; case 6: bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; break; default: dm_output_to_console("Don't have transmitter_control for v%d\n", crev); bp->cmd_tbl.transmitter_control = NULL; break; }} static enum bp_result transmitter_control_v2( struct bios_parser *bp, struct bp_transmitter_control *cntl){ enum bp_result result = BP_RESULT_FAILURE; DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params; enum connector_id connector_id = dal_graphics_object_id_get_connector_id(cntl->connector_obj_id); memset(¶ms, 0, sizeof(params)); switch (cntl->transmitter) { case TRANSMITTER_UNIPHY_A: case TRANSMITTER_UNIPHY_B: case TRANSMITTER_UNIPHY_C: case TRANSMITTER_UNIPHY_D: case TRANSMITTER_UNIPHY_E: case TRANSMITTER_UNIPHY_F: case TRANSMITTER_TRAVIS_LCD: break; default: return BP_RESULT_BADINPUT; } switch (cntl->action) { case TRANSMITTER_CONTROL_INIT: if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) || (CONNECTOR_ID_DUAL_LINK_DVID == connector_id)) /* on INIT this bit should be set according to the * physical connector * Bit0: dual link connector flag * =0 connector is single link connector * =1 connector is dual link connector */ params.acConfig.fDualLinkConnector = 1; /* connector object id */ params.usInitInfo = cpu_to_le16((uint8_t)cntl->connector_obj_id.id); break; case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS: /* voltage swing and pre-emphsis */ params.asMode.ucLaneSel = (uint8_t)cntl->lane_select; params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings; break; default: /* if dual-link */ if (LANE_COUNT_FOUR < cntl->lanes_number) { /* on ENABLE/DISABLE this bit should be set according to * actual timing (number of lanes) * Bit0: dual link connector flag * =0 connector is single link connector * =1 connector is dual link connector */ params.acConfig.fDualLinkConnector = 1; /* link rate, half for dual link * We need to convert from KHz units into 20KHz units */ params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 20)); } else /* link rate, half for dual link * We need to convert from KHz units into 10KHz units */ params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); break; } /* 00 - coherent mode * 01 - incoherent mode */ params.acConfig.fCoherentMode = cntl->coherent; if ((TRANSMITTER_UNIPHY_B == cntl->transmitter) || (TRANSMITTER_UNIPHY_D == cntl->transmitter) || (TRANSMITTER_UNIPHY_F == cntl->transmitter)) /* Bit2: Transmitter Link selection * =0 when bit0=0, single link A/C/E, when bit0=1, * master link A/C/E * =1 when bit0=0, single link B/D/F, when bit0=1, * master link B/D/F */ params.acConfig.ucLinkSel = 1; if (ENGINE_ID_DIGB == cntl->engine_id) /* Bit3: Transmitter data source selection * =0 DIGA is data source. * =1 DIGB is data source. * This bit is only useful when ucAction= ATOM_ENABLE */Lines 1–500 of 2693. Load more
/* * 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 "amdgpu.h" #include "atom.h" #include "include/bios_parser_interface.h" #include "command_table.h" #include "command_table_helper.h" #include "bios_parser_helper.h" #include "bios_parser_types_internal.h" #define EXEC_BIOS_CMD_TABLE(command, params)\ (amdgpu_atom_execute_table(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \ GetIndexIntoMasterTable(COMMAND, command), \ (uint32_t *)¶ms, sizeof(params)) == 0) #define BIOS_CMD_TABLE_REVISION(command, frev, crev)\ amdgpu_atom_parse_cmd_header(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \ GetIndexIntoMasterTable(COMMAND, command), &frev, &crev) #define BIOS_CMD_TABLE_PARA_REVISION(command)\ bios_cmd_table_para_revision(bp->base.ctx->driver_context, \ GetIndexIntoMasterTable(COMMAND, command)) 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_enable_spread_spectrum_on_ppll(struct bios_parser *bp); static void init_adjust_display_pll(struct bios_parser *bp); static void init_select_crtc_source(struct bios_parser *bp); static void init_dac_encoder_control(struct bios_parser *bp); static void init_dac_load_detection(struct bios_parser *bp); static void init_dac_output_control(struct bios_parser *bp); static void init_set_crtc_timing(struct bios_parser *bp); static void init_enable_crtc(struct bios_parser *bp); static void init_enable_crtc_mem_req(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_program_clock(struct bios_parser *bp); static void init_set_dce_clock(struct bios_parser *bp); void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp) { init_dig_encoder_control(bp); init_transmitter_control(bp); init_set_pixel_clock(bp); init_enable_spread_spectrum_on_ppll(bp); init_adjust_display_pll(bp); init_select_crtc_source(bp); init_dac_encoder_control(bp); init_dac_load_detection(bp); init_dac_output_control(bp); init_set_crtc_timing(bp); init_enable_crtc(bp); init_enable_crtc_mem_req(bp); init_program_clock(bp); init_external_encoder_control(bp); init_enable_disp_power_gating(bp); init_set_dce_clock(bp); } static uint32_t bios_cmd_table_para_revision(void *dev, uint32_t index) { struct amdgpu_device *adev = dev; uint8_t frev, crev; if (amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev)) return crev; else return 0; } /******************************************************************************* ******************************************************************************** ** ** D I G E N C O D E R C O N T R O L ** ******************************************************************************** *******************************************************************************/ static enum bp_result encoder_control_digx_v3( struct bios_parser *bp, struct bp_encoder_control *cntl); static enum bp_result encoder_control_digx_v4( struct bios_parser *bp, struct bp_encoder_control *cntl); static enum bp_result encoder_control_digx_v5( struct bios_parser *bp, struct bp_encoder_control *cntl); static void init_encoder_control_dig_v1(struct bios_parser *bp); static void init_dig_encoder_control(struct bios_parser *bp) { uint32_t version = BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl); switch (version) { case 2: bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3; break; case 4: bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4; break; case 5: bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5; break; default: init_encoder_control_dig_v1(bp); break; } } static enum bp_result encoder_control_dig_v1( struct bios_parser *bp, struct bp_encoder_control *cntl); static enum bp_result encoder_control_dig1_v1( struct bios_parser *bp, struct bp_encoder_control *cntl); static enum bp_result encoder_control_dig2_v1( struct bios_parser *bp, struct bp_encoder_control *cntl); static void init_encoder_control_dig_v1(struct bios_parser *bp) { struct cmd_tbl *cmd_tbl = &bp->cmd_tbl; if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl)) cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1; else cmd_tbl->encoder_control_dig1 = NULL; if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl)) cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1; else cmd_tbl->encoder_control_dig2 = NULL; cmd_tbl->dig_encoder_control = encoder_control_dig_v1; } static enum bp_result encoder_control_dig_v1( struct bios_parser *bp, struct bp_encoder_control *cntl) { enum bp_result result = BP_RESULT_FAILURE; struct cmd_tbl *cmd_tbl = &bp->cmd_tbl; if (cntl != NULL) switch (cntl->engine_id) { case ENGINE_ID_DIGA: if (cmd_tbl->encoder_control_dig1 != NULL) result = cmd_tbl->encoder_control_dig1(bp, cntl); break; case ENGINE_ID_DIGB: if (cmd_tbl->encoder_control_dig2 != NULL) result = cmd_tbl->encoder_control_dig2(bp, cntl); break; default: break; } return result; } static enum bp_result encoder_control_dig1_v1( struct bios_parser *bp, struct bp_encoder_control *cntl) { enum bp_result result = BP_RESULT_FAILURE; DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0}; bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms); if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params)) result = BP_RESULT_OK; return result; } static enum bp_result encoder_control_dig2_v1( struct bios_parser *bp, struct bp_encoder_control *cntl) { enum bp_result result = BP_RESULT_FAILURE; DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0}; bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms); if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params)) result = BP_RESULT_OK; return result; } static uint8_t dc_color_depth_to_atom(enum dc_color_depth color_depth) { switch (color_depth) { case COLOR_DEPTH_UNDEFINED: return PANEL_BPC_UNDEFINE; case COLOR_DEPTH_666: return PANEL_6BIT_PER_COLOR; default: case COLOR_DEPTH_888: return PANEL_8BIT_PER_COLOR; case COLOR_DEPTH_101010: return PANEL_10BIT_PER_COLOR; case COLOR_DEPTH_121212: return PANEL_12BIT_PER_COLOR; case COLOR_DEPTH_141414: dm_error("14-bit color not supported by ATOMBIOS\n"); return PANEL_BPC_UNDEFINE; case COLOR_DEPTH_161616: return PANEL_16BIT_PER_COLOR; } } static enum bp_result encoder_control_digx_v3( struct bios_parser *bp, struct bp_encoder_control *cntl) { enum bp_result result = BP_RESULT_FAILURE; DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0}; if (LANE_COUNT_FOUR < cntl->lanes_number) params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */ else params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */ params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id); /* We need to convert from KHz units into 10KHz units */ params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); params.ucEncoderMode = (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( cntl->signal, cntl->enable_dp_audio); params.ucLaneNum = (uint8_t)(cntl->lanes_number); params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) result = BP_RESULT_OK; return result; } static enum bp_result encoder_control_digx_v4( struct bios_parser *bp, struct bp_encoder_control *cntl) { enum bp_result result = BP_RESULT_FAILURE; DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0}; if (LANE_COUNT_FOUR < cntl->lanes_number) params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */ else params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */ params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id); /* We need to convert from KHz units into 10KHz units */ params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); params.ucEncoderMode = (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( cntl->signal, cntl->enable_dp_audio)); params.ucLaneNum = (uint8_t)(cntl->lanes_number); params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) result = BP_RESULT_OK; return result; } static enum bp_result encoder_control_digx_v5( struct bios_parser *bp, struct bp_encoder_control *cntl) { enum bp_result result = BP_RESULT_FAILURE; ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0}; params.ucDigId = (uint8_t)(cntl->engine_id); params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); params.ulPixelClock = cntl->pixel_clock / 10; params.ucDigMode = (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( cntl->signal, cntl->enable_dp_audio)); params.ucLaneNum = (uint8_t)(cntl->lanes_number); params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) switch (cntl->color_depth) { case COLOR_DEPTH_101010: params.ulPixelClock = (params.ulPixelClock * 30) / 24; break; case COLOR_DEPTH_121212: params.ulPixelClock = (params.ulPixelClock * 36) / 24; break; case COLOR_DEPTH_161616: params.ulPixelClock = (params.ulPixelClock * 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_v2( struct bios_parser *bp, struct bp_transmitter_control *cntl); static enum bp_result transmitter_control_v3( struct bios_parser *bp, struct bp_transmitter_control *cntl); static enum bp_result transmitter_control_v4( struct bios_parser *bp, struct bp_transmitter_control *cntl); static enum bp_result transmitter_control_v1_5( struct bios_parser *bp, struct bp_transmitter_control *cntl); 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 = 0; if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl, frev, crev) == false) BREAK_TO_DEBUGGER(); switch (crev) { case 2: bp->cmd_tbl.transmitter_control = transmitter_control_v2; break; case 3: bp->cmd_tbl.transmitter_control = transmitter_control_v3; break; case 4: bp->cmd_tbl.transmitter_control = transmitter_control_v4; break; case 5: bp->cmd_tbl.transmitter_control = transmitter_control_v1_5; break; case 6: bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; break; default: dm_output_to_console("Don't have transmitter_control for v%d\n", crev); bp->cmd_tbl.transmitter_control = NULL; break; } } static enum bp_result transmitter_control_v2( struct bios_parser *bp, struct bp_transmitter_control *cntl) { enum bp_result result = BP_RESULT_FAILURE; DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params; enum connector_id connector_id = dal_graphics_object_id_get_connector_id(cntl->connector_obj_id); memset(¶ms, 0, sizeof(params)); switch (cntl->transmitter) { case TRANSMITTER_UNIPHY_A: case TRANSMITTER_UNIPHY_B: case TRANSMITTER_UNIPHY_C: case TRANSMITTER_UNIPHY_D: case TRANSMITTER_UNIPHY_E: case TRANSMITTER_UNIPHY_F: case TRANSMITTER_TRAVIS_LCD: break; default: return BP_RESULT_BADINPUT; } switch (cntl->action) { case TRANSMITTER_CONTROL_INIT: if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) || (CONNECTOR_ID_DUAL_LINK_DVID == connector_id)) /* on INIT this bit should be set according to the * physical connector * Bit0: dual link connector flag * =0 connector is single link connector * =1 connector is dual link connector */ params.acConfig.fDualLinkConnector = 1; /* connector object id */ params.usInitInfo = cpu_to_le16((uint8_t)cntl->connector_obj_id.id); break; case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS: /* voltage swing and pre-emphsis */ params.asMode.ucLaneSel = (uint8_t)cntl->lane_select; params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings; break; default: /* if dual-link */ if (LANE_COUNT_FOUR < cntl->lanes_number) { /* on ENABLE/DISABLE this bit should be set according to * actual timing (number of lanes) * Bit0: dual link connector flag * =0 connector is single link connector * =1 connector is dual link connector */ params.acConfig.fDualLinkConnector = 1; /* link rate, half for dual link * We need to convert from KHz units into 20KHz units */ params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 20)); } else /* link rate, half for dual link * We need to convert from KHz units into 10KHz units */ params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); break; } /* 00 - coherent mode * 01 - incoherent mode */ params.acConfig.fCoherentMode = cntl->coherent; if ((TRANSMITTER_UNIPHY_B == cntl->transmitter) || (TRANSMITTER_UNIPHY_D == cntl->transmitter) || (TRANSMITTER_UNIPHY_F == cntl->transmitter)) /* Bit2: Transmitter Link selection * =0 when bit0=0, single link A/C/E, when bit0=1, * master link A/C/E * =1 when bit0=0, single link B/D/F, when bit0=1, * master link B/D/F */ params.acConfig.ucLinkSel = 1; if (ENGINE_ID_DIGB == cntl->engine_id) /* Bit3: Transmitter data source selection * =0 DIGA is data source. * =1 DIGB is data source. * This bit is only useful when ucAction= ATOM_ENABLE */