Message ID | 20240703231136.5732-1-laurent.pinchart@ideasonboard.com |
---|---|
State | Accepted |
Commit | 74513c398762737996267b3da7dc6af3c782bd05 |
Headers | show |
Series |
|
Related | show |
Quoting Laurent Pinchart (2024-07-04 00:11:36) > Provide the onsemi AR0144 camera sensor properties and registration with > libipa for the gain code helpers. > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > --- > Now that the kernel driver has been posted to the linux-media mailing > list ([1]), it's time for a second version of this patch. > > [1] https://lore.kernel.org/r/20240603230301.26550-1-laurent.pinchart@ideasonboard.com > > Changes since RFC: > > - Add default case > - Add black level > --- > src/ipa/libipa/camera_sensor_helper.cpp | 94 +++++++++++++++++++ > .../sensor/camera_sensor_properties.cpp | 9 ++ > 2 files changed, 103 insertions(+) I think I'll be able to test this soon. Might as well be in by then ;-) Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > > diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp > index a1339c83c4cb..1cae0b3840af 100644 > --- a/src/ipa/libipa/camera_sensor_helper.cpp > +++ b/src/ipa/libipa/camera_sensor_helper.cpp > @@ -8,6 +8,7 @@ > #include "camera_sensor_helper.h" > > #include <cmath> > +#include <limits> > > #include <libcamera/base/log.h> > > @@ -398,6 +399,99 @@ static constexpr double expGainDb(double step) > return log2_10 * step / 20; > } > > +class CameraSensorHelperAr0144 : public CameraSensorHelper > +{ > +public: > + CameraSensorHelperAr0144() > + { > + /* Power-on default value: 168 at 12bits. */ > + blackLevel_ = 2688; > + } > + > + uint32_t gainCode(double gain) const override > + { > + /* The recommended minimum gain is 1.6842 to avoid artifacts. */ > + gain = std::clamp(gain, 1.0 / (1.0 - 13.0 / 32.0), 18.45); > + > + /* > + * The analogue gain is made of a coarse exponential gain in > + * the range [2^0, 2^4] and a fine inversely linear gain in the > + * range [1.0, 2.0[. There is an additional fixed 1.153125 > + * multiplier when the coarse gain reaches 2^2. > + */ > + > + if (gain > 4.0) > + gain /= 1.153125; > + > + unsigned int coarse = std::log2(gain); > + unsigned int fine = (1 - (1 << coarse) / gain) * 32; > + > + /* The fine gain rounding depends on the coarse gain. */ > + if (coarse == 1 || coarse == 3) > + fine &= ~1; > + else if (coarse == 4) > + fine &= ~3; > + > + return (coarse << 4) | (fine & 0xf); > + } > + > + double gain(uint32_t gainCode) const override > + { > + unsigned int coarse = gainCode >> 4; > + unsigned int fine = gainCode & 0xf; > + unsigned int d1; > + double d2, m; > + > + switch (coarse) { > + default: > + case 0: > + d1 = 1; > + d2 = 32.0; > + m = 1.0; > + break; > + case 1: > + d1 = 2; > + d2 = 16.0; > + m = 1.0; > + break; > + case 2: > + d1 = 1; > + d2 = 32.0; > + m = 1.153125; > + break; > + case 3: > + d1 = 2; > + d2 = 16.0; > + m = 1.153125; > + break; > + case 4: > + d1 = 4; > + d2 = 8.0; > + m = 1.153125; > + break; > + } > + > + /* > + * With infinite precision, the calculated gain would be exact, > + * and the reverse conversion with gainCode() would produce the > + * same gain code. In the real world, rounding errors may cause > + * the calculated gain to be lower by an amount negligible for > + * all purposes, except for the reverse conversion. Converting > + * the gain to a gain code could then return the quantized value > + * just lower than the original gain code. To avoid this, tests > + * showed that adding the machine epsilon to the multiplier m is > + * sufficient. > + */ > + m += std::numeric_limits<decltype(m)>::epsilon(); > + > + return m * (1 << coarse) / (1.0 - (fine / d1) / d2); > + } > + > +private: > + static constexpr double kStep_ = 16; > +}; > +REGISTER_CAMERA_SENSOR_HELPER("ar0144", CameraSensorHelperAr0144) > + > class CameraSensorHelperAr0521 : public CameraSensorHelper > { > public: > diff --git a/src/libcamera/sensor/camera_sensor_properties.cpp b/src/libcamera/sensor/camera_sensor_properties.cpp > index b18524d85b37..4e5217ab51ef 100644 > --- a/src/libcamera/sensor/camera_sensor_properties.cpp > +++ b/src/libcamera/sensor/camera_sensor_properties.cpp > @@ -52,6 +52,15 @@ LOG_DEFINE_CATEGORY(CameraSensorProperties) > const CameraSensorProperties *CameraSensorProperties::get(const std::string &sensor) > { > static const std::map<std::string, const CameraSensorProperties> sensorProps = { > + { "ar0144", { > + .unitCellSize = { 3000, 3000 }, > + .testPatternModes = { > + { controls::draft::TestPatternModeOff, 0 }, > + { controls::draft::TestPatternModeSolidColor, 1 }, > + { controls::draft::TestPatternModeColorBars, 2 }, > + { controls::draft::TestPatternModeColorBarsFadeToGray, 3 }, > + }, > + } }, > { "ar0521", { > .unitCellSize = { 2200, 2200 }, > .testPatternModes = { > > base-commit: 196abb8d1d6e0fe9d190315e72a85eb12d16a554 > -- > Regards, > > Laurent Pinchart >
Hi Kieran, On Tue, Jul 23, 2024 at 04:41:31PM +0100, Kieran Bingham wrote: > Quoting Laurent Pinchart (2024-07-04 00:11:36) > > Provide the onsemi AR0144 camera sensor properties and registration with > > libipa for the gain code helpers. > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > --- > > Now that the kernel driver has been posted to the linux-media mailing > > list ([1]), it's time for a second version of this patch. > > > > [1] https://lore.kernel.org/r/20240603230301.26550-1-laurent.pinchart@ideasonboard.com > > > > Changes since RFC: > > > > - Add default case > > - Add black level > > --- > > src/ipa/libipa/camera_sensor_helper.cpp | 94 +++++++++++++++++++ > > .../sensor/camera_sensor_properties.cpp | 9 ++ > > 2 files changed, 103 insertions(+) > > I think I'll be able to test this soon. Might as well be in by then ;-) > > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> The driver hasn't been merged upstream, but is on its way. I've sent an initial patch series and will continue working on it. Can I merge this patch already, or should I hold on ? > > diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp > > index a1339c83c4cb..1cae0b3840af 100644 > > --- a/src/ipa/libipa/camera_sensor_helper.cpp > > +++ b/src/ipa/libipa/camera_sensor_helper.cpp > > @@ -8,6 +8,7 @@ > > #include "camera_sensor_helper.h" > > > > #include <cmath> > > +#include <limits> > > > > #include <libcamera/base/log.h> > > > > @@ -398,6 +399,99 @@ static constexpr double expGainDb(double step) > > return log2_10 * step / 20; > > } > > > > +class CameraSensorHelperAr0144 : public CameraSensorHelper > > +{ > > +public: > > + CameraSensorHelperAr0144() > > + { > > + /* Power-on default value: 168 at 12bits. */ > > + blackLevel_ = 2688; > > + } > > + > > + uint32_t gainCode(double gain) const override > > + { > > + /* The recommended minimum gain is 1.6842 to avoid artifacts. */ > > + gain = std::clamp(gain, 1.0 / (1.0 - 13.0 / 32.0), 18.45); > > + > > + /* > > + * The analogue gain is made of a coarse exponential gain in > > + * the range [2^0, 2^4] and a fine inversely linear gain in the > > + * range [1.0, 2.0[. There is an additional fixed 1.153125 > > + * multiplier when the coarse gain reaches 2^2. > > + */ > > + > > + if (gain > 4.0) > > + gain /= 1.153125; > > + > > + unsigned int coarse = std::log2(gain); > > + unsigned int fine = (1 - (1 << coarse) / gain) * 32; > > + > > + /* The fine gain rounding depends on the coarse gain. */ > > + if (coarse == 1 || coarse == 3) > > + fine &= ~1; > > + else if (coarse == 4) > > + fine &= ~3; > > + > > + return (coarse << 4) | (fine & 0xf); > > + } > > + > > + double gain(uint32_t gainCode) const override > > + { > > + unsigned int coarse = gainCode >> 4; > > + unsigned int fine = gainCode & 0xf; > > + unsigned int d1; > > + double d2, m; > > + > > + switch (coarse) { > > + default: > > + case 0: > > + d1 = 1; > > + d2 = 32.0; > > + m = 1.0; > > + break; > > + case 1: > > + d1 = 2; > > + d2 = 16.0; > > + m = 1.0; > > + break; > > + case 2: > > + d1 = 1; > > + d2 = 32.0; > > + m = 1.153125; > > + break; > > + case 3: > > + d1 = 2; > > + d2 = 16.0; > > + m = 1.153125; > > + break; > > + case 4: > > + d1 = 4; > > + d2 = 8.0; > > + m = 1.153125; > > + break; > > + } > > + > > + /* > > + * With infinite precision, the calculated gain would be exact, > > + * and the reverse conversion with gainCode() would produce the > > + * same gain code. In the real world, rounding errors may cause > > + * the calculated gain to be lower by an amount negligible for > > + * all purposes, except for the reverse conversion. Converting > > + * the gain to a gain code could then return the quantized value > > + * just lower than the original gain code. To avoid this, tests > > + * showed that adding the machine epsilon to the multiplier m is > > + * sufficient. > > + */ > > + m += std::numeric_limits<decltype(m)>::epsilon(); > > + > > + return m * (1 << coarse) / (1.0 - (fine / d1) / d2); > > + } > > + > > +private: > > + static constexpr double kStep_ = 16; > > +}; > > +REGISTER_CAMERA_SENSOR_HELPER("ar0144", CameraSensorHelperAr0144) > > + > > class CameraSensorHelperAr0521 : public CameraSensorHelper > > { > > public: > > diff --git a/src/libcamera/sensor/camera_sensor_properties.cpp b/src/libcamera/sensor/camera_sensor_properties.cpp > > index b18524d85b37..4e5217ab51ef 100644 > > --- a/src/libcamera/sensor/camera_sensor_properties.cpp > > +++ b/src/libcamera/sensor/camera_sensor_properties.cpp > > @@ -52,6 +52,15 @@ LOG_DEFINE_CATEGORY(CameraSensorProperties) > > const CameraSensorProperties *CameraSensorProperties::get(const std::string &sensor) > > { > > static const std::map<std::string, const CameraSensorProperties> sensorProps = { > > + { "ar0144", { > > + .unitCellSize = { 3000, 3000 }, > > + .testPatternModes = { > > + { controls::draft::TestPatternModeOff, 0 }, > > + { controls::draft::TestPatternModeSolidColor, 1 }, > > + { controls::draft::TestPatternModeColorBars, 2 }, > > + { controls::draft::TestPatternModeColorBarsFadeToGray, 3 }, > > + }, > > + } }, > > { "ar0521", { > > .unitCellSize = { 2200, 2200 }, > > .testPatternModes = { > > > > base-commit: 196abb8d1d6e0fe9d190315e72a85eb12d16a554
Quoting Laurent Pinchart (2024-07-23 21:32:57) > Hi Kieran, > > On Tue, Jul 23, 2024 at 04:41:31PM +0100, Kieran Bingham wrote: > > Quoting Laurent Pinchart (2024-07-04 00:11:36) > > > Provide the onsemi AR0144 camera sensor properties and registration with > > > libipa for the gain code helpers. > > > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > > --- > > > Now that the kernel driver has been posted to the linux-media mailing > > > list ([1]), it's time for a second version of this patch. > > > > > > [1] https://lore.kernel.org/r/20240603230301.26550-1-laurent.pinchart@ideasonboard.com > > > > > > Changes since RFC: > > > > > > - Add default case > > > - Add black level > > > --- > > > src/ipa/libipa/camera_sensor_helper.cpp | 94 +++++++++++++++++++ > > > .../sensor/camera_sensor_properties.cpp | 9 ++ > > > 2 files changed, 103 insertions(+) > > > > I think I'll be able to test this soon. Might as well be in by then ;-) > > > > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > > The driver hasn't been merged upstream, but is on its way. I've sent an > initial patch series and will continue working on it. Can I merge this > patch already, or should I hold on ? Driver is public, posted upstream, expected to land when reviews complete, and the interface isn't expected to change. I think that meets criteria to merge to libcamera support for this. -- Kieran > > > diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp > > > index a1339c83c4cb..1cae0b3840af 100644 > > > --- a/src/ipa/libipa/camera_sensor_helper.cpp > > > +++ b/src/ipa/libipa/camera_sensor_helper.cpp > > > @@ -8,6 +8,7 @@ > > > #include "camera_sensor_helper.h" > > > > > > #include <cmath> > > > +#include <limits> > > > > > > #include <libcamera/base/log.h> > > > > > > @@ -398,6 +399,99 @@ static constexpr double expGainDb(double step) > > > return log2_10 * step / 20; > > > } > > > > > > +class CameraSensorHelperAr0144 : public CameraSensorHelper > > > +{ > > > +public: > > > + CameraSensorHelperAr0144() > > > + { > > > + /* Power-on default value: 168 at 12bits. */ > > > + blackLevel_ = 2688; > > > + } > > > + > > > + uint32_t gainCode(double gain) const override > > > + { > > > + /* The recommended minimum gain is 1.6842 to avoid artifacts. */ > > > + gain = std::clamp(gain, 1.0 / (1.0 - 13.0 / 32.0), 18.45); > > > + > > > + /* > > > + * The analogue gain is made of a coarse exponential gain in > > > + * the range [2^0, 2^4] and a fine inversely linear gain in the > > > + * range [1.0, 2.0[. There is an additional fixed 1.153125 > > > + * multiplier when the coarse gain reaches 2^2. > > > + */ > > > + > > > + if (gain > 4.0) > > > + gain /= 1.153125; > > > + > > > + unsigned int coarse = std::log2(gain); > > > + unsigned int fine = (1 - (1 << coarse) / gain) * 32; > > > + > > > + /* The fine gain rounding depends on the coarse gain. */ > > > + if (coarse == 1 || coarse == 3) > > > + fine &= ~1; > > > + else if (coarse == 4) > > > + fine &= ~3; > > > + > > > + return (coarse << 4) | (fine & 0xf); > > > + } > > > + > > > + double gain(uint32_t gainCode) const override > > > + { > > > + unsigned int coarse = gainCode >> 4; > > > + unsigned int fine = gainCode & 0xf; > > > + unsigned int d1; > > > + double d2, m; > > > + > > > + switch (coarse) { > > > + default: > > > + case 0: > > > + d1 = 1; > > > + d2 = 32.0; > > > + m = 1.0; > > > + break; > > > + case 1: > > > + d1 = 2; > > > + d2 = 16.0; > > > + m = 1.0; > > > + break; > > > + case 2: > > > + d1 = 1; > > > + d2 = 32.0; > > > + m = 1.153125; > > > + break; > > > + case 3: > > > + d1 = 2; > > > + d2 = 16.0; > > > + m = 1.153125; > > > + break; > > > + case 4: > > > + d1 = 4; > > > + d2 = 8.0; > > > + m = 1.153125; > > > + break; > > > + } > > > + > > > + /* > > > + * With infinite precision, the calculated gain would be exact, > > > + * and the reverse conversion with gainCode() would produce the > > > + * same gain code. In the real world, rounding errors may cause > > > + * the calculated gain to be lower by an amount negligible for > > > + * all purposes, except for the reverse conversion. Converting > > > + * the gain to a gain code could then return the quantized value > > > + * just lower than the original gain code. To avoid this, tests > > > + * showed that adding the machine epsilon to the multiplier m is > > > + * sufficient. > > > + */ > > > + m += std::numeric_limits<decltype(m)>::epsilon(); > > > + > > > + return m * (1 << coarse) / (1.0 - (fine / d1) / d2); > > > + } > > > + > > > +private: > > > + static constexpr double kStep_ = 16; > > > +}; > > > +REGISTER_CAMERA_SENSOR_HELPER("ar0144", CameraSensorHelperAr0144) > > > + > > > class CameraSensorHelperAr0521 : public CameraSensorHelper > > > { > > > public: > > > diff --git a/src/libcamera/sensor/camera_sensor_properties.cpp b/src/libcamera/sensor/camera_sensor_properties.cpp > > > index b18524d85b37..4e5217ab51ef 100644 > > > --- a/src/libcamera/sensor/camera_sensor_properties.cpp > > > +++ b/src/libcamera/sensor/camera_sensor_properties.cpp > > > @@ -52,6 +52,15 @@ LOG_DEFINE_CATEGORY(CameraSensorProperties) > > > const CameraSensorProperties *CameraSensorProperties::get(const std::string &sensor) > > > { > > > static const std::map<std::string, const CameraSensorProperties> sensorProps = { > > > + { "ar0144", { > > > + .unitCellSize = { 3000, 3000 }, > > > + .testPatternModes = { > > > + { controls::draft::TestPatternModeOff, 0 }, > > > + { controls::draft::TestPatternModeSolidColor, 1 }, > > > + { controls::draft::TestPatternModeColorBars, 2 }, > > > + { controls::draft::TestPatternModeColorBarsFadeToGray, 3 }, > > > + }, > > > + } }, > > > { "ar0521", { > > > .unitCellSize = { 2200, 2200 }, > > > .testPatternModes = { > > > > > > base-commit: 196abb8d1d6e0fe9d190315e72a85eb12d16a554 > > -- > Regards, > > Laurent Pinchart
diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp index a1339c83c4cb..1cae0b3840af 100644 --- a/src/ipa/libipa/camera_sensor_helper.cpp +++ b/src/ipa/libipa/camera_sensor_helper.cpp @@ -8,6 +8,7 @@ #include "camera_sensor_helper.h" #include <cmath> +#include <limits> #include <libcamera/base/log.h> @@ -398,6 +399,99 @@ static constexpr double expGainDb(double step) return log2_10 * step / 20; } +class CameraSensorHelperAr0144 : public CameraSensorHelper +{ +public: + CameraSensorHelperAr0144() + { + /* Power-on default value: 168 at 12bits. */ + blackLevel_ = 2688; + } + + uint32_t gainCode(double gain) const override + { + /* The recommended minimum gain is 1.6842 to avoid artifacts. */ + gain = std::clamp(gain, 1.0 / (1.0 - 13.0 / 32.0), 18.45); + + /* + * The analogue gain is made of a coarse exponential gain in + * the range [2^0, 2^4] and a fine inversely linear gain in the + * range [1.0, 2.0[. There is an additional fixed 1.153125 + * multiplier when the coarse gain reaches 2^2. + */ + + if (gain > 4.0) + gain /= 1.153125; + + unsigned int coarse = std::log2(gain); + unsigned int fine = (1 - (1 << coarse) / gain) * 32; + + /* The fine gain rounding depends on the coarse gain. */ + if (coarse == 1 || coarse == 3) + fine &= ~1; + else if (coarse == 4) + fine &= ~3; + + return (coarse << 4) | (fine & 0xf); + } + + double gain(uint32_t gainCode) const override + { + unsigned int coarse = gainCode >> 4; + unsigned int fine = gainCode & 0xf; + unsigned int d1; + double d2, m; + + switch (coarse) { + default: + case 0: + d1 = 1; + d2 = 32.0; + m = 1.0; + break; + case 1: + d1 = 2; + d2 = 16.0; + m = 1.0; + break; + case 2: + d1 = 1; + d2 = 32.0; + m = 1.153125; + break; + case 3: + d1 = 2; + d2 = 16.0; + m = 1.153125; + break; + case 4: + d1 = 4; + d2 = 8.0; + m = 1.153125; + break; + } + + /* + * With infinite precision, the calculated gain would be exact, + * and the reverse conversion with gainCode() would produce the + * same gain code. In the real world, rounding errors may cause + * the calculated gain to be lower by an amount negligible for + * all purposes, except for the reverse conversion. Converting + * the gain to a gain code could then return the quantized value + * just lower than the original gain code. To avoid this, tests + * showed that adding the machine epsilon to the multiplier m is + * sufficient. + */ + m += std::numeric_limits<decltype(m)>::epsilon(); + + return m * (1 << coarse) / (1.0 - (fine / d1) / d2); + } + +private: + static constexpr double kStep_ = 16; +}; +REGISTER_CAMERA_SENSOR_HELPER("ar0144", CameraSensorHelperAr0144) + class CameraSensorHelperAr0521 : public CameraSensorHelper { public: diff --git a/src/libcamera/sensor/camera_sensor_properties.cpp b/src/libcamera/sensor/camera_sensor_properties.cpp index b18524d85b37..4e5217ab51ef 100644 --- a/src/libcamera/sensor/camera_sensor_properties.cpp +++ b/src/libcamera/sensor/camera_sensor_properties.cpp @@ -52,6 +52,15 @@ LOG_DEFINE_CATEGORY(CameraSensorProperties) const CameraSensorProperties *CameraSensorProperties::get(const std::string &sensor) { static const std::map<std::string, const CameraSensorProperties> sensorProps = { + { "ar0144", { + .unitCellSize = { 3000, 3000 }, + .testPatternModes = { + { controls::draft::TestPatternModeOff, 0 }, + { controls::draft::TestPatternModeSolidColor, 1 }, + { controls::draft::TestPatternModeColorBars, 2 }, + { controls::draft::TestPatternModeColorBarsFadeToGray, 3 }, + }, + } }, { "ar0521", { .unitCellSize = { 2200, 2200 }, .testPatternModes = {
Provide the onsemi AR0144 camera sensor properties and registration with libipa for the gain code helpers. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> --- Now that the kernel driver has been posted to the linux-media mailing list ([1]), it's time for a second version of this patch. [1] https://lore.kernel.org/r/20240603230301.26550-1-laurent.pinchart@ideasonboard.com Changes since RFC: - Add default case - Add black level --- src/ipa/libipa/camera_sensor_helper.cpp | 94 +++++++++++++++++++ .../sensor/camera_sensor_properties.cpp | 9 ++ 2 files changed, 103 insertions(+) base-commit: 196abb8d1d6e0fe9d190315e72a85eb12d16a554