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