From: Alvin Lee <alvin.l...@amd.com>

[Description]
*  Pass in pipe index for FPO cmd to DMCUB
- This change will pass in the pipe index for each stream
  that is using FPO
- This change is in preparation to enable FPO + VActive

*  Use per pipe P-State force for FPO
- For FPO, instead of using max watermarks value for P-State disallow,
  use per pipe p-state force instead
- This is in preparation to enable FPO + VActive

Reviewed-by: Jun Lei <jun....@amd.com>
Acked-by: Qingqing Zhuo <qingqing.z...@amd.com>
Signed-off-by: Alvin Lee <alvin.l...@amd.com>
---
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c  | 46 +++++++++++--------
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |  1 +
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c    | 10 ++++
 .../drm/amd/display/dc/dcn30/dcn30_resource.c |  2 +
 .../gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c | 10 ++++
 .../gpu/drm/amd/display/dc/dcn32/dcn32_hubp.h |  2 +
 .../drm/amd/display/dc/dcn32/dcn32_hwseq.c    | 41 ++++++++++-------
 .../drm/amd/display/dc/dcn32/dcn32_hwseq.h    |  2 +-
 .../gpu/drm/amd/display/dc/dcn32/dcn32_init.c |  2 +-
 .../drm/amd/display/dc/dml/dcn30/dcn30_fpu.c  |  4 ++
 .../drm/amd/display/dc/dml/dcn32/dcn32_fpu.c  |  8 ++--
 drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h  |  1 +
 .../amd/display/dc/inc/hw_sequencer_private.h |  2 +-
 13 files changed, 88 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c 
b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
index b5c6501c28fc..8f26f7245104 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -302,27 +302,31 @@ static uint8_t dc_dmub_srv_get_pipes_for_stream(struct dc 
*dc, struct dc_stream_
        return pipes;
 }
 
-static int dc_dmub_srv_get_timing_generator_offset(struct dc *dc, struct 
dc_stream_state *stream)
+static void dc_dmub_srv_populate_fams_pipe_info(struct dc *dc, struct dc_state 
*context,
+               struct pipe_ctx *head_pipe,
+               struct dmub_cmd_fw_assisted_mclk_switch_pipe_data 
*fams_pipe_data)
 {
-       int  tg_inst = 0;
-       int i = 0;
+       int j;
 
-       for (i = 0; i < MAX_PIPES; i++) {
-               struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+       // TODO: Uncomment once FW headers are updated in driver
+       //fams_pipe_data->pipe_index[pipe_idx++] = 
head_pipe->plane_res.hubp->inst;
+       for (j = 0; j < dc->res_pool->pipe_count; j++) {
+               struct pipe_ctx *split_pipe = &context->res_ctx.pipe_ctx[j];
 
-               if (pipe->stream == stream && pipe->stream_res.tg) {
-                       tg_inst = pipe->stream_res.tg->inst;
-                       break;
+               if (split_pipe->stream == head_pipe->stream && 
(split_pipe->top_pipe || split_pipe->prev_odm_pipe)) {
+                       // TODO: Uncomment once FW headers are updated in driver
+                       //fams_pipe_data->pipe_index[pipe_idx++] = 
split_pipe->plane_res.hubp->inst;
                }
        }
-       return tg_inst;
+       // TODO: Uncomment once FW headers are updated in driver
+       //fams_pipe_data->pipe_count = pipe_idx;
 }
 
 bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, 
struct dc_state *context)
 {
        union dmub_rb_cmd cmd = { 0 };
        struct dmub_cmd_fw_assisted_mclk_switch_config *config_data = 
&cmd.fw_assisted_mclk_switch.config_data;
-       int i = 0;
+       int i = 0, k = 0;
        int ramp_up_num_steps = 1; // TODO: Ramp is currently disabled. 
Reenable it.
        uint8_t visual_confirm_enabled;
 
@@ -337,17 +341,21 @@ bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool 
should_manage_pstate, stru
        cmd.fw_assisted_mclk_switch.config_data.fams_enabled = 
should_manage_pstate;
        cmd.fw_assisted_mclk_switch.config_data.visual_confirm_enabled = 
visual_confirm_enabled;
 
-       for (i = 0; context && i < context->stream_count; i++) {
-               struct dc_stream_state *stream = context->streams[i];
-               uint8_t min_refresh_in_hz = (stream->timing.min_refresh_in_uhz 
+ 999999) / 1000000;
-               int  tg_inst = dc_dmub_srv_get_timing_generator_offset(dc, 
stream);
+       for (i = 0, k = 0; context && i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
 
-               config_data->pipe_data[tg_inst].pix_clk_100hz = 
stream->timing.pix_clk_100hz;
-               config_data->pipe_data[tg_inst].min_refresh_in_hz = 
min_refresh_in_hz;
-               config_data->pipe_data[tg_inst].max_ramp_step = 
ramp_up_num_steps;
-               config_data->pipe_data[tg_inst].pipes = 
dc_dmub_srv_get_pipes_for_stream(dc, stream);
+               if (!pipe->top_pipe && !pipe->prev_odm_pipe && pipe->stream && 
pipe->stream->fpo_in_use) {
+                       struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+                       uint8_t min_refresh_in_hz = 
(pipe->stream->timing.min_refresh_in_uhz + 999999) / 1000000;
+
+                       config_data->pipe_data[k].pix_clk_100hz = 
pipe->stream->timing.pix_clk_100hz;
+                       config_data->pipe_data[k].min_refresh_in_hz = 
min_refresh_in_hz;
+                       config_data->pipe_data[k].max_ramp_step = 
ramp_up_num_steps;
+                       config_data->pipe_data[k].pipes = 
dc_dmub_srv_get_pipes_for_stream(dc, pipe->stream);
+                       dc_dmub_srv_populate_fams_pipe_info(dc, context, pipe, 
&config_data->pipe_data[k]);
+                       k++;
+               }
        }
-
        cmd.fw_assisted_mclk_switch.header.payload_bytes =
                sizeof(cmd.fw_assisted_mclk_switch) - 
sizeof(cmd.fw_assisted_mclk_switch.header);
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h 
b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 567452599659..181a3408cc61 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -293,6 +293,7 @@ struct dc_stream_state {
 
        bool has_non_synchronizable_pclk;
        bool vblank_synchronized;
+       bool fpo_in_use;
        struct mall_stream_config mall_stream_config;
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index 9ca162ea0d07..5403e9399a46 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -1993,6 +1993,16 @@ void dcn20_post_unlock_program_front_end(
                }
        }
 
+       /* P-State support transitions:
+        * Natural -> FPO:              P-State disabled in prepare, force 
disallow anytime is safe
+        * FPO -> Natural:              Unforce anytime after FW disable is 
safe (P-State will assert naturally)
+        * Unsupported -> FPO:  P-State enabled in optimize, force disallow 
anytime is safe
+        * FPO -> Unsupported:  P-State disabled in prepare, unforce disallow 
anytime is safe
+        * FPO <-> SubVP:               Force disallow is maintained on the FPO 
/ SubVP pipes
+        */
+       if (hwseq && hwseq->funcs.update_force_pstate)
+               dc->hwseq->funcs.update_force_pstate(dc, context);
+
        /* Only program the MALL registers after all the main and phantom pipes
         * are done programming.
         */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
index c9e45da6ccd1..965f5ceb33f7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
@@ -2016,6 +2016,8 @@ bool 
dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc,
        if (context->streams[0]->vrr_active_variable)
                return false;
 
+       context->streams[0]->fpo_in_use = true;
+
        return true;
 }
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c 
b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c
index fe0cd177744c..2d604f7ee782 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c
@@ -47,6 +47,15 @@ void hubp32_update_force_pstate_disallow(struct hubp *hubp, 
bool pstate_disallow
                        DATA_UCLK_PSTATE_FORCE_VALUE, 0);
 }
 
+void hubp32_update_force_cursor_pstate_disallow(struct hubp *hubp, bool 
pstate_disallow)
+{
+       struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+       REG_UPDATE_2(UCLK_PSTATE_FORCE,
+                       CURSOR_UCLK_PSTATE_FORCE_EN, pstate_disallow,
+                       CURSOR_UCLK_PSTATE_FORCE_VALUE, 0);
+}
+
 void hubp32_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool 
c_cursor)
 {
        struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
@@ -188,6 +197,7 @@ static struct hubp_funcs dcn32_hubp_funcs = {
        .hubp_set_flip_int = hubp1_set_flip_int,
        .hubp_in_blank = hubp1_in_blank,
        .hubp_update_force_pstate_disallow = 
hubp32_update_force_pstate_disallow,
+       .hubp_update_force_cursor_pstate_disallow = 
hubp32_update_force_cursor_pstate_disallow,
        .phantom_hubp_post_enable = hubp32_phantom_hubp_post_enable,
        .hubp_update_mall_sel = hubp32_update_mall_sel,
        .hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.h 
b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.h
index d5e5ed8ab869..d2acbc129609 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.h
@@ -46,6 +46,8 @@
 
 void hubp32_update_force_pstate_disallow(struct hubp *hubp, bool 
pstate_disallow);
 
+void hubp32_update_force_cursor_pstate_disallow(struct hubp *hubp, bool 
pstate_disallow);
+
 void hubp32_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool 
c_cursor);
 
 void hubp32_prepare_subvp_buffering(struct hubp *hubp, bool enable);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
index 42255c22605d..5ee9c5a74ecb 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
@@ -571,39 +571,50 @@ bool dcn32_set_output_transfer_func(struct dc *dc,
        return ret;
 }
 
-/* Program P-State force value according to if pipe is using SubVP or not:
+/* Program P-State force value according to if pipe is using SubVP / FPO or 
not:
  * 1. Reset P-State force on all pipes first
  * 2. For each main pipe, force P-State disallow (P-State allow moderated by 
DMUB)
  */
-void dcn32_subvp_update_force_pstate(struct dc *dc, struct dc_state *context)
+void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context)
 {
        int i;
-       int num_subvp = 0;
-       /* Unforce p-state for each pipe
+
+       /* Unforce p-state for each pipe if it is not FPO or SubVP.
+        * For FPO and SubVP, if it's already forced disallow, leave
+        * it as disallow.
         */
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
                struct hubp *hubp = pipe->plane_res.hubp;
 
-               if (hubp && hubp->funcs->hubp_update_force_pstate_disallow)
-                       hubp->funcs->hubp_update_force_pstate_disallow(hubp, 
false);
-               if (pipe->stream && pipe->stream->mall_stream_config.type == 
SUBVP_MAIN)
-                       num_subvp++;
+               if (!pipe->stream || (pipe->stream && 
!(pipe->stream->mall_stream_config.type == SUBVP_MAIN ||
+                                               pipe->stream->fpo_in_use))) {
+                       if (hubp && 
hubp->funcs->hubp_update_force_pstate_disallow)
+                               
hubp->funcs->hubp_update_force_pstate_disallow(hubp, false);
+                       if (hubp && 
hubp->funcs->hubp_update_force_cursor_pstate_disallow)
+                               
hubp->funcs->hubp_update_force_cursor_pstate_disallow(hubp, false);
+               }
        }
 
-       if (num_subvp == 0)
-               return;
-
        /* Loop through each pipe -- for each subvp main pipe force p-state 
allow equal to false.
         */
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+               struct hubp *hubp = pipe->plane_res.hubp;
 
-               if (pipe->stream && pipe->plane_state && 
(pipe->stream->mall_stream_config.type == SUBVP_MAIN)) {
-                       struct hubp *hubp = pipe->plane_res.hubp;
+               if (pipe->stream && pipe->plane_state && 
pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
+                       if (hubp && 
hubp->funcs->hubp_update_force_pstate_disallow)
+                               
hubp->funcs->hubp_update_force_pstate_disallow(hubp, true);
+               }
 
+               if (pipe->stream && pipe->stream->fpo_in_use) {
                        if (hubp && 
hubp->funcs->hubp_update_force_pstate_disallow)
                                
hubp->funcs->hubp_update_force_pstate_disallow(hubp, true);
+                       /* For now only force cursor p-state disallow for FPO
+                        * Needs to be added for subvp once FW side gets updated
+                        */
+                       if (hubp && 
hubp->funcs->hubp_update_force_cursor_pstate_disallow)
+                               
hubp->funcs->hubp_update_force_cursor_pstate_disallow(hubp, true);
                }
        }
 }
@@ -677,10 +688,6 @@ void dcn32_program_mall_pipe_config(struct dc *dc, struct 
dc_state *context)
        if (hws && hws->funcs.update_mall_sel)
                hws->funcs.update_mall_sel(dc, context);
 
-       //update subvp force pstate
-       if (hws && hws->funcs.subvp_update_force_pstate)
-               dc->hwseq->funcs.subvp_update_force_pstate(dc, context);
-
        // Program FORCE_ONE_ROW_FOR_FRAME and CURSOR_REQ_MODE for main subvp 
pipes
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h 
b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h
index 2a5376eb9d66..6694c1d14aa3 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h
@@ -67,7 +67,7 @@ void dcn32_program_mall_pipe_config(struct dc *dc, struct 
dc_state *context);
 
 void dcn32_update_mall_sel(struct dc *dc, struct dc_state *context);
 
-void dcn32_subvp_update_force_pstate(struct dc *dc, struct dc_state *context);
+void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context);
 
 void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx 
*pipe_ctx);
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c 
b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
index dcb81662884f..8085f2acb1a9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
@@ -149,7 +149,7 @@ static const struct hwseq_private_funcs dcn32_private_funcs 
= {
        .dccg_init = dcn20_dccg_init,
        .set_mcm_luts = dcn32_set_mcm_luts,
        .program_mall_pipe_config = dcn32_program_mall_pipe_config,
-       .subvp_update_force_pstate = dcn32_subvp_update_force_pstate,
+       .update_force_pstate = dcn32_update_force_pstate,
        .update_mall_sel = dcn32_update_mall_sel,
        .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
        .set_pixels_per_cycle = dcn32_set_pixels_per_cycle,
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
index ecfa395f5fa8..80972ee5e55b 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
@@ -389,6 +389,10 @@ void dcn30_fpu_calculate_wm_and_dlg(
        dc_assert_fp_enabled();
 
        context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false;
+    for (i = 0; i < context->stream_count; i++) {
+               if (context->streams[i])
+                       context->streams[i]->fpo_in_use = false;
+       }
 
        if (!pstate_en) {
                /* only when the mclk switch can not be natural, is the fw 
based vblank stretch attempted */
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
index 6ab60facc091..1e26adf987cc 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
@@ -1960,6 +1960,10 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, 
struct dc_state *context,
        }
 
        context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false;
+       for (i = 0; i < context->stream_count; i++) {
+               if (context->streams[i])
+                       context->streams[i]->fpo_in_use = false;
+       }
 
        if (!pstate_en || (!dc->debug.disable_fpo_optimizations &&
                        pstate_en && vlevel != 0)) {
@@ -2199,10 +2203,6 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, 
struct dc_state *context,
                context->bw_ctx.dml.soc.dram_clock_change_latency_us =
                                
dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us;
 
-       if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
-               dcn30_setup_mclk_switch_using_fw_based_vblank_stretch(dc, 
context);
-       }
-
        /* revert fclk lat changes if required */
        if (need_fclk_lat_as_dummy)
                context->bw_ctx.dml.soc.fclk_change_latency_us =
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
index b5d353c41aa9..ccf8861483a0 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
@@ -203,6 +203,7 @@ struct hubp_funcs {
        void (*hubp_soft_reset)(struct hubp *hubp, bool reset);
 
        void (*hubp_update_force_pstate_disallow)(struct hubp *hubp, bool 
allow);
+       void (*hubp_update_force_cursor_pstate_disallow)(struct hubp *hubp, 
bool allow);        
        void (*hubp_update_mall_sel)(struct hubp *hubp, uint32_t mall_sel, bool 
c_cursor);
        void (*hubp_prepare_subvp_buffering)(struct hubp *hubp, bool enable);
 
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
index 5f63b67975cf..4513544559be 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
@@ -154,7 +154,7 @@ struct hwseq_private_funcs {
        void (*setup_hpo_hw_control)(const struct dce_hwseq *hws, bool enable);
 #ifdef CONFIG_DRM_AMD_DC_FP
        void (*program_mall_pipe_config)(struct dc *dc, struct dc_state 
*context);
-       void (*subvp_update_force_pstate)(struct dc *dc, struct dc_state 
*context);
+       void (*update_force_pstate)(struct dc *dc, struct dc_state *context);
        void (*update_mall_sel)(struct dc *dc, struct dc_state *context);
        unsigned int (*calculate_dccg_k1_k2_values)(struct pipe_ctx *pipe_ctx,
                        unsigned int *k1_div,
-- 
2.34.1

Reply via email to