From 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 22 Oct 2024 10:36:11 +0000 Subject: [PATCH] 修改4g拨号为QMI,需要在系统里后台执行quectel-CM --- kernel/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 156 ++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 121 insertions(+), 35 deletions(-) diff --git a/kernel/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/kernel/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c index 6f67520..85dc2b1 100644 --- a/kernel/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c +++ b/kernel/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c @@ -23,6 +23,9 @@ * */ +#include <linux/delay.h> +#include <linux/slab.h> + #include "reg_helper.h" #include "core_types.h" @@ -85,7 +88,10 @@ .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 + .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( @@ -228,7 +234,9 @@ { uint32_t value; - ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); + if (!REG(DP_DPHY_INTERNAL_CTRL)) + return; + value = REG_READ(DP_DPHY_INTERNAL_CTRL); switch (panel_mode) { @@ -440,7 +448,46 @@ } } -void configure_encoder( +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) { @@ -543,12 +590,12 @@ 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_khz > TMDS_MAX_PIXEL_CLOCK) + crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10)) return false; - if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) + if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) return false; - if (crtc_timing->pix_clk_khz > max_pixel_clock) + if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10)) return false; /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */ @@ -571,30 +618,36 @@ static bool dcn10_link_encoder_validate_hdmi_output( const struct dcn10_link_encoder *enc10, const struct dc_crtc_timing *crtc_timing, - int adjusted_pix_clk_khz) + 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_khz < TMDS_MIN_PIXEL_CLOCK) + if (adjusted_pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) return false; - if ((adjusted_pix_clk_khz == 0) || - (adjusted_pix_clk_khz > enc10->base.features.max_hdmi_pixel_clock)) + 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.ycbcr420_supported && + 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 && - adjusted_pix_clk_khz >= 300000) + adjusted_pix_clk_100hz >= 3000000) return false; if (enc10->base.ctx->dc->debug.hdmi20_disable && crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) @@ -606,22 +659,12 @@ const struct dcn10_link_encoder *enc10, const struct dc_crtc_timing *crtc_timing) { - /* default RGB only */ - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) - return true; + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) { + if (!enc10->base.features.dp_ycbcr420_supported) + return false; + } - if (enc10->base.features.flags.bits.IS_YCBCR_CAPABLE) - return true; - - /* for DCE 8.x or later DP Y-only feature, - * we need ASIC cap + FeatureSupportDPYonly, not support 666 - */ - if (crtc_timing->flags.Y_ONLY && - enc10->base.features.flags.bits.IS_YCBCR_CAPABLE && - crtc_timing->display_color_depth != COLOR_DEPTH_666) - return true; - - return false; + return true; } void dcn10_link_encoder_construct( @@ -726,6 +769,8 @@ 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__, @@ -743,12 +788,17 @@ 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->sink->link->connector_signal, + stream->link->connector_signal, stream->signal, &stream->timing); break; @@ -756,7 +806,8 @@ is_valid = dcn10_link_encoder_validate_hdmi_output( enc10, &stream->timing, - stream->phy_pix_clk); + &stream->sink->edid_caps, + stream->phy_pix_clk * 10); break; case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: @@ -920,7 +971,7 @@ * but it's not passed to asic_control. * We need to set number of lanes manually. */ - configure_encoder(enc10, link_settings); + enc1_configure_encoder(enc10, link_settings); cntl.action = TRANSMITTER_CONTROL_ENABLE; cntl.engine_id = enc->preferred_engine; @@ -959,7 +1010,7 @@ * but it's not passed to asic_control. * We need to set number of lanes manually. */ - configure_encoder(enc10, link_settings); + enc1_configure_encoder(enc10, link_settings); cntl.action = TRANSMITTER_CONTROL_ENABLE; cntl.engine_id = ENGINE_ID_UNKNOWN; @@ -1304,7 +1355,6 @@ #define HPD_REG_UPDATE_N(reg_name, n, ...) \ generic_reg_update_ex(CTX, \ HPD_REG(reg_name), \ - HPD_REG_READ(reg_name), \ n, __VA_ARGS__) #define HPD_REG_UPDATE(reg_name, field, val) \ @@ -1327,7 +1377,6 @@ DC_HPD_EN, 0); } - #define AUX_REG(reg)\ (enc10->aux_regs->reg) @@ -1337,7 +1386,6 @@ #define AUX_REG_UPDATE_N(reg_name, n, ...) \ generic_reg_update_ex(CTX, \ AUX_REG(reg_name), \ - AUX_REG_READ(reg_name), \ n, __VA_ARGS__) #define AUX_REG_UPDATE(reg_name, field, val) \ @@ -1359,5 +1407,43 @@ /* 1/4 window (the maximum allowed) */ AUX_REG_UPDATE(AUX_DPHY_RX_CONTROL0, - AUX_RX_RECEIVE_WINDOW, 1); + 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; + } + 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; + + *link_settings = max_link_cap; } -- Gitblit v1.6.2