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

Message ID 20260105-softisp-agc-v2-1-9013e693ffd5@mainlining.org
State Superseded
Headers show
Series
  • [v2] ipa: simple: fix minimal analog gain init
Related show

Commit Message

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

again_float = 512.0 / (512.0 - again_ctrl_value)

So the default 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 max sensor gain.

Signed-off-by: Vasiliy Doylov <nekocwd@mainlining.org>
---
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, 1:23 p.m. UTC | #1
Hi,

Thank you for the new version.

On 5-Jan-26 13:41, Vasiliy Doylov wrote:
> On most imx sensors the formula seems to be:
> 
> again_float = 512.0 / (512.0 - again_ctrl_value)
> 
> So the default 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 max sensor gain.

s/default/minimum again/
s/max sensor gain/maximum again/

And can you add some extra text explaining the change a bit more
here, e.g. :

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 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;

Please move this to above:

  		context_.configuration.agc.againMax = againMax;

So that the values are initialized in the same order as in
the if (true) code block above the else.

Regards,

Hans
Robert Mader Jan. 5, 2026, 2:35 p.m. UTC | #2
Hi, thanks for the patch!

On 05.01.26 14:23, johannes.goede@oss.qualcomm.com wrote:
>>   		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;
> Please move this to above:
>
>    		context_.configuration.agc.againMax = againMax;
>
> So that the values are initialized in the same order as in
> the if (true) code block above the else.
>
> Regards,
>
> Hans
I'm afraid this part was forgotten in v3
Kieran Bingham Jan. 5, 2026, 2:51 p.m. UTC | #3
Quoting Robert Mader (2026-01-05 14:35:11)
> Hi, thanks for the patch!
> 
> On 05.01.26 14:23, johannes.goede@oss.qualcomm.com wrote:
> >>              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;
> > Please move this to above:
> >
> >               context_.configuration.agc.againMax = againMax;
> >
> > So that the values are initialized in the same order as in
> > the if (true) code block above the else.
> >
> > Regards,
> >
> > Hans
> I'm afraid this part was forgotten in v3

Argh, sorry - I just merged v3 as I thought it was all handled.

I think the ordering is trivial, but happy to merge a patch fixing the
order too!

--
Kieran


> 
> -- 
> Robert Mader
> Consultant Software Developer
> 
> Collabora Ltd.
> Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK
> Registered in England & Wales, no. 5513718

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;
 	}