ipa: libipa: camera_sensor_helper: Add OV01A10
diff mbox series

Message ID c6a502b4-4193-40a6-8cfa-62a19bfb5011@opendigital.cc
State New
Headers show
Series
  • ipa: libipa: camera_sensor_helper: Add OV01A10
Related show

Commit Message

Stuart J Mackintosh March 25, 2026, 9:31 a.m. UTC
From ae84819121c206dd352c5e24942c1170ff7c6819 Mon Sep 17 00:00:00 2001
From: Stuart J Mackintosh <sjm@opendigital.cc>
Date: Wed, 25 Mar 2026 10:19:05 +0100
Subject: [PATCH] ipa: libipa: camera_sensor_helper: Add OV01A10

Add a CameraSensorHelper for the OmniVision OV01A10 image sensor,
used in Dell XPS 13 and other laptops with the Intel IPU6 camera
subsystem.

The analogue gain model is derived from the V4L2 control range
reported by the sensor driver. The minimum gain code is 256 with
a step of 1, giving the linear model:

   gain = code / 256

This corresponds to AnalogueGainLinear{ 1, 0, 0, 256 }, consistent
with the pattern used by other OmniVision sensors in this file.

The black level of 0x40 at 10 bits (4096 scaled to 16 bits) was
confirmed by dark frame measurement with the lens covered.

Without this helper, libcamera's AGC algorithm cannot convert between
gain codes and real gain values, causing auto-exposure oscillation and
the following warning:

   IPASoft: Failed to create camera sensor helper for ov01a10

Signed-off-by: Stuart J Mackintosh <sjm@opendigital.cc>
---
Note: Colour calibration (CCM) for this sensor is not yet available.
A tuning file exists at /usr/share/libcamera/ipa/simple/ov01a10.yaml
but contains no calibrated parameters. This is deferred to a follow-up
contribution once calibration data is available.

  src/ipa/libipa/camera_sensor_helper.cpp | 12 ++++++++++++
  1 file changed, 12 insertions(+)

Comments

Jacopo Mondi March 25, 2026, 4:02 p.m. UTC | #1
Hi Stuart

On Wed, Mar 25, 2026 at 10:31:45AM +0100, Stuart J Mackintosh wrote:
> From ae84819121c206dd352c5e24942c1170ff7c6819 Mon Sep 17 00:00:00 2001
> From: Stuart J Mackintosh <sjm@opendigital.cc>
> Date: Wed, 25 Mar 2026 10:19:05 +0100
> Subject: [PATCH] ipa: libipa: camera_sensor_helper: Add OV01A10

There is something going on with the way you submitted the patch
as 'git am' is not able to apply it. it seem you copied the patch in
an email message ?

Could you check Documentation/contributing.rst and use git-send-email ?

>
> Add a CameraSensorHelper for the OmniVision OV01A10 image sensor,
> used in Dell XPS 13 and other laptops with the Intel IPU6 camera
> subsystem.
>
> The analogue gain model is derived from the V4L2 control range
> reported by the sensor driver. The minimum gain code is 256 with
> a step of 1, giving the linear model:
>
>   gain = code / 256

Following this line of reasoning, the max gain code in the driver is
said to be 0x3fff which would give a max gain of x64 which seems quite
high (however I surely can't rule out it is correct).

>
> This corresponds to AnalogueGainLinear{ 1, 0, 0, 256 }, consistent
> with the pattern used by other OmniVision sensors in this file.

Are we going by reasoning just looking at the min/max ? Aren't
there other sources that migh confirm the analogue gain model is
actually a linear one ?

Have you tried manually increasing the analogue gain and validate you
get a linear response ?

>
> The black level of 0x40 at 10 bits (4096 scaled to 16 bits) was
> confirmed by dark frame measurement with the lens covered.

Great

>
> Without this helper, libcamera's AGC algorithm cannot convert between
> gain codes and real gain values, causing auto-exposure oscillation and
> the following warning:
>
>   IPASoft: Failed to create camera sensor helper for ov01a10
>
> Signed-off-by: Stuart J Mackintosh <sjm@opendigital.cc>
> ---
> Note: Colour calibration (CCM) for this sensor is not yet available.
> A tuning file exists at /usr/share/libcamera/ipa/simple/ov01a10.yaml
> but contains no calibrated parameters. This is deferred to a follow-up
> contribution once calibration data is available.

That would be nice! Do you plan to generate the CCM values yourself ?

Thanks
  j

>
>  src/ipa/libipa/camera_sensor_helper.cpp | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
>
> diff --git a/src/ipa/libipa/camera_sensor_helper.cpp
> b/src/ipa/libipa/camera_sensor_helper.cpp
> index e3e3e535..72466867 100644
> --- a/src/ipa/libipa/camera_sensor_helper.cpp
> +++ b/src/ipa/libipa/camera_sensor_helper.cpp
> @@ -653,6 +653,18 @@ public:
>  };
>  REGISTER_CAMERA_SENSOR_HELPER("imx708", CameraSensorHelperImx708)
>  +class CameraSensorHelperOv01a10 : public CameraSensorHelper

> +{
> +public:
> +	CameraSensorHelperOv01a10()
> +	{
> +		/* From dark frame measurement: 0x40 at 10bits. */
> +		blackLevel_ = 4096;
> +		gain_ = AnalogueGainLinear{ 1, 0, 0, 256 };
> +	}
> +};
> +REGISTER_CAMERA_SENSOR_HELPER("ov01a10", CameraSensorHelperOv01a10)
> +
>  class CameraSensorHelperOv2685 : public CameraSensorHelper
>  {
>  public:
> --
> 2.47.3
>
>
> --
> Stuart J Mackintosh
>
> Business & digital technology consultant
>
> Open Digital Consulting Co
>
> Open Digital Consulting Co Logo
>
> UK: +44 20 36 27 90 40
>
> FR: +33 1 89 48 00 40
>
> Email: sjm@opendigital.cc <mailto:sjm@opendigital.cc>
>
> Web: https://opendigital.cc <https://opendigital.cc>
>
> IM: xmpp:sjm@opendigital.cc <xmpp:sjm@opendigital.cc>
>
Stuart J Mackintosh March 25, 2026, 4:28 p.m. UTC | #2
Hi Jacopo,

On 25/03/2026 17:02, Jacopo Mondi wrote:
> Hi Stuart
>
> On Wed, Mar 25, 2026 at 10:31:45AM +0100, Stuart J Mackintosh wrote:
>>  From ae84819121c206dd352c5e24942c1170ff7c6819 Mon Sep 17 00:00:00 2001
>> From: Stuart J Mackintosh<sjm@opendigital.cc>
>> Date: Wed, 25 Mar 2026 10:19:05 +0100
>> Subject: [PATCH] ipa: libipa: camera_sensor_helper: Add OV01A10
> There is something going on with the way you submitted the patch
> as 'git am' is not able to apply it. it seem you copied the patch in
> an email message ?
>
> Could you check Documentation/contributing.rst and use git-send-email ?

Yes - I haven't used this method before, I am used to making PR's, so 
learning on this one. I will configure |git send-email| and resubmit.

>> Add a CameraSensorHelper for the OmniVision OV01A10 image sensor,
>> used in Dell XPS 13 and other laptops with the Intel IPU6 camera
>> subsystem.
>>
>> The analogue gain model is derived from the V4L2 control range
>> reported by the sensor driver. The minimum gain code is 256 with
>> a step of 1, giving the linear model:
>>
>>    gain = code / 256
> Following this line of reasoning, the max gain code in the driver is
> said to be 0x3fff which would give a max gain of x64 which seems quite
> high (however I surely can't rule out it is correct).

The upstream kernel driver defines |OV01A10_ANAL_GAIN_MAX = 0x3fff| = 
16383, giving a maximum of 63.99x. My running kernel (6.12.74+deb13) 
reports max=65535 via V4L2, which appears to be an older driver version 
predating a recent fix. The gain model is correct regardless - only the 
clamp value differs.(AI)

>> This corresponds to AnalogueGainLinear{ 1, 0, 0, 256 }, consistent
>> with the pattern used by other OmniVision sensors in this file.
> Are we going by reasoning just looking at the min/max ? Aren't
> there other sources that migh confirm the analogue gain model is
> actually a linear one ?
>
> Have you tried manually increasing the analogue gain and validate you
> get a linear response ?

The kernel driver writes the analogue gain register directly without 
scaling: |cci_write(ov01a10->regmap, OV01A10_REG_ANALOG_GAIN, ctrl->val, 
NULL)|. The minimum |OV01A10_ANAL_GAIN_MIN = 0x100| = 256 represents 
unity gain, consistent with Q8 fixed-point where |gain = register_value 
/ 256|. This is the same fixed-point convention used for digital gain, 
where |OV01A10_DGTL_GAIN_DEFAULT = 1024| represents unity with a 6-bit 
fractional part. (AI)

>> Without this helper, libcamera's AGC algorithm cannot convert between
>> gain codes and real gain values, causing auto-exposure oscillation and
>> the following warning:
>>
>>    IPASoft: Failed to create camera sensor helper for ov01a10
>>
>> Signed-off-by: Stuart J Mackintosh<sjm@opendigital.cc>
>> ---
>> Note: Colour calibration (CCM) for this sensor is not yet available.
>> A tuning file exists at /usr/share/libcamera/ipa/simple/ov01a10.yaml
>> but contains no calibrated parameters. This is deferred to a follow-up
>> contribution once calibration data is available.
> That would be nice! Do you plan to generate the CCM values yourself ?

Yes, that is my intention once I have worked out a reasonable 
calibration approach.

A little more background - I am using a Dell XPS and it generally works 
with Debian, the biggest problem being this camera so I am committed to 
chipping away at it until it is usable. This patch already makes a big 
difference and I am keen to get the fixes upstream. I am using AI to 
assist this work and marked the generated statements with (AI); I am not 
CPP experienced.

What would help me is to know the recommended way to capture frames at a 
fixed analogue gain value on an IPU6 platform, bypassing the AGC, to 
help validate the gain parameters? Any guidance that you might have with 
diagnostics is welcome.

Best wishes,

Stuart.


>
> Thanks
>    j
>
>>   src/ipa/libipa/camera_sensor_helper.cpp | 12 ++++++++++++
>>   1 file changed, 12 insertions(+)
>>
>> diff --git a/src/ipa/libipa/camera_sensor_helper.cpp
>> b/src/ipa/libipa/camera_sensor_helper.cpp
>> index e3e3e535..72466867 100644
>> --- a/src/ipa/libipa/camera_sensor_helper.cpp
>> +++ b/src/ipa/libipa/camera_sensor_helper.cpp
>> @@ -653,6 +653,18 @@ public:
>>   };
>>   REGISTER_CAMERA_SENSOR_HELPER("imx708", CameraSensorHelperImx708)
>>   +class CameraSensorHelperOv01a10 : public CameraSensorHelper
>> +{
>> +public:
>> +	CameraSensorHelperOv01a10()
>> +	{
>> +		/* From dark frame measurement: 0x40 at 10bits. */
>> +		blackLevel_ = 4096;
>> +		gain_ = AnalogueGainLinear{ 1, 0, 0, 256 };
>> +	}
>> +};
>> +REGISTER_CAMERA_SENSOR_HELPER("ov01a10", CameraSensorHelperOv01a10)
>> +
>>   class CameraSensorHelperOv2685 : public CameraSensorHelper
>>   {
>>   public:
>> --
>> 2.47.3
>>
>>
>> --
>> Stuart J Mackintosh
>>
>> Business & digital technology consultant
>>
>> Open Digital Consulting Co
>>
>> Open Digital Consulting Co Logo
>>
>> UK: +44 20 36 27 90 40
>>
>> FR: +33 1 89 48 00 40
>>
>> Email:sjm@opendigital.cc <mailto:sjm@opendigital.cc>
>>
>> Web:https://opendigital.cc <https://opendigital.cc>
>>
>> IM:xmpp:sjm@opendigital.cc <xmpp:sjm@opendigital.cc>
>>
Hans de Goede March 25, 2026, 5:44 p.m. UTC | #3
Hi Stuart, Jacopo,

Stuart, thank you for your interest in this.

When I had a XPS 13 on loan I've made a set of calibration images
of its sensor:

https://fedorapeople.org/~jwrdegoede/sensor-calibration/dell-xps13-9320-ov01a10/

You can use those with the rkisp1.py found under utils/tuning/rkisp1.py
to try and generate a CCM for the camera-module.

Note at the moment there are some know issues with the CCM handling
in the software ISP which we are working on fixing.

So you could give this a try, but you will likely get neon-purple
colors in brightly lit areas. This is a known issue.

On 25-Mar-26 17:02, Jacopo Mondi wrote:
> Hi Stuart
> 
> On Wed, Mar 25, 2026 at 10:31:45AM +0100, Stuart J Mackintosh wrote:
>> From ae84819121c206dd352c5e24942c1170ff7c6819 Mon Sep 17 00:00:00 2001
>> From: Stuart J Mackintosh <sjm@opendigital.cc>
>> Date: Wed, 25 Mar 2026 10:19:05 +0100
>> Subject: [PATCH] ipa: libipa: camera_sensor_helper: Add OV01A10
> 
> There is something going on with the way you submitted the patch
> as 'git am' is not able to apply it. it seem you copied the patch in
> an email message ?
> 
> Could you check Documentation/contributing.rst and use git-send-email ?
> 
>>
>> Add a CameraSensorHelper for the OmniVision OV01A10 image sensor,
>> used in Dell XPS 13 and other laptops with the Intel IPU6 camera
>> subsystem.
>>
>> The analogue gain model is derived from the V4L2 control range
>> reported by the sensor driver. The minimum gain code is 256 with
>> a step of 1, giving the linear model:
>>
>>   gain = code / 256
> 
> Following this line of reasoning, the max gain code in the driver is
> said to be 0x3fff which would give a max gain of x64 which seems quite
> high (however I surely can't rule out it is correct).

I think this is a driver bug, almost all ov-sensors seem to have
a fractional gain with 4 bits for the non fractional parts
and either 7 or 8 bits for the fraction. With the non-fractional
part starting at 1 for 1.0 .

So based on that and other ov sensor drivers I think the driver
is buggy and the maximum should be 0xf80, 0xf80 rather then 0xfff
because, well that is what other omnivision sensor drivers do,
I guess something goes funky in the hw for gains > 15.5 ?

A maximum gain of 15.5 sounds much more realistic IMHO.

So I think we need to fix the kernel driver to make the maximum
0x780.

>> This corresponds to AnalogueGainLinear{ 1, 0, 0, 256 }, consistent
>> with the pattern used by other OmniVision sensors in this file.
> 
> Are we going by reasoning just looking at the min/max ? Aren't
> there other sources that migh confirm the analogue gain model is
> actually a linear one ?
> > Have you tried manually increasing the analogue gain and validate you
> get a linear response ?

When I did the calibration images under controlled lighting conditions
I checked the influence of the gain control on the 18% grey square
(monitoring that square with camshark) of the macbeth chart and it
seemed linear. This also matches other known ov sensors.

Regards,

Hans


p.s.

Stuart many of us have a wariness about over-use of AI, often just
throwing a lot of things at the wall and seeing what looks like it
might work, without rhyme or reason. Or what people call AI slop. 

Note this first submission does not seem to be AI slop at all!

And your disclosure of using of AI is appreciated but please be
careful with your use of AI.

Patch
diff mbox series

diff --git a/src/ipa/libipa/camera_sensor_helper.cpp 
b/src/ipa/libipa/camera_sensor_helper.cpp
index e3e3e535..72466867 100644
--- a/src/ipa/libipa/camera_sensor_helper.cpp
+++ b/src/ipa/libipa/camera_sensor_helper.cpp
@@ -653,6 +653,18 @@  public:
  };
  REGISTER_CAMERA_SENSOR_HELPER("imx708", CameraSensorHelperImx708)
  +class CameraSensorHelperOv01a10 : public CameraSensorHelper
+{
+public:
+	CameraSensorHelperOv01a10()
+	{
+		/* From dark frame measurement: 0x40 at 10bits. */
+		blackLevel_ = 4096;
+		gain_ = AnalogueGainLinear{ 1, 0, 0, 256 };
+	}
+};
+REGISTER_CAMERA_SENSOR_HELPER("ov01a10", CameraSensorHelperOv01a10)
+
  class CameraSensorHelperOv2685 : public CameraSensorHelper
  {
  public:
-- 
2.47.3