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>
20 #include <linux/rk_fb.h>
22 #if defined(CONFIG_DEBUG_FS)
24 #include <linux/debugfs.h>
25 #include <linux/seq_file.h>
28 #include "rk616_hdmi.h"
29 #include "rk616_hdmi_hw.h"
31 extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent);
32 extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi);
34 struct hdmi *hdmi = NULL;
36 #if defined(CONFIG_DEBUG_FS)
37 static int rk616_hdmi_reg_show(struct seq_file *s, void *v)
41 struct mfd_rk616 *rk616 = s->private;
44 dev_err(rk616->dev,"no mfd rk616!\n");
48 seq_printf(s, "\n>>>rk616_ctl reg");
49 for (i = 0; i < 16; i++) {
50 seq_printf(s, " %2x", i);
52 seq_printf(s, "\n-----------------------------------------------------------------");
54 for(i=0;i<= (PHY_PRE_DIV_RATIO << 2);i+=4)
56 rk616->read_dev(rk616,RK616_HDMI_BASE + i,&val);
57 //seq_printf(s,"reg%02x>>0x%08x\n",(i>>2),val);
59 seq_printf(s,"\n>>>rk616_ctl %2x:",i>>2);
60 seq_printf(s," %02x",val);
64 seq_printf(s, "\n-----------------------------------------------------------------\n");
69 static ssize_t rk616_hdmi_reg_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
71 struct mfd_rk616 *rk616 = file->f_path.dentry->d_inode->i_private;
75 if (copy_from_user(kbuf, buf, count))
77 sscanf(kbuf, "%x%x", ®, &val);
78 if ((reg < 0) || (reg > 0xed))
80 printk("it is no hdmi reg\n");
83 printk("/**********rk616 reg config******/");
84 printk("\n reg=%x val=%x\n", reg, val);
86 //sscanf(kbuf, "%x%x", ®, &val);
87 dev_dbg(rk616->dev,"%s:reg:0x%04x val:0x%08x\n",__func__,reg, val);
88 rk616->write_dev(rk616, RK616_HDMI_BASE + (reg << 2), &val);
93 static int rk616_hdmi_reg_open(struct inode *inode, struct file *file)
95 struct mfd_rk616 *rk616 = inode->i_private;
96 return single_open(file,rk616_hdmi_reg_show,rk616);
99 static const struct file_operations rk616_hdmi_reg_fops = {
100 .owner = THIS_MODULE,
101 .open = rk616_hdmi_reg_open,
103 .write = rk616_hdmi_reg_write,
105 .release = single_release,
109 int rk616_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
110 void (*hdcp_irq_cb)(int status),
111 int (*hdcp_power_on_cb)(void),
112 void (*hdcp_power_off_cb)(void))
115 return HDMI_ERROR_FALSE;
117 hdmi->hdcp_cb = hdcp_cb;
118 hdmi->hdcp_irq_cb = hdcp_irq_cb;
119 hdmi->hdcp_power_on_cb = hdcp_power_on_cb;
120 hdmi->hdcp_power_off_cb = hdcp_power_off_cb;
122 return HDMI_ERROR_SUCESS;
125 #ifdef CONFIG_HAS_EARLYSUSPEND
126 static void hdmi_early_suspend(struct early_suspend *h)
128 hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);
130 flush_delayed_work(&hdmi->delay_work);
131 mutex_lock(&hdmi->enable_mutex);
134 mutex_unlock(&hdmi->enable_mutex);
139 disable_irq(hdmi->irq);
141 mutex_unlock(&hdmi->enable_mutex);
142 hdmi->command = HDMI_CONFIG_ENABLE;
143 init_completion(&hdmi->complete);
145 queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
146 wait_for_completion_interruptible_timeout(&hdmi->complete,
147 msecs_to_jiffies(5000));
148 flush_delayed_work(&hdmi->delay_work);
153 static void hdmi_early_resume(struct early_suspend *h)
155 struct rk616_hdmi *rk616_hdmi;
157 rk616_hdmi = container_of(hdmi, struct rk616_hdmi, g_hdmi);
158 hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");
160 mutex_lock(&hdmi->enable_mutex);
163 rk616_hdmi_initial();
164 if(hdmi->enable && hdmi->irq) {
165 enable_irq(hdmi->irq);
170 if (rk616_hdmi->rk616_drv->pdata->hdmi_irq == INVALID_GPIO)
171 queue_delayed_work(hdmi->workqueue, &rk616_hdmi->rk616_delay_work, 100);
173 queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
174 mutex_unlock(&hdmi->enable_mutex);
178 static void rk616_delay_work_func(struct work_struct *work)
180 struct rk616_hdmi *rk616_hdmi;
182 rk616_hdmi = container_of(hdmi, struct rk616_hdmi, g_hdmi);
184 if(hdmi->suspend == 0) {
185 if(hdmi->enable == 1) {
190 if (rk616_hdmi->rk616_drv->pdata->hdmi_irq == INVALID_GPIO) {
191 queue_delayed_work(hdmi->workqueue, &rk616_hdmi->rk616_delay_work, 100);
196 static void rk616_irq_work_func(struct work_struct *work)
198 if((hdmi->suspend == 0) && (hdmi->enable == 1)) {
201 dev_info(hdmi->dev, "func: %s, enable_irq\n", __func__);
202 enable_irq(hdmi->irq);
206 static irqreturn_t rk616_hdmi_irq(int irq, void *dev_id)
208 struct work_struct *rk616_irq_work_struct;
210 rk616_irq_work_struct = dev_id;
211 disable_irq_nosync(hdmi->irq);
212 //printk(KERN_INFO "rk616_hdmi_irq irq triggered.\n");
213 queue_work(hdmi->workqueue, rk616_irq_work_struct);
217 static int __devinit rk616_hdmi_probe (struct platform_device *pdev)
220 struct rk616_hdmi *rk616_hdmi;
222 struct mfd_rk616 *rk616 = dev_get_drvdata(pdev->dev.parent);
225 dev_err(&pdev->dev,"null mfd device rk616!\n");
229 rk616_hdmi = devm_kzalloc(&pdev->dev, sizeof(*rk616_hdmi), GFP_KERNEL);
232 dev_err(&pdev->dev, ">>rk616_hdmi kmalloc fail!");
235 hdmi = &rk616_hdmi->g_hdmi;
236 rk616_hdmi->rk616_drv = rk616;
238 hdmi->dev = &pdev->dev;
239 platform_set_drvdata(pdev, hdmi);
241 if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)
242 hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
244 hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
245 if(hdmi->lcdc == NULL)
247 dev_err(hdmi->dev, "can not connect to video source lcdc\n");
254 ret = rk616_hdmi_initial();
258 hdmi->workqueue = create_singlethread_workqueue("hdmi");
259 INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);
261 #ifdef CONFIG_HAS_EARLYSUSPEND
262 hdmi->early_suspend.suspend = hdmi_early_suspend;
263 hdmi->early_suspend.resume = hdmi_early_resume;
264 hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;
265 register_early_suspend(&hdmi->early_suspend);
268 hdmi_register_display_sysfs(hdmi, NULL);
270 hdmi->switch_hdmi.name="hdmi";
271 switch_dev_register(&(hdmi->switch_hdmi));
274 spin_lock_init(&hdmi->irq_lock);
275 mutex_init(&hdmi->enable_mutex);
277 INIT_DELAYED_WORK(&rk616_hdmi->rk616_delay_work, rk616_delay_work_func);
280 if(rk616->pdata->hdmi_irq != INVALID_GPIO)
282 INIT_WORK(&rk616_hdmi->rk616_irq_work_struct, rk616_irq_work_func);
283 ret = gpio_request(rk616->pdata->hdmi_irq,"rk616_hdmi_irq");
286 dev_err(hdmi->dev,"request gpio for rk616 hdmi irq fail\n");
288 gpio_direction_input(rk616->pdata->hdmi_irq);
289 hdmi->irq = gpio_to_irq(rk616->pdata->hdmi_irq);
291 dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
296 /* request the IRQ */
297 ret = request_irq(hdmi->irq, rk616_hdmi_irq, IRQF_TRIGGER_LOW, dev_name(&pdev->dev), &rk616_hdmi->rk616_irq_work_struct);
300 dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);
305 /* use roll polling method */
308 #if defined(CONFIG_DEBUG_FS)
309 if(rk616->debugfs_dir)
311 debugfs_create_file("hdmi", S_IRUSR,rk616->debugfs_dir,rk616,&rk616_hdmi_reg_fops);
314 // rk616_delay_work_func(NULL);
315 queue_delayed_work(hdmi->workqueue, &rk616_hdmi->rk616_delay_work, msecs_to_jiffies(0));
316 dev_info(hdmi->dev, "rk616 hdmi probe success.\n");
320 switch_dev_unregister(&(hdmi->switch_hdmi));
322 hdmi_unregister_display_sysfs(hdmi);
323 #ifdef CONFIG_HAS_EARLYSUSPEND
324 unregister_early_suspend(&hdmi->early_suspend);
327 hdmi_dbg(hdmi->dev, "rk616 hdmi probe error.\n");
333 static int __devexit rk616_hdmi_remove(struct platform_device *pdev)
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);
341 free_irq(hdmi->irq, NULL);
343 flush_workqueue(hdmi->workqueue);
344 destroy_workqueue(hdmi->workqueue);
346 switch_dev_unregister(&(hdmi->switch_hdmi));
348 hdmi_unregister_display_sysfs(hdmi);
349 #ifdef CONFIG_HAS_EARLYSUSPEND
350 unregister_early_suspend(&hdmi->early_suspend);
352 fb_destroy_modelist(&hdmi->edid.modelist);
354 kfree(hdmi->edid.audio);
357 if(hdmi->edid.specs->modedb)
358 kfree(hdmi->edid.specs->modedb);
359 kfree(hdmi->edid.specs);
364 hdmi_dbg(hdmi->dev, "rk616 hdmi removed.\n");
368 static void rk616_hdmi_shutdown(struct platform_device *pdev)
371 #ifdef CONFIG_HAS_EARLYSUSPEND
372 unregister_early_suspend(&hdmi->early_suspend);
374 flush_delayed_work(&hdmi->delay_work);
375 mutex_lock(&hdmi->enable_mutex);
378 mutex_unlock(&hdmi->enable_mutex);
382 disable_irq(hdmi->irq);
383 mutex_unlock(&hdmi->enable_mutex);
385 hdmi_dbg(hdmi->dev, "rk616 hdmi shut down.\n");
388 static struct platform_driver rk616_hdmi_driver = {
389 .probe = rk616_hdmi_probe,
390 .remove = __devexit_p(rk616_hdmi_remove),
392 .name = "rk616-hdmi",
393 .owner = THIS_MODULE,
395 .shutdown = rk616_hdmi_shutdown,
398 static int __init rk616_hdmi_init(void)
400 return platform_driver_register(&rk616_hdmi_driver);
403 static void __exit rk616_hdmi_exit(void)
405 platform_driver_unregister(&rk616_hdmi_driver);
409 //fs_initcall(rk616_hdmi_init);
410 late_initcall(rk616_hdmi_init);
411 module_exit(rk616_hdmi_exit);