drivers/gpu/drm/vc4/vc4_plane.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/vc4/vc4_plane.c
Extension
.c
Size
77519 bytes
Lines
2621
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 (!vc4_state->dlist) {
			kfree(vc4_state);
			return NULL;
		}
		vc4_state->dlist_size = vc4_state->dlist_count;
	}

	return &vc4_state->base;
}

static void vc4_plane_release_upm_ida(struct vc4_hvs *hvs, unsigned int upm_handle)
{
	struct vc4_upm_refcounts *refcount = &hvs->upm_refcounts[upm_handle];
	unsigned long irqflags;

	spin_lock_irqsave(&hvs->mm_lock, irqflags);
	drm_mm_remove_node(&refcount->upm);
	spin_unlock_irqrestore(&hvs->mm_lock, irqflags);
	refcount->upm.start = 0;
	refcount->upm.size = 0;
	refcount->size = 0;

	ida_free(&hvs->upm_handles, upm_handle);
}

static void vc4_plane_destroy_state(struct drm_plane *plane,
				    struct drm_plane_state *state)
{
	struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
	struct vc4_hvs *hvs = vc4->hvs;
	struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
	unsigned int i;

	if (drm_mm_node_allocated(&vc4_state->lbm)) {
		unsigned long irqflags;

		spin_lock_irqsave(&hvs->mm_lock, irqflags);
		drm_mm_remove_node(&vc4_state->lbm);
		spin_unlock_irqrestore(&hvs->mm_lock, irqflags);
	}

	for (i = 0; i < DRM_FORMAT_MAX_PLANES; i++) {
		struct vc4_upm_refcounts *refcount;

		if (!vc4_state->upm_handle[i])
			continue;

		refcount = &hvs->upm_refcounts[vc4_state->upm_handle[i]];

		if (refcount_dec_and_test(&refcount->refcount))
			vc4_plane_release_upm_ida(hvs, vc4_state->upm_handle[i]);
	}

	kfree(vc4_state->dlist);
	__drm_atomic_helper_plane_destroy_state(&vc4_state->base);
	kfree(state);
}

/* Called during init to allocate the plane's atomic state. */
static void vc4_plane_reset(struct drm_plane *plane)
{
	struct vc4_plane_state *vc4_state;

	if (plane->state)
		__drm_atomic_helper_plane_destroy_state(plane->state);

	kfree(plane->state);

	vc4_state = kzalloc_obj(*vc4_state);
	if (!vc4_state)
		return;

	__drm_atomic_helper_plane_reset(plane, &vc4_state->base);
}

static void vc4_dlist_counter_increment(struct vc4_plane_state *vc4_state)
{
	if (vc4_state->dlist_count == vc4_state->dlist_size) {
		u32 new_size = max(4u, vc4_state->dlist_count * 2);
		u32 *new_dlist = kmalloc_array(new_size, 4, GFP_KERNEL);

		if (!new_dlist)
			return;
		memcpy(new_dlist, vc4_state->dlist, vc4_state->dlist_count * 4);

		kfree(vc4_state->dlist);
		vc4_state->dlist = new_dlist;
		vc4_state->dlist_size = new_size;
	}

Annotation

Implementation Notes