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