summaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch
diff options
context:
space:
mode:
authorVladimir Barinov <vladimir.barinov@cogentembedded.com>2017-11-17 12:13:41 +0300
committerVladimir Barinov <vladimir.barinov@cogentembedded.com>2017-11-17 12:13:41 +0300
commitcc609cd55d04afd285fe95eae2fa3f3151f8d66d (patch)
tree199c9f0bc7254e3bebdd1406317e51b32394a74d /meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch
parent3c441bc9a5e5936747c58f49029edf63d0fe96e3 (diff)
V3M IMR/DRM
- Support IMR/VSP/DRM for V3M - Add packeges to use IMR-DRM demo
Diffstat (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch')
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch538
1 files changed, 538 insertions, 0 deletions
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch
new file mode 100644
index 0000000..42d2e32
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch
@@ -0,0 +1,538 @@
+From a687bfb7343b33992f92e86c234718c3e21144a0 Mon Sep 17 00:00:00 2001
+From: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com>
+Date: Tue, 14 Nov 2017 01:47:11 -0800
+Subject: [PATCH] media: rcar-imr: IMR driver updates for raw DL
+
+IMR driver updates for raw DL
+
+Signed-off-by: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com>
+---
+ drivers/media/platform/rcar_imr.c | 209 ++++++++++++++++++++++++++++++--------
+ include/uapi/linux/rcar-imr.h | 16 +--
+ 2 files changed, 175 insertions(+), 50 deletions(-)
+
+diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c
+index 30c6742..9b601da 100644
+--- a/drivers/media/platform/rcar_imr.c
++++ b/drivers/media/platform/rcar_imr.c
+@@ -94,6 +94,7 @@ struct imr_device {
+ struct v4l2_device v4l2_dev;
+ struct video_device video_dev;
+ struct v4l2_m2m_dev *m2m_dev;
++ struct device *alloc_dev;
+
+ /* ...do we need that counter really? framework counts fh structures for us - tbd */
+ int refcount;
+@@ -117,6 +118,9 @@ struct imr_ctx {
+ /* ...cropping parameters (in pixels) */
+ u16 crop[4];
+
++ /* ...solid color code */
++ u32 color;
++
+ /* ...number of active configurations (debugging) */
+ u32 cfg_num;
+ };
+@@ -192,6 +196,7 @@ struct imr_ctx {
+
+ #define IMR_TRICR 0x6C
+ #define IMR_TRIC_YCFORM (1 << 31)
++#define IMR_TRICR2 0xA0
+
+ #define IMR_UVDPOR 0x70
+ #define IMR_SUSR 0x74
+@@ -212,6 +217,8 @@ struct imr_ctx {
+ #define IMR_CPDP_UBDPO_SHIFT 4
+ #define IMR_CPDP_VRDPO_SHIFT 0
+
++#define IMR_TPOR 0xF0
++
+ /*******************************************************************************
+ * Auxiliary helpers
+ ******************************************************************************/
+@@ -404,11 +411,16 @@ static int imr_queue_setup(struct vb2_queue *vq,
+ return -EINVAL;
+ }
+
++ /* ...specify default allocator */
++ alloc_devs[0] = ctx->imr->alloc_dev;
++
+ return 0;
+ }
+
+ static int imr_buf_prepare(struct vb2_buffer *vb)
+ {
++ struct imr_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
++
+ /* ...unclear yet if we want to prepare a buffer somehow (cache invalidation? - tbd) */
+ return 0;
+ }
+@@ -441,9 +453,10 @@ static void imr_buf_finish(struct vb2_buffer *vb)
+ WARN_ON(!mutex_is_locked(&ctx->imr->mutex));
+
+ /* ...any special processing of completed buffer? - tbd */
+- v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> done\n",
++ v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> done (err: %d) (ctx=%p)\n",
+ q->is_output ? "in" : "out",
+- vb2_dma_contig_plane_dma_addr(vb, 0));
++ vb2_dma_contig_plane_dma_addr(vb, 0),
++ vb->state, ctx);
+
+ /* ...unref configuration pointer as needed */
+ if (q->is_output)
+@@ -568,6 +581,11 @@ static inline u16 __imr_auto_sg_dg_tcm(u32 type)
+ (type & IMR_MAP_TCM ? IMR_TRIM_TCM : 0);
+ }
+
++static inline u16 __imr_bfe_tme(u32 type)
++{
++ return (type & IMR_MAP_TME ? IMR_TRIM_TME : 0) | (type & IMR_MAP_BFE ? IMR_TRIM_BFE : 0);
++}
++
+ static inline u16 __imr_uvdp(u32 type)
+ {
+ return __IMR_MAP_UVDPOR(type) | (type & IMR_MAP_DDP ? (1 << 8) : 0);
+@@ -674,15 +692,14 @@ static inline u32 * imr_tri_set_type_b(u32 *dl, void *map, struct imr_mesh *mesh
+ ******************************************************************************/
+
+ /* ...calculate length of a type "c" mapping */
+-static inline u32 imr_tri_type_c_get_length(struct imr_vbo *vbo, int item_size)
++static inline u32 imr_tri_type_c_get_length(int num, int item_size)
+ {
+- return ((4 + 3 * item_size) * vbo->num + 4);
++ return ((4 + 3 * item_size) * num + 4);
+ }
+
+ /* ...set a VBO mapping using absolute coordinates */
+-static inline u32 * imr_tri_set_type_c(u32 *dl, void *map, struct imr_vbo *vbo, int item_size)
++static inline u32 * imr_tri_set_type_c(u32 *dl, void *map, int num, int item_size)
+ {
+- int num = vbo->num;
+ int i;
+
+ /* ...prepare list of triangles to draw */
+@@ -732,6 +749,7 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
+ int h = ctx->queue[0].fmt.height;
+ int W = ctx->queue[1].fmt.width;
+ int H = ctx->queue[1].fmt.height;
++ u32 tricr = ctx->color & 0xFFFFFF;
+
+ v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "setup %u*%u -> %u*%u mapping (type=%x)\n", w, h, W, H, type);
+
+@@ -739,11 +757,17 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
+ *dl++ = IMR_OP_WTS(IMR_TRIMCR, 0xFFFF);
+
+ /* ...set automatic source / destination coordinates generation flags */
+- *dl++ = IMR_OP_WTS(IMR_TRIMSR, __imr_auto_sg_dg_tcm(type) | IMR_TRIM_BFE | IMR_TRIM_TME);
++ *dl++ = IMR_OP_WTS(IMR_TRIMSR, __imr_auto_sg_dg_tcm(type) | __imr_bfe_tme(type));
++
++ /* ...that's probably not needed? - tbd */
++ *dl++ = IMR_OP_SYNCM;
+
+ /* ...set source / destination coordinate precision */
+ *dl++ = IMR_OP_WTS(IMR_UVDPOR, __imr_uvdp(type));
+
++ /* ...that's probably not needed? - tbd */
++ *dl++ = IMR_OP_SYNCM;
++
+ /* ...set luminance/chromacity correction parameters precision */
+ *dl++ = IMR_OP_WTS(IMR_CPDPOR, __imr_cpdp(type));
+
+@@ -776,14 +800,12 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
+ }
+ } else {
+ u16 src_fmt = (iflags & IMR_F_UV_SWAP ? IMR_CMR2_UVFORM : 0) | (iflags & IMR_F_YUV_SWAP ? IMR_CMR2_YUV422FORM : 0);
+- u32 dst_fmt = (oflags & IMR_F_YUV_SWAP ? IMR_TRIC_YCFORM : 0);
+
+ /* ...interleaved input; output is either interleaved or planar */
+ *dl++ = IMR_OP_WTS(IMR_CMRCSR2, IMR_CMR2_YUV422E | src_fmt);
+
+ /* ...destination is always YUYV or UYVY */
+- *dl++ = IMR_OP_WTL(IMR_TRICR, 1);
+- *dl++ = dst_fmt;
++ tricr |= (oflags & IMR_F_YUV_SWAP ? IMR_TRIC_YCFORM : 0);
+
+ /* ...set precision of Y/UV planes and required correction */
+ *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_clce(type) | __imr_luce(type));
+@@ -810,6 +832,10 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
+ *dl++ = ((w - 2) << 16) | (w - 1);
+ *dl++ = h - 1;
+
++ /* ...set triangle single color */
++ *dl++ = IMR_OP_WTL(IMR_TRICR, 1);
++ *dl++ = tricr;
++
+ /* ...invoke subroutine for triangles drawing */
+ *dl++ = IMR_OP_GOSUB;
+ *dl++ = subaddr;
+@@ -852,7 +878,7 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
+ {
+ struct imr_device *imr = ctx->imr;
+ struct imr_mesh *mesh;
+- struct imr_vbo *vbo;
++ int vbo_num;
+ struct imr_cfg *cfg;
+ void *buf, *map;
+ u32 type;
+@@ -925,13 +951,6 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
+ tri_length = imr_tri_type_a_get_length(mesh, item_size);
+ }
+ } else {
+- /* ...assure we have proper VBO descriptor */
+- if (length < sizeof(struct imr_vbo)) {
+- v4l2_err(&imr->v4l2_dev, "invalid vbo specification size: %u\n", length);
+- ret = -EINVAL;
+- goto out;
+- }
+-
+ /* ...make sure there is no automatic-generation flags */
+ if (type & (IMR_MAP_AUTODG | IMR_MAP_AUTOSG)) {
+ v4l2_err(&imr->v4l2_dev, "invalid auto-dg/sg flags: 0x%x\n", type);
+@@ -939,22 +958,23 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
+ goto out;
+ }
+
+- vbo = (struct imr_vbo *)buf;
+- length -= sizeof(struct imr_vbo);
+- map = buf + sizeof(struct imr_vbo);
++ map = buf;
+
+ /* ...vertex is given with absolute coordinates */
+ item_size += 8;
+
++ /* ...calculate total number of triangles */
++ vbo_num = length / (3 * item_size);
++
+ /* ...check the length is sane */
+- if (length != vbo->num * 3 * item_size) {
+- v4l2_err(&imr->v4l2_dev, "invalid vbo size: %u*%u*3 != %u\n", vbo->num, item_size, length);
++ if (length != vbo_num * 3 * item_size) {
++ v4l2_err(&imr->v4l2_dev, "invalid vbo size: %u*%u*3 != %u\n", vbo_num, item_size, length);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* ...calculate size of trangles drawing subroutine */
+- tri_length = imr_tri_type_c_get_length(vbo, item_size);
++ tri_length = imr_tri_type_c_get_length(vbo_num, item_size);
+ }
+
+ /* ...DL main program shall start with 8-byte aligned address */
+@@ -975,13 +995,16 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
+ imr_cfg_unref(ctx, ctx->cfg);
+
+ /* ...create new configuration */
+- ctx->cfg = cfg = imr_cfg_create(ctx, dl_size, dl_start_offset);
++ cfg = imr_cfg_create(ctx, dl_size, dl_start_offset);
+ if (IS_ERR(cfg)) {
+ ret = PTR_ERR(cfg);
++ ctx->cfg = NULL;
+ v4l2_err(&imr->v4l2_dev, "failed to create configuration: %d\n", ret);
+ goto out;
+ }
+
++ ctx->cfg = cfg;
++
+ /* ...get pointer to the new display list */
+ dl_vaddr = cfg->dl_vaddr;
+ dl_dma_addr = cfg->dl_dma_addr;
+@@ -994,7 +1017,7 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
+ imr_tri_set_type_a(dl_vaddr, map, mesh, item_size);
+ }
+ } else {
+- imr_tri_set_type_c(dl_vaddr, map, vbo, item_size);
++ imr_tri_set_type_c(dl_vaddr, map, vbo_num, item_size);
+ }
+
+ /* ...prepare main DL-program */
+@@ -1020,6 +1043,66 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
+ return ret;
+ }
+
++/* ...set mapping data (function called with video device lock held) */
++static int imr_ioctl_map_raw(struct imr_ctx *ctx, struct imr_map_desc *desc)
++{
++ struct imr_device *imr = ctx->imr;
++ u32 type = desc->type;
++ u32 length = desc->size;
++ struct imr_cfg *cfg;
++ void *dl_vaddr;
++ u32 dl_size;
++ u32 dl_start_offset;
++ dma_addr_t dl_dma_addr;
++
++ /* ...calculate main routine length */
++ dl_size = imr_dl_program_length(ctx);
++ if (!dl_size) {
++ v4l2_err(&imr->v4l2_dev, "format configuration error\n");
++ return -EINVAL;
++ }
++
++ /* ...unref current configuration (will not be used by subsequent jobs) */
++ imr_cfg_unref(ctx, ctx->cfg);
++
++ /* ...create new configuration (starts with zero offset) */
++ cfg = imr_cfg_create(ctx, dl_size, 0);
++ if (IS_ERR(cfg)) {
++ ctx->cfg = NULL;
++ v4l2_err(&imr->v4l2_dev, "failed to create configuration: %ld\n", PTR_ERR(cfg));
++ return PTR_ERR(cfg);
++ }
++
++ ctx->cfg = cfg;
++
++ /* ...get pointer to the new display list */
++ dl_vaddr = cfg->dl_vaddr;
++
++ /* ...prepare main DL-program */
++ imr_dl_program_setup(ctx, cfg, type, dl_vaddr, (u32)(uintptr_t)desc->data);
++
++ /* ...update cropping parameters */
++ cfg->dst_subpixel = (type & IMR_MAP_DDP ? 2 : 0);
++
++ /* ...display list updated successfully */
++ v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "display-list created: #%u[%08X]:%u[%u]\n",
++ cfg->id, (u32)dl_dma_addr, dl_size, 0);
++
++ if (debug >= 4)
++ print_hex_dump_bytes("DL-", DUMP_PREFIX_OFFSET, dl_vaddr + dl_start_offset, dl_size - dl_start_offset);
++
++ /* ...success */
++ return 0;
++}
++
++/* ...set mapping data (function called with video device lock held) */
++static int imr_ioctl_color(struct imr_ctx *ctx, u32 color)
++{
++ ctx->color = color;
++
++ return 0;
++}
++
+ /*******************************************************************************
+ * V4L2 I/O controls
+ ******************************************************************************/
+@@ -1183,7 +1266,7 @@ static int imr_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+ WARN_ON(!mutex_is_locked(&ctx->imr->mutex));
+
+ /* ...verify the configuration is complete */
+- if (!V4L2_TYPE_IS_OUTPUT(buf->type) && !ctx->cfg) {
++ if (!ctx->cfg) {
+ v4l2_err(&ctx->imr->v4l2_dev, "stream configuration is not complete\n");
+ return -EINVAL;
+ }
+@@ -1265,6 +1348,14 @@ static long imr_default(struct file *file, void *fh, bool valid_prio, unsigned i
+ /* ...set mesh data */
+ return imr_ioctl_map(ctx, (struct imr_map_desc *)arg);
+
++ case VIDIOC_IMR_MESH_RAW:
++ /* ...set mesh data */
++ return imr_ioctl_map_raw(ctx, (struct imr_map_desc *)arg);
++
++ case VIDIOC_IMR_COLOR:
++ /* ...set solid color code */
++ return imr_ioctl_color(ctx, *(u32 *)arg);
++
+ default:
+ return -ENOIOCTLCMD;
+ }
+@@ -1326,6 +1417,9 @@ static int imr_open(struct file *file)
+ /* ...set default cropping parameters */
+ ctx->crop[1] = ctx->crop[3] = 0x3FF;
+
++ /* ...set default color */
++ ctx->color = 0x808080;
++
+ /* ...initialize M2M processing context */
+ ctx->m2m_ctx = v4l2_m2m_ctx_init(imr->m2m_dev, ctx, imr_queue_init);
+ if (IS_ERR(ctx->m2m_ctx)) {
+@@ -1418,8 +1512,11 @@ static unsigned int imr_poll(struct file *file, struct poll_table_struct *wait)
+ return -ERESTARTSYS;
+
+ res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
++
+ mutex_unlock(&imr->mutex);
+
++ v4l2_dbg(3, debug, &imr->v4l2_dev, "poll result: %X (ctx=%p)\n", res, ctx);
++
+ return res;
+ }
+
+@@ -1453,7 +1550,6 @@ static const struct v4l2_file_operations imr_fops = {
+ * M2M device interface
+ ******************************************************************************/
+
+-#if 0
+ /* ...job cleanup function */
+ static void imr_cleanup(struct imr_ctx *ctx)
+ {
+@@ -1473,17 +1569,16 @@ static void imr_cleanup(struct imr_ctx *ctx)
+ /* ...release lock before we mark current job as finished */
+ spin_unlock_irqrestore(&imr->lock, flags);
+ }
+-#endif
+
+ /* ...job execution function */
+ static void imr_device_run(void *priv)
+ {
+- struct imr_ctx *ctx = priv;
+- struct imr_device *imr = ctx->imr;
+- struct imr_cfg *cfg;
+- struct vb2_buffer *src_buf, *dst_buf;
+- u32 src_addr, dst_addr;
+- unsigned long flags;
++ struct imr_ctx *ctx = priv;
++ struct imr_device *imr = ctx->imr;
++ struct imr_cfg *cfg;
++ struct vb2_v4l2_buffer *src_buf, *dst_buf;
++ u32 src_addr, dst_addr;
++ unsigned long flags;
+
+ v4l2_dbg(3, debug, &imr->v4l2_dev, "run next job...\n");
+
+@@ -1494,8 +1589,11 @@ static void imr_device_run(void *priv)
+ src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+
++ /* ...put source/destination buffers sequence numbers */
++ dst_buf->sequence = src_buf->sequence = ctx->sequence++;
++
+ /* ...take configuration pointer associated with input buffer */
+- cfg = to_imr_buffer(to_vb2_v4l2_buffer(src_buf))->cfg;
++ cfg = to_imr_buffer(src_buf)->cfg;
+
+ /* ...cancel software reset state as needed */
+ iowrite32(0, imr->mmio + IMR_CR);
+@@ -1507,8 +1605,8 @@ static void imr_device_run(void *priv)
+ iowrite32(ctx->crop[3] << cfg->dst_subpixel, imr->mmio + IMR_YMAXR);
+
+ /* ...adjust source/destination parameters of the program (interleaved / semiplanar) */
+- *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(src_buf, 0);
+- *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(dst_buf, 0);
++ *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
++ *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
+
+ /* ...adjust source/destination parameters of the UV-plane as needed */
+ if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) {
+@@ -1529,6 +1627,9 @@ static void imr_device_run(void *priv)
+ /* ...set display list address */
+ iowrite32(cfg->dl_dma_addr + cfg->dl_start_offset, imr->mmio + IMR_DLSAR);
+
++ /* ...enable texture prefetching */
++ iowrite32(0xACCE5501, imr->mmio + IMR_TPOR);
++
+ /* ...explicitly flush any pending write operations (don't need that, I guess) */
+ wmb();
+
+@@ -1536,7 +1637,7 @@ static void imr_device_run(void *priv)
+ iowrite32(IMR_CR_RS, imr->mmio + IMR_CR);
+
+ /* ...timestamp input buffer */
+- src_buf->timestamp = ktime_get_ns();
++ src_buf->vb2_buf.timestamp = ktime_get_ns();
+
+ /* ...unlock device access */
+ spin_unlock_irqrestore(&imr->lock, flags);
+@@ -1633,13 +1734,14 @@ static irqreturn_t imr_irq_handler(int irq, void *data)
+ dst_buf->timecode = src_buf->timecode;
+ dst_buf->flags = src_buf->flags & (V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_KEYFRAME |
+ V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | V4L2_BUF_FLAG_TSTAMP_SRC_MASK);
+- dst_buf->sequence = src_buf->sequence = ctx->sequence++;
++ //dst_buf->sequence = src_buf->sequence = ctx->sequence++;
++
+ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
+
+- v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done\n",
++ v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done (ctx=%p)\n",
+ (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0),
+- (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0));
++ (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0), ctx);
+ } else {
+ /* ...operation completed in error; no way to understand what exactly went wrong */
+ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+@@ -1668,6 +1770,8 @@ static irqreturn_t imr_irq_handler(int irq, void *data)
+ * Device probing / removal interface
+ ******************************************************************************/
+
++static struct class *imr_alloc_class;
++
+ static int imr_probe(struct platform_device *pdev)
+ {
+ struct imr_device *imr;
+@@ -1727,6 +1831,26 @@ static int imr_probe(struct platform_device *pdev)
+ goto device_register_rollback;
+ }
+
++ if (!imr_alloc_class) {
++ imr_alloc_class = class_create(THIS_MODULE, "imr-alloc");
++ if (IS_ERR(imr_alloc_class)) {
++ v4l2_err(&imr->v4l2_dev, "Failed to create alloc-device class\n");
++ ret = PTR_ERR(imr_alloc_class);
++ goto m2m_init_rollback;
++ }
++ }
++
++ struct device *adev = device_create(imr_alloc_class, imr->dev, MKDEV(0, 0), NULL, "%s_alloc", dev_name(&pdev->dev));
++ if (IS_ERR(adev)) {
++ v4l2_err(&imr->v4l2_dev, "Failed to create alloc-device\n");
++ ret = PTR_ERR(adev);
++ goto m2m_init_rollback;
++ }
++ adev->dma_mask = &adev->coherent_dma_mask;
++ adev->coherent_dma_mask = DMA_BIT_MASK(32);
++ arch_setup_dma_ops(adev, 0, DMA_BIT_MASK(32) + 1, NULL, true);
++ imr->alloc_dev = adev;
++
+ strlcpy(imr->video_dev.name, dev_name(&pdev->dev), sizeof(imr->video_dev.name));
+ imr->video_dev.fops = &imr_fops;
+ imr->video_dev.ioctl_ops = &imr_ioctl_ops;
+@@ -1765,6 +1889,7 @@ static int imr_remove(struct platform_device *pdev)
+
+ //pm_runtime_disable(imr->v4l2_dev.dev);
+ video_unregister_device(&imr->video_dev);
++ //device_destroy(imr->alloc_dev, MKDEV(0, 0));
+ v4l2_m2m_release(imr->m2m_dev);
+ v4l2_device_unregister(&imr->v4l2_dev);
+
+diff --git a/include/uapi/linux/rcar-imr.h b/include/uapi/linux/rcar-imr.h
+index d02082f..7b8ed0c 100644
+--- a/include/uapi/linux/rcar-imr.h
++++ b/include/uapi/linux/rcar-imr.h
+@@ -48,6 +48,12 @@ struct imr_map_desc {
+ /* ...vertex clockwise-mode order */
+ #define IMR_MAP_TCM (1 << 5)
+
++/* ...texture mapping enable flag */
++#define IMR_MAP_TME (1 << 6)
++
++/* ...bilinear filtration enable flag */
++#define IMR_MAP_BFE (1 << 7)
++
+ /* ...source coordinate decimal point position bit index */
+ #define __IMR_MAP_UVDPOR_SHIFT 8
+ #define __IMR_MAP_UVDPOR(v) (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7)
+@@ -81,18 +87,12 @@ struct imr_mesh {
+
+ } __attribute__((packed));
+
+-/* ...VBO descriptor */
+-struct imr_vbo {
+- /* ...number of triangles */
+- u16 num;
+-
+-} __attribute__((packed));
+-
+-
+ /*******************************************************************************
+ * Private IOCTL codes
+ ******************************************************************************/
+
+ #define VIDIOC_IMR_MESH _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct imr_map_desc)
++#define VIDIOC_IMR_MESH_RAW _IOW('V', BASE_VIDIOC_PRIVATE + 1, struct imr_map_desc)
++#define VIDIOC_IMR_COLOR _IOW('V', BASE_VIDIOC_PRIVATE + 2, u32)
+
+ #endif /* RCAR_IMR_USER_H */
+--
+2.7.4
+