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