]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
[media] v4l2-tpg: Init hv_enc field with a valid value
[karo-tx-linux.git] / drivers / media / common / v4l2-tpg / v4l2-tpg-core.c
1 /*
2  * v4l2-tpg-core.c - Test Pattern Generator
3  *
4  * Note: gen_twopix and tpg_gen_text are based on code from vivi.c. See the
5  * vivi.c source for the copyright information of those functions.
6  *
7  * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
8  *
9  * This program is free software; you may redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; version 2 of the License.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
17  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22
23 #include <linux/module.h>
24 #include <media/v4l2-tpg.h>
25
26 /* Must remain in sync with enum tpg_pattern */
27 const char * const tpg_pattern_strings[] = {
28         "75% Colorbar",
29         "100% Colorbar",
30         "CSC Colorbar",
31         "Horizontal 100% Colorbar",
32         "100% Color Squares",
33         "100% Black",
34         "100% White",
35         "100% Red",
36         "100% Green",
37         "100% Blue",
38         "16x16 Checkers",
39         "2x2 Checkers",
40         "1x1 Checkers",
41         "2x2 Red/Green Checkers",
42         "1x1 Red/Green Checkers",
43         "Alternating Hor Lines",
44         "Alternating Vert Lines",
45         "One Pixel Wide Cross",
46         "Two Pixels Wide Cross",
47         "Ten Pixels Wide Cross",
48         "Gray Ramp",
49         "Noise",
50         NULL
51 };
52 EXPORT_SYMBOL_GPL(tpg_pattern_strings);
53
54 /* Must remain in sync with enum tpg_aspect */
55 const char * const tpg_aspect_strings[] = {
56         "Source Width x Height",
57         "4x3",
58         "14x9",
59         "16x9",
60         "16x9 Anamorphic",
61         NULL
62 };
63 EXPORT_SYMBOL_GPL(tpg_aspect_strings);
64
65 /*
66  * Sine table: sin[0] = 127 * sin(-180 degrees)
67  *             sin[128] = 127 * sin(0 degrees)
68  *             sin[256] = 127 * sin(180 degrees)
69  */
70 static const s8 sin[257] = {
71            0,   -4,   -7,  -11,  -13,  -18,  -20,  -22,  -26,  -29,  -33,  -35,  -37,  -41,  -43,  -48,
72          -50,  -52,  -56,  -58,  -62,  -63,  -65,  -69,  -71,  -75,  -76,  -78,  -82,  -83,  -87,  -88,
73          -90,  -93,  -94,  -97,  -99, -101, -103, -104, -107, -108, -110, -111, -112, -114, -115, -117,
74         -118, -119, -120, -121, -122, -123, -123, -124, -125, -125, -126, -126, -127, -127, -127, -127,
75         -127, -127, -127, -127, -126, -126, -125, -125, -124, -124, -123, -122, -121, -120, -119, -118,
76         -117, -116, -114, -113, -111, -110, -109, -107, -105, -103, -101, -100,  -97,  -96,  -93,  -91,
77          -90,  -87,  -85,  -82,  -80,  -76,  -75,  -73,  -69,  -67,  -63,  -62,  -60,  -56,  -54,  -50,
78          -48,  -46,  -41,  -39,  -35,  -33,  -31,  -26,  -24,  -20,  -18,  -15,  -11,   -9,   -4,   -2,
79            0,    2,    4,    9,   11,   15,   18,   20,   24,   26,   31,   33,   35,   39,   41,   46,
80           48,   50,   54,   56,   60,   62,   64,   67,   69,   73,   75,   76,   80,   82,   85,   87,
81           90,   91,   93,   96,   97,  100,  101,  103,  105,  107,  109,  110,  111,  113,  114,  116,
82          117,  118,  119,  120,  121,  122,  123,  124,  124,  125,  125,  126,  126,  127,  127,  127,
83          127,  127,  127,  127,  127,  126,  126,  125,  125,  124,  123,  123,  122,  121,  120,  119,
84          118,  117,  115,  114,  112,  111,  110,  108,  107,  104,  103,  101,   99,   97,   94,   93,
85           90,   88,   87,   83,   82,   78,   76,   75,   71,   69,   65,   64,   62,   58,   56,   52,
86           50,   48,   43,   41,   37,   35,   33,   29,   26,   22,   20,   18,   13,   11,    7,    4,
87            0,
88 };
89
90 #define cos(idx) sin[((idx) + 64) % sizeof(sin)]
91
92 /* Global font descriptor */
93 static const u8 *font8x16;
94
95 void tpg_set_font(const u8 *f)
96 {
97         font8x16 = f;
98 }
99 EXPORT_SYMBOL_GPL(tpg_set_font);
100
101 void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h)
102 {
103         memset(tpg, 0, sizeof(*tpg));
104         tpg->scaled_width = tpg->src_width = w;
105         tpg->src_height = tpg->buf_height = h;
106         tpg->crop.width = tpg->compose.width = w;
107         tpg->crop.height = tpg->compose.height = h;
108         tpg->recalc_colors = true;
109         tpg->recalc_square_border = true;
110         tpg->brightness = 128;
111         tpg->contrast = 128;
112         tpg->saturation = 128;
113         tpg->hue = 0;
114         tpg->mv_hor_mode = TPG_MOVE_NONE;
115         tpg->mv_vert_mode = TPG_MOVE_NONE;
116         tpg->field = V4L2_FIELD_NONE;
117         tpg_s_fourcc(tpg, V4L2_PIX_FMT_RGB24);
118         tpg->colorspace = V4L2_COLORSPACE_SRGB;
119         tpg->perc_fill = 100;
120         tpg->hsv_enc = V4L2_HSV_ENC_180;
121 }
122 EXPORT_SYMBOL_GPL(tpg_init);
123
124 int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
125 {
126         unsigned pat;
127         unsigned plane;
128
129         tpg->max_line_width = max_w;
130         for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++) {
131                 for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
132                         unsigned pixelsz = plane ? 2 : 4;
133
134                         tpg->lines[pat][plane] = vzalloc(max_w * 2 * pixelsz);
135                         if (!tpg->lines[pat][plane])
136                                 return -ENOMEM;
137                         if (plane == 0)
138                                 continue;
139                         tpg->downsampled_lines[pat][plane] = vzalloc(max_w * 2 * pixelsz);
140                         if (!tpg->downsampled_lines[pat][plane])
141                                 return -ENOMEM;
142                 }
143         }
144         for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
145                 unsigned pixelsz = plane ? 2 : 4;
146
147                 tpg->contrast_line[plane] = vzalloc(max_w * pixelsz);
148                 if (!tpg->contrast_line[plane])
149                         return -ENOMEM;
150                 tpg->black_line[plane] = vzalloc(max_w * pixelsz);
151                 if (!tpg->black_line[plane])
152                         return -ENOMEM;
153                 tpg->random_line[plane] = vzalloc(max_w * 2 * pixelsz);
154                 if (!tpg->random_line[plane])
155                         return -ENOMEM;
156         }
157         return 0;
158 }
159 EXPORT_SYMBOL_GPL(tpg_alloc);
160
161 void tpg_free(struct tpg_data *tpg)
162 {
163         unsigned pat;
164         unsigned plane;
165
166         for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++)
167                 for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
168                         vfree(tpg->lines[pat][plane]);
169                         tpg->lines[pat][plane] = NULL;
170                         if (plane == 0)
171                                 continue;
172                         vfree(tpg->downsampled_lines[pat][plane]);
173                         tpg->downsampled_lines[pat][plane] = NULL;
174                 }
175         for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
176                 vfree(tpg->contrast_line[plane]);
177                 vfree(tpg->black_line[plane]);
178                 vfree(tpg->random_line[plane]);
179                 tpg->contrast_line[plane] = NULL;
180                 tpg->black_line[plane] = NULL;
181                 tpg->random_line[plane] = NULL;
182         }
183 }
184 EXPORT_SYMBOL_GPL(tpg_free);
185
186 bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
187 {
188         tpg->fourcc = fourcc;
189         tpg->planes = 1;
190         tpg->buffers = 1;
191         tpg->recalc_colors = true;
192         tpg->interleaved = false;
193         tpg->vdownsampling[0] = 1;
194         tpg->hdownsampling[0] = 1;
195         tpg->hmask[0] = ~0;
196         tpg->hmask[1] = ~0;
197         tpg->hmask[2] = ~0;
198
199         switch (fourcc) {
200         case V4L2_PIX_FMT_SBGGR8:
201         case V4L2_PIX_FMT_SGBRG8:
202         case V4L2_PIX_FMT_SGRBG8:
203         case V4L2_PIX_FMT_SRGGB8:
204         case V4L2_PIX_FMT_SBGGR10:
205         case V4L2_PIX_FMT_SGBRG10:
206         case V4L2_PIX_FMT_SGRBG10:
207         case V4L2_PIX_FMT_SRGGB10:
208         case V4L2_PIX_FMT_SBGGR12:
209         case V4L2_PIX_FMT_SGBRG12:
210         case V4L2_PIX_FMT_SGRBG12:
211         case V4L2_PIX_FMT_SRGGB12:
212                 tpg->interleaved = true;
213                 tpg->vdownsampling[1] = 1;
214                 tpg->hdownsampling[1] = 1;
215                 tpg->planes = 2;
216                 /* fall through */
217         case V4L2_PIX_FMT_RGB332:
218         case V4L2_PIX_FMT_RGB565:
219         case V4L2_PIX_FMT_RGB565X:
220         case V4L2_PIX_FMT_RGB444:
221         case V4L2_PIX_FMT_XRGB444:
222         case V4L2_PIX_FMT_ARGB444:
223         case V4L2_PIX_FMT_RGB555:
224         case V4L2_PIX_FMT_XRGB555:
225         case V4L2_PIX_FMT_ARGB555:
226         case V4L2_PIX_FMT_RGB555X:
227         case V4L2_PIX_FMT_XRGB555X:
228         case V4L2_PIX_FMT_ARGB555X:
229         case V4L2_PIX_FMT_BGR666:
230         case V4L2_PIX_FMT_RGB24:
231         case V4L2_PIX_FMT_BGR24:
232         case V4L2_PIX_FMT_RGB32:
233         case V4L2_PIX_FMT_BGR32:
234         case V4L2_PIX_FMT_XRGB32:
235         case V4L2_PIX_FMT_XBGR32:
236         case V4L2_PIX_FMT_ARGB32:
237         case V4L2_PIX_FMT_ABGR32:
238                 tpg->color_enc = TGP_COLOR_ENC_RGB;
239                 break;
240         case V4L2_PIX_FMT_GREY:
241         case V4L2_PIX_FMT_Y16:
242         case V4L2_PIX_FMT_Y16_BE:
243                 tpg->color_enc = TGP_COLOR_ENC_LUMA;
244                 break;
245         case V4L2_PIX_FMT_YUV444:
246         case V4L2_PIX_FMT_YUV555:
247         case V4L2_PIX_FMT_YUV565:
248         case V4L2_PIX_FMT_YUV32:
249                 tpg->color_enc = TGP_COLOR_ENC_YCBCR;
250                 break;
251         case V4L2_PIX_FMT_YUV420M:
252         case V4L2_PIX_FMT_YVU420M:
253                 tpg->buffers = 3;
254                 /* fall through */
255         case V4L2_PIX_FMT_YUV420:
256         case V4L2_PIX_FMT_YVU420:
257                 tpg->vdownsampling[1] = 2;
258                 tpg->vdownsampling[2] = 2;
259                 tpg->hdownsampling[1] = 2;
260                 tpg->hdownsampling[2] = 2;
261                 tpg->planes = 3;
262                 tpg->color_enc = TGP_COLOR_ENC_YCBCR;
263                 break;
264         case V4L2_PIX_FMT_YUV422M:
265         case V4L2_PIX_FMT_YVU422M:
266                 tpg->buffers = 3;
267                 /* fall through */
268         case V4L2_PIX_FMT_YUV422P:
269                 tpg->vdownsampling[1] = 1;
270                 tpg->vdownsampling[2] = 1;
271                 tpg->hdownsampling[1] = 2;
272                 tpg->hdownsampling[2] = 2;
273                 tpg->planes = 3;
274                 tpg->color_enc = TGP_COLOR_ENC_YCBCR;
275                 break;
276         case V4L2_PIX_FMT_NV16M:
277         case V4L2_PIX_FMT_NV61M:
278                 tpg->buffers = 2;
279                 /* fall through */
280         case V4L2_PIX_FMT_NV16:
281         case V4L2_PIX_FMT_NV61:
282                 tpg->vdownsampling[1] = 1;
283                 tpg->hdownsampling[1] = 1;
284                 tpg->hmask[1] = ~1;
285                 tpg->planes = 2;
286                 tpg->color_enc = TGP_COLOR_ENC_YCBCR;
287                 break;
288         case V4L2_PIX_FMT_NV12M:
289         case V4L2_PIX_FMT_NV21M:
290                 tpg->buffers = 2;
291                 /* fall through */
292         case V4L2_PIX_FMT_NV12:
293         case V4L2_PIX_FMT_NV21:
294                 tpg->vdownsampling[1] = 2;
295                 tpg->hdownsampling[1] = 1;
296                 tpg->hmask[1] = ~1;
297                 tpg->planes = 2;
298                 tpg->color_enc = TGP_COLOR_ENC_YCBCR;
299                 break;
300         case V4L2_PIX_FMT_YUV444M:
301         case V4L2_PIX_FMT_YVU444M:
302                 tpg->buffers = 3;
303                 tpg->planes = 3;
304                 tpg->vdownsampling[1] = 1;
305                 tpg->vdownsampling[2] = 1;
306                 tpg->hdownsampling[1] = 1;
307                 tpg->hdownsampling[2] = 1;
308                 tpg->color_enc = TGP_COLOR_ENC_YCBCR;
309                 break;
310         case V4L2_PIX_FMT_NV24:
311         case V4L2_PIX_FMT_NV42:
312                 tpg->vdownsampling[1] = 1;
313                 tpg->hdownsampling[1] = 1;
314                 tpg->planes = 2;
315                 tpg->color_enc = TGP_COLOR_ENC_YCBCR;
316                 break;
317         case V4L2_PIX_FMT_YUYV:
318         case V4L2_PIX_FMT_UYVY:
319         case V4L2_PIX_FMT_YVYU:
320         case V4L2_PIX_FMT_VYUY:
321                 tpg->hmask[0] = ~1;
322                 tpg->color_enc = TGP_COLOR_ENC_YCBCR;
323                 break;
324         case V4L2_PIX_FMT_HSV24:
325         case V4L2_PIX_FMT_HSV32:
326                 tpg->color_enc = TGP_COLOR_ENC_HSV;
327                 break;
328         default:
329                 return false;
330         }
331
332         switch (fourcc) {
333         case V4L2_PIX_FMT_GREY:
334         case V4L2_PIX_FMT_RGB332:
335                 tpg->twopixelsize[0] = 2;
336                 break;
337         case V4L2_PIX_FMT_RGB565:
338         case V4L2_PIX_FMT_RGB565X:
339         case V4L2_PIX_FMT_RGB444:
340         case V4L2_PIX_FMT_XRGB444:
341         case V4L2_PIX_FMT_ARGB444:
342         case V4L2_PIX_FMT_RGB555:
343         case V4L2_PIX_FMT_XRGB555:
344         case V4L2_PIX_FMT_ARGB555:
345         case V4L2_PIX_FMT_RGB555X:
346         case V4L2_PIX_FMT_XRGB555X:
347         case V4L2_PIX_FMT_ARGB555X:
348         case V4L2_PIX_FMT_YUYV:
349         case V4L2_PIX_FMT_UYVY:
350         case V4L2_PIX_FMT_YVYU:
351         case V4L2_PIX_FMT_VYUY:
352         case V4L2_PIX_FMT_YUV444:
353         case V4L2_PIX_FMT_YUV555:
354         case V4L2_PIX_FMT_YUV565:
355         case V4L2_PIX_FMT_Y16:
356         case V4L2_PIX_FMT_Y16_BE:
357                 tpg->twopixelsize[0] = 2 * 2;
358                 break;
359         case V4L2_PIX_FMT_RGB24:
360         case V4L2_PIX_FMT_BGR24:
361         case V4L2_PIX_FMT_HSV24:
362                 tpg->twopixelsize[0] = 2 * 3;
363                 break;
364         case V4L2_PIX_FMT_BGR666:
365         case V4L2_PIX_FMT_RGB32:
366         case V4L2_PIX_FMT_BGR32:
367         case V4L2_PIX_FMT_XRGB32:
368         case V4L2_PIX_FMT_XBGR32:
369         case V4L2_PIX_FMT_ARGB32:
370         case V4L2_PIX_FMT_ABGR32:
371         case V4L2_PIX_FMT_YUV32:
372         case V4L2_PIX_FMT_HSV32:
373                 tpg->twopixelsize[0] = 2 * 4;
374                 break;
375         case V4L2_PIX_FMT_NV12:
376         case V4L2_PIX_FMT_NV21:
377         case V4L2_PIX_FMT_NV12M:
378         case V4L2_PIX_FMT_NV21M:
379         case V4L2_PIX_FMT_NV16:
380         case V4L2_PIX_FMT_NV61:
381         case V4L2_PIX_FMT_NV16M:
382         case V4L2_PIX_FMT_NV61M:
383         case V4L2_PIX_FMT_SBGGR8:
384         case V4L2_PIX_FMT_SGBRG8:
385         case V4L2_PIX_FMT_SGRBG8:
386         case V4L2_PIX_FMT_SRGGB8:
387                 tpg->twopixelsize[0] = 2;
388                 tpg->twopixelsize[1] = 2;
389                 break;
390         case V4L2_PIX_FMT_SRGGB10:
391         case V4L2_PIX_FMT_SGRBG10:
392         case V4L2_PIX_FMT_SGBRG10:
393         case V4L2_PIX_FMT_SBGGR10:
394         case V4L2_PIX_FMT_SRGGB12:
395         case V4L2_PIX_FMT_SGRBG12:
396         case V4L2_PIX_FMT_SGBRG12:
397         case V4L2_PIX_FMT_SBGGR12:
398                 tpg->twopixelsize[0] = 4;
399                 tpg->twopixelsize[1] = 4;
400                 break;
401         case V4L2_PIX_FMT_YUV444M:
402         case V4L2_PIX_FMT_YVU444M:
403         case V4L2_PIX_FMT_YUV422M:
404         case V4L2_PIX_FMT_YVU422M:
405         case V4L2_PIX_FMT_YUV422P:
406         case V4L2_PIX_FMT_YUV420:
407         case V4L2_PIX_FMT_YVU420:
408         case V4L2_PIX_FMT_YUV420M:
409         case V4L2_PIX_FMT_YVU420M:
410                 tpg->twopixelsize[0] = 2;
411                 tpg->twopixelsize[1] = 2;
412                 tpg->twopixelsize[2] = 2;
413                 break;
414         case V4L2_PIX_FMT_NV24:
415         case V4L2_PIX_FMT_NV42:
416                 tpg->twopixelsize[0] = 2;
417                 tpg->twopixelsize[1] = 4;
418                 break;
419         }
420         return true;
421 }
422 EXPORT_SYMBOL_GPL(tpg_s_fourcc);
423
424 void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop,
425                 const struct v4l2_rect *compose)
426 {
427         tpg->crop = *crop;
428         tpg->compose = *compose;
429         tpg->scaled_width = (tpg->src_width * tpg->compose.width +
430                                  tpg->crop.width - 1) / tpg->crop.width;
431         tpg->scaled_width &= ~1;
432         if (tpg->scaled_width > tpg->max_line_width)
433                 tpg->scaled_width = tpg->max_line_width;
434         if (tpg->scaled_width < 2)
435                 tpg->scaled_width = 2;
436         tpg->recalc_lines = true;
437 }
438 EXPORT_SYMBOL_GPL(tpg_s_crop_compose);
439
440 void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height,
441                        u32 field)
442 {
443         unsigned p;
444
445         tpg->src_width = width;
446         tpg->src_height = height;
447         tpg->field = field;
448         tpg->buf_height = height;
449         if (V4L2_FIELD_HAS_T_OR_B(field))
450                 tpg->buf_height /= 2;
451         tpg->scaled_width = width;
452         tpg->crop.top = tpg->crop.left = 0;
453         tpg->crop.width = width;
454         tpg->crop.height = height;
455         tpg->compose.top = tpg->compose.left = 0;
456         tpg->compose.width = width;
457         tpg->compose.height = tpg->buf_height;
458         for (p = 0; p < tpg->planes; p++)
459                 tpg->bytesperline[p] = (width * tpg->twopixelsize[p]) /
460                                        (2 * tpg->hdownsampling[p]);
461         tpg->recalc_square_border = true;
462 }
463 EXPORT_SYMBOL_GPL(tpg_reset_source);
464
465 static enum tpg_color tpg_get_textbg_color(struct tpg_data *tpg)
466 {
467         switch (tpg->pattern) {
468         case TPG_PAT_BLACK:
469                 return TPG_COLOR_100_WHITE;
470         case TPG_PAT_CSC_COLORBAR:
471                 return TPG_COLOR_CSC_BLACK;
472         default:
473                 return TPG_COLOR_100_BLACK;
474         }
475 }
476
477 static enum tpg_color tpg_get_textfg_color(struct tpg_data *tpg)
478 {
479         switch (tpg->pattern) {
480         case TPG_PAT_75_COLORBAR:
481         case TPG_PAT_CSC_COLORBAR:
482                 return TPG_COLOR_CSC_WHITE;
483         case TPG_PAT_BLACK:
484                 return TPG_COLOR_100_BLACK;
485         default:
486                 return TPG_COLOR_100_WHITE;
487         }
488 }
489
490 static inline int rec709_to_linear(int v)
491 {
492         v = clamp(v, 0, 0xff0);
493         return tpg_rec709_to_linear[v];
494 }
495
496 static inline int linear_to_rec709(int v)
497 {
498         v = clamp(v, 0, 0xff0);
499         return tpg_linear_to_rec709[v];
500 }
501
502 static void color_to_hsv(struct tpg_data *tpg, int r, int g, int b,
503                            int *h, int *s, int *v)
504 {
505         int max_rgb, min_rgb, diff_rgb;
506         int aux;
507         int third;
508         int third_size;
509
510         r >>= 4;
511         g >>= 4;
512         b >>= 4;
513
514         /* Value */
515         max_rgb = max3(r, g, b);
516         *v = max_rgb;
517         if (!max_rgb) {
518                 *h = 0;
519                 *s = 0;
520                 return;
521         }
522
523         /* Saturation */
524         min_rgb = min3(r, g, b);
525         diff_rgb = max_rgb - min_rgb;
526         aux = 255 * diff_rgb;
527         aux += max_rgb / 2;
528         aux /= max_rgb;
529         *s = aux;
530         if (!aux) {
531                 *h = 0;
532                 return;
533         }
534
535         third_size = (tpg->real_hsv_enc == V4L2_HSV_ENC_180) ? 60 : 85;
536
537         /* Hue */
538         if (max_rgb == r) {
539                 aux =  g - b;
540                 third = 0;
541         } else if (max_rgb == g) {
542                 aux =  b - r;
543                 third = third_size;
544         } else {
545                 aux =  r - g;
546                 third = third_size * 2;
547         }
548
549         aux *= third_size / 2;
550         aux += diff_rgb / 2;
551         aux /= diff_rgb;
552         aux += third;
553
554         /* Clamp Hue */
555         if (tpg->real_hsv_enc == V4L2_HSV_ENC_180) {
556                 if (aux < 0)
557                         aux += 180;
558                 else if (aux > 180)
559                         aux -= 180;
560         } else {
561                 aux = aux & 0xff;
562         }
563
564         *h = aux;
565 }
566
567 static void rgb2ycbcr(const int m[3][3], int r, int g, int b,
568                         int y_offset, int *y, int *cb, int *cr)
569 {
570         *y  = ((m[0][0] * r + m[0][1] * g + m[0][2] * b) >> 16) + (y_offset << 4);
571         *cb = ((m[1][0] * r + m[1][1] * g + m[1][2] * b) >> 16) + (128 << 4);
572         *cr = ((m[2][0] * r + m[2][1] * g + m[2][2] * b) >> 16) + (128 << 4);
573 }
574
575 static void color_to_ycbcr(struct tpg_data *tpg, int r, int g, int b,
576                            int *y, int *cb, int *cr)
577 {
578 #define COEFF(v, r) ((int)(0.5 + (v) * (r) * 256.0))
579
580         static const int bt601[3][3] = {
581                 { COEFF(0.299, 219),   COEFF(0.587, 219),   COEFF(0.114, 219)   },
582                 { COEFF(-0.1687, 224), COEFF(-0.3313, 224), COEFF(0.5, 224)     },
583                 { COEFF(0.5, 224),     COEFF(-0.4187, 224), COEFF(-0.0813, 224) },
584         };
585         static const int bt601_full[3][3] = {
586                 { COEFF(0.299, 255),   COEFF(0.587, 255),   COEFF(0.114, 255)   },
587                 { COEFF(-0.1687, 255), COEFF(-0.3313, 255), COEFF(0.5, 255)     },
588                 { COEFF(0.5, 255),     COEFF(-0.4187, 255), COEFF(-0.0813, 255) },
589         };
590         static const int rec709[3][3] = {
591                 { COEFF(0.2126, 219),  COEFF(0.7152, 219),  COEFF(0.0722, 219)  },
592                 { COEFF(-0.1146, 224), COEFF(-0.3854, 224), COEFF(0.5, 224)     },
593                 { COEFF(0.5, 224),     COEFF(-0.4542, 224), COEFF(-0.0458, 224) },
594         };
595         static const int rec709_full[3][3] = {
596                 { COEFF(0.2126, 255),  COEFF(0.7152, 255),  COEFF(0.0722, 255)  },
597                 { COEFF(-0.1146, 255), COEFF(-0.3854, 255), COEFF(0.5, 255)     },
598                 { COEFF(0.5, 255),     COEFF(-0.4542, 255), COEFF(-0.0458, 255) },
599         };
600         static const int smpte240m[3][3] = {
601                 { COEFF(0.212, 219),  COEFF(0.701, 219),  COEFF(0.087, 219)  },
602                 { COEFF(-0.116, 224), COEFF(-0.384, 224), COEFF(0.5, 224)    },
603                 { COEFF(0.5, 224),    COEFF(-0.445, 224), COEFF(-0.055, 224) },
604         };
605         static const int smpte240m_full[3][3] = {
606                 { COEFF(0.212, 255),  COEFF(0.701, 255),  COEFF(0.087, 255)  },
607                 { COEFF(-0.116, 255), COEFF(-0.384, 255), COEFF(0.5, 255)    },
608                 { COEFF(0.5, 255),    COEFF(-0.445, 255), COEFF(-0.055, 255) },
609         };
610         static const int bt2020[3][3] = {
611                 { COEFF(0.2627, 219),  COEFF(0.6780, 219),  COEFF(0.0593, 219)  },
612                 { COEFF(-0.1396, 224), COEFF(-0.3604, 224), COEFF(0.5, 224)     },
613                 { COEFF(0.5, 224),     COEFF(-0.4598, 224), COEFF(-0.0402, 224) },
614         };
615         static const int bt2020_full[3][3] = {
616                 { COEFF(0.2627, 255),  COEFF(0.6780, 255),  COEFF(0.0593, 255)  },
617                 { COEFF(-0.1396, 255), COEFF(-0.3604, 255), COEFF(0.5, 255)     },
618                 { COEFF(0.5, 255),     COEFF(-0.4698, 255), COEFF(-0.0402, 255) },
619         };
620         static const int bt2020c[4] = {
621                 COEFF(1.0 / 1.9404, 224), COEFF(1.0 / 1.5816, 224),
622                 COEFF(1.0 / 1.7184, 224), COEFF(1.0 / 0.9936, 224),
623         };
624         static const int bt2020c_full[4] = {
625                 COEFF(1.0 / 1.9404, 255), COEFF(1.0 / 1.5816, 255),
626                 COEFF(1.0 / 1.7184, 255), COEFF(1.0 / 0.9936, 255),
627         };
628
629         bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE;
630         unsigned y_offset = full ? 0 : 16;
631         int lin_y, yc;
632
633         switch (tpg->real_ycbcr_enc) {
634         case V4L2_YCBCR_ENC_601:
635                 rgb2ycbcr(full ? bt601_full : bt601, r, g, b, y_offset, y, cb, cr);
636                 break;
637         case V4L2_YCBCR_ENC_XV601:
638                 /* Ignore quantization range, there is only one possible
639                  * Y'CbCr encoding. */
640                 rgb2ycbcr(bt601, r, g, b, 16, y, cb, cr);
641                 break;
642         case V4L2_YCBCR_ENC_XV709:
643                 /* Ignore quantization range, there is only one possible
644                  * Y'CbCr encoding. */
645                 rgb2ycbcr(rec709, r, g, b, 16, y, cb, cr);
646                 break;
647         case V4L2_YCBCR_ENC_BT2020:
648                 rgb2ycbcr(full ? bt2020_full : bt2020, r, g, b, y_offset, y, cb, cr);
649                 break;
650         case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
651                 lin_y = (COEFF(0.2627, 255) * rec709_to_linear(r) +
652                          COEFF(0.6780, 255) * rec709_to_linear(g) +
653                          COEFF(0.0593, 255) * rec709_to_linear(b)) >> 16;
654                 yc = linear_to_rec709(lin_y);
655                 *y = full ? yc : (yc * 219) / 255 + (16 << 4);
656                 if (b <= yc)
657                         *cb = (((b - yc) * (full ? bt2020c_full[0] : bt2020c[0])) >> 16) + (128 << 4);
658                 else
659                         *cb = (((b - yc) * (full ? bt2020c_full[1] : bt2020c[1])) >> 16) + (128 << 4);
660                 if (r <= yc)
661                         *cr = (((r - yc) * (full ? bt2020c_full[2] : bt2020c[2])) >> 16) + (128 << 4);
662                 else
663                         *cr = (((r - yc) * (full ? bt2020c_full[3] : bt2020c[3])) >> 16) + (128 << 4);
664                 break;
665         case V4L2_YCBCR_ENC_SMPTE240M:
666                 rgb2ycbcr(full ? smpte240m_full : smpte240m, r, g, b, y_offset, y, cb, cr);
667                 break;
668         case V4L2_YCBCR_ENC_709:
669         default:
670                 rgb2ycbcr(full ? rec709_full : rec709, r, g, b, y_offset, y, cb, cr);
671                 break;
672         }
673 }
674
675 static void ycbcr2rgb(const int m[3][3], int y, int cb, int cr,
676                         int y_offset, int *r, int *g, int *b)
677 {
678         y -= y_offset << 4;
679         cb -= 128 << 4;
680         cr -= 128 << 4;
681         *r = m[0][0] * y + m[0][1] * cb + m[0][2] * cr;
682         *g = m[1][0] * y + m[1][1] * cb + m[1][2] * cr;
683         *b = m[2][0] * y + m[2][1] * cb + m[2][2] * cr;
684         *r = clamp(*r >> 12, 0, 0xff0);
685         *g = clamp(*g >> 12, 0, 0xff0);
686         *b = clamp(*b >> 12, 0, 0xff0);
687 }
688
689 static void ycbcr_to_color(struct tpg_data *tpg, int y, int cb, int cr,
690                            int *r, int *g, int *b)
691 {
692 #undef COEFF
693 #define COEFF(v, r) ((int)(0.5 + (v) * ((255.0 * 255.0 * 16.0) / (r))))
694         static const int bt601[3][3] = {
695                 { COEFF(1, 219), COEFF(0, 224),       COEFF(1.4020, 224)  },
696                 { COEFF(1, 219), COEFF(-0.3441, 224), COEFF(-0.7141, 224) },
697                 { COEFF(1, 219), COEFF(1.7720, 224),  COEFF(0, 224)       },
698         };
699         static const int bt601_full[3][3] = {
700                 { COEFF(1, 255), COEFF(0, 255),       COEFF(1.4020, 255)  },
701                 { COEFF(1, 255), COEFF(-0.3441, 255), COEFF(-0.7141, 255) },
702                 { COEFF(1, 255), COEFF(1.7720, 255),  COEFF(0, 255)       },
703         };
704         static const int rec709[3][3] = {
705                 { COEFF(1, 219), COEFF(0, 224),       COEFF(1.5748, 224)  },
706                 { COEFF(1, 219), COEFF(-0.1873, 224), COEFF(-0.4681, 224) },
707                 { COEFF(1, 219), COEFF(1.8556, 224),  COEFF(0, 224)       },
708         };
709         static const int rec709_full[3][3] = {
710                 { COEFF(1, 255), COEFF(0, 255),       COEFF(1.5748, 255)  },
711                 { COEFF(1, 255), COEFF(-0.1873, 255), COEFF(-0.4681, 255) },
712                 { COEFF(1, 255), COEFF(1.8556, 255),  COEFF(0, 255)       },
713         };
714         static const int smpte240m[3][3] = {
715                 { COEFF(1, 219), COEFF(0, 224),       COEFF(1.5756, 224)  },
716                 { COEFF(1, 219), COEFF(-0.2253, 224), COEFF(-0.4767, 224) },
717                 { COEFF(1, 219), COEFF(1.8270, 224),  COEFF(0, 224)       },
718         };
719         static const int smpte240m_full[3][3] = {
720                 { COEFF(1, 255), COEFF(0, 255),       COEFF(1.5756, 255)  },
721                 { COEFF(1, 255), COEFF(-0.2253, 255), COEFF(-0.4767, 255) },
722                 { COEFF(1, 255), COEFF(1.8270, 255),  COEFF(0, 255)       },
723         };
724         static const int bt2020[3][3] = {
725                 { COEFF(1, 219), COEFF(0, 224),       COEFF(1.4746, 224)  },
726                 { COEFF(1, 219), COEFF(-0.1646, 224), COEFF(-0.5714, 224) },
727                 { COEFF(1, 219), COEFF(1.8814, 224),  COEFF(0, 224)       },
728         };
729         static const int bt2020_full[3][3] = {
730                 { COEFF(1, 255), COEFF(0, 255),       COEFF(1.4746, 255)  },
731                 { COEFF(1, 255), COEFF(-0.1646, 255), COEFF(-0.5714, 255) },
732                 { COEFF(1, 255), COEFF(1.8814, 255),  COEFF(0, 255)       },
733         };
734         static const int bt2020c[4] = {
735                 COEFF(1.9404, 224), COEFF(1.5816, 224),
736                 COEFF(1.7184, 224), COEFF(0.9936, 224),
737         };
738         static const int bt2020c_full[4] = {
739                 COEFF(1.9404, 255), COEFF(1.5816, 255),
740                 COEFF(1.7184, 255), COEFF(0.9936, 255),
741         };
742
743         bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE;
744         unsigned y_offset = full ? 0 : 16;
745         int y_fac = full ? COEFF(1.0, 255) : COEFF(1.0, 219);
746         int lin_r, lin_g, lin_b, lin_y;
747
748         switch (tpg->real_ycbcr_enc) {
749         case V4L2_YCBCR_ENC_601:
750                 ycbcr2rgb(full ? bt601_full : bt601, y, cb, cr, y_offset, r, g, b);
751                 break;
752         case V4L2_YCBCR_ENC_XV601:
753                 /* Ignore quantization range, there is only one possible
754                  * Y'CbCr encoding. */
755                 ycbcr2rgb(bt601, y, cb, cr, 16, r, g, b);
756                 break;
757         case V4L2_YCBCR_ENC_XV709:
758                 /* Ignore quantization range, there is only one possible
759                  * Y'CbCr encoding. */
760                 ycbcr2rgb(rec709, y, cb, cr, 16, r, g, b);
761                 break;
762         case V4L2_YCBCR_ENC_BT2020:
763                 ycbcr2rgb(full ? bt2020_full : bt2020, y, cb, cr, y_offset, r, g, b);
764                 break;
765         case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
766                 y -= full ? 0 : 16 << 4;
767                 cb -= 128 << 4;
768                 cr -= 128 << 4;
769
770                 if (cb <= 0)
771                         *b = y_fac * y + (full ? bt2020c_full[0] : bt2020c[0]) * cb;
772                 else
773                         *b = y_fac * y + (full ? bt2020c_full[1] : bt2020c[1]) * cb;
774                 *b = *b >> 12;
775                 if (cr <= 0)
776                         *r = y_fac * y + (full ? bt2020c_full[2] : bt2020c[2]) * cr;
777                 else
778                         *r = y_fac * y + (full ? bt2020c_full[3] : bt2020c[3]) * cr;
779                 *r = *r >> 12;
780                 lin_r = rec709_to_linear(*r);
781                 lin_b = rec709_to_linear(*b);
782                 lin_y = rec709_to_linear((y * 255) / (full ? 255 : 219));
783
784                 lin_g = COEFF(1.0 / 0.6780, 255) * lin_y -
785                         COEFF(0.2627 / 0.6780, 255) * lin_r -
786                         COEFF(0.0593 / 0.6780, 255) * lin_b;
787                 *g = linear_to_rec709(lin_g >> 12);
788                 break;
789         case V4L2_YCBCR_ENC_SMPTE240M:
790                 ycbcr2rgb(full ? smpte240m_full : smpte240m, y, cb, cr, y_offset, r, g, b);
791                 break;
792         case V4L2_YCBCR_ENC_709:
793         default:
794                 ycbcr2rgb(full ? rec709_full : rec709, y, cb, cr, y_offset, r, g, b);
795                 break;
796         }
797 }
798
799 /* precalculate color bar values to speed up rendering */
800 static void precalculate_color(struct tpg_data *tpg, int k)
801 {
802         int col = k;
803         int r = tpg_colors[col].r;
804         int g = tpg_colors[col].g;
805         int b = tpg_colors[col].b;
806         int y, cb, cr;
807         bool ycbcr_valid = false;
808
809         if (k == TPG_COLOR_TEXTBG) {
810                 col = tpg_get_textbg_color(tpg);
811
812                 r = tpg_colors[col].r;
813                 g = tpg_colors[col].g;
814                 b = tpg_colors[col].b;
815         } else if (k == TPG_COLOR_TEXTFG) {
816                 col = tpg_get_textfg_color(tpg);
817
818                 r = tpg_colors[col].r;
819                 g = tpg_colors[col].g;
820                 b = tpg_colors[col].b;
821         } else if (tpg->pattern == TPG_PAT_NOISE) {
822                 r = g = b = prandom_u32_max(256);
823         } else if (k == TPG_COLOR_RANDOM) {
824                 r = g = b = tpg->qual_offset + prandom_u32_max(196);
825         } else if (k >= TPG_COLOR_RAMP) {
826                 r = g = b = k - TPG_COLOR_RAMP;
827         }
828
829         if (tpg->pattern == TPG_PAT_CSC_COLORBAR && col <= TPG_COLOR_CSC_BLACK) {
830                 r = tpg_csc_colors[tpg->colorspace][tpg->real_xfer_func][col].r;
831                 g = tpg_csc_colors[tpg->colorspace][tpg->real_xfer_func][col].g;
832                 b = tpg_csc_colors[tpg->colorspace][tpg->real_xfer_func][col].b;
833         } else {
834                 r <<= 4;
835                 g <<= 4;
836                 b <<= 4;
837         }
838
839         if (tpg->qual == TPG_QUAL_GRAY ||
840             tpg->color_enc ==  TGP_COLOR_ENC_LUMA) {
841                 /* Rec. 709 Luma function */
842                 /* (0.2126, 0.7152, 0.0722) * (255 * 256) */
843                 r = g = b = (13879 * r + 46688 * g + 4713 * b) >> 16;
844         }
845
846         /*
847          * The assumption is that the RGB output is always full range,
848          * so only if the rgb_range overrides the 'real' rgb range do
849          * we need to convert the RGB values.
850          *
851          * Remember that r, g and b are still in the 0 - 0xff0 range.
852          */
853         if (tpg->real_rgb_range == V4L2_DV_RGB_RANGE_LIMITED &&
854             tpg->rgb_range == V4L2_DV_RGB_RANGE_FULL &&
855             tpg->color_enc == TGP_COLOR_ENC_RGB) {
856                 /*
857                  * Convert from full range (which is what r, g and b are)
858                  * to limited range (which is the 'real' RGB range), which
859                  * is then interpreted as full range.
860                  */
861                 r = (r * 219) / 255 + (16 << 4);
862                 g = (g * 219) / 255 + (16 << 4);
863                 b = (b * 219) / 255 + (16 << 4);
864         } else if (tpg->real_rgb_range != V4L2_DV_RGB_RANGE_LIMITED &&
865                    tpg->rgb_range == V4L2_DV_RGB_RANGE_LIMITED &&
866                    tpg->color_enc == TGP_COLOR_ENC_RGB) {
867
868                 /*
869                  * Clamp r, g and b to the limited range and convert to full
870                  * range since that's what we deliver.
871                  */
872                 r = clamp(r, 16 << 4, 235 << 4);
873                 g = clamp(g, 16 << 4, 235 << 4);
874                 b = clamp(b, 16 << 4, 235 << 4);
875                 r = (r - (16 << 4)) * 255 / 219;
876                 g = (g - (16 << 4)) * 255 / 219;
877                 b = (b - (16 << 4)) * 255 / 219;
878         }
879
880         if ((tpg->brightness != 128 || tpg->contrast != 128 ||
881              tpg->saturation != 128 || tpg->hue) &&
882             tpg->color_enc != TGP_COLOR_ENC_LUMA) {
883                 /* Implement these operations */
884                 int tmp_cb, tmp_cr;
885
886                 /* First convert to YCbCr */
887
888                 color_to_ycbcr(tpg, r, g, b, &y, &cb, &cr);
889
890                 y = (16 << 4) + ((y - (16 << 4)) * tpg->contrast) / 128;
891                 y += (tpg->brightness << 4) - (128 << 4);
892
893                 cb -= 128 << 4;
894                 cr -= 128 << 4;
895                 tmp_cb = (cb * cos(128 + tpg->hue)) / 127 + (cr * sin[128 + tpg->hue]) / 127;
896                 tmp_cr = (cr * cos(128 + tpg->hue)) / 127 - (cb * sin[128 + tpg->hue]) / 127;
897
898                 cb = (128 << 4) + (tmp_cb * tpg->contrast * tpg->saturation) / (128 * 128);
899                 cr = (128 << 4) + (tmp_cr * tpg->contrast * tpg->saturation) / (128 * 128);
900                 if (tpg->color_enc == TGP_COLOR_ENC_YCBCR)
901                         ycbcr_valid = true;
902                 else
903                         ycbcr_to_color(tpg, y, cb, cr, &r, &g, &b);
904         } else if ((tpg->brightness != 128 || tpg->contrast != 128) &&
905                    tpg->color_enc == TGP_COLOR_ENC_LUMA) {
906                 r = (16 << 4) + ((r - (16 << 4)) * tpg->contrast) / 128;
907                 r += (tpg->brightness << 4) - (128 << 4);
908         }
909
910         switch (tpg->color_enc) {
911         case TGP_COLOR_ENC_HSV:
912         {
913                 int h, s, v;
914
915                 color_to_hsv(tpg, r, g, b, &h, &s, &v);
916                 tpg->colors[k][0] = h;
917                 tpg->colors[k][1] = s;
918                 tpg->colors[k][2] = v;
919                 break;
920         }
921         case TGP_COLOR_ENC_YCBCR:
922         {
923                 /* Convert to YCbCr */
924                 if (!ycbcr_valid)
925                         color_to_ycbcr(tpg, r, g, b, &y, &cb, &cr);
926
927                 y >>= 4;
928                 cb >>= 4;
929                 cr >>= 4;
930                 if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) {
931                         y = clamp(y, 16, 235);
932                         cb = clamp(cb, 16, 240);
933                         cr = clamp(cr, 16, 240);
934                 } else {
935                         y = clamp(y, 1, 254);
936                         cb = clamp(cb, 1, 254);
937                         cr = clamp(cr, 1, 254);
938                 }
939                 switch (tpg->fourcc) {
940                 case V4L2_PIX_FMT_YUV444:
941                         y >>= 4;
942                         cb >>= 4;
943                         cr >>= 4;
944                         break;
945                 case V4L2_PIX_FMT_YUV555:
946                         y >>= 3;
947                         cb >>= 3;
948                         cr >>= 3;
949                         break;
950                 case V4L2_PIX_FMT_YUV565:
951                         y >>= 3;
952                         cb >>= 2;
953                         cr >>= 3;
954                         break;
955                 }
956                 tpg->colors[k][0] = y;
957                 tpg->colors[k][1] = cb;
958                 tpg->colors[k][2] = cr;
959                 break;
960         }
961         case TGP_COLOR_ENC_LUMA:
962         {
963                 tpg->colors[k][0] = r >> 4;
964                 break;
965         }
966         case TGP_COLOR_ENC_RGB:
967         {
968                 if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) {
969                         r = (r * 219) / 255 + (16 << 4);
970                         g = (g * 219) / 255 + (16 << 4);
971                         b = (b * 219) / 255 + (16 << 4);
972                 }
973                 switch (tpg->fourcc) {
974                 case V4L2_PIX_FMT_RGB332:
975                         r >>= 9;
976                         g >>= 9;
977                         b >>= 10;
978                         break;
979                 case V4L2_PIX_FMT_RGB565:
980                 case V4L2_PIX_FMT_RGB565X:
981                         r >>= 7;
982                         g >>= 6;
983                         b >>= 7;
984                         break;
985                 case V4L2_PIX_FMT_RGB444:
986                 case V4L2_PIX_FMT_XRGB444:
987                 case V4L2_PIX_FMT_ARGB444:
988                         r >>= 8;
989                         g >>= 8;
990                         b >>= 8;
991                         break;
992                 case V4L2_PIX_FMT_RGB555:
993                 case V4L2_PIX_FMT_XRGB555:
994                 case V4L2_PIX_FMT_ARGB555:
995                 case V4L2_PIX_FMT_RGB555X:
996                 case V4L2_PIX_FMT_XRGB555X:
997                 case V4L2_PIX_FMT_ARGB555X:
998                         r >>= 7;
999                         g >>= 7;
1000                         b >>= 7;
1001                         break;
1002                 case V4L2_PIX_FMT_BGR666:
1003                         r >>= 6;
1004                         g >>= 6;
1005                         b >>= 6;
1006                         break;
1007                 default:
1008                         r >>= 4;
1009                         g >>= 4;
1010                         b >>= 4;
1011                         break;
1012                 }
1013
1014                 tpg->colors[k][0] = r;
1015                 tpg->colors[k][1] = g;
1016                 tpg->colors[k][2] = b;
1017                 break;
1018         }
1019         }
1020 }
1021
1022 static void tpg_precalculate_colors(struct tpg_data *tpg)
1023 {
1024         int k;
1025
1026         for (k = 0; k < TPG_COLOR_MAX; k++)
1027                 precalculate_color(tpg, k);
1028 }
1029
1030 /* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */
1031 static void gen_twopix(struct tpg_data *tpg,
1032                 u8 buf[TPG_MAX_PLANES][8], int color, bool odd)
1033 {
1034         unsigned offset = odd * tpg->twopixelsize[0] / 2;
1035         u8 alpha = tpg->alpha_component;
1036         u8 r_y_h, g_u_s, b_v;
1037
1038         if (tpg->alpha_red_only && color != TPG_COLOR_CSC_RED &&
1039                                    color != TPG_COLOR_100_RED &&
1040                                    color != TPG_COLOR_75_RED)
1041                 alpha = 0;
1042         if (color == TPG_COLOR_RANDOM)
1043                 precalculate_color(tpg, color);
1044         r_y_h = tpg->colors[color][0]; /* R or precalculated Y, H */
1045         g_u_s = tpg->colors[color][1]; /* G or precalculated U, V */
1046         b_v = tpg->colors[color][2]; /* B or precalculated V */
1047
1048         switch (tpg->fourcc) {
1049         case V4L2_PIX_FMT_GREY:
1050                 buf[0][offset] = r_y_h;
1051                 break;
1052         case V4L2_PIX_FMT_Y16:
1053                 /*
1054                  * Ideally both bytes should be set to r_y_h, but then you won't
1055                  * be able to detect endian problems. So keep it 0 except for
1056                  * the corner case where r_y_h is 0xff so white really will be
1057                  * white (0xffff).
1058                  */
1059                 buf[0][offset] = r_y_h == 0xff ? r_y_h : 0;
1060                 buf[0][offset+1] = r_y_h;
1061                 break;
1062         case V4L2_PIX_FMT_Y16_BE:
1063                 /* See comment for V4L2_PIX_FMT_Y16 above */
1064                 buf[0][offset] = r_y_h;
1065                 buf[0][offset+1] = r_y_h == 0xff ? r_y_h : 0;
1066                 break;
1067         case V4L2_PIX_FMT_YUV422M:
1068         case V4L2_PIX_FMT_YUV422P:
1069         case V4L2_PIX_FMT_YUV420:
1070         case V4L2_PIX_FMT_YUV420M:
1071                 buf[0][offset] = r_y_h;
1072                 if (odd) {
1073                         buf[1][0] = (buf[1][0] + g_u_s) / 2;
1074                         buf[2][0] = (buf[2][0] + b_v) / 2;
1075                         buf[1][1] = buf[1][0];
1076                         buf[2][1] = buf[2][0];
1077                         break;
1078                 }
1079                 buf[1][0] = g_u_s;
1080                 buf[2][0] = b_v;
1081                 break;
1082         case V4L2_PIX_FMT_YVU422M:
1083         case V4L2_PIX_FMT_YVU420:
1084         case V4L2_PIX_FMT_YVU420M:
1085                 buf[0][offset] = r_y_h;
1086                 if (odd) {
1087                         buf[1][0] = (buf[1][0] + b_v) / 2;
1088                         buf[2][0] = (buf[2][0] + g_u_s) / 2;
1089                         buf[1][1] = buf[1][0];
1090                         buf[2][1] = buf[2][0];
1091                         break;
1092                 }
1093                 buf[1][0] = b_v;
1094                 buf[2][0] = g_u_s;
1095                 break;
1096
1097         case V4L2_PIX_FMT_NV12:
1098         case V4L2_PIX_FMT_NV12M:
1099         case V4L2_PIX_FMT_NV16:
1100         case V4L2_PIX_FMT_NV16M:
1101                 buf[0][offset] = r_y_h;
1102                 if (odd) {
1103                         buf[1][0] = (buf[1][0] + g_u_s) / 2;
1104                         buf[1][1] = (buf[1][1] + b_v) / 2;
1105                         break;
1106                 }
1107                 buf[1][0] = g_u_s;
1108                 buf[1][1] = b_v;
1109                 break;
1110         case V4L2_PIX_FMT_NV21:
1111         case V4L2_PIX_FMT_NV21M:
1112         case V4L2_PIX_FMT_NV61:
1113         case V4L2_PIX_FMT_NV61M:
1114                 buf[0][offset] = r_y_h;
1115                 if (odd) {
1116                         buf[1][0] = (buf[1][0] + b_v) / 2;
1117                         buf[1][1] = (buf[1][1] + g_u_s) / 2;
1118                         break;
1119                 }
1120                 buf[1][0] = b_v;
1121                 buf[1][1] = g_u_s;
1122                 break;
1123
1124         case V4L2_PIX_FMT_YUV444M:
1125                 buf[0][offset] = r_y_h;
1126                 buf[1][offset] = g_u_s;
1127                 buf[2][offset] = b_v;
1128                 break;
1129
1130         case V4L2_PIX_FMT_YVU444M:
1131                 buf[0][offset] = r_y_h;
1132                 buf[1][offset] = b_v;
1133                 buf[2][offset] = g_u_s;
1134                 break;
1135
1136         case V4L2_PIX_FMT_NV24:
1137                 buf[0][offset] = r_y_h;
1138                 buf[1][2 * offset] = g_u_s;
1139                 buf[1][2 * offset + 1] = b_v;
1140                 break;
1141
1142         case V4L2_PIX_FMT_NV42:
1143                 buf[0][offset] = r_y_h;
1144                 buf[1][2 * offset] = b_v;
1145                 buf[1][2 * offset + 1] = g_u_s;
1146                 break;
1147
1148         case V4L2_PIX_FMT_YUYV:
1149                 buf[0][offset] = r_y_h;
1150                 if (odd) {
1151                         buf[0][1] = (buf[0][1] + g_u_s) / 2;
1152                         buf[0][3] = (buf[0][3] + b_v) / 2;
1153                         break;
1154                 }
1155                 buf[0][1] = g_u_s;
1156                 buf[0][3] = b_v;
1157                 break;
1158         case V4L2_PIX_FMT_UYVY:
1159                 buf[0][offset + 1] = r_y_h;
1160                 if (odd) {
1161                         buf[0][0] = (buf[0][0] + g_u_s) / 2;
1162                         buf[0][2] = (buf[0][2] + b_v) / 2;
1163                         break;
1164                 }
1165                 buf[0][0] = g_u_s;
1166                 buf[0][2] = b_v;
1167                 break;
1168         case V4L2_PIX_FMT_YVYU:
1169                 buf[0][offset] = r_y_h;
1170                 if (odd) {
1171                         buf[0][1] = (buf[0][1] + b_v) / 2;
1172                         buf[0][3] = (buf[0][3] + g_u_s) / 2;
1173                         break;
1174                 }
1175                 buf[0][1] = b_v;
1176                 buf[0][3] = g_u_s;
1177                 break;
1178         case V4L2_PIX_FMT_VYUY:
1179                 buf[0][offset + 1] = r_y_h;
1180                 if (odd) {
1181                         buf[0][0] = (buf[0][0] + b_v) / 2;
1182                         buf[0][2] = (buf[0][2] + g_u_s) / 2;
1183                         break;
1184                 }
1185                 buf[0][0] = b_v;
1186                 buf[0][2] = g_u_s;
1187                 break;
1188         case V4L2_PIX_FMT_RGB332:
1189                 buf[0][offset] = (r_y_h << 5) | (g_u_s << 2) | b_v;
1190                 break;
1191         case V4L2_PIX_FMT_YUV565:
1192         case V4L2_PIX_FMT_RGB565:
1193                 buf[0][offset] = (g_u_s << 5) | b_v;
1194                 buf[0][offset + 1] = (r_y_h << 3) | (g_u_s >> 3);
1195                 break;
1196         case V4L2_PIX_FMT_RGB565X:
1197                 buf[0][offset] = (r_y_h << 3) | (g_u_s >> 3);
1198                 buf[0][offset + 1] = (g_u_s << 5) | b_v;
1199                 break;
1200         case V4L2_PIX_FMT_RGB444:
1201         case V4L2_PIX_FMT_XRGB444:
1202                 alpha = 0;
1203                 /* fall through */
1204         case V4L2_PIX_FMT_YUV444:
1205         case V4L2_PIX_FMT_ARGB444:
1206                 buf[0][offset] = (g_u_s << 4) | b_v;
1207                 buf[0][offset + 1] = (alpha & 0xf0) | r_y_h;
1208                 break;
1209         case V4L2_PIX_FMT_RGB555:
1210         case V4L2_PIX_FMT_XRGB555:
1211                 alpha = 0;
1212                 /* fall through */
1213         case V4L2_PIX_FMT_YUV555:
1214         case V4L2_PIX_FMT_ARGB555:
1215                 buf[0][offset] = (g_u_s << 5) | b_v;
1216                 buf[0][offset + 1] = (alpha & 0x80) | (r_y_h << 2)
1217                                                     | (g_u_s >> 3);
1218                 break;
1219         case V4L2_PIX_FMT_RGB555X:
1220         case V4L2_PIX_FMT_XRGB555X:
1221                 alpha = 0;
1222                 /* fall through */
1223         case V4L2_PIX_FMT_ARGB555X:
1224                 buf[0][offset] = (alpha & 0x80) | (r_y_h << 2) | (g_u_s >> 3);
1225                 buf[0][offset + 1] = (g_u_s << 5) | b_v;
1226                 break;
1227         case V4L2_PIX_FMT_RGB24:
1228         case V4L2_PIX_FMT_HSV24:
1229                 buf[0][offset] = r_y_h;
1230                 buf[0][offset + 1] = g_u_s;
1231                 buf[0][offset + 2] = b_v;
1232                 break;
1233         case V4L2_PIX_FMT_BGR24:
1234                 buf[0][offset] = b_v;
1235                 buf[0][offset + 1] = g_u_s;
1236                 buf[0][offset + 2] = r_y_h;
1237                 break;
1238         case V4L2_PIX_FMT_BGR666:
1239                 buf[0][offset] = (b_v << 2) | (g_u_s >> 4);
1240                 buf[0][offset + 1] = (g_u_s << 4) | (r_y_h >> 2);
1241                 buf[0][offset + 2] = r_y_h << 6;
1242                 buf[0][offset + 3] = 0;
1243                 break;
1244         case V4L2_PIX_FMT_RGB32:
1245         case V4L2_PIX_FMT_XRGB32:
1246         case V4L2_PIX_FMT_HSV32:
1247                 alpha = 0;
1248                 /* fall through */
1249         case V4L2_PIX_FMT_YUV32:
1250         case V4L2_PIX_FMT_ARGB32:
1251                 buf[0][offset] = alpha;
1252                 buf[0][offset + 1] = r_y_h;
1253                 buf[0][offset + 2] = g_u_s;
1254                 buf[0][offset + 3] = b_v;
1255                 break;
1256         case V4L2_PIX_FMT_BGR32:
1257         case V4L2_PIX_FMT_XBGR32:
1258                 alpha = 0;
1259                 /* fall through */
1260         case V4L2_PIX_FMT_ABGR32:
1261                 buf[0][offset] = b_v;
1262                 buf[0][offset + 1] = g_u_s;
1263                 buf[0][offset + 2] = r_y_h;
1264                 buf[0][offset + 3] = alpha;
1265                 break;
1266         case V4L2_PIX_FMT_SBGGR8:
1267                 buf[0][offset] = odd ? g_u_s : b_v;
1268                 buf[1][offset] = odd ? r_y_h : g_u_s;
1269                 break;
1270         case V4L2_PIX_FMT_SGBRG8:
1271                 buf[0][offset] = odd ? b_v : g_u_s;
1272                 buf[1][offset] = odd ? g_u_s : r_y_h;
1273                 break;
1274         case V4L2_PIX_FMT_SGRBG8:
1275                 buf[0][offset] = odd ? r_y_h : g_u_s;
1276                 buf[1][offset] = odd ? g_u_s : b_v;
1277                 break;
1278         case V4L2_PIX_FMT_SRGGB8:
1279                 buf[0][offset] = odd ? g_u_s : r_y_h;
1280                 buf[1][offset] = odd ? b_v : g_u_s;
1281                 break;
1282         case V4L2_PIX_FMT_SBGGR10:
1283                 buf[0][offset] = odd ? g_u_s << 2 : b_v << 2;
1284                 buf[0][offset + 1] = odd ? g_u_s >> 6 : b_v >> 6;
1285                 buf[1][offset] = odd ? r_y_h << 2 : g_u_s << 2;
1286                 buf[1][offset + 1] = odd ? r_y_h >> 6 : g_u_s >> 6;
1287                 buf[0][offset] |= (buf[0][offset] >> 2) & 3;
1288                 buf[1][offset] |= (buf[1][offset] >> 2) & 3;
1289                 break;
1290         case V4L2_PIX_FMT_SGBRG10:
1291                 buf[0][offset] = odd ? b_v << 2 : g_u_s << 2;
1292                 buf[0][offset + 1] = odd ? b_v >> 6 : g_u_s >> 6;
1293                 buf[1][offset] = odd ? g_u_s << 2 : r_y_h << 2;
1294                 buf[1][offset + 1] = odd ? g_u_s >> 6 : r_y_h >> 6;
1295                 buf[0][offset] |= (buf[0][offset] >> 2) & 3;
1296                 buf[1][offset] |= (buf[1][offset] >> 2) & 3;
1297                 break;
1298         case V4L2_PIX_FMT_SGRBG10:
1299                 buf[0][offset] = odd ? r_y_h << 2 : g_u_s << 2;
1300                 buf[0][offset + 1] = odd ? r_y_h >> 6 : g_u_s >> 6;
1301                 buf[1][offset] = odd ? g_u_s << 2 : b_v << 2;
1302                 buf[1][offset + 1] = odd ? g_u_s >> 6 : b_v >> 6;
1303                 buf[0][offset] |= (buf[0][offset] >> 2) & 3;
1304                 buf[1][offset] |= (buf[1][offset] >> 2) & 3;
1305                 break;
1306         case V4L2_PIX_FMT_SRGGB10:
1307                 buf[0][offset] = odd ? g_u_s << 2 : r_y_h << 2;
1308                 buf[0][offset + 1] = odd ? g_u_s >> 6 : r_y_h >> 6;
1309                 buf[1][offset] = odd ? b_v << 2 : g_u_s << 2;
1310                 buf[1][offset + 1] = odd ? b_v >> 6 : g_u_s >> 6;
1311                 buf[0][offset] |= (buf[0][offset] >> 2) & 3;
1312                 buf[1][offset] |= (buf[1][offset] >> 2) & 3;
1313                 break;
1314         case V4L2_PIX_FMT_SBGGR12:
1315                 buf[0][offset] = odd ? g_u_s << 4 : b_v << 4;
1316                 buf[0][offset + 1] = odd ? g_u_s >> 4 : b_v >> 4;
1317                 buf[1][offset] = odd ? r_y_h << 4 : g_u_s << 4;
1318                 buf[1][offset + 1] = odd ? r_y_h >> 4 : g_u_s >> 4;
1319                 buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
1320                 buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
1321                 break;
1322         case V4L2_PIX_FMT_SGBRG12:
1323                 buf[0][offset] = odd ? b_v << 4 : g_u_s << 4;
1324                 buf[0][offset + 1] = odd ? b_v >> 4 : g_u_s >> 4;
1325                 buf[1][offset] = odd ? g_u_s << 4 : r_y_h << 4;
1326                 buf[1][offset + 1] = odd ? g_u_s >> 4 : r_y_h >> 4;
1327                 buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
1328                 buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
1329                 break;
1330         case V4L2_PIX_FMT_SGRBG12:
1331                 buf[0][offset] = odd ? r_y_h << 4 : g_u_s << 4;
1332                 buf[0][offset + 1] = odd ? r_y_h >> 4 : g_u_s >> 4;
1333                 buf[1][offset] = odd ? g_u_s << 4 : b_v << 4;
1334                 buf[1][offset + 1] = odd ? g_u_s >> 4 : b_v >> 4;
1335                 buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
1336                 buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
1337                 break;
1338         case V4L2_PIX_FMT_SRGGB12:
1339                 buf[0][offset] = odd ? g_u_s << 4 : r_y_h << 4;
1340                 buf[0][offset + 1] = odd ? g_u_s >> 4 : r_y_h >> 4;
1341                 buf[1][offset] = odd ? b_v << 4 : g_u_s << 4;
1342                 buf[1][offset + 1] = odd ? b_v >> 4 : g_u_s >> 4;
1343                 buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
1344                 buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
1345                 break;
1346         }
1347 }
1348
1349 unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line)
1350 {
1351         switch (tpg->fourcc) {
1352         case V4L2_PIX_FMT_SBGGR8:
1353         case V4L2_PIX_FMT_SGBRG8:
1354         case V4L2_PIX_FMT_SGRBG8:
1355         case V4L2_PIX_FMT_SRGGB8:
1356         case V4L2_PIX_FMT_SBGGR10:
1357         case V4L2_PIX_FMT_SGBRG10:
1358         case V4L2_PIX_FMT_SGRBG10:
1359         case V4L2_PIX_FMT_SRGGB10:
1360         case V4L2_PIX_FMT_SBGGR12:
1361         case V4L2_PIX_FMT_SGBRG12:
1362         case V4L2_PIX_FMT_SGRBG12:
1363         case V4L2_PIX_FMT_SRGGB12:
1364                 return buf_line & 1;
1365         default:
1366                 return 0;
1367         }
1368 }
1369 EXPORT_SYMBOL_GPL(tpg_g_interleaved_plane);
1370
1371 /* Return how many pattern lines are used by the current pattern. */
1372 static unsigned tpg_get_pat_lines(const struct tpg_data *tpg)
1373 {
1374         switch (tpg->pattern) {
1375         case TPG_PAT_CHECKERS_16X16:
1376         case TPG_PAT_CHECKERS_2X2:
1377         case TPG_PAT_CHECKERS_1X1:
1378         case TPG_PAT_COLOR_CHECKERS_2X2:
1379         case TPG_PAT_COLOR_CHECKERS_1X1:
1380         case TPG_PAT_ALTERNATING_HLINES:
1381         case TPG_PAT_CROSS_1_PIXEL:
1382         case TPG_PAT_CROSS_2_PIXELS:
1383         case TPG_PAT_CROSS_10_PIXELS:
1384                 return 2;
1385         case TPG_PAT_100_COLORSQUARES:
1386         case TPG_PAT_100_HCOLORBAR:
1387                 return 8;
1388         default:
1389                 return 1;
1390         }
1391 }
1392
1393 /* Which pattern line should be used for the given frame line. */
1394 static unsigned tpg_get_pat_line(const struct tpg_data *tpg, unsigned line)
1395 {
1396         switch (tpg->pattern) {
1397         case TPG_PAT_CHECKERS_16X16:
1398                 return (line >> 4) & 1;
1399         case TPG_PAT_CHECKERS_1X1:
1400         case TPG_PAT_COLOR_CHECKERS_1X1:
1401         case TPG_PAT_ALTERNATING_HLINES:
1402                 return line & 1;
1403         case TPG_PAT_CHECKERS_2X2:
1404         case TPG_PAT_COLOR_CHECKERS_2X2:
1405                 return (line & 2) >> 1;
1406         case TPG_PAT_100_COLORSQUARES:
1407         case TPG_PAT_100_HCOLORBAR:
1408                 return (line * 8) / tpg->src_height;
1409         case TPG_PAT_CROSS_1_PIXEL:
1410                 return line == tpg->src_height / 2;
1411         case TPG_PAT_CROSS_2_PIXELS:
1412                 return (line + 1) / 2 == tpg->src_height / 4;
1413         case TPG_PAT_CROSS_10_PIXELS:
1414                 return (line + 10) / 20 == tpg->src_height / 40;
1415         default:
1416                 return 0;
1417         }
1418 }
1419
1420 /*
1421  * Which color should be used for the given pattern line and X coordinate.
1422  * Note: x is in the range 0 to 2 * tpg->src_width.
1423  */
1424 static enum tpg_color tpg_get_color(const struct tpg_data *tpg,
1425                                     unsigned pat_line, unsigned x)
1426 {
1427         /* Maximum number of bars are TPG_COLOR_MAX - otherwise, the input print code
1428            should be modified */
1429         static const enum tpg_color bars[3][8] = {
1430                 /* Standard ITU-R 75% color bar sequence */
1431                 { TPG_COLOR_CSC_WHITE,   TPG_COLOR_75_YELLOW,
1432                   TPG_COLOR_75_CYAN,     TPG_COLOR_75_GREEN,
1433                   TPG_COLOR_75_MAGENTA,  TPG_COLOR_75_RED,
1434                   TPG_COLOR_75_BLUE,     TPG_COLOR_100_BLACK, },
1435                 /* Standard ITU-R 100% color bar sequence */
1436                 { TPG_COLOR_100_WHITE,   TPG_COLOR_100_YELLOW,
1437                   TPG_COLOR_100_CYAN,    TPG_COLOR_100_GREEN,
1438                   TPG_COLOR_100_MAGENTA, TPG_COLOR_100_RED,
1439                   TPG_COLOR_100_BLUE,    TPG_COLOR_100_BLACK, },
1440                 /* Color bar sequence suitable to test CSC */
1441                 { TPG_COLOR_CSC_WHITE,   TPG_COLOR_CSC_YELLOW,
1442                   TPG_COLOR_CSC_CYAN,    TPG_COLOR_CSC_GREEN,
1443                   TPG_COLOR_CSC_MAGENTA, TPG_COLOR_CSC_RED,
1444                   TPG_COLOR_CSC_BLUE,    TPG_COLOR_CSC_BLACK, },
1445         };
1446
1447         switch (tpg->pattern) {
1448         case TPG_PAT_75_COLORBAR:
1449         case TPG_PAT_100_COLORBAR:
1450         case TPG_PAT_CSC_COLORBAR:
1451                 return bars[tpg->pattern][((x * 8) / tpg->src_width) % 8];
1452         case TPG_PAT_100_COLORSQUARES:
1453                 return bars[1][(pat_line + (x * 8) / tpg->src_width) % 8];
1454         case TPG_PAT_100_HCOLORBAR:
1455                 return bars[1][pat_line];
1456         case TPG_PAT_BLACK:
1457                 return TPG_COLOR_100_BLACK;
1458         case TPG_PAT_WHITE:
1459                 return TPG_COLOR_100_WHITE;
1460         case TPG_PAT_RED:
1461                 return TPG_COLOR_100_RED;
1462         case TPG_PAT_GREEN:
1463                 return TPG_COLOR_100_GREEN;
1464         case TPG_PAT_BLUE:
1465                 return TPG_COLOR_100_BLUE;
1466         case TPG_PAT_CHECKERS_16X16:
1467                 return (((x >> 4) & 1) ^ (pat_line & 1)) ?
1468                         TPG_COLOR_100_BLACK : TPG_COLOR_100_WHITE;
1469         case TPG_PAT_CHECKERS_1X1:
1470                 return ((x & 1) ^ (pat_line & 1)) ?
1471                         TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
1472         case TPG_PAT_COLOR_CHECKERS_1X1:
1473                 return ((x & 1) ^ (pat_line & 1)) ?
1474                         TPG_COLOR_100_RED : TPG_COLOR_100_BLUE;
1475         case TPG_PAT_CHECKERS_2X2:
1476                 return (((x >> 1) & 1) ^ (pat_line & 1)) ?
1477                         TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
1478         case TPG_PAT_COLOR_CHECKERS_2X2:
1479                 return (((x >> 1) & 1) ^ (pat_line & 1)) ?
1480                         TPG_COLOR_100_RED : TPG_COLOR_100_BLUE;
1481         case TPG_PAT_ALTERNATING_HLINES:
1482                 return pat_line ? TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
1483         case TPG_PAT_ALTERNATING_VLINES:
1484                 return (x & 1) ? TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
1485         case TPG_PAT_CROSS_1_PIXEL:
1486                 if (pat_line || (x % tpg->src_width) == tpg->src_width / 2)
1487                         return TPG_COLOR_100_BLACK;
1488                 return TPG_COLOR_100_WHITE;
1489         case TPG_PAT_CROSS_2_PIXELS:
1490                 if (pat_line || ((x % tpg->src_width) + 1) / 2 == tpg->src_width / 4)
1491                         return TPG_COLOR_100_BLACK;
1492                 return TPG_COLOR_100_WHITE;
1493         case TPG_PAT_CROSS_10_PIXELS:
1494                 if (pat_line || ((x % tpg->src_width) + 10) / 20 == tpg->src_width / 40)
1495                         return TPG_COLOR_100_BLACK;
1496                 return TPG_COLOR_100_WHITE;
1497         case TPG_PAT_GRAY_RAMP:
1498                 return TPG_COLOR_RAMP + ((x % tpg->src_width) * 256) / tpg->src_width;
1499         default:
1500                 return TPG_COLOR_100_RED;
1501         }
1502 }
1503
1504 /*
1505  * Given the pixel aspect ratio and video aspect ratio calculate the
1506  * coordinates of a centered square and the coordinates of the border of
1507  * the active video area. The coordinates are relative to the source
1508  * frame rectangle.
1509  */
1510 static void tpg_calculate_square_border(struct tpg_data *tpg)
1511 {
1512         unsigned w = tpg->src_width;
1513         unsigned h = tpg->src_height;
1514         unsigned sq_w, sq_h;
1515
1516         sq_w = (w * 2 / 5) & ~1;
1517         if (((w - sq_w) / 2) & 1)
1518                 sq_w += 2;
1519         sq_h = sq_w;
1520         tpg->square.width = sq_w;
1521         if (tpg->vid_aspect == TPG_VIDEO_ASPECT_16X9_ANAMORPHIC) {
1522                 unsigned ana_sq_w = (sq_w / 4) * 3;
1523
1524                 if (((w - ana_sq_w) / 2) & 1)
1525                         ana_sq_w += 2;
1526                 tpg->square.width = ana_sq_w;
1527         }
1528         tpg->square.left = (w - tpg->square.width) / 2;
1529         if (tpg->pix_aspect == TPG_PIXEL_ASPECT_NTSC)
1530                 sq_h = sq_w * 10 / 11;
1531         else if (tpg->pix_aspect == TPG_PIXEL_ASPECT_PAL)
1532                 sq_h = sq_w * 59 / 54;
1533         tpg->square.height = sq_h;
1534         tpg->square.top = (h - sq_h) / 2;
1535         tpg->border.left = 0;
1536         tpg->border.width = w;
1537         tpg->border.top = 0;
1538         tpg->border.height = h;
1539         switch (tpg->vid_aspect) {
1540         case TPG_VIDEO_ASPECT_4X3:
1541                 if (tpg->pix_aspect)
1542                         return;
1543                 if (3 * w >= 4 * h) {
1544                         tpg->border.width = ((4 * h) / 3) & ~1;
1545                         if (((w - tpg->border.width) / 2) & ~1)
1546                                 tpg->border.width -= 2;
1547                         tpg->border.left = (w - tpg->border.width) / 2;
1548                         break;
1549                 }
1550                 tpg->border.height = ((3 * w) / 4) & ~1;
1551                 tpg->border.top = (h - tpg->border.height) / 2;
1552                 break;
1553         case TPG_VIDEO_ASPECT_14X9_CENTRE:
1554                 if (tpg->pix_aspect) {
1555                         tpg->border.height = tpg->pix_aspect == TPG_PIXEL_ASPECT_NTSC ? 420 : 506;
1556                         tpg->border.top = (h - tpg->border.height) / 2;
1557                         break;
1558                 }
1559                 if (9 * w >= 14 * h) {
1560                         tpg->border.width = ((14 * h) / 9) & ~1;
1561                         if (((w - tpg->border.width) / 2) & ~1)
1562                                 tpg->border.width -= 2;
1563                         tpg->border.left = (w - tpg->border.width) / 2;
1564                         break;
1565                 }
1566                 tpg->border.height = ((9 * w) / 14) & ~1;
1567                 tpg->border.top = (h - tpg->border.height) / 2;
1568                 break;
1569         case TPG_VIDEO_ASPECT_16X9_CENTRE:
1570                 if (tpg->pix_aspect) {
1571                         tpg->border.height = tpg->pix_aspect == TPG_PIXEL_ASPECT_NTSC ? 368 : 442;
1572                         tpg->border.top = (h - tpg->border.height) / 2;
1573                         break;
1574                 }
1575                 if (9 * w >= 16 * h) {
1576                         tpg->border.width = ((16 * h) / 9) & ~1;
1577                         if (((w - tpg->border.width) / 2) & ~1)
1578                                 tpg->border.width -= 2;
1579                         tpg->border.left = (w - tpg->border.width) / 2;
1580                         break;
1581                 }
1582                 tpg->border.height = ((9 * w) / 16) & ~1;
1583                 tpg->border.top = (h - tpg->border.height) / 2;
1584                 break;
1585         default:
1586                 break;
1587         }
1588 }
1589
1590 static void tpg_precalculate_line(struct tpg_data *tpg)
1591 {
1592         enum tpg_color contrast;
1593         u8 pix[TPG_MAX_PLANES][8];
1594         unsigned pat;
1595         unsigned p;
1596         unsigned x;
1597
1598         switch (tpg->pattern) {
1599         case TPG_PAT_GREEN:
1600                 contrast = TPG_COLOR_100_RED;
1601                 break;
1602         case TPG_PAT_CSC_COLORBAR:
1603                 contrast = TPG_COLOR_CSC_GREEN;
1604                 break;
1605         default:
1606                 contrast = TPG_COLOR_100_GREEN;
1607                 break;
1608         }
1609
1610         for (pat = 0; pat < tpg_get_pat_lines(tpg); pat++) {
1611                 /* Coarse scaling with Bresenham */
1612                 unsigned int_part = tpg->src_width / tpg->scaled_width;
1613                 unsigned fract_part = tpg->src_width % tpg->scaled_width;
1614                 unsigned src_x = 0;
1615                 unsigned error = 0;
1616
1617                 for (x = 0; x < tpg->scaled_width * 2; x += 2) {
1618                         unsigned real_x = src_x;
1619                         enum tpg_color color1, color2;
1620
1621                         real_x = tpg->hflip ? tpg->src_width * 2 - real_x - 2 : real_x;
1622                         color1 = tpg_get_color(tpg, pat, real_x);
1623
1624                         src_x += int_part;
1625                         error += fract_part;
1626                         if (error >= tpg->scaled_width) {
1627                                 error -= tpg->scaled_width;
1628                                 src_x++;
1629                         }
1630
1631                         real_x = src_x;
1632                         real_x = tpg->hflip ? tpg->src_width * 2 - real_x - 2 : real_x;
1633                         color2 = tpg_get_color(tpg, pat, real_x);
1634
1635                         src_x += int_part;
1636                         error += fract_part;
1637                         if (error >= tpg->scaled_width) {
1638                                 error -= tpg->scaled_width;
1639                                 src_x++;
1640                         }
1641
1642                         gen_twopix(tpg, pix, tpg->hflip ? color2 : color1, 0);
1643                         gen_twopix(tpg, pix, tpg->hflip ? color1 : color2, 1);
1644                         for (p = 0; p < tpg->planes; p++) {
1645                                 unsigned twopixsize = tpg->twopixelsize[p];
1646                                 unsigned hdiv = tpg->hdownsampling[p];
1647                                 u8 *pos = tpg->lines[pat][p] + tpg_hdiv(tpg, p, x);
1648
1649                                 memcpy(pos, pix[p], twopixsize / hdiv);
1650                         }
1651                 }
1652         }
1653
1654         if (tpg->vdownsampling[tpg->planes - 1] > 1) {
1655                 unsigned pat_lines = tpg_get_pat_lines(tpg);
1656
1657                 for (pat = 0; pat < pat_lines; pat++) {
1658                         unsigned next_pat = (pat + 1) % pat_lines;
1659
1660                         for (p = 1; p < tpg->planes; p++) {
1661                                 unsigned w = tpg_hdiv(tpg, p, tpg->scaled_width * 2);
1662                                 u8 *pos1 = tpg->lines[pat][p];
1663                                 u8 *pos2 = tpg->lines[next_pat][p];
1664                                 u8 *dest = tpg->downsampled_lines[pat][p];
1665
1666                                 for (x = 0; x < w; x++, pos1++, pos2++, dest++)
1667                                         *dest = ((u16)*pos1 + (u16)*pos2) / 2;
1668                         }
1669                 }
1670         }
1671
1672         gen_twopix(tpg, pix, contrast, 0);
1673         gen_twopix(tpg, pix, contrast, 1);
1674         for (p = 0; p < tpg->planes; p++) {
1675                 unsigned twopixsize = tpg->twopixelsize[p];
1676                 u8 *pos = tpg->contrast_line[p];
1677
1678                 for (x = 0; x < tpg->scaled_width; x += 2, pos += twopixsize)
1679                         memcpy(pos, pix[p], twopixsize);
1680         }
1681
1682         gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 0);
1683         gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 1);
1684         for (p = 0; p < tpg->planes; p++) {
1685                 unsigned twopixsize = tpg->twopixelsize[p];
1686                 u8 *pos = tpg->black_line[p];
1687
1688                 for (x = 0; x < tpg->scaled_width; x += 2, pos += twopixsize)
1689                         memcpy(pos, pix[p], twopixsize);
1690         }
1691
1692         for (x = 0; x < tpg->scaled_width * 2; x += 2) {
1693                 gen_twopix(tpg, pix, TPG_COLOR_RANDOM, 0);
1694                 gen_twopix(tpg, pix, TPG_COLOR_RANDOM, 1);
1695                 for (p = 0; p < tpg->planes; p++) {
1696                         unsigned twopixsize = tpg->twopixelsize[p];
1697                         u8 *pos = tpg->random_line[p] + x * twopixsize / 2;
1698
1699                         memcpy(pos, pix[p], twopixsize);
1700                 }
1701         }
1702
1703         gen_twopix(tpg, tpg->textbg, TPG_COLOR_TEXTBG, 0);
1704         gen_twopix(tpg, tpg->textbg, TPG_COLOR_TEXTBG, 1);
1705         gen_twopix(tpg, tpg->textfg, TPG_COLOR_TEXTFG, 0);
1706         gen_twopix(tpg, tpg->textfg, TPG_COLOR_TEXTFG, 1);
1707 }
1708
1709 /* need this to do rgb24 rendering */
1710 typedef struct { u16 __; u8 _; } __packed x24;
1711
1712 #define PRINTSTR(PIXTYPE) do {  \
1713         unsigned vdiv = tpg->vdownsampling[p]; \
1714         unsigned hdiv = tpg->hdownsampling[p]; \
1715         int line;       \
1716         PIXTYPE fg;     \
1717         PIXTYPE bg;     \
1718         memcpy(&fg, tpg->textfg[p], sizeof(PIXTYPE));   \
1719         memcpy(&bg, tpg->textbg[p], sizeof(PIXTYPE));   \
1720         \
1721         for (line = first; line < 16; line += vdiv * step) {    \
1722                 int l = tpg->vflip ? 15 - line : line; \
1723                 PIXTYPE *pos = (PIXTYPE *)(basep[p][(line / vdiv) & 1] + \
1724                                ((y * step + l) / (vdiv * div)) * tpg->bytesperline[p] + \
1725                                (x / hdiv) * sizeof(PIXTYPE));   \
1726                 unsigned s;     \
1727         \
1728                 for (s = 0; s < len; s++) {     \
1729                         u8 chr = font8x16[text[s] * 16 + line]; \
1730         \
1731                         if (hdiv == 2 && tpg->hflip) { \
1732                                 pos[3] = (chr & (0x01 << 6) ? fg : bg); \
1733                                 pos[2] = (chr & (0x01 << 4) ? fg : bg); \
1734                                 pos[1] = (chr & (0x01 << 2) ? fg : bg); \
1735                                 pos[0] = (chr & (0x01 << 0) ? fg : bg); \
1736                         } else if (hdiv == 2) { \
1737                                 pos[0] = (chr & (0x01 << 7) ? fg : bg); \
1738                                 pos[1] = (chr & (0x01 << 5) ? fg : bg); \
1739                                 pos[2] = (chr & (0x01 << 3) ? fg : bg); \
1740                                 pos[3] = (chr & (0x01 << 1) ? fg : bg); \
1741                         } else if (tpg->hflip) { \
1742                                 pos[7] = (chr & (0x01 << 7) ? fg : bg); \
1743                                 pos[6] = (chr & (0x01 << 6) ? fg : bg); \
1744                                 pos[5] = (chr & (0x01 << 5) ? fg : bg); \
1745                                 pos[4] = (chr & (0x01 << 4) ? fg : bg); \
1746                                 pos[3] = (chr & (0x01 << 3) ? fg : bg); \
1747                                 pos[2] = (chr & (0x01 << 2) ? fg : bg); \
1748                                 pos[1] = (chr & (0x01 << 1) ? fg : bg); \
1749                                 pos[0] = (chr & (0x01 << 0) ? fg : bg); \
1750                         } else { \
1751                                 pos[0] = (chr & (0x01 << 7) ? fg : bg); \
1752                                 pos[1] = (chr & (0x01 << 6) ? fg : bg); \
1753                                 pos[2] = (chr & (0x01 << 5) ? fg : bg); \
1754                                 pos[3] = (chr & (0x01 << 4) ? fg : bg); \
1755                                 pos[4] = (chr & (0x01 << 3) ? fg : bg); \
1756                                 pos[5] = (chr & (0x01 << 2) ? fg : bg); \
1757                                 pos[6] = (chr & (0x01 << 1) ? fg : bg); \
1758                                 pos[7] = (chr & (0x01 << 0) ? fg : bg); \
1759                         } \
1760         \
1761                         pos += (tpg->hflip ? -8 : 8) / hdiv;    \
1762                 }       \
1763         }       \
1764 } while (0)
1765
1766 static noinline void tpg_print_str_2(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
1767                         unsigned p, unsigned first, unsigned div, unsigned step,
1768                         int y, int x, char *text, unsigned len)
1769 {
1770         PRINTSTR(u8);
1771 }
1772
1773 static noinline void tpg_print_str_4(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
1774                         unsigned p, unsigned first, unsigned div, unsigned step,
1775                         int y, int x, char *text, unsigned len)
1776 {
1777         PRINTSTR(u16);
1778 }
1779
1780 static noinline void tpg_print_str_6(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
1781                         unsigned p, unsigned first, unsigned div, unsigned step,
1782                         int y, int x, char *text, unsigned len)
1783 {
1784         PRINTSTR(x24);
1785 }
1786
1787 static noinline void tpg_print_str_8(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
1788                         unsigned p, unsigned first, unsigned div, unsigned step,
1789                         int y, int x, char *text, unsigned len)
1790 {
1791         PRINTSTR(u32);
1792 }
1793
1794 void tpg_gen_text(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
1795                   int y, int x, char *text)
1796 {
1797         unsigned step = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
1798         unsigned div = step;
1799         unsigned first = 0;
1800         unsigned len = strlen(text);
1801         unsigned p;
1802
1803         if (font8x16 == NULL || basep == NULL)
1804                 return;
1805
1806         /* Checks if it is possible to show string */
1807         if (y + 16 >= tpg->compose.height || x + 8 >= tpg->compose.width)
1808                 return;
1809
1810         if (len > (tpg->compose.width - x) / 8)
1811                 len = (tpg->compose.width - x) / 8;
1812         if (tpg->vflip)
1813                 y = tpg->compose.height - y - 16;
1814         if (tpg->hflip)
1815                 x = tpg->compose.width - x - 8;
1816         y += tpg->compose.top;
1817         x += tpg->compose.left;
1818         if (tpg->field == V4L2_FIELD_BOTTOM)
1819                 first = 1;
1820         else if (tpg->field == V4L2_FIELD_SEQ_TB || tpg->field == V4L2_FIELD_SEQ_BT)
1821                 div = 2;
1822
1823         for (p = 0; p < tpg->planes; p++) {
1824                 /* Print text */
1825                 switch (tpg->twopixelsize[p]) {
1826                 case 2:
1827                         tpg_print_str_2(tpg, basep, p, first, div, step, y, x,
1828                                         text, len);
1829                         break;
1830                 case 4:
1831                         tpg_print_str_4(tpg, basep, p, first, div, step, y, x,
1832                                         text, len);
1833                         break;
1834                 case 6:
1835                         tpg_print_str_6(tpg, basep, p, first, div, step, y, x,
1836                                         text, len);
1837                         break;
1838                 case 8:
1839                         tpg_print_str_8(tpg, basep, p, first, div, step, y, x,
1840                                         text, len);
1841                         break;
1842                 }
1843         }
1844 }
1845 EXPORT_SYMBOL_GPL(tpg_gen_text);
1846
1847 void tpg_update_mv_step(struct tpg_data *tpg)
1848 {
1849         int factor = tpg->mv_hor_mode > TPG_MOVE_NONE ? -1 : 1;
1850
1851         if (tpg->hflip)
1852                 factor = -factor;
1853         switch (tpg->mv_hor_mode) {
1854         case TPG_MOVE_NEG_FAST:
1855         case TPG_MOVE_POS_FAST:
1856                 tpg->mv_hor_step = ((tpg->src_width + 319) / 320) * 4;
1857                 break;
1858         case TPG_MOVE_NEG:
1859         case TPG_MOVE_POS:
1860                 tpg->mv_hor_step = ((tpg->src_width + 639) / 640) * 4;
1861                 break;
1862         case TPG_MOVE_NEG_SLOW:
1863         case TPG_MOVE_POS_SLOW:
1864                 tpg->mv_hor_step = 2;
1865                 break;
1866         case TPG_MOVE_NONE:
1867                 tpg->mv_hor_step = 0;
1868                 break;
1869         }
1870         if (factor < 0)
1871                 tpg->mv_hor_step = tpg->src_width - tpg->mv_hor_step;
1872
1873         factor = tpg->mv_vert_mode > TPG_MOVE_NONE ? -1 : 1;
1874         switch (tpg->mv_vert_mode) {
1875         case TPG_MOVE_NEG_FAST:
1876         case TPG_MOVE_POS_FAST:
1877                 tpg->mv_vert_step = ((tpg->src_width + 319) / 320) * 4;
1878                 break;
1879         case TPG_MOVE_NEG:
1880         case TPG_MOVE_POS:
1881                 tpg->mv_vert_step = ((tpg->src_width + 639) / 640) * 4;
1882                 break;
1883         case TPG_MOVE_NEG_SLOW:
1884         case TPG_MOVE_POS_SLOW:
1885                 tpg->mv_vert_step = 1;
1886                 break;
1887         case TPG_MOVE_NONE:
1888                 tpg->mv_vert_step = 0;
1889                 break;
1890         }
1891         if (factor < 0)
1892                 tpg->mv_vert_step = tpg->src_height - tpg->mv_vert_step;
1893 }
1894 EXPORT_SYMBOL_GPL(tpg_update_mv_step);
1895
1896 /* Map the line number relative to the crop rectangle to a frame line number */
1897 static unsigned tpg_calc_frameline(const struct tpg_data *tpg, unsigned src_y,
1898                                     unsigned field)
1899 {
1900         switch (field) {
1901         case V4L2_FIELD_TOP:
1902                 return tpg->crop.top + src_y * 2;
1903         case V4L2_FIELD_BOTTOM:
1904                 return tpg->crop.top + src_y * 2 + 1;
1905         default:
1906                 return src_y + tpg->crop.top;
1907         }
1908 }
1909
1910 /*
1911  * Map the line number relative to the compose rectangle to a destination
1912  * buffer line number.
1913  */
1914 static unsigned tpg_calc_buffer_line(const struct tpg_data *tpg, unsigned y,
1915                                     unsigned field)
1916 {
1917         y += tpg->compose.top;
1918         switch (field) {
1919         case V4L2_FIELD_SEQ_TB:
1920                 if (y & 1)
1921                         return tpg->buf_height / 2 + y / 2;
1922                 return y / 2;
1923         case V4L2_FIELD_SEQ_BT:
1924                 if (y & 1)
1925                         return y / 2;
1926                 return tpg->buf_height / 2 + y / 2;
1927         default:
1928                 return y;
1929         }
1930 }
1931
1932 static void tpg_recalc(struct tpg_data *tpg)
1933 {
1934         if (tpg->recalc_colors) {
1935                 tpg->recalc_colors = false;
1936                 tpg->recalc_lines = true;
1937                 tpg->real_xfer_func = tpg->xfer_func;
1938                 tpg->real_ycbcr_enc = tpg->ycbcr_enc;
1939                 tpg->real_hsv_enc = tpg->hsv_enc;
1940                 tpg->real_quantization = tpg->quantization;
1941
1942                 if (tpg->xfer_func == V4L2_XFER_FUNC_DEFAULT)
1943                         tpg->real_xfer_func =
1944                                 V4L2_MAP_XFER_FUNC_DEFAULT(tpg->colorspace);
1945
1946                 if (tpg->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT)
1947                         tpg->real_ycbcr_enc =
1948                                 V4L2_MAP_YCBCR_ENC_DEFAULT(tpg->colorspace);
1949
1950                 if (tpg->quantization == V4L2_QUANTIZATION_DEFAULT)
1951                         tpg->real_quantization =
1952                                 V4L2_MAP_QUANTIZATION_DEFAULT(
1953                                         tpg->color_enc != TGP_COLOR_ENC_YCBCR,
1954                                         tpg->colorspace, tpg->real_ycbcr_enc);
1955
1956                 tpg_precalculate_colors(tpg);
1957         }
1958         if (tpg->recalc_square_border) {
1959                 tpg->recalc_square_border = false;
1960                 tpg_calculate_square_border(tpg);
1961         }
1962         if (tpg->recalc_lines) {
1963                 tpg->recalc_lines = false;
1964                 tpg_precalculate_line(tpg);
1965         }
1966 }
1967
1968 void tpg_calc_text_basep(struct tpg_data *tpg,
1969                 u8 *basep[TPG_MAX_PLANES][2], unsigned p, u8 *vbuf)
1970 {
1971         unsigned stride = tpg->bytesperline[p];
1972         unsigned h = tpg->buf_height;
1973
1974         tpg_recalc(tpg);
1975
1976         basep[p][0] = vbuf;
1977         basep[p][1] = vbuf;
1978         h /= tpg->vdownsampling[p];
1979         if (tpg->field == V4L2_FIELD_SEQ_TB)
1980                 basep[p][1] += h * stride / 2;
1981         else if (tpg->field == V4L2_FIELD_SEQ_BT)
1982                 basep[p][0] += h * stride / 2;
1983         if (p == 0 && tpg->interleaved)
1984                 tpg_calc_text_basep(tpg, basep, 1, vbuf);
1985 }
1986 EXPORT_SYMBOL_GPL(tpg_calc_text_basep);
1987
1988 static int tpg_pattern_avg(const struct tpg_data *tpg,
1989                            unsigned pat1, unsigned pat2)
1990 {
1991         unsigned pat_lines = tpg_get_pat_lines(tpg);
1992
1993         if (pat1 == (pat2 + 1) % pat_lines)
1994                 return pat2;
1995         if (pat2 == (pat1 + 1) % pat_lines)
1996                 return pat1;
1997         return -1;
1998 }
1999
2000 static const char *tpg_color_enc_str(enum tgp_color_enc
2001                                                  color_enc)
2002 {
2003         switch (color_enc) {
2004         case TGP_COLOR_ENC_HSV:
2005                 return "HSV";
2006         case TGP_COLOR_ENC_YCBCR:
2007                 return "Y'CbCr";
2008         case TGP_COLOR_ENC_LUMA:
2009                 return "Luma";
2010         case TGP_COLOR_ENC_RGB:
2011         default:
2012                 return "R'G'B";
2013
2014         }
2015 }
2016
2017 void tpg_log_status(struct tpg_data *tpg)
2018 {
2019         pr_info("tpg source WxH: %ux%u (%s)\n",
2020                 tpg->src_width, tpg->src_height,
2021                 tpg_color_enc_str(tpg->color_enc));
2022         pr_info("tpg field: %u\n", tpg->field);
2023         pr_info("tpg crop: %ux%u@%dx%d\n", tpg->crop.width, tpg->crop.height,
2024                         tpg->crop.left, tpg->crop.top);
2025         pr_info("tpg compose: %ux%u@%dx%d\n", tpg->compose.width, tpg->compose.height,
2026                         tpg->compose.left, tpg->compose.top);
2027         pr_info("tpg colorspace: %d\n", tpg->colorspace);
2028         pr_info("tpg transfer function: %d/%d\n", tpg->xfer_func, tpg->real_xfer_func);
2029         pr_info("tpg Y'CbCr encoding: %d/%d\n", tpg->ycbcr_enc, tpg->real_ycbcr_enc);
2030         pr_info("tpg HSV encoding: %d/%d\n", tpg->hsv_enc, tpg->real_hsv_enc);
2031         pr_info("tpg quantization: %d/%d\n", tpg->quantization, tpg->real_quantization);
2032         pr_info("tpg RGB range: %d/%d\n", tpg->rgb_range, tpg->real_rgb_range);
2033 }
2034 EXPORT_SYMBOL_GPL(tpg_log_status);
2035
2036 /*
2037  * This struct contains common parameters used by both the drawing of the
2038  * test pattern and the drawing of the extras (borders, square, etc.)
2039  */
2040 struct tpg_draw_params {
2041         /* common data */
2042         bool is_tv;
2043         bool is_60hz;
2044         unsigned twopixsize;
2045         unsigned img_width;
2046         unsigned stride;
2047         unsigned hmax;
2048         unsigned frame_line;
2049         unsigned frame_line_next;
2050
2051         /* test pattern */
2052         unsigned mv_hor_old;
2053         unsigned mv_hor_new;
2054         unsigned mv_vert_old;
2055         unsigned mv_vert_new;
2056
2057         /* extras */
2058         unsigned wss_width;
2059         unsigned wss_random_offset;
2060         unsigned sav_eav_f;
2061         unsigned left_pillar_width;
2062         unsigned right_pillar_start;
2063 };
2064
2065 static void tpg_fill_params_pattern(const struct tpg_data *tpg, unsigned p,
2066                                     struct tpg_draw_params *params)
2067 {
2068         params->mv_hor_old =
2069                 tpg_hscale_div(tpg, p, tpg->mv_hor_count % tpg->src_width);
2070         params->mv_hor_new =
2071                 tpg_hscale_div(tpg, p, (tpg->mv_hor_count + tpg->mv_hor_step) %
2072                                tpg->src_width);
2073         params->mv_vert_old = tpg->mv_vert_count % tpg->src_height;
2074         params->mv_vert_new =
2075                 (tpg->mv_vert_count + tpg->mv_vert_step) % tpg->src_height;
2076 }
2077
2078 static void tpg_fill_params_extras(const struct tpg_data *tpg,
2079                                    unsigned p,
2080                                    struct tpg_draw_params *params)
2081 {
2082         unsigned left_pillar_width = 0;
2083         unsigned right_pillar_start = params->img_width;
2084
2085         params->wss_width = tpg->crop.left < tpg->src_width / 2 ?
2086                 tpg->src_width / 2 - tpg->crop.left : 0;
2087         if (params->wss_width > tpg->crop.width)
2088                 params->wss_width = tpg->crop.width;
2089         params->wss_width = tpg_hscale_div(tpg, p, params->wss_width);
2090         params->wss_random_offset =
2091                 params->twopixsize * prandom_u32_max(tpg->src_width / 2);
2092
2093         if (tpg->crop.left < tpg->border.left) {
2094                 left_pillar_width = tpg->border.left - tpg->crop.left;
2095                 if (left_pillar_width > tpg->crop.width)
2096                         left_pillar_width = tpg->crop.width;
2097                 left_pillar_width = tpg_hscale_div(tpg, p, left_pillar_width);
2098         }
2099         params->left_pillar_width = left_pillar_width;
2100
2101         if (tpg->crop.left + tpg->crop.width >
2102             tpg->border.left + tpg->border.width) {
2103                 right_pillar_start =
2104                         tpg->border.left + tpg->border.width - tpg->crop.left;
2105                 right_pillar_start =
2106                         tpg_hscale_div(tpg, p, right_pillar_start);
2107                 if (right_pillar_start > params->img_width)
2108                         right_pillar_start = params->img_width;
2109         }
2110         params->right_pillar_start = right_pillar_start;
2111
2112         params->sav_eav_f = tpg->field ==
2113                         (params->is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
2114 }
2115
2116 static void tpg_fill_plane_extras(const struct tpg_data *tpg,
2117                                   const struct tpg_draw_params *params,
2118                                   unsigned p, unsigned h, u8 *vbuf)
2119 {
2120         unsigned twopixsize = params->twopixsize;
2121         unsigned img_width = params->img_width;
2122         unsigned frame_line = params->frame_line;
2123         const struct v4l2_rect *sq = &tpg->square;
2124         const struct v4l2_rect *b = &tpg->border;
2125         const struct v4l2_rect *c = &tpg->crop;
2126
2127         if (params->is_tv && !params->is_60hz &&
2128             frame_line == 0 && params->wss_width) {
2129                 /*
2130                  * Replace the first half of the top line of a 50 Hz frame
2131                  * with random data to simulate a WSS signal.
2132                  */
2133                 u8 *wss = tpg->random_line[p] + params->wss_random_offset;
2134
2135                 memcpy(vbuf, wss, params->wss_width);
2136         }
2137
2138         if (tpg->show_border && frame_line >= b->top &&
2139             frame_line < b->top + b->height) {
2140                 unsigned bottom = b->top + b->height - 1;
2141                 unsigned left = params->left_pillar_width;
2142                 unsigned right = params->right_pillar_start;
2143
2144                 if (frame_line == b->top || frame_line == b->top + 1 ||
2145                     frame_line == bottom || frame_line == bottom - 1) {
2146                         memcpy(vbuf + left, tpg->contrast_line[p],
2147                                         right - left);
2148                 } else {
2149                         if (b->left >= c->left &&
2150                             b->left < c->left + c->width)
2151                                 memcpy(vbuf + left,
2152                                         tpg->contrast_line[p], twopixsize);
2153                         if (b->left + b->width > c->left &&
2154                             b->left + b->width <= c->left + c->width)
2155                                 memcpy(vbuf + right - twopixsize,
2156                                         tpg->contrast_line[p], twopixsize);
2157                 }
2158         }
2159         if (tpg->qual != TPG_QUAL_NOISE && frame_line >= b->top &&
2160             frame_line < b->top + b->height) {
2161                 memcpy(vbuf, tpg->black_line[p], params->left_pillar_width);
2162                 memcpy(vbuf + params->right_pillar_start, tpg->black_line[p],
2163                        img_width - params->right_pillar_start);
2164         }
2165         if (tpg->show_square && frame_line >= sq->top &&
2166             frame_line < sq->top + sq->height &&
2167             sq->left < c->left + c->width &&
2168             sq->left + sq->width >= c->left) {
2169                 unsigned left = sq->left;
2170                 unsigned width = sq->width;
2171
2172                 if (c->left > left) {
2173                         width -= c->left - left;
2174                         left = c->left;
2175                 }
2176                 if (c->left + c->width < left + width)
2177                         width -= left + width - c->left - c->width;
2178                 left -= c->left;
2179                 left = tpg_hscale_div(tpg, p, left);
2180                 width = tpg_hscale_div(tpg, p, width);
2181                 memcpy(vbuf + left, tpg->contrast_line[p], width);
2182         }
2183         if (tpg->insert_sav) {
2184                 unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width / 3);
2185                 u8 *p = vbuf + offset;
2186                 unsigned vact = 0, hact = 0;
2187
2188                 p[0] = 0xff;
2189                 p[1] = 0;
2190                 p[2] = 0;
2191                 p[3] = 0x80 | (params->sav_eav_f << 6) |
2192                         (vact << 5) | (hact << 4) |
2193                         ((hact ^ vact) << 3) |
2194                         ((hact ^ params->sav_eav_f) << 2) |
2195                         ((params->sav_eav_f ^ vact) << 1) |
2196                         (hact ^ vact ^ params->sav_eav_f);
2197         }
2198         if (tpg->insert_eav) {
2199                 unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width * 2 / 3);
2200                 u8 *p = vbuf + offset;
2201                 unsigned vact = 0, hact = 1;
2202
2203                 p[0] = 0xff;
2204                 p[1] = 0;
2205                 p[2] = 0;
2206                 p[3] = 0x80 | (params->sav_eav_f << 6) |
2207                         (vact << 5) | (hact << 4) |
2208                         ((hact ^ vact) << 3) |
2209                         ((hact ^ params->sav_eav_f) << 2) |
2210                         ((params->sav_eav_f ^ vact) << 1) |
2211                         (hact ^ vact ^ params->sav_eav_f);
2212         }
2213 }
2214
2215 static void tpg_fill_plane_pattern(const struct tpg_data *tpg,
2216                                    const struct tpg_draw_params *params,
2217                                    unsigned p, unsigned h, u8 *vbuf)
2218 {
2219         unsigned twopixsize = params->twopixsize;
2220         unsigned img_width = params->img_width;
2221         unsigned mv_hor_old = params->mv_hor_old;
2222         unsigned mv_hor_new = params->mv_hor_new;
2223         unsigned mv_vert_old = params->mv_vert_old;
2224         unsigned mv_vert_new = params->mv_vert_new;
2225         unsigned frame_line = params->frame_line;
2226         unsigned frame_line_next = params->frame_line_next;
2227         unsigned line_offset = tpg_hscale_div(tpg, p, tpg->crop.left);
2228         bool even;
2229         bool fill_blank = false;
2230         unsigned pat_line_old;
2231         unsigned pat_line_new;
2232         u8 *linestart_older;
2233         u8 *linestart_newer;
2234         u8 *linestart_top;
2235         u8 *linestart_bottom;
2236
2237         even = !(frame_line & 1);
2238
2239         if (h >= params->hmax) {
2240                 if (params->hmax == tpg->compose.height)
2241                         return;
2242                 if (!tpg->perc_fill_blank)
2243                         return;
2244                 fill_blank = true;
2245         }
2246
2247         if (tpg->vflip) {
2248                 frame_line = tpg->src_height - frame_line - 1;
2249                 frame_line_next = tpg->src_height - frame_line_next - 1;
2250         }
2251
2252         if (fill_blank) {
2253                 linestart_older = tpg->contrast_line[p];
2254                 linestart_newer = tpg->contrast_line[p];
2255         } else if (tpg->qual != TPG_QUAL_NOISE &&
2256                    (frame_line < tpg->border.top ||
2257                     frame_line >= tpg->border.top + tpg->border.height)) {
2258                 linestart_older = tpg->black_line[p];
2259                 linestart_newer = tpg->black_line[p];
2260         } else if (tpg->pattern == TPG_PAT_NOISE || tpg->qual == TPG_QUAL_NOISE) {
2261                 linestart_older = tpg->random_line[p] +
2262                                   twopixsize * prandom_u32_max(tpg->src_width / 2);
2263                 linestart_newer = tpg->random_line[p] +
2264                                   twopixsize * prandom_u32_max(tpg->src_width / 2);
2265         } else {
2266                 unsigned frame_line_old =
2267                         (frame_line + mv_vert_old) % tpg->src_height;
2268                 unsigned frame_line_new =
2269                         (frame_line + mv_vert_new) % tpg->src_height;
2270                 unsigned pat_line_next_old;
2271                 unsigned pat_line_next_new;
2272
2273                 pat_line_old = tpg_get_pat_line(tpg, frame_line_old);
2274                 pat_line_new = tpg_get_pat_line(tpg, frame_line_new);
2275                 linestart_older = tpg->lines[pat_line_old][p] + mv_hor_old;
2276                 linestart_newer = tpg->lines[pat_line_new][p] + mv_hor_new;
2277
2278                 if (tpg->vdownsampling[p] > 1 && frame_line != frame_line_next) {
2279                         int avg_pat;
2280
2281                         /*
2282                          * Now decide whether we need to use downsampled_lines[].
2283                          * That's necessary if the two lines use different patterns.
2284                          */
2285                         pat_line_next_old = tpg_get_pat_line(tpg,
2286                                         (frame_line_next + mv_vert_old) % tpg->src_height);
2287                         pat_line_next_new = tpg_get_pat_line(tpg,
2288                                         (frame_line_next + mv_vert_new) % tpg->src_height);
2289
2290                         switch (tpg->field) {
2291                         case V4L2_FIELD_INTERLACED:
2292                         case V4L2_FIELD_INTERLACED_BT:
2293                         case V4L2_FIELD_INTERLACED_TB:
2294                                 avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_new);
2295                                 if (avg_pat < 0)
2296                                         break;
2297                                 linestart_older = tpg->downsampled_lines[avg_pat][p] + mv_hor_old;
2298                                 linestart_newer = linestart_older;
2299                                 break;
2300                         case V4L2_FIELD_NONE:
2301                         case V4L2_FIELD_TOP:
2302                         case V4L2_FIELD_BOTTOM:
2303                         case V4L2_FIELD_SEQ_BT:
2304                         case V4L2_FIELD_SEQ_TB:
2305                                 avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_next_old);
2306                                 if (avg_pat >= 0)
2307                                         linestart_older = tpg->downsampled_lines[avg_pat][p] +
2308                                                 mv_hor_old;
2309                                 avg_pat = tpg_pattern_avg(tpg, pat_line_new, pat_line_next_new);
2310                                 if (avg_pat >= 0)
2311                                         linestart_newer = tpg->downsampled_lines[avg_pat][p] +
2312                                                 mv_hor_new;
2313                                 break;
2314                         }
2315                 }
2316                 linestart_older += line_offset;
2317                 linestart_newer += line_offset;
2318         }
2319         if (tpg->field_alternate) {
2320                 linestart_top = linestart_bottom = linestart_older;
2321         } else if (params->is_60hz) {
2322                 linestart_top = linestart_newer;
2323                 linestart_bottom = linestart_older;
2324         } else {
2325                 linestart_top = linestart_older;
2326                 linestart_bottom = linestart_newer;
2327         }
2328
2329         switch (tpg->field) {
2330         case V4L2_FIELD_INTERLACED:
2331         case V4L2_FIELD_INTERLACED_TB:
2332         case V4L2_FIELD_SEQ_TB:
2333         case V4L2_FIELD_SEQ_BT:
2334                 if (even)
2335                         memcpy(vbuf, linestart_top, img_width);
2336                 else
2337                         memcpy(vbuf, linestart_bottom, img_width);
2338                 break;
2339         case V4L2_FIELD_INTERLACED_BT:
2340                 if (even)
2341                         memcpy(vbuf, linestart_bottom, img_width);
2342                 else
2343                         memcpy(vbuf, linestart_top, img_width);
2344                 break;
2345         case V4L2_FIELD_TOP:
2346                 memcpy(vbuf, linestart_top, img_width);
2347                 break;
2348         case V4L2_FIELD_BOTTOM:
2349                 memcpy(vbuf, linestart_bottom, img_width);
2350                 break;
2351         case V4L2_FIELD_NONE:
2352         default:
2353                 memcpy(vbuf, linestart_older, img_width);
2354                 break;
2355         }
2356 }
2357
2358 void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std,
2359                            unsigned p, u8 *vbuf)
2360 {
2361         struct tpg_draw_params params;
2362         unsigned factor = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
2363
2364         /* Coarse scaling with Bresenham */
2365         unsigned int_part = (tpg->crop.height / factor) / tpg->compose.height;
2366         unsigned fract_part = (tpg->crop.height / factor) % tpg->compose.height;
2367         unsigned src_y = 0;
2368         unsigned error = 0;
2369         unsigned h;
2370
2371         tpg_recalc(tpg);
2372
2373         params.is_tv = std;
2374         params.is_60hz = std & V4L2_STD_525_60;
2375         params.twopixsize = tpg->twopixelsize[p];
2376         params.img_width = tpg_hdiv(tpg, p, tpg->compose.width);
2377         params.stride = tpg->bytesperline[p];
2378         params.hmax = (tpg->compose.height * tpg->perc_fill) / 100;
2379
2380         tpg_fill_params_pattern(tpg, p, &params);
2381         tpg_fill_params_extras(tpg, p, &params);
2382
2383         vbuf += tpg_hdiv(tpg, p, tpg->compose.left);
2384
2385         for (h = 0; h < tpg->compose.height; h++) {
2386                 unsigned buf_line;
2387
2388                 params.frame_line = tpg_calc_frameline(tpg, src_y, tpg->field);
2389                 params.frame_line_next = params.frame_line;
2390                 buf_line = tpg_calc_buffer_line(tpg, h, tpg->field);
2391                 src_y += int_part;
2392                 error += fract_part;
2393                 if (error >= tpg->compose.height) {
2394                         error -= tpg->compose.height;
2395                         src_y++;
2396                 }
2397
2398                 /*
2399                  * For line-interleaved formats determine the 'plane'
2400                  * based on the buffer line.
2401                  */
2402                 if (tpg_g_interleaved(tpg))
2403                         p = tpg_g_interleaved_plane(tpg, buf_line);
2404
2405                 if (tpg->vdownsampling[p] > 1) {
2406                         /*
2407                          * When doing vertical downsampling the field setting
2408                          * matters: for SEQ_BT/TB we downsample each field
2409                          * separately (i.e. lines 0+2 are combined, as are
2410                          * lines 1+3), for the other field settings we combine
2411                          * odd and even lines. Doing that for SEQ_BT/TB would
2412                          * be really weird.
2413                          */
2414                         if (tpg->field == V4L2_FIELD_SEQ_BT ||
2415                             tpg->field == V4L2_FIELD_SEQ_TB) {
2416                                 unsigned next_src_y = src_y;
2417
2418                                 if ((h & 3) >= 2)
2419                                         continue;
2420                                 next_src_y += int_part;
2421                                 if (error + fract_part >= tpg->compose.height)
2422                                         next_src_y++;
2423                                 params.frame_line_next =
2424                                         tpg_calc_frameline(tpg, next_src_y, tpg->field);
2425                         } else {
2426                                 if (h & 1)
2427                                         continue;
2428                                 params.frame_line_next =
2429                                         tpg_calc_frameline(tpg, src_y, tpg->field);
2430                         }
2431
2432                         buf_line /= tpg->vdownsampling[p];
2433                 }
2434                 tpg_fill_plane_pattern(tpg, &params, p, h,
2435                                 vbuf + buf_line * params.stride);
2436                 tpg_fill_plane_extras(tpg, &params, p, h,
2437                                 vbuf + buf_line * params.stride);
2438         }
2439 }
2440 EXPORT_SYMBOL_GPL(tpg_fill_plane_buffer);
2441
2442 void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
2443 {
2444         unsigned offset = 0;
2445         unsigned i;
2446
2447         if (tpg->buffers > 1) {
2448                 tpg_fill_plane_buffer(tpg, std, p, vbuf);
2449                 return;
2450         }
2451
2452         for (i = 0; i < tpg_g_planes(tpg); i++) {
2453                 tpg_fill_plane_buffer(tpg, std, i, vbuf + offset);
2454                 offset += tpg_calc_plane_size(tpg, i);
2455         }
2456 }
2457 EXPORT_SYMBOL_GPL(tpg_fillbuffer);
2458
2459 MODULE_DESCRIPTION("V4L2 Test Pattern Generator");
2460 MODULE_AUTHOR("Hans Verkuil");
2461 MODULE_LICENSE("GPL");