media: platform: place NXP drivers on a separate dir
authorMauro Carvalho Chehab <mchehab@kernel.org>
Thu, 10 Mar 2022 15:40:21 +0000 (16:40 +0100)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Mon, 14 Mar 2022 08:42:59 +0000 (09:42 +0100)
In order to cleanup the main platform media directory, move NXP
drivers to their own directory.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
29 files changed:
MAINTAINERS
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/fsl-viu.c [deleted file]
drivers/media/platform/imx-jpeg/Kconfig [deleted file]
drivers/media/platform/imx-jpeg/Makefile [deleted file]
drivers/media/platform/imx-jpeg/mxc-jpeg-hw.c [deleted file]
drivers/media/platform/imx-jpeg/mxc-jpeg-hw.h [deleted file]
drivers/media/platform/imx-jpeg/mxc-jpeg.c [deleted file]
drivers/media/platform/imx-jpeg/mxc-jpeg.h [deleted file]
drivers/media/platform/imx-pxp.c [deleted file]
drivers/media/platform/imx-pxp.h [deleted file]
drivers/media/platform/imx/Kconfig [deleted file]
drivers/media/platform/imx/Makefile [deleted file]
drivers/media/platform/imx/imx-mipi-csis.c [deleted file]
drivers/media/platform/mx2_emmaprp.c [deleted file]
drivers/media/platform/nxp/Kconfig [new file with mode: 0644]
drivers/media/platform/nxp/Makefile [new file with mode: 0644]
drivers/media/platform/nxp/fsl-viu.c [new file with mode: 0644]
drivers/media/platform/nxp/imx-jpeg/Kconfig [new file with mode: 0644]
drivers/media/platform/nxp/imx-jpeg/Makefile [new file with mode: 0644]
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c [new file with mode: 0644]
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.h [new file with mode: 0644]
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c [new file with mode: 0644]
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h [new file with mode: 0644]
drivers/media/platform/nxp/imx-mipi-csis.c [new file with mode: 0644]
drivers/media/platform/nxp/imx-pxp.c [new file with mode: 0644]
drivers/media/platform/nxp/imx-pxp.h [new file with mode: 0644]
drivers/media/platform/nxp/mx2_emmaprp.c [new file with mode: 0644]

index 1b6f48a660de3d0005cc96d59e17bd70dfdd4726..780ef2ef3362b5a42debeff6ae0e4723632a2011 100644 (file)
@@ -11841,7 +11841,7 @@ M:      Philipp Zabel <p.zabel@pengutronix.de>
 L:     linux-media@vger.kernel.org
 S:     Maintained
 T:     git git://linuxtv.org/media_tree.git
-F:     drivers/media/platform/imx-pxp.[ch]
+F:     drivers/media/platform/nxp/imx-pxp.[ch]
 
 MEDIA DRIVERS FOR ASCOT2E
 M:     Sergey Kozlov <serjk@netup.ru>
index 10f453ff2717c99080af296294d3995687c828a4..711b6ab9370b4f57f2c345b94dd6271f5eee4b05 100644 (file)
@@ -29,6 +29,8 @@ config V4L_MEM2MEM_DRIVERS
          to capture and output drivers, which use memory buffers for just
          one of those.
 
+source "drivers/media/platform/nxp/Kconfig"
+
 # V4L platform drivers
 
 source "drivers/media/platform/marvell-ccic/Kconfig"
@@ -61,19 +63,6 @@ config VIDEO_SH_VOU
        help
          Support for the Video Output Unit (VOU) on SuperH SoCs.
 
-config VIDEO_VIU
-       tristate "Freescale VIU Video Driver"
-       depends on V4L_PLATFORM_DRIVERS
-       depends on VIDEO_V4L2 && (PPC_MPC512x || COMPILE_TEST) && I2C
-       select VIDEOBUF_DMA_CONTIG
-       default y
-       help
-         Support for Freescale VIU video driver. This device captures
-         video data, or overlays video on DIU frame buffer.
-
-         Say Y here if you want to enable VIU device on MPC5121e Rev2+.
-         In doubt, say N.
-
 config VIDEO_MUX
        tristate "Video Multiplexer"
        depends on V4L_PLATFORM_DRIVERS
@@ -193,7 +182,6 @@ source "drivers/media/platform/xilinx/Kconfig"
 source "drivers/media/platform/rcar-vin/Kconfig"
 source "drivers/media/platform/atmel/Kconfig"
 source "drivers/media/platform/sunxi/Kconfig"
-source "drivers/media/platform/imx/Kconfig"
 
 config VIDEO_TI_CAL
        tristate "TI CAL (Camera Adaptation Layer) driver"
@@ -273,18 +261,6 @@ config VIDEO_CODA
 config VIDEO_IMX_VDOA
        def_tristate VIDEO_CODA if SOC_IMX6Q || COMPILE_TEST
 
-config VIDEO_IMX_PXP
-       tristate "i.MX Pixel Pipeline (PXP)"
-       depends on V4L_MEM2MEM_DRIVERS
-       depends on VIDEO_DEV && VIDEO_V4L2 && (ARCH_MXC || COMPILE_TEST)
-       select VIDEOBUF2_DMA_CONTIG
-       select V4L2_MEM2MEM_DEV
-       help
-         The i.MX Pixel Pipeline is a memory-to-memory engine for scaling,
-         color space conversion, and rotation.
-
-source "drivers/media/platform/imx-jpeg/Kconfig"
-
 config VIDEO_MEDIATEK_JPEG
        tristate "Mediatek JPEG Codec driver"
        depends on V4L_MEM2MEM_DRIVERS
@@ -423,18 +399,6 @@ config VIDEO_SAMSUNG_S5P_MFC
        help
            MFC 5.1 and 6.x driver for V4L2
 
-config VIDEO_MX2_EMMAPRP
-       tristate "MX2 eMMa-PrP support"
-       depends on V4L_MEM2MEM_DRIVERS
-       depends on VIDEO_DEV && VIDEO_V4L2
-       depends on SOC_IMX27 || COMPILE_TEST
-       select VIDEOBUF2_DMA_CONTIG
-       select V4L2_MEM2MEM_DEV
-       help
-           MX2X chips have a PrP that can be used to process buffers from
-           memory to memory. Operations include resizing and format
-           conversion.
-
 config VIDEO_SAMSUNG_EXYNOS_GSC
        tristate "Samsung Exynos G-Scaler driver"
        depends on V4L_MEM2MEM_DRIVERS
index 18ec3d2084836c6a77fd816ce96174c02bb0a2b8..4458690c196515ce4baf0482d728a78d4835eb52 100644 (file)
@@ -15,14 +15,13 @@ obj-y += coda/
 obj-y += davinci/
 obj-y += exynos-gsc/
 obj-y += exynos4-is/
-obj-y += imx/
-obj-y += imx-jpeg/
 obj-y += marvell-ccic/
 obj-y += meson/ge2d/
 obj-y += mtk-jpeg/
 obj-y += mtk-mdp/
 obj-y += mtk-vcodec/
 obj-y += mtk-vpu/
+obj-y += nxp/
 obj-y += omap/
 obj-y += omap3isp/
 obj-y += qcom/camss/
@@ -48,10 +47,8 @@ obj-y += xilinx/
 # Please place here only ancillary drivers that aren't SoC-specific
 # Please keep it alphabetically sorted by Kconfig name
 # (e. g. LC_ALL=C sort Makefile)
-obj-$(CONFIG_VIDEO_IMX_PXP)            += imx-pxp.o
 obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE)        += m2m-deinterlace.o
 obj-$(CONFIG_VIDEO_MUX)                        += video-mux.o
-obj-$(CONFIG_VIDEO_MX2_EMMAPRP)                += mx2_emmaprp.o
 obj-$(CONFIG_VIDEO_PXA27x)             += pxa_camera.o
 obj-$(CONFIG_VIDEO_RCAR_DRIF)          += rcar_drif.o
 obj-$(CONFIG_VIDEO_RCAR_ISP)           += rcar-isp.o
@@ -61,4 +58,3 @@ obj-$(CONFIG_VIDEO_RENESAS_FDP1)      += rcar_fdp1.o
 obj-$(CONFIG_VIDEO_RENESAS_JPU)                += rcar_jpu.o
 obj-$(CONFIG_VIDEO_SH_VOU)             += sh_vou.o
 obj-$(CONFIG_VIDEO_VIA_CAMERA)         += via-camera.o
-obj-$(CONFIG_VIDEO_VIU)                        += fsl-viu.o
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
deleted file mode 100644 (file)
index afc96f6..0000000
+++ /dev/null
@@ -1,1599 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- *  Freescale VIU video driver
- *
- *  Authors: Hongjun Chen <hong-jun.chen@freescale.com>
- *          Porting to 2.6.35 by DENX Software Engineering,
- *          Anatolij Gustschin <agust@denx.de>
- */
-
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/slab.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf-dma-contig.h>
-
-#define DRV_NAME               "fsl_viu"
-#define VIU_VERSION            "0.5.1"
-
-#define BUFFER_TIMEOUT         msecs_to_jiffies(500)  /* 0.5 seconds */
-
-#define        VIU_VID_MEM_LIMIT       4       /* Video memory limit, in Mb */
-
-/* I2C address of video decoder chip is 0x4A */
-#define VIU_VIDEO_DECODER_ADDR 0x25
-
-static int info_level;
-
-#define dprintk(level, fmt, arg...)                                    \
-       do {                                                            \
-               if (level <= info_level)                                \
-                       printk(KERN_DEBUG "viu: " fmt , ## arg);        \
-       } while (0)
-
-/*
- * Basic structures
- */
-struct viu_fmt {
-       u32   fourcc;           /* v4l2 format id */
-       u32   pixelformat;
-       int   depth;
-};
-
-static struct viu_fmt formats[] = {
-       {
-               .fourcc         = V4L2_PIX_FMT_RGB565,
-               .pixelformat    = V4L2_PIX_FMT_RGB565,
-               .depth          = 16,
-       }, {
-               .fourcc         = V4L2_PIX_FMT_RGB32,
-               .pixelformat    = V4L2_PIX_FMT_RGB32,
-               .depth          = 32,
-       }
-};
-
-struct viu_dev;
-struct viu_buf;
-
-/* buffer for one video frame */
-struct viu_buf {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-       struct viu_fmt *fmt;
-};
-
-struct viu_dmaqueue {
-       struct viu_dev          *dev;
-       struct list_head        active;
-       struct list_head        queued;
-       struct timer_list       timeout;
-};
-
-struct viu_status {
-       u32 field_irq;
-       u32 vsync_irq;
-       u32 hsync_irq;
-       u32 vstart_irq;
-       u32 dma_end_irq;
-       u32 error_irq;
-};
-
-struct viu_reg {
-       u32 status_cfg;
-       u32 luminance;
-       u32 chroma_r;
-       u32 chroma_g;
-       u32 chroma_b;
-       u32 field_base_addr;
-       u32 dma_inc;
-       u32 picture_count;
-       u32 req_alarm;
-       u32 alpha;
-} __attribute__ ((packed));
-
-struct viu_dev {
-       struct v4l2_device      v4l2_dev;
-       struct v4l2_ctrl_handler hdl;
-       struct mutex            lock;
-       spinlock_t              slock;
-       int                     users;
-
-       struct device           *dev;
-       /* various device info */
-       struct video_device     *vdev;
-       struct viu_dmaqueue     vidq;
-       enum v4l2_field         capfield;
-       int                     field;
-       int                     first;
-       int                     dma_done;
-
-       /* Hardware register area */
-       struct viu_reg __iomem  *vr;
-
-       /* Interrupt vector */
-       int                     irq;
-       struct viu_status       irqs;
-
-       /* video overlay */
-       struct v4l2_framebuffer ovbuf;
-       struct viu_fmt          *ovfmt;
-       unsigned int            ovenable;
-       enum v4l2_field         ovfield;
-
-       /* crop */
-       struct v4l2_rect        crop_current;
-
-       /* clock pointer */
-       struct clk              *clk;
-
-       /* decoder */
-       struct v4l2_subdev      *decoder;
-
-       v4l2_std_id             std;
-};
-
-struct viu_fh {
-       /* must remain the first field of this struct */
-       struct v4l2_fh          fh;
-       struct viu_dev          *dev;
-
-       /* video capture */
-       struct videobuf_queue   vb_vidq;
-       spinlock_t              vbq_lock; /* spinlock for the videobuf queue */
-
-       /* video overlay */
-       struct v4l2_window      win;
-       struct v4l2_clip        clips[1];
-
-       /* video capture */
-       struct viu_fmt          *fmt;
-       int                     width, height, sizeimage;
-       enum v4l2_buf_type      type;
-};
-
-static struct viu_reg reg_val;
-
-/*
- * Macro definitions of VIU registers
- */
-
-/* STATUS_CONFIG register */
-enum status_config {
-       SOFT_RST                = 1 << 0,
-
-       ERR_MASK                = 0x0f << 4,    /* Error code mask */
-       ERR_NO                  = 0x00,         /* No error */
-       ERR_DMA_V               = 0x01 << 4,    /* DMA in vertical active */
-       ERR_DMA_VB              = 0x02 << 4,    /* DMA in vertical blanking */
-       ERR_LINE_TOO_LONG       = 0x04 << 4,    /* Line too long */
-       ERR_TOO_MANG_LINES      = 0x05 << 4,    /* Too many lines in field */
-       ERR_LINE_TOO_SHORT      = 0x06 << 4,    /* Line too short */
-       ERR_NOT_ENOUGH_LINE     = 0x07 << 4,    /* Not enough lines in field */
-       ERR_FIFO_OVERFLOW       = 0x08 << 4,    /* FIFO overflow */
-       ERR_FIFO_UNDERFLOW      = 0x09 << 4,    /* FIFO underflow */
-       ERR_1bit_ECC            = 0x0a << 4,    /* One bit ECC error */
-       ERR_MORE_ECC            = 0x0b << 4,    /* Two/more bits ECC error */
-
-       INT_FIELD_EN            = 0x01 << 8,    /* Enable field interrupt */
-       INT_VSYNC_EN            = 0x01 << 9,    /* Enable vsync interrupt */
-       INT_HSYNC_EN            = 0x01 << 10,   /* Enable hsync interrupt */
-       INT_VSTART_EN           = 0x01 << 11,   /* Enable vstart interrupt */
-       INT_DMA_END_EN          = 0x01 << 12,   /* Enable DMA end interrupt */
-       INT_ERROR_EN            = 0x01 << 13,   /* Enable error interrupt */
-       INT_ECC_EN              = 0x01 << 14,   /* Enable ECC interrupt */
-
-       INT_FIELD_STATUS        = 0x01 << 16,   /* field interrupt status */
-       INT_VSYNC_STATUS        = 0x01 << 17,   /* vsync interrupt status */
-       INT_HSYNC_STATUS        = 0x01 << 18,   /* hsync interrupt status */
-       INT_VSTART_STATUS       = 0x01 << 19,   /* vstart interrupt status */
-       INT_DMA_END_STATUS      = 0x01 << 20,   /* DMA end interrupt status */
-       INT_ERROR_STATUS        = 0x01 << 21,   /* error interrupt status */
-
-       DMA_ACT                 = 0x01 << 27,   /* Enable DMA transfer */
-       FIELD_NO                = 0x01 << 28,   /* Field number */
-       DITHER_ON               = 0x01 << 29,   /* Dithering is on */
-       ROUND_ON                = 0x01 << 30,   /* Round is on */
-       MODE_32BIT              = 1UL << 31,    /* Data in RGBa888,
-                                                * 0 in RGB565
-                                                */
-};
-
-#define norm_maxw()    720
-#define norm_maxh()    576
-
-#define INT_ALL_STATUS (INT_FIELD_STATUS | INT_VSYNC_STATUS | \
-                        INT_HSYNC_STATUS | INT_VSTART_STATUS | \
-                        INT_DMA_END_STATUS | INT_ERROR_STATUS)
-
-#define NUM_FORMATS    ARRAY_SIZE(formats)
-
-static irqreturn_t viu_intr(int irq, void *dev_id);
-
-static struct viu_fmt *format_by_fourcc(int fourcc)
-{
-       int i;
-
-       for (i = 0; i < NUM_FORMATS; i++) {
-               if (formats[i].pixelformat == fourcc)
-                       return formats + i;
-       }
-
-       dprintk(0, "unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
-       return NULL;
-}
-
-static void viu_start_dma(struct viu_dev *dev)
-{
-       struct viu_reg __iomem *vr = dev->vr;
-
-       dev->field = 0;
-
-       /* Enable DMA operation */
-       iowrite32be(SOFT_RST, &vr->status_cfg);
-       iowrite32be(INT_FIELD_EN, &vr->status_cfg);
-}
-
-static void viu_stop_dma(struct viu_dev *dev)
-{
-       struct viu_reg __iomem *vr = dev->vr;
-       int cnt = 100;
-       u32 status_cfg;
-
-       iowrite32be(0, &vr->status_cfg);
-
-       /* Clear pending interrupts */
-       status_cfg = ioread32be(&vr->status_cfg);
-       if (status_cfg & 0x3f0000)
-               iowrite32be(status_cfg & 0x3f0000, &vr->status_cfg);
-
-       if (status_cfg & DMA_ACT) {
-               do {
-                       status_cfg = ioread32be(&vr->status_cfg);
-                       if (status_cfg & INT_DMA_END_STATUS)
-                               break;
-               } while (cnt--);
-
-               if (cnt < 0) {
-                       /* timed out, issue soft reset */
-                       iowrite32be(SOFT_RST, &vr->status_cfg);
-                       iowrite32be(0, &vr->status_cfg);
-               } else {
-                       /* clear DMA_END and other pending irqs */
-                       iowrite32be(status_cfg & 0x3f0000, &vr->status_cfg);
-               }
-       }
-
-       dev->field = 0;
-}
-
-static int restart_video_queue(struct viu_dmaqueue *vidq)
-{
-       struct viu_buf *buf, *prev;
-
-       dprintk(1, "%s vidq=%p\n", __func__, vidq);
-       if (!list_empty(&vidq->active)) {
-               buf = list_entry(vidq->active.next, struct viu_buf, vb.queue);
-               dprintk(2, "restart_queue [%p/%d]: restart dma\n",
-                       buf, buf->vb.i);
-
-               viu_stop_dma(vidq->dev);
-
-               /* cancel all outstanding capture requests */
-               list_for_each_entry_safe(buf, prev, &vidq->active, vb.queue) {
-                       list_del(&buf->vb.queue);
-                       buf->vb.state = VIDEOBUF_ERROR;
-                       wake_up(&buf->vb.done);
-               }
-               mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
-               return 0;
-       }
-
-       prev = NULL;
-       for (;;) {
-               if (list_empty(&vidq->queued))
-                       return 0;
-               buf = list_entry(vidq->queued.next, struct viu_buf, vb.queue);
-               if (prev == NULL) {
-                       list_move_tail(&buf->vb.queue, &vidq->active);
-
-                       dprintk(1, "Restarting video dma\n");
-                       viu_stop_dma(vidq->dev);
-                       viu_start_dma(vidq->dev);
-
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
-                       dprintk(2, "[%p/%d] restart_queue - first active\n",
-                               buf, buf->vb.i);
-
-               } else if (prev->vb.width  == buf->vb.width  &&
-                          prev->vb.height == buf->vb.height &&
-                          prev->fmt       == buf->fmt) {
-                       list_move_tail(&buf->vb.queue, &vidq->active);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       dprintk(2, "[%p/%d] restart_queue - move to active\n",
-                               buf, buf->vb.i);
-               } else {
-                       return 0;
-               }
-               prev = buf;
-       }
-}
-
-static void viu_vid_timeout(struct timer_list *t)
-{
-       struct viu_dev *dev = from_timer(dev, t, vidq.timeout);
-       struct viu_buf *buf;
-       struct viu_dmaqueue *vidq = &dev->vidq;
-
-       while (!list_empty(&vidq->active)) {
-               buf = list_entry(vidq->active.next, struct viu_buf, vb.queue);
-               list_del(&buf->vb.queue);
-               buf->vb.state = VIDEOBUF_ERROR;
-               wake_up(&buf->vb.done);
-               dprintk(1, "viu/0: [%p/%d] timeout\n", buf, buf->vb.i);
-       }
-
-       restart_video_queue(vidq);
-}
-
-/*
- * Videobuf operations
- */
-static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
-                       unsigned int *size)
-{
-       struct viu_fh *fh = vq->priv_data;
-
-       *size = fh->width * fh->height * fh->fmt->depth >> 3;
-       if (*count == 0)
-               *count = 32;
-
-       while (*size * *count > VIU_VID_MEM_LIMIT * 1024 * 1024)
-               (*count)--;
-
-       dprintk(1, "%s, count=%d, size=%d\n", __func__, *count, *size);
-       return 0;
-}
-
-static void free_buffer(struct videobuf_queue *vq, struct viu_buf *buf)
-{
-       struct videobuf_buffer *vb = &buf->vb;
-       void *vaddr = NULL;
-
-       videobuf_waiton(vq, &buf->vb, 0, 0);
-
-       if (vq->int_ops && vq->int_ops->vaddr)
-               vaddr = vq->int_ops->vaddr(vb);
-
-       if (vaddr)
-               videobuf_dma_contig_free(vq, &buf->vb);
-
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-inline int buffer_activate(struct viu_dev *dev, struct viu_buf *buf)
-{
-       struct viu_reg __iomem *vr = dev->vr;
-       int bpp;
-
-       /* setup the DMA base address */
-       reg_val.field_base_addr = videobuf_to_dma_contig(&buf->vb);
-
-       dprintk(1, "buffer_activate [%p/%d]: dma addr 0x%lx\n",
-               buf, buf->vb.i, (unsigned long)reg_val.field_base_addr);
-
-       /* interlace is on by default, set horizontal DMA increment */
-       reg_val.status_cfg = 0;
-       bpp = buf->fmt->depth >> 3;
-       switch (bpp) {
-       case 2:
-               reg_val.status_cfg &= ~MODE_32BIT;
-               reg_val.dma_inc = buf->vb.width * 2;
-               break;
-       case 4:
-               reg_val.status_cfg |= MODE_32BIT;
-               reg_val.dma_inc = buf->vb.width * 4;
-               break;
-       default:
-               dprintk(0, "doesn't support color depth(%d)\n",
-                       bpp * 8);
-               return -EINVAL;
-       }
-
-       /* setup picture_count register */
-       reg_val.picture_count = (buf->vb.height / 2) << 16 |
-                               buf->vb.width;
-
-       reg_val.status_cfg |= DMA_ACT | INT_DMA_END_EN | INT_FIELD_EN;
-
-       buf->vb.state = VIDEOBUF_ACTIVE;
-       dev->capfield = buf->vb.field;
-
-       /* reset dma increment if needed */
-       if (!V4L2_FIELD_HAS_BOTH(buf->vb.field))
-               reg_val.dma_inc = 0;
-
-       iowrite32be(reg_val.dma_inc, &vr->dma_inc);
-       iowrite32be(reg_val.picture_count, &vr->picture_count);
-       iowrite32be(reg_val.field_base_addr, &vr->field_base_addr);
-       mod_timer(&dev->vidq.timeout, jiffies + BUFFER_TIMEOUT);
-       return 0;
-}
-
-static int buffer_prepare(struct videobuf_queue *vq,
-                         struct videobuf_buffer *vb,
-                         enum v4l2_field field)
-{
-       struct viu_fh  *fh  = vq->priv_data;
-       struct viu_buf *buf = container_of(vb, struct viu_buf, vb);
-       int rc;
-
-       BUG_ON(fh->fmt == NULL);
-
-       if (fh->width  < 48 || fh->width  > norm_maxw() ||
-           fh->height < 32 || fh->height > norm_maxh())
-               return -EINVAL;
-       buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
-       if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size)
-               return -EINVAL;
-
-       if (buf->fmt       != fh->fmt    ||
-           buf->vb.width  != fh->width  ||
-           buf->vb.height != fh->height ||
-           buf->vb.field  != field) {
-               buf->fmt       = fh->fmt;
-               buf->vb.width  = fh->width;
-               buf->vb.height = fh->height;
-               buf->vb.field  = field;
-       }
-
-       if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
-               rc = videobuf_iolock(vq, &buf->vb, NULL);
-               if (rc != 0)
-                       goto fail;
-
-               buf->vb.width  = fh->width;
-               buf->vb.height = fh->height;
-               buf->vb.field  = field;
-               buf->fmt       = fh->fmt;
-       }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
-fail:
-       free_buffer(vq, buf);
-       return rc;
-}
-
-static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct viu_buf       *buf     = container_of(vb, struct viu_buf, vb);
-       struct viu_fh        *fh      = vq->priv_data;
-       struct viu_dev       *dev     = fh->dev;
-       struct viu_dmaqueue  *vidq    = &dev->vidq;
-       struct viu_buf       *prev;
-
-       if (!list_empty(&vidq->queued)) {
-               dprintk(1, "adding vb queue=%p\n", &buf->vb.queue);
-               dprintk(1, "vidq pointer 0x%p, queued 0x%p\n",
-                               vidq, &vidq->queued);
-               dprintk(1, "dev %p, queued: self %p, next %p, head %p\n",
-                       dev, &vidq->queued, vidq->queued.next,
-                       vidq->queued.prev);
-               list_add_tail(&buf->vb.queue, &vidq->queued);
-               buf->vb.state = VIDEOBUF_QUEUED;
-               dprintk(2, "[%p/%d] buffer_queue - append to queued\n",
-                       buf, buf->vb.i);
-       } else if (list_empty(&vidq->active)) {
-               dprintk(1, "adding vb active=%p\n", &buf->vb.queue);
-               list_add_tail(&buf->vb.queue, &vidq->active);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
-               dprintk(2, "[%p/%d] buffer_queue - first active\n",
-                       buf, buf->vb.i);
-
-               buffer_activate(dev, buf);
-       } else {
-               dprintk(1, "adding vb queue2=%p\n", &buf->vb.queue);
-               prev = list_entry(vidq->active.prev, struct viu_buf, vb.queue);
-               if (prev->vb.width  == buf->vb.width  &&
-                   prev->vb.height == buf->vb.height &&
-                   prev->fmt       == buf->fmt) {
-                       list_add_tail(&buf->vb.queue, &vidq->active);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       dprintk(2, "[%p/%d] buffer_queue - append to active\n",
-                               buf, buf->vb.i);
-               } else {
-                       list_add_tail(&buf->vb.queue, &vidq->queued);
-                       buf->vb.state = VIDEOBUF_QUEUED;
-                       dprintk(2, "[%p/%d] buffer_queue - first queued\n",
-                               buf, buf->vb.i);
-               }
-       }
-}
-
-static void buffer_release(struct videobuf_queue *vq,
-                               struct videobuf_buffer *vb)
-{
-       struct viu_buf *buf  = container_of(vb, struct viu_buf, vb);
-       struct viu_fh  *fh   = vq->priv_data;
-       struct viu_dev *dev  = (struct viu_dev *)fh->dev;
-
-       viu_stop_dma(dev);
-       free_buffer(vq, buf);
-}
-
-static const struct videobuf_queue_ops viu_video_qops = {
-       .buf_setup      = buffer_setup,
-       .buf_prepare    = buffer_prepare,
-       .buf_queue      = buffer_queue,
-       .buf_release    = buffer_release,
-};
-
-/*
- * IOCTL vidioc handling
- */
-static int vidioc_querycap(struct file *file, void *priv,
-                          struct v4l2_capability *cap)
-{
-       strscpy(cap->driver, "viu", sizeof(cap->driver));
-       strscpy(cap->card, "viu", sizeof(cap->card));
-       strscpy(cap->bus_info, "platform:viu", sizeof(cap->bus_info));
-       return 0;
-}
-
-static int vidioc_enum_fmt(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       int index = f->index;
-
-       if (f->index >= NUM_FORMATS)
-               return -EINVAL;
-
-       f->pixelformat = formats[index].fourcc;
-       return 0;
-}
-
-static int vidioc_g_fmt_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct viu_fh *fh = priv;
-
-       f->fmt.pix.width        = fh->width;
-       f->fmt.pix.height       = fh->height;
-       f->fmt.pix.field        = fh->vb_vidq.field;
-       f->fmt.pix.pixelformat  = fh->fmt->pixelformat;
-       f->fmt.pix.bytesperline =
-                       (f->fmt.pix.width * fh->fmt->depth) >> 3;
-       f->fmt.pix.sizeimage    = fh->sizeimage;
-       f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-       return 0;
-}
-
-static int vidioc_try_fmt_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct viu_fmt *fmt;
-       unsigned int maxw, maxh;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (!fmt) {
-               dprintk(1, "Fourcc format (0x%08x) invalid.",
-                       f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       maxw  = norm_maxw();
-       maxh  = norm_maxh();
-
-       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       if (f->fmt.pix.height < 32)
-               f->fmt.pix.height = 32;
-       if (f->fmt.pix.height > maxh)
-               f->fmt.pix.height = maxh;
-       if (f->fmt.pix.width < 48)
-               f->fmt.pix.width = 48;
-       if (f->fmt.pix.width > maxw)
-               f->fmt.pix.width = maxw;
-       f->fmt.pix.width &= ~0x03;
-       f->fmt.pix.bytesperline =
-               (f->fmt.pix.width * fmt->depth) >> 3;
-       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-
-       return 0;
-}
-
-static int vidioc_s_fmt_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct viu_fh *fh = priv;
-       int ret;
-
-       ret = vidioc_try_fmt_cap(file, fh, f);
-       if (ret < 0)
-               return ret;
-
-       fh->fmt           = format_by_fourcc(f->fmt.pix.pixelformat);
-       fh->width         = f->fmt.pix.width;
-       fh->height        = f->fmt.pix.height;
-       fh->sizeimage     = f->fmt.pix.sizeimage;
-       fh->vb_vidq.field = f->fmt.pix.field;
-       fh->type          = f->type;
-       return 0;
-}
-
-static int vidioc_g_fmt_overlay(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct viu_fh *fh = priv;
-
-       f->fmt.win = fh->win;
-       return 0;
-}
-
-static int verify_preview(struct viu_dev *dev, struct v4l2_window *win)
-{
-       enum v4l2_field field;
-       int maxw, maxh;
-
-       if (dev->ovbuf.base == NULL)
-               return -EINVAL;
-       if (dev->ovfmt == NULL)
-               return -EINVAL;
-       if (win->w.width < 48 || win->w.height < 32)
-               return -EINVAL;
-
-       field = win->field;
-       maxw  = dev->crop_current.width;
-       maxh  = dev->crop_current.height;
-
-       if (field == V4L2_FIELD_ANY) {
-               field = (win->w.height > maxh/2)
-                       ? V4L2_FIELD_INTERLACED
-                       : V4L2_FIELD_TOP;
-       }
-       switch (field) {
-       case V4L2_FIELD_TOP:
-       case V4L2_FIELD_BOTTOM:
-               maxh = maxh / 2;
-               break;
-       case V4L2_FIELD_INTERLACED:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       win->field = field;
-       if (win->w.width > maxw)
-               win->w.width = maxw;
-       if (win->w.height > maxh)
-               win->w.height = maxh;
-       return 0;
-}
-
-inline void viu_activate_overlay(struct viu_reg __iomem *vr)
-{
-       iowrite32be(reg_val.field_base_addr, &vr->field_base_addr);
-       iowrite32be(reg_val.dma_inc, &vr->dma_inc);
-       iowrite32be(reg_val.picture_count, &vr->picture_count);
-}
-
-static int viu_setup_preview(struct viu_dev *dev, struct viu_fh *fh)
-{
-       int bpp;
-
-       dprintk(1, "%s %dx%d\n", __func__,
-               fh->win.w.width, fh->win.w.height);
-
-       reg_val.status_cfg = 0;
-
-       /* setup window */
-       reg_val.picture_count = (fh->win.w.height / 2) << 16 |
-                               fh->win.w.width;
-
-       /* setup color depth and dma increment */
-       bpp = dev->ovfmt->depth / 8;
-       switch (bpp) {
-       case 2:
-               reg_val.status_cfg &= ~MODE_32BIT;
-               reg_val.dma_inc = fh->win.w.width * 2;
-               break;
-       case 4:
-               reg_val.status_cfg |= MODE_32BIT;
-               reg_val.dma_inc = fh->win.w.width * 4;
-               break;
-       default:
-               dprintk(0, "device doesn't support color depth(%d)\n",
-                       bpp * 8);
-               return -EINVAL;
-       }
-
-       dev->ovfield = fh->win.field;
-       if (!V4L2_FIELD_HAS_BOTH(dev->ovfield))
-               reg_val.dma_inc = 0;
-
-       reg_val.status_cfg |= DMA_ACT | INT_DMA_END_EN | INT_FIELD_EN;
-
-       /* setup the base address of the overlay buffer */
-       reg_val.field_base_addr = (u32)(long)dev->ovbuf.base;
-
-       return 0;
-}
-
-static int vidioc_s_fmt_overlay(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct viu_fh  *fh  = priv;
-       struct viu_dev *dev = (struct viu_dev *)fh->dev;
-       unsigned long  flags;
-       int err;
-
-       err = verify_preview(dev, &f->fmt.win);
-       if (err)
-               return err;
-
-       fh->win = f->fmt.win;
-
-       spin_lock_irqsave(&dev->slock, flags);
-       viu_setup_preview(dev, fh);
-       spin_unlock_irqrestore(&dev->slock, flags);
-       return 0;
-}
-
-static int vidioc_try_fmt_overlay(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       return 0;
-}
-
-static int vidioc_overlay(struct file *file, void *priv, unsigned int on)
-{
-       struct viu_fh  *fh  = priv;
-       struct viu_dev *dev = (struct viu_dev *)fh->dev;
-       unsigned long  flags;
-
-       if (on) {
-               spin_lock_irqsave(&dev->slock, flags);
-               viu_activate_overlay(dev->vr);
-               dev->ovenable = 1;
-
-               /* start dma */
-               viu_start_dma(dev);
-               spin_unlock_irqrestore(&dev->slock, flags);
-       } else {
-               viu_stop_dma(dev);
-               dev->ovenable = 0;
-       }
-
-       return 0;
-}
-
-static int vidioc_g_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *arg)
-{
-       struct viu_fh  *fh = priv;
-       struct viu_dev *dev = fh->dev;
-       struct v4l2_framebuffer *fb = arg;
-
-       *fb = dev->ovbuf;
-       fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-       return 0;
-}
-
-static int vidioc_s_fbuf(struct file *file, void *priv, const struct v4l2_framebuffer *arg)
-{
-       struct viu_fh  *fh = priv;
-       struct viu_dev *dev = fh->dev;
-       const struct v4l2_framebuffer *fb = arg;
-       struct viu_fmt *fmt;
-
-       if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
-               return -EPERM;
-
-       /* check args */
-       fmt = format_by_fourcc(fb->fmt.pixelformat);
-       if (fmt == NULL)
-               return -EINVAL;
-
-       /* ok, accept it */
-       dev->ovbuf = *fb;
-       dev->ovfmt = fmt;
-       if (dev->ovbuf.fmt.bytesperline == 0) {
-               dev->ovbuf.fmt.bytesperline =
-                       dev->ovbuf.fmt.width * fmt->depth / 8;
-       }
-       return 0;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-                               struct v4l2_requestbuffers *p)
-{
-       struct viu_fh *fh = priv;
-
-       return videobuf_reqbufs(&fh->vb_vidq, p);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-                                       struct v4l2_buffer *p)
-{
-       struct viu_fh *fh = priv;
-
-       return videobuf_querybuf(&fh->vb_vidq, p);
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct viu_fh *fh = priv;
-
-       return videobuf_qbuf(&fh->vb_vidq, p);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct viu_fh *fh = priv;
-
-       return videobuf_dqbuf(&fh->vb_vidq, p,
-                               file->f_flags & O_NONBLOCK);
-}
-
-static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct viu_fh *fh = priv;
-       struct viu_dev *dev = fh->dev;
-
-       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       if (fh->type != i)
-               return -EINVAL;
-
-       if (dev->ovenable)
-               dev->ovenable = 0;
-
-       viu_start_dma(fh->dev);
-
-       return videobuf_streamon(&fh->vb_vidq);
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct viu_fh  *fh = priv;
-
-       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       if (fh->type != i)
-               return -EINVAL;
-
-       viu_stop_dma(fh->dev);
-
-       return videobuf_streamoff(&fh->vb_vidq);
-}
-
-#define decoder_call(viu, o, f, args...) \
-       v4l2_subdev_call(viu->decoder, o, f, ##args)
-
-static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
-{
-       struct viu_fh *fh = priv;
-
-       decoder_call(fh->dev, video, querystd, std_id);
-       return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
-{
-       struct viu_fh *fh = priv;
-
-       fh->dev->std = id;
-       decoder_call(fh->dev, video, s_std, id);
-       return 0;
-}
-
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std_id)
-{
-       struct viu_fh *fh = priv;
-
-       *std_id = fh->dev->std;
-       return 0;
-}
-
-/* only one input in this driver */
-static int vidioc_enum_input(struct file *file, void *priv,
-                                       struct v4l2_input *inp)
-{
-       struct viu_fh *fh = priv;
-
-       if (inp->index != 0)
-               return -EINVAL;
-
-       inp->type = V4L2_INPUT_TYPE_CAMERA;
-       inp->std = fh->dev->vdev->tvnorms;
-       strscpy(inp->name, "Camera", sizeof(inp->name));
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       struct viu_fh *fh = priv;
-
-       if (i)
-               return -EINVAL;
-
-       decoder_call(fh->dev, video, s_routing, i, 0, 0);
-       return 0;
-}
-
-inline void viu_activate_next_buf(struct viu_dev *dev,
-                               struct viu_dmaqueue *viuq)
-{
-       struct viu_dmaqueue *vidq = viuq;
-       struct viu_buf *buf;
-
-       /* launch another DMA operation for an active/queued buffer */
-       if (!list_empty(&vidq->active)) {
-               buf = list_entry(vidq->active.next, struct viu_buf,
-                                       vb.queue);
-               dprintk(1, "start another queued buffer: 0x%p\n", buf);
-               buffer_activate(dev, buf);
-       } else if (!list_empty(&vidq->queued)) {
-               buf = list_entry(vidq->queued.next, struct viu_buf,
-                                       vb.queue);
-               list_del(&buf->vb.queue);
-
-               dprintk(1, "start another queued buffer: 0x%p\n", buf);
-               list_add_tail(&buf->vb.queue, &vidq->active);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               buffer_activate(dev, buf);
-       }
-}
-
-inline void viu_default_settings(struct viu_reg __iomem *vr)
-{
-       iowrite32be(0x9512A254, &vr->luminance);
-       iowrite32be(0x03310000, &vr->chroma_r);
-       iowrite32be(0x06600F38, &vr->chroma_g);
-       iowrite32be(0x00000409, &vr->chroma_b);
-       iowrite32be(0x000000ff, &vr->alpha);
-       iowrite32be(0x00000090, &vr->req_alarm);
-       dprintk(1, "status reg: 0x%08x, field base: 0x%08x\n",
-               ioread32be(&vr->status_cfg), ioread32be(&vr->field_base_addr));
-}
-
-static void viu_overlay_intr(struct viu_dev *dev, u32 status)
-{
-       struct viu_reg __iomem *vr = dev->vr;
-
-       if (status & INT_DMA_END_STATUS)
-               dev->dma_done = 1;
-
-       if (status & INT_FIELD_STATUS) {
-               if (dev->dma_done) {
-                       u32 addr = reg_val.field_base_addr;
-
-                       dev->dma_done = 0;
-                       if (status & FIELD_NO)
-                               addr += reg_val.dma_inc;
-
-                       iowrite32be(addr, &vr->field_base_addr);
-                       iowrite32be(reg_val.dma_inc, &vr->dma_inc);
-                       iowrite32be((status & 0xffc0ffff) |
-                                (status & INT_ALL_STATUS) |
-                                reg_val.status_cfg, &vr->status_cfg);
-               } else if (status & INT_VSYNC_STATUS) {
-                       iowrite32be((status & 0xffc0ffff) |
-                                (status & INT_ALL_STATUS) |
-                                reg_val.status_cfg, &vr->status_cfg);
-               }
-       }
-}
-
-static void viu_capture_intr(struct viu_dev *dev, u32 status)
-{
-       struct viu_dmaqueue *vidq = &dev->vidq;
-       struct viu_reg __iomem *vr = dev->vr;
-       struct viu_buf *buf;
-       int field_num;
-       int need_two;
-       int dma_done = 0;
-
-       field_num = status & FIELD_NO;
-       need_two = V4L2_FIELD_HAS_BOTH(dev->capfield);
-
-       if (status & INT_DMA_END_STATUS) {
-               dma_done = 1;
-               if (((field_num == 0) && (dev->field == 0)) ||
-                   (field_num && (dev->field == 1)))
-                       dev->field++;
-       }
-
-       if (status & INT_FIELD_STATUS) {
-               dprintk(1, "irq: field %d, done %d\n",
-                       !!field_num, dma_done);
-               if (unlikely(dev->first)) {
-                       if (field_num == 0) {
-                               dev->first = 0;
-                               dprintk(1, "activate first buf\n");
-                               viu_activate_next_buf(dev, vidq);
-                       } else
-                               dprintk(1, "wait field 0\n");
-                       return;
-               }
-
-               /* setup buffer address for next dma operation */
-               if (!list_empty(&vidq->active)) {
-                       u32 addr = reg_val.field_base_addr;
-
-                       if (field_num && need_two) {
-                               addr += reg_val.dma_inc;
-                               dprintk(1, "field 1, 0x%lx, dev field %d\n",
-                                       (unsigned long)addr, dev->field);
-                       }
-                       iowrite32be(addr, &vr->field_base_addr);
-                       iowrite32be(reg_val.dma_inc, &vr->dma_inc);
-                       iowrite32be((status & 0xffc0ffff) |
-                                (status & INT_ALL_STATUS) |
-                                reg_val.status_cfg, &vr->status_cfg);
-                       return;
-               }
-       }
-
-       if (dma_done && field_num && (dev->field == 2)) {
-               dev->field = 0;
-               buf = list_entry(vidq->active.next,
-                                struct viu_buf, vb.queue);
-               dprintk(1, "viu/0: [%p/%d] 0x%lx/0x%lx: dma complete\n",
-                       buf, buf->vb.i,
-                       (unsigned long)videobuf_to_dma_contig(&buf->vb),
-                       (unsigned long)ioread32be(&vr->field_base_addr));
-
-               if (waitqueue_active(&buf->vb.done)) {
-                       list_del(&buf->vb.queue);
-                       buf->vb.ts = ktime_get_ns();
-                       buf->vb.state = VIDEOBUF_DONE;
-                       buf->vb.field_count++;
-                       wake_up(&buf->vb.done);
-               }
-               /* activate next dma buffer */
-               viu_activate_next_buf(dev, vidq);
-       }
-}
-
-static irqreturn_t viu_intr(int irq, void *dev_id)
-{
-       struct viu_dev *dev  = (struct viu_dev *)dev_id;
-       struct viu_reg __iomem *vr = dev->vr;
-       u32 status;
-       u32 error;
-
-       status = ioread32be(&vr->status_cfg);
-
-       if (status & INT_ERROR_STATUS) {
-               dev->irqs.error_irq++;
-               error = status & ERR_MASK;
-               if (error)
-                       dprintk(1, "Err: error(%d), times:%d!\n",
-                               error >> 4, dev->irqs.error_irq);
-               /* Clear interrupt error bit and error flags */
-               iowrite32be((status & 0xffc0ffff) | INT_ERROR_STATUS,
-                           &vr->status_cfg);
-       }
-
-       if (status & INT_DMA_END_STATUS) {
-               dev->irqs.dma_end_irq++;
-               dev->dma_done = 1;
-               dprintk(2, "VIU DMA end interrupt times: %d\n",
-                                       dev->irqs.dma_end_irq);
-       }
-
-       if (status & INT_HSYNC_STATUS)
-               dev->irqs.hsync_irq++;
-
-       if (status & INT_FIELD_STATUS) {
-               dev->irqs.field_irq++;
-               dprintk(2, "VIU field interrupt times: %d\n",
-                                       dev->irqs.field_irq);
-       }
-
-       if (status & INT_VSTART_STATUS)
-               dev->irqs.vstart_irq++;
-
-       if (status & INT_VSYNC_STATUS) {
-               dev->irqs.vsync_irq++;
-               dprintk(2, "VIU vsync interrupt times: %d\n",
-                       dev->irqs.vsync_irq);
-       }
-
-       /* clear all pending irqs */
-       status = ioread32be(&vr->status_cfg);
-       iowrite32be((status & 0xffc0ffff) | (status & INT_ALL_STATUS),
-                   &vr->status_cfg);
-
-       if (dev->ovenable) {
-               viu_overlay_intr(dev, status);
-               return IRQ_HANDLED;
-       }
-
-       /* Capture mode */
-       viu_capture_intr(dev, status);
-       return IRQ_HANDLED;
-}
-
-/*
- * File operations for the device
- */
-static int viu_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct viu_dev *dev = video_get_drvdata(vdev);
-       struct viu_fh *fh;
-       struct viu_reg __iomem *vr;
-       int minor = vdev->minor;
-       u32 status_cfg;
-
-       dprintk(1, "viu: open (minor=%d)\n", minor);
-
-       dev->users++;
-       if (dev->users > 1) {
-               dev->users--;
-               return -EBUSY;
-       }
-
-       vr = dev->vr;
-
-       dprintk(1, "open minor=%d type=%s users=%d\n", minor,
-               v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
-
-       if (mutex_lock_interruptible(&dev->lock)) {
-               dev->users--;
-               return -ERESTARTSYS;
-       }
-
-       /* allocate and initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (!fh) {
-               dev->users--;
-               mutex_unlock(&dev->lock);
-               return -ENOMEM;
-       }
-
-       v4l2_fh_init(&fh->fh, vdev);
-       file->private_data = fh;
-       fh->dev = dev;
-
-       fh->type     = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_RGB32);
-       fh->width    = norm_maxw();
-       fh->height   = norm_maxh();
-       dev->crop_current.width  = fh->width;
-       dev->crop_current.height = fh->height;
-
-       dprintk(1, "Open: fh=%p, dev=%p, dev->vidq=%p\n", fh, dev, &dev->vidq);
-       dprintk(1, "Open: list_empty queued=%d\n",
-               list_empty(&dev->vidq.queued));
-       dprintk(1, "Open: list_empty active=%d\n",
-               list_empty(&dev->vidq.active));
-
-       viu_default_settings(vr);
-
-       status_cfg = ioread32be(&vr->status_cfg);
-       iowrite32be(status_cfg & ~(INT_VSYNC_EN | INT_HSYNC_EN |
-                               INT_FIELD_EN | INT_VSTART_EN |
-                               INT_DMA_END_EN | INT_ERROR_EN | INT_ECC_EN),
-                   &vr->status_cfg);
-
-       status_cfg = ioread32be(&vr->status_cfg);
-       iowrite32be(status_cfg | INT_ALL_STATUS, &vr->status_cfg);
-
-       spin_lock_init(&fh->vbq_lock);
-       videobuf_queue_dma_contig_init(&fh->vb_vidq, &viu_video_qops,
-                                      dev->dev, &fh->vbq_lock,
-                                      fh->type, V4L2_FIELD_INTERLACED,
-                                      sizeof(struct viu_buf), fh,
-                                      &fh->dev->lock);
-       v4l2_fh_add(&fh->fh);
-       mutex_unlock(&dev->lock);
-       return 0;
-}
-
-static ssize_t viu_read(struct file *file, char __user *data, size_t count,
-                       loff_t *ppos)
-{
-       struct viu_fh *fh = file->private_data;
-       struct viu_dev *dev = fh->dev;
-       int ret = 0;
-
-       dprintk(2, "%s\n", __func__);
-       if (dev->ovenable)
-               dev->ovenable = 0;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               if (mutex_lock_interruptible(&dev->lock))
-                       return -ERESTARTSYS;
-               viu_start_dma(dev);
-               ret = videobuf_read_stream(&fh->vb_vidq, data, count,
-                               ppos, 0, file->f_flags & O_NONBLOCK);
-               mutex_unlock(&dev->lock);
-               return ret;
-       }
-       return 0;
-}
-
-static __poll_t viu_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct viu_fh *fh = file->private_data;
-       struct videobuf_queue *q = &fh->vb_vidq;
-       struct viu_dev *dev = fh->dev;
-       __poll_t req_events = poll_requested_events(wait);
-       __poll_t res = v4l2_ctrl_poll(file, wait);
-
-       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
-               return EPOLLERR;
-
-       if (!(req_events & (EPOLLIN | EPOLLRDNORM)))
-               return res;
-
-       mutex_lock(&dev->lock);
-       res |= videobuf_poll_stream(file, q, wait);
-       mutex_unlock(&dev->lock);
-       return res;
-}
-
-static int viu_release(struct file *file)
-{
-       struct viu_fh *fh = file->private_data;
-       struct viu_dev *dev = fh->dev;
-       int minor = video_devdata(file)->minor;
-
-       mutex_lock(&dev->lock);
-       viu_stop_dma(dev);
-       videobuf_stop(&fh->vb_vidq);
-       videobuf_mmap_free(&fh->vb_vidq);
-       v4l2_fh_del(&fh->fh);
-       v4l2_fh_exit(&fh->fh);
-       mutex_unlock(&dev->lock);
-
-       kfree(fh);
-
-       dev->users--;
-       dprintk(1, "close (minor=%d, users=%d)\n",
-               minor, dev->users);
-       return 0;
-}
-
-static void viu_reset(struct viu_reg __iomem *reg)
-{
-       iowrite32be(0, &reg->status_cfg);
-       iowrite32be(0x9512a254, &reg->luminance);
-       iowrite32be(0x03310000, &reg->chroma_r);
-       iowrite32be(0x06600f38, &reg->chroma_g);
-       iowrite32be(0x00000409, &reg->chroma_b);
-       iowrite32be(0, &reg->field_base_addr);
-       iowrite32be(0, &reg->dma_inc);
-       iowrite32be(0x01e002d0, &reg->picture_count);
-       iowrite32be(0x00000090, &reg->req_alarm);
-       iowrite32be(0x000000ff, &reg->alpha);
-}
-
-static int viu_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct viu_fh *fh = file->private_data;
-       struct viu_dev *dev = fh->dev;
-       int ret;
-
-       dprintk(1, "mmap called, vma=%p\n", vma);
-
-       if (mutex_lock_interruptible(&dev->lock))
-               return -ERESTARTSYS;
-       ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
-       mutex_unlock(&dev->lock);
-
-       dprintk(1, "vma start=0x%08lx, size=%ld, ret=%d\n",
-               (unsigned long)vma->vm_start,
-               (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
-               ret);
-
-       return ret;
-}
-
-static const struct v4l2_file_operations viu_fops = {
-       .owner          = THIS_MODULE,
-       .open           = viu_open,
-       .release        = viu_release,
-       .read           = viu_read,
-       .poll           = viu_poll,
-       .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
-       .mmap           = viu_mmap,
-};
-
-static const struct v4l2_ioctl_ops viu_ioctl_ops = {
-       .vidioc_querycap        = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt,
-       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_cap,
-       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_cap,
-       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_cap,
-       .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt,
-       .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_overlay,
-       .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_overlay,
-       .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_overlay,
-       .vidioc_overlay       = vidioc_overlay,
-       .vidioc_g_fbuf        = vidioc_g_fbuf,
-       .vidioc_s_fbuf        = vidioc_s_fbuf,
-       .vidioc_reqbufs       = vidioc_reqbufs,
-       .vidioc_querybuf      = vidioc_querybuf,
-       .vidioc_qbuf          = vidioc_qbuf,
-       .vidioc_dqbuf         = vidioc_dqbuf,
-       .vidioc_g_std         = vidioc_g_std,
-       .vidioc_s_std         = vidioc_s_std,
-       .vidioc_querystd      = vidioc_querystd,
-       .vidioc_enum_input    = vidioc_enum_input,
-       .vidioc_g_input       = vidioc_g_input,
-       .vidioc_s_input       = vidioc_s_input,
-       .vidioc_streamon      = vidioc_streamon,
-       .vidioc_streamoff     = vidioc_streamoff,
-       .vidioc_log_status    = v4l2_ctrl_log_status,
-       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
-       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-static const struct video_device viu_template = {
-       .name           = "FSL viu",
-       .fops           = &viu_fops,
-       .minor          = -1,
-       .ioctl_ops      = &viu_ioctl_ops,
-       .release        = video_device_release,
-
-       .tvnorms        = V4L2_STD_NTSC_M | V4L2_STD_PAL,
-       .device_caps    = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
-                         V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_READWRITE,
-};
-
-static int viu_of_probe(struct platform_device *op)
-{
-       struct viu_dev *viu_dev;
-       struct video_device *vdev;
-       struct resource r;
-       struct viu_reg __iomem *viu_regs;
-       struct i2c_adapter *ad;
-       int ret, viu_irq;
-       struct clk *clk;
-
-       ret = of_address_to_resource(op->dev.of_node, 0, &r);
-       if (ret) {
-               dev_err(&op->dev, "Can't parse device node resource\n");
-               return -ENODEV;
-       }
-
-       viu_irq = irq_of_parse_and_map(op->dev.of_node, 0);
-       if (!viu_irq) {
-               dev_err(&op->dev, "Error while mapping the irq\n");
-               return -EINVAL;
-       }
-
-       /* request mem region */
-       if (!devm_request_mem_region(&op->dev, r.start,
-                                    sizeof(struct viu_reg), DRV_NAME)) {
-               dev_err(&op->dev, "Error while requesting mem region\n");
-               ret = -EBUSY;
-               goto err_irq;
-       }
-
-       /* remap registers */
-       viu_regs = devm_ioremap(&op->dev, r.start, sizeof(struct viu_reg));
-       if (!viu_regs) {
-               dev_err(&op->dev, "Can't map register set\n");
-               ret = -ENOMEM;
-               goto err_irq;
-       }
-
-       /* Prepare our private structure */
-       viu_dev = devm_kzalloc(&op->dev, sizeof(struct viu_dev), GFP_KERNEL);
-       if (!viu_dev) {
-               dev_err(&op->dev, "Can't allocate private structure\n");
-               ret = -ENOMEM;
-               goto err_irq;
-       }
-
-       viu_dev->vr = viu_regs;
-       viu_dev->irq = viu_irq;
-       viu_dev->dev = &op->dev;
-
-       /* init video dma queues */
-       INIT_LIST_HEAD(&viu_dev->vidq.active);
-       INIT_LIST_HEAD(&viu_dev->vidq.queued);
-
-       snprintf(viu_dev->v4l2_dev.name,
-                sizeof(viu_dev->v4l2_dev.name), "%s", "VIU");
-       ret = v4l2_device_register(viu_dev->dev, &viu_dev->v4l2_dev);
-       if (ret < 0) {
-               dev_err(&op->dev, "v4l2_device_register() failed: %d\n", ret);
-               goto err_irq;
-       }
-
-       ad = i2c_get_adapter(0);
-       if (!ad) {
-               ret = -EFAULT;
-               dev_err(&op->dev, "couldn't get i2c adapter\n");
-               goto err_v4l2;
-       }
-
-       v4l2_ctrl_handler_init(&viu_dev->hdl, 5);
-       if (viu_dev->hdl.error) {
-               ret = viu_dev->hdl.error;
-               dev_err(&op->dev, "couldn't register control\n");
-               goto err_i2c;
-       }
-       /* This control handler will inherit the control(s) from the
-          sub-device(s). */
-       viu_dev->v4l2_dev.ctrl_handler = &viu_dev->hdl;
-       viu_dev->decoder = v4l2_i2c_new_subdev(&viu_dev->v4l2_dev, ad,
-                       "saa7113", VIU_VIDEO_DECODER_ADDR, NULL);
-
-       timer_setup(&viu_dev->vidq.timeout, viu_vid_timeout, 0);
-       viu_dev->std = V4L2_STD_NTSC_M;
-       viu_dev->first = 1;
-
-       /* Allocate memory for video device */
-       vdev = video_device_alloc();
-       if (vdev == NULL) {
-               ret = -ENOMEM;
-               goto err_hdl;
-       }
-
-       *vdev = viu_template;
-
-       vdev->v4l2_dev = &viu_dev->v4l2_dev;
-
-       viu_dev->vdev = vdev;
-
-       /* initialize locks */
-       mutex_init(&viu_dev->lock);
-       viu_dev->vdev->lock = &viu_dev->lock;
-       spin_lock_init(&viu_dev->slock);
-
-       video_set_drvdata(viu_dev->vdev, viu_dev);
-
-       mutex_lock(&viu_dev->lock);
-
-       ret = video_register_device(viu_dev->vdev, VFL_TYPE_VIDEO, -1);
-       if (ret < 0) {
-               video_device_release(viu_dev->vdev);
-               goto err_unlock;
-       }
-
-       /* enable VIU clock */
-       clk = devm_clk_get(&op->dev, "ipg");
-       if (IS_ERR(clk)) {
-               dev_err(&op->dev, "failed to lookup the clock!\n");
-               ret = PTR_ERR(clk);
-               goto err_vdev;
-       }
-       ret = clk_prepare_enable(clk);
-       if (ret) {
-               dev_err(&op->dev, "failed to enable the clock!\n");
-               goto err_vdev;
-       }
-       viu_dev->clk = clk;
-
-       /* reset VIU module */
-       viu_reset(viu_dev->vr);
-
-       /* install interrupt handler */
-       if (request_irq(viu_dev->irq, viu_intr, 0, "viu", (void *)viu_dev)) {
-               dev_err(&op->dev, "Request VIU IRQ failed.\n");
-               ret = -ENODEV;
-               goto err_clk;
-       }
-
-       mutex_unlock(&viu_dev->lock);
-
-       dev_info(&op->dev, "Freescale VIU Video Capture Board\n");
-       return ret;
-
-err_clk:
-       clk_disable_unprepare(viu_dev->clk);
-err_vdev:
-       video_unregister_device(viu_dev->vdev);
-err_unlock:
-       mutex_unlock(&viu_dev->lock);
-err_hdl:
-       v4l2_ctrl_handler_free(&viu_dev->hdl);
-err_i2c:
-       i2c_put_adapter(ad);
-err_v4l2:
-       v4l2_device_unregister(&viu_dev->v4l2_dev);
-err_irq:
-       irq_dispose_mapping(viu_irq);
-       return ret;
-}
-
-static int viu_of_remove(struct platform_device *op)
-{
-       struct v4l2_device *v4l2_dev = platform_get_drvdata(op);
-       struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev);
-       struct v4l2_subdev *sdev = list_entry(v4l2_dev->subdevs.next,
-                                             struct v4l2_subdev, list);
-       struct i2c_client *client = v4l2_get_subdevdata(sdev);
-
-       free_irq(dev->irq, (void *)dev);
-       irq_dispose_mapping(dev->irq);
-
-       clk_disable_unprepare(dev->clk);
-
-       v4l2_ctrl_handler_free(&dev->hdl);
-       video_unregister_device(dev->vdev);
-       i2c_put_adapter(client->adapter);
-       v4l2_device_unregister(&dev->v4l2_dev);
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int viu_suspend(struct platform_device *op, pm_message_t state)
-{
-       struct v4l2_device *v4l2_dev = platform_get_drvdata(op);
-       struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev);
-
-       clk_disable(dev->clk);
-       return 0;
-}
-
-static int viu_resume(struct platform_device *op)
-{
-       struct v4l2_device *v4l2_dev = platform_get_drvdata(op);
-       struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev);
-
-       clk_enable(dev->clk);
-       return 0;
-}
-#endif
-
-/*
- * Initialization and module stuff
- */
-static const struct of_device_id mpc512x_viu_of_match[] = {
-       {
-               .compatible = "fsl,mpc5121-viu",
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, mpc512x_viu_of_match);
-
-static struct platform_driver viu_of_platform_driver = {
-       .probe = viu_of_probe,
-       .remove = viu_of_remove,
-#ifdef CONFIG_PM
-       .suspend = viu_suspend,
-       .resume = viu_resume,
-#endif
-       .driver = {
-               .name = DRV_NAME,
-               .of_match_table = mpc512x_viu_of_match,
-       },
-};
-
-module_platform_driver(viu_of_platform_driver);
-
-MODULE_DESCRIPTION("Freescale Video-In(VIU)");
-MODULE_AUTHOR("Hongjun Chen");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(VIU_VERSION);
diff --git a/drivers/media/platform/imx-jpeg/Kconfig b/drivers/media/platform/imx-jpeg/Kconfig
deleted file mode 100644 (file)
index cbf6101..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config VIDEO_IMX8_JPEG
-       tristate "IMX8 JPEG Encoder/Decoder"
-       depends on V4L_MEM2MEM_DRIVERS
-       depends on ARCH_MXC || COMPILE_TEST
-       depends on VIDEO_DEV && VIDEO_V4L2
-       select VIDEOBUF2_DMA_CONTIG
-       select V4L2_MEM2MEM_DEV
-       select V4L2_JPEG_HELPER
-       help
-         This is a video4linux2 driver for the i.MX8 QXP/QM integrated
-         JPEG encoder/decoder.
diff --git a/drivers/media/platform/imx-jpeg/Makefile b/drivers/media/platform/imx-jpeg/Makefile
deleted file mode 100644 (file)
index bf19c82..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-mxc-jpeg-encdec-objs := mxc-jpeg-hw.o mxc-jpeg.o
-obj-$(CONFIG_VIDEO_IMX8_JPEG) += mxc-jpeg-encdec.o
diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.c b/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.c
deleted file mode 100644 (file)
index 29c604b..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * i.MX8QXP/i.MX8QM JPEG encoder/decoder v4l2 driver
- *
- * Copyright 2018-2019 NXP
- */
-
-#include <linux/delay.h>
-#include <media/videobuf2-core.h>
-#include "mxc-jpeg-hw.h"
-
-#define print_wrapper_reg(dev, base_address, reg_offset)\
-               internal_print_wrapper_reg(dev, (base_address), #reg_offset,\
-                                          (reg_offset))
-#define internal_print_wrapper_reg(dev, base_address, reg_name, reg_offset) {\
-               int val;\
-               val = readl((base_address) + (reg_offset));\
-               dev_dbg(dev, "Wrapper reg %s = 0x%x\n", reg_name, val);\
-}
-
-void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc)
-{
-       dev_dbg(dev, " MXC JPEG NEXT_DESCPT_PTR 0x%x\n",
-               desc->next_descpt_ptr);
-       dev_dbg(dev, " MXC JPEG BUF_BASE0 0x%x\n", desc->buf_base0);
-       dev_dbg(dev, " MXC JPEG BUF_BASE1 0x%x\n", desc->buf_base1);
-       dev_dbg(dev, " MXC JPEG LINE_PITCH %d\n", desc->line_pitch);
-       dev_dbg(dev, " MXC JPEG STM_BUFBASE 0x%x\n", desc->stm_bufbase);
-       dev_dbg(dev, " MXC JPEG STM_BUFSIZE %d\n", desc->stm_bufsize);
-       dev_dbg(dev, " MXC JPEG IMGSIZE %x (%d x %d)\n", desc->imgsize,
-               desc->imgsize >> 16, desc->imgsize & 0xFFFF);
-       dev_dbg(dev, " MXC JPEG STM_CTRL 0x%x\n", desc->stm_ctrl);
-}
-
-void print_cast_status(struct device *dev, void __iomem *reg,
-                      unsigned int mode)
-{
-       dev_dbg(dev, "CAST IP status regs:\n");
-       print_wrapper_reg(dev, reg, CAST_STATUS0);
-       print_wrapper_reg(dev, reg, CAST_STATUS1);
-       print_wrapper_reg(dev, reg, CAST_STATUS2);
-       print_wrapper_reg(dev, reg, CAST_STATUS3);
-       print_wrapper_reg(dev, reg, CAST_STATUS4);
-       print_wrapper_reg(dev, reg, CAST_STATUS5);
-       print_wrapper_reg(dev, reg, CAST_STATUS6);
-       print_wrapper_reg(dev, reg, CAST_STATUS7);
-       print_wrapper_reg(dev, reg, CAST_STATUS8);
-       print_wrapper_reg(dev, reg, CAST_STATUS9);
-       print_wrapper_reg(dev, reg, CAST_STATUS10);
-       print_wrapper_reg(dev, reg, CAST_STATUS11);
-       print_wrapper_reg(dev, reg, CAST_STATUS12);
-       print_wrapper_reg(dev, reg, CAST_STATUS13);
-       if (mode == MXC_JPEG_DECODE)
-               return;
-       print_wrapper_reg(dev, reg, CAST_STATUS14);
-       print_wrapper_reg(dev, reg, CAST_STATUS15);
-       print_wrapper_reg(dev, reg, CAST_STATUS16);
-       print_wrapper_reg(dev, reg, CAST_STATUS17);
-       print_wrapper_reg(dev, reg, CAST_STATUS18);
-       print_wrapper_reg(dev, reg, CAST_STATUS19);
-}
-
-void print_wrapper_info(struct device *dev, void __iomem *reg)
-{
-       dev_dbg(dev, "Wrapper regs:\n");
-       print_wrapper_reg(dev, reg, GLB_CTRL);
-       print_wrapper_reg(dev, reg, COM_STATUS);
-       print_wrapper_reg(dev, reg, BUF_BASE0);
-       print_wrapper_reg(dev, reg, BUF_BASE1);
-       print_wrapper_reg(dev, reg, LINE_PITCH);
-       print_wrapper_reg(dev, reg, STM_BUFBASE);
-       print_wrapper_reg(dev, reg, STM_BUFSIZE);
-       print_wrapper_reg(dev, reg, IMGSIZE);
-       print_wrapper_reg(dev, reg, STM_CTRL);
-}
-
-void mxc_jpeg_enable_irq(void __iomem *reg, int slot)
-{
-       writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN));
-}
-
-void mxc_jpeg_sw_reset(void __iomem *reg)
-{
-       /*
-        * engine soft reset, internal state machine reset
-        * this will not reset registers, however, it seems
-        * the registers may remain inconsistent with the internal state
-        * so, on purpose, at least let GLB_CTRL bits clear after this reset
-        */
-       writel(GLB_CTRL_SFT_RST, reg + GLB_CTRL);
-}
-
-void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg)
-{
-       dev_dbg(dev, "CAST Encoder CONFIG...\n");
-       /*
-        * "Config_Mode" enabled, "Config_Mode auto clear enabled",
-        */
-       writel(0xa0, reg + CAST_MODE);
-
-       /* all markers and segments */
-       writel(0x3ff, reg + CAST_CFG_MODE);
-
-       /* quality factor */
-       writel(0x4b, reg + CAST_QUALITY);
-}
-
-void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg)
-{
-       dev_dbg(dev, "CAST Encoder GO...\n");
-       /*
-        * "GO" enabled, "GO bit auto clear" enabled
-        */
-       writel(0x140, reg + CAST_MODE);
-}
-
-void mxc_jpeg_dec_mode_go(struct device *dev, void __iomem *reg)
-{
-       dev_dbg(dev, "CAST Decoder GO...\n");
-       writel(MXC_DEC_EXIT_IDLE_MODE, reg + CAST_CTRL);
-}
-
-int mxc_jpeg_enable(void __iomem *reg)
-{
-       u32 regval;
-
-       writel(GLB_CTRL_JPG_EN, reg + GLB_CTRL);
-       regval = readl(reg);
-       return regval;
-}
-
-void mxc_jpeg_enable_slot(void __iomem *reg, int slot)
-{
-       u32 regval;
-
-       regval = readl(reg + GLB_CTRL);
-       writel(GLB_CTRL_SLOT_EN(slot) | regval, reg + GLB_CTRL);
-}
-
-void mxc_jpeg_set_l_endian(void __iomem *reg, int le)
-{
-       u32 regval;
-
-       regval = readl(reg + GLB_CTRL);
-       regval &= ~GLB_CTRL_L_ENDIAN(1); /* clear */
-       writel(GLB_CTRL_L_ENDIAN(le) | regval, reg + GLB_CTRL); /* set */
-}
-
-void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc,  u32 bufsize)
-{
-       desc->stm_bufsize = bufsize;
-}
-
-void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h)
-{
-       desc->imgsize = w << 16 | h;
-}
-
-void mxc_jpeg_set_line_pitch(struct mxc_jpeg_desc *desc, u32 line_pitch)
-{
-       desc->line_pitch = line_pitch;
-}
-
-void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot)
-{
-       writel(desc | MXC_NXT_DESCPT_EN,
-              reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR));
-}
diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.h b/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.h
deleted file mode 100644 (file)
index ae70d3a..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * i.MX8QXP/i.MX8QM JPEG encoder/decoder v4l2 driver
- *
- * Copyright 2018-2019 NXP
- */
-
-#ifndef _MXC_JPEG_HW_H
-#define _MXC_JPEG_HW_H
-
-/* JPEG Decoder/Encoder Wrapper Register Map */
-#define GLB_CTRL                       0x0
-#define COM_STATUS                     0x4
-#define BUF_BASE0                      0x14
-#define BUF_BASE1                      0x18
-#define LINE_PITCH                     0x1C
-#define STM_BUFBASE                    0x20
-#define STM_BUFSIZE                    0x24
-#define IMGSIZE                                0x28
-#define STM_CTRL                       0x2C
-
-/* CAST JPEG-Decoder/Encoder Status Register Map (read-only)*/
-#define CAST_STATUS0                   0x100
-#define CAST_STATUS1                   0x104
-#define CAST_STATUS2                   0x108
-#define CAST_STATUS3                   0x10c
-#define CAST_STATUS4                   0x110
-#define CAST_STATUS5                   0x114
-#define CAST_STATUS6                   0x118
-#define CAST_STATUS7                   0x11c
-#define CAST_STATUS8                   0x120
-#define CAST_STATUS9                   0x124
-#define CAST_STATUS10                  0x128
-#define CAST_STATUS11                  0x12c
-#define CAST_STATUS12                  0x130
-#define CAST_STATUS13                  0x134
-/* the following are for encoder only */
-#define CAST_STATUS14          0x138
-#define CAST_STATUS15          0x13c
-#define CAST_STATUS16          0x140
-#define CAST_STATUS17          0x144
-#define CAST_STATUS18          0x148
-#define CAST_STATUS19          0x14c
-
-/* CAST JPEG-Decoder Control Register Map (write-only) */
-#define CAST_CTRL                      CAST_STATUS13
-
-/* CAST JPEG-Encoder Control Register Map (write-only) */
-#define CAST_MODE                      CAST_STATUS0
-#define CAST_CFG_MODE                  CAST_STATUS1
-#define CAST_QUALITY                   CAST_STATUS2
-#define CAST_RSVD                      CAST_STATUS3
-#define CAST_REC_REGS_SEL              CAST_STATUS4
-#define CAST_LUMTH                     CAST_STATUS5
-#define CAST_CHRTH                     CAST_STATUS6
-#define CAST_NOMFRSIZE_LO              CAST_STATUS7
-#define CAST_NOMFRSIZE_HI              CAST_STATUS8
-#define CAST_OFBSIZE_LO                        CAST_STATUS9
-#define CAST_OFBSIZE_HI                        CAST_STATUS10
-
-#define MXC_MAX_SLOTS  1 /* TODO use all 4 slots*/
-/* JPEG-Decoder Wrapper Slot Registers 0..3 */
-#define SLOT_BASE                      0x10000
-#define SLOT_STATUS                    0x0
-#define SLOT_IRQ_EN                    0x4
-#define SLOT_BUF_PTR                   0x8
-#define SLOT_CUR_DESCPT_PTR            0xC
-#define SLOT_NXT_DESCPT_PTR            0x10
-#define MXC_SLOT_OFFSET(slot, offset)  ((SLOT_BASE * ((slot) + 1)) + (offset))
-
-/* GLB_CTRL fields */
-#define GLB_CTRL_JPG_EN                                        0x1
-#define GLB_CTRL_SFT_RST                               (0x1 << 1)
-#define GLB_CTRL_DEC_GO                                        (0x1 << 2)
-#define GLB_CTRL_L_ENDIAN(le)                          ((le) << 3)
-#define GLB_CTRL_SLOT_EN(slot)                         (0x1 << ((slot) + 4))
-
-/* COM_STAUS fields */
-#define COM_STATUS_DEC_ONGOING(r)              (((r) & (1 << 31)) >> 31)
-#define COM_STATUS_CUR_SLOT(r)                 (((r) & (0x3 << 29)) >> 29)
-
-/* STM_CTRL fields */
-#define STM_CTRL_PIXEL_PRECISION               (0x1 << 2)
-#define STM_CTRL_IMAGE_FORMAT(img_fmt)         ((img_fmt) << 3)
-#define STM_CTRL_IMAGE_FORMAT_MASK             (0xF << 3)
-#define STM_CTRL_BITBUF_PTR_CLR(clr)           ((clr) << 7)
-#define STM_CTRL_AUTO_START(go)                        ((go) << 8)
-#define STM_CTRL_CONFIG_MOD(mod)               ((mod) << 9)
-
-/* SLOT_STATUS fields for slots 0..3 */
-#define SLOT_STATUS_FRMDONE                    (0x1 << 3)
-#define SLOT_STATUS_ENC_CONFIG_ERR             (0x1 << 8)
-
-/* SLOT_IRQ_EN fields TBD */
-
-#define MXC_NXT_DESCPT_EN                      0x1
-#define MXC_DEC_EXIT_IDLE_MODE                 0x4
-
-/* JPEG-Decoder Wrapper - STM_CTRL Register Fields */
-#define MXC_PIXEL_PRECISION(precision) ((precision) / 8 << 2)
-enum mxc_jpeg_image_format {
-       MXC_JPEG_INVALID = -1,
-       MXC_JPEG_YUV420 = 0x0, /* 2 Plannar, Y=1st plane UV=2nd plane */
-       MXC_JPEG_YUV422 = 0x1, /* 1 Plannar, YUYV sequence */
-       MXC_JPEG_RGB    = 0x2, /* RGBRGB packed format */
-       MXC_JPEG_YUV444 = 0x3, /* 1 Plannar, YUVYUV sequence */
-       MXC_JPEG_GRAY = 0x4, /* Y8 or Y12 or Single Component */
-       MXC_JPEG_RESERVED = 0x5,
-       MXC_JPEG_ARGB   = 0x6,
-};
-
-#include "mxc-jpeg.h"
-void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc);
-void print_cast_status(struct device *dev, void __iomem *reg,
-                      unsigned int mode);
-void print_wrapper_info(struct device *dev, void __iomem *reg);
-void mxc_jpeg_sw_reset(void __iomem *reg);
-int mxc_jpeg_enable(void __iomem *reg);
-void wait_frmdone(struct device *dev, void __iomem *reg);
-void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg);
-void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg);
-void mxc_jpeg_dec_mode_go(struct device *dev, void __iomem *reg);
-int mxc_jpeg_get_slot(void __iomem *reg);
-u32 mxc_jpeg_get_offset(void __iomem *reg, int slot);
-void mxc_jpeg_enable_slot(void __iomem *reg, int slot);
-void mxc_jpeg_set_l_endian(void __iomem *reg, int le);
-void mxc_jpeg_enable_irq(void __iomem *reg, int slot);
-int mxc_jpeg_set_input(void __iomem *reg, u32 in_buf, u32 bufsize);
-int mxc_jpeg_set_output(void __iomem *reg, u16 out_pitch, u32 out_buf,
-                       u16 w, u16 h);
-void mxc_jpeg_set_config_mode(void __iomem *reg, int config_mode);
-int mxc_jpeg_set_params(struct mxc_jpeg_desc *desc,  u32 bufsize, u16
-                       out_pitch, u32 format);
-void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc,  u32 bufsize);
-void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h);
-void mxc_jpeg_set_line_pitch(struct mxc_jpeg_desc *desc, u32 line_pitch);
-void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot);
-void mxc_jpeg_set_regs_from_desc(struct mxc_jpeg_desc *desc,
-                                void __iomem *reg);
-#endif
diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/imx-jpeg/mxc-jpeg.c
deleted file mode 100644 (file)
index 3b892c5..0000000
+++ /dev/null
@@ -1,2254 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * V4L2 driver for the JPEG encoder/decoder from i.MX8QXP/i.MX8QM application
- * processors.
- *
- * The multi-planar buffers API is used.
- *
- * Baseline and extended sequential jpeg decoding is supported.
- * Progressive jpeg decoding is not supported by the IP.
- * Supports encode and decode of various formats:
- *     YUV444, YUV422, YUV420, RGB, ARGB, Gray
- * YUV420 is the only multi-planar format supported.
- * Minimum resolution is 64 x 64, maximum 8192 x 8192.
- * To achieve 8192 x 8192, modify in defconfig: CONFIG_CMA_SIZE_MBYTES=320
- * The alignment requirements for the resolution depend on the format,
- * multiple of 16 resolutions should work for all formats.
- * Special workarounds are made in the driver to support NV12 1080p.
- * When decoding, the driver detects image resolution and pixel format
- * from the jpeg stream, by parsing the jpeg markers.
- *
- * The IP has 4 slots available for context switching, but only slot 0
- * was fully tested to work. Context switching is not used by the driver.
- * Each driver instance (context) allocates a slot for itself, but this
- * is postponed until device_run, to allow unlimited opens.
- *
- * The driver submits jobs to the IP by setting up a descriptor for the
- * used slot, and then validating it. The encoder has an additional descriptor
- * for the configuration phase. The driver expects FRM_DONE interrupt from
- * IP to mark the job as finished.
- *
- * The decoder IP has some limitations regarding the component ID's,
- * but the driver works around this by replacing them in the jpeg stream.
- *
- * A module parameter is available for debug purpose (jpeg_tracing), to enable
- * it, enable dynamic debug for this module and:
- * echo 1 > /sys/module/mxc_jpeg_encdec/parameters/jpeg_tracing
- *
- * This is inspired by the drivers/media/platform/s5p-jpeg driver
- *
- * Copyright 2018-2019 NXP
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/irqreturn.h>
-#include <linux/interrupt.h>
-#include <linux/pm_runtime.h>
-#include <linux/pm_domain.h>
-#include <linux/string.h>
-
-#include <media/v4l2-jpeg.h>
-#include <media/v4l2-mem2mem.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-dma-contig.h>
-
-#include "mxc-jpeg-hw.h"
-#include "mxc-jpeg.h"
-
-static const struct mxc_jpeg_fmt mxc_formats[] = {
-       {
-               .name           = "JPEG",
-               .fourcc         = V4L2_PIX_FMT_JPEG,
-               .subsampling    = -1,
-               .nc             = -1,
-               .colplanes      = 1,
-               .flags          = MXC_JPEG_FMT_TYPE_ENC,
-       },
-       {
-               .name           = "RGB", /*RGBRGB packed format*/
-               .fourcc         = V4L2_PIX_FMT_RGB24,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-               .nc             = 3,
-               .depth          = 24,
-               .colplanes      = 1,
-               .h_align        = 3,
-               .v_align        = 3,
-               .flags          = MXC_JPEG_FMT_TYPE_RAW,
-       },
-       {
-               .name           = "ARGB", /* ARGBARGB packed format */
-               .fourcc         = V4L2_PIX_FMT_ARGB32,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-               .nc             = 4,
-               .depth          = 32,
-               .colplanes      = 1,
-               .h_align        = 3,
-               .v_align        = 3,
-               .flags          = MXC_JPEG_FMT_TYPE_RAW,
-       },
-       {
-               .name           = "YUV420", /* 1st plane = Y, 2nd plane = UV */
-               .fourcc         = V4L2_PIX_FMT_NV12M,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
-               .nc             = 3,
-               .depth          = 12, /* 6 bytes (4Y + UV) for 4 pixels */
-               .colplanes      = 2, /* 1 plane Y, 1 plane UV interleaved */
-               .h_align        = 4,
-               .v_align        = 4,
-               .flags          = MXC_JPEG_FMT_TYPE_RAW,
-       },
-       {
-               .name           = "YUV422", /* YUYV */
-               .fourcc         = V4L2_PIX_FMT_YUYV,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
-               .nc             = 3,
-               .depth          = 16,
-               .colplanes      = 1,
-               .h_align        = 4,
-               .v_align        = 3,
-               .flags          = MXC_JPEG_FMT_TYPE_RAW,
-       },
-       {
-               .name           = "YUV444", /* YUVYUV */
-               .fourcc         = V4L2_PIX_FMT_YUV24,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-               .nc             = 3,
-               .depth          = 24,
-               .colplanes      = 1,
-               .h_align        = 3,
-               .v_align        = 3,
-               .flags          = MXC_JPEG_FMT_TYPE_RAW,
-       },
-       {
-               .name           = "Gray", /* Gray (Y8/Y12) or Single Comp */
-               .fourcc         = V4L2_PIX_FMT_GREY,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
-               .nc             = 1,
-               .depth          = 8,
-               .colplanes      = 1,
-               .h_align        = 3,
-               .v_align        = 3,
-               .flags          = MXC_JPEG_FMT_TYPE_RAW,
-       },
-};
-
-#define MXC_JPEG_NUM_FORMATS ARRAY_SIZE(mxc_formats)
-
-static const int mxc_decode_mode = MXC_JPEG_DECODE;
-static const int mxc_encode_mode = MXC_JPEG_ENCODE;
-
-static const struct of_device_id mxc_jpeg_match[] = {
-       {
-               .compatible = "nxp,imx8qxp-jpgdec",
-               .data       = &mxc_decode_mode,
-       },
-       {
-               .compatible = "nxp,imx8qxp-jpgenc",
-               .data       = &mxc_encode_mode,
-       },
-       { },
-};
-
-/*
- * default configuration stream, 64x64 yuv422
- * split by JPEG marker, so it's easier to modify & use
- */
-static const unsigned char jpeg_soi[] = {
-       0xFF, 0xD8
-};
-
-static const unsigned char jpeg_app0[] = {
-       0xFF, 0xE0,
-       0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00,
-       0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x00
-};
-
-static const unsigned char jpeg_app14[] = {
-       0xFF, 0xEE,
-       0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65,
-       0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static const unsigned char jpeg_dqt[] = {
-       0xFF, 0xDB,
-       0x00, 0x84, 0x00, 0x10, 0x0B, 0x0C, 0x0E,
-       0x0C, 0x0A, 0x10, 0x0E, 0x0D, 0x0E, 0x12,
-       0x11, 0x10, 0x13, 0x18, 0x28, 0x1A, 0x18,
-       0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1D,
-       0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33,
-       0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40,
-       0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6D,
-       0x51, 0x57, 0x5F, 0x62, 0x67, 0x68, 0x67,
-       0x3E, 0x4D, 0x71, 0x79, 0x70, 0x64, 0x78,
-       0x5C, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12,
-       0x12, 0x18, 0x15, 0x18, 0x2F, 0x1A, 0x1A,
-       0x2F, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63
-};
-
-static const unsigned char jpeg_sof_maximal[] = {
-       0xFF, 0xC0,
-       0x00, 0x14, 0x08, 0x00, 0x40, 0x00, 0x40,
-       0x04, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01,
-       0x03, 0x11, 0x01, 0x04, 0x11, 0x01
-};
-
-static const unsigned char jpeg_dht[] = {
-       0xFF, 0xC4,
-       0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01,
-       0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-       0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01,
-       0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05,
-       0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
-       0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
-       0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
-       0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91,
-       0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15,
-       0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72,
-       0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19,
-       0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
-       0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
-       0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
-       0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
-       0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
-       0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76,
-       0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85,
-       0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93,
-       0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,
-       0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
-       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
-       0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4,
-       0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2,
-       0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
-       0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
-       0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
-       0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA,
-       0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
-       0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
-       0x0B, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04,
-       0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
-       0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02,
-       0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06,
-       0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13,
-       0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
-       0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52,
-       0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
-       0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18,
-       0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
-       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43,
-       0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
-       0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
-       0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
-       0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77,
-       0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85,
-       0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93,
-       0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,
-       0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
-       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
-       0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4,
-       0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2,
-       0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
-       0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
-       0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5,
-       0xF6, 0xF7, 0xF8, 0xF9, 0xFA
-};
-
-static const unsigned char jpeg_dri[] = {
-       0xFF, 0xDD,
-       0x00, 0x04, 0x00, 0x20
-};
-
-static const unsigned char jpeg_sos_maximal[] = {
-       0xFF, 0xDA,
-       0x00, 0x0C, 0x04, 0x01, 0x00, 0x02, 0x11, 0x03,
-       0x11, 0x04, 0x11, 0x00, 0x3F, 0x00
-};
-
-static const unsigned char jpeg_image_red[] = {
-       0xFC, 0x5F, 0xA2, 0xBF, 0xCA, 0x73, 0xFE, 0xFE,
-       0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00,
-       0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02,
-       0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28,
-       0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A,
-       0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0,
-       0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00,
-       0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02,
-       0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28,
-       0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A,
-       0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00
-};
-
-static const unsigned char jpeg_eoi[] = {
-       0xFF, 0xD9
-};
-
-struct mxc_jpeg_src_buf {
-       /* common v4l buffer stuff -- must be first */
-       struct vb2_v4l2_buffer  b;
-       struct list_head        list;
-
-       /* mxc-jpeg specific */
-       bool                    dht_needed;
-       bool                    jpeg_parse_error;
-};
-
-static inline struct mxc_jpeg_src_buf *vb2_to_mxc_buf(struct vb2_buffer *vb)
-{
-       return container_of(to_vb2_v4l2_buffer(vb),
-                           struct mxc_jpeg_src_buf, b);
-}
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level (0-3)");
-
-static void _bswap16(u16 *a)
-{
-       *a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8);
-}
-
-static void print_mxc_buf(struct mxc_jpeg_dev *jpeg, struct vb2_buffer *buf,
-                         unsigned long len)
-{
-       unsigned int plane_no;
-       u32 dma_addr;
-       void *vaddr;
-       unsigned long payload;
-
-       if (debug < 3)
-               return;
-
-       for (plane_no = 0; plane_no < buf->num_planes; plane_no++) {
-               payload = vb2_get_plane_payload(buf, plane_no);
-               if (len == 0)
-                       len = payload;
-               dma_addr = vb2_dma_contig_plane_dma_addr(buf, plane_no);
-               vaddr = vb2_plane_vaddr(buf, plane_no);
-               v4l2_dbg(3, debug, &jpeg->v4l2_dev,
-                        "plane %d (vaddr=%p dma_addr=%x payload=%ld):",
-                         plane_no, vaddr, dma_addr, payload);
-               print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
-                              vaddr, len, false);
-       }
-}
-
-static inline struct mxc_jpeg_ctx *mxc_jpeg_fh_to_ctx(struct v4l2_fh *fh)
-{
-       return container_of(fh, struct mxc_jpeg_ctx, fh);
-}
-
-static int enum_fmt(const struct mxc_jpeg_fmt *mxc_formats, int n,
-                   struct v4l2_fmtdesc *f, u32 type)
-{
-       int i, num = 0;
-
-       for (i = 0; i < n; ++i) {
-               if (mxc_formats[i].flags == type) {
-                       /* index-th format of searched type found ? */
-                       if (num == f->index)
-                               break;
-                       /* Correct type but haven't reached our index yet,
-                        * just increment per-type index
-                        */
-                       ++num;
-               }
-       }
-
-       /* Format not found */
-       if (i >= n)
-               return -EINVAL;
-
-       strscpy(f->description, mxc_formats[i].name, sizeof(f->description));
-       f->pixelformat = mxc_formats[i].fourcc;
-
-       return 0;
-}
-
-static const struct mxc_jpeg_fmt *mxc_jpeg_find_format(struct mxc_jpeg_ctx *ctx,
-                                                      u32 pixelformat)
-{
-       unsigned int k;
-
-       for (k = 0; k < MXC_JPEG_NUM_FORMATS; k++) {
-               const struct mxc_jpeg_fmt *fmt = &mxc_formats[k];
-
-               if (fmt->fourcc == pixelformat)
-                       return fmt;
-       }
-       return NULL;
-}
-
-static enum mxc_jpeg_image_format mxc_jpeg_fourcc_to_imgfmt(u32 fourcc)
-{
-       switch (fourcc) {
-       case V4L2_PIX_FMT_GREY:
-               return MXC_JPEG_GRAY;
-       case V4L2_PIX_FMT_YUYV:
-               return MXC_JPEG_YUV422;
-       case V4L2_PIX_FMT_NV12M:
-               return MXC_JPEG_YUV420;
-       case V4L2_PIX_FMT_YUV24:
-               return MXC_JPEG_YUV444;
-       case V4L2_PIX_FMT_RGB24:
-               return MXC_JPEG_RGB;
-       case V4L2_PIX_FMT_ARGB32:
-               return MXC_JPEG_ARGB;
-       default:
-               return MXC_JPEG_INVALID;
-       }
-}
-
-static struct mxc_jpeg_q_data *mxc_jpeg_get_q_data(struct mxc_jpeg_ctx *ctx,
-                                                  enum v4l2_buf_type type)
-{
-       if (V4L2_TYPE_IS_OUTPUT(type))
-               return &ctx->out_q;
-       return &ctx->cap_q;
-}
-
-static void mxc_jpeg_addrs(struct mxc_jpeg_desc *desc,
-                          struct vb2_buffer *raw_buf,
-                          struct vb2_buffer *jpeg_buf, int offset)
-{
-       int img_fmt = desc->stm_ctrl & STM_CTRL_IMAGE_FORMAT_MASK;
-
-       desc->buf_base0 = vb2_dma_contig_plane_dma_addr(raw_buf, 0);
-       desc->buf_base1 = 0;
-       if (img_fmt == STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV420)) {
-               WARN_ON(raw_buf->num_planes < 2);
-               desc->buf_base1 = vb2_dma_contig_plane_dma_addr(raw_buf, 1);
-       }
-       desc->stm_bufbase = vb2_dma_contig_plane_dma_addr(jpeg_buf, 0) +
-               offset;
-}
-
-static void notify_eos(struct mxc_jpeg_ctx *ctx)
-{
-       const struct v4l2_event ev = {
-               .type = V4L2_EVENT_EOS
-       };
-
-       dev_dbg(ctx->mxc_jpeg->dev, "Notify app event EOS reached");
-       v4l2_event_queue_fh(&ctx->fh, &ev);
-}
-
-static void notify_src_chg(struct mxc_jpeg_ctx *ctx)
-{
-       const struct v4l2_event ev = {
-                       .type = V4L2_EVENT_SOURCE_CHANGE,
-                       .u.src_change.changes =
-                       V4L2_EVENT_SRC_CH_RESOLUTION,
-               };
-
-       dev_dbg(ctx->mxc_jpeg->dev, "Notify app event SRC_CH_RESOLUTION");
-       v4l2_event_queue_fh(&ctx->fh, &ev);
-}
-
-static int mxc_get_free_slot(struct mxc_jpeg_slot_data slot_data[], int n)
-{
-       int free_slot = 0;
-
-       while (slot_data[free_slot].used && free_slot < n)
-               free_slot++;
-
-       return free_slot; /* >=n when there are no more free slots */
-}
-
-static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg,
-                                    unsigned int slot)
-{
-       struct mxc_jpeg_desc *desc;
-       struct mxc_jpeg_desc *cfg_desc;
-       void *cfg_stm;
-
-       if (jpeg->slot_data[slot].desc)
-               goto skip_alloc; /* already allocated, reuse it */
-
-       /* allocate descriptor for decoding/encoding phase */
-       desc = dma_alloc_coherent(jpeg->dev,
-                                 sizeof(struct mxc_jpeg_desc),
-                                 &jpeg->slot_data[slot].desc_handle,
-                                 GFP_ATOMIC);
-       if (!desc)
-               goto err;
-       jpeg->slot_data[slot].desc = desc;
-
-       /* allocate descriptor for configuration phase (encoder only) */
-       cfg_desc = dma_alloc_coherent(jpeg->dev,
-                                     sizeof(struct mxc_jpeg_desc),
-                                     &jpeg->slot_data[slot].cfg_desc_handle,
-                                     GFP_ATOMIC);
-       if (!cfg_desc)
-               goto err;
-       jpeg->slot_data[slot].cfg_desc = cfg_desc;
-
-       /* allocate configuration stream */
-       cfg_stm = dma_alloc_coherent(jpeg->dev,
-                                    MXC_JPEG_MAX_CFG_STREAM,
-                                    &jpeg->slot_data[slot].cfg_stream_handle,
-                                    GFP_ATOMIC);
-       if (!cfg_stm)
-               goto err;
-       jpeg->slot_data[slot].cfg_stream_vaddr = cfg_stm;
-
-skip_alloc:
-       jpeg->slot_data[slot].used = true;
-
-       return true;
-err:
-       dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", slot);
-
-       return false;
-}
-
-static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg,
-                                   unsigned int slot)
-{
-       if (slot >= MXC_MAX_SLOTS) {
-               dev_err(jpeg->dev, "Invalid slot %d, nothing to free.", slot);
-               return;
-       }
-
-       /* free descriptor for decoding/encoding phase */
-       dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
-                         jpeg->slot_data[slot].desc,
-                         jpeg->slot_data[slot].desc_handle);
-
-       /* free descriptor for encoder configuration phase / decoder DHT */
-       dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
-                         jpeg->slot_data[slot].cfg_desc,
-                         jpeg->slot_data[slot].cfg_desc_handle);
-
-       /* free configuration stream */
-       dma_free_coherent(jpeg->dev, MXC_JPEG_MAX_CFG_STREAM,
-                         jpeg->slot_data[slot].cfg_stream_vaddr,
-                         jpeg->slot_data[slot].cfg_stream_handle);
-
-       jpeg->slot_data[slot].used = false;
-}
-
-static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
-{
-       struct mxc_jpeg_dev *jpeg = priv;
-       struct mxc_jpeg_ctx *ctx;
-       void __iomem *reg = jpeg->base_reg;
-       struct device *dev = jpeg->dev;
-       struct vb2_v4l2_buffer *src_buf, *dst_buf;
-       struct mxc_jpeg_src_buf *jpeg_src_buf;
-       enum vb2_buffer_state buf_state;
-       u32 dec_ret, com_status;
-       unsigned long payload;
-       struct mxc_jpeg_q_data *q_data;
-       enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       unsigned int slot;
-
-       spin_lock(&jpeg->hw_lock);
-
-       com_status = readl(reg + COM_STATUS);
-       slot = COM_STATUS_CUR_SLOT(com_status);
-       dev_dbg(dev, "Irq %d on slot %d.\n", irq, slot);
-
-       ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
-       if (!ctx) {
-               dev_err(dev,
-                       "Instance released before the end of transaction.\n");
-               /* soft reset only resets internal state, not registers */
-               mxc_jpeg_sw_reset(reg);
-               /* clear all interrupts */
-               writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));
-               goto job_unlock;
-       }
-
-       if (slot != ctx->slot) {
-               /* TODO investigate when adding multi-instance support */
-               dev_warn(dev, "IRQ slot %d != context slot %d.\n",
-                        slot, ctx->slot);
-               goto job_unlock;
-       }
-
-       dec_ret = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));
-       writel(dec_ret, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); /* w1c */
-
-       dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-       src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-       if (!dst_buf || !src_buf) {
-               dev_err(dev, "No source or destination buffer.\n");
-               goto job_unlock;
-       }
-       jpeg_src_buf = vb2_to_mxc_buf(&src_buf->vb2_buf);
-
-       if (dec_ret & SLOT_STATUS_ENC_CONFIG_ERR) {
-               u32 ret = readl(reg + CAST_STATUS12);
-
-               dev_err(dev, "Encoder/decoder error, status=0x%08x", ret);
-               mxc_jpeg_sw_reset(reg);
-               buf_state = VB2_BUF_STATE_ERROR;
-               goto buffers_done;
-       }
-
-       if (!(dec_ret & SLOT_STATUS_FRMDONE))
-               goto job_unlock;
-
-       if (jpeg->mode == MXC_JPEG_ENCODE &&
-           ctx->enc_state == MXC_JPEG_ENC_CONF) {
-               ctx->enc_state = MXC_JPEG_ENCODING;
-               dev_dbg(dev, "Encoder config finished. Start encoding...\n");
-               mxc_jpeg_enc_mode_go(dev, reg);
-               goto job_unlock;
-       }
-       if (jpeg->mode == MXC_JPEG_DECODE && jpeg_src_buf->dht_needed) {
-               jpeg_src_buf->dht_needed = false;
-               dev_dbg(dev, "Decoder DHT cfg finished. Start decoding...\n");
-               goto job_unlock;
-       }
-       if (jpeg->mode == MXC_JPEG_ENCODE) {
-               payload = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_BUF_PTR));
-               vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);
-               dev_dbg(dev, "Encoding finished, payload size: %ld\n",
-                       payload);
-       } else {
-               q_data = mxc_jpeg_get_q_data(ctx, cap_type);
-               payload = q_data->sizeimage[0];
-               vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);
-               vb2_set_plane_payload(&dst_buf->vb2_buf, 1, 0);
-               if (q_data->fmt->colplanes == 2) {
-                       payload = q_data->sizeimage[1];
-                       vb2_set_plane_payload(&dst_buf->vb2_buf, 1, payload);
-               }
-               dev_dbg(dev, "Decoding finished, payload size: %ld + %ld\n",
-                       vb2_get_plane_payload(&dst_buf->vb2_buf, 0),
-                       vb2_get_plane_payload(&dst_buf->vb2_buf, 1));
-       }
-
-       /* short preview of the results */
-       dev_dbg(dev, "src_buf preview: ");
-       print_mxc_buf(jpeg, &src_buf->vb2_buf, 32);
-       dev_dbg(dev, "dst_buf preview: ");
-       print_mxc_buf(jpeg, &dst_buf->vb2_buf, 32);
-       buf_state = VB2_BUF_STATE_DONE;
-
-buffers_done:
-       jpeg->slot_data[slot].used = false; /* unused, but don't free */
-       v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-       v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-       v4l2_m2m_buf_done(src_buf, buf_state);
-       v4l2_m2m_buf_done(dst_buf, buf_state);
-       spin_unlock(&jpeg->hw_lock);
-       v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
-       return IRQ_HANDLED;
-job_unlock:
-       spin_unlock(&jpeg->hw_lock);
-       return IRQ_HANDLED;
-}
-
-static int mxc_jpeg_fixup_sof(struct mxc_jpeg_sof *sof,
-                             u32 fourcc,
-                             u16 w, u16 h)
-{
-       int sof_length;
-
-       sof->precision = 8; /* TODO allow 8/12 bit precision*/
-       sof->height = h;
-       _bswap16(&sof->height);
-       sof->width = w;
-       _bswap16(&sof->width);
-
-       switch (fourcc) {
-       case V4L2_PIX_FMT_NV12M:
-               sof->components_no = 3;
-               sof->comp[0].v = 0x2;
-               sof->comp[0].h = 0x2;
-               break;
-       case V4L2_PIX_FMT_YUYV:
-               sof->components_no = 3;
-               sof->comp[0].v = 0x1;
-               sof->comp[0].h = 0x2;
-               break;
-       case V4L2_PIX_FMT_YUV24:
-       case V4L2_PIX_FMT_RGB24:
-       default:
-               sof->components_no = 3;
-               break;
-       case V4L2_PIX_FMT_ARGB32:
-               sof->components_no = 4;
-               break;
-       case V4L2_PIX_FMT_GREY:
-               sof->components_no = 1;
-               break;
-       }
-       sof_length = 8 + 3 * sof->components_no;
-       sof->length = sof_length;
-       _bswap16(&sof->length);
-
-       return sof_length; /* not swaped */
-}
-
-static int mxc_jpeg_fixup_sos(struct mxc_jpeg_sos *sos,
-                             u32 fourcc)
-{
-       int sos_length;
-       u8 *sof_u8 = (u8 *)sos;
-
-       switch (fourcc) {
-       case V4L2_PIX_FMT_NV12M:
-               sos->components_no = 3;
-               break;
-       case V4L2_PIX_FMT_YUYV:
-               sos->components_no = 3;
-               break;
-       case V4L2_PIX_FMT_YUV24:
-       case V4L2_PIX_FMT_RGB24:
-       default:
-               sos->components_no = 3;
-               break;
-       case V4L2_PIX_FMT_ARGB32:
-               sos->components_no = 4;
-               break;
-       case V4L2_PIX_FMT_GREY:
-               sos->components_no = 1;
-               break;
-       }
-       sos_length = 6 + 2 * sos->components_no;
-       sos->length = sos_length;
-       _bswap16(&sos->length);
-
-       /* SOS ignorable bytes, not so ignorable after all */
-       sof_u8[sos_length - 1] = 0x0;
-       sof_u8[sos_length - 2] = 0x3f;
-       sof_u8[sos_length - 3] = 0x0;
-
-       return sos_length; /* not swaped */
-}
-
-static unsigned int mxc_jpeg_setup_cfg_stream(void *cfg_stream_vaddr,
-                                             u32 fourcc,
-                                             u16 w, u16 h)
-{
-       unsigned int offset = 0;
-       u8 *cfg = (u8 *)cfg_stream_vaddr;
-       struct mxc_jpeg_sof *sof;
-       struct mxc_jpeg_sos *sos;
-
-       memcpy(cfg + offset, jpeg_soi, ARRAY_SIZE(jpeg_soi));
-       offset += ARRAY_SIZE(jpeg_soi);
-
-       if (fourcc == V4L2_PIX_FMT_RGB24 ||
-           fourcc == V4L2_PIX_FMT_ARGB32) {
-               memcpy(cfg + offset, jpeg_app14, sizeof(jpeg_app14));
-               offset += sizeof(jpeg_app14);
-       } else {
-               memcpy(cfg + offset, jpeg_app0, sizeof(jpeg_app0));
-               offset += sizeof(jpeg_app0);
-       }
-
-       memcpy(cfg + offset, jpeg_dqt, sizeof(jpeg_dqt));
-       offset += sizeof(jpeg_dqt);
-
-       memcpy(cfg + offset, jpeg_sof_maximal, sizeof(jpeg_sof_maximal));
-       offset += 2; /* skip marker ID */
-       sof = (struct mxc_jpeg_sof *)(cfg + offset);
-       offset += mxc_jpeg_fixup_sof(sof, fourcc, w, h);
-
-       memcpy(cfg + offset, jpeg_dht, sizeof(jpeg_dht));
-       offset += sizeof(jpeg_dht);
-
-       memcpy(cfg + offset, jpeg_dri, sizeof(jpeg_dri));
-       offset += sizeof(jpeg_dri);
-
-       memcpy(cfg + offset, jpeg_sos_maximal, sizeof(jpeg_sos_maximal));
-       offset += 2; /* skip marker ID */
-       sos = (struct mxc_jpeg_sos *)(cfg + offset);
-       offset += mxc_jpeg_fixup_sos(sos, fourcc);
-
-       memcpy(cfg + offset, jpeg_image_red, sizeof(jpeg_image_red));
-       offset += sizeof(jpeg_image_red);
-
-       memcpy(cfg + offset, jpeg_eoi, sizeof(jpeg_eoi));
-       offset += sizeof(jpeg_eoi);
-
-       return offset;
-}
-
-static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf,
-                                    struct mxc_jpeg_ctx *ctx,
-                                    struct vb2_buffer *src_buf,
-                                    struct vb2_buffer *dst_buf)
-{
-       enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       struct mxc_jpeg_q_data *q_data_cap;
-       enum mxc_jpeg_image_format img_fmt;
-       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
-       void __iomem *reg = jpeg->base_reg;
-       unsigned int slot = ctx->slot;
-       struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
-       struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
-       dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
-       dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
-       dma_addr_t cfg_stream_handle = jpeg->slot_data[slot].cfg_stream_handle;
-       unsigned int *cfg_size = &jpeg->slot_data[slot].cfg_stream_size;
-       void *cfg_stream_vaddr = jpeg->slot_data[slot].cfg_stream_vaddr;
-       struct mxc_jpeg_src_buf *jpeg_src_buf;
-
-       jpeg_src_buf = vb2_to_mxc_buf(src_buf);
-
-       /* setup the decoding descriptor */
-       desc->next_descpt_ptr = 0; /* end of chain */
-       q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
-       desc->imgsize = q_data_cap->w_adjusted << 16 | q_data_cap->h_adjusted;
-       img_fmt = mxc_jpeg_fourcc_to_imgfmt(q_data_cap->fmt->fourcc);
-       desc->stm_ctrl &= ~STM_CTRL_IMAGE_FORMAT(0xF); /* clear image format */
-       desc->stm_ctrl |= STM_CTRL_IMAGE_FORMAT(img_fmt);
-       desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
-       desc->line_pitch = q_data_cap->bytesperline[0];
-       mxc_jpeg_addrs(desc, dst_buf, src_buf, 0);
-       mxc_jpeg_set_bufsize(desc, ALIGN(vb2_plane_size(src_buf, 0), 1024));
-       print_descriptor_info(jpeg->dev, desc);
-
-       if (!jpeg_src_buf->dht_needed) {
-               /* validate the decoding descriptor */
-               mxc_jpeg_set_desc(desc_handle, reg, slot);
-               return;
-       }
-
-       /*
-        * if a default huffman table is needed, use the config descriptor to
-        * inject a DHT, by chaining it before the decoding descriptor
-        */
-       *cfg_size = mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,
-                                             V4L2_PIX_FMT_YUYV,
-                                             MXC_JPEG_MIN_WIDTH,
-                                             MXC_JPEG_MIN_HEIGHT);
-       cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;
-       cfg_desc->buf_base0 = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
-       cfg_desc->buf_base1 = 0;
-       cfg_desc->imgsize = MXC_JPEG_MIN_WIDTH << 16;
-       cfg_desc->imgsize |= MXC_JPEG_MIN_HEIGHT;
-       cfg_desc->line_pitch = MXC_JPEG_MIN_WIDTH * 2;
-       cfg_desc->stm_ctrl = STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV422);
-       cfg_desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
-       cfg_desc->stm_bufbase = cfg_stream_handle;
-       cfg_desc->stm_bufsize = ALIGN(*cfg_size, 1024);
-       print_descriptor_info(jpeg->dev, cfg_desc);
-
-       /* validate the configuration descriptor */
-       mxc_jpeg_set_desc(cfg_desc_handle, reg, slot);
-}
-
-static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
-                                    struct mxc_jpeg_ctx *ctx,
-                                    struct vb2_buffer *src_buf,
-                                    struct vb2_buffer *dst_buf)
-{
-       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
-       void __iomem *reg = jpeg->base_reg;
-       unsigned int slot = ctx->slot;
-       struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
-       struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
-       dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
-       dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
-       void *cfg_stream_vaddr = jpeg->slot_data[slot].cfg_stream_vaddr;
-       struct mxc_jpeg_q_data *q_data;
-       enum mxc_jpeg_image_format img_fmt;
-       int w, h;
-
-       q_data = mxc_jpeg_get_q_data(ctx, src_buf->vb2_queue->type);
-
-       jpeg->slot_data[slot].cfg_stream_size =
-                       mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,
-                                                 q_data->fmt->fourcc,
-                                                 q_data->w_adjusted,
-                                                 q_data->h_adjusted);
-
-       /* chain the config descriptor with the encoding descriptor */
-       cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;
-
-       cfg_desc->buf_base0 = jpeg->slot_data[slot].cfg_stream_handle;
-       cfg_desc->buf_base1 = 0;
-       cfg_desc->line_pitch = 0;
-       cfg_desc->stm_bufbase = 0; /* no output expected */
-       cfg_desc->stm_bufsize = 0x0;
-       cfg_desc->imgsize = 0;
-       cfg_desc->stm_ctrl = STM_CTRL_CONFIG_MOD(1);
-       cfg_desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
-
-       desc->next_descpt_ptr = 0; /* end of chain */
-
-       /* use adjusted resolution for CAST IP job */
-       w = q_data->w_adjusted;
-       h = q_data->h_adjusted;
-       mxc_jpeg_set_res(desc, w, h);
-       mxc_jpeg_set_line_pitch(desc, w * (q_data->fmt->depth / 8));
-       mxc_jpeg_set_bufsize(desc, desc->line_pitch * h);
-       img_fmt = mxc_jpeg_fourcc_to_imgfmt(q_data->fmt->fourcc);
-       if (img_fmt == MXC_JPEG_INVALID)
-               dev_err(jpeg->dev, "No valid image format detected\n");
-       desc->stm_ctrl = STM_CTRL_CONFIG_MOD(0) |
-                        STM_CTRL_IMAGE_FORMAT(img_fmt);
-       desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
-       mxc_jpeg_addrs(desc, src_buf, dst_buf, 0);
-       dev_dbg(jpeg->dev, "cfg_desc:\n");
-       print_descriptor_info(jpeg->dev, cfg_desc);
-       dev_dbg(jpeg->dev, "enc desc:\n");
-       print_descriptor_info(jpeg->dev, desc);
-       print_wrapper_info(jpeg->dev, reg);
-       print_cast_status(jpeg->dev, reg, MXC_JPEG_ENCODE);
-
-       /* validate the configuration descriptor */
-       mxc_jpeg_set_desc(cfg_desc_handle, reg, slot);
-}
-
-static void mxc_jpeg_device_run(void *priv)
-{
-       struct mxc_jpeg_ctx *ctx = priv;
-       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
-       void __iomem *reg = jpeg->base_reg;
-       struct device *dev = jpeg->dev;
-       struct vb2_v4l2_buffer *src_buf, *dst_buf;
-       unsigned long flags;
-       struct mxc_jpeg_q_data *q_data_cap, *q_data_out;
-       struct mxc_jpeg_src_buf *jpeg_src_buf;
-
-       spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);
-       src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-       dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-       if (!src_buf || !dst_buf) {
-               dev_err(dev, "Null src or dst buf\n");
-               goto end;
-       }
-
-       q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-       if (!q_data_cap)
-               goto end;
-       q_data_out = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-       if (!q_data_out)
-               goto end;
-       src_buf->sequence = q_data_out->sequence++;
-       dst_buf->sequence = q_data_cap->sequence++;
-
-       v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true);
-
-       jpeg_src_buf = vb2_to_mxc_buf(&src_buf->vb2_buf);
-       if (q_data_cap->fmt->colplanes != dst_buf->vb2_buf.num_planes) {
-               dev_err(dev, "Capture format %s has %d planes, but capture buffer has %d planes\n",
-                       q_data_cap->fmt->name, q_data_cap->fmt->colplanes,
-                       dst_buf->vb2_buf.num_planes);
-               jpeg_src_buf->jpeg_parse_error = true;
-       }
-       if (jpeg_src_buf->jpeg_parse_error) {
-               v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-               v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-               v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
-               v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
-               spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
-               v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
-
-               return;
-       }
-
-       mxc_jpeg_enable(reg);
-       mxc_jpeg_set_l_endian(reg, 1);
-
-       ctx->slot = mxc_get_free_slot(jpeg->slot_data, MXC_MAX_SLOTS);
-       if (ctx->slot >= MXC_MAX_SLOTS) {
-               dev_err(dev, "No more free slots\n");
-               goto end;
-       }
-       if (!mxc_jpeg_alloc_slot_data(jpeg, ctx->slot)) {
-               dev_err(dev, "Cannot allocate slot data\n");
-               goto end;
-       }
-
-       mxc_jpeg_enable_slot(reg, ctx->slot);
-       mxc_jpeg_enable_irq(reg, ctx->slot);
-
-       if (jpeg->mode == MXC_JPEG_ENCODE) {
-               dev_dbg(dev, "Encoding on slot %d\n", ctx->slot);
-               ctx->enc_state = MXC_JPEG_ENC_CONF;
-               mxc_jpeg_config_enc_desc(&dst_buf->vb2_buf, ctx,
-                                        &src_buf->vb2_buf, &dst_buf->vb2_buf);
-               mxc_jpeg_enc_mode_conf(dev, reg); /* start config phase */
-       } else {
-               dev_dbg(dev, "Decoding on slot %d\n", ctx->slot);
-               print_mxc_buf(jpeg, &src_buf->vb2_buf, 0);
-               mxc_jpeg_config_dec_desc(&dst_buf->vb2_buf, ctx,
-                                        &src_buf->vb2_buf, &dst_buf->vb2_buf);
-               mxc_jpeg_dec_mode_go(dev, reg);
-       }
-end:
-       spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
-}
-
-static void mxc_jpeg_set_last_buffer_dequeued(struct mxc_jpeg_ctx *ctx)
-{
-       struct vb2_queue *q;
-
-       ctx->stopped = 1;
-       q = v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx);
-       if (!list_empty(&q->done_list))
-               return;
-
-       q->last_buffer_dequeued = true;
-       wake_up(&q->done_wq);
-       ctx->stopped = 0;
-}
-
-static int mxc_jpeg_decoder_cmd(struct file *file, void *priv,
-                               struct v4l2_decoder_cmd *cmd)
-{
-       struct v4l2_fh *fh = file->private_data;
-       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);
-       struct device *dev = ctx->mxc_jpeg->dev;
-       int ret;
-
-       ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd);
-       if (ret < 0)
-               return ret;
-
-       if (cmd->cmd == V4L2_DEC_CMD_STOP) {
-               dev_dbg(dev, "Received V4L2_DEC_CMD_STOP");
-               if (v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx) == 0) {
-                       /* No more src bufs, notify app EOS */
-                       notify_eos(ctx);
-                       mxc_jpeg_set_last_buffer_dequeued(ctx);
-               } else {
-                       /* will send EOS later*/
-                       ctx->stopping = 1;
-               }
-       }
-
-       return 0;
-}
-
-static int mxc_jpeg_encoder_cmd(struct file *file, void *priv,
-                               struct v4l2_encoder_cmd *cmd)
-{
-       struct v4l2_fh *fh = file->private_data;
-       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);
-       struct device *dev = ctx->mxc_jpeg->dev;
-       int ret;
-
-       ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, cmd);
-       if (ret < 0)
-               return ret;
-
-       if (cmd->cmd == V4L2_ENC_CMD_STOP) {
-               dev_dbg(dev, "Received V4L2_ENC_CMD_STOP");
-               if (v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx) == 0) {
-                       /* No more src bufs, notify app EOS */
-                       notify_eos(ctx);
-                       mxc_jpeg_set_last_buffer_dequeued(ctx);
-               } else {
-                       /* will send EOS later*/
-                       ctx->stopping = 1;
-               }
-       }
-
-       return 0;
-}
-
-static int mxc_jpeg_queue_setup(struct vb2_queue *q,
-                               unsigned int *nbuffers,
-                               unsigned int *nplanes,
-                               unsigned int sizes[],
-                               struct device *alloc_ctxs[])
-{
-       struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);
-       struct mxc_jpeg_q_data *q_data = NULL;
-       int i;
-
-       q_data = mxc_jpeg_get_q_data(ctx, q->type);
-       if (!q_data)
-               return -EINVAL;
-
-       /* Handle CREATE_BUFS situation - *nplanes != 0 */
-       if (*nplanes) {
-               for (i = 0; i < *nplanes; i++) {
-                       if (sizes[i] < q_data->sizeimage[i])
-                               return -EINVAL;
-               }
-               return 0;
-       }
-
-       /* Handle REQBUFS situation */
-       *nplanes = q_data->fmt->colplanes;
-       for (i = 0; i < *nplanes; i++)
-               sizes[i] = q_data->sizeimage[i];
-
-       return 0;
-}
-
-static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
-{
-       struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);
-       struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, q->type);
-       int ret;
-
-       dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx);
-       q_data->sequence = 0;
-
-       ret = pm_runtime_resume_and_get(ctx->mxc_jpeg->dev);
-       if (ret < 0) {
-               dev_err(ctx->mxc_jpeg->dev, "Failed to power up jpeg\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static void mxc_jpeg_stop_streaming(struct vb2_queue *q)
-{
-       struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);
-       struct vb2_v4l2_buffer *vbuf;
-
-       dev_dbg(ctx->mxc_jpeg->dev, "Stop streaming ctx=%p", ctx);
-
-       /* Release all active buffers */
-       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_sync(&ctx->mxc_jpeg->pdev->dev);
-       if (V4L2_TYPE_IS_OUTPUT(q->type)) {
-               ctx->stopping = 0;
-               ctx->stopped = 0;
-       }
-}
-
-static int mxc_jpeg_valid_comp_id(struct device *dev,
-                                 struct mxc_jpeg_sof *sof,
-                                 struct mxc_jpeg_sos *sos)
-{
-       int valid = 1;
-       int i;
-
-       /*
-        * there's a limitation in the IP that the component IDs must be
-        * between 0..4, if they are not, let's patch them
-        */
-       for (i = 0; i < sof->components_no; i++)
-               if (sof->comp[i].id > MXC_JPEG_MAX_COMPONENTS) {
-                       valid = 0;
-                       dev_err(dev, "Component %d has invalid ID: %d",
-                               i, sof->comp[i].id);
-               }
-       if (!valid)
-               /* patch all comp IDs if at least one is invalid */
-               for (i = 0; i < sof->components_no; i++) {
-                       dev_warn(dev, "Component %d ID patched to: %d",
-                                i, i + 1);
-                       sof->comp[i].id = i + 1;
-                       sos->comp[i].id = i + 1;
-               }
-
-       return valid;
-}
-
-static u32 mxc_jpeg_get_image_format(struct device *dev,
-                                    const struct v4l2_jpeg_header *header)
-{
-       int i;
-       u32 fourcc = 0;
-
-       for (i = 0; i < MXC_JPEG_NUM_FORMATS; i++)
-               if (mxc_formats[i].subsampling == header->frame.subsampling &&
-                   mxc_formats[i].nc == header->frame.num_components) {
-                       fourcc = mxc_formats[i].fourcc;
-                       break;
-               }
-       if (fourcc == 0) {
-               dev_err(dev, "Could not identify image format nc=%d, subsampling=%d\n",
-                       header->frame.num_components,
-                       header->frame.subsampling);
-               return fourcc;
-       }
-       /*
-        * If the transform flag from APP14 marker is 0, images that are
-        * encoded with 3 components have RGB colorspace, see Recommendation
-        * ITU-T T.872 chapter 6.5.3 APP14 marker segment for colour encoding
-        */
-       if (fourcc == V4L2_PIX_FMT_YUV24 || fourcc == V4L2_PIX_FMT_RGB24) {
-               if (header->app14_tf == V4L2_JPEG_APP14_TF_CMYK_RGB)
-                       fourcc = V4L2_PIX_FMT_RGB24;
-               else
-                       fourcc = V4L2_PIX_FMT_YUV24;
-       }
-
-       return fourcc;
-}
-
-static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q,
-                                 u32 precision)
-{
-       /* Bytes distance between the leftmost pixels in two adjacent lines */
-       if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {
-               /* bytesperline unused for compressed formats */
-               q->bytesperline[0] = 0;
-               q->bytesperline[1] = 0;
-       } else if (q->fmt->fourcc == V4L2_PIX_FMT_NV12M) {
-               /* When the image format is planar the bytesperline value
-                * applies to the first plane and is divided by the same factor
-                * as the width field for the other planes
-                */
-               q->bytesperline[0] = q->w * (precision / 8) *
-                                    (q->fmt->depth / 8);
-               q->bytesperline[1] = q->bytesperline[0];
-       } else {
-               /* single plane formats */
-               q->bytesperline[0] = q->w * (precision / 8) *
-                                    (q->fmt->depth / 8);
-               q->bytesperline[1] = 0;
-       }
-}
-
-static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q)
-{
-       if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {
-               /* if no sizeimage from user, assume worst jpeg compression */
-               if (!q->sizeimage[0])
-                       q->sizeimage[0] = 6 * q->w * q->h;
-               q->sizeimage[1] = 0;
-
-               if (q->sizeimage[0] > MXC_JPEG_MAX_SIZEIMAGE)
-                       q->sizeimage[0] = MXC_JPEG_MAX_SIZEIMAGE;
-
-               /* jpeg stream size must be multiple of 1K */
-               q->sizeimage[0] = ALIGN(q->sizeimage[0], 1024);
-       } else {
-               q->sizeimage[0] = q->bytesperline[0] * q->h;
-               q->sizeimage[1] = 0;
-               if (q->fmt->fourcc == V4L2_PIX_FMT_NV12M)
-                       q->sizeimage[1] = q->sizeimage[0] / 2;
-       }
-}
-
-static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx,
-                         u8 *src_addr, u32 size, bool *dht_needed)
-{
-       struct device *dev = ctx->mxc_jpeg->dev;
-       struct mxc_jpeg_q_data *q_data_out, *q_data_cap;
-       enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       bool src_chg = false;
-       u32 fourcc;
-       struct v4l2_jpeg_header header;
-       struct mxc_jpeg_sof *psof = NULL;
-       struct mxc_jpeg_sos *psos = NULL;
-       int ret;
-
-       memset(&header, 0, sizeof(header));
-       ret = v4l2_jpeg_parse_header((void *)src_addr, size, &header);
-       if (ret < 0) {
-               dev_err(dev, "Error parsing JPEG stream markers\n");
-               return ret;
-       }
-
-       /* if DHT marker present, no need to inject default one */
-       *dht_needed = (header.num_dht == 0);
-
-       q_data_out = mxc_jpeg_get_q_data(ctx,
-                                        V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
-       if (q_data_out->w == 0 && q_data_out->h == 0) {
-               dev_warn(dev, "Invalid user resolution 0x0");
-               dev_warn(dev, "Keeping resolution from JPEG: %dx%d",
-                        header.frame.width, header.frame.height);
-               q_data_out->w = header.frame.width;
-               q_data_out->h = header.frame.height;
-       } else if (header.frame.width != q_data_out->w ||
-                  header.frame.height != q_data_out->h) {
-               dev_err(dev,
-                       "Resolution mismatch: %dx%d (JPEG) versus %dx%d(user)",
-                       header.frame.width, header.frame.height,
-                       q_data_out->w, q_data_out->h);
-               return -EINVAL;
-       }
-       if (header.frame.width % 8 != 0 || header.frame.height % 8 != 0) {
-               dev_err(dev, "JPEG width or height not multiple of 8: %dx%d\n",
-                       header.frame.width, header.frame.height);
-               return -EINVAL;
-       }
-       if (header.frame.width > MXC_JPEG_MAX_WIDTH ||
-           header.frame.height > MXC_JPEG_MAX_HEIGHT) {
-               dev_err(dev, "JPEG width or height should be <= 8192: %dx%d\n",
-                       header.frame.width, header.frame.height);
-               return -EINVAL;
-       }
-       if (header.frame.width < MXC_JPEG_MIN_WIDTH ||
-           header.frame.height < MXC_JPEG_MIN_HEIGHT) {
-               dev_err(dev, "JPEG width or height should be > 64: %dx%d\n",
-                       header.frame.width, header.frame.height);
-               return -EINVAL;
-       }
-       if (header.frame.num_components > V4L2_JPEG_MAX_COMPONENTS) {
-               dev_err(dev, "JPEG number of components should be <=%d",
-                       V4L2_JPEG_MAX_COMPONENTS);
-               return -EINVAL;
-       }
-       /* check and, if necessary, patch component IDs*/
-       psof = (struct mxc_jpeg_sof *)header.sof.start;
-       psos = (struct mxc_jpeg_sos *)header.sos.start;
-       if (!mxc_jpeg_valid_comp_id(dev, psof, psos))
-               dev_warn(dev, "JPEG component ids should be 0-3 or 1-4");
-
-       fourcc = mxc_jpeg_get_image_format(dev, &header);
-       if (fourcc == 0)
-               return -EINVAL;
-
-       /*
-        * set-up the capture queue with the pixelformat and resolution
-        * detected from the jpeg output stream
-        */
-       q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
-       if (q_data_cap->w != header.frame.width ||
-           q_data_cap->h != header.frame.height)
-               src_chg = true;
-       q_data_cap->w = header.frame.width;
-       q_data_cap->h = header.frame.height;
-       q_data_cap->fmt = mxc_jpeg_find_format(ctx, fourcc);
-       q_data_cap->w_adjusted = q_data_cap->w;
-       q_data_cap->h_adjusted = q_data_cap->h;
-       /*
-        * align up the resolution for CAST IP,
-        * but leave the buffer resolution unchanged
-        */
-       v4l_bound_align_image(&q_data_cap->w_adjusted,
-                             q_data_cap->w_adjusted,  /* adjust up */
-                             MXC_JPEG_MAX_WIDTH,
-                             q_data_cap->fmt->h_align,
-                             &q_data_cap->h_adjusted,
-                             q_data_cap->h_adjusted, /* adjust up */
-                             MXC_JPEG_MAX_HEIGHT,
-                             q_data_cap->fmt->v_align,
-                             0);
-       dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
-               q_data_cap->w, q_data_cap->h,
-               q_data_cap->w_adjusted, q_data_cap->h_adjusted,
-               (fourcc & 0xff),
-               (fourcc >>  8) & 0xff,
-               (fourcc >> 16) & 0xff,
-               (fourcc >> 24) & 0xff);
-
-       /* setup bytesperline/sizeimage for capture queue */
-       mxc_jpeg_bytesperline(q_data_cap, header.frame.precision);
-       mxc_jpeg_sizeimage(q_data_cap);
-
-       /*
-        * if the CAPTURE format was updated with new values, regardless of
-        * whether they match the values set by the client or not, signal
-        * a source change event
-        */
-       if (src_chg)
-               notify_src_chg(ctx);
-
-       return 0;
-}
-
-static void mxc_jpeg_buf_queue(struct vb2_buffer *vb)
-{
-       int ret;
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-       struct mxc_jpeg_src_buf *jpeg_src_buf;
-
-       if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               goto end;
-
-       /* for V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE */
-       if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE)
-               goto end;
-
-       jpeg_src_buf = vb2_to_mxc_buf(vb);
-       jpeg_src_buf->jpeg_parse_error = false;
-       ret = mxc_jpeg_parse(ctx,
-                            (u8 *)vb2_plane_vaddr(vb, 0),
-                            vb2_get_plane_payload(vb, 0),
-                            &jpeg_src_buf->dht_needed);
-       if (ret)
-               jpeg_src_buf->jpeg_parse_error = true;
-
-end:
-       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
-}
-
-static int mxc_jpeg_buf_out_validate(struct vb2_buffer *vb)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-
-       vbuf->field = V4L2_FIELD_NONE;
-
-       return 0;
-}
-
-static int mxc_jpeg_buf_prepare(struct vb2_buffer *vb)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-       struct mxc_jpeg_q_data *q_data = NULL;
-       struct device *dev = ctx->mxc_jpeg->dev;
-       unsigned long sizeimage;
-       int i;
-
-       vbuf->field = V4L2_FIELD_NONE;
-
-       q_data = mxc_jpeg_get_q_data(ctx, vb->vb2_queue->type);
-       if (!q_data)
-               return -EINVAL;
-       for (i = 0; i < q_data->fmt->colplanes; i++) {
-               sizeimage = q_data->sizeimage[i];
-               if (vb2_plane_size(vb, i) < sizeimage) {
-                       dev_err(dev, "plane %d too small (%lu < %lu)",
-                               i, vb2_plane_size(vb, i), sizeimage);
-                       return -EINVAL;
-               }
-               vb2_set_plane_payload(vb, i, sizeimage);
-       }
-       return 0;
-}
-
-static void mxc_jpeg_buf_finish(struct vb2_buffer *vb)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-       struct vb2_queue *q = vb->vb2_queue;
-
-       if (V4L2_TYPE_IS_OUTPUT(vb->type))
-               return;
-       if (!ctx->stopped)
-               return;
-       if (list_empty(&q->done_list)) {
-               vbuf->flags |= V4L2_BUF_FLAG_LAST;
-               ctx->stopped = 0;
-       }
-}
-
-static const struct vb2_ops mxc_jpeg_qops = {
-       .queue_setup            = mxc_jpeg_queue_setup,
-       .wait_prepare           = vb2_ops_wait_prepare,
-       .wait_finish            = vb2_ops_wait_finish,
-       .buf_out_validate       = mxc_jpeg_buf_out_validate,
-       .buf_prepare            = mxc_jpeg_buf_prepare,
-       .buf_finish             = mxc_jpeg_buf_finish,
-       .start_streaming        = mxc_jpeg_start_streaming,
-       .stop_streaming         = mxc_jpeg_stop_streaming,
-       .buf_queue              = mxc_jpeg_buf_queue,
-};
-
-static int mxc_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,
-                              struct vb2_queue *dst_vq)
-{
-       struct mxc_jpeg_ctx *ctx = priv;
-       int ret;
-
-       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-       src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
-       src_vq->drv_priv = ctx;
-       src_vq->buf_struct_size = sizeof(struct mxc_jpeg_src_buf);
-       src_vq->ops = &mxc_jpeg_qops;
-       src_vq->mem_ops = &vb2_dma_contig_memops;
-       src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       src_vq->lock = &ctx->mxc_jpeg->lock;
-       src_vq->dev = ctx->mxc_jpeg->dev;
-       src_vq->allow_zero_bytesused = 1; /* keep old userspace apps working */
-
-       ret = vb2_queue_init(src_vq);
-       if (ret)
-               return ret;
-
-       dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
-       dst_vq->drv_priv = ctx;
-       dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-       dst_vq->ops = &mxc_jpeg_qops;
-       dst_vq->mem_ops = &vb2_dma_contig_memops;
-       dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       dst_vq->lock = &ctx->mxc_jpeg->lock;
-       dst_vq->dev = ctx->mxc_jpeg->dev;
-
-       ret = vb2_queue_init(dst_vq);
-       return ret;
-}
-
-static void mxc_jpeg_set_default_params(struct mxc_jpeg_ctx *ctx)
-{
-       struct mxc_jpeg_q_data *out_q = &ctx->out_q;
-       struct mxc_jpeg_q_data *cap_q = &ctx->cap_q;
-       struct mxc_jpeg_q_data *q[2] = {out_q, cap_q};
-       int i;
-
-       if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) {
-               out_q->fmt = mxc_jpeg_find_format(ctx, MXC_JPEG_DEFAULT_PFMT);
-               cap_q->fmt = mxc_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG);
-       } else {
-               out_q->fmt = mxc_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG);
-               cap_q->fmt = mxc_jpeg_find_format(ctx, MXC_JPEG_DEFAULT_PFMT);
-       }
-
-       for (i = 0; i < 2; i++) {
-               q[i]->w = MXC_JPEG_DEFAULT_WIDTH;
-               q[i]->h = MXC_JPEG_DEFAULT_HEIGHT;
-               q[i]->w_adjusted = MXC_JPEG_DEFAULT_WIDTH;
-               q[i]->h_adjusted = MXC_JPEG_DEFAULT_HEIGHT;
-               mxc_jpeg_bytesperline(q[i], 8);
-               mxc_jpeg_sizeimage(q[i]);
-       }
-}
-
-static int mxc_jpeg_open(struct file *file)
-{
-       struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file);
-       struct video_device *mxc_vfd = video_devdata(file);
-       struct device *dev = mxc_jpeg->dev;
-       struct mxc_jpeg_ctx *ctx;
-       int ret = 0;
-
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)
-               return -ENOMEM;
-
-       if (mutex_lock_interruptible(&mxc_jpeg->lock)) {
-               ret = -ERESTARTSYS;
-               goto free;
-       }
-
-       v4l2_fh_init(&ctx->fh, mxc_vfd);
-       file->private_data = &ctx->fh;
-       v4l2_fh_add(&ctx->fh);
-
-       ctx->mxc_jpeg = mxc_jpeg;
-
-       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(mxc_jpeg->m2m_dev, ctx,
-                                           mxc_jpeg_queue_init);
-
-       if (IS_ERR(ctx->fh.m2m_ctx)) {
-               ret = PTR_ERR(ctx->fh.m2m_ctx);
-               goto error;
-       }
-
-       mxc_jpeg_set_default_params(ctx);
-       ctx->slot = MXC_MAX_SLOTS; /* slot not allocated yet */
-
-       if (mxc_jpeg->mode == MXC_JPEG_DECODE)
-               dev_dbg(dev, "Opened JPEG decoder instance %p\n", ctx);
-       else
-               dev_dbg(dev, "Opened JPEG encoder instance %p\n", ctx);
-       mutex_unlock(&mxc_jpeg->lock);
-
-       return 0;
-
-error:
-       v4l2_fh_del(&ctx->fh);
-       v4l2_fh_exit(&ctx->fh);
-       mutex_unlock(&mxc_jpeg->lock);
-free:
-       kfree(ctx);
-       return ret;
-}
-
-static int mxc_jpeg_querycap(struct file *file, void *priv,
-                            struct v4l2_capability *cap)
-{
-       struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file);
-
-       strscpy(cap->driver, MXC_JPEG_NAME " codec", sizeof(cap->driver));
-       strscpy(cap->card, MXC_JPEG_NAME " codec", sizeof(cap->card));
-       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
-                dev_name(mxc_jpeg->dev));
-       cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
-       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-
-       return 0;
-}
-
-static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
-                                    struct v4l2_fmtdesc *f)
-{
-       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
-
-       if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE)
-               return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
-                       MXC_JPEG_FMT_TYPE_ENC);
-       else
-               return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
-                       MXC_JPEG_FMT_TYPE_RAW);
-}
-
-static int mxc_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
-                                    struct v4l2_fmtdesc *f)
-{
-       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
-
-       if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)
-               return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
-                               MXC_JPEG_FMT_TYPE_ENC);
-       else
-               return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
-                               MXC_JPEG_FMT_TYPE_RAW);
-}
-
-static int mxc_jpeg_try_fmt(struct v4l2_format *f, const struct mxc_jpeg_fmt *fmt,
-                           struct mxc_jpeg_ctx *ctx, int q_type)
-{
-       struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
-       struct v4l2_plane_pix_format *pfmt;
-       u32 w = (pix_mp->width < MXC_JPEG_MAX_WIDTH) ?
-                pix_mp->width : MXC_JPEG_MAX_WIDTH;
-       u32 h = (pix_mp->height < MXC_JPEG_MAX_HEIGHT) ?
-                pix_mp->height : MXC_JPEG_MAX_HEIGHT;
-       int i;
-       struct mxc_jpeg_q_data tmp_q;
-
-       memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
-       pix_mp->field = V4L2_FIELD_NONE;
-       pix_mp->num_planes = fmt->colplanes;
-       pix_mp->pixelformat = fmt->fourcc;
-
-       /*
-        * use MXC_JPEG_H_ALIGN instead of fmt->v_align, for vertical
-        * alignment, to loosen up the alignment to multiple of 8,
-        * otherwise NV12-1080p fails as 1080 is not a multiple of 16
-        */
-       v4l_bound_align_image(&w,
-                             MXC_JPEG_MIN_WIDTH,
-                             w, /* adjust downwards*/
-                             fmt->h_align,
-                             &h,
-                             MXC_JPEG_MIN_HEIGHT,
-                             h, /* adjust downwards*/
-                             MXC_JPEG_H_ALIGN,
-                             0);
-       pix_mp->width = w; /* negotiate the width */
-       pix_mp->height = h; /* negotiate the height */
-
-       /* get user input into the tmp_q */
-       tmp_q.w = w;
-       tmp_q.h = h;
-       tmp_q.fmt = fmt;
-       for (i = 0; i < pix_mp->num_planes; i++) {
-               pfmt = &pix_mp->plane_fmt[i];
-               tmp_q.bytesperline[i] = pfmt->bytesperline;
-               tmp_q.sizeimage[i] = pfmt->sizeimage;
-       }
-
-       /* calculate bytesperline & sizeimage into the tmp_q */
-       mxc_jpeg_bytesperline(&tmp_q, 8);
-       mxc_jpeg_sizeimage(&tmp_q);
-
-       /* adjust user format according to our calculations */
-       for (i = 0; i < pix_mp->num_planes; i++) {
-               pfmt = &pix_mp->plane_fmt[i];
-               memset(pfmt->reserved, 0, sizeof(pfmt->reserved));
-               pfmt->bytesperline = tmp_q.bytesperline[i];
-               pfmt->sizeimage = tmp_q.sizeimage[i];
-       }
-
-       /* fix colorspace information to sRGB for both output & capture */
-       pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
-       pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_601;
-       pix_mp->xfer_func = V4L2_XFER_FUNC_SRGB;
-       /*
-        * this hardware does not change the range of the samples
-        * but since inside JPEG the YUV quantization is full-range,
-        * this driver will always use full-range for the raw frames, too
-        */
-       pix_mp->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-
-       return 0;
-}
-
-static int mxc_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
-                                   struct v4l2_format *f)
-{
-       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
-       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
-       struct device *dev = jpeg->dev;
-       const struct mxc_jpeg_fmt *fmt;
-       u32 fourcc = f->fmt.pix_mp.pixelformat;
-
-       int q_type = (jpeg->mode == MXC_JPEG_DECODE) ?
-                    MXC_JPEG_FMT_TYPE_RAW : MXC_JPEG_FMT_TYPE_ENC;
-
-       if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
-               dev_err(dev, "TRY_FMT with Invalid type: %d\n", f->type);
-               return -EINVAL;
-       }
-
-       fmt = mxc_jpeg_find_format(ctx, fourcc);
-       if (!fmt || fmt->flags != q_type) {
-               dev_warn(dev, "Format not supported: %c%c%c%c, use the default.\n",
-                        (fourcc & 0xff),
-                        (fourcc >>  8) & 0xff,
-                        (fourcc >> 16) & 0xff,
-                        (fourcc >> 24) & 0xff);
-               f->fmt.pix_mp.pixelformat = (jpeg->mode == MXC_JPEG_DECODE) ?
-                               MXC_JPEG_DEFAULT_PFMT : V4L2_PIX_FMT_JPEG;
-               fmt = mxc_jpeg_find_format(ctx, f->fmt.pix_mp.pixelformat);
-       }
-       return mxc_jpeg_try_fmt(f, fmt, ctx, q_type);
-}
-
-static int mxc_jpeg_try_fmt_vid_out(struct file *file, void *priv,
-                                   struct v4l2_format *f)
-{
-       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
-       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
-       struct device *dev = jpeg->dev;
-       const struct mxc_jpeg_fmt *fmt;
-       u32 fourcc = f->fmt.pix_mp.pixelformat;
-
-       int q_type = (jpeg->mode == MXC_JPEG_ENCODE) ?
-                    MXC_JPEG_FMT_TYPE_RAW : MXC_JPEG_FMT_TYPE_ENC;
-
-       if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
-               dev_err(dev, "TRY_FMT with Invalid type: %d\n", f->type);
-               return -EINVAL;
-       }
-
-       fmt = mxc_jpeg_find_format(ctx, fourcc);
-       if (!fmt || fmt->flags != q_type) {
-               dev_warn(dev, "Format not supported: %c%c%c%c, use the default.\n",
-                        (fourcc & 0xff),
-                        (fourcc >>  8) & 0xff,
-                        (fourcc >> 16) & 0xff,
-                        (fourcc >> 24) & 0xff);
-               f->fmt.pix_mp.pixelformat = (jpeg->mode == MXC_JPEG_ENCODE) ?
-                               MXC_JPEG_DEFAULT_PFMT : V4L2_PIX_FMT_JPEG;
-               fmt = mxc_jpeg_find_format(ctx, f->fmt.pix_mp.pixelformat);
-       }
-       return mxc_jpeg_try_fmt(f, fmt, ctx, q_type);
-}
-
-static int mxc_jpeg_s_fmt(struct mxc_jpeg_ctx *ctx,
-                         struct v4l2_format *f)
-{
-       struct vb2_queue *vq;
-       struct mxc_jpeg_q_data *q_data = NULL;
-       struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
-       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
-       int i;
-
-       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-       if (!vq)
-               return -EINVAL;
-
-       q_data = mxc_jpeg_get_q_data(ctx, f->type);
-
-       if (vb2_is_busy(vq)) {
-               v4l2_err(&jpeg->v4l2_dev, "queue busy\n");
-               return -EBUSY;
-       }
-
-       q_data->fmt = mxc_jpeg_find_format(ctx, pix_mp->pixelformat);
-       q_data->w = pix_mp->width;
-       q_data->h = pix_mp->height;
-
-       q_data->w_adjusted = q_data->w;
-       q_data->h_adjusted = q_data->h;
-       if (jpeg->mode == MXC_JPEG_DECODE) {
-               /*
-                * align up the resolution for CAST IP,
-                * but leave the buffer resolution unchanged
-                */
-               v4l_bound_align_image(&q_data->w_adjusted,
-                                     q_data->w_adjusted,  /* adjust upwards */
-                                     MXC_JPEG_MAX_WIDTH,
-                                     q_data->fmt->h_align,
-                                     &q_data->h_adjusted,
-                                     q_data->h_adjusted, /* adjust upwards */
-                                     MXC_JPEG_MAX_HEIGHT,
-                                     q_data->fmt->v_align,
-                                     0);
-       } else {
-               /*
-                * align down the resolution for CAST IP,
-                * but leave the buffer resolution unchanged
-                */
-               v4l_bound_align_image(&q_data->w_adjusted,
-                                     MXC_JPEG_MIN_WIDTH,
-                                     q_data->w_adjusted, /* adjust downwards*/
-                                     q_data->fmt->h_align,
-                                     &q_data->h_adjusted,
-                                     MXC_JPEG_MIN_HEIGHT,
-                                     q_data->h_adjusted, /* adjust downwards*/
-                                     q_data->fmt->v_align,
-                                     0);
-       }
-
-       for (i = 0; i < pix_mp->num_planes; i++) {
-               q_data->bytesperline[i] = pix_mp->plane_fmt[i].bytesperline;
-               q_data->sizeimage[i] = pix_mp->plane_fmt[i].sizeimage;
-       }
-
-       return 0;
-}
-
-static int mxc_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
-                                 struct v4l2_format *f)
-{
-       int ret;
-
-       ret = mxc_jpeg_try_fmt_vid_cap(file, priv, f);
-       if (ret)
-               return ret;
-
-       return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
-}
-
-static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv,
-                                 struct v4l2_format *f)
-{
-       int ret;
-
-       ret = mxc_jpeg_try_fmt_vid_out(file, priv, f);
-       if (ret)
-               return ret;
-
-       return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
-}
-
-static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv,
-                             struct v4l2_format *f)
-{
-       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
-       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
-       struct device *dev = jpeg->dev;
-       struct v4l2_pix_format_mplane   *pix_mp = &f->fmt.pix_mp;
-       struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, f->type);
-       int i;
-
-       if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
-               dev_err(dev, "G_FMT with Invalid type: %d\n", f->type);
-               return -EINVAL;
-       }
-
-       pix_mp->pixelformat = q_data->fmt->fourcc;
-       pix_mp->width = q_data->w;
-       pix_mp->height = q_data->h;
-       pix_mp->field = V4L2_FIELD_NONE;
-
-       /* fix colorspace information to sRGB for both output & capture */
-       pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
-       pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_601;
-       pix_mp->xfer_func = V4L2_XFER_FUNC_SRGB;
-       pix_mp->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-
-       pix_mp->num_planes = q_data->fmt->colplanes;
-       for (i = 0; i < pix_mp->num_planes; i++) {
-               pix_mp->plane_fmt[i].bytesperline = q_data->bytesperline[i];
-               pix_mp->plane_fmt[i].sizeimage = q_data->sizeimage[i];
-       }
-
-       return 0;
-}
-
-static int mxc_jpeg_subscribe_event(struct v4l2_fh *fh,
-                                   const struct v4l2_event_subscription *sub)
-{
-       switch (sub->type) {
-       case V4L2_EVENT_EOS:
-               return v4l2_event_subscribe(fh, sub, 0, NULL);
-       case V4L2_EVENT_SOURCE_CHANGE:
-               return v4l2_src_change_event_subscribe(fh, sub);
-       default:
-               return -EINVAL;
-       }
-}
-
-static int mxc_jpeg_dqbuf(struct file *file, void *priv,
-                         struct v4l2_buffer *buf)
-{
-       struct v4l2_fh *fh = file->private_data;
-       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
-       struct device *dev = ctx->mxc_jpeg->dev;
-       int num_src_ready = v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx);
-       int ret;
-
-       dev_dbg(dev, "DQBUF type=%d, index=%d", buf->type, buf->index);
-       if (ctx->stopping == 1 && num_src_ready == 0) {
-               /* No more src bufs, notify app EOS */
-               notify_eos(ctx);
-               ctx->stopping = 0;
-               mxc_jpeg_set_last_buffer_dequeued(ctx);
-       }
-
-       ret = v4l2_m2m_dqbuf(file, fh->m2m_ctx, buf);
-       return ret;
-}
-
-static const struct v4l2_ioctl_ops mxc_jpeg_ioctl_ops = {
-       .vidioc_querycap                = mxc_jpeg_querycap,
-       .vidioc_enum_fmt_vid_cap        = mxc_jpeg_enum_fmt_vid_cap,
-       .vidioc_enum_fmt_vid_out        = mxc_jpeg_enum_fmt_vid_out,
-
-       .vidioc_try_fmt_vid_cap_mplane  = mxc_jpeg_try_fmt_vid_cap,
-       .vidioc_try_fmt_vid_out_mplane  = mxc_jpeg_try_fmt_vid_out,
-
-       .vidioc_s_fmt_vid_cap_mplane    = mxc_jpeg_s_fmt_vid_cap,
-       .vidioc_s_fmt_vid_out_mplane    = mxc_jpeg_s_fmt_vid_out,
-
-       .vidioc_g_fmt_vid_cap_mplane    = mxc_jpeg_g_fmt_vid,
-       .vidioc_g_fmt_vid_out_mplane    = mxc_jpeg_g_fmt_vid,
-
-       .vidioc_subscribe_event         = mxc_jpeg_subscribe_event,
-       .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
-
-       .vidioc_try_decoder_cmd         = v4l2_m2m_ioctl_try_decoder_cmd,
-       .vidioc_decoder_cmd             = mxc_jpeg_decoder_cmd,
-       .vidioc_try_encoder_cmd         = v4l2_m2m_ioctl_try_encoder_cmd,
-       .vidioc_encoder_cmd             = mxc_jpeg_encoder_cmd,
-
-       .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
-       .vidioc_dqbuf                   = mxc_jpeg_dqbuf,
-
-       .vidioc_create_bufs             = v4l2_m2m_ioctl_create_bufs,
-       .vidioc_prepare_buf             = v4l2_m2m_ioctl_prepare_buf,
-       .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
-       .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
-       .vidioc_expbuf                  = v4l2_m2m_ioctl_expbuf,
-       .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
-       .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
-};
-
-static int mxc_jpeg_release(struct file *file)
-{
-       struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file);
-       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(file->private_data);
-       struct device *dev = mxc_jpeg->dev;
-
-       mutex_lock(&mxc_jpeg->lock);
-       if (mxc_jpeg->mode == MXC_JPEG_DECODE)
-               dev_dbg(dev, "Release JPEG decoder instance on slot %d.",
-                       ctx->slot);
-       else
-               dev_dbg(dev, "Release JPEG encoder instance on slot %d.",
-                       ctx->slot);
-       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
-       v4l2_fh_del(&ctx->fh);
-       v4l2_fh_exit(&ctx->fh);
-       kfree(ctx);
-       mutex_unlock(&mxc_jpeg->lock);
-
-       return 0;
-}
-
-static const struct v4l2_file_operations mxc_jpeg_fops = {
-       .owner          = THIS_MODULE,
-       .open           = mxc_jpeg_open,
-       .release        = mxc_jpeg_release,
-       .poll           = v4l2_m2m_fop_poll,
-       .unlocked_ioctl = video_ioctl2,
-       .mmap           = v4l2_m2m_fop_mmap,
-};
-
-static const struct v4l2_m2m_ops mxc_jpeg_m2m_ops = {
-       .device_run     = mxc_jpeg_device_run,
-};
-
-static void mxc_jpeg_detach_pm_domains(struct mxc_jpeg_dev *jpeg)
-{
-       int i;
-
-       for (i = 0; i < jpeg->num_domains; i++) {
-               if (jpeg->pd_link[i] && !IS_ERR(jpeg->pd_link[i]))
-                       device_link_del(jpeg->pd_link[i]);
-               if (jpeg->pd_dev[i] && !IS_ERR(jpeg->pd_dev[i]))
-                       dev_pm_domain_detach(jpeg->pd_dev[i], true);
-               jpeg->pd_dev[i] = NULL;
-               jpeg->pd_link[i] = NULL;
-       }
-}
-
-static int mxc_jpeg_attach_pm_domains(struct mxc_jpeg_dev *jpeg)
-{
-       struct device *dev = jpeg->dev;
-       struct device_node *np = jpeg->pdev->dev.of_node;
-       int i;
-       int ret;
-
-       jpeg->num_domains = of_count_phandle_with_args(np, "power-domains",
-                                                      "#power-domain-cells");
-       if (jpeg->num_domains < 0) {
-               dev_err(dev, "No power domains defined for jpeg node\n");
-               return jpeg->num_domains;
-       }
-
-       jpeg->pd_dev = devm_kmalloc_array(dev, jpeg->num_domains,
-                                         sizeof(*jpeg->pd_dev), GFP_KERNEL);
-       if (!jpeg->pd_dev)
-               return -ENOMEM;
-
-       jpeg->pd_link = devm_kmalloc_array(dev, jpeg->num_domains,
-                                          sizeof(*jpeg->pd_link), GFP_KERNEL);
-       if (!jpeg->pd_link)
-               return -ENOMEM;
-
-       for (i = 0; i < jpeg->num_domains; i++) {
-               jpeg->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
-               if (IS_ERR(jpeg->pd_dev[i])) {
-                       ret = PTR_ERR(jpeg->pd_dev[i]);
-                       goto fail;
-               }
-
-               jpeg->pd_link[i] = device_link_add(dev, jpeg->pd_dev[i],
-                                                  DL_FLAG_STATELESS |
-                                                  DL_FLAG_PM_RUNTIME);
-               if (!jpeg->pd_link[i]) {
-                       ret = -EINVAL;
-                       goto fail;
-               }
-       }
-
-       return 0;
-fail:
-       mxc_jpeg_detach_pm_domains(jpeg);
-       return ret;
-}
-
-static int mxc_jpeg_probe(struct platform_device *pdev)
-{
-       struct mxc_jpeg_dev *jpeg;
-       struct device *dev = &pdev->dev;
-       int dec_irq;
-       int ret;
-       int mode;
-       const struct of_device_id *of_id;
-       unsigned int slot;
-
-       of_id = of_match_node(mxc_jpeg_match, dev->of_node);
-       mode = *(const int *)of_id->data;
-
-       jpeg = devm_kzalloc(dev, sizeof(struct mxc_jpeg_dev), GFP_KERNEL);
-       if (!jpeg)
-               return -ENOMEM;
-
-       mutex_init(&jpeg->lock);
-       spin_lock_init(&jpeg->hw_lock);
-
-       ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
-       if (ret) {
-               dev_err(&pdev->dev, "No suitable DMA available.\n");
-               goto err_irq;
-       }
-
-       jpeg->base_reg = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(jpeg->base_reg))
-               return PTR_ERR(jpeg->base_reg);
-
-       for (slot = 0; slot < MXC_MAX_SLOTS; slot++) {
-               dec_irq = platform_get_irq(pdev, slot);
-               if (dec_irq < 0) {
-                       ret = dec_irq;
-                       goto err_irq;
-               }
-               ret = devm_request_irq(&pdev->dev, dec_irq, mxc_jpeg_dec_irq,
-                                      0, pdev->name, jpeg);
-               if (ret) {
-                       dev_err(&pdev->dev, "Failed to request irq %d (%d)\n",
-                               dec_irq, ret);
-                       goto err_irq;
-               }
-       }
-
-       jpeg->pdev = pdev;
-       jpeg->dev = dev;
-       jpeg->mode = mode;
-
-       /* Get clocks */
-       jpeg->clk_ipg = devm_clk_get(dev, "ipg");
-       if (IS_ERR(jpeg->clk_ipg)) {
-               dev_err(dev, "failed to get clock: ipg\n");
-               goto err_clk;
-       }
-
-       jpeg->clk_per = devm_clk_get(dev, "per");
-       if (IS_ERR(jpeg->clk_per)) {
-               dev_err(dev, "failed to get clock: per\n");
-               goto err_clk;
-       }
-
-       ret = mxc_jpeg_attach_pm_domains(jpeg);
-       if (ret < 0) {
-               dev_err(dev, "failed to attach power domains %d\n", ret);
-               return ret;
-       }
-
-       /* v4l2 */
-       ret = v4l2_device_register(dev, &jpeg->v4l2_dev);
-       if (ret) {
-               dev_err(dev, "failed to register v4l2 device\n");
-               goto err_register;
-       }
-       jpeg->m2m_dev = v4l2_m2m_init(&mxc_jpeg_m2m_ops);
-       if (IS_ERR(jpeg->m2m_dev)) {
-               dev_err(dev, "failed to register v4l2 device\n");
-               ret = PTR_ERR(jpeg->m2m_dev);
-               goto err_m2m;
-       }
-
-       jpeg->dec_vdev = video_device_alloc();
-       if (!jpeg->dec_vdev) {
-               dev_err(dev, "failed to register v4l2 device\n");
-               ret = -ENOMEM;
-               goto err_vdev_alloc;
-       }
-       if (mode == MXC_JPEG_ENCODE)
-               snprintf(jpeg->dec_vdev->name,
-                        sizeof(jpeg->dec_vdev->name),
-                        "%s-enc", MXC_JPEG_NAME);
-       else
-               snprintf(jpeg->dec_vdev->name,
-                        sizeof(jpeg->dec_vdev->name),
-                        "%s-dec", MXC_JPEG_NAME);
-
-       jpeg->dec_vdev->fops = &mxc_jpeg_fops;
-       jpeg->dec_vdev->ioctl_ops = &mxc_jpeg_ioctl_ops;
-       jpeg->dec_vdev->minor = -1;
-       jpeg->dec_vdev->release = video_device_release;
-       jpeg->dec_vdev->lock = &jpeg->lock; /* lock for ioctl serialization */
-       jpeg->dec_vdev->v4l2_dev = &jpeg->v4l2_dev;
-       jpeg->dec_vdev->vfl_dir = VFL_DIR_M2M;
-       jpeg->dec_vdev->device_caps = V4L2_CAP_STREAMING |
-                                       V4L2_CAP_VIDEO_M2M_MPLANE;
-       if (mode == MXC_JPEG_ENCODE) {
-               v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_DECODER_CMD);
-               v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_TRY_DECODER_CMD);
-       } else {
-               v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_ENCODER_CMD);
-               v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_TRY_ENCODER_CMD);
-       }
-       ret = video_register_device(jpeg->dec_vdev, VFL_TYPE_VIDEO, -1);
-       if (ret) {
-               dev_err(dev, "failed to register video device\n");
-               goto err_vdev_register;
-       }
-       video_set_drvdata(jpeg->dec_vdev, jpeg);
-       if (mode == MXC_JPEG_ENCODE)
-               v4l2_info(&jpeg->v4l2_dev,
-                         "encoder device registered as /dev/video%d (%d,%d)\n",
-                         jpeg->dec_vdev->num, VIDEO_MAJOR,
-                         jpeg->dec_vdev->minor);
-       else
-               v4l2_info(&jpeg->v4l2_dev,
-                         "decoder device registered as /dev/video%d (%d,%d)\n",
-                         jpeg->dec_vdev->num, VIDEO_MAJOR,
-                         jpeg->dec_vdev->minor);
-
-       platform_set_drvdata(pdev, jpeg);
-       pm_runtime_enable(dev);
-
-       return 0;
-
-err_vdev_register:
-       video_device_release(jpeg->dec_vdev);
-
-err_vdev_alloc:
-       v4l2_m2m_release(jpeg->m2m_dev);
-
-err_m2m:
-       v4l2_device_unregister(&jpeg->v4l2_dev);
-
-err_register:
-       mxc_jpeg_detach_pm_domains(jpeg);
-
-err_irq:
-err_clk:
-       return ret;
-}
-
-#ifdef CONFIG_PM
-static int mxc_jpeg_runtime_resume(struct device *dev)
-{
-       struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);
-       int ret;
-
-       ret = clk_prepare_enable(jpeg->clk_ipg);
-       if (ret < 0) {
-               dev_err(dev, "failed to enable clock: ipg\n");
-               goto err_ipg;
-       }
-
-       ret = clk_prepare_enable(jpeg->clk_per);
-       if (ret < 0) {
-               dev_err(dev, "failed to enable clock: per\n");
-               goto err_per;
-       }
-
-       return 0;
-
-err_per:
-       clk_disable_unprepare(jpeg->clk_ipg);
-err_ipg:
-       return ret;
-}
-
-static int mxc_jpeg_runtime_suspend(struct device *dev)
-{
-       struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);
-
-       clk_disable_unprepare(jpeg->clk_ipg);
-       clk_disable_unprepare(jpeg->clk_per);
-
-       return 0;
-}
-#endif
-
-static const struct dev_pm_ops mxc_jpeg_pm_ops = {
-       SET_RUNTIME_PM_OPS(mxc_jpeg_runtime_suspend,
-                          mxc_jpeg_runtime_resume, NULL)
-};
-
-static int mxc_jpeg_remove(struct platform_device *pdev)
-{
-       unsigned int slot;
-       struct mxc_jpeg_dev *jpeg = platform_get_drvdata(pdev);
-
-       for (slot = 0; slot < MXC_MAX_SLOTS; slot++)
-               mxc_jpeg_free_slot_data(jpeg, slot);
-
-       pm_runtime_disable(&pdev->dev);
-       video_unregister_device(jpeg->dec_vdev);
-       v4l2_m2m_release(jpeg->m2m_dev);
-       v4l2_device_unregister(&jpeg->v4l2_dev);
-       mxc_jpeg_detach_pm_domains(jpeg);
-
-       return 0;
-}
-
-MODULE_DEVICE_TABLE(of, mxc_jpeg_match);
-
-static struct platform_driver mxc_jpeg_driver = {
-       .probe = mxc_jpeg_probe,
-       .remove = mxc_jpeg_remove,
-       .driver = {
-               .name = "mxc-jpeg",
-               .of_match_table = mxc_jpeg_match,
-               .pm = &mxc_jpeg_pm_ops,
-       },
-};
-module_platform_driver(mxc_jpeg_driver);
-
-MODULE_AUTHOR("Zhengyu Shen <zhengyu.shen_1@nxp.com>");
-MODULE_AUTHOR("Mirela Rabulea <mirela.rabulea@nxp.com>");
-MODULE_DESCRIPTION("V4L2 driver for i.MX8 QXP/QM JPEG encoder/decoder");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/imx-jpeg/mxc-jpeg.h
deleted file mode 100644 (file)
index f53f004..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * i.MX8QXP/i.MX8QM JPEG encoder/decoder v4l2 driver
- *
- * Copyright 2018-2019 NXP
- */
-
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-fh.h>
-
-#ifndef _MXC_JPEG_CORE_H
-#define _MXC_JPEG_CORE_H
-
-#define MXC_JPEG_NAME                  "mxc-jpeg"
-#define MXC_JPEG_FMT_TYPE_ENC          0
-#define MXC_JPEG_FMT_TYPE_RAW          1
-#define MXC_JPEG_DEFAULT_WIDTH         1280
-#define MXC_JPEG_DEFAULT_HEIGHT                720
-#define MXC_JPEG_DEFAULT_PFMT          V4L2_PIX_FMT_RGB24
-#define MXC_JPEG_MIN_WIDTH             64
-#define MXC_JPEG_MIN_HEIGHT            64
-#define MXC_JPEG_MAX_WIDTH             0x2000
-#define MXC_JPEG_MAX_HEIGHT            0x2000
-#define MXC_JPEG_MAX_CFG_STREAM                0x1000
-#define MXC_JPEG_H_ALIGN               3
-#define MXC_JPEG_W_ALIGN               3
-#define MXC_JPEG_MAX_SIZEIMAGE         0xFFFFFC00
-#define MXC_JPEG_MAX_PLANES            2
-
-enum mxc_jpeg_enc_state {
-       MXC_JPEG_ENCODING       = 0, /* jpeg encode phase */
-       MXC_JPEG_ENC_CONF       = 1, /* jpeg encoder config phase */
-};
-
-enum mxc_jpeg_mode {
-       MXC_JPEG_DECODE = 0, /* jpeg decode mode */
-       MXC_JPEG_ENCODE = 1, /* jpeg encode mode */
-};
-
-/**
- * struct mxc_jpeg_fmt - driver's internal color format data
- * @name:      format description
- * @fourcc:    fourcc code, 0 if not applicable
- * @subsampling: subsampling of jpeg components
- * @nc:                number of color components
- * @depth:     number of bits per pixel
- * @colplanes: number of color planes (1 for packed formats)
- * @h_align:   horizontal alignment order (align to 2^h_align)
- * @v_align:   vertical alignment order (align to 2^v_align)
- * @flags:     flags describing format applicability
- */
-struct mxc_jpeg_fmt {
-       const char                              *name;
-       u32                                     fourcc;
-       enum v4l2_jpeg_chroma_subsampling       subsampling;
-       int                                     nc;
-       int                                     depth;
-       int                                     colplanes;
-       int                                     h_align;
-       int                                     v_align;
-       u32                                     flags;
-};
-
-struct mxc_jpeg_desc {
-       u32 next_descpt_ptr;
-       u32 buf_base0;
-       u32 buf_base1;
-       u32 line_pitch;
-       u32 stm_bufbase;
-       u32 stm_bufsize;
-       u32 imgsize;
-       u32 stm_ctrl;
-} __packed;
-
-struct mxc_jpeg_q_data {
-       const struct mxc_jpeg_fmt       *fmt;
-       u32                             sizeimage[MXC_JPEG_MAX_PLANES];
-       u32                             bytesperline[MXC_JPEG_MAX_PLANES];
-       int                             w;
-       int                             w_adjusted;
-       int                             h;
-       int                             h_adjusted;
-       unsigned int                    sequence;
-};
-
-struct mxc_jpeg_ctx {
-       struct mxc_jpeg_dev             *mxc_jpeg;
-       struct mxc_jpeg_q_data          out_q;
-       struct mxc_jpeg_q_data          cap_q;
-       struct v4l2_fh                  fh;
-       enum mxc_jpeg_enc_state         enc_state;
-       unsigned int                    stopping;
-       unsigned int                    stopped;
-       unsigned int                    slot;
-};
-
-struct mxc_jpeg_slot_data {
-       bool used;
-       struct mxc_jpeg_desc *desc; // enc/dec descriptor
-       struct mxc_jpeg_desc *cfg_desc; // configuration descriptor
-       void *cfg_stream_vaddr; // configuration bitstream virtual address
-       unsigned int cfg_stream_size;
-       dma_addr_t desc_handle;
-       dma_addr_t cfg_desc_handle; // configuration descriptor dma address
-       dma_addr_t cfg_stream_handle; // configuration bitstream dma address
-};
-
-struct mxc_jpeg_dev {
-       spinlock_t                      hw_lock; /* hardware access lock */
-       unsigned int                    mode;
-       struct mutex                    lock; /* v4l2 ioctls serialization */
-       struct clk                      *clk_ipg;
-       struct clk                      *clk_per;
-       struct platform_device          *pdev;
-       struct device                   *dev;
-       void __iomem                    *base_reg;
-       struct v4l2_device              v4l2_dev;
-       struct v4l2_m2m_dev             *m2m_dev;
-       struct video_device             *dec_vdev;
-       struct mxc_jpeg_slot_data       slot_data[MXC_MAX_SLOTS];
-       int                             num_domains;
-       struct device                   **pd_dev;
-       struct device_link              **pd_link;
-};
-
-/**
- * struct mxc_jpeg_sof_comp - JPEG Start Of Frame component fields
- * @id:                                component id
- * @v:                         vertical sampling
- * @h:                         horizontal sampling
- * @quantization_table_no:     id of quantization table
- */
-struct mxc_jpeg_sof_comp {
-       u8 id;
-       u8 v :4;
-       u8 h :4;
-       u8 quantization_table_no;
-} __packed;
-
-#define MXC_JPEG_MAX_COMPONENTS 4
-/**
- * struct mxc_jpeg_sof - JPEG Start Of Frame marker fields
- * @length:            Start of Frame length
- * @precision:         precision (bits per pixel per color component)
- * @height:            image height
- * @width:             image width
- * @components_no:     number of color components
- * @comp:              component fields for each color component
- */
-struct mxc_jpeg_sof {
-       u16 length;
-       u8 precision;
-       u16 height, width;
-       u8 components_no;
-       struct mxc_jpeg_sof_comp comp[MXC_JPEG_MAX_COMPONENTS];
-} __packed;
-
-/**
- * struct mxc_jpeg_sos_comp - JPEG Start Of Scan component fields
- * @id:                        component id
- * @huffman_table_no:  id of the Huffman table
- */
-struct mxc_jpeg_sos_comp {
-       u8 id; /*component id*/
-       u8 huffman_table_no;
-} __packed;
-
-/**
- * struct mxc_jpeg_sos - JPEG Start Of Scan marker fields
- * @length:            Start of Frame length
- * @components_no:     number of color components
- * @comp:              SOS component fields for each color component
- * @ignorable_bytes:   ignorable bytes
- */
-struct mxc_jpeg_sos {
-       u16 length;
-       u8 components_no;
-       struct mxc_jpeg_sos_comp comp[MXC_JPEG_MAX_COMPONENTS];
-       u8 ignorable_bytes[3];
-} __packed;
-
-#endif
diff --git a/drivers/media/platform/imx-pxp.c b/drivers/media/platform/imx-pxp.c
deleted file mode 100644 (file)
index 689ae5e..0000000
+++ /dev/null
@@ -1,1788 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * i.MX Pixel Pipeline (PXP) mem-to-mem scaler/CSC/rotator driver
- *
- * Copyright (c) 2018 Pengutronix, Philipp Zabel
- *
- * based on vim2m
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * Pawel Osciak, <pawel@osciak.com>
- * Marek Szyprowski, <m.szyprowski@samsung.com>
- */
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include <linux/platform_device.h>
-#include <media/v4l2-mem2mem.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-dma-contig.h>
-
-#include "imx-pxp.h"
-
-static unsigned int debug;
-module_param(debug, uint, 0644);
-MODULE_PARM_DESC(debug, "activates debug info");
-
-#define MIN_W 8
-#define MIN_H 8
-#define MAX_W 4096
-#define MAX_H 4096
-#define ALIGN_W 3 /* 8x8 pixel blocks */
-#define ALIGN_H 3
-
-/* Flags that indicate a format can be used for capture/output */
-#define MEM2MEM_CAPTURE        (1 << 0)
-#define MEM2MEM_OUTPUT (1 << 1)
-
-#define MEM2MEM_NAME           "pxp"
-
-/* Flags that indicate processing mode */
-#define MEM2MEM_HFLIP  (1 << 0)
-#define MEM2MEM_VFLIP  (1 << 1)
-
-#define dprintk(dev, fmt, arg...) \
-       v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
-
-struct pxp_fmt {
-       u32     fourcc;
-       int     depth;
-       /* Types the format can be used for */
-       u32     types;
-};
-
-static struct pxp_fmt formats[] = {
-       {
-               .fourcc = V4L2_PIX_FMT_XBGR32,
-               .depth  = 32,
-               /* Both capture and output format */
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_ABGR32,
-               .depth  = 32,
-               /* Capture-only format */
-               .types  = MEM2MEM_CAPTURE,
-       }, {
-               .fourcc = V4L2_PIX_FMT_BGR24,
-               .depth  = 24,
-               .types  = MEM2MEM_CAPTURE,
-       }, {
-               .fourcc = V4L2_PIX_FMT_RGB565,
-               .depth  = 16,
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_RGB555,
-               .depth  = 16,
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_RGB444,
-               .depth  = 16,
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_VUYA32,
-               .depth  = 32,
-               .types  = MEM2MEM_CAPTURE,
-       }, {
-               .fourcc = V4L2_PIX_FMT_VUYX32,
-               .depth  = 32,
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_UYVY,
-               .depth  = 16,
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_YUYV,
-               .depth  = 16,
-               /* Output-only format */
-               .types  = MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_VYUY,
-               .depth  = 16,
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_YVYU,
-               .depth  = 16,
-               .types  = MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_GREY,
-               .depth  = 8,
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_Y4,
-               .depth  = 4,
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_NV16,
-               .depth  = 16,
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_NV12,
-               .depth  = 12,
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_NV21,
-               .depth  = 12,
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_NV61,
-               .depth  = 16,
-               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_YUV422P,
-               .depth  = 16,
-               .types  = MEM2MEM_OUTPUT,
-       }, {
-               .fourcc = V4L2_PIX_FMT_YUV420,
-               .depth  = 12,
-               .types  = MEM2MEM_OUTPUT,
-       },
-};
-
-#define NUM_FORMATS ARRAY_SIZE(formats)
-
-/* Per-queue, driver-specific private data */
-struct pxp_q_data {
-       unsigned int            width;
-       unsigned int            height;
-       unsigned int            bytesperline;
-       unsigned int            sizeimage;
-       unsigned int            sequence;
-       struct pxp_fmt          *fmt;
-       enum v4l2_ycbcr_encoding ycbcr_enc;
-       enum v4l2_quantization  quant;
-};
-
-enum {
-       V4L2_M2M_SRC = 0,
-       V4L2_M2M_DST = 1,
-};
-
-static struct pxp_fmt *find_format(struct v4l2_format *f)
-{
-       struct pxp_fmt *fmt;
-       unsigned int k;
-
-       for (k = 0; k < NUM_FORMATS; k++) {
-               fmt = &formats[k];
-               if (fmt->fourcc == f->fmt.pix.pixelformat)
-                       break;
-       }
-
-       if (k == NUM_FORMATS)
-               return NULL;
-
-       return &formats[k];
-}
-
-struct pxp_dev {
-       struct v4l2_device      v4l2_dev;
-       struct video_device     vfd;
-
-       struct clk              *clk;
-       void __iomem            *mmio;
-
-       atomic_t                num_inst;
-       struct mutex            dev_mutex;
-       spinlock_t              irqlock;
-
-       struct v4l2_m2m_dev     *m2m_dev;
-};
-
-struct pxp_ctx {
-       struct v4l2_fh          fh;
-       struct pxp_dev  *dev;
-
-       struct v4l2_ctrl_handler hdl;
-
-       /* Abort requested by m2m */
-       int                     aborting;
-
-       /* Processing mode */
-       int                     mode;
-       u8                      alpha_component;
-       u8                      rotation;
-
-       enum v4l2_colorspace    colorspace;
-       enum v4l2_xfer_func     xfer_func;
-
-       /* Source and destination queue data */
-       struct pxp_q_data   q_data[2];
-};
-
-static inline struct pxp_ctx *file2ctx(struct file *file)
-{
-       return container_of(file->private_data, struct pxp_ctx, fh);
-}
-
-static struct pxp_q_data *get_q_data(struct pxp_ctx *ctx,
-                                        enum v4l2_buf_type type)
-{
-       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-               return &ctx->q_data[V4L2_M2M_SRC];
-       else
-               return &ctx->q_data[V4L2_M2M_DST];
-}
-
-static u32 pxp_v4l2_pix_fmt_to_ps_format(u32 v4l2_pix_fmt)
-{
-       switch (v4l2_pix_fmt) {
-       case V4L2_PIX_FMT_XBGR32:  return BV_PXP_PS_CTRL_FORMAT__RGB888;
-       case V4L2_PIX_FMT_RGB555:  return BV_PXP_PS_CTRL_FORMAT__RGB555;
-       case V4L2_PIX_FMT_RGB444:  return BV_PXP_PS_CTRL_FORMAT__RGB444;
-       case V4L2_PIX_FMT_RGB565:  return BV_PXP_PS_CTRL_FORMAT__RGB565;
-       case V4L2_PIX_FMT_VUYX32:  return BV_PXP_PS_CTRL_FORMAT__YUV1P444;
-       case V4L2_PIX_FMT_UYVY:    return BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
-       case V4L2_PIX_FMT_YUYV:    return BM_PXP_PS_CTRL_WB_SWAP |
-                                         BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
-       case V4L2_PIX_FMT_VYUY:    return BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
-       case V4L2_PIX_FMT_YVYU:    return BM_PXP_PS_CTRL_WB_SWAP |
-                                         BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
-       case V4L2_PIX_FMT_GREY:    return BV_PXP_PS_CTRL_FORMAT__Y8;
-       default:
-       case V4L2_PIX_FMT_Y4:      return BV_PXP_PS_CTRL_FORMAT__Y4;
-       case V4L2_PIX_FMT_NV16:    return BV_PXP_PS_CTRL_FORMAT__YUV2P422;
-       case V4L2_PIX_FMT_NV12:    return BV_PXP_PS_CTRL_FORMAT__YUV2P420;
-       case V4L2_PIX_FMT_NV21:    return BV_PXP_PS_CTRL_FORMAT__YVU2P420;
-       case V4L2_PIX_FMT_NV61:    return BV_PXP_PS_CTRL_FORMAT__YVU2P422;
-       case V4L2_PIX_FMT_YUV422P: return BV_PXP_PS_CTRL_FORMAT__YUV422;
-       case V4L2_PIX_FMT_YUV420:  return BV_PXP_PS_CTRL_FORMAT__YUV420;
-       }
-}
-
-static u32 pxp_v4l2_pix_fmt_to_out_format(u32 v4l2_pix_fmt)
-{
-       switch (v4l2_pix_fmt) {
-       case V4L2_PIX_FMT_XBGR32:   return BV_PXP_OUT_CTRL_FORMAT__RGB888;
-       case V4L2_PIX_FMT_ABGR32:   return BV_PXP_OUT_CTRL_FORMAT__ARGB8888;
-       case V4L2_PIX_FMT_BGR24:    return BV_PXP_OUT_CTRL_FORMAT__RGB888P;
-       /* Missing V4L2 pixel formats for ARGB1555 and ARGB4444 */
-       case V4L2_PIX_FMT_RGB555:   return BV_PXP_OUT_CTRL_FORMAT__RGB555;
-       case V4L2_PIX_FMT_RGB444:   return BV_PXP_OUT_CTRL_FORMAT__RGB444;
-       case V4L2_PIX_FMT_RGB565:   return BV_PXP_OUT_CTRL_FORMAT__RGB565;
-       case V4L2_PIX_FMT_VUYA32:
-       case V4L2_PIX_FMT_VUYX32:   return BV_PXP_OUT_CTRL_FORMAT__YUV1P444;
-       case V4L2_PIX_FMT_UYVY:     return BV_PXP_OUT_CTRL_FORMAT__UYVY1P422;
-       case V4L2_PIX_FMT_VYUY:     return BV_PXP_OUT_CTRL_FORMAT__VYUY1P422;
-       case V4L2_PIX_FMT_GREY:     return BV_PXP_OUT_CTRL_FORMAT__Y8;
-       default:
-       case V4L2_PIX_FMT_Y4:       return BV_PXP_OUT_CTRL_FORMAT__Y4;
-       case V4L2_PIX_FMT_NV16:     return BV_PXP_OUT_CTRL_FORMAT__YUV2P422;
-       case V4L2_PIX_FMT_NV12:     return BV_PXP_OUT_CTRL_FORMAT__YUV2P420;
-       case V4L2_PIX_FMT_NV61:     return BV_PXP_OUT_CTRL_FORMAT__YVU2P422;
-       case V4L2_PIX_FMT_NV21:     return BV_PXP_OUT_CTRL_FORMAT__YVU2P420;
-       }
-}
-
-static bool pxp_v4l2_pix_fmt_is_yuv(u32 v4l2_pix_fmt)
-{
-       switch (v4l2_pix_fmt) {
-       case V4L2_PIX_FMT_VUYA32:
-       case V4L2_PIX_FMT_VUYX32:
-       case V4L2_PIX_FMT_UYVY:
-       case V4L2_PIX_FMT_YUYV:
-       case V4L2_PIX_FMT_VYUY:
-       case V4L2_PIX_FMT_YVYU:
-       case V4L2_PIX_FMT_NV16:
-       case V4L2_PIX_FMT_NV12:
-       case V4L2_PIX_FMT_NV61:
-       case V4L2_PIX_FMT_NV21:
-       case V4L2_PIX_FMT_YUV420:
-       case V4L2_PIX_FMT_YUV422P:
-       case V4L2_PIX_FMT_GREY:
-       case V4L2_PIX_FMT_Y4:
-               return true;
-       default:
-               return false;
-       }
-}
-
-static void pxp_setup_csc(struct pxp_ctx *ctx)
-{
-       struct pxp_dev *dev = ctx->dev;
-       enum v4l2_ycbcr_encoding ycbcr_enc;
-       enum v4l2_quantization quantization;
-
-       if (pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) &&
-           !pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_DST].fmt->fourcc)) {
-               /*
-                * CSC1 YUV/YCbCr to RGB conversion is implemented as follows:
-                *
-                * |R|   |C0 0  C1|   |Y  + Yoffset |
-                * |G| = |C0 C3 C2| * |Cb + UVoffset|
-                * |B|   |C0 C4 0 |   |Cr + UVoffset|
-                *
-                * Results are clamped to 0..255.
-                *
-                * BT.601 limited range:
-                *
-                * |R|   |1.1644  0.0000  1.5960|   |Y  - 16 |
-                * |G| = |1.1644 -0.3917 -0.8129| * |Cb - 128|
-                * |B|   |1.1644  2.0172  0.0000|   |Cr - 128|
-                */
-               static const u32 csc1_coef_bt601_lim[3] = {
-                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
-                       BF_PXP_CSC1_COEF0_C0(0x12a) |   /*  1.1641 (-0.03 %) */
-                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
-                       BF_PXP_CSC1_COEF0_Y_OFFSET(-16),
-                       BF_PXP_CSC1_COEF1_C1(0x198) |   /*  1.5938 (-0.23 %) */
-                       BF_PXP_CSC1_COEF1_C4(0x204),    /*  2.0156 (-0.16 %) */
-                       BF_PXP_CSC1_COEF2_C2(0x730) |   /* -0.8125 (+0.04 %) */
-                       BF_PXP_CSC1_COEF2_C3(0x79c),    /* -0.3906 (+0.11 %) */
-               };
-               /*
-                * BT.601 full range:
-                *
-                * |R|   |1.0000  0.0000  1.4020|   |Y  + 0  |
-                * |G| = |1.0000 -0.3441 -0.7141| * |Cb - 128|
-                * |B|   |1.0000  1.7720  0.0000|   |Cr - 128|
-                */
-               static const u32 csc1_coef_bt601_full[3] = {
-                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
-                       BF_PXP_CSC1_COEF0_C0(0x100) |   /*  1.0000 (+0.00 %) */
-                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
-                       BF_PXP_CSC1_COEF0_Y_OFFSET(0),
-                       BF_PXP_CSC1_COEF1_C1(0x166) |   /*  1.3984 (-0.36 %) */
-                       BF_PXP_CSC1_COEF1_C4(0x1c5),    /*  1.7695 (-0.25 %) */
-                       BF_PXP_CSC1_COEF2_C2(0x74a) |   /* -0.7109 (+0.32 %) */
-                       BF_PXP_CSC1_COEF2_C3(0x7a8),    /* -0.3438 (+0.04 %) */
-               };
-               /*
-                * Rec.709 limited range:
-                *
-                * |R|   |1.1644  0.0000  1.7927|   |Y  - 16 |
-                * |G| = |1.1644 -0.2132 -0.5329| * |Cb - 128|
-                * |B|   |1.1644  2.1124  0.0000|   |Cr - 128|
-                */
-               static const u32 csc1_coef_rec709_lim[3] = {
-                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
-                       BF_PXP_CSC1_COEF0_C0(0x12a) |   /*  1.1641 (-0.03 %) */
-                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
-                       BF_PXP_CSC1_COEF0_Y_OFFSET(-16),
-                       BF_PXP_CSC1_COEF1_C1(0x1ca) |   /*  1.7891 (-0.37 %) */
-                       BF_PXP_CSC1_COEF1_C4(0x21c),    /*  2.1094 (-0.30 %) */
-                       BF_PXP_CSC1_COEF2_C2(0x778) |   /* -0.5312 (+0.16 %) */
-                       BF_PXP_CSC1_COEF2_C3(0x7ca),    /* -0.2109 (+0.23 %) */
-               };
-               /*
-                * Rec.709 full range:
-                *
-                * |R|   |1.0000  0.0000  1.5748|   |Y  + 0  |
-                * |G| = |1.0000 -0.1873 -0.4681| * |Cb - 128|
-                * |B|   |1.0000  1.8556  0.0000|   |Cr - 128|
-                */
-               static const u32 csc1_coef_rec709_full[3] = {
-                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
-                       BF_PXP_CSC1_COEF0_C0(0x100) |   /*  1.0000 (+0.00 %) */
-                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
-                       BF_PXP_CSC1_COEF0_Y_OFFSET(0),
-                       BF_PXP_CSC1_COEF1_C1(0x193) |   /*  1.5742 (-0.06 %) */
-                       BF_PXP_CSC1_COEF1_C4(0x1db),    /*  1.8555 (-0.01 %) */
-                       BF_PXP_CSC1_COEF2_C2(0x789) |   /* -0.4648 (+0.33 %) */
-                       BF_PXP_CSC1_COEF2_C3(0x7d1),    /* -0.1836 (+0.37 %) */
-               };
-               /*
-                * BT.2020 limited range:
-                *
-                * |R|   |1.1644  0.0000  1.6787|   |Y  - 16 |
-                * |G| = |1.1644 -0.1874 -0.6505| * |Cb - 128|
-                * |B|   |1.1644  2.1418  0.0000|   |Cr - 128|
-                */
-               static const u32 csc1_coef_bt2020_lim[3] = {
-                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
-                       BF_PXP_CSC1_COEF0_C0(0x12a) |   /*  1.1641 (-0.03 %) */
-                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
-                       BF_PXP_CSC1_COEF0_Y_OFFSET(-16),
-                       BF_PXP_CSC1_COEF1_C1(0x1ad) |   /*  1.6758 (-0.29 %) */
-                       BF_PXP_CSC1_COEF1_C4(0x224),    /*  2.1406 (-0.11 %) */
-                       BF_PXP_CSC1_COEF2_C2(0x75a) |   /* -0.6484 (+0.20 %) */
-                       BF_PXP_CSC1_COEF2_C3(0x7d1),    /* -0.1836 (+0.38 %) */
-               };
-               /*
-                * BT.2020 full range:
-                *
-                * |R|   |1.0000  0.0000  1.4746|   |Y  + 0  |
-                * |G| = |1.0000 -0.1646 -0.5714| * |Cb - 128|
-                * |B|   |1.0000  1.8814  0.0000|   |Cr - 128|
-                */
-               static const u32 csc1_coef_bt2020_full[3] = {
-                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
-                       BF_PXP_CSC1_COEF0_C0(0x100) |   /*  1.0000 (+0.00 %) */
-                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
-                       BF_PXP_CSC1_COEF0_Y_OFFSET(0),
-                       BF_PXP_CSC1_COEF1_C1(0x179) |   /*  1.4727 (-0.19 %) */
-                       BF_PXP_CSC1_COEF1_C4(0x1e1),    /*  1.8789 (-0.25 %) */
-                       BF_PXP_CSC1_COEF2_C2(0x76e) |   /* -0.5703 (+0.11 %) */
-                       BF_PXP_CSC1_COEF2_C3(0x7d6),    /* -0.1641 (+0.05 %) */
-               };
-               /*
-                * SMPTE 240m limited range:
-                *
-                * |R|   |1.1644  0.0000  1.7937|   |Y  - 16 |
-                * |G| = |1.1644 -0.2565 -0.5427| * |Cb - 128|
-                * |B|   |1.1644  2.0798  0.0000|   |Cr - 128|
-                */
-               static const u32 csc1_coef_smpte240m_lim[3] = {
-                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
-                       BF_PXP_CSC1_COEF0_C0(0x12a) |   /*  1.1641 (-0.03 %) */
-                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
-                       BF_PXP_CSC1_COEF0_Y_OFFSET(-16),
-                       BF_PXP_CSC1_COEF1_C1(0x1cb) |   /*  1.7930 (-0.07 %) */
-                       BF_PXP_CSC1_COEF1_C4(0x214),    /*  2.0781 (-0.17 %) */
-                       BF_PXP_CSC1_COEF2_C2(0x776) |   /* -0.5391 (+0.36 %) */
-                       BF_PXP_CSC1_COEF2_C3(0x7bf),    /* -0.2539 (+0.26 %) */
-               };
-               /*
-                * SMPTE 240m full range:
-                *
-                * |R|   |1.0000  0.0000  1.5756|   |Y  + 0  |
-                * |G| = |1.0000 -0.2253 -0.4767| * |Cb - 128|
-                * |B|   |1.0000  1.8270  0.0000|   |Cr - 128|
-                */
-               static const u32 csc1_coef_smpte240m_full[3] = {
-                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
-                       BF_PXP_CSC1_COEF0_C0(0x100) |   /*  1.0000 (+0.00 %) */
-                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
-                       BF_PXP_CSC1_COEF0_Y_OFFSET(0),
-                       BF_PXP_CSC1_COEF1_C1(0x193) |   /*  1.5742 (-0.14 %) */
-                       BF_PXP_CSC1_COEF1_C4(0x1d3),    /*  1.8242 (-0.28 %) */
-                       BF_PXP_CSC1_COEF2_C2(0x786) |   /* -0.4766 (+0.01 %) */
-                       BF_PXP_CSC1_COEF2_C3(0x7c7),    /* -0.2227 (+0.26 %) */
-               };
-               const u32 *csc1_coef;
-
-               ycbcr_enc = ctx->q_data[V4L2_M2M_SRC].ycbcr_enc;
-               quantization = ctx->q_data[V4L2_M2M_SRC].quant;
-
-               if (ycbcr_enc == V4L2_YCBCR_ENC_601) {
-                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
-                               csc1_coef = csc1_coef_bt601_full;
-                       else
-                               csc1_coef = csc1_coef_bt601_lim;
-               } else if (ycbcr_enc == V4L2_YCBCR_ENC_709) {
-                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
-                               csc1_coef = csc1_coef_rec709_full;
-                       else
-                               csc1_coef = csc1_coef_rec709_lim;
-               } else if (ycbcr_enc == V4L2_YCBCR_ENC_BT2020) {
-                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
-                               csc1_coef = csc1_coef_bt2020_full;
-                       else
-                               csc1_coef = csc1_coef_bt2020_lim;
-               } else {
-                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
-                               csc1_coef = csc1_coef_smpte240m_full;
-                       else
-                               csc1_coef = csc1_coef_smpte240m_lim;
-               }
-
-               writel(csc1_coef[0], dev->mmio + HW_PXP_CSC1_COEF0);
-               writel(csc1_coef[1], dev->mmio + HW_PXP_CSC1_COEF1);
-               writel(csc1_coef[2], dev->mmio + HW_PXP_CSC1_COEF2);
-       } else {
-               writel(BM_PXP_CSC1_COEF0_BYPASS, dev->mmio + HW_PXP_CSC1_COEF0);
-       }
-
-       if (!pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) &&
-           pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_DST].fmt->fourcc)) {
-               /*
-                * CSC2 RGB to YUV/YCbCr conversion is implemented as follows:
-                *
-                * |Y |   |A1 A2 A3|   |R|   |D1|
-                * |Cb| = |B1 B2 B3| * |G| + |D2|
-                * |Cr|   |C1 C2 C3|   |B|   |D3|
-                *
-                * Results are clamped to 0..255.
-                *
-                * BT.601 limited range:
-                *
-                * |Y |   | 0.2568  0.5041  0.0979|   |R|   |16 |
-                * |Cb| = |-0.1482 -0.2910  0.4392| * |G| + |128|
-                * |Cr|   | 0.4392  0.4392 -0.3678|   |B|   |128|
-                */
-               static const u32 csc2_coef_bt601_lim[6] = {
-                       BF_PXP_CSC2_COEF0_A2(0x081) |   /*  0.5039 (-0.02 %) */
-                       BF_PXP_CSC2_COEF0_A1(0x041),    /*  0.2539 (-0.29 %) */
-                       BF_PXP_CSC2_COEF1_B1(0x7db) |   /* -0.1445 (+0.37 %) */
-                       BF_PXP_CSC2_COEF1_A3(0x019),    /*  0.0977 (-0.02 %) */
-                       BF_PXP_CSC2_COEF2_B3(0x070) |   /*  0.4375 (-0.17 %) */
-                       BF_PXP_CSC2_COEF2_B2(0x7b6),    /* -0.2891 (+0.20 %) */
-                       BF_PXP_CSC2_COEF3_C2(0x7a2) |   /* -0.3672 (+0.06 %) */
-                       BF_PXP_CSC2_COEF3_C1(0x070),    /*  0.4375 (-0.17 %) */
-                       BF_PXP_CSC2_COEF4_D1(16) |
-                       BF_PXP_CSC2_COEF4_C3(0x7ee),    /* -0.0703 (+0.11 %) */
-                       BF_PXP_CSC2_COEF5_D3(128) |
-                       BF_PXP_CSC2_COEF5_D2(128),
-               };
-               /*
-                * BT.601 full range:
-                *
-                * |Y |   | 0.2990  0.5870  0.1140|   |R|   |0  |
-                * |Cb| = |-0.1687 -0.3313  0.5000| * |G| + |128|
-                * |Cr|   | 0.5000  0.5000 -0.4187|   |B|   |128|
-                */
-               static const u32 csc2_coef_bt601_full[6] = {
-                       BF_PXP_CSC2_COEF0_A2(0x096) |   /*  0.5859 (-0.11 %) */
-                       BF_PXP_CSC2_COEF0_A1(0x04c),    /*  0.2969 (-0.21 %) */
-                       BF_PXP_CSC2_COEF1_B1(0x7d5) |   /* -0.1680 (+0.07 %) */
-                       BF_PXP_CSC2_COEF1_A3(0x01d),    /*  0.1133 (-0.07 %) */
-                       BF_PXP_CSC2_COEF2_B3(0x080) |   /*  0.5000 (+0.00 %) */
-                       BF_PXP_CSC2_COEF2_B2(0x7ac),    /* -0.3281 (+0.32 %) */
-                       BF_PXP_CSC2_COEF3_C2(0x795) |   /* -0.4180 (+0.07 %) */
-                       BF_PXP_CSC2_COEF3_C1(0x080),    /*  0.5000 (+0.00 %) */
-                       BF_PXP_CSC2_COEF4_D1(0) |
-                       BF_PXP_CSC2_COEF4_C3(0x7ec),    /* -0.0781 (+0.32 %) */
-                       BF_PXP_CSC2_COEF5_D3(128) |
-                       BF_PXP_CSC2_COEF5_D2(128),
-               };
-               /*
-                * Rec.709 limited range:
-                *
-                * |Y |   | 0.1826  0.6142  0.0620|   |R|   |16 |
-                * |Cb| = |-0.1007 -0.3385  0.4392| * |G| + |128|
-                * |Cr|   | 0.4392  0.4392 -0.3990|   |B|   |128|
-                */
-               static const u32 csc2_coef_rec709_lim[6] = {
-                       BF_PXP_CSC2_COEF0_A2(0x09d) |   /*  0.6133 (-0.09 %) */
-                       BF_PXP_CSC2_COEF0_A1(0x02e),    /*  0.1797 (-0.29 %) */
-                       BF_PXP_CSC2_COEF1_B1(0x7e7) |   /* -0.0977 (+0.30 %) */
-                       BF_PXP_CSC2_COEF1_A3(0x00f),    /*  0.0586 (-0.34 %) */
-                       BF_PXP_CSC2_COEF2_B3(0x070) |   /*  0.4375 (-0.17 %) */
-                       BF_PXP_CSC2_COEF2_B2(0x7aa),    /* -0.3359 (+0.26 %) */
-                       BF_PXP_CSC2_COEF3_C2(0x79a) |   /* -0.3984 (+0.05 %) */
-                       BF_PXP_CSC2_COEF3_C1(0x070),    /*  0.4375 (-0.17 %) */
-                       BF_PXP_CSC2_COEF4_D1(16) |
-                       BF_PXP_CSC2_COEF4_C3(0x7f6),    /* -0.0391 (+0.12 %) */
-                       BF_PXP_CSC2_COEF5_D3(128) |
-                       BF_PXP_CSC2_COEF5_D2(128),
-               };
-               /*
-                * Rec.709 full range:
-                *
-                * |Y |   | 0.2126  0.7152  0.0722|   |R|   |0  |
-                * |Cb| = |-0.1146 -0.3854  0.5000| * |G| + |128|
-                * |Cr|   | 0.5000  0.5000 -0.4542|   |B|   |128|
-                */
-               static const u32 csc2_coef_rec709_full[6] = {
-                       BF_PXP_CSC2_COEF0_A2(0x0b7) |   /*  0.7148 (-0.04 %) */
-                       BF_PXP_CSC2_COEF0_A1(0x036),    /*  0.2109 (-0.17 %) */
-                       BF_PXP_CSC2_COEF1_B1(0x7e3) |   /* -0.1133 (+0.13 %) */
-                       BF_PXP_CSC2_COEF1_A3(0x012),    /*  0.0703 (-0.19 %) */
-                       BF_PXP_CSC2_COEF2_B3(0x080) |   /*  0.5000 (+0.00 %) */
-                       BF_PXP_CSC2_COEF2_B2(0x79e),    /* -0.3828 (+0.26 %) */
-                       BF_PXP_CSC2_COEF3_C2(0x78c) |   /* -0.4531 (+0.11 %) */
-                       BF_PXP_CSC2_COEF3_C1(0x080),    /*  0.5000 (+0.00 %) */
-                       BF_PXP_CSC2_COEF4_D1(0) |
-                       BF_PXP_CSC2_COEF4_C3(0x7f5),    /* -0.0430 (+0.28 %) */
-                       BF_PXP_CSC2_COEF5_D3(128) |
-                       BF_PXP_CSC2_COEF5_D2(128),
-               };
-               /*
-                * BT.2020 limited range:
-                *
-                * |Y |   | 0.2256  0.5823  0.0509|   |R|   |16 |
-                * |Cb| = |-0.1226 -0.3166  0.4392| * |G| + |128|
-                * |Cr|   | 0.4392  0.4392 -0.4039|   |B|   |128|
-                */
-               static const u32 csc2_coef_bt2020_lim[6] = {
-                       BF_PXP_CSC2_COEF0_A2(0x095) |   /*  0.5820 (-0.03 %) */
-                       BF_PXP_CSC2_COEF0_A1(0x039),    /*  0.2227 (-0.30 %) */
-                       BF_PXP_CSC2_COEF1_B1(0x7e1) |   /* -0.1211 (+0.15 %) */
-                       BF_PXP_CSC2_COEF1_A3(0x00d),    /*  0.0508 (-0.01 %) */
-                       BF_PXP_CSC2_COEF2_B3(0x070) |   /*  0.4375 (-0.17 %) */
-                       BF_PXP_CSC2_COEF2_B2(0x7af),    /* -0.3164 (+0.02 %) */
-                       BF_PXP_CSC2_COEF3_C2(0x799) |   /* -0.4023 (+0.16 %) */
-                       BF_PXP_CSC2_COEF3_C1(0x070),    /*  0.4375 (-0.17 %) */
-                       BF_PXP_CSC2_COEF4_D1(16) |
-                       BF_PXP_CSC2_COEF4_C3(0x7f7),    /* -0.0352 (+0.02 %) */
-                       BF_PXP_CSC2_COEF5_D3(128) |
-                       BF_PXP_CSC2_COEF5_D2(128),
-               };
-               /*
-                * BT.2020 full range:
-                *
-                * |Y |   | 0.2627  0.6780  0.0593|   |R|   |0  |
-                * |Cb| = |-0.1396 -0.3604  0.5000| * |G| + |128|
-                * |Cr|   | 0.5000  0.5000 -0.4598|   |B|   |128|
-                */
-               static const u32 csc2_coef_bt2020_full[6] = {
-                       BF_PXP_CSC2_COEF0_A2(0x0ad) |   /*  0.6758 (-0.22 %) */
-                       BF_PXP_CSC2_COEF0_A1(0x043),    /*  0.2617 (-0.10 %) */
-                       BF_PXP_CSC2_COEF1_B1(0x7dd) |   /* -0.1367 (+0.29 %) */
-                       BF_PXP_CSC2_COEF1_A3(0x00f),    /*  0.0586 (-0.07 %) */
-                       BF_PXP_CSC2_COEF2_B3(0x080) |   /*  0.5000 (+0.00 %) */
-                       BF_PXP_CSC2_COEF2_B2(0x7a4),    /* -0.3594 (+0.10 %) */
-                       BF_PXP_CSC2_COEF3_C2(0x78b) |   /* -0.4570 (+0.28 %) */
-                       BF_PXP_CSC2_COEF3_C1(0x080),    /*  0.5000 (+0.00 %) */
-                       BF_PXP_CSC2_COEF4_D1(0) |
-                       BF_PXP_CSC2_COEF4_C3(0x7f6),    /* -0.0391 (+0.11 %) */
-                       BF_PXP_CSC2_COEF5_D3(128) |
-                       BF_PXP_CSC2_COEF5_D2(128),
-               };
-               /*
-                * SMPTE 240m limited range:
-                *
-                * |Y |   | 0.1821  0.6020  0.0747|   |R|   |16 |
-                * |Cb| = |-0.1019 -0.3373  0.4392| * |G| + |128|
-                * |Cr|   | 0.4392  0.4392 -0.3909|   |B|   |128|
-                */
-               static const u32 csc2_coef_smpte240m_lim[6] = {
-                       BF_PXP_CSC2_COEF0_A2(0x09a) |   /*  0.6016 (-0.05 %) */
-                       BF_PXP_CSC2_COEF0_A1(0x02e),    /*  0.1797 (-0.24 %) */
-                       BF_PXP_CSC2_COEF1_B1(0x7e6) |   /* -0.1016 (+0.03 %) */
-                       BF_PXP_CSC2_COEF1_A3(0x013),    /*  0.0742 (-0.05 %) */
-                       BF_PXP_CSC2_COEF2_B3(0x070) |   /*  0.4375 (-0.17 %) */
-                       BF_PXP_CSC2_COEF2_B2(0x7aa),    /* -0.3359 (+0.14 %) */
-                       BF_PXP_CSC2_COEF3_C2(0x79c) |   /* -0.3906 (+0.03 %) */
-                       BF_PXP_CSC2_COEF3_C1(0x070),    /*  0.4375 (-0.17 %) */
-                       BF_PXP_CSC2_COEF4_D1(16) |
-                       BF_PXP_CSC2_COEF4_C3(0x7f4),    /* -0.0469 (+0.14 %) */
-                       BF_PXP_CSC2_COEF5_D3(128) |
-                       BF_PXP_CSC2_COEF5_D2(128),
-               };
-               /*
-                * SMPTE 240m full range:
-                *
-                * |Y |   | 0.2120  0.7010  0.0870|   |R|   |0  |
-                * |Cb| = |-0.1160 -0.3840  0.5000| * |G| + |128|
-                * |Cr|   | 0.5000  0.5000 -0.4450|   |B|   |128|
-                */
-               static const u32 csc2_coef_smpte240m_full[6] = {
-                       BF_PXP_CSC2_COEF0_A2(0x0b3) |   /*  0.6992 (-0.18 %) */
-                       BF_PXP_CSC2_COEF0_A1(0x036),    /*  0.2109 (-0.11 %) */
-                       BF_PXP_CSC2_COEF1_B1(0x7e3) |   /* -0.1133 (+0.27 %) */
-                       BF_PXP_CSC2_COEF1_A3(0x016),    /*  0.0859 (-0.11 %) */
-                       BF_PXP_CSC2_COEF2_B3(0x080) |   /*  0.5000 (+0.00 %) */
-                       BF_PXP_CSC2_COEF2_B2(0x79e),    /* -0.3828 (+0.12 %) */
-                       BF_PXP_CSC2_COEF3_C2(0x78f) |   /* -0.4414 (+0.36 %) */
-                       BF_PXP_CSC2_COEF3_C1(0x080),    /*  0.5000 (+0.00 %) */
-                       BF_PXP_CSC2_COEF4_D1(0) |
-                       BF_PXP_CSC2_COEF4_C3(0x7f2),    /* -0.0547 (+0.03 %) */
-                       BF_PXP_CSC2_COEF5_D3(128) |
-                       BF_PXP_CSC2_COEF5_D2(128),
-               };
-               const u32 *csc2_coef;
-               u32 csc2_ctrl;
-
-               ycbcr_enc = ctx->q_data[V4L2_M2M_DST].ycbcr_enc;
-               quantization = ctx->q_data[V4L2_M2M_DST].quant;
-
-               if (ycbcr_enc == V4L2_YCBCR_ENC_601) {
-                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
-                               csc2_coef = csc2_coef_bt601_full;
-                       else
-                               csc2_coef = csc2_coef_bt601_lim;
-               } else if (ycbcr_enc == V4L2_YCBCR_ENC_709) {
-                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
-                               csc2_coef = csc2_coef_rec709_full;
-                       else
-                               csc2_coef = csc2_coef_rec709_lim;
-               } else if (ycbcr_enc == V4L2_YCBCR_ENC_BT2020) {
-                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
-                               csc2_coef = csc2_coef_bt2020_full;
-                       else
-                               csc2_coef = csc2_coef_bt2020_lim;
-               } else {
-                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
-                               csc2_coef = csc2_coef_smpte240m_full;
-                       else
-                               csc2_coef = csc2_coef_smpte240m_lim;
-               }
-               if (quantization == V4L2_QUANTIZATION_FULL_RANGE) {
-                       csc2_ctrl = BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV <<
-                                   BP_PXP_CSC2_CTRL_CSC_MODE;
-               } else {
-                       csc2_ctrl = BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr <<
-                                   BP_PXP_CSC2_CTRL_CSC_MODE;
-               }
-
-               writel(csc2_ctrl, dev->mmio + HW_PXP_CSC2_CTRL);
-               writel(csc2_coef[0], dev->mmio + HW_PXP_CSC2_COEF0);
-               writel(csc2_coef[1], dev->mmio + HW_PXP_CSC2_COEF1);
-               writel(csc2_coef[2], dev->mmio + HW_PXP_CSC2_COEF2);
-               writel(csc2_coef[3], dev->mmio + HW_PXP_CSC2_COEF3);
-               writel(csc2_coef[4], dev->mmio + HW_PXP_CSC2_COEF4);
-               writel(csc2_coef[5], dev->mmio + HW_PXP_CSC2_COEF5);
-       } else {
-               writel(BM_PXP_CSC2_CTRL_BYPASS, dev->mmio + HW_PXP_CSC2_CTRL);
-       }
-}
-
-static int pxp_start(struct pxp_ctx *ctx, struct vb2_v4l2_buffer *in_vb,
-                    struct vb2_v4l2_buffer *out_vb)
-{
-       struct pxp_dev *dev = ctx->dev;
-       struct pxp_q_data *q_data;
-       u32 src_width, src_height, src_stride, src_fourcc;
-       u32 dst_width, dst_height, dst_stride, dst_fourcc;
-       dma_addr_t p_in, p_out;
-       u32 ctrl, out_ctrl, out_buf, out_buf2, out_pitch, out_lrc, out_ps_ulc;
-       u32 out_ps_lrc;
-       u32 ps_ctrl, ps_buf, ps_ubuf, ps_vbuf, ps_pitch, ps_scale, ps_offset;
-       u32 as_ulc, as_lrc;
-       u32 y_size;
-       u32 decx, decy, xscale, yscale;
-
-       q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-
-       src_width = ctx->q_data[V4L2_M2M_SRC].width;
-       dst_width = ctx->q_data[V4L2_M2M_DST].width;
-       src_height = ctx->q_data[V4L2_M2M_SRC].height;
-       dst_height = ctx->q_data[V4L2_M2M_DST].height;
-       src_stride = ctx->q_data[V4L2_M2M_SRC].bytesperline;
-       dst_stride = ctx->q_data[V4L2_M2M_DST].bytesperline;
-       src_fourcc = ctx->q_data[V4L2_M2M_SRC].fmt->fourcc;
-       dst_fourcc = ctx->q_data[V4L2_M2M_DST].fmt->fourcc;
-
-       p_in = vb2_dma_contig_plane_dma_addr(&in_vb->vb2_buf, 0);
-       p_out = vb2_dma_contig_plane_dma_addr(&out_vb->vb2_buf, 0);
-
-       if (!p_in || !p_out) {
-               v4l2_err(&dev->v4l2_dev,
-                        "Acquiring DMA addresses of buffers failed\n");
-               return -EFAULT;
-       }
-
-       out_vb->sequence =
-               get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++;
-       in_vb->sequence = q_data->sequence++;
-       out_vb->vb2_buf.timestamp = in_vb->vb2_buf.timestamp;
-
-       if (in_vb->flags & V4L2_BUF_FLAG_TIMECODE)
-               out_vb->timecode = in_vb->timecode;
-       out_vb->field = in_vb->field;
-       out_vb->flags = in_vb->flags &
-               (V4L2_BUF_FLAG_TIMECODE |
-                V4L2_BUF_FLAG_KEYFRAME |
-                V4L2_BUF_FLAG_PFRAME |
-                V4L2_BUF_FLAG_BFRAME |
-                V4L2_BUF_FLAG_TSTAMP_SRC_MASK);
-
-       /* 8x8 block size */
-       ctrl = BF_PXP_CTRL_VFLIP0(!!(ctx->mode & MEM2MEM_VFLIP)) |
-              BF_PXP_CTRL_HFLIP0(!!(ctx->mode & MEM2MEM_HFLIP)) |
-              BF_PXP_CTRL_ROTATE0(ctx->rotation);
-       /* Always write alpha value as V4L2_CID_ALPHA_COMPONENT */
-       out_ctrl = BF_PXP_OUT_CTRL_ALPHA(ctx->alpha_component) |
-                  BF_PXP_OUT_CTRL_ALPHA_OUTPUT(1) |
-                  pxp_v4l2_pix_fmt_to_out_format(dst_fourcc);
-       out_buf = p_out;
-
-       if (ctx->rotation == BV_PXP_CTRL_ROTATE0__ROT_90 ||
-           ctx->rotation == BV_PXP_CTRL_ROTATE0__ROT_270)
-               swap(dst_width, dst_height);
-
-       switch (dst_fourcc) {
-       case V4L2_PIX_FMT_NV12:
-       case V4L2_PIX_FMT_NV21:
-       case V4L2_PIX_FMT_NV16:
-       case V4L2_PIX_FMT_NV61:
-               out_buf2 = out_buf + dst_stride * dst_height;
-               break;
-       default:
-               out_buf2 = 0;
-       }
-
-       out_pitch = BF_PXP_OUT_PITCH_PITCH(dst_stride);
-       out_lrc = BF_PXP_OUT_LRC_X(dst_width - 1) |
-                 BF_PXP_OUT_LRC_Y(dst_height - 1);
-       /* PS covers whole output */
-       out_ps_ulc = BF_PXP_OUT_PS_ULC_X(0) | BF_PXP_OUT_PS_ULC_Y(0);
-       out_ps_lrc = BF_PXP_OUT_PS_LRC_X(dst_width - 1) |
-                    BF_PXP_OUT_PS_LRC_Y(dst_height - 1);
-       /* no AS */
-       as_ulc = BF_PXP_OUT_AS_ULC_X(1) | BF_PXP_OUT_AS_ULC_Y(1);
-       as_lrc = BF_PXP_OUT_AS_LRC_X(0) | BF_PXP_OUT_AS_LRC_Y(0);
-
-       decx = (src_width <= dst_width) ? 0 : ilog2(src_width / dst_width);
-       decy = (src_height <= dst_height) ? 0 : ilog2(src_height / dst_height);
-       ps_ctrl = BF_PXP_PS_CTRL_DECX(decx) | BF_PXP_PS_CTRL_DECY(decy) |
-                 pxp_v4l2_pix_fmt_to_ps_format(src_fourcc);
-       ps_buf = p_in;
-       y_size = src_stride * src_height;
-       switch (src_fourcc) {
-       case V4L2_PIX_FMT_YUV420:
-               ps_ubuf = ps_buf + y_size;
-               ps_vbuf = ps_ubuf + y_size / 4;
-               break;
-       case V4L2_PIX_FMT_YUV422P:
-               ps_ubuf = ps_buf + y_size;
-               ps_vbuf = ps_ubuf + y_size / 2;
-               break;
-       case V4L2_PIX_FMT_NV12:
-       case V4L2_PIX_FMT_NV21:
-       case V4L2_PIX_FMT_NV16:
-       case V4L2_PIX_FMT_NV61:
-               ps_ubuf = ps_buf + y_size;
-               ps_vbuf = 0;
-               break;
-       case V4L2_PIX_FMT_GREY:
-       case V4L2_PIX_FMT_Y4:
-               ps_ubuf = 0;
-               /* In grayscale mode, ps_vbuf contents are reused as CbCr */
-               ps_vbuf = 0x8080;
-               break;
-       default:
-               ps_ubuf = 0;
-               ps_vbuf = 0;
-               break;
-       }
-       ps_pitch = BF_PXP_PS_PITCH_PITCH(src_stride);
-       if (decx) {
-               xscale = (src_width >> decx) * 0x1000 / dst_width;
-       } else {
-               switch (src_fourcc) {
-               case V4L2_PIX_FMT_UYVY:
-               case V4L2_PIX_FMT_YUYV:
-               case V4L2_PIX_FMT_VYUY:
-               case V4L2_PIX_FMT_YVYU:
-               case V4L2_PIX_FMT_NV16:
-               case V4L2_PIX_FMT_NV12:
-               case V4L2_PIX_FMT_NV21:
-               case V4L2_PIX_FMT_NV61:
-               case V4L2_PIX_FMT_YUV422P:
-               case V4L2_PIX_FMT_YUV420:
-                       /*
-                        * This avoids sampling past the right edge for
-                        * horizontally chroma subsampled formats.
-                        */
-                       xscale = (src_width - 2) * 0x1000 / (dst_width - 1);
-                       break;
-               default:
-                       xscale = (src_width - 1) * 0x1000 / (dst_width - 1);
-                       break;
-               }
-       }
-       if (decy)
-               yscale = (src_height >> decy) * 0x1000 / dst_height;
-       else
-               yscale = (src_height - 1) * 0x1000 / (dst_height - 1);
-       ps_scale = BF_PXP_PS_SCALE_YSCALE(yscale) |
-                  BF_PXP_PS_SCALE_XSCALE(xscale);
-       ps_offset = BF_PXP_PS_OFFSET_YOFFSET(0) | BF_PXP_PS_OFFSET_XOFFSET(0);
-
-       writel(ctrl, dev->mmio + HW_PXP_CTRL);
-       /* skip STAT */
-       writel(out_ctrl, dev->mmio + HW_PXP_OUT_CTRL);
-       writel(out_buf, dev->mmio + HW_PXP_OUT_BUF);
-       writel(out_buf2, dev->mmio + HW_PXP_OUT_BUF2);
-       writel(out_pitch, dev->mmio + HW_PXP_OUT_PITCH);
-       writel(out_lrc, dev->mmio + HW_PXP_OUT_LRC);
-       writel(out_ps_ulc, dev->mmio + HW_PXP_OUT_PS_ULC);
-       writel(out_ps_lrc, dev->mmio + HW_PXP_OUT_PS_LRC);
-       writel(as_ulc, dev->mmio + HW_PXP_OUT_AS_ULC);
-       writel(as_lrc, dev->mmio + HW_PXP_OUT_AS_LRC);
-       writel(ps_ctrl, dev->mmio + HW_PXP_PS_CTRL);
-       writel(ps_buf, dev->mmio + HW_PXP_PS_BUF);
-       writel(ps_ubuf, dev->mmio + HW_PXP_PS_UBUF);
-       writel(ps_vbuf, dev->mmio + HW_PXP_PS_VBUF);
-       writel(ps_pitch, dev->mmio + HW_PXP_PS_PITCH);
-       writel(0x00ffffff, dev->mmio + HW_PXP_PS_BACKGROUND_0);
-       writel(ps_scale, dev->mmio + HW_PXP_PS_SCALE);
-       writel(ps_offset, dev->mmio + HW_PXP_PS_OFFSET);
-       /* disable processed surface color keying */
-       writel(0x00ffffff, dev->mmio + HW_PXP_PS_CLRKEYLOW_0);
-       writel(0x00000000, dev->mmio + HW_PXP_PS_CLRKEYHIGH_0);
-
-       /* disable alpha surface color keying */
-       writel(0x00ffffff, dev->mmio + HW_PXP_AS_CLRKEYLOW_0);
-       writel(0x00000000, dev->mmio + HW_PXP_AS_CLRKEYHIGH_0);
-
-       /* setup CSC */
-       pxp_setup_csc(ctx);
-
-       /* bypass LUT */
-       writel(BM_PXP_LUT_CTRL_BYPASS, dev->mmio + HW_PXP_LUT_CTRL);
-
-       writel(BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(1)|
-              BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(1)|
-              BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(0)|
-              BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(0),
-              dev->mmio + HW_PXP_DATA_PATH_CTRL0);
-       writel(BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(1) |
-              BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(1),
-              dev->mmio + HW_PXP_DATA_PATH_CTRL1);
-
-       writel(0xffff, dev->mmio + HW_PXP_IRQ_MASK);
-
-       /* ungate, enable PS/AS/OUT and PXP operation */
-       writel(BM_PXP_CTRL_IRQ_ENABLE, dev->mmio + HW_PXP_CTRL_SET);
-       writel(BM_PXP_CTRL_ENABLE | BM_PXP_CTRL_ENABLE_CSC2 |
-              BM_PXP_CTRL_ENABLE_LUT | BM_PXP_CTRL_ENABLE_ROTATE0 |
-              BM_PXP_CTRL_ENABLE_PS_AS_OUT, dev->mmio + HW_PXP_CTRL_SET);
-
-       return 0;
-}
-
-static void pxp_job_finish(struct pxp_dev *dev)
-{
-       struct pxp_ctx *curr_ctx;
-       struct vb2_v4l2_buffer *src_vb, *dst_vb;
-       unsigned long flags;
-
-       curr_ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
-
-       if (curr_ctx == NULL) {
-               pr_err("Instance released before the end of transaction\n");
-               return;
-       }
-
-       src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
-       dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
-
-       spin_lock_irqsave(&dev->irqlock, flags);
-       v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
-       v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-
-       dprintk(curr_ctx->dev, "Finishing transaction\n");
-       v4l2_m2m_job_finish(dev->m2m_dev, curr_ctx->fh.m2m_ctx);
-}
-
-/*
- * mem2mem callbacks
- */
-static void pxp_device_run(void *priv)
-{
-       struct pxp_ctx *ctx = priv;
-       struct vb2_v4l2_buffer *src_buf, *dst_buf;
-
-       src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-       dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-
-       pxp_start(ctx, src_buf, dst_buf);
-}
-
-static int pxp_job_ready(void *priv)
-{
-       struct pxp_ctx *ctx = priv;
-
-       if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < 1 ||
-           v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < 1) {
-               dprintk(ctx->dev, "Not enough buffers available\n");
-               return 0;
-       }
-
-       return 1;
-}
-
-static void pxp_job_abort(void *priv)
-{
-       struct pxp_ctx *ctx = priv;
-
-       /* Will cancel the transaction in the next interrupt handler */
-       ctx->aborting = 1;
-}
-
-/*
- * interrupt handler
- */
-static irqreturn_t pxp_irq_handler(int irq, void *dev_id)
-{
-       struct pxp_dev *dev = dev_id;
-       u32 stat;
-
-       stat = readl(dev->mmio + HW_PXP_STAT);
-
-       if (stat & BM_PXP_STAT_IRQ0) {
-               /* we expect x = 0, y = height, irq0 = 1 */
-               if (stat & ~(BM_PXP_STAT_BLOCKX | BM_PXP_STAT_BLOCKY |
-                            BM_PXP_STAT_IRQ0))
-                       dprintk(dev, "%s: stat = 0x%08x\n", __func__, stat);
-               writel(BM_PXP_STAT_IRQ0, dev->mmio + HW_PXP_STAT_CLR);
-
-               pxp_job_finish(dev);
-       } else {
-               u32 irq = readl(dev->mmio + HW_PXP_IRQ);
-
-               dprintk(dev, "%s: stat = 0x%08x\n", __func__, stat);
-               dprintk(dev, "%s: irq = 0x%08x\n", __func__, irq);
-
-               writel(irq, dev->mmio + HW_PXP_IRQ_CLR);
-       }
-
-       return IRQ_HANDLED;
-}
-
-/*
- * video ioctls
- */
-static int pxp_querycap(struct file *file, void *priv,
-                          struct v4l2_capability *cap)
-{
-       strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
-       strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
-       snprintf(cap->bus_info, sizeof(cap->bus_info),
-                       "platform:%s", MEM2MEM_NAME);
-       return 0;
-}
-
-static int pxp_enum_fmt(struct v4l2_fmtdesc *f, u32 type)
-{
-       int i, num;
-       struct pxp_fmt *fmt;
-
-       num = 0;
-
-       for (i = 0; i < NUM_FORMATS; ++i) {
-               if (formats[i].types & type) {
-                       /* index-th format of type type found ? */
-                       if (num == f->index)
-                               break;
-                       /*
-                        * Correct type but haven't reached our index yet,
-                        * just increment per-type index
-                        */
-                       ++num;
-               }
-       }
-
-       if (i < NUM_FORMATS) {
-               /* Format found */
-               fmt = &formats[i];
-               f->pixelformat = fmt->fourcc;
-               return 0;
-       }
-
-       /* Format not found */
-       return -EINVAL;
-}
-
-static int pxp_enum_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_fmtdesc *f)
-{
-       return pxp_enum_fmt(f, MEM2MEM_CAPTURE);
-}
-
-static int pxp_enum_fmt_vid_out(struct file *file, void *priv,
-                               struct v4l2_fmtdesc *f)
-{
-       return pxp_enum_fmt(f, MEM2MEM_OUTPUT);
-}
-
-static int pxp_g_fmt(struct pxp_ctx *ctx, struct v4l2_format *f)
-{
-       struct vb2_queue *vq;
-       struct pxp_q_data *q_data;
-
-       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-       if (!vq)
-               return -EINVAL;
-
-       q_data = get_q_data(ctx, f->type);
-
-       f->fmt.pix.width        = q_data->width;
-       f->fmt.pix.height       = q_data->height;
-       f->fmt.pix.field        = V4L2_FIELD_NONE;
-       f->fmt.pix.pixelformat  = q_data->fmt->fourcc;
-       f->fmt.pix.bytesperline = q_data->bytesperline;
-       f->fmt.pix.sizeimage    = q_data->sizeimage;
-       f->fmt.pix.colorspace   = ctx->colorspace;
-       f->fmt.pix.xfer_func    = ctx->xfer_func;
-       f->fmt.pix.ycbcr_enc    = q_data->ycbcr_enc;
-       f->fmt.pix.quantization = q_data->quant;
-
-       return 0;
-}
-
-static int pxp_g_fmt_vid_out(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       return pxp_g_fmt(file2ctx(file), f);
-}
-
-static int pxp_g_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       return pxp_g_fmt(file2ctx(file), f);
-}
-
-static inline u32 pxp_bytesperline(struct pxp_fmt *fmt, u32 width)
-{
-       switch (fmt->fourcc) {
-       case V4L2_PIX_FMT_YUV420:
-       case V4L2_PIX_FMT_NV12:
-       case V4L2_PIX_FMT_NV21:
-       case V4L2_PIX_FMT_YUV422P:
-       case V4L2_PIX_FMT_NV16:
-       case V4L2_PIX_FMT_NV61:
-               return width;
-       default:
-               return (width * fmt->depth) >> 3;
-       }
-}
-
-static inline u32 pxp_sizeimage(struct pxp_fmt *fmt, u32 width, u32 height)
-{
-       return (fmt->depth * width * height) >> 3;
-}
-
-static int pxp_try_fmt(struct v4l2_format *f, struct pxp_fmt *fmt)
-{
-       v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, ALIGN_W,
-                             &f->fmt.pix.height, MIN_H, MAX_H, ALIGN_H, 0);
-
-       f->fmt.pix.bytesperline = pxp_bytesperline(fmt, f->fmt.pix.width);
-       f->fmt.pix.sizeimage = pxp_sizeimage(fmt, f->fmt.pix.width,
-                                            f->fmt.pix.height);
-       f->fmt.pix.field = V4L2_FIELD_NONE;
-
-       return 0;
-}
-
-static void
-pxp_fixup_colorimetry_cap(struct pxp_ctx *ctx, u32 dst_fourcc,
-                         enum v4l2_ycbcr_encoding *ycbcr_enc,
-                         enum v4l2_quantization *quantization)
-{
-       bool dst_is_yuv = pxp_v4l2_pix_fmt_is_yuv(dst_fourcc);
-
-       if (pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) ==
-           dst_is_yuv) {
-               /*
-                * There is no support for conversion between different YCbCr
-                * encodings or between RGB limited and full range.
-                */
-               *ycbcr_enc = ctx->q_data[V4L2_M2M_SRC].ycbcr_enc;
-               *quantization = ctx->q_data[V4L2_M2M_SRC].quant;
-       } else {
-               *ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(ctx->colorspace);
-               *quantization = V4L2_MAP_QUANTIZATION_DEFAULT(!dst_is_yuv,
-                                                             ctx->colorspace,
-                                                             *ycbcr_enc);
-       }
-}
-
-static int pxp_try_fmt_vid_cap(struct file *file, void *priv,
-                              struct v4l2_format *f)
-{
-       struct pxp_fmt *fmt;
-       struct pxp_ctx *ctx = file2ctx(file);
-
-       fmt = find_format(f);
-       if (!fmt) {
-               f->fmt.pix.pixelformat = formats[0].fourcc;
-               fmt = find_format(f);
-       }
-       if (!(fmt->types & MEM2MEM_CAPTURE)) {
-               v4l2_err(&ctx->dev->v4l2_dev,
-                        "Fourcc format (0x%08x) invalid.\n",
-                        f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       f->fmt.pix.colorspace = ctx->colorspace;
-       f->fmt.pix.xfer_func = ctx->xfer_func;
-
-       pxp_fixup_colorimetry_cap(ctx, fmt->fourcc,
-                                 &f->fmt.pix.ycbcr_enc,
-                                 &f->fmt.pix.quantization);
-
-       return pxp_try_fmt(f, fmt);
-}
-
-static int pxp_try_fmt_vid_out(struct file *file, void *priv,
-                              struct v4l2_format *f)
-{
-       struct pxp_fmt *fmt;
-       struct pxp_ctx *ctx = file2ctx(file);
-
-       fmt = find_format(f);
-       if (!fmt) {
-               f->fmt.pix.pixelformat = formats[0].fourcc;
-               fmt = find_format(f);
-       }
-       if (!(fmt->types & MEM2MEM_OUTPUT)) {
-               v4l2_err(&ctx->dev->v4l2_dev,
-                        "Fourcc format (0x%08x) invalid.\n",
-                        f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       if (!f->fmt.pix.colorspace)
-               f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
-
-       return pxp_try_fmt(f, fmt);
-}
-
-static int pxp_s_fmt(struct pxp_ctx *ctx, struct v4l2_format *f)
-{
-       struct pxp_q_data *q_data;
-       struct vb2_queue *vq;
-
-       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-       if (!vq)
-               return -EINVAL;
-
-       q_data = get_q_data(ctx, f->type);
-       if (!q_data)
-               return -EINVAL;
-
-       if (vb2_is_busy(vq)) {
-               v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
-               return -EBUSY;
-       }
-
-       q_data->fmt             = find_format(f);
-       q_data->width           = f->fmt.pix.width;
-       q_data->height          = f->fmt.pix.height;
-       q_data->bytesperline    = f->fmt.pix.bytesperline;
-       q_data->sizeimage       = f->fmt.pix.sizeimage;
-
-       dprintk(ctx->dev,
-               "Setting format for type %d, wxh: %dx%d, fmt: %d\n",
-               f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
-
-       return 0;
-}
-
-static int pxp_s_fmt_vid_cap(struct file *file, void *priv,
-                            struct v4l2_format *f)
-{
-       struct pxp_ctx *ctx = file2ctx(file);
-       int ret;
-
-       ret = pxp_try_fmt_vid_cap(file, priv, f);
-       if (ret)
-               return ret;
-
-       ret = pxp_s_fmt(file2ctx(file), f);
-       if (ret)
-               return ret;
-
-       ctx->q_data[V4L2_M2M_DST].ycbcr_enc = f->fmt.pix.ycbcr_enc;
-       ctx->q_data[V4L2_M2M_DST].quant = f->fmt.pix.quantization;
-
-       return 0;
-}
-
-static int pxp_s_fmt_vid_out(struct file *file, void *priv,
-                            struct v4l2_format *f)
-{
-       struct pxp_ctx *ctx = file2ctx(file);
-       int ret;
-
-       ret = pxp_try_fmt_vid_out(file, priv, f);
-       if (ret)
-               return ret;
-
-       ret = pxp_s_fmt(file2ctx(file), f);
-       if (ret)
-               return ret;
-
-       ctx->colorspace = f->fmt.pix.colorspace;
-       ctx->xfer_func = f->fmt.pix.xfer_func;
-       ctx->q_data[V4L2_M2M_SRC].ycbcr_enc = f->fmt.pix.ycbcr_enc;
-       ctx->q_data[V4L2_M2M_SRC].quant = f->fmt.pix.quantization;
-
-       pxp_fixup_colorimetry_cap(ctx, ctx->q_data[V4L2_M2M_DST].fmt->fourcc,
-                                 &ctx->q_data[V4L2_M2M_DST].ycbcr_enc,
-                                 &ctx->q_data[V4L2_M2M_DST].quant);
-
-       return 0;
-}
-
-static u8 pxp_degrees_to_rot_mode(u32 degrees)
-{
-       switch (degrees) {
-       case 90:
-               return BV_PXP_CTRL_ROTATE0__ROT_90;
-       case 180:
-               return BV_PXP_CTRL_ROTATE0__ROT_180;
-       case 270:
-               return BV_PXP_CTRL_ROTATE0__ROT_270;
-       case 0:
-       default:
-               return BV_PXP_CTRL_ROTATE0__ROT_0;
-       }
-}
-
-static int pxp_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct pxp_ctx *ctx =
-               container_of(ctrl->handler, struct pxp_ctx, hdl);
-
-       switch (ctrl->id) {
-       case V4L2_CID_HFLIP:
-               if (ctrl->val)
-                       ctx->mode |= MEM2MEM_HFLIP;
-               else
-                       ctx->mode &= ~MEM2MEM_HFLIP;
-               break;
-
-       case V4L2_CID_VFLIP:
-               if (ctrl->val)
-                       ctx->mode |= MEM2MEM_VFLIP;
-               else
-                       ctx->mode &= ~MEM2MEM_VFLIP;
-               break;
-
-       case V4L2_CID_ROTATE:
-               ctx->rotation = pxp_degrees_to_rot_mode(ctrl->val);
-               break;
-
-       case V4L2_CID_ALPHA_COMPONENT:
-               ctx->alpha_component = ctrl->val;
-               break;
-
-       default:
-               v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static const struct v4l2_ctrl_ops pxp_ctrl_ops = {
-       .s_ctrl = pxp_s_ctrl,
-};
-
-static const struct v4l2_ioctl_ops pxp_ioctl_ops = {
-       .vidioc_querycap        = pxp_querycap,
-
-       .vidioc_enum_fmt_vid_cap = pxp_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap   = pxp_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap = pxp_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap   = pxp_s_fmt_vid_cap,
-
-       .vidioc_enum_fmt_vid_out = pxp_enum_fmt_vid_out,
-       .vidioc_g_fmt_vid_out   = pxp_g_fmt_vid_out,
-       .vidioc_try_fmt_vid_out = pxp_try_fmt_vid_out,
-       .vidioc_s_fmt_vid_out   = pxp_s_fmt_vid_out,
-
-       .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_subscribe_event = v4l2_ctrl_subscribe_event,
-       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-/*
- * Queue operations
- */
-static int pxp_queue_setup(struct vb2_queue *vq,
-                          unsigned int *nbuffers, unsigned int *nplanes,
-                          unsigned int sizes[], struct device *alloc_devs[])
-{
-       struct pxp_ctx *ctx = vb2_get_drv_priv(vq);
-       struct pxp_q_data *q_data;
-       unsigned int size, count = *nbuffers;
-
-       q_data = get_q_data(ctx, vq->type);
-
-       size = q_data->sizeimage;
-
-       *nbuffers = count;
-
-       if (*nplanes)
-               return sizes[0] < size ? -EINVAL : 0;
-
-       *nplanes = 1;
-       sizes[0] = size;
-
-       dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
-
-       return 0;
-}
-
-static int pxp_buf_prepare(struct vb2_buffer *vb)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       struct pxp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-       struct pxp_dev *dev = ctx->dev;
-       struct pxp_q_data *q_data;
-
-       dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
-
-       q_data = get_q_data(ctx, vb->vb2_queue->type);
-       if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
-               if (vbuf->field == V4L2_FIELD_ANY)
-                       vbuf->field = V4L2_FIELD_NONE;
-               if (vbuf->field != V4L2_FIELD_NONE) {
-                       dprintk(dev, "%s field isn't supported\n", __func__);
-                       return -EINVAL;
-               }
-       }
-
-       if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
-               dprintk(dev, "%s data will not fit into plane (%lu < %lu)\n",
-                       __func__, vb2_plane_size(vb, 0),
-                       (long)q_data->sizeimage);
-               return -EINVAL;
-       }
-
-       vb2_set_plane_payload(vb, 0, q_data->sizeimage);
-
-       return 0;
-}
-
-static void pxp_buf_queue(struct vb2_buffer *vb)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       struct pxp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-
-       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
-}
-
-static int pxp_start_streaming(struct vb2_queue *q, unsigned int count)
-{
-       struct pxp_ctx *ctx = vb2_get_drv_priv(q);
-       struct pxp_q_data *q_data = get_q_data(ctx, q->type);
-
-       q_data->sequence = 0;
-       return 0;
-}
-
-static void pxp_stop_streaming(struct vb2_queue *q)
-{
-       struct pxp_ctx *ctx = vb2_get_drv_priv(q);
-       struct vb2_v4l2_buffer *vbuf;
-       unsigned long flags;
-
-       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;
-               spin_lock_irqsave(&ctx->dev->irqlock, flags);
-               v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
-               spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
-       }
-}
-
-static const struct vb2_ops pxp_qops = {
-       .queue_setup     = pxp_queue_setup,
-       .buf_prepare     = pxp_buf_prepare,
-       .buf_queue       = pxp_buf_queue,
-       .start_streaming = pxp_start_streaming,
-       .stop_streaming  = pxp_stop_streaming,
-       .wait_prepare    = vb2_ops_wait_prepare,
-       .wait_finish     = vb2_ops_wait_finish,
-};
-
-static int queue_init(void *priv, struct vb2_queue *src_vq,
-                     struct vb2_queue *dst_vq)
-{
-       struct pxp_ctx *ctx = priv;
-       int ret;
-
-       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-       src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
-       src_vq->drv_priv = ctx;
-       src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-       src_vq->ops = &pxp_qops;
-       src_vq->mem_ops = &vb2_dma_contig_memops;
-       src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       src_vq->lock = &ctx->dev->dev_mutex;
-       src_vq->dev = ctx->dev->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_DMABUF;
-       dst_vq->drv_priv = ctx;
-       dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-       dst_vq->ops = &pxp_qops;
-       dst_vq->mem_ops = &vb2_dma_contig_memops;
-       dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       dst_vq->lock = &ctx->dev->dev_mutex;
-       dst_vq->dev = ctx->dev->v4l2_dev.dev;
-
-       return vb2_queue_init(dst_vq);
-}
-
-/*
- * File operations
- */
-static int pxp_open(struct file *file)
-{
-       struct pxp_dev *dev = video_drvdata(file);
-       struct pxp_ctx *ctx = NULL;
-       struct v4l2_ctrl_handler *hdl;
-       int rc = 0;
-
-       if (mutex_lock_interruptible(&dev->dev_mutex))
-               return -ERESTARTSYS;
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx) {
-               rc = -ENOMEM;
-               goto open_unlock;
-       }
-
-       v4l2_fh_init(&ctx->fh, video_devdata(file));
-       file->private_data = &ctx->fh;
-       ctx->dev = dev;
-       hdl = &ctx->hdl;
-       v4l2_ctrl_handler_init(hdl, 4);
-       v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
-       v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
-       v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_ROTATE, 0, 270, 90, 0);
-       v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
-                         0, 255, 1, 255);
-       if (hdl->error) {
-               rc = hdl->error;
-               v4l2_ctrl_handler_free(hdl);
-               kfree(ctx);
-               goto open_unlock;
-       }
-       ctx->fh.ctrl_handler = hdl;
-       v4l2_ctrl_handler_setup(hdl);
-
-       ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0];
-       ctx->q_data[V4L2_M2M_SRC].width = 640;
-       ctx->q_data[V4L2_M2M_SRC].height = 480;
-       ctx->q_data[V4L2_M2M_SRC].bytesperline =
-               pxp_bytesperline(&formats[0], 640);
-       ctx->q_data[V4L2_M2M_SRC].sizeimage =
-               pxp_sizeimage(&formats[0], 640, 480);
-       ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
-       ctx->colorspace = V4L2_COLORSPACE_REC709;
-
-       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
-
-       if (IS_ERR(ctx->fh.m2m_ctx)) {
-               rc = PTR_ERR(ctx->fh.m2m_ctx);
-
-               v4l2_ctrl_handler_free(hdl);
-               v4l2_fh_exit(&ctx->fh);
-               kfree(ctx);
-               goto open_unlock;
-       }
-
-       v4l2_fh_add(&ctx->fh);
-       atomic_inc(&dev->num_inst);
-
-       dprintk(dev, "Created instance: %p, m2m_ctx: %p\n",
-               ctx, ctx->fh.m2m_ctx);
-
-open_unlock:
-       mutex_unlock(&dev->dev_mutex);
-       return rc;
-}
-
-static int pxp_release(struct file *file)
-{
-       struct pxp_dev *dev = video_drvdata(file);
-       struct pxp_ctx *ctx = file2ctx(file);
-
-       dprintk(dev, "Releasing instance %p\n", ctx);
-
-       v4l2_fh_del(&ctx->fh);
-       v4l2_fh_exit(&ctx->fh);
-       v4l2_ctrl_handler_free(&ctx->hdl);
-       mutex_lock(&dev->dev_mutex);
-       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
-       mutex_unlock(&dev->dev_mutex);
-       kfree(ctx);
-
-       atomic_dec(&dev->num_inst);
-
-       return 0;
-}
-
-static const struct v4l2_file_operations pxp_fops = {
-       .owner          = THIS_MODULE,
-       .open           = pxp_open,
-       .release        = pxp_release,
-       .poll           = v4l2_m2m_fop_poll,
-       .unlocked_ioctl = video_ioctl2,
-       .mmap           = v4l2_m2m_fop_mmap,
-};
-
-static const struct video_device pxp_videodev = {
-       .name           = MEM2MEM_NAME,
-       .vfl_dir        = VFL_DIR_M2M,
-       .fops           = &pxp_fops,
-       .device_caps    = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
-       .ioctl_ops      = &pxp_ioctl_ops,
-       .minor          = -1,
-       .release        = video_device_release_empty,
-};
-
-static const struct v4l2_m2m_ops m2m_ops = {
-       .device_run     = pxp_device_run,
-       .job_ready      = pxp_job_ready,
-       .job_abort      = pxp_job_abort,
-};
-
-static int pxp_soft_reset(struct pxp_dev *dev)
-{
-       int ret;
-       u32 val;
-
-       writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_CLR);
-       writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_CLR);
-
-       writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_SET);
-
-       ret = readl_poll_timeout(dev->mmio + HW_PXP_CTRL, val,
-                                val & BM_PXP_CTRL_CLKGATE, 0, 100);
-       if (ret < 0)
-               return ret;
-
-       writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_CLR);
-       writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_CLR);
-
-       return 0;
-}
-
-static int pxp_probe(struct platform_device *pdev)
-{
-       struct pxp_dev *dev;
-       struct video_device *vfd;
-       int irq;
-       int ret;
-
-       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-       if (!dev)
-               return -ENOMEM;
-
-       dev->clk = devm_clk_get(&pdev->dev, "axi");
-       if (IS_ERR(dev->clk)) {
-               ret = PTR_ERR(dev->clk);
-               dev_err(&pdev->dev, "Failed to get clk: %d\n", ret);
-               return ret;
-       }
-
-       dev->mmio = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(dev->mmio))
-               return PTR_ERR(dev->mmio);
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
-
-       spin_lock_init(&dev->irqlock);
-
-       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, pxp_irq_handler,
-                       IRQF_ONESHOT, dev_name(&pdev->dev), dev);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
-               return ret;
-       }
-
-       ret = clk_prepare_enable(dev->clk);
-       if (ret < 0)
-               return ret;
-
-       ret = pxp_soft_reset(dev);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "PXP reset timeout: %d\n", ret);
-               goto err_clk;
-       }
-
-       ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-       if (ret)
-               goto err_clk;
-
-       atomic_set(&dev->num_inst, 0);
-       mutex_init(&dev->dev_mutex);
-
-       dev->vfd = pxp_videodev;
-       vfd = &dev->vfd;
-       vfd->lock = &dev->dev_mutex;
-       vfd->v4l2_dev = &dev->v4l2_dev;
-
-       video_set_drvdata(vfd, dev);
-       snprintf(vfd->name, sizeof(vfd->name), "%s", pxp_videodev.name);
-       v4l2_info(&dev->v4l2_dev,
-                       "Device registered as /dev/video%d\n", vfd->num);
-
-       platform_set_drvdata(pdev, dev);
-
-       dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
-       if (IS_ERR(dev->m2m_dev)) {
-               v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
-               ret = PTR_ERR(dev->m2m_dev);
-               goto err_v4l2;
-       }
-
-       ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
-       if (ret) {
-               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
-               goto err_m2m;
-       }
-
-       return 0;
-
-err_m2m:
-       v4l2_m2m_release(dev->m2m_dev);
-err_v4l2:
-       v4l2_device_unregister(&dev->v4l2_dev);
-err_clk:
-       clk_disable_unprepare(dev->clk);
-
-       return ret;
-}
-
-static int pxp_remove(struct platform_device *pdev)
-{
-       struct pxp_dev *dev = platform_get_drvdata(pdev);
-
-       writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_SET);
-       writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_SET);
-
-       clk_disable_unprepare(dev->clk);
-
-       v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
-       video_unregister_device(&dev->vfd);
-       v4l2_m2m_release(dev->m2m_dev);
-       v4l2_device_unregister(&dev->v4l2_dev);
-
-       return 0;
-}
-
-static const struct of_device_id pxp_dt_ids[] = {
-       { .compatible = "fsl,imx6ull-pxp", .data = NULL },
-       { },
-};
-MODULE_DEVICE_TABLE(of, pxp_dt_ids);
-
-static struct platform_driver pxp_driver = {
-       .probe          = pxp_probe,
-       .remove         = pxp_remove,
-       .driver         = {
-               .name   = MEM2MEM_NAME,
-               .of_match_table = pxp_dt_ids,
-       },
-};
-
-module_platform_driver(pxp_driver);
-
-MODULE_DESCRIPTION("i.MX PXP mem2mem scaler/CSC/rotator");
-MODULE_AUTHOR("Philipp Zabel <kernel@pengutronix.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/imx-pxp.h b/drivers/media/platform/imx-pxp.h
deleted file mode 100644 (file)
index 44f95c7..0000000
+++ /dev/null
@@ -1,1685 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Freescale PXP Register Definitions
- *
- * based on pxp_dma_v3.h, Xml Revision: 1.77, Template Revision: 1.3
- *
- * Copyright 2014-2015 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-#ifndef __IMX_PXP_H__
-#define __IMX_PXP_H__
-
-#define HW_PXP_CTRL    (0x00000000)
-#define HW_PXP_CTRL_SET        (0x00000004)
-#define HW_PXP_CTRL_CLR        (0x00000008)
-#define HW_PXP_CTRL_TOG        (0x0000000c)
-
-#define BM_PXP_CTRL_SFTRST 0x80000000
-#define BF_PXP_CTRL_SFTRST(v) \
-       (((v) << 31) & BM_PXP_CTRL_SFTRST)
-#define BM_PXP_CTRL_CLKGATE 0x40000000
-#define BF_PXP_CTRL_CLKGATE(v)  \
-       (((v) << 30) & BM_PXP_CTRL_CLKGATE)
-#define BM_PXP_CTRL_RSVD4 0x20000000
-#define BF_PXP_CTRL_RSVD4(v)  \
-       (((v) << 29) & BM_PXP_CTRL_RSVD4)
-#define BM_PXP_CTRL_EN_REPEAT 0x10000000
-#define BF_PXP_CTRL_EN_REPEAT(v)  \
-       (((v) << 28) & BM_PXP_CTRL_EN_REPEAT)
-#define BM_PXP_CTRL_ENABLE_ROTATE1 0x08000000
-#define BF_PXP_CTRL_ENABLE_ROTATE1(v)  \
-       (((v) << 27) & BM_PXP_CTRL_ENABLE_ROTATE1)
-#define BM_PXP_CTRL_ENABLE_ROTATE0 0x04000000
-#define BF_PXP_CTRL_ENABLE_ROTATE0(v)  \
-       (((v) << 26) & BM_PXP_CTRL_ENABLE_ROTATE0)
-#define BM_PXP_CTRL_ENABLE_LUT 0x02000000
-#define BF_PXP_CTRL_ENABLE_LUT(v)  \
-       (((v) << 25) & BM_PXP_CTRL_ENABLE_LUT)
-#define BM_PXP_CTRL_ENABLE_CSC2 0x01000000
-#define BF_PXP_CTRL_ENABLE_CSC2(v)  \
-       (((v) << 24) & BM_PXP_CTRL_ENABLE_CSC2)
-#define BM_PXP_CTRL_BLOCK_SIZE 0x00800000
-#define BF_PXP_CTRL_BLOCK_SIZE(v)  \
-       (((v) << 23) & BM_PXP_CTRL_BLOCK_SIZE)
-#define BV_PXP_CTRL_BLOCK_SIZE__8X8   0x0
-#define BV_PXP_CTRL_BLOCK_SIZE__16X16 0x1
-#define BM_PXP_CTRL_RSVD1 0x00400000
-#define BF_PXP_CTRL_RSVD1(v)  \
-       (((v) << 22) & BM_PXP_CTRL_RSVD1)
-#define BM_PXP_CTRL_ENABLE_ALPHA_B 0x00200000
-#define BF_PXP_CTRL_ENABLE_ALPHA_B(v)  \
-       (((v) << 21) & BM_PXP_CTRL_ENABLE_ALPHA_B)
-#define BM_PXP_CTRL_ENABLE_INPUT_FETCH_STORE 0x00100000
-#define BF_PXP_CTRL_ENABLE_INPUT_FETCH_STORE(v)  \
-       (((v) << 20) & BM_PXP_CTRL_ENABLE_INPUT_FETCH_STORE)
-#define BM_PXP_CTRL_ENABLE_WFE_B 0x00080000
-#define BF_PXP_CTRL_ENABLE_WFE_B(v)  \
-       (((v) << 19) & BM_PXP_CTRL_ENABLE_WFE_B)
-#define BM_PXP_CTRL_ENABLE_WFE_A 0x00040000
-#define BF_PXP_CTRL_ENABLE_WFE_A(v)  \
-       (((v) << 18) & BM_PXP_CTRL_ENABLE_WFE_A)
-#define BM_PXP_CTRL_ENABLE_DITHER 0x00020000
-#define BF_PXP_CTRL_ENABLE_DITHER(v)  \
-       (((v) << 17) & BM_PXP_CTRL_ENABLE_DITHER)
-#define BM_PXP_CTRL_ENABLE_PS_AS_OUT 0x00010000
-#define BF_PXP_CTRL_ENABLE_PS_AS_OUT(v)  \
-       (((v) << 16) & BM_PXP_CTRL_ENABLE_PS_AS_OUT)
-#define BM_PXP_CTRL_VFLIP1 0x00008000
-#define BF_PXP_CTRL_VFLIP1(v)  \
-       (((v) << 15) & BM_PXP_CTRL_VFLIP1)
-#define BM_PXP_CTRL_HFLIP1 0x00004000
-#define BF_PXP_CTRL_HFLIP1(v)  \
-       (((v) << 14) & BM_PXP_CTRL_HFLIP1)
-#define BP_PXP_CTRL_ROTATE1      12
-#define BM_PXP_CTRL_ROTATE1 0x00003000
-#define BF_PXP_CTRL_ROTATE1(v)  \
-       (((v) << 12) & BM_PXP_CTRL_ROTATE1)
-#define BV_PXP_CTRL_ROTATE1__ROT_0   0x0
-#define BV_PXP_CTRL_ROTATE1__ROT_90  0x1
-#define BV_PXP_CTRL_ROTATE1__ROT_180 0x2
-#define BV_PXP_CTRL_ROTATE1__ROT_270 0x3
-#define BM_PXP_CTRL_VFLIP0 0x00000800
-#define BF_PXP_CTRL_VFLIP0(v)  \
-       (((v) << 11) & BM_PXP_CTRL_VFLIP0)
-#define BM_PXP_CTRL_HFLIP0 0x00000400
-#define BF_PXP_CTRL_HFLIP0(v)  \
-       (((v) << 10) & BM_PXP_CTRL_HFLIP0)
-#define BP_PXP_CTRL_ROTATE0      8
-#define BM_PXP_CTRL_ROTATE0 0x00000300
-#define BF_PXP_CTRL_ROTATE0(v)  \
-       (((v) << 8) & BM_PXP_CTRL_ROTATE0)
-#define BV_PXP_CTRL_ROTATE0__ROT_0   0x0
-#define BV_PXP_CTRL_ROTATE0__ROT_90  0x1
-#define BV_PXP_CTRL_ROTATE0__ROT_180 0x2
-#define BV_PXP_CTRL_ROTATE0__ROT_270 0x3
-#define BP_PXP_CTRL_RSVD0      6
-#define BM_PXP_CTRL_RSVD0 0x000000C0
-#define BF_PXP_CTRL_RSVD0(v)  \
-       (((v) << 6) & BM_PXP_CTRL_RSVD0)
-#define BM_PXP_CTRL_HANDSHAKE_ABORT_SKIP 0x00000020
-#define BF_PXP_CTRL_HANDSHAKE_ABORT_SKIP(v)  \
-       (((v) << 5) & BM_PXP_CTRL_HANDSHAKE_ABORT_SKIP)
-#define BM_PXP_CTRL_ENABLE_LCD0_HANDSHAKE 0x00000010
-#define BF_PXP_CTRL_ENABLE_LCD0_HANDSHAKE(v)  \
-       (((v) << 4) & BM_PXP_CTRL_ENABLE_LCD0_HANDSHAKE)
-#define BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE 0x00000008
-#define BF_PXP_CTRL_LUT_DMA_IRQ_ENABLE(v)  \
-       (((v) << 3) & BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE)
-#define BM_PXP_CTRL_NEXT_IRQ_ENABLE 0x00000004
-#define BF_PXP_CTRL_NEXT_IRQ_ENABLE(v)  \
-       (((v) << 2) & BM_PXP_CTRL_NEXT_IRQ_ENABLE)
-#define BM_PXP_CTRL_IRQ_ENABLE 0x00000002
-#define BF_PXP_CTRL_IRQ_ENABLE(v)  \
-       (((v) << 1) & BM_PXP_CTRL_IRQ_ENABLE)
-#define BM_PXP_CTRL_ENABLE 0x00000001
-#define BF_PXP_CTRL_ENABLE(v)  \
-       (((v) << 0) & BM_PXP_CTRL_ENABLE)
-
-#define HW_PXP_STAT    (0x00000010)
-#define HW_PXP_STAT_SET        (0x00000014)
-#define HW_PXP_STAT_CLR        (0x00000018)
-#define HW_PXP_STAT_TOG        (0x0000001c)
-
-#define BP_PXP_STAT_BLOCKX      24
-#define BM_PXP_STAT_BLOCKX 0xFF000000
-#define BF_PXP_STAT_BLOCKX(v) \
-       (((v) << 24) & BM_PXP_STAT_BLOCKX)
-#define BP_PXP_STAT_BLOCKY      16
-#define BM_PXP_STAT_BLOCKY 0x00FF0000
-#define BF_PXP_STAT_BLOCKY(v)  \
-       (((v) << 16) & BM_PXP_STAT_BLOCKY)
-#define BP_PXP_STAT_AXI_ERROR_ID_1      12
-#define BM_PXP_STAT_AXI_ERROR_ID_1 0x0000F000
-#define BF_PXP_STAT_AXI_ERROR_ID_1(v)  \
-       (((v) << 12) & BM_PXP_STAT_AXI_ERROR_ID_1)
-#define BM_PXP_STAT_RSVD2 0x00000800
-#define BF_PXP_STAT_RSVD2(v)  \
-       (((v) << 11) & BM_PXP_STAT_RSVD2)
-#define BM_PXP_STAT_AXI_READ_ERROR_1 0x00000400
-#define BF_PXP_STAT_AXI_READ_ERROR_1(v)  \
-       (((v) << 10) & BM_PXP_STAT_AXI_READ_ERROR_1)
-#define BM_PXP_STAT_AXI_WRITE_ERROR_1 0x00000200
-#define BF_PXP_STAT_AXI_WRITE_ERROR_1(v)  \
-       (((v) << 9) & BM_PXP_STAT_AXI_WRITE_ERROR_1)
-#define BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ 0x00000100
-#define BF_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ(v)  \
-       (((v) << 8) & BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ)
-#define BP_PXP_STAT_AXI_ERROR_ID_0      4
-#define BM_PXP_STAT_AXI_ERROR_ID_0 0x000000F0
-#define BF_PXP_STAT_AXI_ERROR_ID_0(v)  \
-       (((v) << 4) & BM_PXP_STAT_AXI_ERROR_ID_0)
-#define BM_PXP_STAT_NEXT_IRQ 0x00000008
-#define BF_PXP_STAT_NEXT_IRQ(v)  \
-       (((v) << 3) & BM_PXP_STAT_NEXT_IRQ)
-#define BM_PXP_STAT_AXI_READ_ERROR_0 0x00000004
-#define BF_PXP_STAT_AXI_READ_ERROR_0(v)  \
-       (((v) << 2) & BM_PXP_STAT_AXI_READ_ERROR_0)
-#define BM_PXP_STAT_AXI_WRITE_ERROR_0 0x00000002
-#define BF_PXP_STAT_AXI_WRITE_ERROR_0(v)  \
-       (((v) << 1) & BM_PXP_STAT_AXI_WRITE_ERROR_0)
-#define BM_PXP_STAT_IRQ0 0x00000001
-#define BF_PXP_STAT_IRQ0(v)  \
-       (((v) << 0) & BM_PXP_STAT_IRQ0)
-
-#define HW_PXP_OUT_CTRL        (0x00000020)
-#define HW_PXP_OUT_CTRL_SET    (0x00000024)
-#define HW_PXP_OUT_CTRL_CLR    (0x00000028)
-#define HW_PXP_OUT_CTRL_TOG    (0x0000002c)
-
-#define BP_PXP_OUT_CTRL_ALPHA      24
-#define BM_PXP_OUT_CTRL_ALPHA 0xFF000000
-#define BF_PXP_OUT_CTRL_ALPHA(v) \
-       (((v) << 24) & BM_PXP_OUT_CTRL_ALPHA)
-#define BM_PXP_OUT_CTRL_ALPHA_OUTPUT 0x00800000
-#define BF_PXP_OUT_CTRL_ALPHA_OUTPUT(v)  \
-       (((v) << 23) & BM_PXP_OUT_CTRL_ALPHA_OUTPUT)
-#define BP_PXP_OUT_CTRL_RSVD1      10
-#define BM_PXP_OUT_CTRL_RSVD1 0x007FFC00
-#define BF_PXP_OUT_CTRL_RSVD1(v)  \
-       (((v) << 10) & BM_PXP_OUT_CTRL_RSVD1)
-#define BP_PXP_OUT_CTRL_INTERLACED_OUTPUT      8
-#define BM_PXP_OUT_CTRL_INTERLACED_OUTPUT 0x00000300
-#define BF_PXP_OUT_CTRL_INTERLACED_OUTPUT(v)  \
-       (((v) << 8) & BM_PXP_OUT_CTRL_INTERLACED_OUTPUT)
-#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__PROGRESSIVE 0x0
-#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD0      0x1
-#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD1      0x2
-#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__INTERLACED  0x3
-#define BP_PXP_OUT_CTRL_RSVD0      5
-#define BM_PXP_OUT_CTRL_RSVD0 0x000000E0
-#define BF_PXP_OUT_CTRL_RSVD0(v)  \
-       (((v) << 5) & BM_PXP_OUT_CTRL_RSVD0)
-#define BP_PXP_OUT_CTRL_FORMAT      0
-#define BM_PXP_OUT_CTRL_FORMAT 0x0000001F
-#define BF_PXP_OUT_CTRL_FORMAT(v)  \
-       (((v) << 0) & BM_PXP_OUT_CTRL_FORMAT)
-#define BV_PXP_OUT_CTRL_FORMAT__ARGB8888  0x0
-#define BV_PXP_OUT_CTRL_FORMAT__RGB888    0x4
-#define BV_PXP_OUT_CTRL_FORMAT__RGB888P   0x5
-#define BV_PXP_OUT_CTRL_FORMAT__ARGB1555  0x8
-#define BV_PXP_OUT_CTRL_FORMAT__ARGB4444  0x9
-#define BV_PXP_OUT_CTRL_FORMAT__RGB555    0xC
-#define BV_PXP_OUT_CTRL_FORMAT__RGB444    0xD
-#define BV_PXP_OUT_CTRL_FORMAT__RGB565    0xE
-#define BV_PXP_OUT_CTRL_FORMAT__YUV1P444  0x10
-#define BV_PXP_OUT_CTRL_FORMAT__UYVY1P422 0x12
-#define BV_PXP_OUT_CTRL_FORMAT__VYUY1P422 0x13
-#define BV_PXP_OUT_CTRL_FORMAT__Y8     0x14
-#define BV_PXP_OUT_CTRL_FORMAT__Y4     0x15
-#define BV_PXP_OUT_CTRL_FORMAT__YUV2P422  0x18
-#define BV_PXP_OUT_CTRL_FORMAT__YUV2P420  0x19
-#define BV_PXP_OUT_CTRL_FORMAT__YVU2P422  0x1A
-#define BV_PXP_OUT_CTRL_FORMAT__YVU2P420  0x1B
-
-#define HW_PXP_OUT_BUF (0x00000030)
-
-#define BP_PXP_OUT_BUF_ADDR      0
-#define BM_PXP_OUT_BUF_ADDR 0xFFFFFFFF
-#define BF_PXP_OUT_BUF_ADDR(v)   (v)
-
-#define HW_PXP_OUT_BUF2        (0x00000040)
-
-#define BP_PXP_OUT_BUF2_ADDR      0
-#define BM_PXP_OUT_BUF2_ADDR 0xFFFFFFFF
-#define BF_PXP_OUT_BUF2_ADDR(v)   (v)
-
-#define HW_PXP_OUT_PITCH       (0x00000050)
-
-#define BP_PXP_OUT_PITCH_RSVD      16
-#define BM_PXP_OUT_PITCH_RSVD 0xFFFF0000
-#define BF_PXP_OUT_PITCH_RSVD(v) \
-       (((v) << 16) & BM_PXP_OUT_PITCH_RSVD)
-#define BP_PXP_OUT_PITCH_PITCH      0
-#define BM_PXP_OUT_PITCH_PITCH 0x0000FFFF
-#define BF_PXP_OUT_PITCH_PITCH(v)  \
-       (((v) << 0) & BM_PXP_OUT_PITCH_PITCH)
-
-#define HW_PXP_OUT_LRC (0x00000060)
-
-#define BP_PXP_OUT_LRC_RSVD1      30
-#define BM_PXP_OUT_LRC_RSVD1 0xC0000000
-#define BF_PXP_OUT_LRC_RSVD1(v) \
-       (((v) << 30) & BM_PXP_OUT_LRC_RSVD1)
-#define BP_PXP_OUT_LRC_X      16
-#define BM_PXP_OUT_LRC_X 0x3FFF0000
-#define BF_PXP_OUT_LRC_X(v)  \
-       (((v) << 16) & BM_PXP_OUT_LRC_X)
-#define BP_PXP_OUT_LRC_RSVD0      14
-#define BM_PXP_OUT_LRC_RSVD0 0x0000C000
-#define BF_PXP_OUT_LRC_RSVD0(v)  \
-       (((v) << 14) & BM_PXP_OUT_LRC_RSVD0)
-#define BP_PXP_OUT_LRC_Y      0
-#define BM_PXP_OUT_LRC_Y 0x00003FFF
-#define BF_PXP_OUT_LRC_Y(v)  \
-       (((v) << 0) & BM_PXP_OUT_LRC_Y)
-
-#define HW_PXP_OUT_PS_ULC      (0x00000070)
-
-#define BP_PXP_OUT_PS_ULC_RSVD1      30
-#define BM_PXP_OUT_PS_ULC_RSVD1 0xC0000000
-#define BF_PXP_OUT_PS_ULC_RSVD1(v) \
-       (((v) << 30) & BM_PXP_OUT_PS_ULC_RSVD1)
-#define BP_PXP_OUT_PS_ULC_X      16
-#define BM_PXP_OUT_PS_ULC_X 0x3FFF0000
-#define BF_PXP_OUT_PS_ULC_X(v)  \
-       (((v) << 16) & BM_PXP_OUT_PS_ULC_X)
-#define BP_PXP_OUT_PS_ULC_RSVD0      14
-#define BM_PXP_OUT_PS_ULC_RSVD0 0x0000C000
-#define BF_PXP_OUT_PS_ULC_RSVD0(v)  \
-       (((v) << 14) & BM_PXP_OUT_PS_ULC_RSVD0)
-#define BP_PXP_OUT_PS_ULC_Y      0
-#define BM_PXP_OUT_PS_ULC_Y 0x00003FFF
-#define BF_PXP_OUT_PS_ULC_Y(v)  \
-       (((v) << 0) & BM_PXP_OUT_PS_ULC_Y)
-
-#define HW_PXP_OUT_PS_LRC      (0x00000080)
-
-#define BP_PXP_OUT_PS_LRC_RSVD1      30
-#define BM_PXP_OUT_PS_LRC_RSVD1 0xC0000000
-#define BF_PXP_OUT_PS_LRC_RSVD1(v) \
-       (((v) << 30) & BM_PXP_OUT_PS_LRC_RSVD1)
-#define BP_PXP_OUT_PS_LRC_X      16
-#define BM_PXP_OUT_PS_LRC_X 0x3FFF0000
-#define BF_PXP_OUT_PS_LRC_X(v)  \
-       (((v) << 16) & BM_PXP_OUT_PS_LRC_X)
-#define BP_PXP_OUT_PS_LRC_RSVD0      14
-#define BM_PXP_OUT_PS_LRC_RSVD0 0x0000C000
-#define BF_PXP_OUT_PS_LRC_RSVD0(v)  \
-       (((v) << 14) & BM_PXP_OUT_PS_LRC_RSVD0)
-#define BP_PXP_OUT_PS_LRC_Y      0
-#define BM_PXP_OUT_PS_LRC_Y 0x00003FFF
-#define BF_PXP_OUT_PS_LRC_Y(v)  \
-       (((v) << 0) & BM_PXP_OUT_PS_LRC_Y)
-
-#define HW_PXP_OUT_AS_ULC      (0x00000090)
-
-#define BP_PXP_OUT_AS_ULC_RSVD1      30
-#define BM_PXP_OUT_AS_ULC_RSVD1 0xC0000000
-#define BF_PXP_OUT_AS_ULC_RSVD1(v) \
-       (((v) << 30) & BM_PXP_OUT_AS_ULC_RSVD1)
-#define BP_PXP_OUT_AS_ULC_X      16
-#define BM_PXP_OUT_AS_ULC_X 0x3FFF0000
-#define BF_PXP_OUT_AS_ULC_X(v)  \
-       (((v) << 16) & BM_PXP_OUT_AS_ULC_X)
-#define BP_PXP_OUT_AS_ULC_RSVD0      14
-#define BM_PXP_OUT_AS_ULC_RSVD0 0x0000C000
-#define BF_PXP_OUT_AS_ULC_RSVD0(v)  \
-       (((v) << 14) & BM_PXP_OUT_AS_ULC_RSVD0)
-#define BP_PXP_OUT_AS_ULC_Y      0
-#define BM_PXP_OUT_AS_ULC_Y 0x00003FFF
-#define BF_PXP_OUT_AS_ULC_Y(v)  \
-       (((v) << 0) & BM_PXP_OUT_AS_ULC_Y)
-
-#define HW_PXP_OUT_AS_LRC      (0x000000a0)
-
-#define BP_PXP_OUT_AS_LRC_RSVD1      30
-#define BM_PXP_OUT_AS_LRC_RSVD1 0xC0000000
-#define BF_PXP_OUT_AS_LRC_RSVD1(v) \
-       (((v) << 30) & BM_PXP_OUT_AS_LRC_RSVD1)
-#define BP_PXP_OUT_AS_LRC_X      16
-#define BM_PXP_OUT_AS_LRC_X 0x3FFF0000
-#define BF_PXP_OUT_AS_LRC_X(v)  \
-       (((v) << 16) & BM_PXP_OUT_AS_LRC_X)
-#define BP_PXP_OUT_AS_LRC_RSVD0      14
-#define BM_PXP_OUT_AS_LRC_RSVD0 0x0000C000
-#define BF_PXP_OUT_AS_LRC_RSVD0(v)  \
-       (((v) << 14) & BM_PXP_OUT_AS_LRC_RSVD0)
-#define BP_PXP_OUT_AS_LRC_Y      0
-#define BM_PXP_OUT_AS_LRC_Y 0x00003FFF
-#define BF_PXP_OUT_AS_LRC_Y(v)  \
-       (((v) << 0) & BM_PXP_OUT_AS_LRC_Y)
-
-#define HW_PXP_PS_CTRL (0x000000b0)
-#define HW_PXP_PS_CTRL_SET     (0x000000b4)
-#define HW_PXP_PS_CTRL_CLR     (0x000000b8)
-#define HW_PXP_PS_CTRL_TOG     (0x000000bc)
-
-#define BP_PXP_PS_CTRL_RSVD1      12
-#define BM_PXP_PS_CTRL_RSVD1 0xFFFFF000
-#define BF_PXP_PS_CTRL_RSVD1(v) \
-       (((v) << 12) & BM_PXP_PS_CTRL_RSVD1)
-#define BP_PXP_PS_CTRL_DECX      10
-#define BM_PXP_PS_CTRL_DECX 0x00000C00
-#define BF_PXP_PS_CTRL_DECX(v)  \
-       (((v) << 10) & BM_PXP_PS_CTRL_DECX)
-#define BV_PXP_PS_CTRL_DECX__DISABLE 0x0
-#define BV_PXP_PS_CTRL_DECX__DECX2   0x1
-#define BV_PXP_PS_CTRL_DECX__DECX4   0x2
-#define BV_PXP_PS_CTRL_DECX__DECX8   0x3
-#define BP_PXP_PS_CTRL_DECY      8
-#define BM_PXP_PS_CTRL_DECY 0x00000300
-#define BF_PXP_PS_CTRL_DECY(v)  \
-       (((v) << 8) & BM_PXP_PS_CTRL_DECY)
-#define BV_PXP_PS_CTRL_DECY__DISABLE 0x0
-#define BV_PXP_PS_CTRL_DECY__DECY2   0x1
-#define BV_PXP_PS_CTRL_DECY__DECY4   0x2
-#define BV_PXP_PS_CTRL_DECY__DECY8   0x3
-#define BM_PXP_PS_CTRL_RSVD0 0x00000080
-#define BF_PXP_PS_CTRL_RSVD0(v)  \
-       (((v) << 7) & BM_PXP_PS_CTRL_RSVD0)
-#define BM_PXP_PS_CTRL_WB_SWAP 0x00000040
-#define BF_PXP_PS_CTRL_WB_SWAP(v)  \
-       (((v) << 6) & BM_PXP_PS_CTRL_WB_SWAP)
-#define BP_PXP_PS_CTRL_FORMAT      0
-#define BM_PXP_PS_CTRL_FORMAT 0x0000003F
-#define BF_PXP_PS_CTRL_FORMAT(v)  \
-       (((v) << 0) & BM_PXP_PS_CTRL_FORMAT)
-#define BV_PXP_PS_CTRL_FORMAT__RGB888    0x4
-#define BV_PXP_PS_CTRL_FORMAT__RGB555    0xC
-#define BV_PXP_PS_CTRL_FORMAT__RGB444    0xD
-#define BV_PXP_PS_CTRL_FORMAT__RGB565    0xE
-#define BV_PXP_PS_CTRL_FORMAT__YUV1P444  0x10
-#define BV_PXP_PS_CTRL_FORMAT__UYVY1P422 0x12
-#define BV_PXP_PS_CTRL_FORMAT__VYUY1P422 0x13
-#define BV_PXP_PS_CTRL_FORMAT__Y8      0x14
-#define BV_PXP_PS_CTRL_FORMAT__Y4      0x15
-#define BV_PXP_PS_CTRL_FORMAT__YUV2P422  0x18
-#define BV_PXP_PS_CTRL_FORMAT__YUV2P420  0x19
-#define BV_PXP_PS_CTRL_FORMAT__YVU2P422  0x1A
-#define BV_PXP_PS_CTRL_FORMAT__YVU2P420  0x1B
-#define BV_PXP_PS_CTRL_FORMAT__YUV422    0x1E
-#define BV_PXP_PS_CTRL_FORMAT__YUV420    0x1F
-
-#define HW_PXP_PS_BUF  (0x000000c0)
-
-#define BP_PXP_PS_BUF_ADDR      0
-#define BM_PXP_PS_BUF_ADDR 0xFFFFFFFF
-#define BF_PXP_PS_BUF_ADDR(v)   (v)
-
-#define HW_PXP_PS_UBUF (0x000000d0)
-
-#define BP_PXP_PS_UBUF_ADDR      0
-#define BM_PXP_PS_UBUF_ADDR 0xFFFFFFFF
-#define BF_PXP_PS_UBUF_ADDR(v)   (v)
-
-#define HW_PXP_PS_VBUF (0x000000e0)
-
-#define BP_PXP_PS_VBUF_ADDR      0
-#define BM_PXP_PS_VBUF_ADDR 0xFFFFFFFF
-#define BF_PXP_PS_VBUF_ADDR(v)   (v)
-
-#define HW_PXP_PS_PITCH        (0x000000f0)
-
-#define BP_PXP_PS_PITCH_RSVD      16
-#define BM_PXP_PS_PITCH_RSVD 0xFFFF0000
-#define BF_PXP_PS_PITCH_RSVD(v) \
-       (((v) << 16) & BM_PXP_PS_PITCH_RSVD)
-#define BP_PXP_PS_PITCH_PITCH      0
-#define BM_PXP_PS_PITCH_PITCH 0x0000FFFF
-#define BF_PXP_PS_PITCH_PITCH(v)  \
-       (((v) << 0) & BM_PXP_PS_PITCH_PITCH)
-
-#define HW_PXP_PS_BACKGROUND_0 (0x00000100)
-
-#define BP_PXP_PS_BACKGROUND_0_RSVD      24
-#define BM_PXP_PS_BACKGROUND_0_RSVD 0xFF000000
-#define BF_PXP_PS_BACKGROUND_0_RSVD(v) \
-       (((v) << 24) & BM_PXP_PS_BACKGROUND_0_RSVD)
-#define BP_PXP_PS_BACKGROUND_0_COLOR      0
-#define BM_PXP_PS_BACKGROUND_0_COLOR 0x00FFFFFF
-#define BF_PXP_PS_BACKGROUND_0_COLOR(v)  \
-       (((v) << 0) & BM_PXP_PS_BACKGROUND_0_COLOR)
-
-#define HW_PXP_PS_SCALE        (0x00000110)
-
-#define BM_PXP_PS_SCALE_RSVD2 0x80000000
-#define BF_PXP_PS_SCALE_RSVD2(v) \
-       (((v) << 31) & BM_PXP_PS_SCALE_RSVD2)
-#define BP_PXP_PS_SCALE_YSCALE      16
-#define BM_PXP_PS_SCALE_YSCALE 0x7FFF0000
-#define BF_PXP_PS_SCALE_YSCALE(v)  \
-       (((v) << 16) & BM_PXP_PS_SCALE_YSCALE)
-#define BM_PXP_PS_SCALE_RSVD1 0x00008000
-#define BF_PXP_PS_SCALE_RSVD1(v)  \
-       (((v) << 15) & BM_PXP_PS_SCALE_RSVD1)
-#define BP_PXP_PS_SCALE_XSCALE      0
-#define BM_PXP_PS_SCALE_XSCALE 0x00007FFF
-#define BF_PXP_PS_SCALE_XSCALE(v)  \
-       (((v) << 0) & BM_PXP_PS_SCALE_XSCALE)
-
-#define HW_PXP_PS_OFFSET       (0x00000120)
-
-#define BP_PXP_PS_OFFSET_RSVD2      28
-#define BM_PXP_PS_OFFSET_RSVD2 0xF0000000
-#define BF_PXP_PS_OFFSET_RSVD2(v) \
-       (((v) << 28) & BM_PXP_PS_OFFSET_RSVD2)
-#define BP_PXP_PS_OFFSET_YOFFSET      16
-#define BM_PXP_PS_OFFSET_YOFFSET 0x0FFF0000
-#define BF_PXP_PS_OFFSET_YOFFSET(v)  \
-       (((v) << 16) & BM_PXP_PS_OFFSET_YOFFSET)
-#define BP_PXP_PS_OFFSET_RSVD1      12
-#define BM_PXP_PS_OFFSET_RSVD1 0x0000F000
-#define BF_PXP_PS_OFFSET_RSVD1(v)  \
-       (((v) << 12) & BM_PXP_PS_OFFSET_RSVD1)
-#define BP_PXP_PS_OFFSET_XOFFSET      0
-#define BM_PXP_PS_OFFSET_XOFFSET 0x00000FFF
-#define BF_PXP_PS_OFFSET_XOFFSET(v)  \
-       (((v) << 0) & BM_PXP_PS_OFFSET_XOFFSET)
-
-#define HW_PXP_PS_CLRKEYLOW_0  (0x00000130)
-
-#define BP_PXP_PS_CLRKEYLOW_0_RSVD1      24
-#define BM_PXP_PS_CLRKEYLOW_0_RSVD1 0xFF000000
-#define BF_PXP_PS_CLRKEYLOW_0_RSVD1(v) \
-       (((v) << 24) & BM_PXP_PS_CLRKEYLOW_0_RSVD1)
-#define BP_PXP_PS_CLRKEYLOW_0_PIXEL      0
-#define BM_PXP_PS_CLRKEYLOW_0_PIXEL 0x00FFFFFF
-#define BF_PXP_PS_CLRKEYLOW_0_PIXEL(v)  \
-       (((v) << 0) & BM_PXP_PS_CLRKEYLOW_0_PIXEL)
-
-#define HW_PXP_PS_CLRKEYHIGH_0 (0x00000140)
-
-#define BP_PXP_PS_CLRKEYHIGH_0_RSVD1      24
-#define BM_PXP_PS_CLRKEYHIGH_0_RSVD1 0xFF000000
-#define BF_PXP_PS_CLRKEYHIGH_0_RSVD1(v) \
-       (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_0_RSVD1)
-#define BP_PXP_PS_CLRKEYHIGH_0_PIXEL      0
-#define BM_PXP_PS_CLRKEYHIGH_0_PIXEL 0x00FFFFFF
-#define BF_PXP_PS_CLRKEYHIGH_0_PIXEL(v)  \
-       (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_0_PIXEL)
-
-#define HW_PXP_AS_CTRL (0x00000150)
-
-#define BP_PXP_AS_CTRL_RSVD1      22
-#define BM_PXP_AS_CTRL_RSVD1 0xFFC00000
-#define BF_PXP_AS_CTRL_RSVD1(v) \
-       (((v) << 22) & BM_PXP_AS_CTRL_RSVD1)
-#define BM_PXP_AS_CTRL_ALPHA1_INVERT 0x00200000
-#define BF_PXP_AS_CTRL_ALPHA1_INVERT(v)  \
-       (((v) << 21) & BM_PXP_AS_CTRL_ALPHA1_INVERT)
-#define BM_PXP_AS_CTRL_ALPHA0_INVERT 0x00100000
-#define BF_PXP_AS_CTRL_ALPHA0_INVERT(v)  \
-       (((v) << 20) & BM_PXP_AS_CTRL_ALPHA0_INVERT)
-#define BP_PXP_AS_CTRL_ROP      16
-#define BM_PXP_AS_CTRL_ROP 0x000F0000
-#define BF_PXP_AS_CTRL_ROP(v)  \
-       (((v) << 16) & BM_PXP_AS_CTRL_ROP)
-#define BV_PXP_AS_CTRL_ROP__MASKAS     0x0
-#define BV_PXP_AS_CTRL_ROP__MASKNOTAS  0x1
-#define BV_PXP_AS_CTRL_ROP__MASKASNOT  0x2
-#define BV_PXP_AS_CTRL_ROP__MERGEAS    0x3
-#define BV_PXP_AS_CTRL_ROP__MERGENOTAS 0x4
-#define BV_PXP_AS_CTRL_ROP__MERGEASNOT 0x5
-#define BV_PXP_AS_CTRL_ROP__NOTCOPYAS  0x6
-#define BV_PXP_AS_CTRL_ROP__NOT        0x7
-#define BV_PXP_AS_CTRL_ROP__NOTMASKAS  0x8
-#define BV_PXP_AS_CTRL_ROP__NOTMERGEAS 0x9
-#define BV_PXP_AS_CTRL_ROP__XORAS      0xA
-#define BV_PXP_AS_CTRL_ROP__NOTXORAS   0xB
-#define BP_PXP_AS_CTRL_ALPHA      8
-#define BM_PXP_AS_CTRL_ALPHA 0x0000FF00
-#define BF_PXP_AS_CTRL_ALPHA(v)  \
-       (((v) << 8) & BM_PXP_AS_CTRL_ALPHA)
-#define BP_PXP_AS_CTRL_FORMAT      4
-#define BM_PXP_AS_CTRL_FORMAT 0x000000F0
-#define BF_PXP_AS_CTRL_FORMAT(v)  \
-       (((v) << 4) & BM_PXP_AS_CTRL_FORMAT)
-#define BV_PXP_AS_CTRL_FORMAT__ARGB8888 0x0
-#define BV_PXP_AS_CTRL_FORMAT__RGBA8888 0x1
-#define BV_PXP_AS_CTRL_FORMAT__RGB888   0x4
-#define BV_PXP_AS_CTRL_FORMAT__ARGB1555 0x8
-#define BV_PXP_AS_CTRL_FORMAT__ARGB4444 0x9
-#define BV_PXP_AS_CTRL_FORMAT__RGB555   0xC
-#define BV_PXP_AS_CTRL_FORMAT__RGB444   0xD
-#define BV_PXP_AS_CTRL_FORMAT__RGB565   0xE
-#define BM_PXP_AS_CTRL_ENABLE_COLORKEY 0x00000008
-#define BF_PXP_AS_CTRL_ENABLE_COLORKEY(v)  \
-       (((v) << 3) & BM_PXP_AS_CTRL_ENABLE_COLORKEY)
-#define BP_PXP_AS_CTRL_ALPHA_CTRL      1
-#define BM_PXP_AS_CTRL_ALPHA_CTRL 0x00000006
-#define BF_PXP_AS_CTRL_ALPHA_CTRL(v)  \
-       (((v) << 1) & BM_PXP_AS_CTRL_ALPHA_CTRL)
-#define BV_PXP_AS_CTRL_ALPHA_CTRL__Embedded 0x0
-#define BV_PXP_AS_CTRL_ALPHA_CTRL__Override 0x1
-#define BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply 0x2
-#define BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs     0x3
-#define BM_PXP_AS_CTRL_RSVD0 0x00000001
-#define BF_PXP_AS_CTRL_RSVD0(v)  \
-       (((v) << 0) & BM_PXP_AS_CTRL_RSVD0)
-
-#define HW_PXP_AS_BUF  (0x00000160)
-
-#define BP_PXP_AS_BUF_ADDR      0
-#define BM_PXP_AS_BUF_ADDR 0xFFFFFFFF
-#define BF_PXP_AS_BUF_ADDR(v)   (v)
-
-#define HW_PXP_AS_PITCH        (0x00000170)
-
-#define BP_PXP_AS_PITCH_RSVD      16
-#define BM_PXP_AS_PITCH_RSVD 0xFFFF0000
-#define BF_PXP_AS_PITCH_RSVD(v) \
-       (((v) << 16) & BM_PXP_AS_PITCH_RSVD)
-#define BP_PXP_AS_PITCH_PITCH      0
-#define BM_PXP_AS_PITCH_PITCH 0x0000FFFF
-#define BF_PXP_AS_PITCH_PITCH(v)  \
-       (((v) << 0) & BM_PXP_AS_PITCH_PITCH)
-
-#define HW_PXP_AS_CLRKEYLOW_0  (0x00000180)
-
-#define BP_PXP_AS_CLRKEYLOW_0_RSVD1      24
-#define BM_PXP_AS_CLRKEYLOW_0_RSVD1 0xFF000000
-#define BF_PXP_AS_CLRKEYLOW_0_RSVD1(v) \
-       (((v) << 24) & BM_PXP_AS_CLRKEYLOW_0_RSVD1)
-#define BP_PXP_AS_CLRKEYLOW_0_PIXEL      0
-#define BM_PXP_AS_CLRKEYLOW_0_PIXEL 0x00FFFFFF
-#define BF_PXP_AS_CLRKEYLOW_0_PIXEL(v)  \
-       (((v) << 0) & BM_PXP_AS_CLRKEYLOW_0_PIXEL)
-
-#define HW_PXP_AS_CLRKEYHIGH_0 (0x00000190)
-
-#define BP_PXP_AS_CLRKEYHIGH_0_RSVD1      24
-#define BM_PXP_AS_CLRKEYHIGH_0_RSVD1 0xFF000000
-#define BF_PXP_AS_CLRKEYHIGH_0_RSVD1(v) \
-       (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_0_RSVD1)
-#define BP_PXP_AS_CLRKEYHIGH_0_PIXEL      0
-#define BM_PXP_AS_CLRKEYHIGH_0_PIXEL 0x00FFFFFF
-#define BF_PXP_AS_CLRKEYHIGH_0_PIXEL(v)  \
-       (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_0_PIXEL)
-
-#define HW_PXP_CSC1_COEF0      (0x000001a0)
-
-#define BM_PXP_CSC1_COEF0_YCBCR_MODE 0x80000000
-#define BF_PXP_CSC1_COEF0_YCBCR_MODE(v) \
-       (((v) << 31) & BM_PXP_CSC1_COEF0_YCBCR_MODE)
-#define BM_PXP_CSC1_COEF0_BYPASS 0x40000000
-#define BF_PXP_CSC1_COEF0_BYPASS(v)  \
-       (((v) << 30) & BM_PXP_CSC1_COEF0_BYPASS)
-#define BM_PXP_CSC1_COEF0_RSVD1 0x20000000
-#define BF_PXP_CSC1_COEF0_RSVD1(v)  \
-       (((v) << 29) & BM_PXP_CSC1_COEF0_RSVD1)
-#define BP_PXP_CSC1_COEF0_C0      18
-#define BM_PXP_CSC1_COEF0_C0 0x1FFC0000
-#define BF_PXP_CSC1_COEF0_C0(v)  \
-       (((v) << 18) & BM_PXP_CSC1_COEF0_C0)
-#define BP_PXP_CSC1_COEF0_UV_OFFSET      9
-#define BM_PXP_CSC1_COEF0_UV_OFFSET 0x0003FE00
-#define BF_PXP_CSC1_COEF0_UV_OFFSET(v)  \
-       (((v) << 9) & BM_PXP_CSC1_COEF0_UV_OFFSET)
-#define BP_PXP_CSC1_COEF0_Y_OFFSET      0
-#define BM_PXP_CSC1_COEF0_Y_OFFSET 0x000001FF
-#define BF_PXP_CSC1_COEF0_Y_OFFSET(v)  \
-       (((v) << 0) & BM_PXP_CSC1_COEF0_Y_OFFSET)
-
-#define HW_PXP_CSC1_COEF1      (0x000001b0)
-
-#define BP_PXP_CSC1_COEF1_RSVD1      27
-#define BM_PXP_CSC1_COEF1_RSVD1 0xF8000000
-#define BF_PXP_CSC1_COEF1_RSVD1(v) \
-       (((v) << 27) & BM_PXP_CSC1_COEF1_RSVD1)
-#define BP_PXP_CSC1_COEF1_C1      16
-#define BM_PXP_CSC1_COEF1_C1 0x07FF0000
-#define BF_PXP_CSC1_COEF1_C1(v)  \
-       (((v) << 16) & BM_PXP_CSC1_COEF1_C1)
-#define BP_PXP_CSC1_COEF1_RSVD0      11
-#define BM_PXP_CSC1_COEF1_RSVD0 0x0000F800
-#define BF_PXP_CSC1_COEF1_RSVD0(v)  \
-       (((v) << 11) & BM_PXP_CSC1_COEF1_RSVD0)
-#define BP_PXP_CSC1_COEF1_C4      0
-#define BM_PXP_CSC1_COEF1_C4 0x000007FF
-#define BF_PXP_CSC1_COEF1_C4(v)  \
-       (((v) << 0) & BM_PXP_CSC1_COEF1_C4)
-
-#define HW_PXP_CSC1_COEF2      (0x000001c0)
-
-#define BP_PXP_CSC1_COEF2_RSVD1      27
-#define BM_PXP_CSC1_COEF2_RSVD1 0xF8000000
-#define BF_PXP_CSC1_COEF2_RSVD1(v) \
-       (((v) << 27) & BM_PXP_CSC1_COEF2_RSVD1)
-#define BP_PXP_CSC1_COEF2_C2      16
-#define BM_PXP_CSC1_COEF2_C2 0x07FF0000
-#define BF_PXP_CSC1_COEF2_C2(v)  \
-       (((v) << 16) & BM_PXP_CSC1_COEF2_C2)
-#define BP_PXP_CSC1_COEF2_RSVD0      11
-#define BM_PXP_CSC1_COEF2_RSVD0 0x0000F800
-#define BF_PXP_CSC1_COEF2_RSVD0(v)  \
-       (((v) << 11) & BM_PXP_CSC1_COEF2_RSVD0)
-#define BP_PXP_CSC1_COEF2_C3      0
-#define BM_PXP_CSC1_COEF2_C3 0x000007FF
-#define BF_PXP_CSC1_COEF2_C3(v)  \
-       (((v) << 0) & BM_PXP_CSC1_COEF2_C3)
-
-#define HW_PXP_CSC2_CTRL       (0x000001d0)
-
-#define BP_PXP_CSC2_CTRL_RSVD      3
-#define BM_PXP_CSC2_CTRL_RSVD 0xFFFFFFF8
-#define BF_PXP_CSC2_CTRL_RSVD(v) \
-       (((v) << 3) & BM_PXP_CSC2_CTRL_RSVD)
-#define BP_PXP_CSC2_CTRL_CSC_MODE      1
-#define BM_PXP_CSC2_CTRL_CSC_MODE 0x00000006
-#define BF_PXP_CSC2_CTRL_CSC_MODE(v)  \
-       (((v) << 1) & BM_PXP_CSC2_CTRL_CSC_MODE)
-#define BV_PXP_CSC2_CTRL_CSC_MODE__YUV2RGB   0x0
-#define BV_PXP_CSC2_CTRL_CSC_MODE__YCbCr2RGB 0x1
-#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV   0x2
-#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr 0x3
-#define BM_PXP_CSC2_CTRL_BYPASS 0x00000001
-#define BF_PXP_CSC2_CTRL_BYPASS(v)  \
-       (((v) << 0) & BM_PXP_CSC2_CTRL_BYPASS)
-
-#define HW_PXP_CSC2_COEF0      (0x000001e0)
-
-#define BP_PXP_CSC2_COEF0_RSVD1      27
-#define BM_PXP_CSC2_COEF0_RSVD1 0xF8000000
-#define BF_PXP_CSC2_COEF0_RSVD1(v) \
-       (((v) << 27) & BM_PXP_CSC2_COEF0_RSVD1)
-#define BP_PXP_CSC2_COEF0_A2      16
-#define BM_PXP_CSC2_COEF0_A2 0x07FF0000
-#define BF_PXP_CSC2_COEF0_A2(v)  \
-       (((v) << 16) & BM_PXP_CSC2_COEF0_A2)
-#define BP_PXP_CSC2_COEF0_RSVD0      11
-#define BM_PXP_CSC2_COEF0_RSVD0 0x0000F800
-#define BF_PXP_CSC2_COEF0_RSVD0(v)  \
-       (((v) << 11) & BM_PXP_CSC2_COEF0_RSVD0)
-#define BP_PXP_CSC2_COEF0_A1      0
-#define BM_PXP_CSC2_COEF0_A1 0x000007FF
-#define BF_PXP_CSC2_COEF0_A1(v)  \
-       (((v) << 0) & BM_PXP_CSC2_COEF0_A1)
-
-#define HW_PXP_CSC2_COEF1      (0x000001f0)
-
-#define BP_PXP_CSC2_COEF1_RSVD1      27
-#define BM_PXP_CSC2_COEF1_RSVD1 0xF8000000
-#define BF_PXP_CSC2_COEF1_RSVD1(v) \
-       (((v) << 27) & BM_PXP_CSC2_COEF1_RSVD1)
-#define BP_PXP_CSC2_COEF1_B1      16
-#define BM_PXP_CSC2_COEF1_B1 0x07FF0000
-#define BF_PXP_CSC2_COEF1_B1(v)  \
-       (((v) << 16) & BM_PXP_CSC2_COEF1_B1)
-#define BP_PXP_CSC2_COEF1_RSVD0      11
-#define BM_PXP_CSC2_COEF1_RSVD0 0x0000F800
-#define BF_PXP_CSC2_COEF1_RSVD0(v)  \
-       (((v) << 11) & BM_PXP_CSC2_COEF1_RSVD0)
-#define BP_PXP_CSC2_COEF1_A3      0
-#define BM_PXP_CSC2_COEF1_A3 0x000007FF
-#define BF_PXP_CSC2_COEF1_A3(v)  \
-       (((v) << 0) & BM_PXP_CSC2_COEF1_A3)
-
-#define HW_PXP_CSC2_COEF2      (0x00000200)
-
-#define BP_PXP_CSC2_COEF2_RSVD1      27
-#define BM_PXP_CSC2_COEF2_RSVD1 0xF8000000
-#define BF_PXP_CSC2_COEF2_RSVD1(v) \
-       (((v) << 27) & BM_PXP_CSC2_COEF2_RSVD1)
-#define BP_PXP_CSC2_COEF2_B3      16
-#define BM_PXP_CSC2_COEF2_B3 0x07FF0000
-#define BF_PXP_CSC2_COEF2_B3(v)  \
-       (((v) << 16) & BM_PXP_CSC2_COEF2_B3)
-#define BP_PXP_CSC2_COEF2_RSVD0      11
-#define BM_PXP_CSC2_COEF2_RSVD0 0x0000F800
-#define BF_PXP_CSC2_COEF2_RSVD0(v)  \
-       (((v) << 11) & BM_PXP_CSC2_COEF2_RSVD0)
-#define BP_PXP_CSC2_COEF2_B2      0
-#define BM_PXP_CSC2_COEF2_B2 0x000007FF
-#define BF_PXP_CSC2_COEF2_B2(v)  \
-       (((v) << 0) & BM_PXP_CSC2_COEF2_B2)
-
-#define HW_PXP_CSC2_COEF3      (0x00000210)
-
-#define BP_PXP_CSC2_COEF3_RSVD1      27
-#define BM_PXP_CSC2_COEF3_RSVD1 0xF8000000
-#define BF_PXP_CSC2_COEF3_RSVD1(v) \
-       (((v) << 27) & BM_PXP_CSC2_COEF3_RSVD1)
-#define BP_PXP_CSC2_COEF3_C2      16
-#define BM_PXP_CSC2_COEF3_C2 0x07FF0000
-#define BF_PXP_CSC2_COEF3_C2(v)  \
-       (((v) << 16) & BM_PXP_CSC2_COEF3_C2)
-#define BP_PXP_CSC2_COEF3_RSVD0      11
-#define BM_PXP_CSC2_COEF3_RSVD0 0x0000F800
-#define BF_PXP_CSC2_COEF3_RSVD0(v)  \
-       (((v) << 11) & BM_PXP_CSC2_COEF3_RSVD0)
-#define BP_PXP_CSC2_COEF3_C1      0
-#define BM_PXP_CSC2_COEF3_C1 0x000007FF
-#define BF_PXP_CSC2_COEF3_C1(v)  \
-       (((v) << 0) & BM_PXP_CSC2_COEF3_C1)
-
-#define HW_PXP_CSC2_COEF4      (0x00000220)
-
-#define BP_PXP_CSC2_COEF4_RSVD1      25
-#define BM_PXP_CSC2_COEF4_RSVD1 0xFE000000
-#define BF_PXP_CSC2_COEF4_RSVD1(v) \
-       (((v) << 25) & BM_PXP_CSC2_COEF4_RSVD1)
-#define BP_PXP_CSC2_COEF4_D1      16
-#define BM_PXP_CSC2_COEF4_D1 0x01FF0000
-#define BF_PXP_CSC2_COEF4_D1(v)  \
-       (((v) << 16) & BM_PXP_CSC2_COEF4_D1)
-#define BP_PXP_CSC2_COEF4_RSVD0      11
-#define BM_PXP_CSC2_COEF4_RSVD0 0x0000F800
-#define BF_PXP_CSC2_COEF4_RSVD0(v)  \
-       (((v) << 11) & BM_PXP_CSC2_COEF4_RSVD0)
-#define BP_PXP_CSC2_COEF4_C3      0
-#define BM_PXP_CSC2_COEF4_C3 0x000007FF
-#define BF_PXP_CSC2_COEF4_C3(v)  \
-       (((v) << 0) & BM_PXP_CSC2_COEF4_C3)
-
-#define HW_PXP_CSC2_COEF5      (0x00000230)
-
-#define BP_PXP_CSC2_COEF5_RSVD1      25
-#define BM_PXP_CSC2_COEF5_RSVD1 0xFE000000
-#define BF_PXP_CSC2_COEF5_RSVD1(v) \
-       (((v) << 25) & BM_PXP_CSC2_COEF5_RSVD1)
-#define BP_PXP_CSC2_COEF5_D3      16
-#define BM_PXP_CSC2_COEF5_D3 0x01FF0000
-#define BF_PXP_CSC2_COEF5_D3(v)  \
-       (((v) << 16) & BM_PXP_CSC2_COEF5_D3)
-#define BP_PXP_CSC2_COEF5_RSVD0      9
-#define BM_PXP_CSC2_COEF5_RSVD0 0x0000FE00
-#define BF_PXP_CSC2_COEF5_RSVD0(v)  \
-       (((v) << 9) & BM_PXP_CSC2_COEF5_RSVD0)
-#define BP_PXP_CSC2_COEF5_D2      0
-#define BM_PXP_CSC2_COEF5_D2 0x000001FF
-#define BF_PXP_CSC2_COEF5_D2(v)  \
-       (((v) << 0) & BM_PXP_CSC2_COEF5_D2)
-
-#define HW_PXP_LUT_CTRL        (0x00000240)
-
-#define BM_PXP_LUT_CTRL_BYPASS 0x80000000
-#define BF_PXP_LUT_CTRL_BYPASS(v) \
-       (((v) << 31) & BM_PXP_LUT_CTRL_BYPASS)
-#define BP_PXP_LUT_CTRL_RSVD3      26
-#define BM_PXP_LUT_CTRL_RSVD3 0x7C000000
-#define BF_PXP_LUT_CTRL_RSVD3(v)  \
-       (((v) << 26) & BM_PXP_LUT_CTRL_RSVD3)
-#define BP_PXP_LUT_CTRL_LOOKUP_MODE      24
-#define BM_PXP_LUT_CTRL_LOOKUP_MODE 0x03000000
-#define BF_PXP_LUT_CTRL_LOOKUP_MODE(v)  \
-       (((v) << 24) & BM_PXP_LUT_CTRL_LOOKUP_MODE)
-#define BV_PXP_LUT_CTRL_LOOKUP_MODE__CACHE_RGB565  0x0
-#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8     0x1
-#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB444 0x2
-#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB454 0x3
-#define BP_PXP_LUT_CTRL_RSVD2      18
-#define BM_PXP_LUT_CTRL_RSVD2 0x00FC0000
-#define BF_PXP_LUT_CTRL_RSVD2(v)  \
-       (((v) << 18) & BM_PXP_LUT_CTRL_RSVD2)
-#define BP_PXP_LUT_CTRL_OUT_MODE      16
-#define BM_PXP_LUT_CTRL_OUT_MODE 0x00030000
-#define BF_PXP_LUT_CTRL_OUT_MODE(v)  \
-       (((v) << 16) & BM_PXP_LUT_CTRL_OUT_MODE)
-#define BV_PXP_LUT_CTRL_OUT_MODE__RESERVED    0x0
-#define BV_PXP_LUT_CTRL_OUT_MODE__Y8     0x1
-#define BV_PXP_LUT_CTRL_OUT_MODE__RGBW4444CFA 0x2
-#define BV_PXP_LUT_CTRL_OUT_MODE__RGB888      0x3
-#define BP_PXP_LUT_CTRL_RSVD1      11
-#define BM_PXP_LUT_CTRL_RSVD1 0x0000F800
-#define BF_PXP_LUT_CTRL_RSVD1(v)  \
-       (((v) << 11) & BM_PXP_LUT_CTRL_RSVD1)
-#define BM_PXP_LUT_CTRL_SEL_8KB 0x00000400
-#define BF_PXP_LUT_CTRL_SEL_8KB(v)  \
-       (((v) << 10) & BM_PXP_LUT_CTRL_SEL_8KB)
-#define BM_PXP_LUT_CTRL_LRU_UPD 0x00000200
-#define BF_PXP_LUT_CTRL_LRU_UPD(v)  \
-       (((v) << 9) & BM_PXP_LUT_CTRL_LRU_UPD)
-#define BM_PXP_LUT_CTRL_INVALID 0x00000100
-#define BF_PXP_LUT_CTRL_INVALID(v)  \
-       (((v) << 8) & BM_PXP_LUT_CTRL_INVALID)
-#define BP_PXP_LUT_CTRL_RSVD0      1
-#define BM_PXP_LUT_CTRL_RSVD0 0x000000FE
-#define BF_PXP_LUT_CTRL_RSVD0(v)  \
-       (((v) << 1) & BM_PXP_LUT_CTRL_RSVD0)
-#define BM_PXP_LUT_CTRL_DMA_START 0x00000001
-#define BF_PXP_LUT_CTRL_DMA_START(v)  \
-       (((v) << 0) & BM_PXP_LUT_CTRL_DMA_START)
-
-#define HW_PXP_LUT_ADDR        (0x00000250)
-
-#define BM_PXP_LUT_ADDR_RSVD2 0x80000000
-#define BF_PXP_LUT_ADDR_RSVD2(v) \
-       (((v) << 31) & BM_PXP_LUT_ADDR_RSVD2)
-#define BP_PXP_LUT_ADDR_NUM_BYTES      16
-#define BM_PXP_LUT_ADDR_NUM_BYTES 0x7FFF0000
-#define BF_PXP_LUT_ADDR_NUM_BYTES(v)  \
-       (((v) << 16) & BM_PXP_LUT_ADDR_NUM_BYTES)
-#define BP_PXP_LUT_ADDR_RSVD1      14
-#define BM_PXP_LUT_ADDR_RSVD1 0x0000C000
-#define BF_PXP_LUT_ADDR_RSVD1(v)  \
-       (((v) << 14) & BM_PXP_LUT_ADDR_RSVD1)
-#define BP_PXP_LUT_ADDR_ADDR      0
-#define BM_PXP_LUT_ADDR_ADDR 0x00003FFF
-#define BF_PXP_LUT_ADDR_ADDR(v)  \
-       (((v) << 0) & BM_PXP_LUT_ADDR_ADDR)
-
-#define HW_PXP_LUT_DATA        (0x00000260)
-
-#define BP_PXP_LUT_DATA_DATA      0
-#define BM_PXP_LUT_DATA_DATA 0xFFFFFFFF
-#define BF_PXP_LUT_DATA_DATA(v)   (v)
-
-#define HW_PXP_LUT_EXTMEM      (0x00000270)
-
-#define BP_PXP_LUT_EXTMEM_ADDR      0
-#define BM_PXP_LUT_EXTMEM_ADDR 0xFFFFFFFF
-#define BF_PXP_LUT_EXTMEM_ADDR(v)   (v)
-
-#define HW_PXP_CFA     (0x00000280)
-
-#define BP_PXP_CFA_DATA      0
-#define BM_PXP_CFA_DATA 0xFFFFFFFF
-#define BF_PXP_CFA_DATA(v)   (v)
-
-#define HW_PXP_ALPHA_A_CTRL    (0x00000290)
-
-#define BP_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA      24
-#define BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA 0xFF000000
-#define BF_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA(v) \
-       (((v) << 24) & BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA)
-#define BP_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA      16
-#define BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA 0x00FF0000
-#define BF_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA(v)  \
-       (((v) << 16) & BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA)
-#define BP_PXP_ALPHA_A_CTRL_RSVD0      14
-#define BM_PXP_ALPHA_A_CTRL_RSVD0 0x0000C000
-#define BF_PXP_ALPHA_A_CTRL_RSVD0(v)  \
-       (((v) << 14) & BM_PXP_ALPHA_A_CTRL_RSVD0)
-#define BM_PXP_ALPHA_A_CTRL_S1_COLOR_MODE 0x00002000
-#define BF_PXP_ALPHA_A_CTRL_S1_COLOR_MODE(v)  \
-       (((v) << 13) & BM_PXP_ALPHA_A_CTRL_S1_COLOR_MODE)
-#define BV_PXP_ALPHA_A_CTRL_S1_COLOR_MODE__0 0x0
-#define BV_PXP_ALPHA_A_CTRL_S1_COLOR_MODE__1 0x1
-#define BM_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE 0x00001000
-#define BF_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE(v)  \
-       (((v) << 12) & BM_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE)
-#define BV_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE__0 0x0
-#define BV_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE__1 0x1
-#define BP_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE      10
-#define BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE 0x00000C00
-#define BF_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE(v)  \
-       (((v) << 10) & BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE)
-#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__0 0x0
-#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__1 0x0
-#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__2 0x0
-#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__3 0x0
-#define BP_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE      8
-#define BM_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE 0x00000300
-#define BF_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE(v)  \
-       (((v) << 8) & BM_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE)
-#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__0 0x0
-#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__1 0x1
-#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__2 0x2
-#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__3 0x3
-#define BM_PXP_ALPHA_A_CTRL_RSVD1 0x00000080
-#define BF_PXP_ALPHA_A_CTRL_RSVD1(v)  \
-       (((v) << 7) & BM_PXP_ALPHA_A_CTRL_RSVD1)
-#define BM_PXP_ALPHA_A_CTRL_S0_COLOR_MODE 0x00000040
-#define BF_PXP_ALPHA_A_CTRL_S0_COLOR_MODE(v)  \
-       (((v) << 6) & BM_PXP_ALPHA_A_CTRL_S0_COLOR_MODE)
-#define BV_PXP_ALPHA_A_CTRL_S0_COLOR_MODE__0 0x0
-#define BV_PXP_ALPHA_A_CTRL_S0_COLOR_MODE__1 0x1
-#define BM_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE 0x00000020
-#define BF_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE(v)  \
-       (((v) << 5) & BM_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE)
-#define BV_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE__0 0x0
-#define BV_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE__1 0x1
-#define BP_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE      3
-#define BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE 0x00000018
-#define BF_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE(v)  \
-       (((v) << 3) & BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE)
-#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__0 0x0
-#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__1 0x1
-#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__2 0x2
-#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__3 0x3
-#define BP_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE      1
-#define BM_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE 0x00000006
-#define BF_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE(v)  \
-       (((v) << 1) & BM_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE)
-#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__0 0x0
-#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__1 0x1
-#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__2 0x2
-#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__3 0x3
-#define BM_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE 0x00000001
-#define BF_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE(v)  \
-       (((v) << 0) & BM_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE)
-#define BV_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE__0 0x0
-#define BV_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE__1 0x1
-
-#define HW_PXP_ALPHA_B_CTRL    (0x000002a0)
-
-#define BP_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA      24
-#define BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA 0xFF000000
-#define BF_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA(v) \
-       (((v) << 24) & BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA)
-#define BP_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA      16
-#define BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA 0x00FF0000
-#define BF_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA(v)  \
-       (((v) << 16) & BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA)
-#define BP_PXP_ALPHA_B_CTRL_RSVD0      14
-#define BM_PXP_ALPHA_B_CTRL_RSVD0 0x0000C000
-#define BF_PXP_ALPHA_B_CTRL_RSVD0(v)  \
-       (((v) << 14) & BM_PXP_ALPHA_B_CTRL_RSVD0)
-#define BM_PXP_ALPHA_B_CTRL_S1_COLOR_MODE 0x00002000
-#define BF_PXP_ALPHA_B_CTRL_S1_COLOR_MODE(v)  \
-       (((v) << 13) & BM_PXP_ALPHA_B_CTRL_S1_COLOR_MODE)
-#define BV_PXP_ALPHA_B_CTRL_S1_COLOR_MODE__0 0x0
-#define BV_PXP_ALPHA_B_CTRL_S1_COLOR_MODE__1 0x1
-#define BM_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE 0x00001000
-#define BF_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE(v)  \
-       (((v) << 12) & BM_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE)
-#define BV_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE__0 0x0
-#define BV_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE__1 0x1
-#define BP_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE      10
-#define BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE 0x00000C00
-#define BF_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE(v)  \
-       (((v) << 10) & BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE)
-#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__0 0x0
-#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__1 0x1
-#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__2 0x2
-#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__3 0x3
-#define BP_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE      8
-#define BM_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE 0x00000300
-#define BF_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE(v)  \
-       (((v) << 8) & BM_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE)
-#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__0 0x0
-#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__1 0x1
-#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__2 0x2
-#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__3 0x3
-#define BM_PXP_ALPHA_B_CTRL_RSVD1 0x00000080
-#define BF_PXP_ALPHA_B_CTRL_RSVD1(v)  \
-       (((v) << 7) & BM_PXP_ALPHA_B_CTRL_RSVD1)
-#define BM_PXP_ALPHA_B_CTRL_S0_COLOR_MODE 0x00000040
-#define BF_PXP_ALPHA_B_CTRL_S0_COLOR_MODE(v)  \
-       (((v) << 6) & BM_PXP_ALPHA_B_CTRL_S0_COLOR_MODE)
-#define BV_PXP_ALPHA_B_CTRL_S0_COLOR_MODE__0 0x0
-#define BV_PXP_ALPHA_B_CTRL_S0_COLOR_MODE__1 0x1
-#define BM_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE 0x00000020
-#define BF_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE(v)  \
-       (((v) << 5) & BM_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE)
-#define BV_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE__0 0x0
-#define BV_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE__1 0x1
-#define BP_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE      3
-#define BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE 0x00000018
-#define BF_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE(v)  \
-       (((v) << 3) & BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE)
-#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__0 0x0
-#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__1 0x1
-#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__2 0x2
-#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__3 0x3
-#define BP_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE      1
-#define BM_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE 0x00000006
-#define BF_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE(v)  \
-       (((v) << 1) & BM_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE)
-#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__0 0x0
-#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__1 0x1
-#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__2 0x2
-#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__3 0x3
-#define BM_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE 0x00000001
-#define BF_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE(v)  \
-       (((v) << 0) & BM_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE)
-#define BV_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE__0 0x0
-#define BV_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE__1 0x1
-
-#define HW_PXP_ALPHA_B_CTRL_1  (0x000002b0)
-
-#define BP_PXP_ALPHA_B_CTRL_1_RSVD0      8
-#define BM_PXP_ALPHA_B_CTRL_1_RSVD0 0xFFFFFF00
-#define BF_PXP_ALPHA_B_CTRL_1_RSVD0(v) \
-       (((v) << 8) & BM_PXP_ALPHA_B_CTRL_1_RSVD0)
-#define BP_PXP_ALPHA_B_CTRL_1_ROP      4
-#define BM_PXP_ALPHA_B_CTRL_1_ROP 0x000000F0
-#define BF_PXP_ALPHA_B_CTRL_1_ROP(v)  \
-       (((v) << 4) & BM_PXP_ALPHA_B_CTRL_1_ROP)
-#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKAS     0x0
-#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKNOTAS  0x1
-#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKASNOT  0x2
-#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGEAS    0x3
-#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGENOTAS 0x4
-#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGEASNOT 0x5
-#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTCOPYAS  0x6
-#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOT 0x7
-#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTMASKAS  0x8
-#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTMERGEAS 0x9
-#define BV_PXP_ALPHA_B_CTRL_1_ROP__XORAS      0xA
-#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTXORAS   0xB
-#define BP_PXP_ALPHA_B_CTRL_1_RSVD1      2
-#define BM_PXP_ALPHA_B_CTRL_1_RSVD1 0x0000000C
-#define BF_PXP_ALPHA_B_CTRL_1_RSVD1(v)  \
-       (((v) << 2) & BM_PXP_ALPHA_B_CTRL_1_RSVD1)
-#define BM_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE 0x00000002
-#define BF_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE(v)  \
-       (((v) << 1) & BM_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE)
-#define BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE 0x00000001
-#define BF_PXP_ALPHA_B_CTRL_1_ROP_ENABLE(v)  \
-       (((v) << 0) & BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE)
-
-#define HW_PXP_PS_BACKGROUND_1 (0x000002c0)
-
-#define BP_PXP_PS_BACKGROUND_1_RSVD      24
-#define BM_PXP_PS_BACKGROUND_1_RSVD 0xFF000000
-#define BF_PXP_PS_BACKGROUND_1_RSVD(v) \
-       (((v) << 24) & BM_PXP_PS_BACKGROUND_1_RSVD)
-#define BP_PXP_PS_BACKGROUND_1_COLOR      0
-#define BM_PXP_PS_BACKGROUND_1_COLOR 0x00FFFFFF
-#define BF_PXP_PS_BACKGROUND_1_COLOR(v)  \
-       (((v) << 0) & BM_PXP_PS_BACKGROUND_1_COLOR)
-
-#define HW_PXP_PS_CLRKEYLOW_1  (0x000002d0)
-
-#define BP_PXP_PS_CLRKEYLOW_1_RSVD1      24
-#define BM_PXP_PS_CLRKEYLOW_1_RSVD1 0xFF000000
-#define BF_PXP_PS_CLRKEYLOW_1_RSVD1(v) \
-       (((v) << 24) & BM_PXP_PS_CLRKEYLOW_1_RSVD1)
-#define BP_PXP_PS_CLRKEYLOW_1_PIXEL      0
-#define BM_PXP_PS_CLRKEYLOW_1_PIXEL 0x00FFFFFF
-#define BF_PXP_PS_CLRKEYLOW_1_PIXEL(v)  \
-       (((v) << 0) & BM_PXP_PS_CLRKEYLOW_1_PIXEL)
-
-#define HW_PXP_PS_CLRKEYHIGH_1 (0x000002e0)
-
-#define BP_PXP_PS_CLRKEYHIGH_1_RSVD1      24
-#define BM_PXP_PS_CLRKEYHIGH_1_RSVD1 0xFF000000
-#define BF_PXP_PS_CLRKEYHIGH_1_RSVD1(v) \
-       (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_1_RSVD1)
-#define BP_PXP_PS_CLRKEYHIGH_1_PIXEL      0
-#define BM_PXP_PS_CLRKEYHIGH_1_PIXEL 0x00FFFFFF
-#define BF_PXP_PS_CLRKEYHIGH_1_PIXEL(v)  \
-       (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_1_PIXEL)
-
-#define HW_PXP_AS_CLRKEYLOW_1  (0x000002f0)
-
-#define BP_PXP_AS_CLRKEYLOW_1_RSVD1      24
-#define BM_PXP_AS_CLRKEYLOW_1_RSVD1 0xFF000000
-#define BF_PXP_AS_CLRKEYLOW_1_RSVD1(v) \
-       (((v) << 24) & BM_PXP_AS_CLRKEYLOW_1_RSVD1)
-#define BP_PXP_AS_CLRKEYLOW_1_PIXEL      0
-#define BM_PXP_AS_CLRKEYLOW_1_PIXEL 0x00FFFFFF
-#define BF_PXP_AS_CLRKEYLOW_1_PIXEL(v)  \
-       (((v) << 0) & BM_PXP_AS_CLRKEYLOW_1_PIXEL)
-
-#define HW_PXP_AS_CLRKEYHIGH_1 (0x00000300)
-
-#define BP_PXP_AS_CLRKEYHIGH_1_RSVD1      24
-#define BM_PXP_AS_CLRKEYHIGH_1_RSVD1 0xFF000000
-#define BF_PXP_AS_CLRKEYHIGH_1_RSVD1(v) \
-       (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_1_RSVD1)
-#define BP_PXP_AS_CLRKEYHIGH_1_PIXEL      0
-#define BM_PXP_AS_CLRKEYHIGH_1_PIXEL 0x00FFFFFF
-#define BF_PXP_AS_CLRKEYHIGH_1_PIXEL(v)  \
-       (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_1_PIXEL)
-
-#define HW_PXP_CTRL2   (0x00000310)
-#define HW_PXP_CTRL2_SET       (0x00000314)
-#define HW_PXP_CTRL2_CLR       (0x00000318)
-#define HW_PXP_CTRL2_TOG       (0x0000031c)
-
-#define BP_PXP_CTRL2_RSVD3      28
-#define BM_PXP_CTRL2_RSVD3 0xF0000000
-#define BF_PXP_CTRL2_RSVD3(v) \
-       (((v) << 28) & BM_PXP_CTRL2_RSVD3)
-#define BM_PXP_CTRL2_ENABLE_ROTATE1 0x08000000
-#define BF_PXP_CTRL2_ENABLE_ROTATE1(v)  \
-       (((v) << 27) & BM_PXP_CTRL2_ENABLE_ROTATE1)
-#define BM_PXP_CTRL2_ENABLE_ROTATE0 0x04000000
-#define BF_PXP_CTRL2_ENABLE_ROTATE0(v)  \
-       (((v) << 26) & BM_PXP_CTRL2_ENABLE_ROTATE0)
-#define BM_PXP_CTRL2_ENABLE_LUT 0x02000000
-#define BF_PXP_CTRL2_ENABLE_LUT(v)  \
-       (((v) << 25) & BM_PXP_CTRL2_ENABLE_LUT)
-#define BM_PXP_CTRL2_ENABLE_CSC2 0x01000000
-#define BF_PXP_CTRL2_ENABLE_CSC2(v)  \
-       (((v) << 24) & BM_PXP_CTRL2_ENABLE_CSC2)
-#define BM_PXP_CTRL2_BLOCK_SIZE 0x00800000
-#define BF_PXP_CTRL2_BLOCK_SIZE(v)  \
-       (((v) << 23) & BM_PXP_CTRL2_BLOCK_SIZE)
-#define BV_PXP_CTRL2_BLOCK_SIZE__8X8   0x0
-#define BV_PXP_CTRL2_BLOCK_SIZE__16X16 0x1
-#define BM_PXP_CTRL2_RSVD2 0x00400000
-#define BF_PXP_CTRL2_RSVD2(v)  \
-       (((v) << 22) & BM_PXP_CTRL2_RSVD2)
-#define BM_PXP_CTRL2_ENABLE_ALPHA_B 0x00200000
-#define BF_PXP_CTRL2_ENABLE_ALPHA_B(v)  \
-       (((v) << 21) & BM_PXP_CTRL2_ENABLE_ALPHA_B)
-#define BM_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE 0x00100000
-#define BF_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE(v)  \
-       (((v) << 20) & BM_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE)
-#define BM_PXP_CTRL2_ENABLE_WFE_B 0x00080000
-#define BF_PXP_CTRL2_ENABLE_WFE_B(v)  \
-       (((v) << 19) & BM_PXP_CTRL2_ENABLE_WFE_B)
-#define BM_PXP_CTRL2_ENABLE_WFE_A 0x00040000
-#define BF_PXP_CTRL2_ENABLE_WFE_A(v)  \
-       (((v) << 18) & BM_PXP_CTRL2_ENABLE_WFE_A)
-#define BM_PXP_CTRL2_ENABLE_DITHER 0x00020000
-#define BF_PXP_CTRL2_ENABLE_DITHER(v)  \
-       (((v) << 17) & BM_PXP_CTRL2_ENABLE_DITHER)
-#define BM_PXP_CTRL2_RSVD1 0x00010000
-#define BF_PXP_CTRL2_RSVD1(v)  \
-       (((v) << 16) & BM_PXP_CTRL2_RSVD1)
-#define BM_PXP_CTRL2_VFLIP1 0x00008000
-#define BF_PXP_CTRL2_VFLIP1(v)  \
-       (((v) << 15) & BM_PXP_CTRL2_VFLIP1)
-#define BM_PXP_CTRL2_HFLIP1 0x00004000
-#define BF_PXP_CTRL2_HFLIP1(v)  \
-       (((v) << 14) & BM_PXP_CTRL2_HFLIP1)
-#define BP_PXP_CTRL2_ROTATE1      12
-#define BM_PXP_CTRL2_ROTATE1 0x00003000
-#define BF_PXP_CTRL2_ROTATE1(v)  \
-       (((v) << 12) & BM_PXP_CTRL2_ROTATE1)
-#define BV_PXP_CTRL2_ROTATE1__ROT_0   0x0
-#define BV_PXP_CTRL2_ROTATE1__ROT_90  0x1
-#define BV_PXP_CTRL2_ROTATE1__ROT_180 0x2
-#define BV_PXP_CTRL2_ROTATE1__ROT_270 0x3
-#define BM_PXP_CTRL2_VFLIP0 0x00000800
-#define BF_PXP_CTRL2_VFLIP0(v)  \
-       (((v) << 11) & BM_PXP_CTRL2_VFLIP0)
-#define BM_PXP_CTRL2_HFLIP0 0x00000400
-#define BF_PXP_CTRL2_HFLIP0(v)  \
-       (((v) << 10) & BM_PXP_CTRL2_HFLIP0)
-#define BP_PXP_CTRL2_ROTATE0      8
-#define BM_PXP_CTRL2_ROTATE0 0x00000300
-#define BF_PXP_CTRL2_ROTATE0(v)  \
-       (((v) << 8) & BM_PXP_CTRL2_ROTATE0)
-#define BV_PXP_CTRL2_ROTATE0__ROT_0   0x0
-#define BV_PXP_CTRL2_ROTATE0__ROT_90  0x1
-#define BV_PXP_CTRL2_ROTATE0__ROT_180 0x2
-#define BV_PXP_CTRL2_ROTATE0__ROT_270 0x3
-#define BP_PXP_CTRL2_RSVD0      1
-#define BM_PXP_CTRL2_RSVD0 0x000000FE
-#define BF_PXP_CTRL2_RSVD0(v)  \
-       (((v) << 1) & BM_PXP_CTRL2_RSVD0)
-#define BM_PXP_CTRL2_ENABLE 0x00000001
-#define BF_PXP_CTRL2_ENABLE(v)  \
-       (((v) << 0) & BM_PXP_CTRL2_ENABLE)
-
-#define HW_PXP_POWER_REG0      (0x00000320)
-
-#define BP_PXP_POWER_REG0_CTRL      12
-#define BM_PXP_POWER_REG0_CTRL 0xFFFFF000
-#define BF_PXP_POWER_REG0_CTRL(v) \
-       (((v) << 12) & BM_PXP_POWER_REG0_CTRL)
-#define BP_PXP_POWER_REG0_ROT0_MEM_LP_STATE      9
-#define BM_PXP_POWER_REG0_ROT0_MEM_LP_STATE 0x00000E00
-#define BF_PXP_POWER_REG0_ROT0_MEM_LP_STATE(v)  \
-       (((v) << 9) & BM_PXP_POWER_REG0_ROT0_MEM_LP_STATE)
-#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__NONE 0x0
-#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__LS   0x1
-#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__DS   0x2
-#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__SD   0x4
-#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN      6
-#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN 0x000001C0
-#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN(v)  \
-       (((v) << 6) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN)
-#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__NONE 0x0
-#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__LS   0x1
-#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__DS   0x2
-#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__SD   0x4
-#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN      3
-#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN 0x00000038
-#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN(v)  \
-       (((v) << 3) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN)
-#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__NONE 0x0
-#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__LS   0x1
-#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__DS   0x2
-#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__SD   0x4
-#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0      0
-#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0 0x00000007
-#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0(v)  \
-       (((v) << 0) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0)
-#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__NONE 0x0
-#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__LS   0x1
-#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__DS   0x2
-#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__SD   0x4
-
-#define HW_PXP_POWER_REG1      (0x00000330)
-
-#define BP_PXP_POWER_REG1_RSVD0      24
-#define BM_PXP_POWER_REG1_RSVD0 0xFF000000
-#define BF_PXP_POWER_REG1_RSVD0(v) \
-       (((v) << 24) & BM_PXP_POWER_REG1_RSVD0)
-#define BP_PXP_POWER_REG1_ALU_B_MEM_LP_STATE      21
-#define BM_PXP_POWER_REG1_ALU_B_MEM_LP_STATE 0x00E00000
-#define BF_PXP_POWER_REG1_ALU_B_MEM_LP_STATE(v)  \
-       (((v) << 21) & BM_PXP_POWER_REG1_ALU_B_MEM_LP_STATE)
-#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__NONE 0x0
-#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__LS   0x1
-#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__DS   0x2
-#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__SD   0x4
-#define BP_PXP_POWER_REG1_ALU_A_MEM_LP_STATE      18
-#define BM_PXP_POWER_REG1_ALU_A_MEM_LP_STATE 0x001C0000
-#define BF_PXP_POWER_REG1_ALU_A_MEM_LP_STATE(v)  \
-       (((v) << 18) & BM_PXP_POWER_REG1_ALU_A_MEM_LP_STATE)
-#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__NONE 0x0
-#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__LS   0x1
-#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__DS   0x2
-#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__SD   0x4
-#define BP_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE      15
-#define BM_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE 0x00038000
-#define BF_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE(v)  \
-       (((v) << 15) & BM_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE)
-#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__NONE 0x0
-#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__LS   0x1
-#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__DS   0x2
-#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__SD   0x4
-#define BP_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE      12
-#define BM_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE 0x00007000
-#define BF_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE(v)  \
-       (((v) << 12) & BM_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE)
-#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__NONE 0x0
-#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__LS   0x1
-#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__DS   0x2
-#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__SD   0x4
-#define BP_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE      9
-#define BM_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE 0x00000E00
-#define BF_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE(v)  \
-       (((v) << 9) & BM_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE)
-#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__NONE 0x0
-#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__LS   0x1
-#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__DS   0x2
-#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__SD   0x4
-#define BP_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE      6
-#define BM_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE 0x000001C0
-#define BF_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE(v)  \
-       (((v) << 6) & BM_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE)
-#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__NONE 0x0
-#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__LS   0x1
-#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__DS   0x2
-#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__SD   0x4
-#define BP_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE      3
-#define BM_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE 0x00000038
-#define BF_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE(v)  \
-       (((v) << 3) & BM_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE)
-#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__NONE 0x0
-#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__LS   0x1
-#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__DS   0x2
-#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__SD   0x4
-#define BP_PXP_POWER_REG1_ROT1_MEM_LP_STATE      0
-#define BM_PXP_POWER_REG1_ROT1_MEM_LP_STATE 0x00000007
-#define BF_PXP_POWER_REG1_ROT1_MEM_LP_STATE(v)  \
-       (((v) << 0) & BM_PXP_POWER_REG1_ROT1_MEM_LP_STATE)
-#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__NONE 0x0
-#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__LS   0x1
-#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__DS   0x2
-#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__SD   0x4
-
-#define HW_PXP_DATA_PATH_CTRL0 (0x00000340)
-#define HW_PXP_DATA_PATH_CTRL0_SET     (0x00000344)
-#define HW_PXP_DATA_PATH_CTRL0_CLR     (0x00000348)
-#define HW_PXP_DATA_PATH_CTRL0_TOG     (0x0000034c)
-
-#define BP_PXP_DATA_PATH_CTRL0_MUX15_SEL      30
-#define BM_PXP_DATA_PATH_CTRL0_MUX15_SEL 0xC0000000
-#define BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(v) \
-       (((v) << 30) & BM_PXP_DATA_PATH_CTRL0_MUX15_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX14_SEL      28
-#define BM_PXP_DATA_PATH_CTRL0_MUX14_SEL 0x30000000
-#define BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(v)  \
-       (((v) << 28) & BM_PXP_DATA_PATH_CTRL0_MUX14_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX13_SEL      26
-#define BM_PXP_DATA_PATH_CTRL0_MUX13_SEL 0x0C000000
-#define BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(v)  \
-       (((v) << 26) & BM_PXP_DATA_PATH_CTRL0_MUX13_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX12_SEL      24
-#define BM_PXP_DATA_PATH_CTRL0_MUX12_SEL 0x03000000
-#define BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(v)  \
-       (((v) << 24) & BM_PXP_DATA_PATH_CTRL0_MUX12_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX11_SEL      22
-#define BM_PXP_DATA_PATH_CTRL0_MUX11_SEL 0x00C00000
-#define BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(v)  \
-       (((v) << 22) & BM_PXP_DATA_PATH_CTRL0_MUX11_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX10_SEL      20
-#define BM_PXP_DATA_PATH_CTRL0_MUX10_SEL 0x00300000
-#define BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(v)  \
-       (((v) << 20) & BM_PXP_DATA_PATH_CTRL0_MUX10_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX9_SEL      18
-#define BM_PXP_DATA_PATH_CTRL0_MUX9_SEL 0x000C0000
-#define BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(v)  \
-       (((v) << 18) & BM_PXP_DATA_PATH_CTRL0_MUX9_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX8_SEL      16
-#define BM_PXP_DATA_PATH_CTRL0_MUX8_SEL 0x00030000
-#define BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(v)  \
-       (((v) << 16) & BM_PXP_DATA_PATH_CTRL0_MUX8_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX7_SEL      14
-#define BM_PXP_DATA_PATH_CTRL0_MUX7_SEL 0x0000C000
-#define BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(v)  \
-       (((v) << 14) & BM_PXP_DATA_PATH_CTRL0_MUX7_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX6_SEL      12
-#define BM_PXP_DATA_PATH_CTRL0_MUX6_SEL 0x00003000
-#define BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(v)  \
-       (((v) << 12) & BM_PXP_DATA_PATH_CTRL0_MUX6_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX5_SEL      10
-#define BM_PXP_DATA_PATH_CTRL0_MUX5_SEL 0x00000C00
-#define BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(v)  \
-       (((v) << 10) & BM_PXP_DATA_PATH_CTRL0_MUX5_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX4_SEL      8
-#define BM_PXP_DATA_PATH_CTRL0_MUX4_SEL 0x00000300
-#define BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(v)  \
-       (((v) << 8) & BM_PXP_DATA_PATH_CTRL0_MUX4_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX3_SEL      6
-#define BM_PXP_DATA_PATH_CTRL0_MUX3_SEL 0x000000C0
-#define BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(v)  \
-       (((v) << 6) & BM_PXP_DATA_PATH_CTRL0_MUX3_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX2_SEL      4
-#define BM_PXP_DATA_PATH_CTRL0_MUX2_SEL 0x00000030
-#define BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(v)  \
-       (((v) << 4) & BM_PXP_DATA_PATH_CTRL0_MUX2_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX1_SEL      2
-#define BM_PXP_DATA_PATH_CTRL0_MUX1_SEL 0x0000000C
-#define BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(v)  \
-       (((v) << 2) & BM_PXP_DATA_PATH_CTRL0_MUX1_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL0_MUX0_SEL      0
-#define BM_PXP_DATA_PATH_CTRL0_MUX0_SEL 0x00000003
-#define BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(v)  \
-       (((v) << 0) & BM_PXP_DATA_PATH_CTRL0_MUX0_SEL)
-#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__3 0x3
-
-#define HW_PXP_DATA_PATH_CTRL1 (0x00000350)
-#define HW_PXP_DATA_PATH_CTRL1_SET     (0x00000354)
-#define HW_PXP_DATA_PATH_CTRL1_CLR     (0x00000358)
-#define HW_PXP_DATA_PATH_CTRL1_TOG     (0x0000035c)
-
-#define BP_PXP_DATA_PATH_CTRL1_RSVD0      4
-#define BM_PXP_DATA_PATH_CTRL1_RSVD0 0xFFFFFFF0
-#define BF_PXP_DATA_PATH_CTRL1_RSVD0(v) \
-       (((v) << 4) & BM_PXP_DATA_PATH_CTRL1_RSVD0)
-#define BP_PXP_DATA_PATH_CTRL1_MUX17_SEL      2
-#define BM_PXP_DATA_PATH_CTRL1_MUX17_SEL 0x0000000C
-#define BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(v)  \
-       (((v) << 2) & BM_PXP_DATA_PATH_CTRL1_MUX17_SEL)
-#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__3 0x3
-#define BP_PXP_DATA_PATH_CTRL1_MUX16_SEL      0
-#define BM_PXP_DATA_PATH_CTRL1_MUX16_SEL 0x00000003
-#define BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(v)  \
-       (((v) << 0) & BM_PXP_DATA_PATH_CTRL1_MUX16_SEL)
-#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__0 0x0
-#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__1 0x1
-#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__2 0x2
-#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__3 0x3
-
-#define HW_PXP_INIT_MEM_CTRL   (0x00000360)
-#define HW_PXP_INIT_MEM_CTRL_SET       (0x00000364)
-#define HW_PXP_INIT_MEM_CTRL_CLR       (0x00000368)
-#define HW_PXP_INIT_MEM_CTRL_TOG       (0x0000036c)
-
-#define BM_PXP_INIT_MEM_CTRL_START 0x80000000
-#define BF_PXP_INIT_MEM_CTRL_START(v) \
-       (((v) << 31) & BM_PXP_INIT_MEM_CTRL_START)
-#define BP_PXP_INIT_MEM_CTRL_SELECT      27
-#define BM_PXP_INIT_MEM_CTRL_SELECT 0x78000000
-#define BF_PXP_INIT_MEM_CTRL_SELECT(v)  \
-       (((v) << 27) & BM_PXP_INIT_MEM_CTRL_SELECT)
-#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_LUT  0x0
-#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_ERR0 0x1
-#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_ERR1 0x2
-#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER1_LUT  0x3
-#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER2_LUT  0x4
-#define BV_PXP_INIT_MEM_CTRL_SELECT__ALU_A     0x5
-#define BV_PXP_INIT_MEM_CTRL_SELECT__ALU_B     0x6
-#define BV_PXP_INIT_MEM_CTRL_SELECT__WFE_A_FETCH  0x7
-#define BV_PXP_INIT_MEM_CTRL_SELECT__WFE_B_FETCH  0x8
-#define BV_PXP_INIT_MEM_CTRL_SELECT__RESERVED     0x15
-#define BP_PXP_INIT_MEM_CTRL_RSVD0      16
-#define BM_PXP_INIT_MEM_CTRL_RSVD0 0x07FF0000
-#define BF_PXP_INIT_MEM_CTRL_RSVD0(v)  \
-       (((v) << 16) & BM_PXP_INIT_MEM_CTRL_RSVD0)
-#define BP_PXP_INIT_MEM_CTRL_ADDR      0
-#define BM_PXP_INIT_MEM_CTRL_ADDR 0x0000FFFF
-#define BF_PXP_INIT_MEM_CTRL_ADDR(v)  \
-       (((v) << 0) & BM_PXP_INIT_MEM_CTRL_ADDR)
-
-#define HW_PXP_INIT_MEM_DATA   (0x00000370)
-
-#define BP_PXP_INIT_MEM_DATA_DATA      0
-#define BM_PXP_INIT_MEM_DATA_DATA 0xFFFFFFFF
-#define BF_PXP_INIT_MEM_DATA_DATA(v)   (v)
-
-#define HW_PXP_INIT_MEM_DATA_HIGH      (0x00000380)
-
-#define BP_PXP_INIT_MEM_DATA_HIGH_DATA      0
-#define BM_PXP_INIT_MEM_DATA_HIGH_DATA 0xFFFFFFFF
-#define BF_PXP_INIT_MEM_DATA_HIGH_DATA(v)   (v)
-
-#define HW_PXP_IRQ_MASK        (0x00000390)
-#define HW_PXP_IRQ_MASK_SET    (0x00000394)
-#define HW_PXP_IRQ_MASK_CLR    (0x00000398)
-#define HW_PXP_IRQ_MASK_TOG    (0x0000039c)
-
-#define BM_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN 0x80000000
-#define BF_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN(v) \
-       (((v) << 31) & BM_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN)
-#define BP_PXP_IRQ_MASK_RSVD1      16
-#define BM_PXP_IRQ_MASK_RSVD1 0x7FFF0000
-#define BF_PXP_IRQ_MASK_RSVD1(v)  \
-       (((v) << 16) & BM_PXP_IRQ_MASK_RSVD1)
-#define BM_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN 0x00008000
-#define BF_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN(v)  \
-       (((v) << 15) & BM_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN)
-#define BM_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN 0x00004000
-#define BF_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN(v)  \
-       (((v) << 14) & BM_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN)
-#define BM_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN 0x00002000
-#define BF_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN(v)  \
-       (((v) << 13) & BM_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN)
-#define BM_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN 0x00001000
-#define BF_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN(v)  \
-       (((v) << 12) & BM_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN)
-#define BM_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN 0x00000800
-#define BF_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN(v)  \
-       (((v) << 11) & BM_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN)
-#define BM_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN 0x00000400
-#define BF_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN(v)  \
-       (((v) << 10) & BM_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN)
-#define BM_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN 0x00000200
-#define BF_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN(v)  \
-       (((v) << 9) & BM_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN)
-#define BM_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN 0x00000100
-#define BF_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN(v)  \
-       (((v) << 8) & BM_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN)
-#define BM_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN 0x00000080
-#define BF_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN(v)  \
-       (((v) << 7) & BM_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN)
-#define BM_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN 0x00000040
-#define BF_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN(v)  \
-       (((v) << 6) & BM_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN)
-#define BM_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN 0x00000020
-#define BF_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN(v)  \
-       (((v) << 5) & BM_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN)
-#define BM_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN 0x00000010
-#define BF_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN(v)  \
-       (((v) << 4) & BM_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN)
-#define BM_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN 0x00000008
-#define BF_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN(v)  \
-       (((v) << 3) & BM_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN)
-#define BM_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN 0x00000004
-#define BF_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN(v)  \
-       (((v) << 2) & BM_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN)
-#define BM_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN 0x00000002
-#define BF_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN(v)  \
-       (((v) << 1) & BM_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN)
-#define BM_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN 0x00000001
-#define BF_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN(v)  \
-       (((v) << 0) & BM_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN)
-
-#define HW_PXP_IRQ     (0x000003a0)
-#define HW_PXP_IRQ_SET (0x000003a4)
-#define HW_PXP_IRQ_CLR (0x000003a8)
-#define HW_PXP_IRQ_TOG (0x000003ac)
-
-#define BM_PXP_IRQ_COMPRESS_DONE_IRQ 0x80000000
-#define BF_PXP_IRQ_COMPRESS_DONE_IRQ(v) \
-       (((v) << 31) & BM_PXP_IRQ_COMPRESS_DONE_IRQ)
-#define BP_PXP_IRQ_RSVD1      16
-#define BM_PXP_IRQ_RSVD1 0x7FFF0000
-#define BF_PXP_IRQ_RSVD1(v)  \
-       (((v) << 16) & BM_PXP_IRQ_RSVD1)
-#define BM_PXP_IRQ_WFE_B_STORE_IRQ 0x00008000
-#define BF_PXP_IRQ_WFE_B_STORE_IRQ(v)  \
-       (((v) << 15) & BM_PXP_IRQ_WFE_B_STORE_IRQ)
-#define BM_PXP_IRQ_WFE_A_STORE_IRQ 0x00004000
-#define BF_PXP_IRQ_WFE_A_STORE_IRQ(v)  \
-       (((v) << 14) & BM_PXP_IRQ_WFE_A_STORE_IRQ)
-#define BM_PXP_IRQ_DITHER_STORE_IRQ 0x00002000
-#define BF_PXP_IRQ_DITHER_STORE_IRQ(v)  \
-       (((v) << 13) & BM_PXP_IRQ_DITHER_STORE_IRQ)
-#define BM_PXP_IRQ_FIRST_STORE_IRQ 0x00001000
-#define BF_PXP_IRQ_FIRST_STORE_IRQ(v)  \
-       (((v) << 12) & BM_PXP_IRQ_FIRST_STORE_IRQ)
-#define BM_PXP_IRQ_WFE_B_CH1_STORE_IRQ 0x00000800
-#define BF_PXP_IRQ_WFE_B_CH1_STORE_IRQ(v)  \
-       (((v) << 11) & BM_PXP_IRQ_WFE_B_CH1_STORE_IRQ)
-#define BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ 0x00000400
-#define BF_PXP_IRQ_WFE_B_CH0_STORE_IRQ(v)  \
-       (((v) << 10) & BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ)
-#define BM_PXP_IRQ_WFE_A_CH1_STORE_IRQ 0x00000200
-#define BF_PXP_IRQ_WFE_A_CH1_STORE_IRQ(v)  \
-       (((v) << 9) & BM_PXP_IRQ_WFE_A_CH1_STORE_IRQ)
-#define BM_PXP_IRQ_WFE_A_CH0_STORE_IRQ 0x00000100
-#define BF_PXP_IRQ_WFE_A_CH0_STORE_IRQ(v)  \
-       (((v) << 8) & BM_PXP_IRQ_WFE_A_CH0_STORE_IRQ)
-#define BM_PXP_IRQ_DITHER_CH1_STORE_IRQ 0x00000080
-#define BF_PXP_IRQ_DITHER_CH1_STORE_IRQ(v)  \
-       (((v) << 7) & BM_PXP_IRQ_DITHER_CH1_STORE_IRQ)
-#define BM_PXP_IRQ_DITHER_CH0_STORE_IRQ 0x00000040
-#define BF_PXP_IRQ_DITHER_CH0_STORE_IRQ(v)  \
-       (((v) << 6) & BM_PXP_IRQ_DITHER_CH0_STORE_IRQ)
-#define BM_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ 0x00000020
-#define BF_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ(v)  \
-       (((v) << 5) & BM_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ)
-#define BM_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ 0x00000010
-#define BF_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ(v)  \
-       (((v) << 4) & BM_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ)
-#define BM_PXP_IRQ_FIRST_CH1_STORE_IRQ 0x00000008
-#define BF_PXP_IRQ_FIRST_CH1_STORE_IRQ(v)  \
-       (((v) << 3) & BM_PXP_IRQ_FIRST_CH1_STORE_IRQ)
-#define BM_PXP_IRQ_FIRST_CH0_STORE_IRQ 0x00000004
-#define BF_PXP_IRQ_FIRST_CH0_STORE_IRQ(v)  \
-       (((v) << 2) & BM_PXP_IRQ_FIRST_CH0_STORE_IRQ)
-#define BM_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ 0x00000002
-#define BF_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ(v)  \
-       (((v) << 1) & BM_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ)
-#define BM_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ 0x00000001
-#define BF_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ(v)  \
-       (((v) << 0) & BM_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ)
-
-#define HW_PXP_NEXT    (0x00000400)
-
-#define BP_PXP_NEXT_POINTER      2
-#define BM_PXP_NEXT_POINTER 0xFFFFFFFC
-#define BF_PXP_NEXT_POINTER(v) \
-       (((v) << 2) & BM_PXP_NEXT_POINTER)
-#define BM_PXP_NEXT_RSVD 0x00000002
-#define BF_PXP_NEXT_RSVD(v)  \
-       (((v) << 1) & BM_PXP_NEXT_RSVD)
-#define BM_PXP_NEXT_ENABLED 0x00000001
-#define BF_PXP_NEXT_ENABLED(v)  \
-       (((v) << 0) & BM_PXP_NEXT_ENABLED)
-
-#define HW_PXP_DEBUGCTRL       (0x00000410)
-
-#define BP_PXP_DEBUGCTRL_RSVD      12
-#define BM_PXP_DEBUGCTRL_RSVD 0xFFFFF000
-#define BF_PXP_DEBUGCTRL_RSVD(v) \
-       (((v) << 12) & BM_PXP_DEBUGCTRL_RSVD)
-#define BP_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT      8
-#define BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 0x00000F00
-#define BF_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT(v)  \
-       (((v) << 8) & BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT)
-#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__NONE     0x0
-#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MISS_CNT 0x1
-#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__HIT_CNT  0x2
-#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__LAT_CNT  0x4
-#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MAX_LAT  0x8
-#define BP_PXP_DEBUGCTRL_SELECT      0
-#define BM_PXP_DEBUGCTRL_SELECT 0x000000FF
-#define BF_PXP_DEBUGCTRL_SELECT(v)  \
-       (((v) << 0) & BM_PXP_DEBUGCTRL_SELECT)
-#define BV_PXP_DEBUGCTRL_SELECT__NONE  0x0
-#define BV_PXP_DEBUGCTRL_SELECT__CTRL  0x1
-#define BV_PXP_DEBUGCTRL_SELECT__PSBUF       0x2
-#define BV_PXP_DEBUGCTRL_SELECT__PSBAX       0x3
-#define BV_PXP_DEBUGCTRL_SELECT__PSBAY       0x4
-#define BV_PXP_DEBUGCTRL_SELECT__ASBUF       0x5
-#define BV_PXP_DEBUGCTRL_SELECT__ROTATION    0x6
-#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF0     0x7
-#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF1     0x8
-#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF2     0x9
-#define BV_PXP_DEBUGCTRL_SELECT__LUT_STAT    0x10
-#define BV_PXP_DEBUGCTRL_SELECT__LUT_MISS    0x11
-#define BV_PXP_DEBUGCTRL_SELECT__LUT_HIT     0x12
-#define BV_PXP_DEBUGCTRL_SELECT__LUT_LAT     0x13
-#define BV_PXP_DEBUGCTRL_SELECT__LUT_MAX_LAT 0x14
-
-#define HW_PXP_DEBUG   (0x00000420)
-
-#define BP_PXP_DEBUG_DATA      0
-#define BM_PXP_DEBUG_DATA 0xFFFFFFFF
-#define BF_PXP_DEBUG_DATA(v)   (v)
-
-#define HW_PXP_VERSION (0x00000430)
-
-#define BP_PXP_VERSION_MAJOR      24
-#define BM_PXP_VERSION_MAJOR 0xFF000000
-#define BF_PXP_VERSION_MAJOR(v) \
-       (((v) << 24) & BM_PXP_VERSION_MAJOR)
-#define BP_PXP_VERSION_MINOR      16
-#define BM_PXP_VERSION_MINOR 0x00FF0000
-#define BF_PXP_VERSION_MINOR(v)  \
-       (((v) << 16) & BM_PXP_VERSION_MINOR)
-#define BP_PXP_VERSION_STEP      0
-#define BM_PXP_VERSION_STEP 0x0000FFFF
-#define BF_PXP_VERSION_STEP(v)  \
-       (((v) << 0) & BM_PXP_VERSION_STEP)
-
-#endif /* __IMX_PXP_H__ */
diff --git a/drivers/media/platform/imx/Kconfig b/drivers/media/platform/imx/Kconfig
deleted file mode 100644 (file)
index 7cd0617..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-menuconfig VIDEO_IMX
-       bool "V4L2 capture drivers for NXP i.MX devices"
-       depends on V4L_PLATFORM_DRIVERS
-       depends on ARCH_MXC || COMPILE_TEST
-       depends on VIDEO_DEV && VIDEO_V4L2
-       help
-         Say yes here to enable support for capture drivers on i.MX SoCs.
-         Support for the single SoC features are selectable in the sub-menu
-         options.
-
-if VIDEO_IMX
-
-config VIDEO_IMX_MIPI_CSIS
-       tristate "MIPI CSI-2 CSIS receiver found on i.MX7 and i.MX8 models"
-       select MEDIA_CONTROLLER
-       select V4L2_FWNODE
-       select VIDEO_V4L2_SUBDEV_API
-       default n
-       help
-         Video4Linux2 sub-device driver for the MIPI CSI-2 CSIS receiver
-         v3.3/v3.6.3 found on some i.MX7 and i.MX8 SoCs.
-
-endif # VIDEO_IMX
diff --git a/drivers/media/platform/imx/Makefile b/drivers/media/platform/imx/Makefile
deleted file mode 100644 (file)
index f72bdbe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_VIDEO_IMX_MIPI_CSIS) += imx-mipi-csis.o
diff --git a/drivers/media/platform/imx/imx-mipi-csis.c b/drivers/media/platform/imx/imx-mipi-csis.c
deleted file mode 100644 (file)
index 0a72734..0000000
+++ /dev/null
@@ -1,1581 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Samsung CSIS MIPI CSI-2 receiver driver.
- *
- * The Samsung CSIS IP is a MIPI CSI-2 receiver found in various NXP i.MX7 and
- * i.MX8 SoCs. The i.MX7 features version 3.3 of the IP, while i.MX8 features
- * version 3.6.3.
- *
- * Copyright (C) 2019 Linaro Ltd
- * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
- *
- */
-
-#include <linux/clk.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/regulator/consumer.h>
-#include <linux/reset.h>
-#include <linux/spinlock.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-fwnode.h>
-#include <media/v4l2-mc.h>
-#include <media/v4l2-subdev.h>
-
-#define CSIS_DRIVER_NAME                       "imx-mipi-csis"
-
-#define CSIS_PAD_SINK                          0
-#define CSIS_PAD_SOURCE                                1
-#define CSIS_PADS_NUM                          2
-
-#define MIPI_CSIS_DEF_PIX_WIDTH                        640
-#define MIPI_CSIS_DEF_PIX_HEIGHT               480
-
-/* Register map definition */
-
-/* CSIS common control */
-#define MIPI_CSIS_CMN_CTRL                     0x04
-#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW       BIT(16)
-#define MIPI_CSIS_CMN_CTRL_INTER_MODE          BIT(10)
-#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL  BIT(2)
-#define MIPI_CSIS_CMN_CTRL_RESET               BIT(1)
-#define MIPI_CSIS_CMN_CTRL_ENABLE              BIT(0)
-
-#define MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET      8
-#define MIPI_CSIS_CMN_CTRL_LANE_NR_MASK                (3 << 8)
-
-/* CSIS clock control */
-#define MIPI_CSIS_CLK_CTRL                     0x08
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH3(x)        ((x) << 28)
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH2(x)        ((x) << 24)
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH1(x)        ((x) << 20)
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(x)        ((x) << 16)
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK      (0xf << 4)
-#define MIPI_CSIS_CLK_CTRL_WCLK_SRC            BIT(0)
-
-/* CSIS Interrupt mask */
-#define MIPI_CSIS_INT_MSK                      0x10
-#define MIPI_CSIS_INT_MSK_EVEN_BEFORE          BIT(31)
-#define MIPI_CSIS_INT_MSK_EVEN_AFTER           BIT(30)
-#define MIPI_CSIS_INT_MSK_ODD_BEFORE           BIT(29)
-#define MIPI_CSIS_INT_MSK_ODD_AFTER            BIT(28)
-#define MIPI_CSIS_INT_MSK_FRAME_START          BIT(24)
-#define MIPI_CSIS_INT_MSK_FRAME_END            BIT(20)
-#define MIPI_CSIS_INT_MSK_ERR_SOT_HS           BIT(16)
-#define MIPI_CSIS_INT_MSK_ERR_LOST_FS          BIT(12)
-#define MIPI_CSIS_INT_MSK_ERR_LOST_FE          BIT(8)
-#define MIPI_CSIS_INT_MSK_ERR_OVER             BIT(4)
-#define MIPI_CSIS_INT_MSK_ERR_WRONG_CFG                BIT(3)
-#define MIPI_CSIS_INT_MSK_ERR_ECC              BIT(2)
-#define MIPI_CSIS_INT_MSK_ERR_CRC              BIT(1)
-#define MIPI_CSIS_INT_MSK_ERR_UNKNOWN          BIT(0)
-
-/* CSIS Interrupt source */
-#define MIPI_CSIS_INT_SRC                      0x14
-#define MIPI_CSIS_INT_SRC_EVEN_BEFORE          BIT(31)
-#define MIPI_CSIS_INT_SRC_EVEN_AFTER           BIT(30)
-#define MIPI_CSIS_INT_SRC_EVEN                 BIT(30)
-#define MIPI_CSIS_INT_SRC_ODD_BEFORE           BIT(29)
-#define MIPI_CSIS_INT_SRC_ODD_AFTER            BIT(28)
-#define MIPI_CSIS_INT_SRC_ODD                  (0x3 << 28)
-#define MIPI_CSIS_INT_SRC_NON_IMAGE_DATA       (0xf << 28)
-#define MIPI_CSIS_INT_SRC_FRAME_START          BIT(24)
-#define MIPI_CSIS_INT_SRC_FRAME_END            BIT(20)
-#define MIPI_CSIS_INT_SRC_ERR_SOT_HS           BIT(16)
-#define MIPI_CSIS_INT_SRC_ERR_LOST_FS          BIT(12)
-#define MIPI_CSIS_INT_SRC_ERR_LOST_FE          BIT(8)
-#define MIPI_CSIS_INT_SRC_ERR_OVER             BIT(4)
-#define MIPI_CSIS_INT_SRC_ERR_WRONG_CFG                BIT(3)
-#define MIPI_CSIS_INT_SRC_ERR_ECC              BIT(2)
-#define MIPI_CSIS_INT_SRC_ERR_CRC              BIT(1)
-#define MIPI_CSIS_INT_SRC_ERR_UNKNOWN          BIT(0)
-#define MIPI_CSIS_INT_SRC_ERRORS               0xfffff
-
-/* D-PHY status control */
-#define MIPI_CSIS_DPHY_STATUS                  0x20
-#define MIPI_CSIS_DPHY_STATUS_ULPS_DAT         BIT(8)
-#define MIPI_CSIS_DPHY_STATUS_STOPSTATE_DAT    BIT(4)
-#define MIPI_CSIS_DPHY_STATUS_ULPS_CLK         BIT(1)
-#define MIPI_CSIS_DPHY_STATUS_STOPSTATE_CLK    BIT(0)
-
-/* D-PHY common control */
-#define MIPI_CSIS_DPHY_CMN_CTRL                        0x24
-#define MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(n)    ((n) << 24)
-#define MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE_MASK  GENMASK(31, 24)
-#define MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(n)   ((n) << 22)
-#define MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE_MASK GENMASK(23, 22)
-#define MIPI_CSIS_DPHY_CMN_CTRL_DPDN_SWAP_CLK  BIT(6)
-#define MIPI_CSIS_DPHY_CMN_CTRL_DPDN_SWAP_DAT  BIT(5)
-#define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE_DAT     BIT(1)
-#define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE_CLK     BIT(0)
-#define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE         (0x1f << 0)
-
-/* D-PHY Master and Slave Control register Low */
-#define MIPI_CSIS_DPHY_BCTRL_L                 0x30
-#define MIPI_CSIS_DPHY_BCTRL_L_USER_DATA_PATTERN_LOW(n)                (((n) & 3U) << 30)
-#define MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_715MV             (0 << 28)
-#define MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_724MV             (1 << 28)
-#define MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_733MV             (2 << 28)
-#define MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_706MV             (3 << 28)
-#define MIPI_CSIS_DPHY_BCTRL_L_BGR_CHOPPER_FREQ_3MHZ           (0 << 27)
-#define MIPI_CSIS_DPHY_BCTRL_L_BGR_CHOPPER_FREQ_1_5MHZ         (1 << 27)
-#define MIPI_CSIS_DPHY_BCTRL_L_VREG12_EXTPWR_EN_CTL            BIT(26)
-#define MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_2V            (0 << 24)
-#define MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_23V           (1 << 24)
-#define MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_17V           (2 << 24)
-#define MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_26V           (3 << 24)
-#define MIPI_CSIS_DPHY_BCTRL_L_REG_1P2_LVL_SEL                 BIT(23)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_80MV              (0 << 21)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_100MV             (1 << 21)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_120MV             (2 << 21)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_140MV             (3 << 21)
-#define MIPI_CSIS_DPHY_BCTRL_L_VREF_SRC_SEL                    BIT(20)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_715MV            (0 << 18)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_743MV            (1 << 18)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_650MV            (2 << 18)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_682MV            (3 << 18)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_PULSE_REJECT              BIT(17)
-#define MIPI_CSIS_DPHY_BCTRL_L_MSTRCLK_LP_SLEW_RATE_DOWN_0     (0 << 15)
-#define MIPI_CSIS_DPHY_BCTRL_L_MSTRCLK_LP_SLEW_RATE_DOWN_15P   (1 << 15)
-#define MIPI_CSIS_DPHY_BCTRL_L_MSTRCLK_LP_SLEW_RATE_DOWN_30P   (3 << 15)
-#define MIPI_CSIS_DPHY_BCTRL_L_MSTRCLK_LP_SLEW_RATE_UP         BIT(14)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_CD_HYS_60MV                  (0 << 13)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_CD_HYS_70MV                  (1 << 13)
-#define MIPI_CSIS_DPHY_BCTRL_L_BGR_CHOPPER_EN                  BIT(12)
-#define MIPI_CSIS_DPHY_BCTRL_L_ERRCONTENTION_LP_EN             BIT(11)
-#define MIPI_CSIS_DPHY_BCTRL_L_TXTRIGGER_CLK_EN                        BIT(10)
-#define MIPI_CSIS_DPHY_BCTRL_L_B_DPHYCTRL(n)                   (((n) * 25 / 1000000) << 0)
-
-/* D-PHY Master and Slave Control register High */
-#define MIPI_CSIS_DPHY_BCTRL_H                 0x34
-/* D-PHY Slave Control register Low */
-#define MIPI_CSIS_DPHY_SCTRL_L                 0x38
-/* D-PHY Slave Control register High */
-#define MIPI_CSIS_DPHY_SCTRL_H                 0x3c
-
-/* ISP Configuration register */
-#define MIPI_CSIS_ISP_CONFIG_CH(n)             (0x40 + (n) * 0x10)
-#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP_MSK      (0xff << 24)
-#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP(x)       ((x) << 24)
-#define MIPI_CSIS_ISPCFG_PIXEL_MODE_SINGLE     (0 << 12)
-#define MIPI_CSIS_ISPCFG_PIXEL_MODE_DUAL       (1 << 12)
-#define MIPI_CSIS_ISPCFG_PIXEL_MODE_QUAD       (2 << 12)       /* i.MX8M[MNP] only */
-#define MIPI_CSIS_ISPCFG_PIXEL_MASK            (3 << 12)
-#define MIPI_CSIS_ISPCFG_ALIGN_32BIT           BIT(11)
-#define MIPI_CSIS_ISPCFG_FMT(fmt)              ((fmt) << 2)
-#define MIPI_CSIS_ISPCFG_FMT_MASK              (0x3f << 2)
-
-/* ISP Image Resolution register */
-#define MIPI_CSIS_ISP_RESOL_CH(n)              (0x44 + (n) * 0x10)
-#define CSIS_MAX_PIX_WIDTH                     0xffff
-#define CSIS_MAX_PIX_HEIGHT                    0xffff
-
-/* ISP SYNC register */
-#define MIPI_CSIS_ISP_SYNC_CH(n)               (0x48 + (n) * 0x10)
-#define MIPI_CSIS_ISP_SYNC_HSYNC_LINTV_OFFSET  18
-#define MIPI_CSIS_ISP_SYNC_VSYNC_SINTV_OFFSET  12
-#define MIPI_CSIS_ISP_SYNC_VSYNC_EINTV_OFFSET  0
-
-/* ISP shadow registers */
-#define MIPI_CSIS_SDW_CONFIG_CH(n)             (0x80 + (n) * 0x10)
-#define MIPI_CSIS_SDW_RESOL_CH(n)              (0x84 + (n) * 0x10)
-#define MIPI_CSIS_SDW_SYNC_CH(n)               (0x88 + (n) * 0x10)
-
-/* Debug control register */
-#define MIPI_CSIS_DBG_CTRL                     0xc0
-#define MIPI_CSIS_DBG_INTR_MSK                 0xc4
-#define MIPI_CSIS_DBG_INTR_MSK_DT_NOT_SUPPORT  BIT(25)
-#define MIPI_CSIS_DBG_INTR_MSK_DT_IGNORE       BIT(24)
-#define MIPI_CSIS_DBG_INTR_MSK_ERR_FRAME_SIZE  BIT(20)
-#define MIPI_CSIS_DBG_INTR_MSK_TRUNCATED_FRAME BIT(16)
-#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FE                BIT(12)
-#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FS                BIT(8)
-#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_FALL  BIT(4)
-#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_RISE  BIT(0)
-#define MIPI_CSIS_DBG_INTR_SRC                 0xc8
-#define MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT  BIT(25)
-#define MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE       BIT(24)
-#define MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE  BIT(20)
-#define MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME BIT(16)
-#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FE                BIT(12)
-#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FS                BIT(8)
-#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL  BIT(4)
-#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE  BIT(0)
-
-#define MIPI_CSIS_FRAME_COUNTER_CH(n)          (0x0100 + (n) * 4)
-
-/* Non-image packet data buffers */
-#define MIPI_CSIS_PKTDATA_ODD                  0x2000
-#define MIPI_CSIS_PKTDATA_EVEN                 0x3000
-#define MIPI_CSIS_PKTDATA_SIZE                 SZ_4K
-
-#define DEFAULT_SCLK_CSIS_FREQ                 166000000UL
-
-/* MIPI CSI-2 Data Types */
-#define MIPI_CSI2_DATA_TYPE_YUV420_8           0x18
-#define MIPI_CSI2_DATA_TYPE_YUV420_10          0x19
-#define MIPI_CSI2_DATA_TYPE_LE_YUV420_8                0x1a
-#define MIPI_CSI2_DATA_TYPE_CS_YUV420_8                0x1c
-#define MIPI_CSI2_DATA_TYPE_CS_YUV420_10       0x1d
-#define MIPI_CSI2_DATA_TYPE_YUV422_8           0x1e
-#define MIPI_CSI2_DATA_TYPE_YUV422_10          0x1f
-#define MIPI_CSI2_DATA_TYPE_RGB565             0x22
-#define MIPI_CSI2_DATA_TYPE_RGB666             0x23
-#define MIPI_CSI2_DATA_TYPE_RGB888             0x24
-#define MIPI_CSI2_DATA_TYPE_RAW6               0x28
-#define MIPI_CSI2_DATA_TYPE_RAW7               0x29
-#define MIPI_CSI2_DATA_TYPE_RAW8               0x2a
-#define MIPI_CSI2_DATA_TYPE_RAW10              0x2b
-#define MIPI_CSI2_DATA_TYPE_RAW12              0x2c
-#define MIPI_CSI2_DATA_TYPE_RAW14              0x2d
-#define MIPI_CSI2_DATA_TYPE_USER(x)            (0x30 + (x))
-
-enum {
-       ST_POWERED      = 1,
-       ST_STREAMING    = 2,
-       ST_SUSPENDED    = 4,
-};
-
-struct mipi_csis_event {
-       bool debug;
-       u32 mask;
-       const char * const name;
-       unsigned int counter;
-};
-
-static const struct mipi_csis_event mipi_csis_events[] = {
-       /* Errors */
-       { false, MIPI_CSIS_INT_SRC_ERR_SOT_HS,          "SOT Error" },
-       { false, MIPI_CSIS_INT_SRC_ERR_LOST_FS,         "Lost Frame Start Error" },
-       { false, MIPI_CSIS_INT_SRC_ERR_LOST_FE,         "Lost Frame End Error" },
-       { false, MIPI_CSIS_INT_SRC_ERR_OVER,            "FIFO Overflow Error" },
-       { false, MIPI_CSIS_INT_SRC_ERR_WRONG_CFG,       "Wrong Configuration Error" },
-       { false, MIPI_CSIS_INT_SRC_ERR_ECC,             "ECC Error" },
-       { false, MIPI_CSIS_INT_SRC_ERR_CRC,             "CRC Error" },
-       { false, MIPI_CSIS_INT_SRC_ERR_UNKNOWN,         "Unknown Error" },
-       { true, MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT,  "Data Type Not Supported" },
-       { true, MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE,       "Data Type Ignored" },
-       { true, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE,  "Frame Size Error" },
-       { true, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME, "Truncated Frame" },
-       { true, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE,        "Early Frame End" },
-       { true, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS,        "Early Frame Start" },
-       /* Non-image data receive events */
-       { false, MIPI_CSIS_INT_SRC_EVEN_BEFORE,         "Non-image data before even frame" },
-       { false, MIPI_CSIS_INT_SRC_EVEN_AFTER,          "Non-image data after even frame" },
-       { false, MIPI_CSIS_INT_SRC_ODD_BEFORE,          "Non-image data before odd frame" },
-       { false, MIPI_CSIS_INT_SRC_ODD_AFTER,           "Non-image data after odd frame" },
-       /* Frame start/end */
-       { false, MIPI_CSIS_INT_SRC_FRAME_START,         "Frame Start" },
-       { false, MIPI_CSIS_INT_SRC_FRAME_END,           "Frame End" },
-       { true, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL,  "VSYNC Falling Edge" },
-       { true, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE,  "VSYNC Rising Edge" },
-};
-
-#define MIPI_CSIS_NUM_EVENTS ARRAY_SIZE(mipi_csis_events)
-
-enum mipi_csis_clk {
-       MIPI_CSIS_CLK_PCLK,
-       MIPI_CSIS_CLK_WRAP,
-       MIPI_CSIS_CLK_PHY,
-       MIPI_CSIS_CLK_AXI,
-};
-
-static const char * const mipi_csis_clk_id[] = {
-       "pclk",
-       "wrap",
-       "phy",
-       "axi",
-};
-
-enum mipi_csis_version {
-       MIPI_CSIS_V3_3,
-       MIPI_CSIS_V3_6_3,
-};
-
-struct mipi_csis_info {
-       enum mipi_csis_version version;
-       unsigned int num_clocks;
-};
-
-struct csi_state {
-       struct device *dev;
-       void __iomem *regs;
-       struct clk_bulk_data *clks;
-       struct reset_control *mrst;
-       struct regulator *mipi_phy_regulator;
-       const struct mipi_csis_info *info;
-
-       struct v4l2_subdev sd;
-       struct media_pad pads[CSIS_PADS_NUM];
-       struct v4l2_async_notifier notifier;
-       struct v4l2_subdev *src_sd;
-
-       struct v4l2_mbus_config_mipi_csi2 bus;
-       u32 clk_frequency;
-       u32 hs_settle;
-       u32 clk_settle;
-
-       struct mutex lock;      /* Protect csis_fmt, format_mbus and state */
-       const struct csis_pix_format *csis_fmt;
-       struct v4l2_mbus_framefmt format_mbus[CSIS_PADS_NUM];
-       u32 state;
-
-       spinlock_t slock;       /* Protect events */
-       struct mipi_csis_event events[MIPI_CSIS_NUM_EVENTS];
-       struct dentry *debugfs_root;
-       struct {
-               bool enable;
-               u32 hs_settle;
-               u32 clk_settle;
-       } debug;
-};
-
-/* -----------------------------------------------------------------------------
- * Format helpers
- */
-
-struct csis_pix_format {
-       u32 code;
-       u32 output;
-       u32 data_type;
-       u8 width;
-};
-
-static const struct csis_pix_format mipi_csis_formats[] = {
-       /* YUV formats. */
-       {
-               .code = MEDIA_BUS_FMT_UYVY8_1X16,
-               .output = MEDIA_BUS_FMT_UYVY8_1X16,
-               .data_type = MIPI_CSI2_DATA_TYPE_YUV422_8,
-               .width = 16,
-       },
-       /* RGB formats. */
-       {
-               .code = MEDIA_BUS_FMT_RGB565_1X16,
-               .output = MEDIA_BUS_FMT_RGB565_1X16,
-               .data_type = MIPI_CSI2_DATA_TYPE_RGB565,
-               .width = 16,
-       }, {
-               .code = MEDIA_BUS_FMT_BGR888_1X24,
-               .output = MEDIA_BUS_FMT_RGB888_1X24,
-               .data_type = MIPI_CSI2_DATA_TYPE_RGB888,
-               .width = 24,
-       },
-       /* RAW (Bayer and greyscale) formats. */
-       {
-               .code = MEDIA_BUS_FMT_SBGGR8_1X8,
-               .output = MEDIA_BUS_FMT_SBGGR8_1X8,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
-               .width = 8,
-       }, {
-               .code = MEDIA_BUS_FMT_SGBRG8_1X8,
-               .output = MEDIA_BUS_FMT_SGBRG8_1X8,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
-               .width = 8,
-       }, {
-               .code = MEDIA_BUS_FMT_SGRBG8_1X8,
-               .output = MEDIA_BUS_FMT_SGRBG8_1X8,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
-               .width = 8,
-       }, {
-               .code = MEDIA_BUS_FMT_SRGGB8_1X8,
-               .output = MEDIA_BUS_FMT_SRGGB8_1X8,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
-               .width = 8,
-       }, {
-               .code = MEDIA_BUS_FMT_Y8_1X8,
-               .output = MEDIA_BUS_FMT_Y8_1X8,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
-               .width = 8,
-       }, {
-               .code = MEDIA_BUS_FMT_SBGGR10_1X10,
-               .output = MEDIA_BUS_FMT_SBGGR10_1X10,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
-               .width = 10,
-       }, {
-               .code = MEDIA_BUS_FMT_SGBRG10_1X10,
-               .output = MEDIA_BUS_FMT_SGBRG10_1X10,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
-               .width = 10,
-       }, {
-               .code = MEDIA_BUS_FMT_SGRBG10_1X10,
-               .output = MEDIA_BUS_FMT_SGRBG10_1X10,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
-               .width = 10,
-       }, {
-               .code = MEDIA_BUS_FMT_SRGGB10_1X10,
-               .output = MEDIA_BUS_FMT_SRGGB10_1X10,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
-               .width = 10,
-       }, {
-               .code = MEDIA_BUS_FMT_Y10_1X10,
-               .output = MEDIA_BUS_FMT_Y10_1X10,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
-               .width = 10,
-       }, {
-               .code = MEDIA_BUS_FMT_SBGGR12_1X12,
-               .output = MEDIA_BUS_FMT_SBGGR12_1X12,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
-               .width = 12,
-       }, {
-               .code = MEDIA_BUS_FMT_SGBRG12_1X12,
-               .output = MEDIA_BUS_FMT_SGBRG12_1X12,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
-               .width = 12,
-       }, {
-               .code = MEDIA_BUS_FMT_SGRBG12_1X12,
-               .output = MEDIA_BUS_FMT_SGRBG12_1X12,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
-               .width = 12,
-       }, {
-               .code = MEDIA_BUS_FMT_SRGGB12_1X12,
-               .output = MEDIA_BUS_FMT_SRGGB12_1X12,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
-               .width = 12,
-       }, {
-               .code = MEDIA_BUS_FMT_Y12_1X12,
-               .output = MEDIA_BUS_FMT_Y12_1X12,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
-               .width = 12,
-       }, {
-               .code = MEDIA_BUS_FMT_SBGGR14_1X14,
-               .output = MEDIA_BUS_FMT_SBGGR14_1X14,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
-               .width = 14,
-       }, {
-               .code = MEDIA_BUS_FMT_SGBRG14_1X14,
-               .output = MEDIA_BUS_FMT_SGBRG14_1X14,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
-               .width = 14,
-       }, {
-               .code = MEDIA_BUS_FMT_SGRBG14_1X14,
-               .output = MEDIA_BUS_FMT_SGRBG14_1X14,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
-               .width = 14,
-       }, {
-               .code = MEDIA_BUS_FMT_SRGGB14_1X14,
-               .output = MEDIA_BUS_FMT_SRGGB14_1X14,
-               .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
-               .width = 14,
-       }
-};
-
-static const struct csis_pix_format *find_csis_format(u32 code)
-{
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(mipi_csis_formats); i++)
-               if (code == mipi_csis_formats[i].code)
-                       return &mipi_csis_formats[i];
-       return NULL;
-}
-
-/* -----------------------------------------------------------------------------
- * Hardware configuration
- */
-
-static inline u32 mipi_csis_read(struct csi_state *state, u32 reg)
-{
-       return readl(state->regs + reg);
-}
-
-static inline void mipi_csis_write(struct csi_state *state, u32 reg, u32 val)
-{
-       writel(val, state->regs + reg);
-}
-
-static void mipi_csis_enable_interrupts(struct csi_state *state, bool on)
-{
-       mipi_csis_write(state, MIPI_CSIS_INT_MSK, on ? 0xffffffff : 0);
-       mipi_csis_write(state, MIPI_CSIS_DBG_INTR_MSK, on ? 0xffffffff : 0);
-}
-
-static void mipi_csis_sw_reset(struct csi_state *state)
-{
-       u32 val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
-
-       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL,
-                       val | MIPI_CSIS_CMN_CTRL_RESET);
-       usleep_range(10, 20);
-}
-
-static void mipi_csis_system_enable(struct csi_state *state, int on)
-{
-       u32 val, mask;
-
-       val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
-       if (on)
-               val |= MIPI_CSIS_CMN_CTRL_ENABLE;
-       else
-               val &= ~MIPI_CSIS_CMN_CTRL_ENABLE;
-       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
-
-       val = mipi_csis_read(state, MIPI_CSIS_DPHY_CMN_CTRL);
-       val &= ~MIPI_CSIS_DPHY_CMN_CTRL_ENABLE;
-       if (on) {
-               mask = (1 << (state->bus.num_data_lanes + 1)) - 1;
-               val |= (mask & MIPI_CSIS_DPHY_CMN_CTRL_ENABLE);
-       }
-       mipi_csis_write(state, MIPI_CSIS_DPHY_CMN_CTRL, val);
-}
-
-/* Called with the state.lock mutex held */
-static void __mipi_csis_set_format(struct csi_state *state)
-{
-       struct v4l2_mbus_framefmt *mf = &state->format_mbus[CSIS_PAD_SINK];
-       u32 val;
-
-       /* Color format */
-       val = mipi_csis_read(state, MIPI_CSIS_ISP_CONFIG_CH(0));
-       val &= ~(MIPI_CSIS_ISPCFG_ALIGN_32BIT | MIPI_CSIS_ISPCFG_FMT_MASK
-               | MIPI_CSIS_ISPCFG_PIXEL_MASK);
-
-       /*
-        * YUV 4:2:2 can be transferred with 8 or 16 bits per clock sample
-        * (referred to in the documentation as single and dual pixel modes
-        * respectively, although the 8-bit mode transfers half a pixel per
-        * clock sample and the 16-bit mode one pixel). While both mode work
-        * when the CSIS is connected to a receiver that supports either option,
-        * single pixel mode requires clock rates twice as high. As all SoCs
-        * that integrate the CSIS can operate in 16-bit bit mode, and some do
-        * not support 8-bit mode (this is the case of the i.MX8MP), use dual
-        * pixel mode unconditionally.
-        *
-        * TODO: Verify which other formats require DUAL (or QUAD) modes.
-        */
-       if (state->csis_fmt->data_type == MIPI_CSI2_DATA_TYPE_YUV422_8)
-               val |= MIPI_CSIS_ISPCFG_PIXEL_MODE_DUAL;
-
-       val |= MIPI_CSIS_ISPCFG_FMT(state->csis_fmt->data_type);
-       mipi_csis_write(state, MIPI_CSIS_ISP_CONFIG_CH(0), val);
-
-       /* Pixel resolution */
-       val = mf->width | (mf->height << 16);
-       mipi_csis_write(state, MIPI_CSIS_ISP_RESOL_CH(0), val);
-}
-
-static int mipi_csis_calculate_params(struct csi_state *state)
-{
-       s64 link_freq;
-       u32 lane_rate;
-
-       /* Calculate the line rate from the pixel rate. */
-       link_freq = v4l2_get_link_freq(state->src_sd->ctrl_handler,
-                                      state->csis_fmt->width,
-                                      state->bus.num_data_lanes * 2);
-       if (link_freq < 0) {
-               dev_err(state->dev, "Unable to obtain link frequency: %d\n",
-                       (int)link_freq);
-               return link_freq;
-       }
-
-       lane_rate = link_freq * 2;
-
-       if (lane_rate < 80000000 || lane_rate > 1500000000) {
-               dev_dbg(state->dev, "Out-of-bound lane rate %u\n", lane_rate);
-               return -EINVAL;
-       }
-
-       /*
-        * The HSSETTLE counter value is document in a table, but can also
-        * easily be calculated. Hardcode the CLKSETTLE value to 0 for now
-        * (which is documented as corresponding to CSI-2 v0.87 to v1.00) until
-        * we figure out how to compute it correctly.
-        */
-       state->hs_settle = (lane_rate - 5000000) / 45000000;
-       state->clk_settle = 0;
-
-       dev_dbg(state->dev, "lane rate %u, Tclk_settle %u, Ths_settle %u\n",
-               lane_rate, state->clk_settle, state->hs_settle);
-
-       if (state->debug.hs_settle < 0xff) {
-               dev_dbg(state->dev, "overriding Ths_settle with %u\n",
-                       state->debug.hs_settle);
-               state->hs_settle = state->debug.hs_settle;
-       }
-
-       if (state->debug.clk_settle < 4) {
-               dev_dbg(state->dev, "overriding Tclk_settle with %u\n",
-                       state->debug.clk_settle);
-               state->clk_settle = state->debug.clk_settle;
-       }
-
-       return 0;
-}
-
-static void mipi_csis_set_params(struct csi_state *state)
-{
-       int lanes = state->bus.num_data_lanes;
-       u32 val;
-
-       val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
-       val &= ~MIPI_CSIS_CMN_CTRL_LANE_NR_MASK;
-       val |= (lanes - 1) << MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET;
-       if (state->info->version == MIPI_CSIS_V3_3)
-               val |= MIPI_CSIS_CMN_CTRL_INTER_MODE;
-       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
-
-       __mipi_csis_set_format(state);
-
-       mipi_csis_write(state, MIPI_CSIS_DPHY_CMN_CTRL,
-                       MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(state->hs_settle) |
-                       MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(state->clk_settle));
-
-       val = (0 << MIPI_CSIS_ISP_SYNC_HSYNC_LINTV_OFFSET)
-           | (0 << MIPI_CSIS_ISP_SYNC_VSYNC_SINTV_OFFSET)
-           | (0 << MIPI_CSIS_ISP_SYNC_VSYNC_EINTV_OFFSET);
-       mipi_csis_write(state, MIPI_CSIS_ISP_SYNC_CH(0), val);
-
-       val = mipi_csis_read(state, MIPI_CSIS_CLK_CTRL);
-       val |= MIPI_CSIS_CLK_CTRL_WCLK_SRC;
-       val |= MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(15);
-       val &= ~MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK;
-       mipi_csis_write(state, MIPI_CSIS_CLK_CTRL, val);
-
-       mipi_csis_write(state, MIPI_CSIS_DPHY_BCTRL_L,
-                       MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_715MV |
-                       MIPI_CSIS_DPHY_BCTRL_L_BGR_CHOPPER_FREQ_3MHZ |
-                       MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_2V |
-                       MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_80MV |
-                       MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_715MV |
-                       MIPI_CSIS_DPHY_BCTRL_L_LP_CD_HYS_60MV |
-                       MIPI_CSIS_DPHY_BCTRL_L_B_DPHYCTRL(20000000));
-       mipi_csis_write(state, MIPI_CSIS_DPHY_BCTRL_H, 0);
-
-       /* Update the shadow register. */
-       val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
-       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL,
-                       val | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW |
-                       MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL);
-}
-
-static int mipi_csis_clk_enable(struct csi_state *state)
-{
-       return clk_bulk_prepare_enable(state->info->num_clocks, state->clks);
-}
-
-static void mipi_csis_clk_disable(struct csi_state *state)
-{
-       clk_bulk_disable_unprepare(state->info->num_clocks, state->clks);
-}
-
-static int mipi_csis_clk_get(struct csi_state *state)
-{
-       unsigned int i;
-       int ret;
-
-       state->clks = devm_kcalloc(state->dev, state->info->num_clocks,
-                                  sizeof(*state->clks), GFP_KERNEL);
-
-       if (!state->clks)
-               return -ENOMEM;
-
-       for (i = 0; i < state->info->num_clocks; i++)
-               state->clks[i].id = mipi_csis_clk_id[i];
-
-       ret = devm_clk_bulk_get(state->dev, state->info->num_clocks,
-                               state->clks);
-       if (ret < 0)
-               return ret;
-
-       /* Set clock rate */
-       ret = clk_set_rate(state->clks[MIPI_CSIS_CLK_WRAP].clk,
-                          state->clk_frequency);
-       if (ret < 0)
-               dev_err(state->dev, "set rate=%d failed: %d\n",
-                       state->clk_frequency, ret);
-
-       return ret;
-}
-
-static void mipi_csis_start_stream(struct csi_state *state)
-{
-       mipi_csis_sw_reset(state);
-       mipi_csis_set_params(state);
-       mipi_csis_system_enable(state, true);
-       mipi_csis_enable_interrupts(state, true);
-}
-
-static void mipi_csis_stop_stream(struct csi_state *state)
-{
-       mipi_csis_enable_interrupts(state, false);
-       mipi_csis_system_enable(state, false);
-}
-
-static irqreturn_t mipi_csis_irq_handler(int irq, void *dev_id)
-{
-       struct csi_state *state = dev_id;
-       unsigned long flags;
-       unsigned int i;
-       u32 status;
-       u32 dbg_status;
-
-       status = mipi_csis_read(state, MIPI_CSIS_INT_SRC);
-       dbg_status = mipi_csis_read(state, MIPI_CSIS_DBG_INTR_SRC);
-
-       spin_lock_irqsave(&state->slock, flags);
-
-       /* Update the event/error counters */
-       if ((status & MIPI_CSIS_INT_SRC_ERRORS) || state->debug.enable) {
-               for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++) {
-                       struct mipi_csis_event *event = &state->events[i];
-
-                       if ((!event->debug && (status & event->mask)) ||
-                           (event->debug && (dbg_status & event->mask)))
-                               event->counter++;
-               }
-       }
-       spin_unlock_irqrestore(&state->slock, flags);
-
-       mipi_csis_write(state, MIPI_CSIS_INT_SRC, status);
-       mipi_csis_write(state, MIPI_CSIS_DBG_INTR_SRC, dbg_status);
-
-       return IRQ_HANDLED;
-}
-
-/* -----------------------------------------------------------------------------
- * PHY regulator and reset
- */
-
-static int mipi_csis_phy_enable(struct csi_state *state)
-{
-       if (state->info->version != MIPI_CSIS_V3_3)
-               return 0;
-
-       return regulator_enable(state->mipi_phy_regulator);
-}
-
-static int mipi_csis_phy_disable(struct csi_state *state)
-{
-       if (state->info->version != MIPI_CSIS_V3_3)
-               return 0;
-
-       return regulator_disable(state->mipi_phy_regulator);
-}
-
-static void mipi_csis_phy_reset(struct csi_state *state)
-{
-       if (state->info->version != MIPI_CSIS_V3_3)
-               return;
-
-       reset_control_assert(state->mrst);
-       msleep(20);
-       reset_control_deassert(state->mrst);
-}
-
-static int mipi_csis_phy_init(struct csi_state *state)
-{
-       if (state->info->version != MIPI_CSIS_V3_3)
-               return 0;
-
-       /* Get MIPI PHY reset and regulator. */
-       state->mrst = devm_reset_control_get_exclusive(state->dev, NULL);
-       if (IS_ERR(state->mrst))
-               return PTR_ERR(state->mrst);
-
-       state->mipi_phy_regulator = devm_regulator_get(state->dev, "phy");
-       if (IS_ERR(state->mipi_phy_regulator))
-               return PTR_ERR(state->mipi_phy_regulator);
-
-       return regulator_set_voltage(state->mipi_phy_regulator, 1000000,
-                                    1000000);
-}
-
-/* -----------------------------------------------------------------------------
- * Debug
- */
-
-static void mipi_csis_clear_counters(struct csi_state *state)
-{
-       unsigned long flags;
-       unsigned int i;
-
-       spin_lock_irqsave(&state->slock, flags);
-       for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++)
-               state->events[i].counter = 0;
-       spin_unlock_irqrestore(&state->slock, flags);
-}
-
-static void mipi_csis_log_counters(struct csi_state *state, bool non_errors)
-{
-       unsigned int num_events = non_errors ? MIPI_CSIS_NUM_EVENTS
-                               : MIPI_CSIS_NUM_EVENTS - 8;
-       unsigned long flags;
-       unsigned int i;
-
-       spin_lock_irqsave(&state->slock, flags);
-
-       for (i = 0; i < num_events; ++i) {
-               if (state->events[i].counter > 0 || state->debug.enable)
-                       dev_info(state->dev, "%s events: %d\n",
-                                state->events[i].name,
-                                state->events[i].counter);
-       }
-       spin_unlock_irqrestore(&state->slock, flags);
-}
-
-static int mipi_csis_dump_regs(struct csi_state *state)
-{
-       static const struct {
-               u32 offset;
-               const char * const name;
-       } registers[] = {
-               { MIPI_CSIS_CMN_CTRL, "CMN_CTRL" },
-               { MIPI_CSIS_CLK_CTRL, "CLK_CTRL" },
-               { MIPI_CSIS_INT_MSK, "INT_MSK" },
-               { MIPI_CSIS_DPHY_STATUS, "DPHY_STATUS" },
-               { MIPI_CSIS_DPHY_CMN_CTRL, "DPHY_CMN_CTRL" },
-               { MIPI_CSIS_DPHY_SCTRL_L, "DPHY_SCTRL_L" },
-               { MIPI_CSIS_DPHY_SCTRL_H, "DPHY_SCTRL_H" },
-               { MIPI_CSIS_ISP_CONFIG_CH(0), "ISP_CONFIG_CH0" },
-               { MIPI_CSIS_ISP_RESOL_CH(0), "ISP_RESOL_CH0" },
-               { MIPI_CSIS_SDW_CONFIG_CH(0), "SDW_CONFIG_CH0" },
-               { MIPI_CSIS_SDW_RESOL_CH(0), "SDW_RESOL_CH0" },
-               { MIPI_CSIS_DBG_CTRL, "DBG_CTRL" },
-               { MIPI_CSIS_FRAME_COUNTER_CH(0), "FRAME_COUNTER_CH0" },
-       };
-
-       unsigned int i;
-       u32 cfg;
-
-       dev_info(state->dev, "--- REGISTERS ---\n");
-
-       for (i = 0; i < ARRAY_SIZE(registers); i++) {
-               cfg = mipi_csis_read(state, registers[i].offset);
-               dev_info(state->dev, "%14s: 0x%08x\n", registers[i].name, cfg);
-       }
-
-       return 0;
-}
-
-static int mipi_csis_dump_regs_show(struct seq_file *m, void *private)
-{
-       struct csi_state *state = m->private;
-
-       return mipi_csis_dump_regs(state);
-}
-DEFINE_SHOW_ATTRIBUTE(mipi_csis_dump_regs);
-
-static void mipi_csis_debugfs_init(struct csi_state *state)
-{
-       state->debug.hs_settle = UINT_MAX;
-       state->debug.clk_settle = UINT_MAX;
-
-       state->debugfs_root = debugfs_create_dir(dev_name(state->dev), NULL);
-
-       debugfs_create_bool("debug_enable", 0600, state->debugfs_root,
-                           &state->debug.enable);
-       debugfs_create_file("dump_regs", 0600, state->debugfs_root, state,
-                           &mipi_csis_dump_regs_fops);
-       debugfs_create_u32("tclk_settle", 0600, state->debugfs_root,
-                          &state->debug.clk_settle);
-       debugfs_create_u32("ths_settle", 0600, state->debugfs_root,
-                          &state->debug.hs_settle);
-}
-
-static void mipi_csis_debugfs_exit(struct csi_state *state)
-{
-       debugfs_remove_recursive(state->debugfs_root);
-}
-
-/* -----------------------------------------------------------------------------
- * V4L2 subdev operations
- */
-
-static struct csi_state *mipi_sd_to_csis_state(struct v4l2_subdev *sdev)
-{
-       return container_of(sdev, struct csi_state, sd);
-}
-
-static int mipi_csis_s_stream(struct v4l2_subdev *sd, int enable)
-{
-       struct csi_state *state = mipi_sd_to_csis_state(sd);
-       int ret;
-
-       if (enable) {
-               ret = mipi_csis_calculate_params(state);
-               if (ret < 0)
-                       return ret;
-
-               mipi_csis_clear_counters(state);
-
-               ret = pm_runtime_resume_and_get(state->dev);
-               if (ret < 0)
-                       return ret;
-
-               ret = v4l2_subdev_call(state->src_sd, core, s_power, 1);
-               if (ret < 0 && ret != -ENOIOCTLCMD)
-                       goto done;
-       }
-
-       mutex_lock(&state->lock);
-
-       if (enable) {
-               if (state->state & ST_SUSPENDED) {
-                       ret = -EBUSY;
-                       goto unlock;
-               }
-
-               mipi_csis_start_stream(state);
-               ret = v4l2_subdev_call(state->src_sd, video, s_stream, 1);
-               if (ret < 0)
-                       goto unlock;
-
-               mipi_csis_log_counters(state, true);
-
-               state->state |= ST_STREAMING;
-       } else {
-               v4l2_subdev_call(state->src_sd, video, s_stream, 0);
-               ret = v4l2_subdev_call(state->src_sd, core, s_power, 0);
-               if (ret == -ENOIOCTLCMD)
-                       ret = 0;
-               mipi_csis_stop_stream(state);
-               state->state &= ~ST_STREAMING;
-               if (state->debug.enable)
-                       mipi_csis_log_counters(state, true);
-       }
-
-unlock:
-       mutex_unlock(&state->lock);
-
-done:
-       if (!enable || ret < 0)
-               pm_runtime_put(state->dev);
-
-       return ret;
-}
-
-static struct v4l2_mbus_framefmt *
-mipi_csis_get_format(struct csi_state *state,
-                    struct v4l2_subdev_state *sd_state,
-                    enum v4l2_subdev_format_whence which,
-                    unsigned int pad)
-{
-       if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(&state->sd, sd_state, pad);
-
-       return &state->format_mbus[pad];
-}
-
-static int mipi_csis_init_cfg(struct v4l2_subdev *sd,
-                             struct v4l2_subdev_state *sd_state)
-{
-       struct csi_state *state = mipi_sd_to_csis_state(sd);
-       struct v4l2_mbus_framefmt *fmt_sink;
-       struct v4l2_mbus_framefmt *fmt_source;
-       enum v4l2_subdev_format_whence which;
-
-       which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
-       fmt_sink = mipi_csis_get_format(state, sd_state, which, CSIS_PAD_SINK);
-
-       fmt_sink->code = MEDIA_BUS_FMT_UYVY8_1X16;
-       fmt_sink->width = MIPI_CSIS_DEF_PIX_WIDTH;
-       fmt_sink->height = MIPI_CSIS_DEF_PIX_HEIGHT;
-       fmt_sink->field = V4L2_FIELD_NONE;
-
-       fmt_sink->colorspace = V4L2_COLORSPACE_SMPTE170M;
-       fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace);
-       fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace);
-       fmt_sink->quantization =
-               V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace,
-                                             fmt_sink->ycbcr_enc);
-
-       /*
-        * When called from mipi_csis_subdev_init() to initialize the active
-        * configuration, cfg is NULL, which indicates there's no source pad
-        * configuration to set.
-        */
-       if (!sd_state)
-               return 0;
-
-       fmt_source = mipi_csis_get_format(state, sd_state, which,
-                                         CSIS_PAD_SOURCE);
-       *fmt_source = *fmt_sink;
-
-       return 0;
-}
-
-static int mipi_csis_get_fmt(struct v4l2_subdev *sd,
-                            struct v4l2_subdev_state *sd_state,
-                            struct v4l2_subdev_format *sdformat)
-{
-       struct csi_state *state = mipi_sd_to_csis_state(sd);
-       struct v4l2_mbus_framefmt *fmt;
-
-       fmt = mipi_csis_get_format(state, sd_state, sdformat->which,
-                                  sdformat->pad);
-
-       mutex_lock(&state->lock);
-       sdformat->format = *fmt;
-       mutex_unlock(&state->lock);
-
-       return 0;
-}
-
-static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd,
-                                   struct v4l2_subdev_state *sd_state,
-                                   struct v4l2_subdev_mbus_code_enum *code)
-{
-       struct csi_state *state = mipi_sd_to_csis_state(sd);
-
-       /*
-        * The CSIS can't transcode in any way, the source format is identical
-        * to the sink format.
-        */
-       if (code->pad == CSIS_PAD_SOURCE) {
-               struct v4l2_mbus_framefmt *fmt;
-
-               if (code->index > 0)
-                       return -EINVAL;
-
-               fmt = mipi_csis_get_format(state, sd_state, code->which,
-                                          code->pad);
-               code->code = fmt->code;
-               return 0;
-       }
-
-       if (code->pad != CSIS_PAD_SINK)
-               return -EINVAL;
-
-       if (code->index >= ARRAY_SIZE(mipi_csis_formats))
-               return -EINVAL;
-
-       code->code = mipi_csis_formats[code->index].code;
-
-       return 0;
-}
-
-static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
-                            struct v4l2_subdev_state *sd_state,
-                            struct v4l2_subdev_format *sdformat)
-{
-       struct csi_state *state = mipi_sd_to_csis_state(sd);
-       struct csis_pix_format const *csis_fmt;
-       struct v4l2_mbus_framefmt *fmt;
-       unsigned int align;
-
-       /*
-        * The CSIS can't transcode in any way, the source format can't be
-        * modified.
-        */
-       if (sdformat->pad == CSIS_PAD_SOURCE)
-               return mipi_csis_get_fmt(sd, sd_state, sdformat);
-
-       if (sdformat->pad != CSIS_PAD_SINK)
-               return -EINVAL;
-
-       /*
-        * Validate the media bus code and clamp and align the size.
-        *
-        * The total number of bits per line must be a multiple of 8. We thus
-        * need to align the width for formats that are not multiples of 8
-        * bits.
-        */
-       csis_fmt = find_csis_format(sdformat->format.code);
-       if (!csis_fmt)
-               csis_fmt = &mipi_csis_formats[0];
-
-       switch (csis_fmt->width % 8) {
-       case 0:
-               align = 0;
-               break;
-       case 4:
-               align = 1;
-               break;
-       case 2:
-       case 6:
-               align = 2;
-               break;
-       default:
-               /* 1, 3, 5, 7 */
-               align = 3;
-               break;
-       }
-
-       v4l_bound_align_image(&sdformat->format.width, 1,
-                             CSIS_MAX_PIX_WIDTH, align,
-                             &sdformat->format.height, 1,
-                             CSIS_MAX_PIX_HEIGHT, 0, 0);
-
-       fmt = mipi_csis_get_format(state, sd_state, sdformat->which,
-                                  sdformat->pad);
-
-       mutex_lock(&state->lock);
-
-       fmt->code = csis_fmt->code;
-       fmt->width = sdformat->format.width;
-       fmt->height = sdformat->format.height;
-       fmt->colorspace = sdformat->format.colorspace;
-       fmt->quantization = sdformat->format.quantization;
-       fmt->xfer_func = sdformat->format.xfer_func;
-       fmt->ycbcr_enc = sdformat->format.ycbcr_enc;
-
-       sdformat->format = *fmt;
-
-       /* Propagate the format from sink to source. */
-       fmt = mipi_csis_get_format(state, sd_state, sdformat->which,
-                                  CSIS_PAD_SOURCE);
-       *fmt = sdformat->format;
-
-       /* The format on the source pad might change due to unpacking. */
-       fmt->code = csis_fmt->output;
-
-       /* Store the CSIS format descriptor for active formats. */
-       if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
-               state->csis_fmt = csis_fmt;
-
-       mutex_unlock(&state->lock);
-
-       return 0;
-}
-
-static int mipi_csis_log_status(struct v4l2_subdev *sd)
-{
-       struct csi_state *state = mipi_sd_to_csis_state(sd);
-
-       mutex_lock(&state->lock);
-       mipi_csis_log_counters(state, true);
-       if (state->debug.enable && (state->state & ST_POWERED))
-               mipi_csis_dump_regs(state);
-       mutex_unlock(&state->lock);
-
-       return 0;
-}
-
-static const struct v4l2_subdev_core_ops mipi_csis_core_ops = {
-       .log_status     = mipi_csis_log_status,
-};
-
-static const struct v4l2_subdev_video_ops mipi_csis_video_ops = {
-       .s_stream       = mipi_csis_s_stream,
-};
-
-static const struct v4l2_subdev_pad_ops mipi_csis_pad_ops = {
-       .init_cfg               = mipi_csis_init_cfg,
-       .enum_mbus_code         = mipi_csis_enum_mbus_code,
-       .get_fmt                = mipi_csis_get_fmt,
-       .set_fmt                = mipi_csis_set_fmt,
-};
-
-static const struct v4l2_subdev_ops mipi_csis_subdev_ops = {
-       .core   = &mipi_csis_core_ops,
-       .video  = &mipi_csis_video_ops,
-       .pad    = &mipi_csis_pad_ops,
-};
-
-/* -----------------------------------------------------------------------------
- * Media entity operations
- */
-
-static int mipi_csis_link_setup(struct media_entity *entity,
-                               const struct media_pad *local_pad,
-                               const struct media_pad *remote_pad, u32 flags)
-{
-       struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
-       struct csi_state *state = mipi_sd_to_csis_state(sd);
-       struct v4l2_subdev *remote_sd;
-
-       dev_dbg(state->dev, "link setup %s -> %s", remote_pad->entity->name,
-               local_pad->entity->name);
-
-       /* We only care about the link to the source. */
-       if (!(local_pad->flags & MEDIA_PAD_FL_SINK))
-               return 0;
-
-       remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
-
-       if (flags & MEDIA_LNK_FL_ENABLED) {
-               if (state->src_sd)
-                       return -EBUSY;
-
-               state->src_sd = remote_sd;
-       } else {
-               state->src_sd = NULL;
-       }
-
-       return 0;
-}
-
-static const struct media_entity_operations mipi_csis_entity_ops = {
-       .link_setup     = mipi_csis_link_setup,
-       .link_validate  = v4l2_subdev_link_validate,
-       .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
-};
-
-/* -----------------------------------------------------------------------------
- * Async subdev notifier
- */
-
-static struct csi_state *
-mipi_notifier_to_csis_state(struct v4l2_async_notifier *n)
-{
-       return container_of(n, struct csi_state, notifier);
-}
-
-static int mipi_csis_notify_bound(struct v4l2_async_notifier *notifier,
-                                 struct v4l2_subdev *sd,
-                                 struct v4l2_async_subdev *asd)
-{
-       struct csi_state *state = mipi_notifier_to_csis_state(notifier);
-       struct media_pad *sink = &state->sd.entity.pads[CSIS_PAD_SINK];
-
-       return v4l2_create_fwnode_links_to_pad(sd, sink, 0);
-}
-
-static const struct v4l2_async_notifier_operations mipi_csis_notify_ops = {
-       .bound = mipi_csis_notify_bound,
-};
-
-static int mipi_csis_async_register(struct csi_state *state)
-{
-       struct v4l2_fwnode_endpoint vep = {
-               .bus_type = V4L2_MBUS_CSI2_DPHY,
-       };
-       struct v4l2_async_subdev *asd;
-       struct fwnode_handle *ep;
-       unsigned int i;
-       int ret;
-
-       v4l2_async_nf_init(&state->notifier);
-
-       ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0,
-                                            FWNODE_GRAPH_ENDPOINT_NEXT);
-       if (!ep)
-               return -ENOTCONN;
-
-       ret = v4l2_fwnode_endpoint_parse(ep, &vep);
-       if (ret)
-               goto err_parse;
-
-       for (i = 0; i < vep.bus.mipi_csi2.num_data_lanes; ++i) {
-               if (vep.bus.mipi_csi2.data_lanes[i] != i + 1) {
-                       dev_err(state->dev,
-                               "data lanes reordering is not supported");
-                       ret = -EINVAL;
-                       goto err_parse;
-               }
-       }
-
-       state->bus = vep.bus.mipi_csi2;
-
-       dev_dbg(state->dev, "data lanes: %d\n", state->bus.num_data_lanes);
-       dev_dbg(state->dev, "flags: 0x%08x\n", state->bus.flags);
-
-       asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep,
-                                             struct v4l2_async_subdev);
-       if (IS_ERR(asd)) {
-               ret = PTR_ERR(asd);
-               goto err_parse;
-       }
-
-       fwnode_handle_put(ep);
-
-       state->notifier.ops = &mipi_csis_notify_ops;
-
-       ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier);
-       if (ret)
-               return ret;
-
-       return v4l2_async_register_subdev(&state->sd);
-
-err_parse:
-       fwnode_handle_put(ep);
-
-       return ret;
-}
-
-/* -----------------------------------------------------------------------------
- * Suspend/resume
- */
-
-static int mipi_csis_pm_suspend(struct device *dev, bool runtime)
-{
-       struct v4l2_subdev *sd = dev_get_drvdata(dev);
-       struct csi_state *state = mipi_sd_to_csis_state(sd);
-       int ret = 0;
-
-       mutex_lock(&state->lock);
-       if (state->state & ST_POWERED) {
-               mipi_csis_stop_stream(state);
-               ret = mipi_csis_phy_disable(state);
-               if (ret)
-                       goto unlock;
-               mipi_csis_clk_disable(state);
-               state->state &= ~ST_POWERED;
-               if (!runtime)
-                       state->state |= ST_SUSPENDED;
-       }
-
-unlock:
-       mutex_unlock(&state->lock);
-
-       return ret ? -EAGAIN : 0;
-}
-
-static int mipi_csis_pm_resume(struct device *dev, bool runtime)
-{
-       struct v4l2_subdev *sd = dev_get_drvdata(dev);
-       struct csi_state *state = mipi_sd_to_csis_state(sd);
-       int ret = 0;
-
-       mutex_lock(&state->lock);
-       if (!runtime && !(state->state & ST_SUSPENDED))
-               goto unlock;
-
-       if (!(state->state & ST_POWERED)) {
-               ret = mipi_csis_phy_enable(state);
-               if (ret)
-                       goto unlock;
-
-               state->state |= ST_POWERED;
-               mipi_csis_clk_enable(state);
-       }
-       if (state->state & ST_STREAMING)
-               mipi_csis_start_stream(state);
-
-       state->state &= ~ST_SUSPENDED;
-
-unlock:
-       mutex_unlock(&state->lock);
-
-       return ret ? -EAGAIN : 0;
-}
-
-static int __maybe_unused mipi_csis_suspend(struct device *dev)
-{
-       return mipi_csis_pm_suspend(dev, false);
-}
-
-static int __maybe_unused mipi_csis_resume(struct device *dev)
-{
-       return mipi_csis_pm_resume(dev, false);
-}
-
-static int __maybe_unused mipi_csis_runtime_suspend(struct device *dev)
-{
-       return mipi_csis_pm_suspend(dev, true);
-}
-
-static int __maybe_unused mipi_csis_runtime_resume(struct device *dev)
-{
-       return mipi_csis_pm_resume(dev, true);
-}
-
-static const struct dev_pm_ops mipi_csis_pm_ops = {
-       SET_RUNTIME_PM_OPS(mipi_csis_runtime_suspend, mipi_csis_runtime_resume,
-                          NULL)
-       SET_SYSTEM_SLEEP_PM_OPS(mipi_csis_suspend, mipi_csis_resume)
-};
-
-/* -----------------------------------------------------------------------------
- * Probe/remove & platform driver
- */
-
-static int mipi_csis_subdev_init(struct csi_state *state)
-{
-       struct v4l2_subdev *sd = &state->sd;
-
-       v4l2_subdev_init(sd, &mipi_csis_subdev_ops);
-       sd->owner = THIS_MODULE;
-       snprintf(sd->name, sizeof(sd->name), "csis-%s",
-                dev_name(state->dev));
-
-       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-       sd->ctrl_handler = NULL;
-
-       sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
-       sd->entity.ops = &mipi_csis_entity_ops;
-
-       sd->dev = state->dev;
-
-       state->csis_fmt = &mipi_csis_formats[0];
-       mipi_csis_init_cfg(sd, NULL);
-
-       state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK
-                                        | MEDIA_PAD_FL_MUST_CONNECT;
-       state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
-                                          | MEDIA_PAD_FL_MUST_CONNECT;
-       return media_entity_pads_init(&sd->entity, CSIS_PADS_NUM,
-                                     state->pads);
-}
-
-static int mipi_csis_parse_dt(struct csi_state *state)
-{
-       struct device_node *node = state->dev->of_node;
-
-       if (of_property_read_u32(node, "clock-frequency",
-                                &state->clk_frequency))
-               state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
-
-       return 0;
-}
-
-static int mipi_csis_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct csi_state *state;
-       int irq;
-       int ret;
-
-       state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
-       if (!state)
-               return -ENOMEM;
-
-       mutex_init(&state->lock);
-       spin_lock_init(&state->slock);
-
-       state->dev = dev;
-       state->info = of_device_get_match_data(dev);
-
-       memcpy(state->events, mipi_csis_events, sizeof(state->events));
-
-       /* Parse DT properties. */
-       ret = mipi_csis_parse_dt(state);
-       if (ret < 0) {
-               dev_err(dev, "Failed to parse device tree: %d\n", ret);
-               return ret;
-       }
-
-       /* Acquire resources. */
-       state->regs = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(state->regs))
-               return PTR_ERR(state->regs);
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
-
-       ret = mipi_csis_phy_init(state);
-       if (ret < 0)
-               return ret;
-
-       ret = mipi_csis_clk_get(state);
-       if (ret < 0)
-               return ret;
-
-       /* Reset PHY and enable the clocks. */
-       mipi_csis_phy_reset(state);
-
-       ret = mipi_csis_clk_enable(state);
-       if (ret < 0) {
-               dev_err(state->dev, "failed to enable clocks: %d\n", ret);
-               return ret;
-       }
-
-       /* Now that the hardware is initialized, request the interrupt. */
-       ret = devm_request_irq(dev, irq, mipi_csis_irq_handler, 0,
-                              dev_name(dev), state);
-       if (ret) {
-               dev_err(dev, "Interrupt request failed\n");
-               goto disable_clock;
-       }
-
-       /* Initialize and register the subdev. */
-       ret = mipi_csis_subdev_init(state);
-       if (ret < 0)
-               goto disable_clock;
-
-       platform_set_drvdata(pdev, &state->sd);
-
-       ret = mipi_csis_async_register(state);
-       if (ret < 0) {
-               dev_err(dev, "async register failed: %d\n", ret);
-               goto cleanup;
-       }
-
-       /* Initialize debugfs. */
-       mipi_csis_debugfs_init(state);
-
-       /* Enable runtime PM. */
-       pm_runtime_enable(dev);
-       if (!pm_runtime_enabled(dev)) {
-               ret = mipi_csis_pm_resume(dev, true);
-               if (ret < 0)
-                       goto unregister_all;
-       }
-
-       dev_info(dev, "lanes: %d, freq: %u\n",
-                state->bus.num_data_lanes, state->clk_frequency);
-
-       return 0;
-
-unregister_all:
-       mipi_csis_debugfs_exit(state);
-cleanup:
-       media_entity_cleanup(&state->sd.entity);
-       v4l2_async_nf_unregister(&state->notifier);
-       v4l2_async_nf_cleanup(&state->notifier);
-       v4l2_async_unregister_subdev(&state->sd);
-disable_clock:
-       mipi_csis_clk_disable(state);
-       mutex_destroy(&state->lock);
-
-       return ret;
-}
-
-static int mipi_csis_remove(struct platform_device *pdev)
-{
-       struct v4l2_subdev *sd = platform_get_drvdata(pdev);
-       struct csi_state *state = mipi_sd_to_csis_state(sd);
-
-       mipi_csis_debugfs_exit(state);
-       v4l2_async_nf_unregister(&state->notifier);
-       v4l2_async_nf_cleanup(&state->notifier);
-       v4l2_async_unregister_subdev(&state->sd);
-
-       pm_runtime_disable(&pdev->dev);
-       mipi_csis_pm_suspend(&pdev->dev, true);
-       mipi_csis_clk_disable(state);
-       media_entity_cleanup(&state->sd.entity);
-       mutex_destroy(&state->lock);
-       pm_runtime_set_suspended(&pdev->dev);
-
-       return 0;
-}
-
-static const struct of_device_id mipi_csis_of_match[] = {
-       {
-               .compatible = "fsl,imx7-mipi-csi2",
-               .data = &(const struct mipi_csis_info){
-                       .version = MIPI_CSIS_V3_3,
-                       .num_clocks = 3,
-               },
-       }, {
-               .compatible = "fsl,imx8mm-mipi-csi2",
-               .data = &(const struct mipi_csis_info){
-                       .version = MIPI_CSIS_V3_6_3,
-                       .num_clocks = 4,
-               },
-       },
-       { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, mipi_csis_of_match);
-
-static struct platform_driver mipi_csis_driver = {
-       .probe          = mipi_csis_probe,
-       .remove         = mipi_csis_remove,
-       .driver         = {
-               .of_match_table = mipi_csis_of_match,
-               .name           = CSIS_DRIVER_NAME,
-               .pm             = &mipi_csis_pm_ops,
-       },
-};
-
-module_platform_driver(mipi_csis_driver);
-
-MODULE_DESCRIPTION("i.MX7 & i.MX8 MIPI CSI-2 receiver driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:imx-mipi-csi2");
diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c
deleted file mode 100644 (file)
index 3ce84d0..0000000
+++ /dev/null
@@ -1,912 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Support eMMa-PrP through mem2mem framework.
- *
- * eMMa-PrP is a piece of HW that allows fetching buffers
- * from one memory location and do several operations on
- * them such as scaling or format conversion giving, as a result
- * a new processed buffer in another memory location.
- *
- * Based on mem2mem_testdev.c by Pawel Osciak.
- *
- * Copyright (c) 2011 Vista Silicon S.L.
- * Javier Martin <javier.martin@vista-silicon.com>
- */
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-
-#include <linux/platform_device.h>
-#include <media/v4l2-mem2mem.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-dma-contig.h>
-#include <linux/sizes.h>
-
-#define EMMAPRP_MODULE_NAME "mem2mem-emmaprp"
-
-MODULE_DESCRIPTION("Mem-to-mem device which supports eMMa-PrP present in mx2 SoCs");
-MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.0.1");
-
-static bool debug;
-module_param(debug, bool, 0644);
-
-#define MIN_W 32
-#define MIN_H 32
-#define MAX_W 2040
-#define MAX_H 2046
-
-#define S_ALIGN                1 /* multiple of 2 */
-#define W_ALIGN_YUV420 3 /* multiple of 8 */
-#define W_ALIGN_OTHERS 2 /* multiple of 4 */
-#define H_ALIGN                1 /* multiple of 2 */
-
-/* Flags that indicate a format can be used for capture/output */
-#define MEM2MEM_CAPTURE        (1 << 0)
-#define MEM2MEM_OUTPUT (1 << 1)
-
-#define MEM2MEM_NAME           "m2m-emmaprp"
-
-/* In bytes, per queue */
-#define MEM2MEM_VID_MEM_LIMIT  SZ_16M
-
-#define dprintk(dev, fmt, arg...) \
-       v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
-
-/* EMMA PrP */
-#define PRP_CNTL                        0x00
-#define PRP_INTR_CNTL                   0x04
-#define PRP_INTRSTATUS                  0x08
-#define PRP_SOURCE_Y_PTR                0x0c
-#define PRP_SOURCE_CB_PTR               0x10
-#define PRP_SOURCE_CR_PTR               0x14
-#define PRP_DEST_RGB1_PTR               0x18
-#define PRP_DEST_RGB2_PTR               0x1c
-#define PRP_DEST_Y_PTR                  0x20
-#define PRP_DEST_CB_PTR                 0x24
-#define PRP_DEST_CR_PTR                 0x28
-#define PRP_SRC_FRAME_SIZE              0x2c
-#define PRP_DEST_CH1_LINE_STRIDE        0x30
-#define PRP_SRC_PIXEL_FORMAT_CNTL       0x34
-#define PRP_CH1_PIXEL_FORMAT_CNTL       0x38
-#define PRP_CH1_OUT_IMAGE_SIZE          0x3c
-#define PRP_CH2_OUT_IMAGE_SIZE          0x40
-#define PRP_SRC_LINE_STRIDE             0x44
-#define PRP_CSC_COEF_012                0x48
-#define PRP_CSC_COEF_345                0x4c
-#define PRP_CSC_COEF_678                0x50
-#define PRP_CH1_RZ_HORI_COEF1           0x54
-#define PRP_CH1_RZ_HORI_COEF2           0x58
-#define PRP_CH1_RZ_HORI_VALID           0x5c
-#define PRP_CH1_RZ_VERT_COEF1           0x60
-#define PRP_CH1_RZ_VERT_COEF2           0x64
-#define PRP_CH1_RZ_VERT_VALID           0x68
-#define PRP_CH2_RZ_HORI_COEF1           0x6c
-#define PRP_CH2_RZ_HORI_COEF2           0x70
-#define PRP_CH2_RZ_HORI_VALID           0x74
-#define PRP_CH2_RZ_VERT_COEF1           0x78
-#define PRP_CH2_RZ_VERT_COEF2           0x7c
-#define PRP_CH2_RZ_VERT_VALID           0x80
-
-#define PRP_CNTL_CH1EN          (1 << 0)
-#define PRP_CNTL_CH2EN          (1 << 1)
-#define PRP_CNTL_CSIEN          (1 << 2)
-#define PRP_CNTL_DATA_IN_YUV420 (0 << 3)
-#define PRP_CNTL_DATA_IN_YUV422 (1 << 3)
-#define PRP_CNTL_DATA_IN_RGB16  (2 << 3)
-#define PRP_CNTL_DATA_IN_RGB32  (3 << 3)
-#define PRP_CNTL_CH1_OUT_RGB8   (0 << 5)
-#define PRP_CNTL_CH1_OUT_RGB16  (1 << 5)
-#define PRP_CNTL_CH1_OUT_RGB32  (2 << 5)
-#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5)
-#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7)
-#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7)
-#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7)
-#define PRP_CNTL_CH1_LEN        (1 << 9)
-#define PRP_CNTL_CH2_LEN        (1 << 10)
-#define PRP_CNTL_SKIP_FRAME     (1 << 11)
-#define PRP_CNTL_SWRST          (1 << 12)
-#define PRP_CNTL_CLKEN          (1 << 13)
-#define PRP_CNTL_WEN            (1 << 14)
-#define PRP_CNTL_CH1BYP         (1 << 15)
-#define PRP_CNTL_IN_TSKIP(x)    ((x) << 16)
-#define PRP_CNTL_CH1_TSKIP(x)   ((x) << 19)
-#define PRP_CNTL_CH2_TSKIP(x)   ((x) << 22)
-#define PRP_CNTL_INPUT_FIFO_LEVEL(x)    ((x) << 25)
-#define PRP_CNTL_RZ_FIFO_LEVEL(x)       ((x) << 27)
-#define PRP_CNTL_CH2B1EN        (1 << 29)
-#define PRP_CNTL_CH2B2EN        (1 << 30)
-#define PRP_CNTL_CH2FEN         (1UL << 31)
-
-#define PRP_SIZE_HEIGHT(x)     (x)
-#define PRP_SIZE_WIDTH(x)      ((x) << 16)
-
-/* IRQ Enable and status register */
-#define PRP_INTR_RDERR          (1 << 0)
-#define PRP_INTR_CH1WERR        (1 << 1)
-#define PRP_INTR_CH2WERR        (1 << 2)
-#define PRP_INTR_CH1FC          (1 << 3)
-#define PRP_INTR_CH2FC          (1 << 5)
-#define PRP_INTR_LBOVF          (1 << 7)
-#define PRP_INTR_CH2OVF         (1 << 8)
-
-#define PRP_INTR_ST_RDERR      (1 << 0)
-#define PRP_INTR_ST_CH1WERR    (1 << 1)
-#define PRP_INTR_ST_CH2WERR    (1 << 2)
-#define PRP_INTR_ST_CH2B2CI    (1 << 3)
-#define PRP_INTR_ST_CH2B1CI    (1 << 4)
-#define PRP_INTR_ST_CH1B2CI    (1 << 5)
-#define PRP_INTR_ST_CH1B1CI    (1 << 6)
-#define PRP_INTR_ST_LBOVF      (1 << 7)
-#define PRP_INTR_ST_CH2OVF     (1 << 8)
-
-struct emmaprp_fmt {
-       u32     fourcc;
-       /* Types the format can be used for */
-       u32     types;
-};
-
-static struct emmaprp_fmt formats[] = {
-       {
-               .fourcc = V4L2_PIX_FMT_YUV420,
-               .types  = MEM2MEM_CAPTURE,
-       },
-       {
-               .fourcc = V4L2_PIX_FMT_YUYV,
-               .types  = MEM2MEM_OUTPUT,
-       },
-};
-
-/* Per-queue, driver-specific private data */
-struct emmaprp_q_data {
-       unsigned int            width;
-       unsigned int            height;
-       unsigned int            sizeimage;
-       struct emmaprp_fmt      *fmt;
-};
-
-enum {
-       V4L2_M2M_SRC = 0,
-       V4L2_M2M_DST = 1,
-};
-
-#define NUM_FORMATS ARRAY_SIZE(formats)
-
-static struct emmaprp_fmt *find_format(struct v4l2_format *f)
-{
-       struct emmaprp_fmt *fmt;
-       unsigned int k;
-
-       for (k = 0; k < NUM_FORMATS; k++) {
-               fmt = &formats[k];
-               if (fmt->fourcc == f->fmt.pix.pixelformat)
-                       break;
-       }
-
-       if (k == NUM_FORMATS)
-               return NULL;
-
-       return &formats[k];
-}
-
-struct emmaprp_dev {
-       struct v4l2_device      v4l2_dev;
-       struct video_device     *vfd;
-
-       struct mutex            dev_mutex;
-       spinlock_t              irqlock;
-
-       void __iomem            *base_emma;
-       struct clk              *clk_emma_ahb, *clk_emma_ipg;
-
-       struct v4l2_m2m_dev     *m2m_dev;
-};
-
-struct emmaprp_ctx {
-       struct v4l2_fh          fh;
-       struct emmaprp_dev      *dev;
-       /* Abort requested by m2m */
-       int                     aborting;
-       struct emmaprp_q_data   q_data[2];
-};
-
-static struct emmaprp_q_data *get_q_data(struct emmaprp_ctx *ctx,
-                                        enum v4l2_buf_type type)
-{
-       switch (type) {
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-               return &(ctx->q_data[V4L2_M2M_SRC]);
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               return &(ctx->q_data[V4L2_M2M_DST]);
-       default:
-               BUG();
-       }
-       return NULL;
-}
-
-/*
- * mem2mem callbacks
- */
-static void emmaprp_job_abort(void *priv)
-{
-       struct emmaprp_ctx *ctx = priv;
-       struct emmaprp_dev *pcdev = ctx->dev;
-
-       ctx->aborting = 1;
-
-       dprintk(pcdev, "Aborting task\n");
-
-       v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->fh.m2m_ctx);
-}
-
-static inline void emmaprp_dump_regs(struct emmaprp_dev *pcdev)
-{
-       dprintk(pcdev,
-               "eMMa-PrP Registers:\n"
-               "  SOURCE_Y_PTR = 0x%08X\n"
-               "  SRC_FRAME_SIZE = 0x%08X\n"
-               "  DEST_Y_PTR = 0x%08X\n"
-               "  DEST_CR_PTR = 0x%08X\n"
-               "  DEST_CB_PTR = 0x%08X\n"
-               "  CH2_OUT_IMAGE_SIZE = 0x%08X\n"
-               "  CNTL = 0x%08X\n",
-               readl(pcdev->base_emma + PRP_SOURCE_Y_PTR),
-               readl(pcdev->base_emma + PRP_SRC_FRAME_SIZE),
-               readl(pcdev->base_emma + PRP_DEST_Y_PTR),
-               readl(pcdev->base_emma + PRP_DEST_CR_PTR),
-               readl(pcdev->base_emma + PRP_DEST_CB_PTR),
-               readl(pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE),
-               readl(pcdev->base_emma + PRP_CNTL));
-}
-
-static void emmaprp_device_run(void *priv)
-{
-       struct emmaprp_ctx *ctx = priv;
-       struct emmaprp_q_data *s_q_data, *d_q_data;
-       struct vb2_v4l2_buffer *src_buf, *dst_buf;
-       struct emmaprp_dev *pcdev = ctx->dev;
-       unsigned int s_width, s_height;
-       unsigned int d_width, d_height;
-       unsigned int d_size;
-       dma_addr_t p_in, p_out;
-       u32 tmp;
-
-       src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-       dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-
-       s_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-       s_width = s_q_data->width;
-       s_height = s_q_data->height;
-
-       d_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-       d_width = d_q_data->width;
-       d_height = d_q_data->height;
-       d_size = d_width * d_height;
-
-       p_in = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
-       p_out = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
-       if (!p_in || !p_out) {
-               v4l2_err(&pcdev->v4l2_dev,
-                        "Acquiring kernel pointers to buffers failed\n");
-               return;
-       }
-
-       /* Input frame parameters */
-       writel(p_in, pcdev->base_emma + PRP_SOURCE_Y_PTR);
-       writel(PRP_SIZE_WIDTH(s_width) | PRP_SIZE_HEIGHT(s_height),
-              pcdev->base_emma + PRP_SRC_FRAME_SIZE);
-
-       /* Output frame parameters */
-       writel(p_out, pcdev->base_emma + PRP_DEST_Y_PTR);
-       writel(p_out + d_size, pcdev->base_emma + PRP_DEST_CB_PTR);
-       writel(p_out + d_size + (d_size >> 2),
-              pcdev->base_emma + PRP_DEST_CR_PTR);
-       writel(PRP_SIZE_WIDTH(d_width) | PRP_SIZE_HEIGHT(d_height),
-              pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE);
-
-       /* IRQ configuration */
-       tmp = readl(pcdev->base_emma + PRP_INTR_CNTL);
-       writel(tmp | PRP_INTR_RDERR |
-               PRP_INTR_CH2WERR |
-               PRP_INTR_CH2FC,
-               pcdev->base_emma + PRP_INTR_CNTL);
-
-       emmaprp_dump_regs(pcdev);
-
-       /* Enable transfer */
-       tmp = readl(pcdev->base_emma + PRP_CNTL);
-       writel(tmp | PRP_CNTL_CH2_OUT_YUV420 |
-               PRP_CNTL_DATA_IN_YUV422 |
-               PRP_CNTL_CH2EN,
-               pcdev->base_emma + PRP_CNTL);
-}
-
-static irqreturn_t emmaprp_irq(int irq_emma, void *data)
-{
-       struct emmaprp_dev *pcdev = data;
-       struct emmaprp_ctx *curr_ctx;
-       struct vb2_v4l2_buffer *src_vb, *dst_vb;
-       unsigned long flags;
-       u32 irqst;
-
-       /* Check irq flags and clear irq */
-       irqst = readl(pcdev->base_emma + PRP_INTRSTATUS);
-       writel(irqst, pcdev->base_emma + PRP_INTRSTATUS);
-       dprintk(pcdev, "irqst = 0x%08x\n", irqst);
-
-       curr_ctx = v4l2_m2m_get_curr_priv(pcdev->m2m_dev);
-       if (curr_ctx == NULL) {
-               pr_err("Instance released before the end of transaction\n");
-               return IRQ_HANDLED;
-       }
-
-       if (!curr_ctx->aborting) {
-               if ((irqst & PRP_INTR_ST_RDERR) ||
-               (irqst & PRP_INTR_ST_CH2WERR)) {
-                       pr_err("PrP bus error occurred, this transfer is probably corrupted\n");
-                       writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL);
-               } else if (irqst & PRP_INTR_ST_CH2B1CI) { /* buffer ready */
-                       src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
-                       dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
-
-                       dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
-                       dst_vb->flags &=
-                               ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-                       dst_vb->flags |=
-                               src_vb->flags
-                               & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-                       dst_vb->timecode = src_vb->timecode;
-
-                       spin_lock_irqsave(&pcdev->irqlock, flags);
-                       v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
-                       v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
-                       spin_unlock_irqrestore(&pcdev->irqlock, flags);
-               }
-       }
-
-       v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->fh.m2m_ctx);
-       return IRQ_HANDLED;
-}
-
-/*
- * video ioctls
- */
-static int vidioc_querycap(struct file *file, void *priv,
-                          struct v4l2_capability *cap)
-{
-       strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
-       strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
-       return 0;
-}
-
-static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
-{
-       int i, num;
-       struct emmaprp_fmt *fmt;
-
-       num = 0;
-
-       for (i = 0; i < NUM_FORMATS; ++i) {
-               if (formats[i].types & type) {
-                       /* index-th format of type type found ? */
-                       if (num == f->index)
-                               break;
-                       /* Correct type but haven't reached our index yet,
-                        * just increment per-type index */
-                       ++num;
-               }
-       }
-
-       if (i < NUM_FORMATS) {
-               /* Format found */
-               fmt = &formats[i];
-               f->pixelformat = fmt->fourcc;
-               return 0;
-       }
-
-       /* Format not found */
-       return -EINVAL;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
-                                  struct v4l2_fmtdesc *f)
-{
-       return enum_fmt(f, MEM2MEM_CAPTURE);
-}
-
-static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
-                                  struct v4l2_fmtdesc *f)
-{
-       return enum_fmt(f, MEM2MEM_OUTPUT);
-}
-
-static int vidioc_g_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f)
-{
-       struct vb2_queue *vq;
-       struct emmaprp_q_data *q_data;
-
-       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-       if (!vq)
-               return -EINVAL;
-
-       q_data = get_q_data(ctx, f->type);
-
-       f->fmt.pix.width        = q_data->width;
-       f->fmt.pix.height       = q_data->height;
-       f->fmt.pix.field        = V4L2_FIELD_NONE;
-       f->fmt.pix.pixelformat  = q_data->fmt->fourcc;
-       if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
-               f->fmt.pix.bytesperline = q_data->width * 3 / 2;
-       else /* YUYV */
-               f->fmt.pix.bytesperline = q_data->width * 2;
-       f->fmt.pix.sizeimage    = q_data->sizeimage;
-
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       return vidioc_g_fmt(priv, f);
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       return vidioc_g_fmt(priv, f);
-}
-
-static int vidioc_try_fmt(struct v4l2_format *f)
-{
-       enum v4l2_field field;
-
-
-       if (!find_format(f))
-               return -EINVAL;
-
-       field = f->fmt.pix.field;
-       if (field == V4L2_FIELD_ANY)
-               field = V4L2_FIELD_NONE;
-       else if (V4L2_FIELD_NONE != field)
-               return -EINVAL;
-
-       /* V4L2 specification suggests the driver corrects the format struct
-        * if any of the dimensions is unsupported */
-       f->fmt.pix.field = field;
-
-       if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {
-               v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W,
-                                     W_ALIGN_YUV420, &f->fmt.pix.height,
-                                     MIN_H, MAX_H, H_ALIGN, S_ALIGN);
-               f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2;
-       } else {
-               v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W,
-                                     W_ALIGN_OTHERS, &f->fmt.pix.height,
-                                     MIN_H, MAX_H, H_ALIGN, S_ALIGN);
-               f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
-       }
-       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-
-       return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                                 struct v4l2_format *f)
-{
-       struct emmaprp_fmt *fmt;
-       struct emmaprp_ctx *ctx = priv;
-
-       fmt = find_format(f);
-       if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) {
-               v4l2_err(&ctx->dev->v4l2_dev,
-                        "Fourcc format (0x%08x) invalid.\n",
-                        f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       return vidioc_try_fmt(f);
-}
-
-static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
-                                 struct v4l2_format *f)
-{
-       struct emmaprp_fmt *fmt;
-       struct emmaprp_ctx *ctx = priv;
-
-       fmt = find_format(f);
-       if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) {
-               v4l2_err(&ctx->dev->v4l2_dev,
-                        "Fourcc format (0x%08x) invalid.\n",
-                        f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       return vidioc_try_fmt(f);
-}
-
-static int vidioc_s_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f)
-{
-       struct emmaprp_q_data *q_data;
-       struct vb2_queue *vq;
-       int ret;
-
-       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-       if (!vq)
-               return -EINVAL;
-
-       q_data = get_q_data(ctx, f->type);
-       if (!q_data)
-               return -EINVAL;
-
-       if (vb2_is_busy(vq)) {
-               v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
-               return -EBUSY;
-       }
-
-       ret = vidioc_try_fmt(f);
-       if (ret)
-               return ret;
-
-       q_data->fmt             = find_format(f);
-       q_data->width           = f->fmt.pix.width;
-       q_data->height          = f->fmt.pix.height;
-       if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420)
-               q_data->sizeimage = q_data->width * q_data->height * 3 / 2;
-       else /* YUYV */
-               q_data->sizeimage = q_data->width * q_data->height * 2;
-
-       dprintk(ctx->dev,
-               "Setting format for type %d, wxh: %dx%d, fmt: %d\n",
-               f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
-
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       int ret;
-
-       ret = vidioc_try_fmt_vid_cap(file, priv, f);
-       if (ret)
-               return ret;
-
-       return vidioc_s_fmt(priv, f);
-}
-
-static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       int ret;
-
-       ret = vidioc_try_fmt_vid_out(file, priv, f);
-       if (ret)
-               return ret;
-
-       return vidioc_s_fmt(priv, f);
-}
-
-static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = {
-       .vidioc_querycap        = vidioc_querycap,
-
-       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
-
-       .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
-       .vidioc_g_fmt_vid_out   = vidioc_g_fmt_vid_out,
-       .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
-       .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
-
-       .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_expbuf          = v4l2_m2m_ioctl_expbuf,
-       .vidioc_streamon        = v4l2_m2m_ioctl_streamon,
-       .vidioc_streamoff       = v4l2_m2m_ioctl_streamoff,
-};
-
-
-/*
- * Queue operations
- */
-static int emmaprp_queue_setup(struct vb2_queue *vq,
-                               unsigned int *nbuffers, unsigned int *nplanes,
-                               unsigned int sizes[], struct device *alloc_devs[])
-{
-       struct emmaprp_ctx *ctx = vb2_get_drv_priv(vq);
-       struct emmaprp_q_data *q_data;
-       unsigned int size, count = *nbuffers;
-
-       q_data = get_q_data(ctx, vq->type);
-
-       if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420)
-               size = q_data->width * q_data->height * 3 / 2;
-       else
-               size = q_data->width * q_data->height * 2;
-
-       while (size * count > MEM2MEM_VID_MEM_LIMIT)
-               (count)--;
-
-       *nplanes = 1;
-       *nbuffers = count;
-       sizes[0] = size;
-
-       dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
-
-       return 0;
-}
-
-static int emmaprp_buf_prepare(struct vb2_buffer *vb)
-{
-       struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-       struct emmaprp_q_data *q_data;
-
-       dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
-
-       q_data = get_q_data(ctx, vb->vb2_queue->type);
-
-       if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
-               dprintk(ctx->dev,
-                       "%s data will not fit into plane(%lu < %lu)\n",
-                       __func__, vb2_plane_size(vb, 0),
-                       (long)q_data->sizeimage);
-               return -EINVAL;
-       }
-
-       vb2_set_plane_payload(vb, 0, q_data->sizeimage);
-
-       return 0;
-}
-
-static void emmaprp_buf_queue(struct vb2_buffer *vb)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
-}
-
-static const struct vb2_ops emmaprp_qops = {
-       .queue_setup     = emmaprp_queue_setup,
-       .buf_prepare     = emmaprp_buf_prepare,
-       .buf_queue       = emmaprp_buf_queue,
-       .wait_prepare    = vb2_ops_wait_prepare,
-       .wait_finish     = vb2_ops_wait_finish,
-};
-
-static int queue_init(void *priv, struct vb2_queue *src_vq,
-                     struct vb2_queue *dst_vq)
-{
-       struct emmaprp_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->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-       src_vq->ops = &emmaprp_qops;
-       src_vq->mem_ops = &vb2_dma_contig_memops;
-       src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       src_vq->dev = ctx->dev->v4l2_dev.dev;
-       src_vq->lock = &ctx->dev->dev_mutex;
-
-       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->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-       dst_vq->ops = &emmaprp_qops;
-       dst_vq->mem_ops = &vb2_dma_contig_memops;
-       dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       dst_vq->dev = ctx->dev->v4l2_dev.dev;
-       dst_vq->lock = &ctx->dev->dev_mutex;
-
-       return vb2_queue_init(dst_vq);
-}
-
-/*
- * File operations
- */
-static int emmaprp_open(struct file *file)
-{
-       struct emmaprp_dev *pcdev = video_drvdata(file);
-       struct emmaprp_ctx *ctx;
-
-       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
-       if (!ctx)
-               return -ENOMEM;
-
-       v4l2_fh_init(&ctx->fh, video_devdata(file));
-       file->private_data = &ctx->fh;
-       ctx->dev = pcdev;
-
-       if (mutex_lock_interruptible(&pcdev->dev_mutex)) {
-               kfree(ctx);
-               return -ERESTARTSYS;
-       }
-
-       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init);
-
-       if (IS_ERR(ctx->fh.m2m_ctx)) {
-               int ret = PTR_ERR(ctx->fh.m2m_ctx);
-
-               mutex_unlock(&pcdev->dev_mutex);
-               kfree(ctx);
-               return ret;
-       }
-
-       clk_prepare_enable(pcdev->clk_emma_ipg);
-       clk_prepare_enable(pcdev->clk_emma_ahb);
-       ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1];
-       ctx->q_data[V4L2_M2M_DST].fmt = &formats[0];
-       v4l2_fh_add(&ctx->fh);
-       mutex_unlock(&pcdev->dev_mutex);
-
-       dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->fh.m2m_ctx);
-
-       return 0;
-}
-
-static int emmaprp_release(struct file *file)
-{
-       struct emmaprp_dev *pcdev = video_drvdata(file);
-       struct emmaprp_ctx *ctx = file->private_data;
-
-       dprintk(pcdev, "Releasing instance %p\n", ctx);
-
-       mutex_lock(&pcdev->dev_mutex);
-       clk_disable_unprepare(pcdev->clk_emma_ahb);
-       clk_disable_unprepare(pcdev->clk_emma_ipg);
-       v4l2_fh_del(&ctx->fh);
-       v4l2_fh_exit(&ctx->fh);
-       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
-       mutex_unlock(&pcdev->dev_mutex);
-       kfree(ctx);
-
-       return 0;
-}
-
-static const struct v4l2_file_operations emmaprp_fops = {
-       .owner          = THIS_MODULE,
-       .open           = emmaprp_open,
-       .release        = emmaprp_release,
-       .poll           = v4l2_m2m_fop_poll,
-       .unlocked_ioctl = video_ioctl2,
-       .mmap           = v4l2_m2m_fop_mmap,
-};
-
-static const struct video_device emmaprp_videodev = {
-       .name           = MEM2MEM_NAME,
-       .fops           = &emmaprp_fops,
-       .ioctl_ops      = &emmaprp_ioctl_ops,
-       .minor          = -1,
-       .release        = video_device_release,
-       .vfl_dir        = VFL_DIR_M2M,
-       .device_caps    = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
-};
-
-static const struct v4l2_m2m_ops m2m_ops = {
-       .device_run     = emmaprp_device_run,
-       .job_abort      = emmaprp_job_abort,
-};
-
-static int emmaprp_probe(struct platform_device *pdev)
-{
-       struct emmaprp_dev *pcdev;
-       struct video_device *vfd;
-       int irq, ret;
-
-       pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
-       if (!pcdev)
-               return -ENOMEM;
-
-       spin_lock_init(&pcdev->irqlock);
-
-       pcdev->clk_emma_ipg = devm_clk_get(&pdev->dev, "ipg");
-       if (IS_ERR(pcdev->clk_emma_ipg)) {
-               return PTR_ERR(pcdev->clk_emma_ipg);
-       }
-
-       pcdev->clk_emma_ahb = devm_clk_get(&pdev->dev, "ahb");
-       if (IS_ERR(pcdev->clk_emma_ahb))
-               return PTR_ERR(pcdev->clk_emma_ahb);
-
-       pcdev->base_emma = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(pcdev->base_emma))
-               return PTR_ERR(pcdev->base_emma);
-
-       ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
-       if (ret)
-               return ret;
-
-       mutex_init(&pcdev->dev_mutex);
-
-       vfd = video_device_alloc();
-       if (!vfd) {
-               v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n");
-               ret = -ENOMEM;
-               goto unreg_dev;
-       }
-
-       *vfd = emmaprp_videodev;
-       vfd->lock = &pcdev->dev_mutex;
-       vfd->v4l2_dev = &pcdev->v4l2_dev;
-
-       video_set_drvdata(vfd, pcdev);
-       pcdev->vfd = vfd;
-       v4l2_info(&pcdev->v4l2_dev, EMMAPRP_MODULE_NAME
-                 " Device registered as /dev/video%d\n", vfd->num);
-
-       platform_set_drvdata(pdev, pcdev);
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               ret = irq;
-               goto rel_vdev;
-       }
-
-       ret = devm_request_irq(&pdev->dev, irq, emmaprp_irq, 0,
-                              dev_name(&pdev->dev), pcdev);
-       if (ret)
-               goto rel_vdev;
-
-       pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops);
-       if (IS_ERR(pcdev->m2m_dev)) {
-               v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n");
-               ret = PTR_ERR(pcdev->m2m_dev);
-               goto rel_vdev;
-       }
-
-       ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
-       if (ret) {
-               v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n");
-               goto rel_m2m;
-       }
-
-       return 0;
-
-
-rel_m2m:
-       v4l2_m2m_release(pcdev->m2m_dev);
-rel_vdev:
-       video_device_release(vfd);
-unreg_dev:
-       v4l2_device_unregister(&pcdev->v4l2_dev);
-
-       mutex_destroy(&pcdev->dev_mutex);
-
-       return ret;
-}
-
-static int emmaprp_remove(struct platform_device *pdev)
-{
-       struct emmaprp_dev *pcdev = platform_get_drvdata(pdev);
-
-       v4l2_info(&pcdev->v4l2_dev, "Removing " EMMAPRP_MODULE_NAME);
-
-       video_unregister_device(pcdev->vfd);
-       v4l2_m2m_release(pcdev->m2m_dev);
-       v4l2_device_unregister(&pcdev->v4l2_dev);
-       mutex_destroy(&pcdev->dev_mutex);
-
-       return 0;
-}
-
-static struct platform_driver emmaprp_pdrv = {
-       .probe          = emmaprp_probe,
-       .remove         = emmaprp_remove,
-       .driver         = {
-               .name   = MEM2MEM_NAME,
-       },
-};
-module_platform_driver(emmaprp_pdrv);
diff --git a/drivers/media/platform/nxp/Kconfig b/drivers/media/platform/nxp/Kconfig
new file mode 100644 (file)
index 0000000..df52d32
--- /dev/null
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+# V4L drivers
+
+menuconfig VIDEO_IMX
+       bool "V4L2 capture drivers for NXP i.MX devices"
+       depends on V4L_PLATFORM_DRIVERS
+       depends on ARCH_MXC || COMPILE_TEST
+       depends on VIDEO_DEV && VIDEO_V4L2
+       help
+         Say yes here to enable support for capture drivers on i.MX SoCs.
+         Support for the single SoC features are selectable in the sub-menu
+         options.
+
+if VIDEO_IMX
+
+config VIDEO_IMX_MIPI_CSIS
+       tristate "MIPI CSI-2 CSIS receiver found on i.MX7 and i.MX8 models"
+       select MEDIA_CONTROLLER
+       select V4L2_FWNODE
+       select VIDEO_V4L2_SUBDEV_API
+       default n
+       help
+         Video4Linux2 sub-device driver for the MIPI CSI-2 CSIS receiver
+         v3.3/v3.6.3 found on some i.MX7 and i.MX8 SoCs.
+
+endif # VIDEO_IMX
+
+config VIDEO_VIU
+       tristate "Freescale/NXP VIU Video Driver"
+       depends on V4L_PLATFORM_DRIVERS
+       depends on VIDEO_V4L2 && (PPC_MPC512x || COMPILE_TEST) && I2C
+       select VIDEOBUF_DMA_CONTIG
+       default y
+       help
+         Support for Freescale VIU video driver. This device captures
+         video data, or overlays video on DIU frame buffer.
+
+         Say Y here if you want to enable VIU device on MPC5121e Rev2+.
+         In doubt, say N.
+
+# mem2mem drivers
+
+config VIDEO_IMX_PXP
+       tristate "i.MX Pixel Pipeline (PXP)"
+       depends on V4L_MEM2MEM_DRIVERS
+       depends on VIDEO_DEV && VIDEO_V4L2 && (ARCH_MXC || COMPILE_TEST)
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       help
+         The i.MX Pixel Pipeline is a memory-to-memory engine for scaling,
+         color space conversion, and rotation.
+
+config VIDEO_MX2_EMMAPRP
+       tristate "Freescale/NXP MX2 eMMa-PrP support"
+       depends on V4L_MEM2MEM_DRIVERS
+       depends on VIDEO_DEV && VIDEO_V4L2
+       depends on SOC_IMX27 || COMPILE_TEST
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       help
+           MX2X chips have a PrP that can be used to process buffers from
+           memory to memory. Operations include resizing and format
+           conversion.
+
+source "drivers/media/platform/nxp/imx-jpeg/Kconfig"
diff --git a/drivers/media/platform/nxp/Makefile b/drivers/media/platform/nxp/Makefile
new file mode 100644 (file)
index 0000000..efc38c6
--- /dev/null
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += imx-jpeg/
+
+obj-$(CONFIG_VIDEO_IMX_MIPI_CSIS) += imx-mipi-csis.o
+obj-$(CONFIG_VIDEO_IMX_PXP) += imx-pxp.o
+obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o
+obj-$(CONFIG_VIDEO_VIU) += fsl-viu.o
diff --git a/drivers/media/platform/nxp/fsl-viu.c b/drivers/media/platform/nxp/fsl-viu.c
new file mode 100644 (file)
index 0000000..afc96f6
--- /dev/null
@@ -0,0 +1,1599 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ *  Freescale VIU video driver
+ *
+ *  Authors: Hongjun Chen <hong-jun.chen@freescale.com>
+ *          Porting to 2.6.35 by DENX Software Engineering,
+ *          Anatolij Gustschin <agust@denx.de>
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf-dma-contig.h>
+
+#define DRV_NAME               "fsl_viu"
+#define VIU_VERSION            "0.5.1"
+
+#define BUFFER_TIMEOUT         msecs_to_jiffies(500)  /* 0.5 seconds */
+
+#define        VIU_VID_MEM_LIMIT       4       /* Video memory limit, in Mb */
+
+/* I2C address of video decoder chip is 0x4A */
+#define VIU_VIDEO_DECODER_ADDR 0x25
+
+static int info_level;
+
+#define dprintk(level, fmt, arg...)                                    \
+       do {                                                            \
+               if (level <= info_level)                                \
+                       printk(KERN_DEBUG "viu: " fmt , ## arg);        \
+       } while (0)
+
+/*
+ * Basic structures
+ */
+struct viu_fmt {
+       u32   fourcc;           /* v4l2 format id */
+       u32   pixelformat;
+       int   depth;
+};
+
+static struct viu_fmt formats[] = {
+       {
+               .fourcc         = V4L2_PIX_FMT_RGB565,
+               .pixelformat    = V4L2_PIX_FMT_RGB565,
+               .depth          = 16,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_RGB32,
+               .pixelformat    = V4L2_PIX_FMT_RGB32,
+               .depth          = 32,
+       }
+};
+
+struct viu_dev;
+struct viu_buf;
+
+/* buffer for one video frame */
+struct viu_buf {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+       struct viu_fmt *fmt;
+};
+
+struct viu_dmaqueue {
+       struct viu_dev          *dev;
+       struct list_head        active;
+       struct list_head        queued;
+       struct timer_list       timeout;
+};
+
+struct viu_status {
+       u32 field_irq;
+       u32 vsync_irq;
+       u32 hsync_irq;
+       u32 vstart_irq;
+       u32 dma_end_irq;
+       u32 error_irq;
+};
+
+struct viu_reg {
+       u32 status_cfg;
+       u32 luminance;
+       u32 chroma_r;
+       u32 chroma_g;
+       u32 chroma_b;
+       u32 field_base_addr;
+       u32 dma_inc;
+       u32 picture_count;
+       u32 req_alarm;
+       u32 alpha;
+} __attribute__ ((packed));
+
+struct viu_dev {
+       struct v4l2_device      v4l2_dev;
+       struct v4l2_ctrl_handler hdl;
+       struct mutex            lock;
+       spinlock_t              slock;
+       int                     users;
+
+       struct device           *dev;
+       /* various device info */
+       struct video_device     *vdev;
+       struct viu_dmaqueue     vidq;
+       enum v4l2_field         capfield;
+       int                     field;
+       int                     first;
+       int                     dma_done;
+
+       /* Hardware register area */
+       struct viu_reg __iomem  *vr;
+
+       /* Interrupt vector */
+       int                     irq;
+       struct viu_status       irqs;
+
+       /* video overlay */
+       struct v4l2_framebuffer ovbuf;
+       struct viu_fmt          *ovfmt;
+       unsigned int            ovenable;
+       enum v4l2_field         ovfield;
+
+       /* crop */
+       struct v4l2_rect        crop_current;
+
+       /* clock pointer */
+       struct clk              *clk;
+
+       /* decoder */
+       struct v4l2_subdev      *decoder;
+
+       v4l2_std_id             std;
+};
+
+struct viu_fh {
+       /* must remain the first field of this struct */
+       struct v4l2_fh          fh;
+       struct viu_dev          *dev;
+
+       /* video capture */
+       struct videobuf_queue   vb_vidq;
+       spinlock_t              vbq_lock; /* spinlock for the videobuf queue */
+
+       /* video overlay */
+       struct v4l2_window      win;
+       struct v4l2_clip        clips[1];
+
+       /* video capture */
+       struct viu_fmt          *fmt;
+       int                     width, height, sizeimage;
+       enum v4l2_buf_type      type;
+};
+
+static struct viu_reg reg_val;
+
+/*
+ * Macro definitions of VIU registers
+ */
+
+/* STATUS_CONFIG register */
+enum status_config {
+       SOFT_RST                = 1 << 0,
+
+       ERR_MASK                = 0x0f << 4,    /* Error code mask */
+       ERR_NO                  = 0x00,         /* No error */
+       ERR_DMA_V               = 0x01 << 4,    /* DMA in vertical active */
+       ERR_DMA_VB              = 0x02 << 4,    /* DMA in vertical blanking */
+       ERR_LINE_TOO_LONG       = 0x04 << 4,    /* Line too long */
+       ERR_TOO_MANG_LINES      = 0x05 << 4,    /* Too many lines in field */
+       ERR_LINE_TOO_SHORT      = 0x06 << 4,    /* Line too short */
+       ERR_NOT_ENOUGH_LINE     = 0x07 << 4,    /* Not enough lines in field */
+       ERR_FIFO_OVERFLOW       = 0x08 << 4,    /* FIFO overflow */
+       ERR_FIFO_UNDERFLOW      = 0x09 << 4,    /* FIFO underflow */
+       ERR_1bit_ECC            = 0x0a << 4,    /* One bit ECC error */
+       ERR_MORE_ECC            = 0x0b << 4,    /* Two/more bits ECC error */
+
+       INT_FIELD_EN            = 0x01 << 8,    /* Enable field interrupt */
+       INT_VSYNC_EN            = 0x01 << 9,    /* Enable vsync interrupt */
+       INT_HSYNC_EN            = 0x01 << 10,   /* Enable hsync interrupt */
+       INT_VSTART_EN           = 0x01 << 11,   /* Enable vstart interrupt */
+       INT_DMA_END_EN          = 0x01 << 12,   /* Enable DMA end interrupt */
+       INT_ERROR_EN            = 0x01 << 13,   /* Enable error interrupt */
+       INT_ECC_EN              = 0x01 << 14,   /* Enable ECC interrupt */
+
+       INT_FIELD_STATUS        = 0x01 << 16,   /* field interrupt status */
+       INT_VSYNC_STATUS        = 0x01 << 17,   /* vsync interrupt status */
+       INT_HSYNC_STATUS        = 0x01 << 18,   /* hsync interrupt status */
+       INT_VSTART_STATUS       = 0x01 << 19,   /* vstart interrupt status */
+       INT_DMA_END_STATUS      = 0x01 << 20,   /* DMA end interrupt status */
+       INT_ERROR_STATUS        = 0x01 << 21,   /* error interrupt status */
+
+       DMA_ACT                 = 0x01 << 27,   /* Enable DMA transfer */
+       FIELD_NO                = 0x01 << 28,   /* Field number */
+       DITHER_ON               = 0x01 << 29,   /* Dithering is on */
+       ROUND_ON                = 0x01 << 30,   /* Round is on */
+       MODE_32BIT              = 1UL << 31,    /* Data in RGBa888,
+                                                * 0 in RGB565
+                                                */
+};
+
+#define norm_maxw()    720
+#define norm_maxh()    576
+
+#define INT_ALL_STATUS (INT_FIELD_STATUS | INT_VSYNC_STATUS | \
+                        INT_HSYNC_STATUS | INT_VSTART_STATUS | \
+                        INT_DMA_END_STATUS | INT_ERROR_STATUS)
+
+#define NUM_FORMATS    ARRAY_SIZE(formats)
+
+static irqreturn_t viu_intr(int irq, void *dev_id);
+
+static struct viu_fmt *format_by_fourcc(int fourcc)
+{
+       int i;
+
+       for (i = 0; i < NUM_FORMATS; i++) {
+               if (formats[i].pixelformat == fourcc)
+                       return formats + i;
+       }
+
+       dprintk(0, "unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
+       return NULL;
+}
+
+static void viu_start_dma(struct viu_dev *dev)
+{
+       struct viu_reg __iomem *vr = dev->vr;
+
+       dev->field = 0;
+
+       /* Enable DMA operation */
+       iowrite32be(SOFT_RST, &vr->status_cfg);
+       iowrite32be(INT_FIELD_EN, &vr->status_cfg);
+}
+
+static void viu_stop_dma(struct viu_dev *dev)
+{
+       struct viu_reg __iomem *vr = dev->vr;
+       int cnt = 100;
+       u32 status_cfg;
+
+       iowrite32be(0, &vr->status_cfg);
+
+       /* Clear pending interrupts */
+       status_cfg = ioread32be(&vr->status_cfg);
+       if (status_cfg & 0x3f0000)
+               iowrite32be(status_cfg & 0x3f0000, &vr->status_cfg);
+
+       if (status_cfg & DMA_ACT) {
+               do {
+                       status_cfg = ioread32be(&vr->status_cfg);
+                       if (status_cfg & INT_DMA_END_STATUS)
+                               break;
+               } while (cnt--);
+
+               if (cnt < 0) {
+                       /* timed out, issue soft reset */
+                       iowrite32be(SOFT_RST, &vr->status_cfg);
+                       iowrite32be(0, &vr->status_cfg);
+               } else {
+                       /* clear DMA_END and other pending irqs */
+                       iowrite32be(status_cfg & 0x3f0000, &vr->status_cfg);
+               }
+       }
+
+       dev->field = 0;
+}
+
+static int restart_video_queue(struct viu_dmaqueue *vidq)
+{
+       struct viu_buf *buf, *prev;
+
+       dprintk(1, "%s vidq=%p\n", __func__, vidq);
+       if (!list_empty(&vidq->active)) {
+               buf = list_entry(vidq->active.next, struct viu_buf, vb.queue);
+               dprintk(2, "restart_queue [%p/%d]: restart dma\n",
+                       buf, buf->vb.i);
+
+               viu_stop_dma(vidq->dev);
+
+               /* cancel all outstanding capture requests */
+               list_for_each_entry_safe(buf, prev, &vidq->active, vb.queue) {
+                       list_del(&buf->vb.queue);
+                       buf->vb.state = VIDEOBUF_ERROR;
+                       wake_up(&buf->vb.done);
+               }
+               mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
+               return 0;
+       }
+
+       prev = NULL;
+       for (;;) {
+               if (list_empty(&vidq->queued))
+                       return 0;
+               buf = list_entry(vidq->queued.next, struct viu_buf, vb.queue);
+               if (prev == NULL) {
+                       list_move_tail(&buf->vb.queue, &vidq->active);
+
+                       dprintk(1, "Restarting video dma\n");
+                       viu_stop_dma(vidq->dev);
+                       viu_start_dma(vidq->dev);
+
+                       buf->vb.state = VIDEOBUF_ACTIVE;
+                       mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
+                       dprintk(2, "[%p/%d] restart_queue - first active\n",
+                               buf, buf->vb.i);
+
+               } else if (prev->vb.width  == buf->vb.width  &&
+                          prev->vb.height == buf->vb.height &&
+                          prev->fmt       == buf->fmt) {
+                       list_move_tail(&buf->vb.queue, &vidq->active);
+                       buf->vb.state = VIDEOBUF_ACTIVE;
+                       dprintk(2, "[%p/%d] restart_queue - move to active\n",
+                               buf, buf->vb.i);
+               } else {
+                       return 0;
+               }
+               prev = buf;
+       }
+}
+
+static void viu_vid_timeout(struct timer_list *t)
+{
+       struct viu_dev *dev = from_timer(dev, t, vidq.timeout);
+       struct viu_buf *buf;
+       struct viu_dmaqueue *vidq = &dev->vidq;
+
+       while (!list_empty(&vidq->active)) {
+               buf = list_entry(vidq->active.next, struct viu_buf, vb.queue);
+               list_del(&buf->vb.queue);
+               buf->vb.state = VIDEOBUF_ERROR;
+               wake_up(&buf->vb.done);
+               dprintk(1, "viu/0: [%p/%d] timeout\n", buf, buf->vb.i);
+       }
+
+       restart_video_queue(vidq);
+}
+
+/*
+ * Videobuf operations
+ */
+static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
+                       unsigned int *size)
+{
+       struct viu_fh *fh = vq->priv_data;
+
+       *size = fh->width * fh->height * fh->fmt->depth >> 3;
+       if (*count == 0)
+               *count = 32;
+
+       while (*size * *count > VIU_VID_MEM_LIMIT * 1024 * 1024)
+               (*count)--;
+
+       dprintk(1, "%s, count=%d, size=%d\n", __func__, *count, *size);
+       return 0;
+}
+
+static void free_buffer(struct videobuf_queue *vq, struct viu_buf *buf)
+{
+       struct videobuf_buffer *vb = &buf->vb;
+       void *vaddr = NULL;
+
+       videobuf_waiton(vq, &buf->vb, 0, 0);
+
+       if (vq->int_ops && vq->int_ops->vaddr)
+               vaddr = vq->int_ops->vaddr(vb);
+
+       if (vaddr)
+               videobuf_dma_contig_free(vq, &buf->vb);
+
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+inline int buffer_activate(struct viu_dev *dev, struct viu_buf *buf)
+{
+       struct viu_reg __iomem *vr = dev->vr;
+       int bpp;
+
+       /* setup the DMA base address */
+       reg_val.field_base_addr = videobuf_to_dma_contig(&buf->vb);
+
+       dprintk(1, "buffer_activate [%p/%d]: dma addr 0x%lx\n",
+               buf, buf->vb.i, (unsigned long)reg_val.field_base_addr);
+
+       /* interlace is on by default, set horizontal DMA increment */
+       reg_val.status_cfg = 0;
+       bpp = buf->fmt->depth >> 3;
+       switch (bpp) {
+       case 2:
+               reg_val.status_cfg &= ~MODE_32BIT;
+               reg_val.dma_inc = buf->vb.width * 2;
+               break;
+       case 4:
+               reg_val.status_cfg |= MODE_32BIT;
+               reg_val.dma_inc = buf->vb.width * 4;
+               break;
+       default:
+               dprintk(0, "doesn't support color depth(%d)\n",
+                       bpp * 8);
+               return -EINVAL;
+       }
+
+       /* setup picture_count register */
+       reg_val.picture_count = (buf->vb.height / 2) << 16 |
+                               buf->vb.width;
+
+       reg_val.status_cfg |= DMA_ACT | INT_DMA_END_EN | INT_FIELD_EN;
+
+       buf->vb.state = VIDEOBUF_ACTIVE;
+       dev->capfield = buf->vb.field;
+
+       /* reset dma increment if needed */
+       if (!V4L2_FIELD_HAS_BOTH(buf->vb.field))
+               reg_val.dma_inc = 0;
+
+       iowrite32be(reg_val.dma_inc, &vr->dma_inc);
+       iowrite32be(reg_val.picture_count, &vr->picture_count);
+       iowrite32be(reg_val.field_base_addr, &vr->field_base_addr);
+       mod_timer(&dev->vidq.timeout, jiffies + BUFFER_TIMEOUT);
+       return 0;
+}
+
+static int buffer_prepare(struct videobuf_queue *vq,
+                         struct videobuf_buffer *vb,
+                         enum v4l2_field field)
+{
+       struct viu_fh  *fh  = vq->priv_data;
+       struct viu_buf *buf = container_of(vb, struct viu_buf, vb);
+       int rc;
+
+       BUG_ON(fh->fmt == NULL);
+
+       if (fh->width  < 48 || fh->width  > norm_maxw() ||
+           fh->height < 32 || fh->height > norm_maxh())
+               return -EINVAL;
+       buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
+       if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size)
+               return -EINVAL;
+
+       if (buf->fmt       != fh->fmt    ||
+           buf->vb.width  != fh->width  ||
+           buf->vb.height != fh->height ||
+           buf->vb.field  != field) {
+               buf->fmt       = fh->fmt;
+               buf->vb.width  = fh->width;
+               buf->vb.height = fh->height;
+               buf->vb.field  = field;
+       }
+
+       if (buf->vb.state == VIDEOBUF_NEEDS_INIT) {
+               rc = videobuf_iolock(vq, &buf->vb, NULL);
+               if (rc != 0)
+                       goto fail;
+
+               buf->vb.width  = fh->width;
+               buf->vb.height = fh->height;
+               buf->vb.field  = field;
+               buf->fmt       = fh->fmt;
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+fail:
+       free_buffer(vq, buf);
+       return rc;
+}
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct viu_buf       *buf     = container_of(vb, struct viu_buf, vb);
+       struct viu_fh        *fh      = vq->priv_data;
+       struct viu_dev       *dev     = fh->dev;
+       struct viu_dmaqueue  *vidq    = &dev->vidq;
+       struct viu_buf       *prev;
+
+       if (!list_empty(&vidq->queued)) {
+               dprintk(1, "adding vb queue=%p\n", &buf->vb.queue);
+               dprintk(1, "vidq pointer 0x%p, queued 0x%p\n",
+                               vidq, &vidq->queued);
+               dprintk(1, "dev %p, queued: self %p, next %p, head %p\n",
+                       dev, &vidq->queued, vidq->queued.next,
+                       vidq->queued.prev);
+               list_add_tail(&buf->vb.queue, &vidq->queued);
+               buf->vb.state = VIDEOBUF_QUEUED;
+               dprintk(2, "[%p/%d] buffer_queue - append to queued\n",
+                       buf, buf->vb.i);
+       } else if (list_empty(&vidq->active)) {
+               dprintk(1, "adding vb active=%p\n", &buf->vb.queue);
+               list_add_tail(&buf->vb.queue, &vidq->active);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
+               dprintk(2, "[%p/%d] buffer_queue - first active\n",
+                       buf, buf->vb.i);
+
+               buffer_activate(dev, buf);
+       } else {
+               dprintk(1, "adding vb queue2=%p\n", &buf->vb.queue);
+               prev = list_entry(vidq->active.prev, struct viu_buf, vb.queue);
+               if (prev->vb.width  == buf->vb.width  &&
+                   prev->vb.height == buf->vb.height &&
+                   prev->fmt       == buf->fmt) {
+                       list_add_tail(&buf->vb.queue, &vidq->active);
+                       buf->vb.state = VIDEOBUF_ACTIVE;
+                       dprintk(2, "[%p/%d] buffer_queue - append to active\n",
+                               buf, buf->vb.i);
+               } else {
+                       list_add_tail(&buf->vb.queue, &vidq->queued);
+                       buf->vb.state = VIDEOBUF_QUEUED;
+                       dprintk(2, "[%p/%d] buffer_queue - first queued\n",
+                               buf, buf->vb.i);
+               }
+       }
+}
+
+static void buffer_release(struct videobuf_queue *vq,
+                               struct videobuf_buffer *vb)
+{
+       struct viu_buf *buf  = container_of(vb, struct viu_buf, vb);
+       struct viu_fh  *fh   = vq->priv_data;
+       struct viu_dev *dev  = (struct viu_dev *)fh->dev;
+
+       viu_stop_dma(dev);
+       free_buffer(vq, buf);
+}
+
+static const struct videobuf_queue_ops viu_video_qops = {
+       .buf_setup      = buffer_setup,
+       .buf_prepare    = buffer_prepare,
+       .buf_queue      = buffer_queue,
+       .buf_release    = buffer_release,
+};
+
+/*
+ * IOCTL vidioc handling
+ */
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       strscpy(cap->driver, "viu", sizeof(cap->driver));
+       strscpy(cap->card, "viu", sizeof(cap->card));
+       strscpy(cap->bus_info, "platform:viu", sizeof(cap->bus_info));
+       return 0;
+}
+
+static int vidioc_enum_fmt(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       int index = f->index;
+
+       if (f->index >= NUM_FORMATS)
+               return -EINVAL;
+
+       f->pixelformat = formats[index].fourcc;
+       return 0;
+}
+
+static int vidioc_g_fmt_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct viu_fh *fh = priv;
+
+       f->fmt.pix.width        = fh->width;
+       f->fmt.pix.height       = fh->height;
+       f->fmt.pix.field        = fh->vb_vidq.field;
+       f->fmt.pix.pixelformat  = fh->fmt->pixelformat;
+       f->fmt.pix.bytesperline =
+                       (f->fmt.pix.width * fh->fmt->depth) >> 3;
+       f->fmt.pix.sizeimage    = fh->sizeimage;
+       f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
+       return 0;
+}
+
+static int vidioc_try_fmt_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct viu_fmt *fmt;
+       unsigned int maxw, maxh;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (!fmt) {
+               dprintk(1, "Fourcc format (0x%08x) invalid.",
+                       f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       maxw  = norm_maxw();
+       maxh  = norm_maxh();
+
+       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+       if (f->fmt.pix.height < 32)
+               f->fmt.pix.height = 32;
+       if (f->fmt.pix.height > maxh)
+               f->fmt.pix.height = maxh;
+       if (f->fmt.pix.width < 48)
+               f->fmt.pix.width = 48;
+       if (f->fmt.pix.width > maxw)
+               f->fmt.pix.width = maxw;
+       f->fmt.pix.width &= ~0x03;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+       return 0;
+}
+
+static int vidioc_s_fmt_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct viu_fh *fh = priv;
+       int ret;
+
+       ret = vidioc_try_fmt_cap(file, fh, f);
+       if (ret < 0)
+               return ret;
+
+       fh->fmt           = format_by_fourcc(f->fmt.pix.pixelformat);
+       fh->width         = f->fmt.pix.width;
+       fh->height        = f->fmt.pix.height;
+       fh->sizeimage     = f->fmt.pix.sizeimage;
+       fh->vb_vidq.field = f->fmt.pix.field;
+       fh->type          = f->type;
+       return 0;
+}
+
+static int vidioc_g_fmt_overlay(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct viu_fh *fh = priv;
+
+       f->fmt.win = fh->win;
+       return 0;
+}
+
+static int verify_preview(struct viu_dev *dev, struct v4l2_window *win)
+{
+       enum v4l2_field field;
+       int maxw, maxh;
+
+       if (dev->ovbuf.base == NULL)
+               return -EINVAL;
+       if (dev->ovfmt == NULL)
+               return -EINVAL;
+       if (win->w.width < 48 || win->w.height < 32)
+               return -EINVAL;
+
+       field = win->field;
+       maxw  = dev->crop_current.width;
+       maxh  = dev->crop_current.height;
+
+       if (field == V4L2_FIELD_ANY) {
+               field = (win->w.height > maxh/2)
+                       ? V4L2_FIELD_INTERLACED
+                       : V4L2_FIELD_TOP;
+       }
+       switch (field) {
+       case V4L2_FIELD_TOP:
+       case V4L2_FIELD_BOTTOM:
+               maxh = maxh / 2;
+               break;
+       case V4L2_FIELD_INTERLACED:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       win->field = field;
+       if (win->w.width > maxw)
+               win->w.width = maxw;
+       if (win->w.height > maxh)
+               win->w.height = maxh;
+       return 0;
+}
+
+inline void viu_activate_overlay(struct viu_reg __iomem *vr)
+{
+       iowrite32be(reg_val.field_base_addr, &vr->field_base_addr);
+       iowrite32be(reg_val.dma_inc, &vr->dma_inc);
+       iowrite32be(reg_val.picture_count, &vr->picture_count);
+}
+
+static int viu_setup_preview(struct viu_dev *dev, struct viu_fh *fh)
+{
+       int bpp;
+
+       dprintk(1, "%s %dx%d\n", __func__,
+               fh->win.w.width, fh->win.w.height);
+
+       reg_val.status_cfg = 0;
+
+       /* setup window */
+       reg_val.picture_count = (fh->win.w.height / 2) << 16 |
+                               fh->win.w.width;
+
+       /* setup color depth and dma increment */
+       bpp = dev->ovfmt->depth / 8;
+       switch (bpp) {
+       case 2:
+               reg_val.status_cfg &= ~MODE_32BIT;
+               reg_val.dma_inc = fh->win.w.width * 2;
+               break;
+       case 4:
+               reg_val.status_cfg |= MODE_32BIT;
+               reg_val.dma_inc = fh->win.w.width * 4;
+               break;
+       default:
+               dprintk(0, "device doesn't support color depth(%d)\n",
+                       bpp * 8);
+               return -EINVAL;
+       }
+
+       dev->ovfield = fh->win.field;
+       if (!V4L2_FIELD_HAS_BOTH(dev->ovfield))
+               reg_val.dma_inc = 0;
+
+       reg_val.status_cfg |= DMA_ACT | INT_DMA_END_EN | INT_FIELD_EN;
+
+       /* setup the base address of the overlay buffer */
+       reg_val.field_base_addr = (u32)(long)dev->ovbuf.base;
+
+       return 0;
+}
+
+static int vidioc_s_fmt_overlay(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct viu_fh  *fh  = priv;
+       struct viu_dev *dev = (struct viu_dev *)fh->dev;
+       unsigned long  flags;
+       int err;
+
+       err = verify_preview(dev, &f->fmt.win);
+       if (err)
+               return err;
+
+       fh->win = f->fmt.win;
+
+       spin_lock_irqsave(&dev->slock, flags);
+       viu_setup_preview(dev, fh);
+       spin_unlock_irqrestore(&dev->slock, flags);
+       return 0;
+}
+
+static int vidioc_try_fmt_overlay(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       return 0;
+}
+
+static int vidioc_overlay(struct file *file, void *priv, unsigned int on)
+{
+       struct viu_fh  *fh  = priv;
+       struct viu_dev *dev = (struct viu_dev *)fh->dev;
+       unsigned long  flags;
+
+       if (on) {
+               spin_lock_irqsave(&dev->slock, flags);
+               viu_activate_overlay(dev->vr);
+               dev->ovenable = 1;
+
+               /* start dma */
+               viu_start_dma(dev);
+               spin_unlock_irqrestore(&dev->slock, flags);
+       } else {
+               viu_stop_dma(dev);
+               dev->ovenable = 0;
+       }
+
+       return 0;
+}
+
+static int vidioc_g_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *arg)
+{
+       struct viu_fh  *fh = priv;
+       struct viu_dev *dev = fh->dev;
+       struct v4l2_framebuffer *fb = arg;
+
+       *fb = dev->ovbuf;
+       fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+       return 0;
+}
+
+static int vidioc_s_fbuf(struct file *file, void *priv, const struct v4l2_framebuffer *arg)
+{
+       struct viu_fh  *fh = priv;
+       struct viu_dev *dev = fh->dev;
+       const struct v4l2_framebuffer *fb = arg;
+       struct viu_fmt *fmt;
+
+       if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
+               return -EPERM;
+
+       /* check args */
+       fmt = format_by_fourcc(fb->fmt.pixelformat);
+       if (fmt == NULL)
+               return -EINVAL;
+
+       /* ok, accept it */
+       dev->ovbuf = *fb;
+       dev->ovfmt = fmt;
+       if (dev->ovbuf.fmt.bytesperline == 0) {
+               dev->ovbuf.fmt.bytesperline =
+                       dev->ovbuf.fmt.width * fmt->depth / 8;
+       }
+       return 0;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                               struct v4l2_requestbuffers *p)
+{
+       struct viu_fh *fh = priv;
+
+       return videobuf_reqbufs(&fh->vb_vidq, p);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                                       struct v4l2_buffer *p)
+{
+       struct viu_fh *fh = priv;
+
+       return videobuf_querybuf(&fh->vb_vidq, p);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct viu_fh *fh = priv;
+
+       return videobuf_qbuf(&fh->vb_vidq, p);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct viu_fh *fh = priv;
+
+       return videobuf_dqbuf(&fh->vb_vidq, p,
+                               file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct viu_fh *fh = priv;
+       struct viu_dev *dev = fh->dev;
+
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (fh->type != i)
+               return -EINVAL;
+
+       if (dev->ovenable)
+               dev->ovenable = 0;
+
+       viu_start_dma(fh->dev);
+
+       return videobuf_streamon(&fh->vb_vidq);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct viu_fh  *fh = priv;
+
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (fh->type != i)
+               return -EINVAL;
+
+       viu_stop_dma(fh->dev);
+
+       return videobuf_streamoff(&fh->vb_vidq);
+}
+
+#define decoder_call(viu, o, f, args...) \
+       v4l2_subdev_call(viu->decoder, o, f, ##args)
+
+static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+       struct viu_fh *fh = priv;
+
+       decoder_call(fh->dev, video, querystd, std_id);
+       return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
+{
+       struct viu_fh *fh = priv;
+
+       fh->dev->std = id;
+       decoder_call(fh->dev, video, s_std, id);
+       return 0;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std_id)
+{
+       struct viu_fh *fh = priv;
+
+       *std_id = fh->dev->std;
+       return 0;
+}
+
+/* only one input in this driver */
+static int vidioc_enum_input(struct file *file, void *priv,
+                                       struct v4l2_input *inp)
+{
+       struct viu_fh *fh = priv;
+
+       if (inp->index != 0)
+               return -EINVAL;
+
+       inp->type = V4L2_INPUT_TYPE_CAMERA;
+       inp->std = fh->dev->vdev->tvnorms;
+       strscpy(inp->name, "Camera", sizeof(inp->name));
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct viu_fh *fh = priv;
+
+       if (i)
+               return -EINVAL;
+
+       decoder_call(fh->dev, video, s_routing, i, 0, 0);
+       return 0;
+}
+
+inline void viu_activate_next_buf(struct viu_dev *dev,
+                               struct viu_dmaqueue *viuq)
+{
+       struct viu_dmaqueue *vidq = viuq;
+       struct viu_buf *buf;
+
+       /* launch another DMA operation for an active/queued buffer */
+       if (!list_empty(&vidq->active)) {
+               buf = list_entry(vidq->active.next, struct viu_buf,
+                                       vb.queue);
+               dprintk(1, "start another queued buffer: 0x%p\n", buf);
+               buffer_activate(dev, buf);
+       } else if (!list_empty(&vidq->queued)) {
+               buf = list_entry(vidq->queued.next, struct viu_buf,
+                                       vb.queue);
+               list_del(&buf->vb.queue);
+
+               dprintk(1, "start another queued buffer: 0x%p\n", buf);
+               list_add_tail(&buf->vb.queue, &vidq->active);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               buffer_activate(dev, buf);
+       }
+}
+
+inline void viu_default_settings(struct viu_reg __iomem *vr)
+{
+       iowrite32be(0x9512A254, &vr->luminance);
+       iowrite32be(0x03310000, &vr->chroma_r);
+       iowrite32be(0x06600F38, &vr->chroma_g);
+       iowrite32be(0x00000409, &vr->chroma_b);
+       iowrite32be(0x000000ff, &vr->alpha);
+       iowrite32be(0x00000090, &vr->req_alarm);
+       dprintk(1, "status reg: 0x%08x, field base: 0x%08x\n",
+               ioread32be(&vr->status_cfg), ioread32be(&vr->field_base_addr));
+}
+
+static void viu_overlay_intr(struct viu_dev *dev, u32 status)
+{
+       struct viu_reg __iomem *vr = dev->vr;
+
+       if (status & INT_DMA_END_STATUS)
+               dev->dma_done = 1;
+
+       if (status & INT_FIELD_STATUS) {
+               if (dev->dma_done) {
+                       u32 addr = reg_val.field_base_addr;
+
+                       dev->dma_done = 0;
+                       if (status & FIELD_NO)
+                               addr += reg_val.dma_inc;
+
+                       iowrite32be(addr, &vr->field_base_addr);
+                       iowrite32be(reg_val.dma_inc, &vr->dma_inc);
+                       iowrite32be((status & 0xffc0ffff) |
+                                (status & INT_ALL_STATUS) |
+                                reg_val.status_cfg, &vr->status_cfg);
+               } else if (status & INT_VSYNC_STATUS) {
+                       iowrite32be((status & 0xffc0ffff) |
+                                (status & INT_ALL_STATUS) |
+                                reg_val.status_cfg, &vr->status_cfg);
+               }
+       }
+}
+
+static void viu_capture_intr(struct viu_dev *dev, u32 status)
+{
+       struct viu_dmaqueue *vidq = &dev->vidq;
+       struct viu_reg __iomem *vr = dev->vr;
+       struct viu_buf *buf;
+       int field_num;
+       int need_two;
+       int dma_done = 0;
+
+       field_num = status & FIELD_NO;
+       need_two = V4L2_FIELD_HAS_BOTH(dev->capfield);
+
+       if (status & INT_DMA_END_STATUS) {
+               dma_done = 1;
+               if (((field_num == 0) && (dev->field == 0)) ||
+                   (field_num && (dev->field == 1)))
+                       dev->field++;
+       }
+
+       if (status & INT_FIELD_STATUS) {
+               dprintk(1, "irq: field %d, done %d\n",
+                       !!field_num, dma_done);
+               if (unlikely(dev->first)) {
+                       if (field_num == 0) {
+                               dev->first = 0;
+                               dprintk(1, "activate first buf\n");
+                               viu_activate_next_buf(dev, vidq);
+                       } else
+                               dprintk(1, "wait field 0\n");
+                       return;
+               }
+
+               /* setup buffer address for next dma operation */
+               if (!list_empty(&vidq->active)) {
+                       u32 addr = reg_val.field_base_addr;
+
+                       if (field_num && need_two) {
+                               addr += reg_val.dma_inc;
+                               dprintk(1, "field 1, 0x%lx, dev field %d\n",
+                                       (unsigned long)addr, dev->field);
+                       }
+                       iowrite32be(addr, &vr->field_base_addr);
+                       iowrite32be(reg_val.dma_inc, &vr->dma_inc);
+                       iowrite32be((status & 0xffc0ffff) |
+                                (status & INT_ALL_STATUS) |
+                                reg_val.status_cfg, &vr->status_cfg);
+                       return;
+               }
+       }
+
+       if (dma_done && field_num && (dev->field == 2)) {
+               dev->field = 0;
+               buf = list_entry(vidq->active.next,
+                                struct viu_buf, vb.queue);
+               dprintk(1, "viu/0: [%p/%d] 0x%lx/0x%lx: dma complete\n",
+                       buf, buf->vb.i,
+                       (unsigned long)videobuf_to_dma_contig(&buf->vb),
+                       (unsigned long)ioread32be(&vr->field_base_addr));
+
+               if (waitqueue_active(&buf->vb.done)) {
+                       list_del(&buf->vb.queue);
+                       buf->vb.ts = ktime_get_ns();
+                       buf->vb.state = VIDEOBUF_DONE;
+                       buf->vb.field_count++;
+                       wake_up(&buf->vb.done);
+               }
+               /* activate next dma buffer */
+               viu_activate_next_buf(dev, vidq);
+       }
+}
+
+static irqreturn_t viu_intr(int irq, void *dev_id)
+{
+       struct viu_dev *dev  = (struct viu_dev *)dev_id;
+       struct viu_reg __iomem *vr = dev->vr;
+       u32 status;
+       u32 error;
+
+       status = ioread32be(&vr->status_cfg);
+
+       if (status & INT_ERROR_STATUS) {
+               dev->irqs.error_irq++;
+               error = status & ERR_MASK;
+               if (error)
+                       dprintk(1, "Err: error(%d), times:%d!\n",
+                               error >> 4, dev->irqs.error_irq);
+               /* Clear interrupt error bit and error flags */
+               iowrite32be((status & 0xffc0ffff) | INT_ERROR_STATUS,
+                           &vr->status_cfg);
+       }
+
+       if (status & INT_DMA_END_STATUS) {
+               dev->irqs.dma_end_irq++;
+               dev->dma_done = 1;
+               dprintk(2, "VIU DMA end interrupt times: %d\n",
+                                       dev->irqs.dma_end_irq);
+       }
+
+       if (status & INT_HSYNC_STATUS)
+               dev->irqs.hsync_irq++;
+
+       if (status & INT_FIELD_STATUS) {
+               dev->irqs.field_irq++;
+               dprintk(2, "VIU field interrupt times: %d\n",
+                                       dev->irqs.field_irq);
+       }
+
+       if (status & INT_VSTART_STATUS)
+               dev->irqs.vstart_irq++;
+
+       if (status & INT_VSYNC_STATUS) {
+               dev->irqs.vsync_irq++;
+               dprintk(2, "VIU vsync interrupt times: %d\n",
+                       dev->irqs.vsync_irq);
+       }
+
+       /* clear all pending irqs */
+       status = ioread32be(&vr->status_cfg);
+       iowrite32be((status & 0xffc0ffff) | (status & INT_ALL_STATUS),
+                   &vr->status_cfg);
+
+       if (dev->ovenable) {
+               viu_overlay_intr(dev, status);
+               return IRQ_HANDLED;
+       }
+
+       /* Capture mode */
+       viu_capture_intr(dev, status);
+       return IRQ_HANDLED;
+}
+
+/*
+ * File operations for the device
+ */
+static int viu_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct viu_dev *dev = video_get_drvdata(vdev);
+       struct viu_fh *fh;
+       struct viu_reg __iomem *vr;
+       int minor = vdev->minor;
+       u32 status_cfg;
+
+       dprintk(1, "viu: open (minor=%d)\n", minor);
+
+       dev->users++;
+       if (dev->users > 1) {
+               dev->users--;
+               return -EBUSY;
+       }
+
+       vr = dev->vr;
+
+       dprintk(1, "open minor=%d type=%s users=%d\n", minor,
+               v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
+
+       if (mutex_lock_interruptible(&dev->lock)) {
+               dev->users--;
+               return -ERESTARTSYS;
+       }
+
+       /* allocate and initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (!fh) {
+               dev->users--;
+               mutex_unlock(&dev->lock);
+               return -ENOMEM;
+       }
+
+       v4l2_fh_init(&fh->fh, vdev);
+       file->private_data = fh;
+       fh->dev = dev;
+
+       fh->type     = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_RGB32);
+       fh->width    = norm_maxw();
+       fh->height   = norm_maxh();
+       dev->crop_current.width  = fh->width;
+       dev->crop_current.height = fh->height;
+
+       dprintk(1, "Open: fh=%p, dev=%p, dev->vidq=%p\n", fh, dev, &dev->vidq);
+       dprintk(1, "Open: list_empty queued=%d\n",
+               list_empty(&dev->vidq.queued));
+       dprintk(1, "Open: list_empty active=%d\n",
+               list_empty(&dev->vidq.active));
+
+       viu_default_settings(vr);
+
+       status_cfg = ioread32be(&vr->status_cfg);
+       iowrite32be(status_cfg & ~(INT_VSYNC_EN | INT_HSYNC_EN |
+                               INT_FIELD_EN | INT_VSTART_EN |
+                               INT_DMA_END_EN | INT_ERROR_EN | INT_ECC_EN),
+                   &vr->status_cfg);
+
+       status_cfg = ioread32be(&vr->status_cfg);
+       iowrite32be(status_cfg | INT_ALL_STATUS, &vr->status_cfg);
+
+       spin_lock_init(&fh->vbq_lock);
+       videobuf_queue_dma_contig_init(&fh->vb_vidq, &viu_video_qops,
+                                      dev->dev, &fh->vbq_lock,
+                                      fh->type, V4L2_FIELD_INTERLACED,
+                                      sizeof(struct viu_buf), fh,
+                                      &fh->dev->lock);
+       v4l2_fh_add(&fh->fh);
+       mutex_unlock(&dev->lock);
+       return 0;
+}
+
+static ssize_t viu_read(struct file *file, char __user *data, size_t count,
+                       loff_t *ppos)
+{
+       struct viu_fh *fh = file->private_data;
+       struct viu_dev *dev = fh->dev;
+       int ret = 0;
+
+       dprintk(2, "%s\n", __func__);
+       if (dev->ovenable)
+               dev->ovenable = 0;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               if (mutex_lock_interruptible(&dev->lock))
+                       return -ERESTARTSYS;
+               viu_start_dma(dev);
+               ret = videobuf_read_stream(&fh->vb_vidq, data, count,
+                               ppos, 0, file->f_flags & O_NONBLOCK);
+               mutex_unlock(&dev->lock);
+               return ret;
+       }
+       return 0;
+}
+
+static __poll_t viu_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct viu_fh *fh = file->private_data;
+       struct videobuf_queue *q = &fh->vb_vidq;
+       struct viu_dev *dev = fh->dev;
+       __poll_t req_events = poll_requested_events(wait);
+       __poll_t res = v4l2_ctrl_poll(file, wait);
+
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+               return EPOLLERR;
+
+       if (!(req_events & (EPOLLIN | EPOLLRDNORM)))
+               return res;
+
+       mutex_lock(&dev->lock);
+       res |= videobuf_poll_stream(file, q, wait);
+       mutex_unlock(&dev->lock);
+       return res;
+}
+
+static int viu_release(struct file *file)
+{
+       struct viu_fh *fh = file->private_data;
+       struct viu_dev *dev = fh->dev;
+       int minor = video_devdata(file)->minor;
+
+       mutex_lock(&dev->lock);
+       viu_stop_dma(dev);
+       videobuf_stop(&fh->vb_vidq);
+       videobuf_mmap_free(&fh->vb_vidq);
+       v4l2_fh_del(&fh->fh);
+       v4l2_fh_exit(&fh->fh);
+       mutex_unlock(&dev->lock);
+
+       kfree(fh);
+
+       dev->users--;
+       dprintk(1, "close (minor=%d, users=%d)\n",
+               minor, dev->users);
+       return 0;
+}
+
+static void viu_reset(struct viu_reg __iomem *reg)
+{
+       iowrite32be(0, &reg->status_cfg);
+       iowrite32be(0x9512a254, &reg->luminance);
+       iowrite32be(0x03310000, &reg->chroma_r);
+       iowrite32be(0x06600f38, &reg->chroma_g);
+       iowrite32be(0x00000409, &reg->chroma_b);
+       iowrite32be(0, &reg->field_base_addr);
+       iowrite32be(0, &reg->dma_inc);
+       iowrite32be(0x01e002d0, &reg->picture_count);
+       iowrite32be(0x00000090, &reg->req_alarm);
+       iowrite32be(0x000000ff, &reg->alpha);
+}
+
+static int viu_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct viu_fh *fh = file->private_data;
+       struct viu_dev *dev = fh->dev;
+       int ret;
+
+       dprintk(1, "mmap called, vma=%p\n", vma);
+
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
+       ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+       mutex_unlock(&dev->lock);
+
+       dprintk(1, "vma start=0x%08lx, size=%ld, ret=%d\n",
+               (unsigned long)vma->vm_start,
+               (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
+               ret);
+
+       return ret;
+}
+
+static const struct v4l2_file_operations viu_fops = {
+       .owner          = THIS_MODULE,
+       .open           = viu_open,
+       .release        = viu_release,
+       .read           = viu_read,
+       .poll           = viu_poll,
+       .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
+       .mmap           = viu_mmap,
+};
+
+static const struct v4l2_ioctl_ops viu_ioctl_ops = {
+       .vidioc_querycap        = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt,
+       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_cap,
+       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_cap,
+       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_cap,
+       .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt,
+       .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_overlay,
+       .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_overlay,
+       .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_overlay,
+       .vidioc_overlay       = vidioc_overlay,
+       .vidioc_g_fbuf        = vidioc_g_fbuf,
+       .vidioc_s_fbuf        = vidioc_s_fbuf,
+       .vidioc_reqbufs       = vidioc_reqbufs,
+       .vidioc_querybuf      = vidioc_querybuf,
+       .vidioc_qbuf          = vidioc_qbuf,
+       .vidioc_dqbuf         = vidioc_dqbuf,
+       .vidioc_g_std         = vidioc_g_std,
+       .vidioc_s_std         = vidioc_s_std,
+       .vidioc_querystd      = vidioc_querystd,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+       .vidioc_streamon      = vidioc_streamon,
+       .vidioc_streamoff     = vidioc_streamoff,
+       .vidioc_log_status    = v4l2_ctrl_log_status,
+       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static const struct video_device viu_template = {
+       .name           = "FSL viu",
+       .fops           = &viu_fops,
+       .minor          = -1,
+       .ioctl_ops      = &viu_ioctl_ops,
+       .release        = video_device_release,
+
+       .tvnorms        = V4L2_STD_NTSC_M | V4L2_STD_PAL,
+       .device_caps    = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+                         V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_READWRITE,
+};
+
+static int viu_of_probe(struct platform_device *op)
+{
+       struct viu_dev *viu_dev;
+       struct video_device *vdev;
+       struct resource r;
+       struct viu_reg __iomem *viu_regs;
+       struct i2c_adapter *ad;
+       int ret, viu_irq;
+       struct clk *clk;
+
+       ret = of_address_to_resource(op->dev.of_node, 0, &r);
+       if (ret) {
+               dev_err(&op->dev, "Can't parse device node resource\n");
+               return -ENODEV;
+       }
+
+       viu_irq = irq_of_parse_and_map(op->dev.of_node, 0);
+       if (!viu_irq) {
+               dev_err(&op->dev, "Error while mapping the irq\n");
+               return -EINVAL;
+       }
+
+       /* request mem region */
+       if (!devm_request_mem_region(&op->dev, r.start,
+                                    sizeof(struct viu_reg), DRV_NAME)) {
+               dev_err(&op->dev, "Error while requesting mem region\n");
+               ret = -EBUSY;
+               goto err_irq;
+       }
+
+       /* remap registers */
+       viu_regs = devm_ioremap(&op->dev, r.start, sizeof(struct viu_reg));
+       if (!viu_regs) {
+               dev_err(&op->dev, "Can't map register set\n");
+               ret = -ENOMEM;
+               goto err_irq;
+       }
+
+       /* Prepare our private structure */
+       viu_dev = devm_kzalloc(&op->dev, sizeof(struct viu_dev), GFP_KERNEL);
+       if (!viu_dev) {
+               dev_err(&op->dev, "Can't allocate private structure\n");
+               ret = -ENOMEM;
+               goto err_irq;
+       }
+
+       viu_dev->vr = viu_regs;
+       viu_dev->irq = viu_irq;
+       viu_dev->dev = &op->dev;
+
+       /* init video dma queues */
+       INIT_LIST_HEAD(&viu_dev->vidq.active);
+       INIT_LIST_HEAD(&viu_dev->vidq.queued);
+
+       snprintf(viu_dev->v4l2_dev.name,
+                sizeof(viu_dev->v4l2_dev.name), "%s", "VIU");
+       ret = v4l2_device_register(viu_dev->dev, &viu_dev->v4l2_dev);
+       if (ret < 0) {
+               dev_err(&op->dev, "v4l2_device_register() failed: %d\n", ret);
+               goto err_irq;
+       }
+
+       ad = i2c_get_adapter(0);
+       if (!ad) {
+               ret = -EFAULT;
+               dev_err(&op->dev, "couldn't get i2c adapter\n");
+               goto err_v4l2;
+       }
+
+       v4l2_ctrl_handler_init(&viu_dev->hdl, 5);
+       if (viu_dev->hdl.error) {
+               ret = viu_dev->hdl.error;
+               dev_err(&op->dev, "couldn't register control\n");
+               goto err_i2c;
+       }
+       /* This control handler will inherit the control(s) from the
+          sub-device(s). */
+       viu_dev->v4l2_dev.ctrl_handler = &viu_dev->hdl;
+       viu_dev->decoder = v4l2_i2c_new_subdev(&viu_dev->v4l2_dev, ad,
+                       "saa7113", VIU_VIDEO_DECODER_ADDR, NULL);
+
+       timer_setup(&viu_dev->vidq.timeout, viu_vid_timeout, 0);
+       viu_dev->std = V4L2_STD_NTSC_M;
+       viu_dev->first = 1;
+
+       /* Allocate memory for video device */
+       vdev = video_device_alloc();
+       if (vdev == NULL) {
+               ret = -ENOMEM;
+               goto err_hdl;
+       }
+
+       *vdev = viu_template;
+
+       vdev->v4l2_dev = &viu_dev->v4l2_dev;
+
+       viu_dev->vdev = vdev;
+
+       /* initialize locks */
+       mutex_init(&viu_dev->lock);
+       viu_dev->vdev->lock = &viu_dev->lock;
+       spin_lock_init(&viu_dev->slock);
+
+       video_set_drvdata(viu_dev->vdev, viu_dev);
+
+       mutex_lock(&viu_dev->lock);
+
+       ret = video_register_device(viu_dev->vdev, VFL_TYPE_VIDEO, -1);
+       if (ret < 0) {
+               video_device_release(viu_dev->vdev);
+               goto err_unlock;
+       }
+
+       /* enable VIU clock */
+       clk = devm_clk_get(&op->dev, "ipg");
+       if (IS_ERR(clk)) {
+               dev_err(&op->dev, "failed to lookup the clock!\n");
+               ret = PTR_ERR(clk);
+               goto err_vdev;
+       }
+       ret = clk_prepare_enable(clk);
+       if (ret) {
+               dev_err(&op->dev, "failed to enable the clock!\n");
+               goto err_vdev;
+       }
+       viu_dev->clk = clk;
+
+       /* reset VIU module */
+       viu_reset(viu_dev->vr);
+
+       /* install interrupt handler */
+       if (request_irq(viu_dev->irq, viu_intr, 0, "viu", (void *)viu_dev)) {
+               dev_err(&op->dev, "Request VIU IRQ failed.\n");
+               ret = -ENODEV;
+               goto err_clk;
+       }
+
+       mutex_unlock(&viu_dev->lock);
+
+       dev_info(&op->dev, "Freescale VIU Video Capture Board\n");
+       return ret;
+
+err_clk:
+       clk_disable_unprepare(viu_dev->clk);
+err_vdev:
+       video_unregister_device(viu_dev->vdev);
+err_unlock:
+       mutex_unlock(&viu_dev->lock);
+err_hdl:
+       v4l2_ctrl_handler_free(&viu_dev->hdl);
+err_i2c:
+       i2c_put_adapter(ad);
+err_v4l2:
+       v4l2_device_unregister(&viu_dev->v4l2_dev);
+err_irq:
+       irq_dispose_mapping(viu_irq);
+       return ret;
+}
+
+static int viu_of_remove(struct platform_device *op)
+{
+       struct v4l2_device *v4l2_dev = platform_get_drvdata(op);
+       struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev);
+       struct v4l2_subdev *sdev = list_entry(v4l2_dev->subdevs.next,
+                                             struct v4l2_subdev, list);
+       struct i2c_client *client = v4l2_get_subdevdata(sdev);
+
+       free_irq(dev->irq, (void *)dev);
+       irq_dispose_mapping(dev->irq);
+
+       clk_disable_unprepare(dev->clk);
+
+       v4l2_ctrl_handler_free(&dev->hdl);
+       video_unregister_device(dev->vdev);
+       i2c_put_adapter(client->adapter);
+       v4l2_device_unregister(&dev->v4l2_dev);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int viu_suspend(struct platform_device *op, pm_message_t state)
+{
+       struct v4l2_device *v4l2_dev = platform_get_drvdata(op);
+       struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev);
+
+       clk_disable(dev->clk);
+       return 0;
+}
+
+static int viu_resume(struct platform_device *op)
+{
+       struct v4l2_device *v4l2_dev = platform_get_drvdata(op);
+       struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev);
+
+       clk_enable(dev->clk);
+       return 0;
+}
+#endif
+
+/*
+ * Initialization and module stuff
+ */
+static const struct of_device_id mpc512x_viu_of_match[] = {
+       {
+               .compatible = "fsl,mpc5121-viu",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, mpc512x_viu_of_match);
+
+static struct platform_driver viu_of_platform_driver = {
+       .probe = viu_of_probe,
+       .remove = viu_of_remove,
+#ifdef CONFIG_PM
+       .suspend = viu_suspend,
+       .resume = viu_resume,
+#endif
+       .driver = {
+               .name = DRV_NAME,
+               .of_match_table = mpc512x_viu_of_match,
+       },
+};
+
+module_platform_driver(viu_of_platform_driver);
+
+MODULE_DESCRIPTION("Freescale Video-In(VIU)");
+MODULE_AUTHOR("Hongjun Chen");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(VIU_VERSION);
diff --git a/drivers/media/platform/nxp/imx-jpeg/Kconfig b/drivers/media/platform/nxp/imx-jpeg/Kconfig
new file mode 100644 (file)
index 0000000..cbf6101
--- /dev/null
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+config VIDEO_IMX8_JPEG
+       tristate "IMX8 JPEG Encoder/Decoder"
+       depends on V4L_MEM2MEM_DRIVERS
+       depends on ARCH_MXC || COMPILE_TEST
+       depends on VIDEO_DEV && VIDEO_V4L2
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       select V4L2_JPEG_HELPER
+       help
+         This is a video4linux2 driver for the i.MX8 QXP/QM integrated
+         JPEG encoder/decoder.
diff --git a/drivers/media/platform/nxp/imx-jpeg/Makefile b/drivers/media/platform/nxp/imx-jpeg/Makefile
new file mode 100644 (file)
index 0000000..bf19c82
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+mxc-jpeg-encdec-objs := mxc-jpeg-hw.o mxc-jpeg.o
+obj-$(CONFIG_VIDEO_IMX8_JPEG) += mxc-jpeg-encdec.o
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c
new file mode 100644 (file)
index 0000000..29c604b
--- /dev/null
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * i.MX8QXP/i.MX8QM JPEG encoder/decoder v4l2 driver
+ *
+ * Copyright 2018-2019 NXP
+ */
+
+#include <linux/delay.h>
+#include <media/videobuf2-core.h>
+#include "mxc-jpeg-hw.h"
+
+#define print_wrapper_reg(dev, base_address, reg_offset)\
+               internal_print_wrapper_reg(dev, (base_address), #reg_offset,\
+                                          (reg_offset))
+#define internal_print_wrapper_reg(dev, base_address, reg_name, reg_offset) {\
+               int val;\
+               val = readl((base_address) + (reg_offset));\
+               dev_dbg(dev, "Wrapper reg %s = 0x%x\n", reg_name, val);\
+}
+
+void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc)
+{
+       dev_dbg(dev, " MXC JPEG NEXT_DESCPT_PTR 0x%x\n",
+               desc->next_descpt_ptr);
+       dev_dbg(dev, " MXC JPEG BUF_BASE0 0x%x\n", desc->buf_base0);
+       dev_dbg(dev, " MXC JPEG BUF_BASE1 0x%x\n", desc->buf_base1);
+       dev_dbg(dev, " MXC JPEG LINE_PITCH %d\n", desc->line_pitch);
+       dev_dbg(dev, " MXC JPEG STM_BUFBASE 0x%x\n", desc->stm_bufbase);
+       dev_dbg(dev, " MXC JPEG STM_BUFSIZE %d\n", desc->stm_bufsize);
+       dev_dbg(dev, " MXC JPEG IMGSIZE %x (%d x %d)\n", desc->imgsize,
+               desc->imgsize >> 16, desc->imgsize & 0xFFFF);
+       dev_dbg(dev, " MXC JPEG STM_CTRL 0x%x\n", desc->stm_ctrl);
+}
+
+void print_cast_status(struct device *dev, void __iomem *reg,
+                      unsigned int mode)
+{
+       dev_dbg(dev, "CAST IP status regs:\n");
+       print_wrapper_reg(dev, reg, CAST_STATUS0);
+       print_wrapper_reg(dev, reg, CAST_STATUS1);
+       print_wrapper_reg(dev, reg, CAST_STATUS2);
+       print_wrapper_reg(dev, reg, CAST_STATUS3);
+       print_wrapper_reg(dev, reg, CAST_STATUS4);
+       print_wrapper_reg(dev, reg, CAST_STATUS5);
+       print_wrapper_reg(dev, reg, CAST_STATUS6);
+       print_wrapper_reg(dev, reg, CAST_STATUS7);
+       print_wrapper_reg(dev, reg, CAST_STATUS8);
+       print_wrapper_reg(dev, reg, CAST_STATUS9);
+       print_wrapper_reg(dev, reg, CAST_STATUS10);
+       print_wrapper_reg(dev, reg, CAST_STATUS11);
+       print_wrapper_reg(dev, reg, CAST_STATUS12);
+       print_wrapper_reg(dev, reg, CAST_STATUS13);
+       if (mode == MXC_JPEG_DECODE)
+               return;
+       print_wrapper_reg(dev, reg, CAST_STATUS14);
+       print_wrapper_reg(dev, reg, CAST_STATUS15);
+       print_wrapper_reg(dev, reg, CAST_STATUS16);
+       print_wrapper_reg(dev, reg, CAST_STATUS17);
+       print_wrapper_reg(dev, reg, CAST_STATUS18);
+       print_wrapper_reg(dev, reg, CAST_STATUS19);
+}
+
+void print_wrapper_info(struct device *dev, void __iomem *reg)
+{
+       dev_dbg(dev, "Wrapper regs:\n");
+       print_wrapper_reg(dev, reg, GLB_CTRL);
+       print_wrapper_reg(dev, reg, COM_STATUS);
+       print_wrapper_reg(dev, reg, BUF_BASE0);
+       print_wrapper_reg(dev, reg, BUF_BASE1);
+       print_wrapper_reg(dev, reg, LINE_PITCH);
+       print_wrapper_reg(dev, reg, STM_BUFBASE);
+       print_wrapper_reg(dev, reg, STM_BUFSIZE);
+       print_wrapper_reg(dev, reg, IMGSIZE);
+       print_wrapper_reg(dev, reg, STM_CTRL);
+}
+
+void mxc_jpeg_enable_irq(void __iomem *reg, int slot)
+{
+       writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN));
+}
+
+void mxc_jpeg_sw_reset(void __iomem *reg)
+{
+       /*
+        * engine soft reset, internal state machine reset
+        * this will not reset registers, however, it seems
+        * the registers may remain inconsistent with the internal state
+        * so, on purpose, at least let GLB_CTRL bits clear after this reset
+        */
+       writel(GLB_CTRL_SFT_RST, reg + GLB_CTRL);
+}
+
+void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg)
+{
+       dev_dbg(dev, "CAST Encoder CONFIG...\n");
+       /*
+        * "Config_Mode" enabled, "Config_Mode auto clear enabled",
+        */
+       writel(0xa0, reg + CAST_MODE);
+
+       /* all markers and segments */
+       writel(0x3ff, reg + CAST_CFG_MODE);
+
+       /* quality factor */
+       writel(0x4b, reg + CAST_QUALITY);
+}
+
+void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg)
+{
+       dev_dbg(dev, "CAST Encoder GO...\n");
+       /*
+        * "GO" enabled, "GO bit auto clear" enabled
+        */
+       writel(0x140, reg + CAST_MODE);
+}
+
+void mxc_jpeg_dec_mode_go(struct device *dev, void __iomem *reg)
+{
+       dev_dbg(dev, "CAST Decoder GO...\n");
+       writel(MXC_DEC_EXIT_IDLE_MODE, reg + CAST_CTRL);
+}
+
+int mxc_jpeg_enable(void __iomem *reg)
+{
+       u32 regval;
+
+       writel(GLB_CTRL_JPG_EN, reg + GLB_CTRL);
+       regval = readl(reg);
+       return regval;
+}
+
+void mxc_jpeg_enable_slot(void __iomem *reg, int slot)
+{
+       u32 regval;
+
+       regval = readl(reg + GLB_CTRL);
+       writel(GLB_CTRL_SLOT_EN(slot) | regval, reg + GLB_CTRL);
+}
+
+void mxc_jpeg_set_l_endian(void __iomem *reg, int le)
+{
+       u32 regval;
+
+       regval = readl(reg + GLB_CTRL);
+       regval &= ~GLB_CTRL_L_ENDIAN(1); /* clear */
+       writel(GLB_CTRL_L_ENDIAN(le) | regval, reg + GLB_CTRL); /* set */
+}
+
+void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc,  u32 bufsize)
+{
+       desc->stm_bufsize = bufsize;
+}
+
+void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h)
+{
+       desc->imgsize = w << 16 | h;
+}
+
+void mxc_jpeg_set_line_pitch(struct mxc_jpeg_desc *desc, u32 line_pitch)
+{
+       desc->line_pitch = line_pitch;
+}
+
+void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot)
+{
+       writel(desc | MXC_NXT_DESCPT_EN,
+              reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR));
+}
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.h b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.h
new file mode 100644 (file)
index 0000000..ae70d3a
--- /dev/null
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * i.MX8QXP/i.MX8QM JPEG encoder/decoder v4l2 driver
+ *
+ * Copyright 2018-2019 NXP
+ */
+
+#ifndef _MXC_JPEG_HW_H
+#define _MXC_JPEG_HW_H
+
+/* JPEG Decoder/Encoder Wrapper Register Map */
+#define GLB_CTRL                       0x0
+#define COM_STATUS                     0x4
+#define BUF_BASE0                      0x14
+#define BUF_BASE1                      0x18
+#define LINE_PITCH                     0x1C
+#define STM_BUFBASE                    0x20
+#define STM_BUFSIZE                    0x24
+#define IMGSIZE                                0x28
+#define STM_CTRL                       0x2C
+
+/* CAST JPEG-Decoder/Encoder Status Register Map (read-only)*/
+#define CAST_STATUS0                   0x100
+#define CAST_STATUS1                   0x104
+#define CAST_STATUS2                   0x108
+#define CAST_STATUS3                   0x10c
+#define CAST_STATUS4                   0x110
+#define CAST_STATUS5                   0x114
+#define CAST_STATUS6                   0x118
+#define CAST_STATUS7                   0x11c
+#define CAST_STATUS8                   0x120
+#define CAST_STATUS9                   0x124
+#define CAST_STATUS10                  0x128
+#define CAST_STATUS11                  0x12c
+#define CAST_STATUS12                  0x130
+#define CAST_STATUS13                  0x134
+/* the following are for encoder only */
+#define CAST_STATUS14          0x138
+#define CAST_STATUS15          0x13c
+#define CAST_STATUS16          0x140
+#define CAST_STATUS17          0x144
+#define CAST_STATUS18          0x148
+#define CAST_STATUS19          0x14c
+
+/* CAST JPEG-Decoder Control Register Map (write-only) */
+#define CAST_CTRL                      CAST_STATUS13
+
+/* CAST JPEG-Encoder Control Register Map (write-only) */
+#define CAST_MODE                      CAST_STATUS0
+#define CAST_CFG_MODE                  CAST_STATUS1
+#define CAST_QUALITY                   CAST_STATUS2
+#define CAST_RSVD                      CAST_STATUS3
+#define CAST_REC_REGS_SEL              CAST_STATUS4
+#define CAST_LUMTH                     CAST_STATUS5
+#define CAST_CHRTH                     CAST_STATUS6
+#define CAST_NOMFRSIZE_LO              CAST_STATUS7
+#define CAST_NOMFRSIZE_HI              CAST_STATUS8
+#define CAST_OFBSIZE_LO                        CAST_STATUS9
+#define CAST_OFBSIZE_HI                        CAST_STATUS10
+
+#define MXC_MAX_SLOTS  1 /* TODO use all 4 slots*/
+/* JPEG-Decoder Wrapper Slot Registers 0..3 */
+#define SLOT_BASE                      0x10000
+#define SLOT_STATUS                    0x0
+#define SLOT_IRQ_EN                    0x4
+#define SLOT_BUF_PTR                   0x8
+#define SLOT_CUR_DESCPT_PTR            0xC
+#define SLOT_NXT_DESCPT_PTR            0x10
+#define MXC_SLOT_OFFSET(slot, offset)  ((SLOT_BASE * ((slot) + 1)) + (offset))
+
+/* GLB_CTRL fields */
+#define GLB_CTRL_JPG_EN                                        0x1
+#define GLB_CTRL_SFT_RST                               (0x1 << 1)
+#define GLB_CTRL_DEC_GO                                        (0x1 << 2)
+#define GLB_CTRL_L_ENDIAN(le)                          ((le) << 3)
+#define GLB_CTRL_SLOT_EN(slot)                         (0x1 << ((slot) + 4))
+
+/* COM_STAUS fields */
+#define COM_STATUS_DEC_ONGOING(r)              (((r) & (1 << 31)) >> 31)
+#define COM_STATUS_CUR_SLOT(r)                 (((r) & (0x3 << 29)) >> 29)
+
+/* STM_CTRL fields */
+#define STM_CTRL_PIXEL_PRECISION               (0x1 << 2)
+#define STM_CTRL_IMAGE_FORMAT(img_fmt)         ((img_fmt) << 3)
+#define STM_CTRL_IMAGE_FORMAT_MASK             (0xF << 3)
+#define STM_CTRL_BITBUF_PTR_CLR(clr)           ((clr) << 7)
+#define STM_CTRL_AUTO_START(go)                        ((go) << 8)
+#define STM_CTRL_CONFIG_MOD(mod)               ((mod) << 9)
+
+/* SLOT_STATUS fields for slots 0..3 */
+#define SLOT_STATUS_FRMDONE                    (0x1 << 3)
+#define SLOT_STATUS_ENC_CONFIG_ERR             (0x1 << 8)
+
+/* SLOT_IRQ_EN fields TBD */
+
+#define MXC_NXT_DESCPT_EN                      0x1
+#define MXC_DEC_EXIT_IDLE_MODE                 0x4
+
+/* JPEG-Decoder Wrapper - STM_CTRL Register Fields */
+#define MXC_PIXEL_PRECISION(precision) ((precision) / 8 << 2)
+enum mxc_jpeg_image_format {
+       MXC_JPEG_INVALID = -1,
+       MXC_JPEG_YUV420 = 0x0, /* 2 Plannar, Y=1st plane UV=2nd plane */
+       MXC_JPEG_YUV422 = 0x1, /* 1 Plannar, YUYV sequence */
+       MXC_JPEG_RGB    = 0x2, /* RGBRGB packed format */
+       MXC_JPEG_YUV444 = 0x3, /* 1 Plannar, YUVYUV sequence */
+       MXC_JPEG_GRAY = 0x4, /* Y8 or Y12 or Single Component */
+       MXC_JPEG_RESERVED = 0x5,
+       MXC_JPEG_ARGB   = 0x6,
+};
+
+#include "mxc-jpeg.h"
+void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc);
+void print_cast_status(struct device *dev, void __iomem *reg,
+                      unsigned int mode);
+void print_wrapper_info(struct device *dev, void __iomem *reg);
+void mxc_jpeg_sw_reset(void __iomem *reg);
+int mxc_jpeg_enable(void __iomem *reg);
+void wait_frmdone(struct device *dev, void __iomem *reg);
+void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg);
+void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg);
+void mxc_jpeg_dec_mode_go(struct device *dev, void __iomem *reg);
+int mxc_jpeg_get_slot(void __iomem *reg);
+u32 mxc_jpeg_get_offset(void __iomem *reg, int slot);
+void mxc_jpeg_enable_slot(void __iomem *reg, int slot);
+void mxc_jpeg_set_l_endian(void __iomem *reg, int le);
+void mxc_jpeg_enable_irq(void __iomem *reg, int slot);
+int mxc_jpeg_set_input(void __iomem *reg, u32 in_buf, u32 bufsize);
+int mxc_jpeg_set_output(void __iomem *reg, u16 out_pitch, u32 out_buf,
+                       u16 w, u16 h);
+void mxc_jpeg_set_config_mode(void __iomem *reg, int config_mode);
+int mxc_jpeg_set_params(struct mxc_jpeg_desc *desc,  u32 bufsize, u16
+                       out_pitch, u32 format);
+void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc,  u32 bufsize);
+void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h);
+void mxc_jpeg_set_line_pitch(struct mxc_jpeg_desc *desc, u32 line_pitch);
+void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot);
+void mxc_jpeg_set_regs_from_desc(struct mxc_jpeg_desc *desc,
+                                void __iomem *reg);
+#endif
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
new file mode 100644 (file)
index 0000000..3b892c5
--- /dev/null
@@ -0,0 +1,2254 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * V4L2 driver for the JPEG encoder/decoder from i.MX8QXP/i.MX8QM application
+ * processors.
+ *
+ * The multi-planar buffers API is used.
+ *
+ * Baseline and extended sequential jpeg decoding is supported.
+ * Progressive jpeg decoding is not supported by the IP.
+ * Supports encode and decode of various formats:
+ *     YUV444, YUV422, YUV420, RGB, ARGB, Gray
+ * YUV420 is the only multi-planar format supported.
+ * Minimum resolution is 64 x 64, maximum 8192 x 8192.
+ * To achieve 8192 x 8192, modify in defconfig: CONFIG_CMA_SIZE_MBYTES=320
+ * The alignment requirements for the resolution depend on the format,
+ * multiple of 16 resolutions should work for all formats.
+ * Special workarounds are made in the driver to support NV12 1080p.
+ * When decoding, the driver detects image resolution and pixel format
+ * from the jpeg stream, by parsing the jpeg markers.
+ *
+ * The IP has 4 slots available for context switching, but only slot 0
+ * was fully tested to work. Context switching is not used by the driver.
+ * Each driver instance (context) allocates a slot for itself, but this
+ * is postponed until device_run, to allow unlimited opens.
+ *
+ * The driver submits jobs to the IP by setting up a descriptor for the
+ * used slot, and then validating it. The encoder has an additional descriptor
+ * for the configuration phase. The driver expects FRM_DONE interrupt from
+ * IP to mark the job as finished.
+ *
+ * The decoder IP has some limitations regarding the component ID's,
+ * but the driver works around this by replacing them in the jpeg stream.
+ *
+ * A module parameter is available for debug purpose (jpeg_tracing), to enable
+ * it, enable dynamic debug for this module and:
+ * echo 1 > /sys/module/mxc_jpeg_encdec/parameters/jpeg_tracing
+ *
+ * This is inspired by the drivers/media/platform/s5p-jpeg driver
+ *
+ * Copyright 2018-2019 NXP
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/irqreturn.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_domain.h>
+#include <linux/string.h>
+
+#include <media/v4l2-jpeg.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "mxc-jpeg-hw.h"
+#include "mxc-jpeg.h"
+
+static const struct mxc_jpeg_fmt mxc_formats[] = {
+       {
+               .name           = "JPEG",
+               .fourcc         = V4L2_PIX_FMT_JPEG,
+               .subsampling    = -1,
+               .nc             = -1,
+               .colplanes      = 1,
+               .flags          = MXC_JPEG_FMT_TYPE_ENC,
+       },
+       {
+               .name           = "RGB", /*RGBRGB packed format*/
+               .fourcc         = V4L2_PIX_FMT_RGB24,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+               .nc             = 3,
+               .depth          = 24,
+               .colplanes      = 1,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+       },
+       {
+               .name           = "ARGB", /* ARGBARGB packed format */
+               .fourcc         = V4L2_PIX_FMT_ARGB32,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+               .nc             = 4,
+               .depth          = 32,
+               .colplanes      = 1,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+       },
+       {
+               .name           = "YUV420", /* 1st plane = Y, 2nd plane = UV */
+               .fourcc         = V4L2_PIX_FMT_NV12M,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+               .nc             = 3,
+               .depth          = 12, /* 6 bytes (4Y + UV) for 4 pixels */
+               .colplanes      = 2, /* 1 plane Y, 1 plane UV interleaved */
+               .h_align        = 4,
+               .v_align        = 4,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+       },
+       {
+               .name           = "YUV422", /* YUYV */
+               .fourcc         = V4L2_PIX_FMT_YUYV,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+               .nc             = 3,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 4,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+       },
+       {
+               .name           = "YUV444", /* YUVYUV */
+               .fourcc         = V4L2_PIX_FMT_YUV24,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+               .nc             = 3,
+               .depth          = 24,
+               .colplanes      = 1,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+       },
+       {
+               .name           = "Gray", /* Gray (Y8/Y12) or Single Comp */
+               .fourcc         = V4L2_PIX_FMT_GREY,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
+               .nc             = 1,
+               .depth          = 8,
+               .colplanes      = 1,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+       },
+};
+
+#define MXC_JPEG_NUM_FORMATS ARRAY_SIZE(mxc_formats)
+
+static const int mxc_decode_mode = MXC_JPEG_DECODE;
+static const int mxc_encode_mode = MXC_JPEG_ENCODE;
+
+static const struct of_device_id mxc_jpeg_match[] = {
+       {
+               .compatible = "nxp,imx8qxp-jpgdec",
+               .data       = &mxc_decode_mode,
+       },
+       {
+               .compatible = "nxp,imx8qxp-jpgenc",
+               .data       = &mxc_encode_mode,
+       },
+       { },
+};
+
+/*
+ * default configuration stream, 64x64 yuv422
+ * split by JPEG marker, so it's easier to modify & use
+ */
+static const unsigned char jpeg_soi[] = {
+       0xFF, 0xD8
+};
+
+static const unsigned char jpeg_app0[] = {
+       0xFF, 0xE0,
+       0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00,
+       0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x00
+};
+
+static const unsigned char jpeg_app14[] = {
+       0xFF, 0xEE,
+       0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65,
+       0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char jpeg_dqt[] = {
+       0xFF, 0xDB,
+       0x00, 0x84, 0x00, 0x10, 0x0B, 0x0C, 0x0E,
+       0x0C, 0x0A, 0x10, 0x0E, 0x0D, 0x0E, 0x12,
+       0x11, 0x10, 0x13, 0x18, 0x28, 0x1A, 0x18,
+       0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1D,
+       0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33,
+       0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40,
+       0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6D,
+       0x51, 0x57, 0x5F, 0x62, 0x67, 0x68, 0x67,
+       0x3E, 0x4D, 0x71, 0x79, 0x70, 0x64, 0x78,
+       0x5C, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12,
+       0x12, 0x18, 0x15, 0x18, 0x2F, 0x1A, 0x1A,
+       0x2F, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63
+};
+
+static const unsigned char jpeg_sof_maximal[] = {
+       0xFF, 0xC0,
+       0x00, 0x14, 0x08, 0x00, 0x40, 0x00, 0x40,
+       0x04, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01,
+       0x03, 0x11, 0x01, 0x04, 0x11, 0x01
+};
+
+static const unsigned char jpeg_dht[] = {
+       0xFF, 0xC4,
+       0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+       0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01,
+       0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05,
+       0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,
+       0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+       0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
+       0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91,
+       0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15,
+       0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72,
+       0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19,
+       0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
+       0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
+       0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+       0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+       0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
+       0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76,
+       0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85,
+       0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93,
+       0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,
+       0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
+       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
+       0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4,
+       0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2,
+       0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
+       0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+       0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,
+       0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA,
+       0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
+       0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
+       0x0B, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04,
+       0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
+       0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02,
+       0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06,
+       0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13,
+       0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+       0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52,
+       0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,
+       0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18,
+       0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
+       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43,
+       0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
+       0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+       0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+       0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77,
+       0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85,
+       0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93,
+       0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,
+       0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
+       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
+       0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4,
+       0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2,
+       0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
+       0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+       0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5,
+       0xF6, 0xF7, 0xF8, 0xF9, 0xFA
+};
+
+static const unsigned char jpeg_dri[] = {
+       0xFF, 0xDD,
+       0x00, 0x04, 0x00, 0x20
+};
+
+static const unsigned char jpeg_sos_maximal[] = {
+       0xFF, 0xDA,
+       0x00, 0x0C, 0x04, 0x01, 0x00, 0x02, 0x11, 0x03,
+       0x11, 0x04, 0x11, 0x00, 0x3F, 0x00
+};
+
+static const unsigned char jpeg_image_red[] = {
+       0xFC, 0x5F, 0xA2, 0xBF, 0xCA, 0x73, 0xFE, 0xFE,
+       0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00,
+       0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02,
+       0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28,
+       0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A,
+       0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0,
+       0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00,
+       0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02,
+       0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28,
+       0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A,
+       0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00
+};
+
+static const unsigned char jpeg_eoi[] = {
+       0xFF, 0xD9
+};
+
+struct mxc_jpeg_src_buf {
+       /* common v4l buffer stuff -- must be first */
+       struct vb2_v4l2_buffer  b;
+       struct list_head        list;
+
+       /* mxc-jpeg specific */
+       bool                    dht_needed;
+       bool                    jpeg_parse_error;
+};
+
+static inline struct mxc_jpeg_src_buf *vb2_to_mxc_buf(struct vb2_buffer *vb)
+{
+       return container_of(to_vb2_v4l2_buffer(vb),
+                           struct mxc_jpeg_src_buf, b);
+}
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-3)");
+
+static void _bswap16(u16 *a)
+{
+       *a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8);
+}
+
+static void print_mxc_buf(struct mxc_jpeg_dev *jpeg, struct vb2_buffer *buf,
+                         unsigned long len)
+{
+       unsigned int plane_no;
+       u32 dma_addr;
+       void *vaddr;
+       unsigned long payload;
+
+       if (debug < 3)
+               return;
+
+       for (plane_no = 0; plane_no < buf->num_planes; plane_no++) {
+               payload = vb2_get_plane_payload(buf, plane_no);
+               if (len == 0)
+                       len = payload;
+               dma_addr = vb2_dma_contig_plane_dma_addr(buf, plane_no);
+               vaddr = vb2_plane_vaddr(buf, plane_no);
+               v4l2_dbg(3, debug, &jpeg->v4l2_dev,
+                        "plane %d (vaddr=%p dma_addr=%x payload=%ld):",
+                         plane_no, vaddr, dma_addr, payload);
+               print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+                              vaddr, len, false);
+       }
+}
+
+static inline struct mxc_jpeg_ctx *mxc_jpeg_fh_to_ctx(struct v4l2_fh *fh)
+{
+       return container_of(fh, struct mxc_jpeg_ctx, fh);
+}
+
+static int enum_fmt(const struct mxc_jpeg_fmt *mxc_formats, int n,
+                   struct v4l2_fmtdesc *f, u32 type)
+{
+       int i, num = 0;
+
+       for (i = 0; i < n; ++i) {
+               if (mxc_formats[i].flags == type) {
+                       /* index-th format of searched type found ? */
+                       if (num == f->index)
+                               break;
+                       /* Correct type but haven't reached our index yet,
+                        * just increment per-type index
+                        */
+                       ++num;
+               }
+       }
+
+       /* Format not found */
+       if (i >= n)
+               return -EINVAL;
+
+       strscpy(f->description, mxc_formats[i].name, sizeof(f->description));
+       f->pixelformat = mxc_formats[i].fourcc;
+
+       return 0;
+}
+
+static const struct mxc_jpeg_fmt *mxc_jpeg_find_format(struct mxc_jpeg_ctx *ctx,
+                                                      u32 pixelformat)
+{
+       unsigned int k;
+
+       for (k = 0; k < MXC_JPEG_NUM_FORMATS; k++) {
+               const struct mxc_jpeg_fmt *fmt = &mxc_formats[k];
+
+               if (fmt->fourcc == pixelformat)
+                       return fmt;
+       }
+       return NULL;
+}
+
+static enum mxc_jpeg_image_format mxc_jpeg_fourcc_to_imgfmt(u32 fourcc)
+{
+       switch (fourcc) {
+       case V4L2_PIX_FMT_GREY:
+               return MXC_JPEG_GRAY;
+       case V4L2_PIX_FMT_YUYV:
+               return MXC_JPEG_YUV422;
+       case V4L2_PIX_FMT_NV12M:
+               return MXC_JPEG_YUV420;
+       case V4L2_PIX_FMT_YUV24:
+               return MXC_JPEG_YUV444;
+       case V4L2_PIX_FMT_RGB24:
+               return MXC_JPEG_RGB;
+       case V4L2_PIX_FMT_ARGB32:
+               return MXC_JPEG_ARGB;
+       default:
+               return MXC_JPEG_INVALID;
+       }
+}
+
+static struct mxc_jpeg_q_data *mxc_jpeg_get_q_data(struct mxc_jpeg_ctx *ctx,
+                                                  enum v4l2_buf_type type)
+{
+       if (V4L2_TYPE_IS_OUTPUT(type))
+               return &ctx->out_q;
+       return &ctx->cap_q;
+}
+
+static void mxc_jpeg_addrs(struct mxc_jpeg_desc *desc,
+                          struct vb2_buffer *raw_buf,
+                          struct vb2_buffer *jpeg_buf, int offset)
+{
+       int img_fmt = desc->stm_ctrl & STM_CTRL_IMAGE_FORMAT_MASK;
+
+       desc->buf_base0 = vb2_dma_contig_plane_dma_addr(raw_buf, 0);
+       desc->buf_base1 = 0;
+       if (img_fmt == STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV420)) {
+               WARN_ON(raw_buf->num_planes < 2);
+               desc->buf_base1 = vb2_dma_contig_plane_dma_addr(raw_buf, 1);
+       }
+       desc->stm_bufbase = vb2_dma_contig_plane_dma_addr(jpeg_buf, 0) +
+               offset;
+}
+
+static void notify_eos(struct mxc_jpeg_ctx *ctx)
+{
+       const struct v4l2_event ev = {
+               .type = V4L2_EVENT_EOS
+       };
+
+       dev_dbg(ctx->mxc_jpeg->dev, "Notify app event EOS reached");
+       v4l2_event_queue_fh(&ctx->fh, &ev);
+}
+
+static void notify_src_chg(struct mxc_jpeg_ctx *ctx)
+{
+       const struct v4l2_event ev = {
+                       .type = V4L2_EVENT_SOURCE_CHANGE,
+                       .u.src_change.changes =
+                       V4L2_EVENT_SRC_CH_RESOLUTION,
+               };
+
+       dev_dbg(ctx->mxc_jpeg->dev, "Notify app event SRC_CH_RESOLUTION");
+       v4l2_event_queue_fh(&ctx->fh, &ev);
+}
+
+static int mxc_get_free_slot(struct mxc_jpeg_slot_data slot_data[], int n)
+{
+       int free_slot = 0;
+
+       while (slot_data[free_slot].used && free_slot < n)
+               free_slot++;
+
+       return free_slot; /* >=n when there are no more free slots */
+}
+
+static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg,
+                                    unsigned int slot)
+{
+       struct mxc_jpeg_desc *desc;
+       struct mxc_jpeg_desc *cfg_desc;
+       void *cfg_stm;
+
+       if (jpeg->slot_data[slot].desc)
+               goto skip_alloc; /* already allocated, reuse it */
+
+       /* allocate descriptor for decoding/encoding phase */
+       desc = dma_alloc_coherent(jpeg->dev,
+                                 sizeof(struct mxc_jpeg_desc),
+                                 &jpeg->slot_data[slot].desc_handle,
+                                 GFP_ATOMIC);
+       if (!desc)
+               goto err;
+       jpeg->slot_data[slot].desc = desc;
+
+       /* allocate descriptor for configuration phase (encoder only) */
+       cfg_desc = dma_alloc_coherent(jpeg->dev,
+                                     sizeof(struct mxc_jpeg_desc),
+                                     &jpeg->slot_data[slot].cfg_desc_handle,
+                                     GFP_ATOMIC);
+       if (!cfg_desc)
+               goto err;
+       jpeg->slot_data[slot].cfg_desc = cfg_desc;
+
+       /* allocate configuration stream */
+       cfg_stm = dma_alloc_coherent(jpeg->dev,
+                                    MXC_JPEG_MAX_CFG_STREAM,
+                                    &jpeg->slot_data[slot].cfg_stream_handle,
+                                    GFP_ATOMIC);
+       if (!cfg_stm)
+               goto err;
+       jpeg->slot_data[slot].cfg_stream_vaddr = cfg_stm;
+
+skip_alloc:
+       jpeg->slot_data[slot].used = true;
+
+       return true;
+err:
+       dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", slot);
+
+       return false;
+}
+
+static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg,
+                                   unsigned int slot)
+{
+       if (slot >= MXC_MAX_SLOTS) {
+               dev_err(jpeg->dev, "Invalid slot %d, nothing to free.", slot);
+               return;
+       }
+
+       /* free descriptor for decoding/encoding phase */
+       dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
+                         jpeg->slot_data[slot].desc,
+                         jpeg->slot_data[slot].desc_handle);
+
+       /* free descriptor for encoder configuration phase / decoder DHT */
+       dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
+                         jpeg->slot_data[slot].cfg_desc,
+                         jpeg->slot_data[slot].cfg_desc_handle);
+
+       /* free configuration stream */
+       dma_free_coherent(jpeg->dev, MXC_JPEG_MAX_CFG_STREAM,
+                         jpeg->slot_data[slot].cfg_stream_vaddr,
+                         jpeg->slot_data[slot].cfg_stream_handle);
+
+       jpeg->slot_data[slot].used = false;
+}
+
+static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
+{
+       struct mxc_jpeg_dev *jpeg = priv;
+       struct mxc_jpeg_ctx *ctx;
+       void __iomem *reg = jpeg->base_reg;
+       struct device *dev = jpeg->dev;
+       struct vb2_v4l2_buffer *src_buf, *dst_buf;
+       struct mxc_jpeg_src_buf *jpeg_src_buf;
+       enum vb2_buffer_state buf_state;
+       u32 dec_ret, com_status;
+       unsigned long payload;
+       struct mxc_jpeg_q_data *q_data;
+       enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       unsigned int slot;
+
+       spin_lock(&jpeg->hw_lock);
+
+       com_status = readl(reg + COM_STATUS);
+       slot = COM_STATUS_CUR_SLOT(com_status);
+       dev_dbg(dev, "Irq %d on slot %d.\n", irq, slot);
+
+       ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+       if (!ctx) {
+               dev_err(dev,
+                       "Instance released before the end of transaction.\n");
+               /* soft reset only resets internal state, not registers */
+               mxc_jpeg_sw_reset(reg);
+               /* clear all interrupts */
+               writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));
+               goto job_unlock;
+       }
+
+       if (slot != ctx->slot) {
+               /* TODO investigate when adding multi-instance support */
+               dev_warn(dev, "IRQ slot %d != context slot %d.\n",
+                        slot, ctx->slot);
+               goto job_unlock;
+       }
+
+       dec_ret = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));
+       writel(dec_ret, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); /* w1c */
+
+       dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+       src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       if (!dst_buf || !src_buf) {
+               dev_err(dev, "No source or destination buffer.\n");
+               goto job_unlock;
+       }
+       jpeg_src_buf = vb2_to_mxc_buf(&src_buf->vb2_buf);
+
+       if (dec_ret & SLOT_STATUS_ENC_CONFIG_ERR) {
+               u32 ret = readl(reg + CAST_STATUS12);
+
+               dev_err(dev, "Encoder/decoder error, status=0x%08x", ret);
+               mxc_jpeg_sw_reset(reg);
+               buf_state = VB2_BUF_STATE_ERROR;
+               goto buffers_done;
+       }
+
+       if (!(dec_ret & SLOT_STATUS_FRMDONE))
+               goto job_unlock;
+
+       if (jpeg->mode == MXC_JPEG_ENCODE &&
+           ctx->enc_state == MXC_JPEG_ENC_CONF) {
+               ctx->enc_state = MXC_JPEG_ENCODING;
+               dev_dbg(dev, "Encoder config finished. Start encoding...\n");
+               mxc_jpeg_enc_mode_go(dev, reg);
+               goto job_unlock;
+       }
+       if (jpeg->mode == MXC_JPEG_DECODE && jpeg_src_buf->dht_needed) {
+               jpeg_src_buf->dht_needed = false;
+               dev_dbg(dev, "Decoder DHT cfg finished. Start decoding...\n");
+               goto job_unlock;
+       }
+       if (jpeg->mode == MXC_JPEG_ENCODE) {
+               payload = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_BUF_PTR));
+               vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);
+               dev_dbg(dev, "Encoding finished, payload size: %ld\n",
+                       payload);
+       } else {
+               q_data = mxc_jpeg_get_q_data(ctx, cap_type);
+               payload = q_data->sizeimage[0];
+               vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);
+               vb2_set_plane_payload(&dst_buf->vb2_buf, 1, 0);
+               if (q_data->fmt->colplanes == 2) {
+                       payload = q_data->sizeimage[1];
+                       vb2_set_plane_payload(&dst_buf->vb2_buf, 1, payload);
+               }
+               dev_dbg(dev, "Decoding finished, payload size: %ld + %ld\n",
+                       vb2_get_plane_payload(&dst_buf->vb2_buf, 0),
+                       vb2_get_plane_payload(&dst_buf->vb2_buf, 1));
+       }
+
+       /* short preview of the results */
+       dev_dbg(dev, "src_buf preview: ");
+       print_mxc_buf(jpeg, &src_buf->vb2_buf, 32);
+       dev_dbg(dev, "dst_buf preview: ");
+       print_mxc_buf(jpeg, &dst_buf->vb2_buf, 32);
+       buf_state = VB2_BUF_STATE_DONE;
+
+buffers_done:
+       jpeg->slot_data[slot].used = false; /* unused, but don't free */
+       v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+       v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+       v4l2_m2m_buf_done(src_buf, buf_state);
+       v4l2_m2m_buf_done(dst_buf, buf_state);
+       spin_unlock(&jpeg->hw_lock);
+       v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+       return IRQ_HANDLED;
+job_unlock:
+       spin_unlock(&jpeg->hw_lock);
+       return IRQ_HANDLED;
+}
+
+static int mxc_jpeg_fixup_sof(struct mxc_jpeg_sof *sof,
+                             u32 fourcc,
+                             u16 w, u16 h)
+{
+       int sof_length;
+
+       sof->precision = 8; /* TODO allow 8/12 bit precision*/
+       sof->height = h;
+       _bswap16(&sof->height);
+       sof->width = w;
+       _bswap16(&sof->width);
+
+       switch (fourcc) {
+       case V4L2_PIX_FMT_NV12M:
+               sof->components_no = 3;
+               sof->comp[0].v = 0x2;
+               sof->comp[0].h = 0x2;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+               sof->components_no = 3;
+               sof->comp[0].v = 0x1;
+               sof->comp[0].h = 0x2;
+               break;
+       case V4L2_PIX_FMT_YUV24:
+       case V4L2_PIX_FMT_RGB24:
+       default:
+               sof->components_no = 3;
+               break;
+       case V4L2_PIX_FMT_ARGB32:
+               sof->components_no = 4;
+               break;
+       case V4L2_PIX_FMT_GREY:
+               sof->components_no = 1;
+               break;
+       }
+       sof_length = 8 + 3 * sof->components_no;
+       sof->length = sof_length;
+       _bswap16(&sof->length);
+
+       return sof_length; /* not swaped */
+}
+
+static int mxc_jpeg_fixup_sos(struct mxc_jpeg_sos *sos,
+                             u32 fourcc)
+{
+       int sos_length;
+       u8 *sof_u8 = (u8 *)sos;
+
+       switch (fourcc) {
+       case V4L2_PIX_FMT_NV12M:
+               sos->components_no = 3;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+               sos->components_no = 3;
+               break;
+       case V4L2_PIX_FMT_YUV24:
+       case V4L2_PIX_FMT_RGB24:
+       default:
+               sos->components_no = 3;
+               break;
+       case V4L2_PIX_FMT_ARGB32:
+               sos->components_no = 4;
+               break;
+       case V4L2_PIX_FMT_GREY:
+               sos->components_no = 1;
+               break;
+       }
+       sos_length = 6 + 2 * sos->components_no;
+       sos->length = sos_length;
+       _bswap16(&sos->length);
+
+       /* SOS ignorable bytes, not so ignorable after all */
+       sof_u8[sos_length - 1] = 0x0;
+       sof_u8[sos_length - 2] = 0x3f;
+       sof_u8[sos_length - 3] = 0x0;
+
+       return sos_length; /* not swaped */
+}
+
+static unsigned int mxc_jpeg_setup_cfg_stream(void *cfg_stream_vaddr,
+                                             u32 fourcc,
+                                             u16 w, u16 h)
+{
+       unsigned int offset = 0;
+       u8 *cfg = (u8 *)cfg_stream_vaddr;
+       struct mxc_jpeg_sof *sof;
+       struct mxc_jpeg_sos *sos;
+
+       memcpy(cfg + offset, jpeg_soi, ARRAY_SIZE(jpeg_soi));
+       offset += ARRAY_SIZE(jpeg_soi);
+
+       if (fourcc == V4L2_PIX_FMT_RGB24 ||
+           fourcc == V4L2_PIX_FMT_ARGB32) {
+               memcpy(cfg + offset, jpeg_app14, sizeof(jpeg_app14));
+               offset += sizeof(jpeg_app14);
+       } else {
+               memcpy(cfg + offset, jpeg_app0, sizeof(jpeg_app0));
+               offset += sizeof(jpeg_app0);
+       }
+
+       memcpy(cfg + offset, jpeg_dqt, sizeof(jpeg_dqt));
+       offset += sizeof(jpeg_dqt);
+
+       memcpy(cfg + offset, jpeg_sof_maximal, sizeof(jpeg_sof_maximal));
+       offset += 2; /* skip marker ID */
+       sof = (struct mxc_jpeg_sof *)(cfg + offset);
+       offset += mxc_jpeg_fixup_sof(sof, fourcc, w, h);
+
+       memcpy(cfg + offset, jpeg_dht, sizeof(jpeg_dht));
+       offset += sizeof(jpeg_dht);
+
+       memcpy(cfg + offset, jpeg_dri, sizeof(jpeg_dri));
+       offset += sizeof(jpeg_dri);
+
+       memcpy(cfg + offset, jpeg_sos_maximal, sizeof(jpeg_sos_maximal));
+       offset += 2; /* skip marker ID */
+       sos = (struct mxc_jpeg_sos *)(cfg + offset);
+       offset += mxc_jpeg_fixup_sos(sos, fourcc);
+
+       memcpy(cfg + offset, jpeg_image_red, sizeof(jpeg_image_red));
+       offset += sizeof(jpeg_image_red);
+
+       memcpy(cfg + offset, jpeg_eoi, sizeof(jpeg_eoi));
+       offset += sizeof(jpeg_eoi);
+
+       return offset;
+}
+
+static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf,
+                                    struct mxc_jpeg_ctx *ctx,
+                                    struct vb2_buffer *src_buf,
+                                    struct vb2_buffer *dst_buf)
+{
+       enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       struct mxc_jpeg_q_data *q_data_cap;
+       enum mxc_jpeg_image_format img_fmt;
+       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
+       void __iomem *reg = jpeg->base_reg;
+       unsigned int slot = ctx->slot;
+       struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
+       struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
+       dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
+       dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
+       dma_addr_t cfg_stream_handle = jpeg->slot_data[slot].cfg_stream_handle;
+       unsigned int *cfg_size = &jpeg->slot_data[slot].cfg_stream_size;
+       void *cfg_stream_vaddr = jpeg->slot_data[slot].cfg_stream_vaddr;
+       struct mxc_jpeg_src_buf *jpeg_src_buf;
+
+       jpeg_src_buf = vb2_to_mxc_buf(src_buf);
+
+       /* setup the decoding descriptor */
+       desc->next_descpt_ptr = 0; /* end of chain */
+       q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
+       desc->imgsize = q_data_cap->w_adjusted << 16 | q_data_cap->h_adjusted;
+       img_fmt = mxc_jpeg_fourcc_to_imgfmt(q_data_cap->fmt->fourcc);
+       desc->stm_ctrl &= ~STM_CTRL_IMAGE_FORMAT(0xF); /* clear image format */
+       desc->stm_ctrl |= STM_CTRL_IMAGE_FORMAT(img_fmt);
+       desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
+       desc->line_pitch = q_data_cap->bytesperline[0];
+       mxc_jpeg_addrs(desc, dst_buf, src_buf, 0);
+       mxc_jpeg_set_bufsize(desc, ALIGN(vb2_plane_size(src_buf, 0), 1024));
+       print_descriptor_info(jpeg->dev, desc);
+
+       if (!jpeg_src_buf->dht_needed) {
+               /* validate the decoding descriptor */
+               mxc_jpeg_set_desc(desc_handle, reg, slot);
+               return;
+       }
+
+       /*
+        * if a default huffman table is needed, use the config descriptor to
+        * inject a DHT, by chaining it before the decoding descriptor
+        */
+       *cfg_size = mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,
+                                             V4L2_PIX_FMT_YUYV,
+                                             MXC_JPEG_MIN_WIDTH,
+                                             MXC_JPEG_MIN_HEIGHT);
+       cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;
+       cfg_desc->buf_base0 = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+       cfg_desc->buf_base1 = 0;
+       cfg_desc->imgsize = MXC_JPEG_MIN_WIDTH << 16;
+       cfg_desc->imgsize |= MXC_JPEG_MIN_HEIGHT;
+       cfg_desc->line_pitch = MXC_JPEG_MIN_WIDTH * 2;
+       cfg_desc->stm_ctrl = STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV422);
+       cfg_desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
+       cfg_desc->stm_bufbase = cfg_stream_handle;
+       cfg_desc->stm_bufsize = ALIGN(*cfg_size, 1024);
+       print_descriptor_info(jpeg->dev, cfg_desc);
+
+       /* validate the configuration descriptor */
+       mxc_jpeg_set_desc(cfg_desc_handle, reg, slot);
+}
+
+static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
+                                    struct mxc_jpeg_ctx *ctx,
+                                    struct vb2_buffer *src_buf,
+                                    struct vb2_buffer *dst_buf)
+{
+       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
+       void __iomem *reg = jpeg->base_reg;
+       unsigned int slot = ctx->slot;
+       struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
+       struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
+       dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
+       dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
+       void *cfg_stream_vaddr = jpeg->slot_data[slot].cfg_stream_vaddr;
+       struct mxc_jpeg_q_data *q_data;
+       enum mxc_jpeg_image_format img_fmt;
+       int w, h;
+
+       q_data = mxc_jpeg_get_q_data(ctx, src_buf->vb2_queue->type);
+
+       jpeg->slot_data[slot].cfg_stream_size =
+                       mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,
+                                                 q_data->fmt->fourcc,
+                                                 q_data->w_adjusted,
+                                                 q_data->h_adjusted);
+
+       /* chain the config descriptor with the encoding descriptor */
+       cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;
+
+       cfg_desc->buf_base0 = jpeg->slot_data[slot].cfg_stream_handle;
+       cfg_desc->buf_base1 = 0;
+       cfg_desc->line_pitch = 0;
+       cfg_desc->stm_bufbase = 0; /* no output expected */
+       cfg_desc->stm_bufsize = 0x0;
+       cfg_desc->imgsize = 0;
+       cfg_desc->stm_ctrl = STM_CTRL_CONFIG_MOD(1);
+       cfg_desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
+
+       desc->next_descpt_ptr = 0; /* end of chain */
+
+       /* use adjusted resolution for CAST IP job */
+       w = q_data->w_adjusted;
+       h = q_data->h_adjusted;
+       mxc_jpeg_set_res(desc, w, h);
+       mxc_jpeg_set_line_pitch(desc, w * (q_data->fmt->depth / 8));
+       mxc_jpeg_set_bufsize(desc, desc->line_pitch * h);
+       img_fmt = mxc_jpeg_fourcc_to_imgfmt(q_data->fmt->fourcc);
+       if (img_fmt == MXC_JPEG_INVALID)
+               dev_err(jpeg->dev, "No valid image format detected\n");
+       desc->stm_ctrl = STM_CTRL_CONFIG_MOD(0) |
+                        STM_CTRL_IMAGE_FORMAT(img_fmt);
+       desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
+       mxc_jpeg_addrs(desc, src_buf, dst_buf, 0);
+       dev_dbg(jpeg->dev, "cfg_desc:\n");
+       print_descriptor_info(jpeg->dev, cfg_desc);
+       dev_dbg(jpeg->dev, "enc desc:\n");
+       print_descriptor_info(jpeg->dev, desc);
+       print_wrapper_info(jpeg->dev, reg);
+       print_cast_status(jpeg->dev, reg, MXC_JPEG_ENCODE);
+
+       /* validate the configuration descriptor */
+       mxc_jpeg_set_desc(cfg_desc_handle, reg, slot);
+}
+
+static void mxc_jpeg_device_run(void *priv)
+{
+       struct mxc_jpeg_ctx *ctx = priv;
+       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
+       void __iomem *reg = jpeg->base_reg;
+       struct device *dev = jpeg->dev;
+       struct vb2_v4l2_buffer *src_buf, *dst_buf;
+       unsigned long flags;
+       struct mxc_jpeg_q_data *q_data_cap, *q_data_out;
+       struct mxc_jpeg_src_buf *jpeg_src_buf;
+
+       spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);
+       src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+       if (!src_buf || !dst_buf) {
+               dev_err(dev, "Null src or dst buf\n");
+               goto end;
+       }
+
+       q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       if (!q_data_cap)
+               goto end;
+       q_data_out = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+       if (!q_data_out)
+               goto end;
+       src_buf->sequence = q_data_out->sequence++;
+       dst_buf->sequence = q_data_cap->sequence++;
+
+       v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true);
+
+       jpeg_src_buf = vb2_to_mxc_buf(&src_buf->vb2_buf);
+       if (q_data_cap->fmt->colplanes != dst_buf->vb2_buf.num_planes) {
+               dev_err(dev, "Capture format %s has %d planes, but capture buffer has %d planes\n",
+                       q_data_cap->fmt->name, q_data_cap->fmt->colplanes,
+                       dst_buf->vb2_buf.num_planes);
+               jpeg_src_buf->jpeg_parse_error = true;
+       }
+       if (jpeg_src_buf->jpeg_parse_error) {
+               v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+               v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+               v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+               v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
+               spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
+               v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+
+               return;
+       }
+
+       mxc_jpeg_enable(reg);
+       mxc_jpeg_set_l_endian(reg, 1);
+
+       ctx->slot = mxc_get_free_slot(jpeg->slot_data, MXC_MAX_SLOTS);
+       if (ctx->slot >= MXC_MAX_SLOTS) {
+               dev_err(dev, "No more free slots\n");
+               goto end;
+       }
+       if (!mxc_jpeg_alloc_slot_data(jpeg, ctx->slot)) {
+               dev_err(dev, "Cannot allocate slot data\n");
+               goto end;
+       }
+
+       mxc_jpeg_enable_slot(reg, ctx->slot);
+       mxc_jpeg_enable_irq(reg, ctx->slot);
+
+       if (jpeg->mode == MXC_JPEG_ENCODE) {
+               dev_dbg(dev, "Encoding on slot %d\n", ctx->slot);
+               ctx->enc_state = MXC_JPEG_ENC_CONF;
+               mxc_jpeg_config_enc_desc(&dst_buf->vb2_buf, ctx,
+                                        &src_buf->vb2_buf, &dst_buf->vb2_buf);
+               mxc_jpeg_enc_mode_conf(dev, reg); /* start config phase */
+       } else {
+               dev_dbg(dev, "Decoding on slot %d\n", ctx->slot);
+               print_mxc_buf(jpeg, &src_buf->vb2_buf, 0);
+               mxc_jpeg_config_dec_desc(&dst_buf->vb2_buf, ctx,
+                                        &src_buf->vb2_buf, &dst_buf->vb2_buf);
+               mxc_jpeg_dec_mode_go(dev, reg);
+       }
+end:
+       spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
+}
+
+static void mxc_jpeg_set_last_buffer_dequeued(struct mxc_jpeg_ctx *ctx)
+{
+       struct vb2_queue *q;
+
+       ctx->stopped = 1;
+       q = v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx);
+       if (!list_empty(&q->done_list))
+               return;
+
+       q->last_buffer_dequeued = true;
+       wake_up(&q->done_wq);
+       ctx->stopped = 0;
+}
+
+static int mxc_jpeg_decoder_cmd(struct file *file, void *priv,
+                               struct v4l2_decoder_cmd *cmd)
+{
+       struct v4l2_fh *fh = file->private_data;
+       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);
+       struct device *dev = ctx->mxc_jpeg->dev;
+       int ret;
+
+       ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd);
+       if (ret < 0)
+               return ret;
+
+       if (cmd->cmd == V4L2_DEC_CMD_STOP) {
+               dev_dbg(dev, "Received V4L2_DEC_CMD_STOP");
+               if (v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx) == 0) {
+                       /* No more src bufs, notify app EOS */
+                       notify_eos(ctx);
+                       mxc_jpeg_set_last_buffer_dequeued(ctx);
+               } else {
+                       /* will send EOS later*/
+                       ctx->stopping = 1;
+               }
+       }
+
+       return 0;
+}
+
+static int mxc_jpeg_encoder_cmd(struct file *file, void *priv,
+                               struct v4l2_encoder_cmd *cmd)
+{
+       struct v4l2_fh *fh = file->private_data;
+       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);
+       struct device *dev = ctx->mxc_jpeg->dev;
+       int ret;
+
+       ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, cmd);
+       if (ret < 0)
+               return ret;
+
+       if (cmd->cmd == V4L2_ENC_CMD_STOP) {
+               dev_dbg(dev, "Received V4L2_ENC_CMD_STOP");
+               if (v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx) == 0) {
+                       /* No more src bufs, notify app EOS */
+                       notify_eos(ctx);
+                       mxc_jpeg_set_last_buffer_dequeued(ctx);
+               } else {
+                       /* will send EOS later*/
+                       ctx->stopping = 1;
+               }
+       }
+
+       return 0;
+}
+
+static int mxc_jpeg_queue_setup(struct vb2_queue *q,
+                               unsigned int *nbuffers,
+                               unsigned int *nplanes,
+                               unsigned int sizes[],
+                               struct device *alloc_ctxs[])
+{
+       struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);
+       struct mxc_jpeg_q_data *q_data = NULL;
+       int i;
+
+       q_data = mxc_jpeg_get_q_data(ctx, q->type);
+       if (!q_data)
+               return -EINVAL;
+
+       /* Handle CREATE_BUFS situation - *nplanes != 0 */
+       if (*nplanes) {
+               for (i = 0; i < *nplanes; i++) {
+                       if (sizes[i] < q_data->sizeimage[i])
+                               return -EINVAL;
+               }
+               return 0;
+       }
+
+       /* Handle REQBUFS situation */
+       *nplanes = q_data->fmt->colplanes;
+       for (i = 0; i < *nplanes; i++)
+               sizes[i] = q_data->sizeimage[i];
+
+       return 0;
+}
+
+static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);
+       struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, q->type);
+       int ret;
+
+       dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx);
+       q_data->sequence = 0;
+
+       ret = pm_runtime_resume_and_get(ctx->mxc_jpeg->dev);
+       if (ret < 0) {
+               dev_err(ctx->mxc_jpeg->dev, "Failed to power up jpeg\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static void mxc_jpeg_stop_streaming(struct vb2_queue *q)
+{
+       struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);
+       struct vb2_v4l2_buffer *vbuf;
+
+       dev_dbg(ctx->mxc_jpeg->dev, "Stop streaming ctx=%p", ctx);
+
+       /* Release all active buffers */
+       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_sync(&ctx->mxc_jpeg->pdev->dev);
+       if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+               ctx->stopping = 0;
+               ctx->stopped = 0;
+       }
+}
+
+static int mxc_jpeg_valid_comp_id(struct device *dev,
+                                 struct mxc_jpeg_sof *sof,
+                                 struct mxc_jpeg_sos *sos)
+{
+       int valid = 1;
+       int i;
+
+       /*
+        * there's a limitation in the IP that the component IDs must be
+        * between 0..4, if they are not, let's patch them
+        */
+       for (i = 0; i < sof->components_no; i++)
+               if (sof->comp[i].id > MXC_JPEG_MAX_COMPONENTS) {
+                       valid = 0;
+                       dev_err(dev, "Component %d has invalid ID: %d",
+                               i, sof->comp[i].id);
+               }
+       if (!valid)
+               /* patch all comp IDs if at least one is invalid */
+               for (i = 0; i < sof->components_no; i++) {
+                       dev_warn(dev, "Component %d ID patched to: %d",
+                                i, i + 1);
+                       sof->comp[i].id = i + 1;
+                       sos->comp[i].id = i + 1;
+               }
+
+       return valid;
+}
+
+static u32 mxc_jpeg_get_image_format(struct device *dev,
+                                    const struct v4l2_jpeg_header *header)
+{
+       int i;
+       u32 fourcc = 0;
+
+       for (i = 0; i < MXC_JPEG_NUM_FORMATS; i++)
+               if (mxc_formats[i].subsampling == header->frame.subsampling &&
+                   mxc_formats[i].nc == header->frame.num_components) {
+                       fourcc = mxc_formats[i].fourcc;
+                       break;
+               }
+       if (fourcc == 0) {
+               dev_err(dev, "Could not identify image format nc=%d, subsampling=%d\n",
+                       header->frame.num_components,
+                       header->frame.subsampling);
+               return fourcc;
+       }
+       /*
+        * If the transform flag from APP14 marker is 0, images that are
+        * encoded with 3 components have RGB colorspace, see Recommendation
+        * ITU-T T.872 chapter 6.5.3 APP14 marker segment for colour encoding
+        */
+       if (fourcc == V4L2_PIX_FMT_YUV24 || fourcc == V4L2_PIX_FMT_RGB24) {
+               if (header->app14_tf == V4L2_JPEG_APP14_TF_CMYK_RGB)
+                       fourcc = V4L2_PIX_FMT_RGB24;
+               else
+                       fourcc = V4L2_PIX_FMT_YUV24;
+       }
+
+       return fourcc;
+}
+
+static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q,
+                                 u32 precision)
+{
+       /* Bytes distance between the leftmost pixels in two adjacent lines */
+       if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {
+               /* bytesperline unused for compressed formats */
+               q->bytesperline[0] = 0;
+               q->bytesperline[1] = 0;
+       } else if (q->fmt->fourcc == V4L2_PIX_FMT_NV12M) {
+               /* When the image format is planar the bytesperline value
+                * applies to the first plane and is divided by the same factor
+                * as the width field for the other planes
+                */
+               q->bytesperline[0] = q->w * (precision / 8) *
+                                    (q->fmt->depth / 8);
+               q->bytesperline[1] = q->bytesperline[0];
+       } else {
+               /* single plane formats */
+               q->bytesperline[0] = q->w * (precision / 8) *
+                                    (q->fmt->depth / 8);
+               q->bytesperline[1] = 0;
+       }
+}
+
+static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q)
+{
+       if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {
+               /* if no sizeimage from user, assume worst jpeg compression */
+               if (!q->sizeimage[0])
+                       q->sizeimage[0] = 6 * q->w * q->h;
+               q->sizeimage[1] = 0;
+
+               if (q->sizeimage[0] > MXC_JPEG_MAX_SIZEIMAGE)
+                       q->sizeimage[0] = MXC_JPEG_MAX_SIZEIMAGE;
+
+               /* jpeg stream size must be multiple of 1K */
+               q->sizeimage[0] = ALIGN(q->sizeimage[0], 1024);
+       } else {
+               q->sizeimage[0] = q->bytesperline[0] * q->h;
+               q->sizeimage[1] = 0;
+               if (q->fmt->fourcc == V4L2_PIX_FMT_NV12M)
+                       q->sizeimage[1] = q->sizeimage[0] / 2;
+       }
+}
+
+static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx,
+                         u8 *src_addr, u32 size, bool *dht_needed)
+{
+       struct device *dev = ctx->mxc_jpeg->dev;
+       struct mxc_jpeg_q_data *q_data_out, *q_data_cap;
+       enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       bool src_chg = false;
+       u32 fourcc;
+       struct v4l2_jpeg_header header;
+       struct mxc_jpeg_sof *psof = NULL;
+       struct mxc_jpeg_sos *psos = NULL;
+       int ret;
+
+       memset(&header, 0, sizeof(header));
+       ret = v4l2_jpeg_parse_header((void *)src_addr, size, &header);
+       if (ret < 0) {
+               dev_err(dev, "Error parsing JPEG stream markers\n");
+               return ret;
+       }
+
+       /* if DHT marker present, no need to inject default one */
+       *dht_needed = (header.num_dht == 0);
+
+       q_data_out = mxc_jpeg_get_q_data(ctx,
+                                        V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+       if (q_data_out->w == 0 && q_data_out->h == 0) {
+               dev_warn(dev, "Invalid user resolution 0x0");
+               dev_warn(dev, "Keeping resolution from JPEG: %dx%d",
+                        header.frame.width, header.frame.height);
+               q_data_out->w = header.frame.width;
+               q_data_out->h = header.frame.height;
+       } else if (header.frame.width != q_data_out->w ||
+                  header.frame.height != q_data_out->h) {
+               dev_err(dev,
+                       "Resolution mismatch: %dx%d (JPEG) versus %dx%d(user)",
+                       header.frame.width, header.frame.height,
+                       q_data_out->w, q_data_out->h);
+               return -EINVAL;
+       }
+       if (header.frame.width % 8 != 0 || header.frame.height % 8 != 0) {
+               dev_err(dev, "JPEG width or height not multiple of 8: %dx%d\n",
+                       header.frame.width, header.frame.height);
+               return -EINVAL;
+       }
+       if (header.frame.width > MXC_JPEG_MAX_WIDTH ||
+           header.frame.height > MXC_JPEG_MAX_HEIGHT) {
+               dev_err(dev, "JPEG width or height should be <= 8192: %dx%d\n",
+                       header.frame.width, header.frame.height);
+               return -EINVAL;
+       }
+       if (header.frame.width < MXC_JPEG_MIN_WIDTH ||
+           header.frame.height < MXC_JPEG_MIN_HEIGHT) {
+               dev_err(dev, "JPEG width or height should be > 64: %dx%d\n",
+                       header.frame.width, header.frame.height);
+               return -EINVAL;
+       }
+       if (header.frame.num_components > V4L2_JPEG_MAX_COMPONENTS) {
+               dev_err(dev, "JPEG number of components should be <=%d",
+                       V4L2_JPEG_MAX_COMPONENTS);
+               return -EINVAL;
+       }
+       /* check and, if necessary, patch component IDs*/
+       psof = (struct mxc_jpeg_sof *)header.sof.start;
+       psos = (struct mxc_jpeg_sos *)header.sos.start;
+       if (!mxc_jpeg_valid_comp_id(dev, psof, psos))
+               dev_warn(dev, "JPEG component ids should be 0-3 or 1-4");
+
+       fourcc = mxc_jpeg_get_image_format(dev, &header);
+       if (fourcc == 0)
+               return -EINVAL;
+
+       /*
+        * set-up the capture queue with the pixelformat and resolution
+        * detected from the jpeg output stream
+        */
+       q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
+       if (q_data_cap->w != header.frame.width ||
+           q_data_cap->h != header.frame.height)
+               src_chg = true;
+       q_data_cap->w = header.frame.width;
+       q_data_cap->h = header.frame.height;
+       q_data_cap->fmt = mxc_jpeg_find_format(ctx, fourcc);
+       q_data_cap->w_adjusted = q_data_cap->w;
+       q_data_cap->h_adjusted = q_data_cap->h;
+       /*
+        * align up the resolution for CAST IP,
+        * but leave the buffer resolution unchanged
+        */
+       v4l_bound_align_image(&q_data_cap->w_adjusted,
+                             q_data_cap->w_adjusted,  /* adjust up */
+                             MXC_JPEG_MAX_WIDTH,
+                             q_data_cap->fmt->h_align,
+                             &q_data_cap->h_adjusted,
+                             q_data_cap->h_adjusted, /* adjust up */
+                             MXC_JPEG_MAX_HEIGHT,
+                             q_data_cap->fmt->v_align,
+                             0);
+       dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
+               q_data_cap->w, q_data_cap->h,
+               q_data_cap->w_adjusted, q_data_cap->h_adjusted,
+               (fourcc & 0xff),
+               (fourcc >>  8) & 0xff,
+               (fourcc >> 16) & 0xff,
+               (fourcc >> 24) & 0xff);
+
+       /* setup bytesperline/sizeimage for capture queue */
+       mxc_jpeg_bytesperline(q_data_cap, header.frame.precision);
+       mxc_jpeg_sizeimage(q_data_cap);
+
+       /*
+        * if the CAPTURE format was updated with new values, regardless of
+        * whether they match the values set by the client or not, signal
+        * a source change event
+        */
+       if (src_chg)
+               notify_src_chg(ctx);
+
+       return 0;
+}
+
+static void mxc_jpeg_buf_queue(struct vb2_buffer *vb)
+{
+       int ret;
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct mxc_jpeg_src_buf *jpeg_src_buf;
+
+       if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               goto end;
+
+       /* for V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE */
+       if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE)
+               goto end;
+
+       jpeg_src_buf = vb2_to_mxc_buf(vb);
+       jpeg_src_buf->jpeg_parse_error = false;
+       ret = mxc_jpeg_parse(ctx,
+                            (u8 *)vb2_plane_vaddr(vb, 0),
+                            vb2_get_plane_payload(vb, 0),
+                            &jpeg_src_buf->dht_needed);
+       if (ret)
+               jpeg_src_buf->jpeg_parse_error = true;
+
+end:
+       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+}
+
+static int mxc_jpeg_buf_out_validate(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+       vbuf->field = V4L2_FIELD_NONE;
+
+       return 0;
+}
+
+static int mxc_jpeg_buf_prepare(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct mxc_jpeg_q_data *q_data = NULL;
+       struct device *dev = ctx->mxc_jpeg->dev;
+       unsigned long sizeimage;
+       int i;
+
+       vbuf->field = V4L2_FIELD_NONE;
+
+       q_data = mxc_jpeg_get_q_data(ctx, vb->vb2_queue->type);
+       if (!q_data)
+               return -EINVAL;
+       for (i = 0; i < q_data->fmt->colplanes; i++) {
+               sizeimage = q_data->sizeimage[i];
+               if (vb2_plane_size(vb, i) < sizeimage) {
+                       dev_err(dev, "plane %d too small (%lu < %lu)",
+                               i, vb2_plane_size(vb, i), sizeimage);
+                       return -EINVAL;
+               }
+               vb2_set_plane_payload(vb, i, sizeimage);
+       }
+       return 0;
+}
+
+static void mxc_jpeg_buf_finish(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct vb2_queue *q = vb->vb2_queue;
+
+       if (V4L2_TYPE_IS_OUTPUT(vb->type))
+               return;
+       if (!ctx->stopped)
+               return;
+       if (list_empty(&q->done_list)) {
+               vbuf->flags |= V4L2_BUF_FLAG_LAST;
+               ctx->stopped = 0;
+       }
+}
+
+static const struct vb2_ops mxc_jpeg_qops = {
+       .queue_setup            = mxc_jpeg_queue_setup,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
+       .buf_out_validate       = mxc_jpeg_buf_out_validate,
+       .buf_prepare            = mxc_jpeg_buf_prepare,
+       .buf_finish             = mxc_jpeg_buf_finish,
+       .start_streaming        = mxc_jpeg_start_streaming,
+       .stop_streaming         = mxc_jpeg_stop_streaming,
+       .buf_queue              = mxc_jpeg_buf_queue,
+};
+
+static int mxc_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,
+                              struct vb2_queue *dst_vq)
+{
+       struct mxc_jpeg_ctx *ctx = priv;
+       int ret;
+
+       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+       src_vq->drv_priv = ctx;
+       src_vq->buf_struct_size = sizeof(struct mxc_jpeg_src_buf);
+       src_vq->ops = &mxc_jpeg_qops;
+       src_vq->mem_ops = &vb2_dma_contig_memops;
+       src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       src_vq->lock = &ctx->mxc_jpeg->lock;
+       src_vq->dev = ctx->mxc_jpeg->dev;
+       src_vq->allow_zero_bytesused = 1; /* keep old userspace apps working */
+
+       ret = vb2_queue_init(src_vq);
+       if (ret)
+               return ret;
+
+       dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+       dst_vq->drv_priv = ctx;
+       dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       dst_vq->ops = &mxc_jpeg_qops;
+       dst_vq->mem_ops = &vb2_dma_contig_memops;
+       dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       dst_vq->lock = &ctx->mxc_jpeg->lock;
+       dst_vq->dev = ctx->mxc_jpeg->dev;
+
+       ret = vb2_queue_init(dst_vq);
+       return ret;
+}
+
+static void mxc_jpeg_set_default_params(struct mxc_jpeg_ctx *ctx)
+{
+       struct mxc_jpeg_q_data *out_q = &ctx->out_q;
+       struct mxc_jpeg_q_data *cap_q = &ctx->cap_q;
+       struct mxc_jpeg_q_data *q[2] = {out_q, cap_q};
+       int i;
+
+       if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) {
+               out_q->fmt = mxc_jpeg_find_format(ctx, MXC_JPEG_DEFAULT_PFMT);
+               cap_q->fmt = mxc_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG);
+       } else {
+               out_q->fmt = mxc_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG);
+               cap_q->fmt = mxc_jpeg_find_format(ctx, MXC_JPEG_DEFAULT_PFMT);
+       }
+
+       for (i = 0; i < 2; i++) {
+               q[i]->w = MXC_JPEG_DEFAULT_WIDTH;
+               q[i]->h = MXC_JPEG_DEFAULT_HEIGHT;
+               q[i]->w_adjusted = MXC_JPEG_DEFAULT_WIDTH;
+               q[i]->h_adjusted = MXC_JPEG_DEFAULT_HEIGHT;
+               mxc_jpeg_bytesperline(q[i], 8);
+               mxc_jpeg_sizeimage(q[i]);
+       }
+}
+
+static int mxc_jpeg_open(struct file *file)
+{
+       struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file);
+       struct video_device *mxc_vfd = video_devdata(file);
+       struct device *dev = mxc_jpeg->dev;
+       struct mxc_jpeg_ctx *ctx;
+       int ret = 0;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       if (mutex_lock_interruptible(&mxc_jpeg->lock)) {
+               ret = -ERESTARTSYS;
+               goto free;
+       }
+
+       v4l2_fh_init(&ctx->fh, mxc_vfd);
+       file->private_data = &ctx->fh;
+       v4l2_fh_add(&ctx->fh);
+
+       ctx->mxc_jpeg = mxc_jpeg;
+
+       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(mxc_jpeg->m2m_dev, ctx,
+                                           mxc_jpeg_queue_init);
+
+       if (IS_ERR(ctx->fh.m2m_ctx)) {
+               ret = PTR_ERR(ctx->fh.m2m_ctx);
+               goto error;
+       }
+
+       mxc_jpeg_set_default_params(ctx);
+       ctx->slot = MXC_MAX_SLOTS; /* slot not allocated yet */
+
+       if (mxc_jpeg->mode == MXC_JPEG_DECODE)
+               dev_dbg(dev, "Opened JPEG decoder instance %p\n", ctx);
+       else
+               dev_dbg(dev, "Opened JPEG encoder instance %p\n", ctx);
+       mutex_unlock(&mxc_jpeg->lock);
+
+       return 0;
+
+error:
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       mutex_unlock(&mxc_jpeg->lock);
+free:
+       kfree(ctx);
+       return ret;
+}
+
+static int mxc_jpeg_querycap(struct file *file, void *priv,
+                            struct v4l2_capability *cap)
+{
+       struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file);
+
+       strscpy(cap->driver, MXC_JPEG_NAME " codec", sizeof(cap->driver));
+       strscpy(cap->card, MXC_JPEG_NAME " codec", sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                dev_name(mxc_jpeg->dev));
+       cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+       return 0;
+}
+
+static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
+                                    struct v4l2_fmtdesc *f)
+{
+       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
+
+       if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE)
+               return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
+                       MXC_JPEG_FMT_TYPE_ENC);
+       else
+               return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
+                       MXC_JPEG_FMT_TYPE_RAW);
+}
+
+static int mxc_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
+                                    struct v4l2_fmtdesc *f)
+{
+       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
+
+       if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)
+               return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
+                               MXC_JPEG_FMT_TYPE_ENC);
+       else
+               return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
+                               MXC_JPEG_FMT_TYPE_RAW);
+}
+
+static int mxc_jpeg_try_fmt(struct v4l2_format *f, const struct mxc_jpeg_fmt *fmt,
+                           struct mxc_jpeg_ctx *ctx, int q_type)
+{
+       struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+       struct v4l2_plane_pix_format *pfmt;
+       u32 w = (pix_mp->width < MXC_JPEG_MAX_WIDTH) ?
+                pix_mp->width : MXC_JPEG_MAX_WIDTH;
+       u32 h = (pix_mp->height < MXC_JPEG_MAX_HEIGHT) ?
+                pix_mp->height : MXC_JPEG_MAX_HEIGHT;
+       int i;
+       struct mxc_jpeg_q_data tmp_q;
+
+       memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
+       pix_mp->field = V4L2_FIELD_NONE;
+       pix_mp->num_planes = fmt->colplanes;
+       pix_mp->pixelformat = fmt->fourcc;
+
+       /*
+        * use MXC_JPEG_H_ALIGN instead of fmt->v_align, for vertical
+        * alignment, to loosen up the alignment to multiple of 8,
+        * otherwise NV12-1080p fails as 1080 is not a multiple of 16
+        */
+       v4l_bound_align_image(&w,
+                             MXC_JPEG_MIN_WIDTH,
+                             w, /* adjust downwards*/
+                             fmt->h_align,
+                             &h,
+                             MXC_JPEG_MIN_HEIGHT,
+                             h, /* adjust downwards*/
+                             MXC_JPEG_H_ALIGN,
+                             0);
+       pix_mp->width = w; /* negotiate the width */
+       pix_mp->height = h; /* negotiate the height */
+
+       /* get user input into the tmp_q */
+       tmp_q.w = w;
+       tmp_q.h = h;
+       tmp_q.fmt = fmt;
+       for (i = 0; i < pix_mp->num_planes; i++) {
+               pfmt = &pix_mp->plane_fmt[i];
+               tmp_q.bytesperline[i] = pfmt->bytesperline;
+               tmp_q.sizeimage[i] = pfmt->sizeimage;
+       }
+
+       /* calculate bytesperline & sizeimage into the tmp_q */
+       mxc_jpeg_bytesperline(&tmp_q, 8);
+       mxc_jpeg_sizeimage(&tmp_q);
+
+       /* adjust user format according to our calculations */
+       for (i = 0; i < pix_mp->num_planes; i++) {
+               pfmt = &pix_mp->plane_fmt[i];
+               memset(pfmt->reserved, 0, sizeof(pfmt->reserved));
+               pfmt->bytesperline = tmp_q.bytesperline[i];
+               pfmt->sizeimage = tmp_q.sizeimage[i];
+       }
+
+       /* fix colorspace information to sRGB for both output & capture */
+       pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
+       pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_601;
+       pix_mp->xfer_func = V4L2_XFER_FUNC_SRGB;
+       /*
+        * this hardware does not change the range of the samples
+        * but since inside JPEG the YUV quantization is full-range,
+        * this driver will always use full-range for the raw frames, too
+        */
+       pix_mp->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+
+       return 0;
+}
+
+static int mxc_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
+                                   struct v4l2_format *f)
+{
+       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
+       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
+       struct device *dev = jpeg->dev;
+       const struct mxc_jpeg_fmt *fmt;
+       u32 fourcc = f->fmt.pix_mp.pixelformat;
+
+       int q_type = (jpeg->mode == MXC_JPEG_DECODE) ?
+                    MXC_JPEG_FMT_TYPE_RAW : MXC_JPEG_FMT_TYPE_ENC;
+
+       if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
+               dev_err(dev, "TRY_FMT with Invalid type: %d\n", f->type);
+               return -EINVAL;
+       }
+
+       fmt = mxc_jpeg_find_format(ctx, fourcc);
+       if (!fmt || fmt->flags != q_type) {
+               dev_warn(dev, "Format not supported: %c%c%c%c, use the default.\n",
+                        (fourcc & 0xff),
+                        (fourcc >>  8) & 0xff,
+                        (fourcc >> 16) & 0xff,
+                        (fourcc >> 24) & 0xff);
+               f->fmt.pix_mp.pixelformat = (jpeg->mode == MXC_JPEG_DECODE) ?
+                               MXC_JPEG_DEFAULT_PFMT : V4L2_PIX_FMT_JPEG;
+               fmt = mxc_jpeg_find_format(ctx, f->fmt.pix_mp.pixelformat);
+       }
+       return mxc_jpeg_try_fmt(f, fmt, ctx, q_type);
+}
+
+static int mxc_jpeg_try_fmt_vid_out(struct file *file, void *priv,
+                                   struct v4l2_format *f)
+{
+       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
+       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
+       struct device *dev = jpeg->dev;
+       const struct mxc_jpeg_fmt *fmt;
+       u32 fourcc = f->fmt.pix_mp.pixelformat;
+
+       int q_type = (jpeg->mode == MXC_JPEG_ENCODE) ?
+                    MXC_JPEG_FMT_TYPE_RAW : MXC_JPEG_FMT_TYPE_ENC;
+
+       if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
+               dev_err(dev, "TRY_FMT with Invalid type: %d\n", f->type);
+               return -EINVAL;
+       }
+
+       fmt = mxc_jpeg_find_format(ctx, fourcc);
+       if (!fmt || fmt->flags != q_type) {
+               dev_warn(dev, "Format not supported: %c%c%c%c, use the default.\n",
+                        (fourcc & 0xff),
+                        (fourcc >>  8) & 0xff,
+                        (fourcc >> 16) & 0xff,
+                        (fourcc >> 24) & 0xff);
+               f->fmt.pix_mp.pixelformat = (jpeg->mode == MXC_JPEG_ENCODE) ?
+                               MXC_JPEG_DEFAULT_PFMT : V4L2_PIX_FMT_JPEG;
+               fmt = mxc_jpeg_find_format(ctx, f->fmt.pix_mp.pixelformat);
+       }
+       return mxc_jpeg_try_fmt(f, fmt, ctx, q_type);
+}
+
+static int mxc_jpeg_s_fmt(struct mxc_jpeg_ctx *ctx,
+                         struct v4l2_format *f)
+{
+       struct vb2_queue *vq;
+       struct mxc_jpeg_q_data *q_data = NULL;
+       struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
+       int i;
+
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       q_data = mxc_jpeg_get_q_data(ctx, f->type);
+
+       if (vb2_is_busy(vq)) {
+               v4l2_err(&jpeg->v4l2_dev, "queue busy\n");
+               return -EBUSY;
+       }
+
+       q_data->fmt = mxc_jpeg_find_format(ctx, pix_mp->pixelformat);
+       q_data->w = pix_mp->width;
+       q_data->h = pix_mp->height;
+
+       q_data->w_adjusted = q_data->w;
+       q_data->h_adjusted = q_data->h;
+       if (jpeg->mode == MXC_JPEG_DECODE) {
+               /*
+                * align up the resolution for CAST IP,
+                * but leave the buffer resolution unchanged
+                */
+               v4l_bound_align_image(&q_data->w_adjusted,
+                                     q_data->w_adjusted,  /* adjust upwards */
+                                     MXC_JPEG_MAX_WIDTH,
+                                     q_data->fmt->h_align,
+                                     &q_data->h_adjusted,
+                                     q_data->h_adjusted, /* adjust upwards */
+                                     MXC_JPEG_MAX_HEIGHT,
+                                     q_data->fmt->v_align,
+                                     0);
+       } else {
+               /*
+                * align down the resolution for CAST IP,
+                * but leave the buffer resolution unchanged
+                */
+               v4l_bound_align_image(&q_data->w_adjusted,
+                                     MXC_JPEG_MIN_WIDTH,
+                                     q_data->w_adjusted, /* adjust downwards*/
+                                     q_data->fmt->h_align,
+                                     &q_data->h_adjusted,
+                                     MXC_JPEG_MIN_HEIGHT,
+                                     q_data->h_adjusted, /* adjust downwards*/
+                                     q_data->fmt->v_align,
+                                     0);
+       }
+
+       for (i = 0; i < pix_mp->num_planes; i++) {
+               q_data->bytesperline[i] = pix_mp->plane_fmt[i].bytesperline;
+               q_data->sizeimage[i] = pix_mp->plane_fmt[i].sizeimage;
+       }
+
+       return 0;
+}
+
+static int mxc_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       int ret;
+
+       ret = mxc_jpeg_try_fmt_vid_cap(file, priv, f);
+       if (ret)
+               return ret;
+
+       return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
+}
+
+static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       int ret;
+
+       ret = mxc_jpeg_try_fmt_vid_out(file, priv, f);
+       if (ret)
+               return ret;
+
+       return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
+}
+
+static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv,
+                             struct v4l2_format *f)
+{
+       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
+       struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
+       struct device *dev = jpeg->dev;
+       struct v4l2_pix_format_mplane   *pix_mp = &f->fmt.pix_mp;
+       struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, f->type);
+       int i;
+
+       if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
+               dev_err(dev, "G_FMT with Invalid type: %d\n", f->type);
+               return -EINVAL;
+       }
+
+       pix_mp->pixelformat = q_data->fmt->fourcc;
+       pix_mp->width = q_data->w;
+       pix_mp->height = q_data->h;
+       pix_mp->field = V4L2_FIELD_NONE;
+
+       /* fix colorspace information to sRGB for both output & capture */
+       pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
+       pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_601;
+       pix_mp->xfer_func = V4L2_XFER_FUNC_SRGB;
+       pix_mp->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+
+       pix_mp->num_planes = q_data->fmt->colplanes;
+       for (i = 0; i < pix_mp->num_planes; i++) {
+               pix_mp->plane_fmt[i].bytesperline = q_data->bytesperline[i];
+               pix_mp->plane_fmt[i].sizeimage = q_data->sizeimage[i];
+       }
+
+       return 0;
+}
+
+static int mxc_jpeg_subscribe_event(struct v4l2_fh *fh,
+                                   const struct v4l2_event_subscription *sub)
+{
+       switch (sub->type) {
+       case V4L2_EVENT_EOS:
+               return v4l2_event_subscribe(fh, sub, 0, NULL);
+       case V4L2_EVENT_SOURCE_CHANGE:
+               return v4l2_src_change_event_subscribe(fh, sub);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int mxc_jpeg_dqbuf(struct file *file, void *priv,
+                         struct v4l2_buffer *buf)
+{
+       struct v4l2_fh *fh = file->private_data;
+       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
+       struct device *dev = ctx->mxc_jpeg->dev;
+       int num_src_ready = v4l2_m2m_num_src_bufs_ready(fh->m2m_ctx);
+       int ret;
+
+       dev_dbg(dev, "DQBUF type=%d, index=%d", buf->type, buf->index);
+       if (ctx->stopping == 1 && num_src_ready == 0) {
+               /* No more src bufs, notify app EOS */
+               notify_eos(ctx);
+               ctx->stopping = 0;
+               mxc_jpeg_set_last_buffer_dequeued(ctx);
+       }
+
+       ret = v4l2_m2m_dqbuf(file, fh->m2m_ctx, buf);
+       return ret;
+}
+
+static const struct v4l2_ioctl_ops mxc_jpeg_ioctl_ops = {
+       .vidioc_querycap                = mxc_jpeg_querycap,
+       .vidioc_enum_fmt_vid_cap        = mxc_jpeg_enum_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_out        = mxc_jpeg_enum_fmt_vid_out,
+
+       .vidioc_try_fmt_vid_cap_mplane  = mxc_jpeg_try_fmt_vid_cap,
+       .vidioc_try_fmt_vid_out_mplane  = mxc_jpeg_try_fmt_vid_out,
+
+       .vidioc_s_fmt_vid_cap_mplane    = mxc_jpeg_s_fmt_vid_cap,
+       .vidioc_s_fmt_vid_out_mplane    = mxc_jpeg_s_fmt_vid_out,
+
+       .vidioc_g_fmt_vid_cap_mplane    = mxc_jpeg_g_fmt_vid,
+       .vidioc_g_fmt_vid_out_mplane    = mxc_jpeg_g_fmt_vid,
+
+       .vidioc_subscribe_event         = mxc_jpeg_subscribe_event,
+       .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
+
+       .vidioc_try_decoder_cmd         = v4l2_m2m_ioctl_try_decoder_cmd,
+       .vidioc_decoder_cmd             = mxc_jpeg_decoder_cmd,
+       .vidioc_try_encoder_cmd         = v4l2_m2m_ioctl_try_encoder_cmd,
+       .vidioc_encoder_cmd             = mxc_jpeg_encoder_cmd,
+
+       .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
+       .vidioc_dqbuf                   = mxc_jpeg_dqbuf,
+
+       .vidioc_create_bufs             = v4l2_m2m_ioctl_create_bufs,
+       .vidioc_prepare_buf             = v4l2_m2m_ioctl_prepare_buf,
+       .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
+       .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
+       .vidioc_expbuf                  = v4l2_m2m_ioctl_expbuf,
+       .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
+       .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
+};
+
+static int mxc_jpeg_release(struct file *file)
+{
+       struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file);
+       struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(file->private_data);
+       struct device *dev = mxc_jpeg->dev;
+
+       mutex_lock(&mxc_jpeg->lock);
+       if (mxc_jpeg->mode == MXC_JPEG_DECODE)
+               dev_dbg(dev, "Release JPEG decoder instance on slot %d.",
+                       ctx->slot);
+       else
+               dev_dbg(dev, "Release JPEG encoder instance on slot %d.",
+                       ctx->slot);
+       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       kfree(ctx);
+       mutex_unlock(&mxc_jpeg->lock);
+
+       return 0;
+}
+
+static const struct v4l2_file_operations mxc_jpeg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = mxc_jpeg_open,
+       .release        = mxc_jpeg_release,
+       .poll           = v4l2_m2m_fop_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = v4l2_m2m_fop_mmap,
+};
+
+static const struct v4l2_m2m_ops mxc_jpeg_m2m_ops = {
+       .device_run     = mxc_jpeg_device_run,
+};
+
+static void mxc_jpeg_detach_pm_domains(struct mxc_jpeg_dev *jpeg)
+{
+       int i;
+
+       for (i = 0; i < jpeg->num_domains; i++) {
+               if (jpeg->pd_link[i] && !IS_ERR(jpeg->pd_link[i]))
+                       device_link_del(jpeg->pd_link[i]);
+               if (jpeg->pd_dev[i] && !IS_ERR(jpeg->pd_dev[i]))
+                       dev_pm_domain_detach(jpeg->pd_dev[i], true);
+               jpeg->pd_dev[i] = NULL;
+               jpeg->pd_link[i] = NULL;
+       }
+}
+
+static int mxc_jpeg_attach_pm_domains(struct mxc_jpeg_dev *jpeg)
+{
+       struct device *dev = jpeg->dev;
+       struct device_node *np = jpeg->pdev->dev.of_node;
+       int i;
+       int ret;
+
+       jpeg->num_domains = of_count_phandle_with_args(np, "power-domains",
+                                                      "#power-domain-cells");
+       if (jpeg->num_domains < 0) {
+               dev_err(dev, "No power domains defined for jpeg node\n");
+               return jpeg->num_domains;
+       }
+
+       jpeg->pd_dev = devm_kmalloc_array(dev, jpeg->num_domains,
+                                         sizeof(*jpeg->pd_dev), GFP_KERNEL);
+       if (!jpeg->pd_dev)
+               return -ENOMEM;
+
+       jpeg->pd_link = devm_kmalloc_array(dev, jpeg->num_domains,
+                                          sizeof(*jpeg->pd_link), GFP_KERNEL);
+       if (!jpeg->pd_link)
+               return -ENOMEM;
+
+       for (i = 0; i < jpeg->num_domains; i++) {
+               jpeg->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
+               if (IS_ERR(jpeg->pd_dev[i])) {
+                       ret = PTR_ERR(jpeg->pd_dev[i]);
+                       goto fail;
+               }
+
+               jpeg->pd_link[i] = device_link_add(dev, jpeg->pd_dev[i],
+                                                  DL_FLAG_STATELESS |
+                                                  DL_FLAG_PM_RUNTIME);
+               if (!jpeg->pd_link[i]) {
+                       ret = -EINVAL;
+                       goto fail;
+               }
+       }
+
+       return 0;
+fail:
+       mxc_jpeg_detach_pm_domains(jpeg);
+       return ret;
+}
+
+static int mxc_jpeg_probe(struct platform_device *pdev)
+{
+       struct mxc_jpeg_dev *jpeg;
+       struct device *dev = &pdev->dev;
+       int dec_irq;
+       int ret;
+       int mode;
+       const struct of_device_id *of_id;
+       unsigned int slot;
+
+       of_id = of_match_node(mxc_jpeg_match, dev->of_node);
+       mode = *(const int *)of_id->data;
+
+       jpeg = devm_kzalloc(dev, sizeof(struct mxc_jpeg_dev), GFP_KERNEL);
+       if (!jpeg)
+               return -ENOMEM;
+
+       mutex_init(&jpeg->lock);
+       spin_lock_init(&jpeg->hw_lock);
+
+       ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+       if (ret) {
+               dev_err(&pdev->dev, "No suitable DMA available.\n");
+               goto err_irq;
+       }
+
+       jpeg->base_reg = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(jpeg->base_reg))
+               return PTR_ERR(jpeg->base_reg);
+
+       for (slot = 0; slot < MXC_MAX_SLOTS; slot++) {
+               dec_irq = platform_get_irq(pdev, slot);
+               if (dec_irq < 0) {
+                       ret = dec_irq;
+                       goto err_irq;
+               }
+               ret = devm_request_irq(&pdev->dev, dec_irq, mxc_jpeg_dec_irq,
+                                      0, pdev->name, jpeg);
+               if (ret) {
+                       dev_err(&pdev->dev, "Failed to request irq %d (%d)\n",
+                               dec_irq, ret);
+                       goto err_irq;
+               }
+       }
+
+       jpeg->pdev = pdev;
+       jpeg->dev = dev;
+       jpeg->mode = mode;
+
+       /* Get clocks */
+       jpeg->clk_ipg = devm_clk_get(dev, "ipg");
+       if (IS_ERR(jpeg->clk_ipg)) {
+               dev_err(dev, "failed to get clock: ipg\n");
+               goto err_clk;
+       }
+
+       jpeg->clk_per = devm_clk_get(dev, "per");
+       if (IS_ERR(jpeg->clk_per)) {
+               dev_err(dev, "failed to get clock: per\n");
+               goto err_clk;
+       }
+
+       ret = mxc_jpeg_attach_pm_domains(jpeg);
+       if (ret < 0) {
+               dev_err(dev, "failed to attach power domains %d\n", ret);
+               return ret;
+       }
+
+       /* v4l2 */
+       ret = v4l2_device_register(dev, &jpeg->v4l2_dev);
+       if (ret) {
+               dev_err(dev, "failed to register v4l2 device\n");
+               goto err_register;
+       }
+       jpeg->m2m_dev = v4l2_m2m_init(&mxc_jpeg_m2m_ops);
+       if (IS_ERR(jpeg->m2m_dev)) {
+               dev_err(dev, "failed to register v4l2 device\n");
+               ret = PTR_ERR(jpeg->m2m_dev);
+               goto err_m2m;
+       }
+
+       jpeg->dec_vdev = video_device_alloc();
+       if (!jpeg->dec_vdev) {
+               dev_err(dev, "failed to register v4l2 device\n");
+               ret = -ENOMEM;
+               goto err_vdev_alloc;
+       }
+       if (mode == MXC_JPEG_ENCODE)
+               snprintf(jpeg->dec_vdev->name,
+                        sizeof(jpeg->dec_vdev->name),
+                        "%s-enc", MXC_JPEG_NAME);
+       else
+               snprintf(jpeg->dec_vdev->name,
+                        sizeof(jpeg->dec_vdev->name),
+                        "%s-dec", MXC_JPEG_NAME);
+
+       jpeg->dec_vdev->fops = &mxc_jpeg_fops;
+       jpeg->dec_vdev->ioctl_ops = &mxc_jpeg_ioctl_ops;
+       jpeg->dec_vdev->minor = -1;
+       jpeg->dec_vdev->release = video_device_release;
+       jpeg->dec_vdev->lock = &jpeg->lock; /* lock for ioctl serialization */
+       jpeg->dec_vdev->v4l2_dev = &jpeg->v4l2_dev;
+       jpeg->dec_vdev->vfl_dir = VFL_DIR_M2M;
+       jpeg->dec_vdev->device_caps = V4L2_CAP_STREAMING |
+                                       V4L2_CAP_VIDEO_M2M_MPLANE;
+       if (mode == MXC_JPEG_ENCODE) {
+               v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_DECODER_CMD);
+               v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_TRY_DECODER_CMD);
+       } else {
+               v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_ENCODER_CMD);
+               v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_TRY_ENCODER_CMD);
+       }
+       ret = video_register_device(jpeg->dec_vdev, VFL_TYPE_VIDEO, -1);
+       if (ret) {
+               dev_err(dev, "failed to register video device\n");
+               goto err_vdev_register;
+       }
+       video_set_drvdata(jpeg->dec_vdev, jpeg);
+       if (mode == MXC_JPEG_ENCODE)
+               v4l2_info(&jpeg->v4l2_dev,
+                         "encoder device registered as /dev/video%d (%d,%d)\n",
+                         jpeg->dec_vdev->num, VIDEO_MAJOR,
+                         jpeg->dec_vdev->minor);
+       else
+               v4l2_info(&jpeg->v4l2_dev,
+                         "decoder device registered as /dev/video%d (%d,%d)\n",
+                         jpeg->dec_vdev->num, VIDEO_MAJOR,
+                         jpeg->dec_vdev->minor);
+
+       platform_set_drvdata(pdev, jpeg);
+       pm_runtime_enable(dev);
+
+       return 0;
+
+err_vdev_register:
+       video_device_release(jpeg->dec_vdev);
+
+err_vdev_alloc:
+       v4l2_m2m_release(jpeg->m2m_dev);
+
+err_m2m:
+       v4l2_device_unregister(&jpeg->v4l2_dev);
+
+err_register:
+       mxc_jpeg_detach_pm_domains(jpeg);
+
+err_irq:
+err_clk:
+       return ret;
+}
+
+#ifdef CONFIG_PM
+static int mxc_jpeg_runtime_resume(struct device *dev)
+{
+       struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);
+       int ret;
+
+       ret = clk_prepare_enable(jpeg->clk_ipg);
+       if (ret < 0) {
+               dev_err(dev, "failed to enable clock: ipg\n");
+               goto err_ipg;
+       }
+
+       ret = clk_prepare_enable(jpeg->clk_per);
+       if (ret < 0) {
+               dev_err(dev, "failed to enable clock: per\n");
+               goto err_per;
+       }
+
+       return 0;
+
+err_per:
+       clk_disable_unprepare(jpeg->clk_ipg);
+err_ipg:
+       return ret;
+}
+
+static int mxc_jpeg_runtime_suspend(struct device *dev)
+{
+       struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);
+
+       clk_disable_unprepare(jpeg->clk_ipg);
+       clk_disable_unprepare(jpeg->clk_per);
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops mxc_jpeg_pm_ops = {
+       SET_RUNTIME_PM_OPS(mxc_jpeg_runtime_suspend,
+                          mxc_jpeg_runtime_resume, NULL)
+};
+
+static int mxc_jpeg_remove(struct platform_device *pdev)
+{
+       unsigned int slot;
+       struct mxc_jpeg_dev *jpeg = platform_get_drvdata(pdev);
+
+       for (slot = 0; slot < MXC_MAX_SLOTS; slot++)
+               mxc_jpeg_free_slot_data(jpeg, slot);
+
+       pm_runtime_disable(&pdev->dev);
+       video_unregister_device(jpeg->dec_vdev);
+       v4l2_m2m_release(jpeg->m2m_dev);
+       v4l2_device_unregister(&jpeg->v4l2_dev);
+       mxc_jpeg_detach_pm_domains(jpeg);
+
+       return 0;
+}
+
+MODULE_DEVICE_TABLE(of, mxc_jpeg_match);
+
+static struct platform_driver mxc_jpeg_driver = {
+       .probe = mxc_jpeg_probe,
+       .remove = mxc_jpeg_remove,
+       .driver = {
+               .name = "mxc-jpeg",
+               .of_match_table = mxc_jpeg_match,
+               .pm = &mxc_jpeg_pm_ops,
+       },
+};
+module_platform_driver(mxc_jpeg_driver);
+
+MODULE_AUTHOR("Zhengyu Shen <zhengyu.shen_1@nxp.com>");
+MODULE_AUTHOR("Mirela Rabulea <mirela.rabulea@nxp.com>");
+MODULE_DESCRIPTION("V4L2 driver for i.MX8 QXP/QM JPEG encoder/decoder");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
new file mode 100644 (file)
index 0000000..f53f004
--- /dev/null
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * i.MX8QXP/i.MX8QM JPEG encoder/decoder v4l2 driver
+ *
+ * Copyright 2018-2019 NXP
+ */
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+
+#ifndef _MXC_JPEG_CORE_H
+#define _MXC_JPEG_CORE_H
+
+#define MXC_JPEG_NAME                  "mxc-jpeg"
+#define MXC_JPEG_FMT_TYPE_ENC          0
+#define MXC_JPEG_FMT_TYPE_RAW          1
+#define MXC_JPEG_DEFAULT_WIDTH         1280
+#define MXC_JPEG_DEFAULT_HEIGHT                720
+#define MXC_JPEG_DEFAULT_PFMT          V4L2_PIX_FMT_RGB24
+#define MXC_JPEG_MIN_WIDTH             64
+#define MXC_JPEG_MIN_HEIGHT            64
+#define MXC_JPEG_MAX_WIDTH             0x2000
+#define MXC_JPEG_MAX_HEIGHT            0x2000
+#define MXC_JPEG_MAX_CFG_STREAM                0x1000
+#define MXC_JPEG_H_ALIGN               3
+#define MXC_JPEG_W_ALIGN               3
+#define MXC_JPEG_MAX_SIZEIMAGE         0xFFFFFC00
+#define MXC_JPEG_MAX_PLANES            2
+
+enum mxc_jpeg_enc_state {
+       MXC_JPEG_ENCODING       = 0, /* jpeg encode phase */
+       MXC_JPEG_ENC_CONF       = 1, /* jpeg encoder config phase */
+};
+
+enum mxc_jpeg_mode {
+       MXC_JPEG_DECODE = 0, /* jpeg decode mode */
+       MXC_JPEG_ENCODE = 1, /* jpeg encode mode */
+};
+
+/**
+ * struct mxc_jpeg_fmt - driver's internal color format data
+ * @name:      format description
+ * @fourcc:    fourcc code, 0 if not applicable
+ * @subsampling: subsampling of jpeg components
+ * @nc:                number of color components
+ * @depth:     number of bits per pixel
+ * @colplanes: number of color planes (1 for packed formats)
+ * @h_align:   horizontal alignment order (align to 2^h_align)
+ * @v_align:   vertical alignment order (align to 2^v_align)
+ * @flags:     flags describing format applicability
+ */
+struct mxc_jpeg_fmt {
+       const char                              *name;
+       u32                                     fourcc;
+       enum v4l2_jpeg_chroma_subsampling       subsampling;
+       int                                     nc;
+       int                                     depth;
+       int                                     colplanes;
+       int                                     h_align;
+       int                                     v_align;
+       u32                                     flags;
+};
+
+struct mxc_jpeg_desc {
+       u32 next_descpt_ptr;
+       u32 buf_base0;
+       u32 buf_base1;
+       u32 line_pitch;
+       u32 stm_bufbase;
+       u32 stm_bufsize;
+       u32 imgsize;
+       u32 stm_ctrl;
+} __packed;
+
+struct mxc_jpeg_q_data {
+       const struct mxc_jpeg_fmt       *fmt;
+       u32                             sizeimage[MXC_JPEG_MAX_PLANES];
+       u32                             bytesperline[MXC_JPEG_MAX_PLANES];
+       int                             w;
+       int                             w_adjusted;
+       int                             h;
+       int                             h_adjusted;
+       unsigned int                    sequence;
+};
+
+struct mxc_jpeg_ctx {
+       struct mxc_jpeg_dev             *mxc_jpeg;
+       struct mxc_jpeg_q_data          out_q;
+       struct mxc_jpeg_q_data          cap_q;
+       struct v4l2_fh                  fh;
+       enum mxc_jpeg_enc_state         enc_state;
+       unsigned int                    stopping;
+       unsigned int                    stopped;
+       unsigned int                    slot;
+};
+
+struct mxc_jpeg_slot_data {
+       bool used;
+       struct mxc_jpeg_desc *desc; // enc/dec descriptor
+       struct mxc_jpeg_desc *cfg_desc; // configuration descriptor
+       void *cfg_stream_vaddr; // configuration bitstream virtual address
+       unsigned int cfg_stream_size;
+       dma_addr_t desc_handle;
+       dma_addr_t cfg_desc_handle; // configuration descriptor dma address
+       dma_addr_t cfg_stream_handle; // configuration bitstream dma address
+};
+
+struct mxc_jpeg_dev {
+       spinlock_t                      hw_lock; /* hardware access lock */
+       unsigned int                    mode;
+       struct mutex                    lock; /* v4l2 ioctls serialization */
+       struct clk                      *clk_ipg;
+       struct clk                      *clk_per;
+       struct platform_device          *pdev;
+       struct device                   *dev;
+       void __iomem                    *base_reg;
+       struct v4l2_device              v4l2_dev;
+       struct v4l2_m2m_dev             *m2m_dev;
+       struct video_device             *dec_vdev;
+       struct mxc_jpeg_slot_data       slot_data[MXC_MAX_SLOTS];
+       int                             num_domains;
+       struct device                   **pd_dev;
+       struct device_link              **pd_link;
+};
+
+/**
+ * struct mxc_jpeg_sof_comp - JPEG Start Of Frame component fields
+ * @id:                                component id
+ * @v:                         vertical sampling
+ * @h:                         horizontal sampling
+ * @quantization_table_no:     id of quantization table
+ */
+struct mxc_jpeg_sof_comp {
+       u8 id;
+       u8 v :4;
+       u8 h :4;
+       u8 quantization_table_no;
+} __packed;
+
+#define MXC_JPEG_MAX_COMPONENTS 4
+/**
+ * struct mxc_jpeg_sof - JPEG Start Of Frame marker fields
+ * @length:            Start of Frame length
+ * @precision:         precision (bits per pixel per color component)
+ * @height:            image height
+ * @width:             image width
+ * @components_no:     number of color components
+ * @comp:              component fields for each color component
+ */
+struct mxc_jpeg_sof {
+       u16 length;
+       u8 precision;
+       u16 height, width;
+       u8 components_no;
+       struct mxc_jpeg_sof_comp comp[MXC_JPEG_MAX_COMPONENTS];
+} __packed;
+
+/**
+ * struct mxc_jpeg_sos_comp - JPEG Start Of Scan component fields
+ * @id:                        component id
+ * @huffman_table_no:  id of the Huffman table
+ */
+struct mxc_jpeg_sos_comp {
+       u8 id; /*component id*/
+       u8 huffman_table_no;
+} __packed;
+
+/**
+ * struct mxc_jpeg_sos - JPEG Start Of Scan marker fields
+ * @length:            Start of Frame length
+ * @components_no:     number of color components
+ * @comp:              SOS component fields for each color component
+ * @ignorable_bytes:   ignorable bytes
+ */
+struct mxc_jpeg_sos {
+       u16 length;
+       u8 components_no;
+       struct mxc_jpeg_sos_comp comp[MXC_JPEG_MAX_COMPONENTS];
+       u8 ignorable_bytes[3];
+} __packed;
+
+#endif
diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c
new file mode 100644 (file)
index 0000000..0a72734
--- /dev/null
@@ -0,0 +1,1581 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Samsung CSIS MIPI CSI-2 receiver driver.
+ *
+ * The Samsung CSIS IP is a MIPI CSI-2 receiver found in various NXP i.MX7 and
+ * i.MX8 SoCs. The i.MX7 features version 3.3 of the IP, while i.MX8 features
+ * version 3.6.3.
+ *
+ * Copyright (C) 2019 Linaro Ltd
+ * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
+#include <media/v4l2-subdev.h>
+
+#define CSIS_DRIVER_NAME                       "imx-mipi-csis"
+
+#define CSIS_PAD_SINK                          0
+#define CSIS_PAD_SOURCE                                1
+#define CSIS_PADS_NUM                          2
+
+#define MIPI_CSIS_DEF_PIX_WIDTH                        640
+#define MIPI_CSIS_DEF_PIX_HEIGHT               480
+
+/* Register map definition */
+
+/* CSIS common control */
+#define MIPI_CSIS_CMN_CTRL                     0x04
+#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW       BIT(16)
+#define MIPI_CSIS_CMN_CTRL_INTER_MODE          BIT(10)
+#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL  BIT(2)
+#define MIPI_CSIS_CMN_CTRL_RESET               BIT(1)
+#define MIPI_CSIS_CMN_CTRL_ENABLE              BIT(0)
+
+#define MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET      8
+#define MIPI_CSIS_CMN_CTRL_LANE_NR_MASK                (3 << 8)
+
+/* CSIS clock control */
+#define MIPI_CSIS_CLK_CTRL                     0x08
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH3(x)        ((x) << 28)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH2(x)        ((x) << 24)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH1(x)        ((x) << 20)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(x)        ((x) << 16)
+#define MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK      (0xf << 4)
+#define MIPI_CSIS_CLK_CTRL_WCLK_SRC            BIT(0)
+
+/* CSIS Interrupt mask */
+#define MIPI_CSIS_INT_MSK                      0x10
+#define MIPI_CSIS_INT_MSK_EVEN_BEFORE          BIT(31)
+#define MIPI_CSIS_INT_MSK_EVEN_AFTER           BIT(30)
+#define MIPI_CSIS_INT_MSK_ODD_BEFORE           BIT(29)
+#define MIPI_CSIS_INT_MSK_ODD_AFTER            BIT(28)
+#define MIPI_CSIS_INT_MSK_FRAME_START          BIT(24)
+#define MIPI_CSIS_INT_MSK_FRAME_END            BIT(20)
+#define MIPI_CSIS_INT_MSK_ERR_SOT_HS           BIT(16)
+#define MIPI_CSIS_INT_MSK_ERR_LOST_FS          BIT(12)
+#define MIPI_CSIS_INT_MSK_ERR_LOST_FE          BIT(8)
+#define MIPI_CSIS_INT_MSK_ERR_OVER             BIT(4)
+#define MIPI_CSIS_INT_MSK_ERR_WRONG_CFG                BIT(3)
+#define MIPI_CSIS_INT_MSK_ERR_ECC              BIT(2)
+#define MIPI_CSIS_INT_MSK_ERR_CRC              BIT(1)
+#define MIPI_CSIS_INT_MSK_ERR_UNKNOWN          BIT(0)
+
+/* CSIS Interrupt source */
+#define MIPI_CSIS_INT_SRC                      0x14
+#define MIPI_CSIS_INT_SRC_EVEN_BEFORE          BIT(31)
+#define MIPI_CSIS_INT_SRC_EVEN_AFTER           BIT(30)
+#define MIPI_CSIS_INT_SRC_EVEN                 BIT(30)
+#define MIPI_CSIS_INT_SRC_ODD_BEFORE           BIT(29)
+#define MIPI_CSIS_INT_SRC_ODD_AFTER            BIT(28)
+#define MIPI_CSIS_INT_SRC_ODD                  (0x3 << 28)
+#define MIPI_CSIS_INT_SRC_NON_IMAGE_DATA       (0xf << 28)
+#define MIPI_CSIS_INT_SRC_FRAME_START          BIT(24)
+#define MIPI_CSIS_INT_SRC_FRAME_END            BIT(20)
+#define MIPI_CSIS_INT_SRC_ERR_SOT_HS           BIT(16)
+#define MIPI_CSIS_INT_SRC_ERR_LOST_FS          BIT(12)
+#define MIPI_CSIS_INT_SRC_ERR_LOST_FE          BIT(8)
+#define MIPI_CSIS_INT_SRC_ERR_OVER             BIT(4)
+#define MIPI_CSIS_INT_SRC_ERR_WRONG_CFG                BIT(3)
+#define MIPI_CSIS_INT_SRC_ERR_ECC              BIT(2)
+#define MIPI_CSIS_INT_SRC_ERR_CRC              BIT(1)
+#define MIPI_CSIS_INT_SRC_ERR_UNKNOWN          BIT(0)
+#define MIPI_CSIS_INT_SRC_ERRORS               0xfffff
+
+/* D-PHY status control */
+#define MIPI_CSIS_DPHY_STATUS                  0x20
+#define MIPI_CSIS_DPHY_STATUS_ULPS_DAT         BIT(8)
+#define MIPI_CSIS_DPHY_STATUS_STOPSTATE_DAT    BIT(4)
+#define MIPI_CSIS_DPHY_STATUS_ULPS_CLK         BIT(1)
+#define MIPI_CSIS_DPHY_STATUS_STOPSTATE_CLK    BIT(0)
+
+/* D-PHY common control */
+#define MIPI_CSIS_DPHY_CMN_CTRL                        0x24
+#define MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(n)    ((n) << 24)
+#define MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE_MASK  GENMASK(31, 24)
+#define MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(n)   ((n) << 22)
+#define MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE_MASK GENMASK(23, 22)
+#define MIPI_CSIS_DPHY_CMN_CTRL_DPDN_SWAP_CLK  BIT(6)
+#define MIPI_CSIS_DPHY_CMN_CTRL_DPDN_SWAP_DAT  BIT(5)
+#define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE_DAT     BIT(1)
+#define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE_CLK     BIT(0)
+#define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE         (0x1f << 0)
+
+/* D-PHY Master and Slave Control register Low */
+#define MIPI_CSIS_DPHY_BCTRL_L                 0x30
+#define MIPI_CSIS_DPHY_BCTRL_L_USER_DATA_PATTERN_LOW(n)                (((n) & 3U) << 30)
+#define MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_715MV             (0 << 28)
+#define MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_724MV             (1 << 28)
+#define MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_733MV             (2 << 28)
+#define MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_706MV             (3 << 28)
+#define MIPI_CSIS_DPHY_BCTRL_L_BGR_CHOPPER_FREQ_3MHZ           (0 << 27)
+#define MIPI_CSIS_DPHY_BCTRL_L_BGR_CHOPPER_FREQ_1_5MHZ         (1 << 27)
+#define MIPI_CSIS_DPHY_BCTRL_L_VREG12_EXTPWR_EN_CTL            BIT(26)
+#define MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_2V            (0 << 24)
+#define MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_23V           (1 << 24)
+#define MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_17V           (2 << 24)
+#define MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_26V           (3 << 24)
+#define MIPI_CSIS_DPHY_BCTRL_L_REG_1P2_LVL_SEL                 BIT(23)
+#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_80MV              (0 << 21)
+#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_100MV             (1 << 21)
+#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_120MV             (2 << 21)
+#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_140MV             (3 << 21)
+#define MIPI_CSIS_DPHY_BCTRL_L_VREF_SRC_SEL                    BIT(20)
+#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_715MV            (0 << 18)
+#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_743MV            (1 << 18)
+#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_650MV            (2 << 18)
+#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_682MV            (3 << 18)
+#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_PULSE_REJECT              BIT(17)
+#define MIPI_CSIS_DPHY_BCTRL_L_MSTRCLK_LP_SLEW_RATE_DOWN_0     (0 << 15)
+#define MIPI_CSIS_DPHY_BCTRL_L_MSTRCLK_LP_SLEW_RATE_DOWN_15P   (1 << 15)
+#define MIPI_CSIS_DPHY_BCTRL_L_MSTRCLK_LP_SLEW_RATE_DOWN_30P   (3 << 15)
+#define MIPI_CSIS_DPHY_BCTRL_L_MSTRCLK_LP_SLEW_RATE_UP         BIT(14)
+#define MIPI_CSIS_DPHY_BCTRL_L_LP_CD_HYS_60MV                  (0 << 13)
+#define MIPI_CSIS_DPHY_BCTRL_L_LP_CD_HYS_70MV                  (1 << 13)
+#define MIPI_CSIS_DPHY_BCTRL_L_BGR_CHOPPER_EN                  BIT(12)
+#define MIPI_CSIS_DPHY_BCTRL_L_ERRCONTENTION_LP_EN             BIT(11)
+#define MIPI_CSIS_DPHY_BCTRL_L_TXTRIGGER_CLK_EN                        BIT(10)
+#define MIPI_CSIS_DPHY_BCTRL_L_B_DPHYCTRL(n)                   (((n) * 25 / 1000000) << 0)
+
+/* D-PHY Master and Slave Control register High */
+#define MIPI_CSIS_DPHY_BCTRL_H                 0x34
+/* D-PHY Slave Control register Low */
+#define MIPI_CSIS_DPHY_SCTRL_L                 0x38
+/* D-PHY Slave Control register High */
+#define MIPI_CSIS_DPHY_SCTRL_H                 0x3c
+
+/* ISP Configuration register */
+#define MIPI_CSIS_ISP_CONFIG_CH(n)             (0x40 + (n) * 0x10)
+#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP_MSK      (0xff << 24)
+#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP(x)       ((x) << 24)
+#define MIPI_CSIS_ISPCFG_PIXEL_MODE_SINGLE     (0 << 12)
+#define MIPI_CSIS_ISPCFG_PIXEL_MODE_DUAL       (1 << 12)
+#define MIPI_CSIS_ISPCFG_PIXEL_MODE_QUAD       (2 << 12)       /* i.MX8M[MNP] only */
+#define MIPI_CSIS_ISPCFG_PIXEL_MASK            (3 << 12)
+#define MIPI_CSIS_ISPCFG_ALIGN_32BIT           BIT(11)
+#define MIPI_CSIS_ISPCFG_FMT(fmt)              ((fmt) << 2)
+#define MIPI_CSIS_ISPCFG_FMT_MASK              (0x3f << 2)
+
+/* ISP Image Resolution register */
+#define MIPI_CSIS_ISP_RESOL_CH(n)              (0x44 + (n) * 0x10)
+#define CSIS_MAX_PIX_WIDTH                     0xffff
+#define CSIS_MAX_PIX_HEIGHT                    0xffff
+
+/* ISP SYNC register */
+#define MIPI_CSIS_ISP_SYNC_CH(n)               (0x48 + (n) * 0x10)
+#define MIPI_CSIS_ISP_SYNC_HSYNC_LINTV_OFFSET  18
+#define MIPI_CSIS_ISP_SYNC_VSYNC_SINTV_OFFSET  12
+#define MIPI_CSIS_ISP_SYNC_VSYNC_EINTV_OFFSET  0
+
+/* ISP shadow registers */
+#define MIPI_CSIS_SDW_CONFIG_CH(n)             (0x80 + (n) * 0x10)
+#define MIPI_CSIS_SDW_RESOL_CH(n)              (0x84 + (n) * 0x10)
+#define MIPI_CSIS_SDW_SYNC_CH(n)               (0x88 + (n) * 0x10)
+
+/* Debug control register */
+#define MIPI_CSIS_DBG_CTRL                     0xc0
+#define MIPI_CSIS_DBG_INTR_MSK                 0xc4
+#define MIPI_CSIS_DBG_INTR_MSK_DT_NOT_SUPPORT  BIT(25)
+#define MIPI_CSIS_DBG_INTR_MSK_DT_IGNORE       BIT(24)
+#define MIPI_CSIS_DBG_INTR_MSK_ERR_FRAME_SIZE  BIT(20)
+#define MIPI_CSIS_DBG_INTR_MSK_TRUNCATED_FRAME BIT(16)
+#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FE                BIT(12)
+#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FS                BIT(8)
+#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_FALL  BIT(4)
+#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_RISE  BIT(0)
+#define MIPI_CSIS_DBG_INTR_SRC                 0xc8
+#define MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT  BIT(25)
+#define MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE       BIT(24)
+#define MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE  BIT(20)
+#define MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME BIT(16)
+#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FE                BIT(12)
+#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FS                BIT(8)
+#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL  BIT(4)
+#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE  BIT(0)
+
+#define MIPI_CSIS_FRAME_COUNTER_CH(n)          (0x0100 + (n) * 4)
+
+/* Non-image packet data buffers */
+#define MIPI_CSIS_PKTDATA_ODD                  0x2000
+#define MIPI_CSIS_PKTDATA_EVEN                 0x3000
+#define MIPI_CSIS_PKTDATA_SIZE                 SZ_4K
+
+#define DEFAULT_SCLK_CSIS_FREQ                 166000000UL
+
+/* MIPI CSI-2 Data Types */
+#define MIPI_CSI2_DATA_TYPE_YUV420_8           0x18
+#define MIPI_CSI2_DATA_TYPE_YUV420_10          0x19
+#define MIPI_CSI2_DATA_TYPE_LE_YUV420_8                0x1a
+#define MIPI_CSI2_DATA_TYPE_CS_YUV420_8                0x1c
+#define MIPI_CSI2_DATA_TYPE_CS_YUV420_10       0x1d
+#define MIPI_CSI2_DATA_TYPE_YUV422_8           0x1e
+#define MIPI_CSI2_DATA_TYPE_YUV422_10          0x1f
+#define MIPI_CSI2_DATA_TYPE_RGB565             0x22
+#define MIPI_CSI2_DATA_TYPE_RGB666             0x23
+#define MIPI_CSI2_DATA_TYPE_RGB888             0x24
+#define MIPI_CSI2_DATA_TYPE_RAW6               0x28
+#define MIPI_CSI2_DATA_TYPE_RAW7               0x29
+#define MIPI_CSI2_DATA_TYPE_RAW8               0x2a
+#define MIPI_CSI2_DATA_TYPE_RAW10              0x2b
+#define MIPI_CSI2_DATA_TYPE_RAW12              0x2c
+#define MIPI_CSI2_DATA_TYPE_RAW14              0x2d
+#define MIPI_CSI2_DATA_TYPE_USER(x)            (0x30 + (x))
+
+enum {
+       ST_POWERED      = 1,
+       ST_STREAMING    = 2,
+       ST_SUSPENDED    = 4,
+};
+
+struct mipi_csis_event {
+       bool debug;
+       u32 mask;
+       const char * const name;
+       unsigned int counter;
+};
+
+static const struct mipi_csis_event mipi_csis_events[] = {
+       /* Errors */
+       { false, MIPI_CSIS_INT_SRC_ERR_SOT_HS,          "SOT Error" },
+       { false, MIPI_CSIS_INT_SRC_ERR_LOST_FS,         "Lost Frame Start Error" },
+       { false, MIPI_CSIS_INT_SRC_ERR_LOST_FE,         "Lost Frame End Error" },
+       { false, MIPI_CSIS_INT_SRC_ERR_OVER,            "FIFO Overflow Error" },
+       { false, MIPI_CSIS_INT_SRC_ERR_WRONG_CFG,       "Wrong Configuration Error" },
+       { false, MIPI_CSIS_INT_SRC_ERR_ECC,             "ECC Error" },
+       { false, MIPI_CSIS_INT_SRC_ERR_CRC,             "CRC Error" },
+       { false, MIPI_CSIS_INT_SRC_ERR_UNKNOWN,         "Unknown Error" },
+       { true, MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT,  "Data Type Not Supported" },
+       { true, MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE,       "Data Type Ignored" },
+       { true, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE,  "Frame Size Error" },
+       { true, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME, "Truncated Frame" },
+       { true, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE,        "Early Frame End" },
+       { true, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS,        "Early Frame Start" },
+       /* Non-image data receive events */
+       { false, MIPI_CSIS_INT_SRC_EVEN_BEFORE,         "Non-image data before even frame" },
+       { false, MIPI_CSIS_INT_SRC_EVEN_AFTER,          "Non-image data after even frame" },
+       { false, MIPI_CSIS_INT_SRC_ODD_BEFORE,          "Non-image data before odd frame" },
+       { false, MIPI_CSIS_INT_SRC_ODD_AFTER,           "Non-image data after odd frame" },
+       /* Frame start/end */
+       { false, MIPI_CSIS_INT_SRC_FRAME_START,         "Frame Start" },
+       { false, MIPI_CSIS_INT_SRC_FRAME_END,           "Frame End" },
+       { true, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL,  "VSYNC Falling Edge" },
+       { true, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE,  "VSYNC Rising Edge" },
+};
+
+#define MIPI_CSIS_NUM_EVENTS ARRAY_SIZE(mipi_csis_events)
+
+enum mipi_csis_clk {
+       MIPI_CSIS_CLK_PCLK,
+       MIPI_CSIS_CLK_WRAP,
+       MIPI_CSIS_CLK_PHY,
+       MIPI_CSIS_CLK_AXI,
+};
+
+static const char * const mipi_csis_clk_id[] = {
+       "pclk",
+       "wrap",
+       "phy",
+       "axi",
+};
+
+enum mipi_csis_version {
+       MIPI_CSIS_V3_3,
+       MIPI_CSIS_V3_6_3,
+};
+
+struct mipi_csis_info {
+       enum mipi_csis_version version;
+       unsigned int num_clocks;
+};
+
+struct csi_state {
+       struct device *dev;
+       void __iomem *regs;
+       struct clk_bulk_data *clks;
+       struct reset_control *mrst;
+       struct regulator *mipi_phy_regulator;
+       const struct mipi_csis_info *info;
+
+       struct v4l2_subdev sd;
+       struct media_pad pads[CSIS_PADS_NUM];
+       struct v4l2_async_notifier notifier;
+       struct v4l2_subdev *src_sd;
+
+       struct v4l2_mbus_config_mipi_csi2 bus;
+       u32 clk_frequency;
+       u32 hs_settle;
+       u32 clk_settle;
+
+       struct mutex lock;      /* Protect csis_fmt, format_mbus and state */
+       const struct csis_pix_format *csis_fmt;
+       struct v4l2_mbus_framefmt format_mbus[CSIS_PADS_NUM];
+       u32 state;
+
+       spinlock_t slock;       /* Protect events */
+       struct mipi_csis_event events[MIPI_CSIS_NUM_EVENTS];
+       struct dentry *debugfs_root;
+       struct {
+               bool enable;
+               u32 hs_settle;
+               u32 clk_settle;
+       } debug;
+};
+
+/* -----------------------------------------------------------------------------
+ * Format helpers
+ */
+
+struct csis_pix_format {
+       u32 code;
+       u32 output;
+       u32 data_type;
+       u8 width;
+};
+
+static const struct csis_pix_format mipi_csis_formats[] = {
+       /* YUV formats. */
+       {
+               .code = MEDIA_BUS_FMT_UYVY8_1X16,
+               .output = MEDIA_BUS_FMT_UYVY8_1X16,
+               .data_type = MIPI_CSI2_DATA_TYPE_YUV422_8,
+               .width = 16,
+       },
+       /* RGB formats. */
+       {
+               .code = MEDIA_BUS_FMT_RGB565_1X16,
+               .output = MEDIA_BUS_FMT_RGB565_1X16,
+               .data_type = MIPI_CSI2_DATA_TYPE_RGB565,
+               .width = 16,
+       }, {
+               .code = MEDIA_BUS_FMT_BGR888_1X24,
+               .output = MEDIA_BUS_FMT_RGB888_1X24,
+               .data_type = MIPI_CSI2_DATA_TYPE_RGB888,
+               .width = 24,
+       },
+       /* RAW (Bayer and greyscale) formats. */
+       {
+               .code = MEDIA_BUS_FMT_SBGGR8_1X8,
+               .output = MEDIA_BUS_FMT_SBGGR8_1X8,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
+               .width = 8,
+       }, {
+               .code = MEDIA_BUS_FMT_SGBRG8_1X8,
+               .output = MEDIA_BUS_FMT_SGBRG8_1X8,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
+               .width = 8,
+       }, {
+               .code = MEDIA_BUS_FMT_SGRBG8_1X8,
+               .output = MEDIA_BUS_FMT_SGRBG8_1X8,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
+               .width = 8,
+       }, {
+               .code = MEDIA_BUS_FMT_SRGGB8_1X8,
+               .output = MEDIA_BUS_FMT_SRGGB8_1X8,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
+               .width = 8,
+       }, {
+               .code = MEDIA_BUS_FMT_Y8_1X8,
+               .output = MEDIA_BUS_FMT_Y8_1X8,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
+               .width = 8,
+       }, {
+               .code = MEDIA_BUS_FMT_SBGGR10_1X10,
+               .output = MEDIA_BUS_FMT_SBGGR10_1X10,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
+               .width = 10,
+       }, {
+               .code = MEDIA_BUS_FMT_SGBRG10_1X10,
+               .output = MEDIA_BUS_FMT_SGBRG10_1X10,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
+               .width = 10,
+       }, {
+               .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+               .output = MEDIA_BUS_FMT_SGRBG10_1X10,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
+               .width = 10,
+       }, {
+               .code = MEDIA_BUS_FMT_SRGGB10_1X10,
+               .output = MEDIA_BUS_FMT_SRGGB10_1X10,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
+               .width = 10,
+       }, {
+               .code = MEDIA_BUS_FMT_Y10_1X10,
+               .output = MEDIA_BUS_FMT_Y10_1X10,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
+               .width = 10,
+       }, {
+               .code = MEDIA_BUS_FMT_SBGGR12_1X12,
+               .output = MEDIA_BUS_FMT_SBGGR12_1X12,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
+               .width = 12,
+       }, {
+               .code = MEDIA_BUS_FMT_SGBRG12_1X12,
+               .output = MEDIA_BUS_FMT_SGBRG12_1X12,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
+               .width = 12,
+       }, {
+               .code = MEDIA_BUS_FMT_SGRBG12_1X12,
+               .output = MEDIA_BUS_FMT_SGRBG12_1X12,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
+               .width = 12,
+       }, {
+               .code = MEDIA_BUS_FMT_SRGGB12_1X12,
+               .output = MEDIA_BUS_FMT_SRGGB12_1X12,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
+               .width = 12,
+       }, {
+               .code = MEDIA_BUS_FMT_Y12_1X12,
+               .output = MEDIA_BUS_FMT_Y12_1X12,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
+               .width = 12,
+       }, {
+               .code = MEDIA_BUS_FMT_SBGGR14_1X14,
+               .output = MEDIA_BUS_FMT_SBGGR14_1X14,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
+               .width = 14,
+       }, {
+               .code = MEDIA_BUS_FMT_SGBRG14_1X14,
+               .output = MEDIA_BUS_FMT_SGBRG14_1X14,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
+               .width = 14,
+       }, {
+               .code = MEDIA_BUS_FMT_SGRBG14_1X14,
+               .output = MEDIA_BUS_FMT_SGRBG14_1X14,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
+               .width = 14,
+       }, {
+               .code = MEDIA_BUS_FMT_SRGGB14_1X14,
+               .output = MEDIA_BUS_FMT_SRGGB14_1X14,
+               .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
+               .width = 14,
+       }
+};
+
+static const struct csis_pix_format *find_csis_format(u32 code)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(mipi_csis_formats); i++)
+               if (code == mipi_csis_formats[i].code)
+                       return &mipi_csis_formats[i];
+       return NULL;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hardware configuration
+ */
+
+static inline u32 mipi_csis_read(struct csi_state *state, u32 reg)
+{
+       return readl(state->regs + reg);
+}
+
+static inline void mipi_csis_write(struct csi_state *state, u32 reg, u32 val)
+{
+       writel(val, state->regs + reg);
+}
+
+static void mipi_csis_enable_interrupts(struct csi_state *state, bool on)
+{
+       mipi_csis_write(state, MIPI_CSIS_INT_MSK, on ? 0xffffffff : 0);
+       mipi_csis_write(state, MIPI_CSIS_DBG_INTR_MSK, on ? 0xffffffff : 0);
+}
+
+static void mipi_csis_sw_reset(struct csi_state *state)
+{
+       u32 val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
+
+       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL,
+                       val | MIPI_CSIS_CMN_CTRL_RESET);
+       usleep_range(10, 20);
+}
+
+static void mipi_csis_system_enable(struct csi_state *state, int on)
+{
+       u32 val, mask;
+
+       val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
+       if (on)
+               val |= MIPI_CSIS_CMN_CTRL_ENABLE;
+       else
+               val &= ~MIPI_CSIS_CMN_CTRL_ENABLE;
+       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
+
+       val = mipi_csis_read(state, MIPI_CSIS_DPHY_CMN_CTRL);
+       val &= ~MIPI_CSIS_DPHY_CMN_CTRL_ENABLE;
+       if (on) {
+               mask = (1 << (state->bus.num_data_lanes + 1)) - 1;
+               val |= (mask & MIPI_CSIS_DPHY_CMN_CTRL_ENABLE);
+       }
+       mipi_csis_write(state, MIPI_CSIS_DPHY_CMN_CTRL, val);
+}
+
+/* Called with the state.lock mutex held */
+static void __mipi_csis_set_format(struct csi_state *state)
+{
+       struct v4l2_mbus_framefmt *mf = &state->format_mbus[CSIS_PAD_SINK];
+       u32 val;
+
+       /* Color format */
+       val = mipi_csis_read(state, MIPI_CSIS_ISP_CONFIG_CH(0));
+       val &= ~(MIPI_CSIS_ISPCFG_ALIGN_32BIT | MIPI_CSIS_ISPCFG_FMT_MASK
+               | MIPI_CSIS_ISPCFG_PIXEL_MASK);
+
+       /*
+        * YUV 4:2:2 can be transferred with 8 or 16 bits per clock sample
+        * (referred to in the documentation as single and dual pixel modes
+        * respectively, although the 8-bit mode transfers half a pixel per
+        * clock sample and the 16-bit mode one pixel). While both mode work
+        * when the CSIS is connected to a receiver that supports either option,
+        * single pixel mode requires clock rates twice as high. As all SoCs
+        * that integrate the CSIS can operate in 16-bit bit mode, and some do
+        * not support 8-bit mode (this is the case of the i.MX8MP), use dual
+        * pixel mode unconditionally.
+        *
+        * TODO: Verify which other formats require DUAL (or QUAD) modes.
+        */
+       if (state->csis_fmt->data_type == MIPI_CSI2_DATA_TYPE_YUV422_8)
+               val |= MIPI_CSIS_ISPCFG_PIXEL_MODE_DUAL;
+
+       val |= MIPI_CSIS_ISPCFG_FMT(state->csis_fmt->data_type);
+       mipi_csis_write(state, MIPI_CSIS_ISP_CONFIG_CH(0), val);
+
+       /* Pixel resolution */
+       val = mf->width | (mf->height << 16);
+       mipi_csis_write(state, MIPI_CSIS_ISP_RESOL_CH(0), val);
+}
+
+static int mipi_csis_calculate_params(struct csi_state *state)
+{
+       s64 link_freq;
+       u32 lane_rate;
+
+       /* Calculate the line rate from the pixel rate. */
+       link_freq = v4l2_get_link_freq(state->src_sd->ctrl_handler,
+                                      state->csis_fmt->width,
+                                      state->bus.num_data_lanes * 2);
+       if (link_freq < 0) {
+               dev_err(state->dev, "Unable to obtain link frequency: %d\n",
+                       (int)link_freq);
+               return link_freq;
+       }
+
+       lane_rate = link_freq * 2;
+
+       if (lane_rate < 80000000 || lane_rate > 1500000000) {
+               dev_dbg(state->dev, "Out-of-bound lane rate %u\n", lane_rate);
+               return -EINVAL;
+       }
+
+       /*
+        * The HSSETTLE counter value is document in a table, but can also
+        * easily be calculated. Hardcode the CLKSETTLE value to 0 for now
+        * (which is documented as corresponding to CSI-2 v0.87 to v1.00) until
+        * we figure out how to compute it correctly.
+        */
+       state->hs_settle = (lane_rate - 5000000) / 45000000;
+       state->clk_settle = 0;
+
+       dev_dbg(state->dev, "lane rate %u, Tclk_settle %u, Ths_settle %u\n",
+               lane_rate, state->clk_settle, state->hs_settle);
+
+       if (state->debug.hs_settle < 0xff) {
+               dev_dbg(state->dev, "overriding Ths_settle with %u\n",
+                       state->debug.hs_settle);
+               state->hs_settle = state->debug.hs_settle;
+       }
+
+       if (state->debug.clk_settle < 4) {
+               dev_dbg(state->dev, "overriding Tclk_settle with %u\n",
+                       state->debug.clk_settle);
+               state->clk_settle = state->debug.clk_settle;
+       }
+
+       return 0;
+}
+
+static void mipi_csis_set_params(struct csi_state *state)
+{
+       int lanes = state->bus.num_data_lanes;
+       u32 val;
+
+       val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
+       val &= ~MIPI_CSIS_CMN_CTRL_LANE_NR_MASK;
+       val |= (lanes - 1) << MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET;
+       if (state->info->version == MIPI_CSIS_V3_3)
+               val |= MIPI_CSIS_CMN_CTRL_INTER_MODE;
+       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
+
+       __mipi_csis_set_format(state);
+
+       mipi_csis_write(state, MIPI_CSIS_DPHY_CMN_CTRL,
+                       MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(state->hs_settle) |
+                       MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(state->clk_settle));
+
+       val = (0 << MIPI_CSIS_ISP_SYNC_HSYNC_LINTV_OFFSET)
+           | (0 << MIPI_CSIS_ISP_SYNC_VSYNC_SINTV_OFFSET)
+           | (0 << MIPI_CSIS_ISP_SYNC_VSYNC_EINTV_OFFSET);
+       mipi_csis_write(state, MIPI_CSIS_ISP_SYNC_CH(0), val);
+
+       val = mipi_csis_read(state, MIPI_CSIS_CLK_CTRL);
+       val |= MIPI_CSIS_CLK_CTRL_WCLK_SRC;
+       val |= MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(15);
+       val &= ~MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK;
+       mipi_csis_write(state, MIPI_CSIS_CLK_CTRL, val);
+
+       mipi_csis_write(state, MIPI_CSIS_DPHY_BCTRL_L,
+                       MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_715MV |
+                       MIPI_CSIS_DPHY_BCTRL_L_BGR_CHOPPER_FREQ_3MHZ |
+                       MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_2V |
+                       MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_80MV |
+                       MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_715MV |
+                       MIPI_CSIS_DPHY_BCTRL_L_LP_CD_HYS_60MV |
+                       MIPI_CSIS_DPHY_BCTRL_L_B_DPHYCTRL(20000000));
+       mipi_csis_write(state, MIPI_CSIS_DPHY_BCTRL_H, 0);
+
+       /* Update the shadow register. */
+       val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
+       mipi_csis_write(state, MIPI_CSIS_CMN_CTRL,
+                       val | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW |
+                       MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL);
+}
+
+static int mipi_csis_clk_enable(struct csi_state *state)
+{
+       return clk_bulk_prepare_enable(state->info->num_clocks, state->clks);
+}
+
+static void mipi_csis_clk_disable(struct csi_state *state)
+{
+       clk_bulk_disable_unprepare(state->info->num_clocks, state->clks);
+}
+
+static int mipi_csis_clk_get(struct csi_state *state)
+{
+       unsigned int i;
+       int ret;
+
+       state->clks = devm_kcalloc(state->dev, state->info->num_clocks,
+                                  sizeof(*state->clks), GFP_KERNEL);
+
+       if (!state->clks)
+               return -ENOMEM;
+
+       for (i = 0; i < state->info->num_clocks; i++)
+               state->clks[i].id = mipi_csis_clk_id[i];
+
+       ret = devm_clk_bulk_get(state->dev, state->info->num_clocks,
+                               state->clks);
+       if (ret < 0)
+               return ret;
+
+       /* Set clock rate */
+       ret = clk_set_rate(state->clks[MIPI_CSIS_CLK_WRAP].clk,
+                          state->clk_frequency);
+       if (ret < 0)
+               dev_err(state->dev, "set rate=%d failed: %d\n",
+                       state->clk_frequency, ret);
+
+       return ret;
+}
+
+static void mipi_csis_start_stream(struct csi_state *state)
+{
+       mipi_csis_sw_reset(state);
+       mipi_csis_set_params(state);
+       mipi_csis_system_enable(state, true);
+       mipi_csis_enable_interrupts(state, true);
+}
+
+static void mipi_csis_stop_stream(struct csi_state *state)
+{
+       mipi_csis_enable_interrupts(state, false);
+       mipi_csis_system_enable(state, false);
+}
+
+static irqreturn_t mipi_csis_irq_handler(int irq, void *dev_id)
+{
+       struct csi_state *state = dev_id;
+       unsigned long flags;
+       unsigned int i;
+       u32 status;
+       u32 dbg_status;
+
+       status = mipi_csis_read(state, MIPI_CSIS_INT_SRC);
+       dbg_status = mipi_csis_read(state, MIPI_CSIS_DBG_INTR_SRC);
+
+       spin_lock_irqsave(&state->slock, flags);
+
+       /* Update the event/error counters */
+       if ((status & MIPI_CSIS_INT_SRC_ERRORS) || state->debug.enable) {
+               for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++) {
+                       struct mipi_csis_event *event = &state->events[i];
+
+                       if ((!event->debug && (status & event->mask)) ||
+                           (event->debug && (dbg_status & event->mask)))
+                               event->counter++;
+               }
+       }
+       spin_unlock_irqrestore(&state->slock, flags);
+
+       mipi_csis_write(state, MIPI_CSIS_INT_SRC, status);
+       mipi_csis_write(state, MIPI_CSIS_DBG_INTR_SRC, dbg_status);
+
+       return IRQ_HANDLED;
+}
+
+/* -----------------------------------------------------------------------------
+ * PHY regulator and reset
+ */
+
+static int mipi_csis_phy_enable(struct csi_state *state)
+{
+       if (state->info->version != MIPI_CSIS_V3_3)
+               return 0;
+
+       return regulator_enable(state->mipi_phy_regulator);
+}
+
+static int mipi_csis_phy_disable(struct csi_state *state)
+{
+       if (state->info->version != MIPI_CSIS_V3_3)
+               return 0;
+
+       return regulator_disable(state->mipi_phy_regulator);
+}
+
+static void mipi_csis_phy_reset(struct csi_state *state)
+{
+       if (state->info->version != MIPI_CSIS_V3_3)
+               return;
+
+       reset_control_assert(state->mrst);
+       msleep(20);
+       reset_control_deassert(state->mrst);
+}
+
+static int mipi_csis_phy_init(struct csi_state *state)
+{
+       if (state->info->version != MIPI_CSIS_V3_3)
+               return 0;
+
+       /* Get MIPI PHY reset and regulator. */
+       state->mrst = devm_reset_control_get_exclusive(state->dev, NULL);
+       if (IS_ERR(state->mrst))
+               return PTR_ERR(state->mrst);
+
+       state->mipi_phy_regulator = devm_regulator_get(state->dev, "phy");
+       if (IS_ERR(state->mipi_phy_regulator))
+               return PTR_ERR(state->mipi_phy_regulator);
+
+       return regulator_set_voltage(state->mipi_phy_regulator, 1000000,
+                                    1000000);
+}
+
+/* -----------------------------------------------------------------------------
+ * Debug
+ */
+
+static void mipi_csis_clear_counters(struct csi_state *state)
+{
+       unsigned long flags;
+       unsigned int i;
+
+       spin_lock_irqsave(&state->slock, flags);
+       for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++)
+               state->events[i].counter = 0;
+       spin_unlock_irqrestore(&state->slock, flags);
+}
+
+static void mipi_csis_log_counters(struct csi_state *state, bool non_errors)
+{
+       unsigned int num_events = non_errors ? MIPI_CSIS_NUM_EVENTS
+                               : MIPI_CSIS_NUM_EVENTS - 8;
+       unsigned long flags;
+       unsigned int i;
+
+       spin_lock_irqsave(&state->slock, flags);
+
+       for (i = 0; i < num_events; ++i) {
+               if (state->events[i].counter > 0 || state->debug.enable)
+                       dev_info(state->dev, "%s events: %d\n",
+                                state->events[i].name,
+                                state->events[i].counter);
+       }
+       spin_unlock_irqrestore(&state->slock, flags);
+}
+
+static int mipi_csis_dump_regs(struct csi_state *state)
+{
+       static const struct {
+               u32 offset;
+               const char * const name;
+       } registers[] = {
+               { MIPI_CSIS_CMN_CTRL, "CMN_CTRL" },
+               { MIPI_CSIS_CLK_CTRL, "CLK_CTRL" },
+               { MIPI_CSIS_INT_MSK, "INT_MSK" },
+               { MIPI_CSIS_DPHY_STATUS, "DPHY_STATUS" },
+               { MIPI_CSIS_DPHY_CMN_CTRL, "DPHY_CMN_CTRL" },
+               { MIPI_CSIS_DPHY_SCTRL_L, "DPHY_SCTRL_L" },
+               { MIPI_CSIS_DPHY_SCTRL_H, "DPHY_SCTRL_H" },
+               { MIPI_CSIS_ISP_CONFIG_CH(0), "ISP_CONFIG_CH0" },
+               { MIPI_CSIS_ISP_RESOL_CH(0), "ISP_RESOL_CH0" },
+               { MIPI_CSIS_SDW_CONFIG_CH(0), "SDW_CONFIG_CH0" },
+               { MIPI_CSIS_SDW_RESOL_CH(0), "SDW_RESOL_CH0" },
+               { MIPI_CSIS_DBG_CTRL, "DBG_CTRL" },
+               { MIPI_CSIS_FRAME_COUNTER_CH(0), "FRAME_COUNTER_CH0" },
+       };
+
+       unsigned int i;
+       u32 cfg;
+
+       dev_info(state->dev, "--- REGISTERS ---\n");
+
+       for (i = 0; i < ARRAY_SIZE(registers); i++) {
+               cfg = mipi_csis_read(state, registers[i].offset);
+               dev_info(state->dev, "%14s: 0x%08x\n", registers[i].name, cfg);
+       }
+
+       return 0;
+}
+
+static int mipi_csis_dump_regs_show(struct seq_file *m, void *private)
+{
+       struct csi_state *state = m->private;
+
+       return mipi_csis_dump_regs(state);
+}
+DEFINE_SHOW_ATTRIBUTE(mipi_csis_dump_regs);
+
+static void mipi_csis_debugfs_init(struct csi_state *state)
+{
+       state->debug.hs_settle = UINT_MAX;
+       state->debug.clk_settle = UINT_MAX;
+
+       state->debugfs_root = debugfs_create_dir(dev_name(state->dev), NULL);
+
+       debugfs_create_bool("debug_enable", 0600, state->debugfs_root,
+                           &state->debug.enable);
+       debugfs_create_file("dump_regs", 0600, state->debugfs_root, state,
+                           &mipi_csis_dump_regs_fops);
+       debugfs_create_u32("tclk_settle", 0600, state->debugfs_root,
+                          &state->debug.clk_settle);
+       debugfs_create_u32("ths_settle", 0600, state->debugfs_root,
+                          &state->debug.hs_settle);
+}
+
+static void mipi_csis_debugfs_exit(struct csi_state *state)
+{
+       debugfs_remove_recursive(state->debugfs_root);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+static struct csi_state *mipi_sd_to_csis_state(struct v4l2_subdev *sdev)
+{
+       return container_of(sdev, struct csi_state, sd);
+}
+
+static int mipi_csis_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct csi_state *state = mipi_sd_to_csis_state(sd);
+       int ret;
+
+       if (enable) {
+               ret = mipi_csis_calculate_params(state);
+               if (ret < 0)
+                       return ret;
+
+               mipi_csis_clear_counters(state);
+
+               ret = pm_runtime_resume_and_get(state->dev);
+               if (ret < 0)
+                       return ret;
+
+               ret = v4l2_subdev_call(state->src_sd, core, s_power, 1);
+               if (ret < 0 && ret != -ENOIOCTLCMD)
+                       goto done;
+       }
+
+       mutex_lock(&state->lock);
+
+       if (enable) {
+               if (state->state & ST_SUSPENDED) {
+                       ret = -EBUSY;
+                       goto unlock;
+               }
+
+               mipi_csis_start_stream(state);
+               ret = v4l2_subdev_call(state->src_sd, video, s_stream, 1);
+               if (ret < 0)
+                       goto unlock;
+
+               mipi_csis_log_counters(state, true);
+
+               state->state |= ST_STREAMING;
+       } else {
+               v4l2_subdev_call(state->src_sd, video, s_stream, 0);
+               ret = v4l2_subdev_call(state->src_sd, core, s_power, 0);
+               if (ret == -ENOIOCTLCMD)
+                       ret = 0;
+               mipi_csis_stop_stream(state);
+               state->state &= ~ST_STREAMING;
+               if (state->debug.enable)
+                       mipi_csis_log_counters(state, true);
+       }
+
+unlock:
+       mutex_unlock(&state->lock);
+
+done:
+       if (!enable || ret < 0)
+               pm_runtime_put(state->dev);
+
+       return ret;
+}
+
+static struct v4l2_mbus_framefmt *
+mipi_csis_get_format(struct csi_state *state,
+                    struct v4l2_subdev_state *sd_state,
+                    enum v4l2_subdev_format_whence which,
+                    unsigned int pad)
+{
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_format(&state->sd, sd_state, pad);
+
+       return &state->format_mbus[pad];
+}
+
+static int mipi_csis_init_cfg(struct v4l2_subdev *sd,
+                             struct v4l2_subdev_state *sd_state)
+{
+       struct csi_state *state = mipi_sd_to_csis_state(sd);
+       struct v4l2_mbus_framefmt *fmt_sink;
+       struct v4l2_mbus_framefmt *fmt_source;
+       enum v4l2_subdev_format_whence which;
+
+       which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       fmt_sink = mipi_csis_get_format(state, sd_state, which, CSIS_PAD_SINK);
+
+       fmt_sink->code = MEDIA_BUS_FMT_UYVY8_1X16;
+       fmt_sink->width = MIPI_CSIS_DEF_PIX_WIDTH;
+       fmt_sink->height = MIPI_CSIS_DEF_PIX_HEIGHT;
+       fmt_sink->field = V4L2_FIELD_NONE;
+
+       fmt_sink->colorspace = V4L2_COLORSPACE_SMPTE170M;
+       fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace);
+       fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace);
+       fmt_sink->quantization =
+               V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace,
+                                             fmt_sink->ycbcr_enc);
+
+       /*
+        * When called from mipi_csis_subdev_init() to initialize the active
+        * configuration, cfg is NULL, which indicates there's no source pad
+        * configuration to set.
+        */
+       if (!sd_state)
+               return 0;
+
+       fmt_source = mipi_csis_get_format(state, sd_state, which,
+                                         CSIS_PAD_SOURCE);
+       *fmt_source = *fmt_sink;
+
+       return 0;
+}
+
+static int mipi_csis_get_fmt(struct v4l2_subdev *sd,
+                            struct v4l2_subdev_state *sd_state,
+                            struct v4l2_subdev_format *sdformat)
+{
+       struct csi_state *state = mipi_sd_to_csis_state(sd);
+       struct v4l2_mbus_framefmt *fmt;
+
+       fmt = mipi_csis_get_format(state, sd_state, sdformat->which,
+                                  sdformat->pad);
+
+       mutex_lock(&state->lock);
+       sdformat->format = *fmt;
+       mutex_unlock(&state->lock);
+
+       return 0;
+}
+
+static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd,
+                                   struct v4l2_subdev_state *sd_state,
+                                   struct v4l2_subdev_mbus_code_enum *code)
+{
+       struct csi_state *state = mipi_sd_to_csis_state(sd);
+
+       /*
+        * The CSIS can't transcode in any way, the source format is identical
+        * to the sink format.
+        */
+       if (code->pad == CSIS_PAD_SOURCE) {
+               struct v4l2_mbus_framefmt *fmt;
+
+               if (code->index > 0)
+                       return -EINVAL;
+
+               fmt = mipi_csis_get_format(state, sd_state, code->which,
+                                          code->pad);
+               code->code = fmt->code;
+               return 0;
+       }
+
+       if (code->pad != CSIS_PAD_SINK)
+               return -EINVAL;
+
+       if (code->index >= ARRAY_SIZE(mipi_csis_formats))
+               return -EINVAL;
+
+       code->code = mipi_csis_formats[code->index].code;
+
+       return 0;
+}
+
+static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
+                            struct v4l2_subdev_state *sd_state,
+                            struct v4l2_subdev_format *sdformat)
+{
+       struct csi_state *state = mipi_sd_to_csis_state(sd);
+       struct csis_pix_format const *csis_fmt;
+       struct v4l2_mbus_framefmt *fmt;
+       unsigned int align;
+
+       /*
+        * The CSIS can't transcode in any way, the source format can't be
+        * modified.
+        */
+       if (sdformat->pad == CSIS_PAD_SOURCE)
+               return mipi_csis_get_fmt(sd, sd_state, sdformat);
+
+       if (sdformat->pad != CSIS_PAD_SINK)
+               return -EINVAL;
+
+       /*
+        * Validate the media bus code and clamp and align the size.
+        *
+        * The total number of bits per line must be a multiple of 8. We thus
+        * need to align the width for formats that are not multiples of 8
+        * bits.
+        */
+       csis_fmt = find_csis_format(sdformat->format.code);
+       if (!csis_fmt)
+               csis_fmt = &mipi_csis_formats[0];
+
+       switch (csis_fmt->width % 8) {
+       case 0:
+               align = 0;
+               break;
+       case 4:
+               align = 1;
+               break;
+       case 2:
+       case 6:
+               align = 2;
+               break;
+       default:
+               /* 1, 3, 5, 7 */
+               align = 3;
+               break;
+       }
+
+       v4l_bound_align_image(&sdformat->format.width, 1,
+                             CSIS_MAX_PIX_WIDTH, align,
+                             &sdformat->format.height, 1,
+                             CSIS_MAX_PIX_HEIGHT, 0, 0);
+
+       fmt = mipi_csis_get_format(state, sd_state, sdformat->which,
+                                  sdformat->pad);
+
+       mutex_lock(&state->lock);
+
+       fmt->code = csis_fmt->code;
+       fmt->width = sdformat->format.width;
+       fmt->height = sdformat->format.height;
+       fmt->colorspace = sdformat->format.colorspace;
+       fmt->quantization = sdformat->format.quantization;
+       fmt->xfer_func = sdformat->format.xfer_func;
+       fmt->ycbcr_enc = sdformat->format.ycbcr_enc;
+
+       sdformat->format = *fmt;
+
+       /* Propagate the format from sink to source. */
+       fmt = mipi_csis_get_format(state, sd_state, sdformat->which,
+                                  CSIS_PAD_SOURCE);
+       *fmt = sdformat->format;
+
+       /* The format on the source pad might change due to unpacking. */
+       fmt->code = csis_fmt->output;
+
+       /* Store the CSIS format descriptor for active formats. */
+       if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+               state->csis_fmt = csis_fmt;
+
+       mutex_unlock(&state->lock);
+
+       return 0;
+}
+
+static int mipi_csis_log_status(struct v4l2_subdev *sd)
+{
+       struct csi_state *state = mipi_sd_to_csis_state(sd);
+
+       mutex_lock(&state->lock);
+       mipi_csis_log_counters(state, true);
+       if (state->debug.enable && (state->state & ST_POWERED))
+               mipi_csis_dump_regs(state);
+       mutex_unlock(&state->lock);
+
+       return 0;
+}
+
+static const struct v4l2_subdev_core_ops mipi_csis_core_ops = {
+       .log_status     = mipi_csis_log_status,
+};
+
+static const struct v4l2_subdev_video_ops mipi_csis_video_ops = {
+       .s_stream       = mipi_csis_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops mipi_csis_pad_ops = {
+       .init_cfg               = mipi_csis_init_cfg,
+       .enum_mbus_code         = mipi_csis_enum_mbus_code,
+       .get_fmt                = mipi_csis_get_fmt,
+       .set_fmt                = mipi_csis_set_fmt,
+};
+
+static const struct v4l2_subdev_ops mipi_csis_subdev_ops = {
+       .core   = &mipi_csis_core_ops,
+       .video  = &mipi_csis_video_ops,
+       .pad    = &mipi_csis_pad_ops,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+static int mipi_csis_link_setup(struct media_entity *entity,
+                               const struct media_pad *local_pad,
+                               const struct media_pad *remote_pad, u32 flags)
+{
+       struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+       struct csi_state *state = mipi_sd_to_csis_state(sd);
+       struct v4l2_subdev *remote_sd;
+
+       dev_dbg(state->dev, "link setup %s -> %s", remote_pad->entity->name,
+               local_pad->entity->name);
+
+       /* We only care about the link to the source. */
+       if (!(local_pad->flags & MEDIA_PAD_FL_SINK))
+               return 0;
+
+       remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
+       if (flags & MEDIA_LNK_FL_ENABLED) {
+               if (state->src_sd)
+                       return -EBUSY;
+
+               state->src_sd = remote_sd;
+       } else {
+               state->src_sd = NULL;
+       }
+
+       return 0;
+}
+
+static const struct media_entity_operations mipi_csis_entity_ops = {
+       .link_setup     = mipi_csis_link_setup,
+       .link_validate  = v4l2_subdev_link_validate,
+       .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
+};
+
+/* -----------------------------------------------------------------------------
+ * Async subdev notifier
+ */
+
+static struct csi_state *
+mipi_notifier_to_csis_state(struct v4l2_async_notifier *n)
+{
+       return container_of(n, struct csi_state, notifier);
+}
+
+static int mipi_csis_notify_bound(struct v4l2_async_notifier *notifier,
+                                 struct v4l2_subdev *sd,
+                                 struct v4l2_async_subdev *asd)
+{
+       struct csi_state *state = mipi_notifier_to_csis_state(notifier);
+       struct media_pad *sink = &state->sd.entity.pads[CSIS_PAD_SINK];
+
+       return v4l2_create_fwnode_links_to_pad(sd, sink, 0);
+}
+
+static const struct v4l2_async_notifier_operations mipi_csis_notify_ops = {
+       .bound = mipi_csis_notify_bound,
+};
+
+static int mipi_csis_async_register(struct csi_state *state)
+{
+       struct v4l2_fwnode_endpoint vep = {
+               .bus_type = V4L2_MBUS_CSI2_DPHY,
+       };
+       struct v4l2_async_subdev *asd;
+       struct fwnode_handle *ep;
+       unsigned int i;
+       int ret;
+
+       v4l2_async_nf_init(&state->notifier);
+
+       ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0,
+                                            FWNODE_GRAPH_ENDPOINT_NEXT);
+       if (!ep)
+               return -ENOTCONN;
+
+       ret = v4l2_fwnode_endpoint_parse(ep, &vep);
+       if (ret)
+               goto err_parse;
+
+       for (i = 0; i < vep.bus.mipi_csi2.num_data_lanes; ++i) {
+               if (vep.bus.mipi_csi2.data_lanes[i] != i + 1) {
+                       dev_err(state->dev,
+                               "data lanes reordering is not supported");
+                       ret = -EINVAL;
+                       goto err_parse;
+               }
+       }
+
+       state->bus = vep.bus.mipi_csi2;
+
+       dev_dbg(state->dev, "data lanes: %d\n", state->bus.num_data_lanes);
+       dev_dbg(state->dev, "flags: 0x%08x\n", state->bus.flags);
+
+       asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep,
+                                             struct v4l2_async_subdev);
+       if (IS_ERR(asd)) {
+               ret = PTR_ERR(asd);
+               goto err_parse;
+       }
+
+       fwnode_handle_put(ep);
+
+       state->notifier.ops = &mipi_csis_notify_ops;
+
+       ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier);
+       if (ret)
+               return ret;
+
+       return v4l2_async_register_subdev(&state->sd);
+
+err_parse:
+       fwnode_handle_put(ep);
+
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Suspend/resume
+ */
+
+static int mipi_csis_pm_suspend(struct device *dev, bool runtime)
+{
+       struct v4l2_subdev *sd = dev_get_drvdata(dev);
+       struct csi_state *state = mipi_sd_to_csis_state(sd);
+       int ret = 0;
+
+       mutex_lock(&state->lock);
+       if (state->state & ST_POWERED) {
+               mipi_csis_stop_stream(state);
+               ret = mipi_csis_phy_disable(state);
+               if (ret)
+                       goto unlock;
+               mipi_csis_clk_disable(state);
+               state->state &= ~ST_POWERED;
+               if (!runtime)
+                       state->state |= ST_SUSPENDED;
+       }
+
+unlock:
+       mutex_unlock(&state->lock);
+
+       return ret ? -EAGAIN : 0;
+}
+
+static int mipi_csis_pm_resume(struct device *dev, bool runtime)
+{
+       struct v4l2_subdev *sd = dev_get_drvdata(dev);
+       struct csi_state *state = mipi_sd_to_csis_state(sd);
+       int ret = 0;
+
+       mutex_lock(&state->lock);
+       if (!runtime && !(state->state & ST_SUSPENDED))
+               goto unlock;
+
+       if (!(state->state & ST_POWERED)) {
+               ret = mipi_csis_phy_enable(state);
+               if (ret)
+                       goto unlock;
+
+               state->state |= ST_POWERED;
+               mipi_csis_clk_enable(state);
+       }
+       if (state->state & ST_STREAMING)
+               mipi_csis_start_stream(state);
+
+       state->state &= ~ST_SUSPENDED;
+
+unlock:
+       mutex_unlock(&state->lock);
+
+       return ret ? -EAGAIN : 0;
+}
+
+static int __maybe_unused mipi_csis_suspend(struct device *dev)
+{
+       return mipi_csis_pm_suspend(dev, false);
+}
+
+static int __maybe_unused mipi_csis_resume(struct device *dev)
+{
+       return mipi_csis_pm_resume(dev, false);
+}
+
+static int __maybe_unused mipi_csis_runtime_suspend(struct device *dev)
+{
+       return mipi_csis_pm_suspend(dev, true);
+}
+
+static int __maybe_unused mipi_csis_runtime_resume(struct device *dev)
+{
+       return mipi_csis_pm_resume(dev, true);
+}
+
+static const struct dev_pm_ops mipi_csis_pm_ops = {
+       SET_RUNTIME_PM_OPS(mipi_csis_runtime_suspend, mipi_csis_runtime_resume,
+                          NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(mipi_csis_suspend, mipi_csis_resume)
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe/remove & platform driver
+ */
+
+static int mipi_csis_subdev_init(struct csi_state *state)
+{
+       struct v4l2_subdev *sd = &state->sd;
+
+       v4l2_subdev_init(sd, &mipi_csis_subdev_ops);
+       sd->owner = THIS_MODULE;
+       snprintf(sd->name, sizeof(sd->name), "csis-%s",
+                dev_name(state->dev));
+
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+       sd->ctrl_handler = NULL;
+
+       sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+       sd->entity.ops = &mipi_csis_entity_ops;
+
+       sd->dev = state->dev;
+
+       state->csis_fmt = &mipi_csis_formats[0];
+       mipi_csis_init_cfg(sd, NULL);
+
+       state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK
+                                        | MEDIA_PAD_FL_MUST_CONNECT;
+       state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
+                                          | MEDIA_PAD_FL_MUST_CONNECT;
+       return media_entity_pads_init(&sd->entity, CSIS_PADS_NUM,
+                                     state->pads);
+}
+
+static int mipi_csis_parse_dt(struct csi_state *state)
+{
+       struct device_node *node = state->dev->of_node;
+
+       if (of_property_read_u32(node, "clock-frequency",
+                                &state->clk_frequency))
+               state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
+
+       return 0;
+}
+
+static int mipi_csis_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct csi_state *state;
+       int irq;
+       int ret;
+
+       state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+       if (!state)
+               return -ENOMEM;
+
+       mutex_init(&state->lock);
+       spin_lock_init(&state->slock);
+
+       state->dev = dev;
+       state->info = of_device_get_match_data(dev);
+
+       memcpy(state->events, mipi_csis_events, sizeof(state->events));
+
+       /* Parse DT properties. */
+       ret = mipi_csis_parse_dt(state);
+       if (ret < 0) {
+               dev_err(dev, "Failed to parse device tree: %d\n", ret);
+               return ret;
+       }
+
+       /* Acquire resources. */
+       state->regs = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(state->regs))
+               return PTR_ERR(state->regs);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       ret = mipi_csis_phy_init(state);
+       if (ret < 0)
+               return ret;
+
+       ret = mipi_csis_clk_get(state);
+       if (ret < 0)
+               return ret;
+
+       /* Reset PHY and enable the clocks. */
+       mipi_csis_phy_reset(state);
+
+       ret = mipi_csis_clk_enable(state);
+       if (ret < 0) {
+               dev_err(state->dev, "failed to enable clocks: %d\n", ret);
+               return ret;
+       }
+
+       /* Now that the hardware is initialized, request the interrupt. */
+       ret = devm_request_irq(dev, irq, mipi_csis_irq_handler, 0,
+                              dev_name(dev), state);
+       if (ret) {
+               dev_err(dev, "Interrupt request failed\n");
+               goto disable_clock;
+       }
+
+       /* Initialize and register the subdev. */
+       ret = mipi_csis_subdev_init(state);
+       if (ret < 0)
+               goto disable_clock;
+
+       platform_set_drvdata(pdev, &state->sd);
+
+       ret = mipi_csis_async_register(state);
+       if (ret < 0) {
+               dev_err(dev, "async register failed: %d\n", ret);
+               goto cleanup;
+       }
+
+       /* Initialize debugfs. */
+       mipi_csis_debugfs_init(state);
+
+       /* Enable runtime PM. */
+       pm_runtime_enable(dev);
+       if (!pm_runtime_enabled(dev)) {
+               ret = mipi_csis_pm_resume(dev, true);
+               if (ret < 0)
+                       goto unregister_all;
+       }
+
+       dev_info(dev, "lanes: %d, freq: %u\n",
+                state->bus.num_data_lanes, state->clk_frequency);
+
+       return 0;
+
+unregister_all:
+       mipi_csis_debugfs_exit(state);
+cleanup:
+       media_entity_cleanup(&state->sd.entity);
+       v4l2_async_nf_unregister(&state->notifier);
+       v4l2_async_nf_cleanup(&state->notifier);
+       v4l2_async_unregister_subdev(&state->sd);
+disable_clock:
+       mipi_csis_clk_disable(state);
+       mutex_destroy(&state->lock);
+
+       return ret;
+}
+
+static int mipi_csis_remove(struct platform_device *pdev)
+{
+       struct v4l2_subdev *sd = platform_get_drvdata(pdev);
+       struct csi_state *state = mipi_sd_to_csis_state(sd);
+
+       mipi_csis_debugfs_exit(state);
+       v4l2_async_nf_unregister(&state->notifier);
+       v4l2_async_nf_cleanup(&state->notifier);
+       v4l2_async_unregister_subdev(&state->sd);
+
+       pm_runtime_disable(&pdev->dev);
+       mipi_csis_pm_suspend(&pdev->dev, true);
+       mipi_csis_clk_disable(state);
+       media_entity_cleanup(&state->sd.entity);
+       mutex_destroy(&state->lock);
+       pm_runtime_set_suspended(&pdev->dev);
+
+       return 0;
+}
+
+static const struct of_device_id mipi_csis_of_match[] = {
+       {
+               .compatible = "fsl,imx7-mipi-csi2",
+               .data = &(const struct mipi_csis_info){
+                       .version = MIPI_CSIS_V3_3,
+                       .num_clocks = 3,
+               },
+       }, {
+               .compatible = "fsl,imx8mm-mipi-csi2",
+               .data = &(const struct mipi_csis_info){
+                       .version = MIPI_CSIS_V3_6_3,
+                       .num_clocks = 4,
+               },
+       },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mipi_csis_of_match);
+
+static struct platform_driver mipi_csis_driver = {
+       .probe          = mipi_csis_probe,
+       .remove         = mipi_csis_remove,
+       .driver         = {
+               .of_match_table = mipi_csis_of_match,
+               .name           = CSIS_DRIVER_NAME,
+               .pm             = &mipi_csis_pm_ops,
+       },
+};
+
+module_platform_driver(mipi_csis_driver);
+
+MODULE_DESCRIPTION("i.MX7 & i.MX8 MIPI CSI-2 receiver driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx-mipi-csi2");
diff --git a/drivers/media/platform/nxp/imx-pxp.c b/drivers/media/platform/nxp/imx-pxp.c
new file mode 100644 (file)
index 0000000..689ae5e
--- /dev/null
@@ -0,0 +1,1788 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * i.MX Pixel Pipeline (PXP) mem-to-mem scaler/CSC/rotator driver
+ *
+ * Copyright (c) 2018 Pengutronix, Philipp Zabel
+ *
+ * based on vim2m
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <linux/platform_device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "imx-pxp.h"
+
+static unsigned int debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+#define MIN_W 8
+#define MIN_H 8
+#define MAX_W 4096
+#define MAX_H 4096
+#define ALIGN_W 3 /* 8x8 pixel blocks */
+#define ALIGN_H 3
+
+/* Flags that indicate a format can be used for capture/output */
+#define MEM2MEM_CAPTURE        (1 << 0)
+#define MEM2MEM_OUTPUT (1 << 1)
+
+#define MEM2MEM_NAME           "pxp"
+
+/* Flags that indicate processing mode */
+#define MEM2MEM_HFLIP  (1 << 0)
+#define MEM2MEM_VFLIP  (1 << 1)
+
+#define dprintk(dev, fmt, arg...) \
+       v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
+
+struct pxp_fmt {
+       u32     fourcc;
+       int     depth;
+       /* Types the format can be used for */
+       u32     types;
+};
+
+static struct pxp_fmt formats[] = {
+       {
+               .fourcc = V4L2_PIX_FMT_XBGR32,
+               .depth  = 32,
+               /* Both capture and output format */
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_ABGR32,
+               .depth  = 32,
+               /* Capture-only format */
+               .types  = MEM2MEM_CAPTURE,
+       }, {
+               .fourcc = V4L2_PIX_FMT_BGR24,
+               .depth  = 24,
+               .types  = MEM2MEM_CAPTURE,
+       }, {
+               .fourcc = V4L2_PIX_FMT_RGB565,
+               .depth  = 16,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_RGB555,
+               .depth  = 16,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_RGB444,
+               .depth  = 16,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_VUYA32,
+               .depth  = 32,
+               .types  = MEM2MEM_CAPTURE,
+       }, {
+               .fourcc = V4L2_PIX_FMT_VUYX32,
+               .depth  = 32,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_UYVY,
+               .depth  = 16,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_YUYV,
+               .depth  = 16,
+               /* Output-only format */
+               .types  = MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_VYUY,
+               .depth  = 16,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_YVYU,
+               .depth  = 16,
+               .types  = MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_GREY,
+               .depth  = 8,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_Y4,
+               .depth  = 4,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_NV16,
+               .depth  = 16,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_NV12,
+               .depth  = 12,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_NV21,
+               .depth  = 12,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_NV61,
+               .depth  = 16,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_YUV422P,
+               .depth  = 16,
+               .types  = MEM2MEM_OUTPUT,
+       }, {
+               .fourcc = V4L2_PIX_FMT_YUV420,
+               .depth  = 12,
+               .types  = MEM2MEM_OUTPUT,
+       },
+};
+
+#define NUM_FORMATS ARRAY_SIZE(formats)
+
+/* Per-queue, driver-specific private data */
+struct pxp_q_data {
+       unsigned int            width;
+       unsigned int            height;
+       unsigned int            bytesperline;
+       unsigned int            sizeimage;
+       unsigned int            sequence;
+       struct pxp_fmt          *fmt;
+       enum v4l2_ycbcr_encoding ycbcr_enc;
+       enum v4l2_quantization  quant;
+};
+
+enum {
+       V4L2_M2M_SRC = 0,
+       V4L2_M2M_DST = 1,
+};
+
+static struct pxp_fmt *find_format(struct v4l2_format *f)
+{
+       struct pxp_fmt *fmt;
+       unsigned int k;
+
+       for (k = 0; k < NUM_FORMATS; k++) {
+               fmt = &formats[k];
+               if (fmt->fourcc == f->fmt.pix.pixelformat)
+                       break;
+       }
+
+       if (k == NUM_FORMATS)
+               return NULL;
+
+       return &formats[k];
+}
+
+struct pxp_dev {
+       struct v4l2_device      v4l2_dev;
+       struct video_device     vfd;
+
+       struct clk              *clk;
+       void __iomem            *mmio;
+
+       atomic_t                num_inst;
+       struct mutex            dev_mutex;
+       spinlock_t              irqlock;
+
+       struct v4l2_m2m_dev     *m2m_dev;
+};
+
+struct pxp_ctx {
+       struct v4l2_fh          fh;
+       struct pxp_dev  *dev;
+
+       struct v4l2_ctrl_handler hdl;
+
+       /* Abort requested by m2m */
+       int                     aborting;
+
+       /* Processing mode */
+       int                     mode;
+       u8                      alpha_component;
+       u8                      rotation;
+
+       enum v4l2_colorspace    colorspace;
+       enum v4l2_xfer_func     xfer_func;
+
+       /* Source and destination queue data */
+       struct pxp_q_data   q_data[2];
+};
+
+static inline struct pxp_ctx *file2ctx(struct file *file)
+{
+       return container_of(file->private_data, struct pxp_ctx, fh);
+}
+
+static struct pxp_q_data *get_q_data(struct pxp_ctx *ctx,
+                                        enum v4l2_buf_type type)
+{
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               return &ctx->q_data[V4L2_M2M_SRC];
+       else
+               return &ctx->q_data[V4L2_M2M_DST];
+}
+
+static u32 pxp_v4l2_pix_fmt_to_ps_format(u32 v4l2_pix_fmt)
+{
+       switch (v4l2_pix_fmt) {
+       case V4L2_PIX_FMT_XBGR32:  return BV_PXP_PS_CTRL_FORMAT__RGB888;
+       case V4L2_PIX_FMT_RGB555:  return BV_PXP_PS_CTRL_FORMAT__RGB555;
+       case V4L2_PIX_FMT_RGB444:  return BV_PXP_PS_CTRL_FORMAT__RGB444;
+       case V4L2_PIX_FMT_RGB565:  return BV_PXP_PS_CTRL_FORMAT__RGB565;
+       case V4L2_PIX_FMT_VUYX32:  return BV_PXP_PS_CTRL_FORMAT__YUV1P444;
+       case V4L2_PIX_FMT_UYVY:    return BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
+       case V4L2_PIX_FMT_YUYV:    return BM_PXP_PS_CTRL_WB_SWAP |
+                                         BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
+       case V4L2_PIX_FMT_VYUY:    return BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
+       case V4L2_PIX_FMT_YVYU:    return BM_PXP_PS_CTRL_WB_SWAP |
+                                         BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
+       case V4L2_PIX_FMT_GREY:    return BV_PXP_PS_CTRL_FORMAT__Y8;
+       default:
+       case V4L2_PIX_FMT_Y4:      return BV_PXP_PS_CTRL_FORMAT__Y4;
+       case V4L2_PIX_FMT_NV16:    return BV_PXP_PS_CTRL_FORMAT__YUV2P422;
+       case V4L2_PIX_FMT_NV12:    return BV_PXP_PS_CTRL_FORMAT__YUV2P420;
+       case V4L2_PIX_FMT_NV21:    return BV_PXP_PS_CTRL_FORMAT__YVU2P420;
+       case V4L2_PIX_FMT_NV61:    return BV_PXP_PS_CTRL_FORMAT__YVU2P422;
+       case V4L2_PIX_FMT_YUV422P: return BV_PXP_PS_CTRL_FORMAT__YUV422;
+       case V4L2_PIX_FMT_YUV420:  return BV_PXP_PS_CTRL_FORMAT__YUV420;
+       }
+}
+
+static u32 pxp_v4l2_pix_fmt_to_out_format(u32 v4l2_pix_fmt)
+{
+       switch (v4l2_pix_fmt) {
+       case V4L2_PIX_FMT_XBGR32:   return BV_PXP_OUT_CTRL_FORMAT__RGB888;
+       case V4L2_PIX_FMT_ABGR32:   return BV_PXP_OUT_CTRL_FORMAT__ARGB8888;
+       case V4L2_PIX_FMT_BGR24:    return BV_PXP_OUT_CTRL_FORMAT__RGB888P;
+       /* Missing V4L2 pixel formats for ARGB1555 and ARGB4444 */
+       case V4L2_PIX_FMT_RGB555:   return BV_PXP_OUT_CTRL_FORMAT__RGB555;
+       case V4L2_PIX_FMT_RGB444:   return BV_PXP_OUT_CTRL_FORMAT__RGB444;
+       case V4L2_PIX_FMT_RGB565:   return BV_PXP_OUT_CTRL_FORMAT__RGB565;
+       case V4L2_PIX_FMT_VUYA32:
+       case V4L2_PIX_FMT_VUYX32:   return BV_PXP_OUT_CTRL_FORMAT__YUV1P444;
+       case V4L2_PIX_FMT_UYVY:     return BV_PXP_OUT_CTRL_FORMAT__UYVY1P422;
+       case V4L2_PIX_FMT_VYUY:     return BV_PXP_OUT_CTRL_FORMAT__VYUY1P422;
+       case V4L2_PIX_FMT_GREY:     return BV_PXP_OUT_CTRL_FORMAT__Y8;
+       default:
+       case V4L2_PIX_FMT_Y4:       return BV_PXP_OUT_CTRL_FORMAT__Y4;
+       case V4L2_PIX_FMT_NV16:     return BV_PXP_OUT_CTRL_FORMAT__YUV2P422;
+       case V4L2_PIX_FMT_NV12:     return BV_PXP_OUT_CTRL_FORMAT__YUV2P420;
+       case V4L2_PIX_FMT_NV61:     return BV_PXP_OUT_CTRL_FORMAT__YVU2P422;
+       case V4L2_PIX_FMT_NV21:     return BV_PXP_OUT_CTRL_FORMAT__YVU2P420;
+       }
+}
+
+static bool pxp_v4l2_pix_fmt_is_yuv(u32 v4l2_pix_fmt)
+{
+       switch (v4l2_pix_fmt) {
+       case V4L2_PIX_FMT_VUYA32:
+       case V4L2_PIX_FMT_VUYX32:
+       case V4L2_PIX_FMT_UYVY:
+       case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_VYUY:
+       case V4L2_PIX_FMT_YVYU:
+       case V4L2_PIX_FMT_NV16:
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV61:
+       case V4L2_PIX_FMT_NV21:
+       case V4L2_PIX_FMT_YUV420:
+       case V4L2_PIX_FMT_YUV422P:
+       case V4L2_PIX_FMT_GREY:
+       case V4L2_PIX_FMT_Y4:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static void pxp_setup_csc(struct pxp_ctx *ctx)
+{
+       struct pxp_dev *dev = ctx->dev;
+       enum v4l2_ycbcr_encoding ycbcr_enc;
+       enum v4l2_quantization quantization;
+
+       if (pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) &&
+           !pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_DST].fmt->fourcc)) {
+               /*
+                * CSC1 YUV/YCbCr to RGB conversion is implemented as follows:
+                *
+                * |R|   |C0 0  C1|   |Y  + Yoffset |
+                * |G| = |C0 C3 C2| * |Cb + UVoffset|
+                * |B|   |C0 C4 0 |   |Cr + UVoffset|
+                *
+                * Results are clamped to 0..255.
+                *
+                * BT.601 limited range:
+                *
+                * |R|   |1.1644  0.0000  1.5960|   |Y  - 16 |
+                * |G| = |1.1644 -0.3917 -0.8129| * |Cb - 128|
+                * |B|   |1.1644  2.0172  0.0000|   |Cr - 128|
+                */
+               static const u32 csc1_coef_bt601_lim[3] = {
+                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
+                       BF_PXP_CSC1_COEF0_C0(0x12a) |   /*  1.1641 (-0.03 %) */
+                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+                       BF_PXP_CSC1_COEF0_Y_OFFSET(-16),
+                       BF_PXP_CSC1_COEF1_C1(0x198) |   /*  1.5938 (-0.23 %) */
+                       BF_PXP_CSC1_COEF1_C4(0x204),    /*  2.0156 (-0.16 %) */
+                       BF_PXP_CSC1_COEF2_C2(0x730) |   /* -0.8125 (+0.04 %) */
+                       BF_PXP_CSC1_COEF2_C3(0x79c),    /* -0.3906 (+0.11 %) */
+               };
+               /*
+                * BT.601 full range:
+                *
+                * |R|   |1.0000  0.0000  1.4020|   |Y  + 0  |
+                * |G| = |1.0000 -0.3441 -0.7141| * |Cb - 128|
+                * |B|   |1.0000  1.7720  0.0000|   |Cr - 128|
+                */
+               static const u32 csc1_coef_bt601_full[3] = {
+                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
+                       BF_PXP_CSC1_COEF0_C0(0x100) |   /*  1.0000 (+0.00 %) */
+                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+                       BF_PXP_CSC1_COEF0_Y_OFFSET(0),
+                       BF_PXP_CSC1_COEF1_C1(0x166) |   /*  1.3984 (-0.36 %) */
+                       BF_PXP_CSC1_COEF1_C4(0x1c5),    /*  1.7695 (-0.25 %) */
+                       BF_PXP_CSC1_COEF2_C2(0x74a) |   /* -0.7109 (+0.32 %) */
+                       BF_PXP_CSC1_COEF2_C3(0x7a8),    /* -0.3438 (+0.04 %) */
+               };
+               /*
+                * Rec.709 limited range:
+                *
+                * |R|   |1.1644  0.0000  1.7927|   |Y  - 16 |
+                * |G| = |1.1644 -0.2132 -0.5329| * |Cb - 128|
+                * |B|   |1.1644  2.1124  0.0000|   |Cr - 128|
+                */
+               static const u32 csc1_coef_rec709_lim[3] = {
+                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
+                       BF_PXP_CSC1_COEF0_C0(0x12a) |   /*  1.1641 (-0.03 %) */
+                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+                       BF_PXP_CSC1_COEF0_Y_OFFSET(-16),
+                       BF_PXP_CSC1_COEF1_C1(0x1ca) |   /*  1.7891 (-0.37 %) */
+                       BF_PXP_CSC1_COEF1_C4(0x21c),    /*  2.1094 (-0.30 %) */
+                       BF_PXP_CSC1_COEF2_C2(0x778) |   /* -0.5312 (+0.16 %) */
+                       BF_PXP_CSC1_COEF2_C3(0x7ca),    /* -0.2109 (+0.23 %) */
+               };
+               /*
+                * Rec.709 full range:
+                *
+                * |R|   |1.0000  0.0000  1.5748|   |Y  + 0  |
+                * |G| = |1.0000 -0.1873 -0.4681| * |Cb - 128|
+                * |B|   |1.0000  1.8556  0.0000|   |Cr - 128|
+                */
+               static const u32 csc1_coef_rec709_full[3] = {
+                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
+                       BF_PXP_CSC1_COEF0_C0(0x100) |   /*  1.0000 (+0.00 %) */
+                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+                       BF_PXP_CSC1_COEF0_Y_OFFSET(0),
+                       BF_PXP_CSC1_COEF1_C1(0x193) |   /*  1.5742 (-0.06 %) */
+                       BF_PXP_CSC1_COEF1_C4(0x1db),    /*  1.8555 (-0.01 %) */
+                       BF_PXP_CSC1_COEF2_C2(0x789) |   /* -0.4648 (+0.33 %) */
+                       BF_PXP_CSC1_COEF2_C3(0x7d1),    /* -0.1836 (+0.37 %) */
+               };
+               /*
+                * BT.2020 limited range:
+                *
+                * |R|   |1.1644  0.0000  1.6787|   |Y  - 16 |
+                * |G| = |1.1644 -0.1874 -0.6505| * |Cb - 128|
+                * |B|   |1.1644  2.1418  0.0000|   |Cr - 128|
+                */
+               static const u32 csc1_coef_bt2020_lim[3] = {
+                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
+                       BF_PXP_CSC1_COEF0_C0(0x12a) |   /*  1.1641 (-0.03 %) */
+                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+                       BF_PXP_CSC1_COEF0_Y_OFFSET(-16),
+                       BF_PXP_CSC1_COEF1_C1(0x1ad) |   /*  1.6758 (-0.29 %) */
+                       BF_PXP_CSC1_COEF1_C4(0x224),    /*  2.1406 (-0.11 %) */
+                       BF_PXP_CSC1_COEF2_C2(0x75a) |   /* -0.6484 (+0.20 %) */
+                       BF_PXP_CSC1_COEF2_C3(0x7d1),    /* -0.1836 (+0.38 %) */
+               };
+               /*
+                * BT.2020 full range:
+                *
+                * |R|   |1.0000  0.0000  1.4746|   |Y  + 0  |
+                * |G| = |1.0000 -0.1646 -0.5714| * |Cb - 128|
+                * |B|   |1.0000  1.8814  0.0000|   |Cr - 128|
+                */
+               static const u32 csc1_coef_bt2020_full[3] = {
+                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
+                       BF_PXP_CSC1_COEF0_C0(0x100) |   /*  1.0000 (+0.00 %) */
+                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+                       BF_PXP_CSC1_COEF0_Y_OFFSET(0),
+                       BF_PXP_CSC1_COEF1_C1(0x179) |   /*  1.4727 (-0.19 %) */
+                       BF_PXP_CSC1_COEF1_C4(0x1e1),    /*  1.8789 (-0.25 %) */
+                       BF_PXP_CSC1_COEF2_C2(0x76e) |   /* -0.5703 (+0.11 %) */
+                       BF_PXP_CSC1_COEF2_C3(0x7d6),    /* -0.1641 (+0.05 %) */
+               };
+               /*
+                * SMPTE 240m limited range:
+                *
+                * |R|   |1.1644  0.0000  1.7937|   |Y  - 16 |
+                * |G| = |1.1644 -0.2565 -0.5427| * |Cb - 128|
+                * |B|   |1.1644  2.0798  0.0000|   |Cr - 128|
+                */
+               static const u32 csc1_coef_smpte240m_lim[3] = {
+                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
+                       BF_PXP_CSC1_COEF0_C0(0x12a) |   /*  1.1641 (-0.03 %) */
+                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+                       BF_PXP_CSC1_COEF0_Y_OFFSET(-16),
+                       BF_PXP_CSC1_COEF1_C1(0x1cb) |   /*  1.7930 (-0.07 %) */
+                       BF_PXP_CSC1_COEF1_C4(0x214),    /*  2.0781 (-0.17 %) */
+                       BF_PXP_CSC1_COEF2_C2(0x776) |   /* -0.5391 (+0.36 %) */
+                       BF_PXP_CSC1_COEF2_C3(0x7bf),    /* -0.2539 (+0.26 %) */
+               };
+               /*
+                * SMPTE 240m full range:
+                *
+                * |R|   |1.0000  0.0000  1.5756|   |Y  + 0  |
+                * |G| = |1.0000 -0.2253 -0.4767| * |Cb - 128|
+                * |B|   |1.0000  1.8270  0.0000|   |Cr - 128|
+                */
+               static const u32 csc1_coef_smpte240m_full[3] = {
+                       BM_PXP_CSC1_COEF0_YCBCR_MODE |
+                       BF_PXP_CSC1_COEF0_C0(0x100) |   /*  1.0000 (+0.00 %) */
+                       BF_PXP_CSC1_COEF0_UV_OFFSET(-128) |
+                       BF_PXP_CSC1_COEF0_Y_OFFSET(0),
+                       BF_PXP_CSC1_COEF1_C1(0x193) |   /*  1.5742 (-0.14 %) */
+                       BF_PXP_CSC1_COEF1_C4(0x1d3),    /*  1.8242 (-0.28 %) */
+                       BF_PXP_CSC1_COEF2_C2(0x786) |   /* -0.4766 (+0.01 %) */
+                       BF_PXP_CSC1_COEF2_C3(0x7c7),    /* -0.2227 (+0.26 %) */
+               };
+               const u32 *csc1_coef;
+
+               ycbcr_enc = ctx->q_data[V4L2_M2M_SRC].ycbcr_enc;
+               quantization = ctx->q_data[V4L2_M2M_SRC].quant;
+
+               if (ycbcr_enc == V4L2_YCBCR_ENC_601) {
+                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+                               csc1_coef = csc1_coef_bt601_full;
+                       else
+                               csc1_coef = csc1_coef_bt601_lim;
+               } else if (ycbcr_enc == V4L2_YCBCR_ENC_709) {
+                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+                               csc1_coef = csc1_coef_rec709_full;
+                       else
+                               csc1_coef = csc1_coef_rec709_lim;
+               } else if (ycbcr_enc == V4L2_YCBCR_ENC_BT2020) {
+                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+                               csc1_coef = csc1_coef_bt2020_full;
+                       else
+                               csc1_coef = csc1_coef_bt2020_lim;
+               } else {
+                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+                               csc1_coef = csc1_coef_smpte240m_full;
+                       else
+                               csc1_coef = csc1_coef_smpte240m_lim;
+               }
+
+               writel(csc1_coef[0], dev->mmio + HW_PXP_CSC1_COEF0);
+               writel(csc1_coef[1], dev->mmio + HW_PXP_CSC1_COEF1);
+               writel(csc1_coef[2], dev->mmio + HW_PXP_CSC1_COEF2);
+       } else {
+               writel(BM_PXP_CSC1_COEF0_BYPASS, dev->mmio + HW_PXP_CSC1_COEF0);
+       }
+
+       if (!pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) &&
+           pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_DST].fmt->fourcc)) {
+               /*
+                * CSC2 RGB to YUV/YCbCr conversion is implemented as follows:
+                *
+                * |Y |   |A1 A2 A3|   |R|   |D1|
+                * |Cb| = |B1 B2 B3| * |G| + |D2|
+                * |Cr|   |C1 C2 C3|   |B|   |D3|
+                *
+                * Results are clamped to 0..255.
+                *
+                * BT.601 limited range:
+                *
+                * |Y |   | 0.2568  0.5041  0.0979|   |R|   |16 |
+                * |Cb| = |-0.1482 -0.2910  0.4392| * |G| + |128|
+                * |Cr|   | 0.4392  0.4392 -0.3678|   |B|   |128|
+                */
+               static const u32 csc2_coef_bt601_lim[6] = {
+                       BF_PXP_CSC2_COEF0_A2(0x081) |   /*  0.5039 (-0.02 %) */
+                       BF_PXP_CSC2_COEF0_A1(0x041),    /*  0.2539 (-0.29 %) */
+                       BF_PXP_CSC2_COEF1_B1(0x7db) |   /* -0.1445 (+0.37 %) */
+                       BF_PXP_CSC2_COEF1_A3(0x019),    /*  0.0977 (-0.02 %) */
+                       BF_PXP_CSC2_COEF2_B3(0x070) |   /*  0.4375 (-0.17 %) */
+                       BF_PXP_CSC2_COEF2_B2(0x7b6),    /* -0.2891 (+0.20 %) */
+                       BF_PXP_CSC2_COEF3_C2(0x7a2) |   /* -0.3672 (+0.06 %) */
+                       BF_PXP_CSC2_COEF3_C1(0x070),    /*  0.4375 (-0.17 %) */
+                       BF_PXP_CSC2_COEF4_D1(16) |
+                       BF_PXP_CSC2_COEF4_C3(0x7ee),    /* -0.0703 (+0.11 %) */
+                       BF_PXP_CSC2_COEF5_D3(128) |
+                       BF_PXP_CSC2_COEF5_D2(128),
+               };
+               /*
+                * BT.601 full range:
+                *
+                * |Y |   | 0.2990  0.5870  0.1140|   |R|   |0  |
+                * |Cb| = |-0.1687 -0.3313  0.5000| * |G| + |128|
+                * |Cr|   | 0.5000  0.5000 -0.4187|   |B|   |128|
+                */
+               static const u32 csc2_coef_bt601_full[6] = {
+                       BF_PXP_CSC2_COEF0_A2(0x096) |   /*  0.5859 (-0.11 %) */
+                       BF_PXP_CSC2_COEF0_A1(0x04c),    /*  0.2969 (-0.21 %) */
+                       BF_PXP_CSC2_COEF1_B1(0x7d5) |   /* -0.1680 (+0.07 %) */
+                       BF_PXP_CSC2_COEF1_A3(0x01d),    /*  0.1133 (-0.07 %) */
+                       BF_PXP_CSC2_COEF2_B3(0x080) |   /*  0.5000 (+0.00 %) */
+                       BF_PXP_CSC2_COEF2_B2(0x7ac),    /* -0.3281 (+0.32 %) */
+                       BF_PXP_CSC2_COEF3_C2(0x795) |   /* -0.4180 (+0.07 %) */
+                       BF_PXP_CSC2_COEF3_C1(0x080),    /*  0.5000 (+0.00 %) */
+                       BF_PXP_CSC2_COEF4_D1(0) |
+                       BF_PXP_CSC2_COEF4_C3(0x7ec),    /* -0.0781 (+0.32 %) */
+                       BF_PXP_CSC2_COEF5_D3(128) |
+                       BF_PXP_CSC2_COEF5_D2(128),
+               };
+               /*
+                * Rec.709 limited range:
+                *
+                * |Y |   | 0.1826  0.6142  0.0620|   |R|   |16 |
+                * |Cb| = |-0.1007 -0.3385  0.4392| * |G| + |128|
+                * |Cr|   | 0.4392  0.4392 -0.3990|   |B|   |128|
+                */
+               static const u32 csc2_coef_rec709_lim[6] = {
+                       BF_PXP_CSC2_COEF0_A2(0x09d) |   /*  0.6133 (-0.09 %) */
+                       BF_PXP_CSC2_COEF0_A1(0x02e),    /*  0.1797 (-0.29 %) */
+                       BF_PXP_CSC2_COEF1_B1(0x7e7) |   /* -0.0977 (+0.30 %) */
+                       BF_PXP_CSC2_COEF1_A3(0x00f),    /*  0.0586 (-0.34 %) */
+                       BF_PXP_CSC2_COEF2_B3(0x070) |   /*  0.4375 (-0.17 %) */
+                       BF_PXP_CSC2_COEF2_B2(0x7aa),    /* -0.3359 (+0.26 %) */
+                       BF_PXP_CSC2_COEF3_C2(0x79a) |   /* -0.3984 (+0.05 %) */
+                       BF_PXP_CSC2_COEF3_C1(0x070),    /*  0.4375 (-0.17 %) */
+                       BF_PXP_CSC2_COEF4_D1(16) |
+                       BF_PXP_CSC2_COEF4_C3(0x7f6),    /* -0.0391 (+0.12 %) */
+                       BF_PXP_CSC2_COEF5_D3(128) |
+                       BF_PXP_CSC2_COEF5_D2(128),
+               };
+               /*
+                * Rec.709 full range:
+                *
+                * |Y |   | 0.2126  0.7152  0.0722|   |R|   |0  |
+                * |Cb| = |-0.1146 -0.3854  0.5000| * |G| + |128|
+                * |Cr|   | 0.5000  0.5000 -0.4542|   |B|   |128|
+                */
+               static const u32 csc2_coef_rec709_full[6] = {
+                       BF_PXP_CSC2_COEF0_A2(0x0b7) |   /*  0.7148 (-0.04 %) */
+                       BF_PXP_CSC2_COEF0_A1(0x036),    /*  0.2109 (-0.17 %) */
+                       BF_PXP_CSC2_COEF1_B1(0x7e3) |   /* -0.1133 (+0.13 %) */
+                       BF_PXP_CSC2_COEF1_A3(0x012),    /*  0.0703 (-0.19 %) */
+                       BF_PXP_CSC2_COEF2_B3(0x080) |   /*  0.5000 (+0.00 %) */
+                       BF_PXP_CSC2_COEF2_B2(0x79e),    /* -0.3828 (+0.26 %) */
+                       BF_PXP_CSC2_COEF3_C2(0x78c) |   /* -0.4531 (+0.11 %) */
+                       BF_PXP_CSC2_COEF3_C1(0x080),    /*  0.5000 (+0.00 %) */
+                       BF_PXP_CSC2_COEF4_D1(0) |
+                       BF_PXP_CSC2_COEF4_C3(0x7f5),    /* -0.0430 (+0.28 %) */
+                       BF_PXP_CSC2_COEF5_D3(128) |
+                       BF_PXP_CSC2_COEF5_D2(128),
+               };
+               /*
+                * BT.2020 limited range:
+                *
+                * |Y |   | 0.2256  0.5823  0.0509|   |R|   |16 |
+                * |Cb| = |-0.1226 -0.3166  0.4392| * |G| + |128|
+                * |Cr|   | 0.4392  0.4392 -0.4039|   |B|   |128|
+                */
+               static const u32 csc2_coef_bt2020_lim[6] = {
+                       BF_PXP_CSC2_COEF0_A2(0x095) |   /*  0.5820 (-0.03 %) */
+                       BF_PXP_CSC2_COEF0_A1(0x039),    /*  0.2227 (-0.30 %) */
+                       BF_PXP_CSC2_COEF1_B1(0x7e1) |   /* -0.1211 (+0.15 %) */
+                       BF_PXP_CSC2_COEF1_A3(0x00d),    /*  0.0508 (-0.01 %) */
+                       BF_PXP_CSC2_COEF2_B3(0x070) |   /*  0.4375 (-0.17 %) */
+                       BF_PXP_CSC2_COEF2_B2(0x7af),    /* -0.3164 (+0.02 %) */
+                       BF_PXP_CSC2_COEF3_C2(0x799) |   /* -0.4023 (+0.16 %) */
+                       BF_PXP_CSC2_COEF3_C1(0x070),    /*  0.4375 (-0.17 %) */
+                       BF_PXP_CSC2_COEF4_D1(16) |
+                       BF_PXP_CSC2_COEF4_C3(0x7f7),    /* -0.0352 (+0.02 %) */
+                       BF_PXP_CSC2_COEF5_D3(128) |
+                       BF_PXP_CSC2_COEF5_D2(128),
+               };
+               /*
+                * BT.2020 full range:
+                *
+                * |Y |   | 0.2627  0.6780  0.0593|   |R|   |0  |
+                * |Cb| = |-0.1396 -0.3604  0.5000| * |G| + |128|
+                * |Cr|   | 0.5000  0.5000 -0.4598|   |B|   |128|
+                */
+               static const u32 csc2_coef_bt2020_full[6] = {
+                       BF_PXP_CSC2_COEF0_A2(0x0ad) |   /*  0.6758 (-0.22 %) */
+                       BF_PXP_CSC2_COEF0_A1(0x043),    /*  0.2617 (-0.10 %) */
+                       BF_PXP_CSC2_COEF1_B1(0x7dd) |   /* -0.1367 (+0.29 %) */
+                       BF_PXP_CSC2_COEF1_A3(0x00f),    /*  0.0586 (-0.07 %) */
+                       BF_PXP_CSC2_COEF2_B3(0x080) |   /*  0.5000 (+0.00 %) */
+                       BF_PXP_CSC2_COEF2_B2(0x7a4),    /* -0.3594 (+0.10 %) */
+                       BF_PXP_CSC2_COEF3_C2(0x78b) |   /* -0.4570 (+0.28 %) */
+                       BF_PXP_CSC2_COEF3_C1(0x080),    /*  0.5000 (+0.00 %) */
+                       BF_PXP_CSC2_COEF4_D1(0) |
+                       BF_PXP_CSC2_COEF4_C3(0x7f6),    /* -0.0391 (+0.11 %) */
+                       BF_PXP_CSC2_COEF5_D3(128) |
+                       BF_PXP_CSC2_COEF5_D2(128),
+               };
+               /*
+                * SMPTE 240m limited range:
+                *
+                * |Y |   | 0.1821  0.6020  0.0747|   |R|   |16 |
+                * |Cb| = |-0.1019 -0.3373  0.4392| * |G| + |128|
+                * |Cr|   | 0.4392  0.4392 -0.3909|   |B|   |128|
+                */
+               static const u32 csc2_coef_smpte240m_lim[6] = {
+                       BF_PXP_CSC2_COEF0_A2(0x09a) |   /*  0.6016 (-0.05 %) */
+                       BF_PXP_CSC2_COEF0_A1(0x02e),    /*  0.1797 (-0.24 %) */
+                       BF_PXP_CSC2_COEF1_B1(0x7e6) |   /* -0.1016 (+0.03 %) */
+                       BF_PXP_CSC2_COEF1_A3(0x013),    /*  0.0742 (-0.05 %) */
+                       BF_PXP_CSC2_COEF2_B3(0x070) |   /*  0.4375 (-0.17 %) */
+                       BF_PXP_CSC2_COEF2_B2(0x7aa),    /* -0.3359 (+0.14 %) */
+                       BF_PXP_CSC2_COEF3_C2(0x79c) |   /* -0.3906 (+0.03 %) */
+                       BF_PXP_CSC2_COEF3_C1(0x070),    /*  0.4375 (-0.17 %) */
+                       BF_PXP_CSC2_COEF4_D1(16) |
+                       BF_PXP_CSC2_COEF4_C3(0x7f4),    /* -0.0469 (+0.14 %) */
+                       BF_PXP_CSC2_COEF5_D3(128) |
+                       BF_PXP_CSC2_COEF5_D2(128),
+               };
+               /*
+                * SMPTE 240m full range:
+                *
+                * |Y |   | 0.2120  0.7010  0.0870|   |R|   |0  |
+                * |Cb| = |-0.1160 -0.3840  0.5000| * |G| + |128|
+                * |Cr|   | 0.5000  0.5000 -0.4450|   |B|   |128|
+                */
+               static const u32 csc2_coef_smpte240m_full[6] = {
+                       BF_PXP_CSC2_COEF0_A2(0x0b3) |   /*  0.6992 (-0.18 %) */
+                       BF_PXP_CSC2_COEF0_A1(0x036),    /*  0.2109 (-0.11 %) */
+                       BF_PXP_CSC2_COEF1_B1(0x7e3) |   /* -0.1133 (+0.27 %) */
+                       BF_PXP_CSC2_COEF1_A3(0x016),    /*  0.0859 (-0.11 %) */
+                       BF_PXP_CSC2_COEF2_B3(0x080) |   /*  0.5000 (+0.00 %) */
+                       BF_PXP_CSC2_COEF2_B2(0x79e),    /* -0.3828 (+0.12 %) */
+                       BF_PXP_CSC2_COEF3_C2(0x78f) |   /* -0.4414 (+0.36 %) */
+                       BF_PXP_CSC2_COEF3_C1(0x080),    /*  0.5000 (+0.00 %) */
+                       BF_PXP_CSC2_COEF4_D1(0) |
+                       BF_PXP_CSC2_COEF4_C3(0x7f2),    /* -0.0547 (+0.03 %) */
+                       BF_PXP_CSC2_COEF5_D3(128) |
+                       BF_PXP_CSC2_COEF5_D2(128),
+               };
+               const u32 *csc2_coef;
+               u32 csc2_ctrl;
+
+               ycbcr_enc = ctx->q_data[V4L2_M2M_DST].ycbcr_enc;
+               quantization = ctx->q_data[V4L2_M2M_DST].quant;
+
+               if (ycbcr_enc == V4L2_YCBCR_ENC_601) {
+                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+                               csc2_coef = csc2_coef_bt601_full;
+                       else
+                               csc2_coef = csc2_coef_bt601_lim;
+               } else if (ycbcr_enc == V4L2_YCBCR_ENC_709) {
+                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+                               csc2_coef = csc2_coef_rec709_full;
+                       else
+                               csc2_coef = csc2_coef_rec709_lim;
+               } else if (ycbcr_enc == V4L2_YCBCR_ENC_BT2020) {
+                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+                               csc2_coef = csc2_coef_bt2020_full;
+                       else
+                               csc2_coef = csc2_coef_bt2020_lim;
+               } else {
+                       if (quantization == V4L2_QUANTIZATION_FULL_RANGE)
+                               csc2_coef = csc2_coef_smpte240m_full;
+                       else
+                               csc2_coef = csc2_coef_smpte240m_lim;
+               }
+               if (quantization == V4L2_QUANTIZATION_FULL_RANGE) {
+                       csc2_ctrl = BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV <<
+                                   BP_PXP_CSC2_CTRL_CSC_MODE;
+               } else {
+                       csc2_ctrl = BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr <<
+                                   BP_PXP_CSC2_CTRL_CSC_MODE;
+               }
+
+               writel(csc2_ctrl, dev->mmio + HW_PXP_CSC2_CTRL);
+               writel(csc2_coef[0], dev->mmio + HW_PXP_CSC2_COEF0);
+               writel(csc2_coef[1], dev->mmio + HW_PXP_CSC2_COEF1);
+               writel(csc2_coef[2], dev->mmio + HW_PXP_CSC2_COEF2);
+               writel(csc2_coef[3], dev->mmio + HW_PXP_CSC2_COEF3);
+               writel(csc2_coef[4], dev->mmio + HW_PXP_CSC2_COEF4);
+               writel(csc2_coef[5], dev->mmio + HW_PXP_CSC2_COEF5);
+       } else {
+               writel(BM_PXP_CSC2_CTRL_BYPASS, dev->mmio + HW_PXP_CSC2_CTRL);
+       }
+}
+
+static int pxp_start(struct pxp_ctx *ctx, struct vb2_v4l2_buffer *in_vb,
+                    struct vb2_v4l2_buffer *out_vb)
+{
+       struct pxp_dev *dev = ctx->dev;
+       struct pxp_q_data *q_data;
+       u32 src_width, src_height, src_stride, src_fourcc;
+       u32 dst_width, dst_height, dst_stride, dst_fourcc;
+       dma_addr_t p_in, p_out;
+       u32 ctrl, out_ctrl, out_buf, out_buf2, out_pitch, out_lrc, out_ps_ulc;
+       u32 out_ps_lrc;
+       u32 ps_ctrl, ps_buf, ps_ubuf, ps_vbuf, ps_pitch, ps_scale, ps_offset;
+       u32 as_ulc, as_lrc;
+       u32 y_size;
+       u32 decx, decy, xscale, yscale;
+
+       q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+
+       src_width = ctx->q_data[V4L2_M2M_SRC].width;
+       dst_width = ctx->q_data[V4L2_M2M_DST].width;
+       src_height = ctx->q_data[V4L2_M2M_SRC].height;
+       dst_height = ctx->q_data[V4L2_M2M_DST].height;
+       src_stride = ctx->q_data[V4L2_M2M_SRC].bytesperline;
+       dst_stride = ctx->q_data[V4L2_M2M_DST].bytesperline;
+       src_fourcc = ctx->q_data[V4L2_M2M_SRC].fmt->fourcc;
+       dst_fourcc = ctx->q_data[V4L2_M2M_DST].fmt->fourcc;
+
+       p_in = vb2_dma_contig_plane_dma_addr(&in_vb->vb2_buf, 0);
+       p_out = vb2_dma_contig_plane_dma_addr(&out_vb->vb2_buf, 0);
+
+       if (!p_in || !p_out) {
+               v4l2_err(&dev->v4l2_dev,
+                        "Acquiring DMA addresses of buffers failed\n");
+               return -EFAULT;
+       }
+
+       out_vb->sequence =
+               get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++;
+       in_vb->sequence = q_data->sequence++;
+       out_vb->vb2_buf.timestamp = in_vb->vb2_buf.timestamp;
+
+       if (in_vb->flags & V4L2_BUF_FLAG_TIMECODE)
+               out_vb->timecode = in_vb->timecode;
+       out_vb->field = in_vb->field;
+       out_vb->flags = in_vb->flags &
+               (V4L2_BUF_FLAG_TIMECODE |
+                V4L2_BUF_FLAG_KEYFRAME |
+                V4L2_BUF_FLAG_PFRAME |
+                V4L2_BUF_FLAG_BFRAME |
+                V4L2_BUF_FLAG_TSTAMP_SRC_MASK);
+
+       /* 8x8 block size */
+       ctrl = BF_PXP_CTRL_VFLIP0(!!(ctx->mode & MEM2MEM_VFLIP)) |
+              BF_PXP_CTRL_HFLIP0(!!(ctx->mode & MEM2MEM_HFLIP)) |
+              BF_PXP_CTRL_ROTATE0(ctx->rotation);
+       /* Always write alpha value as V4L2_CID_ALPHA_COMPONENT */
+       out_ctrl = BF_PXP_OUT_CTRL_ALPHA(ctx->alpha_component) |
+                  BF_PXP_OUT_CTRL_ALPHA_OUTPUT(1) |
+                  pxp_v4l2_pix_fmt_to_out_format(dst_fourcc);
+       out_buf = p_out;
+
+       if (ctx->rotation == BV_PXP_CTRL_ROTATE0__ROT_90 ||
+           ctx->rotation == BV_PXP_CTRL_ROTATE0__ROT_270)
+               swap(dst_width, dst_height);
+
+       switch (dst_fourcc) {
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV21:
+       case V4L2_PIX_FMT_NV16:
+       case V4L2_PIX_FMT_NV61:
+               out_buf2 = out_buf + dst_stride * dst_height;
+               break;
+       default:
+               out_buf2 = 0;
+       }
+
+       out_pitch = BF_PXP_OUT_PITCH_PITCH(dst_stride);
+       out_lrc = BF_PXP_OUT_LRC_X(dst_width - 1) |
+                 BF_PXP_OUT_LRC_Y(dst_height - 1);
+       /* PS covers whole output */
+       out_ps_ulc = BF_PXP_OUT_PS_ULC_X(0) | BF_PXP_OUT_PS_ULC_Y(0);
+       out_ps_lrc = BF_PXP_OUT_PS_LRC_X(dst_width - 1) |
+                    BF_PXP_OUT_PS_LRC_Y(dst_height - 1);
+       /* no AS */
+       as_ulc = BF_PXP_OUT_AS_ULC_X(1) | BF_PXP_OUT_AS_ULC_Y(1);
+       as_lrc = BF_PXP_OUT_AS_LRC_X(0) | BF_PXP_OUT_AS_LRC_Y(0);
+
+       decx = (src_width <= dst_width) ? 0 : ilog2(src_width / dst_width);
+       decy = (src_height <= dst_height) ? 0 : ilog2(src_height / dst_height);
+       ps_ctrl = BF_PXP_PS_CTRL_DECX(decx) | BF_PXP_PS_CTRL_DECY(decy) |
+                 pxp_v4l2_pix_fmt_to_ps_format(src_fourcc);
+       ps_buf = p_in;
+       y_size = src_stride * src_height;
+       switch (src_fourcc) {
+       case V4L2_PIX_FMT_YUV420:
+               ps_ubuf = ps_buf + y_size;
+               ps_vbuf = ps_ubuf + y_size / 4;
+               break;
+       case V4L2_PIX_FMT_YUV422P:
+               ps_ubuf = ps_buf + y_size;
+               ps_vbuf = ps_ubuf + y_size / 2;
+               break;
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV21:
+       case V4L2_PIX_FMT_NV16:
+       case V4L2_PIX_FMT_NV61:
+               ps_ubuf = ps_buf + y_size;
+               ps_vbuf = 0;
+               break;
+       case V4L2_PIX_FMT_GREY:
+       case V4L2_PIX_FMT_Y4:
+               ps_ubuf = 0;
+               /* In grayscale mode, ps_vbuf contents are reused as CbCr */
+               ps_vbuf = 0x8080;
+               break;
+       default:
+               ps_ubuf = 0;
+               ps_vbuf = 0;
+               break;
+       }
+       ps_pitch = BF_PXP_PS_PITCH_PITCH(src_stride);
+       if (decx) {
+               xscale = (src_width >> decx) * 0x1000 / dst_width;
+       } else {
+               switch (src_fourcc) {
+               case V4L2_PIX_FMT_UYVY:
+               case V4L2_PIX_FMT_YUYV:
+               case V4L2_PIX_FMT_VYUY:
+               case V4L2_PIX_FMT_YVYU:
+               case V4L2_PIX_FMT_NV16:
+               case V4L2_PIX_FMT_NV12:
+               case V4L2_PIX_FMT_NV21:
+               case V4L2_PIX_FMT_NV61:
+               case V4L2_PIX_FMT_YUV422P:
+               case V4L2_PIX_FMT_YUV420:
+                       /*
+                        * This avoids sampling past the right edge for
+                        * horizontally chroma subsampled formats.
+                        */
+                       xscale = (src_width - 2) * 0x1000 / (dst_width - 1);
+                       break;
+               default:
+                       xscale = (src_width - 1) * 0x1000 / (dst_width - 1);
+                       break;
+               }
+       }
+       if (decy)
+               yscale = (src_height >> decy) * 0x1000 / dst_height;
+       else
+               yscale = (src_height - 1) * 0x1000 / (dst_height - 1);
+       ps_scale = BF_PXP_PS_SCALE_YSCALE(yscale) |
+                  BF_PXP_PS_SCALE_XSCALE(xscale);
+       ps_offset = BF_PXP_PS_OFFSET_YOFFSET(0) | BF_PXP_PS_OFFSET_XOFFSET(0);
+
+       writel(ctrl, dev->mmio + HW_PXP_CTRL);
+       /* skip STAT */
+       writel(out_ctrl, dev->mmio + HW_PXP_OUT_CTRL);
+       writel(out_buf, dev->mmio + HW_PXP_OUT_BUF);
+       writel(out_buf2, dev->mmio + HW_PXP_OUT_BUF2);
+       writel(out_pitch, dev->mmio + HW_PXP_OUT_PITCH);
+       writel(out_lrc, dev->mmio + HW_PXP_OUT_LRC);
+       writel(out_ps_ulc, dev->mmio + HW_PXP_OUT_PS_ULC);
+       writel(out_ps_lrc, dev->mmio + HW_PXP_OUT_PS_LRC);
+       writel(as_ulc, dev->mmio + HW_PXP_OUT_AS_ULC);
+       writel(as_lrc, dev->mmio + HW_PXP_OUT_AS_LRC);
+       writel(ps_ctrl, dev->mmio + HW_PXP_PS_CTRL);
+       writel(ps_buf, dev->mmio + HW_PXP_PS_BUF);
+       writel(ps_ubuf, dev->mmio + HW_PXP_PS_UBUF);
+       writel(ps_vbuf, dev->mmio + HW_PXP_PS_VBUF);
+       writel(ps_pitch, dev->mmio + HW_PXP_PS_PITCH);
+       writel(0x00ffffff, dev->mmio + HW_PXP_PS_BACKGROUND_0);
+       writel(ps_scale, dev->mmio + HW_PXP_PS_SCALE);
+       writel(ps_offset, dev->mmio + HW_PXP_PS_OFFSET);
+       /* disable processed surface color keying */
+       writel(0x00ffffff, dev->mmio + HW_PXP_PS_CLRKEYLOW_0);
+       writel(0x00000000, dev->mmio + HW_PXP_PS_CLRKEYHIGH_0);
+
+       /* disable alpha surface color keying */
+       writel(0x00ffffff, dev->mmio + HW_PXP_AS_CLRKEYLOW_0);
+       writel(0x00000000, dev->mmio + HW_PXP_AS_CLRKEYHIGH_0);
+
+       /* setup CSC */
+       pxp_setup_csc(ctx);
+
+       /* bypass LUT */
+       writel(BM_PXP_LUT_CTRL_BYPASS, dev->mmio + HW_PXP_LUT_CTRL);
+
+       writel(BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(1)|
+              BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(1)|
+              BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(0)|
+              BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(0),
+              dev->mmio + HW_PXP_DATA_PATH_CTRL0);
+       writel(BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(1) |
+              BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(1),
+              dev->mmio + HW_PXP_DATA_PATH_CTRL1);
+
+       writel(0xffff, dev->mmio + HW_PXP_IRQ_MASK);
+
+       /* ungate, enable PS/AS/OUT and PXP operation */
+       writel(BM_PXP_CTRL_IRQ_ENABLE, dev->mmio + HW_PXP_CTRL_SET);
+       writel(BM_PXP_CTRL_ENABLE | BM_PXP_CTRL_ENABLE_CSC2 |
+              BM_PXP_CTRL_ENABLE_LUT | BM_PXP_CTRL_ENABLE_ROTATE0 |
+              BM_PXP_CTRL_ENABLE_PS_AS_OUT, dev->mmio + HW_PXP_CTRL_SET);
+
+       return 0;
+}
+
+static void pxp_job_finish(struct pxp_dev *dev)
+{
+       struct pxp_ctx *curr_ctx;
+       struct vb2_v4l2_buffer *src_vb, *dst_vb;
+       unsigned long flags;
+
+       curr_ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
+
+       if (curr_ctx == NULL) {
+               pr_err("Instance released before the end of transaction\n");
+               return;
+       }
+
+       src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
+       dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+       v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
+       v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+
+       dprintk(curr_ctx->dev, "Finishing transaction\n");
+       v4l2_m2m_job_finish(dev->m2m_dev, curr_ctx->fh.m2m_ctx);
+}
+
+/*
+ * mem2mem callbacks
+ */
+static void pxp_device_run(void *priv)
+{
+       struct pxp_ctx *ctx = priv;
+       struct vb2_v4l2_buffer *src_buf, *dst_buf;
+
+       src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+
+       pxp_start(ctx, src_buf, dst_buf);
+}
+
+static int pxp_job_ready(void *priv)
+{
+       struct pxp_ctx *ctx = priv;
+
+       if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < 1 ||
+           v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < 1) {
+               dprintk(ctx->dev, "Not enough buffers available\n");
+               return 0;
+       }
+
+       return 1;
+}
+
+static void pxp_job_abort(void *priv)
+{
+       struct pxp_ctx *ctx = priv;
+
+       /* Will cancel the transaction in the next interrupt handler */
+       ctx->aborting = 1;
+}
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t pxp_irq_handler(int irq, void *dev_id)
+{
+       struct pxp_dev *dev = dev_id;
+       u32 stat;
+
+       stat = readl(dev->mmio + HW_PXP_STAT);
+
+       if (stat & BM_PXP_STAT_IRQ0) {
+               /* we expect x = 0, y = height, irq0 = 1 */
+               if (stat & ~(BM_PXP_STAT_BLOCKX | BM_PXP_STAT_BLOCKY |
+                            BM_PXP_STAT_IRQ0))
+                       dprintk(dev, "%s: stat = 0x%08x\n", __func__, stat);
+               writel(BM_PXP_STAT_IRQ0, dev->mmio + HW_PXP_STAT_CLR);
+
+               pxp_job_finish(dev);
+       } else {
+               u32 irq = readl(dev->mmio + HW_PXP_IRQ);
+
+               dprintk(dev, "%s: stat = 0x%08x\n", __func__, stat);
+               dprintk(dev, "%s: irq = 0x%08x\n", __func__, irq);
+
+               writel(irq, dev->mmio + HW_PXP_IRQ_CLR);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * video ioctls
+ */
+static int pxp_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
+       strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info),
+                       "platform:%s", MEM2MEM_NAME);
+       return 0;
+}
+
+static int pxp_enum_fmt(struct v4l2_fmtdesc *f, u32 type)
+{
+       int i, num;
+       struct pxp_fmt *fmt;
+
+       num = 0;
+
+       for (i = 0; i < NUM_FORMATS; ++i) {
+               if (formats[i].types & type) {
+                       /* index-th format of type type found ? */
+                       if (num == f->index)
+                               break;
+                       /*
+                        * Correct type but haven't reached our index yet,
+                        * just increment per-type index
+                        */
+                       ++num;
+               }
+       }
+
+       if (i < NUM_FORMATS) {
+               /* Format found */
+               fmt = &formats[i];
+               f->pixelformat = fmt->fourcc;
+               return 0;
+       }
+
+       /* Format not found */
+       return -EINVAL;
+}
+
+static int pxp_enum_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_fmtdesc *f)
+{
+       return pxp_enum_fmt(f, MEM2MEM_CAPTURE);
+}
+
+static int pxp_enum_fmt_vid_out(struct file *file, void *priv,
+                               struct v4l2_fmtdesc *f)
+{
+       return pxp_enum_fmt(f, MEM2MEM_OUTPUT);
+}
+
+static int pxp_g_fmt(struct pxp_ctx *ctx, struct v4l2_format *f)
+{
+       struct vb2_queue *vq;
+       struct pxp_q_data *q_data;
+
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       q_data = get_q_data(ctx, f->type);
+
+       f->fmt.pix.width        = q_data->width;
+       f->fmt.pix.height       = q_data->height;
+       f->fmt.pix.field        = V4L2_FIELD_NONE;
+       f->fmt.pix.pixelformat  = q_data->fmt->fourcc;
+       f->fmt.pix.bytesperline = q_data->bytesperline;
+       f->fmt.pix.sizeimage    = q_data->sizeimage;
+       f->fmt.pix.colorspace   = ctx->colorspace;
+       f->fmt.pix.xfer_func    = ctx->xfer_func;
+       f->fmt.pix.ycbcr_enc    = q_data->ycbcr_enc;
+       f->fmt.pix.quantization = q_data->quant;
+
+       return 0;
+}
+
+static int pxp_g_fmt_vid_out(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       return pxp_g_fmt(file2ctx(file), f);
+}
+
+static int pxp_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       return pxp_g_fmt(file2ctx(file), f);
+}
+
+static inline u32 pxp_bytesperline(struct pxp_fmt *fmt, u32 width)
+{
+       switch (fmt->fourcc) {
+       case V4L2_PIX_FMT_YUV420:
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV21:
+       case V4L2_PIX_FMT_YUV422P:
+       case V4L2_PIX_FMT_NV16:
+       case V4L2_PIX_FMT_NV61:
+               return width;
+       default:
+               return (width * fmt->depth) >> 3;
+       }
+}
+
+static inline u32 pxp_sizeimage(struct pxp_fmt *fmt, u32 width, u32 height)
+{
+       return (fmt->depth * width * height) >> 3;
+}
+
+static int pxp_try_fmt(struct v4l2_format *f, struct pxp_fmt *fmt)
+{
+       v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, ALIGN_W,
+                             &f->fmt.pix.height, MIN_H, MAX_H, ALIGN_H, 0);
+
+       f->fmt.pix.bytesperline = pxp_bytesperline(fmt, f->fmt.pix.width);
+       f->fmt.pix.sizeimage = pxp_sizeimage(fmt, f->fmt.pix.width,
+                                            f->fmt.pix.height);
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+
+       return 0;
+}
+
+static void
+pxp_fixup_colorimetry_cap(struct pxp_ctx *ctx, u32 dst_fourcc,
+                         enum v4l2_ycbcr_encoding *ycbcr_enc,
+                         enum v4l2_quantization *quantization)
+{
+       bool dst_is_yuv = pxp_v4l2_pix_fmt_is_yuv(dst_fourcc);
+
+       if (pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) ==
+           dst_is_yuv) {
+               /*
+                * There is no support for conversion between different YCbCr
+                * encodings or between RGB limited and full range.
+                */
+               *ycbcr_enc = ctx->q_data[V4L2_M2M_SRC].ycbcr_enc;
+               *quantization = ctx->q_data[V4L2_M2M_SRC].quant;
+       } else {
+               *ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(ctx->colorspace);
+               *quantization = V4L2_MAP_QUANTIZATION_DEFAULT(!dst_is_yuv,
+                                                             ctx->colorspace,
+                                                             *ycbcr_enc);
+       }
+}
+
+static int pxp_try_fmt_vid_cap(struct file *file, void *priv,
+                              struct v4l2_format *f)
+{
+       struct pxp_fmt *fmt;
+       struct pxp_ctx *ctx = file2ctx(file);
+
+       fmt = find_format(f);
+       if (!fmt) {
+               f->fmt.pix.pixelformat = formats[0].fourcc;
+               fmt = find_format(f);
+       }
+       if (!(fmt->types & MEM2MEM_CAPTURE)) {
+               v4l2_err(&ctx->dev->v4l2_dev,
+                        "Fourcc format (0x%08x) invalid.\n",
+                        f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       f->fmt.pix.colorspace = ctx->colorspace;
+       f->fmt.pix.xfer_func = ctx->xfer_func;
+
+       pxp_fixup_colorimetry_cap(ctx, fmt->fourcc,
+                                 &f->fmt.pix.ycbcr_enc,
+                                 &f->fmt.pix.quantization);
+
+       return pxp_try_fmt(f, fmt);
+}
+
+static int pxp_try_fmt_vid_out(struct file *file, void *priv,
+                              struct v4l2_format *f)
+{
+       struct pxp_fmt *fmt;
+       struct pxp_ctx *ctx = file2ctx(file);
+
+       fmt = find_format(f);
+       if (!fmt) {
+               f->fmt.pix.pixelformat = formats[0].fourcc;
+               fmt = find_format(f);
+       }
+       if (!(fmt->types & MEM2MEM_OUTPUT)) {
+               v4l2_err(&ctx->dev->v4l2_dev,
+                        "Fourcc format (0x%08x) invalid.\n",
+                        f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       if (!f->fmt.pix.colorspace)
+               f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+
+       return pxp_try_fmt(f, fmt);
+}
+
+static int pxp_s_fmt(struct pxp_ctx *ctx, struct v4l2_format *f)
+{
+       struct pxp_q_data *q_data;
+       struct vb2_queue *vq;
+
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       q_data = get_q_data(ctx, f->type);
+       if (!q_data)
+               return -EINVAL;
+
+       if (vb2_is_busy(vq)) {
+               v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
+               return -EBUSY;
+       }
+
+       q_data->fmt             = find_format(f);
+       q_data->width           = f->fmt.pix.width;
+       q_data->height          = f->fmt.pix.height;
+       q_data->bytesperline    = f->fmt.pix.bytesperline;
+       q_data->sizeimage       = f->fmt.pix.sizeimage;
+
+       dprintk(ctx->dev,
+               "Setting format for type %d, wxh: %dx%d, fmt: %d\n",
+               f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
+
+       return 0;
+}
+
+static int pxp_s_fmt_vid_cap(struct file *file, void *priv,
+                            struct v4l2_format *f)
+{
+       struct pxp_ctx *ctx = file2ctx(file);
+       int ret;
+
+       ret = pxp_try_fmt_vid_cap(file, priv, f);
+       if (ret)
+               return ret;
+
+       ret = pxp_s_fmt(file2ctx(file), f);
+       if (ret)
+               return ret;
+
+       ctx->q_data[V4L2_M2M_DST].ycbcr_enc = f->fmt.pix.ycbcr_enc;
+       ctx->q_data[V4L2_M2M_DST].quant = f->fmt.pix.quantization;
+
+       return 0;
+}
+
+static int pxp_s_fmt_vid_out(struct file *file, void *priv,
+                            struct v4l2_format *f)
+{
+       struct pxp_ctx *ctx = file2ctx(file);
+       int ret;
+
+       ret = pxp_try_fmt_vid_out(file, priv, f);
+       if (ret)
+               return ret;
+
+       ret = pxp_s_fmt(file2ctx(file), f);
+       if (ret)
+               return ret;
+
+       ctx->colorspace = f->fmt.pix.colorspace;
+       ctx->xfer_func = f->fmt.pix.xfer_func;
+       ctx->q_data[V4L2_M2M_SRC].ycbcr_enc = f->fmt.pix.ycbcr_enc;
+       ctx->q_data[V4L2_M2M_SRC].quant = f->fmt.pix.quantization;
+
+       pxp_fixup_colorimetry_cap(ctx, ctx->q_data[V4L2_M2M_DST].fmt->fourcc,
+                                 &ctx->q_data[V4L2_M2M_DST].ycbcr_enc,
+                                 &ctx->q_data[V4L2_M2M_DST].quant);
+
+       return 0;
+}
+
+static u8 pxp_degrees_to_rot_mode(u32 degrees)
+{
+       switch (degrees) {
+       case 90:
+               return BV_PXP_CTRL_ROTATE0__ROT_90;
+       case 180:
+               return BV_PXP_CTRL_ROTATE0__ROT_180;
+       case 270:
+               return BV_PXP_CTRL_ROTATE0__ROT_270;
+       case 0:
+       default:
+               return BV_PXP_CTRL_ROTATE0__ROT_0;
+       }
+}
+
+static int pxp_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct pxp_ctx *ctx =
+               container_of(ctrl->handler, struct pxp_ctx, hdl);
+
+       switch (ctrl->id) {
+       case V4L2_CID_HFLIP:
+               if (ctrl->val)
+                       ctx->mode |= MEM2MEM_HFLIP;
+               else
+                       ctx->mode &= ~MEM2MEM_HFLIP;
+               break;
+
+       case V4L2_CID_VFLIP:
+               if (ctrl->val)
+                       ctx->mode |= MEM2MEM_VFLIP;
+               else
+                       ctx->mode &= ~MEM2MEM_VFLIP;
+               break;
+
+       case V4L2_CID_ROTATE:
+               ctx->rotation = pxp_degrees_to_rot_mode(ctrl->val);
+               break;
+
+       case V4L2_CID_ALPHA_COMPONENT:
+               ctx->alpha_component = ctrl->val;
+               break;
+
+       default:
+               v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct v4l2_ctrl_ops pxp_ctrl_ops = {
+       .s_ctrl = pxp_s_ctrl,
+};
+
+static const struct v4l2_ioctl_ops pxp_ioctl_ops = {
+       .vidioc_querycap        = pxp_querycap,
+
+       .vidioc_enum_fmt_vid_cap = pxp_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap   = pxp_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = pxp_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap   = pxp_s_fmt_vid_cap,
+
+       .vidioc_enum_fmt_vid_out = pxp_enum_fmt_vid_out,
+       .vidioc_g_fmt_vid_out   = pxp_g_fmt_vid_out,
+       .vidioc_try_fmt_vid_out = pxp_try_fmt_vid_out,
+       .vidioc_s_fmt_vid_out   = pxp_s_fmt_vid_out,
+
+       .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_subscribe_event = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+/*
+ * Queue operations
+ */
+static int pxp_queue_setup(struct vb2_queue *vq,
+                          unsigned int *nbuffers, unsigned int *nplanes,
+                          unsigned int sizes[], struct device *alloc_devs[])
+{
+       struct pxp_ctx *ctx = vb2_get_drv_priv(vq);
+       struct pxp_q_data *q_data;
+       unsigned int size, count = *nbuffers;
+
+       q_data = get_q_data(ctx, vq->type);
+
+       size = q_data->sizeimage;
+
+       *nbuffers = count;
+
+       if (*nplanes)
+               return sizes[0] < size ? -EINVAL : 0;
+
+       *nplanes = 1;
+       sizes[0] = size;
+
+       dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
+
+       return 0;
+}
+
+static int pxp_buf_prepare(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct pxp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct pxp_dev *dev = ctx->dev;
+       struct pxp_q_data *q_data;
+
+       dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
+
+       q_data = get_q_data(ctx, vb->vb2_queue->type);
+       if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+               if (vbuf->field == V4L2_FIELD_ANY)
+                       vbuf->field = V4L2_FIELD_NONE;
+               if (vbuf->field != V4L2_FIELD_NONE) {
+                       dprintk(dev, "%s field isn't supported\n", __func__);
+                       return -EINVAL;
+               }
+       }
+
+       if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
+               dprintk(dev, "%s data will not fit into plane (%lu < %lu)\n",
+                       __func__, vb2_plane_size(vb, 0),
+                       (long)q_data->sizeimage);
+               return -EINVAL;
+       }
+
+       vb2_set_plane_payload(vb, 0, q_data->sizeimage);
+
+       return 0;
+}
+
+static void pxp_buf_queue(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct pxp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+}
+
+static int pxp_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct pxp_ctx *ctx = vb2_get_drv_priv(q);
+       struct pxp_q_data *q_data = get_q_data(ctx, q->type);
+
+       q_data->sequence = 0;
+       return 0;
+}
+
+static void pxp_stop_streaming(struct vb2_queue *q)
+{
+       struct pxp_ctx *ctx = vb2_get_drv_priv(q);
+       struct vb2_v4l2_buffer *vbuf;
+       unsigned long flags;
+
+       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;
+               spin_lock_irqsave(&ctx->dev->irqlock, flags);
+               v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+               spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
+       }
+}
+
+static const struct vb2_ops pxp_qops = {
+       .queue_setup     = pxp_queue_setup,
+       .buf_prepare     = pxp_buf_prepare,
+       .buf_queue       = pxp_buf_queue,
+       .start_streaming = pxp_start_streaming,
+       .stop_streaming  = pxp_stop_streaming,
+       .wait_prepare    = vb2_ops_wait_prepare,
+       .wait_finish     = vb2_ops_wait_finish,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+                     struct vb2_queue *dst_vq)
+{
+       struct pxp_ctx *ctx = priv;
+       int ret;
+
+       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+       src_vq->drv_priv = ctx;
+       src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       src_vq->ops = &pxp_qops;
+       src_vq->mem_ops = &vb2_dma_contig_memops;
+       src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       src_vq->lock = &ctx->dev->dev_mutex;
+       src_vq->dev = ctx->dev->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_DMABUF;
+       dst_vq->drv_priv = ctx;
+       dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       dst_vq->ops = &pxp_qops;
+       dst_vq->mem_ops = &vb2_dma_contig_memops;
+       dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       dst_vq->lock = &ctx->dev->dev_mutex;
+       dst_vq->dev = ctx->dev->v4l2_dev.dev;
+
+       return vb2_queue_init(dst_vq);
+}
+
+/*
+ * File operations
+ */
+static int pxp_open(struct file *file)
+{
+       struct pxp_dev *dev = video_drvdata(file);
+       struct pxp_ctx *ctx = NULL;
+       struct v4l2_ctrl_handler *hdl;
+       int rc = 0;
+
+       if (mutex_lock_interruptible(&dev->dev_mutex))
+               return -ERESTARTSYS;
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx) {
+               rc = -ENOMEM;
+               goto open_unlock;
+       }
+
+       v4l2_fh_init(&ctx->fh, video_devdata(file));
+       file->private_data = &ctx->fh;
+       ctx->dev = dev;
+       hdl = &ctx->hdl;
+       v4l2_ctrl_handler_init(hdl, 4);
+       v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_ROTATE, 0, 270, 90, 0);
+       v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
+                         0, 255, 1, 255);
+       if (hdl->error) {
+               rc = hdl->error;
+               v4l2_ctrl_handler_free(hdl);
+               kfree(ctx);
+               goto open_unlock;
+       }
+       ctx->fh.ctrl_handler = hdl;
+       v4l2_ctrl_handler_setup(hdl);
+
+       ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0];
+       ctx->q_data[V4L2_M2M_SRC].width = 640;
+       ctx->q_data[V4L2_M2M_SRC].height = 480;
+       ctx->q_data[V4L2_M2M_SRC].bytesperline =
+               pxp_bytesperline(&formats[0], 640);
+       ctx->q_data[V4L2_M2M_SRC].sizeimage =
+               pxp_sizeimage(&formats[0], 640, 480);
+       ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
+       ctx->colorspace = V4L2_COLORSPACE_REC709;
+
+       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
+
+       if (IS_ERR(ctx->fh.m2m_ctx)) {
+               rc = PTR_ERR(ctx->fh.m2m_ctx);
+
+               v4l2_ctrl_handler_free(hdl);
+               v4l2_fh_exit(&ctx->fh);
+               kfree(ctx);
+               goto open_unlock;
+       }
+
+       v4l2_fh_add(&ctx->fh);
+       atomic_inc(&dev->num_inst);
+
+       dprintk(dev, "Created instance: %p, m2m_ctx: %p\n",
+               ctx, ctx->fh.m2m_ctx);
+
+open_unlock:
+       mutex_unlock(&dev->dev_mutex);
+       return rc;
+}
+
+static int pxp_release(struct file *file)
+{
+       struct pxp_dev *dev = video_drvdata(file);
+       struct pxp_ctx *ctx = file2ctx(file);
+
+       dprintk(dev, "Releasing instance %p\n", ctx);
+
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       v4l2_ctrl_handler_free(&ctx->hdl);
+       mutex_lock(&dev->dev_mutex);
+       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+       mutex_unlock(&dev->dev_mutex);
+       kfree(ctx);
+
+       atomic_dec(&dev->num_inst);
+
+       return 0;
+}
+
+static const struct v4l2_file_operations pxp_fops = {
+       .owner          = THIS_MODULE,
+       .open           = pxp_open,
+       .release        = pxp_release,
+       .poll           = v4l2_m2m_fop_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = v4l2_m2m_fop_mmap,
+};
+
+static const struct video_device pxp_videodev = {
+       .name           = MEM2MEM_NAME,
+       .vfl_dir        = VFL_DIR_M2M,
+       .fops           = &pxp_fops,
+       .device_caps    = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
+       .ioctl_ops      = &pxp_ioctl_ops,
+       .minor          = -1,
+       .release        = video_device_release_empty,
+};
+
+static const struct v4l2_m2m_ops m2m_ops = {
+       .device_run     = pxp_device_run,
+       .job_ready      = pxp_job_ready,
+       .job_abort      = pxp_job_abort,
+};
+
+static int pxp_soft_reset(struct pxp_dev *dev)
+{
+       int ret;
+       u32 val;
+
+       writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_CLR);
+       writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_CLR);
+
+       writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_SET);
+
+       ret = readl_poll_timeout(dev->mmio + HW_PXP_CTRL, val,
+                                val & BM_PXP_CTRL_CLKGATE, 0, 100);
+       if (ret < 0)
+               return ret;
+
+       writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_CLR);
+       writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_CLR);
+
+       return 0;
+}
+
+static int pxp_probe(struct platform_device *pdev)
+{
+       struct pxp_dev *dev;
+       struct video_device *vfd;
+       int irq;
+       int ret;
+
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       dev->clk = devm_clk_get(&pdev->dev, "axi");
+       if (IS_ERR(dev->clk)) {
+               ret = PTR_ERR(dev->clk);
+               dev_err(&pdev->dev, "Failed to get clk: %d\n", ret);
+               return ret;
+       }
+
+       dev->mmio = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(dev->mmio))
+               return PTR_ERR(dev->mmio);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       spin_lock_init(&dev->irqlock);
+
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, pxp_irq_handler,
+                       IRQF_ONESHOT, dev_name(&pdev->dev), dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
+               return ret;
+       }
+
+       ret = clk_prepare_enable(dev->clk);
+       if (ret < 0)
+               return ret;
+
+       ret = pxp_soft_reset(dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "PXP reset timeout: %d\n", ret);
+               goto err_clk;
+       }
+
+       ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+       if (ret)
+               goto err_clk;
+
+       atomic_set(&dev->num_inst, 0);
+       mutex_init(&dev->dev_mutex);
+
+       dev->vfd = pxp_videodev;
+       vfd = &dev->vfd;
+       vfd->lock = &dev->dev_mutex;
+       vfd->v4l2_dev = &dev->v4l2_dev;
+
+       video_set_drvdata(vfd, dev);
+       snprintf(vfd->name, sizeof(vfd->name), "%s", pxp_videodev.name);
+       v4l2_info(&dev->v4l2_dev,
+                       "Device registered as /dev/video%d\n", vfd->num);
+
+       platform_set_drvdata(pdev, dev);
+
+       dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
+       if (IS_ERR(dev->m2m_dev)) {
+               v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
+               ret = PTR_ERR(dev->m2m_dev);
+               goto err_v4l2;
+       }
+
+       ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+               goto err_m2m;
+       }
+
+       return 0;
+
+err_m2m:
+       v4l2_m2m_release(dev->m2m_dev);
+err_v4l2:
+       v4l2_device_unregister(&dev->v4l2_dev);
+err_clk:
+       clk_disable_unprepare(dev->clk);
+
+       return ret;
+}
+
+static int pxp_remove(struct platform_device *pdev)
+{
+       struct pxp_dev *dev = platform_get_drvdata(pdev);
+
+       writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_SET);
+       writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_SET);
+
+       clk_disable_unprepare(dev->clk);
+
+       v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
+       video_unregister_device(&dev->vfd);
+       v4l2_m2m_release(dev->m2m_dev);
+       v4l2_device_unregister(&dev->v4l2_dev);
+
+       return 0;
+}
+
+static const struct of_device_id pxp_dt_ids[] = {
+       { .compatible = "fsl,imx6ull-pxp", .data = NULL },
+       { },
+};
+MODULE_DEVICE_TABLE(of, pxp_dt_ids);
+
+static struct platform_driver pxp_driver = {
+       .probe          = pxp_probe,
+       .remove         = pxp_remove,
+       .driver         = {
+               .name   = MEM2MEM_NAME,
+               .of_match_table = pxp_dt_ids,
+       },
+};
+
+module_platform_driver(pxp_driver);
+
+MODULE_DESCRIPTION("i.MX PXP mem2mem scaler/CSC/rotator");
+MODULE_AUTHOR("Philipp Zabel <kernel@pengutronix.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/nxp/imx-pxp.h b/drivers/media/platform/nxp/imx-pxp.h
new file mode 100644 (file)
index 0000000..44f95c7
--- /dev/null
@@ -0,0 +1,1685 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Freescale PXP Register Definitions
+ *
+ * based on pxp_dma_v3.h, Xml Revision: 1.77, Template Revision: 1.3
+ *
+ * Copyright 2014-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+#ifndef __IMX_PXP_H__
+#define __IMX_PXP_H__
+
+#define HW_PXP_CTRL    (0x00000000)
+#define HW_PXP_CTRL_SET        (0x00000004)
+#define HW_PXP_CTRL_CLR        (0x00000008)
+#define HW_PXP_CTRL_TOG        (0x0000000c)
+
+#define BM_PXP_CTRL_SFTRST 0x80000000
+#define BF_PXP_CTRL_SFTRST(v) \
+       (((v) << 31) & BM_PXP_CTRL_SFTRST)
+#define BM_PXP_CTRL_CLKGATE 0x40000000
+#define BF_PXP_CTRL_CLKGATE(v)  \
+       (((v) << 30) & BM_PXP_CTRL_CLKGATE)
+#define BM_PXP_CTRL_RSVD4 0x20000000
+#define BF_PXP_CTRL_RSVD4(v)  \
+       (((v) << 29) & BM_PXP_CTRL_RSVD4)
+#define BM_PXP_CTRL_EN_REPEAT 0x10000000
+#define BF_PXP_CTRL_EN_REPEAT(v)  \
+       (((v) << 28) & BM_PXP_CTRL_EN_REPEAT)
+#define BM_PXP_CTRL_ENABLE_ROTATE1 0x08000000
+#define BF_PXP_CTRL_ENABLE_ROTATE1(v)  \
+       (((v) << 27) & BM_PXP_CTRL_ENABLE_ROTATE1)
+#define BM_PXP_CTRL_ENABLE_ROTATE0 0x04000000
+#define BF_PXP_CTRL_ENABLE_ROTATE0(v)  \
+       (((v) << 26) & BM_PXP_CTRL_ENABLE_ROTATE0)
+#define BM_PXP_CTRL_ENABLE_LUT 0x02000000
+#define BF_PXP_CTRL_ENABLE_LUT(v)  \
+       (((v) << 25) & BM_PXP_CTRL_ENABLE_LUT)
+#define BM_PXP_CTRL_ENABLE_CSC2 0x01000000
+#define BF_PXP_CTRL_ENABLE_CSC2(v)  \
+       (((v) << 24) & BM_PXP_CTRL_ENABLE_CSC2)
+#define BM_PXP_CTRL_BLOCK_SIZE 0x00800000
+#define BF_PXP_CTRL_BLOCK_SIZE(v)  \
+       (((v) << 23) & BM_PXP_CTRL_BLOCK_SIZE)
+#define BV_PXP_CTRL_BLOCK_SIZE__8X8   0x0
+#define BV_PXP_CTRL_BLOCK_SIZE__16X16 0x1
+#define BM_PXP_CTRL_RSVD1 0x00400000
+#define BF_PXP_CTRL_RSVD1(v)  \
+       (((v) << 22) & BM_PXP_CTRL_RSVD1)
+#define BM_PXP_CTRL_ENABLE_ALPHA_B 0x00200000
+#define BF_PXP_CTRL_ENABLE_ALPHA_B(v)  \
+       (((v) << 21) & BM_PXP_CTRL_ENABLE_ALPHA_B)
+#define BM_PXP_CTRL_ENABLE_INPUT_FETCH_STORE 0x00100000
+#define BF_PXP_CTRL_ENABLE_INPUT_FETCH_STORE(v)  \
+       (((v) << 20) & BM_PXP_CTRL_ENABLE_INPUT_FETCH_STORE)
+#define BM_PXP_CTRL_ENABLE_WFE_B 0x00080000
+#define BF_PXP_CTRL_ENABLE_WFE_B(v)  \
+       (((v) << 19) & BM_PXP_CTRL_ENABLE_WFE_B)
+#define BM_PXP_CTRL_ENABLE_WFE_A 0x00040000
+#define BF_PXP_CTRL_ENABLE_WFE_A(v)  \
+       (((v) << 18) & BM_PXP_CTRL_ENABLE_WFE_A)
+#define BM_PXP_CTRL_ENABLE_DITHER 0x00020000
+#define BF_PXP_CTRL_ENABLE_DITHER(v)  \
+       (((v) << 17) & BM_PXP_CTRL_ENABLE_DITHER)
+#define BM_PXP_CTRL_ENABLE_PS_AS_OUT 0x00010000
+#define BF_PXP_CTRL_ENABLE_PS_AS_OUT(v)  \
+       (((v) << 16) & BM_PXP_CTRL_ENABLE_PS_AS_OUT)
+#define BM_PXP_CTRL_VFLIP1 0x00008000
+#define BF_PXP_CTRL_VFLIP1(v)  \
+       (((v) << 15) & BM_PXP_CTRL_VFLIP1)
+#define BM_PXP_CTRL_HFLIP1 0x00004000
+#define BF_PXP_CTRL_HFLIP1(v)  \
+       (((v) << 14) & BM_PXP_CTRL_HFLIP1)
+#define BP_PXP_CTRL_ROTATE1      12
+#define BM_PXP_CTRL_ROTATE1 0x00003000
+#define BF_PXP_CTRL_ROTATE1(v)  \
+       (((v) << 12) & BM_PXP_CTRL_ROTATE1)
+#define BV_PXP_CTRL_ROTATE1__ROT_0   0x0
+#define BV_PXP_CTRL_ROTATE1__ROT_90  0x1
+#define BV_PXP_CTRL_ROTATE1__ROT_180 0x2
+#define BV_PXP_CTRL_ROTATE1__ROT_270 0x3
+#define BM_PXP_CTRL_VFLIP0 0x00000800
+#define BF_PXP_CTRL_VFLIP0(v)  \
+       (((v) << 11) & BM_PXP_CTRL_VFLIP0)
+#define BM_PXP_CTRL_HFLIP0 0x00000400
+#define BF_PXP_CTRL_HFLIP0(v)  \
+       (((v) << 10) & BM_PXP_CTRL_HFLIP0)
+#define BP_PXP_CTRL_ROTATE0      8
+#define BM_PXP_CTRL_ROTATE0 0x00000300
+#define BF_PXP_CTRL_ROTATE0(v)  \
+       (((v) << 8) & BM_PXP_CTRL_ROTATE0)
+#define BV_PXP_CTRL_ROTATE0__ROT_0   0x0
+#define BV_PXP_CTRL_ROTATE0__ROT_90  0x1
+#define BV_PXP_CTRL_ROTATE0__ROT_180 0x2
+#define BV_PXP_CTRL_ROTATE0__ROT_270 0x3
+#define BP_PXP_CTRL_RSVD0      6
+#define BM_PXP_CTRL_RSVD0 0x000000C0
+#define BF_PXP_CTRL_RSVD0(v)  \
+       (((v) << 6) & BM_PXP_CTRL_RSVD0)
+#define BM_PXP_CTRL_HANDSHAKE_ABORT_SKIP 0x00000020
+#define BF_PXP_CTRL_HANDSHAKE_ABORT_SKIP(v)  \
+       (((v) << 5) & BM_PXP_CTRL_HANDSHAKE_ABORT_SKIP)
+#define BM_PXP_CTRL_ENABLE_LCD0_HANDSHAKE 0x00000010
+#define BF_PXP_CTRL_ENABLE_LCD0_HANDSHAKE(v)  \
+       (((v) << 4) & BM_PXP_CTRL_ENABLE_LCD0_HANDSHAKE)
+#define BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE 0x00000008
+#define BF_PXP_CTRL_LUT_DMA_IRQ_ENABLE(v)  \
+       (((v) << 3) & BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE)
+#define BM_PXP_CTRL_NEXT_IRQ_ENABLE 0x00000004
+#define BF_PXP_CTRL_NEXT_IRQ_ENABLE(v)  \
+       (((v) << 2) & BM_PXP_CTRL_NEXT_IRQ_ENABLE)
+#define BM_PXP_CTRL_IRQ_ENABLE 0x00000002
+#define BF_PXP_CTRL_IRQ_ENABLE(v)  \
+       (((v) << 1) & BM_PXP_CTRL_IRQ_ENABLE)
+#define BM_PXP_CTRL_ENABLE 0x00000001
+#define BF_PXP_CTRL_ENABLE(v)  \
+       (((v) << 0) & BM_PXP_CTRL_ENABLE)
+
+#define HW_PXP_STAT    (0x00000010)
+#define HW_PXP_STAT_SET        (0x00000014)
+#define HW_PXP_STAT_CLR        (0x00000018)
+#define HW_PXP_STAT_TOG        (0x0000001c)
+
+#define BP_PXP_STAT_BLOCKX      24
+#define BM_PXP_STAT_BLOCKX 0xFF000000
+#define BF_PXP_STAT_BLOCKX(v) \
+       (((v) << 24) & BM_PXP_STAT_BLOCKX)
+#define BP_PXP_STAT_BLOCKY      16
+#define BM_PXP_STAT_BLOCKY 0x00FF0000
+#define BF_PXP_STAT_BLOCKY(v)  \
+       (((v) << 16) & BM_PXP_STAT_BLOCKY)
+#define BP_PXP_STAT_AXI_ERROR_ID_1      12
+#define BM_PXP_STAT_AXI_ERROR_ID_1 0x0000F000
+#define BF_PXP_STAT_AXI_ERROR_ID_1(v)  \
+       (((v) << 12) & BM_PXP_STAT_AXI_ERROR_ID_1)
+#define BM_PXP_STAT_RSVD2 0x00000800
+#define BF_PXP_STAT_RSVD2(v)  \
+       (((v) << 11) & BM_PXP_STAT_RSVD2)
+#define BM_PXP_STAT_AXI_READ_ERROR_1 0x00000400
+#define BF_PXP_STAT_AXI_READ_ERROR_1(v)  \
+       (((v) << 10) & BM_PXP_STAT_AXI_READ_ERROR_1)
+#define BM_PXP_STAT_AXI_WRITE_ERROR_1 0x00000200
+#define BF_PXP_STAT_AXI_WRITE_ERROR_1(v)  \
+       (((v) << 9) & BM_PXP_STAT_AXI_WRITE_ERROR_1)
+#define BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ 0x00000100
+#define BF_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ(v)  \
+       (((v) << 8) & BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ)
+#define BP_PXP_STAT_AXI_ERROR_ID_0      4
+#define BM_PXP_STAT_AXI_ERROR_ID_0 0x000000F0
+#define BF_PXP_STAT_AXI_ERROR_ID_0(v)  \
+       (((v) << 4) & BM_PXP_STAT_AXI_ERROR_ID_0)
+#define BM_PXP_STAT_NEXT_IRQ 0x00000008
+#define BF_PXP_STAT_NEXT_IRQ(v)  \
+       (((v) << 3) & BM_PXP_STAT_NEXT_IRQ)
+#define BM_PXP_STAT_AXI_READ_ERROR_0 0x00000004
+#define BF_PXP_STAT_AXI_READ_ERROR_0(v)  \
+       (((v) << 2) & BM_PXP_STAT_AXI_READ_ERROR_0)
+#define BM_PXP_STAT_AXI_WRITE_ERROR_0 0x00000002
+#define BF_PXP_STAT_AXI_WRITE_ERROR_0(v)  \
+       (((v) << 1) & BM_PXP_STAT_AXI_WRITE_ERROR_0)
+#define BM_PXP_STAT_IRQ0 0x00000001
+#define BF_PXP_STAT_IRQ0(v)  \
+       (((v) << 0) & BM_PXP_STAT_IRQ0)
+
+#define HW_PXP_OUT_CTRL        (0x00000020)
+#define HW_PXP_OUT_CTRL_SET    (0x00000024)
+#define HW_PXP_OUT_CTRL_CLR    (0x00000028)
+#define HW_PXP_OUT_CTRL_TOG    (0x0000002c)
+
+#define BP_PXP_OUT_CTRL_ALPHA      24
+#define BM_PXP_OUT_CTRL_ALPHA 0xFF000000
+#define BF_PXP_OUT_CTRL_ALPHA(v) \
+       (((v) << 24) & BM_PXP_OUT_CTRL_ALPHA)
+#define BM_PXP_OUT_CTRL_ALPHA_OUTPUT 0x00800000
+#define BF_PXP_OUT_CTRL_ALPHA_OUTPUT(v)  \
+       (((v) << 23) & BM_PXP_OUT_CTRL_ALPHA_OUTPUT)
+#define BP_PXP_OUT_CTRL_RSVD1      10
+#define BM_PXP_OUT_CTRL_RSVD1 0x007FFC00
+#define BF_PXP_OUT_CTRL_RSVD1(v)  \
+       (((v) << 10) & BM_PXP_OUT_CTRL_RSVD1)
+#define BP_PXP_OUT_CTRL_INTERLACED_OUTPUT      8
+#define BM_PXP_OUT_CTRL_INTERLACED_OUTPUT 0x00000300
+#define BF_PXP_OUT_CTRL_INTERLACED_OUTPUT(v)  \
+       (((v) << 8) & BM_PXP_OUT_CTRL_INTERLACED_OUTPUT)
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__PROGRESSIVE 0x0
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD0      0x1
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD1      0x2
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__INTERLACED  0x3
+#define BP_PXP_OUT_CTRL_RSVD0      5
+#define BM_PXP_OUT_CTRL_RSVD0 0x000000E0
+#define BF_PXP_OUT_CTRL_RSVD0(v)  \
+       (((v) << 5) & BM_PXP_OUT_CTRL_RSVD0)
+#define BP_PXP_OUT_CTRL_FORMAT      0
+#define BM_PXP_OUT_CTRL_FORMAT 0x0000001F
+#define BF_PXP_OUT_CTRL_FORMAT(v)  \
+       (((v) << 0) & BM_PXP_OUT_CTRL_FORMAT)
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB8888  0x0
+#define BV_PXP_OUT_CTRL_FORMAT__RGB888    0x4
+#define BV_PXP_OUT_CTRL_FORMAT__RGB888P   0x5
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB1555  0x8
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB4444  0x9
+#define BV_PXP_OUT_CTRL_FORMAT__RGB555    0xC
+#define BV_PXP_OUT_CTRL_FORMAT__RGB444    0xD
+#define BV_PXP_OUT_CTRL_FORMAT__RGB565    0xE
+#define BV_PXP_OUT_CTRL_FORMAT__YUV1P444  0x10
+#define BV_PXP_OUT_CTRL_FORMAT__UYVY1P422 0x12
+#define BV_PXP_OUT_CTRL_FORMAT__VYUY1P422 0x13
+#define BV_PXP_OUT_CTRL_FORMAT__Y8     0x14
+#define BV_PXP_OUT_CTRL_FORMAT__Y4     0x15
+#define BV_PXP_OUT_CTRL_FORMAT__YUV2P422  0x18
+#define BV_PXP_OUT_CTRL_FORMAT__YUV2P420  0x19
+#define BV_PXP_OUT_CTRL_FORMAT__YVU2P422  0x1A
+#define BV_PXP_OUT_CTRL_FORMAT__YVU2P420  0x1B
+
+#define HW_PXP_OUT_BUF (0x00000030)
+
+#define BP_PXP_OUT_BUF_ADDR      0
+#define BM_PXP_OUT_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_OUT_BUF_ADDR(v)   (v)
+
+#define HW_PXP_OUT_BUF2        (0x00000040)
+
+#define BP_PXP_OUT_BUF2_ADDR      0
+#define BM_PXP_OUT_BUF2_ADDR 0xFFFFFFFF
+#define BF_PXP_OUT_BUF2_ADDR(v)   (v)
+
+#define HW_PXP_OUT_PITCH       (0x00000050)
+
+#define BP_PXP_OUT_PITCH_RSVD      16
+#define BM_PXP_OUT_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_OUT_PITCH_RSVD(v) \
+       (((v) << 16) & BM_PXP_OUT_PITCH_RSVD)
+#define BP_PXP_OUT_PITCH_PITCH      0
+#define BM_PXP_OUT_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_OUT_PITCH_PITCH(v)  \
+       (((v) << 0) & BM_PXP_OUT_PITCH_PITCH)
+
+#define HW_PXP_OUT_LRC (0x00000060)
+
+#define BP_PXP_OUT_LRC_RSVD1      30
+#define BM_PXP_OUT_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_LRC_RSVD1(v) \
+       (((v) << 30) & BM_PXP_OUT_LRC_RSVD1)
+#define BP_PXP_OUT_LRC_X      16
+#define BM_PXP_OUT_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_LRC_X(v)  \
+       (((v) << 16) & BM_PXP_OUT_LRC_X)
+#define BP_PXP_OUT_LRC_RSVD0      14
+#define BM_PXP_OUT_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_LRC_RSVD0(v)  \
+       (((v) << 14) & BM_PXP_OUT_LRC_RSVD0)
+#define BP_PXP_OUT_LRC_Y      0
+#define BM_PXP_OUT_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_LRC_Y(v)  \
+       (((v) << 0) & BM_PXP_OUT_LRC_Y)
+
+#define HW_PXP_OUT_PS_ULC      (0x00000070)
+
+#define BP_PXP_OUT_PS_ULC_RSVD1      30
+#define BM_PXP_OUT_PS_ULC_RSVD1 0xC0000000
+#define BF_PXP_OUT_PS_ULC_RSVD1(v) \
+       (((v) << 30) & BM_PXP_OUT_PS_ULC_RSVD1)
+#define BP_PXP_OUT_PS_ULC_X      16
+#define BM_PXP_OUT_PS_ULC_X 0x3FFF0000
+#define BF_PXP_OUT_PS_ULC_X(v)  \
+       (((v) << 16) & BM_PXP_OUT_PS_ULC_X)
+#define BP_PXP_OUT_PS_ULC_RSVD0      14
+#define BM_PXP_OUT_PS_ULC_RSVD0 0x0000C000
+#define BF_PXP_OUT_PS_ULC_RSVD0(v)  \
+       (((v) << 14) & BM_PXP_OUT_PS_ULC_RSVD0)
+#define BP_PXP_OUT_PS_ULC_Y      0
+#define BM_PXP_OUT_PS_ULC_Y 0x00003FFF
+#define BF_PXP_OUT_PS_ULC_Y(v)  \
+       (((v) << 0) & BM_PXP_OUT_PS_ULC_Y)
+
+#define HW_PXP_OUT_PS_LRC      (0x00000080)
+
+#define BP_PXP_OUT_PS_LRC_RSVD1      30
+#define BM_PXP_OUT_PS_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_PS_LRC_RSVD1(v) \
+       (((v) << 30) & BM_PXP_OUT_PS_LRC_RSVD1)
+#define BP_PXP_OUT_PS_LRC_X      16
+#define BM_PXP_OUT_PS_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_PS_LRC_X(v)  \
+       (((v) << 16) & BM_PXP_OUT_PS_LRC_X)
+#define BP_PXP_OUT_PS_LRC_RSVD0      14
+#define BM_PXP_OUT_PS_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_PS_LRC_RSVD0(v)  \
+       (((v) << 14) & BM_PXP_OUT_PS_LRC_RSVD0)
+#define BP_PXP_OUT_PS_LRC_Y      0
+#define BM_PXP_OUT_PS_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_PS_LRC_Y(v)  \
+       (((v) << 0) & BM_PXP_OUT_PS_LRC_Y)
+
+#define HW_PXP_OUT_AS_ULC      (0x00000090)
+
+#define BP_PXP_OUT_AS_ULC_RSVD1      30
+#define BM_PXP_OUT_AS_ULC_RSVD1 0xC0000000
+#define BF_PXP_OUT_AS_ULC_RSVD1(v) \
+       (((v) << 30) & BM_PXP_OUT_AS_ULC_RSVD1)
+#define BP_PXP_OUT_AS_ULC_X      16
+#define BM_PXP_OUT_AS_ULC_X 0x3FFF0000
+#define BF_PXP_OUT_AS_ULC_X(v)  \
+       (((v) << 16) & BM_PXP_OUT_AS_ULC_X)
+#define BP_PXP_OUT_AS_ULC_RSVD0      14
+#define BM_PXP_OUT_AS_ULC_RSVD0 0x0000C000
+#define BF_PXP_OUT_AS_ULC_RSVD0(v)  \
+       (((v) << 14) & BM_PXP_OUT_AS_ULC_RSVD0)
+#define BP_PXP_OUT_AS_ULC_Y      0
+#define BM_PXP_OUT_AS_ULC_Y 0x00003FFF
+#define BF_PXP_OUT_AS_ULC_Y(v)  \
+       (((v) << 0) & BM_PXP_OUT_AS_ULC_Y)
+
+#define HW_PXP_OUT_AS_LRC      (0x000000a0)
+
+#define BP_PXP_OUT_AS_LRC_RSVD1      30
+#define BM_PXP_OUT_AS_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_AS_LRC_RSVD1(v) \
+       (((v) << 30) & BM_PXP_OUT_AS_LRC_RSVD1)
+#define BP_PXP_OUT_AS_LRC_X      16
+#define BM_PXP_OUT_AS_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_AS_LRC_X(v)  \
+       (((v) << 16) & BM_PXP_OUT_AS_LRC_X)
+#define BP_PXP_OUT_AS_LRC_RSVD0      14
+#define BM_PXP_OUT_AS_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_AS_LRC_RSVD0(v)  \
+       (((v) << 14) & BM_PXP_OUT_AS_LRC_RSVD0)
+#define BP_PXP_OUT_AS_LRC_Y      0
+#define BM_PXP_OUT_AS_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_AS_LRC_Y(v)  \
+       (((v) << 0) & BM_PXP_OUT_AS_LRC_Y)
+
+#define HW_PXP_PS_CTRL (0x000000b0)
+#define HW_PXP_PS_CTRL_SET     (0x000000b4)
+#define HW_PXP_PS_CTRL_CLR     (0x000000b8)
+#define HW_PXP_PS_CTRL_TOG     (0x000000bc)
+
+#define BP_PXP_PS_CTRL_RSVD1      12
+#define BM_PXP_PS_CTRL_RSVD1 0xFFFFF000
+#define BF_PXP_PS_CTRL_RSVD1(v) \
+       (((v) << 12) & BM_PXP_PS_CTRL_RSVD1)
+#define BP_PXP_PS_CTRL_DECX      10
+#define BM_PXP_PS_CTRL_DECX 0x00000C00
+#define BF_PXP_PS_CTRL_DECX(v)  \
+       (((v) << 10) & BM_PXP_PS_CTRL_DECX)
+#define BV_PXP_PS_CTRL_DECX__DISABLE 0x0
+#define BV_PXP_PS_CTRL_DECX__DECX2   0x1
+#define BV_PXP_PS_CTRL_DECX__DECX4   0x2
+#define BV_PXP_PS_CTRL_DECX__DECX8   0x3
+#define BP_PXP_PS_CTRL_DECY      8
+#define BM_PXP_PS_CTRL_DECY 0x00000300
+#define BF_PXP_PS_CTRL_DECY(v)  \
+       (((v) << 8) & BM_PXP_PS_CTRL_DECY)
+#define BV_PXP_PS_CTRL_DECY__DISABLE 0x0
+#define BV_PXP_PS_CTRL_DECY__DECY2   0x1
+#define BV_PXP_PS_CTRL_DECY__DECY4   0x2
+#define BV_PXP_PS_CTRL_DECY__DECY8   0x3
+#define BM_PXP_PS_CTRL_RSVD0 0x00000080
+#define BF_PXP_PS_CTRL_RSVD0(v)  \
+       (((v) << 7) & BM_PXP_PS_CTRL_RSVD0)
+#define BM_PXP_PS_CTRL_WB_SWAP 0x00000040
+#define BF_PXP_PS_CTRL_WB_SWAP(v)  \
+       (((v) << 6) & BM_PXP_PS_CTRL_WB_SWAP)
+#define BP_PXP_PS_CTRL_FORMAT      0
+#define BM_PXP_PS_CTRL_FORMAT 0x0000003F
+#define BF_PXP_PS_CTRL_FORMAT(v)  \
+       (((v) << 0) & BM_PXP_PS_CTRL_FORMAT)
+#define BV_PXP_PS_CTRL_FORMAT__RGB888    0x4
+#define BV_PXP_PS_CTRL_FORMAT__RGB555    0xC
+#define BV_PXP_PS_CTRL_FORMAT__RGB444    0xD
+#define BV_PXP_PS_CTRL_FORMAT__RGB565    0xE
+#define BV_PXP_PS_CTRL_FORMAT__YUV1P444  0x10
+#define BV_PXP_PS_CTRL_FORMAT__UYVY1P422 0x12
+#define BV_PXP_PS_CTRL_FORMAT__VYUY1P422 0x13
+#define BV_PXP_PS_CTRL_FORMAT__Y8      0x14
+#define BV_PXP_PS_CTRL_FORMAT__Y4      0x15
+#define BV_PXP_PS_CTRL_FORMAT__YUV2P422  0x18
+#define BV_PXP_PS_CTRL_FORMAT__YUV2P420  0x19
+#define BV_PXP_PS_CTRL_FORMAT__YVU2P422  0x1A
+#define BV_PXP_PS_CTRL_FORMAT__YVU2P420  0x1B
+#define BV_PXP_PS_CTRL_FORMAT__YUV422    0x1E
+#define BV_PXP_PS_CTRL_FORMAT__YUV420    0x1F
+
+#define HW_PXP_PS_BUF  (0x000000c0)
+
+#define BP_PXP_PS_BUF_ADDR      0
+#define BM_PXP_PS_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_BUF_ADDR(v)   (v)
+
+#define HW_PXP_PS_UBUF (0x000000d0)
+
+#define BP_PXP_PS_UBUF_ADDR      0
+#define BM_PXP_PS_UBUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_UBUF_ADDR(v)   (v)
+
+#define HW_PXP_PS_VBUF (0x000000e0)
+
+#define BP_PXP_PS_VBUF_ADDR      0
+#define BM_PXP_PS_VBUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_VBUF_ADDR(v)   (v)
+
+#define HW_PXP_PS_PITCH        (0x000000f0)
+
+#define BP_PXP_PS_PITCH_RSVD      16
+#define BM_PXP_PS_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_PS_PITCH_RSVD(v) \
+       (((v) << 16) & BM_PXP_PS_PITCH_RSVD)
+#define BP_PXP_PS_PITCH_PITCH      0
+#define BM_PXP_PS_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_PS_PITCH_PITCH(v)  \
+       (((v) << 0) & BM_PXP_PS_PITCH_PITCH)
+
+#define HW_PXP_PS_BACKGROUND_0 (0x00000100)
+
+#define BP_PXP_PS_BACKGROUND_0_RSVD      24
+#define BM_PXP_PS_BACKGROUND_0_RSVD 0xFF000000
+#define BF_PXP_PS_BACKGROUND_0_RSVD(v) \
+       (((v) << 24) & BM_PXP_PS_BACKGROUND_0_RSVD)
+#define BP_PXP_PS_BACKGROUND_0_COLOR      0
+#define BM_PXP_PS_BACKGROUND_0_COLOR 0x00FFFFFF
+#define BF_PXP_PS_BACKGROUND_0_COLOR(v)  \
+       (((v) << 0) & BM_PXP_PS_BACKGROUND_0_COLOR)
+
+#define HW_PXP_PS_SCALE        (0x00000110)
+
+#define BM_PXP_PS_SCALE_RSVD2 0x80000000
+#define BF_PXP_PS_SCALE_RSVD2(v) \
+       (((v) << 31) & BM_PXP_PS_SCALE_RSVD2)
+#define BP_PXP_PS_SCALE_YSCALE      16
+#define BM_PXP_PS_SCALE_YSCALE 0x7FFF0000
+#define BF_PXP_PS_SCALE_YSCALE(v)  \
+       (((v) << 16) & BM_PXP_PS_SCALE_YSCALE)
+#define BM_PXP_PS_SCALE_RSVD1 0x00008000
+#define BF_PXP_PS_SCALE_RSVD1(v)  \
+       (((v) << 15) & BM_PXP_PS_SCALE_RSVD1)
+#define BP_PXP_PS_SCALE_XSCALE      0
+#define BM_PXP_PS_SCALE_XSCALE 0x00007FFF
+#define BF_PXP_PS_SCALE_XSCALE(v)  \
+       (((v) << 0) & BM_PXP_PS_SCALE_XSCALE)
+
+#define HW_PXP_PS_OFFSET       (0x00000120)
+
+#define BP_PXP_PS_OFFSET_RSVD2      28
+#define BM_PXP_PS_OFFSET_RSVD2 0xF0000000
+#define BF_PXP_PS_OFFSET_RSVD2(v) \
+       (((v) << 28) & BM_PXP_PS_OFFSET_RSVD2)
+#define BP_PXP_PS_OFFSET_YOFFSET      16
+#define BM_PXP_PS_OFFSET_YOFFSET 0x0FFF0000
+#define BF_PXP_PS_OFFSET_YOFFSET(v)  \
+       (((v) << 16) & BM_PXP_PS_OFFSET_YOFFSET)
+#define BP_PXP_PS_OFFSET_RSVD1      12
+#define BM_PXP_PS_OFFSET_RSVD1 0x0000F000
+#define BF_PXP_PS_OFFSET_RSVD1(v)  \
+       (((v) << 12) & BM_PXP_PS_OFFSET_RSVD1)
+#define BP_PXP_PS_OFFSET_XOFFSET      0
+#define BM_PXP_PS_OFFSET_XOFFSET 0x00000FFF
+#define BF_PXP_PS_OFFSET_XOFFSET(v)  \
+       (((v) << 0) & BM_PXP_PS_OFFSET_XOFFSET)
+
+#define HW_PXP_PS_CLRKEYLOW_0  (0x00000130)
+
+#define BP_PXP_PS_CLRKEYLOW_0_RSVD1      24
+#define BM_PXP_PS_CLRKEYLOW_0_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYLOW_0_RSVD1(v) \
+       (((v) << 24) & BM_PXP_PS_CLRKEYLOW_0_RSVD1)
+#define BP_PXP_PS_CLRKEYLOW_0_PIXEL      0
+#define BM_PXP_PS_CLRKEYLOW_0_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYLOW_0_PIXEL(v)  \
+       (((v) << 0) & BM_PXP_PS_CLRKEYLOW_0_PIXEL)
+
+#define HW_PXP_PS_CLRKEYHIGH_0 (0x00000140)
+
+#define BP_PXP_PS_CLRKEYHIGH_0_RSVD1      24
+#define BM_PXP_PS_CLRKEYHIGH_0_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYHIGH_0_RSVD1(v) \
+       (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_0_RSVD1)
+#define BP_PXP_PS_CLRKEYHIGH_0_PIXEL      0
+#define BM_PXP_PS_CLRKEYHIGH_0_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYHIGH_0_PIXEL(v)  \
+       (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_0_PIXEL)
+
+#define HW_PXP_AS_CTRL (0x00000150)
+
+#define BP_PXP_AS_CTRL_RSVD1      22
+#define BM_PXP_AS_CTRL_RSVD1 0xFFC00000
+#define BF_PXP_AS_CTRL_RSVD1(v) \
+       (((v) << 22) & BM_PXP_AS_CTRL_RSVD1)
+#define BM_PXP_AS_CTRL_ALPHA1_INVERT 0x00200000
+#define BF_PXP_AS_CTRL_ALPHA1_INVERT(v)  \
+       (((v) << 21) & BM_PXP_AS_CTRL_ALPHA1_INVERT)
+#define BM_PXP_AS_CTRL_ALPHA0_INVERT 0x00100000
+#define BF_PXP_AS_CTRL_ALPHA0_INVERT(v)  \
+       (((v) << 20) & BM_PXP_AS_CTRL_ALPHA0_INVERT)
+#define BP_PXP_AS_CTRL_ROP      16
+#define BM_PXP_AS_CTRL_ROP 0x000F0000
+#define BF_PXP_AS_CTRL_ROP(v)  \
+       (((v) << 16) & BM_PXP_AS_CTRL_ROP)
+#define BV_PXP_AS_CTRL_ROP__MASKAS     0x0
+#define BV_PXP_AS_CTRL_ROP__MASKNOTAS  0x1
+#define BV_PXP_AS_CTRL_ROP__MASKASNOT  0x2
+#define BV_PXP_AS_CTRL_ROP__MERGEAS    0x3
+#define BV_PXP_AS_CTRL_ROP__MERGENOTAS 0x4
+#define BV_PXP_AS_CTRL_ROP__MERGEASNOT 0x5
+#define BV_PXP_AS_CTRL_ROP__NOTCOPYAS  0x6
+#define BV_PXP_AS_CTRL_ROP__NOT        0x7
+#define BV_PXP_AS_CTRL_ROP__NOTMASKAS  0x8
+#define BV_PXP_AS_CTRL_ROP__NOTMERGEAS 0x9
+#define BV_PXP_AS_CTRL_ROP__XORAS      0xA
+#define BV_PXP_AS_CTRL_ROP__NOTXORAS   0xB
+#define BP_PXP_AS_CTRL_ALPHA      8
+#define BM_PXP_AS_CTRL_ALPHA 0x0000FF00
+#define BF_PXP_AS_CTRL_ALPHA(v)  \
+       (((v) << 8) & BM_PXP_AS_CTRL_ALPHA)
+#define BP_PXP_AS_CTRL_FORMAT      4
+#define BM_PXP_AS_CTRL_FORMAT 0x000000F0
+#define BF_PXP_AS_CTRL_FORMAT(v)  \
+       (((v) << 4) & BM_PXP_AS_CTRL_FORMAT)
+#define BV_PXP_AS_CTRL_FORMAT__ARGB8888 0x0
+#define BV_PXP_AS_CTRL_FORMAT__RGBA8888 0x1
+#define BV_PXP_AS_CTRL_FORMAT__RGB888   0x4
+#define BV_PXP_AS_CTRL_FORMAT__ARGB1555 0x8
+#define BV_PXP_AS_CTRL_FORMAT__ARGB4444 0x9
+#define BV_PXP_AS_CTRL_FORMAT__RGB555   0xC
+#define BV_PXP_AS_CTRL_FORMAT__RGB444   0xD
+#define BV_PXP_AS_CTRL_FORMAT__RGB565   0xE
+#define BM_PXP_AS_CTRL_ENABLE_COLORKEY 0x00000008
+#define BF_PXP_AS_CTRL_ENABLE_COLORKEY(v)  \
+       (((v) << 3) & BM_PXP_AS_CTRL_ENABLE_COLORKEY)
+#define BP_PXP_AS_CTRL_ALPHA_CTRL      1
+#define BM_PXP_AS_CTRL_ALPHA_CTRL 0x00000006
+#define BF_PXP_AS_CTRL_ALPHA_CTRL(v)  \
+       (((v) << 1) & BM_PXP_AS_CTRL_ALPHA_CTRL)
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Embedded 0x0
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Override 0x1
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply 0x2
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs     0x3
+#define BM_PXP_AS_CTRL_RSVD0 0x00000001
+#define BF_PXP_AS_CTRL_RSVD0(v)  \
+       (((v) << 0) & BM_PXP_AS_CTRL_RSVD0)
+
+#define HW_PXP_AS_BUF  (0x00000160)
+
+#define BP_PXP_AS_BUF_ADDR      0
+#define BM_PXP_AS_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_AS_BUF_ADDR(v)   (v)
+
+#define HW_PXP_AS_PITCH        (0x00000170)
+
+#define BP_PXP_AS_PITCH_RSVD      16
+#define BM_PXP_AS_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_AS_PITCH_RSVD(v) \
+       (((v) << 16) & BM_PXP_AS_PITCH_RSVD)
+#define BP_PXP_AS_PITCH_PITCH      0
+#define BM_PXP_AS_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_AS_PITCH_PITCH(v)  \
+       (((v) << 0) & BM_PXP_AS_PITCH_PITCH)
+
+#define HW_PXP_AS_CLRKEYLOW_0  (0x00000180)
+
+#define BP_PXP_AS_CLRKEYLOW_0_RSVD1      24
+#define BM_PXP_AS_CLRKEYLOW_0_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYLOW_0_RSVD1(v) \
+       (((v) << 24) & BM_PXP_AS_CLRKEYLOW_0_RSVD1)
+#define BP_PXP_AS_CLRKEYLOW_0_PIXEL      0
+#define BM_PXP_AS_CLRKEYLOW_0_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYLOW_0_PIXEL(v)  \
+       (((v) << 0) & BM_PXP_AS_CLRKEYLOW_0_PIXEL)
+
+#define HW_PXP_AS_CLRKEYHIGH_0 (0x00000190)
+
+#define BP_PXP_AS_CLRKEYHIGH_0_RSVD1      24
+#define BM_PXP_AS_CLRKEYHIGH_0_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYHIGH_0_RSVD1(v) \
+       (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_0_RSVD1)
+#define BP_PXP_AS_CLRKEYHIGH_0_PIXEL      0
+#define BM_PXP_AS_CLRKEYHIGH_0_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYHIGH_0_PIXEL(v)  \
+       (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_0_PIXEL)
+
+#define HW_PXP_CSC1_COEF0      (0x000001a0)
+
+#define BM_PXP_CSC1_COEF0_YCBCR_MODE 0x80000000
+#define BF_PXP_CSC1_COEF0_YCBCR_MODE(v) \
+       (((v) << 31) & BM_PXP_CSC1_COEF0_YCBCR_MODE)
+#define BM_PXP_CSC1_COEF0_BYPASS 0x40000000
+#define BF_PXP_CSC1_COEF0_BYPASS(v)  \
+       (((v) << 30) & BM_PXP_CSC1_COEF0_BYPASS)
+#define BM_PXP_CSC1_COEF0_RSVD1 0x20000000
+#define BF_PXP_CSC1_COEF0_RSVD1(v)  \
+       (((v) << 29) & BM_PXP_CSC1_COEF0_RSVD1)
+#define BP_PXP_CSC1_COEF0_C0      18
+#define BM_PXP_CSC1_COEF0_C0 0x1FFC0000
+#define BF_PXP_CSC1_COEF0_C0(v)  \
+       (((v) << 18) & BM_PXP_CSC1_COEF0_C0)
+#define BP_PXP_CSC1_COEF0_UV_OFFSET      9
+#define BM_PXP_CSC1_COEF0_UV_OFFSET 0x0003FE00
+#define BF_PXP_CSC1_COEF0_UV_OFFSET(v)  \
+       (((v) << 9) & BM_PXP_CSC1_COEF0_UV_OFFSET)
+#define BP_PXP_CSC1_COEF0_Y_OFFSET      0
+#define BM_PXP_CSC1_COEF0_Y_OFFSET 0x000001FF
+#define BF_PXP_CSC1_COEF0_Y_OFFSET(v)  \
+       (((v) << 0) & BM_PXP_CSC1_COEF0_Y_OFFSET)
+
+#define HW_PXP_CSC1_COEF1      (0x000001b0)
+
+#define BP_PXP_CSC1_COEF1_RSVD1      27
+#define BM_PXP_CSC1_COEF1_RSVD1 0xF8000000
+#define BF_PXP_CSC1_COEF1_RSVD1(v) \
+       (((v) << 27) & BM_PXP_CSC1_COEF1_RSVD1)
+#define BP_PXP_CSC1_COEF1_C1      16
+#define BM_PXP_CSC1_COEF1_C1 0x07FF0000
+#define BF_PXP_CSC1_COEF1_C1(v)  \
+       (((v) << 16) & BM_PXP_CSC1_COEF1_C1)
+#define BP_PXP_CSC1_COEF1_RSVD0      11
+#define BM_PXP_CSC1_COEF1_RSVD0 0x0000F800
+#define BF_PXP_CSC1_COEF1_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC1_COEF1_RSVD0)
+#define BP_PXP_CSC1_COEF1_C4      0
+#define BM_PXP_CSC1_COEF1_C4 0x000007FF
+#define BF_PXP_CSC1_COEF1_C4(v)  \
+       (((v) << 0) & BM_PXP_CSC1_COEF1_C4)
+
+#define HW_PXP_CSC1_COEF2      (0x000001c0)
+
+#define BP_PXP_CSC1_COEF2_RSVD1      27
+#define BM_PXP_CSC1_COEF2_RSVD1 0xF8000000
+#define BF_PXP_CSC1_COEF2_RSVD1(v) \
+       (((v) << 27) & BM_PXP_CSC1_COEF2_RSVD1)
+#define BP_PXP_CSC1_COEF2_C2      16
+#define BM_PXP_CSC1_COEF2_C2 0x07FF0000
+#define BF_PXP_CSC1_COEF2_C2(v)  \
+       (((v) << 16) & BM_PXP_CSC1_COEF2_C2)
+#define BP_PXP_CSC1_COEF2_RSVD0      11
+#define BM_PXP_CSC1_COEF2_RSVD0 0x0000F800
+#define BF_PXP_CSC1_COEF2_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC1_COEF2_RSVD0)
+#define BP_PXP_CSC1_COEF2_C3      0
+#define BM_PXP_CSC1_COEF2_C3 0x000007FF
+#define BF_PXP_CSC1_COEF2_C3(v)  \
+       (((v) << 0) & BM_PXP_CSC1_COEF2_C3)
+
+#define HW_PXP_CSC2_CTRL       (0x000001d0)
+
+#define BP_PXP_CSC2_CTRL_RSVD      3
+#define BM_PXP_CSC2_CTRL_RSVD 0xFFFFFFF8
+#define BF_PXP_CSC2_CTRL_RSVD(v) \
+       (((v) << 3) & BM_PXP_CSC2_CTRL_RSVD)
+#define BP_PXP_CSC2_CTRL_CSC_MODE      1
+#define BM_PXP_CSC2_CTRL_CSC_MODE 0x00000006
+#define BF_PXP_CSC2_CTRL_CSC_MODE(v)  \
+       (((v) << 1) & BM_PXP_CSC2_CTRL_CSC_MODE)
+#define BV_PXP_CSC2_CTRL_CSC_MODE__YUV2RGB   0x0
+#define BV_PXP_CSC2_CTRL_CSC_MODE__YCbCr2RGB 0x1
+#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV   0x2
+#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr 0x3
+#define BM_PXP_CSC2_CTRL_BYPASS 0x00000001
+#define BF_PXP_CSC2_CTRL_BYPASS(v)  \
+       (((v) << 0) & BM_PXP_CSC2_CTRL_BYPASS)
+
+#define HW_PXP_CSC2_COEF0      (0x000001e0)
+
+#define BP_PXP_CSC2_COEF0_RSVD1      27
+#define BM_PXP_CSC2_COEF0_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF0_RSVD1(v) \
+       (((v) << 27) & BM_PXP_CSC2_COEF0_RSVD1)
+#define BP_PXP_CSC2_COEF0_A2      16
+#define BM_PXP_CSC2_COEF0_A2 0x07FF0000
+#define BF_PXP_CSC2_COEF0_A2(v)  \
+       (((v) << 16) & BM_PXP_CSC2_COEF0_A2)
+#define BP_PXP_CSC2_COEF0_RSVD0      11
+#define BM_PXP_CSC2_COEF0_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF0_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC2_COEF0_RSVD0)
+#define BP_PXP_CSC2_COEF0_A1      0
+#define BM_PXP_CSC2_COEF0_A1 0x000007FF
+#define BF_PXP_CSC2_COEF0_A1(v)  \
+       (((v) << 0) & BM_PXP_CSC2_COEF0_A1)
+
+#define HW_PXP_CSC2_COEF1      (0x000001f0)
+
+#define BP_PXP_CSC2_COEF1_RSVD1      27
+#define BM_PXP_CSC2_COEF1_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF1_RSVD1(v) \
+       (((v) << 27) & BM_PXP_CSC2_COEF1_RSVD1)
+#define BP_PXP_CSC2_COEF1_B1      16
+#define BM_PXP_CSC2_COEF1_B1 0x07FF0000
+#define BF_PXP_CSC2_COEF1_B1(v)  \
+       (((v) << 16) & BM_PXP_CSC2_COEF1_B1)
+#define BP_PXP_CSC2_COEF1_RSVD0      11
+#define BM_PXP_CSC2_COEF1_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF1_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC2_COEF1_RSVD0)
+#define BP_PXP_CSC2_COEF1_A3      0
+#define BM_PXP_CSC2_COEF1_A3 0x000007FF
+#define BF_PXP_CSC2_COEF1_A3(v)  \
+       (((v) << 0) & BM_PXP_CSC2_COEF1_A3)
+
+#define HW_PXP_CSC2_COEF2      (0x00000200)
+
+#define BP_PXP_CSC2_COEF2_RSVD1      27
+#define BM_PXP_CSC2_COEF2_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF2_RSVD1(v) \
+       (((v) << 27) & BM_PXP_CSC2_COEF2_RSVD1)
+#define BP_PXP_CSC2_COEF2_B3      16
+#define BM_PXP_CSC2_COEF2_B3 0x07FF0000
+#define BF_PXP_CSC2_COEF2_B3(v)  \
+       (((v) << 16) & BM_PXP_CSC2_COEF2_B3)
+#define BP_PXP_CSC2_COEF2_RSVD0      11
+#define BM_PXP_CSC2_COEF2_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF2_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC2_COEF2_RSVD0)
+#define BP_PXP_CSC2_COEF2_B2      0
+#define BM_PXP_CSC2_COEF2_B2 0x000007FF
+#define BF_PXP_CSC2_COEF2_B2(v)  \
+       (((v) << 0) & BM_PXP_CSC2_COEF2_B2)
+
+#define HW_PXP_CSC2_COEF3      (0x00000210)
+
+#define BP_PXP_CSC2_COEF3_RSVD1      27
+#define BM_PXP_CSC2_COEF3_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF3_RSVD1(v) \
+       (((v) << 27) & BM_PXP_CSC2_COEF3_RSVD1)
+#define BP_PXP_CSC2_COEF3_C2      16
+#define BM_PXP_CSC2_COEF3_C2 0x07FF0000
+#define BF_PXP_CSC2_COEF3_C2(v)  \
+       (((v) << 16) & BM_PXP_CSC2_COEF3_C2)
+#define BP_PXP_CSC2_COEF3_RSVD0      11
+#define BM_PXP_CSC2_COEF3_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF3_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC2_COEF3_RSVD0)
+#define BP_PXP_CSC2_COEF3_C1      0
+#define BM_PXP_CSC2_COEF3_C1 0x000007FF
+#define BF_PXP_CSC2_COEF3_C1(v)  \
+       (((v) << 0) & BM_PXP_CSC2_COEF3_C1)
+
+#define HW_PXP_CSC2_COEF4      (0x00000220)
+
+#define BP_PXP_CSC2_COEF4_RSVD1      25
+#define BM_PXP_CSC2_COEF4_RSVD1 0xFE000000
+#define BF_PXP_CSC2_COEF4_RSVD1(v) \
+       (((v) << 25) & BM_PXP_CSC2_COEF4_RSVD1)
+#define BP_PXP_CSC2_COEF4_D1      16
+#define BM_PXP_CSC2_COEF4_D1 0x01FF0000
+#define BF_PXP_CSC2_COEF4_D1(v)  \
+       (((v) << 16) & BM_PXP_CSC2_COEF4_D1)
+#define BP_PXP_CSC2_COEF4_RSVD0      11
+#define BM_PXP_CSC2_COEF4_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF4_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC2_COEF4_RSVD0)
+#define BP_PXP_CSC2_COEF4_C3      0
+#define BM_PXP_CSC2_COEF4_C3 0x000007FF
+#define BF_PXP_CSC2_COEF4_C3(v)  \
+       (((v) << 0) & BM_PXP_CSC2_COEF4_C3)
+
+#define HW_PXP_CSC2_COEF5      (0x00000230)
+
+#define BP_PXP_CSC2_COEF5_RSVD1      25
+#define BM_PXP_CSC2_COEF5_RSVD1 0xFE000000
+#define BF_PXP_CSC2_COEF5_RSVD1(v) \
+       (((v) << 25) & BM_PXP_CSC2_COEF5_RSVD1)
+#define BP_PXP_CSC2_COEF5_D3      16
+#define BM_PXP_CSC2_COEF5_D3 0x01FF0000
+#define BF_PXP_CSC2_COEF5_D3(v)  \
+       (((v) << 16) & BM_PXP_CSC2_COEF5_D3)
+#define BP_PXP_CSC2_COEF5_RSVD0      9
+#define BM_PXP_CSC2_COEF5_RSVD0 0x0000FE00
+#define BF_PXP_CSC2_COEF5_RSVD0(v)  \
+       (((v) << 9) & BM_PXP_CSC2_COEF5_RSVD0)
+#define BP_PXP_CSC2_COEF5_D2      0
+#define BM_PXP_CSC2_COEF5_D2 0x000001FF
+#define BF_PXP_CSC2_COEF5_D2(v)  \
+       (((v) << 0) & BM_PXP_CSC2_COEF5_D2)
+
+#define HW_PXP_LUT_CTRL        (0x00000240)
+
+#define BM_PXP_LUT_CTRL_BYPASS 0x80000000
+#define BF_PXP_LUT_CTRL_BYPASS(v) \
+       (((v) << 31) & BM_PXP_LUT_CTRL_BYPASS)
+#define BP_PXP_LUT_CTRL_RSVD3      26
+#define BM_PXP_LUT_CTRL_RSVD3 0x7C000000
+#define BF_PXP_LUT_CTRL_RSVD3(v)  \
+       (((v) << 26) & BM_PXP_LUT_CTRL_RSVD3)
+#define BP_PXP_LUT_CTRL_LOOKUP_MODE      24
+#define BM_PXP_LUT_CTRL_LOOKUP_MODE 0x03000000
+#define BF_PXP_LUT_CTRL_LOOKUP_MODE(v)  \
+       (((v) << 24) & BM_PXP_LUT_CTRL_LOOKUP_MODE)
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__CACHE_RGB565  0x0
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8     0x1
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB444 0x2
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB454 0x3
+#define BP_PXP_LUT_CTRL_RSVD2      18
+#define BM_PXP_LUT_CTRL_RSVD2 0x00FC0000
+#define BF_PXP_LUT_CTRL_RSVD2(v)  \
+       (((v) << 18) & BM_PXP_LUT_CTRL_RSVD2)
+#define BP_PXP_LUT_CTRL_OUT_MODE      16
+#define BM_PXP_LUT_CTRL_OUT_MODE 0x00030000
+#define BF_PXP_LUT_CTRL_OUT_MODE(v)  \
+       (((v) << 16) & BM_PXP_LUT_CTRL_OUT_MODE)
+#define BV_PXP_LUT_CTRL_OUT_MODE__RESERVED    0x0
+#define BV_PXP_LUT_CTRL_OUT_MODE__Y8     0x1
+#define BV_PXP_LUT_CTRL_OUT_MODE__RGBW4444CFA 0x2
+#define BV_PXP_LUT_CTRL_OUT_MODE__RGB888      0x3
+#define BP_PXP_LUT_CTRL_RSVD1      11
+#define BM_PXP_LUT_CTRL_RSVD1 0x0000F800
+#define BF_PXP_LUT_CTRL_RSVD1(v)  \
+       (((v) << 11) & BM_PXP_LUT_CTRL_RSVD1)
+#define BM_PXP_LUT_CTRL_SEL_8KB 0x00000400
+#define BF_PXP_LUT_CTRL_SEL_8KB(v)  \
+       (((v) << 10) & BM_PXP_LUT_CTRL_SEL_8KB)
+#define BM_PXP_LUT_CTRL_LRU_UPD 0x00000200
+#define BF_PXP_LUT_CTRL_LRU_UPD(v)  \
+       (((v) << 9) & BM_PXP_LUT_CTRL_LRU_UPD)
+#define BM_PXP_LUT_CTRL_INVALID 0x00000100
+#define BF_PXP_LUT_CTRL_INVALID(v)  \
+       (((v) << 8) & BM_PXP_LUT_CTRL_INVALID)
+#define BP_PXP_LUT_CTRL_RSVD0      1
+#define BM_PXP_LUT_CTRL_RSVD0 0x000000FE
+#define BF_PXP_LUT_CTRL_RSVD0(v)  \
+       (((v) << 1) & BM_PXP_LUT_CTRL_RSVD0)
+#define BM_PXP_LUT_CTRL_DMA_START 0x00000001
+#define BF_PXP_LUT_CTRL_DMA_START(v)  \
+       (((v) << 0) & BM_PXP_LUT_CTRL_DMA_START)
+
+#define HW_PXP_LUT_ADDR        (0x00000250)
+
+#define BM_PXP_LUT_ADDR_RSVD2 0x80000000
+#define BF_PXP_LUT_ADDR_RSVD2(v) \
+       (((v) << 31) & BM_PXP_LUT_ADDR_RSVD2)
+#define BP_PXP_LUT_ADDR_NUM_BYTES      16
+#define BM_PXP_LUT_ADDR_NUM_BYTES 0x7FFF0000
+#define BF_PXP_LUT_ADDR_NUM_BYTES(v)  \
+       (((v) << 16) & BM_PXP_LUT_ADDR_NUM_BYTES)
+#define BP_PXP_LUT_ADDR_RSVD1      14
+#define BM_PXP_LUT_ADDR_RSVD1 0x0000C000
+#define BF_PXP_LUT_ADDR_RSVD1(v)  \
+       (((v) << 14) & BM_PXP_LUT_ADDR_RSVD1)
+#define BP_PXP_LUT_ADDR_ADDR      0
+#define BM_PXP_LUT_ADDR_ADDR 0x00003FFF
+#define BF_PXP_LUT_ADDR_ADDR(v)  \
+       (((v) << 0) & BM_PXP_LUT_ADDR_ADDR)
+
+#define HW_PXP_LUT_DATA        (0x00000260)
+
+#define BP_PXP_LUT_DATA_DATA      0
+#define BM_PXP_LUT_DATA_DATA 0xFFFFFFFF
+#define BF_PXP_LUT_DATA_DATA(v)   (v)
+
+#define HW_PXP_LUT_EXTMEM      (0x00000270)
+
+#define BP_PXP_LUT_EXTMEM_ADDR      0
+#define BM_PXP_LUT_EXTMEM_ADDR 0xFFFFFFFF
+#define BF_PXP_LUT_EXTMEM_ADDR(v)   (v)
+
+#define HW_PXP_CFA     (0x00000280)
+
+#define BP_PXP_CFA_DATA      0
+#define BM_PXP_CFA_DATA 0xFFFFFFFF
+#define BF_PXP_CFA_DATA(v)   (v)
+
+#define HW_PXP_ALPHA_A_CTRL    (0x00000290)
+
+#define BP_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA      24
+#define BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA 0xFF000000
+#define BF_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA(v) \
+       (((v) << 24) & BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA)
+#define BP_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA      16
+#define BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA 0x00FF0000
+#define BF_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA(v)  \
+       (((v) << 16) & BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA)
+#define BP_PXP_ALPHA_A_CTRL_RSVD0      14
+#define BM_PXP_ALPHA_A_CTRL_RSVD0 0x0000C000
+#define BF_PXP_ALPHA_A_CTRL_RSVD0(v)  \
+       (((v) << 14) & BM_PXP_ALPHA_A_CTRL_RSVD0)
+#define BM_PXP_ALPHA_A_CTRL_S1_COLOR_MODE 0x00002000
+#define BF_PXP_ALPHA_A_CTRL_S1_COLOR_MODE(v)  \
+       (((v) << 13) & BM_PXP_ALPHA_A_CTRL_S1_COLOR_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S1_COLOR_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_COLOR_MODE__1 0x1
+#define BM_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE 0x00001000
+#define BF_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE(v)  \
+       (((v) << 12) & BM_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE__1 0x1
+#define BP_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE      10
+#define BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE 0x00000C00
+#define BF_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE(v)  \
+       (((v) << 10) & BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__1 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__2 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__3 0x0
+#define BP_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE      8
+#define BM_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE 0x00000300
+#define BF_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE(v)  \
+       (((v) << 8) & BM_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__1 0x1
+#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__2 0x2
+#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__3 0x3
+#define BM_PXP_ALPHA_A_CTRL_RSVD1 0x00000080
+#define BF_PXP_ALPHA_A_CTRL_RSVD1(v)  \
+       (((v) << 7) & BM_PXP_ALPHA_A_CTRL_RSVD1)
+#define BM_PXP_ALPHA_A_CTRL_S0_COLOR_MODE 0x00000040
+#define BF_PXP_ALPHA_A_CTRL_S0_COLOR_MODE(v)  \
+       (((v) << 6) & BM_PXP_ALPHA_A_CTRL_S0_COLOR_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S0_COLOR_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S0_COLOR_MODE__1 0x1
+#define BM_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE 0x00000020
+#define BF_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE(v)  \
+       (((v) << 5) & BM_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE__1 0x1
+#define BP_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE      3
+#define BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE 0x00000018
+#define BF_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE(v)  \
+       (((v) << 3) & BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__1 0x1
+#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__2 0x2
+#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__3 0x3
+#define BP_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE      1
+#define BM_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE 0x00000006
+#define BF_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE(v)  \
+       (((v) << 1) & BM_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE)
+#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__1 0x1
+#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__2 0x2
+#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__3 0x3
+#define BM_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE 0x00000001
+#define BF_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE(v)  \
+       (((v) << 0) & BM_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE)
+#define BV_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE__0 0x0
+#define BV_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE__1 0x1
+
+#define HW_PXP_ALPHA_B_CTRL    (0x000002a0)
+
+#define BP_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA      24
+#define BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA 0xFF000000
+#define BF_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA(v) \
+       (((v) << 24) & BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA)
+#define BP_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA      16
+#define BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA 0x00FF0000
+#define BF_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA(v)  \
+       (((v) << 16) & BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA)
+#define BP_PXP_ALPHA_B_CTRL_RSVD0      14
+#define BM_PXP_ALPHA_B_CTRL_RSVD0 0x0000C000
+#define BF_PXP_ALPHA_B_CTRL_RSVD0(v)  \
+       (((v) << 14) & BM_PXP_ALPHA_B_CTRL_RSVD0)
+#define BM_PXP_ALPHA_B_CTRL_S1_COLOR_MODE 0x00002000
+#define BF_PXP_ALPHA_B_CTRL_S1_COLOR_MODE(v)  \
+       (((v) << 13) & BM_PXP_ALPHA_B_CTRL_S1_COLOR_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S1_COLOR_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S1_COLOR_MODE__1 0x1
+#define BM_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE 0x00001000
+#define BF_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE(v)  \
+       (((v) << 12) & BM_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE__1 0x1
+#define BP_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE      10
+#define BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE 0x00000C00
+#define BF_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE(v)  \
+       (((v) << 10) & BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__1 0x1
+#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__2 0x2
+#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__3 0x3
+#define BP_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE      8
+#define BM_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE 0x00000300
+#define BF_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE(v)  \
+       (((v) << 8) & BM_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__1 0x1
+#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__2 0x2
+#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__3 0x3
+#define BM_PXP_ALPHA_B_CTRL_RSVD1 0x00000080
+#define BF_PXP_ALPHA_B_CTRL_RSVD1(v)  \
+       (((v) << 7) & BM_PXP_ALPHA_B_CTRL_RSVD1)
+#define BM_PXP_ALPHA_B_CTRL_S0_COLOR_MODE 0x00000040
+#define BF_PXP_ALPHA_B_CTRL_S0_COLOR_MODE(v)  \
+       (((v) << 6) & BM_PXP_ALPHA_B_CTRL_S0_COLOR_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S0_COLOR_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S0_COLOR_MODE__1 0x1
+#define BM_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE 0x00000020
+#define BF_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE(v)  \
+       (((v) << 5) & BM_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE__1 0x1
+#define BP_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE      3
+#define BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE 0x00000018
+#define BF_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE(v)  \
+       (((v) << 3) & BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__1 0x1
+#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__2 0x2
+#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__3 0x3
+#define BP_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE      1
+#define BM_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE 0x00000006
+#define BF_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE(v)  \
+       (((v) << 1) & BM_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE)
+#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__1 0x1
+#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__2 0x2
+#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__3 0x3
+#define BM_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE 0x00000001
+#define BF_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE(v)  \
+       (((v) << 0) & BM_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE)
+#define BV_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE__0 0x0
+#define BV_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE__1 0x1
+
+#define HW_PXP_ALPHA_B_CTRL_1  (0x000002b0)
+
+#define BP_PXP_ALPHA_B_CTRL_1_RSVD0      8
+#define BM_PXP_ALPHA_B_CTRL_1_RSVD0 0xFFFFFF00
+#define BF_PXP_ALPHA_B_CTRL_1_RSVD0(v) \
+       (((v) << 8) & BM_PXP_ALPHA_B_CTRL_1_RSVD0)
+#define BP_PXP_ALPHA_B_CTRL_1_ROP      4
+#define BM_PXP_ALPHA_B_CTRL_1_ROP 0x000000F0
+#define BF_PXP_ALPHA_B_CTRL_1_ROP(v)  \
+       (((v) << 4) & BM_PXP_ALPHA_B_CTRL_1_ROP)
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKAS     0x0
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKNOTAS  0x1
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKASNOT  0x2
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGEAS    0x3
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGENOTAS 0x4
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGEASNOT 0x5
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTCOPYAS  0x6
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOT 0x7
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTMASKAS  0x8
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTMERGEAS 0x9
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__XORAS      0xA
+#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTXORAS   0xB
+#define BP_PXP_ALPHA_B_CTRL_1_RSVD1      2
+#define BM_PXP_ALPHA_B_CTRL_1_RSVD1 0x0000000C
+#define BF_PXP_ALPHA_B_CTRL_1_RSVD1(v)  \
+       (((v) << 2) & BM_PXP_ALPHA_B_CTRL_1_RSVD1)
+#define BM_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE 0x00000002
+#define BF_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE(v)  \
+       (((v) << 1) & BM_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE)
+#define BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE 0x00000001
+#define BF_PXP_ALPHA_B_CTRL_1_ROP_ENABLE(v)  \
+       (((v) << 0) & BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE)
+
+#define HW_PXP_PS_BACKGROUND_1 (0x000002c0)
+
+#define BP_PXP_PS_BACKGROUND_1_RSVD      24
+#define BM_PXP_PS_BACKGROUND_1_RSVD 0xFF000000
+#define BF_PXP_PS_BACKGROUND_1_RSVD(v) \
+       (((v) << 24) & BM_PXP_PS_BACKGROUND_1_RSVD)
+#define BP_PXP_PS_BACKGROUND_1_COLOR      0
+#define BM_PXP_PS_BACKGROUND_1_COLOR 0x00FFFFFF
+#define BF_PXP_PS_BACKGROUND_1_COLOR(v)  \
+       (((v) << 0) & BM_PXP_PS_BACKGROUND_1_COLOR)
+
+#define HW_PXP_PS_CLRKEYLOW_1  (0x000002d0)
+
+#define BP_PXP_PS_CLRKEYLOW_1_RSVD1      24
+#define BM_PXP_PS_CLRKEYLOW_1_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYLOW_1_RSVD1(v) \
+       (((v) << 24) & BM_PXP_PS_CLRKEYLOW_1_RSVD1)
+#define BP_PXP_PS_CLRKEYLOW_1_PIXEL      0
+#define BM_PXP_PS_CLRKEYLOW_1_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYLOW_1_PIXEL(v)  \
+       (((v) << 0) & BM_PXP_PS_CLRKEYLOW_1_PIXEL)
+
+#define HW_PXP_PS_CLRKEYHIGH_1 (0x000002e0)
+
+#define BP_PXP_PS_CLRKEYHIGH_1_RSVD1      24
+#define BM_PXP_PS_CLRKEYHIGH_1_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYHIGH_1_RSVD1(v) \
+       (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_1_RSVD1)
+#define BP_PXP_PS_CLRKEYHIGH_1_PIXEL      0
+#define BM_PXP_PS_CLRKEYHIGH_1_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYHIGH_1_PIXEL(v)  \
+       (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_1_PIXEL)
+
+#define HW_PXP_AS_CLRKEYLOW_1  (0x000002f0)
+
+#define BP_PXP_AS_CLRKEYLOW_1_RSVD1      24
+#define BM_PXP_AS_CLRKEYLOW_1_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYLOW_1_RSVD1(v) \
+       (((v) << 24) & BM_PXP_AS_CLRKEYLOW_1_RSVD1)
+#define BP_PXP_AS_CLRKEYLOW_1_PIXEL      0
+#define BM_PXP_AS_CLRKEYLOW_1_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYLOW_1_PIXEL(v)  \
+       (((v) << 0) & BM_PXP_AS_CLRKEYLOW_1_PIXEL)
+
+#define HW_PXP_AS_CLRKEYHIGH_1 (0x00000300)
+
+#define BP_PXP_AS_CLRKEYHIGH_1_RSVD1      24
+#define BM_PXP_AS_CLRKEYHIGH_1_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYHIGH_1_RSVD1(v) \
+       (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_1_RSVD1)
+#define BP_PXP_AS_CLRKEYHIGH_1_PIXEL      0
+#define BM_PXP_AS_CLRKEYHIGH_1_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYHIGH_1_PIXEL(v)  \
+       (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_1_PIXEL)
+
+#define HW_PXP_CTRL2   (0x00000310)
+#define HW_PXP_CTRL2_SET       (0x00000314)
+#define HW_PXP_CTRL2_CLR       (0x00000318)
+#define HW_PXP_CTRL2_TOG       (0x0000031c)
+
+#define BP_PXP_CTRL2_RSVD3      28
+#define BM_PXP_CTRL2_RSVD3 0xF0000000
+#define BF_PXP_CTRL2_RSVD3(v) \
+       (((v) << 28) & BM_PXP_CTRL2_RSVD3)
+#define BM_PXP_CTRL2_ENABLE_ROTATE1 0x08000000
+#define BF_PXP_CTRL2_ENABLE_ROTATE1(v)  \
+       (((v) << 27) & BM_PXP_CTRL2_ENABLE_ROTATE1)
+#define BM_PXP_CTRL2_ENABLE_ROTATE0 0x04000000
+#define BF_PXP_CTRL2_ENABLE_ROTATE0(v)  \
+       (((v) << 26) & BM_PXP_CTRL2_ENABLE_ROTATE0)
+#define BM_PXP_CTRL2_ENABLE_LUT 0x02000000
+#define BF_PXP_CTRL2_ENABLE_LUT(v)  \
+       (((v) << 25) & BM_PXP_CTRL2_ENABLE_LUT)
+#define BM_PXP_CTRL2_ENABLE_CSC2 0x01000000
+#define BF_PXP_CTRL2_ENABLE_CSC2(v)  \
+       (((v) << 24) & BM_PXP_CTRL2_ENABLE_CSC2)
+#define BM_PXP_CTRL2_BLOCK_SIZE 0x00800000
+#define BF_PXP_CTRL2_BLOCK_SIZE(v)  \
+       (((v) << 23) & BM_PXP_CTRL2_BLOCK_SIZE)
+#define BV_PXP_CTRL2_BLOCK_SIZE__8X8   0x0
+#define BV_PXP_CTRL2_BLOCK_SIZE__16X16 0x1
+#define BM_PXP_CTRL2_RSVD2 0x00400000
+#define BF_PXP_CTRL2_RSVD2(v)  \
+       (((v) << 22) & BM_PXP_CTRL2_RSVD2)
+#define BM_PXP_CTRL2_ENABLE_ALPHA_B 0x00200000
+#define BF_PXP_CTRL2_ENABLE_ALPHA_B(v)  \
+       (((v) << 21) & BM_PXP_CTRL2_ENABLE_ALPHA_B)
+#define BM_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE 0x00100000
+#define BF_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE(v)  \
+       (((v) << 20) & BM_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE)
+#define BM_PXP_CTRL2_ENABLE_WFE_B 0x00080000
+#define BF_PXP_CTRL2_ENABLE_WFE_B(v)  \
+       (((v) << 19) & BM_PXP_CTRL2_ENABLE_WFE_B)
+#define BM_PXP_CTRL2_ENABLE_WFE_A 0x00040000
+#define BF_PXP_CTRL2_ENABLE_WFE_A(v)  \
+       (((v) << 18) & BM_PXP_CTRL2_ENABLE_WFE_A)
+#define BM_PXP_CTRL2_ENABLE_DITHER 0x00020000
+#define BF_PXP_CTRL2_ENABLE_DITHER(v)  \
+       (((v) << 17) & BM_PXP_CTRL2_ENABLE_DITHER)
+#define BM_PXP_CTRL2_RSVD1 0x00010000
+#define BF_PXP_CTRL2_RSVD1(v)  \
+       (((v) << 16) & BM_PXP_CTRL2_RSVD1)
+#define BM_PXP_CTRL2_VFLIP1 0x00008000
+#define BF_PXP_CTRL2_VFLIP1(v)  \
+       (((v) << 15) & BM_PXP_CTRL2_VFLIP1)
+#define BM_PXP_CTRL2_HFLIP1 0x00004000
+#define BF_PXP_CTRL2_HFLIP1(v)  \
+       (((v) << 14) & BM_PXP_CTRL2_HFLIP1)
+#define BP_PXP_CTRL2_ROTATE1      12
+#define BM_PXP_CTRL2_ROTATE1 0x00003000
+#define BF_PXP_CTRL2_ROTATE1(v)  \
+       (((v) << 12) & BM_PXP_CTRL2_ROTATE1)
+#define BV_PXP_CTRL2_ROTATE1__ROT_0   0x0
+#define BV_PXP_CTRL2_ROTATE1__ROT_90  0x1
+#define BV_PXP_CTRL2_ROTATE1__ROT_180 0x2
+#define BV_PXP_CTRL2_ROTATE1__ROT_270 0x3
+#define BM_PXP_CTRL2_VFLIP0 0x00000800
+#define BF_PXP_CTRL2_VFLIP0(v)  \
+       (((v) << 11) & BM_PXP_CTRL2_VFLIP0)
+#define BM_PXP_CTRL2_HFLIP0 0x00000400
+#define BF_PXP_CTRL2_HFLIP0(v)  \
+       (((v) << 10) & BM_PXP_CTRL2_HFLIP0)
+#define BP_PXP_CTRL2_ROTATE0      8
+#define BM_PXP_CTRL2_ROTATE0 0x00000300
+#define BF_PXP_CTRL2_ROTATE0(v)  \
+       (((v) << 8) & BM_PXP_CTRL2_ROTATE0)
+#define BV_PXP_CTRL2_ROTATE0__ROT_0   0x0
+#define BV_PXP_CTRL2_ROTATE0__ROT_90  0x1
+#define BV_PXP_CTRL2_ROTATE0__ROT_180 0x2
+#define BV_PXP_CTRL2_ROTATE0__ROT_270 0x3
+#define BP_PXP_CTRL2_RSVD0      1
+#define BM_PXP_CTRL2_RSVD0 0x000000FE
+#define BF_PXP_CTRL2_RSVD0(v)  \
+       (((v) << 1) & BM_PXP_CTRL2_RSVD0)
+#define BM_PXP_CTRL2_ENABLE 0x00000001
+#define BF_PXP_CTRL2_ENABLE(v)  \
+       (((v) << 0) & BM_PXP_CTRL2_ENABLE)
+
+#define HW_PXP_POWER_REG0      (0x00000320)
+
+#define BP_PXP_POWER_REG0_CTRL      12
+#define BM_PXP_POWER_REG0_CTRL 0xFFFFF000
+#define BF_PXP_POWER_REG0_CTRL(v) \
+       (((v) << 12) & BM_PXP_POWER_REG0_CTRL)
+#define BP_PXP_POWER_REG0_ROT0_MEM_LP_STATE      9
+#define BM_PXP_POWER_REG0_ROT0_MEM_LP_STATE 0x00000E00
+#define BF_PXP_POWER_REG0_ROT0_MEM_LP_STATE(v)  \
+       (((v) << 9) & BM_PXP_POWER_REG0_ROT0_MEM_LP_STATE)
+#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__LS   0x1
+#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__DS   0x2
+#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__SD   0x4
+#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN      6
+#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN 0x000001C0
+#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN(v)  \
+       (((v) << 6) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN)
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__NONE 0x0
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__LS   0x1
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__DS   0x2
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__SD   0x4
+#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN      3
+#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN 0x00000038
+#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN(v)  \
+       (((v) << 3) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN)
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__NONE 0x0
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__LS   0x1
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__DS   0x2
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__SD   0x4
+#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0      0
+#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0 0x00000007
+#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0(v)  \
+       (((v) << 0) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0)
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__NONE 0x0
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__LS   0x1
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__DS   0x2
+#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__SD   0x4
+
+#define HW_PXP_POWER_REG1      (0x00000330)
+
+#define BP_PXP_POWER_REG1_RSVD0      24
+#define BM_PXP_POWER_REG1_RSVD0 0xFF000000
+#define BF_PXP_POWER_REG1_RSVD0(v) \
+       (((v) << 24) & BM_PXP_POWER_REG1_RSVD0)
+#define BP_PXP_POWER_REG1_ALU_B_MEM_LP_STATE      21
+#define BM_PXP_POWER_REG1_ALU_B_MEM_LP_STATE 0x00E00000
+#define BF_PXP_POWER_REG1_ALU_B_MEM_LP_STATE(v)  \
+       (((v) << 21) & BM_PXP_POWER_REG1_ALU_B_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__LS   0x1
+#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__DS   0x2
+#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__SD   0x4
+#define BP_PXP_POWER_REG1_ALU_A_MEM_LP_STATE      18
+#define BM_PXP_POWER_REG1_ALU_A_MEM_LP_STATE 0x001C0000
+#define BF_PXP_POWER_REG1_ALU_A_MEM_LP_STATE(v)  \
+       (((v) << 18) & BM_PXP_POWER_REG1_ALU_A_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__LS   0x1
+#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__DS   0x2
+#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__SD   0x4
+#define BP_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE      15
+#define BM_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE 0x00038000
+#define BF_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE(v)  \
+       (((v) << 15) & BM_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__LS   0x1
+#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__DS   0x2
+#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__SD   0x4
+#define BP_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE      12
+#define BM_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE 0x00007000
+#define BF_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE(v)  \
+       (((v) << 12) & BM_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__LS   0x1
+#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__DS   0x2
+#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__SD   0x4
+#define BP_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE      9
+#define BM_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE 0x00000E00
+#define BF_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE(v)  \
+       (((v) << 9) & BM_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__LS   0x1
+#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__DS   0x2
+#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__SD   0x4
+#define BP_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE      6
+#define BM_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE 0x000001C0
+#define BF_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE(v)  \
+       (((v) << 6) & BM_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__LS   0x1
+#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__DS   0x2
+#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__SD   0x4
+#define BP_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE      3
+#define BM_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE 0x00000038
+#define BF_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE(v)  \
+       (((v) << 3) & BM_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__LS   0x1
+#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__DS   0x2
+#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__SD   0x4
+#define BP_PXP_POWER_REG1_ROT1_MEM_LP_STATE      0
+#define BM_PXP_POWER_REG1_ROT1_MEM_LP_STATE 0x00000007
+#define BF_PXP_POWER_REG1_ROT1_MEM_LP_STATE(v)  \
+       (((v) << 0) & BM_PXP_POWER_REG1_ROT1_MEM_LP_STATE)
+#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__LS   0x1
+#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__DS   0x2
+#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__SD   0x4
+
+#define HW_PXP_DATA_PATH_CTRL0 (0x00000340)
+#define HW_PXP_DATA_PATH_CTRL0_SET     (0x00000344)
+#define HW_PXP_DATA_PATH_CTRL0_CLR     (0x00000348)
+#define HW_PXP_DATA_PATH_CTRL0_TOG     (0x0000034c)
+
+#define BP_PXP_DATA_PATH_CTRL0_MUX15_SEL      30
+#define BM_PXP_DATA_PATH_CTRL0_MUX15_SEL 0xC0000000
+#define BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(v) \
+       (((v) << 30) & BM_PXP_DATA_PATH_CTRL0_MUX15_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX14_SEL      28
+#define BM_PXP_DATA_PATH_CTRL0_MUX14_SEL 0x30000000
+#define BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(v)  \
+       (((v) << 28) & BM_PXP_DATA_PATH_CTRL0_MUX14_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX13_SEL      26
+#define BM_PXP_DATA_PATH_CTRL0_MUX13_SEL 0x0C000000
+#define BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(v)  \
+       (((v) << 26) & BM_PXP_DATA_PATH_CTRL0_MUX13_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX12_SEL      24
+#define BM_PXP_DATA_PATH_CTRL0_MUX12_SEL 0x03000000
+#define BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(v)  \
+       (((v) << 24) & BM_PXP_DATA_PATH_CTRL0_MUX12_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX11_SEL      22
+#define BM_PXP_DATA_PATH_CTRL0_MUX11_SEL 0x00C00000
+#define BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(v)  \
+       (((v) << 22) & BM_PXP_DATA_PATH_CTRL0_MUX11_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX10_SEL      20
+#define BM_PXP_DATA_PATH_CTRL0_MUX10_SEL 0x00300000
+#define BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(v)  \
+       (((v) << 20) & BM_PXP_DATA_PATH_CTRL0_MUX10_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX9_SEL      18
+#define BM_PXP_DATA_PATH_CTRL0_MUX9_SEL 0x000C0000
+#define BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(v)  \
+       (((v) << 18) & BM_PXP_DATA_PATH_CTRL0_MUX9_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX8_SEL      16
+#define BM_PXP_DATA_PATH_CTRL0_MUX8_SEL 0x00030000
+#define BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(v)  \
+       (((v) << 16) & BM_PXP_DATA_PATH_CTRL0_MUX8_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX7_SEL      14
+#define BM_PXP_DATA_PATH_CTRL0_MUX7_SEL 0x0000C000
+#define BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(v)  \
+       (((v) << 14) & BM_PXP_DATA_PATH_CTRL0_MUX7_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX6_SEL      12
+#define BM_PXP_DATA_PATH_CTRL0_MUX6_SEL 0x00003000
+#define BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(v)  \
+       (((v) << 12) & BM_PXP_DATA_PATH_CTRL0_MUX6_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX5_SEL      10
+#define BM_PXP_DATA_PATH_CTRL0_MUX5_SEL 0x00000C00
+#define BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(v)  \
+       (((v) << 10) & BM_PXP_DATA_PATH_CTRL0_MUX5_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX4_SEL      8
+#define BM_PXP_DATA_PATH_CTRL0_MUX4_SEL 0x00000300
+#define BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(v)  \
+       (((v) << 8) & BM_PXP_DATA_PATH_CTRL0_MUX4_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX3_SEL      6
+#define BM_PXP_DATA_PATH_CTRL0_MUX3_SEL 0x000000C0
+#define BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(v)  \
+       (((v) << 6) & BM_PXP_DATA_PATH_CTRL0_MUX3_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX2_SEL      4
+#define BM_PXP_DATA_PATH_CTRL0_MUX2_SEL 0x00000030
+#define BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(v)  \
+       (((v) << 4) & BM_PXP_DATA_PATH_CTRL0_MUX2_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX1_SEL      2
+#define BM_PXP_DATA_PATH_CTRL0_MUX1_SEL 0x0000000C
+#define BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(v)  \
+       (((v) << 2) & BM_PXP_DATA_PATH_CTRL0_MUX1_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL0_MUX0_SEL      0
+#define BM_PXP_DATA_PATH_CTRL0_MUX0_SEL 0x00000003
+#define BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(v)  \
+       (((v) << 0) & BM_PXP_DATA_PATH_CTRL0_MUX0_SEL)
+#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__3 0x3
+
+#define HW_PXP_DATA_PATH_CTRL1 (0x00000350)
+#define HW_PXP_DATA_PATH_CTRL1_SET     (0x00000354)
+#define HW_PXP_DATA_PATH_CTRL1_CLR     (0x00000358)
+#define HW_PXP_DATA_PATH_CTRL1_TOG     (0x0000035c)
+
+#define BP_PXP_DATA_PATH_CTRL1_RSVD0      4
+#define BM_PXP_DATA_PATH_CTRL1_RSVD0 0xFFFFFFF0
+#define BF_PXP_DATA_PATH_CTRL1_RSVD0(v) \
+       (((v) << 4) & BM_PXP_DATA_PATH_CTRL1_RSVD0)
+#define BP_PXP_DATA_PATH_CTRL1_MUX17_SEL      2
+#define BM_PXP_DATA_PATH_CTRL1_MUX17_SEL 0x0000000C
+#define BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(v)  \
+       (((v) << 2) & BM_PXP_DATA_PATH_CTRL1_MUX17_SEL)
+#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__3 0x3
+#define BP_PXP_DATA_PATH_CTRL1_MUX16_SEL      0
+#define BM_PXP_DATA_PATH_CTRL1_MUX16_SEL 0x00000003
+#define BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(v)  \
+       (((v) << 0) & BM_PXP_DATA_PATH_CTRL1_MUX16_SEL)
+#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__0 0x0
+#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__1 0x1
+#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__2 0x2
+#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__3 0x3
+
+#define HW_PXP_INIT_MEM_CTRL   (0x00000360)
+#define HW_PXP_INIT_MEM_CTRL_SET       (0x00000364)
+#define HW_PXP_INIT_MEM_CTRL_CLR       (0x00000368)
+#define HW_PXP_INIT_MEM_CTRL_TOG       (0x0000036c)
+
+#define BM_PXP_INIT_MEM_CTRL_START 0x80000000
+#define BF_PXP_INIT_MEM_CTRL_START(v) \
+       (((v) << 31) & BM_PXP_INIT_MEM_CTRL_START)
+#define BP_PXP_INIT_MEM_CTRL_SELECT      27
+#define BM_PXP_INIT_MEM_CTRL_SELECT 0x78000000
+#define BF_PXP_INIT_MEM_CTRL_SELECT(v)  \
+       (((v) << 27) & BM_PXP_INIT_MEM_CTRL_SELECT)
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_LUT  0x0
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_ERR0 0x1
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_ERR1 0x2
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER1_LUT  0x3
+#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER2_LUT  0x4
+#define BV_PXP_INIT_MEM_CTRL_SELECT__ALU_A     0x5
+#define BV_PXP_INIT_MEM_CTRL_SELECT__ALU_B     0x6
+#define BV_PXP_INIT_MEM_CTRL_SELECT__WFE_A_FETCH  0x7
+#define BV_PXP_INIT_MEM_CTRL_SELECT__WFE_B_FETCH  0x8
+#define BV_PXP_INIT_MEM_CTRL_SELECT__RESERVED     0x15
+#define BP_PXP_INIT_MEM_CTRL_RSVD0      16
+#define BM_PXP_INIT_MEM_CTRL_RSVD0 0x07FF0000
+#define BF_PXP_INIT_MEM_CTRL_RSVD0(v)  \
+       (((v) << 16) & BM_PXP_INIT_MEM_CTRL_RSVD0)
+#define BP_PXP_INIT_MEM_CTRL_ADDR      0
+#define BM_PXP_INIT_MEM_CTRL_ADDR 0x0000FFFF
+#define BF_PXP_INIT_MEM_CTRL_ADDR(v)  \
+       (((v) << 0) & BM_PXP_INIT_MEM_CTRL_ADDR)
+
+#define HW_PXP_INIT_MEM_DATA   (0x00000370)
+
+#define BP_PXP_INIT_MEM_DATA_DATA      0
+#define BM_PXP_INIT_MEM_DATA_DATA 0xFFFFFFFF
+#define BF_PXP_INIT_MEM_DATA_DATA(v)   (v)
+
+#define HW_PXP_INIT_MEM_DATA_HIGH      (0x00000380)
+
+#define BP_PXP_INIT_MEM_DATA_HIGH_DATA      0
+#define BM_PXP_INIT_MEM_DATA_HIGH_DATA 0xFFFFFFFF
+#define BF_PXP_INIT_MEM_DATA_HIGH_DATA(v)   (v)
+
+#define HW_PXP_IRQ_MASK        (0x00000390)
+#define HW_PXP_IRQ_MASK_SET    (0x00000394)
+#define HW_PXP_IRQ_MASK_CLR    (0x00000398)
+#define HW_PXP_IRQ_MASK_TOG    (0x0000039c)
+
+#define BM_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN 0x80000000
+#define BF_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN(v) \
+       (((v) << 31) & BM_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN)
+#define BP_PXP_IRQ_MASK_RSVD1      16
+#define BM_PXP_IRQ_MASK_RSVD1 0x7FFF0000
+#define BF_PXP_IRQ_MASK_RSVD1(v)  \
+       (((v) << 16) & BM_PXP_IRQ_MASK_RSVD1)
+#define BM_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN 0x00008000
+#define BF_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN(v)  \
+       (((v) << 15) & BM_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN 0x00004000
+#define BF_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN(v)  \
+       (((v) << 14) & BM_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN 0x00002000
+#define BF_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN(v)  \
+       (((v) << 13) & BM_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN 0x00001000
+#define BF_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN(v)  \
+       (((v) << 12) & BM_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN 0x00000800
+#define BF_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN(v)  \
+       (((v) << 11) & BM_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN 0x00000400
+#define BF_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN(v)  \
+       (((v) << 10) & BM_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN 0x00000200
+#define BF_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN(v)  \
+       (((v) << 9) & BM_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN 0x00000100
+#define BF_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN(v)  \
+       (((v) << 8) & BM_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN 0x00000080
+#define BF_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN(v)  \
+       (((v) << 7) & BM_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN 0x00000040
+#define BF_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN(v)  \
+       (((v) << 6) & BM_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN 0x00000020
+#define BF_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN(v)  \
+       (((v) << 5) & BM_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN)
+#define BM_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN 0x00000010
+#define BF_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN(v)  \
+       (((v) << 4) & BM_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN 0x00000008
+#define BF_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN(v)  \
+       (((v) << 3) & BM_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN 0x00000004
+#define BF_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN(v)  \
+       (((v) << 2) & BM_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN 0x00000002
+#define BF_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN(v)  \
+       (((v) << 1) & BM_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN)
+#define BM_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN 0x00000001
+#define BF_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN(v)  \
+       (((v) << 0) & BM_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN)
+
+#define HW_PXP_IRQ     (0x000003a0)
+#define HW_PXP_IRQ_SET (0x000003a4)
+#define HW_PXP_IRQ_CLR (0x000003a8)
+#define HW_PXP_IRQ_TOG (0x000003ac)
+
+#define BM_PXP_IRQ_COMPRESS_DONE_IRQ 0x80000000
+#define BF_PXP_IRQ_COMPRESS_DONE_IRQ(v) \
+       (((v) << 31) & BM_PXP_IRQ_COMPRESS_DONE_IRQ)
+#define BP_PXP_IRQ_RSVD1      16
+#define BM_PXP_IRQ_RSVD1 0x7FFF0000
+#define BF_PXP_IRQ_RSVD1(v)  \
+       (((v) << 16) & BM_PXP_IRQ_RSVD1)
+#define BM_PXP_IRQ_WFE_B_STORE_IRQ 0x00008000
+#define BF_PXP_IRQ_WFE_B_STORE_IRQ(v)  \
+       (((v) << 15) & BM_PXP_IRQ_WFE_B_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_A_STORE_IRQ 0x00004000
+#define BF_PXP_IRQ_WFE_A_STORE_IRQ(v)  \
+       (((v) << 14) & BM_PXP_IRQ_WFE_A_STORE_IRQ)
+#define BM_PXP_IRQ_DITHER_STORE_IRQ 0x00002000
+#define BF_PXP_IRQ_DITHER_STORE_IRQ(v)  \
+       (((v) << 13) & BM_PXP_IRQ_DITHER_STORE_IRQ)
+#define BM_PXP_IRQ_FIRST_STORE_IRQ 0x00001000
+#define BF_PXP_IRQ_FIRST_STORE_IRQ(v)  \
+       (((v) << 12) & BM_PXP_IRQ_FIRST_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_B_CH1_STORE_IRQ 0x00000800
+#define BF_PXP_IRQ_WFE_B_CH1_STORE_IRQ(v)  \
+       (((v) << 11) & BM_PXP_IRQ_WFE_B_CH1_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ 0x00000400
+#define BF_PXP_IRQ_WFE_B_CH0_STORE_IRQ(v)  \
+       (((v) << 10) & BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_A_CH1_STORE_IRQ 0x00000200
+#define BF_PXP_IRQ_WFE_A_CH1_STORE_IRQ(v)  \
+       (((v) << 9) & BM_PXP_IRQ_WFE_A_CH1_STORE_IRQ)
+#define BM_PXP_IRQ_WFE_A_CH0_STORE_IRQ 0x00000100
+#define BF_PXP_IRQ_WFE_A_CH0_STORE_IRQ(v)  \
+       (((v) << 8) & BM_PXP_IRQ_WFE_A_CH0_STORE_IRQ)
+#define BM_PXP_IRQ_DITHER_CH1_STORE_IRQ 0x00000080
+#define BF_PXP_IRQ_DITHER_CH1_STORE_IRQ(v)  \
+       (((v) << 7) & BM_PXP_IRQ_DITHER_CH1_STORE_IRQ)
+#define BM_PXP_IRQ_DITHER_CH0_STORE_IRQ 0x00000040
+#define BF_PXP_IRQ_DITHER_CH0_STORE_IRQ(v)  \
+       (((v) << 6) & BM_PXP_IRQ_DITHER_CH0_STORE_IRQ)
+#define BM_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ 0x00000020
+#define BF_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ(v)  \
+       (((v) << 5) & BM_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ)
+#define BM_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ 0x00000010
+#define BF_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ(v)  \
+       (((v) << 4) & BM_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ)
+#define BM_PXP_IRQ_FIRST_CH1_STORE_IRQ 0x00000008
+#define BF_PXP_IRQ_FIRST_CH1_STORE_IRQ(v)  \
+       (((v) << 3) & BM_PXP_IRQ_FIRST_CH1_STORE_IRQ)
+#define BM_PXP_IRQ_FIRST_CH0_STORE_IRQ 0x00000004
+#define BF_PXP_IRQ_FIRST_CH0_STORE_IRQ(v)  \
+       (((v) << 2) & BM_PXP_IRQ_FIRST_CH0_STORE_IRQ)
+#define BM_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ 0x00000002
+#define BF_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ(v)  \
+       (((v) << 1) & BM_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ)
+#define BM_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ 0x00000001
+#define BF_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ(v)  \
+       (((v) << 0) & BM_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ)
+
+#define HW_PXP_NEXT    (0x00000400)
+
+#define BP_PXP_NEXT_POINTER      2
+#define BM_PXP_NEXT_POINTER 0xFFFFFFFC
+#define BF_PXP_NEXT_POINTER(v) \
+       (((v) << 2) & BM_PXP_NEXT_POINTER)
+#define BM_PXP_NEXT_RSVD 0x00000002
+#define BF_PXP_NEXT_RSVD(v)  \
+       (((v) << 1) & BM_PXP_NEXT_RSVD)
+#define BM_PXP_NEXT_ENABLED 0x00000001
+#define BF_PXP_NEXT_ENABLED(v)  \
+       (((v) << 0) & BM_PXP_NEXT_ENABLED)
+
+#define HW_PXP_DEBUGCTRL       (0x00000410)
+
+#define BP_PXP_DEBUGCTRL_RSVD      12
+#define BM_PXP_DEBUGCTRL_RSVD 0xFFFFF000
+#define BF_PXP_DEBUGCTRL_RSVD(v) \
+       (((v) << 12) & BM_PXP_DEBUGCTRL_RSVD)
+#define BP_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT      8
+#define BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 0x00000F00
+#define BF_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT(v)  \
+       (((v) << 8) & BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT)
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__NONE     0x0
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MISS_CNT 0x1
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__HIT_CNT  0x2
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__LAT_CNT  0x4
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MAX_LAT  0x8
+#define BP_PXP_DEBUGCTRL_SELECT      0
+#define BM_PXP_DEBUGCTRL_SELECT 0x000000FF
+#define BF_PXP_DEBUGCTRL_SELECT(v)  \
+       (((v) << 0) & BM_PXP_DEBUGCTRL_SELECT)
+#define BV_PXP_DEBUGCTRL_SELECT__NONE  0x0
+#define BV_PXP_DEBUGCTRL_SELECT__CTRL  0x1
+#define BV_PXP_DEBUGCTRL_SELECT__PSBUF       0x2
+#define BV_PXP_DEBUGCTRL_SELECT__PSBAX       0x3
+#define BV_PXP_DEBUGCTRL_SELECT__PSBAY       0x4
+#define BV_PXP_DEBUGCTRL_SELECT__ASBUF       0x5
+#define BV_PXP_DEBUGCTRL_SELECT__ROTATION    0x6
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF0     0x7
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF1     0x8
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF2     0x9
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_STAT    0x10
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_MISS    0x11
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_HIT     0x12
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_LAT     0x13
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_MAX_LAT 0x14
+
+#define HW_PXP_DEBUG   (0x00000420)
+
+#define BP_PXP_DEBUG_DATA      0
+#define BM_PXP_DEBUG_DATA 0xFFFFFFFF
+#define BF_PXP_DEBUG_DATA(v)   (v)
+
+#define HW_PXP_VERSION (0x00000430)
+
+#define BP_PXP_VERSION_MAJOR      24
+#define BM_PXP_VERSION_MAJOR 0xFF000000
+#define BF_PXP_VERSION_MAJOR(v) \
+       (((v) << 24) & BM_PXP_VERSION_MAJOR)
+#define BP_PXP_VERSION_MINOR      16
+#define BM_PXP_VERSION_MINOR 0x00FF0000
+#define BF_PXP_VERSION_MINOR(v)  \
+       (((v) << 16) & BM_PXP_VERSION_MINOR)
+#define BP_PXP_VERSION_STEP      0
+#define BM_PXP_VERSION_STEP 0x0000FFFF
+#define BF_PXP_VERSION_STEP(v)  \
+       (((v) << 0) & BM_PXP_VERSION_STEP)
+
+#endif /* __IMX_PXP_H__ */
diff --git a/drivers/media/platform/nxp/mx2_emmaprp.c b/drivers/media/platform/nxp/mx2_emmaprp.c
new file mode 100644 (file)
index 0000000..3ce84d0
--- /dev/null
@@ -0,0 +1,912 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Support eMMa-PrP through mem2mem framework.
+ *
+ * eMMa-PrP is a piece of HW that allows fetching buffers
+ * from one memory location and do several operations on
+ * them such as scaling or format conversion giving, as a result
+ * a new processed buffer in another memory location.
+ *
+ * Based on mem2mem_testdev.c by Pawel Osciak.
+ *
+ * Copyright (c) 2011 Vista Silicon S.L.
+ * Javier Martin <javier.martin@vista-silicon.com>
+ */
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <linux/platform_device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-dma-contig.h>
+#include <linux/sizes.h>
+
+#define EMMAPRP_MODULE_NAME "mem2mem-emmaprp"
+
+MODULE_DESCRIPTION("Mem-to-mem device which supports eMMa-PrP present in mx2 SoCs");
+MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.1");
+
+static bool debug;
+module_param(debug, bool, 0644);
+
+#define MIN_W 32
+#define MIN_H 32
+#define MAX_W 2040
+#define MAX_H 2046
+
+#define S_ALIGN                1 /* multiple of 2 */
+#define W_ALIGN_YUV420 3 /* multiple of 8 */
+#define W_ALIGN_OTHERS 2 /* multiple of 4 */
+#define H_ALIGN                1 /* multiple of 2 */
+
+/* Flags that indicate a format can be used for capture/output */
+#define MEM2MEM_CAPTURE        (1 << 0)
+#define MEM2MEM_OUTPUT (1 << 1)
+
+#define MEM2MEM_NAME           "m2m-emmaprp"
+
+/* In bytes, per queue */
+#define MEM2MEM_VID_MEM_LIMIT  SZ_16M
+
+#define dprintk(dev, fmt, arg...) \
+       v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
+
+/* EMMA PrP */
+#define PRP_CNTL                        0x00
+#define PRP_INTR_CNTL                   0x04
+#define PRP_INTRSTATUS                  0x08
+#define PRP_SOURCE_Y_PTR                0x0c
+#define PRP_SOURCE_CB_PTR               0x10
+#define PRP_SOURCE_CR_PTR               0x14
+#define PRP_DEST_RGB1_PTR               0x18
+#define PRP_DEST_RGB2_PTR               0x1c
+#define PRP_DEST_Y_PTR                  0x20
+#define PRP_DEST_CB_PTR                 0x24
+#define PRP_DEST_CR_PTR                 0x28
+#define PRP_SRC_FRAME_SIZE              0x2c
+#define PRP_DEST_CH1_LINE_STRIDE        0x30
+#define PRP_SRC_PIXEL_FORMAT_CNTL       0x34
+#define PRP_CH1_PIXEL_FORMAT_CNTL       0x38
+#define PRP_CH1_OUT_IMAGE_SIZE          0x3c
+#define PRP_CH2_OUT_IMAGE_SIZE          0x40
+#define PRP_SRC_LINE_STRIDE             0x44
+#define PRP_CSC_COEF_012                0x48
+#define PRP_CSC_COEF_345                0x4c
+#define PRP_CSC_COEF_678                0x50
+#define PRP_CH1_RZ_HORI_COEF1           0x54
+#define PRP_CH1_RZ_HORI_COEF2           0x58
+#define PRP_CH1_RZ_HORI_VALID           0x5c
+#define PRP_CH1_RZ_VERT_COEF1           0x60
+#define PRP_CH1_RZ_VERT_COEF2           0x64
+#define PRP_CH1_RZ_VERT_VALID           0x68
+#define PRP_CH2_RZ_HORI_COEF1           0x6c
+#define PRP_CH2_RZ_HORI_COEF2           0x70
+#define PRP_CH2_RZ_HORI_VALID           0x74
+#define PRP_CH2_RZ_VERT_COEF1           0x78
+#define PRP_CH2_RZ_VERT_COEF2           0x7c
+#define PRP_CH2_RZ_VERT_VALID           0x80
+
+#define PRP_CNTL_CH1EN          (1 << 0)
+#define PRP_CNTL_CH2EN          (1 << 1)
+#define PRP_CNTL_CSIEN          (1 << 2)
+#define PRP_CNTL_DATA_IN_YUV420 (0 << 3)
+#define PRP_CNTL_DATA_IN_YUV422 (1 << 3)
+#define PRP_CNTL_DATA_IN_RGB16  (2 << 3)
+#define PRP_CNTL_DATA_IN_RGB32  (3 << 3)
+#define PRP_CNTL_CH1_OUT_RGB8   (0 << 5)
+#define PRP_CNTL_CH1_OUT_RGB16  (1 << 5)
+#define PRP_CNTL_CH1_OUT_RGB32  (2 << 5)
+#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5)
+#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7)
+#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7)
+#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7)
+#define PRP_CNTL_CH1_LEN        (1 << 9)
+#define PRP_CNTL_CH2_LEN        (1 << 10)
+#define PRP_CNTL_SKIP_FRAME     (1 << 11)
+#define PRP_CNTL_SWRST          (1 << 12)
+#define PRP_CNTL_CLKEN          (1 << 13)
+#define PRP_CNTL_WEN            (1 << 14)
+#define PRP_CNTL_CH1BYP         (1 << 15)
+#define PRP_CNTL_IN_TSKIP(x)    ((x) << 16)
+#define PRP_CNTL_CH1_TSKIP(x)   ((x) << 19)
+#define PRP_CNTL_CH2_TSKIP(x)   ((x) << 22)
+#define PRP_CNTL_INPUT_FIFO_LEVEL(x)    ((x) << 25)
+#define PRP_CNTL_RZ_FIFO_LEVEL(x)       ((x) << 27)
+#define PRP_CNTL_CH2B1EN        (1 << 29)
+#define PRP_CNTL_CH2B2EN        (1 << 30)
+#define PRP_CNTL_CH2FEN         (1UL << 31)
+
+#define PRP_SIZE_HEIGHT(x)     (x)
+#define PRP_SIZE_WIDTH(x)      ((x) << 16)
+
+/* IRQ Enable and status register */
+#define PRP_INTR_RDERR          (1 << 0)
+#define PRP_INTR_CH1WERR        (1 << 1)
+#define PRP_INTR_CH2WERR        (1 << 2)
+#define PRP_INTR_CH1FC          (1 << 3)
+#define PRP_INTR_CH2FC          (1 << 5)
+#define PRP_INTR_LBOVF          (1 << 7)
+#define PRP_INTR_CH2OVF         (1 << 8)
+
+#define PRP_INTR_ST_RDERR      (1 << 0)
+#define PRP_INTR_ST_CH1WERR    (1 << 1)
+#define PRP_INTR_ST_CH2WERR    (1 << 2)
+#define PRP_INTR_ST_CH2B2CI    (1 << 3)
+#define PRP_INTR_ST_CH2B1CI    (1 << 4)
+#define PRP_INTR_ST_CH1B2CI    (1 << 5)
+#define PRP_INTR_ST_CH1B1CI    (1 << 6)
+#define PRP_INTR_ST_LBOVF      (1 << 7)
+#define PRP_INTR_ST_CH2OVF     (1 << 8)
+
+struct emmaprp_fmt {
+       u32     fourcc;
+       /* Types the format can be used for */
+       u32     types;
+};
+
+static struct emmaprp_fmt formats[] = {
+       {
+               .fourcc = V4L2_PIX_FMT_YUV420,
+               .types  = MEM2MEM_CAPTURE,
+       },
+       {
+               .fourcc = V4L2_PIX_FMT_YUYV,
+               .types  = MEM2MEM_OUTPUT,
+       },
+};
+
+/* Per-queue, driver-specific private data */
+struct emmaprp_q_data {
+       unsigned int            width;
+       unsigned int            height;
+       unsigned int            sizeimage;
+       struct emmaprp_fmt      *fmt;
+};
+
+enum {
+       V4L2_M2M_SRC = 0,
+       V4L2_M2M_DST = 1,
+};
+
+#define NUM_FORMATS ARRAY_SIZE(formats)
+
+static struct emmaprp_fmt *find_format(struct v4l2_format *f)
+{
+       struct emmaprp_fmt *fmt;
+       unsigned int k;
+
+       for (k = 0; k < NUM_FORMATS; k++) {
+               fmt = &formats[k];
+               if (fmt->fourcc == f->fmt.pix.pixelformat)
+                       break;
+       }
+
+       if (k == NUM_FORMATS)
+               return NULL;
+
+       return &formats[k];
+}
+
+struct emmaprp_dev {
+       struct v4l2_device      v4l2_dev;
+       struct video_device     *vfd;
+
+       struct mutex            dev_mutex;
+       spinlock_t              irqlock;
+
+       void __iomem            *base_emma;
+       struct clk              *clk_emma_ahb, *clk_emma_ipg;
+
+       struct v4l2_m2m_dev     *m2m_dev;
+};
+
+struct emmaprp_ctx {
+       struct v4l2_fh          fh;
+       struct emmaprp_dev      *dev;
+       /* Abort requested by m2m */
+       int                     aborting;
+       struct emmaprp_q_data   q_data[2];
+};
+
+static struct emmaprp_q_data *get_q_data(struct emmaprp_ctx *ctx,
+                                        enum v4l2_buf_type type)
+{
+       switch (type) {
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+               return &(ctx->q_data[V4L2_M2M_SRC]);
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               return &(ctx->q_data[V4L2_M2M_DST]);
+       default:
+               BUG();
+       }
+       return NULL;
+}
+
+/*
+ * mem2mem callbacks
+ */
+static void emmaprp_job_abort(void *priv)
+{
+       struct emmaprp_ctx *ctx = priv;
+       struct emmaprp_dev *pcdev = ctx->dev;
+
+       ctx->aborting = 1;
+
+       dprintk(pcdev, "Aborting task\n");
+
+       v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->fh.m2m_ctx);
+}
+
+static inline void emmaprp_dump_regs(struct emmaprp_dev *pcdev)
+{
+       dprintk(pcdev,
+               "eMMa-PrP Registers:\n"
+               "  SOURCE_Y_PTR = 0x%08X\n"
+               "  SRC_FRAME_SIZE = 0x%08X\n"
+               "  DEST_Y_PTR = 0x%08X\n"
+               "  DEST_CR_PTR = 0x%08X\n"
+               "  DEST_CB_PTR = 0x%08X\n"
+               "  CH2_OUT_IMAGE_SIZE = 0x%08X\n"
+               "  CNTL = 0x%08X\n",
+               readl(pcdev->base_emma + PRP_SOURCE_Y_PTR),
+               readl(pcdev->base_emma + PRP_SRC_FRAME_SIZE),
+               readl(pcdev->base_emma + PRP_DEST_Y_PTR),
+               readl(pcdev->base_emma + PRP_DEST_CR_PTR),
+               readl(pcdev->base_emma + PRP_DEST_CB_PTR),
+               readl(pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE),
+               readl(pcdev->base_emma + PRP_CNTL));
+}
+
+static void emmaprp_device_run(void *priv)
+{
+       struct emmaprp_ctx *ctx = priv;
+       struct emmaprp_q_data *s_q_data, *d_q_data;
+       struct vb2_v4l2_buffer *src_buf, *dst_buf;
+       struct emmaprp_dev *pcdev = ctx->dev;
+       unsigned int s_width, s_height;
+       unsigned int d_width, d_height;
+       unsigned int d_size;
+       dma_addr_t p_in, p_out;
+       u32 tmp;
+
+       src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+
+       s_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+       s_width = s_q_data->width;
+       s_height = s_q_data->height;
+
+       d_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       d_width = d_q_data->width;
+       d_height = d_q_data->height;
+       d_size = d_width * d_height;
+
+       p_in = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+       p_out = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
+       if (!p_in || !p_out) {
+               v4l2_err(&pcdev->v4l2_dev,
+                        "Acquiring kernel pointers to buffers failed\n");
+               return;
+       }
+
+       /* Input frame parameters */
+       writel(p_in, pcdev->base_emma + PRP_SOURCE_Y_PTR);
+       writel(PRP_SIZE_WIDTH(s_width) | PRP_SIZE_HEIGHT(s_height),
+              pcdev->base_emma + PRP_SRC_FRAME_SIZE);
+
+       /* Output frame parameters */
+       writel(p_out, pcdev->base_emma + PRP_DEST_Y_PTR);
+       writel(p_out + d_size, pcdev->base_emma + PRP_DEST_CB_PTR);
+       writel(p_out + d_size + (d_size >> 2),
+              pcdev->base_emma + PRP_DEST_CR_PTR);
+       writel(PRP_SIZE_WIDTH(d_width) | PRP_SIZE_HEIGHT(d_height),
+              pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE);
+
+       /* IRQ configuration */
+       tmp = readl(pcdev->base_emma + PRP_INTR_CNTL);
+       writel(tmp | PRP_INTR_RDERR |
+               PRP_INTR_CH2WERR |
+               PRP_INTR_CH2FC,
+               pcdev->base_emma + PRP_INTR_CNTL);
+
+       emmaprp_dump_regs(pcdev);
+
+       /* Enable transfer */
+       tmp = readl(pcdev->base_emma + PRP_CNTL);
+       writel(tmp | PRP_CNTL_CH2_OUT_YUV420 |
+               PRP_CNTL_DATA_IN_YUV422 |
+               PRP_CNTL_CH2EN,
+               pcdev->base_emma + PRP_CNTL);
+}
+
+static irqreturn_t emmaprp_irq(int irq_emma, void *data)
+{
+       struct emmaprp_dev *pcdev = data;
+       struct emmaprp_ctx *curr_ctx;
+       struct vb2_v4l2_buffer *src_vb, *dst_vb;
+       unsigned long flags;
+       u32 irqst;
+
+       /* Check irq flags and clear irq */
+       irqst = readl(pcdev->base_emma + PRP_INTRSTATUS);
+       writel(irqst, pcdev->base_emma + PRP_INTRSTATUS);
+       dprintk(pcdev, "irqst = 0x%08x\n", irqst);
+
+       curr_ctx = v4l2_m2m_get_curr_priv(pcdev->m2m_dev);
+       if (curr_ctx == NULL) {
+               pr_err("Instance released before the end of transaction\n");
+               return IRQ_HANDLED;
+       }
+
+       if (!curr_ctx->aborting) {
+               if ((irqst & PRP_INTR_ST_RDERR) ||
+               (irqst & PRP_INTR_ST_CH2WERR)) {
+                       pr_err("PrP bus error occurred, this transfer is probably corrupted\n");
+                       writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL);
+               } else if (irqst & PRP_INTR_ST_CH2B1CI) { /* buffer ready */
+                       src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
+                       dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
+
+                       dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
+                       dst_vb->flags &=
+                               ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+                       dst_vb->flags |=
+                               src_vb->flags
+                               & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+                       dst_vb->timecode = src_vb->timecode;
+
+                       spin_lock_irqsave(&pcdev->irqlock, flags);
+                       v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
+                       v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
+                       spin_unlock_irqrestore(&pcdev->irqlock, flags);
+               }
+       }
+
+       v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->fh.m2m_ctx);
+       return IRQ_HANDLED;
+}
+
+/*
+ * video ioctls
+ */
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
+       strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
+       return 0;
+}
+
+static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
+{
+       int i, num;
+       struct emmaprp_fmt *fmt;
+
+       num = 0;
+
+       for (i = 0; i < NUM_FORMATS; ++i) {
+               if (formats[i].types & type) {
+                       /* index-th format of type type found ? */
+                       if (num == f->index)
+                               break;
+                       /* Correct type but haven't reached our index yet,
+                        * just increment per-type index */
+                       ++num;
+               }
+       }
+
+       if (i < NUM_FORMATS) {
+               /* Format found */
+               fmt = &formats[i];
+               f->pixelformat = fmt->fourcc;
+               return 0;
+       }
+
+       /* Format not found */
+       return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return enum_fmt(f, MEM2MEM_CAPTURE);
+}
+
+static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return enum_fmt(f, MEM2MEM_OUTPUT);
+}
+
+static int vidioc_g_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f)
+{
+       struct vb2_queue *vq;
+       struct emmaprp_q_data *q_data;
+
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       q_data = get_q_data(ctx, f->type);
+
+       f->fmt.pix.width        = q_data->width;
+       f->fmt.pix.height       = q_data->height;
+       f->fmt.pix.field        = V4L2_FIELD_NONE;
+       f->fmt.pix.pixelformat  = q_data->fmt->fourcc;
+       if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
+               f->fmt.pix.bytesperline = q_data->width * 3 / 2;
+       else /* YUYV */
+               f->fmt.pix.bytesperline = q_data->width * 2;
+       f->fmt.pix.sizeimage    = q_data->sizeimage;
+
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       return vidioc_g_fmt(priv, f);
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       return vidioc_g_fmt(priv, f);
+}
+
+static int vidioc_try_fmt(struct v4l2_format *f)
+{
+       enum v4l2_field field;
+
+
+       if (!find_format(f))
+               return -EINVAL;
+
+       field = f->fmt.pix.field;
+       if (field == V4L2_FIELD_ANY)
+               field = V4L2_FIELD_NONE;
+       else if (V4L2_FIELD_NONE != field)
+               return -EINVAL;
+
+       /* V4L2 specification suggests the driver corrects the format struct
+        * if any of the dimensions is unsupported */
+       f->fmt.pix.field = field;
+
+       if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {
+               v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W,
+                                     W_ALIGN_YUV420, &f->fmt.pix.height,
+                                     MIN_H, MAX_H, H_ALIGN, S_ALIGN);
+               f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2;
+       } else {
+               v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W,
+                                     W_ALIGN_OTHERS, &f->fmt.pix.height,
+                                     MIN_H, MAX_H, H_ALIGN, S_ALIGN);
+               f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+       }
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct emmaprp_fmt *fmt;
+       struct emmaprp_ctx *ctx = priv;
+
+       fmt = find_format(f);
+       if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) {
+               v4l2_err(&ctx->dev->v4l2_dev,
+                        "Fourcc format (0x%08x) invalid.\n",
+                        f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       return vidioc_try_fmt(f);
+}
+
+static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct emmaprp_fmt *fmt;
+       struct emmaprp_ctx *ctx = priv;
+
+       fmt = find_format(f);
+       if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) {
+               v4l2_err(&ctx->dev->v4l2_dev,
+                        "Fourcc format (0x%08x) invalid.\n",
+                        f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       return vidioc_try_fmt(f);
+}
+
+static int vidioc_s_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f)
+{
+       struct emmaprp_q_data *q_data;
+       struct vb2_queue *vq;
+       int ret;
+
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       q_data = get_q_data(ctx, f->type);
+       if (!q_data)
+               return -EINVAL;
+
+       if (vb2_is_busy(vq)) {
+               v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
+               return -EBUSY;
+       }
+
+       ret = vidioc_try_fmt(f);
+       if (ret)
+               return ret;
+
+       q_data->fmt             = find_format(f);
+       q_data->width           = f->fmt.pix.width;
+       q_data->height          = f->fmt.pix.height;
+       if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420)
+               q_data->sizeimage = q_data->width * q_data->height * 3 / 2;
+       else /* YUYV */
+               q_data->sizeimage = q_data->width * q_data->height * 2;
+
+       dprintk(ctx->dev,
+               "Setting format for type %d, wxh: %dx%d, fmt: %d\n",
+               f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       int ret;
+
+       ret = vidioc_try_fmt_vid_cap(file, priv, f);
+       if (ret)
+               return ret;
+
+       return vidioc_s_fmt(priv, f);
+}
+
+static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       int ret;
+
+       ret = vidioc_try_fmt_vid_out(file, priv, f);
+       if (ret)
+               return ret;
+
+       return vidioc_s_fmt(priv, f);
+}
+
+static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = {
+       .vidioc_querycap        = vidioc_querycap,
+
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
+
+       .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
+       .vidioc_g_fmt_vid_out   = vidioc_g_fmt_vid_out,
+       .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
+       .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
+
+       .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_expbuf          = v4l2_m2m_ioctl_expbuf,
+       .vidioc_streamon        = v4l2_m2m_ioctl_streamon,
+       .vidioc_streamoff       = v4l2_m2m_ioctl_streamoff,
+};
+
+
+/*
+ * Queue operations
+ */
+static int emmaprp_queue_setup(struct vb2_queue *vq,
+                               unsigned int *nbuffers, unsigned int *nplanes,
+                               unsigned int sizes[], struct device *alloc_devs[])
+{
+       struct emmaprp_ctx *ctx = vb2_get_drv_priv(vq);
+       struct emmaprp_q_data *q_data;
+       unsigned int size, count = *nbuffers;
+
+       q_data = get_q_data(ctx, vq->type);
+
+       if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420)
+               size = q_data->width * q_data->height * 3 / 2;
+       else
+               size = q_data->width * q_data->height * 2;
+
+       while (size * count > MEM2MEM_VID_MEM_LIMIT)
+               (count)--;
+
+       *nplanes = 1;
+       *nbuffers = count;
+       sizes[0] = size;
+
+       dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
+
+       return 0;
+}
+
+static int emmaprp_buf_prepare(struct vb2_buffer *vb)
+{
+       struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct emmaprp_q_data *q_data;
+
+       dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
+
+       q_data = get_q_data(ctx, vb->vb2_queue->type);
+
+       if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
+               dprintk(ctx->dev,
+                       "%s data will not fit into plane(%lu < %lu)\n",
+                       __func__, vb2_plane_size(vb, 0),
+                       (long)q_data->sizeimage);
+               return -EINVAL;
+       }
+
+       vb2_set_plane_payload(vb, 0, q_data->sizeimage);
+
+       return 0;
+}
+
+static void emmaprp_buf_queue(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+}
+
+static const struct vb2_ops emmaprp_qops = {
+       .queue_setup     = emmaprp_queue_setup,
+       .buf_prepare     = emmaprp_buf_prepare,
+       .buf_queue       = emmaprp_buf_queue,
+       .wait_prepare    = vb2_ops_wait_prepare,
+       .wait_finish     = vb2_ops_wait_finish,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+                     struct vb2_queue *dst_vq)
+{
+       struct emmaprp_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->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       src_vq->ops = &emmaprp_qops;
+       src_vq->mem_ops = &vb2_dma_contig_memops;
+       src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       src_vq->dev = ctx->dev->v4l2_dev.dev;
+       src_vq->lock = &ctx->dev->dev_mutex;
+
+       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->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       dst_vq->ops = &emmaprp_qops;
+       dst_vq->mem_ops = &vb2_dma_contig_memops;
+       dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       dst_vq->dev = ctx->dev->v4l2_dev.dev;
+       dst_vq->lock = &ctx->dev->dev_mutex;
+
+       return vb2_queue_init(dst_vq);
+}
+
+/*
+ * File operations
+ */
+static int emmaprp_open(struct file *file)
+{
+       struct emmaprp_dev *pcdev = video_drvdata(file);
+       struct emmaprp_ctx *ctx;
+
+       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       v4l2_fh_init(&ctx->fh, video_devdata(file));
+       file->private_data = &ctx->fh;
+       ctx->dev = pcdev;
+
+       if (mutex_lock_interruptible(&pcdev->dev_mutex)) {
+               kfree(ctx);
+               return -ERESTARTSYS;
+       }
+
+       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init);
+
+       if (IS_ERR(ctx->fh.m2m_ctx)) {
+               int ret = PTR_ERR(ctx->fh.m2m_ctx);
+
+               mutex_unlock(&pcdev->dev_mutex);
+               kfree(ctx);
+               return ret;
+       }
+
+       clk_prepare_enable(pcdev->clk_emma_ipg);
+       clk_prepare_enable(pcdev->clk_emma_ahb);
+       ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1];
+       ctx->q_data[V4L2_M2M_DST].fmt = &formats[0];
+       v4l2_fh_add(&ctx->fh);
+       mutex_unlock(&pcdev->dev_mutex);
+
+       dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->fh.m2m_ctx);
+
+       return 0;
+}
+
+static int emmaprp_release(struct file *file)
+{
+       struct emmaprp_dev *pcdev = video_drvdata(file);
+       struct emmaprp_ctx *ctx = file->private_data;
+
+       dprintk(pcdev, "Releasing instance %p\n", ctx);
+
+       mutex_lock(&pcdev->dev_mutex);
+       clk_disable_unprepare(pcdev->clk_emma_ahb);
+       clk_disable_unprepare(pcdev->clk_emma_ipg);
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+       mutex_unlock(&pcdev->dev_mutex);
+       kfree(ctx);
+
+       return 0;
+}
+
+static const struct v4l2_file_operations emmaprp_fops = {
+       .owner          = THIS_MODULE,
+       .open           = emmaprp_open,
+       .release        = emmaprp_release,
+       .poll           = v4l2_m2m_fop_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = v4l2_m2m_fop_mmap,
+};
+
+static const struct video_device emmaprp_videodev = {
+       .name           = MEM2MEM_NAME,
+       .fops           = &emmaprp_fops,
+       .ioctl_ops      = &emmaprp_ioctl_ops,
+       .minor          = -1,
+       .release        = video_device_release,
+       .vfl_dir        = VFL_DIR_M2M,
+       .device_caps    = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
+};
+
+static const struct v4l2_m2m_ops m2m_ops = {
+       .device_run     = emmaprp_device_run,
+       .job_abort      = emmaprp_job_abort,
+};
+
+static int emmaprp_probe(struct platform_device *pdev)
+{
+       struct emmaprp_dev *pcdev;
+       struct video_device *vfd;
+       int irq, ret;
+
+       pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
+       if (!pcdev)
+               return -ENOMEM;
+
+       spin_lock_init(&pcdev->irqlock);
+
+       pcdev->clk_emma_ipg = devm_clk_get(&pdev->dev, "ipg");
+       if (IS_ERR(pcdev->clk_emma_ipg)) {
+               return PTR_ERR(pcdev->clk_emma_ipg);
+       }
+
+       pcdev->clk_emma_ahb = devm_clk_get(&pdev->dev, "ahb");
+       if (IS_ERR(pcdev->clk_emma_ahb))
+               return PTR_ERR(pcdev->clk_emma_ahb);
+
+       pcdev->base_emma = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(pcdev->base_emma))
+               return PTR_ERR(pcdev->base_emma);
+
+       ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
+       if (ret)
+               return ret;
+
+       mutex_init(&pcdev->dev_mutex);
+
+       vfd = video_device_alloc();
+       if (!vfd) {
+               v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n");
+               ret = -ENOMEM;
+               goto unreg_dev;
+       }
+
+       *vfd = emmaprp_videodev;
+       vfd->lock = &pcdev->dev_mutex;
+       vfd->v4l2_dev = &pcdev->v4l2_dev;
+
+       video_set_drvdata(vfd, pcdev);
+       pcdev->vfd = vfd;
+       v4l2_info(&pcdev->v4l2_dev, EMMAPRP_MODULE_NAME
+                 " Device registered as /dev/video%d\n", vfd->num);
+
+       platform_set_drvdata(pdev, pcdev);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               ret = irq;
+               goto rel_vdev;
+       }
+
+       ret = devm_request_irq(&pdev->dev, irq, emmaprp_irq, 0,
+                              dev_name(&pdev->dev), pcdev);
+       if (ret)
+               goto rel_vdev;
+
+       pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops);
+       if (IS_ERR(pcdev->m2m_dev)) {
+               v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n");
+               ret = PTR_ERR(pcdev->m2m_dev);
+               goto rel_vdev;
+       }
+
+       ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
+       if (ret) {
+               v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n");
+               goto rel_m2m;
+       }
+
+       return 0;
+
+
+rel_m2m:
+       v4l2_m2m_release(pcdev->m2m_dev);
+rel_vdev:
+       video_device_release(vfd);
+unreg_dev:
+       v4l2_device_unregister(&pcdev->v4l2_dev);
+
+       mutex_destroy(&pcdev->dev_mutex);
+
+       return ret;
+}
+
+static int emmaprp_remove(struct platform_device *pdev)
+{
+       struct emmaprp_dev *pcdev = platform_get_drvdata(pdev);
+
+       v4l2_info(&pcdev->v4l2_dev, "Removing " EMMAPRP_MODULE_NAME);
+
+       video_unregister_device(pcdev->vfd);
+       v4l2_m2m_release(pcdev->m2m_dev);
+       v4l2_device_unregister(&pcdev->v4l2_dev);
+       mutex_destroy(&pcdev->dev_mutex);
+
+       return 0;
+}
+
+static struct platform_driver emmaprp_pdrv = {
+       .probe          = emmaprp_probe,
+       .remove         = emmaprp_remove,
+       .driver         = {
+               .name   = MEM2MEM_NAME,
+       },
+};
+module_platform_driver(emmaprp_pdrv);