1 /* 2 * v4l2-tpg-core.c - Test Pattern Generator 3 * 4 * Note: gen_twopix and tpg_gen_text are based on code from vivi.c. See the 5 * vivi.c source for the copyright information of those functions. 6 * 7 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 8 * 9 * This program is free software; you may redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; version 2 of the License. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 17 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 18 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23 #include <linux/module.h> 24 #include <media/v4l2-tpg.h> 25 26 /* Must remain in sync with enum tpg_pattern */ 27 const char * const tpg_pattern_strings[] = { 28 "75% Colorbar", 29 "100% Colorbar", 30 "CSC Colorbar", 31 "Horizontal 100% Colorbar", 32 "100% Color Squares", 33 "100% Black", 34 "100% White", 35 "100% Red", 36 "100% Green", 37 "100% Blue", 38 "16x16 Checkers", 39 "2x2 Checkers", 40 "1x1 Checkers", 41 "2x2 Red/Green Checkers", 42 "1x1 Red/Green Checkers", 43 "Alternating Hor Lines", 44 "Alternating Vert Lines", 45 "One Pixel Wide Cross", 46 "Two Pixels Wide Cross", 47 "Ten Pixels Wide Cross", 48 "Gray Ramp", 49 "Noise", 50 NULL 51 }; 52 EXPORT_SYMBOL_GPL(tpg_pattern_strings); 53 54 /* Must remain in sync with enum tpg_aspect */ 55 const char * const tpg_aspect_strings[] = { 56 "Source Width x Height", 57 "4x3", 58 "14x9", 59 "16x9", 60 "16x9 Anamorphic", 61 NULL 62 }; 63 EXPORT_SYMBOL_GPL(tpg_aspect_strings); 64 65 /* 66 * Sine table: sin[0] = 127 * sin(-180 degrees) 67 * sin[128] = 127 * sin(0 degrees) 68 * sin[256] = 127 * sin(180 degrees) 69 */ 70 static const s8 sin[257] = { 71 0, -4, -7, -11, -13, -18, -20, -22, -26, -29, -33, -35, -37, -41, -43, -48, 72 -50, -52, -56, -58, -62, -63, -65, -69, -71, -75, -76, -78, -82, -83, -87, -88, 73 -90, -93, -94, -97, -99, -101, -103, -104, -107, -108, -110, -111, -112, -114, -115, -117, 74 -118, -119, -120, -121, -122, -123, -123, -124, -125, -125, -126, -126, -127, -127, -127, -127, 75 -127, -127, -127, -127, -126, -126, -125, -125, -124, -124, -123, -122, -121, -120, -119, -118, 76 -117, -116, -114, -113, -111, -110, -109, -107, -105, -103, -101, -100, -97, -96, -93, -91, 77 -90, -87, -85, -82, -80, -76, -75, -73, -69, -67, -63, -62, -60, -56, -54, -50, 78 -48, -46, -41, -39, -35, -33, -31, -26, -24, -20, -18, -15, -11, -9, -4, -2, 79 0, 2, 4, 9, 11, 15, 18, 20, 24, 26, 31, 33, 35, 39, 41, 46, 80 48, 50, 54, 56, 60, 62, 64, 67, 69, 73, 75, 76, 80, 82, 85, 87, 81 90, 91, 93, 96, 97, 100, 101, 103, 105, 107, 109, 110, 111, 113, 114, 116, 82 117, 118, 119, 120, 121, 122, 123, 124, 124, 125, 125, 126, 126, 127, 127, 127, 83 127, 127, 127, 127, 127, 126, 126, 125, 125, 124, 123, 123, 122, 121, 120, 119, 84 118, 117, 115, 114, 112, 111, 110, 108, 107, 104, 103, 101, 99, 97, 94, 93, 85 90, 88, 87, 83, 82, 78, 76, 75, 71, 69, 65, 64, 62, 58, 56, 52, 86 50, 48, 43, 41, 37, 35, 33, 29, 26, 22, 20, 18, 13, 11, 7, 4, 87 0, 88 }; 89 90 #define cos(idx) sin[((idx) + 64) % sizeof(sin)] 91 92 /* Global font descriptor */ 93 static const u8 *font8x16; 94 95 void tpg_set_font(const u8 *f) 96 { 97 font8x16 = f; 98 } 99 EXPORT_SYMBOL_GPL(tpg_set_font); 100 101 void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h) 102 { 103 memset(tpg, 0, sizeof(*tpg)); 104 tpg->scaled_width = tpg->src_width = w; 105 tpg->src_height = tpg->buf_height = h; 106 tpg->crop.width = tpg->compose.width = w; 107 tpg->crop.height = tpg->compose.height = h; 108 tpg->recalc_colors = true; 109 tpg->recalc_square_border = true; 110 tpg->brightness = 128; 111 tpg->contrast = 128; 112 tpg->saturation = 128; 113 tpg->hue = 0; 114 tpg->mv_hor_mode = TPG_MOVE_NONE; 115 tpg->mv_vert_mode = TPG_MOVE_NONE; 116 tpg->field = V4L2_FIELD_NONE; 117 tpg_s_fourcc(tpg, V4L2_PIX_FMT_RGB24); 118 tpg->colorspace = V4L2_COLORSPACE_SRGB; 119 tpg->perc_fill = 100; 120 tpg->hsv_enc = V4L2_HSV_ENC_180; 121 } 122 EXPORT_SYMBOL_GPL(tpg_init); 123 124 int tpg_alloc(struct tpg_data *tpg, unsigned max_w) 125 { 126 unsigned pat; 127 unsigned plane; 128 129 tpg->max_line_width = max_w; 130 for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++) { 131 for (plane = 0; plane < TPG_MAX_PLANES; plane++) { 132 unsigned pixelsz = plane ? 2 : 4; 133 134 tpg->lines[pat][plane] = vzalloc(max_w * 2 * pixelsz); 135 if (!tpg->lines[pat][plane]) 136 return -ENOMEM; 137 if (plane == 0) 138 continue; 139 tpg->downsampled_lines[pat][plane] = vzalloc(max_w * 2 * pixelsz); 140 if (!tpg->downsampled_lines[pat][plane]) 141 return -ENOMEM; 142 } 143 } 144 for (plane = 0; plane < TPG_MAX_PLANES; plane++) { 145 unsigned pixelsz = plane ? 2 : 4; 146 147 tpg->contrast_line[plane] = vzalloc(max_w * pixelsz); 148 if (!tpg->contrast_line[plane]) 149 return -ENOMEM; 150 tpg->black_line[plane] = vzalloc(max_w * pixelsz); 151 if (!tpg->black_line[plane]) 152 return -ENOMEM; 153 tpg->random_line[plane] = vzalloc(max_w * 2 * pixelsz); 154 if (!tpg->random_line[plane]) 155 return -ENOMEM; 156 } 157 return 0; 158 } 159 EXPORT_SYMBOL_GPL(tpg_alloc); 160 161 void tpg_free(struct tpg_data *tpg) 162 { 163 unsigned pat; 164 unsigned plane; 165 166 for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++) 167 for (plane = 0; plane < TPG_MAX_PLANES; plane++) { 168 vfree(tpg->lines[pat][plane]); 169 tpg->lines[pat][plane] = NULL; 170 if (plane == 0) 171 continue; 172 vfree(tpg->downsampled_lines[pat][plane]); 173 tpg->downsampled_lines[pat][plane] = NULL; 174 } 175 for (plane = 0; plane < TPG_MAX_PLANES; plane++) { 176 vfree(tpg->contrast_line[plane]); 177 vfree(tpg->black_line[plane]); 178 vfree(tpg->random_line[plane]); 179 tpg->contrast_line[plane] = NULL; 180 tpg->black_line[plane] = NULL; 181 tpg->random_line[plane] = NULL; 182 } 183 } 184 EXPORT_SYMBOL_GPL(tpg_free); 185 186 bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) 187 { 188 tpg->fourcc = fourcc; 189 tpg->planes = 1; 190 tpg->buffers = 1; 191 tpg->recalc_colors = true; 192 tpg->interleaved = false; 193 tpg->vdownsampling[0] = 1; 194 tpg->hdownsampling[0] = 1; 195 tpg->hmask[0] = ~0; 196 tpg->hmask[1] = ~0; 197 tpg->hmask[2] = ~0; 198 199 switch (fourcc) { 200 case V4L2_PIX_FMT_SBGGR8: 201 case V4L2_PIX_FMT_SGBRG8: 202 case V4L2_PIX_FMT_SGRBG8: 203 case V4L2_PIX_FMT_SRGGB8: 204 case V4L2_PIX_FMT_SBGGR10: 205 case V4L2_PIX_FMT_SGBRG10: 206 case V4L2_PIX_FMT_SGRBG10: 207 case V4L2_PIX_FMT_SRGGB10: 208 case V4L2_PIX_FMT_SBGGR12: 209 case V4L2_PIX_FMT_SGBRG12: 210 case V4L2_PIX_FMT_SGRBG12: 211 case V4L2_PIX_FMT_SRGGB12: 212 tpg->interleaved = true; 213 tpg->vdownsampling[1] = 1; 214 tpg->hdownsampling[1] = 1; 215 tpg->planes = 2; 216 /* fall through */ 217 case V4L2_PIX_FMT_RGB332: 218 case V4L2_PIX_FMT_RGB565: 219 case V4L2_PIX_FMT_RGB565X: 220 case V4L2_PIX_FMT_RGB444: 221 case V4L2_PIX_FMT_XRGB444: 222 case V4L2_PIX_FMT_ARGB444: 223 case V4L2_PIX_FMT_RGB555: 224 case V4L2_PIX_FMT_XRGB555: 225 case V4L2_PIX_FMT_ARGB555: 226 case V4L2_PIX_FMT_RGB555X: 227 case V4L2_PIX_FMT_XRGB555X: 228 case V4L2_PIX_FMT_ARGB555X: 229 case V4L2_PIX_FMT_BGR666: 230 case V4L2_PIX_FMT_RGB24: 231 case V4L2_PIX_FMT_BGR24: 232 case V4L2_PIX_FMT_RGB32: 233 case V4L2_PIX_FMT_BGR32: 234 case V4L2_PIX_FMT_XRGB32: 235 case V4L2_PIX_FMT_XBGR32: 236 case V4L2_PIX_FMT_ARGB32: 237 case V4L2_PIX_FMT_ABGR32: 238 tpg->color_enc = TGP_COLOR_ENC_RGB; 239 break; 240 case V4L2_PIX_FMT_GREY: 241 case V4L2_PIX_FMT_Y16: 242 case V4L2_PIX_FMT_Y16_BE: 243 tpg->color_enc = TGP_COLOR_ENC_LUMA; 244 break; 245 case V4L2_PIX_FMT_YUV444: 246 case V4L2_PIX_FMT_YUV555: 247 case V4L2_PIX_FMT_YUV565: 248 case V4L2_PIX_FMT_YUV32: 249 tpg->color_enc = TGP_COLOR_ENC_YCBCR; 250 break; 251 case V4L2_PIX_FMT_YUV420M: 252 case V4L2_PIX_FMT_YVU420M: 253 tpg->buffers = 3; 254 /* fall through */ 255 case V4L2_PIX_FMT_YUV420: 256 case V4L2_PIX_FMT_YVU420: 257 tpg->vdownsampling[1] = 2; 258 tpg->vdownsampling[2] = 2; 259 tpg->hdownsampling[1] = 2; 260 tpg->hdownsampling[2] = 2; 261 tpg->planes = 3; 262 tpg->color_enc = TGP_COLOR_ENC_YCBCR; 263 break; 264 case V4L2_PIX_FMT_YUV422M: 265 case V4L2_PIX_FMT_YVU422M: 266 tpg->buffers = 3; 267 /* fall through */ 268 case V4L2_PIX_FMT_YUV422P: 269 tpg->vdownsampling[1] = 1; 270 tpg->vdownsampling[2] = 1; 271 tpg->hdownsampling[1] = 2; 272 tpg->hdownsampling[2] = 2; 273 tpg->planes = 3; 274 tpg->color_enc = TGP_COLOR_ENC_YCBCR; 275 break; 276 case V4L2_PIX_FMT_NV16M: 277 case V4L2_PIX_FMT_NV61M: 278 tpg->buffers = 2; 279 /* fall through */ 280 case V4L2_PIX_FMT_NV16: 281 case V4L2_PIX_FMT_NV61: 282 tpg->vdownsampling[1] = 1; 283 tpg->hdownsampling[1] = 1; 284 tpg->hmask[1] = ~1; 285 tpg->planes = 2; 286 tpg->color_enc = TGP_COLOR_ENC_YCBCR; 287 break; 288 case V4L2_PIX_FMT_NV12M: 289 case V4L2_PIX_FMT_NV21M: 290 tpg->buffers = 2; 291 /* fall through */ 292 case V4L2_PIX_FMT_NV12: 293 case V4L2_PIX_FMT_NV21: 294 tpg->vdownsampling[1] = 2; 295 tpg->hdownsampling[1] = 1; 296 tpg->hmask[1] = ~1; 297 tpg->planes = 2; 298 tpg->color_enc = TGP_COLOR_ENC_YCBCR; 299 break; 300 case V4L2_PIX_FMT_YUV444M: 301 case V4L2_PIX_FMT_YVU444M: 302 tpg->buffers = 3; 303 tpg->planes = 3; 304 tpg->vdownsampling[1] = 1; 305 tpg->vdownsampling[2] = 1; 306 tpg->hdownsampling[1] = 1; 307 tpg->hdownsampling[2] = 1; 308 tpg->color_enc = TGP_COLOR_ENC_YCBCR; 309 break; 310 case V4L2_PIX_FMT_NV24: 311 case V4L2_PIX_FMT_NV42: 312 tpg->vdownsampling[1] = 1; 313 tpg->hdownsampling[1] = 1; 314 tpg->planes = 2; 315 tpg->color_enc = TGP_COLOR_ENC_YCBCR; 316 break; 317 case V4L2_PIX_FMT_YUYV: 318 case V4L2_PIX_FMT_UYVY: 319 case V4L2_PIX_FMT_YVYU: 320 case V4L2_PIX_FMT_VYUY: 321 tpg->hmask[0] = ~1; 322 tpg->color_enc = TGP_COLOR_ENC_YCBCR; 323 break; 324 case V4L2_PIX_FMT_HSV24: 325 case V4L2_PIX_FMT_HSV32: 326 tpg->color_enc = TGP_COLOR_ENC_HSV; 327 break; 328 default: 329 return false; 330 } 331 332 switch (fourcc) { 333 case V4L2_PIX_FMT_GREY: 334 case V4L2_PIX_FMT_RGB332: 335 tpg->twopixelsize[0] = 2; 336 break; 337 case V4L2_PIX_FMT_RGB565: 338 case V4L2_PIX_FMT_RGB565X: 339 case V4L2_PIX_FMT_RGB444: 340 case V4L2_PIX_FMT_XRGB444: 341 case V4L2_PIX_FMT_ARGB444: 342 case V4L2_PIX_FMT_RGB555: 343 case V4L2_PIX_FMT_XRGB555: 344 case V4L2_PIX_FMT_ARGB555: 345 case V4L2_PIX_FMT_RGB555X: 346 case V4L2_PIX_FMT_XRGB555X: 347 case V4L2_PIX_FMT_ARGB555X: 348 case V4L2_PIX_FMT_YUYV: 349 case V4L2_PIX_FMT_UYVY: 350 case V4L2_PIX_FMT_YVYU: 351 case V4L2_PIX_FMT_VYUY: 352 case V4L2_PIX_FMT_YUV444: 353 case V4L2_PIX_FMT_YUV555: 354 case V4L2_PIX_FMT_YUV565: 355 case V4L2_PIX_FMT_Y16: 356 case V4L2_PIX_FMT_Y16_BE: 357 tpg->twopixelsize[0] = 2 * 2; 358 break; 359 case V4L2_PIX_FMT_RGB24: 360 case V4L2_PIX_FMT_BGR24: 361 case V4L2_PIX_FMT_HSV24: 362 tpg->twopixelsize[0] = 2 * 3; 363 break; 364 case V4L2_PIX_FMT_BGR666: 365 case V4L2_PIX_FMT_RGB32: 366 case V4L2_PIX_FMT_BGR32: 367 case V4L2_PIX_FMT_XRGB32: 368 case V4L2_PIX_FMT_XBGR32: 369 case V4L2_PIX_FMT_ARGB32: 370 case V4L2_PIX_FMT_ABGR32: 371 case V4L2_PIX_FMT_YUV32: 372 case V4L2_PIX_FMT_HSV32: 373 tpg->twopixelsize[0] = 2 * 4; 374 break; 375 case V4L2_PIX_FMT_NV12: 376 case V4L2_PIX_FMT_NV21: 377 case V4L2_PIX_FMT_NV12M: 378 case V4L2_PIX_FMT_NV21M: 379 case V4L2_PIX_FMT_NV16: 380 case V4L2_PIX_FMT_NV61: 381 case V4L2_PIX_FMT_NV16M: 382 case V4L2_PIX_FMT_NV61M: 383 case V4L2_PIX_FMT_SBGGR8: 384 case V4L2_PIX_FMT_SGBRG8: 385 case V4L2_PIX_FMT_SGRBG8: 386 case V4L2_PIX_FMT_SRGGB8: 387 tpg->twopixelsize[0] = 2; 388 tpg->twopixelsize[1] = 2; 389 break; 390 case V4L2_PIX_FMT_SRGGB10: 391 case V4L2_PIX_FMT_SGRBG10: 392 case V4L2_PIX_FMT_SGBRG10: 393 case V4L2_PIX_FMT_SBGGR10: 394 case V4L2_PIX_FMT_SRGGB12: 395 case V4L2_PIX_FMT_SGRBG12: 396 case V4L2_PIX_FMT_SGBRG12: 397 case V4L2_PIX_FMT_SBGGR12: 398 tpg->twopixelsize[0] = 4; 399 tpg->twopixelsize[1] = 4; 400 break; 401 case V4L2_PIX_FMT_YUV444M: 402 case V4L2_PIX_FMT_YVU444M: 403 case V4L2_PIX_FMT_YUV422M: 404 case V4L2_PIX_FMT_YVU422M: 405 case V4L2_PIX_FMT_YUV422P: 406 case V4L2_PIX_FMT_YUV420: 407 case V4L2_PIX_FMT_YVU420: 408 case V4L2_PIX_FMT_YUV420M: 409 case V4L2_PIX_FMT_YVU420M: 410 tpg->twopixelsize[0] = 2; 411 tpg->twopixelsize[1] = 2; 412 tpg->twopixelsize[2] = 2; 413 break; 414 case V4L2_PIX_FMT_NV24: 415 case V4L2_PIX_FMT_NV42: 416 tpg->twopixelsize[0] = 2; 417 tpg->twopixelsize[1] = 4; 418 break; 419 } 420 return true; 421 } 422 EXPORT_SYMBOL_GPL(tpg_s_fourcc); 423 424 void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop, 425 const struct v4l2_rect *compose) 426 { 427 tpg->crop = *crop; 428 tpg->compose = *compose; 429 tpg->scaled_width = (tpg->src_width * tpg->compose.width + 430 tpg->crop.width - 1) / tpg->crop.width; 431 tpg->scaled_width &= ~1; 432 if (tpg->scaled_width > tpg->max_line_width) 433 tpg->scaled_width = tpg->max_line_width; 434 if (tpg->scaled_width < 2) 435 tpg->scaled_width = 2; 436 tpg->recalc_lines = true; 437 } 438 EXPORT_SYMBOL_GPL(tpg_s_crop_compose); 439 440 void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height, 441 u32 field) 442 { 443 unsigned p; 444 445 tpg->src_width = width; 446 tpg->src_height = height; 447 tpg->field = field; 448 tpg->buf_height = height; 449 if (V4L2_FIELD_HAS_T_OR_B(field)) 450 tpg->buf_height /= 2; 451 tpg->scaled_width = width; 452 tpg->crop.top = tpg->crop.left = 0; 453 tpg->crop.width = width; 454 tpg->crop.height = height; 455 tpg->compose.top = tpg->compose.left = 0; 456 tpg->compose.width = width; 457 tpg->compose.height = tpg->buf_height; 458 for (p = 0; p < tpg->planes; p++) 459 tpg->bytesperline[p] = (width * tpg->twopixelsize[p]) / 460 (2 * tpg->hdownsampling[p]); 461 tpg->recalc_square_border = true; 462 } 463 EXPORT_SYMBOL_GPL(tpg_reset_source); 464 465 static enum tpg_color tpg_get_textbg_color(struct tpg_data *tpg) 466 { 467 switch (tpg->pattern) { 468 case TPG_PAT_BLACK: 469 return TPG_COLOR_100_WHITE; 470 case TPG_PAT_CSC_COLORBAR: 471 return TPG_COLOR_CSC_BLACK; 472 default: 473 return TPG_COLOR_100_BLACK; 474 } 475 } 476 477 static enum tpg_color tpg_get_textfg_color(struct tpg_data *tpg) 478 { 479 switch (tpg->pattern) { 480 case TPG_PAT_75_COLORBAR: 481 case TPG_PAT_CSC_COLORBAR: 482 return TPG_COLOR_CSC_WHITE; 483 case TPG_PAT_BLACK: 484 return TPG_COLOR_100_BLACK; 485 default: 486 return TPG_COLOR_100_WHITE; 487 } 488 } 489 490 static inline int rec709_to_linear(int v) 491 { 492 v = clamp(v, 0, 0xff0); 493 return tpg_rec709_to_linear[v]; 494 } 495 496 static inline int linear_to_rec709(int v) 497 { 498 v = clamp(v, 0, 0xff0); 499 return tpg_linear_to_rec709[v]; 500 } 501 502 static void color_to_hsv(struct tpg_data *tpg, int r, int g, int b, 503 int *h, int *s, int *v) 504 { 505 int max_rgb, min_rgb, diff_rgb; 506 int aux; 507 int third; 508 int third_size; 509 510 r >>= 4; 511 g >>= 4; 512 b >>= 4; 513 514 /* Value */ 515 max_rgb = max3(r, g, b); 516 *v = max_rgb; 517 if (!max_rgb) { 518 *h = 0; 519 *s = 0; 520 return; 521 } 522 523 /* Saturation */ 524 min_rgb = min3(r, g, b); 525 diff_rgb = max_rgb - min_rgb; 526 aux = 255 * diff_rgb; 527 aux += max_rgb / 2; 528 aux /= max_rgb; 529 *s = aux; 530 if (!aux) { 531 *h = 0; 532 return; 533 } 534 535 third_size = (tpg->real_hsv_enc == V4L2_HSV_ENC_180) ? 60 : 85; 536 537 /* Hue */ 538 if (max_rgb == r) { 539 aux = g - b; 540 third = 0; 541 } else if (max_rgb == g) { 542 aux = b - r; 543 third = third_size; 544 } else { 545 aux = r - g; 546 third = third_size * 2; 547 } 548 549 aux *= third_size / 2; 550 aux += diff_rgb / 2; 551 aux /= diff_rgb; 552 aux += third; 553 554 /* Clamp Hue */ 555 if (tpg->real_hsv_enc == V4L2_HSV_ENC_180) { 556 if (aux < 0) 557 aux += 180; 558 else if (aux > 180) 559 aux -= 180; 560 } else { 561 aux = aux & 0xff; 562 } 563 564 *h = aux; 565 } 566 567 static void rgb2ycbcr(const int m[3][3], int r, int g, int b, 568 int y_offset, int *y, int *cb, int *cr) 569 { 570 *y = ((m[0][0] * r + m[0][1] * g + m[0][2] * b) >> 16) + (y_offset << 4); 571 *cb = ((m[1][0] * r + m[1][1] * g + m[1][2] * b) >> 16) + (128 << 4); 572 *cr = ((m[2][0] * r + m[2][1] * g + m[2][2] * b) >> 16) + (128 << 4); 573 } 574 575 static void color_to_ycbcr(struct tpg_data *tpg, int r, int g, int b, 576 int *y, int *cb, int *cr) 577 { 578 #define COEFF(v, r) ((int)(0.5 + (v) * (r) * 256.0)) 579 580 static const int bt601[3][3] = { 581 { COEFF(0.299, 219), COEFF(0.587, 219), COEFF(0.114, 219) }, 582 { COEFF(-0.1687, 224), COEFF(-0.3313, 224), COEFF(0.5, 224) }, 583 { COEFF(0.5, 224), COEFF(-0.4187, 224), COEFF(-0.0813, 224) }, 584 }; 585 static const int bt601_full[3][3] = { 586 { COEFF(0.299, 255), COEFF(0.587, 255), COEFF(0.114, 255) }, 587 { COEFF(-0.1687, 255), COEFF(-0.3313, 255), COEFF(0.5, 255) }, 588 { COEFF(0.5, 255), COEFF(-0.4187, 255), COEFF(-0.0813, 255) }, 589 }; 590 static const int rec709[3][3] = { 591 { COEFF(0.2126, 219), COEFF(0.7152, 219), COEFF(0.0722, 219) }, 592 { COEFF(-0.1146, 224), COEFF(-0.3854, 224), COEFF(0.5, 224) }, 593 { COEFF(0.5, 224), COEFF(-0.4542, 224), COEFF(-0.0458, 224) }, 594 }; 595 static const int rec709_full[3][3] = { 596 { COEFF(0.2126, 255), COEFF(0.7152, 255), COEFF(0.0722, 255) }, 597 { COEFF(-0.1146, 255), COEFF(-0.3854, 255), COEFF(0.5, 255) }, 598 { COEFF(0.5, 255), COEFF(-0.4542, 255), COEFF(-0.0458, 255) }, 599 }; 600 static const int smpte240m[3][3] = { 601 { COEFF(0.212, 219), COEFF(0.701, 219), COEFF(0.087, 219) }, 602 { COEFF(-0.116, 224), COEFF(-0.384, 224), COEFF(0.5, 224) }, 603 { COEFF(0.5, 224), COEFF(-0.445, 224), COEFF(-0.055, 224) }, 604 }; 605 static const int smpte240m_full[3][3] = { 606 { COEFF(0.212, 255), COEFF(0.701, 255), COEFF(0.087, 255) }, 607 { COEFF(-0.116, 255), COEFF(-0.384, 255), COEFF(0.5, 255) }, 608 { COEFF(0.5, 255), COEFF(-0.445, 255), COEFF(-0.055, 255) }, 609 }; 610 static const int bt2020[3][3] = { 611 { COEFF(0.2627, 219), COEFF(0.6780, 219), COEFF(0.0593, 219) }, 612 { COEFF(-0.1396, 224), COEFF(-0.3604, 224), COEFF(0.5, 224) }, 613 { COEFF(0.5, 224), COEFF(-0.4598, 224), COEFF(-0.0402, 224) }, 614 }; 615 static const int bt2020_full[3][3] = { 616 { COEFF(0.2627, 255), COEFF(0.6780, 255), COEFF(0.0593, 255) }, 617 { COEFF(-0.1396, 255), COEFF(-0.3604, 255), COEFF(0.5, 255) }, 618 { COEFF(0.5, 255), COEFF(-0.4698, 255), COEFF(-0.0402, 255) }, 619 }; 620 static const int bt2020c[4] = { 621 COEFF(1.0 / 1.9404, 224), COEFF(1.0 / 1.5816, 224), 622 COEFF(1.0 / 1.7184, 224), COEFF(1.0 / 0.9936, 224), 623 }; 624 static const int bt2020c_full[4] = { 625 COEFF(1.0 / 1.9404, 255), COEFF(1.0 / 1.5816, 255), 626 COEFF(1.0 / 1.7184, 255), COEFF(1.0 / 0.9936, 255), 627 }; 628 629 bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE; 630 unsigned y_offset = full ? 0 : 16; 631 int lin_y, yc; 632 633 switch (tpg->real_ycbcr_enc) { 634 case V4L2_YCBCR_ENC_601: 635 rgb2ycbcr(full ? bt601_full : bt601, r, g, b, y_offset, y, cb, cr); 636 break; 637 case V4L2_YCBCR_ENC_XV601: 638 /* Ignore quantization range, there is only one possible 639 * Y'CbCr encoding. */ 640 rgb2ycbcr(bt601, r, g, b, 16, y, cb, cr); 641 break; 642 case V4L2_YCBCR_ENC_XV709: 643 /* Ignore quantization range, there is only one possible 644 * Y'CbCr encoding. */ 645 rgb2ycbcr(rec709, r, g, b, 16, y, cb, cr); 646 break; 647 case V4L2_YCBCR_ENC_BT2020: 648 rgb2ycbcr(full ? bt2020_full : bt2020, r, g, b, y_offset, y, cb, cr); 649 break; 650 case V4L2_YCBCR_ENC_BT2020_CONST_LUM: 651 lin_y = (COEFF(0.2627, 255) * rec709_to_linear(r) + 652 COEFF(0.6780, 255) * rec709_to_linear(g) + 653 COEFF(0.0593, 255) * rec709_to_linear(b)) >> 16; 654 yc = linear_to_rec709(lin_y); 655 *y = full ? yc : (yc * 219) / 255 + (16 << 4); 656 if (b <= yc) 657 *cb = (((b - yc) * (full ? bt2020c_full[0] : bt2020c[0])) >> 16) + (128 << 4); 658 else 659 *cb = (((b - yc) * (full ? bt2020c_full[1] : bt2020c[1])) >> 16) + (128 << 4); 660 if (r <= yc) 661 *cr = (((r - yc) * (full ? bt2020c_full[2] : bt2020c[2])) >> 16) + (128 << 4); 662 else 663 *cr = (((r - yc) * (full ? bt2020c_full[3] : bt2020c[3])) >> 16) + (128 << 4); 664 break; 665 case V4L2_YCBCR_ENC_SMPTE240M: 666 rgb2ycbcr(full ? smpte240m_full : smpte240m, r, g, b, y_offset, y, cb, cr); 667 break; 668 case V4L2_YCBCR_ENC_709: 669 default: 670 rgb2ycbcr(full ? rec709_full : rec709, r, g, b, y_offset, y, cb, cr); 671 break; 672 } 673 } 674 675 static void ycbcr2rgb(const int m[3][3], int y, int cb, int cr, 676 int y_offset, int *r, int *g, int *b) 677 { 678 y -= y_offset << 4; 679 cb -= 128 << 4; 680 cr -= 128 << 4; 681 *r = m[0][0] * y + m[0][1] * cb + m[0][2] * cr; 682 *g = m[1][0] * y + m[1][1] * cb + m[1][2] * cr; 683 *b = m[2][0] * y + m[2][1] * cb + m[2][2] * cr; 684 *r = clamp(*r >> 12, 0, 0xff0); 685 *g = clamp(*g >> 12, 0, 0xff0); 686 *b = clamp(*b >> 12, 0, 0xff0); 687 } 688 689 static void ycbcr_to_color(struct tpg_data *tpg, int y, int cb, int cr, 690 int *r, int *g, int *b) 691 { 692 #undef COEFF 693 #define COEFF(v, r) ((int)(0.5 + (v) * ((255.0 * 255.0 * 16.0) / (r)))) 694 static const int bt601[3][3] = { 695 { COEFF(1, 219), COEFF(0, 224), COEFF(1.4020, 224) }, 696 { COEFF(1, 219), COEFF(-0.3441, 224), COEFF(-0.7141, 224) }, 697 { COEFF(1, 219), COEFF(1.7720, 224), COEFF(0, 224) }, 698 }; 699 static const int bt601_full[3][3] = { 700 { COEFF(1, 255), COEFF(0, 255), COEFF(1.4020, 255) }, 701 { COEFF(1, 255), COEFF(-0.3441, 255), COEFF(-0.7141, 255) }, 702 { COEFF(1, 255), COEFF(1.7720, 255), COEFF(0, 255) }, 703 }; 704 static const int rec709[3][3] = { 705 { COEFF(1, 219), COEFF(0, 224), COEFF(1.5748, 224) }, 706 { COEFF(1, 219), COEFF(-0.1873, 224), COEFF(-0.4681, 224) }, 707 { COEFF(1, 219), COEFF(1.8556, 224), COEFF(0, 224) }, 708 }; 709 static const int rec709_full[3][3] = { 710 { COEFF(1, 255), COEFF(0, 255), COEFF(1.5748, 255) }, 711 { COEFF(1, 255), COEFF(-0.1873, 255), COEFF(-0.4681, 255) }, 712 { COEFF(1, 255), COEFF(1.8556, 255), COEFF(0, 255) }, 713 }; 714 static const int smpte240m[3][3] = { 715 { COEFF(1, 219), COEFF(0, 224), COEFF(1.5756, 224) }, 716 { COEFF(1, 219), COEFF(-0.2253, 224), COEFF(-0.4767, 224) }, 717 { COEFF(1, 219), COEFF(1.8270, 224), COEFF(0, 224) }, 718 }; 719 static const int smpte240m_full[3][3] = { 720 { COEFF(1, 255), COEFF(0, 255), COEFF(1.5756, 255) }, 721 { COEFF(1, 255), COEFF(-0.2253, 255), COEFF(-0.4767, 255) }, 722 { COEFF(1, 255), COEFF(1.8270, 255), COEFF(0, 255) }, 723 }; 724 static const int bt2020[3][3] = { 725 { COEFF(1, 219), COEFF(0, 224), COEFF(1.4746, 224) }, 726 { COEFF(1, 219), COEFF(-0.1646, 224), COEFF(-0.5714, 224) }, 727 { COEFF(1, 219), COEFF(1.8814, 224), COEFF(0, 224) }, 728 }; 729 static const int bt2020_full[3][3] = { 730 { COEFF(1, 255), COEFF(0, 255), COEFF(1.4746, 255) }, 731 { COEFF(1, 255), COEFF(-0.1646, 255), COEFF(-0.5714, 255) }, 732 { COEFF(1, 255), COEFF(1.8814, 255), COEFF(0, 255) }, 733 }; 734 static const int bt2020c[4] = { 735 COEFF(1.9404, 224), COEFF(1.5816, 224), 736 COEFF(1.7184, 224), COEFF(0.9936, 224), 737 }; 738 static const int bt2020c_full[4] = { 739 COEFF(1.9404, 255), COEFF(1.5816, 255), 740 COEFF(1.7184, 255), COEFF(0.9936, 255), 741 }; 742 743 bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE; 744 unsigned y_offset = full ? 0 : 16; 745 int y_fac = full ? COEFF(1.0, 255) : COEFF(1.0, 219); 746 int lin_r, lin_g, lin_b, lin_y; 747 748 switch (tpg->real_ycbcr_enc) { 749 case V4L2_YCBCR_ENC_601: 750 ycbcr2rgb(full ? bt601_full : bt601, y, cb, cr, y_offset, r, g, b); 751 break; 752 case V4L2_YCBCR_ENC_XV601: 753 /* Ignore quantization range, there is only one possible 754 * Y'CbCr encoding. */ 755 ycbcr2rgb(bt601, y, cb, cr, 16, r, g, b); 756 break; 757 case V4L2_YCBCR_ENC_XV709: 758 /* Ignore quantization range, there is only one possible 759 * Y'CbCr encoding. */ 760 ycbcr2rgb(rec709, y, cb, cr, 16, r, g, b); 761 break; 762 case V4L2_YCBCR_ENC_BT2020: 763 ycbcr2rgb(full ? bt2020_full : bt2020, y, cb, cr, y_offset, r, g, b); 764 break; 765 case V4L2_YCBCR_ENC_BT2020_CONST_LUM: 766 y -= full ? 0 : 16 << 4; 767 cb -= 128 << 4; 768 cr -= 128 << 4; 769 770 if (cb <= 0) 771 *b = y_fac * y + (full ? bt2020c_full[0] : bt2020c[0]) * cb; 772 else 773 *b = y_fac * y + (full ? bt2020c_full[1] : bt2020c[1]) * cb; 774 *b = *b >> 12; 775 if (cr <= 0) 776 *r = y_fac * y + (full ? bt2020c_full[2] : bt2020c[2]) * cr; 777 else 778 *r = y_fac * y + (full ? bt2020c_full[3] : bt2020c[3]) * cr; 779 *r = *r >> 12; 780 lin_r = rec709_to_linear(*r); 781 lin_b = rec709_to_linear(*b); 782 lin_y = rec709_to_linear((y * 255) / (full ? 255 : 219)); 783 784 lin_g = COEFF(1.0 / 0.6780, 255) * lin_y - 785 COEFF(0.2627 / 0.6780, 255) * lin_r - 786 COEFF(0.0593 / 0.6780, 255) * lin_b; 787 *g = linear_to_rec709(lin_g >> 12); 788 break; 789 case V4L2_YCBCR_ENC_SMPTE240M: 790 ycbcr2rgb(full ? smpte240m_full : smpte240m, y, cb, cr, y_offset, r, g, b); 791 break; 792 case V4L2_YCBCR_ENC_709: 793 default: 794 ycbcr2rgb(full ? rec709_full : rec709, y, cb, cr, y_offset, r, g, b); 795 break; 796 } 797 } 798 799 /* precalculate color bar values to speed up rendering */ 800 static void precalculate_color(struct tpg_data *tpg, int k) 801 { 802 int col = k; 803 int r = tpg_colors[col].r; 804 int g = tpg_colors[col].g; 805 int b = tpg_colors[col].b; 806 int y, cb, cr; 807 bool ycbcr_valid = false; 808 809 if (k == TPG_COLOR_TEXTBG) { 810 col = tpg_get_textbg_color(tpg); 811 812 r = tpg_colors[col].r; 813 g = tpg_colors[col].g; 814 b = tpg_colors[col].b; 815 } else if (k == TPG_COLOR_TEXTFG) { 816 col = tpg_get_textfg_color(tpg); 817 818 r = tpg_colors[col].r; 819 g = tpg_colors[col].g; 820 b = tpg_colors[col].b; 821 } else if (tpg->pattern == TPG_PAT_NOISE) { 822 r = g = b = prandom_u32_max(256); 823 } else if (k == TPG_COLOR_RANDOM) { 824 r = g = b = tpg->qual_offset + prandom_u32_max(196); 825 } else if (k >= TPG_COLOR_RAMP) { 826 r = g = b = k - TPG_COLOR_RAMP; 827 } 828 829 if (tpg->pattern == TPG_PAT_CSC_COLORBAR && col <= TPG_COLOR_CSC_BLACK) { 830 r = tpg_csc_colors[tpg->colorspace][tpg->real_xfer_func][col].r; 831 g = tpg_csc_colors[tpg->colorspace][tpg->real_xfer_func][col].g; 832 b = tpg_csc_colors[tpg->colorspace][tpg->real_xfer_func][col].b; 833 } else { 834 r <<= 4; 835 g <<= 4; 836 b <<= 4; 837 } 838 839 if (tpg->qual == TPG_QUAL_GRAY || 840 tpg->color_enc == TGP_COLOR_ENC_LUMA) { 841 /* Rec. 709 Luma function */ 842 /* (0.2126, 0.7152, 0.0722) * (255 * 256) */ 843 r = g = b = (13879 * r + 46688 * g + 4713 * b) >> 16; 844 } 845 846 /* 847 * The assumption is that the RGB output is always full range, 848 * so only if the rgb_range overrides the 'real' rgb range do 849 * we need to convert the RGB values. 850 * 851 * Remember that r, g and b are still in the 0 - 0xff0 range. 852 */ 853 if (tpg->real_rgb_range == V4L2_DV_RGB_RANGE_LIMITED && 854 tpg->rgb_range == V4L2_DV_RGB_RANGE_FULL && 855 tpg->color_enc == TGP_COLOR_ENC_RGB) { 856 /* 857 * Convert from full range (which is what r, g and b are) 858 * to limited range (which is the 'real' RGB range), which 859 * is then interpreted as full range. 860 */ 861 r = (r * 219) / 255 + (16 << 4); 862 g = (g * 219) / 255 + (16 << 4); 863 b = (b * 219) / 255 + (16 << 4); 864 } else if (tpg->real_rgb_range != V4L2_DV_RGB_RANGE_LIMITED && 865 tpg->rgb_range == V4L2_DV_RGB_RANGE_LIMITED && 866 tpg->color_enc == TGP_COLOR_ENC_RGB) { 867 868 /* 869 * Clamp r, g and b to the limited range and convert to full 870 * range since that's what we deliver. 871 */ 872 r = clamp(r, 16 << 4, 235 << 4); 873 g = clamp(g, 16 << 4, 235 << 4); 874 b = clamp(b, 16 << 4, 235 << 4); 875 r = (r - (16 << 4)) * 255 / 219; 876 g = (g - (16 << 4)) * 255 / 219; 877 b = (b - (16 << 4)) * 255 / 219; 878 } 879 880 if ((tpg->brightness != 128 || tpg->contrast != 128 || 881 tpg->saturation != 128 || tpg->hue) && 882 tpg->color_enc != TGP_COLOR_ENC_LUMA) { 883 /* Implement these operations */ 884 int tmp_cb, tmp_cr; 885 886 /* First convert to YCbCr */ 887 888 color_to_ycbcr(tpg, r, g, b, &y, &cb, &cr); 889 890 y = (16 << 4) + ((y - (16 << 4)) * tpg->contrast) / 128; 891 y += (tpg->brightness << 4) - (128 << 4); 892 893 cb -= 128 << 4; 894 cr -= 128 << 4; 895 tmp_cb = (cb * cos(128 + tpg->hue)) / 127 + (cr * sin[128 + tpg->hue]) / 127; 896 tmp_cr = (cr * cos(128 + tpg->hue)) / 127 - (cb * sin[128 + tpg->hue]) / 127; 897 898 cb = (128 << 4) + (tmp_cb * tpg->contrast * tpg->saturation) / (128 * 128); 899 cr = (128 << 4) + (tmp_cr * tpg->contrast * tpg->saturation) / (128 * 128); 900 if (tpg->color_enc == TGP_COLOR_ENC_YCBCR) 901 ycbcr_valid = true; 902 else 903 ycbcr_to_color(tpg, y, cb, cr, &r, &g, &b); 904 } else if ((tpg->brightness != 128 || tpg->contrast != 128) && 905 tpg->color_enc == TGP_COLOR_ENC_LUMA) { 906 r = (16 << 4) + ((r - (16 << 4)) * tpg->contrast) / 128; 907 r += (tpg->brightness << 4) - (128 << 4); 908 } 909 910 switch (tpg->color_enc) { 911 case TGP_COLOR_ENC_HSV: 912 { 913 int h, s, v; 914 915 color_to_hsv(tpg, r, g, b, &h, &s, &v); 916 tpg->colors[k][0] = h; 917 tpg->colors[k][1] = s; 918 tpg->colors[k][2] = v; 919 break; 920 } 921 case TGP_COLOR_ENC_YCBCR: 922 { 923 /* Convert to YCbCr */ 924 if (!ycbcr_valid) 925 color_to_ycbcr(tpg, r, g, b, &y, &cb, &cr); 926 927 y >>= 4; 928 cb >>= 4; 929 cr >>= 4; 930 /* 931 * XV601/709 use the header/footer margins to encode R', G' 932 * and B' values outside the range [0-1]. So do not clamp 933 * XV601/709 values. 934 */ 935 if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE && 936 tpg->real_ycbcr_enc != V4L2_YCBCR_ENC_XV601 && 937 tpg->real_ycbcr_enc != V4L2_YCBCR_ENC_XV709) { 938 y = clamp(y, 16, 235); 939 cb = clamp(cb, 16, 240); 940 cr = clamp(cr, 16, 240); 941 } else { 942 y = clamp(y, 1, 254); 943 cb = clamp(cb, 1, 254); 944 cr = clamp(cr, 1, 254); 945 } 946 switch (tpg->fourcc) { 947 case V4L2_PIX_FMT_YUV444: 948 y >>= 4; 949 cb >>= 4; 950 cr >>= 4; 951 break; 952 case V4L2_PIX_FMT_YUV555: 953 y >>= 3; 954 cb >>= 3; 955 cr >>= 3; 956 break; 957 case V4L2_PIX_FMT_YUV565: 958 y >>= 3; 959 cb >>= 2; 960 cr >>= 3; 961 break; 962 } 963 tpg->colors[k][0] = y; 964 tpg->colors[k][1] = cb; 965 tpg->colors[k][2] = cr; 966 break; 967 } 968 case TGP_COLOR_ENC_LUMA: 969 { 970 tpg->colors[k][0] = r >> 4; 971 break; 972 } 973 case TGP_COLOR_ENC_RGB: 974 { 975 if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) { 976 r = (r * 219) / 255 + (16 << 4); 977 g = (g * 219) / 255 + (16 << 4); 978 b = (b * 219) / 255 + (16 << 4); 979 } 980 switch (tpg->fourcc) { 981 case V4L2_PIX_FMT_RGB332: 982 r >>= 9; 983 g >>= 9; 984 b >>= 10; 985 break; 986 case V4L2_PIX_FMT_RGB565: 987 case V4L2_PIX_FMT_RGB565X: 988 r >>= 7; 989 g >>= 6; 990 b >>= 7; 991 break; 992 case V4L2_PIX_FMT_RGB444: 993 case V4L2_PIX_FMT_XRGB444: 994 case V4L2_PIX_FMT_ARGB444: 995 r >>= 8; 996 g >>= 8; 997 b >>= 8; 998 break; 999 case V4L2_PIX_FMT_RGB555: 1000 case V4L2_PIX_FMT_XRGB555: 1001 case V4L2_PIX_FMT_ARGB555: 1002 case V4L2_PIX_FMT_RGB555X: 1003 case V4L2_PIX_FMT_XRGB555X: 1004 case V4L2_PIX_FMT_ARGB555X: 1005 r >>= 7; 1006 g >>= 7; 1007 b >>= 7; 1008 break; 1009 case V4L2_PIX_FMT_BGR666: 1010 r >>= 6; 1011 g >>= 6; 1012 b >>= 6; 1013 break; 1014 default: 1015 r >>= 4; 1016 g >>= 4; 1017 b >>= 4; 1018 break; 1019 } 1020 1021 tpg->colors[k][0] = r; 1022 tpg->colors[k][1] = g; 1023 tpg->colors[k][2] = b; 1024 break; 1025 } 1026 } 1027 } 1028 1029 static void tpg_precalculate_colors(struct tpg_data *tpg) 1030 { 1031 int k; 1032 1033 for (k = 0; k < TPG_COLOR_MAX; k++) 1034 precalculate_color(tpg, k); 1035 } 1036 1037 /* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */ 1038 static void gen_twopix(struct tpg_data *tpg, 1039 u8 buf[TPG_MAX_PLANES][8], int color, bool odd) 1040 { 1041 unsigned offset = odd * tpg->twopixelsize[0] / 2; 1042 u8 alpha = tpg->alpha_component; 1043 u8 r_y_h, g_u_s, b_v; 1044 1045 if (tpg->alpha_red_only && color != TPG_COLOR_CSC_RED && 1046 color != TPG_COLOR_100_RED && 1047 color != TPG_COLOR_75_RED) 1048 alpha = 0; 1049 if (color == TPG_COLOR_RANDOM) 1050 precalculate_color(tpg, color); 1051 r_y_h = tpg->colors[color][0]; /* R or precalculated Y, H */ 1052 g_u_s = tpg->colors[color][1]; /* G or precalculated U, V */ 1053 b_v = tpg->colors[color][2]; /* B or precalculated V */ 1054 1055 switch (tpg->fourcc) { 1056 case V4L2_PIX_FMT_GREY: 1057 buf[0][offset] = r_y_h; 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] = 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] = 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