mbox series

[00/16] Updates to ov9282 sensor driver

Message ID 20221005152809.3785786-1-dave.stevenson@raspberrypi.com
Headers show
Series Updates to ov9282 sensor driver | expand

Message

Dave Stevenson Oct. 5, 2022, 3:27 p.m. UTC
This series adds to the functionality of the Ominvision
OV9282 driver to make it usable with libcamera.

Tested on a Raspberry Pi with OV9281 sensor (same as
OV9282 but with alternate CRA on the optics)

Dave Stevenson (16):
  media: i2c: ov9282: Remove duplication of registers
  media: i2c: ov9282: Split registers into common and mode specific
  media: i2c: ov9282: Remove format code from the mode
  media: i2c: ov9282: Remove pixel rate from mode definition
  media: i2c: ov9281: Support more than 1 mode.
  media: i2c: ov9282: Correct HTS register for configured pixel rate
  media: i2c: ov9282: Reduce vblank_min values based on testing
  media: i2c: ov9282: Add selection for CSI2 clock mode
  media: i2c: ov9282: Add the properties from fwnode
  media: i2c: ov9282: Action CID_VBLANK when set.
  media: i2c: ov9282: Add HFLIP and VFLIP support
  media: i2c: ov9282: Make V4L2_CID_HBLANK r/w
  media: i2c: ov9282: Add selection API calls for cropping info
  media: i2c: ov9282: Add support for 1280x800 and 640x400 modes
  media: i2c: ov9282: Add support for 8bit readout
  media: i2c: ov9282: Support event handlers

 drivers/media/i2c/ov9282.c | 552 ++++++++++++++++++++++++++++++-------
 1 file changed, 446 insertions(+), 106 deletions(-)

Comments

Sakari Ailus Oct. 26, 2022, 7:21 a.m. UTC | #1
Hi Dave,

On Wed, Oct 05, 2022 at 04:28:01PM +0100, Dave Stevenson wrote:
> The sensor supports either having the CSI2 clock lane free
> running, or gated when there is no packet to transmit.
> The driver only selected gated (non-continuous) clock mode.
> 
> Add code to allow fwnode to configure whether the clock is
> gated or free running.
> 
> Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
> ---
>  drivers/media/i2c/ov9282.c | 16 +++++++++++++++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c
> index abb1223c0260..334b31af34a4 100644
> --- a/drivers/media/i2c/ov9282.c
> +++ b/drivers/media/i2c/ov9282.c
> @@ -46,6 +46,9 @@
>  /* Group hold register */
>  #define OV9282_REG_HOLD		0x3308
>  
> +#define OV9282_REG_MIPI_CTRL00	0x4800
> +#define OV9282_GATED_CLOCK	BIT(5)
> +
>  /* Input clock rate */
>  #define OV9282_INCLK_RATE	24000000
>  
> @@ -138,6 +141,7 @@ struct ov9282 {
>  	struct clk *inclk;
>  	struct regulator_bulk_data supplies[OV9282_NUM_SUPPLIES];
>  	struct v4l2_ctrl_handler ctrl_handler;
> +	bool noncontinuous_clock;
>  	struct v4l2_ctrl *link_freq_ctrl;
>  	struct v4l2_ctrl *hblank_ctrl;
>  	struct v4l2_ctrl *vblank_ctrl;
> @@ -211,7 +215,6 @@ static const struct ov9282_reg common_regs[] = {
>  	{0x4601, 0x04},
>  	{0x470f, 0x00},
>  	{0x4f07, 0x00},
> -	{0x4800, 0x20},
>  	{0x5000, 0x9f},
>  	{0x5001, 0x00},
>  	{0x5e00, 0x00},
> @@ -684,6 +687,14 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
>  		return ret;
>  	}
>  
> +	ret = ov9282_write_reg(ov9282, OV9282_REG_MIPI_CTRL00, 1,
> +			       ov9282->noncontinuous_clock ?
> +					OV9282_GATED_CLOCK : 0);

Wouldn't this better fit for power on?

> +	if (ret) {
> +		dev_err(ov9282->dev, "fail to write MIPI_CTRL00");
> +		return ret;
> +	}
> +
>  	/* Write sensor mode registers */
>  	reg_list = &ov9282->cur_mode->reg_list;
>  	ret = ov9282_write_regs(ov9282, reg_list->regs, reg_list->num_of_regs);
> @@ -861,6 +872,9 @@ static int ov9282_parse_hw_config(struct ov9282 *ov9282)
>  	if (ret)
>  		return ret;
>  
> +	ov9282->noncontinuous_clock =
> +		bus_cfg.bus.mipi_csi2.flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
> +
>  	if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV9282_NUM_DATA_LANES) {
>  		dev_err(ov9282->dev,
>  			"number of CSI2 data lanes %d is not supported",
Sakari Ailus Oct. 26, 2022, 7:22 a.m. UTC | #2
Hi Dave,

On Wed, Oct 05, 2022 at 04:27:58PM +0100, Dave Stevenson wrote:
> The driver currently has multiple assumptions that there is
> only one supported mode.
> 
> Convert supported_mode to an array, and fix up all references
> to correctly look at that array.
> 
> Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
> ---
>  drivers/media/i2c/ov9282.c | 44 ++++++++++++++++++++++----------------
>  1 file changed, 26 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c
> index 798ff8ba50bd..f7823d584522 100644
> --- a/drivers/media/i2c/ov9282.c
> +++ b/drivers/media/i2c/ov9282.c
> @@ -262,20 +262,24 @@ static const struct ov9282_reg mode_1280x720_regs[] = {
>  };
>  
>  /* Supported sensor mode configurations */
> -static const struct ov9282_mode supported_mode = {
> -	.width = 1280,
> -	.height = 720,
> -	.hblank = 250,
> -	.vblank = 1022,
> -	.vblank_min = 151,
> -	.vblank_max = 51540,
> -	.link_freq_idx = 0,
> -	.reg_list = {
> -		.num_of_regs = ARRAY_SIZE(mode_1280x720_regs),
> -		.regs = mode_1280x720_regs,
> +static const struct ov9282_mode supported_modes[] = {
> +	{
> +		.width = 1280,
> +		.height = 720,
> +		.hblank = 250,
> +		.vblank = 1022,
> +		.vblank_min = 151,
> +		.vblank_max = 51540,
> +		.link_freq_idx = 0,
> +		.reg_list = {
> +			.num_of_regs = ARRAY_SIZE(mode_1280x720_regs),
> +			.regs = mode_1280x720_regs,
> +		},
>  	},
>  };
>  
> +#define OV9282_NUM_MODES ARRAY_SIZE(supported_modes)

I think the code would be cleaner without the additional macro, i.e. always
using ARRAY_SIZE(supported_modes).

> +
>  /**
>   * to_ov9282() - ov9282 V4L2 sub-device to ov9282 device.
>   * @subdev: pointer to ov9282 V4L2 sub-device
> @@ -536,15 +540,15 @@ static int ov9282_enum_frame_size(struct v4l2_subdev *sd,
>  				  struct v4l2_subdev_state *sd_state,
>  				  struct v4l2_subdev_frame_size_enum *fsize)
>  {
> -	if (fsize->index > 0)
> +	if (fsize->index >= OV9282_NUM_MODES)
>  		return -EINVAL;
>  
>  	if (fsize->code != MEDIA_BUS_FMT_Y10_1X10)
>  		return -EINVAL;
>  
> -	fsize->min_width = supported_mode.width;
> +	fsize->min_width = supported_modes[fsize->index].width;
>  	fsize->max_width = fsize->min_width;
> -	fsize->min_height = supported_mode.height;
> +	fsize->min_height = supported_modes[fsize->index].height;
>  	fsize->max_height = fsize->min_height;
>  
>  	return 0;
> @@ -619,7 +623,11 @@ static int ov9282_set_pad_format(struct v4l2_subdev *sd,
>  
>  	mutex_lock(&ov9282->mutex);
>  
> -	mode = &supported_mode;
> +	mode = v4l2_find_nearest_size(supported_modes,
> +				      OV9282_NUM_MODES,
> +				      width, height,
> +				      fmt->format.width,
> +				      fmt->format.height);
>  	ov9282_fill_pad_format(ov9282, mode, fmt);
>  
>  	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> @@ -652,7 +660,7 @@ static int ov9282_init_pad_cfg(struct v4l2_subdev *sd,
>  	struct v4l2_subdev_format fmt = { 0 };
>  
>  	fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
> -	ov9282_fill_pad_format(ov9282, &supported_mode, &fmt);
> +	ov9282_fill_pad_format(ov9282, &supported_modes[0], &fmt);
>  
>  	return ov9282_set_pad_format(sd, sd_state, &fmt);
>  }
> @@ -1081,8 +1089,8 @@ static int ov9282_probe(struct i2c_client *client)
>  		goto error_power_off;
>  	}
>  
> -	/* Set default mode to max resolution */
> -	ov9282->cur_mode = &supported_mode;
> +	/* Set default mode to first mode */
> +	ov9282->cur_mode = &supported_modes[0];
>  	ov9282->vblank = ov9282->cur_mode->vblank;
>  
>  	ret = ov9282_init_controls(ov9282);
Dave Stevenson Oct. 28, 2022, 12:57 p.m. UTC | #3
Hi Sakari

On Wed, 26 Oct 2022 at 08:21, Sakari Ailus <sakari.ailus@iki.fi> wrote:
>
> Hi Dave,
>
> On Wed, Oct 05, 2022 at 04:28:01PM +0100, Dave Stevenson wrote:
> > The sensor supports either having the CSI2 clock lane free
> > running, or gated when there is no packet to transmit.
> > The driver only selected gated (non-continuous) clock mode.
> >
> > Add code to allow fwnode to configure whether the clock is
> > gated or free running.
> >
> > Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
> > ---
> >  drivers/media/i2c/ov9282.c | 16 +++++++++++++++-
> >  1 file changed, 15 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c
> > index abb1223c0260..334b31af34a4 100644
> > --- a/drivers/media/i2c/ov9282.c
> > +++ b/drivers/media/i2c/ov9282.c
> > @@ -46,6 +46,9 @@
> >  /* Group hold register */
> >  #define OV9282_REG_HOLD              0x3308
> >
> > +#define OV9282_REG_MIPI_CTRL00       0x4800
> > +#define OV9282_GATED_CLOCK   BIT(5)
> > +
> >  /* Input clock rate */
> >  #define OV9282_INCLK_RATE    24000000
> >
> > @@ -138,6 +141,7 @@ struct ov9282 {
> >       struct clk *inclk;
> >       struct regulator_bulk_data supplies[OV9282_NUM_SUPPLIES];
> >       struct v4l2_ctrl_handler ctrl_handler;
> > +     bool noncontinuous_clock;
> >       struct v4l2_ctrl *link_freq_ctrl;
> >       struct v4l2_ctrl *hblank_ctrl;
> >       struct v4l2_ctrl *vblank_ctrl;
> > @@ -211,7 +215,6 @@ static const struct ov9282_reg common_regs[] = {
> >       {0x4601, 0x04},
> >       {0x470f, 0x00},
> >       {0x4f07, 0x00},
> > -     {0x4800, 0x20},
> >       {0x5000, 0x9f},
> >       {0x5001, 0x00},
> >       {0x5e00, 0x00},
> > @@ -684,6 +687,14 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
> >               return ret;
> >       }
> >
> > +     ret = ov9282_write_reg(ov9282, OV9282_REG_MIPI_CTRL00, 1,
> > +                            ov9282->noncontinuous_clock ?
> > +                                     OV9282_GATED_CLOCK : 0);
>
> Wouldn't this better fit for power on?

It can be done in ov9282_power_on, but is then totally redundantly set
when powering the sensor up to read the ID during initial probe.
Doing so also means there needs to be a great big warning never to
change the driver and hit the software reset via writing 0x01 to
register 0x0103 as part of any register array (very common in many
other sensor drivers).

I'll move it and add a comment before the register tables.

  Dave

> > +     if (ret) {
> > +             dev_err(ov9282->dev, "fail to write MIPI_CTRL00");
> > +             return ret;
> > +     }
> > +
> >       /* Write sensor mode registers */
> >       reg_list = &ov9282->cur_mode->reg_list;
> >       ret = ov9282_write_regs(ov9282, reg_list->regs, reg_list->num_of_regs);
> > @@ -861,6 +872,9 @@ static int ov9282_parse_hw_config(struct ov9282 *ov9282)
> >       if (ret)
> >               return ret;
> >
> > +     ov9282->noncontinuous_clock =
> > +             bus_cfg.bus.mipi_csi2.flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
> > +
> >       if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV9282_NUM_DATA_LANES) {
> >               dev_err(ov9282->dev,
> >                       "number of CSI2 data lanes %d is not supported",
>
> --
> Kind regards,
>
> Sakari Ailus
Sakari Ailus Oct. 28, 2022, 2:30 p.m. UTC | #4
Hi Dave,

On Fri, Oct 28, 2022 at 01:57:48PM +0100, Dave Stevenson wrote:
> Hi Sakari
> 
> On Wed, 26 Oct 2022 at 08:21, Sakari Ailus <sakari.ailus@iki.fi> wrote:
> >
> > Hi Dave,
> >
> > On Wed, Oct 05, 2022 at 04:28:01PM +0100, Dave Stevenson wrote:
> > > The sensor supports either having the CSI2 clock lane free
> > > running, or gated when there is no packet to transmit.
> > > The driver only selected gated (non-continuous) clock mode.
> > >
> > > Add code to allow fwnode to configure whether the clock is
> > > gated or free running.
> > >
> > > Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
> > > ---
> > >  drivers/media/i2c/ov9282.c | 16 +++++++++++++++-
> > >  1 file changed, 15 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c
> > > index abb1223c0260..334b31af34a4 100644
> > > --- a/drivers/media/i2c/ov9282.c
> > > +++ b/drivers/media/i2c/ov9282.c
> > > @@ -46,6 +46,9 @@
> > >  /* Group hold register */
> > >  #define OV9282_REG_HOLD              0x3308
> > >
> > > +#define OV9282_REG_MIPI_CTRL00       0x4800
> > > +#define OV9282_GATED_CLOCK   BIT(5)
> > > +
> > >  /* Input clock rate */
> > >  #define OV9282_INCLK_RATE    24000000
> > >
> > > @@ -138,6 +141,7 @@ struct ov9282 {
> > >       struct clk *inclk;
> > >       struct regulator_bulk_data supplies[OV9282_NUM_SUPPLIES];
> > >       struct v4l2_ctrl_handler ctrl_handler;
> > > +     bool noncontinuous_clock;
> > >       struct v4l2_ctrl *link_freq_ctrl;
> > >       struct v4l2_ctrl *hblank_ctrl;
> > >       struct v4l2_ctrl *vblank_ctrl;
> > > @@ -211,7 +215,6 @@ static const struct ov9282_reg common_regs[] = {
> > >       {0x4601, 0x04},
> > >       {0x470f, 0x00},
> > >       {0x4f07, 0x00},
> > > -     {0x4800, 0x20},
> > >       {0x5000, 0x9f},
> > >       {0x5001, 0x00},
> > >       {0x5e00, 0x00},
> > > @@ -684,6 +687,14 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
> > >               return ret;
> > >       }
> > >
> > > +     ret = ov9282_write_reg(ov9282, OV9282_REG_MIPI_CTRL00, 1,
> > > +                            ov9282->noncontinuous_clock ?
> > > +                                     OV9282_GATED_CLOCK : 0);
> >
> > Wouldn't this better fit for power on?
> 
> It can be done in ov9282_power_on, but is then totally redundantly set
> when powering the sensor up to read the ID during initial probe.

This is the same also when streaming is enabled and disabled multiple times
while the sensor is powered on. Although without autosuspend this may be
unlikely.

> Doing so also means there needs to be a great big warning never to
> change the driver and hit the software reset via writing 0x01 to
> register 0x0103 as part of any register array (very common in many
> other sensor drivers).

If there's a desire to reset the sensor after powering it up, that should
be done as the first thing after power-up. Setting non-continuous clock
isn't anything special here.

But that's up to you. I guess lane configuration etc. is part of the big
register lists.

> 
> I'll move it and add a comment before the register tables.

I think it's unnecessary.
Dave Stevenson Oct. 28, 2022, 3:03 p.m. UTC | #5
Hi Sakari

On Fri, 28 Oct 2022 at 15:30, Sakari Ailus <sakari.ailus@iki.fi> wrote:
>
> Hi Dave,
>
> On Fri, Oct 28, 2022 at 01:57:48PM +0100, Dave Stevenson wrote:
> > Hi Sakari
> >
> > On Wed, 26 Oct 2022 at 08:21, Sakari Ailus <sakari.ailus@iki.fi> wrote:
> > >
> > > Hi Dave,
> > >
> > > On Wed, Oct 05, 2022 at 04:28:01PM +0100, Dave Stevenson wrote:
> > > > The sensor supports either having the CSI2 clock lane free
> > > > running, or gated when there is no packet to transmit.
> > > > The driver only selected gated (non-continuous) clock mode.
> > > >
> > > > Add code to allow fwnode to configure whether the clock is
> > > > gated or free running.
> > > >
> > > > Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
> > > > ---
> > > >  drivers/media/i2c/ov9282.c | 16 +++++++++++++++-
> > > >  1 file changed, 15 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c
> > > > index abb1223c0260..334b31af34a4 100644
> > > > --- a/drivers/media/i2c/ov9282.c
> > > > +++ b/drivers/media/i2c/ov9282.c
> > > > @@ -46,6 +46,9 @@
> > > >  /* Group hold register */
> > > >  #define OV9282_REG_HOLD              0x3308
> > > >
> > > > +#define OV9282_REG_MIPI_CTRL00       0x4800
> > > > +#define OV9282_GATED_CLOCK   BIT(5)
> > > > +
> > > >  /* Input clock rate */
> > > >  #define OV9282_INCLK_RATE    24000000
> > > >
> > > > @@ -138,6 +141,7 @@ struct ov9282 {
> > > >       struct clk *inclk;
> > > >       struct regulator_bulk_data supplies[OV9282_NUM_SUPPLIES];
> > > >       struct v4l2_ctrl_handler ctrl_handler;
> > > > +     bool noncontinuous_clock;
> > > >       struct v4l2_ctrl *link_freq_ctrl;
> > > >       struct v4l2_ctrl *hblank_ctrl;
> > > >       struct v4l2_ctrl *vblank_ctrl;
> > > > @@ -211,7 +215,6 @@ static const struct ov9282_reg common_regs[] = {
> > > >       {0x4601, 0x04},
> > > >       {0x470f, 0x00},
> > > >       {0x4f07, 0x00},
> > > > -     {0x4800, 0x20},
> > > >       {0x5000, 0x9f},
> > > >       {0x5001, 0x00},
> > > >       {0x5e00, 0x00},
> > > > @@ -684,6 +687,14 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
> > > >               return ret;
> > > >       }
> > > >
> > > > +     ret = ov9282_write_reg(ov9282, OV9282_REG_MIPI_CTRL00, 1,
> > > > +                            ov9282->noncontinuous_clock ?
> > > > +                                     OV9282_GATED_CLOCK : 0);
> > >
> > > Wouldn't this better fit for power on?
> >
> > It can be done in ov9282_power_on, but is then totally redundantly set
> > when powering the sensor up to read the ID during initial probe.
>
> This is the same also when streaming is enabled and disabled multiple times
> while the sensor is powered on. Although without autosuspend this may be
> unlikely.
>
> > Doing so also means there needs to be a great big warning never to
> > change the driver and hit the software reset via writing 0x01 to
> > register 0x0103 as part of any register array (very common in many
> > other sensor drivers).
>
> If there's a desire to reset the sensor after powering it up, that should
> be done as the first thing after power-up. Setting non-continuous clock
> isn't anything special here.

I'm only looking at existing drivers in mainline as there is no clear
documentation on do's and don't's within sensor drivers (I know
writing good documentation is hard).
ov7251 [1] reset in ov7251_global_init_setting
ov8856 [2] reset in the lane config tables
ov5695 [3] reset in ov5695_global_regs
ov2740 [4] reset in mipi_data_rate_720mbps
ov13858 [5] explicit reset in ov13858_start_streaming
ov13b10 [6] explicit reset in ov13b10_start_streaming

In my book that's a common enough pattern in mainline drivers for it
to be worth warning against introducing it when it will cause quirky
behaviour.

[1] https://github.com/torvalds/linux/blob/master/drivers/media/i2c/ov7251.c#L238
[2] https://github.com/torvalds/linux/blob/master/drivers/media/i2c/ov8856.c#L167
[3] https://github.com/torvalds/linux/blob/master/drivers/media/i2c/ov5695.c#L128
[4] https://github.com/torvalds/linux/blob/master/drivers/media/i2c/ov2740.c#L127
[5] https://github.com/torvalds/linux/blob/master/drivers/media/i2c/ov13858.c#L1421
[6] https://github.com/torvalds/linux/blob/master/drivers/media/i2c/ov13b10.c#L1033

> But that's up to you. I guess lane configuration etc. is part of the big
> register lists.

Only 2 data lanes are currently supported by the driver.
Bit 5 of 0x3039 in theory allows you to drop to 1 lane, but I've not
got it to work. I suspect further clock tree changes are required.

A 400MHz link freq (800Mbit/s/lane) is already required for the max
1280x800@120fps.
Dropping to 1 lane therefore either requires reducing the max frame
rate, or potentially running at 800MHz link freq, which is well in
excess of the earlier versions of CSI-2 spec (500MHz or 1Gbit/s). IMHO
It's not worth pursuing.

  Dave

> >
> > I'll move it and add a comment before the register tables.
>
> I think it's unnecessary.
>
> --
> Kind regards,
>
> Sakari Ailus