hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/media/platform/ti-vpe/csc.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Color space converter library
34 *
....@@ -6,10 +7,6 @@
67 * David Griego, <dagriego@biglakesoftware.com>
78 * Dale Farnsworth, <dale@farnsworth.org>
89 * Archit Taneja, <archit@ti.com>
9
- *
10
- * This program is free software; you can redistribute it and/or modify it
11
- * under the terms of the GNU General Public License version 2 as published by
12
- * the Free Software Foundation.
1310 */
1411
1512 #include <linux/err.h>
....@@ -18,76 +15,96 @@
1815 #include <linux/platform_device.h>
1916 #include <linux/slab.h>
2017 #include <linux/videodev2.h>
18
+#include <media/v4l2-common.h>
2119
2220 #include "csc.h"
2321
2422 /*
25
- * 16 coefficients in the order:
23
+ * 12 coefficients in the order:
2624 * a0, b0, c0, a1, b1, c1, a2, b2, c2, d0, d1, d2
27
- * (we may need to pass non-default values from user space later on, we might
28
- * need to make the coefficient struct more easy to populate)
2925 */
30
-struct colorspace_coeffs {
31
- u16 sd[12];
32
- u16 hd[12];
26
+struct quantization {
27
+ u16 coeff[12];
3328 };
3429
35
-/* VIDEO_RANGE: limited range, GRAPHICS_RANGE: full range */
36
-#define CSC_COEFFS_VIDEO_RANGE_Y2R 0
37
-#define CSC_COEFFS_GRAPHICS_RANGE_Y2R 1
38
-#define CSC_COEFFS_VIDEO_RANGE_R2Y 2
39
-#define CSC_COEFFS_GRAPHICS_RANGE_R2Y 3
30
+struct colorspace {
31
+ struct quantization limited;
32
+ struct quantization full;
33
+};
34
+
35
+struct encoding_direction {
36
+ struct colorspace r601;
37
+ struct colorspace r709;
38
+};
39
+
40
+struct csc_coeffs {
41
+ struct encoding_direction y2r;
42
+ struct encoding_direction r2y;
43
+};
4044
4145 /* default colorspace coefficients */
42
-static struct colorspace_coeffs colorspace_coeffs[4] = {
43
- [CSC_COEFFS_VIDEO_RANGE_Y2R] = {
44
- {
45
- /* SDTV */
46
- 0x0400, 0x0000, 0x057D, 0x0400, 0x1EA7, 0x1D35,
47
- 0x0400, 0x06EF, 0x1FFE, 0x0D40, 0x0210, 0x0C88,
46
+static struct csc_coeffs csc_coeffs = {
47
+ .y2r = {
48
+ .r601 = {
49
+ .limited = {
50
+ { /* SDTV */
51
+ 0x0400, 0x0000, 0x057D, 0x0400, 0x1EA7, 0x1D35,
52
+ 0x0400, 0x06EF, 0x1FFE, 0x0D40, 0x0210, 0x0C88,
53
+ }
54
+ },
55
+ .full = {
56
+ { /* SDTV */
57
+ 0x04A8, 0x1FFE, 0x0662, 0x04A8, 0x1E6F, 0x1CBF,
58
+ 0x04A8, 0x0812, 0x1FFF, 0x0C84, 0x0220, 0x0BAC,
59
+ }
60
+ },
4861 },
49
- {
50
- /* HDTV */
51
- 0x0400, 0x0000, 0x0629, 0x0400, 0x1F45, 0x1E2B,
52
- 0x0400, 0x0742, 0x0000, 0x0CEC, 0x0148, 0x0C60,
62
+ .r709 = {
63
+ .limited = {
64
+ { /* HDTV */
65
+ 0x0400, 0x0000, 0x0629, 0x0400, 0x1F45, 0x1E2B,
66
+ 0x0400, 0x0742, 0x0000, 0x0CEC, 0x0148, 0x0C60,
67
+ }
68
+ },
69
+ .full = {
70
+ { /* HDTV */
71
+ 0x04A8, 0x0000, 0x072C, 0x04A8, 0x1F26, 0x1DDE,
72
+ 0x04A8, 0x0873, 0x0000, 0x0C20, 0x0134, 0x0B7C,
73
+ }
74
+ },
5375 },
5476 },
55
- [CSC_COEFFS_GRAPHICS_RANGE_Y2R] = {
56
- {
57
- /* SDTV */
58
- 0x04A8, 0x1FFE, 0x0662, 0x04A8, 0x1E6F, 0x1CBF,
59
- 0x04A8, 0x0812, 0x1FFF, 0x0C84, 0x0220, 0x0BAC,
77
+ .r2y = {
78
+ .r601 = {
79
+ .limited = {
80
+ { /* SDTV */
81
+ 0x0132, 0x0259, 0x0075, 0x1F50, 0x1EA5, 0x020B,
82
+ 0x020B, 0x1E4A, 0x1FAB, 0x0000, 0x0200, 0x0200,
83
+ }
84
+ },
85
+ .full = {
86
+ { /* SDTV */
87
+ 0x0107, 0x0204, 0x0064, 0x1F68, 0x1ED6, 0x01C2,
88
+ 0x01C2, 0x1E87, 0x1FB7, 0x0040, 0x0200, 0x0200,
89
+ }
90
+ },
6091 },
61
- {
62
- /* HDTV */
63
- 0x04A8, 0x0000, 0x072C, 0x04A8, 0x1F26, 0x1DDE,
64
- 0x04A8, 0x0873, 0x0000, 0x0C20, 0x0134, 0x0B7C,
92
+ .r709 = {
93
+ .limited = {
94
+ { /* HDTV */
95
+ 0x00DA, 0x02DC, 0x004A, 0x1F88, 0x1E6C, 0x020C,
96
+ 0x020C, 0x1E24, 0x1FD0, 0x0000, 0x0200, 0x0200,
97
+ }
98
+ },
99
+ .full = {
100
+ { /* HDTV */
101
+ 0x00bb, 0x0275, 0x003f, 0x1f99, 0x1ea5, 0x01c2,
102
+ 0x01c2, 0x1e67, 0x1fd7, 0x0040, 0x0200, 0x0200,
103
+ }
104
+ },
65105 },
66106 },
67
- [CSC_COEFFS_VIDEO_RANGE_R2Y] = {
68
- {
69
- /* SDTV */
70
- 0x0132, 0x0259, 0x0075, 0x1F50, 0x1EA5, 0x020B,
71
- 0x020B, 0x1E4A, 0x1FAB, 0x0000, 0x0200, 0x0200,
72
- },
73
- {
74
- /* HDTV */
75
- 0x00DA, 0x02DC, 0x004A, 0x1F88, 0x1E6C, 0x020C,
76
- 0x020C, 0x1E24, 0x1FD0, 0x0000, 0x0200, 0x0200,
77
- },
78
- },
79
- [CSC_COEFFS_GRAPHICS_RANGE_R2Y] = {
80
- {
81
- /* SDTV */
82
- 0x0107, 0x0204, 0x0064, 0x1F68, 0x1ED6, 0x01C2,
83
- 0x01C2, 0x1E87, 0x1FB7, 0x0040, 0x0200, 0x0200,
84
- },
85
- {
86
- /* HDTV */
87
- 0x04A8, 0x0000, 0x072C, 0x04A8, 0x1F26, 0x1DDE,
88
- 0x04A8, 0x0873, 0x0000, 0x0C20, 0x0134, 0x0B7C,
89
- },
90
- },
107
+
91108 };
92109
93110 void csc_dump_regs(struct csc_data *csc)
....@@ -120,45 +137,105 @@
120137 * set the color space converter coefficient shadow register values
121138 */
122139 void csc_set_coeff(struct csc_data *csc, u32 *csc_reg0,
123
- enum v4l2_colorspace src_colorspace,
124
- enum v4l2_colorspace dst_colorspace)
140
+ struct v4l2_format *src_fmt, struct v4l2_format *dst_fmt)
125141 {
126142 u32 *csc_reg5 = csc_reg0 + 5;
127143 u32 *shadow_csc = csc_reg0;
128
- struct colorspace_coeffs *sd_hd_coeffs;
129144 u16 *coeff, *end_coeff;
130
- enum v4l2_colorspace yuv_colorspace;
131
- int sel = 0;
145
+ const struct v4l2_pix_format *pix;
146
+ const struct v4l2_pix_format_mplane *mp;
147
+ const struct v4l2_format_info *src_finfo, *dst_finfo;
148
+ enum v4l2_ycbcr_encoding src_ycbcr_enc, dst_ycbcr_enc;
149
+ enum v4l2_quantization src_quantization, dst_quantization;
150
+ u32 src_pixelformat, dst_pixelformat;
132151
133
- /*
134
- * support only graphics data range(full range) for now, a control ioctl
135
- * would be nice here
136
- */
137
- /* Y2R */
138
- if (dst_colorspace == V4L2_COLORSPACE_SRGB &&
139
- (src_colorspace == V4L2_COLORSPACE_SMPTE170M ||
140
- src_colorspace == V4L2_COLORSPACE_REC709)) {
152
+ if (V4L2_TYPE_IS_MULTIPLANAR(src_fmt->type)) {
153
+ mp = &src_fmt->fmt.pix_mp;
154
+ src_pixelformat = mp->pixelformat;
155
+ src_ycbcr_enc = mp->ycbcr_enc;
156
+ src_quantization = mp->quantization;
157
+ } else {
158
+ pix = &src_fmt->fmt.pix;
159
+ src_pixelformat = pix->pixelformat;
160
+ src_ycbcr_enc = pix->ycbcr_enc;
161
+ src_quantization = pix->quantization;
162
+ }
163
+
164
+ if (V4L2_TYPE_IS_MULTIPLANAR(dst_fmt->type)) {
165
+ mp = &dst_fmt->fmt.pix_mp;
166
+ dst_pixelformat = mp->pixelformat;
167
+ dst_ycbcr_enc = mp->ycbcr_enc;
168
+ dst_quantization = mp->quantization;
169
+ } else {
170
+ pix = &dst_fmt->fmt.pix;
171
+ dst_pixelformat = pix->pixelformat;
172
+ dst_ycbcr_enc = pix->ycbcr_enc;
173
+ dst_quantization = pix->quantization;
174
+ }
175
+
176
+ src_finfo = v4l2_format_info(src_pixelformat);
177
+ dst_finfo = v4l2_format_info(dst_pixelformat);
178
+
179
+ if (v4l2_is_format_yuv(src_finfo) &&
180
+ v4l2_is_format_rgb(dst_finfo)) {
141181 /* Y2R */
142
- sel = 1;
143
- yuv_colorspace = src_colorspace;
144
- } else if ((dst_colorspace == V4L2_COLORSPACE_SMPTE170M ||
145
- dst_colorspace == V4L2_COLORSPACE_REC709) &&
146
- src_colorspace == V4L2_COLORSPACE_SRGB) {
182
+
183
+ /*
184
+ * These are not the standard default values but are
185
+ * set this way for historical compatibility
186
+ */
187
+ if (src_ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT)
188
+ src_ycbcr_enc = V4L2_YCBCR_ENC_601;
189
+
190
+ if (src_quantization == V4L2_QUANTIZATION_DEFAULT)
191
+ src_quantization = V4L2_QUANTIZATION_FULL_RANGE;
192
+
193
+ if (src_ycbcr_enc == V4L2_YCBCR_ENC_601) {
194
+ if (src_quantization == V4L2_QUANTIZATION_FULL_RANGE)
195
+ coeff = csc_coeffs.y2r.r601.full.coeff;
196
+ else
197
+ coeff = csc_coeffs.y2r.r601.limited.coeff;
198
+ } else if (src_ycbcr_enc == V4L2_YCBCR_ENC_709) {
199
+ if (src_quantization == V4L2_QUANTIZATION_FULL_RANGE)
200
+ coeff = csc_coeffs.y2r.r709.full.coeff;
201
+ else
202
+ coeff = csc_coeffs.y2r.r709.limited.coeff;
203
+ } else {
204
+ /* Should never reach this, but it keeps gcc happy */
205
+ coeff = csc_coeffs.y2r.r601.full.coeff;
206
+ }
207
+ } else if (v4l2_is_format_rgb(src_finfo) &&
208
+ v4l2_is_format_yuv(dst_finfo)) {
147209 /* R2Y */
148
- sel = 3;
149
- yuv_colorspace = dst_colorspace;
210
+
211
+ /*
212
+ * These are not the standard default values but are
213
+ * set this way for historical compatibility
214
+ */
215
+ if (dst_ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT)
216
+ dst_ycbcr_enc = V4L2_YCBCR_ENC_601;
217
+
218
+ if (dst_quantization == V4L2_QUANTIZATION_DEFAULT)
219
+ dst_quantization = V4L2_QUANTIZATION_FULL_RANGE;
220
+
221
+ if (dst_ycbcr_enc == V4L2_YCBCR_ENC_601) {
222
+ if (dst_quantization == V4L2_QUANTIZATION_FULL_RANGE)
223
+ coeff = csc_coeffs.r2y.r601.full.coeff;
224
+ else
225
+ coeff = csc_coeffs.r2y.r601.limited.coeff;
226
+ } else if (dst_ycbcr_enc == V4L2_YCBCR_ENC_709) {
227
+ if (dst_quantization == V4L2_QUANTIZATION_FULL_RANGE)
228
+ coeff = csc_coeffs.r2y.r709.full.coeff;
229
+ else
230
+ coeff = csc_coeffs.r2y.r709.limited.coeff;
231
+ } else {
232
+ /* Should never reach this, but it keeps gcc happy */
233
+ coeff = csc_coeffs.r2y.r601.full.coeff;
234
+ }
150235 } else {
151236 *csc_reg5 |= CSC_BYPASS;
152237 return;
153238 }
154
-
155
- sd_hd_coeffs = &colorspace_coeffs[sel];
156
-
157
- /* select between SD or HD coefficients */
158
- if (yuv_colorspace == V4L2_COLORSPACE_SMPTE170M)
159
- coeff = sd_hd_coeffs->sd;
160
- else
161
- coeff = sd_hd_coeffs->hd;
162239
163240 end_coeff = coeff + 12;
164241