[v1,10/16] ipa: rkisp1: algorithms: dpf: collect DPF manual overrides
diff mbox series

Message ID 20251028170847.2673396-10-rui.wang@ideasonboard.com
State New
Headers show
Series
  • [v1,01/16] ipa: rkisp1: algorithms: add Denoise base class shell
Related show

Commit Message

Rui Wang Oct. 28, 2025, 5:08 p.m. UTC
Implement collectManualOverrides() to capture strength and developer-mode
override arrays from control requests. Extend queueRequest() to collect
overrides in manual mode and mark frames dirty when strength values differ
from the active configuration.

Developer mode controls (spatial coefficients, filter size, NLL tables)
are only collected when devmode is enabled. The function populates the
overrides_ structure which will be applied during prepare().

Signed-off-by: Rui Wang <rui.wang@ideasonboard.com>
---
 src/ipa/rkisp1/algorithms/denoise.h   |  1 +
 src/ipa/rkisp1/algorithms/dpf.cpp     | 58 +++++++++++++++++++++++++
 src/ipa/rkisp1/algorithms/dpf.h       | 30 +++++++++++++
 src/libcamera/control_ids_rkisp1.yaml | 62 +++++++++++++++++++++++++++
 4 files changed, 151 insertions(+)

Patch
diff mbox series

diff --git a/src/ipa/rkisp1/algorithms/denoise.h b/src/ipa/rkisp1/algorithms/denoise.h
index 5bc3f941..1a874def 100644
--- a/src/ipa/rkisp1/algorithms/denoise.h
+++ b/src/ipa/rkisp1/algorithms/denoise.h
@@ -38,6 +38,7 @@  protected:
 	int selectIsoBand(unsigned iso, const LevelContainer &levels) const;
 	virtual bool parseConfig(const YamlObject &tuningData) = 0;
 	virtual void handleEnableControl(const ControlList &controls, IPAFrameContext &frameContext, IPAContext &context) = 0;
+	virtual void collectManualOverrides(const ControlList &controls) = 0;
 
 private:
 	bool manualMode_ = false; /**< Current manual/auto mode state */
diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp
index d0bed3e4..145f10b7 100644
--- a/src/ipa/rkisp1/algorithms/dpf.cpp
+++ b/src/ipa/rkisp1/algorithms/dpf.cpp
@@ -243,6 +243,53 @@  void Dpf::handleEnableControl(const ControlList &controls, IPAFrameContext &fram
 	frameContext.dpf.denoise = enableDpf_;
 }
 
+void Dpf::collectManualOverrides(const ControlList &controls)
+{
+	if (const auto &c = controls.get(controls::rkisp1::DpfChannelStrengths); c) {
+		if (c->size() == 3) {
+			overrides_.strength = DpfStrengthSettings{ static_cast<uint16_t>((*c)[0]), static_cast<uint16_t>((*c)[1]), static_cast<uint16_t>((*c)[2]) };
+		}
+	}
+	if (isDevMode()) {
+		if (const auto &c = controls.get(controls::rkisp1::DpfGreenSpatialCoefficients); c) {
+			if (c->size() == RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS) {
+				DpfSpatialGreenSettings green;
+				std::copy_n(c->begin(), RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS, green.coeffs.begin());
+				overrides_.spatialGreen = green;
+			}
+		}
+		if (const auto &c = controls.get(controls::rkisp1::DpfRedBlueSpatialCoefficients); c) {
+			if (c->size() == RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS) {
+				DpfSpatialRbSettings rb;
+				std::copy_n(c->begin(), RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS, rb.coeffs.begin());
+				rb.size = (config_.rb_flt.fltsize == RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9) ? 1 : 0;
+				overrides_.spatialRb = rb;
+			}
+		}
+		if (const auto &c = controls.get(controls::rkisp1::DpfRbFilterSize); c) {
+			overrides_.rbSize = *c ? 1 : 0;
+		}
+		if (const auto &c = controls.get(controls::rkisp1::DpfNoiseLevelLookupCoefficients); c) {
+			if (c->size() == RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS) {
+				DpfNllSettings nll;
+				std::copy_n(c->begin(), RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS, nll.coeffs.begin());
+				nll.scaleMode = (config_.nll.scale_mode == RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC) ? 1 : 0;
+				overrides_.nll = nll;
+			}
+		}
+		if (const auto &c = controls.get(controls::rkisp1::DpfNoiseLevelLookupScaleMode); c) {
+			if (overrides_.nll) {
+				overrides_.nll->scaleMode = *c ? 1 : 0;
+			} else {
+				DpfNllSettings nll;
+				std::copy_n(std::begin(config_.nll.coeff), RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS, nll.coeffs.begin());
+				nll.scaleMode = *c ? 1 : 0;
+				overrides_.nll = nll;
+			}
+		}
+	}
+}
+
 /**
  * \copydoc libcamera::ipa::Algorithm::queueRequest
  */
@@ -253,6 +300,17 @@  void Dpf::queueRequest(IPAContext &context,
 {
 	frameContext.dpf.update = false;
 	handleEnableControl(controls, frameContext, context);
+
+	if (isManualMode()) {
+		collectManualOverrides(controls);
+		// Check if manual overrides have changed and trigger update
+		if (overrides_.strength &&
+		    (overrides_.strength->r != strengthConfig_.r ||
+		     overrides_.strength->g != strengthConfig_.g ||
+		     overrides_.strength->b != strengthConfig_.b)) {
+			frameContext.dpf.update = true;
+		}
+	}
 }
 
 /**
diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h
index c01f711c..1a33a8c4 100644
--- a/src/ipa/rkisp1/algorithms/dpf.h
+++ b/src/ipa/rkisp1/algorithms/dpf.h
@@ -34,23 +34,53 @@  public:
 private:
 	struct rkisp1_cif_isp_dpf_config config_ {
 	};
+
 	struct rkisp1_cif_isp_dpf_strength_config strengthConfig_ {
 	};
+
 	struct rkisp1_cif_isp_dpf_config baseConfig_ {
 	};
+
 	struct rkisp1_cif_isp_dpf_strength_config baseStrengthConfig_ {
 	};
+
+	struct DpfStrengthSettings {
+		uint16_t r, g, b;
+	};
+
+	struct DpfSpatialGreenSettings {
+		std::array<uint8_t, RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS> coeffs;
+	};
+
+	struct DpfSpatialRbSettings {
+		std::array<uint8_t, RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS> coeffs;
+		uint8_t size; // 0=9x9, 1=13x9
+	};
+
+	struct DpfNllSettings {
+		std::array<uint16_t, RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS> coeffs;
+		uint8_t scaleMode; // 0 linear, 1 log
+	};
 	struct IsoLevelConfig {
 		unsigned int maxIso; /* inclusive upper bound */
 		struct rkisp1_cif_isp_dpf_config dpf;
 		struct rkisp1_cif_isp_dpf_strength_config strength;
 	};
+	struct Overrides {
+		std::optional<DpfStrengthSettings> strength;
+		std::optional<DpfSpatialGreenSettings> spatialGreen;
+		std::optional<DpfSpatialRbSettings> spatialRb;
+		std::optional<uint8_t> rbSize;
+		std::optional<DpfNllSettings> nll;
+		void clear() { *this = Overrides{}; }
+	} overrides_;
 
 	std::vector<IsoLevelConfig> isoLevels_;
 	bool useIsoLevels_ = false;
 	bool enableDpf_ = true; /* YAML master enable */
 
 	void handleEnableControl(const ControlList &controls, IPAFrameContext &frameContext, IPAContext &context) override;
+	void collectManualOverrides(const ControlList &controls) override;
 	bool parseConfig(const YamlObject &tuningData) override;
 	bool parseSingleConfig(const YamlObject &config,
 			       rkisp1_cif_isp_dpf_config &cfg,
diff --git a/src/libcamera/control_ids_rkisp1.yaml b/src/libcamera/control_ids_rkisp1.yaml
index 2f29d508..bf7875e9 100644
--- a/src/libcamera/control_ids_rkisp1.yaml
+++ b/src/libcamera/control_ids_rkisp1.yaml
@@ -21,4 +21,66 @@  controls:
 
         Reported in metadata as a boolean.
 
+  - DpfChannelStrengths:
+      type: int32_t
+      direction: inout
+      description: |
+        Override filter strength for R,G,B channels. Values map to hardware
+        strength registers (0..255 typical). Size must be exactly 3 when set.
+        Order: R,G,B. If unset the tuning / ISO level derived strengths apply.
+      size: [3]
+
+  - DpfGreenSpatialCoefficients:
+      type: int32_t
+      direction: inout
+      description: |
+        Override 9x9 green spatial kernel coefficients (6 values). Order must
+        follow tuning file convention. Each value 0..63 typical. All 6 required
+        when provided; otherwise ignored.
+      size: [6]
+
+  - DpfRedBlueSpatialCoefficients:
+      type: int32_t
+      direction: inout
+      description: |
+        Override Red/Blue spatial kernel coefficients (6 values). Applies to
+        either 9x9 or 13x9 depending on DpfRbFilterSize. For 9x9 the last
+        column pair is dropped in hardware. Values 0..63 typical.
+      size: [6]
+
+  - DpfRbFilterSize:
+      type: int32_t
+      direction: inout
+      description: |
+        Override RB spatial filter size selection.
+      enum:
+        - name: DpfRbFilterSize9x9
+          value: 0
+          description: Use 9x9 RB domain filter.
+        - name: DpfRbFilterSize13x9
+          value: 1
+          description: Use 13x9 RB domain filter (if coefficients valid).
+
+  - DpfNoiseLevelLookupCoefficients:
+      type: int32_t
+      direction: inout
+      description: |
+        Override Noise Level Lookup (NLL) piecewise-linear coefficients
+        (17 values). Must supply full set when used or override is ignored.
+      size: [17]
+
+  - DpfNoiseLevelLookupScaleMode:
+      type: int32_t
+      direction: inout
+      description: |
+        Override NLL scale mode (0=linear,1=logarithmic). Matches hardware
+        RKISP1_CIF_ISP_NLL_SCALE_* constants.
+      enum:
+        - name: DpfNoiseLevelLookupScaleLinear
+          value: 0
+          description: Linear scale.
+        - name: DpfNoiseLevelLookupScaleLogarithmic
+          value: 1
+          description: Logarithmic scale.
+
 ...