drivers/gpu/drm/drm_self_refresh_helper.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/drm_self_refresh_helper.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/drm_self_refresh_helper.c
Extension
.c
Size
8477 bytes
Lines
283
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

struct drm_self_refresh_data {
	struct drm_crtc *crtc;
	struct delayed_work entry_work;

	struct mutex avg_mutex;
	struct ewma_psr_time entry_avg_ms;
	struct ewma_psr_time exit_avg_ms;
};

static void drm_self_refresh_helper_entry_work(struct work_struct *work)
{
	struct drm_self_refresh_data *sr_data = container_of(
				to_delayed_work(work),
				struct drm_self_refresh_data, entry_work);
	struct drm_crtc *crtc = sr_data->crtc;
	struct drm_device *dev = crtc->dev;
	struct drm_modeset_acquire_ctx ctx;
	struct drm_atomic_commit *state;
	struct drm_connector *conn;
	struct drm_connector_state *conn_state;
	struct drm_crtc_state *crtc_state;
	int i, ret = 0;

	drm_modeset_acquire_init(&ctx, 0);

	state = drm_atomic_commit_alloc(dev);
	if (!state) {
		ret = -ENOMEM;
		goto out_drop_locks;
	}

retry:
	state->acquire_ctx = &ctx;

	crtc_state = drm_atomic_get_crtc_state(state, crtc);
	if (IS_ERR(crtc_state)) {
		ret = PTR_ERR(crtc_state);
		goto out;
	}

	if (!crtc_state->enable)
		goto out;

	ret = drm_atomic_add_affected_connectors(state, crtc);
	if (ret)
		goto out;

	for_each_new_connector_in_state(state, conn, conn_state, i) {
		if (!conn_state->self_refresh_aware)
			goto out;
	}

	crtc_state->active = false;
	crtc_state->self_refresh_active = true;

	ret = drm_atomic_commit(state);
	if (ret)
		goto out;

out:
	if (ret == -EDEADLK) {
		drm_atomic_commit_clear(state);
		ret = drm_modeset_backoff(&ctx);
		if (!ret)
			goto retry;
	}

	drm_atomic_commit_put(state);

out_drop_locks:
	drm_modeset_drop_locks(&ctx);
	drm_modeset_acquire_fini(&ctx);
}

/**
 * drm_self_refresh_helper_update_avg_times - Updates a crtc's SR time averages
 * @state: the state which has just been applied to hardware
 * @commit_time_ms: the amount of time in ms that this commit took to complete
 * @new_self_refresh_mask: bitmask of crtc's that have self_refresh_active in
 *    new state
 *
 * Called after &drm_mode_config_funcs.atomic_commit_tail, this function will
 * update the average entry/exit self refresh times on self refresh transitions.
 * These averages will be used when calculating how long to delay before
 * entering self refresh mode after activity.
 */
void
drm_self_refresh_helper_update_avg_times(struct drm_atomic_commit *state,
					 unsigned int commit_time_ms,
					 unsigned int new_self_refresh_mask)

Annotation

Implementation Notes