1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/errno.h>
4 #include <linux/string.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>
16 #include <mach/board.h>
18 #include <mach/gpio.h>
19 #include <mach/iomux.h>
21 #if defined(CONFIG_DEBUG_FS)
23 #include <linux/debugfs.h>
24 #include <linux/seq_file.h>
27 #include "rk616_hdmi.h"
28 #include "rk616_hdmi_hw.h"
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;
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);
43 #if defined(CONFIG_DEBUG_FS)
44 static int rk616_hdmi_reg_show(struct seq_file *s, void *v)
48 struct mfd_rk616 *rk616 = s->private;
51 dev_err(rk616->dev,"no mfd rk616!\n");
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);
61 seq_printf(s, "\n-----------------------------------------------------------------");
63 for(i=0;i<= (PHY_PRE_DIV_RATIO << 2);i+=4)
65 rk616->read_dev(rk616,RK616_HDMI_BASE + i,&val);
66 //seq_printf(s,"reg%02x>>0x%08x\n",(i>>2),val);
68 seq_printf(s,"\n>>>rk616_ctl %2x:",i>>2);
69 seq_printf(s," %02x",val);
73 seq_printf(s, "\n-----------------------------------------------------------------\n");
78 static ssize_t rk616_hdmi_reg_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
80 struct mfd_rk616 *rk616 = file->f_path.dentry->d_inode->i_private;
84 if (copy_from_user(kbuf, buf, count))
86 sscanf(kbuf, "%x%x", ®, &val);
87 if ((reg < 0) || (reg > 0xed))
89 printk("it is no hdmi reg\n");
92 printk("/**********rk616 reg config******/");
93 printk("\n reg=%x val=%x\n", reg, val);
95 //sscanf(kbuf, "%x%x", ®, &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);
102 static int rk616_hdmi_reg_open(struct inode *inode, struct file *file)
104 struct mfd_rk616 *rk616 = inode->i_private;
105 return single_open(file,rk616_hdmi_reg_show,rk616);
108 static const struct file_operations rk616_hdmi_reg_fops = {
109 .owner = THIS_MODULE,
110 .open = rk616_hdmi_reg_open,
112 .write = rk616_hdmi_reg_write,
114 .release = single_release,
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))
124 return HDMI_ERROR_FALSE;
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;
131 return HDMI_ERROR_SUCESS;
134 #ifdef CONFIG_HAS_EARLYSUSPEND
135 static void hdmi_early_suspend(struct early_suspend *h)
137 hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);
139 flush_delayed_work(&hdmi->delay_work);
140 mutex_lock(&hdmi->enable_mutex);
143 mutex_unlock(&hdmi->enable_mutex);
148 disable_irq(hdmi->irq);
150 mutex_unlock(&hdmi->enable_mutex);
151 hdmi->command = HDMI_CONFIG_ENABLE;
152 init_completion(&hdmi->complete);
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);
162 static void hdmi_early_resume(struct early_suspend *h)
164 hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");
165 mutex_lock(&hdmi->enable_mutex);
168 rk616_hdmi_initial();
169 if(hdmi->enable && hdmi->irq) {
170 enable_irq(hdmi->irq);
174 if (g_rk616_hdmi->pdata->hdmi_irq == INVALID_GPIO)
175 queue_delayed_work(hdmi->workqueue, &g_rk616_delay_work, 100);
177 queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
178 mutex_unlock(&hdmi->enable_mutex);
182 static void rk616_delay_work_func(struct work_struct *work)
184 if(hdmi->suspend == 0) {
185 if(hdmi->enable == 1) {
190 if (g_rk616_hdmi->pdata->hdmi_irq == INVALID_GPIO) {
191 queue_delayed_work(hdmi->workqueue, &g_rk616_delay_work, 100);
197 static irqreturn_t rk616_hdmi_irq(int irq, void *dev_id)
199 printk(KERN_INFO "rk616_hdmi_irq irq triggered.\n");
200 queue_delayed_work(hdmi->workqueue, &g_rk616_delay_work, 0);
204 static int __devinit rk616_hdmi_probe (struct platform_device *pdev)
208 struct mfd_rk616 *rk616 = dev_get_drvdata(pdev->dev.parent);
211 dev_err(&pdev->dev,"null mfd device rk616!\n");
215 g_rk616_hdmi = rk616;
217 hdmi = kmalloc(sizeof(struct hdmi), GFP_KERNEL);
220 dev_err(&pdev->dev, ">>rk616 hdmi kmalloc fail!");
223 memset(hdmi, 0, sizeof(struct hdmi));
224 hdmi->dev = &pdev->dev;
225 platform_set_drvdata(pdev, hdmi);
227 if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)
228 hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
230 hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
231 if(hdmi->lcdc == NULL)
233 dev_err(hdmi->dev, "can not connect to video source lcdc\n");
240 ret = rk616_hdmi_initial();
244 hdmi->workqueue = create_singlethread_workqueue("hdmi");
245 INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);
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);
254 hdmi_register_display_sysfs(hdmi, NULL);
256 hdmi->switch_hdmi.name="hdmi";
257 switch_dev_register(&(hdmi->switch_hdmi));
260 spin_lock_init(&hdmi->irq_lock);
261 mutex_init(&hdmi->enable_mutex);
263 INIT_DELAYED_WORK(&g_rk616_delay_work, rk616_delay_work_func);
265 if(rk616->pdata->hdmi_irq != INVALID_GPIO)
267 // INIT_DELAYED_WORK(&g_rk616_delay_work, rk616_delay_work_func);
268 ret = gpio_request(rk616->pdata->hdmi_irq,"rk616_hdmi_irq");
271 dev_err(hdmi->dev,"request gpio for rk616 hdmi irq fail\n");
273 gpio_direction_input(rk616->pdata->hdmi_irq);
274 hdmi->irq = gpio_to_irq(rk616->pdata->hdmi_irq);
276 dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
281 /* request the IRQ */
282 ret = request_irq(hdmi->irq,rk616_hdmi_irq,IRQF_TRIGGER_FALLING,dev_name(&pdev->dev), hdmi);
285 dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);
290 /* use roll polling method */
293 #if defined(CONFIG_DEBUG_FS)
294 if(rk616->debugfs_dir)
296 debugfs_create_file("hdmi", S_IRUSR,rk616->debugfs_dir,rk616,&rk616_hdmi_reg_fops);
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");
305 switch_dev_unregister(&(hdmi->switch_hdmi));
307 hdmi_unregister_display_sysfs(hdmi);
308 #ifdef CONFIG_HAS_EARLYSUSPEND
309 unregister_early_suspend(&hdmi->early_suspend);
312 hdmi_dbg(hdmi->dev, "rk616 hdmi probe error.\n");
318 static int __devexit rk616_hdmi_remove(struct platform_device *pdev)
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);
326 free_irq(hdmi->irq, NULL);
328 flush_workqueue(hdmi->workqueue);
329 destroy_workqueue(hdmi->workqueue);
331 switch_dev_unregister(&(hdmi->switch_hdmi));
333 hdmi_unregister_display_sysfs(hdmi);
334 #ifdef CONFIG_HAS_EARLYSUSPEND
335 unregister_early_suspend(&hdmi->early_suspend);
337 fb_destroy_modelist(&hdmi->edid.modelist);
339 kfree(hdmi->edid.audio);
342 if(hdmi->edid.specs->modedb)
343 kfree(hdmi->edid.specs->modedb);
344 kfree(hdmi->edid.specs);
349 printk(KERN_INFO "rk616 hdmi removed.\n");
353 static void rk616_hdmi_shutdown(struct platform_device *pdev)
356 #ifdef CONFIG_HAS_EARLYSUSPEND
357 unregister_early_suspend(&hdmi->early_suspend);
359 flush_delayed_work(&hdmi->delay_work);
360 mutex_lock(&hdmi->enable_mutex);
363 mutex_unlock(&hdmi->enable_mutex);
367 disable_irq(hdmi->irq);
368 mutex_unlock(&hdmi->enable_mutex);
370 printk(KERN_INFO "rk616 hdmi shut down.\n");
373 static struct platform_driver rk616_hdmi_driver = {
374 .probe = rk616_hdmi_probe,
375 .remove = __devexit_p(rk616_hdmi_remove),
377 .name = "rk616-hdmi",
378 .owner = THIS_MODULE,
380 .shutdown = rk616_hdmi_shutdown,
383 static int __init rk616_hdmi_init(void)
385 return platform_driver_register(&rk616_hdmi_driver);
388 static void __exit rk616_hdmi_exit(void)
390 platform_driver_unregister(&rk616_hdmi_driver);
394 //fs_initcall(rk616_hdmi_init);
395 late_initcall(rk616_hdmi_init);
396 module_exit(rk616_hdmi_exit);