From: George Shen <george.s...@amd.com>

[Why]
MPC flow rate control is not needed for DCN30 and above. Current logic
that uses it can result in underflow for certain edge cases (such as
DSC N422 + ODM combine + 422 left edge pixel).

[How]
Remove MPC flow rate control logic and programming for DCN30 and above.

Cc: Mario Limonciello <mario.limoncie...@amd.com>
Cc: Alex Deucher <alexander.deuc...@amd.com>
Cc: sta...@vger.kernel.org
Reviewed-by: Wenjing Liu <wenjing....@amd.com>
Acked-by: Tom Chung <chiahsuan.ch...@amd.com>
Signed-off-by: George Shen <george.s...@amd.com>
---
 .../gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c  | 54 +++++++++++--------
 .../gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h  | 14 ++---
 .../gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c  |  5 +-
 .../amd/display/dc/hwss/dcn314/dcn314_hwseq.c | 41 --------------
 .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c   | 41 --------------
 .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c   | 41 --------------
 6 files changed, 41 insertions(+), 155 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c 
b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
index bf3386cd444d..5ebb57303130 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
@@ -44,6 +44,36 @@
 #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
 
 
+void mpc3_mpc_init(struct mpc *mpc)
+{
+       struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
+       int opp_id;
+
+       mpc1_mpc_init(mpc);
+
+       for (opp_id = 0; opp_id < MAX_OPP; opp_id++) {
+               if (REG(MUX[opp_id]))
+                       /* disable mpc out rate and flow control */
+                       REG_UPDATE_2(MUX[opp_id], MPC_OUT_RATE_CONTROL_DISABLE,
+                                       1, MPC_OUT_FLOW_CONTROL_COUNT, 0);
+       }
+}
+
+void mpc3_mpc_init_single_inst(struct mpc *mpc, unsigned int mpcc_id)
+{
+       struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
+
+       mpc1_mpc_init_single_inst(mpc, mpcc_id);
+
+       /* assuming mpc out mux is connected to opp with the same index at this
+        * point in time (e.g. transitioning from vbios to driver)
+        */
+       if (mpcc_id < MAX_OPP && REG(MUX[mpcc_id]))
+               /* disable mpc out rate and flow control */
+               REG_UPDATE_2(MUX[mpcc_id], MPC_OUT_RATE_CONTROL_DISABLE,
+                               1, MPC_OUT_FLOW_CONTROL_COUNT, 0);
+}
+
 bool mpc3_is_dwb_idle(
        struct mpc *mpc,
        int dwb_id)
@@ -80,25 +110,6 @@ 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);
-
-       REG_UPDATE_2(MUX[opp_id],
-                       MPC_OUT_RATE_CONTROL_DISABLE, !enable,
-                       MPC_OUT_RATE_CONTROL, rate_2x_mode);
-
-       if (flow_control)
-               REG_UPDATE_2(MUX[opp_id],
-                       MPC_OUT_FLOW_CONTROL_MODE, flow_control->flow_ctrl_mode,
-                       MPC_OUT_FLOW_CONTROL_COUNT, 
flow_control->flow_ctrl_cnt1);
-}
-
 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;
@@ -1490,8 +1501,8 @@ static const struct mpc_funcs dcn30_mpc_funcs = {
        .read_mpcc_state = mpc3_read_mpcc_state,
        .insert_plane = mpc1_insert_plane,
        .remove_mpcc = mpc1_remove_mpcc,
-       .mpc_init = mpc1_mpc_init,
-       .mpc_init_single_inst = mpc1_mpc_init_single_inst,
+       .mpc_init = mpc3_mpc_init,
+       .mpc_init_single_inst = mpc3_mpc_init_single_inst,
        .update_blending = mpc2_update_blending,
        .cursor_lock = mpc1_cursor_lock,
        .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp,
@@ -1508,7 +1519,6 @@ 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,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h 
b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h
index 9cb96ae95a2f..ce93003dae01 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h
@@ -1007,6 +1007,13 @@ void dcn30_mpc_construct(struct dcn30_mpc *mpc30,
        int num_mpcc,
        int num_rmu);
 
+void mpc3_mpc_init(
+       struct mpc *mpc);
+
+void mpc3_mpc_init_single_inst(
+       struct mpc *mpc,
+       unsigned int mpcc_id);
+
 bool mpc3_program_shaper(
                struct mpc *mpc,
                const struct pwl_params *params,
@@ -1078,13 +1085,6 @@ 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);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c 
b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
index e789e654c387..e408e859b355 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
@@ -47,7 +47,7 @@ void mpc32_mpc_init(struct mpc *mpc)
        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
        int mpcc_id;
 
-       mpc1_mpc_init(mpc);
+       mpc3_mpc_init(mpc);
 
        if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
                if (mpc30->mpc_mask->MPCC_MCM_SHAPER_MEM_LOW_PWR_MODE && 
mpc30->mpc_mask->MPCC_MCM_3DLUT_MEM_LOW_PWR_MODE) {
@@ -991,7 +991,7 @@ static const struct mpc_funcs dcn32_mpc_funcs = {
        .insert_plane = mpc1_insert_plane,
        .remove_mpcc = mpc1_remove_mpcc,
        .mpc_init = mpc32_mpc_init,
-       .mpc_init_single_inst = mpc1_mpc_init_single_inst,
+       .mpc_init_single_inst = mpc3_mpc_init_single_inst,
        .update_blending = mpc2_update_blending,
        .cursor_lock = mpc1_cursor_lock,
        .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp,
@@ -1008,7 +1008,6 @@ static const struct mpc_funcs dcn32_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 = mpc32_program_shaper,
        .program_3dlut = mpc32_program_3dlut,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
index 3a9cc8ac0c07..093f4387553c 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
@@ -69,29 +69,6 @@
 #define FN(reg_name, field_name) \
        hws->shifts->field_name, hws->masks->field_name
 
-static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
-               int opp_cnt)
-{
-       bool hblank_halved = 
optc2_is_two_pixels_per_containter(&stream->timing);
-       int flow_ctrl_cnt;
-
-       if (opp_cnt >= 2)
-               hblank_halved = true;
-
-       flow_ctrl_cnt = stream->timing.h_total - stream->timing.h_addressable -
-                       stream->timing.h_border_left -
-                       stream->timing.h_border_right;
-
-       if (hblank_halved)
-               flow_ctrl_cnt /= 2;
-
-       /* ODM combine 4:1 case */
-       if (opp_cnt == 4)
-               flow_ctrl_cnt /= 2;
-
-       return flow_ctrl_cnt;
-}
-
 static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
 {
        struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
@@ -183,10 +160,6 @@ void dcn314_update_odm(struct dc *dc, struct dc_state 
*context, struct pipe_ctx
        struct pipe_ctx *odm_pipe;
        int opp_cnt = 0;
        int opp_inst[MAX_PIPES] = {0};
-       bool rate_control_2x_pclk = (pipe_ctx->stream->timing.flags.INTERLACE 
|| optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing));
-       struct mpc_dwb_flow_control flow_control;
-       struct mpc *mpc = dc->res_pool->mpc;
-       int i;
 
        opp_cnt = get_odm_config(pipe_ctx, opp_inst);
 
@@ -199,20 +172,6 @@ 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);
 
-       rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
-       flow_control.flow_ctrl_mode = 0;
-       flow_control.flow_ctrl_cnt0 = 0x80;
-       flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(pipe_ctx->stream, 
opp_cnt);
-       if (mpc->funcs->set_out_rate_control) {
-               for (i = 0; i < opp_cnt; ++i) {
-                       mpc->funcs->set_out_rate_control(
-                                       mpc, opp_inst[i],
-                                       true,
-                                       rate_control_2x_pclk,
-                                       &flow_control);
-               }
-       }
-
        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,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index 367dcaeaf186..62ff99463834 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -970,29 +970,6 @@ void dcn32_init_hw(struct dc *dc)
        }
 }
 
-static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
-               int opp_cnt)
-{
-       bool hblank_halved = 
optc2_is_two_pixels_per_containter(&stream->timing);
-       int flow_ctrl_cnt;
-
-       if (opp_cnt >= 2)
-               hblank_halved = true;
-
-       flow_ctrl_cnt = stream->timing.h_total - stream->timing.h_addressable -
-                       stream->timing.h_border_left -
-                       stream->timing.h_border_right;
-
-       if (hblank_halved)
-               flow_ctrl_cnt /= 2;
-
-       /* ODM combine 4:1 case */
-       if (opp_cnt == 4)
-               flow_ctrl_cnt /= 2;
-
-       return flow_ctrl_cnt;
-}
-
 static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
 {
        struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
@@ -1107,10 +1084,6 @@ void dcn32_update_odm(struct dc *dc, struct dc_state 
*context, struct pipe_ctx *
        struct pipe_ctx *odm_pipe;
        int opp_cnt = 0;
        int opp_inst[MAX_PIPES] = {0};
-       bool rate_control_2x_pclk = (pipe_ctx->stream->timing.flags.INTERLACE 
|| optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing));
-       struct mpc_dwb_flow_control flow_control;
-       struct mpc *mpc = dc->res_pool->mpc;
-       int i;
 
        opp_cnt = get_odm_config(pipe_ctx, opp_inst);
 
@@ -1123,20 +1096,6 @@ void dcn32_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);
 
-       rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
-       flow_control.flow_ctrl_mode = 0;
-       flow_control.flow_ctrl_cnt0 = 0x80;
-       flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(pipe_ctx->stream, 
opp_cnt);
-       if (mpc->funcs->set_out_rate_control) {
-               for (i = 0; i < opp_cnt; ++i) {
-                       mpc->funcs->set_out_rate_control(
-                                       mpc, opp_inst[i],
-                                       true,
-                                       rate_control_2x_pclk,
-                                       &flow_control);
-               }
-       }
-
        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,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index ad88edebcdfe..cdc53384cb51 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -358,29 +358,6 @@ void dcn35_init_hw(struct dc *dc)
        }
 }
 
-static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
-               int opp_cnt)
-{
-       bool hblank_halved = 
optc2_is_two_pixels_per_containter(&stream->timing);
-       int flow_ctrl_cnt;
-
-       if (opp_cnt >= 2)
-               hblank_halved = true;
-
-       flow_ctrl_cnt = stream->timing.h_total - stream->timing.h_addressable -
-                       stream->timing.h_border_left -
-                       stream->timing.h_border_right;
-
-       if (hblank_halved)
-               flow_ctrl_cnt /= 2;
-
-       /* ODM combine 4:1 case */
-       if (opp_cnt == 4)
-               flow_ctrl_cnt /= 2;
-
-       return flow_ctrl_cnt;
-}
-
 static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
 {
        struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
@@ -474,10 +451,6 @@ void dcn35_update_odm(struct dc *dc, struct dc_state 
*context, struct pipe_ctx *
        struct pipe_ctx *odm_pipe;
        int opp_cnt = 0;
        int opp_inst[MAX_PIPES] = {0};
-       bool rate_control_2x_pclk = (pipe_ctx->stream->timing.flags.INTERLACE 
|| optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing));
-       struct mpc_dwb_flow_control flow_control;
-       struct mpc *mpc = dc->res_pool->mpc;
-       int i;
 
        opp_cnt = get_odm_config(pipe_ctx, opp_inst);
 
@@ -490,20 +463,6 @@ 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);
 
-       rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
-       flow_control.flow_ctrl_mode = 0;
-       flow_control.flow_ctrl_cnt0 = 0x80;
-       flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(pipe_ctx->stream, 
opp_cnt);
-       if (mpc->funcs->set_out_rate_control) {
-               for (i = 0; i < opp_cnt; ++i) {
-                       mpc->funcs->set_out_rate_control(
-                                       mpc, opp_inst[i],
-                                       true,
-                                       rate_control_2x_pclk,
-                                       &flow_control);
-               }
-       }
-
        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,
-- 
2.34.1

Reply via email to