diff options
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.patch | 327 |
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 + |