1 // SPDX-License-Identifier: GPL-2.0
3 * Xilinx Video Timing Controller
5 * Copyright (C) 2013-2015 Ideas on Board
6 * Copyright (C) 2013-2015 Xilinx, Inc.
8 * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
9 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
12 #include <linux/clk.h>
13 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/slab.h>
18 #include "xilinx-vip.h"
19 #include "xilinx-vtc.h"
21 #define XVTC_CONTROL_FIELD_ID_POL_SRC (1 << 26)
22 #define XVTC_CONTROL_ACTIVE_CHROMA_POL_SRC (1 << 25)
23 #define XVTC_CONTROL_ACTIVE_VIDEO_POL_SRC (1 << 24)
24 #define XVTC_CONTROL_HSYNC_POL_SRC (1 << 23)
25 #define XVTC_CONTROL_VSYNC_POL_SRC (1 << 22)
26 #define XVTC_CONTROL_HBLANK_POL_SRC (1 << 21)
27 #define XVTC_CONTROL_VBLANK_POL_SRC (1 << 20)
28 #define XVTC_CONTROL_CHROMA_SRC (1 << 18)
29 #define XVTC_CONTROL_VBLANK_HOFF_SRC (1 << 17)
30 #define XVTC_CONTROL_VSYNC_END_SRC (1 << 16)
31 #define XVTC_CONTROL_VSYNC_START_SRC (1 << 15)
32 #define XVTC_CONTROL_ACTIVE_VSIZE_SRC (1 << 14)
33 #define XVTC_CONTROL_FRAME_VSIZE_SRC (1 << 13)
34 #define XVTC_CONTROL_HSYNC_END_SRC (1 << 11)
35 #define XVTC_CONTROL_HSYNC_START_SRC (1 << 10)
36 #define XVTC_CONTROL_ACTIVE_HSIZE_SRC (1 << 9)
37 #define XVTC_CONTROL_FRAME_HSIZE_SRC (1 << 8)
38 #define XVTC_CONTROL_SYNC_ENABLE (1 << 5)
39 #define XVTC_CONTROL_DET_ENABLE (1 << 3)
40 #define XVTC_CONTROL_GEN_ENABLE (1 << 2)
42 #define XVTC_STATUS_FSYNC(n) ((n) << 16)
43 #define XVTC_STATUS_GEN_ACTIVE_VIDEO (1 << 13)
44 #define XVTC_STATUS_GEN_VBLANK (1 << 12)
45 #define XVTC_STATUS_DET_ACTIVE_VIDEO (1 << 11)
46 #define XVTC_STATUS_DET_VBLANK (1 << 10)
47 #define XVTC_STATUS_LOCK_LOSS (1 << 9)
48 #define XVTC_STATUS_LOCK (1 << 8)
50 #define XVTC_ERROR_ACTIVE_CHROMA_LOCK (1 << 21)
51 #define XVTC_ERROR_ACTIVE_VIDEO_LOCK (1 << 20)
52 #define XVTC_ERROR_HSYNC_LOCK (1 << 19)
53 #define XVTC_ERROR_VSYNC_LOCK (1 << 18)
54 #define XVTC_ERROR_HBLANK_LOCK (1 << 17)
55 #define XVTC_ERROR_VBLANK_LOCK (1 << 16)
57 #define XVTC_IRQ_ENABLE_FSYNC(n) ((n) << 16)
58 #define XVTC_IRQ_ENABLE_GEN_ACTIVE_VIDEO (1 << 13)
59 #define XVTC_IRQ_ENABLE_GEN_VBLANK (1 << 12)
60 #define XVTC_IRQ_ENABLE_DET_ACTIVE_VIDEO (1 << 11)
61 #define XVTC_IRQ_ENABLE_DET_VBLANK (1 << 10)
62 #define XVTC_IRQ_ENABLE_LOCK_LOSS (1 << 9)
63 #define XVTC_IRQ_ENABLE_LOCK (1 << 8)
66 * The following registers exist in two blocks, one at 0x0020 for the detector
67 * and one at 0x0060 for the generator.
70 #define XVTC_DETECTOR_OFFSET 0x0020
71 #define XVTC_GENERATOR_OFFSET 0x0060
73 #define XVTC_ACTIVE_SIZE 0x0000
74 #define XVTC_ACTIVE_VSIZE_SHIFT 16
75 #define XVTC_ACTIVE_VSIZE_MASK (0x1fff << 16)
76 #define XVTC_ACTIVE_HSIZE_SHIFT 0
77 #define XVTC_ACTIVE_HSIZE_MASK (0x1fff << 0)
79 #define XVTC_TIMING_STATUS 0x0004
80 #define XVTC_TIMING_STATUS_ACTIVE_VIDEO (1 << 2)
81 #define XVTC_TIMING_STATUS_VBLANK (1 << 1)
82 #define XVTC_TIMING_STATUS_LOCKED (1 << 0)
84 #define XVTC_ENCODING 0x0008
85 #define XVTC_ENCODING_CHROMA_PARITY_SHIFT 8
86 #define XVTC_ENCODING_CHROMA_PARITY_MASK (3 << 8)
87 #define XVTC_ENCODING_CHROMA_PARITY_EVEN_ALL (0 << 8)
88 #define XVTC_ENCODING_CHROMA_PARITY_ODD_ALL (1 << 8)
89 #define XVTC_ENCODING_CHROMA_PARITY_EVEN_EVEN (2 << 8)
90 #define XVTC_ENCODING_CHROMA_PARITY_ODD_EVEN (3 << 8)
91 #define XVTC_ENCODING_VIDEO_FORMAT_SHIFT 0
92 #define XVTC_ENCODING_VIDEO_FORMAT_MASK (0xf << 0)
93 #define XVTC_ENCODING_VIDEO_FORMAT_YUV422 (0 << 0)
94 #define XVTC_ENCODING_VIDEO_FORMAT_YUV444 (1 << 0)
95 #define XVTC_ENCODING_VIDEO_FORMAT_RGB (2 << 0)
96 #define XVTC_ENCODING_VIDEO_FORMAT_YUV420 (3 << 0)
98 #define XVTC_POLARITY 0x000c
99 #define XVTC_POLARITY_ACTIVE_CHROMA_POL (1 << 5)
100 #define XVTC_POLARITY_ACTIVE_VIDEO_POL (1 << 4)
101 #define XVTC_POLARITY_HSYNC_POL (1 << 3)
102 #define XVTC_POLARITY_VSYNC_POL (1 << 2)
103 #define XVTC_POLARITY_HBLANK_POL (1 << 1)
104 #define XVTC_POLARITY_VBLANK_POL (1 << 0)
106 #define XVTC_HSIZE 0x0010
107 #define XVTC_HSIZE_MASK (0x1fff << 0)
109 #define XVTC_VSIZE 0x0014
110 #define XVTC_VSIZE_MASK (0x1fff << 0)
112 #define XVTC_HSYNC 0x0018
113 #define XVTC_HSYNC_END_SHIFT 16
114 #define XVTC_HSYNC_END_MASK (0x1fff << 16)
115 #define XVTC_HSYNC_START_SHIFT 0
116 #define XVTC_HSYNC_START_MASK (0x1fff << 0)
118 #define XVTC_F0_VBLANK_H 0x001c
119 #define XVTC_F0_VBLANK_HEND_SHIFT 16
120 #define XVTC_F0_VBLANK_HEND_MASK (0x1fff << 16)
121 #define XVTC_F0_VBLANK_HSTART_SHIFT 0
122 #define XVTC_F0_VBLANK_HSTART_MASK (0x1fff << 0)
124 #define XVTC_F0_VSYNC_V 0x0020
125 #define XVTC_F0_VSYNC_VEND_SHIFT 16
126 #define XVTC_F0_VSYNC_VEND_MASK (0x1fff << 16)
127 #define XVTC_F0_VSYNC_VSTART_SHIFT 0
128 #define XVTC_F0_VSYNC_VSTART_MASK (0x1fff << 0)
130 #define XVTC_F0_VSYNC_H 0x0024
131 #define XVTC_F0_VSYNC_HEND_SHIFT 16
132 #define XVTC_F0_VSYNC_HEND_MASK (0x1fff << 16)
133 #define XVTC_F0_VSYNC_HSTART_SHIFT 0
134 #define XVTC_F0_VSYNC_HSTART_MASK (0x1fff << 0)
136 #define XVTC_FRAME_SYNC_CONFIG(n) (0x0100 + 4 * (n))
137 #define XVTC_FRAME_SYNC_V_START_SHIFT 16
138 #define XVTC_FRAME_SYNC_V_START_MASK (0x1fff << 16)
139 #define XVTC_FRAME_SYNC_H_START_SHIFT 0
140 #define XVTC_FRAME_SYNC_H_START_MASK (0x1fff << 0)
142 #define XVTC_GENERATOR_GLOBAL_DELAY 0x0104
145 * struct xvtc_device - Xilinx Video Timing Controller device structure
146 * @xvip: Xilinx Video IP device
147 * @list: entry in the global VTC list
148 * @has_detector: the VTC has a timing detector
149 * @has_generator: the VTC has a timing generator
150 * @config: generator timings configuration
153 struct xvip_device xvip
;
154 struct list_head list
;
159 struct xvtc_config config
;
162 static LIST_HEAD(xvtc_list
);
163 static DEFINE_MUTEX(xvtc_lock
);
165 static inline void xvtc_gen_write(struct xvtc_device
*xvtc
, u32 addr
, u32 value
)
167 xvip_write(&xvtc
->xvip
, XVTC_GENERATOR_OFFSET
+ addr
, value
);
170 /* -----------------------------------------------------------------------------
171 * Generator Operations
174 int xvtc_generator_start(struct xvtc_device
*xvtc
,
175 const struct xvtc_config
*config
)
179 if (!xvtc
->has_generator
)
182 ret
= clk_prepare_enable(xvtc
->xvip
.clk
);
186 /* We don't care about the chroma active signal, encoding parameters are
187 * not important for now.
189 xvtc_gen_write(xvtc
, XVTC_POLARITY
,
190 XVTC_POLARITY_ACTIVE_CHROMA_POL
|
191 XVTC_POLARITY_ACTIVE_VIDEO_POL
|
192 XVTC_POLARITY_HSYNC_POL
| XVTC_POLARITY_VSYNC_POL
|
193 XVTC_POLARITY_HBLANK_POL
| XVTC_POLARITY_VBLANK_POL
);
195 /* Hardcode the polarity to active high, as required by the video in to
198 xvtc_gen_write(xvtc
, XVTC_ENCODING
, 0);
200 /* Configure the timings. The VBLANK and VSYNC signals assertion and
201 * deassertion are hardcoded to the first pixel of the line.
203 xvtc_gen_write(xvtc
, XVTC_ACTIVE_SIZE
,
204 (config
->vblank_start
<< XVTC_ACTIVE_VSIZE_SHIFT
) |
205 (config
->hblank_start
<< XVTC_ACTIVE_HSIZE_SHIFT
));
206 xvtc_gen_write(xvtc
, XVTC_HSIZE
, config
->hsize
);
207 xvtc_gen_write(xvtc
, XVTC_VSIZE
, config
->vsize
);
208 xvtc_gen_write(xvtc
, XVTC_HSYNC
,
209 (config
->hsync_end
<< XVTC_HSYNC_END_SHIFT
) |
210 (config
->hsync_start
<< XVTC_HSYNC_START_SHIFT
));
211 xvtc_gen_write(xvtc
, XVTC_F0_VBLANK_H
, 0);
212 xvtc_gen_write(xvtc
, XVTC_F0_VSYNC_V
,
213 (config
->vsync_end
<< XVTC_F0_VSYNC_VEND_SHIFT
) |
214 (config
->vsync_start
<< XVTC_F0_VSYNC_VSTART_SHIFT
));
215 xvtc_gen_write(xvtc
, XVTC_F0_VSYNC_H
, 0);
217 /* Enable the generator. Set the source of all generator parameters to
218 * generator registers.
220 xvip_write(&xvtc
->xvip
, XVIP_CTRL_CONTROL
,
221 XVTC_CONTROL_ACTIVE_CHROMA_POL_SRC
|
222 XVTC_CONTROL_ACTIVE_VIDEO_POL_SRC
|
223 XVTC_CONTROL_HSYNC_POL_SRC
| XVTC_CONTROL_VSYNC_POL_SRC
|
224 XVTC_CONTROL_HBLANK_POL_SRC
| XVTC_CONTROL_VBLANK_POL_SRC
|
225 XVTC_CONTROL_CHROMA_SRC
| XVTC_CONTROL_VBLANK_HOFF_SRC
|
226 XVTC_CONTROL_VSYNC_END_SRC
| XVTC_CONTROL_VSYNC_START_SRC
|
227 XVTC_CONTROL_ACTIVE_VSIZE_SRC
|
228 XVTC_CONTROL_FRAME_VSIZE_SRC
| XVTC_CONTROL_HSYNC_END_SRC
|
229 XVTC_CONTROL_HSYNC_START_SRC
|
230 XVTC_CONTROL_ACTIVE_HSIZE_SRC
|
231 XVTC_CONTROL_FRAME_HSIZE_SRC
| XVTC_CONTROL_GEN_ENABLE
|
232 XVIP_CTRL_CONTROL_REG_UPDATE
);
236 EXPORT_SYMBOL_GPL(xvtc_generator_start
);
238 int xvtc_generator_stop(struct xvtc_device
*xvtc
)
240 if (!xvtc
->has_generator
)
243 xvip_write(&xvtc
->xvip
, XVIP_CTRL_CONTROL
, 0);
245 clk_disable_unprepare(xvtc
->xvip
.clk
);
249 EXPORT_SYMBOL_GPL(xvtc_generator_stop
);
251 struct xvtc_device
*xvtc_of_get(struct device_node
*np
)
253 struct device_node
*xvtc_node
;
254 struct xvtc_device
*found
= NULL
;
255 struct xvtc_device
*xvtc
;
257 if (!of_find_property(np
, "xlnx,vtc", NULL
))
260 xvtc_node
= of_parse_phandle(np
, "xlnx,vtc", 0);
261 if (xvtc_node
== NULL
)
262 return ERR_PTR(-EINVAL
);
264 mutex_lock(&xvtc_lock
);
265 list_for_each_entry(xvtc
, &xvtc_list
, list
) {
266 if (xvtc
->xvip
.dev
->of_node
== xvtc_node
) {
271 mutex_unlock(&xvtc_lock
);
273 of_node_put(xvtc_node
);
276 return ERR_PTR(-EPROBE_DEFER
);
280 EXPORT_SYMBOL_GPL(xvtc_of_get
);
282 void xvtc_put(struct xvtc_device
*xvtc
)
285 EXPORT_SYMBOL_GPL(xvtc_put
);
287 /* -----------------------------------------------------------------------------
288 * Registration and Unregistration
291 static void xvtc_register_device(struct xvtc_device
*xvtc
)
293 mutex_lock(&xvtc_lock
);
294 list_add_tail(&xvtc
->list
, &xvtc_list
);
295 mutex_unlock(&xvtc_lock
);
298 static void xvtc_unregister_device(struct xvtc_device
*xvtc
)
300 mutex_lock(&xvtc_lock
);
301 list_del(&xvtc
->list
);
302 mutex_unlock(&xvtc_lock
);
305 /* -----------------------------------------------------------------------------
306 * Platform Device Driver
309 static int xvtc_parse_of(struct xvtc_device
*xvtc
)
311 struct device_node
*node
= xvtc
->xvip
.dev
->of_node
;
313 xvtc
->has_detector
= of_property_read_bool(node
, "xlnx,detector");
314 xvtc
->has_generator
= of_property_read_bool(node
, "xlnx,generator");
319 static int xvtc_probe(struct platform_device
*pdev
)
321 struct xvtc_device
*xvtc
;
324 xvtc
= devm_kzalloc(&pdev
->dev
, sizeof(*xvtc
), GFP_KERNEL
);
328 xvtc
->xvip
.dev
= &pdev
->dev
;
330 ret
= xvtc_parse_of(xvtc
);
334 ret
= xvip_init_resources(&xvtc
->xvip
);
338 platform_set_drvdata(pdev
, xvtc
);
340 xvip_print_version(&xvtc
->xvip
);
342 xvtc_register_device(xvtc
);
347 static int xvtc_remove(struct platform_device
*pdev
)
349 struct xvtc_device
*xvtc
= platform_get_drvdata(pdev
);
351 xvtc_unregister_device(xvtc
);
353 xvip_cleanup_resources(&xvtc
->xvip
);
358 static const struct of_device_id xvtc_of_id_table
[] = {
359 { .compatible
= "xlnx,v-tc-6.1" },
362 MODULE_DEVICE_TABLE(of
, xvtc_of_id_table
);
364 static struct platform_driver xvtc_driver
= {
366 .name
= "xilinx-vtc",
367 .of_match_table
= xvtc_of_id_table
,
370 .remove
= xvtc_remove
,
373 module_platform_driver(xvtc_driver
);
375 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
376 MODULE_DESCRIPTION("Xilinx Video Timing Controller Driver");
377 MODULE_LICENSE("GPL v2");