[{"id":37686,"web_url":"https://patchwork.libcamera.org/comment/37686/","msgid":"<aWn9S8fgJG2a6Iy3@zed>","date":"2026-01-16T09:21:52","subject":"Re: [PATCH v8 2/7] ipa: rkisp1: algorithms: dpf: Implement mode\n\tswitching","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Rui\n\nOn Thu, Jan 15, 2026 at 11:33:13AM -0500, Rui Wang wrote:\n> Add support for switching between different noise reduction modes.\n>\n> Introduce `noiseReductionModes_` to store mode-specific configs.\n>\n> LoadReductionConfig() select specific config from configs.\n>\n> Signed-off-by: Rui Wang <rui.wang@ideasonboard.com>\n> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n>\n> ---\n> changelog since v5:\n>  - Update log verbos from Info to Debug in loadReductionConfig\n>  - Update log mode value to string to in loadReductionConfig\n>  - improving the return value changed like :\n>        if (ret != 0)  -> if (ret)\n>\n>  Reviewed-by tags from v5 are carried over (no function changes).\n> changelog since v6:\n>  - add { controls::draft::NoiseReductionModeOff, \"off\" }, to fix\n>    out_of_range issue\n>\n> changelog since v7:\n>  - Delete base config parse from parseConfig\n> ---\n>  src/ipa/rkisp1/algorithms/dpf.cpp | 90 +++++++++++++++++++++++++++----\n>  src/ipa/rkisp1/algorithms/dpf.h   | 11 ++++\n>  2 files changed, 92 insertions(+), 9 deletions(-)\n>\n> diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp\n> index dd3effa1..9b663831 100644\n> --- a/src/ipa/rkisp1/algorithms/dpf.cpp\n> +++ b/src/ipa/rkisp1/algorithms/dpf.cpp\n> @@ -8,6 +8,7 @@\n>  #include \"dpf.h\"\n>\n>  #include <algorithm>\n> +#include <map>\n>  #include <string>\n>  #include <vector>\n>\n> @@ -36,8 +37,21 @@ namespace ipa::rkisp1::algorithms {\n>\n>  LOG_DEFINE_CATEGORY(RkISP1Dpf)\n>\n> +namespace {\n> +\n> +const std::map<int32_t, std::string> kModesMap = {\n> +\t{ controls::draft::NoiseReductionModeMinimal, \"minimal\" },\n> +\t{ controls::draft::NoiseReductionModeFast, \"fast\" },\n> +\t{ controls::draft::NoiseReductionModeHighQuality, \"highquality\" },\n> +\t{ controls::draft::NoiseReductionModeZSL, \"zsl\" },\n> +\t{ controls::draft::NoiseReductionModeOff, \"off\" },\n> +};\n> +\n> +} /* namespace */\n> +\n>  Dpf::Dpf()\n> -\t: config_({}), strengthConfig_({})\n> +\t: config_({}), strengthConfig_({}), noiseReductionModes_({}),\n> +\t  runningMode_(controls::draft::NoiseReductionModeOff)\n>  {\n>  }\n>\n> @@ -57,10 +71,43 @@ int Dpf::init([[maybe_unused]] IPAContext &context,\n>\n>  int Dpf::parseConfig(const YamlObject &tuningData)\n>  {\n> -\t/* Parse base config. */\n> -\tint ret = parseSingleConfig(tuningData, config_, strengthConfig_);\n> -\tif (ret)\n> -\t\treturn ret;\n> +\t/* Parse modes. */\n> +\treturn parseModes(tuningData);\n\nThis should be called by init() removing the need for parseConfig() as\nsuggested in the review of the previous patch\n\n> +}\n> +\n> +int Dpf::parseModes(const YamlObject &tuningData)\n> +{\n> +\t/* Parse noise reduction modes. */\n> +\tif (!tuningData.contains(\"modes\"))\n\nShould we LOG(Error) now that modes are mandatory ?\n\n> +\t\treturn -EINVAL;\n> +\n> +\tnoiseReductionModes_.clear();\n> +\tfor (const auto &entry : tuningData[\"modes\"].asList()) {\n> +\t\tstd::optional<std::string> typeOpt =\n> +\t\t\tentry[\"type\"].get<std::string>();\n> +\t\tif (!typeOpt) {\n> +\t\t\tLOG(RkISP1Dpf, Error) << \"Modes entry missing type\";\n> +\t\t\treturn -EINVAL;\n> +\t\t}\n> +\n> +\t\tModeConfig mode;\n> +\t\tauto it = std::find_if(kModesMap.begin(), kModesMap.end(),\n> +\t\t\t\t       [&typeOpt](const auto &pair) {\n> +\t\t\t\t\t       return pair.second == *typeOpt;\n> +\t\t\t\t       });\n> +\n> +\t\tif (it == kModesMap.end()) {\n> +\t\t\tLOG(RkISP1Dpf, Error) << \"Unknown mode type: \" << *typeOpt;\n> +\t\t\treturn -EINVAL;\n> +\t\t}\n> +\n> +\t\tmode.modeValue = it->first;\n> +\t\tauto ret = parseSingleConfig(entry, mode.dpf, mode.strength);\n\n                int ret;\n\nauto gives you nothing here\n\n> +\t\tif (ret)\n> +\t\t\treturn ret;\n> +\n> +\t\tnoiseReductionModes_.push_back(mode);\n\nI think it was pointed out already in the previous versions: you\nshould populate context.ctrlMap[controls::draft::NoiseReductionMode]\nwith one entry for each supported mode.\n\nSee https://git.libcamera.org/libcamera/libcamera.git/tree/src/ipa/rkisp1/algorithms/agc.cpp#n76\n\nWill it happen later on in the series and I've missed it ?\n\n\n> +\t}\n>\n>  \treturn 0;\n>  }\n> @@ -193,6 +240,28 @@ int Dpf::parseSingleConfig(const YamlObject &tuningData,\n>  \treturn 0;\n>  }\n>\n> +bool Dpf::loadReductionConfig(int32_t mode)\n\n             loadModeConfig(int32_t mode)\n\n> +{\n> +\tauto it = std::find_if(noiseReductionModes_.begin(), noiseReductionModes_.end(),\n> +\t\t\t       [mode](const ModeConfig &m) {\n> +\t\t\t\t       return m.modeValue == mode;\n> +\t\t\t       });\n> +\tif (it == noiseReductionModes_.end()) {\n> +\t\tLOG(RkISP1Dpf, Warning)\n> +\t\t\t<< \"No DPF config for reduction mode: \" << kModesMap.at(mode);\n\t\t\t<< \"No DPF config for mode: \" << kModesMap.at(mode);\n\n\n> +\t\treturn false;\n> +\t}\n> +\n> +\tconfig_ = it->dpf;\n> +\tstrengthConfig_ = it->strength;\n\nSo now the config_ and strengthConfig_ member variables point to the\n'active' mode configuration. Why are you copying them instead of just\nkeeping a pointer to the active mode in noiseReductionModes_ ?\n\n> +\n> +\tLOG(RkISP1Dpf, Debug)\n> +\t\t<< \"DPF mode=Reduction (config loaded)\"\n> +\t\t<< \" mode=\" << kModesMap.at(mode);\n\n                   \" mode = \"\n> +\n> +\treturn true;\n> +}\n> +\n>  /**\n>   * \\copydoc libcamera::ipa::Algorithm::queueRequest\n>   */\n> @@ -206,8 +275,6 @@ void Dpf::queueRequest(IPAContext &context,\n>\n>  \tconst auto &denoise = controls.get(controls::draft::NoiseReductionMode);\n>  \tif (denoise) {\n> -\t\tLOG(RkISP1Dpf, Debug) << \"Set denoise to \" << *denoise;\n> -\n>  \t\tswitch (*denoise) {\n>  \t\tcase controls::draft::NoiseReductionModeOff:\n>  \t\t\tif (dpf.denoise) {\n> @@ -218,9 +285,10 @@ void Dpf::queueRequest(IPAContext &context,\n>  \t\tcase controls::draft::NoiseReductionModeMinimal:\n>  \t\tcase controls::draft::NoiseReductionModeHighQuality:\n>  \t\tcase controls::draft::NoiseReductionModeFast:\n> -\t\t\tif (!dpf.denoise) {\n> -\t\t\t\tdpf.denoise = true;\n> +\t\tcase controls::draft::NoiseReductionModeZSL:\n> +\t\t\tif (loadReductionConfig(*denoise)) {\n>  \t\t\t\tupdate = true;\n> +\t\t\t\tdpf.denoise = true;\n>  \t\t\t}\n>  \t\t\tbreak;\n>  \t\tdefault:\n> @@ -229,6 +297,10 @@ void Dpf::queueRequest(IPAContext &context,\n>  \t\t\t\t<< *denoise;\n>  \t\t\tbreak;\n>  \t\t}\n> +\t\tif (update) {\n> +\t\t\trunningMode_ = *denoise;\n\nSo the member variable runningMode_ simply keeps track of the index of\nthe enabled mode, right ? And I see it only used in logConfig()\nintroduced in the next patch.\n\nIf you accept the above suggestion about keeping a\npointer/refernce/iterator to the active mode on the\nnoiseReductionModes_ vector instead of copying its content to config_\nand strengthConfig_ you can use the 'modeValue' index instead of\nduplicating the information in runnigMode_\n\n> +\t\t\tLOG(RkISP1Dpf, Debug) << \"Set denoise to \" << kModesMap.at(runningMode_);\n> +\t\t}\n>  \t}\n>\n>  \tframeContext.dpf.denoise = dpf.denoise;\n> diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h\n> index 39186c55..2a2c7052 100644\n> --- a/src/ipa/rkisp1/algorithms/dpf.h\n> +++ b/src/ipa/rkisp1/algorithms/dpf.h\n> @@ -30,13 +30,24 @@ public:\n>  \t\t     RkISP1Params *params) override;\n>\n>  private:\n> +\tstruct ModeConfig {\n> +\t\tint32_t modeValue;\n> +\t\trkisp1_cif_isp_dpf_config dpf;\n> +\t\trkisp1_cif_isp_dpf_strength_config strength;\n> +\t};\n> +\n>  \tint parseConfig(const YamlObject &tuningData);\n> +\tint parseModes(const YamlObject &tuningData);\n>  \tint parseSingleConfig(const YamlObject &tuningData,\n>  \t\t\t      rkisp1_cif_isp_dpf_config &config,\n>  \t\t\t      rkisp1_cif_isp_dpf_strength_config &strengthConfig);\n>\n> +\tbool loadReductionConfig(int32_t mode);\n> +\n>  \tstruct rkisp1_cif_isp_dpf_config config_;\n>  \tstruct rkisp1_cif_isp_dpf_strength_config strengthConfig_;\n> +\tstd::vector<ModeConfig> noiseReductionModes_;\n> +\tint32_t runningMode_;\n>  };\n>\n>  } /* namespace ipa::rkisp1::algorithms */\n> --\n> 2.43.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 52533BDCBF\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 16 Jan 2026 09:21:59 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 81CCB61FA3;\n\tFri, 16 Jan 2026 10:21:58 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8044A61A35\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 16 Jan 2026 10:21:56 +0100 (CET)","from ideasonboard.com (unknown\n\t[IPv6:2001:b07:6462:5de2:520d:d7a3:63ca:99e8])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 298D64B3;\n\tFri, 16 Jan 2026 10:21:28 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"JCXPK/UL\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768555288;\n\tbh=7Aqf34ij3OgAGku6TQv4y80a271zSB2fa+Y2rW6BDVg=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=JCXPK/ULYWl7GjcwEZBZ9SuspHJu03tzx/6WJCRfiTdic2EDdBWOk/9eJKiEkpu29\n\tVBP1fAcPefC3dkcZNOV9PEBxPoDrLqzUxLJTEcv1x1T9N5oRh7kmxkSqwzU5nFuA/C\n\tG4i8Dt9T/Xd+WjJqhaZySYuyNVJ+Vq6JatXGFUiI=","Date":"Fri, 16 Jan 2026 10:21:52 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Rui Wang <rui.wang@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org, \n\tJacopo Mondi <jacopo.mondi@ideasonboard.com>","Subject":"Re: [PATCH v8 2/7] ipa: rkisp1: algorithms: dpf: Implement mode\n\tswitching","Message-ID":"<aWn9S8fgJG2a6Iy3@zed>","References":"<20260115163318.1339354-1-rui.wang@ideasonboard.com>\n\t<20260115163318.1339354-3-rui.wang@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20260115163318.1339354-3-rui.wang@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37708,"web_url":"https://patchwork.libcamera.org/comment/37708/","msgid":"<45a05dcf-3551-47fb-b820-b53c16abd347@ideasonboard.com>","date":"2026-01-17T03:13:35","subject":"Re: [PATCH v8 2/7] ipa: rkisp1: algorithms: dpf: Implement mode\n\tswitching","submitter":{"id":241,"url":"https://patchwork.libcamera.org/api/people/241/","name":"Rui Wang","email":"rui.wang@ideasonboard.com"},"content":"On 2026-01-16 04:21, Jacopo Mondi wrote:\n> Hi Rui\n>\n> On Thu, Jan 15, 2026 at 11:33:13AM -0500, Rui Wang wrote:\n>> Add support for switching between different noise reduction modes.\n>>\n>> Introduce `noiseReductionModes_` to store mode-specific configs.\n>>\n>> LoadReductionConfig() select specific config from configs.\n>>\n>> Signed-off-by: Rui Wang <rui.wang@ideasonboard.com>\n>> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n>>\n>> ---\n>> changelog since v5:\n>>   - Update log verbos from Info to Debug in loadReductionConfig\n>>   - Update log mode value to string to in loadReductionConfig\n>>   - improving the return value changed like :\n>>         if (ret != 0)  -> if (ret)\n>>\n>>   Reviewed-by tags from v5 are carried over (no function changes).\n>> changelog since v6:\n>>   - add { controls::draft::NoiseReductionModeOff, \"off\" }, to fix\n>>     out_of_range issue\n>>\n>> changelog since v7:\n>>   - Delete base config parse from parseConfig\n>> ---\n>>   src/ipa/rkisp1/algorithms/dpf.cpp | 90 +++++++++++++++++++++++++++----\n>>   src/ipa/rkisp1/algorithms/dpf.h   | 11 ++++\n>>   2 files changed, 92 insertions(+), 9 deletions(-)\n>>\n>> diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp\n>> index dd3effa1..9b663831 100644\n>> --- a/src/ipa/rkisp1/algorithms/dpf.cpp\n>> +++ b/src/ipa/rkisp1/algorithms/dpf.cpp\n>> @@ -8,6 +8,7 @@\n>>   #include \"dpf.h\"\n>>\n>>   #include <algorithm>\n>> +#include <map>\n>>   #include <string>\n>>   #include <vector>\n>>\n>> @@ -36,8 +37,21 @@ namespace ipa::rkisp1::algorithms {\n>>\n>>   LOG_DEFINE_CATEGORY(RkISP1Dpf)\n>>\n>> +namespace {\n>> +\n>> +const std::map<int32_t, std::string> kModesMap = {\n>> +\t{ controls::draft::NoiseReductionModeMinimal, \"minimal\" },\n>> +\t{ controls::draft::NoiseReductionModeFast, \"fast\" },\n>> +\t{ controls::draft::NoiseReductionModeHighQuality, \"highquality\" },\n>> +\t{ controls::draft::NoiseReductionModeZSL, \"zsl\" },\n>> +\t{ controls::draft::NoiseReductionModeOff, \"off\" },\n>> +};\n>> +\n>> +} /* namespace */\n>> +\n>>   Dpf::Dpf()\n>> -\t: config_({}), strengthConfig_({})\n>> +\t: config_({}), strengthConfig_({}), noiseReductionModes_({}),\n>> +\t  runningMode_(controls::draft::NoiseReductionModeOff)\n>>   {\n>>   }\n>>\n>> @@ -57,10 +71,43 @@ int Dpf::init([[maybe_unused]] IPAContext &context,\n>>\n>>   int Dpf::parseConfig(const YamlObject &tuningData)\n>>   {\n>> -\t/* Parse base config. */\n>> -\tint ret = parseSingleConfig(tuningData, config_, strengthConfig_);\n>> -\tif (ret)\n>> -\t\treturn ret;\n>> +\t/* Parse modes. */\n>> +\treturn parseModes(tuningData);\n> This should be called by init() removing the need for parseConfig() as\n> suggested in the review of the previous patch\n\nI am thinking about  add parseActiveMode into parseConfig , and all YAML \nparsing into this function in future.\n\ncurrently it has only parseModes inside parseConfig.\n\n    - enableMode: ''\n\n>\n>> +}\n>> +\n>> +int Dpf::parseModes(const YamlObject &tuningData)\n>> +{\n>> +\t/* Parse noise reduction modes. */\n>> +\tif (!tuningData.contains(\"modes\"))\n> Should we LOG(Error) now that modes are mandatory ?\n>\n>> +\t\treturn -EINVAL;\n>> +\n>> +\tnoiseReductionModes_.clear();\n>> +\tfor (const auto &entry : tuningData[\"modes\"].asList()) {\n>> +\t\tstd::optional<std::string> typeOpt =\n>> +\t\t\tentry[\"type\"].get<std::string>();\n>> +\t\tif (!typeOpt) {\n>> +\t\t\tLOG(RkISP1Dpf, Error) << \"Modes entry missing type\";\n>> +\t\t\treturn -EINVAL;\n>> +\t\t}\n>> +\n>> +\t\tModeConfig mode;\n>> +\t\tauto it = std::find_if(kModesMap.begin(), kModesMap.end(),\n>> +\t\t\t\t       [&typeOpt](const auto &pair) {\n>> +\t\t\t\t\t       return pair.second == *typeOpt;\n>> +\t\t\t\t       });\n>> +\n>> +\t\tif (it == kModesMap.end()) {\n>> +\t\t\tLOG(RkISP1Dpf, Error) << \"Unknown mode type: \" << *typeOpt;\n>> +\t\t\treturn -EINVAL;\n>> +\t\t}\n>> +\n>> +\t\tmode.modeValue = it->first;\n>> +\t\tauto ret = parseSingleConfig(entry, mode.dpf, mode.strength);\n>                  int ret;\n>\n> auto gives you nothing here\n>\n>> +\t\tif (ret)\n>> +\t\t\treturn ret;\n>> +\n>> +\t\tnoiseReductionModes_.push_back(mode);\n> I think it was pointed out already in the previous versions: you\n> should populate context.ctrlMap[controls::draft::NoiseReductionMode]\n> with one entry for each supported mode.\n>\n> See https://git.libcamera.org/libcamera/libcamera.git/tree/src/ipa/rkisp1/algorithms/agc.cpp#n76\n>\n> Will it happen later on in the series and I've missed it ?\n>\nauto it = std::find_if(kModesMap.begin(), kModesMap.end(),\n\n[&typeOpt](const auto &pair) {\n\nreturn pair.second == *typeOpt;\n\n});\n\n\nkModesMap contains all NoiseReductionMode value . so I can traverse each mode in YAML\nand then add into  noiseReductionModes_.\n\n\n>> +\t}\n>>\n>>   \treturn 0;\n>>   }\n>> @@ -193,6 +240,28 @@ int Dpf::parseSingleConfig(const YamlObject &tuningData,\n>>   \treturn 0;\n>>   }\n>>\n>> +bool Dpf::loadReductionConfig(int32_t mode)\n>               loadModeConfig(int32_t mode)\n>\n>> +{\n>> +\tauto it = std::find_if(noiseReductionModes_.begin(), noiseReductionModes_.end(),\n>> +\t\t\t       [mode](const ModeConfig &m) {\n>> +\t\t\t\t       return m.modeValue == mode;\n>> +\t\t\t       });\n>> +\tif (it == noiseReductionModes_.end()) {\n>> +\t\tLOG(RkISP1Dpf, Warning)\n>> +\t\t\t<< \"No DPF config for reduction mode: \" << kModesMap.at(mode);\n> \t\t\t<< \"No DPF config for mode: \" << kModesMap.at(mode);\n>\n> will remove this 'reduction' in v9.\n>> +\t\treturn false;\n>> +\t}\n>> +\n>> +\tconfig_ = it->dpf;\n>> +\tstrengthConfig_ = it->strength;\n> So now the config_ and strengthConfig_ member variables point to the\n> 'active' mode configuration. Why are you copying them instead of just\n> keeping a pointer to the active mode in noiseReductionModes_ ?\ngood idea, Introduce a const interator to point active mode in\n\nnoiseReductionModes_ it can save strengthConfig_,config_, runningMode.\nwill implement in v9.\n\n>\n>> +\n>> +\tLOG(RkISP1Dpf, Debug)\n>> +\t\t<< \"DPF mode=Reduction (config loaded)\"\n>> +\t\t<< \" mode=\" << kModesMap.at(mode);\n>                     \" mode = \"\nwill update in v9.\n>> +\n>> +\treturn true;\n>> +}\n>> +\n>>   /**\n>>    * \\copydoc libcamera::ipa::Algorithm::queueRequest\n>>    */\n>> @@ -206,8 +275,6 @@ void Dpf::queueRequest(IPAContext &context,\n>>\n>>   \tconst auto &denoise = controls.get(controls::draft::NoiseReductionMode);\n>>   \tif (denoise) {\n>> -\t\tLOG(RkISP1Dpf, Debug) << \"Set denoise to \" << *denoise;\n>> -\n>>   \t\tswitch (*denoise) {\n>>   \t\tcase controls::draft::NoiseReductionModeOff:\n>>   \t\t\tif (dpf.denoise) {\n>> @@ -218,9 +285,10 @@ void Dpf::queueRequest(IPAContext &context,\n>>   \t\tcase controls::draft::NoiseReductionModeMinimal:\n>>   \t\tcase controls::draft::NoiseReductionModeHighQuality:\n>>   \t\tcase controls::draft::NoiseReductionModeFast:\n>> -\t\t\tif (!dpf.denoise) {\n>> -\t\t\t\tdpf.denoise = true;\n>> +\t\tcase controls::draft::NoiseReductionModeZSL:\n>> +\t\t\tif (loadReductionConfig(*denoise)) {\n>>   \t\t\t\tupdate = true;\n>> +\t\t\t\tdpf.denoise = true;\n>>   \t\t\t}\n>>   \t\t\tbreak;\n>>   \t\tdefault:\n>> @@ -229,6 +297,10 @@ void Dpf::queueRequest(IPAContext &context,\n>>   \t\t\t\t<< *denoise;\n>>   \t\t\tbreak;\n>>   \t\t}\n>> +\t\tif (update) {\n>> +\t\t\trunningMode_ = *denoise;\n> So the member variable runningMode_ simply keeps track of the index of\n> the enabled mode, right ? And I see it only used in logConfig()\n> introduced in the next patch.\n>\n> If you accept the above suggestion about keeping a\n> pointer/refernce/iterator to the active mode on the\n> noiseReductionModes_ vector instead of copying its content to config_\n> and strengthConfig_ you can use the 'modeValue' index instead of\n> duplicating the information in runnigMode_\n\nyes will add const_iterator activeMode_ to point noiseReductionModes_\n\n\n>\n>> +\t\t\tLOG(RkISP1Dpf, Debug) << \"Set denoise to \" << kModesMap.at(runningMode_);\n>> +\t\t}\n>>   \t}\n>>\n>>   \tframeContext.dpf.denoise = dpf.denoise;\n>> diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h\n>> index 39186c55..2a2c7052 100644\n>> --- a/src/ipa/rkisp1/algorithms/dpf.h\n>> +++ b/src/ipa/rkisp1/algorithms/dpf.h\n>> @@ -30,13 +30,24 @@ public:\n>>   \t\t     RkISP1Params *params) override;\n>>\n>>   private:\n>> +\tstruct ModeConfig {\n>> +\t\tint32_t modeValue;\n>> +\t\trkisp1_cif_isp_dpf_config dpf;\n>> +\t\trkisp1_cif_isp_dpf_strength_config strength;\n>> +\t};\n>> +\n>>   \tint parseConfig(const YamlObject &tuningData);\n>> +\tint parseModes(const YamlObject &tuningData);\n>>   \tint parseSingleConfig(const YamlObject &tuningData,\n>>   \t\t\t      rkisp1_cif_isp_dpf_config &config,\n>>   \t\t\t      rkisp1_cif_isp_dpf_strength_config &strengthConfig);\n>>\n>> +\tbool loadReductionConfig(int32_t mode);\n>> +\n>>   \tstruct rkisp1_cif_isp_dpf_config config_;\n>>   \tstruct rkisp1_cif_isp_dpf_strength_config strengthConfig_;\n>> +\tstd::vector<ModeConfig> noiseReductionModes_;\n>> +\tint32_t runningMode_;\n>>   };\n>>\n>>   } /* namespace ipa::rkisp1::algorithms */\n>> --\n>> 2.43.0\n>>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 36986C3226\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat, 17 Jan 2026 03:13:50 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6F98E61FBC;\n\tSat, 17 Jan 2026 04:13:49 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 88318615B2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 17 Jan 2026 04:13:48 +0100 (CET)","from [192.168.31.114] (unknown [209.216.103.65])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 68EE1352;\n\tSat, 17 Jan 2026 04:13:19 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"V8VjsWjm\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768619599;\n\tbh=dkNCa5Zo7GU+VgZPMkmdcbaS23Nc1Ty++cf2/Tfl7oc=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=V8VjsWjmBsH7Vz6SBsHoKm+IN+VL91NDRiYTzZr5pJCEawutC/3ycfFaN/6zJGzvl\n\t+MJrR0mxcLOf7bEkM9VAoPuRAtRYChWsZG5eaaYMHtqOW+1lxJDQvUMbK7Ti2xYMdB\n\tgBCvZlgZ4qTJRlrXjIAHVkNZlbzvJ0JGgHDLUuw8=","Message-ID":"<45a05dcf-3551-47fb-b820-b53c16abd347@ideasonboard.com>","Date":"Fri, 16 Jan 2026 22:13:35 -0500","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v8 2/7] ipa: rkisp1: algorithms: dpf: Implement mode\n\tswitching","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","References":"<20260115163318.1339354-1-rui.wang@ideasonboard.com>\n\t<20260115163318.1339354-3-rui.wang@ideasonboard.com>\n\t<aWn9S8fgJG2a6Iy3@zed>","Content-Language":"en-US","From":"rui wang <rui.wang@ideasonboard.com>","In-Reply-To":"<aWn9S8fgJG2a6Iy3@zed>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37709,"web_url":"https://patchwork.libcamera.org/comment/37709/","msgid":"<aWtTMuXLyY01Qypr@zed>","date":"2026-01-17T09:38:51","subject":"Re: [PATCH v8 2/7] ipa: rkisp1: algorithms: dpf: Implement mode\n\tswitching","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Rui\n\nOn Fri, Jan 16, 2026 at 10:13:35PM -0500, rui wang wrote:\n>\n> On 2026-01-16 04:21, Jacopo Mondi wrote:\n> > Hi Rui\n> >\n> > On Thu, Jan 15, 2026 at 11:33:13AM -0500, Rui Wang wrote:\n> > > Add support for switching between different noise reduction modes.\n> > >\n> > > Introduce `noiseReductionModes_` to store mode-specific configs.\n> > >\n> > > LoadReductionConfig() select specific config from configs.\n> > >\n> > > Signed-off-by: Rui Wang <rui.wang@ideasonboard.com>\n> > > Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > >\n> > > ---\n> > > changelog since v5:\n> > >   - Update log verbos from Info to Debug in loadReductionConfig\n> > >   - Update log mode value to string to in loadReductionConfig\n> > >   - improving the return value changed like :\n> > >         if (ret != 0)  -> if (ret)\n> > >\n> > >   Reviewed-by tags from v5 are carried over (no function changes).\n> > > changelog since v6:\n> > >   - add { controls::draft::NoiseReductionModeOff, \"off\" }, to fix\n> > >     out_of_range issue\n> > >\n> > > changelog since v7:\n> > >   - Delete base config parse from parseConfig\n> > > ---\n> > >   src/ipa/rkisp1/algorithms/dpf.cpp | 90 +++++++++++++++++++++++++++----\n> > >   src/ipa/rkisp1/algorithms/dpf.h   | 11 ++++\n> > >   2 files changed, 92 insertions(+), 9 deletions(-)\n> > >\n> > > diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp\n> > > index dd3effa1..9b663831 100644\n> > > --- a/src/ipa/rkisp1/algorithms/dpf.cpp\n> > > +++ b/src/ipa/rkisp1/algorithms/dpf.cpp\n> > > @@ -8,6 +8,7 @@\n> > >   #include \"dpf.h\"\n> > >\n> > >   #include <algorithm>\n> > > +#include <map>\n> > >   #include <string>\n> > >   #include <vector>\n> > >\n> > > @@ -36,8 +37,21 @@ namespace ipa::rkisp1::algorithms {\n> > >\n> > >   LOG_DEFINE_CATEGORY(RkISP1Dpf)\n> > >\n> > > +namespace {\n> > > +\n> > > +const std::map<int32_t, std::string> kModesMap = {\n> > > +\t{ controls::draft::NoiseReductionModeMinimal, \"minimal\" },\n> > > +\t{ controls::draft::NoiseReductionModeFast, \"fast\" },\n> > > +\t{ controls::draft::NoiseReductionModeHighQuality, \"highquality\" },\n> > > +\t{ controls::draft::NoiseReductionModeZSL, \"zsl\" },\n> > > +\t{ controls::draft::NoiseReductionModeOff, \"off\" },\n> > > +};\n> > > +\n> > > +} /* namespace */\n> > > +\n> > >   Dpf::Dpf()\n> > > -\t: config_({}), strengthConfig_({})\n> > > +\t: config_({}), strengthConfig_({}), noiseReductionModes_({}),\n> > > +\t  runningMode_(controls::draft::NoiseReductionModeOff)\n> > >   {\n> > >   }\n> > >\n> > > @@ -57,10 +71,43 @@ int Dpf::init([[maybe_unused]] IPAContext &context,\n> > >\n> > >   int Dpf::parseConfig(const YamlObject &tuningData)\n> > >   {\n> > > -\t/* Parse base config. */\n> > > -\tint ret = parseSingleConfig(tuningData, config_, strengthConfig_);\n> > > -\tif (ret)\n> > > -\t\treturn ret;\n> > > +\t/* Parse modes. */\n> > > +\treturn parseModes(tuningData);\n> > This should be called by init() removing the need for parseConfig() as\n> > suggested in the review of the previous patch\n>\n> I am thinking about  add parseActiveMode into parseConfig , and all YAML\n> parsing into this function in future.\n>\n> currently it has only parseModes inside parseConfig.\n>\n>    - enableMode: ''\n>\n> >\n> > > +}\n> > > +\n> > > +int Dpf::parseModes(const YamlObject &tuningData)\n> > > +{\n> > > +\t/* Parse noise reduction modes. */\n> > > +\tif (!tuningData.contains(\"modes\"))\n> > Should we LOG(Error) now that modes are mandatory ?\n> >\n> > > +\t\treturn -EINVAL;\n> > > +\n> > > +\tnoiseReductionModes_.clear();\n> > > +\tfor (const auto &entry : tuningData[\"modes\"].asList()) {\n> > > +\t\tstd::optional<std::string> typeOpt =\n> > > +\t\t\tentry[\"type\"].get<std::string>();\n> > > +\t\tif (!typeOpt) {\n> > > +\t\t\tLOG(RkISP1Dpf, Error) << \"Modes entry missing type\";\n> > > +\t\t\treturn -EINVAL;\n> > > +\t\t}\n> > > +\n> > > +\t\tModeConfig mode;\n> > > +\t\tauto it = std::find_if(kModesMap.begin(), kModesMap.end(),\n> > > +\t\t\t\t       [&typeOpt](const auto &pair) {\n> > > +\t\t\t\t\t       return pair.second == *typeOpt;\n> > > +\t\t\t\t       });\n> > > +\n> > > +\t\tif (it == kModesMap.end()) {\n> > > +\t\t\tLOG(RkISP1Dpf, Error) << \"Unknown mode type: \" << *typeOpt;\n> > > +\t\t\treturn -EINVAL;\n> > > +\t\t}\n> > > +\n> > > +\t\tmode.modeValue = it->first;\n> > > +\t\tauto ret = parseSingleConfig(entry, mode.dpf, mode.strength);\n> >                  int ret;\n> >\n> > auto gives you nothing here\n> >\n> > > +\t\tif (ret)\n> > > +\t\t\treturn ret;\n> > > +\n> > > +\t\tnoiseReductionModes_.push_back(mode);\n> > I think it was pointed out already in the previous versions: you\n> > should populate context.ctrlMap[controls::draft::NoiseReductionMode]\n> > with one entry for each supported mode.\n> >\n> > See https://git.libcamera.org/libcamera/libcamera.git/tree/src/ipa/rkisp1/algorithms/agc.cpp#n76\n> >\n> > Will it happen later on in the series and I've missed it ?\n> >\n> auto it = std::find_if(kModesMap.begin(), kModesMap.end(),\n>\n> [&typeOpt](const auto &pair) {\n>\n> return pair.second == *typeOpt;\n>\n> });\n>\n>\n> kModesMap contains all NoiseReductionMode value . so I can traverse each mode in YAML\n> and then add into  noiseReductionModes_.\n\nI'm sorry but maybe we're not getting each other.\n\nCould you please read the link I provided above where the AGC\nalgorithm populates context.ctrlMap[] ?\n\nYou should populate that map as well with only the modes enabled in\nconfig file.\n\nPlease apply the following patch to your series:\n\n------------------------------------------------------------------------------\n--- a/src/ipa/rkisp1/algorithms/dpf.cpp\n+++ b/src/ipa/rkisp1/algorithms/dpf.cpp\n@@ -58,30 +58,33 @@ Dpf::Dpf()\n /**\n  * \\copydoc libcamera::ipa::Algorithm::init\n  */\n-int Dpf::init([[maybe_unused]] IPAContext &context,\n-             const YamlObject &tuningData)\n+int Dpf::init(IPAContext &context, const YamlObject &tuningData)\n {\n        /* Parse tuning block. */\n-       int ret = parseConfig(tuningData);\n+       int ret = parseConfig(context, tuningData);\n        if (ret)\n                return ret;\n\n        return 0;\n }\n\n-int Dpf::parseConfig(const YamlObject &tuningData)\n+int Dpf::parseConfig(IPAContext &context, const YamlObject &tuningData)\n {\n        /* Parse modes. */\n-       return parseModes(tuningData);\n+       return parseModes(context, tuningData);\n }\n\n-int Dpf::parseModes(const YamlObject &tuningData)\n+int Dpf::parseModes(IPAContext &context, const YamlObject &tuningData)\n {\n        /* Parse noise reduction modes. */\n        if (!tuningData.contains(\"modes\"))\n                return -EINVAL;\n\n+       std::vector<ControlValue> enabledModes{\n+               ControlValue(controls::draft::NoiseReductionModeOff),\n+       };\n        noiseReductionModes_.clear();\n+\n        for (const auto &entry : tuningData[\"modes\"].asList()) {\n                std::optional<std::string> typeOpt =\n                        entry[\"type\"].get<std::string>();\n@@ -107,8 +110,12 @@ int Dpf::parseModes(const YamlObject &tuningData)\n                        return ret;\n\n                noiseReductionModes_.push_back(mode);\n+               enabledModes.push_back(ControlValue(mode.modeValue));\n        }\n\n+       context.ctrlMap[&controls::draft::NoiseReductionMode] =\n+                                               ControlInfo(enabledModes);\n+\n        return 0;\n }\n\ndiff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h\nindex 1821da396cd7..4deedb838d4d 100644\n--- a/src/ipa/rkisp1/algorithms/dpf.h\n+++ b/src/ipa/rkisp1/algorithms/dpf.h\n@@ -36,8 +36,8 @@ private:\n                rkisp1_cif_isp_dpf_strength_config strength;\n        };\n\n-       int parseConfig(const YamlObject &tuningData);\n-       int parseModes(const YamlObject &tuningData);\n+       int parseConfig(IPAContext &context, const YamlObject &tuningData);\n+       int parseModes(IPAContext &context, const YamlObject &tuningData);\n        int parseSingleConfig(const YamlObject &tuningData,\n                              rkisp1_cif_isp_dpf_config &config,\n                              rkisp1_cif_isp_dpf_strength_config &strengthConfig);\ndiff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp\nindex fbcc39103d4b..402ed62ceaa9 100644\n--- a/src/ipa/rkisp1/rkisp1.cpp\n+++ b/src/ipa/rkisp1/rkisp1.cpp\n@@ -120,7 +120,6 @@ const IPAHwSettings ipaHwSettingsV12{\n /* List of controls handled by the RkISP1 IPA */\n const ControlInfoMap::Map rkisp1Controls{\n        { &controls::DebugMetadataEnable, ControlInfo(false, true, false) },\n-       { &controls::draft::NoiseReductionMode, ControlInfo(controls::draft::NoiseReductionModeValues) },\n };\n\n } /* namespace */\n------------------------------------------------------------------------------\n\nSo that only modes enabled in the tuning file are reported in\nCamera::controls().\n\nWithout the patch:\n\n# cam -c1 --list-controls\nControl: [inout] draft::NoiseReductionMode:\n  - NoiseReductionModeOff (0) [default]\n  - NoiseReductionModeFast (1)\n  - NoiseReductionModeHighQuality (2)\n  - NoiseReductionModeMinimal (3)\n  - NoiseReductionModeZSL (4)\n\nWith the patch and modes \"minimal\" and \"highquality\" in the tuning\nfile as per this series on imx219\n\n# cam -c1 --list-controls\nControl: [inout] draft::NoiseReductionMode:\n  - NoiseReductionModeOff (0) [default]\n  - NoiseReductionModeMinimal (3)\n  - NoiseReductionModeHighQuality (2)\n\nWith the patch and mode \"highquality\" removed from the tuning file\n\n# cam -c1 --list-controls\nControl: [inout] draft::NoiseReductionMode:\n  - NoiseReductionModeOff (0) [default]\n  - NoiseReductionModeMinimal (3)\n\n>\n>\n> > > +\t}\n> > >\n> > >   \treturn 0;\n> > >   }\n> > > @@ -193,6 +240,28 @@ int Dpf::parseSingleConfig(const YamlObject &tuningData,\n> > >   \treturn 0;\n> > >   }\n> > >\n> > > +bool Dpf::loadReductionConfig(int32_t mode)\n> >               loadModeConfig(int32_t mode)\n> >\n> > > +{\n> > > +\tauto it = std::find_if(noiseReductionModes_.begin(), noiseReductionModes_.end(),\n> > > +\t\t\t       [mode](const ModeConfig &m) {\n> > > +\t\t\t\t       return m.modeValue == mode;\n> > > +\t\t\t       });\n> > > +\tif (it == noiseReductionModes_.end()) {\n> > > +\t\tLOG(RkISP1Dpf, Warning)\n> > > +\t\t\t<< \"No DPF config for reduction mode: \" << kModesMap.at(mode);\n> > \t\t\t<< \"No DPF config for mode: \" << kModesMap.at(mode);\n> >\n> > will remove this 'reduction' in v9.\n> > > +\t\treturn false;\n> > > +\t}\n> > > +\n> > > +\tconfig_ = it->dpf;\n> > > +\tstrengthConfig_ = it->strength;\n> > So now the config_ and strengthConfig_ member variables point to the\n> > 'active' mode configuration. Why are you copying them instead of just\n> > keeping a pointer to the active mode in noiseReductionModes_ ?\n> good idea, Introduce a const interator to point active mode in\n>\n> noiseReductionModes_ it can save strengthConfig_,config_, runningMode.\n> will implement in v9.\n>\n> >\n> > > +\n> > > +\tLOG(RkISP1Dpf, Debug)\n> > > +\t\t<< \"DPF mode=Reduction (config loaded)\"\n> > > +\t\t<< \" mode=\" << kModesMap.at(mode);\n> >                     \" mode = \"\n> will update in v9.\n> > > +\n> > > +\treturn true;\n> > > +}\n> > > +\n> > >   /**\n> > >    * \\copydoc libcamera::ipa::Algorithm::queueRequest\n> > >    */\n> > > @@ -206,8 +275,6 @@ void Dpf::queueRequest(IPAContext &context,\n> > >\n> > >   \tconst auto &denoise = controls.get(controls::draft::NoiseReductionMode);\n> > >   \tif (denoise) {\n> > > -\t\tLOG(RkISP1Dpf, Debug) << \"Set denoise to \" << *denoise;\n> > > -\n> > >   \t\tswitch (*denoise) {\n> > >   \t\tcase controls::draft::NoiseReductionModeOff:\n> > >   \t\t\tif (dpf.denoise) {\n> > > @@ -218,9 +285,10 @@ void Dpf::queueRequest(IPAContext &context,\n> > >   \t\tcase controls::draft::NoiseReductionModeMinimal:\n> > >   \t\tcase controls::draft::NoiseReductionModeHighQuality:\n> > >   \t\tcase controls::draft::NoiseReductionModeFast:\n> > > -\t\t\tif (!dpf.denoise) {\n> > > -\t\t\t\tdpf.denoise = true;\n> > > +\t\tcase controls::draft::NoiseReductionModeZSL:\n> > > +\t\t\tif (loadReductionConfig(*denoise)) {\n> > >   \t\t\t\tupdate = true;\n> > > +\t\t\t\tdpf.denoise = true;\n> > >   \t\t\t}\n> > >   \t\t\tbreak;\n> > >   \t\tdefault:\n> > > @@ -229,6 +297,10 @@ void Dpf::queueRequest(IPAContext &context,\n> > >   \t\t\t\t<< *denoise;\n> > >   \t\t\tbreak;\n> > >   \t\t}\n> > > +\t\tif (update) {\n> > > +\t\t\trunningMode_ = *denoise;\n> > So the member variable runningMode_ simply keeps track of the index of\n> > the enabled mode, right ? And I see it only used in logConfig()\n> > introduced in the next patch.\n> >\n> > If you accept the above suggestion about keeping a\n> > pointer/refernce/iterator to the active mode on the\n> > noiseReductionModes_ vector instead of copying its content to config_\n> > and strengthConfig_ you can use the 'modeValue' index instead of\n> > duplicating the information in runnigMode_\n>\n> yes will add const_iterator activeMode_ to point noiseReductionModes_\n>\n>\n> >\n> > > +\t\t\tLOG(RkISP1Dpf, Debug) << \"Set denoise to \" << kModesMap.at(runningMode_);\n> > > +\t\t}\n> > >   \t}\n> > >\n> > >   \tframeContext.dpf.denoise = dpf.denoise;\n> > > diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h\n> > > index 39186c55..2a2c7052 100644\n> > > --- a/src/ipa/rkisp1/algorithms/dpf.h\n> > > +++ b/src/ipa/rkisp1/algorithms/dpf.h\n> > > @@ -30,13 +30,24 @@ public:\n> > >   \t\t     RkISP1Params *params) override;\n> > >\n> > >   private:\n> > > +\tstruct ModeConfig {\n> > > +\t\tint32_t modeValue;\n> > > +\t\trkisp1_cif_isp_dpf_config dpf;\n> > > +\t\trkisp1_cif_isp_dpf_strength_config strength;\n> > > +\t};\n> > > +\n> > >   \tint parseConfig(const YamlObject &tuningData);\n> > > +\tint parseModes(const YamlObject &tuningData);\n> > >   \tint parseSingleConfig(const YamlObject &tuningData,\n> > >   \t\t\t      rkisp1_cif_isp_dpf_config &config,\n> > >   \t\t\t      rkisp1_cif_isp_dpf_strength_config &strengthConfig);\n> > >\n> > > +\tbool loadReductionConfig(int32_t mode);\n> > > +\n> > >   \tstruct rkisp1_cif_isp_dpf_config config_;\n> > >   \tstruct rkisp1_cif_isp_dpf_strength_config strengthConfig_;\n> > > +\tstd::vector<ModeConfig> noiseReductionModes_;\n> > > +\tint32_t runningMode_;\n> > >   };\n> > >\n> > >   } /* namespace ipa::rkisp1::algorithms */\n> > > --\n> > > 2.43.0\n> > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 39242BDCBF\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat, 17 Jan 2026 09:38:58 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 5D74561FBC;\n\tSat, 17 Jan 2026 10:38:57 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 924D5606D5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 17 Jan 2026 10:38:55 +0100 (CET)","from ideasonboard.com (net-93-65-100-155.cust.vodafonedsl.it\n\t[93.65.100.155])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 771E2371;\n\tSat, 17 Jan 2026 10:38:26 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"NL57ynWs\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768642706;\n\tbh=5itliz0QiZSkRlX3aahWXoZdmWsdRd2dc+Ey77v60G0=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=NL57ynWsuPofdHPcM3ez14vJx1R4a5/EBeweEI3lopLO7mjiH4ldnHXQejrrMrt5k\n\tEMQ+3pK1i9MFDzmuD02C+i9qShXwxgjSRLSUVTX1q3ltTB9aBBjxdh3LVV00Q3QiiB\n\tNfVnUnHv/y1QC3WkHcEKMaltNXKGf3iKvJMVVCc0=","Date":"Sat, 17 Jan 2026 10:38:51 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"rui wang <rui.wang@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v8 2/7] ipa: rkisp1: algorithms: dpf: Implement mode\n\tswitching","Message-ID":"<aWtTMuXLyY01Qypr@zed>","References":"<20260115163318.1339354-1-rui.wang@ideasonboard.com>\n\t<20260115163318.1339354-3-rui.wang@ideasonboard.com>\n\t<aWn9S8fgJG2a6Iy3@zed>\n\t<45a05dcf-3551-47fb-b820-b53c16abd347@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<45a05dcf-3551-47fb-b820-b53c16abd347@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]