From patchwork Wed Nov 11 16:48:51 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 28861 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 7E32DC3304 for ; Wed, 11 Nov 2026 16:49:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AA43369213; Wed, 11 Nov 2026 17:49:12 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Q5QieRUZ"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 59D8D6910E for ; Wed, 11 Nov 2026 17:49:09 +0100 (CET) Received: from [192.168.1.182] (93-46-82-201.ip106.fastwebnet.it [93.46.82.201]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DE7BB8FD; Wed, 11 Nov 2026 17:46:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1794415606; bh=YUpnzKsKNu228NamQIk9vfZrob6wTXtBpRsPh9uNTpM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Q5QieRUZ6j1zDJuxDVuqURFqkubGTNR/1Cg9YQtJgPr1T3WQHg3uUON++zOt3snRp YTQj2ExyhsHXg5dr81iRy9lNETuJsmXIaqhwzdrx/z7Q+pWApf67luEiTSQgCQCDW1 9IrECY1zcRH+5vFzJkScwNDO7RTU1qd/7RgAoWoM= From: Jacopo Mondi Date: Wed, 11 Nov 2026 17:48:51 +0100 Subject: [PATCH 1/5] ipa: rpi: cam_helper: Add Mira016 cam helper MIME-Version: 1.0 Message-Id: <20261111-b4-mira016-v1-1-340bdb923426@ideasonboard.com> References: <20261111-b4-mira016-v1-0-340bdb923426@ideasonboard.com> In-Reply-To: <20261111-b4-mira016-v1-0-340bdb923426@ideasonboard.com> To: Philippe Baetens , libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3762; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=YUpnzKsKNu228NamQIk9vfZrob6wTXtBpRsPh9uNTpM=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBq9JyDDYxXL+pQqdusjevZplVU00t005O6GVp1a QI1OnKN6wqJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCavScgwAKCRByNAaPFqFW PBw6EACIhr/h65sWwhJ0Ksn1yNW+3PwQHaqYmebiI2zI9Zkm7551aRqd28+EfB8txLifltmo0Yq OD6V8lRuchBeMpF1AOL6Dwcsia0+6tYymr6/mAhOel8UzJO9/SGACNSX6e7U+OEG1kXOKWjl3+h d0zQdFu2+qbzgvBlYPlnnfUexS+WussR3IC/rVN+WAZY0p4L00Unwq9qmOMqB55MI/UU6vaOhho WqChF9VfOvQQbrlXXl+xiMEOvbjUJMsIFXb5ibyL1wrCaoLuike1fngFaNvkevsXguxCj+HkOdm kujJY/dVlEwZ0cmsLsHtmlNpNHNObvhG0Yz21udm11mMbNDSN05E+KIvx2BrNp1cVflYBnHmZIP ATlW9VAVNuzw1PQfE2oQohN8Np2BGGczcygdCmeUDa/eZwR0HMhcfjaNUw7beVrQ1RlQGElZsMD nwXnr8hVd80blH2IqUtW010nwsmR0yCxbnfmxZhZnCmoEkpNk9JtPsjQmg1qhen3ETHaDvfU9H7 GAbB6UQ8LOMLz2FfsnPNayDHidhacoTkJzKItLaWAm68gNVZfzGP67/oM3kqKrKHx7XkBNgEKJL MUgwGRJCsGIZTWo6mxChRDfUvJGOS4qZsB6Eh6KTjJHuN7lQTSDxxuUtt7jlJBKBbKUpZts/aBE QdK3KtJO+go2pEw== X-Developer-Key: i=jacopo.mondi@ideasonboard.com; a=openpgp; fpr=72392EDC88144A65C701EA9BA5826A2587AD026B X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a cam_helper to the RaspberryPi IPA for the AMS-OSRAM Mira016 sensor. The sensor black level has been measured by averaging the pixel value while covering the lens. The mira016 driver gain interface is index-based. The gain() and gainCode() function use a lookup table that translates the desired gain value to an index on the table (and vice-versa). Signed-off-by: Jacopo Mondi --- src/ipa/rpi/cam_helper/cam_helper_mira016.cpp | 88 +++++++++++++++++++++++++++ src/ipa/rpi/cam_helper/meson.build | 1 + 2 files changed, 89 insertions(+) diff --git a/src/ipa/rpi/cam_helper/cam_helper_mira016.cpp b/src/ipa/rpi/cam_helper/cam_helper_mira016.cpp new file mode 100644 index 000000000000..0bc3aefca1ea --- /dev/null +++ b/src/ipa/rpi/cam_helper/cam_helper_mira016.cpp @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2026, ams-OSRAM + * Copyright (C) 2026, Ideas on Board Oy + * + * Camera helper for Mira016 sensor + */ + +#include + +#include "cam_helper.h" + +namespace { + +using namespace RPiController; + +class CamHelperMira016 : public CamHelper +{ +public: + CamHelperMira016(); + uint32_t gainCode(double gain) const override; + double gain(uint32_t code) const override; + +private: + /* + * The sensor manual doesn't really specify a minimum difference between + * the exposure time and the frame duration, so pick a safe value of + * 4 frames. The mira016 driver uses the same value as the exposure + * margin. + */ + static constexpr int frameIntegrationDiff = 4; + + static constexpr float gainLut[] = { + 1, 1.018, 1.056, 1.075, 1.118, 1.14, 1.188, 1.213, 1.267, 1.295, + 1.326, 1.373, 1.425, 1.462, 1.5, 1.541, 1.583, 1.652, 1.701, + 1.727, 1.781, 1.839, 1.9, 1.966, 2, 2.073, 2.151, 2.192, 2.28, + 2.327, 2.426, 2.478, 2.533, 2.651, 2.714, 2.78, 2.886, 2.961, + 3.04, 3.167, 3.257, 3.353, 3.455, 3.563, 3.619, 3.738, 3.864, 4, + 4.071, 4.222, 4.302, 4.471, 4.56, 4.75, 4.851, 5.067, 5.182, + 5.302, 5.494, 5.7, 5.846, 6, 6.247, 6.423, 6.609, 6.806, 7.015, + 7.238, 7.355, 7.6, 7.862, 8.143, 8.291, 8.604, 8.769, 9.12, + 9.306, 9.702, 9.913, 10.133, 10.605, 10.857, 11.259, 11.544, + 11.844, 12.324, 12.667, 13.029, 13.412, 13.818, 14.25, 14.71, + 14.951, 15.458, 16, + }; + uint32_t sizeLut = sizeof(gainLut) / sizeof(gainLut[0]); +}; + +CamHelperMira016::CamHelperMira016() + : CamHelper({}, frameIntegrationDiff) +{ +} + +uint32_t CamHelperMira016::gainCode(double gain) const +{ + uint32_t gainCode = 0; + + while (gainCode < sizeLut - 1) { + if (gain < gainLut[gainCode + 1]) + break; + + gainCode++; + } + + /* + * The V4L2_CID_ANALOGUE_GAIN control is 1-indexed while the lookup + * table is 0-indexed. Return index+1 here, the driver adjusts it to its + * 0-indexed table. + */ + return gainCode + 1; +} + +double CamHelperMira016::gain(uint32_t gainCode) const +{ + if (gainCode >= sizeLut) + gainCode = sizeLut - 1; + + return (double)(gainLut[gainCode]); +} + +static CamHelper *create() +{ + return new CamHelperMira016(); +} + +static RegisterCamHelper reg("mira016", &create); + +} /* namespace */ diff --git a/src/ipa/rpi/cam_helper/meson.build b/src/ipa/rpi/cam_helper/meson.build index 6935cecf885f..6fc5f5c12f37 100644 --- a/src/ipa/rpi/cam_helper/meson.build +++ b/src/ipa/rpi/cam_helper/meson.build @@ -12,6 +12,7 @@ rpi_ipa_cam_helper_sources = files([ 'cam_helper_imx477.cpp', 'cam_helper_imx519.cpp', 'cam_helper_imx708.cpp', + 'cam_helper_mira016.cpp', 'cam_helper_mira220.cpp', 'cam_helper_ov64a40.cpp', 'cam_helper_ov7251.cpp',