diff --git a/src/ipa/rkisp1/algorithms/denoise.h b/src/ipa/rkisp1/algorithms/denoise.h
index 660f648b..ffe27af8 100644
--- a/src/ipa/rkisp1/algorithms/denoise.h
+++ b/src/ipa/rkisp1/algorithms/denoise.h
@@ -22,6 +22,7 @@ protected:
 	~DenoiseBaseAlgorithm() = default;
 	virtual void setDevMode(bool dev) { devMode_ = dev; }
 	virtual bool isDevMode() const { return devMode_; }
+
 	virtual uint32_t computeExposureIndex(const IPAContext &context,
 					      const IPAFrameContext &frameContext) const;
 	template<typename LevelContainer>
@@ -31,6 +32,9 @@ protected:
 	{
 		return true;
 	}
+	virtual void collectManualOverrides([[maybe_unused]] const ControlList &controls)
+	{
+	}
 	virtual void handleReductionModeControl([[maybe_unused]] const ControlList &controls,
 						[[maybe_unused]] IPAFrameContext &frameContext,
 						[[maybe_unused]] IPAContext &context,
@@ -39,7 +43,6 @@ protected:
 	}
 	virtual int32_t getRunningMode() const { return currentRunMode_; }
 	virtual void setRunningMode(int32_t mode) { currentRunMode_ = mode; }
-
 private:
 	/**< Developer mode state for advanced controls */
 	bool devMode_ = false;
diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp
index c006fb5c..2d7d6414 100644
--- a/src/ipa/rkisp1/algorithms/dpf.cpp
+++ b/src/ipa/rkisp1/algorithms/dpf.cpp
@@ -358,6 +358,72 @@ void Dpf::loadReductionModeConfig(IPAFrameContext &frameContext)
 	strengthConfig_ = it->strength;
 	frameContext.dpf.update = true;
 }
+
+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())
+		return;
+
+	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
  */
diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h
index 928e79d9..4cbd7414 100644
--- a/src/ipa/rkisp1/algorithms/dpf.h
+++ b/src/ipa/rkisp1/algorithms/dpf.h
@@ -35,6 +35,20 @@ private:
 	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 ExposureIndexLevelConfig {
 		uint32_t maxExposureIndex; /* inclusive upper bound */
 		struct rkisp1_cif_isp_dpf_config dpf;
@@ -45,6 +59,14 @@ private:
 		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<ExposureIndexLevelConfig> exposureIndexLevels_;
 	std::vector<ModeConfig> modes_;
@@ -56,6 +78,7 @@ private:
 					IPAContext &context,
 					uint32_t frame) override;
 	void loadReductionModeConfig(IPAFrameContext &frameContext);
+	void collectManualOverrides(const ControlList &controls) override;
 	bool parseConfig(const YamlObject &tuningData) override;
 	bool parseSingleConfig(const YamlObject &tuningData,
 			       rkisp1_cif_isp_dpf_config &config,
diff --git a/src/libcamera/control_ids_rkisp1.yaml b/src/libcamera/control_ids_rkisp1.yaml
index 3e008ee4..bfd59925 100644
--- a/src/libcamera/control_ids_rkisp1.yaml
+++ b/src/libcamera/control_ids_rkisp1.yaml
@@ -70,4 +70,75 @@ controls:
           value: 3
           description: |
             Reduction mode - uses predefined noise reduction settings from tuning data.
+  
+  - 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 / exposure index 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.
+
+  - ExposureGainIndex:
+      type: int32_t
+      direction: out
+      description: |
+        Estimated scene exposure gain index used for Denoise tuning selection. Derived
+        from analogue gain (approx index = gain * 100). Provided each frame
+        for client awareness and debugging. Range 0..409600.
+
 ...
