video: rockchip: hdmi: sync to develop-3.10
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / rockchip-hdmiv2 / rockchip_hdmiv2.c
1 #include <linux/kernel.h>
2 #include <linux/delay.h>
3 #include <linux/module.h>
4 #include <linux/platform_device.h>
5 #include <linux/interrupt.h>
6 #include <linux/clk.h>
7 #include <linux/of_gpio.h>
8 #include <linux/rockchip/cpu.h>
9 #include <linux/rockchip/grf.h>
10 #include <linux/rockchip/iomap.h>
11 #include <linux/mfd/syscon.h>
12 #if defined(CONFIG_DEBUG_FS)
13 #include <linux/uaccess.h>
14 #include <linux/fs.h>
15 #include <linux/debugfs.h>
16 #include <linux/seq_file.h>
17 #endif
18
19 #include "rockchip_hdmiv2.h"
20 #include "rockchip_hdmiv2_hw.h"
21
22 #define HDMI_SEL_LCDC(x)        ((((x)&1)<<4)|(1<<20))
23 #define grf_writel(v, offset)   writel_relaxed(v, RK_GRF_VIRT + offset)
24
25 static struct hdmi_dev *hdmi_dev;
26
27 static struct hdmi_property rk_hdmi_property = {
28         .videosrc = DISPLAY_SOURCE_LCDC0,
29         .display = DISPLAY_MAIN,
30 };
31
32 #if defined(CONFIG_DEBUG_FS)
33 static const struct rockchip_hdmiv2_reg_table hdmi_reg_table[] = {
34         {IDENTIFICATION_BASE, CONFIG3_ID},
35         {INTERRUPT_BASE, IH_MUTE},
36         {VIDEO_SAMPLER_BASE, TX_BCBDATA1},
37         {VIDEO_PACKETIZER_BASE, VP_MASK},
38         {FRAME_COMPOSER_BASE, FC_DBGTMDS2},
39         {HDMI_SOURCE_PHY_BASE, PHY_PLLCFGFREQ2},
40         {I2C_MASTER_PHY_BASE, PHY_I2CM_SDA_HOLD},
41         {AUDIO_SAMPLER_BASE, AHB_DMA_STPADDR_SET1_0},
42         {MAIN_CONTROLLER_BASE, MC_SWRSTZREQ_2},
43         {COLOR_SPACE_CONVERTER_BASE, CSC_SPARE_2},
44         {HDCP_ENCRYPTION_ENGINE_BASE, HDCP_REVOC_LIST},
45         {HDCP_BKSV_BASE, HDCPREG_BKSV4},
46         {HDCP_AN_BASE, HDCPREG_AN7},
47         {HDCP2REG_BASE, HDCP2REG_MUTE},
48         {ENCRYPTED_DPK_EMBEDDED_BASE, HDCPREG_DPK6},
49         {CEC_ENGINE_BASE, CEC_WKUPCTRL},
50         {I2C_MASTER_BASE, I2CM_SCDC_UPDATE1},
51 };
52
53 static int hdmi_regs_ctrl_show(struct seq_file *s, void *v)
54 {
55         u32 i = 0, j = 0, val = 0;
56
57         seq_puts(s, "\n>>>hdmi_ctl reg ");
58         for (i = 0; i < 16; i++)
59                 seq_printf(s, " %2x", i);
60         seq_puts(s, "\n-----------------------------------------------------------------");
61
62         for (i = 0; i < ARRAY_SIZE(hdmi_reg_table); i++) {
63                 for (j = hdmi_reg_table[i].reg_base;
64                      j <= hdmi_reg_table[i].reg_end; j++) {
65                         val = hdmi_readl(hdmi_dev, j);
66                         if ((j - hdmi_reg_table[i].reg_base)%16 == 0)
67                                 seq_printf(s, "\n>>>hdmi_ctl %04x:", j);
68                         seq_printf(s, " %02x", val);
69                 }
70         }
71         seq_puts(s, "\n-----------------------------------------------------------------\n");
72
73         return 0;
74 }
75
76 static ssize_t hdmi_regs_ctrl_write(struct file *file,
77                                     const char __user *buf,
78                                     size_t count, loff_t *ppos)
79 {
80         u32 reg, val;
81         char kbuf[25];
82
83         if (copy_from_user(kbuf, buf, count))
84                 return -EFAULT;
85         if (sscanf(kbuf, "%x%x", &reg, &val) == -1)
86                 return -EFAULT;
87         if ((reg < 0) || (reg > I2CM_SCDC_UPDATE1)) {
88                 dev_info(hdmi_dev->hdmi->dev, "it is no hdmi reg\n");
89                 return count;
90         }
91         dev_info(hdmi_dev->hdmi->dev,
92                  "/**********hdmi reg config******/");
93         dev_info(hdmi_dev->hdmi->dev, "\n reg=%x val=%x\n", reg, val);
94         hdmi_writel(hdmi_dev, reg, val);
95
96         return count;
97 }
98
99 static int hdmi_regs_phy_show(struct seq_file *s, void *v)
100 {
101         u32 i, count;
102
103         if (hdmi_dev->soctype == HDMI_SOC_RK322X)
104                 count = 0xff;
105         else
106                 count = 0x28;
107         seq_puts(s, "\n>>>hdmi_phy reg ");
108         for (i = 0; i < count; i++)
109                 seq_printf(s, "regs %02x val %04x\n",
110                            i, rockchip_hdmiv2_read_phy(hdmi_dev, i));
111         return 0;
112 }
113
114 static ssize_t hdmi_regs_phy_write(struct file *file,
115                                    const char __user *buf,
116                                    size_t count, loff_t *ppos)
117 {
118         u32 reg, val;
119         char kbuf[25];
120
121         if (copy_from_user(kbuf, buf, count))
122                 return -EFAULT;
123         if (sscanf(kbuf, "%x%x", &reg, &val) == -1)
124                 return -EFAULT;
125         dev_info(hdmi_dev->hdmi->dev,
126                  "/**********hdmi reg phy config******/");
127         dev_info(hdmi_dev->hdmi->dev, "\n reg=%x val=%x\n", reg, val);
128         rockchip_hdmiv2_write_phy(hdmi_dev, reg, val);
129         return count;
130 }
131
132 #define HDMI_DEBUG_ENTRY(name) \
133 static int hdmi_##name##_open(struct inode *inode, struct file *file) \
134 { \
135         return single_open(file, hdmi_##name##_show, inode->i_private); \
136 } \
137 \
138 static const struct file_operations hdmi_##name##_fops = { \
139         .owner = THIS_MODULE, \
140         .open = hdmi_##name##_open, \
141         .read = seq_read, \
142         .write = hdmi_##name##_write,   \
143         .llseek = seq_lseek, \
144         .release = single_release, \
145 }
146
147 HDMI_DEBUG_ENTRY(regs_phy);
148 HDMI_DEBUG_ENTRY(regs_ctrl);
149 #endif
150
151 #ifdef CONFIG_HAS_EARLYSUSPEND
152 static void rockchip_hdmiv2_early_suspend(struct early_suspend *h)
153 {
154         struct hdmi *hdmi = hdmi_dev->hdmi;
155         struct pinctrl_state *gpio_state;
156
157         HDMIDBG("hdmi enter early suspend\n");
158         hdmi_submit_work(hdmi, HDMI_SUSPEND_CTL, 0, 1);
159         /* iomux to gpio and pull down when suspend */
160         gpio_state = pinctrl_lookup_state(hdmi_dev->dev->pins->p, "gpio");
161         pinctrl_select_state(hdmi_dev->dev->pins->p, gpio_state);
162         rockchip_hdmiv2_clk_disable(hdmi_dev);
163 }
164
165 static void rockchip_hdmiv2_early_resume(struct early_suspend *h)
166 {
167         struct hdmi *hdmi = hdmi_dev->hdmi;
168
169         HDMIDBG("hdmi exit early resume\n");
170         /* iomux to default state for hdmi use when resume */
171         pinctrl_select_state(hdmi_dev->dev->pins->p,
172                              hdmi_dev->dev->pins->default_state);
173         rockchip_hdmiv2_clk_enable(hdmi_dev);
174         hdmi_dev_initial(hdmi_dev);
175         if (hdmi->ops->hdcp_power_on_cb)
176                 hdmi->ops->hdcp_power_on_cb();
177         hdmi_submit_work(hdmi, HDMI_RESUME_CTL, 0, 0);
178 }
179 #endif
180
181 void ext_pll_set_27m_out(void)
182 {
183         if (!hdmi_dev || hdmi_dev->soctype != HDMI_SOC_RK322X)
184                 return;
185         /* PHY PLL VCO is 1080MHz, output pclk is 27MHz */
186         rockchip_hdmiv2_write_phy(hdmi_dev,
187                                   EXT_PHY_PLL_PRE_DIVIDER,
188                                   1);
189         rockchip_hdmiv2_write_phy(hdmi_dev,
190                                   EXT_PHY_PLL_FB_DIVIDER,
191                                   45);
192         rockchip_hdmiv2_write_phy(hdmi_dev,
193                                   EXT_PHY_PCLK_DIVIDER1,
194                                   0x61);
195         rockchip_hdmiv2_write_phy(hdmi_dev,
196                                   EXT_PHY_PCLK_DIVIDER2,
197                                   0x64);
198         rockchip_hdmiv2_write_phy(hdmi_dev,
199                                   EXT_PHY_TMDSCLK_DIVIDER,
200                                   0x1d);
201 }
202
203 #define HDMI_PD_ON              (1 << 0)
204 #define HDMI_PCLK_ON            (1 << 1)
205 #define HDMI_HDCPCLK_ON         (1 << 2)
206 #define HDMI_CECCLK_ON          (1 << 3)
207 #define HDMI_EXT_PHY_CLK_ON     (1 << 4)
208
209 static int rockchip_hdmiv2_clk_enable(struct hdmi_dev *hdmi_dev)
210 {
211         if (hdmi_dev->soctype == HDMI_SOC_RK322X) {
212                 if ((hdmi_dev->clk_on & HDMI_EXT_PHY_CLK_ON) == 0) {
213                         if (!hdmi_dev->pclk_phy) {
214                                 hdmi_dev->pclk_phy =
215                                         devm_clk_get(hdmi_dev->dev,
216                                                      "pclk_hdmi_phy");
217                                 if (IS_ERR(hdmi_dev->pclk_phy)) {
218                                         dev_err(hdmi_dev->dev,
219                                                 "get hdmi phy pclk error\n");
220                                         return -1;
221                                 }
222                         }
223                         clk_prepare_enable(hdmi_dev->pclk_phy);
224                         hdmi_dev->clk_on |= HDMI_EXT_PHY_CLK_ON;
225                 }
226         } else if ((hdmi_dev->clk_on & HDMI_PD_ON) == 0) {
227                 if (!hdmi_dev->pd) {
228                         hdmi_dev->pd = devm_clk_get(hdmi_dev->dev, "pd_hdmi");
229                         if (IS_ERR(hdmi_dev->pd)) {
230                                 dev_err(hdmi_dev->dev,
231                                         "Unable to get hdmi pd\n");
232                                 return -1;
233                         }
234                 }
235                 clk_prepare_enable(hdmi_dev->pd);
236                 hdmi_dev->clk_on |= HDMI_PD_ON;
237         }
238
239         if ((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0) {
240                 if (hdmi_dev->pclk == NULL) {
241                         hdmi_dev->pclk =
242                                 devm_clk_get(hdmi_dev->dev, "pclk_hdmi");
243                         if (IS_ERR(hdmi_dev->pclk)) {
244                                 dev_err(hdmi_dev->dev,
245                                         "Unable to get hdmi pclk\n");
246                                 return -1;
247                         }
248                 }
249                 clk_prepare_enable(hdmi_dev->pclk);
250                 hdmi_dev->clk_on |= HDMI_PCLK_ON;
251         }
252
253         if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON) == 0) {
254                 if (hdmi_dev->hdcp_clk == NULL) {
255                         hdmi_dev->hdcp_clk =
256                                 devm_clk_get(hdmi_dev->dev, "hdcp_clk_hdmi");
257                         if (IS_ERR(hdmi_dev->hdcp_clk)) {
258                                 dev_err(hdmi_dev->dev,
259                                         "Unable to get hdmi hdcp_clk\n");
260                                 return -1;
261                         }
262                 }
263                 clk_prepare_enable(hdmi_dev->hdcp_clk);
264                 hdmi_dev->clk_on |= HDMI_HDCPCLK_ON;
265         }
266
267         if ((rk_hdmi_property.feature & SUPPORT_CEC) &&
268             (hdmi_dev->clk_on & HDMI_CECCLK_ON) == 0) {
269                 if (hdmi_dev->cec_clk == NULL) {
270                         hdmi_dev->cec_clk =
271                                 devm_clk_get(hdmi_dev->dev, "cec_clk_hdmi");
272                         if (IS_ERR(hdmi_dev->cec_clk)) {
273                                 dev_err(hdmi_dev->dev,
274                                         "Unable to get hdmi cec_clk\n");
275                                 return -1;
276                         }
277                 }
278                 clk_prepare_enable(hdmi_dev->cec_clk);
279                 hdmi_dev->clk_on |= HDMI_CECCLK_ON;
280         }
281         return 0;
282 }
283
284 static int rockchip_hdmiv2_clk_disable(struct hdmi_dev *hdmi_dev)
285 {
286         if (hdmi_dev->clk_on == 0)
287                 return 0;
288
289         if ((hdmi_dev->clk_on & HDMI_PD_ON) && (hdmi_dev->pd != NULL)) {
290                 clk_disable_unprepare(hdmi_dev->pd);
291                 hdmi_dev->clk_on &= ~HDMI_PD_ON;
292         }
293
294         if ((hdmi_dev->clk_on & HDMI_PCLK_ON) &&
295             (hdmi_dev->pclk != NULL)) {
296                 clk_disable_unprepare(hdmi_dev->pclk);
297                 hdmi_dev->clk_on &= ~HDMI_PCLK_ON;
298         }
299
300         if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON) &&
301             (hdmi_dev->hdcp_clk != NULL)) {
302                 clk_disable_unprepare(hdmi_dev->hdcp_clk);
303                 hdmi_dev->clk_on &= ~HDMI_HDCPCLK_ON;
304         }
305
306         if ((hdmi_dev->clk_on & HDMI_EXT_PHY_CLK_ON) &&
307             hdmi_dev->pclk_phy) {
308                 clk_disable_unprepare(hdmi_dev->pclk_phy);
309                 hdmi_dev->clk_on &= ~HDMI_EXT_PHY_CLK_ON;
310         }
311         return 0;
312 }
313
314 static int rockchip_hdmiv2_fb_event_notify(struct notifier_block *self,
315                                            unsigned long action, void *data)
316 {
317         struct fb_event *event = data;
318         int blank_mode = *((int *)event->data);
319         struct hdmi *hdmi = hdmi_dev->hdmi;
320         struct pinctrl_state *gpio_state;
321 #ifdef CONFIG_PINCTRL
322         struct dev_pin_info *pins = hdmi_dev->dev->pins;
323 #endif
324
325         if (action == FB_EARLY_EVENT_BLANK) {
326                 switch (blank_mode) {
327                 case FB_BLANK_UNBLANK:
328                         break;
329                 default:
330                         HDMIDBG("suspend hdmi\n");
331                         if (!hdmi->sleep) {
332                                 hdmi_submit_work(hdmi,
333                                                  HDMI_SUSPEND_CTL,
334                                                  0, 1);
335                                 if (hdmi_dev->hdcp2_en)
336                                         hdmi_dev->hdcp2_en(0);
337                                 rockchip_hdmiv2_clk_disable(hdmi_dev);
338                                 #ifdef CONFIG_PINCTRL
339                                 if (hdmi_dev->soctype == HDMI_SOC_RK3288)
340                                         gpio_state =
341                                         pinctrl_lookup_state(pins->p,
342                                                              "sleep");
343                                 else
344                                         gpio_state =
345                                         pinctrl_lookup_state(pins->p,
346                                                              "gpio");
347                                 pinctrl_select_state(pins->p,
348                                                      gpio_state);
349                                 #endif
350                         }
351                         break;
352                 }
353         } else if (action == FB_EVENT_BLANK) {
354                 switch (blank_mode) {
355                 case FB_BLANK_UNBLANK:
356                         HDMIDBG("resume hdmi\n");
357                         if (hdmi->sleep) {
358                                 #ifdef CONFIG_PINCTRL
359                                 pinctrl_select_state(pins->p,
360                                                      pins->default_state);
361                                 #endif
362                                 rockchip_hdmiv2_clk_enable(hdmi_dev);
363                                 rockchip_hdmiv2_dev_initial(hdmi_dev);
364                                 if (hdmi->ops->hdcp_power_on_cb)
365                                         hdmi->ops->hdcp_power_on_cb();
366                                 if (hdmi_dev->hdcp2_reset)
367                                         hdmi_dev->hdcp2_reset();
368                                 if (hdmi_dev->hdcp2_en)
369                                         hdmi_dev->hdcp2_en(1);
370                                 hdmi_submit_work(hdmi, HDMI_RESUME_CTL,
371                                                  0, 0);
372                         }
373                         break;
374                 default:
375                         break;
376                 }
377         }
378         return NOTIFY_OK;
379 }
380
381 static struct notifier_block rockchip_hdmiv2_fb_notifier = {
382         .notifier_call = rockchip_hdmiv2_fb_event_notify,
383 };
384
385 #ifdef HDMI_INT_USE_POLL
386 static void rockchip_hdmiv2_irq_work_func(struct work_struct *work)
387 {
388         if (hdmi_dev->enable) {
389                 rockchip_hdmiv2_dev_irq(0, hdmi_dev);
390                 queue_delayed_work(hdmi_dev->workqueue,
391                                    &(hdmi_dev->delay_work),
392                                    msecs_to_jiffies(50));
393         }
394 }
395 #endif
396
397 static struct hdmi_ops rk_hdmi_ops;
398
399 #if defined(CONFIG_OF)
400 static const struct of_device_id rk_hdmi_dt_ids[] = {
401         {.compatible = "rockchip,rk3288-hdmi",},
402         {.compatible = "rockchip,rk3368-hdmi",},
403         {.compatible = "rockchip,rk322x-hdmi",},
404         {}
405 };
406
407 static int rockchip_hdmiv2_parse_dt(struct hdmi_dev *hdmi_dev)
408 {
409         int val = 0;
410         struct device_node *np = hdmi_dev->dev->of_node;
411         const struct of_device_id *match;
412
413         match = of_match_node(rk_hdmi_dt_ids, np);
414         if (!match)
415                 return PTR_ERR(match);
416
417         if (!strcmp(match->compatible, "rockchip,rk3288-hdmi")) {
418                 hdmi_dev->soctype = HDMI_SOC_RK3288;
419         } else if (!strcmp(match->compatible, "rockchip,rk3368-hdmi")) {
420                 hdmi_dev->soctype = HDMI_SOC_RK3368;
421         } else if (!strcmp(match->compatible, "rockchip,rk322x-hdmi")) {
422                 hdmi_dev->soctype = HDMI_SOC_RK322X;
423         } else {
424                 pr_err("It is not a valid rockchip soc!");
425                 return -ENOMEM;
426         }
427
428         if (!of_property_read_u32(np, "rockchip,hdmi_video_source", &val))
429                 rk_hdmi_property.videosrc = val;
430
431         if (!of_property_read_u32(np, "rockchip,hdmi_audio_source", &val))
432                 hdmi_dev->audiosrc = val;
433
434         if (!of_property_read_u32(np, "rockchip,cec_enable", &val) &&
435             (val == 1)) {
436                 pr_debug("hdmi support cec\n");
437                 rk_hdmi_property.feature |= SUPPORT_CEC;
438         }
439         if (!of_property_read_u32(np, "rockchip,hdcp_enable", &val) &&
440             (val == 1)) {
441                 pr_debug("hdmi support hdcp\n");
442                 rk_hdmi_property.feature |= SUPPORT_HDCP;
443         }
444         if (!of_property_read_u32(np, "rockchip,defaultmode", &val) &&
445             (val > 0)) {
446                 pr_debug("default mode is %d\n", val);
447                 rk_hdmi_property.defaultmode = val;
448         } else {
449                 rk_hdmi_property.defaultmode = HDMI_VIDEO_DEFAULT_MODE;
450         }
451         if (of_get_property(np, "rockchip,phy_table", &val)) {
452                 hdmi_dev->phy_table = kmalloc(val, GFP_KERNEL);
453                 if (!hdmi_dev->phy_table) {
454                         pr_err("kmalloc phy table %d error\n", val);
455                         return -ENOMEM;
456                 }
457                 hdmi_dev->phy_table_size =
458                                 val / sizeof(struct hdmi_dev_phy_para);
459                 of_property_read_u32_array(np, "rockchip,phy_table",
460                                            (u32 *)hdmi_dev->phy_table,
461                                            val / sizeof(u32));
462         } else {
463                 pr_info("hdmi phy_table not exist\n");
464         }
465
466         of_property_read_string(np, "rockchip,vendor",
467                                 &(hdmi_dev->vendor_name));
468         of_property_read_string(np, "rockchip,product",
469                                 &(hdmi_dev->product_name));
470         if (!of_property_read_u32(np, "rockchip,deviceinfo", &val))
471                 hdmi_dev->deviceinfo = val & 0xff;
472
473         #ifdef CONFIG_MFD_SYSCON
474         hdmi_dev->grf_base =
475                 syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
476         if (IS_ERR(hdmi_dev->grf_base)) {
477                 hdmi_dev->grf_base = NULL;
478         } else {
479                 if (of_property_read_u32(np, "rockchip,grf_reg_offset",
480                                          &hdmi_dev->grf_reg_offset)) {
481                         pr_err("get cru_reg_offset failed\n");
482                         return -ENXIO;
483                 }
484                 if (of_property_read_u32(np, "rockchip,grf_reg_shift",
485                                          &hdmi_dev->grf_reg_shift)) {
486                         pr_err("get cru_reg_shift failed\n");
487                         return -ENXIO;
488                 }
489         }
490         #endif
491         return 0;
492 }
493 #endif
494
495 static int rockchip_hdmiv2_probe(struct platform_device *pdev)
496 {
497         int ret = -1;
498         struct resource *res;
499
500         HDMIDBG("%s\n", __func__);
501         hdmi_dev = kmalloc(sizeof(*hdmi_dev), GFP_KERNEL);
502         if (!hdmi_dev) {
503                 dev_err(&pdev->dev, ">>rockchip hdmiv2 kmalloc fail!");
504                 return -ENOMEM;
505         }
506         memset(hdmi_dev, 0, sizeof(struct hdmi_dev));
507         platform_set_drvdata(pdev, hdmi_dev);
508         hdmi_dev->dev = &pdev->dev;
509
510         if (rockchip_hdmiv2_parse_dt(hdmi_dev))
511                 goto failed;
512
513         /*request and remap iomem*/
514         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
515         if (!res) {
516                 dev_err(&pdev->dev, "Unable to get register resource\n");
517                 ret = -ENXIO;
518                 goto failed;
519         }
520         hdmi_dev->regbase = devm_ioremap_resource(&pdev->dev, res);
521         if (IS_ERR(hdmi_dev->regbase)) {
522                 ret = PTR_ERR(hdmi_dev->regbase);
523                 dev_err(&pdev->dev,
524                         "cannot ioremap registers,err=%d\n", ret);
525                 goto failed;
526         }
527         if (hdmi_dev->soctype == HDMI_SOC_RK322X) {
528                 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
529                 if (!res) {
530                         dev_err(&pdev->dev,
531                                 "Unable to get phy register resource\n");
532                         ret = -ENXIO;
533                         goto failed;
534                 }
535                 hdmi_dev->phybase = devm_ioremap_resource(&pdev->dev, res);
536                 if (IS_ERR(hdmi_dev->phybase)) {
537                         ret = PTR_ERR(hdmi_dev->phybase);
538                         dev_err(&pdev->dev,
539                                 "cannot ioremap registers,err=%d\n", ret);
540                         goto failed;
541                 }
542         }
543
544         hdmi_dev->reset = devm_reset_control_get(&pdev->dev, "hdmi");
545         if (IS_ERR(hdmi_dev->reset) &&
546             hdmi_dev->soctype != HDMI_SOC_RK3288) {
547                 ret = PTR_ERR(hdmi_dev->reset);
548                 dev_err(&pdev->dev, "failed to get hdmi reset: %d\n", ret);
549                 goto failed;
550         }
551
552         /*enable pd and pclk and hdcp_clk*/
553         if (rockchip_hdmiv2_clk_enable(hdmi_dev) < 0) {
554                 ret = -ENXIO;
555                 goto failed1;
556         }
557         /*lcdc source select*/
558         if (hdmi_dev->soctype == HDMI_SOC_RK3288) {
559                 grf_writel(HDMI_SEL_LCDC(rk_hdmi_property.videosrc),
560                            RK3288_GRF_SOC_CON6);
561                 /* select GPIO7_C0 as cec pin */
562                 grf_writel(((1 << 12) | (1 << 28)), RK3288_GRF_SOC_CON8);
563         }
564         rockchip_hdmiv2_dev_init_ops(&rk_hdmi_ops);
565         /* Register HDMI device */
566         rk_hdmi_property.name = (char *)pdev->name;
567         rk_hdmi_property.priv = hdmi_dev;
568         if (hdmi_dev->soctype == HDMI_SOC_RK3288) {
569                 rk_hdmi_property.feature |= SUPPORT_DEEP_10BIT;
570                 if (rk_hdmi_property.videosrc == DISPLAY_SOURCE_LCDC0)
571                         rk_hdmi_property.feature |=
572                                                 SUPPORT_4K |
573                                                 SUPPORT_TMDS_600M;
574         } else if (hdmi_dev->soctype == HDMI_SOC_RK3368) {
575                 rk_hdmi_property.feature |=
576                                 SUPPORT_4K |
577                                 SUPPORT_4K_4096 |
578                                 SUPPORT_YUV420 |
579                                 SUPPORT_YCBCR_INPUT |
580                                 SUPPORT_VESA_DMT;
581         } else if (hdmi_dev->soctype == HDMI_SOC_RK322X) {
582                 rk_hdmi_property.feature |=
583                                 SUPPORT_4K |
584                                 SUPPORT_4K_4096 |
585                                 SUPPORT_YCBCR_INPUT |
586                                 SUPPORT_1080I |
587                                 SUPPORT_480I_576I;
588                 if (rockchip_get_cpu_version())
589                         rk_hdmi_property.feature |=
590                                 SUPPORT_YUV420 |
591                                 SUPPORT_DEEP_10BIT;
592         } else {
593                 ret = -ENXIO;
594                 goto failed1;
595         }
596         hdmi_dev->hdmi =
597                 rockchip_hdmi_register(&rk_hdmi_property, &rk_hdmi_ops);
598         if (hdmi_dev->hdmi == NULL) {
599                 dev_err(&pdev->dev, "register hdmi device failed\n");
600                 ret = -ENOMEM;
601                 goto failed1;
602         }
603         mutex_init(&hdmi_dev->ddc_lock);
604         hdmi_dev->hdmi->dev = &pdev->dev;
605         hdmi_dev->hdmi->soctype = hdmi_dev->soctype;
606         fb_register_client(&rockchip_hdmiv2_fb_notifier);
607         rockchip_hdmiv2_dev_initial(hdmi_dev);
608         pinctrl_select_state(hdmi_dev->dev->pins->p,
609                              hdmi_dev->dev->pins->default_state);
610 #if defined(CONFIG_DEBUG_FS)
611         hdmi_dev->debugfs_dir = debugfs_create_dir("rockchip_hdmiv2", NULL);
612         if (IS_ERR(hdmi_dev->debugfs_dir))
613                 dev_err(hdmi_dev->hdmi->dev,
614                         "failed to create debugfs dir for rockchip hdmiv2!\n");
615         else {
616                 debugfs_create_file("regs_ctrl", S_IRUSR,
617                                     hdmi_dev->debugfs_dir,
618                                     hdmi_dev, &hdmi_regs_ctrl_fops);
619                 debugfs_create_file("regs_phy", S_IRUSR,
620                                     hdmi_dev->debugfs_dir,
621                                     hdmi_dev, &hdmi_regs_phy_fops);
622         }
623 #endif
624
625 #ifndef HDMI_INT_USE_POLL
626         /* get and request the IRQ */
627         hdmi_dev->irq = platform_get_irq(pdev, 0);
628         if (hdmi_dev->irq <= 0) {
629                 dev_err(hdmi_dev->dev,
630                         "failed to get hdmi irq resource (%d).\n",
631                         hdmi_dev->irq);
632                 ret = -ENXIO;
633                 goto failed1;
634         }
635
636         ret = devm_request_irq(hdmi_dev->dev, hdmi_dev->irq,
637                                rockchip_hdmiv2_dev_irq,
638                                IRQF_TRIGGER_HIGH,
639                                dev_name(hdmi_dev->dev), hdmi_dev);
640         if (ret) {
641                 dev_err(hdmi_dev->dev,
642                         "hdmi request_irq failed (%d).\n",
643                         ret);
644                 goto failed1;
645         }
646 #else
647         hdmi_dev->workqueue =
648                 create_singlethread_workqueue("rockchip hdmiv2 irq");
649         INIT_DELAYED_WORK(&(hdmi_dev->delay_work),
650                           rockchip_hdmiv2_irq_work_func);
651         rockchip_hdmiv2_irq_work_func(NULL);
652
653 #endif
654         rk_display_device_enable(hdmi_dev->hdmi->ddev);
655         dev_info(&pdev->dev, "rockchip hdmiv2 probe sucess.\n");
656         return 0;
657
658 failed1:
659         rockchip_hdmi_unregister(hdmi_dev->hdmi);
660 failed:
661         kfree(hdmi_dev->phy_table);
662         kfree(hdmi_dev);
663         hdmi_dev = NULL;
664         dev_err(&pdev->dev, "rk3288 hdmi probe error.\n");
665         return ret;
666 }
667
668 static int rockchip_hdmiv2_suspend(struct platform_device *pdev,
669                                    pm_message_t state)
670 {
671         if (hdmi_dev &&
672             hdmi_dev->grf_base &&
673             hdmi_dev->soctype == HDMI_SOC_RK322X) {
674                 regmap_write(hdmi_dev->grf_base,
675                              RK322X_GRF_SOC_CON2,
676                              RK322X_PLL_POWER_DOWN);
677         }
678         return 0;
679 }
680
681 static int rockchip_hdmiv2_resume(struct platform_device *pdev)
682 {
683         if (hdmi_dev &&
684             hdmi_dev->grf_base &&
685             hdmi_dev->soctype == HDMI_SOC_RK322X) {
686                 regmap_write(hdmi_dev->grf_base,
687                              RK322X_GRF_SOC_CON2,
688                              RK322X_PLL_POWER_UP);
689         }
690         return 0;
691 }
692
693 static int rockchip_hdmiv2_remove(struct platform_device *pdev)
694 {
695         dev_info(&pdev->dev, "rk3288 hdmi driver removed.\n");
696         return 0;
697 }
698
699 static void rockchip_hdmiv2_shutdown(struct platform_device *pdev)
700 {
701         struct hdmi *hdmi;
702
703         if (hdmi_dev) {
704                 #ifdef CONFIG_HAS_EARLYSUSPEND
705                 unregister_early_suspend(&hdmi_dev->early_suspend);
706                 #endif
707                 hdmi = hdmi_dev->hdmi;
708                 if (hdmi->hotplug == HDMI_HPD_ACTIVED &&
709                     hdmi->ops->setmute)
710                         hdmi->ops->setmute(hdmi, HDMI_VIDEO_MUTE);
711         }
712 }
713
714 static struct platform_driver rockchip_hdmiv2_driver = {
715         .probe          = rockchip_hdmiv2_probe,
716         .remove         = rockchip_hdmiv2_remove,
717         .driver         = {
718                 .name   = "rockchip-hdmiv2",
719                 .owner  = THIS_MODULE,
720                 #if defined(CONFIG_OF)
721                 .of_match_table = of_match_ptr(rk_hdmi_dt_ids),
722                 #endif
723         },
724         .suspend        = rockchip_hdmiv2_suspend,
725         .resume         = rockchip_hdmiv2_resume,
726         .shutdown       = rockchip_hdmiv2_shutdown,
727 };
728
729 static int __init rockchip_hdmiv2_init(void)
730 {
731         return platform_driver_register(&rockchip_hdmiv2_driver);
732 }
733
734 static void __exit rockchip_hdmiv2_exit(void)
735 {
736         platform_driver_unregister(&rockchip_hdmiv2_driver);
737 }
738
739 module_init(rockchip_hdmiv2_init);
740 module_exit(rockchip_hdmiv2_exit);