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