upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / video / s5p_mipi_dsi.c
1 /* linux/drivers/video/s5p_mipi_dsi.c
2  *
3  * Samsung SoC MIPI-DSIM driver.
4  *
5  * Copyright (c) 2011 Samsung Electronics Co., Ltd
6  *
7  * InKi Dae, <inki.dae@samsung.com>
8  *
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.
12 */
13
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>
20 #include <linux/fs.h>
21 #include <linux/mm.h>
22 #include <linux/fb.h>
23 #include <linux/ctype.h>
24 #include <linux/platform_device.h>
25 #include <linux/io.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>
33
34 #include <plat/fb.h>
35 #include <plat/mipi_dsim.h>
36
37 #include "s5p_mipi_dsi_common.h"
38 #include "s5p_mipi_dsi_lowlevel.h"
39
40 #define master_to_driver(a)     (a->dsim_lcd_drv)
41 #define master_to_device(a)     (a->dsim_lcd_dev)
42
43 struct mipi_dsim_ddi {
44         int                             bus_id;
45         struct list_head                list;
46         struct mipi_dsim_lcd_device     *dsim_lcd_dev;
47         struct mipi_dsim_lcd_driver     *dsim_lcd_drv;
48 };
49
50 static LIST_HEAD(dsim_ddi_list);
51
52 static DEFINE_MUTEX(mipi_dsim_lock);
53
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)
56 {
57         while (id->name[0]) {
58                 if (!strcmp(dsim_dev->panel_id, id->name))
59                         return id;
60                 id++;
61         }
62         return NULL;
63 }
64
65 const struct mipi_dsim_device_id *mipi_dsim_get_device_id(const struct mipi_dsim_lcd_device *dsim_dev)
66 {
67         const struct mipi_dsim_lcd_driver *dsim_drv = dsim_dev->master->dsim_lcd_drv;
68
69         return mipi_dsim_match_id(dsim_drv->id_entry, dsim_dev);
70 }
71
72 static struct s5p_platform_mipi_dsim *to_dsim_plat(struct platform_device *pdev)
73 {
74         return (struct s5p_platform_mipi_dsim *)pdev->dev.platform_data;
75 }
76
77 /* update all register settings to MIPI DSI controller. */
78 static void s5p_mipi_update_cfg(struct mipi_dsim_device *dsim)
79 {
80         /*
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
83          * registers.
84          */
85         s5p_mipi_dsi_stand_by(dsim, 0);
86
87         s5p_mipi_dsi_init_dsim(dsim);
88         s5p_mipi_dsi_init_link(dsim);
89
90         s5p_mipi_dsi_set_hs_enable(dsim);
91
92         /* set display timing. */
93         s5p_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
94
95         /*
96          * data from Display controller(FIMD) is transferred in video mode
97          * but in case of command mode, all settigs is updated to registers.
98          */
99         s5p_mipi_dsi_stand_by(dsim, 1);
100
101 }
102
103 static int s5p_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim, int power)
104 {
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);
108         pm_message_t mesg;
109
110         mesg.event = PM_EVENT_SUSPEND;
111
112         switch (power) {
113         case FB_BLANK_POWERDOWN:
114                 if (!atomic_read(&dsim->power_t))
115                         return 0;
116
117                 if (client_drv && client_drv->suspend)
118                         client_drv->suspend(client_dev, mesg);
119
120                 /* enable MIPI-DSI PHY. */
121                 if (dsim->pd->phy_enable)
122                         dsim->pd->phy_enable(pdev, false);
123
124                 clk_disable(dsim->clock);
125
126                 if (dsim->pd->mipi_power)
127                         dsim->pd->mipi_power(pdev, 0);
128
129                 atomic_set(&dsim->power_t, 0);
130
131                 pm_runtime_put(&pdev->dev);
132
133                 break;
134         default:
135                 break;
136         }
137
138         return 0;
139 }
140
141 static int s5p_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
142 {
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);
146
147         switch (power) {
148         case FB_BLANK_UNBLANK:
149                 if (atomic_read(&dsim->power_t))
150                         return 0;
151
152                 pm_runtime_get_sync(&pdev->dev);
153
154                 /* lcd panel power on. */
155                 if (client_drv && client_drv->power_on)
156                         client_drv->power_on(client_dev);
157
158                 if (dsim->pd->mipi_power)
159                         dsim->pd->mipi_power(pdev, 1);
160
161                 /* enable MIPI-DSI PHY. */
162                 if (dsim->pd->phy_enable)
163                         dsim->pd->phy_enable(pdev, true);
164
165                 clk_enable(dsim->clock);
166
167                 s5p_mipi_update_cfg(dsim);
168
169                 /* set lcd panel sequence commands. */
170                 if (client_drv && client_drv->set_sequence)
171                         client_drv->set_sequence(client_dev);
172
173                 atomic_set(&dsim->power_t, 1);
174
175                 break;
176         case FB_BLANK_NORMAL:
177                 /* TODO. */
178                 break;
179         default:
180                 break;
181         }
182
183         return 0;
184 }
185
186 int s5p_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
187 {
188         struct mipi_dsim_ddi *dsim_ddi;
189
190         if (!lcd_dev) {
191                 printk(KERN_ERR "mipi_dsim_lcd_device is NULL.\n");
192                 return -EFAULT;
193         }
194
195         if (!lcd_dev->name) {
196                 printk(KERN_ERR "dsim_lcd_device name is NULL.\n");
197                 return -EFAULT;
198         }
199
200         dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
201         if (!dsim_ddi) {
202                 printk(KERN_ERR "failed to allocate dsim_ddi object.\n");
203                 return -EFAULT;
204         }
205
206         dsim_ddi->dsim_lcd_dev = lcd_dev;
207
208         mutex_lock(&mipi_dsim_lock);
209         list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
210         mutex_unlock(&mipi_dsim_lock);
211
212         return 0;
213 }
214
215 struct mipi_dsim_ddi
216         *s5p_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv)
217 {
218         struct mipi_dsim_ddi *dsim_ddi;
219         struct mipi_dsim_lcd_device *lcd_dev;
220
221         mutex_lock(&mipi_dsim_lock);
222
223         list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) {
224                 lcd_dev = dsim_ddi->dsim_lcd_dev;
225                 if (!lcd_dev)
226                         continue;
227
228                 if (lcd_drv->id >= 0) {
229                         if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0 &&
230                                         lcd_drv->id == lcd_dev->id) {
231                                 /**
232                                  * bus_id would be used to identify
233                                  * connected bus.
234                                  */
235                                 dsim_ddi->bus_id = lcd_dev->bus_id;
236                                 mutex_unlock(&mipi_dsim_lock);
237
238                                 return dsim_ddi;
239                         }
240                 } else {
241                         if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) {
242                                 /**
243                                  * bus_id would be used to identify
244                                  * connected bus.
245                                  */
246                                 dsim_ddi->bus_id = lcd_dev->bus_id;
247                                 mutex_unlock(&mipi_dsim_lock);
248
249                                 return dsim_ddi;
250                         }
251                 }
252
253                 kfree(dsim_ddi);
254                 list_del(&dsim_ddi->list);
255         }
256
257         mutex_unlock(&mipi_dsim_lock);
258
259         return NULL;
260 }
261
262 int s5p_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
263 {
264         struct mipi_dsim_ddi *dsim_ddi;
265
266         if (!lcd_drv) {
267                 printk(KERN_ERR "mipi_dsim_lcd_driver is NULL.\n");
268                 return -EFAULT;
269         }
270
271         if (!lcd_drv->name) {
272                 printk(KERN_ERR "dsim_lcd_driver name is NULL.\n");
273                 return -EFAULT;
274         }
275
276         dsim_ddi = s5p_mipi_dsi_find_lcd_device(lcd_drv);
277         if (!dsim_ddi) {
278                 printk(KERN_ERR "mipi_dsim_ddi object not found.\n");
279                 return -EFAULT;
280         }
281
282         dsim_ddi->dsim_lcd_drv = lcd_drv;
283
284         printk(KERN_INFO "registered panel driver(%s) to mipi-dsi driver.\n",
285                 lcd_drv->name);
286
287         return 0;
288
289 }
290
291 struct mipi_dsim_ddi
292         *s5p_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim,
293                         const char *name)
294 {
295         struct mipi_dsim_ddi *dsim_ddi;
296         struct mipi_dsim_lcd_driver *lcd_drv;
297         struct mipi_dsim_lcd_device *lcd_dev;
298         int ret;
299
300         mutex_lock(&dsim->lock);
301
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))
307                                 continue;
308
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);
313
314                 if ((strcmp(lcd_drv->name, name) == 0)) {
315                         lcd_dev->master = dsim;
316
317                         lcd_dev->dev.parent = dsim->dev;
318                         dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name);
319
320                         ret = device_register(&lcd_dev->dev);
321                         if (ret < 0) {
322                                 dev_err(dsim->dev,
323                                         "can't register %s, status %d\n",
324                                         dev_name(&lcd_dev->dev), ret);
325                                 mutex_unlock(&dsim->lock);
326
327                                 return NULL;
328                         }
329
330                         dsim->dsim_lcd_dev = lcd_dev;
331                         dsim->dsim_lcd_drv = lcd_drv;
332
333                         mutex_unlock(&dsim->lock);
334
335                         return dsim_ddi;
336                 }
337         }
338
339         mutex_unlock(&dsim->lock);
340
341         return NULL;
342 }
343
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,
352 };
353
354 static int s5p_mipi_dsi_probe(struct platform_device *pdev)
355 {
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;
361         int ret = -EINVAL;
362
363         dsim = kzalloc(sizeof(struct mipi_dsim_device), GFP_KERNEL);
364         if (!dsim) {
365                 dev_err(&pdev->dev, "failed to allocate dsim object.\n");
366                 return -EFAULT;
367         }
368
369         dsim->pd = to_dsim_plat(pdev);
370         dsim->dev = &pdev->dev;
371         dsim->id = pdev->id;
372
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");
377                 return -EFAULT;
378         }
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");
383                 return -EFAULT;
384         }
385
386         dsim->dsim_config = dsim_config;
387         dsim->master_ops = &master_ops;
388
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");
392                 goto err_clock_get;
393         }
394
395         clk_enable(dsim->clock);
396
397         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
398         if (!res) {
399                 dev_err(&pdev->dev, "failed to get io memory region\n");
400                 goto err_platform_get;
401         }
402
403         dsim->res = request_mem_region(res->start, resource_size(res),
404                                         dev_name(&pdev->dev));
405         if (!dsim->res) {
406                 dev_err(&pdev->dev, "failed to request io memory region\n");
407                 ret = -ENOMEM;
408                 goto err_mem_region;
409         }
410
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");
414                 ret = -EFAULT;
415                 goto err_ioremap;
416         }
417
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);
421         if (!dsim_ddi) {
422                 dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
423                 goto err_bind;
424         }
425
426         dsim->irq = platform_get_irq(pdev, 0);
427         if (dsim->irq < 0) {
428                 dev_err(&pdev->dev, "failed to request dsim irq resource\n");
429                 ret = -EINVAL;
430                 goto err_platform_get_irq;
431         }
432
433         ret = request_irq(dsim->irq, s5p_mipi_dsi_interrupt_handler,
434                         IRQF_SHARED, pdev->name, dsim);
435         if (ret != 0) {
436                 dev_err(&pdev->dev, "failed to request dsim irq\n");
437                 ret = -EINVAL;
438                 goto err_bind;
439         }
440         init_completion(&dsim_rd_comp);
441
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);
447
448         /* in case that mipi got enabled at bootloader. */
449         if (dsim_pd->enabled)
450                 goto out;
451
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);
455
456         if (dsim->pd->mipi_power)
457                 dsim->pd->mipi_power(pdev, 1);
458
459         /* enable MIPI-DSI PHY. */
460         if (dsim->pd->phy_enable)
461                 dsim->pd->phy_enable(pdev, true);
462
463         s5p_mipi_update_cfg(dsim);
464
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);
468
469         atomic_set(&dsim->power_t, 1);
470
471 out:
472         platform_set_drvdata(pdev, dsim);
473
474         dev_dbg(&pdev->dev, "mipi-dsi driver(%s mode) has been probed.\n",
475                 (dsim_config->e_interface == DSIM_COMMAND) ?
476                         "CPU" : "RGB");
477
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);
482
483         return 0;
484
485 err_bind:
486         iounmap((void __iomem *) dsim->reg_base);
487
488 err_ioremap:
489         release_mem_region(dsim->res->start, resource_size(dsim->res));
490
491 err_mem_region:
492         release_resource(dsim->res);
493
494 err_platform_get:
495         clk_disable(dsim->clock);
496         clk_put(dsim->clock);
497
498 err_clock_get:
499         kfree(dsim);
500
501 err_platform_get_irq:
502         return ret;
503 }
504
505 static int __devexit s5p_mipi_dsi_remove(struct platform_device *pdev)
506 {
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;
510
511         iounmap(dsim->reg_base);
512
513         clk_disable(dsim->clock);
514         clk_put(dsim->clock);
515
516         release_resource(dsim->res);
517         release_mem_region(dsim->res->start, resource_size(dsim->res));
518
519         list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) {
520                 if (dsim_ddi) {
521                         if (dsim->id != dsim_ddi->bus_id)
522                                 continue;
523
524                         dsim_lcd_drv = dsim_ddi->dsim_lcd_drv;
525
526                         if (dsim_lcd_drv->remove)
527                                 dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev);
528
529                         kfree(dsim_ddi);
530                 }
531         }
532
533         kfree(dsim);
534
535         return 0;
536 }
537 #ifdef CONFIG_PM
538 static int s5p_mipi_dsi_suspend(struct device *dev, pm_message_t state)
539 {
540         struct platform_device *pdev = to_platform_device(dev);
541         struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
542
543         disable_irq(dsim->irq);
544
545         /* before entering suspend, power_t was set in s5p_mipi_dsi_early_blank() */
546         if (!atomic_read(&dsim->power_t))
547                 return 0;
548
549         if (master_to_driver(dsim) && (master_to_driver(dsim))->suspend)
550                 (master_to_driver(dsim))->suspend(master_to_device(dsim), state);
551
552         /* enable MIPI-DSI PHY. */
553         if (dsim->pd->phy_enable)
554                 dsim->pd->phy_enable(pdev, false);
555
556         clk_disable(dsim->clock);
557
558         if (dsim->pd->mipi_power)
559                 dsim->pd->mipi_power(pdev, 0);
560
561         atomic_set(&dsim->power_t, 0);
562
563         pm_runtime_put(&pdev->dev);
564
565         return 0;
566 }
567
568 static int s5p_mipi_dsi_resume(struct device *dev)
569 {
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);
574
575         if (atomic_read(&dsim->power_t))
576                 return 0;
577
578         pm_runtime_get_sync(&pdev->dev);
579
580         /* lcd panel power on. */
581         if (client_drv && client_drv->power_on)
582                 client_drv->power_on(client_dev);
583
584         if (dsim->pd->mipi_power)
585                 dsim->pd->mipi_power(pdev, 1);
586
587         /* enable MIPI-DSI PHY. */
588         if (dsim->pd->phy_enable)
589                 dsim->pd->phy_enable(pdev, true);
590
591         clk_enable(dsim->clock);
592
593         s5p_mipi_update_cfg(dsim);
594
595         /* set lcd panel sequence commands. */
596         if (client_drv && client_drv->set_sequence)
597                 client_drv->set_sequence(client_dev);
598
599         enable_irq(dsim->irq);
600
601         atomic_set(&dsim->power_t, 1);
602
603         return 0;
604 }
605 #else
606 #define s5p_mipi_dsi_suspend NULL
607 #define s5p_mipi_dsi_resume NULL
608 #endif
609
610 static struct platform_driver s5p_mipi_dsi_driver = {
611         .probe = s5p_mipi_dsi_probe,
612         .remove = __devexit_p(s5p_mipi_dsi_remove),
613         .driver = {
614                 .name = "s5p-mipi-dsim",
615                 .owner = THIS_MODULE,
616                 .suspend = s5p_mipi_dsi_suspend,
617                 .resume = s5p_mipi_dsi_resume,
618         },
619 };
620
621 static int s5p_mipi_dsi_register(void)
622 {
623         platform_driver_register(&s5p_mipi_dsi_driver);
624
625         return 0;
626 }
627
628 static void s5p_mipi_dsi_unregister(void)
629 {
630         platform_driver_unregister(&s5p_mipi_dsi_driver);
631 }
632
633 module_init(s5p_mipi_dsi_register);
634 module_exit(s5p_mipi_dsi_unregister);
635
636 MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
637 MODULE_DESCRIPTION("Samusung SoC MIPI-DSI driver");
638 MODULE_LICENSE("GPL");