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