1
2
3
4
5
6
7
8
9
10#include <linux/bitfield.h>
11#include <linux/clk.h>
12#include <linux/device.h>
13#include <linux/interrupt.h>
14#include <linux/module.h>
15#include <linux/of_irq.h>
16#include <linux/of_address.h>
17#include <linux/phy/phy.h>
18#include <linux/phy/phy-dp.h>
19#include <linux/platform_device.h>
20#include <linux/types.h>
21#include <linux/v4l2-dv-timings.h>
22#include <linux/v4l2-subdev.h>
23
24#include <drm/drm_dp_helper.h>
25#include <dt-bindings/media/xilinx-vip.h>
26
27#include <media/v4l2-dv-timings.h>
28#include <media/v4l2-event.h>
29#include <media/v4l2-subdev.h>
30
31#include "xilinx-vip.h"
32
33
34#define XDPRX_LINK_ENABLE_REG 0x000
35#define XDPRX_AUX_CLKDIV_REG 0x004
36#define XDPRX_AUX_DEFER_COUNT 6
37#define XDPRX_AUX_DEFER_SHIFT 24
38#define XDPRX_AUX_DEFER_MASK GENMASK(27, 24)
39
40#define XDPRX_LINERST_DIS_REG 0x008
41#define XDPRX_DTG_REG 0x00c
42#define XDPRX_DTG_DIS_MASK GENMASK(31, 1)
43
44#define XDPRX_PIXEL_WIDTH_REG 0x010
45#define XDPRX_INTR_MASK_REG 0x014
46#define XDPRX_INTR_POWER_MASK BIT(1)
47#define XDPRX_INTR_NOVID_MASK BIT(2)
48#define XDPRX_INTR_VBLANK_MASK BIT(3)
49#define XDPRX_INTR_TRLOST_MASK BIT(4)
50#define XDPRX_INTR_VID_MASK BIT(6)
51#define XDPRX_INTR_TRDONE_MASK BIT(14)
52#define XDPRX_INTR_BWCHANGE_MASK BIT(15)
53#define XDPRX_INTR_TP1_MASK BIT(16)
54#define XDPRX_INTR_T2_MASK BIT(17)
55#define XDPRX_INTR_TP3_MASK BIT(18)
56#define XDPRX_INTR_LINKQUAL_MASK BIT(29)
57#define XDPRX_INTR_UNPLUG_MASK BIT(31)
58#define XDPRX_INTR_CRCTST_MASK BIT(30)
59#define XDPRX_INTR_TRNG_MASK (XDPRX_INTR_TP1_MASK | \
60 XDPRX_INTR_T2_MASK |\
61 XDPRX_INTR_TP3_MASK | \
62 XDPRX_INTR_POWER_MASK |\
63 XDPRX_INTR_CRCTST_MASK |\
64 XDPRX_INTR_BWCHANGE_MASK)
65#define XDPRX_INTR_ALL_MASK 0xffffffff
66
67#define XDPRX_SOFT_RST_REG 0x01c
68#define XDPRX_SOFT_VIDRST_MASK BIT(0)
69#define XDPRX_SOFT_AUXRST_MASK BIT(7)
70
71#define XDPRX_HPD_INTR_REG 0x02c
72#define XDPRX_HPD_INTR_MASK BIT(1)
73#define XDPRX_HPD_PULSE_MASK GENMASK(31, 16)
74
75#define XDPRX_INTR_CAUSE_REG 0x040
76#define XDPRX_INTR_CAUSE1_REG 0x048
77#define XDPRX_CRC_CONFIG_REG 0x074
78#define XDPRX_CRC_EN_MASK BIT(5)
79
80#define XDPRX_LOCAL_EDID_REG 0x084
81#define XDPRX_VIDEO_UNSUPPORTED_REG 0x094
82#define XDPRX_VRD_BWSET_REG 0x09c
83#define XDPRX_LANE_CNT_REG 0x0a0
84#define XDPRX_EFRAME_CAP_MASK BIT(7)
85#define XDPRX_LNCNT_TPS3_MASK BIT(6)
86
87#define XDPRX_TP_SET_REG 0x0a4
88#define XDPRX_AUX_RDINT_SHIFT 8
89#define XDPRX_AUX_RDINT_16MS 4
90#define XDPRX_AUX_READINTRVL_REG BIT(15)
91
92#define XDPRX_CTRL_DPCD_REG 0x0b8
93#define XDPRX_MST_CAP_REG 0x0d0
94#define XDPRX_SINK_COUNT_REG 0x0d4
95
96#define XDPRX_PHY_REG 0x200
97#define XDPRX_PHY_GTPLLRST_MASK BIT(0)
98#define XDPRX_PHY_GTRXRST_MASK BIT(1)
99#define XDPRX_PHYRST_TRITER_MASK BIT(23)
100#define XDPRX_PHYRST_RATECHANGE_MASK BIT(24)
101#define XDPRX_PHYRST_TP1START_MASK BIT(25)
102#define XDPRX_PHYRST_ENBL_MASK 0x0
103#define XDPRX_PHY_INIT_MASK GENMASK(29, 27)
104
105#define XDPRX_MINVOLT_SWING_REG 0x214
106#define XDPRX_VS_PE_SHIFT 12
107#define XDPRX_VS_SWEEP_CNTSHIFT 4
108#define XDPRX_VS_CROPT_SHIFT 2
109#define XDPRX_VS_CROPT_INC4CNT 1
110#define XDPRX_MIN_VS_MASK (1 | (XDPRX_VS_CROPT_INC4CNT << \
111 XDPRX_VS_CROPT_SHIFT) | \
112 (4 << XDPRX_VS_SWEEP_CNTSHIFT) | \
113 (1 << XDPRX_VS_PE_SHIFT))
114
115#define XDPRX_CDRCTRL_CFG_REG 0x21c
116
117#define XDPRX_CDRCTRL_TDLOCK_VAL 0x1388
118#define XDPRX_CDRCTRL_DIS_TIMEOUT BIT(30)
119
120#define XDPRX_BSIDLE_TIME_REG 0x220
121#define XDPRX_BSIDLE_TMOUT_VAL 0x047868C0
122
123#define XDPRX_LINK_BW_REG 0x400
124#define XDPRX_LANE_COUNT_REG 0x404
125#define XDPRX_MSA_HRES_REG 0x500
126#define XDPRX_MSA_VHEIGHT_REG 0x514
127#define XDPRX_MSA_HTOTAL_REG 0x510
128#define XDPRX_MSA_VTOTAL_REG 0x524
129#define XDPRX_MSA_MISC0_REG 0x528
130#define XDPRX_MSA_FMT_MASK GENMASK(2, 1)
131#define XDPRX_MSA_BPC_MASK GENMASK(7, 5)
132#define XDPRX_COLOR_DEPTH_SHIFT 5
133#define XDPRX_COLOR_FMT_SHIFT 1
134
135#define XDPRX_MSA_MISC1_REG 0x52c
136#define XDPRX_INTERLACE_MASK BIT(0)
137
138#define XDPRX_MSA_MVID_REG 0x530
139#define XDPRX_MSA_NVID_REG 0x534
140#define XDPRX_INTR_ERRORCNT_MASK BIT(28)
141#define XDPRX_INTR_LANESET_MASK BIT(30)
142
143#define XDPRX_COLOR_FORMAT_RGB 0x0
144#define XDPRX_COLOR_FORMAT_422 0x1
145#define XDPRX_COLOR_FORMAT_444 0x2
146#define MHZ 1000000
147#define XDPRX_MAX_LANE_COUNT 4
148
149#define XDPRX_EDID_NUM_BLOCKS 3
150#define XDPRX_EDID_BLOCK_SIZE 128
151#define XDPRX_EDID_LENGTH (XDPRX_EDID_BLOCK_SIZE * \
152 XDPRX_EDID_NUM_BLOCKS * 4)
153
154
155
156
157#define XDPRX_HPD_PLUSE_5000 5000
158
159
160
161
162#define XDPRX_HPD_PLUSE_750 750
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189struct xdprxss_state {
190 struct device *dev;
191 struct v4l2_subdev subdev;
192 struct v4l2_event event;
193 struct v4l2_dv_timings detected_timings;
194 struct phy *phy[XDPRX_MAX_LANE_COUNT];
195 struct media_pad pad;
196 struct clk *axi_clk;
197 struct clk *rx_lnk_clk;
198 struct clk *rx_vid_clk;
199 void __iomem *dp_base;
200 void __iomem *edid_base;
201
202 spinlock_t lock;
203 struct v4l2_mbus_framefmt format;
204 unsigned int frame_interval;
205 u32 max_linkrate;
206 u32 max_lanecount;
207 u32 bpc;
208 bool hdcp_enable;
209 bool audio_enable;
210 unsigned int valid_stream : 1;
211 unsigned int streaming : 1;
212};
213
214
215
216
217
218
219static u8 xilinx_edid[384] = {
220 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x47, 0x41,
221 0x4c, 0x35, 0x37, 0x30, 0x20, 0x1b, 0x01, 0x04, 0xb5, 0x46, 0x27, 0x78,
222 0x3a, 0x76, 0x45, 0xae, 0x51, 0x33, 0xba, 0x26, 0x0d, 0x50, 0x54, 0xa5,
223 0x4b, 0x00, 0x81, 0x00, 0xb3, 0x00, 0xd1, 0x00, 0xa9, 0x40, 0x81, 0x80,
224 0xd1, 0xc0, 0x01, 0x01, 0x01, 0x01, 0x4d, 0xd0, 0x00, 0xa0, 0xf0, 0x70,
225 0x3e, 0x80, 0x30, 0x20, 0x35, 0x00, 0xba, 0x89, 0x21, 0x00, 0x00, 0x1a,
226 0x00, 0x00, 0x00, 0xff, 0x00, 0x46, 0x46, 0x4e, 0x58, 0x4d, 0x37, 0x38,
227 0x37, 0x30, 0x37, 0x35, 0x4c, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
228 0x45, 0x4c, 0x4c, 0x20, 0x55, 0x50, 0x33, 0x32, 0x31, 0x38, 0x4b, 0x0a,
229 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x4b, 0x1e, 0xb4, 0x6c, 0x01, 0x0a,
230 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x02, 0x70, 0x02, 0x03, 0x1d, 0xf1,
231 0x50, 0x10, 0x1f, 0x20, 0x05, 0x14, 0x04, 0x13, 0x12, 0x11, 0x03, 0x02,
232 0x16, 0x15, 0x07, 0x06, 0x01, 0x23, 0x09, 0x1f, 0x07, 0x83, 0x01, 0x00,
233 0x00, 0xa3, 0x66, 0x00, 0xa0, 0xf0, 0x70, 0x1f, 0x80, 0x30, 0x20, 0x35,
234 0x00, 0xba, 0x89, 0x21, 0x00, 0x00, 0x1a, 0x56, 0x5e, 0x00, 0xa0, 0xa0,
235 0xa0, 0x29, 0x50, 0x30, 0x20, 0x35, 0x00, 0xba, 0x89, 0x21, 0x00, 0x00,
236 0x1a, 0x7c, 0x39, 0x00, 0xA0, 0x80, 0x38, 0x1f, 0x40, 0x30, 0x20, 0x3a,
237 0x00, 0xba, 0x89, 0x21, 0x00, 0x00, 0x1a, 0xa8, 0x16, 0x00, 0xa0, 0x80,
238 0x38, 0x13, 0x40, 0x30, 0x20, 0x3a, 0x00, 0xba, 0x89, 0x21, 0x00, 0x00,
239 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 0x00, 0x00, 0x00, 0x47, 0x70, 0x12, 0x79, 0x00, 0x00, 0x12, 0x00, 0x16,
242 0x82, 0x10, 0x10, 0x00, 0xff, 0x0e, 0xdf, 0x10, 0x00, 0x00, 0x00, 0x00,
243 0x00, 0x44, 0x45, 0x4c, 0x47, 0x41, 0x4c, 0x35, 0x37, 0x30, 0x03, 0x01,
244 0x50, 0x70, 0x92, 0x01, 0x84, 0xff, 0x1d, 0xc7, 0x00, 0x1d, 0x80, 0x09,
245 0x00, 0xdf, 0x10, 0x2f, 0x00, 0x02, 0x00, 0x04, 0x00, 0xc1, 0x42, 0x01,
246 0x84, 0xff, 0x1d, 0xc7, 0x00, 0x2f, 0x80, 0x1f, 0x00, 0xdf, 0x10, 0x30,
247 0x00, 0x02, 0x00, 0x04, 0x00, 0xa8, 0x4e, 0x01, 0x04, 0xff, 0x0e, 0xc7,
248 0x00, 0x2f, 0x80, 0x1f, 0x00, 0xdf, 0x10, 0x61, 0x00, 0x02, 0x00, 0x09,
249 0x00, 0x97, 0x9d, 0x01, 0x04, 0xff, 0x0e, 0xc7, 0x00, 0x2f, 0x80, 0x1f,
250 0x00, 0xdf, 0x10, 0x2f, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x90,
252};
253
254static const u32 xdprxss_supported_mbus_fmts[] = {
255 MEDIA_BUS_FMT_UYVY8_1X16,
256 MEDIA_BUS_FMT_VUY8_1X24,
257 MEDIA_BUS_FMT_RBG888_1X24,
258 MEDIA_BUS_FMT_UYVY10_1X20,
259 MEDIA_BUS_FMT_VUY10_1X30,
260 MEDIA_BUS_FMT_RBG101010_1X30,
261};
262
263#define XLNX_V4L2_DV_BT_2048X1080P60 { \
264 .type = V4L2_DV_BT_656_1120, \
265 V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
266 V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
267 148500000, 88, 44, 20, 4, 5, 36, 0, 0, 0, \
268 V4L2_DV_BT_STD_CEA861) \
269}
270
271#define XLNX_V4L2_DV_BT_2048X1080I50 { \
272 .type = V4L2_DV_BT_656_1120, \
273 V4L2_INIT_BT_TIMINGS(2048, 1080, 1, \
274 V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
275 74250000, 274, 44, 274, 2, 5, 15, 3, 5, 15, \
276 V4L2_DV_BT_STD_CEA861) \
277}
278
279#define XLNX_V4L2_DV_BT_2048X1080I60 { \
280 .type = V4L2_DV_BT_656_1120, \
281 V4L2_INIT_BT_TIMINGS(2048, 1080, 1, \
282 V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
283 74250000, 66, 20, 66, 2, 5, 15, 3, 5, 15, \
284 V4L2_DV_BT_STD_CEA861) \
285}
286
287#define XLNX_V4L2_DV_BT_2048X1080P50 { \
288 .type = V4L2_DV_BT_656_1120, \
289 V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
290 V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
291 148500000, 400, 44, 148, 4, 5, 36, 0, 0, 0, \
292 V4L2_DV_BT_STD_CEA861) \
293}
294
295#define XLNX_V4L2_DV_BT_7680X4320P30 { \
296 .type = V4L2_DV_BT_656_1120, \
297 V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
298 V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
299 74250000, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
300 V4L2_DV_BT_STD_CEA861) \
301}
302
303static const struct v4l2_dv_timings fmt_cap[] = {
304 V4L2_DV_BT_CEA_1280X720P25,
305 V4L2_DV_BT_CEA_1280X720P30,
306 V4L2_DV_BT_CEA_1280X720P50,
307 V4L2_DV_BT_CEA_1280X720P60,
308 V4L2_DV_BT_CEA_1920X1080P25,
309 V4L2_DV_BT_CEA_1920X1080P30,
310 V4L2_DV_BT_CEA_1920X1080P50,
311 V4L2_DV_BT_CEA_1920X1080P60,
312 V4L2_DV_BT_CEA_1920X1080I50,
313 V4L2_DV_BT_CEA_1920X1080I60,
314 V4L2_DV_BT_CEA_3840X2160P30,
315 V4L2_DV_BT_CEA_3840X2160P50,
316 V4L2_DV_BT_CEA_3840X2160P60,
317 V4L2_DV_BT_CEA_4096X2160P25,
318 V4L2_DV_BT_CEA_4096X2160P30,
319 V4L2_DV_BT_CEA_4096X2160P50,
320 V4L2_DV_BT_CEA_4096X2160P60,
321
322 XLNX_V4L2_DV_BT_2048X1080I50,
323 XLNX_V4L2_DV_BT_2048X1080I60,
324 XLNX_V4L2_DV_BT_2048X1080P50,
325 XLNX_V4L2_DV_BT_2048X1080P60,
326 XLNX_V4L2_DV_BT_7680X4320P30,
327};
328
329struct xdprxss_dv_map {
330 u32 width;
331 u32 height;
332 u32 fps;
333 struct v4l2_dv_timings timing;
334};
335
336static const struct xdprxss_dv_map xdprxss_dv_timings[] = {
337
338 { 1280, 720, 25, V4L2_DV_BT_CEA_1280X720P25 },
339
340 { 1280, 720, 30, V4L2_DV_BT_CEA_1280X720P30 },
341
342 { 1280, 720, 50, V4L2_DV_BT_CEA_1280X720P50 },
343
344 { 1280, 720, 60, V4L2_DV_BT_CEA_1280X720P60 },
345
346 { 1920, 1080, 25, V4L2_DV_BT_CEA_1920X1080P25 },
347
348 { 1920, 1080, 30, V4L2_DV_BT_CEA_1920X1080P30 },
349
350 { 1920, 1080, 50, V4L2_DV_BT_CEA_1920X1080P50 },
351
352 { 1920, 1080, 60, V4L2_DV_BT_CEA_1920X1080P60 },
353
354 { 1920, 540, 25, V4L2_DV_BT_CEA_1920X1080I50 },
355
356
357 { 1920, 540, 30, V4L2_DV_BT_CEA_1920X1080I60 },
358 { 3840, 2160, 30, V4L2_DV_BT_CEA_3840X2160P30 },
359 { 3840, 2160, 50, V4L2_DV_BT_CEA_3840X2160P50 },
360 { 3840, 2160, 60, V4L2_DV_BT_CEA_3840X2160P60 },
361 { 4096, 2160, 25, V4L2_DV_BT_CEA_4096X2160P25 },
362 { 4096, 2160, 30, V4L2_DV_BT_CEA_4096X2160P30 },
363 { 4096, 2160, 50, V4L2_DV_BT_CEA_4096X2160P50 },
364 { 4096, 2160, 60, V4L2_DV_BT_CEA_4096X2160P60 },
365
366 { 2048, 540, 25, XLNX_V4L2_DV_BT_2048X1080I50 },
367
368
369 { 2048, 540, 30, XLNX_V4L2_DV_BT_2048X1080I60 },
370
371 { 2048, 1080, 50, XLNX_V4L2_DV_BT_2048X1080P50 },
372
373
374 { 2048, 1080, 60, XLNX_V4L2_DV_BT_2048X1080P60 },
375 { 7680, 4320, 30, XLNX_V4L2_DV_BT_7680X4320P30 }
376};
377
378static inline struct xdprxss_state *
379to_xdprxssstate(struct v4l2_subdev *subdev)
380{
381 return container_of(subdev, struct xdprxss_state, subdev);
382}
383
384
385static inline u32 xdprxss_read(struct xdprxss_state *xdprxss, u32 addr)
386{
387 return ioread32(xdprxss->dp_base + addr);
388}
389
390static inline void xdprxss_write(struct xdprxss_state *xdprxss, u32 addr,
391 u32 value)
392{
393 iowrite32(value, xdprxss->dp_base + addr);
394}
395
396static inline void xdprxss_clr(struct xdprxss_state *xdprxss, u32 addr,
397 u32 clr)
398{
399 xdprxss_write(xdprxss, addr, xdprxss_read(xdprxss, addr) & ~clr);
400}
401
402static inline void xdprxss_set(struct xdprxss_state *xdprxss, u32 addr,
403 u32 set)
404{
405 xdprxss_write(xdprxss, addr, xdprxss_read(xdprxss, addr) | set);
406}
407
408static inline void xdprxss_dpcd_update_start(struct xdprxss_state *xdprxss)
409{
410 iowrite32(0x1, xdprxss->dp_base + XDPRX_CTRL_DPCD_REG);
411}
412
413static inline void xdprxss_dpcd_update_end(struct xdprxss_state *xdprxss)
414{
415 iowrite32(0x0, xdprxss->dp_base + XDPRX_CTRL_DPCD_REG);
416}
417
418
419
420
421
422
423
424
425
426
427
428static inline void xdprxss_dpcd_update(struct xdprxss_state *xdprxss,
429 u32 addr, u32 val)
430{
431 xdprxss_write(xdprxss, addr, val);
432}
433
434
435
436
437
438
439
440
441
442static int xdprxss_get_stream_properties(struct xdprxss_state *state)
443{
444 struct v4l2_mbus_framefmt *format = &state->format;
445 struct v4l2_bt_timings *bt = &state->detected_timings.bt;
446
447 u32 rxmsa_mvid, rxmsa_nvid, rxmsa_misc, recv_clk_freq, linkrate;
448 u16 vres_total, hres_total, framerate, lanecount;
449 u8 pixel_width, fmt;
450 u16 read_val;
451
452 rxmsa_mvid = xdprxss_read(state, XDPRX_MSA_MVID_REG);
453 rxmsa_nvid = xdprxss_read(state, XDPRX_MSA_NVID_REG);
454
455 bt->width = xdprxss_read(state, XDPRX_MSA_HRES_REG);
456
457 bt->height = xdprxss_read(state, XDPRX_MSA_VHEIGHT_REG);
458 rxmsa_misc = xdprxss_read(state, XDPRX_MSA_MISC0_REG);
459
460 vres_total = xdprxss_read(state, XDPRX_MSA_VTOTAL_REG);
461 hres_total = xdprxss_read(state, XDPRX_MSA_HTOTAL_REG);
462 linkrate = xdprxss_read(state, XDPRX_LINK_BW_REG);
463 lanecount = xdprxss_read(state, XDPRX_LANE_COUNT_REG);
464
465 recv_clk_freq = (linkrate * 27 * rxmsa_mvid) / rxmsa_nvid;
466
467 if (recv_clk_freq > 540 && lanecount == 4)
468 pixel_width = 0x4;
469 else if (recv_clk_freq > 270 && (lanecount != 1))
470 pixel_width = 0x2;
471 else
472 pixel_width = 0x1;
473
474 framerate = (recv_clk_freq * MHZ) / (hres_total * vres_total);
475 framerate = roundup(framerate, 5);
476 xdprxss_write(state, XDPRX_LINERST_DIS_REG, 0x1);
477
478 read_val = xdprxss_read(state, XDPRX_DTG_REG);
479 xdprxss_write(state, XDPRX_DTG_REG, (read_val & XDPRX_DTG_DIS_MASK));
480 xdprxss_write(state, XDPRX_PIXEL_WIDTH_REG, pixel_width);
481 read_val = xdprxss_read(state, XDPRX_DTG_REG);
482 xdprxss_write(state, XDPRX_DTG_REG, (read_val | 0x1));
483 fmt = FIELD_GET(XDPRX_MSA_FMT_MASK, rxmsa_misc);
484 state->bpc = FIELD_GET(XDPRX_MSA_BPC_MASK, rxmsa_misc);
485
486 switch (fmt) {
487 case XDPRX_COLOR_FORMAT_422:
488 if (state->bpc == 10)
489 format->code = MEDIA_BUS_FMT_UYVY10_1X20;
490 else
491 format->code = MEDIA_BUS_FMT_UYVY8_1X16;
492 break;
493 case XDPRX_COLOR_FORMAT_444:
494 if (state->bpc == 10)
495 format->code = MEDIA_BUS_FMT_VUY10_1X30;
496 else
497 format->code = MEDIA_BUS_FMT_VUY8_1X24;
498 break;
499 case XDPRX_COLOR_FORMAT_RGB:
500 if (state->bpc == 10)
501 format->code = MEDIA_BUS_FMT_RBG101010_1X30;
502 else
503 format->code = MEDIA_BUS_FMT_RBG888_1X24;
504 break;
505 default:
506 dev_err(state->dev, "Unsupported color format\n");
507
508 return -EINVAL;
509 }
510
511 spin_lock(&state->lock);
512 format->width = bt->width;
513 format->height = bt->height;
514 format->colorspace = V4L2_COLORSPACE_REC709;
515 format->xfer_func = V4L2_XFER_FUNC_DEFAULT;
516 format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
517 format->quantization = V4L2_QUANTIZATION_DEFAULT;
518 format->field = V4L2_FIELD_NONE;
519 state->frame_interval = framerate;
520 spin_unlock(&state->lock);
521
522 dev_dbg(state->dev, "detected properties : width %d height %d\n",
523 bt->width, bt->height);
524
525 return 0;
526}
527
528static void xdprxss_set_training_params(struct xdprxss_state *xdprxss)
529{
530 unsigned int offset;
531
532
533
534
535
536
537
538 xdprxss_write(xdprxss, XDPRX_MINVOLT_SWING_REG, XDPRX_MIN_VS_MASK);
539 xdprxss_write(xdprxss, XDPRX_AUX_CLKDIV_REG,
540 xdprxss_read(xdprxss, XDPRX_AUX_CLKDIV_REG) |
541 FIELD_PREP(XDPRX_AUX_DEFER_MASK, XDPRX_AUX_DEFER_COUNT));
542
543 xdprxss_dpcd_update_start(xdprxss);
544 xdprxss_dpcd_update(xdprxss, XDPRX_TP_SET_REG,
545 (XDPRX_AUX_RDINT_16MS << XDPRX_AUX_RDINT_SHIFT) |
546 XDPRX_AUX_READINTRVL_REG);
547 xdprxss_dpcd_update_end(xdprxss);
548
549 xdprxss_clr(xdprxss, XDPRX_INTR_MASK_REG, XDPRX_INTR_ALL_MASK);
550
551
552 for (offset = 0; offset < XDPRX_EDID_LENGTH; offset = offset + 4) {
553 iowrite32((uint32_t)xilinx_edid[offset / 4],
554 xdprxss->edid_base + offset);
555 }
556 xdprxss_write(xdprxss, XDPRX_LOCAL_EDID_REG, 0x1);
557
558
559 xdprxss_set(xdprxss, XDPRX_INTR_MASK_REG, XDPRX_INTR_ALL_MASK);
560
561
562 xdprxss_clr(xdprxss, XDPRX_INTR_MASK_REG, XDPRX_INTR_TRNG_MASK);
563 xdprxss_write(xdprxss, XDPRX_AUX_CLKDIV_REG,
564 xdprxss_read(xdprxss, XDPRX_AUX_CLKDIV_REG) |
565 FIELD_PREP(XDPRX_AUX_DEFER_MASK, XDPRX_AUX_DEFER_COUNT));
566 xdprxss_write(xdprxss, XDPRX_BSIDLE_TIME_REG, XDPRX_BSIDLE_TMOUT_VAL);
567 xdprxss_clr(xdprxss, XDPRX_CRC_CONFIG_REG, XDPRX_CRC_EN_MASK);
568 xdprxss_write(xdprxss, XDPRX_LINK_ENABLE_REG, 0x1);
569}
570
571static void xdprxss_core_init(struct xdprxss_state *xdprxss)
572{
573 unsigned long axi_clk;
574
575 u32 max_lanecount = xdprxss->max_lanecount;
576
577 xdprxss_dpcd_update_start(xdprxss);
578 xdprxss_dpcd_update(xdprxss,
579 XDPRX_VRD_BWSET_REG, xdprxss->max_linkrate);
580 max_lanecount |= (XDPRX_EFRAME_CAP_MASK | XDPRX_LNCNT_TPS3_MASK);
581 xdprxss_dpcd_update(xdprxss, XDPRX_LANE_CNT_REG, max_lanecount);
582 xdprxss_dpcd_update_end(xdprxss);
583 xdprxss_write(xdprxss, XDPRX_LINK_ENABLE_REG, 0x0);
584 axi_clk = clk_get_rate(xdprxss->axi_clk);
585 xdprxss_write(xdprxss, XDPRX_AUX_CLKDIV_REG, axi_clk / MHZ);
586
587 xdprxss_write(xdprxss, XDPRX_PHY_REG, XDPRX_PHY_GTPLLRST_MASK |
588 XDPRX_PHY_GTRXRST_MASK);
589
590 xdprxss_write(xdprxss, XDPRX_PHY_REG, XDPRX_PHY_GTRXRST_MASK);
591
592
593
594
595
596 xdprxss_write(xdprxss, XDPRX_PHY_REG,
597 XDPRX_PHYRST_ENBL_MASK |
598 XDPRX_PHYRST_TRITER_MASK |
599 XDPRX_PHYRST_RATECHANGE_MASK |
600 XDPRX_PHYRST_TP1START_MASK);
601 xdprxss_write(xdprxss, XDPRX_MST_CAP_REG, 0x0);
602 xdprxss_write(xdprxss, XDPRX_SINK_COUNT_REG, 1);
603 xdprxss_set_training_params(xdprxss);
604}
605
606static void xdprxss_irq_unplug(struct xdprxss_state *state)
607{
608 dev_dbg(state->dev, "Asserted cable unplug interrupt\n");
609
610 xdprxss_set(state, XDPRX_SOFT_RST_REG, XDPRX_SOFT_VIDRST_MASK);
611 xdprxss_clr(state, XDPRX_SOFT_RST_REG, XDPRX_SOFT_VIDRST_MASK);
612
613 xdprxss_set(state, XDPRX_INTR_MASK_REG, XDPRX_INTR_ALL_MASK);
614 xdprxss_clr(state, XDPRX_INTR_MASK_REG, XDPRX_INTR_TRNG_MASK);
615
616
617
618
619
620
621 xdprxss_write(state, XDPRX_HPD_INTR_REG,
622 FIELD_PREP(XDPRX_HPD_PULSE_MASK, XDPRX_HPD_PLUSE_5000) |
623 XDPRX_HPD_INTR_MASK);
624}
625
626static void xdprxss_irq_tp1(struct xdprxss_state *state)
627{
628 union phy_configure_opts phy_opts = { 0 };
629 struct phy_configure_opts_dp *phy_cfg = &phy_opts.dp;
630 u32 linkrate;
631 unsigned int i;
632
633 dev_dbg(state->dev, "Asserted traning pattern 1\n");
634
635 linkrate = xdprxss_read(state, XDPRX_LINK_BW_REG);
636
637 switch (linkrate) {
638 case DP_LINK_BW_1_62:
639 case DP_LINK_BW_2_7:
640 case DP_LINK_BW_5_4:
641 case DP_LINK_BW_8_1:
642 phy_cfg->link_rate = linkrate * 270;
643 break;
644 default:
645 dev_err(state->dev, "invalid link rate\n");
646 break;
647 }
648 phy_cfg->set_rate = 1;
649 for (i = 0; i < state->max_lanecount; i++)
650 phy_configure(state->phy[i], &phy_opts);
651
652
653 xdprxss_write(state, XDPRX_PHY_REG, XDPRX_PHY_INIT_MASK);
654 phy_reset(state->phy[0]);
655 xdprxss_clr(state, XDPRX_INTR_MASK_REG, XDPRX_INTR_ALL_MASK);
656}
657
658static void xdprxss_training_failure(struct xdprxss_state *state)
659{
660 dev_dbg(state->dev, "Traning Lost !!\n");
661 state->valid_stream = false;
662
663 xdprxss_write(state, XDPRX_HPD_INTR_REG,
664 FIELD_PREP(XDPRX_HPD_PULSE_MASK, XDPRX_HPD_PLUSE_750) |
665 XDPRX_HPD_INTR_MASK);
666
667
668 xdprxss_set(state, XDPRX_SOFT_RST_REG, XDPRX_SOFT_AUXRST_MASK);
669 xdprxss_clr(state, XDPRX_SOFT_RST_REG, XDPRX_SOFT_AUXRST_MASK);
670}
671
672static void xdprxss_irq_no_video(struct xdprxss_state *state)
673{
674 dev_dbg(state->dev, "No Valid video received !!\n");
675
676 xdprxss_write(state, XDPRX_VIDEO_UNSUPPORTED_REG, 0x1);
677 xdprxss_clr(state, XDPRX_INTR_MASK_REG, XDPRX_INTR_VBLANK_MASK);
678 xdprxss_set(state, XDPRX_INTR_MASK_REG, XDPRX_INTR_NOVID_MASK);
679
680 xdprxss_set(state, XDPRX_DTG_REG, 0x0);
681 xdprxss_set(state, XDPRX_DTG_REG, 0x1);
682
683
684 xdprxss_set(state, XDPRX_SOFT_RST_REG, XDPRX_SOFT_VIDRST_MASK);
685 xdprxss_clr(state, XDPRX_SOFT_RST_REG, XDPRX_SOFT_VIDRST_MASK);
686
687
688 memset(&state->event, 0, sizeof(state->event));
689 state->event.type = V4L2_EVENT_SOURCE_CHANGE;
690 state->event.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION;
691 v4l2_subdev_notify_event(&state->subdev, &state->event);
692 state->valid_stream = false;
693}
694
695static void xdprxss_irq_valid_video(struct xdprxss_state *state)
696{
697 dev_dbg(state->dev, "Valid Video received !!\n");
698 xdprxss_write(state, XDPRX_VIDEO_UNSUPPORTED_REG, 0x0);
699
700 if (!xdprxss_get_stream_properties(state)) {
701 memset(&state->event, 0, sizeof(state->event));
702 state->event.type = V4L2_EVENT_SOURCE_CHANGE;
703 state->event.u.src_change.changes =
704 V4L2_EVENT_SRC_CH_RESOLUTION;
705 v4l2_subdev_notify_event(&state->subdev, &state->event);
706 state->valid_stream = true;
707 } else {
708 dev_err(state->dev, "Unable to get stream properties!\n");
709 state->valid_stream = false;
710 }
711}
712
713static irqreturn_t xdprxss_irq_handler(int irq, void *dev_id)
714{
715 struct xdprxss_state *state = (struct xdprxss_state *)dev_id;
716 u32 status;
717
718 status = xdprxss_read(state, XDPRX_INTR_CAUSE_REG);
719 status &= ~xdprxss_read(state, XDPRX_INTR_MASK_REG);
720
721 if (!status)
722 return IRQ_NONE;
723
724 if (status & XDPRX_INTR_UNPLUG_MASK)
725 xdprxss_irq_unplug(state);
726 if (status & XDPRX_INTR_TP1_MASK)
727 xdprxss_irq_tp1(state);
728 if (status & XDPRX_INTR_TRLOST_MASK)
729 xdprxss_training_failure(state);
730 if (status & XDPRX_INTR_NOVID_MASK)
731 xdprxss_irq_no_video(state);
732 if (status & XDPRX_INTR_VID_MASK)
733 xdprxss_irq_valid_video(state);
734#ifdef DEBUG
735 if (status & XDPRX_INTR_TRDONE_MASK)
736 dev_dbg(state->dev, "DP Link training is done !!\n");
737#endif
738
739 return IRQ_HANDLED;
740}
741
742
743
744
745
746
747
748
749
750static int xdprxss_subscribe_event(struct v4l2_subdev *sd,
751 struct v4l2_fh *fh,
752 struct v4l2_event_subscription *sub)
753{
754 int ret;
755 struct xdprxss_state *xdprxss = to_xdprxssstate(sd);
756
757 dev_dbg(xdprxss->dev, "Event subscribed : 0x%08x\n", sub->type);
758
759 switch (sub->type) {
760 case V4L2_EVENT_SOURCE_CHANGE:
761 ret = v4l2_src_change_event_subscribe(fh, sub);
762 break;
763 default:
764 ret = -EINVAL;
765 }
766
767 return ret;
768}
769
770static int xdprxss_s_stream(struct v4l2_subdev *sd, int enable)
771{
772 struct xdprxss_state *xdprxss = to_xdprxssstate(sd);
773
774
775 if (enable == xdprxss->streaming)
776 return 0;
777
778 if (enable && !xdprxss->valid_stream)
779 return -EINVAL;
780
781 xdprxss->streaming = enable;
782
783 return 0;
784}
785
786
787
788
789
790
791
792
793
794
795
796
797
798static int xdprxss_g_input_status(struct v4l2_subdev *sd, u32 *status)
799{
800 struct xdprxss_state *xdprxss = to_xdprxssstate(sd);
801
802 if (!xdprxss->valid_stream)
803 *status = V4L2_IN_ST_NO_SYNC | V4L2_IN_ST_NO_SIGNAL;
804 else
805 *status = 0;
806
807 return 0;
808}
809
810static struct v4l2_mbus_framefmt *
811__xdprxss_get_pad_format(struct xdprxss_state *xdprxss,
812 struct v4l2_subdev_pad_config *cfg,
813 unsigned int pad, u32 which)
814{
815 struct v4l2_mbus_framefmt *format;
816
817 switch (which) {
818 case V4L2_SUBDEV_FORMAT_TRY:
819 format = v4l2_subdev_get_try_format(&xdprxss->subdev, cfg, pad);
820 break;
821 case V4L2_SUBDEV_FORMAT_ACTIVE:
822 format = &xdprxss->format;
823 break;
824 default:
825 format = NULL;
826 break;
827 }
828
829 return format;
830}
831
832
833
834
835
836
837
838
839
840
841
842static int xdprxss_init_cfg(struct v4l2_subdev *sd,
843 struct v4l2_subdev_pad_config *cfg)
844{
845 struct xdprxss_state *xdprxss = to_xdprxssstate(sd);
846 struct v4l2_mbus_framefmt *format;
847
848 format = v4l2_subdev_get_try_format(sd, cfg, 0);
849
850 if (!xdprxss->valid_stream)
851 *format = xdprxss->format;
852
853 return 0;
854}
855
856
857
858
859
860
861
862
863
864
865
866
867
868static int xdprxss_getset_format(struct v4l2_subdev *sd,
869 struct v4l2_subdev_pad_config *cfg,
870 struct v4l2_subdev_format *fmt)
871{
872 struct xdprxss_state *xdprxss = to_xdprxssstate(sd);
873 struct v4l2_mbus_framefmt *format;
874
875 if (!xdprxss->valid_stream) {
876 dev_err(xdprxss->dev, "Video not locked!\n");
877 return -EINVAL;
878 }
879
880 dev_dbg(xdprxss->dev,
881 "set width %d height %d code %d field %d colorspace %d\n",
882 fmt->format.width, fmt->format.height,
883 fmt->format.code, fmt->format.field,
884 fmt->format.colorspace);
885 format = __xdprxss_get_pad_format(xdprxss, cfg,
886 fmt->pad, fmt->which);
887 if (!format)
888 return -EINVAL;
889
890 fmt->format = *format;
891
892 return 0;
893}
894
895
896
897
898
899
900
901
902
903static int xdprxss_enum_mbus_code(struct v4l2_subdev *sd,
904 struct v4l2_subdev_pad_config *cfg,
905 struct v4l2_subdev_mbus_code_enum *code)
906{
907 struct xdprxss_state *xdprxss = to_xdprxssstate(sd);
908 u32 index = code->index;
909 u32 base = 0;
910
911 if (xdprxss->bpc == 8)
912 base = 0;
913
914 if (xdprxss->bpc == 10)
915 base = 3;
916
917 if (code->pad || index >= 3)
918 return -EINVAL;
919
920 code->code = xdprxss_supported_mbus_fmts[base + index];
921
922 return 0;
923}
924
925
926
927
928
929
930
931
932static int xdprxss_enum_dv_timings(struct v4l2_subdev *sd,
933 struct v4l2_enum_dv_timings *timings)
934{
935 if (timings->index >= ARRAY_SIZE(fmt_cap))
936 return -EINVAL;
937
938 if (timings->pad != 0)
939 return -EINVAL;
940
941 timings->timings = fmt_cap[timings->index];
942
943 return 0;
944}
945
946
947
948
949
950
951
952
953
954static int xdprxss_get_dv_timings_cap(struct v4l2_subdev *subdev,
955 struct v4l2_dv_timings_cap *cap)
956{
957 struct v4l2_dv_timings_cap xdprxss_dv_timings_cap = {
958 .type = V4L2_DV_BT_656_1120,
959 .reserved = { 0 },
960 V4L2_INIT_BT_TIMINGS
961 (800, 7680,
962 600, 4320,
963 25000000, 297000000,
964 V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
965 V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
966 V4L2_DV_BT_CAP_INTERLACED | V4L2_DV_BT_CAP_PROGRESSIVE |
967 V4L2_DV_BT_CAP_REDUCED_BLANKING |
968 V4L2_DV_BT_CAP_CUSTOM
969 )
970 };
971
972 if (cap->pad != 0)
973 return -EINVAL;
974
975 *cap = xdprxss_dv_timings_cap;
976
977 return 0;
978}
979
980static int xdprxss_query_dv_timings(struct v4l2_subdev *sd,
981 struct v4l2_dv_timings *timings)
982{
983 struct xdprxss_state *state = to_xdprxssstate(sd);
984 unsigned int i;
985
986 if (!timings)
987 return -EINVAL;
988
989 if (!state->valid_stream)
990 return -ENOLCK;
991 for (i = 0; i < ARRAY_SIZE(xdprxss_dv_timings); i++) {
992 if (state->format.width == xdprxss_dv_timings[i].width &&
993 state->format.height == xdprxss_dv_timings[i].height &&
994 state->frame_interval == xdprxss_dv_timings[i].fps) {
995 *timings = xdprxss_dv_timings[i].timing;
996 return 0;
997 }
998 }
999
1000 return -ERANGE;
1001}
1002
1003
1004
1005
1006
1007static const struct media_entity_operations xdprxss_media_ops = {
1008 .link_validate = v4l2_subdev_link_validate
1009};
1010
1011static const struct v4l2_subdev_core_ops xdprxss_core_ops = {
1012 .subscribe_event = xdprxss_subscribe_event,
1013 .unsubscribe_event = v4l2_event_subdev_unsubscribe,
1014};
1015
1016static const struct v4l2_subdev_video_ops xdprxss_video_ops = {
1017 .query_dv_timings = xdprxss_query_dv_timings,
1018 .s_stream = xdprxss_s_stream,
1019 .g_input_status = xdprxss_g_input_status,
1020};
1021
1022static const struct v4l2_subdev_pad_ops xdprxss_pad_ops = {
1023 .init_cfg = xdprxss_init_cfg,
1024 .enum_mbus_code = xdprxss_enum_mbus_code,
1025 .get_fmt = xdprxss_getset_format,
1026 .set_fmt = xdprxss_getset_format,
1027 .enum_dv_timings = xdprxss_enum_dv_timings,
1028 .dv_timings_cap = xdprxss_get_dv_timings_cap,
1029};
1030
1031static const struct v4l2_subdev_ops xdprxss_ops = {
1032 .core = &xdprxss_core_ops,
1033 .video = &xdprxss_video_ops,
1034 .pad = &xdprxss_pad_ops
1035};
1036
1037
1038
1039
1040static int xdprxss_parse_of(struct xdprxss_state *xdprxss)
1041{
1042 struct device_node *node = xdprxss->dev->of_node;
1043 u32 val = 0;
1044 int ret;
1045
1046 ret = of_property_read_u32(node, "xlnx,bpc", &xdprxss->bpc);
1047 if (ret < 0) {
1048 if (ret != -EINVAL) {
1049 dev_err(xdprxss->dev, "failed to get xlnx,bpp\n");
1050 return ret;
1051 }
1052 }
1053
1054
1055
1056
1057 if (xdprxss->bpc != 8 && xdprxss->bpc != 10) {
1058 dev_err(xdprxss->dev, "unsupported bpc = %u\n", xdprxss->bpc);
1059 return -EINVAL;
1060 }
1061
1062 xdprxss->hdcp_enable = of_property_read_bool(node, "xlnx,hdcp-enable");
1063
1064 if (xdprxss->hdcp_enable) {
1065 dev_err(xdprxss->dev, "hdcp unsupported\n");
1066 return -EINVAL;
1067 }
1068
1069 xdprxss->audio_enable = of_property_read_bool(node,
1070 "xlnx,audio-enable");
1071
1072 if (xdprxss->audio_enable) {
1073 dev_err(xdprxss->dev, "audio unsupported\n");
1074 return -EINVAL;
1075 }
1076
1077 ret = of_property_read_u32(node, "xlnx,link-rate", &val);
1078 if (ret < 0) {
1079 dev_err(xdprxss->dev, "xlnx,link-rate property not found\n");
1080 return ret;
1081 }
1082 if (!(val == DP_LINK_BW_1_62 ||
1083 val == DP_LINK_BW_2_7 ||
1084 val == DP_LINK_BW_5_4 ||
1085 val == DP_LINK_BW_8_1)) {
1086 dev_err(xdprxss->dev, "invalid link rate\n");
1087 return -EINVAL;
1088 }
1089 xdprxss->max_linkrate = val;
1090
1091 ret = of_property_read_u32(node, "xlnx,lane-count", &val);
1092 if (ret < 0) {
1093 dev_err(xdprxss->dev, "xlnx,lane-count property not found\n");
1094 return ret;
1095 }
1096 if (val < 1 && val > 4) {
1097 dev_err(xdprxss->dev, "invalid lane count\n");
1098 return -EINVAL;
1099 }
1100 xdprxss->max_lanecount = val;
1101
1102 ret = of_property_read_u32(node, "xlnx,mode", &val);
1103 if (ret < 0) {
1104 dev_err(xdprxss->dev, "xlnx,mode property not found\n");
1105 return ret;
1106 }
1107 if (val > 0) {
1108 dev_err(xdprxss->dev, "driver does't support MST mode\n");
1109 return -EINVAL;
1110 }
1111
1112 return 0;
1113}
1114
1115static int xdprxss_probe(struct platform_device *pdev)
1116{
1117 struct v4l2_subdev *subdev;
1118 struct xdprxss_state *xdprxss;
1119 struct device_node *node;
1120 struct device *dev = &pdev->dev;
1121 struct resource *res;
1122 int ret, irq;
1123 unsigned int i = 0, j;
1124
1125 xdprxss = devm_kzalloc(dev, sizeof(*xdprxss), GFP_KERNEL);
1126 if (!xdprxss)
1127 return -ENOMEM;
1128
1129 xdprxss->dev = &pdev->dev;
1130 node = xdprxss->dev->of_node;
1131
1132 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp_base");
1133 xdprxss->dp_base = devm_ioremap_resource(dev, res);
1134 if (IS_ERR(xdprxss->dp_base)) {
1135 dev_err(dev, "couldn't map DisplayPort registers\n");
1136 return -ENODEV;
1137 }
1138
1139 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "edid_base");
1140 xdprxss->edid_base = devm_ioremap_resource(dev, res);
1141 if (IS_ERR(xdprxss->edid_base)) {
1142 dev_err(dev, "Couldn't map EDID IP memory\n");
1143 return -ENOENT;
1144 }
1145
1146 xdprxss->axi_clk = devm_clk_get(dev, "s_axi_aclk");
1147 if (IS_ERR(xdprxss->axi_clk)) {
1148 ret = PTR_ERR(xdprxss->axi_clk);
1149 dev_err(&pdev->dev, "failed to get s_axi_clk (%d)\n", ret);
1150 return ret;
1151 }
1152
1153 xdprxss->rx_lnk_clk = devm_clk_get(dev, "rx_lnk_clk");
1154 if (IS_ERR(xdprxss->rx_lnk_clk)) {
1155 ret = PTR_ERR(xdprxss->rx_lnk_clk);
1156 dev_err(&pdev->dev, "failed to get rx_lnk_clk (%d)\n", ret);
1157 return ret;
1158 }
1159
1160 xdprxss->rx_vid_clk = devm_clk_get(dev, "rx_vid_clk");
1161 if (IS_ERR(xdprxss->rx_vid_clk)) {
1162 ret = PTR_ERR(xdprxss->rx_vid_clk);
1163 dev_err(&pdev->dev, "failed to get rx_vid_clk (%d)\n", ret);
1164 return ret;
1165 }
1166
1167 ret = xdprxss_parse_of(xdprxss);
1168 if (ret < 0)
1169 goto clk_err;
1170
1171
1172 for (i = 0; i < xdprxss->max_lanecount; i++) {
1173 char phy_name[16];
1174
1175 snprintf(phy_name, sizeof(phy_name), "dp-phy%d", i);
1176 xdprxss->phy[i] = devm_phy_get(xdprxss->dev, phy_name);
1177 if (IS_ERR(xdprxss->phy[i])) {
1178 ret = PTR_ERR(xdprxss->phy[i]);
1179 xdprxss->phy[i] = NULL;
1180 if (ret == -EPROBE_DEFER)
1181 dev_info(dev, "phy not ready -EPROBE_DEFER\n");
1182 if (ret != -EPROBE_DEFER)
1183 dev_err(dev,
1184 "failed to get phy lane %s i %d\n",
1185 phy_name, i);
1186 goto error_phy;
1187 }
1188 ret = phy_init(xdprxss->phy[i]);
1189 if (ret) {
1190 dev_err(dev,
1191 "failed to init phy lane %d\n", i);
1192 goto error_phy;
1193 }
1194 }
1195
1196 ret = clk_prepare_enable(xdprxss->axi_clk);
1197 if (ret) {
1198 dev_err(dev, "failed to enable axi_clk (%d)\n", ret);
1199 goto error_phy;
1200 }
1201
1202 ret = clk_prepare_enable(xdprxss->rx_lnk_clk);
1203 if (ret) {
1204 dev_err(dev, "failed to enable rx_lnk_clk (%d)\n", ret);
1205 goto rx_lnk_clk_err;
1206 }
1207
1208 ret = clk_prepare_enable(xdprxss->rx_vid_clk);
1209 if (ret) {
1210 dev_err(dev, "failed to enable rx_vid_clk (%d)\n", ret);
1211 goto rx_vid_clk_err;
1212 }
1213
1214 spin_lock_init(&xdprxss->lock);
1215
1216
1217 xdprxss_core_init(xdprxss);
1218
1219
1220 xdprxss->pad.flags = MEDIA_PAD_FL_SOURCE;
1221
1222
1223 subdev = &xdprxss->subdev;
1224 v4l2_subdev_init(subdev, &xdprxss_ops);
1225 subdev->dev = &pdev->dev;
1226 strscpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
1227
1228 subdev->flags = V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
1229
1230 subdev->entity.ops = &xdprxss_media_ops;
1231
1232 v4l2_set_subdevdata(subdev, xdprxss);
1233 ret = media_entity_pads_init(&subdev->entity, 1, &xdprxss->pad);
1234 if (ret < 0)
1235 goto error;
1236
1237
1238 irq = irq_of_parse_and_map(node, 0);
1239 ret = devm_request_irq(xdprxss->dev, irq, xdprxss_irq_handler,
1240 IRQF_SHARED, subdev->name, xdprxss);
1241 if (ret) {
1242 dev_err(dev, "Err = %d Interrupt handler reg failed!\n",
1243 ret);
1244 goto error;
1245 }
1246
1247 platform_set_drvdata(pdev, xdprxss);
1248
1249 ret = v4l2_async_register_subdev(subdev);
1250 if (ret < 0) {
1251 dev_err(dev, "failed to register subdev\n");
1252 goto error;
1253 }
1254
1255 return 0;
1256
1257error:
1258 media_entity_cleanup(&subdev->entity);
1259clk_err:
1260 clk_disable_unprepare(xdprxss->rx_vid_clk);
1261rx_vid_clk_err:
1262 clk_disable_unprepare(xdprxss->rx_lnk_clk);
1263rx_lnk_clk_err:
1264 clk_disable_unprepare(xdprxss->axi_clk);
1265error_phy:
1266 dev_dbg(dev, " %s error_phy:\n", __func__);
1267
1268 for (j = 0; j < i; j++) {
1269 if (xdprxss->phy[j]) {
1270 dev_dbg(dev,
1271 "phy_exit() xdprxss->phy[%d] = %p\n",
1272 j, xdprxss->phy[j]);
1273 phy_exit(xdprxss->phy[j]);
1274 xdprxss->phy[j] = NULL;
1275 }
1276 }
1277
1278 return ret;
1279}
1280
1281static int xdprxss_remove(struct platform_device *pdev)
1282{
1283 struct xdprxss_state *xdprxss = platform_get_drvdata(pdev);
1284 struct v4l2_subdev *subdev = &xdprxss->subdev;
1285 unsigned int i;
1286
1287 v4l2_async_unregister_subdev(subdev);
1288 media_entity_cleanup(&subdev->entity);
1289 clk_disable_unprepare(xdprxss->rx_vid_clk);
1290 clk_disable_unprepare(xdprxss->rx_lnk_clk);
1291 clk_disable_unprepare(xdprxss->axi_clk);
1292 for (i = 0; i < XDPRX_MAX_LANE_COUNT; i++) {
1293 phy_exit(xdprxss->phy[i]);
1294 xdprxss->phy[i] = NULL;
1295 }
1296 return 0;
1297}
1298
1299static const struct of_device_id xdprxss_of_id_table[] = {
1300 { .compatible = "xlnx,v-dp-rxss-3.0", },
1301 { }
1302};
1303MODULE_DEVICE_TABLE(of, xdprxss_of_id_table);
1304
1305static struct platform_driver xdprxss_driver = {
1306 .driver = {
1307 .name = "xilinx-dprxss",
1308 .of_match_table = xdprxss_of_id_table,
1309 },
1310 .probe = xdprxss_probe,
1311 .remove = xdprxss_remove,
1312};
1313
1314module_platform_driver(xdprxss_driver);
1315
1316MODULE_AUTHOR("Rajesh Gugulothu <gugulothu.rajesh@xilinx.com");
1317MODULE_DESCRIPTION("Xilinx DP Rx Subsystem Driver");
1318MODULE_LICENSE("GPL v2");
1319