new file mode 100644
@@ -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 <assert.h>
+
+#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 */
@@ -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',
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 <jacopo.mondi@ideasonboard.com> --- src/ipa/rpi/cam_helper/cam_helper_mira016.cpp | 93 +++++++++++++++++++++++++++ src/ipa/rpi/cam_helper/meson.build | 1 + 2 files changed, 94 insertions(+)