Re: [PATCH] media: i2c: add ov01a10 image sensor driver

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

 



Sakari,

Thanks for your review.

On 2/9/23 9:06 PM, Sakari Ailus wrote:
> Hi Bingbu,
> 
> Thanks for the patch.
> 
> On Thu, Feb 09, 2023 at 07:22:38PM +0800, Bingbu Cao wrote:
>> Add v4l2 device driver for OmniVision ov01a10 image sensor, ov01a10
>> image sensor can deliver 1280x800 resolution BGGR10 images at 60 fps.
>>
>> Signed-off-by: Bingbu Cao <bingbu.cao@xxxxxxxxx>
>> Signed-off-by: Yating Wang <yating.wang@xxxxxxxxx>
>> ---
>>  drivers/media/i2c/Kconfig   |  13 +
>>  drivers/media/i2c/Makefile  |   1 +
>>  drivers/media/i2c/ov01a10.c | 906 ++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 920 insertions(+)
>>  create mode 100644 drivers/media/i2c/ov01a10.c
>>
>> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
>> index 833241897d63..8e5d1ef0616f 100644
>> --- a/drivers/media/i2c/Kconfig
>> +++ b/drivers/media/i2c/Kconfig
>> @@ -338,6 +338,19 @@ config VIDEO_OG01A1B
>>  	  To compile this driver as a module, choose M here: the
>>  	  module will be called og01a1b.
>>  
>> +config VIDEO_OV01A10
>> +	tristate "OmniVision OV01A10 sensor support"
>> +	depends on VIDEO_DEV && I2C
>> +	select MEDIA_CONTROLLER
>> +	select VIDEO_V4L2_SUBDEV_API
>> +	select V4L2_FWNODE
>> +	help
>> +	  This is a Video4Linux2 sensor driver for the OmniVision
>> +	  OV01A10 camera.
>> +
>> +	  To compile this driver as a module, choose M here: the
>> +	  module will be called ov01a10.
>> +
>>  config VIDEO_OV02A10
>>  	tristate "OmniVision OV02A10 sensor support"
>>  	depends on VIDEO_DEV && I2C
>> diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
>> index 4d6c052bb5a7..ce214503b526 100644
>> --- a/drivers/media/i2c/Makefile
>> +++ b/drivers/media/i2c/Makefile
>> @@ -70,6 +70,7 @@ obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
>>  obj-$(CONFIG_VIDEO_MT9V111) += mt9v111.o
>>  obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
>>  obj-$(CONFIG_VIDEO_OG01A1B) += og01a1b.o
>> +obj-$(CONFIG_VIDEO_OV01A10) += ov01a10.o
>>  obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o
>>  obj-$(CONFIG_VIDEO_OV08D10) += ov08d10.o
>>  obj-$(CONFIG_VIDEO_OV08X40) += ov08x40.o
>> diff --git a/drivers/media/i2c/ov01a10.c b/drivers/media/i2c/ov01a10.c
>> new file mode 100644
>> index 000000000000..13de9f9ccdc8
>> --- /dev/null
>> +++ b/drivers/media/i2c/ov01a10.c
>> @@ -0,0 +1,906 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +// Copyright (c) 2020-2021 Intel Corporation.

..snip..

>> +static void ov01a10_update_pad_format(const struct ov01a10_mode *mode,
>> +				      struct v4l2_mbus_framefmt *fmt)
>> +{
>> +	fmt->width = mode->width;
>> +	fmt->height = mode->height;
>> +	fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
>> +	fmt->field = V4L2_FIELD_NONE;
>> +}
>> +
..snip..

>> +static int ov01a10_set_format(struct v4l2_subdev *sd,
>> +			      struct v4l2_subdev_state *sd_state,
>> +			      struct v4l2_subdev_format *fmt)
>> +{
>> +	struct ov01a10 *ov01a10 = to_ov01a10(sd);
>> +	const struct ov01a10_mode *mode;
>> +	s32 vblank_def, h_blank;
>> +
>> +	mode = v4l2_find_nearest_size(supported_modes,
>> +				      ARRAY_SIZE(supported_modes), width,
>> +				      height, fmt->format.width,
>> +				      fmt->format.height);
>> +
>> +	mutex_lock(&ov01a10->mutex);
>> +	ov01a10_update_pad_format(mode, &fmt->format);
> 
> Could you switch to the sub-device state? That is now the preferred way to
> serialise access to e.g. the format.
> 
> See e.g.
> <URL:https://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git/tree/drivers/media/i2c/ov1063x.c?h=streams/work-v16>.
> 
> The control handler's mutex doubles as a sub-device state mutex.

Is it fine to use v4l2_subdev_get_fmt()? Or will it be deprecated soon?

> 
>> +	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
>> +		*v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
>> +	} else {
>> +		ov01a10->cur_mode = mode;
>> +		__v4l2_ctrl_s_ctrl(ov01a10->link_freq, mode->link_freq_index);
>> +		__v4l2_ctrl_s_ctrl_int64(ov01a10->pixel_rate, OV01A10_SCLK);
>> +
>> +		vblank_def = mode->vts_def - mode->height;
>> +		__v4l2_ctrl_modify_range(ov01a10->vblank,
>> +					 mode->vts_min - mode->height,
>> +					 OV01A10_VTS_MAX - mode->height, 1,
>> +					 vblank_def);
>> +		__v4l2_ctrl_s_ctrl(ov01a10->vblank, vblank_def);
>> +		h_blank = mode->hts - mode->width;
>> +		__v4l2_ctrl_modify_range(ov01a10->hblank, h_blank, h_blank, 1,
>> +					 h_blank);
>> +	}
>> +	mutex_unlock(&ov01a10->mutex);
>> +
>> +	return 0;
>> +}
>> +
>> +static int ov01a10_get_format(struct v4l2_subdev *sd,
>> +			      struct v4l2_subdev_state *sd_state,
>> +			      struct v4l2_subdev_format *fmt)
>> +{
>> +	struct ov01a10 *ov01a10 = to_ov01a10(sd);
>> +
>> +	mutex_lock(&ov01a10->mutex);
>> +	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
>> +		fmt->format = *v4l2_subdev_get_try_format(&ov01a10->sd,
>> +							  sd_state, fmt->pad);
>> +	else
>> +		ov01a10_update_pad_format(ov01a10->cur_mode, &fmt->format);
>> +
>> +	mutex_unlock(&ov01a10->mutex);
>> +
>> +	return 0;
>> +}
>> +
>> +static int ov01a10_enum_mbus_code(struct v4l2_subdev *sd,
>> +				  struct v4l2_subdev_state *sd_state,
>> +				  struct v4l2_subdev_mbus_code_enum *code)
>> +{
>> +	if (code->index > 0)
>> +		return -EINVAL;
>> +
>> +	code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
>> +
>> +	return 0;
>> +}
>> +
>> +static int ov01a10_enum_frame_size(struct v4l2_subdev *sd,
>> +				   struct v4l2_subdev_state *sd_state,
>> +				   struct v4l2_subdev_frame_size_enum *fse)
>> +{
>> +	if (fse->index >= ARRAY_SIZE(supported_modes))
>> +		return -EINVAL;
>> +
>> +	if (fse->code != MEDIA_BUS_FMT_SBGGR10_1X10)
>> +		return -EINVAL;
>> +
>> +	fse->min_width = supported_modes[fse->index].width;
>> +	fse->max_width = fse->min_width;
>> +	fse->min_height = supported_modes[fse->index].height;
>> +	fse->max_height = fse->min_height;
>> +
>> +	return 0;
>> +}
>> +
>> +static int ov01a10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
>> +{
>> +	struct ov01a10 *ov01a10 = to_ov01a10(sd);
>> +
>> +	mutex_lock(&ov01a10->mutex);
>> +	ov01a10_update_pad_format(&supported_modes[0],
>> +				  v4l2_subdev_get_try_format(sd, fh->state, 0));
>> +	mutex_unlock(&ov01a10->mutex);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct v4l2_subdev_core_ops ov01a10_core_ops = {
>> +	.log_status = v4l2_ctrl_subdev_log_status,
>> +	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
>> +	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
>> +};
>> +
>> +static const struct v4l2_subdev_video_ops ov01a10_video_ops = {
>> +	.s_stream = ov01a10_set_stream,
>> +};
>> +
>> +static const struct v4l2_subdev_pad_ops ov01a10_pad_ops = {
>> +	.set_fmt = ov01a10_set_format,
>> +	.get_fmt = ov01a10_get_format,
>> +	.enum_mbus_code = ov01a10_enum_mbus_code,
>> +	.enum_frame_size = ov01a10_enum_frame_size,
>> +};
>> +

...

> 

-- 
Best regards,
Bingbu Cao



[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