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