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