{"id":27593,"url":"https://patchwork.libcamera.org/api/patches/27593/?format=json","web_url":"https://patchwork.libcamera.org/patch/27593/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260803131435.153927-47-barnabas.pocze@ideasonboard.com>","date":"2026-08-03T13:14:31","name":"[RFC,v3,46/50] ipa: libipa: agc: Work without `CameraSensorHelper`","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"f3a14884536e8340bf6ffbe5c5c71aabdc8f3c94","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/?format=json","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/27593/mbox/","series":[{"id":6103,"url":"https://patchwork.libcamera.org/api/series/6103/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=6103","date":"2026-08-03T13:13:45","name":"ipa: libipa: agc rework","version":3,"mbox":"https://patchwork.libcamera.org/series/6103/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/27593/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/27593/checks/","tags":{},"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 60571C334C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  3 Aug 2026 13:15:25 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 86BFC68114;\n\tMon,  3 Aug 2026 15:15:22 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 29101680B6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  3 Aug 2026 15:14:49 +0200 (CEST)","from pb-laptop.local (185.221.141.208.nat.pool.zt.hu\n\t[185.221.141.208])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 3CAB05B3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  3 Aug 2026 15:13:40 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"niedp9VD\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1785762820;\n\tbh=uVwY8ebloj2wewVG1SXsYBxf63jtyTvh3CVAWVzZ5Ac=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=niedp9VDb6uJWzJUTttel/GJV8k9z5x1y+qhZdU5qMjYau1rh2vsd1w1V0a8fytYf\n\tql1btYZi3/d1GROWHka/VixpnQPoivOIc/O6EJO94tEqvnyvcnmOdGHUGo2qhGzwWp\n\tAn9bLIq9IVsSnPiHc2+rg3bQqaDjhBDxzjS2q5IM=","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Subject":"[RFC PATCH v3 46/50] ipa: libipa: agc: Work without\n\t`CameraSensorHelper`","Date":"Mon,  3 Aug 2026 15:14:31 +0200","Message-ID":"<20260803131435.153927-47-barnabas.pocze@ideasonboard.com>","X-Mailer":"git-send-email 2.55.0","In-Reply-To":"<20260803131435.153927-1-barnabas.pocze@ideasonboard.com>","References":"<20260803131435.153927-1-barnabas.pocze@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","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>"},"content":"Use the agc algorithm extracted from the simple ipa module (AgcMSV)\nto provide some kind of operation when a `CameraSensorHelper` is\nnot available.\n\nSigned-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n---\n src/ipa/ipu3/algorithms/agc.cpp     |   4 +-\n src/ipa/libipa/agc.cpp              | 197 +++++++++++++++++++---------\n src/ipa/libipa/agc.h                |   9 +-\n src/ipa/mali-c55/algorithms/agc.cpp |   4 +-\n src/ipa/rkisp1/algorithms/agc.cpp   |   4 +-\n 5 files changed, 142 insertions(+), 76 deletions(-)","diff":"diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp\nindex 91923c7f70..a79898520c 100644\n--- a/src/ipa/ipu3/algorithms/agc.cpp\n+++ b/src/ipa/ipu3/algorithms/agc.cpp\n@@ -68,12 +68,11 @@ int Agc::init(IPAContext &context, const ValueNode &tuningData)\n {\n \tint ret;\n \n-\tret = agc_.init(tuningData);\n+\tret = agc_.init(tuningData, context.camHelper.get());\n \tif (ret)\n \t\treturn ret;\n \n \tret = agc_.configure(context.configuration.agc, context.activeState.agc, {\n-\t\t.sensor = context.camHelper.get(),\n \t\t.sensorInfo = context.sensorInfo,\n \t\t.sensorControls = context.sensorControls,\n \t\t.ctrlMap = context.ctrlMap,\n@@ -98,7 +97,6 @@ int Agc::configure(IPAContext &context,\n \tbdsGrid_ = context.configuration.grid.bdsGrid;\n \n \treturn agc_.configure(context.configuration.agc, context.activeState.agc, {\n-\t\t.sensor = context.camHelper.get(),\n \t\t.sensorInfo = context.sensorInfo,\n \t\t.sensorControls = context.sensorControls,\n \t\t.ctrlMap = context.ctrlMap,\ndiff --git a/src/ipa/libipa/agc.cpp b/src/ipa/libipa/agc.cpp\nindex 3efa4a89e1..b8b4cc9e83 100644\n--- a/src/ipa/libipa/agc.cpp\n+++ b/src/ipa/libipa/agc.cpp\n@@ -11,10 +11,12 @@\n #include <array>\n #include <chrono>\n #include <optional>\n+#include <variant>\n \n #include <linux/v4l2-controls.h>\n \n #include <libcamera/base/log.h>\n+#include <libcamera/base/utils.h>\n \n #include <libcamera/control_ids.h>\n #include <libcamera/controls.h>\n@@ -50,6 +52,9 @@ LOG_DEFINE_CATEGORY(Agc)\n  * \\var agc::Session::maxAnalogueGain\n  * \\brief Maximum analogue gain for the streaming session\n  *\n+ * \\var agc::Session::defAnalogueGain\n+ * \\brief Default analogue gain of the configured sensor\n+ *\n  * \\var agc::Session::minFrameDuration\n  * \\brief Minimum frame duration for the streaming session\n  *\n@@ -188,9 +193,6 @@ LOG_DEFINE_CATEGORY(Agc)\n  * \\struct AgcAlgorithm::ConfigurationParams\n  * \\brief Parameters for AgcAlgorithm::configure()\n  *\n- * \\var AgcAlgorithm::ConfigurationParams::sensor\n- * \\brief CameraSensorHelper for the sensor\n- *\n  * \\var AgcAlgorithm::ConfigurationParams::sensorInfo\n  * \\brief Current configuration of the sensor\n  *\n@@ -235,11 +237,18 @@ LOG_DEFINE_CATEGORY(Agc)\n /**\n  * \\brief Load tuning data\n  */\n-int AgcAlgorithm::init(const ValueNode &tuningData)\n+int AgcAlgorithm::init(const ValueNode &tuningData, CameraSensorHelper *sensor)\n {\n-\tint ret = impl_.parseTuningData(tuningData);\n-\tif (ret)\n-\t\treturn ret;\n+\tif (sensor) {\n+\t\tauto &impl = impl_.emplace<AgcMeanLuminance>();\n+\t\tint ret = impl.parseTuningData(tuningData);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t} else {\n+\t\timpl_.emplace<AgcMSV>();\n+\t}\n+\n+\tsensor_ = sensor;\n \n \treturn 0;\n }\n@@ -270,10 +279,14 @@ int AgcAlgorithm::configure(agc::Session &session, agc::ActiveState &state,\n \tint32_t defExposure = v4l2Exposure.def().get<int32_t>();\n \n \t/* Compute the analogue gain limits. */\n+\tconst auto extractGain = [&](const ControlValue &v) {\n+\t\tauto gainCode = v.get<int32_t>();\n+\t\treturn sensor_ ? sensor_->gain(gainCode) : gainCode;\n+\t};\n \tconst ControlInfo &v4l2Gain = config.sensorControls.find(V4L2_CID_ANALOGUE_GAIN)->second;\n-\tfloat minGain = config.sensor->gain(v4l2Gain.min().get<int32_t>());\n-\tfloat maxGain = config.sensor->gain(v4l2Gain.max().get<int32_t>());\n-\tfloat defGain = config.sensor->gain(v4l2Gain.def().get<int32_t>());\n+\tfloat minGain = extractGain(v4l2Gain.min());\n+\tfloat maxGain = extractGain(v4l2Gain.max());\n+\tfloat defGain = extractGain(v4l2Gain.def());\n \n \tLOG(Agc, Debug)\n \t\t<< \"exposure:[\" << minExposure << ',' << maxExposure << ']'\n@@ -312,28 +325,21 @@ int AgcAlgorithm::configure(agc::Session &session, agc::ActiveState &state,\n \tsession.maxExposureTime = maxExposure * session.lineDuration;\n \tsession.minAnalogueGain = minGain;\n \tsession.maxAnalogueGain = maxGain;\n+\tsession.defAnalogueGain = defGain;\n \tsession.minFrameDuration = std::chrono::microseconds(frameDurations[0]);\n \tsession.maxFrameDuration = std::chrono::microseconds(frameDurations[1]);\n \n-\timpl_.configure(session.lineDuration, config.sensor);\n-\timpl_.resetFrameCount();\n-\n \t/* Configure the default exposure and gain. */\n \tstate = {};\n \tstate.automatic.gain = session.minAnalogueGain;\n \tstate.automatic.exposure = defExposure;\n \tstate.automatic.quantizationGain = 1;\n \tstate.automatic.digitalGain = 1;\n-\tstate.automatic.yTarget = impl_.effectiveYTarget(0, 1);\n \tstate.manual.gain = state.automatic.gain;\n \tstate.manual.exposure = state.automatic.exposure;\n \tstate.autoExposureEnabled = session.autoAllowed;\n \tstate.autoGainEnabled = session.autoAllowed;\n \tstate.exposureValue = 0;\n-\tstate.constraintMode =\n-\t\tstatic_cast<controls::AeConstraintModeEnum>(impl_.constraintModes().begin()->first);\n-\tstate.exposureMode =\n-\t\tstatic_cast<controls::AeExposureModeEnum>(impl_.exposureModeHelpers().begin()->first);\n \tstate.minFrameDuration = session.minFrameDuration;\n \tstate.maxFrameDuration = session.maxFrameDuration;\n \n@@ -379,25 +385,59 @@ int AgcAlgorithm::configure(agc::Session &session, agc::ActiveState &state,\n \t\tSpan<const int64_t, 2>{ { frameDurations[0], frameDurations[1] } },\n \t};\n \n-\tif (session.autoAllowed) {\n-\t\tconfig.ctrlMap[&controls::ExposureValue] = ControlInfo(-8.0f, 8.0f, 0.0f);\n-\n-\t\t{\n-\t\t\tstd::vector<ControlValue> options;\n-\t\t\tfor (const auto &[id, _] : impl_.constraintModes())\n-\t\t\t\toptions.emplace_back(id);\n-\n-\t\t\tconfig.ctrlMap[&controls::AeConstraintMode] = ControlInfo(options);\n-\t\t}\n-\n-\t\t{\n-\t\t\tstd::vector<ControlValue> options;\n-\t\t\tfor (const auto &[id, _] : impl_.exposureModeHelpers())\n-\t\t\t\toptions.emplace_back(id);\n-\n-\t\t\tconfig.ctrlMap[&controls::AeExposureMode] = ControlInfo(options);\n-\t\t}\n-\t} else {\n+\tstd::visit(utils::overloaded{\n+\t\t[&](AgcMSV&) {\n+\t\t\t/* no constraint/exposure mode support */\n+\t\t\tstate.constraintMode = controls::AeConstraintModeEnum::ConstraintNormal;\n+\t\t\tstate.exposureMode = controls::AeExposureModeEnum::ExposureNormal;\n+\n+\t\t\tstate.automatic.yTarget = (2.5 - 1) / (5 - 1); /* \\todo hack? */\n+\n+\t\t\tif (session.autoAllowed) {\n+\t\t\t\tconfig.ctrlMap[&controls::AeConstraintMode] = ControlInfo(\n+\t\t\t\t\tstd::array{ ControlValue(state.constraintMode) }\n+\t\t\t\t);\n+\n+\t\t\t\tconfig.ctrlMap[&controls::AeExposureMode] = ControlInfo(\n+\t\t\t\t\tstd::array{ ControlValue(state.exposureMode) }\n+\t\t\t\t);\n+\t\t\t}\n+\t\t},\n+\t\t[&](AgcMeanLuminance& impl) {\n+\t\t\tstate.constraintMode =\n+\t\t\t\tstatic_cast<controls::AeConstraintModeEnum>(impl.constraintModes().begin()->first);\n+\t\t\tstate.exposureMode =\n+\t\t\t\tstatic_cast<controls::AeExposureModeEnum>(impl.exposureModeHelpers().begin()->first);\n+\n+\t\t\tstate.automatic.yTarget = impl.effectiveYTarget(0, 1);\n+\n+\t\t\tASSERT(sensor_);\n+\t\t\timpl.configure(session.lineDuration, sensor_);\n+\t\t\timpl.resetFrameCount();\n+\n+\t\t\tif (session.autoAllowed) {\n+\t\t\t\tconfig.ctrlMap[&controls::ExposureValue] = ControlInfo(-8.0f, 8.0f, 0.0f);\n+\n+\t\t\t\t{\n+\t\t\t\t\tstd::vector<ControlValue> options;\n+\t\t\t\t\tfor (const auto &[id, _] : impl.constraintModes())\n+\t\t\t\t\t\toptions.emplace_back(id);\n+\n+\t\t\t\t\tconfig.ctrlMap[&controls::AeConstraintMode] = ControlInfo(options);\n+\t\t\t\t}\n+\n+\t\t\t\t{\n+\t\t\t\t\tstd::vector<ControlValue> options;\n+\t\t\t\t\tfor (const auto &[id, _] : impl.exposureModeHelpers())\n+\t\t\t\t\t\toptions.emplace_back(id);\n+\n+\t\t\t\t\tconfig.ctrlMap[&controls::AeExposureMode] = ControlInfo(options);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t},\n+\t}, impl_);\n+\n+\tif (!session.autoAllowed) {\n \t\tconfig.ctrlMap.erase(&controls::ExposureValue);\n \t\tconfig.ctrlMap.erase(&controls::AeConstraintMode);\n \t\tconfig.ctrlMap.erase(&controls::AeExposureMode);\n@@ -599,33 +639,62 @@ void AgcAlgorithm::process(const agc::Session &session, agc::ActiveState &state,\n \t\t\tmaxAnalogueGain = frameContext.gain;\n \t\t}\n \n-\t\t/*\n-\t\t * The Agc algorithm needs to know the effective exposure value that was\n-\t\t * applied to the sensor when the statistics were collected.\n-\t\t */\n-\t\tutils::Duration effectiveExposureValue =\n-\t\t\tlineDuration * params->exposure * params->gain;\n-\n-\t\timpl_.setLimits(minExposureTime, maxExposureTime,\n-\t\t\t\tminAnalogueGain, maxAnalogueGain,\n-\t\t\t\tstd::move(params->additionalConstraints));\n-\n-\t\tconst auto &newEv = impl_.calculateNewEv({\n-\t\t\t.traits = params->traits,\n-\t\t\t.yHist = params->yHist,\n-\t\t\t.effectiveExposureValue = effectiveExposureValue,\n-\t\t\t.constraintModeIndex = frameContext.constraintMode,\n-\t\t\t.exposureModeIndex = frameContext.exposureMode,\n-\t\t\t.lux = params->lux,\n-\t\t\t.exposureCompensation = pow(2.0, frameContext.exposureValue),\n-\t\t});\n-\n-\t\t/* Update the estimated exposure and gain. */\n-\t\tstate.automatic.exposure = newEv.exposureTime / lineDuration;\n-\t\tstate.automatic.gain = newEv.analogueGain;\n-\t\tstate.automatic.quantizationGain = newEv.quantizationGain;\n-\t\tstate.automatic.digitalGain = newEv.digitalGain;\n-\t\tstate.automatic.yTarget = newEv.yTarget;\n+\t\tstd::visit(utils::overloaded{\n+\t\t\t[&](AgcMSV& impl) {\n+\t\t\t\timpl.setLimits({\n+\t\t\t\t\t.exposure = {\n+\t\t\t\t\t\tuint32_t(minExposureTime / lineDuration),\n+\t\t\t\t\t\tuint32_t(maxExposureTime / lineDuration),\n+\t\t\t\t\t},\n+\t\t\t\t\t.gain = {\n+\t\t\t\t\t\tminAnalogueGain,\n+\t\t\t\t\t\tmaxAnalogueGain,\n+\t\t\t\t\t},\n+\t\t\t\t\t/* gain codes -> step size of 1 */\n+\t\t\t\t\t.gainMinStep = 1,\n+\t\t\t\t\t/* assume default gain is close to 1.0 */\n+\t\t\t\t\t.gain1 = session.defAnalogueGain,\n+\t\t\t\t});\n+\n+\t\t\t\tconst auto& newEv = impl.calculateNewEv({\n+\t\t\t\t\t.yHist = params->yHist,\n+\t\t\t\t\t.exposure = params->exposure,\n+\t\t\t\t\t.gain = params->gain,\n+\t\t\t\t});\n+\n+\t\t\t\tstate.automatic.exposure = newEv.exposure;\n+\t\t\t\tstate.automatic.gain = newEv.analogueGain;\n+\t\t\t},\n+\t\t\t[&](AgcMeanLuminance& impl) {\n+\t\t\t\t/*\n+\t\t\t\t * The Agc algorithm needs to know the effective exposure value that was\n+\t\t\t\t * applied to the sensor when the statistics were collected.\n+\t\t\t\t */\n+\t\t\t\tutils::Duration effectiveExposureValue =\n+\t\t\t\t\tlineDuration * params->exposure * params->gain;\n+\n+\t\t\t\timpl.setLimits(minExposureTime, maxExposureTime,\n+\t\t\t\t\t       minAnalogueGain, maxAnalogueGain,\n+\t\t\t\t\t       std::move(params->additionalConstraints));\n+\n+\t\t\t\tconst auto &newEv = impl.calculateNewEv({\n+\t\t\t\t\t.traits = params->traits,\n+\t\t\t\t\t.yHist = params->yHist,\n+\t\t\t\t\t.effectiveExposureValue = effectiveExposureValue,\n+\t\t\t\t\t.constraintModeIndex = frameContext.constraintMode,\n+\t\t\t\t\t.exposureModeIndex = frameContext.exposureMode,\n+\t\t\t\t\t.lux = params->lux,\n+\t\t\t\t\t.exposureCompensation = pow(2.0, frameContext.exposureValue),\n+\t\t\t\t});\n+\n+\t\t\t\t/* Update the estimated exposure and gain. */\n+\t\t\t\tstate.automatic.exposure = newEv.exposureTime / lineDuration;\n+\t\t\t\tstate.automatic.gain = newEv.analogueGain;\n+\t\t\t\tstate.automatic.quantizationGain = newEv.quantizationGain;\n+\t\t\t\tstate.automatic.digitalGain = newEv.digitalGain;\n+\t\t\t\tstate.automatic.yTarget = newEv.yTarget;\n+\t\t\t},\n+\t\t}, impl_);\n \n \t\tLOG(Agc, Debug)\n \t\t\t<< \"exposure-time:\" << utils::Duration(state.automatic.exposure * lineDuration)\ndiff --git a/src/ipa/libipa/agc.h b/src/ipa/libipa/agc.h\nindex e96c6926b2..4f8038ae41 100644\n--- a/src/ipa/libipa/agc.h\n+++ b/src/ipa/libipa/agc.h\n@@ -9,6 +9,7 @@\n \n #include <optional>\n #include <utility>\n+#include <variant>\n \n #include <linux/v4l2-controls.h>\n \n@@ -18,6 +19,7 @@\n #include <libcamera/ipa/core_ipa_interface.h>\n \n #include \"agc_mean_luminance.h\"\n+#include \"agc_msv.h\"\n #include \"camera_sensor_helper.h\"\n #include \"histogram.h\"\n \n@@ -53,6 +55,7 @@ struct Session {\n \tutils::Duration maxExposureTime;\n \tdouble minAnalogueGain;\n \tdouble maxAnalogueGain;\n+\tdouble defAnalogueGain;\n \tutils::Duration minFrameDuration;\n \tutils::Duration maxFrameDuration;\n \n@@ -111,14 +114,13 @@ class AgcAlgorithm\n {\n public:\n \tstruct ConfigurationParams {\n-\t\tconst CameraSensorHelper *sensor;\n \t\tconst IPACameraSensorInfo &sensorInfo;\n \t\tconst ControlInfoMap &sensorControls;\n \t\tControlInfoMap::Map &ctrlMap;\n \t\tbool autoAllowed = true;\n \t};\n \n-\tint init(const ValueNode &tuningData);\n+\tint init(const ValueNode &tuningData, CameraSensorHelper *sensor);\n \n \tint configure(agc::Session &session, agc::ActiveState &state,\n \t\t      const ConfigurationParams &config);\n@@ -143,7 +145,8 @@ public:\n \t\t     ControlList &metadata);\n \n private:\n-\tAgcMeanLuminance impl_;\n+\tstd::variant<AgcMSV, AgcMeanLuminance> impl_;\n+\tCameraSensorHelper *sensor_ = nullptr;\n };\n \n } /* namespace ipa */\ndiff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp\nindex 87586e8a82..c869cc0235 100644\n--- a/src/ipa/mali-c55/algorithms/agc.cpp\n+++ b/src/ipa/mali-c55/algorithms/agc.cpp\n@@ -122,12 +122,11 @@ Agc::Agc()\n \n int Agc::init(IPAContext &context, const ValueNode &tuningData)\n {\n-\tint ret = agc_.init(tuningData);\n+\tint ret = agc_.init(tuningData, context.camHelper.get());\n \tif (ret)\n \t\treturn ret;\n \n \tret = agc_.configure(context.configuration.agc, context.activeState.agc, {\n-\t\t.sensor = context.camHelper.get(),\n \t\t.sensorInfo = context.sensorInfo,\n \t\t.sensorControls = context.sensorControls,\n \t\t.ctrlMap = context.ctrlMap,\n@@ -147,7 +146,6 @@ int Agc::configure(IPAContext &context,\n \t\treturn ret;\n \n \tret = agc_.configure(context.configuration.agc, context.activeState.agc, {\n-\t\t.sensor = context.camHelper.get(),\n \t\t.sensorInfo = context.sensorInfo,\n \t\t.sensorControls = context.sensorControls,\n \t\t.ctrlMap = context.ctrlMap,\ndiff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp\nindex 06e0646981..c4de8d4bab 100644\n--- a/src/ipa/rkisp1/algorithms/agc.cpp\n+++ b/src/ipa/rkisp1/algorithms/agc.cpp\n@@ -136,12 +136,11 @@ int Agc::init(IPAContext &context, const ValueNode &tuningData)\n {\n \tint ret;\n \n-\tret = agc_.init(tuningData);\n+\tret = agc_.init(tuningData, context.camHelper.get());\n \tif (ret)\n \t\treturn ret;\n \n \tret = agc_.configure(context.configuration.agc, context.activeState.agc, {\n-\t\t.sensor = context.camHelper.get(),\n \t\t.sensorInfo = context.sensorInfo,\n \t\t.sensorControls = context.sensorControls,\n \t\t.ctrlMap = context.ctrlMap,\n@@ -167,7 +166,6 @@ int Agc::init(IPAContext &context, const ValueNode &tuningData)\n int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)\n {\n \tint ret = agc_.configure(context.configuration.agc, context.activeState.agc, {\n-\t\t.sensor = context.camHelper.get(),\n \t\t.sensorInfo = context.sensorInfo,\n \t\t.sensorControls = context.sensorControls,\n \t\t.ctrlMap = context.ctrlMap,\n","prefixes":["RFC","v3","46/50"]}