drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.c
Extension
.c
Size
24936 bytes
Lines
843
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 (!new_plane_state->format) {
			dev_dbg(rcdu->dev, "%s: plane is being disabled\n",
				__func__);
			index = plane - plane->group->planes;
			group_freed_planes[plane->group->index] |= 1 << index;
			new_plane_state->hwindex = -1;
			continue;
		}

		/*
		 * If the plane needs to be reallocated mark it as such, and
		 * mark the hardware plane(s) as free.
		 */
		if (rcar_du_plane_needs_realloc(old_plane_state, new_plane_state)) {
			dev_dbg(rcdu->dev, "%s: plane needs reallocation\n",
				__func__);
			groups |= 1 << plane->group->index;
			needs_realloc = true;

			index = plane - plane->group->planes;
			group_freed_planes[plane->group->index] |= 1 << index;
			new_plane_state->hwindex = -1;
		}
	}

	if (!needs_realloc)
		return 0;

	/*
	 * Grab all plane states for the groups that need reallocation to ensure
	 * locking and avoid racy updates. This serializes the update operation,
	 * but there's not much we can do about it as that's the hardware
	 * design.
	 *
	 * Compute the used planes mask for each group at the same time to avoid
	 * looping over the planes separately later.
	 */
	while (groups) {
		unsigned int index = ffs(groups) - 1;
		struct rcar_du_group *group = &rcdu->groups[index];
		unsigned int used_planes = 0;

		dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n",
			__func__, index);

		for (i = 0; i < group->num_planes; ++i) {
			struct rcar_du_plane *plane = &group->planes[i];
			struct rcar_du_plane_state *new_plane_state;
			struct drm_plane_state *s;

			s = drm_atomic_get_plane_state(state, &plane->plane);
			if (IS_ERR(s))
				return PTR_ERR(s);

			/*
			 * If the plane has been freed in the above loop its
			 * hardware planes must not be added to the used planes
			 * bitmask. However, the current state doesn't reflect
			 * the free state yet, as we've modified the new state
			 * above. Use the local freed planes list to check for
			 * that condition instead.
			 */
			if (group_freed_planes[index] & (1 << i)) {
				dev_dbg(rcdu->dev,
					"%s: plane (%u,%tu) has been freed, skipping\n",
					__func__, plane->group->index,
					plane - plane->group->planes);
				continue;
			}

			new_plane_state = to_rcar_plane_state(s);
			used_planes |= rcar_du_plane_hwmask(new_plane_state);

			dev_dbg(rcdu->dev,
				"%s: plane (%u,%tu) uses %u hwplanes (index %d)\n",
				__func__, plane->group->index,
				plane - plane->group->planes,
				new_plane_state->format ?
				new_plane_state->format->planes : 0,
				new_plane_state->hwindex);
		}

		group_free_planes[index] = 0xff & ~used_planes;
		groups &= ~(1 << index);

		dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
			__func__, index, group_free_planes[index]);
	}

	/* Reallocate hardware planes for each plane that needs it. */

Annotation

Implementation Notes