summaryrefslogtreecommitdiff
path: root/src/ipa/raspberrypi/cam_helper_imx477.cpp
diff options
context:
space:
mode:
authorNaushir Patuck <naush@raspberrypi.com>2020-05-03 16:48:42 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-05-11 23:54:40 +0300
commit0db2c8dc75e466e7648dc1b95380495c6a126349 (patch)
treefc723a251981ded749c900947a2f510ed56e60da /src/ipa/raspberrypi/cam_helper_imx477.cpp
parent740fd1b62f670bd1ad4965ef0866ef5d51bdf947 (diff)
libcamera: ipa: Raspberry Pi IPA
Initial implementation of the Raspberry Pi (BCM2835) libcamera IPA and associated libraries. All code is licensed under the BSD-2-Clause terms. Copyright (c) 2019-2020 Raspberry Pi Trading Ltd. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src/ipa/raspberrypi/cam_helper_imx477.cpp')
-rw-r--r--src/ipa/raspberrypi/cam_helper_imx477.cpp162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/ipa/raspberrypi/cam_helper_imx477.cpp b/src/ipa/raspberrypi/cam_helper_imx477.cpp
new file mode 100644
index 00000000..69544456
--- /dev/null
+++ b/src/ipa/raspberrypi/cam_helper_imx477.cpp
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2020, Raspberry Pi (Trading) Limited
+ *
+ * cam_helper_imx477.cpp - camera helper for imx477 sensor
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cam_helper.hpp"
+#include "md_parser.hpp"
+
+using namespace RPi;
+
+/* Metadata parser implementation specific to Sony IMX477 sensors. */
+
+class MdParserImx477 : public MdParserSmia
+{
+public:
+ MdParserImx477();
+ Status Parse(void *data) override;
+ Status GetExposureLines(unsigned int &lines) override;
+ Status GetGainCode(unsigned int &gain_code) override;
+private:
+ /* Offset of the register's value in the metadata block. */
+ int reg_offsets_[4];
+ /* Value of the register, once read from the metadata block. */
+ int reg_values_[4];
+};
+
+class CamHelperImx477 : public CamHelper
+{
+public:
+ CamHelperImx477();
+ uint32_t GainCode(double gain) const override;
+ double Gain(uint32_t gain_code) const override;
+ bool SensorEmbeddedDataPresent() const override;
+ CamTransform GetOrientation() const override;
+};
+
+CamHelperImx477::CamHelperImx477()
+ : CamHelper(new MdParserImx477())
+{
+}
+
+uint32_t CamHelperImx477::GainCode(double gain) const
+{
+ return static_cast<uint32_t>(1024 - 1024 / gain);
+}
+
+double CamHelperImx477::Gain(uint32_t gain_code) const
+{
+ return 1024.0 / (1024 - gain_code);
+}
+
+bool CamHelperImx477::SensorEmbeddedDataPresent() const
+{
+ return true;
+}
+
+CamTransform CamHelperImx477::GetOrientation() const
+{
+ /* Camera is "upside down" on this board. */
+ return CamTransform_HFLIP | CamTransform_VFLIP;
+}
+
+static CamHelper *Create()
+{
+ return new CamHelperImx477();
+}
+
+static RegisterCamHelper reg("imx477", &Create);
+
+/*
+ * We care about two gain registers and a pair of exposure registers. Their
+ * I2C addresses from the Sony IMX477 datasheet:
+ */
+#define EXPHI_REG 0x0202
+#define EXPLO_REG 0x0203
+#define GAINHI_REG 0x0204
+#define GAINLO_REG 0x0205
+
+/*
+ * Index of each into the reg_offsets and reg_values arrays. Must be in register
+ * address order.
+ */
+#define EXPHI_INDEX 0
+#define EXPLO_INDEX 1
+#define GAINHI_INDEX 2
+#define GAINLO_INDEX 3
+
+MdParserImx477::MdParserImx477()
+{
+ reg_offsets_[0] = reg_offsets_[1] = reg_offsets_[2] = reg_offsets_[3] = -1;
+}
+
+MdParser::Status MdParserImx477::Parse(void *data)
+{
+ bool try_again = false;
+
+ if (reset_) {
+ /*
+ * Search again through the metadata for the gain and exposure
+ * registers.
+ */
+ assert(bits_per_pixel_);
+ assert(num_lines_ || buffer_size_bytes_);
+ /* Need to be ordered */
+ uint32_t regs[4] = {
+ EXPHI_REG,
+ EXPLO_REG,
+ GAINHI_REG,
+ GAINLO_REG
+ };
+ reg_offsets_[0] = reg_offsets_[1] = reg_offsets_[2] = reg_offsets_[3] = -1;
+ int ret = static_cast<int>(findRegs(static_cast<uint8_t *>(data),
+ regs, reg_offsets_, 4));
+ /*
+ * > 0 means "worked partially but parse again next time",
+ * < 0 means "hard error".
+ */
+ if (ret > 0)
+ try_again = true;
+ else if (ret < 0)
+ return ERROR;
+ }
+
+ for (int i = 0; i < 4; i++) {
+ if (reg_offsets_[i] == -1)
+ continue;
+
+ reg_values_[i] = static_cast<uint8_t *>(data)[reg_offsets_[i]];
+ }
+
+ /* Re-parse next time if we were unhappy in some way. */
+ reset_ = try_again;
+
+ return OK;
+}
+
+MdParser::Status MdParserImx477::GetExposureLines(unsigned int &lines)
+{
+ if (reg_offsets_[EXPHI_INDEX] == -1 || reg_offsets_[EXPLO_INDEX] == -1)
+ return NOTFOUND;
+
+ lines = reg_values_[EXPHI_INDEX] * 256 + reg_values_[EXPLO_INDEX];
+
+ return OK;
+}
+
+MdParser::Status MdParserImx477::GetGainCode(unsigned int &gain_code)
+{
+ if (reg_offsets_[GAINHI_INDEX] == -1 || reg_offsets_[GAINLO_INDEX] == -1)
+ return NOTFOUND;
+
+ gain_code = reg_values_[GAINHI_INDEX] * 256 + reg_values_[GAINLO_INDEX];
+
+ return OK;
+}