diff options
| -rw-r--r-- | drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c index 26a8eaa98b3d..d0a681ba78eb 100644 --- a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c +++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c @@ -32,6 +32,7 @@ #define SHIM_DMACNTX_YUV422 GENMASK(27, 26) #define SHIM_DMACNTX_DUAL_PCK_CFG BIT(24) #define SHIM_DMACNTX_SIZE GENMASK(21, 20) +#define SHIM_DMACNTX_VC GENMASK(9, 6) #define SHIM_DMACNTX_FMT GENMASK(5, 0) #define SHIM_DMACNTX_YUV422_MODE_11 3 #define SHIM_DMACNTX_SIZE_8 0 @@ -110,6 +111,9 @@ struct ti_csi2rx_ctx { struct media_pad pad; u32 sequence; u32 idx; + u32 vc; + u32 dt; + u32 stream; }; struct ti_csi2rx_dev { @@ -569,7 +573,7 @@ static void ti_csi2rx_setup_shim(struct ti_csi2rx_ctx *ctx) ti_csi2rx_request_max_ppc(csi); reg = SHIM_DMACNTX_EN; - reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt); + reg |= FIELD_PREP(SHIM_DMACNTX_FMT, ctx->dt); /* * The hardware assumes incoming YUV422 8-bit data on MIPI CSI2 bus @@ -608,6 +612,8 @@ static void ti_csi2rx_setup_shim(struct ti_csi2rx_ctx *ctx) break; } + reg |= FIELD_PREP(SHIM_DMACNTX_VC, ctx->vc); + writel(reg, csi->shim + SHIM_DMACNTX(ctx->idx)); reg = FIELD_PREP(SHIM_PSI_CFG0_SRC_TAG, 0) | @@ -881,12 +887,46 @@ static void ti_csi2rx_buffer_queue(struct vb2_buffer *vb) } } +static int ti_csi2rx_get_vc_and_dt(struct ti_csi2rx_ctx *ctx) +{ + struct ti_csi2rx_dev *csi = ctx->csi; + struct v4l2_mbus_frame_desc fd; + struct media_pad *pad; + int ret, i; + + pad = media_entity_remote_pad_unique(&csi->subdev.entity, MEDIA_PAD_FL_SOURCE); + if (IS_ERR(pad)) + return PTR_ERR(pad); + + ret = v4l2_subdev_call(csi->source, pad, get_frame_desc, pad->index, &fd); + if (ret) + return ret; + + if (fd.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) + return -EINVAL; + + for (i = 0; i < fd.num_entries; i++) { + if (ctx->stream == fd.entry[i].stream) { + ctx->vc = fd.entry[i].bus.csi2.vc; + ctx->dt = fd.entry[i].bus.csi2.dt; + break; + } + + /* Return error if no matching stream found */ + if (i == fd.num_entries) + return -EINVAL; + } + + return 0; +} + static int ti_csi2rx_start_streaming(struct vb2_queue *vq, unsigned int count) { struct ti_csi2rx_ctx *ctx = vb2_get_drv_priv(vq); struct ti_csi2rx_dev *csi = ctx->csi; struct ti_csi2rx_dma *dma = &ctx->dma; struct ti_csi2rx_buffer *buf; + const struct ti_csi2rx_fmt *fmt; unsigned long flags; int ret = 0; @@ -901,6 +941,15 @@ static int ti_csi2rx_start_streaming(struct vb2_queue *vq, unsigned int count) if (ret) goto err; + ret = ti_csi2rx_get_vc_and_dt(ctx); + if (ret == -ENOIOCTLCMD) { + ctx->vc = 0; + fmt = find_format_by_fourcc(ctx->v_fmt.fmt.pix.pixelformat); + ctx->dt = fmt->csi_dt; + } else if (ret < 0) { + goto err; + } + ti_csi2rx_setup_shim(ctx); ctx->sequence = 0; |
