dc96d95b533f9b7aeed03f2ecda492086677cddc
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / rockchip / dw_hdmi-rockchip.c
1 /*
2  * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  */
9
10 #include <linux/clk.h>
11 #include <linux/clk-provider.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/rockchip/cpu.h>
16 #include <linux/regmap.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/phy/phy.h>
19
20 #include <drm/drm_of.h>
21 #include <drm/drmP.h>
22 #include <drm/drm_crtc_helper.h>
23 #include <drm/drm_edid.h>
24 #include <drm/drm_encoder_slave.h>
25 #include <drm/bridge/dw_hdmi.h>
26
27 #include "rockchip_drm_drv.h"
28 #include "rockchip_drm_vop.h"
29
30 #define RK3228_GRF_SOC_CON2             0x0408
31 #define RK3228_DDC_MASK_EN              ((3 << 13) | (3 << (13 + 16)))
32 #define RK3228_GRF_SOC_CON6             0x0418
33 #define RK3228_IO_3V_DOMAIN             ((7 << 4) | (7 << (4 + 16)))
34
35 #define RK3288_GRF_SOC_CON6             0x025C
36 #define RK3288_HDMI_LCDC_SEL            BIT(4)
37 #define RK3366_GRF_SOC_CON0             0x0400
38 #define RK3366_HDMI_LCDC_SEL            BIT(1)
39 #define RK3399_GRF_SOC_CON20            0x6250
40 #define RK3399_HDMI_LCDC_SEL            BIT(6)
41
42 #define RK3328_GRF_SOC_CON2             0x0408
43 #define RK3328_DDC_MASK_EN              ((3 << 10) | (3 << (10 + 16)))
44 #define RK3328_GRF_SOC_CON3             0x040c
45 #define RK3328_IO_CTRL_BY_HDMI          (0xf0000000 | BIT(13) | BIT(12))
46 #define RK3328_GRF_SOC_CON4             0x0410
47 #define RK3328_IO_3V_DOMAIN             (7 << (9 + 16))
48 #define RK3328_IO_5V_DOMAIN             ((7 << 9) | (3 << (9 + 16)))
49 #define RK3328_HPD_3V                   (BIT(8 + 16) | BIT(13 + 16))
50
51 #define HIWORD_UPDATE(val, mask)        (val | (mask) << 16)
52
53 struct rockchip_hdmi {
54         struct device *dev;
55         struct regmap *regmap;
56         void __iomem *hdmiphy;
57         struct drm_encoder encoder;
58         enum dw_hdmi_devtype dev_type;
59         struct clk *vpll_clk;
60         struct clk *grf_clk;
61         struct clk *hclk_vio;
62         struct clk *dclk;
63
64         struct phy *phy;
65 };
66
67 #define to_rockchip_hdmi(x)     container_of(x, struct rockchip_hdmi, x)
68
69 static int
70 inno_dw_hdmi_phy_init(struct dw_hdmi *dw_hdmi, void *data,
71                       struct drm_display_mode *mode)
72 {
73         struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
74
75         return phy_power_on(hdmi->phy);
76 }
77
78 static void inno_dw_hdmi_phy_disable(struct dw_hdmi *dw_hdmi, void *data)
79 {
80         struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
81
82         phy_power_off(hdmi->phy);
83 }
84
85 static enum drm_connector_status
86 inno_dw_hdmi_phy_read_hpd(struct dw_hdmi *dw_hdmi, void *data)
87 {
88         struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
89         enum drm_connector_status status;
90
91         status = dw_hdmi_phy_read_hpd(dw_hdmi, data);
92
93         if (hdmi->dev_type == RK3228_HDMI)
94                 return status;
95
96         if (status == connector_status_connected)
97                 regmap_write(hdmi->regmap,
98                              RK3328_GRF_SOC_CON4,
99                              RK3328_IO_5V_DOMAIN);
100         else
101                 regmap_write(hdmi->regmap,
102                              RK3328_GRF_SOC_CON4,
103                              RK3328_IO_3V_DOMAIN);
104         return status;
105 }
106
107 static int inno_dw_hdmi_init(struct rockchip_hdmi *hdmi)
108 {
109         int ret;
110
111         ret = clk_prepare_enable(hdmi->grf_clk);
112         if (ret < 0) {
113                 dev_err(hdmi->dev, "failed to enable grfclk %d\n", ret);
114                 return -EPROBE_DEFER;
115         }
116         if (hdmi->dev_type == RK3328_HDMI) {
117                 /* Map HPD pin to 3V io */
118                 regmap_write(hdmi->regmap,
119                              RK3328_GRF_SOC_CON4,
120                              RK3328_IO_3V_DOMAIN |
121                              RK3328_HPD_3V);
122                 /* Map ddc pin to 5V io */
123                 regmap_write(hdmi->regmap,
124                              RK3328_GRF_SOC_CON3,
125                              RK3328_IO_CTRL_BY_HDMI);
126                 regmap_write(hdmi->regmap,
127                              RK3328_GRF_SOC_CON2,
128                              RK3328_DDC_MASK_EN |
129                              BIT(18));
130         } else {
131                 regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON2,
132                              RK3228_DDC_MASK_EN);
133                 regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON6,
134                              RK3228_IO_3V_DOMAIN);
135         }
136         clk_disable_unprepare(hdmi->grf_clk);
137         return 0;
138 }
139
140 /*
141  * There are some rates that would be ranged for better clock jitter at
142  * Chrome OS tree, like 25.175Mhz would range to 25.170732Mhz. But due
143  * to the clock is aglined to KHz in struct drm_display_mode, this would
144  * bring some inaccurate error if we still run the compute_n math, so
145  * let's just code an const table for it until we can actually get the
146  * right clock rate.
147  */
148 static const struct dw_hdmi_audio_tmds_n rockchip_werid_tmds_n_table[] = {
149         /* 25176471 for 25.175 MHz = 428000000 / 17. */
150         { .tmds = 25177000, .n_32k = 4352, .n_44k1 = 14994, .n_48k = 6528, },
151         /* 57290323 for 57.284 MHz */
152         { .tmds = 57291000, .n_32k = 3968, .n_44k1 = 4557, .n_48k = 5952, },
153         /* 74437500 for 74.44 MHz = 297750000 / 4 */
154         { .tmds = 74438000, .n_32k = 8192, .n_44k1 = 18816, .n_48k = 4096, },
155         /* 118666667 for 118.68 MHz */
156         { .tmds = 118667000, .n_32k = 4224, .n_44k1 = 5292, .n_48k = 6336, },
157         /* 121714286 for 121.75 MHz */
158         { .tmds = 121715000, .n_32k = 4480, .n_44k1 = 6174, .n_48k = 6272, },
159         /* 136800000 for 136.75 MHz */
160         { .tmds = 136800000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, },
161         /* End of table */
162         { .tmds = 0,         .n_32k = 0,    .n_44k1 = 0,    .n_48k = 0, },
163 };
164
165 static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = {
166         {
167                 30666000, {
168                         { 0x00b3, 0x0000 },
169                         { 0x2153, 0x0000 },
170                         { 0x40f3, 0x0000 },
171                 },
172         },  {
173                 36800000, {
174                         { 0x00b3, 0x0000 },
175                         { 0x2153, 0x0000 },
176                         { 0x40a2, 0x0001 },
177                 },
178         },  {
179                 46000000, {
180                         { 0x00b3, 0x0000 },
181                         { 0x2142, 0x0001 },
182                         { 0x40a2, 0x0001 },
183                 },
184         },  {
185                 61333000, {
186                         { 0x0072, 0x0001 },
187                         { 0x2142, 0x0001 },
188                         { 0x40a2, 0x0001 },
189                 },
190         },  {
191                 73600000, {
192                         { 0x0072, 0x0001 },
193                         { 0x2142, 0x0001 },
194                         { 0x4061, 0x0002 },
195                 },
196         },  {
197                 92000000, {
198                         { 0x0072, 0x0001 },
199                         { 0x2145, 0x0002 },
200                         { 0x4061, 0x0002 },
201                 },
202         },  {
203                 122666000, {
204                         { 0x0051, 0x0002 },
205                         { 0x2145, 0x0002 },
206                         { 0x4061, 0x0002 },
207                 },
208         },  {
209                 147200000, {
210                         { 0x0051, 0x0002 },
211                         { 0x2145, 0x0002 },
212                         { 0x4064, 0x0003 },
213                 },
214         },  {
215                 184000000, {
216                         { 0x0051, 0x0002 },
217                         { 0x214c, 0x0003 },
218                         { 0x4064, 0x0003 },
219                 },
220         },  {
221                 226666000, {
222                         { 0x0040, 0x0003 },
223                         { 0x214c, 0x0003 },
224                         { 0x4064, 0x0003 },
225                 },
226         },  {
227                 272000000, {
228                         { 0x0040, 0x0003 },
229                         { 0x214c, 0x0003 },
230                         { 0x5a64, 0x0003 },
231                 },
232         },  {
233                 340000000, {
234                         { 0x0040, 0x0003 },
235                         { 0x3b4c, 0x0003 },
236                         { 0x5a64, 0x0003 },
237                 },
238         },  {
239                 600000000, {
240                         { 0x1a40, 0x0003 },
241                         { 0x3b4c, 0x0003 },
242                         { 0x5a64, 0x0003 },
243                 },
244         },  {
245                 ~0UL, {
246                         { 0x0000, 0x0000 },
247                         { 0x0000, 0x0000 },
248                         { 0x0000, 0x0000 },
249                 },
250         }
251 };
252
253 static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = {
254         /*      pixelclk    bpp8    bpp10   bpp12 */
255         {
256                 600000000, { 0x0000, 0x0000, 0x0000 },
257         },  {
258                 ~0UL,      { 0x0000, 0x0000, 0x0000},
259         }
260 };
261
262 static struct dw_hdmi_phy_config rockchip_phy_config[] = {
263         /*pixelclk   symbol   term   vlev*/
264         { 74250000,  0x8009, 0x0004, 0x0272},
265         { 165000000, 0x802b, 0x0004, 0x0209},
266         { 297000000, 0x8039, 0x0005, 0x028d},
267         { 594000000, 0x8039, 0x0000, 0x019d},
268         { ~0UL,      0x0000, 0x0000, 0x0000}
269 };
270
271 static int rockchip_hdmi_update_phy_table(struct rockchip_hdmi *hdmi,
272                                           u32 *config,
273                                           int phy_table_size)
274 {
275         int i;
276
277         if (phy_table_size > ARRAY_SIZE(rockchip_phy_config)) {
278                 dev_err(hdmi->dev, "phy table array number is out of range\n");
279                 return -E2BIG;
280         }
281
282         for (i = 0; i < phy_table_size; i++) {
283                 if (config[i * 4] != 0)
284                         rockchip_phy_config[i].mpixelclock = (u64)config[i * 4];
285                 else
286                         rockchip_phy_config[i].mpixelclock = ~0UL;
287                 rockchip_phy_config[i].term = (u16)config[i * 4 + 1];
288                 rockchip_phy_config[i].sym_ctr = (u16)config[i * 4 + 2];
289                 rockchip_phy_config[i].vlev_ctr = (u16)config[i * 4 + 3];
290         }
291
292         return 0;
293 }
294
295 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
296 {
297         struct device_node *np = hdmi->dev->of_node;
298         int ret, val, phy_table_size;
299         u32 *phy_config;
300
301         hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
302         if (IS_ERR(hdmi->regmap)) {
303                 dev_err(hdmi->dev, "Unable to get rockchip,grf\n");
304                 return PTR_ERR(hdmi->regmap);
305         }
306
307         hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll");
308         if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) {
309                 hdmi->vpll_clk = NULL;
310         } else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) {
311                 return -EPROBE_DEFER;
312         } else if (IS_ERR(hdmi->vpll_clk)) {
313                 dev_err(hdmi->dev, "failed to get grf clock\n");
314                 return PTR_ERR(hdmi->vpll_clk);
315         }
316
317         hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf");
318         if (PTR_ERR(hdmi->grf_clk) == -ENOENT) {
319                 hdmi->grf_clk = NULL;
320         } else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) {
321                 return -EPROBE_DEFER;
322         } else if (IS_ERR(hdmi->grf_clk)) {
323                 dev_err(hdmi->dev, "failed to get grf clock\n");
324                 return PTR_ERR(hdmi->grf_clk);
325         }
326
327         hdmi->hclk_vio = devm_clk_get(hdmi->dev, "hclk_vio");
328         if (PTR_ERR(hdmi->hclk_vio) == -ENOENT) {
329                 hdmi->hclk_vio = NULL;
330         } else if (PTR_ERR(hdmi->hclk_vio) == -EPROBE_DEFER) {
331                 return -EPROBE_DEFER;
332         } else if (IS_ERR(hdmi->hclk_vio)) {
333                 dev_err(hdmi->dev, "failed to get hclk_vio clock\n");
334                 return PTR_ERR(hdmi->hclk_vio);
335         }
336
337         hdmi->dclk = devm_clk_get(hdmi->dev, "dclk");
338         if (PTR_ERR(hdmi->dclk) == -ENOENT) {
339                 hdmi->dclk = NULL;
340         } else if (PTR_ERR(hdmi->dclk) == -EPROBE_DEFER) {
341                 return -EPROBE_DEFER;
342         } else if (IS_ERR(hdmi->dclk)) {
343                 dev_err(hdmi->dev, "failed to get dclk\n");
344                 return PTR_ERR(hdmi->dclk);
345         }
346
347         ret = clk_prepare_enable(hdmi->vpll_clk);
348         if (ret) {
349                 dev_err(hdmi->dev, "Failed to enable HDMI vpll: %d\n", ret);
350                 return ret;
351         }
352
353         ret = clk_prepare_enable(hdmi->hclk_vio);
354         if (ret) {
355                 dev_err(hdmi->dev, "Failed to eanble HDMI hclk_vio: %d\n",
356                         ret);
357                 return ret;
358         }
359
360         if (of_get_property(np, "rockchip,phy-table", &val)) {
361                 phy_config = kmalloc(val, GFP_KERNEL);
362                 if (!phy_config) {
363                         /* use default table when kmalloc failed. */
364                         dev_err(hdmi->dev, "kmalloc phy table failed\n");
365
366                         return -ENOMEM;
367                 }
368                 phy_table_size = val / 16;
369                 of_property_read_u32_array(np, "rockchip,phy-table",
370                                            phy_config, val / sizeof(u32));
371                 ret = rockchip_hdmi_update_phy_table(hdmi, phy_config,
372                                                      phy_table_size);
373                 if (ret) {
374                         kfree(phy_config);
375                         return ret;
376                 }
377                 kfree(phy_config);
378         } else {
379                 dev_dbg(hdmi->dev, "use default hdmi phy table\n");
380         }
381
382         return 0;
383 }
384
385 static enum drm_mode_status
386 dw_hdmi_rockchip_mode_valid(struct drm_connector *connector,
387                             struct drm_display_mode *mode)
388 {
389         struct drm_encoder *encoder = connector->encoder;
390         enum drm_mode_status status = MODE_OK;
391         struct drm_device *dev = connector->dev;
392         struct rockchip_drm_private *priv = dev->dev_private;
393         struct drm_crtc *crtc;
394
395         /*
396          * Pixel clocks we support are always < 2GHz and so fit in an
397          * int.  We should make sure source rate does too so we don't get
398          * overflow when we multiply by 1000.
399          */
400         if (mode->clock > INT_MAX / 1000)
401                 return MODE_BAD;
402         /*
403          * If sink max TMDS clock < 340MHz, we should check the mode pixel
404          * clock > 340MHz is YCbCr420 or not.
405          */
406         if (mode->clock > 340000 &&
407             connector->display_info.max_tmds_clock < 340000 &&
408             !(mode->flags & DRM_MODE_FLAG_420_MASK))
409                 return MODE_BAD;
410
411         if (!encoder) {
412                 const struct drm_connector_helper_funcs *funcs;
413
414                 funcs = connector->helper_private;
415                 if (funcs->atomic_best_encoder)
416                         encoder = funcs->atomic_best_encoder(connector,
417                                                              connector->state);
418                 else
419                         encoder = funcs->best_encoder(connector);
420         }
421
422         if (!encoder || !encoder->possible_crtcs)
423                 return MODE_BAD;
424         /*
425          * ensure all drm display mode can work, if someone want support more
426          * resolutions, please limit the possible_crtc, only connect to
427          * needed crtc.
428          */
429         drm_for_each_crtc(crtc, connector->dev) {
430                 int pipe = drm_crtc_index(crtc);
431                 const struct rockchip_crtc_funcs *funcs =
432                                                 priv->crtc_funcs[pipe];
433
434                 if (!(encoder->possible_crtcs & drm_crtc_mask(crtc)))
435                         continue;
436                 if (!funcs || !funcs->mode_valid)
437                         continue;
438
439                 status = funcs->mode_valid(crtc, mode,
440                                            DRM_MODE_CONNECTOR_HDMIA);
441                 if (status != MODE_OK)
442                         return status;
443         }
444
445         return status;
446 }
447
448 static const struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = {
449         .destroy = drm_encoder_cleanup,
450 };
451
452 static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder)
453 {
454         struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
455
456         clk_disable_unprepare(hdmi->dclk);
457 }
458
459 static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
460 {
461         struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
462         struct drm_crtc *crtc = encoder->crtc;
463         u32 lcdsel_grf_reg, lcdsel_mask;
464         u32 val;
465         int mux;
466         int ret;
467
468         if (WARN_ON(!crtc || !crtc->state))
469                 return;
470
471         clk_set_rate(hdmi->vpll_clk,
472                      crtc->state->adjusted_mode.crtc_clock * 1000);
473
474         clk_set_rate(hdmi->dclk, crtc->state->adjusted_mode.crtc_clock * 1000);
475         clk_prepare_enable(hdmi->dclk);
476
477         switch (hdmi->dev_type) {
478         case RK3288_HDMI:
479                 lcdsel_grf_reg = RK3288_GRF_SOC_CON6;
480                 lcdsel_mask = RK3288_HDMI_LCDC_SEL;
481                 break;
482         case RK3366_HDMI:
483                 lcdsel_grf_reg = RK3366_GRF_SOC_CON0;
484                 lcdsel_mask = RK3366_HDMI_LCDC_SEL;
485                 break;
486         case RK3399_HDMI:
487                 lcdsel_grf_reg = RK3399_GRF_SOC_CON20;
488                 lcdsel_mask = RK3399_HDMI_LCDC_SEL;
489                 break;
490         default:
491                 return;
492         }
493
494         mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder);
495         if (mux)
496                 val = HIWORD_UPDATE(lcdsel_mask, lcdsel_mask);
497         else
498                 val = HIWORD_UPDATE(0, lcdsel_mask);
499
500         ret = clk_prepare_enable(hdmi->grf_clk);
501         if (ret < 0) {
502                 dev_err(hdmi->dev, "failed to enable grfclk %d\n", ret);
503                 return;
504         }
505
506         regmap_write(hdmi->regmap, lcdsel_grf_reg, val);
507         dev_dbg(hdmi->dev, "vop %s output to hdmi\n",
508                 (mux) ? "LIT" : "BIG");
509
510         clk_disable_unprepare(hdmi->grf_clk);
511 }
512
513 static int
514 dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
515                                       struct drm_crtc_state *crtc_state,
516                                       struct drm_connector_state *conn_state)
517 {
518         struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
519         struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
520
521         if (hdmi->phy) {
522                 if (drm_match_cea_mode(&crtc_state->mode) > 94 &&
523                     crtc_state->mode.crtc_clock > 340000 &&
524                     !(crtc_state->mode.flags & DRM_MODE_FLAG_420_MASK)) {
525                         crtc_state->mode.flags |= DRM_MODE_FLAG_420;
526                         phy_set_bus_width(hdmi->phy, 4);
527                 } else {
528                         phy_set_bus_width(hdmi->phy, 8);
529                 }
530         }
531
532         if (crtc_state->mode.flags & DRM_MODE_FLAG_420_MASK) {
533                 s->output_mode = ROCKCHIP_OUT_MODE_YUV420;
534                 s->bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
535         } else {
536                 s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
537                 s->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
538         }
539         s->output_type = DRM_MODE_CONNECTOR_HDMIA;
540
541         return 0;
542 }
543
544 static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = {
545         .enable     = dw_hdmi_rockchip_encoder_enable,
546         .disable    = dw_hdmi_rockchip_encoder_disable,
547         .atomic_check = dw_hdmi_rockchip_encoder_atomic_check,
548 };
549
550 static const struct dw_hdmi_phy_ops inno_dw_hdmi_phy_ops = {
551         .init           = inno_dw_hdmi_phy_init,
552         .disable        = inno_dw_hdmi_phy_disable,
553         .read_hpd       = inno_dw_hdmi_phy_read_hpd,
554 };
555
556 static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = {
557         .mode_valid = dw_hdmi_rockchip_mode_valid,
558         .phy_ops    = &inno_dw_hdmi_phy_ops,
559         .phy_name   = "inno_dw_hdmi_phy",
560         .dev_type   = RK3228_HDMI,
561 };
562
563 static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = {
564         .mode_valid = dw_hdmi_rockchip_mode_valid,
565         .mpll_cfg   = rockchip_mpll_cfg,
566         .cur_ctr    = rockchip_cur_ctr,
567         .phy_config = rockchip_phy_config,
568         .dev_type   = RK3288_HDMI,
569         .tmds_n_table = rockchip_werid_tmds_n_table,
570 };
571
572 static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = {
573         .mode_valid = dw_hdmi_rockchip_mode_valid,
574         .phy_ops    = &inno_dw_hdmi_phy_ops,
575         .phy_name   = "inno_dw_hdmi_phy2",
576         .dev_type   = RK3328_HDMI,
577 };
578
579 static const struct dw_hdmi_plat_data rk3366_hdmi_drv_data = {
580         .mode_valid = dw_hdmi_rockchip_mode_valid,
581         .mpll_cfg   = rockchip_mpll_cfg,
582         .cur_ctr    = rockchip_cur_ctr,
583         .phy_config = rockchip_phy_config,
584         .dev_type   = RK3366_HDMI,
585 };
586
587 static const struct dw_hdmi_plat_data rk3368_hdmi_drv_data = {
588         .mode_valid = dw_hdmi_rockchip_mode_valid,
589         .mpll_cfg   = rockchip_mpll_cfg,
590         .cur_ctr    = rockchip_cur_ctr,
591         .phy_config = rockchip_phy_config,
592         .dev_type   = RK3368_HDMI,
593 };
594
595 static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
596         .mode_valid = dw_hdmi_rockchip_mode_valid,
597         .mpll_cfg   = rockchip_mpll_cfg,
598         .cur_ctr    = rockchip_cur_ctr,
599         .phy_config = rockchip_phy_config,
600         .dev_type   = RK3399_HDMI,
601 };
602
603 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
604         { .compatible = "rockchip,rk3228-dw-hdmi",
605           .data = &rk3228_hdmi_drv_data
606         },
607         { .compatible = "rockchip,rk3288-dw-hdmi",
608           .data = &rk3288_hdmi_drv_data
609         },
610         {
611           .compatible = "rockchip,rk3328-dw-hdmi",
612           .data = &rk3328_hdmi_drv_data
613         },
614         {
615          .compatible = "rockchip,rk3366-dw-hdmi",
616          .data = &rk3366_hdmi_drv_data
617         },
618         {
619          .compatible = "rockchip,rk3368-dw-hdmi",
620          .data = &rk3368_hdmi_drv_data
621         },
622         { .compatible = "rockchip,rk3399-dw-hdmi",
623           .data = &rk3399_hdmi_drv_data
624         },
625         {},
626 };
627 MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids);
628
629 static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
630                                  void *data)
631 {
632         struct platform_device *pdev = to_platform_device(dev);
633         struct dw_hdmi_plat_data *plat_data;
634         const struct of_device_id *match;
635         struct drm_device *drm = data;
636         struct drm_encoder *encoder;
637         struct rockchip_hdmi *hdmi;
638         struct resource *iores;
639         int irq;
640         int ret;
641
642         if (!pdev->dev.of_node)
643                 return -ENODEV;
644
645         hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
646         if (!hdmi)
647                 return -ENOMEM;
648
649         match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node);
650         plat_data = (struct dw_hdmi_plat_data *)match->data;
651         hdmi->dev = &pdev->dev;
652         hdmi->dev_type = plat_data->dev_type;
653         encoder = &hdmi->encoder;
654
655         irq = platform_get_irq(pdev, 0);
656         if (irq < 0)
657                 return irq;
658
659         iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
660         if (!iores)
661                 return -ENXIO;
662
663         encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
664         /*
665          * If we failed to find the CRTC(s) which this encoder is
666          * supposed to be connected to, it's because the CRTC has
667          * not been registered yet.  Defer probing, and hope that
668          * the required CRTC is added later.
669          */
670         if (encoder->possible_crtcs == 0)
671                 return -EPROBE_DEFER;
672
673         ret = rockchip_hdmi_parse_dt(hdmi);
674         if (ret) {
675                 dev_err(hdmi->dev, "Unable to parse OF data\n");
676                 return ret;
677         }
678
679         if (hdmi->dev_type == RK3328_HDMI || hdmi->dev_type == RK3228_HDMI) {
680                 hdmi->phy = devm_phy_get(dev, "hdmi_phy");
681                 if (IS_ERR(hdmi->phy)) {
682                         ret = PTR_ERR(hdmi->phy);
683                         dev_err(dev, "failed to get phy: %d\n", ret);
684                         return ret;
685                 }
686                 plat_data->phy_data = hdmi;
687                 ret = inno_dw_hdmi_init(hdmi);
688                 if (ret < 0)
689                         return ret;
690         }
691
692         drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
693         drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
694                          DRM_MODE_ENCODER_TMDS, NULL);
695
696         ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
697
698         /*
699          * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
700          * which would have called the encoder cleanup.  Do it manually.
701          */
702         if (ret)
703                 drm_encoder_cleanup(encoder);
704
705         return ret;
706 }
707
708 static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
709                                     void *data)
710 {
711         return dw_hdmi_unbind(dev, master, data);
712 }
713
714 static const struct component_ops dw_hdmi_rockchip_ops = {
715         .bind   = dw_hdmi_rockchip_bind,
716         .unbind = dw_hdmi_rockchip_unbind,
717 };
718
719 static int dw_hdmi_rockchip_probe(struct platform_device *pdev)
720 {
721         pm_runtime_enable(&pdev->dev);
722         pm_runtime_get_sync(&pdev->dev);
723
724         return component_add(&pdev->dev, &dw_hdmi_rockchip_ops);
725 }
726
727 static int dw_hdmi_rockchip_remove(struct platform_device *pdev)
728 {
729         component_del(&pdev->dev, &dw_hdmi_rockchip_ops);
730         pm_runtime_disable(&pdev->dev);
731
732         return 0;
733 }
734
735 static int dw_hdmi_rockchip_suspend(struct device *dev)
736 {
737         dw_hdmi_suspend(dev);
738         pm_runtime_put_sync(dev);
739
740         return 0;
741 }
742
743 static int dw_hdmi_rockchip_resume(struct device *dev)
744 {
745         pm_runtime_get_sync(dev);
746         dw_hdmi_resume(dev);
747
748         return  0;
749 }
750
751 static const struct dev_pm_ops dw_hdmi_pm_ops = {
752         SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_rockchip_suspend,
753                                 dw_hdmi_rockchip_resume)
754 };
755
756 static struct platform_driver dw_hdmi_rockchip_pltfm_driver = {
757         .probe  = dw_hdmi_rockchip_probe,
758         .remove = dw_hdmi_rockchip_remove,
759         .driver = {
760                 .name = "dwhdmi-rockchip",
761                 .of_match_table = dw_hdmi_rockchip_dt_ids,
762                 .pm = &dw_hdmi_pm_ops,
763         },
764 };
765
766 module_platform_driver(dw_hdmi_rockchip_pltfm_driver);
767
768 MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
769 MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
770 MODULE_DESCRIPTION("Rockchip Specific DW-HDMI Driver Extension");
771 MODULE_LICENSE("GPL");
772 MODULE_ALIAS("platform:dwhdmi-rockchip");