summaryrefslogtreecommitdiff
path: root/src/ipa/rkisp1/algorithms/dpcc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipa/rkisp1/algorithms/dpcc.cpp')
-rw-r--r--src/ipa/rkisp1/algorithms/dpcc.cpp251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/ipa/rkisp1/algorithms/dpcc.cpp b/src/ipa/rkisp1/algorithms/dpcc.cpp
new file mode 100644
index 00000000..80a1b734
--- /dev/null
+++ b/src/ipa/rkisp1/algorithms/dpcc.cpp
@@ -0,0 +1,251 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2021-2022, Ideas On Board
+ *
+ * dpcc.cpp - RkISP1 Defect Pixel Cluster Correction control
+ */
+
+#include "dpcc.h"
+
+#include <libcamera/base/log.h>
+
+#include "libcamera/internal/yaml_parser.h"
+
+#include "linux/rkisp1-config.h"
+
+/**
+ * \file dpcc.h
+ */
+
+namespace libcamera {
+
+namespace ipa::rkisp1::algorithms {
+
+/**
+ * \class DefectPixelClusterCorrection
+ * \brief RkISP1 Defect Pixel Cluster Correction control
+ *
+ * Depending of the sensor quality, some pixels can be defective and then
+ * appear significantly brighter or darker than the other pixels.
+ *
+ * The Defect Pixel Cluster Correction algorithms is responsible to minimize
+ * the impact of the pixels. This can be done with algorithms applied at run
+ * time (on-the-fly method) or with a table of defective pixels. Only the first
+ * method is supported for the moment.
+ */
+
+LOG_DEFINE_CATEGORY(RkISP1Dpcc)
+
+DefectPixelClusterCorrection::DefectPixelClusterCorrection()
+ : config_({})
+{
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::init
+ */
+int DefectPixelClusterCorrection::init([[maybe_unused]] IPAContext &context,
+ const YamlObject &tuningData)
+{
+ config_.mode = RKISP1_CIF_ISP_DPCC_MODE_STAGE1_ENABLE;
+ config_.output_mode = RKISP1_CIF_ISP_DPCC_OUTPUT_MODE_STAGE1_INCL_G_CENTER
+ | RKISP1_CIF_ISP_DPCC_OUTPUT_MODE_STAGE1_INCL_RB_CENTER;
+
+ config_.set_use = tuningData["fixed-set"].get<bool>(false)
+ ? RKISP1_CIF_ISP_DPCC_SET_USE_STAGE1_USE_FIX_SET : 0;
+
+ /* Get all defined sets to apply (up to 3). */
+ const YamlObject &setsObject = tuningData["sets"];
+ if (!setsObject.isList()) {
+ LOG(RkISP1Dpcc, Error)
+ << "'sets' parameter not found in tuning file";
+ return -EINVAL;
+ }
+
+ if (setsObject.size() > RKISP1_CIF_ISP_DPCC_METHODS_MAX) {
+ LOG(RkISP1Dpcc, Error)
+ << "'sets' size in tuning file (" << setsObject.size()
+ << ") exceeds the maximum hardware capacity (3)";
+ return -EINVAL;
+ }
+
+ for (std::size_t i = 0; i < setsObject.size(); ++i) {
+ struct rkisp1_cif_isp_dpcc_methods_config &method = config_.methods[i];
+ const YamlObject &set = setsObject[i];
+ uint16_t value;
+
+ /* Enable set if described in YAML tuning file. */
+ config_.set_use |= 1 << i;
+
+ /* PG Method */
+ const YamlObject &pgObject = set["pg-factor"];
+
+ if (pgObject.contains("green")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_PG_GREEN_ENABLE;
+
+ value = pgObject["green"].get<uint16_t>(0);
+ method.pg_fac |= RKISP1_CIF_ISP_DPCC_PG_FAC_G(value);
+ }
+
+ if (pgObject.contains("red-blue")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_PG_RED_BLUE_ENABLE;
+
+ value = pgObject["red-blue"].get<uint16_t>(0);
+ method.pg_fac |= RKISP1_CIF_ISP_DPCC_PG_FAC_RB(value);
+ }
+
+ /* RO Method */
+ const YamlObject &roObject = set["ro-limits"];
+
+ if (roObject.contains("green")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_RO_GREEN_ENABLE;
+
+ value = roObject["green"].get<uint16_t>(0);
+ config_.ro_limits |=
+ RKISP1_CIF_ISP_DPCC_RO_LIMITS_n_G(i, value);
+ }
+
+ if (roObject.contains("red-blue")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_RO_RED_BLUE_ENABLE;
+
+ value = roObject["red-blue"].get<uint16_t>(0);
+ config_.ro_limits |=
+ RKISP1_CIF_ISP_DPCC_RO_LIMITS_n_RB(i, value);
+ }
+
+ /* RG Method */
+ const YamlObject &rgObject = set["rg-factor"];
+ method.rg_fac = 0;
+
+ if (rgObject.contains("green")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_RG_GREEN_ENABLE;
+
+ value = rgObject["green"].get<uint16_t>(0);
+ method.rg_fac |= RKISP1_CIF_ISP_DPCC_RG_FAC_G(value);
+ }
+
+ if (rgObject.contains("red-blue")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_RG_RED_BLUE_ENABLE;
+
+ value = rgObject["red-blue"].get<uint16_t>(0);
+ method.rg_fac |= RKISP1_CIF_ISP_DPCC_RG_FAC_RB(value);
+ }
+
+ /* RND Method */
+ const YamlObject &rndOffsetsObject = set["rnd-offsets"];
+
+ if (rndOffsetsObject.contains("green")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_RND_GREEN_ENABLE;
+
+ value = rndOffsetsObject["green"].get<uint16_t>(0);
+ config_.rnd_offs |=
+ RKISP1_CIF_ISP_DPCC_RND_OFFS_n_G(i, value);
+ }
+
+ if (rndOffsetsObject.contains("red-blue")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_RND_RED_BLUE_ENABLE;
+
+ value = rndOffsetsObject["red-blue"].get<uint16_t>(0);
+ config_.rnd_offs |=
+ RKISP1_CIF_ISP_DPCC_RND_OFFS_n_RB(i, value);
+ }
+
+ const YamlObject &rndThresholdObject = set["rnd-threshold"];
+ method.rnd_thresh = 0;
+
+ if (rndThresholdObject.contains("green")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_RND_GREEN_ENABLE;
+
+ value = rndThresholdObject["green"].get<uint16_t>(0);
+ method.rnd_thresh |=
+ RKISP1_CIF_ISP_DPCC_RND_THRESH_G(value);
+ }
+
+ if (rndThresholdObject.contains("red-blue")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_RND_RED_BLUE_ENABLE;
+
+ value = rndThresholdObject["red-blue"].get<uint16_t>(0);
+ method.rnd_thresh |=
+ RKISP1_CIF_ISP_DPCC_RND_THRESH_RB(value);
+ }
+
+ /* LC Method */
+ const YamlObject &lcThresholdObject = set["line-threshold"];
+ method.line_thresh = 0;
+
+ if (lcThresholdObject.contains("green")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_LC_GREEN_ENABLE;
+
+ value = lcThresholdObject["green"].get<uint16_t>(0);
+ method.line_thresh |=
+ RKISP1_CIF_ISP_DPCC_LINE_THRESH_G(value);
+ }
+
+ if (lcThresholdObject.contains("red-blue")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_LC_RED_BLUE_ENABLE;
+
+ value = lcThresholdObject["red-blue"].get<uint16_t>(0);
+ method.line_thresh |=
+ RKISP1_CIF_ISP_DPCC_LINE_THRESH_RB(value);
+ }
+
+ const YamlObject &lcTMadFactorObject = set["line-mad-factor"];
+ method.line_mad_fac = 0;
+
+ if (lcTMadFactorObject.contains("green")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_LC_GREEN_ENABLE;
+
+ value = lcTMadFactorObject["green"].get<uint16_t>(0);
+ method.line_mad_fac |=
+ RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_G(value);
+ }
+
+ if (lcTMadFactorObject.contains("red-blue")) {
+ method.method |=
+ RKISP1_CIF_ISP_DPCC_METHODS_SET_LC_RED_BLUE_ENABLE;
+
+ value = lcTMadFactorObject["red-blue"].get<uint16_t>(0);
+ method.line_mad_fac |=
+ RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_RB(value);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::prepare
+ */
+void DefectPixelClusterCorrection::prepare([[maybe_unused]] IPAContext &context,
+ const uint32_t frame,
+ [[maybe_unused]] IPAFrameContext &frameContext,
+ rkisp1_params_cfg *params)
+{
+ if (frame > 0)
+ return;
+
+ params->others.dpcc_config = config_;
+
+ params->module_en_update |= RKISP1_CIF_ISP_MODULE_DPCC;
+ params->module_ens |= RKISP1_CIF_ISP_MODULE_DPCC;
+ params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_DPCC;
+}
+
+REGISTER_IPA_ALGORITHM(DefectPixelClusterCorrection, "DefectPixelClusterCorrection")
+
+} /* namespace ipa::rkisp1::algorithms */
+
+} /* namespace libcamera */