summaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch')
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch327
1 files changed, 327 insertions, 0 deletions
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch
new file mode 100644
index 0000000..1c8d800
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch
@@ -0,0 +1,327 @@
+From a6fd88487f2dda6f8c5ec28230129478711206fb Mon Sep 17 00:00:00 2001
+From: Andrey Dolnikov <andrey.dolnikov@cogentembedded.com>
+Date: Tue, 6 Feb 2018 13:38:34 +0300
+Subject: [PATCH] media: rcar-imr: Add RSE support
+
+This adds RSE support for V3H IMR
+
+Signed-off-by: Andrey Dolnikov <andrey.dolnikov@cogentembedded.com>
+---
+ drivers/media/platform/rcar_imr.c | 143 +++++++++++++++++++++++++++++++
+ include/uapi/linux/rcar-imr.h | 22 ++++-
+ 2 files changed, 165 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c
+index 9b601da..7b16765 100644
+--- a/drivers/media/platform/rcar_imr.c
++++ b/drivers/media/platform/rcar_imr.c
+@@ -17,6 +17,7 @@
+ #include <linux/pm_runtime.h>
+ #include <linux/delay.h>
+ #include <linux/rcar-imr.h>
++#include <linux/of.h>
+ #include <media/v4l2-device.h>
+ #include <media/v4l2-ctrls.h>
+ #include <media/v4l2-fh.h>
+@@ -38,6 +39,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-4)");
+ * Local types definitions
+ ******************************************************************************/
+
++/* Number of RSE planes on V3H (non scaled, 1/2, 1/4, 1/8) */
++#define RSE_PLANES_NUM 4
++
+ /* ...configuration data */
+ struct imr_cfg {
+ /* ...display-list main program data */
+@@ -49,6 +53,21 @@ struct imr_cfg {
+ /* ...pointers to the source/destination planes */
+ u32 *src_pa_ptr[2];
+ u32 *dst_pa_ptr[2];
++ /* ...pointers to the RSE destination planes */
++ u32 *dstn_pa_ptr[RSE_PLANES_NUM];
++ u32 *dstr_pa_ptr[RSE_PLANES_NUM];
++
++ /* ...offsets to RSE destination planes */
++ u32 dstnr_offsets[IMR_EXTDST_NUM];
++
++ /* ...RSE logical right shift data */
++ u32 *rscr_ptr;
++ u8 rscr_sc8, rscr_sc4, rscr_sc2;
++
++ /* ...RSE destination stride values */
++ u32 dstnr_strides[IMR_EXTDST_NUM];
++ u32 *striden_ptr[RSE_PLANES_NUM];
++ u32 *strider_ptr[RSE_PLANES_NUM];
+
+ /* ...subpixel destination coordinates space */
+ int dst_subpixel;
+@@ -96,6 +115,8 @@ struct imr_device {
+ struct v4l2_m2m_dev *m2m_dev;
+ struct device *alloc_dev;
+
++ bool rse;
++
+ /* ...do we need that counter really? framework counts fh structures for us - tbd */
+ int refcount;
+
+@@ -219,6 +240,18 @@ struct imr_ctx {
+
+ #define IMR_TPOR 0xF0
+
++#define IMR_RSCSR 0x204
++#define IMR_RSCCR 0x208
++#define IMR_RSCR_RSE 31
++#define IMR_RSCR_SC8 25
++#define IMR_RSCR_SC4 21
++#define IMR_RSCR_SC2 17
++
++#define IMR_DSANRR0 0x210
++#define IMR_DSTNRR0 0x214
++#define IMR_DSARR0 0x218
++#define IMR_DSTRR0 0x21C
++
+ /*******************************************************************************
+ * Auxiliary helpers
+ ******************************************************************************/
+@@ -398,6 +431,7 @@ static int imr_queue_setup(struct vb2_queue *vq,
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_Y10:
++ case V4L2_PIX_FMT_Y12:
+ case V4L2_PIX_FMT_Y16:
+ sizes[0] = w * h * 2;
+ break;
+@@ -750,6 +784,7 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
+ int W = ctx->queue[1].fmt.width;
+ int H = ctx->queue[1].fmt.height;
+ u32 tricr = ctx->color & 0xFFFFFF;
++ int i;
+
+ v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "setup %u*%u -> %u*%u mapping (type=%x)\n", w, h, W, H, type);
+
+@@ -775,6 +810,38 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
+ *dl++ = IMR_OP_WTS(IMR_CMRCCR, 0xFFFF);
+ *dl++ = IMR_OP_WTS(IMR_CMRCCR2, 0xFFFF);
+
++ if (type & IMR_MAP_RSE) {
++ /* ...enable RSE */
++ *dl++ = IMR_OP_WTL(IMR_RSCCR, 1);
++ *dl++ = 0xffffffff;
++ *dl++ = IMR_OP_WTL(IMR_RSCSR, 1);
++ cfg->rscr_ptr = dl++;
++
++ for (i = 0; i < RSE_PLANES_NUM; i++) {
++ /* ...set destination planes base address and strides */
++ *dl++ = IMR_OP_WTL(IMR_DSANRR0 + i * 0x10, 4);
++ cfg->dstn_pa_ptr[i] = dl++;
++ cfg->striden_ptr[i] = dl++;
++ cfg->dstr_pa_ptr[i] = dl++;
++ cfg->strider_ptr[i] = dl++;
++ }
++
++ cfg->rscr_sc8 = cfg->rscr_sc4 = cfg->rscr_sc2 = 0;
++ memset(cfg->dstnr_offsets, 0, sizeof(cfg->dstnr_offsets));
++ memset(cfg->dstnr_strides, 0, sizeof(cfg->dstnr_strides));
++ } else {
++ /* ...disable RSE */
++ *dl++ = IMR_OP_WTL(IMR_RSCCR, 1);
++ *dl++ = 0xffffffff;
++
++ for (i = 0; i < RSE_PLANES_NUM; i++) {
++ cfg->dstn_pa_ptr[i] = NULL;
++ cfg->striden_ptr[i] = NULL;
++ cfg->dstr_pa_ptr[i] = NULL;
++ cfg->strider_ptr[i] = NULL;
++ }
++ cfg->rscr_ptr = NULL;
++ }
+ /* ...set source/destination addresses of Y/UV plane */
+ *dl++ = IMR_OP_WTL(IMR_DSAR, 2);
+ cfg->dst_pa_ptr[0] = dl++;
+@@ -907,6 +974,12 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
+
+ type = desc->type;
+
++ /* ...check for RSE */
++ if ((type & IMR_MAP_RSE) && !imr->rse) {
++ v4l2_err(&imr->v4l2_dev, "Rotator & Scaler extension not supported\n");
++ return -EINVAL;
++ }
++
+ /* ...mesh item size calculation */
+ item_size = (type & IMR_MAP_LUCE ? 4 : 0) + (type & IMR_MAP_CLCE ? 4 : 0);
+
+@@ -1055,6 +1128,12 @@ static int imr_ioctl_map_raw(struct imr_ctx *ctx, struct imr_map_desc *desc)
+ u32 dl_start_offset;
+ dma_addr_t dl_dma_addr;
+
++ /* ...check RSE */
++ if ((type & IMR_MAP_RSE) && !imr->rse) {
++ v4l2_err(&imr->v4l2_dev, "Rotator & Scaler extension not supported\n");
++ return -EINVAL;
++ }
++
+ /* ...calculate main routine length */
+ dl_size = imr_dl_program_length(ctx);
+ if (!dl_size) {
+@@ -1103,6 +1182,46 @@ static int imr_ioctl_color(struct imr_ctx *ctx, u32 color)
+ return 0;
+ }
+
++static int imr_extdst_set(struct imr_ctx *ctx, u32 *extdst)
++{
++ struct imr_device *imr = ctx->imr;
++ struct imr_cfg *cfg = ctx->cfg;
++
++ if (!cfg) {
++ v4l2_err(&imr->v4l2_dev, "failed to set V3H extension dst buffers: No active confguration.\n");
++ return -EINVAL;
++ }
++
++ if (copy_from_user((void *) cfg->dstnr_offsets, (void __user *) extdst, sizeof(cfg->dstnr_offsets))) {
++ v4l2_err(&imr->v4l2_dev, "failed to read V3H extension dst buffers\n");
++ return -EFAULT;
++ }
++
++ return 0;
++}
++
++static int imr_extstride_set(struct imr_ctx *ctx, struct imr_rse_param *param)
++{
++ struct imr_device *imr = ctx->imr;
++ struct imr_cfg *cfg = ctx->cfg;
++
++ if (!cfg) {
++ v4l2_err(&imr->v4l2_dev, "failed to set V3H extension buffers params: No active confguration.\n");
++ return -EINVAL;
++ }
++
++ cfg->rscr_sc8 = param->sc8;
++ cfg->rscr_sc4 = param->sc4;
++ cfg->rscr_sc2 = param->sc2;
++
++ if (copy_from_user((void *) cfg->dstnr_strides, (void __user *) param->strides, sizeof(cfg->dstnr_strides))) {
++ v4l2_err(&imr->v4l2_dev, "failed to read V3H extension buffers strides\n");
++ return -EFAULT;
++ }
++
++ return 0;
++}
++
+ /*******************************************************************************
+ * V4L2 I/O controls
+ ******************************************************************************/
+@@ -1356,6 +1475,14 @@ static long imr_default(struct file *file, void *fh, bool valid_prio, unsigned i
+ /* ...set solid color code */
+ return imr_ioctl_color(ctx, *(u32 *)arg);
+
++ case VIDIOC_IMR_EXTDST:
++ /* ...set V3H extension dst buffers */
++ return imr_extdst_set(ctx, *(u32 **)arg);
++
++ case VIDIOC_IMR_EXTSTRIDE:
++ /* ...set V3H extension dst strides */
++ return imr_extstride_set(ctx, (struct imr_rse_param *)arg);
++
+ default:
+ return -ENOIOCTLCMD;
+ }
+@@ -1579,6 +1706,7 @@ static void imr_device_run(void *priv)
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
+ u32 src_addr, dst_addr;
+ unsigned long flags;
++ int i;
+
+ v4l2_dbg(3, debug, &imr->v4l2_dev, "run next job...\n");
+
+@@ -1608,6 +1736,17 @@ static void imr_device_run(void *priv)
+ *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);
+
++ for (i = 0; i < RSE_PLANES_NUM; i++) {
++ if (cfg->rscr_ptr) *cfg->rscr_ptr = (1 << IMR_RSCR_RSE) | (cfg->rscr_sc8 << IMR_RSCR_SC8) |
++ (cfg->rscr_sc4 << IMR_RSCR_SC4) |(cfg->rscr_sc2 << IMR_RSCR_SC2);
++
++ if (cfg->dstn_pa_ptr[i]) *cfg->dstn_pa_ptr[i] = dst_addr + cfg->dstnr_offsets[i];
++ if (cfg->dstr_pa_ptr[i]) *cfg->dstr_pa_ptr[i] = dst_addr + cfg->dstnr_offsets[i + RSE_PLANES_NUM];
++
++ if (cfg->striden_ptr[i]) *cfg->striden_ptr[i] = cfg->dstnr_strides[i];
++ if (cfg->strider_ptr[i]) *cfg->strider_ptr[i] = cfg->dstnr_strides[i + RSE_PLANES_NUM];
++ }
++
+ /* ...adjust source/destination parameters of the UV-plane as needed */
+ if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) {
+ *cfg->src_pa_ptr[1] = src_addr + ctx->queue[0].fmt.width * ctx->queue[0].fmt.height;
+@@ -1776,6 +1915,7 @@ static int imr_probe(struct platform_device *pdev)
+ {
+ struct imr_device *imr;
+ struct resource *res;
++ struct device_node *np = pdev->dev.of_node;
+ int ret;
+
+ imr = devm_kzalloc(&pdev->dev, sizeof(*imr), GFP_KERNEL);
+@@ -1786,6 +1926,9 @@ static int imr_probe(struct platform_device *pdev)
+ spin_lock_init(&imr->lock);
+ imr->dev = &pdev->dev;
+
++ /* Check RSE support */
++ imr->rse = of_property_read_bool(np, "rse");
++
+ /* ...memory-mapped registers */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+diff --git a/include/uapi/linux/rcar-imr.h b/include/uapi/linux/rcar-imr.h
+index 7b8ed0c..19fdbae 100644
+--- a/include/uapi/linux/rcar-imr.h
++++ b/include/uapi/linux/rcar-imr.h
+@@ -25,8 +25,8 @@ struct imr_map_desc {
+ /* ...total size of the mesh structure */
+ u32 size;
+
+- /* ...map-specific user-pointer */
+- void *data;
++ /* ...map-specific user-pointer */
++ void *data;
+
+ } __attribute__((packed));
+
+@@ -54,6 +54,9 @@ struct imr_map_desc {
+ /* ...bilinear filtration enable flag */
+ #define IMR_MAP_BFE (1 << 7)
+
++/* ...extended functionality (rotation/scaling) enable flag */
++#define IMR_MAP_RSE (1 << 21)
++
+ /* ...source coordinate decimal point position bit index */
+ #define __IMR_MAP_UVDPOR_SHIFT 8
+ #define __IMR_MAP_UVDPOR(v) (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7)
+@@ -88,11 +91,26 @@ struct imr_mesh {
+ } __attribute__((packed));
+
+ /*******************************************************************************
++ * V3H Extension destination data
++ ******************************************************************************/
++/* ...number of V3H extension destination buffers (rotated/non-rotated, scaled 1/1, 1/2, 1/4, 1/8) */
++#define IMR_EXTDST_NUM 8
++
++struct imr_rse_param {
++ /* ...logical right shift data */
++ u8 sc8, sc4, sc2;
++ /* ...destination buffers stride */
++ u32 *strides;
++};
++
++/*******************************************************************************
+ * 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)
++#define VIDIOC_IMR_EXTDST _IOW('V', BASE_VIDIOC_PRIVATE + 3, u32 *)
++#define VIDIOC_IMR_EXTSTRIDE _IOW('V', BASE_VIDIOC_PRIVATE + 4, struct imr_rse_param)
+
+ #endif /* RCAR_IMR_USER_H */
+--
+2.7.4
+