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>
17 //#include <mach/io.h>
18 #include <linux/of_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 seq_printf(s, "\n>>>rk616_ctl reg");
42 for (i = 0; i < 16; i++) {
43 seq_printf(s, " %2x", i);
45 seq_printf(s, "\n-----------------------------------------------------------------");
47 for(i=0; i<= PHY_PRE_DIV_RATIO; i++) {
50 seq_printf(s,"\n>>>rk616_ctl %2x:", i);
51 seq_printf(s," %02x",val);
54 seq_printf(s, "\n-----------------------------------------------------------------\n");
59 static ssize_t rk616_hdmi_reg_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
64 if (copy_from_user(kbuf, buf, count))
66 sscanf(kbuf, "%x%x", ®, &val);
67 if ((reg < 0) || (reg > 0xed)) {
68 dev_info(hdmi->dev, "it is no hdmi reg\n");
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);
78 static int rk616_hdmi_reg_open(struct inode *inode, struct file *file)
80 struct mfd_rk616 *rk616 = inode->i_private;
81 return single_open(file,rk616_hdmi_reg_show,rk616);
84 static const struct file_operations rk616_hdmi_reg_fops = {
86 .open = rk616_hdmi_reg_open,
88 .write = rk616_hdmi_reg_write,
90 .release = single_release,
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))
100 return HDMI_ERROR_FALSE;
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;
107 return HDMI_ERROR_SUCESS;
110 #ifdef CONFIG_HAS_EARLYSUSPEND
111 static void hdmi_early_suspend(struct early_suspend *h)
113 hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);
115 flush_delayed_work(&hdmi->delay_work);
116 mutex_lock(&hdmi->enable_mutex);
119 mutex_unlock(&hdmi->enable_mutex);
124 disable_irq(hdmi->irq);
126 mutex_unlock(&hdmi->enable_mutex);
127 hdmi->command = HDMI_CONFIG_ENABLE;
128 init_completion(&hdmi->complete);
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);
138 static void hdmi_early_resume(struct early_suspend *h)
140 struct rk616_hdmi *rk616_hdmi;
142 rk616_hdmi = container_of(hdmi, struct rk616_hdmi, g_hdmi);
143 hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");
145 mutex_lock(&hdmi->enable_mutex);
148 rk616_hdmi_initial(hdmi);
149 if(hdmi->enable && hdmi->irq) {
150 enable_irq(hdmi->irq);
152 rk616_hdmi_work(hdmi);
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);
161 static void rk616_delay_work_func(struct work_struct *work)
163 struct rk616_hdmi *rk616_hdmi;
165 rk616_hdmi = container_of(hdmi, struct rk616_hdmi, g_hdmi);
167 if(hdmi->suspend == 0) {
168 if(hdmi->enable == 1) {
170 rk616_hdmi_work(hdmi);
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);
179 static void __maybe_unused rk616_irq_work_func(struct work_struct *work)
181 if((hdmi->suspend == 0) && (hdmi->enable == 1)) {
182 rk616_hdmi_work(hdmi);
184 dev_info(hdmi->dev, "func: %s, enable_irq\n", __func__);
185 enable_irq(hdmi->irq);
188 static irqreturn_t rk616_hdmi_irq(int irq, void *dev_id)
190 struct work_struct *rk616_irq_work_struct;
191 struct rk616_hdmi *rk616_hdmi;
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);
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);
208 static int rk616_hdmi_probe(struct platform_device *pdev)
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;
216 rk616_hdmi = devm_kzalloc(&pdev->dev, sizeof(*rk616_hdmi), GFP_KERNEL);
219 dev_err(&pdev->dev, ">>rk616_hdmi kmalloc fail!");
222 hdmi = &rk616_hdmi->g_hdmi;
224 #ifdef CONFIG_ARCH_RK3026
225 rk616_hdmi->rk616_drv = NULL;
227 rk616_hdmi->rk616_drv = dev_get_drvdata(pdev->dev.parent);
228 if(!(rk616_hdmi->rk616_drv))
230 dev_err(&pdev->dev,"null mfd device rk616!\n");
236 hdmi->dev = &pdev->dev;
237 platform_set_drvdata(pdev, hdmi);
239 if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)
240 hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
242 hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
243 if(hdmi->lcdc == NULL)
245 dev_err(hdmi->dev, "can not connect to video source lcdc\n");
255 hdmi->workqueue = create_singlethread_workqueue("hdmi");
256 INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);
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);
266 hdmi->switch_hdmi.name="hdmi";
267 switch_dev_register(&(hdmi->switch_hdmi));
270 spin_lock_init(&hdmi->irq_lock);
271 mutex_init(&hdmi->enable_mutex);
273 INIT_DELAYED_WORK(&rk616_hdmi->rk616_delay_work, rk616_delay_work_func);
276 // if(rk616->pdata->hdmi_irq != INVALID_GPIO)
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");
285 clk_enable(hdmi->hclk);
287 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
289 dev_err(hdmi->dev, "Unable to get register resource\n");
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);
297 dev_err(hdmi->dev, "failed to request mem region for hdmi\n");
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");
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);
317 ret = rk616_hdmi_initial(hdmi);
319 hdmi->irq = platform_get_irq(pdev, 0);
321 dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
324 /* request the IRQ */
325 ret = request_irq(hdmi->irq, rk616_hdmi_irq, 0, dev_name(&pdev->dev), hdmi);
327 dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);
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");
337 dev_err(hdmi->dev,"request gpio for rk616 hdmi irq fail\n");
339 gpio_direction_input(rk616_hdmi->rk616_drv->pdata->hdmi_irq);
340 hdmi->irq = gpio_to_irq(rk616_hdmi->rk616_drv->pdata->hdmi_irq);
342 dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);
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);
350 dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);
354 /* use roll polling method */
359 hdmi_register_display_sysfs(hdmi, NULL);
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);
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");
369 debugfs_create_file("hdmi", S_IRUSR, rk616_hdmi->debugfs_dir, rk616_hdmi, &rk616_hdmi_reg_fops);
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");
379 switch_dev_unregister(&(hdmi->switch_hdmi));
381 hdmi_unregister_display_sysfs(hdmi);
382 #ifdef CONFIG_HAS_EARLYSUSPEND
383 unregister_early_suspend(&hdmi->early_suspend);
386 hdmi_dbg(hdmi->dev, "rk616 hdmi probe error.\n");
392 static int rk616_hdmi_remove(struct platform_device *pdev)
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);
400 free_irq(hdmi->irq, NULL);
402 flush_workqueue(hdmi->workqueue);
403 destroy_workqueue(hdmi->workqueue);
405 switch_dev_unregister(&(hdmi->switch_hdmi));
407 hdmi_unregister_display_sysfs(hdmi);
408 #ifdef CONFIG_HAS_EARLYSUSPEND
409 unregister_early_suspend(&hdmi->early_suspend);
411 fb_destroy_modelist(&hdmi->edid.modelist);
413 kfree(hdmi->edid.audio);
416 if(hdmi->edid.specs->modedb)
417 kfree(hdmi->edid.specs->modedb);
418 kfree(hdmi->edid.specs);
423 hdmi_dbg(hdmi->dev, "rk616 hdmi removed.\n");
427 static void rk616_hdmi_shutdown(struct platform_device *pdev)
430 #ifdef CONFIG_HAS_EARLYSUSPEND
431 unregister_early_suspend(&hdmi->early_suspend);
433 flush_delayed_work(&hdmi->delay_work);
434 mutex_lock(&hdmi->enable_mutex);
437 mutex_unlock(&hdmi->enable_mutex);
441 disable_irq(hdmi->irq);
442 mutex_unlock(&hdmi->enable_mutex);
444 hdmi_dbg(hdmi->dev, "rk616 hdmi shut down.\n");
447 #if defined(CONFIG_OF)
448 static const struct of_device_id rk616_hdmi_of_match[] = {
449 {.compatible = "rockchip,rk616-hdmi",},
453 MODULE_DEVICE_TABLE(of, rk616_hdmi_of_match);
456 static struct platform_driver rk616_hdmi_driver = {
457 .probe = rk616_hdmi_probe,
458 .remove = rk616_hdmi_remove,
460 #ifdef CONFIG_ARCH_RK3026
461 .name = "rk3026-hdmi",
463 .name = "rk616-hdmi",
465 .owner = THIS_MODULE,
466 .of_match_table = of_match_ptr(rk616_hdmi_of_match),
468 .shutdown = rk616_hdmi_shutdown,
471 static int __init rk616_hdmi_init(void)
473 return platform_driver_register(&rk616_hdmi_driver);
476 static void __exit rk616_hdmi_exit(void)
478 platform_driver_unregister(&rk616_hdmi_driver);
482 //fs_initcall(rk616_hdmi_init);
483 late_initcall(rk616_hdmi_init);
484 module_exit(rk616_hdmi_exit);