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

source code of linux/drivers/media/platform/xilinx/xilinx-tpg.c