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.
+
 ...
