1 /* linux/drivers/video/s5p_mipi_dsi.c
3 * Samsung SoC MIPI-DSIM driver.
5 * Copyright (c) 2011 Samsung Electronics Co., Ltd
7 * InKi Dae, <inki.dae@samsung.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/clk.h>
18 #include <linux/mutex.h>
19 #include <linux/wait.h>
23 #include <linux/ctype.h>
24 #include <linux/platform_device.h>
26 #include <linux/irq.h>
27 #include <linux/memory.h>
28 #include <linux/delay.h>
29 #include <linux/interrupt.h>
30 #include <linux/kthread.h>
31 #include <linux/notifier.h>
32 #include <linux/pm_runtime.h>
35 #include <plat/mipi_dsim.h>
37 #include "s5p_mipi_dsi_common.h"
38 #include "s5p_mipi_dsi_lowlevel.h"
40 #define master_to_driver(a) (a->dsim_lcd_drv)
41 #define master_to_device(a) (a->dsim_lcd_dev)
43 struct mipi_dsim_ddi {
45 struct list_head list;
46 struct mipi_dsim_lcd_device *dsim_lcd_dev;
47 struct mipi_dsim_lcd_driver *dsim_lcd_drv;
50 static LIST_HEAD(dsim_ddi_list);
52 static DEFINE_MUTEX(mipi_dsim_lock);
54 static const struct mipi_dsim_device_id *mipi_dsim_match_id(const struct mipi_dsim_device_id *id,
55 const struct mipi_dsim_lcd_device *dsim_dev)
58 if (!strcmp(dsim_dev->panel_id, id->name))
65 const struct mipi_dsim_device_id *mipi_dsim_get_device_id(const struct mipi_dsim_lcd_device *dsim_dev)
67 const struct mipi_dsim_lcd_driver *dsim_drv = dsim_dev->master->dsim_lcd_drv;
69 return mipi_dsim_match_id(dsim_drv->id_entry, dsim_dev);
72 static struct s5p_platform_mipi_dsim *to_dsim_plat(struct platform_device *pdev)
74 return (struct s5p_platform_mipi_dsim *)pdev->dev.platform_data;
77 /* update all register settings to MIPI DSI controller. */
78 static void s5p_mipi_update_cfg(struct mipi_dsim_device *dsim)
81 * data from Display controller(FIMD) is not transferred in video mode
82 * but in case of command mode, all settings is not updated to
85 s5p_mipi_dsi_stand_by(dsim, 0);
87 s5p_mipi_dsi_init_dsim(dsim);
88 s5p_mipi_dsi_init_link(dsim);
90 s5p_mipi_dsi_set_hs_enable(dsim);
92 /* set display timing. */
93 s5p_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
96 * data from Display controller(FIMD) is transferred in video mode
97 * but in case of command mode, all settigs is updated to registers.
99 s5p_mipi_dsi_stand_by(dsim, 1);
103 static int s5p_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim, int power)
105 struct platform_device *pdev = to_platform_device(dsim->dev);
106 struct mipi_dsim_lcd_driver *client_drv = master_to_driver(dsim);
107 struct mipi_dsim_lcd_device *client_dev = master_to_device(dsim);
110 mesg.event = PM_EVENT_SUSPEND;
113 case FB_BLANK_POWERDOWN:
114 if (!atomic_read(&dsim->power_t))
117 if (client_drv && client_drv->suspend)
118 client_drv->suspend(client_dev, mesg);
120 /* enable MIPI-DSI PHY. */
121 if (dsim->pd->phy_enable)
122 dsim->pd->phy_enable(pdev, false);
124 clk_disable(dsim->clock);
126 if (dsim->pd->mipi_power)
127 dsim->pd->mipi_power(pdev, 0);
129 atomic_set(&dsim->power_t, 0);
131 pm_runtime_put(&pdev->dev);
141 static int s5p_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
143 struct platform_device *pdev = to_platform_device(dsim->dev);
144 struct mipi_dsim_lcd_driver *client_drv = master_to_driver(dsim);
145 struct mipi_dsim_lcd_device *client_dev = master_to_device(dsim);
148 case FB_BLANK_UNBLANK:
149 if (atomic_read(&dsim->power_t))
152 pm_runtime_get_sync(&pdev->dev);
154 /* lcd panel power on. */
155 if (client_drv && client_drv->power_on)
156 client_drv->power_on(client_dev);
158 if (dsim->pd->mipi_power)
159 dsim->pd->mipi_power(pdev, 1);
161 /* enable MIPI-DSI PHY. */
162 if (dsim->pd->phy_enable)
163 dsim->pd->phy_enable(pdev, true);
165 clk_enable(dsim->clock);
167 s5p_mipi_update_cfg(dsim);
169 /* set lcd panel sequence commands. */
170 if (client_drv && client_drv->set_sequence)
171 client_drv->set_sequence(client_dev);
173 atomic_set(&dsim->power_t, 1);
176 case FB_BLANK_NORMAL:
186 int s5p_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
188 struct mipi_dsim_ddi *dsim_ddi;
191 printk(KERN_ERR "mipi_dsim_lcd_device is NULL.\n");
195 if (!lcd_dev->name) {
196 printk(KERN_ERR "dsim_lcd_device name is NULL.\n");
200 dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
202 printk(KERN_ERR "failed to allocate dsim_ddi object.\n");
206 dsim_ddi->dsim_lcd_dev = lcd_dev;
208 mutex_lock(&mipi_dsim_lock);
209 list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
210 mutex_unlock(&mipi_dsim_lock);
216 *s5p_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv)
218 struct mipi_dsim_ddi *dsim_ddi;
219 struct mipi_dsim_lcd_device *lcd_dev;
221 mutex_lock(&mipi_dsim_lock);
223 list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) {
224 lcd_dev = dsim_ddi->dsim_lcd_dev;
228 if (lcd_drv->id >= 0) {
229 if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0 &&
230 lcd_drv->id == lcd_dev->id) {
232 * bus_id would be used to identify
235 dsim_ddi->bus_id = lcd_dev->bus_id;
236 mutex_unlock(&mipi_dsim_lock);
241 if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) {
243 * bus_id would be used to identify
246 dsim_ddi->bus_id = lcd_dev->bus_id;
247 mutex_unlock(&mipi_dsim_lock);
254 list_del(&dsim_ddi->list);
257 mutex_unlock(&mipi_dsim_lock);
262 int s5p_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
264 struct mipi_dsim_ddi *dsim_ddi;
267 printk(KERN_ERR "mipi_dsim_lcd_driver is NULL.\n");
271 if (!lcd_drv->name) {
272 printk(KERN_ERR "dsim_lcd_driver name is NULL.\n");
276 dsim_ddi = s5p_mipi_dsi_find_lcd_device(lcd_drv);
278 printk(KERN_ERR "mipi_dsim_ddi object not found.\n");
282 dsim_ddi->dsim_lcd_drv = lcd_drv;
284 printk(KERN_INFO "registered panel driver(%s) to mipi-dsi driver.\n",
292 *s5p_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim,
295 struct mipi_dsim_ddi *dsim_ddi;
296 struct mipi_dsim_lcd_driver *lcd_drv;
297 struct mipi_dsim_lcd_device *lcd_dev;
300 mutex_lock(&dsim->lock);
302 list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) {
303 lcd_drv = dsim_ddi->dsim_lcd_drv;
304 lcd_dev = dsim_ddi->dsim_lcd_dev;
305 if (!lcd_drv || !lcd_dev ||
306 (dsim->id != dsim_ddi->bus_id))
309 dev_dbg(dsim->dev, "lcd_drv->id = %d, lcd_dev->id = %d\n",
310 lcd_drv->id, lcd_dev->id);
311 dev_dbg(dsim->dev, "lcd_dev->bus_id = %d, dsim->id = %d\n",
312 lcd_dev->bus_id, dsim->id);
314 if ((strcmp(lcd_drv->name, name) == 0)) {
315 lcd_dev->master = dsim;
317 lcd_dev->dev.parent = dsim->dev;
318 dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name);
320 ret = device_register(&lcd_dev->dev);
323 "can't register %s, status %d\n",
324 dev_name(&lcd_dev->dev), ret);
325 mutex_unlock(&dsim->lock);
330 dsim->dsim_lcd_dev = lcd_dev;
331 dsim->dsim_lcd_drv = lcd_drv;
333 mutex_unlock(&dsim->lock);
339 mutex_unlock(&dsim->lock);
344 /* define MIPI-DSI Master operations. */
345 static struct mipi_dsim_master_ops master_ops = {
346 .cmd_read = s5p_mipi_dsi_rd_data,
347 .cmd_write = s5p_mipi_dsi_wr_data,
348 .get_dsim_frame_done = s5p_mipi_dsi_get_frame_done_status,
349 .clear_dsim_frame_done = s5p_mipi_dsi_clear_frame_done,
350 .set_early_blank_mode = s5p_mipi_dsi_early_blank_mode,
351 .set_blank_mode = s5p_mipi_dsi_blank_mode,
354 static int s5p_mipi_dsi_probe(struct platform_device *pdev)
356 struct resource *res;
357 struct mipi_dsim_device *dsim;
358 struct mipi_dsim_config *dsim_config;
359 struct s5p_platform_mipi_dsim *dsim_pd;
360 struct mipi_dsim_ddi *dsim_ddi;
363 dsim = kzalloc(sizeof(struct mipi_dsim_device), GFP_KERNEL);
365 dev_err(&pdev->dev, "failed to allocate dsim object.\n");
369 dsim->pd = to_dsim_plat(pdev);
370 dsim->dev = &pdev->dev;
373 /* get s5p_platform_mipi_dsim. */
374 dsim_pd = (struct s5p_platform_mipi_dsim *)dsim->pd;
375 if (dsim_pd == NULL) {
376 dev_err(&pdev->dev, "failed to get platform data for dsim.\n");
379 /* get mipi_dsim_config. */
380 dsim_config = dsim_pd->dsim_config;
381 if (dsim_config == NULL) {
382 dev_err(&pdev->dev, "failed to get dsim config data.\n");
386 dsim->dsim_config = dsim_config;
387 dsim->master_ops = &master_ops;
389 dsim->clock = clk_get(&pdev->dev, "dsim0");
390 if (IS_ERR(dsim->clock)) {
391 dev_err(&pdev->dev, "failed to get dsim clock source\n");
395 clk_enable(dsim->clock);
397 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
399 dev_err(&pdev->dev, "failed to get io memory region\n");
400 goto err_platform_get;
403 dsim->res = request_mem_region(res->start, resource_size(res),
404 dev_name(&pdev->dev));
406 dev_err(&pdev->dev, "failed to request io memory region\n");
411 dsim->reg_base = ioremap(res->start, resource_size(res));
412 if (!dsim->reg_base) {
413 dev_err(&pdev->dev, "failed to remap io region\n");
418 mutex_init(&dsim->lock);
419 /* bind lcd ddi matched with panel name. */
420 dsim_ddi = s5p_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
422 dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
426 dsim->irq = platform_get_irq(pdev, 0);
428 dev_err(&pdev->dev, "failed to request dsim irq resource\n");
430 goto err_platform_get_irq;
433 ret = request_irq(dsim->irq, s5p_mipi_dsi_interrupt_handler,
434 IRQF_SHARED, pdev->name, dsim);
436 dev_err(&pdev->dev, "failed to request dsim irq\n");
440 init_completion(&dsim_rd_comp);
442 /* enable interrupt */
443 s5p_mipi_dsi_init_interrupt(dsim);
444 /* initialize mipi-dsi client(lcd panel). */
445 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe)
446 dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev);
448 /* in case that mipi got enabled at bootloader. */
449 if (dsim_pd->enabled)
452 /* lcd panel power on. */
453 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on)
454 dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev);
456 if (dsim->pd->mipi_power)
457 dsim->pd->mipi_power(pdev, 1);
459 /* enable MIPI-DSI PHY. */
460 if (dsim->pd->phy_enable)
461 dsim->pd->phy_enable(pdev, true);
463 s5p_mipi_update_cfg(dsim);
465 /* set lcd panel sequence commands. */
466 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->set_sequence)
467 dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev);
469 atomic_set(&dsim->power_t, 1);
472 platform_set_drvdata(pdev, dsim);
474 dev_dbg(&pdev->dev, "mipi-dsi driver(%s mode) has been probed.\n",
475 (dsim_config->e_interface == DSIM_COMMAND) ?
478 pm_runtime_set_active(&pdev->dev);
479 pm_runtime_get_noresume(&pdev->dev);
480 pm_runtime_enable(&pdev->dev);
481 pm_runtime_put_sync(&pdev->dev);
486 iounmap((void __iomem *) dsim->reg_base);
489 release_mem_region(dsim->res->start, resource_size(dsim->res));
492 release_resource(dsim->res);
495 clk_disable(dsim->clock);
496 clk_put(dsim->clock);
501 err_platform_get_irq:
505 static int __devexit s5p_mipi_dsi_remove(struct platform_device *pdev)
507 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
508 struct mipi_dsim_ddi *dsim_ddi;
509 struct mipi_dsim_lcd_driver *dsim_lcd_drv;
511 iounmap(dsim->reg_base);
513 clk_disable(dsim->clock);
514 clk_put(dsim->clock);
516 release_resource(dsim->res);
517 release_mem_region(dsim->res->start, resource_size(dsim->res));
519 list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) {
521 if (dsim->id != dsim_ddi->bus_id)
524 dsim_lcd_drv = dsim_ddi->dsim_lcd_drv;
526 if (dsim_lcd_drv->remove)
527 dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev);
538 static int s5p_mipi_dsi_suspend(struct device *dev, pm_message_t state)
540 struct platform_device *pdev = to_platform_device(dev);
541 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
543 disable_irq(dsim->irq);
545 /* before entering suspend, power_t was set in s5p_mipi_dsi_early_blank() */
546 if (!atomic_read(&dsim->power_t))
549 if (master_to_driver(dsim) && (master_to_driver(dsim))->suspend)
550 (master_to_driver(dsim))->suspend(master_to_device(dsim), state);
552 /* enable MIPI-DSI PHY. */
553 if (dsim->pd->phy_enable)
554 dsim->pd->phy_enable(pdev, false);
556 clk_disable(dsim->clock);
558 if (dsim->pd->mipi_power)
559 dsim->pd->mipi_power(pdev, 0);
561 atomic_set(&dsim->power_t, 0);
563 pm_runtime_put(&pdev->dev);
568 static int s5p_mipi_dsi_resume(struct device *dev)
570 struct platform_device *pdev = to_platform_device(dev);
571 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
572 struct mipi_dsim_lcd_driver *client_drv = master_to_driver(dsim);
573 struct mipi_dsim_lcd_device *client_dev = master_to_device(dsim);
575 if (atomic_read(&dsim->power_t))
578 pm_runtime_get_sync(&pdev->dev);
580 /* lcd panel power on. */
581 if (client_drv && client_drv->power_on)
582 client_drv->power_on(client_dev);
584 if (dsim->pd->mipi_power)
585 dsim->pd->mipi_power(pdev, 1);
587 /* enable MIPI-DSI PHY. */
588 if (dsim->pd->phy_enable)
589 dsim->pd->phy_enable(pdev, true);
591 clk_enable(dsim->clock);
593 s5p_mipi_update_cfg(dsim);
595 /* set lcd panel sequence commands. */
596 if (client_drv && client_drv->set_sequence)
597 client_drv->set_sequence(client_dev);
599 enable_irq(dsim->irq);
601 atomic_set(&dsim->power_t, 1);
606 #define s5p_mipi_dsi_suspend NULL
607 #define s5p_mipi_dsi_resume NULL
610 static struct platform_driver s5p_mipi_dsi_driver = {
611 .probe = s5p_mipi_dsi_probe,
612 .remove = __devexit_p(s5p_mipi_dsi_remove),
614 .name = "s5p-mipi-dsim",
615 .owner = THIS_MODULE,
616 .suspend = s5p_mipi_dsi_suspend,
617 .resume = s5p_mipi_dsi_resume,
621 static int s5p_mipi_dsi_register(void)
623 platform_driver_register(&s5p_mipi_dsi_driver);
628 static void s5p_mipi_dsi_unregister(void)
630 platform_driver_unregister(&s5p_mipi_dsi_driver);
633 module_init(s5p_mipi_dsi_register);
634 module_exit(s5p_mipi_dsi_unregister);
636 MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
637 MODULE_DESCRIPTION("Samusung SoC MIPI-DSI driver");
638 MODULE_LICENSE("GPL");