RK616: add dts property and fix some compile error
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / chips / rk616 / rk616_hdmi.c
1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/errno.h>
4 #include <linux/string.h>
5 #include <linux/mm.h>
6 #include <linux/slab.h>
7 #include <linux/delay.h>
8 #include <linux/device.h>
9 #include <linux/init.h>
10 #include <linux/dma-mapping.h>
11 #include <linux/interrupt.h>
12 #include <linux/platform_device.h>
13 #include <linux/clk.h>
14 #include <linux/uaccess.h>
15
16 //#include <mach/board.h>
17 //#include <mach/io.h>
18 #include <linux/of_gpio.h>
19 //#include <mach/iomux.h>
20 #include <linux/rk_fb.h> 
21
22 #if defined(CONFIG_DEBUG_FS)
23 #include <linux/fs.h>
24 #include <linux/debugfs.h>
25 #include <linux/seq_file.h>
26 #endif
27
28 #include "rk616_hdmi.h"
29 #include "rk616_hdmi_hw.h"
30
31 extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent);
32 extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi);
33
34 struct hdmi *hdmi = NULL;
35
36 #if defined(CONFIG_DEBUG_FS)
37 static int rk616_hdmi_reg_show(struct seq_file *s, void *v)
38 {
39         int i = 0;
40         u32 val = 0;
41         seq_printf(s, "\n>>>rk616_ctl reg");
42         for (i = 0; i < 16; i++) {
43                 seq_printf(s, " %2x", i);
44         }
45         seq_printf(s, "\n-----------------------------------------------------------------");
46         
47         for(i=0; i<= PHY_PRE_DIV_RATIO; i++) {
48                 hdmi_readl(i, &val);
49                 if(i%16==0)
50                         seq_printf(s,"\n>>>rk616_ctl %2x:", i);
51                 seq_printf(s," %02x",val);
52
53         }
54         seq_printf(s, "\n-----------------------------------------------------------------\n");
55         
56         return 0;
57 }
58
59 static ssize_t rk616_hdmi_reg_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
60
61         u32 reg;
62         u32 val;
63         char kbuf[25];
64         if (copy_from_user(kbuf, buf, count))
65                 return -EFAULT;
66         sscanf(kbuf, "%x%x", &reg, &val);
67         if ((reg < 0) || (reg > 0xed)) {
68                 dev_info(hdmi->dev, "it is no hdmi reg\n");
69                 return count;
70         }
71         dev_info(hdmi->dev, "/**********rk616 reg config******/");
72         dev_info(hdmi->dev, "\n reg=%x val=%x\n", reg, val);
73         hdmi_writel(reg, val);
74
75         return count;
76 }
77
78 static int rk616_hdmi_reg_open(struct inode *inode, struct file *file)
79 {
80         struct mfd_rk616 *rk616 = inode->i_private;
81         return single_open(file,rk616_hdmi_reg_show,rk616);
82 }
83
84 static const struct file_operations rk616_hdmi_reg_fops = {
85         .owner          = THIS_MODULE,
86         .open           = rk616_hdmi_reg_open,
87         .read           = seq_read,
88         .write          = rk616_hdmi_reg_write,
89         .llseek         = seq_lseek,
90         .release        = single_release,
91 };
92 #endif
93
94 int rk616_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
95                 void (*hdcp_irq_cb)(int status),
96                 int (*hdcp_power_on_cb)(void),
97                 void (*hdcp_power_off_cb)(void))
98 {
99         if(hdmi == NULL)
100                 return HDMI_ERROR_FALSE;
101
102         hdmi->hdcp_cb = hdcp_cb;
103         hdmi->hdcp_irq_cb = hdcp_irq_cb;
104         hdmi->hdcp_power_on_cb = hdcp_power_on_cb;
105         hdmi->hdcp_power_off_cb = hdcp_power_off_cb;
106
107         return HDMI_ERROR_SUCESS;
108 }
109
110 #ifdef CONFIG_HAS_EARLYSUSPEND
111 static void hdmi_early_suspend(struct early_suspend *h)
112 {
113         hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);
114
115         flush_delayed_work(&hdmi->delay_work);  
116         mutex_lock(&hdmi->enable_mutex);
117         hdmi->suspend = 1;
118         if(!hdmi->enable) {
119                 mutex_unlock(&hdmi->enable_mutex);
120                 return;
121         }
122
123         if (hdmi->irq)
124                 disable_irq(hdmi->irq);
125
126         mutex_unlock(&hdmi->enable_mutex);
127         hdmi->command = HDMI_CONFIG_ENABLE;
128         init_completion(&hdmi->complete);
129         hdmi->wait = 1;
130         queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
131         wait_for_completion_interruptible_timeout(&hdmi->complete,
132                         msecs_to_jiffies(5000));
133         flush_delayed_work(&hdmi->delay_work);
134
135         return;
136 }
137
138 static void hdmi_early_resume(struct early_suspend *h)
139 {
140         struct rk616_hdmi *rk616_hdmi;
141
142         rk616_hdmi = container_of(hdmi, struct rk616_hdmi, g_hdmi);
143         hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");
144
145         mutex_lock(&hdmi->enable_mutex);
146
147         hdmi->suspend = 0;
148         rk616_hdmi_initial(hdmi);
149         if(hdmi->enable && hdmi->irq) {
150                 enable_irq(hdmi->irq);
151                 // hdmi_irq();
152                 rk616_hdmi_work(hdmi);
153         }
154         if (rk616_hdmi->rk616_drv && !gpio_is_valid(rk616_hdmi->rk616_drv->pdata->hdmi_irq)) 
155                 queue_delayed_work(hdmi->workqueue, &rk616_hdmi->rk616_delay_work, 100);
156         queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));   
157         mutex_unlock(&hdmi->enable_mutex);
158         return;
159 }
160 #endif
161 static void rk616_delay_work_func(struct work_struct *work)
162 {
163         struct rk616_hdmi *rk616_hdmi;
164
165         rk616_hdmi = container_of(hdmi, struct rk616_hdmi, g_hdmi);
166
167         if(hdmi->suspend == 0) {
168                 if(hdmi->enable == 1) {
169                         //hdmi_irq();
170                         rk616_hdmi_work(hdmi);
171                 }
172
173                 if (rk616_hdmi->rk616_drv && !gpio_is_valid(rk616_hdmi->rk616_drv->pdata->hdmi_irq)) {
174                         queue_delayed_work(hdmi->workqueue, &rk616_hdmi->rk616_delay_work, 100);
175                 }
176         }
177 }
178
179 static void __maybe_unused rk616_irq_work_func(struct work_struct *work)
180 {
181         if((hdmi->suspend == 0) && (hdmi->enable == 1)) {
182                 rk616_hdmi_work(hdmi);
183         }
184         dev_info(hdmi->dev, "func: %s, enable_irq\n", __func__);
185         enable_irq(hdmi->irq);
186 }
187
188 static irqreturn_t rk616_hdmi_irq(int irq, void *dev_id)
189 {
190         struct work_struct  *rk616_irq_work_struct;
191         struct rk616_hdmi *rk616_hdmi;
192
193         rk616_hdmi = container_of(hdmi, struct rk616_hdmi, g_hdmi);
194         if(rk616_hdmi->rk616_drv) {
195                 rk616_irq_work_struct  = dev_id;
196                 disable_irq_nosync(hdmi->irq);
197                 queue_work(hdmi->workqueue, rk616_irq_work_struct);
198         } else {
199                 /* 3028a hdmi */
200                 if((hdmi->suspend == 0) && (hdmi->enable == 1)) {
201                         printk(KERN_INFO "line = %d, rk616_hdmi_irq irq triggered.\n", __LINE__);
202                         rk616_hdmi_work(hdmi);
203                 }
204         }
205         return IRQ_HANDLED;
206 }
207
208 static int rk616_hdmi_probe(struct platform_device *pdev)
209 {
210         int ret;
211         struct rk616_hdmi *rk616_hdmi;
212         struct resource __maybe_unused *mem;
213         struct resource __maybe_unused *res;
214         struct device_node *np = pdev->dev.of_node;
215
216         rk616_hdmi = devm_kzalloc(&pdev->dev, sizeof(*rk616_hdmi), GFP_KERNEL);
217         if(!rk616_hdmi)
218         {
219                 dev_err(&pdev->dev, ">>rk616_hdmi kmalloc fail!");
220                 return -ENOMEM;
221         }
222         hdmi = &rk616_hdmi->g_hdmi;
223
224 #ifdef CONFIG_ARCH_RK3026
225         rk616_hdmi->rk616_drv = NULL;
226 #else
227         rk616_hdmi->rk616_drv = dev_get_drvdata(pdev->dev.parent);
228         if(!(rk616_hdmi->rk616_drv))
229         {
230                 dev_err(&pdev->dev,"null mfd device rk616!\n");
231                 return -ENODEV;
232         }
233
234 #endif
235
236         hdmi->dev = &pdev->dev;
237         platform_set_drvdata(pdev, hdmi);
238
239         if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)
240                 hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
241         else
242                 hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
243         if(hdmi->lcdc == NULL)
244         {
245                 dev_err(hdmi->dev, "can not connect to video source lcdc\n");
246                 ret = -ENXIO;
247                 goto err0;
248         }
249         hdmi->xscale = 100;
250         hdmi->yscale = 100;
251
252
253         hdmi_sys_init(hdmi);
254
255         hdmi->workqueue = create_singlethread_workqueue("hdmi");
256         INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);
257
258 #ifdef CONFIG_HAS_EARLYSUSPEND
259         hdmi->early_suspend.suspend = hdmi_early_suspend;
260         hdmi->early_suspend.resume = hdmi_early_resume;
261         hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;
262         register_early_suspend(&hdmi->early_suspend);
263 #endif
264
265 #ifdef CONFIG_SWITCH
266         hdmi->switch_hdmi.name="hdmi";
267         switch_dev_register(&(hdmi->switch_hdmi));
268 #endif
269
270         spin_lock_init(&hdmi->irq_lock);
271         mutex_init(&hdmi->enable_mutex);
272
273         INIT_DELAYED_WORK(&rk616_hdmi->rk616_delay_work, rk616_delay_work_func);
274
275         /* get the IRQ */
276         // if(rk616->pdata->hdmi_irq != INVALID_GPIO)
277         
278 #ifdef CONFIG_ARCH_RK3026
279         hdmi->hclk = clk_get(NULL,"pclk_hdmi");
280         if(IS_ERR(hdmi->hclk)) {
281                 dev_err(hdmi->dev, "Unable to get hdmi hclk\n");
282                 ret = -ENXIO;
283                 goto err0;
284         }
285         clk_enable(hdmi->hclk);
286         
287         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
288         if (!res) {
289                 dev_err(hdmi->dev, "Unable to get register resource\n");
290                 ret = -ENXIO;
291                 goto err0;
292         }
293         hdmi->regbase_phy = res->start;
294         hdmi->regsize_phy = (res->end - res->start) + 1;
295         mem = request_mem_region(res->start, (res->end - res->start) + 1, pdev->name);
296         if (!mem) {
297                 dev_err(hdmi->dev, "failed to request mem region for hdmi\n");
298                 ret = -ENOENT;
299                 goto err0;
300         }
301         
302         dev_info(hdmi->dev, "res->start = 0x%x\n,res->end = 0x%x\n", res->start, res->end);
303         hdmi->regbase = (int)ioremap(res->start, (res->end - res->start) + 1);
304         if (!hdmi->regbase) {
305                 dev_err(hdmi->dev, "cannot ioremap registers\n");
306                 ret = -ENXIO;
307                 goto err1;
308         }
309         
310         // rk30_mux_api_set(GPIO0A7_I2C3_SDA_HDMI_DDCSDA_NAME, GPIO0A_HDMI_DDCSDA);
311         // rk30_mux_api_set(GPIO0A6_I2C3_SCL_HDMI_DDCSCL_NAME, GPIO0A_HDMI_DDCSCL);
312         // rk30_mux_api_set(GPIO0B7_HDMI_HOTPLUGIN_NAME, GPIO0B_HDMI_HOTPLUGIN);
313         iomux_set(HDMI_DDCSDA);
314         iomux_set(HDMI_DDCSCL);
315         iomux_set(HDMI_HOTPLUGIN);
316         
317         ret = rk616_hdmi_initial(hdmi);
318         /* get the IRQ */
319         hdmi->irq = platform_get_irq(pdev, 0);
320         if(hdmi->irq <= 0) {
321                 dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
322                 hdmi->irq = 0;
323         } else {               
324                 /* request the IRQ */
325                 ret = request_irq(hdmi->irq, rk616_hdmi_irq, 0, dev_name(&pdev->dev), hdmi);
326                 if (ret) {
327                         dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);
328                         goto err1;
329                 }
330         }
331 #else
332         ret = rk616_hdmi_initial(hdmi);
333         if(gpio_is_valid(rk616_hdmi->rk616_drv->pdata->hdmi_irq)) {               
334                 INIT_WORK(&rk616_hdmi->rk616_irq_work_struct, rk616_irq_work_func);
335                 ret = gpio_request(rk616_hdmi->rk616_drv->pdata->hdmi_irq,"rk616_hdmi_irq");
336                 if(ret < 0) {
337                         dev_err(hdmi->dev,"request gpio for rk616 hdmi irq fail\n");
338                 }
339                 gpio_direction_input(rk616_hdmi->rk616_drv->pdata->hdmi_irq);
340                 hdmi->irq = gpio_to_irq(rk616_hdmi->rk616_drv->pdata->hdmi_irq);
341                 if(hdmi->irq <= 0) {
342                         dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
343                         ret = -ENXIO;
344                         goto err1;
345                 }
346                 
347                 /* request the IRQ */
348                 ret = request_irq(hdmi->irq, rk616_hdmi_irq, IRQF_TRIGGER_LOW, dev_name(&pdev->dev), &rk616_hdmi->rk616_irq_work_struct);
349                 if (ret) {
350                         dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);
351                         goto err1;
352                 }
353         } else {                
354                 /* use roll polling method */
355                 hdmi->irq = 0;
356         }
357
358 #endif
359         hdmi_register_display_sysfs(hdmi, NULL);
360
361 #if defined(CONFIG_DEBUG_FS)
362         if(rk616_hdmi->rk616_drv && rk616_hdmi->rk616_drv->debugfs_dir) {
363                 debugfs_create_file("hdmi", S_IRUSR, rk616_hdmi->rk616_drv->debugfs_dir, rk616_hdmi->rk616_drv, &rk616_hdmi_reg_fops);
364         } else {
365                 rk616_hdmi->debugfs_dir = debugfs_create_dir("rk616", NULL);
366                 if (IS_ERR(rk616_hdmi->debugfs_dir)) {
367                         dev_err(hdmi->dev,"failed to create debugfs dir for rk616!\n");
368                 } else {
369                         debugfs_create_file("hdmi", S_IRUSR, rk616_hdmi->debugfs_dir, rk616_hdmi, &rk616_hdmi_reg_fops);
370                 }
371         }
372 #endif
373         // rk616_delay_work_func(NULL);
374         queue_delayed_work(hdmi->workqueue, &rk616_hdmi->rk616_delay_work, msecs_to_jiffies(0));
375         dev_info(hdmi->dev, "rk616 hdmi probe success.\n");
376         return 0;
377 err1:
378 #ifdef CONFIG_SWITCH
379         switch_dev_unregister(&(hdmi->switch_hdmi));
380 #endif
381         hdmi_unregister_display_sysfs(hdmi);
382 #ifdef CONFIG_HAS_EARLYSUSPEND
383         unregister_early_suspend(&hdmi->early_suspend);
384 #endif
385 err0:
386         hdmi_dbg(hdmi->dev, "rk616 hdmi probe error.\n");
387         kfree(hdmi);
388         hdmi = NULL;
389         return ret;
390 }
391
392 static int rk616_hdmi_remove(struct platform_device *pdev)
393 {
394         if(hdmi) {
395                 mutex_lock(&hdmi->enable_mutex);
396                 if(!hdmi->suspend && hdmi->enable && hdmi->irq)
397                         disable_irq(hdmi->irq);
398                 mutex_unlock(&hdmi->enable_mutex);
399                 if (hdmi->irq) {
400                         free_irq(hdmi->irq, NULL);
401                 }
402                 flush_workqueue(hdmi->workqueue);
403                 destroy_workqueue(hdmi->workqueue);
404 #ifdef CONFIG_SWITCH
405                 switch_dev_unregister(&(hdmi->switch_hdmi));
406 #endif
407                 hdmi_unregister_display_sysfs(hdmi);
408 #ifdef CONFIG_HAS_EARLYSUSPEND
409                 unregister_early_suspend(&hdmi->early_suspend);
410 #endif
411                 fb_destroy_modelist(&hdmi->edid.modelist);
412                 if(hdmi->edid.audio)
413                         kfree(hdmi->edid.audio);
414                 if(hdmi->edid.specs)
415                 {
416                         if(hdmi->edid.specs->modedb)
417                                 kfree(hdmi->edid.specs->modedb);
418                         kfree(hdmi->edid.specs);
419                 }
420                 kfree(hdmi);
421                 hdmi = NULL;
422         }
423         hdmi_dbg(hdmi->dev, "rk616 hdmi removed.\n");
424         return 0;
425 }
426
427 static void rk616_hdmi_shutdown(struct platform_device *pdev)
428 {
429         if(hdmi) {
430 #ifdef CONFIG_HAS_EARLYSUSPEND
431                 unregister_early_suspend(&hdmi->early_suspend);
432 #endif 
433                 flush_delayed_work(&hdmi->delay_work);
434                 mutex_lock(&hdmi->enable_mutex);
435                 hdmi->suspend = 1;
436                 if(!hdmi->enable) {
437                         mutex_unlock(&hdmi->enable_mutex);
438                         return;
439                 }
440                 if (hdmi->irq)
441                         disable_irq(hdmi->irq);
442                 mutex_unlock(&hdmi->enable_mutex);
443         }
444         hdmi_dbg(hdmi->dev,  "rk616 hdmi shut down.\n");
445 }
446
447 #if defined(CONFIG_OF)
448 static const struct of_device_id rk616_hdmi_of_match[] = {
449         {.compatible = "rockchip,rk616-hdmi",},
450         {}
451 };
452
453 MODULE_DEVICE_TABLE(of, rk616_hdmi_of_match);
454 #endif
455
456 static struct platform_driver rk616_hdmi_driver = {
457         .probe          = rk616_hdmi_probe,
458         .remove         = rk616_hdmi_remove,
459         .driver         = {
460 #ifdef CONFIG_ARCH_RK3026
461                 .name   = "rk3026-hdmi",
462 #else
463                 .name   = "rk616-hdmi",
464 #endif
465                 .owner  = THIS_MODULE,
466                 .of_match_table = of_match_ptr(rk616_hdmi_of_match),
467         },
468         .shutdown   = rk616_hdmi_shutdown,
469 };
470
471 static int __init rk616_hdmi_init(void)
472 {
473         return platform_driver_register(&rk616_hdmi_driver);
474 }
475
476 static void __exit rk616_hdmi_exit(void)
477 {
478         platform_driver_unregister(&rk616_hdmi_driver);
479 }
480
481
482 //fs_initcall(rk616_hdmi_init);
483 late_initcall(rk616_hdmi_init);
484 module_exit(rk616_hdmi_exit);