]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/display: Keep VBios pixel rate div setting util next mode set
authorWebb Chen <yi-lchen@amd.com>
Tue, 27 Feb 2024 02:01:25 +0000 (10:01 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 30 Apr 2024 13:49:45 +0000 (09:49 -0400)
[why]
VBios & Driver may have differnet pixel rate div policy.
If the policy is not same and fast boot is enabled,
it would cause the pixel rate is too high
after driver only performs stream blank & unblank.

[how]
We would keep pixel rate div setting by VBios until next mode set.

Reviewed-by: Jun Lei <jun.lei@amd.com>
Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Webb Chen <yi-lchen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
20 files changed:
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c
drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.c
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
drivers/gpu/drm/amd/display/dc/inc/core_types.h
drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h

index ebbeb37f36a6f1af79cbba479bbff9ea9add2ff6..7e56f6987b13b9fe3fc1861e0d7cc730ef2cd776 100644 (file)
@@ -49,6 +49,7 @@
 #include "link/hwss/link_hwss_hpo_dp.h"
 #include "link/hwss/link_hwss_dio_fixed_vs_pe_retimer.h"
 #include "link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.h"
+#include "hw_sequencer_private.h"
 
 #if defined(CONFIG_DRM_AMD_DC_SI)
 #include "dce60/dce60_resource.h"
@@ -3902,6 +3903,9 @@ enum dc_status dc_validate_with_context(struct dc *dc,
                if (res != DC_OK)
                        goto fail;
 
+               if (dc->hwseq->funcs.calculate_pix_rate_divider)
+                       dc->hwseq->funcs.calculate_pix_rate_divider(dc, context, add_streams[i]);
+
                if (!add_all_planes_for_stream(dc, add_streams[i], set, set_count, context)) {
                        res = DC_FAIL_ATTACH_SURFACES;
                        goto fail;
index 17a1174b8d80203eaf8b1dce224847ce051cedd9..8f6edd8e9bebb3a0631a3da4bdf27fed5819ce2b 100644 (file)
@@ -58,8 +58,8 @@ static void dccg314_trigger_dio_fifo_resync(
 static void dccg314_get_pixel_rate_div(
                struct dccg *dccg,
                uint32_t otg_inst,
-               enum pixel_rate_div *k1,
-               enum pixel_rate_div *k2)
+               uint32_t *k1,
+               uint32_t *k2)
 {
        struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
        uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
@@ -93,8 +93,8 @@ static void dccg314_get_pixel_rate_div(
                return;
        }
 
-       *k1 = (enum pixel_rate_div)val_k1;
-       *k2 = (enum pixel_rate_div)val_k2;
+       *k1 = val_k1;
+       *k2 = val_k2;
 }
 
 static void dccg314_set_pixel_rate_div(
@@ -104,7 +104,8 @@ static void dccg314_set_pixel_rate_div(
                enum pixel_rate_div k2)
 {
        struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
-       enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
+       uint32_t cur_k1 = PIXEL_RATE_DIV_NA;
+       uint32_t cur_k2 = PIXEL_RATE_DIV_NA;
 
        // Don't program 0xF into the register field. Not valid since
        // K1 / K2 field is only 1 / 2 bits wide
@@ -373,6 +374,7 @@ static const struct dccg_funcs dccg314_funcs = {
        .disable_dsc = dccg31_disable_dscclk,
        .enable_dsc = dccg31_enable_dscclk,
        .set_pixel_rate_div = dccg314_set_pixel_rate_div,
+       .get_pixel_rate_div = dccg314_get_pixel_rate_div,
        .trigger_dio_fifo_resync = dccg314_trigger_dio_fifo_resync,
        .set_valid_pixel_rate = dccg314_set_valid_pixel_rate,
        .set_dtbclk_p_src = dccg314_set_dtbclk_p_src
index 036d05468d76c9a845d522dba7e55c988878ca33..21a6ca5ca19276d1d189d8b8da96cb63e603fae5 100644 (file)
@@ -58,8 +58,8 @@ static void dccg32_trigger_dio_fifo_resync(
 static void dccg32_get_pixel_rate_div(
                struct dccg *dccg,
                uint32_t otg_inst,
-               enum pixel_rate_div *k1,
-               enum pixel_rate_div *k2)
+               uint32_t *k1,
+               uint32_t *k2)
 {
        struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
        uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
@@ -93,8 +93,8 @@ static void dccg32_get_pixel_rate_div(
                return;
        }
 
-       *k1 = (enum pixel_rate_div)val_k1;
-       *k2 = (enum pixel_rate_div)val_k2;
+       *k1 = val_k1;
+       *k2 = val_k2;
 }
 
 static void dccg32_set_pixel_rate_div(
@@ -104,8 +104,8 @@ static void dccg32_set_pixel_rate_div(
                enum pixel_rate_div k2)
 {
        struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
-
-       enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
+       uint32_t cur_k1 = PIXEL_RATE_DIV_NA;
+       uint32_t cur_k2 = PIXEL_RATE_DIV_NA;
 
        // Don't program 0xF into the register field. Not valid since
        // K1 / K2 field is only 1 / 2 bits wide
@@ -344,6 +344,7 @@ static const struct dccg_funcs dccg32_funcs = {
        .otg_add_pixel = dccg32_otg_add_pixel,
        .otg_drop_pixel = dccg32_otg_drop_pixel,
        .set_pixel_rate_div = dccg32_set_pixel_rate_div,
+       .get_pixel_rate_div = dccg32_get_pixel_rate_div,
        .trigger_dio_fifo_resync = dccg32_trigger_dio_fifo_resync,
        .set_dtbclk_p_src = dccg32_set_dtbclk_p_src,
 };
index 2fef1419ae91743cbfd2903df5f64d85751758fb..1a9bb614c41e03b60cffde9c0f542c4f9c912f26 100644 (file)
 
 static void enc32_dp_set_odm_combine(
        struct stream_encoder *enc,
-       bool odm_combine)
+       bool two_pixel_per_cyle)
 {
        struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
 
-       REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_PER_CYCLE_PROCESSING_MODE, odm_combine ? 1 : 0);
+       REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_PER_CYCLE_PROCESSING_MODE, two_pixel_per_cyle ? 1 : 0);
 }
 
 /* setup stream encoder in dvi mode */
@@ -241,46 +241,12 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
        return two_pix;
 }
 
-static bool is_h_timing_divisible_by_2(const struct dc_crtc_timing *timing)
-{
-       /* math borrowed from function of same name in inc/resource
-        * checks if h_timing is divisible by 2
-        */
-
-       bool divisible = false;
-       uint16_t h_blank_start = 0;
-       uint16_t h_blank_end = 0;
-
-       if (timing) {
-               h_blank_start = timing->h_total - timing->h_front_porch;
-               h_blank_end = h_blank_start - timing->h_addressable;
-
-               /* HTOTAL, Hblank start/end, and Hsync start/end all must be
-                * divisible by 2 in order for the horizontal timing params
-                * to be considered divisible by 2. Hsync start is always 0.
-                */
-               divisible = (timing->h_total % 2 == 0) &&
-                               (h_blank_start % 2 == 0) &&
-                               (h_blank_end % 2 == 0) &&
-                               (timing->h_sync_width % 2 == 0);
-       }
-       return divisible;
-}
-
-static bool is_dp_dig_pixel_rate_div_policy(struct dc *dc, const struct dc_crtc_timing *timing)
-{
-       /* should be functionally the same as dcn32_is_dp_dig_pixel_rate_div_policy for DP encoders*/
-       return is_h_timing_divisible_by_2(timing) &&
-               dc->debug.enable_dp_dig_pixel_rate_div_policy;
-}
-
 void enc32_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);
-       struct dc *dc = enc->ctx->dc;
 
        if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
                uint32_t n_vid = 0x8000;
@@ -291,7 +257,7 @@ void enc32_stream_encoder_dp_unblank(
 
                /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */
                if (is_two_pixels_per_containter(&param->timing) || param->opp_cnt > 1
-                       || is_dp_dig_pixel_rate_div_policy(dc, &param->timing)) {
+                       || param->pix_per_cycle > 1) {
                        /*this logic should be the same in get_pixel_clock_parameters() */
                        n_multiply = 1;
                        pix_per_cycle = 1;
index 58dd3c5bbff092478a698b652b1a3a0eedd72cd8..4c53e339e3256b63749b965c7a6c62984aec7fa3 100644 (file)
@@ -137,8 +137,8 @@ static void dccg35_set_dppclk_root_clock_gating(struct dccg *dccg,
 static void dccg35_get_pixel_rate_div(
                struct dccg *dccg,
                uint32_t otg_inst,
-               enum pixel_rate_div *k1,
-               enum pixel_rate_div *k2)
+               uint32_t *k1,
+               uint32_t *k2)
 {
        struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
        uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
@@ -183,7 +183,8 @@ static void dccg35_set_pixel_rate_div(
                enum pixel_rate_div k2)
 {
        struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
-       enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
+       uint32_t cur_k1 = PIXEL_RATE_DIV_NA;
+       uint32_t cur_k2 = PIXEL_RATE_DIV_NA;
 
        // Don't program 0xF into the register field. Not valid since
        // K1 / K2 field is only 1 / 2 bits wide
@@ -1054,6 +1055,7 @@ static const struct dccg_funcs dccg35_funcs = {
        .disable_dsc = dccg35_disable_dscclk,
        .enable_dsc = dccg35_enable_dscclk,
        .set_pixel_rate_div = dccg35_set_pixel_rate_div,
+       .get_pixel_rate_div = dccg35_get_pixel_rate_div,
        .set_valid_pixel_rate = dccg35_set_valid_pixel_rate,
        .enable_symclk_se = dccg35_enable_symclk_se,
        .disable_symclk_se = dccg35_disable_symclk_se,
index 62a8f0b56006201d6b8db01a0641d5a355887cbb..2595cbef59423cd0a8f8a2fc31596da7badce4eb 100644 (file)
@@ -273,46 +273,12 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
        return two_pix;
 }
 
-static bool is_h_timing_divisible_by_2(const struct dc_crtc_timing *timing)
-{
-       /* math borrowed from function of same name in inc/resource
-        * checks if h_timing is divisible by 2
-        */
-
-       bool divisible = false;
-       uint16_t h_blank_start = 0;
-       uint16_t h_blank_end = 0;
-
-       if (timing) {
-               h_blank_start = timing->h_total - timing->h_front_porch;
-               h_blank_end = h_blank_start - timing->h_addressable;
-
-               /* HTOTAL, Hblank start/end, and Hsync start/end all must be
-                * divisible by 2 in order for the horizontal timing params
-                * to be considered divisible by 2. Hsync start is always 0.
-                */
-               divisible = (timing->h_total % 2 == 0) &&
-                               (h_blank_start % 2 == 0) &&
-                               (h_blank_end % 2 == 0) &&
-                               (timing->h_sync_width % 2 == 0);
-       }
-       return divisible;
-}
-
-static bool is_dp_dig_pixel_rate_div_policy(struct dc *dc, const struct dc_crtc_timing *timing)
-{
-       /* should be functionally the same as dcn32_is_dp_dig_pixel_rate_div_policy for DP encoders*/
-       return is_h_timing_divisible_by_2(timing) &&
-               dc->debug.enable_dp_dig_pixel_rate_div_policy;
-}
-
 static void enc35_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);
-       struct dc *dc = enc->ctx->dc;
 
        if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
                uint32_t n_vid = 0x8000;
@@ -323,7 +289,7 @@ static void enc35_stream_encoder_dp_unblank(
 
                /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */
                if (is_two_pixels_per_containter(&param->timing) || param->opp_cnt > 1
-                       || is_dp_dig_pixel_rate_div_policy(dc, &param->timing)) {
+                       || param->pix_per_cycle > 1) {
                        /*this logic should be the same in get_pixel_clock_parameters() */
                        n_multiply = 1;
                        pix_per_cycle = 1;
index 0d3ea291eeee1847b30daa9c503719cced93090b..5b4b16326ddfc15468d1835a0af97cf9d8473653 100644 (file)
@@ -1782,6 +1782,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
        struct dc_stream_state *edp_streams[MAX_NUM_EDP];
        struct dc_link *edp_link_with_sink = NULL;
        struct dc_link *edp_link = NULL;
+       struct pipe_ctx *pipe_ctx = NULL;
        struct dce_hwseq *hws = dc->hwseq;
        int edp_with_sink_num;
        int edp_num;
@@ -1818,9 +1819,26 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
                                can_apply_edp_fast_boot = dc_validate_boot_timing(dc,
                                        edp_stream->sink, &edp_stream->timing);
                                edp_stream->apply_edp_fast_boot_optimization = can_apply_edp_fast_boot;
-                               if (can_apply_edp_fast_boot)
-                                       DC_LOG_EVENT_LINK_TRAINING("eDP fast boot disabled to optimize link rate\n");
-
+                               if (can_apply_edp_fast_boot) {
+                                       DC_LOG_EVENT_LINK_TRAINING("eDP fast boot Enable\n");
+
+                                       // Vbios & Driver support different pixel rate div policy.
+                                       pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, edp_stream);
+                                       if (pipe_ctx &&
+                                               hws->funcs.is_dp_dig_pixel_rate_div_policy &&
+                                               hws->funcs.is_dp_dig_pixel_rate_div_policy(pipe_ctx)) {
+                                               // Get Vbios div factor from register
+                                               dc->res_pool->dccg->funcs->get_pixel_rate_div(
+                                                       dc->res_pool->dccg,
+                                                       pipe_ctx->stream_res.tg->inst,
+                                                       &pipe_ctx->pixel_rate_divider.div_factor1,
+                                                       &pipe_ctx->pixel_rate_divider.div_factor2);
+
+                                               // VBios doesn't support pixel rate div, so force it.
+                                               // If VBios supports it, we check it from reigster or other flags.
+                                               pipe_ctx->pixel_per_cycle = 1;
+                                       }
+                               }
                                break;
                        }
                }
index 429d3b6620501dcb582322aa3d520e971eccbfa7..37b61891f11e05d7098afcd275d9bd265c22a084 100644 (file)
@@ -828,17 +828,14 @@ enum dc_status dcn20_enable_stream_timing(
        struct mpc_dwb_flow_control flow_control;
        struct mpc *mpc = dc->res_pool->mpc;
        bool rate_control_2x_pclk = (interlace || optc2_is_two_pixels_per_containter(&stream->timing));
-       unsigned int k1_div = PIXEL_RATE_DIV_NA;
-       unsigned int k2_div = PIXEL_RATE_DIV_NA;
-
-       if (hws->funcs.calculate_dccg_k1_k2_values && dc->res_pool->dccg->funcs->set_pixel_rate_div) {
-               hws->funcs.calculate_dccg_k1_k2_values(pipe_ctx, &k1_div, &k2_div);
 
+       if (dc->res_pool->dccg->funcs->set_pixel_rate_div)
                dc->res_pool->dccg->funcs->set_pixel_rate_div(
                        dc->res_pool->dccg,
                        pipe_ctx->stream_res.tg->inst,
-                       k1_div, k2_div);
-       }
+                       pipe_ctx->pixel_rate_divider.div_factor1,
+                       pipe_ctx->pixel_rate_divider.div_factor2);
+
        /* by upper caller loop, pipe0 is parent pipe and be called first.
         * back end is set up by for pipe0. Other children pipe share back end
         * with pipe 0. No program is needed.
@@ -2893,9 +2890,6 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
        struct dccg *dccg = dc->res_pool->dccg;
        enum phyd32clk_clock_source phyd32clk;
        int dp_hpo_inst;
-       struct dce_hwseq *hws = dc->hwseq;
-       unsigned int k1_div = PIXEL_RATE_DIV_NA;
-       unsigned int k2_div = PIXEL_RATE_DIV_NA;
        struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link);
        struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
 
@@ -2916,14 +2910,13 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
                        dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst,
                                                      link_enc->transmitter - TRANSMITTER_UNIPHY_A);
        }
-       if (hws->funcs.calculate_dccg_k1_k2_values && dc->res_pool->dccg->funcs->set_pixel_rate_div) {
-               hws->funcs.calculate_dccg_k1_k2_values(pipe_ctx, &k1_div, &k2_div);
 
+       if (dc->res_pool->dccg->funcs->set_pixel_rate_div)
                dc->res_pool->dccg->funcs->set_pixel_rate_div(
                        dc->res_pool->dccg,
                        pipe_ctx->stream_res.tg->inst,
-                       k1_div, k2_div);
-       }
+                       pipe_ctx->pixel_rate_divider.div_factor1,
+                       pipe_ctx->pixel_rate_divider.div_factor2);
 
        link_hwss->setup_stream_encoder(pipe_ctx);
 
index 0d8a05cf8b1a1850c52fa3f54f755f09325c9dbd..948b8398d1a6e2578cd8e4d979fe1f866ae53392 100644 (file)
@@ -332,6 +332,29 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig
        return odm_combine_factor;
 }
 
+void dcn314_calculate_pix_rate_divider(
+               struct dc *dc,
+               struct dc_state *context,
+               const struct dc_stream_state *stream)
+{
+       struct dce_hwseq *hws = dc->hwseq;
+       struct pipe_ctx *pipe_ctx = NULL;
+       unsigned int k1_div = PIXEL_RATE_DIV_NA;
+       unsigned int k2_div = PIXEL_RATE_DIV_NA;
+
+       pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
+
+       if (pipe_ctx) {
+               pipe_ctx->pixel_per_cycle = 1;
+
+               if (hws->funcs.calculate_dccg_k1_k2_values)
+                       hws->funcs.calculate_dccg_k1_k2_values(pipe_ctx, &k1_div, &k2_div);
+
+               pipe_ctx->pixel_rate_divider.div_factor1 = k1_div;
+               pipe_ctx->pixel_rate_divider.div_factor2 = k2_div;
+       }
+}
+
 void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
 {
        uint32_t pix_per_cycle = 1;
index eafcc4ea6d2498262863c337572bb2c71d0283c5..fb94e327d4eea05ef78d60a3ab2dd4040705d2aa 100644 (file)
@@ -39,6 +39,10 @@ void dcn314_enable_power_gating_plane(struct dce_hwseq *hws, bool enable);
 
 unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div);
 
+void dcn314_calculate_pix_rate_divider(struct dc *dc,
+       struct dc_state *context,
+       const struct dc_stream_state *stream);
+
 void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx);
 
 void dcn314_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context);
index 542ce3b7f9e4d12d4bf7c6fcab2b4ce05c01f4f5..934203ef52bb649beb527c4c618baf4a3b2ffe59 100644 (file)
@@ -151,6 +151,7 @@ static const struct hwseq_private_funcs dcn314_private_funcs = {
        .set_shaper_3dlut = dcn20_set_shaper_3dlut,
        .setup_hpo_hw_control = dcn31_setup_hpo_hw_control,
        .calculate_dccg_k1_k2_values = dcn314_calculate_dccg_k1_k2_values,
+       .calculate_pix_rate_divider = dcn314_calculate_pix_rate_divider,
        .set_pixels_per_cycle = dcn314_set_pixels_per_cycle,
        .resync_fifo_dccg_dio = dcn314_resync_fifo_dccg_dio,
 };
index b8e884368dc6e5580bfb740d8872d9a7e578b907..1c56e3f3f7d1f8363058bdd055c9b317994b89a5 100644 (file)
@@ -1159,15 +1159,14 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
 
 void dcn32_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
 {
-       uint32_t pix_per_cycle = 1;
+       uint32_t pix_per_cycle = pipe_ctx->pixel_per_cycle;
        uint32_t odm_combine_factor = 1;
 
        if (!pipe_ctx || !pipe_ctx->stream || !pipe_ctx->stream_res.stream_enc)
                return;
 
        odm_combine_factor = get_odm_config(pipe_ctx, NULL);
-       if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1
-               || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx))
+       if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1)
                pix_per_cycle = 2;
 
        if (pipe_ctx->stream_res.stream_enc->funcs->set_input_mode)
@@ -1213,8 +1212,8 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
        struct dc_link *link = stream->link;
        struct dce_hwseq *hws = link->dc->hwseq;
        struct pipe_ctx *odm_pipe;
-       uint32_t pix_per_cycle = 1;
 
+       params.pix_per_cycle = pipe_ctx->pixel_per_cycle;
        params.opp_cnt = 1;
        for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
                params.opp_cnt++;
@@ -1230,13 +1229,14 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
                                pipe_ctx->stream_res.hpo_dp_stream_enc,
                                pipe_ctx->stream_res.tg->inst);
        } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
-               if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1
-                       || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) {
+               if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1)
+                       params.pix_per_cycle = 2;
+
+               if (params.pix_per_cycle == 2)
                        params.timing.pix_clk_100hz /= 2;
-                       pix_per_cycle = 2;
-               }
+
                pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
-                               pipe_ctx->stream_res.stream_enc, pix_per_cycle > 1);
+                               pipe_ctx->stream_res.stream_enc, params.pix_per_cycle > 1);
                pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, &params);
        }
 
@@ -1257,6 +1257,32 @@ bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx)
        return false;
 }
 
+void dcn32_calculate_pix_rate_divider(
+               struct dc *dc,
+               struct dc_state *context,
+               const struct dc_stream_state *stream)
+{
+       struct dce_hwseq *hws = dc->hwseq;
+       struct pipe_ctx *pipe_ctx = NULL;
+       unsigned int k1_div = PIXEL_RATE_DIV_NA;
+       unsigned int k2_div = PIXEL_RATE_DIV_NA;
+
+       pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
+
+       if (pipe_ctx) {
+               pipe_ctx->pixel_per_cycle = 1;
+
+               if (dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx))
+                       pipe_ctx->pixel_per_cycle = 2;
+
+               if (hws->funcs.calculate_dccg_k1_k2_values)
+                       hws->funcs.calculate_dccg_k1_k2_values(pipe_ctx, &k1_div, &k2_div);
+
+               pipe_ctx->pixel_rate_divider.div_factor1 = k1_div;
+               pipe_ctx->pixel_rate_divider.div_factor2 = k2_div;
+       }
+}
+
 static void apply_symclk_on_tx_off_wa(struct dc_link *link)
 {
        /* There are use cases where SYMCLK is referenced by OTG. For instance
index f55c11fc56ec7a7a3d86cff32269a89fb6c5a3d5..d6345a2408be9a7bc8759d10f2ff7cab5b207148 100644 (file)
@@ -91,6 +91,10 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
 
 bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx);
 
+void dcn32_calculate_pix_rate_divider(struct dc *dc,
+               struct dc_state *context,
+               const struct dc_stream_state *stream);
+
 void dcn32_disable_link_output(struct dc_link *link,
                const struct link_resource *link_res,
                enum signal_type signal);
index b1f79ca7d77a7720cf4ef09f52e88db6200d39eb..033dca8b9a4722e5765893909698017b42e8313a 100644 (file)
@@ -161,6 +161,7 @@ static const struct hwseq_private_funcs dcn32_private_funcs = {
        .set_pixels_per_cycle = dcn32_set_pixels_per_cycle,
        .resync_fifo_dccg_dio = dcn32_resync_fifo_dccg_dio,
        .is_dp_dig_pixel_rate_div_policy = dcn32_is_dp_dig_pixel_rate_div_policy,
+       .calculate_pix_rate_divider = dcn32_calculate_pix_rate_divider,
        .apply_single_controller_ctx_to_hw = dce110_apply_single_controller_ctx_to_hw,
        .reset_back_end_for_pipe = dcn20_reset_back_end_for_pipe,
        .populate_mcm_luts = dcn401_populate_mcm_luts,
index df3bf77f3fb46f3d7047b5bcf0f54306c554fa93..7ed5de5c5ec1ab12d13630530c19c447cd5b1ee5 100644 (file)
@@ -159,6 +159,7 @@ static const struct hwseq_private_funcs dcn35_private_funcs = {
        .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
        .set_pixels_per_cycle = dcn32_set_pixels_per_cycle,
        .is_dp_dig_pixel_rate_div_policy = dcn32_is_dp_dig_pixel_rate_div_policy,
+       .calculate_pix_rate_divider = dcn32_calculate_pix_rate_divider,
        .dsc_pg_control = dcn35_dsc_pg_control,
        .dsc_pg_status = dcn32_dsc_pg_status,
        .enable_plane = dcn35_enable_plane,
index c4944478ed912f3f5c537910d43763808f036429..3a5352c57c05064fcf97e57c2f207ca42df7ae5f 100644 (file)
@@ -158,6 +158,7 @@ static const struct hwseq_private_funcs dcn351_private_funcs = {
        .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
        .set_pixels_per_cycle = dcn32_set_pixels_per_cycle,
        .is_dp_dig_pixel_rate_div_policy = dcn32_is_dp_dig_pixel_rate_div_policy,
+       .calculate_pix_rate_divider = dcn32_calculate_pix_rate_divider,
        .dsc_pg_control = dcn35_dsc_pg_control,
        .dsc_pg_status = dcn32_dsc_pg_status,
        .enable_plane = dcn35_enable_plane,
index 3a23d05a615ef78691cb7cb8e2fe8da821931bb7..939832372baf1fa2914b3ec96238c9a8b619b3d7 100644 (file)
@@ -173,6 +173,9 @@ struct hwseq_private_funcs {
                        struct dc_state *context,
                        struct dc *dc);
        bool (*is_dp_dig_pixel_rate_div_policy)(struct pipe_ctx *pipe_ctx);
+       void (*calculate_pix_rate_divider)(struct dc *dc,
+                       struct dc_state *context,
+                       const struct dc_stream_state *stream);
        void (*reset_back_end_for_pipe)(struct dc *dc,
                        struct pipe_ctx *pipe_ctx,
                        struct dc_state *context);
index 286f3219b77e124c22bc42340356417a62926f88..634d52fe111ec2d54e3226f3393024d20983e73d 100644 (file)
@@ -399,6 +399,11 @@ union pipe_update_flags {
        uint32_t raw;
 };
 
+struct pixel_rate_divider {
+       uint32_t div_factor1;
+       uint32_t div_factor2;
+};
+
 enum p_state_switch_method {
        P_STATE_UNKNOWN                                         = 0,
        P_STATE_V_BLANK                                         = 1,
@@ -464,6 +469,8 @@ struct pipe_ctx {
        bool has_vactive_margin;
        /* subvp_index: only valid if the pipe is a SUBVP_MAIN*/
        uint8_t subvp_index;
+       uint32_t pixel_per_cycle;
+       struct pixel_rate_divider pixel_rate_divider;
 };
 
 /* Data used for dynamic link encoder assignment.
index d4c7885fc916e5cf1ddae7f2af1f0ee98dca4054..d6248a73c7c170a1d8be166fb1a20384246885f7 100644 (file)
@@ -176,6 +176,11 @@ struct dccg_funcs {
                        enum pixel_rate_div k1,
                        enum pixel_rate_div k2);
 
+       void (*get_pixel_rate_div)(struct dccg *dccg,
+                       uint32_t otg_inst,
+                       uint32_t *div_factor1,
+                       uint32_t *div_factor2);
+
        void (*set_valid_pixel_rate)(
                        struct dccg *dccg,
                        int ref_dtbclk_khz,
index 75b9ec21f29785c59f414c6db9554a47bf296f7f..60228f5de4d7626c3025ec48e90cf856111963b4 100644 (file)
@@ -99,6 +99,7 @@ struct encoder_unblank_param {
        struct dc_link_settings link_settings;
        struct dc_crtc_timing timing;
        int opp_cnt;
+       uint32_t pix_per_cycle;
 };
 
 struct encoder_set_dp_phy_pattern_param {