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