drivers/media/platform/rockchip/rga/rga-hw.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/rockchip/rga/rga-hw.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/rockchip/rga/rga-hw.c
Extension
.c
Size
16256 bytes
Lines
616
Domain
Driver Families
Bucket
drivers/media
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 rga_corners_addrs {
	struct rga_addrs left_top;
	struct rga_addrs right_top;
	struct rga_addrs left_bottom;
	struct rga_addrs right_bottom;
};

static unsigned int rga_get_scaling(unsigned int src, unsigned int dst)
{
	/*
	 * The rga hw scaling factor is a normalized inverse of the
	 * scaling factor.
	 * For example: When source width is 100 and destination width is 200
	 * (scaling of 2x), then the hw factor is NC * 100 / 200.
	 * The normalization factor (NC) is 2^16 = 0x10000.
	 */

	return (src > dst) ? ((dst << 16) / src) : ((src << 16) / dst);
}

static struct rga_corners_addrs
rga_get_corner_addrs(struct rga_frame *frm, struct rga_addrs *addrs,
		     unsigned int x, unsigned int y, unsigned int w, unsigned int h)
{
	struct rga_corners_addrs corner_addrs;
	struct rga_addrs *lt, *lb, *rt, *rb;
	const struct v4l2_format_info *format_info;
	unsigned int x_div = 0,
		     y_div = 0, y_stride = 0, uv_stride = 0, pixel_width = 0;

	lt = &corner_addrs.left_top;
	lb = &corner_addrs.left_bottom;
	rt = &corner_addrs.right_top;
	rb = &corner_addrs.right_bottom;

	format_info = v4l2_format_info(frm->pix.pixelformat);
	/* x_div is only used for the u/v planes.
	 * When the format doesn't have these, use 1 to avoid a division by zero.
	 */
	if (format_info->bpp[1])
		x_div = format_info->hdiv * format_info->bpp_div[1] /
			format_info->bpp[1];
	else
		x_div = 1;
	y_div = format_info->vdiv;
	y_stride = frm->pix.plane_fmt[0].bytesperline;
	uv_stride = y_stride / x_div;
	pixel_width = y_stride / frm->pix.width;

	lt->y_addr = addrs->y_addr + y * y_stride + x * pixel_width;
	lt->u_addr = addrs->u_addr + (y / y_div) * uv_stride + x / x_div;
	lt->v_addr = addrs->v_addr + (y / y_div) * uv_stride + x / x_div;

	lb->y_addr = lt->y_addr + (h - 1) * y_stride;
	lb->u_addr = lt->u_addr + (h / y_div - 1) * uv_stride;
	lb->v_addr = lt->v_addr + (h / y_div - 1) * uv_stride;

	rt->y_addr = lt->y_addr + (w - 1) * pixel_width;
	rt->u_addr = lt->u_addr + w / x_div - 1;
	rt->v_addr = lt->v_addr + w / x_div - 1;

	rb->y_addr = lb->y_addr + (w - 1) * pixel_width;
	rb->u_addr = lb->u_addr + w / x_div - 1;
	rb->v_addr = lb->v_addr + w / x_div - 1;

	return corner_addrs;
}

static struct rga_addrs *rga_lookup_draw_pos(struct rga_corners_addrs *corner_addrs,
					     u32 rotate_mode,
					     u32 mirr_mode)
{
	static enum e_rga_start_pos rot_mir_point_matrix[4][4] = {
		{
			LT, RT, LB, RB,
		},
		{
			RT, LT, RB, LB,
		},
		{
			RB, LB, RT, LT,
		},
		{
			LB, RB, LT, RT,
		},
	};

	if (!corner_addrs)
		return NULL;

Annotation

Implementation Notes