diff mbox series

[07/13] media: am437x-vpfe: Use a per instance format array instead of a static one

Message ID 20190909162743.30114-8-bparrot@ti.com (mailing list archive)
State New, archived
Headers show
Series media: am437x-vpfe: overdue maintenance | expand

Commit Message

Benoit Parrot Sept. 9, 2019, 4:27 p.m. UTC
Using a statically defined format array would cause issue when
multiple vpfe instance would be connected to sub-device of
different capabilities. We need to use an instance based array
instead to properly maintain a per port/instance format list.

Signed-off-by: Benoit Parrot <bparrot@ti.com>
---
 drivers/media/platform/am437x/am437x-vpfe.c | 108 ++++++++------------
 drivers/media/platform/am437x/am437x-vpfe.h |  34 ++++++
 2 files changed, 74 insertions(+), 68 deletions(-)

Comments

Hans Verkuil Sept. 13, 2019, 1:07 p.m. UTC | #1
On 9/9/19 6:27 PM, Benoit Parrot wrote:
> Using a statically defined format array would cause issue when
> multiple vpfe instance would be connected to sub-device of
> different capabilities. We need to use an instance based array
> instead to properly maintain a per port/instance format list.
> 
> Signed-off-by: Benoit Parrot <bparrot@ti.com>
> ---
>  drivers/media/platform/am437x/am437x-vpfe.c | 108 ++++++++------------
>  drivers/media/platform/am437x/am437x-vpfe.h |  34 ++++++
>  2 files changed, 74 insertions(+), 68 deletions(-)
> 
> diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
> index ac759c066d00..e76dc2b3b7b8 100644
> --- a/drivers/media/platform/am437x/am437x-vpfe.c
> +++ b/drivers/media/platform/am437x/am437x-vpfe.c
> @@ -69,30 +69,6 @@ static const struct vpfe_standard vpfe_standards[] = {
>  	{V4L2_STD_625_50, 720, 576, {54, 59}, 1},
>  };
>  
> -struct bus_format {
> -	unsigned int width;
> -	unsigned int bpp;
> -};
> -
> -/*
> - * struct vpfe_fmt - VPFE media bus format information
> - * @code: V4L2 media bus format code
> - * @shifted: V4L2 media bus format code for the same pixel layout but
> - *	shifted to be 8 bits per pixel. =0 if format is not shiftable.
> - * @pixelformat: V4L2 pixel format FCC identifier
> - * @width: Bits per pixel (when transferred over a bus)
> - * @bpp: Bytes per pixel (when stored in memory)
> - * @supported: Indicates format supported by subdev
> - */
> -struct vpfe_fmt {
> -	u32 fourcc;
> -	u32 code;
> -	struct bus_format l;
> -	struct bus_format s;
> -	bool supported;
> -	u32 index;
> -};
> -
>  static struct vpfe_fmt formats[] = {
>  	{
>  		.fourcc		= V4L2_PIX_FMT_YUYV,
> @@ -101,7 +77,6 @@ static struct vpfe_fmt formats[] = {
>  		.l.bpp		= 4,
>  		.s.width	= 8,
>  		.s.bpp		= 2,
> -		.supported	= false,
>  	}, {
>  		.fourcc		= V4L2_PIX_FMT_UYVY,
>  		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
> @@ -109,7 +84,6 @@ static struct vpfe_fmt formats[] = {
>  		.l.bpp		= 4,
>  		.s.width	= 8,
>  		.s.bpp		= 2,
> -		.supported	= false,
>  	}, {
>  		.fourcc		= V4L2_PIX_FMT_YVYU,
>  		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
> @@ -117,7 +91,6 @@ static struct vpfe_fmt formats[] = {
>  		.l.bpp		= 4,
>  		.s.width	= 8,
>  		.s.bpp		= 2,
> -		.supported	= false,
>  	}, {
>  		.fourcc		= V4L2_PIX_FMT_VYUY,
>  		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
> @@ -125,7 +98,6 @@ static struct vpfe_fmt formats[] = {
>  		.l.bpp		= 4,
>  		.s.width	= 8,
>  		.s.bpp		= 2,
> -		.supported	= false,
>  	}, {
>  		.fourcc		= V4L2_PIX_FMT_SBGGR8,
>  		.code		= MEDIA_BUS_FMT_SBGGR8_1X8,
> @@ -133,7 +105,6 @@ static struct vpfe_fmt formats[] = {
>  		.l.bpp		= 2,
>  		.s.width	= 8,
>  		.s.bpp		= 1,
> -		.supported	= false,
>  	}, {
>  		.fourcc		= V4L2_PIX_FMT_SGBRG8,
>  		.code		= MEDIA_BUS_FMT_SGBRG8_1X8,
> @@ -141,7 +112,6 @@ static struct vpfe_fmt formats[] = {
>  		.l.bpp		= 2,
>  		.s.width	= 8,
>  		.s.bpp		= 1,
> -		.supported	= false,
>  	}, {
>  		.fourcc		= V4L2_PIX_FMT_SGRBG8,
>  		.code		= MEDIA_BUS_FMT_SGRBG8_1X8,
> @@ -149,7 +119,6 @@ static struct vpfe_fmt formats[] = {
>  		.l.bpp		= 2,
>  		.s.width	= 8,
>  		.s.bpp		= 1,
> -		.supported	= false,
>  	}, {
>  		.fourcc		= V4L2_PIX_FMT_SRGGB8,
>  		.code		= MEDIA_BUS_FMT_SRGGB8_1X8,
> @@ -157,7 +126,6 @@ static struct vpfe_fmt formats[] = {
>  		.l.bpp		= 2,
>  		.s.width	= 8,
>  		.s.bpp		= 1,
> -		.supported	= false,
>  	}, {
>  		.fourcc		= V4L2_PIX_FMT_RGB565,
>  		.code		= MEDIA_BUS_FMT_RGB565_2X8_LE,
> @@ -165,7 +133,6 @@ static struct vpfe_fmt formats[] = {
>  		.l.bpp		= 4,
>  		.s.width	= 8,
>  		.s.bpp		= 2,
> -		.supported	= false,
>  	}, {
>  		.fourcc		= V4L2_PIX_FMT_RGB565X,
>  		.code		= MEDIA_BUS_FMT_RGB565_2X8_BE,
> @@ -173,7 +140,6 @@ static struct vpfe_fmt formats[] = {
>  		.l.bpp		= 4,
>  		.s.width	= 8,
>  		.s.bpp		= 2,
> -		.supported	= false,
>  	},
>  };
>  
> @@ -181,13 +147,14 @@ static int
>  __vpfe_get_format(struct vpfe_device *vpfe,
>  		  struct v4l2_format *format, unsigned int *bpp);
>  
> -static struct vpfe_fmt *find_format_by_code(unsigned int code)
> +static struct vpfe_fmt *find_format_by_code(struct vpfe_device *vpfe,
> +					    unsigned int code)
>  {
>  	struct vpfe_fmt *fmt;
>  	unsigned int k;
>  
> -	for (k = 0; k < ARRAY_SIZE(formats); k++) {
> -		fmt = &formats[k];
> +	for (k = 0; k < vpfe->num_active_fmt; k++) {
> +		fmt = vpfe->active_fmt[k];
>  		if (fmt->code == code)
>  			return fmt;
>  	}
> @@ -195,13 +162,14 @@ static struct vpfe_fmt *find_format_by_code(unsigned int code)
>  	return NULL;
>  }
>  
> -static struct vpfe_fmt *find_format_by_pix(unsigned int pixelformat)
> +static struct vpfe_fmt *find_format_by_pix(struct vpfe_device *vpfe,
> +					   unsigned int pixelformat)
>  {
>  	struct vpfe_fmt *fmt;
>  	unsigned int k;
>  
> -	for (k = 0; k < ARRAY_SIZE(formats); k++) {
> -		fmt = &formats[k];
> +	for (k = 0; k < vpfe->num_active_fmt; k++) {
> +		fmt = vpfe->active_fmt[k];
>  		if (fmt->fourcc == pixelformat)
>  			return fmt;
>  	}
> @@ -218,7 +186,7 @@ mbus_to_pix(struct vpfe_device *vpfe,
>  	unsigned int bus_width = sdinfo->vpfe_param.bus_width;
>  	struct vpfe_fmt *fmt;
>  
> -	fmt = find_format_by_code(mbus->code);
> +	fmt = find_format_by_code(vpfe, mbus->code);
>  	if (WARN_ON(fmt == NULL)) {
>  		pr_err("Invalid mbus code set\n");
>  		*bpp = 1;
> @@ -241,12 +209,12 @@ static void pix_to_mbus(struct vpfe_device *vpfe,
>  {
>  	struct vpfe_fmt *fmt;
>  
> -	fmt = find_format_by_pix(pix_fmt->pixelformat);
> +	fmt = find_format_by_pix(vpfe, pix_fmt->pixelformat);
>  	if (!fmt) {
>  		/* default to first entry */
>  		vpfe_dbg(3, vpfe, "Invalid pixel code: %x, default used instead\n",
>  			pix_fmt->pixelformat);
> -		fmt = &formats[0];
> +		fmt = vpfe->active_fmt[0];
>  	}
>  
>  	memset(mbus_fmt, 0, sizeof(*mbus_fmt));
> @@ -1494,8 +1462,7 @@ static int vpfe_enum_fmt(struct file *file, void  *priv,
>  {
>  	struct vpfe_device *vpfe = video_drvdata(file);
>  	struct vpfe_subdev_info *sdinfo;
> -	struct vpfe_fmt *fmt = NULL;
> -	unsigned int k;
> +	struct vpfe_fmt *fmt;
>  
>  	vpfe_dbg(2, vpfe, "vpfe_enum_format index:%d\n",
>  		f->index);
> @@ -1504,17 +1471,10 @@ static int vpfe_enum_fmt(struct file *file, void  *priv,
>  	if (!sdinfo->sd)
>  		return -EINVAL;
>  
> -	if (f->index > ARRAY_SIZE(formats))
> +	if (f->index >= vpfe->num_active_fmt)
>  		return -EINVAL;
>  
> -	for (k = 0; k < ARRAY_SIZE(formats); k++) {
> -		if (formats[k].index == f->index) {
> -			fmt = &formats[k];
> -			break;
> -		}
> -	}
> -	if (!fmt)
> -		return -EINVAL;
> +	fmt = vpfe->active_fmt[f->index];
>  
>  	f->pixelformat = fmt->fourcc;
>  
> @@ -1593,7 +1553,7 @@ static int vpfe_enum_size(struct file *file, void  *priv,
>  	vpfe_dbg(2, vpfe, "vpfe_enum_size\n");
>  
>  	/* check for valid format */
> -	fmt = find_format_by_pix(fsize->pixel_format);
> +	fmt = find_format_by_pix(vpfe, fsize->pixel_format);
>  	if (!fmt) {
>  		vpfe_dbg(3, vpfe, "Invalid pixel code: %x, default used instead\n",
>  			fsize->pixel_format);
> @@ -2281,8 +2241,10 @@ vpfe_async_bound(struct v4l2_async_notifier *notifier,
>  					       struct vpfe_device, v4l2_dev);
>  	struct v4l2_subdev_mbus_code_enum mbus_code;
>  	struct vpfe_subdev_info *sdinfo;
> +	struct vpfe_fmt *fmt;
> +	int ret = 0;
>  	bool found = false;
> -	int i, j;
> +	int i, j, k;
>  
>  	vpfe_dbg(1, vpfe, "vpfe_async_bound\n");
>  
> @@ -2304,27 +2266,37 @@ vpfe_async_bound(struct v4l2_async_notifier *notifier,
>  
>  	vpfe->video_dev.tvnorms |= sdinfo->inputs[0].std;
>  
> -	/* setup the supported formats & indexes */
> -	for (j = 0, i = 0; ; ++j) {
> -		struct vpfe_fmt *fmt;
> -		int ret;
> -
> +	vpfe->num_active_fmt = 0;
> +	for (j = 0, i = 0; (ret != -EINVAL); ++j) {
>  		memset(&mbus_code, 0, sizeof(mbus_code));
>  		mbus_code.index = j;
>  		mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
>  		ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
> -			       NULL, &mbus_code);
> +				       NULL, &mbus_code);
>  		if (ret)
> -			break;
> -
> -		fmt = find_format_by_code(mbus_code.code);
> -		if (!fmt)
>  			continue;
>  
> -		fmt->supported = true;
> -		fmt->index = i++;
> +		vpfe_dbg(3, vpfe,
> +			 "subdev %s: code: %04x idx: %d\n",
> +			 subdev->name, mbus_code.code, j);
> +
> +		for (k = 0; k < ARRAY_SIZE(formats); k++) {
> +			fmt = &formats[k];
> +			if (mbus_code.code != fmt->code)
> +				continue;
> +			vpfe->active_fmt[i] = fmt;
> +			vpfe_dbg(3, vpfe,
> +				 "matched fourcc: %4.4s code: %04x idx: %d\n",
> +				 (char *)&fmt->fourcc, mbus_code.code, i);
> +			vpfe->num_active_fmt = ++i;
> +		}
>  	}
>  
> +	if (!i) {
> +		vpfe_err(vpfe, "No suitable format reported by subdev %s\n",
> +			 subdev->name);
> +		return -EINVAL;
> +	}
>  	return 0;
>  }
>  
> diff --git a/drivers/media/platform/am437x/am437x-vpfe.h b/drivers/media/platform/am437x/am437x-vpfe.h
> index 2dde09780215..6f25750f84e4 100644
> --- a/drivers/media/platform/am437x/am437x-vpfe.h
> +++ b/drivers/media/platform/am437x/am437x-vpfe.h
> @@ -215,6 +215,37 @@ struct vpfe_ccdc {
>  	u32 ccdc_ctx[VPFE_REG_END / sizeof(u32)];
>  };
>  
> +/*
> + * struct bus_format - VPFE bus format information
> + * @width: Bits per pixel (when transferred over a bus)
> + * @bpp: Bytes per pixel (when stored in memory)

Slightly confused: the '@' indicates docbook format, but the '/*'
indicates a regular comment. Either choose '/**' or drop the @.

> + */
> +struct bus_format {
> +	unsigned int width;
> +	unsigned int bpp;
> +};
> +
> +/*
> + * struct vpfe_fmt - VPFE media bus format information
> + * @fourcc: V4L2 pixel format code
> + * @code: V4L2 media bus format code
> + * @l: 10 bit bus format info
> + * @s: 8 bit bus format info
> + */
> +struct vpfe_fmt {
> +	u32 fourcc;
> +	u32 code;
> +	struct bus_format l;
> +	struct bus_format s;
> +};
> +
> +/*
> + * This value needs to be at least as large as the number of entry in
> + * formats[].
> + * When formats[] is modified make sure to adjust this value also.
> + */
> +#define VPFE_MAX_ACTIVE_FMT	10

I recommend adding something like:

#if ARRAY_SIZE(formats) > VPFE_MAX_ACTIVE_FMT
	#error must update VPFE_MAX_ACTIVE_FMT
#endif

to am437x-vpfe.c.

Or something along those lines. Don't rely on just the comment :-)

Regards,

	Hans

> +
>  struct vpfe_device {
>  	/* V4l2 specific parameters */
>  	/* Identifies video device for this channel */
> @@ -252,6 +283,9 @@ struct vpfe_device {
>  	struct v4l2_format fmt;
>  	/* Used to store current bytes per pixel based on current format */
>  	unsigned int bpp;
> +	struct vpfe_fmt	*active_fmt[VPFE_MAX_ACTIVE_FMT];
> +	unsigned int num_active_fmt;
> +
>  	/*
>  	 * used when IMP is chained to store the crop window which
>  	 * is different from the image window
>
Benoit Parrot Sept. 13, 2019, 1:29 p.m. UTC | #2
Hans Verkuil <hverkuil@xs4all.nl> wrote on Fri [2019-Sep-13 15:07:29 +0200]:
> On 9/9/19 6:27 PM, Benoit Parrot wrote:
> > Using a statically defined format array would cause issue when
> > multiple vpfe instance would be connected to sub-device of
> > different capabilities. We need to use an instance based array
> > instead to properly maintain a per port/instance format list.
> > 
> > Signed-off-by: Benoit Parrot <bparrot@ti.com>
> > ---
> >  drivers/media/platform/am437x/am437x-vpfe.c | 108 ++++++++------------
> >  drivers/media/platform/am437x/am437x-vpfe.h |  34 ++++++
> >  2 files changed, 74 insertions(+), 68 deletions(-)
> > 
> > diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
> > index ac759c066d00..e76dc2b3b7b8 100644
> > --- a/drivers/media/platform/am437x/am437x-vpfe.c
> > +++ b/drivers/media/platform/am437x/am437x-vpfe.c
> > @@ -69,30 +69,6 @@ static const struct vpfe_standard vpfe_standards[] = {
> >  	{V4L2_STD_625_50, 720, 576, {54, 59}, 1},
> >  };
> >  
> > -struct bus_format {
> > -	unsigned int width;
> > -	unsigned int bpp;
> > -};
> > -
> > -/*
> > - * struct vpfe_fmt - VPFE media bus format information
> > - * @code: V4L2 media bus format code
> > - * @shifted: V4L2 media bus format code for the same pixel layout but
> > - *	shifted to be 8 bits per pixel. =0 if format is not shiftable.
> > - * @pixelformat: V4L2 pixel format FCC identifier
> > - * @width: Bits per pixel (when transferred over a bus)
> > - * @bpp: Bytes per pixel (when stored in memory)
> > - * @supported: Indicates format supported by subdev
> > - */
> > -struct vpfe_fmt {
> > -	u32 fourcc;
> > -	u32 code;
> > -	struct bus_format l;
> > -	struct bus_format s;
> > -	bool supported;
> > -	u32 index;
> > -};
> > -
> >  static struct vpfe_fmt formats[] = {
> >  	{
> >  		.fourcc		= V4L2_PIX_FMT_YUYV,
> > @@ -101,7 +77,6 @@ static struct vpfe_fmt formats[] = {
> >  		.l.bpp		= 4,
> >  		.s.width	= 8,
> >  		.s.bpp		= 2,
> > -		.supported	= false,
> >  	}, {
> >  		.fourcc		= V4L2_PIX_FMT_UYVY,
> >  		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
> > @@ -109,7 +84,6 @@ static struct vpfe_fmt formats[] = {
> >  		.l.bpp		= 4,
> >  		.s.width	= 8,
> >  		.s.bpp		= 2,
> > -		.supported	= false,
> >  	}, {
> >  		.fourcc		= V4L2_PIX_FMT_YVYU,
> >  		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
> > @@ -117,7 +91,6 @@ static struct vpfe_fmt formats[] = {
> >  		.l.bpp		= 4,
> >  		.s.width	= 8,
> >  		.s.bpp		= 2,
> > -		.supported	= false,
> >  	}, {
> >  		.fourcc		= V4L2_PIX_FMT_VYUY,
> >  		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
> > @@ -125,7 +98,6 @@ static struct vpfe_fmt formats[] = {
> >  		.l.bpp		= 4,
> >  		.s.width	= 8,
> >  		.s.bpp		= 2,
> > -		.supported	= false,
> >  	}, {
> >  		.fourcc		= V4L2_PIX_FMT_SBGGR8,
> >  		.code		= MEDIA_BUS_FMT_SBGGR8_1X8,
> > @@ -133,7 +105,6 @@ static struct vpfe_fmt formats[] = {
> >  		.l.bpp		= 2,
> >  		.s.width	= 8,
> >  		.s.bpp		= 1,
> > -		.supported	= false,
> >  	}, {
> >  		.fourcc		= V4L2_PIX_FMT_SGBRG8,
> >  		.code		= MEDIA_BUS_FMT_SGBRG8_1X8,
> > @@ -141,7 +112,6 @@ static struct vpfe_fmt formats[] = {
> >  		.l.bpp		= 2,
> >  		.s.width	= 8,
> >  		.s.bpp		= 1,
> > -		.supported	= false,
> >  	}, {
> >  		.fourcc		= V4L2_PIX_FMT_SGRBG8,
> >  		.code		= MEDIA_BUS_FMT_SGRBG8_1X8,
> > @@ -149,7 +119,6 @@ static struct vpfe_fmt formats[] = {
> >  		.l.bpp		= 2,
> >  		.s.width	= 8,
> >  		.s.bpp		= 1,
> > -		.supported	= false,
> >  	}, {
> >  		.fourcc		= V4L2_PIX_FMT_SRGGB8,
> >  		.code		= MEDIA_BUS_FMT_SRGGB8_1X8,
> > @@ -157,7 +126,6 @@ static struct vpfe_fmt formats[] = {
> >  		.l.bpp		= 2,
> >  		.s.width	= 8,
> >  		.s.bpp		= 1,
> > -		.supported	= false,
> >  	}, {
> >  		.fourcc		= V4L2_PIX_FMT_RGB565,
> >  		.code		= MEDIA_BUS_FMT_RGB565_2X8_LE,
> > @@ -165,7 +133,6 @@ static struct vpfe_fmt formats[] = {
> >  		.l.bpp		= 4,
> >  		.s.width	= 8,
> >  		.s.bpp		= 2,
> > -		.supported	= false,
> >  	}, {
> >  		.fourcc		= V4L2_PIX_FMT_RGB565X,
> >  		.code		= MEDIA_BUS_FMT_RGB565_2X8_BE,
> > @@ -173,7 +140,6 @@ static struct vpfe_fmt formats[] = {
> >  		.l.bpp		= 4,
> >  		.s.width	= 8,
> >  		.s.bpp		= 2,
> > -		.supported	= false,
> >  	},
> >  };
> >  
> > @@ -181,13 +147,14 @@ static int
> >  __vpfe_get_format(struct vpfe_device *vpfe,
> >  		  struct v4l2_format *format, unsigned int *bpp);
> >  
> > -static struct vpfe_fmt *find_format_by_code(unsigned int code)
> > +static struct vpfe_fmt *find_format_by_code(struct vpfe_device *vpfe,
> > +					    unsigned int code)
> >  {
> >  	struct vpfe_fmt *fmt;
> >  	unsigned int k;
> >  
> > -	for (k = 0; k < ARRAY_SIZE(formats); k++) {
> > -		fmt = &formats[k];
> > +	for (k = 0; k < vpfe->num_active_fmt; k++) {
> > +		fmt = vpfe->active_fmt[k];
> >  		if (fmt->code == code)
> >  			return fmt;
> >  	}
> > @@ -195,13 +162,14 @@ static struct vpfe_fmt *find_format_by_code(unsigned int code)
> >  	return NULL;
> >  }
> >  
> > -static struct vpfe_fmt *find_format_by_pix(unsigned int pixelformat)
> > +static struct vpfe_fmt *find_format_by_pix(struct vpfe_device *vpfe,
> > +					   unsigned int pixelformat)
> >  {
> >  	struct vpfe_fmt *fmt;
> >  	unsigned int k;
> >  
> > -	for (k = 0; k < ARRAY_SIZE(formats); k++) {
> > -		fmt = &formats[k];
> > +	for (k = 0; k < vpfe->num_active_fmt; k++) {
> > +		fmt = vpfe->active_fmt[k];
> >  		if (fmt->fourcc == pixelformat)
> >  			return fmt;
> >  	}
> > @@ -218,7 +186,7 @@ mbus_to_pix(struct vpfe_device *vpfe,
> >  	unsigned int bus_width = sdinfo->vpfe_param.bus_width;
> >  	struct vpfe_fmt *fmt;
> >  
> > -	fmt = find_format_by_code(mbus->code);
> > +	fmt = find_format_by_code(vpfe, mbus->code);
> >  	if (WARN_ON(fmt == NULL)) {
> >  		pr_err("Invalid mbus code set\n");
> >  		*bpp = 1;
> > @@ -241,12 +209,12 @@ static void pix_to_mbus(struct vpfe_device *vpfe,
> >  {
> >  	struct vpfe_fmt *fmt;
> >  
> > -	fmt = find_format_by_pix(pix_fmt->pixelformat);
> > +	fmt = find_format_by_pix(vpfe, pix_fmt->pixelformat);
> >  	if (!fmt) {
> >  		/* default to first entry */
> >  		vpfe_dbg(3, vpfe, "Invalid pixel code: %x, default used instead\n",
> >  			pix_fmt->pixelformat);
> > -		fmt = &formats[0];
> > +		fmt = vpfe->active_fmt[0];
> >  	}
> >  
> >  	memset(mbus_fmt, 0, sizeof(*mbus_fmt));
> > @@ -1494,8 +1462,7 @@ static int vpfe_enum_fmt(struct file *file, void  *priv,
> >  {
> >  	struct vpfe_device *vpfe = video_drvdata(file);
> >  	struct vpfe_subdev_info *sdinfo;
> > -	struct vpfe_fmt *fmt = NULL;
> > -	unsigned int k;
> > +	struct vpfe_fmt *fmt;
> >  
> >  	vpfe_dbg(2, vpfe, "vpfe_enum_format index:%d\n",
> >  		f->index);
> > @@ -1504,17 +1471,10 @@ static int vpfe_enum_fmt(struct file *file, void  *priv,
> >  	if (!sdinfo->sd)
> >  		return -EINVAL;
> >  
> > -	if (f->index > ARRAY_SIZE(formats))
> > +	if (f->index >= vpfe->num_active_fmt)
> >  		return -EINVAL;
> >  
> > -	for (k = 0; k < ARRAY_SIZE(formats); k++) {
> > -		if (formats[k].index == f->index) {
> > -			fmt = &formats[k];
> > -			break;
> > -		}
> > -	}
> > -	if (!fmt)
> > -		return -EINVAL;
> > +	fmt = vpfe->active_fmt[f->index];
> >  
> >  	f->pixelformat = fmt->fourcc;
> >  
> > @@ -1593,7 +1553,7 @@ static int vpfe_enum_size(struct file *file, void  *priv,
> >  	vpfe_dbg(2, vpfe, "vpfe_enum_size\n");
> >  
> >  	/* check for valid format */
> > -	fmt = find_format_by_pix(fsize->pixel_format);
> > +	fmt = find_format_by_pix(vpfe, fsize->pixel_format);
> >  	if (!fmt) {
> >  		vpfe_dbg(3, vpfe, "Invalid pixel code: %x, default used instead\n",
> >  			fsize->pixel_format);
> > @@ -2281,8 +2241,10 @@ vpfe_async_bound(struct v4l2_async_notifier *notifier,
> >  					       struct vpfe_device, v4l2_dev);
> >  	struct v4l2_subdev_mbus_code_enum mbus_code;
> >  	struct vpfe_subdev_info *sdinfo;
> > +	struct vpfe_fmt *fmt;
> > +	int ret = 0;
> >  	bool found = false;
> > -	int i, j;
> > +	int i, j, k;
> >  
> >  	vpfe_dbg(1, vpfe, "vpfe_async_bound\n");
> >  
> > @@ -2304,27 +2266,37 @@ vpfe_async_bound(struct v4l2_async_notifier *notifier,
> >  
> >  	vpfe->video_dev.tvnorms |= sdinfo->inputs[0].std;
> >  
> > -	/* setup the supported formats & indexes */
> > -	for (j = 0, i = 0; ; ++j) {
> > -		struct vpfe_fmt *fmt;
> > -		int ret;
> > -
> > +	vpfe->num_active_fmt = 0;
> > +	for (j = 0, i = 0; (ret != -EINVAL); ++j) {
> >  		memset(&mbus_code, 0, sizeof(mbus_code));
> >  		mbus_code.index = j;
> >  		mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> >  		ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
> > -			       NULL, &mbus_code);
> > +				       NULL, &mbus_code);
> >  		if (ret)
> > -			break;
> > -
> > -		fmt = find_format_by_code(mbus_code.code);
> > -		if (!fmt)
> >  			continue;
> >  
> > -		fmt->supported = true;
> > -		fmt->index = i++;
> > +		vpfe_dbg(3, vpfe,
> > +			 "subdev %s: code: %04x idx: %d\n",
> > +			 subdev->name, mbus_code.code, j);
> > +
> > +		for (k = 0; k < ARRAY_SIZE(formats); k++) {
> > +			fmt = &formats[k];
> > +			if (mbus_code.code != fmt->code)
> > +				continue;
> > +			vpfe->active_fmt[i] = fmt;
> > +			vpfe_dbg(3, vpfe,
> > +				 "matched fourcc: %4.4s code: %04x idx: %d\n",
> > +				 (char *)&fmt->fourcc, mbus_code.code, i);
> > +			vpfe->num_active_fmt = ++i;
> > +		}
> >  	}
> >  
> > +	if (!i) {
> > +		vpfe_err(vpfe, "No suitable format reported by subdev %s\n",
> > +			 subdev->name);
> > +		return -EINVAL;
> > +	}
> >  	return 0;
> >  }
> >  
> > diff --git a/drivers/media/platform/am437x/am437x-vpfe.h b/drivers/media/platform/am437x/am437x-vpfe.h
> > index 2dde09780215..6f25750f84e4 100644
> > --- a/drivers/media/platform/am437x/am437x-vpfe.h
> > +++ b/drivers/media/platform/am437x/am437x-vpfe.h
> > @@ -215,6 +215,37 @@ struct vpfe_ccdc {
> >  	u32 ccdc_ctx[VPFE_REG_END / sizeof(u32)];
> >  };
> >  
> > +/*
> > + * struct bus_format - VPFE bus format information
> > + * @width: Bits per pixel (when transferred over a bus)
> > + * @bpp: Bytes per pixel (when stored in memory)
> 
> Slightly confused: the '@' indicates docbook format, but the '/*'
> indicates a regular comment. Either choose '/**' or drop the @.

Yeah I think this driver pre-date all of that.

Now did you mean to fix just the above comments or all of the other ones
also.

Frankly, I do not have a clear idea either way.
I guess i'll just remove the '@' tag then.

> 
> > + */
> > +struct bus_format {
> > +	unsigned int width;
> > +	unsigned int bpp;
> > +};
> > +
> > +/*
> > + * struct vpfe_fmt - VPFE media bus format information
> > + * @fourcc: V4L2 pixel format code
> > + * @code: V4L2 media bus format code
> > + * @l: 10 bit bus format info
> > + * @s: 8 bit bus format info
> > + */
> > +struct vpfe_fmt {
> > +	u32 fourcc;
> > +	u32 code;
> > +	struct bus_format l;
> > +	struct bus_format s;
> > +};
> > +
> > +/*
> > + * This value needs to be at least as large as the number of entry in
> > + * formats[].
> > + * When formats[] is modified make sure to adjust this value also.
> > + */
> > +#define VPFE_MAX_ACTIVE_FMT	10
> 
> I recommend adding something like:
> 
> #if ARRAY_SIZE(formats) > VPFE_MAX_ACTIVE_FMT
> 	#error must update VPFE_MAX_ACTIVE_FMT
> #endif
> 
> to am437x-vpfe.c.
> 
> Or something along those lines. Don't rely on just the comment :-)

Ah yes very good.

> 
> Regards,
> 
> 	Hans
> 
> > +
> >  struct vpfe_device {
> >  	/* V4l2 specific parameters */
> >  	/* Identifies video device for this channel */
> > @@ -252,6 +283,9 @@ struct vpfe_device {
> >  	struct v4l2_format fmt;
> >  	/* Used to store current bytes per pixel based on current format */
> >  	unsigned int bpp;
> > +	struct vpfe_fmt	*active_fmt[VPFE_MAX_ACTIVE_FMT];
> > +	unsigned int num_active_fmt;
> > +
> >  	/*
> >  	 * used when IMP is chained to store the crop window which
> >  	 * is different from the image window
> > 
>
Benoit Parrot Sept. 17, 2019, 4:19 p.m. UTC | #3
Hans Verkuil <hverkuil@xs4all.nl> wrote on Fri [2019-Sep-13 15:07:29 +0200]:
> On 9/9/19 6:27 PM, Benoit Parrot wrote:
> > +/*
> > + * This value needs to be at least as large as the number of entry in
> > + * formats[].
> > + * When formats[] is modified make sure to adjust this value also.
> > + */
> > +#define VPFE_MAX_ACTIVE_FMT	10
> 
> I recommend adding something like:
> 
> #if ARRAY_SIZE(formats) > VPFE_MAX_ACTIVE_FMT
> 	#error must update VPFE_MAX_ACTIVE_FMT
> #endif
> 
> to am437x-vpfe.c.
> 
> Or something along those lines. Don't rely on just the comment :-)

I remeber doing this a while back for another driver.
Not sure if you ever treid this or not but "#if ARRAY_SIZE()" construct
does not work because the ARRAY_SIZE() macro which needs to evaluate
sizeof() generates the following compiler error:

In file included from ../include/linux/delay.h:22,
                 from ../drivers/media/platform/am437x/am437x-vpfe.c:23:
../include/linux/kernel.h:47:26: warning: "sizeof" is not defined,
evaluates to 0 [-Wundef]
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) +
                          __must_be_array(arr))

So no luck there. But I remembered also how I previously fixed it.
In this case if instead of leaving the formats[] definition with empty
brackets you actually used the same defined value like
formats[VPFE_MAX_ACTIVE_FMT] then if you inadvertantly add more enties in
the table then the value of VPFE_MAX_ACTIVE_FMT then you'll get series of
compile time warnings like this:

drivers/media/platform/am437x/am437x-vpfe.c:108:5: warning: excess elements
in array initializer
  }, {
     ^
drivers/media/platform/am437x/am437x-vpfe.c:108:5: note: (near initialization
for ‘formats’)
drivers/media/platform/am437x/am437x-vpfe.c:115:5: warning: excess elements
in array initializer
  }, {

etc...

So this is how I will address this.

Benoit

> 
> Regards,
> 
> 	Hans
>
diff mbox series

Patch

diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
index ac759c066d00..e76dc2b3b7b8 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
@@ -69,30 +69,6 @@  static const struct vpfe_standard vpfe_standards[] = {
 	{V4L2_STD_625_50, 720, 576, {54, 59}, 1},
 };
 
-struct bus_format {
-	unsigned int width;
-	unsigned int bpp;
-};
-
-/*
- * struct vpfe_fmt - VPFE media bus format information
- * @code: V4L2 media bus format code
- * @shifted: V4L2 media bus format code for the same pixel layout but
- *	shifted to be 8 bits per pixel. =0 if format is not shiftable.
- * @pixelformat: V4L2 pixel format FCC identifier
- * @width: Bits per pixel (when transferred over a bus)
- * @bpp: Bytes per pixel (when stored in memory)
- * @supported: Indicates format supported by subdev
- */
-struct vpfe_fmt {
-	u32 fourcc;
-	u32 code;
-	struct bus_format l;
-	struct bus_format s;
-	bool supported;
-	u32 index;
-};
-
 static struct vpfe_fmt formats[] = {
 	{
 		.fourcc		= V4L2_PIX_FMT_YUYV,
@@ -101,7 +77,6 @@  static struct vpfe_fmt formats[] = {
 		.l.bpp		= 4,
 		.s.width	= 8,
 		.s.bpp		= 2,
-		.supported	= false,
 	}, {
 		.fourcc		= V4L2_PIX_FMT_UYVY,
 		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
@@ -109,7 +84,6 @@  static struct vpfe_fmt formats[] = {
 		.l.bpp		= 4,
 		.s.width	= 8,
 		.s.bpp		= 2,
-		.supported	= false,
 	}, {
 		.fourcc		= V4L2_PIX_FMT_YVYU,
 		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
@@ -117,7 +91,6 @@  static struct vpfe_fmt formats[] = {
 		.l.bpp		= 4,
 		.s.width	= 8,
 		.s.bpp		= 2,
-		.supported	= false,
 	}, {
 		.fourcc		= V4L2_PIX_FMT_VYUY,
 		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
@@ -125,7 +98,6 @@  static struct vpfe_fmt formats[] = {
 		.l.bpp		= 4,
 		.s.width	= 8,
 		.s.bpp		= 2,
-		.supported	= false,
 	}, {
 		.fourcc		= V4L2_PIX_FMT_SBGGR8,
 		.code		= MEDIA_BUS_FMT_SBGGR8_1X8,
@@ -133,7 +105,6 @@  static struct vpfe_fmt formats[] = {
 		.l.bpp		= 2,
 		.s.width	= 8,
 		.s.bpp		= 1,
-		.supported	= false,
 	}, {
 		.fourcc		= V4L2_PIX_FMT_SGBRG8,
 		.code		= MEDIA_BUS_FMT_SGBRG8_1X8,
@@ -141,7 +112,6 @@  static struct vpfe_fmt formats[] = {
 		.l.bpp		= 2,
 		.s.width	= 8,
 		.s.bpp		= 1,
-		.supported	= false,
 	}, {
 		.fourcc		= V4L2_PIX_FMT_SGRBG8,
 		.code		= MEDIA_BUS_FMT_SGRBG8_1X8,
@@ -149,7 +119,6 @@  static struct vpfe_fmt formats[] = {
 		.l.bpp		= 2,
 		.s.width	= 8,
 		.s.bpp		= 1,
-		.supported	= false,
 	}, {
 		.fourcc		= V4L2_PIX_FMT_SRGGB8,
 		.code		= MEDIA_BUS_FMT_SRGGB8_1X8,
@@ -157,7 +126,6 @@  static struct vpfe_fmt formats[] = {
 		.l.bpp		= 2,
 		.s.width	= 8,
 		.s.bpp		= 1,
-		.supported	= false,
 	}, {
 		.fourcc		= V4L2_PIX_FMT_RGB565,
 		.code		= MEDIA_BUS_FMT_RGB565_2X8_LE,
@@ -165,7 +133,6 @@  static struct vpfe_fmt formats[] = {
 		.l.bpp		= 4,
 		.s.width	= 8,
 		.s.bpp		= 2,
-		.supported	= false,
 	}, {
 		.fourcc		= V4L2_PIX_FMT_RGB565X,
 		.code		= MEDIA_BUS_FMT_RGB565_2X8_BE,
@@ -173,7 +140,6 @@  static struct vpfe_fmt formats[] = {
 		.l.bpp		= 4,
 		.s.width	= 8,
 		.s.bpp		= 2,
-		.supported	= false,
 	},
 };
 
@@ -181,13 +147,14 @@  static int
 __vpfe_get_format(struct vpfe_device *vpfe,
 		  struct v4l2_format *format, unsigned int *bpp);
 
-static struct vpfe_fmt *find_format_by_code(unsigned int code)
+static struct vpfe_fmt *find_format_by_code(struct vpfe_device *vpfe,
+					    unsigned int code)
 {
 	struct vpfe_fmt *fmt;
 	unsigned int k;
 
-	for (k = 0; k < ARRAY_SIZE(formats); k++) {
-		fmt = &formats[k];
+	for (k = 0; k < vpfe->num_active_fmt; k++) {
+		fmt = vpfe->active_fmt[k];
 		if (fmt->code == code)
 			return fmt;
 	}
@@ -195,13 +162,14 @@  static struct vpfe_fmt *find_format_by_code(unsigned int code)
 	return NULL;
 }
 
-static struct vpfe_fmt *find_format_by_pix(unsigned int pixelformat)
+static struct vpfe_fmt *find_format_by_pix(struct vpfe_device *vpfe,
+					   unsigned int pixelformat)
 {
 	struct vpfe_fmt *fmt;
 	unsigned int k;
 
-	for (k = 0; k < ARRAY_SIZE(formats); k++) {
-		fmt = &formats[k];
+	for (k = 0; k < vpfe->num_active_fmt; k++) {
+		fmt = vpfe->active_fmt[k];
 		if (fmt->fourcc == pixelformat)
 			return fmt;
 	}
@@ -218,7 +186,7 @@  mbus_to_pix(struct vpfe_device *vpfe,
 	unsigned int bus_width = sdinfo->vpfe_param.bus_width;
 	struct vpfe_fmt *fmt;
 
-	fmt = find_format_by_code(mbus->code);
+	fmt = find_format_by_code(vpfe, mbus->code);
 	if (WARN_ON(fmt == NULL)) {
 		pr_err("Invalid mbus code set\n");
 		*bpp = 1;
@@ -241,12 +209,12 @@  static void pix_to_mbus(struct vpfe_device *vpfe,
 {
 	struct vpfe_fmt *fmt;
 
-	fmt = find_format_by_pix(pix_fmt->pixelformat);
+	fmt = find_format_by_pix(vpfe, pix_fmt->pixelformat);
 	if (!fmt) {
 		/* default to first entry */
 		vpfe_dbg(3, vpfe, "Invalid pixel code: %x, default used instead\n",
 			pix_fmt->pixelformat);
-		fmt = &formats[0];
+		fmt = vpfe->active_fmt[0];
 	}
 
 	memset(mbus_fmt, 0, sizeof(*mbus_fmt));
@@ -1494,8 +1462,7 @@  static int vpfe_enum_fmt(struct file *file, void  *priv,
 {
 	struct vpfe_device *vpfe = video_drvdata(file);
 	struct vpfe_subdev_info *sdinfo;
-	struct vpfe_fmt *fmt = NULL;
-	unsigned int k;
+	struct vpfe_fmt *fmt;
 
 	vpfe_dbg(2, vpfe, "vpfe_enum_format index:%d\n",
 		f->index);
@@ -1504,17 +1471,10 @@  static int vpfe_enum_fmt(struct file *file, void  *priv,
 	if (!sdinfo->sd)
 		return -EINVAL;
 
-	if (f->index > ARRAY_SIZE(formats))
+	if (f->index >= vpfe->num_active_fmt)
 		return -EINVAL;
 
-	for (k = 0; k < ARRAY_SIZE(formats); k++) {
-		if (formats[k].index == f->index) {
-			fmt = &formats[k];
-			break;
-		}
-	}
-	if (!fmt)
-		return -EINVAL;
+	fmt = vpfe->active_fmt[f->index];
 
 	f->pixelformat = fmt->fourcc;
 
@@ -1593,7 +1553,7 @@  static int vpfe_enum_size(struct file *file, void  *priv,
 	vpfe_dbg(2, vpfe, "vpfe_enum_size\n");
 
 	/* check for valid format */
-	fmt = find_format_by_pix(fsize->pixel_format);
+	fmt = find_format_by_pix(vpfe, fsize->pixel_format);
 	if (!fmt) {
 		vpfe_dbg(3, vpfe, "Invalid pixel code: %x, default used instead\n",
 			fsize->pixel_format);
@@ -2281,8 +2241,10 @@  vpfe_async_bound(struct v4l2_async_notifier *notifier,
 					       struct vpfe_device, v4l2_dev);
 	struct v4l2_subdev_mbus_code_enum mbus_code;
 	struct vpfe_subdev_info *sdinfo;
+	struct vpfe_fmt *fmt;
+	int ret = 0;
 	bool found = false;
-	int i, j;
+	int i, j, k;
 
 	vpfe_dbg(1, vpfe, "vpfe_async_bound\n");
 
@@ -2304,27 +2266,37 @@  vpfe_async_bound(struct v4l2_async_notifier *notifier,
 
 	vpfe->video_dev.tvnorms |= sdinfo->inputs[0].std;
 
-	/* setup the supported formats & indexes */
-	for (j = 0, i = 0; ; ++j) {
-		struct vpfe_fmt *fmt;
-		int ret;
-
+	vpfe->num_active_fmt = 0;
+	for (j = 0, i = 0; (ret != -EINVAL); ++j) {
 		memset(&mbus_code, 0, sizeof(mbus_code));
 		mbus_code.index = j;
 		mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 		ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
-			       NULL, &mbus_code);
+				       NULL, &mbus_code);
 		if (ret)
-			break;
-
-		fmt = find_format_by_code(mbus_code.code);
-		if (!fmt)
 			continue;
 
-		fmt->supported = true;
-		fmt->index = i++;
+		vpfe_dbg(3, vpfe,
+			 "subdev %s: code: %04x idx: %d\n",
+			 subdev->name, mbus_code.code, j);
+
+		for (k = 0; k < ARRAY_SIZE(formats); k++) {
+			fmt = &formats[k];
+			if (mbus_code.code != fmt->code)
+				continue;
+			vpfe->active_fmt[i] = fmt;
+			vpfe_dbg(3, vpfe,
+				 "matched fourcc: %4.4s code: %04x idx: %d\n",
+				 (char *)&fmt->fourcc, mbus_code.code, i);
+			vpfe->num_active_fmt = ++i;
+		}
 	}
 
+	if (!i) {
+		vpfe_err(vpfe, "No suitable format reported by subdev %s\n",
+			 subdev->name);
+		return -EINVAL;
+	}
 	return 0;
 }
 
diff --git a/drivers/media/platform/am437x/am437x-vpfe.h b/drivers/media/platform/am437x/am437x-vpfe.h
index 2dde09780215..6f25750f84e4 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.h
+++ b/drivers/media/platform/am437x/am437x-vpfe.h
@@ -215,6 +215,37 @@  struct vpfe_ccdc {
 	u32 ccdc_ctx[VPFE_REG_END / sizeof(u32)];
 };
 
+/*
+ * struct bus_format - VPFE bus format information
+ * @width: Bits per pixel (when transferred over a bus)
+ * @bpp: Bytes per pixel (when stored in memory)
+ */
+struct bus_format {
+	unsigned int width;
+	unsigned int bpp;
+};
+
+/*
+ * struct vpfe_fmt - VPFE media bus format information
+ * @fourcc: V4L2 pixel format code
+ * @code: V4L2 media bus format code
+ * @l: 10 bit bus format info
+ * @s: 8 bit bus format info
+ */
+struct vpfe_fmt {
+	u32 fourcc;
+	u32 code;
+	struct bus_format l;
+	struct bus_format s;
+};
+
+/*
+ * This value needs to be at least as large as the number of entry in
+ * formats[].
+ * When formats[] is modified make sure to adjust this value also.
+ */
+#define VPFE_MAX_ACTIVE_FMT	10
+
 struct vpfe_device {
 	/* V4l2 specific parameters */
 	/* Identifies video device for this channel */
@@ -252,6 +283,9 @@  struct vpfe_device {
 	struct v4l2_format fmt;
 	/* Used to store current bytes per pixel based on current format */
 	unsigned int bpp;
+	struct vpfe_fmt	*active_fmt[VPFE_MAX_ACTIVE_FMT];
+	unsigned int num_active_fmt;
+
 	/*
 	 * used when IMP is chained to store the crop window which
 	 * is different from the image window