[libcamera-devel,v6,4/4] libcamera: pipeline: ipu3: Apply the requested test pattern mode
diff mbox series

Message ID 20211110072207.3273703-4-hiroh@chromium.org
State Superseded
Headers show
Series
  • [libcamera-devel,v6,1/4] lc-compliance: Build with gtest in subprojects
Related show

Commit Message

Hirokazu Honda Nov. 10, 2021, 7:22 a.m. UTC
This enables ipu3 pipeline handler to apply the test pattern mode
per frame.

Signed-off-by: Hirokazu Honda <hiroh@chromium.org>
Reviewed-by: Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>
---
 include/libcamera/internal/camera_sensor.h |  1 +
 src/libcamera/camera_sensor.cpp            | 34 ++++++++++++++++++++++
 src/libcamera/pipeline/ipu3/ipu3.cpp       | 29 ++++++++++++++++--
 3 files changed, 62 insertions(+), 2 deletions(-)

Patch
diff mbox series

diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
index 60ce0c45..ed782476 100644
--- a/include/libcamera/internal/camera_sensor.h
+++ b/include/libcamera/internal/camera_sensor.h
@@ -58,6 +58,7 @@  public:
 	const ControlInfoMap &controls() const;
 	ControlList getControls(const std::vector<uint32_t> &ids);
 	int setControls(ControlList *ctrls);
+	int applyRequestControls(Request *request);
 
 	V4L2Subdevice *device() { return subdev_.get(); }
 
diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
index cfb9bc17..a20f3d95 100644
--- a/src/libcamera/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor.cpp
@@ -755,6 +755,40 @@  int CameraSensor::setControls(ControlList *ctrls)
 	return subdev_->setControls(ctrls);
 }
 
+/**
+ * \brief Apply controls associated with Request
+ * \param[in] request Request that may contain contorls to be applied
+ *
+ * Some controls have to be applied for a capture associated with Request.
+ * This picks up such controls and set the driver them.
+ *
+ * \return 0 on success or an error code otherwise
+ */
+int32_t CameraSensor::applyRequestControls(Request *request)
+{
+	/* Assumes applying the test pattern mode affects immediately. */
+	if (request->controls().contains(controls::draft::TestPatternMode)) {
+		const int32_t testPatternMode = request->controls().get(
+			controls::draft::TestPatternMode);
+
+		LOG(CameraSensor, Debug) << "Apply test pattern mode: "
+					 << testPatternMode;
+
+		int ret = setTestPatternMode(
+			static_cast<controls::draft::TestPatternModeEnum>(testPatternMode));
+		if (ret) {
+			LOG(CameraSensor, Error)
+				<< "Failed to set test pattern mode: " << ret;
+			return ret;
+		}
+
+		request->metadata().set(controls::draft::TestPatternMode,
+					testPatternMode);
+	}
+
+	return 0;
+}
+
 /**
  * \fn CameraSensor::device()
  * \brief Retrieve the camera sensor device
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 63cb7f11..f4137f2d 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -59,6 +59,7 @@  public:
 	void statBufferReady(FrameBuffer *buffer);
 	void queuePendingRequests();
 	void cancelPendingRequests();
+	void frameStart(uint32_t sequence);
 
 	CIO2Device cio2_;
 	ImgUDevice *imgu_;
@@ -77,7 +78,10 @@  public:
 
 	std::unique_ptr<ipa::ipu3::IPAProxyIPU3> ipa_;
 
+	/* Requests before queueing cio2 device. */
 	std::queue<Request *> pendingRequests_;
+	/* Requests queued in cio2 device and before passing imgu device. */
+	std::queue<Request *> processingRequests_;
 
 	ControlInfoMap ipaControls_;
 
@@ -802,6 +806,7 @@  void PipelineHandlerIPU3::stop(Camera *camera)
 
 	ret |= data->imgu_->stop();
 	ret |= data->cio2_.stop();
+
 	if (ret)
 		LOG(IPU3, Warning) << "Failed to stop camera " << camera->id();
 
@@ -822,6 +827,8 @@  void IPU3CameraData::cancelPendingRequests()
 		pipe()->completeRequest(request);
 		pendingRequests_.pop();
 	}
+
+	processingRequests_ = {};
 }
 
 void IPU3CameraData::queuePendingRequests()
@@ -852,6 +859,8 @@  void IPU3CameraData::queuePendingRequests()
 
 		info->rawBuffer = rawBuffer;
 
+		processingRequests_.push(request);
+
 		ipa::ipu3::IPU3Event ev;
 		ev.op = ipa::ipu3::EventProcessControls;
 		ev.frame = info->id;
@@ -1131,8 +1140,8 @@  int PipelineHandlerIPU3::registerCameras()
 		data->delayedCtrls_ =
 			std::make_unique<DelayedControls>(cio2->sensor()->device(),
 							  params);
-		data->cio2_.frameStart().connect(data->delayedCtrls_.get(),
-						 &DelayedControls::applyControls);
+		data->cio2_.frameStart().connect(data.get(),
+						 &IPU3CameraData::frameStart);
 
 		/* Convert the sensor rotation to a transformation */
 		int32_t rotation = 0;
@@ -1423,6 +1432,22 @@  void IPU3CameraData::statBufferReady(FrameBuffer *buffer)
 	ipa_->processEvent(ev);
 }
 
+void IPU3CameraData::frameStart(uint32_t sequence)
+{
+	if (!processingRequests_.empty()) {
+		/* Handle controls which are to be set ready for the next frame to start. */
+		Request *request = processingRequests_.front();
+		processingRequests_.pop();
+
+		int ret = cio2_.sensor()->applyRequestControls(request);
+		if (ret)
+			LOG(IPU3, Error) << "Failed applying controls: " << ret;
+	}
+
+	/* Controls that don't affect immediately are applied in delayedCtrls. */
+	delayedCtrls_->applyControls(sequence);
+}
+
 REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3)
 
 } /* namespace libcamera */