add rk616 hdmi roll polling method when hdmi_irq = INVALID_GPIO
[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 <mach/gpio.h>
19 #include <mach/iomux.h>
20
21 #if defined(CONFIG_DEBUG_FS)
22 #include <linux/fs.h>
23 #include <linux/debugfs.h>
24 #include <linux/seq_file.h>
25 #endif
26
27 #include "rk616_hdmi.h"
28 #include "rk616_hdmi_hw.h"
29
30 struct hdmi *hdmi = NULL;
31 struct mfd_rk616 *g_rk616_hdmi = NULL;
32 // struct work_struct   g_rk616_delay_work;
33 struct delayed_work     g_rk616_delay_work;
34
35 // extern void hdmi_irq(void);
36 extern void rk616_hdmi_work(void);
37 extern void hdmi_work(struct work_struct *work);
38 extern struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name);
39 extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent);
40 extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi);
41
42
43 #if defined(CONFIG_DEBUG_FS)
44 static int rk616_hdmi_reg_show(struct seq_file *s, void *v)
45 {
46         int i = 0;
47         u32 val = 0;
48         struct mfd_rk616 *rk616 = s->private;
49         if(!rk616)
50         {
51                 dev_err(rk616->dev,"no mfd rk616!\n");
52                 return 0;
53         }
54
55
56         //seq_printf(s,"------>gpio = %d \n",gpio_get_value(rk616->pdata->hdmi_irq));
57         seq_printf(s, "\n>>>rk616_ctl reg");
58         for (i = 0; i < 16; i++) {
59                 seq_printf(s, " %2x", i);
60         }
61         seq_printf(s, "\n-----------------------------------------------------------------");
62         
63         for(i=0;i<= (PHY_PRE_DIV_RATIO << 2);i+=4)
64         {
65                 rk616->read_dev(rk616,RK616_HDMI_BASE + i,&val);
66                 //seq_printf(s,"reg%02x>>0x%08x\n",(i>>2),val);
67                 if((i>>2)%16==0)
68                         seq_printf(s,"\n>>>rk616_ctl %2x:",i>>2);
69                 seq_printf(s," %02x",val);
70
71         }
72         
73         seq_printf(s, "\n-----------------------------------------------------------------\n");
74         
75         return 0;
76 }
77
78 static ssize_t rk616_hdmi_reg_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
79
80         struct mfd_rk616 *rk616 = file->f_path.dentry->d_inode->i_private;
81         u32 reg;
82         u32 val;
83         char kbuf[25];
84         if (copy_from_user(kbuf, buf, count))
85                 return -EFAULT;
86         sscanf(kbuf, "%x%x", &reg, &val);
87         if ((reg < 0) || (reg > 0xed))
88         {
89                 printk("it is no hdmi reg\n");
90                 return count;
91         }
92         printk("/**********rk616 reg config******/");
93         printk("\n reg=%x val=%x\n", reg, val);
94
95         //sscanf(kbuf, "%x%x", &reg, &val);
96         dev_dbg(rk616->dev,"%s:reg:0x%04x val:0x%08x\n",__func__,reg, val);
97         rk616->write_dev(rk616, RK616_HDMI_BASE + (reg << 2), &val);
98
99         return count;
100 }
101
102 static int rk616_hdmi_reg_open(struct inode *inode, struct file *file)
103 {
104         struct mfd_rk616 *rk616 = inode->i_private;
105         return single_open(file,rk616_hdmi_reg_show,rk616);
106 }
107
108 static const struct file_operations rk616_hdmi_reg_fops = {
109         .owner          = THIS_MODULE,
110         .open           = rk616_hdmi_reg_open,
111         .read           = seq_read,
112         .write          = rk616_hdmi_reg_write,
113         .llseek         = seq_lseek,
114         .release        = single_release,
115 };
116 #endif
117
118 int rk616_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
119                 void (*hdcp_irq_cb)(int status),
120                 int (*hdcp_power_on_cb)(void),
121                 void (*hdcp_power_off_cb)(void))
122 {
123         if(hdmi == NULL)
124                 return HDMI_ERROR_FALSE;
125
126         hdmi->hdcp_cb = hdcp_cb;
127         hdmi->hdcp_irq_cb = hdcp_irq_cb;
128         hdmi->hdcp_power_on_cb = hdcp_power_on_cb;
129         hdmi->hdcp_power_off_cb = hdcp_power_off_cb;
130
131         return HDMI_ERROR_SUCESS;
132 }
133
134 #ifdef CONFIG_HAS_EARLYSUSPEND
135 static void hdmi_early_suspend(struct early_suspend *h)
136 {
137         hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);
138
139         flush_delayed_work(&hdmi->delay_work);  
140         mutex_lock(&hdmi->enable_mutex);
141         hdmi->suspend = 1;
142         if(!hdmi->enable) {
143                 mutex_unlock(&hdmi->enable_mutex);
144                 return;
145         }
146
147         if (hdmi->irq)
148                 disable_irq(hdmi->irq);
149
150         mutex_unlock(&hdmi->enable_mutex);
151         hdmi->command = HDMI_CONFIG_ENABLE;
152         init_completion(&hdmi->complete);
153         hdmi->wait = 1;
154         queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
155         wait_for_completion_interruptible_timeout(&hdmi->complete,
156                         msecs_to_jiffies(5000));
157         flush_delayed_work(&hdmi->delay_work);
158
159         return;
160 }
161
162 static void hdmi_early_resume(struct early_suspend *h)
163 {
164         hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");
165         mutex_lock(&hdmi->enable_mutex);
166
167         hdmi->suspend = 0;
168         rk616_hdmi_initial();
169         if(hdmi->enable && hdmi->irq) {
170                 enable_irq(hdmi->irq);
171                 // hdmi_irq();
172                 rk616_hdmi_work();
173         }
174         if (g_rk616_hdmi->pdata->hdmi_irq == INVALID_GPIO) 
175                 queue_delayed_work(hdmi->workqueue, &g_rk616_delay_work, 100);
176
177         queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));   
178         mutex_unlock(&hdmi->enable_mutex);
179         return;
180 }
181 #endif
182 static void rk616_delay_work_func(struct work_struct *work)
183 {
184         if(hdmi->suspend == 0) {
185                 if(hdmi->enable == 1) {
186                         //hdmi_irq();
187                         rk616_hdmi_work();
188                 }
189
190                 if (g_rk616_hdmi->pdata->hdmi_irq == INVALID_GPIO) {
191                         queue_delayed_work(hdmi->workqueue, &g_rk616_delay_work, 100);
192                 }
193         }
194 }
195
196 #if 1
197 static irqreturn_t rk616_hdmi_irq(int irq, void *dev_id)
198 {
199         printk(KERN_INFO "rk616_hdmi_irq irq triggered.\n");
200         queue_delayed_work(hdmi->workqueue, &g_rk616_delay_work, 0);
201         return IRQ_HANDLED;
202 }
203 #endif
204 static int __devinit rk616_hdmi_probe (struct platform_device *pdev)
205 {
206         int ret;
207
208         struct mfd_rk616 *rk616 = dev_get_drvdata(pdev->dev.parent);
209         if(!rk616)
210         {
211                 dev_err(&pdev->dev,"null mfd device rk616!\n");
212                 return -ENODEV;
213         }
214
215         g_rk616_hdmi = rk616;
216
217         hdmi = kmalloc(sizeof(struct hdmi), GFP_KERNEL);
218         if(!hdmi)
219         {
220                 dev_err(&pdev->dev, ">>rk616 hdmi kmalloc fail!");
221                 return -ENOMEM;
222         }
223         memset(hdmi, 0, sizeof(struct hdmi));
224         hdmi->dev = &pdev->dev;
225         platform_set_drvdata(pdev, hdmi);
226
227         if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)
228                 hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
229         else
230                 hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
231         if(hdmi->lcdc == NULL)
232         {
233                 dev_err(hdmi->dev, "can not connect to video source lcdc\n");
234                 ret = -ENXIO;
235                 goto err0;
236         }
237         hdmi->xscale = 100;
238         hdmi->yscale = 100;
239
240         ret = rk616_hdmi_initial();
241
242         hdmi_sys_init();
243
244         hdmi->workqueue = create_singlethread_workqueue("hdmi");
245         INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);
246
247 #ifdef CONFIG_HAS_EARLYSUSPEND
248         hdmi->early_suspend.suspend = hdmi_early_suspend;
249         hdmi->early_suspend.resume = hdmi_early_resume;
250         hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;
251         register_early_suspend(&hdmi->early_suspend);
252 #endif
253
254         hdmi_register_display_sysfs(hdmi, NULL);
255 #ifdef CONFIG_SWITCH
256         hdmi->switch_hdmi.name="hdmi";
257         switch_dev_register(&(hdmi->switch_hdmi));
258 #endif
259
260         spin_lock_init(&hdmi->irq_lock);
261         mutex_init(&hdmi->enable_mutex);
262
263         INIT_DELAYED_WORK(&g_rk616_delay_work, rk616_delay_work_func);
264         /* get the IRQ */
265         if(rk616->pdata->hdmi_irq != INVALID_GPIO)
266         {
267                 // INIT_DELAYED_WORK(&g_rk616_delay_work, rk616_delay_work_func);
268                 ret = gpio_request(rk616->pdata->hdmi_irq,"rk616_hdmi_irq");
269                 if(ret < 0)
270                 {
271                         dev_err(hdmi->dev,"request gpio for rk616 hdmi irq fail\n");
272                 }
273                 gpio_direction_input(rk616->pdata->hdmi_irq);
274                 hdmi->irq = gpio_to_irq(rk616->pdata->hdmi_irq);
275                 if(hdmi->irq <= 0) {
276                         dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
277                         ret = -ENXIO;
278                         goto err1;
279                 }
280
281                 /* request the IRQ */
282                 ret = request_irq(hdmi->irq,rk616_hdmi_irq,IRQF_TRIGGER_FALLING,dev_name(&pdev->dev), hdmi);
283                 if (ret)
284                 {
285                         dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);
286                         goto err1;
287                 }
288         } else {
289
290                 /* use roll polling method */
291                 hdmi->irq = 0;
292         }
293 #if defined(CONFIG_DEBUG_FS)
294         if(rk616->debugfs_dir)
295         {
296                 debugfs_create_file("hdmi", S_IRUSR,rk616->debugfs_dir,rk616,&rk616_hdmi_reg_fops);
297         }
298 #endif
299         // rk616_delay_work_func(NULL);
300         queue_delayed_work(hdmi->workqueue, &g_rk616_delay_work, msecs_to_jiffies(0));  
301         dev_info(hdmi->dev, "rk616 hdmi probe success.\n");
302         return 0;
303 err1:
304 #ifdef CONFIG_SWITCH
305         switch_dev_unregister(&(hdmi->switch_hdmi));
306 #endif
307         hdmi_unregister_display_sysfs(hdmi);
308 #ifdef CONFIG_HAS_EARLYSUSPEND
309         unregister_early_suspend(&hdmi->early_suspend);
310 #endif
311 err0:
312         hdmi_dbg(hdmi->dev, "rk616 hdmi probe error.\n");
313         kfree(hdmi);
314         hdmi = NULL;
315         return ret;
316 }
317
318 static int __devexit rk616_hdmi_remove(struct platform_device *pdev)
319 {
320         if(hdmi) {
321                 mutex_lock(&hdmi->enable_mutex);
322                 if(!hdmi->suspend && hdmi->enable && hdmi->irq)
323                         disable_irq(hdmi->irq);
324                 mutex_unlock(&hdmi->enable_mutex);
325                 if (hdmi->irq) {
326                         free_irq(hdmi->irq, NULL);
327                 }
328                 flush_workqueue(hdmi->workqueue);
329                 destroy_workqueue(hdmi->workqueue);
330 #ifdef CONFIG_SWITCH
331                 switch_dev_unregister(&(hdmi->switch_hdmi));
332 #endif
333                 hdmi_unregister_display_sysfs(hdmi);
334 #ifdef CONFIG_HAS_EARLYSUSPEND
335                 unregister_early_suspend(&hdmi->early_suspend);
336 #endif
337                 fb_destroy_modelist(&hdmi->edid.modelist);
338                 if(hdmi->edid.audio)
339                         kfree(hdmi->edid.audio);
340                 if(hdmi->edid.specs)
341                 {
342                         if(hdmi->edid.specs->modedb)
343                                 kfree(hdmi->edid.specs->modedb);
344                         kfree(hdmi->edid.specs);
345                 }
346                 kfree(hdmi);
347                 hdmi = NULL;
348         }
349         printk(KERN_INFO "rk616 hdmi removed.\n");
350         return 0;
351 }
352
353 static void rk616_hdmi_shutdown(struct platform_device *pdev)
354 {
355         if(hdmi) {
356 #ifdef CONFIG_HAS_EARLYSUSPEND
357                 unregister_early_suspend(&hdmi->early_suspend);
358 #endif
359         }
360         printk(KERN_INFO "rk616 hdmi shut down.\n");
361 }
362
363 static struct platform_driver rk616_hdmi_driver = {
364         .probe          = rk616_hdmi_probe,
365         .remove         = __devexit_p(rk616_hdmi_remove),
366         .driver         = {
367                 .name   = "rk616-hdmi",
368                 .owner  = THIS_MODULE,
369         },
370         .shutdown   = rk616_hdmi_shutdown,
371 };
372
373 static int __init rk616_hdmi_init(void)
374 {
375         return platform_driver_register(&rk616_hdmi_driver);
376 }
377
378 static void __exit rk616_hdmi_exit(void)
379 {
380         platform_driver_unregister(&rk616_hdmi_driver);
381 }
382
383
384 //fs_initcall(rk616_hdmi_init);
385 late_initcall(rk616_hdmi_init);
386 module_exit(rk616_hdmi_exit);