forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/drivers/gpu/drm/sun4i/sun8i_csc.c
....@@ -1,13 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net>
3
- *
4
- * This program is free software; you can redistribute it and/or
5
- * modify it under the terms of the GNU General Public License as
6
- * published by the Free Software Foundation; either version 2 of
7
- * the License, or (at your option) any later version.
84 */
95
10
-#include <drm/drmP.h>
6
+#include <drm/drm_print.h>
117
128 #include "sun8i_csc.h"
139 #include "sun8i_mixer.h"
....@@ -22,43 +18,184 @@
2218 * First tree values in each line are multiplication factor and last
2319 * value is constant, which is added at the end.
2420 */
25
-static const u32 yuv2rgb[] = {
26
- 0x000004A8, 0x00000000, 0x00000662, 0xFFFC845A,
27
- 0x000004A8, 0xFFFFFE6F, 0xFFFFFCBF, 0x00021DF4,
28
- 0x000004A8, 0x00000813, 0x00000000, 0xFFFBAC4A,
21
+
22
+static const u32 yuv2rgb[2][2][12] = {
23
+ [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
24
+ [DRM_COLOR_YCBCR_BT601] = {
25
+ 0x000004A8, 0x00000000, 0x00000662, 0xFFFC8451,
26
+ 0x000004A8, 0xFFFFFE6F, 0xFFFFFCC0, 0x00021E4D,
27
+ 0x000004A8, 0x00000811, 0x00000000, 0xFFFBACA9,
28
+ },
29
+ [DRM_COLOR_YCBCR_BT709] = {
30
+ 0x000004A8, 0x00000000, 0x0000072B, 0xFFFC1F99,
31
+ 0x000004A8, 0xFFFFFF26, 0xFFFFFDDF, 0x00013383,
32
+ 0x000004A8, 0x00000873, 0x00000000, 0xFFFB7BEF,
33
+ }
34
+ },
35
+ [DRM_COLOR_YCBCR_FULL_RANGE] = {
36
+ [DRM_COLOR_YCBCR_BT601] = {
37
+ 0x00000400, 0x00000000, 0x0000059B, 0xFFFD322E,
38
+ 0x00000400, 0xFFFFFEA0, 0xFFFFFD25, 0x00021DD5,
39
+ 0x00000400, 0x00000716, 0x00000000, 0xFFFC74BD,
40
+ },
41
+ [DRM_COLOR_YCBCR_BT709] = {
42
+ 0x00000400, 0x00000000, 0x0000064C, 0xFFFCD9B4,
43
+ 0x00000400, 0xFFFFFF41, 0xFFFFFE21, 0x00014F96,
44
+ 0x00000400, 0x0000076C, 0x00000000, 0xFFFC49EF,
45
+ }
46
+ },
2947 };
3048
31
-static const u32 yvu2rgb[] = {
32
- 0x000004A8, 0x00000662, 0x00000000, 0xFFFC845A,
33
- 0x000004A8, 0xFFFFFCBF, 0xFFFFFE6F, 0x00021DF4,
34
- 0x000004A8, 0x00000000, 0x00000813, 0xFFFBAC4A,
49
+static const u32 yvu2rgb[2][2][12] = {
50
+ [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
51
+ [DRM_COLOR_YCBCR_BT601] = {
52
+ 0x000004A8, 0x00000662, 0x00000000, 0xFFFC8451,
53
+ 0x000004A8, 0xFFFFFCC0, 0xFFFFFE6F, 0x00021E4D,
54
+ 0x000004A8, 0x00000000, 0x00000811, 0xFFFBACA9,
55
+ },
56
+ [DRM_COLOR_YCBCR_BT709] = {
57
+ 0x000004A8, 0x0000072B, 0x00000000, 0xFFFC1F99,
58
+ 0x000004A8, 0xFFFFFDDF, 0xFFFFFF26, 0x00013383,
59
+ 0x000004A8, 0x00000000, 0x00000873, 0xFFFB7BEF,
60
+ }
61
+ },
62
+ [DRM_COLOR_YCBCR_FULL_RANGE] = {
63
+ [DRM_COLOR_YCBCR_BT601] = {
64
+ 0x00000400, 0x0000059B, 0x00000000, 0xFFFD322E,
65
+ 0x00000400, 0xFFFFFD25, 0xFFFFFEA0, 0x00021DD5,
66
+ 0x00000400, 0x00000000, 0x00000716, 0xFFFC74BD,
67
+ },
68
+ [DRM_COLOR_YCBCR_BT709] = {
69
+ 0x00000400, 0x0000064C, 0x00000000, 0xFFFCD9B4,
70
+ 0x00000400, 0xFFFFFE21, 0xFFFFFF41, 0x00014F96,
71
+ 0x00000400, 0x00000000, 0x0000076C, 0xFFFC49EF,
72
+ }
73
+ },
74
+};
75
+
76
+/*
77
+ * DE3 has a bit different CSC units. Factors are in two's complement format.
78
+ * First three factors in a row are multiplication factors which have 17 bits
79
+ * for fractional part. Fourth value in a row is comprised of two factors.
80
+ * Upper 16 bits represents difference, which is subtracted from the input
81
+ * value before multiplication and lower 16 bits represents constant, which
82
+ * is addes at the end.
83
+ *
84
+ * x' = c00 * (x + d0) + c01 * (y + d1) + c02 * (z + d2) + const0
85
+ * y' = c10 * (x + d0) + c11 * (y + d1) + c12 * (z + d2) + const1
86
+ * z' = c20 * (x + d0) + c21 * (y + d1) + c22 * (z + d2) + const2
87
+ *
88
+ * Please note that above formula is true only for Blender CSC. Other DE3 CSC
89
+ * units takes only positive value for difference. From what can be deducted
90
+ * from BSP driver code, those units probably automatically assume that
91
+ * difference has to be subtracted.
92
+ *
93
+ * Layout of factors in table:
94
+ * c00 c01 c02 [d0 const0]
95
+ * c10 c11 c12 [d1 const1]
96
+ * c20 c21 c22 [d2 const2]
97
+ */
98
+
99
+static const u32 yuv2rgb_de3[2][2][12] = {
100
+ [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
101
+ [DRM_COLOR_YCBCR_BT601] = {
102
+ 0x0002542A, 0x00000000, 0x0003312A, 0xFFC00000,
103
+ 0x0002542A, 0xFFFF376B, 0xFFFE5FC3, 0xFE000000,
104
+ 0x0002542A, 0x000408D2, 0x00000000, 0xFE000000,
105
+ },
106
+ [DRM_COLOR_YCBCR_BT709] = {
107
+ 0x0002542A, 0x00000000, 0x000395E2, 0xFFC00000,
108
+ 0x0002542A, 0xFFFF92D2, 0xFFFEEF27, 0xFE000000,
109
+ 0x0002542A, 0x0004398C, 0x00000000, 0xFE000000,
110
+ }
111
+ },
112
+ [DRM_COLOR_YCBCR_FULL_RANGE] = {
113
+ [DRM_COLOR_YCBCR_BT601] = {
114
+ 0x00020000, 0x00000000, 0x0002CDD2, 0x00000000,
115
+ 0x00020000, 0xFFFF4FCE, 0xFFFE925D, 0xFE000000,
116
+ 0x00020000, 0x00038B43, 0x00000000, 0xFE000000,
117
+ },
118
+ [DRM_COLOR_YCBCR_BT709] = {
119
+ 0x00020000, 0x00000000, 0x0003264C, 0x00000000,
120
+ 0x00020000, 0xFFFFA018, 0xFFFF1053, 0xFE000000,
121
+ 0x00020000, 0x0003B611, 0x00000000, 0xFE000000,
122
+ }
123
+ },
124
+};
125
+
126
+static const u32 yvu2rgb_de3[2][2][12] = {
127
+ [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
128
+ [DRM_COLOR_YCBCR_BT601] = {
129
+ 0x0002542A, 0x0003312A, 0x00000000, 0xFFC00000,
130
+ 0x0002542A, 0xFFFE5FC3, 0xFFFF376B, 0xFE000000,
131
+ 0x0002542A, 0x00000000, 0x000408D2, 0xFE000000,
132
+ },
133
+ [DRM_COLOR_YCBCR_BT709] = {
134
+ 0x0002542A, 0x000395E2, 0x00000000, 0xFFC00000,
135
+ 0x0002542A, 0xFFFEEF27, 0xFFFF92D2, 0xFE000000,
136
+ 0x0002542A, 0x00000000, 0x0004398C, 0xFE000000,
137
+ }
138
+ },
139
+ [DRM_COLOR_YCBCR_FULL_RANGE] = {
140
+ [DRM_COLOR_YCBCR_BT601] = {
141
+ 0x00020000, 0x0002CDD2, 0x00000000, 0x00000000,
142
+ 0x00020000, 0xFFFE925D, 0xFFFF4FCE, 0xFE000000,
143
+ 0x00020000, 0x00000000, 0x00038B43, 0xFE000000,
144
+ },
145
+ [DRM_COLOR_YCBCR_BT709] = {
146
+ 0x00020000, 0x0003264C, 0x00000000, 0x00000000,
147
+ 0x00020000, 0xFFFF1053, 0xFFFFA018, 0xFE000000,
148
+ 0x00020000, 0x00000000, 0x0003B611, 0xFE000000,
149
+ }
150
+ },
35151 };
36152
37153 static void sun8i_csc_set_coefficients(struct regmap *map, u32 base,
38
- enum sun8i_csc_mode mode)
154
+ enum sun8i_csc_mode mode,
155
+ enum drm_color_encoding encoding,
156
+ enum drm_color_range range)
39157 {
40158 const u32 *table;
41
- int i, data;
159
+ u32 base_reg;
42160
43161 switch (mode) {
44162 case SUN8I_CSC_MODE_YUV2RGB:
45
- table = yuv2rgb;
163
+ table = yuv2rgb[range][encoding];
46164 break;
47165 case SUN8I_CSC_MODE_YVU2RGB:
48
- table = yvu2rgb;
166
+ table = yvu2rgb[range][encoding];
49167 break;
50168 default:
51169 DRM_WARN("Wrong CSC mode specified.\n");
52170 return;
53171 }
54172
55
- for (i = 0; i < 12; i++) {
56
- data = table[i];
57
- /* For some reason, 0x200 must be added to constant parts */
58
- if (((i + 1) & 3) == 0)
59
- data += 0x200;
60
- regmap_write(map, SUN8I_CSC_COEFF(base, i), data);
173
+ base_reg = SUN8I_CSC_COEFF(base, 0);
174
+ regmap_bulk_write(map, base_reg, table, 12);
175
+}
176
+
177
+static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer,
178
+ enum sun8i_csc_mode mode,
179
+ enum drm_color_encoding encoding,
180
+ enum drm_color_range range)
181
+{
182
+ const u32 *table;
183
+ u32 base_reg;
184
+
185
+ switch (mode) {
186
+ case SUN8I_CSC_MODE_YUV2RGB:
187
+ table = yuv2rgb_de3[range][encoding];
188
+ break;
189
+ case SUN8I_CSC_MODE_YVU2RGB:
190
+ table = yvu2rgb_de3[range][encoding];
191
+ break;
192
+ default:
193
+ DRM_WARN("Wrong CSC mode specified.\n");
194
+ return;
61195 }
196
+
197
+ base_reg = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0, 0);
198
+ regmap_bulk_write(map, base_reg, table, 12);
62199 }
63200
64201 static void sun8i_csc_enable(struct regmap *map, u32 base, bool enable)
....@@ -73,20 +210,49 @@
73210 regmap_update_bits(map, SUN8I_CSC_CTRL(base), SUN8I_CSC_CTRL_EN, val);
74211 }
75212
213
+static void sun8i_de3_ccsc_enable(struct regmap *map, int layer, bool enable)
214
+{
215
+ u32 val, mask;
216
+
217
+ mask = SUN50I_MIXER_BLEND_CSC_CTL_EN(layer);
218
+
219
+ if (enable)
220
+ val = mask;
221
+ else
222
+ val = 0;
223
+
224
+ regmap_update_bits(map, SUN50I_MIXER_BLEND_CSC_CTL(DE3_BLD_BASE),
225
+ mask, val);
226
+}
227
+
76228 void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
77
- enum sun8i_csc_mode mode)
229
+ enum sun8i_csc_mode mode,
230
+ enum drm_color_encoding encoding,
231
+ enum drm_color_range range)
78232 {
79233 u32 base;
80234
235
+ if (mixer->cfg->is_de3) {
236
+ sun8i_de3_ccsc_set_coefficients(mixer->engine.regs, layer,
237
+ mode, encoding, range);
238
+ return;
239
+ }
240
+
81241 base = ccsc_base[mixer->cfg->ccsc][layer];
82242
83
- sun8i_csc_set_coefficients(mixer->engine.regs, base, mode);
243
+ sun8i_csc_set_coefficients(mixer->engine.regs, base,
244
+ mode, encoding, range);
84245 }
85246
86247 void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable)
87248 {
88249 u32 base;
89250
251
+ if (mixer->cfg->is_de3) {
252
+ sun8i_de3_ccsc_enable(mixer->engine.regs, layer, enable);
253
+ return;
254
+ }
255
+
90256 base = ccsc_base[mixer->cfg->ccsc][layer];
91257
92258 sun8i_csc_enable(mixer->engine.regs, base, enable);