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