[v1,2/4] ipa: rkisp1: dpf: Implement manual noise reduction mode
diff mbox series

Message ID 20260208174450.416314-3-rui.wang@ideasonboard.com
State New
Headers show
Series
  • dpf_manual_patch_v1
Related show

Commit Message

Rui Wang Feb. 8, 2026, 5:44 p.m. UTC
Support manual control of the Denoise Pre-Filter (DPF) parameters.

- When the manual noise reduction mode is selected, apply the control
values to the DPF configuration and enable the hardware block if
requested.
- DPF register values can be applied manually from controls.
Register the DPF vendor controls with appropriate limits and defaults.

Signed-off-by: Rui Wang <rui.wang@ideasonboard.com>
---
 src/ipa/rkisp1/algorithms/dpf.cpp | 116 +++++++++++++++++++++++++++++-
 src/ipa/rkisp1/algorithms/dpf.h   |   1 +
 2 files changed, 116 insertions(+), 1 deletion(-)

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp
index df6bef87..c232f2ad 100644
--- a/src/ipa/rkisp1/algorithms/dpf.cpp
+++ b/src/ipa/rkisp1/algorithms/dpf.cpp
@@ -135,6 +135,49 @@  void Dpf::registerControls(IPAContext &context)
 	 */
 	context.ctrlMap[&controls::draft::NoiseReductionMode] =
 		ControlInfo(modes, activeMode_->modeValue);
+	if (noiseReductionModes_.empty())
+		return;
+	/* if active mode is setted, set active mode config to control map
+	   else set first mode config to control map
+	*/
+	const ModeConfig *config = nullptr;
+	if (activeMode_->modeValue != controls::draft::NoiseReductionModeOff)
+		config = &(*activeMode_);
+	else
+		config = &noiseReductionModes_[0];
+	/* Set the default enable value to the active mode */
+	context.ctrlMap[&controls::rkisp1::DpfEnable] = ControlInfo(0, 1, config->modeValue == controls::draft::NoiseReductionModeOff ? 0 : 1);
+
+	std::array<int32_t, 3> strengthDefault = {
+		static_cast<int32_t>(config->strength.r),
+		static_cast<int32_t>(config->strength.g),
+		static_cast<int32_t>(config->strength.b)
+	};
+	context.ctrlMap[&controls::rkisp1::DpfChannelStrengths] =
+		ControlInfo(1, 255, Span<const int32_t, 3>(strengthDefault));
+
+	std::array<int32_t, RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS> greenCoeffs;
+	std::copy(std::begin(config->dpf.g_flt.spatial_coeff), std::end(config->dpf.g_flt.spatial_coeff), greenCoeffs.begin());
+	context.ctrlMap[&controls::rkisp1::DpfGreenSpatialCoefficients] =
+		ControlInfo(0, 16, Span<const int32_t, RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS>(greenCoeffs));
+
+	context.ctrlMap[&controls::rkisp1::DpfRedBlueFilterSize] =
+		ControlInfo(controls::rkisp1::DpfRedBlueFilterSizeValues,
+			    ControlValue(static_cast<int32_t>(config->dpf.rb_flt.fltsize)));
+
+	std::array<int32_t, RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS> redBlueCoeffs;
+	std::copy(std::begin(config->dpf.rb_flt.spatial_coeff), std::end(config->dpf.rb_flt.spatial_coeff), redBlueCoeffs.begin());
+	context.ctrlMap[&controls::rkisp1::DpfRedBlueSpatialCoefficients] =
+		ControlInfo(0, 16, Span<const int32_t, RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS>(redBlueCoeffs));
+
+	std::array<int32_t, RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS> nllCoeffs;
+	std::copy(std::begin(config->dpf.nll.coeff), std::end(config->dpf.nll.coeff), nllCoeffs.begin());
+	context.ctrlMap[&controls::rkisp1::DpfNoiseLevelLookupCoefficients] =
+		ControlInfo(1, 1023, Span<const int32_t, RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS>(nllCoeffs));
+
+	context.ctrlMap[&controls::rkisp1::DpfNoiseLevelLookupScaleMode] =
+		ControlInfo(controls::rkisp1::DpfNoiseLevelLookupScaleModeValues,
+			    ControlValue(static_cast<int32_t>(config->dpf.nll.scale_mode)));
 }
 
 int Dpf::parseSingleConfig(const YamlObject &tuningData,
@@ -339,7 +382,8 @@  void Dpf::queueRequest(IPAContext &context,
 	bool update = false;
 
 	const auto &denoise = controls.get(controls::draft::NoiseReductionMode);
-	if (denoise) {
+	/* only update denoise mode when it has changed */
+	if (denoise && activeMode_->modeValue != *denoise) {
 		switch (*denoise) {
 		case controls::draft::NoiseReductionModeOff:
 			if (dpf.denoise) {
@@ -351,6 +395,7 @@  void Dpf::queueRequest(IPAContext &context,
 		case controls::draft::NoiseReductionModeHighQuality:
 		case controls::draft::NoiseReductionModeFast:
 		case controls::draft::NoiseReductionModeZSL:
+		case controls::draft::NoiseReductionModeManual:
 			if (loadConfig(*denoise)) {
 				update = true;
 				dpf.denoise = true;
@@ -365,6 +410,24 @@  void Dpf::queueRequest(IPAContext &context,
 		if (update)
 			LOG(RkISP1Dpf, Debug) << "Set denoise to " << *denoise;
 	}
+	/* handle manual mode, collect all dpf config from controls */
+	if (activeMode_->modeValue == controls::draft::NoiseReductionModeManual) {
+		/*
+		 * In manual mode, if DpfEnable is present and true, we enable DPF.
+		 * If DpfEnable is present and false, we disable DPF.
+		 * If DpfEnable is not present, we keep the previous state (or default).
+		 */
+		const auto &enable = controls.get(controls::rkisp1::DpfEnable);
+		if (*enable) {
+			dpf.denoise = true;
+			update = true;
+		}
+		bool ret = parseControls(controls);
+		if (!ret) {
+			LOG(RkISP1Dpf, Error) << "Failed to collect manual overrides";
+			return;
+		}
+	}
 
 	frameContext.dpf.denoise = dpf.denoise;
 	frameContext.dpf.update = update;
@@ -437,6 +500,57 @@  void Dpf::prepareEnabledMode(IPAContext &context, IPAFrameContext &frameContext,
 		logConfig(frameContext, *config, *strengthConfig);
 }
 
+bool Dpf::parseControls(const ControlList &controls)
+{
+	/*
+	 * activeMode_ is a const_iterator, so we need to find the mutable element
+	 * in noiseReductionModes_, and parse the controls values into manualMode
+	 * config
+	 */
+	const auto it = std::find_if(noiseReductionModes_.begin(), noiseReductionModes_.end(),
+				     [](const ModeConfig &mode) {
+					     return mode.modeValue == controls::draft::NoiseReductionModeManual;
+				     });
+
+	if (it == noiseReductionModes_.end()) {
+		LOG(RkISP1Dpf, Error) << "Manual mode not found in configuration";
+		return false;
+	}
+
+	ModeConfig &config = *it;
+
+	if (const auto &c = controls.get(controls::rkisp1::DpfGreenSpatialCoefficients); c)
+		if (c->size() == RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS)
+			std::copy(c->begin(), c->end(), std::begin(config.dpf.g_flt.spatial_coeff));
+
+	config.dpf.rb_flt.r_enable = true;
+	config.dpf.rb_flt.b_enable = true;
+
+	if (const auto &c = controls.get(controls::rkisp1::DpfRedBlueSpatialCoefficients); c) {
+		if (c->size() == RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS || c->size() == RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - 1)
+			std::copy(c->begin(), c->end(), std::begin(config.dpf.rb_flt.spatial_coeff));
+	}
+
+	if (const auto &c = controls.get(controls::rkisp1::DpfRedBlueFilterSize); c)
+		config.dpf.rb_flt.fltsize = *c;
+
+	if (const auto &c = controls.get(controls::rkisp1::DpfNoiseLevelLookupCoefficients); c)
+		if (c->size() == RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS)
+			std::copy(c->begin(), c->end(), std::begin(config.dpf.nll.coeff));
+
+	if (const auto &c = controls.get(controls::rkisp1::DpfNoiseLevelLookupScaleMode); c)
+		config.dpf.nll.scale_mode = *c;
+
+	if (const auto &c = controls.get(controls::rkisp1::DpfChannelStrengths); c)
+		if (c->size() == 3) {
+			config.strength.r = (*c)[0];
+			config.strength.g = (*c)[1];
+			config.strength.b = (*c)[2];
+		}
+
+	return true;
+}
+
 REGISTER_IPA_ALGORITHM(Dpf, "Dpf")
 
 } /* namespace ipa::rkisp1::algorithms */
diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h
index 66d3f302..e3dea97b 100644
--- a/src/ipa/rkisp1/algorithms/dpf.h
+++ b/src/ipa/rkisp1/algorithms/dpf.h
@@ -41,6 +41,7 @@  private:
 	int parseSingleConfig(const YamlObject &tuningData,
 			      rkisp1_cif_isp_dpf_config &config,
 			      rkisp1_cif_isp_dpf_strength_config &strengthConfig);
+	bool parseControls(const ControlList &controls);
 
 	bool loadConfig(int32_t mode);
 	void logConfig(const IPAFrameContext &frameContext,