[v5,04/14] staging: media: starfive: Add a params sink pad and a scd source pad for ISP
Commit Message
StarFive ISP can use params sink pad to transmit ISP parameters and use
scd source pad to capture statistics collection data.
Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
---
.../staging/media/starfive/camss/stf-isp.c | 77 +++++++++++++++++--
.../staging/media/starfive/camss/stf-isp.h | 2 +
2 files changed, 71 insertions(+), 8 deletions(-)
Comments
Hello Changhuang
On Tue, Jul 09, 2024 at 01:38:14AM GMT, Changhuang Liang wrote:
> StarFive ISP can use params sink pad to transmit ISP parameters and use
> scd source pad to capture statistics collection data.
>
> Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
> ---
> .../staging/media/starfive/camss/stf-isp.c | 77 +++++++++++++++++--
> .../staging/media/starfive/camss/stf-isp.h | 2 +
> 2 files changed, 71 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/staging/media/starfive/camss/stf-isp.c b/drivers/staging/media/starfive/camss/stf-isp.c
> index 4e6e26736852..0ebffd09842a 100644
> --- a/drivers/staging/media/starfive/camss/stf-isp.c
> +++ b/drivers/staging/media/starfive/camss/stf-isp.c
> @@ -21,13 +21,23 @@ static const struct stf_isp_format isp_formats_sink[] = {
> { MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
> };
>
> +static const struct stf_isp_format isp_formats_sink_params[] = {
> + { MEDIA_BUS_FMT_METADATA_FIXED },
> +};
> +
> static const struct stf_isp_format isp_formats_source[] = {
> { MEDIA_BUS_FMT_YUYV8_1_5X8, 8 },
> };
>
> +static const struct stf_isp_format isp_formats_source_scd[] = {
> + { MEDIA_BUS_FMT_METADATA_FIXED },
> +};
> +
> static const struct stf_isp_format_table isp_formats_st7110[] = {
> { isp_formats_sink, ARRAY_SIZE(isp_formats_sink) },
> + { isp_formats_sink_params, ARRAY_SIZE(isp_formats_sink_params) },
> { isp_formats_source, ARRAY_SIZE(isp_formats_source) },
> + { isp_formats_source_scd, ARRAY_SIZE(isp_formats_source_scd) },
> };
>
> static const struct stf_isp_format *
> @@ -93,13 +103,19 @@ static void isp_try_format(struct stf_isp_dev *isp_dev,
>
> formats = &isp_dev->formats[pad];
>
> - fmt->width = clamp_t(u32, fmt->width, STFCAMSS_FRAME_MIN_WIDTH,
> - STFCAMSS_FRAME_MAX_WIDTH);
> - fmt->height = clamp_t(u32, fmt->height, STFCAMSS_FRAME_MIN_HEIGHT,
> - STFCAMSS_FRAME_MAX_HEIGHT);
> - fmt->height &= ~0x1;
> + if (pad != STF_ISP_PAD_SRC_SCD && pad != STF_ISP_PAD_SINK_PARAMS) {
> + fmt->width = clamp_t(u32, fmt->width, STFCAMSS_FRAME_MIN_WIDTH,
> + STFCAMSS_FRAME_MAX_WIDTH);
> + fmt->height = clamp_t(u32, fmt->height, STFCAMSS_FRAME_MIN_HEIGHT,
> + STFCAMSS_FRAME_MAX_HEIGHT);
> + fmt->height &= ~0x1;
> + fmt->colorspace = V4L2_COLORSPACE_SRGB;
> + } else {
> + fmt->width = 1;
> + fmt->height = 1;
> + }
> +
> fmt->field = V4L2_FIELD_NONE;
> - fmt->colorspace = V4L2_COLORSPACE_SRGB;
> fmt->flags = 0;
>
> if (!stf_g_fmt_by_mcode(formats, fmt->code))
> @@ -119,7 +135,7 @@ static int isp_enum_mbus_code(struct v4l2_subdev *sd,
>
> formats = &isp_dev->formats[code->pad];
> code->code = formats->fmts[code->index].code;
> - } else {
> + } else if (code->pad == STF_ISP_PAD_SRC) {
> struct v4l2_mbus_framefmt *sink_fmt;
>
> if (code->index >= ARRAY_SIZE(isp_formats_source))
> @@ -131,6 +147,10 @@ static int isp_enum_mbus_code(struct v4l2_subdev *sd,
> code->code = sink_fmt->code;
> if (!code->code)
> return -EINVAL;
> + } else {
> + if (code->index > 0)
> + return -EINVAL;
> + code->code = MEDIA_BUS_FMT_METADATA_FIXED;
> }
> code->flags = 0;
>
> @@ -151,6 +171,9 @@ static int isp_set_format(struct v4l2_subdev *sd,
> isp_try_format(isp_dev, state, fmt->pad, &fmt->format);
> *format = fmt->format;
>
> + if (fmt->pad == STF_ISP_PAD_SRC_SCD || fmt->pad == STF_ISP_PAD_SINK_PARAMS)
nit: can easily be made < 80 cols (again, not mandatory in Linux but
enforced in v4l according to
Documentation/driver-api/media/maintainer-entry-profile.rst)
> + return 0;
> +
> isp_dev->current_fmt = stf_g_fmt_by_mcode(&isp_dev->formats[fmt->pad],
> fmt->format.code);
>
> @@ -202,6 +225,9 @@ static int isp_get_selection(struct v4l2_subdev *sd,
> struct v4l2_subdev_format fmt = { 0 };
> struct v4l2_rect *rect;
>
> + if (sel->pad == STF_ISP_PAD_SRC_SCD || sel->pad == STF_ISP_PAD_SINK_PARAMS)
> + return -EINVAL;
> +
> switch (sel->target) {
> case V4L2_SEL_TGT_CROP_BOUNDS:
> if (sel->pad == STF_ISP_PAD_SINK) {
> @@ -239,6 +265,9 @@ static int isp_set_selection(struct v4l2_subdev *sd,
> struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
> struct v4l2_rect *rect;
>
> + if (sel->pad == STF_ISP_PAD_SRC_SCD || sel->pad == STF_ISP_PAD_SINK_PARAMS)
> + return -EINVAL;
> +
> if (sel->target != V4L2_SEL_TGT_CROP)
> return -EINVAL;
>
> @@ -296,8 +325,38 @@ static int isp_init_formats(struct v4l2_subdev *sd,
> .height = 1080
> }
> };
> + struct v4l2_subdev_format format_params = {
> + .pad = STF_ISP_PAD_SINK_PARAMS,
> + .which = V4L2_SUBDEV_FORMAT_ACTIVE,
> + .format = {
> + .code = MEDIA_BUS_FMT_METADATA_FIXED,
> + .width = 1,
> + .height = 1
> + }
> + };
> + struct v4l2_subdev_format format_scd = {
> + .pad = STF_ISP_PAD_SRC_SCD,
> + .which = V4L2_SUBDEV_FORMAT_ACTIVE,
> + .format = {
> + .code = MEDIA_BUS_FMT_METADATA_FIXED,
> + .width = 1,
> + .height = 1
> + }
> + };
> + int ret;
> +
> + /* Init for STF_ISP_PAD_SINK and STF_ISP_PAD_SRC pad */
Does this initialize the format on STF_ISP_PAD_SRC for real ?
Anyway, was there already so
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Thanks
j
> + ret = isp_set_format(sd, sd_state, &format);
> + if (ret < 0)
> + return ret;
> +
> + /* Init for STF_ISP_PAD_SINK_PARAMS pad */
> + ret = isp_set_format(sd, sd_state, &format_params);
> + if (ret < 0)
> + return ret;
>
> - return isp_set_format(sd, sd_state, &format);
> + /* Init for STF_ISP_PAD_SRC_SCD pad */
> + return isp_set_format(sd, sd_state, &format_scd);
> }
>
> static const struct v4l2_subdev_video_ops isp_video_ops = {
> @@ -338,7 +397,9 @@ int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev)
> v4l2_set_subdevdata(sd, isp_dev);
>
> pads[STF_ISP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
> + pads[STF_ISP_PAD_SINK_PARAMS].flags = MEDIA_PAD_FL_SINK;
> pads[STF_ISP_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
> + pads[STF_ISP_PAD_SRC_SCD].flags = MEDIA_PAD_FL_SOURCE;
>
> sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP;
> sd->entity.ops = &isp_media_ops;
> diff --git a/drivers/staging/media/starfive/camss/stf-isp.h b/drivers/staging/media/starfive/camss/stf-isp.h
> index 955cbb048363..bc7e7b0736fa 100644
> --- a/drivers/staging/media/starfive/camss/stf-isp.h
> +++ b/drivers/staging/media/starfive/camss/stf-isp.h
> @@ -392,7 +392,9 @@
> /* pad id for media framework */
> enum stf_isp_pad_id {
> STF_ISP_PAD_SINK = 0,
> + STF_ISP_PAD_SINK_PARAMS,
> STF_ISP_PAD_SRC,
> + STF_ISP_PAD_SRC_SCD,
> STF_ISP_PAD_MAX
> };
>
> --
> 2.25.1
>
>
Hi, Jacopo
Thanks for your comments.
[...]
> > @@ -151,6 +171,9 @@ static int isp_set_format(struct v4l2_subdev *sd,
> > isp_try_format(isp_dev, state, fmt->pad, &fmt->format);
> > *format = fmt->format;
> >
> > + if (fmt->pad == STF_ISP_PAD_SRC_SCD || fmt->pad ==
> > +STF_ISP_PAD_SINK_PARAMS)
>
> nit: can easily be made < 80 cols (again, not mandatory in Linux but enforced
> in v4l according to
> Documentation/driver-api/media/maintainer-entry-profile.rst)
>
I will add --max-line-length=80 to check patchs again.
> > + return 0;
> > +
> > isp_dev->current_fmt =
> stf_g_fmt_by_mcode(&isp_dev->formats[fmt->pad],
> > fmt->format.code);
> >
> > @@ -202,6 +225,9 @@ static int isp_get_selection(struct v4l2_subdev *sd,
> > struct v4l2_subdev_format fmt = { 0 };
> > struct v4l2_rect *rect;
> >
> > + if (sel->pad == STF_ISP_PAD_SRC_SCD || sel->pad ==
> STF_ISP_PAD_SINK_PARAMS)
> > + return -EINVAL;
> > +
> > switch (sel->target) {
> > case V4L2_SEL_TGT_CROP_BOUNDS:
> > if (sel->pad == STF_ISP_PAD_SINK) { @@ -239,6 +265,9 @@ static
> int
> > isp_set_selection(struct v4l2_subdev *sd,
> > struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
> > struct v4l2_rect *rect;
> >
> > + if (sel->pad == STF_ISP_PAD_SRC_SCD || sel->pad ==
> STF_ISP_PAD_SINK_PARAMS)
> > + return -EINVAL;
> > +
> > if (sel->target != V4L2_SEL_TGT_CROP)
> > return -EINVAL;
> >
> > @@ -296,8 +325,38 @@ static int isp_init_formats(struct v4l2_subdev *sd,
> > .height = 1080
> > }
> > };
> > + struct v4l2_subdev_format format_params = {
> > + .pad = STF_ISP_PAD_SINK_PARAMS,
> > + .which = V4L2_SUBDEV_FORMAT_ACTIVE,
> > + .format = {
> > + .code = MEDIA_BUS_FMT_METADATA_FIXED,
> > + .width = 1,
> > + .height = 1
> > + }
> > + };
> > + struct v4l2_subdev_format format_scd = {
> > + .pad = STF_ISP_PAD_SRC_SCD,
> > + .which = V4L2_SUBDEV_FORMAT_ACTIVE,
> > + .format = {
> > + .code = MEDIA_BUS_FMT_METADATA_FIXED,
> > + .width = 1,
> > + .height = 1
> > + }
> > + };
> > + int ret;
> > +
> > + /* Init for STF_ISP_PAD_SINK and STF_ISP_PAD_SRC pad */
>
> Does this initialize the format on STF_ISP_PAD_SRC for real ?
>
Yes, it will initialize the PAD_SINK and PAND_SRC formats by isp_set_selection.
> Anyway, was there already so
> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>
> Thanks
> j
>
Hello Changhuang,
Thank you for the patch.
On Tue, Jul 09, 2024 at 01:38:14AM -0700, Changhuang Liang wrote:
> StarFive ISP can use params sink pad to transmit ISP parameters and use
> scd source pad to capture statistics collection data.
>
> Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
> ---
> .../staging/media/starfive/camss/stf-isp.c | 77 +++++++++++++++++--
> .../staging/media/starfive/camss/stf-isp.h | 2 +
> 2 files changed, 71 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/staging/media/starfive/camss/stf-isp.c b/drivers/staging/media/starfive/camss/stf-isp.c
> index 4e6e26736852..0ebffd09842a 100644
> --- a/drivers/staging/media/starfive/camss/stf-isp.c
> +++ b/drivers/staging/media/starfive/camss/stf-isp.c
> @@ -21,13 +21,23 @@ static const struct stf_isp_format isp_formats_sink[] = {
> { MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
> };
>
> +static const struct stf_isp_format isp_formats_sink_params[] = {
> + { MEDIA_BUS_FMT_METADATA_FIXED },
> +};
> +
> static const struct stf_isp_format isp_formats_source[] = {
> { MEDIA_BUS_FMT_YUYV8_1_5X8, 8 },
> };
>
> +static const struct stf_isp_format isp_formats_source_scd[] = {
> + { MEDIA_BUS_FMT_METADATA_FIXED },
> +};
> +
> static const struct stf_isp_format_table isp_formats_st7110[] = {
> { isp_formats_sink, ARRAY_SIZE(isp_formats_sink) },
> + { isp_formats_sink_params, ARRAY_SIZE(isp_formats_sink_params) },
> { isp_formats_source, ARRAY_SIZE(isp_formats_source) },
> + { isp_formats_source_scd, ARRAY_SIZE(isp_formats_source_scd) },
> };
>
> static const struct stf_isp_format *
> @@ -93,13 +103,19 @@ static void isp_try_format(struct stf_isp_dev *isp_dev,
>
> formats = &isp_dev->formats[pad];
>
> - fmt->width = clamp_t(u32, fmt->width, STFCAMSS_FRAME_MIN_WIDTH,
> - STFCAMSS_FRAME_MAX_WIDTH);
> - fmt->height = clamp_t(u32, fmt->height, STFCAMSS_FRAME_MIN_HEIGHT,
> - STFCAMSS_FRAME_MAX_HEIGHT);
> - fmt->height &= ~0x1;
> + if (pad != STF_ISP_PAD_SRC_SCD && pad != STF_ISP_PAD_SINK_PARAMS) {
> + fmt->width = clamp_t(u32, fmt->width, STFCAMSS_FRAME_MIN_WIDTH,
> + STFCAMSS_FRAME_MAX_WIDTH);
> + fmt->height = clamp_t(u32, fmt->height, STFCAMSS_FRAME_MIN_HEIGHT,
> + STFCAMSS_FRAME_MAX_HEIGHT);
> + fmt->height &= ~0x1;
> + fmt->colorspace = V4L2_COLORSPACE_SRGB;
> + } else {
> + fmt->width = 1;
> + fmt->height = 1;
You should set fmt->colorspace here too. I think you can set it to 0.
> + }
> +
> fmt->field = V4L2_FIELD_NONE;
> - fmt->colorspace = V4L2_COLORSPACE_SRGB;
> fmt->flags = 0;
>
> if (!stf_g_fmt_by_mcode(formats, fmt->code))
> @@ -119,7 +135,7 @@ static int isp_enum_mbus_code(struct v4l2_subdev *sd,
>
> formats = &isp_dev->formats[code->pad];
> code->code = formats->fmts[code->index].code;
> - } else {
> + } else if (code->pad == STF_ISP_PAD_SRC) {
> struct v4l2_mbus_framefmt *sink_fmt;
>
> if (code->index >= ARRAY_SIZE(isp_formats_source))
> @@ -131,6 +147,10 @@ static int isp_enum_mbus_code(struct v4l2_subdev *sd,
> code->code = sink_fmt->code;
> if (!code->code)
> return -EINVAL;
> + } else {
> + if (code->index > 0)
> + return -EINVAL;
> + code->code = MEDIA_BUS_FMT_METADATA_FIXED;
> }
> code->flags = 0;
>
> @@ -151,6 +171,9 @@ static int isp_set_format(struct v4l2_subdev *sd,
> isp_try_format(isp_dev, state, fmt->pad, &fmt->format);
> *format = fmt->format;
>
> + if (fmt->pad == STF_ISP_PAD_SRC_SCD || fmt->pad == STF_ISP_PAD_SINK_PARAMS)
> + return 0;
> +
> isp_dev->current_fmt = stf_g_fmt_by_mcode(&isp_dev->formats[fmt->pad],
> fmt->format.code);
>
> @@ -202,6 +225,9 @@ static int isp_get_selection(struct v4l2_subdev *sd,
> struct v4l2_subdev_format fmt = { 0 };
> struct v4l2_rect *rect;
>
> + if (sel->pad == STF_ISP_PAD_SRC_SCD || sel->pad == STF_ISP_PAD_SINK_PARAMS)
> + return -EINVAL;
> +
> switch (sel->target) {
> case V4L2_SEL_TGT_CROP_BOUNDS:
> if (sel->pad == STF_ISP_PAD_SINK) {
> @@ -239,6 +265,9 @@ static int isp_set_selection(struct v4l2_subdev *sd,
> struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
> struct v4l2_rect *rect;
>
> + if (sel->pad == STF_ISP_PAD_SRC_SCD || sel->pad == STF_ISP_PAD_SINK_PARAMS)
> + return -EINVAL;
> +
> if (sel->target != V4L2_SEL_TGT_CROP)
> return -EINVAL;
>
> @@ -296,8 +325,38 @@ static int isp_init_formats(struct v4l2_subdev *sd,
While at it, you could rename the function to isp_init_state().
> .height = 1080
> }
> };
> + struct v4l2_subdev_format format_params = {
> + .pad = STF_ISP_PAD_SINK_PARAMS,
> + .which = V4L2_SUBDEV_FORMAT_ACTIVE,
That's not quite right, as the .init_state() handler is used to
initialized both the TRY and ACTIVE states. As the "which" field is
currently ignored through the driver the code should behave correctly
(as far as I can tell), but you may want at some point to initialize the
formats and selection rectangles directly in this function instead of
calling isp_set_format().
> + .format = {
> + .code = MEDIA_BUS_FMT_METADATA_FIXED,
> + .width = 1,
> + .height = 1
According to
https://docs.kernel.org/userspace-api/media/v4l/subdev-formats.html#metadata-formats,
width and height should be set to 0 for MEDIA_BUS_FMT_METADATA_FIXED.
> + }
> + };
> + struct v4l2_subdev_format format_scd = {
> + .pad = STF_ISP_PAD_SRC_SCD,
> + .which = V4L2_SUBDEV_FORMAT_ACTIVE,
> + .format = {
> + .code = MEDIA_BUS_FMT_METADATA_FIXED,
> + .width = 1,
> + .height = 1
> + }
> + };
> + int ret;
> +
> + /* Init for STF_ISP_PAD_SINK and STF_ISP_PAD_SRC pad */
> + ret = isp_set_format(sd, sd_state, &format);
> + if (ret < 0)
> + return ret;
> +
> + /* Init for STF_ISP_PAD_SINK_PARAMS pad */
> + ret = isp_set_format(sd, sd_state, &format_params);
> + if (ret < 0)
> + return ret;
>
> - return isp_set_format(sd, sd_state, &format);
> + /* Init for STF_ISP_PAD_SRC_SCD pad */
> + return isp_set_format(sd, sd_state, &format_scd);
> }
>
> static const struct v4l2_subdev_video_ops isp_video_ops = {
> @@ -338,7 +397,9 @@ int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev)
> v4l2_set_subdevdata(sd, isp_dev);
>
> pads[STF_ISP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
> + pads[STF_ISP_PAD_SINK_PARAMS].flags = MEDIA_PAD_FL_SINK;
> pads[STF_ISP_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
> + pads[STF_ISP_PAD_SRC_SCD].flags = MEDIA_PAD_FL_SOURCE;
>
> sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP;
> sd->entity.ops = &isp_media_ops;
> diff --git a/drivers/staging/media/starfive/camss/stf-isp.h b/drivers/staging/media/starfive/camss/stf-isp.h
> index 955cbb048363..bc7e7b0736fa 100644
> --- a/drivers/staging/media/starfive/camss/stf-isp.h
> +++ b/drivers/staging/media/starfive/camss/stf-isp.h
> @@ -392,7 +392,9 @@
> /* pad id for media framework */
> enum stf_isp_pad_id {
> STF_ISP_PAD_SINK = 0,
> + STF_ISP_PAD_SINK_PARAMS,
> STF_ISP_PAD_SRC,
> + STF_ISP_PAD_SRC_SCD,
> STF_ISP_PAD_MAX
> };
>
@@ -21,13 +21,23 @@ static const struct stf_isp_format isp_formats_sink[] = {
{ MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
};
+static const struct stf_isp_format isp_formats_sink_params[] = {
+ { MEDIA_BUS_FMT_METADATA_FIXED },
+};
+
static const struct stf_isp_format isp_formats_source[] = {
{ MEDIA_BUS_FMT_YUYV8_1_5X8, 8 },
};
+static const struct stf_isp_format isp_formats_source_scd[] = {
+ { MEDIA_BUS_FMT_METADATA_FIXED },
+};
+
static const struct stf_isp_format_table isp_formats_st7110[] = {
{ isp_formats_sink, ARRAY_SIZE(isp_formats_sink) },
+ { isp_formats_sink_params, ARRAY_SIZE(isp_formats_sink_params) },
{ isp_formats_source, ARRAY_SIZE(isp_formats_source) },
+ { isp_formats_source_scd, ARRAY_SIZE(isp_formats_source_scd) },
};
static const struct stf_isp_format *
@@ -93,13 +103,19 @@ static void isp_try_format(struct stf_isp_dev *isp_dev,
formats = &isp_dev->formats[pad];
- fmt->width = clamp_t(u32, fmt->width, STFCAMSS_FRAME_MIN_WIDTH,
- STFCAMSS_FRAME_MAX_WIDTH);
- fmt->height = clamp_t(u32, fmt->height, STFCAMSS_FRAME_MIN_HEIGHT,
- STFCAMSS_FRAME_MAX_HEIGHT);
- fmt->height &= ~0x1;
+ if (pad != STF_ISP_PAD_SRC_SCD && pad != STF_ISP_PAD_SINK_PARAMS) {
+ fmt->width = clamp_t(u32, fmt->width, STFCAMSS_FRAME_MIN_WIDTH,
+ STFCAMSS_FRAME_MAX_WIDTH);
+ fmt->height = clamp_t(u32, fmt->height, STFCAMSS_FRAME_MIN_HEIGHT,
+ STFCAMSS_FRAME_MAX_HEIGHT);
+ fmt->height &= ~0x1;
+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ } else {
+ fmt->width = 1;
+ fmt->height = 1;
+ }
+
fmt->field = V4L2_FIELD_NONE;
- fmt->colorspace = V4L2_COLORSPACE_SRGB;
fmt->flags = 0;
if (!stf_g_fmt_by_mcode(formats, fmt->code))
@@ -119,7 +135,7 @@ static int isp_enum_mbus_code(struct v4l2_subdev *sd,
formats = &isp_dev->formats[code->pad];
code->code = formats->fmts[code->index].code;
- } else {
+ } else if (code->pad == STF_ISP_PAD_SRC) {
struct v4l2_mbus_framefmt *sink_fmt;
if (code->index >= ARRAY_SIZE(isp_formats_source))
@@ -131,6 +147,10 @@ static int isp_enum_mbus_code(struct v4l2_subdev *sd,
code->code = sink_fmt->code;
if (!code->code)
return -EINVAL;
+ } else {
+ if (code->index > 0)
+ return -EINVAL;
+ code->code = MEDIA_BUS_FMT_METADATA_FIXED;
}
code->flags = 0;
@@ -151,6 +171,9 @@ static int isp_set_format(struct v4l2_subdev *sd,
isp_try_format(isp_dev, state, fmt->pad, &fmt->format);
*format = fmt->format;
+ if (fmt->pad == STF_ISP_PAD_SRC_SCD || fmt->pad == STF_ISP_PAD_SINK_PARAMS)
+ return 0;
+
isp_dev->current_fmt = stf_g_fmt_by_mcode(&isp_dev->formats[fmt->pad],
fmt->format.code);
@@ -202,6 +225,9 @@ static int isp_get_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_format fmt = { 0 };
struct v4l2_rect *rect;
+ if (sel->pad == STF_ISP_PAD_SRC_SCD || sel->pad == STF_ISP_PAD_SINK_PARAMS)
+ return -EINVAL;
+
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
if (sel->pad == STF_ISP_PAD_SINK) {
@@ -239,6 +265,9 @@ static int isp_set_selection(struct v4l2_subdev *sd,
struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
struct v4l2_rect *rect;
+ if (sel->pad == STF_ISP_PAD_SRC_SCD || sel->pad == STF_ISP_PAD_SINK_PARAMS)
+ return -EINVAL;
+
if (sel->target != V4L2_SEL_TGT_CROP)
return -EINVAL;
@@ -296,8 +325,38 @@ static int isp_init_formats(struct v4l2_subdev *sd,
.height = 1080
}
};
+ struct v4l2_subdev_format format_params = {
+ .pad = STF_ISP_PAD_SINK_PARAMS,
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .format = {
+ .code = MEDIA_BUS_FMT_METADATA_FIXED,
+ .width = 1,
+ .height = 1
+ }
+ };
+ struct v4l2_subdev_format format_scd = {
+ .pad = STF_ISP_PAD_SRC_SCD,
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .format = {
+ .code = MEDIA_BUS_FMT_METADATA_FIXED,
+ .width = 1,
+ .height = 1
+ }
+ };
+ int ret;
+
+ /* Init for STF_ISP_PAD_SINK and STF_ISP_PAD_SRC pad */
+ ret = isp_set_format(sd, sd_state, &format);
+ if (ret < 0)
+ return ret;
+
+ /* Init for STF_ISP_PAD_SINK_PARAMS pad */
+ ret = isp_set_format(sd, sd_state, &format_params);
+ if (ret < 0)
+ return ret;
- return isp_set_format(sd, sd_state, &format);
+ /* Init for STF_ISP_PAD_SRC_SCD pad */
+ return isp_set_format(sd, sd_state, &format_scd);
}
static const struct v4l2_subdev_video_ops isp_video_ops = {
@@ -338,7 +397,9 @@ int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev)
v4l2_set_subdevdata(sd, isp_dev);
pads[STF_ISP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+ pads[STF_ISP_PAD_SINK_PARAMS].flags = MEDIA_PAD_FL_SINK;
pads[STF_ISP_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
+ pads[STF_ISP_PAD_SRC_SCD].flags = MEDIA_PAD_FL_SOURCE;
sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP;
sd->entity.ops = &isp_media_ops;
@@ -392,7 +392,9 @@
/* pad id for media framework */
enum stf_isp_pad_id {
STF_ISP_PAD_SINK = 0,
+ STF_ISP_PAD_SINK_PARAMS,
STF_ISP_PAD_SRC,
+ STF_ISP_PAD_SRC_SCD,
STF_ISP_PAD_MAX
};