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