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