From patchwork Thu Nov 12 14:20:43 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 28878 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 1D37ABDE17 for ; Thu, 12 Nov 2026 14:21:08 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 556666A7F5; Thu, 12 Nov 2026 15:21:04 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="oQMYpT9R"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 106DF691CD for ; Thu, 12 Nov 2026 15:21:00 +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 D71A7802; Thu, 12 Nov 2026 15:18:35 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1794493116; bh=9i0amGK6dkJlYJV7DKxQEf6IITH1iizB82ibemxhG20=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=oQMYpT9RlsJhRfAKZk/RWA2BIniKT70NBEBYDJF1rKlRt9sNvMLor8Pm1FA3vFtp3 CGrLC1o3CXXbPqnZIX+0Jtw36HEe3fFa1D0JqV6lMe6HyEx6zBCzlt4xNY6FRM1t+K vEGkQpbJynxsljqnEzNsG3RSPmyJUmyw0TvC58NM= From: Jacopo Mondi Date: Thu, 12 Nov 2026 15:20:43 +0100 Subject: [PATCH v2 1/5] ipa: rpi: cam_helper: Add Mira016 cam helper MIME-Version: 1.0 Message-Id: <20261112-b4-mira016-v2-1-c96443a745ce@ideasonboard.com> References: <20261112-b4-mira016-v2-0-c96443a745ce@ideasonboard.com> In-Reply-To: <20261112-b4-mira016-v2-0-c96443a745ce@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=3889; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=9i0amGK6dkJlYJV7DKxQEf6IITH1iizB82ibemxhG20=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBq9ctKkHRPkMX0dwV6GH8pvY2ecZX88+BXsN6RJ DI6ecUQ1/mJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCavXLSgAKCRByNAaPFqFW PNVED/4o5qqu8qVHtdvuGf+ouICrCRnGq/RnafGpt2q6Wjl2+k/D4DycZGt1edmwny/uZSibGam NT0+GTCatbRi6xtSPS7BJzUuctykIVZ6kxFxrQDrL0DKoc1l/jcfPseDVWloPbfE22cI3H1RHQH 03SVQ+HaMSr0YP5IybzyC+gyDNi5Yy9hC+r0qtpBYVG52IO0WDOeeNHDWPTBcxZ3byyNv/yNRCr cpzjyzHgvL5VJUryoDTkQT6NFAQMgo2iIQMIApvQT0gfBkZH9/q1Eq8MT11QCIHNTCA3Phb+eh1 0PrySu2fBFYR+LeWlEyPQ2/VaqLXti/zn/Am0KV/Ci+2YtqaKo4GzkJdix/SNad7v36Cc2jmSGg ewBQ2bzWbpXe5pHUfzxjEV4fV0Wr67I7ZnIX738sfHG8oByi4dP4VW1DP4ffNZU1QDP63MsKlkZ lcwlmFZyPcUwOmUKHVgXC/3pOPBEpVqyI56YdjZI1TFMTkl9r3mpy3F7qsN/zLg/Zv0zd2L9IOO FTyqGXKegFv5N5hAyogjs+MVZsSLmEWN44Mciei0OAZ6ViXkM2w15AQOLnpiRtkU9LGjKRkEwG1 svBDVs5qPTapa6S3WM5Frq1PX2A0izk81rTPty+NPw9spr1+0KAnVv27hX4+D6OeGRmm7w48t9g TyZTmIXVbHOqLjA== 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 | 93 +++++++++++++++++++++++++++ src/ipa/rpi/cam_helper/meson.build | 1 + 2 files changed, 94 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..0bfb44ec10b0 --- /dev/null +++ b/src/ipa/rpi/cam_helper/cam_helper_mira016.cpp @@ -0,0 +1,93 @@ +/* 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 lines. The mira016 driver uses the same value as the exposure + * margin. + */ + static constexpr int frameIntegrationDiff = 4; + + static constexpr std::array gainLut{ + 1.0, 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.0, + 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.0, 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.0, 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.0, + }; + static constexpr uint32_t maxGainIndex = gainLut.size() - 1; +}; + +CamHelperMira016::CamHelperMira016() + : CamHelper({}, frameIntegrationDiff) +{ +} + +uint32_t CamHelperMira016::gainCode(double gain) const +{ + uint32_t gainCode = 0; + + while (gainCode < maxGainIndex) { + 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 +{ + /* + * The V4L2_CID_ANALOGUE_GAIN control is 1-indexed while the lookup + * table is 0-indexed. + */ + assert(gainCode > 0); + gainCode = std::min(gainCode - 1, maxGainIndex); + + return gainLut[gainCode]; +} + +CamHelper *create() +{ + return new CamHelperMira016(); +} + +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',