Merge tag 'amd-drm-fixes-6.9-2024-03-21' of https://gitlab.freedesktop.org/agd5f...
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / core / dc.c
index 5211c1c..e7dc128 100644 (file)
@@ -1302,6 +1302,54 @@ static void disable_vbios_mode_if_required(
        }
 }
 
+/**
+ * wait_for_blank_complete - wait for all active OPPs to finish pending blank
+ * pattern updates
+ *
+ * @dc: [in] dc reference
+ * @context: [in] hardware context in use
+ */
+static void wait_for_blank_complete(struct dc *dc,
+               struct dc_state *context)
+{
+       struct pipe_ctx *opp_head;
+       struct dce_hwseq *hws = dc->hwseq;
+       int i;
+
+       if (!hws->funcs.wait_for_blank_complete)
+               return;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               opp_head = &context->res_ctx.pipe_ctx[i];
+
+               if (!resource_is_pipe_type(opp_head, OPP_HEAD) ||
+                               dc_state_get_pipe_subvp_type(context, opp_head) == SUBVP_PHANTOM)
+                       continue;
+
+               hws->funcs.wait_for_blank_complete(opp_head->stream_res.opp);
+       }
+}
+
+static void wait_for_odm_update_pending_complete(struct dc *dc, struct dc_state *context)
+{
+       struct pipe_ctx *otg_master;
+       struct timing_generator *tg;
+       int i;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               otg_master = &context->res_ctx.pipe_ctx[i];
+               if (!resource_is_pipe_type(otg_master, OTG_MASTER) ||
+                               dc_state_get_pipe_subvp_type(context, otg_master) == SUBVP_PHANTOM)
+                       continue;
+               tg = otg_master->stream_res.tg;
+               if (tg->funcs->wait_odm_doublebuffer_pending_clear)
+                       tg->funcs->wait_odm_doublebuffer_pending_clear(tg);
+       }
+
+       /* ODM update may require to reprogram blank pattern for each OPP */
+       wait_for_blank_complete(dc, context);
+}
+
 static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
 {
        int i;
@@ -1993,6 +2041,11 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
                context->stream_count == 0) {
                /* Must wait for no flips to be pending before doing optimize bw */
                wait_for_no_pipes_pending(dc, context);
+               /*
+                * optimized dispclk depends on ODM setup. Need to wait for ODM
+                * update pending complete before optimizing bandwidth.
+                */
+               wait_for_odm_update_pending_complete(dc, context);
                /* pplib is notified if disp_num changed */
                dc->hwss.optimize_bandwidth(dc, context);
                /* Need to do otg sync again as otg could be out of sync due to otg
@@ -3270,6 +3323,9 @@ static bool dc_dmub_should_send_dirty_rect_cmd(struct dc *dc, struct dc_stream_s
        if (stream->link->replay_settings.config.replay_supported)
                return true;
 
+       if (stream->ctx->dce_version >= DCN_VERSION_3_5 && stream->abm_level)
+               return true;
+
        return false;
 }
 
@@ -3493,7 +3549,7 @@ static void commit_planes_for_stream_fast(struct dc *dc,
                top_pipe_to_program->stream->update_flags.raw = 0;
 }
 
-static void wait_for_outstanding_hw_updates(struct dc *dc, const struct dc_state *dc_context)
+static void wait_for_outstanding_hw_updates(struct dc *dc, struct dc_state *dc_context)
 {
 /*
  * This function calls HWSS to wait for any potentially double buffered
@@ -3531,6 +3587,7 @@ static void wait_for_outstanding_hw_updates(struct dc *dc, const struct dc_state
                        }
                }
        }
+       wait_for_odm_update_pending_complete(dc, dc_context);
 }
 
 static void commit_planes_for_stream(struct dc *dc,
@@ -4844,22 +4901,16 @@ void dc_exit_ips_for_hw_access(struct dc *dc)
 
 bool dc_dmub_is_ips_idle_state(struct dc *dc)
 {
-       uint32_t idle_state = 0;
-
        if (dc->debug.disable_idle_power_optimizations)
                return false;
 
        if (!dc->caps.ips_support || (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL))
                return false;
 
-       if (dc->hwss.get_idle_state)
-               idle_state = dc->hwss.get_idle_state(dc);
-
-       if (!(idle_state & DMUB_IPS1_ALLOW_MASK) ||
-               !(idle_state & DMUB_IPS2_ALLOW_MASK))
-               return true;
+       if (!dc->ctx->dmub_srv)
+               return false;
 
-       return false;
+       return dc->ctx->dmub_srv->idle_allowed;
 }
 
 /* set min and max memory clock to lowest and highest DPM level, respectively */