Re: [PATCH 1/5] [media] rockchip/rga: v4l2 m2m support

From: Nicolas Dufresne
Date: Tue Jun 27 2017 - 11:49:58 EST


Le mardi 27 juin 2017 Ã 23:11 +0800, Jacob Chen a ÃcritÂ:
> Hi Nicolas.
>
> 2017-06-26 23:49 GMT+08:00 Nicolas Dufresne <nicolas@xxxxxxxxxxxx>:
> >
> > Le lundi 26 juin 2017 Ã 22:51 +0800, Jacob Chen a Ãcrit :
> > > 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 drvier is mostly based on s5p-g2d v4l2 m2m driver.
> > > And 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 accroding to
> > > operations.
> > >
> > > The code in rga-buf.c is used to create private mmu table for
> > > RGA.
> > > The tables is stored in a list, and be removed when buffer is
> > > cleanup.
> > >
> > > Signed-off-by: Jacob Chen <jacob-chen@xxxxxxxxxx>
> > > ---
> > > Âdrivers/media/platform/KconfigÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ|ÂÂ11 +
> > > Âdrivers/media/platform/MakefileÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ|ÂÂÂ2 +
> > > Âdrivers/media/platform/rockchip-rga/MakefileÂÂ|ÂÂÂ3 +
> > > Âdrivers/media/platform/rockchip-rga/rga-buf.c | 176 +++++
> > > Âdrivers/media/platform/rockchip-rga/rga-hw.cÂÂ| 456 ++++++++++++
> > > Âdrivers/media/platform/rockchip-rga/rga-hw.hÂÂ| 434 ++++++++++++
> > > Âdrivers/media/platform/rockchip-rga/rga.cÂÂÂÂÂ| 979
> > > ++++++++++++++++++++++++++
> > > Âdrivers/media/platform/rockchip-rga/rga.hÂÂÂÂÂ| 133 ++++
> > > Â8 files changed, 2194 insertions(+)
> > > Âcreate mode 100644 drivers/media/platform/rockchip-rga/Makefile
> > > Âcreate mode 100644 drivers/media/platform/rockchip-rga/rga-buf.c
> > > Âcreate mode 100644 drivers/media/platform/rockchip-rga/rga-hw.c
> > > Âcreate mode 100644 drivers/media/platform/rockchip-rga/rga-hw.h
> > > Âcreate mode 100644 drivers/media/platform/rockchip-rga/rga.c
> > > Âcreate mode 100644 drivers/media/platform/rockchip-rga/rga.h
> > >
> > > diff --git a/drivers/media/platform/Kconfig
> > > b/drivers/media/platform/Kconfig
> > > index c9106e1..8199bcf 100644
> > > --- a/drivers/media/platform/Kconfig
> > > +++ b/drivers/media/platform/Kconfig
> > > @@ -411,6 +411,17 @@ 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 Grapphic 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 RGA2
> > > +ÂÂÂÂÂÂÂ2d graphics accelerator.
> > > +
> > > Âconfig VIDEO_TI_VPE
> > > ÂÂÂÂÂÂtristate "TI VPE (Video Processing Engine) driver"
> > > ÂÂÂÂÂÂdepends on VIDEO_DEV && VIDEO_V4L2
> > > diff --git a/drivers/media/platform/Makefile
> > > b/drivers/media/platform/Makefile
> > > index 349ddf6..3bf096f 100644
> > > --- a/drivers/media/platform/Makefile
> > > +++ b/drivers/media/platform/Makefile
> > > @@ -54,6 +54,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/
> > > diff --git a/drivers/media/platform/rockchip-rga/Makefile
> > > b/drivers/media/platform/rockchip-rga/Makefile
> > > new file mode 100644
> > > index 0000000..92fe254
> > > --- /dev/null
> > > +++ b/drivers/media/platform/rockchip-rga/Makefile
> > > @@ -0,0 +1,3 @@
> > > +rockchip-rga-objs := rga.o rga-hw.o rga-buf.o
> > > +
> > > +obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip-rga.o
> > > diff --git a/drivers/media/platform/rockchip-rga/rga-buf.c
> > > b/drivers/media/platform/rockchip-rga/rga-buf.c
> > > new file mode 100644
> > > index 0000000..8582092
> > > --- /dev/null
> > > +++ b/drivers/media/platform/rockchip-rga/rga-buf.c
> > > @@ -0,0 +1,176 @@
> > > +/*
> > > + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
> > > + * Author: Jacob Chen <jacob-chen@xxxxxxxxxx>
> > > + *
> > > + * 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);
> > > +
> > > +ÂÂÂÂÂsizes[0] = f->size;
> > > +ÂÂÂÂÂ*nplanes = 1;
> > > +
> > > +ÂÂÂÂÂif (*nbuffers == 0)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ*nbuffers = 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_init(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;
> > > +ÂÂÂÂÂstruct rga_buf *buf;
> > > +ÂÂÂÂÂunsigned int address, len, i, p;
> > > +ÂÂÂÂÂunsigned int mapped_size = 0;
> > > +
> > > +ÂÂÂÂÂ/* Create local MMU table for RGA */
> > > +ÂÂÂÂÂsgt = vb2_plane_cookie(vb, 0);
> > > +
> > > +ÂÂÂÂÂ/*
> > > +ÂÂÂÂÂÂ* Alloc (2^3 * 4K) = 32K byte for storing pages, those
> > > space could
> > > +ÂÂÂÂÂÂ* cover 32K * 4K = 128M ram address.
> > > +ÂÂÂÂÂÂ*/
> > > +ÂÂÂÂÂpages = (unsigned int *)__get_free_pages(GFP_KERNEL |
> > > __GFP_ZERO, 3);
> > > +
> > > +ÂÂÂÂÂ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);
> > > +
> > > +ÂÂÂÂÂ/* Store the buffer to the RGA private buffers list */
> > > +ÂÂÂÂÂbuf = kmalloc(sizeof(struct rga_buf), GFP_KERNEL);
> > > +ÂÂÂÂÂbuf->index = vb->index;
> > > +ÂÂÂÂÂbuf->type = vb->type;
> > > +ÂÂÂÂÂbuf->mmu_pages = pages;
> > > +
> > > +ÂÂÂÂÂlist_add_tail(&buf->entry, &ctx->buffers_list);
> > > +
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static void rga_buf_cleanup(struct vb2_buffer *vb)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
> > > +ÂÂÂÂÂstruct rga_buf *buf, *tmp;
> > > +
> > > +ÂÂÂÂÂ/* Release the RGA private buffers */
> > > +ÂÂÂÂÂlist_for_each_entry_safe(buf, tmp, &ctx->buffers_list,
> > > entry) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂif (buf->index == vb->index && buf->type == vb-
> > > > type) {
> > >
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂfree_pages((unsigned long)buf->mmu_pages,
> > > 3);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂlist_del(&buf->entry);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂkfree(buf);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ}
> > > +ÂÂÂÂÂ}
> > > +}
> > > +
> > > +static void rga_buf_stop_streaming(struct vb2_queue *q)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = vb2_get_drv_priv(q);
> > > +ÂÂÂÂÂ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 == NULL)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
> > > +ÂÂÂÂÂ}
> > > +}
> > > +
> > > +const struct vb2_ops rga_qops = {
> > > +ÂÂÂÂÂ.queue_setup = rga_queue_setup,
> > > +ÂÂÂÂÂ.buf_prepare = rga_buf_prepare,
> > > +ÂÂÂÂÂ.buf_queue = rga_buf_queue,
> > > +ÂÂÂÂÂ.buf_init = rga_buf_init,
> > > +ÂÂÂÂÂ.buf_cleanup = rga_buf_cleanup,
> > > +ÂÂÂÂÂ.stop_streaming = rga_buf_stop_streaming,
> > > +};
> > > +
> > > +void *rga_buf_find_page(struct vb2_buffer *vb)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
> > > +ÂÂÂÂÂstruct rga_buf *buf;
> > > +
> > > +ÂÂÂÂÂlist_for_each_entry(buf, &ctx->buffers_list, entry) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂif (buf->index == vb->index && buf->type == vb-
> > > > type) {
> > >
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn buf->mmu_pages;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ}
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂreturn NULL;
> > > +}
> > > +
> > > +void rga_buf_clean(struct rga_ctx *ctx)
> > > +{
> > > +ÂÂÂÂÂstruct rga_buf *buf, *tmp;
> > > +
> > > +ÂÂÂÂÂlist_for_each_entry_safe(buf, tmp, &ctx->buffers_list,
> > > entry) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂfree_pages((unsigned long)buf->mmu_pages, 3);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂlist_del(&buf->entry);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂkfree(buf);
> > > +ÂÂÂÂÂ}
> > > +}
> > > diff --git a/drivers/media/platform/rockchip-rga/rga-hw.c
> > > b/drivers/media/platform/rockchip-rga/rga-hw.c
> > > new file mode 100644
> > > index 0000000..5c20fc8
> > > --- /dev/null
> > > +++ b/drivers/media/platform/rockchip-rga/rga-hw.c
> > > @@ -0,0 +1,456 @@
> > > +/*
> > > + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
> > > + * Author: Jacob Chen <jacob-chen@xxxxxxxxxx>
> > > + *
> > > + * 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 == NULL)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ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)
> > > +{
> > > +ÂÂÂÂÂu32 *dest = ctx->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)
> > > +{
> > > +ÂÂÂÂÂu32 *dest = ctx->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)
> > > +{
> > > +ÂÂÂÂÂu32 *dest = ctx->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)
> > > +{
> > > +ÂÂÂÂÂu32 *dest = ctx->cmdbuf_virt;
> > > +ÂÂÂÂÂstruct rockchip_rga *rga = ctx->rga;
> > > +ÂÂÂÂÂ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)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂsrc_info.data.csc_mode =
> > > RGA_SRC_CSC_MODE_BT601_R0;
> > > +ÂÂÂÂÂ}
> > > +ÂÂÂÂÂif (ctx->out.fmt->hw_format >= RGA_COLOR_FMT_YUV422SP)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdst_info.data.csc_mode = RGA_DST_CSC_MODE_BT601_R0;
> > > +
> > > +ÂÂÂÂÂif (ctx->op == OP_SOLID_FILL) {
> > > +
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ/*
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ* Configure the target color to foreground color.
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ*/
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdest[(RGA_SRC_FG_COLOR - RGA_MODE_BASE_REG) >> 2] =
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂctx->fill_color;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ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;
> > > +
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂoffsets =
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂrga_get_addr_offset(&ctx->out, dst_x, dst_y,
> > > dst_w, dst_h);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdst_offset = &offsets.left_top;
> > > +
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂgoto write_dst;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂ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;
> > > +
> > > +write_dst:
> > > +ÂÂÂÂÂ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)
> > > +{
> > > +ÂÂÂÂÂu32 *dest = ctx->cmdbuf_virt;
> > > +ÂÂÂÂÂunion rga_mode_ctrl mode;
> > > +
> > > +ÂÂÂÂÂmode.val = 0;
> > > +
> > > +ÂÂÂÂÂswitch (ctx->op) {
> > > +ÂÂÂÂÂcase OP_ALPHA_BLEND:
> > > +ÂÂÂÂÂcase OP_COPY:
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂmode.data.gradient_sat = 1;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂmode.data.render = RGA_MODE_RENDER_BITBLT;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂmode.data.bitblt = RGA_MODE_BITBLT_MODE_SRC_TO_DST;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > > +ÂÂÂÂÂcase OP_SOLID_FILL:
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂmode.data.gradient_sat = 1;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂmode.data.render = RGA_MODE_RENDER_RECTANGLE_FILL;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂmode.data.cf_rop4_pat = RGA_MODE_CF_ROP4_SOLID;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂmode.data.bitblt = RGA_MODE_BITBLT_MODE_SRC_TO_DST;
> > > +
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂdest[(RGA_MODE_CTRL - RGA_MODE_BASE_REG) >> 2] = mode.val;
> > > +}
> > > +
> > > +static void rga_cmd_set_alpha_blend(struct rga_ctx *ctx)
> > > +{
> > > +ÂÂÂÂÂu32 *dest = ctx->cmdbuf_virt;
> > > +ÂÂÂÂÂunion rga_alpha_ctrl0 alpha_ctrl0;
> > > +ÂÂÂÂÂunion rga_alpha_ctrl1 alpha_ctrl1;
> > > +
> > > +ÂÂÂÂÂ/* just expose reg to userspace */
> > > +ÂÂÂÂÂalpha_ctrl0.val = ctx->alpha0;
> > > +ÂÂÂÂÂalpha_ctrl1.val = ctx->alpha1;
> > > +
> > > +ÂÂÂÂÂdest[(RGA_ALPHA_CTRL0 - RGA_MODE_BASE_REG) >> 2] =
> > > alpha_ctrl0.val;
> > > +ÂÂÂÂÂdest[(RGA_ALPHA_CTRL1 - RGA_MODE_BASE_REG) >> 2] =
> > > alpha_ctrl1.val;
> > > +}
> > > +
> > > +void rga_cmd_set(struct rga_ctx *ctx, void *src_mmu_pages, void
> > > *dst_mmu_pages)
> > > +{
> > > +ÂÂÂÂÂstruct rockchip_rga *rga = ctx->rga;
> > > +
> > > +ÂÂÂÂÂmemset(ctx->cmdbuf_virt, 0, RGA_CMDBUF_SIZE * 4);
> > > +
> > > +ÂÂÂÂÂif (ctx->op != OP_SOLID_FILL) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂrga_cmd_set_src_addr(ctx, src_mmu_pages);
> > > +ÂÂÂÂÂ}
> > > +ÂÂÂÂÂrga_cmd_set_dst_addr(ctx, dst_mmu_pages);
> > > +ÂÂÂÂÂrga_cmd_set_mode(ctx);
> > > +
> > > +ÂÂÂÂÂif (ctx->op == OP_ALPHA_BLEND) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ/*
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ* Due to hardware bug,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ* src1 mmu also should be configured when use
> > > alpha
> > > blending.
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ*/
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂrga_cmd_set_src1_addr(ctx, src_mmu_pages);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂrga_cmd_set_alpha_blend(ctx);
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂrga_cmd_set_trans_info(ctx);
> > > +
> > > +ÂÂÂÂÂrga_write(rga, RGA_CMD_BASE, ctx->cmdbuf_phy);
> > > +}
> > > +
> > > +void rga_write(struct rockchip_rga *rga, u32 reg, u32 value)
> > > +{
> > > +ÂÂÂÂÂwritel(value, rga->regs + reg);
> > > +}
> > > +
> > > +u32 rga_read(struct rockchip_rga *rga, u32 reg)
> > > +{
> > > +ÂÂÂÂÂreturn readl(rga->regs + reg);
> > > +}
> > > +
> > > +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_start(struct rockchip_rga *rga)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = rga->curr;
> > > +
> > > +ÂÂÂÂÂ/* sync CMD buf for RGA */
> > > +ÂÂÂÂÂdma_sync_single_for_device(rga->dev, ctx->cmdbuf_phy,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂPAGE_SIZE, DMA_BIDIRECTIONAL);
> > > +
> > > +ÂÂÂÂÂ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);
> > > +}
> > > diff --git a/drivers/media/platform/rockchip-rga/rga-hw.h
> > > b/drivers/media/platform/rockchip-rga/rga-hw.h
> > > new file mode 100644
> > > index 0000000..783ea64e
> > > --- /dev/null
> > > +++ b/drivers/media/platform/rockchip-rga/rga-hw.h
> > > @@ -0,0 +1,434 @@
> > > +/*
> > > + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
> > > + * Author: Jacob Chen <jacob-chen@xxxxxxxxxx>
> > > + *
> > > + * 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 adress */
> > > +#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_BGR888 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 1
> > > +#define RGA_ALPHA_SELECT_ROP 2
> > > +
> > > +#define RGA_ALPHA_NORMAL 0
> > > +#define RGA_ALPHA_REVERSE 1
> > > +
> > > +#define RGA_ALPHA_BLEND_GLOBAL 0
> > > +#define RGA_ALPHA_BLEND_PIXEL 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_MAX 1
> > > +#define RGA_ALPHA_FACTOR_NORMAL 2
> > > +#define RGA_ALPHA_FACTOR_REVERSE 3
> > > +#define RGA_ALPHA_FACTOR_OTHER 4
> > > +
> > > +#define RGA_ALPHA_COLOR_PIXEL 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
> > > diff --git a/drivers/media/platform/rockchip-rga/rga.c
> > > b/drivers/media/platform/rockchip-rga/rga.c
> > > new file mode 100644
> > > index 0000000..7292007
> > > --- /dev/null
> > > +++ b/drivers/media/platform/rockchip-rga/rga.c
> > > @@ -0,0 +1,979 @@
> > > +/*
> > > + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
> > > + * Author: Jacob Chen <jacob-chen@xxxxxxxxxx>
> > > + *
> > > + * 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/clk.h>
> > > +#include <linux/debugfs.h>
> > > +#include <linux/delay.h>
> > > +#include <linux/fs.h>
> > > +#include <linux/interrupt.h>
> > > +#include <linux/module.h>
> > > +#include <linux/of.h>
> > > +#include <linux/pm_runtime.h>
> > > +#include <linux/reset.h>
> > > +#include <linux/sched.h>
> > > +#include <linux/slab.h>
> > > +#include <linux/timer.h>
> > > +
> > > +#include <linux/platform_device.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 void job_abort(void *prv)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = prv;
> > > +ÂÂÂÂÂstruct rockchip_rga *rga = ctx->rga;
> > > +
> > > +ÂÂÂÂÂif (rga->curr == NULL)ÂÂ/* No job currently running */
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn;
> > > +
> > > +ÂÂÂÂÂwait_event_timeout(rga->irq_queue,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂrga->curr == NULL,
> > > msecs_to_jiffies(RGA_TIMEOUT));
> > > +}
> > > +
> > > +static void device_run(void *prv)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = prv;
> > > +ÂÂÂÂÂstruct rockchip_rga *rga = ctx->rga;
> > > +ÂÂÂÂÂstruct vb2_buffer *src, *dst;
> > > +ÂÂÂÂÂunsigned long flags;
> > > +
> > > +ÂÂÂÂÂspin_lock_irqsave(&rga->ctrl_lock, flags);
> > > +
> > > +ÂÂÂÂÂrga->curr = ctx;
> > > +
> > > +ÂÂÂÂÂsrc = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
> > > +ÂÂÂÂÂdst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> > > +
> > > +ÂÂÂÂÂrga_cmd_set(ctx, rga_buf_find_page(src),
> > > rga_buf_find_page(dst));
> > > +
> > > +ÂÂÂÂÂrga_start(rga);
> > > +
> > > +ÂÂÂÂÂspin_unlock_irqrestore(&rga->ctrl_lock, flags);
> > > +}
> > > +
> > > +static irqreturn_t rga_isr(int irq, void *prv)
> > > +{
> > > +ÂÂÂÂÂstruct rockchip_rga *rga = prv;
> > > +ÂÂÂÂÂint intr;
> > > +
> > > +ÂÂÂÂÂintr = rga_read(rga, RGA_INT) & 0xf;
> > > +
> > > +ÂÂÂÂÂrga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
> > > +
> > > +ÂÂÂÂÂif (intr & 0x04) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂstruct vb2_v4l2_buffer *src, *dst;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂstruct rga_ctx *ctx = rga->curr;
> > > +
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂBUG_ON(ctx == NULL);
> > > +
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂrga->curr = NULL;
> > > +
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂsrc = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> > > +
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂBUG_ON(src == NULL);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂBUG_ON(dst == NULL);
> > > +
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdst->timecode = src->timecode;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdst->vb2_buf.timestamp = src->vb2_buf.timestamp;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdst->flags |= src->flags &
> > > V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> > > +
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_m2m_job_finish(rga->m2m_dev, ctx->fh.m2m_ctx);
> > > +
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂwake_up(&rga->irq_queue);
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂreturn IRQ_HANDLED;
> > > +}
> > > +
> > > +static struct v4l2_m2m_ops rga_m2m_ops = {
> > > +ÂÂÂÂÂ.device_run = device_run,
> > > +ÂÂÂÂÂ.job_abort = job_abort,
> > > +};
> > > +
> > > +static int
> > > +queue_init(void *priv, struct vb2_queue *src_vq, struct
> > > vb2_queue
> > > *dst_vq)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = priv;
> > > +ÂÂÂÂÂint ret;
> > > +
> > > +ÂÂÂÂÂsrc_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
> > > +ÂÂÂÂÂsrc_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
> > > +ÂÂÂÂÂsrc_vq->drv_priv = ctx;
> > > +ÂÂÂÂÂsrc_vq->ops = &rga_qops;
> > > +ÂÂÂÂÂsrc_vq->mem_ops = &vb2_dma_sg_memops;
> > > +ÂÂÂÂÂsrc_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
> > > +ÂÂÂÂÂsrc_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
> > > +ÂÂÂÂÂsrc_vq->lock = &ctx->rga->mutex;
> > > +ÂÂÂÂÂsrc_vq->dev = ctx->rga->v4l2_dev.dev;
> > > +
> > > +ÂÂÂÂÂret = vb2_queue_init(src_vq);
> > > +ÂÂÂÂÂif (ret)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn ret;
> > > +
> > > +ÂÂÂÂÂdst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> > > +ÂÂÂÂÂdst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
> > > +ÂÂÂÂÂdst_vq->drv_priv = ctx;
> > > +ÂÂÂÂÂdst_vq->ops = &rga_qops;
> > > +ÂÂÂÂÂdst_vq->mem_ops = &vb2_dma_sg_memops;
> > > +ÂÂÂÂÂdst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
> > > +ÂÂÂÂÂdst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
> > > +ÂÂÂÂÂdst_vq->lock = &ctx->rga->mutex;
> > > +ÂÂÂÂÂdst_vq->dev = ctx->rga->v4l2_dev.dev;
> > > +
> > > +ÂÂÂÂÂreturn vb2_queue_init(dst_vq);
> > > +}
> > > +
> > > +static int rga_s_ctrl(struct v4l2_ctrl *ctrl)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = container_of(ctrl->handler, struct
> > > rga_ctx,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂctrl_handler);
> > > +ÂÂÂÂÂunsigned long flags;
> > > +
> > > +ÂÂÂÂÂspin_lock_irqsave(&ctx->rga->ctrl_lock, flags);
> > > +ÂÂÂÂÂswitch (ctrl->id) {
> > > +ÂÂÂÂÂcase V4L2_CID_RGA_OP:
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂctx->op = ctrl->val;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > > +ÂÂÂÂÂcase V4L2_CID_HFLIP:
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂctx->hflip = ctrl->val;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > > +ÂÂÂÂÂcase V4L2_CID_VFLIP:
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂctx->vflip = ctrl->val;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > > +ÂÂÂÂÂcase V4L2_CID_ROTATE:
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂctx->rotate = ctrl->val;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > > +ÂÂÂÂÂcase V4L2_CID_BG_COLOR:
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂctx->fill_color = ctrl->val;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > > +ÂÂÂÂÂcase V4L2_CID_RGA_ALHPA_REG0:
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂctx->alpha0 = ctrl->val;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > > +ÂÂÂÂÂcase V4L2_CID_RGA_ALHPA_REG1:
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂctx->alpha1 = ctrl->val;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > > +ÂÂÂÂÂ}
> > > +ÂÂÂÂÂspin_unlock_irqrestore(&ctx->rga->ctrl_lock, flags);
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static const struct v4l2_ctrl_ops rga_ctrl_ops = {
> > > +ÂÂÂÂÂ.s_ctrl = rga_s_ctrl,
> > > +};
> > > +
> > > +static const struct v4l2_ctrl_config op_control = {
> > > +ÂÂÂÂÂ.ops = &rga_ctrl_ops,
> > > +ÂÂÂÂÂ.id = V4L2_CID_RGA_OP,
> > > +ÂÂÂÂÂ.name = "Transform operation",
> > > +ÂÂÂÂÂ.type = V4L2_CTRL_TYPE_INTEGER,
> > > +ÂÂÂÂÂ.min = 0x0,
> > > +ÂÂÂÂÂ.max = 0xf,
> > > +ÂÂÂÂÂ.step = 1,
> > > +ÂÂÂÂÂ.def = 0,
> > > +};
> > > +
> > > +static const struct v4l2_ctrl_config alpha0_control = {
> > > +ÂÂÂÂÂ.ops = &rga_ctrl_ops,
> > > +ÂÂÂÂÂ.id = V4L2_CID_RGA_ALHPA_REG0,
> > > +ÂÂÂÂÂ.name = "Exposed alpha blending register 0",
> > > +ÂÂÂÂÂ.type = V4L2_CTRL_TYPE_INTEGER,
> > > +ÂÂÂÂÂ.min = 0x0,
> > > +ÂÂÂÂÂ.max = 0xffffffff,
> > > +ÂÂÂÂÂ.step = 1,
> > > +ÂÂÂÂÂ.def = 0,
> > > +};
> > > +
> > > +static const struct v4l2_ctrl_config alpha1_control = {
> > > +ÂÂÂÂÂ.ops = &rga_ctrl_ops,
> > > +ÂÂÂÂÂ.id = V4L2_CID_RGA_ALHPA_REG1,
> > > +ÂÂÂÂÂ.name = "Exposed alpha blending register 1",
> > > +ÂÂÂÂÂ.type = V4L2_CTRL_TYPE_INTEGER,
> > > +ÂÂÂÂÂ.min = 0x0,
> > > +ÂÂÂÂÂ.max = 0xffffffff,
> > > +ÂÂÂÂÂ.step = 1,
> > > +ÂÂÂÂÂ.def = 0,
> > > +};
> > > +
> > > +static int rga_setup_ctrls(struct rga_ctx *ctx)
> > > +{
> > > +ÂÂÂÂÂstruct rockchip_rga *rga = ctx->rga;
> > > +
> > > +ÂÂÂÂÂv4l2_ctrl_handler_init(&ctx->ctrl_handler, 7);
> > > +
> > > +ÂÂÂÂÂv4l2_ctrl_new_std(&ctx->ctrl_handler, &rga_ctrl_ops,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂV4L2_CID_HFLIP, 0, 1, 1, 0);
> > > +
> > > +ÂÂÂÂÂv4l2_ctrl_new_std(&ctx->ctrl_handler, &rga_ctrl_ops,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂV4L2_CID_VFLIP, 0, 1, 1, 0);
> > > +
> > > +ÂÂÂÂÂv4l2_ctrl_new_std(&ctx->ctrl_handler, &rga_ctrl_ops,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂV4L2_CID_ROTATE, 0, 270, 90, 0);
> > > +
> > > +ÂÂÂÂÂv4l2_ctrl_new_std(&ctx->ctrl_handler, &rga_ctrl_ops,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂV4L2_CID_BG_COLOR, 0, 0xffffffff, 1, 0);
> > > +
> > > +ÂÂÂÂÂv4l2_ctrl_new_custom(&ctx->ctrl_handler, &op_control,
> > > NULL);
> > > +ÂÂÂÂÂv4l2_ctrl_new_custom(&ctx->ctrl_handler, &alpha0_control,
> > > NULL);
> > > +ÂÂÂÂÂv4l2_ctrl_new_custom(&ctx->ctrl_handler, &alpha1_control,
> > > NULL);
> > > +
> > > +ÂÂÂÂÂif (ctx->ctrl_handler.error) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂint err = ctx->ctrl_handler.error;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_err(&rga->v4l2_dev, "%s failed\n", __func__);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_ctrl_handler_free(&ctx->ctrl_handler);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn err;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +struct rga_fmt formats[] = {
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "ARGB_8888",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_ARGB32,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_RB_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_ABGR8888,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 32,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 1,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "XRGB_8888",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_XRGB32,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_RB_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_XBGR8888,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 32,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 1,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "BGRA_8888",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_ABGR32,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_ALPHA_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_ABGR8888,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 32,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 1,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "BGRX_8888",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_XBGR32,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_ALPHA_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_XBGR8888,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 32,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 1,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "RGB_888",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_RGB24,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_RB_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_BGR888,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 24,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 1,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "ARGB_444",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_ARGB444,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_RB_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_ABGR4444,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 16,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 1,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "ARGB_1555",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_ARGB555,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_RB_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_ABGR1555,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 16,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 1,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "RGB_565",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_RGB565,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_RB_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_BGR565,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 16,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 1,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "NV_21",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_NV21,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_UV_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_YUV420SP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 12,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 4,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 2,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 1,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "NV_61",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_NV61,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_UV_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_YUV422SP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 16,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 2,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 1,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "NV_12",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_NV12,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_NONE_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_YUV420SP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 12,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 4,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 2,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 1,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "NV_16",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_NV16,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_NONE_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_YUV422SP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 16,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 2,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 1,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "YUV_420",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_YUV420,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_NONE_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_YUV420P,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 12,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 4,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 2,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 2,
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "YUV_422",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.fourcc = V4L2_PIX_FMT_YUV422P,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.color_swap = RGA_COLOR_NONE_SWAP,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.hw_format = RGA_COLOR_FMT_YUV422P,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.depth = 16,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.uv_factor = 2,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.y_div = 1,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.x_div = 2,
> > > +ÂÂÂÂÂ},
> > > +};
> > > +
> > > +#define NUM_FORMATS ARRAY_SIZE(formats)
> > > +
> > > +struct rga_fmt *rga_fmt_find(struct v4l2_format *f)
> > > +{
> > > +ÂÂÂÂÂunsigned int i;
> > > +ÂÂÂÂÂfor (i = 0; i < NUM_FORMATS; i++) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂif (formats[i].fourcc == f->fmt.pix.pixelformat)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn &formats[i];
> > > +ÂÂÂÂÂ}
> > > +ÂÂÂÂÂreturn NULL;
> > > +}
> > > +
> > > +static struct rga_frame def_frame = {
> > > +ÂÂÂÂÂ.width = DEFAULT_WIDTH,
> > > +ÂÂÂÂÂ.height = DEFAULT_HEIGHT,
> > > +ÂÂÂÂÂ.crop.left = 0,
> > > +ÂÂÂÂÂ.crop.top = 0,
> > > +ÂÂÂÂÂ.crop.width = DEFAULT_WIDTH,
> > > +ÂÂÂÂÂ.crop.height = DEFAULT_HEIGHT,
> > > +ÂÂÂÂÂ.fmt = &formats[0],
> > > +};
> > > +
> > > +struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum
> > > v4l2_buf_type type)
> > > +{
> > > +ÂÂÂÂÂswitch (type) {
> > > +ÂÂÂÂÂcase V4L2_BUF_TYPE_VIDEO_OUTPUT:
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn &ctx->in;
> > > +ÂÂÂÂÂcase V4L2_BUF_TYPE_VIDEO_CAPTURE:
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn &ctx->out;
> > > +ÂÂÂÂÂdefault:
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn ERR_PTR(-EINVAL);
> > > +ÂÂÂÂÂ}
> > > +}
> > > +
> > > +static int rga_open(struct file *file)
> > > +{
> > > +ÂÂÂÂÂstruct rockchip_rga *rga = video_drvdata(file);
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = NULL;
> > > +ÂÂÂÂÂint ret = 0;
> > > +
> > > +ÂÂÂÂÂctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
> > > +ÂÂÂÂÂif (!ctx)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -ENOMEM;
> > > +ÂÂÂÂÂctx->rga = rga;
> > > +ÂÂÂÂÂ/* Set default formats */
> > > +ÂÂÂÂÂctx->in = def_frame;
> > > +ÂÂÂÂÂctx->out = def_frame;
> > > +
> > > +ÂÂÂÂÂif (mutex_lock_interruptible(&rga->mutex)) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂkfree(ctx);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -ERESTARTSYS;
> > > +ÂÂÂÂÂ}
> > > +ÂÂÂÂÂctx->fh.m2m_ctx = v4l2_m2m_ctx_init(rga->m2m_dev, ctx,
> > > &queue_init);
> > > +ÂÂÂÂÂif (IS_ERR(ctx->fh.m2m_ctx)) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂret = PTR_ERR(ctx->fh.m2m_ctx);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂmutex_unlock(&rga->mutex);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂkfree(ctx);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn ret;
> > > +ÂÂÂÂÂ}
> > > +ÂÂÂÂÂv4l2_fh_init(&ctx->fh, video_devdata(file));
> > > +ÂÂÂÂÂfile->private_data = &ctx->fh;
> > > +ÂÂÂÂÂv4l2_fh_add(&ctx->fh);
> > > +
> > > +ÂÂÂÂÂrga_setup_ctrls(ctx);
> > > +
> > > +ÂÂÂÂÂ/* Write the default values to the ctx struct */
> > > +ÂÂÂÂÂv4l2_ctrl_handler_setup(&ctx->ctrl_handler);
> > > +
> > > +ÂÂÂÂÂctx->fh.ctrl_handler = &ctx->ctrl_handler;
> > > +ÂÂÂÂÂmutex_unlock(&rga->mutex);
> > > +
> > > +ÂÂÂÂÂ/* Create CMD buffer */
> > > +ÂÂÂÂÂctx->cmdbuf_virt = dma_alloc_attrs(rga->dev,
> > > RGA_CMDBUF_SIZE,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ&ctx->cmdbuf_phy,
> > > GFP_KERNEL,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂDMA_ATTR_WRITE_COMBINE);
> > > +
> > > +ÂÂÂÂÂ/* Init RGA private buffer list */
> > > +ÂÂÂÂÂINIT_LIST_HEAD(&ctx->buffers_list);
> > > +
> > > +ÂÂÂÂÂpm_runtime_get_sync(rga->dev);
> > > +
> > > +ÂÂÂÂÂv4l2_info(&rga->v4l2_dev, "instance opened\n");
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static int rga_release(struct file *file)
> > > +{
> > > +ÂÂÂÂÂstruct rockchip_rga *rga = video_drvdata(file);
> > > +ÂÂÂÂÂstruct rga_ctx *ctx =
> > > +ÂÂÂÂÂÂÂÂÂcontainer_of(file->private_data, struct rga_ctx, fh);
> > > +
> > > +ÂÂÂÂÂpm_runtime_put(rga->dev);
> > > +ÂÂÂÂÂv4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
> > > +ÂÂÂÂÂif (!list_empty(&ctx->buffers_list)) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_info(&rga->v4l2_dev, "close with unreleased
> > > buffers\n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂrga_buf_clean(ctx);
> > > +ÂÂÂÂÂ}
> > > +ÂÂÂÂÂv4l2_ctrl_handler_free(&ctx->ctrl_handler);
> > > +ÂÂÂÂÂv4l2_fh_del(&ctx->fh);
> > > +ÂÂÂÂÂv4l2_fh_exit(&ctx->fh);
> > > +ÂÂÂÂÂkfree(ctx);
> > > +ÂÂÂÂÂv4l2_info(&rga->v4l2_dev, "instance closed\n");
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static const struct v4l2_file_operations rga_fops = {
> > > +ÂÂÂÂÂ.owner = THIS_MODULE,
> > > +ÂÂÂÂÂ.open = rga_open,
> > > +ÂÂÂÂÂ.release = rga_release,
> > > +ÂÂÂÂÂ.poll = v4l2_m2m_fop_poll,
> > > +ÂÂÂÂÂ.unlocked_ioctl = video_ioctl2,
> > > +ÂÂÂÂÂ.mmap = v4l2_m2m_fop_mmap,
> > > +};
> > > +
> > > +static int
> > > +vidioc_querycap(struct file *file, void *priv, struct
> > > v4l2_capability *cap)
> > > +{
> > > +ÂÂÂÂÂstrncpy(cap->driver, RGA_NAME, sizeof(cap->driver) - 1);
> > > +ÂÂÂÂÂstrncpy(cap->card, RGA_NAME, sizeof(cap->card) - 1);
> > > +ÂÂÂÂÂcap->bus_info[0] = 0;
> > > +ÂÂÂÂÂcap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
> > > +ÂÂÂÂÂcap->capabilities = cap->device_caps |
> > > V4L2_CAP_DEVICE_CAPS;
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static int vidioc_enum_fmt(struct file *file, void *prv, struct
> > > v4l2_fmtdesc *f)
> > > +{
> > > +ÂÂÂÂÂstruct rga_fmt *fmt;
> > > +ÂÂÂÂÂif (f->index >= NUM_FORMATS)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -EINVAL;
> > > +ÂÂÂÂÂfmt = &formats[f->index];
> > > +ÂÂÂÂÂf->pixelformat = fmt->fourcc;
> > > +ÂÂÂÂÂstrncpy(f->description, fmt->name, sizeof(f->description) -
> > > 1);
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static int vidioc_g_fmt(struct file *file, void *prv, struct
> > > v4l2_format *f)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = prv;
> > > +ÂÂÂÂÂstruct vb2_queue *vq;
> > > +ÂÂÂÂÂstruct rga_frame *frm;
> > > +
> > > +ÂÂÂÂÂvq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
> > > +ÂÂÂÂÂif (!vq)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -EINVAL;
> > > +ÂÂÂÂÂfrm = rga_get_frame(ctx, f->type);
> > > +ÂÂÂÂÂif (IS_ERR(frm))
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn PTR_ERR(frm);
> > > +
> > > +ÂÂÂÂÂf->fmt.pix.width = frm->width;
> > > +ÂÂÂÂÂf->fmt.pix.height = frm->height;
> > > +ÂÂÂÂÂf->fmt.pix.field = V4L2_FIELD_NONE;
> > > +ÂÂÂÂÂf->fmt.pix.pixelformat = frm->fmt->fourcc;
> > > +ÂÂÂÂÂf->fmt.pix.bytesperline = frm->stride;
> > > +ÂÂÂÂÂf->fmt.pix.sizeimage = frm->size;
> > > +
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static int vidioc_try_fmt(struct file *file, void *prv, struct
> > > v4l2_format *f)
> > > +{
> > > +ÂÂÂÂÂstruct rga_fmt *fmt;
> > > +ÂÂÂÂÂenum v4l2_field *field;
> > > +
> > > +ÂÂÂÂÂfmt = rga_fmt_find(f);
> > > +ÂÂÂÂÂif (!fmt)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -EINVAL;
> > > +
> > > +ÂÂÂÂÂfield = &f->fmt.pix.field;
> > > +ÂÂÂÂÂif (*field == V4L2_FIELD_ANY)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ*field = V4L2_FIELD_NONE;
> > > +ÂÂÂÂÂelse if (*field != V4L2_FIELD_NONE)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -EINVAL;
> > > +
> > > +ÂÂÂÂÂif (f->fmt.pix.width > MAX_WIDTH)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂf->fmt.pix.width = MAX_WIDTH;
> > > +ÂÂÂÂÂif (f->fmt.pix.height > MAX_HEIGHT)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂf->fmt.pix.height = MAX_HEIGHT;
> > > +
> > > +ÂÂÂÂÂif (f->fmt.pix.width < MIN_WIDTH)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂf->fmt.pix.width = MIN_WIDTH;
> > > +ÂÂÂÂÂif (f->fmt.pix.height < MIN_HEIGHT)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂf->fmt.pix.height = MIN_HEIGHT;
> > > +
> > > +ÂÂÂÂÂif (fmt->hw_format >= RGA_COLOR_FMT_YUV422SP)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂf->fmt.pix.bytesperline = f->fmt.pix.width;
> > > +ÂÂÂÂÂelse
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂf->fmt.pix.bytesperline = (f->fmt.pix.width * fmt-
> > > > depth) >> 3;
> > >
> > > +
> > > +ÂÂÂÂÂf->fmt.pix.sizeimage =
> > > +ÂÂÂÂÂÂÂÂÂf->fmt.pix.height * (f->fmt.pix.width * fmt->depth) >>
> > > 3;
> > > +
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static int vidioc_s_fmt(struct file *file, void *prv, struct
> > > v4l2_format *f)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = prv;
> > > +ÂÂÂÂÂstruct rockchip_rga *rga = ctx->rga;
> > > +ÂÂÂÂÂstruct vb2_queue *vq;
> > > +ÂÂÂÂÂstruct rga_frame *frm;
> > > +ÂÂÂÂÂstruct rga_fmt *fmt;
> > > +ÂÂÂÂÂint ret = 0;
> > > +
> > > +ÂÂÂÂÂ/* Adjust all values accordingly to the hardware
> > > capabilities
> > > +ÂÂÂÂÂÂ* and chosen format. */
> > > +ÂÂÂÂÂret = vidioc_try_fmt(file, prv, f);
> > > +ÂÂÂÂÂif (ret)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn ret;
> > > +ÂÂÂÂÂvq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
> > > +ÂÂÂÂÂif (vb2_is_busy(vq)) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_err(&rga->v4l2_dev, "queue (%d) bust\n", f-
> > > > type);
> > >
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -EBUSY;
> > > +ÂÂÂÂÂ}
> > > +ÂÂÂÂÂfrm = rga_get_frame(ctx, f->type);
> > > +ÂÂÂÂÂif (IS_ERR(frm))
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn PTR_ERR(frm);
> > > +ÂÂÂÂÂfmt = rga_fmt_find(f);
> > > +ÂÂÂÂÂif (!fmt)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -EINVAL;
> > > +ÂÂÂÂÂfrm->width = f->fmt.pix.width;
> > > +ÂÂÂÂÂfrm->height = f->fmt.pix.height;
> > > +ÂÂÂÂÂfrm->size = f->fmt.pix.sizeimage;
> > > +ÂÂÂÂÂfrm->fmt = fmt;
> > > +ÂÂÂÂÂfrm->stride = f->fmt.pix.bytesperline;
> > > +
> > > +ÂÂÂÂÂ/* Reset crop settings */
> > > +ÂÂÂÂÂfrm->crop.left = 0;
> > > +ÂÂÂÂÂfrm->crop.top = 0;
> > > +ÂÂÂÂÂfrm->crop.width = frm->width;
> > > +ÂÂÂÂÂfrm->crop.height = frm->height;
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static int
> > > +vidioc_cropcap(struct file *file, void *priv, struct
> > > v4l2_cropcap
> > > *cr)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = priv;
> > > +ÂÂÂÂÂstruct rga_frame *f;
> > > +
> > > +ÂÂÂÂÂf = rga_get_frame(ctx, cr->type);
> > > +ÂÂÂÂÂif (IS_ERR(f))
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn PTR_ERR(f);
> > > +
> > > +ÂÂÂÂÂcr->bounds.left = 0;
> > > +ÂÂÂÂÂcr->bounds.top = 0;
> > > +ÂÂÂÂÂcr->bounds.width = f->width;
> > > +ÂÂÂÂÂcr->bounds.height = f->height;
> > > +ÂÂÂÂÂcr->defrect = cr->bounds;
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static int vidioc_g_crop(struct file *file, void *prv, struct
> > > v4l2_crop *cr)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = prv;
> > > +ÂÂÂÂÂstruct rga_frame *f;
> > > +
> > > +ÂÂÂÂÂf = rga_get_frame(ctx, cr->type);
> > > +ÂÂÂÂÂif (IS_ERR(f))
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn PTR_ERR(f);
> > > +
> > > +ÂÂÂÂÂcr->c = f->crop;
> > > +
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static int
> > > +vidioc_try_crop(struct file *file, void *prv, const struct
> > > v4l2_crop
> > > *cr)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = prv;
> > > +ÂÂÂÂÂstruct rockchip_rga *rga = ctx->rga;
> > > +ÂÂÂÂÂstruct rga_frame *f;
> > > +
> > > +ÂÂÂÂÂf = rga_get_frame(ctx, cr->type);
> > > +ÂÂÂÂÂif (IS_ERR(f))
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn PTR_ERR(f);
> > > +
> > > +ÂÂÂÂÂif (cr->c.top < 0 || cr->c.left < 0) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_err(&rga->v4l2_dev,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ"doesn't support negative values for top &
> > > left. \n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -EINVAL;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂif (cr->c.left + cr->c.width > f->width ||
> > > +ÂÂÂÂÂÂÂÂÂcr->c.top + cr->c.height > f->height ||
> > > +ÂÂÂÂÂÂÂÂÂcr->c.width < MIN_WIDTH || cr->c.height < MIN_HEIGHT) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_err(&rga->v4l2_dev, "unsupport crop value.
> > > \n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -EINVAL;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static int
> > > +vidioc_s_crop(struct file *file, void *prv, const struct
> > > v4l2_crop
> > > *cr)
> > > +{
> > > +ÂÂÂÂÂstruct rga_ctx *ctx = prv;
> > > +ÂÂÂÂÂstruct rga_frame *f;
> > > +ÂÂÂÂÂint ret;
> > > +
> > > +ÂÂÂÂÂret = vidioc_try_crop(file, prv, cr);
> > > +ÂÂÂÂÂif (ret)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn ret;
> > > +ÂÂÂÂÂf = rga_get_frame(ctx, cr->type);
> > > +ÂÂÂÂÂif (IS_ERR(f))
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn PTR_ERR(f);
> > > +
> > > +ÂÂÂÂÂf->crop = cr->c;
> > > +
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static const struct v4l2_ioctl_ops rga_ioctl_ops = {
> > > +ÂÂÂÂÂ.vidioc_querycap = vidioc_querycap,
> > > +
> > > +ÂÂÂÂÂ.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt,
> > > +ÂÂÂÂÂ.vidioc_g_fmt_vid_cap = vidioc_g_fmt,
> > > +ÂÂÂÂÂ.vidioc_try_fmt_vid_cap = vidioc_try_fmt,
> > > +ÂÂÂÂÂ.vidioc_s_fmt_vid_cap = vidioc_s_fmt,
> > > +
> > > +ÂÂÂÂÂ.vidioc_enum_fmt_vid_out = vidioc_enum_fmt,
> > > +ÂÂÂÂÂ.vidioc_g_fmt_vid_out = vidioc_g_fmt,
> > > +ÂÂÂÂÂ.vidioc_try_fmt_vid_out = vidioc_try_fmt,
> > > +ÂÂÂÂÂ.vidioc_s_fmt_vid_out = vidioc_s_fmt,
> > > +
> > > +ÂÂÂÂÂ.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
> > > +ÂÂÂÂÂ.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
> > > +ÂÂÂÂÂ.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
> > > +ÂÂÂÂÂ.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
> > > +ÂÂÂÂÂ.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
> > > +ÂÂÂÂÂ.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
> > > +ÂÂÂÂÂ.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
> > > +
> > > +ÂÂÂÂÂ.vidioc_streamon = v4l2_m2m_ioctl_streamon,
> > > +ÂÂÂÂÂ.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
> > > +
> > > +ÂÂÂÂÂ.vidioc_g_crop = vidioc_g_crop,
> > > +ÂÂÂÂÂ.vidioc_s_crop = vidioc_s_crop,
> > > +ÂÂÂÂÂ.vidioc_cropcap = vidioc_cropcap,
> > > +};
> > > +
> > > +static struct video_device rga_videodev = {
> > > +ÂÂÂÂÂ.name = "rockchip-rga",
> > > +ÂÂÂÂÂ.fops = &rga_fops,
> > > +ÂÂÂÂÂ.ioctl_ops = &rga_ioctl_ops,
> > > +ÂÂÂÂÂ.minor = -1,
> > > +ÂÂÂÂÂ.release = video_device_release,
> > > +ÂÂÂÂÂ.vfl_dir = VFL_DIR_M2M,
> > > +};
> > > +
> > > +static int rga_enable_clocks(struct rockchip_rga *rga)
> > > +{
> > > +ÂÂÂÂÂint ret;
> > > +
> > > +ÂÂÂÂÂret = clk_prepare_enable(rga->sclk);
> > > +ÂÂÂÂÂif (ret) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(rga->dev, "Cannot enable rga sclk: %d\n",
> > > ret);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn ret;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂret = clk_prepare_enable(rga->aclk);
> > > +ÂÂÂÂÂif (ret) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(rga->dev, "Cannot enable rga aclk: %d\n",
> > > ret);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂgoto err_disable_sclk;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂret = clk_prepare_enable(rga->hclk);
> > > +ÂÂÂÂÂif (ret) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(rga->dev, "Cannot enable rga hclk: %d\n",
> > > ret);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂgoto err_disable_aclk;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂreturn 0;
> > > +
> > > +err_disable_sclk:
> > > +ÂÂÂÂÂclk_disable_unprepare(rga->sclk);
> > > +err_disable_aclk:
> > > +ÂÂÂÂÂclk_disable_unprepare(rga->aclk);
> > > +
> > > +ÂÂÂÂÂreturn ret;
> > > +}
> > > +
> > > +static int rga_parse_dt(struct rockchip_rga *rga)
> > > +{
> > > +ÂÂÂÂÂstruct reset_control *core_rst, *axi_rst, *ahb_rst;
> > > +
> > > +ÂÂÂÂÂcore_rst = devm_reset_control_get(rga->dev, "core");
> > > +ÂÂÂÂÂif (IS_ERR(core_rst)) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(rga->dev, "failed to get core reset
> > > controller\n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn PTR_ERR(core_rst);
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂaxi_rst = devm_reset_control_get(rga->dev, "axi");
> > > +ÂÂÂÂÂif (IS_ERR(axi_rst)) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(rga->dev, "failed to get axi reset
> > > controller\n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn PTR_ERR(axi_rst);
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂahb_rst = devm_reset_control_get(rga->dev, "ahb");
> > > +ÂÂÂÂÂif (IS_ERR(ahb_rst)) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(rga->dev, "failed to get ahb reset
> > > controller\n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn PTR_ERR(ahb_rst);
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂreset_control_assert(core_rst);
> > > +ÂÂÂÂÂudelay(1);
> > > +ÂÂÂÂÂreset_control_deassert(core_rst);
> > > +
> > > +ÂÂÂÂÂreset_control_assert(axi_rst);
> > > +ÂÂÂÂÂudelay(1);
> > > +ÂÂÂÂÂreset_control_deassert(axi_rst);
> > > +
> > > +ÂÂÂÂÂreset_control_assert(ahb_rst);
> > > +ÂÂÂÂÂudelay(1);
> > > +ÂÂÂÂÂreset_control_deassert(ahb_rst);
> > > +
> > > +ÂÂÂÂÂrga->sclk = devm_clk_get(rga->dev, "sclk");
> > > +ÂÂÂÂÂif (IS_ERR(rga->sclk)) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(rga->dev, "failed to get sclk clock\n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn PTR_ERR(rga->sclk);
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂrga->aclk = devm_clk_get(rga->dev, "aclk");
> > > +ÂÂÂÂÂif (IS_ERR(rga->aclk)) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(rga->dev, "failed to get aclk clock\n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn PTR_ERR(rga->aclk);
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂrga->hclk = devm_clk_get(rga->dev, "hclk");
> > > +ÂÂÂÂÂif (IS_ERR(rga->hclk)) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(rga->dev, "failed to get hclk clock\n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn PTR_ERR(rga->hclk);
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂreturn rga_enable_clocks(rga);
> > > +}
> > > +
> > > +static int rga_probe(struct platform_device *pdev)
> > > +{
> > > +ÂÂÂÂÂstruct rockchip_rga *rga;
> > > +ÂÂÂÂÂstruct video_device *vfd;
> > > +ÂÂÂÂÂstruct resource *res;
> > > +ÂÂÂÂÂint ret = 0;
> > > +ÂÂÂÂÂint irq;
> > > +
> > > +ÂÂÂÂÂif (!pdev->dev.of_node)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -ENODEV;
> > > +
> > > +ÂÂÂÂÂrga = devm_kzalloc(&pdev->dev, sizeof(*rga), GFP_KERNEL);
> > > +ÂÂÂÂÂif (!rga)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -ENOMEM;
> > > +
> > > +ÂÂÂÂÂrga->dev = &pdev->dev;
> > > +ÂÂÂÂÂspin_lock_init(&rga->ctrl_lock);
> > > +ÂÂÂÂÂmutex_init(&rga->mutex);
> > > +
> > > +ÂÂÂÂÂinit_waitqueue_head(&rga->irq_queue);
> > > +
> > > +ÂÂÂÂÂret = rga_parse_dt(rga);
> > > +ÂÂÂÂÂif (ret) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(&pdev->dev, "Unable to parse OF data\n");
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂpm_runtime_enable(rga->dev);
> > > +
> > > +ÂÂÂÂÂres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > +
> > > +ÂÂÂÂÂrga->regs = devm_ioremap_resource(rga->dev, res);
> > > +ÂÂÂÂÂif (IS_ERR(rga->regs)) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂret = PTR_ERR(rga->regs);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂgoto err_put_clk;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂirq = platform_get_irq(pdev, 0);
> > > +ÂÂÂÂÂif (irq < 0) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(rga->dev, "failed to get irq\n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂret = irq;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂgoto err_put_clk;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂret = devm_request_irq(rga->dev, irq, rga_isr, 0,
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂdev_name(rga->dev), rga);
> > > +ÂÂÂÂÂif (ret < 0) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(rga->dev, "failed to request irq\n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂgoto err_put_clk;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂpm_runtime_get_sync(rga->dev);
> > > +
> > > +ÂÂÂÂÂrga->version.major = (rga_read(rga, RGA_VERSION_INFO) >>
> > > 24)
> > > & 0xFF;
> > > +ÂÂÂÂÂrga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >>
> > > 20)
> > > & 0x0F;
> > > +
> > > +ÂÂÂÂÂpm_runtime_put(rga->dev);
> > > +
> > > +ÂÂÂÂÂret = v4l2_device_register(&pdev->dev, &rga->v4l2_dev);
> > > +ÂÂÂÂÂif (ret)
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂgoto err_put_clk;
> > > +ÂÂÂÂÂvfd = video_device_alloc();
> > > +ÂÂÂÂÂif (!vfd) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_err(&rga->v4l2_dev, "Failed to allocate video
> > > device\n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂret = -ENOMEM;
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂgoto unreg_v4l2_dev;
> > > +ÂÂÂÂÂ}
> > > +ÂÂÂÂÂ*vfd = rga_videodev;
> > > +ÂÂÂÂÂvfd->lock = &rga->mutex;
> > > +ÂÂÂÂÂvfd->v4l2_dev = &rga->v4l2_dev;
> > > +ÂÂÂÂÂret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
> > > +ÂÂÂÂÂif (ret) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_err(&rga->v4l2_dev, "Failed to register video
> > > device\n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂgoto rel_vdev;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂvideo_set_drvdata(vfd, rga);
> > > +ÂÂÂÂÂsnprintf(vfd->name, sizeof(vfd->name), "%s",
> > > rga_videodev.name);
> > > +ÂÂÂÂÂrga->vfd = vfd;
> > > +ÂÂÂÂÂv4l2_info(&rga->v4l2_dev, "device registered as
> > > /dev/video%d\n",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂvfd->num);
> > > +ÂÂÂÂÂplatform_set_drvdata(pdev, rga);
> > > +ÂÂÂÂÂrga->m2m_dev = v4l2_m2m_init(&rga_m2m_ops);
> > > +ÂÂÂÂÂif (IS_ERR(rga->m2m_dev)) {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂv4l2_err(&rga->v4l2_dev, "Failed to init mem2mem
> > > device\n");
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂret = PTR_ERR(rga->m2m_dev);
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂgoto unreg_video_dev;
> > > +ÂÂÂÂÂ}
> > > +
> > > +ÂÂÂÂÂdef_frame.stride = (def_frame.width * def_frame.fmt->depth)
> > > > > 3;
> > >
> > > +
> > > +ÂÂÂÂÂreturn 0;
> > > +
> > > +unreg_video_dev:
> > > +ÂÂÂÂÂvideo_unregister_device(rga->vfd);
> > > +rel_vdev:
> > > +ÂÂÂÂÂvideo_device_release(vfd);
> > > +unreg_v4l2_dev:
> > > +ÂÂÂÂÂv4l2_device_unregister(&rga->v4l2_dev);
> > > +err_put_clk:
> > > +ÂÂÂÂÂpm_runtime_disable(rga->dev);
> > > +
> > > +ÂÂÂÂÂreturn ret;
> > > +}
> > > +
> > > +static int rga_remove(struct platform_device *pdev)
> > > +{
> > > +ÂÂÂÂÂstruct rockchip_rga *rga = platform_get_drvdata(pdev);
> > > +
> > > +ÂÂÂÂÂv4l2_info(&rga->v4l2_dev, "Removing \n");
> > > +ÂÂÂÂÂv4l2_m2m_release(rga->m2m_dev);
> > > +ÂÂÂÂÂvideo_unregister_device(rga->vfd);
> > > +ÂÂÂÂÂv4l2_device_unregister(&rga->v4l2_dev);
> > > +
> > > +ÂÂÂÂÂpm_runtime_disable(rga->dev);
> > > +
> > > +ÂÂÂÂÂreturn 0;
> > > +}
> > > +
> > > +static const struct of_device_id rockchip_rga_match[] = {
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.compatible = "rockchip,rk3288-rga",
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.compatible = "rockchip,rk3228-rga",
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.compatible = "rockchip,rk3328-rga",
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.compatible = "rockchip,rk3399-rga",
> > > +ÂÂÂÂÂ},
> > > +ÂÂÂÂÂ{},
> > > +};
> > > +
> > > +MODULE_DEVICE_TABLE(of, rockchip_rga_match);
> > > +
> > > +static struct platform_driver rga_pdrv = {
> > > +ÂÂÂÂÂ.probe = rga_probe,
> > > +ÂÂÂÂÂ.remove = rga_remove,
> > > +ÂÂÂÂÂ.driver = {
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.name = "rockchip-rga",
> > > +ÂÂÂÂÂÂÂÂÂÂÂÂÂ.of_match_table = rockchip_rga_match,
> > > +ÂÂÂÂÂ},
> > > +};
> > > +
> > > +module_platform_driver(rga_pdrv);
> > > +
> > > +MODULE_AUTHOR("Jacob Chen <jacob-chen@xxxxxxxxxx>");
> > > +MODULE_DESCRIPTION("Rockchip Raster 2d Grapphic Acceleration
> > > Unit");
> > > +MODULE_LICENSE("GPL");
> > > diff --git a/drivers/media/platform/rockchip-rga/rga.h
> > > b/drivers/media/platform/rockchip-rga/rga.h
> > > new file mode 100644
> > > index 0000000..272c4d82
> > > --- /dev/null
> > > +++ b/drivers/media/platform/rockchip-rga/rga.h
> > > @@ -0,0 +1,133 @@
> > > +/*
> > > + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
> > > + * Author: Jacob Chen <jacob-chen@xxxxxxxxxx>
> > > + *
> > > + * 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 {
> > > +ÂÂÂÂÂchar *name;
> > > +ÂÂÂÂÂ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;
> > > +
> > > +ÂÂÂÂÂ/* 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_buf {
> > > +ÂÂÂÂÂu32 index;
> > > +ÂÂÂÂÂu32 type;
> > > +ÂÂÂÂÂvoid *mmu_pages;
> > > +ÂÂÂÂÂstruct list_head entry;
> > > +};
> > > +
> > > +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;
> > > +ÂÂÂÂÂu32 alpha0;
> > > +ÂÂÂÂÂu32 alpha1;
> > > +
> > > +ÂÂÂÂÂ/* CMD Buffers for RGA reading */
> > > +ÂÂÂÂÂdma_addr_t cmdbuf_phy;
> > > +ÂÂÂÂÂvoid *cmdbuf_virt;
> > > +
> > > +ÂÂÂÂÂ/* Buffers queued for RGA */
> > > +ÂÂÂÂÂstruct list_head buffers_list;
> > > +};
> > > +
> > > +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;
> > > +
> > > +ÂÂÂÂÂstruct mutex mutex;
> > > +ÂÂÂÂÂspinlock_t ctrl_lock;
> > > +
> > > +ÂÂÂÂÂwait_queue_head_t irq_queue;
> > > +
> > > +ÂÂÂÂÂstruct rga_ctx *curr;
> > > +};
> > > +
> > > +/* Controls */
> > > +
> > > +#define V4L2_CID_RGA_OP (V4L2_CID_USER_BASE | 0x1001)
> >
> > Could be nice to generalize. We could setup a control and fill the
> > values base on porter duff operations, then drivers can implement a
> > subset. Right now, there is no generic way for userspace to know if
> > a
> > driver is just doing copies with some transformations, or if it can
> > actually do alpha blending hence used for composting streams. Note
> > that
> > I haven't looked at all possibilities, Freescale IMX.6 seems to
> > have a
> > similar driver, which has been wrapped in GStreamer with this
> > proposed
> > elements:
> >
> > https://bugzilla.gnome.org/show_bug.cgi?id=772766
> >
>
> Yeah, i also want it use a generic api.
> "porter duff operations" looks good, i will look at it.
>
> > > +#define V4L2_CID_RGA_ALHPA_REG0 (V4L2_CID_USER_BASE | 0x1002)
> > > +#define V4L2_CID_RGA_ALHPA_REG1 (V4L2_CID_USER_BASE | 0x1003)
> >
> > It's not obvious why there is two CID, and how this differ from
> > existing V4L2_CID_ALPHA (the global alpha control).
>
> They are used to calculate factors for below formulas.
>
> ÂÂÂÂdst alpha = Factor1 * src alpha + Factor2 * dst alpha
> ÂÂÂÂdst color = Factor3 * src color + Factor4 * dst color
>
> I have no idea how to generalize it, and there is no upstream
> application need it,
> so i just simply exposed the reg.

Then maybe it's better to just not expose it in the public API in the
initial patch (nothing forces you to enable everything). The idea is
that it can be added later as needed, taking the time to figure-out a
new API or to figure-out how this matches anything that exist.

>
> > > +
> > > +/* Operation values */
> > > +#define OP_COPY 0
> > > +#define OP_SOLID_FILL 1
> > > +#define OP_ALPHA_BLEND 2
> > > +
> > > +struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum
> > > v4l2_buf_type type);
> > > +
> > > +/* RGA Buffers Manage Part */
> > > +extern const struct vb2_ops rga_qops;
> > > +void *rga_buf_find_page(struct vb2_buffer *vb);
> > > +void rga_buf_clean(struct rga_ctx *ctx);
> > > +
> > > +/* RGA Hardware Part */
> > > +void rga_write(struct rockchip_rga *rga, u32 reg, u32 value);
> > > +u32 rga_read(struct rockchip_rga *rga, u32 reg);
> > > +void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32
> > > mask);
> > > +void rga_start(struct rockchip_rga *rga);
> > > +void rga_cmd_set(struct rga_ctx *ctx, void *src_mmu_pages, void
> > > *dst_mmu_pages);
> > > +
> > > +#endif

Attachment: signature.asc
Description: This is a digitally signed message part