b11fb18a54f5d310a771a1d3239cc503d68b3e10
[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/rockchip/grf.h>
8 #include <linux/rockchip/iomap.h>
9 #include <linux/mfd/syscon.h>
10 #if defined(CONFIG_DEBUG_FS)
11 #include <linux/uaccess.h>
12 #include <linux/fs.h>
13 #include <linux/debugfs.h>
14 #include <linux/seq_file.h>
15 #endif
16
17 #include "rockchip_hdmiv2.h"
18 #include "rockchip_hdmiv2_hw.h"
19
20 #define HDMI_SEL_LCDC(x)        ((((x)&1)<<4)|(1<<20))
21 #define grf_writel(v, offset)   writel_relaxed(v, RK_GRF_VIRT + offset)
22
23 static struct hdmi_dev *hdmi_dev;
24
25 static struct hdmi_property rk_hdmi_property = {
26         .videosrc = DISPLAY_SOURCE_LCDC0,
27         .display = DISPLAY_MAIN,
28 };
29
30 #if defined(CONFIG_DEBUG_FS)
31 static const struct rockchip_hdmiv2_reg_table hdmi_reg_table[] = {
32         {IDENTIFICATION_BASE, CONFIG3_ID},
33         {INTERRUPT_BASE, IH_MUTE},
34         {VIDEO_SAMPLER_BASE, TX_BCBDATA1},
35         {VIDEO_PACKETIZER_BASE, VP_MASK},
36         {FRAME_COMPOSER_BASE, FC_DBGTMDS2},
37         {HDMI_SOURCE_PHY_BASE, PHY_PLLCFGFREQ2},
38         {I2C_MASTER_PHY_BASE, PHY_I2CM_SDA_HOLD},
39         {AUDIO_SAMPLER_BASE, AHB_DMA_STPADDR_SET1_0},
40         {MAIN_CONTROLLER_BASE, MC_SWRSTZREQ_2},
41         {COLOR_SPACE_CONVERTER_BASE, CSC_SPARE_2},
42         {HDCP_ENCRYPTION_ENGINE_BASE, HDCP_REVOC_LIST},
43         {HDCP_BKSV_BASE, HDCPREG_BKSV4},
44         {HDCP_AN_BASE, HDCPREG_AN7},
45         {HDCP2REG_BASE, HDCP2REG_MUTE},
46         {ENCRYPTED_DPK_EMBEDDED_BASE, HDCPREG_DPK6},
47         {CEC_ENGINE_BASE, CEC_WKUPCTRL},
48         {I2C_MASTER_BASE, I2CM_SCDC_UPDATE1},
49 };
50
51 static int rockchip_hdmiv2_reg_show(struct seq_file *s, void *v)
52 {
53         int i = 0, j = 0;
54         u32 val = 0;
55
56         seq_puts(s, "\n>>>hdmi_ctl reg ");
57         for (i = 0; i < 16; i++)
58                 seq_printf(s, " %2x", i);
59         seq_puts(s, "\n-----------------------------------------------------------------");
60
61         for (i = 0; i < ARRAY_SIZE(hdmi_reg_table); i++) {
62                 for (j = hdmi_reg_table[i].reg_base;
63                      j <= hdmi_reg_table[i].reg_end; j++) {
64                         val = hdmi_readl(hdmi_dev, j);
65                         if ((j - hdmi_reg_table[i].reg_base)%16 == 0)
66                                 seq_printf(s, "\n>>>hdmi_ctl %04x:", j);
67                         seq_printf(s, " %02x", val);
68                 }
69         }
70         seq_puts(s, "\n-----------------------------------------------------------------\n");
71
72         /*rockchip_hdmiv2_dump_phy_regs(hdmi_dev);*/
73         return 0;
74 }
75
76 static ssize_t rockchip_hdmiv2_reg_write(struct file *file,
77                                          const char __user *buf,
78                                          size_t count, loff_t *ppos)
79 {
80         u32 reg;
81         u32 val;
82         char kbuf[25];
83
84         if (copy_from_user(kbuf, buf, count))
85                 return -EFAULT;
86         if (sscanf(kbuf, "%x%x", &reg, &val) == -1)
87                 return -EFAULT;
88         if ((reg < 0) || (reg > I2CM_SCDC_UPDATE1)) {
89                 dev_info(hdmi_dev->hdmi->dev, "it is no hdmi reg\n");
90                 return count;
91         }
92         dev_info(hdmi_dev->hdmi->dev,
93                  "/**********hdmi reg config******/");
94         dev_info(hdmi_dev->hdmi->dev, "\n reg=%x val=%x\n", reg, val);
95         hdmi_writel(hdmi_dev, reg, val);
96
97         return count;
98 }
99
100 static int rockchip_hdmiv2_reg_open(struct inode *inode, struct file *file)
101 {
102         struct hdmi_dev *hdmi_dev = inode->i_private;
103
104         return single_open(file, rockchip_hdmiv2_reg_show, hdmi_dev);
105 }
106
107 static const struct file_operations rockchip_hdmiv2_reg_fops = {
108         .owner          = THIS_MODULE,
109         .open           = rockchip_hdmiv2_reg_open,
110         .read           = seq_read,
111         .write          = rockchip_hdmiv2_reg_write,
112         .llseek         = seq_lseek,
113         .release        = single_release,
114 };
115 #endif
116
117 #ifdef CONFIG_HAS_EARLYSUSPEND
118 static void rockchip_hdmiv2_early_suspend(struct early_suspend *h)
119 {
120         struct hdmi *hdmi = hdmi_dev->hdmi;
121         struct delay_work *delay_work;
122         struct pinctrl_state *gpio_state;
123
124         HDMIDBG("hdmi enter early suspend\n");
125         delay_work = hdmi_submit_work(hdmi, HDMI_SUSPEND_CTL, 0, NULL);
126         if (delay_work)
127                 flush_delayed_work_sync(delay_work);
128         /* iomux to gpio and pull down when suspend */
129         gpio_state = pinctrl_lookup_state(hdmi_dev->dev->pins->p, "gpio");
130         pinctrl_select_state(hdmi_dev->dev->pins->p, gpio_state);
131         rockchip_hdmiv2_clk_disable(hdmi_dev);
132 }
133
134 static void rockchip_hdmiv2_early_resume(struct early_suspend *h)
135 {
136         struct hdmi *hdmi = hdmi_dev->hdmi;
137
138         HDMIDBG("hdmi exit early resume\n");
139         /* iomux to default state for hdmi use when resume */
140         pinctrl_select_state(hdmi_dev->dev->pins->p,
141                              hdmi_dev->dev->pins->default_state);
142         rockchip_hdmiv2_clk_enable(hdmi_dev);
143         hdmi_dev_initial(hdmi_dev);
144         if (hdmi->ops->hdcp_power_on_cb)
145                 hdmi->ops->hdcp_power_on_cb();
146         hdmi_submit_work(hdmi, HDMI_RESUME_CTL, 0, NULL);
147 }
148 #endif
149
150 #define HDMI_PD_ON                      (1 << 0)
151 #define HDMI_PCLK_ON            (1 << 1)
152 #define HDMI_HDCPCLK_ON         (1 << 2)
153 #define HDMI_CECCLK_ON          (1 << 3)
154
155 static int rockchip_hdmiv2_clk_enable(struct hdmi_dev *hdmi_dev)
156 {
157         if ((hdmi_dev->clk_on & HDMI_PD_ON) &&
158             (hdmi_dev->clk_on & HDMI_PCLK_ON) &&
159             (hdmi_dev->clk_on & HDMI_HDCPCLK_ON))
160                 return 0;
161
162         if ((hdmi_dev->clk_on & HDMI_PD_ON) == 0 &&
163             hdmi_dev->soctype == HDMI_SOC_RK3288) {
164                 if (hdmi_dev->pd == NULL) {
165                         hdmi_dev->pd = devm_clk_get(hdmi_dev->dev, "pd_hdmi");
166                         if (IS_ERR(hdmi_dev->pd)) {
167                                 dev_err(hdmi_dev->dev,
168                                         "Unable to get hdmi pd\n");
169                                 return -1;
170                         }
171                 }
172                 clk_prepare_enable(hdmi_dev->pd);
173                 hdmi_dev->clk_on |= HDMI_PD_ON;
174         }
175
176         if ((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0) {
177                 if (hdmi_dev->pclk == NULL) {
178                         hdmi_dev->pclk =
179                                 devm_clk_get(hdmi_dev->dev, "pclk_hdmi");
180                         if (IS_ERR(hdmi_dev->pclk)) {
181                                 dev_err(hdmi_dev->dev,
182                                         "Unable to get hdmi pclk\n");
183                                 return -1;
184                         }
185                 }
186                 clk_prepare_enable(hdmi_dev->pclk);
187                 hdmi_dev->clk_on |= HDMI_PCLK_ON;
188         }
189
190         if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON) == 0) {
191                 if (hdmi_dev->hdcp_clk == NULL) {
192                         hdmi_dev->hdcp_clk =
193                                 devm_clk_get(hdmi_dev->dev, "hdcp_clk_hdmi");
194                         if (IS_ERR(hdmi_dev->hdcp_clk)) {
195                                 dev_err(hdmi_dev->dev,
196                                         "Unable to get hdmi hdcp_clk\n");
197                                 return -1;
198                         }
199                 }
200                 clk_prepare_enable(hdmi_dev->hdcp_clk);
201                 hdmi_dev->clk_on |= HDMI_HDCPCLK_ON;
202         }
203
204         if ((rk_hdmi_property.feature & SUPPORT_CEC) &&
205             (hdmi_dev->clk_on & HDMI_CECCLK_ON) == 0) {
206                 if (hdmi_dev->cec_clk == NULL) {
207                         hdmi_dev->cec_clk =
208                                 devm_clk_get(hdmi_dev->dev, "cec_clk_hdmi");
209                         if (IS_ERR(hdmi_dev->cec_clk)) {
210                                 dev_err(hdmi_dev->dev,
211                                         "Unable to get hdmi cec_clk\n");
212                                 return -1;
213                         }
214                 }
215                 clk_prepare_enable(hdmi_dev->cec_clk);
216                 hdmi_dev->clk_on |= HDMI_CECCLK_ON;
217         }
218         return 0;
219 }
220
221 static int rockchip_hdmiv2_clk_disable(struct hdmi_dev *hdmi_dev)
222 {
223         if (hdmi_dev->clk_on == 0)
224                 return 0;
225
226         if ((hdmi_dev->clk_on & HDMI_PD_ON) && (hdmi_dev->pd != NULL)) {
227                 clk_disable_unprepare(hdmi_dev->pd);
228                 hdmi_dev->clk_on &= ~HDMI_PD_ON;
229         }
230
231         if ((hdmi_dev->clk_on & HDMI_PCLK_ON) &&
232             (hdmi_dev->pclk != NULL)) {
233                 clk_disable_unprepare(hdmi_dev->pclk);
234                 hdmi_dev->clk_on &= ~HDMI_PCLK_ON;
235         }
236
237         if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON) &&
238             (hdmi_dev->hdcp_clk != NULL)) {
239                 clk_disable_unprepare(hdmi_dev->hdcp_clk);
240                 hdmi_dev->clk_on &= ~HDMI_HDCPCLK_ON;
241         }
242
243         return 0;
244 }
245
246 static int rockchip_hdmiv2_fb_event_notify(struct notifier_block *self,
247                                            unsigned long action, void *data)
248 {
249         struct fb_event *event = data;
250         int blank_mode = *((int *)event->data);
251         struct hdmi *hdmi = hdmi_dev->hdmi;
252         struct delayed_work *delay_work;
253
254         if (action == FB_EARLY_EVENT_BLANK) {
255                 switch (blank_mode) {
256                 case FB_BLANK_UNBLANK:
257                         break;
258                 default:
259                         HDMIDBG("suspend hdmi\n");
260                         if (!hdmi->sleep) {
261                                 delay_work =
262                                         hdmi_submit_work(hdmi,
263                                                          HDMI_SUSPEND_CTL,
264                                                          0, NULL);
265                                 if (delay_work)
266                                         flush_delayed_work(delay_work);
267                                 rockchip_hdmiv2_clk_disable(hdmi_dev);
268                         }
269                         break;
270                 }
271         } else if (action == FB_EVENT_BLANK) {
272                 switch (blank_mode) {
273                 case FB_BLANK_UNBLANK:
274                         HDMIDBG("resume hdmi\n");
275                         if (hdmi->sleep) {
276                                 rockchip_hdmiv2_clk_enable(hdmi_dev);
277                                 rockchip_hdmiv2_dev_initial(hdmi_dev);
278                                 if (hdmi->ops->hdcp_power_on_cb)
279                                         hdmi->ops->hdcp_power_on_cb();
280                                 hdmi_submit_work(hdmi, HDMI_RESUME_CTL,
281                                                  0, NULL);
282                         }
283                         break;
284                 default:
285                         break;
286                 }
287         }
288         return NOTIFY_OK;
289 }
290
291 static struct notifier_block rockchip_hdmiv2_fb_notifier = {
292         .notifier_call = rockchip_hdmiv2_fb_event_notify,
293 };
294 #ifdef HDMI_INT_USE_POLL
295 static void rockchip_hdmiv2_irq_work_func(struct work_struct *work)
296 {
297         if (hdmi_dev->enable) {
298                 rockchip_hdmiv2_dev_irq(0, hdmi_dev);
299                 queue_delayed_work(hdmi_dev->workqueue,
300                                    &(hdmi_dev->delay_work),
301                                    msecs_to_jiffies(50));
302         }
303 }
304 #endif
305
306 static struct hdmi_ops rk_hdmi_ops;
307
308
309 #if defined(CONFIG_OF)
310 static const struct of_device_id rk_hdmi_dt_ids[] = {
311         {.compatible = "rockchip,rk3288-hdmi",},
312         {.compatible = "rockchip,rk3368-hdmi",},
313         {}
314 };
315
316 static int rockchip_hdmiv2_parse_dt(struct hdmi_dev *hdmi_dev)
317 {
318         int val = 0;
319         struct device_node *np = hdmi_dev->dev->of_node;
320         const struct of_device_id *match;
321
322         match = of_match_node(rk_hdmi_dt_ids, np);
323         if (!match)
324                 return PTR_ERR(match);
325
326         if (!strcmp(match->compatible, "rockchip,rk3288-hdmi")) {
327                 hdmi_dev->soctype = HDMI_SOC_RK3288;
328         } else if (!strcmp(match->compatible, "rockchip,rk3368-hdmi")) {
329                 hdmi_dev->soctype = HDMI_SOC_RK3368;
330         } else {
331                 pr_err("It is not a valid rockchip soc!");
332                 return -ENOMEM;
333         }
334
335         if (!of_property_read_u32(np, "rockchip,hdmi_video_source", &val))
336                 rk_hdmi_property.videosrc = val;
337
338         if (!of_property_read_u32(np, "rockchip,hdmi_audio_source", &val))
339                 hdmi_dev->audiosrc = val;
340
341         if (!of_property_read_u32(np, "rockchip,cec_enable", &val) &&
342             (val == 1)) {
343                 pr_info("hdmi support cec\n");
344                 rk_hdmi_property.feature |= SUPPORT_CEC;
345         }
346         if (!of_property_read_u32(np, "rockchip,hdcp_enable", &val) &&
347             (val == 1)) {
348                 pr_info("hdmi support hdcp\n");
349                 rk_hdmi_property.feature |= SUPPORT_HDCP;
350         }
351         #ifdef CONFIG_MFD_SYSCON
352         hdmi_dev->grf_base =
353                 syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
354         #endif
355         return 0;
356 }
357 #endif
358
359 static int rockchip_hdmiv2_probe(struct platform_device *pdev)
360 {
361         int ret = -1;
362         struct resource *res;
363
364         HDMIDBG("%s\n", __func__);
365         hdmi_dev = kmalloc(sizeof(*hdmi_dev), GFP_KERNEL);
366         if (!hdmi_dev) {
367                 dev_err(&pdev->dev, ">>rockchip hdmiv2 kmalloc fail!");
368                 return -ENOMEM;
369         }
370         memset(hdmi_dev, 0, sizeof(struct hdmi_dev));
371         platform_set_drvdata(pdev, hdmi_dev);
372         hdmi_dev->dev = &pdev->dev;
373
374         rockchip_hdmiv2_parse_dt(hdmi_dev);
375
376         /*request and remap iomem*/
377         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
378         if (!res) {
379                 dev_err(&pdev->dev, "Unable to get register resource\n");
380                 ret = -ENXIO;
381                 goto failed;
382         }
383         hdmi_dev->regbase_phy = res->start;
384         hdmi_dev->regsize_phy = resource_size(res);
385         hdmi_dev->regbase = devm_ioremap_resource(&pdev->dev, res);
386         if (IS_ERR(hdmi_dev->regbase)) {
387                 ret = PTR_ERR(hdmi_dev->regbase);
388                 dev_err(&pdev->dev,
389                         "cannot ioremap registers,err=%d\n", ret);
390                 goto failed;
391         }
392
393         /*enable pd and pclk and hdcp_clk*/
394         if (rockchip_hdmiv2_clk_enable(hdmi_dev) < 0) {
395                 ret = -ENXIO;
396                 goto failed1;
397         }
398         /*lcdc source select*/
399         if (hdmi_dev->soctype == HDMI_SOC_RK3288) {
400                 grf_writel(HDMI_SEL_LCDC(rk_hdmi_property.videosrc),
401                            RK3288_GRF_SOC_CON6);
402                 /* select GPIO7_C0 as cec pin */
403                 grf_writel(((1 << 12) | (1 << 28)), RK3288_GRF_SOC_CON8);
404         }
405         rockchip_hdmiv2_dev_init_ops(&rk_hdmi_ops);
406         /* Register HDMI device */
407         rk_hdmi_property.name = (char *)pdev->name;
408         rk_hdmi_property.priv = hdmi_dev;
409         if (hdmi_dev->soctype == HDMI_SOC_RK3288) {
410                 /*rk_hdmi_property.feature |= SUPPORT_DEEP_10BIT;*/
411                 if (rk_hdmi_property.videosrc == DISPLAY_SOURCE_LCDC0)
412                         rk_hdmi_property.feature |=
413                                                 SUPPORT_4K |
414                                                 SUPPORT_TMDS_600M;
415         } else if (hdmi_dev->soctype == HDMI_SOC_RK3368) {
416                 rk_hdmi_property.feature |=
417                                 SUPPORT_4K |
418                                 SUPPORT_4K_4096 |
419                                 SUPPORT_YUV420 |
420                                 SUPPORT_YCBCR_INPUT;
421         }
422         hdmi_dev->hdmi =
423                 rockchip_hdmi_register(&rk_hdmi_property, &rk_hdmi_ops);
424         if (hdmi_dev->hdmi == NULL) {
425                 dev_err(&pdev->dev, "register hdmi device failed\n");
426                 ret = -ENOMEM;
427                 goto failed1;
428         }
429         mutex_init(&hdmi_dev->ddc_lock);
430         hdmi_dev->hdmi->dev = &pdev->dev;
431         hdmi_dev->hdmi->soctype = hdmi_dev->soctype;
432         fb_register_client(&rockchip_hdmiv2_fb_notifier);
433         rockchip_hdmiv2_dev_initial(hdmi_dev);
434         pinctrl_select_state(hdmi_dev->dev->pins->p,
435                              hdmi_dev->dev->pins->default_state);
436 #if defined(CONFIG_DEBUG_FS)
437         hdmi_dev->debugfs_dir = debugfs_create_dir("rockchip_hdmiv2", NULL);
438         if (IS_ERR(hdmi_dev->debugfs_dir))
439                 dev_err(hdmi_dev->hdmi->dev,
440                         "failed to create debugfs dir for rockchip hdmiv2!\n");
441         else
442                 debugfs_create_file("hdmi", S_IRUSR,
443                                     hdmi_dev->debugfs_dir,
444                                     hdmi_dev, &rockchip_hdmiv2_reg_fops);
445 #endif
446         rk_display_device_enable(hdmi_dev->hdmi->ddev);
447
448 #ifndef HDMI_INT_USE_POLL
449         /* get and request the IRQ */
450         hdmi_dev->irq = platform_get_irq(pdev, 0);
451         if (hdmi_dev->irq <= 0) {
452                 dev_err(hdmi_dev->dev,
453                         "failed to get hdmi irq resource (%d).\n",
454                         hdmi_dev->irq);
455                 ret = -ENXIO;
456                 goto failed1;
457         }
458
459         ret =
460             devm_request_irq(hdmi_dev->dev, hdmi_dev->irq,
461                              rockchip_hdmiv2_dev_irq,
462                              IRQF_TRIGGER_HIGH,
463                              dev_name(hdmi_dev->dev), hdmi_dev);
464         if (ret) {
465                 dev_err(hdmi_dev->dev, "hdmi request_irq failed (%d).\n", ret);
466                 goto failed1;
467         }
468 #else
469         hdmi_dev->workqueue =
470                 create_singlethread_workqueue("rockchip hdmiv2 irq");
471         INIT_DELAYED_WORK(&(hdmi_dev->delay_work),
472                           rockchip_hdmiv2_irq_work_func);
473         rockchip_hdmiv2_irq_work_func(NULL);
474
475 #endif
476         dev_info(&pdev->dev, "rockchip hdmiv2 probe sucess.\n");
477         return 0;
478
479 failed1:
480         rockchip_hdmi_unregister(hdmi_dev->hdmi);
481 failed:
482         kfree(hdmi_dev);
483         hdmi_dev = NULL;
484         dev_err(&pdev->dev, "rk3288 hdmi probe error.\n");
485         return ret;
486 }
487
488 static int rockchip_hdmiv2_remove(struct platform_device *pdev)
489 {
490         dev_info(&pdev->dev, "rk3288 hdmi driver removed.\n");
491         return 0;
492 }
493
494 static void rockchip_hdmiv2_shutdown(struct platform_device *pdev)
495 {
496         struct hdmi *hdmi;
497
498         if (hdmi_dev) {
499                 #ifdef CONFIG_HAS_EARLYSUSPEND
500                 unregister_early_suspend(&hdmi_dev->early_suspend);
501                 #endif
502                 hdmi = hdmi_dev->hdmi;
503                 if (hdmi->hotplug == HDMI_HPD_ACTIVED &&
504                     hdmi->ops->setmute)
505                         hdmi->ops->setmute(hdmi, HDMI_VIDEO_MUTE);
506         }
507 }
508
509 static struct platform_driver rockchip_hdmiv2_driver = {
510         .probe          = rockchip_hdmiv2_probe,
511         .remove         = rockchip_hdmiv2_remove,
512         .driver         = {
513                 .name   = "rockchip-hdmiv2",
514                 .owner  = THIS_MODULE,
515                 #if defined(CONFIG_OF)
516                 .of_match_table = of_match_ptr(rk_hdmi_dt_ids),
517                 #endif
518         },
519         .shutdown   = rockchip_hdmiv2_shutdown,
520 };
521
522 static int __init rockchip_hdmiv2_init(void)
523 {
524         return platform_driver_register(&rockchip_hdmiv2_driver);
525 }
526
527 static void __exit rockchip_hdmiv2_exit(void)
528 {
529         platform_driver_unregister(&rockchip_hdmiv2_driver);
530 }
531
532 module_init(rockchip_hdmiv2_init);
533 module_exit(rockchip_hdmiv2_exit);