drm/amd/display: set blank functionality
authorHersen Wu <hersenxs.wu@amd.com>
Fri, 6 Jan 2017 21:23:18 +0000 (16:23 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 26 Sep 2017 21:09:13 +0000 (17:09 -0400)
1. remove the sleep mechanism while set_blank true from
the timing generator.
Since Hw sequencer is the one that manages the flow
he will be responsible for wait for blanck in a critical places.

Signed-off-by: Leon Elazar <leon.elazar@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_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h

index d5cffa5..9f462a2 100644 (file)
@@ -91,3 +91,23 @@ void color_space_to_black_color(
                break;
        }
 }
+
+bool hwss_wait_for_blank_complete(
+               struct timing_generator *tg)
+{
+       int counter;
+
+       for (counter = 0; counter < 100; counter++) {
+               if (tg->funcs->is_blanked(tg))
+                       break;
+
+               msleep(1);
+       }
+
+       if (counter == 100) {
+               dm_error("DC: failed to blank crtc!\n");
+               return false;
+       }
+
+       return true;
+}
index 7c27a82..965e47a 100644 (file)
@@ -623,7 +623,7 @@ static void program_scaler(const struct core_dc *dc,
                &pipe_ctx->scl_data);
 }
 
-static enum dc_status prog_pixclk_crtc_otg(
+static enum dc_status dce110_prog_pixclk_crtc_otg(
                struct pipe_ctx *pipe_ctx,
                struct validate_context *context,
                struct core_dc *dc)
@@ -641,6 +641,7 @@ static enum dc_status prog_pixclk_crtc_otg(
                pipe_ctx->tg->funcs->set_blank_color(
                                pipe_ctx->tg,
                                &black_color);
+
                /*
                 * Must blank CRTC after disabling power gating and before any
                 * programming, otherwise CRTC will be hung in bad state
@@ -1047,7 +1048,8 @@ static void reset_single_pipe_hw_ctx(
                struct validate_context *context)
 {
        core_link_disable_stream(pipe_ctx);
-       if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) {
+       pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
+       if (!hwss_wait_for_blank_complete(pipe_ctx->tg)) {
                dm_error("DC: failed to blank crtc!\n");
                BREAK_TO_DEBUGGER();
        }
@@ -1560,9 +1562,6 @@ static void update_plane_addr(const struct core_dc *dc,
                        surface->public.flip_immediate);
 
        surface->status.requested_address = surface->public.address;
-
-       if (surface->public.visible)
-               pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, false);
 }
 
 void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
@@ -1718,6 +1717,7 @@ static void init_hw(struct core_dc *dc)
                /* Blank controller using driver code instead of
                 * command table. */
                tg->funcs->set_blank(tg, true);
+               hwss_wait_for_blank_complete(tg);
        }
 
        for (i = 0; i < dc->res_pool->audio_count; i++) {
@@ -2002,7 +2002,7 @@ static const struct hw_sequencer_funcs dce110_funcs = {
        .set_drr = set_drr,
        .set_static_screen_control = set_static_screen_control,
        .reset_hw_ctx_wrap = reset_hw_ctx_wrap,
-       .prog_pixclk_crtc_otg = prog_pixclk_crtc_otg,
+       .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg,
 };
 
 bool dce110_hw_sequencer_construct(struct core_dc *dc)
index e70704d..f4b8576 100644 (file)
@@ -1808,7 +1808,7 @@ bool dce110_tg_is_blanked(struct timing_generator *tg)
        return false;
 }
 
-bool dce110_tg_set_blank(struct timing_generator *tg,
+void dce110_tg_set_blank(struct timing_generator *tg,
                bool enable_blanking)
 {
        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
@@ -1824,8 +1824,6 @@ bool dce110_tg_set_blank(struct timing_generator *tg,
        value = 0;
 
        if (enable_blanking) {
-               int counter;
-
                set_reg_field_value(
                        value,
                        1,
@@ -1834,32 +1832,8 @@ bool dce110_tg_set_blank(struct timing_generator *tg,
 
                dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value);
 
-               for (counter = 0; counter < 100; counter++) {
-                       value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL));
-
-                       if (get_reg_field_value(
-                               value,
-                               CRTC_BLANK_CONTROL,
-                               CRTC_BLANK_DATA_EN) == 1 &&
-                               get_reg_field_value(
-                               value,
-                               CRTC_BLANK_CONTROL,
-                               CRTC_CURRENT_BLANK_STATE) == 1)
-                               break;
-
-                       msleep(1);
-               }
-
-               if (counter == 100) {
-                       dm_logger_write(tg->ctx->logger, LOG_ERROR,
-                                       "timing generator %d blank timing out.\n",
-                                       tg110->controller_id);
-                       return false;
-               }
        } else
                dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0);
-
-       return true;
 }
 
 bool dce110_tg_validate_timing(struct timing_generator *tg,
index 3990650..dcb49fe 100644 (file)
@@ -257,7 +257,7 @@ void dce110_tg_program_timing(struct timing_generator *tg,
 
 bool dce110_tg_is_blanked(struct timing_generator *tg);
 
-bool dce110_tg_set_blank(struct timing_generator *tg,
+void dce110_tg_set_blank(struct timing_generator *tg,
                bool enable_blanking);
 
 bool dce110_tg_validate_timing(struct timing_generator *tg,
index 3bf3179..682a3de 100644 (file)
@@ -72,12 +72,11 @@ static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg)
        return true;
 }
 
-static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg)
+static void dce110_timing_generator_v_blank_crtc(struct timing_generator *tg)
 {
        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
        uint32_t addr = mmCRTCV_BLANK_CONTROL;
        uint32_t value = dm_read_reg(tg->ctx, addr);
-       uint8_t counter = 100;
 
        set_reg_field_value(
                value,
@@ -92,35 +91,9 @@ static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg)
                CRTC_BLANK_DE_MODE);
 
        dm_write_reg(tg->ctx, addr, value);
-
-       while (counter > 0) {
-               value = dm_read_reg(tg->ctx, addr);
-
-               if (get_reg_field_value(
-                       value,
-                       CRTCV_BLANK_CONTROL,
-                       CRTC_BLANK_DATA_EN) == 1 &&
-                       get_reg_field_value(
-                       value,
-                       CRTCV_BLANK_CONTROL,
-                       CRTC_CURRENT_BLANK_STATE) == 1)
-                       break;
-
-               msleep(1);
-               counter--;
-       }
-
-       if (!counter) {
-               dm_logger_write(tg->ctx->logger, LOG_ERROR,
-                               "timing generator %d blank timing out.\n",
-                               tg110->controller_id);
-               return false;
-       }
-
-       return true;
 }
 
-static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg)
+static void dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg)
 {
        uint32_t addr = mmCRTCV_BLANK_CONTROL;
        uint32_t value = dm_read_reg(tg->ctx, addr);
@@ -138,8 +111,6 @@ static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg)
                CRTC_BLANK_DE_MODE);
 
        dm_write_reg(tg->ctx, addr, value);
-
-       return true;
 }
 
 static bool dce110_timing_generator_v_is_in_vertical_blank(
@@ -429,13 +400,13 @@ static void dce110_timing_generator_v_enable_advanced_request(
        dm_write_reg(tg->ctx, addr, value);
 }
 
-static bool dce110_timing_generator_v_set_blank(struct timing_generator *tg,
+static void dce110_timing_generator_v_set_blank(struct timing_generator *tg,
                bool enable_blanking)
 {
        if (enable_blanking)
-               return dce110_timing_generator_v_blank_crtc(tg);
+               dce110_timing_generator_v_blank_crtc(tg);
        else
-               return dce110_timing_generator_v_unblank_crtc(tg);
+               dce110_timing_generator_v_unblank_crtc(tg);
 }
 
 static void dce110_timing_generator_v_program_timing(struct timing_generator *tg,
index 6ac609f..baa9445 100644 (file)
@@ -129,7 +129,7 @@ struct timing_generator_funcs {
                                                           uint32_t early_cntl);
        void (*wait_for_state)(struct timing_generator *tg,
                                                        enum crtc_state state);
-       bool (*set_blank)(struct timing_generator *tg,
+       void (*set_blank)(struct timing_generator *tg,
                                        bool enable_blanking);
        bool (*is_blanked)(struct timing_generator *tg);
        void (*set_overscan_blank_color) (struct timing_generator *tg, const struct tg_color *color);
index 895c446..562c897 100644 (file)
@@ -151,4 +151,7 @@ void color_space_to_black_color(
        enum dc_color_space colorspace,
        struct tg_color *black_color);
 
+bool hwss_wait_for_blank_complete(
+               struct timing_generator *tg);
+
 #endif /* __DC_HW_SEQUENCER_H__ */