drm/amd/display: Fix GSL acquire
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / dcn20 / dcn20_hwseq.c
index 5b9cbed..9713f45 100644 (file)
@@ -572,7 +572,6 @@ void dcn20_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
        dpp->funcs->dpp_dppclk_control(dpp, false, false);
 
        hubp->power_gated = true;
-       dc->optimized_required = false; /* We're powering off, no need to optimize */
 
        hws->funcs.plane_atomic_power_down(dc,
                        pipe_ctx->plane_res.dpp,
@@ -686,9 +685,13 @@ enum dc_status dcn20_enable_stream_timing(
        // DRR should set trigger event to monitor surface update event
        if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
                event_triggers = 0x80;
+       /* Event triggers and num frames initialized for DRR, but can be
+        * later updated for PSR use. Note DRR trigger events are generated
+        * regardless of whether num frames met.
+        */
        if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control)
                pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
-                               pipe_ctx->stream_res.tg, event_triggers);
+                               pipe_ctx->stream_res.tg, event_triggers, 2);
 
        /* TODO program crtc source select for non-virtual signal*/
        /* TODO program FMT */
@@ -941,6 +944,9 @@ void dcn20_blank_pixel_data(
        int width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
        int height = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
 
+       if (stream->link->test_pattern_enabled)
+               return;
+
        /* get opp dpg blank color */
        color_space_to_black_color(dc, color_space, &black_color);
 
@@ -1082,40 +1088,18 @@ void dcn20_enable_plane(
 //     }
 }
 
-
-void dcn20_pipe_control_lock_global(
-               struct dc *dc,
-               struct pipe_ctx *pipe,
-               bool lock)
-{
-       if (lock) {
-               pipe->stream_res.tg->funcs->lock_doublebuffer_enable(
-                               pipe->stream_res.tg);
-               pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
-       } else {
-               pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
-               pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
-                               CRTC_STATE_VACTIVE);
-               pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
-                               CRTC_STATE_VBLANK);
-               pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
-                               CRTC_STATE_VACTIVE);
-               pipe->stream_res.tg->funcs->lock_doublebuffer_disable(
-                               pipe->stream_res.tg);
-       }
-}
-
 void dcn20_pipe_control_lock(
        struct dc *dc,
        struct pipe_ctx *pipe,
        bool lock)
 {
        bool flip_immediate = false;
+       bool dig_update_required = false;
 
        /* use TG master update lock to lock everything on the TG
         * therefore only top pipe need to lock
         */
-       if (pipe->top_pipe)
+       if (!pipe || pipe->top_pipe)
                return;
 
        if (pipe->plane_state != NULL)
@@ -1148,6 +1132,19 @@ void dcn20_pipe_control_lock(
                    (!flip_immediate && pipe->stream_res.gsl_group > 0))
                        dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate);
 
+       if (pipe->stream && pipe->stream->update_flags.bits.dsc_changed)
+               dig_update_required = true;
+
+       /* Need double buffer lock mode in order to synchronize front end pipe
+        * updates with dig updates.
+        */
+       if (dig_update_required) {
+               if (lock) {
+                       pipe->stream_res.tg->funcs->lock_doublebuffer_enable(
+                                       pipe->stream_res.tg);
+               }
+       }
+
        if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) {
                if (lock)
                        pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg);
@@ -1159,6 +1156,19 @@ void dcn20_pipe_control_lock(
                else
                        pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
        }
+
+       if (dig_update_required) {
+               if (!lock) {
+                       pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
+                                       CRTC_STATE_VACTIVE);
+                       pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
+                                       CRTC_STATE_VBLANK);
+                       pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
+                                       CRTC_STATE_VACTIVE);
+                       pipe->stream_res.tg->funcs->lock_doublebuffer_disable(
+                                       pipe->stream_res.tg);
+               }
+       }
 }
 
 static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx *new_pipe)
@@ -1530,48 +1540,32 @@ static void dcn20_program_pipe(
        }
 }
 
-static bool does_pipe_need_lock(struct pipe_ctx *pipe)
-{
-       if ((pipe->plane_state && pipe->plane_state->update_flags.raw)
-                       || pipe->update_flags.raw)
-               return true;
-       if (pipe->bottom_pipe)
-               return does_pipe_need_lock(pipe->bottom_pipe);
-
-       return false;
-}
-
 void dcn20_program_front_end_for_ctx(
                struct dc *dc,
                struct dc_state *context)
 {
-       const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100;
        int i;
        struct dce_hwseq *hws = dc->hwseq;
-       bool pipe_locked[MAX_PIPES] = {false};
        DC_LOGGER_INIT(dc->ctx->logger);
 
-       /* Carry over GSL groups in case the context is changing. */
-       for (i = 0; i < dc->res_pool->pipe_count; i++)
-               if (context->res_ctx.pipe_ctx[i].stream == dc->current_state->res_ctx.pipe_ctx[i].stream)
-                       context->res_ctx.pipe_ctx[i].stream_res.gsl_group =
-                               dc->current_state->res_ctx.pipe_ctx[i].stream_res.gsl_group;
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+               if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->plane_state) {
+                       ASSERT(!pipe_ctx->plane_state->triplebuffer_flips);
+                       if (dc->hwss.program_triplebuffer != NULL &&
+                               !dc->debug.disable_tri_buf) {
+                               /*turn off triple buffer for full update*/
+                               dc->hwss.program_triplebuffer(
+                                       dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
+                       }
+               }
+       }
 
        /* Set pipe update flags and lock pipes */
        for (i = 0; i < dc->res_pool->pipe_count; i++)
                dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i],
                                &context->res_ctx.pipe_ctx[i]);
-       for (i = 0; i < dc->res_pool->pipe_count; i++)
-               if (!context->res_ctx.pipe_ctx[i].top_pipe &&
-                               does_pipe_need_lock(&context->res_ctx.pipe_ctx[i])) {
-                       struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-
-                       if (pipe_ctx->update_flags.bits.tg_changed || pipe_ctx->update_flags.bits.enable)
-                               dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
-                       if (!pipe_ctx->update_flags.bits.enable)
-                               dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], true);
-                       pipe_locked[i] = true;
-               }
 
        /* OTG blank before disabling all front ends */
        for (i = 0; i < dc->res_pool->pipe_count; i++)
@@ -1609,17 +1603,16 @@ void dcn20_program_front_end_for_ctx(
                                hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context);
                }
        }
+}
 
-       /* Unlock all locked pipes */
-       for (i = 0; i < dc->res_pool->pipe_count; i++)
-               if (pipe_locked[i]) {
-                       struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+void dcn20_post_unlock_program_front_end(
+               struct dc *dc,
+               struct dc_state *context)
+{
+       int i;
+       const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100;
 
-                       if (pipe_ctx->update_flags.bits.tg_changed || pipe_ctx->update_flags.bits.enable)
-                               dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
-                       if (!pipe_ctx->update_flags.bits.enable)
-                               dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], false);
-               }
+       DC_LOGGER_INIT(dc->ctx->logger);
 
        for (i = 0; i < dc->res_pool->pipe_count; i++)
                if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
@@ -1638,9 +1631,9 @@ void dcn20_program_front_end_for_ctx(
                        struct hubp *hubp = pipe->plane_res.hubp;
                        int j = 0;
 
-                       for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS
+                       for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000
                                        && hubp->funcs->hubp_is_flip_pending(hubp); j++)
-                               msleep(1);
+                               mdelay(1);
                }
        }
 
@@ -1649,7 +1642,6 @@ void dcn20_program_front_end_for_ctx(
                dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub);
 }
 
-
 void dcn20_prepare_bandwidth(
                struct dc *dc,
                struct dc_state *context)