1/* 2 * vivid-tpg.h - Test Pattern Generator 3 * 4 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 5 * 6 * This program is free software; you may redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; version 2 of the License. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 * SOFTWARE. 18 */ 19 20#ifndef _VIVID_TPG_H_ 21#define _VIVID_TPG_H_ 22 23#include <linux/types.h> 24#include <linux/errno.h> 25#include <linux/random.h> 26#include <linux/slab.h> 27#include <linux/vmalloc.h> 28#include <linux/videodev2.h> 29 30#include "vivid-tpg-colors.h" 31 32enum tpg_pattern { 33 TPG_PAT_75_COLORBAR, 34 TPG_PAT_100_COLORBAR, 35 TPG_PAT_CSC_COLORBAR, 36 TPG_PAT_100_HCOLORBAR, 37 TPG_PAT_100_COLORSQUARES, 38 TPG_PAT_BLACK, 39 TPG_PAT_WHITE, 40 TPG_PAT_RED, 41 TPG_PAT_GREEN, 42 TPG_PAT_BLUE, 43 TPG_PAT_CHECKERS_16X16, 44 TPG_PAT_CHECKERS_2X2, 45 TPG_PAT_CHECKERS_1X1, 46 TPG_PAT_COLOR_CHECKERS_2X2, 47 TPG_PAT_COLOR_CHECKERS_1X1, 48 TPG_PAT_ALTERNATING_HLINES, 49 TPG_PAT_ALTERNATING_VLINES, 50 TPG_PAT_CROSS_1_PIXEL, 51 TPG_PAT_CROSS_2_PIXELS, 52 TPG_PAT_CROSS_10_PIXELS, 53 TPG_PAT_GRAY_RAMP, 54 55 /* Must be the last pattern */ 56 TPG_PAT_NOISE, 57}; 58 59extern const char * const tpg_pattern_strings[]; 60 61enum tpg_quality { 62 TPG_QUAL_COLOR, 63 TPG_QUAL_GRAY, 64 TPG_QUAL_NOISE 65}; 66 67enum tpg_video_aspect { 68 TPG_VIDEO_ASPECT_IMAGE, 69 TPG_VIDEO_ASPECT_4X3, 70 TPG_VIDEO_ASPECT_14X9_CENTRE, 71 TPG_VIDEO_ASPECT_16X9_CENTRE, 72 TPG_VIDEO_ASPECT_16X9_ANAMORPHIC, 73}; 74 75enum tpg_pixel_aspect { 76 TPG_PIXEL_ASPECT_SQUARE, 77 TPG_PIXEL_ASPECT_NTSC, 78 TPG_PIXEL_ASPECT_PAL, 79}; 80 81enum tpg_move_mode { 82 TPG_MOVE_NEG_FAST, 83 TPG_MOVE_NEG, 84 TPG_MOVE_NEG_SLOW, 85 TPG_MOVE_NONE, 86 TPG_MOVE_POS_SLOW, 87 TPG_MOVE_POS, 88 TPG_MOVE_POS_FAST, 89}; 90 91extern const char * const tpg_aspect_strings[]; 92 93#define TPG_MAX_PLANES 3 94#define TPG_MAX_PAT_LINES 8 95 96struct tpg_data { 97 /* Source frame size */ 98 unsigned src_width, src_height; 99 /* Buffer height */ 100 unsigned buf_height; 101 /* Scaled output frame size */ 102 unsigned scaled_width; 103 u32 field; 104 bool field_alternate; 105 /* crop coordinates are frame-based */ 106 struct v4l2_rect crop; 107 /* compose coordinates are format-based */ 108 struct v4l2_rect compose; 109 /* border and square coordinates are frame-based */ 110 struct v4l2_rect border; 111 struct v4l2_rect square; 112 113 /* Color-related fields */ 114 enum tpg_quality qual; 115 unsigned qual_offset; 116 u8 alpha_component; 117 bool alpha_red_only; 118 u8 brightness; 119 u8 contrast; 120 u8 saturation; 121 s16 hue; 122 u32 fourcc; 123 bool is_yuv; 124 u32 colorspace; 125 u32 ycbcr_enc; 126 /* 127 * Stores the actual Y'CbCr encoding, i.e. will never be 128 * V4L2_YCBCR_ENC_DEFAULT. 129 */ 130 u32 real_ycbcr_enc; 131 u32 quantization; 132 /* 133 * Stores the actual quantization, i.e. will never be 134 * V4L2_QUANTIZATION_DEFAULT. 135 */ 136 u32 real_quantization; 137 enum tpg_video_aspect vid_aspect; 138 enum tpg_pixel_aspect pix_aspect; 139 unsigned rgb_range; 140 unsigned real_rgb_range; 141 unsigned buffers; 142 unsigned planes; 143 bool interleaved; 144 u8 vdownsampling[TPG_MAX_PLANES]; 145 u8 hdownsampling[TPG_MAX_PLANES]; 146 /* 147 * horizontal positions must be ANDed with this value to enforce 148 * correct boundaries for packed YUYV values. 149 */ 150 unsigned hmask[TPG_MAX_PLANES]; 151 /* Used to store the colors in native format, either RGB or YUV */ 152 u8 colors[TPG_COLOR_MAX][3]; 153 u8 textfg[TPG_MAX_PLANES][8], textbg[TPG_MAX_PLANES][8]; 154 /* size in bytes for two pixels in each plane */ 155 unsigned twopixelsize[TPG_MAX_PLANES]; 156 unsigned bytesperline[TPG_MAX_PLANES]; 157 158 /* Configuration */ 159 enum tpg_pattern pattern; 160 bool hflip; 161 bool vflip; 162 unsigned perc_fill; 163 bool perc_fill_blank; 164 bool show_border; 165 bool show_square; 166 bool insert_sav; 167 bool insert_eav; 168 169 /* Test pattern movement */ 170 enum tpg_move_mode mv_hor_mode; 171 int mv_hor_count; 172 int mv_hor_step; 173 enum tpg_move_mode mv_vert_mode; 174 int mv_vert_count; 175 int mv_vert_step; 176 177 bool recalc_colors; 178 bool recalc_lines; 179 bool recalc_square_border; 180 181 /* Used to store TPG_MAX_PAT_LINES lines, each with up to two planes */ 182 unsigned max_line_width; 183 u8 *lines[TPG_MAX_PAT_LINES][TPG_MAX_PLANES]; 184 u8 *downsampled_lines[TPG_MAX_PAT_LINES][TPG_MAX_PLANES]; 185 u8 *random_line[TPG_MAX_PLANES]; 186 u8 *contrast_line[TPG_MAX_PLANES]; 187 u8 *black_line[TPG_MAX_PLANES]; 188}; 189 190void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h); 191int tpg_alloc(struct tpg_data *tpg, unsigned max_w); 192void tpg_free(struct tpg_data *tpg); 193void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height, 194 u32 field); 195 196void tpg_set_font(const u8 *f); 197void tpg_gen_text(const struct tpg_data *tpg, 198 u8 *basep[TPG_MAX_PLANES][2], int y, int x, char *text); 199void tpg_calc_text_basep(struct tpg_data *tpg, 200 u8 *basep[TPG_MAX_PLANES][2], unsigned p, u8 *vbuf); 201unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line); 202void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, 203 unsigned p, u8 *vbuf); 204void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, 205 unsigned p, u8 *vbuf); 206bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc); 207void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop, 208 const struct v4l2_rect *compose); 209 210static inline void tpg_s_pattern(struct tpg_data *tpg, enum tpg_pattern pattern) 211{ 212 if (tpg->pattern == pattern) 213 return; 214 tpg->pattern = pattern; 215 tpg->recalc_colors = true; 216} 217 218static inline void tpg_s_quality(struct tpg_data *tpg, 219 enum tpg_quality qual, unsigned qual_offset) 220{ 221 if (tpg->qual == qual && tpg->qual_offset == qual_offset) 222 return; 223 tpg->qual = qual; 224 tpg->qual_offset = qual_offset; 225 tpg->recalc_colors = true; 226} 227 228static inline enum tpg_quality tpg_g_quality(const struct tpg_data *tpg) 229{ 230 return tpg->qual; 231} 232 233static inline void tpg_s_alpha_component(struct tpg_data *tpg, 234 u8 alpha_component) 235{ 236 if (tpg->alpha_component == alpha_component) 237 return; 238 tpg->alpha_component = alpha_component; 239 tpg->recalc_colors = true; 240} 241 242static inline void tpg_s_alpha_mode(struct tpg_data *tpg, 243 bool red_only) 244{ 245 if (tpg->alpha_red_only == red_only) 246 return; 247 tpg->alpha_red_only = red_only; 248 tpg->recalc_colors = true; 249} 250 251static inline void tpg_s_brightness(struct tpg_data *tpg, 252 u8 brightness) 253{ 254 if (tpg->brightness == brightness) 255 return; 256 tpg->brightness = brightness; 257 tpg->recalc_colors = true; 258} 259 260static inline void tpg_s_contrast(struct tpg_data *tpg, 261 u8 contrast) 262{ 263 if (tpg->contrast == contrast) 264 return; 265 tpg->contrast = contrast; 266 tpg->recalc_colors = true; 267} 268 269static inline void tpg_s_saturation(struct tpg_data *tpg, 270 u8 saturation) 271{ 272 if (tpg->saturation == saturation) 273 return; 274 tpg->saturation = saturation; 275 tpg->recalc_colors = true; 276} 277 278static inline void tpg_s_hue(struct tpg_data *tpg, 279 s16 hue) 280{ 281 if (tpg->hue == hue) 282 return; 283 tpg->hue = hue; 284 tpg->recalc_colors = true; 285} 286 287static inline void tpg_s_rgb_range(struct tpg_data *tpg, 288 unsigned rgb_range) 289{ 290 if (tpg->rgb_range == rgb_range) 291 return; 292 tpg->rgb_range = rgb_range; 293 tpg->recalc_colors = true; 294} 295 296static inline void tpg_s_real_rgb_range(struct tpg_data *tpg, 297 unsigned rgb_range) 298{ 299 if (tpg->real_rgb_range == rgb_range) 300 return; 301 tpg->real_rgb_range = rgb_range; 302 tpg->recalc_colors = true; 303} 304 305static inline void tpg_s_colorspace(struct tpg_data *tpg, u32 colorspace) 306{ 307 if (tpg->colorspace == colorspace) 308 return; 309 tpg->colorspace = colorspace; 310 tpg->recalc_colors = true; 311} 312 313static inline u32 tpg_g_colorspace(const struct tpg_data *tpg) 314{ 315 return tpg->colorspace; 316} 317 318static inline void tpg_s_ycbcr_enc(struct tpg_data *tpg, u32 ycbcr_enc) 319{ 320 if (tpg->ycbcr_enc == ycbcr_enc) 321 return; 322 tpg->ycbcr_enc = ycbcr_enc; 323 tpg->recalc_colors = true; 324} 325 326static inline u32 tpg_g_ycbcr_enc(const struct tpg_data *tpg) 327{ 328 return tpg->ycbcr_enc; 329} 330 331static inline void tpg_s_quantization(struct tpg_data *tpg, u32 quantization) 332{ 333 if (tpg->quantization == quantization) 334 return; 335 tpg->quantization = quantization; 336 tpg->recalc_colors = true; 337} 338 339static inline u32 tpg_g_quantization(const struct tpg_data *tpg) 340{ 341 return tpg->quantization; 342} 343 344static inline unsigned tpg_g_buffers(const struct tpg_data *tpg) 345{ 346 return tpg->buffers; 347} 348 349static inline unsigned tpg_g_planes(const struct tpg_data *tpg) 350{ 351 return tpg->interleaved ? 1 : tpg->planes; 352} 353 354static inline bool tpg_g_interleaved(const struct tpg_data *tpg) 355{ 356 return tpg->interleaved; 357} 358 359static inline unsigned tpg_g_twopixelsize(const struct tpg_data *tpg, unsigned plane) 360{ 361 return tpg->twopixelsize[plane]; 362} 363 364static inline unsigned tpg_hdiv(const struct tpg_data *tpg, 365 unsigned plane, unsigned x) 366{ 367 return ((x / tpg->hdownsampling[plane]) & tpg->hmask[plane]) * 368 tpg->twopixelsize[plane] / 2; 369} 370 371static inline unsigned tpg_hscale(const struct tpg_data *tpg, unsigned x) 372{ 373 return (x * tpg->scaled_width) / tpg->src_width; 374} 375 376static inline unsigned tpg_hscale_div(const struct tpg_data *tpg, 377 unsigned plane, unsigned x) 378{ 379 return tpg_hdiv(tpg, plane, tpg_hscale(tpg, x)); 380} 381 382static inline unsigned tpg_g_bytesperline(const struct tpg_data *tpg, unsigned plane) 383{ 384 return tpg->bytesperline[plane]; 385} 386 387static inline void tpg_s_bytesperline(struct tpg_data *tpg, unsigned plane, unsigned bpl) 388{ 389 unsigned p; 390 391 if (tpg->buffers > 1) { 392 tpg->bytesperline[plane] = bpl; 393 return; 394 } 395 396 for (p = 0; p < tpg_g_planes(tpg); p++) { 397 unsigned plane_w = bpl * tpg->twopixelsize[p] / tpg->twopixelsize[0]; 398 399 tpg->bytesperline[p] = plane_w / tpg->hdownsampling[p]; 400 } 401} 402 403 404static inline unsigned tpg_g_line_width(const struct tpg_data *tpg, unsigned plane) 405{ 406 unsigned w = 0; 407 unsigned p; 408 409 if (tpg->buffers > 1) 410 return tpg_g_bytesperline(tpg, plane); 411 for (p = 0; p < tpg_g_planes(tpg); p++) { 412 unsigned plane_w = tpg_g_bytesperline(tpg, p); 413 414 w += plane_w / tpg->vdownsampling[p]; 415 } 416 return w; 417} 418 419static inline unsigned tpg_calc_line_width(const struct tpg_data *tpg, 420 unsigned plane, unsigned bpl) 421{ 422 unsigned w = 0; 423 unsigned p; 424 425 if (tpg->buffers > 1) 426 return bpl; 427 for (p = 0; p < tpg_g_planes(tpg); p++) { 428 unsigned plane_w = bpl * tpg->twopixelsize[p] / tpg->twopixelsize[0]; 429 430 plane_w /= tpg->hdownsampling[p]; 431 w += plane_w / tpg->vdownsampling[p]; 432 } 433 return w; 434} 435 436static inline unsigned tpg_calc_plane_size(const struct tpg_data *tpg, unsigned plane) 437{ 438 if (plane >= tpg_g_planes(tpg)) 439 return 0; 440 441 return tpg_g_bytesperline(tpg, plane) * tpg->buf_height / 442 tpg->vdownsampling[plane]; 443} 444 445static inline void tpg_s_buf_height(struct tpg_data *tpg, unsigned h) 446{ 447 tpg->buf_height = h; 448} 449 450static inline void tpg_s_field(struct tpg_data *tpg, unsigned field, bool alternate) 451{ 452 tpg->field = field; 453 tpg->field_alternate = alternate; 454} 455 456static inline void tpg_s_perc_fill(struct tpg_data *tpg, 457 unsigned perc_fill) 458{ 459 tpg->perc_fill = perc_fill; 460} 461 462static inline unsigned tpg_g_perc_fill(const struct tpg_data *tpg) 463{ 464 return tpg->perc_fill; 465} 466 467static inline void tpg_s_perc_fill_blank(struct tpg_data *tpg, 468 bool perc_fill_blank) 469{ 470 tpg->perc_fill_blank = perc_fill_blank; 471} 472 473static inline void tpg_s_video_aspect(struct tpg_data *tpg, 474 enum tpg_video_aspect vid_aspect) 475{ 476 if (tpg->vid_aspect == vid_aspect) 477 return; 478 tpg->vid_aspect = vid_aspect; 479 tpg->recalc_square_border = true; 480} 481 482static inline enum tpg_video_aspect tpg_g_video_aspect(const struct tpg_data *tpg) 483{ 484 return tpg->vid_aspect; 485} 486 487static inline void tpg_s_pixel_aspect(struct tpg_data *tpg, 488 enum tpg_pixel_aspect pix_aspect) 489{ 490 if (tpg->pix_aspect == pix_aspect) 491 return; 492 tpg->pix_aspect = pix_aspect; 493 tpg->recalc_square_border = true; 494} 495 496static inline void tpg_s_show_border(struct tpg_data *tpg, 497 bool show_border) 498{ 499 tpg->show_border = show_border; 500} 501 502static inline void tpg_s_show_square(struct tpg_data *tpg, 503 bool show_square) 504{ 505 tpg->show_square = show_square; 506} 507 508static inline void tpg_s_insert_sav(struct tpg_data *tpg, bool insert_sav) 509{ 510 tpg->insert_sav = insert_sav; 511} 512 513static inline void tpg_s_insert_eav(struct tpg_data *tpg, bool insert_eav) 514{ 515 tpg->insert_eav = insert_eav; 516} 517 518void tpg_update_mv_step(struct tpg_data *tpg); 519 520static inline void tpg_s_mv_hor_mode(struct tpg_data *tpg, 521 enum tpg_move_mode mv_hor_mode) 522{ 523 tpg->mv_hor_mode = mv_hor_mode; 524 tpg_update_mv_step(tpg); 525} 526 527static inline void tpg_s_mv_vert_mode(struct tpg_data *tpg, 528 enum tpg_move_mode mv_vert_mode) 529{ 530 tpg->mv_vert_mode = mv_vert_mode; 531 tpg_update_mv_step(tpg); 532} 533 534static inline void tpg_init_mv_count(struct tpg_data *tpg) 535{ 536 tpg->mv_hor_count = tpg->mv_vert_count = 0; 537} 538 539static inline void tpg_update_mv_count(struct tpg_data *tpg, bool frame_is_field) 540{ 541 tpg->mv_hor_count += tpg->mv_hor_step * (frame_is_field ? 1 : 2); 542 tpg->mv_vert_count += tpg->mv_vert_step * (frame_is_field ? 1 : 2); 543} 544 545static inline void tpg_s_hflip(struct tpg_data *tpg, bool hflip) 546{ 547 if (tpg->hflip == hflip) 548 return; 549 tpg->hflip = hflip; 550 tpg_update_mv_step(tpg); 551 tpg->recalc_lines = true; 552} 553 554static inline bool tpg_g_hflip(const struct tpg_data *tpg) 555{ 556 return tpg->hflip; 557} 558 559static inline void tpg_s_vflip(struct tpg_data *tpg, bool vflip) 560{ 561 tpg->vflip = vflip; 562} 563 564static inline bool tpg_g_vflip(const struct tpg_data *tpg) 565{ 566 return tpg->vflip; 567} 568 569static inline bool tpg_pattern_is_static(const struct tpg_data *tpg) 570{ 571 return tpg->pattern != TPG_PAT_NOISE && 572 tpg->mv_hor_mode == TPG_MOVE_NONE && 573 tpg->mv_vert_mode == TPG_MOVE_NONE; 574} 575 576#endif 577