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