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