]> rtime.felk.cvut.cz Git - vajnamar/linux-xlnx.git/blob - drivers/gpu/drm/xilinx/xilinx_drm_sdi.c
drm: xilinx: sdi: adding vblank support
[vajnamar/linux-xlnx.git] / drivers / gpu / drm / xilinx / xilinx_drm_sdi.c
1 /*
2  * Xilinx FPGA SDI Tx Controller driver.
3  *
4  * Copyright (c) 2017 Xilinx Pvt., Ltd
5  *
6  * Contacts: Saurabh Sengar <saurabhs@xilinx.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <drm/drm_crtc_helper.h>
14 #include <drm/drmP.h>
15 #include <linux/component.h>
16 #include <linux/device.h>
17 #include <linux/list.h>
18 #include <linux/of_device.h>
19 #include <linux/of_graph.h>
20 #include <linux/phy/phy.h>
21 #include <video/videomode.h>
22 #include "xilinx_drm_sdi.h"
23 #include "xilinx_vtc.h"
24
25 /* SDI register offsets */
26 #define XSDI_TX_RST_CTRL                                0x00
27 #define XSDI_TX_MDL_CTRL                                0x04
28 #define XSDI_TX_GLBL_IER                                0x0C
29 #define XSDI_TX_ISR_STAT                                0x10
30 #define XSDI_TX_IER_STAT                                0x14
31 #define XSDI_TX_ST352_LINE                              0x18
32 #define XSDI_TX_ST352_DATA_CH0                          0x1C
33 #define XSDI_TX_VER                                     0x3C
34 #define XSDI_TX_SYS_CFG                                 0x40
35 #define XSDI_TX_STS_SB_TDATA                            0x60
36 #define XSDI_TX_AXI4S_STS1                              0x68
37 #define XSDI_TX_AXI4S_STS2                              0x6C
38
39 /* MODULE_CTRL register masks */
40 #define XSDI_TX_CTRL_MDL_EN_MASK                        BIT(0)
41 #define XSDI_TX_CTRL_OUT_EN_MASK                        BIT(1)
42 #define XSDI_TX_CTRL_M_MASK                             BIT(7)
43 #define XSDI_TX_CTRL_INS_CRC_MASK                       BIT(12)
44 #define XSDI_TX_CTRL_INS_ST352_MASK                     BIT(13)
45 #define XSDI_TX_CTRL_OVR_ST352_MASK                     BIT(14)
46 #define XSDI_TX_CTRL_INS_SYNC_BIT_MASK                  BIT(16)
47 #define XSDI_TX_CTRL_SD_BITREP_BYPASS_MASK              BIT(17)
48 #define XSDI_TX_CTRL_USE_ANC_IN_MASK                    BIT(18)
49 #define XSDI_TX_CTRL_INS_LN_MASK                        BIT(19)
50 #define XSDI_TX_CTRL_INS_EDH_MASK                       BIT(20)
51 #define XSDI_TX_CTRL_MODE_MASK                          0x7
52 #define XSDI_TX_CTRL_MUX_MASK                           0x7
53 #define XSDI_TX_CTRL_MODE_SHIFT                         4
54 #define XSDI_TX_CTRL_M_SHIFT                            7
55 #define XSDI_TX_CTRL_MUX_SHIFT                          8
56 #define XSDI_TX_CTRL_INS_CRC_SHIFT                      12
57 #define XSDI_TX_CTRL_INS_ST352_SHIFT                    13
58 #define XSDI_TX_CTRL_OVR_ST352_SHIFT                    14
59 #define XSDI_TX_CTRL_ST352_F2_EN_SHIFT                  15
60 #define XSDI_TX_CTRL_INS_SYNC_BIT_SHIFT                 16
61 #define XSDI_TX_CTRL_SD_BITREP_BYPASS_SHIFT             17
62 #define XSDI_TX_CTRL_USE_ANC_IN_SHIFT                   18
63 #define XSDI_TX_CTRL_INS_LN_SHIFT                       19
64 #define XSDI_TX_CTRL_INS_EDH_SHIFT                      20
65
66 /* TX_ST352_LINE register masks */
67 #define XSDI_TX_ST352_LINE_MASK                         GENMASK(10, 0)
68 #define XSDI_TX_ST352_LINE_F2_SHIFT                     16
69
70 /* ISR STAT register masks */
71 #define XSDI_GTTX_RSTDONE_INTR_MASK                     BIT(0)
72 #define XSDI_TX_CE_ALIGN_ERR_INTR_MASK                  BIT(1)
73 #define XSDI_AXI4S_VID_LOCK_INTR_MASK                   BIT(8)
74 #define XSDI_OVERFLOW_INTR_MASK                         BIT(9)
75 #define XSDI_UNDERFLOW_INTR_MASK                        BIT(10)
76 #define XSDI_IER_EN_MASK                (XSDI_GTTX_RSTDONE_INTR_MASK | \
77                                         XSDI_TX_CE_ALIGN_ERR_INTR_MASK | \
78                                         XSDI_OVERFLOW_INTR_MASK | \
79                                         XSDI_UNDERFLOW_INTR_MASK)
80
81 /* RST_CTRL_OFFSET masks */
82 #define XSDI_TX_BRIDGE_CTRL_EN_MASK                     BIT(8)
83 #define XSDI_TX_AXI4S_CTRL_EN_MASK                      BIT(9)
84 #define XSDI_TX_CTRL_EN_MASK                            BIT(0)
85
86 /* STS_SB_TX_TDATA masks */
87 #define XSDI_TX_TDATA_DONE_MASK                         BIT(0)
88 #define XSDI_TX_TDATA_FAIL_MASK                         BIT(1)
89 #define XSDI_TX_TDATA_GT_RESETDONE_MASK                 BIT(2)
90 #define XSDI_TX_TDATA_SLEW_RATE_MASK                    BIT(3)
91 #define XSDI_TX_TDATA_TXPLLCLKSEL_MASK                  GENMASK(5, 4)
92 #define XSDI_TX_TDATA_GT_SYSCLKSEL_MASK                 GENMASK(7, 6)
93 #define XSDI_TX_TDATA_FABRIC_RST_MASK                   BIT(8)
94 #define XSDI_TX_TDATA_DRP_FAIL_MASK                     BIT(9)
95 #define XSDI_TX_TDATA_FAIL_CODE_MASK                    GENMASK(14, 12)
96 #define XSDI_TX_TDATA_DRP_FAIL_CNT_MASK                 0xFF0000
97 #define XSDI_TX_TDATA_GT_QPLL0LOCK_MASK                 BIT(24)
98 #define XSDI_TX_TDATA_GT_QPLL1LOCK_MASK                 BIT(25)
99
100 #define SDI_MAX_DATASTREAM                                      8
101
102 #define XSDI_TX_MUX_SD_HD_3GA                   0
103 #define XSDI_TX_MUX_3GB                         1
104 #define XSDI_TX_MUX_8STREAM_6G_12G              2
105 #define XSDI_TX_MUX_4STREAM_6G                  3
106 #define XSDI_TX_MUX_16STREAM_12G                4
107
108 #define PIXELS_PER_CLK                          2
109 #define XSDI_CH_SHIFT                           29
110 #define XST352_PROG_PIC_MASK                    BIT(6)
111 #define XST352_PROG_TRANS_MASK                  BIT(7)
112 #define XST352_2048_SHIFT                       BIT(6)
113 #define ST352_BYTE3                             0x00
114 #define ST352_BYTE4                             0x01
115 #define INVALID_VALUE                           -1
116 #define GT_TIMEOUT                              500
117
118 static LIST_HEAD(xilinx_sdi_list);
119 static DEFINE_MUTEX(xilinx_sdi_lock);
120 /**
121  * enum payload_line_1 - Payload Ids Line 1 number
122  * @PAYLD_LN1_HD_3_6_12G:       line 1 HD,3G,6G or 12G mode value
123  * @PAYLD_LN1_SDPAL:            line 1 SD PAL mode value
124  * @PAYLD_LN1_SDNTSC:           line 1 SD NTSC mode value
125  */
126 enum payload_line_1 {
127         PAYLD_LN1_HD_3_6_12G = 10,
128         PAYLD_LN1_SDPAL = 9,
129         PAYLD_LN1_SDNTSC = 13
130 };
131
132 /**
133  * enum payload_line_2 - Payload Ids Line 2 number
134  * @PAYLD_LN2_HD_3_6_12G:       line 2 HD,3G,6G or 12G mode value
135  * @PAYLD_LN2_SDPAL:            line 2 SD PAL mode value
136  * @PAYLD_LN2_SDNTSC:           line 2 SD NTSC mode value
137  */
138 enum payload_line_2 {
139         PAYLD_LN2_HD_3_6_12G = 572,
140         PAYLD_LN2_SDPAL = 322,
141         PAYLD_LN2_SDNTSC = 276
142 };
143
144 /**
145  * enum sdi_modes - SDI modes
146  * @XSDI_MODE_HD:       HD mode
147  * @XSDI_MODE_SD:       SD mode
148  * @XSDI_MODE_3GA:      3GA mode
149  * @XSDI_MODE_3GB:      3GB mode
150  * @XSDI_MODE_6G:       6G mode
151  * @XSDI_MODE_12G:      12G mode
152  */
153 enum sdi_modes {
154         XSDI_MODE_HD = 0,
155         XSDI_MODE_SD,
156         XSDI_MODE_3GA,
157         XSDI_MODE_3GB,
158         XSDI_MODE_6G,
159         XSDI_MODE_12G
160 };
161
162 /**
163  * struct xilinx_sdi - Core configuration SDI Tx subsystem device structure
164  * @encoder: DRM encoder structure
165  * @connector: DRM connector structure
166  * @vtc: Pointer to VTC structure
167  * @dev: device structure
168  * @base: Base address of SDI subsystem
169  * @mode_flags: SDI operation mode related flags
170  * @wait_event: wait event
171  * @event_received: wait event status
172  * @list: entry in the global SDI subsystem list
173  * @vblank_fn: vblank handler
174  * @vblank_data: vblank data to be used in vblank_fn
175  * @sdi_mode: configurable SDI mode parameter, supported values are:
176  *              0 - HD
177  *              1 - SD
178  *              2 - 3GA
179  *              3 - 3GB
180  *              4 - 6G
181  *              5 - 12G
182  * @sdi_mod_prop_val: configurable SDI mode parameter value
183  * @sdi_data_strm: configurable SDI data stream parameter
184  * @sdi_data_strm_prop_val: configurable number of SDI data streams
185  *                          value currently supported are 2, 4 and 8
186  * @is_frac_prop: configurable SDI fractional fps parameter
187  * @is_frac_prop_val: configurable SDI fractional fps parameter value
188  */
189 struct xilinx_sdi {
190         struct drm_encoder encoder;
191         struct drm_connector connector;
192         struct xilinx_vtc *vtc;
193         struct device *dev;
194         void __iomem *base;
195         u32 mode_flags;
196         wait_queue_head_t wait_event;
197         bool event_received;
198         struct list_head list;
199         void (*vblank_fn)(void *);
200         void *vblank_data;
201         struct drm_property *sdi_mode;
202         u32 sdi_mod_prop_val;
203         struct drm_property *sdi_data_strm;
204         u32 sdi_data_strm_prop_val;
205         struct drm_property *is_frac_prop;
206         bool is_frac_prop_val;
207 };
208
209 /**
210  * struct xilinx_sdi_display_config - SDI supported modes structure
211  * @mode: drm display mode
212  * @st352_byt2: st352 byte 2 value
213  *              index 0 : value for integral fps
214  *              index 1 : value for fractional fps
215  * @st352_byt1: st352 byte 1 value
216  *              index 0 : value for HD mode
217  *              index 1 : value for SD mode
218  *              index 2 : value for 3GA
219  *              index 3 : value for 3GB
220  *              index 4 : value for 6G
221  *              index 5 : value for 12G
222  */
223 struct xlnx_sdi_display_config {
224         struct drm_display_mode mode;
225         u8 st352_byt2[2];
226         u8 st352_byt1[6];
227 };
228
229 /*
230  * xlnx_sdi_modes - SDI DRM modes
231  */
232 static const struct xlnx_sdi_display_config xlnx_sdi_modes[] = {
233         /* 0 - dummy, VICs start at 1 */
234         { },
235         /* SD: 720x480i@60Hz */
236         {{ DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, 720, 739,
237                    801, 858, 0, 240, 244, 247, 262, 0,
238                    DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
239                    DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
240                    .vrefresh = 60, }, {0x7, 0x6},
241                    {0x81, 0x81, 0x81, 0x81, 0x81, 0x81} },
242         /* SD: 720x576i@50Hz */
243         {{ DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, 720, 732,
244                    795, 864, 0, 288, 290, 293, 312, 0,
245                    DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
246                    DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
247                    .vrefresh = 50, }, {0x9, 0x9},
248                    {0x81, 0x81, 0x81, 0x81, 0x81, 0x81} },
249         /* HD: 1280x720@25Hz */
250         {{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 2250,
251                    2990, 3960, 0, 720, 725, 730, 750, 0,
252                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
253                    .vrefresh = 25, }, {0x5, 0x5},
254                    {0x84, 0x84, 0x88, 0x84, 0x84, 0x84} },
255         /* HD: 1280x720@24Hz */
256         {{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 2250,
257                    3155, 4125, 0, 720, 725, 730, 750, 0,
258                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
259                    .vrefresh = 24, }, {0x3, 0x2},
260                    {0x84, 0x84, 0x88, 0x84, 0x84, 0x84} },
261         /* HD: 1280x720@30Hz */
262          {{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 2250,
263                    2330, 3300, 0, 720, 725, 730, 750, 0,
264                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
265                    .vrefresh = 30, }, {0x7, 0x6},
266                    {0x84, 0x84, 0x88, 0x84, 0x84, 0x84} },
267         /* HD: 1280x720@50Hz */
268         {{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
269                    1760, 1980, 0, 720, 725, 730, 750, 0,
270                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
271                    .vrefresh = 50, }, {0x9, 0x9},
272                    {0x84, 0x84, 0x88, 0x84, 0x84, 0x84} },
273         /* HD: 1280x720@60Hz */
274         {{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
275                    1430, 1650, 0, 720, 725, 730, 750, 0,
276                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
277                    .vrefresh = 60, }, {0xB, 0xA},
278                    {0x84, 0x84, 0x88, 0x84, 0x84, 0x84} },
279         /* HD: 1920x1080@24Hz */
280         {{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558,
281                    2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
282                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
283                    .vrefresh = 24, }, {0x3, 0x2},
284                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
285         /* HD: 1920x1080@25Hz */
286         {{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
287                    2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
288                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
289                    .vrefresh = 25, }, {0x5, 0x5},
290                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
291         /* HD: 1920x1080@30Hz */
292         {{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
293                    2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
294                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
295                    .vrefresh = 30, }, {0x7, 0x6},
296                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
297         /* HD: 1920x1080i@48Hz */
298         {{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2291,
299                    2379, 2750, 0, 540, 542, 547, 562, 0,
300                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
301                    DRM_MODE_FLAG_INTERLACE),
302                    .vrefresh = 48, }, {0x3, 0x2},
303                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
304         /* HD: 1920x1080i@50Hz */
305         {{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
306                    2492, 2640, 0, 540, 542, 547, 562, 0,
307                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
308                    DRM_MODE_FLAG_INTERLACE),
309                    .vrefresh = 50, }, {0x5, 0x5},
310                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
311         /* HD: 1920x1080i@60Hz */
312         {{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
313                    2052, 2200, 0, 540, 542, 547, 562, 0,
314                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
315                    DRM_MODE_FLAG_INTERLACE),
316                    .vrefresh = 60, }, {0x7, 0x6},
317                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
318         /* HD: 1920x1080sf@24Hz */
319         {{ DRM_MODE("1920x1080sf", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2291,
320                    2379, 2750, 0, 540, 542, 547, 562, 0,
321                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
322                    DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN),
323                    .vrefresh = 48, }, {0x3, 0x2},
324                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
325         /* HD: 1920x1080sf@25Hz */
326         {{ DRM_MODE("1920x1080sf", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
327                    2492, 2640, 0, 540, 542, 547, 562, 0,
328                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
329                    DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN),
330                    .vrefresh = 50, }, {0x5, 0x5},
331                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
332         /* HD: 1920x1080sf@30Hz */
333         {{ DRM_MODE("1920x1080sf", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
334                    2052, 2200, 0, 540, 542, 547, 562, 0,
335                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
336                    DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN),
337                    .vrefresh = 60, }, {0x7, 0x6},
338                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
339         /* HD: 2048x1080i@48Hz */
340         {{ DRM_MODE("2048x1080i", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2377,
341                    2421, 2750, 0, 540, 542, 547, 562, 0,
342                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
343                    DRM_MODE_FLAG_INTERLACE),
344                    .vrefresh = 48, }, {0x3, 0x2},
345                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
346         /* HD: 2048x1080i@50Hz */
347         {{ DRM_MODE("2048x1080i", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2322,
348                    2366, 2640, 0, 540, 542, 547, 562, 0,
349                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
350                    DRM_MODE_FLAG_INTERLACE),
351                    .vrefresh = 50, }, {0x5, 0x5},
352                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
353         /* HD: 2048x1080i@60Hz */
354         {{ DRM_MODE("2048x1080i", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2114,
355                    2134, 2200, 0, 540, 542, 547, 562, 0,
356                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
357                    DRM_MODE_FLAG_INTERLACE),
358                    .vrefresh = 60, }, {0x7, 0x6},
359                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
360         /* HD: 2048x1080sf@24Hz */
361         {{ DRM_MODE("2048x1080sf", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2377,
362                    2421, 2750, 0, 540, 542, 547, 562, 0,
363                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
364                    DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN),
365                    .vrefresh = 48, }, {0x3, 0x2},
366                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
367         /* HD: 2048x1080sf@25Hz */
368         {{ DRM_MODE("2048x1080sf", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2322,
369                    2366, 2640, 0, 540, 542, 547, 562, 0,
370                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
371                    DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN),
372                    .vrefresh = 50, }, {0x5, 0x5},
373                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
374         /* HD: 2048x1080sf@30Hz */
375         {{ DRM_MODE("2048x1080sf", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2114,
376                    2134, 2200, 0, 540, 542, 547, 562, 0,
377                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
378                    DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN),
379                    .vrefresh = 60, }, {0x7, 0x6},
380                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
381         /* HD: 2048x1080@30Hz */
382         {{ DRM_MODE("2048x1080", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2114,
383                    2134, 2200, 0, 1080, 1084, 1089, 1125, 0,
384                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
385                    .vrefresh = 30, }, {0x7, 0x6},
386                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
387         /* HD: 2048x1080@25Hz */
388         {{ DRM_MODE("2048x1080", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2448,
389                    2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
390                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
391                    .vrefresh = 25, }, {0x5, 0x5},
392                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
393         /* HD: 2048x1080@24Hz */
394         {{ DRM_MODE("2048x1080", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2558,
395                    2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
396                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
397                    .vrefresh = 24, }, {0x3, 0x2},
398                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
399         /* 3G: 1920x1080@48Hz */
400         {{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2558,
401                    2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
402                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
403                    .vrefresh = 48, }, {0x8, 0x4},
404                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
405         /* 3G: 1920x1080@50Hz */
406         {{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
407                    2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
408                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
409                    .vrefresh = 50, }, {0x9, 0x9},
410                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
411         /* 3G: 1920x1080@60Hz */
412         {{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
413                    2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
414                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
415                    .vrefresh = 60, }, {0xB, 0xA},
416                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
417         /* 3G: 2048x1080@60Hz */
418         {{ DRM_MODE("2048x1080", DRM_MODE_TYPE_DRIVER, 148500, 2048, 2136,
419                    2180, 2200, 0, 1080, 1084, 1089, 1125, 0,
420                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
421                    .vrefresh = 60, }, {0xB, 0xA},
422                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
423         /* 3G: 2048x1080@50Hz */
424         {{ DRM_MODE("2048x1080", DRM_MODE_TYPE_DRIVER, 148500, 2048, 2448,
425                    2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
426                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
427                    .vrefresh = 50, }, {0x9, 0x9},
428                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
429         /* 3G: 2048x1080@48Hz */
430         {{ DRM_MODE("2048x1080", DRM_MODE_TYPE_DRIVER, 148500, 2048, 2558,
431                    2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
432                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
433                    .vrefresh = 48, }, {0x8, 0x4},
434                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
435         /* 3G-B: 1920x1080i@96Hz */
436         {{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2291,
437                    2379, 2750, 0, 1080, 1084, 1094, 1124, 0,
438                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
439                    DRM_MODE_FLAG_INTERLACE),
440                    .vrefresh = 96, }, {0x8, 0x4},
441                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
442         /* 3G-B: 1920x1080i@100Hz */
443         {{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
444                    2492, 2640, 0, 1080, 1084, 1094, 1124, 0,
445                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
446                    DRM_MODE_FLAG_INTERLACE),
447                    .vrefresh = 100, }, {0x9, 0x9},
448                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
449         /* 3G-B: 1920x1080i@120Hz */
450         {{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
451                    2052, 2200, 0, 1080, 1084, 1094, 1124, 0,
452                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
453                    DRM_MODE_FLAG_INTERLACE),
454                    .vrefresh = 120, }, {0xB, 0xA},
455                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
456         /* 3G-B: 2048x1080i@96Hz */
457         {{ DRM_MODE("2048x1080i", DRM_MODE_TYPE_DRIVER, 148500, 2048, 2377,
458                    2421, 2750, 0, 1080, 1084, 1094, 1124, 0,
459                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
460                    DRM_MODE_FLAG_INTERLACE),
461                    .vrefresh = 96, }, {0x8, 0x4},
462                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
463         /* 3G-B: 2048x1080i@100Hz */
464         {{ DRM_MODE("2048x1080i", DRM_MODE_TYPE_DRIVER, 148500, 2048, 2322,
465                    2366, 2640, 0, 1080, 1084, 1094, 1124, 0,
466                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
467                    DRM_MODE_FLAG_INTERLACE),
468                    .vrefresh = 100, }, {0x9, 0x9},
469                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
470         /* 3G-B: 2048x1080i@120Hz */
471         {{ DRM_MODE("2048x1080i", DRM_MODE_TYPE_DRIVER, 148500, 2048, 2114,
472                    2134, 2200, 0, 1080, 1084, 1094, 1124, 0,
473                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
474                    DRM_MODE_FLAG_INTERLACE),
475                    .vrefresh = 120, }, {0xB, 0xA},
476                    {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
477         /* 6G: 3840x2160@30Hz */
478         {{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
479                    4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
480                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
481                    .vrefresh = 30, }, {0x7, 0x6},
482                    {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
483         /* 6G: 3840x2160@25Hz */
484         {{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896,
485                    4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
486                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
487                    .vrefresh = 25, }, {0x5, 0x5},
488                    {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
489         /* 6G: 3840x2160@24Hz */
490         {{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116,
491                    5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
492                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
493                    .vrefresh = 24, }, {0x3, 0x2},
494                    {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
495         /* 6G: 4096x2160@24Hz */
496         {{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 296704, 4096, 5116,
497                    5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
498                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
499                    .vrefresh = 24, }, {0x3, 0x2},
500                    {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
501         /* 6G: 4096x2160@25Hz */
502         {{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5064,
503                    5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
504                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
505                    .vrefresh = 25, }, {0x5, 0x5},
506                    {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
507         /* 6G: 4096x2160@30Hz */
508         {{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 296704, 4096, 4184,
509                    4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
510                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
511                    .vrefresh = 30, }, {0x7, 0x6},
512                    {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
513         /* 12G: 3840x2160@48Hz */
514         {{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 5116,
515                    5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
516                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
517                    .vrefresh = 48, }, {0x8, 0x4},
518                    {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
519         /* 12G: 3840x2160@50Hz */
520         {{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896,
521                    4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
522                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
523                    .vrefresh = 50, }, {0x9, 0x9},
524                    {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
525         /* 12G: 3840x2160@60Hz */
526         {{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
527                    4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
528                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
529                    .vrefresh = 60, }, {0xB, 0xA},
530                    {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
531         /* 12G: 4096x2160@48Hz */
532         {{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5116,
533                    5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
534                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
535                    .vrefresh = 48, }, {0x8, 0x4},
536                    {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
537         /* 12G: 4096x2160@50Hz */
538         {{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5064,
539                    5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
540                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
541                    .vrefresh = 50, }, {0x9, 0x9},
542                    {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
543         /* 12G: 4096x2160@60Hz */
544         {{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 593408, 4096, 4184,
545                    4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
546                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
547                    .vrefresh = 60, }, {0xB, 0xA},
548                    {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
549 };
550
551 #define connector_to_sdi(c) container_of(c, struct xilinx_sdi, connector)
552 #define encoder_to_sdi(e) container_of(e, struct xilinx_sdi, encoder)
553
554 /**
555  * xilinx_sdi_writel - Memory mapped SDI Tx register write
556  * @base:       Pointer to SDI Tx registers base
557  * @offset:     Register offset
558  * @val:        value to be written
559  *
560  * This function writes the value to SDI TX registers
561  */
562 static inline void xilinx_sdi_writel(void __iomem *base, int offset, u32 val)
563 {
564         writel(val, base + offset);
565 }
566
567 /**
568  * xilinx_sdi_readl - Memory mapped SDI Tx register read
569  * @base:       Pointer to SDI Tx registers base
570  * @offset:     Register offset
571  *
572  * Return: The contents of the SDI Tx register
573  *
574  * This function returns the contents of the corresponding SDI Tx register.
575  */
576 static inline u32 xilinx_sdi_readl(void __iomem *base, int offset)
577 {
578         return readl(base + offset);
579 }
580
581 /**
582  * xilinx_en_axi4s - Enable SDI Tx AXI4S-to-Video core
583  * @sdi:        Pointer to SDI Tx structure
584  *
585  * This function enables the SDI Tx AXI4S-to-Video core.
586  */
587 static void xilinx_en_axi4s(struct xilinx_sdi *sdi)
588 {
589         u32 data;
590
591         data = xilinx_sdi_readl(sdi->base, XSDI_TX_RST_CTRL);
592         data |= XSDI_TX_AXI4S_CTRL_EN_MASK;
593         xilinx_sdi_writel(sdi->base, XSDI_TX_RST_CTRL, data);
594 }
595
596 /**
597  * xilinx_en_bridge - Enable SDI Tx bridge
598  * @sdi:        Pointer to SDI Tx structure
599  *
600  * This function enables the SDI Tx bridge.
601  */
602 static void xilinx_en_bridge(struct xilinx_sdi *sdi)
603 {
604         u32 data;
605
606         data = xilinx_sdi_readl(sdi->base, XSDI_TX_RST_CTRL);
607         data |= XSDI_TX_BRIDGE_CTRL_EN_MASK;
608         xilinx_sdi_writel(sdi->base, XSDI_TX_RST_CTRL, data);
609 }
610
611 /**
612  * xilinx_sdi_set_default_drm_properties - Configure SDI DRM
613  * properties with their default values
614  * @sdi: SDI structure having the updated user parameters
615  */
616 static void
617 xilinx_sdi_set_default_drm_properties(struct xilinx_sdi *sdi)
618 {
619         drm_object_property_set_value(&sdi->connector.base,
620                                       sdi->sdi_mode, 0);
621         drm_object_property_set_value(&sdi->connector.base,
622                                       sdi->sdi_data_strm, 0);
623         drm_object_property_set_value(&sdi->connector.base,
624                                       sdi->is_frac_prop, 0);
625 }
626
627 /**
628  * xilinx_sdi_irq_handler - SDI Tx interrupt
629  * @irq:        irq number
630  * @data:       irq data
631  *
632  * Return: IRQ_HANDLED for all cases.
633  *
634  * This is the compact GT ready interrupt.
635  */
636 static irqreturn_t xilinx_sdi_irq_handler(int irq, void *data)
637 {
638         struct xilinx_sdi *sdi = (struct xilinx_sdi *)data;
639         u32 reg;
640
641         reg = xilinx_sdi_readl(sdi->base, XSDI_TX_ISR_STAT);
642
643         if (reg & XSDI_GTTX_RSTDONE_INTR_MASK)
644                 dev_dbg(sdi->dev, "GT reset interrupt received\n");
645         if (reg & XSDI_TX_CE_ALIGN_ERR_INTR_MASK)
646                 dev_err_ratelimited(sdi->dev, "SDI SD CE align error\n");
647         if (reg & XSDI_OVERFLOW_INTR_MASK)
648                 dev_err_ratelimited(sdi->dev, "AXI-4 Stream Overflow error\n");
649         if (reg & XSDI_UNDERFLOW_INTR_MASK)
650                 dev_err_ratelimited(sdi->dev, "AXI-4 Stream Underflow error\n");
651         xilinx_sdi_writel(sdi->base, XSDI_TX_ISR_STAT,
652                           reg & ~(XSDI_AXI4S_VID_LOCK_INTR_MASK));
653
654         reg = xilinx_sdi_readl(sdi->base, XSDI_TX_STS_SB_TDATA);
655         if (reg & XSDI_TX_TDATA_GT_RESETDONE_MASK) {
656                 sdi->event_received = true;
657                 wake_up_interruptible(&sdi->wait_event);
658         }
659         return IRQ_HANDLED;
660 }
661
662 /**
663  * xilinx_sdi_set_payload_line - set ST352 packet line number
664  * @sdi:        Pointer to SDI Tx structure
665  * @line_1:     line number used to insert st352 packet for field 1.
666  * @line_2:     line number used to insert st352 packet for field 2.
667  *
668  * This function set 352 packet line number.
669  */
670 static void xilinx_sdi_set_payload_line(struct xilinx_sdi *sdi,
671                                         u32 line_1, u32 line_2)
672 {
673         u32 data;
674
675         data = ((line_1 & XSDI_TX_ST352_LINE_MASK) |
676                 ((line_2 & XSDI_TX_ST352_LINE_MASK) <<
677                 XSDI_TX_ST352_LINE_F2_SHIFT));
678
679         xilinx_sdi_writel(sdi->base, XSDI_TX_ST352_LINE, data);
680
681         data = xilinx_sdi_readl(sdi->base, XSDI_TX_MDL_CTRL);
682         data |= (1 << XSDI_TX_CTRL_ST352_F2_EN_SHIFT);
683
684         xilinx_sdi_writel(sdi->base, XSDI_TX_MDL_CTRL, data);
685 }
686
687 /**
688  * xilinx_sdi_set_payload_data - set ST352 packet payload
689  * @sdi:                Pointer to SDI Tx structure
690  * @data_strm:          data stream number
691  * @payload:            st352 packet payload
692  *
693  * This function set ST352 payload data to corresponding stream.
694  */
695 static void xilinx_sdi_set_payload_data(struct xilinx_sdi *sdi,
696                                         u32 data_strm, u32 payload)
697 {
698         xilinx_sdi_writel(sdi->base,
699                           (XSDI_TX_ST352_DATA_CH0 + (data_strm * 4)), payload);
700 }
701
702 /**
703  * xilinx_sdi_set_display_disable - Disable the SDI Tx IP core enable
704  * register bit
705  * @sdi: SDI structure having the updated user parameters
706  *
707  * This function takes the SDI strucure and disables the core enable bit
708  * of core configuration register.
709  */
710 static void xilinx_sdi_set_display_disable(struct xilinx_sdi *sdi)
711 {
712         u32 i;
713
714         for (i = 0; i < SDI_MAX_DATASTREAM; i++)
715                 xilinx_sdi_set_payload_data(sdi, i, 0);
716
717         xilinx_sdi_writel(sdi->base, XSDI_TX_GLBL_IER, 0);
718         xilinx_sdi_writel(sdi->base, XSDI_TX_RST_CTRL, 0);
719 }
720
721 /**
722  * xilinx_sdi_payload_config -  config the SDI payload parameters
723  * @sdi:        pointer Xilinx SDI Tx structure
724  * @mode:       display mode
725  *
726  * This function config the SDI st352 payload parameter.
727  */
728 static void xilinx_sdi_payload_config(struct xilinx_sdi *sdi, u32 mode)
729 {
730         u32 payload_1, payload_2;
731
732         switch (mode) {
733         case XSDI_MODE_SD:
734                 payload_1 = PAYLD_LN1_SDPAL;
735                 payload_2 = PAYLD_LN2_SDPAL;
736                 break;
737         case XSDI_MODE_HD:
738         case XSDI_MODE_3GA:
739         case XSDI_MODE_3GB:
740         case XSDI_MODE_6G:
741         case XSDI_MODE_12G:
742                 payload_1 = PAYLD_LN1_HD_3_6_12G;
743                 payload_2 = PAYLD_LN2_HD_3_6_12G;
744                 break;
745         default:
746                 payload_1 = 0;
747                 payload_2 = 0;
748                 break;
749         }
750
751         xilinx_sdi_set_payload_line(sdi, payload_1, payload_2);
752 }
753
754 /**
755  * xilinx_set_sdi_mode -  Set mode parameters in SDI Tx
756  * @sdi:        pointer Xilinx SDI Tx structure
757  * @mode:       SDI Tx display mode
758  * @is_frac:    0 - integer 1 - fractional
759  * @mux_ptrn:   specifiy the data stream interleaving pattern to be used
760  * This function config the SDI st352 payload parameter.
761  */
762 static void xilinx_set_sdi_mode(struct xilinx_sdi *sdi, u32 mode,
763                                 bool is_frac, u32 mux_ptrn)
764 {
765         u32 data;
766
767         xilinx_sdi_payload_config(sdi, mode);
768
769         data = xilinx_sdi_readl(sdi->base, XSDI_TX_MDL_CTRL);
770         data &= ~((XSDI_TX_CTRL_MODE_MASK << XSDI_TX_CTRL_MODE_SHIFT) |
771                 (XSDI_TX_CTRL_M_MASK) | (XSDI_TX_CTRL_MUX_MASK
772                 << XSDI_TX_CTRL_MUX_SHIFT));
773
774         data |= (((mode & XSDI_TX_CTRL_MODE_MASK)
775                 << XSDI_TX_CTRL_MODE_SHIFT) |
776                 (is_frac  << XSDI_TX_CTRL_M_SHIFT) |
777                 ((mux_ptrn & XSDI_TX_CTRL_MUX_MASK) << XSDI_TX_CTRL_MUX_SHIFT));
778
779         xilinx_sdi_writel(sdi->base, XSDI_TX_MDL_CTRL, data);
780 }
781
782 /**
783  * xilinx_sdi_set_config_parameters - Configure SDI Tx registers with parameters
784  * given from user application.
785  * @sdi: SDI structure having the updated user parameters
786  *
787  * This function takes the SDI structure having drm_property parameters
788  * configured from  user application and writes them into SDI IP registers.
789  */
790 static void xilinx_sdi_set_config_parameters(struct xilinx_sdi *sdi)
791 {
792         u32 mode;
793         int mux_ptrn = INVALID_VALUE;
794         bool is_frac;
795
796         mode = sdi->sdi_mod_prop_val;
797         is_frac = sdi->is_frac_prop_val;
798
799         switch (mode) {
800         case XSDI_MODE_3GA:
801                 mux_ptrn = XSDI_TX_MUX_SD_HD_3GA;
802                 break;
803         case XSDI_MODE_3GB:
804                 mux_ptrn = XSDI_TX_MUX_3GB;
805                 break;
806         case XSDI_MODE_6G:
807                 if (sdi->sdi_data_strm_prop_val == 4)
808                         mux_ptrn = XSDI_TX_MUX_4STREAM_6G;
809                 else if (sdi->sdi_data_strm_prop_val == 8)
810                         mux_ptrn = XSDI_TX_MUX_8STREAM_6G_12G;
811                 break;
812         case XSDI_MODE_12G:
813                 if (sdi->sdi_data_strm_prop_val == 8)
814                         mux_ptrn = XSDI_TX_MUX_8STREAM_6G_12G;
815                 break;
816         default:
817                 mux_ptrn = 0;
818                 break;
819         }
820         if (mux_ptrn == INVALID_VALUE) {
821                 dev_err(sdi->dev, "%d data stream not supported for %d mode",
822                         sdi->sdi_data_strm_prop_val, mode);
823                 return;
824         }
825         xilinx_set_sdi_mode(sdi, mode, is_frac, mux_ptrn);
826 }
827
828 /**
829  * xilinx_sdi_connector_set_property - implementation of drm_connector_funcs
830  * set_property invoked by IOCTL call to DRM_IOCTL_MODE_OBJ_SETPROPERTY
831  *
832  * @base_connector: pointer Xilinx SDI connector
833  * @property: pointer to the drm_property structure
834  * @value: SDI parameter value that is configured from user application
835  *
836  * This function takes a drm_property name and value given from user application
837  * and update the SDI structure property varabiles with the values.
838  * These values are later used to configure the SDI Rx IP.
839  *
840  * Return: 0 on success OR -EINVAL if setting property fails
841  */
842 static int
843 xilinx_sdi_connector_set_property(struct drm_connector *base_connector,
844                                   struct drm_property *property,
845                                   u64 value)
846 {
847         struct xilinx_sdi *sdi = connector_to_sdi(base_connector);
848
849         if (property == sdi->sdi_mode)
850                 sdi->sdi_mod_prop_val = (unsigned int)value;
851         else if (property == sdi->sdi_data_strm)
852                 sdi->sdi_data_strm_prop_val = (unsigned int)value;
853         else if (property == sdi->is_frac_prop)
854                 sdi->is_frac_prop_val = !!value;
855         else
856                 return -EINVAL;
857         return 0;
858 }
859
860 /**
861  * xilinx_sdi_get_mode_id - Search for a video mode in the supported modes table
862  *
863  * @mode: mode being searched
864  *
865  * Return: true if mode is found
866  */
867 static int xilinx_sdi_get_mode_id(struct drm_display_mode *mode)
868 {
869         unsigned int i;
870
871         for (i = 0; i < ARRAY_SIZE(xlnx_sdi_modes); i++)
872                 if (drm_mode_equal(&xlnx_sdi_modes[i].mode, mode))
873                         return i;
874         return -EINVAL;
875 }
876
877 /**
878  * xilinx_sdi_drm_add_modes - Adds SDI supported modes
879  * @connector: pointer Xilinx SDI connector
880  *
881  * Return:      Count of modes added
882  *
883  * This function adds the SDI modes supported and returns its count
884  */
885 static int xilinx_sdi_drm_add_modes(struct drm_connector *connector)
886 {
887         int i, num_modes = 0;
888         struct drm_display_mode *mode;
889         struct drm_device *dev = connector->dev;
890
891         for (i = 0; i < ARRAY_SIZE(xlnx_sdi_modes); i++) {
892                 const struct drm_display_mode *ptr = &xlnx_sdi_modes[i].mode;
893
894                 mode = drm_mode_duplicate(dev, ptr);
895                 if (mode) {
896                         drm_mode_probed_add(connector, mode);
897                         num_modes++;
898                 }
899         }
900         return num_modes;
901 }
902
903 static int xilinx_sdi_connector_dpms(struct drm_connector *connector,
904                                      int mode)
905 {
906         return drm_helper_connector_dpms(connector, mode);
907 }
908
909 static enum drm_connector_status
910 xilinx_sdi_detect(struct drm_connector *connector, bool force)
911 {
912         return connector_status_connected;
913 }
914
915 static void xilinx_sdi_connector_destroy(struct drm_connector *connector)
916 {
917         drm_connector_unregister(connector);
918         drm_connector_cleanup(connector);
919         connector->dev = NULL;
920 }
921
922 static const struct drm_connector_funcs xilinx_sdi_connector_funcs = {
923         .dpms = xilinx_sdi_connector_dpms,
924         .detect = xilinx_sdi_detect,
925         .fill_modes = drm_helper_probe_single_connector_modes,
926         .destroy = xilinx_sdi_connector_destroy,
927         .set_property = xilinx_sdi_connector_set_property,
928 };
929
930 static struct drm_encoder *
931 xilinx_sdi_best_encoder(struct drm_connector *connector)
932 {
933         return &(connector_to_sdi(connector)->encoder);
934 }
935
936 static int xilinx_sdi_get_modes(struct drm_connector *connector)
937 {
938         return xilinx_sdi_drm_add_modes(connector);
939 }
940
941 static struct drm_connector_helper_funcs xilinx_sdi_connector_helper_funcs = {
942         .get_modes = xilinx_sdi_get_modes,
943         .best_encoder = xilinx_sdi_best_encoder,
944 };
945
946 /**
947  * xilinx_sdi_drm_connector_create_property -  create SDI connector properties
948  *
949  * @base_connector: pointer to Xilinx SDI connector
950  *
951  * This function takes the xilinx SDI connector component and defines
952  * the drm_property variables with their default values.
953  */
954 static void
955 xilinx_sdi_drm_connector_create_property(struct drm_connector *base_connector)
956 {
957         struct drm_device *dev = base_connector->dev;
958         struct xilinx_sdi *sdi  = connector_to_sdi(base_connector);
959
960         sdi->is_frac_prop = drm_property_create_bool(dev, 1, "is_frac");
961         sdi->sdi_mode = drm_property_create_range(dev, 0,
962                         "sdi_mode", 0, 5);
963         sdi->sdi_data_strm = drm_property_create_range(dev, 0,
964                         "sdi_data_stream", 2, 8);
965 }
966
967 /**
968  * xilinx_sdi_drm_connector_attach_property -  attach SDI connector
969  * properties
970  *
971  * @base_connector: pointer to Xilinx SDI connector
972  */
973 static void
974 xilinx_sdi_drm_connector_attach_property(struct drm_connector *base_connector)
975 {
976         struct xilinx_sdi *sdi = connector_to_sdi(base_connector);
977         struct drm_mode_object *obj = &base_connector->base;
978
979         if (sdi->sdi_mode)
980                 drm_object_attach_property(obj, sdi->sdi_mode, 0);
981
982         if (sdi->sdi_data_strm)
983                 drm_object_attach_property(obj, sdi->sdi_data_strm, 0);
984
985         if (sdi->is_frac_prop)
986                 drm_object_attach_property(obj, sdi->is_frac_prop, 0);
987 }
988
989 static int xilinx_sdi_create_connector(struct drm_encoder *encoder)
990 {
991         struct xilinx_sdi *sdi = encoder_to_sdi(encoder);
992         struct drm_connector *connector = &sdi->connector;
993         int ret;
994
995         connector->polled = DRM_CONNECTOR_POLL_HPD;
996         connector->interlace_allowed = true;
997         connector->doublescan_allowed = true;
998
999         ret = drm_connector_init(encoder->dev, connector,
1000                                  &xilinx_sdi_connector_funcs,
1001                                  DRM_MODE_CONNECTOR_Unknown);
1002         if (ret) {
1003                 dev_err(sdi->dev, "Failed to initialize connector with drm\n");
1004                 return ret;
1005         }
1006
1007         drm_connector_helper_add(connector, &xilinx_sdi_connector_helper_funcs);
1008         drm_connector_register(connector);
1009         drm_mode_connector_attach_encoder(connector, encoder);
1010         xilinx_sdi_drm_connector_create_property(connector);
1011         xilinx_sdi_drm_connector_attach_property(connector);
1012
1013         return 0;
1014 }
1015
1016 static bool xilinx_sdi_mode_fixup(struct drm_encoder *encoder,
1017                                   const struct drm_display_mode *mode,
1018                                   struct drm_display_mode *adjusted_mode)
1019 {
1020         return true;
1021 }
1022
1023 /**
1024  * xilinx_sdi_set_display_enable - Enables the SDI Tx IP core enable
1025  * register bit
1026  * @sdi: SDI structure having the updated user parameters
1027  *
1028  * This function takes the SDI strucure and enables the core enable bit
1029  * of core configuration register.
1030  */
1031 static void xilinx_sdi_set_display_enable(struct xilinx_sdi *sdi)
1032 {
1033         u32 data;
1034
1035         data = xilinx_sdi_readl(sdi->base, XSDI_TX_RST_CTRL);
1036         data |= XSDI_TX_CTRL_EN_MASK;
1037         /* start sdi stream */
1038         xilinx_sdi_writel(sdi->base, XSDI_TX_RST_CTRL, data);
1039 }
1040
1041 static void xilinx_sdi_encoder_dpms(struct drm_encoder *encoder,
1042                                     int mode)
1043 {
1044         struct xilinx_sdi *sdi = encoder_to_sdi(encoder);
1045
1046         dev_dbg(sdi->dev, "encoder dpms state: %d\n", mode);
1047
1048         switch (mode) {
1049         case DRM_MODE_DPMS_ON:
1050                 xilinx_sdi_set_display_enable(sdi);
1051                 return;
1052         default:
1053                 xilinx_sdi_set_display_disable(sdi);
1054                 xilinx_sdi_set_default_drm_properties(sdi);
1055         }
1056 }
1057
1058 /**
1059  * xilinx_sdi_calc_st352_payld -  calculate the st352 payload
1060  *
1061  * @sdi: pointer to SDI Tx structure
1062  * @mode: DRM display mode
1063  *
1064  * This function calculates the st352 payload to be configured.
1065  * Please refer to SMPTE ST352 documents for it.
1066  * Return:      return st352 payload
1067  */
1068 static u32 xilinx_sdi_calc_st352_payld(struct xilinx_sdi *sdi,
1069                                        struct drm_display_mode *mode)
1070 {
1071         u8 byt1, byt2;
1072         u16 is_p;
1073         u32 id, sdi_mode = sdi->sdi_mod_prop_val;
1074         bool is_frac = sdi->is_frac_prop_val;
1075         u32 byt3 = ST352_BYTE3;
1076
1077         id = xilinx_sdi_get_mode_id(mode);
1078         dev_dbg(sdi->dev, "mode id: %d\n", id);
1079         if (mode->hdisplay == 2048 || mode->hdisplay == 4096)
1080                 byt3 |= XST352_2048_SHIFT;
1081         /* byte 2 calculation */
1082         is_p = !(mode->flags & DRM_MODE_FLAG_INTERLACE);
1083         byt2 = xlnx_sdi_modes[id].st352_byt2[is_frac];
1084         if ((sdi_mode == XSDI_MODE_3GB) ||
1085             (mode->flags & DRM_MODE_FLAG_DBLSCAN) || is_p)
1086                 byt2 |= XST352_PROG_PIC_MASK;
1087         if (is_p && (mode->vtotal >= 1125))
1088                 byt2 |= XST352_PROG_TRANS_MASK;
1089
1090         /* byte 1 calculation */
1091         byt1 = xlnx_sdi_modes[id].st352_byt1[sdi_mode];
1092
1093         return (ST352_BYTE4 << 24 | byt3 << 16 | byt2 << 8 | byt1);
1094 }
1095
1096 /**
1097  * xilinx_sdi_mode_set -  drive the SDI timing parameters
1098  *
1099  * @encoder: pointer to Xilinx DRM encoder
1100  * @mode: DRM kernel-internal display mode structure
1101  * @adjusted_mode: SDI panel timing parameters
1102  *
1103  * This function derives the SDI IP timing parameters from the timing
1104  * values given by VTC driver.
1105  */
1106 static void xilinx_sdi_mode_set(struct drm_encoder *encoder,
1107                                 struct drm_display_mode *mode,
1108                                 struct drm_display_mode *adjusted_mode)
1109 {
1110         struct xilinx_sdi *sdi = encoder_to_sdi(encoder);
1111         struct videomode vm;
1112         u32 payload, i;
1113
1114         xilinx_sdi_set_config_parameters(sdi);
1115
1116         /* set st352 payloads */
1117         payload = xilinx_sdi_calc_st352_payld(sdi, adjusted_mode);
1118         dev_dbg(sdi->dev, "payload : %0x\n", payload);
1119
1120         for (i = 0; i < sdi->sdi_data_strm_prop_val / 2; i++) {
1121                 if (sdi->sdi_mod_prop_val == XSDI_MODE_3GB)
1122                         payload |= (i << 1) << XSDI_CH_SHIFT;
1123                 xilinx_sdi_set_payload_data(sdi, i, payload);
1124         }
1125
1126         /* UHDSDI is fixed 2 pixels per clock, horizontal timings div by 2 */
1127         vm.hactive = adjusted_mode->hdisplay / PIXELS_PER_CLK;
1128         vm.hfront_porch = (adjusted_mode->hsync_start -
1129                           adjusted_mode->hdisplay) / PIXELS_PER_CLK;
1130         vm.hback_porch = (adjusted_mode->htotal -
1131                          adjusted_mode->hsync_end) / PIXELS_PER_CLK;
1132         vm.hsync_len = (adjusted_mode->hsync_end -
1133                        adjusted_mode->hsync_start) / PIXELS_PER_CLK;
1134
1135         vm.vactive = adjusted_mode->vdisplay;
1136         vm.vfront_porch = adjusted_mode->vsync_start -
1137                           adjusted_mode->vdisplay;
1138         vm.vback_porch = adjusted_mode->vtotal -
1139                          adjusted_mode->vsync_end;
1140         vm.vsync_len = adjusted_mode->vsync_end -
1141                        adjusted_mode->vsync_start;
1142         vm.flags = 0;
1143         if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
1144                 vm.flags |= DISPLAY_FLAGS_INTERLACED;
1145         if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
1146                 vm.flags |= DISPLAY_FLAGS_HSYNC_LOW;
1147         if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
1148                 vm.flags |= DISPLAY_FLAGS_VSYNC_LOW;
1149
1150         xilinx_vtc_config_sig(sdi->vtc, &vm);
1151 }
1152
1153 static void xilinx_sdi_prepare(struct drm_encoder *encoder)
1154 {
1155         struct xilinx_sdi *sdi = encoder_to_sdi(encoder);
1156         u32 reg;
1157
1158         dev_dbg(sdi->dev, "%s\n", __func__);
1159
1160         reg = xilinx_sdi_readl(sdi->base, XSDI_TX_MDL_CTRL);
1161         reg |= XSDI_TX_CTRL_INS_CRC_MASK | XSDI_TX_CTRL_INS_ST352_MASK |
1162                 XSDI_TX_CTRL_OVR_ST352_MASK | XSDI_TX_CTRL_INS_SYNC_BIT_MASK |
1163                 XSDI_TX_CTRL_INS_EDH_MASK;
1164         xilinx_sdi_writel(sdi->base, XSDI_TX_MDL_CTRL, reg);
1165         xilinx_sdi_writel(sdi->base, XSDI_TX_IER_STAT, XSDI_IER_EN_MASK);
1166         xilinx_sdi_writel(sdi->base, XSDI_TX_GLBL_IER, 1);
1167         xilinx_vtc_reset(sdi->vtc);
1168 }
1169
1170 static void xilinx_sdi_commit(struct drm_encoder *encoder)
1171 {
1172         struct xilinx_sdi *sdi = encoder_to_sdi(encoder);
1173         u32 ret;
1174
1175         dev_dbg(sdi->dev, "%s\n", __func__);
1176         xilinx_sdi_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
1177
1178         ret = wait_event_interruptible_timeout(sdi->wait_event,
1179                                                sdi->event_received,
1180                                                usecs_to_jiffies(GT_TIMEOUT));
1181         if (!ret) {
1182                 dev_err(sdi->dev, "Timeout: GT interrupt not received\n");
1183                 return;
1184         }
1185         sdi->event_received = false;
1186         /* enable sdi bridge, vtc and Axi4s_vid_out_ctrl */
1187         xilinx_en_bridge(sdi);
1188         xilinx_vtc_enable(sdi->vtc);
1189         xilinx_en_axi4s(sdi);
1190 }
1191
1192 static const struct drm_encoder_helper_funcs xilinx_sdi_encoder_helper_funcs = {
1193         .dpms = xilinx_sdi_encoder_dpms,
1194         .mode_fixup = xilinx_sdi_mode_fixup,
1195         .mode_set = xilinx_sdi_mode_set,
1196         .prepare = xilinx_sdi_prepare,
1197         .commit = xilinx_sdi_commit,
1198 };
1199
1200 static const struct drm_encoder_funcs xilinx_sdi_encoder_funcs = {
1201         .destroy = drm_encoder_cleanup,
1202 };
1203
1204 static int xilinx_sdi_bind(struct device *dev, struct device *master,
1205                            void *data)
1206 {
1207         struct xilinx_sdi *sdi = dev_get_drvdata(dev);
1208         struct drm_encoder *encoder = &sdi->encoder;
1209         struct drm_device *drm_dev = data;
1210         int ret;
1211
1212         /*
1213          * TODO: The possible CRTCs are 1 now as per current implementation of
1214          * SDI tx drivers. DRM framework can support more than one CRTCs and
1215          * SDI driver can be enhanced for that.
1216          */
1217         encoder->possible_crtcs = 1;
1218
1219         drm_encoder_init(drm_dev, encoder, &xilinx_sdi_encoder_funcs,
1220                          DRM_MODE_ENCODER_TMDS, NULL);
1221
1222         drm_encoder_helper_add(encoder, &xilinx_sdi_encoder_helper_funcs);
1223
1224         ret = xilinx_sdi_create_connector(encoder);
1225         if (ret) {
1226                 dev_err(sdi->dev, "fail creating connector, ret = %d\n", ret);
1227                 drm_encoder_cleanup(encoder);
1228         }
1229         return ret;
1230 }
1231
1232 static void xilinx_sdi_unbind(struct device *dev, struct device *master,
1233                               void *data)
1234 {
1235         struct xilinx_sdi *sdi = dev_get_drvdata(dev);
1236
1237         xilinx_sdi_encoder_dpms(&sdi->encoder, DRM_MODE_DPMS_OFF);
1238         drm_encoder_cleanup(&sdi->encoder);
1239         drm_connector_cleanup(&sdi->connector);
1240 }
1241
1242 static const struct component_ops xilinx_sdi_component_ops = {
1243         .bind   = xilinx_sdi_bind,
1244         .unbind = xilinx_sdi_unbind,
1245 };
1246
1247 static irqreturn_t xilinx_sdi_vblank_handler(int irq, void *data)
1248 {
1249         struct xilinx_sdi *sdi = (struct xilinx_sdi *)data;
1250         u32 intr = xilinx_vtc_intr_get(sdi->vtc);
1251
1252         if (!intr)
1253                 return IRQ_NONE;
1254
1255         if (sdi->vblank_fn)
1256                 sdi->vblank_fn(sdi->vblank_data);
1257
1258         xilinx_vtc_intr_clear(sdi->vtc, intr);
1259         return IRQ_HANDLED;
1260 }
1261
1262 /**
1263  * xilinx_drm_sdi_enable_vblank - Enable the vblank handling
1264  * @sdi: SDI subsystem
1265  * @vblank_fn: callback to be called on vblank event
1266  * @vblank_data: data to be used in @vblank_fn
1267  *
1268  * This function register the vblank handler, and the handler will be triggered
1269  * on vblank event after.
1270  */
1271 void xilinx_drm_sdi_enable_vblank(struct xilinx_sdi *sdi,
1272                                   void (*vblank_fn)(void *),
1273                                   void *vblank_data)
1274 {
1275         sdi->vblank_fn = vblank_fn;
1276         sdi->vblank_data = vblank_data;
1277         xilinx_vtc_vblank_enable(sdi->vtc);
1278 }
1279 EXPORT_SYMBOL_GPL(xilinx_drm_sdi_enable_vblank);
1280
1281 /**
1282  * xilinx_drm_sdi_disable_vblank - Disable the vblank handling
1283  * @sdi: SDI subsystem
1284  *
1285  * Disable the vblank handler. The vblank handler and data are unregistered.
1286  */
1287 void xilinx_drm_sdi_disable_vblank(struct xilinx_sdi *sdi)
1288 {
1289         sdi->vblank_fn = NULL;
1290         sdi->vblank_data = NULL;
1291         xilinx_vtc_vblank_disable(sdi->vtc);
1292 }
1293
1294 /**
1295  * xilinx_sdi_register_device - Register the SDI subsystem to the global list
1296  * @sdi: SDI subsystem
1297  *
1298  * Register the SDI subsystem instance to the global list
1299  */
1300 static void xilinx_sdi_register_device(struct xilinx_sdi *sdi)
1301 {
1302         mutex_lock(&xilinx_sdi_lock);
1303         list_add_tail(&sdi->list, &xilinx_sdi_list);
1304         mutex_unlock(&xilinx_sdi_lock);
1305 }
1306
1307 /**
1308  * xilinx_drm_sdi_of_get - Get the SDI subsystem instance
1309  * @np: parent device node
1310  *
1311  * This function searches and returns a SDI subsystem structure for
1312  * the parent device node, @np. The SDI subsystem node should be a child node
1313  * of @np, with 'xlnx,v-smpte-uhdsdi-tx-ss' property pointing to the SDI
1314  * device node. An instance can be shared by multiple users.
1315  *
1316  * Return: corresponding SDI subsystem structure if found. NULL if
1317  * the device node doesn't have 'xlnx,v-smpte-uhdsdi-tx-ss' property, or
1318  * -EPROBE_DEFER error pointer if the the SDI subsystem isn't found.
1319  */
1320 struct xilinx_sdi *xilinx_drm_sdi_of_get(struct device_node *np)
1321 {
1322         struct xilinx_sdi *found = NULL;
1323         struct xilinx_sdi *sdi;
1324         struct device_node *ep_node, *sdi_node;
1325
1326         ep_node = of_find_node_by_name(np, "endpoint");
1327         if (!ep_node)
1328                 return NULL;
1329         sdi_node = of_graph_get_remote_port_parent(ep_node);
1330         of_node_put(ep_node);
1331         if (!sdi_node)
1332                 return NULL;
1333
1334         mutex_lock(&xilinx_sdi_lock);
1335         list_for_each_entry(sdi, &xilinx_sdi_list, list) {
1336                 if (sdi->dev->of_node == sdi_node) {
1337                         found = sdi;
1338                         break;
1339                 }
1340         }
1341         mutex_unlock(&xilinx_sdi_lock);
1342
1343         of_node_put(sdi_node);
1344         if (!found)
1345                 return ERR_PTR(-EPROBE_DEFER);
1346         return found;
1347 }
1348
1349 /**
1350  * xilinx_sdi_unregister_device - Unregister the SDI subsystem instance
1351  * @sdi: SDI subsystem
1352  *
1353  * Unregister the SDI subsystem instance from the global list
1354  */
1355 static void xilinx_sdi_unregister_device(struct xilinx_sdi *sdi)
1356 {
1357         mutex_lock(&xilinx_sdi_lock);
1358         list_del(&sdi->list);
1359         mutex_unlock(&xilinx_sdi_lock);
1360 }
1361
1362 static int xilinx_sdi_probe(struct platform_device *pdev)
1363 {
1364         struct device *dev = &pdev->dev;
1365         struct resource *res;
1366         struct xilinx_sdi *sdi;
1367         struct device_node *vtc_node;
1368         int ret, irq;
1369
1370         sdi = devm_kzalloc(dev, sizeof(*sdi), GFP_KERNEL);
1371         if (!sdi)
1372                 return -ENOMEM;
1373
1374         sdi->dev = dev;
1375         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1376         sdi->base = devm_ioremap_resource(dev, res);
1377
1378         if (IS_ERR(sdi->base)) {
1379                 dev_err(dev, "failed to remap io region\n");
1380                 return PTR_ERR(sdi->base);
1381         }
1382         platform_set_drvdata(pdev, sdi);
1383
1384         vtc_node = of_parse_phandle(sdi->dev->of_node, "xlnx,vtc", 0);
1385         if (!vtc_node) {
1386                 dev_err(dev, "vtc node not present\n");
1387                 return PTR_ERR(vtc_node);
1388         }
1389         sdi->vtc = xilinx_vtc_probe(sdi->dev, vtc_node);
1390         of_node_put(vtc_node);
1391         if (IS_ERR(sdi->vtc)) {
1392                 dev_err(dev, "failed to probe VTC\n");
1393                 return PTR_ERR(sdi->vtc);
1394         }
1395
1396         /* disable interrupt */
1397         xilinx_sdi_writel(sdi->base, XSDI_TX_GLBL_IER, 0);
1398         irq = platform_get_irq(pdev, 0);
1399         if (irq < 0)
1400                 return irq;
1401
1402         ret = devm_request_threaded_irq(sdi->dev, irq, NULL,
1403                                         xilinx_sdi_irq_handler, IRQF_ONESHOT,
1404                                         dev_name(sdi->dev), sdi);
1405         if (ret < 0)
1406                 return ret;
1407
1408         irq = platform_get_irq(pdev, 1); /* vblank interrupt */
1409         if (irq < 0)
1410                 return irq;
1411         ret = devm_request_threaded_irq(sdi->dev, irq, NULL,
1412                                         xilinx_sdi_vblank_handler, IRQF_ONESHOT,
1413                                         "sdiTx-vblank", sdi);
1414         if (ret < 0)
1415                 return ret;
1416
1417         init_waitqueue_head(&sdi->wait_event);
1418         sdi->event_received = false;
1419
1420         xilinx_sdi_register_device(sdi);
1421         return component_add(dev, &xilinx_sdi_component_ops);
1422 }
1423
1424 static int xilinx_sdi_remove(struct platform_device *pdev)
1425 {
1426         struct xilinx_sdi *sdi = platform_get_drvdata(pdev);
1427
1428         xilinx_sdi_unregister_device(sdi);
1429         component_del(&pdev->dev, &xilinx_sdi_component_ops);
1430
1431         return 0;
1432 }
1433
1434 static const struct of_device_id xilinx_sdi_of_match[] = {
1435         { .compatible = "xlnx,v-smpte-uhdsdi-tx-ss"},
1436         { }
1437 };
1438 MODULE_DEVICE_TABLE(of, xilinx_sdi_of_match);
1439
1440 static struct platform_driver sdi_tx_driver = {
1441         .probe = xilinx_sdi_probe,
1442         .remove = xilinx_sdi_remove,
1443         .driver = {
1444                 .name = "xlnx,uhdsdi-tx",
1445                 .of_match_table = xilinx_sdi_of_match,
1446         },
1447 };
1448
1449 module_platform_driver(sdi_tx_driver);
1450
1451 MODULE_AUTHOR("Saurabh Sengar <saurabhs@xilinx.com>");
1452 MODULE_DESCRIPTION("Xilinx FPGA SDI Tx Driver");
1453 MODULE_LICENSE("GPL v2");