]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/display: Disable MPC rate control on ODM pipe update
authorGeorge Shen <george.shen@amd.com>
Thu, 5 Dec 2024 21:58:21 +0000 (16:58 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 18 Dec 2024 17:21:50 +0000 (12:21 -0500)
[Why]
Seamless boot skips MPC init for the active pipe, resulting in stale MPC
rate control state being retained. This will cause issues since other
logic assumes it is disabled (as DCN30 and newer does not need it).

[How]
Disable MPC rate control on ODM pipe update to cover the seamless boot
case.

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: George Shen <george.shen@amd.com>
Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c
drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.h

index 9b88eb72086db5595bd998a546acab90cb3ed03b..be26c925fdfa1a969b04a4cc9bbca2e09f0e158c 100644 (file)
@@ -162,6 +162,8 @@ void dcn314_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx
        int opp_inst[MAX_PIPES] = {0};
        int odm_slice_width = resource_get_odm_slice_dst_width(pipe_ctx, false);
        int last_odm_slice_width = resource_get_odm_slice_dst_width(pipe_ctx, true);
+       struct mpc *mpc = dc->res_pool->mpc;
+       int i;
 
        opp_cnt = get_odm_config(pipe_ctx, opp_inst);
 
@@ -174,6 +176,16 @@ void dcn314_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx
                pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
                                pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
 
+       if (mpc->funcs->set_out_rate_control) {
+               for (i = 0; i < opp_cnt; ++i) {
+                       mpc->funcs->set_out_rate_control(
+                                       mpc, opp_inst[i],
+                                       false,
+                                       0,
+                                       NULL);
+               }
+       }
+
        for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
                odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
                                odm_pipe->stream_res.opp,
index e599cdc465bfd2a1936f447696482930d6296846..d5f76cc69c73609e2cba52f1f50362673c374fca 100644 (file)
@@ -426,6 +426,8 @@ void dcn35_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
        int opp_inst[MAX_PIPES] = {0};
        int odm_slice_width = resource_get_odm_slice_dst_width(pipe_ctx, false);
        int last_odm_slice_width = resource_get_odm_slice_dst_width(pipe_ctx, true);
+       struct mpc *mpc = dc->res_pool->mpc;
+       int i;
 
        opp_cnt = get_odm_config(pipe_ctx, opp_inst);
 
@@ -438,6 +440,16 @@ void dcn35_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
                pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
                                pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
 
+       if (mpc->funcs->set_out_rate_control) {
+               for (i = 0; i < opp_cnt; ++i) {
+                       mpc->funcs->set_out_rate_control(
+                                       mpc, opp_inst[i],
+                                       false,
+                                       0,
+                                       NULL);
+               }
+       }
+
        for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
                odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
                                odm_pipe->stream_res.opp,
index fe26fde12eeb3c407a7ae75458c815f48c61d588..85298b8a1b5efa1abfdcdec2f66afbb35c1d7532 100644 (file)
@@ -110,6 +110,23 @@ void mpc3_disable_dwb_mux(
                MPC_DWB0_MUX, 0xf);
 }
 
+void mpc3_set_out_rate_control(
+       struct mpc *mpc,
+       int opp_id,
+       bool enable,
+       bool rate_2x_mode,
+       struct mpc_dwb_flow_control *flow_control)
+{
+       struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
+
+       /* Always disable mpc out rate and flow control.
+        * MPC flow rate control is not needed for DCN30 and above.
+        */
+       REG_UPDATE_2(MUX[opp_id],
+                       MPC_OUT_RATE_CONTROL_DISABLE, 1,
+                       MPC_OUT_RATE_CONTROL, 0);
+}
+
 enum dc_lut_mode mpc3_get_ogam_current(struct mpc *mpc, int mpcc_id)
 {
        /*Contrary to DCN2 and DCN1 wherein a single status register field holds this info;
@@ -1519,6 +1536,7 @@ static const struct mpc_funcs dcn30_mpc_funcs = {
        .set_dwb_mux = mpc3_set_dwb_mux,
        .disable_dwb_mux = mpc3_disable_dwb_mux,
        .is_dwb_idle = mpc3_is_dwb_idle,
+       .set_out_rate_control = mpc3_set_out_rate_control,
        .set_gamut_remap = mpc3_set_gamut_remap,
        .program_shaper = mpc3_program_shaper,
        .acquire_rmu = mpcc3_acquire_rmu,
index ce93003dae011325efa0e1e3e5351646a5406017..103f29900a2c70380e8744ccc67758956b533687 100644 (file)
@@ -1085,6 +1085,13 @@ bool mpc3_is_dwb_idle(
        struct mpc *mpc,
        int dwb_id);
 
+void mpc3_set_out_rate_control(
+       struct mpc *mpc,
+       int opp_id,
+       bool enable,
+       bool rate_2x_mode,
+       struct mpc_dwb_flow_control *flow_control);
+
 void mpc3_power_on_ogam_lut(
        struct mpc *mpc, int mpcc_id,
        bool power_on);