[v3] ipa: simple: fix minimal analog gain init
diff mbox series

Message ID 20260105-softisp-agc-v3-1-434f2053c549@mainlining.org
State Accepted
Commit 98e5e561502bdff0da6e58fe265846906bf72816
Headers show
Series
  • [v3] ipa: simple: fix minimal analog gain init
Related show

Commit Message

Vasiliy Doylov Jan. 5, 2026, 1:57 p.m. UTC
On most imx sensors the formula seems to be:

again_float = 512.0 / (512.0 - again_ctrl_value)

So the minimum again of 0 makes sense and actually translates to a gain of 1.0.
And the max gain of 400 leads to 512.0 / 112.0 = 4.57 which is about typical for
a maximum again. Since a minimum again value of 0 is actually normal, the special
handling of againMin == 0 is undesirable and this is actually causing problems
on these IMX sensors. again10 correctly gets set to 0 which is less then the
adjusted againMin which causes the AGC code to not work properly.

Fix this by dropping the special handling of againMin == 0.

Signed-off-by: Vasiliy Doylov <nekocwd@mainlining.org>
---
Changes in v3:
- Expanded commit message
- Link to v2: https://lists.libcamera.org/pipermail/libcamera-devel/2026-January/056068.html

Changes in v2:
- Drop old solution
- Fix minimal analog gain initialisation
- Link to v1: https://lists.libcamera.org/pipermail/libcamera-devel/2026-January/056045.html
---
 src/ipa/simple/soft_simple.cpp | 19 +------------------
 1 file changed, 1 insertion(+), 18 deletions(-)


---
base-commit: 2861817f09c96a0660b88783eff159631e42030f
change-id: 20260105-softisp-agc-16d01cb3da49

Best regards,

Comments

Hans de Goede Jan. 5, 2026, 2:04 p.m. UTC | #1
Hi,

On 5-Jan-26 14:57, Vasiliy Doylov wrote:
> On most imx sensors the formula seems to be:
> 
> again_float = 512.0 / (512.0 - again_ctrl_value)
> 
> So the minimum again of 0 makes sense and actually translates to a gain of 1.0.
> And the max gain of 400 leads to 512.0 / 112.0 = 4.57 which is about typical for
> a maximum again. Since a minimum again value of 0 is actually normal, the special
> handling of againMin == 0 is undesirable and this is actually causing problems
> on these IMX sensors. again10 correctly gets set to 0 which is less then the
> adjusted againMin which causes the AGC code to not work properly.
> 
> Fix this by dropping the special handling of againMin == 0.
> 
> Signed-off-by: Vasiliy Doylov <nekocwd@mainlining.org>

Thanks, patch looks good to me:

Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>

Regards,

Hans



> ---
> Changes in v3:
> - Expanded commit message
> - Link to v2: https://lists.libcamera.org/pipermail/libcamera-devel/2026-January/056068.html
> 
> Changes in v2:
> - Drop old solution
> - Fix minimal analog gain initialisation
> - Link to v1: https://lists.libcamera.org/pipermail/libcamera-devel/2026-January/056045.html
> ---
>  src/ipa/simple/soft_simple.cpp | 19 +------------------
>  1 file changed, 1 insertion(+), 18 deletions(-)
> 
> diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
> index b147aca2..dde11666 100644
> --- a/src/ipa/simple/soft_simple.cpp
> +++ b/src/ipa/simple/soft_simple.cpp
> @@ -237,26 +237,9 @@ int IPASoftSimple::configure(const IPAConfigInfo &configInfo)
>  				camHelper_->blackLevel().value() / 256;
>  		}
>  	} else {
> -		/*
> -		 * The camera sensor gain (g) is usually not equal to the value written
> -		 * into the gain register (x). But the way how the AGC algorithm changes
> -		 * the gain value to make the total exposure closer to the optimum
> -		 * assumes that g(x) is not too far from linear function. If the minimal
> -		 * gain is 0, the g(x) is likely to be far from the linear, like
> -		 * g(x) = a / (b * x + c). To avoid unexpected changes to the gain by
> -		 * the AGC algorithm (abrupt near one edge, and very small near the
> -		 * other) we limit the range of the gain values used.
> -		 */
>  		context_.configuration.agc.againMax = againMax;
>  		context_.configuration.agc.again10 = againDef;
> -		if (againMin) {
> -			context_.configuration.agc.againMin = againMin;
> -		} else {
> -			LOG(IPASoft, Warning)
> -				<< "Minimum gain is zero, that can't be linear";
> -			context_.configuration.agc.againMin =
> -				std::min(100, againMin / 2 + againMax / 2);
> -		}
> +		context_.configuration.agc.againMin = againMin;
>  		context_.configuration.agc.againMinStep = 1.0;
>  	}
>  
> 
> ---
> base-commit: 2861817f09c96a0660b88783eff159631e42030f
> change-id: 20260105-softisp-agc-16d01cb3da49
> 
> Best regards,
Milan Zamazal Jan. 5, 2026, 2:39 p.m. UTC | #2
Vasiliy Doylov <nekocwd@mainlining.org> writes:

> On most imx sensors the formula seems to be:
>
> again_float = 512.0 / (512.0 - again_ctrl_value)
>
> So the minimum again of 0 makes sense and actually translates to a gain of 1.0.
> And the max gain of 400 leads to 512.0 / 112.0 = 4.57 which is about typical for
> a maximum again. Since a minimum again value of 0 is actually normal, the special
> handling of againMin == 0 is undesirable and this is actually causing problems
> on these IMX sensors. again10 correctly gets set to 0 which is less then the

s/then/than/

(No need to resubmit because of this.)

> adjusted againMin which causes the AGC code to not work properly.
>
> Fix this by dropping the special handling of againMin == 0.
>
> Signed-off-by: Vasiliy Doylov <nekocwd@mainlining.org>
> ---
> Changes in v3:
> - Expanded commit message
> - Link to v2: https://lists.libcamera.org/pipermail/libcamera-devel/2026-January/056068.html
>
> Changes in v2:
> - Drop old solution
> - Fix minimal analog gain initialisation
> - Link to v1: https://lists.libcamera.org/pipermail/libcamera-devel/2026-January/056045.html
> ---
>  src/ipa/simple/soft_simple.cpp | 19 +------------------
>  1 file changed, 1 insertion(+), 18 deletions(-)
>
> diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
> index b147aca2..dde11666 100644
> --- a/src/ipa/simple/soft_simple.cpp
> +++ b/src/ipa/simple/soft_simple.cpp
> @@ -237,26 +237,9 @@ int IPASoftSimple::configure(const IPAConfigInfo &configInfo)
>  				camHelper_->blackLevel().value() / 256;
>  		}
>  	} else {
> -		/*
> -		 * The camera sensor gain (g) is usually not equal to the value written
> -		 * into the gain register (x). But the way how the AGC algorithm changes
> -		 * the gain value to make the total exposure closer to the optimum
> -		 * assumes that g(x) is not too far from linear function. If the minimal
> -		 * gain is 0, the g(x) is likely to be far from the linear, like
> -		 * g(x) = a / (b * x + c). To avoid unexpected changes to the gain by
> -		 * the AGC algorithm (abrupt near one edge, and very small near the
> -		 * other) we limit the range of the gain values used.
> -		 */

I guess it was put there for a reason but the workaround still looks
weird and if the fix works, let's take it.

Reviewed-by: Milan Zamazal <mzamazal@redhat.com>

>  		context_.configuration.agc.againMax = againMax;
>  		context_.configuration.agc.again10 = againDef;
> -		if (againMin) {
> -			context_.configuration.agc.againMin = againMin;
> -		} else {
> -			LOG(IPASoft, Warning)
> -				<< "Minimum gain is zero, that can't be linear";
> -			context_.configuration.agc.againMin =
> -				std::min(100, againMin / 2 + againMax / 2);
> -		}
> +		context_.configuration.agc.againMin = againMin;
>  		context_.configuration.agc.againMinStep = 1.0;
>  	}
>  
>
> ---
> base-commit: 2861817f09c96a0660b88783eff159631e42030f
> change-id: 20260105-softisp-agc-16d01cb3da49
>
> Best regards,

Patch
diff mbox series

diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
index b147aca2..dde11666 100644
--- a/src/ipa/simple/soft_simple.cpp
+++ b/src/ipa/simple/soft_simple.cpp
@@ -237,26 +237,9 @@  int IPASoftSimple::configure(const IPAConfigInfo &configInfo)
 				camHelper_->blackLevel().value() / 256;
 		}
 	} else {
-		/*
-		 * The camera sensor gain (g) is usually not equal to the value written
-		 * into the gain register (x). But the way how the AGC algorithm changes
-		 * the gain value to make the total exposure closer to the optimum
-		 * assumes that g(x) is not too far from linear function. If the minimal
-		 * gain is 0, the g(x) is likely to be far from the linear, like
-		 * g(x) = a / (b * x + c). To avoid unexpected changes to the gain by
-		 * the AGC algorithm (abrupt near one edge, and very small near the
-		 * other) we limit the range of the gain values used.
-		 */
 		context_.configuration.agc.againMax = againMax;
 		context_.configuration.agc.again10 = againDef;
-		if (againMin) {
-			context_.configuration.agc.againMin = againMin;
-		} else {
-			LOG(IPASoft, Warning)
-				<< "Minimum gain is zero, that can't be linear";
-			context_.configuration.agc.againMin =
-				std::min(100, againMin / 2 + againMax / 2);
-		}
+		context_.configuration.agc.againMin = againMin;
 		context_.configuration.agc.againMinStep = 1.0;
 	}