[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
|
To compile this driver as a module, choose M here: the module
|
||||||
will be called vsp1.
|
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
|
config VIDEO_TI_VPE
|
||||||
tristate "TI VPE (Video Processing Engine) driver"
|
tristate "TI VPE (Video Processing Engine) driver"
|
||||||
depends on VIDEO_DEV && VIDEO_V4L2
|
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_JPU) += rcar_jpu.o
|
||||||
obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/
|
obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/
|
||||||
|
|
||||||
|
obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip/rga/
|
||||||
|
|
||||||
obj-y += omap/
|
obj-y += omap/
|
||||||
|
|
||||||
obj-$(CONFIG_VIDEO_AM437X_VPFE) += am437x/
|
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