drm/amd/display: fix cursor related Pstate hang
authorEric Yang <Eric.Yang2@amd.com>
Fri, 19 Jan 2018 00:07:54 +0000 (19:07 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 19 Feb 2018 19:19:28 +0000 (14:19 -0500)
Move cursor programming to inside the OTG_MASTER_UPDATE_LOCK

If graphics plane go from 1 pipe to hsplit, the cursor updates
after mpc programming and unlock. Which means there is a window
of time where cursor is enabled on the wrong pipe if it's on
the right side of the screen (i.e. case where cursor need to
move from pipe 0 to pipe 3 post split). This will cause pstate hang.

Solution is to program the cursor while still locked.

Signed-off-by: Eric Yang <Eric.Yang2@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h

index c3b198836d1d62c07070038591cabd88dba63722..87a193ac2883791fad68aaa3e6a7c115784e32b5 100644 (file)
@@ -193,6 +193,7 @@ bool dc_stream_set_cursor_attributes(
 
        core_dc = stream->ctx->dc;
        res_ctx = &core_dc->current_state->res_ctx;
+       stream->cursor_attributes = *attributes;
 
        for (i = 0; i < MAX_PIPES; i++) {
                struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
@@ -203,34 +204,8 @@ bool dc_stream_set_cursor_attributes(
                        continue;
 
 
-               if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes != NULL)
-                       pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
-                                               pipe_ctx->plane_res.ipp, attributes);
-
-               if (pipe_ctx->plane_res.hubp != NULL &&
-                               pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes != NULL)
-                       pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
-                                       pipe_ctx->plane_res.hubp, attributes);
-
-               if (pipe_ctx->plane_res.mi != NULL &&
-                               pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL)
-                       pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
-                                       pipe_ctx->plane_res.mi, attributes);
-
-
-               if (pipe_ctx->plane_res.xfm != NULL &&
-                               pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL)
-                       pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
-                               pipe_ctx->plane_res.xfm, attributes);
-
-               if (pipe_ctx->plane_res.dpp != NULL &&
-                               pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes != NULL)
-                       pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
-                               pipe_ctx->plane_res.dpp, attributes->color_format);
+               core_dc->hwss.set_cursor_attribute(pipe_ctx);
        }
-
-       stream->cursor_attributes = *attributes;
-
        return true;
 }
 
@@ -254,21 +229,10 @@ bool dc_stream_set_cursor_position(
 
        core_dc = stream->ctx->dc;
        res_ctx = &core_dc->current_state->res_ctx;
+       stream->cursor_position = *position;
 
        for (i = 0; i < MAX_PIPES; i++) {
                struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
-               struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
-               struct mem_input *mi = pipe_ctx->plane_res.mi;
-               struct hubp *hubp = pipe_ctx->plane_res.hubp;
-               struct dpp *dpp = pipe_ctx->plane_res.dpp;
-               struct dc_cursor_position pos_cpy = *position;
-               struct dc_cursor_mi_param param = {
-                       .pixel_clk_khz = stream->timing.pix_clk_khz,
-                       .ref_clk_khz = core_dc->res_pool->ref_clock_inKhz,
-                       .viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x,
-                       .viewport_width = pipe_ctx->plane_res.scl_data.viewport.width,
-                       .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz
-               };
 
                if (pipe_ctx->stream != stream ||
                                (!pipe_ctx->plane_res.mi  && !pipe_ctx->plane_res.hubp) ||
@@ -276,33 +240,9 @@ bool dc_stream_set_cursor_position(
                                (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp))
                        continue;
 
-               if (pipe_ctx->plane_state->address.type
-                               == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
-                       pos_cpy.enable = false;
-
-               if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
-                       pos_cpy.enable = false;
-
-
-               if (ipp != NULL && ipp->funcs->ipp_cursor_set_position != NULL)
-                       ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, &param);
-
-               if (mi != NULL && mi->funcs->set_cursor_position != NULL)
-                       mi->funcs->set_cursor_position(mi, &pos_cpy, &param);
-
-               if (!hubp)
-                       continue;
-
-               if (hubp->funcs->set_cursor_position != NULL)
-                       hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
-
-               if (dpp != NULL && dpp->funcs->set_cursor_position != NULL)
-                       dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width);
-
+               core_dc->hwss.set_cursor_position(pipe_ctx);
        }
 
-       stream->cursor_position = *position;
-
        return true;
 }
 
index fbb84a7ccaf5081b2d58ed36c2876d185f4b1594..914d39eceec74e0123570c91499076e2c273ce03 100644 (file)
@@ -2908,6 +2908,44 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx,
        }
 }
 
+void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx)
+{
+       struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
+       struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
+       struct mem_input *mi = pipe_ctx->plane_res.mi;
+       struct dc_cursor_mi_param param = {
+               .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz,
+               .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz,
+               .viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x,
+               .viewport_width = pipe_ctx->plane_res.scl_data.viewport.width,
+               .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz
+       };
+
+       if (pipe_ctx->plane_state->address.type
+                       == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
+               pos_cpy.enable = false;
+
+       if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
+               pos_cpy.enable = false;
+
+       ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, &param);
+       mi->funcs->set_cursor_position(mi, &pos_cpy, &param);
+}
+
+void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
+{
+       struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
+
+       pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
+                               pipe_ctx->plane_res.ipp, attributes);
+
+       pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
+                       pipe_ctx->plane_res.mi, attributes);
+
+       pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
+               pipe_ctx->plane_res.xfm, attributes);
+}
+
 static void ready_shared_resources(struct dc *dc, struct dc_state *context) {}
 
 static void optimize_shared_resources(struct dc *dc) {}
@@ -2951,6 +2989,8 @@ static const struct hw_sequencer_funcs dce110_funcs = {
        .edp_backlight_control = hwss_edp_backlight_control,
        .edp_power_control = hwss_edp_power_control,
        .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
+       .set_cursor_position = dce110_set_cursor_position,
+       .set_cursor_attribute = dce110_set_cursor_attribute
 };
 
 void dce110_hw_sequencer_construct(struct dc *dc)
index e6f822761b37e8658d9d86f9aa262d3c1ec78eb7..a17b0b7859fb2d1c0242c416af89ff0f2ff6ec50 100644 (file)
@@ -1716,6 +1716,11 @@ static void update_dchubp_dpp(
                        &pipe_ctx->plane_res.scl_data.viewport_c);
        }
 
+       if (pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
+               dc->hwss.set_cursor_position(pipe_ctx);
+               dc->hwss.set_cursor_attribute(pipe_ctx);
+       }
+
        if (plane_state->update_flags.bits.full_update) {
                /*gamut remap*/
                program_gamut_remap(pipe_ctx);
@@ -2265,7 +2270,7 @@ static bool dcn10_dummy_display_power_gating(
        return true;
 }
 
-void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)
+static void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)
 {
        struct dc_plane_state *plane_state = pipe_ctx->plane_state;
        struct timing_generator *tg = pipe_ctx->stream_res.tg;
@@ -2285,12 +2290,46 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)
        }
 }
 
-void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)
+static void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)
 {
        if (hws->ctx->dc->res_pool->hubbub != NULL)
                hubbub1_update_dchub(hws->ctx->dc->res_pool->hubbub, dh_data);
 }
 
+static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
+{
+       struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
+       struct hubp *hubp = pipe_ctx->plane_res.hubp;
+       struct dpp *dpp = pipe_ctx->plane_res.dpp;
+       struct dc_cursor_mi_param param = {
+               .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz,
+               .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz,
+               .viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x,
+               .viewport_width = pipe_ctx->plane_res.scl_data.viewport.width,
+               .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz
+       };
+
+       if (pipe_ctx->plane_state->address.type
+                       == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
+               pos_cpy.enable = false;
+
+       if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
+               pos_cpy.enable = false;
+
+       hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
+       dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width);
+}
+
+static void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
+{
+       struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
+
+       pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
+                       pipe_ctx->plane_res.hubp, attributes);
+       pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
+               pipe_ctx->plane_res.dpp, attributes->color_format);
+}
+
 static const struct hw_sequencer_funcs dcn10_funcs = {
        .program_gamut_remap = program_gamut_remap,
        .program_csc_matrix = program_csc_matrix,
@@ -2332,6 +2371,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
        .edp_backlight_control = hwss_edp_backlight_control,
        .edp_power_control = hwss_edp_power_control,
        .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
+       .set_cursor_position = dcn10_set_cursor_position,
+       .set_cursor_attribute = dcn10_set_cursor_attribute
 };
 
 
index 5e9a59351a00e088f9c830a28472fac2c5ef4fff..ad956ae2c6807c18023324082acc85803ab51af2 100644 (file)
@@ -199,6 +199,9 @@ struct hw_sequencer_funcs {
                        bool enable);
        void (*edp_wait_for_hpd_ready)(struct dc_link *link, bool power_up);
 
+       void (*set_cursor_position)(struct pipe_ctx *pipe);
+       void (*set_cursor_attribute)(struct pipe_ctx *pipe);
+
 };
 
 void color_space_to_black_color(