Skip to content

Commit dbca7b3

Browse files
Pratyush YadavHans Verkuil
authored andcommitted
media: cadence: csi2rx: Add get_fmt and set_fmt pad ops
The format is needed to calculate the link speed for the external DPHY configuration. It is not right to query the format from the source subdev. Add get_fmt and set_fmt pad operations so that the format can be configured and correct bpp be selected. Initialize and use the v4l2 subdev active state to keep track of the active formats. Also propagate the new format from the sink pad to all the source pads. Signed-off-by: Pratyush Yadav <p.yadav@ti.com> Tested-by: Julien Massot <julien.massot@collabora.com> Reviewed-by: Maxime Ripard <mripard@kernel.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> Co-developed-by: Jai Luthra <j-luthra@ti.com> Signed-off-by: Jai Luthra <j-luthra@ti.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
1 parent aee5b41 commit dbca7b3

1 file changed

Lines changed: 95 additions & 1 deletion

File tree

drivers/media/platform/cadence/cdns-csi2rx.c

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ enum csi2rx_pads {
6161
CSI2RX_PAD_MAX,
6262
};
6363

64+
struct csi2rx_fmt {
65+
u32 code;
66+
u8 bpp;
67+
};
68+
6469
struct csi2rx_priv {
6570
struct device *dev;
6671
unsigned int count;
@@ -95,6 +100,32 @@ struct csi2rx_priv {
95100
int source_pad;
96101
};
97102

103+
static const struct csi2rx_fmt formats[] = {
104+
{ .code = MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, },
105+
{ .code = MEDIA_BUS_FMT_UYVY8_1X16, .bpp = 16, },
106+
{ .code = MEDIA_BUS_FMT_YVYU8_1X16, .bpp = 16, },
107+
{ .code = MEDIA_BUS_FMT_VYUY8_1X16, .bpp = 16, },
108+
{ .code = MEDIA_BUS_FMT_SBGGR8_1X8, .bpp = 8, },
109+
{ .code = MEDIA_BUS_FMT_SGBRG8_1X8, .bpp = 8, },
110+
{ .code = MEDIA_BUS_FMT_SGRBG8_1X8, .bpp = 8, },
111+
{ .code = MEDIA_BUS_FMT_SRGGB8_1X8, .bpp = 8, },
112+
{ .code = MEDIA_BUS_FMT_SBGGR10_1X10, .bpp = 10, },
113+
{ .code = MEDIA_BUS_FMT_SGBRG10_1X10, .bpp = 10, },
114+
{ .code = MEDIA_BUS_FMT_SGRBG10_1X10, .bpp = 10, },
115+
{ .code = MEDIA_BUS_FMT_SRGGB10_1X10, .bpp = 10, },
116+
};
117+
118+
static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)
119+
{
120+
unsigned int i;
121+
122+
for (i = 0; i < ARRAY_SIZE(formats); i++)
123+
if (formats[i].code == code)
124+
return &formats[i];
125+
126+
return NULL;
127+
}
128+
98129
static inline
99130
struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
100131
{
@@ -303,12 +334,68 @@ static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
303334
return ret;
304335
}
305336

337+
static int csi2rx_set_fmt(struct v4l2_subdev *subdev,
338+
struct v4l2_subdev_state *state,
339+
struct v4l2_subdev_format *format)
340+
{
341+
struct v4l2_mbus_framefmt *fmt;
342+
unsigned int i;
343+
344+
/* No transcoding, source and sink formats must match. */
345+
if (format->pad != CSI2RX_PAD_SINK)
346+
return v4l2_subdev_get_fmt(subdev, state, format);
347+
348+
if (!csi2rx_get_fmt_by_code(format->format.code))
349+
format->format.code = formats[0].code;
350+
351+
format->format.field = V4L2_FIELD_NONE;
352+
353+
/* Set sink format */
354+
fmt = v4l2_subdev_get_pad_format(subdev, state, format->pad);
355+
*fmt = format->format;
356+
357+
/* Propagate to source formats */
358+
for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++) {
359+
fmt = v4l2_subdev_get_pad_format(subdev, state, i);
360+
*fmt = format->format;
361+
}
362+
363+
return 0;
364+
}
365+
366+
static int csi2rx_init_cfg(struct v4l2_subdev *subdev,
367+
struct v4l2_subdev_state *state)
368+
{
369+
struct v4l2_subdev_format format = {
370+
.pad = CSI2RX_PAD_SINK,
371+
.format = {
372+
.width = 640,
373+
.height = 480,
374+
.code = MEDIA_BUS_FMT_UYVY8_1X16,
375+
.field = V4L2_FIELD_NONE,
376+
.colorspace = V4L2_COLORSPACE_SRGB,
377+
.ycbcr_enc = V4L2_YCBCR_ENC_601,
378+
.quantization = V4L2_QUANTIZATION_LIM_RANGE,
379+
.xfer_func = V4L2_XFER_FUNC_SRGB,
380+
},
381+
};
382+
383+
return csi2rx_set_fmt(subdev, state, &format);
384+
}
385+
386+
static const struct v4l2_subdev_pad_ops csi2rx_pad_ops = {
387+
.get_fmt = v4l2_subdev_get_fmt,
388+
.set_fmt = csi2rx_set_fmt,
389+
.init_cfg = csi2rx_init_cfg,
390+
};
391+
306392
static const struct v4l2_subdev_video_ops csi2rx_video_ops = {
307393
.s_stream = csi2rx_s_stream,
308394
};
309395

310396
static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
311397
.video = &csi2rx_video_ops,
398+
.pad = &csi2rx_pad_ops,
312399
};
313400

314401
static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
@@ -532,9 +619,13 @@ static int csi2rx_probe(struct platform_device *pdev)
532619
if (ret)
533620
goto err_cleanup;
534621

622+
ret = v4l2_subdev_init_finalize(&csi2rx->subdev);
623+
if (ret)
624+
goto err_cleanup;
625+
535626
ret = v4l2_async_register_subdev(&csi2rx->subdev);
536627
if (ret < 0)
537-
goto err_cleanup;
628+
goto err_free_state;
538629

539630
dev_info(&pdev->dev,
540631
"Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n",
@@ -544,6 +635,8 @@ static int csi2rx_probe(struct platform_device *pdev)
544635

545636
return 0;
546637

638+
err_free_state:
639+
v4l2_subdev_cleanup(&csi2rx->subdev);
547640
err_cleanup:
548641
v4l2_async_nf_unregister(&csi2rx->notifier);
549642
v4l2_async_nf_cleanup(&csi2rx->notifier);
@@ -560,6 +653,7 @@ static void csi2rx_remove(struct platform_device *pdev)
560653
v4l2_async_nf_unregister(&csi2rx->notifier);
561654
v4l2_async_nf_cleanup(&csi2rx->notifier);
562655
v4l2_async_unregister_subdev(&csi2rx->subdev);
656+
v4l2_subdev_cleanup(&csi2rx->subdev);
563657
media_entity_cleanup(&csi2rx->subdev.entity);
564658
kfree(csi2rx);
565659
}

0 commit comments

Comments
 (0)