[{"id":30459,"web_url":"https://patchwork.libcamera.org/comment/30459/","msgid":"<172174929197.392292.4744767989081091722@ping.linuxembedded.co.uk>","date":"2024-07-23T15:41:31","subject":"Re: [PATCH v2] libcamera: libipa: camera_sensor: Add onsemi AR0144\n\tsensor properties","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Laurent Pinchart (2024-07-04 00:11:36)\n> Provide the onsemi AR0144 camera sensor properties and registration with\n> libipa for the gain code helpers.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n> Now that the kernel driver has been posted to the linux-media mailing\n> list ([1]), it's time for a second version of this patch.\n> \n> [1] https://lore.kernel.org/r/20240603230301.26550-1-laurent.pinchart@ideasonboard.com\n> \n> Changes since RFC:\n> \n> - Add default case\n> - Add black level\n> ---\n>  src/ipa/libipa/camera_sensor_helper.cpp       | 94 +++++++++++++++++++\n>  .../sensor/camera_sensor_properties.cpp       |  9 ++\n>  2 files changed, 103 insertions(+)\n\nI think I'll be able to test this soon. Might as well be in by then ;-)\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> \n> diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp\n> index a1339c83c4cb..1cae0b3840af 100644\n> --- a/src/ipa/libipa/camera_sensor_helper.cpp\n> +++ b/src/ipa/libipa/camera_sensor_helper.cpp\n> @@ -8,6 +8,7 @@\n>  #include \"camera_sensor_helper.h\"\n>  \n>  #include <cmath>\n> +#include <limits>\n>  \n>  #include <libcamera/base/log.h>\n>  \n> @@ -398,6 +399,99 @@ static constexpr double expGainDb(double step)\n>         return log2_10 * step / 20;\n>  }\n>  \n> +class CameraSensorHelperAr0144 : public CameraSensorHelper\n> +{\n> +public:\n> +       CameraSensorHelperAr0144()\n> +       {\n> +               /* Power-on default value: 168 at 12bits. */\n> +               blackLevel_ = 2688;\n> +       }\n> +\n> +       uint32_t gainCode(double gain) const override\n> +       {\n> +               /* The recommended minimum gain is 1.6842 to avoid artifacts. */\n> +               gain = std::clamp(gain, 1.0 / (1.0 - 13.0 / 32.0), 18.45);\n> +\n> +               /*\n> +                * The analogue gain is made of a coarse exponential gain in\n> +                * the range [2^0, 2^4] and a fine inversely linear gain in the\n> +                * range [1.0, 2.0[. There is an additional fixed 1.153125\n> +                * multiplier when the coarse gain reaches 2^2.\n> +                */\n> +\n> +               if (gain > 4.0)\n> +                       gain /= 1.153125;\n> +\n> +               unsigned int coarse = std::log2(gain);\n> +               unsigned int fine = (1 - (1 << coarse) / gain) * 32;\n> +\n> +               /* The fine gain rounding depends on the coarse gain. */\n> +               if (coarse == 1 || coarse == 3)\n> +                       fine &= ~1;\n> +               else if (coarse == 4)\n> +                       fine &= ~3;\n> +\n> +               return (coarse << 4) | (fine & 0xf);\n> +       }\n> +\n> +       double gain(uint32_t gainCode) const override\n> +       {\n> +               unsigned int coarse = gainCode >> 4;\n> +               unsigned int fine = gainCode & 0xf;\n> +               unsigned int d1;\n> +               double d2, m;\n> +\n> +               switch (coarse) {\n> +               default:\n> +               case 0:\n> +                       d1 = 1;\n> +                       d2 = 32.0;\n> +                       m = 1.0;\n> +                       break;\n> +               case 1:\n> +                       d1 = 2;\n> +                       d2 = 16.0;\n> +                       m = 1.0;\n> +                       break;\n> +               case 2:\n> +                       d1 = 1;\n> +                       d2 = 32.0;\n> +                       m = 1.153125;\n> +                       break;\n> +               case 3:\n> +                       d1 = 2;\n> +                       d2 = 16.0;\n> +                       m = 1.153125;\n> +                       break;\n> +               case 4:\n> +                       d1 = 4;\n> +                       d2 = 8.0;\n> +                       m = 1.153125;\n> +                       break;\n> +               }\n> +\n> +               /*\n> +                * With infinite precision, the calculated gain would be exact,\n> +                * and the reverse conversion with gainCode() would produce the\n> +                * same gain code. In the real world, rounding errors may cause\n> +                * the calculated gain to be lower by an amount negligible for\n> +                * all purposes, except for the reverse conversion. Converting\n> +                * the gain to a gain code could then return the quantized value\n> +                * just lower than the original gain code. To avoid this, tests\n> +                * showed that adding the machine epsilon to the multiplier m is\n> +                * sufficient.\n> +                */\n> +               m += std::numeric_limits<decltype(m)>::epsilon();\n> +\n> +               return m * (1 << coarse) / (1.0 - (fine / d1) / d2);\n> +       }\n> +\n> +private:\n> +       static constexpr double kStep_ = 16;\n> +};\n> +REGISTER_CAMERA_SENSOR_HELPER(\"ar0144\", CameraSensorHelperAr0144)\n> +\n>  class CameraSensorHelperAr0521 : public CameraSensorHelper\n>  {\n>  public:\n> diff --git a/src/libcamera/sensor/camera_sensor_properties.cpp b/src/libcamera/sensor/camera_sensor_properties.cpp\n> index b18524d85b37..4e5217ab51ef 100644\n> --- a/src/libcamera/sensor/camera_sensor_properties.cpp\n> +++ b/src/libcamera/sensor/camera_sensor_properties.cpp\n> @@ -52,6 +52,15 @@ LOG_DEFINE_CATEGORY(CameraSensorProperties)\n>  const CameraSensorProperties *CameraSensorProperties::get(const std::string &sensor)\n>  {\n>         static const std::map<std::string, const CameraSensorProperties> sensorProps = {\n> +               { \"ar0144\", {\n> +                       .unitCellSize = { 3000, 3000 },\n> +                       .testPatternModes = {\n> +                               { controls::draft::TestPatternModeOff, 0 },\n> +                               { controls::draft::TestPatternModeSolidColor, 1 },\n> +                               { controls::draft::TestPatternModeColorBars, 2 },\n> +                               { controls::draft::TestPatternModeColorBarsFadeToGray, 3 },\n> +                       },\n> +               } },\n>                 { \"ar0521\", {\n>                         .unitCellSize = { 2200, 2200 },\n>                         .testPatternModes = {\n> \n> base-commit: 196abb8d1d6e0fe9d190315e72a85eb12d16a554\n> -- \n> Regards,\n> \n> Laurent Pinchart\n>","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 9D019BDB1C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 23 Jul 2024 15:41:38 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E99806336F;\n\tTue, 23 Jul 2024 17:41:36 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id EA4B7619A1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 23 Jul 2024 17:41:34 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 6E1B27E2;\n\tTue, 23 Jul 2024 17:40:52 +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=\"Gg6wp11y\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1721749252;\n\tbh=HqYl5UdBm7sH4WT7W4fqq3r8De/A1pdi3DoX/DnTc3w=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=Gg6wp11ysC5rzmFtV15DAnIlD8Fs5mQFLRgRRHAlzqeHZCD6QOSHWzfQ9WXSPZYhY\n\tf/iZT89HrggiHDMWNHqMn0dQ9vW6Ih3jnXavrn7NgYh8iEuqwAtp3I3XX8QP0U64F2\n\t5wAwg7RkxFD/aG13dPOwb5XLdw/O1Vu+36qpWENA=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20240703231136.5732-1-laurent.pinchart@ideasonboard.com>","References":"<20240703231136.5732-1-laurent.pinchart@ideasonboard.com>","Subject":"Re: [PATCH v2] libcamera: libipa: camera_sensor: Add onsemi AR0144\n\tsensor properties","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Tue, 23 Jul 2024 16:41:31 +0100","Message-ID":"<172174929197.392292.4744767989081091722@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","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>"}},{"id":30464,"web_url":"https://patchwork.libcamera.org/comment/30464/","msgid":"<20240723203257.GA14252@pendragon.ideasonboard.com>","date":"2024-07-23T20:32:57","subject":"Re: [PATCH v2] libcamera: libipa: camera_sensor: Add onsemi AR0144\n\tsensor properties","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Kieran,\n\nOn Tue, Jul 23, 2024 at 04:41:31PM +0100, Kieran Bingham wrote:\n> Quoting Laurent Pinchart (2024-07-04 00:11:36)\n> > Provide the onsemi AR0144 camera sensor properties and registration with\n> > libipa for the gain code helpers.\n> > \n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> > Now that the kernel driver has been posted to the linux-media mailing\n> > list ([1]), it's time for a second version of this patch.\n> > \n> > [1] https://lore.kernel.org/r/20240603230301.26550-1-laurent.pinchart@ideasonboard.com\n> > \n> > Changes since RFC:\n> > \n> > - Add default case\n> > - Add black level\n> > ---\n> >  src/ipa/libipa/camera_sensor_helper.cpp       | 94 +++++++++++++++++++\n> >  .../sensor/camera_sensor_properties.cpp       |  9 ++\n> >  2 files changed, 103 insertions(+)\n> \n> I think I'll be able to test this soon. Might as well be in by then ;-)\n> \n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\nThe driver hasn't been merged upstream, but is on its way. I've sent an\ninitial patch series and will continue working on it. Can I merge this\npatch already, or should I hold on ?\n\n> > diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp\n> > index a1339c83c4cb..1cae0b3840af 100644\n> > --- a/src/ipa/libipa/camera_sensor_helper.cpp\n> > +++ b/src/ipa/libipa/camera_sensor_helper.cpp\n> > @@ -8,6 +8,7 @@\n> >  #include \"camera_sensor_helper.h\"\n> >  \n> >  #include <cmath>\n> > +#include <limits>\n> >  \n> >  #include <libcamera/base/log.h>\n> >  \n> > @@ -398,6 +399,99 @@ static constexpr double expGainDb(double step)\n> >         return log2_10 * step / 20;\n> >  }\n> >  \n> > +class CameraSensorHelperAr0144 : public CameraSensorHelper\n> > +{\n> > +public:\n> > +       CameraSensorHelperAr0144()\n> > +       {\n> > +               /* Power-on default value: 168 at 12bits. */\n> > +               blackLevel_ = 2688;\n> > +       }\n> > +\n> > +       uint32_t gainCode(double gain) const override\n> > +       {\n> > +               /* The recommended minimum gain is 1.6842 to avoid artifacts. */\n> > +               gain = std::clamp(gain, 1.0 / (1.0 - 13.0 / 32.0), 18.45);\n> > +\n> > +               /*\n> > +                * The analogue gain is made of a coarse exponential gain in\n> > +                * the range [2^0, 2^4] and a fine inversely linear gain in the\n> > +                * range [1.0, 2.0[. There is an additional fixed 1.153125\n> > +                * multiplier when the coarse gain reaches 2^2.\n> > +                */\n> > +\n> > +               if (gain > 4.0)\n> > +                       gain /= 1.153125;\n> > +\n> > +               unsigned int coarse = std::log2(gain);\n> > +               unsigned int fine = (1 - (1 << coarse) / gain) * 32;\n> > +\n> > +               /* The fine gain rounding depends on the coarse gain. */\n> > +               if (coarse == 1 || coarse == 3)\n> > +                       fine &= ~1;\n> > +               else if (coarse == 4)\n> > +                       fine &= ~3;\n> > +\n> > +               return (coarse << 4) | (fine & 0xf);\n> > +       }\n> > +\n> > +       double gain(uint32_t gainCode) const override\n> > +       {\n> > +               unsigned int coarse = gainCode >> 4;\n> > +               unsigned int fine = gainCode & 0xf;\n> > +               unsigned int d1;\n> > +               double d2, m;\n> > +\n> > +               switch (coarse) {\n> > +               default:\n> > +               case 0:\n> > +                       d1 = 1;\n> > +                       d2 = 32.0;\n> > +                       m = 1.0;\n> > +                       break;\n> > +               case 1:\n> > +                       d1 = 2;\n> > +                       d2 = 16.0;\n> > +                       m = 1.0;\n> > +                       break;\n> > +               case 2:\n> > +                       d1 = 1;\n> > +                       d2 = 32.0;\n> > +                       m = 1.153125;\n> > +                       break;\n> > +               case 3:\n> > +                       d1 = 2;\n> > +                       d2 = 16.0;\n> > +                       m = 1.153125;\n> > +                       break;\n> > +               case 4:\n> > +                       d1 = 4;\n> > +                       d2 = 8.0;\n> > +                       m = 1.153125;\n> > +                       break;\n> > +               }\n> > +\n> > +               /*\n> > +                * With infinite precision, the calculated gain would be exact,\n> > +                * and the reverse conversion with gainCode() would produce the\n> > +                * same gain code. In the real world, rounding errors may cause\n> > +                * the calculated gain to be lower by an amount negligible for\n> > +                * all purposes, except for the reverse conversion. Converting\n> > +                * the gain to a gain code could then return the quantized value\n> > +                * just lower than the original gain code. To avoid this, tests\n> > +                * showed that adding the machine epsilon to the multiplier m is\n> > +                * sufficient.\n> > +                */\n> > +               m += std::numeric_limits<decltype(m)>::epsilon();\n> > +\n> > +               return m * (1 << coarse) / (1.0 - (fine / d1) / d2);\n> > +       }\n> > +\n> > +private:\n> > +       static constexpr double kStep_ = 16;\n> > +};\n> > +REGISTER_CAMERA_SENSOR_HELPER(\"ar0144\", CameraSensorHelperAr0144)\n> > +\n> >  class CameraSensorHelperAr0521 : public CameraSensorHelper\n> >  {\n> >  public:\n> > diff --git a/src/libcamera/sensor/camera_sensor_properties.cpp b/src/libcamera/sensor/camera_sensor_properties.cpp\n> > index b18524d85b37..4e5217ab51ef 100644\n> > --- a/src/libcamera/sensor/camera_sensor_properties.cpp\n> > +++ b/src/libcamera/sensor/camera_sensor_properties.cpp\n> > @@ -52,6 +52,15 @@ LOG_DEFINE_CATEGORY(CameraSensorProperties)\n> >  const CameraSensorProperties *CameraSensorProperties::get(const std::string &sensor)\n> >  {\n> >         static const std::map<std::string, const CameraSensorProperties> sensorProps = {\n> > +               { \"ar0144\", {\n> > +                       .unitCellSize = { 3000, 3000 },\n> > +                       .testPatternModes = {\n> > +                               { controls::draft::TestPatternModeOff, 0 },\n> > +                               { controls::draft::TestPatternModeSolidColor, 1 },\n> > +                               { controls::draft::TestPatternModeColorBars, 2 },\n> > +                               { controls::draft::TestPatternModeColorBarsFadeToGray, 3 },\n> > +                       },\n> > +               } },\n> >                 { \"ar0521\", {\n> >                         .unitCellSize = { 2200, 2200 },\n> >                         .testPatternModes = {\n> > \n> > base-commit: 196abb8d1d6e0fe9d190315e72a85eb12d16a554","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 5B8D2C323E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 23 Jul 2024 20:33:19 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7B0D36336F;\n\tTue, 23 Jul 2024 22:33:18 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E1555619A1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 23 Jul 2024 22:33:16 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi\n\t[81.175.209.231])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 34253AFD;\n\tTue, 23 Jul 2024 22:32:34 +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=\"GWKIRr5p\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1721766754;\n\tbh=ojAfO/S5VKKiBlmar8lAIjmJow4nCmyQ/TA/Ffmgoec=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=GWKIRr5p8pKySmUog/D3gCo5MV2siHF4xthwpHNX4yCAF9HIcR6UkXMXQGgnIGAxY\n\tfGHKfD/IOTUdza2Kj0/vZ6D9ZYxYY58tNfGIfNXFz/v1AV4btcqlpaJdjZnUehDLPS\n\tIK+1wLFNzHPQDWkt7P7AeJNyxRkazwycBT9voxkM=","Date":"Tue, 23 Jul 2024 23:32:57 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v2] libcamera: libipa: camera_sensor: Add onsemi AR0144\n\tsensor properties","Message-ID":"<20240723203257.GA14252@pendragon.ideasonboard.com>","References":"<20240703231136.5732-1-laurent.pinchart@ideasonboard.com>\n\t<172174929197.392292.4744767989081091722@ping.linuxembedded.co.uk>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<172174929197.392292.4744767989081091722@ping.linuxembedded.co.uk>","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>"}},{"id":30465,"web_url":"https://patchwork.libcamera.org/comment/30465/","msgid":"<172180755443.1225899.4482634864005295713@ping.linuxembedded.co.uk>","date":"2024-07-24T07:52:34","subject":"Re: [PATCH v2] libcamera: libipa: camera_sensor: Add onsemi AR0144\n\tsensor properties","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Laurent Pinchart (2024-07-23 21:32:57)\n> Hi Kieran,\n> \n> On Tue, Jul 23, 2024 at 04:41:31PM +0100, Kieran Bingham wrote:\n> > Quoting Laurent Pinchart (2024-07-04 00:11:36)\n> > > Provide the onsemi AR0144 camera sensor properties and registration with\n> > > libipa for the gain code helpers.\n> > > \n> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > > ---\n> > > Now that the kernel driver has been posted to the linux-media mailing\n> > > list ([1]), it's time for a second version of this patch.\n> > > \n> > > [1] https://lore.kernel.org/r/20240603230301.26550-1-laurent.pinchart@ideasonboard.com\n> > > \n> > > Changes since RFC:\n> > > \n> > > - Add default case\n> > > - Add black level\n> > > ---\n> > >  src/ipa/libipa/camera_sensor_helper.cpp       | 94 +++++++++++++++++++\n> > >  .../sensor/camera_sensor_properties.cpp       |  9 ++\n> > >  2 files changed, 103 insertions(+)\n> > \n> > I think I'll be able to test this soon. Might as well be in by then ;-)\n> > \n> > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> \n> The driver hasn't been merged upstream, but is on its way. I've sent an\n> initial patch series and will continue working on it. Can I merge this\n> patch already, or should I hold on ?\n\nDriver is public, posted upstream, expected to land when reviews\ncomplete, and the interface isn't expected to change. I think that meets\ncriteria to merge to libcamera support for this.\n\n--\nKieran\n\n\n\n \n> > > diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp\n> > > index a1339c83c4cb..1cae0b3840af 100644\n> > > --- a/src/ipa/libipa/camera_sensor_helper.cpp\n> > > +++ b/src/ipa/libipa/camera_sensor_helper.cpp\n> > > @@ -8,6 +8,7 @@\n> > >  #include \"camera_sensor_helper.h\"\n> > >  \n> > >  #include <cmath>\n> > > +#include <limits>\n> > >  \n> > >  #include <libcamera/base/log.h>\n> > >  \n> > > @@ -398,6 +399,99 @@ static constexpr double expGainDb(double step)\n> > >         return log2_10 * step / 20;\n> > >  }\n> > >  \n> > > +class CameraSensorHelperAr0144 : public CameraSensorHelper\n> > > +{\n> > > +public:\n> > > +       CameraSensorHelperAr0144()\n> > > +       {\n> > > +               /* Power-on default value: 168 at 12bits. */\n> > > +               blackLevel_ = 2688;\n> > > +       }\n> > > +\n> > > +       uint32_t gainCode(double gain) const override\n> > > +       {\n> > > +               /* The recommended minimum gain is 1.6842 to avoid artifacts. */\n> > > +               gain = std::clamp(gain, 1.0 / (1.0 - 13.0 / 32.0), 18.45);\n> > > +\n> > > +               /*\n> > > +                * The analogue gain is made of a coarse exponential gain in\n> > > +                * the range [2^0, 2^4] and a fine inversely linear gain in the\n> > > +                * range [1.0, 2.0[. There is an additional fixed 1.153125\n> > > +                * multiplier when the coarse gain reaches 2^2.\n> > > +                */\n> > > +\n> > > +               if (gain > 4.0)\n> > > +                       gain /= 1.153125;\n> > > +\n> > > +               unsigned int coarse = std::log2(gain);\n> > > +               unsigned int fine = (1 - (1 << coarse) / gain) * 32;\n> > > +\n> > > +               /* The fine gain rounding depends on the coarse gain. */\n> > > +               if (coarse == 1 || coarse == 3)\n> > > +                       fine &= ~1;\n> > > +               else if (coarse == 4)\n> > > +                       fine &= ~3;\n> > > +\n> > > +               return (coarse << 4) | (fine & 0xf);\n> > > +       }\n> > > +\n> > > +       double gain(uint32_t gainCode) const override\n> > > +       {\n> > > +               unsigned int coarse = gainCode >> 4;\n> > > +               unsigned int fine = gainCode & 0xf;\n> > > +               unsigned int d1;\n> > > +               double d2, m;\n> > > +\n> > > +               switch (coarse) {\n> > > +               default:\n> > > +               case 0:\n> > > +                       d1 = 1;\n> > > +                       d2 = 32.0;\n> > > +                       m = 1.0;\n> > > +                       break;\n> > > +               case 1:\n> > > +                       d1 = 2;\n> > > +                       d2 = 16.0;\n> > > +                       m = 1.0;\n> > > +                       break;\n> > > +               case 2:\n> > > +                       d1 = 1;\n> > > +                       d2 = 32.0;\n> > > +                       m = 1.153125;\n> > > +                       break;\n> > > +               case 3:\n> > > +                       d1 = 2;\n> > > +                       d2 = 16.0;\n> > > +                       m = 1.153125;\n> > > +                       break;\n> > > +               case 4:\n> > > +                       d1 = 4;\n> > > +                       d2 = 8.0;\n> > > +                       m = 1.153125;\n> > > +                       break;\n> > > +               }\n> > > +\n> > > +               /*\n> > > +                * With infinite precision, the calculated gain would be exact,\n> > > +                * and the reverse conversion with gainCode() would produce the\n> > > +                * same gain code. In the real world, rounding errors may cause\n> > > +                * the calculated gain to be lower by an amount negligible for\n> > > +                * all purposes, except for the reverse conversion. Converting\n> > > +                * the gain to a gain code could then return the quantized value\n> > > +                * just lower than the original gain code. To avoid this, tests\n> > > +                * showed that adding the machine epsilon to the multiplier m is\n> > > +                * sufficient.\n> > > +                */\n> > > +               m += std::numeric_limits<decltype(m)>::epsilon();\n> > > +\n> > > +               return m * (1 << coarse) / (1.0 - (fine / d1) / d2);\n> > > +       }\n> > > +\n> > > +private:\n> > > +       static constexpr double kStep_ = 16;\n> > > +};\n> > > +REGISTER_CAMERA_SENSOR_HELPER(\"ar0144\", CameraSensorHelperAr0144)\n> > > +\n> > >  class CameraSensorHelperAr0521 : public CameraSensorHelper\n> > >  {\n> > >  public:\n> > > diff --git a/src/libcamera/sensor/camera_sensor_properties.cpp b/src/libcamera/sensor/camera_sensor_properties.cpp\n> > > index b18524d85b37..4e5217ab51ef 100644\n> > > --- a/src/libcamera/sensor/camera_sensor_properties.cpp\n> > > +++ b/src/libcamera/sensor/camera_sensor_properties.cpp\n> > > @@ -52,6 +52,15 @@ LOG_DEFINE_CATEGORY(CameraSensorProperties)\n> > >  const CameraSensorProperties *CameraSensorProperties::get(const std::string &sensor)\n> > >  {\n> > >         static const std::map<std::string, const CameraSensorProperties> sensorProps = {\n> > > +               { \"ar0144\", {\n> > > +                       .unitCellSize = { 3000, 3000 },\n> > > +                       .testPatternModes = {\n> > > +                               { controls::draft::TestPatternModeOff, 0 },\n> > > +                               { controls::draft::TestPatternModeSolidColor, 1 },\n> > > +                               { controls::draft::TestPatternModeColorBars, 2 },\n> > > +                               { controls::draft::TestPatternModeColorBarsFadeToGray, 3 },\n> > > +                       },\n> > > +               } },\n> > >                 { \"ar0521\", {\n> > >                         .unitCellSize = { 2200, 2200 },\n> > >                         .testPatternModes = {\n> > > \n> > > base-commit: 196abb8d1d6e0fe9d190315e72a85eb12d16a554\n> \n> -- \n> Regards,\n> \n> Laurent Pinchart","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 2BB5ABDB1C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 24 Jul 2024 07:52:40 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3DE706336F;\n\tWed, 24 Jul 2024 09:52:39 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 58C816199C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 24 Jul 2024 09:52:37 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 680584CD;\n\tWed, 24 Jul 2024 09:51:54 +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=\"XX802t4y\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1721807514;\n\tbh=BSss9Ad5KLZyZKOYSw8IE0RMjW4AxhYd134jcjN8dqU=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=XX802t4ynLZXZUKHq9v/NJUG2IHh4innKE+KojIYOHXvqcM+uNddS7eRBwiESs/dd\n\tDU5hUKT47HJkMGiCKvW2CJebOuLQBljoUbnRCLlDAC9lAujIzt5VTyGnJte9JRo9Pl\n\tTBvqhCHCYhmFSv9Y24rhiuWD22S5lhJ9DAikLrPg=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20240723203257.GA14252@pendragon.ideasonboard.com>","References":"<20240703231136.5732-1-laurent.pinchart@ideasonboard.com>\n\t<172174929197.392292.4744767989081091722@ping.linuxembedded.co.uk>\n\t<20240723203257.GA14252@pendragon.ideasonboard.com>","Subject":"Re: [PATCH v2] libcamera: libipa: camera_sensor: Add onsemi AR0144\n\tsensor properties","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Date":"Wed, 24 Jul 2024 08:52:34 +0100","Message-ID":"<172180755443.1225899.4482634864005295713@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","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>"}}]