Patch Detail
Show a patch.
GET /api/patches/20197/?format=api
{ "id": 20197, "url": "https://patchwork.libcamera.org/api/patches/20197/?format=api", "web_url": "https://patchwork.libcamera.org/patch/20197/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20240603230301.26550-1-laurent.pinchart@ideasonboard.com>", "date": "2024-06-03T23:03:00", "name": "[RFC/PATCH] libcamera: libipa: camera_sensor: Add onsemi AR0144 sensor properties", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "7a388c6109a8b2173b850d73810389021d209f56", "submitter": { "id": 2, "url": "https://patchwork.libcamera.org/api/people/2/?format=api", "name": "Laurent Pinchart", "email": "laurent.pinchart@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/20197/mbox/", "series": [ { "id": 4356, "url": "https://patchwork.libcamera.org/api/series/4356/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4356", "date": "2024-06-03T23:03:00", "name": "[RFC/PATCH] libcamera: libipa: camera_sensor: Add onsemi AR0144 sensor properties", "version": 1, "mbox": "https://patchwork.libcamera.org/series/4356/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/20197/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/20197/checks/", "tags": {}, "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 EB0F9BD87C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 3 Jun 2024 23:03:19 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 07500634C5;\n\tTue, 4 Jun 2024 01:03:19 +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 59BA7634B2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 4 Jun 2024 01:03:17 +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 D11FF16D4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 4 Jun 2024 01:03:09 +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=\"UjBf5IV+\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1717455790;\n\tbh=NIneKZ/DxZgol2JzpgMTqt13+r3JhDNk5zYZxO0rdqA=;\n\th=From:To:Subject:Date:From;\n\tb=UjBf5IV+eexorJ40z2NRc2pY8ErqXPGbvxuyFhJSYVOzZREofgrvN5sppaZOXbXll\n\t5JfwdJKvtmRTqhEH3xHr34Uigg5mmuUP2/B4hnCws7nCU4FdUs2zyfwayI2Y1aoVyU\n\t3SD2JFkt6wFzi6Vs9U/qCRArjquhFm1Fkg1PN1hM=", "From": "Laurent Pinchart <laurent.pinchart@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Subject": "[RFC/PATCH] libcamera: libipa: camera_sensor: Add onsemi AR0144\n\tsensor properties", "Date": "Tue, 4 Jun 2024 02:03:00 +0300", "Message-ID": "<20240603230301.26550-1-laurent.pinchart@ideasonboard.com>", "X-Mailer": "git-send-email 2.44.2", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "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>" }, "content": "Provide the onsemi AR0144 camera sensor properties and registration with\nlibipa for the gain code helpers.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\nI'm working on a driver for the AR0144 camera sensor, which implements\nan exotic gain model. While I would normally post the kernel driver\nbefore submitting the libcamera integration patch, I thought reversing\nthe order would be useful for discussion purpose, as we recently\nresurected the topic of gain rounding (see\nhttps://patchwork.libcamera.org/cover/20097/).\n\nThe approach I've taken here is to ensure that the code -> gain -> code\nroundtrip conversion always results to the same gain code, for all valid\ngain codes. To achieve this, I had to increase the multiple m in the\ngain() function by the machine epsilon. In theory increasing other\nfactors and terms in the formula may have been needed, but this proved\nenough in practice by running the roundtrip conversion on all possible\ncode values.\n\nOne challenge to test this in unit tests is that the valid gain code\nranges is not contiguous. The sensor rounds the fine gain differently\ndepending on the coarse gain, which creates holes in the range. It would\nbe feasible (and is considered) to extend the helpers to expose the\n[min, max] range of valid codes, but exposing arbitrary holes is more\nproblematic. One option would be to specify that the gain() function\nshould return NaN when the gain code is invalid. To make this safe, we\nwould need to prove that the gainCode() function will never an invalid\ngain code, ideally formally but possibly by brute force.\n---\n src/ipa/libipa/camera_sensor_helper.cpp | 87 +++++++++++++++++++\n .../sensor/camera_sensor_properties.cpp | 9 ++\n 2 files changed, 96 insertions(+)\n\n\nbase-commit: 6cd17515ffeb67fb38ffcc4d57aadf9732b54800", "diff": "diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp\nindex 782ff9904e81..c2be011300b1 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@@ -366,6 +367,92 @@ static constexpr double expGainDb(double step)\n \treturn log2_10 * step / 20;\n }\n \n+class CameraSensorHelperAr0144 : public CameraSensorHelper\n+{\n+public:\n+\tuint32_t gainCode(double gain) const override\n+\t{\n+\t\t/* The recommended minimum gain is 1.6842 to avoid artifacts. */\n+\t\tgain = std::clamp(gain, 1.0 / (1.0 - 13.0 / 32.0), 18.45);\n+\n+\t\t/*\n+\t\t * The analogue gain is made of a coarse exponential gain in\n+\t\t * the range [2^0, 2^4] and a fine inversely linear gain in the\n+\t\t * range [1.0, 2.0[. There is an additional fixed 1.153125\n+\t\t * multiplier when the coarse gain reaches 2^2.\n+\t\t */\n+\n+\t\tif (gain > 4.0)\n+\t\t\tgain /= 1.153125;\n+\n+\t\tunsigned int coarse = std::log2(gain);\n+\t\tunsigned int fine = (1 - (1 << coarse) / gain) * 32;\n+\n+\t\t/* The fine gain rounding depends on the coarse gain. */\n+\t\tif (coarse == 1 || coarse == 3)\n+\t\t\tfine &= ~1;\n+\t\telse if (coarse == 4)\n+\t\t\tfine &= ~3;\n+\n+\t\treturn (coarse << 4) | (fine & 0xf);\n+\t}\n+\n+\tdouble gain(uint32_t gainCode) const override\n+\t{\n+\t\tunsigned int coarse = gainCode >> 4;\n+\t\tunsigned int fine = gainCode & 0xf;\n+\t\tunsigned int d1;\n+\t\tdouble d2, m;\n+\n+\t\tswitch (coarse) {\n+\t\tcase 0:\n+\t\t\td1 = 1;\n+\t\t\td2 = 32.0;\n+\t\t\tm = 1.0;\n+\t\t\tbreak;\n+\t\tcase 1:\n+\t\t\td1 = 2;\n+\t\t\td2 = 16.0;\n+\t\t\tm = 1.0;\n+\t\t\tbreak;\n+\t\tcase 2:\n+\t\t\td1 = 1;\n+\t\t\td2 = 32.0;\n+\t\t\tm = 1.153125;\n+\t\t\tbreak;\n+\t\tcase 3:\n+\t\t\td1 = 2;\n+\t\t\td2 = 16.0;\n+\t\t\tm = 1.153125;\n+\t\t\tbreak;\n+\t\tcase 4:\n+\t\t\td1 = 4;\n+\t\t\td2 = 8.0;\n+\t\t\tm = 1.153125;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\t/*\n+\t\t * With infinite precision, the calculated gain would be exact,\n+\t\t * and the reverse conversion with gainCode() would produce the\n+\t\t * same gain code. In the real world, rounding errors may cause\n+\t\t * the calculated gain to be lower by an amount negligible for\n+\t\t * all purposes, except for the reverse conversion. Converting\n+\t\t * the gain to a gain code could then return the quantized value\n+\t\t * just lower than the original gain code. To avoid this, tests\n+\t\t * showed that adding the machine epsilon to the multiplier m is\n+\t\t * sufficient.\n+\t\t */\n+\t\tm += std::numeric_limits<decltype(m)>::epsilon();\n+\n+\t\treturn m * (1 << coarse) / (1.0 - (fine / d1) / d2);\n+\t}\n+\n+private:\n+\tstatic constexpr double kStep_ = 16;\n+};\n+REGISTER_CAMERA_SENSOR_HELPER(\"ar0144\", CameraSensorHelperAr0144)\n+\n class CameraSensorHelperAr0521 : public CameraSensorHelper\n {\n public:\ndiff --git a/src/libcamera/sensor/camera_sensor_properties.cpp b/src/libcamera/sensor/camera_sensor_properties.cpp\nindex 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 \tstatic const std::map<std::string, const CameraSensorProperties> sensorProps = {\n+\t\t{ \"ar0144\", {\n+\t\t\t.unitCellSize = { 3000, 3000 },\n+\t\t\t.testPatternModes = {\n+\t\t\t\t{ controls::draft::TestPatternModeOff, 0 },\n+\t\t\t\t{ controls::draft::TestPatternModeSolidColor, 1 },\n+\t\t\t\t{ controls::draft::TestPatternModeColorBars, 2 },\n+\t\t\t\t{ controls::draft::TestPatternModeColorBarsFadeToGray, 3 },\n+\t\t\t},\n+\t\t} },\n \t\t{ \"ar0521\", {\n \t\t\t.unitCellSize = { 2200, 2200 },\n \t\t\t.testPatternModes = {\n", "prefixes": [ "RFC/PATCH" ] }