[3/3] rkisp1: synchronize sensor controls with IPA
diff mbox series

Message ID 20241017124613.3853273-4-mike.rudenko@gmail.com
State Superseded
Headers show
Series
  • Reduce rkisp1 flicker on first start
Related show

Commit Message

Mikhail Rudenko Oct. 17, 2024, 12:46 p.m. UTC
When IPA AGC active state is initialized in configure() method, it may
fall out of sync with actual sensor controls and initial values in the
delayed controls. Fix this by sending updated controls to the pipeline
handler on first start() after configure(). Also reset delayedCtrls_
on start to make it capture the updated control values.

Signed-off-by: Mikhail Rudenko <mike.rudenko@gmail.com>
---
 include/libcamera/ipa/rkisp1.mojom       |  2 +-
 src/ipa/rkisp1/ipa_context.h             |  2 ++
 src/ipa/rkisp1/rkisp1.cpp                | 19 +++++++++++++++----
 src/libcamera/pipeline/rkisp1/rkisp1.cpp |  6 +++++-
 4 files changed, 23 insertions(+), 6 deletions(-)

Patch
diff mbox series

diff --git a/include/libcamera/ipa/rkisp1.mojom b/include/libcamera/ipa/rkisp1.mojom
index 80d54a03..09900742 100644
--- a/include/libcamera/ipa/rkisp1.mojom
+++ b/include/libcamera/ipa/rkisp1.mojom
@@ -20,7 +20,7 @@  interface IPARkISP1Interface {
 	     libcamera.IPACameraSensorInfo sensorInfo,
 	     libcamera.ControlInfoMap sensorControls)
 		=> (int32 ret, libcamera.ControlInfoMap ipaControls);
-	start() => (int32 ret);
+	start() => (int32 ret, libcamera.ControlList sensorControls);
 	stop();
 
 	configure(IPAConfigInfo configInfo,
diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
index e274d9b0..e07a5cdb 100644
--- a/src/ipa/rkisp1/ipa_context.h
+++ b/src/ipa/rkisp1/ipa_context.h
@@ -191,6 +191,8 @@  struct IPAContext {
 
 	/* Interface to the Camera Helper */
 	std::unique_ptr<CameraSensorHelper> camHelper;
+
+	bool sensorControlsNeedSync;
 };
 
 } /* namespace ipa::rkisp1 */
diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index 9e161cab..680a7eee 100644
--- a/src/ipa/rkisp1/rkisp1.cpp
+++ b/src/ipa/rkisp1/rkisp1.cpp
@@ -55,7 +55,7 @@  public:
 		 const IPACameraSensorInfo &sensorInfo,
 		 const ControlInfoMap &sensorControls,
 		 ControlInfoMap *ipaControls) override;
-	int start() override;
+	int start(ControlList *sensorControls) override;
 	void stop() override;
 
 	int configure(const IPAConfigInfo &ipaConfig,
@@ -124,7 +124,7 @@  const ControlInfoMap::Map rkisp1Controls{
 } /* namespace */
 
 IPARkISP1::IPARkISP1()
-	: context_({ {}, {}, {}, {}, { kMaxFrameContexts }, {}, {} })
+	: context_({ {}, {}, {}, {}, { kMaxFrameContexts }, {}, {}, false })
 {
 }
 
@@ -208,10 +208,19 @@  int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision,
 	return 0;
 }
 
-int IPARkISP1::start()
+int IPARkISP1::start(ControlList *sensorControls)
 {
-	setControls(0);
+	if (context_.sensorControlsNeedSync) {
+		const auto &agc = context_.activeState.agc;
+		uint32_t exposure = agc.automatic.exposure;
+		uint32_t gain = context_.camHelper->gainCode(agc.automatic.gain);
 
+		*sensorControls = ControlList{ sensorControls_ };
+		sensorControls->set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure));
+		sensorControls->set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(gain));
+
+		context_.sensorControlsNeedSync = false;
+	}
 	return 0;
 }
 
@@ -290,6 +299,8 @@  int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,
 			return ret;
 	}
 
+	context_.sensorControlsNeedSync = true;
+
 	return 0;
 }
 
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index 42961c12..18d98547 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -943,6 +943,7 @@  int PipelineHandlerRkISP1::start(Camera *camera, [[maybe_unused]] const ControlL
 {
 	RkISP1CameraData *data = cameraData(camera);
 	utils::ScopeExitActions actions;
+	ControlList sensorControls;
 	int ret;
 
 	/* Allocate buffers for internal pipeline usage. */
@@ -951,7 +952,7 @@  int PipelineHandlerRkISP1::start(Camera *camera, [[maybe_unused]] const ControlL
 		return ret;
 	actions += [&]() { freeBuffers(camera); };
 
-	ret = data->ipa_->start();
+	ret = data->ipa_->start(&sensorControls);
 	if (ret) {
 		LOG(RkISP1, Error)
 			<< "Failed to start IPA " << camera->id();
@@ -961,6 +962,9 @@  int PipelineHandlerRkISP1::start(Camera *camera, [[maybe_unused]] const ControlL
 
 	data->frame_ = 0;
 
+	data->sensor_->setControls(&sensorControls);
+	data->delayedCtrls_->reset();
+
 	if (!isRaw_) {
 		ret = param_->streamOn();
 		if (ret) {