summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAlex Hung <alex.hung@amd.com>2026-05-15 13:27:56 -0600
committerAlex Deucher <alexander.deucher@amd.com>2026-06-03 13:41:44 -0400
commitf84c48048b491941af8caaa65d4260123cab7257 (patch)
treed5c7759967ccdc4e1c11648bb2c3ed90c60ba2dc /drivers/gpu
parenta3142b13fe9fdbc3738026cc1cfeb7b2ab38a382 (diff)
drm/amd/display: Extract dm_ism_dispatch_next_event
[Why & How] Separate the "should we emit IMMEDIATE?" decision into a pure, side-effect-free helper so it can be tested in isolation without a full DRM context. - dm_ism_dispatch_next_event(current_state, delay_ns, sso_delay_ns) returns DM_ISM_EVENT_IMMEDIATE when the state requires an immediate follow-up (HYSTERESIS_WAITING with zero delay, OPTIMIZED_IDLE with zero SSO delay, or TIMER_ABORTED), and DM_ISM_NUM_EVENTS otherwise. - Removes the passthrough event parameter that was always DM_ISM_NUM_EVENTS at the call site, making the sentinel explicit. - Drops the now-unused event parameter from dm_ism_dispatch_power_state. Assisted-by: Copilot:Claude-Sonnet-4.6 Reviewed-by: Ray Wu <ray.wu@amd.com> Signed-off-by: Alex Hung <alex.hung@amd.com> Signed-off-by: Ray Wu <ray.wu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c71
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h3
2 files changed, 39 insertions, 35 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
index 0a010802540d..5c0841728671 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
@@ -332,15 +332,36 @@ static void dm_ism_commit_idle_optimization_state(struct amdgpu_dm_ism *ism,
}
}
+STATIC_IFN_KUNIT
+enum amdgpu_dm_ism_event dm_ism_dispatch_next_event(
+ enum amdgpu_dm_ism_state current_state,
+ uint64_t delay_ns,
+ uint64_t sso_delay_ns)
+{
+ switch (current_state) {
+ case DM_ISM_STATE_HYSTERESIS_WAITING:
+ if (delay_ns == 0)
+ return DM_ISM_EVENT_IMMEDIATE;
+ break;
+ case DM_ISM_STATE_OPTIMIZED_IDLE:
+ if (sso_delay_ns == 0)
+ return DM_ISM_EVENT_IMMEDIATE;
+ break;
+ case DM_ISM_STATE_TIMER_ABORTED:
+ return DM_ISM_EVENT_IMMEDIATE;
+ default:
+ break;
+ }
+ return DM_ISM_NUM_EVENTS;
+}
+EXPORT_IF_KUNIT(dm_ism_dispatch_next_event);
static enum amdgpu_dm_ism_event dm_ism_dispatch_power_state(
struct amdgpu_dm_ism *ism,
- struct dm_crtc_state *acrtc_state,
- enum amdgpu_dm_ism_event event)
+ struct dm_crtc_state *acrtc_state)
{
- enum amdgpu_dm_ism_event ret = event;
const struct amdgpu_dm_ism_config *config = &ism->config;
- uint64_t delay_ns, sso_delay_ns;
+ uint64_t delay_ns = 0, sso_delay_ns = 0;
switch (ism->previous_state) {
case DM_ISM_STATE_HYSTERESIS_WAITING:
@@ -374,30 +395,15 @@ static enum amdgpu_dm_ism_event dm_ism_dispatch_power_state(
switch (ism->current_state) {
case DM_ISM_STATE_HYSTERESIS_WAITING:
dm_ism_set_last_idle_ts(ism);
-
- /* CRTC can be disabled; allow immediate idle */
- if (!acrtc_state->stream) {
- ret = DM_ISM_EVENT_IMMEDIATE;
- break;
- }
-
- delay_ns = dm_ism_get_idle_allow_delay(ism,
- acrtc_state->stream);
- if (delay_ns == 0) {
- ret = DM_ISM_EVENT_IMMEDIATE;
- break;
- }
-
+ delay_ns = dm_ism_get_idle_allow_delay(ism, acrtc_state->stream);
/* Schedule worker */
- mod_delayed_work(system_dfl_wq, &ism->delayed_work,
- nsecs_to_jiffies(delay_ns));
-
+ if (delay_ns > 0)
+ mod_delayed_work(system_dfl_wq, &ism->delayed_work,
+ nsecs_to_jiffies(delay_ns));
break;
case DM_ISM_STATE_OPTIMIZED_IDLE:
sso_delay_ns = dm_ism_get_sso_delay(ism, acrtc_state->stream);
- if (sso_delay_ns == 0)
- ret = DM_ISM_EVENT_IMMEDIATE;
- else if (config->sso_num_frames < config->filter_num_frames) {
+ if (sso_delay_ns > 0) {
/*
* If sso_num_frames is less than hysteresis frames, it
* indicates that allowing idle here, then disallowing
@@ -405,13 +411,10 @@ static enum amdgpu_dm_ism_event dm_ism_dispatch_power_state(
* have a negative power impact. Skip idle allow here,
* and let the sso_delayed_work handle it.
*/
- mod_delayed_work(system_dfl_wq,
- &ism->sso_delayed_work,
- nsecs_to_jiffies(sso_delay_ns));
- } else {
- /* Enable idle optimization without SSO */
- dm_ism_commit_idle_optimization_state(
- ism, acrtc_state->stream, false, false);
+ if (config->sso_num_frames >= config->filter_num_frames)
+ dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
+ false, false);
+
mod_delayed_work(system_dfl_wq,
&ism->sso_delayed_work,
nsecs_to_jiffies(sso_delay_ns));
@@ -426,13 +429,12 @@ static enum amdgpu_dm_ism_event dm_ism_dispatch_power_state(
dm_ism_insert_record(ism);
dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
true, false);
- ret = DM_ISM_EVENT_IMMEDIATE;
break;
default:
break;
}
- return ret;
+ return dm_ism_dispatch_next_event(ism->current_state, delay_ns, sso_delay_ns);
}
static char *dm_ism_events_str[DM_ISM_NUM_EVENTS] = {
@@ -487,8 +489,7 @@ void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism,
dm_ism_states_str[ism->previous_state],
dm_ism_states_str[ism->current_state],
dm_ism_events_str[event]);
- next_event = dm_ism_dispatch_power_state(
- ism, acrtc_state, next_event);
+ next_event = dm_ism_dispatch_power_state(ism, acrtc_state);
} else {
trace_amdgpu_dm_ism_event(
acrtc->crtc_id,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h
index da3e192e8d25..afce16f7085a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h
@@ -161,6 +161,9 @@ void dm_ism_insert_record(struct amdgpu_dm_ism *ism);
void dm_ism_set_last_idle_ts(struct amdgpu_dm_ism *ism);
bool dm_ism_trigger_event(struct amdgpu_dm_ism *ism,
enum amdgpu_dm_ism_event event);
+enum amdgpu_dm_ism_event dm_ism_dispatch_next_event(enum amdgpu_dm_ism_state current_state,
+ uint64_t delay_ns,
+ uint64_t sso_delay_ns);
#endif
#endif