[libcamera-devel,08/15] libcamera: camera_sensor: Initialize controls
diff mbox series

Message ID 20220627162732.33160-9-jacopo@jmondi.org
State Not Applicable, archived
Headers show
Series
  • Internal controls, sensor delays and IPA init/configure rework
Related show

Commit Message

Jacopo Mondi June 27, 2022, 4:27 p.m. UTC
Initialize the control interface of the CameraSensor class by
registering the control limits for controls::internal::ExposureTime,
controls::internal::FrameDuration and
controls::internal::draft::SensorAnalogueGain.

Update the CameraSensor controls in the CameraSensor::updateControlInfo()
function after having updated the subdevice V4L2 controls.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 include/libcamera/internal/camera_sensor.h |  3 +
 src/libcamera/camera_sensor.cpp            | 89 ++++++++++++++++++++++
 src/libcamera/internal_control_ids.yaml    | 10 +++
 3 files changed, 102 insertions(+)

Patch
diff mbox series

diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
index 0bed6e679840..c71f93f230d1 100644
--- a/include/libcamera/internal/camera_sensor.h
+++ b/include/libcamera/internal/camera_sensor.h
@@ -66,6 +66,7 @@  public:
 	V4L2Subdevice *device() { return subdev_.get(); }
 
 	const ControlList &properties() const { return properties_; }
+	const ControlInfoMap &controls() const { return controls_; }
 	int sensorInfo(IPACameraSensorInfo *info) const;
 
 	void updateControlInfo();
@@ -84,6 +85,7 @@  private:
 	void initStaticProperties();
 	void initTestPatternModes();
 	int initProperties();
+	int updateControls();
 	int applyTestPatternMode(controls::draft::TestPatternModeEnum mode);
 	int discoverAncillaryDevices();
 
@@ -107,6 +109,7 @@  private:
 	const BayerFormat *bayerFormat_;
 
 	ControlList properties_;
+	ControlInfoMap controls_;
 
 	std::unique_ptr<CameraLens> focusLens_;
 };
diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
index e3354530380c..82e51272cccc 100644
--- a/src/libcamera/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor.cpp
@@ -22,6 +22,7 @@ 
 #include "libcamera/internal/bayer_format.h"
 #include "libcamera/internal/camera_lens.h"
 #include "libcamera/internal/camera_sensor_properties.h"
+#include "libcamera/internal/control_ids.h"
 #include "libcamera/internal/formats.h"
 #include "libcamera/internal/sysfs.h"
 
@@ -180,6 +181,10 @@  int CameraSensor::init()
 	if (ret)
 		return ret;
 
+	ret = updateControls();
+	if (ret)
+		return ret;
+
 	ret = discoverAncillaryDevices();
 	if (ret)
 		return ret;
@@ -455,6 +460,83 @@  int CameraSensor::initProperties()
 	return 0;
 }
 
+int CameraSensor::updateControls()
+{
+	if (!bayerFormat_)
+		return 0;
+
+	ControlInfoMap::Map controlsMap;
+
+	/* The subdev driver has been validate already, the controls are there! */
+	ControlList subdevControls = subdev_->getControls({ V4L2_CID_PIXEL_RATE,
+							    V4L2_CID_HBLANK,
+							    V4L2_CID_VBLANK });
+	uint64_t pixelRate = subdevControls.get(V4L2_CID_PIXEL_RATE).get<int64_t>();
+	uint32_t hblank = subdevControls.get(V4L2_CID_HBLANK).get<int32_t>();
+
+	/*  Assume the sensor has a single source pad #0. */
+	V4L2SubdeviceFormat subdevFormat;
+	subdev_->getFormat(0, &subdevFormat);
+
+	const ControlInfoMap &subdevControlsInfo = subdev_->controls();
+
+	/*
+	 * Compute controls::ExposureTime limits by using line length and pixel
+	 * rate converted to microseconds. Use the V4L2_CID_EXPOSURE control to
+	 * get exposure min, max and default and convert it from lines to
+	 * microseconds.
+	 */
+	uint32_t lineLength = subdevFormat.size.width + hblank;
+	double lineDuration = lineLength / (pixelRate / 1000000.0F);
+	auto &[expId, v4l2Exposure] = *subdevControlsInfo.find(V4L2_CID_EXPOSURE);
+	int32_t minExposure = v4l2Exposure.min().get<int32_t>() * lineDuration;
+	int32_t maxExposure = v4l2Exposure.max().get<int32_t>() * lineDuration;
+	int32_t defExposure = v4l2Exposure.def().get<int32_t>() * lineDuration;
+
+	controlsMap[&controls::internal::ExposureTime] =
+		ControlInfo(minExposure, maxExposure, defExposure);
+
+	/*
+	 * Compute the frame duration limits.
+	 *
+	 * The frame length is computed assuming a fixed line length combined
+	 * with the vertical frame sizes.
+	 */
+	auto &[vblankId, v4l2VBlank] = *subdevControlsInfo.find(V4L2_CID_VBLANK);
+	std::array<uint32_t, 3> frameHeights{
+		v4l2VBlank.min().get<int32_t>() + subdevFormat.size.height,
+		v4l2VBlank.max().get<int32_t>() + subdevFormat.size.height,
+		v4l2VBlank.def().get<int32_t>() + subdevFormat.size.height,
+	};
+
+	std::array<int64_t, 3> frameDurations;
+	for (unsigned int i = 0; i < frameHeights.size(); ++i) {
+		uint64_t frameSize = lineLength * frameHeights[i];
+		frameDurations[i] = frameSize / (pixelRate / 1000000.0F);
+	}
+
+	controlsMap[&controls::internal::FrameDuration] =
+		ControlInfo(frameDurations[0], frameDurations[1], frameDurations[2]);
+
+	/*
+	 * For analogue gain collect the raw V4L2 control values which express
+	 * the gain codes as seen from the sensor and need to be translated
+	 * on the IPA side.
+	 *
+	 * \todo Translate it by using a CameraSensorHelper.
+	 */
+	auto &[gainId, v4l2AGain] = *subdevControlsInfo.find(V4L2_CID_ANALOGUE_GAIN);
+	controlsMap[&controls::internal::draft::SensorAnalogueGain] =
+		ControlInfo(v4l2AGain.min().get<int32_t>(),
+			    v4l2AGain.max().get<int32_t>(),
+			    v4l2AGain.def().get<int32_t>());
+
+	controls_ = ControlInfoMap(std::move(controlsMap),
+				   controls::internal::controls);
+
+	return 0;
+}
+
 /**
  * \brief Check for and initialise any ancillary devices
  *
@@ -837,6 +919,12 @@  int CameraSensor::setV4L2Controls(ControlList *ctrls)
  * \return The list of camera sensor properties
  */
 
+/**
+ * \fn CameraSensor::controls()
+ * \brief Retrieve the map of the camera sensor controls limits
+ * \return The map of camera sensor control information
+ */
+
 /**
  * \brief Assemble and return the camera sensor info
  * \param[out] info The camera sensor info
@@ -932,6 +1020,7 @@  int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const
 void CameraSensor::updateControlInfo()
 {
 	subdev_->updateControlInfo();
+	updateControls();
 }
 
 /**
diff --git a/src/libcamera/internal_control_ids.yaml b/src/libcamera/internal_control_ids.yaml
index e69e0d30657c..c6e6bd111cf7 100644
--- a/src/libcamera/internal_control_ids.yaml
+++ b/src/libcamera/internal_control_ids.yaml
@@ -9,6 +9,16 @@ 
 
 controls:
 
+  - ExposureTime:
+      type: int32_t
+      description: |
+        The sensor exposure time in milliseconds.
+
+  - FrameDuration:
+      type: int64_t
+      description: |
+        The sensor frame duration time in milliseconds.
+
   # ----------------------------------------------------------------------------
   # Draft controls section