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