2 * Xilinx Video Timing Controller
4 * Copyright (C) 2013-2015 Ideas on Board
5 * Copyright (C) 2013-2015 Xilinx, Inc.
7 * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
8 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
15 #include <linux/clk.h>
16 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
21 #include "xilinx-vip.h"
22 #include "xilinx-vtc.h"
24 #define XVTC_CONTROL_FIELD_ID_POL_SRC (1 << 26)
25 #define XVTC_CONTROL_ACTIVE_CHROMA_POL_SRC (1 << 25)
26 #define XVTC_CONTROL_ACTIVE_VIDEO_POL_SRC (1 << 24)
27 #define XVTC_CONTROL_HSYNC_POL_SRC (1 << 23)
28 #define XVTC_CONTROL_VSYNC_POL_SRC (1 << 22)
29 #define XVTC_CONTROL_HBLANK_POL_SRC (1 << 21)
30 #define XVTC_CONTROL_VBLANK_POL_SRC (1 << 20)
31 #define XVTC_CONTROL_CHROMA_SRC (1 << 18)
32 #define XVTC_CONTROL_VBLANK_HOFF_SRC (1 << 17)
33 #define XVTC_CONTROL_VSYNC_END_SRC (1 << 16)
34 #define XVTC_CONTROL_VSYNC_START_SRC (1 << 15)
35 #define XVTC_CONTROL_ACTIVE_VSIZE_SRC (1 << 14)
36 #define XVTC_CONTROL_FRAME_VSIZE_SRC (1 << 13)
37 #define XVTC_CONTROL_HSYNC_END_SRC (1 << 11)
38 #define XVTC_CONTROL_HSYNC_START_SRC (1 << 10)
39 #define XVTC_CONTROL_ACTIVE_HSIZE_SRC (1 << 9)
40 #define XVTC_CONTROL_FRAME_HSIZE_SRC (1 << 8)
41 #define XVTC_CONTROL_SYNC_ENABLE (1 << 5)
42 #define XVTC_CONTROL_DET_ENABLE (1 << 3)
43 #define XVTC_CONTROL_GEN_ENABLE (1 << 2)
45 #define XVTC_STATUS_FSYNC(n) ((n) << 16)
46 #define XVTC_STATUS_GEN_ACTIVE_VIDEO (1 << 13)
47 #define XVTC_STATUS_GEN_VBLANK (1 << 12)
48 #define XVTC_STATUS_DET_ACTIVE_VIDEO (1 << 11)
49 #define XVTC_STATUS_DET_VBLANK (1 << 10)
50 #define XVTC_STATUS_LOCK_LOSS (1 << 9)
51 #define XVTC_STATUS_LOCK (1 << 8)
53 #define XVTC_ERROR_ACTIVE_CHROMA_LOCK (1 << 21)
54 #define XVTC_ERROR_ACTIVE_VIDEO_LOCK (1 << 20)
55 #define XVTC_ERROR_HSYNC_LOCK (1 << 19)
56 #define XVTC_ERROR_VSYNC_LOCK (1 << 18)
57 #define XVTC_ERROR_HBLANK_LOCK (1 << 17)
58 #define XVTC_ERROR_VBLANK_LOCK (1 << 16)
60 #define XVTC_IRQ_ENABLE_FSYNC(n) ((n) << 16)
61 #define XVTC_IRQ_ENABLE_GEN_ACTIVE_VIDEO (1 << 13)
62 #define XVTC_IRQ_ENABLE_GEN_VBLANK (1 << 12)
63 #define XVTC_IRQ_ENABLE_DET_ACTIVE_VIDEO (1 << 11)
64 #define XVTC_IRQ_ENABLE_DET_VBLANK (1 << 10)
65 #define XVTC_IRQ_ENABLE_LOCK_LOSS (1 << 9)
66 #define XVTC_IRQ_ENABLE_LOCK (1 << 8)
69 * The following registers exist in two blocks, one at 0x0020 for the detector
70 * and one at 0x0060 for the generator.
73 #define XVTC_DETECTOR_OFFSET 0x0020
74 #define XVTC_GENERATOR_OFFSET 0x0060
76 #define XVTC_ACTIVE_SIZE 0x0000
77 #define XVTC_ACTIVE_VSIZE_SHIFT 16
78 #define XVTC_ACTIVE_VSIZE_MASK (0x1fff << 16)
79 #define XVTC_ACTIVE_HSIZE_SHIFT 0
80 #define XVTC_ACTIVE_HSIZE_MASK (0x1fff << 0)
82 #define XVTC_TIMING_STATUS 0x0004
83 #define XVTC_TIMING_STATUS_ACTIVE_VIDEO (1 << 2)
84 #define XVTC_TIMING_STATUS_VBLANK (1 << 1)
85 #define XVTC_TIMING_STATUS_LOCKED (1 << 0)
87 #define XVTC_ENCODING 0x0008
88 #define XVTC_ENCODING_CHROMA_PARITY_SHIFT 8
89 #define XVTC_ENCODING_CHROMA_PARITY_MASK (3 << 8)
90 #define XVTC_ENCODING_CHROMA_PARITY_EVEN_ALL (0 << 8)
91 #define XVTC_ENCODING_CHROMA_PARITY_ODD_ALL (1 << 8)
92 #define XVTC_ENCODING_CHROMA_PARITY_EVEN_EVEN (2 << 8)
93 #define XVTC_ENCODING_CHROMA_PARITY_ODD_EVEN (3 << 8)
94 #define XVTC_ENCODING_VIDEO_FORMAT_SHIFT 0
95 #define XVTC_ENCODING_VIDEO_FORMAT_MASK (0xf << 0)
96 #define XVTC_ENCODING_VIDEO_FORMAT_YUV422 (0 << 0)
97 #define XVTC_ENCODING_VIDEO_FORMAT_YUV444 (1 << 0)
98 #define XVTC_ENCODING_VIDEO_FORMAT_RGB (2 << 0)
99 #define XVTC_ENCODING_VIDEO_FORMAT_YUV420 (3 << 0)
101 #define XVTC_POLARITY 0x000c
102 #define XVTC_POLARITY_ACTIVE_CHROMA_POL (1 << 5)
103 #define XVTC_POLARITY_ACTIVE_VIDEO_POL (1 << 4)
104 #define XVTC_POLARITY_HSYNC_POL (1 << 3)
105 #define XVTC_POLARITY_VSYNC_POL (1 << 2)
106 #define XVTC_POLARITY_HBLANK_POL (1 << 1)
107 #define XVTC_POLARITY_VBLANK_POL (1 << 0)
109 #define XVTC_HSIZE 0x0010
110 #define XVTC_HSIZE_MASK (0x1fff << 0)
112 #define XVTC_VSIZE 0x0014
113 #define XVTC_VSIZE_MASK (0x1fff << 0)
115 #define XVTC_HSYNC 0x0018
116 #define XVTC_HSYNC_END_SHIFT 16
117 #define XVTC_HSYNC_END_MASK (0x1fff << 16)
118 #define XVTC_HSYNC_START_SHIFT 0
119 #define XVTC_HSYNC_START_MASK (0x1fff << 0)
121 #define XVTC_F0_VBLANK_H 0x001c
122 #define XVTC_F0_VBLANK_HEND_SHIFT 16
123 #define XVTC_F0_VBLANK_HEND_MASK (0x1fff << 16)
124 #define XVTC_F0_VBLANK_HSTART_SHIFT 0
125 #define XVTC_F0_VBLANK_HSTART_MASK (0x1fff << 0)
127 #define XVTC_F0_VSYNC_V 0x0020
128 #define XVTC_F0_VSYNC_VEND_SHIFT 16
129 #define XVTC_F0_VSYNC_VEND_MASK (0x1fff << 16)
130 #define XVTC_F0_VSYNC_VSTART_SHIFT 0
131 #define XVTC_F0_VSYNC_VSTART_MASK (0x1fff << 0)
133 #define XVTC_F0_VSYNC_H 0x0024
134 #define XVTC_F0_VSYNC_HEND_SHIFT 16
135 #define XVTC_F0_VSYNC_HEND_MASK (0x1fff << 16)
136 #define XVTC_F0_VSYNC_HSTART_SHIFT 0
137 #define XVTC_F0_VSYNC_HSTART_MASK (0x1fff << 0)
139 #define XVTC_FRAME_SYNC_CONFIG(n) (0x0100 + 4 * (n))
140 #define XVTC_FRAME_SYNC_V_START_SHIFT 16
141 #define XVTC_FRAME_SYNC_V_START_MASK (0x1fff << 16)
142 #define XVTC_FRAME_SYNC_H_START_SHIFT 0
143 #define XVTC_FRAME_SYNC_H_START_MASK (0x1fff << 0)
145 #define XVTC_GENERATOR_GLOBAL_DELAY 0x0104
148 * struct xvtc_device - Xilinx Video Timing Controller device structure
149 * @xvip: Xilinx Video IP device
150 * @list: entry in the global VTC list
151 * @has_detector: the VTC has a timing detector
152 * @has_generator: the VTC has a timing generator
153 * @config: generator timings configuration
156 struct xvip_device xvip
;
157 struct list_head list
;
162 struct xvtc_config config
;
165 static LIST_HEAD(xvtc_list
);
166 static DEFINE_MUTEX(xvtc_lock
);
168 static inline void xvtc_gen_write(struct xvtc_device
*xvtc
, u32 addr
, u32 value
)
170 xvip_write(&xvtc
->xvip
, XVTC_GENERATOR_OFFSET
+ addr
, value
);
173 /* -----------------------------------------------------------------------------
174 * Generator Operations
177 int xvtc_generator_start(struct xvtc_device
*xvtc
,
178 const struct xvtc_config
*config
)
182 if (!xvtc
->has_generator
)
185 ret
= clk_prepare_enable(xvtc
->xvip
.clk
);
189 /* We don't care about the chroma active signal, encoding parameters are
190 * not important for now.
192 xvtc_gen_write(xvtc
, XVTC_POLARITY
,
193 XVTC_POLARITY_ACTIVE_CHROMA_POL
|
194 XVTC_POLARITY_ACTIVE_VIDEO_POL
|
195 XVTC_POLARITY_HSYNC_POL
| XVTC_POLARITY_VSYNC_POL
|
196 XVTC_POLARITY_HBLANK_POL
| XVTC_POLARITY_VBLANK_POL
);
198 /* Hardcode the polarity to active high, as required by the video in to
201 xvtc_gen_write(xvtc
, XVTC_ENCODING
, 0);
203 /* Configure the timings. The VBLANK and VSYNC signals assertion and
204 * deassertion are hardcoded to the first pixel of the line.
206 xvtc_gen_write(xvtc
, XVTC_ACTIVE_SIZE
,
207 (config
->vblank_start
<< XVTC_ACTIVE_VSIZE_SHIFT
) |
208 (config
->hblank_start
<< XVTC_ACTIVE_HSIZE_SHIFT
));
209 xvtc_gen_write(xvtc
, XVTC_HSIZE
, config
->hsize
);
210 xvtc_gen_write(xvtc
, XVTC_VSIZE
, config
->vsize
);
211 xvtc_gen_write(xvtc
, XVTC_HSYNC
,
212 (config
->hsync_end
<< XVTC_HSYNC_END_SHIFT
) |
213 (config
->hsync_start
<< XVTC_HSYNC_START_SHIFT
));
214 xvtc_gen_write(xvtc
, XVTC_F0_VBLANK_H
, 0);
215 xvtc_gen_write(xvtc
, XVTC_F0_VSYNC_V
,
216 (config
->vsync_end
<< XVTC_F0_VSYNC_VEND_SHIFT
) |
217 (config
->vsync_start
<< XVTC_F0_VSYNC_VSTART_SHIFT
));
218 xvtc_gen_write(xvtc
, XVTC_F0_VSYNC_H
, 0);
220 /* Enable the generator. Set the source of all generator parameters to
221 * generator registers.
223 xvip_write(&xvtc
->xvip
, XVIP_CTRL_CONTROL
,
224 XVTC_CONTROL_ACTIVE_CHROMA_POL_SRC
|
225 XVTC_CONTROL_ACTIVE_VIDEO_POL_SRC
|
226 XVTC_CONTROL_HSYNC_POL_SRC
| XVTC_CONTROL_VSYNC_POL_SRC
|
227 XVTC_CONTROL_HBLANK_POL_SRC
| XVTC_CONTROL_VBLANK_POL_SRC
|
228 XVTC_CONTROL_CHROMA_SRC
| XVTC_CONTROL_VBLANK_HOFF_SRC
|
229 XVTC_CONTROL_VSYNC_END_SRC
| XVTC_CONTROL_VSYNC_START_SRC
|
230 XVTC_CONTROL_ACTIVE_VSIZE_SRC
|
231 XVTC_CONTROL_FRAME_VSIZE_SRC
| XVTC_CONTROL_HSYNC_END_SRC
|
232 XVTC_CONTROL_HSYNC_START_SRC
|
233 XVTC_CONTROL_ACTIVE_HSIZE_SRC
|
234 XVTC_CONTROL_FRAME_HSIZE_SRC
| XVTC_CONTROL_GEN_ENABLE
|
235 XVIP_CTRL_CONTROL_REG_UPDATE
);
239 EXPORT_SYMBOL_GPL(xvtc_generator_start
);
241 int xvtc_generator_stop(struct xvtc_device
*xvtc
)
243 if (!xvtc
->has_generator
)
246 xvip_write(&xvtc
->xvip
, XVIP_CTRL_CONTROL
, 0);
248 clk_disable_unprepare(xvtc
->xvip
.clk
);
252 EXPORT_SYMBOL_GPL(xvtc_generator_stop
);
254 struct xvtc_device
*xvtc_of_get(struct device_node
*np
)
256 struct device_node
*xvtc_node
;
257 struct xvtc_device
*found
= NULL
;
258 struct xvtc_device
*xvtc
;
260 if (!of_find_property(np
, "xlnx,vtc", NULL
))
263 xvtc_node
= of_parse_phandle(np
, "xlnx,vtc", 0);
264 if (xvtc_node
== NULL
)
265 return ERR_PTR(-EINVAL
);
267 mutex_lock(&xvtc_lock
);
268 list_for_each_entry(xvtc
, &xvtc_list
, list
) {
269 if (xvtc
->xvip
.dev
->of_node
== xvtc_node
) {
274 mutex_unlock(&xvtc_lock
);
276 of_node_put(xvtc_node
);
279 return ERR_PTR(-EPROBE_DEFER
);
283 EXPORT_SYMBOL_GPL(xvtc_of_get
);
285 void xvtc_put(struct xvtc_device
*xvtc
)
288 EXPORT_SYMBOL_GPL(xvtc_put
);
290 /* -----------------------------------------------------------------------------
291 * Registration and Unregistration
294 static void xvtc_register_device(struct xvtc_device
*xvtc
)
296 mutex_lock(&xvtc_lock
);
297 list_add_tail(&xvtc
->list
, &xvtc_list
);
298 mutex_unlock(&xvtc_lock
);
301 static void xvtc_unregister_device(struct xvtc_device
*xvtc
)
303 mutex_lock(&xvtc_lock
);
304 list_del(&xvtc
->list
);
305 mutex_unlock(&xvtc_lock
);
308 /* -----------------------------------------------------------------------------
309 * Platform Device Driver
312 static int xvtc_parse_of(struct xvtc_device
*xvtc
)
314 struct device_node
*node
= xvtc
->xvip
.dev
->of_node
;
316 xvtc
->has_detector
= of_property_read_bool(node
, "xlnx,detector");
317 xvtc
->has_generator
= of_property_read_bool(node
, "xlnx,generator");
322 static int xvtc_probe(struct platform_device
*pdev
)
324 struct xvtc_device
*xvtc
;
327 xvtc
= devm_kzalloc(&pdev
->dev
, sizeof(*xvtc
), GFP_KERNEL
);
331 xvtc
->xvip
.dev
= &pdev
->dev
;
333 ret
= xvtc_parse_of(xvtc
);
337 ret
= xvip_init_resources(&xvtc
->xvip
);
341 platform_set_drvdata(pdev
, xvtc
);
343 xvip_print_version(&xvtc
->xvip
);
345 xvtc_register_device(xvtc
);
350 static int xvtc_remove(struct platform_device
*pdev
)
352 struct xvtc_device
*xvtc
= platform_get_drvdata(pdev
);
354 xvtc_unregister_device(xvtc
);
356 xvip_cleanup_resources(&xvtc
->xvip
);
361 static const struct of_device_id xvtc_of_id_table
[] = {
362 { .compatible
= "xlnx,v-tc-6.1" },
365 MODULE_DEVICE_TABLE(of
, xvtc_of_id_table
);
367 static struct platform_driver xvtc_driver
= {
369 .name
= "xilinx-vtc",
370 .of_match_table
= xvtc_of_id_table
,
373 .remove
= xvtc_remove
,
376 module_platform_driver(xvtc_driver
);
378 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
379 MODULE_DESCRIPTION("Xilinx Video Timing Controller Driver");
380 MODULE_LICENSE("GPL v2");