drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
Extension
.c
Size
12030 bytes
Lines
454
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

struct ipu_crtc {
	struct device		*dev;
	struct drm_crtc		base;

	/* plane[0] is the full plane, plane[1] is the partial plane */
	struct ipu_plane	*plane[2];

	struct ipu_dc		*dc;
	struct ipu_di		*di;
	int			irq;
	struct drm_pending_vblank_event *event;
};

static inline struct ipu_crtc *to_ipu_crtc(struct drm_crtc *crtc)
{
	return container_of(crtc, struct ipu_crtc, base);
}

static void ipu_crtc_atomic_enable(struct drm_crtc *crtc,
				   struct drm_atomic_commit *state)
{
	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);

	ipu_prg_enable(ipu);
	ipu_dc_enable(ipu);
	ipu_dc_enable_channel(ipu_crtc->dc);
	ipu_di_enable(ipu_crtc->di);
}

static void ipu_crtc_disable_planes(struct ipu_crtc *ipu_crtc,
				    struct drm_crtc_state *old_crtc_state)
{
	bool disable_partial = false;
	bool disable_full = false;
	struct drm_plane *plane;

	drm_atomic_crtc_state_for_each_plane(plane, old_crtc_state) {
		if (plane == &ipu_crtc->plane[0]->base)
			disable_full = true;
		if (ipu_crtc->plane[1] && plane == &ipu_crtc->plane[1]->base)
			disable_partial = true;
	}

	if (disable_partial)
		ipu_plane_disable(ipu_crtc->plane[1], true);
	if (disable_full)
		ipu_plane_disable(ipu_crtc->plane[0], true);
}

static void ipu_crtc_atomic_disable(struct drm_crtc *crtc,
				    struct drm_atomic_commit *state)
{
	struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state,
									      crtc);
	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);

	ipu_dc_disable_channel(ipu_crtc->dc);
	ipu_di_disable(ipu_crtc->di);
	/*
	 * Planes must be disabled before DC clock is removed, as otherwise the
	 * attached IDMACs will be left in undefined state, possibly hanging
	 * the IPU or even system.
	 */
	ipu_crtc_disable_planes(ipu_crtc, old_crtc_state);
	ipu_dc_disable(ipu);
	ipu_prg_disable(ipu);

	drm_crtc_vblank_off(crtc);

	spin_lock_irq(&crtc->dev->event_lock);
	if (crtc->state->event && !crtc->state->active) {
		drm_crtc_send_vblank_event(crtc, crtc->state->event);
		crtc->state->event = NULL;
	}
	spin_unlock_irq(&crtc->dev->event_lock);
}

static void imx_drm_crtc_reset(struct drm_crtc *crtc)
{
	struct imx_crtc_state *state;

	if (crtc->state)
		__drm_atomic_helper_crtc_destroy_state(crtc->state);

	kfree(to_imx_crtc_state(crtc->state));
	crtc->state = NULL;

	state = kzalloc_obj(*state);

Annotation

Implementation Notes