Message ID | 20240709083824.430473-5-changhuang.liang@starfivetech.com |
---|---|
State | New |
Headers | show |
Series | Add ISP 3A for StarFive | expand |
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 > }; >
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) + 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; 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 };
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(-)