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