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 <[email protected]>
9 * Laurent Pinchart <[email protected]>
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/of_graph.h>
17 #include <linux/platform_device.h>
18 #include <linux/xilinx-v4l2-controls.h>
19
20 #include <media/v4l2-async.h>
21 #include <media/v4l2-ctrls.h>
22 #include <media/v4l2-subdev.h>
23
24 #include "xilinx-vip.h"
25 #include "xilinx-vtc.h"
26
27 #define XTPG_CTRL_STATUS_SLAVE_ERROR (1 << 16)
28 #define XTPG_CTRL_IRQ_SLAVE_ERROR (1 << 16)
29
30 #define XTPG_PATTERN_CONTROL 0x0100
31 #define XTPG_PATTERN_MASK (0xf << 0)
32 #define XTPG_PATTERN_CONTROL_CROSS_HAIRS (1 << 4)
33 #define XTPG_PATTERN_CONTROL_MOVING_BOX (1 << 5)
34 #define XTPG_PATTERN_CONTROL_COLOR_MASK_SHIFT 6
35 #define XTPG_PATTERN_CONTROL_COLOR_MASK_MASK (0xf << 6)
36 #define XTPG_PATTERN_CONTROL_STUCK_PIXEL (1 << 9)
37 #define XTPG_PATTERN_CONTROL_NOISE (1 << 10)
38 #define XTPG_PATTERN_CONTROL_MOTION (1 << 12)
39 #define XTPG_MOTION_SPEED 0x0104
40 #define XTPG_CROSS_HAIRS 0x0108
41 #define XTPG_CROSS_HAIRS_ROW_SHIFT 0
42 #define XTPG_CROSS_HAIRS_ROW_MASK (0xfff << 0)
43 #define XTPG_CROSS_HAIRS_COLUMN_SHIFT 16
44 #define XTPG_CROSS_HAIRS_COLUMN_MASK (0xfff << 16)
45 #define XTPG_ZPLATE_HOR_CONTROL 0x010c
46 #define XTPG_ZPLATE_VER_CONTROL 0x0110
47 #define XTPG_ZPLATE_START_SHIFT 0
48 #define XTPG_ZPLATE_START_MASK (0xffff << 0)
49 #define XTPG_ZPLATE_SPEED_SHIFT 16
50 #define XTPG_ZPLATE_SPEED_MASK (0xffff << 16)
51 #define XTPG_BOX_SIZE 0x0114
52 #define XTPG_BOX_COLOR 0x0118
53 #define XTPG_STUCK_PIXEL_THRESH 0x011c
54 #define XTPG_NOISE_GAIN 0x0120
55 #define XTPG_BAYER_PHASE 0x0124
56 #define XTPG_BAYER_PHASE_RGGB 0
57 #define XTPG_BAYER_PHASE_GRBG 1
58 #define XTPG_BAYER_PHASE_GBRG 2
59 #define XTPG_BAYER_PHASE_BGGR 3
60 #define XTPG_BAYER_PHASE_OFF 4
61
62 /*
63 * The minimum blanking value is one clock cycle for the front porch, one clock
64 * cycle for the sync pulse and one clock cycle for the back porch.
65 */
66 #define XTPG_MIN_HBLANK 3
67 #define XTPG_MAX_HBLANK (XVTC_MAX_HSIZE - XVIP_MIN_WIDTH)
68 #define XTPG_MIN_VBLANK 3
69 #define XTPG_MAX_VBLANK (XVTC_MAX_VSIZE - XVIP_MIN_HEIGHT)
70
71 /**
72 * struct xtpg_device - Xilinx Test Pattern Generator device structure
73 * @xvip: Xilinx Video IP device
74 * @pads: media pads
75 * @npads: number of pads (1 or 2)
76 * @has_input: whether an input is connected to the sink pad
77 * @formats: active V4L2 media bus format for each pad
78 * @default_format: default V4L2 media bus format
79 * @vip_format: format information corresponding to the active format
80 * @bayer: boolean flag if TPG is set to any bayer format
81 * @ctrl_handler: control handler
82 * @hblank: horizontal blanking control
83 * @vblank: vertical blanking control
84 * @pattern: test pattern control
85 * @streaming: is the video stream active
86 * @vtc: video timing controller
87 * @vtmux_gpio: video timing mux GPIO
88 */
89 struct xtpg_device {
90 struct xvip_device xvip;
91
92 struct media_pad pads[2];
93 unsigned int npads;
94 bool has_input;
95
96 struct v4l2_mbus_framefmt formats[2];
97 struct v4l2_mbus_framefmt default_format;
98 const struct xvip_video_format *vip_format;
99 bool bayer;
100
101 struct v4l2_ctrl_handler ctrl_handler;
102 struct v4l2_ctrl *hblank;
103 struct v4l2_ctrl *vblank;
104 struct v4l2_ctrl *pattern;
105 bool streaming;
106
107 struct xvtc_device *vtc;
108 struct gpio_desc *vtmux_gpio;
109 };
110
to_tpg(struct v4l2_subdev * subdev)111 static inline struct xtpg_device *to_tpg(struct v4l2_subdev *subdev)
112 {
113 return container_of(subdev, struct xtpg_device, xvip.subdev);
114 }
115
xtpg_get_bayer_phase(unsigned int code)116 static u32 xtpg_get_bayer_phase(unsigned int code)
117 {
118 switch (code) {
119 case MEDIA_BUS_FMT_SRGGB8_1X8:
120 return XTPG_BAYER_PHASE_RGGB;
121 case MEDIA_BUS_FMT_SGRBG8_1X8:
122 return XTPG_BAYER_PHASE_GRBG;
123 case MEDIA_BUS_FMT_SGBRG8_1X8:
124 return XTPG_BAYER_PHASE_GBRG;
125 case MEDIA_BUS_FMT_SBGGR8_1X8:
126 return XTPG_BAYER_PHASE_BGGR;
127 default:
128 return XTPG_BAYER_PHASE_OFF;
129 }
130 }
131
__xtpg_update_pattern_control(struct xtpg_device * xtpg,bool passthrough,bool pattern)132 static void __xtpg_update_pattern_control(struct xtpg_device *xtpg,
133 bool passthrough, bool pattern)
134 {
135 u32 pattern_mask = (1 << (xtpg->pattern->maximum + 1)) - 1;
136
137 /*
138 * If the TPG has no sink pad or no input connected to its sink pad
139 * passthrough mode can't be enabled.
140 */
141 if (xtpg->npads == 1 || !xtpg->has_input)
142 passthrough = false;
143
144 /* If passthrough mode is allowed unmask bit 0. */
145 if (passthrough)
146 pattern_mask &= ~1;
147
148 /* If test pattern mode is allowed unmask all other bits. */
149 if (pattern)
150 pattern_mask &= 1;
151
152 __v4l2_ctrl_modify_range(xtpg->pattern, 0, xtpg->pattern->maximum,
153 pattern_mask, pattern ? 9 : 0);
154 }
155
xtpg_update_pattern_control(struct xtpg_device * xtpg,bool passthrough,bool pattern)156 static void xtpg_update_pattern_control(struct xtpg_device *xtpg,
157 bool passthrough, bool pattern)
158 {
159 mutex_lock(xtpg->ctrl_handler.lock);
160 __xtpg_update_pattern_control(xtpg, passthrough, pattern);
161 mutex_unlock(xtpg->ctrl_handler.lock);
162 }
163
164 /* -----------------------------------------------------------------------------
165 * V4L2 Subdevice Video Operations
166 */
167
xtpg_s_stream(struct v4l2_subdev * subdev,int enable)168 static int xtpg_s_stream(struct v4l2_subdev *subdev, int enable)
169 {
170 struct xtpg_device *xtpg = to_tpg(subdev);
171 unsigned int width = xtpg->formats[0].width;
172 unsigned int height = xtpg->formats[0].height;
173 bool passthrough;
174 u32 bayer_phase;
175
176 if (!enable) {
177 xvip_stop(&xtpg->xvip);
178 if (xtpg->vtc)
179 xvtc_generator_stop(xtpg->vtc);
180
181 xtpg_update_pattern_control(xtpg, true, true);
182 xtpg->streaming = false;
183 return 0;
184 }
185
186 xvip_set_frame_size(&xtpg->xvip, &xtpg->formats[0]);
187
188 if (xtpg->vtc) {
189 struct xvtc_config config = {
190 .hblank_start = width,
191 .hsync_start = width + 1,
192 .vblank_start = height,
193 .vsync_start = height + 1,
194 };
195 unsigned int htotal;
196 unsigned int vtotal;
197
198 htotal = min_t(unsigned int, XVTC_MAX_HSIZE,
199 v4l2_ctrl_g_ctrl(xtpg->hblank) + width);
200 vtotal = min_t(unsigned int, XVTC_MAX_VSIZE,
201 v4l2_ctrl_g_ctrl(xtpg->vblank) + height);
202
203 config.hsync_end = htotal - 1;
204 config.hsize = htotal;
205 config.vsync_end = vtotal - 1;
206 config.vsize = vtotal;
207
208 xvtc_generator_start(xtpg->vtc, &config);
209 }
210
211 /*
212 * Configure the bayer phase and video timing mux based on the
213 * operation mode (passthrough or test pattern generation). The test
214 * pattern can be modified by the control set handler, we thus need to
215 * take the control lock here to avoid races.
216 */
217 mutex_lock(xtpg->ctrl_handler.lock);
218
219 xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
220 XTPG_PATTERN_MASK, xtpg->pattern->cur.val);
221
222 /*
223 * Switching between passthrough and test pattern generation modes isn't
224 * allowed during streaming, update the control range accordingly.
225 */
226 passthrough = xtpg->pattern->cur.val == 0;
227 __xtpg_update_pattern_control(xtpg, passthrough, !passthrough);
228
229 xtpg->streaming = true;
230
231 mutex_unlock(xtpg->ctrl_handler.lock);
232
233 /*
234 * For TPG v5.0, the bayer phase needs to be off for the pass through
235 * mode, otherwise the external input would be subsampled.
236 */
237 bayer_phase = passthrough ? XTPG_BAYER_PHASE_OFF
238 : xtpg_get_bayer_phase(xtpg->formats[0].code);
239 xvip_write(&xtpg->xvip, XTPG_BAYER_PHASE, bayer_phase);
240
241 if (xtpg->vtmux_gpio)
242 gpiod_set_value_cansleep(xtpg->vtmux_gpio, !passthrough);
243
244 xvip_start(&xtpg->xvip);
245
246 return 0;
247 }
248
249 /* -----------------------------------------------------------------------------
250 * V4L2 Subdevice Pad Operations
251 */
252
253 static struct v4l2_mbus_framefmt *
__xtpg_get_pad_format(struct xtpg_device * xtpg,struct v4l2_subdev_state * sd_state,unsigned int pad,u32 which)254 __xtpg_get_pad_format(struct xtpg_device *xtpg,
255 struct v4l2_subdev_state *sd_state,
256 unsigned int pad, u32 which)
257 {
258 switch (which) {
259 case V4L2_SUBDEV_FORMAT_TRY:
260 return v4l2_subdev_state_get_format(sd_state, pad);
261 case V4L2_SUBDEV_FORMAT_ACTIVE:
262 return &xtpg->formats[pad];
263 default:
264 return NULL;
265 }
266 }
267
xtpg_get_format(struct v4l2_subdev * subdev,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)268 static int xtpg_get_format(struct v4l2_subdev *subdev,
269 struct v4l2_subdev_state *sd_state,
270 struct v4l2_subdev_format *fmt)
271 {
272 struct xtpg_device *xtpg = to_tpg(subdev);
273
274 fmt->format = *__xtpg_get_pad_format(xtpg, sd_state, fmt->pad,
275 fmt->which);
276
277 return 0;
278 }
279
xtpg_set_format(struct v4l2_subdev * subdev,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)280 static int xtpg_set_format(struct v4l2_subdev *subdev,
281 struct v4l2_subdev_state *sd_state,
282 struct v4l2_subdev_format *fmt)
283 {
284 struct xtpg_device *xtpg = to_tpg(subdev);
285 struct v4l2_mbus_framefmt *__format;
286 u32 bayer_phase;
287
288 __format = __xtpg_get_pad_format(xtpg, sd_state, fmt->pad, fmt->which);
289
290 /* In two pads mode the source pad format is always identical to the
291 * sink pad format.
292 */
293 if (xtpg->npads == 2 && fmt->pad == 1) {
294 fmt->format = *__format;
295 return 0;
296 }
297
298 /* Bayer phase is configurable at runtime */
299 if (xtpg->bayer) {
300 bayer_phase = xtpg_get_bayer_phase(fmt->format.code);
301 if (bayer_phase != XTPG_BAYER_PHASE_OFF)
302 __format->code = fmt->format.code;
303 }
304
305 xvip_set_format_size(__format, fmt);
306
307 fmt->format = *__format;
308
309 /* Propagate the format to the source pad. */
310 if (xtpg->npads == 2) {
311 __format = __xtpg_get_pad_format(xtpg, sd_state, 1,
312 fmt->which);
313 *__format = fmt->format;
314 }
315
316 return 0;
317 }
318
319 /* -----------------------------------------------------------------------------
320 * V4L2 Subdevice Operations
321 */
322
xtpg_enum_frame_size(struct v4l2_subdev * subdev,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_frame_size_enum * fse)323 static int xtpg_enum_frame_size(struct v4l2_subdev *subdev,
324 struct v4l2_subdev_state *sd_state,
325 struct v4l2_subdev_frame_size_enum *fse)
326 {
327 struct v4l2_mbus_framefmt *format;
328
329 format = v4l2_subdev_state_get_format(sd_state, 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
xtpg_open(struct v4l2_subdev * subdev,struct v4l2_subdev_fh * fh)352 static 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_state_get_format(fh->state, 0);
358 *format = xtpg->default_format;
359
360 if (xtpg->npads == 2) {
361 format = v4l2_subdev_state_get_format(fh->state, 1);
362 *format = xtpg->default_format;
363 }
364
365 return 0;
366 }
367
xtpg_close(struct v4l2_subdev * subdev,struct v4l2_subdev_fh * fh)368 static int xtpg_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
369 {
370 return 0;
371 }
372
xtpg_s_ctrl(struct v4l2_ctrl * ctrl)373 static 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
459 static const struct v4l2_ctrl_ops xtpg_ctrl_ops = {
460 .s_ctrl = xtpg_s_ctrl,
461 };
462
463 static const struct v4l2_subdev_core_ops xtpg_core_ops = {
464 };
465
466 static const struct v4l2_subdev_video_ops xtpg_video_ops = {
467 .s_stream = xtpg_s_stream,
468 };
469
470 static const 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
477 static const struct v4l2_subdev_ops xtpg_ops = {
478 .core = &xtpg_core_ops,
479 .video = &xtpg_video_ops,
480 .pad = &xtpg_pad_ops,
481 };
482
483 static 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
492 static 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
511 static 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
681 static const struct media_entity_operations xtpg_media_ops = {
682 .link_validate = v4l2_subdev_link_validate,
683 };
684
685 /* -----------------------------------------------------------------------------
686 * Power Management
687 */
688
xtpg_pm_suspend(struct device * dev)689 static 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
xtpg_pm_resume(struct device * dev)698 static 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
xtpg_parse_of(struct xtpg_device * xtpg)711 static 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 unsigned int nports = 0;
716 bool has_endpoint = false;
717
718 for_each_of_graph_port(node, port) {
719 const struct xvip_video_format *format;
720 struct device_node *endpoint;
721
722 format = xvip_of_get_format(port);
723 if (IS_ERR(format)) {
724 dev_err(dev, "invalid format in DT");
725 return PTR_ERR(format);
726 }
727
728 /* Get and check the format description */
729 if (!xtpg->vip_format) {
730 xtpg->vip_format = format;
731 } else if (xtpg->vip_format != format) {
732 dev_err(dev, "in/out format mismatch in DT");
733 return -EINVAL;
734 }
735
736 if (nports == 0) {
737 endpoint = of_graph_get_next_port_endpoint(port, NULL);
738 if (endpoint)
739 has_endpoint = true;
740 of_node_put(endpoint);
741 }
742
743 /* Count the number of ports. */
744 nports++;
745 }
746
747 if (nports != 1 && nports != 2) {
748 dev_err(dev, "invalid number of ports %u\n", nports);
749 return -EINVAL;
750 }
751
752 xtpg->npads = nports;
753 if (nports == 2 && has_endpoint)
754 xtpg->has_input = true;
755
756 return 0;
757 }
758
xtpg_probe(struct platform_device * pdev)759 static int xtpg_probe(struct platform_device *pdev)
760 {
761 struct v4l2_subdev *subdev;
762 struct xtpg_device *xtpg;
763 u32 i, bayer_phase;
764 int ret;
765
766 xtpg = devm_kzalloc(&pdev->dev, sizeof(*xtpg), GFP_KERNEL);
767 if (!xtpg)
768 return -ENOMEM;
769
770 xtpg->xvip.dev = &pdev->dev;
771
772 ret = xtpg_parse_of(xtpg);
773 if (ret < 0)
774 return ret;
775
776 ret = xvip_init_resources(&xtpg->xvip);
777 if (ret < 0)
778 return ret;
779
780 xtpg->vtmux_gpio = devm_gpiod_get_optional(&pdev->dev, "timing",
781 GPIOD_OUT_HIGH);
782 if (IS_ERR(xtpg->vtmux_gpio)) {
783 ret = PTR_ERR(xtpg->vtmux_gpio);
784 goto error_resource;
785 }
786
787 xtpg->vtc = xvtc_of_get(pdev->dev.of_node);
788 if (IS_ERR(xtpg->vtc)) {
789 ret = PTR_ERR(xtpg->vtc);
790 goto error_resource;
791 }
792
793 /* Reset and initialize the core */
794 xvip_reset(&xtpg->xvip);
795
796 /* Initialize V4L2 subdevice and media entity. Pad numbers depend on the
797 * number of pads.
798 */
799 if (xtpg->npads == 2) {
800 xtpg->pads[0].flags = MEDIA_PAD_FL_SINK;
801 xtpg->pads[1].flags = MEDIA_PAD_FL_SOURCE;
802 } else {
803 xtpg->pads[0].flags = MEDIA_PAD_FL_SOURCE;
804 }
805
806 /* Initialize the default format */
807 xtpg->default_format.code = xtpg->vip_format->code;
808 xtpg->default_format.field = V4L2_FIELD_NONE;
809 xtpg->default_format.colorspace = V4L2_COLORSPACE_SRGB;
810 xvip_get_frame_size(&xtpg->xvip, &xtpg->default_format);
811
812 bayer_phase = xtpg_get_bayer_phase(xtpg->vip_format->code);
813 if (bayer_phase != XTPG_BAYER_PHASE_OFF)
814 xtpg->bayer = true;
815
816 xtpg->formats[0] = xtpg->default_format;
817 if (xtpg->npads == 2)
818 xtpg->formats[1] = xtpg->default_format;
819
820 /* Initialize V4L2 subdevice and media entity */
821 subdev = &xtpg->xvip.subdev;
822 v4l2_subdev_init(subdev, &xtpg_ops);
823 subdev->dev = &pdev->dev;
824 subdev->internal_ops = &xtpg_internal_ops;
825 strscpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
826 v4l2_set_subdevdata(subdev, xtpg);
827 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
828 subdev->entity.ops = &xtpg_media_ops;
829
830 ret = media_entity_pads_init(&subdev->entity, xtpg->npads, xtpg->pads);
831 if (ret < 0)
832 goto error;
833
834 v4l2_ctrl_handler_init(&xtpg->ctrl_handler, 3 + ARRAY_SIZE(xtpg_ctrls));
835
836 xtpg->vblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops,
837 V4L2_CID_VBLANK, XTPG_MIN_VBLANK,
838 XTPG_MAX_VBLANK, 1, 100);
839 xtpg->hblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops,
840 V4L2_CID_HBLANK, XTPG_MIN_HBLANK,
841 XTPG_MAX_HBLANK, 1, 100);
842 xtpg->pattern = v4l2_ctrl_new_std_menu_items(&xtpg->ctrl_handler,
843 &xtpg_ctrl_ops, V4L2_CID_TEST_PATTERN,
844 ARRAY_SIZE(xtpg_pattern_strings) - 1,
845 1, 9, xtpg_pattern_strings);
846
847 for (i = 0; i < ARRAY_SIZE(xtpg_ctrls); i++)
848 v4l2_ctrl_new_custom(&xtpg->ctrl_handler, &xtpg_ctrls[i], NULL);
849
850 if (xtpg->ctrl_handler.error) {
851 dev_err(&pdev->dev, "failed to add controls\n");
852 ret = xtpg->ctrl_handler.error;
853 goto error;
854 }
855 subdev->ctrl_handler = &xtpg->ctrl_handler;
856
857 xtpg_update_pattern_control(xtpg, true, true);
858
859 ret = v4l2_ctrl_handler_setup(&xtpg->ctrl_handler);
860 if (ret < 0) {
861 dev_err(&pdev->dev, "failed to set controls\n");
862 goto error;
863 }
864
865 platform_set_drvdata(pdev, xtpg);
866
867 xvip_print_version(&xtpg->xvip);
868
869 ret = v4l2_async_register_subdev(subdev);
870 if (ret < 0) {
871 dev_err(&pdev->dev, "failed to register subdev\n");
872 goto error;
873 }
874
875 return 0;
876
877 error:
878 v4l2_ctrl_handler_free(&xtpg->ctrl_handler);
879 media_entity_cleanup(&subdev->entity);
880 xvtc_put(xtpg->vtc);
881 error_resource:
882 xvip_cleanup_resources(&xtpg->xvip);
883 return ret;
884 }
885
xtpg_remove(struct platform_device * pdev)886 static void xtpg_remove(struct platform_device *pdev)
887 {
888 struct xtpg_device *xtpg = platform_get_drvdata(pdev);
889 struct v4l2_subdev *subdev = &xtpg->xvip.subdev;
890
891 v4l2_async_unregister_subdev(subdev);
892 v4l2_ctrl_handler_free(&xtpg->ctrl_handler);
893 media_entity_cleanup(&subdev->entity);
894
895 xvip_cleanup_resources(&xtpg->xvip);
896 }
897
898 static SIMPLE_DEV_PM_OPS(xtpg_pm_ops, xtpg_pm_suspend, xtpg_pm_resume);
899
900 static const struct of_device_id xtpg_of_id_table[] = {
901 { .compatible = "xlnx,v-tpg-5.0" },
902 { }
903 };
904 MODULE_DEVICE_TABLE(of, xtpg_of_id_table);
905
906 static struct platform_driver xtpg_driver = {
907 .driver = {
908 .name = "xilinx-tpg",
909 .pm = &xtpg_pm_ops,
910 .of_match_table = xtpg_of_id_table,
911 },
912 .probe = xtpg_probe,
913 .remove = xtpg_remove,
914 };
915
916 module_platform_driver(xtpg_driver);
917
918 MODULE_AUTHOR("Laurent Pinchart <[email protected]>");
919 MODULE_DESCRIPTION("Xilinx Test Pattern Generator Driver");
920 MODULE_LICENSE("GPL v2");
921