diff options
| author | Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> | 2026-07-30 19:12:37 +0200 |
|---|---|---|
| committer | Sakari Ailus <sakari.ailus@linux.intel.com> | 2026-07-30 20:51:35 +0300 |
| commit | 3f8a2a88365501998df6cd35ecd384be823bfa39 (patch) | |
| tree | e6176e9708ef8fb44ff9379e9669859262c034a4 /drivers | |
| parent | 9a52f7de7c20fe055b5cbb3c792e76a8562ccb2f (diff) | |
| download | linux-stable-3f8a2a88365501998df6cd35ecd384be823bfa39.tar.gz linux-stable-3f8a2a88365501998df6cd35ecd384be823bfa39.zip | |
media: rppx1: bls: Add support for black level compensation
Extend the RPPX1 driver to allow setting the black level measurement
and gain configuration. It uses the RPPX1 framework for parameters and
its writer abstraction to allow the user to control how, and when,
configuration is applied to the RPPX1.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Co-developed-by: Jai Luthra <jai.luthra+renesas@ideasonboard.com>
Signed-off-by: Jai Luthra <jai.luthra+renesas@ideasonboard.com>
Co-developed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/media/platform/dreamchip/rppx1/rpp_module.h | 1 | ||||
| -rw-r--r-- | drivers/media/platform/dreamchip/rppx1/rpp_params.c | 5 | ||||
| -rw-r--r-- | drivers/media/platform/dreamchip/rppx1/rppx1_bls.c | 97 |
3 files changed, 103 insertions, 0 deletions
diff --git a/drivers/media/platform/dreamchip/rppx1/rpp_module.h b/drivers/media/platform/dreamchip/rppx1/rpp_module.h index b134d140fe22..5e20fcdcbcc4 100644 --- a/drivers/media/platform/dreamchip/rppx1/rpp_module.h +++ b/drivers/media/platform/dreamchip/rppx1/rpp_module.h @@ -47,6 +47,7 @@ void rpp_module_clrset(struct rpp_module *mod, u32 offset, u32 mask, u32 value); union rppx1_params_block { struct v4l2_isp_block_header header; + struct rppx1_bls_params bls; struct rppx1_awbg_params awbg; struct rppx1_hist_params hist; struct rppx1_exm_params exm; diff --git a/drivers/media/platform/dreamchip/rppx1/rpp_params.c b/drivers/media/platform/dreamchip/rppx1/rpp_params.c index 975ce3a42fb5..831cf7ca154c 100644 --- a/drivers/media/platform/dreamchip/rppx1/rpp_params.c +++ b/drivers/media/platform/dreamchip/rppx1/rpp_params.c @@ -17,6 +17,8 @@ static const struct v4l2_isp_params_block_type_info rppx1_ext_params_blocks_info[] = { + RPPX1_PARAMS_BLOCK_INFO(BLS_PRE1, bls), + RPPX1_PARAMS_BLOCK_INFO(BLS_PRE2, bls), RPPX1_PARAMS_BLOCK_INFO(AWBG_PRE1, awbg), RPPX1_PARAMS_BLOCK_INFO(AWBG_PRE2, awbg), RPPX1_PARAMS_BLOCK_INFO(HIST_PRE1, hist), @@ -58,6 +60,9 @@ int rppx1_params(struct rppx1 *rpp, struct vb2_buffer *vb, size_t max_size, block_offset += block->header.size; switch (block->header.type) { + case RPPX1_PARAMS_BLOCK_TYPE_BLS_PRE1: + module = &rpp->pre1.bls; + break; case RPPX1_PARAMS_BLOCK_TYPE_AWBG_PRE1: module = &rpp->pre1.awbg; break; diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_bls.c b/drivers/media/platform/dreamchip/rppx1/rppx1_bls.c index 882a9a819229..01a61db279bf 100644 --- a/drivers/media/platform/dreamchip/rppx1/rppx1_bls.c +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_bls.c @@ -6,6 +6,7 @@ */ #include "rpp_module.h" +#include "rppx1.h" #define BLS_VERSION_REG 0x0000 @@ -32,6 +33,8 @@ #define BLS_B_MEASURED_REG 0x0040 #define BLS_C_MEASURED_REG 0x0044 #define BLS_D_MEASURED_REG 0x0048 +#define BLS_PRE1_FIXED_MASK GENMASK(24, 0) +#define BLS_PRE2_FIXED_MASK GENMASK(12, 0) static int rppx1_bls_probe(struct rpp_module *mod) { @@ -55,6 +58,100 @@ static int rppx1_bls_probe(struct rpp_module *mod) return 0; } +static void +rppx1_bls_swap_regs(struct rpp_module *mod, const u32 input[4], u32 output[4]) +{ + static const unsigned int swap[4][4] = { + [RPP_RGGB] = { 0, 1, 2, 3 }, + [RPP_GRBG] = { 1, 0, 3, 2 }, + [RPP_GBRG] = { 2, 3, 0, 1 }, + [RPP_BGGR] = { 3, 2, 1, 0 }, + }; + + /* Swap to pattern used in our path, PRE1 or PRE2. */ + struct rpp_module *acq = mod == &mod->rpp->pre1.bls ? + &mod->rpp->pre1.acq : &mod->rpp->pre2.bls; + enum rpp_raw_pattern pattern = acq->info.acq.raw_pattern; + + for (unsigned int i = 0; i < 4; ++i) + output[i] = input[swap[pattern][i]]; +} + +static int +rppx1_bls_fill_params(struct rpp_module *mod, + const union rppx1_params_block *block, + rppx1_reg_write write, void *priv) +{ + const struct rppx1_bls_params *cfg = &block->bls; + + /* If the modules is disabled, simply bypass it. */ + if (cfg->header.flags & V4L2_ISP_PARAMS_FL_BLOCK_DISABLE) { + write(priv, mod->base + BLS_CTRL_REG, 0); + return 0; + } + + u32 ctrl = BLS_CTRL_BLS_EN; + + if (cfg->mode == RPPX1_BLS_MODE_FIXED) { + static const u32 regs[] = { + BLS_A_FIXED_REG, + BLS_B_FIXED_REG, + BLS_C_FIXED_REG, + BLS_D_FIXED_REG, + }; + u32 swapped[4]; + + rppx1_bls_swap_regs(mod, regs, swapped); + + /* + * The PRE1 pipe fixed values are 24-bits + 1 sign bit, while + * the PRE2 pipe values are 12-bits + 1 sign bit. + */ + u32 mask; + + switch (cfg->header.type) { + case RPPX1_PARAMS_BLOCK_TYPE_BLS_PRE1: + mask = BLS_PRE1_FIXED_MASK; + break; + case RPPX1_PARAMS_BLOCK_TYPE_BLS_PRE2: + mask = BLS_PRE2_FIXED_MASK; + break; + default: + return -EINVAL; + } + + write(priv, mod->base + swapped[0], cfg->fixed.a & mask); + write(priv, mod->base + swapped[1], cfg->fixed.b & mask); + write(priv, mod->base + swapped[2], cfg->fixed.c & mask); + write(priv, mod->base + swapped[3], cfg->fixed.d & mask); + } else { + write(priv, mod->base + BLS_SAMPLES_REG, cfg->samples); + + if (cfg->en_windows & RPPX1_BLS_WIN_EN_WIN1) { + write(priv, mod->base + BLS_H1_START_REG, cfg->window1.h_offs); + write(priv, mod->base + BLS_H1_STOP_REG, cfg->window1.h_size); + write(priv, mod->base + BLS_V1_START_REG, cfg->window1.v_offs); + write(priv, mod->base + BLS_V1_STOP_REG, cfg->window1.v_size); + ctrl |= BLS_CTRL_BLS_WIN1; + } + + if (cfg->en_windows & RPPX1_BLS_WIN_EN_WIN2) { + write(priv, mod->base + BLS_H2_START_REG, cfg->window2.h_offs); + write(priv, mod->base + BLS_H2_STOP_REG, cfg->window2.h_size); + write(priv, mod->base + BLS_V2_START_REG, cfg->window2.v_offs); + write(priv, mod->base + BLS_V2_STOP_REG, cfg->window2.v_size); + ctrl |= BLS_CTRL_BLS_WIN2; + } + + ctrl |= BLS_CTRL_BLS_MODE_MEASURED; + } + + write(priv, mod->base + BLS_CTRL_REG, ctrl); + + return 0; +} + const struct rpp_module_ops rppx1_bls_ops = { .probe = rppx1_bls_probe, + .fill_params = rppx1_bls_fill_params, }; |
