drm/amd/display: change the panel power savings level without a modeset
authorHamza Mahfooz <hamza.mahfooz@amd.com>
Fri, 9 Aug 2024 20:42:53 +0000 (16:42 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 26 Sep 2024 21:07:25 +0000 (17:07 -0400)
We don't actually need to request that the compositor does a full
modeset to modify the panel power savings level, we can instead
just make a request to DMUB, to set the new level dynamically.

Cc: Harry Wentland <harry.wentland@amd.com>
Cc: Leo Li <sunpeng.li@amd.com>
Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Sebastian Wick <sebastian@sebastianwick.net>
Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
Tested-by: Mario Limonciello <mario.limonciello@amd.com>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3578
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dc.h

index 6e79028..1d2d5fb 100644 (file)
@@ -6908,9 +6908,14 @@ static ssize_t panel_power_savings_store(struct device *device,
                                         const char *buf, size_t count)
 {
        struct drm_connector *connector = dev_get_drvdata(device);
+       struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(connector);
        struct drm_device *dev = connector->dev;
+       struct amdgpu_device *adev = drm_to_adev(dev);
+       struct dc *dc = adev->dm.dc;
+       struct pipe_ctx *pipe_ctx;
        long val;
        int ret;
+       int i;
 
        ret = kstrtol(buf, 0, &val);
 
@@ -6925,7 +6930,17 @@ static ssize_t panel_power_savings_store(struct device *device,
                ABM_LEVEL_IMMEDIATE_DISABLE;
        drm_modeset_unlock(&dev->mode_config.connection_mutex);
 
-       drm_kms_helper_hotplug_event(dev);
+       mutex_lock(&adev->dm.dc_lock);
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
+
+               if (pipe_ctx->stream &&
+                   pipe_ctx->stream->link == aconn->dc_link) {
+                       dc_set_abm_level(dc, pipe_ctx, val);
+                       break;
+               }
+       }
+       mutex_unlock(&adev->dm.dc_lock);
 
        return count;
 }
index 5c39390..dc07ff4 100644 (file)
@@ -3260,6 +3260,23 @@ fail:
 
 }
 
+void dc_set_abm_level(struct dc *dc, struct pipe_ctx *pipe_ctx, int level)
+{
+       struct timing_generator *tg = pipe_ctx->stream_res.tg;
+       struct abm *abm = pipe_ctx->stream_res.abm;
+
+       if (!abm)
+               return;
+
+       if (tg->funcs->is_blanked && !tg->funcs->is_blanked(tg))
+               tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
+
+       if (level == ABM_LEVEL_IMMEDIATE_DISABLE)
+               dc->hwss.set_abm_immediate_disable(pipe_ctx);
+       else
+               abm->funcs->set_abm_level(abm, level);
+}
+
 static void commit_planes_do_stream_update(struct dc *dc,
                struct dc_stream_state *stream,
                struct dc_stream_update *stream_update,
@@ -3388,22 +3405,12 @@ static void commit_planes_do_stream_update(struct dc *dc,
                                dc->link_srv->set_dpms_on(dc->current_state, pipe_ctx);
                        }
 
-                       if (stream_update->abm_level && pipe_ctx->stream_res.abm) {
-                               bool should_program_abm = true;
-
-                               // if otg funcs defined check if blanked before programming
-                               if (pipe_ctx->stream_res.tg->funcs->is_blanked)
-                                       if (pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg))
-                                               should_program_abm = false;
-
-                               if (should_program_abm) {
-                                       if (*stream_update->abm_level == ABM_LEVEL_IMMEDIATE_DISABLE) {
-                                               dc->hwss.set_abm_immediate_disable(pipe_ctx);
-                                       } else {
-                                               pipe_ctx->stream_res.abm->funcs->set_abm_level(
-                                                       pipe_ctx->stream_res.abm, stream->abm_level);
-                                       }
-                               }
+                       if (stream_update->abm_level) {
+                               dc_set_abm_level(dc, pipe_ctx,
+                                                *stream_update->abm_level ==
+                                                ABM_LEVEL_IMMEDIATE_DISABLE ?
+                                                ABM_LEVEL_IMMEDIATE_DISABLE :
+                                                stream->abm_level);
                        }
                }
        }
index 3992ad7..8c769d6 100644 (file)
@@ -2503,6 +2503,8 @@ void dc_z10_save_init(struct dc *dc);
 bool dc_is_dmub_outbox_supported(struct dc *dc);
 bool dc_enable_dmub_notifications(struct dc *dc);
 
+void dc_set_abm_level(struct dc *dc, struct pipe_ctx *pipe_ctx, int level);
+
 bool dc_abm_save_restore(
                struct dc *dc,
                struct dc_stream_state *stream,