2 * Copyright (c) 2017 Rockchip Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/clk.h>
15 #include <linux/delay.h>
16 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/phy/phy.h>
21 #include <linux/platform_device.h>
22 #include <linux/regmap.h>
24 #include <drm/drm_mipi_dsi.h>
26 #include <video/mipi_display.h>
27 #include <video/of_videomode.h>
28 #include <video/videomode.h>
30 #define DRV_NAME "inno-mipi-dphy"
32 #define INNO_PHY_LANE_CTRL 0x00000
33 #define INNO_PHY_POWER_CTRL 0x00004
34 #define INNO_PHY_PLL_CTRL_0 0x0000c
35 #define INNO_PHY_PLL_CTRL_1 0x00010
36 #define INNO_PHY_DIG_CTRL 0x00080
37 #define INNO_PHY_PIN_CTRL 0x00084
39 #define INNO_CLOCK_LANE_REG_BASE 0x00100
40 #define INNO_DATA_LANE_0_REG_BASE 0x00180
41 #define INNO_DATA_LANE_1_REG_BASE 0x00200
42 #define INNO_DATA_LANE_2_REG_BASE 0x00280
43 #define INNO_DATA_LANE_3_REG_BASE 0x00300
45 #define T_LPX_OFFSET 0x00014
46 #define T_HS_PREPARE_OFFSET 0x00018
47 #define T_HS_ZERO_OFFSET 0x0001c
48 #define T_HS_TRAIL_OFFSET 0x00020
49 #define T_HS_EXIT_OFFSET 0x00024
50 #define T_CLK_POST_OFFSET 0x00028
51 #define T_WAKUP_H_OFFSET 0x00030
52 #define T_WAKUP_L_OFFSET 0x00034
53 #define T_CLK_PRE_OFFSET 0x00038
54 #define T_TA_GO_OFFSET 0x00040
55 #define T_TA_SURE_OFFSET 0x00044
56 #define T_TA_WAIT_OFFSET 0x00048
58 /* INNO_PHY_LANE_CTRL */
59 #define M_CLK_LANE_EN BIT(6)
60 #define M_DATA_LANE_3_EN BIT(5)
61 #define M_DATA_LANE_2_EN BIT(4)
62 #define M_DATA_LANE_1_EN BIT(3)
63 #define M_DATA_LANE_0_EN BIT(2)
64 #define V_CLK_LANE_EN BIT(6)
65 #define V_DATA_LANE_3_EN BIT(5)
66 #define V_DATA_LANE_2_EN BIT(4)
67 #define V_DATA_LANE_1_EN BIT(3)
68 #define V_DATA_LANE_0_EN BIT(2)
69 /* INNO_PHY_PLL_CTRL_0 */
70 #define M_FBDIV_8 BIT(5)
71 #define M_PREDIV (0x1f << 0)
72 #define V_FBDIV_8(x) ((x) << 5)
73 #define V_PREDIV(x) ((x) << 0)
74 /* INNO_PHY_PLL_CTRL_1 */
75 #define M_FBDIV_7_0 (0xff << 0)
76 #define V_FBDIV_7_0(x) ((x) << 0)
78 #define M_T_LPX (0x3f << 0)
79 #define V_T_LPX(x) ((x) << 0)
80 #define M_T_HS_PREPARE (0x7f << 0)
81 #define V_T_HS_PREPARE(x) ((x) << 0)
82 #define M_T_HS_ZERO (0x3f << 0)
83 #define V_T_HS_ZERO(x) ((x) << 0)
84 #define M_T_HS_TRAIL (0x7f << 0)
85 #define V_T_HS_TRAIL(x) ((x) << 0)
86 #define M_T_HS_EXIT (0x1f << 0)
87 #define V_T_HS_EXIT(x) ((x) << 0)
88 #define M_T_CLK_POST (0xf << 0)
89 #define V_T_CLK_POST(x) ((x) << 0)
90 #define M_T_WAKUP_H (0x3 << 0)
91 #define V_T_WAKUP_H(x) ((x) << 0)
92 #define M_T_WAKUP_L (0xff << 0)
93 #define V_T_WAKUP_L(x) ((x) << 0)
94 #define M_T_CLK_PRE (0xf << 0)
95 #define V_T_CLK_PRE(x) ((x) << 0)
96 #define M_T_TA_GO (0x3f << 0)
97 #define V_T_TA_GO(x) ((x) << 0)
98 #define M_T_TA_SURE (0x3f << 0)
99 #define V_T_TA_SURE(x) ((x) << 0)
100 #define M_T_TA_WAIT (0x3f << 0)
101 #define V_T_TA_WAIT(x) ((x) << 0)
111 static const u32 lane_reg_offset[] = {
112 [CLOCK_LANE] = INNO_CLOCK_LANE_REG_BASE,
113 [DATA_LANE_0] = INNO_DATA_LANE_0_REG_BASE,
114 [DATA_LANE_1] = INNO_DATA_LANE_1_REG_BASE,
115 [DATA_LANE_2] = INNO_DATA_LANE_2_REG_BASE,
116 [DATA_LANE_3] = INNO_DATA_LANE_3_REG_BASE,
120 HS_CLK_RANGE_80_110_MHZ,
121 HS_CLK_RANGE_110_150_MHZ,
122 HS_CLK_RANGE_150_200_MHZ,
123 HS_CLK_RANGE_200_250_MHZ,
124 HS_CLK_RANGE_250_300_MHZ,
125 HS_CLK_RANGE_300_400_MHZ,
126 HS_CLK_RANGE_400_500_MHZ,
127 HS_CLK_RANGE_500_600_MHZ,
128 HS_CLK_RANGE_600_700_MHZ,
129 HS_CLK_RANGE_700_800_MHZ,
130 HS_CLK_RANGE_800_1000_MHZ,
133 static const u8 t_hs_prepare_val[] = {
134 [HS_CLK_RANGE_80_110_MHZ] = 0x20,
135 [HS_CLK_RANGE_110_150_MHZ] = 0x06,
136 [HS_CLK_RANGE_150_200_MHZ] = 0x18,
137 [HS_CLK_RANGE_200_250_MHZ] = 0x05,
138 [HS_CLK_RANGE_250_300_MHZ] = 0x51,
139 [HS_CLK_RANGE_300_400_MHZ] = 0x64,
140 [HS_CLK_RANGE_400_500_MHZ] = 0x20,
141 [HS_CLK_RANGE_500_600_MHZ] = 0x6a,
142 [HS_CLK_RANGE_600_700_MHZ] = 0x3e,
143 [HS_CLK_RANGE_700_800_MHZ] = 0x21,
144 [HS_CLK_RANGE_800_1000_MHZ] = 0x09,
147 static const u8 clock_lane_t_hs_zero_val[] = {
148 [HS_CLK_RANGE_80_110_MHZ] = 0x16,
149 [HS_CLK_RANGE_110_150_MHZ] = 0x16,
150 [HS_CLK_RANGE_150_200_MHZ] = 0x17,
151 [HS_CLK_RANGE_200_250_MHZ] = 0x17,
152 [HS_CLK_RANGE_250_300_MHZ] = 0x18,
153 [HS_CLK_RANGE_300_400_MHZ] = 0x19,
154 [HS_CLK_RANGE_400_500_MHZ] = 0x1b,
155 [HS_CLK_RANGE_500_600_MHZ] = 0x1d,
156 [HS_CLK_RANGE_600_700_MHZ] = 0x1e,
157 [HS_CLK_RANGE_700_800_MHZ] = 0x1f,
158 [HS_CLK_RANGE_800_1000_MHZ] = 0x20,
161 static const u8 data_lane_t_hs_zero_val[] = {
162 [HS_CLK_RANGE_80_110_MHZ] = 2,
163 [HS_CLK_RANGE_110_150_MHZ] = 3,
164 [HS_CLK_RANGE_150_200_MHZ] = 4,
165 [HS_CLK_RANGE_200_250_MHZ] = 5,
166 [HS_CLK_RANGE_250_300_MHZ] = 6,
167 [HS_CLK_RANGE_300_400_MHZ] = 7,
168 [HS_CLK_RANGE_400_500_MHZ] = 7,
169 [HS_CLK_RANGE_500_600_MHZ] = 8,
170 [HS_CLK_RANGE_600_700_MHZ] = 8,
171 [HS_CLK_RANGE_700_800_MHZ] = 9,
172 [HS_CLK_RANGE_800_1000_MHZ] = 9,
175 static const u8 t_hs_trail_val[] = {
176 [HS_CLK_RANGE_80_110_MHZ] = 0x22,
177 [HS_CLK_RANGE_110_150_MHZ] = 0x45,
178 [HS_CLK_RANGE_150_200_MHZ] = 0x0b,
179 [HS_CLK_RANGE_200_250_MHZ] = 0x16,
180 [HS_CLK_RANGE_250_300_MHZ] = 0x2c,
181 [HS_CLK_RANGE_300_400_MHZ] = 0x33,
182 [HS_CLK_RANGE_400_500_MHZ] = 0x4e,
183 [HS_CLK_RANGE_500_600_MHZ] = 0x3a,
184 [HS_CLK_RANGE_600_700_MHZ] = 0x6a,
185 [HS_CLK_RANGE_700_800_MHZ] = 0x29,
186 [HS_CLK_RANGE_800_1000_MHZ] = 0x27,
189 struct mipi_dphy_timing {
190 unsigned int clkmiss;
191 unsigned int clkpost;
193 unsigned int clkprepare;
194 unsigned int clksettle;
195 unsigned int clktermen;
196 unsigned int clktrail;
197 unsigned int clkzero;
198 unsigned int dtermen;
201 unsigned int hsprepare;
203 unsigned int hssettle;
205 unsigned int hstrail;
214 struct inno_mipi_dphy_timing {
234 struct inno_mipi_dphy {
240 struct dsi_panel *panel;
245 static inline void inno_write(struct inno_mipi_dphy *inno, u32 reg, u32 val)
247 writel_relaxed(val, inno->regs + reg);
250 static inline u32 inno_read(struct inno_mipi_dphy *inno, u32 reg)
252 return readl_relaxed(inno->regs + reg);
255 static inline void inno_update_bits(struct inno_mipi_dphy *inno, u32 reg,
260 orig = inno_read(inno, reg);
263 inno_write(inno, reg, tmp);
266 static void mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
267 unsigned long period)
269 /* Global Operation Timing Parameters */
271 timing->clkpost = 70000 + 52 * period;
272 timing->clkpre = 8000;
273 timing->clkprepare = 65000;
274 timing->clksettle = 95000;
275 timing->clktermen = 0;
276 timing->clktrail = 80000;
277 timing->clkzero = 260000;
280 timing->hsexit = 120000;
281 timing->hsprepare = 65000 + 5 * period;
282 timing->hszero = 145000 + 5 * period;
283 timing->hssettle = 85000 + 6 * period;
284 timing->hsskip = 40000;
285 timing->hstrail = max(4 * 8 * period, 60000 + 4 * 4 * period);
286 timing->init = 100000000;
288 timing->taget = 5 * timing->lpx;
289 timing->tago = 4 * timing->lpx;
290 timing->tasure = timing->lpx;
291 timing->wakeup = 1000000000;
294 static u32 fre_to_period(u32 fre)
299 integer = 1000000000UL / fre;
300 decimals = 1000000000UL % fre;
301 if (decimals <= 40000000)
302 decimals = (decimals * 100) / (fre / 10);
303 else if (decimals <= 400000000)
304 decimals = (decimals * 10) / (fre / 100);
306 decimals = decimals / (fre / 1000);
307 integer = integer * 1000 + decimals;
312 static void inno_mipi_dphy_timing_update(struct inno_mipi_dphy *inno,
313 enum lane_type lane_type,
314 struct inno_mipi_dphy_timing *t)
316 u32 base = lane_reg_offset[lane_type];
319 mask = M_T_HS_PREPARE;
320 val = V_T_HS_PREPARE(t->t_hs_prepare);
321 inno_update_bits(inno, base + T_HS_PREPARE_OFFSET, mask, val);
324 val = V_T_HS_ZERO(t->t_hs_zero);
325 inno_update_bits(inno, base + T_HS_ZERO_OFFSET, mask, val);
328 val = V_T_HS_TRAIL(t->t_hs_trail);
329 inno_update_bits(inno, base + T_HS_TRAIL_OFFSET, mask, val);
332 val = V_T_HS_EXIT(t->t_hs_exit);
333 inno_update_bits(inno, base + T_HS_EXIT_OFFSET, mask, val);
335 if (lane_type == CLOCK_LANE) {
337 val = V_T_CLK_POST(t->t_clk_post);
338 inno_update_bits(inno, base + T_CLK_POST_OFFSET, mask, val);
341 val = V_T_CLK_PRE(t->t_clk_pre);
342 inno_update_bits(inno, base + T_CLK_PRE_OFFSET, mask, val);
346 val = V_T_WAKUP_H(t->t_wakup_h);
347 inno_update_bits(inno, base + T_WAKUP_H_OFFSET, mask, val);
350 val = V_T_WAKUP_L(t->t_wakup_l);
351 inno_update_bits(inno, base + T_WAKUP_L_OFFSET, mask, val);
354 val = V_T_LPX(t->t_lpx);
355 inno_update_bits(inno, base + T_LPX_OFFSET, mask, val);
358 val = V_T_TA_GO(t->t_ta_go);
359 inno_update_bits(inno, base + T_TA_GO_OFFSET, mask, val);
362 val = V_T_TA_SURE(t->t_ta_sure);
363 inno_update_bits(inno, base + T_TA_SURE_OFFSET, mask, val);
366 val = V_T_TA_WAIT(t->t_ta_wait);
367 inno_update_bits(inno, base + T_TA_WAIT_OFFSET, mask, val);
370 static enum hs_clk_range inno_mipi_dphy_get_hs_clk_range(u32 lane_rate)
372 u32 range = lane_rate / USEC_PER_SEC;
375 return HS_CLK_RANGE_80_110_MHZ;
376 else if (range < 150)
377 return HS_CLK_RANGE_110_150_MHZ;
378 else if (range < 200)
379 return HS_CLK_RANGE_150_200_MHZ;
380 else if (range < 250)
381 return HS_CLK_RANGE_200_250_MHZ;
382 else if (range < 300)
383 return HS_CLK_RANGE_250_300_MHZ;
384 else if (range < 400)
385 return HS_CLK_RANGE_400_500_MHZ;
386 else if (range < 500)
387 return HS_CLK_RANGE_400_500_MHZ;
388 else if (range < 600)
389 return HS_CLK_RANGE_500_600_MHZ;
390 else if (range < 700)
391 return HS_CLK_RANGE_600_700_MHZ;
392 else if (range < 800)
393 return HS_CLK_RANGE_700_800_MHZ;
395 return HS_CLK_RANGE_800_1000_MHZ;
398 static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno,
399 enum lane_type lane_type)
401 struct mipi_dphy_timing timing;
402 struct inno_mipi_dphy_timing data;
403 u32 txbyteclkhs = inno->lane_mbps * USEC_PER_SEC / 8;
404 u32 txclkesc = 20000000;
405 u32 UI = fre_to_period(inno->lane_mbps * USEC_PER_SEC);
407 enum hs_clk_range range;
409 memset(&timing, 0, sizeof(timing));
410 memset(&data, 0, sizeof(data));
412 mipi_dphy_timing_get_default(&timing, UI);
414 range = inno_mipi_dphy_get_hs_clk_range(inno->lane_mbps * USEC_PER_SEC);
416 if (lane_type == CLOCK_LANE)
417 data.t_hs_zero = clock_lane_t_hs_zero_val[range];
419 data.t_hs_zero = data_lane_t_hs_zero_val[range];
421 data.t_hs_prepare = t_hs_prepare_val[range];
422 data.t_hs_trail = t_hs_trail_val[range];
424 /* txbyteclkhs domain */
425 unit = fre_to_period(txbyteclkhs);
426 data.t_hs_exit = DIV_ROUND_UP(timing.hsexit, unit);
427 data.t_clk_post = DIV_ROUND_UP(timing.clkpost, unit);
428 data.t_clk_pre = DIV_ROUND_UP(timing.clkpre, unit);
429 data.t_wakup_h = 0x3;
430 data.t_wakup_l = 0xff;
431 data.t_lpx = DIV_ROUND_UP(timing.lpx, unit) - 2;
433 /* txclkesc domain */
434 unit = fre_to_period(txclkesc);
435 data.t_ta_go = DIV_ROUND_UP(timing.tago, unit);
436 data.t_ta_sure = DIV_ROUND_UP(timing.tasure, unit);
437 data.t_ta_wait = DIV_ROUND_UP(timing.taget, unit);
439 inno_mipi_dphy_timing_update(inno, lane_type, &data);
442 static void inno_mipi_dphy_pll_init(struct inno_mipi_dphy *inno)
444 struct dsi_panel *panel = inno->panel;
446 unsigned long mpclk, pllref, tmp;
447 unsigned int target_mbps = 1000;
448 unsigned int max_mbps = 1000;
449 u32 fbdiv = 1, prediv = 1;
452 mpclk = DIV_ROUND_UP(panel->vm.pixelclock, USEC_PER_SEC);
454 /* take 1 / 0.9, since mbps must big than bandwidth of RGB */
455 tmp = mpclk * (panel->bpp / inno->lanes) * 10 / 9;
459 dev_err(inno->dev, "DPHY clock frequency is out of range\n");
462 pllref = DIV_ROUND_UP(clk_get_rate(inno->ref_clk) / 2, USEC_PER_SEC);
465 for (i = 1; i < 6; i++) {
467 if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) {
468 tmp = target_mbps % pre;
470 fbdiv = target_mbps / pre;
476 inno->lane_mbps = pllref / prediv * fbdiv;
478 mask = M_FBDIV_8 | M_PREDIV;
479 val = V_FBDIV_8(fbdiv >> 8) | V_PREDIV(prediv);
480 inno_update_bits(inno, INNO_PHY_PLL_CTRL_0, mask, val);
483 val = V_FBDIV_7_0(fbdiv);
484 inno_update_bits(inno, INNO_PHY_PLL_CTRL_1, mask, val);
486 dev_info(inno->dev, "fin=%ld, fout=%d, prediv=%d, fbdiv=%d\n",
487 pllref, inno->lane_mbps, prediv, fbdiv);
490 static void inno_mipi_dphy_reset(struct inno_mipi_dphy *inno)
493 inno_write(inno, INNO_PHY_POWER_CTRL, 0xe0);
496 inno_write(inno, INNO_PHY_DIG_CTRL, 0x1e);
498 inno_write(inno, INNO_PHY_DIG_CTRL, 0x1f);
502 static void inno_mipi_dphy_timing_init(struct inno_mipi_dphy *inno)
504 switch (inno->lanes) {
506 inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_3);
509 inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_2);
512 inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_1);
516 inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_0);
517 inno_mipi_dphy_lane_timing_init(inno, CLOCK_LANE);
522 static inline void inno_mipi_dphy_lane_enable(struct inno_mipi_dphy *inno)
527 switch (inno->lanes) {
529 mask |= M_DATA_LANE_3_EN;
530 val |= V_DATA_LANE_3_EN;
533 mask |= M_DATA_LANE_2_EN;
534 val |= V_DATA_LANE_2_EN;
537 mask |= M_DATA_LANE_1_EN;
538 val |= V_DATA_LANE_1_EN;
542 mask |= M_DATA_LANE_0_EN | M_CLK_LANE_EN;
543 val |= V_DATA_LANE_0_EN | V_CLK_LANE_EN;
547 inno_update_bits(inno, INNO_PHY_LANE_CTRL, mask, val);
550 static inline void inno_mipi_dphy_pll_ldo_enable(struct inno_mipi_dphy *inno)
552 inno_write(inno, INNO_PHY_POWER_CTRL, 0xe4);
556 static int inno_mipi_dphy_power_on(struct phy *phy)
558 struct inno_mipi_dphy *inno = phy_get_drvdata(phy);
560 clk_prepare_enable(inno->ref_clk);
561 clk_prepare_enable(inno->pclk);
563 inno_mipi_dphy_pll_init(inno);
564 inno_mipi_dphy_pll_ldo_enable(inno);
565 inno_mipi_dphy_lane_enable(inno);
566 inno_mipi_dphy_reset(inno);
567 inno_mipi_dphy_timing_init(inno);
569 dev_info(inno->dev, "Inno MIPI-DPHY Power-On\n");
574 static inline void inno_mipi_dphy_lane_disable(struct inno_mipi_dphy *inno)
576 inno_update_bits(inno, INNO_PHY_LANE_CTRL, 0x7c, 0x00);
579 static inline void inno_mipi_dphy_pll_ldo_disable(struct inno_mipi_dphy *inno)
581 inno_write(inno, INNO_PHY_POWER_CTRL, 0xe3);
585 static int inno_mipi_dphy_power_off(struct phy *phy)
587 struct inno_mipi_dphy *inno = phy_get_drvdata(phy);
589 inno_mipi_dphy_lane_disable(inno);
590 inno_mipi_dphy_pll_ldo_disable(inno);
592 clk_disable_unprepare(inno->pclk);
593 clk_disable_unprepare(inno->ref_clk);
595 dev_info(inno->dev, "Inno MIPI-DPHY Power-Off\n");
600 static const struct phy_ops inno_mipi_dphy_ops = {
601 .power_on = inno_mipi_dphy_power_on,
602 .power_off = inno_mipi_dphy_power_off,
603 .owner = THIS_MODULE,
606 static int get_bpp(struct device_node *np)
610 if (of_property_read_u32(np, "dsi,format", &format))
614 case MIPI_DSI_FMT_RGB666_PACKED:
616 case MIPI_DSI_FMT_RGB565:
618 case MIPI_DSI_FMT_RGB888:
619 case MIPI_DSI_FMT_RGB666:
625 static int inno_mipi_dphy_parse_dt(struct device_node *np,
626 struct inno_mipi_dphy *inno)
628 struct device_node *panel_node;
629 struct dsi_panel *panel;
632 panel_node = of_parse_phandle(np, "rockchip,dsi-panel", 0);
634 dev_err(inno->dev, "Missing 'rockchip,dsi-panel' property");
638 panel = devm_kzalloc(inno->dev, sizeof(*panel), GFP_KERNEL);
644 ret = of_get_videomode(panel_node, &panel->vm, 0);
648 panel->bpp = get_bpp(panel_node);
650 if (of_property_read_u32(panel_node, "dsi,lanes", &inno->lanes))
653 of_node_put(panel_node);
660 of_node_put(panel_node);
664 static int inno_mipi_dphy_probe(struct platform_device *pdev)
666 struct device_node *np = pdev->dev.of_node;
667 struct inno_mipi_dphy *inno;
669 struct phy_provider *phy_provider;
670 struct resource *res;
673 inno = devm_kzalloc(&pdev->dev, sizeof(*inno), GFP_KERNEL);
677 inno->dev = &pdev->dev;
679 ret = inno_mipi_dphy_parse_dt(np, inno);
681 dev_err(&pdev->dev, "failed to parse DT\n");
685 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
686 inno->regs = devm_ioremap_resource(&pdev->dev, res);
687 if (IS_ERR(inno->regs))
688 return PTR_ERR(inno->regs);
690 inno->ref_clk = devm_clk_get(&pdev->dev, "ref");
691 if (IS_ERR(inno->ref_clk)) {
692 dev_err(&pdev->dev, "failed to get mipi dphy ref clk\n");
693 return PTR_ERR(inno->ref_clk);
696 inno->pclk = devm_clk_get(&pdev->dev, "pclk");
697 if (IS_ERR(inno->pclk)) {
698 dev_err(&pdev->dev, "failed to get mipi dphy pclk\n");
699 return PTR_ERR(inno->pclk);
702 phy = devm_phy_create(&pdev->dev, NULL, &inno_mipi_dphy_ops);
704 dev_err(&pdev->dev, "failed to create MIPI D-PHY\n");
708 phy_set_drvdata(phy, inno);
710 phy_provider = devm_of_phy_provider_register(&pdev->dev,
711 of_phy_simple_xlate);
712 if (IS_ERR(phy_provider)) {
713 dev_err(&pdev->dev, "failed to register phy provider\n");
714 return PTR_ERR(phy_provider);
717 dev_info(&pdev->dev, "Inno MIPI-DPHY Driver Probe\n");
722 static const struct of_device_id inno_mipi_dphy_of_match[] = {
723 { .compatible = "rockchip,rk3368-mipi-dphy", },
726 MODULE_DEVICE_TABLE(of, inno_mipi_dphy_of_match);
728 static struct platform_driver inno_mipi_dphy_driver = {
729 .probe = inno_mipi_dphy_probe,
732 .of_match_table = inno_mipi_dphy_of_match,
736 module_platform_driver(inno_mipi_dphy_driver);
738 MODULE_DESCRIPTION("Innosilicon MIPI D-PHY Driver");
739 MODULE_LICENSE("GPL v2");