drivers/gpu/drm/sun4i/sun8i_vi_layer.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/sun4i/sun8i_vi_layer.c
Extension
.c
Size
12896 bytes
Lines
468
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 (ability < required) {
			DRM_DEBUG_DRIVER("Using vertical coarse scaling\n");
			vm = src_h;
			vn = (u32)ability * dst_h / 100;
			src_h = vn;
		}

		/* it seems that every RGB scaler has buffer for 2048 pixels */
		scanline = subsampled ? layer->cfg->scanline_yuv : 2048;

		if (src_w > scanline) {
			DRM_DEBUG_DRIVER("Using horizontal coarse scaling\n");
			hm = src_w;
			hn = scanline;
			src_w = hn;
		}

		hscale = (src_w << 16) / dst_w;
		vscale = (src_h << 16) / dst_h;

		sun8i_vi_scaler_setup(layer, src_w, src_h, dst_w, dst_h,
				      hscale, vscale, hphase, vphase, format);
		sun8i_vi_scaler_enable(layer, true);
	} else {
		DRM_DEBUG_DRIVER("HW scaling is not needed\n");
		sun8i_vi_scaler_enable(layer, false);
	}

	regmap_write(layer->regs,
		     SUN8I_MIXER_CHAN_VI_HDS_Y(ch_base),
		     SUN8I_MIXER_CHAN_VI_DS_N(hn) |
		     SUN8I_MIXER_CHAN_VI_DS_M(hm));
	regmap_write(layer->regs,
		     SUN8I_MIXER_CHAN_VI_HDS_UV(ch_base),
		     SUN8I_MIXER_CHAN_VI_DS_N(hn) |
		     SUN8I_MIXER_CHAN_VI_DS_M(hm));
	regmap_write(layer->regs,
		     SUN8I_MIXER_CHAN_VI_VDS_Y(ch_base),
		     SUN8I_MIXER_CHAN_VI_DS_N(vn) |
		     SUN8I_MIXER_CHAN_VI_DS_M(vm));
	regmap_write(layer->regs,
		     SUN8I_MIXER_CHAN_VI_VDS_UV(ch_base),
		     SUN8I_MIXER_CHAN_VI_DS_N(vn) |
		     SUN8I_MIXER_CHAN_VI_DS_M(vm));
}

static void sun8i_vi_layer_update_buffer(struct sun8i_layer *layer,
					 struct drm_plane *plane)
{
	struct drm_plane_state *state = plane->state;
	struct drm_framebuffer *fb = state->fb;
	const struct drm_format_info *format = fb->format;
	dma_addr_t dma_addr;
	u32 ch_base;
	int i;

	ch_base = sun8i_channel_base(layer);

	for (i = 0; i < format->num_planes; i++) {
		/* Get the start of the displayed memory */
		dma_addr = drm_fb_dma_get_gem_addr(fb, state, i);

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

		DRM_DEBUG_DRIVER("Setting %d. buffer address to %pad\n",
				 i + 1, &dma_addr);

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

static int sun8i_vi_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;

Annotation

Implementation Notes