drivers/gpu/drm/vc4/vc4_crtc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/vc4/vc4_crtc.c
Extension
.c
Size
44527 bytes
Lines
1543
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 vc4_async_flip_state {
	struct drm_crtc *crtc;
	struct drm_framebuffer *fb;
	struct drm_framebuffer *old_fb;
	struct drm_pending_vblank_event *event;
	struct dma_fence_cb cb;
};

/* Called when the V3D execution for the BO being flipped to is done, so that
 * we can actually update the plane's address to point to it.
 */
static void
vc4_async_page_flip_complete(struct vc4_async_flip_state *flip_state)
{
	struct drm_crtc *crtc = flip_state->crtc;
	struct drm_device *dev = crtc->dev;
	struct drm_plane *plane = crtc->primary;

	vc4_plane_async_set_fb(plane, flip_state->fb);
	if (flip_state->event) {
		unsigned long flags;

		spin_lock_irqsave(&dev->event_lock, flags);
		drm_crtc_send_vblank_event(crtc, flip_state->event);
		spin_unlock_irqrestore(&dev->event_lock, flags);
	}

	drm_crtc_vblank_put(crtc);
	drm_framebuffer_put(flip_state->fb);

	if (flip_state->old_fb)
		drm_framebuffer_put(flip_state->old_fb);

	kfree(flip_state);
}

static void vc4_async_page_flip_complete_with_cleanup(struct dma_fence *fence,
						      struct dma_fence_cb *cb)
{
	struct vc4_async_flip_state *flip_state =
		container_of(cb, struct vc4_async_flip_state, cb);
	struct vc4_bo *bo = NULL;

	if (flip_state->old_fb) {
		struct drm_gem_dma_object *dma_bo =
			drm_fb_dma_get_gem_obj(flip_state->old_fb, 0);
		bo = to_vc4_bo(&dma_bo->base);
	}

	vc4_async_page_flip_complete(flip_state);
	dma_fence_put(fence);

	/*
	 * Decrement the BO usecnt in order to keep the inc/dec
	 * calls balanced when the planes are updated through
	 * the async update path.
	 *
	 * FIXME: we should move to generic async-page-flip when
	 * it's available, so that we can get rid of this
	 * hand-made cleanup_fb() logic.
	 */
	if (bo)
		vc4_bo_dec_usecnt(bo);
}

static void vc4_async_page_flip_fence_complete(struct dma_fence *fence,
					       struct dma_fence_cb *cb)
{
	struct vc4_async_flip_state *flip_state =
		container_of(cb, struct vc4_async_flip_state, cb);

	vc4_async_page_flip_complete(flip_state);
	dma_fence_put(fence);
}

static int vc4_async_set_fence_cb(struct drm_device *dev,
				  struct vc4_async_flip_state *flip_state)
{
	struct drm_framebuffer *fb = flip_state->fb;
	struct drm_gem_dma_object *dma_bo = drm_fb_dma_get_gem_obj(fb, 0);
	dma_fence_func_t async_page_flip_complete_function;
	struct vc4_dev *vc4 = to_vc4_dev(dev);
	struct dma_fence *fence;
	int ret;

	if (vc4->gen == VC4_GEN_4)
		async_page_flip_complete_function = vc4_async_page_flip_complete_with_cleanup;
	else
		async_page_flip_complete_function = vc4_async_page_flip_fence_complete;

Annotation

Implementation Notes