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-vip.h" 27#include "xilinx-vtc.h" 28 29#define XTPG_CTRL_STATUS_SLAVE_ERROR (1 << 16) 30#define XTPG_CTRL_IRQ_SLAVE_ERROR (1 << 16) 31 32#define XTPG_PATTERN_CONTROL 0x0100 33#define XTPG_PATTERN_MASK (0xf << 0) 34#define XTPG_PATTERN_CONTROL_CROSS_HAIRS (1 << 4) 35#define XTPG_PATTERN_CONTROL_MOVING_BOX (1 << 5) 36#define XTPG_PATTERN_CONTROL_COLOR_MASK_SHIFT 6 37#define XTPG_PATTERN_CONTROL_COLOR_MASK_MASK (0xf << 6) 38#define XTPG_PATTERN_CONTROL_STUCK_PIXEL (1 << 9) 39#define XTPG_PATTERN_CONTROL_NOISE (1 << 10) 40#define XTPG_PATTERN_CONTROL_MOTION (1 << 12) 41#define XTPG_MOTION_SPEED 0x0104 42#define XTPG_CROSS_HAIRS 0x0108 43#define XTPG_CROSS_HAIRS_ROW_SHIFT 0 44#define XTPG_CROSS_HAIRS_ROW_MASK (0xfff << 0) 45#define XTPG_CROSS_HAIRS_COLUMN_SHIFT 16 46#define XTPG_CROSS_HAIRS_COLUMN_MASK (0xfff << 16) 47#define XTPG_ZPLATE_HOR_CONTROL 0x010c 48#define XTPG_ZPLATE_VER_CONTROL 0x0110 49#define XTPG_ZPLATE_START_SHIFT 0 50#define XTPG_ZPLATE_START_MASK (0xffff << 0) 51#define XTPG_ZPLATE_SPEED_SHIFT 16 52#define XTPG_ZPLATE_SPEED_MASK (0xffff << 16) 53#define XTPG_BOX_SIZE 0x0114 54#define XTPG_BOX_COLOR 0x0118 55#define XTPG_STUCK_PIXEL_THRESH 0x011c 56#define XTPG_NOISE_GAIN 0x0120 57#define XTPG_BAYER_PHASE 0x0124 58#define XTPG_BAYER_PHASE_RGGB 0 59#define XTPG_BAYER_PHASE_GRBG 1 60#define XTPG_BAYER_PHASE_GBRG 2 61#define XTPG_BAYER_PHASE_BGGR 3 62#define XTPG_BAYER_PHASE_OFF 4 63 64/* 65 * The minimum blanking value is one clock cycle for the front porch, one clock 66 * cycle for the sync pulse and one clock cycle for the back porch. 67 */ 68#define XTPG_MIN_HBLANK 3 69#define XTPG_MAX_HBLANK (XVTC_MAX_HSIZE - XVIP_MIN_WIDTH) 70#define XTPG_MIN_VBLANK 3 71#define XTPG_MAX_VBLANK (XVTC_MAX_VSIZE - XVIP_MIN_HEIGHT) 72 73/** 74 * struct xtpg_device - Xilinx Test Pattern Generator device structure 75 * @xvip: Xilinx Video IP device 76 * @pads: media pads 77 * @npads: number of pads (1 or 2) 78 * @has_input: whether an input is connected to the sink pad 79 * @formats: active V4L2 media bus format for each pad 80 * @default_format: default V4L2 media bus format 81 * @vip_format: format information corresponding to the active format 82 * @bayer: boolean flag if TPG is set to any bayer format 83 * @ctrl_handler: control handler 84 * @hblank: horizontal blanking control 85 * @vblank: vertical blanking control 86 * @pattern: test pattern control 87 * @streaming: is the video stream active 88 * @vtc: video timing controller 89 * @vtmux_gpio: video timing mux GPIO 90 */ 91struct xtpg_device { 92 struct xvip_device xvip; 93 94 struct media_pad pads[2]; 95 unsigned int npads; 96 bool has_input; 97 98 struct v4l2_mbus_framefmt formats[2]; 99 struct v4l2_mbus_framefmt default_format; 100 const struct xvip_video_format *vip_format; 101 bool bayer; 102 103 struct v4l2_ctrl_handler ctrl_handler; 104 struct v4l2_ctrl *hblank; 105 struct v4l2_ctrl *vblank; 106 struct v4l2_ctrl *pattern; 107 bool streaming; 108 109 struct xvtc_device *vtc; 110 struct gpio_desc *vtmux_gpio; 111}; 112 113static inline struct xtpg_device *to_tpg(struct v4l2_subdev *subdev) 114{ 115 return container_of(subdev, struct xtpg_device, xvip.subdev); 116} 117 118static u32 xtpg_get_bayer_phase(unsigned int code) 119{ 120 switch (code) { 121 case MEDIA_BUS_FMT_SRGGB8_1X8: 122 return XTPG_BAYER_PHASE_RGGB; 123 case MEDIA_BUS_FMT_SGRBG8_1X8: 124 return XTPG_BAYER_PHASE_GRBG; 125 case MEDIA_BUS_FMT_SGBRG8_1X8: 126 return XTPG_BAYER_PHASE_GBRG; 127 case MEDIA_BUS_FMT_SBGGR8_1X8: 128 return XTPG_BAYER_PHASE_BGGR; 129 default: 130 return XTPG_BAYER_PHASE_OFF; 131 } 132} 133 134static void __xtpg_update_pattern_control(struct xtpg_device *xtpg, 135 bool passthrough, bool pattern) 136{ 137 u32 pattern_mask = (1 << (xtpg->pattern->maximum + 1)) - 1; 138 139 /* 140 * If the TPG has no sink pad or no input connected to its sink pad 141 * passthrough mode can't be enabled. 142 */ 143 if (xtpg->npads == 1 || !xtpg->has_input) 144 passthrough = false; 145 146 /* If passthrough mode is allowed unmask bit 0. */ 147 if (passthrough) 148 pattern_mask &= ~1; 149 150 /* If test pattern mode is allowed unmask all other bits. */ 151 if (pattern) 152 pattern_mask &= 1; 153 154 __v4l2_ctrl_modify_range(xtpg->pattern, 0, xtpg->pattern->maximum, 155 pattern_mask, pattern ? 9 : 0); 156} 157 158static void xtpg_update_pattern_control(struct xtpg_device *xtpg, 159 bool passthrough, bool pattern) 160{ 161 mutex_lock(xtpg->ctrl_handler.lock); 162 __xtpg_update_pattern_control(xtpg, passthrough, pattern); 163 mutex_unlock(xtpg->ctrl_handler.lock); 164} 165 166/* ----------------------------------------------------------------------------- 167 * V4L2 Subdevice Video Operations 168 */ 169 170static int xtpg_s_stream(struct v4l2_subdev *subdev, int enable) 171{ 172 struct xtpg_device *xtpg = to_tpg(subdev); 173 unsigned int width = xtpg->formats[0].width; 174 unsigned int height = xtpg->formats[0].height; 175 bool passthrough; 176 u32 bayer_phase; 177 178 if (!enable) { 179 xvip_stop(&xtpg->xvip); 180 if (xtpg->vtc) 181 xvtc_generator_stop(xtpg->vtc); 182 183 xtpg_update_pattern_control(xtpg, true, true); 184 xtpg->streaming = false; 185 return 0; 186 } 187 188 xvip_set_frame_size(&xtpg->xvip, &xtpg->formats[0]); 189 190 if (xtpg->vtc) { 191 struct xvtc_config config = { 192 .hblank_start = width, 193 .hsync_start = width + 1, 194 .vblank_start = height, 195 .vsync_start = height + 1, 196 }; 197 unsigned int htotal; 198 unsigned int vtotal; 199 200 htotal = min_t(unsigned int, XVTC_MAX_HSIZE, 201 v4l2_ctrl_g_ctrl(xtpg->hblank) + width); 202 vtotal = min_t(unsigned int, XVTC_MAX_VSIZE, 203 v4l2_ctrl_g_ctrl(xtpg->vblank) + height); 204 205 config.hsync_end = htotal - 1; 206 config.hsize = htotal; 207 config.vsync_end = vtotal - 1; 208 config.vsize = vtotal; 209 210 xvtc_generator_start(xtpg->vtc, &config); 211 } 212 213 /* 214 * Configure the bayer phase and video timing mux based on the 215 * operation mode (passthrough or test pattern generation). The test 216 * pattern can be modified by the control set handler, we thus need to 217 * take the control lock here to avoid races. 218 */ 219 mutex_lock(xtpg->ctrl_handler.lock); 220 221 xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL, 222 XTPG_PATTERN_MASK, xtpg->pattern->cur.val); 223 224 /* 225 * Switching between passthrough and test pattern generation modes isn't 226 * allowed during streaming, update the control range accordingly. 227 */ 228 passthrough = xtpg->pattern->cur.val == 0; 229 __xtpg_update_pattern_control(xtpg, passthrough, !passthrough); 230 231 xtpg->streaming = true; 232 233 mutex_unlock(xtpg->ctrl_handler.lock); 234 235 /* 236 * For TPG v5.0, the bayer phase needs to be off for the pass through 237 * mode, otherwise the external input would be subsampled. 238 */ 239 bayer_phase = passthrough ? XTPG_BAYER_PHASE_OFF 240 : xtpg_get_bayer_phase(xtpg->formats[0].code); 241 xvip_write(&xtpg->xvip, XTPG_BAYER_PHASE, bayer_phase); 242 243 if (xtpg->vtmux_gpio) 244 gpiod_set_value_cansleep(xtpg->vtmux_gpio, !passthrough); 245 246 xvip_start(&xtpg->xvip); 247 248 return 0; 249} 250 251/* ----------------------------------------------------------------------------- 252 * V4L2 Subdevice Pad Operations 253 */ 254 255static struct v4l2_mbus_framefmt * 256__xtpg_get_pad_format(struct xtpg_device *xtpg, 257 struct v4l2_subdev_pad_config *cfg, 258 unsigned int pad, u32 which) 259{ 260 switch (which) { 261 case V4L2_SUBDEV_FORMAT_TRY: 262 return v4l2_subdev_get_try_format(&xtpg->xvip.subdev, cfg, pad); 263 case V4L2_SUBDEV_FORMAT_ACTIVE: 264 return &xtpg->formats[pad]; 265 default: 266 return NULL; 267 } 268} 269 270static int xtpg_get_format(struct v4l2_subdev *subdev, 271 struct v4l2_subdev_pad_config *cfg, 272 struct v4l2_subdev_format *fmt) 273{ 274 struct xtpg_device *xtpg = to_tpg(subdev); 275 276 fmt->format = *__xtpg_get_pad_format(xtpg, cfg, fmt->pad, fmt->which); 277 278 return 0; 279} 280 281static int xtpg_set_format(struct v4l2_subdev *subdev, 282 struct v4l2_subdev_pad_config *cfg, 283 struct v4l2_subdev_format *fmt) 284{ 285 struct xtpg_device *xtpg = to_tpg(subdev); 286 struct v4l2_mbus_framefmt *__format; 287 u32 bayer_phase; 288 289 __format = __xtpg_get_pad_format(xtpg, cfg, fmt->pad, fmt->which); 290 291 /* In two pads mode the source pad format is always identical to the 292 * sink pad format. 293 */ 294 if (xtpg->npads == 2 && fmt->pad == 1) { 295 fmt->format = *__format; 296 return 0; 297 } 298 299 /* Bayer phase is configurable at runtime */ 300 if (xtpg->bayer) { 301 bayer_phase = xtpg_get_bayer_phase(fmt->format.code); 302 if (bayer_phase != XTPG_BAYER_PHASE_OFF) 303 __format->code = fmt->format.code; 304 } 305 306 xvip_set_format_size(__format, fmt); 307 308 fmt->format = *__format; 309 310 /* Propagate the format to the source pad. */ 311 if (xtpg->npads == 2) { 312 __format = __xtpg_get_pad_format(xtpg, cfg, 1, fmt->which); 313 *__format = fmt->format; 314 } 315 316 return 0; 317} 318 319/* ----------------------------------------------------------------------------- 320 * V4L2 Subdevice Operations 321 */ 322 323static int xtpg_enum_frame_size(struct v4l2_subdev *subdev, 324 struct v4l2_subdev_pad_config *cfg, 325 struct v4l2_subdev_frame_size_enum *fse) 326{ 327 struct v4l2_mbus_framefmt *format; 328 329 format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad); 330 331 if (fse->index || fse->code != format->code) 332 return -EINVAL; 333 334 /* Min / max values for pad 0 is always fixed in both one and two pads 335 * modes. In two pads mode, the source pad(= 1) size is identical to 336 * the sink pad size */ 337 if (fse->pad == 0) { 338 fse->min_width = XVIP_MIN_WIDTH; 339 fse->max_width = XVIP_MAX_WIDTH; 340 fse->min_height = XVIP_MIN_HEIGHT; 341 fse->max_height = XVIP_MAX_HEIGHT; 342 } else { 343 fse->min_width = format->width; 344 fse->max_width = format->width; 345 fse->min_height = format->height; 346 fse->max_height = format->height; 347 } 348 349 return 0; 350} 351 352static int xtpg_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) 353{ 354 struct xtpg_device *xtpg = to_tpg(subdev); 355 struct v4l2_mbus_framefmt *format; 356 357 format = v4l2_subdev_get_try_format(subdev, fh->pad, 0); 358 *format = xtpg->default_format; 359 360 if (xtpg->npads == 2) { 361 format = v4l2_subdev_get_try_format(subdev, fh->pad, 1); 362 *format = xtpg->default_format; 363 } 364 365 return 0; 366} 367 368static int xtpg_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) 369{ 370 return 0; 371} 372 373static int xtpg_s_ctrl(struct v4l2_ctrl *ctrl) 374{ 375 struct xtpg_device *xtpg = container_of(ctrl->handler, 376 struct xtpg_device, 377 ctrl_handler); 378 switch (ctrl->id) { 379 case V4L2_CID_TEST_PATTERN: 380 xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL, 381 XTPG_PATTERN_MASK, ctrl->val); 382 return 0; 383 case V4L2_CID_XILINX_TPG_CROSS_HAIRS: 384 xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL, 385 XTPG_PATTERN_CONTROL_CROSS_HAIRS, ctrl->val); 386 return 0; 387 case V4L2_CID_XILINX_TPG_MOVING_BOX: 388 xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL, 389 XTPG_PATTERN_CONTROL_MOVING_BOX, ctrl->val); 390 return 0; 391 case V4L2_CID_XILINX_TPG_COLOR_MASK: 392 xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL, 393 XTPG_PATTERN_CONTROL_COLOR_MASK_MASK, 394 ctrl->val << 395 XTPG_PATTERN_CONTROL_COLOR_MASK_SHIFT); 396 return 0; 397 case V4L2_CID_XILINX_TPG_STUCK_PIXEL: 398 xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL, 399 XTPG_PATTERN_CONTROL_STUCK_PIXEL, ctrl->val); 400 return 0; 401 case V4L2_CID_XILINX_TPG_NOISE: 402 xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL, 403 XTPG_PATTERN_CONTROL_NOISE, ctrl->val); 404 return 0; 405 case V4L2_CID_XILINX_TPG_MOTION: 406 xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL, 407 XTPG_PATTERN_CONTROL_MOTION, ctrl->val); 408 return 0; 409 case V4L2_CID_XILINX_TPG_MOTION_SPEED: 410 xvip_write(&xtpg->xvip, XTPG_MOTION_SPEED, ctrl->val); 411 return 0; 412 case V4L2_CID_XILINX_TPG_CROSS_HAIR_ROW: 413 xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS, 414 XTPG_CROSS_HAIRS_ROW_MASK, 415 ctrl->val << XTPG_CROSS_HAIRS_ROW_SHIFT); 416 return 0; 417 case V4L2_CID_XILINX_TPG_CROSS_HAIR_COLUMN: 418 xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS, 419 XTPG_CROSS_HAIRS_COLUMN_MASK, 420 ctrl->val << XTPG_CROSS_HAIRS_COLUMN_SHIFT); 421 return 0; 422 case V4L2_CID_XILINX_TPG_ZPLATE_HOR_START: 423 xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL, 424 XTPG_ZPLATE_START_MASK, 425 ctrl->val << XTPG_ZPLATE_START_SHIFT); 426 return 0; 427 case V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED: 428 xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL, 429 XTPG_ZPLATE_SPEED_MASK, 430 ctrl->val << XTPG_ZPLATE_SPEED_SHIFT); 431 return 0; 432 case V4L2_CID_XILINX_TPG_ZPLATE_VER_START: 433 xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL, 434 XTPG_ZPLATE_START_MASK, 435 ctrl->val << XTPG_ZPLATE_START_SHIFT); 436 return 0; 437 case V4L2_CID_XILINX_TPG_ZPLATE_VER_SPEED: 438 xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL, 439 XTPG_ZPLATE_SPEED_MASK, 440 ctrl->val << XTPG_ZPLATE_SPEED_SHIFT); 441 return 0; 442 case V4L2_CID_XILINX_TPG_BOX_SIZE: 443 xvip_write(&xtpg->xvip, XTPG_BOX_SIZE, ctrl->val); 444 return 0; 445 case V4L2_CID_XILINX_TPG_BOX_COLOR: 446 xvip_write(&xtpg->xvip, XTPG_BOX_COLOR, ctrl->val); 447 return 0; 448 case V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH: 449 xvip_write(&xtpg->xvip, XTPG_STUCK_PIXEL_THRESH, ctrl->val); 450 return 0; 451 case V4L2_CID_XILINX_TPG_NOISE_GAIN: 452 xvip_write(&xtpg->xvip, XTPG_NOISE_GAIN, ctrl->val); 453 return 0; 454 } 455 456 return 0; 457} 458 459static const struct v4l2_ctrl_ops xtpg_ctrl_ops = { 460 .s_ctrl = xtpg_s_ctrl, 461}; 462 463static struct v4l2_subdev_core_ops xtpg_core_ops = { 464}; 465 466static struct v4l2_subdev_video_ops xtpg_video_ops = { 467 .s_stream = xtpg_s_stream, 468}; 469 470static struct v4l2_subdev_pad_ops xtpg_pad_ops = { 471 .enum_mbus_code = xvip_enum_mbus_code, 472 .enum_frame_size = xtpg_enum_frame_size, 473 .get_fmt = xtpg_get_format, 474 .set_fmt = xtpg_set_format, 475}; 476 477static struct v4l2_subdev_ops xtpg_ops = { 478 .core = &xtpg_core_ops, 479 .video = &xtpg_video_ops, 480 .pad = &xtpg_pad_ops, 481}; 482 483static const struct v4l2_subdev_internal_ops xtpg_internal_ops = { 484 .open = xtpg_open, 485 .close = xtpg_close, 486}; 487 488/* 489 * Control Config 490 */ 491 492static const char *const xtpg_pattern_strings[] = { 493 "Passthrough", 494 "Horizontal Ramp", 495 "Vertical Ramp", 496 "Temporal Ramp", 497 "Solid Red", 498 "Solid Green", 499 "Solid Blue", 500 "Solid Black", 501 "Solid White", 502 "Color Bars", 503 "Zone Plate", 504 "Tartan Color Bars", 505 "Cross Hatch", 506 "None", 507 "Vertical/Horizontal Ramps", 508 "Black/White Checker Board", 509}; 510 511static struct v4l2_ctrl_config xtpg_ctrls[] = { 512 { 513 .ops = &xtpg_ctrl_ops, 514 .id = V4L2_CID_XILINX_TPG_CROSS_HAIRS, 515 .name = "Test Pattern: Cross Hairs", 516 .type = V4L2_CTRL_TYPE_BOOLEAN, 517 .min = false, 518 .max = true, 519 .step = 1, 520 .def = 0, 521 }, { 522 .ops = &xtpg_ctrl_ops, 523 .id = V4L2_CID_XILINX_TPG_MOVING_BOX, 524 .name = "Test Pattern: Moving Box", 525 .type = V4L2_CTRL_TYPE_BOOLEAN, 526 .min = false, 527 .max = true, 528 .step = 1, 529 .def = 0, 530 }, { 531 .ops = &xtpg_ctrl_ops, 532 .id = V4L2_CID_XILINX_TPG_COLOR_MASK, 533 .name = "Test Pattern: Color Mask", 534 .type = V4L2_CTRL_TYPE_BITMASK, 535 .min = 0, 536 .max = 0xf, 537 .def = 0, 538 }, { 539 .ops = &xtpg_ctrl_ops, 540 .id = V4L2_CID_XILINX_TPG_STUCK_PIXEL, 541 .name = "Test Pattern: Stuck Pixel", 542 .type = V4L2_CTRL_TYPE_BOOLEAN, 543 .min = false, 544 .max = true, 545 .step = 1, 546 .def = 0, 547 }, { 548 .ops = &xtpg_ctrl_ops, 549 .id = V4L2_CID_XILINX_TPG_NOISE, 550 .name = "Test Pattern: Noise", 551 .type = V4L2_CTRL_TYPE_BOOLEAN, 552 .min = false, 553 .max = true, 554 .step = 1, 555 .def = 0, 556 }, { 557 .ops = &xtpg_ctrl_ops, 558 .id = V4L2_CID_XILINX_TPG_MOTION, 559 .name = "Test Pattern: Motion", 560 .type = V4L2_CTRL_TYPE_BOOLEAN, 561 .min = false, 562 .max = true, 563 .step = 1, 564 .def = 0, 565 }, { 566 .ops = &xtpg_ctrl_ops, 567 .id = V4L2_CID_XILINX_TPG_MOTION_SPEED, 568 .name = "Test Pattern: Motion Speed", 569 .type = V4L2_CTRL_TYPE_INTEGER, 570 .min = 0, 571 .max = (1 << 8) - 1, 572 .step = 1, 573 .def = 4, 574 .flags = V4L2_CTRL_FLAG_SLIDER, 575 }, { 576 .ops = &xtpg_ctrl_ops, 577 .id = V4L2_CID_XILINX_TPG_CROSS_HAIR_ROW, 578 .name = "Test Pattern: Cross Hairs Row", 579 .type = V4L2_CTRL_TYPE_INTEGER, 580 .min = 0, 581 .max = (1 << 12) - 1, 582 .step = 1, 583 .def = 0x64, 584 .flags = V4L2_CTRL_FLAG_SLIDER, 585 }, { 586 .ops = &xtpg_ctrl_ops, 587 .id = V4L2_CID_XILINX_TPG_CROSS_HAIR_COLUMN, 588 .name = "Test Pattern: Cross Hairs Column", 589 .type = V4L2_CTRL_TYPE_INTEGER, 590 .min = 0, 591 .max = (1 << 12) - 1, 592 .step = 1, 593 .def = 0x64, 594 .flags = V4L2_CTRL_FLAG_SLIDER, 595 }, { 596 .ops = &xtpg_ctrl_ops, 597 .id = V4L2_CID_XILINX_TPG_ZPLATE_HOR_START, 598 .name = "Test Pattern: Zplate Horizontal Start Pos", 599 .type = V4L2_CTRL_TYPE_INTEGER, 600 .min = 0, 601 .max = (1 << 16) - 1, 602 .step = 1, 603 .def = 0x1e, 604 .flags = V4L2_CTRL_FLAG_SLIDER, 605 }, { 606 .ops = &xtpg_ctrl_ops, 607 .id = V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED, 608 .name = "Test Pattern: Zplate Horizontal Speed", 609 .type = V4L2_CTRL_TYPE_INTEGER, 610 .min = 0, 611 .max = (1 << 16) - 1, 612 .step = 1, 613 .def = 0, 614 .flags = V4L2_CTRL_FLAG_SLIDER, 615 }, { 616 .ops = &xtpg_ctrl_ops, 617 .id = V4L2_CID_XILINX_TPG_ZPLATE_VER_START, 618 .name = "Test Pattern: Zplate Vertical Start Pos", 619 .type = V4L2_CTRL_TYPE_INTEGER, 620 .min = 0, 621 .max = (1 << 16) - 1, 622 .step = 1, 623 .def = 1, 624 .flags = V4L2_CTRL_FLAG_SLIDER, 625 }, { 626 .ops = &xtpg_ctrl_ops, 627 .id = V4L2_CID_XILINX_TPG_ZPLATE_VER_SPEED, 628 .name = "Test Pattern: Zplate Vertical Speed", 629 .type = V4L2_CTRL_TYPE_INTEGER, 630 .min = 0, 631 .max = (1 << 16) - 1, 632 .step = 1, 633 .def = 0, 634 .flags = V4L2_CTRL_FLAG_SLIDER, 635 }, { 636 .ops = &xtpg_ctrl_ops, 637 .id = V4L2_CID_XILINX_TPG_BOX_SIZE, 638 .name = "Test Pattern: Box Size", 639 .type = V4L2_CTRL_TYPE_INTEGER, 640 .min = 0, 641 .max = (1 << 12) - 1, 642 .step = 1, 643 .def = 0x32, 644 .flags = V4L2_CTRL_FLAG_SLIDER, 645 }, { 646 .ops = &xtpg_ctrl_ops, 647 .id = V4L2_CID_XILINX_TPG_BOX_COLOR, 648 .name = "Test Pattern: Box Color(RGB)", 649 .type = V4L2_CTRL_TYPE_INTEGER, 650 .min = 0, 651 .max = (1 << 24) - 1, 652 .step = 1, 653 .def = 0, 654 }, { 655 .ops = &xtpg_ctrl_ops, 656 .id = V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH, 657 .name = "Test Pattern: Stuck Pixel threshold", 658 .type = V4L2_CTRL_TYPE_INTEGER, 659 .min = 0, 660 .max = (1 << 16) - 1, 661 .step = 1, 662 .def = 0, 663 .flags = V4L2_CTRL_FLAG_SLIDER, 664 }, { 665 .ops = &xtpg_ctrl_ops, 666 .id = V4L2_CID_XILINX_TPG_NOISE_GAIN, 667 .name = "Test Pattern: Noise Gain", 668 .type = V4L2_CTRL_TYPE_INTEGER, 669 .min = 0, 670 .max = (1 << 8) - 1, 671 .step = 1, 672 .def = 0, 673 .flags = V4L2_CTRL_FLAG_SLIDER, 674 }, 675}; 676 677/* ----------------------------------------------------------------------------- 678 * Media Operations 679 */ 680 681static const struct media_entity_operations xtpg_media_ops = { 682 .link_validate = v4l2_subdev_link_validate, 683}; 684 685/* ----------------------------------------------------------------------------- 686 * Power Management 687 */ 688 689static int __maybe_unused xtpg_pm_suspend(struct device *dev) 690{ 691 struct xtpg_device *xtpg = dev_get_drvdata(dev); 692 693 xvip_suspend(&xtpg->xvip); 694 695 return 0; 696} 697 698static int __maybe_unused xtpg_pm_resume(struct device *dev) 699{ 700 struct xtpg_device *xtpg = dev_get_drvdata(dev); 701 702 xvip_resume(&xtpg->xvip); 703 704 return 0; 705} 706 707/* ----------------------------------------------------------------------------- 708 * Platform Device Driver 709 */ 710 711static int xtpg_parse_of(struct xtpg_device *xtpg) 712{ 713 struct device *dev = xtpg->xvip.dev; 714 struct device_node *node = xtpg->xvip.dev->of_node; 715 struct device_node *ports; 716 struct device_node *port; 717 unsigned int nports = 0; 718 bool has_endpoint = false; 719 720 ports = of_get_child_by_name(node, "ports"); 721 if (ports == NULL) 722 ports = node; 723 724 for_each_child_of_node(ports, port) { 725 const struct xvip_video_format *format; 726 struct device_node *endpoint; 727 728 if (!port->name || of_node_cmp(port->name, "port")) 729 continue; 730 731 format = xvip_of_get_format(port); 732 if (IS_ERR(format)) { 733 dev_err(dev, "invalid format in DT"); 734 return PTR_ERR(format); 735 } 736 737 /* Get and check the format description */ 738 if (!xtpg->vip_format) { 739 xtpg->vip_format = format; 740 } else if (xtpg->vip_format != format) { 741 dev_err(dev, "in/out format mismatch in DT"); 742 return -EINVAL; 743 } 744 745 if (nports == 0) { 746 endpoint = of_get_next_child(port, NULL); 747 if (endpoint) 748 has_endpoint = true; 749 of_node_put(endpoint); 750 } 751 752 /* Count the number of ports. */ 753 nports++; 754 } 755 756 if (nports != 1 && nports != 2) { 757 dev_err(dev, "invalid number of ports %u\n", nports); 758 return -EINVAL; 759 } 760 761 xtpg->npads = nports; 762 if (nports == 2 && has_endpoint) 763 xtpg->has_input = true; 764 765 return 0; 766} 767 768static int xtpg_probe(struct platform_device *pdev) 769{ 770 struct v4l2_subdev *subdev; 771 struct xtpg_device *xtpg; 772 u32 i, bayer_phase; 773 int ret; 774 775 xtpg = devm_kzalloc(&pdev->dev, sizeof(*xtpg), GFP_KERNEL); 776 if (!xtpg) 777 return -ENOMEM; 778 779 xtpg->xvip.dev = &pdev->dev; 780 781 ret = xtpg_parse_of(xtpg); 782 if (ret < 0) 783 return ret; 784 785 ret = xvip_init_resources(&xtpg->xvip); 786 if (ret < 0) 787 return ret; 788 789 xtpg->vtmux_gpio = devm_gpiod_get_optional(&pdev->dev, "timing", 790 GPIOD_OUT_HIGH); 791 if (IS_ERR(xtpg->vtmux_gpio)) { 792 ret = PTR_ERR(xtpg->vtmux_gpio); 793 goto error_resource; 794 } 795 796 xtpg->vtc = xvtc_of_get(pdev->dev.of_node); 797 if (IS_ERR(xtpg->vtc)) { 798 ret = PTR_ERR(xtpg->vtc); 799 goto error_resource; 800 } 801 802 /* Reset and initialize the core */ 803 xvip_reset(&xtpg->xvip); 804 805 /* Initialize V4L2 subdevice and media entity. Pad numbers depend on the 806 * number of pads. 807 */ 808 if (xtpg->npads == 2) { 809 xtpg->pads[0].flags = MEDIA_PAD_FL_SINK; 810 xtpg->pads[1].flags = MEDIA_PAD_FL_SOURCE; 811 } else { 812 xtpg->pads[0].flags = MEDIA_PAD_FL_SOURCE; 813 } 814 815 /* Initialize the default format */ 816 xtpg->default_format.code = xtpg->vip_format->code; 817 xtpg->default_format.field = V4L2_FIELD_NONE; 818 xtpg->default_format.colorspace = V4L2_COLORSPACE_SRGB; 819 xvip_get_frame_size(&xtpg->xvip, &xtpg->default_format); 820 821 bayer_phase = xtpg_get_bayer_phase(xtpg->vip_format->code); 822 if (bayer_phase != XTPG_BAYER_PHASE_OFF) 823 xtpg->bayer = true; 824 825 xtpg->formats[0] = xtpg->default_format; 826 if (xtpg->npads == 2) 827 xtpg->formats[1] = xtpg->default_format; 828 829 /* Initialize V4L2 subdevice and media entity */ 830 subdev = &xtpg->xvip.subdev; 831 v4l2_subdev_init(subdev, &xtpg_ops); 832 subdev->dev = &pdev->dev; 833 subdev->internal_ops = &xtpg_internal_ops; 834 strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name)); 835 v4l2_set_subdevdata(subdev, xtpg); 836 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 837 subdev->entity.ops = &xtpg_media_ops; 838 839 ret = media_entity_init(&subdev->entity, xtpg->npads, xtpg->pads, 0); 840 if (ret < 0) 841 goto error; 842 843 v4l2_ctrl_handler_init(&xtpg->ctrl_handler, 3 + ARRAY_SIZE(xtpg_ctrls)); 844 845 xtpg->vblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops, 846 V4L2_CID_VBLANK, XTPG_MIN_VBLANK, 847 XTPG_MAX_VBLANK, 1, 100); 848 xtpg->hblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops, 849 V4L2_CID_HBLANK, XTPG_MIN_HBLANK, 850 XTPG_MAX_HBLANK, 1, 100); 851 xtpg->pattern = v4l2_ctrl_new_std_menu_items(&xtpg->ctrl_handler, 852 &xtpg_ctrl_ops, V4L2_CID_TEST_PATTERN, 853 ARRAY_SIZE(xtpg_pattern_strings) - 1, 854 1, 9, xtpg_pattern_strings); 855 856 for (i = 0; i < ARRAY_SIZE(xtpg_ctrls); i++) 857 v4l2_ctrl_new_custom(&xtpg->ctrl_handler, &xtpg_ctrls[i], NULL); 858 859 if (xtpg->ctrl_handler.error) { 860 dev_err(&pdev->dev, "failed to add controls\n"); 861 ret = xtpg->ctrl_handler.error; 862 goto error; 863 } 864 subdev->ctrl_handler = &xtpg->ctrl_handler; 865 866 xtpg_update_pattern_control(xtpg, true, true); 867 868 ret = v4l2_ctrl_handler_setup(&xtpg->ctrl_handler); 869 if (ret < 0) { 870 dev_err(&pdev->dev, "failed to set controls\n"); 871 goto error; 872 } 873 874 platform_set_drvdata(pdev, xtpg); 875 876 xvip_print_version(&xtpg->xvip); 877 878 ret = v4l2_async_register_subdev(subdev); 879 if (ret < 0) { 880 dev_err(&pdev->dev, "failed to register subdev\n"); 881 goto error; 882 } 883 884 return 0; 885 886error: 887 v4l2_ctrl_handler_free(&xtpg->ctrl_handler); 888 media_entity_cleanup(&subdev->entity); 889 xvtc_put(xtpg->vtc); 890error_resource: 891 xvip_cleanup_resources(&xtpg->xvip); 892 return ret; 893} 894 895static int xtpg_remove(struct platform_device *pdev) 896{ 897 struct xtpg_device *xtpg = platform_get_drvdata(pdev); 898 struct v4l2_subdev *subdev = &xtpg->xvip.subdev; 899 900 v4l2_async_unregister_subdev(subdev); 901 v4l2_ctrl_handler_free(&xtpg->ctrl_handler); 902 media_entity_cleanup(&subdev->entity); 903 904 xvip_cleanup_resources(&xtpg->xvip); 905 906 return 0; 907} 908 909static SIMPLE_DEV_PM_OPS(xtpg_pm_ops, xtpg_pm_suspend, xtpg_pm_resume); 910 911static const struct of_device_id xtpg_of_id_table[] = { 912 { .compatible = "xlnx,v-tpg-5.0" }, 913 { } 914}; 915MODULE_DEVICE_TABLE(of, xtpg_of_id_table); 916 917static struct platform_driver xtpg_driver = { 918 .driver = { 919 .name = "xilinx-tpg", 920 .pm = &xtpg_pm_ops, 921 .of_match_table = xtpg_of_id_table, 922 }, 923 .probe = xtpg_probe, 924 .remove = xtpg_remove, 925}; 926 927module_platform_driver(xtpg_driver); 928 929MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 930MODULE_DESCRIPTION("Xilinx Test Pattern Generator Driver"); 931MODULE_LICENSE("GPL v2"); 932