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 */
88 struct 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
to_tpg(struct v4l2_subdev * subdev)110 static inline struct xtpg_device *to_tpg(struct v4l2_subdev *subdev)
111 {
112 return container_of(subdev, struct xtpg_device, xvip.subdev);
113 }
114
xtpg_get_bayer_phase(unsigned int code)115 static 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
__xtpg_update_pattern_control(struct xtpg_device * xtpg,bool passthrough,bool pattern)131 static 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(xtpg->pattern, 0, xtpg->pattern->maximum,
152 pattern_mask, pattern ? 9 : 0);
153 }
154
xtpg_update_pattern_control(struct xtpg_device * xtpg,bool passthrough,bool pattern)155 static 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(xtpg->ctrl_handler.lock);
161 }
162
163 /* -----------------------------------------------------------------------------
164 * V4L2 Subdevice Video Operations
165 */
166
xtpg_s_stream(struct v4l2_subdev * subdev,int enable)167 static 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(&xtpg->xvip);
177 if (xtpg->vtc)
178 xvtc_generator_stop(xtpg->vtc);
179
180 xtpg_update_pattern_control(xtpg, true, true);
181 xtpg->streaming = false;
182 return 0;
183 }
184
185 xvip_set_frame_size(&xtpg->xvip, &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(xtpg->vtc, &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(&xtpg->xvip, XTPG_PATTERN_CONTROL,
219 XTPG_PATTERN_MASK, 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, !passthrough);
227
228 xtpg->streaming = true;
229
230 mutex_unlock(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(xtpg->formats[0].code);
238 xvip_write(&xtpg->xvip, XTPG_BAYER_PHASE, bayer_phase);
239
240 if (xtpg->vtmux_gpio)
241 gpiod_set_value_cansleep(xtpg->vtmux_gpio, !passthrough);
242
243 xvip_start(&xtpg->xvip);
244
245 return 0;
246 }
247
248 /* -----------------------------------------------------------------------------
249 * V4L2 Subdevice Pad Operations
250 */
251
252 static struct v4l2_mbus_framefmt *
__xtpg_get_pad_format(struct xtpg_device * xtpg,struct v4l2_subdev_pad_config * cfg,unsigned int pad,u32 which)253 __xtpg_get_pad_format(struct xtpg_device *xtpg,
254 struct v4l2_subdev_pad_config *cfg,
255 unsigned int pad, u32 which)
256 {
257 switch (which) {
258 case V4L2_SUBDEV_FORMAT_TRY:
259 return v4l2_subdev_get_try_format(&xtpg->xvip.subdev, cfg, pad);
260 case V4L2_SUBDEV_FORMAT_ACTIVE:
261 return &xtpg->formats[pad];
262 default:
263 return NULL;
264 }
265 }
266
xtpg_get_format(struct v4l2_subdev * subdev,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)267 static int xtpg_get_format(struct v4l2_subdev *subdev,
268 struct v4l2_subdev_pad_config *cfg,
269 struct v4l2_subdev_format *fmt)
270 {
271 struct xtpg_device *xtpg = to_tpg(subdev);
272
273 fmt->format = *__xtpg_get_pad_format(xtpg, cfg, fmt->pad, fmt->which);
274
275 return 0;
276 }
277
xtpg_set_format(struct v4l2_subdev * subdev,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)278 static int xtpg_set_format(struct v4l2_subdev *subdev,
279 struct v4l2_subdev_pad_config *cfg,
280 struct v4l2_subdev_format *fmt)
281 {
282 struct xtpg_device *xtpg = to_tpg(subdev);
283 struct v4l2_mbus_framefmt *__format;
284 u32 bayer_phase;
285
286 __format = __xtpg_get_pad_format(xtpg, cfg, fmt->pad, fmt->which);
287
288 /* In two pads mode the source pad format is always identical to the
289 * sink pad format.
290 */
291 if (xtpg->npads == 2 && fmt->pad == 1) {
292 fmt->format = *__format;
293 return 0;
294 }
295
296 /* Bayer phase is configurable at runtime */
297 if (xtpg->bayer) {
298 bayer_phase = xtpg_get_bayer_phase(fmt->format.code);
299 if (bayer_phase != XTPG_BAYER_PHASE_OFF)
300 __format->code = fmt->format.code;
301 }
302
303 xvip_set_format_size(__format, fmt);
304
305 fmt->format = *__format;
306
307 /* Propagate the format to the source pad. */
308 if (xtpg->npads == 2) {
309 __format = __xtpg_get_pad_format(xtpg, cfg, 1, fmt->which);
310 *__format = fmt->format;
311 }
312
313 return 0;
314 }
315
316 /* -----------------------------------------------------------------------------
317 * V4L2 Subdevice Operations
318 */
319
xtpg_enum_frame_size(struct v4l2_subdev * subdev,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_frame_size_enum * fse)320 static int xtpg_enum_frame_size(struct v4l2_subdev *subdev,
321 struct v4l2_subdev_pad_config *cfg,
322 struct v4l2_subdev_frame_size_enum *fse)
323 {
324 struct v4l2_mbus_framefmt *format;
325
326 format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad);
327
328 if (fse->index || fse->code != format->code)
329 return -EINVAL;
330
331 /* Min / max values for pad 0 is always fixed in both one and two pads
332 * modes. In two pads mode, the source pad(= 1) size is identical to
333 * the sink pad size */
334 if (fse->pad == 0) {
335 fse->min_width = XVIP_MIN_WIDTH;
336 fse->max_width = XVIP_MAX_WIDTH;
337 fse->min_height = XVIP_MIN_HEIGHT;
338 fse->max_height = XVIP_MAX_HEIGHT;
339 } else {
340 fse->min_width = format->width;
341 fse->max_width = format->width;
342 fse->min_height = format->height;
343 fse->max_height = format->height;
344 }
345
346 return 0;
347 }
348
xtpg_open(struct v4l2_subdev * subdev,struct v4l2_subdev_fh * fh)349 static int xtpg_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
350 {
351 struct xtpg_device *xtpg = to_tpg(subdev);
352 struct v4l2_mbus_framefmt *format;
353
354 format = v4l2_subdev_get_try_format(subdev, fh->pad, 0);
355 *format = xtpg->default_format;
356
357 if (xtpg->npads == 2) {
358 format = v4l2_subdev_get_try_format(subdev, fh->pad, 1);
359 *format = xtpg->default_format;
360 }
361
362 return 0;
363 }
364
xtpg_close(struct v4l2_subdev * subdev,struct v4l2_subdev_fh * fh)365 static int xtpg_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
366 {
367 return 0;
368 }
369
xtpg_s_ctrl(struct v4l2_ctrl * ctrl)370 static int xtpg_s_ctrl(struct v4l2_ctrl *ctrl)
371 {
372 struct xtpg_device *xtpg = container_of(ctrl->handler,
373 struct xtpg_device,
374 ctrl_handler);
375 switch (ctrl->id) {
376 case V4L2_CID_TEST_PATTERN:
377 xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
378 XTPG_PATTERN_MASK, ctrl->val);
379 return 0;
380 case V4L2_CID_XILINX_TPG_CROSS_HAIRS:
381 xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
382 XTPG_PATTERN_CONTROL_CROSS_HAIRS, ctrl->val);
383 return 0;
384 case V4L2_CID_XILINX_TPG_MOVING_BOX:
385 xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
386 XTPG_PATTERN_CONTROL_MOVING_BOX, ctrl->val);
387 return 0;
388 case V4L2_CID_XILINX_TPG_COLOR_MASK:
389 xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
390 XTPG_PATTERN_CONTROL_COLOR_MASK_MASK,
391 ctrl->val <<
392 XTPG_PATTERN_CONTROL_COLOR_MASK_SHIFT);
393 return 0;
394 case V4L2_CID_XILINX_TPG_STUCK_PIXEL:
395 xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
396 XTPG_PATTERN_CONTROL_STUCK_PIXEL, ctrl->val);
397 return 0;
398 case V4L2_CID_XILINX_TPG_NOISE:
399 xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
400 XTPG_PATTERN_CONTROL_NOISE, ctrl->val);
401 return 0;
402 case V4L2_CID_XILINX_TPG_MOTION:
403 xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
404 XTPG_PATTERN_CONTROL_MOTION, ctrl->val);
405 return 0;
406 case V4L2_CID_XILINX_TPG_MOTION_SPEED:
407 xvip_write(&xtpg->xvip, XTPG_MOTION_SPEED, ctrl->val);
408 return 0;
409 case V4L2_CID_XILINX_TPG_CROSS_HAIR_ROW:
410 xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS,
411 XTPG_CROSS_HAIRS_ROW_MASK,
412 ctrl->val << XTPG_CROSS_HAIRS_ROW_SHIFT);
413 return 0;
414 case V4L2_CID_XILINX_TPG_CROSS_HAIR_COLUMN:
415 xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS,
416 XTPG_CROSS_HAIRS_COLUMN_MASK,
417 ctrl->val << XTPG_CROSS_HAIRS_COLUMN_SHIFT);
418 return 0;
419 case V4L2_CID_XILINX_TPG_ZPLATE_HOR_START:
420 xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL,
421 XTPG_ZPLATE_START_MASK,
422 ctrl->val << XTPG_ZPLATE_START_SHIFT);
423 return 0;
424 case V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED:
425 xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL,
426 XTPG_ZPLATE_SPEED_MASK,
427 ctrl->val << XTPG_ZPLATE_SPEED_SHIFT);
428 return 0;
429 case V4L2_CID_XILINX_TPG_ZPLATE_VER_START:
430 xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL,
431 XTPG_ZPLATE_START_MASK,
432 ctrl->val << XTPG_ZPLATE_START_SHIFT);
433 return 0;
434 case V4L2_CID_XILINX_TPG_ZPLATE_VER_SPEED:
435 xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL,
436 XTPG_ZPLATE_SPEED_MASK,
437 ctrl->val << XTPG_ZPLATE_SPEED_SHIFT);
438 return 0;
439 case V4L2_CID_XILINX_TPG_BOX_SIZE:
440 xvip_write(&xtpg->xvip, XTPG_BOX_SIZE, ctrl->val);
441 return 0;
442 case V4L2_CID_XILINX_TPG_BOX_COLOR:
443 xvip_write(&xtpg->xvip, XTPG_BOX_COLOR, ctrl->val);
444 return 0;
445 case V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH:
446 xvip_write(&xtpg->xvip, XTPG_STUCK_PIXEL_THRESH, ctrl->val);
447 return 0;
448 case V4L2_CID_XILINX_TPG_NOISE_GAIN:
449 xvip_write(&xtpg->xvip, XTPG_NOISE_GAIN, ctrl->val);
450 return 0;
451 }
452
453 return 0;
454 }
455
456 static const struct v4l2_ctrl_ops xtpg_ctrl_ops = {
457 .s_ctrl = xtpg_s_ctrl,
458 };
459
460 static const struct v4l2_subdev_core_ops xtpg_core_ops = {
461 };
462
463 static const struct v4l2_subdev_video_ops xtpg_video_ops = {
464 .s_stream = xtpg_s_stream,
465 };
466
467 static const struct v4l2_subdev_pad_ops xtpg_pad_ops = {
468 .enum_mbus_code = xvip_enum_mbus_code,
469 .enum_frame_size = xtpg_enum_frame_size,
470 .get_fmt = xtpg_get_format,
471 .set_fmt = xtpg_set_format,
472 };
473
474 static const struct v4l2_subdev_ops xtpg_ops = {
475 .core = &xtpg_core_ops,
476 .video = &xtpg_video_ops,
477 .pad = &xtpg_pad_ops,
478 };
479
480 static const struct v4l2_subdev_internal_ops xtpg_internal_ops = {
481 .open = xtpg_open,
482 .close = xtpg_close,
483 };
484
485 /*
486 * Control Config
487 */
488
489 static const char *const xtpg_pattern_strings[] = {
490 "Passthrough",
491 "Horizontal Ramp",
492 "Vertical Ramp",
493 "Temporal Ramp",
494 "Solid Red",
495 "Solid Green",
496 "Solid Blue",
497 "Solid Black",
498 "Solid White",
499 "Color Bars",
500 "Zone Plate",
501 "Tartan Color Bars",
502 "Cross Hatch",
503 "None",
504 "Vertical/Horizontal Ramps",
505 "Black/White Checker Board",
506 };
507
508 static struct v4l2_ctrl_config xtpg_ctrls[] = {
509 {
510 .ops = &xtpg_ctrl_ops,
511 .id = V4L2_CID_XILINX_TPG_CROSS_HAIRS,
512 .name = "Test Pattern: Cross Hairs",
513 .type = V4L2_CTRL_TYPE_BOOLEAN,
514 .min = false,
515 .max = true,
516 .step = 1,
517 .def = 0,
518 }, {
519 .ops = &xtpg_ctrl_ops,
520 .id = V4L2_CID_XILINX_TPG_MOVING_BOX,
521 .name = "Test Pattern: Moving Box",
522 .type = V4L2_CTRL_TYPE_BOOLEAN,
523 .min = false,
524 .max = true,
525 .step = 1,
526 .def = 0,
527 }, {
528 .ops = &xtpg_ctrl_ops,
529 .id = V4L2_CID_XILINX_TPG_COLOR_MASK,
530 .name = "Test Pattern: Color Mask",
531 .type = V4L2_CTRL_TYPE_BITMASK,
532 .min = 0,
533 .max = 0xf,
534 .def = 0,
535 }, {
536 .ops = &xtpg_ctrl_ops,
537 .id = V4L2_CID_XILINX_TPG_STUCK_PIXEL,
538 .name = "Test Pattern: Stuck Pixel",
539 .type = V4L2_CTRL_TYPE_BOOLEAN,
540 .min = false,
541 .max = true,
542 .step = 1,
543 .def = 0,
544 }, {
545 .ops = &xtpg_ctrl_ops,
546 .id = V4L2_CID_XILINX_TPG_NOISE,
547 .name = "Test Pattern: Noise",
548 .type = V4L2_CTRL_TYPE_BOOLEAN,
549 .min = false,
550 .max = true,
551 .step = 1,
552 .def = 0,
553 }, {
554 .ops = &xtpg_ctrl_ops,
555 .id = V4L2_CID_XILINX_TPG_MOTION,
556 .name = "Test Pattern: Motion",
557 .type = V4L2_CTRL_TYPE_BOOLEAN,
558 .min = false,
559 .max = true,
560 .step = 1,
561 .def = 0,
562 }, {
563 .ops = &xtpg_ctrl_ops,
564 .id = V4L2_CID_XILINX_TPG_MOTION_SPEED,
565 .name = "Test Pattern: Motion Speed",
566 .type = V4L2_CTRL_TYPE_INTEGER,
567 .min = 0,
568 .max = (1 << 8) - 1,
569 .step = 1,
570 .def = 4,
571 .flags = V4L2_CTRL_FLAG_SLIDER,
572 }, {
573 .ops = &xtpg_ctrl_ops,
574 .id = V4L2_CID_XILINX_TPG_CROSS_HAIR_ROW,
575 .name = "Test Pattern: Cross Hairs Row",
576 .type = V4L2_CTRL_TYPE_INTEGER,
577 .min = 0,
578 .max = (1 << 12) - 1,
579 .step = 1,
580 .def = 0x64,
581 .flags = V4L2_CTRL_FLAG_SLIDER,
582 }, {
583 .ops = &xtpg_ctrl_ops,
584 .id = V4L2_CID_XILINX_TPG_CROSS_HAIR_COLUMN,
585 .name = "Test Pattern: Cross Hairs Column",
586 .type = V4L2_CTRL_TYPE_INTEGER,
587 .min = 0,
588 .max = (1 << 12) - 1,
589 .step = 1,
590 .def = 0x64,
591 .flags = V4L2_CTRL_FLAG_SLIDER,
592 }, {
593 .ops = &xtpg_ctrl_ops,
594 .id = V4L2_CID_XILINX_TPG_ZPLATE_HOR_START,
595 .name = "Test Pattern: Zplate Horizontal Start Pos",
596 .type = V4L2_CTRL_TYPE_INTEGER,
597 .min = 0,
598 .max = (1 << 16) - 1,
599 .step = 1,
600 .def = 0x1e,
601 .flags = V4L2_CTRL_FLAG_SLIDER,
602 }, {
603 .ops = &xtpg_ctrl_ops,
604 .id = V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED,
605 .name = "Test Pattern: Zplate Horizontal Speed",
606 .type = V4L2_CTRL_TYPE_INTEGER,
607 .min = 0,
608 .max = (1 << 16) - 1,
609 .step = 1,
610 .def = 0,
611 .flags = V4L2_CTRL_FLAG_SLIDER,
612 }, {
613 .ops = &xtpg_ctrl_ops,
614 .id = V4L2_CID_XILINX_TPG_ZPLATE_VER_START,
615 .name = "Test Pattern: Zplate Vertical Start Pos",
616 .type = V4L2_CTRL_TYPE_INTEGER,
617 .min = 0,
618 .max = (1 << 16) - 1,
619 .step = 1,
620 .def = 1,
621 .flags = V4L2_CTRL_FLAG_SLIDER,
622 }, {
623 .ops = &xtpg_ctrl_ops,
624 .id = V4L2_CID_XILINX_TPG_ZPLATE_VER_SPEED,
625 .name = "Test Pattern: Zplate Vertical Speed",
626 .type = V4L2_CTRL_TYPE_INTEGER,
627 .min = 0,
628 .max = (1 << 16) - 1,
629 .step = 1,
630 .def = 0,
631 .flags = V4L2_CTRL_FLAG_SLIDER,
632 }, {
633 .ops = &xtpg_ctrl_ops,
634 .id = V4L2_CID_XILINX_TPG_BOX_SIZE,
635 .name = "Test Pattern: Box Size",
636 .type = V4L2_CTRL_TYPE_INTEGER,
637 .min = 0,
638 .max = (1 << 12) - 1,
639 .step = 1,
640 .def = 0x32,
641 .flags = V4L2_CTRL_FLAG_SLIDER,
642 }, {
643 .ops = &xtpg_ctrl_ops,
644 .id = V4L2_CID_XILINX_TPG_BOX_COLOR,
645 .name = "Test Pattern: Box Color(RGB)",
646 .type = V4L2_CTRL_TYPE_INTEGER,
647 .min = 0,
648 .max = (1 << 24) - 1,
649 .step = 1,
650 .def = 0,
651 }, {
652 .ops = &xtpg_ctrl_ops,
653 .id = V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH,
654 .name = "Test Pattern: Stuck Pixel threshold",
655 .type = V4L2_CTRL_TYPE_INTEGER,
656 .min = 0,
657 .max = (1 << 16) - 1,
658 .step = 1,
659 .def = 0,
660 .flags = V4L2_CTRL_FLAG_SLIDER,
661 }, {
662 .ops = &xtpg_ctrl_ops,
663 .id = V4L2_CID_XILINX_TPG_NOISE_GAIN,
664 .name = "Test Pattern: Noise Gain",
665 .type = V4L2_CTRL_TYPE_INTEGER,
666 .min = 0,
667 .max = (1 << 8) - 1,
668 .step = 1,
669 .def = 0,
670 .flags = V4L2_CTRL_FLAG_SLIDER,
671 },
672 };
673
674 /* -----------------------------------------------------------------------------
675 * Media Operations
676 */
677
678 static const struct media_entity_operations xtpg_media_ops = {
679 .link_validate = v4l2_subdev_link_validate,
680 };
681
682 /* -----------------------------------------------------------------------------
683 * Power Management
684 */
685
xtpg_pm_suspend(struct device * dev)686 static int __maybe_unused xtpg_pm_suspend(struct device *dev)
687 {
688 struct xtpg_device *xtpg = dev_get_drvdata(dev);
689
690 xvip_suspend(&xtpg->xvip);
691
692 return 0;
693 }
694
xtpg_pm_resume(struct device * dev)695 static int __maybe_unused xtpg_pm_resume(struct device *dev)
696 {
697 struct xtpg_device *xtpg = dev_get_drvdata(dev);
698
699 xvip_resume(&xtpg->xvip);
700
701 return 0;
702 }
703
704 /* -----------------------------------------------------------------------------
705 * Platform Device Driver
706 */
707
xtpg_parse_of(struct xtpg_device * xtpg)708 static int xtpg_parse_of(struct xtpg_device *xtpg)
709 {
710 struct device *dev = xtpg->xvip.dev;
711 struct device_node *node = xtpg->xvip.dev->of_node;
712 struct device_node *ports;
713 struct device_node *port;
714 unsigned int nports = 0;
715 bool has_endpoint = false;
716
717 ports = of_get_child_by_name(node, "ports");
718 if (ports == NULL)
719 ports = node;
720
721 for_each_child_of_node(ports, port) {
722 const struct xvip_video_format *format;
723 struct device_node *endpoint;
724
725 if (!of_node_name_eq(port, "port"))
726 continue;
727
728 format = xvip_of_get_format(port);
729 if (IS_ERR(format)) {
730 dev_err(dev, "invalid format in DT");
731 of_node_put(port);
732 return PTR_ERR(format);
733 }
734
735 /* Get and check the format description */
736 if (!xtpg->vip_format) {
737 xtpg->vip_format = format;
738 } else if (xtpg->vip_format != format) {
739 dev_err(dev, "in/out format mismatch in DT");
740 of_node_put(port);
741 return -EINVAL;
742 }
743
744 if (nports == 0) {
745 endpoint = of_get_next_child(port, NULL);
746 if (endpoint)
747 has_endpoint = true;
748 of_node_put(endpoint);
749 }
750
751 /* Count the number of ports. */
752 nports++;
753 }
754
755 if (nports != 1 && nports != 2) {
756 dev_err(dev, "invalid number of ports %u\n", nports);
757 return -EINVAL;
758 }
759
760 xtpg->npads = nports;
761 if (nports == 2 && has_endpoint)
762 xtpg->has_input = true;
763
764 return 0;
765 }
766
xtpg_probe(struct platform_device * pdev)767 static int xtpg_probe(struct platform_device *pdev)
768 {
769 struct v4l2_subdev *subdev;
770 struct xtpg_device *xtpg;
771 u32 i, bayer_phase;
772 int ret;
773
774 xtpg = devm_kzalloc(&pdev->dev, sizeof(*xtpg), GFP_KERNEL);
775 if (!xtpg)
776 return -ENOMEM;
777
778 xtpg->xvip.dev = &pdev->dev;
779
780 ret = xtpg_parse_of(xtpg);
781 if (ret < 0)
782 return ret;
783
784 ret = xvip_init_resources(&xtpg->xvip);
785 if (ret < 0)
786 return ret;
787
788 xtpg->vtmux_gpio = devm_gpiod_get_optional(&pdev->dev, "timing",
789 GPIOD_OUT_HIGH);
790 if (IS_ERR(xtpg->vtmux_gpio)) {
791 ret = PTR_ERR(xtpg->vtmux_gpio);
792 goto error_resource;
793 }
794
795 xtpg->vtc = xvtc_of_get(pdev->dev.of_node);
796 if (IS_ERR(xtpg->vtc)) {
797 ret = PTR_ERR(xtpg->vtc);
798 goto error_resource;
799 }
800
801 /* Reset and initialize the core */
802 xvip_reset(&xtpg->xvip);
803
804 /* Initialize V4L2 subdevice and media entity. Pad numbers depend on the
805 * number of pads.
806 */
807 if (xtpg->npads == 2) {
808 xtpg->pads[0].flags = MEDIA_PAD_FL_SINK;
809 xtpg->pads[1].flags = MEDIA_PAD_FL_SOURCE;
810 } else {
811 xtpg->pads[0].flags = MEDIA_PAD_FL_SOURCE;
812 }
813
814 /* Initialize the default format */
815 xtpg->default_format.code = xtpg->vip_format->code;
816 xtpg->default_format.field = V4L2_FIELD_NONE;
817 xtpg->default_format.colorspace = V4L2_COLORSPACE_SRGB;
818 xvip_get_frame_size(&xtpg->xvip, &xtpg->default_format);
819
820 bayer_phase = xtpg_get_bayer_phase(xtpg->vip_format->code);
821 if (bayer_phase != XTPG_BAYER_PHASE_OFF)
822 xtpg->bayer = true;
823
824 xtpg->formats[0] = xtpg->default_format;
825 if (xtpg->npads == 2)
826 xtpg->formats[1] = xtpg->default_format;
827
828 /* Initialize V4L2 subdevice and media entity */
829 subdev = &xtpg->xvip.subdev;
830 v4l2_subdev_init(subdev, &xtpg_ops);
831 subdev->dev = &pdev->dev;
832 subdev->internal_ops = &xtpg_internal_ops;
833 strscpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
834 v4l2_set_subdevdata(subdev, xtpg);
835 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
836 subdev->entity.ops = &xtpg_media_ops;
837
838 ret = media_entity_pads_init(&subdev->entity, xtpg->npads, xtpg->pads);
839 if (ret < 0)
840 goto error;
841
842 v4l2_ctrl_handler_init(&xtpg->ctrl_handler, 3 + ARRAY_SIZE(xtpg_ctrls));
843
844 xtpg->vblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops,
845 V4L2_CID_VBLANK, XTPG_MIN_VBLANK,
846 XTPG_MAX_VBLANK, 1, 100);
847 xtpg->hblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops,
848 V4L2_CID_HBLANK, XTPG_MIN_HBLANK,
849 XTPG_MAX_HBLANK, 1, 100);
850 xtpg->pattern = v4l2_ctrl_new_std_menu_items(&xtpg->ctrl_handler,
851 &xtpg_ctrl_ops, V4L2_CID_TEST_PATTERN,
852 ARRAY_SIZE(xtpg_pattern_strings) - 1,
853 1, 9, xtpg_pattern_strings);
854
855 for (i = 0; i < ARRAY_SIZE(xtpg_ctrls); i++)
856 v4l2_ctrl_new_custom(&xtpg->ctrl_handler, &xtpg_ctrls[i], NULL);
857
858 if (xtpg->ctrl_handler.error) {
859 dev_err(&pdev->dev, "failed to add controls\n");
860 ret = xtpg->ctrl_handler.error;
861 goto error;
862 }
863 subdev->ctrl_handler = &xtpg->ctrl_handler;
864
865 xtpg_update_pattern_control(xtpg, true, true);
866
867 ret = v4l2_ctrl_handler_setup(&xtpg->ctrl_handler);
868 if (ret < 0) {
869 dev_err(&pdev->dev, "failed to set controls\n");
870 goto error;
871 }
872
873 platform_set_drvdata(pdev, xtpg);
874
875 xvip_print_version(&xtpg->xvip);
876
877 ret = v4l2_async_register_subdev(subdev);
878 if (ret < 0) {
879 dev_err(&pdev->dev, "failed to register subdev\n");
880 goto error;
881 }
882
883 return 0;
884
885 error:
886 v4l2_ctrl_handler_free(&xtpg->ctrl_handler);
887 media_entity_cleanup(&subdev->entity);
888 xvtc_put(xtpg->vtc);
889 error_resource:
890 xvip_cleanup_resources(&xtpg->xvip);
891 return ret;
892 }
893
xtpg_remove(struct platform_device * pdev)894 static int xtpg_remove(struct platform_device *pdev)
895 {
896 struct xtpg_device *xtpg = platform_get_drvdata(pdev);
897 struct v4l2_subdev *subdev = &xtpg->xvip.subdev;
898
899 v4l2_async_unregister_subdev(subdev);
900 v4l2_ctrl_handler_free(&xtpg->ctrl_handler);
901 media_entity_cleanup(&subdev->entity);
902
903 xvip_cleanup_resources(&xtpg->xvip);
904
905 return 0;
906 }
907
908 static SIMPLE_DEV_PM_OPS(xtpg_pm_ops, xtpg_pm_suspend, xtpg_pm_resume);
909
910 static const struct of_device_id xtpg_of_id_table[] = {
911 { .compatible = "xlnx,v-tpg-5.0" },
912 { }
913 };
914 MODULE_DEVICE_TABLE(of, xtpg_of_id_table);
915
916 static 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 = xtpg_remove,
924 };
925
926 module_platform_driver(xtpg_driver);
927
928 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
929 MODULE_DESCRIPTION("Xilinx Test Pattern Generator Driver");
930 MODULE_LICENSE("GPL v2");
931