[libcamera-devel,2/5] libcamera: camera_sensor: Initialize controls
diff mbox series

Message ID 20201223184516.58791-3-jacopo@jmondi.org
State Superseded
Delegated to: Jacopo Mondi
Headers show
Series
  • libcamera: Register CameraSensor controls
Related show

Commit Message

Jacopo Mondi Dec. 23, 2020, 6:45 p.m. UTC
Initialize the ControlInfoMap of sensor available controls by
reporting the sensor exposure time range.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 include/libcamera/internal/camera_sensor.h |  2 ++
 src/libcamera/camera_sensor.cpp            | 42 +++++++++++++++++++++-
 2 files changed, 43 insertions(+), 1 deletion(-)

Comments

Paul Elder Dec. 28, 2020, 8:26 a.m. UTC | #1
Hi Jacopo,

On Wed, Dec 23, 2020 at 07:45:13PM +0100, Jacopo Mondi wrote:
> Initialize the ControlInfoMap of sensor available controls by
> reporting the sensor exposure time range.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  include/libcamera/internal/camera_sensor.h |  2 ++
>  src/libcamera/camera_sensor.cpp            | 42 +++++++++++++++++++++-
>  2 files changed, 43 insertions(+), 1 deletion(-)
> 
> diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> index aee10aa6e3c7..0357b2a630f7 100644
> --- a/include/libcamera/internal/camera_sensor.h
> +++ b/include/libcamera/internal/camera_sensor.h
> @@ -71,6 +71,7 @@ private:
>  	int generateId();
>  	int validateSensorDriver();
>  	int initProperties();
> +	int initControls();
>  
>  	const MediaEntity *entity_;
>  	std::unique_ptr<V4L2Subdevice> subdev_;
> @@ -85,6 +86,7 @@ private:
>  	std::vector<Size> sizes_;
>  
>  	ControlList properties_;
> +	ControlInfoMap controls_;
>  };
>  
>  } /* namespace libcamera */
> diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> index 3a65ac3de5bc..609f948c56a6 100644
> --- a/src/libcamera/camera_sensor.cpp
> +++ b/src/libcamera/camera_sensor.cpp
> @@ -15,6 +15,7 @@
>  #include <regex>
>  #include <string.h>
>  
> +#include <libcamera/control_ids.h>
>  #include <libcamera/property_ids.h>
>  
>  #include "libcamera/internal/bayer_format.h"
> @@ -215,7 +216,7 @@ int CameraSensor::init()
>  	if (ret)
>  		return ret;
>  
> -	return 0;
> +	return initControls();
>  }
>  
>  int CameraSensor::validateSensorDriver()
> @@ -229,6 +230,7 @@ int CameraSensor::validateSensorDriver()
>  	const std::vector<uint32_t> mandatoryControls{
>  		V4L2_CID_PIXEL_RATE,
>  		V4L2_CID_HBLANK,
> +		V4L2_CID_EXPOSURE,
>  	};
>  
>  	ControlList ctrls = subdev_->getControls(mandatoryControls);
> @@ -430,6 +432,44 @@ int CameraSensor::initProperties()
>  	return 0;
>  }
>  
> +int CameraSensor::initControls()
> +{
> +	const ControlInfoMap &v4l2Controls = subdev_->controls();
> +
> +	/* Exposure time limits expressed in micro-seconds. */
> +
> +	/* Calculate the line length in pixels. */
> +	ControlList ctrls = subdev_->getControls({ V4L2_CID_HBLANK });

I see that the presence of this control is declared as mandatory in
validateSensorDriver() in 1/5, but it just returns -EINVAL and
continues; would that cause a problem here?

> +	int32_t hblank = ctrls.get(V4L2_CID_HBLANK).get<int32_t>();

Would it just make this zero and continue? And the user has been warned
of unexpected behavior in the validation step already.

> +	V4L2SubdeviceFormat format{};
> +	int ret = subdev_->getFormat(pad_, &format);
> +	if (ret)
> +		return ret;
> +	int32_t ppl = format.size.width + hblank;
> +
> +	const ControlInfo &v4l2ExposureInfo = v4l2Controls.find(V4L2_CID_EXPOSURE)->second;
> +	int32_t minExposurePixels = v4l2ExposureInfo.min().get<int32_t>() * ppl;
> +	int32_t maxExposurePixels = v4l2ExposureInfo.max().get<int32_t>() * ppl;
> +	int32_t defExposurePixels = v4l2ExposureInfo.max().get<int32_t>() * ppl;

s/max/def/ ?


Paul

> +
> +	/* Get the pixel rate (in useconds) and calculate the exposure timings. */
> +	const ControlInfo &pixelRateInfo = v4l2Controls.find(V4L2_CID_PIXEL_RATE)->second;
> +	float minPixelRate = pixelRateInfo.min().get<int64_t>() / 1e6f;
> +	float maxPixelRate = pixelRateInfo.max().get<int64_t>() / 1e6f;
> +	float defPixelRate = pixelRateInfo.def().get<int64_t>() / 1e6f;
> +
> +	int32_t minExposure = static_cast<int32_t>(minExposurePixels / maxPixelRate);
> +	int32_t maxExposure = static_cast<int32_t>(maxExposurePixels / minPixelRate);
> +	int32_t defExposure = static_cast<int32_t>(defExposurePixels / defPixelRate);
> +
> +	ControlInfoMap::Map map;
> +	map[&controls::ExposureTime] = ControlInfo(minExposure, maxExposure,
> +						   defExposure);
> +	controls_ = std::move(map);
> +
> +	return 0;
> +}
> +
>  /**
>   * \fn CameraSensor::model()
>   * \brief Retrieve the sensor model name
> -- 
> 2.29.2
> 
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel@lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
Jacopo Mondi Dec. 28, 2020, 9:39 a.m. UTC | #2
Hi Paul,

On Mon, Dec 28, 2020 at 05:26:57PM +0900, paul.elder@ideasonboard.com wrote:
> Hi Jacopo,
>
> On Wed, Dec 23, 2020 at 07:45:13PM +0100, Jacopo Mondi wrote:
> > Initialize the ControlInfoMap of sensor available controls by
> > reporting the sensor exposure time range.
> >
> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> > ---
> >  include/libcamera/internal/camera_sensor.h |  2 ++
> >  src/libcamera/camera_sensor.cpp            | 42 +++++++++++++++++++++-
> >  2 files changed, 43 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> > index aee10aa6e3c7..0357b2a630f7 100644
> > --- a/include/libcamera/internal/camera_sensor.h
> > +++ b/include/libcamera/internal/camera_sensor.h
> > @@ -71,6 +71,7 @@ private:
> >  	int generateId();
> >  	int validateSensorDriver();
> >  	int initProperties();
> > +	int initControls();
> >
> >  	const MediaEntity *entity_;
> >  	std::unique_ptr<V4L2Subdevice> subdev_;
> > @@ -85,6 +86,7 @@ private:
> >  	std::vector<Size> sizes_;
> >
> >  	ControlList properties_;
> > +	ControlInfoMap controls_;
> >  };
> >
> >  } /* namespace libcamera */
> > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> > index 3a65ac3de5bc..609f948c56a6 100644
> > --- a/src/libcamera/camera_sensor.cpp
> > +++ b/src/libcamera/camera_sensor.cpp
> > @@ -15,6 +15,7 @@
> >  #include <regex>
> >  #include <string.h>
> >
> > +#include <libcamera/control_ids.h>
> >  #include <libcamera/property_ids.h>
> >
> >  #include "libcamera/internal/bayer_format.h"
> > @@ -215,7 +216,7 @@ int CameraSensor::init()
> >  	if (ret)
> >  		return ret;
> >
> > -	return 0;
> > +	return initControls();
> >  }
> >
> >  int CameraSensor::validateSensorDriver()
> > @@ -229,6 +230,7 @@ int CameraSensor::validateSensorDriver()
> >  	const std::vector<uint32_t> mandatoryControls{
> >  		V4L2_CID_PIXEL_RATE,
> >  		V4L2_CID_HBLANK,
> > +		V4L2_CID_EXPOSURE,
> >  	};
> >
> >  	ControlList ctrls = subdev_->getControls(mandatoryControls);
> > @@ -430,6 +432,44 @@ int CameraSensor::initProperties()
> >  	return 0;
> >  }
> >
> > +int CameraSensor::initControls()
> > +{
> > +	const ControlInfoMap &v4l2Controls = subdev_->controls();
> > +
> > +	/* Exposure time limits expressed in micro-seconds. */
> > +
> > +	/* Calculate the line length in pixels. */
> > +	ControlList ctrls = subdev_->getControls({ V4L2_CID_HBLANK });
>
> I see that the presence of this control is declared as mandatory in
> validateSensorDriver() in 1/5, but it just returns -EINVAL and
> continues; would that cause a problem here?

Do you mean 'validateSensorDriver()' returns -EINVAL ? In that case
CameraSensor::init() bails out before calling this method. Or have I
mis-understood your question ?

One thing I would add: reading a control might fail for other reason
than not being implemented in the driver. I should probably check for
        if (ctrl.empty())
nonetheless

>
> > +	int32_t hblank = ctrls.get(V4L2_CID_HBLANK).get<int32_t>();
>
> Would it just make this zero and continue? And the user has been warned
> of unexpected behavior in the validation step already.
>

We don't get here if validation fails if that's what you mean.

And in case reading the control fails for unrelated reasons, I would
fail instead of zeroing...

> > +	V4L2SubdeviceFormat format{};
> > +	int ret = subdev_->getFormat(pad_, &format);
> > +	if (ret)
> > +		return ret;
> > +	int32_t ppl = format.size.width + hblank;
> > +
> > +	const ControlInfo &v4l2ExposureInfo = v4l2Controls.find(V4L2_CID_EXPOSURE)->second;
> > +	int32_t minExposurePixels = v4l2ExposureInfo.min().get<int32_t>() * ppl;
> > +	int32_t maxExposurePixels = v4l2ExposureInfo.max().get<int32_t>() * ppl;
> > +	int32_t defExposurePixels = v4l2ExposureInfo.max().get<int32_t>() * ppl;
>
> s/max/def/ ?

Good catch!

Thanks
  j

>
>
> Paul
>
> > +
> > +	/* Get the pixel rate (in useconds) and calculate the exposure timings. */
> > +	const ControlInfo &pixelRateInfo = v4l2Controls.find(V4L2_CID_PIXEL_RATE)->second;
> > +	float minPixelRate = pixelRateInfo.min().get<int64_t>() / 1e6f;
> > +	float maxPixelRate = pixelRateInfo.max().get<int64_t>() / 1e6f;
> > +	float defPixelRate = pixelRateInfo.def().get<int64_t>() / 1e6f;
> > +
> > +	int32_t minExposure = static_cast<int32_t>(minExposurePixels / maxPixelRate);
> > +	int32_t maxExposure = static_cast<int32_t>(maxExposurePixels / minPixelRate);
> > +	int32_t defExposure = static_cast<int32_t>(defExposurePixels / defPixelRate);
> > +
> > +	ControlInfoMap::Map map;
> > +	map[&controls::ExposureTime] = ControlInfo(minExposure, maxExposure,
> > +						   defExposure);
> > +	controls_ = std::move(map);
> > +
> > +	return 0;
> > +}
> > +
> >  /**
> >   * \fn CameraSensor::model()
> >   * \brief Retrieve the sensor model name
> > --
> > 2.29.2
> >
> > _______________________________________________
> > libcamera-devel mailing list
> > libcamera-devel@lists.libcamera.org
> > https://lists.libcamera.org/listinfo/libcamera-devel
Paul Elder Dec. 28, 2020, 10:12 a.m. UTC | #3
Hi Jacopo,

On Mon, Dec 28, 2020 at 10:39:25AM +0100, Jacopo Mondi wrote:
> Hi Paul,
> 
> On Mon, Dec 28, 2020 at 05:26:57PM +0900, paul.elder@ideasonboard.com wrote:
> > Hi Jacopo,
> >
> > On Wed, Dec 23, 2020 at 07:45:13PM +0100, Jacopo Mondi wrote:
> > > Initialize the ControlInfoMap of sensor available controls by
> > > reporting the sensor exposure time range.
> > >
> > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> > > ---
> > >  include/libcamera/internal/camera_sensor.h |  2 ++
> > >  src/libcamera/camera_sensor.cpp            | 42 +++++++++++++++++++++-
> > >  2 files changed, 43 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> > > index aee10aa6e3c7..0357b2a630f7 100644
> > > --- a/include/libcamera/internal/camera_sensor.h
> > > +++ b/include/libcamera/internal/camera_sensor.h
> > > @@ -71,6 +71,7 @@ private:
> > >  	int generateId();
> > >  	int validateSensorDriver();
> > >  	int initProperties();
> > > +	int initControls();
> > >
> > >  	const MediaEntity *entity_;
> > >  	std::unique_ptr<V4L2Subdevice> subdev_;
> > > @@ -85,6 +86,7 @@ private:
> > >  	std::vector<Size> sizes_;
> > >
> > >  	ControlList properties_;
> > > +	ControlInfoMap controls_;
> > >  };
> > >
> > >  } /* namespace libcamera */
> > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> > > index 3a65ac3de5bc..609f948c56a6 100644
> > > --- a/src/libcamera/camera_sensor.cpp
> > > +++ b/src/libcamera/camera_sensor.cpp
> > > @@ -15,6 +15,7 @@
> > >  #include <regex>
> > >  #include <string.h>
> > >
> > > +#include <libcamera/control_ids.h>
> > >  #include <libcamera/property_ids.h>
> > >
> > >  #include "libcamera/internal/bayer_format.h"
> > > @@ -215,7 +216,7 @@ int CameraSensor::init()
> > >  	if (ret)
> > >  		return ret;
> > >
> > > -	return 0;
> > > +	return initControls();
> > >  }
> > >
> > >  int CameraSensor::validateSensorDriver()
> > > @@ -229,6 +230,7 @@ int CameraSensor::validateSensorDriver()
> > >  	const std::vector<uint32_t> mandatoryControls{
> > >  		V4L2_CID_PIXEL_RATE,
> > >  		V4L2_CID_HBLANK,
> > > +		V4L2_CID_EXPOSURE,
> > >  	};
> > >
> > >  	ControlList ctrls = subdev_->getControls(mandatoryControls);
> > > @@ -430,6 +432,44 @@ int CameraSensor::initProperties()
> > >  	return 0;
> > >  }
> > >
> > > +int CameraSensor::initControls()
> > > +{
> > > +	const ControlInfoMap &v4l2Controls = subdev_->controls();
> > > +
> > > +	/* Exposure time limits expressed in micro-seconds. */
> > > +
> > > +	/* Calculate the line length in pixels. */
> > > +	ControlList ctrls = subdev_->getControls({ V4L2_CID_HBLANK });
> >
> > I see that the presence of this control is declared as mandatory in
> > validateSensorDriver() in 1/5, but it just returns -EINVAL and
> > continues; would that cause a problem here?
> 
> Do you mean 'validateSensorDriver()' returns -EINVAL ? In that case

Ah yeah, I mean in the case that the mandatory control is not present,
so validateSensorDriver() returns -EINVAL.

> CameraSensor::init() bails out before calling this method. Or have I

Wouldn't that mean that this method won't be called either if the
optional controls aren't present in the driver?

> mis-understood your question ?
> 
> One thing I would add: reading a control might fail for other reason
> than not being implemented in the driver. I should probably check for
>         if (ctrl.empty())
> nonetheless
> 
> >
> > > +	int32_t hblank = ctrls.get(V4L2_CID_HBLANK).get<int32_t>();
> >
> > Would it just make this zero and continue? And the user has been warned
> > of unexpected behavior in the validation step already.
> >
> 
> We don't get here if validation fails if that's what you mean.

I see.


Paul

> And in case reading the control fails for unrelated reasons, I would
> fail instead of zeroing...
> 
> > > +	V4L2SubdeviceFormat format{};
> > > +	int ret = subdev_->getFormat(pad_, &format);
> > > +	if (ret)
> > > +		return ret;
> > > +	int32_t ppl = format.size.width + hblank;
> > > +
> > > +	const ControlInfo &v4l2ExposureInfo = v4l2Controls.find(V4L2_CID_EXPOSURE)->second;
> > > +	int32_t minExposurePixels = v4l2ExposureInfo.min().get<int32_t>() * ppl;
> > > +	int32_t maxExposurePixels = v4l2ExposureInfo.max().get<int32_t>() * ppl;
> > > +	int32_t defExposurePixels = v4l2ExposureInfo.max().get<int32_t>() * ppl;
> >
> > s/max/def/ ?
> 
> Good catch!
> 
> Thanks
>   j
> 
> >
> >
> > Paul
> >
> > > +
> > > +	/* Get the pixel rate (in useconds) and calculate the exposure timings. */
> > > +	const ControlInfo &pixelRateInfo = v4l2Controls.find(V4L2_CID_PIXEL_RATE)->second;
> > > +	float minPixelRate = pixelRateInfo.min().get<int64_t>() / 1e6f;
> > > +	float maxPixelRate = pixelRateInfo.max().get<int64_t>() / 1e6f;
> > > +	float defPixelRate = pixelRateInfo.def().get<int64_t>() / 1e6f;
> > > +
> > > +	int32_t minExposure = static_cast<int32_t>(minExposurePixels / maxPixelRate);
> > > +	int32_t maxExposure = static_cast<int32_t>(maxExposurePixels / minPixelRate);
> > > +	int32_t defExposure = static_cast<int32_t>(defExposurePixels / defPixelRate);
> > > +
> > > +	ControlInfoMap::Map map;
> > > +	map[&controls::ExposureTime] = ControlInfo(minExposure, maxExposure,
> > > +						   defExposure);
> > > +	controls_ = std::move(map);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >  /**
> > >   * \fn CameraSensor::model()
> > >   * \brief Retrieve the sensor model name
> > > --
> > > 2.29.2
> > >
> > > _______________________________________________
> > > libcamera-devel mailing list
> > > libcamera-devel@lists.libcamera.org
> > > https://lists.libcamera.org/listinfo/libcamera-devel
Paul Elder Dec. 28, 2020, 10:13 a.m. UTC | #4
On Mon, Dec 28, 2020 at 07:12:25PM +0900, paul.elder@ideasonboard.com wrote:
> Hi Jacopo,
> 
> On Mon, Dec 28, 2020 at 10:39:25AM +0100, Jacopo Mondi wrote:
> > Hi Paul,
> > 
> > On Mon, Dec 28, 2020 at 05:26:57PM +0900, paul.elder@ideasonboard.com wrote:
> > > Hi Jacopo,
> > >
> > > On Wed, Dec 23, 2020 at 07:45:13PM +0100, Jacopo Mondi wrote:
> > > > Initialize the ControlInfoMap of sensor available controls by
> > > > reporting the sensor exposure time range.
> > > >
> > > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> > > > ---
> > > >  include/libcamera/internal/camera_sensor.h |  2 ++
> > > >  src/libcamera/camera_sensor.cpp            | 42 +++++++++++++++++++++-
> > > >  2 files changed, 43 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> > > > index aee10aa6e3c7..0357b2a630f7 100644
> > > > --- a/include/libcamera/internal/camera_sensor.h
> > > > +++ b/include/libcamera/internal/camera_sensor.h
> > > > @@ -71,6 +71,7 @@ private:
> > > >  	int generateId();
> > > >  	int validateSensorDriver();
> > > >  	int initProperties();
> > > > +	int initControls();
> > > >
> > > >  	const MediaEntity *entity_;
> > > >  	std::unique_ptr<V4L2Subdevice> subdev_;
> > > > @@ -85,6 +86,7 @@ private:
> > > >  	std::vector<Size> sizes_;
> > > >
> > > >  	ControlList properties_;
> > > > +	ControlInfoMap controls_;
> > > >  };
> > > >
> > > >  } /* namespace libcamera */
> > > > diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
> > > > index 3a65ac3de5bc..609f948c56a6 100644
> > > > --- a/src/libcamera/camera_sensor.cpp
> > > > +++ b/src/libcamera/camera_sensor.cpp
> > > > @@ -15,6 +15,7 @@
> > > >  #include <regex>
> > > >  #include <string.h>
> > > >
> > > > +#include <libcamera/control_ids.h>
> > > >  #include <libcamera/property_ids.h>
> > > >
> > > >  #include "libcamera/internal/bayer_format.h"
> > > > @@ -215,7 +216,7 @@ int CameraSensor::init()
> > > >  	if (ret)
> > > >  		return ret;
> > > >
> > > > -	return 0;
> > > > +	return initControls();
> > > >  }
> > > >
> > > >  int CameraSensor::validateSensorDriver()
> > > > @@ -229,6 +230,7 @@ int CameraSensor::validateSensorDriver()
> > > >  	const std::vector<uint32_t> mandatoryControls{
> > > >  		V4L2_CID_PIXEL_RATE,
> > > >  		V4L2_CID_HBLANK,
> > > > +		V4L2_CID_EXPOSURE,
> > > >  	};
> > > >
> > > >  	ControlList ctrls = subdev_->getControls(mandatoryControls);
> > > > @@ -430,6 +432,44 @@ int CameraSensor::initProperties()
> > > >  	return 0;
> > > >  }
> > > >
> > > > +int CameraSensor::initControls()
> > > > +{
> > > > +	const ControlInfoMap &v4l2Controls = subdev_->controls();
> > > > +
> > > > +	/* Exposure time limits expressed in micro-seconds. */
> > > > +
> > > > +	/* Calculate the line length in pixels. */
> > > > +	ControlList ctrls = subdev_->getControls({ V4L2_CID_HBLANK });
> > >
> > > I see that the presence of this control is declared as mandatory in
> > > validateSensorDriver() in 1/5, but it just returns -EINVAL and
> > > continues; would that cause a problem here?
> > 
> > Do you mean 'validateSensorDriver()' returns -EINVAL ? In that case
> 
> Ah yeah, I mean in the case that the mandatory control is not present,
> so validateSensorDriver() returns -EINVAL.
> 
> > CameraSensor::init() bails out before calling this method. Or have I
> 
> Wouldn't that mean that this method won't be called either if the
> optional controls aren't present in the driver?

Oh nvm, I misread the last patch.


Paul

> > mis-understood your question ?
> > 
> > One thing I would add: reading a control might fail for other reason
> > than not being implemented in the driver. I should probably check for
> >         if (ctrl.empty())
> > nonetheless
> > 
> > >
> > > > +	int32_t hblank = ctrls.get(V4L2_CID_HBLANK).get<int32_t>();
> > >
> > > Would it just make this zero and continue? And the user has been warned
> > > of unexpected behavior in the validation step already.
> > >
> > 
> > We don't get here if validation fails if that's what you mean.
> 
> I see.
> 
> 
> Paul
> 
> > And in case reading the control fails for unrelated reasons, I would
> > fail instead of zeroing...
> > 
> > > > +	V4L2SubdeviceFormat format{};
> > > > +	int ret = subdev_->getFormat(pad_, &format);
> > > > +	if (ret)
> > > > +		return ret;
> > > > +	int32_t ppl = format.size.width + hblank;
> > > > +
> > > > +	const ControlInfo &v4l2ExposureInfo = v4l2Controls.find(V4L2_CID_EXPOSURE)->second;
> > > > +	int32_t minExposurePixels = v4l2ExposureInfo.min().get<int32_t>() * ppl;
> > > > +	int32_t maxExposurePixels = v4l2ExposureInfo.max().get<int32_t>() * ppl;
> > > > +	int32_t defExposurePixels = v4l2ExposureInfo.max().get<int32_t>() * ppl;
> > >
> > > s/max/def/ ?
> > 
> > Good catch!
> > 
> > Thanks
> >   j
> > 
> > >
> > >
> > > Paul
> > >
> > > > +
> > > > +	/* Get the pixel rate (in useconds) and calculate the exposure timings. */
> > > > +	const ControlInfo &pixelRateInfo = v4l2Controls.find(V4L2_CID_PIXEL_RATE)->second;
> > > > +	float minPixelRate = pixelRateInfo.min().get<int64_t>() / 1e6f;
> > > > +	float maxPixelRate = pixelRateInfo.max().get<int64_t>() / 1e6f;
> > > > +	float defPixelRate = pixelRateInfo.def().get<int64_t>() / 1e6f;
> > > > +
> > > > +	int32_t minExposure = static_cast<int32_t>(minExposurePixels / maxPixelRate);
> > > > +	int32_t maxExposure = static_cast<int32_t>(maxExposurePixels / minPixelRate);
> > > > +	int32_t defExposure = static_cast<int32_t>(defExposurePixels / defPixelRate);
> > > > +
> > > > +	ControlInfoMap::Map map;
> > > > +	map[&controls::ExposureTime] = ControlInfo(minExposure, maxExposure,
> > > > +						   defExposure);
> > > > +	controls_ = std::move(map);
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > >  /**
> > > >   * \fn CameraSensor::model()
> > > >   * \brief Retrieve the sensor model name
> > > > --
> > > > 2.29.2
> > > >
> > > > _______________________________________________
> > > > libcamera-devel mailing list
> > > > libcamera-devel@lists.libcamera.org
> > > > https://lists.libcamera.org/listinfo/libcamera-devel
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel@lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel

Patch
diff mbox series

diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
index aee10aa6e3c7..0357b2a630f7 100644
--- a/include/libcamera/internal/camera_sensor.h
+++ b/include/libcamera/internal/camera_sensor.h
@@ -71,6 +71,7 @@  private:
 	int generateId();
 	int validateSensorDriver();
 	int initProperties();
+	int initControls();
 
 	const MediaEntity *entity_;
 	std::unique_ptr<V4L2Subdevice> subdev_;
@@ -85,6 +86,7 @@  private:
 	std::vector<Size> sizes_;
 
 	ControlList properties_;
+	ControlInfoMap controls_;
 };
 
 } /* namespace libcamera */
diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
index 3a65ac3de5bc..609f948c56a6 100644
--- a/src/libcamera/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor.cpp
@@ -15,6 +15,7 @@ 
 #include <regex>
 #include <string.h>
 
+#include <libcamera/control_ids.h>
 #include <libcamera/property_ids.h>
 
 #include "libcamera/internal/bayer_format.h"
@@ -215,7 +216,7 @@  int CameraSensor::init()
 	if (ret)
 		return ret;
 
-	return 0;
+	return initControls();
 }
 
 int CameraSensor::validateSensorDriver()
@@ -229,6 +230,7 @@  int CameraSensor::validateSensorDriver()
 	const std::vector<uint32_t> mandatoryControls{
 		V4L2_CID_PIXEL_RATE,
 		V4L2_CID_HBLANK,
+		V4L2_CID_EXPOSURE,
 	};
 
 	ControlList ctrls = subdev_->getControls(mandatoryControls);
@@ -430,6 +432,44 @@  int CameraSensor::initProperties()
 	return 0;
 }
 
+int CameraSensor::initControls()
+{
+	const ControlInfoMap &v4l2Controls = subdev_->controls();
+
+	/* Exposure time limits expressed in micro-seconds. */
+
+	/* Calculate the line length in pixels. */
+	ControlList ctrls = subdev_->getControls({ V4L2_CID_HBLANK });
+	int32_t hblank = ctrls.get(V4L2_CID_HBLANK).get<int32_t>();
+	V4L2SubdeviceFormat format{};
+	int ret = subdev_->getFormat(pad_, &format);
+	if (ret)
+		return ret;
+	int32_t ppl = format.size.width + hblank;
+
+	const ControlInfo &v4l2ExposureInfo = v4l2Controls.find(V4L2_CID_EXPOSURE)->second;
+	int32_t minExposurePixels = v4l2ExposureInfo.min().get<int32_t>() * ppl;
+	int32_t maxExposurePixels = v4l2ExposureInfo.max().get<int32_t>() * ppl;
+	int32_t defExposurePixels = v4l2ExposureInfo.max().get<int32_t>() * ppl;
+
+	/* Get the pixel rate (in useconds) and calculate the exposure timings. */
+	const ControlInfo &pixelRateInfo = v4l2Controls.find(V4L2_CID_PIXEL_RATE)->second;
+	float minPixelRate = pixelRateInfo.min().get<int64_t>() / 1e6f;
+	float maxPixelRate = pixelRateInfo.max().get<int64_t>() / 1e6f;
+	float defPixelRate = pixelRateInfo.def().get<int64_t>() / 1e6f;
+
+	int32_t minExposure = static_cast<int32_t>(minExposurePixels / maxPixelRate);
+	int32_t maxExposure = static_cast<int32_t>(maxExposurePixels / minPixelRate);
+	int32_t defExposure = static_cast<int32_t>(defExposurePixels / defPixelRate);
+
+	ControlInfoMap::Map map;
+	map[&controls::ExposureTime] = ControlInfo(minExposure, maxExposure,
+						   defExposure);
+	controls_ = std::move(map);
+
+	return 0;
+}
+
 /**
  * \fn CameraSensor::model()
  * \brief Retrieve the sensor model name