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