summaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen3-adas/recipes-kernel/linux
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
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')
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch546
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch367
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch538
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend6
4 files changed, 1457 insertions, 0 deletions
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch
new file mode 100644
index 0000000..e3f24a6
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch
@@ -0,0 +1,546 @@
+From b6176e313aea415b83d5762db275b2f364f08820 Mon Sep 17 00:00:00 2001
+From: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com>
+Date: Tue, 14 Nov 2017 01:38:51 -0800
+Subject: [PATCH] gpu: drm: rcar-du: Extend VSP1-DRM interface
+
+Extend VSP1-DRM interface
+
+Signed-off-by: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com>
+---
+ drivers/gpu/drm/drm_framebuffer.c | 1 +
+ drivers/gpu/drm/rcar-du/rcar_du_drv.h | 5 +
+ drivers/gpu/drm/rcar-du/rcar_du_kms.c | 42 ++++++-
+ drivers/gpu/drm/rcar-du/rcar_du_plane.c | 3 +-
+ drivers/gpu/drm/rcar-du/rcar_du_plane.h | 5 +
+ drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 209 ++++++++++++++++++++++++++------
+ drivers/gpu/drm/rcar-du/rcar_du_vsp.h | 7 +-
+ 7 files changed, 232 insertions(+), 40 deletions(-)
+
+diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
+index 398efd6..4a43e15 100644
+--- a/drivers/gpu/drm/drm_framebuffer.c
++++ b/drivers/gpu/drm/drm_framebuffer.c
+@@ -192,6 +192,7 @@ static int format_check(const struct drm_mode_fb_cmd2 *r)
+ case DRM_FORMAT_YVU422:
+ case DRM_FORMAT_YUV444:
+ case DRM_FORMAT_YVU444:
++ case DRM_FORMAT_R8:
+ return 0;
+ default:
+ format_name = drm_get_format_name(r->pixel_format);
+diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+index 45d6e7e..bdf2612 100644
+--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+@@ -104,6 +104,11 @@ struct rcar_du_device {
+ struct {
+ struct drm_property *alpha;
+ struct drm_property *colorkey;
++ struct drm_property *alphaplane;
++ struct drm_property *blend;
++ struct drm_property *ckey;
++ struct drm_property *ckey_set0;
++ struct drm_property *ckey_set1;
+ } props;
+
+ unsigned int dpad0_source;
+diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+index e955e92..31b48bc 100644
+--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+@@ -10,7 +10,7 @@
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+-
++//#define DEBUG
+ #include <drm/drmP.h>
+ #include <drm/drm_atomic.h>
+ #include <drm/drm_atomic_helper.h>
+@@ -101,6 +101,12 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = {
+ .planes = 2,
+ .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,
+ .edf = PnDDCR4_EDF_NONE,
++ }, {
++ .fourcc = DRM_FORMAT_R8,
++ .bpp = 8,
++ .planes = 1,
++ .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_8BPP,
++ .edf = PnDDCR4_EDF_NONE,
+ },
+ };
+
+@@ -169,6 +175,10 @@ static const struct rcar_du_format_info rcar_vsp_format_infos[] = {
+ .fourcc = DRM_FORMAT_YVU444,
+ .bpp = 24,
+ .planes = 3,
++ }, {
++ .fourcc = DRM_FORMAT_R8,
++ .bpp = 8,
++ .planes = 1,
+ },
+ };
+
+@@ -565,6 +575,36 @@ static int rcar_du_properties_init(struct rcar_du_device *rcdu)
+ if (rcdu->props.colorkey == NULL)
+ return -ENOMEM;
+
++ rcdu->props.alphaplane =
++ drm_property_create(rcdu->ddev, DRM_MODE_PROP_OBJECT, "alphaplane", 1);
++ if (rcdu->props.alphaplane == NULL)
++ return -ENOMEM;
++ rcdu->props.alphaplane->values[0] = DRM_MODE_OBJECT_FB;
++
++ rcdu->props.blend =
++ drm_property_create_range(rcdu->ddev, 0, "blend",
++ 0, 0xffffffff);
++ if (rcdu->props.blend == NULL)
++ return -ENOMEM;
++
++ rcdu->props.ckey =
++ drm_property_create_range(rcdu->ddev, 0, "ckey",
++ 0, 0xffffffff);
++ if (rcdu->props.ckey == NULL)
++ return -ENOMEM;
++
++ rcdu->props.ckey_set0 =
++ drm_property_create_range(rcdu->ddev, 0, "ckey_set0",
++ 0, 0xffffffff);
++ if (rcdu->props.ckey_set0 == NULL)
++ return -ENOMEM;
++
++ rcdu->props.ckey_set1 =
++ drm_property_create_range(rcdu->ddev, 0, "ckey_set1",
++ 0, 0xffffffff);
++ if (rcdu->props.ckey_set1 == NULL)
++ return -ENOMEM;
++
+ return 0;
+ }
+
+diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+index e408aa3..2b57f09 100644
+--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+@@ -10,7 +10,7 @@
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+-
++//#define DEBUG
+ #include <drm/drmP.h>
+ #include <drm/drm_atomic.h>
+ #include <drm/drm_atomic_helper.h>
+@@ -719,6 +719,7 @@ static const uint32_t formats[] = {
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_NV21,
+ DRM_FORMAT_NV16,
++ DRM_FORMAT_R8,
+ };
+
+ int rcar_du_planes_init(struct rcar_du_group *rgrp)
+diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+index c1de338..a6065ef 100644
+--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
++++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+@@ -66,6 +66,11 @@ struct rcar_du_plane_state {
+
+ unsigned int alpha;
+ unsigned int colorkey;
++ struct drm_framebuffer *alphaplane;
++ unsigned int blend;
++ unsigned int ckey;
++ unsigned int ckey_set0;
++ unsigned int ckey_set1;
+ };
+
+ static inline struct rcar_du_plane_state *
+diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+index 770238a..910e0f0 100644
+--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+@@ -10,7 +10,7 @@
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+-
++//#define DEBUG
+ #include <drm/drmP.h>
+ #include <drm/drm_atomic.h>
+ #include <drm/drm_atomic_helper.h>
+@@ -91,6 +91,16 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
+
+ void rcar_du_vsp_disable(struct rcar_du_crtc *crtc)
+ {
++ struct rcar_du_vsp *vsp = crtc->vsp;
++ struct rcar_du_vsp_plane *primary = &vsp->planes[0];
++ struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(primary->plane.state);
++
++ /* ...drop alpha-plane associated with primary plane (why only primary? - tbd) */
++ if (rstate->alphaplane) {
++ drm_framebuffer_unreference(rstate->alphaplane);
++ rstate->alphaplane = NULL;
++ }
++
+ vsp1_du_setup_lif(crtc->vsp->vsp, NULL, crtc->lif_index,
+ crtc->suspend);
+ }
+@@ -133,6 +143,7 @@ static const u32 formats_kms[] = {
+ DRM_FORMAT_YVU422,
+ DRM_FORMAT_YUV444,
+ DRM_FORMAT_YVU444,
++ DRM_FORMAT_R8,
+ };
+
+ static const u32 formats_v4l2[] = {
+@@ -162,6 +173,7 @@ static const u32 formats_v4l2[] = {
+ V4L2_PIX_FMT_YVU422M,
+ V4L2_PIX_FMT_YUV444M,
+ V4L2_PIX_FMT_YVU444M,
++ V4L2_PIX_FMT_GREY,
+ };
+
+ static const u32 formats_xlate[][2] = {
+@@ -184,6 +196,7 @@ static const u32 formats_xlate[][2] = {
+ { DRM_FORMAT_NV21, V4L2_PIX_FMT_NV21M },
+ { DRM_FORMAT_NV16, V4L2_PIX_FMT_NV16M },
+ { DRM_FORMAT_NV61, V4L2_PIX_FMT_NV61M },
++ { DRM_FORMAT_R8, V4L2_PIX_FMT_GREY },
+ };
+
+ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
+@@ -226,6 +239,27 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
+ }
+ }
+
++ /* ...add alpha-plane as needed */
++ if (state->alphaplane) {
++ i = state->format->planes;
++ cfg.alpha_mem = sg_dma_address(state->sg_tables[i].sgl);
++ cfg.alpha_pitch = state->alphaplane->pitches[0];
++ pr_debug("alpha-%d: set alpha-mem address: %llx, pitch=%d\n", i, (unsigned long long)cfg.alpha_mem, cfg.alpha_pitch);
++ }
++
++ /* ...add blending formula as needed */
++ if (state->blend) {
++ cfg.blend = state->blend;
++ pr_debug("set blending formula: %X\n", cfg.blend);
++ }
++
++ /* ...add color key property as needed */
++ if (state->ckey) {
++ cfg.ckey = state->ckey;
++ cfg.ckey_set0 = state->ckey_set0;
++ cfg.ckey_set1 = state->ckey_set1;
++ }
++
+ vsp1_du_atomic_update(plane->vsp->vsp, plane->index, &cfg);
+ }
+
+@@ -259,6 +293,23 @@ static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane,
+ }
+ }
+
++ /* ...check if we have alpha-plane attached */
++ if (rstate->alphaplane) {
++ struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(rstate->alphaplane, 0);
++ struct sg_table *sgt = &rstate->sg_tables[i++];
++
++ ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr, gem->base.size);
++ if (ret)
++ goto fail;
++
++ ret = vsp1_du_map_sg(vsp->vsp, sgt);
++ if (!ret) {
++ sg_free_table(sgt);
++ ret = -ENOMEM;
++ goto fail;
++ }
++ }
++
+ return 0;
+
+ fail:
+@@ -288,6 +339,14 @@ static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane,
+ vsp1_du_unmap_sg(vsp->vsp, sgt);
+ sg_free_table(sgt);
+ }
++
++ if (rstate->alphaplane) {
++ struct sg_table *sgt = &rstate->sg_tables[i];
++
++ vsp1_du_unmap_sg(vsp->vsp, sgt);
++ sg_free_table(sgt);
++ pr_debug("unmap alpha-plane\n");
++ }
+ }
+
+ static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane,
+@@ -369,6 +428,11 @@ rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane)
+ if (copy == NULL)
+ return NULL;
+
++ if (copy->alphaplane) {
++ drm_framebuffer_reference(copy->alphaplane);
++ pr_debug("duplicate alpha-plane '%p' (refcount=%d)\n", copy->alphaplane, drm_framebuffer_read_refcount(copy->alphaplane));
++ }
++
+ __drm_atomic_helper_plane_duplicate_state(plane, &copy->state);
+
+ return &copy->state;
+@@ -377,8 +441,15 @@ rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane)
+ static void rcar_du_vsp_plane_atomic_destroy_state(struct drm_plane *plane,
+ struct drm_plane_state *state)
+ {
++ struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
++
++ if (rstate->alphaplane) {
++ pr_debug("unref alpha-plane '%p' (refcount=%d)\n", rstate->alphaplane, drm_framebuffer_read_refcount(rstate->alphaplane));
++ drm_framebuffer_unreference(rstate->alphaplane);
++ }
++
+ __drm_atomic_helper_plane_destroy_state(state);
+- kfree(to_rcar_vsp_plane_state(state));
++ kfree(rstate);
+ }
+
+ static void rcar_du_vsp_plane_reset(struct drm_plane *plane)
+@@ -386,6 +457,7 @@ static void rcar_du_vsp_plane_reset(struct drm_plane *plane)
+ struct rcar_du_vsp_plane_state *state;
+
+ if (plane->state) {
++ pr_debug("reset plane '%p'\n", to_rcar_vsp_plane_state(plane->state)->alphaplane);
+ rcar_du_vsp_plane_atomic_destroy_state(plane, plane->state);
+ plane->state = NULL;
+ }
+@@ -410,7 +482,30 @@ static int rcar_du_vsp_plane_atomic_set_property(struct drm_plane *plane,
+
+ if (property == rcdu->props.alpha)
+ rstate->alpha = val;
+- else
++ else if (property == rcdu->props.blend)
++ rstate->blend = val;
++ else if (property == rcdu->props.ckey)
++ rstate->ckey = val;
++ else if (property == rcdu->props.ckey_set0)
++ rstate->ckey_set0 = val;
++ else if (property == rcdu->props.ckey_set1)
++ rstate->ckey_set1 = val;
++ else if (property == rcdu->props.alphaplane) {
++ if (rstate->alphaplane) {
++ pr_debug("unref alpha-plane '%p' (refcount=%d)\n", rstate->alphaplane, drm_framebuffer_read_refcount(rstate->alphaplane));
++ drm_framebuffer_unreference(rstate->alphaplane);
++ }
++ rstate->alphaplane = drm_framebuffer_lookup(plane->dev, val);
++ if (rstate->alphaplane) {
++ pr_debug("use alpha-plane '%p' (refcount=%d)\n", rstate->alphaplane, drm_framebuffer_read_refcount(rstate->alphaplane));
++ /* ...the way how we handle this leads to a "loss" of plane reference (it is acquired
++ * within "drm_property_change_valid_get" but not returned in symmetric "drm_property_change_valid_put")
++ * Whether it is a bug or was done intentionally, I don't know. For a moment just drop that
++ * extra reference right here
++ */
++ if (0) drm_framebuffer_unreference(rstate->alphaplane);
++ }
++ } else
+ return -EINVAL;
+
+ return 0;
+@@ -426,6 +521,16 @@ static int rcar_du_vsp_plane_atomic_get_property(struct drm_plane *plane,
+
+ if (property == rcdu->props.alpha)
+ *val = rstate->alpha;
++ else if (property == rcdu->props.alphaplane)
++ *val = (rstate->alphaplane ? rstate->alphaplane->base.id : 0);
++ else if (property == rcdu->props.blend)
++ *val = rstate->blend;
++ else if (property == rcdu->props.ckey)
++ *val = rstate->ckey;
++ else if (property == rcdu->props.ckey_set0)
++ *val = rstate->ckey_set0;
++ else if (property == rcdu->props.ckey_set1)
++ *val = rstate->ckey_set1;
+ else
+ return -EINVAL;
+
+@@ -442,9 +547,10 @@ int rcar_du_vsp_write_back(struct drm_device *dev, void *data,
+ struct rcar_du_crtc *rcrtc;
+ struct rcar_du_device *rcdu;
+ const struct drm_display_mode *mode;
+- u32 pixelformat, bpp;
+- unsigned int pitch;
++ struct drm_framebuffer *fb;
+ dma_addr_t mem[3];
++ struct sg_table sg_tables[3];
++ int i = 0;
+
+ obj = drm_mode_object_find(dev, sh->crtc_id, DRM_MODE_OBJECT_CRTC);
+ if (!obj)
+@@ -455,62 +561,79 @@ int rcar_du_vsp_write_back(struct drm_device *dev, void *data,
+ rcdu = rcrtc->group->dev;
+ mode = &rcrtc->crtc.state->adjusted_mode;
+
+- switch (sh->fmt) {
+- case DRM_FORMAT_RGB565:
+- bpp = 16;
+- pixelformat = V4L2_PIX_FMT_RGB565;
+- break;
+- case DRM_FORMAT_ARGB1555:
+- bpp = 16;
+- pixelformat = V4L2_PIX_FMT_ARGB555;
+- break;
+- case DRM_FORMAT_ARGB8888:
+- bpp = 32;
+- pixelformat = V4L2_PIX_FMT_ABGR32;
+- break;
+- default:
+- dev_err(rcdu->dev, "specified format is not supported.\n");
++ fb = drm_framebuffer_lookup(dev, sh->buff);
++ if (!fb) {
++ dev_err(dev->dev, "failed to lookup destination framebuffer '%lu'\n", sh->buff);
+ return -EINVAL;
+ }
+
+- pitch = mode->hdisplay * bpp / 8;
++ /* ...check framebuffer is okay */
++ if ((fb->width != (mode->hdisplay)) ||
++ (fb->height != (mode->vdisplay))) {
++ dev_err(dev->dev, "wrong fb mode: %d*%d vs %d*%d\n", fb->width, fb->height, mode->hdisplay, mode->vdisplay);
++ ret = -EINVAL;
++ goto done;
++ }
+
+- mem[0] = sh->buff;
+- mem[1] = 0;
+- mem[2] = 0;
++ /* ...need to verify compatibility of output format, I guess - tbd */
+
+- if ((sh->width != (mode->hdisplay)) ||
+- (sh->height != (mode->vdisplay)))
+- return -EINVAL;
++ /* ...fill memory planes addresses */
++ for (i = 0; i < 3; i++) {
++ struct drm_gem_cma_object *gem;
++ struct sg_table *sgt = &sg_tables[i];
++ gem = drm_fb_cma_get_gem_obj(fb, i);
++ if (!gem)
++ break;
++ ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr,
++ gem->base.size);
++ if (ret)
++ goto done;
+
+- if ((pitch * mode->vdisplay) > sh->buff_len)
+- return -EINVAL;
++ ret = vsp1_du_map_sg(rcrtc->vsp->vsp, sgt);
++ if (!ret) {
++ sg_free_table(sgt);
++ ret = -ENOMEM;
++ goto done;
++ }
++ mem[i] = sg_dma_address(sg_tables[i].sgl) + fb->offsets[i];
++ }
++
++ dev_info(dev->dev, "setup write-back (pixfmt=%X, %u*%u, planes: %d)\n", fb->pixel_format, fb->width, fb->height, i);
++
++ vsp1_du_setup_wb(rcrtc->vsp->vsp, fb->pixel_format, fb->pitches[0], mem, rcrtc->lif_index);
+
+- vsp1_du_setup_wb(rcrtc->vsp->vsp, pixelformat, pitch, mem,
+- rcrtc->lif_index);
+ ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_SET,
+ rcrtc->lif_index);
+ if (ret != 0)
+- return ret;
++ goto done;
+
+ ret = rcar_du_async_commit(dev, crtc);
+ if (ret != 0)
+- return ret;
++ goto done;
+
+ ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_START,
+ rcrtc->lif_index);
+ if (ret != 0)
+- return ret;
++ goto done;
+
+ ret = rcar_du_async_commit(dev, crtc);
+ if (ret != 0)
+- return ret;
++ goto done;
+
+ ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_DONE,
+ rcrtc->lif_index);
+ if (ret != 0)
+- return ret;
++ goto done;
++
++done:
++ /* ...unmap all tables */
++ while (i--) {
++ struct sg_table *sgt = &sg_tables[i];
++ vsp1_du_unmap_sg(rcrtc->vsp->vsp, sgt);
++ sg_free_table(sgt);
++ }
+
++ drm_framebuffer_unreference(fb);
+ return ret;
+ }
+
+@@ -574,6 +697,7 @@ static const uint32_t formats[] = {
+ DRM_FORMAT_NV21,
+ DRM_FORMAT_NV16,
+ DRM_FORMAT_NV61,
++ DRM_FORMAT_R8,
+ };
+
+ int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
+@@ -653,13 +777,24 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
+ drm_plane_helper_add(&plane->plane,
+ &rcar_du_vsp_plane_helper_funcs);
+
++#if 0 // ...use same set of properties for all planes
+ if (type == DRM_PLANE_TYPE_PRIMARY)
+ continue;
+-
++#endif
+ drm_object_attach_property(&plane->plane.base,
+ rcdu->props.alpha, 255);
+ drm_plane_create_zpos_property(&plane->plane, 1, 1,
+ vsp->num_planes - 1);
++ drm_object_attach_property(&plane->plane.base,
++ rcdu->props.alphaplane, 0);
++ drm_object_attach_property(&plane->plane.base,
++ rcdu->props.blend, 0);
++ drm_object_attach_property(&plane->plane.base,
++ rcdu->props.ckey, 0);
++ drm_object_attach_property(&plane->plane.base,
++ rcdu->props.ckey_set0, 0);
++ drm_object_attach_property(&plane->plane.base,
++ rcdu->props.ckey_set1, 0);
+ }
+
+ return 0;
+diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
+index 3fd9cef..2f4aa41 100644
+--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
++++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
+@@ -52,10 +52,15 @@ struct rcar_du_vsp_plane_state {
+ struct drm_plane_state state;
+
+ const struct rcar_du_format_info *format;
+- struct sg_table sg_tables[3];
++ struct sg_table sg_tables[4];
+
+ unsigned int alpha;
+ unsigned int zpos;
++ struct drm_framebuffer *alphaplane;
++ unsigned int blend;
++ unsigned int ckey;
++ unsigned int ckey_set0;
++ unsigned int ckey_set1;
+ };
+
+ static inline struct rcar_du_vsp_plane_state *
+--
+2.7.4
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch
new file mode 100644
index 0000000..2f6fa35
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch
@@ -0,0 +1,367 @@
+From 0cbfce87c1a16b80111cdcecdd703ad5f75cc6e7 Mon Sep 17 00:00:00 2001
+From: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com>
+Date: Tue, 14 Nov 2017 01:41:06 -0800
+Subject: [PATCH] media: platform: vsp1: extend DRM-VSP1 interface
+
+- Extend DRM-VSP1 interface
+- Add alpha-plane support for VSP1
+
+Signed-off-by: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com>
+---
+ drivers/media/platform/vsp1/vsp1_bru.c | 13 ++++++++++++-
+ drivers/media/platform/vsp1/vsp1_dl.c | 5 +++++
+ drivers/media/platform/vsp1/vsp1_drm.c | 34 ++++++++++++++++++++++++++-------
+ drivers/media/platform/vsp1/vsp1_lif.c | 2 +-
+ drivers/media/platform/vsp1/vsp1_pipe.c | 4 ++++
+ drivers/media/platform/vsp1/vsp1_rpf.c | 24 ++++++++++++++++++++---
+ drivers/media/platform/vsp1/vsp1_rwpf.c | 2 +-
+ drivers/media/platform/vsp1/vsp1_rwpf.h | 6 ++++++
+ drivers/media/platform/vsp1/vsp1_wpf.c | 4 +++-
+ include/media/vsp1.h | 6 ++++++
+ 10 files changed, 86 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
+index 8b3164a..2c131be 100644
+--- a/drivers/media/platform/vsp1/vsp1_bru.c
++++ b/drivers/media/platform/vsp1/vsp1_bru.c
+@@ -387,6 +387,16 @@ static void bru_configure(struct vsp1_entity *entity,
+ ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i);
+
+ vsp1_bru_write(bru, dl, VI6_BRU_CTRL(i), ctrl);
++ dev_dbg(entity->vsp1->dev, "bru#%d: ctrl=%X\n", i, ctrl);
++
++ /* ...set blending formula as defined by the input RPF */
++ if (bru->inputs[i].rpf) {
++ if (bru->inputs[i].rpf->blend) {
++ vsp1_bru_write(bru, dl, VI6_BRU_BLD(i), bru->inputs[i].rpf->blend);
++ dev_dbg(entity->vsp1->dev, "bru#%d(#%d): setup blending formula: %X\n", i, bru->inputs[i].rpf->entity.index, bru->inputs[i].rpf->blend);
++ continue;
++ }
++ }
+
+ /* Harcode the blending formula to
+ *
+@@ -441,7 +451,8 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1)
+ v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR,
+ 0, 0xffffff, 1, 0);
+
+- bru->bgcolor = 0;
++ /* ...for YUV, set black background */
++ bru->bgcolor = 0x00800080;
+
+ bru->entity.subdev.ctrl_handler = &bru->ctrls;
+
+diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c
+index 478e093..f9c6d09 100644
+--- a/drivers/media/platform/vsp1/vsp1_dl.c
++++ b/drivers/media/platform/vsp1/vsp1_dl.c
+@@ -272,6 +272,7 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_list *dl, struct vsp1_rwpf *rpf)
+ u32 y_top_index, y_bot_index;
+ u32 u_top_index, u_bot_index;
+ u32 v_top_index, v_bot_index;
++ u32 alpha_index;
+ dma_addr_t y_top_addr, y_bot_addr;
+ dma_addr_t u_top_addr, u_bot_addr;
+ dma_addr_t v_top_addr, v_bot_addr;
+@@ -287,6 +288,7 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_list *dl, struct vsp1_rwpf *rpf)
+ u_bot_index = rpf->entity.index * 8 + 3;
+ v_top_index = rpf->entity.index * 8 + 4;
+ v_bot_index = rpf->entity.index * 8 + 5;
++ alpha_index = rpf->entity.index * 8 + 6;
+
+ switch (rpf->fmtinfo->fourcc) {
+ case V4L2_PIX_FMT_YUV420M:
+@@ -359,6 +361,9 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_list *dl, struct vsp1_rwpf *rpf)
+ dl->src_dst_addr[u_bot_index].addr = u_bot_addr;
+ dl->src_dst_addr[v_top_index].addr = v_top_addr;
+ dl->src_dst_addr[v_bot_index].addr = v_bot_addr;
++
++ /* ...set alpha-plane address as needed */
++ dl->src_dst_addr[alpha_index].addr = rpf->mem.alpha;
+ }
+
+ static struct vsp1_dl_list *vsp1_dl_list_alloc(struct vsp1_dl_manager *dlm)
+diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
+index 2681c8a..542ca5a 100644
+--- a/drivers/media/platform/vsp1/vsp1_drm.c
++++ b/drivers/media/platform/vsp1/vsp1_drm.c
+@@ -10,7 +10,7 @@
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+-
++//#define DEBUG
+ #include <linux/device.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/slab.h>
+@@ -201,7 +201,9 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg,
+
+ format.format.width = cfg->width;
+ format.format.height = cfg->height;
+- format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
++ //format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
++ /* ...always blend in YUV colorspace; apply conversion as needed */
++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32;
+ format.format.field = V4L2_FIELD_NONE;
+
+ ret = v4l2_subdev_call(&brs->entity.subdev, pad,
+@@ -222,7 +224,9 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg,
+
+ format.format.width = cfg->width;
+ format.format.height = cfg->height;
+- format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
++ //format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
++ /* ...always blend in YUV colorspace; apply conversion as needed */
++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32;
+ format.format.field = V4L2_FIELD_NONE;
+
+ ret = v4l2_subdev_call(&bru->entity.subdev, pad,
+@@ -241,7 +245,8 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg,
+
+ format.format.width = cfg->width;
+ format.format.height = cfg->height;
+- format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
++ //format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32;
+ format.format.field = V4L2_FIELD_NONE;
+
+ if (lif_index == 1) {
+@@ -275,6 +280,13 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg,
+ format.format.code, lif_index);
+
+ format.pad = RWPF_PAD_SOURCE;
++ /* ...force conversion back to ARGB at the output */
++ format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
++ ret = v4l2_subdev_call(&vsp1->wpf[0]->entity.subdev, pad, set_fmt, NULL,
++ &format);
++ if (ret < 0)
++ return ret;
++
+ ret = v4l2_subdev_call(&vsp1->wpf[lif_index]->entity.subdev,
+ pad, get_fmt, NULL, &format);
+ if (ret < 0)
+@@ -402,12 +414,12 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
+ }
+
+ dev_dbg(vsp1->dev,
+- "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad, %pad } zpos %u\n",
++ "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad, %pad } zpos %u, alpha %pad, ckey %x/%x/%x\n",
+ __func__, rpf_index,
+ cfg->src.left, cfg->src.top, cfg->src.width, cfg->src.height,
+ cfg->dst.left, cfg->dst.top, cfg->dst.width, cfg->dst.height,
+ cfg->pixelformat, cfg->pitch, &cfg->mem[0], &cfg->mem[1],
+- &cfg->mem[2], cfg->zpos);
++ &cfg->mem[2], cfg->zpos, &cfg->alpha_mem, cfg->ckey, cfg->ckey_set0, cfg->ckey_set1);
+
+ /*
+ * Store the format, stride, memory buffer address, crop and compose
+@@ -432,6 +444,11 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
+ rpf->format.plane_fmt[1].bytesperline = cfg->pitch;
+ rpf->alpha = cfg->alpha;
+ rpf->interlaced = cfg->interlaced;
++ rpf->alpha_pitch = cfg->alpha_pitch;
++ rpf->ckey = cfg->ckey;
++ rpf->ckey_set0 = cfg->ckey_set0;
++ rpf->ckey_set1 = cfg->ckey_set1;
++ rpf->blend = cfg->blend;
+
+ if ((vsp1->ths_quirks & VSP1_AUTO_FLD_NOT_SUPPORT) &&
+ rpf->interlaced) {
+@@ -443,6 +460,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
+ rpf->mem.addr[0] = cfg->mem[0];
+ rpf->mem.addr[1] = cfg->mem[1];
+ rpf->mem.addr[2] = cfg->mem[2];
++ rpf->mem.alpha = cfg->alpha_mem;
+
+ vsp1->drm->inputs[rpf_index].crop = cfg->src;
+ vsp1->drm->inputs[rpf_index].compose = cfg->dst;
+@@ -517,7 +535,9 @@ static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
+ __func__, format.format.width, format.format.height,
+ format.format.code, rpf->entity.index);
+
+- format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
++ //format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
++ /* ...do blending in YUV color-space; apply conversion as needed */
++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32;
+
+ ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL,
+ &format);
+diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
+index e79f9e6..753763d 100644
+--- a/drivers/media/platform/vsp1/vsp1_lif.c
++++ b/drivers/media/platform/vsp1/vsp1_lif.c
+@@ -162,7 +162,7 @@ static void lif_configure(struct vsp1_entity *entity,
+
+ vsp1_lif_write(lif, dl, VI6_LIF_CTRL(lif->entity.index),
+ (obth << VI6_LIF_CTRL_OBTH_SHIFT) |
+- (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) |
++ (format->code != MEDIA_BUS_FMT_ARGB8888_1X32 ? VI6_LIF_CTRL_CFMT : 0) |
+ VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN);
+
+ if (soc_device_match(r8a7797))
+diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
+index 8379962..86d4a85 100644
+--- a/drivers/media/platform/vsp1/vsp1_pipe.c
++++ b/drivers/media/platform/vsp1/vsp1_pipe.c
+@@ -137,6 +137,10 @@ static const struct vsp1_format_info vsp1_video_formats[] = {
+ VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+ VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+ 3, { 8, 8, 8 }, false, false, 1, 1, false },
++ { V4L2_PIX_FMT_GREY, MEDIA_BUS_FMT_Y8_1X8,
++ /*VI6_FMT_Y_U_V_444*/0xDEAD, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
++ VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
++ 1, { 8, 0, 0 }, false, false, 0, 0, false },
+ };
+
+ /**
+diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
+index ff25470..2cce294 100644
+--- a/drivers/media/platform/vsp1/vsp1_rpf.c
++++ b/drivers/media/platform/vsp1/vsp1_rpf.c
+@@ -10,7 +10,7 @@
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+-
++//#define DEBUG
+ #include <linux/device.h>
+
+ #include <media/v4l2-subdev.h>
+@@ -253,8 +253,10 @@ static void rpf_configure(struct vsp1_entity *entity,
+ if (sink_format->code != source_format->code)
+ infmt |= VI6_RPF_INFMT_CSC;
+
++ dev_dbg(vsp1->dev, "rpf#%d: infmt=%x (csc=%d)\n", rpf->entity.index, infmt, !!(infmt & VI6_RPF_INFMT_CSC));
++
+ vsp1_rpf_write(rpf, dl, VI6_RPF_INFMT, infmt);
+- vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap);
++ vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap | 0xF00);
+
+ /* Output location */
+ if (pipe->bru) {
+@@ -288,6 +290,15 @@ static void rpf_configure(struct vsp1_entity *entity,
+ (left << VI6_RPF_LOC_HCOORD_SHIFT) |
+ (top << VI6_RPF_LOC_VCOORD_SHIFT));
+
++ // ...setup alpha-plane as required
++ if (rpf->mem.alpha) {
++ vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_AI, rpf->mem.alpha);
++ vsp1_rpf_write(rpf, dl, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_ASEL_8B_PLANE);
++ vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ASTRIDE, rpf->alpha_pitch);
++ dev_dbg(vsp1->dev, "rpf#%d: setup alpha-plane: buffer=%pad, stride=%u\n", rpf->entity.index, &rpf->mem.alpha, rpf->alpha_pitch);
++ goto out;
++ }
++
+ /* On Gen2 use the alpha channel (extended to 8 bits) when available or
+ * a fixed alpha value set through the V4L2_CID_ALPHA_COMPONENT control
+ * otherwise.
+@@ -342,7 +353,9 @@ static void rpf_configure(struct vsp1_entity *entity,
+ if (entity->vsp1->info->gen == 3) {
+ u32 mult;
+
+- if ((fmtinfo->alpha) &&
++ dev_dbg(vsp1->dev, "rpf#%d: alpha=%x, fourcc=%x\n", rpf->entity.index, fmtinfo->alpha, fmtinfo->fourcc);
++
++ if (0 && (fmtinfo->alpha) &&
+ (fmtinfo->fourcc != V4L2_PIX_FMT_ARGB555)) {
+ /* When the input contains an alpha channel enable the
+ * alpha multiplier. If the input is premultiplied we
+@@ -371,9 +384,14 @@ static void rpf_configure(struct vsp1_entity *entity,
+ rpf->mult_alpha = mult;
+ }
+
++out:
+ vsp1_rpf_write(rpf, dl, VI6_RPF_MSK_CTRL, 0);
+ vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_CTRL, 0);
+
++ /* ...set up color keying */
++ vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_CTRL, rpf->ckey);
++ vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_SET0, rpf->ckey_set0);
++ vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_SET1, rpf->ckey_set1);
+ }
+
+ static const struct vsp1_entity_operations rpf_entity_ops = {
+diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c
+index 66e4d7e..d7e730f 100644
+--- a/drivers/media/platform/vsp1/vsp1_rwpf.c
++++ b/drivers/media/platform/vsp1/vsp1_rwpf.c
+@@ -10,7 +10,7 @@
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+-
++//#define DEBUG
+ #include <media/v4l2-subdev.h>
+
+ #include "vsp1.h"
+diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
+index fbe6aa6..7553f2b 100644
+--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
++++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
+@@ -33,6 +33,7 @@ struct vsp1_video;
+
+ struct vsp1_rwpf_memory {
+ dma_addr_t addr[3];
++ dma_addr_t alpha;
+ };
+
+ struct vsp1_rwpf {
+@@ -72,6 +73,11 @@ struct vsp1_rwpf {
+
+ int write_back;
+ dma_addr_t buf_addr[3];
++ unsigned int alpha_pitch;
++ unsigned int ckey;
++ unsigned int ckey_set0;
++ unsigned int ckey_set1;
++ unsigned int blend;
+ };
+
+ static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev)
+diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
+index e8b3cfb..cb81848 100644
+--- a/drivers/media/platform/vsp1/vsp1_wpf.c
++++ b/drivers/media/platform/vsp1/vsp1_wpf.c
+@@ -10,7 +10,7 @@
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+-
++//#define DEBUG
+ #include <linux/device.h>
+
+ #include <media/v4l2-subdev.h>
+@@ -358,6 +358,8 @@ static void wpf_configure(struct vsp1_entity *entity,
+
+ wpf->outfmt = outfmt;
+
++ dev_dbg(vsp1->dev, "wpf#%d: outfmt=%x (csc=%d)\n", wpf->entity.index, outfmt, !!(outfmt & VI6_WPF_OUTFMT_CSC));
++
+ vsp1_dl_list_write(dl, VI6_DPR_WPF_FPORCH(wpf->entity.index),
+ VI6_DPR_WPF_FPORCH_FP_WPFN);
+
+diff --git a/include/media/vsp1.h b/include/media/vsp1.h
+index d5d93ed..c1c3201 100644
+--- a/include/media/vsp1.h
++++ b/include/media/vsp1.h
+@@ -53,11 +53,17 @@ struct vsp1_du_atomic_config {
+ u32 pixelformat;
+ unsigned int pitch;
+ dma_addr_t mem[3];
++ dma_addr_t alpha_mem;
++ unsigned int alpha_pitch;
++ unsigned int ckey;
++ unsigned int ckey_set0;
++ unsigned int ckey_set1;
+ struct v4l2_rect src;
+ struct v4l2_rect dst;
+ unsigned int alpha;
+ unsigned int zpos;
+ bool interlaced;
++ unsigned int blend;
+ };
+
+ void vsp1_du_atomic_begin(struct device *dev, unsigned int lif_index);
+--
+2.7.4
+
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
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend
index 57a1ee6..d73c1e3 100644
--- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend
@@ -69,6 +69,12 @@ SRC_URI_append = " \
file://0079-ASoC-fix-pcm-creation-regression.patch \
"
+SRC_URI_append_r8a7797 = " \
+ file://0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch \
+ file://0104-media-vsp1-extend-DRM-VSP1-interface.patch \
+ file://0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch \
+"
+
SRC_URI_append_h3ulcb = " file://ulcb.cfg"
SRC_URI_append_m3ulcb = " file://ulcb.cfg"
SRC_URI_append_salvator-x = " file://salvator-x.cfg"