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 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.

> -	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;

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

>  }
>  
>  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