[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250617103201.1594152-3-niklas.soderlund+renesas@ragnatech.se>
Date: Tue, 17 Jun 2025 12:31:56 +0200
From: Niklas Söderlund <niklas.soderlund+renesas@...natech.se>
To: Mauro Carvalho Chehab <mchehab@...nel.org>,
Jacopo Mondi <jacopo.mondi@...asonboard.com>,
Laurent Pinchart <laurent.pinchart@...asonboard.com>,
linux-media@...r.kernel.org,
linux-renesas-soc@...r.kernel.org,
linux-kernel@...r.kernel.org
Cc: Niklas Söderlund <niklas.soderlund+renesas@...natech.se>
Subject: [PATCH 2/7] media: rppx1: Add support for AWB measurement parameters and statistics
Extend the RPPX1 driver to parse parameter blocks configuring for the
auto white balance measurement window and parameters. As well as
producing the measurements as part of a statistics buffer.
This is the first ISP algorithm added to the RPPX1 driver and exercises
both the parameter and statistics API provided by the base driver. It
shows how the RkISP1 parameter and statistics buffer data can be scaled
and adopted to fit the RPPX1 hardware.
It also uses the parameter writing interface which allows the framework
user to specify how (and when) the configuration are applied to the
RPPX1.
As the RkISP1 parameters and statics buffers have lower precision then
the RPPX1 hardware the values needs to be scaled.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@...natech.se>
---
.../platform/dreamchip/rppx1/rpp_params.c | 3 +
.../platform/dreamchip/rppx1/rpp_stats.c | 4 +
.../platform/dreamchip/rppx1/rppx1_wbmeas.c | 127 ++++++++++++++++++
3 files changed, 134 insertions(+)
diff --git a/drivers/media/platform/dreamchip/rppx1/rpp_params.c b/drivers/media/platform/dreamchip/rppx1/rpp_params.c
index e0c5ceb4d72b..e7f18edc6819 100644
--- a/drivers/media/platform/dreamchip/rppx1/rpp_params.c
+++ b/drivers/media/platform/dreamchip/rppx1/rpp_params.c
@@ -23,6 +23,9 @@ int rppx1_params_rkisp1(struct rppx1 *rpp, struct rkisp1_ext_params_cfg *cfg,
block_offset += block->header.size;
switch (block->header.type) {
+ case RKISP1_EXT_PARAMS_BLOCK_TYPE_AWB_MEAS:
+ module = &rpp->post.wbmeas;
+ break;
default:
module = NULL;
break;
diff --git a/drivers/media/platform/dreamchip/rppx1/rpp_stats.c b/drivers/media/platform/dreamchip/rppx1/rpp_stats.c
index a5daa28e09cf..a6abb85f0df1 100644
--- a/drivers/media/platform/dreamchip/rppx1/rpp_stats.c
+++ b/drivers/media/platform/dreamchip/rppx1/rpp_stats.c
@@ -11,5 +11,9 @@ void rppx1_stats_fill_isr(struct rppx1 *rpp, u32 isc, void *buf)
struct rkisp1_stat_buffer *stats = buf;
stats->meas_type = 0;
+
+ if (isc & RPPX1_IRQ_ID_POST_AWB_MEAS)
+ if (!rpp_module_call(&rpp->post.wbmeas, stats_rkisp1, &stats->params))
+ stats->meas_type |= RKISP1_CIF_ISP_STAT_AWB;
}
EXPORT_SYMBOL_GPL(rppx1_stats_fill_isr);
diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_wbmeas.c b/drivers/media/platform/dreamchip/rppx1/rppx1_wbmeas.c
index 3d197d914d07..126972cfd57a 100644
--- a/drivers/media/platform/dreamchip/rppx1/rppx1_wbmeas.c
+++ b/drivers/media/platform/dreamchip/rppx1/rppx1_wbmeas.c
@@ -56,6 +56,133 @@ static int rppx1_wbmeas_probe(struct rpp_module *mod)
return 0;
}
+static int
+rppx1_wbmeas_param_rkisp1(struct rpp_module *mod,
+ const union rppx1_params_rkisp1_config *block,
+ rppx1_reg_write write, void *priv)
+{
+ const struct rkisp1_ext_params_awb_meas_config *cfg = &block->awbm;
+ /*
+ * The RkISP params are 8-bit while the RPP can be 8, 20 or 24 bit.
+ * Figure out how much we need to adjust the input parameters.
+ */
+ const unsigned int shift = mod->info.wbmeas.colorbits - 8;
+
+ /* If the modules is disabled, simply bypass it. */
+ if (cfg->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
+ write(priv, mod->base + AWB_MEAS_PROP_REG, 0);
+ return 0;
+ }
+
+ /* Program measurement window. */
+ write(priv, mod->base + AWB_MEAS_H_OFFS_REG,
+ cfg->config.awb_wnd.h_offs);
+ write(priv, mod->base + AWB_MEAS_V_OFFS_REG,
+ cfg->config.awb_wnd.v_offs);
+ write(priv, mod->base + AWB_MEAS_H_SIZE_REG,
+ cfg->config.awb_wnd.h_size);
+ write(priv, mod->base + AWB_MEAS_V_SIZE_REG,
+ cfg->config.awb_wnd.v_size);
+
+ /* Set number of frames to sample. */
+ write(priv, mod->base + AWB_MEAS_FRAMES_REG, cfg->config.frames);
+
+ if (cfg->config.awb_mode == RKISP1_CIF_ISP_AWB_MODE_YCBCR) {
+ write(priv, mod->base + AWB_MEAS_REF_CB_MAX_B_REG,
+ cfg->config.awb_ref_cb << shift);
+ write(priv, mod->base + AWB_MEAS_REF_CR_MAX_R_REG,
+ cfg->config.awb_ref_cr << shift);
+ write(priv, mod->base + AWB_MEAS_MAX_Y_REG,
+ cfg->config.max_y << shift);
+ write(priv, mod->base + AWB_MEAS_MIN_Y_MAX_G_REG,
+ cfg->config.min_y << shift);
+ write(priv, mod->base + AWB_MEAS_MAX_CSUM_REG,
+ cfg->config.max_csum << shift);
+ write(priv, mod->base + AWB_MEAS_MIN_C_REG,
+ cfg->config.min_c << shift);
+
+ /*
+ * Match RkISP1 conversion, documented as
+ * Y = 16 + 0.2500 R + 0.5000 G + 0.1094 B
+ * Cb = 128 - 0.1406 R - 0.2969 G + 0.4375 B
+ * Cr = 128 + 0.4375 R - 0.3750 G - 0.0625 B
+ *
+ * Note map Y to G. Matrix is GBR, not RGB documented for RPPX1.
+ */
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(0), 0x0800);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(1), 0x01c0);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(2), 0x0400);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(3), 0xfb40);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(4), 0x0700);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(5), 0xfdc0);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(6), 0xfa00);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(7), 0xff00);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(8), 0x0700);
+
+ write(priv, mod->base + AWB_MEAS_CCOR_OFFSET_R_REG, 0x00100000);
+ write(priv, mod->base + AWB_MEAS_CCOR_OFFSET_G_REG, 0x00800000);
+ write(priv, mod->base + AWB_MEAS_CCOR_OFFSET_B_REG, 0x00800000);
+
+ write(priv, mod->base + AWB_MEAS_PROP_REG,
+ cfg->config.enable_ymax_cmp ? AWB_MEAS_PROP_YMAX : 0 |
+ AWB_MEAS_PROP_AWB_MODE_ON);
+ } else {
+ /* The RkISP params are oddly named, but do map to RGB. */
+ write(priv, mod->base + AWB_MEAS_REF_CB_MAX_B_REG,
+ cfg->config.awb_ref_cb << shift);
+ write(priv, mod->base + AWB_MEAS_REF_CR_MAX_R_REG,
+ cfg->config.awb_ref_cr << shift);
+ write(priv, mod->base + AWB_MEAS_MIN_Y_MAX_G_REG,
+ cfg->config.min_y << shift);
+
+ /* Values from datasheet to map G to Y, B to Cb and R to Cr. */
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(0), 0x1000);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(1), 0x0000);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(2), 0x0000);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(3), 0x0000);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(4), 0x1000);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(5), 0x0000);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(6), 0x0000);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(7), 0x0000);
+ write(priv, mod->base + AWB_MEAS_CCOR_COEFF_REG(8), 0x1000);
+
+ /* Values from datasheet. */
+ write(priv, mod->base + AWB_MEAS_CCOR_OFFSET_R_REG, 0x00000000);
+ write(priv, mod->base + AWB_MEAS_CCOR_OFFSET_G_REG, 0x00000000);
+ write(priv, mod->base + AWB_MEAS_CCOR_OFFSET_B_REG, 0x00000000);
+
+ write(priv, mod->base + AWB_MEAS_PROP_REG,
+ AWB_MEAS_PROP_MEAS_MODE_RGB |
+ AWB_MEAS_PROP_AWB_MODE_ON);
+ }
+
+ return 0;
+}
+
+static int rppx1_wbmeas_stats_rkisp1(struct rpp_module *mod,
+ struct rkisp1_cif_isp_stat *stats)
+{
+ struct rkisp1_cif_isp_awb_meas *meas = &stats->awb.awb_mean[0];
+ /*
+ * The RkISP YCbCr/RGB mean stats are 8-bit while the RPP can be 8, 20
+ * or 24 bit. Figure out how much we need to adjust the output
+ * statistics.
+ */
+ const unsigned int shift = mod->info.wbmeas.colorbits - 8;
+
+ meas->cnt = rpp_module_read(mod, AWB_MEAS_WHITE_CNT_REG);
+ meas->mean_y_or_g =
+ rpp_module_read(mod, AWB_MEAS_MEAN_Y_G_REG) >> shift;
+ meas->mean_cb_or_b =
+ rpp_module_read(mod, AWB_MEAS_MEAN_CB_B_REG) >> shift;
+ meas->mean_cr_or_r =
+ rpp_module_read(mod, AWB_MEAS_MEAN_CR_R_REG) >> shift;
+
+ return 0;
+}
+
const struct rpp_module_ops rppx1_wbmeas_ops = {
.probe = rppx1_wbmeas_probe,
+ .param_rkisp1 = rppx1_wbmeas_param_rkisp1,
+ .stats_rkisp1 = rppx1_wbmeas_stats_rkisp1
};
--
2.49.0
Powered by blists - more mailing lists