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