drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
Extension
.c
Size
19618 bytes
Lines
652
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (sso_delay_ns > 0) {
			/*
			 * If sso_num_frames is less than hysteresis frames, it
			 * indicates that allowing idle here, then disallowing
			 * idle after sso_num_frames has expired, will likely
			 * have a negative power impact. Skip idle allow here,
			 * and let the sso_delayed_work handle it.
			 */
			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));
		}
		break;
	case DM_ISM_STATE_OPTIMIZED_IDLE_SSO:
		/* Enable static screen optimizations. */
		dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
						      false, true);
		break;
	case DM_ISM_STATE_TIMER_ABORTED:
		dm_ism_insert_record(ism);
		dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
						      true, false);
		break;
	default:
		break;
	}

	return dm_ism_dispatch_next_event(ism->current_state, delay_ns, sso_delay_ns);
}

static char *dm_ism_events_str[DM_ISM_NUM_EVENTS] = {
	[DM_ISM_EVENT_IMMEDIATE] = "IMMEDIATE",
	[DM_ISM_EVENT_ENTER_IDLE_REQUESTED] = "ENTER_IDLE_REQUESTED",
	[DM_ISM_EVENT_EXIT_IDLE_REQUESTED] = "EXIT_IDLE_REQUESTED",
	[DM_ISM_EVENT_BEGIN_CURSOR_UPDATE] = "BEGIN_CURSOR_UPDATE",
	[DM_ISM_EVENT_END_CURSOR_UPDATE] = "END_CURSOR_UPDATE",
	[DM_ISM_EVENT_TIMER_ELAPSED] = "TIMER_ELAPSED",
	[DM_ISM_EVENT_SSO_TIMER_ELAPSED] = "SSO_TIMER_ELAPSED",
};

static char *dm_ism_states_str[DM_ISM_NUM_STATES] = {
	[DM_ISM_STATE_FULL_POWER_RUNNING] = "FULL_POWER_RUNNING",
	[DM_ISM_STATE_FULL_POWER_BUSY] = "FULL_POWER_BUSY",
	[DM_ISM_STATE_HYSTERESIS_WAITING] = "HYSTERESIS_WAITING",
	[DM_ISM_STATE_HYSTERESIS_BUSY] = "HYSTERESIS_BUSY",
	[DM_ISM_STATE_OPTIMIZED_IDLE] = "OPTIMIZED_IDLE",
	[DM_ISM_STATE_OPTIMIZED_IDLE_SSO] = "OPTIMIZED_IDLE_SSO",
	[DM_ISM_STATE_TIMER_ABORTED] = "TIMER_ABORTED",
};


void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism,
				enum amdgpu_dm_ism_event event)
{
	enum amdgpu_dm_ism_event next_event = event;
	struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
	struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
	struct amdgpu_display_manager *dm = &adev->dm;
	struct dm_crtc_state *acrtc_state = to_dm_crtc_state(acrtc->base.state);

	/* ISM transitions must be called with dc_lock held */
	lockdep_assert_held(&dm->dc_lock);

	/* ISM should not run after dc is destroyed */
	ASSERT(dm->dc);

	if (!acrtc_state) {
		trace_amdgpu_dm_ism_event(acrtc->crtc_id, "NO_STATE",
					  "NO_STATE", "N/A");
		return;
	}

	do {
		bool transition = dm_ism_trigger_event(ism, event);

		next_event = DM_ISM_NUM_EVENTS;
		if (transition) {
			trace_amdgpu_dm_ism_event(
				acrtc->crtc_id,
				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);
		} else {
			trace_amdgpu_dm_ism_event(
				acrtc->crtc_id,

Annotation

Implementation Notes