1 // SPDX-License-Identifier: GPL-2.0-only
3 * v4l2-tpg-core.c - Test Pattern Generator
5 * Note: gen_twopix and tpg_gen_text are based on code from vivi.c. See the
6 * vivi.c source for the copyright information of those functions.
8 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
11 #include <linux/module.h>
12 #include <media/tpg/v4l2-tpg.h>
14 /* Must remain in sync with enum tpg_pattern */
15 const char * const tpg_pattern_strings
[] = {
19 "Horizontal 100% Colorbar",
29 "2x2 Red/Green Checkers",
30 "1x1 Red/Green Checkers",
31 "Alternating Hor Lines",
32 "Alternating Vert Lines",
33 "One Pixel Wide Cross",
34 "Two Pixels Wide Cross",
35 "Ten Pixels Wide Cross",
40 EXPORT_SYMBOL_GPL(tpg_pattern_strings
);
42 /* Must remain in sync with enum tpg_aspect */
43 const char * const tpg_aspect_strings
[] = {
44 "Source Width x Height",
51 EXPORT_SYMBOL_GPL(tpg_aspect_strings
);
54 * Sine table: sin[0] = 127 * sin(-180 degrees)
55 * sin[128] = 127 * sin(0 degrees)
56 * sin[256] = 127 * sin(180 degrees)
58 static const s8 sin
[257] = {
59 0, -4, -7, -11, -13, -18, -20, -22, -26, -29, -33, -35, -37, -41, -43, -48,
60 -50, -52, -56, -58, -62, -63, -65, -69, -71, -75, -76, -78, -82, -83, -87, -88,
61 -90, -93, -94, -97, -99, -101, -103, -104, -107, -108, -110, -111, -112, -114, -115, -117,
62 -118, -119, -120, -121, -122, -123, -123, -124, -125, -125, -126, -126, -127, -127, -127, -127,
63 -127, -127, -127, -127, -126, -126, -125, -125, -124, -124, -123, -122, -121, -120, -119, -118,
64 -117, -116, -114, -113, -111, -110, -109, -107, -105, -103, -101, -100, -97, -96, -93, -91,
65 -90, -87, -85, -82, -80, -76, -75, -73, -69, -67, -63, -62, -60, -56, -54, -50,
66 -48, -46, -41, -39, -35, -33, -31, -26, -24, -20, -18, -15, -11, -9, -4, -2,
67 0, 2, 4, 9, 11, 15, 18, 20, 24, 26, 31, 33, 35, 39, 41, 46,
68 48, 50, 54, 56, 60, 62, 64, 67, 69, 73, 75, 76, 80, 82, 85, 87,
69 90, 91, 93, 96, 97, 100, 101, 103, 105, 107, 109, 110, 111, 113, 114, 116,
70 117, 118, 119, 120, 121, 122, 123, 124, 124, 125, 125, 126, 126, 127, 127, 127,
71 127, 127, 127, 127, 127, 126, 126, 125, 125, 124, 123, 123, 122, 121, 120, 119,
72 118, 117, 115, 114, 112, 111, 110, 108, 107, 104, 103, 101, 99, 97, 94, 93,
73 90, 88, 87, 83, 82, 78, 76, 75, 71, 69, 65, 64, 62, 58, 56, 52,
74 50, 48, 43, 41, 37, 35, 33, 29, 26, 22, 20, 18, 13, 11, 7, 4,
78 #define cos(idx) sin[((idx) + 64) % sizeof(sin)]
80 /* Global font descriptor */
81 static const u8
*font8x16
;
83 void tpg_set_font(const u8
*f
)
87 EXPORT_SYMBOL_GPL(tpg_set_font
);
89 void tpg_init(struct tpg_data
*tpg
, unsigned w
, unsigned h
)
91 memset(tpg
, 0, sizeof(*tpg
));
92 tpg
->scaled_width
= tpg
->src_width
= w
;
93 tpg
->src_height
= tpg
->buf_height
= h
;
94 tpg
->crop
.width
= tpg
->compose
.width
= w
;
95 tpg
->crop
.height
= tpg
->compose
.height
= h
;
96 tpg
->recalc_colors
= true;
97 tpg
->recalc_square_border
= true;
98 tpg
->brightness
= 128;
100 tpg
->saturation
= 128;
102 tpg
->mv_hor_mode
= TPG_MOVE_NONE
;
103 tpg
->mv_vert_mode
= TPG_MOVE_NONE
;
104 tpg
->field
= V4L2_FIELD_NONE
;
105 tpg_s_fourcc(tpg
, V4L2_PIX_FMT_RGB24
);
106 tpg
->colorspace
= V4L2_COLORSPACE_SRGB
;
107 tpg
->perc_fill
= 100;
108 tpg
->hsv_enc
= V4L2_HSV_ENC_180
;
110 EXPORT_SYMBOL_GPL(tpg_init
);
112 int tpg_alloc(struct tpg_data
*tpg
, unsigned max_w
)
117 tpg
->max_line_width
= max_w
;
118 for (pat
= 0; pat
< TPG_MAX_PAT_LINES
; pat
++) {
119 for (plane
= 0; plane
< TPG_MAX_PLANES
; plane
++) {
120 unsigned pixelsz
= plane
? 2 : 4;
122 tpg
->lines
[pat
][plane
] =
123 vzalloc(array3_size(max_w
, 2, pixelsz
));
124 if (!tpg
->lines
[pat
][plane
])
128 tpg
->downsampled_lines
[pat
][plane
] =
129 vzalloc(array3_size(max_w
, 2, pixelsz
));
130 if (!tpg
->downsampled_lines
[pat
][plane
])
134 for (plane
= 0; plane
< TPG_MAX_PLANES
; plane
++) {
135 unsigned pixelsz
= plane
? 2 : 4;
137 tpg
->contrast_line
[plane
] =
138 vzalloc(array_size(pixelsz
, max_w
));
139 if (!tpg
->contrast_line
[plane
])
141 tpg
->black_line
[plane
] =
142 vzalloc(array_size(pixelsz
, max_w
));
143 if (!tpg
->black_line
[plane
])
145 tpg
->random_line
[plane
] =
146 vzalloc(array3_size(max_w
, 2, pixelsz
));
147 if (!tpg
->random_line
[plane
])
152 EXPORT_SYMBOL_GPL(tpg_alloc
);
154 void tpg_free(struct tpg_data
*tpg
)
159 for (pat
= 0; pat
< TPG_MAX_PAT_LINES
; pat
++)
160 for (plane
= 0; plane
< TPG_MAX_PLANES
; plane
++) {
161 vfree(tpg
->lines
[pat
][plane
]);
162 tpg
->lines
[pat
][plane
] = NULL
;
165 vfree(tpg
->downsampled_lines
[pat
][plane
]);
166 tpg
->downsampled_lines
[pat
][plane
] = NULL
;
168 for (plane
= 0; plane
< TPG_MAX_PLANES
; plane
++) {
169 vfree(tpg
->contrast_line
[plane
]);
170 vfree(tpg
->black_line
[plane
]);
171 vfree(tpg
->random_line
[plane
]);
172 tpg
->contrast_line
[plane
] = NULL
;
173 tpg
->black_line
[plane
] = NULL
;
174 tpg
->random_line
[plane
] = NULL
;
177 EXPORT_SYMBOL_GPL(tpg_free
);
179 bool tpg_s_fourcc(struct tpg_data
*tpg
, u32 fourcc
)
181 tpg
->fourcc
= fourcc
;
184 tpg
->recalc_colors
= true;
185 tpg
->interleaved
= false;
186 tpg
->vdownsampling
[0] = 1;
187 tpg
->hdownsampling
[0] = 1;
193 case V4L2_PIX_FMT_SBGGR8
:
194 case V4L2_PIX_FMT_SGBRG8
:
195 case V4L2_PIX_FMT_SGRBG8
:
196 case V4L2_PIX_FMT_SRGGB8
:
197 case V4L2_PIX_FMT_SBGGR10
:
198 case V4L2_PIX_FMT_SGBRG10
:
199 case V4L2_PIX_FMT_SGRBG10
:
200 case V4L2_PIX_FMT_SRGGB10
:
201 case V4L2_PIX_FMT_SBGGR12
:
202 case V4L2_PIX_FMT_SGBRG12
:
203 case V4L2_PIX_FMT_SGRBG12
:
204 case V4L2_PIX_FMT_SRGGB12
:
205 tpg
->interleaved
= true;
206 tpg
->vdownsampling
[1] = 1;
207 tpg
->hdownsampling
[1] = 1;
210 case V4L2_PIX_FMT_RGB332
:
211 case V4L2_PIX_FMT_RGB565
:
212 case V4L2_PIX_FMT_RGB565X
:
213 case V4L2_PIX_FMT_RGB444
:
214 case V4L2_PIX_FMT_XRGB444
:
215 case V4L2_PIX_FMT_ARGB444
:
216 case V4L2_PIX_FMT_RGB555
:
217 case V4L2_PIX_FMT_XRGB555
:
218 case V4L2_PIX_FMT_ARGB555
:
219 case V4L2_PIX_FMT_RGB555X
:
220 case V4L2_PIX_FMT_XRGB555X
:
221 case V4L2_PIX_FMT_ARGB555X
:
222 case V4L2_PIX_FMT_BGR666
:
223 case V4L2_PIX_FMT_RGB24
:
224 case V4L2_PIX_FMT_BGR24
:
225 case V4L2_PIX_FMT_RGB32
:
226 case V4L2_PIX_FMT_BGR32
:
227 case V4L2_PIX_FMT_XRGB32
:
228 case V4L2_PIX_FMT_XBGR32
:
229 case V4L2_PIX_FMT_ARGB32
:
230 case V4L2_PIX_FMT_ABGR32
:
231 tpg
->color_enc
= TGP_COLOR_ENC_RGB
;
233 case V4L2_PIX_FMT_GREY
:
234 case V4L2_PIX_FMT_Y10
:
235 case V4L2_PIX_FMT_Y12
:
236 case V4L2_PIX_FMT_Y16
:
237 case V4L2_PIX_FMT_Y16_BE
:
238 tpg
->color_enc
= TGP_COLOR_ENC_LUMA
;
240 case V4L2_PIX_FMT_YUV444
:
241 case V4L2_PIX_FMT_YUV555
:
242 case V4L2_PIX_FMT_YUV565
:
243 case V4L2_PIX_FMT_YUV32
:
244 tpg
->color_enc
= TGP_COLOR_ENC_YCBCR
;
246 case V4L2_PIX_FMT_YUV420M
:
247 case V4L2_PIX_FMT_YVU420M
:
250 case V4L2_PIX_FMT_YUV420
:
251 case V4L2_PIX_FMT_YVU420
:
252 tpg
->vdownsampling
[1] = 2;
253 tpg
->vdownsampling
[2] = 2;
254 tpg
->hdownsampling
[1] = 2;
255 tpg
->hdownsampling
[2] = 2;
257 tpg
->color_enc
= TGP_COLOR_ENC_YCBCR
;
259 case V4L2_PIX_FMT_YUV422M
:
260 case V4L2_PIX_FMT_YVU422M
:
263 case V4L2_PIX_FMT_YUV422P
:
264 tpg
->vdownsampling
[1] = 1;
265 tpg
->vdownsampling
[2] = 1;
266 tpg
->hdownsampling
[1] = 2;
267 tpg
->hdownsampling
[2] = 2;
269 tpg
->color_enc
= TGP_COLOR_ENC_YCBCR
;
271 case V4L2_PIX_FMT_NV16M
:
272 case V4L2_PIX_FMT_NV61M
:
275 case V4L2_PIX_FMT_NV16
:
276 case V4L2_PIX_FMT_NV61
:
277 tpg
->vdownsampling
[1] = 1;
278 tpg
->hdownsampling
[1] = 1;
281 tpg
->color_enc
= TGP_COLOR_ENC_YCBCR
;
283 case V4L2_PIX_FMT_NV12M
:
284 case V4L2_PIX_FMT_NV21M
:
287 case V4L2_PIX_FMT_NV12
:
288 case V4L2_PIX_FMT_NV21
:
289 tpg
->vdownsampling
[1] = 2;
290 tpg
->hdownsampling
[1] = 1;
293 tpg
->color_enc
= TGP_COLOR_ENC_YCBCR
;
295 case V4L2_PIX_FMT_YUV444M
:
296 case V4L2_PIX_FMT_YVU444M
:
299 tpg
->vdownsampling
[1] = 1;
300 tpg
->vdownsampling
[2] = 1;
301 tpg
->hdownsampling
[1] = 1;
302 tpg
->hdownsampling
[2] = 1;
303 tpg
->color_enc
= TGP_COLOR_ENC_YCBCR
;
305 case V4L2_PIX_FMT_NV24
:
306 case V4L2_PIX_FMT_NV42
:
307 tpg
->vdownsampling
[1] = 1;
308 tpg
->hdownsampling
[1] = 1;
310 tpg
->color_enc
= TGP_COLOR_ENC_YCBCR
;
312 case V4L2_PIX_FMT_YUYV
:
313 case V4L2_PIX_FMT_UYVY
:
314 case V4L2_PIX_FMT_YVYU
:
315 case V4L2_PIX_FMT_VYUY
:
317 tpg
->color_enc
= TGP_COLOR_ENC_YCBCR
;
319 case V4L2_PIX_FMT_HSV24
:
320 case V4L2_PIX_FMT_HSV32
:
321 tpg
->color_enc
= TGP_COLOR_ENC_HSV
;
328 case V4L2_PIX_FMT_GREY
:
329 case V4L2_PIX_FMT_RGB332
:
330 tpg
->twopixelsize
[0] = 2;
332 case V4L2_PIX_FMT_RGB565
:
333 case V4L2_PIX_FMT_RGB565X
:
334 case V4L2_PIX_FMT_RGB444
:
335 case V4L2_PIX_FMT_XRGB444
:
336 case V4L2_PIX_FMT_ARGB444
:
337 case V4L2_PIX_FMT_RGB555
:
338 case V4L2_PIX_FMT_XRGB555
:
339 case V4L2_PIX_FMT_ARGB555
:
340 case V4L2_PIX_FMT_RGB555X
:
341 case V4L2_PIX_FMT_XRGB555X
:
342 case V4L2_PIX_FMT_ARGB555X
:
343 case V4L2_PIX_FMT_YUYV
:
344 case V4L2_PIX_FMT_UYVY
:
345 case V4L2_PIX_FMT_YVYU
:
346 case V4L2_PIX_FMT_VYUY
:
347 case V4L2_PIX_FMT_YUV444
:
348 case V4L2_PIX_FMT_YUV555
:
349 case V4L2_PIX_FMT_YUV565
:
350 case V4L2_PIX_FMT_Y10
:
351 case V4L2_PIX_FMT_Y12
:
352 case V4L2_PIX_FMT_Y16
:
353 case V4L2_PIX_FMT_Y16_BE
:
354 tpg
->twopixelsize
[0] = 2 * 2;
356 case V4L2_PIX_FMT_RGB24
:
357 case V4L2_PIX_FMT_BGR24
:
358 case V4L2_PIX_FMT_HSV24
:
359 tpg
->twopixelsize
[0] = 2 * 3;
361 case V4L2_PIX_FMT_BGR666
:
362 case V4L2_PIX_FMT_RGB32
:
363 case V4L2_PIX_FMT_BGR32
:
364 case V4L2_PIX_FMT_XRGB32
:
365 case V4L2_PIX_FMT_XBGR32
:
366 case V4L2_PIX_FMT_ARGB32
:
367 case V4L2_PIX_FMT_ABGR32
:
368 case V4L2_PIX_FMT_YUV32
:
369 case V4L2_PIX_FMT_HSV32
:
370 tpg
->twopixelsize
[0] = 2 * 4;
372 case V4L2_PIX_FMT_NV12
:
373 case V4L2_PIX_FMT_NV21
:
374 case V4L2_PIX_FMT_NV12M
:
375 case V4L2_PIX_FMT_NV21M
:
376 case V4L2_PIX_FMT_NV16
:
377 case V4L2_PIX_FMT_NV61
:
378 case V4L2_PIX_FMT_NV16M
:
379 case V4L2_PIX_FMT_NV61M
:
380 case V4L2_PIX_FMT_SBGGR8
:
381 case V4L2_PIX_FMT_SGBRG8
:
382 case V4L2_PIX_FMT_SGRBG8
:
383 case V4L2_PIX_FMT_SRGGB8
:
384 tpg
->twopixelsize
[0] = 2;
385 tpg
->twopixelsize
[1] = 2;
387 case V4L2_PIX_FMT_SRGGB10
:
388 case V4L2_PIX_FMT_SGRBG10
:
389 case V4L2_PIX_FMT_SGBRG10
:
390 case V4L2_PIX_FMT_SBGGR10
:
391 case V4L2_PIX_FMT_SRGGB12
:
392 case V4L2_PIX_FMT_SGRBG12
:
393 case V4L2_PIX_FMT_SGBRG12
:
394 case V4L2_PIX_FMT_SBGGR12
:
395 tpg
->twopixelsize
[0] = 4;
396 tpg
->twopixelsize
[1] = 4;
398 case V4L2_PIX_FMT_YUV444M
:
399 case V4L2_PIX_FMT_YVU444M
:
400 case V4L2_PIX_FMT_YUV422M
:
401 case V4L2_PIX_FMT_YVU422M
:
402 case V4L2_PIX_FMT_YUV422P
:
403 case V4L2_PIX_FMT_YUV420
:
404 case V4L2_PIX_FMT_YVU420
:
405 case V4L2_PIX_FMT_YUV420M
:
406 case V4L2_PIX_FMT_YVU420M
:
407 tpg
->twopixelsize
[0] = 2;
408 tpg
->twopixelsize
[1] = 2;
409 tpg
->twopixelsize
[2] = 2;
411 case V4L2_PIX_FMT_NV24
:
412 case V4L2_PIX_FMT_NV42
:
413 tpg
->twopixelsize
[0] = 2;
414 tpg
->twopixelsize
[1] = 4;
419 EXPORT_SYMBOL_GPL(tpg_s_fourcc
);
421 void tpg_s_crop_compose(struct tpg_data
*tpg
, const struct v4l2_rect
*crop
,
422 const struct v4l2_rect
*compose
)
425 tpg
->compose
= *compose
;
426 tpg
->scaled_width
= (tpg
->src_width
* tpg
->compose
.width
+
427 tpg
->crop
.width
- 1) / tpg
->crop
.width
;
428 tpg
->scaled_width
&= ~1;
429 if (tpg
->scaled_width
> tpg
->max_line_width
)
430 tpg
->scaled_width
= tpg
->max_line_width
;
431 if (tpg
->scaled_width
< 2)
432 tpg
->scaled_width
= 2;
433 tpg
->recalc_lines
= true;
435 EXPORT_SYMBOL_GPL(tpg_s_crop_compose
);
437 void tpg_reset_source(struct tpg_data
*tpg
, unsigned width
, unsigned height
,
442 tpg
->src_width
= width
;
443 tpg
->src_height
= height
;
445 tpg
->buf_height
= height
;
446 if (V4L2_FIELD_HAS_T_OR_B(field
))
447 tpg
->buf_height
/= 2;
448 tpg
->scaled_width
= width
;
449 tpg
->crop
.top
= tpg
->crop
.left
= 0;
450 tpg
->crop
.width
= width
;
451 tpg
->crop
.height
= height
;
452 tpg
->compose
.top
= tpg
->compose
.left
= 0;
453 tpg
->compose
.width
= width
;
454 tpg
->compose
.height
= tpg
->buf_height
;
455 for (p
= 0; p
< tpg
->planes
; p
++)
456 tpg
->bytesperline
[p
] = (width
* tpg
->twopixelsize
[p
]) /
457 (2 * tpg
->hdownsampling
[p
]);
458 tpg
->recalc_square_border
= true;
460 EXPORT_SYMBOL_GPL(tpg_reset_source
);
462 static enum tpg_color
tpg_get_textbg_color(struct tpg_data
*tpg
)
464 switch (tpg
->pattern
) {
466 return TPG_COLOR_100_WHITE
;
467 case TPG_PAT_CSC_COLORBAR
:
468 return TPG_COLOR_CSC_BLACK
;
470 return TPG_COLOR_100_BLACK
;
474 static enum tpg_color
tpg_get_textfg_color(struct tpg_data
*tpg
)
476 switch (tpg
->pattern
) {
477 case TPG_PAT_75_COLORBAR
:
478 case TPG_PAT_CSC_COLORBAR
:
479 return TPG_COLOR_CSC_WHITE
;
481 return TPG_COLOR_100_BLACK
;
483 return TPG_COLOR_100_WHITE
;
487 static inline int rec709_to_linear(int v
)
489 v
= clamp(v
, 0, 0xff0);
490 return tpg_rec709_to_linear
[v
];
493 static inline int linear_to_rec709(int v
)
495 v
= clamp(v
, 0, 0xff0);
496 return tpg_linear_to_rec709
[v
];
499 static void color_to_hsv(struct tpg_data
*tpg
, int r
, int g
, int b
,
500 int *h
, int *s
, int *v
)
502 int max_rgb
, min_rgb
, diff_rgb
;
512 max_rgb
= max3(r
, g
, b
);
521 min_rgb
= min3(r
, g
, b
);
522 diff_rgb
= max_rgb
- min_rgb
;
523 aux
= 255 * diff_rgb
;
532 third_size
= (tpg
->real_hsv_enc
== V4L2_HSV_ENC_180
) ? 60 : 85;
538 } else if (max_rgb
== g
) {
543 third
= third_size
* 2;
546 aux
*= third_size
/ 2;
552 if (tpg
->real_hsv_enc
== V4L2_HSV_ENC_180
) {
564 static void rgb2ycbcr(const int m
[3][3], int r
, int g
, int b
,
565 int y_offset
, int *y
, int *cb
, int *cr
)
567 *y
= ((m
[0][0] * r
+ m
[0][1] * g
+ m
[0][2] * b
) >> 16) + (y_offset
<< 4);
568 *cb
= ((m
[1][0] * r
+ m
[1][1] * g
+ m
[1][2] * b
) >> 16) + (128 << 4);
569 *cr
= ((m
[2][0] * r
+ m
[2][1] * g
+ m
[2][2] * b
) >> 16) + (128 << 4);
572 static void color_to_ycbcr(struct tpg_data
*tpg
, int r
, int g
, int b
,
573 int *y
, int *cb
, int *cr
)
575 #define COEFF(v, r) ((int)(0.5 + (v) * (r) * 256.0))
577 static const int bt601
[3][3] = {
578 { COEFF(0.299, 219), COEFF(0.587, 219), COEFF(0.114, 219) },
579 { COEFF(-0.1687, 224), COEFF(-0.3313, 224), COEFF(0.5, 224) },
580 { COEFF(0.5, 224), COEFF(-0.4187, 224), COEFF(-0.0813, 224) },
582 static const int bt601_full
[3][3] = {
583 { COEFF(0.299, 255), COEFF(0.587, 255), COEFF(0.114, 255) },
584 { COEFF(-0.1687, 255), COEFF(-0.3313, 255), COEFF(0.5, 255) },
585 { COEFF(0.5, 255), COEFF(-0.4187, 255), COEFF(-0.0813, 255) },
587 static const int rec709
[3][3] = {
588 { COEFF(0.2126, 219), COEFF(0.7152, 219), COEFF(0.0722, 219) },
589 { COEFF(-0.1146, 224), COEFF(-0.3854, 224), COEFF(0.5, 224) },
590 { COEFF(0.5, 224), COEFF(-0.4542, 224), COEFF(-0.0458, 224) },
592 static const int rec709_full
[3][3] = {
593 { COEFF(0.2126, 255), COEFF(0.7152, 255), COEFF(0.0722, 255) },
594 { COEFF(-0.1146, 255), COEFF(-0.3854, 255), COEFF(0.5, 255) },
595 { COEFF(0.5, 255), COEFF(-0.4542, 255), COEFF(-0.0458, 255) },
597 static const int smpte240m
[3][3] = {
598 { COEFF(0.212, 219), COEFF(0.701, 219), COEFF(0.087, 219) },
599 { COEFF(-0.116, 224), COEFF(-0.384, 224), COEFF(0.5, 224) },
600 { COEFF(0.5, 224), COEFF(-0.445, 224), COEFF(-0.055, 224) },
602 static const int smpte240m_full
[3][3] = {
603 { COEFF(0.212, 255), COEFF(0.701, 255), COEFF(0.087, 255) },
604 { COEFF(-0.116, 255), COEFF(-0.384, 255), COEFF(0.5, 255) },
605 { COEFF(0.5, 255), COEFF(-0.445, 255), COEFF(-0.055, 255) },
607 static const int bt2020
[3][3] = {
608 { COEFF(0.2627, 219), COEFF(0.6780, 219), COEFF(0.0593, 219) },
609 { COEFF(-0.1396, 224), COEFF(-0.3604, 224), COEFF(0.5, 224) },
610 { COEFF(0.5, 224), COEFF(-0.4598, 224), COEFF(-0.0402, 224) },
612 static const int bt2020_full
[3][3] = {
613 { COEFF(0.2627, 255), COEFF(0.6780, 255), COEFF(0.0593, 255) },
614 { COEFF(-0.1396, 255), COEFF(-0.3604, 255), COEFF(0.5, 255) },
615 { COEFF(0.5, 255), COEFF(-0.4598, 255), COEFF(-0.0402, 255) },
617 static const int bt2020c
[4] = {
618 COEFF(1.0 / 1.9404, 224), COEFF(1.0 / 1.5816, 224),
619 COEFF(1.0 / 1.7184, 224), COEFF(1.0 / 0.9936, 224),
621 static const int bt2020c_full
[4] = {
622 COEFF(1.0 / 1.9404, 255), COEFF(1.0 / 1.5816, 255),
623 COEFF(1.0 / 1.7184, 255), COEFF(1.0 / 0.9936, 255),
626 bool full
= tpg
->real_quantization
== V4L2_QUANTIZATION_FULL_RANGE
;
627 unsigned y_offset
= full
? 0 : 16;
630 switch (tpg
->real_ycbcr_enc
) {
631 case V4L2_YCBCR_ENC_601
:
632 rgb2ycbcr(full
? bt601_full
: bt601
, r
, g
, b
, y_offset
, y
, cb
, cr
);
634 case V4L2_YCBCR_ENC_XV601
:
635 /* Ignore quantization range, there is only one possible
636 * Y'CbCr encoding. */
637 rgb2ycbcr(bt601
, r
, g
, b
, 16, y
, cb
, cr
);
639 case V4L2_YCBCR_ENC_XV709
:
640 /* Ignore quantization range, there is only one possible
641 * Y'CbCr encoding. */
642 rgb2ycbcr(rec709
, r
, g
, b
, 16, y
, cb
, cr
);
644 case V4L2_YCBCR_ENC_BT2020
:
645 rgb2ycbcr(full
? bt2020_full
: bt2020
, r
, g
, b
, y_offset
, y
, cb
, cr
);
647 case V4L2_YCBCR_ENC_BT2020_CONST_LUM
:
648 lin_y
= (COEFF(0.2627, 255) * rec709_to_linear(r
) +
649 COEFF(0.6780, 255) * rec709_to_linear(g
) +
650 COEFF(0.0593, 255) * rec709_to_linear(b
)) >> 16;
651 yc
= linear_to_rec709(lin_y
);
652 *y
= full
? yc
: (yc
* 219) / 255 + (16 << 4);
654 *cb
= (((b
- yc
) * (full
? bt2020c_full
[0] : bt2020c
[0])) >> 16) + (128 << 4);
656 *cb
= (((b
- yc
) * (full
? bt2020c_full
[1] : bt2020c
[1])) >> 16) + (128 << 4);
658 *cr
= (((r
- yc
) * (full
? bt2020c_full
[2] : bt2020c
[2])) >> 16) + (128 << 4);
660 *cr
= (((r
- yc
) * (full
? bt2020c_full
[3] : bt2020c
[3])) >> 16) + (128 << 4);
662 case V4L2_YCBCR_ENC_SMPTE240M
:
663 rgb2ycbcr(full
? smpte240m_full
: smpte240m
, r
, g
, b
, y_offset
, y
, cb
, cr
);
665 case V4L2_YCBCR_ENC_709
:
667 rgb2ycbcr(full
? rec709_full
: rec709
, r
, g
, b
, y_offset
, y
, cb
, cr
);
672 static void ycbcr2rgb(const int m
[3][3], int y
, int cb
, int cr
,
673 int y_offset
, int *r
, int *g
, int *b
)
678 *r
= m
[0][0] * y
+ m
[0][1] * cb
+ m
[0][2] * cr
;
679 *g
= m
[1][0] * y
+ m
[1][1] * cb
+ m
[1][2] * cr
;
680 *b
= m
[2][0] * y
+ m
[2][1] * cb
+ m
[2][2] * cr
;
681 *r
= clamp(*r
>> 12, 0, 0xff0);
682 *g
= clamp(*g
>> 12, 0, 0xff0);
683 *b
= clamp(*b
>> 12, 0, 0xff0);
686 static void ycbcr_to_color(struct tpg_data
*tpg
, int y
, int cb
, int cr
,
687 int *r
, int *g
, int *b
)
690 #define COEFF(v, r) ((int)(0.5 + (v) * ((255.0 * 255.0 * 16.0) / (r))))
691 static const int bt601
[3][3] = {
692 { COEFF(1, 219), COEFF(0, 224), COEFF(1.4020, 224) },
693 { COEFF(1, 219), COEFF(-0.3441, 224), COEFF(-0.7141, 224) },
694 { COEFF(1, 219), COEFF(1.7720, 224), COEFF(0, 224) },
696 static const int bt601_full
[3][3] = {
697 { COEFF(1, 255), COEFF(0, 255), COEFF(1.4020, 255) },
698 { COEFF(1, 255), COEFF(-0.3441, 255), COEFF(-0.7141, 255) },
699 { COEFF(1, 255), COEFF(1.7720, 255), COEFF(0, 255) },
701 static const int rec709
[3][3] = {
702 { COEFF(1, 219), COEFF(0, 224), COEFF(1.5748, 224) },
703 { COEFF(1, 219), COEFF(-0.1873, 224), COEFF(-0.4681, 224) },
704 { COEFF(1, 219), COEFF(1.8556, 224), COEFF(0, 224) },
706 static const int rec709_full
[3][3] = {
707 { COEFF(1, 255), COEFF(0, 255), COEFF(1.5748, 255) },
708 { COEFF(1, 255), COEFF(-0.1873, 255), COEFF(-0.4681, 255) },
709 { COEFF(1, 255), COEFF(1.8556, 255), COEFF(0, 255) },
711 static const int smpte240m
[3][3] = {
712 { COEFF(1, 219), COEFF(0, 224), COEFF(1.5756, 224) },
713 { COEFF(1, 219), COEFF(-0.2253, 224), COEFF(-0.4767, 224) },
714 { COEFF(1, 219), COEFF(1.8270, 224), COEFF(0, 224) },
716 static const int smpte240m_full
[3][3] = {
717 { COEFF(1, 255), COEFF(0, 255), COEFF(1.5756, 255) },
718 { COEFF(1, 255), COEFF(-0.2253, 255), COEFF(-0.4767, 255) },
719 { COEFF(1, 255), COEFF(1.8270, 255), COEFF(0, 255) },
721 static const int bt2020
[3][3] = {
722 { COEFF(1, 219), COEFF(0, 224), COEFF(1.4746, 224) },
723 { COEFF(1, 219), COEFF(-0.1646, 224), COEFF(-0.5714, 224) },
724 { COEFF(1, 219), COEFF(1.8814, 224), COEFF(0, 224) },
726 static const int bt2020_full
[3][3] = {
727 { COEFF(1, 255), COEFF(0, 255), COEFF(1.4746, 255) },
728 { COEFF(1, 255), COEFF(-0.1646, 255), COEFF(-0.5714, 255) },
729 { COEFF(1, 255), COEFF(1.8814, 255), COEFF(0, 255) },
731 static const int bt2020c
[4] = {
732 COEFF(1.9404, 224), COEFF(1.5816, 224),
733 COEFF(1.7184, 224), COEFF(0.9936, 224),
735 static const int bt2020c_full
[4] = {
736 COEFF(1.9404, 255), COEFF(1.5816, 255),
737 COEFF(1.7184, 255), COEFF(0.9936, 255),
740 bool full
= tpg
->real_quantization
== V4L2_QUANTIZATION_FULL_RANGE
;
741 unsigned y_offset
= full
? 0 : 16;
742 int y_fac
= full
? COEFF(1.0, 255) : COEFF(1.0, 219);
743 int lin_r
, lin_g
, lin_b
, lin_y
;
745 switch (tpg
->real_ycbcr_enc
) {
746 case V4L2_YCBCR_ENC_601
:
747 ycbcr2rgb(full
? bt601_full
: bt601
, y
, cb
, cr
, y_offset
, r
, g
, b
);
749 case V4L2_YCBCR_ENC_XV601
:
750 /* Ignore quantization range, there is only one possible
751 * Y'CbCr encoding. */
752 ycbcr2rgb(bt601
, y
, cb
, cr
, 16, r
, g
, b
);
754 case V4L2_YCBCR_ENC_XV709
:
755 /* Ignore quantization range, there is only one possible
756 * Y'CbCr encoding. */
757 ycbcr2rgb(rec709
, y
, cb
, cr
, 16, r
, g
, b
);
759 case V4L2_YCBCR_ENC_BT2020
:
760 ycbcr2rgb(full
? bt2020_full
: bt2020
, y
, cb
, cr
, y_offset
, r
, g
, b
);
762 case V4L2_YCBCR_ENC_BT2020_CONST_LUM
:
763 y
-= full
? 0 : 16 << 4;
768 *b
= y_fac
* y
+ (full
? bt2020c_full
[0] : bt2020c
[0]) * cb
;
770 *b
= y_fac
* y
+ (full
? bt2020c_full
[1] : bt2020c
[1]) * cb
;
773 *r
= y_fac
* y
+ (full
? bt2020c_full
[2] : bt2020c
[2]) * cr
;
775 *r
= y_fac
* y
+ (full
? bt2020c_full
[3] : bt2020c
[3]) * cr
;
777 lin_r
= rec709_to_linear(*r
);
778 lin_b
= rec709_to_linear(*b
);
779 lin_y
= rec709_to_linear((y
* 255) / (full
? 255 : 219));
781 lin_g
= COEFF(1.0 / 0.6780, 255) * lin_y
-
782 COEFF(0.2627 / 0.6780, 255) * lin_r
-
783 COEFF(0.0593 / 0.6780, 255) * lin_b
;
784 *g
= linear_to_rec709(lin_g
>> 12);
786 case V4L2_YCBCR_ENC_SMPTE240M
:
787 ycbcr2rgb(full
? smpte240m_full
: smpte240m
, y
, cb
, cr
, y_offset
, r
, g
, b
);
789 case V4L2_YCBCR_ENC_709
:
791 ycbcr2rgb(full
? rec709_full
: rec709
, y
, cb
, cr
, y_offset
, r
, g
, b
);
796 /* precalculate color bar values to speed up rendering */
797 static void precalculate_color(struct tpg_data
*tpg
, int k
)
800 int r
= tpg_colors
[col
].r
;
801 int g
= tpg_colors
[col
].g
;
802 int b
= tpg_colors
[col
].b
;
804 bool ycbcr_valid
= false;
806 if (k
== TPG_COLOR_TEXTBG
) {
807 col
= tpg_get_textbg_color(tpg
);
809 r
= tpg_colors
[col
].r
;
810 g
= tpg_colors
[col
].g
;
811 b
= tpg_colors
[col
].b
;
812 } else if (k
== TPG_COLOR_TEXTFG
) {
813 col
= tpg_get_textfg_color(tpg
);
815 r
= tpg_colors
[col
].r
;
816 g
= tpg_colors
[col
].g
;
817 b
= tpg_colors
[col
].b
;
818 } else if (tpg
->pattern
== TPG_PAT_NOISE
) {
819 r
= g
= b
= prandom_u32_max(256);
820 } else if (k
== TPG_COLOR_RANDOM
) {
821 r
= g
= b
= tpg
->qual_offset
+ prandom_u32_max(196);
822 } else if (k
>= TPG_COLOR_RAMP
) {
823 r
= g
= b
= k
- TPG_COLOR_RAMP
;
826 if (tpg
->pattern
== TPG_PAT_CSC_COLORBAR
&& col
<= TPG_COLOR_CSC_BLACK
) {
827 r
= tpg_csc_colors
[tpg
->colorspace
][tpg
->real_xfer_func
][col
].r
;
828 g
= tpg_csc_colors
[tpg
->colorspace
][tpg
->real_xfer_func
][col
].g
;
829 b
= tpg_csc_colors
[tpg
->colorspace
][tpg
->real_xfer_func
][col
].b
;
836 if (tpg
->qual
== TPG_QUAL_GRAY
||
837 tpg
->color_enc
== TGP_COLOR_ENC_LUMA
) {
838 /* Rec. 709 Luma function */
839 /* (0.2126, 0.7152, 0.0722) * (255 * 256) */
840 r
= g
= b
= (13879 * r
+ 46688 * g
+ 4713 * b
) >> 16;
844 * The assumption is that the RGB output is always full range,
845 * so only if the rgb_range overrides the 'real' rgb range do
846 * we need to convert the RGB values.
848 * Remember that r, g and b are still in the 0 - 0xff0 range.
850 if (tpg
->real_rgb_range
== V4L2_DV_RGB_RANGE_LIMITED
&&
851 tpg
->rgb_range
== V4L2_DV_RGB_RANGE_FULL
&&
852 tpg
->color_enc
== TGP_COLOR_ENC_RGB
) {
854 * Convert from full range (which is what r, g and b are)
855 * to limited range (which is the 'real' RGB range), which
856 * is then interpreted as full range.
858 r
= (r
* 219) / 255 + (16 << 4);
859 g
= (g
* 219) / 255 + (16 << 4);
860 b
= (b
* 219) / 255 + (16 << 4);
861 } else if (tpg
->real_rgb_range
!= V4L2_DV_RGB_RANGE_LIMITED
&&
862 tpg
->rgb_range
== V4L2_DV_RGB_RANGE_LIMITED
&&
863 tpg
->color_enc
== TGP_COLOR_ENC_RGB
) {
866 * Clamp r, g and b to the limited range and convert to full
867 * range since that's what we deliver.
869 r
= clamp(r
, 16 << 4, 235 << 4);
870 g
= clamp(g
, 16 << 4, 235 << 4);
871 b
= clamp(b
, 16 << 4, 235 << 4);
872 r
= (r
- (16 << 4)) * 255 / 219;
873 g
= (g
- (16 << 4)) * 255 / 219;
874 b
= (b
- (16 << 4)) * 255 / 219;
877 if ((tpg
->brightness
!= 128 || tpg
->contrast
!= 128 ||
878 tpg
->saturation
!= 128 || tpg
->hue
) &&
879 tpg
->color_enc
!= TGP_COLOR_ENC_LUMA
) {
880 /* Implement these operations */
883 /* First convert to YCbCr */
885 color_to_ycbcr(tpg
, r
, g
, b
, &y
, &cb
, &cr
);
887 y
= (16 << 4) + ((y
- (16 << 4)) * tpg
->contrast
) / 128;
888 y
+= (tpg
->brightness
<< 4) - (128 << 4);
892 tmp_cb
= (cb
* cos(128 + tpg
->hue
)) / 127 + (cr
* sin
[128 + tpg
->hue
]) / 127;
893 tmp_cr
= (cr
* cos(128 + tpg
->hue
)) / 127 - (cb
* sin
[128 + tpg
->hue
]) / 127;
895 cb
= (128 << 4) + (tmp_cb
* tpg
->contrast
* tpg
->saturation
) / (128 * 128);
896 cr
= (128 << 4) + (tmp_cr
* tpg
->contrast
* tpg
->saturation
) / (128 * 128);
897 if (tpg
->color_enc
== TGP_COLOR_ENC_YCBCR
)
900 ycbcr_to_color(tpg
, y
, cb
, cr
, &r
, &g
, &b
);
901 } else if ((tpg
->brightness
!= 128 || tpg
->contrast
!= 128) &&
902 tpg
->color_enc
== TGP_COLOR_ENC_LUMA
) {
903 r
= (16 << 4) + ((r
- (16 << 4)) * tpg
->contrast
) / 128;
904 r
+= (tpg
->brightness
<< 4) - (128 << 4);
907 switch (tpg
->color_enc
) {
908 case TGP_COLOR_ENC_HSV
:
912 color_to_hsv(tpg
, r
, g
, b
, &h
, &s
, &v
);
913 tpg
->colors
[k
][0] = h
;
914 tpg
->colors
[k
][1] = s
;
915 tpg
->colors
[k
][2] = v
;
918 case TGP_COLOR_ENC_YCBCR
:
920 /* Convert to YCbCr */
922 color_to_ycbcr(tpg
, r
, g
, b
, &y
, &cb
, &cr
);
928 * XV601/709 use the header/footer margins to encode R', G'
929 * and B' values outside the range [0-1]. So do not clamp
932 if (tpg
->real_quantization
== V4L2_QUANTIZATION_LIM_RANGE
&&
933 tpg
->real_ycbcr_enc
!= V4L2_YCBCR_ENC_XV601
&&
934 tpg
->real_ycbcr_enc
!= V4L2_YCBCR_ENC_XV709
) {
935 y
= clamp(y
, 16, 235);
936 cb
= clamp(cb
, 16, 240);
937 cr
= clamp(cr
, 16, 240);
939 y
= clamp(y
, 1, 254);
940 cb
= clamp(cb
, 1, 254);
941 cr
= clamp(cr
, 1, 254);
943 switch (tpg
->fourcc
) {
944 case V4L2_PIX_FMT_YUV444
:
949 case V4L2_PIX_FMT_YUV555
:
954 case V4L2_PIX_FMT_YUV565
:
960 tpg
->colors
[k
][0] = y
;
961 tpg
->colors
[k
][1] = cb
;
962 tpg
->colors
[k
][2] = cr
;
965 case TGP_COLOR_ENC_LUMA
:
967 tpg
->colors
[k
][0] = r
>> 4;
970 case TGP_COLOR_ENC_RGB
:
972 if (tpg
->real_quantization
== V4L2_QUANTIZATION_LIM_RANGE
) {
973 r
= (r
* 219) / 255 + (16 << 4);
974 g
= (g
* 219) / 255 + (16 << 4);
975 b
= (b
* 219) / 255 + (16 << 4);
977 switch (tpg
->fourcc
) {
978 case V4L2_PIX_FMT_RGB332
:
983 case V4L2_PIX_FMT_RGB565
:
984 case V4L2_PIX_FMT_RGB565X
:
989 case V4L2_PIX_FMT_RGB444
:
990 case V4L2_PIX_FMT_XRGB444
:
991 case V4L2_PIX_FMT_ARGB444
:
996 case V4L2_PIX_FMT_RGB555
:
997 case V4L2_PIX_FMT_XRGB555
:
998 case V4L2_PIX_FMT_ARGB555
:
999 case V4L2_PIX_FMT_RGB555X
:
1000 case V4L2_PIX_FMT_XRGB555X
:
1001 case V4L2_PIX_FMT_ARGB555X
:
1006 case V4L2_PIX_FMT_BGR666
:
1018 tpg
->colors
[k
][0] = r
;
1019 tpg
->colors
[k
][1] = g
;
1020 tpg
->colors
[k
][2] = b
;
1026 static void tpg_precalculate_colors(struct tpg_data
*tpg
)
1030 for (k
= 0; k
< TPG_COLOR_MAX
; k
++)
1031 precalculate_color(tpg
, k
);
1034 /* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */
1035 static void gen_twopix(struct tpg_data
*tpg
,
1036 u8 buf
[TPG_MAX_PLANES
][8], int color
, bool odd
)
1038 unsigned offset
= odd
* tpg
->twopixelsize
[0] / 2;
1039 u8 alpha
= tpg
->alpha_component
;
1040 u8 r_y_h
, g_u_s
, b_v
;
1042 if (tpg
->alpha_red_only
&& color
!= TPG_COLOR_CSC_RED
&&
1043 color
!= TPG_COLOR_100_RED
&&
1044 color
!= TPG_COLOR_75_RED
)
1046 if (color
== TPG_COLOR_RANDOM
)
1047 precalculate_color(tpg
, color
);
1048 r_y_h
= tpg
->colors
[color
][0]; /* R or precalculated Y, H */
1049 g_u_s
= tpg
->colors
[color
][1]; /* G or precalculated U, V */
1050 b_v
= tpg
->colors
[color
][2]; /* B or precalculated V */
1052 switch (tpg
->fourcc
) {
1053 case V4L2_PIX_FMT_GREY
:
1054 buf
[0][offset
] = r_y_h
;
1056 case V4L2_PIX_FMT_Y10
:
1057 buf
[0][offset
] = (r_y_h
<< 2) & 0xff;
1058 buf
[0][offset
+1] = r_y_h
>> 6;
1060 case V4L2_PIX_FMT_Y12
:
1061 buf
[0][offset
] = (r_y_h
<< 4) & 0xff;
1062 buf
[0][offset
+1] = r_y_h
>> 4;
1064 case V4L2_PIX_FMT_Y16
:
1066 * Ideally both bytes should be set to r_y_h, but then you won't
1067 * be able to detect endian problems. So keep it 0 except for
1068 * the corner case where r_y_h is 0xff so white really will be
1071 buf
[0][offset
] = r_y_h
== 0xff ? r_y_h
: 0;
1072 buf
[0][offset
+1] = r_y_h
;
1074 case V4L2_PIX_FMT_Y16_BE
:
1075 /* See comment for V4L2_PIX_FMT_Y16 above */
1076 buf
[0][offset
] = r_y_h
;
1077 buf
[0][offset
+1] = r_y_h
== 0xff ? r_y_h
: 0;
1079 case V4L2_PIX_FMT_YUV422M
:
1080 case V4L2_PIX_FMT_YUV422P
:
1081 case V4L2_PIX_FMT_YUV420
:
1082 case V4L2_PIX_FMT_YUV420M
:
1083 buf
[0][offset
] = r_y_h
;
1085 buf
[1][0] = (buf
[1][0] + g_u_s
) / 2;
1086 buf
[2][0] = (buf
[2][0] + b_v
) / 2;
1087 buf
[1][1] = buf
[1][0];
1088 buf
[2][1] = buf
[2][0];
1094 case V4L2_PIX_FMT_YVU422M
:
1095 case V4L2_PIX_FMT_YVU420
:
1096 case V4L2_PIX_FMT_YVU420M
:
1097 buf
[0][offset
] = r_y_h
;
1099 buf
[1][0] = (buf
[1][0] + b_v
) / 2;
1100 buf
[2][0] = (buf
[2][0] + g_u_s
) / 2;
1101 buf
[1][1] = buf
[1][0];
1102 buf
[2][1] = buf
[2][0];
1109 case V4L2_PIX_FMT_NV12
:
1110 case V4L2_PIX_FMT_NV12M
:
1111 case V4L2_PIX_FMT_NV16
:
1112 case V4L2_PIX_FMT_NV16M
:
1113 buf
[0][offset
] = r_y_h
;
1115 buf
[1][0] = (buf
[1][0] + g_u_s
) / 2;
1116 buf
[1][1] = (buf
[1][1] + b_v
) / 2;
1122 case V4L2_PIX_FMT_NV21
:
1123 case V4L2_PIX_FMT_NV21M
:
1124 case V4L2_PIX_FMT_NV61
:
1125 case V4L2_PIX_FMT_NV61M
:
1126 buf
[0][offset
] = r_y_h
;
1128 buf
[1][0] = (buf
[1][0] + b_v
) / 2;
1129 buf
[1][1] = (buf
[1][1] + g_u_s
) / 2;
1136 case V4L2_PIX_FMT_YUV444M
:
1137 buf
[0][offset
] = r_y_h
;
1138 buf
[1][offset
] = g_u_s
;
1139 buf
[2][offset
] = b_v
;
1142 case V4L2_PIX_FMT_YVU444M
:
1143 buf
[0][offset
] = r_y_h
;
1144 buf
[1][offset
] = b_v
;
1145 buf
[2][offset
] = g_u_s
;
1148 case V4L2_PIX_FMT_NV24
:
1149 buf
[0][offset
] = r_y_h
;
1150 buf
[1][2 * offset
] = g_u_s
;
1151 buf
[1][(2 * offset
+ 1) % 8] = b_v
;
1154 case V4L2_PIX_FMT_NV42
:
1155 buf
[0][offset
] = r_y_h
;
1156 buf
[1][2 * offset
] = b_v
;
1157 buf
[1][(2 * offset
+ 1) % 8] = g_u_s
;
1160 case V4L2_PIX_FMT_YUYV
:
1161 buf
[0][offset
] = r_y_h
;
1163 buf
[0][1] = (buf
[0][1] + g_u_s
) / 2;
1164 buf
[0][3] = (buf
[0][3] + b_v
) / 2;
1170 case V4L2_PIX_FMT_UYVY
:
1171 buf
[0][offset
+ 1] = r_y_h
;
1173 buf
[0][0] = (buf
[0][0] + g_u_s
) / 2;
1174 buf
[0][2] = (buf
[0][2] + b_v
) / 2;
1180 case V4L2_PIX_FMT_YVYU
:
1181 buf
[0][offset
] = r_y_h
;
1183 buf
[0][1] = (buf
[0][1] + b_v
) / 2;
1184 buf
[0][3] = (buf
[0][3] + g_u_s
) / 2;
1190 case V4L2_PIX_FMT_VYUY
:
1191 buf
[0][offset
+ 1] = r_y_h
;
1193 buf
[0][0] = (buf
[0][0] + b_v
) / 2;
1194 buf
[0][2] = (buf
[0][2] + g_u_s
) / 2;
1200 case V4L2_PIX_FMT_RGB332
:
1201 buf
[0][offset
] = (r_y_h
<< 5) | (g_u_s
<< 2) | b_v
;
1203 case V4L2_PIX_FMT_YUV565
:
1204 case V4L2_PIX_FMT_RGB565
:
1205 buf
[0][offset
] = (g_u_s
<< 5) | b_v
;
1206 buf
[0][offset
+ 1] = (r_y_h
<< 3) | (g_u_s
>> 3);
1208 case V4L2_PIX_FMT_RGB565X
:
1209 buf
[0][offset
] = (r_y_h
<< 3) | (g_u_s
>> 3);
1210 buf
[0][offset
+ 1] = (g_u_s
<< 5) | b_v
;
1212 case V4L2_PIX_FMT_RGB444
:
1213 case V4L2_PIX_FMT_XRGB444
:
1216 case V4L2_PIX_FMT_YUV444
:
1217 case V4L2_PIX_FMT_ARGB444
:
1218 buf
[0][offset
] = (g_u_s
<< 4) | b_v
;
1219 buf
[0][offset
+ 1] = (alpha
& 0xf0) | r_y_h
;
1221 case V4L2_PIX_FMT_RGB555
:
1222 case V4L2_PIX_FMT_XRGB555
:
1225 case V4L2_PIX_FMT_YUV555
:
1226 case V4L2_PIX_FMT_ARGB555
:
1227 buf
[0][offset
] = (g_u_s
<< 5) | b_v
;
1228 buf
[0][offset
+ 1] = (alpha
& 0x80) | (r_y_h
<< 2)
1231 case V4L2_PIX_FMT_RGB555X
:
1232 case V4L2_PIX_FMT_XRGB555X
:
1235 case V4L2_PIX_FMT_ARGB555X
:
1236 buf
[0][offset
] = (alpha
& 0x80) | (r_y_h
<< 2) | (g_u_s
>> 3);
1237 buf
[0][offset
+ 1] = (g_u_s
<< 5) | b_v
;
1239 case V4L2_PIX_FMT_RGB24
:
1240 case V4L2_PIX_FMT_HSV24
:
1241 buf
[0][offset
] = r_y_h
;
1242 buf
[0][offset
+ 1] = g_u_s
;
1243 buf
[0][offset
+ 2] = b_v
;
1245 case V4L2_PIX_FMT_BGR24
:
1246 buf
[0][offset
] = b_v
;
1247 buf
[0][offset
+ 1] = g_u_s
;
1248 buf
[0][offset
+ 2] = r_y_h
;
1250 case V4L2_PIX_FMT_BGR666
:
1251 buf
[0][offset
] = (b_v
<< 2) | (g_u_s
>> 4);
1252 buf
[0][offset
+ 1] = (g_u_s
<< 4) | (r_y_h
>> 2);
1253 buf
[0][offset
+ 2] = r_y_h
<< 6;
1254 buf
[0][offset
+ 3] = 0;
1256 case V4L2_PIX_FMT_RGB32
:
1257 case V4L2_PIX_FMT_XRGB32
:
1258 case V4L2_PIX_FMT_HSV32
:
1261 case V4L2_PIX_FMT_YUV32
:
1262 case V4L2_PIX_FMT_ARGB32
:
1263 buf
[0][offset
] = alpha
;
1264 buf
[0][offset
+ 1] = r_y_h
;
1265 buf
[0][offset
+ 2] = g_u_s
;
1266 buf
[0][offset
+ 3] = b_v
;
1268 case V4L2_PIX_FMT_BGR32
:
1269 case V4L2_PIX_FMT_XBGR32
:
1272 case V4L2_PIX_FMT_ABGR32
:
1273 buf
[0][offset
] = b_v
;
1274 buf
[0][offset
+ 1] = g_u_s
;
1275 buf
[0][offset
+ 2] = r_y_h
;
1276 buf
[0][offset
+ 3] = alpha
;
1278 case V4L2_PIX_FMT_SBGGR8
:
1279 buf
[0][offset
] = odd
? g_u_s
: b_v
;
1280 buf
[1][offset
] = odd
? r_y_h
: g_u_s
;
1282 case V4L2_PIX_FMT_SGBRG8
:
1283 buf
[0][offset
] = odd
? b_v
: g_u_s
;
1284 buf
[1][offset
] = odd
? g_u_s
: r_y_h
;
1286 case V4L2_PIX_FMT_SGRBG8
:
1287 buf
[0][offset
] = odd
? r_y_h
: g_u_s
;
1288 buf
[1][offset
] = odd
? g_u_s
: b_v
;
1290 case V4L2_PIX_FMT_SRGGB8
:
1291 buf
[0][offset
] = odd
? g_u_s
: r_y_h
;
1292 buf
[1][offset
] = odd
? b_v
: g_u_s
;
1294 case V4L2_PIX_FMT_SBGGR10
:
1295 buf
[0][offset
] = odd
? g_u_s
<< 2 : b_v
<< 2;
1296 buf
[0][offset
+ 1] = odd
? g_u_s
>> 6 : b_v
>> 6;
1297 buf
[1][offset
] = odd
? r_y_h
<< 2 : g_u_s
<< 2;
1298 buf
[1][offset
+ 1] = odd
? r_y_h
>> 6 : g_u_s
>> 6;
1299 buf
[0][offset
] |= (buf
[0][offset
] >> 2) & 3;
1300 buf
[1][offset
] |= (buf
[1][offset
] >> 2) & 3;
1302 case V4L2_PIX_FMT_SGBRG10
:
1303 buf
[0][offset
] = odd
? b_v
<< 2 : g_u_s
<< 2;
1304 buf
[0][offset
+ 1] = odd
? b_v
>> 6 : g_u_s
>> 6;
1305 buf
[1][offset
] = odd
? g_u_s
<< 2 : r_y_h
<< 2;
1306 buf
[1][offset
+ 1] = odd
? g_u_s
>> 6 : r_y_h
>> 6;
1307 buf
[0][offset
] |= (buf
[0][offset
] >> 2) & 3;
1308 buf
[1][offset
] |= (buf
[1][offset
] >> 2) & 3;
1310 case V4L2_PIX_FMT_SGRBG10
:
1311 buf
[0][offset
] = odd
? r_y_h
<< 2 : g_u_s
<< 2;
1312 buf
[0][offset
+ 1] = odd
? r_y_h
>> 6 : g_u_s
>> 6;
1313 buf
[1][offset
] = odd
? g_u_s
<< 2 : b_v
<< 2;
1314 buf
[1][offset
+ 1] = odd
? g_u_s
>> 6 : b_v
>> 6;
1315 buf
[0][offset
] |= (buf
[0][offset
] >> 2) & 3;
1316 buf
[1][offset
] |= (buf
[1][offset
] >> 2) & 3;
1318 case V4L2_PIX_FMT_SRGGB10
:
1319 buf
[0][offset
] = odd
? g_u_s
<< 2 : r_y_h
<< 2;
1320 buf
[0][offset
+ 1] = odd
? g_u_s
>> 6 : r_y_h
>> 6;
1321 buf
[1][offset
] = odd
? b_v
<< 2 : g_u_s
<< 2;
1322 buf
[1][offset
+ 1] = odd
? b_v
>> 6 : g_u_s
>> 6;
1323 buf
[0][offset
] |= (buf
[0][offset
] >> 2) & 3;
1324 buf
[1][offset
] |= (buf
[1][offset
] >> 2) & 3;
1326 case V4L2_PIX_FMT_SBGGR12
:
1327 buf
[0][offset
] = odd
? g_u_s
<< 4 : b_v
<< 4;
1328 buf
[0][offset
+ 1] = odd
? g_u_s
>> 4 : b_v
>> 4;
1329 buf
[1][offset
] = odd
? r_y_h
<< 4 : g_u_s
<< 4;
1330 buf
[1][offset
+ 1] = odd
? r_y_h
>> 4 : g_u_s
>> 4;
1331 buf
[0][offset
] |= (buf
[0][offset
] >> 4) & 0xf;
1332 buf
[1][offset
] |= (buf
[1][offset
] >> 4) & 0xf;
1334 case V4L2_PIX_FMT_SGBRG12
:
1335 buf
[0][offset
] = odd
? b_v
<< 4 : g_u_s
<< 4;
1336 buf
[0][offset
+ 1] = odd
? b_v
>> 4 : g_u_s
>> 4;
1337 buf
[1][offset
] = odd
? g_u_s
<< 4 : r_y_h
<< 4;
1338 buf
[1][offset
+ 1] = odd
? g_u_s
>> 4 : r_y_h
>> 4;
1339 buf
[0][offset
] |= (buf
[0][offset
] >> 4) & 0xf;
1340 buf
[1][offset
] |= (buf
[1][offset
] >> 4) & 0xf;
1342 case V4L2_PIX_FMT_SGRBG12
:
1343 buf
[0][offset
] = odd
? r_y_h
<< 4 : g_u_s
<< 4;
1344 buf
[0][offset
+ 1] = odd
? r_y_h
>> 4 : g_u_s
>> 4;
1345 buf
[1][offset
] = odd
? g_u_s
<< 4 : b_v
<< 4;
1346 buf
[1][offset
+ 1] = odd
? g_u_s
>> 4 : b_v
>> 4;
1347 buf
[0][offset
] |= (buf
[0][offset
] >> 4) & 0xf;
1348 buf
[1][offset
] |= (buf
[1][offset
] >> 4) & 0xf;
1350 case V4L2_PIX_FMT_SRGGB12
:
1351 buf
[0][offset
] = odd
? g_u_s
<< 4 : r_y_h
<< 4;
1352 buf
[0][offset
+ 1] = odd
? g_u_s
>> 4 : r_y_h
>> 4;
1353 buf
[1][offset
] = odd
? b_v
<< 4 : g_u_s
<< 4;
1354 buf
[1][offset
+ 1] = odd
? b_v
>> 4 : g_u_s
>> 4;
1355 buf
[0][offset
] |= (buf
[0][offset
] >> 4) & 0xf;
1356 buf
[1][offset
] |= (buf
[1][offset
] >> 4) & 0xf;
1361 unsigned tpg_g_interleaved_plane(const struct tpg_data
*tpg
, unsigned buf_line
)
1363 switch (tpg
->fourcc
) {
1364 case V4L2_PIX_FMT_SBGGR8
:
1365 case V4L2_PIX_FMT_SGBRG8
:
1366 case V4L2_PIX_FMT_SGRBG8
:
1367 case V4L2_PIX_FMT_SRGGB8
:
1368 case V4L2_PIX_FMT_SBGGR10
:
1369 case V4L2_PIX_FMT_SGBRG10
:
1370 case V4L2_PIX_FMT_SGRBG10
:
1371 case V4L2_PIX_FMT_SRGGB10
:
1372 case V4L2_PIX_FMT_SBGGR12
:
1373 case V4L2_PIX_FMT_SGBRG12
:
1374 case V4L2_PIX_FMT_SGRBG12
:
1375 case V4L2_PIX_FMT_SRGGB12
:
1376 return buf_line
& 1;
1381 EXPORT_SYMBOL_GPL(tpg_g_interleaved_plane
);
1383 /* Return how many pattern lines are used by the current pattern. */
1384 static unsigned tpg_get_pat_lines(const struct tpg_data
*tpg
)
1386 switch (tpg
->pattern
) {
1387 case TPG_PAT_CHECKERS_16X16
:
1388 case TPG_PAT_CHECKERS_2X2
:
1389 case TPG_PAT_CHECKERS_1X1
:
1390 case TPG_PAT_COLOR_CHECKERS_2X2
:
1391 case TPG_PAT_COLOR_CHECKERS_1X1
:
1392 case TPG_PAT_ALTERNATING_HLINES
:
1393 case TPG_PAT_CROSS_1_PIXEL
:
1394 case TPG_PAT_CROSS_2_PIXELS
:
1395 case TPG_PAT_CROSS_10_PIXELS
:
1397 case TPG_PAT_100_COLORSQUARES
:
1398 case TPG_PAT_100_HCOLORBAR
:
1405 /* Which pattern line should be used for the given frame line. */
1406 static unsigned tpg_get_pat_line(const struct tpg_data
*tpg
, unsigned line
)
1408 switch (tpg
->pattern
) {
1409 case TPG_PAT_CHECKERS_16X16
:
1410 return (line
>> 4) & 1;
1411 case TPG_PAT_CHECKERS_1X1
:
1412 case TPG_PAT_COLOR_CHECKERS_1X1
:
1413 case TPG_PAT_ALTERNATING_HLINES
:
1415 case TPG_PAT_CHECKERS_2X2
:
1416 case TPG_PAT_COLOR_CHECKERS_2X2
:
1417 return (line
& 2) >> 1;
1418 case TPG_PAT_100_COLORSQUARES
:
1419 case TPG_PAT_100_HCOLORBAR
:
1420 return (line
* 8) / tpg
->src_height
;
1421 case TPG_PAT_CROSS_1_PIXEL
:
1422 return line
== tpg
->src_height
/ 2;
1423 case TPG_PAT_CROSS_2_PIXELS
:
1424 return (line
+ 1) / 2 == tpg
->src_height
/ 4;
1425 case TPG_PAT_CROSS_10_PIXELS
:
1426 return (line
+ 10) / 20 == tpg
->src_height
/ 40;
1433 * Which color should be used for the given pattern line and X coordinate.
1434 * Note: x is in the range 0 to 2 * tpg->src_width.
1436 static enum tpg_color
tpg_get_color(const struct tpg_data
*tpg
,
1437 unsigned pat_line
, unsigned x
)
1439 /* Maximum number of bars are TPG_COLOR_MAX - otherwise, the input print code
1440 should be modified */
1441 static const enum tpg_color bars
[3][8] = {
1442 /* Standard ITU-R 75% color bar sequence */
1443 { TPG_COLOR_CSC_WHITE
, TPG_COLOR_75_YELLOW
,
1444 TPG_COLOR_75_CYAN
, TPG_COLOR_75_GREEN
,
1445 TPG_COLOR_75_MAGENTA
, TPG_COLOR_75_RED
,
1446 TPG_COLOR_75_BLUE
, TPG_COLOR_100_BLACK
, },
1447 /* Standard ITU-R 100% color bar sequence */
1448 { TPG_COLOR_100_WHITE
, TPG_COLOR_100_YELLOW
,
1449 TPG_COLOR_100_CYAN
, TPG_COLOR_100_GREEN
,
1450 TPG_COLOR_100_MAGENTA
, TPG_COLOR_100_RED
,
1451 TPG_COLOR_100_BLUE
, TPG_COLOR_100_BLACK
, },
1452 /* Color bar sequence suitable to test CSC */
1453 { TPG_COLOR_CSC_WHITE
, TPG_COLOR_CSC_YELLOW
,
1454 TPG_COLOR_CSC_CYAN
, TPG_COLOR_CSC_GREEN
,
1455 TPG_COLOR_CSC_MAGENTA
, TPG_COLOR_CSC_RED
,
1456 TPG_COLOR_CSC_BLUE
, TPG_COLOR_CSC_BLACK
, },
1459 switch (tpg
->pattern
) {
1460 case TPG_PAT_75_COLORBAR
:
1461 case TPG_PAT_100_COLORBAR
:
1462 case TPG_PAT_CSC_COLORBAR
:
1463 return bars
[tpg
->pattern
][((x
* 8) / tpg
->src_width
) % 8];
1464 case TPG_PAT_100_COLORSQUARES
:
1465 return bars
[1][(pat_line
+ (x
* 8) / tpg
->src_width
) % 8];
1466 case TPG_PAT_100_HCOLORBAR
:
1467 return bars
[1][pat_line
];
1469 return TPG_COLOR_100_BLACK
;
1471 return TPG_COLOR_100_WHITE
;
1473 return TPG_COLOR_100_RED
;
1475 return TPG_COLOR_100_GREEN
;
1477 return TPG_COLOR_100_BLUE
;
1478 case TPG_PAT_CHECKERS_16X16
:
1479 return (((x
>> 4) & 1) ^ (pat_line
& 1)) ?
1480 TPG_COLOR_100_BLACK
: TPG_COLOR_100_WHITE
;
1481 case TPG_PAT_CHECKERS_1X1
:
1482 return ((x
& 1) ^ (pat_line
& 1)) ?
1483 TPG_COLOR_100_WHITE
: TPG_COLOR_100_BLACK
;
1484 case TPG_PAT_COLOR_CHECKERS_1X1
:
1485 return ((x
& 1) ^ (pat_line
& 1)) ?
1486 TPG_COLOR_100_RED
: TPG_COLOR_100_BLUE
;
1487 case TPG_PAT_CHECKERS_2X2
:
1488 return (((x
>> 1) & 1) ^ (pat_line
& 1)) ?
1489 TPG_COLOR_100_WHITE
: TPG_COLOR_100_BLACK
;
1490 case TPG_PAT_COLOR_CHECKERS_2X2
:
1491 return (((x
>> 1) & 1) ^ (pat_line
& 1)) ?
1492 TPG_COLOR_100_RED
: TPG_COLOR_100_BLUE
;
1493 case TPG_PAT_ALTERNATING_HLINES
:
1494 return pat_line
? TPG_COLOR_100_WHITE
: TPG_COLOR_100_BLACK
;
1495 case TPG_PAT_ALTERNATING_VLINES
:
1496 return (x
& 1) ? TPG_COLOR_100_WHITE
: TPG_COLOR_100_BLACK
;
1497 case TPG_PAT_CROSS_1_PIXEL
:
1498 if (pat_line
|| (x
% tpg
->src_width
) == tpg
->src_width
/ 2)
1499 return TPG_COLOR_100_BLACK
;
1500 return TPG_COLOR_100_WHITE
;
1501 case TPG_PAT_CROSS_2_PIXELS
:
1502 if (pat_line
|| ((x
% tpg
->src_width
) + 1) / 2 == tpg
->src_width
/ 4)
1503 return TPG_COLOR_100_BLACK
;
1504 return TPG_COLOR_100_WHITE
;
1505 case TPG_PAT_CROSS_10_PIXELS
:
1506 if (pat_line
|| ((x
% tpg
->src_width
) + 10) / 20 == tpg
->src_width
/ 40)
1507 return TPG_COLOR_100_BLACK
;
1508 return TPG_COLOR_100_WHITE
;
1509 case TPG_PAT_GRAY_RAMP
:
1510 return TPG_COLOR_RAMP
+ ((x
% tpg
->src_width
) * 256) / tpg
->src_width
;
1512 return TPG_COLOR_100_RED
;
1517 * Given the pixel aspect ratio and video aspect ratio calculate the
1518 * coordinates of a centered square and the coordinates of the border of
1519 * the active video area. The coordinates are relative to the source
1522 static void tpg_calculate_square_border(struct tpg_data
*tpg
)
1524 unsigned w
= tpg
->src_width
;
1525 unsigned h
= tpg
->src_height
;
1526 unsigned sq_w
, sq_h
;
1528 sq_w
= (w
* 2 / 5) & ~1;
1529 if (((w
- sq_w
) / 2) & 1)
1532 tpg
->square
.width
= sq_w
;
1533 if (tpg
->vid_aspect
== TPG_VIDEO_ASPECT_16X9_ANAMORPHIC
) {
1534 unsigned ana_sq_w
= (sq_w
/ 4) * 3;
1536 if (((w
- ana_sq_w
) / 2) & 1)
1538 tpg
->square
.width
= ana_sq_w
;
1540 tpg
->square
.left
= (w
- tpg
->square
.width
) / 2;
1541 if (tpg
->pix_aspect
== TPG_PIXEL_ASPECT_NTSC
)
1542 sq_h
= sq_w
* 10 / 11;
1543 else if (tpg
->pix_aspect
== TPG_PIXEL_ASPECT_PAL
)
1544 sq_h
= sq_w
* 59 / 54;
1545 tpg
->square
.height
= sq_h
;
1546 tpg
->square
.top
= (h
- sq_h
) / 2;
1547 tpg
->border
.left
= 0;
1548 tpg
->border
.width
= w
;
1549 tpg
->border
.top
= 0;
1550 tpg
->border
.height
= h
;
1551 switch (tpg
->vid_aspect
) {
1552 case TPG_VIDEO_ASPECT_4X3
:
1553 if (tpg
->pix_aspect
)
1555 if (3 * w
>= 4 * h
) {
1556 tpg
->border
.width
= ((4 * h
) / 3) & ~1;
1557 if (((w
- tpg
->border
.width
) / 2) & ~1)
1558 tpg
->border
.width
-= 2;
1559 tpg
->border
.left
= (w
- tpg
->border
.width
) / 2;
1562 tpg
->border
.height
= ((3 * w
) / 4) & ~1;
1563 tpg
->border
.top
= (h
- tpg
->border
.height
) / 2;
1565 case TPG_VIDEO_ASPECT_14X9_CENTRE
:
1566 if (tpg
->pix_aspect
) {
1567 tpg
->border
.height
= tpg
->pix_aspect
== TPG_PIXEL_ASPECT_NTSC
? 420 : 506;
1568 tpg
->border
.top
= (h
- tpg
->border
.height
) / 2;
1571 if (9 * w
>= 14 * h
) {
1572 tpg
->border
.width
= ((14 * h
) / 9) & ~1;
1573 if (((w
- tpg
->border
.width
) / 2) & ~1)
1574 tpg
->border
.width
-= 2;
1575 tpg
->border
.left
= (w
- tpg
->border
.width
) / 2;
1578 tpg
->border
.height
= ((9 * w
) / 14) & ~1;
1579 tpg
->border
.top
= (h
- tpg
->border
.height
) / 2;
1581 case TPG_VIDEO_ASPECT_16X9_CENTRE
:
1582 if (tpg
->pix_aspect
) {
1583 tpg
->border
.height
= tpg
->pix_aspect
== TPG_PIXEL_ASPECT_NTSC
? 368 : 442;
1584 tpg
->border
.top
= (h
- tpg
->border
.height
) / 2;
1587 if (9 * w
>= 16 * h
) {
1588 tpg
->border
.width
= ((16 * h
) / 9) & ~1;
1589 if (((w
- tpg
->border
.width
) / 2) & ~1)
1590 tpg
->border
.width
-= 2;
1591 tpg
->border
.left
= (w
- tpg
->border
.width
) / 2;
1594 tpg
->border
.height
= ((9 * w
) / 16) & ~1;
1595 tpg
->border
.top
= (h
- tpg
->border
.height
) / 2;
1602 static void tpg_precalculate_line(struct tpg_data
*tpg
)
1604 enum tpg_color contrast
;
1605 u8 pix
[TPG_MAX_PLANES
][8];
1610 switch (tpg
->pattern
) {
1612 contrast
= TPG_COLOR_100_RED
;
1614 case TPG_PAT_CSC_COLORBAR
:
1615 contrast
= TPG_COLOR_CSC_GREEN
;
1618 contrast
= TPG_COLOR_100_GREEN
;
1622 for (pat
= 0; pat
< tpg_get_pat_lines(tpg
); pat
++) {
1623 /* Coarse scaling with Bresenham */
1624 unsigned int_part
= tpg
->src_width
/ tpg
->scaled_width
;
1625 unsigned fract_part
= tpg
->src_width
% tpg
->scaled_width
;
1629 for (x
= 0; x
< tpg
->scaled_width
* 2; x
+= 2) {
1630 unsigned real_x
= src_x
;
1631 enum tpg_color color1
, color2
;
1633 real_x
= tpg
->hflip
? tpg
->src_width
* 2 - real_x
- 2 : real_x
;
1634 color1
= tpg_get_color(tpg
, pat
, real_x
);
1637 error
+= fract_part
;
1638 if (error
>= tpg
->scaled_width
) {
1639 error
-= tpg
->scaled_width
;
1644 real_x
= tpg
->hflip
? tpg
->src_width
* 2 - real_x
- 2 : real_x
;
1645 color2
= tpg_get_color(tpg
, pat
, real_x
);
1648 error
+= fract_part
;
1649 if (error
>= tpg
->scaled_width
) {
1650 error
-= tpg
->scaled_width
;
1654 gen_twopix(tpg
, pix
, tpg
->hflip
? color2
: color1
, 0);
1655 gen_twopix(tpg
, pix
, tpg
->hflip
? color1
: color2
, 1);
1656 for (p
= 0; p
< tpg
->planes
; p
++) {
1657 unsigned twopixsize
= tpg
->twopixelsize
[p
];
1658 unsigned hdiv
= tpg
->hdownsampling
[p
];
1659 u8
*pos
= tpg
->lines
[pat
][p
] + tpg_hdiv(tpg
, p
, x
);
1661 memcpy(pos
, pix
[p
], twopixsize
/ hdiv
);
1666 if (tpg
->vdownsampling
[tpg
->planes
- 1] > 1) {
1667 unsigned pat_lines
= tpg_get_pat_lines(tpg
);
1669 for (pat
= 0; pat
< pat_lines
; pat
++) {
1670 unsigned next_pat
= (pat
+ 1) % pat_lines
;
1672 for (p
= 1; p
< tpg
->planes
; p
++) {
1673 unsigned w
= tpg_hdiv(tpg
, p
, tpg
->scaled_width
* 2);
1674 u8
*pos1
= tpg
->lines
[pat
][p
];
1675 u8
*pos2
= tpg
->lines
[next_pat
][p
];
1676 u8
*dest
= tpg
->downsampled_lines
[pat
][p
];
1678 for (x
= 0; x
< w
; x
++, pos1
++, pos2
++, dest
++)
1679 *dest
= ((u16
)*pos1
+ (u16
)*pos2
) / 2;
1684 gen_twopix(tpg
, pix
, contrast
, 0);
1685 gen_twopix(tpg
, pix
, contrast
, 1);
1686 for (p
= 0; p
< tpg
->planes
; p
++) {
1687 unsigned twopixsize
= tpg
->twopixelsize
[p
];
1688 u8
*pos
= tpg
->contrast_line
[p
];
1690 for (x
= 0; x
< tpg
->scaled_width
; x
+= 2, pos
+= twopixsize
)
1691 memcpy(pos
, pix
[p
], twopixsize
);
1694 gen_twopix(tpg
, pix
, TPG_COLOR_100_BLACK
, 0);
1695 gen_twopix(tpg
, pix
, TPG_COLOR_100_BLACK
, 1);
1696 for (p
= 0; p
< tpg
->planes
; p
++) {
1697 unsigned twopixsize
= tpg
->twopixelsize
[p
];
1698 u8
*pos
= tpg
->black_line
[p
];
1700 for (x
= 0; x
< tpg
->scaled_width
; x
+= 2, pos
+= twopixsize
)
1701 memcpy(pos
, pix
[p
], twopixsize
);
1704 for (x
= 0; x
< tpg
->scaled_width
* 2; x
+= 2) {
1705 gen_twopix(tpg
, pix
, TPG_COLOR_RANDOM
, 0);
1706 gen_twopix(tpg
, pix
, TPG_COLOR_RANDOM
, 1);
1707 for (p
= 0; p
< tpg
->planes
; p
++) {
1708 unsigned twopixsize
= tpg
->twopixelsize
[p
];
1709 u8
*pos
= tpg
->random_line
[p
] + x
* twopixsize
/ 2;
1711 memcpy(pos
, pix
[p
], twopixsize
);
1715 gen_twopix(tpg
, tpg
->textbg
, TPG_COLOR_TEXTBG
, 0);
1716 gen_twopix(tpg
, tpg
->textbg
, TPG_COLOR_TEXTBG
, 1);
1717 gen_twopix(tpg
, tpg
->textfg
, TPG_COLOR_TEXTFG
, 0);
1718 gen_twopix(tpg
, tpg
->textfg
, TPG_COLOR_TEXTFG
, 1);
1721 /* need this to do rgb24 rendering */
1722 typedef struct { u16 __
; u8 _
; } __packed x24
;
1724 #define PRINTSTR(PIXTYPE) do { \
1725 unsigned vdiv = tpg->vdownsampling[p]; \
1726 unsigned hdiv = tpg->hdownsampling[p]; \
1730 memcpy(&fg, tpg->textfg[p], sizeof(PIXTYPE)); \
1731 memcpy(&bg, tpg->textbg[p], sizeof(PIXTYPE)); \
1733 for (line = first; line < 16; line += vdiv * step) { \
1734 int l = tpg->vflip ? 15 - line : line; \
1735 PIXTYPE *pos = (PIXTYPE *)(basep[p][(line / vdiv) & 1] + \
1736 ((y * step + l) / (vdiv * div)) * tpg->bytesperline[p] + \
1737 (x / hdiv) * sizeof(PIXTYPE)); \
1740 for (s = 0; s < len; s++) { \
1741 u8 chr = font8x16[(u8)text[s] * 16 + line]; \
1743 if (hdiv == 2 && tpg->hflip) { \
1744 pos[3] = (chr & (0x01 << 6) ? fg : bg); \
1745 pos[2] = (chr & (0x01 << 4) ? fg : bg); \
1746 pos[1] = (chr & (0x01 << 2) ? fg : bg); \
1747 pos[0] = (chr & (0x01 << 0) ? fg : bg); \
1748 } else if (hdiv == 2) { \
1749 pos[0] = (chr & (0x01 << 7) ? fg : bg); \
1750 pos[1] = (chr & (0x01 << 5) ? fg : bg); \
1751 pos[2] = (chr & (0x01 << 3) ? fg : bg); \
1752 pos[3] = (chr & (0x01 << 1) ? fg : bg); \
1753 } else if (tpg->hflip) { \
1754 pos[7] = (chr & (0x01 << 7) ? fg : bg); \
1755 pos[6] = (chr & (0x01 << 6) ? fg : bg); \
1756 pos[5] = (chr & (0x01 << 5) ? fg : bg); \
1757 pos[4] = (chr & (0x01 << 4) ? fg : bg); \
1758 pos[3] = (chr & (0x01 << 3) ? fg : bg); \
1759 pos[2] = (chr & (0x01 << 2) ? fg : bg); \
1760 pos[1] = (chr & (0x01 << 1) ? fg : bg); \
1761 pos[0] = (chr & (0x01 << 0) ? fg : bg); \
1763 pos[0] = (chr & (0x01 << 7) ? fg : bg); \
1764 pos[1] = (chr & (0x01 << 6) ? fg : bg); \
1765 pos[2] = (chr & (0x01 << 5) ? fg : bg); \
1766 pos[3] = (chr & (0x01 << 4) ? fg : bg); \
1767 pos[4] = (chr & (0x01 << 3) ? fg : bg); \
1768 pos[5] = (chr & (0x01 << 2) ? fg : bg); \
1769 pos[6] = (chr & (0x01 << 1) ? fg : bg); \
1770 pos[7] = (chr & (0x01 << 0) ? fg : bg); \
1773 pos += (tpg->hflip ? -8 : 8) / (int)hdiv; \
1778 static noinline
void tpg_print_str_2(const struct tpg_data
*tpg
, u8
*basep
[TPG_MAX_PLANES
][2],
1779 unsigned p
, unsigned first
, unsigned div
, unsigned step
,
1780 int y
, int x
, char *text
, unsigned len
)
1785 static noinline
void tpg_print_str_4(const struct tpg_data
*tpg
, u8
*basep
[TPG_MAX_PLANES
][2],
1786 unsigned p
, unsigned first
, unsigned div
, unsigned step
,
1787 int y
, int x
, char *text
, unsigned len
)
1792 static noinline
void tpg_print_str_6(const struct tpg_data
*tpg
, u8
*basep
[TPG_MAX_PLANES
][2],
1793 unsigned p
, unsigned first
, unsigned div
, unsigned step
,
1794 int y
, int x
, char *text
, unsigned len
)
1799 static noinline
void tpg_print_str_8(const struct tpg_data
*tpg
, u8
*basep
[TPG_MAX_PLANES
][2],
1800 unsigned p
, unsigned first
, unsigned div
, unsigned step
,
1801 int y
, int x
, char *text
, unsigned len
)
1806 void tpg_gen_text(const struct tpg_data
*tpg
, u8
*basep
[TPG_MAX_PLANES
][2],
1807 int y
, int x
, char *text
)
1809 unsigned step
= V4L2_FIELD_HAS_T_OR_B(tpg
->field
) ? 2 : 1;
1810 unsigned div
= step
;
1812 unsigned len
= strlen(text
);
1815 if (font8x16
== NULL
|| basep
== NULL
)
1818 /* Checks if it is possible to show string */
1819 if (y
+ 16 >= tpg
->compose
.height
|| x
+ 8 >= tpg
->compose
.width
)
1822 if (len
> (tpg
->compose
.width
- x
) / 8)
1823 len
= (tpg
->compose
.width
- x
) / 8;
1825 y
= tpg
->compose
.height
- y
- 16;
1827 x
= tpg
->compose
.width
- x
- 8;
1828 y
+= tpg
->compose
.top
;
1829 x
+= tpg
->compose
.left
;
1830 if (tpg
->field
== V4L2_FIELD_BOTTOM
)
1832 else if (tpg
->field
== V4L2_FIELD_SEQ_TB
|| tpg
->field
== V4L2_FIELD_SEQ_BT
)
1835 for (p
= 0; p
< tpg
->planes
; p
++) {
1837 switch (tpg
->twopixelsize
[p
]) {
1839 tpg_print_str_2(tpg
, basep
, p
, first
, div
, step
, y
, x
,
1843 tpg_print_str_4(tpg
, basep
, p
, first
, div
, step
, y
, x
,
1847 tpg_print_str_6(tpg
, basep
, p
, first
, div
, step
, y
, x
,
1851 tpg_print_str_8(tpg
, basep
, p
, first
, div
, step
, y
, x
,
1857 EXPORT_SYMBOL_GPL(tpg_gen_text
);
1859 void tpg_update_mv_step(struct tpg_data
*tpg
)
1861 int factor
= tpg
->mv_hor_mode
> TPG_MOVE_NONE
? -1 : 1;
1865 switch (tpg
->mv_hor_mode
) {
1866 case TPG_MOVE_NEG_FAST
:
1867 case TPG_MOVE_POS_FAST
:
1868 tpg
->mv_hor_step
= ((tpg
->src_width
+ 319) / 320) * 4;
1872 tpg
->mv_hor_step
= ((tpg
->src_width
+ 639) / 640) * 4;
1874 case TPG_MOVE_NEG_SLOW
:
1875 case TPG_MOVE_POS_SLOW
:
1876 tpg
->mv_hor_step
= 2;
1879 tpg
->mv_hor_step
= 0;
1883 tpg
->mv_hor_step
= tpg
->src_width
- tpg
->mv_hor_step
;
1885 factor
= tpg
->mv_vert_mode
> TPG_MOVE_NONE
? -1 : 1;
1886 switch (tpg
->mv_vert_mode
) {
1887 case TPG_MOVE_NEG_FAST
:
1888 case TPG_MOVE_POS_FAST
:
1889 tpg
->mv_vert_step
= ((tpg
->src_width
+ 319) / 320) * 4;
1893 tpg
->mv_vert_step
= ((tpg
->src_width
+ 639) / 640) * 4;
1895 case TPG_MOVE_NEG_SLOW
:
1896 case TPG_MOVE_POS_SLOW
:
1897 tpg
->mv_vert_step
= 1;
1900 tpg
->mv_vert_step
= 0;
1904 tpg
->mv_vert_step
= tpg
->src_height
- tpg
->mv_vert_step
;
1906 EXPORT_SYMBOL_GPL(tpg_update_mv_step
);
1908 /* Map the line number relative to the crop rectangle to a frame line number */
1909 static unsigned tpg_calc_frameline(const struct tpg_data
*tpg
, unsigned src_y
,
1913 case V4L2_FIELD_TOP
:
1914 return tpg
->crop
.top
+ src_y
* 2;
1915 case V4L2_FIELD_BOTTOM
:
1916 return tpg
->crop
.top
+ src_y
* 2 + 1;
1918 return src_y
+ tpg
->crop
.top
;
1923 * Map the line number relative to the compose rectangle to a destination
1924 * buffer line number.
1926 static unsigned tpg_calc_buffer_line(const struct tpg_data
*tpg
, unsigned y
,
1929 y
+= tpg
->compose
.top
;
1931 case V4L2_FIELD_SEQ_TB
:
1933 return tpg
->buf_height
/ 2 + y
/ 2;
1935 case V4L2_FIELD_SEQ_BT
:
1938 return tpg
->buf_height
/ 2 + y
/ 2;
1944 static void tpg_recalc(struct tpg_data
*tpg
)
1946 if (tpg
->recalc_colors
) {
1947 tpg
->recalc_colors
= false;
1948 tpg
->recalc_lines
= true;
1949 tpg
->real_xfer_func
= tpg
->xfer_func
;
1950 tpg
->real_ycbcr_enc
= tpg
->ycbcr_enc
;
1951 tpg
->real_hsv_enc
= tpg
->hsv_enc
;
1952 tpg
->real_quantization
= tpg
->quantization
;
1954 if (tpg
->xfer_func
== V4L2_XFER_FUNC_DEFAULT
)
1955 tpg
->real_xfer_func
=
1956 V4L2_MAP_XFER_FUNC_DEFAULT(tpg
->colorspace
);
1958 if (tpg
->ycbcr_enc
== V4L2_YCBCR_ENC_DEFAULT
)
1959 tpg
->real_ycbcr_enc
=
1960 V4L2_MAP_YCBCR_ENC_DEFAULT(tpg
->colorspace
);
1962 if (tpg
->quantization
== V4L2_QUANTIZATION_DEFAULT
)
1963 tpg
->real_quantization
=
1964 V4L2_MAP_QUANTIZATION_DEFAULT(
1965 tpg
->color_enc
!= TGP_COLOR_ENC_YCBCR
,
1966 tpg
->colorspace
, tpg
->real_ycbcr_enc
);
1968 tpg_precalculate_colors(tpg
);
1970 if (tpg
->recalc_square_border
) {
1971 tpg
->recalc_square_border
= false;
1972 tpg_calculate_square_border(tpg
);
1974 if (tpg
->recalc_lines
) {
1975 tpg
->recalc_lines
= false;
1976 tpg_precalculate_line(tpg
);
1980 void tpg_calc_text_basep(struct tpg_data
*tpg
,
1981 u8
*basep
[TPG_MAX_PLANES
][2], unsigned p
, u8
*vbuf
)
1983 unsigned stride
= tpg
->bytesperline
[p
];
1984 unsigned h
= tpg
->buf_height
;
1990 h
/= tpg
->vdownsampling
[p
];
1991 if (tpg
->field
== V4L2_FIELD_SEQ_TB
)
1992 basep
[p
][1] += h
* stride
/ 2;
1993 else if (tpg
->field
== V4L2_FIELD_SEQ_BT
)
1994 basep
[p
][0] += h
* stride
/ 2;
1995 if (p
== 0 && tpg
->interleaved
)
1996 tpg_calc_text_basep(tpg
, basep
, 1, vbuf
);
1998 EXPORT_SYMBOL_GPL(tpg_calc_text_basep
);
2000 static int tpg_pattern_avg(const struct tpg_data
*tpg
,
2001 unsigned pat1
, unsigned pat2
)
2003 unsigned pat_lines
= tpg_get_pat_lines(tpg
);
2005 if (pat1
== (pat2
+ 1) % pat_lines
)
2007 if (pat2
== (pat1
+ 1) % pat_lines
)
2012 static const char *tpg_color_enc_str(enum tgp_color_enc
2015 switch (color_enc
) {
2016 case TGP_COLOR_ENC_HSV
:
2018 case TGP_COLOR_ENC_YCBCR
:
2020 case TGP_COLOR_ENC_LUMA
:
2022 case TGP_COLOR_ENC_RGB
:
2029 void tpg_log_status(struct tpg_data
*tpg
)
2031 pr_info("tpg source WxH: %ux%u (%s)\n",
2032 tpg
->src_width
, tpg
->src_height
,
2033 tpg_color_enc_str(tpg
->color_enc
));
2034 pr_info("tpg field: %u\n", tpg
->field
);
2035 pr_info("tpg crop: %ux%u@%dx%d\n", tpg
->crop
.width
, tpg
->crop
.height
,
2036 tpg
->crop
.left
, tpg
->crop
.top
);
2037 pr_info("tpg compose: %ux%u@%dx%d\n", tpg
->compose
.width
, tpg
->compose
.height
,
2038 tpg
->compose
.left
, tpg
->compose
.top
);
2039 pr_info("tpg colorspace: %d\n", tpg
->colorspace
);
2040 pr_info("tpg transfer function: %d/%d\n", tpg
->xfer_func
, tpg
->real_xfer_func
);
2041 pr_info("tpg Y'CbCr encoding: %d/%d\n", tpg
->ycbcr_enc
, tpg
->real_ycbcr_enc
);
2042 pr_info("tpg HSV encoding: %d/%d\n", tpg
->hsv_enc
, tpg
->real_hsv_enc
);
2043 pr_info("tpg quantization: %d/%d\n", tpg
->quantization
, tpg
->real_quantization
);
2044 pr_info("tpg RGB range: %d/%d\n", tpg
->rgb_range
, tpg
->real_rgb_range
);
2046 EXPORT_SYMBOL_GPL(tpg_log_status
);
2049 * This struct contains common parameters used by both the drawing of the
2050 * test pattern and the drawing of the extras (borders, square, etc.)
2052 struct tpg_draw_params
{
2056 unsigned twopixsize
;
2060 unsigned frame_line
;
2061 unsigned frame_line_next
;
2064 unsigned mv_hor_old
;
2065 unsigned mv_hor_new
;
2066 unsigned mv_vert_old
;
2067 unsigned mv_vert_new
;
2071 unsigned wss_random_offset
;
2073 unsigned left_pillar_width
;
2074 unsigned right_pillar_start
;
2077 static void tpg_fill_params_pattern(const struct tpg_data
*tpg
, unsigned p
,
2078 struct tpg_draw_params
*params
)
2080 params
->mv_hor_old
=
2081 tpg_hscale_div(tpg
, p
, tpg
->mv_hor_count
% tpg
->src_width
);
2082 params
->mv_hor_new
=
2083 tpg_hscale_div(tpg
, p
, (tpg
->mv_hor_count
+ tpg
->mv_hor_step
) %
2085 params
->mv_vert_old
= tpg
->mv_vert_count
% tpg
->src_height
;
2086 params
->mv_vert_new
=
2087 (tpg
->mv_vert_count
+ tpg
->mv_vert_step
) % tpg
->src_height
;
2090 static void tpg_fill_params_extras(const struct tpg_data
*tpg
,
2092 struct tpg_draw_params
*params
)
2094 unsigned left_pillar_width
= 0;
2095 unsigned right_pillar_start
= params
->img_width
;
2097 params
->wss_width
= tpg
->crop
.left
< tpg
->src_width
/ 2 ?
2098 tpg
->src_width
/ 2 - tpg
->crop
.left
: 0;
2099 if (params
->wss_width
> tpg
->crop
.width
)
2100 params
->wss_width
= tpg
->crop
.width
;
2101 params
->wss_width
= tpg_hscale_div(tpg
, p
, params
->wss_width
);
2102 params
->wss_random_offset
=
2103 params
->twopixsize
* prandom_u32_max(tpg
->src_width
/ 2);
2105 if (tpg
->crop
.left
< tpg
->border
.left
) {
2106 left_pillar_width
= tpg
->border
.left
- tpg
->crop
.left
;
2107 if (left_pillar_width
> tpg
->crop
.width
)
2108 left_pillar_width
= tpg
->crop
.width
;
2109 left_pillar_width
= tpg_hscale_div(tpg
, p
, left_pillar_width
);
2111 params
->left_pillar_width
= left_pillar_width
;
2113 if (tpg
->crop
.left
+ tpg
->crop
.width
>
2114 tpg
->border
.left
+ tpg
->border
.width
) {
2115 right_pillar_start
=
2116 tpg
->border
.left
+ tpg
->border
.width
- tpg
->crop
.left
;
2117 right_pillar_start
=
2118 tpg_hscale_div(tpg
, p
, right_pillar_start
);
2119 if (right_pillar_start
> params
->img_width
)
2120 right_pillar_start
= params
->img_width
;
2122 params
->right_pillar_start
= right_pillar_start
;
2124 params
->sav_eav_f
= tpg
->field
==
2125 (params
->is_60hz
? V4L2_FIELD_TOP
: V4L2_FIELD_BOTTOM
);
2128 static void tpg_fill_plane_extras(const struct tpg_data
*tpg
,
2129 const struct tpg_draw_params
*params
,
2130 unsigned p
, unsigned h
, u8
*vbuf
)
2132 unsigned twopixsize
= params
->twopixsize
;
2133 unsigned img_width
= params
->img_width
;
2134 unsigned frame_line
= params
->frame_line
;
2135 const struct v4l2_rect
*sq
= &tpg
->square
;
2136 const struct v4l2_rect
*b
= &tpg
->border
;
2137 const struct v4l2_rect
*c
= &tpg
->crop
;
2139 if (params
->is_tv
&& !params
->is_60hz
&&
2140 frame_line
== 0 && params
->wss_width
) {
2142 * Replace the first half of the top line of a 50 Hz frame
2143 * with random data to simulate a WSS signal.
2145 u8
*wss
= tpg
->random_line
[p
] + params
->wss_random_offset
;
2147 memcpy(vbuf
, wss
, params
->wss_width
);
2150 if (tpg
->show_border
&& frame_line
>= b
->top
&&
2151 frame_line
< b
->top
+ b
->height
) {
2152 unsigned bottom
= b
->top
+ b
->height
- 1;
2153 unsigned left
= params
->left_pillar_width
;
2154 unsigned right
= params
->right_pillar_start
;
2156 if (frame_line
== b
->top
|| frame_line
== b
->top
+ 1 ||
2157 frame_line
== bottom
|| frame_line
== bottom
- 1) {
2158 memcpy(vbuf
+ left
, tpg
->contrast_line
[p
],
2161 if (b
->left
>= c
->left
&&
2162 b
->left
< c
->left
+ c
->width
)
2164 tpg
->contrast_line
[p
], twopixsize
);
2165 if (b
->left
+ b
->width
> c
->left
&&
2166 b
->left
+ b
->width
<= c
->left
+ c
->width
)
2167 memcpy(vbuf
+ right
- twopixsize
,
2168 tpg
->contrast_line
[p
], twopixsize
);
2171 if (tpg
->qual
!= TPG_QUAL_NOISE
&& frame_line
>= b
->top
&&
2172 frame_line
< b
->top
+ b
->height
) {
2173 memcpy(vbuf
, tpg
->black_line
[p
], params
->left_pillar_width
);
2174 memcpy(vbuf
+ params
->right_pillar_start
, tpg
->black_line
[p
],
2175 img_width
- params
->right_pillar_start
);
2177 if (tpg
->show_square
&& frame_line
>= sq
->top
&&
2178 frame_line
< sq
->top
+ sq
->height
&&
2179 sq
->left
< c
->left
+ c
->width
&&
2180 sq
->left
+ sq
->width
>= c
->left
) {
2181 unsigned left
= sq
->left
;
2182 unsigned width
= sq
->width
;
2184 if (c
->left
> left
) {
2185 width
-= c
->left
- left
;
2188 if (c
->left
+ c
->width
< left
+ width
)
2189 width
-= left
+ width
- c
->left
- c
->width
;
2191 left
= tpg_hscale_div(tpg
, p
, left
);
2192 width
= tpg_hscale_div(tpg
, p
, width
);
2193 memcpy(vbuf
+ left
, tpg
->contrast_line
[p
], width
);
2195 if (tpg
->insert_sav
) {
2196 unsigned offset
= tpg_hdiv(tpg
, p
, tpg
->compose
.width
/ 3);
2197 u8
*p
= vbuf
+ offset
;
2198 unsigned vact
= 0, hact
= 0;
2203 p
[3] = 0x80 | (params
->sav_eav_f
<< 6) |
2204 (vact
<< 5) | (hact
<< 4) |
2205 ((hact
^ vact
) << 3) |
2206 ((hact
^ params
->sav_eav_f
) << 2) |
2207 ((params
->sav_eav_f
^ vact
) << 1) |
2208 (hact
^ vact
^ params
->sav_eav_f
);
2210 if (tpg
->insert_eav
) {
2211 unsigned offset
= tpg_hdiv(tpg
, p
, tpg
->compose
.width
* 2 / 3);
2212 u8
*p
= vbuf
+ offset
;
2213 unsigned vact
= 0, hact
= 1;
2218 p
[3] = 0x80 | (params
->sav_eav_f
<< 6) |
2219 (vact
<< 5) | (hact
<< 4) |
2220 ((hact
^ vact
) << 3) |
2221 ((hact
^ params
->sav_eav_f
) << 2) |
2222 ((params
->sav_eav_f
^ vact
) << 1) |
2223 (hact
^ vact
^ params
->sav_eav_f
);
2227 static void tpg_fill_plane_pattern(const struct tpg_data
*tpg
,
2228 const struct tpg_draw_params
*params
,
2229 unsigned p
, unsigned h
, u8
*vbuf
)
2231 unsigned twopixsize
= params
->twopixsize
;
2232 unsigned img_width
= params
->img_width
;
2233 unsigned mv_hor_old
= params
->mv_hor_old
;
2234 unsigned mv_hor_new
= params
->mv_hor_new
;
2235 unsigned mv_vert_old
= params
->mv_vert_old
;
2236 unsigned mv_vert_new
= params
->mv_vert_new
;
2237 unsigned frame_line
= params
->frame_line
;
2238 unsigned frame_line_next
= params
->frame_line_next
;
2239 unsigned line_offset
= tpg_hscale_div(tpg
, p
, tpg
->crop
.left
);
2241 bool fill_blank
= false;
2242 unsigned pat_line_old
;
2243 unsigned pat_line_new
;
2244 u8
*linestart_older
;
2245 u8
*linestart_newer
;
2247 u8
*linestart_bottom
;
2249 even
= !(frame_line
& 1);
2251 if (h
>= params
->hmax
) {
2252 if (params
->hmax
== tpg
->compose
.height
)
2254 if (!tpg
->perc_fill_blank
)
2260 frame_line
= tpg
->src_height
- frame_line
- 1;
2261 frame_line_next
= tpg
->src_height
- frame_line_next
- 1;
2265 linestart_older
= tpg
->contrast_line
[p
];
2266 linestart_newer
= tpg
->contrast_line
[p
];
2267 } else if (tpg
->qual
!= TPG_QUAL_NOISE
&&
2268 (frame_line
< tpg
->border
.top
||
2269 frame_line
>= tpg
->border
.top
+ tpg
->border
.height
)) {
2270 linestart_older
= tpg
->black_line
[p
];
2271 linestart_newer
= tpg
->black_line
[p
];
2272 } else if (tpg
->pattern
== TPG_PAT_NOISE
|| tpg
->qual
== TPG_QUAL_NOISE
) {
2273 linestart_older
= tpg
->random_line
[p
] +
2274 twopixsize
* prandom_u32_max(tpg
->src_width
/ 2);
2275 linestart_newer
= tpg
->random_line
[p
] +
2276 twopixsize
* prandom_u32_max(tpg
->src_width
/ 2);
2278 unsigned frame_line_old
=
2279 (frame_line
+ mv_vert_old
) % tpg
->src_height
;
2280 unsigned frame_line_new
=
2281 (frame_line
+ mv_vert_new
) % tpg
->src_height
;
2282 unsigned pat_line_next_old
;
2283 unsigned pat_line_next_new
;
2285 pat_line_old
= tpg_get_pat_line(tpg
, frame_line_old
);
2286 pat_line_new
= tpg_get_pat_line(tpg
, frame_line_new
);
2287 linestart_older
= tpg
->lines
[pat_line_old
][p
] + mv_hor_old
;
2288 linestart_newer
= tpg
->lines
[pat_line_new
][p
] + mv_hor_new
;
2290 if (tpg
->vdownsampling
[p
] > 1 && frame_line
!= frame_line_next
) {
2294 * Now decide whether we need to use downsampled_lines[].
2295 * That's necessary if the two lines use different patterns.
2297 pat_line_next_old
= tpg_get_pat_line(tpg
,
2298 (frame_line_next
+ mv_vert_old
) % tpg
->src_height
);
2299 pat_line_next_new
= tpg_get_pat_line(tpg
,
2300 (frame_line_next
+ mv_vert_new
) % tpg
->src_height
);
2302 switch (tpg
->field
) {
2303 case V4L2_FIELD_INTERLACED
:
2304 case V4L2_FIELD_INTERLACED_BT
:
2305 case V4L2_FIELD_INTERLACED_TB
:
2306 avg_pat
= tpg_pattern_avg(tpg
, pat_line_old
, pat_line_new
);
2309 linestart_older
= tpg
->downsampled_lines
[avg_pat
][p
] + mv_hor_old
;
2310 linestart_newer
= linestart_older
;
2312 case V4L2_FIELD_NONE
:
2313 case V4L2_FIELD_TOP
:
2314 case V4L2_FIELD_BOTTOM
:
2315 case V4L2_FIELD_SEQ_BT
:
2316 case V4L2_FIELD_SEQ_TB
:
2317 avg_pat
= tpg_pattern_avg(tpg
, pat_line_old
, pat_line_next_old
);
2319 linestart_older
= tpg
->downsampled_lines
[avg_pat
][p
] +
2321 avg_pat
= tpg_pattern_avg(tpg
, pat_line_new
, pat_line_next_new
);
2323 linestart_newer
= tpg
->downsampled_lines
[avg_pat
][p
] +
2328 linestart_older
+= line_offset
;
2329 linestart_newer
+= line_offset
;
2331 if (tpg
->field_alternate
) {
2332 linestart_top
= linestart_bottom
= linestart_older
;
2333 } else if (params
->is_60hz
) {
2334 linestart_top
= linestart_newer
;
2335 linestart_bottom
= linestart_older
;
2337 linestart_top
= linestart_older
;
2338 linestart_bottom
= linestart_newer
;
2341 switch (tpg
->field
) {
2342 case V4L2_FIELD_INTERLACED
:
2343 case V4L2_FIELD_INTERLACED_TB
:
2344 case V4L2_FIELD_SEQ_TB
:
2345 case V4L2_FIELD_SEQ_BT
:
2347 memcpy(vbuf
, linestart_top
, img_width
);
2349 memcpy(vbuf
, linestart_bottom
, img_width
);
2351 case V4L2_FIELD_INTERLACED_BT
:
2353 memcpy(vbuf
, linestart_bottom
, img_width
);
2355 memcpy(vbuf
, linestart_top
, img_width
);
2357 case V4L2_FIELD_TOP
:
2358 memcpy(vbuf
, linestart_top
, img_width
);
2360 case V4L2_FIELD_BOTTOM
:
2361 memcpy(vbuf
, linestart_bottom
, img_width
);
2363 case V4L2_FIELD_NONE
:
2365 memcpy(vbuf
, linestart_older
, img_width
);
2370 void tpg_fill_plane_buffer(struct tpg_data
*tpg
, v4l2_std_id std
,
2371 unsigned p
, u8
*vbuf
)
2373 struct tpg_draw_params params
;
2374 unsigned factor
= V4L2_FIELD_HAS_T_OR_B(tpg
->field
) ? 2 : 1;
2376 /* Coarse scaling with Bresenham */
2377 unsigned int_part
= (tpg
->crop
.height
/ factor
) / tpg
->compose
.height
;
2378 unsigned fract_part
= (tpg
->crop
.height
/ factor
) % tpg
->compose
.height
;
2386 params
.is_60hz
= std
& V4L2_STD_525_60
;
2387 params
.twopixsize
= tpg
->twopixelsize
[p
];
2388 params
.img_width
= tpg_hdiv(tpg
, p
, tpg
->compose
.width
);
2389 params
.stride
= tpg
->bytesperline
[p
];
2390 params
.hmax
= (tpg
->compose
.height
* tpg
->perc_fill
) / 100;
2392 tpg_fill_params_pattern(tpg
, p
, ¶ms
);
2393 tpg_fill_params_extras(tpg
, p
, ¶ms
);
2395 vbuf
+= tpg_hdiv(tpg
, p
, tpg
->compose
.left
);
2397 for (h
= 0; h
< tpg
->compose
.height
; h
++) {
2400 params
.frame_line
= tpg_calc_frameline(tpg
, src_y
, tpg
->field
);
2401 params
.frame_line_next
= params
.frame_line
;
2402 buf_line
= tpg_calc_buffer_line(tpg
, h
, tpg
->field
);
2404 error
+= fract_part
;
2405 if (error
>= tpg
->compose
.height
) {
2406 error
-= tpg
->compose
.height
;
2411 * For line-interleaved formats determine the 'plane'
2412 * based on the buffer line.
2414 if (tpg_g_interleaved(tpg
))
2415 p
= tpg_g_interleaved_plane(tpg
, buf_line
);
2417 if (tpg
->vdownsampling
[p
] > 1) {
2419 * When doing vertical downsampling the field setting
2420 * matters: for SEQ_BT/TB we downsample each field
2421 * separately (i.e. lines 0+2 are combined, as are
2422 * lines 1+3), for the other field settings we combine
2423 * odd and even lines. Doing that for SEQ_BT/TB would
2426 if (tpg
->field
== V4L2_FIELD_SEQ_BT
||
2427 tpg
->field
== V4L2_FIELD_SEQ_TB
) {
2428 unsigned next_src_y
= src_y
;
2432 next_src_y
+= int_part
;
2433 if (error
+ fract_part
>= tpg
->compose
.height
)
2435 params
.frame_line_next
=
2436 tpg_calc_frameline(tpg
, next_src_y
, tpg
->field
);
2440 params
.frame_line_next
=
2441 tpg_calc_frameline(tpg
, src_y
, tpg
->field
);
2444 buf_line
/= tpg
->vdownsampling
[p
];
2446 tpg_fill_plane_pattern(tpg
, ¶ms
, p
, h
,
2447 vbuf
+ buf_line
* params
.stride
);
2448 tpg_fill_plane_extras(tpg
, ¶ms
, p
, h
,
2449 vbuf
+ buf_line
* params
.stride
);
2452 EXPORT_SYMBOL_GPL(tpg_fill_plane_buffer
);
2454 void tpg_fillbuffer(struct tpg_data
*tpg
, v4l2_std_id std
, unsigned p
, u8
*vbuf
)
2456 unsigned offset
= 0;
2459 if (tpg
->buffers
> 1) {
2460 tpg_fill_plane_buffer(tpg
, std
, p
, vbuf
);
2464 for (i
= 0; i
< tpg_g_planes(tpg
); i
++) {
2465 tpg_fill_plane_buffer(tpg
, std
, i
, vbuf
+ offset
);
2466 offset
+= tpg_calc_plane_size(tpg
, i
);
2469 EXPORT_SYMBOL_GPL(tpg_fillbuffer
);
2471 MODULE_DESCRIPTION("V4L2 Test Pattern Generator");
2472 MODULE_AUTHOR("Hans Verkuil");
2473 MODULE_LICENSE("GPL");