[libcamera-devel,8/8] ipa: rkisp1: Add "Windows" Metering mode to auto focus algorithm
diff mbox series

Message ID 20220630143543.39599-9-dse@thaumatec.com
State Superseded
Headers show
Series
  • ipa: rkisp1: Add autofocus algorithm
Related show

Commit Message

Daniel Semkowicz June 30, 2022, 2:35 p.m. UTC
Allow manually setting auto focus window. Currently only one window is
enabled, but ISP allows up to three of them.

Signed-off-by: Daniel Semkowicz <dse@thaumatec.com>
---
 src/ipa/rkisp1/algorithms/af.cpp         | 74 ++++++++++++++++++++++--
 src/ipa/rkisp1/algorithms/af.h           |  9 +++
 src/ipa/rkisp1/rkisp1.cpp                | 20 +++++++
 src/libcamera/pipeline/rkisp1/rkisp1.cpp |  2 +
 4 files changed, 99 insertions(+), 6 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/algorithms/af.cpp b/src/ipa/rkisp1/algorithms/af.cpp
index 8da970e3..22507918 100644
--- a/src/ipa/rkisp1/algorithms/af.cpp
+++ b/src/ipa/rkisp1/algorithms/af.cpp
@@ -20,20 +20,54 @@  namespace libcamera::ipa::rkisp1::algorithms {
 
 LOG_DEFINE_CATEGORY(RkISP1Af)
 
+
+static rkisp1_cif_isp_window rectangleToIspWindow(const Rectangle &rectangle)
+{
+	rkisp1_cif_isp_window ispwindow;
+
+	ispwindow.h_offs = rectangle.x;
+	ispwindow.v_offs = rectangle.y;
+	ispwindow.h_size = rectangle.width;
+	ispwindow.v_size = rectangle.height;
+
+	return ispwindow;
+}
+
 /**
  * \copydoc libcamera::ipa::Algorithm::configure
  */
 int Af::configure([[maybe_unused]] IPAContext &context,
-		  [[maybe_unused]] const IPACameraSensorInfo &configInfo)
+		  const IPACameraSensorInfo &configInfo)
 {
+	/* Default AF window of 3/4 size of the screen placed at the center */
+	defaultWindow_ = Rectangle(configInfo.outputSize.width / 8,
+				   configInfo.outputSize.height / 8,
+				   3 * configInfo.outputSize.width / 4,
+				   3 * configInfo.outputSize.height / 4);
+	updateCurrentWindow(defaultWindow_);
+
 	return 0;
 }
 
 /**
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
-void Af::prepare([[maybe_unused]] IPAContext &context, [[maybe_unused]] rkisp1_params_cfg *params)
+void Af::prepare([[maybe_unused]] IPAContext &context, rkisp1_params_cfg *params)
 {
+	if (updateAfwindow_) {
+		params->meas.afc_config.num_afm_win = 1;
+		params->meas.afc_config.thres = 128;
+		params->meas.afc_config.var_shift = 4;
+		/* \todo Allow setting thres and var_shift in tuning file */
+
+		params->meas.afc_config.afm_win[0] = rectangleToIspWindow(currentWindow_);
+
+		params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_AFC;
+		params->module_ens |= RKISP1_CIF_ISP_MODULE_AFC;
+		params->module_en_update |= RKISP1_CIF_ISP_MODULE_AFC;
+
+		updateAfwindow_ = false;
+	}
 }
 
 /**
@@ -55,14 +89,42 @@  void Af::process(IPAContext &context,
 	context.frameContext.af.focus = lensPosition;
 }
 
-void Af::setMetering([[maybe_unused]] controls::AfMeteringEnum metering)
+void Af::setMetering(controls::AfMeteringEnum metering)
 {
-	LOG(RkISP1Af, Error) << __FUNCTION__ << " not implemented!";
+	if (metering == meteringMode_)
+		return;
+
+	if (metering == controls::AfMeteringWindows) {
+		updateCurrentWindow(userWindow_);
+	} else {
+		updateCurrentWindow(defaultWindow_);
+	}
+
+	meteringMode_ = metering;
+}
+
+void Af::setWindows(Span<const Rectangle> windows)
+{
+	if (windows.size() != 1) {
+		LOG(RkISP1Af, Error) << "Only one AF window is supported";
+		return;
+	}
+
+	/* \todo Check if window size is valid for ISP */
+
+	LOG(RkISP1Af, Debug) << "setWindows: " << userWindow_;
+
+	userWindow_ = windows[0];
+
+	if (meteringMode_ == controls::AfMeteringWindows) {
+		updateCurrentWindow(userWindow_);
+	}
 }
 
-void Af::setWindows([[maybe_unused]] Span<const Rectangle> windows)
+void Af::updateCurrentWindow(const Rectangle &window)
 {
-	LOG(RkISP1Af, Error) << __FUNCTION__ << " not implemented!";
+	currentWindow_ = window;
+	updateAfwindow_ = true;
 }
 
 REGISTER_IPA_ALGORITHM(Af, "Af")
diff --git a/src/ipa/rkisp1/algorithms/af.h b/src/ipa/rkisp1/algorithms/af.h
index c470c9b2..c709ee98 100644
--- a/src/ipa/rkisp1/algorithms/af.h
+++ b/src/ipa/rkisp1/algorithms/af.h
@@ -27,6 +27,15 @@  public:
 
 	void setMetering(controls::AfMeteringEnum metering) override;
 	void setWindows(Span<const Rectangle> windows) override;
+
+private:
+	void updateCurrentWindow(const Rectangle &window);
+
+	controls::AfMeteringEnum meteringMode_ = controls::AfMeteringAuto;
+	Rectangle currentWindow_;
+	Rectangle defaultWindow_;
+	Rectangle userWindow_;
+	bool updateAfwindow_ = false;
 };
 
 } /* namespace libcamera::ipa::rkisp1::algorithms */
diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index 53b53f12..99ac1fb7 100644
--- a/src/ipa/rkisp1/rkisp1.cpp
+++ b/src/ipa/rkisp1/rkisp1.cpp
@@ -319,6 +319,26 @@  void IPARkISP1::queueRequest([[maybe_unused]] const uint32_t frame,
 			af->setMode(static_cast<controls::AfModeEnum>(ctrlValue.get<int32_t>()));
 			break;
 		}
+		case controls::AF_METERING: {
+			Af *af = getAlgorithm<Af>();
+			if (!af) {
+				LOG(IPARkISP1, Warning) << "Could not set AF_WINDOWS - no AF algorithm";
+				break;
+			}
+
+			af->setMetering(static_cast<controls::AfMeteringEnum>(ctrlValue.get<int32_t>()));
+			break;
+		}
+		case controls::AF_WINDOWS: {
+			Af *af = getAlgorithm<Af>();
+			if (!af) {
+				LOG(IPARkISP1, Warning) << "Could not set AF_WINDOWS - no AF algorithm";
+				break;
+			}
+
+			af->setWindows(ctrlValue.get<Span<const Rectangle>>());
+			break;
+		}
 		case controls::AF_TRIGGER: {
 			Af *af = getAlgorithm<Af>();
 			if (!af) {
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index 99d66b1d..7ab03057 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -961,6 +961,8 @@  int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor)
 	ControlInfoMap::Map ctrls({
 		{ &controls::AeEnable, ControlInfo(false, true) },
 		{ &controls::AfMode, ControlInfo(controls::AfModeValues) },
+		{ &controls::AfMetering, ControlInfo(controls::AfMeteringValues) },
+		{ &controls::AfWindows, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535), Rectangle{}) },
 		{ &controls::AfTrigger, ControlInfo(controls::AfTriggerValues) },
 		{ &controls::AfPause, ControlInfo(controls::AfPauseValues) }
 	});