xref: /linux/drivers/media/platform/dreamchip/rppx1/rppx1_lin.c (revision f4cdf7ca9a1fdcca413157df19753f388a5a224e)
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