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