File Index
Files and directories
Sign in
FILE

v4l2-tpg-core.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c C
   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 */
  15const 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};
  40EXPORT_SYMBOL_GPL(tpg_pattern_strings);
  41
  42/* Must remain in sync with enum tpg_aspect */
  43const char * const tpg_aspect_strings[] = {
  44	"Source Width x Height",
  45	"4x3",
  46	"14x9",
  47	"16x9",
  48	"16x9 Anamorphic",
  49	NULL
  50};
  51EXPORT_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 */
  58static 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 */
  81static const u8 *font8x16;
  82
  83void tpg_set_font(const u8 *f)
  84{
  85	font8x16 = f;
  86}
  87EXPORT_SYMBOL_GPL(tpg_set_font);
  88
  89void 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}
 110EXPORT_SYMBOL_GPL(tpg_init);
 111
 112int 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
 163free_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	}
 172free_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}
 184EXPORT_SYMBOL_GPL(tpg_alloc);
 185
 186void 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}
 209EXPORT_SYMBOL_GPL(tpg_free);
 210
 211bool 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}
 505EXPORT_SYMBOL_GPL(tpg_s_fourcc);
 506
 507void 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}
 521EXPORT_SYMBOL_GPL(tpg_s_crop_compose);
 522
 523void 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}
 546EXPORT_SYMBOL_GPL(tpg_reset_source);
 547
 548static 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
 560static 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
 573static inline int rec709_to_linear(int v)
 574{
 575	v = clamp(v, 0, 0xff0);
 576	return tpg_rec709_to_linear[v];
 577}
 578
 579static inline int linear_to_rec709(int v)
 580{
 581	v = clamp(v, 0, 0xff0);
 582	return tpg_linear_to_rec709[v];
 583}
 584
 585static 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
 650static 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
 658static 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
 758static 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
 772static 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 */
 883static 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
1124static 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. */
1133static 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
1545unsigned 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}
1569EXPORT_SYMBOL_GPL(tpg_g_interleaved_plane);
1570
1571/* Return how many pattern lines are used by the current pattern. */
1572static 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. */
1594static 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 */
1624static 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 */
1710static 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
1790static 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 */
1913typedef 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
1969static 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
1976static 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
1983static 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
1990static 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
1997void 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}
2050EXPORT_SYMBOL_GPL(tpg_gen_text);
2051
2052const 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}
2074EXPORT_SYMBOL_GPL(tpg_g_color_order);
2075
2076void 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}
2123EXPORT_SYMBOL_GPL(tpg_update_mv_step);
2124
2125/* Map the line number relative to the crop rectangle to a frame line number */
2126static 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 */
2143static 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
2161static 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
2197void 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}
2215EXPORT_SYMBOL_GPL(tpg_calc_text_basep);
2216
2217static 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
2229static 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
2246void 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: (%d,%d)/%ux%u\n", tpg->crop.left, tpg->crop.top,
2253		tpg->crop.width, tpg->crop.height);
2254	pr_info("tpg compose: (%d,%d)/%ux%u\n", tpg->compose.left, tpg->compose.top,
2255		tpg->compose.width, tpg->compose.height);
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}
2267EXPORT_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 */
2273struct 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
2298static 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
2311static 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
2349static 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
2486static 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
2629void 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}
2711EXPORT_SYMBOL_GPL(tpg_fill_plane_buffer);
2712
2713void 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}
2728EXPORT_SYMBOL_GPL(tpg_fillbuffer);
2729
2730MODULE_DESCRIPTION("V4L2 Test Pattern Generator");
2731MODULE_AUTHOR("Hans Verkuil");
2732MODULE_LICENSE("GPL");
~/ Read-only file preview.