linux/drivers/media/platform/xilinx/xilinx-tpg.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Xilinx Test Pattern Generator
   4 *
   5 * Copyright (C) 2013-2015 Ideas on Board
   6 * Copyright (C) 2013-2015 Xilinx, Inc.
   7 *
   8 * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
   9 *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  10 */
  11
  12#include <linux/device.h>
  13#include <linux/gpio/consumer.h>
  14#include <linux/module.h>
  15#include <linux/of.h>
  16#include <linux/platform_device.h>
  17#include <linux/xilinx-v4l2-controls.h>
  18
  19#include <media/v4l2-async.h>
  20#include <media/v4l2-ctrls.h>
  21#include <media/v4l2-subdev.h>
  22
  23#include "xilinx-hls-common.h"
  24#include "xilinx-vip.h"
  25#include "xilinx-vtc.h"
  26
  27#define XTPG_CTRL_STATUS_SLAVE_ERROR            (1 << 16)
  28#define XTPG_CTRL_IRQ_SLAVE_ERROR               (1 << 16)
  29
  30#define XTPG_PATTERN_CONTROL                    0x0100
  31#define XTPG_PATTERN_MASK                       (0xf << 0)
  32#define XTPG_PATTERN_CONTROL_CROSS_HAIRS        (1 << 4)
  33#define XTPG_PATTERN_CONTROL_MOVING_BOX         (1 << 5)
  34#define XTPG_PATTERN_CONTROL_COLOR_MASK_SHIFT   6
  35#define XTPG_PATTERN_CONTROL_COLOR_MASK_MASK    (0xf << 6)
  36#define XTPG_PATTERN_CONTROL_STUCK_PIXEL        (1 << 9)
  37#define XTPG_PATTERN_CONTROL_NOISE              (1 << 10)
  38#define XTPG_PATTERN_CONTROL_MOTION             (1 << 12)
  39#define XTPG_MOTION_SPEED                       0x0104
  40#define XTPG_CROSS_HAIRS                        0x0108
  41#define XTPG_CROSS_HAIRS_ROW_SHIFT              0
  42#define XTPG_CROSS_HAIRS_ROW_MASK               (0xfff << 0)
  43#define XTPG_CROSS_HAIRS_COLUMN_SHIFT           16
  44#define XTPG_CROSS_HAIRS_COLUMN_MASK            (0xfff << 16)
  45#define XTPG_ZPLATE_HOR_CONTROL                 0x010c
  46#define XTPG_ZPLATE_VER_CONTROL                 0x0110
  47#define XTPG_ZPLATE_START_SHIFT                 0
  48#define XTPG_ZPLATE_START_MASK                  (0xffff << 0)
  49#define XTPG_ZPLATE_SPEED_SHIFT                 16
  50#define XTPG_ZPLATE_SPEED_MASK                  (0xffff << 16)
  51#define XTPG_BOX_SIZE                           0x0114
  52#define XTPG_BOX_COLOR                          0x0118
  53#define XTPG_STUCK_PIXEL_THRESH                 0x011c
  54#define XTPG_NOISE_GAIN                         0x0120
  55#define XTPG_BAYER_PHASE                        0x0124
  56#define XTPG_BAYER_PHASE_RGGB                   0
  57#define XTPG_BAYER_PHASE_GRBG                   1
  58#define XTPG_BAYER_PHASE_GBRG                   2
  59#define XTPG_BAYER_PHASE_BGGR                   3
  60#define XTPG_BAYER_PHASE_OFF                    4
  61
  62/* TPG v7 is a completely redesigned IP using Vivado HLS
  63 * having a different AXI4-Lite interface
  64 */
  65#define XTPG_HLS_BG_PATTERN                     0x0020
  66#define XTPG_HLS_FG_PATTERN                     0x0028
  67#define XTPG_HLS_FG_PATTERN_CROSS_HAIR          (1 << 1)
  68#define XTPG_HLS_MASK_ID                        0x0030
  69#define XTPG_HLS_MOTION_SPEED                   0x0038
  70#define XTPG_HLS_COLOR_FORMAT                   0x0040
  71#define XTPG_HLS_COLOR_FORMAT_RGB               0
  72#define XTPG_HLS_COLOR_FORMAT_YUV_444           1
  73#define XTPG_HLS_COLOR_FORMAT_YUV_422           2
  74#define XTPG_HLS_COLOR_FORMAT_YUV_420           3
  75#define XTPG_HLS_CROSS_HAIR_HOR                 0x0048
  76#define XTPG_HLS_CROSS_HAIR_VER                 0x0050
  77#define XTPG_HLS_ZPLATE_HOR_CNTL_START          0x0058
  78#define XTPG_HLS_ZPLATE_HOR_CNTL_DELTA          0x0060
  79#define XTPG_HLS_ZPLATE_VER_CNTL_START          0x0068
  80#define XTPG_HLS_ZPLATE_VER_CNTL_DELTA          0x0070
  81#define XTPG_HLS_BOX_SIZE                       0x0078
  82#define XTPG_HLS_BOX_COLOR_RED_CB               0x0080
  83#define XTPG_HLS_BOX_COLOR_GREEN_CR             0x0088
  84#define XTPG_HLS_BOX_COLOR_BLUE_Y               0x0090
  85#define XTPG_HLS_ENABLE_INPUT                   0x0098
  86#define XTPG_HLS_USE_INPUT_VID_STREAM           (1 << 0)
  87#define XTPG_HLS_PASS_THRU_START_X              0x00a0
  88#define XTPG_HLS_PASS_THRU_START_Y              0x00a8
  89#define XTPG_HLS_PASS_THRU_END_X                0x00b0
  90#define XTPG_HLS_PASS_THRU_END_Y                0x00b8
  91
  92/*
  93 * The minimum blanking value is one clock cycle for the front porch, one clock
  94 * cycle for the sync pulse and one clock cycle for the back porch.
  95 */
  96#define XTPG_MIN_HBLANK                 3
  97#define XTPG_MAX_HBLANK                 (XVTC_MAX_HSIZE - XVIP_MIN_WIDTH)
  98#define XTPG_MIN_VBLANK                 3
  99#define XTPG_MAX_VBLANK                 (XVTC_MAX_VSIZE - XVIP_MIN_HEIGHT)
 100
 101#define XTPG_MIN_WIDTH                  (64)
 102#define XTPG_MIN_HEIGHT                 (64)
 103#define XTPG_MAX_WIDTH                  (10328)
 104#define XTPG_MAX_HEIGHT                 (7760)
 105
 106#define XTPG_MIN_PPC                    1
 107
 108#define XTPG_MIN_FRM_INT                1
 109
 110/**
 111 * struct xtpg_device - Xilinx Test Pattern Generator device structure
 112 * @xvip: Xilinx Video IP device
 113 * @pads: media pads
 114 * @npads: number of pads (1 or 2)
 115 * @has_input: whether an input is connected to the sink pad
 116 * @formats: active V4L2 media bus format for each pad
 117 * @default_format: default V4L2 media bus format
 118 * @vip_format: format information corresponding to the active format
 119 * @bayer: boolean flag if TPG is set to any bayer format
 120 * @ctrl_handler: control handler
 121 * @hblank: horizontal blanking control
 122 * @vblank: vertical blanking control
 123 * @pattern: test pattern control
 124 * @streaming: is the video stream active
 125 * @is_hls: whether the IP core is HLS based
 126 * @vtc: video timing controller
 127 * @vtmux_gpio: video timing mux GPIO
 128 * @rst_gpio: reset IP core GPIO
 129 * @max_width: Maximum width supported by this instance
 130 * @max_height: Maximum height supported by this instance
 131 * @fi_d: frame interval denominator
 132 * @fi_n: frame interval numerator
 133 * @ppc: Pixels per clock control
 134 */
 135struct xtpg_device {
 136        struct xvip_device xvip;
 137
 138        struct media_pad pads[2];
 139        unsigned int npads;
 140        bool has_input;
 141
 142        struct v4l2_mbus_framefmt formats[2];
 143        struct v4l2_mbus_framefmt default_format;
 144        const struct xvip_video_format *vip_format;
 145        bool bayer;
 146
 147        struct v4l2_ctrl_handler ctrl_handler;
 148        struct v4l2_ctrl *hblank;
 149        struct v4l2_ctrl *vblank;
 150        struct v4l2_ctrl *pattern;
 151        bool streaming;
 152        bool is_hls;
 153
 154        struct xvtc_device *vtc;
 155        struct gpio_desc *vtmux_gpio;
 156        struct gpio_desc *rst_gpio;
 157
 158        u32 max_width;
 159        u32 max_height;
 160        u32 fi_d;
 161        u32 fi_n;
 162        u32 ppc;
 163};
 164
 165static inline struct xtpg_device *to_tpg(struct v4l2_subdev *subdev)
 166{
 167        return container_of(subdev, struct xtpg_device, xvip.subdev);
 168}
 169
 170static u32 xtpg_get_bayer_phase(unsigned int code)
 171{
 172        switch (code) {
 173        case MEDIA_BUS_FMT_SRGGB8_1X8:
 174                return XTPG_BAYER_PHASE_RGGB;
 175        case MEDIA_BUS_FMT_SGRBG8_1X8:
 176                return XTPG_BAYER_PHASE_GRBG;
 177        case MEDIA_BUS_FMT_SGBRG8_1X8:
 178                return XTPG_BAYER_PHASE_GBRG;
 179        case MEDIA_BUS_FMT_SBGGR8_1X8:
 180                return XTPG_BAYER_PHASE_BGGR;
 181        default:
 182                return XTPG_BAYER_PHASE_OFF;
 183        }
 184}
 185
 186static void xtpg_config_vtc(struct xtpg_device *xtpg, int width, int height)
 187{
 188
 189        struct xvtc_config config = {
 190                .hblank_start = width / xtpg->ppc,
 191                .hsync_start = width / xtpg->ppc + 1,
 192                .vblank_start = height,
 193                .vsync_start = height + 1,
 194                .fps = xtpg->fi_d / xtpg->fi_n,
 195        };
 196        unsigned int htotal;
 197        unsigned int vtotal;
 198
 199        htotal = min_t(unsigned int, XVTC_MAX_HSIZE,
 200                       (v4l2_ctrl_g_ctrl(xtpg->hblank) + width) / xtpg->ppc);
 201        vtotal = min_t(unsigned int, XVTC_MAX_VSIZE,
 202                       v4l2_ctrl_g_ctrl(xtpg->vblank) + height);
 203
 204        config.hsync_end = htotal - 1;
 205        config.hsize = htotal;
 206        config.vsync_end = vtotal - 1;
 207        config.vsize = vtotal;
 208
 209        xvtc_generator_start(xtpg->vtc, &config);
 210}
 211
 212static void __xtpg_update_pattern_control(struct xtpg_device *xtpg,
 213                                          bool passthrough, bool pattern)
 214{
 215        u32 pattern_mask = (1 << (xtpg->pattern->maximum + 1)) - 1;
 216
 217        /*
 218         * If the TPG has no sink pad or no input connected to its sink pad
 219         * passthrough mode can't be enabled.
 220         */
 221        if (xtpg->npads == 1 || !xtpg->has_input)
 222                passthrough = false;
 223
 224        /* If passthrough mode is allowed unmask bit 0. */
 225        if (passthrough)
 226                pattern_mask &= ~1;
 227
 228        /* If test pattern mode is allowed unmask all other bits. */
 229        if (pattern)
 230                pattern_mask &= 1;
 231
 232        __v4l2_ctrl_modify_range(xtpg->pattern, 0, xtpg->pattern->maximum,
 233                                 pattern_mask, pattern ? 9 : 0);
 234}
 235
 236static void xtpg_update_pattern_control(struct xtpg_device *xtpg,
 237                                        bool passthrough, bool pattern)
 238{
 239        mutex_lock(xtpg->ctrl_handler.lock);
 240        __xtpg_update_pattern_control(xtpg, passthrough, pattern);
 241        mutex_unlock(xtpg->ctrl_handler.lock);
 242}
 243
 244/* -----------------------------------------------------------------------------
 245 * V4L2 Subdevice Video Operations
 246 */
 247
 248static int xtpg_g_frame_interval(struct v4l2_subdev *subdev,
 249                                 struct v4l2_subdev_frame_interval *fi)
 250{
 251        struct xtpg_device *xtpg = to_tpg(subdev);
 252
 253        fi->interval.numerator = xtpg->fi_n;
 254        fi->interval.denominator = xtpg->fi_d;
 255
 256        return 0;
 257}
 258
 259static int xtpg_s_frame_interval(struct v4l2_subdev *subdev,
 260                                 struct v4l2_subdev_frame_interval *fi)
 261{
 262        struct xtpg_device *xtpg = to_tpg(subdev);
 263
 264        if (!fi->interval.numerator || !fi->interval.denominator) {
 265                xtpg->fi_n = XTPG_MIN_FRM_INT;
 266                xtpg->fi_d = XTPG_MIN_FRM_INT;
 267        } else {
 268                xtpg->fi_n = fi->interval.numerator;
 269                xtpg->fi_d = fi->interval.denominator;
 270        }
 271
 272        return 0;
 273}
 274
 275static int xtpg_s_stream(struct v4l2_subdev *subdev, int enable)
 276{
 277        struct xtpg_device *xtpg = to_tpg(subdev);
 278        unsigned int width = xtpg->formats[0].width;
 279        unsigned int height = xtpg->formats[0].height;
 280        bool passthrough;
 281        u32 bayer_phase;
 282
 283        if (!enable) {
 284                if (!xtpg->is_hls) {
 285                        xvip_stop(&xtpg->xvip);
 286                } else {
 287                        /*
 288                         * There is an known issue in TPG v7.0 that on
 289                         * resolution change it doesn't generates pattern
 290                         * correctly i.e some hor/ver offset is added.
 291                         * As a workaround issue reset on stop.
 292                         */
 293                        gpiod_set_value_cansleep(xtpg->rst_gpio, 0x1);
 294                        gpiod_set_value_cansleep(xtpg->rst_gpio, 0x0);
 295                        v4l2_ctrl_handler_setup(&xtpg->ctrl_handler);
 296                }
 297
 298                if (xtpg->vtc)
 299                        xvtc_generator_stop(xtpg->vtc);
 300
 301                xtpg_update_pattern_control(xtpg, true, true);
 302                xtpg->streaming = false;
 303                return 0;
 304        }
 305
 306        if (xtpg->is_hls) {
 307                u32 fmt = 0;
 308
 309                switch (xtpg->formats[0].code) {
 310                case MEDIA_BUS_FMT_VYYUYY8_1X24:
 311                case MEDIA_BUS_FMT_VYYUYY10_4X20:
 312                        fmt = XTPG_HLS_COLOR_FORMAT_YUV_420;
 313                        break;
 314                case MEDIA_BUS_FMT_UYVY8_1X16:
 315                case MEDIA_BUS_FMT_UYVY10_1X20:
 316                        fmt = XTPG_HLS_COLOR_FORMAT_YUV_422;
 317                        break;
 318                case MEDIA_BUS_FMT_VUY8_1X24:
 319                case MEDIA_BUS_FMT_VUY10_1X30:
 320                        fmt = XTPG_HLS_COLOR_FORMAT_YUV_444;
 321                        break;
 322                case MEDIA_BUS_FMT_RBG888_1X24:
 323                case MEDIA_BUS_FMT_RBG101010_1X30:
 324                        fmt = XTPG_HLS_COLOR_FORMAT_RGB;
 325                        break;
 326                }
 327                xvip_write(&xtpg->xvip, XTPG_HLS_COLOR_FORMAT, fmt);
 328                xvip_write(&xtpg->xvip, XHLS_REG_COLS, width);
 329                xvip_write(&xtpg->xvip, XHLS_REG_ROWS, height);
 330        } else {
 331                xvip_set_frame_size(&xtpg->xvip, &xtpg->formats[0]);
 332        }
 333
 334        if (xtpg->vtc)
 335                xtpg_config_vtc(xtpg, width, height);
 336        /*
 337         * Configure the bayer phase and video timing mux based on the
 338         * operation mode (passthrough or test pattern generation). The test
 339         * pattern can be modified by the control set handler, we thus need to
 340         * take the control lock here to avoid races.
 341         */
 342        mutex_lock(xtpg->ctrl_handler.lock);
 343
 344        if (xtpg->is_hls)
 345                xvip_write(&xtpg->xvip, XTPG_HLS_BG_PATTERN,
 346                           xtpg->pattern->cur.val);
 347        else
 348                xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
 349                         XTPG_PATTERN_MASK, xtpg->pattern->cur.val);
 350
 351        /*
 352         * Switching between passthrough and test pattern generation modes isn't
 353         * allowed during streaming, update the control range accordingly.
 354         */
 355        passthrough = xtpg->pattern->cur.val == 0;
 356        __xtpg_update_pattern_control(xtpg, passthrough, !passthrough);
 357
 358        xtpg->streaming = true;
 359
 360        mutex_unlock(xtpg->ctrl_handler.lock);
 361
 362        if (xtpg->vtmux_gpio)
 363                gpiod_set_value_cansleep(xtpg->vtmux_gpio, !passthrough);
 364
 365        if (xtpg->is_hls) {
 366                xvip_set(&xtpg->xvip, XTPG_HLS_ENABLE_INPUT,
 367                         XTPG_HLS_USE_INPUT_VID_STREAM);
 368                xvip_set(&xtpg->xvip, XVIP_CTRL_CONTROL,
 369                         XHLS_REG_CTRL_AUTO_RESTART |
 370                         XVIP_CTRL_CONTROL_SW_ENABLE);
 371        } else {
 372                /*
 373                 * For TPG v5.0, the bayer phase needs to be off for the pass
 374                 * through mode, otherwise the external input would
 375                 * be subsampled.
 376                 */
 377                bayer_phase = passthrough ? XTPG_BAYER_PHASE_OFF
 378                            : xtpg_get_bayer_phase(xtpg->formats[0].code);
 379                xvip_write(&xtpg->xvip, XTPG_BAYER_PHASE, bayer_phase);
 380                xvip_start(&xtpg->xvip);
 381        }
 382
 383        return 0;
 384}
 385
 386/* -----------------------------------------------------------------------------
 387 * V4L2 Subdevice Pad Operations
 388 */
 389
 390static struct v4l2_mbus_framefmt *
 391__xtpg_get_pad_format(struct xtpg_device *xtpg,
 392                      struct v4l2_subdev_pad_config *cfg,
 393                      unsigned int pad, u32 which)
 394{
 395        switch (which) {
 396        case V4L2_SUBDEV_FORMAT_TRY:
 397                return v4l2_subdev_get_try_format(&xtpg->xvip.subdev, cfg, pad);
 398        case V4L2_SUBDEV_FORMAT_ACTIVE:
 399                return &xtpg->formats[pad];
 400        default:
 401                return NULL;
 402        }
 403}
 404
 405static int xtpg_get_format(struct v4l2_subdev *subdev,
 406                           struct v4l2_subdev_pad_config *cfg,
 407                           struct v4l2_subdev_format *fmt)
 408{
 409        struct xtpg_device *xtpg = to_tpg(subdev);
 410
 411        fmt->format = *__xtpg_get_pad_format(xtpg, cfg, fmt->pad, fmt->which);
 412
 413        return 0;
 414}
 415
 416static int xtpg_set_format(struct v4l2_subdev *subdev,
 417                           struct v4l2_subdev_pad_config *cfg,
 418                           struct v4l2_subdev_format *fmt)
 419{
 420        struct xtpg_device *xtpg = to_tpg(subdev);
 421        struct v4l2_mbus_framefmt *__format;
 422        u32 bayer_phase;
 423
 424        __format = __xtpg_get_pad_format(xtpg, cfg, fmt->pad, fmt->which);
 425
 426        /* In two pads mode the source pad format is always identical to the
 427         * sink pad format.
 428         */
 429        if (xtpg->npads == 2 && fmt->pad == 1) {
 430                fmt->format = *__format;
 431                return 0;
 432        }
 433
 434        /* Bayer phase is configurable at runtime */
 435        if (xtpg->bayer) {
 436                bayer_phase = xtpg_get_bayer_phase(fmt->format.code);
 437                if (bayer_phase != XTPG_BAYER_PHASE_OFF)
 438                        __format->code = fmt->format.code;
 439        }
 440
 441        if (xtpg->is_hls) {
 442                switch (fmt->format.code) {
 443                case MEDIA_BUS_FMT_VYYUYY8_1X24:
 444                case MEDIA_BUS_FMT_VYYUYY10_4X20:
 445                case MEDIA_BUS_FMT_UYVY8_1X16:
 446                case MEDIA_BUS_FMT_UYVY10_1X20:
 447                case MEDIA_BUS_FMT_VUY8_1X24:
 448                case MEDIA_BUS_FMT_VUY10_1X30:
 449                case MEDIA_BUS_FMT_RBG888_1X24:
 450                case MEDIA_BUS_FMT_RBG101010_1X30:
 451                        __format->code = fmt->format.code;
 452                        break;
 453                default:
 454                        __format->code = xtpg->default_format.code;
 455                }
 456        }
 457
 458        __format->width = clamp_t(unsigned int, fmt->format.width,
 459                                  XTPG_MIN_WIDTH, xtpg->max_width);
 460        __format->height = clamp_t(unsigned int, fmt->format.height,
 461                                   XTPG_MIN_HEIGHT, xtpg->max_height);
 462
 463        fmt->format = *__format;
 464
 465        /* Propagate the format to the source pad. */
 466        if (xtpg->npads == 2) {
 467                __format = __xtpg_get_pad_format(xtpg, cfg, 1, fmt->which);
 468                *__format = fmt->format;
 469        }
 470
 471        return 0;
 472}
 473
 474/* -----------------------------------------------------------------------------
 475 * V4L2 Subdevice Operations
 476 */
 477
 478static int xtpg_enum_frame_size(struct v4l2_subdev *subdev,
 479                                struct v4l2_subdev_pad_config *cfg,
 480                                struct v4l2_subdev_frame_size_enum *fse)
 481{
 482        struct v4l2_mbus_framefmt *format;
 483        struct xtpg_device *xtpg = to_tpg(subdev);
 484
 485        format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad);
 486
 487        if (fse->index || fse->code != format->code)
 488                return -EINVAL;
 489
 490        /* Min / max values for pad 0 is always fixed in both one and two pads
 491         * modes. In two pads mode, the source pad(= 1) size is identical to
 492         * the sink pad size.
 493         */
 494        if (fse->pad == 0) {
 495                fse->min_width = XTPG_MIN_WIDTH;
 496                fse->max_width = xtpg->max_width;
 497                fse->min_height = XTPG_MIN_HEIGHT;
 498                fse->max_height = xtpg->max_height;
 499        } else {
 500                fse->min_width = format->width;
 501                fse->max_width = format->width;
 502                fse->min_height = format->height;
 503                fse->max_height = format->height;
 504        }
 505
 506        return 0;
 507}
 508
 509static int xtpg_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
 510{
 511        struct xtpg_device *xtpg = to_tpg(subdev);
 512        struct v4l2_mbus_framefmt *format;
 513
 514        format = v4l2_subdev_get_try_format(subdev, fh->pad, 0);
 515        *format = xtpg->default_format;
 516
 517        if (xtpg->npads == 2) {
 518                format = v4l2_subdev_get_try_format(subdev, fh->pad, 1);
 519                *format = xtpg->default_format;
 520        }
 521
 522        return 0;
 523}
 524
 525static int xtpg_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
 526{
 527        return 0;
 528}
 529
 530static int xtpg_s_ctrl(struct v4l2_ctrl *ctrl)
 531{
 532        struct xtpg_device *xtpg = container_of(ctrl->handler,
 533                                                struct xtpg_device,
 534                                                ctrl_handler);
 535        switch (ctrl->id) {
 536        case V4L2_CID_TEST_PATTERN:
 537                if (xtpg->is_hls)
 538                        xvip_write(&xtpg->xvip, XTPG_HLS_BG_PATTERN,
 539                                   ctrl->val);
 540                else
 541                        xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
 542                                         XTPG_PATTERN_MASK, ctrl->val);
 543                return 0;
 544        case V4L2_CID_XILINX_TPG_CROSS_HAIRS:
 545                xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
 546                                XTPG_PATTERN_CONTROL_CROSS_HAIRS, ctrl->val);
 547                return 0;
 548        case V4L2_CID_XILINX_TPG_MOVING_BOX:
 549                xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
 550                                XTPG_PATTERN_CONTROL_MOVING_BOX, ctrl->val);
 551                return 0;
 552        case V4L2_CID_XILINX_TPG_COLOR_MASK:
 553                if (xtpg->is_hls)
 554                        xvip_write(&xtpg->xvip, XTPG_HLS_MASK_ID, ctrl->val);
 555                else
 556                        xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
 557                                      XTPG_PATTERN_CONTROL_COLOR_MASK_MASK,
 558                                      ctrl->val <<
 559                                      XTPG_PATTERN_CONTROL_COLOR_MASK_SHIFT);
 560                return 0;
 561        case V4L2_CID_XILINX_TPG_STUCK_PIXEL:
 562                xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
 563                                XTPG_PATTERN_CONTROL_STUCK_PIXEL, ctrl->val);
 564                return 0;
 565        case V4L2_CID_XILINX_TPG_NOISE:
 566                xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
 567                                XTPG_PATTERN_CONTROL_NOISE, ctrl->val);
 568                return 0;
 569        case V4L2_CID_XILINX_TPG_MOTION:
 570                xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
 571                                XTPG_PATTERN_CONTROL_MOTION, ctrl->val);
 572                return 0;
 573        case V4L2_CID_XILINX_TPG_MOTION_SPEED:
 574                if (xtpg->is_hls)
 575                        xvip_write(&xtpg->xvip, XTPG_HLS_MOTION_SPEED,
 576                                   ctrl->val);
 577                else
 578                        xvip_write(&xtpg->xvip, XTPG_MOTION_SPEED, ctrl->val);
 579                return 0;
 580        case V4L2_CID_XILINX_TPG_CROSS_HAIR_ROW:
 581                if (xtpg->is_hls)
 582                        xvip_write(&xtpg->xvip, XTPG_HLS_CROSS_HAIR_HOR,
 583                                    ctrl->val);
 584                else
 585                        xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS,
 586                                         XTPG_CROSS_HAIRS_ROW_MASK,
 587                                         ctrl->val <<
 588                                         XTPG_CROSS_HAIRS_ROW_SHIFT);
 589                return 0;
 590        case V4L2_CID_XILINX_TPG_CROSS_HAIR_COLUMN:
 591                if (xtpg->is_hls)
 592                        xvip_write(&xtpg->xvip, XTPG_HLS_CROSS_HAIR_VER,
 593                                   ctrl->val);
 594                else
 595                        xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS,
 596                                         XTPG_CROSS_HAIRS_COLUMN_MASK,
 597                                         ctrl->val <<
 598                                         XTPG_CROSS_HAIRS_COLUMN_SHIFT);
 599                return 0;
 600        case V4L2_CID_XILINX_TPG_ZPLATE_HOR_START:
 601                if (xtpg->is_hls)
 602                        xvip_write(&xtpg->xvip, XTPG_HLS_ZPLATE_HOR_CNTL_START,
 603                                   ctrl->val);
 604                else
 605                        xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL,
 606                                         XTPG_ZPLATE_START_MASK,
 607                                         ctrl->val << XTPG_ZPLATE_START_SHIFT);
 608                return 0;
 609        case V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED:
 610                if (xtpg->is_hls)
 611                        xvip_write(&xtpg->xvip, XTPG_HLS_ZPLATE_HOR_CNTL_DELTA,
 612                                   ctrl->val);
 613                else
 614                        xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL,
 615                                         XTPG_ZPLATE_SPEED_MASK,
 616                                         ctrl->val << XTPG_ZPLATE_SPEED_SHIFT);
 617                return 0;
 618        case V4L2_CID_XILINX_TPG_ZPLATE_VER_START:
 619                if (xtpg->is_hls)
 620                        xvip_write(&xtpg->xvip, XTPG_HLS_ZPLATE_VER_CNTL_START,
 621                                   ctrl->val);
 622                else
 623                        xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL,
 624                                         XTPG_ZPLATE_START_MASK,
 625                                         ctrl->val << XTPG_ZPLATE_START_SHIFT);
 626                return 0;
 627        case V4L2_CID_XILINX_TPG_ZPLATE_VER_SPEED:
 628                if (xtpg->is_hls)
 629                        xvip_write(&xtpg->xvip, XTPG_HLS_ZPLATE_VER_CNTL_DELTA,
 630                                   ctrl->val);
 631                else
 632                        xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL,
 633                                         XTPG_ZPLATE_SPEED_MASK,
 634                                         ctrl->val << XTPG_ZPLATE_SPEED_SHIFT);
 635                return 0;
 636        case V4L2_CID_XILINX_TPG_BOX_SIZE:
 637                if (xtpg->is_hls)
 638                        xvip_write(&xtpg->xvip, XTPG_HLS_BOX_SIZE, ctrl->val);
 639                else
 640                        xvip_write(&xtpg->xvip, XTPG_BOX_SIZE, ctrl->val);
 641                return 0;
 642        case V4L2_CID_XILINX_TPG_BOX_COLOR:
 643                if (xtpg->is_hls) {
 644                        xvip_write(&xtpg->xvip, XTPG_HLS_BOX_COLOR_RED_CB,
 645                                   ctrl->val >> 16);
 646                        xvip_write(&xtpg->xvip, XTPG_HLS_BOX_COLOR_GREEN_CR,
 647                                   ctrl->val >> 8);
 648                        xvip_write(&xtpg->xvip, XTPG_HLS_BOX_COLOR_BLUE_Y,
 649                                   ctrl->val);
 650                } else {
 651                        xvip_write(&xtpg->xvip, XTPG_BOX_COLOR, ctrl->val);
 652                }
 653                return 0;
 654        case V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH:
 655                xvip_write(&xtpg->xvip, XTPG_STUCK_PIXEL_THRESH, ctrl->val);
 656                return 0;
 657        case V4L2_CID_XILINX_TPG_NOISE_GAIN:
 658                xvip_write(&xtpg->xvip, XTPG_NOISE_GAIN, ctrl->val);
 659                return 0;
 660        case V4L2_CID_XILINX_TPG_HLS_FG_PATTERN:
 661                xvip_write(&xtpg->xvip, XTPG_HLS_FG_PATTERN, ctrl->val);
 662                return 0;
 663        }
 664
 665        return 0;
 666}
 667
 668static const struct v4l2_ctrl_ops xtpg_ctrl_ops = {
 669        .s_ctrl = xtpg_s_ctrl,
 670};
 671
 672static const struct v4l2_subdev_core_ops xtpg_core_ops = {
 673};
 674
 675static const struct v4l2_subdev_video_ops xtpg_video_ops = {
 676        .g_frame_interval = xtpg_g_frame_interval,
 677        .s_frame_interval = xtpg_s_frame_interval,
 678        .s_stream = xtpg_s_stream,
 679};
 680
 681static const struct v4l2_subdev_pad_ops xtpg_pad_ops = {
 682        .enum_mbus_code         = xvip_enum_mbus_code,
 683        .enum_frame_size        = xtpg_enum_frame_size,
 684        .get_fmt                = xtpg_get_format,
 685        .set_fmt                = xtpg_set_format,
 686};
 687
 688static const struct v4l2_subdev_ops xtpg_ops = {
 689        .core   = &xtpg_core_ops,
 690        .video  = &xtpg_video_ops,
 691        .pad    = &xtpg_pad_ops,
 692};
 693
 694static const struct v4l2_subdev_internal_ops xtpg_internal_ops = {
 695        .open   = xtpg_open,
 696        .close  = xtpg_close,
 697};
 698
 699/*
 700 * Control Config
 701 */
 702
 703static const char *const xtpg_pattern_strings[] = {
 704        "Passthrough",
 705        "Horizontal Ramp",
 706        "Vertical Ramp",
 707        "Temporal Ramp",
 708        "Solid Red",
 709        "Solid Green",
 710        "Solid Blue",
 711        "Solid Black",
 712        "Solid White",
 713        "Color Bars",
 714        "Zone Plate",
 715        "Tartan Color Bars",
 716        "Cross Hatch",
 717        "None",
 718        "Vertical/Horizontal Ramps",
 719        "Black/White Checker Board",
 720};
 721
 722static const char *const xtpg_hls_pattern_strings[] = {
 723        "Passthrough",
 724        "Horizontal Ramp",
 725        "Vertical Ramp",
 726        "Temporal Ramp",
 727        "Solid Red",
 728        "Solid Green",
 729        "Solid Blue",
 730        "Solid Black",
 731        "Solid White",
 732        "Color Bars",
 733        "Zone Plate",
 734        "Tartan Color Bars",
 735        "Cross Hatch",
 736        "Color Sweep",
 737        "Vertical/Horizontal Ramps",
 738        "Black/White Checker Board",
 739        "PseudoRandom",
 740};
 741
 742static const char *const xtpg_hls_fg_strings[] = {
 743        "No Overlay",
 744        "Moving Box",
 745        "Cross Hairs",
 746};
 747
 748static const struct v4l2_ctrl_config xtpg_hls_fg_ctrl = {
 749        .ops    = &xtpg_ctrl_ops,
 750        .id     = V4L2_CID_XILINX_TPG_HLS_FG_PATTERN,
 751        .name   = "Test Pattern: Foreground Pattern",
 752        .type   = V4L2_CTRL_TYPE_MENU,
 753        .min    = 0,
 754        .max    = ARRAY_SIZE(xtpg_hls_fg_strings) - 1,
 755        .qmenu  = xtpg_hls_fg_strings,
 756};
 757
 758static struct v4l2_ctrl_config xtpg_common_ctrls[] = {
 759        {
 760                .ops    = &xtpg_ctrl_ops,
 761                .id     = V4L2_CID_XILINX_TPG_COLOR_MASK,
 762                .name   = "Test Pattern: Color Mask",
 763                .type   = V4L2_CTRL_TYPE_BITMASK,
 764                .min    = 0,
 765                .max    = 0x7,
 766                .def    = 0,
 767        }, {
 768                .ops    = &xtpg_ctrl_ops,
 769                .id     = V4L2_CID_XILINX_TPG_MOTION_SPEED,
 770                .name   = "Test Pattern: Motion Speed",
 771                .type   = V4L2_CTRL_TYPE_INTEGER,
 772                .min    = 0,
 773                .max    = (1 << 8) - 1,
 774                .step   = 1,
 775                .def    = 4,
 776                .flags  = V4L2_CTRL_FLAG_SLIDER,
 777        }, {
 778                .ops    = &xtpg_ctrl_ops,
 779                .id     = V4L2_CID_XILINX_TPG_CROSS_HAIR_ROW,
 780                .name   = "Test Pattern: Cross Hairs Row",
 781                .type   = V4L2_CTRL_TYPE_INTEGER,
 782                .min    = 0,
 783                .max    = (1 << 12) - 1,
 784                .step   = 1,
 785                .def    = 0x64,
 786                .flags  = V4L2_CTRL_FLAG_SLIDER,
 787        }, {
 788                .ops    = &xtpg_ctrl_ops,
 789                .id     = V4L2_CID_XILINX_TPG_CROSS_HAIR_COLUMN,
 790                .name   = "Test Pattern: Cross Hairs Column",
 791                .type   = V4L2_CTRL_TYPE_INTEGER,
 792                .min    = 0,
 793                .max    = (1 << 12) - 1,
 794                .step   = 1,
 795                .def    = 0x64,
 796                .flags  = V4L2_CTRL_FLAG_SLIDER,
 797        }, {
 798                .ops    = &xtpg_ctrl_ops,
 799                .id     = V4L2_CID_XILINX_TPG_ZPLATE_HOR_START,
 800                .name   = "Test Pattern: Zplate Horizontal Start Pos",
 801                .type   = V4L2_CTRL_TYPE_INTEGER,
 802                .min    = 0,
 803                .max    = (1 << 16) - 1,
 804                .step   = 1,
 805                .def    = 0x1e,
 806                .flags  = V4L2_CTRL_FLAG_SLIDER,
 807        }, {
 808                .ops    = &xtpg_ctrl_ops,
 809                .id     = V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED,
 810                .name   = "Test Pattern: Zplate Horizontal Speed",
 811                .type   = V4L2_CTRL_TYPE_INTEGER,
 812                .min    = 0,
 813                .max    = (1 << 16) - 1,
 814                .step   = 1,
 815                .def    = 0,
 816                .flags  = V4L2_CTRL_FLAG_SLIDER,
 817        }, {
 818                .ops    = &xtpg_ctrl_ops,
 819                .id     = V4L2_CID_XILINX_TPG_ZPLATE_VER_START,
 820                .name   = "Test Pattern: Zplate Vertical Start Pos",
 821                .type   = V4L2_CTRL_TYPE_INTEGER,
 822                .min    = 0,
 823                .max    = (1 << 16) - 1,
 824                .step   = 1,
 825                .def    = 1,
 826                .flags  = V4L2_CTRL_FLAG_SLIDER,
 827        }, {
 828                .ops    = &xtpg_ctrl_ops,
 829                .id     = V4L2_CID_XILINX_TPG_ZPLATE_VER_SPEED,
 830                .name   = "Test Pattern: Zplate Vertical Speed",
 831                .type   = V4L2_CTRL_TYPE_INTEGER,
 832                .min    = 0,
 833                .max    = (1 << 16) - 1,
 834                .step   = 1,
 835                .def    = 0,
 836                .flags  = V4L2_CTRL_FLAG_SLIDER,
 837        }, {
 838                .ops    = &xtpg_ctrl_ops,
 839                .id     = V4L2_CID_XILINX_TPG_BOX_SIZE,
 840                .name   = "Test Pattern: Box Size",
 841                .type   = V4L2_CTRL_TYPE_INTEGER,
 842                .min    = 0,
 843                .max    = (1 << 12) - 1,
 844                .step   = 1,
 845                .def    = 0x32,
 846                .flags  = V4L2_CTRL_FLAG_SLIDER,
 847        }, {
 848                .ops    = &xtpg_ctrl_ops,
 849                .id     = V4L2_CID_XILINX_TPG_BOX_COLOR,
 850                .name   = "Test Pattern: Box Color(RGB/YCbCr)",
 851                .type   = V4L2_CTRL_TYPE_INTEGER,
 852                .min    = 0,
 853                .max    = (1 << 24) - 1,
 854                .step   = 1,
 855                .def    = 0,
 856        },
 857};
 858
 859static struct v4l2_ctrl_config xtpg_ctrls[] = {
 860        {
 861                .ops    = &xtpg_ctrl_ops,
 862                .id     = V4L2_CID_XILINX_TPG_CROSS_HAIRS,
 863                .name   = "Test Pattern: Cross Hairs",
 864                .type   = V4L2_CTRL_TYPE_BOOLEAN,
 865                .min    = false,
 866                .max    = true,
 867                .step   = 1,
 868                .def    = 0,
 869        }, {
 870                .ops    = &xtpg_ctrl_ops,
 871                .id     = V4L2_CID_XILINX_TPG_MOVING_BOX,
 872                .name   = "Test Pattern: Moving Box",
 873                .type   = V4L2_CTRL_TYPE_BOOLEAN,
 874                .min    = false,
 875                .max    = true,
 876                .step   = 1,
 877                .def    = 0,
 878        }, {
 879                .ops    = &xtpg_ctrl_ops,
 880                .id     = V4L2_CID_XILINX_TPG_STUCK_PIXEL,
 881                .name   = "Test Pattern: Stuck Pixel",
 882                .type   = V4L2_CTRL_TYPE_BOOLEAN,
 883                .min    = false,
 884                .max    = true,
 885                .step   = 1,
 886                .def    = 0,
 887        }, {
 888                .ops    = &xtpg_ctrl_ops,
 889                .id     = V4L2_CID_XILINX_TPG_NOISE,
 890                .name   = "Test Pattern: Noise",
 891                .type   = V4L2_CTRL_TYPE_BOOLEAN,
 892                .min    = false,
 893                .max    = true,
 894                .step   = 1,
 895                .def    = 0,
 896        }, {
 897                .ops    = &xtpg_ctrl_ops,
 898                .id     = V4L2_CID_XILINX_TPG_MOTION,
 899                .name   = "Test Pattern: Motion",
 900                .type   = V4L2_CTRL_TYPE_BOOLEAN,
 901                .min    = false,
 902                .max    = true,
 903                .step   = 1,
 904                .def    = 0,
 905        }, {
 906                .ops    = &xtpg_ctrl_ops,
 907                .id     = V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH,
 908                .name   = "Test Pattern: Stuck Pixel threshold",
 909                .type   = V4L2_CTRL_TYPE_INTEGER,
 910                .min    = 0,
 911                .max    = (1 << 16) - 1,
 912                .step   = 1,
 913                .def    = 0,
 914                .flags  = V4L2_CTRL_FLAG_SLIDER,
 915        }, {
 916                .ops    = &xtpg_ctrl_ops,
 917                .id     = V4L2_CID_XILINX_TPG_NOISE_GAIN,
 918                .name   = "Test Pattern: Noise Gain",
 919                .type   = V4L2_CTRL_TYPE_INTEGER,
 920                .min    = 0,
 921                .max    = (1 << 8) - 1,
 922                .step   = 1,
 923                .def    = 0,
 924                .flags  = V4L2_CTRL_FLAG_SLIDER,
 925        },
 926};
 927
 928/* -----------------------------------------------------------------------------
 929 * Media Operations
 930 */
 931
 932static const struct media_entity_operations xtpg_media_ops = {
 933        .link_validate = v4l2_subdev_link_validate,
 934};
 935
 936/* -----------------------------------------------------------------------------
 937 * Power Management
 938 */
 939
 940static int __maybe_unused xtpg_pm_suspend(struct device *dev)
 941{
 942        struct xtpg_device *xtpg = dev_get_drvdata(dev);
 943
 944        xvip_suspend(&xtpg->xvip);
 945
 946        return 0;
 947}
 948
 949static int __maybe_unused xtpg_pm_resume(struct device *dev)
 950{
 951        struct xtpg_device *xtpg = dev_get_drvdata(dev);
 952
 953        xvip_resume(&xtpg->xvip);
 954
 955        return 0;
 956}
 957
 958/* -----------------------------------------------------------------------------
 959 * Platform Device Driver
 960 */
 961
 962static int xtpg_parse_of(struct xtpg_device *xtpg)
 963{
 964        struct device *dev = xtpg->xvip.dev;
 965        struct device_node *node = xtpg->xvip.dev->of_node;
 966        struct device_node *ports;
 967        struct device_node *port;
 968        unsigned int nports = 0;
 969        bool has_endpoint = false;
 970        int ret;
 971
 972        if (!of_device_is_compatible(dev->of_node, "xlnx,v-tpg-5.0"))
 973                xtpg->is_hls = true;
 974
 975        ret = of_property_read_u32(node, "xlnx,max-height",
 976                                   &xtpg->max_height);
 977        if (ret < 0) {
 978                if (of_device_is_compatible(dev->of_node, "xlnx,v-tpg-8.0")) {
 979                        dev_err(dev, "xlnx,max-height dt property is missing!");
 980                        return -EINVAL;
 981                }
 982                xtpg->max_height = XTPG_MAX_HEIGHT;
 983        } else if (xtpg->max_height > XTPG_MAX_HEIGHT ||
 984                   xtpg->max_height < XTPG_MIN_HEIGHT) {
 985                dev_err(dev, "Invalid height in dt");
 986                return -EINVAL;
 987        }
 988
 989        ret = of_property_read_u32(node, "xlnx,max-width",
 990                                   &xtpg->max_width);
 991        if (ret < 0) {
 992                if (of_device_is_compatible(dev->of_node, "xlnx,v-tpg-8.0")) {
 993                        dev_err(dev, "xlnx,max-width dt property is missing!");
 994                        return -EINVAL;
 995                }
 996                xtpg->max_width = XTPG_MAX_WIDTH;
 997        } else if (xtpg->max_width > XTPG_MAX_WIDTH ||
 998                   xtpg->max_width < XTPG_MIN_WIDTH) {
 999                dev_err(dev, "Invalid width in dt");
1000                return -EINVAL;
1001        }
1002
1003        ret = of_property_read_u32(node, "xlnx,ppc",
1004                                   &xtpg->ppc);
1005        if (ret < 0) {
1006                xtpg->ppc = XTPG_MIN_PPC;
1007                dev_dbg(dev, "failed to read ppc in dt\n");
1008        } else if ((xtpg->ppc != 1) && (xtpg->ppc != 2) &&
1009                        (xtpg->ppc != 4) && (xtpg->ppc != 8)) {
1010                dev_err(dev, "Invalid ppc config in dt\n");
1011                return -EINVAL;
1012        }
1013
1014        ports = of_get_child_by_name(node, "ports");
1015        if (ports == NULL)
1016                ports = node;
1017
1018        for_each_child_of_node(ports, port) {
1019                const struct xvip_video_format *format;
1020                struct device_node *endpoint;
1021
1022                if (!of_node_name_eq(port, "port"))
1023                        continue;
1024
1025                format = xvip_of_get_format(port);
1026                if (IS_ERR(format)) {
1027                        dev_err(dev, "invalid format in DT");
1028                        of_node_put(port);
1029                        return PTR_ERR(format);
1030                }
1031
1032                /* Get and check the format description */
1033                if (!xtpg->vip_format) {
1034                        xtpg->vip_format = format;
1035                } else if (xtpg->vip_format != format) {
1036                        dev_err(dev, "in/out format mismatch in DT");
1037                        of_node_put(port);
1038                        return -EINVAL;
1039                }
1040
1041                if (nports == 0) {
1042                        endpoint = of_get_next_child(port, NULL);
1043                        if (endpoint)
1044                                has_endpoint = true;
1045                        of_node_put(endpoint);
1046                }
1047
1048                /* Count the number of ports. */
1049                nports++;
1050        }
1051
1052        if (nports != 1 && nports != 2) {
1053                dev_err(dev, "invalid number of ports %u\n", nports);
1054                return -EINVAL;
1055        }
1056
1057        xtpg->npads = nports;
1058        if (nports == 2 && has_endpoint)
1059                xtpg->has_input = true;
1060
1061        return 0;
1062}
1063
1064static int xtpg_probe(struct platform_device *pdev)
1065{
1066        struct v4l2_subdev *subdev;
1067        struct xtpg_device *xtpg;
1068        u32 i, bayer_phase;
1069        u32 npatterns;
1070        int ret;
1071
1072        xtpg = devm_kzalloc(&pdev->dev, sizeof(*xtpg), GFP_KERNEL);
1073        if (!xtpg)
1074                return -ENOMEM;
1075
1076        xtpg->xvip.dev = &pdev->dev;
1077
1078        ret = xtpg_parse_of(xtpg);
1079        if (ret < 0)
1080                return ret;
1081
1082        ret = xvip_init_resources(&xtpg->xvip);
1083        if (ret < 0)
1084                return ret;
1085
1086        xtpg->vtmux_gpio = devm_gpiod_get_optional(&pdev->dev, "timing",
1087                                                   GPIOD_OUT_HIGH);
1088        if (IS_ERR(xtpg->vtmux_gpio)) {
1089                ret = PTR_ERR(xtpg->vtmux_gpio);
1090                goto error_resource;
1091        }
1092
1093        if (xtpg->is_hls) {
1094                xtpg->rst_gpio = devm_gpiod_get(&pdev->dev, "reset",
1095                                                   GPIOD_OUT_HIGH);
1096                if (IS_ERR(xtpg->rst_gpio)) {
1097                        ret = PTR_ERR(xtpg->rst_gpio);
1098                        goto error_resource;
1099                }
1100        }
1101
1102        xtpg->vtc = xvtc_of_get(pdev->dev.of_node);
1103        if (IS_ERR(xtpg->vtc)) {
1104                ret = PTR_ERR(xtpg->vtc);
1105                goto error_resource;
1106        }
1107
1108        /*
1109         * Reset and initialize the core. For TPG HLS version there
1110         * is no SW_RESET bit hence using GPIO based reset.
1111         */
1112        if (xtpg->is_hls)
1113                gpiod_set_value_cansleep(xtpg->rst_gpio, 0x0);
1114        else
1115                xvip_reset(&xtpg->xvip);
1116
1117        /* Initialize V4L2 subdevice and media entity. Pad numbers depend on the
1118         * number of pads.
1119         */
1120        if (xtpg->npads == 2) {
1121                xtpg->pads[0].flags = MEDIA_PAD_FL_SINK;
1122                xtpg->pads[1].flags = MEDIA_PAD_FL_SOURCE;
1123        } else {
1124                xtpg->pads[0].flags = MEDIA_PAD_FL_SOURCE;
1125        }
1126
1127        /* Initialize the default format */
1128        xtpg->default_format.code = xtpg->vip_format->code;
1129        xtpg->default_format.field = V4L2_FIELD_NONE;
1130        xtpg->default_format.colorspace = V4L2_COLORSPACE_SRGB;
1131
1132        if (xtpg->is_hls) {
1133                npatterns = ARRAY_SIZE(xtpg_hls_pattern_strings);
1134                xtpg->default_format.width = xvip_read(&xtpg->xvip,
1135                                                       XHLS_REG_COLS);
1136                xtpg->default_format.height = xvip_read(&xtpg->xvip,
1137                                                        XHLS_REG_ROWS);
1138        } else {
1139                npatterns = ARRAY_SIZE(xtpg_pattern_strings);
1140                xvip_get_frame_size(&xtpg->xvip, &xtpg->default_format);
1141        }
1142
1143        if (!xtpg->is_hls) {
1144                bayer_phase = xtpg_get_bayer_phase(xtpg->vip_format->code);
1145                if (bayer_phase != XTPG_BAYER_PHASE_OFF)
1146                        xtpg->bayer = true;
1147        }
1148
1149        xtpg->formats[0] = xtpg->default_format;
1150        if (xtpg->npads == 2)
1151                xtpg->formats[1] = xtpg->default_format;
1152
1153        /* Initialize V4L2 subdevice and media entity */
1154        subdev = &xtpg->xvip.subdev;
1155        v4l2_subdev_init(subdev, &xtpg_ops);
1156        subdev->dev = &pdev->dev;
1157        subdev->internal_ops = &xtpg_internal_ops;
1158        strscpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
1159        v4l2_set_subdevdata(subdev, xtpg);
1160        subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1161        subdev->entity.ops = &xtpg_media_ops;
1162
1163        ret = media_entity_pads_init(&subdev->entity, xtpg->npads, xtpg->pads);
1164        if (ret < 0)
1165                goto error;
1166
1167        if (xtpg->is_hls)
1168                v4l2_ctrl_handler_init(&xtpg->ctrl_handler, 4 +
1169                                       ARRAY_SIZE(xtpg_common_ctrls));
1170        else
1171                v4l2_ctrl_handler_init(&xtpg->ctrl_handler, 3 +
1172                                       ARRAY_SIZE(xtpg_common_ctrls) +
1173                                       ARRAY_SIZE(xtpg_ctrls));
1174
1175        xtpg->vblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops,
1176                                         V4L2_CID_VBLANK, XTPG_MIN_VBLANK,
1177                                         XTPG_MAX_VBLANK, 1, 100);
1178        xtpg->hblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops,
1179                                         V4L2_CID_HBLANK, XTPG_MIN_HBLANK,
1180                                         XTPG_MAX_HBLANK, 1, 100);
1181
1182        if (xtpg->is_hls) {
1183                xtpg->pattern =
1184                        v4l2_ctrl_new_std_menu_items(&xtpg->ctrl_handler,
1185                                                     &xtpg_ctrl_ops,
1186                                                     V4L2_CID_TEST_PATTERN,
1187                                                     npatterns - 1,
1188                                                     1, 9,
1189                                                     xtpg_hls_pattern_strings);
1190                v4l2_ctrl_new_custom(&xtpg->ctrl_handler,
1191                                     &xtpg_hls_fg_ctrl, NULL);
1192        } else {
1193                xtpg->pattern =
1194                        v4l2_ctrl_new_std_menu_items(&xtpg->ctrl_handler,
1195                                                     &xtpg_ctrl_ops,
1196                                                     V4L2_CID_TEST_PATTERN,
1197                                                     npatterns - 1,
1198                                                     1, 9,
1199                                                     xtpg_pattern_strings);
1200
1201                for (i = 0; i < ARRAY_SIZE(xtpg_ctrls); i++)
1202                        v4l2_ctrl_new_custom(&xtpg->ctrl_handler,
1203                                             &xtpg_ctrls[i], NULL);
1204        }
1205
1206        for (i = 0; i < ARRAY_SIZE(xtpg_common_ctrls); i++)
1207                v4l2_ctrl_new_custom(&xtpg->ctrl_handler,
1208                                     &xtpg_common_ctrls[i], NULL);
1209
1210        if (xtpg->ctrl_handler.error) {
1211                dev_err(&pdev->dev, "failed to add controls\n");
1212                ret = xtpg->ctrl_handler.error;
1213                goto error;
1214        }
1215
1216        subdev->ctrl_handler = &xtpg->ctrl_handler;
1217
1218        xtpg_update_pattern_control(xtpg, true, true);
1219
1220        ret = v4l2_ctrl_handler_setup(&xtpg->ctrl_handler);
1221        if (ret < 0) {
1222                dev_err(&pdev->dev, "failed to set controls\n");
1223                goto error;
1224        }
1225
1226        platform_set_drvdata(pdev, xtpg);
1227
1228        xvip_print_version(&xtpg->xvip);
1229
1230        /* Initialize default frame interval */
1231        xtpg->fi_n = 1;
1232        xtpg->fi_d = 30;
1233
1234        ret = v4l2_async_register_subdev(subdev);
1235        if (ret < 0) {
1236                dev_err(&pdev->dev, "failed to register subdev\n");
1237                goto error;
1238        }
1239
1240        return 0;
1241
1242error:
1243        v4l2_ctrl_handler_free(&xtpg->ctrl_handler);
1244        media_entity_cleanup(&subdev->entity);
1245        xvtc_put(xtpg->vtc);
1246error_resource:
1247        xvip_cleanup_resources(&xtpg->xvip);
1248        return ret;
1249}
1250
1251static int xtpg_remove(struct platform_device *pdev)
1252{
1253        struct xtpg_device *xtpg = platform_get_drvdata(pdev);
1254        struct v4l2_subdev *subdev = &xtpg->xvip.subdev;
1255
1256        v4l2_async_unregister_subdev(subdev);
1257        v4l2_ctrl_handler_free(&xtpg->ctrl_handler);
1258        media_entity_cleanup(&subdev->entity);
1259
1260        xvip_cleanup_resources(&xtpg->xvip);
1261
1262        return 0;
1263}
1264
1265static SIMPLE_DEV_PM_OPS(xtpg_pm_ops, xtpg_pm_suspend, xtpg_pm_resume);
1266
1267static const struct of_device_id xtpg_of_id_table[] = {
1268        { .compatible = "xlnx,v-tpg-5.0" },
1269        { .compatible = "xlnx,v-tpg-7.0" },
1270        { .compatible = "xlnx,v-tpg-8.0" },
1271        { }
1272};
1273MODULE_DEVICE_TABLE(of, xtpg_of_id_table);
1274
1275static struct platform_driver xtpg_driver = {
1276        .driver = {
1277                .name           = "xilinx-tpg",
1278                .pm             = &xtpg_pm_ops,
1279                .of_match_table = xtpg_of_id_table,
1280        },
1281        .probe                  = xtpg_probe,
1282        .remove                 = xtpg_remove,
1283};
1284
1285module_platform_driver(xtpg_driver);
1286
1287MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
1288MODULE_DESCRIPTION("Xilinx Test Pattern Generator Driver");
1289MODULE_LICENSE("GPL v2");
1290