summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacopo Mondi <jacopo.mondi@ideasonboard.com>2024-11-15 12:25:37 +0000
committerDaniel Scally <dan.scally@ideasonboard.com>2024-12-17 22:35:59 +0000
commitfbea6a4c023cd0757c0a7e812763c1193916fc61 (patch)
treedca5e229c23a004b19339a446ed3d9531b449dc7
parente8cae247e8ebd13f31c854dd8cd8d1b2929a8eb4 (diff)
ipa: mali-c55: Add BLC Algorithm
Add a Black Level Correction algorithm. Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> Acked-by: Nayden Kanchev <nayden.kanchev@arm.com> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
-rw-r--r--src/ipa/mali-c55/algorithms/blc.cpp140
-rw-r--r--src/ipa/mali-c55/algorithms/blc.h42
-rw-r--r--src/ipa/mali-c55/algorithms/meson.build1
-rw-r--r--src/ipa/mali-c55/ipa_context.h1
-rw-r--r--src/ipa/mali-c55/mali-c55.cpp10
5 files changed, 194 insertions, 0 deletions
diff --git a/src/ipa/mali-c55/algorithms/blc.cpp b/src/ipa/mali-c55/algorithms/blc.cpp
new file mode 100644
index 00000000..2a54c86a
--- /dev/null
+++ b/src/ipa/mali-c55/algorithms/blc.cpp
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Ideas On Board
+ *
+ * Mali-C55 sensor offset (black level) correction
+ */
+
+#include "blc.h"
+
+#include <libcamera/base/log.h>
+#include <libcamera/control_ids.h>
+
+#include "libcamera/internal/yaml_parser.h"
+
+/**
+ * \file blc.h
+ */
+
+namespace libcamera {
+
+namespace ipa::mali_c55::algorithms {
+
+/**
+ * \class BlackLevelCorrection
+ * \brief MaliC55 Black Level Correction control
+ */
+
+LOG_DEFINE_CATEGORY(MaliC55Blc)
+
+BlackLevelCorrection::BlackLevelCorrection()
+ : tuningParameters_(false)
+{
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::init
+ */
+int BlackLevelCorrection::init([[maybe_unused]] IPAContext &context,
+ const YamlObject &tuningData)
+{
+ offset00 = tuningData["offset00"].get<uint32_t>(0);
+ offset01 = tuningData["offset01"].get<uint32_t>(0);
+ offset10 = tuningData["offset10"].get<uint32_t>(0);
+ offset11 = tuningData["offset11"].get<uint32_t>(0);
+
+ if (offset00 > kMaxOffset || offset01 > kMaxOffset ||
+ offset10 > kMaxOffset || offset11 > kMaxOffset) {
+ LOG(MaliC55Blc, Error) << "Invalid black level offsets";
+ return -EINVAL;
+ }
+
+ tuningParameters_ = true;
+
+ LOG(MaliC55Blc, Debug)
+ << "Black levels: 00 " << offset00 << ", 01 " << offset01
+ << ", 10 " << offset10 << ", 11 " << offset11;
+
+ return 0;
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::configure
+ */
+int BlackLevelCorrection::configure(IPAContext &context,
+ [[maybe_unused]] const IPACameraSensorInfo &configInfo)
+{
+ /*
+ * If no Black Levels were passed in through tuning data then we could
+ * use the value from the CameraSensorHelper if one is available.
+ */
+ if (context.configuration.sensor.blackLevel &&
+ !(offset00 + offset01 + offset10 + offset11)) {
+ offset00 = context.configuration.sensor.blackLevel;
+ offset01 = context.configuration.sensor.blackLevel;
+ offset10 = context.configuration.sensor.blackLevel;
+ offset11 = context.configuration.sensor.blackLevel;
+ }
+
+ return 0;
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::prepare
+ */
+void BlackLevelCorrection::prepare([[maybe_unused]] IPAContext &context,
+ const uint32_t frame,
+ [[maybe_unused]] IPAFrameContext &frameContext,
+ mali_c55_params_buffer *params)
+{
+ mali_c55_params_block block;
+ block.data = &params->data[params->total_size];
+
+ if (frame > 0)
+ return;
+
+ if (!tuningParameters_)
+ return;
+
+ block.header->type = MALI_C55_PARAM_BLOCK_SENSOR_OFFS;
+ block.header->flags = MALI_C55_PARAM_BLOCK_FL_NONE;
+ block.header->size = sizeof(mali_c55_params_sensor_off_preshading);
+
+ block.sensor_offs->chan00 = offset00;
+ block.sensor_offs->chan01 = offset01;
+ block.sensor_offs->chan10 = offset10;
+ block.sensor_offs->chan11 = offset11;
+
+ params->total_size += block.header->size;
+}
+
+void BlackLevelCorrection::process([[maybe_unused]] IPAContext &context,
+ [[maybe_unused]] const uint32_t frame,
+ [[maybe_unused]] IPAFrameContext &frameContext,
+ [[maybe_unused]] const mali_c55_stats_buffer *stats,
+ ControlList &metadata)
+{
+ /*
+ * Black Level Offsets in tuning data need to be 20-bit, whereas the
+ * metadata expects values from a 16-bit range. Right-shift to remove
+ * the 4 least significant bits.
+ *
+ * The black levels should be reported in the order R, Gr, Gb, B. We
+ * ignore that here given we're using matching values so far, but it
+ * would be safer to check the sensor's bayer order.
+ *
+ * \todo Account for bayer order.
+ */
+ metadata.set(controls::SensorBlackLevels, {
+ static_cast<int32_t>(offset00 >> 4),
+ static_cast<int32_t>(offset01 >> 4),
+ static_cast<int32_t>(offset10 >> 4),
+ static_cast<int32_t>(offset11 >> 4),
+ });
+}
+
+REGISTER_IPA_ALGORITHM(BlackLevelCorrection, "BlackLevelCorrection")
+
+} /* namespace ipa::mali_c55::algorithms */
+
+} /* namespace libcamera */
diff --git a/src/ipa/mali-c55/algorithms/blc.h b/src/ipa/mali-c55/algorithms/blc.h
new file mode 100644
index 00000000..9696e8e9
--- /dev/null
+++ b/src/ipa/mali-c55/algorithms/blc.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Ideas On Board
+ *
+ * Mali-C55 sensor offset (black level) correction
+ */
+
+#include "algorithm.h"
+
+namespace libcamera {
+
+namespace ipa::mali_c55::algorithms {
+
+class BlackLevelCorrection : public Algorithm
+{
+public:
+ BlackLevelCorrection();
+ ~BlackLevelCorrection() = default;
+
+ int init(IPAContext &context, const YamlObject &tuningData) override;
+ int configure(IPAContext &context,
+ const IPACameraSensorInfo &configInfo) override;
+ void prepare(IPAContext &context, const uint32_t frame,
+ IPAFrameContext &frameContext,
+ mali_c55_params_buffer *params) override;
+ void process(IPAContext &context, const uint32_t frame,
+ IPAFrameContext &frameContext,
+ const mali_c55_stats_buffer *stats,
+ ControlList &metadata) override;
+
+private:
+ static constexpr uint32_t kMaxOffset = 0xfffff;
+
+ bool tuningParameters_;
+ uint32_t offset00;
+ uint32_t offset01;
+ uint32_t offset10;
+ uint32_t offset11;
+};
+
+} /* namespace ipa::mali_c55::algorithms */
+} /* namespace libcamera */
diff --git a/src/ipa/mali-c55/algorithms/meson.build b/src/ipa/mali-c55/algorithms/meson.build
index 3c872888..96808431 100644
--- a/src/ipa/mali-c55/algorithms/meson.build
+++ b/src/ipa/mali-c55/algorithms/meson.build
@@ -2,4 +2,5 @@
mali_c55_ipa_algorithms = files([
'agc.cpp',
+ 'blc.cpp',
])
diff --git a/src/ipa/mali-c55/ipa_context.h b/src/ipa/mali-c55/ipa_context.h
index 6c9019a8..af1c3d96 100644
--- a/src/ipa/mali-c55/ipa_context.h
+++ b/src/ipa/mali-c55/ipa_context.h
@@ -30,6 +30,7 @@ struct IPASessionConfiguration {
struct {
BayerFormat::Order bayerOrder;
utils::Duration lineDuration;
+ uint32_t blackLevel;
} sensor;
};
diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp
index e332c7a7..c6941a95 100644
--- a/src/ipa/mali-c55/mali-c55.cpp
+++ b/src/ipa/mali-c55/mali-c55.cpp
@@ -193,6 +193,16 @@ void IPAMaliC55::updateSessionConfiguration(const IPACameraSensorInfo &info,
context_.configuration.agc.defaultExposure = defExposure;
context_.configuration.agc.minAnalogueGain = camHelper_->gain(minGain);
context_.configuration.agc.maxAnalogueGain = camHelper_->gain(maxGain);
+
+ if (camHelper_->blackLevel().has_value()) {
+ /*
+ * The black level from CameraSensorHelper is a 16-bit value.
+ * The Mali-C55 ISP expects 20-bit settings, so we shift it to
+ * the appropriate width
+ */
+ context_.configuration.sensor.blackLevel =
+ camHelper_->blackLevel().value() << 4;
+ }
}
void IPAMaliC55::updateControls(const IPACameraSensorInfo &sensorInfo,