drivers/gpu/drm/arm/display/komeda/komeda_crtc.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
Extension
.c
Size
19057 bytes
Lines
690
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 (kcrtc->disable_done) {
			complete_all(kcrtc->disable_done);
			kcrtc->disable_done = NULL;
		} else if (crtc->state->event) {
			event = crtc->state->event;
			/*
			 * Consume event before notifying drm core that flip
			 * happened.
			 */
			crtc->state->event = NULL;
			drm_crtc_send_vblank_event(crtc, event);
		} else {
			drm_warn(drm, "CRTC[%d]: FLIP happened but no pending commit.\n",
				 drm_crtc_index(&kcrtc->base));
		}
		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
	}
}

static void
komeda_crtc_do_flush(struct drm_crtc *crtc,
		     struct drm_crtc_state *old)
{
	struct komeda_crtc *kcrtc = to_kcrtc(crtc);
	struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(crtc->state);
	struct komeda_dev *mdev = kcrtc->base.dev->dev_private;
	struct komeda_pipeline *master = kcrtc->master;
	struct komeda_pipeline *slave = kcrtc->slave;
	struct komeda_wb_connector *wb_conn = kcrtc->wb_conn;
	struct drm_connector_state *conn_st;

	DRM_DEBUG_ATOMIC("CRTC%d_FLUSH: active_pipes: 0x%x, affected: 0x%x.\n",
			 drm_crtc_index(crtc),
			 kcrtc_st->active_pipes, kcrtc_st->affected_pipes);

	/* step 1: update the pipeline/component state to HW */
	if (has_bit(master->id, kcrtc_st->affected_pipes))
		komeda_pipeline_update(master, old->state);

	if (slave && has_bit(slave->id, kcrtc_st->affected_pipes))
		komeda_pipeline_update(slave, old->state);

	conn_st = wb_conn ? wb_conn->base.base.state : NULL;
	if (conn_st && conn_st->writeback_job)
		drm_writeback_queue_job(&wb_conn->base, conn_st);

	/* step 2: notify the HW to kickoff the update */
	mdev->funcs->flush(mdev, master->id, kcrtc_st->active_pipes);
}

static void
komeda_crtc_atomic_enable(struct drm_crtc *crtc,
			  struct drm_atomic_commit *state)
{
	struct drm_crtc_state *old = drm_atomic_get_old_crtc_state(state,
								   crtc);
	pm_runtime_get_sync(crtc->dev->dev);
	komeda_crtc_prepare(to_kcrtc(crtc));
	drm_crtc_vblank_on(crtc);
	WARN_ON(drm_crtc_vblank_get(crtc));
	komeda_crtc_do_flush(crtc, old);
}

void
komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
					 struct completion *input_flip_done)
{
	struct drm_device *drm = kcrtc->base.dev;
	struct komeda_dev *mdev = kcrtc->master->mdev;
	struct completion *flip_done;
	struct completion temp;

	/* if caller doesn't send a flip_done, use a private flip_done */
	if (input_flip_done) {
		flip_done = input_flip_done;
	} else {
		init_completion(&temp);
		kcrtc->disable_done = &temp;
		flip_done = &temp;
	}

	mdev->funcs->flush(mdev, kcrtc->master->id, 0);

	/* wait the flip take affect.*/
	if (wait_for_completion_timeout(flip_done, HZ) == 0) {
		drm_err(drm, "wait pipe%d flip done timeout\n", kcrtc->master->id);
		if (!input_flip_done) {
			unsigned long flags;

			spin_lock_irqsave(&drm->event_lock, flags);

Annotation

Implementation Notes