drivers/gpu/drm/sun4i/sun8i_ui_layer.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/sun4i/sun8i_ui_layer.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/sun4i/sun8i_ui_layer.c
Extension
.c
Size
8370 bytes
Lines
297
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 (layer->cfg->de_type == SUN8I_MIXER_DE33) {
			sun8i_vi_scaler_setup(layer, src_w, src_h, dst_w, dst_h,
					      hscale, vscale, hphase, vphase,
					      state->fb->format);
			sun8i_vi_scaler_enable(layer, true);
		} else {
			sun8i_ui_scaler_setup(layer, src_w, src_h, dst_w, dst_h,
					      hscale, vscale, hphase, vphase);
			sun8i_ui_scaler_enable(layer, true);
		}
	} else {
		DRM_DEBUG_DRIVER("HW scaling is not needed\n");
		if (layer->cfg->de_type == SUN8I_MIXER_DE33)
			sun8i_vi_scaler_enable(layer, false);
		else
			sun8i_ui_scaler_enable(layer, false);
	}
}

static void sun8i_ui_layer_update_buffer(struct sun8i_layer *layer,
					 struct drm_plane *plane)
{
	struct drm_plane_state *state = plane->state;
	struct drm_framebuffer *fb = state->fb;
	dma_addr_t dma_addr;
	u32 ch_base;

	ch_base = sun8i_channel_base(layer);

	/* Get the start of the displayed memory */
	dma_addr = drm_fb_dma_get_gem_addr(fb, state, 0);

	/* Set the line width */
	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
	regmap_write(layer->regs,
		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch_base, layer->overlay),
		     fb->pitches[0]);

	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &dma_addr);

	regmap_write(layer->regs,
		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch_base, layer->overlay),
		     lower_32_bits(dma_addr));
}

static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
				       struct drm_atomic_commit *state)
{
	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
										 plane);
	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
	struct drm_crtc *crtc = new_plane_state->crtc;
	struct drm_crtc_state *crtc_state;
	const struct drm_format_info *fmt;
	int min_scale, max_scale, ret;
	u32 hw_fmt;

	if (!crtc)
		return 0;

	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
	if (WARN_ON(!crtc_state))
		return -EINVAL;

	fmt = new_plane_state->fb->format;
	ret = sun8i_mixer_drm_format_to_hw(fmt->format, &hw_fmt);
	if (ret || fmt->is_yuv) {
		DRM_DEBUG_DRIVER("Invalid plane format\n");
		return -EINVAL;
	}

	min_scale = DRM_PLANE_NO_SCALING;
	max_scale = DRM_PLANE_NO_SCALING;

	if (layer->cfg->scaler_mask & BIT(layer->channel)) {
		min_scale = SUN8I_UI_SCALER_SCALE_MIN;
		max_scale = SUN8I_UI_SCALER_SCALE_MAX;
	}

	return drm_atomic_helper_check_plane_state(new_plane_state,
						   crtc_state,
						   min_scale, max_scale,
						   true, true);
}


static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
					 struct drm_atomic_commit *state)
{
	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,

Annotation

Implementation Notes