Re: [PATCH v3 26/27] media: ov5640: Split DVP and CSI-2 formats

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Laurent

On Wed, Feb 23, 2022 at 02:17:30PM +0200, Laurent Pinchart wrote:
> Hi Jacopo,
>
> Thank you for the patch.
>
> On Wed, Feb 23, 2022 at 11:40:33AM +0100, Jacopo Mondi wrote:
> > The format enumeration list is shared between CSI-2 and DVP modes.
> > This lead to the enumeration of unsupported format variants in both
> > modes.
> >
> > Separate the list of DVP and CSI-2 formats and create helpers to access
> > the correct one.
> >
> > Signed-off-by: Jacopo Mondi <jacopo@xxxxxxxxxx>
> > ---
> >  drivers/media/i2c/ov5640.c | 125 +++++++++++++++++++++++++------------
> >  1 file changed, 86 insertions(+), 39 deletions(-)
> >
> > diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> > index a709e7f73364..f35006bcea3a 100644
> > --- a/drivers/media/i2c/ov5640.c
> > +++ b/drivers/media/i2c/ov5640.c
> > @@ -188,11 +188,13 @@ enum ov5640_format_mux {
> >  	OV5640_FMT_MUX_RAW_CIP,
> >  };
> >
> > -static const struct ov5640_pixfmt {
> > +struct ov5640_pixfmt {
> >  	u32 code;
> >  	u32 colorspace;
> >  	u8 bpp;
> > -} ov5640_formats[] = {
> > +};
> > +
> > +static const struct ov5640_pixfmt ov5640_dvp_formats[] = {
> >  	{
> >  		.code = MEDIA_BUS_FMT_JPEG_1X8,
> >  		.colorspace = V4L2_COLORSPACE_JPEG,
> > @@ -202,23 +204,48 @@ static const struct ov5640_pixfmt {
> >  		.colorspace = V4L2_COLORSPACE_SRGB,
> >  		.bpp = 16,
> >  	}, {
> > -		.code = MEDIA_BUS_FMT_UYVY8_1X16,
> > +		.code = MEDIA_BUS_FMT_YUYV8_2X8,
> >  		.colorspace = V4L2_COLORSPACE_SRGB,
> >  		.bpp = 16,
> >  	}, {
> > -		.code = MEDIA_BUS_FMT_YUYV8_2X8,
> > +		.code = MEDIA_BUS_FMT_RGB565_2X8_LE,
> >  		.colorspace = V4L2_COLORSPACE_SRGB,
> >  		.bpp = 16,
> >  	}, {
> > -		.code = MEDIA_BUS_FMT_YUYV8_1X16,
> > +		.code = MEDIA_BUS_FMT_RGB565_2X8_BE,
> >  		.colorspace = V4L2_COLORSPACE_SRGB,
> >  		.bpp = 16,
> >  	}, {
> > -		.code = MEDIA_BUS_FMT_RGB565_2X8_LE,
> > +		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
> >  		.colorspace = V4L2_COLORSPACE_SRGB,
> > +		.bpp = 8,
> > +	}, {
> > +		.code = MEDIA_BUS_FMT_SGBRG8_1X8,
> > +		.colorspace = V4L2_COLORSPACE_SRGB,
> > +		.bpp = 8
> > +	}, {
> > +		.code = MEDIA_BUS_FMT_SGRBG8_1X8,
> > +		.colorspace = V4L2_COLORSPACE_SRGB,
> > +		.bpp = 8,
> > +	}, {
> > +		.code = MEDIA_BUS_FMT_SRGGB8_1X8,
> > +		.colorspace = V4L2_COLORSPACE_SRGB,
> > +		.bpp = 8,
> > +	},
> > +	{ /* sentinel */ }
> > +};
> > +
> > +static const struct ov5640_pixfmt ov5640_csi2_formats[] = {
> > +	{
> > +		.code = MEDIA_BUS_FMT_JPEG_1X8,
> > +		.colorspace = V4L2_COLORSPACE_JPEG,
> >  		.bpp = 16,
> >  	}, {
> > -		.code = MEDIA_BUS_FMT_RGB565_2X8_BE,
> > +		.code = MEDIA_BUS_FMT_UYVY8_1X16,
> > +		.colorspace = V4L2_COLORSPACE_SRGB,
> > +		.bpp = 16,
> > +	}, {
> > +		.code = MEDIA_BUS_FMT_YUYV8_1X16,
> >  		.colorspace = V4L2_COLORSPACE_SRGB,
> >  		.bpp = 16,
> >  	}, {
> > @@ -246,20 +273,9 @@ static const struct ov5640_pixfmt {
> >  		.colorspace = V4L2_COLORSPACE_SRGB,
> >  		.bpp = 8,
> >  	},
> > +	{ /* sentinel */ }
> >  };
> >
> > -static u32 ov5640_code_to_bpp(u32 code)
> > -{
> > -	unsigned int i;
> > -
> > -	for (i = 0; i < ARRAY_SIZE(ov5640_formats); ++i) {
> > -		if (ov5640_formats[i].code == code)
> > -			return ov5640_formats[i].bpp;
> > -	}
> > -
> > -	return 0;
> > -}
> > -
> >  /*
> >   * FIXME: remove this when a subdev API becomes available
> >   * to set the MIPI CSI-2 virtual channel.
> > @@ -408,6 +424,33 @@ static inline bool ov5640_is_csi2(const struct ov5640_dev *sensor)
> >  	return sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY;
> >  }
> >
> > +static inline const struct ov5640_pixfmt *ov5640_formats(struct ov5640_dev *sensor)
> > +{
> > +	return ov5640_is_csi2(sensor) ? ov5640_csi2_formats : ov5640_dvp_formats;
> > +}
> > +
> > +static const struct ov5640_pixfmt *ov5640_code_to_pixfmt(struct ov5640_dev *sensor,
> > +							 u32 code)
> > +{
> > +	const struct ov5640_pixfmt *formats = ov5640_formats(sensor);
> > +	unsigned int i = 0;
> > +
> > +	while (formats[i].code) {
>
> 	for (i = 0; formats[i].code; ++i) {
>
> > +		if (formats[i].code == code)
> > +			return &formats[i];
> > +		++i;
>
> and drop this one.
>
> > +	}
> > +
> > +	return &formats[0];
> > +}
> > +
> > +static u32 ov5640_code_to_bpp(struct ov5640_dev *sensor, u32 code)
> > +{
> > +	const struct ov5640_pixfmt *format = ov5640_code_to_pixfmt(sensor, code);
> > +
> > +	return format->bpp;
> > +}
> > +
> >  /*
> >   * FIXME: all of these register tables are likely filled with
> >   * entries that set the register to their power-on default values,
> > @@ -1391,7 +1434,7 @@ static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor)
> >  	 * (0x01=0.5ns).
> >  	 */
> >  	sample_rate = ov5640_pixel_rates[sensor->current_mode->pixel_rate]
> > -		    * (ov5640_code_to_bpp(fmt->code) / 8);
> > +		    * (ov5640_code_to_bpp(sensor, fmt->code) / 8);
> >  	pclk_period = 2000000000U / sample_rate;
> >
> >  	/* Program the clock tree registers. */
> > @@ -1456,7 +1499,7 @@ static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor)
> >  	int ret;
> >
> >  	rate = ov5640_calc_pixel_rate(sensor);
> > -	rate *= ov5640_code_to_bpp(sensor->fmt.code);
> > +	rate *= ov5640_code_to_bpp(sensor, sensor->fmt.code);
> >  	rate /= sensor->ep.bus.parallel.bus_width;
> >
> >  	ov5640_calc_pclk(sensor, rate, &prediv, &mult, &sysdiv, &pll_rdiv,
> > @@ -2690,15 +2733,18 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
> >  				   enum ov5640_frame_rate fr,
> >  				   const struct ov5640_mode_info **new_mode)
> >  {
> > -	unsigned int bpp = ov5640_code_to_bpp(fmt->code);
> >  	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> >  	const struct ov5640_mode_info *mode;
> > -	int i;
> > +	const struct ov5640_pixfmt *pixfmt;
> > +	unsigned int bpp;
> >
> >  	mode = ov5640_find_mode(sensor, fr, fmt->width, fmt->height, true);
> >  	if (!mode)
> >  		return -EINVAL;
> >
> > +	pixfmt = ov5640_code_to_pixfmt(sensor, fmt->code);
> > +	bpp = pixfmt->bpp;
> > +
> >  	/*
> >  	 * Adjust mode according to bpp:
> >  	 * - 8bpp modes work for resolution >= 1280x720
> > @@ -2715,14 +2761,8 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
> >  	if (new_mode)
> >  		*new_mode = mode;
> >
> > -	for (i = 0; i < ARRAY_SIZE(ov5640_formats); i++)
> > -		if (ov5640_formats[i].code == fmt->code)
> > -			break;
> > -	if (i >= ARRAY_SIZE(ov5640_formats))
> > -		i = 0;
> > -
> > -	fmt->code = ov5640_formats[i].code;
> > -	fmt->colorspace = ov5640_formats[i].colorspace;
> > +	fmt->code = pixfmt->code;
> > +	fmt->colorspace = pixfmt->colorspace;
> >  	fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
> >  	fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
> >  	fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
> > @@ -2764,7 +2804,7 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor)
> >  	 * progressively slow it down if it exceeds 1GHz.
> >  	 */
> >  	num_lanes = sensor->ep.bus.mipi_csi2.num_data_lanes;
> > -	bpp = ov5640_code_to_bpp(fmt->code);
> > +	bpp = ov5640_code_to_bpp(sensor, fmt->code);
> >  	do {
> >  		pixel_rate = ov5640_pixel_rates[pixel_rate_id];
> >  		link_freq = pixel_rate * bpp / (2 * num_lanes);
> > @@ -3462,7 +3502,8 @@ static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
> >  				  struct v4l2_subdev_state *sd_state,
> >  				  struct v4l2_subdev_frame_size_enum *fse)
> >  {
> > -	u32 bpp = ov5640_code_to_bpp(fse->code);
> > +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> > +	u32 bpp = ov5640_code_to_bpp(sensor, fse->code);
> >  	unsigned int index = fse->index;
> >
> >  	if (fse->pad != 0)
> > @@ -3589,13 +3630,19 @@ static int ov5640_enum_mbus_code(struct v4l2_subdev *sd,
> >  				 struct v4l2_subdev_state *sd_state,
> >  				 struct v4l2_subdev_mbus_code_enum *code)
> >  {
> > -	if (code->pad != 0)
> > -		return -EINVAL;
>
> You've lost this check.
>

The driver has a single pad, doesn't core verify that the pad argument
is valid ?

> > -	if (code->index >= ARRAY_SIZE(ov5640_formats))
> > -		return -EINVAL;
> > +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> > +	const struct ov5640_pixfmt *formats = ov5640_formats(sensor);
> > +	unsigned int i = 0;
> >
> > -	code->code = ov5640_formats[code->index].code;
> > -	return 0;
> > +	while (formats[i].code) {
> > +		if (i == code->index) {
> > +			code->code = formats[i].code;
> > +			return 0;
> > +		}
> > +		++i;
> > +	}
> > +
> > +	return -EINVAL;
>
> That's quite inefficient.
>
> 	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> 	const struct ov5640_pixfmt *formats;
> 	unsigned int num_formats;
>
> 	if (ov5640_is_csi2(sensor)) {
> 		formats = ov5640_csi2_formats;
> 		num_formats = ARRAY_SIZE(ov5640_csi2_formats) - 1;
> 	} else {
> 		formats = ov5640_dvp_formats;
> 		num_formats = ARRAY_SIZE(ov5640_dvp_formats) - 1;
> 	}
>
> 	if (code->pad != 0 || code->index >= num_formats)
> 		return -EINVAL;
>
> 	code->code = formats[code->index].code;
> 	return 0;

ack

>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>

Thanks

>
> >  }
> >
> >  static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
>
> --
> Regards,
>
> Laurent Pinchart



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux