lightnvm: NVM should depend on HAS_DMA
[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.169, 224), COEFF(-0.331, 224), COEFF(0.5, 224) },
509 { COEFF(0.5, 224), COEFF(-0.419, 224), COEFF(-0.081, 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.169, 255), COEFF(-0.331, 255), COEFF(0.5, 255) },
514 { COEFF(0.5, 255), COEFF(-0.419, 255), COEFF(-0.081, 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 case V4L2_YCBCR_ENC_SYCC:
562 rgb2ycbcr(full ? bt601_full : bt601, r, g, b, y_offset, y, cb, cr);
563 break;
564 case V4L2_YCBCR_ENC_XV601:
565 /* Ignore quantization range, there is only one possible
566 * Y'CbCr encoding. */
567 rgb2ycbcr(bt601, r, g, b, 16, y, cb, cr);
568 break;
569 case V4L2_YCBCR_ENC_XV709:
570 /* Ignore quantization range, there is only one possible
571 * Y'CbCr encoding. */
572 rgb2ycbcr(rec709, r, g, b, 16, y, cb, cr);
573 break;
574 case V4L2_YCBCR_ENC_BT2020:
575 rgb2ycbcr(full ? bt2020_full : bt2020, r, g, b, y_offset, y, cb, cr);
576 break;
577 case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
578 lin_y = (COEFF(0.2627, 255) * rec709_to_linear(r) +
579 COEFF(0.6780, 255) * rec709_to_linear(g) +
580 COEFF(0.0593, 255) * rec709_to_linear(b)) >> 16;
581 yc = linear_to_rec709(lin_y);
582 *y = full ? yc : (yc * 219) / 255 + (16 << 4);
583 if (b <= yc)
584 *cb = (((b - yc) * (full ? bt2020c_full[0] : bt2020c[0])) >> 16) + (128 << 4);
585 else
586 *cb = (((b - yc) * (full ? bt2020c_full[1] : bt2020c[1])) >> 16) + (128 << 4);
587 if (r <= yc)
588 *cr = (((r - yc) * (full ? bt2020c_full[2] : bt2020c[2])) >> 16) + (128 << 4);
589 else
590 *cr = (((r - yc) * (full ? bt2020c_full[3] : bt2020c[3])) >> 16) + (128 << 4);
591 break;
592 case V4L2_YCBCR_ENC_SMPTE240M:
593 rgb2ycbcr(full ? smpte240m_full : smpte240m, r, g, b, y_offset, y, cb, cr);
594 break;
595 case V4L2_YCBCR_ENC_709:
596 default:
597 rgb2ycbcr(full ? rec709_full : rec709, r, g, b, y_offset, y, cb, cr);
598 break;
599 }
600 }
601
602 static void ycbcr2rgb(const int m[3][3], int y, int cb, int cr,
603 int y_offset, int *r, int *g, int *b)
604 {
605 y -= y_offset << 4;
606 cb -= 128 << 4;
607 cr -= 128 << 4;
608 *r = m[0][0] * y + m[0][1] * cb + m[0][2] * cr;
609 *g = m[1][0] * y + m[1][1] * cb + m[1][2] * cr;
610 *b = m[2][0] * y + m[2][1] * cb + m[2][2] * cr;
611 *r = clamp(*r >> 12, 0, 0xff0);
612 *g = clamp(*g >> 12, 0, 0xff0);
613 *b = clamp(*b >> 12, 0, 0xff0);
614 }
615
616 static void ycbcr_to_color(struct tpg_data *tpg, int y, int cb, int cr,
617 int *r, int *g, int *b)
618 {
619 #undef COEFF
620 #define COEFF(v, r) ((int)(0.5 + (v) * ((255.0 * 255.0 * 16.0) / (r))))
621 static const int bt601[3][3] = {
622 { COEFF(1, 219), COEFF(0, 224), COEFF(1.4020, 224) },
623 { COEFF(1, 219), COEFF(-0.3441, 224), COEFF(-0.7141, 224) },
624 { COEFF(1, 219), COEFF(1.7720, 224), COEFF(0, 224) },
625 };
626 static const int bt601_full[3][3] = {
627 { COEFF(1, 255), COEFF(0, 255), COEFF(1.4020, 255) },
628 { COEFF(1, 255), COEFF(-0.3441, 255), COEFF(-0.7141, 255) },
629 { COEFF(1, 255), COEFF(1.7720, 255), COEFF(0, 255) },
630 };
631 static const int rec709[3][3] = {
632 { COEFF(1, 219), COEFF(0, 224), COEFF(1.5748, 224) },
633 { COEFF(1, 219), COEFF(-0.1873, 224), COEFF(-0.4681, 224) },
634 { COEFF(1, 219), COEFF(1.8556, 224), COEFF(0, 224) },
635 };
636 static const int rec709_full[3][3] = {
637 { COEFF(1, 255), COEFF(0, 255), COEFF(1.5748, 255) },
638 { COEFF(1, 255), COEFF(-0.1873, 255), COEFF(-0.4681, 255) },
639 { COEFF(1, 255), COEFF(1.8556, 255), COEFF(0, 255) },
640 };
641 static const int smpte240m[3][3] = {
642 { COEFF(1, 219), COEFF(0, 224), COEFF(1.5756, 224) },
643 { COEFF(1, 219), COEFF(-0.2253, 224), COEFF(-0.4767, 224) },
644 { COEFF(1, 219), COEFF(1.8270, 224), COEFF(0, 224) },
645 };
646 static const int smpte240m_full[3][3] = {
647 { COEFF(1, 255), COEFF(0, 255), COEFF(1.5756, 255) },
648 { COEFF(1, 255), COEFF(-0.2253, 255), COEFF(-0.4767, 255) },
649 { COEFF(1, 255), COEFF(1.8270, 255), COEFF(0, 255) },
650 };
651 static const int bt2020[3][3] = {
652 { COEFF(1, 219), COEFF(0, 224), COEFF(1.4746, 224) },
653 { COEFF(1, 219), COEFF(-0.1646, 224), COEFF(-0.5714, 224) },
654 { COEFF(1, 219), COEFF(1.8814, 224), COEFF(0, 224) },
655 };
656 static const int bt2020_full[3][3] = {
657 { COEFF(1, 255), COEFF(0, 255), COEFF(1.4746, 255) },
658 { COEFF(1, 255), COEFF(-0.1646, 255), COEFF(-0.5714, 255) },
659 { COEFF(1, 255), COEFF(1.8814, 255), COEFF(0, 255) },
660 };
661 static const int bt2020c[4] = {
662 COEFF(1.9404, 224), COEFF(1.5816, 224),
663 COEFF(1.7184, 224), COEFF(0.9936, 224),
664 };
665 static const int bt2020c_full[4] = {
666 COEFF(1.9404, 255), COEFF(1.5816, 255),
667 COEFF(1.7184, 255), COEFF(0.9936, 255),
668 };
669
670 bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE;
671 unsigned y_offset = full ? 0 : 16;
672 int y_fac = full ? COEFF(1.0, 255) : COEFF(1.0, 219);
673 int lin_r, lin_g, lin_b, lin_y;
674
675 switch (tpg->real_ycbcr_enc) {
676 case V4L2_YCBCR_ENC_601:
677 case V4L2_YCBCR_ENC_SYCC:
678 ycbcr2rgb(full ? bt601_full : bt601, y, cb, cr, y_offset, r, g, b);
679 break;
680 case V4L2_YCBCR_ENC_XV601:
681 /* Ignore quantization range, there is only one possible
682 * Y'CbCr encoding. */
683 ycbcr2rgb(bt601, y, cb, cr, 16, r, g, b);
684 break;
685 case V4L2_YCBCR_ENC_XV709:
686 /* Ignore quantization range, there is only one possible
687 * Y'CbCr encoding. */
688 ycbcr2rgb(rec709, y, cb, cr, 16, r, g, b);
689 break;
690 case V4L2_YCBCR_ENC_BT2020:
691 ycbcr2rgb(full ? bt2020_full : bt2020, y, cb, cr, y_offset, r, g, b);
692 break;
693 case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
694 y -= full ? 0 : 16 << 4;
695 cb -= 128 << 4;
696 cr -= 128 << 4;
697
698 if (cb <= 0)
699 *b = y_fac * y + (full ? bt2020c_full[0] : bt2020c[0]) * cb;
700 else
701 *b = y_fac * y + (full ? bt2020c_full[1] : bt2020c[1]) * cb;
702 *b = *b >> 12;
703 if (cr <= 0)
704 *r = y_fac * y + (full ? bt2020c_full[2] : bt2020c[2]) * cr;
705 else
706 *r = y_fac * y + (full ? bt2020c_full[3] : bt2020c[3]) * cr;
707 *r = *r >> 12;
708 lin_r = rec709_to_linear(*r);
709 lin_b = rec709_to_linear(*b);
710 lin_y = rec709_to_linear((y * 255) / (full ? 255 : 219));
711
712 lin_g = COEFF(1.0 / 0.6780, 255) * lin_y -
713 COEFF(0.2627 / 0.6780, 255) * lin_r -
714 COEFF(0.0593 / 0.6780, 255) * lin_b;
715 *g = linear_to_rec709(lin_g >> 12);
716 break;
717 case V4L2_YCBCR_ENC_SMPTE240M:
718 ycbcr2rgb(full ? smpte240m_full : smpte240m, y, cb, cr, y_offset, r, g, b);
719 break;
720 case V4L2_YCBCR_ENC_709:
721 default:
722 ycbcr2rgb(full ? rec709_full : rec709, y, cb, cr, y_offset, r, g, b);
723 break;
724 }
725 }
726
727 /* precalculate color bar values to speed up rendering */
728 static void precalculate_color(struct tpg_data *tpg, int k)
729 {
730 int col = k;
731 int r = tpg_colors[col].r;
732 int g = tpg_colors[col].g;
733 int b = tpg_colors[col].b;
734
735 if (k == TPG_COLOR_TEXTBG) {
736 col = tpg_get_textbg_color(tpg);
737
738 r = tpg_colors[col].r;
739 g = tpg_colors[col].g;
740 b = tpg_colors[col].b;
741 } else if (k == TPG_COLOR_TEXTFG) {
742 col = tpg_get_textfg_color(tpg);
743
744 r = tpg_colors[col].r;
745 g = tpg_colors[col].g;
746 b = tpg_colors[col].b;
747 } else if (tpg->pattern == TPG_PAT_NOISE) {
748 r = g = b = prandom_u32_max(256);
749 } else if (k == TPG_COLOR_RANDOM) {
750 r = g = b = tpg->qual_offset + prandom_u32_max(196);
751 } else if (k >= TPG_COLOR_RAMP) {
752 r = g = b = k - TPG_COLOR_RAMP;
753 }
754
755 if (tpg->pattern == TPG_PAT_CSC_COLORBAR && col <= TPG_COLOR_CSC_BLACK) {
756 r = tpg_csc_colors[tpg->colorspace][tpg->real_xfer_func][col].r;
757 g = tpg_csc_colors[tpg->colorspace][tpg->real_xfer_func][col].g;
758 b = tpg_csc_colors[tpg->colorspace][tpg->real_xfer_func][col].b;
759 } else {
760 r <<= 4;
761 g <<= 4;
762 b <<= 4;
763 }
764 if (tpg->qual == TPG_QUAL_GRAY || tpg->fourcc == V4L2_PIX_FMT_GREY ||
765 tpg->fourcc == V4L2_PIX_FMT_Y16 ||
766 tpg->fourcc == V4L2_PIX_FMT_Y16_BE) {
767 /* Rec. 709 Luma function */
768 /* (0.2126, 0.7152, 0.0722) * (255 * 256) */
769 r = g = b = (13879 * r + 46688 * g + 4713 * b) >> 16;
770 }
771
772 /*
773 * The assumption is that the RGB output is always full range,
774 * so only if the rgb_range overrides the 'real' rgb range do
775 * we need to convert the RGB values.
776 *
777 * Remember that r, g and b are still in the 0 - 0xff0 range.
778 */
779 if (tpg->real_rgb_range == V4L2_DV_RGB_RANGE_LIMITED &&
780 tpg->rgb_range == V4L2_DV_RGB_RANGE_FULL && !tpg->is_yuv) {
781 /*
782 * Convert from full range (which is what r, g and b are)
783 * to limited range (which is the 'real' RGB range), which
784 * is then interpreted as full range.
785 */
786 r = (r * 219) / 255 + (16 << 4);
787 g = (g * 219) / 255 + (16 << 4);
788 b = (b * 219) / 255 + (16 << 4);
789 } else if (tpg->real_rgb_range != V4L2_DV_RGB_RANGE_LIMITED &&
790 tpg->rgb_range == V4L2_DV_RGB_RANGE_LIMITED && !tpg->is_yuv) {
791 /*
792 * Clamp r, g and b to the limited range and convert to full
793 * range since that's what we deliver.
794 */
795 r = clamp(r, 16 << 4, 235 << 4);
796 g = clamp(g, 16 << 4, 235 << 4);
797 b = clamp(b, 16 << 4, 235 << 4);
798 r = (r - (16 << 4)) * 255 / 219;
799 g = (g - (16 << 4)) * 255 / 219;
800 b = (b - (16 << 4)) * 255 / 219;
801 }
802
803 if (tpg->brightness != 128 || tpg->contrast != 128 ||
804 tpg->saturation != 128 || tpg->hue) {
805 /* Implement these operations */
806 int y, cb, cr;
807 int tmp_cb, tmp_cr;
808
809 /* First convert to YCbCr */
810
811 color_to_ycbcr(tpg, r, g, b, &y, &cb, &cr);
812
813 y = (16 << 4) + ((y - (16 << 4)) * tpg->contrast) / 128;
814 y += (tpg->brightness << 4) - (128 << 4);
815
816 cb -= 128 << 4;
817 cr -= 128 << 4;
818 tmp_cb = (cb * cos(128 + tpg->hue)) / 127 + (cr * sin[128 + tpg->hue]) / 127;
819 tmp_cr = (cr * cos(128 + tpg->hue)) / 127 - (cb * sin[128 + tpg->hue]) / 127;
820
821 cb = (128 << 4) + (tmp_cb * tpg->contrast * tpg->saturation) / (128 * 128);
822 cr = (128 << 4) + (tmp_cr * tpg->contrast * tpg->saturation) / (128 * 128);
823 if (tpg->is_yuv) {
824 tpg->colors[k][0] = clamp(y >> 4, 1, 254);
825 tpg->colors[k][1] = clamp(cb >> 4, 1, 254);
826 tpg->colors[k][2] = clamp(cr >> 4, 1, 254);
827 return;
828 }
829 ycbcr_to_color(tpg, y, cb, cr, &r, &g, &b);
830 }
831
832 if (tpg->is_yuv) {
833 /* Convert to YCbCr */
834 int y, cb, cr;
835
836 color_to_ycbcr(tpg, r, g, b, &y, &cb, &cr);
837
838 if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) {
839 y = clamp(y, 16 << 4, 235 << 4);
840 cb = clamp(cb, 16 << 4, 240 << 4);
841 cr = clamp(cr, 16 << 4, 240 << 4);
842 }
843 y = clamp(y >> 4, 1, 254);
844 cb = clamp(cb >> 4, 1, 254);
845 cr = clamp(cr >> 4, 1, 254);
846 switch (tpg->fourcc) {
847 case V4L2_PIX_FMT_YUV444:
848 y >>= 4;
849 cb >>= 4;
850 cr >>= 4;
851 break;
852 case V4L2_PIX_FMT_YUV555:
853 y >>= 3;
854 cb >>= 3;
855 cr >>= 3;
856 break;
857 case V4L2_PIX_FMT_YUV565:
858 y >>= 3;
859 cb >>= 2;
860 cr >>= 3;
861 break;
862 }
863 tpg->colors[k][0] = y;
864 tpg->colors[k][1] = cb;
865 tpg->colors[k][2] = cr;
866 } else {
867 if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) {
868 r = (r * 219) / 255 + (16 << 4);
869 g = (g * 219) / 255 + (16 << 4);
870 b = (b * 219) / 255 + (16 << 4);
871 }
872 switch (tpg->fourcc) {
873 case V4L2_PIX_FMT_RGB332:
874 r >>= 9;
875 g >>= 9;
876 b >>= 10;
877 break;
878 case V4L2_PIX_FMT_RGB565:
879 case V4L2_PIX_FMT_RGB565X:
880 r >>= 7;
881 g >>= 6;
882 b >>= 7;
883 break;
884 case V4L2_PIX_FMT_RGB444:
885 case V4L2_PIX_FMT_XRGB444:
886 case V4L2_PIX_FMT_ARGB444:
887 r >>= 8;
888 g >>= 8;
889 b >>= 8;
890 break;
891 case V4L2_PIX_FMT_RGB555:
892 case V4L2_PIX_FMT_XRGB555:
893 case V4L2_PIX_FMT_ARGB555:
894 case V4L2_PIX_FMT_RGB555X:
895 case V4L2_PIX_FMT_XRGB555X:
896 case V4L2_PIX_FMT_ARGB555X:
897 r >>= 7;
898 g >>= 7;
899 b >>= 7;
900 break;
901 case V4L2_PIX_FMT_BGR666:
902 r >>= 6;
903 g >>= 6;
904 b >>= 6;
905 break;
906 default:
907 r >>= 4;
908 g >>= 4;
909 b >>= 4;
910 break;
911 }
912
913 tpg->colors[k][0] = r;
914 tpg->colors[k][1] = g;
915 tpg->colors[k][2] = b;
916 }
917 }
918
919 static void tpg_precalculate_colors(struct tpg_data *tpg)
920 {
921 int k;
922
923 for (k = 0; k < TPG_COLOR_MAX; k++)
924 precalculate_color(tpg, k);
925 }
926
927 /* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */
928 static void gen_twopix(struct tpg_data *tpg,
929 u8 buf[TPG_MAX_PLANES][8], int color, bool odd)
930 {
931 unsigned offset = odd * tpg->twopixelsize[0] / 2;
932 u8 alpha = tpg->alpha_component;
933 u8 r_y, g_u, b_v;
934
935 if (tpg->alpha_red_only && color != TPG_COLOR_CSC_RED &&
936 color != TPG_COLOR_100_RED &&
937 color != TPG_COLOR_75_RED)
938 alpha = 0;
939 if (color == TPG_COLOR_RANDOM)
940 precalculate_color(tpg, color);
941 r_y = tpg->colors[color][0]; /* R or precalculated Y */
942 g_u = tpg->colors[color][1]; /* G or precalculated U */
943 b_v = tpg->colors[color][2]; /* B or precalculated V */
944
945 switch (tpg->fourcc) {
946 case V4L2_PIX_FMT_GREY:
947 buf[0][offset] = r_y;
948 break;
949 case V4L2_PIX_FMT_Y16:
950 /*
951 * Ideally both bytes should be set to r_y, but then you won't
952 * be able to detect endian problems. So keep it 0 except for
953 * the corner case where r_y is 0xff so white really will be
954 * white (0xffff).
955 */
956 buf[0][offset] = r_y == 0xff ? r_y : 0;
957 buf[0][offset+1] = r_y;
958 break;
959 case V4L2_PIX_FMT_Y16_BE:
960 /* See comment for V4L2_PIX_FMT_Y16 above */
961 buf[0][offset] = r_y;
962 buf[0][offset+1] = r_y == 0xff ? r_y : 0;
963 break;
964 case V4L2_PIX_FMT_YUV422M:
965 case V4L2_PIX_FMT_YUV422P:
966 case V4L2_PIX_FMT_YUV420:
967 case V4L2_PIX_FMT_YUV420M:
968 buf[0][offset] = r_y;
969 if (odd) {
970 buf[1][0] = (buf[1][0] + g_u) / 2;
971 buf[2][0] = (buf[2][0] + b_v) / 2;
972 buf[1][1] = buf[1][0];
973 buf[2][1] = buf[2][0];
974 break;
975 }
976 buf[1][0] = g_u;
977 buf[2][0] = b_v;
978 break;
979 case V4L2_PIX_FMT_YVU422M:
980 case V4L2_PIX_FMT_YVU420:
981 case V4L2_PIX_FMT_YVU420M:
982 buf[0][offset] = r_y;
983 if (odd) {
984 buf[1][0] = (buf[1][0] + b_v) / 2;
985 buf[2][0] = (buf[2][0] + g_u) / 2;
986 buf[1][1] = buf[1][0];
987 buf[2][1] = buf[2][0];
988 break;
989 }
990 buf[1][0] = b_v;
991 buf[2][0] = g_u;
992 break;
993
994 case V4L2_PIX_FMT_NV12:
995 case V4L2_PIX_FMT_NV12M:
996 case V4L2_PIX_FMT_NV16:
997 case V4L2_PIX_FMT_NV16M:
998 buf[0][offset] = r_y;
999 if (odd) {
1000 buf[1][0] = (buf[1][0] + g_u) / 2;
1001 buf[1][1] = (buf[1][1] + b_v) / 2;
1002 break;
1003 }
1004 buf[1][0] = g_u;
1005 buf[1][1] = b_v;
1006 break;
1007 case V4L2_PIX_FMT_NV21:
1008 case V4L2_PIX_FMT_NV21M:
1009 case V4L2_PIX_FMT_NV61:
1010 case V4L2_PIX_FMT_NV61M:
1011 buf[0][offset] = r_y;
1012 if (odd) {
1013 buf[1][0] = (buf[1][0] + b_v) / 2;
1014 buf[1][1] = (buf[1][1] + g_u) / 2;
1015 break;
1016 }
1017 buf[1][0] = b_v;
1018 buf[1][1] = g_u;
1019 break;
1020
1021 case V4L2_PIX_FMT_YUV444M:
1022 buf[0][offset] = r_y;
1023 buf[1][offset] = g_u;
1024 buf[2][offset] = b_v;
1025 break;
1026
1027 case V4L2_PIX_FMT_YVU444M:
1028 buf[0][offset] = r_y;
1029 buf[1][offset] = b_v;
1030 buf[2][offset] = g_u;
1031 break;
1032
1033 case V4L2_PIX_FMT_NV24:
1034 buf[0][offset] = r_y;
1035 buf[1][2 * offset] = g_u;
1036 buf[1][2 * offset + 1] = b_v;
1037 break;
1038
1039 case V4L2_PIX_FMT_NV42:
1040 buf[0][offset] = r_y;
1041 buf[1][2 * offset] = b_v;
1042 buf[1][2 * offset + 1] = g_u;
1043 break;
1044
1045 case V4L2_PIX_FMT_YUYV:
1046 buf[0][offset] = r_y;
1047 if (odd) {
1048 buf[0][1] = (buf[0][1] + g_u) / 2;
1049 buf[0][3] = (buf[0][3] + b_v) / 2;
1050 break;
1051 }
1052 buf[0][1] = g_u;
1053 buf[0][3] = b_v;
1054 break;
1055 case V4L2_PIX_FMT_UYVY:
1056 buf[0][offset + 1] = r_y;
1057 if (odd) {
1058 buf[0][0] = (buf[0][0] + g_u) / 2;
1059 buf[0][2] = (buf[0][2] + b_v) / 2;
1060 break;
1061 }
1062 buf[0][0] = g_u;
1063 buf[0][2] = b_v;
1064 break;
1065 case V4L2_PIX_FMT_YVYU:
1066 buf[0][offset] = r_y;
1067 if (odd) {
1068 buf[0][1] = (buf[0][1] + b_v) / 2;
1069 buf[0][3] = (buf[0][3] + g_u) / 2;
1070 break;
1071 }
1072 buf[0][1] = b_v;
1073 buf[0][3] = g_u;
1074 break;
1075 case V4L2_PIX_FMT_VYUY:
1076 buf[0][offset + 1] = r_y;
1077 if (odd) {
1078 buf[0][0] = (buf[0][0] + b_v) / 2;
1079 buf[0][2] = (buf[0][2] + g_u) / 2;
1080 break;
1081 }
1082 buf[0][0] = b_v;
1083 buf[0][2] = g_u;
1084 break;
1085 case V4L2_PIX_FMT_RGB332:
1086 buf[0][offset] = (r_y << 5) | (g_u << 2) | b_v;
1087 break;
1088 case V4L2_PIX_FMT_YUV565:
1089 case V4L2_PIX_FMT_RGB565:
1090 buf[0][offset] = (g_u << 5) | b_v;
1091 buf[0][offset + 1] = (r_y << 3) | (g_u >> 3);
1092 break;
1093 case V4L2_PIX_FMT_RGB565X:
1094 buf[0][offset] = (r_y << 3) | (g_u >> 3);
1095 buf[0][offset + 1] = (g_u << 5) | b_v;
1096 break;
1097 case V4L2_PIX_FMT_RGB444:
1098 case V4L2_PIX_FMT_XRGB444:
1099 alpha = 0;
1100 /* fall through */
1101 case V4L2_PIX_FMT_YUV444:
1102 case V4L2_PIX_FMT_ARGB444:
1103 buf[0][offset] = (g_u << 4) | b_v;
1104 buf[0][offset + 1] = (alpha & 0xf0) | r_y;
1105 break;
1106 case V4L2_PIX_FMT_RGB555:
1107 case V4L2_PIX_FMT_XRGB555:
1108 alpha = 0;
1109 /* fall through */
1110 case V4L2_PIX_FMT_YUV555:
1111 case V4L2_PIX_FMT_ARGB555:
1112 buf[0][offset] = (g_u << 5) | b_v;
1113 buf[0][offset + 1] = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
1114 break;
1115 case V4L2_PIX_FMT_RGB555X:
1116 case V4L2_PIX_FMT_XRGB555X:
1117 alpha = 0;
1118 /* fall through */
1119 case V4L2_PIX_FMT_ARGB555X:
1120 buf[0][offset] = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
1121 buf[0][offset + 1] = (g_u << 5) | b_v;
1122 break;
1123 case V4L2_PIX_FMT_RGB24:
1124 buf[0][offset] = r_y;
1125 buf[0][offset + 1] = g_u;
1126 buf[0][offset + 2] = b_v;
1127 break;
1128 case V4L2_PIX_FMT_BGR24:
1129 buf[0][offset] = b_v;
1130 buf[0][offset + 1] = g_u;
1131 buf[0][offset + 2] = r_y;
1132 break;
1133 case V4L2_PIX_FMT_BGR666:
1134 buf[0][offset] = (b_v << 2) | (g_u >> 4);
1135 buf[0][offset + 1] = (g_u << 4) | (r_y >> 2);
1136 buf[0][offset + 2] = r_y << 6;
1137 buf[0][offset + 3] = 0;
1138 break;
1139 case V4L2_PIX_FMT_RGB32:
1140 case V4L2_PIX_FMT_XRGB32:
1141 alpha = 0;
1142 /* fall through */
1143 case V4L2_PIX_FMT_YUV32:
1144 case V4L2_PIX_FMT_ARGB32:
1145 buf[0][offset] = alpha;
1146 buf[0][offset + 1] = r_y;
1147 buf[0][offset + 2] = g_u;
1148 buf[0][offset + 3] = b_v;
1149 break;
1150 case V4L2_PIX_FMT_BGR32:
1151 case V4L2_PIX_FMT_XBGR32:
1152 alpha = 0;
1153 /* fall through */
1154 case V4L2_PIX_FMT_ABGR32:
1155 buf[0][offset] = b_v;
1156 buf[0][offset + 1] = g_u;
1157 buf[0][offset + 2] = r_y;
1158 buf[0][offset + 3] = alpha;
1159 break;
1160 case V4L2_PIX_FMT_SBGGR8:
1161 buf[0][offset] = odd ? g_u : b_v;
1162 buf[1][offset] = odd ? r_y : g_u;
1163 break;
1164 case V4L2_PIX_FMT_SGBRG8:
1165 buf[0][offset] = odd ? b_v : g_u;
1166 buf[1][offset] = odd ? g_u : r_y;
1167 break;
1168 case V4L2_PIX_FMT_SGRBG8:
1169 buf[0][offset] = odd ? r_y : g_u;
1170 buf[1][offset] = odd ? g_u : b_v;
1171 break;
1172 case V4L2_PIX_FMT_SRGGB8:
1173 buf[0][offset] = odd ? g_u : r_y;
1174 buf[1][offset] = odd ? b_v : g_u;
1175 break;
1176 case V4L2_PIX_FMT_SBGGR10:
1177 buf[0][offset] = odd ? g_u << 2 : b_v << 2;
1178 buf[0][offset + 1] = odd ? g_u >> 6 : b_v >> 6;
1179 buf[1][offset] = odd ? r_y << 2 : g_u << 2;
1180 buf[1][offset + 1] = odd ? r_y >> 6 : g_u >> 6;
1181 buf[0][offset] |= (buf[0][offset] >> 2) & 3;
1182 buf[1][offset] |= (buf[1][offset] >> 2) & 3;
1183 break;
1184 case V4L2_PIX_FMT_SGBRG10:
1185 buf[0][offset] = odd ? b_v << 2 : g_u << 2;
1186 buf[0][offset + 1] = odd ? b_v >> 6 : g_u >> 6;
1187 buf[1][offset] = odd ? g_u << 2 : r_y << 2;
1188 buf[1][offset + 1] = odd ? g_u >> 6 : r_y >> 6;
1189 buf[0][offset] |= (buf[0][offset] >> 2) & 3;
1190 buf[1][offset] |= (buf[1][offset] >> 2) & 3;
1191 break;
1192 case V4L2_PIX_FMT_SGRBG10:
1193 buf[0][offset] = odd ? r_y << 2 : g_u << 2;
1194 buf[0][offset + 1] = odd ? r_y >> 6 : g_u >> 6;
1195 buf[1][offset] = odd ? g_u << 2 : b_v << 2;
1196 buf[1][offset + 1] = odd ? g_u >> 6 : b_v >> 6;
1197 buf[0][offset] |= (buf[0][offset] >> 2) & 3;
1198 buf[1][offset] |= (buf[1][offset] >> 2) & 3;
1199 break;
1200 case V4L2_PIX_FMT_SRGGB10:
1201 buf[0][offset] = odd ? g_u << 2 : r_y << 2;
1202 buf[0][offset + 1] = odd ? g_u >> 6 : r_y >> 6;
1203 buf[1][offset] = odd ? b_v << 2 : g_u << 2;
1204 buf[1][offset + 1] = odd ? b_v >> 6 : g_u >> 6;
1205 buf[0][offset] |= (buf[0][offset] >> 2) & 3;
1206 buf[1][offset] |= (buf[1][offset] >> 2) & 3;
1207 break;
1208 case V4L2_PIX_FMT_SBGGR12:
1209 buf[0][offset] = odd ? g_u << 4 : b_v << 4;
1210 buf[0][offset + 1] = odd ? g_u >> 4 : b_v >> 4;
1211 buf[1][offset] = odd ? r_y << 4 : g_u << 4;
1212 buf[1][offset + 1] = odd ? r_y >> 4 : g_u >> 4;
1213 buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
1214 buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
1215 break;
1216 case V4L2_PIX_FMT_SGBRG12:
1217 buf[0][offset] = odd ? b_v << 4 : g_u << 4;
1218 buf[0][offset + 1] = odd ? b_v >> 4 : g_u >> 4;
1219 buf[1][offset] = odd ? g_u << 4 : r_y << 4;
1220 buf[1][offset + 1] = odd ? g_u >> 4 : r_y >> 4;
1221 buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
1222 buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
1223 break;
1224 case V4L2_PIX_FMT_SGRBG12:
1225 buf[0][offset] = odd ? r_y << 4 : g_u << 4;
1226 buf[0][offset + 1] = odd ? r_y >> 4 : g_u >> 4;
1227 buf[1][offset] = odd ? g_u << 4 : b_v << 4;
1228 buf[1][offset + 1] = odd ? g_u >> 4 : b_v >> 4;
1229 buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
1230 buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
1231 break;
1232 case V4L2_PIX_FMT_SRGGB12:
1233 buf[0][offset] = odd ? g_u << 4 : r_y << 4;
1234 buf[0][offset + 1] = odd ? g_u >> 4 : r_y >> 4;
1235 buf[1][offset] = odd ? b_v << 4 : g_u << 4;
1236 buf[1][offset + 1] = odd ? b_v >> 4 : g_u >> 4;
1237 buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
1238 buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
1239 break;
1240 }
1241 }
1242
1243 unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line)
1244 {
1245 switch (tpg->fourcc) {
1246 case V4L2_PIX_FMT_SBGGR8:
1247 case V4L2_PIX_FMT_SGBRG8:
1248 case V4L2_PIX_FMT_SGRBG8:
1249 case V4L2_PIX_FMT_SRGGB8:
1250 case V4L2_PIX_FMT_SBGGR10:
1251 case V4L2_PIX_FMT_SGBRG10:
1252 case V4L2_PIX_FMT_SGRBG10:
1253 case V4L2_PIX_FMT_SRGGB10:
1254 case V4L2_PIX_FMT_SBGGR12:
1255 case V4L2_PIX_FMT_SGBRG12:
1256 case V4L2_PIX_FMT_SGRBG12:
1257 case V4L2_PIX_FMT_SRGGB12:
1258 return buf_line & 1;
1259 default:
1260 return 0;
1261 }
1262 }
1263 EXPORT_SYMBOL_GPL(tpg_g_interleaved_plane);
1264
1265 /* Return how many pattern lines are used by the current pattern. */
1266 static unsigned tpg_get_pat_lines(const struct tpg_data *tpg)
1267 {
1268 switch (tpg->pattern) {
1269 case TPG_PAT_CHECKERS_16X16:
1270 case TPG_PAT_CHECKERS_2X2:
1271 case TPG_PAT_CHECKERS_1X1:
1272 case TPG_PAT_COLOR_CHECKERS_2X2:
1273 case TPG_PAT_COLOR_CHECKERS_1X1:
1274 case TPG_PAT_ALTERNATING_HLINES:
1275 case TPG_PAT_CROSS_1_PIXEL:
1276 case TPG_PAT_CROSS_2_PIXELS:
1277 case TPG_PAT_CROSS_10_PIXELS:
1278 return 2;
1279 case TPG_PAT_100_COLORSQUARES:
1280 case TPG_PAT_100_HCOLORBAR:
1281 return 8;
1282 default:
1283 return 1;
1284 }
1285 }
1286
1287 /* Which pattern line should be used for the given frame line. */
1288 static unsigned tpg_get_pat_line(const struct tpg_data *tpg, unsigned line)
1289 {
1290 switch (tpg->pattern) {
1291 case TPG_PAT_CHECKERS_16X16:
1292 return (line >> 4) & 1;
1293 case TPG_PAT_CHECKERS_1X1:
1294 case TPG_PAT_COLOR_CHECKERS_1X1:
1295 case TPG_PAT_ALTERNATING_HLINES:
1296 return line & 1;
1297 case TPG_PAT_CHECKERS_2X2:
1298 case TPG_PAT_COLOR_CHECKERS_2X2:
1299 return (line & 2) >> 1;
1300 case TPG_PAT_100_COLORSQUARES:
1301 case TPG_PAT_100_HCOLORBAR:
1302 return (line * 8) / tpg->src_height;
1303 case TPG_PAT_CROSS_1_PIXEL:
1304 return line == tpg->src_height / 2;
1305 case TPG_PAT_CROSS_2_PIXELS:
1306 return (line + 1) / 2 == tpg->src_height / 4;
1307 case TPG_PAT_CROSS_10_PIXELS:
1308 return (line + 10) / 20 == tpg->src_height / 40;
1309 default:
1310 return 0;
1311 }
1312 }
1313
1314 /*
1315 * Which color should be used for the given pattern line and X coordinate.
1316 * Note: x is in the range 0 to 2 * tpg->src_width.
1317 */
1318 static enum tpg_color tpg_get_color(const struct tpg_data *tpg,
1319 unsigned pat_line, unsigned x)
1320 {
1321 /* Maximum number of bars are TPG_COLOR_MAX - otherwise, the input print code
1322 should be modified */
1323 static const enum tpg_color bars[3][8] = {
1324 /* Standard ITU-R 75% color bar sequence */
1325 { TPG_COLOR_CSC_WHITE, TPG_COLOR_75_YELLOW,
1326 TPG_COLOR_75_CYAN, TPG_COLOR_75_GREEN,
1327 TPG_COLOR_75_MAGENTA, TPG_COLOR_75_RED,
1328 TPG_COLOR_75_BLUE, TPG_COLOR_100_BLACK, },
1329 /* Standard ITU-R 100% color bar sequence */
1330 { TPG_COLOR_100_WHITE, TPG_COLOR_100_YELLOW,
1331 TPG_COLOR_100_CYAN, TPG_COLOR_100_GREEN,
1332 TPG_COLOR_100_MAGENTA, TPG_COLOR_100_RED,
1333 TPG_COLOR_100_BLUE, TPG_COLOR_100_BLACK, },
1334 /* Color bar sequence suitable to test CSC */
1335 { TPG_COLOR_CSC_WHITE, TPG_COLOR_CSC_YELLOW,
1336 TPG_COLOR_CSC_CYAN, TPG_COLOR_CSC_GREEN,
1337 TPG_COLOR_CSC_MAGENTA, TPG_COLOR_CSC_RED,
1338 TPG_COLOR_CSC_BLUE, TPG_COLOR_CSC_BLACK, },
1339 };
1340
1341 switch (tpg->pattern) {
1342 case TPG_PAT_75_COLORBAR:
1343 case TPG_PAT_100_COLORBAR:
1344 case TPG_PAT_CSC_COLORBAR:
1345 return bars[tpg->pattern][((x * 8) / tpg->src_width) % 8];
1346 case TPG_PAT_100_COLORSQUARES:
1347 return bars[1][(pat_line + (x * 8) / tpg->src_width) % 8];
1348 case TPG_PAT_100_HCOLORBAR:
1349 return bars[1][pat_line];
1350 case TPG_PAT_BLACK:
1351 return TPG_COLOR_100_BLACK;
1352 case TPG_PAT_WHITE:
1353 return TPG_COLOR_100_WHITE;
1354 case TPG_PAT_RED:
1355 return TPG_COLOR_100_RED;
1356 case TPG_PAT_GREEN:
1357 return TPG_COLOR_100_GREEN;
1358 case TPG_PAT_BLUE:
1359 return TPG_COLOR_100_BLUE;
1360 case TPG_PAT_CHECKERS_16X16:
1361 return (((x >> 4) & 1) ^ (pat_line & 1)) ?
1362 TPG_COLOR_100_BLACK : TPG_COLOR_100_WHITE;
1363 case TPG_PAT_CHECKERS_1X1:
1364 return ((x & 1) ^ (pat_line & 1)) ?
1365 TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
1366 case TPG_PAT_COLOR_CHECKERS_1X1:
1367 return ((x & 1) ^ (pat_line & 1)) ?
1368 TPG_COLOR_100_RED : TPG_COLOR_100_BLUE;
1369 case TPG_PAT_CHECKERS_2X2:
1370 return (((x >> 1) & 1) ^ (pat_line & 1)) ?
1371 TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
1372 case TPG_PAT_COLOR_CHECKERS_2X2:
1373 return (((x >> 1) & 1) ^ (pat_line & 1)) ?
1374 TPG_COLOR_100_RED : TPG_COLOR_100_BLUE;
1375 case TPG_PAT_ALTERNATING_HLINES:
1376 return pat_line ? TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
1377 case TPG_PAT_ALTERNATING_VLINES:
1378 return (x & 1) ? TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
1379 case TPG_PAT_CROSS_1_PIXEL:
1380 if (pat_line || (x % tpg->src_width) == tpg->src_width / 2)
1381 return TPG_COLOR_100_BLACK;
1382 return TPG_COLOR_100_WHITE;
1383 case TPG_PAT_CROSS_2_PIXELS:
1384 if (pat_line || ((x % tpg->src_width) + 1) / 2 == tpg->src_width / 4)
1385 return TPG_COLOR_100_BLACK;
1386 return TPG_COLOR_100_WHITE;
1387 case TPG_PAT_CROSS_10_PIXELS:
1388 if (pat_line || ((x % tpg->src_width) + 10) / 20 == tpg->src_width / 40)
1389 return TPG_COLOR_100_BLACK;
1390 return TPG_COLOR_100_WHITE;
1391 case TPG_PAT_GRAY_RAMP:
1392 return TPG_COLOR_RAMP + ((x % tpg->src_width) * 256) / tpg->src_width;
1393 default:
1394 return TPG_COLOR_100_RED;
1395 }
1396 }
1397
1398 /*
1399 * Given the pixel aspect ratio and video aspect ratio calculate the
1400 * coordinates of a centered square and the coordinates of the border of
1401 * the active video area. The coordinates are relative to the source
1402 * frame rectangle.
1403 */
1404 static void tpg_calculate_square_border(struct tpg_data *tpg)
1405 {
1406 unsigned w = tpg->src_width;
1407 unsigned h = tpg->src_height;
1408 unsigned sq_w, sq_h;
1409
1410 sq_w = (w * 2 / 5) & ~1;
1411 if (((w - sq_w) / 2) & 1)
1412 sq_w += 2;
1413 sq_h = sq_w;
1414 tpg->square.width = sq_w;
1415 if (tpg->vid_aspect == TPG_VIDEO_ASPECT_16X9_ANAMORPHIC) {
1416 unsigned ana_sq_w = (sq_w / 4) * 3;
1417
1418 if (((w - ana_sq_w) / 2) & 1)
1419 ana_sq_w += 2;
1420 tpg->square.width = ana_sq_w;
1421 }
1422 tpg->square.left = (w - tpg->square.width) / 2;
1423 if (tpg->pix_aspect == TPG_PIXEL_ASPECT_NTSC)
1424 sq_h = sq_w * 10 / 11;
1425 else if (tpg->pix_aspect == TPG_PIXEL_ASPECT_PAL)
1426 sq_h = sq_w * 59 / 54;
1427 tpg->square.height = sq_h;
1428 tpg->square.top = (h - sq_h) / 2;
1429 tpg->border.left = 0;
1430 tpg->border.width = w;
1431 tpg->border.top = 0;
1432 tpg->border.height = h;
1433 switch (tpg->vid_aspect) {
1434 case TPG_VIDEO_ASPECT_4X3:
1435 if (tpg->pix_aspect)
1436 return;
1437 if (3 * w >= 4 * h) {
1438 tpg->border.width = ((4 * h) / 3) & ~1;
1439 if (((w - tpg->border.width) / 2) & ~1)
1440 tpg->border.width -= 2;
1441 tpg->border.left = (w - tpg->border.width) / 2;
1442 break;
1443 }
1444 tpg->border.height = ((3 * w) / 4) & ~1;
1445 tpg->border.top = (h - tpg->border.height) / 2;
1446 break;
1447 case TPG_VIDEO_ASPECT_14X9_CENTRE:
1448 if (tpg->pix_aspect) {
1449 tpg->border.height = tpg->pix_aspect == TPG_PIXEL_ASPECT_NTSC ? 420 : 506;
1450 tpg->border.top = (h - tpg->border.height) / 2;
1451 break;
1452 }
1453 if (9 * w >= 14 * h) {
1454 tpg->border.width = ((14 * h) / 9) & ~1;
1455 if (((w - tpg->border.width) / 2) & ~1)
1456 tpg->border.width -= 2;
1457 tpg->border.left = (w - tpg->border.width) / 2;
1458 break;
1459 }
1460 tpg->border.height = ((9 * w) / 14) & ~1;
1461 tpg->border.top = (h - tpg->border.height) / 2;
1462 break;
1463 case TPG_VIDEO_ASPECT_16X9_CENTRE:
1464 if (tpg->pix_aspect) {
1465 tpg->border.height = tpg->pix_aspect == TPG_PIXEL_ASPECT_NTSC ? 368 : 442;
1466 tpg->border.top = (h - tpg->border.height) / 2;
1467 break;
1468 }
1469 if (9 * w >= 16 * h) {
1470 tpg->border.width = ((16 * h) / 9) & ~1;
1471 if (((w - tpg->border.width) / 2) & ~1)
1472 tpg->border.width -= 2;
1473 tpg->border.left = (w - tpg->border.width) / 2;
1474 break;
1475 }
1476 tpg->border.height = ((9 * w) / 16) & ~1;
1477 tpg->border.top = (h - tpg->border.height) / 2;
1478 break;
1479 default:
1480 break;
1481 }
1482 }
1483
1484 static void tpg_precalculate_line(struct tpg_data *tpg)
1485 {
1486 enum tpg_color contrast;
1487 u8 pix[TPG_MAX_PLANES][8];
1488 unsigned pat;
1489 unsigned p;
1490 unsigned x;
1491
1492 switch (tpg->pattern) {
1493 case TPG_PAT_GREEN:
1494 contrast = TPG_COLOR_100_RED;
1495 break;
1496 case TPG_PAT_CSC_COLORBAR:
1497 contrast = TPG_COLOR_CSC_GREEN;
1498 break;
1499 default:
1500 contrast = TPG_COLOR_100_GREEN;
1501 break;
1502 }
1503
1504 for (pat = 0; pat < tpg_get_pat_lines(tpg); pat++) {
1505 /* Coarse scaling with Bresenham */
1506 unsigned int_part = tpg->src_width / tpg->scaled_width;
1507 unsigned fract_part = tpg->src_width % tpg->scaled_width;
1508 unsigned src_x = 0;
1509 unsigned error = 0;
1510
1511 for (x = 0; x < tpg->scaled_width * 2; x += 2) {
1512 unsigned real_x = src_x;
1513 enum tpg_color color1, color2;
1514
1515 real_x = tpg->hflip ? tpg->src_width * 2 - real_x - 2 : real_x;
1516 color1 = tpg_get_color(tpg, pat, real_x);
1517
1518 src_x += int_part;
1519 error += fract_part;
1520 if (error >= tpg->scaled_width) {
1521 error -= tpg->scaled_width;
1522 src_x++;
1523 }
1524
1525 real_x = src_x;
1526 real_x = tpg->hflip ? tpg->src_width * 2 - real_x - 2 : real_x;
1527 color2 = tpg_get_color(tpg, pat, real_x);
1528
1529 src_x += int_part;
1530 error += fract_part;
1531 if (error >= tpg->scaled_width) {
1532 error -= tpg->scaled_width;
1533 src_x++;
1534 }
1535
1536 gen_twopix(tpg, pix, tpg->hflip ? color2 : color1, 0);
1537 gen_twopix(tpg, pix, tpg->hflip ? color1 : color2, 1);
1538 for (p = 0; p < tpg->planes; p++) {
1539 unsigned twopixsize = tpg->twopixelsize[p];
1540 unsigned hdiv = tpg->hdownsampling[p];
1541 u8 *pos = tpg->lines[pat][p] + tpg_hdiv(tpg, p, x);
1542
1543 memcpy(pos, pix[p], twopixsize / hdiv);
1544 }
1545 }
1546 }
1547
1548 if (tpg->vdownsampling[tpg->planes - 1] > 1) {
1549 unsigned pat_lines = tpg_get_pat_lines(tpg);
1550
1551 for (pat = 0; pat < pat_lines; pat++) {
1552 unsigned next_pat = (pat + 1) % pat_lines;
1553
1554 for (p = 1; p < tpg->planes; p++) {
1555 unsigned w = tpg_hdiv(tpg, p, tpg->scaled_width * 2);
1556 u8 *pos1 = tpg->lines[pat][p];
1557 u8 *pos2 = tpg->lines[next_pat][p];
1558 u8 *dest = tpg->downsampled_lines[pat][p];
1559
1560 for (x = 0; x < w; x++, pos1++, pos2++, dest++)
1561 *dest = ((u16)*pos1 + (u16)*pos2) / 2;
1562 }
1563 }
1564 }
1565
1566 gen_twopix(tpg, pix, contrast, 0);
1567 gen_twopix(tpg, pix, contrast, 1);
1568 for (p = 0; p < tpg->planes; p++) {
1569 unsigned twopixsize = tpg->twopixelsize[p];
1570 u8 *pos = tpg->contrast_line[p];
1571
1572 for (x = 0; x < tpg->scaled_width; x += 2, pos += twopixsize)
1573 memcpy(pos, pix[p], twopixsize);
1574 }
1575
1576 gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 0);
1577 gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 1);
1578 for (p = 0; p < tpg->planes; p++) {
1579 unsigned twopixsize = tpg->twopixelsize[p];
1580 u8 *pos = tpg->black_line[p];
1581
1582 for (x = 0; x < tpg->scaled_width; x += 2, pos += twopixsize)
1583 memcpy(pos, pix[p], twopixsize);
1584 }
1585
1586 for (x = 0; x < tpg->scaled_width * 2; x += 2) {
1587 gen_twopix(tpg, pix, TPG_COLOR_RANDOM, 0);
1588 gen_twopix(tpg, pix, TPG_COLOR_RANDOM, 1);
1589 for (p = 0; p < tpg->planes; p++) {
1590 unsigned twopixsize = tpg->twopixelsize[p];
1591 u8 *pos = tpg->random_line[p] + x * twopixsize / 2;
1592
1593 memcpy(pos, pix[p], twopixsize);
1594 }
1595 }
1596
1597 gen_twopix(tpg, tpg->textbg, TPG_COLOR_TEXTBG, 0);
1598 gen_twopix(tpg, tpg->textbg, TPG_COLOR_TEXTBG, 1);
1599 gen_twopix(tpg, tpg->textfg, TPG_COLOR_TEXTFG, 0);
1600 gen_twopix(tpg, tpg->textfg, TPG_COLOR_TEXTFG, 1);
1601 }
1602
1603 /* need this to do rgb24 rendering */
1604 typedef struct { u16 __; u8 _; } __packed x24;
1605
1606 #define PRINTSTR(PIXTYPE) do { \
1607 unsigned vdiv = tpg->vdownsampling[p]; \
1608 unsigned hdiv = tpg->hdownsampling[p]; \
1609 int line; \
1610 PIXTYPE fg; \
1611 PIXTYPE bg; \
1612 memcpy(&fg, tpg->textfg[p], sizeof(PIXTYPE)); \
1613 memcpy(&bg, tpg->textbg[p], sizeof(PIXTYPE)); \
1614 \
1615 for (line = first; line < 16; line += vdiv * step) { \
1616 int l = tpg->vflip ? 15 - line : line; \
1617 PIXTYPE *pos = (PIXTYPE *)(basep[p][(line / vdiv) & 1] + \
1618 ((y * step + l) / (vdiv * div)) * tpg->bytesperline[p] + \
1619 (x / hdiv) * sizeof(PIXTYPE)); \
1620 unsigned s; \
1621 \
1622 for (s = 0; s < len; s++) { \
1623 u8 chr = font8x16[text[s] * 16 + line]; \
1624 \
1625 if (hdiv == 2 && tpg->hflip) { \
1626 pos[3] = (chr & (0x01 << 6) ? fg : bg); \
1627 pos[2] = (chr & (0x01 << 4) ? fg : bg); \
1628 pos[1] = (chr & (0x01 << 2) ? fg : bg); \
1629 pos[0] = (chr & (0x01 << 0) ? fg : bg); \
1630 } else if (hdiv == 2) { \
1631 pos[0] = (chr & (0x01 << 7) ? fg : bg); \
1632 pos[1] = (chr & (0x01 << 5) ? fg : bg); \
1633 pos[2] = (chr & (0x01 << 3) ? fg : bg); \
1634 pos[3] = (chr & (0x01 << 1) ? fg : bg); \
1635 } else if (tpg->hflip) { \
1636 pos[7] = (chr & (0x01 << 7) ? fg : bg); \
1637 pos[6] = (chr & (0x01 << 6) ? fg : bg); \
1638 pos[5] = (chr & (0x01 << 5) ? fg : bg); \
1639 pos[4] = (chr & (0x01 << 4) ? fg : bg); \
1640 pos[3] = (chr & (0x01 << 3) ? fg : bg); \
1641 pos[2] = (chr & (0x01 << 2) ? fg : bg); \
1642 pos[1] = (chr & (0x01 << 1) ? fg : bg); \
1643 pos[0] = (chr & (0x01 << 0) ? fg : bg); \
1644 } else { \
1645 pos[0] = (chr & (0x01 << 7) ? fg : bg); \
1646 pos[1] = (chr & (0x01 << 6) ? fg : bg); \
1647 pos[2] = (chr & (0x01 << 5) ? fg : bg); \
1648 pos[3] = (chr & (0x01 << 4) ? fg : bg); \
1649 pos[4] = (chr & (0x01 << 3) ? fg : bg); \
1650 pos[5] = (chr & (0x01 << 2) ? fg : bg); \
1651 pos[6] = (chr & (0x01 << 1) ? fg : bg); \
1652 pos[7] = (chr & (0x01 << 0) ? fg : bg); \
1653 } \
1654 \
1655 pos += (tpg->hflip ? -8 : 8) / hdiv; \
1656 } \
1657 } \
1658 } while (0)
1659
1660 static noinline void tpg_print_str_2(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
1661 unsigned p, unsigned first, unsigned div, unsigned step,
1662 int y, int x, char *text, unsigned len)
1663 {
1664 PRINTSTR(u8);
1665 }
1666
1667 static noinline void tpg_print_str_4(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
1668 unsigned p, unsigned first, unsigned div, unsigned step,
1669 int y, int x, char *text, unsigned len)
1670 {
1671 PRINTSTR(u16);
1672 }
1673
1674 static noinline void tpg_print_str_6(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
1675 unsigned p, unsigned first, unsigned div, unsigned step,
1676 int y, int x, char *text, unsigned len)
1677 {
1678 PRINTSTR(x24);
1679 }
1680
1681 static noinline void tpg_print_str_8(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
1682 unsigned p, unsigned first, unsigned div, unsigned step,
1683 int y, int x, char *text, unsigned len)
1684 {
1685 PRINTSTR(u32);
1686 }
1687
1688 void tpg_gen_text(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
1689 int y, int x, char *text)
1690 {
1691 unsigned step = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
1692 unsigned div = step;
1693 unsigned first = 0;
1694 unsigned len = strlen(text);
1695 unsigned p;
1696
1697 if (font8x16 == NULL || basep == NULL)
1698 return;
1699
1700 /* Checks if it is possible to show string */
1701 if (y + 16 >= tpg->compose.height || x + 8 >= tpg->compose.width)
1702 return;
1703
1704 if (len > (tpg->compose.width - x) / 8)
1705 len = (tpg->compose.width - x) / 8;
1706 if (tpg->vflip)
1707 y = tpg->compose.height - y - 16;
1708 if (tpg->hflip)
1709 x = tpg->compose.width - x - 8;
1710 y += tpg->compose.top;
1711 x += tpg->compose.left;
1712 if (tpg->field == V4L2_FIELD_BOTTOM)
1713 first = 1;
1714 else if (tpg->field == V4L2_FIELD_SEQ_TB || tpg->field == V4L2_FIELD_SEQ_BT)
1715 div = 2;
1716
1717 for (p = 0; p < tpg->planes; p++) {
1718 /* Print text */
1719 switch (tpg->twopixelsize[p]) {
1720 case 2:
1721 tpg_print_str_2(tpg, basep, p, first, div, step, y, x,
1722 text, len);
1723 break;
1724 case 4:
1725 tpg_print_str_4(tpg, basep, p, first, div, step, y, x,
1726 text, len);
1727 break;
1728 case 6:
1729 tpg_print_str_6(tpg, basep, p, first, div, step, y, x,
1730 text, len);
1731 break;
1732 case 8:
1733 tpg_print_str_8(tpg, basep, p, first, div, step, y, x,
1734 text, len);
1735 break;
1736 }
1737 }
1738 }
1739 EXPORT_SYMBOL_GPL(tpg_gen_text);
1740
1741 void tpg_update_mv_step(struct tpg_data *tpg)
1742 {
1743 int factor = tpg->mv_hor_mode > TPG_MOVE_NONE ? -1 : 1;
1744
1745 if (tpg->hflip)
1746 factor = -factor;
1747 switch (tpg->mv_hor_mode) {
1748 case TPG_MOVE_NEG_FAST:
1749 case TPG_MOVE_POS_FAST:
1750 tpg->mv_hor_step = ((tpg->src_width + 319) / 320) * 4;
1751 break;
1752 case TPG_MOVE_NEG:
1753 case TPG_MOVE_POS:
1754 tpg->mv_hor_step = ((tpg->src_width + 639) / 640) * 4;
1755 break;
1756 case TPG_MOVE_NEG_SLOW:
1757 case TPG_MOVE_POS_SLOW:
1758 tpg->mv_hor_step = 2;
1759 break;
1760 case TPG_MOVE_NONE:
1761 tpg->mv_hor_step = 0;
1762 break;
1763 }
1764 if (factor < 0)
1765 tpg->mv_hor_step = tpg->src_width - tpg->mv_hor_step;
1766
1767 factor = tpg->mv_vert_mode > TPG_MOVE_NONE ? -1 : 1;
1768 switch (tpg->mv_vert_mode) {
1769 case TPG_MOVE_NEG_FAST:
1770 case TPG_MOVE_POS_FAST:
1771 tpg->mv_vert_step = ((tpg->src_width + 319) / 320) * 4;
1772 break;
1773 case TPG_MOVE_NEG:
1774 case TPG_MOVE_POS:
1775 tpg->mv_vert_step = ((tpg->src_width + 639) / 640) * 4;
1776 break;
1777 case TPG_MOVE_NEG_SLOW:
1778 case TPG_MOVE_POS_SLOW:
1779 tpg->mv_vert_step = 1;
1780 break;
1781 case TPG_MOVE_NONE:
1782 tpg->mv_vert_step = 0;
1783 break;
1784 }
1785 if (factor < 0)
1786 tpg->mv_vert_step = tpg->src_height - tpg->mv_vert_step;
1787 }
1788 EXPORT_SYMBOL_GPL(tpg_update_mv_step);
1789
1790 /* Map the line number relative to the crop rectangle to a frame line number */
1791 static unsigned tpg_calc_frameline(const struct tpg_data *tpg, unsigned src_y,
1792 unsigned field)
1793 {
1794 switch (field) {
1795 case V4L2_FIELD_TOP:
1796 return tpg->crop.top + src_y * 2;
1797 case V4L2_FIELD_BOTTOM:
1798 return tpg->crop.top + src_y * 2 + 1;
1799 default:
1800 return src_y + tpg->crop.top;
1801 }
1802 }
1803
1804 /*
1805 * Map the line number relative to the compose rectangle to a destination
1806 * buffer line number.
1807 */
1808 static unsigned tpg_calc_buffer_line(const struct tpg_data *tpg, unsigned y,
1809 unsigned field)
1810 {
1811 y += tpg->compose.top;
1812 switch (field) {
1813 case V4L2_FIELD_SEQ_TB:
1814 if (y & 1)
1815 return tpg->buf_height / 2 + y / 2;
1816 return y / 2;
1817 case V4L2_FIELD_SEQ_BT:
1818 if (y & 1)
1819 return y / 2;
1820 return tpg->buf_height / 2 + y / 2;
1821 default:
1822 return y;
1823 }
1824 }
1825
1826 static void tpg_recalc(struct tpg_data *tpg)
1827 {
1828 if (tpg->recalc_colors) {
1829 tpg->recalc_colors = false;
1830 tpg->recalc_lines = true;
1831 tpg->real_xfer_func = tpg->xfer_func;
1832 tpg->real_ycbcr_enc = tpg->ycbcr_enc;
1833 tpg->real_quantization = tpg->quantization;
1834
1835 if (tpg->xfer_func == V4L2_XFER_FUNC_DEFAULT)
1836 tpg->real_xfer_func =
1837 V4L2_MAP_XFER_FUNC_DEFAULT(tpg->colorspace);
1838
1839 if (tpg->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT)
1840 tpg->real_ycbcr_enc =
1841 V4L2_MAP_YCBCR_ENC_DEFAULT(tpg->colorspace);
1842
1843 if (tpg->quantization == V4L2_QUANTIZATION_DEFAULT)
1844 tpg->real_quantization =
1845 V4L2_MAP_QUANTIZATION_DEFAULT(!tpg->is_yuv,
1846 tpg->colorspace, tpg->real_ycbcr_enc);
1847
1848 tpg_precalculate_colors(tpg);
1849 }
1850 if (tpg->recalc_square_border) {
1851 tpg->recalc_square_border = false;
1852 tpg_calculate_square_border(tpg);
1853 }
1854 if (tpg->recalc_lines) {
1855 tpg->recalc_lines = false;
1856 tpg_precalculate_line(tpg);
1857 }
1858 }
1859
1860 void tpg_calc_text_basep(struct tpg_data *tpg,
1861 u8 *basep[TPG_MAX_PLANES][2], unsigned p, u8 *vbuf)
1862 {
1863 unsigned stride = tpg->bytesperline[p];
1864 unsigned h = tpg->buf_height;
1865
1866 tpg_recalc(tpg);
1867
1868 basep[p][0] = vbuf;
1869 basep[p][1] = vbuf;
1870 h /= tpg->vdownsampling[p];
1871 if (tpg->field == V4L2_FIELD_SEQ_TB)
1872 basep[p][1] += h * stride / 2;
1873 else if (tpg->field == V4L2_FIELD_SEQ_BT)
1874 basep[p][0] += h * stride / 2;
1875 if (p == 0 && tpg->interleaved)
1876 tpg_calc_text_basep(tpg, basep, 1, vbuf);
1877 }
1878 EXPORT_SYMBOL_GPL(tpg_calc_text_basep);
1879
1880 static int tpg_pattern_avg(const struct tpg_data *tpg,
1881 unsigned pat1, unsigned pat2)
1882 {
1883 unsigned pat_lines = tpg_get_pat_lines(tpg);
1884
1885 if (pat1 == (pat2 + 1) % pat_lines)
1886 return pat2;
1887 if (pat2 == (pat1 + 1) % pat_lines)
1888 return pat1;
1889 return -1;
1890 }
1891
1892 void tpg_log_status(struct tpg_data *tpg)
1893 {
1894 pr_info("tpg source WxH: %ux%u (%s)\n",
1895 tpg->src_width, tpg->src_height,
1896 tpg->is_yuv ? "YCbCr" : "RGB");
1897 pr_info("tpg field: %u\n", tpg->field);
1898 pr_info("tpg crop: %ux%u@%dx%d\n", tpg->crop.width, tpg->crop.height,
1899 tpg->crop.left, tpg->crop.top);
1900 pr_info("tpg compose: %ux%u@%dx%d\n", tpg->compose.width, tpg->compose.height,
1901 tpg->compose.left, tpg->compose.top);
1902 pr_info("tpg colorspace: %d\n", tpg->colorspace);
1903 pr_info("tpg transfer function: %d/%d\n", tpg->xfer_func, tpg->real_xfer_func);
1904 pr_info("tpg Y'CbCr encoding: %d/%d\n", tpg->ycbcr_enc, tpg->real_ycbcr_enc);
1905 pr_info("tpg quantization: %d/%d\n", tpg->quantization, tpg->real_quantization);
1906 pr_info("tpg RGB range: %d/%d\n", tpg->rgb_range, tpg->real_rgb_range);
1907 }
1908 EXPORT_SYMBOL_GPL(tpg_log_status);
1909
1910 /*
1911 * This struct contains common parameters used by both the drawing of the
1912 * test pattern and the drawing of the extras (borders, square, etc.)
1913 */
1914 struct tpg_draw_params {
1915 /* common data */
1916 bool is_tv;
1917 bool is_60hz;
1918 unsigned twopixsize;
1919 unsigned img_width;
1920 unsigned stride;
1921 unsigned hmax;
1922 unsigned frame_line;
1923 unsigned frame_line_next;
1924
1925 /* test pattern */
1926 unsigned mv_hor_old;
1927 unsigned mv_hor_new;
1928 unsigned mv_vert_old;
1929 unsigned mv_vert_new;
1930
1931 /* extras */
1932 unsigned wss_width;
1933 unsigned wss_random_offset;
1934 unsigned sav_eav_f;
1935 unsigned left_pillar_width;
1936 unsigned right_pillar_start;
1937 };
1938
1939 static void tpg_fill_params_pattern(const struct tpg_data *tpg, unsigned p,
1940 struct tpg_draw_params *params)
1941 {
1942 params->mv_hor_old =
1943 tpg_hscale_div(tpg, p, tpg->mv_hor_count % tpg->src_width);
1944 params->mv_hor_new =
1945 tpg_hscale_div(tpg, p, (tpg->mv_hor_count + tpg->mv_hor_step) %
1946 tpg->src_width);
1947 params->mv_vert_old = tpg->mv_vert_count % tpg->src_height;
1948 params->mv_vert_new =
1949 (tpg->mv_vert_count + tpg->mv_vert_step) % tpg->src_height;
1950 }
1951
1952 static void tpg_fill_params_extras(const struct tpg_data *tpg,
1953 unsigned p,
1954 struct tpg_draw_params *params)
1955 {
1956 unsigned left_pillar_width = 0;
1957 unsigned right_pillar_start = params->img_width;
1958
1959 params->wss_width = tpg->crop.left < tpg->src_width / 2 ?
1960 tpg->src_width / 2 - tpg->crop.left : 0;
1961 if (params->wss_width > tpg->crop.width)
1962 params->wss_width = tpg->crop.width;
1963 params->wss_width = tpg_hscale_div(tpg, p, params->wss_width);
1964 params->wss_random_offset =
1965 params->twopixsize * prandom_u32_max(tpg->src_width / 2);
1966
1967 if (tpg->crop.left < tpg->border.left) {
1968 left_pillar_width = tpg->border.left - tpg->crop.left;
1969 if (left_pillar_width > tpg->crop.width)
1970 left_pillar_width = tpg->crop.width;
1971 left_pillar_width = tpg_hscale_div(tpg, p, left_pillar_width);
1972 }
1973 params->left_pillar_width = left_pillar_width;
1974
1975 if (tpg->crop.left + tpg->crop.width >
1976 tpg->border.left + tpg->border.width) {
1977 right_pillar_start =
1978 tpg->border.left + tpg->border.width - tpg->crop.left;
1979 right_pillar_start =
1980 tpg_hscale_div(tpg, p, right_pillar_start);
1981 if (right_pillar_start > params->img_width)
1982 right_pillar_start = params->img_width;
1983 }
1984 params->right_pillar_start = right_pillar_start;
1985
1986 params->sav_eav_f = tpg->field ==
1987 (params->is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
1988 }
1989
1990 static void tpg_fill_plane_extras(const struct tpg_data *tpg,
1991 const struct tpg_draw_params *params,
1992 unsigned p, unsigned h, u8 *vbuf)
1993 {
1994 unsigned twopixsize = params->twopixsize;
1995 unsigned img_width = params->img_width;
1996 unsigned frame_line = params->frame_line;
1997 const struct v4l2_rect *sq = &tpg->square;
1998 const struct v4l2_rect *b = &tpg->border;
1999 const struct v4l2_rect *c = &tpg->crop;
2000
2001 if (params->is_tv && !params->is_60hz &&
2002 frame_line == 0 && params->wss_width) {
2003 /*
2004 * Replace the first half of the top line of a 50 Hz frame
2005 * with random data to simulate a WSS signal.
2006 */
2007 u8 *wss = tpg->random_line[p] + params->wss_random_offset;
2008
2009 memcpy(vbuf, wss, params->wss_width);
2010 }
2011
2012 if (tpg->show_border && frame_line >= b->top &&
2013 frame_line < b->top + b->height) {
2014 unsigned bottom = b->top + b->height - 1;
2015 unsigned left = params->left_pillar_width;
2016 unsigned right = params->right_pillar_start;
2017
2018 if (frame_line == b->top || frame_line == b->top + 1 ||
2019 frame_line == bottom || frame_line == bottom - 1) {
2020 memcpy(vbuf + left, tpg->contrast_line[p],
2021 right - left);
2022 } else {
2023 if (b->left >= c->left &&
2024 b->left < c->left + c->width)
2025 memcpy(vbuf + left,
2026 tpg->contrast_line[p], twopixsize);
2027 if (b->left + b->width > c->left &&
2028 b->left + b->width <= c->left + c->width)
2029 memcpy(vbuf + right - twopixsize,
2030 tpg->contrast_line[p], twopixsize);
2031 }
2032 }
2033 if (tpg->qual != TPG_QUAL_NOISE && frame_line >= b->top &&
2034 frame_line < b->top + b->height) {
2035 memcpy(vbuf, tpg->black_line[p], params->left_pillar_width);
2036 memcpy(vbuf + params->right_pillar_start, tpg->black_line[p],
2037 img_width - params->right_pillar_start);
2038 }
2039 if (tpg->show_square && frame_line >= sq->top &&
2040 frame_line < sq->top + sq->height &&
2041 sq->left < c->left + c->width &&
2042 sq->left + sq->width >= c->left) {
2043 unsigned left = sq->left;
2044 unsigned width = sq->width;
2045
2046 if (c->left > left) {
2047 width -= c->left - left;
2048 left = c->left;
2049 }
2050 if (c->left + c->width < left + width)
2051 width -= left + width - c->left - c->width;
2052 left -= c->left;
2053 left = tpg_hscale_div(tpg, p, left);
2054 width = tpg_hscale_div(tpg, p, width);
2055 memcpy(vbuf + left, tpg->contrast_line[p], width);
2056 }
2057 if (tpg->insert_sav) {
2058 unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width / 3);
2059 u8 *p = vbuf + offset;
2060 unsigned vact = 0, hact = 0;
2061
2062 p[0] = 0xff;
2063 p[1] = 0;
2064 p[2] = 0;
2065 p[3] = 0x80 | (params->sav_eav_f << 6) |
2066 (vact << 5) | (hact << 4) |
2067 ((hact ^ vact) << 3) |
2068 ((hact ^ params->sav_eav_f) << 2) |
2069 ((params->sav_eav_f ^ vact) << 1) |
2070 (hact ^ vact ^ params->sav_eav_f);
2071 }
2072 if (tpg->insert_eav) {
2073 unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width * 2 / 3);
2074 u8 *p = vbuf + offset;
2075 unsigned vact = 0, hact = 1;
2076
2077 p[0] = 0xff;
2078 p[1] = 0;
2079 p[2] = 0;
2080 p[3] = 0x80 | (params->sav_eav_f << 6) |
2081 (vact << 5) | (hact << 4) |
2082 ((hact ^ vact) << 3) |
2083 ((hact ^ params->sav_eav_f) << 2) |
2084 ((params->sav_eav_f ^ vact) << 1) |
2085 (hact ^ vact ^ params->sav_eav_f);
2086 }
2087 }
2088
2089 static void tpg_fill_plane_pattern(const struct tpg_data *tpg,
2090 const struct tpg_draw_params *params,
2091 unsigned p, unsigned h, u8 *vbuf)
2092 {
2093 unsigned twopixsize = params->twopixsize;
2094 unsigned img_width = params->img_width;
2095 unsigned mv_hor_old = params->mv_hor_old;
2096 unsigned mv_hor_new = params->mv_hor_new;
2097 unsigned mv_vert_old = params->mv_vert_old;
2098 unsigned mv_vert_new = params->mv_vert_new;
2099 unsigned frame_line = params->frame_line;
2100 unsigned frame_line_next = params->frame_line_next;
2101 unsigned line_offset = tpg_hscale_div(tpg, p, tpg->crop.left);
2102 bool even;
2103 bool fill_blank = false;
2104 unsigned pat_line_old;
2105 unsigned pat_line_new;
2106 u8 *linestart_older;
2107 u8 *linestart_newer;
2108 u8 *linestart_top;
2109 u8 *linestart_bottom;
2110
2111 even = !(frame_line & 1);
2112
2113 if (h >= params->hmax) {
2114 if (params->hmax == tpg->compose.height)
2115 return;
2116 if (!tpg->perc_fill_blank)
2117 return;
2118 fill_blank = true;
2119 }
2120
2121 if (tpg->vflip) {
2122 frame_line = tpg->src_height - frame_line - 1;
2123 frame_line_next = tpg->src_height - frame_line_next - 1;
2124 }
2125
2126 if (fill_blank) {
2127 linestart_older = tpg->contrast_line[p];
2128 linestart_newer = tpg->contrast_line[p];
2129 } else if (tpg->qual != TPG_QUAL_NOISE &&
2130 (frame_line < tpg->border.top ||
2131 frame_line >= tpg->border.top + tpg->border.height)) {
2132 linestart_older = tpg->black_line[p];
2133 linestart_newer = tpg->black_line[p];
2134 } else if (tpg->pattern == TPG_PAT_NOISE || tpg->qual == TPG_QUAL_NOISE) {
2135 linestart_older = tpg->random_line[p] +
2136 twopixsize * prandom_u32_max(tpg->src_width / 2);
2137 linestart_newer = tpg->random_line[p] +
2138 twopixsize * prandom_u32_max(tpg->src_width / 2);
2139 } else {
2140 unsigned frame_line_old =
2141 (frame_line + mv_vert_old) % tpg->src_height;
2142 unsigned frame_line_new =
2143 (frame_line + mv_vert_new) % tpg->src_height;
2144 unsigned pat_line_next_old;
2145 unsigned pat_line_next_new;
2146
2147 pat_line_old = tpg_get_pat_line(tpg, frame_line_old);
2148 pat_line_new = tpg_get_pat_line(tpg, frame_line_new);
2149 linestart_older = tpg->lines[pat_line_old][p] + mv_hor_old;
2150 linestart_newer = tpg->lines[pat_line_new][p] + mv_hor_new;
2151
2152 if (tpg->vdownsampling[p] > 1 && frame_line != frame_line_next) {
2153 int avg_pat;
2154
2155 /*
2156 * Now decide whether we need to use downsampled_lines[].
2157 * That's necessary if the two lines use different patterns.
2158 */
2159 pat_line_next_old = tpg_get_pat_line(tpg,
2160 (frame_line_next + mv_vert_old) % tpg->src_height);
2161 pat_line_next_new = tpg_get_pat_line(tpg,
2162 (frame_line_next + mv_vert_new) % tpg->src_height);
2163
2164 switch (tpg->field) {
2165 case V4L2_FIELD_INTERLACED:
2166 case V4L2_FIELD_INTERLACED_BT:
2167 case V4L2_FIELD_INTERLACED_TB:
2168 avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_new);
2169 if (avg_pat < 0)
2170 break;
2171 linestart_older = tpg->downsampled_lines[avg_pat][p] + mv_hor_old;
2172 linestart_newer = linestart_older;
2173 break;
2174 case V4L2_FIELD_NONE:
2175 case V4L2_FIELD_TOP:
2176 case V4L2_FIELD_BOTTOM:
2177 case V4L2_FIELD_SEQ_BT:
2178 case V4L2_FIELD_SEQ_TB:
2179 avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_next_old);
2180 if (avg_pat >= 0)
2181 linestart_older = tpg->downsampled_lines[avg_pat][p] +
2182 mv_hor_old;
2183 avg_pat = tpg_pattern_avg(tpg, pat_line_new, pat_line_next_new);
2184 if (avg_pat >= 0)
2185 linestart_newer = tpg->downsampled_lines[avg_pat][p] +
2186 mv_hor_new;
2187 break;
2188 }
2189 }
2190 linestart_older += line_offset;
2191 linestart_newer += line_offset;
2192 }
2193 if (tpg->field_alternate) {
2194 linestart_top = linestart_bottom = linestart_older;
2195 } else if (params->is_60hz) {
2196 linestart_top = linestart_newer;
2197 linestart_bottom = linestart_older;
2198 } else {
2199 linestart_top = linestart_older;
2200 linestart_bottom = linestart_newer;
2201 }
2202
2203 switch (tpg->field) {
2204 case V4L2_FIELD_INTERLACED:
2205 case V4L2_FIELD_INTERLACED_TB:
2206 case V4L2_FIELD_SEQ_TB:
2207 case V4L2_FIELD_SEQ_BT:
2208 if (even)
2209 memcpy(vbuf, linestart_top, img_width);
2210 else
2211 memcpy(vbuf, linestart_bottom, img_width);
2212 break;
2213 case V4L2_FIELD_INTERLACED_BT:
2214 if (even)
2215 memcpy(vbuf, linestart_bottom, img_width);
2216 else
2217 memcpy(vbuf, linestart_top, img_width);
2218 break;
2219 case V4L2_FIELD_TOP:
2220 memcpy(vbuf, linestart_top, img_width);
2221 break;
2222 case V4L2_FIELD_BOTTOM:
2223 memcpy(vbuf, linestart_bottom, img_width);
2224 break;
2225 case V4L2_FIELD_NONE:
2226 default:
2227 memcpy(vbuf, linestart_older, img_width);
2228 break;
2229 }
2230 }
2231
2232 void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std,
2233 unsigned p, u8 *vbuf)
2234 {
2235 struct tpg_draw_params params;
2236 unsigned factor = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
2237
2238 /* Coarse scaling with Bresenham */
2239 unsigned int_part = (tpg->crop.height / factor) / tpg->compose.height;
2240 unsigned fract_part = (tpg->crop.height / factor) % tpg->compose.height;
2241 unsigned src_y = 0;
2242 unsigned error = 0;
2243 unsigned h;
2244
2245 tpg_recalc(tpg);
2246
2247 params.is_tv = std;
2248 params.is_60hz = std & V4L2_STD_525_60;
2249 params.twopixsize = tpg->twopixelsize[p];
2250 params.img_width = tpg_hdiv(tpg, p, tpg->compose.width);
2251 params.stride = tpg->bytesperline[p];
2252 params.hmax = (tpg->compose.height * tpg->perc_fill) / 100;
2253
2254 tpg_fill_params_pattern(tpg, p, &params);
2255 tpg_fill_params_extras(tpg, p, &params);
2256
2257 vbuf += tpg_hdiv(tpg, p, tpg->compose.left);
2258
2259 for (h = 0; h < tpg->compose.height; h++) {
2260 unsigned buf_line;
2261
2262 params.frame_line = tpg_calc_frameline(tpg, src_y, tpg->field);
2263 params.frame_line_next = params.frame_line;
2264 buf_line = tpg_calc_buffer_line(tpg, h, tpg->field);
2265 src_y += int_part;
2266 error += fract_part;
2267 if (error >= tpg->compose.height) {
2268 error -= tpg->compose.height;
2269 src_y++;
2270 }
2271
2272 /*
2273 * For line-interleaved formats determine the 'plane'
2274 * based on the buffer line.
2275 */
2276 if (tpg_g_interleaved(tpg))
2277 p = tpg_g_interleaved_plane(tpg, buf_line);
2278
2279 if (tpg->vdownsampling[p] > 1) {
2280 /*
2281 * When doing vertical downsampling the field setting
2282 * matters: for SEQ_BT/TB we downsample each field
2283 * separately (i.e. lines 0+2 are combined, as are
2284 * lines 1+3), for the other field settings we combine
2285 * odd and even lines. Doing that for SEQ_BT/TB would
2286 * be really weird.
2287 */
2288 if (tpg->field == V4L2_FIELD_SEQ_BT ||
2289 tpg->field == V4L2_FIELD_SEQ_TB) {
2290 unsigned next_src_y = src_y;
2291
2292 if ((h & 3) >= 2)
2293 continue;
2294 next_src_y += int_part;
2295 if (error + fract_part >= tpg->compose.height)
2296 next_src_y++;
2297 params.frame_line_next =
2298 tpg_calc_frameline(tpg, next_src_y, tpg->field);
2299 } else {
2300 if (h & 1)
2301 continue;
2302 params.frame_line_next =
2303 tpg_calc_frameline(tpg, src_y, tpg->field);
2304 }
2305
2306 buf_line /= tpg->vdownsampling[p];
2307 }
2308 tpg_fill_plane_pattern(tpg, &params, p, h,
2309 vbuf + buf_line * params.stride);
2310 tpg_fill_plane_extras(tpg, &params, p, h,
2311 vbuf + buf_line * params.stride);
2312 }
2313 }
2314 EXPORT_SYMBOL_GPL(tpg_fill_plane_buffer);
2315
2316 void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
2317 {
2318 unsigned offset = 0;
2319 unsigned i;
2320
2321 if (tpg->buffers > 1) {
2322 tpg_fill_plane_buffer(tpg, std, p, vbuf);
2323 return;
2324 }
2325
2326 for (i = 0; i < tpg_g_planes(tpg); i++) {
2327 tpg_fill_plane_buffer(tpg, std, i, vbuf + offset);
2328 offset += tpg_calc_plane_size(tpg, i);
2329 }
2330 }
2331 EXPORT_SYMBOL_GPL(tpg_fillbuffer);
2332
2333 MODULE_DESCRIPTION("V4L2 Test Pattern Generator");
2334 MODULE_AUTHOR("Hans Verkuil");
2335 MODULE_LICENSE("GPL");
This page took 0.084417 seconds and 5 git commands to generate.