[media] rockchip/rga: v4l2 m2m support
Rockchip RGA is a separate 2D raster graphic acceleration unit. It accelerates 2D graphics operations, such as point/line drawing, image scaling, rotation, BitBLT, alpha blending and image blur/sharpness The driver supports various operations from the rendering pipeline. - copy - fast solid color fill - rotation - flip - alpha blending The code in rga-hw.c is used to configure regs according to operations The code in rga-buf.c is used to create private mmu table for RGA. Signed-off-by: Jacob Chen <jacob-chen@iotwrt.com> Signed-off-by: Hans Verkuil <hansverk@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
This commit is contained in:
		
							parent
							
								
									7ef3b44cea
								
							
						
					
					
						commit
						f7e7b48e6d
					
				| @ -458,6 +458,21 @@ config VIDEO_RENESAS_VSP1 | ||||
| 	  To compile this driver as a module, choose M here: the module | ||||
| 	  will be called vsp1. | ||||
| 
 | ||||
| config VIDEO_ROCKCHIP_RGA | ||||
| 	tristate "Rockchip Raster 2d Graphic Acceleration Unit" | ||||
| 	depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA | ||||
| 	depends on ARCH_ROCKCHIP || COMPILE_TEST | ||||
| 	select VIDEOBUF2_DMA_SG | ||||
| 	select V4L2_MEM2MEM_DEV | ||||
| 	default n | ||||
| 	---help--- | ||||
| 	  This is a v4l2 driver for Rockchip SOC RGA 2d graphics accelerator. | ||||
| 	  Rockchip RGA is a separate 2D raster graphic acceleration unit. | ||||
| 	  It accelerates 2D graphics operations, such as point/line drawing, | ||||
| 	  image scaling, rotation, BitBLT, alpha blending and image blur/sharpness. | ||||
| 
 | ||||
| 	  To compile this driver as a module choose m here. | ||||
| 
 | ||||
| config VIDEO_TI_VPE | ||||
| 	tristate "TI VPE (Video Processing Engine) driver" | ||||
| 	depends on VIDEO_DEV && VIDEO_V4L2 | ||||
|  | ||||
| @ -64,6 +64,8 @@ obj-$(CONFIG_VIDEO_RENESAS_FDP1)	+= rcar_fdp1.o | ||||
| obj-$(CONFIG_VIDEO_RENESAS_JPU) 	+= rcar_jpu.o | ||||
| obj-$(CONFIG_VIDEO_RENESAS_VSP1)	+= vsp1/ | ||||
| 
 | ||||
| obj-$(CONFIG_VIDEO_ROCKCHIP_RGA)	+= rockchip/rga/ | ||||
| 
 | ||||
| obj-y	+= omap/ | ||||
| 
 | ||||
| obj-$(CONFIG_VIDEO_AM437X_VPFE)		+= am437x/ | ||||
|  | ||||
							
								
								
									
										3
									
								
								drivers/media/platform/rockchip/rga/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								drivers/media/platform/rockchip/rga/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| rockchip-rga-objs := rga.o rga-hw.o rga-buf.o | ||||
| 
 | ||||
| obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip-rga.o | ||||
							
								
								
									
										154
									
								
								drivers/media/platform/rockchip/rga/rga-buf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								drivers/media/platform/rockchip/rga/rga-buf.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,154 @@ | ||||
| /*
 | ||||
|  * Copyright (C) 2017 Fuzhou Rockchip Electronics Co.Ltd | ||||
|  * Author: Jacob Chen <jacob-chen@iotwrt.com> | ||||
|  * | ||||
|  * This software is licensed under the terms of the GNU General Public | ||||
|  * License version 2, as published by the Free Software Foundation, and | ||||
|  * may be copied, distributed, and modified under those terms. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/pm_runtime.h> | ||||
| 
 | ||||
| #include <media/v4l2-device.h> | ||||
| #include <media/v4l2-ioctl.h> | ||||
| #include <media/v4l2-mem2mem.h> | ||||
| #include <media/videobuf2-dma-sg.h> | ||||
| #include <media/videobuf2-v4l2.h> | ||||
| 
 | ||||
| #include "rga-hw.h" | ||||
| #include "rga.h" | ||||
| 
 | ||||
| static int | ||||
| rga_queue_setup(struct vb2_queue *vq, | ||||
| 		unsigned int *nbuffers, unsigned int *nplanes, | ||||
| 		unsigned int sizes[], struct device *alloc_devs[]) | ||||
| { | ||||
| 	struct rga_ctx *ctx = vb2_get_drv_priv(vq); | ||||
| 	struct rga_frame *f = rga_get_frame(ctx, vq->type); | ||||
| 
 | ||||
| 	if (IS_ERR(f)) | ||||
| 		return PTR_ERR(f); | ||||
| 
 | ||||
| 	if (*nplanes) | ||||
| 		return sizes[0] < f->size ? -EINVAL : 0; | ||||
| 
 | ||||
| 	sizes[0] = f->size; | ||||
| 	*nplanes = 1; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int rga_buf_prepare(struct vb2_buffer *vb) | ||||
| { | ||||
| 	struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||||
| 	struct rga_frame *f = rga_get_frame(ctx, vb->vb2_queue->type); | ||||
| 
 | ||||
| 	if (IS_ERR(f)) | ||||
| 		return PTR_ERR(f); | ||||
| 
 | ||||
| 	vb2_set_plane_payload(vb, 0, f->size); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void rga_buf_queue(struct vb2_buffer *vb) | ||||
| { | ||||
| 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | ||||
| 	struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||||
| 
 | ||||
| 	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); | ||||
| } | ||||
| 
 | ||||
| static int rga_buf_start_streaming(struct vb2_queue *q, unsigned int count) | ||||
| { | ||||
| 	struct rga_ctx *ctx = vb2_get_drv_priv(q); | ||||
| 	struct rockchip_rga *rga = ctx->rga; | ||||
| 	int ret, i; | ||||
| 
 | ||||
| 	ret = pm_runtime_get_sync(rga->dev); | ||||
| 
 | ||||
| 	if (!ret) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	for (i = 0; i < q->num_buffers; ++i) { | ||||
| 		if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) { | ||||
| 			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(q->bufs[i]), | ||||
| 					  VB2_BUF_STATE_QUEUED); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static void rga_buf_stop_streaming(struct vb2_queue *q) | ||||
| { | ||||
| 	struct rga_ctx *ctx = vb2_get_drv_priv(q); | ||||
| 	struct rockchip_rga *rga = ctx->rga; | ||||
| 	struct vb2_v4l2_buffer *vbuf; | ||||
| 
 | ||||
| 	for (;;) { | ||||
| 		if (V4L2_TYPE_IS_OUTPUT(q->type)) | ||||
| 			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); | ||||
| 		else | ||||
| 			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); | ||||
| 		if (!vbuf) | ||||
| 			break; | ||||
| 		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); | ||||
| 	} | ||||
| 
 | ||||
| 	pm_runtime_put(rga->dev); | ||||
| } | ||||
| 
 | ||||
| const struct vb2_ops rga_qops = { | ||||
| 	.queue_setup = rga_queue_setup, | ||||
| 	.buf_prepare = rga_buf_prepare, | ||||
| 	.buf_queue = rga_buf_queue, | ||||
| 	.wait_prepare = vb2_ops_wait_prepare, | ||||
| 	.wait_finish = vb2_ops_wait_finish, | ||||
| 	.start_streaming = rga_buf_start_streaming, | ||||
| 	.stop_streaming = rga_buf_stop_streaming, | ||||
| }; | ||||
| 
 | ||||
| /* RGA MMU is a 1-Level MMU, so it can't be used through the IOMMU API.
 | ||||
|  * We use it more like a scatter-gather list. | ||||
|  */ | ||||
| void rga_buf_map(struct vb2_buffer *vb) | ||||
| { | ||||
| 	struct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||||
| 	struct rockchip_rga *rga = ctx->rga; | ||||
| 	struct sg_table *sgt; | ||||
| 	struct scatterlist *sgl; | ||||
| 	unsigned int *pages; | ||||
| 	unsigned int address, len, i, p; | ||||
| 	unsigned int mapped_size = 0; | ||||
| 
 | ||||
| 	if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||||
| 		pages = rga->src_mmu_pages; | ||||
| 	else | ||||
| 		pages = rga->dst_mmu_pages; | ||||
| 
 | ||||
| 	/* Create local MMU table for RGA */ | ||||
| 	sgt = vb2_plane_cookie(vb, 0); | ||||
| 
 | ||||
| 	for_each_sg(sgt->sgl, sgl, sgt->nents, i) { | ||||
| 		len = sg_dma_len(sgl) >> PAGE_SHIFT; | ||||
| 		address = sg_phys(sgl); | ||||
| 
 | ||||
| 		for (p = 0; p < len; p++) { | ||||
| 			dma_addr_t phys = address + (p << PAGE_SHIFT); | ||||
| 
 | ||||
| 			pages[mapped_size + p] = phys; | ||||
| 		} | ||||
| 
 | ||||
| 		mapped_size += len; | ||||
| 	} | ||||
| 
 | ||||
| 	/* sync local MMU table for RGA */ | ||||
| 	dma_sync_single_for_device(rga->dev, virt_to_phys(pages), | ||||
| 				   8 * PAGE_SIZE, DMA_BIDIRECTIONAL); | ||||
| } | ||||
							
								
								
									
										421
									
								
								drivers/media/platform/rockchip/rga/rga-hw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										421
									
								
								drivers/media/platform/rockchip/rga/rga-hw.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,421 @@ | ||||
| /*
 | ||||
|  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd | ||||
|  * Author: Jacob Chen <jacob-chen@iotwrt.com> | ||||
|  * | ||||
|  * This software is licensed under the terms of the GNU General Public | ||||
|  * License version 2, as published by the Free Software Foundation, and | ||||
|  * may be copied, distributed, and modified under those terms. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/pm_runtime.h> | ||||
| 
 | ||||
| #include "rga-hw.h" | ||||
| #include "rga.h" | ||||
| 
 | ||||
| enum e_rga_start_pos { | ||||
| 	LT = 0, | ||||
| 	LB = 1, | ||||
| 	RT = 2, | ||||
| 	RB = 3, | ||||
| }; | ||||
| 
 | ||||
| struct rga_addr_offset { | ||||
| 	unsigned int y_off; | ||||
| 	unsigned int u_off; | ||||
| 	unsigned int v_off; | ||||
| }; | ||||
| 
 | ||||
| struct rga_corners_addr_offset { | ||||
| 	struct rga_addr_offset left_top; | ||||
| 	struct rga_addr_offset right_top; | ||||
| 	struct rga_addr_offset left_bottom; | ||||
| 	struct rga_addr_offset 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_addr_offset | ||||
| rga_get_addr_offset(struct rga_frame *frm, unsigned int x, unsigned int y, | ||||
| 		    unsigned int w, unsigned int h) | ||||
| { | ||||
| 	struct rga_corners_addr_offset offsets; | ||||
| 	struct rga_addr_offset *lt, *lb, *rt, *rb; | ||||
| 	unsigned int x_div = 0, | ||||
| 		     y_div = 0, uv_stride = 0, pixel_width = 0, uv_factor = 0; | ||||
| 
 | ||||
| 	lt = &offsets.left_top; | ||||
| 	lb = &offsets.left_bottom; | ||||
| 	rt = &offsets.right_top; | ||||
| 	rb = &offsets.right_bottom; | ||||
| 
 | ||||
| 	x_div = frm->fmt->x_div; | ||||
| 	y_div = frm->fmt->y_div; | ||||
| 	uv_factor = frm->fmt->uv_factor; | ||||
| 	uv_stride = frm->stride / x_div; | ||||
| 	pixel_width = frm->stride / frm->width; | ||||
| 
 | ||||
| 	lt->y_off = y * frm->stride + x * pixel_width; | ||||
| 	lt->u_off = | ||||
| 		frm->width * frm->height + (y / y_div) * uv_stride + x / x_div; | ||||
| 	lt->v_off = lt->u_off + frm->width * frm->height / uv_factor; | ||||
| 
 | ||||
| 	lb->y_off = lt->y_off + (h - 1) * frm->stride; | ||||
| 	lb->u_off = lt->u_off + (h / y_div - 1) * uv_stride; | ||||
| 	lb->v_off = lt->v_off + (h / y_div - 1) * uv_stride; | ||||
| 
 | ||||
| 	rt->y_off = lt->y_off + (w - 1) * pixel_width; | ||||
| 	rt->u_off = lt->u_off + w / x_div - 1; | ||||
| 	rt->v_off = lt->v_off + w / x_div - 1; | ||||
| 
 | ||||
| 	rb->y_off = lb->y_off + (w - 1) * pixel_width; | ||||
| 	rb->u_off = lb->u_off + w / x_div - 1; | ||||
| 	rb->v_off = lb->v_off + w / x_div - 1; | ||||
| 
 | ||||
| 	return offsets; | ||||
| } | ||||
| 
 | ||||
| static struct rga_addr_offset *rga_lookup_draw_pos(struct | ||||
| 		rga_corners_addr_offset | ||||
| 		* offsets, 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 (!offsets) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	switch (rot_mir_point_matrix[rotate_mode][mirr_mode]) { | ||||
| 	case LT: | ||||
| 		return &offsets->left_top; | ||||
| 	case LB: | ||||
| 		return &offsets->left_bottom; | ||||
| 	case RT: | ||||
| 		return &offsets->right_top; | ||||
| 	case RB: | ||||
| 		return &offsets->right_bottom; | ||||
| 	} | ||||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static void rga_cmd_set_src_addr(struct rga_ctx *ctx, void *mmu_pages) | ||||
| { | ||||
| 	struct rockchip_rga *rga = ctx->rga; | ||||
| 	u32 *dest = rga->cmdbuf_virt; | ||||
| 	unsigned int reg; | ||||
| 
 | ||||
| 	reg = RGA_MMU_SRC_BASE - RGA_MODE_BASE_REG; | ||||
| 	dest[reg >> 2] = virt_to_phys(mmu_pages) >> 4; | ||||
| 
 | ||||
| 	reg = RGA_MMU_CTRL1 - RGA_MODE_BASE_REG; | ||||
| 	dest[reg >> 2] |= 0x7; | ||||
| } | ||||
| 
 | ||||
| static void rga_cmd_set_src1_addr(struct rga_ctx *ctx, void *mmu_pages) | ||||
| { | ||||
| 	struct rockchip_rga *rga = ctx->rga; | ||||
| 	u32 *dest = rga->cmdbuf_virt; | ||||
| 	unsigned int reg; | ||||
| 
 | ||||
| 	reg = RGA_MMU_SRC1_BASE - RGA_MODE_BASE_REG; | ||||
| 	dest[reg >> 2] = virt_to_phys(mmu_pages) >> 4; | ||||
| 
 | ||||
| 	reg = RGA_MMU_CTRL1 - RGA_MODE_BASE_REG; | ||||
| 	dest[reg >> 2] |= 0x7 << 4; | ||||
| } | ||||
| 
 | ||||
| static void rga_cmd_set_dst_addr(struct rga_ctx *ctx, void *mmu_pages) | ||||
| { | ||||
| 	struct rockchip_rga *rga = ctx->rga; | ||||
| 	u32 *dest = rga->cmdbuf_virt; | ||||
| 	unsigned int reg; | ||||
| 
 | ||||
| 	reg = RGA_MMU_DST_BASE - RGA_MODE_BASE_REG; | ||||
| 	dest[reg >> 2] = virt_to_phys(mmu_pages) >> 4; | ||||
| 
 | ||||
| 	reg = RGA_MMU_CTRL1 - RGA_MODE_BASE_REG; | ||||
| 	dest[reg >> 2] |= 0x7 << 8; | ||||
| } | ||||
| 
 | ||||
| static void rga_cmd_set_trans_info(struct rga_ctx *ctx) | ||||
| { | ||||
| 	struct rockchip_rga *rga = ctx->rga; | ||||
| 	u32 *dest = rga->cmdbuf_virt; | ||||
| 	unsigned int scale_dst_w, scale_dst_h; | ||||
| 	unsigned int src_h, src_w, src_x, src_y, dst_h, dst_w, dst_x, dst_y; | ||||
| 	union rga_src_info src_info; | ||||
| 	union rga_dst_info dst_info; | ||||
| 	union rga_src_x_factor x_factor; | ||||
| 	union rga_src_y_factor y_factor; | ||||
| 	union rga_src_vir_info src_vir_info; | ||||
| 	union rga_src_act_info src_act_info; | ||||
| 	union rga_dst_vir_info dst_vir_info; | ||||
| 	union rga_dst_act_info dst_act_info; | ||||
| 
 | ||||
| 	struct rga_addr_offset *dst_offset; | ||||
| 	struct rga_corners_addr_offset offsets; | ||||
| 	struct rga_corners_addr_offset src_offsets; | ||||
| 
 | ||||
| 	src_h = ctx->in.crop.height; | ||||
| 	src_w = ctx->in.crop.width; | ||||
| 	src_x = ctx->in.crop.left; | ||||
| 	src_y = ctx->in.crop.top; | ||||
| 	dst_h = ctx->out.crop.height; | ||||
| 	dst_w = ctx->out.crop.width; | ||||
| 	dst_x = ctx->out.crop.left; | ||||
| 	dst_y = ctx->out.crop.top; | ||||
| 
 | ||||
| 	src_info.val = dest[(RGA_SRC_INFO - RGA_MODE_BASE_REG) >> 2]; | ||||
| 	dst_info.val = dest[(RGA_DST_INFO - RGA_MODE_BASE_REG) >> 2]; | ||||
| 	x_factor.val = dest[(RGA_SRC_X_FACTOR - RGA_MODE_BASE_REG) >> 2]; | ||||
| 	y_factor.val = dest[(RGA_SRC_Y_FACTOR - RGA_MODE_BASE_REG) >> 2]; | ||||
| 	src_vir_info.val = dest[(RGA_SRC_VIR_INFO - RGA_MODE_BASE_REG) >> 2]; | ||||
| 	src_act_info.val = dest[(RGA_SRC_ACT_INFO - RGA_MODE_BASE_REG) >> 2]; | ||||
| 	dst_vir_info.val = dest[(RGA_DST_VIR_INFO - RGA_MODE_BASE_REG) >> 2]; | ||||
| 	dst_act_info.val = dest[(RGA_DST_ACT_INFO - RGA_MODE_BASE_REG) >> 2]; | ||||
| 
 | ||||
| 	src_info.data.format = ctx->in.fmt->hw_format; | ||||
| 	src_info.data.swap = ctx->in.fmt->color_swap; | ||||
| 	dst_info.data.format = ctx->out.fmt->hw_format; | ||||
| 	dst_info.data.swap = ctx->out.fmt->color_swap; | ||||
| 
 | ||||
| 	if (ctx->in.fmt->hw_format >= RGA_COLOR_FMT_YUV422SP) { | ||||
| 		if (ctx->out.fmt->hw_format < RGA_COLOR_FMT_YUV422SP) { | ||||
| 			switch (ctx->in.colorspace) { | ||||
| 			case V4L2_COLORSPACE_REC709: | ||||
| 				src_info.data.csc_mode = | ||||
| 					RGA_SRC_CSC_MODE_BT709_R0; | ||||
| 				break; | ||||
| 			default: | ||||
| 				src_info.data.csc_mode = | ||||
| 					RGA_SRC_CSC_MODE_BT601_R0; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (ctx->out.fmt->hw_format >= RGA_COLOR_FMT_YUV422SP) { | ||||
| 		switch (ctx->out.colorspace) { | ||||
| 		case V4L2_COLORSPACE_REC709: | ||||
| 			dst_info.data.csc_mode = RGA_SRC_CSC_MODE_BT709_R0; | ||||
| 			break; | ||||
| 		default: | ||||
| 			dst_info.data.csc_mode = RGA_DST_CSC_MODE_BT601_R0; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (ctx->vflip) | ||||
| 		src_info.data.mir_mode |= RGA_SRC_MIRR_MODE_X; | ||||
| 
 | ||||
| 	if (ctx->hflip) | ||||
| 		src_info.data.mir_mode |= RGA_SRC_MIRR_MODE_Y; | ||||
| 
 | ||||
| 	switch (ctx->rotate) { | ||||
| 	case 90: | ||||
| 		src_info.data.rot_mode = RGA_SRC_ROT_MODE_90_DEGREE; | ||||
| 		break; | ||||
| 	case 180: | ||||
| 		src_info.data.rot_mode = RGA_SRC_ROT_MODE_180_DEGREE; | ||||
| 		break; | ||||
| 	case 270: | ||||
| 		src_info.data.rot_mode = RGA_SRC_ROT_MODE_270_DEGREE; | ||||
| 		break; | ||||
| 	default: | ||||
| 		src_info.data.rot_mode = RGA_SRC_ROT_MODE_0_DEGREE; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Cacluate the up/down scaling mode/factor. | ||||
| 	 * | ||||
| 	 * RGA used to scale the picture first, and then rotate second, | ||||
| 	 * so we need to swap the w/h when rotate degree is 90/270. | ||||
| 	 */ | ||||
| 	if (src_info.data.rot_mode == RGA_SRC_ROT_MODE_90_DEGREE || | ||||
| 	    src_info.data.rot_mode == RGA_SRC_ROT_MODE_270_DEGREE) { | ||||
| 		if (rga->version.major == 0 || rga->version.minor == 0) { | ||||
| 			if (dst_w == src_h) | ||||
| 				src_h -= 8; | ||||
| 			if (abs(src_w - dst_h) < 16) | ||||
| 				src_w -= 16; | ||||
| 		} | ||||
| 
 | ||||
| 		scale_dst_h = dst_w; | ||||
| 		scale_dst_w = dst_h; | ||||
| 	} else { | ||||
| 		scale_dst_w = dst_w; | ||||
| 		scale_dst_h = dst_h; | ||||
| 	} | ||||
| 
 | ||||
| 	if (src_w == scale_dst_w) { | ||||
| 		src_info.data.hscl_mode = RGA_SRC_HSCL_MODE_NO; | ||||
| 		x_factor.val = 0; | ||||
| 	} else if (src_w > scale_dst_w) { | ||||
| 		src_info.data.hscl_mode = RGA_SRC_HSCL_MODE_DOWN; | ||||
| 		x_factor.data.down_scale_factor = | ||||
| 			rga_get_scaling(src_w, scale_dst_w) + 1; | ||||
| 	} else { | ||||
| 		src_info.data.hscl_mode = RGA_SRC_HSCL_MODE_UP; | ||||
| 		x_factor.data.up_scale_factor = | ||||
| 			rga_get_scaling(src_w - 1, scale_dst_w - 1); | ||||
| 	} | ||||
| 
 | ||||
| 	if (src_h == scale_dst_h) { | ||||
| 		src_info.data.vscl_mode = RGA_SRC_VSCL_MODE_NO; | ||||
| 		y_factor.val = 0; | ||||
| 	} else if (src_h > scale_dst_h) { | ||||
| 		src_info.data.vscl_mode = RGA_SRC_VSCL_MODE_DOWN; | ||||
| 		y_factor.data.down_scale_factor = | ||||
| 			rga_get_scaling(src_h, scale_dst_h) + 1; | ||||
| 	} else { | ||||
| 		src_info.data.vscl_mode = RGA_SRC_VSCL_MODE_UP; | ||||
| 		y_factor.data.up_scale_factor = | ||||
| 			rga_get_scaling(src_h - 1, scale_dst_h - 1); | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Cacluate the framebuffer virtual strides and active size, | ||||
| 	 * note that the step of vir_stride / vir_width is 4 byte words | ||||
| 	 */ | ||||
| 	src_vir_info.data.vir_stride = ctx->in.stride >> 2; | ||||
| 	src_vir_info.data.vir_width = ctx->in.stride >> 2; | ||||
| 
 | ||||
| 	src_act_info.data.act_height = src_h - 1; | ||||
| 	src_act_info.data.act_width = src_w - 1; | ||||
| 
 | ||||
| 	dst_vir_info.data.vir_stride = ctx->out.stride >> 2; | ||||
| 	dst_act_info.data.act_height = dst_h - 1; | ||||
| 	dst_act_info.data.act_width = dst_w - 1; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Cacluate the source framebuffer base address with offset pixel. | ||||
| 	 */ | ||||
| 	src_offsets = rga_get_addr_offset(&ctx->in, src_x, src_y, | ||||
| 					  src_w, src_h); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Configure the dest framebuffer base address with pixel offset. | ||||
| 	 */ | ||||
| 	offsets = rga_get_addr_offset(&ctx->out, dst_x, dst_y, dst_w, dst_h); | ||||
| 	dst_offset = rga_lookup_draw_pos(&offsets, src_info.data.rot_mode, | ||||
| 					 src_info.data.mir_mode); | ||||
| 
 | ||||
| 	dest[(RGA_SRC_Y_RGB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = | ||||
| 		src_offsets.left_top.y_off; | ||||
| 	dest[(RGA_SRC_CB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = | ||||
| 		src_offsets.left_top.u_off; | ||||
| 	dest[(RGA_SRC_CR_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = | ||||
| 		src_offsets.left_top.v_off; | ||||
| 
 | ||||
| 	dest[(RGA_SRC_X_FACTOR - RGA_MODE_BASE_REG) >> 2] = x_factor.val; | ||||
| 	dest[(RGA_SRC_Y_FACTOR - RGA_MODE_BASE_REG) >> 2] = y_factor.val; | ||||
| 	dest[(RGA_SRC_VIR_INFO - RGA_MODE_BASE_REG) >> 2] = src_vir_info.val; | ||||
| 	dest[(RGA_SRC_ACT_INFO - RGA_MODE_BASE_REG) >> 2] = src_act_info.val; | ||||
| 
 | ||||
| 	dest[(RGA_SRC_INFO - RGA_MODE_BASE_REG) >> 2] = src_info.val; | ||||
| 
 | ||||
| 	dest[(RGA_DST_Y_RGB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = | ||||
| 		dst_offset->y_off; | ||||
| 	dest[(RGA_DST_CB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = | ||||
| 		dst_offset->u_off; | ||||
| 	dest[(RGA_DST_CR_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = | ||||
| 		dst_offset->v_off; | ||||
| 
 | ||||
| 	dest[(RGA_DST_VIR_INFO - RGA_MODE_BASE_REG) >> 2] = dst_vir_info.val; | ||||
| 	dest[(RGA_DST_ACT_INFO - RGA_MODE_BASE_REG) >> 2] = dst_act_info.val; | ||||
| 
 | ||||
| 	dest[(RGA_DST_INFO - RGA_MODE_BASE_REG) >> 2] = dst_info.val; | ||||
| } | ||||
| 
 | ||||
| static void rga_cmd_set_mode(struct rga_ctx *ctx) | ||||
| { | ||||
| 	struct rockchip_rga *rga = ctx->rga; | ||||
| 	u32 *dest = rga->cmdbuf_virt; | ||||
| 	union rga_mode_ctrl mode; | ||||
| 	union rga_alpha_ctrl0 alpha_ctrl0; | ||||
| 	union rga_alpha_ctrl1 alpha_ctrl1; | ||||
| 
 | ||||
| 	mode.val = 0; | ||||
| 	alpha_ctrl0.val = 0; | ||||
| 	alpha_ctrl1.val = 0; | ||||
| 
 | ||||
| 	mode.data.gradient_sat = 1; | ||||
| 	mode.data.render = RGA_MODE_RENDER_BITBLT; | ||||
| 	mode.data.bitblt = RGA_MODE_BITBLT_MODE_SRC_TO_DST; | ||||
| 
 | ||||
| 	/* disable alpha blending */ | ||||
| 	dest[(RGA_ALPHA_CTRL0 - RGA_MODE_BASE_REG) >> 2] = alpha_ctrl0.val; | ||||
| 	dest[(RGA_ALPHA_CTRL1 - RGA_MODE_BASE_REG) >> 2] = alpha_ctrl1.val; | ||||
| 
 | ||||
| 	dest[(RGA_MODE_CTRL - RGA_MODE_BASE_REG) >> 2] = mode.val; | ||||
| } | ||||
| 
 | ||||
| void rga_cmd_set(struct rga_ctx *ctx) | ||||
| { | ||||
| 	struct rockchip_rga *rga = ctx->rga; | ||||
| 
 | ||||
| 	memset(rga->cmdbuf_virt, 0, RGA_CMDBUF_SIZE * 4); | ||||
| 
 | ||||
| 	rga_cmd_set_src_addr(ctx, rga->src_mmu_pages); | ||||
| 	/*
 | ||||
| 	 * Due to hardware bug, | ||||
| 	 * src1 mmu also should be configured when using alpha blending. | ||||
| 	 */ | ||||
| 	rga_cmd_set_src1_addr(ctx, rga->dst_mmu_pages); | ||||
| 
 | ||||
| 	rga_cmd_set_dst_addr(ctx, rga->dst_mmu_pages); | ||||
| 	rga_cmd_set_mode(ctx); | ||||
| 
 | ||||
| 	rga_cmd_set_trans_info(ctx); | ||||
| 
 | ||||
| 	rga_write(rga, RGA_CMD_BASE, rga->cmdbuf_phy); | ||||
| 
 | ||||
| 	/* sync CMD buf for RGA */ | ||||
| 	dma_sync_single_for_device(rga->dev, rga->cmdbuf_phy, | ||||
| 		PAGE_SIZE, DMA_BIDIRECTIONAL); | ||||
| } | ||||
| 
 | ||||
| void rga_hw_start(struct rockchip_rga *rga) | ||||
| { | ||||
| 	struct rga_ctx *ctx = rga->curr; | ||||
| 
 | ||||
| 	rga_cmd_set(ctx); | ||||
| 
 | ||||
| 	rga_write(rga, RGA_SYS_CTRL, 0x00); | ||||
| 
 | ||||
| 	rga_write(rga, RGA_SYS_CTRL, 0x22); | ||||
| 
 | ||||
| 	rga_write(rga, RGA_INT, 0x600); | ||||
| 
 | ||||
| 	rga_write(rga, RGA_CMD_CTRL, 0x1); | ||||
| } | ||||
							
								
								
									
										437
									
								
								drivers/media/platform/rockchip/rga/rga-hw.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										437
									
								
								drivers/media/platform/rockchip/rga/rga-hw.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,437 @@ | ||||
| /*
 | ||||
|  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd | ||||
|  * Author: Jacob Chen <jacob-chen@iotwrt.com> | ||||
|  * | ||||
|  * This software is licensed under the terms of the GNU General Public | ||||
|  * License version 2, as published by the Free Software Foundation, and | ||||
|  * may be copied, distributed, and modified under those terms. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  */ | ||||
| #ifndef __RGA_HW_H__ | ||||
| #define __RGA_HW_H__ | ||||
| 
 | ||||
| #define RGA_CMDBUF_SIZE 0x20 | ||||
| 
 | ||||
| /* Hardware limits */ | ||||
| #define MAX_WIDTH 8192 | ||||
| #define MAX_HEIGHT 8192 | ||||
| 
 | ||||
| #define MIN_WIDTH 34 | ||||
| #define MIN_HEIGHT 34 | ||||
| 
 | ||||
| #define DEFAULT_WIDTH 100 | ||||
| #define DEFAULT_HEIGHT 100 | ||||
| 
 | ||||
| #define RGA_TIMEOUT 500 | ||||
| 
 | ||||
| /* Registers address */ | ||||
| #define RGA_SYS_CTRL 0x0000 | ||||
| #define RGA_CMD_CTRL 0x0004 | ||||
| #define RGA_CMD_BASE 0x0008 | ||||
| #define RGA_INT 0x0010 | ||||
| #define RGA_MMU_CTRL0 0x0014 | ||||
| #define RGA_VERSION_INFO 0x0028 | ||||
| 
 | ||||
| #define RGA_MODE_BASE_REG 0x0100 | ||||
| #define RGA_MODE_MAX_REG 0x017C | ||||
| 
 | ||||
| #define RGA_MODE_CTRL 0x0100 | ||||
| #define RGA_SRC_INFO 0x0104 | ||||
| #define RGA_SRC_Y_RGB_BASE_ADDR 0x0108 | ||||
| #define RGA_SRC_CB_BASE_ADDR 0x010c | ||||
| #define RGA_SRC_CR_BASE_ADDR 0x0110 | ||||
| #define RGA_SRC1_RGB_BASE_ADDR 0x0114 | ||||
| #define RGA_SRC_VIR_INFO 0x0118 | ||||
| #define RGA_SRC_ACT_INFO 0x011c | ||||
| #define RGA_SRC_X_FACTOR 0x0120 | ||||
| #define RGA_SRC_Y_FACTOR 0x0124 | ||||
| #define RGA_SRC_BG_COLOR 0x0128 | ||||
| #define RGA_SRC_FG_COLOR 0x012c | ||||
| #define RGA_SRC_TR_COLOR0 0x0130 | ||||
| #define RGA_SRC_TR_COLOR1 0x0134 | ||||
| 
 | ||||
| #define RGA_DST_INFO 0x0138 | ||||
| #define RGA_DST_Y_RGB_BASE_ADDR 0x013c | ||||
| #define RGA_DST_CB_BASE_ADDR 0x0140 | ||||
| #define RGA_DST_CR_BASE_ADDR 0x0144 | ||||
| #define RGA_DST_VIR_INFO 0x0148 | ||||
| #define RGA_DST_ACT_INFO 0x014c | ||||
| 
 | ||||
| #define RGA_ALPHA_CTRL0 0x0150 | ||||
| #define RGA_ALPHA_CTRL1 0x0154 | ||||
| #define RGA_FADING_CTRL 0x0158 | ||||
| #define RGA_PAT_CON 0x015c | ||||
| #define RGA_ROP_CON0 0x0160 | ||||
| #define RGA_ROP_CON1 0x0164 | ||||
| #define RGA_MASK_BASE 0x0168 | ||||
| 
 | ||||
| #define RGA_MMU_CTRL1 0x016C | ||||
| #define RGA_MMU_SRC_BASE 0x0170 | ||||
| #define RGA_MMU_SRC1_BASE 0x0174 | ||||
| #define RGA_MMU_DST_BASE 0x0178 | ||||
| 
 | ||||
| /* Registers value */ | ||||
| #define RGA_MODE_RENDER_BITBLT 0 | ||||
| #define RGA_MODE_RENDER_COLOR_PALETTE 1 | ||||
| #define RGA_MODE_RENDER_RECTANGLE_FILL 2 | ||||
| #define RGA_MODE_RENDER_UPDATE_PALETTE_LUT_RAM 3 | ||||
| 
 | ||||
| #define RGA_MODE_BITBLT_MODE_SRC_TO_DST 0 | ||||
| #define RGA_MODE_BITBLT_MODE_SRC_SRC1_TO_DST 1 | ||||
| 
 | ||||
| #define RGA_MODE_CF_ROP4_SOLID 0 | ||||
| #define RGA_MODE_CF_ROP4_PATTERN 1 | ||||
| 
 | ||||
| #define RGA_COLOR_FMT_ABGR8888 0 | ||||
| #define RGA_COLOR_FMT_XBGR8888 1 | ||||
| #define RGA_COLOR_FMT_RGB888 2 | ||||
| #define RGA_COLOR_FMT_BGR565 4 | ||||
| #define RGA_COLOR_FMT_ABGR1555 5 | ||||
| #define RGA_COLOR_FMT_ABGR4444 6 | ||||
| #define RGA_COLOR_FMT_YUV422SP 8 | ||||
| #define RGA_COLOR_FMT_YUV422P 9 | ||||
| #define RGA_COLOR_FMT_YUV420SP 10 | ||||
| #define RGA_COLOR_FMT_YUV420P 11 | ||||
| /* SRC_COLOR Palette */ | ||||
| #define RGA_COLOR_FMT_CP_1BPP 12 | ||||
| #define RGA_COLOR_FMT_CP_2BPP 13 | ||||
| #define RGA_COLOR_FMT_CP_4BPP 14 | ||||
| #define RGA_COLOR_FMT_CP_8BPP 15 | ||||
| #define RGA_COLOR_FMT_MASK 15 | ||||
| 
 | ||||
| #define RGA_COLOR_NONE_SWAP 0 | ||||
| #define RGA_COLOR_RB_SWAP 1 | ||||
| #define RGA_COLOR_ALPHA_SWAP 2 | ||||
| #define RGA_COLOR_UV_SWAP 4 | ||||
| 
 | ||||
| #define RGA_SRC_CSC_MODE_BYPASS 0 | ||||
| #define RGA_SRC_CSC_MODE_BT601_R0 1 | ||||
| #define RGA_SRC_CSC_MODE_BT601_R1 2 | ||||
| #define RGA_SRC_CSC_MODE_BT709_R0 3 | ||||
| #define RGA_SRC_CSC_MODE_BT709_R1 4 | ||||
| 
 | ||||
| #define RGA_SRC_ROT_MODE_0_DEGREE 0 | ||||
| #define RGA_SRC_ROT_MODE_90_DEGREE 1 | ||||
| #define RGA_SRC_ROT_MODE_180_DEGREE 2 | ||||
| #define RGA_SRC_ROT_MODE_270_DEGREE 3 | ||||
| 
 | ||||
| #define RGA_SRC_MIRR_MODE_NO 0 | ||||
| #define RGA_SRC_MIRR_MODE_X 1 | ||||
| #define RGA_SRC_MIRR_MODE_Y 2 | ||||
| #define RGA_SRC_MIRR_MODE_X_Y 3 | ||||
| 
 | ||||
| #define RGA_SRC_HSCL_MODE_NO 0 | ||||
| #define RGA_SRC_HSCL_MODE_DOWN 1 | ||||
| #define RGA_SRC_HSCL_MODE_UP 2 | ||||
| 
 | ||||
| #define RGA_SRC_VSCL_MODE_NO 0 | ||||
| #define RGA_SRC_VSCL_MODE_DOWN 1 | ||||
| #define RGA_SRC_VSCL_MODE_UP 2 | ||||
| 
 | ||||
| #define RGA_SRC_TRANS_ENABLE_R 1 | ||||
| #define RGA_SRC_TRANS_ENABLE_G 2 | ||||
| #define RGA_SRC_TRANS_ENABLE_B 4 | ||||
| #define RGA_SRC_TRANS_ENABLE_A 8 | ||||
| 
 | ||||
| #define RGA_SRC_BIC_COE_SELEC_CATROM 0 | ||||
| #define RGA_SRC_BIC_COE_SELEC_MITCHELL 1 | ||||
| #define RGA_SRC_BIC_COE_SELEC_HERMITE 2 | ||||
| #define RGA_SRC_BIC_COE_SELEC_BSPLINE 3 | ||||
| 
 | ||||
| #define RGA_DST_DITHER_MODE_888_TO_666 0 | ||||
| #define RGA_DST_DITHER_MODE_888_TO_565 1 | ||||
| #define RGA_DST_DITHER_MODE_888_TO_555 2 | ||||
| #define RGA_DST_DITHER_MODE_888_TO_444 3 | ||||
| 
 | ||||
| #define RGA_DST_CSC_MODE_BYPASS 0 | ||||
| #define RGA_DST_CSC_MODE_BT601_R0 1 | ||||
| #define RGA_DST_CSC_MODE_BT601_R1 2 | ||||
| #define RGA_DST_CSC_MODE_BT709_R0 3 | ||||
| 
 | ||||
| #define RGA_ALPHA_ROP_MODE_2 0 | ||||
| #define RGA_ALPHA_ROP_MODE_3 1 | ||||
| #define RGA_ALPHA_ROP_MODE_4 2 | ||||
| 
 | ||||
| #define RGA_ALPHA_SELECT_ALPHA 0 | ||||
| #define RGA_ALPHA_SELECT_ROP 1 | ||||
| 
 | ||||
| #define RGA_ALPHA_MASK_BIG_ENDIAN 0 | ||||
| #define RGA_ALPHA_MASK_LITTLE_ENDIAN 1 | ||||
| 
 | ||||
| #define RGA_ALPHA_NORMAL 0 | ||||
| #define RGA_ALPHA_REVERSE 1 | ||||
| 
 | ||||
| #define RGA_ALPHA_BLEND_GLOBAL 0 | ||||
| #define RGA_ALPHA_BLEND_NORMAL 1 | ||||
| #define RGA_ALPHA_BLEND_MULTIPLY 2 | ||||
| 
 | ||||
| #define RGA_ALPHA_CAL_CUT 0 | ||||
| #define RGA_ALPHA_CAL_NORMAL 1 | ||||
| 
 | ||||
| #define RGA_ALPHA_FACTOR_ZERO 0 | ||||
| #define RGA_ALPHA_FACTOR_ONE 1 | ||||
| #define RGA_ALPHA_FACTOR_OTHER 2 | ||||
| #define RGA_ALPHA_FACTOR_OTHER_REVERSE 3 | ||||
| #define RGA_ALPHA_FACTOR_SELF 4 | ||||
| 
 | ||||
| #define RGA_ALPHA_COLOR_NORMAL 0 | ||||
| #define RGA_ALPHA_COLOR_MULTIPLY_CAL 1 | ||||
| 
 | ||||
| /* Registers union */ | ||||
| union rga_mode_ctrl { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:2] */ | ||||
| 		unsigned int render:3; | ||||
| 		/* [3:6] */ | ||||
| 		unsigned int bitblt:1; | ||||
| 		unsigned int cf_rop4_pat:1; | ||||
| 		unsigned int alpha_zero_key:1; | ||||
| 		unsigned int gradient_sat:1; | ||||
| 		/* [7:31] */ | ||||
| 		unsigned int reserved:25; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_src_info { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:3] */ | ||||
| 		unsigned int format:4; | ||||
| 		/* [4:7] */ | ||||
| 		unsigned int swap:3; | ||||
| 		unsigned int cp_endian:1; | ||||
| 		/* [8:17] */ | ||||
| 		unsigned int csc_mode:2; | ||||
| 		unsigned int rot_mode:2; | ||||
| 		unsigned int mir_mode:2; | ||||
| 		unsigned int hscl_mode:2; | ||||
| 		unsigned int vscl_mode:2; | ||||
| 		/* [18:22] */ | ||||
| 		unsigned int trans_mode:1; | ||||
| 		unsigned int trans_enable:4; | ||||
| 		/* [23:25] */ | ||||
| 		unsigned int dither_up_en:1; | ||||
| 		unsigned int bic_coe_sel:2; | ||||
| 		/* [26:31] */ | ||||
| 		unsigned int reserved:6; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_src_vir_info { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:15] */ | ||||
| 		unsigned int vir_width:15; | ||||
| 		unsigned int reserved:1; | ||||
| 		/* [16:25] */ | ||||
| 		unsigned int vir_stride:10; | ||||
| 		/* [26:31] */ | ||||
| 		unsigned int reserved1:6; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_src_act_info { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:15] */ | ||||
| 		unsigned int act_width:13; | ||||
| 		unsigned int reserved:3; | ||||
| 		/* [16:31] */ | ||||
| 		unsigned int act_height:13; | ||||
| 		unsigned int reserved1:3; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_src_x_factor { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:15] */ | ||||
| 		unsigned int down_scale_factor:16; | ||||
| 		/* [16:31] */ | ||||
| 		unsigned int up_scale_factor:16; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_src_y_factor { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:15] */ | ||||
| 		unsigned int down_scale_factor:16; | ||||
| 		/* [16:31] */ | ||||
| 		unsigned int up_scale_factor:16; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| /* Alpha / Red / Green / Blue */ | ||||
| union rga_src_cp_gr_color { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:15] */ | ||||
| 		unsigned int gradient_x:16; | ||||
| 		/* [16:31] */ | ||||
| 		unsigned int gradient_y:16; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_src_transparency_color0 { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:7] */ | ||||
| 		unsigned int trans_rmin:8; | ||||
| 		/* [8:15] */ | ||||
| 		unsigned int trans_gmin:8; | ||||
| 		/* [16:23] */ | ||||
| 		unsigned int trans_bmin:8; | ||||
| 		/* [24:31] */ | ||||
| 		unsigned int trans_amin:8; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_src_transparency_color1 { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:7] */ | ||||
| 		unsigned int trans_rmax:8; | ||||
| 		/* [8:15] */ | ||||
| 		unsigned int trans_gmax:8; | ||||
| 		/* [16:23] */ | ||||
| 		unsigned int trans_bmax:8; | ||||
| 		/* [24:31] */ | ||||
| 		unsigned int trans_amax:8; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_dst_info { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:3] */ | ||||
| 		unsigned int format:4; | ||||
| 		/* [4:6] */ | ||||
| 		unsigned int swap:3; | ||||
| 		/* [7:9] */ | ||||
| 		unsigned int src1_format:3; | ||||
| 		/* [10:11] */ | ||||
| 		unsigned int src1_swap:2; | ||||
| 		/* [12:15] */ | ||||
| 		unsigned int dither_up_en:1; | ||||
| 		unsigned int dither_down_en:1; | ||||
| 		unsigned int dither_down_mode:2; | ||||
| 		/* [16:18] */ | ||||
| 		unsigned int csc_mode:2; | ||||
| 		unsigned int csc_clip:1; | ||||
| 		/* [19:31] */ | ||||
| 		unsigned int reserved:13; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_dst_vir_info { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:15] */ | ||||
| 		unsigned int vir_stride:15; | ||||
| 		unsigned int reserved:1; | ||||
| 		/* [16:31] */ | ||||
| 		unsigned int src1_vir_stride:15; | ||||
| 		unsigned int reserved1:1; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_dst_act_info { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:15] */ | ||||
| 		unsigned int act_width:12; | ||||
| 		unsigned int reserved:4; | ||||
| 		/* [16:31] */ | ||||
| 		unsigned int act_height:12; | ||||
| 		unsigned int reserved1:4; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_alpha_ctrl0 { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:3] */ | ||||
| 		unsigned int rop_en:1; | ||||
| 		unsigned int rop_select:1; | ||||
| 		unsigned int rop_mode:2; | ||||
| 		/* [4:11] */ | ||||
| 		unsigned int src_fading_val:8; | ||||
| 		/* [12:20] */ | ||||
| 		unsigned int dst_fading_val:8; | ||||
| 		unsigned int mask_endian:1; | ||||
| 		/* [21:31] */ | ||||
| 		unsigned int reserved:11; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_alpha_ctrl1 { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:1] */ | ||||
| 		unsigned int dst_color_m0:1; | ||||
| 		unsigned int src_color_m0:1; | ||||
| 		/* [2:7] */ | ||||
| 		unsigned int dst_factor_m0:3; | ||||
| 		unsigned int src_factor_m0:3; | ||||
| 		/* [8:9] */ | ||||
| 		unsigned int dst_alpha_cal_m0:1; | ||||
| 		unsigned int src_alpha_cal_m0:1; | ||||
| 		/* [10:13] */ | ||||
| 		unsigned int dst_blend_m0:2; | ||||
| 		unsigned int src_blend_m0:2; | ||||
| 		/* [14:15] */ | ||||
| 		unsigned int dst_alpha_m0:1; | ||||
| 		unsigned int src_alpha_m0:1; | ||||
| 		/* [16:21] */ | ||||
| 		unsigned int dst_factor_m1:3; | ||||
| 		unsigned int src_factor_m1:3; | ||||
| 		/* [22:23] */ | ||||
| 		unsigned int dst_alpha_cal_m1:1; | ||||
| 		unsigned int src_alpha_cal_m1:1; | ||||
| 		/* [24:27] */ | ||||
| 		unsigned int dst_blend_m1:2; | ||||
| 		unsigned int src_blend_m1:2; | ||||
| 		/* [28:29] */ | ||||
| 		unsigned int dst_alpha_m1:1; | ||||
| 		unsigned int src_alpha_m1:1; | ||||
| 		/* [30:31] */ | ||||
| 		unsigned int reserved:2; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_fading_ctrl { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:7] */ | ||||
| 		unsigned int fading_offset_r:8; | ||||
| 		/* [8:15] */ | ||||
| 		unsigned int fading_offset_g:8; | ||||
| 		/* [16:23] */ | ||||
| 		unsigned int fading_offset_b:8; | ||||
| 		/* [24:31] */ | ||||
| 		unsigned int fading_en:1; | ||||
| 		unsigned int reserved:7; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| union rga_pat_con { | ||||
| 	unsigned int val; | ||||
| 	struct { | ||||
| 		/* [0:7] */ | ||||
| 		unsigned int width:8; | ||||
| 		/* [8:15] */ | ||||
| 		unsigned int height:8; | ||||
| 		/* [16:23] */ | ||||
| 		unsigned int offset_x:8; | ||||
| 		/* [24:31] */ | ||||
| 		unsigned int offset_y:8; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										1012
									
								
								drivers/media/platform/rockchip/rga/rga.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1012
									
								
								drivers/media/platform/rockchip/rga/rga.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										125
									
								
								drivers/media/platform/rockchip/rga/rga.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								drivers/media/platform/rockchip/rga/rga.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,125 @@ | ||||
| /*
 | ||||
|  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd | ||||
|  * Author: Jacob Chen <jacob-chen@iotwrt.com> | ||||
|  * | ||||
|  * This software is licensed under the terms of the GNU General Public | ||||
|  * License version 2, as published by the Free Software Foundation, and | ||||
|  * may be copied, distributed, and modified under those terms. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  */ | ||||
| #ifndef __RGA_H__ | ||||
| #define __RGA_H__ | ||||
| 
 | ||||
| #include <linux/platform_device.h> | ||||
| #include <media/videobuf2-v4l2.h> | ||||
| #include <media/v4l2-ctrls.h> | ||||
| #include <media/v4l2-device.h> | ||||
| 
 | ||||
| #define RGA_NAME "rockchip-rga" | ||||
| 
 | ||||
| struct rga_fmt { | ||||
| 	u32 fourcc; | ||||
| 	int depth; | ||||
| 	u8 uv_factor; | ||||
| 	u8 y_div; | ||||
| 	u8 x_div; | ||||
| 	u8 color_swap; | ||||
| 	u8 hw_format; | ||||
| }; | ||||
| 
 | ||||
| struct rga_frame { | ||||
| 	/* Original dimensions */ | ||||
| 	u32 width; | ||||
| 	u32 height; | ||||
| 	u32 colorspace; | ||||
| 
 | ||||
| 	/* Crop */ | ||||
| 	struct v4l2_rect crop; | ||||
| 
 | ||||
| 	/* Image format */ | ||||
| 	struct rga_fmt *fmt; | ||||
| 
 | ||||
| 	/* Variables that can calculated once and reused */ | ||||
| 	u32 stride; | ||||
| 	u32 size; | ||||
| }; | ||||
| 
 | ||||
| struct rockchip_rga_version { | ||||
| 	u32 major; | ||||
| 	u32 minor; | ||||
| }; | ||||
| 
 | ||||
| struct rga_ctx { | ||||
| 	struct v4l2_fh fh; | ||||
| 	struct rockchip_rga *rga; | ||||
| 	struct rga_frame in; | ||||
| 	struct rga_frame out; | ||||
| 	struct v4l2_ctrl_handler ctrl_handler; | ||||
| 
 | ||||
| 	/* Control values */ | ||||
| 	u32 op; | ||||
| 	u32 hflip; | ||||
| 	u32 vflip; | ||||
| 	u32 rotate; | ||||
| 	u32 fill_color; | ||||
| }; | ||||
| 
 | ||||
| struct rockchip_rga { | ||||
| 	struct v4l2_device v4l2_dev; | ||||
| 	struct v4l2_m2m_dev *m2m_dev; | ||||
| 	struct video_device *vfd; | ||||
| 
 | ||||
| 	struct device *dev; | ||||
| 	struct regmap *grf; | ||||
| 	void __iomem *regs; | ||||
| 	struct clk *sclk; | ||||
| 	struct clk *aclk; | ||||
| 	struct clk *hclk; | ||||
| 	struct rockchip_rga_version version; | ||||
| 
 | ||||
| 	/* vfd lock */ | ||||
| 	struct mutex mutex; | ||||
| 	/* ctrl parm lock */ | ||||
| 	spinlock_t ctrl_lock; | ||||
| 
 | ||||
| 	wait_queue_head_t irq_queue; | ||||
| 
 | ||||
| 	struct rga_ctx *curr; | ||||
| 	dma_addr_t cmdbuf_phy; | ||||
| 	void *cmdbuf_virt; | ||||
| 	unsigned int *src_mmu_pages; | ||||
| 	unsigned int *dst_mmu_pages; | ||||
| }; | ||||
| 
 | ||||
| struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type type); | ||||
| 
 | ||||
| /* RGA Buffers Manage */ | ||||
| extern const struct vb2_ops rga_qops; | ||||
| void rga_buf_map(struct vb2_buffer *vb); | ||||
| 
 | ||||
| /* RGA Hardware */ | ||||
| static inline void rga_write(struct rockchip_rga *rga, u32 reg, u32 value) | ||||
| { | ||||
| 	writel(value, rga->regs + reg); | ||||
| }; | ||||
| 
 | ||||
| static inline u32 rga_read(struct rockchip_rga *rga, u32 reg) | ||||
| { | ||||
| 	return readl(rga->regs + reg); | ||||
| }; | ||||
| 
 | ||||
| static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask) | ||||
| { | ||||
| 	u32 temp = rga_read(rga, reg) & ~(mask); | ||||
| 
 | ||||
| 	temp |= val & mask; | ||||
| 	rga_write(rga, reg, temp); | ||||
| }; | ||||
| 
 | ||||
| void rga_hw_start(struct rockchip_rga *rga); | ||||
| 
 | ||||
| #endif | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user