xref: /linux/drivers/media/platform/dreamchip/rppx1/rppx1_ccor.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 #define CCOR_VERSION_REG				0x0000
11 
12 #define CCOR_COEFF_REG_NUM				9
13 #define CCOR_COEFF_REG(n)				(0x0004 + (4 * (n)))
14 
15 #define CCOR_OFFSET_R_REG				0x0028
16 #define CCOR_OFFSET_G_REG				0x002c
17 #define CCOR_OFFSET_B_REG				0x0030
18 
19 #define CCOR_CONFIG_TYPE_REG				0x0034
20 #define CCOR_CONFIG_TYPE_USE_OFFSETS_AS_PRE_OFFSETS	BIT(1)
21 #define CCOR_CONFIG_TYPE_CCOR_RANGE_AVAILABLE		BIT(0)
22 
23 #define CCOR_RANGE_REG					0x0038
24 #define CCOR_RANGE_CCOR_C_RANGE				BIT(1)
25 #define CCOR_RANGE_CCOR_Y_RANGE				BIT(0)
26 
27 static int rppx1_ccor_probe(struct rpp_module *mod)
28 {
29 	/* Version check. */
30 	switch (rpp_module_read(mod, CCOR_VERSION_REG)) {
31 	case 3:
32 		/* 12-bit. */
33 		break;
34 	case 4:
35 		/* 20-bit. */
36 		break;
37 	case 5:
38 		/* 24-bit. */
39 		break;
40 	default:
41 		return -EINVAL;
42 	}
43 
44 	return 0;
45 }
46 
47 static int rppx1_ccor_start(struct rpp_module *mod,
48 			    const struct v4l2_mbus_framefmt *fmt)
49 {
50 	/* Configure matrix in bypass mode. */
51 	rpp_module_write(mod, CCOR_COEFF_REG(0), 0x1000);
52 	rpp_module_write(mod, CCOR_COEFF_REG(1), 0x0000);
53 	rpp_module_write(mod, CCOR_COEFF_REG(2), 0x0000);
54 
55 	rpp_module_write(mod, CCOR_COEFF_REG(3), 0x0000);
56 	rpp_module_write(mod, CCOR_COEFF_REG(4), 0x1000);
57 	rpp_module_write(mod, CCOR_COEFF_REG(5), 0x0000);
58 
59 	rpp_module_write(mod, CCOR_COEFF_REG(6), 0x0000);
60 	rpp_module_write(mod, CCOR_COEFF_REG(7), 0x0000);
61 	rpp_module_write(mod, CCOR_COEFF_REG(8), 0x1000);
62 
63 	rpp_module_write(mod, CCOR_OFFSET_R_REG, 0x00000000);
64 	rpp_module_write(mod, CCOR_OFFSET_G_REG, 0x00000000);
65 	rpp_module_write(mod, CCOR_OFFSET_B_REG, 0x00000000);
66 
67 	return 0;
68 }
69 
70 static int
71 rppx1_ccor_fill_params(struct rpp_module *mod,
72 		       const union rppx1_params_block *block,
73 		       rppx1_reg_write write, void *priv)
74 {
75 	const struct rppx1_ccor_params *cfg = &block->ccor;
76 
77 	/* If the modules is disabled, configure in bypass mode. */
78 	if (cfg->header.flags & V4L2_ISP_PARAMS_FL_BLOCK_DISABLE) {
79 		write(priv, mod->base + CCOR_COEFF_REG(0), 0x1000);
80 		write(priv, mod->base + CCOR_COEFF_REG(1), 0x0000);
81 		write(priv, mod->base + CCOR_COEFF_REG(2), 0x0000);
82 
83 		write(priv, mod->base + CCOR_COEFF_REG(3), 0x0000);
84 		write(priv, mod->base + CCOR_COEFF_REG(4), 0x1000);
85 		write(priv, mod->base + CCOR_COEFF_REG(5), 0x0000);
86 
87 		write(priv, mod->base + CCOR_COEFF_REG(6), 0x0000);
88 		write(priv, mod->base + CCOR_COEFF_REG(7), 0x0000);
89 		write(priv, mod->base + CCOR_COEFF_REG(8), 0x1000);
90 
91 		write(priv, mod->base + CCOR_OFFSET_R_REG, 0x00000000);
92 		write(priv, mod->base + CCOR_OFFSET_G_REG, 0x00000000);
93 		write(priv, mod->base + CCOR_OFFSET_B_REG, 0x00000000);
94 
95 		return 0;
96 	}
97 
98 	/*
99 	 * Coefficient n for color correction matrix.
100 	 *
101 	 * RPP coefficients are 16-bit signed fixed-point numbers with 4 bit
102 	 * integer and 12 bit fractional part ranging from -8 (0x8000) to
103 	 * +7.9996 (0x7FFF). 0 is represented by 0x0000 and a coefficient
104 	 * value of 1 as 0x1000.
105 	 */
106 	write(priv, mod->base + CCOR_COEFF_REG(0), cfg->coeff[0][0]);
107 	write(priv, mod->base + CCOR_COEFF_REG(1), cfg->coeff[0][1]);
108 	write(priv, mod->base + CCOR_COEFF_REG(2), cfg->coeff[0][2]);
109 
110 	write(priv, mod->base + CCOR_COEFF_REG(3), cfg->coeff[1][0]);
111 	write(priv, mod->base + CCOR_COEFF_REG(4), cfg->coeff[1][1]);
112 	write(priv, mod->base + CCOR_COEFF_REG(5), cfg->coeff[1][2]);
113 
114 	write(priv, mod->base + CCOR_COEFF_REG(6), cfg->coeff[2][0]);
115 	write(priv, mod->base + CCOR_COEFF_REG(7), cfg->coeff[2][1]);
116 	write(priv, mod->base + CCOR_COEFF_REG(8), cfg->coeff[2][2]);
117 
118 	/*
119 	 * Offset for color components correction matrix.
120 	 *
121 	 * Values are a two's complement integer with one sign bit.
122 	 */
123 	write(priv, mod->base + CCOR_OFFSET_R_REG, cfg->offset[0]);
124 	write(priv, mod->base + CCOR_OFFSET_G_REG, cfg->offset[1]);
125 	write(priv, mod->base + CCOR_OFFSET_B_REG, cfg->offset[2]);
126 
127 	return 0;
128 }
129 
130 const struct rpp_module_ops rppx1_ccor_ops = {
131 	.probe = rppx1_ccor_probe,
132 	.start = rppx1_ccor_start,
133 	.fill_params = rppx1_ccor_fill_params,
134 };
135 
136 static int rppx1_ccor_csm_start(struct rpp_module *mod,
137 				const struct v4l2_mbus_framefmt *fmt)
138 {
139 	/* Reuse bypass matrix setup. */
140 	if (fmt->code == MEDIA_BUS_FMT_RGB888_1X24)
141 		return rppx1_ccor_start(mod, fmt);
142 
143 	/* Color Transformation RGB to YUV according to ITU-R BT.709. */
144 	rpp_module_write(mod, CCOR_COEFF_REG(0), 0x0367);
145 	rpp_module_write(mod, CCOR_COEFF_REG(1), 0x0b71);
146 	rpp_module_write(mod, CCOR_COEFF_REG(2), 0x0128);
147 
148 	rpp_module_write(mod, CCOR_COEFF_REG(3), 0xfe2b);
149 	rpp_module_write(mod, CCOR_COEFF_REG(4), 0xf9d5);
150 	rpp_module_write(mod, CCOR_COEFF_REG(5), 0x0800);
151 
152 	rpp_module_write(mod, CCOR_COEFF_REG(6), 0x0800);
153 	rpp_module_write(mod, CCOR_COEFF_REG(7), 0xf8bc);
154 	rpp_module_write(mod, CCOR_COEFF_REG(8), 0xff44);
155 
156 	rpp_module_write(mod, CCOR_OFFSET_R_REG, 0x00000000);
157 	rpp_module_write(mod, CCOR_OFFSET_G_REG, 0x00000800);
158 	rpp_module_write(mod, CCOR_OFFSET_B_REG, 0x00000800);
159 
160 	return 0;
161 }
162 
163 const struct rpp_module_ops rppx1_ccor_csm_ops = {
164 	.probe = rppx1_ccor_probe,
165 	.start = rppx1_ccor_csm_start,
166 };
167