1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2026 Renesas Electronics Corp. 4 * Copyright (C) 2026 Ideas on Board Oy 5 * Copyright (C) 2026 Ragnatech AB 6 */ 7 8 #include "rpp_module.h" 9 10 /* NOTE: The module is called LIN the registers GAMMA_IN. */ 11 #define LIN_VERSION_REG 0x0000 12 13 #define LIN_ENABLE_REG 0x0004 14 #define LIN_ENABLE_GAMMA_IN_EN BIT(0) 15 16 #define LIN_DX_LO_REG 0x0008 17 #define LIN_DX_HI_REG 0x000c 18 19 #define LIN_R_Y_REG_NUM 17 20 #define LIN_R_Y_REG(n) (0x0010 + (4 * (n))) 21 22 #define LIN_G_Y_REG_NUM 17 23 #define LIN_G_Y_REG(n) (0x0054 + (4 * (n))) 24 25 #define LIN_B_Y_REG_NUM 17 26 #define LIN_B_Y_REG(n) (0x0098 + (4 * (n))) 27 28 #define LIN_PRE1_DEGAMMA_CURVE_MASK GENMASK(23, 0) 29 #define LIN_PRE1_SAMPLE_POINTS_MASK GENMASK(3, 0) 30 #define LIN_PRE2_DEGAMMA_CURVE_MASK GENMASK(11, 0) 31 #define LIN_PRE2_SAMPLE_POINTS_MASK GENMASK(2, 0) 32 33 static int rppx1_lin_probe(struct rpp_module *mod) 34 { 35 /* Version check. */ 36 switch (rpp_module_read(mod, LIN_VERSION_REG)) { 37 case 7: 38 /* 12-bit. */ 39 break; 40 case 8: 41 /* 20-bit. */ 42 break; 43 case 9: 44 /* 24-bit. */ 45 break; 46 default: 47 return -EINVAL; 48 } 49 50 return 0; 51 } 52 53 static int rppx1_lin_start(struct rpp_module *mod, 54 const struct v4l2_mbus_framefmt *fmt) 55 { 56 rpp_module_clrset(mod, LIN_ENABLE_REG, LIN_ENABLE_GAMMA_IN_EN, 0); 57 58 return 0; 59 } 60 61 static int rppx1_lin_fill_params(struct rpp_module *mod, 62 const union rppx1_params_block *block, 63 rppx1_reg_write write, void *priv) 64 { 65 const struct rppx1_lin_params *cfg = &block->lin; 66 u8 sample_mask; 67 u32 dx_lo = 0; 68 u32 dx_hi = 0; 69 u32 mask; 70 71 if (cfg->header.flags & V4L2_ISP_PARAMS_FL_BLOCK_DISABLE) { 72 write(priv, mod->base + LIN_ENABLE_REG, 0); 73 return 0; 74 } 75 76 switch (cfg->header.type) { 77 case RPPX1_PARAMS_BLOCK_TYPE_LIN_PRE1: 78 mask = LIN_PRE1_DEGAMMA_CURVE_MASK; 79 sample_mask = LIN_PRE1_SAMPLE_POINTS_MASK; 80 break; 81 case RPPX1_PARAMS_BLOCK_TYPE_LIN_PRE2: 82 mask = LIN_PRE2_DEGAMMA_CURVE_MASK; 83 sample_mask = LIN_PRE2_SAMPLE_POINTS_MASK; 84 break; 85 default: 86 return -EINVAL; 87 } 88 89 for (unsigned int i = 0; i < 8; ++i) { 90 dx_lo |= (cfg->dx[i] & sample_mask) << 4 * i; 91 dx_hi |= (cfg->dx[i + 8] & sample_mask) << 4 * i; 92 } 93 94 write(priv, mod->base + LIN_DX_LO_REG, dx_lo); 95 write(priv, mod->base + LIN_DX_HI_REG, dx_hi); 96 97 for (unsigned int i = 0; i < RPPX1_LIN_DEGAMMA_CURVE_NUM; i++) { 98 write(priv, mod->base + LIN_R_Y_REG(i), cfg->curve_r[i] & mask); 99 write(priv, mod->base + LIN_G_Y_REG(i), cfg->curve_g[i] & mask); 100 write(priv, mod->base + LIN_B_Y_REG(i), cfg->curve_b[i] & mask); 101 } 102 103 write(priv, mod->base + LIN_ENABLE_REG, LIN_ENABLE_GAMMA_IN_EN); 104 105 return 0; 106 } 107 108 const struct rpp_module_ops rppx1_lin_ops = { 109 .probe = rppx1_lin_probe, 110 .start = rppx1_lin_start, 111 .fill_params = rppx1_lin_fill_params, 112 }; 113