.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Color space converter library |
---|
3 | 4 | * |
---|
.. | .. |
---|
6 | 7 | * David Griego, <dagriego@biglakesoftware.com> |
---|
7 | 8 | * Dale Farnsworth, <dale@farnsworth.org> |
---|
8 | 9 | * 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. |
---|
13 | 10 | */ |
---|
14 | 11 | |
---|
15 | 12 | #include <linux/err.h> |
---|
.. | .. |
---|
18 | 15 | #include <linux/platform_device.h> |
---|
19 | 16 | #include <linux/slab.h> |
---|
20 | 17 | #include <linux/videodev2.h> |
---|
| 18 | +#include <media/v4l2-common.h> |
---|
21 | 19 | |
---|
22 | 20 | #include "csc.h" |
---|
23 | 21 | |
---|
24 | 22 | /* |
---|
25 | | - * 16 coefficients in the order: |
---|
| 23 | + * 12 coefficients in the order: |
---|
26 | 24 | * 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) |
---|
29 | 25 | */ |
---|
30 | | -struct colorspace_coeffs { |
---|
31 | | - u16 sd[12]; |
---|
32 | | - u16 hd[12]; |
---|
| 26 | +struct quantization { |
---|
| 27 | + u16 coeff[12]; |
---|
33 | 28 | }; |
---|
34 | 29 | |
---|
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 | +}; |
---|
40 | 44 | |
---|
41 | 45 | /* 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 | + }, |
---|
48 | 61 | }, |
---|
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 | + }, |
---|
53 | 75 | }, |
---|
54 | 76 | }, |
---|
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 | + }, |
---|
60 | 91 | }, |
---|
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 | + }, |
---|
65 | 105 | }, |
---|
66 | 106 | }, |
---|
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 | + |
---|
91 | 108 | }; |
---|
92 | 109 | |
---|
93 | 110 | void csc_dump_regs(struct csc_data *csc) |
---|
.. | .. |
---|
120 | 137 | * set the color space converter coefficient shadow register values |
---|
121 | 138 | */ |
---|
122 | 139 | 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) |
---|
125 | 141 | { |
---|
126 | 142 | u32 *csc_reg5 = csc_reg0 + 5; |
---|
127 | 143 | u32 *shadow_csc = csc_reg0; |
---|
128 | | - struct colorspace_coeffs *sd_hd_coeffs; |
---|
129 | 144 | 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; |
---|
132 | 151 | |
---|
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)) { |
---|
141 | 181 | /* 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)) { |
---|
147 | 209 | /* 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 | + } |
---|
150 | 235 | } else { |
---|
151 | 236 | *csc_reg5 |= CSC_BYPASS; |
---|
152 | 237 | return; |
---|
153 | 238 | } |
---|
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; |
---|
162 | 239 | |
---|
163 | 240 | end_coeff = coeff + 12; |
---|
164 | 241 | |
---|