From: Bhuvanachandra Pinninti Date: Thu, 20 Jun 2024 12:24:23 +0000 (+0530) Subject: drm/amd/display: Move dio files into dio folder X-Git-Tag: io_uring-6.11-20240722~49^2~7^2~52 X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=d19deabe5a4566851f6ecade5ebd2e63c3248cf2;p=linux-block.git drm/amd/display: Move dio files into dio folder [why] Refactor the code of dio to unit test. [how] Moved files to respective folders and changed cMakeLists and makefiles. Acked-by: Rodrigo Siqueira Signed-off-by: Jerry Zuo Signed-off-by: Bhuvanachandra Pinninti Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 68484264831b..9923d0d620d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -27,7 +27,6 @@ DCN10 = dcn10_ipp.o \ dcn10_opp.o \ dcn10_mpc.o \ dcn10_cm_common.o \ - dcn10_stream_encoder.o dcn10_link_encoder.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c deleted file mode 100644 index e0558a78b11c..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c +++ /dev/null @@ -1,1474 +0,0 @@ -/* - * 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 "reg_helper.h" - -#include "core_types.h" -#include "link_encoder.h" -#include "dcn10_link_encoder.h" -#include "stream_encoder.h" -#include "dc_bios_types.h" - -#include "gpio_service_interface.h" - -#define CTX \ - enc10->base.ctx -#define DC_LOGGER \ - enc10->base.ctx->logger - -#define REG(reg)\ - (enc10->link_regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc10->link_shift->field_name, enc10->link_mask->field_name - - -/* - * @brief - * Trigger Source Select - * ASIC-dependent, actual values for register programming - */ -#define DCN10_DIG_FE_SOURCE_SELECT_INVALID 0x0 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGA 0x1 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGB 0x2 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGC 0x4 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGD 0x08 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGE 0x10 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGF 0x20 -#define DCN10_DIG_FE_SOURCE_SELECT_DIGG 0x40 - -enum { - DP_MST_UPDATE_MAX_RETRY = 50 -}; - -static const struct link_encoder_funcs dcn10_lnk_enc_funcs = { - .validate_output_with_stream = - dcn10_link_encoder_validate_output_with_stream, - .hw_init = dcn10_link_encoder_hw_init, - .setup = dcn10_link_encoder_setup, - .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, - .enable_dp_output = dcn10_link_encoder_enable_dp_output, - .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, - .disable_output = dcn10_link_encoder_disable_output, - .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, - .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, - .update_mst_stream_allocation_table = - dcn10_link_encoder_update_mst_stream_allocation_table, - .psr_program_dp_dphy_fast_training = - dcn10_psr_program_dp_dphy_fast_training, - .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, - .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, - .enable_hpd = dcn10_link_encoder_enable_hpd, - .disable_hpd = dcn10_link_encoder_disable_hpd, - .is_dig_enabled = dcn10_is_dig_enabled, - .get_dig_frontend = dcn10_get_dig_frontend, - .get_dig_mode = dcn10_get_dig_mode, - .destroy = dcn10_link_encoder_destroy, - .get_max_link_cap = dcn10_link_encoder_get_max_link_cap, -}; - -static enum bp_result link_transmitter_control( - struct dcn10_link_encoder *enc10, - struct bp_transmitter_control *cntl) -{ - enum bp_result result; - struct dc_bios *bp = enc10->base.ctx->dc_bios; - - result = bp->funcs->transmitter_control(bp, cntl); - - return result; -} - -static void enable_phy_bypass_mode( - struct dcn10_link_encoder *enc10, - bool enable) -{ - /* This register resides in DP back end block; - * transmitter is used for the offset - */ - REG_UPDATE(DP_DPHY_CNTL, DPHY_BYPASS, enable); - -} - -static void disable_prbs_symbols( - struct dcn10_link_encoder *enc10, - bool disable) -{ - /* This register resides in DP back end block; - * transmitter is used for the offset - */ - REG_UPDATE_4(DP_DPHY_CNTL, - DPHY_ATEST_SEL_LANE0, disable, - DPHY_ATEST_SEL_LANE1, disable, - DPHY_ATEST_SEL_LANE2, disable, - DPHY_ATEST_SEL_LANE3, disable); -} - -static void disable_prbs_mode( - struct dcn10_link_encoder *enc10) -{ - REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0); -} - -static void program_pattern_symbols( - struct dcn10_link_encoder *enc10, - uint16_t pattern_symbols[8]) -{ - /* This register resides in DP back end block; - * transmitter is used for the offset - */ - REG_SET_3(DP_DPHY_SYM0, 0, - DPHY_SYM1, pattern_symbols[0], - DPHY_SYM2, pattern_symbols[1], - DPHY_SYM3, pattern_symbols[2]); - - /* This register resides in DP back end block; - * transmitter is used for the offset - */ - REG_SET_3(DP_DPHY_SYM1, 0, - DPHY_SYM4, pattern_symbols[3], - DPHY_SYM5, pattern_symbols[4], - DPHY_SYM6, pattern_symbols[5]); - - /* This register resides in DP back end block; - * transmitter is used for the offset - */ - REG_SET_2(DP_DPHY_SYM2, 0, - DPHY_SYM7, pattern_symbols[6], - DPHY_SYM8, pattern_symbols[7]); -} - -static void set_dp_phy_pattern_d102( - struct dcn10_link_encoder *enc10) -{ - /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc10, false); - - /* For 10-bit PRBS or debug symbols - * please use the following sequence: - * - * Enable debug symbols on the lanes - */ - disable_prbs_symbols(enc10, true); - - /* Disable PRBS mode */ - disable_prbs_mode(enc10); - - /* Program debug symbols to be output */ - { - uint16_t pattern_symbols[8] = { - 0x2AA, 0x2AA, 0x2AA, 0x2AA, - 0x2AA, 0x2AA, 0x2AA, 0x2AA - }; - - program_pattern_symbols(enc10, pattern_symbols); - } - - /* Enable phy bypass mode to enable the test pattern */ - - enable_phy_bypass_mode(enc10, true); -} - -static void set_link_training_complete( - struct dcn10_link_encoder *enc10, - bool complete) -{ - /* This register resides in DP back end block; - * transmitter is used for the offset - */ - REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete); - -} - -void dcn10_link_encoder_set_dp_phy_pattern_training_pattern( - struct link_encoder *enc, - uint32_t index) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - /* Write Training Pattern */ - - REG_WRITE(DP_DPHY_TRAINING_PATTERN_SEL, index); - - /* Set HW Register Training Complete to false */ - - set_link_training_complete(enc10, false); - - /* Disable PHY Bypass mode to output Training Pattern */ - - enable_phy_bypass_mode(enc10, false); - - /* Disable PRBS mode */ - disable_prbs_mode(enc10); -} - -static void setup_panel_mode( - struct dcn10_link_encoder *enc10, - enum dp_panel_mode panel_mode) -{ - uint32_t value; - - if (!REG(DP_DPHY_INTERNAL_CTRL)) - return; - - value = REG_READ(DP_DPHY_INTERNAL_CTRL); - - switch (panel_mode) { - case DP_PANEL_MODE_EDP: - value = 0x1; - break; - case DP_PANEL_MODE_SPECIAL: - value = 0x11; - break; - default: - value = 0x0; - break; - } - - REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); -} - -static void set_dp_phy_pattern_symbol_error( - struct dcn10_link_encoder *enc10) -{ - /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc10, false); - - /* program correct panel mode*/ - setup_panel_mode(enc10, DP_PANEL_MODE_DEFAULT); - - /* A PRBS23 pattern is used for most DP electrical measurements. */ - - /* Enable PRBS symbols on the lanes */ - disable_prbs_symbols(enc10, false); - - /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */ - REG_UPDATE_2(DP_DPHY_PRBS_CNTL, - DPHY_PRBS_SEL, 1, - DPHY_PRBS_EN, 1); - - /* Enable phy bypass mode to enable the test pattern */ - enable_phy_bypass_mode(enc10, true); -} - -static void set_dp_phy_pattern_prbs7( - struct dcn10_link_encoder *enc10) -{ - /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc10, false); - - /* A PRBS7 pattern is used for most DP electrical measurements. */ - - /* Enable PRBS symbols on the lanes */ - disable_prbs_symbols(enc10, false); - - /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */ - REG_UPDATE_2(DP_DPHY_PRBS_CNTL, - DPHY_PRBS_SEL, 0, - DPHY_PRBS_EN, 1); - - /* Enable phy bypass mode to enable the test pattern */ - enable_phy_bypass_mode(enc10, true); -} - -static void set_dp_phy_pattern_80bit_custom( - struct dcn10_link_encoder *enc10, - const uint8_t *pattern) -{ - /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc10, false); - - /* Enable debug symbols on the lanes */ - - disable_prbs_symbols(enc10, true); - - /* Enable PHY bypass mode to enable the test pattern */ - /* TODO is it really needed ? */ - - enable_phy_bypass_mode(enc10, true); - - /* Program 80 bit custom pattern */ - { - uint16_t pattern_symbols[8]; - - pattern_symbols[0] = - ((pattern[1] & 0x03) << 8) | pattern[0]; - pattern_symbols[1] = - ((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f); - pattern_symbols[2] = - ((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f); - pattern_symbols[3] = - (pattern[4] << 2) | ((pattern[3] >> 6) & 0x03); - pattern_symbols[4] = - ((pattern[6] & 0x03) << 8) | pattern[5]; - pattern_symbols[5] = - ((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f); - pattern_symbols[6] = - ((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f); - pattern_symbols[7] = - (pattern[9] << 2) | ((pattern[8] >> 6) & 0x03); - - program_pattern_symbols(enc10, pattern_symbols); - } - - /* Enable phy bypass mode to enable the test pattern */ - - enable_phy_bypass_mode(enc10, true); -} - -static void set_dp_phy_pattern_hbr2_compliance_cp2520_2( - struct dcn10_link_encoder *enc10, - unsigned int cp2520_pattern) -{ - - /* previously there is a register DP_HBR2_EYE_PATTERN - * that is enabled to get the pattern. - * But it does not work with the latest spec change, - * so we are programming the following registers manually. - * - * The following settings have been confirmed - * by Nick Chorney and Sandra Liu - */ - - /* Disable PHY Bypass mode to setup the test pattern */ - - enable_phy_bypass_mode(enc10, false); - - /* Setup DIG encoder in DP SST mode */ - enc10->base.funcs->setup(&enc10->base, SIGNAL_TYPE_DISPLAY_PORT); - - /* ensure normal panel mode. */ - setup_panel_mode(enc10, DP_PANEL_MODE_DEFAULT); - - /* no vbid after BS (SR) - * DP_LINK_FRAMING_CNTL changed history Sandra Liu - * 11000260 / 11000104 / 110000FC - */ - REG_UPDATE_3(DP_LINK_FRAMING_CNTL, - DP_IDLE_BS_INTERVAL, 0xFC, - DP_VBID_DISABLE, 1, - DP_VID_ENHANCED_FRAME_MODE, 1); - - /* swap every BS with SR */ - REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0); - - /* select cp2520 patterns */ - if (REG(DP_DPHY_HBR2_PATTERN_CONTROL)) - REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL, - DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern); - else - /* pre-DCE11 can only generate CP2520 pattern 2 */ - ASSERT(cp2520_pattern == 2); - - /* set link training complete */ - set_link_training_complete(enc10, true); - - /* disable video stream */ - REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); - - /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc10, false); -} - -static void set_dp_phy_pattern_passthrough_mode( - struct dcn10_link_encoder *enc10, - enum dp_panel_mode panel_mode) -{ - /* program correct panel mode */ - setup_panel_mode(enc10, panel_mode); - - /* restore LINK_FRAMING_CNTL and DPHY_SCRAMBLER_BS_COUNT - * in case we were doing HBR2 compliance pattern before - */ - REG_UPDATE_3(DP_LINK_FRAMING_CNTL, - DP_IDLE_BS_INTERVAL, 0x2000, - DP_VBID_DISABLE, 0, - DP_VID_ENHANCED_FRAME_MODE, 1); - - REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF); - - /* set link training complete */ - set_link_training_complete(enc10, true); - - /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc10, false); - - /* Disable PRBS mode */ - disable_prbs_mode(enc10); -} - -/* return value is bit-vector */ -static uint8_t get_frontend_source( - enum engine_id engine) -{ - switch (engine) { - case ENGINE_ID_DIGA: - return DCN10_DIG_FE_SOURCE_SELECT_DIGA; - case ENGINE_ID_DIGB: - return DCN10_DIG_FE_SOURCE_SELECT_DIGB; - case ENGINE_ID_DIGC: - return DCN10_DIG_FE_SOURCE_SELECT_DIGC; - case ENGINE_ID_DIGD: - return DCN10_DIG_FE_SOURCE_SELECT_DIGD; - case ENGINE_ID_DIGE: - return DCN10_DIG_FE_SOURCE_SELECT_DIGE; - case ENGINE_ID_DIGF: - return DCN10_DIG_FE_SOURCE_SELECT_DIGF; - case ENGINE_ID_DIGG: - return DCN10_DIG_FE_SOURCE_SELECT_DIGG; - default: - ASSERT_CRITICAL(false); - return DCN10_DIG_FE_SOURCE_SELECT_INVALID; - } -} - -unsigned int dcn10_get_dig_frontend(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - int32_t value; - enum engine_id result; - - REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value); - - switch (value) { - case DCN10_DIG_FE_SOURCE_SELECT_DIGA: - result = ENGINE_ID_DIGA; - break; - case DCN10_DIG_FE_SOURCE_SELECT_DIGB: - result = ENGINE_ID_DIGB; - break; - case DCN10_DIG_FE_SOURCE_SELECT_DIGC: - result = ENGINE_ID_DIGC; - break; - case DCN10_DIG_FE_SOURCE_SELECT_DIGD: - result = ENGINE_ID_DIGD; - break; - case DCN10_DIG_FE_SOURCE_SELECT_DIGE: - result = ENGINE_ID_DIGE; - break; - case DCN10_DIG_FE_SOURCE_SELECT_DIGF: - result = ENGINE_ID_DIGF; - break; - case DCN10_DIG_FE_SOURCE_SELECT_DIGG: - result = ENGINE_ID_DIGG; - break; - default: - // invalid source select DIG - result = ENGINE_ID_UNKNOWN; - } - - return result; - -} - -void enc1_configure_encoder( - struct dcn10_link_encoder *enc10, - const struct dc_link_settings *link_settings) -{ - /* set number of lanes */ - REG_SET(DP_CONFIG, 0, - DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE); - - /* setup scrambler */ - REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1); -} - -void dcn10_psr_program_dp_dphy_fast_training(struct link_encoder *enc, - bool exit_link_training_required) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - if (exit_link_training_required) - REG_UPDATE(DP_DPHY_FAST_TRAINING, - DPHY_RX_FAST_TRAINING_CAPABLE, 1); - else { - REG_UPDATE(DP_DPHY_FAST_TRAINING, - DPHY_RX_FAST_TRAINING_CAPABLE, 0); - /*In DCE 11, we are able to pre-program a Force SR register - * to be able to trigger SR symbol after 5 idle patterns - * transmitted. Upon PSR Exit, DMCU can trigger - * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to - * DPHY_LOAD_BS_COUNT_START and the internal counter - * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be - * replaced by SR symbol once. - */ - - REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5); - } -} - -void dcn10_psr_program_secondary_packet(struct link_encoder *enc, - unsigned int sdp_transmit_line_num_deadline) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - REG_UPDATE_2(DP_SEC_CNTL1, - DP_SEC_GSP0_LINE_NUM, sdp_transmit_line_num_deadline, - DP_SEC_GSP0_PRIORITY, 1); -} - -bool dcn10_is_dig_enabled(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t value; - - REG_GET(DIG_BE_EN_CNTL, DIG_ENABLE, &value); - return value; -} - -static void link_encoder_disable(struct dcn10_link_encoder *enc10) -{ - /* reset training pattern */ - REG_SET(DP_DPHY_TRAINING_PATTERN_SEL, 0, - DPHY_TRAINING_PATTERN_SEL, 0); - - /* reset training complete */ - REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); - - /* reset panel mode */ - setup_panel_mode(enc10, DP_PANEL_MODE_DEFAULT); -} - -static void hpd_initialize( - struct dcn10_link_encoder *enc10) -{ - /* Associate HPD with DIG_BE */ - enum hpd_source_id hpd_source = enc10->base.hpd_source; - - REG_UPDATE(DIG_BE_CNTL, DIG_HPD_SELECT, hpd_source); -} - -bool dcn10_link_encoder_validate_dvi_output( - const struct dcn10_link_encoder *enc10, - enum signal_type connector_signal, - enum signal_type signal, - const struct dc_crtc_timing *crtc_timing) -{ - uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK; - - if (signal == SIGNAL_TYPE_DVI_DUAL_LINK) - max_pixel_clock *= 2; - - /* This handles the case of HDMI downgrade to DVI we don't want to - * we don't want to cap the pixel clock if the DDI is not DVI. - */ - if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK && - connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) - max_pixel_clock = enc10->base.features.max_hdmi_pixel_clock; - - /* DVI only support RGB pixel encoding */ - if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) - return false; - - /*connect DVI via adpater's HDMI connector*/ - if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || - connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) && - signal != SIGNAL_TYPE_HDMI_TYPE_A && - crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10)) - return false; - if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) - return false; - - if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10)) - return false; - - /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */ - switch (crtc_timing->display_color_depth) { - case COLOR_DEPTH_666: - case COLOR_DEPTH_888: - break; - case COLOR_DEPTH_101010: - case COLOR_DEPTH_161616: - if (signal != SIGNAL_TYPE_DVI_DUAL_LINK) - return false; - break; - default: - return false; - } - - return true; -} - -static bool dcn10_link_encoder_validate_hdmi_output( - const struct dcn10_link_encoder *enc10, - const struct dc_crtc_timing *crtc_timing, - const struct dc_edid_caps *edid_caps, - int adjusted_pix_clk_100hz) -{ - enum dc_color_depth max_deep_color = - enc10->base.features.max_hdmi_deep_color; - - // check pixel clock against edid specified max TMDS clk - if (edid_caps->max_tmds_clk_mhz != 0 && - adjusted_pix_clk_100hz > edid_caps->max_tmds_clk_mhz * 10000) - return false; - - if (max_deep_color < crtc_timing->display_color_depth) - return false; - - if (crtc_timing->display_color_depth < COLOR_DEPTH_888) - return false; - if (adjusted_pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) - return false; - - if ((adjusted_pix_clk_100hz == 0) || - (adjusted_pix_clk_100hz > (enc10->base.features.max_hdmi_pixel_clock * 10))) - return false; - - /* DCE11 HW does not support 420 */ - if (!enc10->base.features.hdmi_ycbcr420_supported && - crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) - return false; - - if ((!enc10->base.features.flags.bits.HDMI_6GB_EN || - enc10->base.ctx->dc->debug.hdmi20_disable) && - adjusted_pix_clk_100hz >= 3000000) - return false; - if (enc10->base.ctx->dc->debug.hdmi20_disable && - crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) - return false; - return true; -} - -bool dcn10_link_encoder_validate_dp_output( - const struct dcn10_link_encoder *enc10, - const struct dc_crtc_timing *crtc_timing) -{ - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) { - if (!enc10->base.features.dp_ycbcr420_supported) - return false; - } - - return true; -} - -void dcn10_link_encoder_construct( - struct dcn10_link_encoder *enc10, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask) -{ - struct bp_encoder_cap_info bp_cap_info = {0}; - const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; - enum bp_result result = BP_RESULT_OK; - - enc10->base.funcs = &dcn10_lnk_enc_funcs; - enc10->base.ctx = init_data->ctx; - enc10->base.id = init_data->encoder; - - enc10->base.hpd_source = init_data->hpd_source; - enc10->base.connector = init_data->connector; - - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - - enc10->base.features = *enc_features; - - enc10->base.transmitter = init_data->transmitter; - - /* set the flag to indicate whether driver poll the I2C data pin - * while doing the DP sink detect - */ - -/* if (dal_adapter_service_is_feature_supported(as, - FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) - enc10->base.features.flags.bits. - DP_SINK_DETECT_POLL_DATA_PIN = true;*/ - - enc10->base.output_signals = - SIGNAL_TYPE_DVI_SINGLE_LINK | - SIGNAL_TYPE_DVI_DUAL_LINK | - SIGNAL_TYPE_LVDS | - SIGNAL_TYPE_DISPLAY_PORT | - SIGNAL_TYPE_DISPLAY_PORT_MST | - SIGNAL_TYPE_EDP | - SIGNAL_TYPE_HDMI_TYPE_A; - - /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. - * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. - * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer - * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. - * Prefer DIG assignment is decided by board design. - * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design - * and VBIOS will filter out 7 UNIPHY for DCE 8.0. - * By this, adding DIGG should not hurt DCE 8.0. - * This will let DCE 8.1 share DCE 8.0 as much as possible - */ - - enc10->link_regs = link_regs; - enc10->aux_regs = aux_regs; - enc10->hpd_regs = hpd_regs; - enc10->link_shift = link_shift; - enc10->link_mask = link_mask; - - switch (enc10->base.transmitter) { - case TRANSMITTER_UNIPHY_A: - enc10->base.preferred_engine = ENGINE_ID_DIGA; - break; - case TRANSMITTER_UNIPHY_B: - enc10->base.preferred_engine = ENGINE_ID_DIGB; - break; - case TRANSMITTER_UNIPHY_C: - enc10->base.preferred_engine = ENGINE_ID_DIGC; - break; - case TRANSMITTER_UNIPHY_D: - enc10->base.preferred_engine = ENGINE_ID_DIGD; - break; - case TRANSMITTER_UNIPHY_E: - enc10->base.preferred_engine = ENGINE_ID_DIGE; - break; - case TRANSMITTER_UNIPHY_F: - enc10->base.preferred_engine = ENGINE_ID_DIGF; - break; - case TRANSMITTER_UNIPHY_G: - enc10->base.preferred_engine = ENGINE_ID_DIGG; - break; - default: - ASSERT_CRITICAL(false); - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - } - - /* default to one to mirror Windows behavior */ - enc10->base.features.flags.bits.HDMI_6GB_EN = 1; - - result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, - enc10->base.id, &bp_cap_info); - - /* Override features with DCE-specific values */ - if (result == BP_RESULT_OK) { - enc10->base.features.flags.bits.IS_HBR2_CAPABLE = - bp_cap_info.DP_HBR2_EN; - enc10->base.features.flags.bits.IS_HBR3_CAPABLE = - bp_cap_info.DP_HBR3_EN; - enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; - enc10->base.features.flags.bits.DP_IS_USB_C = - bp_cap_info.DP_IS_USB_C; - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, - result); - } - if (enc10->base.ctx->dc->debug.hdmi20_disable) { - enc10->base.features.flags.bits.HDMI_6GB_EN = 0; - } -} - -bool dcn10_link_encoder_validate_output_with_stream( - struct link_encoder *enc, - const struct dc_stream_state *stream) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - bool is_valid; - - //if SCDC (340-600MHz) is disabled, set to HDMI 1.4 timing limit - if (stream->sink->edid_caps.panel_patch.skip_scdc_overwrite && - enc10->base.features.max_hdmi_pixel_clock > 300000) - enc10->base.features.max_hdmi_pixel_clock = 300000; - - switch (stream->signal) { - case SIGNAL_TYPE_DVI_SINGLE_LINK: - case SIGNAL_TYPE_DVI_DUAL_LINK: - is_valid = dcn10_link_encoder_validate_dvi_output( - enc10, - stream->link->connector_signal, - stream->signal, - &stream->timing); - break; - case SIGNAL_TYPE_HDMI_TYPE_A: - is_valid = dcn10_link_encoder_validate_hdmi_output( - enc10, - &stream->timing, - &stream->sink->edid_caps, - stream->phy_pix_clk * 10); - break; - case SIGNAL_TYPE_DISPLAY_PORT: - case SIGNAL_TYPE_DISPLAY_PORT_MST: - is_valid = dcn10_link_encoder_validate_dp_output( - enc10, &stream->timing); - break; - case SIGNAL_TYPE_EDP: - is_valid = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? true : false; - break; - case SIGNAL_TYPE_VIRTUAL: - is_valid = true; - break; - default: - is_valid = false; - break; - } - - return is_valid; -} - -void dcn10_link_encoder_hw_init( - struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - struct bp_transmitter_control cntl = { 0 }; - enum bp_result result; - - cntl.action = TRANSMITTER_CONTROL_INIT; - cntl.engine_id = ENGINE_ID_UNKNOWN; - cntl.transmitter = enc10->base.transmitter; - cntl.connector_obj_id = enc10->base.connector; - cntl.lanes_number = LANE_COUNT_FOUR; - cntl.coherent = false; - cntl.hpd_sel = enc10->base.hpd_source; - - if (enc10->base.connector.id == CONNECTOR_ID_EDP) - cntl.signal = SIGNAL_TYPE_EDP; - - result = link_transmitter_control(enc10, &cntl); - - if (result != BP_RESULT_OK) { - DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", - __func__); - BREAK_TO_DEBUGGER(); - return; - } - - if (enc10->base.connector.id == CONNECTOR_ID_LVDS) { - cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS; - - result = link_transmitter_control(enc10, &cntl); - - ASSERT(result == BP_RESULT_OK); - - } - dcn10_aux_initialize(enc10); - - /* reinitialize HPD. - * hpd_initialize() will pass DIG_FE id to HW context. - * All other routine within HW context will use fe_engine_offset - * as DIG_FE id even caller pass DIG_FE id. - * So this routine must be called first. - */ - hpd_initialize(enc10); -} - -void dcn10_link_encoder_destroy(struct link_encoder **enc) -{ - kfree(TO_DCN10_LINK_ENC(*enc)); - *enc = NULL; -} - -void dcn10_link_encoder_setup( - struct link_encoder *enc, - enum signal_type signal) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - switch (signal) { - case SIGNAL_TYPE_EDP: - case SIGNAL_TYPE_DISPLAY_PORT: - /* DP SST */ - REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 0); - break; - case SIGNAL_TYPE_LVDS: - /* LVDS */ - REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 1); - break; - case SIGNAL_TYPE_DVI_SINGLE_LINK: - case SIGNAL_TYPE_DVI_DUAL_LINK: - /* TMDS-DVI */ - REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 2); - break; - case SIGNAL_TYPE_HDMI_TYPE_A: - /* TMDS-HDMI */ - REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 3); - break; - case SIGNAL_TYPE_DISPLAY_PORT_MST: - /* DP MST */ - REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 5); - break; - default: - ASSERT_CRITICAL(false); - /* invalid mode ! */ - break; - } - -} - -/* TODO: still need depth or just pass in adjusted pixel clock? */ -void dcn10_link_encoder_enable_tmds_output( - struct link_encoder *enc, - enum clock_source_id clock_source, - enum dc_color_depth color_depth, - enum signal_type signal, - uint32_t pixel_clock) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - struct bp_transmitter_control cntl = { 0 }; - enum bp_result result; - - /* Enable the PHY */ - - cntl.action = TRANSMITTER_CONTROL_ENABLE; - cntl.engine_id = enc->preferred_engine; - cntl.transmitter = enc10->base.transmitter; - cntl.pll_id = clock_source; - cntl.signal = signal; - if (cntl.signal == SIGNAL_TYPE_DVI_DUAL_LINK) - cntl.lanes_number = 8; - else - cntl.lanes_number = 4; - - cntl.hpd_sel = enc10->base.hpd_source; - - cntl.pixel_clock = pixel_clock; - cntl.color_depth = color_depth; - - result = link_transmitter_control(enc10, &cntl); - - if (result != BP_RESULT_OK) { - DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", - __func__); - BREAK_TO_DEBUGGER(); - } -} - -void dcn10_link_encoder_enable_tmds_output_with_clk_pattern_wa( - struct link_encoder *enc, - enum clock_source_id clock_source, - enum dc_color_depth color_depth, - enum signal_type signal, - uint32_t pixel_clock) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - dcn10_link_encoder_enable_tmds_output( - enc, clock_source, color_depth, signal, pixel_clock); - - REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); -} - -/* enables DP PHY output */ -void dcn10_link_encoder_enable_dp_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - struct bp_transmitter_control cntl = { 0 }; - enum bp_result result; - - /* Enable the PHY */ - - /* number_of_lanes is used for pixel clock adjust, - * but it's not passed to asic_control. - * We need to set number of lanes manually. - */ - enc1_configure_encoder(enc10, link_settings); - - cntl.action = TRANSMITTER_CONTROL_ENABLE; - cntl.engine_id = enc->preferred_engine; - cntl.transmitter = enc10->base.transmitter; - cntl.pll_id = clock_source; - cntl.signal = SIGNAL_TYPE_DISPLAY_PORT; - cntl.lanes_number = link_settings->lane_count; - cntl.hpd_sel = enc10->base.hpd_source; - cntl.pixel_clock = link_settings->link_rate - * LINK_RATE_REF_FREQ_IN_KHZ; - /* TODO: check if undefined works */ - cntl.color_depth = COLOR_DEPTH_UNDEFINED; - - result = link_transmitter_control(enc10, &cntl); - - if (result != BP_RESULT_OK) { - DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", - __func__); - BREAK_TO_DEBUGGER(); - } -} - -/* enables DP PHY output in MST mode */ -void dcn10_link_encoder_enable_dp_mst_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - struct bp_transmitter_control cntl = { 0 }; - enum bp_result result; - - /* Enable the PHY */ - - /* number_of_lanes is used for pixel clock adjust, - * but it's not passed to asic_control. - * We need to set number of lanes manually. - */ - enc1_configure_encoder(enc10, link_settings); - - cntl.action = TRANSMITTER_CONTROL_ENABLE; - cntl.engine_id = ENGINE_ID_UNKNOWN; - cntl.transmitter = enc10->base.transmitter; - cntl.pll_id = clock_source; - cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST; - cntl.lanes_number = link_settings->lane_count; - cntl.hpd_sel = enc10->base.hpd_source; - cntl.pixel_clock = link_settings->link_rate - * LINK_RATE_REF_FREQ_IN_KHZ; - /* TODO: check if undefined works */ - cntl.color_depth = COLOR_DEPTH_UNDEFINED; - - result = link_transmitter_control(enc10, &cntl); - - if (result != BP_RESULT_OK) { - DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", - __func__); - BREAK_TO_DEBUGGER(); - } -} -/* - * @brief - * Disable transmitter and its encoder - */ -void dcn10_link_encoder_disable_output( - struct link_encoder *enc, - enum signal_type signal) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - struct bp_transmitter_control cntl = { 0 }; - enum bp_result result; - - if (enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc)) { - /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */ - /*in DP_Alt_No_Connect case, we turn off the dig already, - after excuation the PHY w/a sequence, not allow touch PHY any more*/ - return; - } - /* Power-down RX and disable GPU PHY should be paired. - * Disabling PHY without powering down RX may cause - * symbol lock loss, on which we will get DP Sink interrupt. - */ - - /* There is a case for the DP active dongles - * where we want to disable the PHY but keep RX powered, - * for those we need to ignore DP Sink interrupt - * by checking lane count that has been set - * on the last do_enable_output(). - */ - - /* disable transmitter */ - cntl.action = TRANSMITTER_CONTROL_DISABLE; - cntl.transmitter = enc10->base.transmitter; - cntl.hpd_sel = enc10->base.hpd_source; - cntl.signal = signal; - cntl.connector_obj_id = enc10->base.connector; - - result = link_transmitter_control(enc10, &cntl); - - if (result != BP_RESULT_OK) { - DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", - __func__); - BREAK_TO_DEBUGGER(); - return; - } - - /* disable encoder */ - if (dc_is_dp_signal(signal)) - link_encoder_disable(enc10); -} - -void dcn10_link_encoder_dp_set_lane_settings( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - union dpcd_training_lane_set training_lane_set = { { 0 } }; - int32_t lane = 0; - struct bp_transmitter_control cntl = { 0 }; - enum bp_result result; - - if (!link_settings) { - BREAK_TO_DEBUGGER(); - return; - } - - cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS; - cntl.transmitter = enc10->base.transmitter; - cntl.connector_obj_id = enc10->base.connector; - cntl.lanes_number = link_settings->lane_count; - cntl.hpd_sel = enc10->base.hpd_source; - cntl.pixel_clock = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_KHZ; - - for (lane = 0; lane < link_settings->lane_count; lane++) { - /* translate lane settings */ - - training_lane_set.bits.VOLTAGE_SWING_SET = - lane_settings[lane].VOLTAGE_SWING; - training_lane_set.bits.PRE_EMPHASIS_SET = - lane_settings[lane].PRE_EMPHASIS; - - /* post cursor 2 setting only applies to HBR2 link rate */ - if (link_settings->link_rate == LINK_RATE_HIGH2) { - /* this is passed to VBIOS - * to program post cursor 2 level - */ - training_lane_set.bits.POST_CURSOR2_SET = - lane_settings[lane].POST_CURSOR2; - } - - cntl.lane_select = lane; - cntl.lane_settings = training_lane_set.raw; - - /* call VBIOS table to set voltage swing and pre-emphasis */ - result = link_transmitter_control(enc10, &cntl); - - if (result != BP_RESULT_OK) { - DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", __func__); - BREAK_TO_DEBUGGER(); - } - } -} - -/* set DP PHY test and training patterns */ -void dcn10_link_encoder_dp_set_phy_pattern( - struct link_encoder *enc, - const struct encoder_set_dp_phy_pattern_param *param) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - switch (param->dp_phy_pattern) { - case DP_TEST_PATTERN_TRAINING_PATTERN1: - dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0); - break; - case DP_TEST_PATTERN_TRAINING_PATTERN2: - dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1); - break; - case DP_TEST_PATTERN_TRAINING_PATTERN3: - dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2); - break; - case DP_TEST_PATTERN_TRAINING_PATTERN4: - dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3); - break; - case DP_TEST_PATTERN_D102: - set_dp_phy_pattern_d102(enc10); - break; - case DP_TEST_PATTERN_SYMBOL_ERROR: - set_dp_phy_pattern_symbol_error(enc10); - break; - case DP_TEST_PATTERN_PRBS7: - set_dp_phy_pattern_prbs7(enc10); - break; - case DP_TEST_PATTERN_80BIT_CUSTOM: - set_dp_phy_pattern_80bit_custom( - enc10, param->custom_pattern); - break; - case DP_TEST_PATTERN_CP2520_1: - set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc10, 1); - break; - case DP_TEST_PATTERN_CP2520_2: - set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc10, 2); - break; - case DP_TEST_PATTERN_CP2520_3: - set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc10, 3); - break; - case DP_TEST_PATTERN_VIDEO_MODE: { - set_dp_phy_pattern_passthrough_mode( - enc10, param->dp_panel_mode); - break; - } - - default: - /* invalid phy pattern */ - ASSERT_CRITICAL(false); - break; - } -} - -static void fill_stream_allocation_row_info( - const struct link_mst_stream_allocation *stream_allocation, - uint32_t *src, - uint32_t *slots) -{ - const struct stream_encoder *stream_enc = stream_allocation->stream_enc; - - if (stream_enc) { - *src = stream_enc->id; - *slots = stream_allocation->slot_count; - } else { - *src = 0; - *slots = 0; - } -} - -/* programs DP MST VC payload allocation */ -void dcn10_link_encoder_update_mst_stream_allocation_table( - struct link_encoder *enc, - const struct link_mst_stream_allocation_table *table) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t value1 = 0; - uint32_t value2 = 0; - uint32_t slots = 0; - uint32_t src = 0; - uint32_t retries = 0; - - /* For CZ, there are only 3 pipes. So Virtual channel is up 3.*/ - - /* --- Set MSE Stream Attribute - - * Setup VC Payload Table on Tx Side, - * Issue allocation change trigger - * to commit payload on both tx and rx side - */ - - /* we should clean-up table each time */ - - if (table->stream_count >= 1) { - fill_stream_allocation_row_info( - &table->stream_allocations[0], - &src, - &slots); - } else { - src = 0; - slots = 0; - } - - REG_UPDATE_2(DP_MSE_SAT0, - DP_MSE_SAT_SRC0, src, - DP_MSE_SAT_SLOT_COUNT0, slots); - - if (table->stream_count >= 2) { - fill_stream_allocation_row_info( - &table->stream_allocations[1], - &src, - &slots); - } else { - src = 0; - slots = 0; - } - - REG_UPDATE_2(DP_MSE_SAT0, - DP_MSE_SAT_SRC1, src, - DP_MSE_SAT_SLOT_COUNT1, slots); - - if (table->stream_count >= 3) { - fill_stream_allocation_row_info( - &table->stream_allocations[2], - &src, - &slots); - } else { - src = 0; - slots = 0; - } - - REG_UPDATE_2(DP_MSE_SAT1, - DP_MSE_SAT_SRC2, src, - DP_MSE_SAT_SLOT_COUNT2, slots); - - if (table->stream_count >= 4) { - fill_stream_allocation_row_info( - &table->stream_allocations[3], - &src, - &slots); - } else { - src = 0; - slots = 0; - } - - REG_UPDATE_2(DP_MSE_SAT1, - DP_MSE_SAT_SRC3, src, - DP_MSE_SAT_SLOT_COUNT3, slots); - - /* --- wait for transaction finish */ - - /* send allocation change trigger (ACT) ? - * this step first sends the ACT, - * then double buffers the SAT into the hardware - * making the new allocation active on the DP MST mode link - */ - - /* DP_MSE_SAT_UPDATE: - * 0 - No Action - * 1 - Update SAT with trigger - * 2 - Update SAT without trigger - */ - REG_UPDATE(DP_MSE_SAT_UPDATE, - DP_MSE_SAT_UPDATE, 1); - - /* wait for update to complete - * (i.e. DP_MSE_SAT_UPDATE field is reset to 0) - * then wait for the transmission - * of at least 16 MTP headers on immediate local link. - * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 0 - * a value of 1 indicates that DP MST mode - * is in the 16 MTP keepout region after a VC has been added. - * MST stream bandwidth (VC rate) can be configured - * after this bit is cleared - */ - do { - udelay(10); - - REG_READ(DP_MSE_SAT_UPDATE); - - REG_GET(DP_MSE_SAT_UPDATE, - DP_MSE_SAT_UPDATE, &value1); - - REG_GET(DP_MSE_SAT_UPDATE, - DP_MSE_16_MTP_KEEPOUT, &value2); - - /* bit field DP_MSE_SAT_UPDATE is set to 1 already */ - if (!value1 && !value2) - break; - ++retries; - } while (retries < DP_MST_UPDATE_MAX_RETRY); -} - -void dcn10_link_encoder_connect_dig_be_to_fe( - struct link_encoder *enc, - enum engine_id engine, - bool connect) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t field; - - if (engine != ENGINE_ID_UNKNOWN) { - - REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &field); - - if (connect) - field |= get_frontend_source(engine); - else - field &= ~get_frontend_source(engine); - - REG_UPDATE(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, field); - } -} - - -#define HPD_REG(reg)\ - (enc10->hpd_regs->reg) - -#define HPD_REG_READ(reg_name) \ - dm_read_reg(CTX, HPD_REG(reg_name)) - -#define HPD_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_ex(CTX, \ - HPD_REG(reg_name), \ - n, __VA_ARGS__) - -#define HPD_REG_UPDATE(reg_name, field, val) \ - HPD_REG_UPDATE_N(reg_name, 1, \ - FN(reg_name, field), val) - -void dcn10_link_encoder_enable_hpd(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - HPD_REG_UPDATE(DC_HPD_CONTROL, - DC_HPD_EN, 1); -} - -void dcn10_link_encoder_disable_hpd(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - HPD_REG_UPDATE(DC_HPD_CONTROL, - DC_HPD_EN, 0); -} - -#define AUX_REG(reg)\ - (enc10->aux_regs->reg) - -#define AUX_REG_READ(reg_name) \ - dm_read_reg(CTX, AUX_REG(reg_name)) - -#define AUX_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_ex(CTX, \ - AUX_REG(reg_name), \ - n, __VA_ARGS__) - -#define AUX_REG_UPDATE(reg_name, field, val) \ - AUX_REG_UPDATE_N(reg_name, 1, \ - FN(reg_name, field), val) - -#define AUX_REG_UPDATE_2(reg, f1, v1, f2, v2) \ - AUX_REG_UPDATE_N(reg, 2,\ - FN(reg, f1), v1,\ - FN(reg, f2), v2) - -void dcn10_aux_initialize(struct dcn10_link_encoder *enc10) -{ - enum hpd_source_id hpd_source = enc10->base.hpd_source; - - AUX_REG_UPDATE_2(AUX_CONTROL, - AUX_HPD_SEL, hpd_source, - AUX_LS_READ_EN, 0); - - /* 1/4 window (the maximum allowed) */ - AUX_REG_UPDATE(AUX_DPHY_RX_CONTROL0, - AUX_RX_RECEIVE_WINDOW, 0); -} - -enum signal_type dcn10_get_dig_mode( - struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t value; - REG_GET(DIG_BE_CNTL, DIG_MODE, &value); - switch (value) { - case 1: - return SIGNAL_TYPE_DISPLAY_PORT; - case 2: - return SIGNAL_TYPE_DVI_SINGLE_LINK; - case 3: - return SIGNAL_TYPE_HDMI_TYPE_A; - case 5: - return SIGNAL_TYPE_DISPLAY_PORT_MST; - default: - return SIGNAL_TYPE_NONE; - } -} - -void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc, - struct dc_link_settings *link_settings) -{ - /* Set Default link settings */ - struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH, - LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0}; - - /* Higher link settings based on feature supported */ - if (enc->features.flags.bits.IS_HBR2_CAPABLE) - max_link_cap.link_rate = LINK_RATE_HIGH2; - - if (enc->features.flags.bits.IS_HBR3_CAPABLE) - max_link_cap.link_rate = LINK_RATE_HIGH3; - - if (enc->features.flags.bits.IS_UHBR10_CAPABLE) - max_link_cap.link_rate = LINK_RATE_UHBR10; - - if (enc->features.flags.bits.IS_UHBR13_5_CAPABLE) - max_link_cap.link_rate = LINK_RATE_UHBR13_5; - - if (enc->features.flags.bits.IS_UHBR20_CAPABLE) - max_link_cap.link_rate = LINK_RATE_UHBR20; - - *link_settings = max_link_cap; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h deleted file mode 100644 index b7a89c39f445..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h +++ /dev/null @@ -1,659 +0,0 @@ -/* - * 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 - * - */ - -#ifndef __DC_LINK_ENCODER__DCN10_H__ -#define __DC_LINK_ENCODER__DCN10_H__ - -#include "link_encoder.h" - -#define TO_DCN10_LINK_ENC(link_encoder)\ - container_of(link_encoder, struct dcn10_link_encoder, base) - -#define AUX_REG_LIST(id)\ - SRI(AUX_CONTROL, DP_AUX, id), \ - SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \ - SRI(AUX_DPHY_RX_CONTROL1, DP_AUX, id) - -#define HPD_REG_LIST(id)\ - SRI(DC_HPD_CONTROL, HPD, id) - -#define LE_DCN_COMMON_REG_LIST(id) \ - SRI(DIG_BE_CNTL, DIG, id), \ - SRI(DIG_BE_EN_CNTL, DIG, id), \ - SRI(DIG_CLOCK_PATTERN, DIG, id), \ - SRI(TMDS_CTL_BITS, DIG, id), \ - SRI(DP_CONFIG, DP, id), \ - SRI(DP_DPHY_CNTL, DP, id), \ - SRI(DP_DPHY_PRBS_CNTL, DP, id), \ - SRI(DP_DPHY_SCRAM_CNTL, DP, id),\ - SRI(DP_DPHY_SYM0, DP, id), \ - SRI(DP_DPHY_SYM1, DP, id), \ - SRI(DP_DPHY_SYM2, DP, id), \ - SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ - SRI(DP_LINK_CNTL, DP, id), \ - SRI(DP_LINK_FRAMING_CNTL, DP, id), \ - SRI(DP_MSE_SAT0, DP, id), \ - SRI(DP_MSE_SAT1, DP, id), \ - SRI(DP_MSE_SAT2, DP, id), \ - SRI(DP_MSE_SAT_UPDATE, DP, id), \ - SRI(DP_SEC_CNTL, DP, id), \ - SRI(DP_VID_STREAM_CNTL, DP, id), \ - SRI(DP_DPHY_FAST_TRAINING, DP, id), \ - SRI(DP_SEC_CNTL1, DP, id), \ - SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) - - -#define LE_DCN10_REG_LIST(id)\ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - LE_DCN_COMMON_REG_LIST(id) - -struct dcn10_link_enc_aux_registers { - uint32_t AUX_CONTROL; - uint32_t AUX_DPHY_RX_CONTROL0; - uint32_t AUX_DPHY_TX_CONTROL; - uint32_t AUX_DPHY_RX_CONTROL1; -}; - -struct dcn10_link_enc_hpd_registers { - uint32_t DC_HPD_CONTROL; -}; - -struct dcn10_link_enc_registers { - uint32_t DIG_BE_CNTL; - uint32_t DIG_BE_EN_CNTL; - uint32_t DIG_CLOCK_PATTERN; - uint32_t DP_CONFIG; - uint32_t DP_DPHY_CNTL; - uint32_t DP_DPHY_INTERNAL_CTRL; - uint32_t DP_DPHY_PRBS_CNTL; - uint32_t DP_DPHY_SCRAM_CNTL; - uint32_t DP_DPHY_SYM0; - uint32_t DP_DPHY_SYM1; - uint32_t DP_DPHY_SYM2; - uint32_t DP_DPHY_TRAINING_PATTERN_SEL; - uint32_t DP_LINK_CNTL; - uint32_t DP_LINK_FRAMING_CNTL; - uint32_t DP_MSE_SAT0; - uint32_t DP_MSE_SAT1; - uint32_t DP_MSE_SAT2; - uint32_t DP_MSE_SAT_UPDATE; - uint32_t DP_SEC_CNTL; - uint32_t DP_VID_STREAM_CNTL; - uint32_t DP_DPHY_FAST_TRAINING; - uint32_t DP_DPHY_BS_SR_SWAP_CNTL; - uint32_t DP_DPHY_HBR2_PATTERN_CONTROL; - uint32_t DP_SEC_CNTL1; - uint32_t TMDS_CTL_BITS; - /* DCCG */ - uint32_t CLOCK_ENABLE; - /* DIG */ - uint32_t DIG_LANE_ENABLE; - /* UNIPHY */ - uint32_t CHANNEL_XBAR_CNTL; - /* DPCS */ - uint32_t RDPCSTX_PHY_CNTL3; - uint32_t RDPCSTX_PHY_CNTL4; - uint32_t RDPCSTX_PHY_CNTL5; - uint32_t RDPCSTX_PHY_CNTL6; - uint32_t RDPCSPIPE_PHY_CNTL6; - uint32_t RDPCSTX_PHY_CNTL7; - uint32_t RDPCSTX_PHY_CNTL8; - uint32_t RDPCSTX_PHY_CNTL9; - uint32_t RDPCSTX_PHY_CNTL10; - uint32_t RDPCSTX_PHY_CNTL11; - uint32_t RDPCSTX_PHY_CNTL12; - uint32_t RDPCSTX_PHY_CNTL13; - uint32_t RDPCSTX_PHY_CNTL14; - uint32_t RDPCSTX_PHY_CNTL15; - uint32_t RDPCSTX_CNTL; - uint32_t RDPCSTX_CLOCK_CNTL; - uint32_t RDPCSTX_PHY_CNTL0; - uint32_t RDPCSTX_PHY_CNTL2; - uint32_t RDPCSTX_PLL_UPDATE_DATA; - uint32_t RDPCS_TX_CR_ADDR; - uint32_t RDPCS_TX_CR_DATA; - uint32_t DPCSTX_TX_CLOCK_CNTL; - uint32_t DPCSTX_TX_CNTL; - uint32_t RDPCSTX_INTERRUPT_CONTROL; - uint32_t RDPCSTX_PHY_FUSE0; - uint32_t RDPCSTX_PHY_FUSE1; - uint32_t RDPCSTX_PHY_FUSE2; - uint32_t RDPCSTX_PHY_FUSE3; - uint32_t RDPCSTX_PHY_RX_LD_VAL; - uint32_t DPCSTX_DEBUG_CONFIG; - uint32_t RDPCSTX_DEBUG_CONFIG; - uint32_t RDPCSTX0_RDPCSTX_SCRATCH; - uint32_t RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG; - uint32_t DCIO_SOFT_RESET; - /* indirect registers */ - uint32_t RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_2; - uint32_t RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_3; - uint32_t RAWLANE1_DIG_PCS_XF_RX_OVRD_IN_2; - uint32_t RAWLANE1_DIG_PCS_XF_RX_OVRD_IN_3; - uint32_t RAWLANE2_DIG_PCS_XF_RX_OVRD_IN_2; - uint32_t RAWLANE2_DIG_PCS_XF_RX_OVRD_IN_3; - uint32_t RAWLANE3_DIG_PCS_XF_RX_OVRD_IN_2; - uint32_t RAWLANE3_DIG_PCS_XF_RX_OVRD_IN_3; - uint32_t TMDS_DCBALANCER_CONTROL; - uint32_t PHYA_LINK_CNTL2; - uint32_t PHYB_LINK_CNTL2; - uint32_t PHYC_LINK_CNTL2; - uint32_t DIO_LINKA_CNTL; - uint32_t DIO_LINKB_CNTL; - uint32_t DIO_LINKC_CNTL; - uint32_t DIO_LINKD_CNTL; - uint32_t DIO_LINKE_CNTL; - uint32_t DIO_LINKF_CNTL; - uint32_t DIO_CLK_CNTL; - uint32_t DIG_BE_CLK_CNTL; -}; - -#define LE_SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh)\ - LE_SF(DIG0_DIG_BE_EN_CNTL, DIG_ENABLE, mask_sh),\ - LE_SF(DIG0_DIG_BE_CNTL, DIG_HPD_SELECT, mask_sh),\ - LE_SF(DIG0_DIG_BE_CNTL, DIG_MODE, mask_sh),\ - LE_SF(DIG0_DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, mask_sh),\ - LE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\ - LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_BYPASS, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE0, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE1, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE2, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE3, mask_sh),\ - LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, mask_sh),\ - LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM1, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM2, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM3, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM4, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM5, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM6, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM7, mask_sh),\ - LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM8, mask_sh),\ - LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, mask_sh),\ - LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, mask_sh),\ - LE_SF(DP0_DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, mask_sh),\ - LE_SF(DP0_DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, mask_sh),\ - LE_SF(DP0_DP_DPHY_TRAINING_PATTERN_SEL, DPHY_TRAINING_PATTERN_SEL, mask_sh),\ - LE_SF(DP0_DP_DPHY_HBR2_PATTERN_CONTROL, DP_DPHY_HBR2_PATTERN_CONTROL, mask_sh),\ - LE_SF(DP0_DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, mask_sh),\ - LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL, mask_sh),\ - LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE, mask_sh),\ - LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE, mask_sh),\ - LE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ - LE_SF(DP0_DP_CONFIG, DP_UDI_LANES, mask_sh),\ - LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_LINE_NUM, mask_sh),\ - LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_PRIORITY, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC0, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC1, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT0, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT1, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC2, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC3, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT2, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT3, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_SAT_UPDATE, mask_sh),\ - LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_16_MTP_KEEPOUT, mask_sh),\ - LE_SF(DP_AUX0_AUX_CONTROL, AUX_HPD_SEL, mask_sh),\ - LE_SF(DP_AUX0_AUX_CONTROL, AUX_LS_READ_EN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW, mask_sh),\ - LE_SF(HPD0_DC_HPD_CONTROL, DC_HPD_EN, mask_sh) - -#define DCN_LINK_ENCODER_REG_FIELD_LIST(type) \ - type DIG_ENABLE;\ - type DIG_HPD_SELECT;\ - type DIG_MODE;\ - type DIG_FE_SOURCE_SELECT;\ - type DIG_CLOCK_PATTERN;\ - type DPHY_BYPASS;\ - type DPHY_ATEST_SEL_LANE0;\ - type DPHY_ATEST_SEL_LANE1;\ - type DPHY_ATEST_SEL_LANE2;\ - type DPHY_ATEST_SEL_LANE3;\ - type DPHY_PRBS_EN;\ - type DPHY_PRBS_SEL;\ - type DPHY_SYM1;\ - type DPHY_SYM2;\ - type DPHY_SYM3;\ - type DPHY_SYM4;\ - type DPHY_SYM5;\ - type DPHY_SYM6;\ - type DPHY_SYM7;\ - type DPHY_SYM8;\ - type DPHY_SCRAMBLER_BS_COUNT;\ - type DPHY_SCRAMBLER_ADVANCE;\ - type DPHY_RX_FAST_TRAINING_CAPABLE;\ - type DPHY_LOAD_BS_COUNT;\ - type DPHY_TRAINING_PATTERN_SEL;\ - type DP_DPHY_HBR2_PATTERN_CONTROL;\ - type DP_LINK_TRAINING_COMPLETE;\ - type DP_IDLE_BS_INTERVAL;\ - type DP_VBID_DISABLE;\ - type DP_VID_ENHANCED_FRAME_MODE;\ - type DP_VID_STREAM_ENABLE;\ - type DP_UDI_LANES;\ - type DP_SEC_GSP0_LINE_NUM;\ - type DP_SEC_GSP0_PRIORITY;\ - type DP_MSE_SAT_SRC0;\ - type DP_MSE_SAT_SRC1;\ - type DP_MSE_SAT_SRC2;\ - type DP_MSE_SAT_SRC3;\ - type DP_MSE_SAT_SLOT_COUNT0;\ - type DP_MSE_SAT_SLOT_COUNT1;\ - type DP_MSE_SAT_SLOT_COUNT2;\ - type DP_MSE_SAT_SLOT_COUNT3;\ - type DP_MSE_SAT_UPDATE;\ - type DP_MSE_16_MTP_KEEPOUT;\ - type DC_HPD_EN;\ - type TMDS_CTL0;\ - type AUX_HPD_SEL;\ - type AUX_LS_READ_EN;\ - type AUX_RX_RECEIVE_WINDOW - - -#define DCN20_LINK_ENCODER_DPCS_REG_FIELD_LIST(type) \ - type RDPCS_PHY_DP_TX0_DATA_EN;\ - type RDPCS_PHY_DP_TX1_DATA_EN;\ - type RDPCS_PHY_DP_TX2_DATA_EN;\ - type RDPCS_PHY_DP_TX3_DATA_EN;\ - type RDPCS_PHY_DP_TX0_PSTATE;\ - type RDPCS_PHY_DP_TX1_PSTATE;\ - type RDPCS_PHY_DP_TX2_PSTATE;\ - type RDPCS_PHY_DP_TX3_PSTATE;\ - type RDPCS_PHY_DP_TX0_MPLL_EN;\ - type RDPCS_PHY_DP_TX1_MPLL_EN;\ - type RDPCS_PHY_DP_TX2_MPLL_EN;\ - type RDPCS_PHY_DP_TX3_MPLL_EN;\ - type RDPCS_TX_FIFO_LANE0_EN;\ - type RDPCS_TX_FIFO_LANE1_EN;\ - type RDPCS_TX_FIFO_LANE2_EN;\ - type RDPCS_TX_FIFO_LANE3_EN;\ - type RDPCS_EXT_REFCLK_EN;\ - type RDPCS_TX_FIFO_EN;\ - type UNIPHY_LINK_ENABLE;\ - type UNIPHY_CHANNEL0_XBAR_SOURCE;\ - type UNIPHY_CHANNEL1_XBAR_SOURCE;\ - type UNIPHY_CHANNEL2_XBAR_SOURCE;\ - type UNIPHY_CHANNEL3_XBAR_SOURCE;\ - type UNIPHY_CHANNEL0_INVERT;\ - type UNIPHY_CHANNEL1_INVERT;\ - type UNIPHY_CHANNEL2_INVERT;\ - type UNIPHY_CHANNEL3_INVERT;\ - type UNIPHY_LINK_ENABLE_HPD_MASK;\ - type UNIPHY_LANE_STAGGER_DELAY;\ - type RDPCS_SRAMCLK_BYPASS;\ - type RDPCS_SRAMCLK_EN;\ - type RDPCS_SRAMCLK_CLOCK_ON;\ - type DPCS_TX_FIFO_EN;\ - type RDPCS_PHY_DP_TX0_DISABLE;\ - type RDPCS_PHY_DP_TX1_DISABLE;\ - type RDPCS_PHY_DP_TX2_DISABLE;\ - type RDPCS_PHY_DP_TX3_DISABLE;\ - type RDPCS_PHY_DP_TX0_CLK_RDY;\ - type RDPCS_PHY_DP_TX1_CLK_RDY;\ - type RDPCS_PHY_DP_TX2_CLK_RDY;\ - type RDPCS_PHY_DP_TX3_CLK_RDY;\ - type RDPCS_PHY_DP_TX0_REQ;\ - type RDPCS_PHY_DP_TX1_REQ;\ - type RDPCS_PHY_DP_TX2_REQ;\ - type RDPCS_PHY_DP_TX3_REQ;\ - type RDPCS_PHY_DP_TX0_ACK;\ - type RDPCS_PHY_DP_TX1_ACK;\ - type RDPCS_PHY_DP_TX2_ACK;\ - type RDPCS_PHY_DP_TX3_ACK;\ - type RDPCS_PHY_DP_TX0_RESET;\ - type RDPCS_PHY_DP_TX1_RESET;\ - type RDPCS_PHY_DP_TX2_RESET;\ - type RDPCS_PHY_DP_TX3_RESET;\ - type RDPCS_PHY_RESET;\ - type RDPCS_PHY_CR_MUX_SEL;\ - type RDPCS_PHY_REF_RANGE;\ - type RDPCS_PHY_DP4_POR;\ - type RDPCS_SRAM_BYPASS;\ - type RDPCS_SRAM_EXT_LD_DONE;\ - type RDPCS_PHY_DP_TX0_TERM_CTRL;\ - type RDPCS_PHY_DP_TX1_TERM_CTRL;\ - type RDPCS_PHY_DP_TX2_TERM_CTRL;\ - type RDPCS_PHY_DP_TX3_TERM_CTRL;\ - type RDPCS_PHY_DP_REF_CLK_MPLLB_DIV;\ - type RDPCS_PHY_DP_MPLLB_MULTIPLIER;\ - type RDPCS_PHY_DP_MPLLB_SSC_EN;\ - type RDPCS_PHY_DP_MPLLB_DIV5_CLK_EN;\ - type RDPCS_PHY_DP_MPLLB_TX_CLK_DIV;\ - type RDPCS_PHY_DP_MPLLB_WORD_DIV2_EN;\ - type RDPCS_PHY_DP_MPLLB_FRACN_EN;\ - type RDPCS_PHY_DP_MPLLB_PMIX_EN;\ - type RDPCS_PHY_DP_MPLLB_FRACN_QUOT;\ - type RDPCS_PHY_DP_MPLLB_FRACN_DEN;\ - type RDPCS_PHY_DP_MPLLB_FRACN_REM;\ - type RDPCS_PHY_DP_MPLLB_SSC_UP_SPREAD;\ - type RDPCS_PHY_DP_MPLLB_SSC_STEPSIZE;\ - type RDPCS_PHY_DP_MPLLB_SSC_PEAK;\ - type RDPCS_PHY_DP_MPLLB_DIV_CLK_EN;\ - type RDPCS_PHY_DP_MPLLB_DIV_MULTIPLIER;\ - type RDPCS_PHY_TX_VBOOST_LVL;\ - type RDPCS_PHY_HDMIMODE_ENABLE;\ - type RDPCS_PHY_DP_REF_CLK_EN;\ - type RDPCS_PLL_UPDATE_DATA;\ - type RDPCS_SRAM_INIT_DONE;\ - type RDPCS_TX_CR_ADDR;\ - type RDPCS_TX_CR_DATA;\ - type RDPCS_PHY_HDMI_MPLLB_HDMI_DIV;\ - type RDPCS_PHY_DP_MPLLB_STATE;\ - type RDPCS_PHY_DP_TX0_WIDTH;\ - type RDPCS_PHY_DP_TX0_RATE;\ - type RDPCS_PHY_DP_TX1_WIDTH;\ - type RDPCS_PHY_DP_TX1_RATE;\ - type RDPCS_PHY_DP_TX2_WIDTH;\ - type RDPCS_PHY_DP_TX2_RATE;\ - type RDPCS_PHY_DP_TX3_WIDTH;\ - type RDPCS_PHY_DP_TX3_RATE;\ - type DPCS_SYMCLK_CLOCK_ON;\ - type DPCS_SYMCLK_GATE_DIS;\ - type DPCS_SYMCLK_EN;\ - type RDPCS_SYMCLK_DIV2_CLOCK_ON;\ - type RDPCS_SYMCLK_DIV2_GATE_DIS;\ - type RDPCS_SYMCLK_DIV2_EN;\ - type DPCS_TX_DATA_SWAP;\ - type DPCS_TX_DATA_ORDER_INVERT;\ - type DPCS_TX_FIFO_RD_START_DELAY;\ - type RDPCS_TX_FIFO_RD_START_DELAY;\ - type RDPCS_REG_FIFO_ERROR_MASK;\ - type RDPCS_TX_FIFO_ERROR_MASK;\ - type RDPCS_DPALT_DISABLE_TOGGLE_MASK;\ - type RDPCS_DPALT_4LANE_TOGGLE_MASK;\ - type RDPCS_PHY_DPALT_DP4;\ - type RDPCS_PHY_DPALT_DISABLE;\ - type RDPCS_PHY_DPALT_DISABLE_ACK;\ - type RDPCS_PHY_DP_MPLLB_V2I;\ - type RDPCS_PHY_DP_MPLLB_FREQ_VCO;\ - type RDPCS_PHY_DP_MPLLB_CP_INT_GS;\ - type RDPCS_PHY_RX_VREF_CTRL;\ - type RDPCS_PHY_DP_MPLLB_CP_INT;\ - type RDPCS_PHY_DP_MPLLB_CP_PROP;\ - type RDPCS_PHY_RX_REF_LD_VAL;\ - type RDPCS_PHY_RX_VCO_LD_VAL;\ - type DPCSTX_DEBUG_CONFIG; \ - type RDPCSTX_DEBUG_CONFIG; \ - type RDPCS_PHY_DP_TX0_EQ_MAIN;\ - type RDPCS_PHY_DP_TX0_EQ_PRE;\ - type RDPCS_PHY_DP_TX0_EQ_POST;\ - type RDPCS_PHY_DP_TX1_EQ_MAIN;\ - type RDPCS_PHY_DP_TX1_EQ_PRE;\ - type RDPCS_PHY_DP_TX1_EQ_POST;\ - type RDPCS_PHY_DP_TX2_EQ_MAIN;\ - type RDPCS_PHY_DP_MPLLB_CP_PROP_GS;\ - type RDPCS_PHY_DP_TX2_EQ_PRE;\ - type RDPCS_PHY_DP_TX2_EQ_POST;\ - type RDPCS_PHY_DP_TX3_EQ_MAIN;\ - type RDPCS_PHY_DCO_RANGE;\ - type RDPCS_PHY_DCO_FINETUNE;\ - type RDPCS_PHY_DP_TX3_EQ_PRE;\ - type RDPCS_PHY_DP_TX3_EQ_POST;\ - type RDPCS_PHY_SUP_PRE_HP;\ - type RDPCS_PHY_DP_TX0_VREGDRV_BYP;\ - type RDPCS_PHY_DP_TX1_VREGDRV_BYP;\ - type RDPCS_PHY_DP_TX2_VREGDRV_BYP;\ - type RDPCS_PHY_DP_TX3_VREGDRV_BYP;\ - type RDPCS_DMCU_DPALT_DIS_BLOCK_REG;\ - type UNIPHYA_SOFT_RESET;\ - type UNIPHYB_SOFT_RESET;\ - type UNIPHYC_SOFT_RESET;\ - type UNIPHYD_SOFT_RESET;\ - type UNIPHYE_SOFT_RESET;\ - type UNIPHYF_SOFT_RESET - -#define DCN20_LINK_ENCODER_REG_FIELD_LIST(type) \ - type DIG_LANE0EN;\ - type DIG_LANE1EN;\ - type DIG_LANE2EN;\ - type DIG_LANE3EN;\ - type DIG_CLK_EN;\ - type SYMCLKA_CLOCK_ENABLE;\ - type DPHY_FEC_EN;\ - type DPHY_FEC_READY_SHADOW;\ - type DPHY_FEC_ACTIVE_STATUS;\ - DCN20_LINK_ENCODER_DPCS_REG_FIELD_LIST(type);\ - type VCO_LD_VAL_OVRD;\ - type VCO_LD_VAL_OVRD_EN;\ - type REF_LD_VAL_OVRD;\ - type REF_LD_VAL_OVRD_EN;\ - type AUX_RX_START_WINDOW; \ - type AUX_RX_HALF_SYM_DETECT_LEN; \ - type AUX_RX_TRANSITION_FILTER_EN; \ - type AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT; \ - type AUX_RX_ALLOW_BELOW_THRESHOLD_START; \ - type AUX_RX_ALLOW_BELOW_THRESHOLD_STOP; \ - type AUX_RX_PHASE_DETECT_LEN; \ - type AUX_RX_DETECTION_THRESHOLD; \ - type AUX_TX_PRECHARGE_LEN; \ - type AUX_TX_PRECHARGE_SYMBOLS; \ - type AUX_MODE_DET_CHECK_DELAY;\ - type DPCS_DBG_CBUS_DIS;\ - type AUX_RX_PRECHARGE_SKIP;\ - type AUX_RX_TIMEOUT_LEN;\ - type AUX_RX_TIMEOUT_LEN_MUL - -#define DCN30_LINK_ENCODER_REG_FIELD_LIST(type) \ - type TMDS_SYNC_DCBAL_EN;\ - type PHY_HPO_DIG_SRC_SEL;\ - type PHY_HPO_ENC_SRC_SEL;\ - type DPCS_TX_HDMI_FRL_MODE;\ - type DPCS_TX_DATA_SWAP_10_BIT;\ - type DPCS_TX_DATA_ORDER_INVERT_18_BIT;\ - type RDPCS_TX_CLK_EN - -#define DCN31_LINK_ENCODER_REG_FIELD_LIST(type) \ - type ENC_TYPE_SEL;\ - type HPO_DP_ENC_SEL;\ - type HPO_HDMI_ENC_SEL - -#define DCN35_LINK_ENCODER_REG_FIELD_LIST(type) \ - type DIG_BE_ENABLE;\ - type DIG_RB_SWITCH_EN;\ - type DIG_BE_MODE;\ - type DIG_BE_CLK_EN;\ - type DIG_BE_SOFT_RESET;\ - type HDCP_SOFT_RESET;\ - type DIG_BE_SYMCLK_G_CLOCK_ON;\ - type DIG_BE_SYMCLK_G_HDCP_CLOCK_ON;\ - type DIG_BE_SYMCLK_G_TMDS_CLOCK_ON;\ - type DISPCLK_R_GATE_DIS;\ - type DISPCLK_G_GATE_DIS;\ - type REFCLK_R_GATE_DIS;\ - type REFCLK_G_GATE_DIS;\ - type SOCCLK_G_GATE_DIS;\ - type SYMCLK_FE_R_GATE_DIS;\ - type SYMCLK_FE_G_GATE_DIS;\ - type SYMCLK_R_GATE_DIS;\ - type SYMCLK_G_GATE_DIS;\ - type DIO_FGCG_REP_DIS;\ - type DISPCLK_G_HDCP_GATE_DIS;\ - type SYMCLKA_G_HDCP_GATE_DIS;\ - type SYMCLKB_G_HDCP_GATE_DIS;\ - type SYMCLKC_G_HDCP_GATE_DIS;\ - type SYMCLKD_G_HDCP_GATE_DIS;\ - type SYMCLKE_G_HDCP_GATE_DIS;\ - type SYMCLKF_G_HDCP_GATE_DIS;\ - type SYMCLKG_G_HDCP_GATE_DIS - -struct dcn10_link_enc_shift { - DCN_LINK_ENCODER_REG_FIELD_LIST(uint8_t); - DCN20_LINK_ENCODER_REG_FIELD_LIST(uint8_t); - DCN30_LINK_ENCODER_REG_FIELD_LIST(uint8_t); - DCN31_LINK_ENCODER_REG_FIELD_LIST(uint8_t); - DCN35_LINK_ENCODER_REG_FIELD_LIST(uint8_t); -}; - -struct dcn10_link_enc_mask { - DCN_LINK_ENCODER_REG_FIELD_LIST(uint32_t); - DCN20_LINK_ENCODER_REG_FIELD_LIST(uint32_t); - DCN30_LINK_ENCODER_REG_FIELD_LIST(uint32_t); - DCN31_LINK_ENCODER_REG_FIELD_LIST(uint32_t); - DCN35_LINK_ENCODER_REG_FIELD_LIST(uint32_t); -}; - -struct dcn10_link_encoder { - struct link_encoder base; - const struct dcn10_link_enc_registers *link_regs; - const struct dcn10_link_enc_aux_registers *aux_regs; - const struct dcn10_link_enc_hpd_registers *hpd_regs; - const struct dcn10_link_enc_shift *link_shift; - const struct dcn10_link_enc_mask *link_mask; -}; - - -void dcn10_link_encoder_construct( - struct dcn10_link_encoder *enc10, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask); - -bool dcn10_link_encoder_validate_dvi_output( - const struct dcn10_link_encoder *enc10, - enum signal_type connector_signal, - enum signal_type signal, - const struct dc_crtc_timing *crtc_timing); - -bool dcn10_link_encoder_validate_rgb_output( - const struct dcn10_link_encoder *enc10, - const struct dc_crtc_timing *crtc_timing); - -bool dcn10_link_encoder_validate_dp_output( - const struct dcn10_link_encoder *enc10, - const struct dc_crtc_timing *crtc_timing); - -bool dcn10_link_encoder_validate_wireless_output( - const struct dcn10_link_encoder *enc10, - const struct dc_crtc_timing *crtc_timing); - -bool dcn10_link_encoder_validate_output_with_stream( - struct link_encoder *enc, - const struct dc_stream_state *stream); - -/****************** HW programming ************************/ - -/* initialize HW */ /* why do we initialze aux in here? */ -void dcn10_link_encoder_hw_init(struct link_encoder *enc); - -void dcn10_link_encoder_destroy(struct link_encoder **enc); - -/* program DIG_MODE in DIG_BE */ -/* TODO can this be combined with enable_output? */ -void dcn10_link_encoder_setup( - struct link_encoder *enc, - enum signal_type signal); - -void enc1_configure_encoder( - struct dcn10_link_encoder *enc10, - const struct dc_link_settings *link_settings); - -/* enables TMDS PHY output */ -/* TODO: still need depth or just pass in adjusted pixel clock? */ -void dcn10_link_encoder_enable_tmds_output( - struct link_encoder *enc, - enum clock_source_id clock_source, - enum dc_color_depth color_depth, - enum signal_type signal, - uint32_t pixel_clock); - -void dcn10_link_encoder_enable_tmds_output_with_clk_pattern_wa( - struct link_encoder *enc, - enum clock_source_id clock_source, - enum dc_color_depth color_depth, - enum signal_type signal, - uint32_t pixel_clock); - -/* enables DP PHY output */ -void dcn10_link_encoder_enable_dp_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source); - -/* enables DP PHY output in MST mode */ -void dcn10_link_encoder_enable_dp_mst_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source); - -/* disable PHY output */ -void dcn10_link_encoder_disable_output( - struct link_encoder *enc, - enum signal_type signal); - -/* set DP lane settings */ -void dcn10_link_encoder_dp_set_lane_settings( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); - -void dcn10_link_encoder_dp_set_phy_pattern( - struct link_encoder *enc, - const struct encoder_set_dp_phy_pattern_param *param); - -/* programs DP MST VC payload allocation */ -void dcn10_link_encoder_update_mst_stream_allocation_table( - struct link_encoder *enc, - const struct link_mst_stream_allocation_table *table); - -void dcn10_link_encoder_connect_dig_be_to_fe( - struct link_encoder *enc, - enum engine_id engine, - bool connect); - -void dcn10_link_encoder_set_dp_phy_pattern_training_pattern( - struct link_encoder *enc, - uint32_t index); - -void dcn10_link_encoder_enable_hpd(struct link_encoder *enc); - -void dcn10_link_encoder_disable_hpd(struct link_encoder *enc); - -void dcn10_psr_program_dp_dphy_fast_training(struct link_encoder *enc, - bool exit_link_training_required); - -void dcn10_psr_program_secondary_packet(struct link_encoder *enc, - unsigned int sdp_transmit_line_num_deadline); - -bool dcn10_is_dig_enabled(struct link_encoder *enc); - -unsigned int dcn10_get_dig_frontend(struct link_encoder *enc); - -void dcn10_aux_initialize(struct dcn10_link_encoder *enc10); - -enum signal_type dcn10_get_dig_mode( - struct link_encoder *enc); - -void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc, - struct dc_link_settings *link_settings); -#endif /* __DC_LINK_ENCODER__DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c deleted file mode 100644 index f496e952ceec..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ /dev/null @@ -1,1628 +0,0 @@ -/* - * 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 "dc_bios_types.h" -#include "dcn10_stream_encoder.h" -#include "reg_helper.h" -#include "hw_shared.h" -#include "link.h" -#include "dpcd_defs.h" -#include "dcn30/dcn30_afmt.h" - -#define DC_LOGGER \ - enc1->base.ctx->logger - -#define REG(reg)\ - (enc1->regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc1->se_shift->field_name, enc1->se_mask->field_name - -#define VBI_LINE_0 0 -#define DP_BLANK_MAX_RETRY 20 -#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 - - -enum { - DP_MST_UPDATE_MAX_RETRY = 50 -}; - -#define CTX \ - enc1->base.ctx - -void enc1_update_generic_info_packet( - struct dcn10_stream_encoder *enc1, - uint32_t packet_index, - const struct dc_info_packet *info_packet) -{ - /* TODOFPGA Figure out a proper number for max_retries polling for lock - * use 50 for now. - */ - uint32_t max_retries = 50; - - /*we need turn on clock before programming AFMT block*/ - REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); - - if (packet_index >= 8) - ASSERT(0); - - /* poll dig_update_lock is not locked -> asic internal signal - * assume otg master lock will unlock it - */ -/* REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, - 0, 10, max_retries);*/ - - /* check if HW reading GSP memory */ - REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, - 0, 10, max_retries); - - /* HW does is not reading GSP memory not reading too long -> - * something wrong. clear GPS memory access and notify? - * hw SW is writing to GSP memory - */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); - - /* choose which generic packet to use */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, - AFMT_GENERIC_INDEX, packet_index); - - /* write generic packet header - * (4th byte is for GENERIC0 only) - */ - REG_SET_4(AFMT_GENERIC_HDR, 0, - AFMT_GENERIC_HB0, info_packet->hb0, - AFMT_GENERIC_HB1, info_packet->hb1, - AFMT_GENERIC_HB2, info_packet->hb2, - AFMT_GENERIC_HB3, info_packet->hb3); - - /* write generic packet contents - * (we never use last 4 bytes) - * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers - */ - { - const uint32_t *content = - (const uint32_t *) &info_packet->sb[0]; - - REG_WRITE(AFMT_GENERIC_0, *content++); - REG_WRITE(AFMT_GENERIC_1, *content++); - REG_WRITE(AFMT_GENERIC_2, *content++); - REG_WRITE(AFMT_GENERIC_3, *content++); - REG_WRITE(AFMT_GENERIC_4, *content++); - REG_WRITE(AFMT_GENERIC_5, *content++); - REG_WRITE(AFMT_GENERIC_6, *content++); - REG_WRITE(AFMT_GENERIC_7, *content); - } - - switch (packet_index) { - case 0: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC0_IMMEDIATE_UPDATE, 1); - break; - case 1: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC1_IMMEDIATE_UPDATE, 1); - break; - case 2: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC2_IMMEDIATE_UPDATE, 1); - break; - case 3: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC3_IMMEDIATE_UPDATE, 1); - break; - case 4: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC4_IMMEDIATE_UPDATE, 1); - break; - case 5: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC5_IMMEDIATE_UPDATE, 1); - break; - case 6: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC6_IMMEDIATE_UPDATE, 1); - break; - case 7: - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC7_IMMEDIATE_UPDATE, 1); - break; - default: - break; - } -} - -static void enc1_update_hdmi_info_packet( - struct dcn10_stream_encoder *enc1, - uint32_t packet_index, - const struct dc_info_packet *info_packet) -{ - uint32_t cont, send, line; - - if (info_packet->valid) { - enc1_update_generic_info_packet( - enc1, - packet_index, - info_packet); - - /* enable transmission of packet(s) - - * packet transmission begins on the next frame - */ - cont = 1; - /* send packet(s) every frame */ - send = 1; - /* select line number to send packets on */ - line = 2; - } else { - cont = 0; - send = 0; - line = 0; - } - - /* choose which generic packet control to use */ - switch (packet_index) { - case 0: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC0_CONT, cont, - HDMI_GENERIC0_SEND, send, - HDMI_GENERIC0_LINE, line); - break; - case 1: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC1_CONT, cont, - HDMI_GENERIC1_SEND, send, - HDMI_GENERIC1_LINE, line); - break; - case 2: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1, - HDMI_GENERIC0_CONT, cont, - HDMI_GENERIC0_SEND, send, - HDMI_GENERIC0_LINE, line); - break; - case 3: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1, - HDMI_GENERIC1_CONT, cont, - HDMI_GENERIC1_SEND, send, - HDMI_GENERIC1_LINE, line); - break; - case 4: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2, - HDMI_GENERIC0_CONT, cont, - HDMI_GENERIC0_SEND, send, - HDMI_GENERIC0_LINE, line); - break; - case 5: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2, - HDMI_GENERIC1_CONT, cont, - HDMI_GENERIC1_SEND, send, - HDMI_GENERIC1_LINE, line); - break; - case 6: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL3, - HDMI_GENERIC0_CONT, cont, - HDMI_GENERIC0_SEND, send, - HDMI_GENERIC0_LINE, line); - break; - case 7: - REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL3, - HDMI_GENERIC1_CONT, cont, - HDMI_GENERIC1_SEND, send, - HDMI_GENERIC1_LINE, line); - break; - default: - /* invalid HW packet index */ - DC_LOG_WARNING( - "Invalid HW packet index: %s()\n", - __func__); - return; - } -} - -/* setup stream encoder in dp mode */ -void enc1_stream_encoder_dp_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - enum dc_color_space output_color_space, - bool use_vsc_sdp_for_colorimetry, - uint32_t enable_sdp_splitting) -{ - uint32_t h_active_start; - uint32_t v_active_start; - uint32_t misc0 = 0; - uint32_t misc1 = 0; - uint32_t h_blank; - uint32_t h_back_porch; - uint8_t synchronous_clock = 0; /* asynchronous mode */ - uint8_t colorimetry_bpc; - uint8_t dp_pixel_encoding = 0; - uint8_t dp_component_depth = 0; - - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - struct dc_crtc_timing hw_crtc_timing = *crtc_timing; - - if (hw_crtc_timing.flags.INTERLACE) { - /*the input timing is in VESA spec format with Interlace flag =1*/ - hw_crtc_timing.v_total /= 2; - hw_crtc_timing.v_border_top /= 2; - hw_crtc_timing.v_addressable /= 2; - hw_crtc_timing.v_border_bottom /= 2; - hw_crtc_timing.v_front_porch /= 2; - hw_crtc_timing.v_sync_width /= 2; - } - - - /* set pixel encoding */ - switch (hw_crtc_timing.pixel_encoding) { - case PIXEL_ENCODING_YCBCR422: - dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR422; - break; - case PIXEL_ENCODING_YCBCR444: - dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR444; - - if (hw_crtc_timing.flags.Y_ONLY) - if (hw_crtc_timing.display_color_depth != COLOR_DEPTH_666) - /* HW testing only, no use case yet. - * Color depth of Y-only could be - * 8, 10, 12, 16 bits - */ - dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_Y_ONLY; - - /* Note: DP_MSA_MISC1 bit 7 is the indicator - * of Y-only mode. - * This bit is set in HW if register - * DP_PIXEL_ENCODING is programmed to 0x4 - */ - break; - case PIXEL_ENCODING_YCBCR420: - dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR420; - break; - default: - dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_RGB444; - break; - } - - misc1 = REG_READ(DP_MSA_MISC); - /* For YCbCr420 and BT2020 Colorimetry Formats, VSC SDP shall be used. - * When MISC1, bit 6, is Set to 1, a Source device uses a VSC SDP to indicate the - * Pixel Encoding/Colorimetry Format and that a Sink device shall ignore MISC1, bit 7, - * and MISC0, bits 7:1 (MISC1, bit 7, and MISC0, bits 7:1, become "don't care"). - */ - if (use_vsc_sdp_for_colorimetry) - misc1 = misc1 | 0x40; - else - misc1 = misc1 & ~0x40; - - /* set color depth */ - switch (hw_crtc_timing.display_color_depth) { - case COLOR_DEPTH_666: - dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_6BPC; - break; - case COLOR_DEPTH_888: - dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_8BPC; - break; - case COLOR_DEPTH_101010: - dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_10BPC; - break; - case COLOR_DEPTH_121212: - dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_12BPC; - break; - case COLOR_DEPTH_161616: - dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_16BPC; - break; - default: - dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_6BPC; - break; - } - - /* Set DP pixel encoding and component depth */ - REG_UPDATE_2(DP_PIXEL_FORMAT, - DP_PIXEL_ENCODING, dp_pixel_encoding, - DP_COMPONENT_DEPTH, dp_component_depth); - - /* set dynamic range and YCbCr range */ - - switch (hw_crtc_timing.display_color_depth) { - case COLOR_DEPTH_666: - colorimetry_bpc = 0; - break; - case COLOR_DEPTH_888: - colorimetry_bpc = 1; - break; - case COLOR_DEPTH_101010: - colorimetry_bpc = 2; - break; - case COLOR_DEPTH_121212: - colorimetry_bpc = 3; - break; - default: - colorimetry_bpc = 0; - break; - } - - misc0 = misc0 | synchronous_clock; - misc0 = colorimetry_bpc << 5; - - switch (output_color_space) { - case COLOR_SPACE_SRGB: - misc1 = misc1 & ~0x80; /* bit7 = 0*/ - break; - case COLOR_SPACE_SRGB_LIMITED: - misc0 = misc0 | 0x8; /* bit3=1 */ - misc1 = misc1 & ~0x80; /* bit7 = 0*/ - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR601_LIMITED: - misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ - misc1 = misc1 & ~0x80; /* bit7 = 0*/ - if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) - misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ - else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) - misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR709_LIMITED: - misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */ - misc1 = misc1 & ~0x80; /* bit7 = 0*/ - if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) - misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ - else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) - misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ - break; - case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - case COLOR_SPACE_2020_RGB_FULLRANGE: - case COLOR_SPACE_2020_YCBCR: - case COLOR_SPACE_XR_RGB: - case COLOR_SPACE_MSREF_SCRGB: - case COLOR_SPACE_ADOBERGB: - case COLOR_SPACE_DCIP3: - case COLOR_SPACE_XV_YCC_709: - case COLOR_SPACE_XV_YCC_601: - case COLOR_SPACE_DISPLAYNATIVE: - case COLOR_SPACE_DOLBYVISION: - case COLOR_SPACE_APPCTRL: - case COLOR_SPACE_CUSTOMPOINTS: - case COLOR_SPACE_UNKNOWN: - case COLOR_SPACE_YCBCR709_BLACK: - /* do nothing */ - break; - } - - REG_SET(DP_MSA_COLORIMETRY, 0, DP_MSA_MISC0, misc0); - REG_WRITE(DP_MSA_MISC, misc1); /* MSA_MISC1 */ - - /* dcn new register - * dc_crtc_timing is vesa dmt struct. data from edid - */ - REG_SET_2(DP_MSA_TIMING_PARAM1, 0, - DP_MSA_HTOTAL, hw_crtc_timing.h_total, - DP_MSA_VTOTAL, hw_crtc_timing.v_total); - - /* calculate from vesa timing parameters - * h_active_start related to leading edge of sync - */ - - h_blank = hw_crtc_timing.h_total - hw_crtc_timing.h_border_left - - hw_crtc_timing.h_addressable - hw_crtc_timing.h_border_right; - - h_back_porch = h_blank - hw_crtc_timing.h_front_porch - - hw_crtc_timing.h_sync_width; - - /* start at beginning of left border */ - h_active_start = hw_crtc_timing.h_sync_width + h_back_porch; - - - v_active_start = hw_crtc_timing.v_total - hw_crtc_timing.v_border_top - - hw_crtc_timing.v_addressable - hw_crtc_timing.v_border_bottom - - hw_crtc_timing.v_front_porch; - - - /* start at beginning of left border */ - REG_SET_2(DP_MSA_TIMING_PARAM2, 0, - DP_MSA_HSTART, h_active_start, - DP_MSA_VSTART, v_active_start); - - REG_SET_4(DP_MSA_TIMING_PARAM3, 0, - DP_MSA_HSYNCWIDTH, - hw_crtc_timing.h_sync_width, - DP_MSA_HSYNCPOLARITY, - !hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY, - DP_MSA_VSYNCWIDTH, - hw_crtc_timing.v_sync_width, - DP_MSA_VSYNCPOLARITY, - !hw_crtc_timing.flags.VSYNC_POSITIVE_POLARITY); - - /* HWDITH include border or overscan */ - REG_SET_2(DP_MSA_TIMING_PARAM4, 0, - DP_MSA_HWIDTH, hw_crtc_timing.h_border_left + - hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right, - DP_MSA_VHEIGHT, hw_crtc_timing.v_border_top + - hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom); -} - -void enc1_stream_encoder_set_stream_attribute_helper( - struct dcn10_stream_encoder *enc1, - struct dc_crtc_timing *crtc_timing) -{ - switch (crtc_timing->pixel_encoding) { - case PIXEL_ENCODING_YCBCR422: - REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 1); - break; - default: - REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 0); - break; - } - REG_UPDATE(DIG_FE_CNTL, TMDS_COLOR_FORMAT, 0); -} - -/* setup stream encoder in hdmi mode */ -void enc1_stream_encoder_hdmi_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - int actual_pix_clk_khz, - bool enable_audio) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - struct bp_encoder_control cntl = {0}; - - cntl.action = ENCODER_CONTROL_SETUP; - cntl.engine_id = enc1->base.id; - cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; - cntl.enable_dp_audio = enable_audio; - cntl.pixel_clock = actual_pix_clk_khz; - cntl.lanes_number = LANE_COUNT_FOUR; - - if (enc1->base.bp->funcs->encoder_control( - enc1->base.bp, &cntl) != BP_RESULT_OK) - return; - - enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); - - /* setup HDMI engine */ - REG_UPDATE_6(HDMI_CONTROL, - HDMI_PACKET_GEN_VERSION, 1, - HDMI_KEEPOUT_MODE, 1, - HDMI_DEEP_COLOR_ENABLE, 0, - HDMI_DATA_SCRAMBLE_EN, 0, - HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, - HDMI_CLOCK_CHANNEL_RATE, 0); - - - switch (crtc_timing->display_color_depth) { - case COLOR_DEPTH_888: - REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); - DC_LOG_DEBUG("HDMI source set to 24BPP deep color depth\n"); - break; - case COLOR_DEPTH_101010: - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 1, - HDMI_DEEP_COLOR_ENABLE, 0); - DC_LOG_DEBUG("HDMI source 30BPP deep color depth" \ - "disabled for YCBCR422 pixel encoding\n"); - } else { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 1, - HDMI_DEEP_COLOR_ENABLE, 1); - DC_LOG_DEBUG("HDMI source 30BPP deep color depth" \ - "enabled for YCBCR422 non-pixel encoding\n"); - } - break; - case COLOR_DEPTH_121212: - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 2, - HDMI_DEEP_COLOR_ENABLE, 0); - DC_LOG_DEBUG("HDMI source 36BPP deep color depth" \ - "disabled for YCBCR422 pixel encoding\n"); - } else { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 2, - HDMI_DEEP_COLOR_ENABLE, 1); - DC_LOG_DEBUG("HDMI source 36BPP deep color depth" \ - "enabled for non-pixel YCBCR422 encoding\n"); - } - break; - case COLOR_DEPTH_161616: - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 3, - HDMI_DEEP_COLOR_ENABLE, 1); - DC_LOG_DEBUG("HDMI source deep color depth enabled in" \ - "reserved mode\n"); - break; - default: - break; - } - - if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { - /* enable HDMI data scrambler - * HDMI_CLOCK_CHANNEL_RATE_MORE_340M - * Clock channel frequency is 1/4 of character rate. - */ - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DATA_SCRAMBLE_EN, 1, - HDMI_CLOCK_CHANNEL_RATE, 1); - } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { - - /* TODO: New feature for DCE11, still need to implement */ - - /* enable HDMI data scrambler - * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE - * Clock channel frequency is the same - * as character rate - */ - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DATA_SCRAMBLE_EN, 1, - HDMI_CLOCK_CHANNEL_RATE, 0); - } - - - REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, - HDMI_GC_CONT, 1, - HDMI_GC_SEND, 1, - HDMI_NULL_SEND, 1); - - REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); - - /* following belongs to audio */ - REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); - - REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); - - REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, - VBI_LINE_0 + 2); - - REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); -} - -/* setup stream encoder in dvi mode */ -void enc1_stream_encoder_dvi_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - bool is_dual_link) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - struct bp_encoder_control cntl = {0}; - - cntl.action = ENCODER_CONTROL_SETUP; - cntl.engine_id = enc1->base.id; - cntl.signal = is_dual_link ? - SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; - cntl.enable_dp_audio = false; - cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; - cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; - - if (enc1->base.bp->funcs->encoder_control( - enc1->base.bp, &cntl) != BP_RESULT_OK) - return; - - ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); - ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); - enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); -} - -void enc1_stream_encoder_set_throttled_vcp_size( - struct stream_encoder *enc, - struct fixed31_32 avg_time_slots_per_mtp) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t x = dc_fixpt_floor( - avg_time_slots_per_mtp); - uint32_t y = dc_fixpt_ceil( - dc_fixpt_shl( - dc_fixpt_sub_int( - avg_time_slots_per_mtp, - x), - 26)); - - // If y rounds up to integer, carry it over to x. - if (y >> 26) { - x += 1; - y = 0; - } - - REG_SET_2(DP_MSE_RATE_CNTL, 0, - DP_MSE_RATE_X, x, - DP_MSE_RATE_Y, y); - - /* wait for update to be completed on the link */ - /* i.e. DP_MSE_RATE_UPDATE_PENDING field (read only) */ - /* is reset to 0 (not pending) */ - REG_WAIT(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, - 0, - 10, DP_MST_UPDATE_MAX_RETRY); -} - -static void enc1_stream_encoder_update_hdmi_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* for bring up, disable dp double TODO */ - REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); - - /*Always add mandatory packets first followed by optional ones*/ - enc1_update_hdmi_info_packet(enc1, 0, &info_frame->avi); - enc1_update_hdmi_info_packet(enc1, 1, &info_frame->hfvsif); - enc1_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); - enc1_update_hdmi_info_packet(enc1, 3, &info_frame->vendor); - enc1_update_hdmi_info_packet(enc1, 4, &info_frame->spd); - enc1_update_hdmi_info_packet(enc1, 5, &info_frame->hdrsmd); -} - -static void enc1_stream_encoder_stop_hdmi_info_packets( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* stop generic packets 0 & 1 on HDMI */ - REG_SET_6(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC1_CONT, 0, - HDMI_GENERIC1_LINE, 0, - HDMI_GENERIC1_SEND, 0, - HDMI_GENERIC0_CONT, 0, - HDMI_GENERIC0_LINE, 0, - HDMI_GENERIC0_SEND, 0); - - /* stop generic packets 2 & 3 on HDMI */ - REG_SET_6(HDMI_GENERIC_PACKET_CONTROL1, 0, - HDMI_GENERIC0_CONT, 0, - HDMI_GENERIC0_LINE, 0, - HDMI_GENERIC0_SEND, 0, - HDMI_GENERIC1_CONT, 0, - HDMI_GENERIC1_LINE, 0, - HDMI_GENERIC1_SEND, 0); - - /* stop generic packets 2 & 3 on HDMI */ - REG_SET_6(HDMI_GENERIC_PACKET_CONTROL2, 0, - HDMI_GENERIC0_CONT, 0, - HDMI_GENERIC0_LINE, 0, - HDMI_GENERIC0_SEND, 0, - HDMI_GENERIC1_CONT, 0, - HDMI_GENERIC1_LINE, 0, - HDMI_GENERIC1_SEND, 0); - - REG_SET_6(HDMI_GENERIC_PACKET_CONTROL3, 0, - HDMI_GENERIC0_CONT, 0, - HDMI_GENERIC0_LINE, 0, - HDMI_GENERIC0_SEND, 0, - HDMI_GENERIC1_CONT, 0, - HDMI_GENERIC1_LINE, 0, - HDMI_GENERIC1_SEND, 0); -} - -void enc1_stream_encoder_update_dp_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t value = 0; - - if (info_frame->vsc.valid) - enc1_update_generic_info_packet( - enc1, - 0, /* packetIndex */ - &info_frame->vsc); - - /* VSC SDP at packetIndex 1 is used by PSR in DMCUB FW. - * Note that the enablement of GSP1 is not done below, - * it's done in FW. - */ - if (info_frame->vsc.valid) - enc1_update_generic_info_packet( - enc1, - 1, /* packetIndex */ - &info_frame->vsc); - - if (info_frame->spd.valid) - enc1_update_generic_info_packet( - enc1, - 2, /* packetIndex */ - &info_frame->spd); - - if (info_frame->hdrsmd.valid) - enc1_update_generic_info_packet( - enc1, - 3, /* packetIndex */ - &info_frame->hdrsmd); - - /* packetIndex 4 is used for send immediate sdp message, and please - * use other packetIndex (such as 5,6) for other info packet - */ - - if (info_frame->adaptive_sync.valid) - enc1_update_generic_info_packet( - enc1, - 5, /* packetIndex */ - &info_frame->adaptive_sync); - - /* enable/disable transmission of packet(s). - * If enabled, packet transmission begins on the next frame - */ - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid); - - /* This bit is the master enable bit. - * When enabling secondary stream engine, - * this master bit must also be set. - * This register shared with audio info frame. - * Therefore we need to enable master bit - * if at least on of the fields is not 0 - */ - value = REG_READ(DP_SEC_CNTL); - if (value) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); -} - -void enc1_stream_encoder_send_immediate_sdp_message( - struct stream_encoder *enc, - const uint8_t *custom_sdp_message, - unsigned int sdp_message_size) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t value = 0; - - /* TODOFPGA Figure out a proper number for max_retries polling for lock - * use 50 for now. - */ - uint32_t max_retries = 50; - - /* check if GSP4 is transmitted */ - REG_WAIT(DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, - 0, 10, max_retries); - - /* disable GSP4 transmitting */ - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP4_SEND, 0); - - /* transmit GSP4 at the earliest time in a frame */ - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, 1); - - /*we need turn on clock before programming AFMT block*/ - REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); - - /* check if HW reading GSP memory */ - REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, - 0, 10, max_retries); - - /* HW does is not reading GSP memory not reading too long -> - * something wrong. clear GPS memory access and notify? - * hw SW is writing to GSP memory - */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); - - /* use generic packet 4 for immediate sdp message */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, - AFMT_GENERIC_INDEX, 4); - - /* write generic packet header - * (4th byte is for GENERIC0 only) - */ - REG_SET_4(AFMT_GENERIC_HDR, 0, - AFMT_GENERIC_HB0, custom_sdp_message[0], - AFMT_GENERIC_HB1, custom_sdp_message[1], - AFMT_GENERIC_HB2, custom_sdp_message[2], - AFMT_GENERIC_HB3, custom_sdp_message[3]); - - /* write generic packet contents - * (we never use last 4 bytes) - * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers - */ - { - const uint32_t *content = - (const uint32_t *) &custom_sdp_message[4]; - - REG_WRITE(AFMT_GENERIC_0, *content++); - REG_WRITE(AFMT_GENERIC_1, *content++); - REG_WRITE(AFMT_GENERIC_2, *content++); - REG_WRITE(AFMT_GENERIC_3, *content++); - REG_WRITE(AFMT_GENERIC_4, *content++); - REG_WRITE(AFMT_GENERIC_5, *content++); - REG_WRITE(AFMT_GENERIC_6, *content++); - REG_WRITE(AFMT_GENERIC_7, *content); - } - - /* check whether GENERIC4 registers double buffer update in immediate mode - * is pending - */ - REG_WAIT(AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE_PENDING, - 0, 10, max_retries); - - /* atomically update double-buffered GENERIC4 registers in immediate mode - * (update immediately) - */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC4_IMMEDIATE_UPDATE, 1); - - /* enable GSP4 transmitting */ - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP4_SEND, 1); - - /* This bit is the master enable bit. - * When enabling secondary stream engine, - * this master bit must also be set. - * This register shared with audio info frame. - * Therefore we need to enable master bit - * if at least on of the fields is not 0 - */ - value = REG_READ(DP_SEC_CNTL); - if (value) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); -} - -void enc1_stream_encoder_stop_dp_info_packets( - struct stream_encoder *enc) -{ - /* stop generic packets on DP */ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t value = 0; - - REG_SET_10(DP_SEC_CNTL, 0, - DP_SEC_GSP0_ENABLE, 0, - DP_SEC_GSP1_ENABLE, 0, - DP_SEC_GSP2_ENABLE, 0, - DP_SEC_GSP3_ENABLE, 0, - DP_SEC_GSP4_ENABLE, 0, - DP_SEC_GSP5_ENABLE, 0, - DP_SEC_GSP6_ENABLE, 0, - DP_SEC_GSP7_ENABLE, 0, - DP_SEC_MPG_ENABLE, 0, - DP_SEC_STREAM_ENABLE, 0); - - /* this register shared with audio info frame. - * therefore we need to keep master enabled - * if at least one of the fields is not 0 */ - value = REG_READ(DP_SEC_CNTL); - if (value) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); - -} - -void enc1_stream_encoder_dp_blank( - struct dc_link *link, - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t reg1 = 0; - uint32_t max_retries = DP_BLANK_MAX_RETRY * 10; - - /* Note: For CZ, we are changing driver default to disable - * stream deferred to next VBLANK. If results are positive, we - * will make the same change to all DCE versions. There are a - * handful of panels that cannot handle disable stream at - * HBLANK and will result in a white line flash across the - * screen on stream disable. - */ - REG_GET(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, ®1); - if ((reg1 & 0x1) == 0) - /*stream not enabled*/ - return; - /* Specify the video stream disable point - * (2 = start of the next vertical blank) - */ - REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, 2); - /* Larger delay to wait until VBLANK - use max retry of - * 10us*10200=102ms. This covers 100.0ms of minimum 10 Hz mode + - * a little more because we may not trust delay accuracy. - */ - max_retries = DP_BLANK_MAX_RETRY * 501; - - /* disable DP stream */ - REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); - - link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_DP_VID_STREAM); - - /* the encoder stops sending the video stream - * at the start of the vertical blanking. - * Poll for DP_VID_STREAM_STATUS == 0 - */ - - REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, - 0, - 10, max_retries); - - /* Tell the DP encoder to ignore timing from CRTC, must be done after - * the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is - * complete, stream status will be stuck in video stream enabled state, - * i.e. DP_VID_STREAM_STATUS stuck at 1. - */ - - REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, true); - - link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_FIFO_STEER_RESET); -} - -/* output video stream to link encoder */ -void enc1_stream_encoder_dp_unblank( - struct dc_link *link, - struct stream_encoder *enc, - const struct encoder_unblank_param *param) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { - uint32_t n_vid = 0x8000; - uint32_t m_vid; - uint32_t n_multiply = 0; - uint64_t m_vid_l = n_vid; - - /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ - if (param->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { - /*this param->pixel_clk_khz is half of 444 rate for 420 already*/ - n_multiply = 1; - } - /* M / N = Fstream / Flink - * m_vid / n_vid = pixel rate / link rate - */ - - m_vid_l *= param->timing.pix_clk_100hz / 10; - m_vid_l = div_u64(m_vid_l, - param->link_settings.link_rate - * LINK_RATE_REF_FREQ_IN_KHZ); - - m_vid = (uint32_t) m_vid_l; - - /* enable auto measurement */ - - REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); - - /* auto measurement need 1 full 0x8000 symbol cycle to kick in, - * therefore program initial value for Mvid and Nvid - */ - - REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); - - REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); - - REG_UPDATE_2(DP_VID_TIMING, - DP_VID_M_N_GEN_EN, 1, - DP_VID_N_MUL, n_multiply); - } - - /* set DIG_START to 0x1 to resync FIFO */ - - REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); - - /* switch DP encoder to CRTC data */ - - REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); - - /* wait 100us for DIG/DP logic to prime - * (i.e. a few video lines) - */ - udelay(100); - - /* the hardware would start sending video at the start of the next DP - * frame (i.e. rising edge of the vblank). - * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this - * register has no effect on enable transition! HW always guarantees - * VID_STREAM enable at start of next frame, and this is not - * programmable - */ - - REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); - - link->dc->link_srv->dp_trace_source_sequence(link, - DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); -} - -void enc1_stream_encoder_set_avmute( - struct stream_encoder *enc, - bool enable) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - unsigned int value = enable ? 1 : 0; - - REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, value); -} - -void enc1_reset_hdmi_stream_attribute( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE_5(HDMI_CONTROL, - HDMI_PACKET_GEN_VERSION, 1, - HDMI_KEEPOUT_MODE, 1, - HDMI_DEEP_COLOR_ENABLE, 0, - HDMI_DATA_SCRAMBLE_EN, 0, - HDMI_CLOCK_CHANNEL_RATE, 0); -} - - -#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 -#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 - -#include "include/audio_types.h" - - -/* 25.2MHz/1.001*/ -/* 25.2MHz/1.001*/ -/* 25.2MHz*/ -/* 27MHz */ -/* 27MHz*1.001*/ -/* 27MHz*1.001*/ -/* 54MHz*/ -/* 54MHz*1.001*/ -/* 74.25MHz/1.001*/ -/* 74.25MHz*/ -/* 148.5MHz/1.001*/ -/* 148.5MHz*/ - -static const struct audio_clock_info audio_clock_info_table[16] = { - {2517, 4576, 28125, 7007, 31250, 6864, 28125}, - {2518, 4576, 28125, 7007, 31250, 6864, 28125}, - {2520, 4096, 25200, 6272, 28000, 6144, 25200}, - {2700, 4096, 27000, 6272, 30000, 6144, 27000}, - {2702, 4096, 27027, 6272, 30030, 6144, 27027}, - {2703, 4096, 27027, 6272, 30030, 6144, 27027}, - {5400, 4096, 54000, 6272, 60000, 6144, 54000}, - {5405, 4096, 54054, 6272, 60060, 6144, 54054}, - {7417, 11648, 210937, 17836, 234375, 11648, 140625}, - {7425, 4096, 74250, 6272, 82500, 6144, 74250}, - {14835, 11648, 421875, 8918, 234375, 5824, 140625}, - {14850, 4096, 148500, 6272, 165000, 6144, 148500}, - {29670, 5824, 421875, 4459, 234375, 5824, 281250}, - {29700, 3072, 222750, 4704, 247500, 5120, 247500}, - {59340, 5824, 843750, 8918, 937500, 5824, 562500}, - {59400, 3072, 445500, 9408, 990000, 6144, 594000} -}; - -static const struct audio_clock_info audio_clock_info_table_36bpc[14] = { - {2517, 9152, 84375, 7007, 48875, 9152, 56250}, - {2518, 9152, 84375, 7007, 48875, 9152, 56250}, - {2520, 4096, 37800, 6272, 42000, 6144, 37800}, - {2700, 4096, 40500, 6272, 45000, 6144, 40500}, - {2702, 8192, 81081, 6272, 45045, 8192, 54054}, - {2703, 8192, 81081, 6272, 45045, 8192, 54054}, - {5400, 4096, 81000, 6272, 90000, 6144, 81000}, - {5405, 4096, 81081, 6272, 90090, 6144, 81081}, - {7417, 11648, 316406, 17836, 351562, 11648, 210937}, - {7425, 4096, 111375, 6272, 123750, 6144, 111375}, - {14835, 11648, 632812, 17836, 703125, 11648, 421875}, - {14850, 4096, 222750, 6272, 247500, 6144, 222750}, - {29670, 5824, 632812, 8918, 703125, 5824, 421875}, - {29700, 4096, 445500, 4704, 371250, 5120, 371250} -}; - -static const struct audio_clock_info audio_clock_info_table_48bpc[14] = { - {2517, 4576, 56250, 7007, 62500, 6864, 56250}, - {2518, 4576, 56250, 7007, 62500, 6864, 56250}, - {2520, 4096, 50400, 6272, 56000, 6144, 50400}, - {2700, 4096, 54000, 6272, 60000, 6144, 54000}, - {2702, 4096, 54054, 6267, 60060, 8192, 54054}, - {2703, 4096, 54054, 6272, 60060, 8192, 54054}, - {5400, 4096, 108000, 6272, 120000, 6144, 108000}, - {5405, 4096, 108108, 6272, 120120, 6144, 108108}, - {7417, 11648, 421875, 17836, 468750, 11648, 281250}, - {7425, 4096, 148500, 6272, 165000, 6144, 148500}, - {14835, 11648, 843750, 8918, 468750, 11648, 281250}, - {14850, 4096, 297000, 6272, 330000, 6144, 297000}, - {29670, 5824, 843750, 4459, 468750, 5824, 562500}, - {29700, 3072, 445500, 4704, 495000, 5120, 495000} - - -}; - -static union audio_cea_channels speakers_to_channels( - struct audio_speaker_flags speaker_flags) -{ - union audio_cea_channels cea_channels = {0}; - - /* these are one to one */ - cea_channels.channels.FL = speaker_flags.FL_FR; - cea_channels.channels.FR = speaker_flags.FL_FR; - cea_channels.channels.LFE = speaker_flags.LFE; - cea_channels.channels.FC = speaker_flags.FC; - - /* if Rear Left and Right exist move RC speaker to channel 7 - * otherwise to channel 5 - */ - if (speaker_flags.RL_RR) { - cea_channels.channels.RL_RC = speaker_flags.RL_RR; - cea_channels.channels.RR = speaker_flags.RL_RR; - cea_channels.channels.RC_RLC_FLC = speaker_flags.RC; - } else { - cea_channels.channels.RL_RC = speaker_flags.RC; - } - - /* FRONT Left Right Center and REAR Left Right Center are exclusive */ - if (speaker_flags.FLC_FRC) { - cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC; - cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC; - } else { - cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC; - cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC; - } - - return cea_channels; -} - -void get_audio_clock_info( - enum dc_color_depth color_depth, - uint32_t crtc_pixel_clock_100Hz, - uint32_t actual_pixel_clock_100Hz, - struct audio_clock_info *audio_clock_info) -{ - const struct audio_clock_info *clock_info; - uint32_t index; - uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_100Hz / 100; - uint32_t audio_array_size; - - switch (color_depth) { - case COLOR_DEPTH_161616: - clock_info = audio_clock_info_table_48bpc; - audio_array_size = ARRAY_SIZE( - audio_clock_info_table_48bpc); - break; - case COLOR_DEPTH_121212: - clock_info = audio_clock_info_table_36bpc; - audio_array_size = ARRAY_SIZE( - audio_clock_info_table_36bpc); - break; - default: - clock_info = audio_clock_info_table; - audio_array_size = ARRAY_SIZE( - audio_clock_info_table); - break; - } - - if (clock_info != NULL) { - /* search for exact pixel clock in table */ - for (index = 0; index < audio_array_size; index++) { - if (clock_info[index].pixel_clock_in_10khz > - crtc_pixel_clock_in_10khz) - break; /* not match */ - else if (clock_info[index].pixel_clock_in_10khz == - crtc_pixel_clock_in_10khz) { - /* match found */ - *audio_clock_info = clock_info[index]; - return; - } - } - } - - /* not found */ - if (actual_pixel_clock_100Hz == 0) - actual_pixel_clock_100Hz = crtc_pixel_clock_100Hz; - - /* See HDMI spec the table entry under - * pixel clock of "Other". */ - audio_clock_info->pixel_clock_in_10khz = - actual_pixel_clock_100Hz / 100; - audio_clock_info->cts_32khz = actual_pixel_clock_100Hz / 10; - audio_clock_info->cts_44khz = actual_pixel_clock_100Hz / 10; - audio_clock_info->cts_48khz = actual_pixel_clock_100Hz / 10; - - audio_clock_info->n_32khz = 4096; - audio_clock_info->n_44khz = 6272; - audio_clock_info->n_48khz = 6144; -} - -static void enc1_se_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *audio_info) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - uint32_t channels = 0; - - ASSERT(audio_info); - if (audio_info == NULL) - /* This should not happen.it does so we don't get BSOD*/ - return; - - channels = speakers_to_channels(audio_info->flags.speaker_flags).all; - - /* setup the audio stream source select (audio -> dig mapping) */ - REG_SET(AFMT_AUDIO_SRC_CONTROL, 0, AFMT_AUDIO_SRC_SELECT, az_inst); - - /* Channel allocation */ - REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, channels); -} - -static void enc1_se_setup_hdmi_audio( - struct stream_encoder *enc, - const struct audio_crtc_info *crtc_info) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - struct audio_clock_info audio_clock_info = {0}; - - /* HDMI_AUDIO_PACKET_CONTROL */ - REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, - HDMI_AUDIO_DELAY_EN, 1); - - /* AFMT_AUDIO_PACKET_CONTROL */ - REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); - - /* AFMT_AUDIO_PACKET_CONTROL2 */ - REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, - AFMT_AUDIO_LAYOUT_OVRD, 0, - AFMT_60958_OSF_OVRD, 0); - - /* HDMI_ACR_PACKET_CONTROL */ - REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL, - HDMI_ACR_AUTO_SEND, 1, - HDMI_ACR_SOURCE, 0, - HDMI_ACR_AUDIO_PRIORITY, 0); - - /* Program audio clock sample/regeneration parameters */ - get_audio_clock_info(crtc_info->color_depth, - crtc_info->requested_pixel_clock_100Hz, - crtc_info->calculated_pixel_clock_100Hz, - &audio_clock_info); - DC_LOG_HW_AUDIO( - "\n%s:Input::requested_pixel_clock_100Hz = %d" \ - "calculated_pixel_clock_100Hz = %d \n", __func__, \ - crtc_info->requested_pixel_clock_100Hz, \ - crtc_info->calculated_pixel_clock_100Hz); - - /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ - REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); - - /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ - REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); - - /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ - REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); - - /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ - REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); - - /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ - REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); - - /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ - REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); - - /* Video driver cannot know in advance which sample rate will - * be used by HD Audio driver - * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is - * programmed below in interruppt callback - */ - - /* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK & - * AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK - */ - REG_UPDATE_2(AFMT_60958_0, - AFMT_60958_CS_CHANNEL_NUMBER_L, 1, - AFMT_60958_CS_CLOCK_ACCURACY, 0); - - /* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */ - REG_UPDATE(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, 2); - - /* AFMT_60958_2 now keep this settings until - * Programming guide comes out - */ - REG_UPDATE_6(AFMT_60958_2, - AFMT_60958_CS_CHANNEL_NUMBER_2, 3, - AFMT_60958_CS_CHANNEL_NUMBER_3, 4, - AFMT_60958_CS_CHANNEL_NUMBER_4, 5, - AFMT_60958_CS_CHANNEL_NUMBER_5, 6, - AFMT_60958_CS_CHANNEL_NUMBER_6, 7, - AFMT_60958_CS_CHANNEL_NUMBER_7, 8); -} - -static void enc1_se_setup_dp_audio( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* --- DP Audio packet configurations --- */ - - /* ATP Configuration */ - REG_SET(DP_SEC_AUD_N, 0, - DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); - - /* Async/auto-calc timestamp mode */ - REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, - DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); - - /* --- The following are the registers - * copied from the SetupHDMI --- - */ - - /* AFMT_AUDIO_PACKET_CONTROL */ - REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); - - /* AFMT_AUDIO_PACKET_CONTROL2 */ - /* Program the ATP and AIP next */ - REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, - AFMT_AUDIO_LAYOUT_OVRD, 0, - AFMT_60958_OSF_OVRD, 0); - - /* AFMT_INFOFRAME_CONTROL0 */ - REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); - - /* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ - REG_UPDATE(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, 0); -} - -void enc1_se_enable_audio_clock( - struct stream_encoder *enc, - bool enable) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (REG(AFMT_CNTL) == 0) - return; /* DCE8/10 does not have this register */ - - REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, !!enable); - - /* wait for AFMT clock to turn on, - * expectation: this should complete in 1-2 reads - * - * REG_WAIT(AFMT_CNTL, AFMT_AUDIO_CLOCK_ON, !!enable, 1, 10); - * - * TODO: wait for clock_on does not work well. May need HW - * program sequence. But audio seems work normally even without wait - * for clock_on status change - */ -} - -void enc1_se_enable_dp_audio( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* Enable Audio packets */ - REG_UPDATE(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, 1); - - /* Program the ATP and AIP next */ - REG_UPDATE_2(DP_SEC_CNTL, - DP_SEC_ATP_ENABLE, 1, - DP_SEC_AIP_ENABLE, 1); - - /* Program STREAM_ENABLE after all the other enables. */ - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); -} - -static void enc1_se_disable_dp_audio( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t value = 0; - - /* Disable Audio packets */ - REG_UPDATE_5(DP_SEC_CNTL, - DP_SEC_ASP_ENABLE, 0, - DP_SEC_ATP_ENABLE, 0, - DP_SEC_AIP_ENABLE, 0, - DP_SEC_ACM_ENABLE, 0, - DP_SEC_STREAM_ENABLE, 0); - - /* This register shared with encoder info frame. Therefore we need to - * keep master enabled if at least on of the fields is not 0 - */ - value = REG_READ(DP_SEC_CNTL); - if (value != 0) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); - -} - -void enc1_se_audio_mute_control( - struct stream_encoder *enc, - bool mute) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, !mute); -} - -void enc1_se_dp_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info) -{ - enc1_se_audio_setup(enc, az_inst, info); -} - -void enc1_se_dp_audio_enable( - struct stream_encoder *enc) -{ - enc1_se_enable_audio_clock(enc, true); - enc1_se_setup_dp_audio(enc); - enc1_se_enable_dp_audio(enc); -} - -void enc1_se_dp_audio_disable( - struct stream_encoder *enc) -{ - enc1_se_disable_dp_audio(enc); - enc1_se_enable_audio_clock(enc, false); -} - -void enc1_se_hdmi_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info, - struct audio_crtc_info *audio_crtc_info) -{ - enc1_se_enable_audio_clock(enc, true); - enc1_se_setup_hdmi_audio(enc, audio_crtc_info); - enc1_se_audio_setup(enc, az_inst, info); -} - -void enc1_se_hdmi_audio_disable( - struct stream_encoder *enc) -{ - if (enc->afmt && enc->afmt->funcs->afmt_powerdown) - enc->afmt->funcs->afmt_powerdown(enc->afmt); - - enc1_se_enable_audio_clock(enc, false); -} - - -void enc1_setup_stereo_sync( - struct stream_encoder *enc, - int tg_inst, bool enable) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, tg_inst); - REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, !enable); -} - -void enc1_dig_connect_to_otg( - struct stream_encoder *enc, - int tg_inst) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE(DIG_FE_CNTL, DIG_SOURCE_SELECT, tg_inst); -} - -unsigned int enc1_dig_source_otg( - struct stream_encoder *enc) -{ - uint32_t tg_inst = 0; - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_GET(DIG_FE_CNTL, DIG_SOURCE_SELECT, &tg_inst); - - return tg_inst; -} - -bool enc1_stream_encoder_dp_get_pixel_format( - struct stream_encoder *enc, - enum dc_pixel_encoding *encoding, - enum dc_color_depth *depth) -{ - uint32_t hw_encoding = 0; - uint32_t hw_depth = 0; - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (enc == NULL || - encoding == NULL || - depth == NULL) - return false; - - REG_GET_2(DP_PIXEL_FORMAT, - DP_PIXEL_ENCODING, &hw_encoding, - DP_COMPONENT_DEPTH, &hw_depth); - - switch (hw_depth) { - case DP_COMPONENT_PIXEL_DEPTH_6BPC: - *depth = COLOR_DEPTH_666; - break; - case DP_COMPONENT_PIXEL_DEPTH_8BPC: - *depth = COLOR_DEPTH_888; - break; - case DP_COMPONENT_PIXEL_DEPTH_10BPC: - *depth = COLOR_DEPTH_101010; - break; - case DP_COMPONENT_PIXEL_DEPTH_12BPC: - *depth = COLOR_DEPTH_121212; - break; - case DP_COMPONENT_PIXEL_DEPTH_16BPC: - *depth = COLOR_DEPTH_161616; - break; - default: - *depth = COLOR_DEPTH_UNDEFINED; - break; - } - - switch (hw_encoding) { - case DP_PIXEL_ENCODING_TYPE_RGB444: - *encoding = PIXEL_ENCODING_RGB; - break; - case DP_PIXEL_ENCODING_TYPE_YCBCR422: - *encoding = PIXEL_ENCODING_YCBCR422; - break; - case DP_PIXEL_ENCODING_TYPE_YCBCR444: - case DP_PIXEL_ENCODING_TYPE_Y_ONLY: - *encoding = PIXEL_ENCODING_YCBCR444; - break; - case DP_PIXEL_ENCODING_TYPE_YCBCR420: - *encoding = PIXEL_ENCODING_YCBCR420; - break; - default: - *encoding = PIXEL_ENCODING_UNDEFINED; - break; - } - return true; -} - -static const struct stream_encoder_funcs dcn10_str_enc_funcs = { - .dp_set_stream_attribute = - enc1_stream_encoder_dp_set_stream_attribute, - .hdmi_set_stream_attribute = - enc1_stream_encoder_hdmi_set_stream_attribute, - .dvi_set_stream_attribute = - enc1_stream_encoder_dvi_set_stream_attribute, - .set_throttled_vcp_size = - enc1_stream_encoder_set_throttled_vcp_size, - .update_hdmi_info_packets = - enc1_stream_encoder_update_hdmi_info_packets, - .stop_hdmi_info_packets = - enc1_stream_encoder_stop_hdmi_info_packets, - .update_dp_info_packets = - enc1_stream_encoder_update_dp_info_packets, - .send_immediate_sdp_message = - enc1_stream_encoder_send_immediate_sdp_message, - .stop_dp_info_packets = - enc1_stream_encoder_stop_dp_info_packets, - .dp_blank = - enc1_stream_encoder_dp_blank, - .dp_unblank = - enc1_stream_encoder_dp_unblank, - .audio_mute_control = enc1_se_audio_mute_control, - - .dp_audio_setup = enc1_se_dp_audio_setup, - .dp_audio_enable = enc1_se_dp_audio_enable, - .dp_audio_disable = enc1_se_dp_audio_disable, - - .hdmi_audio_setup = enc1_se_hdmi_audio_setup, - .hdmi_audio_disable = enc1_se_hdmi_audio_disable, - .setup_stereo_sync = enc1_setup_stereo_sync, - .set_avmute = enc1_stream_encoder_set_avmute, - .dig_connect_to_otg = enc1_dig_connect_to_otg, - .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, - .dig_source_otg = enc1_dig_source_otg, - - .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, -}; - -void dcn10_stream_encoder_construct( - struct dcn10_stream_encoder *enc1, - struct dc_context *ctx, - struct dc_bios *bp, - enum engine_id eng_id, - const struct dcn10_stream_enc_registers *regs, - const struct dcn10_stream_encoder_shift *se_shift, - const struct dcn10_stream_encoder_mask *se_mask) -{ - enc1->base.funcs = &dcn10_str_enc_funcs; - enc1->base.ctx = ctx; - enc1->base.id = eng_id; - enc1->base.bp = bp; - enc1->regs = regs; - enc1->se_shift = se_shift; - enc1->se_mask = se_mask; - enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h deleted file mode 100644 index 54a6a4ebd636..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ /dev/null @@ -1,749 +0,0 @@ -/* - * 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 - * - */ - -#ifndef __DC_STREAM_ENCODER_DCN10_H__ -#define __DC_STREAM_ENCODER_DCN10_H__ - -#include "stream_encoder.h" - -#define DCN10STRENC_FROM_STRENC(stream_encoder)\ - container_of(stream_encoder, struct dcn10_stream_encoder, base) - -#define SE_COMMON_DCN_REG_LIST(id) \ - SRI(AFMT_CNTL, DIG, id), \ - SRI(AFMT_GENERIC_0, DIG, id), \ - SRI(AFMT_GENERIC_1, DIG, id), \ - SRI(AFMT_GENERIC_2, DIG, id), \ - SRI(AFMT_GENERIC_3, DIG, id), \ - SRI(AFMT_GENERIC_4, DIG, id), \ - SRI(AFMT_GENERIC_5, DIG, id), \ - SRI(AFMT_GENERIC_6, DIG, id), \ - SRI(AFMT_GENERIC_7, DIG, id), \ - SRI(AFMT_GENERIC_HDR, DIG, id), \ - SRI(AFMT_INFOFRAME_CONTROL0, DIG, id), \ - SRI(AFMT_VBI_PACKET_CONTROL, DIG, id), \ - SRI(AFMT_VBI_PACKET_CONTROL1, DIG, id), \ - SRI(AFMT_AUDIO_PACKET_CONTROL, DIG, id), \ - SRI(AFMT_AUDIO_PACKET_CONTROL2, DIG, id), \ - SRI(AFMT_AUDIO_SRC_CONTROL, DIG, id), \ - SRI(AFMT_60958_0, DIG, id), \ - SRI(AFMT_60958_1, DIG, id), \ - SRI(AFMT_60958_2, DIG, id), \ - SRI(DIG_FE_CNTL, DIG, id), \ - SRI(DIG_FIFO_STATUS, DIG, id), \ - SRI(HDMI_CONTROL, DIG, id), \ - SRI(HDMI_DB_CONTROL, DIG, id), \ - SRI(HDMI_GC, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ - SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \ - SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \ - SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \ - SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ - SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\ - SRI(HDMI_ACR_32_0, DIG, id),\ - SRI(HDMI_ACR_32_1, DIG, id),\ - SRI(HDMI_ACR_44_0, DIG, id),\ - SRI(HDMI_ACR_44_1, DIG, id),\ - SRI(HDMI_ACR_48_0, DIG, id),\ - SRI(HDMI_ACR_48_1, DIG, id),\ - SRI(DP_DB_CNTL, DP, id), \ - SRI(DP_MSA_MISC, DP, id), \ - SRI(DP_MSA_VBID_MISC, DP, id), \ - SRI(DP_MSA_COLORIMETRY, DP, id), \ - SRI(DP_MSA_TIMING_PARAM1, DP, id), \ - SRI(DP_MSA_TIMING_PARAM2, DP, id), \ - SRI(DP_MSA_TIMING_PARAM3, DP, id), \ - SRI(DP_MSA_TIMING_PARAM4, DP, id), \ - SRI(DP_MSE_RATE_CNTL, DP, id), \ - SRI(DP_MSE_RATE_UPDATE, DP, id), \ - SRI(DP_PIXEL_FORMAT, DP, id), \ - SRI(DP_SEC_CNTL, DP, id), \ - SRI(DP_SEC_CNTL1, DP, id), \ - SRI(DP_SEC_CNTL2, DP, id), \ - SRI(DP_SEC_CNTL5, DP, id), \ - SRI(DP_SEC_CNTL6, DP, id), \ - SRI(DP_STEER_FIFO, DP, id), \ - SRI(DP_VID_M, DP, id), \ - SRI(DP_VID_N, DP, id), \ - SRI(DP_VID_STREAM_CNTL, DP, id), \ - SRI(DP_VID_TIMING, DP, id), \ - SRI(DP_SEC_AUD_N, DP, id), \ - SRI(DP_SEC_AUD_N_READBACK, DP, id), \ - SRI(DP_SEC_AUD_M_READBACK, DP, id), \ - SRI(DP_SEC_TIMESTAMP, DP, id), \ - SRI(DIG_CLOCK_PATTERN, DIG, id) - -#define SE_DCN_REG_LIST(id)\ - SE_COMMON_DCN_REG_LIST(id) - - -struct dcn10_stream_enc_registers { - uint32_t AFMT_CNTL; - uint32_t AFMT_AVI_INFO0; - uint32_t AFMT_AVI_INFO1; - uint32_t AFMT_AVI_INFO2; - uint32_t AFMT_AVI_INFO3; - uint32_t AFMT_GENERIC_0; - uint32_t AFMT_GENERIC_1; - uint32_t AFMT_GENERIC_2; - uint32_t AFMT_GENERIC_3; - uint32_t AFMT_GENERIC_4; - uint32_t AFMT_GENERIC_5; - uint32_t AFMT_GENERIC_6; - uint32_t AFMT_GENERIC_7; - uint32_t AFMT_GENERIC_HDR; - uint32_t AFMT_INFOFRAME_CONTROL0; - uint32_t AFMT_VBI_PACKET_CONTROL; - uint32_t AFMT_VBI_PACKET_CONTROL1; - uint32_t AFMT_AUDIO_PACKET_CONTROL; - uint32_t AFMT_AUDIO_PACKET_CONTROL2; - uint32_t AFMT_AUDIO_SRC_CONTROL; - uint32_t AFMT_60958_0; - uint32_t AFMT_60958_1; - uint32_t AFMT_60958_2; - uint32_t DIG_FE_CNTL; - uint32_t DIG_FIFO_STATUS; - uint32_t DP_MSE_RATE_CNTL; - uint32_t DP_MSE_RATE_UPDATE; - uint32_t DP_PIXEL_FORMAT; - uint32_t DP_SEC_CNTL; - uint32_t DP_SEC_CNTL1; - uint32_t DP_SEC_CNTL2; - uint32_t DP_SEC_CNTL5; - uint32_t DP_SEC_CNTL6; - uint32_t DP_STEER_FIFO; - uint32_t DP_VID_M; - uint32_t DP_VID_N; - uint32_t DP_VID_STREAM_CNTL; - uint32_t DP_VID_TIMING; - uint32_t DP_SEC_AUD_N; - uint32_t DP_SEC_AUD_N_READBACK; - uint32_t DP_SEC_AUD_M_READBACK; - uint32_t DP_SEC_TIMESTAMP; - uint32_t HDMI_CONTROL; - uint32_t HDMI_GC; - uint32_t HDMI_GENERIC_PACKET_CONTROL0; - uint32_t HDMI_GENERIC_PACKET_CONTROL1; - uint32_t HDMI_GENERIC_PACKET_CONTROL2; - uint32_t HDMI_GENERIC_PACKET_CONTROL3; - uint32_t HDMI_GENERIC_PACKET_CONTROL4; - uint32_t HDMI_GENERIC_PACKET_CONTROL5; - uint32_t HDMI_INFOFRAME_CONTROL0; - uint32_t HDMI_INFOFRAME_CONTROL1; - uint32_t HDMI_VBI_PACKET_CONTROL; - uint32_t HDMI_AUDIO_PACKET_CONTROL; - uint32_t HDMI_ACR_PACKET_CONTROL; - uint32_t HDMI_ACR_32_0; - uint32_t HDMI_ACR_32_1; - uint32_t HDMI_ACR_44_0; - uint32_t HDMI_ACR_44_1; - uint32_t HDMI_ACR_48_0; - uint32_t HDMI_ACR_48_1; - uint32_t DP_DB_CNTL; - uint32_t DP_MSA_MISC; - uint32_t DP_MSA_VBID_MISC; - uint32_t DP_MSA_COLORIMETRY; - uint32_t DP_MSA_TIMING_PARAM1; - uint32_t DP_MSA_TIMING_PARAM2; - uint32_t DP_MSA_TIMING_PARAM3; - uint32_t DP_MSA_TIMING_PARAM4; - uint32_t HDMI_DB_CONTROL; - uint32_t DP_DSC_CNTL; - uint32_t DP_DSC_BYTES_PER_PIXEL; - uint32_t DME_CONTROL; - uint32_t DP_SEC_METADATA_TRANSMISSION; - uint32_t HDMI_METADATA_PACKET_CONTROL; - uint32_t DP_SEC_FRAMING4; - uint32_t DP_GSP11_CNTL; - uint32_t HDMI_GENERIC_PACKET_CONTROL6; - uint32_t HDMI_GENERIC_PACKET_CONTROL7; - uint32_t HDMI_GENERIC_PACKET_CONTROL8; - uint32_t HDMI_GENERIC_PACKET_CONTROL9; - uint32_t HDMI_GENERIC_PACKET_CONTROL10; - uint32_t DIG_CLOCK_PATTERN; - uint32_t DIG_FIFO_CTRL0; - uint32_t DIG_FE_CLK_CNTL; - uint32_t DIG_FE_EN_CNTL; - uint32_t STREAM_MAPPER_CONTROL; -}; - - -#define SE_SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\ - SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\ - SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, mask_sh),\ - SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, mask_sh),\ - SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB3, mask_sh),\ - SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ - SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ - SE_SF(DIG0_AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\ - SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ - SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ - SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ - SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\ - SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ - SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ - SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ - SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ - SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ - SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ - SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_START, mask_sh),\ - SE_SF(DIG0_AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\ - SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\ - SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ - SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\ - SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ - SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\ - SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\ - SE_SF(DIG0_AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\ - SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\ - SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\ - SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\ - SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\ - SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\ - SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\ - SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ - SE_SF(DP0_DP_SEC_AUD_N_READBACK, DP_SEC_AUD_N_READBACK, mask_sh),\ - SE_SF(DP0_DP_SEC_AUD_M_READBACK, DP_SEC_AUD_M_READBACK, mask_sh),\ - SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ - SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh),\ - SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_LEVEL_ERROR, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_USE_OVERWRITE_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_OVERWRITE_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_ERROR_ACK, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CAL_AVERAGE_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MAXIMUM_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MINIMUM_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_READ_CLOCK_SRC, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CALIBRATED, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECAL_AVERAGE, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECOMP_MINMAX, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE_PENDING, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_IMMEDIATE_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE, mask_sh),\ - SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_PPS, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ - SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ - SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ - SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh),\ - SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh) - -#define SE_COMMON_MASK_SH_LIST_DCN10(mask_sh)\ - SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_LINE, mask_sh) - - -#define SE_REG_FIELD_LIST_DCN1_0(type) \ - type AFMT_GENERIC_INDEX;\ - type AFMT_GENERIC_HB0;\ - type AFMT_GENERIC_HB1;\ - type AFMT_GENERIC_HB2;\ - type AFMT_GENERIC_HB3;\ - type AFMT_GENERIC_LOCK_STATUS;\ - type AFMT_GENERIC_CONFLICT;\ - type AFMT_GENERIC_CONFLICT_CLR;\ - type AFMT_GENERIC0_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC1_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC2_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC3_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC4_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC4_IMMEDIATE_UPDATE_PENDING;\ - type AFMT_GENERIC5_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC6_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC7_FRAME_UPDATE_PENDING;\ - type AFMT_GENERIC0_FRAME_UPDATE;\ - type AFMT_GENERIC1_FRAME_UPDATE;\ - type AFMT_GENERIC2_FRAME_UPDATE;\ - type AFMT_GENERIC3_FRAME_UPDATE;\ - type AFMT_GENERIC4_FRAME_UPDATE;\ - type AFMT_GENERIC0_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC1_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC2_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC3_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC4_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC5_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC6_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC7_IMMEDIATE_UPDATE;\ - type AFMT_GENERIC5_FRAME_UPDATE;\ - type AFMT_GENERIC6_FRAME_UPDATE;\ - type AFMT_GENERIC7_FRAME_UPDATE;\ - type HDMI_GENERIC0_CONT;\ - type HDMI_GENERIC0_SEND;\ - type HDMI_GENERIC0_LINE;\ - type HDMI_GENERIC1_CONT;\ - type HDMI_GENERIC1_SEND;\ - type HDMI_GENERIC1_LINE;\ - type HDMI_GENERIC2_CONT;\ - type HDMI_GENERIC2_SEND;\ - type HDMI_GENERIC2_LINE;\ - type HDMI_GENERIC3_CONT;\ - type HDMI_GENERIC3_SEND;\ - type HDMI_GENERIC3_LINE;\ - type HDMI_GENERIC4_CONT;\ - type HDMI_GENERIC4_SEND;\ - type HDMI_GENERIC4_LINE;\ - type HDMI_GENERIC5_CONT;\ - type HDMI_GENERIC5_SEND;\ - type HDMI_GENERIC5_LINE;\ - type HDMI_GENERIC6_CONT;\ - type HDMI_GENERIC6_SEND;\ - type HDMI_GENERIC6_LINE;\ - type HDMI_GENERIC7_CONT;\ - type HDMI_GENERIC7_SEND;\ - type HDMI_GENERIC7_LINE;\ - type DP_PIXEL_ENCODING;\ - type DP_COMPONENT_DEPTH;\ - type HDMI_PACKET_GEN_VERSION;\ - type HDMI_KEEPOUT_MODE;\ - type HDMI_DEEP_COLOR_ENABLE;\ - type HDMI_CLOCK_CHANNEL_RATE;\ - type HDMI_DEEP_COLOR_DEPTH;\ - type HDMI_GC_CONT;\ - type HDMI_GC_SEND;\ - type HDMI_NULL_SEND;\ - type HDMI_DATA_SCRAMBLE_EN;\ - type HDMI_NO_EXTRA_NULL_PACKET_FILLED;\ - type HDMI_AUDIO_INFO_SEND;\ - type AFMT_AUDIO_INFO_UPDATE;\ - type HDMI_AUDIO_INFO_LINE;\ - type HDMI_GC_AVMUTE;\ - type DP_MSE_RATE_X;\ - type DP_MSE_RATE_Y;\ - type DP_MSE_RATE_UPDATE_PENDING;\ - type DP_SEC_GSP0_ENABLE;\ - type DP_SEC_STREAM_ENABLE;\ - type DP_SEC_GSP1_ENABLE;\ - type DP_SEC_GSP2_ENABLE;\ - type DP_SEC_GSP3_ENABLE;\ - type DP_SEC_GSP4_ENABLE;\ - type DP_SEC_GSP5_ENABLE;\ - type DP_SEC_GSP5_LINE_NUM;\ - type DP_SEC_GSP5_LINE_REFERENCE;\ - type DP_SEC_GSP6_ENABLE;\ - type DP_SEC_GSP7_ENABLE;\ - type DP_SEC_GSP7_PPS;\ - type DP_SEC_GSP7_SEND;\ - type DP_SEC_GSP4_SEND;\ - type DP_SEC_GSP4_SEND_PENDING;\ - type DP_SEC_GSP4_LINE_NUM;\ - type DP_SEC_GSP4_SEND_ANY_LINE;\ - type DP_SEC_MPG_ENABLE;\ - type DP_VID_STREAM_DIS_DEFER;\ - type DP_VID_STREAM_ENABLE;\ - type DP_VID_STREAM_STATUS;\ - type DP_STEER_FIFO_RESET;\ - type DP_VID_M_N_GEN_EN;\ - type DP_VID_N;\ - type DP_VID_M;\ - type DIG_START;\ - type AFMT_AUDIO_SRC_SELECT;\ - type AFMT_AUDIO_CHANNEL_ENABLE;\ - type HDMI_AUDIO_PACKETS_PER_LINE;\ - type HDMI_AUDIO_DELAY_EN;\ - type AFMT_60958_CS_UPDATE;\ - type AFMT_AUDIO_LAYOUT_OVRD;\ - type AFMT_60958_OSF_OVRD;\ - type HDMI_ACR_AUTO_SEND;\ - type HDMI_ACR_SOURCE;\ - type HDMI_ACR_AUDIO_PRIORITY;\ - type HDMI_ACR_CTS_32;\ - type HDMI_ACR_N_32;\ - type HDMI_ACR_CTS_44;\ - type HDMI_ACR_N_44;\ - type HDMI_ACR_CTS_48;\ - type HDMI_ACR_N_48;\ - type AFMT_60958_CS_CHANNEL_NUMBER_L;\ - type AFMT_60958_CS_CLOCK_ACCURACY;\ - type AFMT_60958_CS_CHANNEL_NUMBER_R;\ - type AFMT_60958_CS_CHANNEL_NUMBER_2;\ - type AFMT_60958_CS_CHANNEL_NUMBER_3;\ - type AFMT_60958_CS_CHANNEL_NUMBER_4;\ - type AFMT_60958_CS_CHANNEL_NUMBER_5;\ - type AFMT_60958_CS_CHANNEL_NUMBER_6;\ - type AFMT_60958_CS_CHANNEL_NUMBER_7;\ - type DP_SEC_AUD_N;\ - type DP_SEC_AUD_N_READBACK;\ - type DP_SEC_AUD_M_READBACK;\ - type DP_SEC_TIMESTAMP_MODE;\ - type DP_SEC_ASP_ENABLE;\ - type DP_SEC_ATP_ENABLE;\ - type DP_SEC_AIP_ENABLE;\ - type DP_SEC_ACM_ENABLE;\ - type DP_SEC_GSP7_LINE_NUM;\ - type AFMT_AUDIO_SAMPLE_SEND;\ - type AFMT_AUDIO_CLOCK_EN;\ - type TMDS_PIXEL_ENCODING;\ - type TMDS_COLOR_FORMAT;\ - type DIG_STEREOSYNC_SELECT;\ - type DIG_STEREOSYNC_GATE_EN;\ - type DP_DB_DISABLE;\ - type DP_MSA_MISC0;\ - type DP_MSA_HTOTAL;\ - type DP_MSA_VTOTAL;\ - type DP_MSA_HSTART;\ - type DP_MSA_VSTART;\ - type DP_MSA_HSYNCWIDTH;\ - type DP_MSA_HSYNCPOLARITY;\ - type DP_MSA_VSYNCWIDTH;\ - type DP_MSA_VSYNCPOLARITY;\ - type DP_MSA_HWIDTH;\ - type DP_MSA_VHEIGHT;\ - type HDMI_DB_DISABLE;\ - type DP_VID_N_MUL;\ - type DP_VID_M_DOUBLE_VALUE_EN;\ - type DIG_SOURCE_SELECT;\ - type DIG_FIFO_LEVEL_ERROR;\ - type DIG_FIFO_USE_OVERWRITE_LEVEL;\ - type DIG_FIFO_OVERWRITE_LEVEL;\ - type DIG_FIFO_ERROR_ACK;\ - type DIG_FIFO_CAL_AVERAGE_LEVEL;\ - type DIG_FIFO_MAXIMUM_LEVEL;\ - type DIG_FIFO_MINIMUM_LEVEL;\ - type DIG_FIFO_READ_CLOCK_SRC;\ - type DIG_FIFO_CALIBRATED;\ - type DIG_FIFO_FORCE_RECAL_AVERAGE;\ - type DIG_FIFO_FORCE_RECOMP_MINMAX;\ - type DIG_CLOCK_PATTERN - -#define SE_REG_FIELD_LIST_DCN2_0(type) \ - type DP_DSC_MODE;\ - type DP_DSC_SLICE_WIDTH;\ - type DP_DSC_BYTES_PER_PIXEL;\ - type DP_VBID6_LINE_REFERENCE;\ - type DP_VBID6_LINE_NUM;\ - type METADATA_ENGINE_EN;\ - type METADATA_HUBP_REQUESTOR_ID;\ - type METADATA_STREAM_TYPE;\ - type DP_SEC_METADATA_PACKET_ENABLE;\ - type DP_SEC_METADATA_PACKET_LINE_REFERENCE;\ - type DP_SEC_METADATA_PACKET_LINE;\ - type HDMI_METADATA_PACKET_ENABLE;\ - type HDMI_METADATA_PACKET_LINE_REFERENCE;\ - type HDMI_METADATA_PACKET_LINE;\ - type DOLBY_VISION_EN;\ - type DP_PIXEL_COMBINE;\ - type DP_SST_SDP_SPLITTING - -#define SE_REG_FIELD_LIST_DCN3_0(type) \ - type HDMI_GENERIC8_CONT;\ - type HDMI_GENERIC8_SEND;\ - type HDMI_GENERIC8_LINE;\ - type HDMI_GENERIC9_CONT;\ - type HDMI_GENERIC9_SEND;\ - type HDMI_GENERIC9_LINE;\ - type HDMI_GENERIC10_CONT;\ - type HDMI_GENERIC10_SEND;\ - type HDMI_GENERIC10_LINE;\ - type HDMI_GENERIC11_CONT;\ - type HDMI_GENERIC11_SEND;\ - type HDMI_GENERIC11_LINE;\ - type HDMI_GENERIC12_CONT;\ - type HDMI_GENERIC12_SEND;\ - type HDMI_GENERIC12_LINE;\ - type HDMI_GENERIC13_CONT;\ - type HDMI_GENERIC13_SEND;\ - type HDMI_GENERIC13_LINE;\ - type HDMI_GENERIC14_CONT;\ - type HDMI_GENERIC14_SEND;\ - type HDMI_GENERIC14_LINE;\ - type DP_SEC_GSP11_PPS;\ - type DP_SEC_GSP11_ENABLE;\ - type DP_SEC_GSP11_LINE_NUM - -#define SE_REG_FIELD_LIST_DCN3_1_COMMON(type) \ - type DIG_FIFO_OUTPUT_PIXEL_MODE;\ - type DP_PIXEL_PER_CYCLE_PROCESSING_MODE;\ - type DIG_SYMCLK_FE_ON;\ - type DIG_FIFO_READ_START_LEVEL;\ - type DIG_FIFO_ENABLE;\ - type DIG_FIFO_RESET;\ - type DIG_FIFO_RESET_DONE;\ - type PIXEL_ENCODING_TYPE;\ - type UNCOMPRESSED_PIXEL_FORMAT;\ - type UNCOMPRESSED_COMPONENT_DEPTH - -#define SE_REG_FIELD_LIST_DCN3_5_COMMON(type) \ - type DIG_FE_CLK_EN;\ - type DIG_FE_MODE;\ - type DIG_FE_SOFT_RESET;\ - type DIG_FE_ENABLE;\ - type DIG_FE_SYMCLK_FE_G_CLOCK_ON;\ - type DIG_FE_DISPCLK_G_CLOCK_ON;\ - type DIG_FE_SYMCLK_FE_G_AFMT_CLOCK_ON;\ - type DIG_FE_SYMCLK_FE_G_TMDS_CLOCK_ON;\ - type DIG_FE_SOCCLK_G_AFMT_CLOCK_ON;\ - type DIG_STREAM_LINK_TARGET - -#define SE_REG_FIELD_LIST_DCN4_01_COMMON(type) \ - type COMPRESSED_PIXEL_FORMAT;\ - type DP_VID_N_INTERVAL;\ - type DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE;\ - type DP_STEER_FIFO_ENABLE -struct dcn10_stream_encoder_shift { - SE_REG_FIELD_LIST_DCN1_0(uint8_t); - uint8_t HDMI_ACP_SEND; - SE_REG_FIELD_LIST_DCN2_0(uint8_t); - SE_REG_FIELD_LIST_DCN3_0(uint8_t); - SE_REG_FIELD_LIST_DCN3_1_COMMON(uint8_t); - SE_REG_FIELD_LIST_DCN3_5_COMMON(uint8_t); - SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); -}; - -struct dcn10_stream_encoder_mask { - SE_REG_FIELD_LIST_DCN1_0(uint32_t); - uint32_t HDMI_ACP_SEND; - SE_REG_FIELD_LIST_DCN2_0(uint32_t); - SE_REG_FIELD_LIST_DCN3_0(uint32_t); - SE_REG_FIELD_LIST_DCN3_1_COMMON(uint32_t); - SE_REG_FIELD_LIST_DCN3_5_COMMON(uint32_t); - SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); -}; - -struct dcn10_stream_encoder { - struct stream_encoder base; - const struct dcn10_stream_enc_registers *regs; - const struct dcn10_stream_encoder_shift *se_shift; - const struct dcn10_stream_encoder_mask *se_mask; -}; - -void dcn10_stream_encoder_construct( - struct dcn10_stream_encoder *enc1, - struct dc_context *ctx, - struct dc_bios *bp, - enum engine_id eng_id, - const struct dcn10_stream_enc_registers *regs, - const struct dcn10_stream_encoder_shift *se_shift, - const struct dcn10_stream_encoder_mask *se_mask); - -void enc1_update_generic_info_packet( - struct dcn10_stream_encoder *enc1, - uint32_t packet_index, - const struct dc_info_packet *info_packet); - -void enc1_stream_encoder_dp_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - enum dc_color_space output_color_space, - bool use_vsc_sdp_for_colorimetry, - uint32_t enable_sdp_splitting); - -void enc1_stream_encoder_hdmi_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - int actual_pix_clk_khz, - bool enable_audio); - -void enc1_stream_encoder_dvi_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - bool is_dual_link); - -void enc1_stream_encoder_set_throttled_vcp_size( - struct stream_encoder *enc, - struct fixed31_32 avg_time_slots_per_mtp); - -void enc1_stream_encoder_update_dp_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame); - -void enc1_stream_encoder_send_immediate_sdp_message( - struct stream_encoder *enc, - const uint8_t *custom_sdp_message, - unsigned int sdp_message_size); - -void enc1_stream_encoder_stop_dp_info_packets( - struct stream_encoder *enc); - -void enc1_stream_encoder_dp_blank( - struct dc_link *link, - struct stream_encoder *enc); - -void enc1_stream_encoder_dp_unblank( - struct dc_link *link, - struct stream_encoder *enc, - const struct encoder_unblank_param *param); - -void enc1_setup_stereo_sync( - struct stream_encoder *enc, - int tg_inst, bool enable); - -void enc1_stream_encoder_set_avmute( - struct stream_encoder *enc, - bool enable); - -void enc1_se_audio_mute_control( - struct stream_encoder *enc, - bool mute); - -void enc1_se_dp_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info); - -void enc1_se_dp_audio_enable( - struct stream_encoder *enc); - -void enc1_se_dp_audio_disable( - struct stream_encoder *enc); - -void enc1_se_hdmi_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info, - struct audio_crtc_info *audio_crtc_info); - -void enc1_se_hdmi_audio_disable( - struct stream_encoder *enc); - -void enc1_dig_connect_to_otg( - struct stream_encoder *enc, - int tg_inst); - -unsigned int enc1_dig_source_otg( - struct stream_encoder *enc); - -void enc1_stream_encoder_set_stream_attribute_helper( - struct dcn10_stream_encoder *enc1, - struct dc_crtc_timing *crtc_timing); - -void enc1_se_enable_audio_clock( - struct stream_encoder *enc, - bool enable); - -void enc1_se_enable_dp_audio( - struct stream_encoder *enc); - -void get_audio_clock_info( - enum dc_color_depth color_depth, - uint32_t crtc_pixel_clock_100Hz, - uint32_t actual_pixel_clock_100Hz, - struct audio_clock_info *audio_clock_info); - -void enc1_reset_hdmi_stream_attribute( - struct stream_encoder *enc); - -bool enc1_stream_encoder_dp_get_pixel_format( - struct stream_encoder *enc, - enum dc_pixel_encoding *encoding, - enum dc_color_depth *depth); - -#endif /* __DC_STREAM_ENCODER_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile index 1ca1cbeabbca..b3aeabc4d605 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile @@ -2,7 +2,6 @@ # Copyright © 2019-2024 Advanced Micro Devices, Inc. All rights reserved. DCN20 = dcn20_mpc.o dcn20_opp.o dcn20_mmhubbub.o \ - dcn20_stream_encoder.o dcn20_link_encoder.o \ dcn20_vmid.o dcn20_dwb.o dcn20_dwb_scl.o AMD_DAL_DCN20 = $(addprefix $(AMDDALPATH)/dc/dcn20/,$(DCN20)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c deleted file mode 100644 index 51a57dae1811..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * 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 "reg_helper.h" - -#include "core_types.h" -#include "link_encoder.h" -#include "dcn20_link_encoder.h" -#include "stream_encoder.h" -#include "dc_bios_types.h" - -#include "gpio_service_interface.h" - -#define CTX \ - enc10->base.ctx -#define DC_LOGGER \ - enc10->base.ctx->logger - -#define REG(reg)\ - (enc10->link_regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc10->link_shift->field_name, enc10->link_mask->field_name - -#define IND_REG(index) \ - (enc10->link_regs->index) - -#ifndef MAX -#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) -#endif -#ifndef MIN -#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) -#endif - -static struct mpll_cfg dcn2_mpll_cfg[] = { - // RBR - { - .hdmimode_enable = 1, - .ref_range = 3, - .ref_clk_mpllb_div = 2, - .mpllb_ssc_en = 1, - .mpllb_div5_clk_en = 1, - .mpllb_multiplier = 226, - .mpllb_fracn_en = 1, - .mpllb_fracn_quot = 39321, - .mpllb_fracn_rem = 3, - .mpllb_fracn_den = 5, - .mpllb_ssc_up_spread = 0, - .mpllb_ssc_peak = 38221, - .mpllb_ssc_stepsize = 49314, - .mpllb_div_clk_en = 0, - .mpllb_div_multiplier = 0, - .mpllb_hdmi_div = 0, - .mpllb_tx_clk_div = 2, - .tx_vboost_lvl = 4, - .mpllb_pmix_en = 1, - .mpllb_word_div2_en = 0, - .mpllb_ana_v2i = 2, - .mpllb_ana_freq_vco = 2, - .mpllb_ana_cp_int = 7, - .mpllb_ana_cp_prop = 18, - .hdmi_pixel_clk_div = 0, - }, - // HBR - { - .hdmimode_enable = 1, - .ref_range = 3, - .ref_clk_mpllb_div = 2, - .mpllb_ssc_en = 1, - .mpllb_div5_clk_en = 1, - .mpllb_multiplier = 184, - .mpllb_fracn_en = 0, - .mpllb_fracn_quot = 0, - .mpllb_fracn_rem = 0, - .mpllb_fracn_den = 1, - .mpllb_ssc_up_spread = 0, - .mpllb_ssc_peak = 31850, - .mpllb_ssc_stepsize = 41095, - .mpllb_div_clk_en = 0, - .mpllb_div_multiplier = 0, - .mpllb_hdmi_div = 0, - .mpllb_tx_clk_div = 1, - .tx_vboost_lvl = 4, - .mpllb_pmix_en = 1, - .mpllb_word_div2_en = 0, - .mpllb_ana_v2i = 2, - .mpllb_ana_freq_vco = 3, - .mpllb_ana_cp_int = 7, - .mpllb_ana_cp_prop = 18, - .hdmi_pixel_clk_div = 0, - }, - //HBR2 - { - .hdmimode_enable = 1, - .ref_range = 3, - .ref_clk_mpllb_div = 2, - .mpllb_ssc_en = 1, - .mpllb_div5_clk_en = 1, - .mpllb_multiplier = 184, - .mpllb_fracn_en = 0, - .mpllb_fracn_quot = 0, - .mpllb_fracn_rem = 0, - .mpllb_fracn_den = 1, - .mpllb_ssc_up_spread = 0, - .mpllb_ssc_peak = 31850, - .mpllb_ssc_stepsize = 41095, - .mpllb_div_clk_en = 0, - .mpllb_div_multiplier = 0, - .mpllb_hdmi_div = 0, - .mpllb_tx_clk_div = 0, - .tx_vboost_lvl = 4, - .mpllb_pmix_en = 1, - .mpllb_word_div2_en = 0, - .mpllb_ana_v2i = 2, - .mpllb_ana_freq_vco = 3, - .mpllb_ana_cp_int = 7, - .mpllb_ana_cp_prop = 18, - .hdmi_pixel_clk_div = 0, - }, - //HBR3 - { - .hdmimode_enable = 1, - .ref_range = 3, - .ref_clk_mpllb_div = 2, - .mpllb_ssc_en = 1, - .mpllb_div5_clk_en = 1, - .mpllb_multiplier = 292, - .mpllb_fracn_en = 0, - .mpllb_fracn_quot = 0, - .mpllb_fracn_rem = 0, - .mpllb_fracn_den = 1, - .mpllb_ssc_up_spread = 0, - .mpllb_ssc_peak = 47776, - .mpllb_ssc_stepsize = 61642, - .mpllb_div_clk_en = 0, - .mpllb_div_multiplier = 0, - .mpllb_hdmi_div = 0, - .mpllb_tx_clk_div = 0, - .tx_vboost_lvl = 4, - .mpllb_pmix_en = 1, - .mpllb_word_div2_en = 0, - .mpllb_ana_v2i = 2, - .mpllb_ana_freq_vco = 0, - .mpllb_ana_cp_int = 7, - .mpllb_ana_cp_prop = 18, - .hdmi_pixel_clk_div = 0, - }, -}; - -void enc2_fec_set_enable(struct link_encoder *enc, bool enable) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - DC_LOG_DSC("%s FEC at link encoder inst %d", - enable ? "Enabling" : "Disabling", enc->id.enum_id); - REG_UPDATE(DP_DPHY_CNTL, DPHY_FEC_EN, enable); -} - -void enc2_fec_set_ready(struct link_encoder *enc, bool ready) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - REG_UPDATE(DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, ready); -} - -bool enc2_fec_is_active(struct link_encoder *enc) -{ - uint32_t active = 0; - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - REG_GET(DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, &active); - - return (active != 0); -} - -/* this function reads dsc related register fields to be logged later in dcn10_log_hw_state - * into a dcn_dsc_state struct. - */ -void link_enc2_read_state(struct link_encoder *enc, struct link_enc_state *s) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - REG_GET(DP_DPHY_CNTL, DPHY_FEC_EN, &s->dphy_fec_en); - REG_GET(DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, &s->dphy_fec_ready_shadow); - REG_GET(DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, &s->dphy_fec_active_status); - REG_GET(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, &s->dp_link_training_complete); -} - -static bool update_cfg_data( - struct dcn10_link_encoder *enc10, - const struct dc_link_settings *link_settings, - struct dpcssys_phy_seq_cfg *cfg) -{ - int i; - - cfg->load_sram_fw = false; - - for (i = 0; i < link_settings->lane_count; i++) - cfg->lane_en[i] = true; - - switch (link_settings->link_rate) { - case LINK_RATE_LOW: - cfg->mpll_cfg = dcn2_mpll_cfg[0]; - break; - case LINK_RATE_HIGH: - cfg->mpll_cfg = dcn2_mpll_cfg[1]; - break; - case LINK_RATE_HIGH2: - cfg->mpll_cfg = dcn2_mpll_cfg[2]; - break; - case LINK_RATE_HIGH3: - cfg->mpll_cfg = dcn2_mpll_cfg[3]; - break; - default: - DC_LOG_ERROR("%s: No supported link rate found %X!\n", - __func__, link_settings->link_rate); - return false; - } - - return true; -} - -void dcn20_link_encoder_enable_dp_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - struct dcn20_link_encoder *enc20 = (struct dcn20_link_encoder *) enc10; - struct dpcssys_phy_seq_cfg *cfg = &enc20->phy_seq_cfg; - - if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { - dcn10_link_encoder_enable_dp_output(enc, link_settings, clock_source); - return; - } - - if (!update_cfg_data(enc10, link_settings, cfg)) - return; - - enc1_configure_encoder(enc10, link_settings); - - dcn10_link_encoder_setup(enc, SIGNAL_TYPE_DISPLAY_PORT); - -} - -void dcn20_link_encoder_get_max_link_cap(struct link_encoder *enc, - struct dc_link_settings *link_settings) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t is_in_usb_c_dp4_mode = 0; - - dcn10_link_encoder_get_max_link_cap(enc, link_settings); - - /* in usb c dp2 mode, max lane count is 2 */ - if (enc->funcs->is_in_alt_mode && enc->funcs->is_in_alt_mode(enc)) { - REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &is_in_usb_c_dp4_mode); - if (!is_in_usb_c_dp4_mode) - link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); - } - -} - -bool dcn20_link_encoder_is_in_alt_mode(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t dp_alt_mode_disable = 0; - bool is_usb_c_alt_mode = false; - - if (enc->features.flags.bits.DP_IS_USB_C) { - /* if value == 1 alt mode is disabled, otherwise it is enabled */ - REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable); - is_usb_c_alt_mode = (dp_alt_mode_disable == 0); - } - - return is_usb_c_alt_mode; -} - -#define AUX_REG(reg)\ - (enc10->aux_regs->reg) - -#define AUX_REG_READ(reg_name) \ - dm_read_reg(CTX, AUX_REG(reg_name)) - -#define AUX_REG_WRITE(reg_name, val) \ - dm_write_reg(CTX, AUX_REG(reg_name), val) -void enc2_hw_init(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); -/* - 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 - 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 - 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 - 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 - 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 - 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 - 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 - 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 -*/ - -/* - AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, - AUX_RX_START_WINDOW = 1 [6:4] - AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] - AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 - AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 - AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 - AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 - AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 - AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 - AUX_RX_DETECTION_THRESHOLD [30:28] = 1 -*/ - if (enc->ctx->dc_bios->golden_table.dc_golden_table_ver > 0) { - AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, enc->ctx->dc_bios->golden_table.aux_dphy_rx_control0_val); - - AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, enc->ctx->dc_bios->golden_table.aux_dphy_tx_control_val); - - AUX_REG_WRITE(AUX_DPHY_RX_CONTROL1, enc->ctx->dc_bios->golden_table.aux_dphy_rx_control1_val); - } else { - AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); - - AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); - } - - //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; - // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk - // 27MHz -> 0xd - // 100MHz -> 0x32 - // 48MHz -> 0x18 - - // Set TMDS_CTL0 to 1. This is a legacy setting. - REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); - - dcn10_aux_initialize(enc10); -} - -static const struct link_encoder_funcs dcn20_link_enc_funcs = { - .read_state = link_enc2_read_state, - .validate_output_with_stream = - dcn10_link_encoder_validate_output_with_stream, - .hw_init = enc2_hw_init, - .setup = dcn10_link_encoder_setup, - .enable_tmds_output = dcn10_link_encoder_enable_tmds_output_with_clk_pattern_wa, - .enable_dp_output = dcn20_link_encoder_enable_dp_output, - .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, - .disable_output = dcn10_link_encoder_disable_output, - .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, - .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, - .update_mst_stream_allocation_table = - dcn10_link_encoder_update_mst_stream_allocation_table, - .psr_program_dp_dphy_fast_training = - dcn10_psr_program_dp_dphy_fast_training, - .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, - .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, - .enable_hpd = dcn10_link_encoder_enable_hpd, - .disable_hpd = dcn10_link_encoder_disable_hpd, - .is_dig_enabled = dcn10_is_dig_enabled, - .destroy = dcn10_link_encoder_destroy, - .fec_set_enable = enc2_fec_set_enable, - .fec_set_ready = enc2_fec_set_ready, - .fec_is_active = enc2_fec_is_active, - .get_dig_mode = dcn10_get_dig_mode, - .get_dig_frontend = dcn10_get_dig_frontend, - .is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode, - .get_max_link_cap = dcn20_link_encoder_get_max_link_cap, -}; - -void dcn20_link_encoder_construct( - struct dcn20_link_encoder *enc20, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask) -{ - struct bp_encoder_cap_info bp_cap_info = {0}; - const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; - enum bp_result result = BP_RESULT_OK; - struct dcn10_link_encoder *enc10 = &enc20->enc10; - - enc10->base.funcs = &dcn20_link_enc_funcs; - enc10->base.ctx = init_data->ctx; - enc10->base.id = init_data->encoder; - - enc10->base.hpd_source = init_data->hpd_source; - enc10->base.connector = init_data->connector; - - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - - enc10->base.features = *enc_features; - - enc10->base.transmitter = init_data->transmitter; - - /* set the flag to indicate whether driver poll the I2C data pin - * while doing the DP sink detect - */ - -/* if (dal_adapter_service_is_feature_supported(as, - FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) - enc10->base.features.flags.bits. - DP_SINK_DETECT_POLL_DATA_PIN = true;*/ - - enc10->base.output_signals = - SIGNAL_TYPE_DVI_SINGLE_LINK | - SIGNAL_TYPE_DVI_DUAL_LINK | - SIGNAL_TYPE_LVDS | - SIGNAL_TYPE_DISPLAY_PORT | - SIGNAL_TYPE_DISPLAY_PORT_MST | - SIGNAL_TYPE_EDP | - SIGNAL_TYPE_HDMI_TYPE_A; - - /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. - * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. - * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer - * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. - * Prefer DIG assignment is decided by board design. - * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design - * and VBIOS will filter out 7 UNIPHY for DCE 8.0. - * By this, adding DIGG should not hurt DCE 8.0. - * This will let DCE 8.1 share DCE 8.0 as much as possible - */ - - enc10->link_regs = link_regs; - enc10->aux_regs = aux_regs; - enc10->hpd_regs = hpd_regs; - enc10->link_shift = link_shift; - enc10->link_mask = link_mask; - - switch (enc10->base.transmitter) { - case TRANSMITTER_UNIPHY_A: - enc10->base.preferred_engine = ENGINE_ID_DIGA; - break; - case TRANSMITTER_UNIPHY_B: - enc10->base.preferred_engine = ENGINE_ID_DIGB; - break; - case TRANSMITTER_UNIPHY_C: - enc10->base.preferred_engine = ENGINE_ID_DIGC; - break; - case TRANSMITTER_UNIPHY_D: - enc10->base.preferred_engine = ENGINE_ID_DIGD; - break; - case TRANSMITTER_UNIPHY_E: - enc10->base.preferred_engine = ENGINE_ID_DIGE; - break; - case TRANSMITTER_UNIPHY_F: - enc10->base.preferred_engine = ENGINE_ID_DIGF; - break; - case TRANSMITTER_UNIPHY_G: - enc10->base.preferred_engine = ENGINE_ID_DIGG; - break; - default: - ASSERT_CRITICAL(false); - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - } - - /* default to one to mirror Windows behavior */ - enc10->base.features.flags.bits.HDMI_6GB_EN = 1; - - result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, - enc10->base.id, &bp_cap_info); - - /* Override features with DCE-specific values */ - if (result == BP_RESULT_OK) { - enc10->base.features.flags.bits.IS_HBR2_CAPABLE = - bp_cap_info.DP_HBR2_EN; - enc10->base.features.flags.bits.IS_HBR3_CAPABLE = - bp_cap_info.DP_HBR3_EN; - enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; - enc10->base.features.flags.bits.DP_IS_USB_C = - bp_cap_info.DP_IS_USB_C; - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, - result); - } - if (enc10->base.ctx->dc->debug.hdmi20_disable) { - enc10->base.features.flags.bits.HDMI_6GB_EN = 0; - } -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h deleted file mode 100644 index 762c579fcb44..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h +++ /dev/null @@ -1,366 +0,0 @@ -/* - * 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 - * - */ - -#ifndef __DC_LINK_ENCODER__DCN20_H__ -#define __DC_LINK_ENCODER__DCN20_H__ - -#include "dcn10/dcn10_link_encoder.h" - -#define DCN2_AUX_REG_LIST(id)\ - AUX_REG_LIST(id), \ - SRI(AUX_DPHY_TX_CONTROL, DP_AUX, id) - -#define UNIPHY_MASK_SH_LIST(mask_sh)\ - LE_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, mask_sh),\ - LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_LINK_ENABLE, mask_sh),\ - LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL0_XBAR_SOURCE, mask_sh),\ - LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL1_XBAR_SOURCE, mask_sh),\ - LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL2_XBAR_SOURCE, mask_sh),\ - LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL3_XBAR_SOURCE, mask_sh) - -#define DPCS_MASK_SH_LIST(mask_sh)\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX0_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX1_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX2_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX3_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_MPLLB_MULTIPLIER, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_WIDTH, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_RATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_WIDTH, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_RATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_PSTATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_PSTATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_MPLL_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_MPLL_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_QUOT, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_DEN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL8, RDPCS_PHY_DP_MPLLB_SSC_PEAK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_UP_SPREAD, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_STEPSIZE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL10, RDPCS_PHY_DP_MPLLB_FRACN_REM, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_REF_CLK_MPLLB_DIV, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_HDMI_MPLLB_HDMI_DIV, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_SSC_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_DIV5_CLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_TX_CLK_DIV, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_WORD_DIV2_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_STATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_CLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_MULTIPLIER, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_FRACN_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_PMIX_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE0_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE1_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE2_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE3_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_EXT_REFCLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_BYPASS, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_CLOCK_ON, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_CLOCK_ON, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_GATE_DIS, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_CR_MUX_SEL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_REF_RANGE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_BYPASS, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_EXT_LD_DONE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_HDMIMODE_ENABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_INIT_DONE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL2, RDPCS_PHY_DP4_POR, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PLL_UPDATE_DATA, RDPCS_PLL_UPDATE_DATA, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_REG_FIFO_ERROR_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_TX_FIFO_ERROR_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_DISABLE_TOGGLE_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_4LANE_TOGGLE_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCS_TX_CR_ADDR, RDPCS_TX_CR_ADDR, mask_sh),\ - LE_SF(RDPCSTX0_RDPCS_TX_CR_DATA, RDPCS_TX_CR_DATA, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_V2I, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_POST, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_FREQ_VCO, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_INT, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_PROP, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_POST, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_POST, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_FINETUNE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_RANGE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_POST, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CLOCK_CNTL, DPCS_SYMCLK_CLOCK_ON, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CLOCK_CNTL, DPCS_SYMCLK_GATE_DIS, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CLOCK_CNTL, DPCS_SYMCLK_EN, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_SWAP, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_FIFO_EN, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_DEBUG_CONFIG, DPCS_DBG_CBUS_DIS, mask_sh) - -#define DPCS_DCN2_MASK_SH_LIST(mask_sh)\ - DPCS_MASK_SH_LIST(mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_RX_LD_VAL, RDPCS_PHY_RX_REF_LD_VAL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_RX_LD_VAL, RDPCS_PHY_RX_VCO_LD_VAL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX0_PSTATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX1_PSTATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX0_MPLL_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX1_MPLL_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_REF_CLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX2_WIDTH, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX2_RATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX3_WIDTH, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX3_RATE, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYA_SOFT_RESET, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYB_SOFT_RESET, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYC_SOFT_RESET, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYD_SOFT_RESET, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYE_SOFT_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) - -#define LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh)\ - LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\ - LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE0EN, mask_sh),\ - LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE1EN, mask_sh),\ - LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE2EN, mask_sh),\ - LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE3EN, mask_sh),\ - LE_SF(DIG0_DIG_LANE_ENABLE, DIG_CLK_EN, mask_sh),\ - LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ - UNIPHY_MASK_SH_LIST(mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh) - -#define UNIPHY_DCN2_REG_LIST(id) \ - SRI(CLOCK_ENABLE, SYMCLK, id), \ - SRI(CHANNEL_XBAR_CNTL, UNIPHY, id) - -#define DPCS_DCN2_CMN_REG_LIST(id) \ - SRI(DIG_LANE_ENABLE, DIG, id), \ - SRI(TMDS_CTL_BITS, DIG, id), \ - SRI(RDPCSTX_PHY_CNTL3, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL6, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL10, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL11, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL12, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL13, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL14, RDPCSTX, id), \ - SRI(RDPCSTX_CNTL, RDPCSTX, id), \ - SRI(RDPCSTX_CLOCK_CNTL, RDPCSTX, id), \ - SRI(RDPCSTX_INTERRUPT_CONTROL, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL2, RDPCSTX, id), \ - SRI(RDPCSTX_PLL_UPDATE_DATA, RDPCSTX, id), \ - SRI(RDPCS_TX_CR_ADDR, RDPCSTX, id), \ - SRI(RDPCS_TX_CR_DATA, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE0, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ - SRI(DPCSTX_TX_CLOCK_CNTL, DPCSTX, id), \ - SRI(DPCSTX_TX_CNTL, DPCSTX, id), \ - SRI(DPCSTX_DEBUG_CONFIG, DPCSTX, id), \ - SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ - SR(RDPCSTX0_RDPCSTX_SCRATCH) - - -#define DPCS_DCN2_REG_LIST(id) \ - DPCS_DCN2_CMN_REG_LIST(id), \ - SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ - SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) - -#define LE_DCN2_REG_LIST(id) \ - LE_DCN10_REG_LIST(id), \ - SR(DCIO_SOFT_RESET) - -struct mpll_cfg { - uint32_t mpllb_ana_v2i; - uint32_t mpllb_ana_freq_vco; - uint32_t mpllb_ana_cp_int; - uint32_t mpllb_ana_cp_prop; - uint32_t mpllb_multiplier; - uint32_t ref_clk_mpllb_div; - bool mpllb_word_div2_en; - bool mpllb_ssc_en; - bool mpllb_div5_clk_en; - bool mpllb_div_clk_en; - bool mpllb_fracn_en; - bool mpllb_pmix_en; - uint32_t mpllb_div_multiplier; - uint32_t mpllb_tx_clk_div; - uint32_t mpllb_fracn_quot; - uint32_t mpllb_fracn_den; - uint32_t mpllb_ssc_peak; - uint32_t mpllb_ssc_stepsize; - uint32_t mpllb_ssc_up_spread; - uint32_t mpllb_fracn_rem; - uint32_t mpllb_hdmi_div; - // TODO: May not mpll params, need to figure out. - uint32_t tx_vboost_lvl; - uint32_t hdmi_pixel_clk_div; - uint32_t ref_range; - uint32_t ref_clk; - bool hdmimode_enable; - bool sup_pre_hp; - bool dp_tx0_vergdrv_byp; - bool dp_tx1_vergdrv_byp; - bool dp_tx2_vergdrv_byp; - bool dp_tx3_vergdrv_byp; - uint32_t tx_peaking_lvl; - uint32_t ctr_reqs_pll; - -}; - -struct dpcssys_phy_seq_cfg { - bool program_fuse; - bool bypass_sram; - bool lane_en[4]; - bool use_calibration_setting; - struct mpll_cfg mpll_cfg; - bool load_sram_fw; -#if 0 - - bool hdmimode_enable; - bool silver2; - bool ext_refclk_en; - uint32_t dp_tx0_term_ctrl; - uint32_t dp_tx1_term_ctrl; - uint32_t dp_tx2_term_ctrl; - uint32_t dp_tx3_term_ctrl; - uint32_t fw_data[0x1000]; - uint32_t dp_tx0_width; - uint32_t dp_tx1_width; - uint32_t dp_tx2_width; - uint32_t dp_tx3_width; - uint32_t dp_tx0_rate; - uint32_t dp_tx1_rate; - uint32_t dp_tx2_rate; - uint32_t dp_tx3_rate; - uint32_t dp_tx0_eq_main; - uint32_t dp_tx0_eq_pre; - uint32_t dp_tx0_eq_post; - uint32_t dp_tx1_eq_main; - uint32_t dp_tx1_eq_pre; - uint32_t dp_tx1_eq_post; - uint32_t dp_tx2_eq_main; - uint32_t dp_tx2_eq_pre; - uint32_t dp_tx2_eq_post; - uint32_t dp_tx3_eq_main; - uint32_t dp_tx3_eq_pre; - uint32_t dp_tx3_eq_post; - bool data_swap_en; - bool data_order_invert_en; - uint32_t ldpcs_fifo_start_delay; - uint32_t rdpcs_fifo_start_delay; - bool rdpcs_reg_fifo_error_mask; - bool rdpcs_tx_fifo_error_mask; - bool rdpcs_dpalt_disable_mask; - bool rdpcs_dpalt_4lane_mask; -#endif -}; - -struct dcn20_link_encoder { - struct dcn10_link_encoder enc10; - struct dpcssys_phy_seq_cfg phy_seq_cfg; -}; - -void enc2_fec_set_enable(struct link_encoder *enc, bool enable); -void enc2_fec_set_ready(struct link_encoder *enc, bool ready); -bool enc2_fec_is_active(struct link_encoder *enc); -void enc2_hw_init(struct link_encoder *enc); - -void link_enc2_read_state(struct link_encoder *enc, struct link_enc_state *s); - -void dcn20_link_encoder_enable_dp_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source); - -bool dcn20_link_encoder_is_in_alt_mode(struct link_encoder *enc); -void dcn20_link_encoder_get_max_link_cap(struct link_encoder *enc, - struct dc_link_settings *link_settings); - -void dcn20_link_encoder_construct( - struct dcn20_link_encoder *enc20, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask); - -#endif /* __DC_LINK_ENCODER__DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c deleted file mode 100644 index 0b47aeb60e79..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +++ /dev/null @@ -1,661 +0,0 @@ -/* - * 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 - -#include "dc_bios_types.h" -#include "dcn20_stream_encoder.h" -#include "reg_helper.h" -#include "hw_shared.h" -#include "link.h" -#include "dpcd_defs.h" - -#define DC_LOGGER \ - enc1->base.ctx->logger - -#define REG(reg)\ - (enc1->regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc1->se_shift->field_name, enc1->se_mask->field_name - - -#define CTX \ - enc1->base.ctx - - -static void enc2_update_hdmi_info_packet( - struct dcn10_stream_encoder *enc1, - uint32_t packet_index, - const struct dc_info_packet *info_packet) -{ - uint32_t cont, send, line; - - if (info_packet->valid) { - enc1_update_generic_info_packet( - enc1, - packet_index, - info_packet); - - /* enable transmission of packet(s) - - * packet transmission begins on the next frame */ - cont = 1; - /* send packet(s) every frame */ - send = 1; - /* select line number to send packets on */ - line = 2; - } else { - cont = 0; - send = 0; - line = 0; - } - - /* DP_SEC_GSP[x]_LINE_REFERENCE - keep default value REFER_TO_DP_SOF */ - - /* choose which generic packet control to use */ - switch (packet_index) { - case 0: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC0_CONT, cont, - HDMI_GENERIC0_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, - HDMI_GENERIC0_LINE, line); - break; - case 1: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC1_CONT, cont, - HDMI_GENERIC1_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, - HDMI_GENERIC1_LINE, line); - break; - case 2: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC2_CONT, cont, - HDMI_GENERIC2_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, - HDMI_GENERIC2_LINE, line); - break; - case 3: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC3_CONT, cont, - HDMI_GENERIC3_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, - HDMI_GENERIC3_LINE, line); - break; - case 4: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC4_CONT, cont, - HDMI_GENERIC4_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, - HDMI_GENERIC4_LINE, line); - break; - case 5: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC5_CONT, cont, - HDMI_GENERIC5_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, - HDMI_GENERIC5_LINE, line); - break; - case 6: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC6_CONT, cont, - HDMI_GENERIC6_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, - HDMI_GENERIC6_LINE, line); - break; - case 7: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC7_CONT, cont, - HDMI_GENERIC7_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, - HDMI_GENERIC7_LINE, line); - break; - default: - /* invalid HW packet index */ - DC_LOG_WARNING( - "Invalid HW packet index: %s()\n", - __func__); - return; - } -} - -static void enc2_stream_encoder_update_hdmi_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* for bring up, disable dp double TODO */ - REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); - - /*Always add mandatory packets first followed by optional ones*/ - enc2_update_hdmi_info_packet(enc1, 0, &info_frame->avi); - enc2_update_hdmi_info_packet(enc1, 1, &info_frame->hfvsif); - enc2_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); - enc2_update_hdmi_info_packet(enc1, 3, &info_frame->vendor); - enc2_update_hdmi_info_packet(enc1, 4, &info_frame->spd); - enc2_update_hdmi_info_packet(enc1, 5, &info_frame->hdrsmd); - enc2_update_hdmi_info_packet(enc1, 6, &info_frame->vtem); -} - -static void enc2_stream_encoder_stop_hdmi_info_packets( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* stop generic packets 0,1 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC0_CONT, 0, - HDMI_GENERIC0_SEND, 0, - HDMI_GENERIC1_CONT, 0, - HDMI_GENERIC1_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL1, 0, - HDMI_GENERIC0_LINE, 0, - HDMI_GENERIC1_LINE, 0); - - /* stop generic packets 2,3 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC2_CONT, 0, - HDMI_GENERIC2_SEND, 0, - HDMI_GENERIC3_CONT, 0, - HDMI_GENERIC3_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL2, 0, - HDMI_GENERIC2_LINE, 0, - HDMI_GENERIC3_LINE, 0); - - /* stop generic packets 4,5 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC4_CONT, 0, - HDMI_GENERIC4_SEND, 0, - HDMI_GENERIC5_CONT, 0, - HDMI_GENERIC5_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL3, 0, - HDMI_GENERIC4_LINE, 0, - HDMI_GENERIC5_LINE, 0); - - /* stop generic packets 6,7 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC6_CONT, 0, - HDMI_GENERIC6_SEND, 0, - HDMI_GENERIC7_CONT, 0, - HDMI_GENERIC7_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL4, 0, - HDMI_GENERIC6_LINE, 0, - HDMI_GENERIC7_LINE, 0); -} - - -/* Update GSP7 SDP 128 byte long */ -static void enc2_update_gsp7_128_info_packet( - struct dcn10_stream_encoder *enc1, - const struct dc_info_packet_128 *info_packet, - bool immediate_update) -{ - uint32_t i; - - /* TODOFPGA Figure out a proper number for max_retries polling for lock - * use 50 for now. - */ - uint32_t max_retries = 50; - const uint32_t *content = (const uint32_t *) &info_packet->sb[0]; - - ASSERT(info_packet->hb1 == DC_DP_INFOFRAME_TYPE_PPS); - - /* Configure for PPS packet size (128 bytes) */ - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 1); - - /* We need turn on clock before programming AFMT block*/ - REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); - - /* Poll dig_update_lock is not locked -> asic internal signal - * assumes otg master lock will unlock it - */ - /*REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, 0, 10, max_retries);*/ - - /* Wait for HW/SW GSP memory access conflict to go away */ - REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, - 0, 10, max_retries); - - /* Clear HW/SW memory access conflict flag */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); - - /* write generic packet header */ - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, 7); - REG_SET_4(AFMT_GENERIC_HDR, 0, - AFMT_GENERIC_HB0, info_packet->hb0, - AFMT_GENERIC_HB1, info_packet->hb1, - AFMT_GENERIC_HB2, info_packet->hb2, - AFMT_GENERIC_HB3, info_packet->hb3); - - /* Write generic packet content 128 bytes long. Four sets are used (indexes 7 - * through 10) to fit 128 bytes. - */ - for (i = 0; i < 4; i++) { - uint32_t packet_index = 7 + i; - REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, packet_index); - - REG_WRITE(AFMT_GENERIC_0, *content++); - REG_WRITE(AFMT_GENERIC_1, *content++); - REG_WRITE(AFMT_GENERIC_2, *content++); - REG_WRITE(AFMT_GENERIC_3, *content++); - REG_WRITE(AFMT_GENERIC_4, *content++); - REG_WRITE(AFMT_GENERIC_5, *content++); - REG_WRITE(AFMT_GENERIC_6, *content++); - REG_WRITE(AFMT_GENERIC_7, *content++); - } - - REG_UPDATE_2(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC7_FRAME_UPDATE, !immediate_update, - AFMT_GENERIC7_IMMEDIATE_UPDATE, immediate_update); -} - -/* Set DSC-related configuration. - * dsc_mode: 0 disables DSC, other values enable DSC in specified format - * sc_bytes_per_pixel: Bytes per pixel in u3.28 format - * dsc_slice_width: Slice width in pixels - */ -static void enc2_dp_set_dsc_config(struct stream_encoder *enc, - enum optc_dsc_mode dsc_mode, - uint32_t dsc_bytes_per_pixel, - uint32_t dsc_slice_width) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE_2(DP_DSC_CNTL, - DP_DSC_MODE, dsc_mode, - DP_DSC_SLICE_WIDTH, dsc_slice_width); - - REG_SET(DP_DSC_BYTES_PER_PIXEL, 0, - DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); -} - - -static void enc2_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, - bool enable, - uint8_t *dsc_packed_pps, - bool immediate_update) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (enable) { - struct dc_info_packet_128 pps_sdp; - - ASSERT(dsc_packed_pps); - - /* Load PPS into infoframe (SDP) registers */ - pps_sdp.valid = true; - pps_sdp.hb0 = 0; - pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; - pps_sdp.hb2 = 127; - pps_sdp.hb3 = 0; - memcpy(&pps_sdp.sb[0], dsc_packed_pps, sizeof(pps_sdp.sb)); - enc2_update_gsp7_128_info_packet(enc1, &pps_sdp, immediate_update); - - /* Enable Generic Stream Packet 7 (GSP) transmission */ - //REG_UPDATE(DP_SEC_CNTL, - // DP_SEC_GSP7_ENABLE, 1); - - /* SW should make sure VBID[6] update line number is bigger - * than PPS transmit line number - */ - REG_UPDATE(DP_SEC_CNTL6, - DP_SEC_GSP7_LINE_NUM, 2); - REG_UPDATE_2(DP_MSA_VBID_MISC, - DP_VBID6_LINE_REFERENCE, 0, - DP_VBID6_LINE_NUM, 3); - - /* Send PPS data at the line number specified above. - * DP spec requires PPS to be sent only when it changes, however since - * decoder has to be able to handle its change on every frame, we're - * sending it always (i.e. on every frame) to reduce the chance it'd be - * missed by decoder. If it turns out required to send PPS only when it - * changes, we can use DP_SEC_GSP7_SEND register. - */ - REG_UPDATE_2(DP_SEC_CNTL, - DP_SEC_GSP7_ENABLE, 1, - DP_SEC_STREAM_ENABLE, 1); - } else { - /* Disable Generic Stream Packet 7 (GSP) transmission */ - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, 0); - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 0); - } -} - - -/* this function read dsc related register fields to be logged later in dcn10_log_hw_state - * into a dcn_dsc_state struct. - */ -static void enc2_read_state(struct stream_encoder *enc, struct enc_state *s) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - //if dsc is enabled, continue to read - REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode); - if (s->dsc_mode) { - REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width); - REG_GET(DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, &s->sec_gsp_pps_line_num); - - REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference); - REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num); - - REG_GET(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, &s->sec_gsp_pps_enable); - REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable); - } -} - -/* Set Dynamic Metadata-configuration. - * enable_dme: TRUE: enables Dynamic Metadata Enfine, FALSE: disables DME - * hubp_requestor_id: HUBP physical instance that is the source of dynamic metadata - * only needs to be set when enable_dme is TRUE - * dmdata_mode: dynamic metadata packet type: DP, HDMI, or Dolby Vision - * - * Ensure the OTG master update lock is set when changing DME configuration. - */ -void enc2_set_dynamic_metadata(struct stream_encoder *enc, - bool enable_dme, - uint32_t hubp_requestor_id, - enum dynamic_metadata_mode dmdata_mode) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (enable_dme) { - REG_UPDATE_2(DME_CONTROL, - METADATA_HUBP_REQUESTOR_ID, hubp_requestor_id, - METADATA_STREAM_TYPE, (dmdata_mode == dmdata_dolby_vision) ? 1 : 0); - - /* Use default line reference DP_SOF for bringup. - * Should use OTG_SOF for DRR cases - */ - if (dmdata_mode == dmdata_dp) - REG_UPDATE_3(DP_SEC_METADATA_TRANSMISSION, - DP_SEC_METADATA_PACKET_ENABLE, 1, - DP_SEC_METADATA_PACKET_LINE_REFERENCE, 0, - DP_SEC_METADATA_PACKET_LINE, 20); - else { - REG_UPDATE_3(HDMI_METADATA_PACKET_CONTROL, - HDMI_METADATA_PACKET_ENABLE, 1, - HDMI_METADATA_PACKET_LINE_REFERENCE, 0, - HDMI_METADATA_PACKET_LINE, 2); - - if (dmdata_mode == dmdata_dolby_vision) - REG_UPDATE(DIG_FE_CNTL, - DOLBY_VISION_EN, 1); - } - - REG_UPDATE(DME_CONTROL, - METADATA_ENGINE_EN, 1); - } else { - REG_UPDATE(DME_CONTROL, - METADATA_ENGINE_EN, 0); - - if (dmdata_mode == dmdata_dp) - REG_UPDATE(DP_SEC_METADATA_TRANSMISSION, - DP_SEC_METADATA_PACKET_ENABLE, 0); - else { - REG_UPDATE(HDMI_METADATA_PACKET_CONTROL, - HDMI_METADATA_PACKET_ENABLE, 0); - REG_UPDATE(DIG_FE_CNTL, - DOLBY_VISION_EN, 0); - } - } -} - -static void enc2_stream_encoder_update_dp_info_packets_sdp_line_num( - struct stream_encoder *enc, - struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (info_frame->adaptive_sync.valid == true && - info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { - //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF - REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1); - - REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, - info_frame->sdp_line_num.adaptive_sync_line_num); - } -} - -static void enc2_stream_encoder_update_dp_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t dmdata_packet_enabled = 0; - - enc1_stream_encoder_update_dp_info_packets(enc, info_frame); - - /* check if dynamic metadata packet transmission is enabled */ - REG_GET(DP_SEC_METADATA_TRANSMISSION, - DP_SEC_METADATA_PACKET_ENABLE, &dmdata_packet_enabled); - - if (dmdata_packet_enabled) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); -} - -static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing) -{ - bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; - - two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 - && !timing->dsc_cfg.ycbcr422_simple); - return two_pix; -} - -void enc2_stream_encoder_dp_unblank( - struct dc_link *link, - struct stream_encoder *enc, - const struct encoder_unblank_param *param) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { - uint32_t n_vid = 0x8000; - uint32_t m_vid; - uint32_t n_multiply = 0; - uint64_t m_vid_l = n_vid; - - /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ - if (is_two_pixels_per_containter(¶m->timing) || param->opp_cnt > 1) { - /*this logic should be the same in get_pixel_clock_parameters() */ - n_multiply = 1; - } - /* M / N = Fstream / Flink - * m_vid / n_vid = pixel rate / link rate - */ - - m_vid_l *= param->timing.pix_clk_100hz / 10; - m_vid_l = div_u64(m_vid_l, - param->link_settings.link_rate - * LINK_RATE_REF_FREQ_IN_KHZ); - - m_vid = (uint32_t) m_vid_l; - - /* enable auto measurement */ - - REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); - - /* auto measurement need 1 full 0x8000 symbol cycle to kick in, - * therefore program initial value for Mvid and Nvid - */ - - REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); - - REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); - - REG_UPDATE_2(DP_VID_TIMING, - DP_VID_M_N_GEN_EN, 1, - DP_VID_N_MUL, n_multiply); - } - - /* make sure stream is disabled before resetting steer fifo */ - REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false); - REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000); - - /* set DIG_START to 0x1 to reset FIFO */ - REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); - udelay(1); - - /* write 0 to take the FIFO out of reset */ - - REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); - - /* switch DP encoder to CRTC data, but reset it the fifo first. It may happen - * that it overflows during mode transition, and sometimes doesn't recover. - */ - REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1); - udelay(10); - - REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); - - /* wait 100us for DIG/DP logic to prime - * (i.e. a few video lines) - */ - udelay(100); - - /* the hardware would start sending video at the start of the next DP - * frame (i.e. rising edge of the vblank). - * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this - * register has no effect on enable transition! HW always guarantees - * VID_STREAM enable at start of next frame, and this is not - * programmable - */ - - REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); - - link->dc->link_srv->dp_trace_source_sequence(link, - DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); -} - -static void enc2_dp_set_odm_combine( - struct stream_encoder *enc, - bool odm_combine) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, odm_combine); -} - -void enc2_stream_encoder_dp_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - enum dc_color_space output_color_space, - bool use_vsc_sdp_for_colorimetry, - uint32_t enable_sdp_splitting) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - enc1_stream_encoder_dp_set_stream_attribute(enc, - crtc_timing, - output_color_space, - use_vsc_sdp_for_colorimetry, - enable_sdp_splitting); - - REG_UPDATE(DP_SEC_FRAMING4, - DP_SST_SDP_SPLITTING, enable_sdp_splitting); -} - -uint32_t enc2_get_fifo_cal_average_level( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t fifo_level; - - REG_GET(DIG_FIFO_STATUS, - DIG_FIFO_CAL_AVERAGE_LEVEL, &fifo_level); - return fifo_level; -} - -static const struct stream_encoder_funcs dcn20_str_enc_funcs = { - .dp_set_odm_combine = - enc2_dp_set_odm_combine, - .dp_set_stream_attribute = - enc2_stream_encoder_dp_set_stream_attribute, - .hdmi_set_stream_attribute = - enc1_stream_encoder_hdmi_set_stream_attribute, - .dvi_set_stream_attribute = - enc1_stream_encoder_dvi_set_stream_attribute, - .set_throttled_vcp_size = - enc1_stream_encoder_set_throttled_vcp_size, - .update_hdmi_info_packets = - enc2_stream_encoder_update_hdmi_info_packets, - .stop_hdmi_info_packets = - enc2_stream_encoder_stop_hdmi_info_packets, - .update_dp_info_packets_sdp_line_num = - enc2_stream_encoder_update_dp_info_packets_sdp_line_num, - .update_dp_info_packets = - enc2_stream_encoder_update_dp_info_packets, - .send_immediate_sdp_message = - enc1_stream_encoder_send_immediate_sdp_message, - .stop_dp_info_packets = - enc1_stream_encoder_stop_dp_info_packets, - .dp_blank = - enc1_stream_encoder_dp_blank, - .dp_unblank = - enc2_stream_encoder_dp_unblank, - .audio_mute_control = enc1_se_audio_mute_control, - - .dp_audio_setup = enc1_se_dp_audio_setup, - .dp_audio_enable = enc1_se_dp_audio_enable, - .dp_audio_disable = enc1_se_dp_audio_disable, - - .hdmi_audio_setup = enc1_se_hdmi_audio_setup, - .hdmi_audio_disable = enc1_se_hdmi_audio_disable, - .setup_stereo_sync = enc1_setup_stereo_sync, - .set_avmute = enc1_stream_encoder_set_avmute, - .dig_connect_to_otg = enc1_dig_connect_to_otg, - .dig_source_otg = enc1_dig_source_otg, - - .dp_get_pixel_format = - enc1_stream_encoder_dp_get_pixel_format, - - .enc_read_state = enc2_read_state, - .dp_set_dsc_config = enc2_dp_set_dsc_config, - .dp_set_dsc_pps_info_packet = enc2_dp_set_dsc_pps_info_packet, - .set_dynamic_metadata = enc2_set_dynamic_metadata, - .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, - .get_fifo_cal_average_level = enc2_get_fifo_cal_average_level, -}; - -void dcn20_stream_encoder_construct( - struct dcn10_stream_encoder *enc1, - struct dc_context *ctx, - struct dc_bios *bp, - enum engine_id eng_id, - const struct dcn10_stream_enc_registers *regs, - const struct dcn10_stream_encoder_shift *se_shift, - const struct dcn10_stream_encoder_mask *se_mask) -{ - enc1->base.funcs = &dcn20_str_enc_funcs; - enc1->base.ctx = ctx; - enc1->base.id = eng_id; - enc1->base.bp = bp; - enc1->regs = regs; - enc1->se_shift = se_shift; - enc1->se_mask = se_mask; - enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h deleted file mode 100644 index baa1e539f341..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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 - * - */ - -#ifndef __DC_STREAM_ENCODER_DCN20_H__ -#define __DC_STREAM_ENCODER_DCN20_H__ - -#include "stream_encoder.h" -#include "dcn10/dcn10_stream_encoder.h" - - -#define SE_DCN2_REG_LIST(id)\ - SE_COMMON_DCN_REG_LIST(id),\ - SRI(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ - SRI(DP_DSC_CNTL, DP, id), \ - SRI(DP_DSC_BYTES_PER_PIXEL, DP, id), \ - SRI(DME_CONTROL, DIG, id),\ - SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ - SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ - SRI(DP_SEC_FRAMING4, DP, id) - -#define SE_COMMON_MASK_SH_LIST_DCN20(mask_sh)\ - SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\ - SE_SF(DP0_DP_DSC_CNTL, DP_DSC_MODE, mask_sh),\ - SE_SF(DP0_DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, mask_sh),\ - SE_SF(DP0_DP_DSC_BYTES_PER_PIXEL, DP_DSC_BYTES_PER_PIXEL, mask_sh),\ - SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\ - SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\ - SE_SF(DIG0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\ - SE_SF(DIG0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\ - SE_SF(DIG0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\ - SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ - SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\ - SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ - SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DOLBY_VISION_EN, mask_sh),\ - SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh) - -void dcn20_stream_encoder_construct( - struct dcn10_stream_encoder *enc1, - struct dc_context *ctx, - struct dc_bios *bp, - enum engine_id eng_id, - const struct dcn10_stream_enc_registers *regs, - const struct dcn10_stream_encoder_shift *se_shift, - const struct dcn10_stream_encoder_mask *se_mask); - -void enc2_stream_encoder_dp_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - enum dc_color_space output_color_space, - bool use_vsc_sdp_for_colorimetry, - uint32_t enable_sdp_splitting); - -void enc2_stream_encoder_dp_unblank( - struct dc_link *link, - struct stream_encoder *enc, - const struct encoder_unblank_param *param); - -void enc2_set_dynamic_metadata(struct stream_encoder *enc, - bool enable_dme, - uint32_t hubp_requestor_id, - enum dynamic_metadata_mode dmdata_mode); - -uint32_t enc2_get_fifo_cal_average_level( - struct stream_encoder *enc); - -#endif /* __DC_STREAM_ENCODER_DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile index 2131d228f6fb..4c43af867d86 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile @@ -25,12 +25,10 @@ DCN30 := dcn30_mpc.o dcn30_vpg.o \ dcn30_afmt.o \ - dcn30_dio_stream_encoder.o \ dcn30_dwb.o \ dcn30_dwb_cm.o \ dcn30_cm_common.o \ dcn30_mmhubbub.o \ - dcn30_dio_link_encoder.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c deleted file mode 100644 index b8e31b5ea114..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright 2020 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 "reg_helper.h" - -#include "core_types.h" -#include "link_encoder.h" -#include "dcn30_dio_link_encoder.h" -#include "stream_encoder.h" -#include "dc_bios_types.h" -#include "gpio_service_interface.h" - -#define CTX \ - enc10->base.ctx -#define DC_LOGGER \ - enc10->base.ctx->logger - -#define REG(reg)\ - (enc10->link_regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc10->link_shift->field_name, enc10->link_mask->field_name - -#define IND_REG(index) \ - (enc10->link_regs->index) - - -bool dcn30_link_encoder_validate_output_with_stream( - struct link_encoder *enc, - const struct dc_stream_state *stream) -{ - return dcn10_link_encoder_validate_output_with_stream(enc, stream); -} - -static const struct link_encoder_funcs dcn30_link_enc_funcs = { - .read_state = link_enc2_read_state, - .validate_output_with_stream = - dcn30_link_encoder_validate_output_with_stream, - .hw_init = enc3_hw_init, - .setup = dcn10_link_encoder_setup, - .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, - .enable_dp_output = dcn20_link_encoder_enable_dp_output, - .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, - .disable_output = dcn10_link_encoder_disable_output, - .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, - .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, - .update_mst_stream_allocation_table = - dcn10_link_encoder_update_mst_stream_allocation_table, - .psr_program_dp_dphy_fast_training = - dcn10_psr_program_dp_dphy_fast_training, - .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, - .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, - .enable_hpd = dcn10_link_encoder_enable_hpd, - .disable_hpd = dcn10_link_encoder_disable_hpd, - .is_dig_enabled = dcn10_is_dig_enabled, - .destroy = dcn10_link_encoder_destroy, - .fec_set_enable = enc2_fec_set_enable, - .fec_set_ready = enc2_fec_set_ready, - .fec_is_active = enc2_fec_is_active, - .get_dig_frontend = dcn10_get_dig_frontend, - .get_dig_mode = dcn10_get_dig_mode, - .is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode, - .get_max_link_cap = dcn20_link_encoder_get_max_link_cap, -}; - -void dcn30_link_encoder_construct( - struct dcn20_link_encoder *enc20, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask) -{ - struct bp_encoder_cap_info bp_cap_info = {0}; - const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; - enum bp_result result = BP_RESULT_OK; - struct dcn10_link_encoder *enc10 = &enc20->enc10; - - enc10->base.funcs = &dcn30_link_enc_funcs; - enc10->base.ctx = init_data->ctx; - enc10->base.id = init_data->encoder; - - enc10->base.hpd_source = init_data->hpd_source; - enc10->base.connector = init_data->connector; - - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - - enc10->base.features = *enc_features; - - enc10->base.transmitter = init_data->transmitter; - - /* set the flag to indicate whether driver poll the I2C data pin - * while doing the DP sink detect - */ - -/* if (dal_adapter_service_is_feature_supported(as, - FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) - enc10->base.features.flags.bits. - DP_SINK_DETECT_POLL_DATA_PIN = true;*/ - - enc10->base.output_signals = - SIGNAL_TYPE_DVI_SINGLE_LINK | - SIGNAL_TYPE_DVI_DUAL_LINK | - SIGNAL_TYPE_LVDS | - SIGNAL_TYPE_DISPLAY_PORT | - SIGNAL_TYPE_DISPLAY_PORT_MST | - SIGNAL_TYPE_EDP | - SIGNAL_TYPE_HDMI_TYPE_A; - - /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. - * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. - * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer - * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. - * Prefer DIG assignment is decided by board design. - * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design - * and VBIOS will filter out 7 UNIPHY for DCE 8.0. - * By this, adding DIGG should not hurt DCE 8.0. - * This will let DCE 8.1 share DCE 8.0 as much as possible - */ - - enc10->link_regs = link_regs; - enc10->aux_regs = aux_regs; - enc10->hpd_regs = hpd_regs; - enc10->link_shift = link_shift; - enc10->link_mask = link_mask; - - switch (enc10->base.transmitter) { - case TRANSMITTER_UNIPHY_A: - enc10->base.preferred_engine = ENGINE_ID_DIGA; - break; - case TRANSMITTER_UNIPHY_B: - enc10->base.preferred_engine = ENGINE_ID_DIGB; - break; - case TRANSMITTER_UNIPHY_C: - enc10->base.preferred_engine = ENGINE_ID_DIGC; - break; - case TRANSMITTER_UNIPHY_D: - enc10->base.preferred_engine = ENGINE_ID_DIGD; - break; - case TRANSMITTER_UNIPHY_E: - enc10->base.preferred_engine = ENGINE_ID_DIGE; - break; - case TRANSMITTER_UNIPHY_F: - enc10->base.preferred_engine = ENGINE_ID_DIGF; - break; - case TRANSMITTER_UNIPHY_G: - enc10->base.preferred_engine = ENGINE_ID_DIGG; - break; - default: - ASSERT_CRITICAL(false); - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - } - - /* default to one to mirror Windows behavior */ - enc10->base.features.flags.bits.HDMI_6GB_EN = 1; - - result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, - enc10->base.id, &bp_cap_info); - - /* Override features with DCE-specific values */ - if (result == BP_RESULT_OK) { - enc10->base.features.flags.bits.IS_HBR2_CAPABLE = - bp_cap_info.DP_HBR2_EN; - enc10->base.features.flags.bits.IS_HBR3_CAPABLE = - bp_cap_info.DP_HBR3_EN; - enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; - enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE; - enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; - enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; - enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; - enc10->base.features.flags.bits.DP_IS_USB_C = - bp_cap_info.DP_IS_USB_C; - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, - result); - } - if (enc10->base.ctx->dc->debug.hdmi20_disable) { - enc10->base.features.flags.bits.HDMI_6GB_EN = 0; - } -} - -#define AUX_REG(reg)\ - (enc10->aux_regs->reg) - -#define AUX_REG_READ(reg_name) \ - dm_read_reg(CTX, AUX_REG(reg_name)) - -#define AUX_REG_WRITE(reg_name, val) \ - dm_write_reg(CTX, AUX_REG(reg_name), val) -void enc3_hw_init(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - -/* - 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 - 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 - 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 - 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 - 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 - 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 - 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 - 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 -*/ - -/* - AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, - AUX_RX_START_WINDOW = 1 [6:4] - AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] - AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 - AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 - AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 - AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 - AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 - AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 - AUX_RX_DETECTION_THRESHOLD [30:28] = 1 -*/ - AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); - - AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); - - //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; - // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk - // 27MHz -> 0xd - // 100MHz -> 0x32 - // 48MHz -> 0x18 - - // Set TMDS_CTL0 to 1. This is a legacy setting. - REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); - - dcn10_aux_initialize(enc10); -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h deleted file mode 100644 index 5b6177c2ae98..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2020 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 - * - */ - -#ifndef __DC_LINK_ENCODER__DCN30_H__ -#define __DC_LINK_ENCODER__DCN30_H__ - -#include "dcn20/dcn20_link_encoder.h" - -#define LE_DCN3_REG_LIST(id)\ - SRI(DIG_BE_CNTL, DIG, id), \ - SRI(DIG_BE_EN_CNTL, DIG, id), \ - SRI(TMDS_CTL_BITS, DIG, id), \ - SRI(TMDS_DCBALANCER_CONTROL, DIG, id), \ - SRI(DP_CONFIG, DP, id), \ - SRI(DP_DPHY_CNTL, DP, id), \ - SRI(DP_DPHY_PRBS_CNTL, DP, id), \ - SRI(DP_DPHY_SCRAM_CNTL, DP, id),\ - SRI(DP_DPHY_SYM0, DP, id), \ - SRI(DP_DPHY_SYM1, DP, id), \ - SRI(DP_DPHY_SYM2, DP, id), \ - SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ - SRI(DP_LINK_CNTL, DP, id), \ - SRI(DP_LINK_FRAMING_CNTL, DP, id), \ - SRI(DP_MSE_SAT0, DP, id), \ - SRI(DP_MSE_SAT1, DP, id), \ - SRI(DP_MSE_SAT2, DP, id), \ - SRI(DP_MSE_SAT_UPDATE, DP, id), \ - SRI(DP_SEC_CNTL, DP, id), \ - SRI(DP_VID_STREAM_CNTL, DP, id), \ - SRI(DP_DPHY_FAST_TRAINING, DP, id), \ - SRI(DP_SEC_CNTL1, DP, id), \ - SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) - -#define LINK_ENCODER_MASK_SH_LIST_DCN30(mask_sh) \ - LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh),\ - LE_SF(DIG0_TMDS_DCBALANCER_CONTROL, TMDS_SYNC_DCBAL_EN, mask_sh) - -#define DPCS_DCN3_MASK_SH_LIST(mask_sh)\ - DPCS_DCN2_MASK_SH_LIST(mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT_18_BIT, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_TX_VBOOST_LVL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) - - -void dcn30_link_encoder_construct( - struct dcn20_link_encoder *enc20, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask); - -void enc3_hw_init(struct link_encoder *enc); - -bool dcn30_link_encoder_validate_output_with_stream( - struct link_encoder *enc, - const struct dc_stream_state *stream); - -#endif /* __DC_LINK_ENCODER__DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c deleted file mode 100644 index 425b830b88d2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c +++ /dev/null @@ -1,899 +0,0 @@ -/* - * Copyright 2020 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 "dc_bios_types.h" -#include "dcn30_dio_stream_encoder.h" -#include "reg_helper.h" -#include "hw_shared.h" -#include "dc.h" - -#define DC_LOGGER \ - enc1->base.ctx->logger - -#define REG(reg)\ - (enc1->regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc1->se_shift->field_name, enc1->se_mask->field_name - -#define VBI_LINE_0 0 -#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 - -#define CTX \ - enc1->base.ctx - - -static void enc3_update_hdmi_info_packet( - struct dcn10_stream_encoder *enc1, - uint32_t packet_index, - const struct dc_info_packet *info_packet) -{ - uint32_t cont, send, line; - - if (info_packet->valid) { - enc1->base.vpg->funcs->update_generic_info_packet( - enc1->base.vpg, - packet_index, - info_packet, - true); - - /* enable transmission of packet(s) - - * packet transmission begins on the next frame */ - cont = 1; - /* send packet(s) every frame */ - send = 1; - /* select line number to send packets on */ - line = 2; - } else { - cont = 0; - send = 0; - line = 0; - } - - /* DP_SEC_GSP[x]_LINE_REFERENCE - keep default value REFER_TO_DP_SOF */ - - /* choose which generic packet control to use */ - switch (packet_index) { - case 0: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC0_CONT, cont, - HDMI_GENERIC0_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, - HDMI_GENERIC0_LINE, line); - break; - case 1: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC1_CONT, cont, - HDMI_GENERIC1_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, - HDMI_GENERIC1_LINE, line); - break; - case 2: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC2_CONT, cont, - HDMI_GENERIC2_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, - HDMI_GENERIC2_LINE, line); - break; - case 3: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC3_CONT, cont, - HDMI_GENERIC3_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, - HDMI_GENERIC3_LINE, line); - break; - case 4: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC4_CONT, cont, - HDMI_GENERIC4_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, - HDMI_GENERIC4_LINE, line); - break; - case 5: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC5_CONT, cont, - HDMI_GENERIC5_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, - HDMI_GENERIC5_LINE, line); - break; - case 6: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC6_CONT, cont, - HDMI_GENERIC6_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, - HDMI_GENERIC6_LINE, line); - break; - case 7: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, - HDMI_GENERIC7_CONT, cont, - HDMI_GENERIC7_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, - HDMI_GENERIC7_LINE, line); - break; - case 8: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC8_CONT, cont, - HDMI_GENERIC8_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL7, - HDMI_GENERIC8_LINE, line); - break; - case 9: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC9_CONT, cont, - HDMI_GENERIC9_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL7, - HDMI_GENERIC9_LINE, line); - break; - case 10: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC10_CONT, cont, - HDMI_GENERIC10_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL8, - HDMI_GENERIC10_LINE, line); - break; - case 11: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC11_CONT, cont, - HDMI_GENERIC11_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL8, - HDMI_GENERIC11_LINE, line); - break; - case 12: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC12_CONT, cont, - HDMI_GENERIC12_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL9, - HDMI_GENERIC12_LINE, line); - break; - case 13: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC13_CONT, cont, - HDMI_GENERIC13_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL9, - HDMI_GENERIC13_LINE, line); - break; - case 14: - REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, - HDMI_GENERIC14_CONT, cont, - HDMI_GENERIC14_SEND, send); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL10, - HDMI_GENERIC14_LINE, line); - break; - default: - /* invalid HW packet index */ - DC_LOG_WARNING( - "Invalid HW packet index: %s()\n", - __func__); - return; - } -} - -void enc3_stream_encoder_update_hdmi_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* for bring up, disable dp double TODO */ - REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); - REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); - - /*Always add mandatory packets first followed by optional ones*/ - enc3_update_hdmi_info_packet(enc1, 0, &info_frame->avi); - enc3_update_hdmi_info_packet(enc1, 5, &info_frame->hfvsif); - enc3_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); - enc3_update_hdmi_info_packet(enc1, 1, &info_frame->vendor); - enc3_update_hdmi_info_packet(enc1, 3, &info_frame->spd); - enc3_update_hdmi_info_packet(enc1, 4, &info_frame->hdrsmd); - enc3_update_hdmi_info_packet(enc1, 6, &info_frame->vtem); -} - -void enc3_stream_encoder_stop_hdmi_info_packets( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* stop generic packets 0,1 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC0_CONT, 0, - HDMI_GENERIC0_SEND, 0, - HDMI_GENERIC1_CONT, 0, - HDMI_GENERIC1_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL1, 0, - HDMI_GENERIC0_LINE, 0, - HDMI_GENERIC1_LINE, 0); - - /* stop generic packets 2,3 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC2_CONT, 0, - HDMI_GENERIC2_SEND, 0, - HDMI_GENERIC3_CONT, 0, - HDMI_GENERIC3_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL2, 0, - HDMI_GENERIC2_LINE, 0, - HDMI_GENERIC3_LINE, 0); - - /* stop generic packets 4,5 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC4_CONT, 0, - HDMI_GENERIC4_SEND, 0, - HDMI_GENERIC5_CONT, 0, - HDMI_GENERIC5_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL3, 0, - HDMI_GENERIC4_LINE, 0, - HDMI_GENERIC5_LINE, 0); - - /* stop generic packets 6,7 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, - HDMI_GENERIC6_CONT, 0, - HDMI_GENERIC6_SEND, 0, - HDMI_GENERIC7_CONT, 0, - HDMI_GENERIC7_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL4, 0, - HDMI_GENERIC6_LINE, 0, - HDMI_GENERIC7_LINE, 0); - - /* stop generic packets 8,9 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, - HDMI_GENERIC8_CONT, 0, - HDMI_GENERIC8_SEND, 0, - HDMI_GENERIC9_CONT, 0, - HDMI_GENERIC9_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL7, 0, - HDMI_GENERIC8_LINE, 0, - HDMI_GENERIC9_LINE, 0); - - /* stop generic packets 10,11 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, - HDMI_GENERIC10_CONT, 0, - HDMI_GENERIC10_SEND, 0, - HDMI_GENERIC11_CONT, 0, - HDMI_GENERIC11_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL8, 0, - HDMI_GENERIC10_LINE, 0, - HDMI_GENERIC11_LINE, 0); - - /* stop generic packets 12,13 on HDMI */ - REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, - HDMI_GENERIC12_CONT, 0, - HDMI_GENERIC12_SEND, 0, - HDMI_GENERIC13_CONT, 0, - HDMI_GENERIC13_SEND, 0); - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL9, 0, - HDMI_GENERIC12_LINE, 0, - HDMI_GENERIC13_LINE, 0); - - /* stop generic packet 14 on HDMI */ - REG_SET_2(HDMI_GENERIC_PACKET_CONTROL6, 0, - HDMI_GENERIC14_CONT, 0, - HDMI_GENERIC14_SEND, 0); - REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL10, - HDMI_GENERIC14_LINE, 0); -} - -/* Set DSC-related configuration. - * dsc_mode: 0 disables DSC, other values enable DSC in specified format - * sc_bytes_per_pixel: Bytes per pixel in u3.28 format - * dsc_slice_width: Slice width in pixels - */ -static void enc3_dp_set_dsc_config(struct stream_encoder *enc, - enum optc_dsc_mode dsc_mode, - uint32_t dsc_bytes_per_pixel, - uint32_t dsc_slice_width) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE_2(DP_DSC_CNTL, - DP_DSC_MODE, dsc_mode, - DP_DSC_SLICE_WIDTH, dsc_slice_width); - - REG_SET(DP_DSC_BYTES_PER_PIXEL, 0, - DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); -} - - -void enc3_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, - bool enable, - uint8_t *dsc_packed_pps, - bool immediate_update) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (enable) { - struct dc_info_packet pps_sdp; - int i; - - /* Configure for PPS packet size (128 bytes) */ - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 1); - - /* We need turn on clock before programming AFMT block - * - * TODO: We may not need this here anymore since update_generic_info_packet - * no longer touches AFMT - */ - REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); - - /* Load PPS into infoframe (SDP) registers */ - pps_sdp.valid = true; - pps_sdp.hb0 = 0; - pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; - pps_sdp.hb2 = 127; - pps_sdp.hb3 = 0; - - for (i = 0; i < 4; i++) { - memcpy(pps_sdp.sb, &dsc_packed_pps[i * 32], 32); - enc1->base.vpg->funcs->update_generic_info_packet( - enc1->base.vpg, - 11 + i, - &pps_sdp, - immediate_update); - } - - /* SW should make sure VBID[6] update line number is bigger - * than PPS transmit line number - */ - REG_UPDATE(DP_GSP11_CNTL, - DP_SEC_GSP11_LINE_NUM, 2); - REG_UPDATE_2(DP_MSA_VBID_MISC, - DP_VBID6_LINE_REFERENCE, 0, - DP_VBID6_LINE_NUM, 3); - - /* Send PPS data at the line number specified above. - * DP spec requires PPS to be sent only when it changes, however since - * decoder has to be able to handle its change on every frame, we're - * sending it always (i.e. on every frame) to reduce the chance it'd be - * missed by decoder. If it turns out required to send PPS only when it - * changes, we can use DP_SEC_GSP11_SEND register. - */ - REG_UPDATE(DP_GSP11_CNTL, - DP_SEC_GSP11_ENABLE, 1); - REG_UPDATE(DP_SEC_CNTL, - DP_SEC_STREAM_ENABLE, 1); - } else { - /* Disable Generic Stream Packet 11 (GSP) transmission */ - REG_UPDATE(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, 0); - REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 0); - } -} - - -/* this function read dsc related register fields to be logged later in dcn10_log_hw_state - * into a dcn_dsc_state struct. - */ -static void enc3_read_state(struct stream_encoder *enc, struct enc_state *s) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - //if dsc is enabled, continue to read - REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode); - if (s->dsc_mode) { - REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width); - REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, &s->sec_gsp_pps_line_num); - - REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference); - REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num); - - REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, &s->sec_gsp_pps_enable); - REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable); - } -} - -void enc3_stream_encoder_update_dp_info_packets_sdp_line_num( - struct stream_encoder *enc, - struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (info_frame->adaptive_sync.valid == true && - info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { - //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF - REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1); - - REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, - info_frame->sdp_line_num.adaptive_sync_line_num); - } -} - -void enc3_stream_encoder_update_dp_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t value = 0; - uint32_t dmdata_packet_enabled = 0; - - if (info_frame->vsc.valid) { - enc->vpg->funcs->update_generic_info_packet( - enc->vpg, - 0, /* packetIndex */ - &info_frame->vsc, - true); - } - /* TODO: VSC SDP at packetIndex 1 should be retricted only if PSR-SU on. - * There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU. - * In addition, currently the driver check the valid bit then update and - * send the corresponding Infopacket. For PSR-SU, the SDP only be sent - * while entering PSR-SU mode. So we need another parameter(e.g. send) - * in dc_info_packet to indicate which infopacket should be enabled by - * default here. - */ - if (info_frame->vsc.valid) { - enc->vpg->funcs->update_generic_info_packet( - enc->vpg, - 1, /* packetIndex */ - &info_frame->vsc, - true); - } - /* TODO: VSC SDP at packetIndex 1 should be restricted only if PSR-SU on. - * There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU. - * In addition, currently the driver check the valid bit then update and - * send the corresponding Infopacket. For PSR-SU, the SDP only be sent - * while entering PSR-SU mode. So we need another parameter(e.g. send) - * in dc_info_packet to indicate which infopacket should be enabled by - * default here. - */ - if (info_frame->vsc.valid) { - enc->vpg->funcs->update_generic_info_packet( - enc->vpg, - 1, /* packetIndex */ - &info_frame->vsc, - true); - } - if (info_frame->spd.valid) { - enc->vpg->funcs->update_generic_info_packet( - enc->vpg, - 2, /* packetIndex */ - &info_frame->spd, - true); - } - if (info_frame->hdrsmd.valid) { - enc->vpg->funcs->update_generic_info_packet( - enc->vpg, - 3, /* packetIndex */ - &info_frame->hdrsmd, - true); - } - /* packetIndex 4 is used for send immediate sdp message, and please - * use other packetIndex (such as 5,6) for other info packet - */ - - if (info_frame->adaptive_sync.valid) - enc->vpg->funcs->update_generic_info_packet( - enc->vpg, - 5, /* packetIndex */ - &info_frame->adaptive_sync, - true); - - /* enable/disable transmission of packet(s). - * If enabled, packet transmission begins on the next frame - */ - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid); - - /* This bit is the master enable bit. - * When enabling secondary stream engine, - * this master bit must also be set. - * This register shared with audio info frame. - * Therefore we need to enable master bit - * if at least on of the fields is not 0 - */ - value = REG_READ(DP_SEC_CNTL); - if (value) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); - - /* check if dynamic metadata packet transmission is enabled */ - REG_GET(DP_SEC_METADATA_TRANSMISSION, - DP_SEC_METADATA_PACKET_ENABLE, &dmdata_packet_enabled); - - if (dmdata_packet_enabled) - REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); -} - -static void enc3_dp_set_odm_combine( - struct stream_encoder *enc, - bool odm_combine) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, odm_combine); -} - -/* setup stream encoder in dvi mode */ -static void enc3_stream_encoder_dvi_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - bool is_dual_link) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { - struct bp_encoder_control cntl = {0}; - - cntl.action = ENCODER_CONTROL_SETUP; - cntl.engine_id = enc1->base.id; - cntl.signal = is_dual_link ? - SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; - cntl.enable_dp_audio = false; - cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; - cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; - - if (enc1->base.bp->funcs->encoder_control( - enc1->base.bp, &cntl) != BP_RESULT_OK) - return; - - } else { - - //Set pattern for clock channel, default vlue 0x63 does not work - REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); - - //DIG_BE_TMDS_DVI_MODE : TMDS-DVI mode is already set in link_encoder_setup - - //DIG_SOURCE_SELECT is already set in dig_connect_to_otg - - /* set DIG_START to 0x1 to reset FIFO */ - REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); - udelay(1); - - /* write 0 to take the FIFO out of reset */ - REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); - udelay(1); - } - - ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); - ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); - enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); -} - -/* setup stream encoder in hdmi mode */ -static void enc3_stream_encoder_hdmi_set_stream_attribute( - struct stream_encoder *enc, - struct dc_crtc_timing *crtc_timing, - int actual_pix_clk_khz, - bool enable_audio) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { - struct bp_encoder_control cntl = {0}; - - cntl.action = ENCODER_CONTROL_SETUP; - cntl.engine_id = enc1->base.id; - cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; - cntl.enable_dp_audio = enable_audio; - cntl.pixel_clock = actual_pix_clk_khz; - cntl.lanes_number = LANE_COUNT_FOUR; - - if (enc1->base.bp->funcs->encoder_control( - enc1->base.bp, &cntl) != BP_RESULT_OK) - return; - - } else { - - //Set pattern for clock channel, default vlue 0x63 does not work - REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); - - //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup - - //DIG_SOURCE_SELECT is already set in dig_connect_to_otg - - /* set DIG_START to 0x1 to reset FIFO */ - REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); - udelay(1); - - /* write 0 to take the FIFO out of reset */ - REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); - udelay(1); - } - - /* Configure pixel encoding */ - enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); - - /* setup HDMI engine */ - REG_UPDATE_6(HDMI_CONTROL, - HDMI_PACKET_GEN_VERSION, 1, - HDMI_KEEPOUT_MODE, 1, - HDMI_DEEP_COLOR_ENABLE, 0, - HDMI_DATA_SCRAMBLE_EN, 0, - HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, - HDMI_CLOCK_CHANNEL_RATE, 0); - - /* Configure color depth */ - switch (crtc_timing->display_color_depth) { - case COLOR_DEPTH_888: - REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); - break; - case COLOR_DEPTH_101010: - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 1, - HDMI_DEEP_COLOR_ENABLE, 0); - } else { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 1, - HDMI_DEEP_COLOR_ENABLE, 1); - } - break; - case COLOR_DEPTH_121212: - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 2, - HDMI_DEEP_COLOR_ENABLE, 0); - } else { - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 2, - HDMI_DEEP_COLOR_ENABLE, 1); - } - break; - case COLOR_DEPTH_161616: - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 3, - HDMI_DEEP_COLOR_ENABLE, 1); - break; - default: - break; - } - - if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { - /* enable HDMI data scrambler - * HDMI_CLOCK_CHANNEL_RATE_MORE_340M - * Clock channel frequency is 1/4 of character rate. - */ - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DATA_SCRAMBLE_EN, 1, - HDMI_CLOCK_CHANNEL_RATE, 1); - } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { - - /* TODO: New feature for DCE11, still need to implement */ - - /* enable HDMI data scrambler - * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE - * Clock channel frequency is the same - * as character rate - */ - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DATA_SCRAMBLE_EN, 1, - HDMI_CLOCK_CHANNEL_RATE, 0); - } - - - /* Enable transmission of General Control packet on every frame */ - REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, - HDMI_GC_CONT, 1, - HDMI_GC_SEND, 1, - HDMI_NULL_SEND, 1); - - /* Disable Audio Content Protection packet transmission */ - REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); - - /* following belongs to audio */ - /* Enable Audio InfoFrame packet transmission. */ - REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); - - /* update double-buffered AUDIO_INFO registers immediately */ - ASSERT (enc->afmt); - enc->afmt->funcs->audio_info_immediate_update(enc->afmt); - - /* Select line number on which to send Audio InfoFrame packets */ - REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, - VBI_LINE_0 + 2); - - /* set HDMI GC AVMUTE */ - REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); -} - -void enc3_audio_mute_control( - struct stream_encoder *enc, - bool mute) -{ - ASSERT (enc->afmt); - enc->afmt->funcs->audio_mute_control(enc->afmt, mute); -} - -void enc3_se_dp_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info) -{ - ASSERT (enc->afmt); - enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); -} - -#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 -#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 - -static void enc3_se_setup_dp_audio( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* --- DP Audio packet configurations --- */ - - /* ATP Configuration */ - REG_SET(DP_SEC_AUD_N, 0, - DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); - - /* Async/auto-calc timestamp mode */ - REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, - DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); - - ASSERT (enc->afmt); - enc->afmt->funcs->setup_dp_audio(enc->afmt); -} - -void enc3_se_dp_audio_enable( - struct stream_encoder *enc) -{ - enc1_se_enable_audio_clock(enc, true); - enc3_se_setup_dp_audio(enc); - enc1_se_enable_dp_audio(enc); -} - -static void enc3_se_setup_hdmi_audio( - struct stream_encoder *enc, - const struct audio_crtc_info *crtc_info) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - struct audio_clock_info audio_clock_info = {0}; - - /* Setup audio in AFMT - program AFMT block associated with DIO */ - ASSERT (enc->afmt); - enc->afmt->funcs->setup_hdmi_audio(enc->afmt); - - /* HDMI_AUDIO_PACKET_CONTROL */ - REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, - HDMI_AUDIO_DELAY_EN, 1); - - /* HDMI_ACR_PACKET_CONTROL */ - REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL, - HDMI_ACR_AUTO_SEND, 1, - HDMI_ACR_SOURCE, 0, - HDMI_ACR_AUDIO_PRIORITY, 0); - - /* Program audio clock sample/regeneration parameters */ - get_audio_clock_info(crtc_info->color_depth, - crtc_info->requested_pixel_clock_100Hz, - crtc_info->calculated_pixel_clock_100Hz, - &audio_clock_info); - DC_LOG_HW_AUDIO( - "\n%s:Input::requested_pixel_clock_100Hz = %d" \ - "calculated_pixel_clock_100Hz = %d \n", __func__, \ - crtc_info->requested_pixel_clock_100Hz, \ - crtc_info->calculated_pixel_clock_100Hz); - - /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ - REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); - - /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ - REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); - - /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ - REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); - - /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ - REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); - - /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ - REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); - - /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ - REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); - - /* Video driver cannot know in advance which sample rate will - * be used by HD Audio driver - * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is - * programmed below in interruppt callback - */ -} - -void enc3_se_hdmi_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info, - struct audio_crtc_info *audio_crtc_info) -{ - enc1_se_enable_audio_clock(enc, true); - enc3_se_setup_hdmi_audio(enc, audio_crtc_info); - ASSERT (enc->afmt); - enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); -} - - -static const struct stream_encoder_funcs dcn30_str_enc_funcs = { - .dp_set_odm_combine = - enc3_dp_set_odm_combine, - .dp_set_stream_attribute = - enc2_stream_encoder_dp_set_stream_attribute, - .hdmi_set_stream_attribute = - enc3_stream_encoder_hdmi_set_stream_attribute, - .dvi_set_stream_attribute = - enc3_stream_encoder_dvi_set_stream_attribute, - .set_throttled_vcp_size = - enc1_stream_encoder_set_throttled_vcp_size, - .update_hdmi_info_packets = - enc3_stream_encoder_update_hdmi_info_packets, - .stop_hdmi_info_packets = - enc3_stream_encoder_stop_hdmi_info_packets, - .update_dp_info_packets_sdp_line_num = - enc3_stream_encoder_update_dp_info_packets_sdp_line_num, - .update_dp_info_packets = - enc3_stream_encoder_update_dp_info_packets, - .stop_dp_info_packets = - enc1_stream_encoder_stop_dp_info_packets, - .dp_blank = - enc1_stream_encoder_dp_blank, - .dp_unblank = - enc2_stream_encoder_dp_unblank, - .audio_mute_control = enc3_audio_mute_control, - - .dp_audio_setup = enc3_se_dp_audio_setup, - .dp_audio_enable = enc3_se_dp_audio_enable, - .dp_audio_disable = enc1_se_dp_audio_disable, - - .hdmi_audio_setup = enc3_se_hdmi_audio_setup, - .hdmi_audio_disable = enc1_se_hdmi_audio_disable, - .setup_stereo_sync = enc1_setup_stereo_sync, - .set_avmute = enc1_stream_encoder_set_avmute, - .dig_connect_to_otg = enc1_dig_connect_to_otg, - .dig_source_otg = enc1_dig_source_otg, - - .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, - - .enc_read_state = enc3_read_state, - .dp_set_dsc_config = enc3_dp_set_dsc_config, - .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet, - .set_dynamic_metadata = enc2_set_dynamic_metadata, - .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, - - .get_fifo_cal_average_level = enc2_get_fifo_cal_average_level, -}; - -void dcn30_dio_stream_encoder_construct( - struct dcn10_stream_encoder *enc1, - struct dc_context *ctx, - struct dc_bios *bp, - enum engine_id eng_id, - struct vpg *vpg, - struct afmt *afmt, - const struct dcn10_stream_enc_registers *regs, - const struct dcn10_stream_encoder_shift *se_shift, - const struct dcn10_stream_encoder_mask *se_mask) -{ - enc1->base.funcs = &dcn30_str_enc_funcs; - enc1->base.ctx = ctx; - enc1->base.id = eng_id; - enc1->base.bp = bp; - enc1->base.vpg = vpg; - enc1->base.afmt = afmt; - enc1->regs = regs; - enc1->se_shift = se_shift; - enc1->se_mask = se_mask; - enc1->base.stream_enc_inst = vpg->inst; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h deleted file mode 100644 index 06310973ded2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright 2020 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 - * - */ - -#ifndef __DC_DIO_STREAM_ENCODER_DCN30_H__ -#define __DC_DIO_STREAM_ENCODER_DCN30_H__ - -#include "dcn30/dcn30_vpg.h" -#include "dcn30/dcn30_afmt.h" -#include "stream_encoder.h" -#include "dcn20/dcn20_stream_encoder.h" - -/* Register bit field name change */ -#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_GATE_DIS__SHIFT 0x8 -#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_EN__SHIFT 0x9 -#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_CLOCK_ON__SHIFT 0xa -#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP__SHIFT 0xe -#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_ORDER_INVERT__SHIFT 0xf - -#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_GATE_DIS_MASK 0x00000100L -#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_EN_MASK 0x00000200L -#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_CLOCK_ON_MASK 0x00000400L -#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP_MASK 0x00004000L -#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_ORDER_INVERT_MASK 0x00008000L - - -#define SE_DCN3_REG_LIST(id)\ - SRI(AFMT_CNTL, DIG, id), \ - SRI(DIG_FE_CNTL, DIG, id), \ - SRI(HDMI_CONTROL, DIG, id), \ - SRI(HDMI_DB_CONTROL, DIG, id), \ - SRI(HDMI_GC, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \ - SRI(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \ - SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \ - SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \ - SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \ - SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ - SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\ - SRI(HDMI_ACR_32_0, DIG, id),\ - SRI(HDMI_ACR_32_1, DIG, id),\ - SRI(HDMI_ACR_44_0, DIG, id),\ - SRI(HDMI_ACR_44_1, DIG, id),\ - SRI(HDMI_ACR_48_0, DIG, id),\ - SRI(HDMI_ACR_48_1, DIG, id),\ - SRI(DP_DB_CNTL, DP, id), \ - SRI(DP_MSA_MISC, DP, id), \ - SRI(DP_MSA_VBID_MISC, DP, id), \ - SRI(DP_MSA_COLORIMETRY, DP, id), \ - SRI(DP_MSA_TIMING_PARAM1, DP, id), \ - SRI(DP_MSA_TIMING_PARAM2, DP, id), \ - SRI(DP_MSA_TIMING_PARAM3, DP, id), \ - SRI(DP_MSA_TIMING_PARAM4, DP, id), \ - SRI(DP_MSE_RATE_CNTL, DP, id), \ - SRI(DP_MSE_RATE_UPDATE, DP, id), \ - SRI(DP_PIXEL_FORMAT, DP, id), \ - SRI(DP_SEC_CNTL, DP, id), \ - SRI(DP_SEC_CNTL1, DP, id), \ - SRI(DP_SEC_CNTL2, DP, id), \ - SRI(DP_SEC_CNTL5, DP, id), \ - SRI(DP_SEC_CNTL6, DP, id), \ - SRI(DP_STEER_FIFO, DP, id), \ - SRI(DP_VID_M, DP, id), \ - SRI(DP_VID_N, DP, id), \ - SRI(DP_VID_STREAM_CNTL, DP, id), \ - SRI(DP_VID_TIMING, DP, id), \ - SRI(DP_SEC_AUD_N, DP, id), \ - SRI(DP_SEC_AUD_N_READBACK, DP, id), \ - SRI(DP_SEC_AUD_M_READBACK, DP, id), \ - SRI(DP_SEC_TIMESTAMP, DP, id), \ - SRI(DP_DSC_CNTL, DP, id), \ - SRI(DP_DSC_BYTES_PER_PIXEL, DP, id), \ - SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ - SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ - SRI(DP_SEC_FRAMING4, DP, id), \ - SRI(DP_GSP11_CNTL, DP, id), \ - SRI(DME_CONTROL, DME, id),\ - SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ - SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ - SRI(DIG_FE_CNTL, DIG, id), \ - SRI(DIG_FIFO_STATUS, DIG, id), \ - SRI(DIG_CLOCK_PATTERN, DIG, id) - - -#define SE_COMMON_MASK_SH_LIST_DCN30(mask_sh)\ - SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ - SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ - SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ - SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ - SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\ - SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ - SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ - SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ - SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ - SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ - SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ - SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_START, mask_sh),\ - SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ - SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ - SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ - SE_SF(DP0_DP_SEC_AUD_N_READBACK, DP_SEC_AUD_N_READBACK, mask_sh),\ - SE_SF(DP0_DP_SEC_AUD_M_READBACK, DP_SEC_AUD_M_READBACK, mask_sh),\ - SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ - SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ - SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_LEVEL_ERROR, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_USE_OVERWRITE_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_OVERWRITE_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_ERROR_ACK, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CAL_AVERAGE_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MAXIMUM_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MINIMUM_LEVEL, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_READ_CLOCK_SRC, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CALIBRATED, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECAL_AVERAGE, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECOMP_MINMAX, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP11_PPS, mask_sh),\ - SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, mask_sh),\ - SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, mask_sh),\ - SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ - SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ - SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ - SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ - SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh), \ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_CONT, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_SEND, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC8_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC9_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC10_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC11_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC12_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC13_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL10, HDMI_GENERIC14_LINE, mask_sh),\ - SE_SF(DP0_DP_DSC_CNTL, DP_DSC_MODE, mask_sh),\ - SE_SF(DP0_DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, mask_sh),\ - SE_SF(DP0_DP_DSC_BYTES_PER_PIXEL, DP_DSC_BYTES_PER_PIXEL, mask_sh),\ - SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\ - SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\ - SE_SF(DME0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\ - SE_SF(DME0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\ - SE_SF(DME0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\ - SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\ - SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ - SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\ - SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\ - SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ - SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DOLBY_VISION_EN, mask_sh),\ - SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, mask_sh),\ - SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh),\ - SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh) - -void dcn30_dio_stream_encoder_construct( - struct dcn10_stream_encoder *enc1, - struct dc_context *ctx, - struct dc_bios *bp, - enum engine_id eng_id, - struct vpg *vpg, - struct afmt *afmt, - const struct dcn10_stream_enc_registers *regs, - const struct dcn10_stream_encoder_shift *se_shift, - const struct dcn10_stream_encoder_mask *se_mask); - -void enc3_stream_encoder_update_hdmi_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame); - -void enc3_stream_encoder_stop_hdmi_info_packets( - struct stream_encoder *enc); - -void enc3_stream_encoder_update_dp_info_packets_sdp_line_num( - struct stream_encoder *enc, - struct encoder_info_frame *info_frame); - -void enc3_stream_encoder_update_dp_info_packets( - struct stream_encoder *enc, - const struct encoder_info_frame *info_frame); - -void enc3_audio_mute_control( - struct stream_encoder *enc, - bool mute); - -void enc3_se_dp_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info); - -void enc3_se_dp_audio_enable( - struct stream_encoder *enc); - -void enc3_se_hdmi_audio_setup( - struct stream_encoder *enc, - unsigned int az_inst, - struct audio_info *info, - struct audio_crtc_info *audio_crtc_info); - -void enc3_dp_set_dsc_pps_info_packet( - struct stream_encoder *enc, - bool enable, - uint8_t *dsc_packed_pps, - bool immediate_update); - -#endif /* __DC_DIO_STREAM_ENCODER_DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile index d9816313c3b1..e2601d0aba41 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile @@ -4,7 +4,7 @@ # # Makefile for dcn31. -DCN31 = dcn31_dio_link_encoder.o dcn31_panel_cntl.o \ +DCN31 = dcn31_panel_cntl.o \ dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o \ dcn31_afmt.o dcn31_vpg.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c deleted file mode 100644 index b2cea59ba5d4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c +++ /dev/null @@ -1,681 +0,0 @@ -/* - * 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 "reg_helper.h" - -#include "core_types.h" -#include "link_encoder.h" -#include "dcn31_dio_link_encoder.h" -#include "stream_encoder.h" -#include "dc_bios_types.h" - -#include "gpio_service_interface.h" - -#include "link_enc_cfg.h" -#include "dc_dmub_srv.h" -#include "dal_asic_id.h" -#include "link.h" - -#define CTX \ - enc10->base.ctx -#define DC_LOGGER \ - enc10->base.ctx->logger - -#define REG(reg)\ - (enc10->link_regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - enc10->link_shift->field_name, enc10->link_mask->field_name - -#define IND_REG(index) \ - (enc10->link_regs->index) - -#define AUX_REG(reg)\ - (enc10->aux_regs->reg) - -#define AUX_REG_READ(reg_name) \ - dm_read_reg(CTX, AUX_REG(reg_name)) - -#define AUX_REG_WRITE(reg_name, val) \ - dm_write_reg(CTX, AUX_REG(reg_name), val) - -#ifndef MIN -#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) -#endif - -static uint8_t phy_id_from_transmitter(enum transmitter t) -{ - uint8_t phy_id; - - switch (t) { - case TRANSMITTER_UNIPHY_A: - phy_id = 0; - break; - case TRANSMITTER_UNIPHY_B: - phy_id = 1; - break; - case TRANSMITTER_UNIPHY_C: - phy_id = 2; - break; - case TRANSMITTER_UNIPHY_D: - phy_id = 3; - break; - case TRANSMITTER_UNIPHY_E: - phy_id = 4; - break; - case TRANSMITTER_UNIPHY_F: - phy_id = 5; - break; - case TRANSMITTER_UNIPHY_G: - phy_id = 6; - break; - default: - phy_id = 0; - break; - } - return phy_id; -} - -static bool has_query_dp_alt(struct link_encoder *enc) -{ - struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv; - - if (enc->ctx->dce_version >= DCN_VERSION_3_15) - return true; - - /* Supports development firmware and firmware >= 4.0.11 */ - return dc_dmub_srv && - !(dc_dmub_srv->dmub->fw_version >= DMUB_FW_VERSION(4, 0, 0) && - dc_dmub_srv->dmub->fw_version <= DMUB_FW_VERSION(4, 0, 10)); -} - -static bool query_dp_alt_from_dmub(struct link_encoder *enc, - union dmub_rb_cmd *cmd) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - memset(cmd, 0, sizeof(*cmd)); - cmd->query_dp_alt.header.type = DMUB_CMD__VBIOS; - cmd->query_dp_alt.header.sub_type = - DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT; - cmd->query_dp_alt.header.payload_bytes = sizeof(cmd->query_dp_alt.data); - cmd->query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter); - - if (!dc_wake_and_execute_dmub_cmd(enc->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) - return false; - - return true; -} - -void dcn31_link_encoder_set_dio_phy_mux( - struct link_encoder *enc, - enum encoder_type_select sel, - uint32_t hpo_inst) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - switch (enc->transmitter) { - case TRANSMITTER_UNIPHY_A: - if (sel == ENCODER_TYPE_HDMI_FRL) - REG_UPDATE(DIO_LINKA_CNTL, - HPO_HDMI_ENC_SEL, hpo_inst); - else if (sel == ENCODER_TYPE_DP_128B132B) - REG_UPDATE(DIO_LINKA_CNTL, - HPO_DP_ENC_SEL, hpo_inst); - REG_UPDATE(DIO_LINKA_CNTL, - ENC_TYPE_SEL, sel); - break; - case TRANSMITTER_UNIPHY_B: - if (sel == ENCODER_TYPE_HDMI_FRL) - REG_UPDATE(DIO_LINKB_CNTL, - HPO_HDMI_ENC_SEL, hpo_inst); - else if (sel == ENCODER_TYPE_DP_128B132B) - REG_UPDATE(DIO_LINKB_CNTL, - HPO_DP_ENC_SEL, hpo_inst); - REG_UPDATE(DIO_LINKB_CNTL, - ENC_TYPE_SEL, sel); - break; - case TRANSMITTER_UNIPHY_C: - if (sel == ENCODER_TYPE_HDMI_FRL) - REG_UPDATE(DIO_LINKC_CNTL, - HPO_HDMI_ENC_SEL, hpo_inst); - else if (sel == ENCODER_TYPE_DP_128B132B) - REG_UPDATE(DIO_LINKC_CNTL, - HPO_DP_ENC_SEL, hpo_inst); - REG_UPDATE(DIO_LINKC_CNTL, - ENC_TYPE_SEL, sel); - break; - case TRANSMITTER_UNIPHY_D: - if (sel == ENCODER_TYPE_HDMI_FRL) - REG_UPDATE(DIO_LINKD_CNTL, - HPO_HDMI_ENC_SEL, hpo_inst); - else if (sel == ENCODER_TYPE_DP_128B132B) - REG_UPDATE(DIO_LINKD_CNTL, - HPO_DP_ENC_SEL, hpo_inst); - REG_UPDATE(DIO_LINKD_CNTL, - ENC_TYPE_SEL, sel); - break; - case TRANSMITTER_UNIPHY_E: - if (sel == ENCODER_TYPE_HDMI_FRL) - REG_UPDATE(DIO_LINKE_CNTL, - HPO_HDMI_ENC_SEL, hpo_inst); - else if (sel == ENCODER_TYPE_DP_128B132B) - REG_UPDATE(DIO_LINKE_CNTL, - HPO_DP_ENC_SEL, hpo_inst); - REG_UPDATE(DIO_LINKE_CNTL, - ENC_TYPE_SEL, sel); - break; - case TRANSMITTER_UNIPHY_F: - if (sel == ENCODER_TYPE_HDMI_FRL) - REG_UPDATE(DIO_LINKF_CNTL, - HPO_HDMI_ENC_SEL, hpo_inst); - else if (sel == ENCODER_TYPE_DP_128B132B) - REG_UPDATE(DIO_LINKF_CNTL, - HPO_DP_ENC_SEL, hpo_inst); - REG_UPDATE(DIO_LINKF_CNTL, - ENC_TYPE_SEL, sel); - break; - default: - /* Do nothing */ - break; - } -} - -void enc31_hw_init(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - -/* - 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 - 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 - 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 - 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 - 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 - 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 - 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 - 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 -*/ - -/* - AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, - AUX_RX_START_WINDOW = 1 [6:4] - AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] - AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 - AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 - AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 - AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 - AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 - AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 - AUX_RX_DETECTION_THRESHOLD [30:28] = 1 -*/ - // dmub will read AUX_DPHY_RX_CONTROL0/AUX_DPHY_TX_CONTROL from vbios table in dp_aux_init - - //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; - // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk - // 27MHz -> 0xd - // 100MHz -> 0x32 - // 48MHz -> 0x18 - - // Set TMDS_CTL0 to 1. This is a legacy setting. - REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); - - dcn10_aux_initialize(enc10); -} - -static const struct link_encoder_funcs dcn31_link_enc_funcs = { - .read_state = link_enc2_read_state, - .validate_output_with_stream = - dcn30_link_encoder_validate_output_with_stream, - .hw_init = enc31_hw_init, - .setup = dcn10_link_encoder_setup, - .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, - .enable_dp_output = dcn31_link_encoder_enable_dp_output, - .enable_dp_mst_output = dcn31_link_encoder_enable_dp_mst_output, - .disable_output = dcn31_link_encoder_disable_output, - .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, - .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, - .update_mst_stream_allocation_table = - dcn10_link_encoder_update_mst_stream_allocation_table, - .psr_program_dp_dphy_fast_training = - dcn10_psr_program_dp_dphy_fast_training, - .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, - .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, - .enable_hpd = dcn10_link_encoder_enable_hpd, - .disable_hpd = dcn10_link_encoder_disable_hpd, - .is_dig_enabled = dcn10_is_dig_enabled, - .destroy = dcn10_link_encoder_destroy, - .fec_set_enable = enc2_fec_set_enable, - .fec_set_ready = enc2_fec_set_ready, - .fec_is_active = enc2_fec_is_active, - .get_dig_frontend = dcn10_get_dig_frontend, - .get_dig_mode = dcn10_get_dig_mode, - .is_in_alt_mode = dcn31_link_encoder_is_in_alt_mode, - .get_max_link_cap = dcn31_link_encoder_get_max_link_cap, - .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux, -}; - -void dcn31_link_encoder_construct( - struct dcn20_link_encoder *enc20, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask) -{ - struct bp_encoder_cap_info bp_cap_info = {0}; - const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; - enum bp_result result = BP_RESULT_OK; - struct dcn10_link_encoder *enc10 = &enc20->enc10; - - enc10->base.funcs = &dcn31_link_enc_funcs; - enc10->base.ctx = init_data->ctx; - enc10->base.id = init_data->encoder; - - enc10->base.hpd_source = init_data->hpd_source; - enc10->base.connector = init_data->connector; - - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - - enc10->base.features = *enc_features; - - enc10->base.transmitter = init_data->transmitter; - - /* set the flag to indicate whether driver poll the I2C data pin - * while doing the DP sink detect - */ - -/* if (dal_adapter_service_is_feature_supported(as, - FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) - enc10->base.features.flags.bits. - DP_SINK_DETECT_POLL_DATA_PIN = true;*/ - - enc10->base.output_signals = - SIGNAL_TYPE_DVI_SINGLE_LINK | - SIGNAL_TYPE_DVI_DUAL_LINK | - SIGNAL_TYPE_LVDS | - SIGNAL_TYPE_DISPLAY_PORT | - SIGNAL_TYPE_DISPLAY_PORT_MST | - SIGNAL_TYPE_EDP | - SIGNAL_TYPE_HDMI_TYPE_A; - - /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. - * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. - * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer - * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. - * Prefer DIG assignment is decided by board design. - * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design - * and VBIOS will filter out 7 UNIPHY for DCE 8.0. - * By this, adding DIGG should not hurt DCE 8.0. - * This will let DCE 8.1 share DCE 8.0 as much as possible - */ - - enc10->link_regs = link_regs; - enc10->aux_regs = aux_regs; - enc10->hpd_regs = hpd_regs; - enc10->link_shift = link_shift; - enc10->link_mask = link_mask; - - switch (enc10->base.transmitter) { - case TRANSMITTER_UNIPHY_A: - enc10->base.preferred_engine = ENGINE_ID_DIGA; - break; - case TRANSMITTER_UNIPHY_B: - enc10->base.preferred_engine = ENGINE_ID_DIGB; - break; - case TRANSMITTER_UNIPHY_C: - enc10->base.preferred_engine = ENGINE_ID_DIGC; - break; - case TRANSMITTER_UNIPHY_D: - enc10->base.preferred_engine = ENGINE_ID_DIGD; - break; - case TRANSMITTER_UNIPHY_E: - enc10->base.preferred_engine = ENGINE_ID_DIGE; - break; - case TRANSMITTER_UNIPHY_F: - enc10->base.preferred_engine = ENGINE_ID_DIGF; - break; - default: - ASSERT_CRITICAL(false); - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - } - - /* default to one to mirror Windows behavior */ - enc10->base.features.flags.bits.HDMI_6GB_EN = 1; - - result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, - enc10->base.id, &bp_cap_info); - - /* Override features with DCE-specific values */ - if (result == BP_RESULT_OK) { - enc10->base.features.flags.bits.IS_HBR2_CAPABLE = - bp_cap_info.DP_HBR2_EN; - enc10->base.features.flags.bits.IS_HBR3_CAPABLE = - bp_cap_info.DP_HBR3_EN; - enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; - enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE; - enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; - enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; - enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; - enc10->base.features.flags.bits.DP_IS_USB_C = - bp_cap_info.DP_IS_USB_C; - } else { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, - result); - } - if (enc10->base.ctx->dc->debug.hdmi20_disable) { - enc10->base.features.flags.bits.HDMI_6GB_EN = 0; - } -} - -void dcn31_link_encoder_construct_minimal( - struct dcn20_link_encoder *enc20, - struct dc_context *ctx, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - enum engine_id eng_id) -{ - struct dcn10_link_encoder *enc10 = &enc20->enc10; - - enc10->base.funcs = &dcn31_link_enc_funcs; - enc10->base.ctx = ctx; - enc10->base.id.type = OBJECT_TYPE_ENCODER; - enc10->base.hpd_source = HPD_SOURCEID_UNKNOWN; - enc10->base.connector.type = OBJECT_TYPE_CONNECTOR; - enc10->base.preferred_engine = eng_id; - enc10->base.features = *enc_features; - enc10->base.transmitter = TRANSMITTER_UNKNOWN; - enc10->link_regs = link_regs; - - enc10->base.output_signals = - SIGNAL_TYPE_DISPLAY_PORT | - SIGNAL_TYPE_DISPLAY_PORT_MST | - SIGNAL_TYPE_EDP; -} - -/* DPIA equivalent of link_transmitter_control. */ -static bool link_dpia_control(struct dc_context *dc_ctx, - struct dmub_cmd_dig_dpia_control_data *dpia_control) -{ - union dmub_rb_cmd cmd; - - memset(&cmd, 0, sizeof(cmd)); - - cmd.dig1_dpia_control.header.type = DMUB_CMD__DPIA; - cmd.dig1_dpia_control.header.sub_type = - DMUB_CMD__DPIA_DIG1_DPIA_CONTROL; - cmd.dig1_dpia_control.header.payload_bytes = - sizeof(cmd.dig1_dpia_control) - - sizeof(cmd.dig1_dpia_control.header); - - cmd.dig1_dpia_control.dpia_control = *dpia_control; - - dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); - - return true; -} - -static void link_encoder_disable(struct dcn10_link_encoder *enc10) -{ - /* reset training complete */ - REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); -} - -void dcn31_link_encoder_enable_dp_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - /* Enable transmitter and encoder. */ - if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { - - DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); - dcn20_link_encoder_enable_dp_output(enc, link_settings, clock_source); - - } else { - - struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; - struct dc_link *link; - - link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); - - enc1_configure_encoder(enc10, link_settings); - - dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_ENABLE; - dpia_control.enc_id = enc->preferred_engine; - dpia_control.mode_laneset.digmode = 0; /* 0 for SST; 5 for MST */ - dpia_control.lanenum = (uint8_t)link_settings->lane_count; - dpia_control.symclk_10khz = link_settings->link_rate * - LINK_RATE_REF_FREQ_IN_KHZ / 10; - /* DIG_BE_CNTL.DIG_HPD_SELECT set to 5 (hpdsel - 1) to indicate HPD pin - * unused by DPIA. - */ - dpia_control.hpdsel = 6; - - if (link) { - dpia_control.dpia_id = link->ddc_hw_inst; - dpia_control.fec_rdy = link->dc->link_srv->dp_should_enable_fec(link); - } else { - DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); - BREAK_TO_DEBUGGER(); - return; - } - - DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); - link_dpia_control(enc->ctx, &dpia_control); - } -} - -void dcn31_link_encoder_enable_dp_mst_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - /* Enable transmitter and encoder. */ - if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { - - DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); - dcn10_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source); - - } else { - - struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; - struct dc_link *link; - - link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); - - enc1_configure_encoder(enc10, link_settings); - - dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_ENABLE; - dpia_control.enc_id = enc->preferred_engine; - dpia_control.mode_laneset.digmode = 5; /* 0 for SST; 5 for MST */ - dpia_control.lanenum = (uint8_t)link_settings->lane_count; - dpia_control.symclk_10khz = link_settings->link_rate * - LINK_RATE_REF_FREQ_IN_KHZ / 10; - /* DIG_BE_CNTL.DIG_HPD_SELECT set to 5 (hpdsel - 1) to indicate HPD pin - * unused by DPIA. - */ - dpia_control.hpdsel = 6; - - if (link) { - dpia_control.dpia_id = link->ddc_hw_inst; - dpia_control.fec_rdy = link->dc->link_srv->dp_should_enable_fec(link); - } else { - DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); - BREAK_TO_DEBUGGER(); - return; - } - - DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); - link_dpia_control(enc->ctx, &dpia_control); - } -} - -void dcn31_link_encoder_disable_output( - struct link_encoder *enc, - enum signal_type signal) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - - /* Disable transmitter and encoder. */ - if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { - - DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); - dcn10_link_encoder_disable_output(enc, signal); - - } else { - - struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; - struct dc_link *link; - - if (enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc)) - return; - - link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); - - dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_DISABLE; - dpia_control.enc_id = enc->preferred_engine; - if (signal == SIGNAL_TYPE_DISPLAY_PORT) { - dpia_control.mode_laneset.digmode = 0; /* 0 for SST; 5 for MST */ - } else if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { - dpia_control.mode_laneset.digmode = 5; /* 0 for SST; 5 for MST */ - } else { - DC_LOG_ERROR("%s: USB4 DPIA only supports DisplayPort.\n", __func__); - BREAK_TO_DEBUGGER(); - } - - if (link) { - dpia_control.dpia_id = link->ddc_hw_inst; - } else { - DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); - BREAK_TO_DEBUGGER(); - return; - } - - DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); - link_dpia_control(enc->ctx, &dpia_control); - - link_encoder_disable(enc10); - } -} - -bool dcn31_link_encoder_is_in_alt_mode(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - union dmub_rb_cmd cmd; - uint32_t dp_alt_mode_disable; - - /* Only applicable to USB-C PHY. */ - if (!enc->features.flags.bits.DP_IS_USB_C) - return false; - - /* - * Use the new interface from DMCUB if available. - * Avoids hanging the RDCPSPIPE if DMCUB wasn't already running. - */ - if (has_query_dp_alt(enc)) { - if (!query_dp_alt_from_dmub(enc, &cmd)) - return false; - - return (cmd.query_dp_alt.data.is_dp_alt_disable == 0); - } - - /* Legacy path, avoid if possible. */ - if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) { - REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, - &dp_alt_mode_disable); - } else { - /* - * B0 phys use a new set of registers to check whether alt mode is disabled. - * if value == 1 alt mode is disabled, otherwise it is enabled. - */ - if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) || - (enc10->base.transmitter == TRANSMITTER_UNIPHY_B) || - (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) { - REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, - &dp_alt_mode_disable); - } else { - REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, - &dp_alt_mode_disable); - } - } - - return (dp_alt_mode_disable == 0); -} - -void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, struct dc_link_settings *link_settings) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - union dmub_rb_cmd cmd; - uint32_t is_in_usb_c_dp4_mode = 0; - - dcn10_link_encoder_get_max_link_cap(enc, link_settings); - - /* Take the link cap directly if not USB */ - if (!enc->features.flags.bits.DP_IS_USB_C) - return; - - /* - * Use the new interface from DMCUB if available. - * Avoids hanging the RDCPSPIPE if DMCUB wasn't already running. - */ - if (has_query_dp_alt(enc)) { - if (!query_dp_alt_from_dmub(enc, &cmd)) - return; - - if (cmd.query_dp_alt.data.is_usb && - cmd.query_dp_alt.data.is_dp4 == 0) - link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); - - return; - } - - /* Legacy path, avoid if possible. */ - if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) { - REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, - &is_in_usb_c_dp4_mode); - } else { - if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) || - (enc10->base.transmitter == TRANSMITTER_UNIPHY_B) || - (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) { - REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, - &is_in_usb_c_dp4_mode); - } else { - REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, - &is_in_usb_c_dp4_mode); - } - } - - if (!is_in_usb_c_dp4_mode) - link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h deleted file mode 100644 index ee78ba80797c..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h +++ /dev/null @@ -1,290 +0,0 @@ -/* - * 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 - * - */ - -#ifndef __DC_LINK_ENCODER__DCN31_H__ -#define __DC_LINK_ENCODER__DCN31_H__ - -#include "dcn30/dcn30_dio_link_encoder.h" - - -#define LE_DCN31_REG_LIST(id)\ - LE_DCN3_REG_LIST(id),\ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(DIO_LINKA_CNTL), \ - SR(DIO_LINKB_CNTL), \ - SR(DIO_LINKC_CNTL), \ - SR(DIO_LINKD_CNTL), \ - SR(DIO_LINKE_CNTL), \ - SR(DIO_LINKF_CNTL) - -#define LINK_ENCODER_MASK_SH_LIST_DCN31(mask_sh) \ - LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\ - LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\ - LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh),\ - LE_SF(DIO_LINKA_CNTL, ENC_TYPE_SEL, mask_sh),\ - LE_SF(DIO_LINKA_CNTL, HPO_DP_ENC_SEL, mask_sh),\ - LE_SF(DIO_LINKA_CNTL, HPO_HDMI_ENC_SEL, mask_sh) - -#define DPCS_DCN31_REG_LIST(id) \ - SRI(TMDS_CTL_BITS, DIG, id), \ - SRI(RDPCSTX_PHY_CNTL3, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL6, RDPCSTX, id), \ - SRI(RDPCSPIPE_PHY_CNTL6, RDPCSPIPE, id), \ - SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL10, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL11, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL12, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL13, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL14, RDPCSTX, id), \ - SRI(RDPCSTX_CNTL, RDPCSTX, id), \ - SRI(RDPCSTX_CLOCK_CNTL, RDPCSTX, id), \ - SRI(RDPCSTX_INTERRUPT_CONTROL, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL2, RDPCSTX, id), \ - SRI(RDPCS_TX_CR_ADDR, RDPCSTX, id), \ - SRI(RDPCS_TX_CR_DATA, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE0, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ - SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ - SR(RDPCSTX0_RDPCSTX_SCRATCH), \ - SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ - SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) - -#define DPCS_DCN31_MASK_SH_LIST(mask_sh)\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_CLK_RDY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DATA_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX0_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX1_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX2_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX3_TERM_CTRL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_MPLLB_MULTIPLIER, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_WIDTH, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_RATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_WIDTH, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_RATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_PSTATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_PSTATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_MPLL_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_MPLL_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ - LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ - LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh),\ - LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_QUOT, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_DEN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL8, RDPCS_PHY_DP_MPLLB_SSC_PEAK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_UP_SPREAD, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_STEPSIZE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL10, RDPCS_PHY_DP_MPLLB_FRACN_REM, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_REF_CLK_MPLLB_DIV, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_HDMI_MPLLB_HDMI_DIV, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_SSC_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_DIV5_CLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_TX_CLK_DIV, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_WORD_DIV2_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_STATE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_CLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_MULTIPLIER, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_FRACN_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_PMIX_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE0_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE1_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE2_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE3_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_EXT_REFCLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_BYPASS, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_CLOCK_ON, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_CLOCK_ON, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_GATE_DIS, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_EN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DISABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_REQ, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_ACK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_RESET, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_CR_MUX_SEL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_REF_RANGE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_BYPASS, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_EXT_LD_DONE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_HDMIMODE_ENABLE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_INIT_DONE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL2, RDPCS_PHY_DP4_POR, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_REG_FIFO_ERROR_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_TX_FIFO_ERROR_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_DISABLE_TOGGLE_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_4LANE_TOGGLE_MASK, mask_sh),\ - LE_SF(RDPCSTX0_RDPCS_TX_CR_ADDR, RDPCS_TX_CR_ADDR, mask_sh),\ - LE_SF(RDPCSTX0_RDPCS_TX_CR_DATA, RDPCS_TX_CR_DATA, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_V2I, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_POST, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_FREQ_VCO, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_INT, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_PROP, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_POST, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_POST, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_MAIN, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_FINETUNE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_RANGE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_PRE, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_POST, mask_sh) - -#define DPCS_DCN314_REG_LIST(id) \ - SRI(TMDS_CTL_BITS, DIG, id), \ - SRI(RDPCSTX_PHY_CNTL3, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL10, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL11, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL12, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL13, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL14, RDPCSTX, id), \ - SRI(RDPCSTX_CNTL, RDPCSTX, id), \ - SRI(RDPCSTX_CLOCK_CNTL, RDPCSTX, id), \ - SRI(RDPCSTX_INTERRUPT_CONTROL, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_CNTL2, RDPCSTX, id), \ - SRI(RDPCS_TX_CR_ADDR, RDPCSTX, id), \ - SRI(RDPCS_TX_CR_DATA, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE0, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ - SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ - SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ - SR(RDPCSTX0_RDPCSTX_SCRATCH), \ - SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ - SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) - -void dcn31_link_encoder_construct( - struct dcn20_link_encoder *enc20, - const struct encoder_init_data *init_data, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - const struct dcn10_link_enc_aux_registers *aux_regs, - const struct dcn10_link_enc_hpd_registers *hpd_regs, - const struct dcn10_link_enc_shift *link_shift, - const struct dcn10_link_enc_mask *link_mask); - -/* - * Create a minimal link encoder object with no dc_link object associated with it. - */ -void dcn31_link_encoder_construct_minimal( - struct dcn20_link_encoder *enc20, - struct dc_context *ctx, - const struct encoder_feature_support *enc_features, - const struct dcn10_link_enc_registers *link_regs, - enum engine_id eng_id); - -void dcn31_link_encoder_set_dio_phy_mux( - struct link_encoder *enc, - enum encoder_type_select sel, - uint32_t hpo_inst); - -/* - * Enable DP transmitter and its encoder. - */ -void dcn31_link_encoder_enable_dp_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source); - -/* - * Enable DP transmitter and its encoder in MST mode. - */ -void dcn31_link_encoder_enable_dp_mst_output( - struct link_encoder *enc, - const struct dc_link_settings *link_settings, - enum clock_source_id clock_source); - -/* - * Disable transmitter and its encoder. - */ -void dcn31_link_encoder_disable_output( - struct link_encoder *enc, - enum signal_type signal); - -/* - * Check whether USB-C DP Alt mode is disabled - */ -bool dcn31_link_encoder_is_in_alt_mode( - struct link_encoder *enc); - -void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, - struct dc_link_settings *link_settings); - -void enc31_hw_init(struct link_encoder *enc); - -#endif /* __DC_LINK_ENCODER__DCN31_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/Makefile b/drivers/gpu/drm/amd/display/dc/dio/Makefile index 5fa905c2fe55..67840e474d7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dio/Makefile @@ -24,6 +24,42 @@ # ifdef CONFIG_DRM_AMD_DC_FP +############################################################################### +# DCN10 +############################################################################### +DIO_DCN10 = dcn10_link_encoder.o dcn10_stream_encoder.o + +AMD_DAL_DIO_DCN10 = $(addprefix $(AMDDALPATH)/dc/dio/dcn10/,$(DIO_DCN10)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN10) + +############################################################################### +# DCN20 +############################################################################### +DIO_DCN20 = dcn20_link_encoder.o dcn20_stream_encoder.o + +AMD_DAL_DIO_DCN20 = $(addprefix $(AMDDALPATH)/dc/dio/dcn20/,$(DIO_DCN20)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN20) + +############################################################################### +# DCN30 +############################################################################### +DIO_DCN30 = dcn30_dio_link_encoder.o dcn30_dio_stream_encoder.o + +AMD_DAL_DIO_DCN30 = $(addprefix $(AMDDALPATH)/dc/dio/dcn30/,$(DIO_DCN30)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN30) + +############################################################################### +# DCN31 +############################################################################### +DIO_DCN31 = dcn31_dio_link_encoder.o + +AMD_DAL_DIO_DCN31 = $(addprefix $(AMDDALPATH)/dc/dio/dcn31/,$(DIO_DCN31)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN31) + ############################################################################### # DCN32 ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c new file mode 100644 index 000000000000..e0558a78b11c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c @@ -0,0 +1,1474 @@ +/* + * 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 "reg_helper.h" + +#include "core_types.h" +#include "link_encoder.h" +#include "dcn10_link_encoder.h" +#include "stream_encoder.h" +#include "dc_bios_types.h" + +#include "gpio_service_interface.h" + +#define CTX \ + enc10->base.ctx +#define DC_LOGGER \ + enc10->base.ctx->logger + +#define REG(reg)\ + (enc10->link_regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc10->link_shift->field_name, enc10->link_mask->field_name + + +/* + * @brief + * Trigger Source Select + * ASIC-dependent, actual values for register programming + */ +#define DCN10_DIG_FE_SOURCE_SELECT_INVALID 0x0 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGA 0x1 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGB 0x2 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGC 0x4 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGD 0x08 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGE 0x10 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGF 0x20 +#define DCN10_DIG_FE_SOURCE_SELECT_DIGG 0x40 + +enum { + DP_MST_UPDATE_MAX_RETRY = 50 +}; + +static const struct link_encoder_funcs dcn10_lnk_enc_funcs = { + .validate_output_with_stream = + dcn10_link_encoder_validate_output_with_stream, + .hw_init = dcn10_link_encoder_hw_init, + .setup = dcn10_link_encoder_setup, + .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, + .enable_dp_output = dcn10_link_encoder_enable_dp_output, + .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, + .disable_output = dcn10_link_encoder_disable_output, + .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dcn10_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dcn10_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, + .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dcn10_link_encoder_enable_hpd, + .disable_hpd = dcn10_link_encoder_disable_hpd, + .is_dig_enabled = dcn10_is_dig_enabled, + .get_dig_frontend = dcn10_get_dig_frontend, + .get_dig_mode = dcn10_get_dig_mode, + .destroy = dcn10_link_encoder_destroy, + .get_max_link_cap = dcn10_link_encoder_get_max_link_cap, +}; + +static enum bp_result link_transmitter_control( + struct dcn10_link_encoder *enc10, + struct bp_transmitter_control *cntl) +{ + enum bp_result result; + struct dc_bios *bp = enc10->base.ctx->dc_bios; + + result = bp->funcs->transmitter_control(bp, cntl); + + return result; +} + +static void enable_phy_bypass_mode( + struct dcn10_link_encoder *enc10, + bool enable) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset + */ + REG_UPDATE(DP_DPHY_CNTL, DPHY_BYPASS, enable); + +} + +static void disable_prbs_symbols( + struct dcn10_link_encoder *enc10, + bool disable) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset + */ + REG_UPDATE_4(DP_DPHY_CNTL, + DPHY_ATEST_SEL_LANE0, disable, + DPHY_ATEST_SEL_LANE1, disable, + DPHY_ATEST_SEL_LANE2, disable, + DPHY_ATEST_SEL_LANE3, disable); +} + +static void disable_prbs_mode( + struct dcn10_link_encoder *enc10) +{ + REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0); +} + +static void program_pattern_symbols( + struct dcn10_link_encoder *enc10, + uint16_t pattern_symbols[8]) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset + */ + REG_SET_3(DP_DPHY_SYM0, 0, + DPHY_SYM1, pattern_symbols[0], + DPHY_SYM2, pattern_symbols[1], + DPHY_SYM3, pattern_symbols[2]); + + /* This register resides in DP back end block; + * transmitter is used for the offset + */ + REG_SET_3(DP_DPHY_SYM1, 0, + DPHY_SYM4, pattern_symbols[3], + DPHY_SYM5, pattern_symbols[4], + DPHY_SYM6, pattern_symbols[5]); + + /* This register resides in DP back end block; + * transmitter is used for the offset + */ + REG_SET_2(DP_DPHY_SYM2, 0, + DPHY_SYM7, pattern_symbols[6], + DPHY_SYM8, pattern_symbols[7]); +} + +static void set_dp_phy_pattern_d102( + struct dcn10_link_encoder *enc10) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc10, false); + + /* For 10-bit PRBS or debug symbols + * please use the following sequence: + * + * Enable debug symbols on the lanes + */ + disable_prbs_symbols(enc10, true); + + /* Disable PRBS mode */ + disable_prbs_mode(enc10); + + /* Program debug symbols to be output */ + { + uint16_t pattern_symbols[8] = { + 0x2AA, 0x2AA, 0x2AA, 0x2AA, + 0x2AA, 0x2AA, 0x2AA, 0x2AA + }; + + program_pattern_symbols(enc10, pattern_symbols); + } + + /* Enable phy bypass mode to enable the test pattern */ + + enable_phy_bypass_mode(enc10, true); +} + +static void set_link_training_complete( + struct dcn10_link_encoder *enc10, + bool complete) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset + */ + REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete); + +} + +void dcn10_link_encoder_set_dp_phy_pattern_training_pattern( + struct link_encoder *enc, + uint32_t index) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + /* Write Training Pattern */ + + REG_WRITE(DP_DPHY_TRAINING_PATTERN_SEL, index); + + /* Set HW Register Training Complete to false */ + + set_link_training_complete(enc10, false); + + /* Disable PHY Bypass mode to output Training Pattern */ + + enable_phy_bypass_mode(enc10, false); + + /* Disable PRBS mode */ + disable_prbs_mode(enc10); +} + +static void setup_panel_mode( + struct dcn10_link_encoder *enc10, + enum dp_panel_mode panel_mode) +{ + uint32_t value; + + if (!REG(DP_DPHY_INTERNAL_CTRL)) + return; + + value = REG_READ(DP_DPHY_INTERNAL_CTRL); + + switch (panel_mode) { + case DP_PANEL_MODE_EDP: + value = 0x1; + break; + case DP_PANEL_MODE_SPECIAL: + value = 0x11; + break; + default: + value = 0x0; + break; + } + + REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); +} + +static void set_dp_phy_pattern_symbol_error( + struct dcn10_link_encoder *enc10) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc10, false); + + /* program correct panel mode*/ + setup_panel_mode(enc10, DP_PANEL_MODE_DEFAULT); + + /* A PRBS23 pattern is used for most DP electrical measurements. */ + + /* Enable PRBS symbols on the lanes */ + disable_prbs_symbols(enc10, false); + + /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */ + REG_UPDATE_2(DP_DPHY_PRBS_CNTL, + DPHY_PRBS_SEL, 1, + DPHY_PRBS_EN, 1); + + /* Enable phy bypass mode to enable the test pattern */ + enable_phy_bypass_mode(enc10, true); +} + +static void set_dp_phy_pattern_prbs7( + struct dcn10_link_encoder *enc10) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc10, false); + + /* A PRBS7 pattern is used for most DP electrical measurements. */ + + /* Enable PRBS symbols on the lanes */ + disable_prbs_symbols(enc10, false); + + /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */ + REG_UPDATE_2(DP_DPHY_PRBS_CNTL, + DPHY_PRBS_SEL, 0, + DPHY_PRBS_EN, 1); + + /* Enable phy bypass mode to enable the test pattern */ + enable_phy_bypass_mode(enc10, true); +} + +static void set_dp_phy_pattern_80bit_custom( + struct dcn10_link_encoder *enc10, + const uint8_t *pattern) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc10, false); + + /* Enable debug symbols on the lanes */ + + disable_prbs_symbols(enc10, true); + + /* Enable PHY bypass mode to enable the test pattern */ + /* TODO is it really needed ? */ + + enable_phy_bypass_mode(enc10, true); + + /* Program 80 bit custom pattern */ + { + uint16_t pattern_symbols[8]; + + pattern_symbols[0] = + ((pattern[1] & 0x03) << 8) | pattern[0]; + pattern_symbols[1] = + ((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f); + pattern_symbols[2] = + ((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f); + pattern_symbols[3] = + (pattern[4] << 2) | ((pattern[3] >> 6) & 0x03); + pattern_symbols[4] = + ((pattern[6] & 0x03) << 8) | pattern[5]; + pattern_symbols[5] = + ((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f); + pattern_symbols[6] = + ((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f); + pattern_symbols[7] = + (pattern[9] << 2) | ((pattern[8] >> 6) & 0x03); + + program_pattern_symbols(enc10, pattern_symbols); + } + + /* Enable phy bypass mode to enable the test pattern */ + + enable_phy_bypass_mode(enc10, true); +} + +static void set_dp_phy_pattern_hbr2_compliance_cp2520_2( + struct dcn10_link_encoder *enc10, + unsigned int cp2520_pattern) +{ + + /* previously there is a register DP_HBR2_EYE_PATTERN + * that is enabled to get the pattern. + * But it does not work with the latest spec change, + * so we are programming the following registers manually. + * + * The following settings have been confirmed + * by Nick Chorney and Sandra Liu + */ + + /* Disable PHY Bypass mode to setup the test pattern */ + + enable_phy_bypass_mode(enc10, false); + + /* Setup DIG encoder in DP SST mode */ + enc10->base.funcs->setup(&enc10->base, SIGNAL_TYPE_DISPLAY_PORT); + + /* ensure normal panel mode. */ + setup_panel_mode(enc10, DP_PANEL_MODE_DEFAULT); + + /* no vbid after BS (SR) + * DP_LINK_FRAMING_CNTL changed history Sandra Liu + * 11000260 / 11000104 / 110000FC + */ + REG_UPDATE_3(DP_LINK_FRAMING_CNTL, + DP_IDLE_BS_INTERVAL, 0xFC, + DP_VBID_DISABLE, 1, + DP_VID_ENHANCED_FRAME_MODE, 1); + + /* swap every BS with SR */ + REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0); + + /* select cp2520 patterns */ + if (REG(DP_DPHY_HBR2_PATTERN_CONTROL)) + REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL, + DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern); + else + /* pre-DCE11 can only generate CP2520 pattern 2 */ + ASSERT(cp2520_pattern == 2); + + /* set link training complete */ + set_link_training_complete(enc10, true); + + /* disable video stream */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); + + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc10, false); +} + +static void set_dp_phy_pattern_passthrough_mode( + struct dcn10_link_encoder *enc10, + enum dp_panel_mode panel_mode) +{ + /* program correct panel mode */ + setup_panel_mode(enc10, panel_mode); + + /* restore LINK_FRAMING_CNTL and DPHY_SCRAMBLER_BS_COUNT + * in case we were doing HBR2 compliance pattern before + */ + REG_UPDATE_3(DP_LINK_FRAMING_CNTL, + DP_IDLE_BS_INTERVAL, 0x2000, + DP_VBID_DISABLE, 0, + DP_VID_ENHANCED_FRAME_MODE, 1); + + REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF); + + /* set link training complete */ + set_link_training_complete(enc10, true); + + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc10, false); + + /* Disable PRBS mode */ + disable_prbs_mode(enc10); +} + +/* return value is bit-vector */ +static uint8_t get_frontend_source( + enum engine_id engine) +{ + switch (engine) { + case ENGINE_ID_DIGA: + return DCN10_DIG_FE_SOURCE_SELECT_DIGA; + case ENGINE_ID_DIGB: + return DCN10_DIG_FE_SOURCE_SELECT_DIGB; + case ENGINE_ID_DIGC: + return DCN10_DIG_FE_SOURCE_SELECT_DIGC; + case ENGINE_ID_DIGD: + return DCN10_DIG_FE_SOURCE_SELECT_DIGD; + case ENGINE_ID_DIGE: + return DCN10_DIG_FE_SOURCE_SELECT_DIGE; + case ENGINE_ID_DIGF: + return DCN10_DIG_FE_SOURCE_SELECT_DIGF; + case ENGINE_ID_DIGG: + return DCN10_DIG_FE_SOURCE_SELECT_DIGG; + default: + ASSERT_CRITICAL(false); + return DCN10_DIG_FE_SOURCE_SELECT_INVALID; + } +} + +unsigned int dcn10_get_dig_frontend(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + int32_t value; + enum engine_id result; + + REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value); + + switch (value) { + case DCN10_DIG_FE_SOURCE_SELECT_DIGA: + result = ENGINE_ID_DIGA; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGB: + result = ENGINE_ID_DIGB; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGC: + result = ENGINE_ID_DIGC; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGD: + result = ENGINE_ID_DIGD; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGE: + result = ENGINE_ID_DIGE; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGF: + result = ENGINE_ID_DIGF; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGG: + result = ENGINE_ID_DIGG; + break; + default: + // invalid source select DIG + result = ENGINE_ID_UNKNOWN; + } + + return result; + +} + +void enc1_configure_encoder( + struct dcn10_link_encoder *enc10, + const struct dc_link_settings *link_settings) +{ + /* set number of lanes */ + REG_SET(DP_CONFIG, 0, + DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE); + + /* setup scrambler */ + REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1); +} + +void dcn10_psr_program_dp_dphy_fast_training(struct link_encoder *enc, + bool exit_link_training_required) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + if (exit_link_training_required) + REG_UPDATE(DP_DPHY_FAST_TRAINING, + DPHY_RX_FAST_TRAINING_CAPABLE, 1); + else { + REG_UPDATE(DP_DPHY_FAST_TRAINING, + DPHY_RX_FAST_TRAINING_CAPABLE, 0); + /*In DCE 11, we are able to pre-program a Force SR register + * to be able to trigger SR symbol after 5 idle patterns + * transmitted. Upon PSR Exit, DMCU can trigger + * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to + * DPHY_LOAD_BS_COUNT_START and the internal counter + * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be + * replaced by SR symbol once. + */ + + REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5); + } +} + +void dcn10_psr_program_secondary_packet(struct link_encoder *enc, + unsigned int sdp_transmit_line_num_deadline) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + REG_UPDATE_2(DP_SEC_CNTL1, + DP_SEC_GSP0_LINE_NUM, sdp_transmit_line_num_deadline, + DP_SEC_GSP0_PRIORITY, 1); +} + +bool dcn10_is_dig_enabled(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t value; + + REG_GET(DIG_BE_EN_CNTL, DIG_ENABLE, &value); + return value; +} + +static void link_encoder_disable(struct dcn10_link_encoder *enc10) +{ + /* reset training pattern */ + REG_SET(DP_DPHY_TRAINING_PATTERN_SEL, 0, + DPHY_TRAINING_PATTERN_SEL, 0); + + /* reset training complete */ + REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); + + /* reset panel mode */ + setup_panel_mode(enc10, DP_PANEL_MODE_DEFAULT); +} + +static void hpd_initialize( + struct dcn10_link_encoder *enc10) +{ + /* Associate HPD with DIG_BE */ + enum hpd_source_id hpd_source = enc10->base.hpd_source; + + REG_UPDATE(DIG_BE_CNTL, DIG_HPD_SELECT, hpd_source); +} + +bool dcn10_link_encoder_validate_dvi_output( + const struct dcn10_link_encoder *enc10, + enum signal_type connector_signal, + enum signal_type signal, + const struct dc_crtc_timing *crtc_timing) +{ + uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK; + + if (signal == SIGNAL_TYPE_DVI_DUAL_LINK) + max_pixel_clock *= 2; + + /* This handles the case of HDMI downgrade to DVI we don't want to + * we don't want to cap the pixel clock if the DDI is not DVI. + */ + if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK && + connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) + max_pixel_clock = enc10->base.features.max_hdmi_pixel_clock; + + /* DVI only support RGB pixel encoding */ + if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) + return false; + + /*connect DVI via adpater's HDMI connector*/ + if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || + connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) && + signal != SIGNAL_TYPE_HDMI_TYPE_A && + crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10)) + return false; + if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) + return false; + + if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10)) + return false; + + /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */ + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_666: + case COLOR_DEPTH_888: + break; + case COLOR_DEPTH_101010: + case COLOR_DEPTH_161616: + if (signal != SIGNAL_TYPE_DVI_DUAL_LINK) + return false; + break; + default: + return false; + } + + return true; +} + +static bool dcn10_link_encoder_validate_hdmi_output( + const struct dcn10_link_encoder *enc10, + const struct dc_crtc_timing *crtc_timing, + const struct dc_edid_caps *edid_caps, + int adjusted_pix_clk_100hz) +{ + enum dc_color_depth max_deep_color = + enc10->base.features.max_hdmi_deep_color; + + // check pixel clock against edid specified max TMDS clk + if (edid_caps->max_tmds_clk_mhz != 0 && + adjusted_pix_clk_100hz > edid_caps->max_tmds_clk_mhz * 10000) + return false; + + if (max_deep_color < crtc_timing->display_color_depth) + return false; + + if (crtc_timing->display_color_depth < COLOR_DEPTH_888) + return false; + if (adjusted_pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) + return false; + + if ((adjusted_pix_clk_100hz == 0) || + (adjusted_pix_clk_100hz > (enc10->base.features.max_hdmi_pixel_clock * 10))) + return false; + + /* DCE11 HW does not support 420 */ + if (!enc10->base.features.hdmi_ycbcr420_supported && + crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) + return false; + + if ((!enc10->base.features.flags.bits.HDMI_6GB_EN || + enc10->base.ctx->dc->debug.hdmi20_disable) && + adjusted_pix_clk_100hz >= 3000000) + return false; + if (enc10->base.ctx->dc->debug.hdmi20_disable && + crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) + return false; + return true; +} + +bool dcn10_link_encoder_validate_dp_output( + const struct dcn10_link_encoder *enc10, + const struct dc_crtc_timing *crtc_timing) +{ + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) { + if (!enc10->base.features.dp_ycbcr420_supported) + return false; + } + + return true; +} + +void dcn10_link_encoder_construct( + struct dcn10_link_encoder *enc10, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask) +{ + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enum bp_result result = BP_RESULT_OK; + + enc10->base.funcs = &dcn10_lnk_enc_funcs; + enc10->base.ctx = init_data->ctx; + enc10->base.id = init_data->encoder; + + enc10->base.hpd_source = init_data->hpd_source; + enc10->base.connector = init_data->connector; + + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc10->base.features = *enc_features; + + enc10->base.transmitter = init_data->transmitter; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc10->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc10->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + enc10->link_regs = link_regs; + enc10->aux_regs = aux_regs; + enc10->hpd_regs = hpd_regs; + enc10->link_shift = link_shift; + enc10->link_mask = link_mask; + + switch (enc10->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc10->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc10->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc10->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc10->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc10->base.preferred_engine = ENGINE_ID_DIGE; + break; + case TRANSMITTER_UNIPHY_F: + enc10->base.preferred_engine = ENGINE_ID_DIGF; + break; + case TRANSMITTER_UNIPHY_G: + enc10->base.preferred_engine = ENGINE_ID_DIGG; + break; + default: + ASSERT_CRITICAL(false); + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + /* default to one to mirror Windows behavior */ + enc10->base.features.flags.bits.HDMI_6GB_EN = 1; + + result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, + enc10->base.id, &bp_cap_info); + + /* Override features with DCE-specific values */ + if (result == BP_RESULT_OK) { + enc10->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_EN; + enc10->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + enc10->base.features.flags.bits.DP_IS_USB_C = + bp_cap_info.DP_IS_USB_C; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, + result); + } + if (enc10->base.ctx->dc->debug.hdmi20_disable) { + enc10->base.features.flags.bits.HDMI_6GB_EN = 0; + } +} + +bool dcn10_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + const struct dc_stream_state *stream) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + bool is_valid; + + //if SCDC (340-600MHz) is disabled, set to HDMI 1.4 timing limit + if (stream->sink->edid_caps.panel_patch.skip_scdc_overwrite && + enc10->base.features.max_hdmi_pixel_clock > 300000) + enc10->base.features.max_hdmi_pixel_clock = 300000; + + switch (stream->signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + is_valid = dcn10_link_encoder_validate_dvi_output( + enc10, + stream->link->connector_signal, + stream->signal, + &stream->timing); + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + is_valid = dcn10_link_encoder_validate_hdmi_output( + enc10, + &stream->timing, + &stream->sink->edid_caps, + stream->phy_pix_clk * 10); + break; + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + is_valid = dcn10_link_encoder_validate_dp_output( + enc10, &stream->timing); + break; + case SIGNAL_TYPE_EDP: + is_valid = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? true : false; + break; + case SIGNAL_TYPE_VIRTUAL: + is_valid = true; + break; + default: + is_valid = false; + break; + } + + return is_valid; +} + +void dcn10_link_encoder_hw_init( + struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + cntl.action = TRANSMITTER_CONTROL_INIT; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc10->base.transmitter; + cntl.connector_obj_id = enc10->base.connector; + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.coherent = false; + cntl.hpd_sel = enc10->base.hpd_source; + + if (enc10->base.connector.id == CONNECTOR_ID_EDP) + cntl.signal = SIGNAL_TYPE_EDP; + + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + return; + } + + if (enc10->base.connector.id == CONNECTOR_ID_LVDS) { + cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS; + + result = link_transmitter_control(enc10, &cntl); + + ASSERT(result == BP_RESULT_OK); + + } + dcn10_aux_initialize(enc10); + + /* reinitialize HPD. + * hpd_initialize() will pass DIG_FE id to HW context. + * All other routine within HW context will use fe_engine_offset + * as DIG_FE id even caller pass DIG_FE id. + * So this routine must be called first. + */ + hpd_initialize(enc10); +} + +void dcn10_link_encoder_destroy(struct link_encoder **enc) +{ + kfree(TO_DCN10_LINK_ENC(*enc)); + *enc = NULL; +} + +void dcn10_link_encoder_setup( + struct link_encoder *enc, + enum signal_type signal) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + switch (signal) { + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT: + /* DP SST */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 0); + break; + case SIGNAL_TYPE_LVDS: + /* LVDS */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 1); + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + /* TMDS-DVI */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 2); + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + /* TMDS-HDMI */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 3); + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + /* DP MST */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 5); + break; + default: + ASSERT_CRITICAL(false); + /* invalid mode ! */ + break; + } + +} + +/* TODO: still need depth or just pass in adjusted pixel clock? */ +void dcn10_link_encoder_enable_tmds_output( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + enum signal_type signal, + uint32_t pixel_clock) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = enc->preferred_engine; + cntl.transmitter = enc10->base.transmitter; + cntl.pll_id = clock_source; + cntl.signal = signal; + if (cntl.signal == SIGNAL_TYPE_DVI_DUAL_LINK) + cntl.lanes_number = 8; + else + cntl.lanes_number = 4; + + cntl.hpd_sel = enc10->base.hpd_source; + + cntl.pixel_clock = pixel_clock; + cntl.color_depth = color_depth; + + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} + +void dcn10_link_encoder_enable_tmds_output_with_clk_pattern_wa( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + enum signal_type signal, + uint32_t pixel_clock) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + dcn10_link_encoder_enable_tmds_output( + enc, clock_source, color_depth, signal, pixel_clock); + + REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); +} + +/* enables DP PHY output */ +void dcn10_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + /* number_of_lanes is used for pixel clock adjust, + * but it's not passed to asic_control. + * We need to set number of lanes manually. + */ + enc1_configure_encoder(enc10, link_settings); + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = enc->preferred_engine; + cntl.transmitter = enc10->base.transmitter; + cntl.pll_id = clock_source; + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc10->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate + * LINK_RATE_REF_FREQ_IN_KHZ; + /* TODO: check if undefined works */ + cntl.color_depth = COLOR_DEPTH_UNDEFINED; + + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} + +/* enables DP PHY output in MST mode */ +void dcn10_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + /* number_of_lanes is used for pixel clock adjust, + * but it's not passed to asic_control. + * We need to set number of lanes manually. + */ + enc1_configure_encoder(enc10, link_settings); + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc10->base.transmitter; + cntl.pll_id = clock_source; + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc10->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate + * LINK_RATE_REF_FREQ_IN_KHZ; + /* TODO: check if undefined works */ + cntl.color_depth = COLOR_DEPTH_UNDEFINED; + + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} +/* + * @brief + * Disable transmitter and its encoder + */ +void dcn10_link_encoder_disable_output( + struct link_encoder *enc, + enum signal_type signal) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + if (enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc)) { + /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */ + /*in DP_Alt_No_Connect case, we turn off the dig already, + after excuation the PHY w/a sequence, not allow touch PHY any more*/ + return; + } + /* Power-down RX and disable GPU PHY should be paired. + * Disabling PHY without powering down RX may cause + * symbol lock loss, on which we will get DP Sink interrupt. + */ + + /* There is a case for the DP active dongles + * where we want to disable the PHY but keep RX powered, + * for those we need to ignore DP Sink interrupt + * by checking lane count that has been set + * on the last do_enable_output(). + */ + + /* disable transmitter */ + cntl.action = TRANSMITTER_CONTROL_DISABLE; + cntl.transmitter = enc10->base.transmitter; + cntl.hpd_sel = enc10->base.hpd_source; + cntl.signal = signal; + cntl.connector_obj_id = enc10->base.connector; + + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + return; + } + + /* disable encoder */ + if (dc_is_dp_signal(signal)) + link_encoder_disable(enc10); +} + +void dcn10_link_encoder_dp_set_lane_settings( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + union dpcd_training_lane_set training_lane_set = { { 0 } }; + int32_t lane = 0; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + if (!link_settings) { + BREAK_TO_DEBUGGER(); + return; + } + + cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS; + cntl.transmitter = enc10->base.transmitter; + cntl.connector_obj_id = enc10->base.connector; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc10->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_KHZ; + + for (lane = 0; lane < link_settings->lane_count; lane++) { + /* translate lane settings */ + + training_lane_set.bits.VOLTAGE_SWING_SET = + lane_settings[lane].VOLTAGE_SWING; + training_lane_set.bits.PRE_EMPHASIS_SET = + lane_settings[lane].PRE_EMPHASIS; + + /* post cursor 2 setting only applies to HBR2 link rate */ + if (link_settings->link_rate == LINK_RATE_HIGH2) { + /* this is passed to VBIOS + * to program post cursor 2 level + */ + training_lane_set.bits.POST_CURSOR2_SET = + lane_settings[lane].POST_CURSOR2; + } + + cntl.lane_select = lane; + cntl.lane_settings = training_lane_set.raw; + + /* call VBIOS table to set voltage swing and pre-emphasis */ + result = link_transmitter_control(enc10, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", __func__); + BREAK_TO_DEBUGGER(); + } + } +} + +/* set DP PHY test and training patterns */ +void dcn10_link_encoder_dp_set_phy_pattern( + struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *param) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + switch (param->dp_phy_pattern) { + case DP_TEST_PATTERN_TRAINING_PATTERN1: + dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN2: + dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN3: + dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN4: + dcn10_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3); + break; + case DP_TEST_PATTERN_D102: + set_dp_phy_pattern_d102(enc10); + break; + case DP_TEST_PATTERN_SYMBOL_ERROR: + set_dp_phy_pattern_symbol_error(enc10); + break; + case DP_TEST_PATTERN_PRBS7: + set_dp_phy_pattern_prbs7(enc10); + break; + case DP_TEST_PATTERN_80BIT_CUSTOM: + set_dp_phy_pattern_80bit_custom( + enc10, param->custom_pattern); + break; + case DP_TEST_PATTERN_CP2520_1: + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc10, 1); + break; + case DP_TEST_PATTERN_CP2520_2: + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc10, 2); + break; + case DP_TEST_PATTERN_CP2520_3: + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc10, 3); + break; + case DP_TEST_PATTERN_VIDEO_MODE: { + set_dp_phy_pattern_passthrough_mode( + enc10, param->dp_panel_mode); + break; + } + + default: + /* invalid phy pattern */ + ASSERT_CRITICAL(false); + break; + } +} + +static void fill_stream_allocation_row_info( + const struct link_mst_stream_allocation *stream_allocation, + uint32_t *src, + uint32_t *slots) +{ + const struct stream_encoder *stream_enc = stream_allocation->stream_enc; + + if (stream_enc) { + *src = stream_enc->id; + *slots = stream_allocation->slot_count; + } else { + *src = 0; + *slots = 0; + } +} + +/* programs DP MST VC payload allocation */ +void dcn10_link_encoder_update_mst_stream_allocation_table( + struct link_encoder *enc, + const struct link_mst_stream_allocation_table *table) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t value1 = 0; + uint32_t value2 = 0; + uint32_t slots = 0; + uint32_t src = 0; + uint32_t retries = 0; + + /* For CZ, there are only 3 pipes. So Virtual channel is up 3.*/ + + /* --- Set MSE Stream Attribute - + * Setup VC Payload Table on Tx Side, + * Issue allocation change trigger + * to commit payload on both tx and rx side + */ + + /* we should clean-up table each time */ + + if (table->stream_count >= 1) { + fill_stream_allocation_row_info( + &table->stream_allocations[0], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT0, + DP_MSE_SAT_SRC0, src, + DP_MSE_SAT_SLOT_COUNT0, slots); + + if (table->stream_count >= 2) { + fill_stream_allocation_row_info( + &table->stream_allocations[1], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT0, + DP_MSE_SAT_SRC1, src, + DP_MSE_SAT_SLOT_COUNT1, slots); + + if (table->stream_count >= 3) { + fill_stream_allocation_row_info( + &table->stream_allocations[2], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT1, + DP_MSE_SAT_SRC2, src, + DP_MSE_SAT_SLOT_COUNT2, slots); + + if (table->stream_count >= 4) { + fill_stream_allocation_row_info( + &table->stream_allocations[3], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT1, + DP_MSE_SAT_SRC3, src, + DP_MSE_SAT_SLOT_COUNT3, slots); + + /* --- wait for transaction finish */ + + /* send allocation change trigger (ACT) ? + * this step first sends the ACT, + * then double buffers the SAT into the hardware + * making the new allocation active on the DP MST mode link + */ + + /* DP_MSE_SAT_UPDATE: + * 0 - No Action + * 1 - Update SAT with trigger + * 2 - Update SAT without trigger + */ + REG_UPDATE(DP_MSE_SAT_UPDATE, + DP_MSE_SAT_UPDATE, 1); + + /* wait for update to complete + * (i.e. DP_MSE_SAT_UPDATE field is reset to 0) + * then wait for the transmission + * of at least 16 MTP headers on immediate local link. + * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 0 + * a value of 1 indicates that DP MST mode + * is in the 16 MTP keepout region after a VC has been added. + * MST stream bandwidth (VC rate) can be configured + * after this bit is cleared + */ + do { + udelay(10); + + REG_READ(DP_MSE_SAT_UPDATE); + + REG_GET(DP_MSE_SAT_UPDATE, + DP_MSE_SAT_UPDATE, &value1); + + REG_GET(DP_MSE_SAT_UPDATE, + DP_MSE_16_MTP_KEEPOUT, &value2); + + /* bit field DP_MSE_SAT_UPDATE is set to 1 already */ + if (!value1 && !value2) + break; + ++retries; + } while (retries < DP_MST_UPDATE_MAX_RETRY); +} + +void dcn10_link_encoder_connect_dig_be_to_fe( + struct link_encoder *enc, + enum engine_id engine, + bool connect) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t field; + + if (engine != ENGINE_ID_UNKNOWN) { + + REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &field); + + if (connect) + field |= get_frontend_source(engine); + else + field &= ~get_frontend_source(engine); + + REG_UPDATE(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, field); + } +} + + +#define HPD_REG(reg)\ + (enc10->hpd_regs->reg) + +#define HPD_REG_READ(reg_name) \ + dm_read_reg(CTX, HPD_REG(reg_name)) + +#define HPD_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_ex(CTX, \ + HPD_REG(reg_name), \ + n, __VA_ARGS__) + +#define HPD_REG_UPDATE(reg_name, field, val) \ + HPD_REG_UPDATE_N(reg_name, 1, \ + FN(reg_name, field), val) + +void dcn10_link_encoder_enable_hpd(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + HPD_REG_UPDATE(DC_HPD_CONTROL, + DC_HPD_EN, 1); +} + +void dcn10_link_encoder_disable_hpd(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + HPD_REG_UPDATE(DC_HPD_CONTROL, + DC_HPD_EN, 0); +} + +#define AUX_REG(reg)\ + (enc10->aux_regs->reg) + +#define AUX_REG_READ(reg_name) \ + dm_read_reg(CTX, AUX_REG(reg_name)) + +#define AUX_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_ex(CTX, \ + AUX_REG(reg_name), \ + n, __VA_ARGS__) + +#define AUX_REG_UPDATE(reg_name, field, val) \ + AUX_REG_UPDATE_N(reg_name, 1, \ + FN(reg_name, field), val) + +#define AUX_REG_UPDATE_2(reg, f1, v1, f2, v2) \ + AUX_REG_UPDATE_N(reg, 2,\ + FN(reg, f1), v1,\ + FN(reg, f2), v2) + +void dcn10_aux_initialize(struct dcn10_link_encoder *enc10) +{ + enum hpd_source_id hpd_source = enc10->base.hpd_source; + + AUX_REG_UPDATE_2(AUX_CONTROL, + AUX_HPD_SEL, hpd_source, + AUX_LS_READ_EN, 0); + + /* 1/4 window (the maximum allowed) */ + AUX_REG_UPDATE(AUX_DPHY_RX_CONTROL0, + AUX_RX_RECEIVE_WINDOW, 0); +} + +enum signal_type dcn10_get_dig_mode( + struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t value; + REG_GET(DIG_BE_CNTL, DIG_MODE, &value); + switch (value) { + case 1: + return SIGNAL_TYPE_DISPLAY_PORT; + case 2: + return SIGNAL_TYPE_DVI_SINGLE_LINK; + case 3: + return SIGNAL_TYPE_HDMI_TYPE_A; + case 5: + return SIGNAL_TYPE_DISPLAY_PORT_MST; + default: + return SIGNAL_TYPE_NONE; + } +} + +void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc, + struct dc_link_settings *link_settings) +{ + /* Set Default link settings */ + struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH, + LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0}; + + /* Higher link settings based on feature supported */ + if (enc->features.flags.bits.IS_HBR2_CAPABLE) + max_link_cap.link_rate = LINK_RATE_HIGH2; + + if (enc->features.flags.bits.IS_HBR3_CAPABLE) + max_link_cap.link_rate = LINK_RATE_HIGH3; + + if (enc->features.flags.bits.IS_UHBR10_CAPABLE) + max_link_cap.link_rate = LINK_RATE_UHBR10; + + if (enc->features.flags.bits.IS_UHBR13_5_CAPABLE) + max_link_cap.link_rate = LINK_RATE_UHBR13_5; + + if (enc->features.flags.bits.IS_UHBR20_CAPABLE) + max_link_cap.link_rate = LINK_RATE_UHBR20; + + *link_settings = max_link_cap; +} diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h new file mode 100644 index 000000000000..b7a89c39f445 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h @@ -0,0 +1,659 @@ +/* + * 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 + * + */ + +#ifndef __DC_LINK_ENCODER__DCN10_H__ +#define __DC_LINK_ENCODER__DCN10_H__ + +#include "link_encoder.h" + +#define TO_DCN10_LINK_ENC(link_encoder)\ + container_of(link_encoder, struct dcn10_link_encoder, base) + +#define AUX_REG_LIST(id)\ + SRI(AUX_CONTROL, DP_AUX, id), \ + SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \ + SRI(AUX_DPHY_RX_CONTROL1, DP_AUX, id) + +#define HPD_REG_LIST(id)\ + SRI(DC_HPD_CONTROL, HPD, id) + +#define LE_DCN_COMMON_REG_LIST(id) \ + SRI(DIG_BE_CNTL, DIG, id), \ + SRI(DIG_BE_EN_CNTL, DIG, id), \ + SRI(DIG_CLOCK_PATTERN, DIG, id), \ + SRI(TMDS_CTL_BITS, DIG, id), \ + SRI(DP_CONFIG, DP, id), \ + SRI(DP_DPHY_CNTL, DP, id), \ + SRI(DP_DPHY_PRBS_CNTL, DP, id), \ + SRI(DP_DPHY_SCRAM_CNTL, DP, id),\ + SRI(DP_DPHY_SYM0, DP, id), \ + SRI(DP_DPHY_SYM1, DP, id), \ + SRI(DP_DPHY_SYM2, DP, id), \ + SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ + SRI(DP_LINK_CNTL, DP, id), \ + SRI(DP_LINK_FRAMING_CNTL, DP, id), \ + SRI(DP_MSE_SAT0, DP, id), \ + SRI(DP_MSE_SAT1, DP, id), \ + SRI(DP_MSE_SAT2, DP, id), \ + SRI(DP_MSE_SAT_UPDATE, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_DPHY_FAST_TRAINING, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) + + +#define LE_DCN10_REG_LIST(id)\ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + LE_DCN_COMMON_REG_LIST(id) + +struct dcn10_link_enc_aux_registers { + uint32_t AUX_CONTROL; + uint32_t AUX_DPHY_RX_CONTROL0; + uint32_t AUX_DPHY_TX_CONTROL; + uint32_t AUX_DPHY_RX_CONTROL1; +}; + +struct dcn10_link_enc_hpd_registers { + uint32_t DC_HPD_CONTROL; +}; + +struct dcn10_link_enc_registers { + uint32_t DIG_BE_CNTL; + uint32_t DIG_BE_EN_CNTL; + uint32_t DIG_CLOCK_PATTERN; + uint32_t DP_CONFIG; + uint32_t DP_DPHY_CNTL; + uint32_t DP_DPHY_INTERNAL_CTRL; + uint32_t DP_DPHY_PRBS_CNTL; + uint32_t DP_DPHY_SCRAM_CNTL; + uint32_t DP_DPHY_SYM0; + uint32_t DP_DPHY_SYM1; + uint32_t DP_DPHY_SYM2; + uint32_t DP_DPHY_TRAINING_PATTERN_SEL; + uint32_t DP_LINK_CNTL; + uint32_t DP_LINK_FRAMING_CNTL; + uint32_t DP_MSE_SAT0; + uint32_t DP_MSE_SAT1; + uint32_t DP_MSE_SAT2; + uint32_t DP_MSE_SAT_UPDATE; + uint32_t DP_SEC_CNTL; + uint32_t DP_VID_STREAM_CNTL; + uint32_t DP_DPHY_FAST_TRAINING; + uint32_t DP_DPHY_BS_SR_SWAP_CNTL; + uint32_t DP_DPHY_HBR2_PATTERN_CONTROL; + uint32_t DP_SEC_CNTL1; + uint32_t TMDS_CTL_BITS; + /* DCCG */ + uint32_t CLOCK_ENABLE; + /* DIG */ + uint32_t DIG_LANE_ENABLE; + /* UNIPHY */ + uint32_t CHANNEL_XBAR_CNTL; + /* DPCS */ + uint32_t RDPCSTX_PHY_CNTL3; + uint32_t RDPCSTX_PHY_CNTL4; + uint32_t RDPCSTX_PHY_CNTL5; + uint32_t RDPCSTX_PHY_CNTL6; + uint32_t RDPCSPIPE_PHY_CNTL6; + uint32_t RDPCSTX_PHY_CNTL7; + uint32_t RDPCSTX_PHY_CNTL8; + uint32_t RDPCSTX_PHY_CNTL9; + uint32_t RDPCSTX_PHY_CNTL10; + uint32_t RDPCSTX_PHY_CNTL11; + uint32_t RDPCSTX_PHY_CNTL12; + uint32_t RDPCSTX_PHY_CNTL13; + uint32_t RDPCSTX_PHY_CNTL14; + uint32_t RDPCSTX_PHY_CNTL15; + uint32_t RDPCSTX_CNTL; + uint32_t RDPCSTX_CLOCK_CNTL; + uint32_t RDPCSTX_PHY_CNTL0; + uint32_t RDPCSTX_PHY_CNTL2; + uint32_t RDPCSTX_PLL_UPDATE_DATA; + uint32_t RDPCS_TX_CR_ADDR; + uint32_t RDPCS_TX_CR_DATA; + uint32_t DPCSTX_TX_CLOCK_CNTL; + uint32_t DPCSTX_TX_CNTL; + uint32_t RDPCSTX_INTERRUPT_CONTROL; + uint32_t RDPCSTX_PHY_FUSE0; + uint32_t RDPCSTX_PHY_FUSE1; + uint32_t RDPCSTX_PHY_FUSE2; + uint32_t RDPCSTX_PHY_FUSE3; + uint32_t RDPCSTX_PHY_RX_LD_VAL; + uint32_t DPCSTX_DEBUG_CONFIG; + uint32_t RDPCSTX_DEBUG_CONFIG; + uint32_t RDPCSTX0_RDPCSTX_SCRATCH; + uint32_t RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG; + uint32_t DCIO_SOFT_RESET; + /* indirect registers */ + uint32_t RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_2; + uint32_t RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_3; + uint32_t RAWLANE1_DIG_PCS_XF_RX_OVRD_IN_2; + uint32_t RAWLANE1_DIG_PCS_XF_RX_OVRD_IN_3; + uint32_t RAWLANE2_DIG_PCS_XF_RX_OVRD_IN_2; + uint32_t RAWLANE2_DIG_PCS_XF_RX_OVRD_IN_3; + uint32_t RAWLANE3_DIG_PCS_XF_RX_OVRD_IN_2; + uint32_t RAWLANE3_DIG_PCS_XF_RX_OVRD_IN_3; + uint32_t TMDS_DCBALANCER_CONTROL; + uint32_t PHYA_LINK_CNTL2; + uint32_t PHYB_LINK_CNTL2; + uint32_t PHYC_LINK_CNTL2; + uint32_t DIO_LINKA_CNTL; + uint32_t DIO_LINKB_CNTL; + uint32_t DIO_LINKC_CNTL; + uint32_t DIO_LINKD_CNTL; + uint32_t DIO_LINKE_CNTL; + uint32_t DIO_LINKF_CNTL; + uint32_t DIO_CLK_CNTL; + uint32_t DIG_BE_CLK_CNTL; +}; + +#define LE_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh)\ + LE_SF(DIG0_DIG_BE_EN_CNTL, DIG_ENABLE, mask_sh),\ + LE_SF(DIG0_DIG_BE_CNTL, DIG_HPD_SELECT, mask_sh),\ + LE_SF(DIG0_DIG_BE_CNTL, DIG_MODE, mask_sh),\ + LE_SF(DIG0_DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, mask_sh),\ + LE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\ + LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_BYPASS, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE0, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE1, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE2, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE3, mask_sh),\ + LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, mask_sh),\ + LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM1, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM2, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM3, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM4, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM5, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM6, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM7, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM8, mask_sh),\ + LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, mask_sh),\ + LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, mask_sh),\ + LE_SF(DP0_DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, mask_sh),\ + LE_SF(DP0_DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, mask_sh),\ + LE_SF(DP0_DP_DPHY_TRAINING_PATTERN_SEL, DPHY_TRAINING_PATTERN_SEL, mask_sh),\ + LE_SF(DP0_DP_DPHY_HBR2_PATTERN_CONTROL, DP_DPHY_HBR2_PATTERN_CONTROL, mask_sh),\ + LE_SF(DP0_DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, mask_sh),\ + LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL, mask_sh),\ + LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE, mask_sh),\ + LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE, mask_sh),\ + LE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + LE_SF(DP0_DP_CONFIG, DP_UDI_LANES, mask_sh),\ + LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_LINE_NUM, mask_sh),\ + LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_PRIORITY, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC0, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC1, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT0, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT1, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC2, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC3, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT2, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT3, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_SAT_UPDATE, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_16_MTP_KEEPOUT, mask_sh),\ + LE_SF(DP_AUX0_AUX_CONTROL, AUX_HPD_SEL, mask_sh),\ + LE_SF(DP_AUX0_AUX_CONTROL, AUX_LS_READ_EN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW, mask_sh),\ + LE_SF(HPD0_DC_HPD_CONTROL, DC_HPD_EN, mask_sh) + +#define DCN_LINK_ENCODER_REG_FIELD_LIST(type) \ + type DIG_ENABLE;\ + type DIG_HPD_SELECT;\ + type DIG_MODE;\ + type DIG_FE_SOURCE_SELECT;\ + type DIG_CLOCK_PATTERN;\ + type DPHY_BYPASS;\ + type DPHY_ATEST_SEL_LANE0;\ + type DPHY_ATEST_SEL_LANE1;\ + type DPHY_ATEST_SEL_LANE2;\ + type DPHY_ATEST_SEL_LANE3;\ + type DPHY_PRBS_EN;\ + type DPHY_PRBS_SEL;\ + type DPHY_SYM1;\ + type DPHY_SYM2;\ + type DPHY_SYM3;\ + type DPHY_SYM4;\ + type DPHY_SYM5;\ + type DPHY_SYM6;\ + type DPHY_SYM7;\ + type DPHY_SYM8;\ + type DPHY_SCRAMBLER_BS_COUNT;\ + type DPHY_SCRAMBLER_ADVANCE;\ + type DPHY_RX_FAST_TRAINING_CAPABLE;\ + type DPHY_LOAD_BS_COUNT;\ + type DPHY_TRAINING_PATTERN_SEL;\ + type DP_DPHY_HBR2_PATTERN_CONTROL;\ + type DP_LINK_TRAINING_COMPLETE;\ + type DP_IDLE_BS_INTERVAL;\ + type DP_VBID_DISABLE;\ + type DP_VID_ENHANCED_FRAME_MODE;\ + type DP_VID_STREAM_ENABLE;\ + type DP_UDI_LANES;\ + type DP_SEC_GSP0_LINE_NUM;\ + type DP_SEC_GSP0_PRIORITY;\ + type DP_MSE_SAT_SRC0;\ + type DP_MSE_SAT_SRC1;\ + type DP_MSE_SAT_SRC2;\ + type DP_MSE_SAT_SRC3;\ + type DP_MSE_SAT_SLOT_COUNT0;\ + type DP_MSE_SAT_SLOT_COUNT1;\ + type DP_MSE_SAT_SLOT_COUNT2;\ + type DP_MSE_SAT_SLOT_COUNT3;\ + type DP_MSE_SAT_UPDATE;\ + type DP_MSE_16_MTP_KEEPOUT;\ + type DC_HPD_EN;\ + type TMDS_CTL0;\ + type AUX_HPD_SEL;\ + type AUX_LS_READ_EN;\ + type AUX_RX_RECEIVE_WINDOW + + +#define DCN20_LINK_ENCODER_DPCS_REG_FIELD_LIST(type) \ + type RDPCS_PHY_DP_TX0_DATA_EN;\ + type RDPCS_PHY_DP_TX1_DATA_EN;\ + type RDPCS_PHY_DP_TX2_DATA_EN;\ + type RDPCS_PHY_DP_TX3_DATA_EN;\ + type RDPCS_PHY_DP_TX0_PSTATE;\ + type RDPCS_PHY_DP_TX1_PSTATE;\ + type RDPCS_PHY_DP_TX2_PSTATE;\ + type RDPCS_PHY_DP_TX3_PSTATE;\ + type RDPCS_PHY_DP_TX0_MPLL_EN;\ + type RDPCS_PHY_DP_TX1_MPLL_EN;\ + type RDPCS_PHY_DP_TX2_MPLL_EN;\ + type RDPCS_PHY_DP_TX3_MPLL_EN;\ + type RDPCS_TX_FIFO_LANE0_EN;\ + type RDPCS_TX_FIFO_LANE1_EN;\ + type RDPCS_TX_FIFO_LANE2_EN;\ + type RDPCS_TX_FIFO_LANE3_EN;\ + type RDPCS_EXT_REFCLK_EN;\ + type RDPCS_TX_FIFO_EN;\ + type UNIPHY_LINK_ENABLE;\ + type UNIPHY_CHANNEL0_XBAR_SOURCE;\ + type UNIPHY_CHANNEL1_XBAR_SOURCE;\ + type UNIPHY_CHANNEL2_XBAR_SOURCE;\ + type UNIPHY_CHANNEL3_XBAR_SOURCE;\ + type UNIPHY_CHANNEL0_INVERT;\ + type UNIPHY_CHANNEL1_INVERT;\ + type UNIPHY_CHANNEL2_INVERT;\ + type UNIPHY_CHANNEL3_INVERT;\ + type UNIPHY_LINK_ENABLE_HPD_MASK;\ + type UNIPHY_LANE_STAGGER_DELAY;\ + type RDPCS_SRAMCLK_BYPASS;\ + type RDPCS_SRAMCLK_EN;\ + type RDPCS_SRAMCLK_CLOCK_ON;\ + type DPCS_TX_FIFO_EN;\ + type RDPCS_PHY_DP_TX0_DISABLE;\ + type RDPCS_PHY_DP_TX1_DISABLE;\ + type RDPCS_PHY_DP_TX2_DISABLE;\ + type RDPCS_PHY_DP_TX3_DISABLE;\ + type RDPCS_PHY_DP_TX0_CLK_RDY;\ + type RDPCS_PHY_DP_TX1_CLK_RDY;\ + type RDPCS_PHY_DP_TX2_CLK_RDY;\ + type RDPCS_PHY_DP_TX3_CLK_RDY;\ + type RDPCS_PHY_DP_TX0_REQ;\ + type RDPCS_PHY_DP_TX1_REQ;\ + type RDPCS_PHY_DP_TX2_REQ;\ + type RDPCS_PHY_DP_TX3_REQ;\ + type RDPCS_PHY_DP_TX0_ACK;\ + type RDPCS_PHY_DP_TX1_ACK;\ + type RDPCS_PHY_DP_TX2_ACK;\ + type RDPCS_PHY_DP_TX3_ACK;\ + type RDPCS_PHY_DP_TX0_RESET;\ + type RDPCS_PHY_DP_TX1_RESET;\ + type RDPCS_PHY_DP_TX2_RESET;\ + type RDPCS_PHY_DP_TX3_RESET;\ + type RDPCS_PHY_RESET;\ + type RDPCS_PHY_CR_MUX_SEL;\ + type RDPCS_PHY_REF_RANGE;\ + type RDPCS_PHY_DP4_POR;\ + type RDPCS_SRAM_BYPASS;\ + type RDPCS_SRAM_EXT_LD_DONE;\ + type RDPCS_PHY_DP_TX0_TERM_CTRL;\ + type RDPCS_PHY_DP_TX1_TERM_CTRL;\ + type RDPCS_PHY_DP_TX2_TERM_CTRL;\ + type RDPCS_PHY_DP_TX3_TERM_CTRL;\ + type RDPCS_PHY_DP_REF_CLK_MPLLB_DIV;\ + type RDPCS_PHY_DP_MPLLB_MULTIPLIER;\ + type RDPCS_PHY_DP_MPLLB_SSC_EN;\ + type RDPCS_PHY_DP_MPLLB_DIV5_CLK_EN;\ + type RDPCS_PHY_DP_MPLLB_TX_CLK_DIV;\ + type RDPCS_PHY_DP_MPLLB_WORD_DIV2_EN;\ + type RDPCS_PHY_DP_MPLLB_FRACN_EN;\ + type RDPCS_PHY_DP_MPLLB_PMIX_EN;\ + type RDPCS_PHY_DP_MPLLB_FRACN_QUOT;\ + type RDPCS_PHY_DP_MPLLB_FRACN_DEN;\ + type RDPCS_PHY_DP_MPLLB_FRACN_REM;\ + type RDPCS_PHY_DP_MPLLB_SSC_UP_SPREAD;\ + type RDPCS_PHY_DP_MPLLB_SSC_STEPSIZE;\ + type RDPCS_PHY_DP_MPLLB_SSC_PEAK;\ + type RDPCS_PHY_DP_MPLLB_DIV_CLK_EN;\ + type RDPCS_PHY_DP_MPLLB_DIV_MULTIPLIER;\ + type RDPCS_PHY_TX_VBOOST_LVL;\ + type RDPCS_PHY_HDMIMODE_ENABLE;\ + type RDPCS_PHY_DP_REF_CLK_EN;\ + type RDPCS_PLL_UPDATE_DATA;\ + type RDPCS_SRAM_INIT_DONE;\ + type RDPCS_TX_CR_ADDR;\ + type RDPCS_TX_CR_DATA;\ + type RDPCS_PHY_HDMI_MPLLB_HDMI_DIV;\ + type RDPCS_PHY_DP_MPLLB_STATE;\ + type RDPCS_PHY_DP_TX0_WIDTH;\ + type RDPCS_PHY_DP_TX0_RATE;\ + type RDPCS_PHY_DP_TX1_WIDTH;\ + type RDPCS_PHY_DP_TX1_RATE;\ + type RDPCS_PHY_DP_TX2_WIDTH;\ + type RDPCS_PHY_DP_TX2_RATE;\ + type RDPCS_PHY_DP_TX3_WIDTH;\ + type RDPCS_PHY_DP_TX3_RATE;\ + type DPCS_SYMCLK_CLOCK_ON;\ + type DPCS_SYMCLK_GATE_DIS;\ + type DPCS_SYMCLK_EN;\ + type RDPCS_SYMCLK_DIV2_CLOCK_ON;\ + type RDPCS_SYMCLK_DIV2_GATE_DIS;\ + type RDPCS_SYMCLK_DIV2_EN;\ + type DPCS_TX_DATA_SWAP;\ + type DPCS_TX_DATA_ORDER_INVERT;\ + type DPCS_TX_FIFO_RD_START_DELAY;\ + type RDPCS_TX_FIFO_RD_START_DELAY;\ + type RDPCS_REG_FIFO_ERROR_MASK;\ + type RDPCS_TX_FIFO_ERROR_MASK;\ + type RDPCS_DPALT_DISABLE_TOGGLE_MASK;\ + type RDPCS_DPALT_4LANE_TOGGLE_MASK;\ + type RDPCS_PHY_DPALT_DP4;\ + type RDPCS_PHY_DPALT_DISABLE;\ + type RDPCS_PHY_DPALT_DISABLE_ACK;\ + type RDPCS_PHY_DP_MPLLB_V2I;\ + type RDPCS_PHY_DP_MPLLB_FREQ_VCO;\ + type RDPCS_PHY_DP_MPLLB_CP_INT_GS;\ + type RDPCS_PHY_RX_VREF_CTRL;\ + type RDPCS_PHY_DP_MPLLB_CP_INT;\ + type RDPCS_PHY_DP_MPLLB_CP_PROP;\ + type RDPCS_PHY_RX_REF_LD_VAL;\ + type RDPCS_PHY_RX_VCO_LD_VAL;\ + type DPCSTX_DEBUG_CONFIG; \ + type RDPCSTX_DEBUG_CONFIG; \ + type RDPCS_PHY_DP_TX0_EQ_MAIN;\ + type RDPCS_PHY_DP_TX0_EQ_PRE;\ + type RDPCS_PHY_DP_TX0_EQ_POST;\ + type RDPCS_PHY_DP_TX1_EQ_MAIN;\ + type RDPCS_PHY_DP_TX1_EQ_PRE;\ + type RDPCS_PHY_DP_TX1_EQ_POST;\ + type RDPCS_PHY_DP_TX2_EQ_MAIN;\ + type RDPCS_PHY_DP_MPLLB_CP_PROP_GS;\ + type RDPCS_PHY_DP_TX2_EQ_PRE;\ + type RDPCS_PHY_DP_TX2_EQ_POST;\ + type RDPCS_PHY_DP_TX3_EQ_MAIN;\ + type RDPCS_PHY_DCO_RANGE;\ + type RDPCS_PHY_DCO_FINETUNE;\ + type RDPCS_PHY_DP_TX3_EQ_PRE;\ + type RDPCS_PHY_DP_TX3_EQ_POST;\ + type RDPCS_PHY_SUP_PRE_HP;\ + type RDPCS_PHY_DP_TX0_VREGDRV_BYP;\ + type RDPCS_PHY_DP_TX1_VREGDRV_BYP;\ + type RDPCS_PHY_DP_TX2_VREGDRV_BYP;\ + type RDPCS_PHY_DP_TX3_VREGDRV_BYP;\ + type RDPCS_DMCU_DPALT_DIS_BLOCK_REG;\ + type UNIPHYA_SOFT_RESET;\ + type UNIPHYB_SOFT_RESET;\ + type UNIPHYC_SOFT_RESET;\ + type UNIPHYD_SOFT_RESET;\ + type UNIPHYE_SOFT_RESET;\ + type UNIPHYF_SOFT_RESET + +#define DCN20_LINK_ENCODER_REG_FIELD_LIST(type) \ + type DIG_LANE0EN;\ + type DIG_LANE1EN;\ + type DIG_LANE2EN;\ + type DIG_LANE3EN;\ + type DIG_CLK_EN;\ + type SYMCLKA_CLOCK_ENABLE;\ + type DPHY_FEC_EN;\ + type DPHY_FEC_READY_SHADOW;\ + type DPHY_FEC_ACTIVE_STATUS;\ + DCN20_LINK_ENCODER_DPCS_REG_FIELD_LIST(type);\ + type VCO_LD_VAL_OVRD;\ + type VCO_LD_VAL_OVRD_EN;\ + type REF_LD_VAL_OVRD;\ + type REF_LD_VAL_OVRD_EN;\ + type AUX_RX_START_WINDOW; \ + type AUX_RX_HALF_SYM_DETECT_LEN; \ + type AUX_RX_TRANSITION_FILTER_EN; \ + type AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT; \ + type AUX_RX_ALLOW_BELOW_THRESHOLD_START; \ + type AUX_RX_ALLOW_BELOW_THRESHOLD_STOP; \ + type AUX_RX_PHASE_DETECT_LEN; \ + type AUX_RX_DETECTION_THRESHOLD; \ + type AUX_TX_PRECHARGE_LEN; \ + type AUX_TX_PRECHARGE_SYMBOLS; \ + type AUX_MODE_DET_CHECK_DELAY;\ + type DPCS_DBG_CBUS_DIS;\ + type AUX_RX_PRECHARGE_SKIP;\ + type AUX_RX_TIMEOUT_LEN;\ + type AUX_RX_TIMEOUT_LEN_MUL + +#define DCN30_LINK_ENCODER_REG_FIELD_LIST(type) \ + type TMDS_SYNC_DCBAL_EN;\ + type PHY_HPO_DIG_SRC_SEL;\ + type PHY_HPO_ENC_SRC_SEL;\ + type DPCS_TX_HDMI_FRL_MODE;\ + type DPCS_TX_DATA_SWAP_10_BIT;\ + type DPCS_TX_DATA_ORDER_INVERT_18_BIT;\ + type RDPCS_TX_CLK_EN + +#define DCN31_LINK_ENCODER_REG_FIELD_LIST(type) \ + type ENC_TYPE_SEL;\ + type HPO_DP_ENC_SEL;\ + type HPO_HDMI_ENC_SEL + +#define DCN35_LINK_ENCODER_REG_FIELD_LIST(type) \ + type DIG_BE_ENABLE;\ + type DIG_RB_SWITCH_EN;\ + type DIG_BE_MODE;\ + type DIG_BE_CLK_EN;\ + type DIG_BE_SOFT_RESET;\ + type HDCP_SOFT_RESET;\ + type DIG_BE_SYMCLK_G_CLOCK_ON;\ + type DIG_BE_SYMCLK_G_HDCP_CLOCK_ON;\ + type DIG_BE_SYMCLK_G_TMDS_CLOCK_ON;\ + type DISPCLK_R_GATE_DIS;\ + type DISPCLK_G_GATE_DIS;\ + type REFCLK_R_GATE_DIS;\ + type REFCLK_G_GATE_DIS;\ + type SOCCLK_G_GATE_DIS;\ + type SYMCLK_FE_R_GATE_DIS;\ + type SYMCLK_FE_G_GATE_DIS;\ + type SYMCLK_R_GATE_DIS;\ + type SYMCLK_G_GATE_DIS;\ + type DIO_FGCG_REP_DIS;\ + type DISPCLK_G_HDCP_GATE_DIS;\ + type SYMCLKA_G_HDCP_GATE_DIS;\ + type SYMCLKB_G_HDCP_GATE_DIS;\ + type SYMCLKC_G_HDCP_GATE_DIS;\ + type SYMCLKD_G_HDCP_GATE_DIS;\ + type SYMCLKE_G_HDCP_GATE_DIS;\ + type SYMCLKF_G_HDCP_GATE_DIS;\ + type SYMCLKG_G_HDCP_GATE_DIS + +struct dcn10_link_enc_shift { + DCN_LINK_ENCODER_REG_FIELD_LIST(uint8_t); + DCN20_LINK_ENCODER_REG_FIELD_LIST(uint8_t); + DCN30_LINK_ENCODER_REG_FIELD_LIST(uint8_t); + DCN31_LINK_ENCODER_REG_FIELD_LIST(uint8_t); + DCN35_LINK_ENCODER_REG_FIELD_LIST(uint8_t); +}; + +struct dcn10_link_enc_mask { + DCN_LINK_ENCODER_REG_FIELD_LIST(uint32_t); + DCN20_LINK_ENCODER_REG_FIELD_LIST(uint32_t); + DCN30_LINK_ENCODER_REG_FIELD_LIST(uint32_t); + DCN31_LINK_ENCODER_REG_FIELD_LIST(uint32_t); + DCN35_LINK_ENCODER_REG_FIELD_LIST(uint32_t); +}; + +struct dcn10_link_encoder { + struct link_encoder base; + const struct dcn10_link_enc_registers *link_regs; + const struct dcn10_link_enc_aux_registers *aux_regs; + const struct dcn10_link_enc_hpd_registers *hpd_regs; + const struct dcn10_link_enc_shift *link_shift; + const struct dcn10_link_enc_mask *link_mask; +}; + + +void dcn10_link_encoder_construct( + struct dcn10_link_encoder *enc10, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask); + +bool dcn10_link_encoder_validate_dvi_output( + const struct dcn10_link_encoder *enc10, + enum signal_type connector_signal, + enum signal_type signal, + const struct dc_crtc_timing *crtc_timing); + +bool dcn10_link_encoder_validate_rgb_output( + const struct dcn10_link_encoder *enc10, + const struct dc_crtc_timing *crtc_timing); + +bool dcn10_link_encoder_validate_dp_output( + const struct dcn10_link_encoder *enc10, + const struct dc_crtc_timing *crtc_timing); + +bool dcn10_link_encoder_validate_wireless_output( + const struct dcn10_link_encoder *enc10, + const struct dc_crtc_timing *crtc_timing); + +bool dcn10_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + const struct dc_stream_state *stream); + +/****************** HW programming ************************/ + +/* initialize HW */ /* why do we initialze aux in here? */ +void dcn10_link_encoder_hw_init(struct link_encoder *enc); + +void dcn10_link_encoder_destroy(struct link_encoder **enc); + +/* program DIG_MODE in DIG_BE */ +/* TODO can this be combined with enable_output? */ +void dcn10_link_encoder_setup( + struct link_encoder *enc, + enum signal_type signal); + +void enc1_configure_encoder( + struct dcn10_link_encoder *enc10, + const struct dc_link_settings *link_settings); + +/* enables TMDS PHY output */ +/* TODO: still need depth or just pass in adjusted pixel clock? */ +void dcn10_link_encoder_enable_tmds_output( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + enum signal_type signal, + uint32_t pixel_clock); + +void dcn10_link_encoder_enable_tmds_output_with_clk_pattern_wa( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + enum signal_type signal, + uint32_t pixel_clock); + +/* enables DP PHY output */ +void dcn10_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* enables DP PHY output in MST mode */ +void dcn10_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* disable PHY output */ +void dcn10_link_encoder_disable_output( + struct link_encoder *enc, + enum signal_type signal); + +/* set DP lane settings */ +void dcn10_link_encoder_dp_set_lane_settings( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); + +void dcn10_link_encoder_dp_set_phy_pattern( + struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *param); + +/* programs DP MST VC payload allocation */ +void dcn10_link_encoder_update_mst_stream_allocation_table( + struct link_encoder *enc, + const struct link_mst_stream_allocation_table *table); + +void dcn10_link_encoder_connect_dig_be_to_fe( + struct link_encoder *enc, + enum engine_id engine, + bool connect); + +void dcn10_link_encoder_set_dp_phy_pattern_training_pattern( + struct link_encoder *enc, + uint32_t index); + +void dcn10_link_encoder_enable_hpd(struct link_encoder *enc); + +void dcn10_link_encoder_disable_hpd(struct link_encoder *enc); + +void dcn10_psr_program_dp_dphy_fast_training(struct link_encoder *enc, + bool exit_link_training_required); + +void dcn10_psr_program_secondary_packet(struct link_encoder *enc, + unsigned int sdp_transmit_line_num_deadline); + +bool dcn10_is_dig_enabled(struct link_encoder *enc); + +unsigned int dcn10_get_dig_frontend(struct link_encoder *enc); + +void dcn10_aux_initialize(struct dcn10_link_encoder *enc10); + +enum signal_type dcn10_get_dig_mode( + struct link_encoder *enc); + +void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc, + struct dc_link_settings *link_settings); +#endif /* __DC_LINK_ENCODER__DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c new file mode 100644 index 000000000000..f496e952ceec --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c @@ -0,0 +1,1628 @@ +/* + * 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 "dc_bios_types.h" +#include "dcn10_stream_encoder.h" +#include "reg_helper.h" +#include "hw_shared.h" +#include "link.h" +#include "dpcd_defs.h" +#include "dcn30/dcn30_afmt.h" + +#define DC_LOGGER \ + enc1->base.ctx->logger + +#define REG(reg)\ + (enc1->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc1->se_shift->field_name, enc1->se_mask->field_name + +#define VBI_LINE_0 0 +#define DP_BLANK_MAX_RETRY 20 +#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 + + +enum { + DP_MST_UPDATE_MAX_RETRY = 50 +}; + +#define CTX \ + enc1->base.ctx + +void enc1_update_generic_info_packet( + struct dcn10_stream_encoder *enc1, + uint32_t packet_index, + const struct dc_info_packet *info_packet) +{ + /* TODOFPGA Figure out a proper number for max_retries polling for lock + * use 50 for now. + */ + uint32_t max_retries = 50; + + /*we need turn on clock before programming AFMT block*/ + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); + + if (packet_index >= 8) + ASSERT(0); + + /* poll dig_update_lock is not locked -> asic internal signal + * assume otg master lock will unlock it + */ +/* REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, + 0, 10, max_retries);*/ + + /* check if HW reading GSP memory */ + REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, + 0, 10, max_retries); + + /* HW does is not reading GSP memory not reading too long -> + * something wrong. clear GPS memory access and notify? + * hw SW is writing to GSP memory + */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); + + /* choose which generic packet to use */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, + AFMT_GENERIC_INDEX, packet_index); + + /* write generic packet header + * (4th byte is for GENERIC0 only) + */ + REG_SET_4(AFMT_GENERIC_HDR, 0, + AFMT_GENERIC_HB0, info_packet->hb0, + AFMT_GENERIC_HB1, info_packet->hb1, + AFMT_GENERIC_HB2, info_packet->hb2, + AFMT_GENERIC_HB3, info_packet->hb3); + + /* write generic packet contents + * (we never use last 4 bytes) + * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers + */ + { + const uint32_t *content = + (const uint32_t *) &info_packet->sb[0]; + + REG_WRITE(AFMT_GENERIC_0, *content++); + REG_WRITE(AFMT_GENERIC_1, *content++); + REG_WRITE(AFMT_GENERIC_2, *content++); + REG_WRITE(AFMT_GENERIC_3, *content++); + REG_WRITE(AFMT_GENERIC_4, *content++); + REG_WRITE(AFMT_GENERIC_5, *content++); + REG_WRITE(AFMT_GENERIC_6, *content++); + REG_WRITE(AFMT_GENERIC_7, *content); + } + + switch (packet_index) { + case 0: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC0_IMMEDIATE_UPDATE, 1); + break; + case 1: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC1_IMMEDIATE_UPDATE, 1); + break; + case 2: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC2_IMMEDIATE_UPDATE, 1); + break; + case 3: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC3_IMMEDIATE_UPDATE, 1); + break; + case 4: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC4_IMMEDIATE_UPDATE, 1); + break; + case 5: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC5_IMMEDIATE_UPDATE, 1); + break; + case 6: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC6_IMMEDIATE_UPDATE, 1); + break; + case 7: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC7_IMMEDIATE_UPDATE, 1); + break; + default: + break; + } +} + +static void enc1_update_hdmi_info_packet( + struct dcn10_stream_encoder *enc1, + uint32_t packet_index, + const struct dc_info_packet *info_packet) +{ + uint32_t cont, send, line; + + if (info_packet->valid) { + enc1_update_generic_info_packet( + enc1, + packet_index, + info_packet); + + /* enable transmission of packet(s) - + * packet transmission begins on the next frame + */ + cont = 1; + /* send packet(s) every frame */ + send = 1; + /* select line number to send packets on */ + line = 2; + } else { + cont = 0; + send = 0; + line = 0; + } + + /* choose which generic packet control to use */ + switch (packet_index) { + case 0: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 1: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + case 2: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 3: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + case 4: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 5: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + case 6: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 7: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + default: + /* invalid HW packet index */ + DC_LOG_WARNING( + "Invalid HW packet index: %s()\n", + __func__); + return; + } +} + +/* setup stream encoder in dp mode */ +void enc1_stream_encoder_dp_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space, + bool use_vsc_sdp_for_colorimetry, + uint32_t enable_sdp_splitting) +{ + uint32_t h_active_start; + uint32_t v_active_start; + uint32_t misc0 = 0; + uint32_t misc1 = 0; + uint32_t h_blank; + uint32_t h_back_porch; + uint8_t synchronous_clock = 0; /* asynchronous mode */ + uint8_t colorimetry_bpc; + uint8_t dp_pixel_encoding = 0; + uint8_t dp_component_depth = 0; + + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + struct dc_crtc_timing hw_crtc_timing = *crtc_timing; + + if (hw_crtc_timing.flags.INTERLACE) { + /*the input timing is in VESA spec format with Interlace flag =1*/ + hw_crtc_timing.v_total /= 2; + hw_crtc_timing.v_border_top /= 2; + hw_crtc_timing.v_addressable /= 2; + hw_crtc_timing.v_border_bottom /= 2; + hw_crtc_timing.v_front_porch /= 2; + hw_crtc_timing.v_sync_width /= 2; + } + + + /* set pixel encoding */ + switch (hw_crtc_timing.pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR422; + break; + case PIXEL_ENCODING_YCBCR444: + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR444; + + if (hw_crtc_timing.flags.Y_ONLY) + if (hw_crtc_timing.display_color_depth != COLOR_DEPTH_666) + /* HW testing only, no use case yet. + * Color depth of Y-only could be + * 8, 10, 12, 16 bits + */ + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_Y_ONLY; + + /* Note: DP_MSA_MISC1 bit 7 is the indicator + * of Y-only mode. + * This bit is set in HW if register + * DP_PIXEL_ENCODING is programmed to 0x4 + */ + break; + case PIXEL_ENCODING_YCBCR420: + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR420; + break; + default: + dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_RGB444; + break; + } + + misc1 = REG_READ(DP_MSA_MISC); + /* For YCbCr420 and BT2020 Colorimetry Formats, VSC SDP shall be used. + * When MISC1, bit 6, is Set to 1, a Source device uses a VSC SDP to indicate the + * Pixel Encoding/Colorimetry Format and that a Sink device shall ignore MISC1, bit 7, + * and MISC0, bits 7:1 (MISC1, bit 7, and MISC0, bits 7:1, become "don't care"). + */ + if (use_vsc_sdp_for_colorimetry) + misc1 = misc1 | 0x40; + else + misc1 = misc1 & ~0x40; + + /* set color depth */ + switch (hw_crtc_timing.display_color_depth) { + case COLOR_DEPTH_666: + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_6BPC; + break; + case COLOR_DEPTH_888: + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_8BPC; + break; + case COLOR_DEPTH_101010: + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_10BPC; + break; + case COLOR_DEPTH_121212: + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_12BPC; + break; + case COLOR_DEPTH_161616: + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_16BPC; + break; + default: + dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_6BPC; + break; + } + + /* Set DP pixel encoding and component depth */ + REG_UPDATE_2(DP_PIXEL_FORMAT, + DP_PIXEL_ENCODING, dp_pixel_encoding, + DP_COMPONENT_DEPTH, dp_component_depth); + + /* set dynamic range and YCbCr range */ + + switch (hw_crtc_timing.display_color_depth) { + case COLOR_DEPTH_666: + colorimetry_bpc = 0; + break; + case COLOR_DEPTH_888: + colorimetry_bpc = 1; + break; + case COLOR_DEPTH_101010: + colorimetry_bpc = 2; + break; + case COLOR_DEPTH_121212: + colorimetry_bpc = 3; + break; + default: + colorimetry_bpc = 0; + break; + } + + misc0 = misc0 | synchronous_clock; + misc0 = colorimetry_bpc << 5; + + switch (output_color_space) { + case COLOR_SPACE_SRGB: + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + break; + case COLOR_SPACE_SRGB_LIMITED: + misc0 = misc0 | 0x8; /* bit3=1 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ + else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) + misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ + else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) + misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ + break; + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_2020_RGB_FULLRANGE: + case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_XR_RGB: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_ADOBERGB: + case COLOR_SPACE_DCIP3: + case COLOR_SPACE_XV_YCC_709: + case COLOR_SPACE_XV_YCC_601: + case COLOR_SPACE_DISPLAYNATIVE: + case COLOR_SPACE_DOLBYVISION: + case COLOR_SPACE_APPCTRL: + case COLOR_SPACE_CUSTOMPOINTS: + case COLOR_SPACE_UNKNOWN: + case COLOR_SPACE_YCBCR709_BLACK: + /* do nothing */ + break; + } + + REG_SET(DP_MSA_COLORIMETRY, 0, DP_MSA_MISC0, misc0); + REG_WRITE(DP_MSA_MISC, misc1); /* MSA_MISC1 */ + + /* dcn new register + * dc_crtc_timing is vesa dmt struct. data from edid + */ + REG_SET_2(DP_MSA_TIMING_PARAM1, 0, + DP_MSA_HTOTAL, hw_crtc_timing.h_total, + DP_MSA_VTOTAL, hw_crtc_timing.v_total); + + /* calculate from vesa timing parameters + * h_active_start related to leading edge of sync + */ + + h_blank = hw_crtc_timing.h_total - hw_crtc_timing.h_border_left - + hw_crtc_timing.h_addressable - hw_crtc_timing.h_border_right; + + h_back_porch = h_blank - hw_crtc_timing.h_front_porch - + hw_crtc_timing.h_sync_width; + + /* start at beginning of left border */ + h_active_start = hw_crtc_timing.h_sync_width + h_back_porch; + + + v_active_start = hw_crtc_timing.v_total - hw_crtc_timing.v_border_top - + hw_crtc_timing.v_addressable - hw_crtc_timing.v_border_bottom - + hw_crtc_timing.v_front_porch; + + + /* start at beginning of left border */ + REG_SET_2(DP_MSA_TIMING_PARAM2, 0, + DP_MSA_HSTART, h_active_start, + DP_MSA_VSTART, v_active_start); + + REG_SET_4(DP_MSA_TIMING_PARAM3, 0, + DP_MSA_HSYNCWIDTH, + hw_crtc_timing.h_sync_width, + DP_MSA_HSYNCPOLARITY, + !hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY, + DP_MSA_VSYNCWIDTH, + hw_crtc_timing.v_sync_width, + DP_MSA_VSYNCPOLARITY, + !hw_crtc_timing.flags.VSYNC_POSITIVE_POLARITY); + + /* HWDITH include border or overscan */ + REG_SET_2(DP_MSA_TIMING_PARAM4, 0, + DP_MSA_HWIDTH, hw_crtc_timing.h_border_left + + hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right, + DP_MSA_VHEIGHT, hw_crtc_timing.v_border_top + + hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom); +} + +void enc1_stream_encoder_set_stream_attribute_helper( + struct dcn10_stream_encoder *enc1, + struct dc_crtc_timing *crtc_timing) +{ + switch (crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 1); + break; + default: + REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 0); + break; + } + REG_UPDATE(DIG_FE_CNTL, TMDS_COLOR_FORMAT, 0); +} + +/* setup stream encoder in hdmi mode */ +void enc1_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc1->base.id; + cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; + cntl.enable_dp_audio = enable_audio; + cntl.pixel_clock = actual_pix_clk_khz; + cntl.lanes_number = LANE_COUNT_FOUR; + + if (enc1->base.bp->funcs->encoder_control( + enc1->base.bp, &cntl) != BP_RESULT_OK) + return; + + enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); + + /* setup HDMI engine */ + REG_UPDATE_6(HDMI_CONTROL, + HDMI_PACKET_GEN_VERSION, 1, + HDMI_KEEPOUT_MODE, 1, + HDMI_DEEP_COLOR_ENABLE, 0, + HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + + + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_888: + REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); + DC_LOG_DEBUG("HDMI source set to 24BPP deep color depth\n"); + break; + case COLOR_DEPTH_101010: + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 0); + DC_LOG_DEBUG("HDMI source 30BPP deep color depth" \ + "disabled for YCBCR422 pixel encoding\n"); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 1); + DC_LOG_DEBUG("HDMI source 30BPP deep color depth" \ + "enabled for YCBCR422 non-pixel encoding\n"); + } + break; + case COLOR_DEPTH_121212: + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 0); + DC_LOG_DEBUG("HDMI source 36BPP deep color depth" \ + "disabled for YCBCR422 pixel encoding\n"); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 1); + DC_LOG_DEBUG("HDMI source 36BPP deep color depth" \ + "enabled for non-pixel YCBCR422 encoding\n"); + } + break; + case COLOR_DEPTH_161616: + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 3, + HDMI_DEEP_COLOR_ENABLE, 1); + DC_LOG_DEBUG("HDMI source deep color depth enabled in" \ + "reserved mode\n"); + break; + default: + break; + } + + if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_RATE_MORE_340M + * Clock channel frequency is 1/4 of character rate. + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 1); + } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { + + /* TODO: New feature for DCE11, still need to implement */ + + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE + * Clock channel frequency is the same + * as character rate + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + } + + + REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, + HDMI_GC_CONT, 1, + HDMI_GC_SEND, 1, + HDMI_NULL_SEND, 1); + + REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); + + /* following belongs to audio */ + REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); + + REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); + + REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, + VBI_LINE_0 + 2); + + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); +} + +/* setup stream encoder in dvi mode */ +void enc1_stream_encoder_dvi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc1->base.id; + cntl.signal = is_dual_link ? + SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; + cntl.enable_dp_audio = false; + cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; + cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; + + if (enc1->base.bp->funcs->encoder_control( + enc1->base.bp, &cntl) != BP_RESULT_OK) + return; + + ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); + ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); + enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); +} + +void enc1_stream_encoder_set_throttled_vcp_size( + struct stream_encoder *enc, + struct fixed31_32 avg_time_slots_per_mtp) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t x = dc_fixpt_floor( + avg_time_slots_per_mtp); + uint32_t y = dc_fixpt_ceil( + dc_fixpt_shl( + dc_fixpt_sub_int( + avg_time_slots_per_mtp, + x), + 26)); + + // If y rounds up to integer, carry it over to x. + if (y >> 26) { + x += 1; + y = 0; + } + + REG_SET_2(DP_MSE_RATE_CNTL, 0, + DP_MSE_RATE_X, x, + DP_MSE_RATE_Y, y); + + /* wait for update to be completed on the link */ + /* i.e. DP_MSE_RATE_UPDATE_PENDING field (read only) */ + /* is reset to 0 (not pending) */ + REG_WAIT(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, + 0, + 10, DP_MST_UPDATE_MAX_RETRY); +} + +static void enc1_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* for bring up, disable dp double TODO */ + REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); + + /*Always add mandatory packets first followed by optional ones*/ + enc1_update_hdmi_info_packet(enc1, 0, &info_frame->avi); + enc1_update_hdmi_info_packet(enc1, 1, &info_frame->hfvsif); + enc1_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); + enc1_update_hdmi_info_packet(enc1, 3, &info_frame->vendor); + enc1_update_hdmi_info_packet(enc1, 4, &info_frame->spd); + enc1_update_hdmi_info_packet(enc1, 5, &info_frame->hdrsmd); +} + +static void enc1_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* stop generic packets 0 & 1 on HDMI */ + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0); + + /* stop generic packets 2 & 3 on HDMI */ + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL1, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0); + + /* stop generic packets 2 & 3 on HDMI */ + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL2, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0); + + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL3, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0); +} + +void enc1_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + + if (info_frame->vsc.valid) + enc1_update_generic_info_packet( + enc1, + 0, /* packetIndex */ + &info_frame->vsc); + + /* VSC SDP at packetIndex 1 is used by PSR in DMCUB FW. + * Note that the enablement of GSP1 is not done below, + * it's done in FW. + */ + if (info_frame->vsc.valid) + enc1_update_generic_info_packet( + enc1, + 1, /* packetIndex */ + &info_frame->vsc); + + if (info_frame->spd.valid) + enc1_update_generic_info_packet( + enc1, + 2, /* packetIndex */ + &info_frame->spd); + + if (info_frame->hdrsmd.valid) + enc1_update_generic_info_packet( + enc1, + 3, /* packetIndex */ + &info_frame->hdrsmd); + + /* packetIndex 4 is used for send immediate sdp message, and please + * use other packetIndex (such as 5,6) for other info packet + */ + + if (info_frame->adaptive_sync.valid) + enc1_update_generic_info_packet( + enc1, + 5, /* packetIndex */ + &info_frame->adaptive_sync); + + /* enable/disable transmission of packet(s). + * If enabled, packet transmission begins on the next frame + */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid); + + /* This bit is the master enable bit. + * When enabling secondary stream engine, + * this master bit must also be set. + * This register shared with audio info frame. + * Therefore we need to enable master bit + * if at least on of the fields is not 0 + */ + value = REG_READ(DP_SEC_CNTL); + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +void enc1_stream_encoder_send_immediate_sdp_message( + struct stream_encoder *enc, + const uint8_t *custom_sdp_message, + unsigned int sdp_message_size) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + + /* TODOFPGA Figure out a proper number for max_retries polling for lock + * use 50 for now. + */ + uint32_t max_retries = 50; + + /* check if GSP4 is transmitted */ + REG_WAIT(DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, + 0, 10, max_retries); + + /* disable GSP4 transmitting */ + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP4_SEND, 0); + + /* transmit GSP4 at the earliest time in a frame */ + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, 1); + + /*we need turn on clock before programming AFMT block*/ + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); + + /* check if HW reading GSP memory */ + REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, + 0, 10, max_retries); + + /* HW does is not reading GSP memory not reading too long -> + * something wrong. clear GPS memory access and notify? + * hw SW is writing to GSP memory + */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); + + /* use generic packet 4 for immediate sdp message */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, + AFMT_GENERIC_INDEX, 4); + + /* write generic packet header + * (4th byte is for GENERIC0 only) + */ + REG_SET_4(AFMT_GENERIC_HDR, 0, + AFMT_GENERIC_HB0, custom_sdp_message[0], + AFMT_GENERIC_HB1, custom_sdp_message[1], + AFMT_GENERIC_HB2, custom_sdp_message[2], + AFMT_GENERIC_HB3, custom_sdp_message[3]); + + /* write generic packet contents + * (we never use last 4 bytes) + * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers + */ + { + const uint32_t *content = + (const uint32_t *) &custom_sdp_message[4]; + + REG_WRITE(AFMT_GENERIC_0, *content++); + REG_WRITE(AFMT_GENERIC_1, *content++); + REG_WRITE(AFMT_GENERIC_2, *content++); + REG_WRITE(AFMT_GENERIC_3, *content++); + REG_WRITE(AFMT_GENERIC_4, *content++); + REG_WRITE(AFMT_GENERIC_5, *content++); + REG_WRITE(AFMT_GENERIC_6, *content++); + REG_WRITE(AFMT_GENERIC_7, *content); + } + + /* check whether GENERIC4 registers double buffer update in immediate mode + * is pending + */ + REG_WAIT(AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE_PENDING, + 0, 10, max_retries); + + /* atomically update double-buffered GENERIC4 registers in immediate mode + * (update immediately) + */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC4_IMMEDIATE_UPDATE, 1); + + /* enable GSP4 transmitting */ + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP4_SEND, 1); + + /* This bit is the master enable bit. + * When enabling secondary stream engine, + * this master bit must also be set. + * This register shared with audio info frame. + * Therefore we need to enable master bit + * if at least on of the fields is not 0 + */ + value = REG_READ(DP_SEC_CNTL); + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +void enc1_stream_encoder_stop_dp_info_packets( + struct stream_encoder *enc) +{ + /* stop generic packets on DP */ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + + REG_SET_10(DP_SEC_CNTL, 0, + DP_SEC_GSP0_ENABLE, 0, + DP_SEC_GSP1_ENABLE, 0, + DP_SEC_GSP2_ENABLE, 0, + DP_SEC_GSP3_ENABLE, 0, + DP_SEC_GSP4_ENABLE, 0, + DP_SEC_GSP5_ENABLE, 0, + DP_SEC_GSP6_ENABLE, 0, + DP_SEC_GSP7_ENABLE, 0, + DP_SEC_MPG_ENABLE, 0, + DP_SEC_STREAM_ENABLE, 0); + + /* this register shared with audio info frame. + * therefore we need to keep master enabled + * if at least one of the fields is not 0 */ + value = REG_READ(DP_SEC_CNTL); + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); + +} + +void enc1_stream_encoder_dp_blank( + struct dc_link *link, + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t reg1 = 0; + uint32_t max_retries = DP_BLANK_MAX_RETRY * 10; + + /* Note: For CZ, we are changing driver default to disable + * stream deferred to next VBLANK. If results are positive, we + * will make the same change to all DCE versions. There are a + * handful of panels that cannot handle disable stream at + * HBLANK and will result in a white line flash across the + * screen on stream disable. + */ + REG_GET(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, ®1); + if ((reg1 & 0x1) == 0) + /*stream not enabled*/ + return; + /* Specify the video stream disable point + * (2 = start of the next vertical blank) + */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, 2); + /* Larger delay to wait until VBLANK - use max retry of + * 10us*10200=102ms. This covers 100.0ms of minimum 10 Hz mode + + * a little more because we may not trust delay accuracy. + */ + max_retries = DP_BLANK_MAX_RETRY * 501; + + /* disable DP stream */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); + + link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_DP_VID_STREAM); + + /* the encoder stops sending the video stream + * at the start of the vertical blanking. + * Poll for DP_VID_STREAM_STATUS == 0 + */ + + REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, + 0, + 10, max_retries); + + /* Tell the DP encoder to ignore timing from CRTC, must be done after + * the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is + * complete, stream status will be stuck in video stream enabled state, + * i.e. DP_VID_STREAM_STATUS stuck at 1. + */ + + REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, true); + + link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_FIFO_STEER_RESET); +} + +/* output video stream to link encoder */ +void enc1_stream_encoder_dp_unblank( + struct dc_link *link, + struct stream_encoder *enc, + const struct encoder_unblank_param *param) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { + uint32_t n_vid = 0x8000; + uint32_t m_vid; + uint32_t n_multiply = 0; + uint64_t m_vid_l = n_vid; + + /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ + if (param->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + /*this param->pixel_clk_khz is half of 444 rate for 420 already*/ + n_multiply = 1; + } + /* M / N = Fstream / Flink + * m_vid / n_vid = pixel rate / link rate + */ + + m_vid_l *= param->timing.pix_clk_100hz / 10; + m_vid_l = div_u64(m_vid_l, + param->link_settings.link_rate + * LINK_RATE_REF_FREQ_IN_KHZ); + + m_vid = (uint32_t) m_vid_l; + + /* enable auto measurement */ + + REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); + + /* auto measurement need 1 full 0x8000 symbol cycle to kick in, + * therefore program initial value for Mvid and Nvid + */ + + REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); + + REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); + + REG_UPDATE_2(DP_VID_TIMING, + DP_VID_M_N_GEN_EN, 1, + DP_VID_N_MUL, n_multiply); + } + + /* set DIG_START to 0x1 to resync FIFO */ + + REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); + + /* switch DP encoder to CRTC data */ + + REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); + + /* wait 100us for DIG/DP logic to prime + * (i.e. a few video lines) + */ + udelay(100); + + /* the hardware would start sending video at the start of the next DP + * frame (i.e. rising edge of the vblank). + * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this + * register has no effect on enable transition! HW always guarantees + * VID_STREAM enable at start of next frame, and this is not + * programmable + */ + + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); + + link->dc->link_srv->dp_trace_source_sequence(link, + DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); +} + +void enc1_stream_encoder_set_avmute( + struct stream_encoder *enc, + bool enable) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + unsigned int value = enable ? 1 : 0; + + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, value); +} + +void enc1_reset_hdmi_stream_attribute( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE_5(HDMI_CONTROL, + HDMI_PACKET_GEN_VERSION, 1, + HDMI_KEEPOUT_MODE, 1, + HDMI_DEEP_COLOR_ENABLE, 0, + HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_CLOCK_CHANNEL_RATE, 0); +} + + +#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 +#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 + +#include "include/audio_types.h" + + +/* 25.2MHz/1.001*/ +/* 25.2MHz/1.001*/ +/* 25.2MHz*/ +/* 27MHz */ +/* 27MHz*1.001*/ +/* 27MHz*1.001*/ +/* 54MHz*/ +/* 54MHz*1.001*/ +/* 74.25MHz/1.001*/ +/* 74.25MHz*/ +/* 148.5MHz/1.001*/ +/* 148.5MHz*/ + +static const struct audio_clock_info audio_clock_info_table[16] = { + {2517, 4576, 28125, 7007, 31250, 6864, 28125}, + {2518, 4576, 28125, 7007, 31250, 6864, 28125}, + {2520, 4096, 25200, 6272, 28000, 6144, 25200}, + {2700, 4096, 27000, 6272, 30000, 6144, 27000}, + {2702, 4096, 27027, 6272, 30030, 6144, 27027}, + {2703, 4096, 27027, 6272, 30030, 6144, 27027}, + {5400, 4096, 54000, 6272, 60000, 6144, 54000}, + {5405, 4096, 54054, 6272, 60060, 6144, 54054}, + {7417, 11648, 210937, 17836, 234375, 11648, 140625}, + {7425, 4096, 74250, 6272, 82500, 6144, 74250}, + {14835, 11648, 421875, 8918, 234375, 5824, 140625}, + {14850, 4096, 148500, 6272, 165000, 6144, 148500}, + {29670, 5824, 421875, 4459, 234375, 5824, 281250}, + {29700, 3072, 222750, 4704, 247500, 5120, 247500}, + {59340, 5824, 843750, 8918, 937500, 5824, 562500}, + {59400, 3072, 445500, 9408, 990000, 6144, 594000} +}; + +static const struct audio_clock_info audio_clock_info_table_36bpc[14] = { + {2517, 9152, 84375, 7007, 48875, 9152, 56250}, + {2518, 9152, 84375, 7007, 48875, 9152, 56250}, + {2520, 4096, 37800, 6272, 42000, 6144, 37800}, + {2700, 4096, 40500, 6272, 45000, 6144, 40500}, + {2702, 8192, 81081, 6272, 45045, 8192, 54054}, + {2703, 8192, 81081, 6272, 45045, 8192, 54054}, + {5400, 4096, 81000, 6272, 90000, 6144, 81000}, + {5405, 4096, 81081, 6272, 90090, 6144, 81081}, + {7417, 11648, 316406, 17836, 351562, 11648, 210937}, + {7425, 4096, 111375, 6272, 123750, 6144, 111375}, + {14835, 11648, 632812, 17836, 703125, 11648, 421875}, + {14850, 4096, 222750, 6272, 247500, 6144, 222750}, + {29670, 5824, 632812, 8918, 703125, 5824, 421875}, + {29700, 4096, 445500, 4704, 371250, 5120, 371250} +}; + +static const struct audio_clock_info audio_clock_info_table_48bpc[14] = { + {2517, 4576, 56250, 7007, 62500, 6864, 56250}, + {2518, 4576, 56250, 7007, 62500, 6864, 56250}, + {2520, 4096, 50400, 6272, 56000, 6144, 50400}, + {2700, 4096, 54000, 6272, 60000, 6144, 54000}, + {2702, 4096, 54054, 6267, 60060, 8192, 54054}, + {2703, 4096, 54054, 6272, 60060, 8192, 54054}, + {5400, 4096, 108000, 6272, 120000, 6144, 108000}, + {5405, 4096, 108108, 6272, 120120, 6144, 108108}, + {7417, 11648, 421875, 17836, 468750, 11648, 281250}, + {7425, 4096, 148500, 6272, 165000, 6144, 148500}, + {14835, 11648, 843750, 8918, 468750, 11648, 281250}, + {14850, 4096, 297000, 6272, 330000, 6144, 297000}, + {29670, 5824, 843750, 4459, 468750, 5824, 562500}, + {29700, 3072, 445500, 4704, 495000, 5120, 495000} + + +}; + +static union audio_cea_channels speakers_to_channels( + struct audio_speaker_flags speaker_flags) +{ + union audio_cea_channels cea_channels = {0}; + + /* these are one to one */ + cea_channels.channels.FL = speaker_flags.FL_FR; + cea_channels.channels.FR = speaker_flags.FL_FR; + cea_channels.channels.LFE = speaker_flags.LFE; + cea_channels.channels.FC = speaker_flags.FC; + + /* if Rear Left and Right exist move RC speaker to channel 7 + * otherwise to channel 5 + */ + if (speaker_flags.RL_RR) { + cea_channels.channels.RL_RC = speaker_flags.RL_RR; + cea_channels.channels.RR = speaker_flags.RL_RR; + cea_channels.channels.RC_RLC_FLC = speaker_flags.RC; + } else { + cea_channels.channels.RL_RC = speaker_flags.RC; + } + + /* FRONT Left Right Center and REAR Left Right Center are exclusive */ + if (speaker_flags.FLC_FRC) { + cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC; + cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC; + } else { + cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC; + cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC; + } + + return cea_channels; +} + +void get_audio_clock_info( + enum dc_color_depth color_depth, + uint32_t crtc_pixel_clock_100Hz, + uint32_t actual_pixel_clock_100Hz, + struct audio_clock_info *audio_clock_info) +{ + const struct audio_clock_info *clock_info; + uint32_t index; + uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_100Hz / 100; + uint32_t audio_array_size; + + switch (color_depth) { + case COLOR_DEPTH_161616: + clock_info = audio_clock_info_table_48bpc; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table_48bpc); + break; + case COLOR_DEPTH_121212: + clock_info = audio_clock_info_table_36bpc; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table_36bpc); + break; + default: + clock_info = audio_clock_info_table; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table); + break; + } + + if (clock_info != NULL) { + /* search for exact pixel clock in table */ + for (index = 0; index < audio_array_size; index++) { + if (clock_info[index].pixel_clock_in_10khz > + crtc_pixel_clock_in_10khz) + break; /* not match */ + else if (clock_info[index].pixel_clock_in_10khz == + crtc_pixel_clock_in_10khz) { + /* match found */ + *audio_clock_info = clock_info[index]; + return; + } + } + } + + /* not found */ + if (actual_pixel_clock_100Hz == 0) + actual_pixel_clock_100Hz = crtc_pixel_clock_100Hz; + + /* See HDMI spec the table entry under + * pixel clock of "Other". */ + audio_clock_info->pixel_clock_in_10khz = + actual_pixel_clock_100Hz / 100; + audio_clock_info->cts_32khz = actual_pixel_clock_100Hz / 10; + audio_clock_info->cts_44khz = actual_pixel_clock_100Hz / 10; + audio_clock_info->cts_48khz = actual_pixel_clock_100Hz / 10; + + audio_clock_info->n_32khz = 4096; + audio_clock_info->n_44khz = 6272; + audio_clock_info->n_48khz = 6144; +} + +static void enc1_se_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *audio_info) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + uint32_t channels = 0; + + ASSERT(audio_info); + if (audio_info == NULL) + /* This should not happen.it does so we don't get BSOD*/ + return; + + channels = speakers_to_channels(audio_info->flags.speaker_flags).all; + + /* setup the audio stream source select (audio -> dig mapping) */ + REG_SET(AFMT_AUDIO_SRC_CONTROL, 0, AFMT_AUDIO_SRC_SELECT, az_inst); + + /* Channel allocation */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, channels); +} + +static void enc1_se_setup_hdmi_audio( + struct stream_encoder *enc, + const struct audio_crtc_info *crtc_info) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + struct audio_clock_info audio_clock_info = {0}; + + /* HDMI_AUDIO_PACKET_CONTROL */ + REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, + HDMI_AUDIO_DELAY_EN, 1); + + /* AFMT_AUDIO_PACKET_CONTROL */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); + + /* AFMT_AUDIO_PACKET_CONTROL2 */ + REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, + AFMT_AUDIO_LAYOUT_OVRD, 0, + AFMT_60958_OSF_OVRD, 0); + + /* HDMI_ACR_PACKET_CONTROL */ + REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL, + HDMI_ACR_AUTO_SEND, 1, + HDMI_ACR_SOURCE, 0, + HDMI_ACR_AUDIO_PRIORITY, 0); + + /* Program audio clock sample/regeneration parameters */ + get_audio_clock_info(crtc_info->color_depth, + crtc_info->requested_pixel_clock_100Hz, + crtc_info->calculated_pixel_clock_100Hz, + &audio_clock_info); + DC_LOG_HW_AUDIO( + "\n%s:Input::requested_pixel_clock_100Hz = %d" \ + "calculated_pixel_clock_100Hz = %d \n", __func__, \ + crtc_info->requested_pixel_clock_100Hz, \ + crtc_info->calculated_pixel_clock_100Hz); + + /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ + REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); + + /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ + REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); + + /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ + REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); + + /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ + REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); + + /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ + REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); + + /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ + REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); + + /* Video driver cannot know in advance which sample rate will + * be used by HD Audio driver + * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is + * programmed below in interruppt callback + */ + + /* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK & + * AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK + */ + REG_UPDATE_2(AFMT_60958_0, + AFMT_60958_CS_CHANNEL_NUMBER_L, 1, + AFMT_60958_CS_CLOCK_ACCURACY, 0); + + /* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */ + REG_UPDATE(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, 2); + + /* AFMT_60958_2 now keep this settings until + * Programming guide comes out + */ + REG_UPDATE_6(AFMT_60958_2, + AFMT_60958_CS_CHANNEL_NUMBER_2, 3, + AFMT_60958_CS_CHANNEL_NUMBER_3, 4, + AFMT_60958_CS_CHANNEL_NUMBER_4, 5, + AFMT_60958_CS_CHANNEL_NUMBER_5, 6, + AFMT_60958_CS_CHANNEL_NUMBER_6, 7, + AFMT_60958_CS_CHANNEL_NUMBER_7, 8); +} + +static void enc1_se_setup_dp_audio( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* --- DP Audio packet configurations --- */ + + /* ATP Configuration */ + REG_SET(DP_SEC_AUD_N, 0, + DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); + + /* Async/auto-calc timestamp mode */ + REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, + DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); + + /* --- The following are the registers + * copied from the SetupHDMI --- + */ + + /* AFMT_AUDIO_PACKET_CONTROL */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); + + /* AFMT_AUDIO_PACKET_CONTROL2 */ + /* Program the ATP and AIP next */ + REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, + AFMT_AUDIO_LAYOUT_OVRD, 0, + AFMT_60958_OSF_OVRD, 0); + + /* AFMT_INFOFRAME_CONTROL0 */ + REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); + + /* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ + REG_UPDATE(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, 0); +} + +void enc1_se_enable_audio_clock( + struct stream_encoder *enc, + bool enable) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (REG(AFMT_CNTL) == 0) + return; /* DCE8/10 does not have this register */ + + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, !!enable); + + /* wait for AFMT clock to turn on, + * expectation: this should complete in 1-2 reads + * + * REG_WAIT(AFMT_CNTL, AFMT_AUDIO_CLOCK_ON, !!enable, 1, 10); + * + * TODO: wait for clock_on does not work well. May need HW + * program sequence. But audio seems work normally even without wait + * for clock_on status change + */ +} + +void enc1_se_enable_dp_audio( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* Enable Audio packets */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, 1); + + /* Program the ATP and AIP next */ + REG_UPDATE_2(DP_SEC_CNTL, + DP_SEC_ATP_ENABLE, 1, + DP_SEC_AIP_ENABLE, 1); + + /* Program STREAM_ENABLE after all the other enables. */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static void enc1_se_disable_dp_audio( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + + /* Disable Audio packets */ + REG_UPDATE_5(DP_SEC_CNTL, + DP_SEC_ASP_ENABLE, 0, + DP_SEC_ATP_ENABLE, 0, + DP_SEC_AIP_ENABLE, 0, + DP_SEC_ACM_ENABLE, 0, + DP_SEC_STREAM_ENABLE, 0); + + /* This register shared with encoder info frame. Therefore we need to + * keep master enabled if at least on of the fields is not 0 + */ + value = REG_READ(DP_SEC_CNTL); + if (value != 0) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); + +} + +void enc1_se_audio_mute_control( + struct stream_encoder *enc, + bool mute) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, !mute); +} + +void enc1_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info) +{ + enc1_se_audio_setup(enc, az_inst, info); +} + +void enc1_se_dp_audio_enable( + struct stream_encoder *enc) +{ + enc1_se_enable_audio_clock(enc, true); + enc1_se_setup_dp_audio(enc); + enc1_se_enable_dp_audio(enc); +} + +void enc1_se_dp_audio_disable( + struct stream_encoder *enc) +{ + enc1_se_disable_dp_audio(enc); + enc1_se_enable_audio_clock(enc, false); +} + +void enc1_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info) +{ + enc1_se_enable_audio_clock(enc, true); + enc1_se_setup_hdmi_audio(enc, audio_crtc_info); + enc1_se_audio_setup(enc, az_inst, info); +} + +void enc1_se_hdmi_audio_disable( + struct stream_encoder *enc) +{ + if (enc->afmt && enc->afmt->funcs->afmt_powerdown) + enc->afmt->funcs->afmt_powerdown(enc->afmt); + + enc1_se_enable_audio_clock(enc, false); +} + + +void enc1_setup_stereo_sync( + struct stream_encoder *enc, + int tg_inst, bool enable) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, tg_inst); + REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, !enable); +} + +void enc1_dig_connect_to_otg( + struct stream_encoder *enc, + int tg_inst) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE(DIG_FE_CNTL, DIG_SOURCE_SELECT, tg_inst); +} + +unsigned int enc1_dig_source_otg( + struct stream_encoder *enc) +{ + uint32_t tg_inst = 0; + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_GET(DIG_FE_CNTL, DIG_SOURCE_SELECT, &tg_inst); + + return tg_inst; +} + +bool enc1_stream_encoder_dp_get_pixel_format( + struct stream_encoder *enc, + enum dc_pixel_encoding *encoding, + enum dc_color_depth *depth) +{ + uint32_t hw_encoding = 0; + uint32_t hw_depth = 0; + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (enc == NULL || + encoding == NULL || + depth == NULL) + return false; + + REG_GET_2(DP_PIXEL_FORMAT, + DP_PIXEL_ENCODING, &hw_encoding, + DP_COMPONENT_DEPTH, &hw_depth); + + switch (hw_depth) { + case DP_COMPONENT_PIXEL_DEPTH_6BPC: + *depth = COLOR_DEPTH_666; + break; + case DP_COMPONENT_PIXEL_DEPTH_8BPC: + *depth = COLOR_DEPTH_888; + break; + case DP_COMPONENT_PIXEL_DEPTH_10BPC: + *depth = COLOR_DEPTH_101010; + break; + case DP_COMPONENT_PIXEL_DEPTH_12BPC: + *depth = COLOR_DEPTH_121212; + break; + case DP_COMPONENT_PIXEL_DEPTH_16BPC: + *depth = COLOR_DEPTH_161616; + break; + default: + *depth = COLOR_DEPTH_UNDEFINED; + break; + } + + switch (hw_encoding) { + case DP_PIXEL_ENCODING_TYPE_RGB444: + *encoding = PIXEL_ENCODING_RGB; + break; + case DP_PIXEL_ENCODING_TYPE_YCBCR422: + *encoding = PIXEL_ENCODING_YCBCR422; + break; + case DP_PIXEL_ENCODING_TYPE_YCBCR444: + case DP_PIXEL_ENCODING_TYPE_Y_ONLY: + *encoding = PIXEL_ENCODING_YCBCR444; + break; + case DP_PIXEL_ENCODING_TYPE_YCBCR420: + *encoding = PIXEL_ENCODING_YCBCR420; + break; + default: + *encoding = PIXEL_ENCODING_UNDEFINED; + break; + } + return true; +} + +static const struct stream_encoder_funcs dcn10_str_enc_funcs = { + .dp_set_stream_attribute = + enc1_stream_encoder_dp_set_stream_attribute, + .hdmi_set_stream_attribute = + enc1_stream_encoder_hdmi_set_stream_attribute, + .dvi_set_stream_attribute = + enc1_stream_encoder_dvi_set_stream_attribute, + .set_throttled_vcp_size = + enc1_stream_encoder_set_throttled_vcp_size, + .update_hdmi_info_packets = + enc1_stream_encoder_update_hdmi_info_packets, + .stop_hdmi_info_packets = + enc1_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets = + enc1_stream_encoder_update_dp_info_packets, + .send_immediate_sdp_message = + enc1_stream_encoder_send_immediate_sdp_message, + .stop_dp_info_packets = + enc1_stream_encoder_stop_dp_info_packets, + .dp_blank = + enc1_stream_encoder_dp_blank, + .dp_unblank = + enc1_stream_encoder_dp_unblank, + .audio_mute_control = enc1_se_audio_mute_control, + + .dp_audio_setup = enc1_se_dp_audio_setup, + .dp_audio_enable = enc1_se_dp_audio_enable, + .dp_audio_disable = enc1_se_dp_audio_disable, + + .hdmi_audio_setup = enc1_se_hdmi_audio_setup, + .hdmi_audio_disable = enc1_se_hdmi_audio_disable, + .setup_stereo_sync = enc1_setup_stereo_sync, + .set_avmute = enc1_stream_encoder_set_avmute, + .dig_connect_to_otg = enc1_dig_connect_to_otg, + .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, + .dig_source_otg = enc1_dig_source_otg, + + .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, +}; + +void dcn10_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask) +{ + enc1->base.funcs = &dcn10_str_enc_funcs; + enc1->base.ctx = ctx; + enc1->base.id = eng_id; + enc1->base.bp = bp; + enc1->regs = regs; + enc1->se_shift = se_shift; + enc1->se_mask = se_mask; + enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h new file mode 100644 index 000000000000..54a6a4ebd636 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h @@ -0,0 +1,749 @@ +/* + * 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 + * + */ + +#ifndef __DC_STREAM_ENCODER_DCN10_H__ +#define __DC_STREAM_ENCODER_DCN10_H__ + +#include "stream_encoder.h" + +#define DCN10STRENC_FROM_STRENC(stream_encoder)\ + container_of(stream_encoder, struct dcn10_stream_encoder, base) + +#define SE_COMMON_DCN_REG_LIST(id) \ + SRI(AFMT_CNTL, DIG, id), \ + SRI(AFMT_GENERIC_0, DIG, id), \ + SRI(AFMT_GENERIC_1, DIG, id), \ + SRI(AFMT_GENERIC_2, DIG, id), \ + SRI(AFMT_GENERIC_3, DIG, id), \ + SRI(AFMT_GENERIC_4, DIG, id), \ + SRI(AFMT_GENERIC_5, DIG, id), \ + SRI(AFMT_GENERIC_6, DIG, id), \ + SRI(AFMT_GENERIC_7, DIG, id), \ + SRI(AFMT_GENERIC_HDR, DIG, id), \ + SRI(AFMT_INFOFRAME_CONTROL0, DIG, id), \ + SRI(AFMT_VBI_PACKET_CONTROL, DIG, id), \ + SRI(AFMT_VBI_PACKET_CONTROL1, DIG, id), \ + SRI(AFMT_AUDIO_PACKET_CONTROL, DIG, id), \ + SRI(AFMT_AUDIO_PACKET_CONTROL2, DIG, id), \ + SRI(AFMT_AUDIO_SRC_CONTROL, DIG, id), \ + SRI(AFMT_60958_0, DIG, id), \ + SRI(AFMT_60958_1, DIG, id), \ + SRI(AFMT_60958_2, DIG, id), \ + SRI(DIG_FE_CNTL, DIG, id), \ + SRI(DIG_FIFO_STATUS, DIG, id), \ + SRI(HDMI_CONTROL, DIG, id), \ + SRI(HDMI_DB_CONTROL, DIG, id), \ + SRI(HDMI_GC, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \ + SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \ + SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_32_0, DIG, id),\ + SRI(HDMI_ACR_32_1, DIG, id),\ + SRI(HDMI_ACR_44_0, DIG, id),\ + SRI(HDMI_ACR_44_1, DIG, id),\ + SRI(HDMI_ACR_48_0, DIG, id),\ + SRI(HDMI_ACR_48_1, DIG, id),\ + SRI(DP_DB_CNTL, DP, id), \ + SRI(DP_MSA_MISC, DP, id), \ + SRI(DP_MSA_VBID_MISC, DP, id), \ + SRI(DP_MSA_COLORIMETRY, DP, id), \ + SRI(DP_MSA_TIMING_PARAM1, DP, id), \ + SRI(DP_MSA_TIMING_PARAM2, DP, id), \ + SRI(DP_MSA_TIMING_PARAM3, DP, id), \ + SRI(DP_MSA_TIMING_PARAM4, DP, id), \ + SRI(DP_MSE_RATE_CNTL, DP, id), \ + SRI(DP_MSE_RATE_UPDATE, DP, id), \ + SRI(DP_PIXEL_FORMAT, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id), \ + SRI(DP_SEC_CNTL2, DP, id), \ + SRI(DP_SEC_CNTL5, DP, id), \ + SRI(DP_SEC_CNTL6, DP, id), \ + SRI(DP_STEER_FIFO, DP, id), \ + SRI(DP_VID_M, DP, id), \ + SRI(DP_VID_N, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_VID_TIMING, DP, id), \ + SRI(DP_SEC_AUD_N, DP, id), \ + SRI(DP_SEC_AUD_N_READBACK, DP, id), \ + SRI(DP_SEC_AUD_M_READBACK, DP, id), \ + SRI(DP_SEC_TIMESTAMP, DP, id), \ + SRI(DIG_CLOCK_PATTERN, DIG, id) + +#define SE_DCN_REG_LIST(id)\ + SE_COMMON_DCN_REG_LIST(id) + + +struct dcn10_stream_enc_registers { + uint32_t AFMT_CNTL; + uint32_t AFMT_AVI_INFO0; + uint32_t AFMT_AVI_INFO1; + uint32_t AFMT_AVI_INFO2; + uint32_t AFMT_AVI_INFO3; + uint32_t AFMT_GENERIC_0; + uint32_t AFMT_GENERIC_1; + uint32_t AFMT_GENERIC_2; + uint32_t AFMT_GENERIC_3; + uint32_t AFMT_GENERIC_4; + uint32_t AFMT_GENERIC_5; + uint32_t AFMT_GENERIC_6; + uint32_t AFMT_GENERIC_7; + uint32_t AFMT_GENERIC_HDR; + uint32_t AFMT_INFOFRAME_CONTROL0; + uint32_t AFMT_VBI_PACKET_CONTROL; + uint32_t AFMT_VBI_PACKET_CONTROL1; + uint32_t AFMT_AUDIO_PACKET_CONTROL; + uint32_t AFMT_AUDIO_PACKET_CONTROL2; + uint32_t AFMT_AUDIO_SRC_CONTROL; + uint32_t AFMT_60958_0; + uint32_t AFMT_60958_1; + uint32_t AFMT_60958_2; + uint32_t DIG_FE_CNTL; + uint32_t DIG_FIFO_STATUS; + uint32_t DP_MSE_RATE_CNTL; + uint32_t DP_MSE_RATE_UPDATE; + uint32_t DP_PIXEL_FORMAT; + uint32_t DP_SEC_CNTL; + uint32_t DP_SEC_CNTL1; + uint32_t DP_SEC_CNTL2; + uint32_t DP_SEC_CNTL5; + uint32_t DP_SEC_CNTL6; + uint32_t DP_STEER_FIFO; + uint32_t DP_VID_M; + uint32_t DP_VID_N; + uint32_t DP_VID_STREAM_CNTL; + uint32_t DP_VID_TIMING; + uint32_t DP_SEC_AUD_N; + uint32_t DP_SEC_AUD_N_READBACK; + uint32_t DP_SEC_AUD_M_READBACK; + uint32_t DP_SEC_TIMESTAMP; + uint32_t HDMI_CONTROL; + uint32_t HDMI_GC; + uint32_t HDMI_GENERIC_PACKET_CONTROL0; + uint32_t HDMI_GENERIC_PACKET_CONTROL1; + uint32_t HDMI_GENERIC_PACKET_CONTROL2; + uint32_t HDMI_GENERIC_PACKET_CONTROL3; + uint32_t HDMI_GENERIC_PACKET_CONTROL4; + uint32_t HDMI_GENERIC_PACKET_CONTROL5; + uint32_t HDMI_INFOFRAME_CONTROL0; + uint32_t HDMI_INFOFRAME_CONTROL1; + uint32_t HDMI_VBI_PACKET_CONTROL; + uint32_t HDMI_AUDIO_PACKET_CONTROL; + uint32_t HDMI_ACR_PACKET_CONTROL; + uint32_t HDMI_ACR_32_0; + uint32_t HDMI_ACR_32_1; + uint32_t HDMI_ACR_44_0; + uint32_t HDMI_ACR_44_1; + uint32_t HDMI_ACR_48_0; + uint32_t HDMI_ACR_48_1; + uint32_t DP_DB_CNTL; + uint32_t DP_MSA_MISC; + uint32_t DP_MSA_VBID_MISC; + uint32_t DP_MSA_COLORIMETRY; + uint32_t DP_MSA_TIMING_PARAM1; + uint32_t DP_MSA_TIMING_PARAM2; + uint32_t DP_MSA_TIMING_PARAM3; + uint32_t DP_MSA_TIMING_PARAM4; + uint32_t HDMI_DB_CONTROL; + uint32_t DP_DSC_CNTL; + uint32_t DP_DSC_BYTES_PER_PIXEL; + uint32_t DME_CONTROL; + uint32_t DP_SEC_METADATA_TRANSMISSION; + uint32_t HDMI_METADATA_PACKET_CONTROL; + uint32_t DP_SEC_FRAMING4; + uint32_t DP_GSP11_CNTL; + uint32_t HDMI_GENERIC_PACKET_CONTROL6; + uint32_t HDMI_GENERIC_PACKET_CONTROL7; + uint32_t HDMI_GENERIC_PACKET_CONTROL8; + uint32_t HDMI_GENERIC_PACKET_CONTROL9; + uint32_t HDMI_GENERIC_PACKET_CONTROL10; + uint32_t DIG_CLOCK_PATTERN; + uint32_t DIG_FIFO_CTRL0; + uint32_t DIG_FE_CLK_CNTL; + uint32_t DIG_FE_EN_CNTL; + uint32_t STREAM_MAPPER_CONTROL; +}; + + +#define SE_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB3, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ + SE_SF(DIG0_AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ + SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ + SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ + SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_START, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ + SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\ + SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\ + SE_SF(DIG0_AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N_READBACK, DP_SEC_AUD_N_READBACK, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_M_READBACK, DP_SEC_AUD_M_READBACK, mask_sh),\ + SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh),\ + SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_LEVEL_ERROR, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_USE_OVERWRITE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_OVERWRITE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_ERROR_ACK, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CAL_AVERAGE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MAXIMUM_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MINIMUM_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_READ_CLOCK_SRC, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CALIBRATED, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECAL_AVERAGE, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECOMP_MINMAX, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_PPS, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ + SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh),\ + SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh) + +#define SE_COMMON_MASK_SH_LIST_DCN10(mask_sh)\ + SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_LINE, mask_sh) + + +#define SE_REG_FIELD_LIST_DCN1_0(type) \ + type AFMT_GENERIC_INDEX;\ + type AFMT_GENERIC_HB0;\ + type AFMT_GENERIC_HB1;\ + type AFMT_GENERIC_HB2;\ + type AFMT_GENERIC_HB3;\ + type AFMT_GENERIC_LOCK_STATUS;\ + type AFMT_GENERIC_CONFLICT;\ + type AFMT_GENERIC_CONFLICT_CLR;\ + type AFMT_GENERIC0_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC1_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC2_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC3_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC4_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC4_IMMEDIATE_UPDATE_PENDING;\ + type AFMT_GENERIC5_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC6_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC7_FRAME_UPDATE_PENDING;\ + type AFMT_GENERIC0_FRAME_UPDATE;\ + type AFMT_GENERIC1_FRAME_UPDATE;\ + type AFMT_GENERIC2_FRAME_UPDATE;\ + type AFMT_GENERIC3_FRAME_UPDATE;\ + type AFMT_GENERIC4_FRAME_UPDATE;\ + type AFMT_GENERIC0_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC1_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC2_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC3_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC4_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC5_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC6_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC7_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC5_FRAME_UPDATE;\ + type AFMT_GENERIC6_FRAME_UPDATE;\ + type AFMT_GENERIC7_FRAME_UPDATE;\ + type HDMI_GENERIC0_CONT;\ + type HDMI_GENERIC0_SEND;\ + type HDMI_GENERIC0_LINE;\ + type HDMI_GENERIC1_CONT;\ + type HDMI_GENERIC1_SEND;\ + type HDMI_GENERIC1_LINE;\ + type HDMI_GENERIC2_CONT;\ + type HDMI_GENERIC2_SEND;\ + type HDMI_GENERIC2_LINE;\ + type HDMI_GENERIC3_CONT;\ + type HDMI_GENERIC3_SEND;\ + type HDMI_GENERIC3_LINE;\ + type HDMI_GENERIC4_CONT;\ + type HDMI_GENERIC4_SEND;\ + type HDMI_GENERIC4_LINE;\ + type HDMI_GENERIC5_CONT;\ + type HDMI_GENERIC5_SEND;\ + type HDMI_GENERIC5_LINE;\ + type HDMI_GENERIC6_CONT;\ + type HDMI_GENERIC6_SEND;\ + type HDMI_GENERIC6_LINE;\ + type HDMI_GENERIC7_CONT;\ + type HDMI_GENERIC7_SEND;\ + type HDMI_GENERIC7_LINE;\ + type DP_PIXEL_ENCODING;\ + type DP_COMPONENT_DEPTH;\ + type HDMI_PACKET_GEN_VERSION;\ + type HDMI_KEEPOUT_MODE;\ + type HDMI_DEEP_COLOR_ENABLE;\ + type HDMI_CLOCK_CHANNEL_RATE;\ + type HDMI_DEEP_COLOR_DEPTH;\ + type HDMI_GC_CONT;\ + type HDMI_GC_SEND;\ + type HDMI_NULL_SEND;\ + type HDMI_DATA_SCRAMBLE_EN;\ + type HDMI_NO_EXTRA_NULL_PACKET_FILLED;\ + type HDMI_AUDIO_INFO_SEND;\ + type AFMT_AUDIO_INFO_UPDATE;\ + type HDMI_AUDIO_INFO_LINE;\ + type HDMI_GC_AVMUTE;\ + type DP_MSE_RATE_X;\ + type DP_MSE_RATE_Y;\ + type DP_MSE_RATE_UPDATE_PENDING;\ + type DP_SEC_GSP0_ENABLE;\ + type DP_SEC_STREAM_ENABLE;\ + type DP_SEC_GSP1_ENABLE;\ + type DP_SEC_GSP2_ENABLE;\ + type DP_SEC_GSP3_ENABLE;\ + type DP_SEC_GSP4_ENABLE;\ + type DP_SEC_GSP5_ENABLE;\ + type DP_SEC_GSP5_LINE_NUM;\ + type DP_SEC_GSP5_LINE_REFERENCE;\ + type DP_SEC_GSP6_ENABLE;\ + type DP_SEC_GSP7_ENABLE;\ + type DP_SEC_GSP7_PPS;\ + type DP_SEC_GSP7_SEND;\ + type DP_SEC_GSP4_SEND;\ + type DP_SEC_GSP4_SEND_PENDING;\ + type DP_SEC_GSP4_LINE_NUM;\ + type DP_SEC_GSP4_SEND_ANY_LINE;\ + type DP_SEC_MPG_ENABLE;\ + type DP_VID_STREAM_DIS_DEFER;\ + type DP_VID_STREAM_ENABLE;\ + type DP_VID_STREAM_STATUS;\ + type DP_STEER_FIFO_RESET;\ + type DP_VID_M_N_GEN_EN;\ + type DP_VID_N;\ + type DP_VID_M;\ + type DIG_START;\ + type AFMT_AUDIO_SRC_SELECT;\ + type AFMT_AUDIO_CHANNEL_ENABLE;\ + type HDMI_AUDIO_PACKETS_PER_LINE;\ + type HDMI_AUDIO_DELAY_EN;\ + type AFMT_60958_CS_UPDATE;\ + type AFMT_AUDIO_LAYOUT_OVRD;\ + type AFMT_60958_OSF_OVRD;\ + type HDMI_ACR_AUTO_SEND;\ + type HDMI_ACR_SOURCE;\ + type HDMI_ACR_AUDIO_PRIORITY;\ + type HDMI_ACR_CTS_32;\ + type HDMI_ACR_N_32;\ + type HDMI_ACR_CTS_44;\ + type HDMI_ACR_N_44;\ + type HDMI_ACR_CTS_48;\ + type HDMI_ACR_N_48;\ + type AFMT_60958_CS_CHANNEL_NUMBER_L;\ + type AFMT_60958_CS_CLOCK_ACCURACY;\ + type AFMT_60958_CS_CHANNEL_NUMBER_R;\ + type AFMT_60958_CS_CHANNEL_NUMBER_2;\ + type AFMT_60958_CS_CHANNEL_NUMBER_3;\ + type AFMT_60958_CS_CHANNEL_NUMBER_4;\ + type AFMT_60958_CS_CHANNEL_NUMBER_5;\ + type AFMT_60958_CS_CHANNEL_NUMBER_6;\ + type AFMT_60958_CS_CHANNEL_NUMBER_7;\ + type DP_SEC_AUD_N;\ + type DP_SEC_AUD_N_READBACK;\ + type DP_SEC_AUD_M_READBACK;\ + type DP_SEC_TIMESTAMP_MODE;\ + type DP_SEC_ASP_ENABLE;\ + type DP_SEC_ATP_ENABLE;\ + type DP_SEC_AIP_ENABLE;\ + type DP_SEC_ACM_ENABLE;\ + type DP_SEC_GSP7_LINE_NUM;\ + type AFMT_AUDIO_SAMPLE_SEND;\ + type AFMT_AUDIO_CLOCK_EN;\ + type TMDS_PIXEL_ENCODING;\ + type TMDS_COLOR_FORMAT;\ + type DIG_STEREOSYNC_SELECT;\ + type DIG_STEREOSYNC_GATE_EN;\ + type DP_DB_DISABLE;\ + type DP_MSA_MISC0;\ + type DP_MSA_HTOTAL;\ + type DP_MSA_VTOTAL;\ + type DP_MSA_HSTART;\ + type DP_MSA_VSTART;\ + type DP_MSA_HSYNCWIDTH;\ + type DP_MSA_HSYNCPOLARITY;\ + type DP_MSA_VSYNCWIDTH;\ + type DP_MSA_VSYNCPOLARITY;\ + type DP_MSA_HWIDTH;\ + type DP_MSA_VHEIGHT;\ + type HDMI_DB_DISABLE;\ + type DP_VID_N_MUL;\ + type DP_VID_M_DOUBLE_VALUE_EN;\ + type DIG_SOURCE_SELECT;\ + type DIG_FIFO_LEVEL_ERROR;\ + type DIG_FIFO_USE_OVERWRITE_LEVEL;\ + type DIG_FIFO_OVERWRITE_LEVEL;\ + type DIG_FIFO_ERROR_ACK;\ + type DIG_FIFO_CAL_AVERAGE_LEVEL;\ + type DIG_FIFO_MAXIMUM_LEVEL;\ + type DIG_FIFO_MINIMUM_LEVEL;\ + type DIG_FIFO_READ_CLOCK_SRC;\ + type DIG_FIFO_CALIBRATED;\ + type DIG_FIFO_FORCE_RECAL_AVERAGE;\ + type DIG_FIFO_FORCE_RECOMP_MINMAX;\ + type DIG_CLOCK_PATTERN + +#define SE_REG_FIELD_LIST_DCN2_0(type) \ + type DP_DSC_MODE;\ + type DP_DSC_SLICE_WIDTH;\ + type DP_DSC_BYTES_PER_PIXEL;\ + type DP_VBID6_LINE_REFERENCE;\ + type DP_VBID6_LINE_NUM;\ + type METADATA_ENGINE_EN;\ + type METADATA_HUBP_REQUESTOR_ID;\ + type METADATA_STREAM_TYPE;\ + type DP_SEC_METADATA_PACKET_ENABLE;\ + type DP_SEC_METADATA_PACKET_LINE_REFERENCE;\ + type DP_SEC_METADATA_PACKET_LINE;\ + type HDMI_METADATA_PACKET_ENABLE;\ + type HDMI_METADATA_PACKET_LINE_REFERENCE;\ + type HDMI_METADATA_PACKET_LINE;\ + type DOLBY_VISION_EN;\ + type DP_PIXEL_COMBINE;\ + type DP_SST_SDP_SPLITTING + +#define SE_REG_FIELD_LIST_DCN3_0(type) \ + type HDMI_GENERIC8_CONT;\ + type HDMI_GENERIC8_SEND;\ + type HDMI_GENERIC8_LINE;\ + type HDMI_GENERIC9_CONT;\ + type HDMI_GENERIC9_SEND;\ + type HDMI_GENERIC9_LINE;\ + type HDMI_GENERIC10_CONT;\ + type HDMI_GENERIC10_SEND;\ + type HDMI_GENERIC10_LINE;\ + type HDMI_GENERIC11_CONT;\ + type HDMI_GENERIC11_SEND;\ + type HDMI_GENERIC11_LINE;\ + type HDMI_GENERIC12_CONT;\ + type HDMI_GENERIC12_SEND;\ + type HDMI_GENERIC12_LINE;\ + type HDMI_GENERIC13_CONT;\ + type HDMI_GENERIC13_SEND;\ + type HDMI_GENERIC13_LINE;\ + type HDMI_GENERIC14_CONT;\ + type HDMI_GENERIC14_SEND;\ + type HDMI_GENERIC14_LINE;\ + type DP_SEC_GSP11_PPS;\ + type DP_SEC_GSP11_ENABLE;\ + type DP_SEC_GSP11_LINE_NUM + +#define SE_REG_FIELD_LIST_DCN3_1_COMMON(type) \ + type DIG_FIFO_OUTPUT_PIXEL_MODE;\ + type DP_PIXEL_PER_CYCLE_PROCESSING_MODE;\ + type DIG_SYMCLK_FE_ON;\ + type DIG_FIFO_READ_START_LEVEL;\ + type DIG_FIFO_ENABLE;\ + type DIG_FIFO_RESET;\ + type DIG_FIFO_RESET_DONE;\ + type PIXEL_ENCODING_TYPE;\ + type UNCOMPRESSED_PIXEL_FORMAT;\ + type UNCOMPRESSED_COMPONENT_DEPTH + +#define SE_REG_FIELD_LIST_DCN3_5_COMMON(type) \ + type DIG_FE_CLK_EN;\ + type DIG_FE_MODE;\ + type DIG_FE_SOFT_RESET;\ + type DIG_FE_ENABLE;\ + type DIG_FE_SYMCLK_FE_G_CLOCK_ON;\ + type DIG_FE_DISPCLK_G_CLOCK_ON;\ + type DIG_FE_SYMCLK_FE_G_AFMT_CLOCK_ON;\ + type DIG_FE_SYMCLK_FE_G_TMDS_CLOCK_ON;\ + type DIG_FE_SOCCLK_G_AFMT_CLOCK_ON;\ + type DIG_STREAM_LINK_TARGET + +#define SE_REG_FIELD_LIST_DCN4_01_COMMON(type) \ + type COMPRESSED_PIXEL_FORMAT;\ + type DP_VID_N_INTERVAL;\ + type DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE;\ + type DP_STEER_FIFO_ENABLE +struct dcn10_stream_encoder_shift { + SE_REG_FIELD_LIST_DCN1_0(uint8_t); + uint8_t HDMI_ACP_SEND; + SE_REG_FIELD_LIST_DCN2_0(uint8_t); + SE_REG_FIELD_LIST_DCN3_0(uint8_t); + SE_REG_FIELD_LIST_DCN3_1_COMMON(uint8_t); + SE_REG_FIELD_LIST_DCN3_5_COMMON(uint8_t); + SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); +}; + +struct dcn10_stream_encoder_mask { + SE_REG_FIELD_LIST_DCN1_0(uint32_t); + uint32_t HDMI_ACP_SEND; + SE_REG_FIELD_LIST_DCN2_0(uint32_t); + SE_REG_FIELD_LIST_DCN3_0(uint32_t); + SE_REG_FIELD_LIST_DCN3_1_COMMON(uint32_t); + SE_REG_FIELD_LIST_DCN3_5_COMMON(uint32_t); + SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); +}; + +struct dcn10_stream_encoder { + struct stream_encoder base; + const struct dcn10_stream_enc_registers *regs; + const struct dcn10_stream_encoder_shift *se_shift; + const struct dcn10_stream_encoder_mask *se_mask; +}; + +void dcn10_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask); + +void enc1_update_generic_info_packet( + struct dcn10_stream_encoder *enc1, + uint32_t packet_index, + const struct dc_info_packet *info_packet); + +void enc1_stream_encoder_dp_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space, + bool use_vsc_sdp_for_colorimetry, + uint32_t enable_sdp_splitting); + +void enc1_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio); + +void enc1_stream_encoder_dvi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link); + +void enc1_stream_encoder_set_throttled_vcp_size( + struct stream_encoder *enc, + struct fixed31_32 avg_time_slots_per_mtp); + +void enc1_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame); + +void enc1_stream_encoder_send_immediate_sdp_message( + struct stream_encoder *enc, + const uint8_t *custom_sdp_message, + unsigned int sdp_message_size); + +void enc1_stream_encoder_stop_dp_info_packets( + struct stream_encoder *enc); + +void enc1_stream_encoder_dp_blank( + struct dc_link *link, + struct stream_encoder *enc); + +void enc1_stream_encoder_dp_unblank( + struct dc_link *link, + struct stream_encoder *enc, + const struct encoder_unblank_param *param); + +void enc1_setup_stereo_sync( + struct stream_encoder *enc, + int tg_inst, bool enable); + +void enc1_stream_encoder_set_avmute( + struct stream_encoder *enc, + bool enable); + +void enc1_se_audio_mute_control( + struct stream_encoder *enc, + bool mute); + +void enc1_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info); + +void enc1_se_dp_audio_enable( + struct stream_encoder *enc); + +void enc1_se_dp_audio_disable( + struct stream_encoder *enc); + +void enc1_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info); + +void enc1_se_hdmi_audio_disable( + struct stream_encoder *enc); + +void enc1_dig_connect_to_otg( + struct stream_encoder *enc, + int tg_inst); + +unsigned int enc1_dig_source_otg( + struct stream_encoder *enc); + +void enc1_stream_encoder_set_stream_attribute_helper( + struct dcn10_stream_encoder *enc1, + struct dc_crtc_timing *crtc_timing); + +void enc1_se_enable_audio_clock( + struct stream_encoder *enc, + bool enable); + +void enc1_se_enable_dp_audio( + struct stream_encoder *enc); + +void get_audio_clock_info( + enum dc_color_depth color_depth, + uint32_t crtc_pixel_clock_100Hz, + uint32_t actual_pixel_clock_100Hz, + struct audio_clock_info *audio_clock_info); + +void enc1_reset_hdmi_stream_attribute( + struct stream_encoder *enc); + +bool enc1_stream_encoder_dp_get_pixel_format( + struct stream_encoder *enc, + enum dc_pixel_encoding *encoding, + enum dc_color_depth *depth); + +#endif /* __DC_STREAM_ENCODER_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c new file mode 100644 index 000000000000..51a57dae1811 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c @@ -0,0 +1,502 @@ +/* + * 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 "reg_helper.h" + +#include "core_types.h" +#include "link_encoder.h" +#include "dcn20_link_encoder.h" +#include "stream_encoder.h" +#include "dc_bios_types.h" + +#include "gpio_service_interface.h" + +#define CTX \ + enc10->base.ctx +#define DC_LOGGER \ + enc10->base.ctx->logger + +#define REG(reg)\ + (enc10->link_regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc10->link_shift->field_name, enc10->link_mask->field_name + +#define IND_REG(index) \ + (enc10->link_regs->index) + +#ifndef MAX +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#endif +#ifndef MIN +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#endif + +static struct mpll_cfg dcn2_mpll_cfg[] = { + // RBR + { + .hdmimode_enable = 1, + .ref_range = 3, + .ref_clk_mpllb_div = 2, + .mpllb_ssc_en = 1, + .mpllb_div5_clk_en = 1, + .mpllb_multiplier = 226, + .mpllb_fracn_en = 1, + .mpllb_fracn_quot = 39321, + .mpllb_fracn_rem = 3, + .mpllb_fracn_den = 5, + .mpllb_ssc_up_spread = 0, + .mpllb_ssc_peak = 38221, + .mpllb_ssc_stepsize = 49314, + .mpllb_div_clk_en = 0, + .mpllb_div_multiplier = 0, + .mpllb_hdmi_div = 0, + .mpllb_tx_clk_div = 2, + .tx_vboost_lvl = 4, + .mpllb_pmix_en = 1, + .mpllb_word_div2_en = 0, + .mpllb_ana_v2i = 2, + .mpllb_ana_freq_vco = 2, + .mpllb_ana_cp_int = 7, + .mpllb_ana_cp_prop = 18, + .hdmi_pixel_clk_div = 0, + }, + // HBR + { + .hdmimode_enable = 1, + .ref_range = 3, + .ref_clk_mpllb_div = 2, + .mpllb_ssc_en = 1, + .mpllb_div5_clk_en = 1, + .mpllb_multiplier = 184, + .mpllb_fracn_en = 0, + .mpllb_fracn_quot = 0, + .mpllb_fracn_rem = 0, + .mpllb_fracn_den = 1, + .mpllb_ssc_up_spread = 0, + .mpllb_ssc_peak = 31850, + .mpllb_ssc_stepsize = 41095, + .mpllb_div_clk_en = 0, + .mpllb_div_multiplier = 0, + .mpllb_hdmi_div = 0, + .mpllb_tx_clk_div = 1, + .tx_vboost_lvl = 4, + .mpllb_pmix_en = 1, + .mpllb_word_div2_en = 0, + .mpllb_ana_v2i = 2, + .mpllb_ana_freq_vco = 3, + .mpllb_ana_cp_int = 7, + .mpllb_ana_cp_prop = 18, + .hdmi_pixel_clk_div = 0, + }, + //HBR2 + { + .hdmimode_enable = 1, + .ref_range = 3, + .ref_clk_mpllb_div = 2, + .mpllb_ssc_en = 1, + .mpllb_div5_clk_en = 1, + .mpllb_multiplier = 184, + .mpllb_fracn_en = 0, + .mpllb_fracn_quot = 0, + .mpllb_fracn_rem = 0, + .mpllb_fracn_den = 1, + .mpllb_ssc_up_spread = 0, + .mpllb_ssc_peak = 31850, + .mpllb_ssc_stepsize = 41095, + .mpllb_div_clk_en = 0, + .mpllb_div_multiplier = 0, + .mpllb_hdmi_div = 0, + .mpllb_tx_clk_div = 0, + .tx_vboost_lvl = 4, + .mpllb_pmix_en = 1, + .mpllb_word_div2_en = 0, + .mpllb_ana_v2i = 2, + .mpllb_ana_freq_vco = 3, + .mpllb_ana_cp_int = 7, + .mpllb_ana_cp_prop = 18, + .hdmi_pixel_clk_div = 0, + }, + //HBR3 + { + .hdmimode_enable = 1, + .ref_range = 3, + .ref_clk_mpllb_div = 2, + .mpllb_ssc_en = 1, + .mpllb_div5_clk_en = 1, + .mpllb_multiplier = 292, + .mpllb_fracn_en = 0, + .mpllb_fracn_quot = 0, + .mpllb_fracn_rem = 0, + .mpllb_fracn_den = 1, + .mpllb_ssc_up_spread = 0, + .mpllb_ssc_peak = 47776, + .mpllb_ssc_stepsize = 61642, + .mpllb_div_clk_en = 0, + .mpllb_div_multiplier = 0, + .mpllb_hdmi_div = 0, + .mpllb_tx_clk_div = 0, + .tx_vboost_lvl = 4, + .mpllb_pmix_en = 1, + .mpllb_word_div2_en = 0, + .mpllb_ana_v2i = 2, + .mpllb_ana_freq_vco = 0, + .mpllb_ana_cp_int = 7, + .mpllb_ana_cp_prop = 18, + .hdmi_pixel_clk_div = 0, + }, +}; + +void enc2_fec_set_enable(struct link_encoder *enc, bool enable) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + DC_LOG_DSC("%s FEC at link encoder inst %d", + enable ? "Enabling" : "Disabling", enc->id.enum_id); + REG_UPDATE(DP_DPHY_CNTL, DPHY_FEC_EN, enable); +} + +void enc2_fec_set_ready(struct link_encoder *enc, bool ready) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + REG_UPDATE(DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, ready); +} + +bool enc2_fec_is_active(struct link_encoder *enc) +{ + uint32_t active = 0; + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + REG_GET(DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, &active); + + return (active != 0); +} + +/* this function reads dsc related register fields to be logged later in dcn10_log_hw_state + * into a dcn_dsc_state struct. + */ +void link_enc2_read_state(struct link_encoder *enc, struct link_enc_state *s) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + REG_GET(DP_DPHY_CNTL, DPHY_FEC_EN, &s->dphy_fec_en); + REG_GET(DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, &s->dphy_fec_ready_shadow); + REG_GET(DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, &s->dphy_fec_active_status); + REG_GET(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, &s->dp_link_training_complete); +} + +static bool update_cfg_data( + struct dcn10_link_encoder *enc10, + const struct dc_link_settings *link_settings, + struct dpcssys_phy_seq_cfg *cfg) +{ + int i; + + cfg->load_sram_fw = false; + + for (i = 0; i < link_settings->lane_count; i++) + cfg->lane_en[i] = true; + + switch (link_settings->link_rate) { + case LINK_RATE_LOW: + cfg->mpll_cfg = dcn2_mpll_cfg[0]; + break; + case LINK_RATE_HIGH: + cfg->mpll_cfg = dcn2_mpll_cfg[1]; + break; + case LINK_RATE_HIGH2: + cfg->mpll_cfg = dcn2_mpll_cfg[2]; + break; + case LINK_RATE_HIGH3: + cfg->mpll_cfg = dcn2_mpll_cfg[3]; + break; + default: + DC_LOG_ERROR("%s: No supported link rate found %X!\n", + __func__, link_settings->link_rate); + return false; + } + + return true; +} + +void dcn20_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + struct dcn20_link_encoder *enc20 = (struct dcn20_link_encoder *) enc10; + struct dpcssys_phy_seq_cfg *cfg = &enc20->phy_seq_cfg; + + if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { + dcn10_link_encoder_enable_dp_output(enc, link_settings, clock_source); + return; + } + + if (!update_cfg_data(enc10, link_settings, cfg)) + return; + + enc1_configure_encoder(enc10, link_settings); + + dcn10_link_encoder_setup(enc, SIGNAL_TYPE_DISPLAY_PORT); + +} + +void dcn20_link_encoder_get_max_link_cap(struct link_encoder *enc, + struct dc_link_settings *link_settings) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t is_in_usb_c_dp4_mode = 0; + + dcn10_link_encoder_get_max_link_cap(enc, link_settings); + + /* in usb c dp2 mode, max lane count is 2 */ + if (enc->funcs->is_in_alt_mode && enc->funcs->is_in_alt_mode(enc)) { + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &is_in_usb_c_dp4_mode); + if (!is_in_usb_c_dp4_mode) + link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); + } + +} + +bool dcn20_link_encoder_is_in_alt_mode(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t dp_alt_mode_disable = 0; + bool is_usb_c_alt_mode = false; + + if (enc->features.flags.bits.DP_IS_USB_C) { + /* if value == 1 alt mode is disabled, otherwise it is enabled */ + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable); + is_usb_c_alt_mode = (dp_alt_mode_disable == 0); + } + + return is_usb_c_alt_mode; +} + +#define AUX_REG(reg)\ + (enc10->aux_regs->reg) + +#define AUX_REG_READ(reg_name) \ + dm_read_reg(CTX, AUX_REG(reg_name)) + +#define AUX_REG_WRITE(reg_name, val) \ + dm_write_reg(CTX, AUX_REG(reg_name), val) +void enc2_hw_init(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); +/* + 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 + 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 + 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 + 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 + 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 + 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 + 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 + 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 +*/ + +/* + AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, + AUX_RX_START_WINDOW = 1 [6:4] + AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] + AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 + AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 + AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 + AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 + AUX_RX_DETECTION_THRESHOLD [30:28] = 1 +*/ + if (enc->ctx->dc_bios->golden_table.dc_golden_table_ver > 0) { + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, enc->ctx->dc_bios->golden_table.aux_dphy_rx_control0_val); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, enc->ctx->dc_bios->golden_table.aux_dphy_tx_control_val); + + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL1, enc->ctx->dc_bios->golden_table.aux_dphy_rx_control1_val); + } else { + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); + } + + //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; + // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk + // 27MHz -> 0xd + // 100MHz -> 0x32 + // 48MHz -> 0x18 + + // Set TMDS_CTL0 to 1. This is a legacy setting. + REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); + + dcn10_aux_initialize(enc10); +} + +static const struct link_encoder_funcs dcn20_link_enc_funcs = { + .read_state = link_enc2_read_state, + .validate_output_with_stream = + dcn10_link_encoder_validate_output_with_stream, + .hw_init = enc2_hw_init, + .setup = dcn10_link_encoder_setup, + .enable_tmds_output = dcn10_link_encoder_enable_tmds_output_with_clk_pattern_wa, + .enable_dp_output = dcn20_link_encoder_enable_dp_output, + .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, + .disable_output = dcn10_link_encoder_disable_output, + .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dcn10_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dcn10_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, + .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dcn10_link_encoder_enable_hpd, + .disable_hpd = dcn10_link_encoder_disable_hpd, + .is_dig_enabled = dcn10_is_dig_enabled, + .destroy = dcn10_link_encoder_destroy, + .fec_set_enable = enc2_fec_set_enable, + .fec_set_ready = enc2_fec_set_ready, + .fec_is_active = enc2_fec_is_active, + .get_dig_mode = dcn10_get_dig_mode, + .get_dig_frontend = dcn10_get_dig_frontend, + .is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode, + .get_max_link_cap = dcn20_link_encoder_get_max_link_cap, +}; + +void dcn20_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask) +{ + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enum bp_result result = BP_RESULT_OK; + struct dcn10_link_encoder *enc10 = &enc20->enc10; + + enc10->base.funcs = &dcn20_link_enc_funcs; + enc10->base.ctx = init_data->ctx; + enc10->base.id = init_data->encoder; + + enc10->base.hpd_source = init_data->hpd_source; + enc10->base.connector = init_data->connector; + + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc10->base.features = *enc_features; + + enc10->base.transmitter = init_data->transmitter; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc10->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc10->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + enc10->link_regs = link_regs; + enc10->aux_regs = aux_regs; + enc10->hpd_regs = hpd_regs; + enc10->link_shift = link_shift; + enc10->link_mask = link_mask; + + switch (enc10->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc10->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc10->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc10->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc10->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc10->base.preferred_engine = ENGINE_ID_DIGE; + break; + case TRANSMITTER_UNIPHY_F: + enc10->base.preferred_engine = ENGINE_ID_DIGF; + break; + case TRANSMITTER_UNIPHY_G: + enc10->base.preferred_engine = ENGINE_ID_DIGG; + break; + default: + ASSERT_CRITICAL(false); + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + /* default to one to mirror Windows behavior */ + enc10->base.features.flags.bits.HDMI_6GB_EN = 1; + + result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, + enc10->base.id, &bp_cap_info); + + /* Override features with DCE-specific values */ + if (result == BP_RESULT_OK) { + enc10->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_EN; + enc10->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + enc10->base.features.flags.bits.DP_IS_USB_C = + bp_cap_info.DP_IS_USB_C; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, + result); + } + if (enc10->base.ctx->dc->debug.hdmi20_disable) { + enc10->base.features.flags.bits.HDMI_6GB_EN = 0; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.h new file mode 100644 index 000000000000..762c579fcb44 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.h @@ -0,0 +1,366 @@ +/* + * 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 + * + */ + +#ifndef __DC_LINK_ENCODER__DCN20_H__ +#define __DC_LINK_ENCODER__DCN20_H__ + +#include "dcn10/dcn10_link_encoder.h" + +#define DCN2_AUX_REG_LIST(id)\ + AUX_REG_LIST(id), \ + SRI(AUX_DPHY_TX_CONTROL, DP_AUX, id) + +#define UNIPHY_MASK_SH_LIST(mask_sh)\ + LE_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, mask_sh),\ + LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_LINK_ENABLE, mask_sh),\ + LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL0_XBAR_SOURCE, mask_sh),\ + LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL1_XBAR_SOURCE, mask_sh),\ + LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL2_XBAR_SOURCE, mask_sh),\ + LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL3_XBAR_SOURCE, mask_sh) + +#define DPCS_MASK_SH_LIST(mask_sh)\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX0_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX1_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX2_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX3_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_MPLLB_MULTIPLIER, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_WIDTH, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_RATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_WIDTH, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_RATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_PSTATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_PSTATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_MPLL_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_MPLL_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_QUOT, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_DEN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL8, RDPCS_PHY_DP_MPLLB_SSC_PEAK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_UP_SPREAD, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_STEPSIZE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL10, RDPCS_PHY_DP_MPLLB_FRACN_REM, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_REF_CLK_MPLLB_DIV, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_HDMI_MPLLB_HDMI_DIV, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_SSC_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_DIV5_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_TX_CLK_DIV, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_WORD_DIV2_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_STATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_MULTIPLIER, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_FRACN_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_PMIX_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE0_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE1_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE2_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE3_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_EXT_REFCLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_BYPASS, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_CLOCK_ON, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_CLOCK_ON, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_GATE_DIS, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_CR_MUX_SEL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_REF_RANGE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_BYPASS, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_EXT_LD_DONE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_HDMIMODE_ENABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_INIT_DONE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL2, RDPCS_PHY_DP4_POR, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PLL_UPDATE_DATA, RDPCS_PLL_UPDATE_DATA, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_REG_FIFO_ERROR_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_TX_FIFO_ERROR_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_DISABLE_TOGGLE_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_4LANE_TOGGLE_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCS_TX_CR_ADDR, RDPCS_TX_CR_ADDR, mask_sh),\ + LE_SF(RDPCSTX0_RDPCS_TX_CR_DATA, RDPCS_TX_CR_DATA, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_V2I, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_POST, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_FREQ_VCO, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_INT, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_PROP, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_POST, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_POST, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_FINETUNE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_RANGE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_POST, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CLOCK_CNTL, DPCS_SYMCLK_CLOCK_ON, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CLOCK_CNTL, DPCS_SYMCLK_GATE_DIS, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CLOCK_CNTL, DPCS_SYMCLK_EN, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_SWAP, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_FIFO_EN, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_DEBUG_CONFIG, DPCS_DBG_CBUS_DIS, mask_sh) + +#define DPCS_DCN2_MASK_SH_LIST(mask_sh)\ + DPCS_MASK_SH_LIST(mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_RX_LD_VAL, RDPCS_PHY_RX_REF_LD_VAL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_RX_LD_VAL, RDPCS_PHY_RX_VCO_LD_VAL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX0_PSTATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX1_PSTATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX0_MPLL_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX1_MPLL_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_REF_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX2_WIDTH, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX2_RATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX3_WIDTH, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX3_RATE, mask_sh),\ + LE_SF(DCIO_SOFT_RESET, UNIPHYA_SOFT_RESET, mask_sh),\ + LE_SF(DCIO_SOFT_RESET, UNIPHYB_SOFT_RESET, mask_sh),\ + LE_SF(DCIO_SOFT_RESET, UNIPHYC_SOFT_RESET, mask_sh),\ + LE_SF(DCIO_SOFT_RESET, UNIPHYD_SOFT_RESET, mask_sh),\ + LE_SF(DCIO_SOFT_RESET, UNIPHYE_SOFT_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) + +#define LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh)\ + LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\ + LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE0EN, mask_sh),\ + LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE1EN, mask_sh),\ + LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE2EN, mask_sh),\ + LE_SF(DIG0_DIG_LANE_ENABLE, DIG_LANE3EN, mask_sh),\ + LE_SF(DIG0_DIG_LANE_ENABLE, DIG_CLK_EN, mask_sh),\ + LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ + UNIPHY_MASK_SH_LIST(mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh) + +#define UNIPHY_DCN2_REG_LIST(id) \ + SRI(CLOCK_ENABLE, SYMCLK, id), \ + SRI(CHANNEL_XBAR_CNTL, UNIPHY, id) + +#define DPCS_DCN2_CMN_REG_LIST(id) \ + SRI(DIG_LANE_ENABLE, DIG, id), \ + SRI(TMDS_CTL_BITS, DIG, id), \ + SRI(RDPCSTX_PHY_CNTL3, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL6, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL10, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL11, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL12, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL13, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL14, RDPCSTX, id), \ + SRI(RDPCSTX_CNTL, RDPCSTX, id), \ + SRI(RDPCSTX_CLOCK_CNTL, RDPCSTX, id), \ + SRI(RDPCSTX_INTERRUPT_CONTROL, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL2, RDPCSTX, id), \ + SRI(RDPCSTX_PLL_UPDATE_DATA, RDPCSTX, id), \ + SRI(RDPCS_TX_CR_ADDR, RDPCSTX, id), \ + SRI(RDPCS_TX_CR_DATA, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE0, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ + SRI(DPCSTX_TX_CLOCK_CNTL, DPCSTX, id), \ + SRI(DPCSTX_TX_CNTL, DPCSTX, id), \ + SRI(DPCSTX_DEBUG_CONFIG, DPCSTX, id), \ + SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ + SR(RDPCSTX0_RDPCSTX_SCRATCH) + + +#define DPCS_DCN2_REG_LIST(id) \ + DPCS_DCN2_CMN_REG_LIST(id), \ + SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ + SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) + +#define LE_DCN2_REG_LIST(id) \ + LE_DCN10_REG_LIST(id), \ + SR(DCIO_SOFT_RESET) + +struct mpll_cfg { + uint32_t mpllb_ana_v2i; + uint32_t mpllb_ana_freq_vco; + uint32_t mpllb_ana_cp_int; + uint32_t mpllb_ana_cp_prop; + uint32_t mpllb_multiplier; + uint32_t ref_clk_mpllb_div; + bool mpllb_word_div2_en; + bool mpllb_ssc_en; + bool mpllb_div5_clk_en; + bool mpllb_div_clk_en; + bool mpllb_fracn_en; + bool mpllb_pmix_en; + uint32_t mpllb_div_multiplier; + uint32_t mpllb_tx_clk_div; + uint32_t mpllb_fracn_quot; + uint32_t mpllb_fracn_den; + uint32_t mpllb_ssc_peak; + uint32_t mpllb_ssc_stepsize; + uint32_t mpllb_ssc_up_spread; + uint32_t mpllb_fracn_rem; + uint32_t mpllb_hdmi_div; + // TODO: May not mpll params, need to figure out. + uint32_t tx_vboost_lvl; + uint32_t hdmi_pixel_clk_div; + uint32_t ref_range; + uint32_t ref_clk; + bool hdmimode_enable; + bool sup_pre_hp; + bool dp_tx0_vergdrv_byp; + bool dp_tx1_vergdrv_byp; + bool dp_tx2_vergdrv_byp; + bool dp_tx3_vergdrv_byp; + uint32_t tx_peaking_lvl; + uint32_t ctr_reqs_pll; + +}; + +struct dpcssys_phy_seq_cfg { + bool program_fuse; + bool bypass_sram; + bool lane_en[4]; + bool use_calibration_setting; + struct mpll_cfg mpll_cfg; + bool load_sram_fw; +#if 0 + + bool hdmimode_enable; + bool silver2; + bool ext_refclk_en; + uint32_t dp_tx0_term_ctrl; + uint32_t dp_tx1_term_ctrl; + uint32_t dp_tx2_term_ctrl; + uint32_t dp_tx3_term_ctrl; + uint32_t fw_data[0x1000]; + uint32_t dp_tx0_width; + uint32_t dp_tx1_width; + uint32_t dp_tx2_width; + uint32_t dp_tx3_width; + uint32_t dp_tx0_rate; + uint32_t dp_tx1_rate; + uint32_t dp_tx2_rate; + uint32_t dp_tx3_rate; + uint32_t dp_tx0_eq_main; + uint32_t dp_tx0_eq_pre; + uint32_t dp_tx0_eq_post; + uint32_t dp_tx1_eq_main; + uint32_t dp_tx1_eq_pre; + uint32_t dp_tx1_eq_post; + uint32_t dp_tx2_eq_main; + uint32_t dp_tx2_eq_pre; + uint32_t dp_tx2_eq_post; + uint32_t dp_tx3_eq_main; + uint32_t dp_tx3_eq_pre; + uint32_t dp_tx3_eq_post; + bool data_swap_en; + bool data_order_invert_en; + uint32_t ldpcs_fifo_start_delay; + uint32_t rdpcs_fifo_start_delay; + bool rdpcs_reg_fifo_error_mask; + bool rdpcs_tx_fifo_error_mask; + bool rdpcs_dpalt_disable_mask; + bool rdpcs_dpalt_4lane_mask; +#endif +}; + +struct dcn20_link_encoder { + struct dcn10_link_encoder enc10; + struct dpcssys_phy_seq_cfg phy_seq_cfg; +}; + +void enc2_fec_set_enable(struct link_encoder *enc, bool enable); +void enc2_fec_set_ready(struct link_encoder *enc, bool ready); +bool enc2_fec_is_active(struct link_encoder *enc); +void enc2_hw_init(struct link_encoder *enc); + +void link_enc2_read_state(struct link_encoder *enc, struct link_enc_state *s); + +void dcn20_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +bool dcn20_link_encoder_is_in_alt_mode(struct link_encoder *enc); +void dcn20_link_encoder_get_max_link_cap(struct link_encoder *enc, + struct dc_link_settings *link_settings); + +void dcn20_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask); + +#endif /* __DC_LINK_ENCODER__DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c new file mode 100644 index 000000000000..0b47aeb60e79 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c @@ -0,0 +1,661 @@ +/* + * 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 + +#include "dc_bios_types.h" +#include "dcn20_stream_encoder.h" +#include "reg_helper.h" +#include "hw_shared.h" +#include "link.h" +#include "dpcd_defs.h" + +#define DC_LOGGER \ + enc1->base.ctx->logger + +#define REG(reg)\ + (enc1->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc1->se_shift->field_name, enc1->se_mask->field_name + + +#define CTX \ + enc1->base.ctx + + +static void enc2_update_hdmi_info_packet( + struct dcn10_stream_encoder *enc1, + uint32_t packet_index, + const struct dc_info_packet *info_packet) +{ + uint32_t cont, send, line; + + if (info_packet->valid) { + enc1_update_generic_info_packet( + enc1, + packet_index, + info_packet); + + /* enable transmission of packet(s) - + * packet transmission begins on the next frame */ + cont = 1; + /* send packet(s) every frame */ + send = 1; + /* select line number to send packets on */ + line = 2; + } else { + cont = 0; + send = 0; + line = 0; + } + + /* DP_SEC_GSP[x]_LINE_REFERENCE - keep default value REFER_TO_DP_SOF */ + + /* choose which generic packet control to use */ + switch (packet_index) { + case 0: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC0_LINE, line); + break; + case 1: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC1_LINE, line); + break; + case 2: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC2_CONT, cont, + HDMI_GENERIC2_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC2_LINE, line); + break; + case 3: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC3_CONT, cont, + HDMI_GENERIC3_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC3_LINE, line); + break; + case 4: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC4_CONT, cont, + HDMI_GENERIC4_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC4_LINE, line); + break; + case 5: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC5_CONT, cont, + HDMI_GENERIC5_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC5_LINE, line); + break; + case 6: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC6_CONT, cont, + HDMI_GENERIC6_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, + HDMI_GENERIC6_LINE, line); + break; + case 7: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC7_CONT, cont, + HDMI_GENERIC7_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, + HDMI_GENERIC7_LINE, line); + break; + default: + /* invalid HW packet index */ + DC_LOG_WARNING( + "Invalid HW packet index: %s()\n", + __func__); + return; + } +} + +static void enc2_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* for bring up, disable dp double TODO */ + REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); + + /*Always add mandatory packets first followed by optional ones*/ + enc2_update_hdmi_info_packet(enc1, 0, &info_frame->avi); + enc2_update_hdmi_info_packet(enc1, 1, &info_frame->hfvsif); + enc2_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); + enc2_update_hdmi_info_packet(enc1, 3, &info_frame->vendor); + enc2_update_hdmi_info_packet(enc1, 4, &info_frame->spd); + enc2_update_hdmi_info_packet(enc1, 5, &info_frame->hdrsmd); + enc2_update_hdmi_info_packet(enc1, 6, &info_frame->vtem); +} + +static void enc2_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* stop generic packets 0,1 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL1, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC1_LINE, 0); + + /* stop generic packets 2,3 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC2_CONT, 0, + HDMI_GENERIC2_SEND, 0, + HDMI_GENERIC3_CONT, 0, + HDMI_GENERIC3_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL2, 0, + HDMI_GENERIC2_LINE, 0, + HDMI_GENERIC3_LINE, 0); + + /* stop generic packets 4,5 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC4_CONT, 0, + HDMI_GENERIC4_SEND, 0, + HDMI_GENERIC5_CONT, 0, + HDMI_GENERIC5_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL3, 0, + HDMI_GENERIC4_LINE, 0, + HDMI_GENERIC5_LINE, 0); + + /* stop generic packets 6,7 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC6_CONT, 0, + HDMI_GENERIC6_SEND, 0, + HDMI_GENERIC7_CONT, 0, + HDMI_GENERIC7_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL4, 0, + HDMI_GENERIC6_LINE, 0, + HDMI_GENERIC7_LINE, 0); +} + + +/* Update GSP7 SDP 128 byte long */ +static void enc2_update_gsp7_128_info_packet( + struct dcn10_stream_encoder *enc1, + const struct dc_info_packet_128 *info_packet, + bool immediate_update) +{ + uint32_t i; + + /* TODOFPGA Figure out a proper number for max_retries polling for lock + * use 50 for now. + */ + uint32_t max_retries = 50; + const uint32_t *content = (const uint32_t *) &info_packet->sb[0]; + + ASSERT(info_packet->hb1 == DC_DP_INFOFRAME_TYPE_PPS); + + /* Configure for PPS packet size (128 bytes) */ + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 1); + + /* We need turn on clock before programming AFMT block*/ + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); + + /* Poll dig_update_lock is not locked -> asic internal signal + * assumes otg master lock will unlock it + */ + /*REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, 0, 10, max_retries);*/ + + /* Wait for HW/SW GSP memory access conflict to go away */ + REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, + 0, 10, max_retries); + + /* Clear HW/SW memory access conflict flag */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); + + /* write generic packet header */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, 7); + REG_SET_4(AFMT_GENERIC_HDR, 0, + AFMT_GENERIC_HB0, info_packet->hb0, + AFMT_GENERIC_HB1, info_packet->hb1, + AFMT_GENERIC_HB2, info_packet->hb2, + AFMT_GENERIC_HB3, info_packet->hb3); + + /* Write generic packet content 128 bytes long. Four sets are used (indexes 7 + * through 10) to fit 128 bytes. + */ + for (i = 0; i < 4; i++) { + uint32_t packet_index = 7 + i; + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, packet_index); + + REG_WRITE(AFMT_GENERIC_0, *content++); + REG_WRITE(AFMT_GENERIC_1, *content++); + REG_WRITE(AFMT_GENERIC_2, *content++); + REG_WRITE(AFMT_GENERIC_3, *content++); + REG_WRITE(AFMT_GENERIC_4, *content++); + REG_WRITE(AFMT_GENERIC_5, *content++); + REG_WRITE(AFMT_GENERIC_6, *content++); + REG_WRITE(AFMT_GENERIC_7, *content++); + } + + REG_UPDATE_2(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC7_FRAME_UPDATE, !immediate_update, + AFMT_GENERIC7_IMMEDIATE_UPDATE, immediate_update); +} + +/* Set DSC-related configuration. + * dsc_mode: 0 disables DSC, other values enable DSC in specified format + * sc_bytes_per_pixel: Bytes per pixel in u3.28 format + * dsc_slice_width: Slice width in pixels + */ +static void enc2_dp_set_dsc_config(struct stream_encoder *enc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, + uint32_t dsc_slice_width) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE_2(DP_DSC_CNTL, + DP_DSC_MODE, dsc_mode, + DP_DSC_SLICE_WIDTH, dsc_slice_width); + + REG_SET(DP_DSC_BYTES_PER_PIXEL, 0, + DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); +} + + +static void enc2_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, + bool enable, + uint8_t *dsc_packed_pps, + bool immediate_update) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (enable) { + struct dc_info_packet_128 pps_sdp; + + ASSERT(dsc_packed_pps); + + /* Load PPS into infoframe (SDP) registers */ + pps_sdp.valid = true; + pps_sdp.hb0 = 0; + pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; + pps_sdp.hb2 = 127; + pps_sdp.hb3 = 0; + memcpy(&pps_sdp.sb[0], dsc_packed_pps, sizeof(pps_sdp.sb)); + enc2_update_gsp7_128_info_packet(enc1, &pps_sdp, immediate_update); + + /* Enable Generic Stream Packet 7 (GSP) transmission */ + //REG_UPDATE(DP_SEC_CNTL, + // DP_SEC_GSP7_ENABLE, 1); + + /* SW should make sure VBID[6] update line number is bigger + * than PPS transmit line number + */ + REG_UPDATE(DP_SEC_CNTL6, + DP_SEC_GSP7_LINE_NUM, 2); + REG_UPDATE_2(DP_MSA_VBID_MISC, + DP_VBID6_LINE_REFERENCE, 0, + DP_VBID6_LINE_NUM, 3); + + /* Send PPS data at the line number specified above. + * DP spec requires PPS to be sent only when it changes, however since + * decoder has to be able to handle its change on every frame, we're + * sending it always (i.e. on every frame) to reduce the chance it'd be + * missed by decoder. If it turns out required to send PPS only when it + * changes, we can use DP_SEC_GSP7_SEND register. + */ + REG_UPDATE_2(DP_SEC_CNTL, + DP_SEC_GSP7_ENABLE, 1, + DP_SEC_STREAM_ENABLE, 1); + } else { + /* Disable Generic Stream Packet 7 (GSP) transmission */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, 0); + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP7_PPS, 0); + } +} + + +/* this function read dsc related register fields to be logged later in dcn10_log_hw_state + * into a dcn_dsc_state struct. + */ +static void enc2_read_state(struct stream_encoder *enc, struct enc_state *s) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + //if dsc is enabled, continue to read + REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode); + if (s->dsc_mode) { + REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width); + REG_GET(DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, &s->sec_gsp_pps_line_num); + + REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference); + REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num); + + REG_GET(DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, &s->sec_gsp_pps_enable); + REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable); + } +} + +/* Set Dynamic Metadata-configuration. + * enable_dme: TRUE: enables Dynamic Metadata Enfine, FALSE: disables DME + * hubp_requestor_id: HUBP physical instance that is the source of dynamic metadata + * only needs to be set when enable_dme is TRUE + * dmdata_mode: dynamic metadata packet type: DP, HDMI, or Dolby Vision + * + * Ensure the OTG master update lock is set when changing DME configuration. + */ +void enc2_set_dynamic_metadata(struct stream_encoder *enc, + bool enable_dme, + uint32_t hubp_requestor_id, + enum dynamic_metadata_mode dmdata_mode) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (enable_dme) { + REG_UPDATE_2(DME_CONTROL, + METADATA_HUBP_REQUESTOR_ID, hubp_requestor_id, + METADATA_STREAM_TYPE, (dmdata_mode == dmdata_dolby_vision) ? 1 : 0); + + /* Use default line reference DP_SOF for bringup. + * Should use OTG_SOF for DRR cases + */ + if (dmdata_mode == dmdata_dp) + REG_UPDATE_3(DP_SEC_METADATA_TRANSMISSION, + DP_SEC_METADATA_PACKET_ENABLE, 1, + DP_SEC_METADATA_PACKET_LINE_REFERENCE, 0, + DP_SEC_METADATA_PACKET_LINE, 20); + else { + REG_UPDATE_3(HDMI_METADATA_PACKET_CONTROL, + HDMI_METADATA_PACKET_ENABLE, 1, + HDMI_METADATA_PACKET_LINE_REFERENCE, 0, + HDMI_METADATA_PACKET_LINE, 2); + + if (dmdata_mode == dmdata_dolby_vision) + REG_UPDATE(DIG_FE_CNTL, + DOLBY_VISION_EN, 1); + } + + REG_UPDATE(DME_CONTROL, + METADATA_ENGINE_EN, 1); + } else { + REG_UPDATE(DME_CONTROL, + METADATA_ENGINE_EN, 0); + + if (dmdata_mode == dmdata_dp) + REG_UPDATE(DP_SEC_METADATA_TRANSMISSION, + DP_SEC_METADATA_PACKET_ENABLE, 0); + else { + REG_UPDATE(HDMI_METADATA_PACKET_CONTROL, + HDMI_METADATA_PACKET_ENABLE, 0); + REG_UPDATE(DIG_FE_CNTL, + DOLBY_VISION_EN, 0); + } + } +} + +static void enc2_stream_encoder_update_dp_info_packets_sdp_line_num( + struct stream_encoder *enc, + struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (info_frame->adaptive_sync.valid == true && + info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { + //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF + REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1); + + REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, + info_frame->sdp_line_num.adaptive_sync_line_num); + } +} + +static void enc2_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t dmdata_packet_enabled = 0; + + enc1_stream_encoder_update_dp_info_packets(enc, info_frame); + + /* check if dynamic metadata packet transmission is enabled */ + REG_GET(DP_SEC_METADATA_TRANSMISSION, + DP_SEC_METADATA_PACKET_ENABLE, &dmdata_packet_enabled); + + if (dmdata_packet_enabled) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing) +{ + bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; + + two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 + && !timing->dsc_cfg.ycbcr422_simple); + return two_pix; +} + +void enc2_stream_encoder_dp_unblank( + struct dc_link *link, + struct stream_encoder *enc, + const struct encoder_unblank_param *param) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { + uint32_t n_vid = 0x8000; + uint32_t m_vid; + uint32_t n_multiply = 0; + uint64_t m_vid_l = n_vid; + + /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */ + if (is_two_pixels_per_containter(¶m->timing) || param->opp_cnt > 1) { + /*this logic should be the same in get_pixel_clock_parameters() */ + n_multiply = 1; + } + /* M / N = Fstream / Flink + * m_vid / n_vid = pixel rate / link rate + */ + + m_vid_l *= param->timing.pix_clk_100hz / 10; + m_vid_l = div_u64(m_vid_l, + param->link_settings.link_rate + * LINK_RATE_REF_FREQ_IN_KHZ); + + m_vid = (uint32_t) m_vid_l; + + /* enable auto measurement */ + + REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); + + /* auto measurement need 1 full 0x8000 symbol cycle to kick in, + * therefore program initial value for Mvid and Nvid + */ + + REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); + + REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); + + REG_UPDATE_2(DP_VID_TIMING, + DP_VID_M_N_GEN_EN, 1, + DP_VID_N_MUL, n_multiply); + } + + /* make sure stream is disabled before resetting steer fifo */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false); + REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000); + + /* set DIG_START to 0x1 to reset FIFO */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); + udelay(1); + + /* write 0 to take the FIFO out of reset */ + + REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); + + /* switch DP encoder to CRTC data, but reset it the fifo first. It may happen + * that it overflows during mode transition, and sometimes doesn't recover. + */ + REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1); + udelay(10); + + REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); + + /* wait 100us for DIG/DP logic to prime + * (i.e. a few video lines) + */ + udelay(100); + + /* the hardware would start sending video at the start of the next DP + * frame (i.e. rising edge of the vblank). + * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this + * register has no effect on enable transition! HW always guarantees + * VID_STREAM enable at start of next frame, and this is not + * programmable + */ + + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); + + link->dc->link_srv->dp_trace_source_sequence(link, + DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); +} + +static void enc2_dp_set_odm_combine( + struct stream_encoder *enc, + bool odm_combine) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, odm_combine); +} + +void enc2_stream_encoder_dp_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space, + bool use_vsc_sdp_for_colorimetry, + uint32_t enable_sdp_splitting) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + enc1_stream_encoder_dp_set_stream_attribute(enc, + crtc_timing, + output_color_space, + use_vsc_sdp_for_colorimetry, + enable_sdp_splitting); + + REG_UPDATE(DP_SEC_FRAMING4, + DP_SST_SDP_SPLITTING, enable_sdp_splitting); +} + +uint32_t enc2_get_fifo_cal_average_level( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t fifo_level; + + REG_GET(DIG_FIFO_STATUS, + DIG_FIFO_CAL_AVERAGE_LEVEL, &fifo_level); + return fifo_level; +} + +static const struct stream_encoder_funcs dcn20_str_enc_funcs = { + .dp_set_odm_combine = + enc2_dp_set_odm_combine, + .dp_set_stream_attribute = + enc2_stream_encoder_dp_set_stream_attribute, + .hdmi_set_stream_attribute = + enc1_stream_encoder_hdmi_set_stream_attribute, + .dvi_set_stream_attribute = + enc1_stream_encoder_dvi_set_stream_attribute, + .set_throttled_vcp_size = + enc1_stream_encoder_set_throttled_vcp_size, + .update_hdmi_info_packets = + enc2_stream_encoder_update_hdmi_info_packets, + .stop_hdmi_info_packets = + enc2_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets_sdp_line_num = + enc2_stream_encoder_update_dp_info_packets_sdp_line_num, + .update_dp_info_packets = + enc2_stream_encoder_update_dp_info_packets, + .send_immediate_sdp_message = + enc1_stream_encoder_send_immediate_sdp_message, + .stop_dp_info_packets = + enc1_stream_encoder_stop_dp_info_packets, + .dp_blank = + enc1_stream_encoder_dp_blank, + .dp_unblank = + enc2_stream_encoder_dp_unblank, + .audio_mute_control = enc1_se_audio_mute_control, + + .dp_audio_setup = enc1_se_dp_audio_setup, + .dp_audio_enable = enc1_se_dp_audio_enable, + .dp_audio_disable = enc1_se_dp_audio_disable, + + .hdmi_audio_setup = enc1_se_hdmi_audio_setup, + .hdmi_audio_disable = enc1_se_hdmi_audio_disable, + .setup_stereo_sync = enc1_setup_stereo_sync, + .set_avmute = enc1_stream_encoder_set_avmute, + .dig_connect_to_otg = enc1_dig_connect_to_otg, + .dig_source_otg = enc1_dig_source_otg, + + .dp_get_pixel_format = + enc1_stream_encoder_dp_get_pixel_format, + + .enc_read_state = enc2_read_state, + .dp_set_dsc_config = enc2_dp_set_dsc_config, + .dp_set_dsc_pps_info_packet = enc2_dp_set_dsc_pps_info_packet, + .set_dynamic_metadata = enc2_set_dynamic_metadata, + .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, + .get_fifo_cal_average_level = enc2_get_fifo_cal_average_level, +}; + +void dcn20_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask) +{ + enc1->base.funcs = &dcn20_str_enc_funcs; + enc1->base.ctx = ctx; + enc1->base.id = eng_id; + enc1->base.bp = bp; + enc1->regs = regs; + enc1->se_shift = se_shift; + enc1->se_mask = se_mask; + enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.h new file mode 100644 index 000000000000..baa1e539f341 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.h @@ -0,0 +1,119 @@ +/* + * 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 + * + */ + +#ifndef __DC_STREAM_ENCODER_DCN20_H__ +#define __DC_STREAM_ENCODER_DCN20_H__ + +#include "stream_encoder.h" +#include "dcn10/dcn10_stream_encoder.h" + + +#define SE_DCN2_REG_LIST(id)\ + SE_COMMON_DCN_REG_LIST(id),\ + SRI(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ + SRI(DP_DSC_CNTL, DP, id), \ + SRI(DP_DSC_BYTES_PER_PIXEL, DP, id), \ + SRI(DME_CONTROL, DIG, id),\ + SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI(DP_SEC_FRAMING4, DP, id) + +#define SE_COMMON_MASK_SH_LIST_DCN20(mask_sh)\ + SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\ + SE_SF(DP0_DP_DSC_CNTL, DP_DSC_MODE, mask_sh),\ + SE_SF(DP0_DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, mask_sh),\ + SE_SF(DP0_DP_DSC_BYTES_PER_PIXEL, DP_DSC_BYTES_PER_PIXEL, mask_sh),\ + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\ + SE_SF(DIG0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\ + SE_SF(DIG0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\ + SE_SF(DIG0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DOLBY_VISION_EN, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh) + +void dcn20_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask); + +void enc2_stream_encoder_dp_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space, + bool use_vsc_sdp_for_colorimetry, + uint32_t enable_sdp_splitting); + +void enc2_stream_encoder_dp_unblank( + struct dc_link *link, + struct stream_encoder *enc, + const struct encoder_unblank_param *param); + +void enc2_set_dynamic_metadata(struct stream_encoder *enc, + bool enable_dme, + uint32_t hubp_requestor_id, + enum dynamic_metadata_mode dmdata_mode); + +uint32_t enc2_get_fifo_cal_average_level( + struct stream_encoder *enc); + +#endif /* __DC_STREAM_ENCODER_DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c new file mode 100644 index 000000000000..b8e31b5ea114 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c @@ -0,0 +1,257 @@ +/* + * Copyright 2020 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 "reg_helper.h" + +#include "core_types.h" +#include "link_encoder.h" +#include "dcn30_dio_link_encoder.h" +#include "stream_encoder.h" +#include "dc_bios_types.h" +#include "gpio_service_interface.h" + +#define CTX \ + enc10->base.ctx +#define DC_LOGGER \ + enc10->base.ctx->logger + +#define REG(reg)\ + (enc10->link_regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc10->link_shift->field_name, enc10->link_mask->field_name + +#define IND_REG(index) \ + (enc10->link_regs->index) + + +bool dcn30_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + const struct dc_stream_state *stream) +{ + return dcn10_link_encoder_validate_output_with_stream(enc, stream); +} + +static const struct link_encoder_funcs dcn30_link_enc_funcs = { + .read_state = link_enc2_read_state, + .validate_output_with_stream = + dcn30_link_encoder_validate_output_with_stream, + .hw_init = enc3_hw_init, + .setup = dcn10_link_encoder_setup, + .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, + .enable_dp_output = dcn20_link_encoder_enable_dp_output, + .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, + .disable_output = dcn10_link_encoder_disable_output, + .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dcn10_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dcn10_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, + .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dcn10_link_encoder_enable_hpd, + .disable_hpd = dcn10_link_encoder_disable_hpd, + .is_dig_enabled = dcn10_is_dig_enabled, + .destroy = dcn10_link_encoder_destroy, + .fec_set_enable = enc2_fec_set_enable, + .fec_set_ready = enc2_fec_set_ready, + .fec_is_active = enc2_fec_is_active, + .get_dig_frontend = dcn10_get_dig_frontend, + .get_dig_mode = dcn10_get_dig_mode, + .is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode, + .get_max_link_cap = dcn20_link_encoder_get_max_link_cap, +}; + +void dcn30_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask) +{ + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enum bp_result result = BP_RESULT_OK; + struct dcn10_link_encoder *enc10 = &enc20->enc10; + + enc10->base.funcs = &dcn30_link_enc_funcs; + enc10->base.ctx = init_data->ctx; + enc10->base.id = init_data->encoder; + + enc10->base.hpd_source = init_data->hpd_source; + enc10->base.connector = init_data->connector; + + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc10->base.features = *enc_features; + + enc10->base.transmitter = init_data->transmitter; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc10->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc10->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + enc10->link_regs = link_regs; + enc10->aux_regs = aux_regs; + enc10->hpd_regs = hpd_regs; + enc10->link_shift = link_shift; + enc10->link_mask = link_mask; + + switch (enc10->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc10->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc10->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc10->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc10->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc10->base.preferred_engine = ENGINE_ID_DIGE; + break; + case TRANSMITTER_UNIPHY_F: + enc10->base.preferred_engine = ENGINE_ID_DIGF; + break; + case TRANSMITTER_UNIPHY_G: + enc10->base.preferred_engine = ENGINE_ID_DIGG; + break; + default: + ASSERT_CRITICAL(false); + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + /* default to one to mirror Windows behavior */ + enc10->base.features.flags.bits.HDMI_6GB_EN = 1; + + result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, + enc10->base.id, &bp_cap_info); + + /* Override features with DCE-specific values */ + if (result == BP_RESULT_OK) { + enc10->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_EN; + enc10->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE; + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; + enc10->base.features.flags.bits.DP_IS_USB_C = + bp_cap_info.DP_IS_USB_C; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, + result); + } + if (enc10->base.ctx->dc->debug.hdmi20_disable) { + enc10->base.features.flags.bits.HDMI_6GB_EN = 0; + } +} + +#define AUX_REG(reg)\ + (enc10->aux_regs->reg) + +#define AUX_REG_READ(reg_name) \ + dm_read_reg(CTX, AUX_REG(reg_name)) + +#define AUX_REG_WRITE(reg_name, val) \ + dm_write_reg(CTX, AUX_REG(reg_name), val) +void enc3_hw_init(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + +/* + 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 + 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 + 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 + 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 + 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 + 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 + 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 + 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 +*/ + +/* + AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, + AUX_RX_START_WINDOW = 1 [6:4] + AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] + AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 + AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 + AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 + AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 + AUX_RX_DETECTION_THRESHOLD [30:28] = 1 +*/ + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); + + //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; + // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk + // 27MHz -> 0xd + // 100MHz -> 0x32 + // 48MHz -> 0x18 + + // Set TMDS_CTL0 to 1. This is a legacy setting. + REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); + + dcn10_aux_initialize(enc10); +} diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.h new file mode 100644 index 000000000000..5b6177c2ae98 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.h @@ -0,0 +1,86 @@ +/* + * Copyright 2020 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 + * + */ + +#ifndef __DC_LINK_ENCODER__DCN30_H__ +#define __DC_LINK_ENCODER__DCN30_H__ + +#include "dcn20/dcn20_link_encoder.h" + +#define LE_DCN3_REG_LIST(id)\ + SRI(DIG_BE_CNTL, DIG, id), \ + SRI(DIG_BE_EN_CNTL, DIG, id), \ + SRI(TMDS_CTL_BITS, DIG, id), \ + SRI(TMDS_DCBALANCER_CONTROL, DIG, id), \ + SRI(DP_CONFIG, DP, id), \ + SRI(DP_DPHY_CNTL, DP, id), \ + SRI(DP_DPHY_PRBS_CNTL, DP, id), \ + SRI(DP_DPHY_SCRAM_CNTL, DP, id),\ + SRI(DP_DPHY_SYM0, DP, id), \ + SRI(DP_DPHY_SYM1, DP, id), \ + SRI(DP_DPHY_SYM2, DP, id), \ + SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ + SRI(DP_LINK_CNTL, DP, id), \ + SRI(DP_LINK_FRAMING_CNTL, DP, id), \ + SRI(DP_MSE_SAT0, DP, id), \ + SRI(DP_MSE_SAT1, DP, id), \ + SRI(DP_MSE_SAT2, DP, id), \ + SRI(DP_MSE_SAT_UPDATE, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_DPHY_FAST_TRAINING, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) + +#define LINK_ENCODER_MASK_SH_LIST_DCN30(mask_sh) \ + LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh),\ + LE_SF(DIG0_TMDS_DCBALANCER_CONTROL, TMDS_SYNC_DCBAL_EN, mask_sh) + +#define DPCS_DCN3_MASK_SH_LIST(mask_sh)\ + DPCS_DCN2_MASK_SH_LIST(mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT_18_BIT, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_TX_VBOOST_LVL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) + + +void dcn30_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask); + +void enc3_hw_init(struct link_encoder *enc); + +bool dcn30_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + const struct dc_stream_state *stream); + +#endif /* __DC_LINK_ENCODER__DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c new file mode 100644 index 000000000000..425b830b88d2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c @@ -0,0 +1,899 @@ +/* + * Copyright 2020 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 "dc_bios_types.h" +#include "dcn30_dio_stream_encoder.h" +#include "reg_helper.h" +#include "hw_shared.h" +#include "dc.h" + +#define DC_LOGGER \ + enc1->base.ctx->logger + +#define REG(reg)\ + (enc1->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc1->se_shift->field_name, enc1->se_mask->field_name + +#define VBI_LINE_0 0 +#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 + +#define CTX \ + enc1->base.ctx + + +static void enc3_update_hdmi_info_packet( + struct dcn10_stream_encoder *enc1, + uint32_t packet_index, + const struct dc_info_packet *info_packet) +{ + uint32_t cont, send, line; + + if (info_packet->valid) { + enc1->base.vpg->funcs->update_generic_info_packet( + enc1->base.vpg, + packet_index, + info_packet, + true); + + /* enable transmission of packet(s) - + * packet transmission begins on the next frame */ + cont = 1; + /* send packet(s) every frame */ + send = 1; + /* select line number to send packets on */ + line = 2; + } else { + cont = 0; + send = 0; + line = 0; + } + + /* DP_SEC_GSP[x]_LINE_REFERENCE - keep default value REFER_TO_DP_SOF */ + + /* choose which generic packet control to use */ + switch (packet_index) { + case 0: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC0_LINE, line); + break; + case 1: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC1_LINE, line); + break; + case 2: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC2_CONT, cont, + HDMI_GENERIC2_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC2_LINE, line); + break; + case 3: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC3_CONT, cont, + HDMI_GENERIC3_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC3_LINE, line); + break; + case 4: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC4_CONT, cont, + HDMI_GENERIC4_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC4_LINE, line); + break; + case 5: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC5_CONT, cont, + HDMI_GENERIC5_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC5_LINE, line); + break; + case 6: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC6_CONT, cont, + HDMI_GENERIC6_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, + HDMI_GENERIC6_LINE, line); + break; + case 7: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC7_CONT, cont, + HDMI_GENERIC7_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, + HDMI_GENERIC7_LINE, line); + break; + case 8: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC8_CONT, cont, + HDMI_GENERIC8_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL7, + HDMI_GENERIC8_LINE, line); + break; + case 9: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC9_CONT, cont, + HDMI_GENERIC9_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL7, + HDMI_GENERIC9_LINE, line); + break; + case 10: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC10_CONT, cont, + HDMI_GENERIC10_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL8, + HDMI_GENERIC10_LINE, line); + break; + case 11: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC11_CONT, cont, + HDMI_GENERIC11_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL8, + HDMI_GENERIC11_LINE, line); + break; + case 12: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC12_CONT, cont, + HDMI_GENERIC12_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL9, + HDMI_GENERIC12_LINE, line); + break; + case 13: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC13_CONT, cont, + HDMI_GENERIC13_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL9, + HDMI_GENERIC13_LINE, line); + break; + case 14: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC14_CONT, cont, + HDMI_GENERIC14_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL10, + HDMI_GENERIC14_LINE, line); + break; + default: + /* invalid HW packet index */ + DC_LOG_WARNING( + "Invalid HW packet index: %s()\n", + __func__); + return; + } +} + +void enc3_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* for bring up, disable dp double TODO */ + REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); + + /*Always add mandatory packets first followed by optional ones*/ + enc3_update_hdmi_info_packet(enc1, 0, &info_frame->avi); + enc3_update_hdmi_info_packet(enc1, 5, &info_frame->hfvsif); + enc3_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); + enc3_update_hdmi_info_packet(enc1, 1, &info_frame->vendor); + enc3_update_hdmi_info_packet(enc1, 3, &info_frame->spd); + enc3_update_hdmi_info_packet(enc1, 4, &info_frame->hdrsmd); + enc3_update_hdmi_info_packet(enc1, 6, &info_frame->vtem); +} + +void enc3_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* stop generic packets 0,1 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL1, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC1_LINE, 0); + + /* stop generic packets 2,3 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC2_CONT, 0, + HDMI_GENERIC2_SEND, 0, + HDMI_GENERIC3_CONT, 0, + HDMI_GENERIC3_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL2, 0, + HDMI_GENERIC2_LINE, 0, + HDMI_GENERIC3_LINE, 0); + + /* stop generic packets 4,5 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC4_CONT, 0, + HDMI_GENERIC4_SEND, 0, + HDMI_GENERIC5_CONT, 0, + HDMI_GENERIC5_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL3, 0, + HDMI_GENERIC4_LINE, 0, + HDMI_GENERIC5_LINE, 0); + + /* stop generic packets 6,7 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC6_CONT, 0, + HDMI_GENERIC6_SEND, 0, + HDMI_GENERIC7_CONT, 0, + HDMI_GENERIC7_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL4, 0, + HDMI_GENERIC6_LINE, 0, + HDMI_GENERIC7_LINE, 0); + + /* stop generic packets 8,9 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, + HDMI_GENERIC8_CONT, 0, + HDMI_GENERIC8_SEND, 0, + HDMI_GENERIC9_CONT, 0, + HDMI_GENERIC9_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL7, 0, + HDMI_GENERIC8_LINE, 0, + HDMI_GENERIC9_LINE, 0); + + /* stop generic packets 10,11 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, + HDMI_GENERIC10_CONT, 0, + HDMI_GENERIC10_SEND, 0, + HDMI_GENERIC11_CONT, 0, + HDMI_GENERIC11_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL8, 0, + HDMI_GENERIC10_LINE, 0, + HDMI_GENERIC11_LINE, 0); + + /* stop generic packets 12,13 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, + HDMI_GENERIC12_CONT, 0, + HDMI_GENERIC12_SEND, 0, + HDMI_GENERIC13_CONT, 0, + HDMI_GENERIC13_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL9, 0, + HDMI_GENERIC12_LINE, 0, + HDMI_GENERIC13_LINE, 0); + + /* stop generic packet 14 on HDMI */ + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL6, 0, + HDMI_GENERIC14_CONT, 0, + HDMI_GENERIC14_SEND, 0); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL10, + HDMI_GENERIC14_LINE, 0); +} + +/* Set DSC-related configuration. + * dsc_mode: 0 disables DSC, other values enable DSC in specified format + * sc_bytes_per_pixel: Bytes per pixel in u3.28 format + * dsc_slice_width: Slice width in pixels + */ +static void enc3_dp_set_dsc_config(struct stream_encoder *enc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, + uint32_t dsc_slice_width) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE_2(DP_DSC_CNTL, + DP_DSC_MODE, dsc_mode, + DP_DSC_SLICE_WIDTH, dsc_slice_width); + + REG_SET(DP_DSC_BYTES_PER_PIXEL, 0, + DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); +} + + +void enc3_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, + bool enable, + uint8_t *dsc_packed_pps, + bool immediate_update) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (enable) { + struct dc_info_packet pps_sdp; + int i; + + /* Configure for PPS packet size (128 bytes) */ + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 1); + + /* We need turn on clock before programming AFMT block + * + * TODO: We may not need this here anymore since update_generic_info_packet + * no longer touches AFMT + */ + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); + + /* Load PPS into infoframe (SDP) registers */ + pps_sdp.valid = true; + pps_sdp.hb0 = 0; + pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; + pps_sdp.hb2 = 127; + pps_sdp.hb3 = 0; + + for (i = 0; i < 4; i++) { + memcpy(pps_sdp.sb, &dsc_packed_pps[i * 32], 32); + enc1->base.vpg->funcs->update_generic_info_packet( + enc1->base.vpg, + 11 + i, + &pps_sdp, + immediate_update); + } + + /* SW should make sure VBID[6] update line number is bigger + * than PPS transmit line number + */ + REG_UPDATE(DP_GSP11_CNTL, + DP_SEC_GSP11_LINE_NUM, 2); + REG_UPDATE_2(DP_MSA_VBID_MISC, + DP_VBID6_LINE_REFERENCE, 0, + DP_VBID6_LINE_NUM, 3); + + /* Send PPS data at the line number specified above. + * DP spec requires PPS to be sent only when it changes, however since + * decoder has to be able to handle its change on every frame, we're + * sending it always (i.e. on every frame) to reduce the chance it'd be + * missed by decoder. If it turns out required to send PPS only when it + * changes, we can use DP_SEC_GSP11_SEND register. + */ + REG_UPDATE(DP_GSP11_CNTL, + DP_SEC_GSP11_ENABLE, 1); + REG_UPDATE(DP_SEC_CNTL, + DP_SEC_STREAM_ENABLE, 1); + } else { + /* Disable Generic Stream Packet 11 (GSP) transmission */ + REG_UPDATE(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, 0); + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 0); + } +} + + +/* this function read dsc related register fields to be logged later in dcn10_log_hw_state + * into a dcn_dsc_state struct. + */ +static void enc3_read_state(struct stream_encoder *enc, struct enc_state *s) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + //if dsc is enabled, continue to read + REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode); + if (s->dsc_mode) { + REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width); + REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, &s->sec_gsp_pps_line_num); + + REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference); + REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num); + + REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, &s->sec_gsp_pps_enable); + REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable); + } +} + +void enc3_stream_encoder_update_dp_info_packets_sdp_line_num( + struct stream_encoder *enc, + struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (info_frame->adaptive_sync.valid == true && + info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { + //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF + REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1); + + REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, + info_frame->sdp_line_num.adaptive_sync_line_num); + } +} + +void enc3_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + uint32_t dmdata_packet_enabled = 0; + + if (info_frame->vsc.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 0, /* packetIndex */ + &info_frame->vsc, + true); + } + /* TODO: VSC SDP at packetIndex 1 should be retricted only if PSR-SU on. + * There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU. + * In addition, currently the driver check the valid bit then update and + * send the corresponding Infopacket. For PSR-SU, the SDP only be sent + * while entering PSR-SU mode. So we need another parameter(e.g. send) + * in dc_info_packet to indicate which infopacket should be enabled by + * default here. + */ + if (info_frame->vsc.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 1, /* packetIndex */ + &info_frame->vsc, + true); + } + /* TODO: VSC SDP at packetIndex 1 should be restricted only if PSR-SU on. + * There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU. + * In addition, currently the driver check the valid bit then update and + * send the corresponding Infopacket. For PSR-SU, the SDP only be sent + * while entering PSR-SU mode. So we need another parameter(e.g. send) + * in dc_info_packet to indicate which infopacket should be enabled by + * default here. + */ + if (info_frame->vsc.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 1, /* packetIndex */ + &info_frame->vsc, + true); + } + if (info_frame->spd.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 2, /* packetIndex */ + &info_frame->spd, + true); + } + if (info_frame->hdrsmd.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 3, /* packetIndex */ + &info_frame->hdrsmd, + true); + } + /* packetIndex 4 is used for send immediate sdp message, and please + * use other packetIndex (such as 5,6) for other info packet + */ + + if (info_frame->adaptive_sync.valid) + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 5, /* packetIndex */ + &info_frame->adaptive_sync, + true); + + /* enable/disable transmission of packet(s). + * If enabled, packet transmission begins on the next frame + */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid); + + /* This bit is the master enable bit. + * When enabling secondary stream engine, + * this master bit must also be set. + * This register shared with audio info frame. + * Therefore we need to enable master bit + * if at least on of the fields is not 0 + */ + value = REG_READ(DP_SEC_CNTL); + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); + + /* check if dynamic metadata packet transmission is enabled */ + REG_GET(DP_SEC_METADATA_TRANSMISSION, + DP_SEC_METADATA_PACKET_ENABLE, &dmdata_packet_enabled); + + if (dmdata_packet_enabled) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static void enc3_dp_set_odm_combine( + struct stream_encoder *enc, + bool odm_combine) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, odm_combine); +} + +/* setup stream encoder in dvi mode */ +static void enc3_stream_encoder_dvi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc1->base.id; + cntl.signal = is_dual_link ? + SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; + cntl.enable_dp_audio = false; + cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; + cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; + + if (enc1->base.bp->funcs->encoder_control( + enc1->base.bp, &cntl) != BP_RESULT_OK) + return; + + } else { + + //Set pattern for clock channel, default vlue 0x63 does not work + REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); + + //DIG_BE_TMDS_DVI_MODE : TMDS-DVI mode is already set in link_encoder_setup + + //DIG_SOURCE_SELECT is already set in dig_connect_to_otg + + /* set DIG_START to 0x1 to reset FIFO */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); + udelay(1); + + /* write 0 to take the FIFO out of reset */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); + udelay(1); + } + + ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); + ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); + enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); +} + +/* setup stream encoder in hdmi mode */ +static void enc3_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc1->base.id; + cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; + cntl.enable_dp_audio = enable_audio; + cntl.pixel_clock = actual_pix_clk_khz; + cntl.lanes_number = LANE_COUNT_FOUR; + + if (enc1->base.bp->funcs->encoder_control( + enc1->base.bp, &cntl) != BP_RESULT_OK) + return; + + } else { + + //Set pattern for clock channel, default vlue 0x63 does not work + REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); + + //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup + + //DIG_SOURCE_SELECT is already set in dig_connect_to_otg + + /* set DIG_START to 0x1 to reset FIFO */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); + udelay(1); + + /* write 0 to take the FIFO out of reset */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); + udelay(1); + } + + /* Configure pixel encoding */ + enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); + + /* setup HDMI engine */ + REG_UPDATE_6(HDMI_CONTROL, + HDMI_PACKET_GEN_VERSION, 1, + HDMI_KEEPOUT_MODE, 1, + HDMI_DEEP_COLOR_ENABLE, 0, + HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + + /* Configure color depth */ + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_888: + REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); + break; + case COLOR_DEPTH_101010: + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 0); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 1); + } + break; + case COLOR_DEPTH_121212: + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 0); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 1); + } + break; + case COLOR_DEPTH_161616: + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 3, + HDMI_DEEP_COLOR_ENABLE, 1); + break; + default: + break; + } + + if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_RATE_MORE_340M + * Clock channel frequency is 1/4 of character rate. + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 1); + } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { + + /* TODO: New feature for DCE11, still need to implement */ + + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE + * Clock channel frequency is the same + * as character rate + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + } + + + /* Enable transmission of General Control packet on every frame */ + REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, + HDMI_GC_CONT, 1, + HDMI_GC_SEND, 1, + HDMI_NULL_SEND, 1); + + /* Disable Audio Content Protection packet transmission */ + REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); + + /* following belongs to audio */ + /* Enable Audio InfoFrame packet transmission. */ + REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); + + /* update double-buffered AUDIO_INFO registers immediately */ + ASSERT (enc->afmt); + enc->afmt->funcs->audio_info_immediate_update(enc->afmt); + + /* Select line number on which to send Audio InfoFrame packets */ + REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, + VBI_LINE_0 + 2); + + /* set HDMI GC AVMUTE */ + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); +} + +void enc3_audio_mute_control( + struct stream_encoder *enc, + bool mute) +{ + ASSERT (enc->afmt); + enc->afmt->funcs->audio_mute_control(enc->afmt, mute); +} + +void enc3_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info) +{ + ASSERT (enc->afmt); + enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); +} + +#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 +#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 + +static void enc3_se_setup_dp_audio( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* --- DP Audio packet configurations --- */ + + /* ATP Configuration */ + REG_SET(DP_SEC_AUD_N, 0, + DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); + + /* Async/auto-calc timestamp mode */ + REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, + DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); + + ASSERT (enc->afmt); + enc->afmt->funcs->setup_dp_audio(enc->afmt); +} + +void enc3_se_dp_audio_enable( + struct stream_encoder *enc) +{ + enc1_se_enable_audio_clock(enc, true); + enc3_se_setup_dp_audio(enc); + enc1_se_enable_dp_audio(enc); +} + +static void enc3_se_setup_hdmi_audio( + struct stream_encoder *enc, + const struct audio_crtc_info *crtc_info) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + struct audio_clock_info audio_clock_info = {0}; + + /* Setup audio in AFMT - program AFMT block associated with DIO */ + ASSERT (enc->afmt); + enc->afmt->funcs->setup_hdmi_audio(enc->afmt); + + /* HDMI_AUDIO_PACKET_CONTROL */ + REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, + HDMI_AUDIO_DELAY_EN, 1); + + /* HDMI_ACR_PACKET_CONTROL */ + REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL, + HDMI_ACR_AUTO_SEND, 1, + HDMI_ACR_SOURCE, 0, + HDMI_ACR_AUDIO_PRIORITY, 0); + + /* Program audio clock sample/regeneration parameters */ + get_audio_clock_info(crtc_info->color_depth, + crtc_info->requested_pixel_clock_100Hz, + crtc_info->calculated_pixel_clock_100Hz, + &audio_clock_info); + DC_LOG_HW_AUDIO( + "\n%s:Input::requested_pixel_clock_100Hz = %d" \ + "calculated_pixel_clock_100Hz = %d \n", __func__, \ + crtc_info->requested_pixel_clock_100Hz, \ + crtc_info->calculated_pixel_clock_100Hz); + + /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ + REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); + + /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ + REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); + + /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ + REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); + + /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ + REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); + + /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ + REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); + + /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ + REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); + + /* Video driver cannot know in advance which sample rate will + * be used by HD Audio driver + * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is + * programmed below in interruppt callback + */ +} + +void enc3_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info) +{ + enc1_se_enable_audio_clock(enc, true); + enc3_se_setup_hdmi_audio(enc, audio_crtc_info); + ASSERT (enc->afmt); + enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); +} + + +static const struct stream_encoder_funcs dcn30_str_enc_funcs = { + .dp_set_odm_combine = + enc3_dp_set_odm_combine, + .dp_set_stream_attribute = + enc2_stream_encoder_dp_set_stream_attribute, + .hdmi_set_stream_attribute = + enc3_stream_encoder_hdmi_set_stream_attribute, + .dvi_set_stream_attribute = + enc3_stream_encoder_dvi_set_stream_attribute, + .set_throttled_vcp_size = + enc1_stream_encoder_set_throttled_vcp_size, + .update_hdmi_info_packets = + enc3_stream_encoder_update_hdmi_info_packets, + .stop_hdmi_info_packets = + enc3_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets_sdp_line_num = + enc3_stream_encoder_update_dp_info_packets_sdp_line_num, + .update_dp_info_packets = + enc3_stream_encoder_update_dp_info_packets, + .stop_dp_info_packets = + enc1_stream_encoder_stop_dp_info_packets, + .dp_blank = + enc1_stream_encoder_dp_blank, + .dp_unblank = + enc2_stream_encoder_dp_unblank, + .audio_mute_control = enc3_audio_mute_control, + + .dp_audio_setup = enc3_se_dp_audio_setup, + .dp_audio_enable = enc3_se_dp_audio_enable, + .dp_audio_disable = enc1_se_dp_audio_disable, + + .hdmi_audio_setup = enc3_se_hdmi_audio_setup, + .hdmi_audio_disable = enc1_se_hdmi_audio_disable, + .setup_stereo_sync = enc1_setup_stereo_sync, + .set_avmute = enc1_stream_encoder_set_avmute, + .dig_connect_to_otg = enc1_dig_connect_to_otg, + .dig_source_otg = enc1_dig_source_otg, + + .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, + + .enc_read_state = enc3_read_state, + .dp_set_dsc_config = enc3_dp_set_dsc_config, + .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet, + .set_dynamic_metadata = enc2_set_dynamic_metadata, + .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, + + .get_fifo_cal_average_level = enc2_get_fifo_cal_average_level, +}; + +void dcn30_dio_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + struct vpg *vpg, + struct afmt *afmt, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask) +{ + enc1->base.funcs = &dcn30_str_enc_funcs; + enc1->base.ctx = ctx; + enc1->base.id = eng_id; + enc1->base.bp = bp; + enc1->base.vpg = vpg; + enc1->base.afmt = afmt; + enc1->regs = regs; + enc1->se_shift = se_shift; + enc1->se_mask = se_mask; + enc1->base.stream_enc_inst = vpg->inst; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.h new file mode 100644 index 000000000000..06310973ded2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.h @@ -0,0 +1,327 @@ +/* + * Copyright 2020 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 + * + */ + +#ifndef __DC_DIO_STREAM_ENCODER_DCN30_H__ +#define __DC_DIO_STREAM_ENCODER_DCN30_H__ + +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "stream_encoder.h" +#include "dcn20/dcn20_stream_encoder.h" + +/* Register bit field name change */ +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_GATE_DIS__SHIFT 0x8 +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_EN__SHIFT 0x9 +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_CLOCK_ON__SHIFT 0xa +#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP__SHIFT 0xe +#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_ORDER_INVERT__SHIFT 0xf + +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_GATE_DIS_MASK 0x00000100L +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_EN_MASK 0x00000200L +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_CLOCK_ON_MASK 0x00000400L +#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP_MASK 0x00004000L +#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_ORDER_INVERT_MASK 0x00008000L + + +#define SE_DCN3_REG_LIST(id)\ + SRI(AFMT_CNTL, DIG, id), \ + SRI(DIG_FE_CNTL, DIG, id), \ + SRI(HDMI_CONTROL, DIG, id), \ + SRI(HDMI_DB_CONTROL, DIG, id), \ + SRI(HDMI_GC, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \ + SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \ + SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_32_0, DIG, id),\ + SRI(HDMI_ACR_32_1, DIG, id),\ + SRI(HDMI_ACR_44_0, DIG, id),\ + SRI(HDMI_ACR_44_1, DIG, id),\ + SRI(HDMI_ACR_48_0, DIG, id),\ + SRI(HDMI_ACR_48_1, DIG, id),\ + SRI(DP_DB_CNTL, DP, id), \ + SRI(DP_MSA_MISC, DP, id), \ + SRI(DP_MSA_VBID_MISC, DP, id), \ + SRI(DP_MSA_COLORIMETRY, DP, id), \ + SRI(DP_MSA_TIMING_PARAM1, DP, id), \ + SRI(DP_MSA_TIMING_PARAM2, DP, id), \ + SRI(DP_MSA_TIMING_PARAM3, DP, id), \ + SRI(DP_MSA_TIMING_PARAM4, DP, id), \ + SRI(DP_MSE_RATE_CNTL, DP, id), \ + SRI(DP_MSE_RATE_UPDATE, DP, id), \ + SRI(DP_PIXEL_FORMAT, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id), \ + SRI(DP_SEC_CNTL2, DP, id), \ + SRI(DP_SEC_CNTL5, DP, id), \ + SRI(DP_SEC_CNTL6, DP, id), \ + SRI(DP_STEER_FIFO, DP, id), \ + SRI(DP_VID_M, DP, id), \ + SRI(DP_VID_N, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_VID_TIMING, DP, id), \ + SRI(DP_SEC_AUD_N, DP, id), \ + SRI(DP_SEC_AUD_N_READBACK, DP, id), \ + SRI(DP_SEC_AUD_M_READBACK, DP, id), \ + SRI(DP_SEC_TIMESTAMP, DP, id), \ + SRI(DP_DSC_CNTL, DP, id), \ + SRI(DP_DSC_BYTES_PER_PIXEL, DP, id), \ + SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI(DP_SEC_FRAMING4, DP, id), \ + SRI(DP_GSP11_CNTL, DP, id), \ + SRI(DME_CONTROL, DME, id),\ + SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI(DIG_FE_CNTL, DIG, id), \ + SRI(DIG_FIFO_STATUS, DIG, id), \ + SRI(DIG_CLOCK_PATTERN, DIG, id) + + +#define SE_COMMON_MASK_SH_LIST_DCN30(mask_sh)\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ + SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ + SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ + SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_START, mask_sh),\ + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N_READBACK, DP_SEC_AUD_N_READBACK, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_M_READBACK, DP_SEC_AUD_M_READBACK, mask_sh),\ + SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ + SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_LEVEL_ERROR, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_USE_OVERWRITE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_OVERWRITE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_ERROR_ACK, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CAL_AVERAGE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MAXIMUM_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MINIMUM_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_READ_CLOCK_SRC, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CALIBRATED, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECAL_AVERAGE, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECOMP_MINMAX, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP11_PPS, mask_sh),\ + SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, mask_sh),\ + SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ + SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh), \ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC8_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC9_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC10_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC11_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC12_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC13_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL10, HDMI_GENERIC14_LINE, mask_sh),\ + SE_SF(DP0_DP_DSC_CNTL, DP_DSC_MODE, mask_sh),\ + SE_SF(DP0_DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, mask_sh),\ + SE_SF(DP0_DP_DSC_BYTES_PER_PIXEL, DP_DSC_BYTES_PER_PIXEL, mask_sh),\ + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\ + SE_SF(DME0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\ + SE_SF(DME0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\ + SE_SF(DME0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DOLBY_VISION_EN, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, mask_sh),\ + SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh),\ + SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh) + +void dcn30_dio_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + struct vpg *vpg, + struct afmt *afmt, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask); + +void enc3_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame); + +void enc3_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc); + +void enc3_stream_encoder_update_dp_info_packets_sdp_line_num( + struct stream_encoder *enc, + struct encoder_info_frame *info_frame); + +void enc3_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame); + +void enc3_audio_mute_control( + struct stream_encoder *enc, + bool mute); + +void enc3_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info); + +void enc3_se_dp_audio_enable( + struct stream_encoder *enc); + +void enc3_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info); + +void enc3_dp_set_dsc_pps_info_packet( + struct stream_encoder *enc, + bool enable, + uint8_t *dsc_packed_pps, + bool immediate_update); + +#endif /* __DC_DIO_STREAM_ENCODER_DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c new file mode 100644 index 000000000000..b2cea59ba5d4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c @@ -0,0 +1,681 @@ +/* + * 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 "reg_helper.h" + +#include "core_types.h" +#include "link_encoder.h" +#include "dcn31_dio_link_encoder.h" +#include "stream_encoder.h" +#include "dc_bios_types.h" + +#include "gpio_service_interface.h" + +#include "link_enc_cfg.h" +#include "dc_dmub_srv.h" +#include "dal_asic_id.h" +#include "link.h" + +#define CTX \ + enc10->base.ctx +#define DC_LOGGER \ + enc10->base.ctx->logger + +#define REG(reg)\ + (enc10->link_regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc10->link_shift->field_name, enc10->link_mask->field_name + +#define IND_REG(index) \ + (enc10->link_regs->index) + +#define AUX_REG(reg)\ + (enc10->aux_regs->reg) + +#define AUX_REG_READ(reg_name) \ + dm_read_reg(CTX, AUX_REG(reg_name)) + +#define AUX_REG_WRITE(reg_name, val) \ + dm_write_reg(CTX, AUX_REG(reg_name), val) + +#ifndef MIN +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#endif + +static uint8_t phy_id_from_transmitter(enum transmitter t) +{ + uint8_t phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + phy_id = 0; + break; + case TRANSMITTER_UNIPHY_B: + phy_id = 1; + break; + case TRANSMITTER_UNIPHY_C: + phy_id = 2; + break; + case TRANSMITTER_UNIPHY_D: + phy_id = 3; + break; + case TRANSMITTER_UNIPHY_E: + phy_id = 4; + break; + case TRANSMITTER_UNIPHY_F: + phy_id = 5; + break; + case TRANSMITTER_UNIPHY_G: + phy_id = 6; + break; + default: + phy_id = 0; + break; + } + return phy_id; +} + +static bool has_query_dp_alt(struct link_encoder *enc) +{ + struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv; + + if (enc->ctx->dce_version >= DCN_VERSION_3_15) + return true; + + /* Supports development firmware and firmware >= 4.0.11 */ + return dc_dmub_srv && + !(dc_dmub_srv->dmub->fw_version >= DMUB_FW_VERSION(4, 0, 0) && + dc_dmub_srv->dmub->fw_version <= DMUB_FW_VERSION(4, 0, 10)); +} + +static bool query_dp_alt_from_dmub(struct link_encoder *enc, + union dmub_rb_cmd *cmd) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + memset(cmd, 0, sizeof(*cmd)); + cmd->query_dp_alt.header.type = DMUB_CMD__VBIOS; + cmd->query_dp_alt.header.sub_type = + DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT; + cmd->query_dp_alt.header.payload_bytes = sizeof(cmd->query_dp_alt.data); + cmd->query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter); + + if (!dc_wake_and_execute_dmub_cmd(enc->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) + return false; + + return true; +} + +void dcn31_link_encoder_set_dio_phy_mux( + struct link_encoder *enc, + enum encoder_type_select sel, + uint32_t hpo_inst) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + switch (enc->transmitter) { + case TRANSMITTER_UNIPHY_A: + if (sel == ENCODER_TYPE_HDMI_FRL) + REG_UPDATE(DIO_LINKA_CNTL, + HPO_HDMI_ENC_SEL, hpo_inst); + else if (sel == ENCODER_TYPE_DP_128B132B) + REG_UPDATE(DIO_LINKA_CNTL, + HPO_DP_ENC_SEL, hpo_inst); + REG_UPDATE(DIO_LINKA_CNTL, + ENC_TYPE_SEL, sel); + break; + case TRANSMITTER_UNIPHY_B: + if (sel == ENCODER_TYPE_HDMI_FRL) + REG_UPDATE(DIO_LINKB_CNTL, + HPO_HDMI_ENC_SEL, hpo_inst); + else if (sel == ENCODER_TYPE_DP_128B132B) + REG_UPDATE(DIO_LINKB_CNTL, + HPO_DP_ENC_SEL, hpo_inst); + REG_UPDATE(DIO_LINKB_CNTL, + ENC_TYPE_SEL, sel); + break; + case TRANSMITTER_UNIPHY_C: + if (sel == ENCODER_TYPE_HDMI_FRL) + REG_UPDATE(DIO_LINKC_CNTL, + HPO_HDMI_ENC_SEL, hpo_inst); + else if (sel == ENCODER_TYPE_DP_128B132B) + REG_UPDATE(DIO_LINKC_CNTL, + HPO_DP_ENC_SEL, hpo_inst); + REG_UPDATE(DIO_LINKC_CNTL, + ENC_TYPE_SEL, sel); + break; + case TRANSMITTER_UNIPHY_D: + if (sel == ENCODER_TYPE_HDMI_FRL) + REG_UPDATE(DIO_LINKD_CNTL, + HPO_HDMI_ENC_SEL, hpo_inst); + else if (sel == ENCODER_TYPE_DP_128B132B) + REG_UPDATE(DIO_LINKD_CNTL, + HPO_DP_ENC_SEL, hpo_inst); + REG_UPDATE(DIO_LINKD_CNTL, + ENC_TYPE_SEL, sel); + break; + case TRANSMITTER_UNIPHY_E: + if (sel == ENCODER_TYPE_HDMI_FRL) + REG_UPDATE(DIO_LINKE_CNTL, + HPO_HDMI_ENC_SEL, hpo_inst); + else if (sel == ENCODER_TYPE_DP_128B132B) + REG_UPDATE(DIO_LINKE_CNTL, + HPO_DP_ENC_SEL, hpo_inst); + REG_UPDATE(DIO_LINKE_CNTL, + ENC_TYPE_SEL, sel); + break; + case TRANSMITTER_UNIPHY_F: + if (sel == ENCODER_TYPE_HDMI_FRL) + REG_UPDATE(DIO_LINKF_CNTL, + HPO_HDMI_ENC_SEL, hpo_inst); + else if (sel == ENCODER_TYPE_DP_128B132B) + REG_UPDATE(DIO_LINKF_CNTL, + HPO_DP_ENC_SEL, hpo_inst); + REG_UPDATE(DIO_LINKF_CNTL, + ENC_TYPE_SEL, sel); + break; + default: + /* Do nothing */ + break; + } +} + +void enc31_hw_init(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + +/* + 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 + 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 + 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 + 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 + 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 + 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 + 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 + 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 +*/ + +/* + AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, + AUX_RX_START_WINDOW = 1 [6:4] + AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] + AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 + AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 + AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 + AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 + AUX_RX_DETECTION_THRESHOLD [30:28] = 1 +*/ + // dmub will read AUX_DPHY_RX_CONTROL0/AUX_DPHY_TX_CONTROL from vbios table in dp_aux_init + + //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; + // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk + // 27MHz -> 0xd + // 100MHz -> 0x32 + // 48MHz -> 0x18 + + // Set TMDS_CTL0 to 1. This is a legacy setting. + REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); + + dcn10_aux_initialize(enc10); +} + +static const struct link_encoder_funcs dcn31_link_enc_funcs = { + .read_state = link_enc2_read_state, + .validate_output_with_stream = + dcn30_link_encoder_validate_output_with_stream, + .hw_init = enc31_hw_init, + .setup = dcn10_link_encoder_setup, + .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, + .enable_dp_output = dcn31_link_encoder_enable_dp_output, + .enable_dp_mst_output = dcn31_link_encoder_enable_dp_mst_output, + .disable_output = dcn31_link_encoder_disable_output, + .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dcn10_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dcn10_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, + .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dcn10_link_encoder_enable_hpd, + .disable_hpd = dcn10_link_encoder_disable_hpd, + .is_dig_enabled = dcn10_is_dig_enabled, + .destroy = dcn10_link_encoder_destroy, + .fec_set_enable = enc2_fec_set_enable, + .fec_set_ready = enc2_fec_set_ready, + .fec_is_active = enc2_fec_is_active, + .get_dig_frontend = dcn10_get_dig_frontend, + .get_dig_mode = dcn10_get_dig_mode, + .is_in_alt_mode = dcn31_link_encoder_is_in_alt_mode, + .get_max_link_cap = dcn31_link_encoder_get_max_link_cap, + .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux, +}; + +void dcn31_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask) +{ + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enum bp_result result = BP_RESULT_OK; + struct dcn10_link_encoder *enc10 = &enc20->enc10; + + enc10->base.funcs = &dcn31_link_enc_funcs; + enc10->base.ctx = init_data->ctx; + enc10->base.id = init_data->encoder; + + enc10->base.hpd_source = init_data->hpd_source; + enc10->base.connector = init_data->connector; + + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc10->base.features = *enc_features; + + enc10->base.transmitter = init_data->transmitter; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc10->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc10->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + enc10->link_regs = link_regs; + enc10->aux_regs = aux_regs; + enc10->hpd_regs = hpd_regs; + enc10->link_shift = link_shift; + enc10->link_mask = link_mask; + + switch (enc10->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc10->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc10->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc10->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc10->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc10->base.preferred_engine = ENGINE_ID_DIGE; + break; + case TRANSMITTER_UNIPHY_F: + enc10->base.preferred_engine = ENGINE_ID_DIGF; + break; + default: + ASSERT_CRITICAL(false); + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + /* default to one to mirror Windows behavior */ + enc10->base.features.flags.bits.HDMI_6GB_EN = 1; + + result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, + enc10->base.id, &bp_cap_info); + + /* Override features with DCE-specific values */ + if (result == BP_RESULT_OK) { + enc10->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_EN; + enc10->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE; + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; + enc10->base.features.flags.bits.DP_IS_USB_C = + bp_cap_info.DP_IS_USB_C; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, + result); + } + if (enc10->base.ctx->dc->debug.hdmi20_disable) { + enc10->base.features.flags.bits.HDMI_6GB_EN = 0; + } +} + +void dcn31_link_encoder_construct_minimal( + struct dcn20_link_encoder *enc20, + struct dc_context *ctx, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + enum engine_id eng_id) +{ + struct dcn10_link_encoder *enc10 = &enc20->enc10; + + enc10->base.funcs = &dcn31_link_enc_funcs; + enc10->base.ctx = ctx; + enc10->base.id.type = OBJECT_TYPE_ENCODER; + enc10->base.hpd_source = HPD_SOURCEID_UNKNOWN; + enc10->base.connector.type = OBJECT_TYPE_CONNECTOR; + enc10->base.preferred_engine = eng_id; + enc10->base.features = *enc_features; + enc10->base.transmitter = TRANSMITTER_UNKNOWN; + enc10->link_regs = link_regs; + + enc10->base.output_signals = + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP; +} + +/* DPIA equivalent of link_transmitter_control. */ +static bool link_dpia_control(struct dc_context *dc_ctx, + struct dmub_cmd_dig_dpia_control_data *dpia_control) +{ + union dmub_rb_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + + cmd.dig1_dpia_control.header.type = DMUB_CMD__DPIA; + cmd.dig1_dpia_control.header.sub_type = + DMUB_CMD__DPIA_DIG1_DPIA_CONTROL; + cmd.dig1_dpia_control.header.payload_bytes = + sizeof(cmd.dig1_dpia_control) - + sizeof(cmd.dig1_dpia_control.header); + + cmd.dig1_dpia_control.dpia_control = *dpia_control; + + dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; +} + +static void link_encoder_disable(struct dcn10_link_encoder *enc10) +{ + /* reset training complete */ + REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); +} + +void dcn31_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + /* Enable transmitter and encoder. */ + if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { + + DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); + dcn20_link_encoder_enable_dp_output(enc, link_settings, clock_source); + + } else { + + struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; + struct dc_link *link; + + link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); + + enc1_configure_encoder(enc10, link_settings); + + dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_ENABLE; + dpia_control.enc_id = enc->preferred_engine; + dpia_control.mode_laneset.digmode = 0; /* 0 for SST; 5 for MST */ + dpia_control.lanenum = (uint8_t)link_settings->lane_count; + dpia_control.symclk_10khz = link_settings->link_rate * + LINK_RATE_REF_FREQ_IN_KHZ / 10; + /* DIG_BE_CNTL.DIG_HPD_SELECT set to 5 (hpdsel - 1) to indicate HPD pin + * unused by DPIA. + */ + dpia_control.hpdsel = 6; + + if (link) { + dpia_control.dpia_id = link->ddc_hw_inst; + dpia_control.fec_rdy = link->dc->link_srv->dp_should_enable_fec(link); + } else { + DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); + BREAK_TO_DEBUGGER(); + return; + } + + DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); + link_dpia_control(enc->ctx, &dpia_control); + } +} + +void dcn31_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + /* Enable transmitter and encoder. */ + if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { + + DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); + dcn10_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source); + + } else { + + struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; + struct dc_link *link; + + link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); + + enc1_configure_encoder(enc10, link_settings); + + dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_ENABLE; + dpia_control.enc_id = enc->preferred_engine; + dpia_control.mode_laneset.digmode = 5; /* 0 for SST; 5 for MST */ + dpia_control.lanenum = (uint8_t)link_settings->lane_count; + dpia_control.symclk_10khz = link_settings->link_rate * + LINK_RATE_REF_FREQ_IN_KHZ / 10; + /* DIG_BE_CNTL.DIG_HPD_SELECT set to 5 (hpdsel - 1) to indicate HPD pin + * unused by DPIA. + */ + dpia_control.hpdsel = 6; + + if (link) { + dpia_control.dpia_id = link->ddc_hw_inst; + dpia_control.fec_rdy = link->dc->link_srv->dp_should_enable_fec(link); + } else { + DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); + BREAK_TO_DEBUGGER(); + return; + } + + DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); + link_dpia_control(enc->ctx, &dpia_control); + } +} + +void dcn31_link_encoder_disable_output( + struct link_encoder *enc, + enum signal_type signal) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + /* Disable transmitter and encoder. */ + if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { + + DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); + dcn10_link_encoder_disable_output(enc, signal); + + } else { + + struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; + struct dc_link *link; + + if (enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc)) + return; + + link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); + + dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_DISABLE; + dpia_control.enc_id = enc->preferred_engine; + if (signal == SIGNAL_TYPE_DISPLAY_PORT) { + dpia_control.mode_laneset.digmode = 0; /* 0 for SST; 5 for MST */ + } else if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + dpia_control.mode_laneset.digmode = 5; /* 0 for SST; 5 for MST */ + } else { + DC_LOG_ERROR("%s: USB4 DPIA only supports DisplayPort.\n", __func__); + BREAK_TO_DEBUGGER(); + } + + if (link) { + dpia_control.dpia_id = link->ddc_hw_inst; + } else { + DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); + BREAK_TO_DEBUGGER(); + return; + } + + DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); + link_dpia_control(enc->ctx, &dpia_control); + + link_encoder_disable(enc10); + } +} + +bool dcn31_link_encoder_is_in_alt_mode(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + union dmub_rb_cmd cmd; + uint32_t dp_alt_mode_disable; + + /* Only applicable to USB-C PHY. */ + if (!enc->features.flags.bits.DP_IS_USB_C) + return false; + + /* + * Use the new interface from DMCUB if available. + * Avoids hanging the RDCPSPIPE if DMCUB wasn't already running. + */ + if (has_query_dp_alt(enc)) { + if (!query_dp_alt_from_dmub(enc, &cmd)) + return false; + + return (cmd.query_dp_alt.data.is_dp_alt_disable == 0); + } + + /* Legacy path, avoid if possible. */ + if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) { + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, + &dp_alt_mode_disable); + } else { + /* + * B0 phys use a new set of registers to check whether alt mode is disabled. + * if value == 1 alt mode is disabled, otherwise it is enabled. + */ + if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) || + (enc10->base.transmitter == TRANSMITTER_UNIPHY_B) || + (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) { + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, + &dp_alt_mode_disable); + } else { + REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, + &dp_alt_mode_disable); + } + } + + return (dp_alt_mode_disable == 0); +} + +void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, struct dc_link_settings *link_settings) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + union dmub_rb_cmd cmd; + uint32_t is_in_usb_c_dp4_mode = 0; + + dcn10_link_encoder_get_max_link_cap(enc, link_settings); + + /* Take the link cap directly if not USB */ + if (!enc->features.flags.bits.DP_IS_USB_C) + return; + + /* + * Use the new interface from DMCUB if available. + * Avoids hanging the RDCPSPIPE if DMCUB wasn't already running. + */ + if (has_query_dp_alt(enc)) { + if (!query_dp_alt_from_dmub(enc, &cmd)) + return; + + if (cmd.query_dp_alt.data.is_usb && + cmd.query_dp_alt.data.is_dp4 == 0) + link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); + + return; + } + + /* Legacy path, avoid if possible. */ + if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) { + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, + &is_in_usb_c_dp4_mode); + } else { + if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) || + (enc10->base.transmitter == TRANSMITTER_UNIPHY_B) || + (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) { + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, + &is_in_usb_c_dp4_mode); + } else { + REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, + &is_in_usb_c_dp4_mode); + } + } + + if (!is_in_usb_c_dp4_mode) + link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); +} diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.h new file mode 100644 index 000000000000..ee78ba80797c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.h @@ -0,0 +1,290 @@ +/* + * 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 + * + */ + +#ifndef __DC_LINK_ENCODER__DCN31_H__ +#define __DC_LINK_ENCODER__DCN31_H__ + +#include "dcn30/dcn30_dio_link_encoder.h" + + +#define LE_DCN31_REG_LIST(id)\ + LE_DCN3_REG_LIST(id),\ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(DIO_LINKA_CNTL), \ + SR(DIO_LINKB_CNTL), \ + SR(DIO_LINKC_CNTL), \ + SR(DIO_LINKD_CNTL), \ + SR(DIO_LINKE_CNTL), \ + SR(DIO_LINKF_CNTL) + +#define LINK_ENCODER_MASK_SH_LIST_DCN31(mask_sh) \ + LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\ + LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh),\ + LE_SF(DIO_LINKA_CNTL, ENC_TYPE_SEL, mask_sh),\ + LE_SF(DIO_LINKA_CNTL, HPO_DP_ENC_SEL, mask_sh),\ + LE_SF(DIO_LINKA_CNTL, HPO_HDMI_ENC_SEL, mask_sh) + +#define DPCS_DCN31_REG_LIST(id) \ + SRI(TMDS_CTL_BITS, DIG, id), \ + SRI(RDPCSTX_PHY_CNTL3, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL6, RDPCSTX, id), \ + SRI(RDPCSPIPE_PHY_CNTL6, RDPCSPIPE, id), \ + SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL10, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL11, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL12, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL13, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL14, RDPCSTX, id), \ + SRI(RDPCSTX_CNTL, RDPCSTX, id), \ + SRI(RDPCSTX_CLOCK_CNTL, RDPCSTX, id), \ + SRI(RDPCSTX_INTERRUPT_CONTROL, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL2, RDPCSTX, id), \ + SRI(RDPCS_TX_CR_ADDR, RDPCSTX, id), \ + SRI(RDPCS_TX_CR_DATA, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE0, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ + SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ + SR(RDPCSTX0_RDPCSTX_SCRATCH), \ + SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ + SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) + +#define DPCS_DCN31_MASK_SH_LIST(mask_sh)\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_CLK_RDY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DATA_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX0_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX1_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX2_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL4, RDPCS_PHY_DP_TX3_TERM_CTRL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_MPLLB_MULTIPLIER, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_WIDTH, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX0_RATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_WIDTH, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL5, RDPCS_PHY_DP_TX1_RATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_PSTATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_PSTATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_MPLL_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_MPLL_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh),\ + LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_QUOT, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_DEN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL8, RDPCS_PHY_DP_MPLLB_SSC_PEAK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_UP_SPREAD, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL9, RDPCS_PHY_DP_MPLLB_SSC_STEPSIZE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL10, RDPCS_PHY_DP_MPLLB_FRACN_REM, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_REF_CLK_MPLLB_DIV, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_HDMI_MPLLB_HDMI_DIV, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_SSC_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_DIV5_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_TX_CLK_DIV, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_WORD_DIV2_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL12, RDPCS_PHY_DP_MPLLB_STATE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL13, RDPCS_PHY_DP_MPLLB_DIV_MULTIPLIER, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_FRACN_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL14, RDPCS_PHY_DP_MPLLB_PMIX_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE0_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE1_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE2_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_LANE3_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CNTL, RDPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_EXT_REFCLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_BYPASS, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SRAMCLK_CLOCK_ON, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_CLOCK_ON, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_GATE_DIS, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_SYMCLK_DIV2_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_DISABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_REQ, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_ACK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX0_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX1_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX2_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL3, RDPCS_PHY_DP_TX3_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_CR_MUX_SEL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_REF_RANGE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_BYPASS, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_EXT_LD_DONE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_HDMIMODE_ENABLE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_SRAM_INIT_DONE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL2, RDPCS_PHY_DP4_POR, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_REG_FIFO_ERROR_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_TX_FIFO_ERROR_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_DISABLE_TOGGLE_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_INTERRUPT_CONTROL, RDPCS_DPALT_4LANE_TOGGLE_MASK, mask_sh),\ + LE_SF(RDPCSTX0_RDPCS_TX_CR_ADDR, RDPCS_TX_CR_ADDR, mask_sh),\ + LE_SF(RDPCSTX0_RDPCS_TX_CR_DATA, RDPCS_TX_CR_DATA, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_V2I, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_TX0_EQ_POST, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE0, RDPCS_PHY_DP_MPLLB_FREQ_VCO, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_INT, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_MPLLB_CP_PROP, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE1, RDPCS_PHY_DP_TX1_EQ_POST, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE2, RDPCS_PHY_DP_TX2_EQ_POST, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_MAIN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_FINETUNE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DCO_RANGE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_PRE, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_FUSE3, RDPCS_PHY_DP_TX3_EQ_POST, mask_sh) + +#define DPCS_DCN314_REG_LIST(id) \ + SRI(TMDS_CTL_BITS, DIG, id), \ + SRI(RDPCSTX_PHY_CNTL3, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL10, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL11, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL12, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL13, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL14, RDPCSTX, id), \ + SRI(RDPCSTX_CNTL, RDPCSTX, id), \ + SRI(RDPCSTX_CLOCK_CNTL, RDPCSTX, id), \ + SRI(RDPCSTX_INTERRUPT_CONTROL, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL0, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_CNTL2, RDPCSTX, id), \ + SRI(RDPCS_TX_CR_ADDR, RDPCSTX, id), \ + SRI(RDPCS_TX_CR_DATA, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE0, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ + SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ + SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ + SR(RDPCSTX0_RDPCSTX_SCRATCH), \ + SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ + SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) + +void dcn31_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask); + +/* + * Create a minimal link encoder object with no dc_link object associated with it. + */ +void dcn31_link_encoder_construct_minimal( + struct dcn20_link_encoder *enc20, + struct dc_context *ctx, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + enum engine_id eng_id); + +void dcn31_link_encoder_set_dio_phy_mux( + struct link_encoder *enc, + enum encoder_type_select sel, + uint32_t hpo_inst); + +/* + * Enable DP transmitter and its encoder. + */ +void dcn31_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* + * Enable DP transmitter and its encoder in MST mode. + */ +void dcn31_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* + * Disable transmitter and its encoder. + */ +void dcn31_link_encoder_disable_output( + struct link_encoder *enc, + enum signal_type signal); + +/* + * Check whether USB-C DP Alt mode is disabled + */ +bool dcn31_link_encoder_is_in_alt_mode( + struct link_encoder *enc); + +void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, + struct dc_link_settings *link_settings); + +void enc31_hw_init(struct link_encoder *enc); + +#endif /* __DC_LINK_ENCODER__DCN31_H__ */