]> rtime.felk.cvut.cz Git - vajnamar/linux-xlnx.git/blob - drivers/media/platform/xilinx/xilinx-sdirxss.c
v4l: xilinx: sdirxss: Add ST352 decode macros
[vajnamar/linux-xlnx.git] / drivers / media / platform / xilinx / xilinx-sdirxss.c
1 /*
2  * Xilinx SDI Rx Subsystem
3  *
4  * Copyright (C) 2017 Xilinx, Inc.
5  *
6  * Contacts: Vishal Sagar <vsagar@xilinx.com>
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  */
17
18 #include <dt-bindings/media/xilinx-vip.h>
19 #include <linux/bitops.h>
20 #include <linux/compiler.h>
21 #include <linux/delay.h>
22 #include <linux/device.h>
23 #include <linux/interrupt.h>
24 #include <linux/io.h>
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/of.h>
28 #include <linux/of_irq.h>
29 #include <linux/platform_device.h>
30 #include <linux/pm.h>
31 #include <linux/slab.h>
32 #include <linux/spinlock.h>
33 #include <linux/spinlock_types.h>
34 #include <linux/types.h>
35 #include <linux/v4l2-subdev.h>
36 #include <linux/xilinx-sdirxss.h>
37 #include <linux/xilinx-v4l2-controls.h>
38 #include <media/media-entity.h>
39 #include <media/v4l2-common.h>
40 #include <media/v4l2-ctrls.h>
41 #include <media/v4l2-event.h>
42 #include <media/v4l2-of.h>
43 #include <media/v4l2-subdev.h>
44 #include "xilinx-vip.h"
45
46 /*
47  * SDI Rx register map, bitmask and offsets
48  */
49 #define XSDIRX_RST_CTRL_REG             0x00
50 #define XSDIRX_MDL_CTRL_REG             0x04
51 #define XSDIRX_GLBL_IER_REG             0x0C
52 #define XSDIRX_ISR_REG                  0x10
53 #define XSDIRX_IER_REG                  0x14
54 #define XSDIRX_ST352_VALID_REG          0x18
55 #define XSDIRX_ST352_DS1_REG            0x1C
56 #define XSDIRX_ST352_DS3_REG            0x20
57 #define XSDIRX_ST352_DS5_REG            0x24
58 #define XSDIRX_ST352_DS7_REG            0x28
59 #define XSDIRX_ST352_DS9_REG            0x2C
60 #define XSDIRX_ST352_DS11_REG           0x30
61 #define XSDIRX_ST352_DS13_REG           0x34
62 #define XSDIRX_ST352_DS15_REG           0x38
63 #define XSDIRX_VERSION_REG              0x3C
64 #define XSDIRX_SS_CONFIG_REG            0x40
65 #define XSDIRX_MODE_DET_STAT_REG        0x44
66 #define XSDIRX_TS_DET_STAT_REG          0x48
67 #define XSDIRX_EDH_STAT_REG             0x4C
68 #define XSDIRX_EDH_ERRCNT_EN_REG        0x50
69 #define XSDIRX_EDH_ERRCNT_REG           0x54
70 #define XSDIRX_CRC_ERRCNT_REG           0x58
71 #define XSDIRX_VID_LOCK_WINDOW_REG      0x5C
72 #define XSDIRX_SB_RX_STS_REG            0x60
73
74 #define XSDIRX_RST_CTRL_SS_EN_MASK                      BIT(0)
75 #define XSDIRX_RST_CTRL_SRST_MASK                       BIT(1)
76 #define XSDIRX_RST_CTRL_RST_CRC_ERRCNT_MASK             BIT(2)
77 #define XSDIRX_RST_CTRL_RST_EDH_ERRCNT_MASK             BIT(3)
78 #define XSDIRX_RST_CTRL_SDIRX_BRIDGE_ENB_MASK           BIT(8)
79 #define XSDIRX_RST_CTRL_VIDIN_AXI4S_MOD_ENB_MASK        BIT(9)
80
81 #define XSDIRX_MDL_CTRL_FRM_EN_MASK             BIT(4)
82 #define XSDIRX_MDL_CTRL_MODE_DET_EN_MASK        BIT(5)
83 #define XSDIRX_MDL_CTRL_MODE_HD_EN_MASK         BIT(8)
84 #define XSDIRX_MDL_CTRL_MODE_SD_EN_MASK         BIT(9)
85 #define XSDIRX_MDL_CTRL_MODE_3G_EN_MASK         BIT(10)
86 #define XSDIRX_MDL_CTRL_MODE_6G_EN_MASK         BIT(11)
87 #define XSDIRX_MDL_CTRL_MODE_12GI_EN_MASK       BIT(12)
88 #define XSDIRX_MDL_CTRL_MODE_12GF_EN_MASK       BIT(13)
89 #define XSDIRX_MDL_CTRL_MODE_AUTO_DET_MASK      GENMASK(13, 8)
90
91 #define XSDIRX_MDL_CTRL_FORCED_MODE_OFFSET      16
92 #define XSDIRX_MDL_CTRL_FORCED_MODE_MASK        GENMASK(18, 16)
93
94 #define XSDIRX_GLBL_INTR_EN_MASK        BIT(0)
95
96 #define XSDIRX_INTR_VIDLOCK_MASK        BIT(0)
97 #define XSDIRX_INTR_VIDUNLOCK_MASK      BIT(1)
98 #define XSDIRX_INTR_OVERFLOW_MASK       BIT(9)
99 #define XSDIRX_INTR_UNDERFLOW_MASK      BIT(10)
100
101 #define XSDIRX_INTR_ALL_MASK    (XSDIRX_INTR_VIDLOCK_MASK |\
102                                 XSDIRX_INTR_VIDUNLOCK_MASK |\
103                                 XSDIRX_INTR_OVERFLOW_MASK |\
104                                 XSDIRX_INTR_UNDERFLOW_MASK)
105
106 #define XSDIRX_ST352_VALID_DS1_MASK     BIT(0)
107 #define XSDIRX_ST352_VALID_DS3_MASK     BIT(1)
108 #define XSDIRX_ST352_VALID_DS5_MASK     BIT(2)
109 #define XSDIRX_ST352_VALID_DS7_MASK     BIT(3)
110 #define XSDIRX_ST352_VALID_DS9_MASK     BIT(4)
111 #define XSDIRX_ST352_VALID_DS11_MASK    BIT(5)
112 #define XSDIRX_ST352_VALID_DS13_MASK    BIT(6)
113 #define XSDIRX_ST352_VALID_DS15_MASK    BIT(7)
114
115 #define XSDIRX_MODE_DET_STAT_RX_MODE_MASK       GENMASK(2, 0)
116 #define XSDIRX_MODE_DET_STAT_MODE_LOCK_MASK     BIT(3)
117 #define XSDIRX_MODE_DET_STAT_ACT_STREAM_MASK    GENMASK(6, 4)
118 #define XSDIRX_MODE_DET_STAT_LVLB_3G_MASK       BIT(7)
119
120 #define XSDIRX_ACTIVE_STREAMS_1         0x0
121 #define XSDIRX_ACTIVE_STREAMS_2         0x1
122 #define XSDIRX_ACTIVE_STREAMS_4         0x2
123 #define XSDIRX_ACTIVE_STREAMS_8         0x3
124 #define XSDIRX_ACTIVE_STREAMS_16        0x4
125
126 #define XSDIRX_TS_DET_STAT_LOCKED_MASK          BIT(0)
127 #define XSDIRX_TS_DET_STAT_SCAN_MASK            BIT(1)
128 #define XSDIRX_TS_DET_STAT_SCAN_OFFSET          (1)
129 #define XSDIRX_TS_DET_STAT_FAMILY_MASK          GENMASK(7, 4)
130 #define XSDIRX_TS_DET_STAT_FAMILY_OFFSET        (4)
131 #define XSDIRX_TS_DET_STAT_RATE_MASK            GENMASK(11, 8)
132 #define XSDIRX_TS_DET_STAT_RATE_OFFSET          (8)
133
134 #define XSDIRX_TS_DET_STAT_RATE_NONE            0x0
135 #define XSDIRX_TS_DET_STAT_RATE_23_98HZ         0x2
136 #define XSDIRX_TS_DET_STAT_RATE_24HZ            0x3
137 #define XSDIRX_TS_DET_STAT_RATE_47_95HZ         0x4
138 #define XSDIRX_TS_DET_STAT_RATE_25HZ            0x5
139 #define XSDIRX_TS_DET_STAT_RATE_29_97HZ         0x6
140 #define XSDIRX_TS_DET_STAT_RATE_30HZ            0x7
141 #define XSDIRX_TS_DET_STAT_RATE_48HZ            0x8
142 #define XSDIRX_TS_DET_STAT_RATE_50HZ            0x9
143 #define XSDIRX_TS_DET_STAT_RATE_59_94HZ         0xA
144 #define XSDIRX_TS_DET_STAT_RATE_60HZ            0xB
145
146 #define XSDIRX_EDH_STAT_EDH_AP_MASK     BIT(0)
147 #define XSDIRX_EDH_STAT_EDH_FF_MASK     BIT(1)
148 #define XSDIRX_EDH_STAT_EDH_ANC_MASK    BIT(2)
149 #define XSDIRX_EDH_STAT_AP_FLAG_MASK    GENMASK(8, 4)
150 #define XSDIRX_EDH_STAT_FF_FLAG_MASK    GENMASK(13, 9)
151 #define XSDIRX_EDH_STAT_ANC_FLAG_MASK   GENMASK(18, 14)
152 #define XSDIRX_EDH_STAT_PKT_FLAG_MASK   GENMASK(22, 19)
153
154 #define XSDIRX_EDH_ERRCNT_COUNT_MASK    GENMASK(15, 0)
155
156 #define XSDIRX_CRC_ERRCNT_COUNT_MASK    GENMASK(31, 16)
157 #define XSDIRX_CRC_ERRCNT_DS_CRC_MASK   GENMASK(15, 0)
158
159 #define XSDIRX_VERSION_REV_MASK         GENMASK(7, 0)
160 #define XSDIRX_VERSION_PATCHID_MASK     GENMASK(11, 8)
161 #define XSDIRX_VERSION_VER_REV_MASK     GENMASK(15, 12)
162 #define XSDIRX_VERSION_VER_MIN_MASK     GENMASK(23, 16)
163 #define XSDIRX_VERSION_VER_MAJ_MASK     GENMASK(31, 24)
164
165 #define XSDIRX_SS_CONFIG_EDH_INCLUDED_MASK              BIT(1)
166
167 #define XSDIRX_STAT_SB_RX_TDATA_CHANGE_DONE_MASK        BIT(0)
168 #define XSDIRX_STAT_SB_RX_TDATA_CHANGE_FAIL_MASK        BIT(1)
169 #define XSDIRX_STAT_SB_RX_TDATA_GT_RESETDONE_MASK       BIT(2)
170 #define XSDIRX_STAT_SB_RX_TDATA_GT_BITRATE_MASK         BIT(3)
171
172 #define XSDIRX_VID_LOCK_WINDOW_VAL_MASK                 GENMASK(15, 0)
173
174 /* Number of media pads */
175 #define XSDIRX_MEDIA_PADS       (1)
176
177 #define XSDIRX_DEFAULT_WIDTH    (1920)
178 #define XSDIRX_DEFAULT_HEIGHT   (1080)
179
180 #define XSDIRX_MAX_STR_LENGTH   16
181
182 #define XSDIRXSS_SDI_STD_3G             0
183 #define XSDIRXSS_SDI_STD_6G             1
184 #define XSDIRXSS_SDI_STD_12G_8DS        2
185
186 #define XSDIRX_DEFAULT_VIDEO_LOCK_WINDOW        0x3000
187
188 #define XSDIRX_MODE_HD_MASK     0x0
189 #define XSDIRX_MODE_SD_MASK     0x1
190 #define XSDIRX_MODE_3G_MASK     0x2
191 #define XSDIRX_MODE_6G_MASK     0x4
192 #define XSDIRX_MODE_12GI_MASK   0x5
193 #define XSDIRX_MODE_12GF_MASK   0x6
194
195 /*
196  * Maximum number of events per file handle.
197  */
198 #define XSDIRX_MAX_EVENTS       (128)
199
200 /* ST352 related macros */
201 #define XST352_PAYLOAD_BYTE_MASK        0xFF
202 #define XST352_PAYLOAD_BYTE1_SHIFT      0
203 #define XST352_PAYLOAD_BYTE2_SHIFT      8
204 #define XST352_PAYLOAD_BYTE3_SHIFT      16
205 #define XST352_PAYLOAD_BYTE4_SHIFT      24
206
207 #define XST352_BYTE1_ST292_1x720L_1_5G          0x84
208 #define XST352_BYTE1_ST292_1x1080L_1_5G         0x85
209 #define XST352_BYTE1_ST425_2008_750L_3GB        0x88
210 #define XST352_BYTE1_ST425_2008_1125L_3GA       0x89
211 #define XST352_BYTE1_ST372_DL_3GB               0x8A
212 #define XST352_BYTE1_ST372_2x720L_3GB           0x8B
213 #define XST352_BYTE1_ST372_2x1080L_3GB          0x8C
214 #define XST352_BYTE1_ST2081_10_2160L_6G         0xC0
215 #define XST352_BYTE1_ST2081_10_DL_2160L_6G      0xC2
216 #define XST352_BYTE1_ST2082_10_2160L_12G        0xCE
217
218 #define XST352_BYTE2_TS_TYPE_MASK               BIT(15)
219 #define XST352_BYTE2_TS_TYPE_OFFSET             15
220 #define XST352_BYTE2_PIC_TYPE_MASK              BIT(14)
221 #define XST352_BYTE2_PIC_TYPE_OFFSET            14
222 #define XST352_BYTE2_TS_PIC_TYPE_INTERLACED     0
223 #define XST352_BYTE2_TS_PIC_TYPE_PROGRESSIVE    1
224
225 #define XST352_BYTE2_FPS_MASK                   0xF
226 #define XST352_BYTE2_FPS_SHIFT                  8
227 #define XST352_BYTE2_FPS_24F                    0x2
228 #define XST352_BYTE2_FPS_24                     0x3
229 #define XST352_BYTE2_FPS_48F                    0x4
230 #define XST352_BYTE2_FPS_25                     0x5
231 #define XST352_BYTE2_FPS_30F                    0x6
232 #define XST352_BYTE2_FPS_30                     0x7
233 #define XST352_BYTE2_FPS_48                     0x8
234 #define XST352_BYTE2_FPS_50                     0x9
235 #define XST352_BYTE2_FPS_60F                    0xA
236 #define XST352_BYTE2_FPS_60                     0xB
237 /* Table 4 ST 2081-10:2015 */
238 #define XST352_BYTE2_FPS_96                     0xC
239 #define XST352_BYTE2_FPS_100                    0xD
240 #define XST352_BYTE2_FPS_120                    0xE
241 #define XST352_BYTE2_FPS_120F                   0xF
242
243 #define XST352_BYTE3_ACT_LUMA_COUNT_MASK        BIT(22)
244 #define XST352_BYTE3_ACT_LUMA_COUNT_OFFSET      22
245
246 /**
247  * enum sdi_family_enc - SDI Transport Video Format Detected with Active Pixels
248  * @XSDIRX_SMPTE_ST_274: SMPTE ST 274 detected with AP 1920x1080
249  * @XSDIRX_SMPTE_ST_296: SMPTE ST 296 detected with AP 1280x720
250  * @XSDIRX_SMPTE_ST_2048_2: SMPTE ST 2048-2 detected with AP 2048x1080
251  * @XSDIRX_SMPTE_ST_295: SMPTE ST 295 detected with AP 1920x1080
252  * @XSDIRX_NTSC: NTSC encoding detected with AP 720x480
253  * @XSDIRX_PAL: PAL encoding detected with AP 720x576
254  * @XSDIRX_TS_UNKNOWN: Unknown SMPTE Transport family type
255  */
256 enum sdi_family_enc {
257         XSDIRX_SMPTE_ST_274     = 0,
258         XSDIRX_SMPTE_ST_296     = 1,
259         XSDIRX_SMPTE_ST_2048_2  = 2,
260         XSDIRX_SMPTE_ST_295     = 3,
261         XSDIRX_NTSC             = 8,
262         XSDIRX_PAL              = 9,
263         XSDIRX_TS_UNKNOWN       = 15
264 };
265
266 /**
267  * struct xsdirxss_core - Core configuration SDI Rx Subsystem device structure
268  * @dev: Platform structure
269  * @iomem: Base address of subsystem
270  * @irq: requested irq number
271  * @include_edh: EDH processor presence
272  * @mode: 3G/6G/12G mode
273  */
274 struct xsdirxss_core {
275         struct device *dev;
276         void __iomem *iomem;
277         int irq;
278         bool include_edh;
279         int mode;
280 };
281
282 /**
283  * struct xsdirxss_state - SDI Rx Subsystem device structure
284  * @core: Core structure for MIPI SDI Rx Subsystem
285  * @subdev: The v4l2 subdev structure
286  * @ctrl_handler: control handler
287  * @event: Holds the video unlock event
288  * @formats: Active V4L2 formats on each pad
289  * @default_format: default V4L2 media bus format
290  * @vip_format: format information corresponding to the active format
291  * @pads: media pads
292  * @streaming: Flag for storing streaming state
293  * @vidlocked: Flag indicating SDI Rx has locked onto video stream
294  *
295  * This structure contains the device driver related parameters
296  */
297 struct xsdirxss_state {
298         struct xsdirxss_core core;
299         struct v4l2_subdev subdev;
300         struct v4l2_ctrl_handler ctrl_handler;
301         struct v4l2_event event;
302         struct v4l2_mbus_framefmt formats[XSDIRX_MEDIA_PADS];
303         struct v4l2_mbus_framefmt default_format;
304         const struct xvip_video_format *vip_format;
305         struct media_pad pads[XSDIRX_MEDIA_PADS];
306         bool streaming;
307         bool vidlocked;
308 };
309
310 static inline struct xsdirxss_state *
311 to_xsdirxssstate(struct v4l2_subdev *subdev)
312 {
313         return container_of(subdev, struct xsdirxss_state, subdev);
314 }
315
316 /*
317  * Register related operations
318  */
319 static inline u32 xsdirxss_read(struct xsdirxss_core *xsdirxss, u32 addr)
320 {
321         return ioread32(xsdirxss->iomem + addr);
322 }
323
324 static inline void xsdirxss_write(struct xsdirxss_core *xsdirxss, u32 addr,
325                                   u32 value)
326 {
327         iowrite32(value, xsdirxss->iomem + addr);
328 }
329
330 static inline void xsdirxss_clr(struct xsdirxss_core *xsdirxss, u32 addr,
331                                 u32 clr)
332 {
333         xsdirxss_write(xsdirxss, addr, xsdirxss_read(xsdirxss, addr) & ~clr);
334 }
335
336 static inline void xsdirxss_set(struct xsdirxss_core *xsdirxss, u32 addr,
337                                 u32 set)
338 {
339         xsdirxss_write(xsdirxss, addr, xsdirxss_read(xsdirxss, addr) | set);
340 }
341
342 static void xsdirx_core_disable(struct xsdirxss_core *core)
343 {
344         xsdirxss_clr(core, XSDIRX_RST_CTRL_REG, XSDIRX_RST_CTRL_SS_EN_MASK);
345 }
346
347 static void xsdirx_core_enable(struct xsdirxss_core *core)
348 {
349         xsdirxss_set(core, XSDIRX_RST_CTRL_REG, XSDIRX_RST_CTRL_SS_EN_MASK);
350 }
351
352 static int xsdirx_set_modedetect(struct xsdirxss_core *core, u16 mask)
353 {
354         u32 i, val;
355
356         mask &= XSDIRX_DETECT_ALL_MODES;
357         if (!mask) {
358                 dev_err(core->dev, "Invalid bit mask = 0x%08x\n", mask);
359                 return -EINVAL;
360         }
361
362         dev_dbg(core->dev, "mask = 0x%x\n", mask);
363
364         val = xsdirxss_read(core, XSDIRX_MDL_CTRL_REG);
365         val &= ~(XSDIRX_MDL_CTRL_MODE_DET_EN_MASK);
366         val &= ~(XSDIRX_MDL_CTRL_MODE_AUTO_DET_MASK);
367         val &= ~(XSDIRX_MDL_CTRL_FORCED_MODE_MASK);
368
369         if (hweight16(mask) > 1) {
370                 /* Multi mode detection as more than 1 bit set in mask */
371                 dev_dbg(core->dev, "Detect multiple modes\n");
372                 for (i = 0; i < XSDIRX_MODE_NUM_SUPPORTED; i++) {
373                         switch (mask & (1 << i)) {
374                         case BIT(XSDIRX_MODE_SD_OFFSET):
375                                 val |= XSDIRX_MDL_CTRL_MODE_SD_EN_MASK;
376                                 break;
377                         case BIT(XSDIRX_MODE_HD_OFFSET):
378                                 val |= XSDIRX_MDL_CTRL_MODE_HD_EN_MASK;
379                                 break;
380                         case BIT(XSDIRX_MODE_3G_OFFSET):
381                                 val |= XSDIRX_MDL_CTRL_MODE_3G_EN_MASK;
382                                 break;
383                         case BIT(XSDIRX_MODE_6G_OFFSET):
384                                 val |= XSDIRX_MDL_CTRL_MODE_6G_EN_MASK;
385                                 break;
386                         case BIT(XSDIRX_MODE_12GI_OFFSET):
387                                 val |= XSDIRX_MDL_CTRL_MODE_12GI_EN_MASK;
388                                 break;
389                         case BIT(XSDIRX_MODE_12GF_OFFSET):
390                                 val |= XSDIRX_MDL_CTRL_MODE_12GF_EN_MASK;
391                                 break;
392                         }
393                 }
394                 val |= XSDIRX_MDL_CTRL_MODE_DET_EN_MASK;
395         } else {
396                 /* Fixed Mode */
397                 u32 forced_mode_mask = 0;
398
399                 dev_dbg(core->dev, "Detect fixed mode\n");
400
401                 /* Find offset of first bit set */
402                 switch (__ffs(mask)) {
403                 case XSDIRX_MODE_SD_OFFSET:
404                         forced_mode_mask = XSDIRX_MODE_SD_MASK;
405                         break;
406                 case XSDIRX_MODE_HD_OFFSET:
407                         forced_mode_mask = XSDIRX_MODE_HD_MASK;
408                         break;
409                 case XSDIRX_MODE_3G_OFFSET:
410                         forced_mode_mask = XSDIRX_MODE_3G_MASK;
411                         break;
412                 case XSDIRX_MODE_6G_OFFSET:
413                         forced_mode_mask = XSDIRX_MODE_6G_MASK;
414                         break;
415                 case XSDIRX_MODE_12GI_OFFSET:
416                         forced_mode_mask = XSDIRX_MODE_12GI_MASK;
417                         break;
418                 case XSDIRX_MODE_12GF_OFFSET:
419                         forced_mode_mask = XSDIRX_MODE_12GF_MASK;
420                         break;
421                 }
422                 dev_dbg(core->dev, "Forced Mode Mask : 0x%x\n",
423                         forced_mode_mask);
424                 val |= forced_mode_mask << XSDIRX_MDL_CTRL_FORCED_MODE_OFFSET;
425         }
426
427         dev_dbg(core->dev, "Modes to be detected : sdi ctrl reg = 0x%08x\n",
428                 val);
429         xsdirxss_write(core, XSDIRX_MDL_CTRL_REG, val);
430
431         return 0;
432 }
433
434 static void xsdirx_framer(struct xsdirxss_core *core, bool flag)
435 {
436         if (flag)
437                 xsdirxss_set(core, XSDIRX_MDL_CTRL_REG,
438                              XSDIRX_MDL_CTRL_FRM_EN_MASK);
439         else
440                 xsdirxss_clr(core, XSDIRX_MDL_CTRL_REG,
441                              XSDIRX_MDL_CTRL_FRM_EN_MASK);
442 }
443
444 static void xsdirx_setedherrcnttrigger(struct xsdirxss_core *core, u32 enable)
445 {
446         u32 val = xsdirxss_read(core, XSDIRX_EDH_ERRCNT_EN_REG);
447
448         val = enable & XSDIRX_EDH_ALLERR_MASK;
449
450         xsdirxss_write(core, XSDIRX_EDH_ERRCNT_EN_REG, val);
451 }
452
453 static void xsdirx_setvidlockwindow(struct xsdirxss_core *core, u32 val)
454 {
455         /*
456          * The video lock window is the amount of time for which the
457          * the mode and transport stream should be locked to get the
458          * video lock interrupt.
459          */
460         xsdirxss_write(core, XSDIRX_VID_LOCK_WINDOW_REG,
461                        val & XSDIRX_VID_LOCK_WINDOW_VAL_MASK);
462 }
463
464 static void xsdirx_disableintr(struct xsdirxss_core *core, u32 mask)
465 {
466         xsdirxss_clr(core, XSDIRX_IER_REG, mask);
467 }
468
469 static void xsdirx_enableintr(struct xsdirxss_core *core, u32 mask)
470 {
471         xsdirxss_set(core, XSDIRX_IER_REG, mask);
472 }
473
474 static void xsdirx_globalintr(struct xsdirxss_core *core, bool flag)
475 {
476         if (flag)
477                 xsdirxss_set(core, XSDIRX_GLBL_IER_REG,
478                              XSDIRX_GLBL_INTR_EN_MASK);
479         else
480                 xsdirxss_clr(core, XSDIRX_GLBL_IER_REG,
481                              XSDIRX_GLBL_INTR_EN_MASK);
482 }
483
484 static void xsdirx_clearintr(struct xsdirxss_core *core, u32 mask)
485 {
486         xsdirxss_set(core, XSDIRX_ISR_REG, mask);
487 }
488
489 static void xsdirx_vid_bridge_control(struct xsdirxss_core *core, bool enable)
490 {
491         if (enable)
492                 xsdirxss_set(core, XSDIRX_RST_CTRL_REG,
493                              XSDIRX_RST_CTRL_SDIRX_BRIDGE_ENB_MASK);
494         else
495                 xsdirxss_clr(core, XSDIRX_RST_CTRL_REG,
496                              XSDIRX_RST_CTRL_SDIRX_BRIDGE_ENB_MASK);
497 }
498
499 static void xsdirx_axis4_bridge_control(struct xsdirxss_core *core, bool enable)
500 {
501         if (enable)
502                 xsdirxss_set(core, XSDIRX_RST_CTRL_REG,
503                              XSDIRX_RST_CTRL_VIDIN_AXI4S_MOD_ENB_MASK);
504         else
505                 xsdirxss_clr(core, XSDIRX_RST_CTRL_REG,
506                              XSDIRX_RST_CTRL_VIDIN_AXI4S_MOD_ENB_MASK);
507 }
508
509 static void xsdirx_streamflow_control(struct xsdirxss_core *core, bool enable)
510 {
511         /* The sdi to native bridge is followed by native to axis4 bridge */
512         if (enable) {
513                 xsdirx_axis4_bridge_control(core, enable);
514                 xsdirx_vid_bridge_control(core, enable);
515         } else {
516                 xsdirx_vid_bridge_control(core, enable);
517                 xsdirx_axis4_bridge_control(core, enable);
518         }
519 }
520
521 static void xsdirx_streamdowncb(struct xsdirxss_core *core)
522 {
523         xsdirx_streamflow_control(core, false);
524 }
525
526 /**
527  * xsdirx_get_stream_properties - Get SDI Rx stream properties
528  * @state: pointer to driver state
529  *
530  * This function decodes the stream's ST352 payload (if available) to get
531  * stream properties like width, height, picture type (interlaced/progressive),
532  * etc.
533  *
534  * Return: 0 for success else errors
535  */
536 static int xsdirx_get_stream_properties(struct xsdirxss_state *state)
537 {
538         struct xsdirxss_core *core = &state->core;
539         u32 mode, payload = 0, val, family, valid, trate, tscan;
540         u8 byte1 = 0, active_luma = 0, pic_type = 0;
541         struct v4l2_mbus_framefmt *format = &state->formats[0];
542
543         mode = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
544         mode &= XSDIRX_MODE_DET_STAT_RX_MODE_MASK;
545
546         valid = xsdirxss_read(core, XSDIRX_ST352_VALID_REG);
547
548         if ((mode >= XSDIRX_MODE_3G_MASK) && !valid) {
549                 dev_err(core->dev, "No valid ST352 payload present even for 3G mode and above\n");
550                 return -EINVAL;
551         }
552
553         if (valid & XSDIRX_ST352_VALID_DS1_MASK) {
554                 payload = xsdirxss_read(core, XSDIRX_ST352_DS1_REG);
555                 byte1 = (payload >> XST352_PAYLOAD_BYTE1_SHIFT) &
556                                 XST352_PAYLOAD_BYTE_MASK;
557                 active_luma = (payload & XST352_BYTE3_ACT_LUMA_COUNT_MASK) >>
558                                 XST352_BYTE3_ACT_LUMA_COUNT_OFFSET;
559                 pic_type = (payload & XST352_BYTE2_PIC_TYPE_MASK) >>
560                                 XST352_BYTE2_PIC_TYPE_OFFSET;
561         } else {
562                 dev_dbg(core->dev, "No ST352 payload available : Mode = %d\n",
563                         mode);
564         }
565
566         val = xsdirxss_read(core, XSDIRX_TS_DET_STAT_REG);
567         family = (val & XSDIRX_TS_DET_STAT_FAMILY_MASK) >>
568                   XSDIRX_TS_DET_STAT_FAMILY_OFFSET;
569         trate = (val & XSDIRX_TS_DET_STAT_RATE_MASK) >>
570                  XSDIRX_TS_DET_STAT_RATE_OFFSET;
571         tscan = (val & XSDIRX_TS_DET_STAT_SCAN_MASK) >>
572                  XSDIRX_TS_DET_STAT_SCAN_OFFSET;
573
574         switch (mode) {
575         case XSDIRX_MODE_HD_MASK:
576                 if (!valid) {
577                         /* No payload obtained */
578                         dev_dbg(core->dev, "frame rate : %d, tscan = %d\n",
579                                 trate, tscan);
580                         /*
581                          * NOTE : A progressive segmented frame pSF will be
582                          * reported incorrectly as Interlaced as we rely on IP's
583                          * transport scan locked bit.
584                          */
585                         dev_warn(core->dev, "pSF will be incorrectly reported as Interlaced\n");
586
587                         switch (trate) {
588                         case XSDIRX_TS_DET_STAT_RATE_23_98HZ:
589                         case XSDIRX_TS_DET_STAT_RATE_24HZ:
590                         case XSDIRX_TS_DET_STAT_RATE_25HZ:
591                         case XSDIRX_TS_DET_STAT_RATE_29_97HZ:
592                         case XSDIRX_TS_DET_STAT_RATE_30HZ:
593                                 if (family == XSDIRX_SMPTE_ST_296) {
594                                         format->width = 1280;
595                                         format->height = 720;
596                                         format->field = V4L2_FIELD_NONE;
597                                 } else if (family == XSDIRX_SMPTE_ST_2048_2) {
598                                         format->width = 2048;
599                                         format->height = 1080;
600                                         if (tscan)
601                                                 format->field = V4L2_FIELD_NONE;
602                                         else
603                                                 format->field =
604                                                         V4L2_FIELD_INTERLACED;
605                                 } else {
606                                         format->width = 1920;
607                                         format->height = 1080;
608                                         if (tscan)
609                                                 format->field = V4L2_FIELD_NONE;
610                                         else
611                                                 format->field =
612                                                         V4L2_FIELD_INTERLACED;
613                                 }
614                                 break;
615                         case XSDIRX_TS_DET_STAT_RATE_50HZ:
616                         case XSDIRX_TS_DET_STAT_RATE_59_94HZ:
617                         case XSDIRX_TS_DET_STAT_RATE_60HZ:
618                                 if (family == XSDIRX_SMPTE_ST_274) {
619                                         format->width = 1920;
620                                         format->height = 1080;
621                                 } else {
622                                         format->width = 1280;
623                                         format->height = 720;
624                                 }
625                                 format->field = V4L2_FIELD_NONE;
626                                 break;
627                         default:
628                                 format->width = 1920;
629                                 format->height = 1080;
630                                 format->field = V4L2_FIELD_NONE;
631                         }
632                 } else {
633                         dev_dbg(core->dev, "Got the payload\n");
634                         switch (byte1) {
635                         case XST352_BYTE1_ST292_1x720L_1_5G:
636                                 /* SMPTE ST 292-1 for 720 line payloads */
637                                 format->width = 1280;
638                                 format->height = 720;
639                                 break;
640                         case XST352_BYTE1_ST292_1x1080L_1_5G:
641                                 /* SMPTE ST 292-1 for 1080 line payloads */
642                                 format->height = 1080;
643                                 if (active_luma)
644                                         format->width = 2048;
645                                 else
646                                         format->width = 1920;
647                                 break;
648                         default:
649                                 dev_dbg(core->dev, "Unknown HD Mode SMPTE standard\n");
650                                 return -EINVAL;
651                         }
652                 }
653                 break;
654         case XSDIRX_MODE_SD_MASK:
655                 format->field = V4L2_FIELD_INTERLACED;
656
657                 switch (family) {
658                 case XSDIRX_NTSC:
659                         format->width = 720;
660                         format->height = 480;
661                         break;
662                 case XSDIRX_PAL:
663                         format->width = 720;
664                         format->height = 576;
665                         break;
666                 default:
667                         dev_dbg(core->dev, "Unknown SD Mode SMPTE standard\n");
668                         return -EINVAL;
669                 }
670                 break;
671         case XSDIRX_MODE_3G_MASK:
672                 switch (byte1) {
673                 case XST352_BYTE1_ST425_2008_750L_3GB:
674                         /* Sec 4.1.6.1 SMPTE 425-2008 */
675                 case XST352_BYTE1_ST372_2x720L_3GB:
676                         /* Table 13 SMPTE 425-2008 */
677                         format->width = 1280;
678                         format->height = 720;
679                         break;
680                 case XST352_BYTE1_ST425_2008_1125L_3GA:
681                         /* ST352 Table SMPTE 425-1 */
682                 case XST352_BYTE1_ST372_DL_3GB:
683                         /* Table 13 SMPTE 425-2008 */
684                 case XST352_BYTE1_ST372_2x1080L_3GB:
685                         /* Table 13 SMPTE 425-2008 */
686                         format->height = 1080;
687                         if (active_luma)
688                                 format->width = 2048;
689                         else
690                                 format->width = 1920;
691                         break;
692                 default:
693                         dev_dbg(core->dev, "Unknown 3G Mode SMPTE standard\n");
694                         return -EINVAL;
695                 }
696                 break;
697         case XSDIRX_MODE_6G_MASK:
698                 switch (byte1) {
699                 case XST352_BYTE1_ST2081_10_DL_2160L_6G:
700                         /* Dual link 6G */
701                 case XST352_BYTE1_ST2081_10_2160L_6G:
702                         /* Table 3 SMPTE ST 2081-10 */
703                         format->height = 2160;
704                         if (active_luma)
705                                 format->width = 4096;
706                         else
707                                 format->width = 3840;
708                         break;
709                 default:
710                         dev_dbg(core->dev, "Unknown 6G Mode SMPTE standard\n");
711                         return -EINVAL;
712                 }
713                 break;
714         case XSDIRX_MODE_12GI_MASK:
715         case XSDIRX_MODE_12GF_MASK:
716                 switch (byte1) {
717                 case XST352_BYTE1_ST2082_10_2160L_12G:
718                         /* Section 4.3.1 SMPTE ST 2082-10 */
719                         format->height = 2160;
720                         if (active_luma)
721                                 format->width = 4096;
722                         else
723                                 format->width = 3840;
724                         break;
725                 default:
726                         dev_dbg(core->dev, "Unknown 12G Mode SMPTE standard\n");
727                         return -EINVAL;
728                 };
729                 break;
730         default:
731                 dev_err(core->dev, "Invalid Mode\n");
732                 return -EINVAL;
733         }
734
735         if (valid) {
736                 if (pic_type)
737                         format->field = V4L2_FIELD_NONE;
738                 else
739                         format->field = V4L2_FIELD_INTERLACED;
740         }
741
742         dev_dbg(core->dev, "Stream width = %d height = %d Field = %d payload = 0x%08x ts = 0x%08x\n",
743                 format->width, format->height, format->field, payload, val);
744
745         return 0;
746 }
747
748 /**
749  * xsdirxss_irq_handler - Interrupt handler for SDI Rx
750  * @irq: IRQ number
751  * @dev_id: Pointer to device state
752  *
753  * The SDI Rx interrupts are cleared by first setting and then clearing the bits
754  * in the interrupt clear register. The interrupt status register is read only.
755  *
756  * Return: IRQ_HANDLED after handling interrupts
757  */
758 static irqreturn_t xsdirxss_irq_handler(int irq, void *dev_id)
759 {
760         struct xsdirxss_state *state = (struct xsdirxss_state *)dev_id;
761         struct xsdirxss_core *core = &state->core;
762         u32 status;
763
764         status = xsdirxss_read(core, XSDIRX_ISR_REG);
765         dev_dbg(core->dev, "interrupt status = 0x%08x\n", status);
766
767         if (!status)
768                 return IRQ_NONE;
769
770         if (status & XSDIRX_INTR_VIDLOCK_MASK) {
771                 u32 val1, val2;
772
773                 dev_dbg(core->dev, "video lock interrupt\n");
774                 xsdirx_clearintr(core, XSDIRX_INTR_VIDLOCK_MASK);
775
776                 val1 = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
777                 val2 = xsdirxss_read(core, XSDIRX_TS_DET_STAT_REG);
778
779                 if ((val1 & XSDIRX_MODE_DET_STAT_MODE_LOCK_MASK) &&
780                     (val2 & XSDIRX_TS_DET_STAT_LOCKED_MASK)) {
781                         u32 mask = XSDIRX_RST_CTRL_RST_CRC_ERRCNT_MASK |
782                                    XSDIRX_RST_CTRL_RST_EDH_ERRCNT_MASK;
783
784                         dev_dbg(core->dev, "mode & ts lock occurred\n");
785
786                         xsdirxss_set(core, XSDIRX_RST_CTRL_REG, mask);
787                         xsdirxss_clr(core, XSDIRX_RST_CTRL_REG, mask);
788
789                         val1 = xsdirxss_read(core, XSDIRX_ST352_VALID_REG);
790                         val2 = xsdirxss_read(core, XSDIRX_ST352_DS1_REG);
791
792                         dev_dbg(core->dev, "valid st352 mask = 0x%08x\n", val1);
793                         dev_dbg(core->dev, "st352 payload = 0x%08x\n", val2);
794
795                         if (!xsdirx_get_stream_properties(state)) {
796                                 memset(&state->event, 0, sizeof(state->event));
797                                 state->event.type = V4L2_EVENT_SOURCE_CHANGE;
798                                 state->event.u.src_change.changes =
799                                         V4L2_EVENT_SRC_CH_RESOLUTION;
800                                 v4l2_subdev_notify_event(&state->subdev,
801                                                          &state->event);
802
803                                 state->vidlocked = true;
804                         } else {
805                                 dev_err(core->dev, "Unable to get stream properties!\n");
806                                 state->vidlocked = false;
807                         }
808                 } else {
809                         dev_dbg(core->dev, "video unlock before video lock!\n");
810                         state->vidlocked = false;
811                 }
812         }
813
814         if (status & XSDIRX_INTR_VIDUNLOCK_MASK) {
815                 dev_dbg(core->dev, "video unlock interrupt\n");
816                 xsdirx_clearintr(core, XSDIRX_INTR_VIDUNLOCK_MASK);
817                 xsdirx_streamdowncb(core);
818
819                 memset(&state->event, 0, sizeof(state->event));
820                 state->event.type = V4L2_EVENT_XLNXSDIRX_VIDUNLOCK;
821                 v4l2_subdev_notify_event(&state->subdev, &state->event);
822
823                 state->vidlocked = false;
824         }
825
826         if (status & XSDIRX_INTR_UNDERFLOW_MASK) {
827                 dev_dbg(core->dev, "Video in to AXI4 Stream core underflow interrupt\n");
828                 xsdirx_clearintr(core, XSDIRX_INTR_UNDERFLOW_MASK);
829
830                 memset(&state->event, 0, sizeof(state->event));
831                 state->event.type = V4L2_EVENT_XLNXSDIRX_UNDERFLOW;
832                 v4l2_subdev_notify_event(&state->subdev, &state->event);
833         }
834
835         if (status & XSDIRX_INTR_OVERFLOW_MASK) {
836                 dev_dbg(core->dev, "Video in to AXI4 Stream core overflow interrupt\n");
837                 xsdirx_clearintr(core, XSDIRX_INTR_OVERFLOW_MASK);
838
839                 memset(&state->event, 0, sizeof(state->event));
840                 state->event.type = V4L2_EVENT_XLNXSDIRX_OVERFLOW;
841                 v4l2_subdev_notify_event(&state->subdev, &state->event);
842         }
843         return IRQ_HANDLED;
844 }
845
846 /**
847  * xsdirxss_subscribe_event - Subscribe to video lock and unlock event
848  * @sd: V4L2 Sub device
849  * @fh: V4L2 File Handle
850  * @sub: Subcribe event structure
851  *
852  * Return: 0 on success, errors otherwise
853  */
854 static int xsdirxss_subscribe_event(struct v4l2_subdev *sd,
855                                     struct v4l2_fh *fh,
856                                     struct v4l2_event_subscription *sub)
857 {
858         int ret;
859         struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
860         struct xsdirxss_core *core = &xsdirxss->core;
861
862         switch (sub->type) {
863         case V4L2_EVENT_XLNXSDIRX_VIDUNLOCK:
864         case V4L2_EVENT_XLNXSDIRX_UNDERFLOW:
865         case V4L2_EVENT_XLNXSDIRX_OVERFLOW:
866                 ret = v4l2_event_subscribe(fh, sub, XSDIRX_MAX_EVENTS, NULL);
867                 break;
868         case V4L2_EVENT_SOURCE_CHANGE:
869                 ret = v4l2_src_change_event_subscribe(fh, sub);
870                 break;
871         default:
872                 return -EINVAL;
873         }
874         dev_dbg(core->dev, "Event subscribed : 0x%08x\n", sub->type);
875         return ret;
876 }
877
878 /**
879  * xsdirxss_unsubscribe_event - Unsubscribe from all events registered
880  * @sd: V4L2 Sub device
881  * @fh: V4L2 file handle
882  * @sub: pointer to Event unsubscription structure
883  *
884  * Return: zero on success, else a negative error code.
885  */
886 static int xsdirxss_unsubscribe_event(struct v4l2_subdev *sd,
887                                       struct v4l2_fh *fh,
888                                       struct v4l2_event_subscription *sub)
889 {
890         struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
891         struct xsdirxss_core *core = &xsdirxss->core;
892
893         dev_dbg(core->dev, "Event unsubscribe : 0x%08x\n", sub->type);
894         return v4l2_event_unsubscribe(fh, sub);
895 }
896
897 /**
898  * xsdirxss_s_ctrl - This is used to set the Xilinx SDI Rx V4L2 controls
899  * @ctrl: V4L2 control to be set
900  *
901  * This function is used to set the V4L2 controls for the Xilinx SDI Rx
902  * Subsystem.
903  *
904  * Return: 0 on success, errors otherwise
905  */
906 static int xsdirxss_s_ctrl(struct v4l2_ctrl *ctrl)
907 {
908         int ret = 0;
909         struct xsdirxss_state *xsdirxss =
910                 container_of(ctrl->handler,
911                              struct xsdirxss_state, ctrl_handler);
912         struct xsdirxss_core *core = &xsdirxss->core;
913
914         dev_dbg(core->dev, "set ctrl id = 0x%08x val = 0x%08x\n",
915                 ctrl->id, ctrl->val);
916
917         if (xsdirxss->streaming) {
918                 dev_err(core->dev, "Cannot set controls while streaming\n");
919                 return -EINVAL;
920         }
921
922         xsdirx_core_disable(core);
923         switch (ctrl->id) {
924         case V4L2_CID_XILINX_SDIRX_FRAMER:
925                 xsdirx_framer(core, ctrl->val);
926                 break;
927         case V4L2_CID_XILINX_SDIRX_VIDLOCK_WINDOW:
928                 xsdirx_setvidlockwindow(core, ctrl->val);
929                 break;
930         case V4L2_CID_XILINX_SDIRX_EDH_ERRCNT_ENABLE:
931                 xsdirx_setedherrcnttrigger(core, ctrl->val);
932                 break;
933         case V4L2_CID_XILINX_SDIRX_SEARCH_MODES:
934                 if (ctrl->val) {
935                         if (core->mode == XSDIRXSS_SDI_STD_3G) {
936                                 dev_dbg(core->dev, "Upto 3G supported\n");
937                                 ctrl->val &= ~(BIT(XSDIRX_MODE_6G_OFFSET) |
938                                                BIT(XSDIRX_MODE_12GI_OFFSET) |
939                                                BIT(XSDIRX_MODE_12GF_OFFSET));
940                         }
941
942                         if (core->mode == XSDIRXSS_SDI_STD_6G) {
943                                 dev_dbg(core->dev, "Upto 6G supported\n");
944                                 ctrl->val &= ~(BIT(XSDIRX_MODE_12GI_OFFSET) |
945                                                BIT(XSDIRX_MODE_12GF_OFFSET));
946                         }
947
948                         ret = xsdirx_set_modedetect(core, ctrl->val);
949                 } else {
950                         dev_err(core->dev, "Select at least one mode!\n");
951                         return -EINVAL;
952                 }
953                 break;
954         default:
955                 xsdirxss_set(core, XSDIRX_RST_CTRL_REG,
956                              XSDIRX_RST_CTRL_SS_EN_MASK);
957                 return -EINVAL;
958         }
959         xsdirx_core_enable(core);
960         return ret;
961 }
962
963 /**
964  * xsdirxss_g_volatile_ctrl - get the Xilinx SDI Rx controls
965  * @ctrl: Pointer to V4L2 control
966  *
967  * Return: 0 on success, errors otherwise
968  */
969 static int xsdirxss_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
970 {
971         u32 val;
972         struct xsdirxss_state *xsdirxss =
973                 container_of(ctrl->handler,
974                              struct xsdirxss_state, ctrl_handler);
975         struct xsdirxss_core *core = &xsdirxss->core;
976
977         switch (ctrl->id) {
978         case V4L2_CID_XILINX_SDIRX_MODE_DETECT:
979                 if (!xsdirxss->vidlocked) {
980                         dev_err(core->dev, "Can't get values when video not locked!\n");
981                         return -EINVAL;
982                 }
983                 val = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
984                 val &= XSDIRX_MODE_DET_STAT_RX_MODE_MASK;
985
986                 switch (val) {
987                 case XSDIRX_MODE_SD_MASK:
988                         ctrl->val = XSDIRX_MODE_SD_OFFSET;
989                         break;
990                 case XSDIRX_MODE_HD_MASK:
991                         ctrl->val = XSDIRX_MODE_HD_OFFSET;
992                         break;
993                 case XSDIRX_MODE_3G_MASK:
994                         ctrl->val = XSDIRX_MODE_3G_OFFSET;
995                         break;
996                 case XSDIRX_MODE_6G_MASK:
997                         ctrl->val = XSDIRX_MODE_6G_OFFSET;
998                         break;
999                 case XSDIRX_MODE_12GI_MASK:
1000                         ctrl->val = XSDIRX_MODE_12GI_OFFSET;
1001                         break;
1002                 case XSDIRX_MODE_12GF_MASK:
1003                         ctrl->val = XSDIRX_MODE_12GF_OFFSET;
1004                         break;
1005                 }
1006                 break;
1007         case V4L2_CID_XILINX_SDIRX_CRC:
1008                 ctrl->val = xsdirxss_read(core, XSDIRX_CRC_ERRCNT_REG);
1009                 xsdirxss_write(core, XSDIRX_CRC_ERRCNT_REG, 0xFFFF);
1010                 break;
1011         case V4L2_CID_XILINX_SDIRX_EDH_ERRCNT:
1012                 val = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
1013                 val &= XSDIRX_MODE_DET_STAT_RX_MODE_MASK;
1014                 if (val == XSDIRX_MODE_SD_MASK) {
1015                         ctrl->val = xsdirxss_read(core, XSDIRX_EDH_ERRCNT_REG);
1016                 } else {
1017                         dev_dbg(core->dev, "%d - not in SD mode\n", ctrl->id);
1018                         return -EINVAL;
1019                 }
1020                 break;
1021         case V4L2_CID_XILINX_SDIRX_EDH_STATUS:
1022                 val = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
1023                 val &= XSDIRX_MODE_DET_STAT_RX_MODE_MASK;
1024                 if (val == XSDIRX_MODE_SD_MASK) {
1025                         ctrl->val = xsdirxss_read(core, XSDIRX_EDH_STAT_REG);
1026                 } else {
1027                         dev_dbg(core->dev, "%d - not in SD mode\n", ctrl->id);
1028                         return -EINVAL;
1029                 }
1030                 break;
1031         default:
1032                 dev_err(core->dev, "Get Invalid control id 0x%0x\n", ctrl->id);
1033                 return -EINVAL;
1034         }
1035         dev_dbg(core->dev, "Get ctrl id = 0x%08x val = 0x%08x\n",
1036                 ctrl->id, ctrl->val);
1037         return 0;
1038 }
1039
1040 /**
1041  * xsdirxss_log_status - Logs the status of the SDI Rx Subsystem
1042  * @sd: Pointer to V4L2 subdevice structure
1043  *
1044  * This function prints the current status of Xilinx SDI Rx Subsystem
1045  *
1046  * Return: 0 on success
1047  */
1048 static int xsdirxss_log_status(struct v4l2_subdev *sd)
1049 {
1050         struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
1051         struct xsdirxss_core *core = &xsdirxss->core;
1052         u32 data, i;
1053
1054         v4l2_info(sd, "***** SDI Rx subsystem reg dump start *****\n");
1055         for (i = 0; i < 0x28; i++) {
1056                 data = xsdirxss_read(core, i * 4);
1057                 v4l2_info(sd, "offset 0x%08x data 0x%08x\n",
1058                           i * 4, data);
1059         }
1060         v4l2_info(sd, "***** SDI Rx subsystem reg dump end *****\n");
1061         return 0;
1062 }
1063
1064 static void xsdirxss_start_stream(struct xsdirxss_state *xsdirxss)
1065 {
1066         xsdirx_streamflow_control(&xsdirxss->core, true);
1067 }
1068
1069 static void xsdirxss_stop_stream(struct xsdirxss_state *xsdirxss)
1070 {
1071         xsdirx_streamflow_control(&xsdirxss->core, false);
1072 }
1073
1074 /**
1075  * xsdirxss_s_stream - It is used to start/stop the streaming.
1076  * @sd: V4L2 Sub device
1077  * @enable: Flag (True / False)
1078  *
1079  * This function controls the start or stop of streaming for the
1080  * Xilinx SDI Rx Subsystem.
1081  *
1082  * Return: 0 on success, errors otherwise
1083  */
1084 static int xsdirxss_s_stream(struct v4l2_subdev *sd, int enable)
1085 {
1086         struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
1087         struct xsdirxss_core *core = &xsdirxss->core;
1088
1089         if (enable) {
1090                 if (!xsdirxss->vidlocked) {
1091                         dev_dbg(core->dev, "Video is not locked\n");
1092                         return -EINVAL;
1093                 }
1094                 if (xsdirxss->streaming) {
1095                         dev_dbg(core->dev, "Already streaming\n");
1096                         return -EINVAL;
1097                 }
1098
1099                 xsdirxss_start_stream(xsdirxss);
1100                 xsdirxss->streaming = true;
1101                 dev_dbg(core->dev, "Streaming started\n");
1102         } else {
1103                 if (!xsdirxss->streaming) {
1104                         dev_dbg(core->dev, "Stopped streaming already\n");
1105                         return -EINVAL;
1106                 }
1107
1108                 xsdirxss_stop_stream(xsdirxss);
1109                 xsdirxss->streaming = false;
1110                 dev_dbg(core->dev, "Streaming stopped\n");
1111         }
1112
1113         return 0;
1114 }
1115
1116 static struct v4l2_mbus_framefmt *
1117 __xsdirxss_get_pad_format(struct xsdirxss_state *xsdirxss,
1118                           struct v4l2_subdev_pad_config *cfg,
1119                                 unsigned int pad, u32 which)
1120 {
1121         switch (which) {
1122         case V4L2_SUBDEV_FORMAT_TRY:
1123                 return v4l2_subdev_get_try_format(&xsdirxss->subdev, cfg, pad);
1124         case V4L2_SUBDEV_FORMAT_ACTIVE:
1125                 return &xsdirxss->formats[pad];
1126         default:
1127                 return NULL;
1128         }
1129 }
1130
1131 /**
1132  * xsdirxss_get_format - Get the pad format
1133  * @sd: Pointer to V4L2 Sub device structure
1134  * @cfg: Pointer to sub device pad information structure
1135  * @fmt: Pointer to pad level media bus format
1136  *
1137  * This function is used to get the pad format information.
1138  *
1139  * Return: 0 on success
1140  */
1141 static int xsdirxss_get_format(struct v4l2_subdev *sd,
1142                                struct v4l2_subdev_pad_config *cfg,
1143                                         struct v4l2_subdev_format *fmt)
1144 {
1145         struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
1146         struct xsdirxss_core *core = &xsdirxss->core;
1147
1148         if (!xsdirxss->vidlocked) {
1149                 dev_err(core->dev, "Video not locked!\n");
1150                 return -EINVAL;
1151         }
1152
1153         fmt->format = *__xsdirxss_get_pad_format(xsdirxss, cfg,
1154                                                  fmt->pad, fmt->which);
1155
1156         dev_dbg(core->dev, "Stream width = %d height = %d Field = %d\n",
1157                 fmt->format.width, fmt->format.height, fmt->format.field);
1158
1159         return 0;
1160 }
1161
1162 /**
1163  * xsdirxss_set_format - This is used to set the pad format
1164  * @sd: Pointer to V4L2 Sub device structure
1165  * @cfg: Pointer to sub device pad information structure
1166  * @fmt: Pointer to pad level media bus format
1167  *
1168  * This function is used to set the pad format.
1169  * Since the pad format is fixed in hardware, it can't be
1170  * modified on run time.
1171  *
1172  * Return: 0 on success
1173  */
1174 static int xsdirxss_set_format(struct v4l2_subdev *sd,
1175                                struct v4l2_subdev_pad_config *cfg,
1176                                 struct v4l2_subdev_format *fmt)
1177 {
1178         struct v4l2_mbus_framefmt *__format;
1179         struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
1180
1181         dev_dbg(xsdirxss->core.dev,
1182                 "set width %d height %d code %d field %d colorspace %d\n",
1183                 fmt->format.width, fmt->format.height,
1184                 fmt->format.code, fmt->format.field,
1185                 fmt->format.colorspace);
1186
1187         __format = __xsdirxss_get_pad_format(xsdirxss, cfg,
1188                                              fmt->pad, fmt->which);
1189
1190         /* Currently reset the code to one fixed in hardware */
1191         /* TODO : Add checks for width height */
1192         fmt->format.code = __format->code;
1193
1194         return 0;
1195 }
1196
1197 /**
1198  * xsdirxss_open - Called on v4l2_open()
1199  * @sd: Pointer to V4L2 sub device structure
1200  * @fh: Pointer to V4L2 File handle
1201  *
1202  * This function is called on v4l2_open(). It sets the default format for pad.
1203  *
1204  * Return: 0 on success
1205  */
1206 static int xsdirxss_open(struct v4l2_subdev *sd,
1207                          struct v4l2_subdev_fh *fh)
1208 {
1209         struct v4l2_mbus_framefmt *format;
1210         struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
1211
1212         format = v4l2_subdev_get_try_format(sd, fh->pad, 0);
1213         *format = xsdirxss->default_format;
1214
1215         return 0;
1216 }
1217
1218 /**
1219  * xsdirxss_close - Called on v4l2_close()
1220  * @sd: Pointer to V4L2 sub device structure
1221  * @fh: Pointer to V4L2 File handle
1222  *
1223  * This function is called on v4l2_close().
1224  *
1225  * Return: 0 on success
1226  */
1227 static int xsdirxss_close(struct v4l2_subdev *sd,
1228                           struct v4l2_subdev_fh *fh)
1229 {
1230         return 0;
1231 }
1232
1233 /* -----------------------------------------------------------------------------
1234  * Media Operations
1235  */
1236
1237 static const struct media_entity_operations xsdirxss_media_ops = {
1238         .link_validate = v4l2_subdev_link_validate
1239 };
1240
1241 static const struct v4l2_ctrl_ops xsdirxss_ctrl_ops = {
1242         .g_volatile_ctrl = xsdirxss_g_volatile_ctrl,
1243         .s_ctrl = xsdirxss_s_ctrl
1244 };
1245
1246 static struct v4l2_ctrl_config xsdirxss_edh_ctrls[] = {
1247         {
1248                 .ops    = &xsdirxss_ctrl_ops,
1249                 .id     = V4L2_CID_XILINX_SDIRX_EDH_ERRCNT_ENABLE,
1250                 .name   = "SDI Rx : EDH Error Count Enable",
1251                 .type   = V4L2_CTRL_TYPE_BITMASK,
1252                 .min    = 0,
1253                 .max    = XSDIRX_EDH_ALLERR_MASK,
1254                 .def    = 0,
1255         }, {
1256                 .ops    = &xsdirxss_ctrl_ops,
1257                 .id     = V4L2_CID_XILINX_SDIRX_EDH_ERRCNT,
1258                 .name   = "SDI Rx : EDH Error Count",
1259                 .type   = V4L2_CTRL_TYPE_INTEGER,
1260                 .min    = 0,
1261                 .max    = 0xFFFF,
1262                 .step   = 1,
1263                 .def    = 0,
1264                 .flags  = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
1265         }, {
1266                 .ops    = &xsdirxss_ctrl_ops,
1267                 .id     = V4L2_CID_XILINX_SDIRX_EDH_STATUS,
1268                 .name   = "SDI Rx : EDH Status",
1269                 .type   = V4L2_CTRL_TYPE_INTEGER,
1270                 .min    = 0,
1271                 .max    = 0xFFFFFFFF,
1272                 .step   = 1,
1273                 .def    = 0,
1274                 .flags  = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
1275         }
1276 };
1277
1278 static struct v4l2_ctrl_config xsdirxss_ctrls[] = {
1279         {
1280                 .ops    = &xsdirxss_ctrl_ops,
1281                 .id     = V4L2_CID_XILINX_SDIRX_FRAMER,
1282                 .name   = "SDI Rx : Enable Framer",
1283                 .type   = V4L2_CTRL_TYPE_BOOLEAN,
1284                 .min    = false,
1285                 .max    = true,
1286                 .step   = 1,
1287                 .def    = true,
1288         }, {
1289                 .ops    = &xsdirxss_ctrl_ops,
1290                 .id     = V4L2_CID_XILINX_SDIRX_VIDLOCK_WINDOW,
1291                 .name   = "SDI Rx : Video Lock Window",
1292                 .type   = V4L2_CTRL_TYPE_INTEGER,
1293                 .min    = 0,
1294                 .max    = 0xFFFF,
1295                 .step   = 1,
1296                 .def    = XSDIRX_DEFAULT_VIDEO_LOCK_WINDOW,
1297         }, {
1298                 .ops    = &xsdirxss_ctrl_ops,
1299                 .id     = V4L2_CID_XILINX_SDIRX_SEARCH_MODES,
1300                 .name   = "SDI Rx : Modes search Mask",
1301                 .type   = V4L2_CTRL_TYPE_BITMASK,
1302                 .min    = 0,
1303                 .max    = XSDIRX_DETECT_ALL_MODES,
1304                 .def    = XSDIRX_DETECT_ALL_MODES,
1305         }, {
1306                 .ops    = &xsdirxss_ctrl_ops,
1307                 .id     = V4L2_CID_XILINX_SDIRX_MODE_DETECT,
1308                 .name   = "SDI Rx : Mode Detect Status",
1309                 .type   = V4L2_CTRL_TYPE_INTEGER,
1310                 .min    = XSDIRX_MODE_SD_OFFSET,
1311                 .max    = XSDIRX_MODE_12GF_OFFSET,
1312                 .step   = 1,
1313                 .flags  = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
1314         }, {
1315                 .ops    = &xsdirxss_ctrl_ops,
1316                 .id     = V4L2_CID_XILINX_SDIRX_CRC,
1317                 .name   = "SDI Rx : CRC Error status",
1318                 .type   = V4L2_CTRL_TYPE_INTEGER,
1319                 .min    = 0,
1320                 .max    = 0xFFFFFFFF,
1321                 .step   = 1,
1322                 .def    = 0,
1323                 .flags  = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
1324         }
1325 };
1326
1327 static const struct v4l2_subdev_core_ops xsdirxss_core_ops = {
1328         .log_status = xsdirxss_log_status,
1329         .subscribe_event = xsdirxss_subscribe_event,
1330         .unsubscribe_event = xsdirxss_unsubscribe_event
1331 };
1332
1333 static struct v4l2_subdev_video_ops xsdirxss_video_ops = {
1334         .s_stream = xsdirxss_s_stream
1335 };
1336
1337 static struct v4l2_subdev_pad_ops xsdirxss_pad_ops = {
1338         .get_fmt = xsdirxss_get_format,
1339         .set_fmt = xsdirxss_set_format,
1340 };
1341
1342 static struct v4l2_subdev_ops xsdirxss_ops = {
1343         .core = &xsdirxss_core_ops,
1344         .video = &xsdirxss_video_ops,
1345         .pad = &xsdirxss_pad_ops
1346 };
1347
1348 static const struct v4l2_subdev_internal_ops xsdirxss_internal_ops = {
1349         .open = xsdirxss_open,
1350         .close = xsdirxss_close
1351 };
1352
1353 /* -----------------------------------------------------------------------------
1354  * Platform Device Driver
1355  */
1356
1357 static int xsdirxss_parse_of(struct xsdirxss_state *xsdirxss)
1358 {
1359         struct device_node *node = xsdirxss->core.dev->of_node;
1360         struct device_node *ports = NULL;
1361         struct device_node *port = NULL;
1362         unsigned int nports = 0;
1363         struct xsdirxss_core *core = &xsdirxss->core;
1364         int ret;
1365         const char *sdi_std;
1366
1367         core->include_edh = of_property_read_bool(node, "xlnx,include-edh");
1368         dev_dbg(core->dev, "EDH property = %s\n",
1369                 core->include_edh ? "Present" : "Absent");
1370
1371         ret = of_property_read_string(node, "xlnx,line-rate",
1372                                       &sdi_std);
1373         if (ret < 0) {
1374                 dev_err(core->dev, "xlnx,line-rate property not found\n");
1375                 return ret;
1376         }
1377
1378         if (!strncmp(sdi_std, "12G_SDI_8DS", XSDIRX_MAX_STR_LENGTH)) {
1379                 core->mode = XSDIRXSS_SDI_STD_12G_8DS;
1380         } else if (!strncmp(sdi_std, "6G_SDI", XSDIRX_MAX_STR_LENGTH)) {
1381                 core->mode = XSDIRXSS_SDI_STD_6G;
1382         } else if (!strncmp(sdi_std, "3G_SDI", XSDIRX_MAX_STR_LENGTH)) {
1383                 core->mode = XSDIRXSS_SDI_STD_3G;
1384         } else {
1385                 dev_err(core->dev, "Invalid Line Rate\n");
1386                 return -EINVAL;
1387         }
1388         dev_dbg(core->dev, "SDI Rx Line Rate = %s, mode = %d\n", sdi_std,
1389                 core->mode);
1390
1391         ports = of_get_child_by_name(node, "ports");
1392         if (!ports)
1393                 ports = node;
1394
1395         for_each_child_of_node(ports, port) {
1396                 const struct xvip_video_format *format;
1397                 struct device_node *endpoint;
1398
1399                 if (!port->name || of_node_cmp(port->name, "port"))
1400                         continue;
1401
1402                 format = xvip_of_get_format(port);
1403                 if (IS_ERR(format)) {
1404                         dev_err(core->dev, "invalid format in DT");
1405                         return PTR_ERR(format);
1406                 }
1407
1408                 dev_dbg(core->dev, "vf_code = %d bpc = %d bpp = %d\n",
1409                         format->vf_code, format->width, format->bpp);
1410
1411                 if (format->vf_code != XVIP_VF_YUV_422) {
1412                         dev_err(core->dev, "Incorrect UG934 video format set. Accepts only YUV422\n");
1413                         return -EINVAL;
1414                 }
1415                 xsdirxss->vip_format = format;
1416
1417                 endpoint = of_get_next_child(port, NULL);
1418                 if (!endpoint) {
1419                         dev_err(core->dev, "No port at\n");
1420                         return -EINVAL;
1421                 }
1422
1423                 /* Count the number of ports. */
1424                 nports++;
1425         }
1426
1427         if (nports != 1) {
1428                 dev_err(core->dev, "invalid number of ports %u\n", nports);
1429                 return -EINVAL;
1430         }
1431
1432         /* Register interrupt handler */
1433         core->irq = irq_of_parse_and_map(node, 0);
1434
1435         ret = devm_request_irq(core->dev, core->irq, xsdirxss_irq_handler,
1436                                IRQF_SHARED, "xilinx-sdirxss", xsdirxss);
1437         if (ret) {
1438                 dev_err(core->dev, "Err = %d Interrupt handler reg failed!\n",
1439                         ret);
1440                 return ret;
1441         }
1442
1443         return 0;
1444 }
1445
1446 static int xsdirxss_probe(struct platform_device *pdev)
1447 {
1448         struct v4l2_subdev *subdev;
1449         struct xsdirxss_state *xsdirxss;
1450         struct xsdirxss_core *core;
1451         struct resource *res;
1452         int ret;
1453         unsigned int num_ctrls, num_edh_ctrls = 0, i;
1454
1455         xsdirxss = devm_kzalloc(&pdev->dev, sizeof(*xsdirxss), GFP_KERNEL);
1456         if (!xsdirxss)
1457                 return -ENOMEM;
1458
1459         xsdirxss->core.dev = &pdev->dev;
1460         core = &xsdirxss->core;
1461
1462         ret = xsdirxss_parse_of(xsdirxss);
1463         if (ret < 0)
1464                 return ret;
1465
1466         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1467         xsdirxss->core.iomem = devm_ioremap_resource(xsdirxss->core.dev, res);
1468         if (IS_ERR(xsdirxss->core.iomem))
1469                 return PTR_ERR(xsdirxss->core.iomem);
1470
1471         /* Reset the core */
1472         xsdirx_streamflow_control(core, false);
1473         xsdirx_core_disable(core);
1474         xsdirx_clearintr(core, XSDIRX_INTR_ALL_MASK);
1475         xsdirx_disableintr(core, XSDIRX_INTR_ALL_MASK);
1476         xsdirx_enableintr(core, XSDIRX_INTR_ALL_MASK);
1477         xsdirx_globalintr(core, true);
1478         xsdirxss_write(core, XSDIRX_CRC_ERRCNT_REG, 0xFFFF);
1479
1480         /* Initialize V4L2 subdevice and media entity */
1481         xsdirxss->pads[0].flags = MEDIA_PAD_FL_SOURCE;
1482
1483         /* Initialize the default format */
1484         xsdirxss->default_format.code = xsdirxss->vip_format->code;
1485         xsdirxss->default_format.field = V4L2_FIELD_NONE;
1486         xsdirxss->default_format.colorspace = V4L2_COLORSPACE_DEFAULT;
1487         xsdirxss->default_format.width = XSDIRX_DEFAULT_WIDTH;
1488         xsdirxss->default_format.height = XSDIRX_DEFAULT_HEIGHT;
1489
1490         xsdirxss->formats[0] = xsdirxss->default_format;
1491
1492         /* Initialize V4L2 subdevice and media entity */
1493         subdev = &xsdirxss->subdev;
1494         v4l2_subdev_init(subdev, &xsdirxss_ops);
1495
1496         subdev->dev = &pdev->dev;
1497         subdev->internal_ops = &xsdirxss_internal_ops;
1498         strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
1499
1500         subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
1501
1502         subdev->entity.ops = &xsdirxss_media_ops;
1503
1504         v4l2_set_subdevdata(subdev, xsdirxss);
1505
1506         ret = media_entity_pads_init(&subdev->entity, 1, xsdirxss->pads);
1507         if (ret < 0)
1508                 goto error;
1509
1510         /* Initialise and register the controls */
1511         num_ctrls = ARRAY_SIZE(xsdirxss_ctrls);
1512
1513         if (xsdirxss->core.include_edh)
1514                 num_edh_ctrls = ARRAY_SIZE(xsdirxss_edh_ctrls);
1515
1516         v4l2_ctrl_handler_init(&xsdirxss->ctrl_handler,
1517                                (num_ctrls + num_edh_ctrls));
1518
1519         for (i = 0; i < num_ctrls; i++) {
1520                 struct v4l2_ctrl *ctrl;
1521
1522                 dev_dbg(xsdirxss->core.dev, "%d %s ctrl = 0x%x\n",
1523                         i, xsdirxss_ctrls[i].name, xsdirxss_ctrls[i].id);
1524
1525                 ctrl = v4l2_ctrl_new_custom(&xsdirxss->ctrl_handler,
1526                                             &xsdirxss_ctrls[i], NULL);
1527                 if (!ctrl) {
1528                         dev_dbg(xsdirxss->core.dev, "Failed to add %s ctrl\n",
1529                                 xsdirxss_ctrls[i].name);
1530                         goto error;
1531                 }
1532         }
1533
1534         if (xsdirxss->core.include_edh) {
1535                 for (i = 0; i < num_edh_ctrls; i++) {
1536                         struct v4l2_ctrl *ctrl;
1537
1538                         dev_dbg(xsdirxss->core.dev, "%d %s ctrl = 0x%x\n",
1539                                 i, xsdirxss_edh_ctrls[i].name,
1540                                 xsdirxss_edh_ctrls[i].id);
1541
1542                         ctrl = v4l2_ctrl_new_custom(&xsdirxss->ctrl_handler,
1543                                                     &xsdirxss_edh_ctrls[i],
1544                                                     NULL);
1545                         if (!ctrl) {
1546                                 dev_dbg(xsdirxss->core.dev, "Failed to add %s ctrl\n",
1547                                         xsdirxss_edh_ctrls[i].name);
1548                                 goto error;
1549                         }
1550                 }
1551         } else {
1552                 dev_dbg(xsdirxss->core.dev, "Not registering the EDH controls as EDH is disabled in IP\n");
1553         }
1554
1555         if (xsdirxss->ctrl_handler.error) {
1556                 dev_err(&pdev->dev, "failed to add controls\n");
1557                 ret = xsdirxss->ctrl_handler.error;
1558                 goto error;
1559         }
1560
1561         subdev->ctrl_handler = &xsdirxss->ctrl_handler;
1562
1563         ret = v4l2_ctrl_handler_setup(&xsdirxss->ctrl_handler);
1564         if (ret < 0) {
1565                 dev_err(&pdev->dev, "failed to set controls\n");
1566                 goto error;
1567         }
1568
1569         platform_set_drvdata(pdev, xsdirxss);
1570
1571         ret = v4l2_async_register_subdev(subdev);
1572         if (ret < 0) {
1573                 dev_err(&pdev->dev, "failed to register subdev\n");
1574                 goto error;
1575         }
1576
1577         xsdirxss->streaming = false;
1578
1579         dev_info(xsdirxss->core.dev, "Xilinx SDI Rx Subsystem device found!\n");
1580
1581         xsdirx_core_enable(core);
1582
1583         return 0;
1584 error:
1585         v4l2_ctrl_handler_free(&xsdirxss->ctrl_handler);
1586         media_entity_cleanup(&subdev->entity);
1587
1588         return ret;
1589 }
1590
1591 static int xsdirxss_remove(struct platform_device *pdev)
1592 {
1593         struct xsdirxss_state *xsdirxss = platform_get_drvdata(pdev);
1594         struct v4l2_subdev *subdev = &xsdirxss->subdev;
1595
1596         v4l2_async_unregister_subdev(subdev);
1597         v4l2_ctrl_handler_free(&xsdirxss->ctrl_handler);
1598         media_entity_cleanup(&subdev->entity);
1599
1600         return 0;
1601 }
1602
1603 static const struct of_device_id xsdirxss_of_id_table[] = {
1604         { .compatible = "xlnx,v-smpte-uhdsdi-rx-ss" },
1605         { }
1606 };
1607 MODULE_DEVICE_TABLE(of, xsdirxss_of_id_table);
1608
1609 static struct platform_driver xsdirxss_driver = {
1610         .driver = {
1611                 .name           = "xilinx-sdirxss",
1612                 .of_match_table = xsdirxss_of_id_table,
1613         },
1614         .probe                  = xsdirxss_probe,
1615         .remove                 = xsdirxss_remove,
1616 };
1617
1618 module_platform_driver(xsdirxss_driver);
1619
1620 MODULE_AUTHOR("Vishal Sagar <vsagar@xilinx.com>");
1621 MODULE_DESCRIPTION("Xilinx SDI Rx Subsystem Driver");
1622 MODULE_LICENSE("GPL v2");