1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Xilinx Video Timing Controller 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/clk.h> 13 #include <linux/module.h> 14 #include <linux/of.h> 15 #include <linux/platform_device.h> 16 #include <linux/slab.h> 17 18 #include "xilinx-vip.h" 19 #include "xilinx-vtc.h" 20 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) 41 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) 49 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) 56 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) 64 65 /* 66 * The following registers exist in two blocks, one at 0x0020 for the detector 67 * and one at 0x0060 for the generator. 68 */ 69 70 #define XVTC_DETECTOR_OFFSET 0x0020 71 #define XVTC_GENERATOR_OFFSET 0x0060 72 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) 78 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) 83 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) 97 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) 105 106 #define XVTC_HSIZE 0x0010 107 #define XVTC_HSIZE_MASK (0x1fff << 0) 108 109 #define XVTC_VSIZE 0x0014 110 #define XVTC_VSIZE_MASK (0x1fff << 0) 111 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) 117 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) 123 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) 129 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) 135 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) 141 142 #define XVTC_GENERATOR_GLOBAL_DELAY 0x0104 143 144 /** 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 151 */ 152 struct xvtc_device { 153 struct xvip_device xvip; 154 struct list_head list; 155 156 bool has_detector; 157 bool has_generator; 158 159 struct xvtc_config config; 160 }; 161 162 static LIST_HEAD(xvtc_list); 163 static DEFINE_MUTEX(xvtc_lock); 164 165 static inline void xvtc_gen_write(struct xvtc_device *xvtc, u32 addr, u32 value) 166 { 167 xvip_write(&xvtc->xvip, XVTC_GENERATOR_OFFSET + addr, value); 168 } 169 170 /* ----------------------------------------------------------------------------- 171 * Generator Operations 172 */ 173 174 int xvtc_generator_start(struct xvtc_device *xvtc, 175 const struct xvtc_config *config) 176 { 177 int ret; 178 179 if (!xvtc->has_generator) 180 return -ENXIO; 181 182 ret = clk_prepare_enable(xvtc->xvip.clk); 183 if (ret < 0) 184 return ret; 185 186 /* We don't care about the chroma active signal, encoding parameters are 187 * not important for now. 188 */ 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); 194 195 /* Hardcode the polarity to active high, as required by the video in to 196 * AXI4-stream core. 197 */ 198 xvtc_gen_write(xvtc, XVTC_ENCODING, 0); 199 200 /* Configure the timings. The VBLANK and VSYNC signals assertion and 201 * deassertion are hardcoded to the first pixel of the line. 202 */ 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); 216 217 /* Enable the generator. Set the source of all generator parameters to 218 * generator registers. 219 */ 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); 233 234 return 0; 235 } 236 EXPORT_SYMBOL_GPL(xvtc_generator_start); 237 238 int xvtc_generator_stop(struct xvtc_device *xvtc) 239 { 240 if (!xvtc->has_generator) 241 return -ENXIO; 242 243 xvip_write(&xvtc->xvip, XVIP_CTRL_CONTROL, 0); 244 245 clk_disable_unprepare(xvtc->xvip.clk); 246 247 return 0; 248 } 249 EXPORT_SYMBOL_GPL(xvtc_generator_stop); 250 251 struct xvtc_device *xvtc_of_get(struct device_node *np) 252 { 253 struct device_node *xvtc_node; 254 struct xvtc_device *found = NULL; 255 struct xvtc_device *xvtc; 256 257 if (!of_find_property(np, "xlnx,vtc", NULL)) 258 return NULL; 259 260 xvtc_node = of_parse_phandle(np, "xlnx,vtc", 0); 261 if (xvtc_node == NULL) 262 return ERR_PTR(-EINVAL); 263 264 mutex_lock(&xvtc_lock); 265 list_for_each_entry(xvtc, &xvtc_list, list) { 266 if (xvtc->xvip.dev->of_node == xvtc_node) { 267 found = xvtc; 268 break; 269 } 270 } 271 mutex_unlock(&xvtc_lock); 272 273 of_node_put(xvtc_node); 274 275 if (!found) 276 return ERR_PTR(-EPROBE_DEFER); 277 278 return found; 279 } 280 EXPORT_SYMBOL_GPL(xvtc_of_get); 281 282 void xvtc_put(struct xvtc_device *xvtc) 283 { 284 } 285 EXPORT_SYMBOL_GPL(xvtc_put); 286 287 /* ----------------------------------------------------------------------------- 288 * Registration and Unregistration 289 */ 290 291 static void xvtc_register_device(struct xvtc_device *xvtc) 292 { 293 mutex_lock(&xvtc_lock); 294 list_add_tail(&xvtc->list, &xvtc_list); 295 mutex_unlock(&xvtc_lock); 296 } 297 298 static void xvtc_unregister_device(struct xvtc_device *xvtc) 299 { 300 mutex_lock(&xvtc_lock); 301 list_del(&xvtc->list); 302 mutex_unlock(&xvtc_lock); 303 } 304 305 /* ----------------------------------------------------------------------------- 306 * Platform Device Driver 307 */ 308 309 static int xvtc_parse_of(struct xvtc_device *xvtc) 310 { 311 struct device_node *node = xvtc->xvip.dev->of_node; 312 313 xvtc->has_detector = of_property_read_bool(node, "xlnx,detector"); 314 xvtc->has_generator = of_property_read_bool(node, "xlnx,generator"); 315 316 return 0; 317 } 318 319 static int xvtc_probe(struct platform_device *pdev) 320 { 321 struct xvtc_device *xvtc; 322 int ret; 323 324 xvtc = devm_kzalloc(&pdev->dev, sizeof(*xvtc), GFP_KERNEL); 325 if (!xvtc) 326 return -ENOMEM; 327 328 xvtc->xvip.dev = &pdev->dev; 329 330 ret = xvtc_parse_of(xvtc); 331 if (ret < 0) 332 return ret; 333 334 ret = xvip_init_resources(&xvtc->xvip); 335 if (ret < 0) 336 return ret; 337 338 platform_set_drvdata(pdev, xvtc); 339 340 xvip_print_version(&xvtc->xvip); 341 342 xvtc_register_device(xvtc); 343 344 return 0; 345 } 346 347 static int xvtc_remove(struct platform_device *pdev) 348 { 349 struct xvtc_device *xvtc = platform_get_drvdata(pdev); 350 351 xvtc_unregister_device(xvtc); 352 353 xvip_cleanup_resources(&xvtc->xvip); 354 355 return 0; 356 } 357 358 static const struct of_device_id xvtc_of_id_table[] = { 359 { .compatible = "xlnx,v-tc-6.1" }, 360 { } 361 }; 362 MODULE_DEVICE_TABLE(of, xvtc_of_id_table); 363 364 static struct platform_driver xvtc_driver = { 365 .driver = { 366 .name = "xilinx-vtc", 367 .of_match_table = xvtc_of_id_table, 368 }, 369 .probe = xvtc_probe, 370 .remove = xvtc_remove, 371 }; 372 373 module_platform_driver(xvtc_driver); 374 375 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 376 MODULE_DESCRIPTION("Xilinx Video Timing Controller Driver"); 377 MODULE_LICENSE("GPL v2"); 378