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