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