diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 20:38:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 20:38:49 -0500 |
commit | 7c2db36e730ee4facd341679ecb21ee73ba92831 (patch) | |
tree | 75016fba72aaf0581b9263f7fa4c565e6e634f3c /drivers | |
parent | 8b5628ab83b671f96ac9f174c1bd51c92589fc82 (diff) | |
parent | a47a376f1c025e23e836c0376813c0424de665c2 (diff) |
Merge branch 'akpm' (incoming from Andrew)
Merge misc patches from Andrew Morton:
- Florian has vanished so I appear to have become fbdev maintainer
again :(
- Joel and Mark are distracted to welcome to the new OCFS2 maintainer
- The backlight queue
- Small core kernel changes
- lib/ updates
- The rtc queue
- Various random bits
* akpm: (164 commits)
rtc: rtc-davinci: use devm_*() functions
rtc: rtc-max8997: use devm_request_threaded_irq()
rtc: rtc-max8907: use devm_request_threaded_irq()
rtc: rtc-da9052: use devm_request_threaded_irq()
rtc: rtc-wm831x: use devm_request_threaded_irq()
rtc: rtc-tps80031: use devm_request_threaded_irq()
rtc: rtc-lp8788: use devm_request_threaded_irq()
rtc: rtc-coh901331: use devm_clk_get()
rtc: rtc-vt8500: use devm_*() functions
rtc: rtc-tps6586x: use devm_request_threaded_irq()
rtc: rtc-imxdi: use devm_clk_get()
rtc: rtc-cmos: use dev_warn()/dev_dbg() instead of printk()/pr_debug()
rtc: rtc-pcf8583: use dev_warn() instead of printk()
rtc: rtc-sun4v: use pr_warn() instead of printk()
rtc: rtc-vr41xx: use dev_info() instead of printk()
rtc: rtc-rs5c313: use pr_err() instead of printk()
rtc: rtc-at91rm9200: use dev_dbg()/dev_err() instead of printk()/pr_debug()
rtc: rtc-rs5c372: use dev_dbg()/dev_warn() instead of printk()/pr_debug()
rtc: rtc-ds2404: use dev_err() instead of printk()
rtc: rtc-efi: use dev_err()/dev_warn()/pr_err() instead of printk()
...
Diffstat (limited to 'drivers')
91 files changed, 8531 insertions, 708 deletions
diff --git a/drivers/net/ethernet/sun/Kconfig b/drivers/net/ethernet/sun/Kconfig index ae3a3557293f..3074aa374c6b 100644 --- a/drivers/net/ethernet/sun/Kconfig +++ b/drivers/net/ethernet/sun/Kconfig | |||
@@ -61,7 +61,7 @@ config SUNGEM | |||
61 | select SUNGEM_PHY | 61 | select SUNGEM_PHY |
62 | ---help--- | 62 | ---help--- |
63 | Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also | 63 | Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also |
64 | <http://www.sun.com/products-n-solutions/hardware/docs/pdf/806-3985-10.pdf>. | 64 | <http://docs.oracle.com/cd/E19455-01/806-3985-10/806-3985-10.pdf>. |
65 | 65 | ||
66 | config CASSINI | 66 | config CASSINI |
67 | tristate "Sun Cassini support" | 67 | tristate "Sun Cassini support" |
@@ -69,7 +69,7 @@ config CASSINI | |||
69 | select CRC32 | 69 | select CRC32 |
70 | ---help--- | 70 | ---help--- |
71 | Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also | 71 | Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also |
72 | <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf> | 72 | <http://docs.oracle.com/cd/E19113-01/giga.ether.pci/817-4341-10/817-4341-10.pdf>. |
73 | 73 | ||
74 | config SUNVNET | 74 | config SUNVNET |
75 | tristate "Sun Virtual Network support" | 75 | tristate "Sun Virtual Network support" |
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 673c14ea11e3..5292db69c426 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -484,7 +484,7 @@ static int socket_early_resume(struct pcmcia_socket *skt) | |||
484 | 484 | ||
485 | static int socket_late_resume(struct pcmcia_socket *skt) | 485 | static int socket_late_resume(struct pcmcia_socket *skt) |
486 | { | 486 | { |
487 | int ret; | 487 | int ret = 0; |
488 | 488 | ||
489 | mutex_lock(&skt->ops_mutex); | 489 | mutex_lock(&skt->ops_mutex); |
490 | skt->state &= ~SOCKET_SUSPEND; | 490 | skt->state &= ~SOCKET_SUSPEND; |
@@ -511,19 +511,31 @@ static int socket_late_resume(struct pcmcia_socket *skt) | |||
511 | return socket_insert(skt); | 511 | return socket_insert(skt); |
512 | } | 512 | } |
513 | 513 | ||
514 | if (!(skt->state & SOCKET_CARDBUS) && (skt->callback)) | ||
515 | ret = skt->callback->early_resume(skt); | ||
516 | return ret; | ||
517 | } | ||
518 | |||
519 | /* | ||
520 | * Finalize the resume. In case of a cardbus socket, we have | ||
521 | * to rebind the devices as we can't be certain that it has been | ||
522 | * replaced, or not. | ||
523 | */ | ||
524 | static int socket_complete_resume(struct pcmcia_socket *skt) | ||
525 | { | ||
526 | int ret = 0; | ||
514 | #ifdef CONFIG_CARDBUS | 527 | #ifdef CONFIG_CARDBUS |
515 | if (skt->state & SOCKET_CARDBUS) { | 528 | if (skt->state & SOCKET_CARDBUS) { |
516 | /* We can't be sure the CardBus card is the same | 529 | /* We can't be sure the CardBus card is the same |
517 | * as the one previously inserted. Therefore, remove | 530 | * as the one previously inserted. Therefore, remove |
518 | * and re-add... */ | 531 | * and re-add... */ |
519 | cb_free(skt); | 532 | cb_free(skt); |
520 | cb_alloc(skt); | 533 | ret = cb_alloc(skt); |
521 | return 0; | 534 | if (ret) |
535 | cb_free(skt); | ||
522 | } | 536 | } |
523 | #endif | 537 | #endif |
524 | if (!(skt->state & SOCKET_CARDBUS) && (skt->callback)) | 538 | return ret; |
525 | skt->callback->early_resume(skt); | ||
526 | return 0; | ||
527 | } | 539 | } |
528 | 540 | ||
529 | /* | 541 | /* |
@@ -533,11 +545,15 @@ static int socket_late_resume(struct pcmcia_socket *skt) | |||
533 | */ | 545 | */ |
534 | static int socket_resume(struct pcmcia_socket *skt) | 546 | static int socket_resume(struct pcmcia_socket *skt) |
535 | { | 547 | { |
548 | int err; | ||
536 | if (!(skt->state & SOCKET_SUSPEND)) | 549 | if (!(skt->state & SOCKET_SUSPEND)) |
537 | return -EBUSY; | 550 | return -EBUSY; |
538 | 551 | ||
539 | socket_early_resume(skt); | 552 | socket_early_resume(skt); |
540 | return socket_late_resume(skt); | 553 | err = socket_late_resume(skt); |
554 | if (!err) | ||
555 | err = socket_complete_resume(skt); | ||
556 | return err; | ||
541 | } | 557 | } |
542 | 558 | ||
543 | static void socket_remove(struct pcmcia_socket *skt) | 559 | static void socket_remove(struct pcmcia_socket *skt) |
@@ -848,6 +864,12 @@ static int __used pcmcia_socket_dev_resume(struct device *dev) | |||
848 | return __pcmcia_pm_op(dev, socket_late_resume); | 864 | return __pcmcia_pm_op(dev, socket_late_resume); |
849 | } | 865 | } |
850 | 866 | ||
867 | static void __used pcmcia_socket_dev_complete(struct device *dev) | ||
868 | { | ||
869 | WARN(__pcmcia_pm_op(dev, socket_complete_resume), | ||
870 | "failed to complete resume"); | ||
871 | } | ||
872 | |||
851 | static const struct dev_pm_ops pcmcia_socket_pm_ops = { | 873 | static const struct dev_pm_ops pcmcia_socket_pm_ops = { |
852 | /* dev_resume may be called with IRQs enabled */ | 874 | /* dev_resume may be called with IRQs enabled */ |
853 | SET_SYSTEM_SLEEP_PM_OPS(NULL, | 875 | SET_SYSTEM_SLEEP_PM_OPS(NULL, |
@@ -862,6 +884,7 @@ static const struct dev_pm_ops pcmcia_socket_pm_ops = { | |||
862 | .resume_noirq = pcmcia_socket_dev_resume_noirq, | 884 | .resume_noirq = pcmcia_socket_dev_resume_noirq, |
863 | .thaw_noirq = pcmcia_socket_dev_resume_noirq, | 885 | .thaw_noirq = pcmcia_socket_dev_resume_noirq, |
864 | .restore_noirq = pcmcia_socket_dev_resume_noirq, | 886 | .restore_noirq = pcmcia_socket_dev_resume_noirq, |
887 | .complete = pcmcia_socket_dev_complete, | ||
865 | }; | 888 | }; |
866 | 889 | ||
867 | #define PCMCIA_SOCKET_CLASS_PM_OPS (&pcmcia_socket_pm_ops) | 890 | #define PCMCIA_SOCKET_CLASS_PM_OPS (&pcmcia_socket_pm_ops) |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 476d06452af8..e6ab071fb6fd 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -204,6 +204,12 @@ config RTC_DRV_DS3232 | |||
204 | This driver can also be built as a module. If so, the module | 204 | This driver can also be built as a module. If so, the module |
205 | will be called rtc-ds3232. | 205 | will be called rtc-ds3232. |
206 | 206 | ||
207 | config RTC_DRV_LP8788 | ||
208 | tristate "TI LP8788 RTC driver" | ||
209 | depends on MFD_LP8788 | ||
210 | help | ||
211 | Say Y to enable support for the LP8788 RTC/ALARM driver. | ||
212 | |||
207 | config RTC_DRV_MAX6900 | 213 | config RTC_DRV_MAX6900 |
208 | tristate "Maxim MAX6900" | 214 | tristate "Maxim MAX6900" |
209 | help | 215 | help |
@@ -243,6 +249,26 @@ config RTC_DRV_MAX8998 | |||
243 | This driver can also be built as a module. If so, the module | 249 | This driver can also be built as a module. If so, the module |
244 | will be called rtc-max8998. | 250 | will be called rtc-max8998. |
245 | 251 | ||
252 | config RTC_DRV_MAX8997 | ||
253 | tristate "Maxim MAX8997" | ||
254 | depends on MFD_MAX8997 | ||
255 | help | ||
256 | If you say yes here you will get support for the | ||
257 | RTC of Maxim MAX8997 PMIC. | ||
258 | |||
259 | This driver can also be built as a module. If so, the module | ||
260 | will be called rtc-max8997. | ||
261 | |||
262 | config RTC_DRV_MAX77686 | ||
263 | tristate "Maxim MAX77686" | ||
264 | depends on MFD_MAX77686 | ||
265 | help | ||
266 | If you say yes here you will get support for the | ||
267 | RTC of Maxim MAX77686 PMIC. | ||
268 | |||
269 | This driver can also be built as a module. If so, the module | ||
270 | will be called rtc-max77686. | ||
271 | |||
246 | config RTC_DRV_RS5C372 | 272 | config RTC_DRV_RS5C372 |
247 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" | 273 | tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" |
248 | help | 274 | help |
@@ -380,6 +406,14 @@ config RTC_DRV_TPS65910 | |||
380 | This driver can also be built as a module. If so, the module | 406 | This driver can also be built as a module. If so, the module |
381 | will be called rtc-tps65910. | 407 | will be called rtc-tps65910. |
382 | 408 | ||
409 | config RTC_DRV_TPS80031 | ||
410 | tristate "TI TPS80031/TPS80032 RTC driver" | ||
411 | depends on MFD_TPS80031 | ||
412 | help | ||
413 | TI Power Managment IC TPS80031 supports RTC functionality | ||
414 | along with alarm. This driver supports the RTC driver for | ||
415 | the TPS80031 RTC module. | ||
416 | |||
383 | config RTC_DRV_RC5T583 | 417 | config RTC_DRV_RC5T583 |
384 | tristate "RICOH 5T583 RTC driver" | 418 | tristate "RICOH 5T583 RTC driver" |
385 | depends on MFD_RC5T583 | 419 | depends on MFD_RC5T583 |
@@ -537,6 +571,14 @@ config RTC_DRV_PCF2123 | |||
537 | This driver can also be built as a module. If so, the module | 571 | This driver can also be built as a module. If so, the module |
538 | will be called rtc-pcf2123. | 572 | will be called rtc-pcf2123. |
539 | 573 | ||
574 | config RTC_DRV_RX4581 | ||
575 | tristate "Epson RX-4581" | ||
576 | help | ||
577 | If you say yes here you will get support for the Epson RX-4581. | ||
578 | |||
579 | This driver can also be built as a module. If so the module | ||
580 | will be called rtc-rx4581. | ||
581 | |||
540 | endif # SPI_MASTER | 582 | endif # SPI_MASTER |
541 | 583 | ||
542 | comment "Platform RTC drivers" | 584 | comment "Platform RTC drivers" |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 60c0414d67fa..e8f2e2fee06f 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -58,6 +58,7 @@ obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o | |||
58 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 58 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
59 | obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o | 59 | obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o |
60 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o | 60 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o |
61 | obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o | ||
61 | obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o | 62 | obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o |
62 | obj-$(CONFIG_RTC_DRV_LOONGSON1) += rtc-ls1x.o | 63 | obj-$(CONFIG_RTC_DRV_LOONGSON1) += rtc-ls1x.o |
63 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | 64 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o |
@@ -71,7 +72,9 @@ obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | |||
71 | obj-$(CONFIG_RTC_DRV_MAX8907) += rtc-max8907.o | 72 | obj-$(CONFIG_RTC_DRV_MAX8907) += rtc-max8907.o |
72 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o | 73 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o |
73 | obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o | 74 | obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o |
75 | obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o | ||
74 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 76 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
77 | obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o | ||
75 | obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o | 78 | obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o |
76 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o | 79 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o |
77 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o | 80 | obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o |
@@ -97,6 +100,7 @@ obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | |||
97 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 100 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
98 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o | 101 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o |
99 | obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o | 102 | obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o |
103 | obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o | ||
100 | obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o | 104 | obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o |
101 | obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o | 105 | obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o |
102 | obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o | 106 | obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o |
@@ -115,6 +119,7 @@ obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o | |||
115 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o | 119 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o |
116 | obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o | 120 | obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o |
117 | obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o | 121 | obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o |
122 | obj-$(CONFIG_RTC_DRV_TPS80031) += rtc-tps80031.o | ||
118 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o | 123 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o |
119 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 124 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
120 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 125 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 26388f182594..9b742d3ffb94 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -11,6 +11,8 @@ | |||
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
15 | |||
14 | #include <linux/module.h> | 16 | #include <linux/module.h> |
15 | #include <linux/rtc.h> | 17 | #include <linux/rtc.h> |
16 | #include <linux/kdev_t.h> | 18 | #include <linux/kdev_t.h> |
@@ -261,7 +263,7 @@ static int __init rtc_init(void) | |||
261 | { | 263 | { |
262 | rtc_class = class_create(THIS_MODULE, "rtc"); | 264 | rtc_class = class_create(THIS_MODULE, "rtc"); |
263 | if (IS_ERR(rtc_class)) { | 265 | if (IS_ERR(rtc_class)) { |
264 | printk(KERN_ERR "%s: couldn't create class\n", __FILE__); | 266 | pr_err("couldn't create class\n"); |
265 | return PTR_ERR(rtc_class); | 267 | return PTR_ERR(rtc_class); |
266 | } | 268 | } |
267 | rtc_class->suspend = rtc_suspend; | 269 | rtc_class->suspend = rtc_suspend; |
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index b6469e2cae89..434ebc3a99dc 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
@@ -86,7 +86,7 @@ static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm) | |||
86 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); | 86 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); |
87 | tm->tm_year = tm->tm_year - 1900; | 87 | tm->tm_year = tm->tm_year - 1900; |
88 | 88 | ||
89 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, | 89 | dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, |
90 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | 90 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
91 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 91 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
92 | 92 | ||
@@ -100,7 +100,7 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
100 | { | 100 | { |
101 | unsigned long cr; | 101 | unsigned long cr; |
102 | 102 | ||
103 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, | 103 | dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, |
104 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | 104 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
105 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 105 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
106 | 106 | ||
@@ -145,7 +145,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
145 | alrm->enabled = (at91_rtc_read(AT91_RTC_IMR) & AT91_RTC_ALARM) | 145 | alrm->enabled = (at91_rtc_read(AT91_RTC_IMR) & AT91_RTC_ALARM) |
146 | ? 1 : 0; | 146 | ? 1 : 0; |
147 | 147 | ||
148 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, | 148 | dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, |
149 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | 149 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
150 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 150 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
151 | 151 | ||
@@ -183,7 +183,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
183 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); | 183 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); |
184 | } | 184 | } |
185 | 185 | ||
186 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, | 186 | dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, |
187 | at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, | 187 | at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, |
188 | tm.tm_min, tm.tm_sec); | 188 | tm.tm_min, tm.tm_sec); |
189 | 189 | ||
@@ -192,7 +192,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
192 | 192 | ||
193 | static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 193 | static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
194 | { | 194 | { |
195 | pr_debug("%s(): cmd=%08x\n", __func__, enabled); | 195 | dev_dbg(dev, "%s(): cmd=%08x\n", __func__, enabled); |
196 | 196 | ||
197 | if (enabled) { | 197 | if (enabled) { |
198 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | 198 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); |
@@ -240,7 +240,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id) | |||
240 | 240 | ||
241 | rtc_update_irq(rtc, 1, events); | 241 | rtc_update_irq(rtc, 1, events); |
242 | 242 | ||
243 | pr_debug("%s(): num=%ld, events=0x%02lx\n", __func__, | 243 | dev_dbg(&pdev->dev, "%s(): num=%ld, events=0x%02lx\n", __func__, |
244 | events >> 8, events & 0x000000FF); | 244 | events >> 8, events & 0x000000FF); |
245 | 245 | ||
246 | return IRQ_HANDLED; | 246 | return IRQ_HANDLED; |
@@ -296,8 +296,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) | |||
296 | IRQF_SHARED, | 296 | IRQF_SHARED, |
297 | "at91_rtc", pdev); | 297 | "at91_rtc", pdev); |
298 | if (ret) { | 298 | if (ret) { |
299 | printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", | 299 | dev_err(&pdev->dev, "IRQ %d already in use.\n", irq); |
300 | irq); | ||
301 | return ret; | 300 | return ret; |
302 | } | 301 | } |
303 | 302 | ||
@@ -315,7 +314,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) | |||
315 | } | 314 | } |
316 | platform_set_drvdata(pdev, rtc); | 315 | platform_set_drvdata(pdev, rtc); |
317 | 316 | ||
318 | printk(KERN_INFO "AT91 Real Time Clock driver.\n"); | 317 | dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n"); |
319 | return 0; | 318 | return 0; |
320 | } | 319 | } |
321 | 320 | ||
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 16630aa87f45..af97c94e8a3a 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -706,7 +706,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
706 | rtc_cmos_int_handler = hpet_rtc_interrupt; | 706 | rtc_cmos_int_handler = hpet_rtc_interrupt; |
707 | err = hpet_register_irq_handler(cmos_interrupt); | 707 | err = hpet_register_irq_handler(cmos_interrupt); |
708 | if (err != 0) { | 708 | if (err != 0) { |
709 | printk(KERN_WARNING "hpet_register_irq_handler " | 709 | dev_warn(dev, "hpet_register_irq_handler " |
710 | " failed in rtc_init()."); | 710 | " failed in rtc_init()."); |
711 | goto cleanup1; | 711 | goto cleanup1; |
712 | } | 712 | } |
@@ -731,8 +731,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
731 | goto cleanup2; | 731 | goto cleanup2; |
732 | } | 732 | } |
733 | 733 | ||
734 | pr_info("%s: %s%s, %zd bytes nvram%s\n", | 734 | dev_info(dev, "%s%s, %zd bytes nvram%s\n", |
735 | dev_name(&cmos_rtc.rtc->dev), | ||
736 | !is_valid_irq(rtc_irq) ? "no alarms" : | 735 | !is_valid_irq(rtc_irq) ? "no alarms" : |
737 | cmos_rtc.mon_alrm ? "alarms up to one year" : | 736 | cmos_rtc.mon_alrm ? "alarms up to one year" : |
738 | cmos_rtc.day_alrm ? "alarms up to one month" : | 737 | cmos_rtc.day_alrm ? "alarms up to one month" : |
@@ -820,8 +819,7 @@ static int cmos_suspend(struct device *dev) | |||
820 | enable_irq_wake(cmos->irq); | 819 | enable_irq_wake(cmos->irq); |
821 | } | 820 | } |
822 | 821 | ||
823 | pr_debug("%s: suspend%s, ctrl %02x\n", | 822 | dev_dbg(dev, "suspend%s, ctrl %02x\n", |
824 | dev_name(&cmos_rtc.rtc->dev), | ||
825 | (tmp & RTC_AIE) ? ", alarm may wake" : "", | 823 | (tmp & RTC_AIE) ? ", alarm may wake" : "", |
826 | tmp); | 824 | tmp); |
827 | 825 | ||
@@ -876,9 +874,7 @@ static int cmos_resume(struct device *dev) | |||
876 | spin_unlock_irq(&rtc_lock); | 874 | spin_unlock_irq(&rtc_lock); |
877 | } | 875 | } |
878 | 876 | ||
879 | pr_debug("%s: resume, ctrl %02x\n", | 877 | dev_dbg(dev, "resume, ctrl %02x\n", tmp); |
880 | dev_name(&cmos_rtc.rtc->dev), | ||
881 | tmp); | ||
882 | 878 | ||
883 | return 0; | 879 | return 0; |
884 | } | 880 | } |
@@ -1098,7 +1094,6 @@ static __init void cmos_of_init(struct platform_device *pdev) | |||
1098 | } | 1094 | } |
1099 | #else | 1095 | #else |
1100 | static inline void cmos_of_init(struct platform_device *pdev) {} | 1096 | static inline void cmos_of_init(struct platform_device *pdev) {} |
1101 | #define of_cmos_match NULL | ||
1102 | #endif | 1097 | #endif |
1103 | /*----------------------------------------------------------------*/ | 1098 | /*----------------------------------------------------------------*/ |
1104 | 1099 | ||
@@ -1140,7 +1135,7 @@ static struct platform_driver cmos_platform_driver = { | |||
1140 | #ifdef CONFIG_PM | 1135 | #ifdef CONFIG_PM |
1141 | .pm = &cmos_pm_ops, | 1136 | .pm = &cmos_pm_ops, |
1142 | #endif | 1137 | #endif |
1143 | .of_match_table = of_cmos_match, | 1138 | .of_match_table = of_match_ptr(of_cmos_match), |
1144 | } | 1139 | } |
1145 | }; | 1140 | }; |
1146 | 1141 | ||
diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c index c8115b83e5ab..2d28ec1aa1cd 100644 --- a/drivers/rtc/rtc-coh901331.c +++ b/drivers/rtc/rtc-coh901331.c | |||
@@ -157,7 +157,6 @@ static int __exit coh901331_remove(struct platform_device *pdev) | |||
157 | if (rtap) { | 157 | if (rtap) { |
158 | rtc_device_unregister(rtap->rtc); | 158 | rtc_device_unregister(rtap->rtc); |
159 | clk_unprepare(rtap->clk); | 159 | clk_unprepare(rtap->clk); |
160 | clk_put(rtap->clk); | ||
161 | platform_set_drvdata(pdev, NULL); | 160 | platform_set_drvdata(pdev, NULL); |
162 | } | 161 | } |
163 | 162 | ||
@@ -196,7 +195,7 @@ static int __init coh901331_probe(struct platform_device *pdev) | |||
196 | "RTC COH 901 331 Alarm", rtap)) | 195 | "RTC COH 901 331 Alarm", rtap)) |
197 | return -EIO; | 196 | return -EIO; |
198 | 197 | ||
199 | rtap->clk = clk_get(&pdev->dev, NULL); | 198 | rtap->clk = devm_clk_get(&pdev->dev, NULL); |
200 | if (IS_ERR(rtap->clk)) { | 199 | if (IS_ERR(rtap->clk)) { |
201 | ret = PTR_ERR(rtap->clk); | 200 | ret = PTR_ERR(rtap->clk); |
202 | dev_err(&pdev->dev, "could not get clock\n"); | 201 | dev_err(&pdev->dev, "could not get clock\n"); |
@@ -207,7 +206,7 @@ static int __init coh901331_probe(struct platform_device *pdev) | |||
207 | ret = clk_prepare_enable(rtap->clk); | 206 | ret = clk_prepare_enable(rtap->clk); |
208 | if (ret) { | 207 | if (ret) { |
209 | dev_err(&pdev->dev, "could not enable clock\n"); | 208 | dev_err(&pdev->dev, "could not enable clock\n"); |
210 | goto out_no_clk_prepenable; | 209 | return ret; |
211 | } | 210 | } |
212 | clk_disable(rtap->clk); | 211 | clk_disable(rtap->clk); |
213 | 212 | ||
@@ -224,8 +223,6 @@ static int __init coh901331_probe(struct platform_device *pdev) | |||
224 | out_no_rtc: | 223 | out_no_rtc: |
225 | platform_set_drvdata(pdev, NULL); | 224 | platform_set_drvdata(pdev, NULL); |
226 | clk_unprepare(rtap->clk); | 225 | clk_unprepare(rtap->clk); |
227 | out_no_clk_prepenable: | ||
228 | clk_put(rtap->clk); | ||
229 | return ret; | 226 | return ret; |
230 | } | 227 | } |
231 | 228 | ||
diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index 60b826e520e2..0dde688ca09b 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c | |||
@@ -240,9 +240,10 @@ static int da9052_rtc_probe(struct platform_device *pdev) | |||
240 | rtc->da9052 = dev_get_drvdata(pdev->dev.parent); | 240 | rtc->da9052 = dev_get_drvdata(pdev->dev.parent); |
241 | platform_set_drvdata(pdev, rtc); | 241 | platform_set_drvdata(pdev, rtc); |
242 | rtc->irq = platform_get_irq_byname(pdev, "ALM"); | 242 | rtc->irq = platform_get_irq_byname(pdev, "ALM"); |
243 | ret = request_threaded_irq(rtc->irq, NULL, da9052_rtc_irq, | 243 | ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, |
244 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | 244 | da9052_rtc_irq, |
245 | "ALM", rtc); | 245 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, |
246 | "ALM", rtc); | ||
246 | if (ret != 0) { | 247 | if (ret != 0) { |
247 | rtc_err(rtc->da9052, "irq registration failed: %d\n", ret); | 248 | rtc_err(rtc->da9052, "irq registration failed: %d\n", ret); |
248 | return ret; | 249 | return ret; |
@@ -250,16 +251,10 @@ static int da9052_rtc_probe(struct platform_device *pdev) | |||
250 | 251 | ||
251 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | 252 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, |
252 | &da9052_rtc_ops, THIS_MODULE); | 253 | &da9052_rtc_ops, THIS_MODULE); |
253 | if (IS_ERR(rtc->rtc)) { | 254 | if (IS_ERR(rtc->rtc)) |
254 | ret = PTR_ERR(rtc->rtc); | 255 | return PTR_ERR(rtc->rtc); |
255 | goto err_free_irq; | ||
256 | } | ||
257 | 256 | ||
258 | return 0; | 257 | return 0; |
259 | |||
260 | err_free_irq: | ||
261 | free_irq(rtc->irq, rtc); | ||
262 | return ret; | ||
263 | } | 258 | } |
264 | 259 | ||
265 | static int da9052_rtc_remove(struct platform_device *pdev) | 260 | static int da9052_rtc_remove(struct platform_device *pdev) |
@@ -267,7 +262,6 @@ static int da9052_rtc_remove(struct platform_device *pdev) | |||
267 | struct da9052_rtc *rtc = pdev->dev.platform_data; | 262 | struct da9052_rtc *rtc = pdev->dev.platform_data; |
268 | 263 | ||
269 | rtc_device_unregister(rtc->rtc); | 264 | rtc_device_unregister(rtc->rtc); |
270 | free_irq(rtc->irq, rtc); | ||
271 | platform_set_drvdata(pdev, NULL); | 265 | platform_set_drvdata(pdev, NULL); |
272 | 266 | ||
273 | return 0; | 267 | return 0; |
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index 5f7982f7c1b5..56b73089bb29 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c | |||
@@ -506,19 +506,19 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) | |||
506 | davinci_rtc->pbase = res->start; | 506 | davinci_rtc->pbase = res->start; |
507 | davinci_rtc->base_size = resource_size(res); | 507 | davinci_rtc->base_size = resource_size(res); |
508 | 508 | ||
509 | mem = request_mem_region(davinci_rtc->pbase, davinci_rtc->base_size, | 509 | mem = devm_request_mem_region(dev, davinci_rtc->pbase, |
510 | pdev->name); | 510 | davinci_rtc->base_size, pdev->name); |
511 | if (!mem) { | 511 | if (!mem) { |
512 | dev_err(dev, "RTC registers at %08x are not free\n", | 512 | dev_err(dev, "RTC registers at %08x are not free\n", |
513 | davinci_rtc->pbase); | 513 | davinci_rtc->pbase); |
514 | return -EBUSY; | 514 | return -EBUSY; |
515 | } | 515 | } |
516 | 516 | ||
517 | davinci_rtc->base = ioremap(davinci_rtc->pbase, davinci_rtc->base_size); | 517 | davinci_rtc->base = devm_ioremap(dev, davinci_rtc->pbase, |
518 | davinci_rtc->base_size); | ||
518 | if (!davinci_rtc->base) { | 519 | if (!davinci_rtc->base) { |
519 | dev_err(dev, "unable to ioremap MEM resource\n"); | 520 | dev_err(dev, "unable to ioremap MEM resource\n"); |
520 | ret = -ENOMEM; | 521 | return -ENOMEM; |
521 | goto fail2; | ||
522 | } | 522 | } |
523 | 523 | ||
524 | platform_set_drvdata(pdev, davinci_rtc); | 524 | platform_set_drvdata(pdev, davinci_rtc); |
@@ -529,7 +529,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) | |||
529 | ret = PTR_ERR(davinci_rtc->rtc); | 529 | ret = PTR_ERR(davinci_rtc->rtc); |
530 | dev_err(dev, "unable to register RTC device, err %d\n", | 530 | dev_err(dev, "unable to register RTC device, err %d\n", |
531 | ret); | 531 | ret); |
532 | goto fail3; | 532 | goto fail1; |
533 | } | 533 | } |
534 | 534 | ||
535 | rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, PRTCIF_INTFLG); | 535 | rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, PRTCIF_INTFLG); |
@@ -539,11 +539,11 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) | |||
539 | rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CTRL); | 539 | rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CTRL); |
540 | rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CCTRL); | 540 | rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CCTRL); |
541 | 541 | ||
542 | ret = request_irq(davinci_rtc->irq, davinci_rtc_interrupt, | 542 | ret = devm_request_irq(dev, davinci_rtc->irq, davinci_rtc_interrupt, |
543 | 0, "davinci_rtc", davinci_rtc); | 543 | 0, "davinci_rtc", davinci_rtc); |
544 | if (ret < 0) { | 544 | if (ret < 0) { |
545 | dev_err(dev, "unable to register davinci RTC interrupt\n"); | 545 | dev_err(dev, "unable to register davinci RTC interrupt\n"); |
546 | goto fail4; | 546 | goto fail2; |
547 | } | 547 | } |
548 | 548 | ||
549 | /* Enable interrupts */ | 549 | /* Enable interrupts */ |
@@ -557,13 +557,10 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) | |||
557 | 557 | ||
558 | return 0; | 558 | return 0; |
559 | 559 | ||
560 | fail4: | 560 | fail2: |
561 | rtc_device_unregister(davinci_rtc->rtc); | 561 | rtc_device_unregister(davinci_rtc->rtc); |
562 | fail3: | 562 | fail1: |
563 | platform_set_drvdata(pdev, NULL); | 563 | platform_set_drvdata(pdev, NULL); |
564 | iounmap(davinci_rtc->base); | ||
565 | fail2: | ||
566 | release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); | ||
567 | return ret; | 564 | return ret; |
568 | } | 565 | } |
569 | 566 | ||
@@ -575,13 +572,8 @@ static int davinci_rtc_remove(struct platform_device *pdev) | |||
575 | 572 | ||
576 | rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); | 573 | rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); |
577 | 574 | ||
578 | free_irq(davinci_rtc->irq, davinci_rtc); | ||
579 | |||
580 | rtc_device_unregister(davinci_rtc->rtc); | 575 | rtc_device_unregister(davinci_rtc->rtc); |
581 | 576 | ||
582 | iounmap(davinci_rtc->base); | ||
583 | release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); | ||
584 | |||
585 | platform_set_drvdata(pdev, NULL); | 577 | platform_set_drvdata(pdev, NULL); |
586 | 578 | ||
587 | return 0; | 579 | return 0; |
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 9a86b4bd8699..d04939369251 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
@@ -11,6 +11,8 @@ | |||
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
15 | |||
14 | #include <linux/module.h> | 16 | #include <linux/module.h> |
15 | #include <linux/rtc.h> | 17 | #include <linux/rtc.h> |
16 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
@@ -462,7 +464,7 @@ void rtc_dev_prepare(struct rtc_device *rtc) | |||
462 | return; | 464 | return; |
463 | 465 | ||
464 | if (rtc->id >= RTC_DEV_MAX) { | 466 | if (rtc->id >= RTC_DEV_MAX) { |
465 | pr_debug("%s: too many RTC devices\n", rtc->name); | 467 | dev_dbg(&rtc->dev, "%s: too many RTC devices\n", rtc->name); |
466 | return; | 468 | return; |
467 | } | 469 | } |
468 | 470 | ||
@@ -480,10 +482,10 @@ void rtc_dev_prepare(struct rtc_device *rtc) | |||
480 | void rtc_dev_add_device(struct rtc_device *rtc) | 482 | void rtc_dev_add_device(struct rtc_device *rtc) |
481 | { | 483 | { |
482 | if (cdev_add(&rtc->char_dev, rtc->dev.devt, 1)) | 484 | if (cdev_add(&rtc->char_dev, rtc->dev.devt, 1)) |
483 | printk(KERN_WARNING "%s: failed to add char device %d:%d\n", | 485 | dev_warn(&rtc->dev, "%s: failed to add char device %d:%d\n", |
484 | rtc->name, MAJOR(rtc_devt), rtc->id); | 486 | rtc->name, MAJOR(rtc_devt), rtc->id); |
485 | else | 487 | else |
486 | pr_debug("%s: dev (%d:%d)\n", rtc->name, | 488 | dev_dbg(&rtc->dev, "%s: dev (%d:%d)\n", rtc->name, |
487 | MAJOR(rtc_devt), rtc->id); | 489 | MAJOR(rtc_devt), rtc->id); |
488 | } | 490 | } |
489 | 491 | ||
@@ -499,8 +501,7 @@ void __init rtc_dev_init(void) | |||
499 | 501 | ||
500 | err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc"); | 502 | err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc"); |
501 | if (err < 0) | 503 | if (err < 0) |
502 | printk(KERN_ERR "%s: failed to allocate char dev region\n", | 504 | pr_err("failed to allocate char dev region\n"); |
503 | __FILE__); | ||
504 | } | 505 | } |
505 | 506 | ||
506 | void __exit rtc_dev_exit(void) | 507 | void __exit rtc_dev_exit(void) |
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index d578773f5ce2..b05a6dc96405 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c | |||
@@ -635,9 +635,7 @@ static int ds1305_probe(struct spi_device *spi) | |||
635 | goto fail0; | 635 | goto fail0; |
636 | } | 636 | } |
637 | 637 | ||
638 | dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n", | 638 | dev_dbg(&spi->dev, "ctrl %s: %3ph\n", "read", ds1305->ctrl); |
639 | "read", ds1305->ctrl[0], | ||
640 | ds1305->ctrl[1], ds1305->ctrl[2]); | ||
641 | 639 | ||
642 | /* Sanity check register values ... partially compensating for the | 640 | /* Sanity check register values ... partially compensating for the |
643 | * fact that SPI has no device handshake. A pullup on MISO would | 641 | * fact that SPI has no device handshake. A pullup on MISO would |
@@ -723,9 +721,7 @@ static int ds1305_probe(struct spi_device *spi) | |||
723 | goto fail0; | 721 | goto fail0; |
724 | } | 722 | } |
725 | 723 | ||
726 | dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n", | 724 | dev_dbg(&spi->dev, "ctrl %s: %3ph\n", "write", ds1305->ctrl); |
727 | "write", ds1305->ctrl[0], | ||
728 | ds1305->ctrl[1], ds1305->ctrl[2]); | ||
729 | } | 725 | } |
730 | 726 | ||
731 | /* see if non-Linux software set up AM/PM mode */ | 727 | /* see if non-Linux software set up AM/PM mode */ |
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index e0d0ba4de03f..970a236b147a 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -322,12 +322,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) | |||
322 | return -EIO; | 322 | return -EIO; |
323 | } | 323 | } |
324 | 324 | ||
325 | dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n", | 325 | dev_dbg(dev, "%s: %7ph\n", "read", ds1307->regs); |
326 | "read", | ||
327 | ds1307->regs[0], ds1307->regs[1], | ||
328 | ds1307->regs[2], ds1307->regs[3], | ||
329 | ds1307->regs[4], ds1307->regs[5], | ||
330 | ds1307->regs[6]); | ||
331 | 326 | ||
332 | t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f); | 327 | t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f); |
333 | t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f); | 328 | t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f); |
@@ -398,9 +393,7 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) | |||
398 | break; | 393 | break; |
399 | } | 394 | } |
400 | 395 | ||
401 | dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n", | 396 | dev_dbg(dev, "%s: %7ph\n", "write", buf); |
402 | "write", buf[0], buf[1], buf[2], buf[3], | ||
403 | buf[4], buf[5], buf[6]); | ||
404 | 397 | ||
405 | result = ds1307->write_block_data(ds1307->client, | 398 | result = ds1307->write_block_data(ds1307->client, |
406 | ds1307->offset, 7, buf); | 399 | ds1307->offset, 7, buf); |
diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c index 5ea9df7c8c31..b04fc4272fb3 100644 --- a/drivers/rtc/rtc-ds2404.c +++ b/drivers/rtc/rtc-ds2404.c | |||
@@ -70,7 +70,7 @@ static int ds2404_gpio_map(struct ds2404 *chip, struct platform_device *pdev, | |||
70 | for (i = 0; i < ARRAY_SIZE(ds2404_gpio); i++) { | 70 | for (i = 0; i < ARRAY_SIZE(ds2404_gpio); i++) { |
71 | err = gpio_request(ds2404_gpio[i].gpio, ds2404_gpio[i].name); | 71 | err = gpio_request(ds2404_gpio[i].gpio, ds2404_gpio[i].name); |
72 | if (err) { | 72 | if (err) { |
73 | printk(KERN_ERR "error mapping gpio %s: %d\n", | 73 | dev_err(&pdev->dev, "error mapping gpio %s: %d\n", |
74 | ds2404_gpio[i].name, err); | 74 | ds2404_gpio[i].name, err); |
75 | goto err_request; | 75 | goto err_request; |
76 | } | 76 | } |
@@ -177,7 +177,7 @@ static void ds2404_write_memory(struct device *dev, u16 offset, | |||
177 | 177 | ||
178 | for (i = 0; i < length; i++) { | 178 | for (i = 0; i < length; i++) { |
179 | if (out[i] != ds2404_read_byte(dev)) { | 179 | if (out[i] != ds2404_read_byte(dev)) { |
180 | printk(KERN_ERR "read invalid data\n"); | 180 | dev_err(dev, "read invalid data\n"); |
181 | return; | 181 | return; |
182 | } | 182 | } |
183 | } | 183 | } |
@@ -283,19 +283,7 @@ static struct platform_driver rtc_device_driver = { | |||
283 | .owner = THIS_MODULE, | 283 | .owner = THIS_MODULE, |
284 | }, | 284 | }, |
285 | }; | 285 | }; |
286 | 286 | module_platform_driver(rtc_device_driver); | |
287 | static __init int ds2404_init(void) | ||
288 | { | ||
289 | return platform_driver_register(&rtc_device_driver); | ||
290 | } | ||
291 | |||
292 | static __exit void ds2404_exit(void) | ||
293 | { | ||
294 | platform_driver_unregister(&rtc_device_driver); | ||
295 | } | ||
296 | |||
297 | module_init(ds2404_init); | ||
298 | module_exit(ds2404_exit); | ||
299 | 287 | ||
300 | MODULE_DESCRIPTION("DS2404 RTC"); | 288 | MODULE_DESCRIPTION("DS2404 RTC"); |
301 | MODULE_AUTHOR("Sven Schnelle"); | 289 | MODULE_AUTHOR("Sven Schnelle"); |
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c index c9f890b088da..1a0c37c9152b 100644 --- a/drivers/rtc/rtc-efi.c +++ b/drivers/rtc/rtc-efi.c | |||
@@ -13,6 +13,8 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
17 | |||
16 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | 19 | #include <linux/module.h> |
18 | #include <linux/time.h> | 20 | #include <linux/time.h> |
@@ -47,7 +49,7 @@ compute_wday(efi_time_t *eft) | |||
47 | int ndays = 0; | 49 | int ndays = 0; |
48 | 50 | ||
49 | if (eft->year < 1998) { | 51 | if (eft->year < 1998) { |
50 | printk(KERN_ERR "efirtc: EFI year < 1998, invalid date\n"); | 52 | pr_err("EFI year < 1998, invalid date\n"); |
51 | return -1; | 53 | return -1; |
52 | } | 54 | } |
53 | 55 | ||
@@ -70,7 +72,7 @@ convert_to_efi_time(struct rtc_time *wtime, efi_time_t *eft) | |||
70 | eft->day = wtime->tm_mday; | 72 | eft->day = wtime->tm_mday; |
71 | eft->hour = wtime->tm_hour; | 73 | eft->hour = wtime->tm_hour; |
72 | eft->minute = wtime->tm_min; | 74 | eft->minute = wtime->tm_min; |
73 | eft->second = wtime->tm_sec; | 75 | eft->second = wtime->tm_sec; |
74 | eft->nanosecond = 0; | 76 | eft->nanosecond = 0; |
75 | eft->daylight = wtime->tm_isdst ? EFI_ISDST : 0; | 77 | eft->daylight = wtime->tm_isdst ? EFI_ISDST : 0; |
76 | eft->timezone = EFI_UNSPECIFIED_TIMEZONE; | 78 | eft->timezone = EFI_UNSPECIFIED_TIMEZONE; |
@@ -142,7 +144,7 @@ static int efi_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
142 | */ | 144 | */ |
143 | status = efi.set_wakeup_time((efi_bool_t)wkalrm->enabled, &eft); | 145 | status = efi.set_wakeup_time((efi_bool_t)wkalrm->enabled, &eft); |
144 | 146 | ||
145 | printk(KERN_WARNING "write status is %d\n", (int)status); | 147 | dev_warn(dev, "write status is %d\n", (int)status); |
146 | 148 | ||
147 | return status == EFI_SUCCESS ? 0 : -EINVAL; | 149 | return status == EFI_SUCCESS ? 0 : -EINVAL; |
148 | } | 150 | } |
@@ -157,7 +159,7 @@ static int efi_read_time(struct device *dev, struct rtc_time *tm) | |||
157 | 159 | ||
158 | if (status != EFI_SUCCESS) { | 160 | if (status != EFI_SUCCESS) { |
159 | /* should never happen */ | 161 | /* should never happen */ |
160 | printk(KERN_ERR "efitime: can't read time\n"); | 162 | dev_err(dev, "can't read time\n"); |
161 | return -EINVAL; | 163 | return -EINVAL; |
162 | } | 164 | } |
163 | 165 | ||
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index 04e93c6597f8..bff3cdc5140e 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c | |||
@@ -116,17 +116,7 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t) | |||
116 | 116 | ||
117 | fm3130_rtc_mode(dev, FM3130_MODE_NORMAL); | 117 | fm3130_rtc_mode(dev, FM3130_MODE_NORMAL); |
118 | 118 | ||
119 | dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x" | 119 | dev_dbg(dev, "%s: %15ph\n", "read", fm3130->regs); |
120 | "%02x %02x %02x %02x %02x %02x %02x\n", | ||
121 | "read", | ||
122 | fm3130->regs[0], fm3130->regs[1], | ||
123 | fm3130->regs[2], fm3130->regs[3], | ||
124 | fm3130->regs[4], fm3130->regs[5], | ||
125 | fm3130->regs[6], fm3130->regs[7], | ||
126 | fm3130->regs[8], fm3130->regs[9], | ||
127 | fm3130->regs[0xa], fm3130->regs[0xb], | ||
128 | fm3130->regs[0xc], fm3130->regs[0xd], | ||
129 | fm3130->regs[0xe]); | ||
130 | 120 | ||
131 | t->tm_sec = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f); | 121 | t->tm_sec = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f); |
132 | t->tm_min = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); | 122 | t->tm_min = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); |
@@ -175,12 +165,7 @@ static int fm3130_set_time(struct device *dev, struct rtc_time *t) | |||
175 | tmp = t->tm_year - 100; | 165 | tmp = t->tm_year - 100; |
176 | buf[FM3130_RTC_YEARS] = bin2bcd(tmp); | 166 | buf[FM3130_RTC_YEARS] = bin2bcd(tmp); |
177 | 167 | ||
178 | dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x" | 168 | dev_dbg(dev, "%s: %15ph\n", "write", buf); |
179 | "%02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
180 | "write", buf[0], buf[1], buf[2], buf[3], | ||
181 | buf[4], buf[5], buf[6], buf[7], | ||
182 | buf[8], buf[9], buf[0xa], buf[0xb], | ||
183 | buf[0xc], buf[0xd], buf[0xe]); | ||
184 | 169 | ||
185 | fm3130_rtc_mode(dev, FM3130_MODE_WRITE); | 170 | fm3130_rtc_mode(dev, FM3130_MODE_WRITE); |
186 | 171 | ||
@@ -517,18 +502,8 @@ bad_alarm: | |||
517 | bad_clock: | 502 | bad_clock: |
518 | 503 | ||
519 | if (!fm3130->data_valid || !fm3130->alarm_valid) | 504 | if (!fm3130->data_valid || !fm3130->alarm_valid) |
520 | dev_dbg(&client->dev, | 505 | dev_dbg(&client->dev, "%s: %15ph\n", "bogus registers", |
521 | "%s: %02x %02x %02x %02x %02x %02x %02x %02x" | 506 | fm3130->regs); |
522 | "%02x %02x %02x %02x %02x %02x %02x\n", | ||
523 | "bogus registers", | ||
524 | fm3130->regs[0], fm3130->regs[1], | ||
525 | fm3130->regs[2], fm3130->regs[3], | ||
526 | fm3130->regs[4], fm3130->regs[5], | ||
527 | fm3130->regs[6], fm3130->regs[7], | ||
528 | fm3130->regs[8], fm3130->regs[9], | ||
529 | fm3130->regs[0xa], fm3130->regs[0xb], | ||
530 | fm3130->regs[0xc], fm3130->regs[0xd], | ||
531 | fm3130->regs[0xe]); | ||
532 | 507 | ||
533 | /* We won't bail out here because we just got invalid data. | 508 | /* We won't bail out here because we just got invalid data. |
534 | Time setting from u-boot doesn't work anyway */ | 509 | Time setting from u-boot doesn't work anyway */ |
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 75d307ab37f4..82aad695979e 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c | |||
@@ -406,7 +406,7 @@ static int dryice_rtc_probe(struct platform_device *pdev) | |||
406 | 406 | ||
407 | mutex_init(&imxdi->write_mutex); | 407 | mutex_init(&imxdi->write_mutex); |
408 | 408 | ||
409 | imxdi->clk = clk_get(&pdev->dev, NULL); | 409 | imxdi->clk = devm_clk_get(&pdev->dev, NULL); |
410 | if (IS_ERR(imxdi->clk)) | 410 | if (IS_ERR(imxdi->clk)) |
411 | return PTR_ERR(imxdi->clk); | 411 | return PTR_ERR(imxdi->clk); |
412 | clk_prepare_enable(imxdi->clk); | 412 | clk_prepare_enable(imxdi->clk); |
@@ -475,7 +475,6 @@ static int dryice_rtc_probe(struct platform_device *pdev) | |||
475 | 475 | ||
476 | err: | 476 | err: |
477 | clk_disable_unprepare(imxdi->clk); | 477 | clk_disable_unprepare(imxdi->clk); |
478 | clk_put(imxdi->clk); | ||
479 | 478 | ||
480 | return rc; | 479 | return rc; |
481 | } | 480 | } |
@@ -492,7 +491,6 @@ static int dryice_rtc_remove(struct platform_device *pdev) | |||
492 | rtc_device_unregister(imxdi->rtc); | 491 | rtc_device_unregister(imxdi->rtc); |
493 | 492 | ||
494 | clk_disable_unprepare(imxdi->clk); | 493 | clk_disable_unprepare(imxdi->clk); |
495 | clk_put(imxdi->clk); | ||
496 | 494 | ||
497 | return 0; | 495 | return 0; |
498 | } | 496 | } |
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 1850104705c0..6b4298ea683d 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c | |||
@@ -227,7 +227,7 @@ static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
227 | buf[ISL12022_REG_SC + i]); | 227 | buf[ISL12022_REG_SC + i]); |
228 | if (ret) | 228 | if (ret) |
229 | return -EIO; | 229 | return -EIO; |
230 | }; | 230 | } |
231 | 231 | ||
232 | return 0; | 232 | return 0; |
233 | } | 233 | } |
diff --git a/drivers/rtc/rtc-lp8788.c b/drivers/rtc/rtc-lp8788.c new file mode 100644 index 000000000000..9a4631218f41 --- /dev/null +++ b/drivers/rtc/rtc-lp8788.c | |||
@@ -0,0 +1,338 @@ | |||
1 | /* | ||
2 | * TI LP8788 MFD - rtc driver | ||
3 | * | ||
4 | * Copyright 2012 Texas Instruments | ||
5 | * | ||
6 | * Author: Milo(Woogyom) Kim <milo.kim@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/err.h> | ||
15 | #include <linux/irqdomain.h> | ||
16 | #include <linux/mfd/lp8788.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | /* register address */ | ||
23 | #define LP8788_INTEN_3 0x05 | ||
24 | #define LP8788_RTC_UNLOCK 0x64 | ||
25 | #define LP8788_RTC_SEC 0x70 | ||
26 | #define LP8788_ALM1_SEC 0x77 | ||
27 | #define LP8788_ALM1_EN 0x7D | ||
28 | #define LP8788_ALM2_SEC 0x7E | ||
29 | #define LP8788_ALM2_EN 0x84 | ||
30 | |||
31 | /* mask/shift bits */ | ||
32 | #define LP8788_INT_RTC_ALM1_M BIT(1) /* Addr 05h */ | ||
33 | #define LP8788_INT_RTC_ALM1_S 1 | ||
34 | #define LP8788_INT_RTC_ALM2_M BIT(2) /* Addr 05h */ | ||
35 | #define LP8788_INT_RTC_ALM2_S 2 | ||
36 | #define LP8788_ALM_EN_M BIT(7) /* Addr 7Dh or 84h */ | ||
37 | #define LP8788_ALM_EN_S 7 | ||
38 | |||
39 | #define DEFAULT_ALARM_SEL LP8788_ALARM_1 | ||
40 | #define LP8788_MONTH_OFFSET 1 | ||
41 | #define LP8788_BASE_YEAR 2000 | ||
42 | #define MAX_WDAY_BITS 7 | ||
43 | #define LP8788_WDAY_SET 1 | ||
44 | #define RTC_UNLOCK 0x1 | ||
45 | #define RTC_LATCH 0x2 | ||
46 | #define ALARM_IRQ_FLAG (RTC_IRQF | RTC_AF) | ||
47 | |||
48 | enum lp8788_time { | ||
49 | LPTIME_SEC, | ||
50 | LPTIME_MIN, | ||
51 | LPTIME_HOUR, | ||
52 | LPTIME_MDAY, | ||
53 | LPTIME_MON, | ||
54 | LPTIME_YEAR, | ||
55 | LPTIME_WDAY, | ||
56 | LPTIME_MAX, | ||
57 | }; | ||
58 | |||
59 | struct lp8788_rtc { | ||
60 | struct lp8788 *lp; | ||
61 | struct rtc_device *rdev; | ||
62 | enum lp8788_alarm_sel alarm; | ||
63 | int irq; | ||
64 | }; | ||
65 | |||
66 | static const u8 addr_alarm_sec[LP8788_ALARM_MAX] = { | ||
67 | LP8788_ALM1_SEC, | ||
68 | LP8788_ALM2_SEC, | ||
69 | }; | ||
70 | |||
71 | static const u8 addr_alarm_en[LP8788_ALARM_MAX] = { | ||
72 | LP8788_ALM1_EN, | ||
73 | LP8788_ALM2_EN, | ||
74 | }; | ||
75 | |||
76 | static const u8 mask_alarm_en[LP8788_ALARM_MAX] = { | ||
77 | LP8788_INT_RTC_ALM1_M, | ||
78 | LP8788_INT_RTC_ALM2_M, | ||
79 | }; | ||
80 | |||
81 | static const u8 shift_alarm_en[LP8788_ALARM_MAX] = { | ||
82 | LP8788_INT_RTC_ALM1_S, | ||
83 | LP8788_INT_RTC_ALM2_S, | ||
84 | }; | ||
85 | |||
86 | static int _to_tm_wday(u8 lp8788_wday) | ||
87 | { | ||
88 | int i; | ||
89 | |||
90 | if (lp8788_wday == 0) | ||
91 | return 0; | ||
92 | |||
93 | /* lookup defined weekday from read register value */ | ||
94 | for (i = 0; i < MAX_WDAY_BITS; i++) { | ||
95 | if ((lp8788_wday >> i) == LP8788_WDAY_SET) | ||
96 | break; | ||
97 | } | ||
98 | |||
99 | return i + 1; | ||
100 | } | ||
101 | |||
102 | static inline int _to_lp8788_wday(int tm_wday) | ||
103 | { | ||
104 | return LP8788_WDAY_SET << (tm_wday - 1); | ||
105 | } | ||
106 | |||
107 | static void lp8788_rtc_unlock(struct lp8788 *lp) | ||
108 | { | ||
109 | lp8788_write_byte(lp, LP8788_RTC_UNLOCK, RTC_UNLOCK); | ||
110 | lp8788_write_byte(lp, LP8788_RTC_UNLOCK, RTC_LATCH); | ||
111 | } | ||
112 | |||
113 | static int lp8788_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
114 | { | ||
115 | struct lp8788_rtc *rtc = dev_get_drvdata(dev); | ||
116 | struct lp8788 *lp = rtc->lp; | ||
117 | u8 data[LPTIME_MAX]; | ||
118 | int ret; | ||
119 | |||
120 | lp8788_rtc_unlock(lp); | ||
121 | |||
122 | ret = lp8788_read_multi_bytes(lp, LP8788_RTC_SEC, data, LPTIME_MAX); | ||
123 | if (ret) | ||
124 | return ret; | ||
125 | |||
126 | tm->tm_sec = data[LPTIME_SEC]; | ||
127 | tm->tm_min = data[LPTIME_MIN]; | ||
128 | tm->tm_hour = data[LPTIME_HOUR]; | ||
129 | tm->tm_mday = data[LPTIME_MDAY]; | ||
130 | tm->tm_mon = data[LPTIME_MON] - LP8788_MONTH_OFFSET; | ||
131 | tm->tm_year = data[LPTIME_YEAR] + LP8788_BASE_YEAR - 1900; | ||
132 | tm->tm_wday = _to_tm_wday(data[LPTIME_WDAY]); | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int lp8788_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
138 | { | ||
139 | struct lp8788_rtc *rtc = dev_get_drvdata(dev); | ||
140 | struct lp8788 *lp = rtc->lp; | ||
141 | u8 data[LPTIME_MAX - 1]; | ||
142 | int ret, i, year; | ||
143 | |||
144 | year = tm->tm_year + 1900 - LP8788_BASE_YEAR; | ||
145 | if (year < 0) { | ||
146 | dev_err(lp->dev, "invalid year: %d\n", year); | ||
147 | return -EINVAL; | ||
148 | } | ||
149 | |||
150 | /* because rtc weekday is a readonly register, do not update */ | ||
151 | data[LPTIME_SEC] = tm->tm_sec; | ||
152 | data[LPTIME_MIN] = tm->tm_min; | ||
153 | data[LPTIME_HOUR] = tm->tm_hour; | ||
154 | data[LPTIME_MDAY] = tm->tm_mday; | ||
155 | data[LPTIME_MON] = tm->tm_mon + LP8788_MONTH_OFFSET; | ||
156 | data[LPTIME_YEAR] = year; | ||
157 | |||
158 | for (i = 0; i < ARRAY_SIZE(data); i++) { | ||
159 | ret = lp8788_write_byte(lp, LP8788_RTC_SEC + i, data[i]); | ||
160 | if (ret) | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int lp8788_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
168 | { | ||
169 | struct lp8788_rtc *rtc = dev_get_drvdata(dev); | ||
170 | struct lp8788 *lp = rtc->lp; | ||
171 | struct rtc_time *tm = &alarm->time; | ||
172 | u8 addr, data[LPTIME_MAX]; | ||
173 | int ret; | ||
174 | |||
175 | addr = addr_alarm_sec[rtc->alarm]; | ||
176 | ret = lp8788_read_multi_bytes(lp, addr, data, LPTIME_MAX); | ||
177 | if (ret) | ||
178 | return ret; | ||
179 | |||
180 | tm->tm_sec = data[LPTIME_SEC]; | ||
181 | tm->tm_min = data[LPTIME_MIN]; | ||
182 | tm->tm_hour = data[LPTIME_HOUR]; | ||
183 | tm->tm_mday = data[LPTIME_MDAY]; | ||
184 | tm->tm_mon = data[LPTIME_MON] - LP8788_MONTH_OFFSET; | ||
185 | tm->tm_year = data[LPTIME_YEAR] + LP8788_BASE_YEAR - 1900; | ||
186 | tm->tm_wday = _to_tm_wday(data[LPTIME_WDAY]); | ||
187 | alarm->enabled = data[LPTIME_WDAY] & LP8788_ALM_EN_M; | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int lp8788_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
193 | { | ||
194 | struct lp8788_rtc *rtc = dev_get_drvdata(dev); | ||
195 | struct lp8788 *lp = rtc->lp; | ||
196 | struct rtc_time *tm = &alarm->time; | ||
197 | u8 addr, data[LPTIME_MAX]; | ||
198 | int ret, i, year; | ||
199 | |||
200 | year = tm->tm_year + 1900 - LP8788_BASE_YEAR; | ||
201 | if (year < 0) { | ||
202 | dev_err(lp->dev, "invalid year: %d\n", year); | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | |||
206 | data[LPTIME_SEC] = tm->tm_sec; | ||
207 | data[LPTIME_MIN] = tm->tm_min; | ||
208 | data[LPTIME_HOUR] = tm->tm_hour; | ||
209 | data[LPTIME_MDAY] = tm->tm_mday; | ||
210 | data[LPTIME_MON] = tm->tm_mon + LP8788_MONTH_OFFSET; | ||
211 | data[LPTIME_YEAR] = year; | ||
212 | data[LPTIME_WDAY] = _to_lp8788_wday(tm->tm_wday); | ||
213 | |||
214 | for (i = 0; i < ARRAY_SIZE(data); i++) { | ||
215 | addr = addr_alarm_sec[rtc->alarm] + i; | ||
216 | ret = lp8788_write_byte(lp, addr, data[i]); | ||
217 | if (ret) | ||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | alarm->enabled = 1; | ||
222 | addr = addr_alarm_en[rtc->alarm]; | ||
223 | |||
224 | return lp8788_update_bits(lp, addr, LP8788_ALM_EN_M, | ||
225 | alarm->enabled << LP8788_ALM_EN_S); | ||
226 | } | ||
227 | |||
228 | static int lp8788_alarm_irq_enable(struct device *dev, unsigned int enable) | ||
229 | { | ||
230 | struct lp8788_rtc *rtc = dev_get_drvdata(dev); | ||
231 | struct lp8788 *lp = rtc->lp; | ||
232 | u8 mask, shift; | ||
233 | |||
234 | if (!rtc->irq) | ||
235 | return -EIO; | ||
236 | |||
237 | mask = mask_alarm_en[rtc->alarm]; | ||
238 | shift = shift_alarm_en[rtc->alarm]; | ||
239 | |||
240 | return lp8788_update_bits(lp, LP8788_INTEN_3, mask, enable << shift); | ||
241 | } | ||
242 | |||
243 | static const struct rtc_class_ops lp8788_rtc_ops = { | ||
244 | .read_time = lp8788_rtc_read_time, | ||
245 | .set_time = lp8788_rtc_set_time, | ||
246 | .read_alarm = lp8788_read_alarm, | ||
247 | .set_alarm = lp8788_set_alarm, | ||
248 | .alarm_irq_enable = lp8788_alarm_irq_enable, | ||
249 | }; | ||
250 | |||
251 | static irqreturn_t lp8788_alarm_irq_handler(int irq, void *ptr) | ||
252 | { | ||
253 | struct lp8788_rtc *rtc = ptr; | ||
254 | |||
255 | rtc_update_irq(rtc->rdev, 1, ALARM_IRQ_FLAG); | ||
256 | return IRQ_HANDLED; | ||
257 | } | ||
258 | |||
259 | static int lp8788_alarm_irq_register(struct platform_device *pdev, | ||
260 | struct lp8788_rtc *rtc) | ||
261 | { | ||
262 | struct resource *r; | ||
263 | struct lp8788 *lp = rtc->lp; | ||
264 | struct irq_domain *irqdm = lp->irqdm; | ||
265 | int irq; | ||
266 | |||
267 | rtc->irq = 0; | ||
268 | |||
269 | /* even the alarm IRQ number is not specified, rtc time should work */ | ||
270 | r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, LP8788_ALM_IRQ); | ||
271 | if (!r) | ||
272 | return 0; | ||
273 | |||
274 | if (rtc->alarm == LP8788_ALARM_1) | ||
275 | irq = r->start; | ||
276 | else | ||
277 | irq = r->end; | ||
278 | |||
279 | rtc->irq = irq_create_mapping(irqdm, irq); | ||
280 | |||
281 | return devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, | ||
282 | lp8788_alarm_irq_handler, | ||
283 | 0, LP8788_ALM_IRQ, rtc); | ||
284 | } | ||
285 | |||
286 | static int lp8788_rtc_probe(struct platform_device *pdev) | ||
287 | { | ||
288 | struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); | ||
289 | struct lp8788_rtc *rtc; | ||
290 | struct device *dev = &pdev->dev; | ||
291 | |||
292 | rtc = devm_kzalloc(dev, sizeof(struct lp8788_rtc), GFP_KERNEL); | ||
293 | if (!rtc) | ||
294 | return -ENOMEM; | ||
295 | |||
296 | rtc->lp = lp; | ||
297 | rtc->alarm = lp->pdata ? lp->pdata->alarm_sel : DEFAULT_ALARM_SEL; | ||
298 | platform_set_drvdata(pdev, rtc); | ||
299 | |||
300 | device_init_wakeup(dev, 1); | ||
301 | |||
302 | rtc->rdev = rtc_device_register("lp8788_rtc", dev, | ||
303 | &lp8788_rtc_ops, THIS_MODULE); | ||
304 | if (IS_ERR(rtc->rdev)) { | ||
305 | dev_err(dev, "can not register rtc device\n"); | ||
306 | return PTR_ERR(rtc->rdev); | ||
307 | } | ||
308 | |||
309 | if (lp8788_alarm_irq_register(pdev, rtc)) | ||
310 | dev_warn(lp->dev, "no rtc irq handler\n"); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static int lp8788_rtc_remove(struct platform_device *pdev) | ||
316 | { | ||
317 | struct lp8788_rtc *rtc = platform_get_drvdata(pdev); | ||
318 | |||
319 | rtc_device_unregister(rtc->rdev); | ||
320 | platform_set_drvdata(pdev, NULL); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static struct platform_driver lp8788_rtc_driver = { | ||
326 | .probe = lp8788_rtc_probe, | ||
327 | .remove = lp8788_rtc_remove, | ||
328 | .driver = { | ||
329 | .name = LP8788_DEV_RTC, | ||
330 | .owner = THIS_MODULE, | ||
331 | }, | ||
332 | }; | ||
333 | module_platform_driver(lp8788_rtc_driver); | ||
334 | |||
335 | MODULE_DESCRIPTION("Texas Instruments LP8788 RTC Driver"); | ||
336 | MODULE_AUTHOR("Milo Kim"); | ||
337 | MODULE_LICENSE("GPL"); | ||
338 | MODULE_ALIAS("platform:lp8788-rtc"); | ||
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c new file mode 100644 index 000000000000..6b1337f9baf4 --- /dev/null +++ b/drivers/rtc/rtc-max77686.c | |||
@@ -0,0 +1,641 @@ | |||
1 | /* | ||
2 | * RTC driver for Maxim MAX77686 | ||
3 | * | ||
4 | * Copyright (C) 2012 Samsung Electronics Co.Ltd | ||
5 | * | ||
6 | * based on rtc-max8997.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/slab.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/mutex.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/mfd/max77686-private.h> | ||
22 | #include <linux/irqdomain.h> | ||
23 | #include <linux/regmap.h> | ||
24 | |||
25 | /* RTC Control Register */ | ||
26 | #define BCD_EN_SHIFT 0 | ||
27 | #define BCD_EN_MASK (1 << BCD_EN_SHIFT) | ||
28 | #define MODEL24_SHIFT 1 | ||
29 | #define MODEL24_MASK (1 << MODEL24_SHIFT) | ||
30 | /* RTC Update Register1 */ | ||
31 | #define RTC_UDR_SHIFT 0 | ||
32 | #define RTC_UDR_MASK (1 << RTC_UDR_SHIFT) | ||
33 | #define RTC_RBUDR_SHIFT 4 | ||
34 | #define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT) | ||
35 | /* WTSR and SMPL Register */ | ||
36 | #define WTSRT_SHIFT 0 | ||
37 | #define SMPLT_SHIFT 2 | ||
38 | #define WTSR_EN_SHIFT 6 | ||
39 | #define SMPL_EN_SHIFT 7 | ||
40 | #define WTSRT_MASK (3 << WTSRT_SHIFT) | ||
41 | #define SMPLT_MASK (3 << SMPLT_SHIFT) | ||
42 | #define WTSR_EN_MASK (1 << WTSR_EN_SHIFT) | ||
43 | #define SMPL_EN_MASK (1 << SMPL_EN_SHIFT) | ||
44 | /* RTC Hour register */ | ||
45 | #define HOUR_PM_SHIFT 6 | ||
46 | #define HOUR_PM_MASK (1 << HOUR_PM_SHIFT) | ||
47 | /* RTC Alarm Enable */ | ||
48 | #define ALARM_ENABLE_SHIFT 7 | ||
49 | #define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) | ||
50 | |||
51 | #define MAX77686_RTC_UPDATE_DELAY 16 | ||
52 | #undef MAX77686_RTC_WTSR_SMPL | ||
53 | |||
54 | enum { | ||
55 | RTC_SEC = 0, | ||
56 | RTC_MIN, | ||
57 | RTC_HOUR, | ||
58 | RTC_WEEKDAY, | ||
59 | RTC_MONTH, | ||
60 | RTC_YEAR, | ||
61 | RTC_DATE, | ||
62 | RTC_NR_TIME | ||
63 | }; | ||
64 | |||
65 | struct max77686_rtc_info { | ||
66 | struct device *dev; | ||
67 | struct max77686_dev *max77686; | ||
68 | struct i2c_client *rtc; | ||
69 | struct rtc_device *rtc_dev; | ||
70 | struct mutex lock; | ||
71 | |||
72 | struct regmap *regmap; | ||
73 | |||
74 | int virq; | ||
75 | int rtc_24hr_mode; | ||
76 | }; | ||
77 | |||
78 | enum MAX77686_RTC_OP { | ||
79 | MAX77686_RTC_WRITE, | ||
80 | MAX77686_RTC_READ, | ||
81 | }; | ||
82 | |||
83 | static inline int max77686_rtc_calculate_wday(u8 shifted) | ||
84 | { | ||
85 | int counter = -1; | ||
86 | while (shifted) { | ||
87 | shifted >>= 1; | ||
88 | counter++; | ||
89 | } | ||
90 | return counter; | ||
91 | } | ||
92 | |||
93 | static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, | ||
94 | int rtc_24hr_mode) | ||
95 | { | ||
96 | tm->tm_sec = data[RTC_SEC] & 0x7f; | ||
97 | tm->tm_min = data[RTC_MIN] & 0x7f; | ||
98 | if (rtc_24hr_mode) | ||
99 | tm->tm_hour = data[RTC_HOUR] & 0x1f; | ||
100 | else { | ||
101 | tm->tm_hour = data[RTC_HOUR] & 0x0f; | ||
102 | if (data[RTC_HOUR] & HOUR_PM_MASK) | ||
103 | tm->tm_hour += 12; | ||
104 | } | ||
105 | |||
106 | tm->tm_wday = max77686_rtc_calculate_wday(data[RTC_WEEKDAY] & 0x7f); | ||
107 | tm->tm_mday = data[RTC_DATE] & 0x1f; | ||
108 | tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; | ||
109 | tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100; | ||
110 | tm->tm_yday = 0; | ||
111 | tm->tm_isdst = 0; | ||
112 | } | ||
113 | |||
114 | static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data) | ||
115 | { | ||
116 | data[RTC_SEC] = tm->tm_sec; | ||
117 | data[RTC_MIN] = tm->tm_min; | ||
118 | data[RTC_HOUR] = tm->tm_hour; | ||
119 | data[RTC_WEEKDAY] = 1 << tm->tm_wday; | ||
120 | data[RTC_DATE] = tm->tm_mday; | ||
121 | data[RTC_MONTH] = tm->tm_mon + 1; | ||
122 | data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0 ; | ||
123 | |||
124 | if (tm->tm_year < 100) { | ||
125 | pr_warn("%s: MAX77686 RTC cannot handle the year %d." | ||
126 | "Assume it's 2000.\n", __func__, 1900 + tm->tm_year); | ||
127 | return -EINVAL; | ||
128 | } | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int max77686_rtc_update(struct max77686_rtc_info *info, | ||
133 | enum MAX77686_RTC_OP op) | ||
134 | { | ||
135 | int ret; | ||
136 | unsigned int data; | ||
137 | |||
138 | if (op == MAX77686_RTC_WRITE) | ||
139 | data = 1 << RTC_UDR_SHIFT; | ||
140 | else | ||
141 | data = 1 << RTC_RBUDR_SHIFT; | ||
142 | |||
143 | ret = regmap_update_bits(info->max77686->rtc_regmap, | ||
144 | MAX77686_RTC_UPDATE0, data, data); | ||
145 | if (ret < 0) | ||
146 | dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n", | ||
147 | __func__, ret, data); | ||
148 | else { | ||
149 | /* Minimum 16ms delay required before RTC update. */ | ||
150 | msleep(MAX77686_RTC_UPDATE_DELAY); | ||
151 | } | ||
152 | |||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
157 | { | ||
158 | struct max77686_rtc_info *info = dev_get_drvdata(dev); | ||
159 | u8 data[RTC_NR_TIME]; | ||
160 | int ret; | ||
161 | |||
162 | mutex_lock(&info->lock); | ||
163 | |||
164 | ret = max77686_rtc_update(info, MAX77686_RTC_READ); | ||
165 | if (ret < 0) | ||
166 | goto out; | ||
167 | |||
168 | ret = regmap_bulk_read(info->max77686->rtc_regmap, | ||
169 | MAX77686_RTC_SEC, data, RTC_NR_TIME); | ||
170 | if (ret < 0) { | ||
171 | dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, ret); | ||
172 | goto out; | ||
173 | } | ||
174 | |||
175 | max77686_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); | ||
176 | |||
177 | ret = rtc_valid_tm(tm); | ||
178 | |||
179 | out: | ||
180 | mutex_unlock(&info->lock); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
185 | { | ||
186 | struct max77686_rtc_info *info = dev_get_drvdata(dev); | ||
187 | u8 data[RTC_NR_TIME]; | ||
188 | int ret; | ||
189 | |||
190 | ret = max77686_rtc_tm_to_data(tm, data); | ||
191 | if (ret < 0) | ||
192 | return ret; | ||
193 | |||
194 | mutex_lock(&info->lock); | ||
195 | |||
196 | ret = regmap_bulk_write(info->max77686->rtc_regmap, | ||
197 | MAX77686_RTC_SEC, data, RTC_NR_TIME); | ||
198 | if (ret < 0) { | ||
199 | dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, | ||
200 | ret); | ||
201 | goto out; | ||
202 | } | ||
203 | |||
204 | ret = max77686_rtc_update(info, MAX77686_RTC_WRITE); | ||
205 | |||
206 | out: | ||
207 | mutex_unlock(&info->lock); | ||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
212 | { | ||
213 | struct max77686_rtc_info *info = dev_get_drvdata(dev); | ||
214 | u8 data[RTC_NR_TIME]; | ||
215 | unsigned int val; | ||
216 | int i, ret; | ||
217 | |||
218 | mutex_lock(&info->lock); | ||
219 | |||
220 | ret = max77686_rtc_update(info, MAX77686_RTC_READ); | ||
221 | if (ret < 0) | ||
222 | goto out; | ||
223 | |||
224 | ret = regmap_bulk_read(info->max77686->rtc_regmap, | ||
225 | MAX77686_ALARM1_SEC, data, RTC_NR_TIME); | ||
226 | if (ret < 0) { | ||
227 | dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", | ||
228 | __func__, __LINE__, ret); | ||
229 | goto out; | ||
230 | } | ||
231 | |||
232 | max77686_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); | ||
233 | |||
234 | alrm->enabled = 0; | ||
235 | for (i = 0; i < RTC_NR_TIME; i++) { | ||
236 | if (data[i] & ALARM_ENABLE_MASK) { | ||
237 | alrm->enabled = 1; | ||
238 | break; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | alrm->pending = 0; | ||
243 | ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS1, &val); | ||
244 | if (ret < 0) { | ||
245 | dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n", | ||
246 | __func__, __LINE__, ret); | ||
247 | goto out; | ||
248 | } | ||
249 | |||
250 | if (val & (1 << 4)) /* RTCA1 */ | ||
251 | alrm->pending = 1; | ||
252 | |||
253 | out: | ||
254 | mutex_unlock(&info->lock); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) | ||
259 | { | ||
260 | u8 data[RTC_NR_TIME]; | ||
261 | int ret, i; | ||
262 | struct rtc_time tm; | ||
263 | |||
264 | if (!mutex_is_locked(&info->lock)) | ||
265 | dev_warn(info->dev, "%s: should have mutex locked\n", __func__); | ||
266 | |||
267 | ret = max77686_rtc_update(info, MAX77686_RTC_READ); | ||
268 | if (ret < 0) | ||
269 | goto out; | ||
270 | |||
271 | ret = regmap_bulk_read(info->max77686->rtc_regmap, | ||
272 | MAX77686_ALARM1_SEC, data, RTC_NR_TIME); | ||
273 | if (ret < 0) { | ||
274 | dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", | ||
275 | __func__, ret); | ||
276 | goto out; | ||
277 | } | ||
278 | |||
279 | max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode); | ||
280 | |||
281 | for (i = 0; i < RTC_NR_TIME; i++) | ||
282 | data[i] &= ~ALARM_ENABLE_MASK; | ||
283 | |||
284 | ret = regmap_bulk_write(info->max77686->rtc_regmap, | ||
285 | MAX77686_ALARM1_SEC, data, RTC_NR_TIME); | ||
286 | if (ret < 0) { | ||
287 | dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", | ||
288 | __func__, ret); | ||
289 | goto out; | ||
290 | } | ||
291 | |||
292 | ret = max77686_rtc_update(info, MAX77686_RTC_WRITE); | ||
293 | out: | ||
294 | return ret; | ||
295 | } | ||
296 | |||
297 | static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) | ||
298 | { | ||
299 | u8 data[RTC_NR_TIME]; | ||
300 | int ret; | ||
301 | struct rtc_time tm; | ||
302 | |||
303 | if (!mutex_is_locked(&info->lock)) | ||
304 | dev_warn(info->dev, "%s: should have mutex locked\n", __func__); | ||
305 | |||
306 | ret = max77686_rtc_update(info, MAX77686_RTC_READ); | ||
307 | if (ret < 0) | ||
308 | goto out; | ||
309 | |||
310 | ret = regmap_bulk_read(info->max77686->rtc_regmap, | ||
311 | MAX77686_ALARM1_SEC, data, RTC_NR_TIME); | ||
312 | if (ret < 0) { | ||
313 | dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", | ||
314 | __func__, ret); | ||
315 | goto out; | ||
316 | } | ||
317 | |||
318 | max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode); | ||
319 | |||
320 | data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT); | ||
321 | data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT); | ||
322 | data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT); | ||
323 | data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK; | ||
324 | if (data[RTC_MONTH] & 0xf) | ||
325 | data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT); | ||
326 | if (data[RTC_YEAR] & 0x7f) | ||
327 | data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT); | ||
328 | if (data[RTC_DATE] & 0x1f) | ||
329 | data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); | ||
330 | |||
331 | ret = regmap_bulk_write(info->max77686->rtc_regmap, | ||
332 | MAX77686_ALARM1_SEC, data, RTC_NR_TIME); | ||
333 | if (ret < 0) { | ||
334 | dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", | ||
335 | __func__, ret); | ||
336 | goto out; | ||
337 | } | ||
338 | |||
339 | ret = max77686_rtc_update(info, MAX77686_RTC_WRITE); | ||
340 | out: | ||
341 | return ret; | ||
342 | } | ||
343 | |||
344 | static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
345 | { | ||
346 | struct max77686_rtc_info *info = dev_get_drvdata(dev); | ||
347 | u8 data[RTC_NR_TIME]; | ||
348 | int ret; | ||
349 | |||
350 | ret = max77686_rtc_tm_to_data(&alrm->time, data); | ||
351 | if (ret < 0) | ||
352 | return ret; | ||
353 | |||
354 | mutex_lock(&info->lock); | ||
355 | |||
356 | ret = max77686_rtc_stop_alarm(info); | ||
357 | if (ret < 0) | ||
358 | goto out; | ||
359 | |||
360 | ret = regmap_bulk_write(info->max77686->rtc_regmap, | ||
361 | MAX77686_ALARM1_SEC, data, RTC_NR_TIME); | ||
362 | |||
363 | if (ret < 0) { | ||
364 | dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", | ||
365 | __func__, ret); | ||
366 | goto out; | ||
367 | } | ||
368 | |||
369 | ret = max77686_rtc_update(info, MAX77686_RTC_WRITE); | ||
370 | if (ret < 0) | ||
371 | goto out; | ||
372 | |||
373 | if (alrm->enabled) | ||
374 | ret = max77686_rtc_start_alarm(info); | ||
375 | out: | ||
376 | mutex_unlock(&info->lock); | ||
377 | return ret; | ||
378 | } | ||
379 | |||
380 | static int max77686_rtc_alarm_irq_enable(struct device *dev, | ||
381 | unsigned int enabled) | ||
382 | { | ||
383 | struct max77686_rtc_info *info = dev_get_drvdata(dev); | ||
384 | int ret; | ||
385 | |||
386 | mutex_lock(&info->lock); | ||
387 | if (enabled) | ||
388 | ret = max77686_rtc_start_alarm(info); | ||
389 | else | ||
390 | ret = max77686_rtc_stop_alarm(info); | ||
391 | mutex_unlock(&info->lock); | ||
392 | |||
393 | return ret; | ||
394 | } | ||
395 | |||
396 | static irqreturn_t max77686_rtc_alarm_irq(int irq, void *data) | ||
397 | { | ||
398 | struct max77686_rtc_info *info = data; | ||
399 | |||
400 | dev_info(info->dev, "%s:irq(%d)\n", __func__, irq); | ||
401 | |||
402 | rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); | ||
403 | |||
404 | return IRQ_HANDLED; | ||
405 | } | ||
406 | |||
407 | static const struct rtc_class_ops max77686_rtc_ops = { | ||
408 | .read_time = max77686_rtc_read_time, | ||
409 | .set_time = max77686_rtc_set_time, | ||
410 | .read_alarm = max77686_rtc_read_alarm, | ||
411 | .set_alarm = max77686_rtc_set_alarm, | ||
412 | .alarm_irq_enable = max77686_rtc_alarm_irq_enable, | ||
413 | }; | ||
414 | |||
415 | #ifdef MAX77686_RTC_WTSR_SMPL | ||
416 | static void max77686_rtc_enable_wtsr(struct max77686_rtc_info *info, bool enable) | ||
417 | { | ||
418 | int ret; | ||
419 | unsigned int val, mask; | ||
420 | |||
421 | if (enable) | ||
422 | val = (1 << WTSR_EN_SHIFT) | (3 << WTSRT_SHIFT); | ||
423 | else | ||
424 | val = 0; | ||
425 | |||
426 | mask = WTSR_EN_MASK | WTSRT_MASK; | ||
427 | |||
428 | dev_info(info->dev, "%s: %s WTSR\n", __func__, | ||
429 | enable ? "enable" : "disable"); | ||
430 | |||
431 | ret = regmap_update_bits(info->max77686->rtc_regmap, | ||
432 | MAX77686_WTSR_SMPL_CNTL, mask, val); | ||
433 | if (ret < 0) { | ||
434 | dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n", | ||
435 | __func__, ret); | ||
436 | return; | ||
437 | } | ||
438 | |||
439 | max77686_rtc_update(info, MAX77686_RTC_WRITE); | ||
440 | } | ||
441 | |||
442 | static void max77686_rtc_enable_smpl(struct max77686_rtc_info *info, bool enable) | ||
443 | { | ||
444 | int ret; | ||
445 | unsigned int val, mask; | ||
446 | |||
447 | if (enable) | ||
448 | val = (1 << SMPL_EN_SHIFT) | (0 << SMPLT_SHIFT); | ||
449 | else | ||
450 | val = 0; | ||
451 | |||
452 | mask = SMPL_EN_MASK | SMPLT_MASK; | ||
453 | |||
454 | dev_info(info->dev, "%s: %s SMPL\n", __func__, | ||
455 | enable ? "enable" : "disable"); | ||
456 | |||
457 | ret = regmap_update_bits(info->max77686->rtc_regmap, | ||
458 | MAX77686_WTSR_SMPL_CNTL, mask, val); | ||
459 | if (ret < 0) { | ||
460 | dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n", | ||
461 | __func__, ret); | ||
462 | return; | ||
463 | } | ||
464 | |||
465 | max77686_rtc_update(info, MAX77686_RTC_WRITE); | ||
466 | |||
467 | val = 0; | ||
468 | regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val); | ||
469 | pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val); | ||
470 | } | ||
471 | #endif /* MAX77686_RTC_WTSR_SMPL */ | ||
472 | |||
473 | static int max77686_rtc_init_reg(struct max77686_rtc_info *info) | ||
474 | { | ||
475 | u8 data[2]; | ||
476 | int ret; | ||
477 | |||
478 | /* Set RTC control register : Binary mode, 24hour mdoe */ | ||
479 | data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); | ||
480 | data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); | ||
481 | |||
482 | info->rtc_24hr_mode = 1; | ||
483 | |||
484 | ret = regmap_bulk_write(info->max77686->rtc_regmap, MAX77686_RTC_CONTROLM, data, 2); | ||
485 | if (ret < 0) { | ||
486 | dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", | ||
487 | __func__, ret); | ||
488 | return ret; | ||
489 | } | ||
490 | |||
491 | ret = max77686_rtc_update(info, MAX77686_RTC_WRITE); | ||
492 | return ret; | ||
493 | } | ||
494 | |||
495 | static struct regmap_config max77686_rtc_regmap_config = { | ||
496 | .reg_bits = 8, | ||
497 | .val_bits = 8, | ||
498 | }; | ||
499 | |||
500 | static int max77686_rtc_probe(struct platform_device *pdev) | ||
501 | { | ||
502 | struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent); | ||
503 | struct max77686_rtc_info *info; | ||
504 | int ret, virq; | ||
505 | |||
506 | dev_info(&pdev->dev, "%s\n", __func__); | ||
507 | |||
508 | info = kzalloc(sizeof(struct max77686_rtc_info), GFP_KERNEL); | ||
509 | if (!info) | ||
510 | return -ENOMEM; | ||
511 | |||
512 | mutex_init(&info->lock); | ||
513 | info->dev = &pdev->dev; | ||
514 | info->max77686 = max77686; | ||
515 | info->rtc = max77686->rtc; | ||
516 | info->max77686->rtc_regmap = regmap_init_i2c(info->max77686->rtc, | ||
517 | &max77686_rtc_regmap_config); | ||
518 | if (IS_ERR(info->max77686->rtc_regmap)) { | ||
519 | ret = PTR_ERR(info->max77686->rtc_regmap); | ||
520 | dev_err(info->max77686->dev, "Failed to allocate register map: %d\n", | ||
521 | ret); | ||
522 | kfree(info); | ||
523 | return ret; | ||
524 | } | ||
525 | platform_set_drvdata(pdev, info); | ||
526 | |||
527 | ret = max77686_rtc_init_reg(info); | ||
528 | |||
529 | if (ret < 0) { | ||
530 | dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret); | ||
531 | goto err_rtc; | ||
532 | } | ||
533 | |||
534 | #ifdef MAX77686_RTC_WTSR_SMPL | ||
535 | max77686_rtc_enable_wtsr(info, true); | ||
536 | max77686_rtc_enable_smpl(info, true); | ||
537 | #endif | ||
538 | |||
539 | device_init_wakeup(&pdev->dev, 1); | ||
540 | |||
541 | info->rtc_dev = rtc_device_register("max77686-rtc", &pdev->dev, | ||
542 | &max77686_rtc_ops, THIS_MODULE); | ||
543 | |||
544 | if (IS_ERR(info->rtc_dev)) { | ||
545 | dev_info(&pdev->dev, "%s: fail\n", __func__); | ||
546 | |||
547 | ret = PTR_ERR(info->rtc_dev); | ||
548 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | ||
549 | if (ret == 0) | ||
550 | ret = -EINVAL; | ||
551 | goto err_rtc; | ||
552 | } | ||
553 | virq = irq_create_mapping(max77686->irq_domain, MAX77686_RTCIRQ_RTCA1); | ||
554 | if (!virq) | ||
555 | goto err_rtc; | ||
556 | info->virq = virq; | ||
557 | |||
558 | ret = request_threaded_irq(virq, NULL, max77686_rtc_alarm_irq, 0, | ||
559 | "rtc-alarm0", info); | ||
560 | if (ret < 0) { | ||
561 | dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", | ||
562 | info->virq, ret); | ||
563 | goto err_rtc; | ||
564 | } | ||
565 | |||
566 | goto out; | ||
567 | err_rtc: | ||
568 | kfree(info); | ||
569 | return ret; | ||
570 | out: | ||
571 | return ret; | ||
572 | } | ||
573 | |||
574 | static int max77686_rtc_remove(struct platform_device *pdev) | ||
575 | { | ||
576 | struct max77686_rtc_info *info = platform_get_drvdata(pdev); | ||
577 | |||
578 | if (info) { | ||
579 | free_irq(info->virq, info); | ||
580 | rtc_device_unregister(info->rtc_dev); | ||
581 | kfree(info); | ||
582 | } | ||
583 | |||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | static void max77686_rtc_shutdown(struct platform_device *pdev) | ||
588 | { | ||
589 | #ifdef MAX77686_RTC_WTSR_SMPL | ||
590 | struct max77686_rtc_info *info = platform_get_drvdata(pdev); | ||
591 | int i; | ||
592 | u8 val = 0; | ||
593 | |||
594 | for (i = 0; i < 3; i++) { | ||
595 | max77686_rtc_enable_wtsr(info, false); | ||
596 | regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val); | ||
597 | pr_info("%s: WTSR_SMPL reg(0x%02x)\n", __func__, val); | ||
598 | if (val & WTSR_EN_MASK) | ||
599 | pr_emerg("%s: fail to disable WTSR\n", __func__); | ||
600 | else { | ||
601 | pr_info("%s: success to disable WTSR\n", __func__); | ||
602 | break; | ||
603 | } | ||
604 | } | ||
605 | |||
606 | /* Disable SMPL when power off */ | ||
607 | max77686_rtc_enable_smpl(info, false); | ||
608 | #endif /* MAX77686_RTC_WTSR_SMPL */ | ||
609 | } | ||
610 | |||
611 | static const struct platform_device_id rtc_id[] = { | ||
612 | { "max77686-rtc", 0 }, | ||
613 | {}, | ||
614 | }; | ||
615 | |||
616 | static struct platform_driver max77686_rtc_driver = { | ||
617 | .driver = { | ||
618 | .name = "max77686-rtc", | ||
619 | .owner = THIS_MODULE, | ||
620 | }, | ||
621 | .probe = max77686_rtc_probe, | ||
622 | .remove = max77686_rtc_remove, | ||
623 | .shutdown = max77686_rtc_shutdown, | ||
624 | .id_table = rtc_id, | ||
625 | }; | ||
626 | |||
627 | static int __init max77686_rtc_init(void) | ||
628 | { | ||
629 | return platform_driver_register(&max77686_rtc_driver); | ||
630 | } | ||
631 | module_init(max77686_rtc_init); | ||
632 | |||
633 | static void __exit max77686_rtc_exit(void) | ||
634 | { | ||
635 | platform_driver_unregister(&max77686_rtc_driver); | ||
636 | } | ||
637 | module_exit(max77686_rtc_exit); | ||
638 | |||
639 | MODULE_DESCRIPTION("Maxim MAX77686 RTC driver"); | ||
640 | MODULE_AUTHOR("<woong.byun@samsung.com>"); | ||
641 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-max8907.c b/drivers/rtc/rtc-max8907.c index 1d049da16c85..31ca8faf9f05 100644 --- a/drivers/rtc/rtc-max8907.c +++ b/drivers/rtc/rtc-max8907.c | |||
@@ -205,8 +205,9 @@ static int max8907_rtc_probe(struct platform_device *pdev) | |||
205 | goto err_unregister; | 205 | goto err_unregister; |
206 | } | 206 | } |
207 | 207 | ||
208 | ret = request_threaded_irq(rtc->irq, NULL, max8907_irq_handler, | 208 | ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, |
209 | IRQF_ONESHOT, "max8907-alarm0", rtc); | 209 | max8907_irq_handler, |
210 | IRQF_ONESHOT, "max8907-alarm0", rtc); | ||
210 | if (ret < 0) { | 211 | if (ret < 0) { |
211 | dev_err(&pdev->dev, "Failed to request IRQ%d: %d\n", | 212 | dev_err(&pdev->dev, "Failed to request IRQ%d: %d\n", |
212 | rtc->irq, ret); | 213 | rtc->irq, ret); |
@@ -224,7 +225,6 @@ static int max8907_rtc_remove(struct platform_device *pdev) | |||
224 | { | 225 | { |
225 | struct max8907_rtc *rtc = platform_get_drvdata(pdev); | 226 | struct max8907_rtc *rtc = platform_get_drvdata(pdev); |
226 | 227 | ||
227 | free_irq(rtc->irq, rtc); | ||
228 | rtc_device_unregister(rtc->rtc_dev); | 228 | rtc_device_unregister(rtc->rtc_dev); |
229 | 229 | ||
230 | return 0; | 230 | return 0; |
diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c new file mode 100644 index 000000000000..00e505b6bee3 --- /dev/null +++ b/drivers/rtc/rtc-max8997.c | |||
@@ -0,0 +1,552 @@ | |||
1 | /* | ||
2 | * RTC driver for Maxim MAX8997 | ||
3 | * | ||
4 | * Copyright (C) 2013 Samsung Electronics Co.Ltd | ||
5 | * | ||
6 | * based on rtc-max8998.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/slab.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/mutex.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/mfd/max8997-private.h> | ||
22 | #include <linux/irqdomain.h> | ||
23 | |||
24 | /* Module parameter for WTSR function control */ | ||
25 | static int wtsr_en = 1; | ||
26 | module_param(wtsr_en, int, 0444); | ||
27 | MODULE_PARM_DESC(wtsr_en, "Wachdog Timeout & Sofware Reset (default=on)"); | ||
28 | /* Module parameter for SMPL function control */ | ||
29 | static int smpl_en = 1; | ||
30 | module_param(smpl_en, int, 0444); | ||
31 | MODULE_PARM_DESC(smpl_en, "Sudden Momentary Power Loss (default=on)"); | ||
32 | |||
33 | /* RTC Control Register */ | ||
34 | #define BCD_EN_SHIFT 0 | ||
35 | #define BCD_EN_MASK (1 << BCD_EN_SHIFT) | ||
36 | #define MODEL24_SHIFT 1 | ||
37 | #define MODEL24_MASK (1 << MODEL24_SHIFT) | ||
38 | /* RTC Update Register1 */ | ||
39 | #define RTC_UDR_SHIFT 0 | ||
40 | #define RTC_UDR_MASK (1 << RTC_UDR_SHIFT) | ||
41 | /* WTSR and SMPL Register */ | ||
42 | #define WTSRT_SHIFT 0 | ||
43 | #define SMPLT_SHIFT 2 | ||
44 | #define WTSR_EN_SHIFT 6 | ||
45 | #define SMPL_EN_SHIFT 7 | ||
46 | #define WTSRT_MASK (3 << WTSRT_SHIFT) | ||
47 | #define SMPLT_MASK (3 << SMPLT_SHIFT) | ||
48 | #define WTSR_EN_MASK (1 << WTSR_EN_SHIFT) | ||
49 | #define SMPL_EN_MASK (1 << SMPL_EN_SHIFT) | ||
50 | /* RTC Hour register */ | ||
51 | #define HOUR_PM_SHIFT 6 | ||
52 | #define HOUR_PM_MASK (1 << HOUR_PM_SHIFT) | ||
53 | /* RTC Alarm Enable */ | ||
54 | #define ALARM_ENABLE_SHIFT 7 | ||
55 | #define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) | ||
56 | |||
57 | enum { | ||
58 | RTC_SEC = 0, | ||
59 | RTC_MIN, | ||
60 | RTC_HOUR, | ||
61 | RTC_WEEKDAY, | ||
62 | RTC_MONTH, | ||
63 | RTC_YEAR, | ||
64 | RTC_DATE, | ||
65 | RTC_NR_TIME | ||
66 | }; | ||
67 | |||
68 | struct max8997_rtc_info { | ||
69 | struct device *dev; | ||
70 | struct max8997_dev *max8997; | ||
71 | struct i2c_client *rtc; | ||
72 | struct rtc_device *rtc_dev; | ||
73 | struct mutex lock; | ||
74 | int virq; | ||
75 | int rtc_24hr_mode; | ||
76 | }; | ||
77 | |||
78 | static void max8997_rtc_data_to_tm(u8 *data, struct rtc_time *tm, | ||
79 | int rtc_24hr_mode) | ||
80 | { | ||
81 | tm->tm_sec = data[RTC_SEC] & 0x7f; | ||
82 | tm->tm_min = data[RTC_MIN] & 0x7f; | ||
83 | if (rtc_24hr_mode) | ||
84 | tm->tm_hour = data[RTC_HOUR] & 0x1f; | ||
85 | else { | ||
86 | tm->tm_hour = data[RTC_HOUR] & 0x0f; | ||
87 | if (data[RTC_HOUR] & HOUR_PM_MASK) | ||
88 | tm->tm_hour += 12; | ||
89 | } | ||
90 | |||
91 | tm->tm_wday = fls(data[RTC_WEEKDAY] & 0x7f) - 1; | ||
92 | tm->tm_mday = data[RTC_DATE] & 0x1f; | ||
93 | tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; | ||
94 | tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100; | ||
95 | tm->tm_yday = 0; | ||
96 | tm->tm_isdst = 0; | ||
97 | } | ||
98 | |||
99 | static int max8997_rtc_tm_to_data(struct rtc_time *tm, u8 *data) | ||
100 | { | ||
101 | data[RTC_SEC] = tm->tm_sec; | ||
102 | data[RTC_MIN] = tm->tm_min; | ||
103 | data[RTC_HOUR] = tm->tm_hour; | ||
104 | data[RTC_WEEKDAY] = 1 << tm->tm_wday; | ||
105 | data[RTC_DATE] = tm->tm_mday; | ||
106 | data[RTC_MONTH] = tm->tm_mon + 1; | ||
107 | data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0 ; | ||
108 | |||
109 | if (tm->tm_year < 100) { | ||
110 | pr_warn("%s: MAX8997 RTC cannot handle the year %d." | ||
111 | "Assume it's 2000.\n", __func__, 1900 + tm->tm_year); | ||
112 | return -EINVAL; | ||
113 | } | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static inline int max8997_rtc_set_update_reg(struct max8997_rtc_info *info) | ||
118 | { | ||
119 | int ret; | ||
120 | |||
121 | ret = max8997_write_reg(info->rtc, MAX8997_RTC_UPDATE1, | ||
122 | RTC_UDR_MASK); | ||
123 | if (ret < 0) | ||
124 | dev_err(info->dev, "%s: fail to write update reg(%d)\n", | ||
125 | __func__, ret); | ||
126 | else { | ||
127 | /* Minimum 16ms delay required before RTC update. | ||
128 | * Otherwise, we may read and update based on out-of-date | ||
129 | * value */ | ||
130 | msleep(20); | ||
131 | } | ||
132 | |||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
137 | { | ||
138 | struct max8997_rtc_info *info = dev_get_drvdata(dev); | ||
139 | u8 data[RTC_NR_TIME]; | ||
140 | int ret; | ||
141 | |||
142 | mutex_lock(&info->lock); | ||
143 | ret = max8997_bulk_read(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data); | ||
144 | mutex_unlock(&info->lock); | ||
145 | |||
146 | if (ret < 0) { | ||
147 | dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, | ||
148 | ret); | ||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | max8997_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); | ||
153 | |||
154 | return rtc_valid_tm(tm); | ||
155 | } | ||
156 | |||
157 | static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
158 | { | ||
159 | struct max8997_rtc_info *info = dev_get_drvdata(dev); | ||
160 | u8 data[RTC_NR_TIME]; | ||
161 | int ret; | ||
162 | |||
163 | ret = max8997_rtc_tm_to_data(tm, data); | ||
164 | if (ret < 0) | ||
165 | return ret; | ||
166 | |||
167 | mutex_lock(&info->lock); | ||
168 | |||
169 | ret = max8997_bulk_write(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data); | ||
170 | if (ret < 0) { | ||
171 | dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, | ||
172 | ret); | ||
173 | goto out; | ||
174 | } | ||
175 | |||
176 | ret = max8997_rtc_set_update_reg(info); | ||
177 | out: | ||
178 | mutex_unlock(&info->lock); | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
183 | { | ||
184 | struct max8997_rtc_info *info = dev_get_drvdata(dev); | ||
185 | u8 data[RTC_NR_TIME]; | ||
186 | u8 val; | ||
187 | int i, ret; | ||
188 | |||
189 | mutex_lock(&info->lock); | ||
190 | |||
191 | ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, | ||
192 | data); | ||
193 | if (ret < 0) { | ||
194 | dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", | ||
195 | __func__, __LINE__, ret); | ||
196 | goto out; | ||
197 | } | ||
198 | |||
199 | max8997_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); | ||
200 | |||
201 | alrm->enabled = 0; | ||
202 | for (i = 0; i < RTC_NR_TIME; i++) { | ||
203 | if (data[i] & ALARM_ENABLE_MASK) { | ||
204 | alrm->enabled = 1; | ||
205 | break; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | alrm->pending = 0; | ||
210 | ret = max8997_read_reg(info->max8997->i2c, MAX8997_REG_STATUS1, &val); | ||
211 | if (ret < 0) { | ||
212 | dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n", | ||
213 | __func__, __LINE__, ret); | ||
214 | goto out; | ||
215 | } | ||
216 | |||
217 | if (val & (1 << 4)) /* RTCA1 */ | ||
218 | alrm->pending = 1; | ||
219 | |||
220 | out: | ||
221 | mutex_unlock(&info->lock); | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info) | ||
226 | { | ||
227 | u8 data[RTC_NR_TIME]; | ||
228 | int ret, i; | ||
229 | |||
230 | if (!mutex_is_locked(&info->lock)) | ||
231 | dev_warn(info->dev, "%s: should have mutex locked\n", __func__); | ||
232 | |||
233 | ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, | ||
234 | data); | ||
235 | if (ret < 0) { | ||
236 | dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", | ||
237 | __func__, ret); | ||
238 | goto out; | ||
239 | } | ||
240 | |||
241 | for (i = 0; i < RTC_NR_TIME; i++) | ||
242 | data[i] &= ~ALARM_ENABLE_MASK; | ||
243 | |||
244 | ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, | ||
245 | data); | ||
246 | if (ret < 0) { | ||
247 | dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", | ||
248 | __func__, ret); | ||
249 | goto out; | ||
250 | } | ||
251 | |||
252 | ret = max8997_rtc_set_update_reg(info); | ||
253 | out: | ||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static int max8997_rtc_start_alarm(struct max8997_rtc_info *info) | ||
258 | { | ||
259 | u8 data[RTC_NR_TIME]; | ||
260 | int ret; | ||
261 | |||
262 | if (!mutex_is_locked(&info->lock)) | ||
263 | dev_warn(info->dev, "%s: should have mutex locked\n", __func__); | ||
264 | |||
265 | ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, | ||
266 | data); | ||
267 | if (ret < 0) { | ||
268 | dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", | ||
269 | __func__, ret); | ||
270 | goto out; | ||
271 | } | ||
272 | |||
273 | data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT); | ||
274 | data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT); | ||
275 | data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT); | ||
276 | data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK; | ||
277 | if (data[RTC_MONTH] & 0xf) | ||
278 | data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT); | ||
279 | if (data[RTC_YEAR] & 0x7f) | ||
280 | data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT); | ||
281 | if (data[RTC_DATE] & 0x1f) | ||
282 | data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); | ||
283 | |||
284 | ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, | ||
285 | data); | ||
286 | if (ret < 0) { | ||
287 | dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", | ||
288 | __func__, ret); | ||
289 | goto out; | ||
290 | } | ||
291 | |||
292 | ret = max8997_rtc_set_update_reg(info); | ||
293 | out: | ||
294 | return ret; | ||
295 | } | ||
296 | static int max8997_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
297 | { | ||
298 | struct max8997_rtc_info *info = dev_get_drvdata(dev); | ||
299 | u8 data[RTC_NR_TIME]; | ||
300 | int ret; | ||
301 | |||
302 | ret = max8997_rtc_tm_to_data(&alrm->time, data); | ||
303 | if (ret < 0) | ||
304 | return ret; | ||
305 | |||
306 | dev_info(info->dev, "%s: %d-%02d-%02d %02d:%02d:%02d\n", __func__, | ||
307 | data[RTC_YEAR] + 2000, data[RTC_MONTH], data[RTC_DATE], | ||
308 | data[RTC_HOUR], data[RTC_MIN], data[RTC_SEC]); | ||
309 | |||
310 | mutex_lock(&info->lock); | ||
311 | |||
312 | ret = max8997_rtc_stop_alarm(info); | ||
313 | if (ret < 0) | ||
314 | goto out; | ||
315 | |||
316 | ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, | ||
317 | data); | ||
318 | if (ret < 0) { | ||
319 | dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", | ||
320 | __func__, ret); | ||
321 | goto out; | ||
322 | } | ||
323 | |||
324 | ret = max8997_rtc_set_update_reg(info); | ||
325 | if (ret < 0) | ||
326 | goto out; | ||
327 | |||
328 | if (alrm->enabled) | ||
329 | ret = max8997_rtc_start_alarm(info); | ||
330 | out: | ||
331 | mutex_unlock(&info->lock); | ||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | static int max8997_rtc_alarm_irq_enable(struct device *dev, | ||
336 | unsigned int enabled) | ||
337 | { | ||
338 | struct max8997_rtc_info *info = dev_get_drvdata(dev); | ||
339 | int ret; | ||
340 | |||
341 | mutex_lock(&info->lock); | ||
342 | if (enabled) | ||
343 | ret = max8997_rtc_start_alarm(info); | ||
344 | else | ||
345 | ret = max8997_rtc_stop_alarm(info); | ||
346 | mutex_unlock(&info->lock); | ||
347 | |||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | static irqreturn_t max8997_rtc_alarm_irq(int irq, void *data) | ||
352 | { | ||
353 | struct max8997_rtc_info *info = data; | ||
354 | |||
355 | dev_info(info->dev, "%s:irq(%d)\n", __func__, irq); | ||
356 | |||
357 | rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); | ||
358 | |||
359 | return IRQ_HANDLED; | ||
360 | } | ||
361 | |||
362 | static const struct rtc_class_ops max8997_rtc_ops = { | ||
363 | .read_time = max8997_rtc_read_time, | ||
364 | .set_time = max8997_rtc_set_time, | ||
365 | .read_alarm = max8997_rtc_read_alarm, | ||
366 | .set_alarm = max8997_rtc_set_alarm, | ||
367 | .alarm_irq_enable = max8997_rtc_alarm_irq_enable, | ||
368 | }; | ||
369 | |||
370 | static void max8997_rtc_enable_wtsr(struct max8997_rtc_info *info, bool enable) | ||
371 | { | ||
372 | int ret; | ||
373 | u8 val, mask; | ||
374 | |||
375 | if (!wtsr_en) | ||
376 | return; | ||
377 | |||
378 | if (enable) | ||
379 | val = (1 << WTSR_EN_SHIFT) | (3 << WTSRT_SHIFT); | ||
380 | else | ||
381 | val = 0; | ||
382 | |||
383 | mask = WTSR_EN_MASK | WTSRT_MASK; | ||
384 | |||
385 | dev_info(info->dev, "%s: %s WTSR\n", __func__, | ||
386 | enable ? "enable" : "disable"); | ||
387 | |||
388 | ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask); | ||
389 | if (ret < 0) { | ||
390 | dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n", | ||
391 | __func__, ret); | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | max8997_rtc_set_update_reg(info); | ||
396 | } | ||
397 | |||
398 | static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable) | ||
399 | { | ||
400 | int ret; | ||
401 | u8 val, mask; | ||
402 | |||
403 | if (!smpl_en) | ||
404 | return; | ||
405 | |||
406 | if (enable) | ||
407 | val = (1 << SMPL_EN_SHIFT) | (0 << SMPLT_SHIFT); | ||
408 | else | ||
409 | val = 0; | ||
410 | |||
411 | mask = SMPL_EN_MASK | SMPLT_MASK; | ||
412 | |||
413 | dev_info(info->dev, "%s: %s SMPL\n", __func__, | ||
414 | enable ? "enable" : "disable"); | ||
415 | |||
416 | ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask); | ||
417 | if (ret < 0) { | ||
418 | dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n", | ||
419 | __func__, ret); | ||
420 | return; | ||
421 | } | ||
422 | |||
423 | max8997_rtc_set_update_reg(info); | ||
424 | |||
425 | val = 0; | ||
426 | max8997_read_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, &val); | ||
427 | pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val); | ||
428 | } | ||
429 | |||
430 | static int max8997_rtc_init_reg(struct max8997_rtc_info *info) | ||
431 | { | ||
432 | u8 data[2]; | ||
433 | int ret; | ||
434 | |||
435 | /* Set RTC control register : Binary mode, 24hour mdoe */ | ||
436 | data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); | ||
437 | data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); | ||
438 | |||
439 | info->rtc_24hr_mode = 1; | ||
440 | |||
441 | ret = max8997_bulk_write(info->rtc, MAX8997_RTC_CTRLMASK, 2, data); | ||
442 | if (ret < 0) { | ||
443 | dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", | ||
444 | __func__, ret); | ||
445 | return ret; | ||
446 | } | ||
447 | |||
448 | ret = max8997_rtc_set_update_reg(info); | ||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | static int max8997_rtc_probe(struct platform_device *pdev) | ||
453 | { | ||
454 | struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent); | ||
455 | struct max8997_rtc_info *info; | ||
456 | int ret, virq; | ||
457 | |||
458 | info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_rtc_info), | ||
459 | GFP_KERNEL); | ||
460 | if (!info) | ||
461 | return -ENOMEM; | ||
462 | |||
463 | mutex_init(&info->lock); | ||
464 | info->dev = &pdev->dev; | ||
465 | info->max8997 = max8997; | ||
466 | info->rtc = max8997->rtc; | ||
467 | |||
468 | platform_set_drvdata(pdev, info); | ||
469 | |||
470 | ret = max8997_rtc_init_reg(info); | ||
471 | |||
472 | if (ret < 0) { | ||
473 | dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret); | ||
474 | return ret; | ||
475 | } | ||
476 | |||
477 | max8997_rtc_enable_wtsr(info, true); | ||
478 | max8997_rtc_enable_smpl(info, true); | ||
479 | |||
480 | device_init_wakeup(&pdev->dev, 1); | ||
481 | |||
482 | info->rtc_dev = rtc_device_register("max8997-rtc", &pdev->dev, | ||
483 | &max8997_rtc_ops, THIS_MODULE); | ||
484 | |||
485 | if (IS_ERR(info->rtc_dev)) { | ||
486 | ret = PTR_ERR(info->rtc_dev); | ||
487 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | ||
488 | return ret; | ||
489 | } | ||
490 | |||
491 | virq = irq_create_mapping(max8997->irq_domain, MAX8997_PMICIRQ_RTCA1); | ||
492 | if (!virq) { | ||
493 | dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n"); | ||
494 | goto err_out; | ||
495 | } | ||
496 | info->virq = virq; | ||
497 | |||
498 | ret = devm_request_threaded_irq(&pdev->dev, virq, NULL, | ||
499 | max8997_rtc_alarm_irq, 0, | ||
500 | "rtc-alarm0", info); | ||
501 | if (ret < 0) { | ||
502 | dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", | ||
503 | info->virq, ret); | ||
504 | goto err_out; | ||
505 | } | ||
506 | |||
507 | return ret; | ||
508 | |||
509 | err_out: | ||
510 | rtc_device_unregister(info->rtc_dev); | ||
511 | return ret; | ||
512 | } | ||
513 | |||
514 | static int max8997_rtc_remove(struct platform_device *pdev) | ||
515 | { | ||
516 | struct max8997_rtc_info *info = platform_get_drvdata(pdev); | ||
517 | |||
518 | if (info) | ||
519 | rtc_device_unregister(info->rtc_dev); | ||
520 | |||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | static void max8997_rtc_shutdown(struct platform_device *pdev) | ||
525 | { | ||
526 | struct max8997_rtc_info *info = platform_get_drvdata(pdev); | ||
527 | |||
528 | max8997_rtc_enable_wtsr(info, false); | ||
529 | max8997_rtc_enable_smpl(info, false); | ||
530 | } | ||
531 | |||
532 | static const struct platform_device_id rtc_id[] = { | ||
533 | { "max8997-rtc", 0 }, | ||
534 | {}, | ||
535 | }; | ||
536 | |||
537 | static struct platform_driver max8997_rtc_driver = { | ||
538 | .driver = { | ||
539 | .name = "max8997-rtc", | ||
540 | .owner = THIS_MODULE, | ||
541 | }, | ||
542 | .probe = max8997_rtc_probe, | ||
543 | .remove = max8997_rtc_remove, | ||
544 | .shutdown = max8997_rtc_shutdown, | ||
545 | .id_table = rtc_id, | ||
546 | }; | ||
547 | |||
548 | module_platform_driver(max8997_rtc_driver); | ||
549 | |||
550 | MODULE_DESCRIPTION("Maxim MAX8997 RTC driver"); | ||
551 | MODULE_AUTHOR("<ms925.kim@samsung.com>"); | ||
552 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index bec10be96f84..bdcc60830aec 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
16 | #include <linux/of.h> | ||
16 | #include <linux/of_device.h> | 17 | #include <linux/of_device.h> |
17 | #include <linux/of_platform.h> | 18 | #include <linux/of_platform.h> |
18 | #include <linux/io.h> | 19 | #include <linux/io.h> |
@@ -403,17 +404,19 @@ static int mpc5121_rtc_remove(struct platform_device *op) | |||
403 | return 0; | 404 | return 0; |
404 | } | 405 | } |
405 | 406 | ||
407 | #ifdef CONFIG_OF | ||
406 | static struct of_device_id mpc5121_rtc_match[] = { | 408 | static struct of_device_id mpc5121_rtc_match[] = { |
407 | { .compatible = "fsl,mpc5121-rtc", }, | 409 | { .compatible = "fsl,mpc5121-rtc", }, |
408 | { .compatible = "fsl,mpc5200-rtc", }, | 410 | { .compatible = "fsl,mpc5200-rtc", }, |
409 | {}, | 411 | {}, |
410 | }; | 412 | }; |
413 | #endif | ||
411 | 414 | ||
412 | static struct platform_driver mpc5121_rtc_driver = { | 415 | static struct platform_driver mpc5121_rtc_driver = { |
413 | .driver = { | 416 | .driver = { |
414 | .name = "mpc5121-rtc", | 417 | .name = "mpc5121-rtc", |
415 | .owner = THIS_MODULE, | 418 | .owner = THIS_MODULE, |
416 | .of_match_table = mpc5121_rtc_match, | 419 | .of_match_table = of_match_ptr(mpc5121_rtc_match), |
417 | }, | 420 | }, |
418 | .probe = mpc5121_rtc_probe, | 421 | .probe = mpc5121_rtc_probe, |
419 | .remove = mpc5121_rtc_remove, | 422 | .remove = mpc5121_rtc_remove, |
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index be05a645f99e..889e3160e701 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #define REG_CONTROL3_PM_VDD (1 << 6) /* switch-over disabled */ | 23 | #define REG_CONTROL3_PM_VDD (1 << 6) /* switch-over disabled */ |
24 | #define REG_CONTROL3_PM_DSM (1 << 5) /* direct switching mode */ | 24 | #define REG_CONTROL3_PM_DSM (1 << 5) /* direct switching mode */ |
25 | #define REG_CONTROL3_PM_MASK 0xe0 | 25 | #define REG_CONTROL3_PM_MASK 0xe0 |
26 | #define REG_CONTROL3_BLF (1 << 2) /* battery low bit, read-only */ | ||
26 | 27 | ||
27 | #define REG_SECONDS 0x03 | 28 | #define REG_SECONDS 0x03 |
28 | #define REG_SECONDS_OS (1 << 7) | 29 | #define REG_SECONDS_OS (1 << 7) |
@@ -250,9 +251,39 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
250 | return pcf8523_start_rtc(client); | 251 | return pcf8523_start_rtc(client); |
251 | } | 252 | } |
252 | 253 | ||
254 | #ifdef CONFIG_RTC_INTF_DEV | ||
255 | static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
256 | unsigned long arg) | ||
257 | { | ||
258 | struct i2c_client *client = to_i2c_client(dev); | ||
259 | u8 value; | ||
260 | int ret = 0, err; | ||
261 | |||
262 | switch (cmd) { | ||
263 | case RTC_VL_READ: | ||
264 | err = pcf8523_read(client, REG_CONTROL3, &value); | ||
265 | if (err < 0) | ||
266 | return err; | ||
267 | |||
268 | if (value & REG_CONTROL3_BLF) | ||
269 | ret = 1; | ||
270 | |||
271 | if (copy_to_user((void __user *)arg, &ret, sizeof(int))) | ||
272 | return -EFAULT; | ||
273 | |||
274 | return 0; | ||
275 | default: | ||
276 | return -ENOIOCTLCMD; | ||
277 | } | ||
278 | } | ||
279 | #else | ||
280 | #define pcf8523_rtc_ioctl NULL | ||
281 | #endif | ||
282 | |||
253 | static const struct rtc_class_ops pcf8523_rtc_ops = { | 283 | static const struct rtc_class_ops pcf8523_rtc_ops = { |
254 | .read_time = pcf8523_rtc_read_time, | 284 | .read_time = pcf8523_rtc_read_time, |
255 | .set_time = pcf8523_rtc_set_time, | 285 | .set_time = pcf8523_rtc_set_time, |
286 | .ioctl = pcf8523_rtc_ioctl, | ||
256 | }; | 287 | }; |
257 | 288 | ||
258 | static int pcf8523_probe(struct i2c_client *client, | 289 | static int pcf8523_probe(struct i2c_client *client, |
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 7098ee89bd29..f7daf18a112e 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
@@ -181,7 +181,7 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
181 | __func__, err, data[0], data[1]); | 181 | __func__, err, data[0], data[1]); |
182 | return -EIO; | 182 | return -EIO; |
183 | } | 183 | } |
184 | }; | 184 | } |
185 | 185 | ||
186 | return 0; | 186 | return 0; |
187 | } | 187 | } |
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 3415b8f18555..5f97c61247d5 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c | |||
@@ -185,8 +185,8 @@ static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
185 | if (ctrl & (CTRL_STOP | CTRL_HOLD)) { | 185 | if (ctrl & (CTRL_STOP | CTRL_HOLD)) { |
186 | unsigned char new_ctrl = ctrl & ~(CTRL_STOP | CTRL_HOLD); | 186 | unsigned char new_ctrl = ctrl & ~(CTRL_STOP | CTRL_HOLD); |
187 | 187 | ||
188 | printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n", | 188 | dev_warn(dev, "resetting control %02x -> %02x\n", |
189 | ctrl, new_ctrl); | 189 | ctrl, new_ctrl); |
190 | 190 | ||
191 | if ((err = pcf8583_set_ctrl(client, &new_ctrl)) < 0) | 191 | if ((err = pcf8583_set_ctrl(client, &new_ctrl)) < 0) |
192 | return err; | 192 | return err; |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 81c5077feff3..8900ea784817 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
@@ -384,6 +384,8 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) | |||
384 | goto out_no_irq; | 384 | goto out_no_irq; |
385 | } | 385 | } |
386 | 386 | ||
387 | device_init_wakeup(&adev->dev, 1); | ||
388 | |||
387 | return 0; | 389 | return 0; |
388 | 390 | ||
389 | out_no_irq: | 391 | out_no_irq: |
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index f771b2ee4b18..03c85ee719a7 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c | |||
@@ -62,6 +62,10 @@ | |||
62 | #define RYxR_MONTH_S 5 | 62 | #define RYxR_MONTH_S 5 |
63 | #define RYxR_MONTH_MASK (0xf << RYxR_MONTH_S) | 63 | #define RYxR_MONTH_MASK (0xf << RYxR_MONTH_S) |
64 | #define RYxR_DAY_MASK 0x1f | 64 | #define RYxR_DAY_MASK 0x1f |
65 | #define RDxR_WOM_S 20 | ||
66 | #define RDxR_WOM_MASK (0x7 << RDxR_WOM_S) | ||
67 | #define RDxR_DOW_S 17 | ||
68 | #define RDxR_DOW_MASK (0x7 << RDxR_DOW_S) | ||
65 | #define RDxR_HOUR_S 12 | 69 | #define RDxR_HOUR_S 12 |
66 | #define RDxR_HOUR_MASK (0x1f << RDxR_HOUR_S) | 70 | #define RDxR_HOUR_MASK (0x1f << RDxR_HOUR_S) |
67 | #define RDxR_MIN_S 6 | 71 | #define RDxR_MIN_S 6 |
@@ -91,6 +95,7 @@ struct pxa_rtc { | |||
91 | spinlock_t lock; /* Protects this structure */ | 95 | spinlock_t lock; /* Protects this structure */ |
92 | }; | 96 | }; |
93 | 97 | ||
98 | |||
94 | static u32 ryxr_calc(struct rtc_time *tm) | 99 | static u32 ryxr_calc(struct rtc_time *tm) |
95 | { | 100 | { |
96 | return ((tm->tm_year + 1900) << RYxR_YEAR_S) | 101 | return ((tm->tm_year + 1900) << RYxR_YEAR_S) |
@@ -100,7 +105,10 @@ static u32 ryxr_calc(struct rtc_time *tm) | |||
100 | 105 | ||
101 | static u32 rdxr_calc(struct rtc_time *tm) | 106 | static u32 rdxr_calc(struct rtc_time *tm) |
102 | { | 107 | { |
103 | return (tm->tm_hour << RDxR_HOUR_S) | (tm->tm_min << RDxR_MIN_S) | 108 | return ((((tm->tm_mday + 6) / 7) << RDxR_WOM_S) & RDxR_WOM_MASK) |
109 | | (((tm->tm_wday + 1) << RDxR_DOW_S) & RDxR_DOW_MASK) | ||
110 | | (tm->tm_hour << RDxR_HOUR_S) | ||
111 | | (tm->tm_min << RDxR_MIN_S) | ||
104 | | tm->tm_sec; | 112 | | tm->tm_sec; |
105 | } | 113 | } |
106 | 114 | ||
@@ -109,6 +117,7 @@ static void tm_calc(u32 rycr, u32 rdcr, struct rtc_time *tm) | |||
109 | tm->tm_year = ((rycr & RYxR_YEAR_MASK) >> RYxR_YEAR_S) - 1900; | 117 | tm->tm_year = ((rycr & RYxR_YEAR_MASK) >> RYxR_YEAR_S) - 1900; |
110 | tm->tm_mon = (((rycr & RYxR_MONTH_MASK) >> RYxR_MONTH_S)) - 1; | 118 | tm->tm_mon = (((rycr & RYxR_MONTH_MASK) >> RYxR_MONTH_S)) - 1; |
111 | tm->tm_mday = (rycr & RYxR_DAY_MASK); | 119 | tm->tm_mday = (rycr & RYxR_DAY_MASK); |
120 | tm->tm_wday = ((rycr & RDxR_DOW_MASK) >> RDxR_DOW_S) - 1; | ||
112 | tm->tm_hour = (rdcr & RDxR_HOUR_MASK) >> RDxR_HOUR_S; | 121 | tm->tm_hour = (rdcr & RDxR_HOUR_MASK) >> RDxR_HOUR_S; |
113 | tm->tm_min = (rdcr & RDxR_MIN_MASK) >> RDxR_MIN_S; | 122 | tm->tm_min = (rdcr & RDxR_MIN_MASK) >> RDxR_MIN_S; |
114 | tm->tm_sec = rdcr & RDxR_SEC_MASK; | 123 | tm->tm_sec = rdcr & RDxR_SEC_MASK; |
@@ -300,8 +309,6 @@ static int pxa_rtc_proc(struct device *dev, struct seq_file *seq) | |||
300 | } | 309 | } |
301 | 310 | ||
302 | static const struct rtc_class_ops pxa_rtc_ops = { | 311 | static const struct rtc_class_ops pxa_rtc_ops = { |
303 | .open = pxa_rtc_open, | ||
304 | .release = pxa_rtc_release, | ||
305 | .read_time = pxa_rtc_read_time, | 312 | .read_time = pxa_rtc_read_time, |
306 | .set_time = pxa_rtc_set_time, | 313 | .set_time = pxa_rtc_set_time, |
307 | .read_alarm = pxa_rtc_read_alarm, | 314 | .read_alarm = pxa_rtc_read_alarm, |
@@ -341,7 +348,7 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) | |||
341 | dev_err(dev, "No alarm IRQ resource defined\n"); | 348 | dev_err(dev, "No alarm IRQ resource defined\n"); |
342 | goto err_ress; | 349 | goto err_ress; |
343 | } | 350 | } |
344 | 351 | pxa_rtc_open(dev); | |
345 | ret = -ENOMEM; | 352 | ret = -ENOMEM; |
346 | pxa_rtc->base = ioremap(pxa_rtc->ress->start, | 353 | pxa_rtc->base = ioremap(pxa_rtc->ress->start, |
347 | resource_size(pxa_rtc->ress)); | 354 | resource_size(pxa_rtc->ress)); |
@@ -387,6 +394,9 @@ static int __exit pxa_rtc_remove(struct platform_device *pdev) | |||
387 | { | 394 | { |
388 | struct pxa_rtc *pxa_rtc = platform_get_drvdata(pdev); | 395 | struct pxa_rtc *pxa_rtc = platform_get_drvdata(pdev); |
389 | 396 | ||
397 | struct device *dev = &pdev->dev; | ||
398 | pxa_rtc_release(dev); | ||
399 | |||
390 | rtc_device_unregister(pxa_rtc->rtc); | 400 | rtc_device_unregister(pxa_rtc->rtc); |
391 | 401 | ||
392 | spin_lock_irq(&pxa_rtc->lock); | 402 | spin_lock_irq(&pxa_rtc->lock); |
@@ -444,10 +454,7 @@ static struct platform_driver pxa_rtc_driver = { | |||
444 | 454 | ||
445 | static int __init pxa_rtc_init(void) | 455 | static int __init pxa_rtc_init(void) |
446 | { | 456 | { |
447 | if (cpu_is_pxa27x() || cpu_is_pxa3xx()) | 457 | return platform_driver_probe(&pxa_rtc_driver, pxa_rtc_probe); |
448 | return platform_driver_probe(&pxa_rtc_driver, pxa_rtc_probe); | ||
449 | |||
450 | return -ENODEV; | ||
451 | } | 458 | } |
452 | 459 | ||
453 | static void __exit pxa_rtc_exit(void) | 460 | static void __exit pxa_rtc_exit(void) |
diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c index d1aee793ecc8..d98ea5b759c8 100644 --- a/drivers/rtc/rtc-rs5c313.c +++ b/drivers/rtc/rtc-rs5c313.c | |||
@@ -39,6 +39,8 @@ | |||
39 | * 1.13 Nobuhiro Iwamatsu: Updata driver. | 39 | * 1.13 Nobuhiro Iwamatsu: Updata driver. |
40 | */ | 40 | */ |
41 | 41 | ||
42 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
43 | |||
42 | #include <linux/module.h> | 44 | #include <linux/module.h> |
43 | #include <linux/err.h> | 45 | #include <linux/err.h> |
44 | #include <linux/rtc.h> | 46 | #include <linux/rtc.h> |
@@ -352,8 +354,7 @@ static void rs5c313_check_xstp_bit(void) | |||
352 | tm.tm_year = 2000 - 1900; | 354 | tm.tm_year = 2000 - 1900; |
353 | 355 | ||
354 | rs5c313_rtc_set_time(NULL, &tm); | 356 | rs5c313_rtc_set_time(NULL, &tm); |
355 | printk(KERN_ERR "RICHO RS5C313: invalid value, resetting to " | 357 | pr_err("invalid value, resetting to 1 Jan 2000\n"); |
356 | "1 Jan 2000\n"); | ||
357 | } | 358 | } |
358 | RS5C313_CEDISABLE; | 359 | RS5C313_CEDISABLE; |
359 | ndelay(700); /* CE:L */ | 360 | ndelay(700); /* CE:L */ |
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 76f565ae384d..581739f40097 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c | |||
@@ -311,8 +311,7 @@ static int rs5c_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
311 | buf &= ~RS5C_CTRL1_AALE; | 311 | buf &= ~RS5C_CTRL1_AALE; |
312 | 312 | ||
313 | if (i2c_smbus_write_byte_data(client, addr, buf) < 0) { | 313 | if (i2c_smbus_write_byte_data(client, addr, buf) < 0) { |
314 | printk(KERN_WARNING "%s: can't update alarm\n", | 314 | dev_warn(dev, "can't update alarm\n"); |
315 | rs5c->rtc->name); | ||
316 | status = -EIO; | 315 | status = -EIO; |
317 | } else | 316 | } else |
318 | rs5c->regs[RS5C_REG_CTRL1] = buf; | 317 | rs5c->regs[RS5C_REG_CTRL1] = buf; |
@@ -381,7 +380,7 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
381 | addr = RS5C_ADDR(RS5C_REG_CTRL1); | 380 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
382 | buf[0] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE; | 381 | buf[0] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE; |
383 | if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) { | 382 | if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) { |
384 | pr_debug("%s: can't disable alarm\n", rs5c->rtc->name); | 383 | dev_dbg(dev, "can't disable alarm\n"); |
385 | return -EIO; | 384 | return -EIO; |
386 | } | 385 | } |
387 | rs5c->regs[RS5C_REG_CTRL1] = buf[0]; | 386 | rs5c->regs[RS5C_REG_CTRL1] = buf[0]; |
@@ -395,7 +394,7 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
395 | for (i = 0; i < sizeof(buf); i++) { | 394 | for (i = 0; i < sizeof(buf); i++) { |
396 | addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i); | 395 | addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i); |
397 | if (i2c_smbus_write_byte_data(client, addr, buf[i]) < 0) { | 396 | if (i2c_smbus_write_byte_data(client, addr, buf[i]) < 0) { |
398 | pr_debug("%s: can't set alarm time\n", rs5c->rtc->name); | 397 | dev_dbg(dev, "can't set alarm time\n"); |
399 | return -EIO; | 398 | return -EIO; |
400 | } | 399 | } |
401 | } | 400 | } |
@@ -405,8 +404,7 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
405 | addr = RS5C_ADDR(RS5C_REG_CTRL1); | 404 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
406 | buf[0] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE; | 405 | buf[0] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE; |
407 | if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) | 406 | if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) |
408 | printk(KERN_WARNING "%s: can't enable alarm\n", | 407 | dev_warn(dev, "can't enable alarm\n"); |
409 | rs5c->rtc->name); | ||
410 | rs5c->regs[RS5C_REG_CTRL1] = buf[0]; | 408 | rs5c->regs[RS5C_REG_CTRL1] = buf[0]; |
411 | } | 409 | } |
412 | 410 | ||
diff --git a/drivers/rtc/rtc-rx4581.c b/drivers/rtc/rtc-rx4581.c new file mode 100644 index 000000000000..599ec73ec886 --- /dev/null +++ b/drivers/rtc/rtc-rx4581.c | |||
@@ -0,0 +1,314 @@ | |||
1 | /* drivers/rtc/rtc-rx4581.c | ||
2 | * | ||
3 | * written by Torben Hohn <torbenh@linutronix.de> | ||
4 | * | ||
5 | * Based on: | ||
6 | * drivers/rtc/rtc-max6902.c | ||
7 | * | ||
8 | * Copyright (C) 2006 8D Technologies inc. | ||
9 | * Copyright (C) 2004 Compulab Ltd. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * Driver for MAX6902 spi RTC | ||
16 | * | ||
17 | * and based on: | ||
18 | * drivers/rtc/rtc-rx8581.c | ||
19 | * | ||
20 | * An I2C driver for the Epson RX8581 RTC | ||
21 | * | ||
22 | * Author: Martyn Welch <martyn.welch@ge.com> | ||
23 | * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. | ||
24 | * | ||
25 | * This program is free software; you can redistribute it and/or modify | ||
26 | * it under the terms of the GNU General Public License version 2 as | ||
27 | * published by the Free Software Foundation. | ||
28 | * | ||
29 | * Based on: rtc-pcf8563.c (An I2C driver for the Philips PCF8563 RTC) | ||
30 | * Copyright 2005-06 Tower Technologies | ||
31 | * | ||
32 | */ | ||
33 | |||
34 | #include <linux/module.h> | ||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/platform_device.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/rtc.h> | ||
39 | #include <linux/spi/spi.h> | ||
40 | #include <linux/bcd.h> | ||
41 | |||
42 | #define RX4581_REG_SC 0x00 /* Second in BCD */ | ||
43 | #define RX4581_REG_MN 0x01 /* Minute in BCD */ | ||
44 | #define RX4581_REG_HR 0x02 /* Hour in BCD */ | ||
45 | #define RX4581_REG_DW 0x03 /* Day of Week */ | ||
46 | #define RX4581_REG_DM 0x04 /* Day of Month in BCD */ | ||
47 | #define RX4581_REG_MO 0x05 /* Month in BCD */ | ||
48 | #define RX4581_REG_YR 0x06 /* Year in BCD */ | ||
49 | #define RX4581_REG_RAM 0x07 /* RAM */ | ||
50 | #define RX4581_REG_AMN 0x08 /* Alarm Min in BCD*/ | ||
51 | #define RX4581_REG_AHR 0x09 /* Alarm Hour in BCD */ | ||
52 | #define RX4581_REG_ADM 0x0A | ||
53 | #define RX4581_REG_ADW 0x0A | ||
54 | #define RX4581_REG_TMR0 0x0B | ||
55 | #define RX4581_REG_TMR1 0x0C | ||
56 | #define RX4581_REG_EXT 0x0D /* Extension Register */ | ||
57 | #define RX4581_REG_FLAG 0x0E /* Flag Register */ | ||
58 | #define RX4581_REG_CTRL 0x0F /* Control Register */ | ||
59 | |||
60 | |||
61 | /* Flag Register bit definitions */ | ||
62 | #define RX4581_FLAG_UF 0x20 /* Update */ | ||
63 | #define RX4581_FLAG_TF 0x10 /* Timer */ | ||
64 | #define RX4581_FLAG_AF 0x08 /* Alarm */ | ||
65 | #define RX4581_FLAG_VLF 0x02 /* Voltage Low */ | ||
66 | |||
67 | /* Control Register bit definitions */ | ||
68 | #define RX4581_CTRL_UIE 0x20 /* Update Interrupt Enable */ | ||
69 | #define RX4581_CTRL_TIE 0x10 /* Timer Interrupt Enable */ | ||
70 | #define RX4581_CTRL_AIE 0x08 /* Alarm Interrupt Enable */ | ||
71 | #define RX4581_CTRL_STOP 0x02 /* STOP bit */ | ||
72 | #define RX4581_CTRL_RESET 0x01 /* RESET bit */ | ||
73 | |||
74 | static int rx4581_set_reg(struct device *dev, unsigned char address, | ||
75 | unsigned char data) | ||
76 | { | ||
77 | struct spi_device *spi = to_spi_device(dev); | ||
78 | unsigned char buf[2]; | ||
79 | |||
80 | /* high nibble must be '0' to write */ | ||
81 | buf[0] = address & 0x0f; | ||
82 | buf[1] = data; | ||
83 | |||
84 | return spi_write_then_read(spi, buf, 2, NULL, 0); | ||
85 | } | ||
86 | |||
87 | static int rx4581_get_reg(struct device *dev, unsigned char address, | ||
88 | unsigned char *data) | ||
89 | { | ||
90 | struct spi_device *spi = to_spi_device(dev); | ||
91 | |||
92 | /* Set MSB to indicate read */ | ||
93 | *data = address | 0x80; | ||
94 | |||
95 | return spi_write_then_read(spi, data, 1, data, 1); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * In the routines that deal directly with the rx8581 hardware, we use | ||
100 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
101 | */ | ||
102 | static int rx4581_get_datetime(struct device *dev, struct rtc_time *tm) | ||
103 | { | ||
104 | struct spi_device *spi = to_spi_device(dev); | ||
105 | unsigned char date[7]; | ||
106 | unsigned char data; | ||
107 | int err; | ||
108 | |||
109 | /* First we ensure that the "update flag" is not set, we read the | ||
110 | * time and date then re-read the "update flag". If the update flag | ||
111 | * has been set, we know that the time has changed during the read so | ||
112 | * we repeat the whole process again. | ||
113 | */ | ||
114 | err = rx4581_get_reg(dev, RX4581_REG_FLAG, &data); | ||
115 | if (err != 0) { | ||
116 | dev_err(dev, "Unable to read device flags\n"); | ||
117 | return -EIO; | ||
118 | } | ||
119 | |||
120 | do { | ||
121 | /* If update flag set, clear it */ | ||
122 | if (data & RX4581_FLAG_UF) { | ||
123 | err = rx4581_set_reg(dev, | ||
124 | RX4581_REG_FLAG, (data & ~RX4581_FLAG_UF)); | ||
125 | if (err != 0) { | ||
126 | dev_err(dev, "Unable to write device " | ||
127 | "flags\n"); | ||
128 | return -EIO; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | /* Now read time and date */ | ||
133 | date[0] = 0x80; | ||
134 | err = spi_write_then_read(spi, date, 1, date, 7); | ||
135 | if (err < 0) { | ||
136 | dev_err(dev, "Unable to read date\n"); | ||
137 | return -EIO; | ||
138 | } | ||
139 | |||
140 | /* Check flag register */ | ||
141 | err = rx4581_get_reg(dev, RX4581_REG_FLAG, &data); | ||
142 | if (err != 0) { | ||
143 | dev_err(dev, "Unable to read device flags\n"); | ||
144 | return -EIO; | ||
145 | } | ||
146 | } while (data & RX4581_FLAG_UF); | ||
147 | |||
148 | if (data & RX4581_FLAG_VLF) | ||
149 | dev_info(dev, | ||
150 | "low voltage detected, date/time is not reliable.\n"); | ||
151 | |||
152 | dev_dbg(dev, | ||
153 | "%s: raw data is sec=%02x, min=%02x, hr=%02x, " | ||
154 | "wday=%02x, mday=%02x, mon=%02x, year=%02x\n", | ||
155 | __func__, | ||
156 | date[0], date[1], date[2], date[3], date[4], date[5], date[6]); | ||
157 | |||
158 | tm->tm_sec = bcd2bin(date[RX4581_REG_SC] & 0x7F); | ||
159 | tm->tm_min = bcd2bin(date[RX4581_REG_MN] & 0x7F); | ||
160 | tm->tm_hour = bcd2bin(date[RX4581_REG_HR] & 0x3F); /* rtc hr 0-23 */ | ||
161 | tm->tm_wday = ilog2(date[RX4581_REG_DW] & 0x7F); | ||
162 | tm->tm_mday = bcd2bin(date[RX4581_REG_DM] & 0x3F); | ||
163 | tm->tm_mon = bcd2bin(date[RX4581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ | ||
164 | tm->tm_year = bcd2bin(date[RX4581_REG_YR]); | ||
165 | if (tm->tm_year < 70) | ||
166 | tm->tm_year += 100; /* assume we are in 1970...2069 */ | ||
167 | |||
168 | |||
169 | dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | ||
170 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
171 | __func__, | ||
172 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
173 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
174 | |||
175 | err = rtc_valid_tm(tm); | ||
176 | if (err < 0) | ||
177 | dev_err(dev, "retrieved date/time is not valid.\n"); | ||
178 | |||
179 | return err; | ||
180 | } | ||
181 | |||
182 | static int rx4581_set_datetime(struct device *dev, struct rtc_time *tm) | ||
183 | { | ||
184 | struct spi_device *spi = to_spi_device(dev); | ||
185 | int err; | ||
186 | unsigned char buf[8], data; | ||
187 | |||
188 | dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, " | ||
189 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
190 | __func__, | ||
191 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
192 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
193 | |||
194 | buf[0] = 0x00; | ||
195 | /* hours, minutes and seconds */ | ||
196 | buf[RX4581_REG_SC+1] = bin2bcd(tm->tm_sec); | ||
197 | buf[RX4581_REG_MN+1] = bin2bcd(tm->tm_min); | ||
198 | buf[RX4581_REG_HR+1] = bin2bcd(tm->tm_hour); | ||
199 | |||
200 | buf[RX4581_REG_DM+1] = bin2bcd(tm->tm_mday); | ||
201 | |||
202 | /* month, 1 - 12 */ | ||
203 | buf[RX4581_REG_MO+1] = bin2bcd(tm->tm_mon + 1); | ||
204 | |||
205 | /* year and century */ | ||
206 | buf[RX4581_REG_YR+1] = bin2bcd(tm->tm_year % 100); | ||
207 | buf[RX4581_REG_DW+1] = (0x1 << tm->tm_wday); | ||
208 | |||
209 | /* Stop the clock */ | ||
210 | err = rx4581_get_reg(dev, RX4581_REG_CTRL, &data); | ||
211 | if (err != 0) { | ||
212 | dev_err(dev, "Unable to read control register\n"); | ||
213 | return -EIO; | ||
214 | } | ||
215 | |||
216 | err = rx4581_set_reg(dev, RX4581_REG_CTRL, | ||
217 | (data | RX4581_CTRL_STOP)); | ||
218 | if (err != 0) { | ||
219 | dev_err(dev, "Unable to write control register\n"); | ||
220 | return -EIO; | ||
221 | } | ||
222 | |||
223 | /* write register's data */ | ||
224 | err = spi_write_then_read(spi, buf, 8, NULL, 0); | ||
225 | if (err != 0) { | ||
226 | dev_err(dev, "Unable to write to date registers\n"); | ||
227 | return -EIO; | ||
228 | } | ||
229 | |||
230 | /* get VLF and clear it */ | ||
231 | err = rx4581_get_reg(dev, RX4581_REG_FLAG, &data); | ||
232 | if (err != 0) { | ||
233 | dev_err(dev, "Unable to read flag register\n"); | ||
234 | return -EIO; | ||
235 | } | ||
236 | |||
237 | err = rx4581_set_reg(dev, RX4581_REG_FLAG, | ||
238 | (data & ~(RX4581_FLAG_VLF))); | ||
239 | if (err != 0) { | ||
240 | dev_err(dev, "Unable to write flag register\n"); | ||
241 | return -EIO; | ||
242 | } | ||
243 | |||
244 | /* Restart the clock */ | ||
245 | err = rx4581_get_reg(dev, RX4581_REG_CTRL, &data); | ||
246 | if (err != 0) { | ||
247 | dev_err(dev, "Unable to read control register\n"); | ||
248 | return -EIO; | ||
249 | } | ||
250 | |||
251 | err = rx4581_set_reg(dev, RX4581_REG_CTRL, | ||
252 | (data & ~(RX4581_CTRL_STOP))); | ||
253 | if (err != 0) { | ||
254 | dev_err(dev, "Unable to write control register\n"); | ||
255 | return -EIO; | ||
256 | } | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static const struct rtc_class_ops rx4581_rtc_ops = { | ||
262 | .read_time = rx4581_get_datetime, | ||
263 | .set_time = rx4581_set_datetime, | ||
264 | }; | ||
265 | |||
266 | static int rx4581_probe(struct spi_device *spi) | ||
267 | { | ||
268 | struct rtc_device *rtc; | ||
269 | unsigned char tmp; | ||
270 | int res; | ||
271 | |||
272 | res = rx4581_get_reg(&spi->dev, RX4581_REG_SC, &tmp); | ||
273 | if (res != 0) | ||
274 | return res; | ||
275 | |||
276 | rtc = rtc_device_register("rx4581", | ||
277 | &spi->dev, &rx4581_rtc_ops, THIS_MODULE); | ||
278 | if (IS_ERR(rtc)) | ||
279 | return PTR_ERR(rtc); | ||
280 | |||
281 | dev_set_drvdata(&spi->dev, rtc); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int rx4581_remove(struct spi_device *spi) | ||
286 | { | ||
287 | struct rtc_device *rtc = dev_get_drvdata(&spi->dev); | ||
288 | |||
289 | rtc_device_unregister(rtc); | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static const struct spi_device_id rx4581_id[] = { | ||
294 | { "rx4581", 0 }, | ||
295 | { } | ||
296 | }; | ||
297 | MODULE_DEVICE_TABLE(spi, rx4581_id); | ||
298 | |||
299 | static struct spi_driver rx4581_driver = { | ||
300 | .driver = { | ||
301 | .name = "rtc-rx4581", | ||
302 | .owner = THIS_MODULE, | ||
303 | }, | ||
304 | .probe = rx4581_probe, | ||
305 | .remove = rx4581_remove, | ||
306 | .id_table = rx4581_id, | ||
307 | }; | ||
308 | |||
309 | module_spi_driver(rx4581_driver); | ||
310 | |||
311 | MODULE_DESCRIPTION("rx4581 spi RTC driver"); | ||
312 | MODULE_AUTHOR("Torben Hohn"); | ||
313 | MODULE_LICENSE("GPL"); | ||
314 | MODULE_ALIAS("spi:rtc-rx4581"); | ||
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 0c397ac3b132..fb994e9ddc15 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -115,7 +115,7 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled) | |||
115 | { | 115 | { |
116 | unsigned int tmp; | 116 | unsigned int tmp; |
117 | 117 | ||
118 | pr_debug("%s: aie=%d\n", __func__, enabled); | 118 | dev_dbg(dev, "%s: aie=%d\n", __func__, enabled); |
119 | 119 | ||
120 | clk_enable(rtc_clk); | 120 | clk_enable(rtc_clk); |
121 | tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; | 121 | tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; |
@@ -203,7 +203,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
203 | 203 | ||
204 | rtc_tm->tm_year += 100; | 204 | rtc_tm->tm_year += 100; |
205 | 205 | ||
206 | pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n", | 206 | dev_dbg(dev, "read time %04d.%02d.%02d %02d:%02d:%02d\n", |
207 | 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, | 207 | 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, |
208 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); | 208 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); |
209 | 209 | ||
@@ -218,7 +218,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
218 | void __iomem *base = s3c_rtc_base; | 218 | void __iomem *base = s3c_rtc_base; |
219 | int year = tm->tm_year - 100; | 219 | int year = tm->tm_year - 100; |
220 | 220 | ||
221 | pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", | 221 | dev_dbg(dev, "set time %04d.%02d.%02d %02d:%02d:%02d\n", |
222 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | 222 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
223 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 223 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
224 | 224 | ||
@@ -259,7 +259,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
259 | 259 | ||
260 | alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; | 260 | alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; |
261 | 261 | ||
262 | pr_debug("read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n", | 262 | dev_dbg(dev, "read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n", |
263 | alm_en, | 263 | alm_en, |
264 | 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, | 264 | 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, |
265 | alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); | 265 | alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); |
@@ -310,7 +310,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
310 | unsigned int alrm_en; | 310 | unsigned int alrm_en; |
311 | 311 | ||
312 | clk_enable(rtc_clk); | 312 | clk_enable(rtc_clk); |
313 | pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", | 313 | dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", |
314 | alrm->enabled, | 314 | alrm->enabled, |
315 | 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, | 315 | 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, |
316 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 316 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
@@ -333,7 +333,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
333 | writeb(bin2bcd(tm->tm_hour), base + S3C2410_ALMHOUR); | 333 | writeb(bin2bcd(tm->tm_hour), base + S3C2410_ALMHOUR); |
334 | } | 334 | } |
335 | 335 | ||
336 | pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en); | 336 | dev_dbg(dev, "setting S3C2410_RTCALM to %08x\n", alrm_en); |
337 | 337 | ||
338 | writeb(alrm_en, base + S3C2410_RTCALM); | 338 | writeb(alrm_en, base + S3C2410_RTCALM); |
339 | 339 | ||
@@ -459,7 +459,7 @@ static int s3c_rtc_probe(struct platform_device *pdev) | |||
459 | int ret; | 459 | int ret; |
460 | int tmp; | 460 | int tmp; |
461 | 461 | ||
462 | pr_debug("%s: probe=%p\n", __func__, pdev); | 462 | dev_dbg(&pdev->dev, "%s: probe=%p\n", __func__, pdev); |
463 | 463 | ||
464 | /* find the IRQs */ | 464 | /* find the IRQs */ |
465 | 465 | ||
@@ -475,7 +475,7 @@ static int s3c_rtc_probe(struct platform_device *pdev) | |||
475 | return s3c_rtc_alarmno; | 475 | return s3c_rtc_alarmno; |
476 | } | 476 | } |
477 | 477 | ||
478 | pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n", | 478 | dev_dbg(&pdev->dev, "s3c2410_rtc: tick irq %d, alarm irq %d\n", |
479 | s3c_rtc_tickno, s3c_rtc_alarmno); | 479 | s3c_rtc_tickno, s3c_rtc_alarmno); |
480 | 480 | ||
481 | /* get the memory region */ | 481 | /* get the memory region */ |
@@ -504,7 +504,7 @@ static int s3c_rtc_probe(struct platform_device *pdev) | |||
504 | 504 | ||
505 | s3c_rtc_enable(pdev, 1); | 505 | s3c_rtc_enable(pdev, 1); |
506 | 506 | ||
507 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", | 507 | dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n", |
508 | readw(s3c_rtc_base + S3C2410_RTCCON)); | 508 | readw(s3c_rtc_base + S3C2410_RTCCON)); |
509 | 509 | ||
510 | device_init_wakeup(&pdev->dev, 1); | 510 | device_init_wakeup(&pdev->dev, 1); |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 50a5c4adee48..5ec5036df0bc 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -108,9 +108,6 @@ static int sa1100_rtc_open(struct device *dev) | |||
108 | struct rtc_device *rtc = info->rtc; | 108 | struct rtc_device *rtc = info->rtc; |
109 | int ret; | 109 | int ret; |
110 | 110 | ||
111 | ret = clk_prepare_enable(info->clk); | ||
112 | if (ret) | ||
113 | goto fail_clk; | ||
114 | ret = request_irq(info->irq_1hz, sa1100_rtc_interrupt, 0, "rtc 1Hz", dev); | 111 | ret = request_irq(info->irq_1hz, sa1100_rtc_interrupt, 0, "rtc 1Hz", dev); |
115 | if (ret) { | 112 | if (ret) { |
116 | dev_err(dev, "IRQ %d already in use.\n", info->irq_1hz); | 113 | dev_err(dev, "IRQ %d already in use.\n", info->irq_1hz); |
@@ -130,7 +127,6 @@ static int sa1100_rtc_open(struct device *dev) | |||
130 | free_irq(info->irq_1hz, dev); | 127 | free_irq(info->irq_1hz, dev); |
131 | fail_ui: | 128 | fail_ui: |
132 | clk_disable_unprepare(info->clk); | 129 | clk_disable_unprepare(info->clk); |
133 | fail_clk: | ||
134 | return ret; | 130 | return ret; |
135 | } | 131 | } |
136 | 132 | ||
@@ -144,7 +140,6 @@ static void sa1100_rtc_release(struct device *dev) | |||
144 | 140 | ||
145 | free_irq(info->irq_alarm, dev); | 141 | free_irq(info->irq_alarm, dev); |
146 | free_irq(info->irq_1hz, dev); | 142 | free_irq(info->irq_1hz, dev); |
147 | clk_disable_unprepare(info->clk); | ||
148 | } | 143 | } |
149 | 144 | ||
150 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 145 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
@@ -253,6 +248,9 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
253 | spin_lock_init(&info->lock); | 248 | spin_lock_init(&info->lock); |
254 | platform_set_drvdata(pdev, info); | 249 | platform_set_drvdata(pdev, info); |
255 | 250 | ||
251 | ret = clk_prepare_enable(info->clk); | ||
252 | if (ret) | ||
253 | goto err_enable_clk; | ||
256 | /* | 254 | /* |
257 | * According to the manual we should be able to let RTTR be zero | 255 | * According to the manual we should be able to let RTTR be zero |
258 | * and then a default diviser for a 32.768KHz clock is used. | 256 | * and then a default diviser for a 32.768KHz clock is used. |
@@ -305,6 +303,8 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
305 | 303 | ||
306 | return 0; | 304 | return 0; |
307 | err_dev: | 305 | err_dev: |
306 | clk_disable_unprepare(info->clk); | ||
307 | err_enable_clk: | ||
308 | platform_set_drvdata(pdev, NULL); | 308 | platform_set_drvdata(pdev, NULL); |
309 | clk_put(info->clk); | 309 | clk_put(info->clk); |
310 | err_clk: | 310 | err_clk: |
@@ -318,6 +318,7 @@ static int sa1100_rtc_remove(struct platform_device *pdev) | |||
318 | 318 | ||
319 | if (info) { | 319 | if (info) { |
320 | rtc_device_unregister(info->rtc); | 320 | rtc_device_unregister(info->rtc); |
321 | clk_disable_unprepare(info->clk); | ||
321 | clk_put(info->clk); | 322 | clk_put(info->clk); |
322 | platform_set_drvdata(pdev, NULL); | 323 | platform_set_drvdata(pdev, NULL); |
323 | kfree(info); | 324 | kfree(info); |
@@ -349,12 +350,14 @@ static const struct dev_pm_ops sa1100_rtc_pm_ops = { | |||
349 | }; | 350 | }; |
350 | #endif | 351 | #endif |
351 | 352 | ||
353 | #ifdef CONFIG_OF | ||
352 | static struct of_device_id sa1100_rtc_dt_ids[] = { | 354 | static struct of_device_id sa1100_rtc_dt_ids[] = { |
353 | { .compatible = "mrvl,sa1100-rtc", }, | 355 | { .compatible = "mrvl,sa1100-rtc", }, |
354 | { .compatible = "mrvl,mmp-rtc", }, | 356 | { .compatible = "mrvl,mmp-rtc", }, |
355 | {} | 357 | {} |
356 | }; | 358 | }; |
357 | MODULE_DEVICE_TABLE(of, sa1100_rtc_dt_ids); | 359 | MODULE_DEVICE_TABLE(of, sa1100_rtc_dt_ids); |
360 | #endif | ||
358 | 361 | ||
359 | static struct platform_driver sa1100_rtc_driver = { | 362 | static struct platform_driver sa1100_rtc_driver = { |
360 | .probe = sa1100_rtc_probe, | 363 | .probe = sa1100_rtc_probe, |
@@ -364,7 +367,7 @@ static struct platform_driver sa1100_rtc_driver = { | |||
364 | #ifdef CONFIG_PM | 367 | #ifdef CONFIG_PM |
365 | .pm = &sa1100_rtc_pm_ops, | 368 | .pm = &sa1100_rtc_pm_ops, |
366 | #endif | 369 | #endif |
367 | .of_match_table = sa1100_rtc_dt_ids, | 370 | .of_match_table = of_match_ptr(sa1100_rtc_dt_ids), |
368 | }, | 371 | }, |
369 | }; | 372 | }; |
370 | 373 | ||
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 40662e9dc0ab..f7d90703db5e 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c | |||
@@ -338,7 +338,7 @@ static struct platform_driver snvs_rtc_driver = { | |||
338 | .name = "snvs_rtc", | 338 | .name = "snvs_rtc", |
339 | .owner = THIS_MODULE, | 339 | .owner = THIS_MODULE, |
340 | .pm = &snvs_rtc_pm_ops, | 340 | .pm = &snvs_rtc_pm_ops, |
341 | .of_match_table = snvs_dt_ids, | 341 | .of_match_table = of_match_ptr(snvs_dt_ids), |
342 | }, | 342 | }, |
343 | .probe = snvs_rtc_probe, | 343 | .probe = snvs_rtc_probe, |
344 | .remove = snvs_rtc_remove, | 344 | .remove = snvs_rtc_remove, |
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 739ef55694f4..b2a8ed99b2bf 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/rtc.h> | 26 | #include <linux/rtc.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/of_device.h> | 28 | #include <linux/of_device.h> |
29 | #include <linux/of.h> | ||
29 | 30 | ||
30 | #include <mach/common.h> | 31 | #include <mach/common.h> |
31 | 32 | ||
@@ -280,7 +281,7 @@ static struct platform_driver stmp3xxx_rtcdrv = { | |||
280 | .driver = { | 281 | .driver = { |
281 | .name = "stmp3xxx-rtc", | 282 | .name = "stmp3xxx-rtc", |
282 | .owner = THIS_MODULE, | 283 | .owner = THIS_MODULE, |
283 | .of_match_table = rtc_dt_ids, | 284 | .of_match_table = of_match_ptr(rtc_dt_ids), |
284 | }, | 285 | }, |
285 | }; | 286 | }; |
286 | 287 | ||
diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c index 5b2261052a65..59b5c2dcb58c 100644 --- a/drivers/rtc/rtc-sun4v.c +++ b/drivers/rtc/rtc-sun4v.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
7 | |||
6 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
7 | #include <linux/module.h> | 9 | #include <linux/module.h> |
8 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
@@ -26,10 +28,10 @@ retry: | |||
26 | udelay(100); | 28 | udelay(100); |
27 | goto retry; | 29 | goto retry; |
28 | } | 30 | } |
29 | printk(KERN_WARNING "SUN4V: tod_get() timed out.\n"); | 31 | pr_warn("tod_get() timed out.\n"); |
30 | return 0; | 32 | return 0; |
31 | } | 33 | } |
32 | printk(KERN_WARNING "SUN4V: tod_get() not supported.\n"); | 34 | pr_warn("tod_get() not supported.\n"); |
33 | return 0; | 35 | return 0; |
34 | } | 36 | } |
35 | 37 | ||
@@ -53,10 +55,10 @@ retry: | |||
53 | udelay(100); | 55 | udelay(100); |
54 | goto retry; | 56 | goto retry; |
55 | } | 57 | } |
56 | printk(KERN_WARNING "SUN4V: tod_set() timed out.\n"); | 58 | pr_warn("tod_set() timed out.\n"); |
57 | return -EAGAIN; | 59 | return -EAGAIN; |
58 | } | 60 | } |
59 | printk(KERN_WARNING "SUN4V: tod_set() not supported.\n"); | 61 | pr_warn("tod_set() not supported.\n"); |
60 | return -EOPNOTSUPP; | 62 | return -EOPNOTSUPP; |
61 | } | 63 | } |
62 | 64 | ||
diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c index 70f61b8e9e6f..aab4e8c93622 100644 --- a/drivers/rtc/rtc-tps6586x.c +++ b/drivers/rtc/rtc-tps6586x.c | |||
@@ -282,7 +282,8 @@ static int tps6586x_rtc_probe(struct platform_device *pdev) | |||
282 | goto fail_rtc_register; | 282 | goto fail_rtc_register; |
283 | } | 283 | } |
284 | 284 | ||
285 | ret = request_threaded_irq(rtc->irq, NULL, tps6586x_rtc_irq, | 285 | ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, |
286 | tps6586x_rtc_irq, | ||
286 | IRQF_ONESHOT | IRQF_EARLY_RESUME, | 287 | IRQF_ONESHOT | IRQF_EARLY_RESUME, |
287 | dev_name(&pdev->dev), rtc); | 288 | dev_name(&pdev->dev), rtc); |
288 | if (ret < 0) { | 289 | if (ret < 0) { |
@@ -311,7 +312,6 @@ static int tps6586x_rtc_remove(struct platform_device *pdev) | |||
311 | tps6586x_update(tps_dev, RTC_CTRL, 0, | 312 | tps6586x_update(tps_dev, RTC_CTRL, 0, |
312 | RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK); | 313 | RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK); |
313 | rtc_device_unregister(rtc->rtc); | 314 | rtc_device_unregister(rtc->rtc); |
314 | free_irq(rtc->irq, rtc); | ||
315 | return 0; | 315 | return 0; |
316 | } | 316 | } |
317 | 317 | ||
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index e5fef141a0e2..8bd8115329b5 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c | |||
@@ -22,13 +22,13 @@ | |||
22 | #include <linux/rtc.h> | 22 | #include <linux/rtc.h> |
23 | #include <linux/bcd.h> | 23 | #include <linux/bcd.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/pm_runtime.h> | ||
25 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
26 | #include <linux/mfd/tps65910.h> | 27 | #include <linux/mfd/tps65910.h> |
27 | 28 | ||
28 | struct tps65910_rtc { | 29 | struct tps65910_rtc { |
29 | struct rtc_device *rtc; | 30 | struct rtc_device *rtc; |
30 | /* To store the list of enabled interrupts */ | 31 | int irq; |
31 | u32 irqstat; | ||
32 | }; | 32 | }; |
33 | 33 | ||
34 | /* Total number of RTC registers needed to set time*/ | 34 | /* Total number of RTC registers needed to set time*/ |
@@ -267,13 +267,14 @@ static int tps65910_rtc_probe(struct platform_device *pdev) | |||
267 | } | 267 | } |
268 | 268 | ||
269 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, | 269 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
270 | tps65910_rtc_interrupt, IRQF_TRIGGER_LOW, | 270 | tps65910_rtc_interrupt, IRQF_TRIGGER_LOW | IRQF_EARLY_RESUME, |
271 | dev_name(&pdev->dev), &pdev->dev); | 271 | dev_name(&pdev->dev), &pdev->dev); |
272 | if (ret < 0) { | 272 | if (ret < 0) { |
273 | dev_err(&pdev->dev, "IRQ is not free.\n"); | 273 | dev_err(&pdev->dev, "IRQ is not free.\n"); |
274 | return ret; | 274 | return ret; |
275 | } | 275 | } |
276 | device_init_wakeup(&pdev->dev, 1); | 276 | tps_rtc->irq = irq; |
277 | device_set_wakeup_capable(&pdev->dev, 1); | ||
277 | 278 | ||
278 | tps_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | 279 | tps_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, |
279 | &tps65910_rtc_ops, THIS_MODULE); | 280 | &tps65910_rtc_ops, THIS_MODULE); |
@@ -304,49 +305,36 @@ static int tps65910_rtc_remove(struct platform_device *pdev) | |||
304 | } | 305 | } |
305 | 306 | ||
306 | #ifdef CONFIG_PM_SLEEP | 307 | #ifdef CONFIG_PM_SLEEP |
307 | |||
308 | static int tps65910_rtc_suspend(struct device *dev) | 308 | static int tps65910_rtc_suspend(struct device *dev) |
309 | { | 309 | { |
310 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | 310 | struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); |
311 | u8 alarm = TPS65910_RTC_INTERRUPTS_IT_ALARM; | ||
312 | int ret; | ||
313 | |||
314 | /* Store current list of enabled interrupts*/ | ||
315 | ret = regmap_read(tps->regmap, TPS65910_RTC_INTERRUPTS, | ||
316 | &tps->rtc->irqstat); | ||
317 | if (ret < 0) | ||
318 | return ret; | ||
319 | 311 | ||
320 | /* Enable RTC ALARM interrupt only */ | 312 | if (device_may_wakeup(dev)) |
321 | return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, alarm); | 313 | enable_irq_wake(tps_rtc->irq); |
314 | return 0; | ||
322 | } | 315 | } |
323 | 316 | ||
324 | static int tps65910_rtc_resume(struct device *dev) | 317 | static int tps65910_rtc_resume(struct device *dev) |
325 | { | 318 | { |
326 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | 319 | struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); |
327 | 320 | ||
328 | /* Restore list of enabled interrupts before suspend */ | 321 | if (device_may_wakeup(dev)) |
329 | return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, | 322 | disable_irq_wake(tps_rtc->irq); |
330 | tps->rtc->irqstat); | 323 | return 0; |
331 | } | 324 | } |
325 | #endif | ||
332 | 326 | ||
333 | static const struct dev_pm_ops tps65910_rtc_pm_ops = { | 327 | static const struct dev_pm_ops tps65910_rtc_pm_ops = { |
334 | .suspend = tps65910_rtc_suspend, | 328 | SET_SYSTEM_SLEEP_PM_OPS(tps65910_rtc_suspend, tps65910_rtc_resume) |
335 | .resume = tps65910_rtc_resume, | ||
336 | }; | 329 | }; |
337 | 330 | ||
338 | #define DEV_PM_OPS (&tps65910_rtc_pm_ops) | ||
339 | #else | ||
340 | #define DEV_PM_OPS NULL | ||
341 | #endif | ||
342 | |||
343 | static struct platform_driver tps65910_rtc_driver = { | 331 | static struct platform_driver tps65910_rtc_driver = { |
344 | .probe = tps65910_rtc_probe, | 332 | .probe = tps65910_rtc_probe, |
345 | .remove = tps65910_rtc_remove, | 333 | .remove = tps65910_rtc_remove, |
346 | .driver = { | 334 | .driver = { |
347 | .owner = THIS_MODULE, | 335 | .owner = THIS_MODULE, |
348 | .name = "tps65910-rtc", | 336 | .name = "tps65910-rtc", |
349 | .pm = DEV_PM_OPS, | 337 | .pm = &tps65910_rtc_pm_ops, |
350 | }, | 338 | }, |
351 | }; | 339 | }; |
352 | 340 | ||
diff --git a/drivers/rtc/rtc-tps80031.c b/drivers/rtc/rtc-tps80031.c new file mode 100644 index 000000000000..9aaf8aaebae9 --- /dev/null +++ b/drivers/rtc/rtc-tps80031.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /* | ||
2 | * rtc-tps80031.c -- TI TPS80031/TPS80032 RTC driver | ||
3 | * | ||
4 | * RTC driver for TI TPS80031/TPS80032 Fully Integrated | ||
5 | * Power Management with Power Path and Battery Charger | ||
6 | * | ||
7 | * Copyright (c) 2012, NVIDIA Corporation. | ||
8 | * | ||
9 | * Author: Laxman Dewangan <ldewangan@nvidia.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License as | ||
13 | * published by the Free Software Foundation version 2. | ||
14 | * | ||
15 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, | ||
16 | * whether express or implied; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
23 | * 02111-1307, USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/bcd.h> | ||
27 | #include <linux/device.h> | ||
28 | #include <linux/err.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/mfd/tps80031.h> | ||
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/pm.h> | ||
35 | #include <linux/rtc.h> | ||
36 | #include <linux/slab.h> | ||
37 | |||
38 | #define ENABLE_ALARM_INT 0x08 | ||
39 | #define ALARM_INT_STATUS 0x40 | ||
40 | |||
41 | /** | ||
42 | * Setting bit to 1 in STOP_RTC will run the RTC and | ||
43 | * setting this bit to 0 will freeze RTC. | ||
44 | */ | ||
45 | #define STOP_RTC 0x1 | ||
46 | |||
47 | /* Power on reset Values of RTC registers */ | ||
48 | #define TPS80031_RTC_POR_YEAR 0 | ||
49 | #define TPS80031_RTC_POR_MONTH 1 | ||
50 | #define TPS80031_RTC_POR_DAY 1 | ||
51 | |||
52 | /* Numbers of registers for time and alarms */ | ||
53 | #define TPS80031_RTC_TIME_NUM_REGS 7 | ||
54 | #define TPS80031_RTC_ALARM_NUM_REGS 6 | ||
55 | |||
56 | /** | ||
57 | * PMU RTC have only 2 nibbles to store year information, so using an | ||
58 | * offset of 100 to set the base year as 2000 for our driver. | ||
59 | */ | ||
60 | #define RTC_YEAR_OFFSET 100 | ||
61 | |||
62 | struct tps80031_rtc { | ||
63 | struct rtc_device *rtc; | ||
64 | int irq; | ||
65 | }; | ||
66 | |||
67 | static int tps80031_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
68 | { | ||
69 | u8 buff[TPS80031_RTC_TIME_NUM_REGS]; | ||
70 | int ret; | ||
71 | |||
72 | ret = tps80031_reads(dev->parent, TPS80031_SLAVE_ID1, | ||
73 | TPS80031_SECONDS_REG, TPS80031_RTC_TIME_NUM_REGS, buff); | ||
74 | if (ret < 0) { | ||
75 | dev_err(dev, "reading RTC_SECONDS_REG failed, err = %d\n", ret); | ||
76 | return ret; | ||
77 | } | ||
78 | |||
79 | tm->tm_sec = bcd2bin(buff[0]); | ||
80 | tm->tm_min = bcd2bin(buff[1]); | ||
81 | tm->tm_hour = bcd2bin(buff[2]); | ||
82 | tm->tm_mday = bcd2bin(buff[3]); | ||
83 | tm->tm_mon = bcd2bin(buff[4]) - 1; | ||
84 | tm->tm_year = bcd2bin(buff[5]) + RTC_YEAR_OFFSET; | ||
85 | tm->tm_wday = bcd2bin(buff[6]); | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int tps80031_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
90 | { | ||
91 | u8 buff[7]; | ||
92 | int ret; | ||
93 | |||
94 | buff[0] = bin2bcd(tm->tm_sec); | ||
95 | buff[1] = bin2bcd(tm->tm_min); | ||
96 | buff[2] = bin2bcd(tm->tm_hour); | ||
97 | buff[3] = bin2bcd(tm->tm_mday); | ||
98 | buff[4] = bin2bcd(tm->tm_mon + 1); | ||
99 | buff[5] = bin2bcd(tm->tm_year % RTC_YEAR_OFFSET); | ||
100 | buff[6] = bin2bcd(tm->tm_wday); | ||
101 | |||
102 | /* Stop RTC while updating the RTC time registers */ | ||
103 | ret = tps80031_clr_bits(dev->parent, TPS80031_SLAVE_ID1, | ||
104 | TPS80031_RTC_CTRL_REG, STOP_RTC); | ||
105 | if (ret < 0) { | ||
106 | dev_err(dev->parent, "Stop RTC failed, err = %d\n", ret); | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | ret = tps80031_writes(dev->parent, TPS80031_SLAVE_ID1, | ||
111 | TPS80031_SECONDS_REG, | ||
112 | TPS80031_RTC_TIME_NUM_REGS, buff); | ||
113 | if (ret < 0) { | ||
114 | dev_err(dev, "writing RTC_SECONDS_REG failed, err %d\n", ret); | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1, | ||
119 | TPS80031_RTC_CTRL_REG, STOP_RTC); | ||
120 | if (ret < 0) | ||
121 | dev_err(dev->parent, "Start RTC failed, err = %d\n", ret); | ||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static int tps80031_rtc_alarm_irq_enable(struct device *dev, | ||
126 | unsigned int enable) | ||
127 | { | ||
128 | int ret; | ||
129 | |||
130 | if (enable) | ||
131 | ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1, | ||
132 | TPS80031_RTC_INTERRUPTS_REG, ENABLE_ALARM_INT); | ||
133 | else | ||
134 | ret = tps80031_clr_bits(dev->parent, TPS80031_SLAVE_ID1, | ||
135 | TPS80031_RTC_INTERRUPTS_REG, ENABLE_ALARM_INT); | ||
136 | if (ret < 0) { | ||
137 | dev_err(dev, "Update on RTC_INT failed, err = %d\n", ret); | ||
138 | return ret; | ||
139 | } | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static int tps80031_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
144 | { | ||
145 | u8 buff[TPS80031_RTC_ALARM_NUM_REGS]; | ||
146 | int ret; | ||
147 | |||
148 | buff[0] = bin2bcd(alrm->time.tm_sec); | ||
149 | buff[1] = bin2bcd(alrm->time.tm_min); | ||
150 | buff[2] = bin2bcd(alrm->time.tm_hour); | ||
151 | buff[3] = bin2bcd(alrm->time.tm_mday); | ||
152 | buff[4] = bin2bcd(alrm->time.tm_mon + 1); | ||
153 | buff[5] = bin2bcd(alrm->time.tm_year % RTC_YEAR_OFFSET); | ||
154 | ret = tps80031_writes(dev->parent, TPS80031_SLAVE_ID1, | ||
155 | TPS80031_ALARM_SECONDS_REG, | ||
156 | TPS80031_RTC_ALARM_NUM_REGS, buff); | ||
157 | if (ret < 0) { | ||
158 | dev_err(dev, "Writing RTC_ALARM failed, err %d\n", ret); | ||
159 | return ret; | ||
160 | } | ||
161 | return tps80031_rtc_alarm_irq_enable(dev, alrm->enabled); | ||
162 | } | ||
163 | |||
164 | static int tps80031_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
165 | { | ||
166 | u8 buff[6]; | ||
167 | int ret; | ||
168 | |||
169 | ret = tps80031_reads(dev->parent, TPS80031_SLAVE_ID1, | ||
170 | TPS80031_ALARM_SECONDS_REG, | ||
171 | TPS80031_RTC_ALARM_NUM_REGS, buff); | ||
172 | if (ret < 0) { | ||
173 | dev_err(dev->parent, | ||
174 | "reading RTC_ALARM failed, err = %d\n", ret); | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | alrm->time.tm_sec = bcd2bin(buff[0]); | ||
179 | alrm->time.tm_min = bcd2bin(buff[1]); | ||
180 | alrm->time.tm_hour = bcd2bin(buff[2]); | ||
181 | alrm->time.tm_mday = bcd2bin(buff[3]); | ||
182 | alrm->time.tm_mon = bcd2bin(buff[4]) - 1; | ||
183 | alrm->time.tm_year = bcd2bin(buff[5]) + RTC_YEAR_OFFSET; | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static int clear_alarm_int_status(struct device *dev, struct tps80031_rtc *rtc) | ||
188 | { | ||
189 | int ret; | ||
190 | u8 buf; | ||
191 | |||
192 | /** | ||
193 | * As per datasheet, A dummy read of this RTC_STATUS_REG register | ||
194 | * is necessary before each I2C read in order to update the status | ||
195 | * register value. | ||
196 | */ | ||
197 | ret = tps80031_read(dev->parent, TPS80031_SLAVE_ID1, | ||
198 | TPS80031_RTC_STATUS_REG, &buf); | ||
199 | if (ret < 0) { | ||
200 | dev_err(dev, "reading RTC_STATUS failed. err = %d\n", ret); | ||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | /* clear Alarm status bits.*/ | ||
205 | ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1, | ||
206 | TPS80031_RTC_STATUS_REG, ALARM_INT_STATUS); | ||
207 | if (ret < 0) { | ||
208 | dev_err(dev, "clear Alarm INT failed, err = %d\n", ret); | ||
209 | return ret; | ||
210 | } | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static irqreturn_t tps80031_rtc_irq(int irq, void *data) | ||
215 | { | ||
216 | struct device *dev = data; | ||
217 | struct tps80031_rtc *rtc = dev_get_drvdata(dev); | ||
218 | int ret; | ||
219 | |||
220 | ret = clear_alarm_int_status(dev, rtc); | ||
221 | if (ret < 0) | ||
222 | return ret; | ||
223 | |||
224 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
225 | return IRQ_HANDLED; | ||
226 | } | ||
227 | |||
228 | static const struct rtc_class_ops tps80031_rtc_ops = { | ||
229 | .read_time = tps80031_rtc_read_time, | ||
230 | .set_time = tps80031_rtc_set_time, | ||
231 | .set_alarm = tps80031_rtc_set_alarm, | ||
232 | .read_alarm = tps80031_rtc_read_alarm, | ||
233 | .alarm_irq_enable = tps80031_rtc_alarm_irq_enable, | ||
234 | }; | ||
235 | |||
236 | static int tps80031_rtc_probe(struct platform_device *pdev) | ||
237 | { | ||
238 | struct tps80031_rtc *rtc; | ||
239 | struct rtc_time tm; | ||
240 | int ret; | ||
241 | |||
242 | rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); | ||
243 | if (!rtc) | ||
244 | return -ENOMEM; | ||
245 | |||
246 | rtc->irq = platform_get_irq(pdev, 0); | ||
247 | platform_set_drvdata(pdev, rtc); | ||
248 | |||
249 | /* Start RTC */ | ||
250 | ret = tps80031_set_bits(pdev->dev.parent, TPS80031_SLAVE_ID1, | ||
251 | TPS80031_RTC_CTRL_REG, STOP_RTC); | ||
252 | if (ret < 0) { | ||
253 | dev_err(&pdev->dev, "failed to start RTC. err = %d\n", ret); | ||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | /* If RTC have POR values, set time 01:01:2000 */ | ||
258 | tps80031_rtc_read_time(&pdev->dev, &tm); | ||
259 | if ((tm.tm_year == RTC_YEAR_OFFSET + TPS80031_RTC_POR_YEAR) && | ||
260 | (tm.tm_mon == (TPS80031_RTC_POR_MONTH - 1)) && | ||
261 | (tm.tm_mday == TPS80031_RTC_POR_DAY)) { | ||
262 | tm.tm_year = 2000; | ||
263 | tm.tm_mday = 1; | ||
264 | tm.tm_mon = 1; | ||
265 | ret = tps80031_rtc_set_time(&pdev->dev, &tm); | ||
266 | if (ret < 0) { | ||
267 | dev_err(&pdev->dev, | ||
268 | "RTC set time failed, err = %d\n", ret); | ||
269 | return ret; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | /* Clear alarm intretupt status if it is there */ | ||
274 | ret = clear_alarm_int_status(&pdev->dev, rtc); | ||
275 | if (ret < 0) { | ||
276 | dev_err(&pdev->dev, "Clear alarm int failed, err = %d\n", ret); | ||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
281 | &tps80031_rtc_ops, THIS_MODULE); | ||
282 | if (IS_ERR(rtc->rtc)) { | ||
283 | ret = PTR_ERR(rtc->rtc); | ||
284 | dev_err(&pdev->dev, "RTC registration failed, err %d\n", ret); | ||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, | ||
289 | tps80031_rtc_irq, | ||
290 | IRQF_ONESHOT | IRQF_EARLY_RESUME, | ||
291 | dev_name(&pdev->dev), rtc); | ||
292 | if (ret < 0) { | ||
293 | dev_err(&pdev->dev, "request IRQ:%d failed, err = %d\n", | ||
294 | rtc->irq, ret); | ||
295 | rtc_device_unregister(rtc->rtc); | ||
296 | return ret; | ||
297 | } | ||
298 | device_set_wakeup_capable(&pdev->dev, 1); | ||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static int tps80031_rtc_remove(struct platform_device *pdev) | ||
303 | { | ||
304 | struct tps80031_rtc *rtc = platform_get_drvdata(pdev); | ||
305 | |||
306 | rtc_device_unregister(rtc->rtc); | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | #ifdef CONFIG_PM_SLEEP | ||
311 | static int tps80031_rtc_suspend(struct device *dev) | ||
312 | { | ||
313 | struct tps80031_rtc *rtc = dev_get_drvdata(dev); | ||
314 | |||
315 | if (device_may_wakeup(dev)) | ||
316 | enable_irq_wake(rtc->irq); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | static int tps80031_rtc_resume(struct device *dev) | ||
321 | { | ||
322 | struct tps80031_rtc *rtc = dev_get_drvdata(dev); | ||
323 | |||
324 | if (device_may_wakeup(dev)) | ||
325 | disable_irq_wake(rtc->irq); | ||
326 | return 0; | ||
327 | }; | ||
328 | #endif | ||
329 | |||
330 | static const struct dev_pm_ops tps80031_pm_ops = { | ||
331 | SET_SYSTEM_SLEEP_PM_OPS(tps80031_rtc_suspend, tps80031_rtc_resume) | ||
332 | }; | ||
333 | |||
334 | static struct platform_driver tps80031_rtc_driver = { | ||
335 | .driver = { | ||
336 | .name = "tps80031-rtc", | ||
337 | .owner = THIS_MODULE, | ||
338 | .pm = &tps80031_pm_ops, | ||
339 | }, | ||
340 | .probe = tps80031_rtc_probe, | ||
341 | .remove = tps80031_rtc_remove, | ||
342 | }; | ||
343 | |||
344 | module_platform_driver(tps80031_rtc_driver); | ||
345 | |||
346 | MODULE_ALIAS("platform:tps80031-rtc"); | ||
347 | MODULE_DESCRIPTION("TI TPS80031/TPS80032 RTC driver"); | ||
348 | MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); | ||
349 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index ccd4ad370b32..8bc6c80b184c 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/bcd.h> | 27 | #include <linux/bcd.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/of.h> | ||
30 | 31 | ||
31 | #include <linux/i2c/twl.h> | 32 | #include <linux/i2c/twl.h> |
32 | 33 | ||
@@ -588,11 +589,14 @@ static int twl_rtc_resume(struct platform_device *pdev) | |||
588 | #define twl_rtc_resume NULL | 589 | #define twl_rtc_resume NULL |
589 | #endif | 590 | #endif |
590 | 591 | ||
592 | #ifdef CONFIG_OF | ||
591 | static const struct of_device_id twl_rtc_of_match[] = { | 593 | static const struct of_device_id twl_rtc_of_match[] = { |
592 | {.compatible = "ti,twl4030-rtc", }, | 594 | {.compatible = "ti,twl4030-rtc", }, |
593 | { }, | 595 | { }, |
594 | }; | 596 | }; |
595 | MODULE_DEVICE_TABLE(of, twl_rtc_of_match); | 597 | MODULE_DEVICE_TABLE(of, twl_rtc_of_match); |
598 | #endif | ||
599 | |||
596 | MODULE_ALIAS("platform:twl_rtc"); | 600 | MODULE_ALIAS("platform:twl_rtc"); |
597 | 601 | ||
598 | static struct platform_driver twl4030rtc_driver = { | 602 | static struct platform_driver twl4030rtc_driver = { |
@@ -604,7 +608,7 @@ static struct platform_driver twl4030rtc_driver = { | |||
604 | .driver = { | 608 | .driver = { |
605 | .owner = THIS_MODULE, | 609 | .owner = THIS_MODULE, |
606 | .name = "twl_rtc", | 610 | .name = "twl_rtc", |
607 | .of_match_table = twl_rtc_of_match, | 611 | .of_match_table = of_match_ptr(twl_rtc_of_match), |
608 | }, | 612 | }, |
609 | }; | 613 | }; |
610 | 614 | ||
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index 6c3774cf5a24..f91be04b9050 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
@@ -352,7 +352,7 @@ static int rtc_probe(struct platform_device *pdev) | |||
352 | disable_irq(aie_irq); | 352 | disable_irq(aie_irq); |
353 | disable_irq(pie_irq); | 353 | disable_irq(pie_irq); |
354 | 354 | ||
355 | printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n"); | 355 | dev_info(&pdev->dev, "Real Time Clock of NEC VR4100 series\n"); |
356 | 356 | ||
357 | return 0; | 357 | return 0; |
358 | 358 | ||
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index 2730533e2d2d..a000bc0a8bff 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c | |||
@@ -231,20 +231,21 @@ static int vt8500_rtc_probe(struct platform_device *pdev) | |||
231 | return -ENXIO; | 231 | return -ENXIO; |
232 | } | 232 | } |
233 | 233 | ||
234 | vt8500_rtc->res = request_mem_region(vt8500_rtc->res->start, | 234 | vt8500_rtc->res = devm_request_mem_region(&pdev->dev, |
235 | resource_size(vt8500_rtc->res), | 235 | vt8500_rtc->res->start, |
236 | "vt8500-rtc"); | 236 | resource_size(vt8500_rtc->res), |
237 | "vt8500-rtc"); | ||
237 | if (vt8500_rtc->res == NULL) { | 238 | if (vt8500_rtc->res == NULL) { |
238 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | 239 | dev_err(&pdev->dev, "failed to request I/O memory\n"); |
239 | return -EBUSY; | 240 | return -EBUSY; |
240 | } | 241 | } |
241 | 242 | ||
242 | vt8500_rtc->regbase = ioremap(vt8500_rtc->res->start, | 243 | vt8500_rtc->regbase = devm_ioremap(&pdev->dev, vt8500_rtc->res->start, |
243 | resource_size(vt8500_rtc->res)); | 244 | resource_size(vt8500_rtc->res)); |
244 | if (!vt8500_rtc->regbase) { | 245 | if (!vt8500_rtc->regbase) { |
245 | dev_err(&pdev->dev, "Unable to map RTC I/O memory\n"); | 246 | dev_err(&pdev->dev, "Unable to map RTC I/O memory\n"); |
246 | ret = -EBUSY; | 247 | ret = -EBUSY; |
247 | goto err_release; | 248 | goto err_return; |
248 | } | 249 | } |
249 | 250 | ||
250 | /* Enable RTC and set it to 24-hour mode */ | 251 | /* Enable RTC and set it to 24-hour mode */ |
@@ -257,11 +258,11 @@ static int vt8500_rtc_probe(struct platform_device *pdev) | |||
257 | ret = PTR_ERR(vt8500_rtc->rtc); | 258 | ret = PTR_ERR(vt8500_rtc->rtc); |
258 | dev_err(&pdev->dev, | 259 | dev_err(&pdev->dev, |
259 | "Failed to register RTC device -> %d\n", ret); | 260 | "Failed to register RTC device -> %d\n", ret); |
260 | goto err_unmap; | 261 | goto err_return; |
261 | } | 262 | } |
262 | 263 | ||
263 | ret = request_irq(vt8500_rtc->irq_alarm, vt8500_rtc_irq, 0, | 264 | ret = devm_request_irq(&pdev->dev, vt8500_rtc->irq_alarm, |
264 | "rtc alarm", vt8500_rtc); | 265 | vt8500_rtc_irq, 0, "rtc alarm", vt8500_rtc); |
265 | if (ret < 0) { | 266 | if (ret < 0) { |
266 | dev_err(&pdev->dev, "can't get irq %i, err %d\n", | 267 | dev_err(&pdev->dev, "can't get irq %i, err %d\n", |
267 | vt8500_rtc->irq_alarm, ret); | 268 | vt8500_rtc->irq_alarm, ret); |
@@ -272,11 +273,7 @@ static int vt8500_rtc_probe(struct platform_device *pdev) | |||
272 | 273 | ||
273 | err_unreg: | 274 | err_unreg: |
274 | rtc_device_unregister(vt8500_rtc->rtc); | 275 | rtc_device_unregister(vt8500_rtc->rtc); |
275 | err_unmap: | 276 | err_return: |
276 | iounmap(vt8500_rtc->regbase); | ||
277 | err_release: | ||
278 | release_mem_region(vt8500_rtc->res->start, | ||
279 | resource_size(vt8500_rtc->res)); | ||
280 | return ret; | 277 | return ret; |
281 | } | 278 | } |
282 | 279 | ||
@@ -284,15 +281,10 @@ static int vt8500_rtc_remove(struct platform_device *pdev) | |||
284 | { | 281 | { |
285 | struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev); | 282 | struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev); |
286 | 283 | ||
287 | free_irq(vt8500_rtc->irq_alarm, vt8500_rtc); | ||
288 | |||
289 | rtc_device_unregister(vt8500_rtc->rtc); | 284 | rtc_device_unregister(vt8500_rtc->rtc); |
290 | 285 | ||
291 | /* Disable alarm matching */ | 286 | /* Disable alarm matching */ |
292 | writel(0, vt8500_rtc->regbase + VT8500_RTC_IS); | 287 | writel(0, vt8500_rtc->regbase + VT8500_RTC_IS); |
293 | iounmap(vt8500_rtc->regbase); | ||
294 | release_mem_region(vt8500_rtc->res->start, | ||
295 | resource_size(vt8500_rtc->res)); | ||
296 | 288 | ||
297 | platform_set_drvdata(pdev, NULL); | 289 | platform_set_drvdata(pdev, NULL); |
298 | 290 | ||
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 1b0affbe2659..2f0ac7b30a0c 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c | |||
@@ -443,9 +443,10 @@ static int wm831x_rtc_probe(struct platform_device *pdev) | |||
443 | goto err; | 443 | goto err; |
444 | } | 444 | } |
445 | 445 | ||
446 | ret = request_threaded_irq(alm_irq, NULL, wm831x_alm_irq, | 446 | ret = devm_request_threaded_irq(&pdev->dev, alm_irq, NULL, |
447 | IRQF_TRIGGER_RISING, "RTC alarm", | 447 | wm831x_alm_irq, |
448 | wm831x_rtc); | 448 | IRQF_TRIGGER_RISING, "RTC alarm", |
449 | wm831x_rtc); | ||
449 | if (ret != 0) { | 450 | if (ret != 0) { |
450 | dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", | 451 | dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", |
451 | alm_irq, ret); | 452 | alm_irq, ret); |
@@ -462,9 +463,7 @@ err: | |||
462 | static int wm831x_rtc_remove(struct platform_device *pdev) | 463 | static int wm831x_rtc_remove(struct platform_device *pdev) |
463 | { | 464 | { |
464 | struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev); | 465 | struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev); |
465 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); | ||
466 | 466 | ||
467 | free_irq(alm_irq, wm831x_rtc); | ||
468 | rtc_device_unregister(wm831x_rtc->rtc); | 467 | rtc_device_unregister(wm831x_rtc->rtc); |
469 | 468 | ||
470 | return 0; | 469 | return 0; |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e4e1765b82f2..80cbd21b483f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -364,7 +364,7 @@ config FB_SA1100 | |||
364 | Y here. | 364 | Y here. |
365 | 365 | ||
366 | config FB_IMX | 366 | config FB_IMX |
367 | tristate "Freescale i.MX LCD support" | 367 | tristate "Freescale i.MX1/21/25/27 LCD support" |
368 | depends on FB && IMX_HAVE_PLATFORM_IMX_FB | 368 | depends on FB && IMX_HAVE_PLATFORM_IMX_FB |
369 | select FB_CFB_FILLRECT | 369 | select FB_CFB_FILLRECT |
370 | select FB_CFB_COPYAREA | 370 | select FB_CFB_COPYAREA |
@@ -2025,7 +2025,8 @@ config FB_TMIO_ACCELL | |||
2025 | 2025 | ||
2026 | config FB_S3C | 2026 | config FB_S3C |
2027 | tristate "Samsung S3C framebuffer support" | 2027 | tristate "Samsung S3C framebuffer support" |
2028 | depends on FB && (S3C_DEV_FB || S5P_DEV_FIMD0) | 2028 | depends on FB && (CPU_S3C2416 || ARCH_S3C64XX || ARCH_S5P64X0 || \ |
2029 | ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) | ||
2029 | select FB_CFB_FILLRECT | 2030 | select FB_CFB_FILLRECT |
2030 | select FB_CFB_COPYAREA | 2031 | select FB_CFB_COPYAREA |
2031 | select FB_CFB_IMAGEBLIT | 2032 | select FB_CFB_IMAGEBLIT |
@@ -2183,6 +2184,15 @@ config FB_XILINX | |||
2183 | framebuffer. ML300 carries a 640*480 LCD display on the board, | 2184 | framebuffer. ML300 carries a 640*480 LCD display on the board, |
2184 | ML403 uses a standard DB15 VGA connector. | 2185 | ML403 uses a standard DB15 VGA connector. |
2185 | 2186 | ||
2187 | config FB_GOLDFISH | ||
2188 | tristate "Goldfish Framebuffer" | ||
2189 | depends on FB | ||
2190 | select FB_CFB_FILLRECT | ||
2191 | select FB_CFB_COPYAREA | ||
2192 | select FB_CFB_IMAGEBLIT | ||
2193 | ---help--- | ||
2194 | Framebuffer driver for Goldfish Virtual Platform | ||
2195 | |||
2186 | config FB_COBALT | 2196 | config FB_COBALT |
2187 | tristate "Cobalt server LCD frame buffer support" | 2197 | tristate "Cobalt server LCD frame buffer support" |
2188 | depends on FB && (MIPS_COBALT || MIPS_SEAD3) | 2198 | depends on FB && (MIPS_COBALT || MIPS_SEAD3) |
@@ -2422,6 +2432,7 @@ config FB_PUV3_UNIGFX | |||
2422 | source "drivers/video/omap/Kconfig" | 2432 | source "drivers/video/omap/Kconfig" |
2423 | source "drivers/video/omap2/Kconfig" | 2433 | source "drivers/video/omap2/Kconfig" |
2424 | source "drivers/video/exynos/Kconfig" | 2434 | source "drivers/video/exynos/Kconfig" |
2435 | source "drivers/video/mmp/Kconfig" | ||
2425 | source "drivers/video/backlight/Kconfig" | 2436 | source "drivers/video/backlight/Kconfig" |
2426 | 2437 | ||
2427 | if VT | 2438 | if VT |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 768a137a1bac..0577f834fdcd 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -98,6 +98,7 @@ obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o | |||
98 | obj-$(CONFIG_FB_PVR2) += pvr2fb.o | 98 | obj-$(CONFIG_FB_PVR2) += pvr2fb.o |
99 | obj-$(CONFIG_FB_VOODOO1) += sstfb.o | 99 | obj-$(CONFIG_FB_VOODOO1) += sstfb.o |
100 | obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o | 100 | obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o |
101 | obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o | ||
101 | obj-$(CONFIG_FB_68328) += 68328fb.o | 102 | obj-$(CONFIG_FB_68328) += 68328fb.o |
102 | obj-$(CONFIG_FB_GBE) += gbefb.o | 103 | obj-$(CONFIG_FB_GBE) += gbefb.o |
103 | obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o | 104 | obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o |
@@ -105,6 +106,7 @@ obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o | |||
105 | obj-$(CONFIG_FB_PXA) += pxafb.o | 106 | obj-$(CONFIG_FB_PXA) += pxafb.o |
106 | obj-$(CONFIG_FB_PXA168) += pxa168fb.o | 107 | obj-$(CONFIG_FB_PXA168) += pxa168fb.o |
107 | obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o | 108 | obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o |
109 | obj-$(CONFIG_MMP_DISP) += mmp/ | ||
108 | obj-$(CONFIG_FB_W100) += w100fb.o | 110 | obj-$(CONFIG_FB_W100) += w100fb.o |
109 | obj-$(CONFIG_FB_TMIO) += tmiofb.o | 111 | obj-$(CONFIG_FB_TMIO) += tmiofb.o |
110 | obj-$(CONFIG_FB_AU1100) += au1100fb.o | 112 | obj-$(CONFIG_FB_AU1100) += au1100fb.o |
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index c072ed9aea36..2cd63507ed74 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c | |||
@@ -165,8 +165,10 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev, | |||
165 | struct pm860x_backlight_data *data, | 165 | struct pm860x_backlight_data *data, |
166 | char *name) | 166 | char *name) |
167 | { | 167 | { |
168 | struct device_node *nproot = pdev->dev.parent->of_node, *np; | 168 | struct device_node *nproot, *np; |
169 | int iset = 0; | 169 | int iset = 0; |
170 | |||
171 | nproot = of_node_get(pdev->dev.parent->of_node); | ||
170 | if (!nproot) | 172 | if (!nproot) |
171 | return -ENODEV; | 173 | return -ENODEV; |
172 | nproot = of_find_node_by_name(nproot, "backlights"); | 174 | nproot = of_find_node_by_name(nproot, "backlights"); |
@@ -184,6 +186,7 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev, | |||
184 | break; | 186 | break; |
185 | } | 187 | } |
186 | } | 188 | } |
189 | of_node_put(nproot); | ||
187 | return 0; | 190 | return 0; |
188 | } | 191 | } |
189 | #else | 192 | #else |
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 765a945f8ea1..be27b551473f 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
@@ -126,6 +126,21 @@ config LCD_AMS369FG06 | |||
126 | If you have an AMS369FG06 AMOLED Panel, say Y to enable its | 126 | If you have an AMS369FG06 AMOLED Panel, say Y to enable its |
127 | LCD control driver. | 127 | LCD control driver. |
128 | 128 | ||
129 | config LCD_LMS501KF03 | ||
130 | tristate "LMS501KF03 LCD Driver" | ||
131 | depends on SPI | ||
132 | default n | ||
133 | help | ||
134 | If you have an LMS501KF03 LCD Panel, say Y to enable its | ||
135 | LCD control driver. | ||
136 | |||
137 | config LCD_HX8357 | ||
138 | tristate "Himax HX-8357 LCD Driver" | ||
139 | depends on SPI | ||
140 | help | ||
141 | If you have a HX-8357 LCD panel, say Y to enable its LCD control | ||
142 | driver. | ||
143 | |||
129 | endif # LCD_CLASS_DEVICE | 144 | endif # LCD_CLASS_DEVICE |
130 | 145 | ||
131 | # | 146 | # |
@@ -366,7 +381,7 @@ config BACKLIGHT_LP855X | |||
366 | tristate "Backlight driver for TI LP855X" | 381 | tristate "Backlight driver for TI LP855X" |
367 | depends on BACKLIGHT_CLASS_DEVICE && I2C | 382 | depends on BACKLIGHT_CLASS_DEVICE && I2C |
368 | help | 383 | help |
369 | This supports TI LP8550, LP8551, LP8552, LP8553 and LP8556 | 384 | This supports TI LP8550, LP8551, LP8552, LP8553, LP8556 and LP8557 |
370 | backlight driver. | 385 | backlight driver. |
371 | 386 | ||
372 | config BACKLIGHT_OT200 | 387 | config BACKLIGHT_OT200 |
@@ -390,6 +405,13 @@ config BACKLIGHT_TPS65217 | |||
390 | If you have a Texas Instruments TPS65217 say Y to enable the | 405 | If you have a Texas Instruments TPS65217 say Y to enable the |
391 | backlight driver. | 406 | backlight driver. |
392 | 407 | ||
408 | config BACKLIGHT_AS3711 | ||
409 | tristate "AS3711 Backlight" | ||
410 | depends on BACKLIGHT_CLASS_DEVICE && MFD_AS3711 | ||
411 | help | ||
412 | If you have an Austrian Microsystems AS3711 say Y to enable the | ||
413 | backlight driver. | ||
414 | |||
393 | endif # BACKLIGHT_CLASS_DEVICE | 415 | endif # BACKLIGHT_CLASS_DEVICE |
394 | 416 | ||
395 | endif # BACKLIGHT_LCD_SUPPORT | 417 | endif # BACKLIGHT_LCD_SUPPORT |
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index e7ce7291635d..4606c218e8e4 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile | |||
@@ -1,47 +1,50 @@ | |||
1 | # Backlight & LCD drivers | 1 | # Backlight & LCD drivers |
2 | 2 | ||
3 | obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o | 3 | obj-$(CONFIG_LCD_AMS369FG06) += ams369fg06.o |
4 | obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o | 4 | obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o |
5 | obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o | 5 | obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o |
6 | obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o | 6 | obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o |
7 | obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o | 7 | obj-$(CONFIG_LCD_HX8357) += hx8357.o |
8 | obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o | 8 | obj-$(CONFIG_LCD_ILI9320) += ili9320.o |
9 | obj-$(CONFIG_LCD_ILI9320) += ili9320.o | 9 | obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o |
10 | obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o | 10 | obj-$(CONFIG_LCD_LD9040) += ld9040.o |
11 | obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o | 11 | obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o |
12 | obj-$(CONFIG_LCD_TDO24M) += tdo24m.o | 12 | obj-$(CONFIG_LCD_LMS501KF03) += lms501kf03.o |
13 | obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o | 13 | obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o |
14 | obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o | 14 | obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o |
15 | obj-$(CONFIG_LCD_LD9040) += ld9040.o | 15 | obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o |
16 | obj-$(CONFIG_LCD_AMS369FG06) += ams369fg06.o | 16 | obj-$(CONFIG_LCD_TDO24M) += tdo24m.o |
17 | obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o | ||
18 | obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o | ||
17 | 19 | ||
18 | obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o | 20 | obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o |
19 | obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o | 21 | obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o |
20 | obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o | 22 | obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o |
21 | obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o | 23 | obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o |
22 | obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o | 24 | obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o |
23 | obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o | 25 | obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o |
24 | obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o | 26 | obj-$(CONFIG_BACKLIGHT_AS3711) += as3711_bl.o |
25 | obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o | 27 | obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o |
26 | obj-$(CONFIG_BACKLIGHT_LM3630) += lm3630_bl.o | 28 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o |
27 | obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o | 29 | obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o |
28 | obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o | 30 | obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o |
29 | obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o | 31 | obj-$(CONFIG_BACKLIGHT_DA9052) += da9052_bl.o |
30 | obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o | 32 | obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o |
31 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o | 33 | obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o |
32 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o | 34 | obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o |
33 | obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o | 35 | obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o |
34 | obj-$(CONFIG_BACKLIGHT_DA9052) += da9052_bl.o | 36 | obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o |
35 | obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o | 37 | obj-$(CONFIG_BACKLIGHT_LM3630) += lm3630_bl.o |
36 | obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o | 38 | obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o |
37 | obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o | 39 | obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o |
38 | obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o | 40 | obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o |
39 | obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o | 41 | obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o |
40 | obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o | 42 | obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o |
41 | obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o | 43 | obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o |
42 | obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o | 44 | obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o |
43 | obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o | ||
44 | obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o | 45 | obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o |
45 | obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o | 46 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o |
46 | obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o | 47 | obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o |
47 | obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o | 48 | obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o |
49 | obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o | ||
50 | obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o | ||
diff --git a/drivers/video/backlight/aat2870_bl.c b/drivers/video/backlight/aat2870_bl.c index 7ff752288b92..c6fc668d6236 100644 --- a/drivers/video/backlight/aat2870_bl.c +++ b/drivers/video/backlight/aat2870_bl.c | |||
@@ -74,7 +74,7 @@ static int aat2870_bl_get_brightness(struct backlight_device *bd) | |||
74 | 74 | ||
75 | static int aat2870_bl_update_status(struct backlight_device *bd) | 75 | static int aat2870_bl_update_status(struct backlight_device *bd) |
76 | { | 76 | { |
77 | struct aat2870_bl_driver_data *aat2870_bl = dev_get_drvdata(&bd->dev); | 77 | struct aat2870_bl_driver_data *aat2870_bl = bl_get_data(bd); |
78 | struct aat2870_data *aat2870 = | 78 | struct aat2870_data *aat2870 = |
79 | dev_get_drvdata(aat2870_bl->pdev->dev.parent); | 79 | dev_get_drvdata(aat2870_bl->pdev->dev.parent); |
80 | int brightness = bd->props.brightness; | 80 | int brightness = bd->props.brightness; |
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index 6bb72c0cb803..a77c9cad3320 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c | |||
@@ -783,7 +783,7 @@ static int adp8860_i2c_suspend(struct i2c_client *client, pm_message_t message) | |||
783 | 783 | ||
784 | static int adp8860_i2c_resume(struct i2c_client *client) | 784 | static int adp8860_i2c_resume(struct i2c_client *client) |
785 | { | 785 | { |
786 | adp8860_set_bits(client, ADP8860_MDCR, NSTBY); | 786 | adp8860_set_bits(client, ADP8860_MDCR, NSTBY | BLEN); |
787 | 787 | ||
788 | return 0; | 788 | return 0; |
789 | } | 789 | } |
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index 63c882b8177a..712c25a0d8fe 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c | |||
@@ -957,7 +957,7 @@ static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message) | |||
957 | 957 | ||
958 | static int adp8870_i2c_resume(struct i2c_client *client) | 958 | static int adp8870_i2c_resume(struct i2c_client *client) |
959 | { | 959 | { |
960 | adp8870_set_bits(client, ADP8870_MDCR, NSTBY); | 960 | adp8870_set_bits(client, ADP8870_MDCR, NSTBY | BLEN); |
961 | 961 | ||
962 | return 0; | 962 | return 0; |
963 | } | 963 | } |
diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c index f57e1905236a..d29e49443f29 100644 --- a/drivers/video/backlight/ams369fg06.c +++ b/drivers/video/backlight/ams369fg06.c | |||
@@ -10,25 +10,16 @@ | |||
10 | * under the terms of the GNU General Public License as published by the | 10 | * under the terms of the GNU General Public License as published by the |
11 | * Free Software Foundation; either version 2 of the License, or (at your | 11 | * Free Software Foundation; either version 2 of the License, or (at your |
12 | * option) any later version. | 12 | * option) any later version. |
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | */ | 13 | */ |
23 | 14 | ||
24 | #include <linux/wait.h> | 15 | #include <linux/backlight.h> |
25 | #include <linux/module.h> | ||
26 | #include <linux/fb.h> | ||
27 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/fb.h> | ||
28 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
29 | #include <linux/spi/spi.h> | ||
30 | #include <linux/lcd.h> | 19 | #include <linux/lcd.h> |
31 | #include <linux/backlight.h> | 20 | #include <linux/module.h> |
21 | #include <linux/spi/spi.h> | ||
22 | #include <linux/wait.h> | ||
32 | 23 | ||
33 | #define SLEEPMSEC 0x1000 | 24 | #define SLEEPMSEC 0x1000 |
34 | #define ENDDEF 0x2000 | 25 | #define ENDDEF 0x2000 |
@@ -210,8 +201,9 @@ static int ams369fg06_panel_send_sequence(struct ams369fg06 *lcd, | |||
210 | ret = ams369fg06_spi_write(lcd, wbuf[i], wbuf[i+1]); | 201 | ret = ams369fg06_spi_write(lcd, wbuf[i], wbuf[i+1]); |
211 | if (ret) | 202 | if (ret) |
212 | break; | 203 | break; |
213 | } else | 204 | } else { |
214 | mdelay(wbuf[i+1]); | 205 | msleep(wbuf[i+1]); |
206 | } | ||
215 | i += 2; | 207 | i += 2; |
216 | } | 208 | } |
217 | 209 | ||
@@ -313,41 +305,32 @@ static int ams369fg06_ldi_disable(struct ams369fg06 *lcd) | |||
313 | 305 | ||
314 | static int ams369fg06_power_is_on(int power) | 306 | static int ams369fg06_power_is_on(int power) |
315 | { | 307 | { |
316 | return ((power) <= FB_BLANK_NORMAL); | 308 | return power <= FB_BLANK_NORMAL; |
317 | } | 309 | } |
318 | 310 | ||
319 | static int ams369fg06_power_on(struct ams369fg06 *lcd) | 311 | static int ams369fg06_power_on(struct ams369fg06 *lcd) |
320 | { | 312 | { |
321 | int ret = 0; | 313 | int ret = 0; |
322 | struct lcd_platform_data *pd = NULL; | 314 | struct lcd_platform_data *pd; |
323 | struct backlight_device *bd = NULL; | 315 | struct backlight_device *bd; |
324 | 316 | ||
325 | pd = lcd->lcd_pd; | 317 | pd = lcd->lcd_pd; |
326 | if (!pd) { | ||
327 | dev_err(lcd->dev, "platform data is NULL.\n"); | ||
328 | return -EFAULT; | ||
329 | } | ||
330 | |||
331 | bd = lcd->bd; | 318 | bd = lcd->bd; |
332 | if (!bd) { | ||
333 | dev_err(lcd->dev, "backlight device is NULL.\n"); | ||
334 | return -EFAULT; | ||
335 | } | ||
336 | 319 | ||
337 | if (!pd->power_on) { | 320 | if (!pd->power_on) { |
338 | dev_err(lcd->dev, "power_on is NULL.\n"); | 321 | dev_err(lcd->dev, "power_on is NULL.\n"); |
339 | return -EFAULT; | 322 | return -EINVAL; |
340 | } else { | 323 | } else { |
341 | pd->power_on(lcd->ld, 1); | 324 | pd->power_on(lcd->ld, 1); |
342 | mdelay(pd->power_on_delay); | 325 | msleep(pd->power_on_delay); |
343 | } | 326 | } |
344 | 327 | ||
345 | if (!pd->reset) { | 328 | if (!pd->reset) { |
346 | dev_err(lcd->dev, "reset is NULL.\n"); | 329 | dev_err(lcd->dev, "reset is NULL.\n"); |
347 | return -EFAULT; | 330 | return -EINVAL; |
348 | } else { | 331 | } else { |
349 | pd->reset(lcd->ld); | 332 | pd->reset(lcd->ld); |
350 | mdelay(pd->reset_delay); | 333 | msleep(pd->reset_delay); |
351 | } | 334 | } |
352 | 335 | ||
353 | ret = ams369fg06_ldi_init(lcd); | 336 | ret = ams369fg06_ldi_init(lcd); |
@@ -374,14 +357,10 @@ static int ams369fg06_power_on(struct ams369fg06 *lcd) | |||
374 | 357 | ||
375 | static int ams369fg06_power_off(struct ams369fg06 *lcd) | 358 | static int ams369fg06_power_off(struct ams369fg06 *lcd) |
376 | { | 359 | { |
377 | int ret = 0; | 360 | int ret; |
378 | struct lcd_platform_data *pd = NULL; | 361 | struct lcd_platform_data *pd; |
379 | 362 | ||
380 | pd = lcd->lcd_pd; | 363 | pd = lcd->lcd_pd; |
381 | if (!pd) { | ||
382 | dev_err(lcd->dev, "platform data is NULL\n"); | ||
383 | return -EFAULT; | ||
384 | } | ||
385 | 364 | ||
386 | ret = ams369fg06_ldi_disable(lcd); | 365 | ret = ams369fg06_ldi_disable(lcd); |
387 | if (ret) { | 366 | if (ret) { |
@@ -389,13 +368,9 @@ static int ams369fg06_power_off(struct ams369fg06 *lcd) | |||
389 | return -EIO; | 368 | return -EIO; |
390 | } | 369 | } |
391 | 370 | ||
392 | mdelay(pd->power_off_delay); | 371 | msleep(pd->power_off_delay); |
393 | 372 | ||
394 | if (!pd->power_on) { | 373 | pd->power_on(lcd->ld, 0); |
395 | dev_err(lcd->dev, "power_on is NULL.\n"); | ||
396 | return -EFAULT; | ||
397 | } else | ||
398 | pd->power_on(lcd->ld, 0); | ||
399 | 374 | ||
400 | return 0; | 375 | return 0; |
401 | } | 376 | } |
@@ -446,7 +421,7 @@ static int ams369fg06_set_brightness(struct backlight_device *bd) | |||
446 | { | 421 | { |
447 | int ret = 0; | 422 | int ret = 0; |
448 | int brightness = bd->props.brightness; | 423 | int brightness = bd->props.brightness; |
449 | struct ams369fg06 *lcd = dev_get_drvdata(&bd->dev); | 424 | struct ams369fg06 *lcd = bl_get_data(bd); |
450 | 425 | ||
451 | if (brightness < MIN_BRIGHTNESS || | 426 | if (brightness < MIN_BRIGHTNESS || |
452 | brightness > bd->props.max_brightness) { | 427 | brightness > bd->props.max_brightness) { |
@@ -501,7 +476,7 @@ static int ams369fg06_probe(struct spi_device *spi) | |||
501 | lcd->lcd_pd = spi->dev.platform_data; | 476 | lcd->lcd_pd = spi->dev.platform_data; |
502 | if (!lcd->lcd_pd) { | 477 | if (!lcd->lcd_pd) { |
503 | dev_err(&spi->dev, "platform data is NULL\n"); | 478 | dev_err(&spi->dev, "platform data is NULL\n"); |
504 | return -EFAULT; | 479 | return -EINVAL; |
505 | } | 480 | } |
506 | 481 | ||
507 | ld = lcd_device_register("ams369fg06", &spi->dev, lcd, | 482 | ld = lcd_device_register("ams369fg06", &spi->dev, lcd, |
@@ -534,10 +509,11 @@ static int ams369fg06_probe(struct spi_device *spi) | |||
534 | lcd->power = FB_BLANK_POWERDOWN; | 509 | lcd->power = FB_BLANK_POWERDOWN; |
535 | 510 | ||
536 | ams369fg06_power(lcd, FB_BLANK_UNBLANK); | 511 | ams369fg06_power(lcd, FB_BLANK_UNBLANK); |
537 | } else | 512 | } else { |
538 | lcd->power = FB_BLANK_UNBLANK; | 513 | lcd->power = FB_BLANK_UNBLANK; |
514 | } | ||
539 | 515 | ||
540 | dev_set_drvdata(&spi->dev, lcd); | 516 | spi_set_drvdata(spi, lcd); |
541 | 517 | ||
542 | dev_info(&spi->dev, "ams369fg06 panel driver has been probed.\n"); | 518 | dev_info(&spi->dev, "ams369fg06 panel driver has been probed.\n"); |
543 | 519 | ||
@@ -550,7 +526,7 @@ out_lcd_unregister: | |||
550 | 526 | ||
551 | static int ams369fg06_remove(struct spi_device *spi) | 527 | static int ams369fg06_remove(struct spi_device *spi) |
552 | { | 528 | { |
553 | struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev); | 529 | struct ams369fg06 *lcd = spi_get_drvdata(spi); |
554 | 530 | ||
555 | ams369fg06_power(lcd, FB_BLANK_POWERDOWN); | 531 | ams369fg06_power(lcd, FB_BLANK_POWERDOWN); |
556 | backlight_device_unregister(lcd->bd); | 532 | backlight_device_unregister(lcd->bd); |
@@ -560,44 +536,26 @@ static int ams369fg06_remove(struct spi_device *spi) | |||
560 | } | 536 | } |
561 | 537 | ||
562 | #if defined(CONFIG_PM) | 538 | #if defined(CONFIG_PM) |
563 | static unsigned int before_power; | ||
564 | |||
565 | static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg) | 539 | static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg) |
566 | { | 540 | { |
567 | int ret = 0; | 541 | struct ams369fg06 *lcd = spi_get_drvdata(spi); |
568 | struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev); | ||
569 | 542 | ||
570 | dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); | 543 | dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); |
571 | 544 | ||
572 | before_power = lcd->power; | ||
573 | |||
574 | /* | 545 | /* |
575 | * when lcd panel is suspend, lcd panel becomes off | 546 | * when lcd panel is suspend, lcd panel becomes off |
576 | * regardless of status. | 547 | * regardless of status. |
577 | */ | 548 | */ |
578 | ret = ams369fg06_power(lcd, FB_BLANK_POWERDOWN); | 549 | return ams369fg06_power(lcd, FB_BLANK_POWERDOWN); |
579 | |||
580 | return ret; | ||
581 | } | 550 | } |
582 | 551 | ||
583 | static int ams369fg06_resume(struct spi_device *spi) | 552 | static int ams369fg06_resume(struct spi_device *spi) |
584 | { | 553 | { |
585 | int ret = 0; | 554 | struct ams369fg06 *lcd = spi_get_drvdata(spi); |
586 | struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev); | ||
587 | 555 | ||
588 | /* | 556 | lcd->power = FB_BLANK_POWERDOWN; |
589 | * after suspended, if lcd panel status is FB_BLANK_UNBLANK | ||
590 | * (at that time, before_power is FB_BLANK_UNBLANK) then | ||
591 | * it changes that status to FB_BLANK_POWERDOWN to get lcd on. | ||
592 | */ | ||
593 | if (before_power == FB_BLANK_UNBLANK) | ||
594 | lcd->power = FB_BLANK_POWERDOWN; | ||
595 | |||
596 | dev_dbg(&spi->dev, "before_power = %d\n", before_power); | ||
597 | 557 | ||
598 | ret = ams369fg06_power(lcd, before_power); | 558 | return ams369fg06_power(lcd, FB_BLANK_UNBLANK); |
599 | |||
600 | return ret; | ||
601 | } | 559 | } |
602 | #else | 560 | #else |
603 | #define ams369fg06_suspend NULL | 561 | #define ams369fg06_suspend NULL |
@@ -606,7 +564,7 @@ static int ams369fg06_resume(struct spi_device *spi) | |||
606 | 564 | ||
607 | static void ams369fg06_shutdown(struct spi_device *spi) | 565 | static void ams369fg06_shutdown(struct spi_device *spi) |
608 | { | 566 | { |
609 | struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev); | 567 | struct ams369fg06 *lcd = spi_get_drvdata(spi); |
610 | 568 | ||
611 | ams369fg06_power(lcd, FB_BLANK_POWERDOWN); | 569 | ams369fg06_power(lcd, FB_BLANK_POWERDOWN); |
612 | } | 570 | } |
diff --git a/drivers/video/backlight/as3711_bl.c b/drivers/video/backlight/as3711_bl.c new file mode 100644 index 000000000000..41d52fe52543 --- /dev/null +++ b/drivers/video/backlight/as3711_bl.c | |||
@@ -0,0 +1,380 @@ | |||
1 | /* | ||
2 | * AS3711 PMIC backlight driver, using DCDC Step Up Converters | ||
3 | * | ||
4 | * Copyright (C) 2012 Renesas Electronics Corporation | ||
5 | * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation | ||
10 | */ | ||
11 | |||
12 | #include <linux/backlight.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/fb.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/mfd/as3711.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/regmap.h> | ||
22 | #include <linux/slab.h> | ||
23 | |||
24 | enum as3711_bl_type { | ||
25 | AS3711_BL_SU1, | ||
26 | AS3711_BL_SU2, | ||
27 | }; | ||
28 | |||
29 | struct as3711_bl_data { | ||
30 | bool powered; | ||
31 | const char *fb_name; | ||
32 | struct device *fb_dev; | ||
33 | enum as3711_bl_type type; | ||
34 | int brightness; | ||
35 | struct backlight_device *bl; | ||
36 | }; | ||
37 | |||
38 | struct as3711_bl_supply { | ||
39 | struct as3711_bl_data su1; | ||
40 | struct as3711_bl_data su2; | ||
41 | const struct as3711_bl_pdata *pdata; | ||
42 | struct as3711 *as3711; | ||
43 | }; | ||
44 | |||
45 | static struct as3711_bl_supply *to_supply(struct as3711_bl_data *su) | ||
46 | { | ||
47 | switch (su->type) { | ||
48 | case AS3711_BL_SU1: | ||
49 | return container_of(su, struct as3711_bl_supply, su1); | ||
50 | case AS3711_BL_SU2: | ||
51 | return container_of(su, struct as3711_bl_supply, su2); | ||
52 | } | ||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | static int as3711_set_brightness_auto_i(struct as3711_bl_data *data, | ||
57 | unsigned int brightness) | ||
58 | { | ||
59 | struct as3711_bl_supply *supply = to_supply(data); | ||
60 | struct as3711 *as3711 = supply->as3711; | ||
61 | const struct as3711_bl_pdata *pdata = supply->pdata; | ||
62 | int ret = 0; | ||
63 | |||
64 | /* Only all equal current values are supported */ | ||
65 | if (pdata->su2_auto_curr1) | ||
66 | ret = regmap_write(as3711->regmap, AS3711_CURR1_VALUE, | ||
67 | brightness); | ||
68 | if (!ret && pdata->su2_auto_curr2) | ||
69 | ret = regmap_write(as3711->regmap, AS3711_CURR2_VALUE, | ||
70 | brightness); | ||
71 | if (!ret && pdata->su2_auto_curr3) | ||
72 | ret = regmap_write(as3711->regmap, AS3711_CURR3_VALUE, | ||
73 | brightness); | ||
74 | |||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | static int as3711_set_brightness_v(struct as3711 *as3711, | ||
79 | unsigned int brightness, | ||
80 | unsigned int reg) | ||
81 | { | ||
82 | if (brightness > 31) | ||
83 | return -EINVAL; | ||
84 | |||
85 | return regmap_update_bits(as3711->regmap, reg, 0xf0, | ||
86 | brightness << 4); | ||
87 | } | ||
88 | |||
89 | static int as3711_bl_su2_reset(struct as3711_bl_supply *supply) | ||
90 | { | ||
91 | struct as3711 *as3711 = supply->as3711; | ||
92 | int ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_5, | ||
93 | 3, supply->pdata->su2_fbprot); | ||
94 | if (!ret) | ||
95 | ret = regmap_update_bits(as3711->regmap, | ||
96 | AS3711_STEPUP_CONTROL_2, 1, 0); | ||
97 | if (!ret) | ||
98 | ret = regmap_update_bits(as3711->regmap, | ||
99 | AS3711_STEPUP_CONTROL_2, 1, 1); | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * Someone with less fragile or less expensive hardware could try to simplify | ||
105 | * the brightness adjustment procedure. | ||
106 | */ | ||
107 | static int as3711_bl_update_status(struct backlight_device *bl) | ||
108 | { | ||
109 | struct as3711_bl_data *data = bl_get_data(bl); | ||
110 | struct as3711_bl_supply *supply = to_supply(data); | ||
111 | struct as3711 *as3711 = supply->as3711; | ||
112 | int brightness = bl->props.brightness; | ||
113 | int ret = 0; | ||
114 | |||
115 | dev_dbg(&bl->dev, "%s(): brightness %u, pwr %x, blank %x, state %x\n", | ||
116 | __func__, bl->props.brightness, bl->props.power, | ||
117 | bl->props.fb_blank, bl->props.state); | ||
118 | |||
119 | if (bl->props.power != FB_BLANK_UNBLANK || | ||
120 | bl->props.fb_blank != FB_BLANK_UNBLANK || | ||
121 | bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) | ||
122 | brightness = 0; | ||
123 | |||
124 | if (data->type == AS3711_BL_SU1) { | ||
125 | ret = as3711_set_brightness_v(as3711, brightness, | ||
126 | AS3711_STEPUP_CONTROL_1); | ||
127 | } else { | ||
128 | const struct as3711_bl_pdata *pdata = supply->pdata; | ||
129 | |||
130 | switch (pdata->su2_feedback) { | ||
131 | case AS3711_SU2_VOLTAGE: | ||
132 | ret = as3711_set_brightness_v(as3711, brightness, | ||
133 | AS3711_STEPUP_CONTROL_2); | ||
134 | break; | ||
135 | case AS3711_SU2_CURR_AUTO: | ||
136 | ret = as3711_set_brightness_auto_i(data, brightness / 4); | ||
137 | if (ret < 0) | ||
138 | return ret; | ||
139 | if (brightness) { | ||
140 | ret = as3711_bl_su2_reset(supply); | ||
141 | if (ret < 0) | ||
142 | return ret; | ||
143 | udelay(500); | ||
144 | ret = as3711_set_brightness_auto_i(data, brightness); | ||
145 | } else { | ||
146 | ret = regmap_update_bits(as3711->regmap, | ||
147 | AS3711_STEPUP_CONTROL_2, 1, 0); | ||
148 | } | ||
149 | break; | ||
150 | /* Manual one current feedback pin below */ | ||
151 | case AS3711_SU2_CURR1: | ||
152 | ret = regmap_write(as3711->regmap, AS3711_CURR1_VALUE, | ||
153 | brightness); | ||
154 | break; | ||
155 | case AS3711_SU2_CURR2: | ||
156 | ret = regmap_write(as3711->regmap, AS3711_CURR2_VALUE, | ||
157 | brightness); | ||
158 | break; | ||
159 | case AS3711_SU2_CURR3: | ||
160 | ret = regmap_write(as3711->regmap, AS3711_CURR3_VALUE, | ||
161 | brightness); | ||
162 | break; | ||
163 | default: | ||
164 | ret = -EINVAL; | ||
165 | } | ||
166 | } | ||
167 | if (!ret) | ||
168 | data->brightness = brightness; | ||
169 | |||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | static int as3711_bl_get_brightness(struct backlight_device *bl) | ||
174 | { | ||
175 | struct as3711_bl_data *data = bl_get_data(bl); | ||
176 | |||
177 | return data->brightness; | ||
178 | } | ||
179 | |||
180 | static const struct backlight_ops as3711_bl_ops = { | ||
181 | .update_status = as3711_bl_update_status, | ||
182 | .get_brightness = as3711_bl_get_brightness, | ||
183 | }; | ||
184 | |||
185 | static int as3711_bl_init_su2(struct as3711_bl_supply *supply) | ||
186 | { | ||
187 | struct as3711 *as3711 = supply->as3711; | ||
188 | const struct as3711_bl_pdata *pdata = supply->pdata; | ||
189 | u8 ctl = 0; | ||
190 | int ret; | ||
191 | |||
192 | dev_dbg(as3711->dev, "%s(): use %u\n", __func__, pdata->su2_feedback); | ||
193 | |||
194 | /* Turn SU2 off */ | ||
195 | ret = regmap_write(as3711->regmap, AS3711_STEPUP_CONTROL_2, 0); | ||
196 | if (ret < 0) | ||
197 | return ret; | ||
198 | |||
199 | switch (pdata->su2_feedback) { | ||
200 | case AS3711_SU2_VOLTAGE: | ||
201 | ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_4, 3, 0); | ||
202 | break; | ||
203 | case AS3711_SU2_CURR1: | ||
204 | ctl = 1; | ||
205 | ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_4, 3, 1); | ||
206 | break; | ||
207 | case AS3711_SU2_CURR2: | ||
208 | ctl = 4; | ||
209 | ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_4, 3, 2); | ||
210 | break; | ||
211 | case AS3711_SU2_CURR3: | ||
212 | ctl = 0x10; | ||
213 | ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_4, 3, 3); | ||
214 | break; | ||
215 | case AS3711_SU2_CURR_AUTO: | ||
216 | if (pdata->su2_auto_curr1) | ||
217 | ctl = 2; | ||
218 | if (pdata->su2_auto_curr2) | ||
219 | ctl |= 8; | ||
220 | if (pdata->su2_auto_curr3) | ||
221 | ctl |= 0x20; | ||
222 | ret = 0; | ||
223 | break; | ||
224 | default: | ||
225 | return -EINVAL; | ||
226 | } | ||
227 | |||
228 | if (!ret) | ||
229 | ret = regmap_write(as3711->regmap, AS3711_CURR_CONTROL, ctl); | ||
230 | |||
231 | return ret; | ||
232 | } | ||
233 | |||
234 | static int as3711_bl_register(struct platform_device *pdev, | ||
235 | unsigned int max_brightness, struct as3711_bl_data *su) | ||
236 | { | ||
237 | struct backlight_properties props = {.type = BACKLIGHT_RAW,}; | ||
238 | struct backlight_device *bl; | ||
239 | |||
240 | /* max tuning I = 31uA for voltage- and 38250uA for current-feedback */ | ||
241 | props.max_brightness = max_brightness; | ||
242 | |||
243 | bl = backlight_device_register(su->type == AS3711_BL_SU1 ? | ||
244 | "as3711-su1" : "as3711-su2", | ||
245 | &pdev->dev, su, | ||
246 | &as3711_bl_ops, &props); | ||
247 | if (IS_ERR(bl)) { | ||
248 | dev_err(&pdev->dev, "failed to register backlight\n"); | ||
249 | return PTR_ERR(bl); | ||
250 | } | ||
251 | |||
252 | bl->props.brightness = props.max_brightness; | ||
253 | |||
254 | backlight_update_status(bl); | ||
255 | |||
256 | su->bl = bl; | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static int as3711_backlight_probe(struct platform_device *pdev) | ||
262 | { | ||
263 | struct as3711_bl_pdata *pdata = dev_get_platdata(&pdev->dev); | ||
264 | struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent); | ||
265 | struct as3711_bl_supply *supply; | ||
266 | struct as3711_bl_data *su; | ||
267 | unsigned int max_brightness; | ||
268 | int ret; | ||
269 | |||
270 | if (!pdata || (!pdata->su1_fb && !pdata->su2_fb)) { | ||
271 | dev_err(&pdev->dev, "No platform data, exiting...\n"); | ||
272 | return -ENODEV; | ||
273 | } | ||
274 | |||
275 | /* | ||
276 | * Due to possible hardware damage I chose to block all modes, | ||
277 | * unsupported on my hardware. Anyone, wishing to use any of those modes | ||
278 | * will have to first review the code, then activate and test it. | ||
279 | */ | ||
280 | if (pdata->su1_fb || | ||
281 | pdata->su2_fbprot != AS3711_SU2_GPIO4 || | ||
282 | pdata->su2_feedback != AS3711_SU2_CURR_AUTO) { | ||
283 | dev_warn(&pdev->dev, | ||
284 | "Attention! An untested mode has been chosen!\n" | ||
285 | "Please, review the code, enable, test, and report success:-)\n"); | ||
286 | return -EINVAL; | ||
287 | } | ||
288 | |||
289 | supply = devm_kzalloc(&pdev->dev, sizeof(*supply), GFP_KERNEL); | ||
290 | if (!supply) | ||
291 | return -ENOMEM; | ||
292 | |||
293 | supply->as3711 = as3711; | ||
294 | supply->pdata = pdata; | ||
295 | |||
296 | if (pdata->su1_fb) { | ||
297 | su = &supply->su1; | ||
298 | su->fb_name = pdata->su1_fb; | ||
299 | su->type = AS3711_BL_SU1; | ||
300 | |||
301 | max_brightness = min(pdata->su1_max_uA, 31); | ||
302 | ret = as3711_bl_register(pdev, max_brightness, su); | ||
303 | if (ret < 0) | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | if (pdata->su2_fb) { | ||
308 | su = &supply->su2; | ||
309 | su->fb_name = pdata->su2_fb; | ||
310 | su->type = AS3711_BL_SU2; | ||
311 | |||
312 | switch (pdata->su2_fbprot) { | ||
313 | case AS3711_SU2_GPIO2: | ||
314 | case AS3711_SU2_GPIO3: | ||
315 | case AS3711_SU2_GPIO4: | ||
316 | case AS3711_SU2_LX_SD4: | ||
317 | break; | ||
318 | default: | ||
319 | ret = -EINVAL; | ||
320 | goto esu2; | ||
321 | } | ||
322 | |||
323 | switch (pdata->su2_feedback) { | ||
324 | case AS3711_SU2_VOLTAGE: | ||
325 | max_brightness = min(pdata->su2_max_uA, 31); | ||
326 | break; | ||
327 | case AS3711_SU2_CURR1: | ||
328 | case AS3711_SU2_CURR2: | ||
329 | case AS3711_SU2_CURR3: | ||
330 | case AS3711_SU2_CURR_AUTO: | ||
331 | max_brightness = min(pdata->su2_max_uA / 150, 255); | ||
332 | break; | ||
333 | default: | ||
334 | ret = -EINVAL; | ||
335 | goto esu2; | ||
336 | } | ||
337 | |||
338 | ret = as3711_bl_init_su2(supply); | ||
339 | if (ret < 0) | ||
340 | return ret; | ||
341 | |||
342 | ret = as3711_bl_register(pdev, max_brightness, su); | ||
343 | if (ret < 0) | ||
344 | goto esu2; | ||
345 | } | ||
346 | |||
347 | platform_set_drvdata(pdev, supply); | ||
348 | |||
349 | return 0; | ||
350 | |||
351 | esu2: | ||
352 | backlight_device_unregister(supply->su1.bl); | ||
353 | return ret; | ||
354 | } | ||
355 | |||
356 | static int as3711_backlight_remove(struct platform_device *pdev) | ||
357 | { | ||
358 | struct as3711_bl_supply *supply = platform_get_drvdata(pdev); | ||
359 | |||
360 | backlight_device_unregister(supply->su1.bl); | ||
361 | backlight_device_unregister(supply->su2.bl); | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static struct platform_driver as3711_backlight_driver = { | ||
367 | .driver = { | ||
368 | .name = "as3711-backlight", | ||
369 | .owner = THIS_MODULE, | ||
370 | }, | ||
371 | .probe = as3711_backlight_probe, | ||
372 | .remove = as3711_backlight_remove, | ||
373 | }; | ||
374 | |||
375 | module_platform_driver(as3711_backlight_driver); | ||
376 | |||
377 | MODULE_DESCRIPTION("Backlight Driver for AS3711 PMICs"); | ||
378 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de"); | ||
379 | MODULE_LICENSE("GPL"); | ||
380 | MODULE_ALIAS("platform:as3711-backlight"); | ||
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index e323fcbe884e..aa782f302983 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c | |||
@@ -337,7 +337,7 @@ static void corgi_lcd_power_off(struct corgi_lcd *lcd) | |||
337 | 337 | ||
338 | static int corgi_lcd_set_mode(struct lcd_device *ld, struct fb_videomode *m) | 338 | static int corgi_lcd_set_mode(struct lcd_device *ld, struct fb_videomode *m) |
339 | { | 339 | { |
340 | struct corgi_lcd *lcd = dev_get_drvdata(&ld->dev); | 340 | struct corgi_lcd *lcd = lcd_get_data(ld); |
341 | int mode = CORGI_LCD_MODE_QVGA; | 341 | int mode = CORGI_LCD_MODE_QVGA; |
342 | 342 | ||
343 | if (m->xres == 640 || m->xres == 480) | 343 | if (m->xres == 640 || m->xres == 480) |
@@ -364,7 +364,7 @@ static int corgi_lcd_set_mode(struct lcd_device *ld, struct fb_videomode *m) | |||
364 | 364 | ||
365 | static int corgi_lcd_set_power(struct lcd_device *ld, int power) | 365 | static int corgi_lcd_set_power(struct lcd_device *ld, int power) |
366 | { | 366 | { |
367 | struct corgi_lcd *lcd = dev_get_drvdata(&ld->dev); | 367 | struct corgi_lcd *lcd = lcd_get_data(ld); |
368 | 368 | ||
369 | if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) | 369 | if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) |
370 | corgi_lcd_power_on(lcd); | 370 | corgi_lcd_power_on(lcd); |
@@ -378,7 +378,7 @@ static int corgi_lcd_set_power(struct lcd_device *ld, int power) | |||
378 | 378 | ||
379 | static int corgi_lcd_get_power(struct lcd_device *ld) | 379 | static int corgi_lcd_get_power(struct lcd_device *ld) |
380 | { | 380 | { |
381 | struct corgi_lcd *lcd = dev_get_drvdata(&ld->dev); | 381 | struct corgi_lcd *lcd = lcd_get_data(ld); |
382 | 382 | ||
383 | return lcd->power; | 383 | return lcd->power; |
384 | } | 384 | } |
@@ -391,7 +391,7 @@ static struct lcd_ops corgi_lcd_ops = { | |||
391 | 391 | ||
392 | static int corgi_bl_get_intensity(struct backlight_device *bd) | 392 | static int corgi_bl_get_intensity(struct backlight_device *bd) |
393 | { | 393 | { |
394 | struct corgi_lcd *lcd = dev_get_drvdata(&bd->dev); | 394 | struct corgi_lcd *lcd = bl_get_data(bd); |
395 | 395 | ||
396 | return lcd->intensity; | 396 | return lcd->intensity; |
397 | } | 397 | } |
@@ -423,7 +423,7 @@ static int corgi_bl_set_intensity(struct corgi_lcd *lcd, int intensity) | |||
423 | 423 | ||
424 | static int corgi_bl_update_status(struct backlight_device *bd) | 424 | static int corgi_bl_update_status(struct backlight_device *bd) |
425 | { | 425 | { |
426 | struct corgi_lcd *lcd = dev_get_drvdata(&bd->dev); | 426 | struct corgi_lcd *lcd = bl_get_data(bd); |
427 | int intensity = bd->props.brightness; | 427 | int intensity = bd->props.brightness; |
428 | 428 | ||
429 | if (bd->props.power != FB_BLANK_UNBLANK) | 429 | if (bd->props.power != FB_BLANK_UNBLANK) |
@@ -460,7 +460,7 @@ static const struct backlight_ops corgi_bl_ops = { | |||
460 | #ifdef CONFIG_PM | 460 | #ifdef CONFIG_PM |
461 | static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state) | 461 | static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state) |
462 | { | 462 | { |
463 | struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev); | 463 | struct corgi_lcd *lcd = spi_get_drvdata(spi); |
464 | 464 | ||
465 | corgibl_flags |= CORGIBL_SUSPENDED; | 465 | corgibl_flags |= CORGIBL_SUSPENDED; |
466 | corgi_bl_set_intensity(lcd, 0); | 466 | corgi_bl_set_intensity(lcd, 0); |
@@ -470,7 +470,7 @@ static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state) | |||
470 | 470 | ||
471 | static int corgi_lcd_resume(struct spi_device *spi) | 471 | static int corgi_lcd_resume(struct spi_device *spi) |
472 | { | 472 | { |
473 | struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev); | 473 | struct corgi_lcd *lcd = spi_get_drvdata(spi); |
474 | 474 | ||
475 | corgibl_flags &= ~CORGIBL_SUSPENDED; | 475 | corgibl_flags &= ~CORGIBL_SUSPENDED; |
476 | corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK); | 476 | corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK); |
@@ -577,7 +577,7 @@ static int corgi_lcd_probe(struct spi_device *spi) | |||
577 | 577 | ||
578 | lcd->kick_battery = pdata->kick_battery; | 578 | lcd->kick_battery = pdata->kick_battery; |
579 | 579 | ||
580 | dev_set_drvdata(&spi->dev, lcd); | 580 | spi_set_drvdata(spi, lcd); |
581 | corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK); | 581 | corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK); |
582 | backlight_update_status(lcd->bl_dev); | 582 | backlight_update_status(lcd->bl_dev); |
583 | 583 | ||
@@ -594,7 +594,7 @@ err_unregister_lcd: | |||
594 | 594 | ||
595 | static int corgi_lcd_remove(struct spi_device *spi) | 595 | static int corgi_lcd_remove(struct spi_device *spi) |
596 | { | 596 | { |
597 | struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev); | 597 | struct corgi_lcd *lcd = spi_get_drvdata(spi); |
598 | 598 | ||
599 | lcd->bl_dev->props.power = FB_BLANK_UNBLANK; | 599 | lcd->bl_dev->props.power = FB_BLANK_UNBLANK; |
600 | lcd->bl_dev->props.brightness = 0; | 600 | lcd->bl_dev->props.brightness = 0; |
diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c new file mode 100644 index 000000000000..a0482b567bfe --- /dev/null +++ b/drivers/video/backlight/hx8357.c | |||
@@ -0,0 +1,497 @@ | |||
1 | /* | ||
2 | * Driver for the Himax HX-8357 LCD Controller | ||
3 | * | ||
4 | * Copyright 2012 Free Electrons | ||
5 | * | ||
6 | * Licensed under the GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/delay.h> | ||
10 | #include <linux/lcd.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/of.h> | ||
13 | #include <linux/of_device.h> | ||
14 | #include <linux/of_gpio.h> | ||
15 | #include <linux/spi/spi.h> | ||
16 | |||
17 | #define HX8357_NUM_IM_PINS 3 | ||
18 | |||
19 | #define HX8357_SWRESET 0x01 | ||
20 | #define HX8357_GET_RED_CHANNEL 0x06 | ||
21 | #define HX8357_GET_GREEN_CHANNEL 0x07 | ||
22 | #define HX8357_GET_BLUE_CHANNEL 0x08 | ||
23 | #define HX8357_GET_POWER_MODE 0x0a | ||
24 | #define HX8357_GET_MADCTL 0x0b | ||
25 | #define HX8357_GET_PIXEL_FORMAT 0x0c | ||
26 | #define HX8357_GET_DISPLAY_MODE 0x0d | ||
27 | #define HX8357_GET_SIGNAL_MODE 0x0e | ||
28 | #define HX8357_GET_DIAGNOSTIC_RESULT 0x0f | ||
29 | #define HX8357_ENTER_SLEEP_MODE 0x10 | ||
30 | #define HX8357_EXIT_SLEEP_MODE 0x11 | ||
31 | #define HX8357_ENTER_PARTIAL_MODE 0x12 | ||
32 | #define HX8357_ENTER_NORMAL_MODE 0x13 | ||
33 | #define HX8357_EXIT_INVERSION_MODE 0x20 | ||
34 | #define HX8357_ENTER_INVERSION_MODE 0x21 | ||
35 | #define HX8357_SET_DISPLAY_OFF 0x28 | ||
36 | #define HX8357_SET_DISPLAY_ON 0x29 | ||
37 | #define HX8357_SET_COLUMN_ADDRESS 0x2a | ||
38 | #define HX8357_SET_PAGE_ADDRESS 0x2b | ||
39 | #define HX8357_WRITE_MEMORY_START 0x2c | ||
40 | #define HX8357_READ_MEMORY_START 0x2e | ||
41 | #define HX8357_SET_PARTIAL_AREA 0x30 | ||
42 | #define HX8357_SET_SCROLL_AREA 0x33 | ||
43 | #define HX8357_SET_TEAR_OFF 0x34 | ||
44 | #define HX8357_SET_TEAR_ON 0x35 | ||
45 | #define HX8357_SET_ADDRESS_MODE 0x36 | ||
46 | #define HX8357_SET_SCROLL_START 0x37 | ||
47 | #define HX8357_EXIT_IDLE_MODE 0x38 | ||
48 | #define HX8357_ENTER_IDLE_MODE 0x39 | ||
49 | #define HX8357_SET_PIXEL_FORMAT 0x3a | ||
50 | #define HX8357_SET_PIXEL_FORMAT_DBI_3BIT (0x1) | ||
51 | #define HX8357_SET_PIXEL_FORMAT_DBI_16BIT (0x5) | ||
52 | #define HX8357_SET_PIXEL_FORMAT_DBI_18BIT (0x6) | ||
53 | #define HX8357_SET_PIXEL_FORMAT_DPI_3BIT (0x1 << 4) | ||
54 | #define HX8357_SET_PIXEL_FORMAT_DPI_16BIT (0x5 << 4) | ||
55 | #define HX8357_SET_PIXEL_FORMAT_DPI_18BIT (0x6 << 4) | ||
56 | #define HX8357_WRITE_MEMORY_CONTINUE 0x3c | ||
57 | #define HX8357_READ_MEMORY_CONTINUE 0x3e | ||
58 | #define HX8357_SET_TEAR_SCAN_LINES 0x44 | ||
59 | #define HX8357_GET_SCAN_LINES 0x45 | ||
60 | #define HX8357_READ_DDB_START 0xa1 | ||
61 | #define HX8357_SET_DISPLAY_MODE 0xb4 | ||
62 | #define HX8357_SET_DISPLAY_MODE_RGB_THROUGH (0x3) | ||
63 | #define HX8357_SET_DISPLAY_MODE_RGB_INTERFACE (1 << 4) | ||
64 | #define HX8357_SET_PANEL_DRIVING 0xc0 | ||
65 | #define HX8357_SET_DISPLAY_FRAME 0xc5 | ||
66 | #define HX8357_SET_RGB 0xc6 | ||
67 | #define HX8357_SET_RGB_ENABLE_HIGH (1 << 1) | ||
68 | #define HX8357_SET_GAMMA 0xc8 | ||
69 | #define HX8357_SET_POWER 0xd0 | ||
70 | #define HX8357_SET_VCOM 0xd1 | ||
71 | #define HX8357_SET_POWER_NORMAL 0xd2 | ||
72 | #define HX8357_SET_PANEL_RELATED 0xe9 | ||
73 | |||
74 | struct hx8357_data { | ||
75 | unsigned im_pins[HX8357_NUM_IM_PINS]; | ||
76 | unsigned reset; | ||
77 | struct spi_device *spi; | ||
78 | int state; | ||
79 | }; | ||
80 | |||
81 | static u8 hx8357_seq_power[] = { | ||
82 | HX8357_SET_POWER, 0x44, 0x41, 0x06, | ||
83 | }; | ||
84 | |||
85 | static u8 hx8357_seq_vcom[] = { | ||
86 | HX8357_SET_VCOM, 0x40, 0x10, | ||
87 | }; | ||
88 | |||
89 | static u8 hx8357_seq_power_normal[] = { | ||
90 | HX8357_SET_POWER_NORMAL, 0x05, 0x12, | ||
91 | }; | ||
92 | |||
93 | static u8 hx8357_seq_panel_driving[] = { | ||
94 | HX8357_SET_PANEL_DRIVING, 0x14, 0x3b, 0x00, 0x02, 0x11, | ||
95 | }; | ||
96 | |||
97 | static u8 hx8357_seq_display_frame[] = { | ||
98 | HX8357_SET_DISPLAY_FRAME, 0x0c, | ||
99 | }; | ||
100 | |||
101 | static u8 hx8357_seq_panel_related[] = { | ||
102 | HX8357_SET_PANEL_RELATED, 0x01, | ||
103 | }; | ||
104 | |||
105 | static u8 hx8357_seq_undefined1[] = { | ||
106 | 0xea, 0x03, 0x00, 0x00, | ||
107 | }; | ||
108 | |||
109 | static u8 hx8357_seq_undefined2[] = { | ||
110 | 0xeb, 0x40, 0x54, 0x26, 0xdb, | ||
111 | }; | ||
112 | |||
113 | static u8 hx8357_seq_gamma[] = { | ||
114 | HX8357_SET_GAMMA, 0x00, 0x15, 0x00, 0x22, 0x00, | ||
115 | 0x08, 0x77, 0x26, 0x77, 0x22, 0x04, 0x00, | ||
116 | }; | ||
117 | |||
118 | static u8 hx8357_seq_address_mode[] = { | ||
119 | HX8357_SET_ADDRESS_MODE, 0xc0, | ||
120 | }; | ||
121 | |||
122 | static u8 hx8357_seq_pixel_format[] = { | ||
123 | HX8357_SET_PIXEL_FORMAT, | ||
124 | HX8357_SET_PIXEL_FORMAT_DPI_18BIT | | ||
125 | HX8357_SET_PIXEL_FORMAT_DBI_18BIT, | ||
126 | }; | ||
127 | |||
128 | static u8 hx8357_seq_column_address[] = { | ||
129 | HX8357_SET_COLUMN_ADDRESS, 0x00, 0x00, 0x01, 0x3f, | ||
130 | }; | ||
131 | |||
132 | static u8 hx8357_seq_page_address[] = { | ||
133 | HX8357_SET_PAGE_ADDRESS, 0x00, 0x00, 0x01, 0xdf, | ||
134 | }; | ||
135 | |||
136 | static u8 hx8357_seq_rgb[] = { | ||
137 | HX8357_SET_RGB, 0x02, | ||
138 | }; | ||
139 | |||
140 | static u8 hx8357_seq_display_mode[] = { | ||
141 | HX8357_SET_DISPLAY_MODE, | ||
142 | HX8357_SET_DISPLAY_MODE_RGB_THROUGH | | ||
143 | HX8357_SET_DISPLAY_MODE_RGB_INTERFACE, | ||
144 | }; | ||
145 | |||
146 | static int hx8357_spi_write_then_read(struct lcd_device *lcdev, | ||
147 | u8 *txbuf, u16 txlen, | ||
148 | u8 *rxbuf, u16 rxlen) | ||
149 | { | ||
150 | struct hx8357_data *lcd = lcd_get_data(lcdev); | ||
151 | struct spi_message msg; | ||
152 | struct spi_transfer xfer[2]; | ||
153 | u16 *local_txbuf = NULL; | ||
154 | int ret = 0; | ||
155 | |||
156 | memset(xfer, 0, sizeof(xfer)); | ||
157 | spi_message_init(&msg); | ||
158 | |||
159 | if (txlen) { | ||
160 | int i; | ||
161 | |||
162 | local_txbuf = kcalloc(txlen, sizeof(*local_txbuf), GFP_KERNEL); | ||
163 | |||
164 | if (!local_txbuf) | ||
165 | return -ENOMEM; | ||
166 | |||
167 | for (i = 0; i < txlen; i++) { | ||
168 | local_txbuf[i] = txbuf[i]; | ||
169 | if (i > 0) | ||
170 | local_txbuf[i] |= 1 << 8; | ||
171 | } | ||
172 | |||
173 | xfer[0].len = 2 * txlen; | ||
174 | xfer[0].bits_per_word = 9; | ||
175 | xfer[0].tx_buf = local_txbuf; | ||
176 | spi_message_add_tail(&xfer[0], &msg); | ||
177 | } | ||
178 | |||
179 | if (rxlen) { | ||
180 | xfer[1].len = rxlen; | ||
181 | xfer[1].bits_per_word = 8; | ||
182 | xfer[1].rx_buf = rxbuf; | ||
183 | spi_message_add_tail(&xfer[1], &msg); | ||
184 | } | ||
185 | |||
186 | ret = spi_sync(lcd->spi, &msg); | ||
187 | if (ret < 0) | ||
188 | dev_err(&lcdev->dev, "Couldn't send SPI data\n"); | ||
189 | |||
190 | if (txlen) | ||
191 | kfree(local_txbuf); | ||
192 | |||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | static inline int hx8357_spi_write_array(struct lcd_device *lcdev, | ||
197 | u8 *value, u8 len) | ||
198 | { | ||
199 | return hx8357_spi_write_then_read(lcdev, value, len, NULL, 0); | ||
200 | } | ||
201 | |||
202 | static inline int hx8357_spi_write_byte(struct lcd_device *lcdev, | ||
203 | u8 value) | ||
204 | { | ||
205 | return hx8357_spi_write_then_read(lcdev, &value, 1, NULL, 0); | ||
206 | } | ||
207 | |||
208 | static int hx8357_enter_standby(struct lcd_device *lcdev) | ||
209 | { | ||
210 | int ret; | ||
211 | |||
212 | ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_OFF); | ||
213 | if (ret < 0) | ||
214 | return ret; | ||
215 | |||
216 | usleep_range(10000, 12000); | ||
217 | |||
218 | ret = hx8357_spi_write_byte(lcdev, HX8357_ENTER_SLEEP_MODE); | ||
219 | if (ret < 0) | ||
220 | return ret; | ||
221 | |||
222 | msleep(120); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int hx8357_exit_standby(struct lcd_device *lcdev) | ||
228 | { | ||
229 | int ret; | ||
230 | |||
231 | ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE); | ||
232 | if (ret < 0) | ||
233 | return ret; | ||
234 | |||
235 | msleep(120); | ||
236 | |||
237 | ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON); | ||
238 | if (ret < 0) | ||
239 | return ret; | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int hx8357_lcd_init(struct lcd_device *lcdev) | ||
245 | { | ||
246 | struct hx8357_data *lcd = lcd_get_data(lcdev); | ||
247 | int ret; | ||
248 | |||
249 | /* | ||
250 | * Set the interface selection pins to SPI mode, with three | ||
251 | * wires | ||
252 | */ | ||
253 | gpio_set_value_cansleep(lcd->im_pins[0], 1); | ||
254 | gpio_set_value_cansleep(lcd->im_pins[1], 0); | ||
255 | gpio_set_value_cansleep(lcd->im_pins[2], 1); | ||
256 | |||
257 | /* Reset the screen */ | ||
258 | gpio_set_value(lcd->reset, 1); | ||
259 | usleep_range(10000, 12000); | ||
260 | gpio_set_value(lcd->reset, 0); | ||
261 | usleep_range(10000, 12000); | ||
262 | gpio_set_value(lcd->reset, 1); | ||
263 | msleep(120); | ||
264 | |||
265 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_power, | ||
266 | ARRAY_SIZE(hx8357_seq_power)); | ||
267 | if (ret < 0) | ||
268 | return ret; | ||
269 | |||
270 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_vcom, | ||
271 | ARRAY_SIZE(hx8357_seq_vcom)); | ||
272 | if (ret < 0) | ||
273 | return ret; | ||
274 | |||
275 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_power_normal, | ||
276 | ARRAY_SIZE(hx8357_seq_power_normal)); | ||
277 | if (ret < 0) | ||
278 | return ret; | ||
279 | |||
280 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_panel_driving, | ||
281 | ARRAY_SIZE(hx8357_seq_panel_driving)); | ||
282 | if (ret < 0) | ||
283 | return ret; | ||
284 | |||
285 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_display_frame, | ||
286 | ARRAY_SIZE(hx8357_seq_display_frame)); | ||
287 | if (ret < 0) | ||
288 | return ret; | ||
289 | |||
290 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_panel_related, | ||
291 | ARRAY_SIZE(hx8357_seq_panel_related)); | ||
292 | if (ret < 0) | ||
293 | return ret; | ||
294 | |||
295 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_undefined1, | ||
296 | ARRAY_SIZE(hx8357_seq_undefined1)); | ||
297 | if (ret < 0) | ||
298 | return ret; | ||
299 | |||
300 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_undefined2, | ||
301 | ARRAY_SIZE(hx8357_seq_undefined2)); | ||
302 | if (ret < 0) | ||
303 | return ret; | ||
304 | |||
305 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_gamma, | ||
306 | ARRAY_SIZE(hx8357_seq_gamma)); | ||
307 | if (ret < 0) | ||
308 | return ret; | ||
309 | |||
310 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_address_mode, | ||
311 | ARRAY_SIZE(hx8357_seq_address_mode)); | ||
312 | if (ret < 0) | ||
313 | return ret; | ||
314 | |||
315 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_pixel_format, | ||
316 | ARRAY_SIZE(hx8357_seq_pixel_format)); | ||
317 | if (ret < 0) | ||
318 | return ret; | ||
319 | |||
320 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_column_address, | ||
321 | ARRAY_SIZE(hx8357_seq_column_address)); | ||
322 | if (ret < 0) | ||
323 | return ret; | ||
324 | |||
325 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_page_address, | ||
326 | ARRAY_SIZE(hx8357_seq_page_address)); | ||
327 | if (ret < 0) | ||
328 | return ret; | ||
329 | |||
330 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_rgb, | ||
331 | ARRAY_SIZE(hx8357_seq_rgb)); | ||
332 | if (ret < 0) | ||
333 | return ret; | ||
334 | |||
335 | ret = hx8357_spi_write_array(lcdev, hx8357_seq_display_mode, | ||
336 | ARRAY_SIZE(hx8357_seq_display_mode)); | ||
337 | if (ret < 0) | ||
338 | return ret; | ||
339 | |||
340 | ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE); | ||
341 | if (ret < 0) | ||
342 | return ret; | ||
343 | |||
344 | msleep(120); | ||
345 | |||
346 | ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON); | ||
347 | if (ret < 0) | ||
348 | return ret; | ||
349 | |||
350 | usleep_range(5000, 7000); | ||
351 | |||
352 | ret = hx8357_spi_write_byte(lcdev, HX8357_WRITE_MEMORY_START); | ||
353 | if (ret < 0) | ||
354 | return ret; | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | #define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) | ||
360 | |||
361 | static int hx8357_set_power(struct lcd_device *lcdev, int power) | ||
362 | { | ||
363 | struct hx8357_data *lcd = lcd_get_data(lcdev); | ||
364 | int ret = 0; | ||
365 | |||
366 | if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->state)) | ||
367 | ret = hx8357_exit_standby(lcdev); | ||
368 | else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->state)) | ||
369 | ret = hx8357_enter_standby(lcdev); | ||
370 | |||
371 | if (ret == 0) | ||
372 | lcd->state = power; | ||
373 | else | ||
374 | dev_warn(&lcdev->dev, "failed to set power mode %d\n", power); | ||
375 | |||
376 | return ret; | ||
377 | } | ||
378 | |||
379 | static int hx8357_get_power(struct lcd_device *lcdev) | ||
380 | { | ||
381 | struct hx8357_data *lcd = lcd_get_data(lcdev); | ||
382 | |||
383 | return lcd->state; | ||
384 | } | ||
385 | |||
386 | static struct lcd_ops hx8357_ops = { | ||
387 | .set_power = hx8357_set_power, | ||
388 | .get_power = hx8357_get_power, | ||
389 | }; | ||
390 | |||
391 | static int hx8357_probe(struct spi_device *spi) | ||
392 | { | ||
393 | struct lcd_device *lcdev; | ||
394 | struct hx8357_data *lcd; | ||
395 | int i, ret; | ||
396 | |||
397 | lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL); | ||
398 | if (!lcd) { | ||
399 | dev_err(&spi->dev, "Couldn't allocate lcd internal structure!\n"); | ||
400 | return -ENOMEM; | ||
401 | } | ||
402 | |||
403 | ret = spi_setup(spi); | ||
404 | if (ret < 0) { | ||
405 | dev_err(&spi->dev, "SPI setup failed.\n"); | ||
406 | return ret; | ||
407 | } | ||
408 | |||
409 | lcd->spi = spi; | ||
410 | |||
411 | lcd->reset = of_get_named_gpio(spi->dev.of_node, "gpios-reset", 0); | ||
412 | if (!gpio_is_valid(lcd->reset)) { | ||
413 | dev_err(&spi->dev, "Missing dt property: gpios-reset\n"); | ||
414 | return -EINVAL; | ||
415 | } | ||
416 | |||
417 | ret = devm_gpio_request_one(&spi->dev, lcd->reset, | ||
418 | GPIOF_OUT_INIT_HIGH, | ||
419 | "hx8357-reset"); | ||
420 | if (ret) { | ||
421 | dev_err(&spi->dev, | ||
422 | "failed to request gpio %d: %d\n", | ||
423 | lcd->reset, ret); | ||
424 | return -EINVAL; | ||
425 | } | ||
426 | |||
427 | for (i = 0; i < HX8357_NUM_IM_PINS; i++) { | ||
428 | lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node, | ||
429 | "im-gpios", i); | ||
430 | if (lcd->im_pins[i] == -EPROBE_DEFER) { | ||
431 | dev_info(&spi->dev, "GPIO requested is not here yet, deferring the probe\n"); | ||
432 | return -EPROBE_DEFER; | ||
433 | } | ||
434 | if (!gpio_is_valid(lcd->im_pins[i])) { | ||
435 | dev_err(&spi->dev, "Missing dt property: im-gpios\n"); | ||
436 | return -EINVAL; | ||
437 | } | ||
438 | |||
439 | ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i], | ||
440 | GPIOF_OUT_INIT_LOW, "im_pins"); | ||
441 | if (ret) { | ||
442 | dev_err(&spi->dev, "failed to request gpio %d: %d\n", | ||
443 | lcd->im_pins[i], ret); | ||
444 | return -EINVAL; | ||
445 | } | ||
446 | } | ||
447 | |||
448 | lcdev = lcd_device_register("mxsfb", &spi->dev, lcd, &hx8357_ops); | ||
449 | if (IS_ERR(lcdev)) { | ||
450 | ret = PTR_ERR(lcdev); | ||
451 | return ret; | ||
452 | } | ||
453 | spi_set_drvdata(spi, lcdev); | ||
454 | |||
455 | ret = hx8357_lcd_init(lcdev); | ||
456 | if (ret) { | ||
457 | dev_err(&spi->dev, "Couldn't initialize panel\n"); | ||
458 | goto init_error; | ||
459 | } | ||
460 | |||
461 | dev_info(&spi->dev, "Panel probed\n"); | ||
462 | |||
463 | return 0; | ||
464 | |||
465 | init_error: | ||
466 | lcd_device_unregister(lcdev); | ||
467 | return ret; | ||
468 | } | ||
469 | |||
470 | static int hx8357_remove(struct spi_device *spi) | ||
471 | { | ||
472 | struct lcd_device *lcdev = spi_get_drvdata(spi); | ||
473 | |||
474 | lcd_device_unregister(lcdev); | ||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static const struct of_device_id hx8357_dt_ids[] = { | ||
479 | { .compatible = "himax,hx8357" }, | ||
480 | {}, | ||
481 | }; | ||
482 | MODULE_DEVICE_TABLE(of, hx8357_dt_ids); | ||
483 | |||
484 | static struct spi_driver hx8357_driver = { | ||
485 | .probe = hx8357_probe, | ||
486 | .remove = hx8357_remove, | ||
487 | .driver = { | ||
488 | .name = "hx8357", | ||
489 | .of_match_table = of_match_ptr(hx8357_dt_ids), | ||
490 | }, | ||
491 | }; | ||
492 | |||
493 | module_spi_driver(hx8357_driver); | ||
494 | |||
495 | MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); | ||
496 | MODULE_DESCRIPTION("Himax HX-8357 LCD Driver"); | ||
497 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index 9a35196d12d7..fb6155771326 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c | |||
@@ -49,7 +49,7 @@ static void l4f00242t03_reset(unsigned int gpio) | |||
49 | static void l4f00242t03_lcd_init(struct spi_device *spi) | 49 | static void l4f00242t03_lcd_init(struct spi_device *spi) |
50 | { | 50 | { |
51 | struct l4f00242t03_pdata *pdata = spi->dev.platform_data; | 51 | struct l4f00242t03_pdata *pdata = spi->dev.platform_data; |
52 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); | 52 | struct l4f00242t03_priv *priv = spi_get_drvdata(spi); |
53 | const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) }; | 53 | const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) }; |
54 | 54 | ||
55 | dev_dbg(&spi->dev, "initializing LCD\n"); | 55 | dev_dbg(&spi->dev, "initializing LCD\n"); |
@@ -70,7 +70,7 @@ static void l4f00242t03_lcd_init(struct spi_device *spi) | |||
70 | static void l4f00242t03_lcd_powerdown(struct spi_device *spi) | 70 | static void l4f00242t03_lcd_powerdown(struct spi_device *spi) |
71 | { | 71 | { |
72 | struct l4f00242t03_pdata *pdata = spi->dev.platform_data; | 72 | struct l4f00242t03_pdata *pdata = spi->dev.platform_data; |
73 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); | 73 | struct l4f00242t03_priv *priv = spi_get_drvdata(spi); |
74 | 74 | ||
75 | dev_dbg(&spi->dev, "Powering down LCD\n"); | 75 | dev_dbg(&spi->dev, "Powering down LCD\n"); |
76 | 76 | ||
@@ -168,7 +168,7 @@ static int l4f00242t03_probe(struct spi_device *spi) | |||
168 | return -ENOMEM; | 168 | return -ENOMEM; |
169 | } | 169 | } |
170 | 170 | ||
171 | dev_set_drvdata(&spi->dev, priv); | 171 | spi_set_drvdata(spi, priv); |
172 | spi->bits_per_word = 9; | 172 | spi->bits_per_word = 9; |
173 | spi_setup(spi); | 173 | spi_setup(spi); |
174 | 174 | ||
@@ -190,27 +190,24 @@ static int l4f00242t03_probe(struct spi_device *spi) | |||
190 | return ret; | 190 | return ret; |
191 | } | 191 | } |
192 | 192 | ||
193 | priv->io_reg = regulator_get(&spi->dev, "vdd"); | 193 | priv->io_reg = devm_regulator_get(&spi->dev, "vdd"); |
194 | if (IS_ERR(priv->io_reg)) { | 194 | if (IS_ERR(priv->io_reg)) { |
195 | dev_err(&spi->dev, "%s: Unable to get the IO regulator\n", | 195 | dev_err(&spi->dev, "%s: Unable to get the IO regulator\n", |
196 | __func__); | 196 | __func__); |
197 | return PTR_ERR(priv->io_reg); | 197 | return PTR_ERR(priv->io_reg); |
198 | } | 198 | } |
199 | 199 | ||
200 | priv->core_reg = regulator_get(&spi->dev, "vcore"); | 200 | priv->core_reg = devm_regulator_get(&spi->dev, "vcore"); |
201 | if (IS_ERR(priv->core_reg)) { | 201 | if (IS_ERR(priv->core_reg)) { |
202 | ret = PTR_ERR(priv->core_reg); | ||
203 | dev_err(&spi->dev, "%s: Unable to get the core regulator\n", | 202 | dev_err(&spi->dev, "%s: Unable to get the core regulator\n", |
204 | __func__); | 203 | __func__); |
205 | goto err1; | 204 | return PTR_ERR(priv->core_reg); |
206 | } | 205 | } |
207 | 206 | ||
208 | priv->ld = lcd_device_register("l4f00242t03", | 207 | priv->ld = lcd_device_register("l4f00242t03", |
209 | &spi->dev, priv, &l4f_ops); | 208 | &spi->dev, priv, &l4f_ops); |
210 | if (IS_ERR(priv->ld)) { | 209 | if (IS_ERR(priv->ld)) |
211 | ret = PTR_ERR(priv->ld); | 210 | return PTR_ERR(priv->ld); |
212 | goto err2; | ||
213 | } | ||
214 | 211 | ||
215 | /* Init the LCD */ | 212 | /* Init the LCD */ |
216 | l4f00242t03_lcd_init(spi); | 213 | l4f00242t03_lcd_init(spi); |
@@ -220,33 +217,22 @@ static int l4f00242t03_probe(struct spi_device *spi) | |||
220 | dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n"); | 217 | dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n"); |
221 | 218 | ||
222 | return 0; | 219 | return 0; |
223 | |||
224 | err2: | ||
225 | regulator_put(priv->core_reg); | ||
226 | err1: | ||
227 | regulator_put(priv->io_reg); | ||
228 | |||
229 | return ret; | ||
230 | } | 220 | } |
231 | 221 | ||
232 | static int l4f00242t03_remove(struct spi_device *spi) | 222 | static int l4f00242t03_remove(struct spi_device *spi) |
233 | { | 223 | { |
234 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); | 224 | struct l4f00242t03_priv *priv = spi_get_drvdata(spi); |
235 | 225 | ||
236 | l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); | 226 | l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); |
237 | lcd_device_unregister(priv->ld); | 227 | lcd_device_unregister(priv->ld); |
238 | 228 | spi_set_drvdata(spi, NULL); | |
239 | dev_set_drvdata(&spi->dev, NULL); | ||
240 | |||
241 | regulator_put(priv->io_reg); | ||
242 | regulator_put(priv->core_reg); | ||
243 | 229 | ||
244 | return 0; | 230 | return 0; |
245 | } | 231 | } |
246 | 232 | ||
247 | static void l4f00242t03_shutdown(struct spi_device *spi) | 233 | static void l4f00242t03_shutdown(struct spi_device *spi) |
248 | { | 234 | { |
249 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); | 235 | struct l4f00242t03_priv *priv = spi_get_drvdata(spi); |
250 | 236 | ||
251 | if (priv) | 237 | if (priv) |
252 | l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); | 238 | l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); |
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c index 1cb352418513..1b642f5f381a 100644 --- a/drivers/video/backlight/ld9040.c +++ b/drivers/video/backlight/ld9040.c | |||
@@ -9,29 +9,20 @@ | |||
9 | * under the terms of the GNU General Public License as published by the | 9 | * under the terms of the GNU General Public License as published by the |
10 | * Free Software Foundation; either version 2 of the License, or (at your | 10 | * Free Software Foundation; either version 2 of the License, or (at your |
11 | * option) any later version. | 11 | * option) any later version. |
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | */ | 12 | */ |
22 | 13 | ||
23 | #include <linux/wait.h> | 14 | #include <linux/backlight.h> |
24 | #include <linux/fb.h> | ||
25 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/fb.h> | ||
26 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
27 | #include <linux/spi/spi.h> | ||
28 | #include <linux/irq.h> | ||
29 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/irq.h> | ||
30 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
31 | #include <linux/lcd.h> | 21 | #include <linux/lcd.h> |
32 | #include <linux/backlight.h> | ||
33 | #include <linux/module.h> | 22 | #include <linux/module.h> |
34 | #include <linux/regulator/consumer.h> | 23 | #include <linux/regulator/consumer.h> |
24 | #include <linux/spi/spi.h> | ||
25 | #include <linux/wait.h> | ||
35 | 26 | ||
36 | #include "ld9040_gamma.h" | 27 | #include "ld9040_gamma.h" |
37 | 28 | ||
@@ -43,7 +34,6 @@ | |||
43 | 34 | ||
44 | #define MIN_BRIGHTNESS 0 | 35 | #define MIN_BRIGHTNESS 0 |
45 | #define MAX_BRIGHTNESS 24 | 36 | #define MAX_BRIGHTNESS 24 |
46 | #define power_is_on(pwr) ((pwr) <= FB_BLANK_NORMAL) | ||
47 | 37 | ||
48 | struct ld9040 { | 38 | struct ld9040 { |
49 | struct device *dev; | 39 | struct device *dev; |
@@ -78,7 +68,7 @@ static void ld9040_regulator_enable(struct ld9040 *lcd) | |||
78 | 68 | ||
79 | lcd->enabled = true; | 69 | lcd->enabled = true; |
80 | } | 70 | } |
81 | mdelay(pd->power_on_delay); | 71 | msleep(pd->power_on_delay); |
82 | out: | 72 | out: |
83 | mutex_unlock(&lcd->lock); | 73 | mutex_unlock(&lcd->lock); |
84 | } | 74 | } |
@@ -474,8 +464,9 @@ static int ld9040_panel_send_sequence(struct ld9040 *lcd, | |||
474 | ret = ld9040_spi_write(lcd, wbuf[i], wbuf[i+1]); | 464 | ret = ld9040_spi_write(lcd, wbuf[i], wbuf[i+1]); |
475 | if (ret) | 465 | if (ret) |
476 | break; | 466 | break; |
477 | } else | 467 | } else { |
478 | udelay(wbuf[i+1]*1000); | 468 | msleep(wbuf[i+1]); |
469 | } | ||
479 | i += 2; | 470 | i += 2; |
480 | } | 471 | } |
481 | 472 | ||
@@ -513,14 +504,9 @@ gamma_err: | |||
513 | 504 | ||
514 | static int ld9040_gamma_ctl(struct ld9040 *lcd, int gamma) | 505 | static int ld9040_gamma_ctl(struct ld9040 *lcd, int gamma) |
515 | { | 506 | { |
516 | int ret = 0; | 507 | return _ld9040_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]); |
517 | |||
518 | ret = _ld9040_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]); | ||
519 | |||
520 | return ret; | ||
521 | } | 508 | } |
522 | 509 | ||
523 | |||
524 | static int ld9040_ldi_init(struct ld9040 *lcd) | 510 | static int ld9040_ldi_init(struct ld9040 *lcd) |
525 | { | 511 | { |
526 | int ret, i; | 512 | int ret, i; |
@@ -539,7 +525,7 @@ static int ld9040_ldi_init(struct ld9040 *lcd) | |||
539 | for (i = 0; i < ARRAY_SIZE(init_seq); i++) { | 525 | for (i = 0; i < ARRAY_SIZE(init_seq); i++) { |
540 | ret = ld9040_panel_send_sequence(lcd, init_seq[i]); | 526 | ret = ld9040_panel_send_sequence(lcd, init_seq[i]); |
541 | /* workaround: minimum delay time for transferring CMD */ | 527 | /* workaround: minimum delay time for transferring CMD */ |
542 | udelay(300); | 528 | usleep_range(300, 310); |
543 | if (ret) | 529 | if (ret) |
544 | break; | 530 | break; |
545 | } | 531 | } |
@@ -549,11 +535,7 @@ static int ld9040_ldi_init(struct ld9040 *lcd) | |||
549 | 535 | ||
550 | static int ld9040_ldi_enable(struct ld9040 *lcd) | 536 | static int ld9040_ldi_enable(struct ld9040 *lcd) |
551 | { | 537 | { |
552 | int ret = 0; | 538 | return ld9040_panel_send_sequence(lcd, seq_display_on); |
553 | |||
554 | ret = ld9040_panel_send_sequence(lcd, seq_display_on); | ||
555 | |||
556 | return ret; | ||
557 | } | 539 | } |
558 | 540 | ||
559 | static int ld9040_ldi_disable(struct ld9040 *lcd) | 541 | static int ld9040_ldi_disable(struct ld9040 *lcd) |
@@ -566,25 +548,27 @@ static int ld9040_ldi_disable(struct ld9040 *lcd) | |||
566 | return ret; | 548 | return ret; |
567 | } | 549 | } |
568 | 550 | ||
551 | static int ld9040_power_is_on(int power) | ||
552 | { | ||
553 | return power <= FB_BLANK_NORMAL; | ||
554 | } | ||
555 | |||
569 | static int ld9040_power_on(struct ld9040 *lcd) | 556 | static int ld9040_power_on(struct ld9040 *lcd) |
570 | { | 557 | { |
571 | int ret = 0; | 558 | int ret = 0; |
572 | struct lcd_platform_data *pd = NULL; | 559 | struct lcd_platform_data *pd; |
560 | |||
573 | pd = lcd->lcd_pd; | 561 | pd = lcd->lcd_pd; |
574 | if (!pd) { | ||
575 | dev_err(lcd->dev, "platform data is NULL.\n"); | ||
576 | return -EFAULT; | ||
577 | } | ||
578 | 562 | ||
579 | /* lcd power on */ | 563 | /* lcd power on */ |
580 | ld9040_regulator_enable(lcd); | 564 | ld9040_regulator_enable(lcd); |
581 | 565 | ||
582 | if (!pd->reset) { | 566 | if (!pd->reset) { |
583 | dev_err(lcd->dev, "reset is NULL.\n"); | 567 | dev_err(lcd->dev, "reset is NULL.\n"); |
584 | return -EFAULT; | 568 | return -EINVAL; |
585 | } else { | 569 | } else { |
586 | pd->reset(lcd->ld); | 570 | pd->reset(lcd->ld); |
587 | mdelay(pd->reset_delay); | 571 | msleep(pd->reset_delay); |
588 | } | 572 | } |
589 | 573 | ||
590 | ret = ld9040_ldi_init(lcd); | 574 | ret = ld9040_ldi_init(lcd); |
@@ -604,14 +588,10 @@ static int ld9040_power_on(struct ld9040 *lcd) | |||
604 | 588 | ||
605 | static int ld9040_power_off(struct ld9040 *lcd) | 589 | static int ld9040_power_off(struct ld9040 *lcd) |
606 | { | 590 | { |
607 | int ret = 0; | 591 | int ret; |
608 | struct lcd_platform_data *pd = NULL; | 592 | struct lcd_platform_data *pd; |
609 | 593 | ||
610 | pd = lcd->lcd_pd; | 594 | pd = lcd->lcd_pd; |
611 | if (!pd) { | ||
612 | dev_err(lcd->dev, "platform data is NULL.\n"); | ||
613 | return -EFAULT; | ||
614 | } | ||
615 | 595 | ||
616 | ret = ld9040_ldi_disable(lcd); | 596 | ret = ld9040_ldi_disable(lcd); |
617 | if (ret) { | 597 | if (ret) { |
@@ -619,7 +599,7 @@ static int ld9040_power_off(struct ld9040 *lcd) | |||
619 | return -EIO; | 599 | return -EIO; |
620 | } | 600 | } |
621 | 601 | ||
622 | mdelay(pd->power_off_delay); | 602 | msleep(pd->power_off_delay); |
623 | 603 | ||
624 | /* lcd power off */ | 604 | /* lcd power off */ |
625 | ld9040_regulator_disable(lcd); | 605 | ld9040_regulator_disable(lcd); |
@@ -631,9 +611,9 @@ static int ld9040_power(struct ld9040 *lcd, int power) | |||
631 | { | 611 | { |
632 | int ret = 0; | 612 | int ret = 0; |
633 | 613 | ||
634 | if (power_is_on(power) && !power_is_on(lcd->power)) | 614 | if (ld9040_power_is_on(power) && !ld9040_power_is_on(lcd->power)) |
635 | ret = ld9040_power_on(lcd); | 615 | ret = ld9040_power_on(lcd); |
636 | else if (!power_is_on(power) && power_is_on(lcd->power)) | 616 | else if (!ld9040_power_is_on(power) && ld9040_power_is_on(lcd->power)) |
637 | ret = ld9040_power_off(lcd); | 617 | ret = ld9040_power_off(lcd); |
638 | 618 | ||
639 | if (!ret) | 619 | if (!ret) |
@@ -698,7 +678,6 @@ static const struct backlight_ops ld9040_backlight_ops = { | |||
698 | .update_status = ld9040_set_brightness, | 678 | .update_status = ld9040_set_brightness, |
699 | }; | 679 | }; |
700 | 680 | ||
701 | |||
702 | static int ld9040_probe(struct spi_device *spi) | 681 | static int ld9040_probe(struct spi_device *spi) |
703 | { | 682 | { |
704 | int ret = 0; | 683 | int ret = 0; |
@@ -726,22 +705,20 @@ static int ld9040_probe(struct spi_device *spi) | |||
726 | lcd->lcd_pd = spi->dev.platform_data; | 705 | lcd->lcd_pd = spi->dev.platform_data; |
727 | if (!lcd->lcd_pd) { | 706 | if (!lcd->lcd_pd) { |
728 | dev_err(&spi->dev, "platform data is NULL.\n"); | 707 | dev_err(&spi->dev, "platform data is NULL.\n"); |
729 | return -EFAULT; | 708 | return -EINVAL; |
730 | } | 709 | } |
731 | 710 | ||
732 | mutex_init(&lcd->lock); | 711 | mutex_init(&lcd->lock); |
733 | 712 | ||
734 | ret = regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies); | 713 | ret = devm_regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies); |
735 | if (ret) { | 714 | if (ret) { |
736 | dev_err(lcd->dev, "Failed to get regulators: %d\n", ret); | 715 | dev_err(lcd->dev, "Failed to get regulators: %d\n", ret); |
737 | return ret; | 716 | return ret; |
738 | } | 717 | } |
739 | 718 | ||
740 | ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops); | 719 | ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops); |
741 | if (IS_ERR(ld)) { | 720 | if (IS_ERR(ld)) |
742 | ret = PTR_ERR(ld); | 721 | return PTR_ERR(ld); |
743 | goto out_free_regulator; | ||
744 | } | ||
745 | 722 | ||
746 | lcd->ld = ld; | 723 | lcd->ld = ld; |
747 | 724 | ||
@@ -772,30 +749,28 @@ static int ld9040_probe(struct spi_device *spi) | |||
772 | lcd->power = FB_BLANK_POWERDOWN; | 749 | lcd->power = FB_BLANK_POWERDOWN; |
773 | 750 | ||
774 | ld9040_power(lcd, FB_BLANK_UNBLANK); | 751 | ld9040_power(lcd, FB_BLANK_UNBLANK); |
775 | } else | 752 | } else { |
776 | lcd->power = FB_BLANK_UNBLANK; | 753 | lcd->power = FB_BLANK_UNBLANK; |
754 | } | ||
777 | 755 | ||
778 | dev_set_drvdata(&spi->dev, lcd); | 756 | spi_set_drvdata(spi, lcd); |
779 | 757 | ||
780 | dev_info(&spi->dev, "ld9040 panel driver has been probed.\n"); | 758 | dev_info(&spi->dev, "ld9040 panel driver has been probed.\n"); |
781 | return 0; | 759 | return 0; |
782 | 760 | ||
783 | out_unregister_lcd: | 761 | out_unregister_lcd: |
784 | lcd_device_unregister(lcd->ld); | 762 | lcd_device_unregister(lcd->ld); |
785 | out_free_regulator: | ||
786 | regulator_bulk_free(ARRAY_SIZE(supplies), supplies); | ||
787 | 763 | ||
788 | return ret; | 764 | return ret; |
789 | } | 765 | } |
790 | 766 | ||
791 | static int ld9040_remove(struct spi_device *spi) | 767 | static int ld9040_remove(struct spi_device *spi) |
792 | { | 768 | { |
793 | struct ld9040 *lcd = dev_get_drvdata(&spi->dev); | 769 | struct ld9040 *lcd = spi_get_drvdata(spi); |
794 | 770 | ||
795 | ld9040_power(lcd, FB_BLANK_POWERDOWN); | 771 | ld9040_power(lcd, FB_BLANK_POWERDOWN); |
796 | backlight_device_unregister(lcd->bd); | 772 | backlight_device_unregister(lcd->bd); |
797 | lcd_device_unregister(lcd->ld); | 773 | lcd_device_unregister(lcd->ld); |
798 | regulator_bulk_free(ARRAY_SIZE(supplies), supplies); | ||
799 | 774 | ||
800 | return 0; | 775 | return 0; |
801 | } | 776 | } |
@@ -803,8 +778,7 @@ static int ld9040_remove(struct spi_device *spi) | |||
803 | #if defined(CONFIG_PM) | 778 | #if defined(CONFIG_PM) |
804 | static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg) | 779 | static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg) |
805 | { | 780 | { |
806 | int ret = 0; | 781 | struct ld9040 *lcd = spi_get_drvdata(spi); |
807 | struct ld9040 *lcd = dev_get_drvdata(&spi->dev); | ||
808 | 782 | ||
809 | dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); | 783 | dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); |
810 | 784 | ||
@@ -812,21 +786,16 @@ static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg) | |||
812 | * when lcd panel is suspend, lcd panel becomes off | 786 | * when lcd panel is suspend, lcd panel becomes off |
813 | * regardless of status. | 787 | * regardless of status. |
814 | */ | 788 | */ |
815 | ret = ld9040_power(lcd, FB_BLANK_POWERDOWN); | 789 | return ld9040_power(lcd, FB_BLANK_POWERDOWN); |
816 | |||
817 | return ret; | ||
818 | } | 790 | } |
819 | 791 | ||
820 | static int ld9040_resume(struct spi_device *spi) | 792 | static int ld9040_resume(struct spi_device *spi) |
821 | { | 793 | { |
822 | int ret = 0; | 794 | struct ld9040 *lcd = spi_get_drvdata(spi); |
823 | struct ld9040 *lcd = dev_get_drvdata(&spi->dev); | ||
824 | 795 | ||
825 | lcd->power = FB_BLANK_POWERDOWN; | 796 | lcd->power = FB_BLANK_POWERDOWN; |
826 | 797 | ||
827 | ret = ld9040_power(lcd, FB_BLANK_UNBLANK); | 798 | return ld9040_power(lcd, FB_BLANK_UNBLANK); |
828 | |||
829 | return ret; | ||
830 | } | 799 | } |
831 | #else | 800 | #else |
832 | #define ld9040_suspend NULL | 801 | #define ld9040_suspend NULL |
@@ -836,7 +805,7 @@ static int ld9040_resume(struct spi_device *spi) | |||
836 | /* Power down all displays on reboot, poweroff or halt. */ | 805 | /* Power down all displays on reboot, poweroff or halt. */ |
837 | static void ld9040_shutdown(struct spi_device *spi) | 806 | static void ld9040_shutdown(struct spi_device *spi) |
838 | { | 807 | { |
839 | struct ld9040 *lcd = dev_get_drvdata(&spi->dev); | 808 | struct ld9040 *lcd = spi_get_drvdata(spi); |
840 | 809 | ||
841 | ld9040_power(lcd, FB_BLANK_POWERDOWN); | 810 | ld9040_power(lcd, FB_BLANK_POWERDOWN); |
842 | } | 811 | } |
diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c index a6d637b5c68f..76a62e978fc3 100644 --- a/drivers/video/backlight/lm3630_bl.c +++ b/drivers/video/backlight/lm3630_bl.c | |||
@@ -320,7 +320,7 @@ static int lm3630_backlight_register(struct lm3630_chip_data *pchip, | |||
320 | backlight_device_register(name, pchip->dev, pchip, | 320 | backlight_device_register(name, pchip->dev, pchip, |
321 | &lm3630_bank_a_ops, &props); | 321 | &lm3630_bank_a_ops, &props); |
322 | if (IS_ERR(pchip->bled1)) | 322 | if (IS_ERR(pchip->bled1)) |
323 | return -EIO; | 323 | return PTR_ERR(pchip->bled1); |
324 | break; | 324 | break; |
325 | case BLED_2: | 325 | case BLED_2: |
326 | props.brightness = pdata->init_brt_led2; | 326 | props.brightness = pdata->init_brt_led2; |
@@ -329,7 +329,7 @@ static int lm3630_backlight_register(struct lm3630_chip_data *pchip, | |||
329 | backlight_device_register(name, pchip->dev, pchip, | 329 | backlight_device_register(name, pchip->dev, pchip, |
330 | &lm3630_bank_b_ops, &props); | 330 | &lm3630_bank_b_ops, &props); |
331 | if (IS_ERR(pchip->bled2)) | 331 | if (IS_ERR(pchip->bled2)) |
332 | return -EIO; | 332 | return PTR_ERR(pchip->bled2); |
333 | break; | 333 | break; |
334 | } | 334 | } |
335 | return 0; | 335 | return 0; |
diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c index 7ab2d2a04e41..053964da8dd3 100644 --- a/drivers/video/backlight/lm3639_bl.c +++ b/drivers/video/backlight/lm3639_bl.c | |||
@@ -350,14 +350,13 @@ static int lm3639_probe(struct i2c_client *client, | |||
350 | &lm3639_bled_ops, &props); | 350 | &lm3639_bled_ops, &props); |
351 | if (IS_ERR(pchip->bled)) { | 351 | if (IS_ERR(pchip->bled)) { |
352 | dev_err(&client->dev, "fail : backlight register\n"); | 352 | dev_err(&client->dev, "fail : backlight register\n"); |
353 | ret = -EIO; | 353 | ret = PTR_ERR(pchip->bled); |
354 | goto err_out; | 354 | goto err_out; |
355 | } | 355 | } |
356 | 356 | ||
357 | ret = device_create_file(&(pchip->bled->dev), &dev_attr_bled_mode); | 357 | ret = device_create_file(&(pchip->bled->dev), &dev_attr_bled_mode); |
358 | if (ret < 0) { | 358 | if (ret < 0) { |
359 | dev_err(&client->dev, "failed : add sysfs entries\n"); | 359 | dev_err(&client->dev, "failed : add sysfs entries\n"); |
360 | ret = -EIO; | ||
361 | goto err_bled_mode; | 360 | goto err_bled_mode; |
362 | } | 361 | } |
363 | 362 | ||
@@ -369,7 +368,6 @@ static int lm3639_probe(struct i2c_client *client, | |||
369 | &client->dev, &pchip->cdev_flash); | 368 | &client->dev, &pchip->cdev_flash); |
370 | if (ret < 0) { | 369 | if (ret < 0) { |
371 | dev_err(&client->dev, "fail : flash register\n"); | 370 | dev_err(&client->dev, "fail : flash register\n"); |
372 | ret = -EIO; | ||
373 | goto err_flash; | 371 | goto err_flash; |
374 | } | 372 | } |
375 | 373 | ||
@@ -381,7 +379,6 @@ static int lm3639_probe(struct i2c_client *client, | |||
381 | &client->dev, &pchip->cdev_torch); | 379 | &client->dev, &pchip->cdev_torch); |
382 | if (ret < 0) { | 380 | if (ret < 0) { |
383 | dev_err(&client->dev, "fail : torch register\n"); | 381 | dev_err(&client->dev, "fail : torch register\n"); |
384 | ret = -EIO; | ||
385 | goto err_torch; | 382 | goto err_torch; |
386 | } | 383 | } |
387 | 384 | ||
diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c index 55819b384701..4eec47261cd3 100644 --- a/drivers/video/backlight/lms283gf05.c +++ b/drivers/video/backlight/lms283gf05.c | |||
@@ -180,7 +180,7 @@ static int lms283gf05_probe(struct spi_device *spi) | |||
180 | st->spi = spi; | 180 | st->spi = spi; |
181 | st->ld = ld; | 181 | st->ld = ld; |
182 | 182 | ||
183 | dev_set_drvdata(&spi->dev, st); | 183 | spi_set_drvdata(spi, st); |
184 | 184 | ||
185 | /* kick in the LCD */ | 185 | /* kick in the LCD */ |
186 | if (pdata) | 186 | if (pdata) |
@@ -192,7 +192,7 @@ static int lms283gf05_probe(struct spi_device *spi) | |||
192 | 192 | ||
193 | static int lms283gf05_remove(struct spi_device *spi) | 193 | static int lms283gf05_remove(struct spi_device *spi) |
194 | { | 194 | { |
195 | struct lms283gf05_state *st = dev_get_drvdata(&spi->dev); | 195 | struct lms283gf05_state *st = spi_get_drvdata(spi); |
196 | 196 | ||
197 | lcd_device_unregister(st->ld); | 197 | lcd_device_unregister(st->ld); |
198 | 198 | ||
diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c new file mode 100644 index 000000000000..b43882abefaf --- /dev/null +++ b/drivers/video/backlight/lms501kf03.c | |||
@@ -0,0 +1,441 @@ | |||
1 | /* | ||
2 | * lms501kf03 TFT LCD panel driver. | ||
3 | * | ||
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
5 | * Author: Jingoo Han <jg1.han@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/backlight.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/fb.h> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/lcd.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/spi/spi.h> | ||
20 | #include <linux/wait.h> | ||
21 | |||
22 | #define COMMAND_ONLY 0x00 | ||
23 | #define DATA_ONLY 0x01 | ||
24 | |||
25 | struct lms501kf03 { | ||
26 | struct device *dev; | ||
27 | struct spi_device *spi; | ||
28 | unsigned int power; | ||
29 | struct lcd_device *ld; | ||
30 | struct lcd_platform_data *lcd_pd; | ||
31 | }; | ||
32 | |||
33 | static const unsigned char seq_password[] = { | ||
34 | 0xb9, 0xff, 0x83, 0x69, | ||
35 | }; | ||
36 | |||
37 | static const unsigned char seq_power[] = { | ||
38 | 0xb1, 0x01, 0x00, 0x34, 0x06, 0x00, 0x14, 0x14, 0x20, 0x28, | ||
39 | 0x12, 0x12, 0x17, 0x0a, 0x01, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, | ||
40 | }; | ||
41 | |||
42 | static const unsigned char seq_display[] = { | ||
43 | 0xb2, 0x00, 0x2b, 0x03, 0x03, 0x70, 0x00, 0xff, 0x00, 0x00, | ||
44 | 0x00, 0x00, 0x03, 0x03, 0x00, 0x01, | ||
45 | }; | ||
46 | |||
47 | static const unsigned char seq_rgb_if[] = { | ||
48 | 0xb3, 0x09, | ||
49 | }; | ||
50 | |||
51 | static const unsigned char seq_display_inv[] = { | ||
52 | 0xb4, 0x01, 0x08, 0x77, 0x0e, 0x06, | ||
53 | }; | ||
54 | |||
55 | static const unsigned char seq_vcom[] = { | ||
56 | 0xb6, 0x4c, 0x2e, | ||
57 | }; | ||
58 | |||
59 | static const unsigned char seq_gate[] = { | ||
60 | 0xd5, 0x00, 0x05, 0x03, 0x29, 0x01, 0x07, 0x17, 0x68, 0x13, | ||
61 | 0x37, 0x20, 0x31, 0x8a, 0x46, 0x9b, 0x57, 0x13, 0x02, 0x75, | ||
62 | 0xb9, 0x64, 0xa8, 0x07, 0x0f, 0x04, 0x07, | ||
63 | }; | ||
64 | |||
65 | static const unsigned char seq_panel[] = { | ||
66 | 0xcc, 0x02, | ||
67 | }; | ||
68 | |||
69 | static const unsigned char seq_col_mod[] = { | ||
70 | 0x3a, 0x77, | ||
71 | }; | ||
72 | |||
73 | static const unsigned char seq_w_gamma[] = { | ||
74 | 0xe0, 0x00, 0x04, 0x09, 0x0f, 0x1f, 0x3f, 0x1f, 0x2f, 0x0a, | ||
75 | 0x0f, 0x10, 0x16, 0x18, 0x16, 0x17, 0x0d, 0x15, 0x00, 0x04, | ||
76 | 0x09, 0x0f, 0x38, 0x3f, 0x20, 0x39, 0x0a, 0x0f, 0x10, 0x16, | ||
77 | 0x18, 0x16, 0x17, 0x0d, 0x15, | ||
78 | }; | ||
79 | |||
80 | static const unsigned char seq_rgb_gamma[] = { | ||
81 | 0xc1, 0x01, 0x03, 0x07, 0x0f, 0x1a, 0x22, 0x2c, 0x33, 0x3c, | ||
82 | 0x46, 0x4f, 0x58, 0x60, 0x69, 0x71, 0x79, 0x82, 0x89, 0x92, | ||
83 | 0x9a, 0xa1, 0xa9, 0xb1, 0xb9, 0xc1, 0xc9, 0xcf, 0xd6, 0xde, | ||
84 | 0xe5, 0xec, 0xf3, 0xf9, 0xff, 0xdd, 0x39, 0x07, 0x1c, 0xcb, | ||
85 | 0xab, 0x5f, 0x49, 0x80, 0x03, 0x07, 0x0f, 0x19, 0x20, 0x2a, | ||
86 | 0x31, 0x39, 0x42, 0x4b, 0x53, 0x5b, 0x63, 0x6b, 0x73, 0x7b, | ||
87 | 0x83, 0x8a, 0x92, 0x9b, 0xa2, 0xaa, 0xb2, 0xba, 0xc2, 0xca, | ||
88 | 0xd0, 0xd8, 0xe1, 0xe8, 0xf0, 0xf8, 0xff, 0xf7, 0xd8, 0xbe, | ||
89 | 0xa7, 0x39, 0x40, 0x85, 0x8c, 0xc0, 0x04, 0x07, 0x0c, 0x17, | ||
90 | 0x1c, 0x23, 0x2b, 0x34, 0x3b, 0x43, 0x4c, 0x54, 0x5b, 0x63, | ||
91 | 0x6a, 0x73, 0x7a, 0x82, 0x8a, 0x91, 0x98, 0xa1, 0xa8, 0xb0, | ||
92 | 0xb7, 0xc1, 0xc9, 0xcf, 0xd9, 0xe3, 0xea, 0xf4, 0xff, 0x00, | ||
93 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
94 | }; | ||
95 | |||
96 | static const unsigned char seq_up_dn[] = { | ||
97 | 0x36, 0x10, | ||
98 | }; | ||
99 | |||
100 | static const unsigned char seq_sleep_in[] = { | ||
101 | 0x10, | ||
102 | }; | ||
103 | |||
104 | static const unsigned char seq_sleep_out[] = { | ||
105 | 0x11, | ||
106 | }; | ||
107 | |||
108 | static const unsigned char seq_display_on[] = { | ||
109 | 0x29, | ||
110 | }; | ||
111 | |||
112 | static const unsigned char seq_display_off[] = { | ||
113 | 0x10, | ||
114 | }; | ||
115 | |||
116 | static int lms501kf03_spi_write_byte(struct lms501kf03 *lcd, int addr, int data) | ||
117 | { | ||
118 | u16 buf[1]; | ||
119 | struct spi_message msg; | ||
120 | |||
121 | struct spi_transfer xfer = { | ||
122 | .len = 2, | ||
123 | .tx_buf = buf, | ||
124 | }; | ||
125 | |||
126 | buf[0] = (addr << 8) | data; | ||
127 | |||
128 | spi_message_init(&msg); | ||
129 | spi_message_add_tail(&xfer, &msg); | ||
130 | |||
131 | return spi_sync(lcd->spi, &msg); | ||
132 | } | ||
133 | |||
134 | static int lms501kf03_spi_write(struct lms501kf03 *lcd, unsigned char address, | ||
135 | unsigned char command) | ||
136 | { | ||
137 | return lms501kf03_spi_write_byte(lcd, address, command); | ||
138 | } | ||
139 | |||
140 | static int lms501kf03_panel_send_sequence(struct lms501kf03 *lcd, | ||
141 | const unsigned char *wbuf, | ||
142 | unsigned int len) | ||
143 | { | ||
144 | int ret = 0, i = 0; | ||
145 | |||
146 | while (i < len) { | ||
147 | if (i == 0) | ||
148 | ret = lms501kf03_spi_write(lcd, COMMAND_ONLY, wbuf[i]); | ||
149 | else | ||
150 | ret = lms501kf03_spi_write(lcd, DATA_ONLY, wbuf[i]); | ||
151 | if (ret) | ||
152 | break; | ||
153 | i += 1; | ||
154 | } | ||
155 | |||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | static int lms501kf03_ldi_init(struct lms501kf03 *lcd) | ||
160 | { | ||
161 | int ret, i; | ||
162 | static const unsigned char *init_seq[] = { | ||
163 | seq_password, | ||
164 | seq_power, | ||
165 | seq_display, | ||
166 | seq_rgb_if, | ||
167 | seq_display_inv, | ||
168 | seq_vcom, | ||
169 | seq_gate, | ||
170 | seq_panel, | ||
171 | seq_col_mod, | ||
172 | seq_w_gamma, | ||
173 | seq_rgb_gamma, | ||
174 | seq_sleep_out, | ||
175 | }; | ||
176 | |||
177 | static const unsigned int size_seq[] = { | ||
178 | ARRAY_SIZE(seq_password), | ||
179 | ARRAY_SIZE(seq_power), | ||
180 | ARRAY_SIZE(seq_display), | ||
181 | ARRAY_SIZE(seq_rgb_if), | ||
182 | ARRAY_SIZE(seq_display_inv), | ||
183 | ARRAY_SIZE(seq_vcom), | ||
184 | ARRAY_SIZE(seq_gate), | ||
185 | ARRAY_SIZE(seq_panel), | ||
186 | ARRAY_SIZE(seq_col_mod), | ||
187 | ARRAY_SIZE(seq_w_gamma), | ||
188 | ARRAY_SIZE(seq_rgb_gamma), | ||
189 | ARRAY_SIZE(seq_sleep_out), | ||
190 | }; | ||
191 | |||
192 | for (i = 0; i < ARRAY_SIZE(init_seq); i++) { | ||
193 | ret = lms501kf03_panel_send_sequence(lcd, init_seq[i], | ||
194 | size_seq[i]); | ||
195 | if (ret) | ||
196 | break; | ||
197 | } | ||
198 | /* | ||
199 | * According to the datasheet, 120ms delay time is required. | ||
200 | * After sleep out sequence, command is blocked for 120ms. | ||
201 | * Thus, LDI should wait for 120ms. | ||
202 | */ | ||
203 | msleep(120); | ||
204 | |||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | static int lms501kf03_ldi_enable(struct lms501kf03 *lcd) | ||
209 | { | ||
210 | return lms501kf03_panel_send_sequence(lcd, seq_display_on, | ||
211 | ARRAY_SIZE(seq_display_on)); | ||
212 | } | ||
213 | |||
214 | static int lms501kf03_ldi_disable(struct lms501kf03 *lcd) | ||
215 | { | ||
216 | return lms501kf03_panel_send_sequence(lcd, seq_display_off, | ||
217 | ARRAY_SIZE(seq_display_off)); | ||
218 | } | ||
219 | |||
220 | static int lms501kf03_power_is_on(int power) | ||
221 | { | ||
222 | return (power) <= FB_BLANK_NORMAL; | ||
223 | } | ||
224 | |||
225 | static int lms501kf03_power_on(struct lms501kf03 *lcd) | ||
226 | { | ||
227 | int ret = 0; | ||
228 | struct lcd_platform_data *pd; | ||
229 | |||
230 | pd = lcd->lcd_pd; | ||
231 | |||
232 | if (!pd->power_on) { | ||
233 | dev_err(lcd->dev, "power_on is NULL.\n"); | ||
234 | return -EINVAL; | ||
235 | } else { | ||
236 | pd->power_on(lcd->ld, 1); | ||
237 | msleep(pd->power_on_delay); | ||
238 | } | ||
239 | |||
240 | if (!pd->reset) { | ||
241 | dev_err(lcd->dev, "reset is NULL.\n"); | ||
242 | return -EINVAL; | ||
243 | } else { | ||
244 | pd->reset(lcd->ld); | ||
245 | msleep(pd->reset_delay); | ||
246 | } | ||
247 | |||
248 | ret = lms501kf03_ldi_init(lcd); | ||
249 | if (ret) { | ||
250 | dev_err(lcd->dev, "failed to initialize ldi.\n"); | ||
251 | return ret; | ||
252 | } | ||
253 | |||
254 | ret = lms501kf03_ldi_enable(lcd); | ||
255 | if (ret) { | ||
256 | dev_err(lcd->dev, "failed to enable ldi.\n"); | ||
257 | return ret; | ||
258 | } | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static int lms501kf03_power_off(struct lms501kf03 *lcd) | ||
264 | { | ||
265 | int ret = 0; | ||
266 | struct lcd_platform_data *pd; | ||
267 | |||
268 | pd = lcd->lcd_pd; | ||
269 | |||
270 | ret = lms501kf03_ldi_disable(lcd); | ||
271 | if (ret) { | ||
272 | dev_err(lcd->dev, "lcd setting failed.\n"); | ||
273 | return -EIO; | ||
274 | } | ||
275 | |||
276 | msleep(pd->power_off_delay); | ||
277 | |||
278 | pd->power_on(lcd->ld, 0); | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int lms501kf03_power(struct lms501kf03 *lcd, int power) | ||
284 | { | ||
285 | int ret = 0; | ||
286 | |||
287 | if (lms501kf03_power_is_on(power) && | ||
288 | !lms501kf03_power_is_on(lcd->power)) | ||
289 | ret = lms501kf03_power_on(lcd); | ||
290 | else if (!lms501kf03_power_is_on(power) && | ||
291 | lms501kf03_power_is_on(lcd->power)) | ||
292 | ret = lms501kf03_power_off(lcd); | ||
293 | |||
294 | if (!ret) | ||
295 | lcd->power = power; | ||
296 | |||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | static int lms501kf03_get_power(struct lcd_device *ld) | ||
301 | { | ||
302 | struct lms501kf03 *lcd = lcd_get_data(ld); | ||
303 | |||
304 | return lcd->power; | ||
305 | } | ||
306 | |||
307 | static int lms501kf03_set_power(struct lcd_device *ld, int power) | ||
308 | { | ||
309 | struct lms501kf03 *lcd = lcd_get_data(ld); | ||
310 | |||
311 | if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && | ||
312 | power != FB_BLANK_NORMAL) { | ||
313 | dev_err(lcd->dev, "power value should be 0, 1 or 4.\n"); | ||
314 | return -EINVAL; | ||
315 | } | ||
316 | |||
317 | return lms501kf03_power(lcd, power); | ||
318 | } | ||
319 | |||
320 | static struct lcd_ops lms501kf03_lcd_ops = { | ||
321 | .get_power = lms501kf03_get_power, | ||
322 | .set_power = lms501kf03_set_power, | ||
323 | }; | ||
324 | |||
325 | static int lms501kf03_probe(struct spi_device *spi) | ||
326 | { | ||
327 | struct lms501kf03 *lcd = NULL; | ||
328 | struct lcd_device *ld = NULL; | ||
329 | int ret = 0; | ||
330 | |||
331 | lcd = devm_kzalloc(&spi->dev, sizeof(struct lms501kf03), GFP_KERNEL); | ||
332 | if (!lcd) | ||
333 | return -ENOMEM; | ||
334 | |||
335 | /* lms501kf03 lcd panel uses 3-wire 9-bit SPI Mode. */ | ||
336 | spi->bits_per_word = 9; | ||
337 | |||
338 | ret = spi_setup(spi); | ||
339 | if (ret < 0) { | ||
340 | dev_err(&spi->dev, "spi setup failed.\n"); | ||
341 | return ret; | ||
342 | } | ||
343 | |||
344 | lcd->spi = spi; | ||
345 | lcd->dev = &spi->dev; | ||
346 | |||
347 | lcd->lcd_pd = spi->dev.platform_data; | ||
348 | if (!lcd->lcd_pd) { | ||
349 | dev_err(&spi->dev, "platform data is NULL\n"); | ||
350 | return -EINVAL; | ||
351 | } | ||
352 | |||
353 | ld = lcd_device_register("lms501kf03", &spi->dev, lcd, | ||
354 | &lms501kf03_lcd_ops); | ||
355 | if (IS_ERR(ld)) | ||
356 | return PTR_ERR(ld); | ||
357 | |||
358 | lcd->ld = ld; | ||
359 | |||
360 | if (!lcd->lcd_pd->lcd_enabled) { | ||
361 | /* | ||
362 | * if lcd panel was off from bootloader then | ||
363 | * current lcd status is powerdown and then | ||
364 | * it enables lcd panel. | ||
365 | */ | ||
366 | lcd->power = FB_BLANK_POWERDOWN; | ||
367 | |||
368 | lms501kf03_power(lcd, FB_BLANK_UNBLANK); | ||
369 | } else { | ||
370 | lcd->power = FB_BLANK_UNBLANK; | ||
371 | } | ||
372 | |||
373 | spi_set_drvdata(spi, lcd); | ||
374 | |||
375 | dev_info(&spi->dev, "lms501kf03 panel driver has been probed.\n"); | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static int lms501kf03_remove(struct spi_device *spi) | ||
381 | { | ||
382 | struct lms501kf03 *lcd = spi_get_drvdata(spi); | ||
383 | |||
384 | lms501kf03_power(lcd, FB_BLANK_POWERDOWN); | ||
385 | lcd_device_unregister(lcd->ld); | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | #if defined(CONFIG_PM) | ||
391 | |||
392 | static int lms501kf03_suspend(struct spi_device *spi, pm_message_t mesg) | ||
393 | { | ||
394 | struct lms501kf03 *lcd = spi_get_drvdata(spi); | ||
395 | |||
396 | dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); | ||
397 | |||
398 | /* | ||
399 | * when lcd panel is suspend, lcd panel becomes off | ||
400 | * regardless of status. | ||
401 | */ | ||
402 | return lms501kf03_power(lcd, FB_BLANK_POWERDOWN); | ||
403 | } | ||
404 | |||
405 | static int lms501kf03_resume(struct spi_device *spi) | ||
406 | { | ||
407 | struct lms501kf03 *lcd = spi_get_drvdata(spi); | ||
408 | |||
409 | lcd->power = FB_BLANK_POWERDOWN; | ||
410 | |||
411 | return lms501kf03_power(lcd, FB_BLANK_UNBLANK); | ||
412 | } | ||
413 | #else | ||
414 | #define lms501kf03_suspend NULL | ||
415 | #define lms501kf03_resume NULL | ||
416 | #endif | ||
417 | |||
418 | static void lms501kf03_shutdown(struct spi_device *spi) | ||
419 | { | ||
420 | struct lms501kf03 *lcd = spi_get_drvdata(spi); | ||
421 | |||
422 | lms501kf03_power(lcd, FB_BLANK_POWERDOWN); | ||
423 | } | ||
424 | |||
425 | static struct spi_driver lms501kf03_driver = { | ||
426 | .driver = { | ||
427 | .name = "lms501kf03", | ||
428 | .owner = THIS_MODULE, | ||
429 | }, | ||
430 | .probe = lms501kf03_probe, | ||
431 | .remove = lms501kf03_remove, | ||
432 | .shutdown = lms501kf03_shutdown, | ||
433 | .suspend = lms501kf03_suspend, | ||
434 | .resume = lms501kf03_resume, | ||
435 | }; | ||
436 | |||
437 | module_spi_driver(lms501kf03_driver); | ||
438 | |||
439 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); | ||
440 | MODULE_DESCRIPTION("lms501kf03 LCD Driver"); | ||
441 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index 6e4db0c874c8..7ae9ae6f4655 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c | |||
@@ -17,21 +17,48 @@ | |||
17 | #include <linux/platform_data/lp855x.h> | 17 | #include <linux/platform_data/lp855x.h> |
18 | #include <linux/pwm.h> | 18 | #include <linux/pwm.h> |
19 | 19 | ||
20 | /* Registers */ | 20 | /* LP8550/1/2/3/6 Registers */ |
21 | #define BRIGHTNESS_CTRL 0x00 | 21 | #define LP855X_BRIGHTNESS_CTRL 0x00 |
22 | #define DEVICE_CTRL 0x01 | 22 | #define LP855X_DEVICE_CTRL 0x01 |
23 | #define EEPROM_START 0xA0 | 23 | #define LP855X_EEPROM_START 0xA0 |
24 | #define EEPROM_END 0xA7 | 24 | #define LP855X_EEPROM_END 0xA7 |
25 | #define EPROM_START 0xA0 | 25 | #define LP8556_EPROM_START 0xA0 |
26 | #define EPROM_END 0xAF | 26 | #define LP8556_EPROM_END 0xAF |
27 | |||
28 | /* LP8557 Registers */ | ||
29 | #define LP8557_BL_CMD 0x00 | ||
30 | #define LP8557_BL_MASK 0x01 | ||
31 | #define LP8557_BL_ON 0x01 | ||
32 | #define LP8557_BL_OFF 0x00 | ||
33 | #define LP8557_BRIGHTNESS_CTRL 0x04 | ||
34 | #define LP8557_CONFIG 0x10 | ||
35 | #define LP8557_EPROM_START 0x10 | ||
36 | #define LP8557_EPROM_END 0x1E | ||
27 | 37 | ||
28 | #define BUF_SIZE 20 | 38 | #define BUF_SIZE 20 |
29 | #define DEFAULT_BL_NAME "lcd-backlight" | 39 | #define DEFAULT_BL_NAME "lcd-backlight" |
30 | #define MAX_BRIGHTNESS 255 | 40 | #define MAX_BRIGHTNESS 255 |
31 | 41 | ||
42 | struct lp855x; | ||
43 | |||
44 | /* | ||
45 | * struct lp855x_device_config | ||
46 | * @pre_init_device: init device function call before updating the brightness | ||
47 | * @reg_brightness: register address for brigthenss control | ||
48 | * @reg_devicectrl: register address for device control | ||
49 | * @post_init_device: late init device function call | ||
50 | */ | ||
51 | struct lp855x_device_config { | ||
52 | int (*pre_init_device)(struct lp855x *); | ||
53 | u8 reg_brightness; | ||
54 | u8 reg_devicectrl; | ||
55 | int (*post_init_device)(struct lp855x *); | ||
56 | }; | ||
57 | |||
32 | struct lp855x { | 58 | struct lp855x { |
33 | const char *chipname; | 59 | const char *chipname; |
34 | enum lp855x_chip_id chip_id; | 60 | enum lp855x_chip_id chip_id; |
61 | struct lp855x_device_config *cfg; | ||
35 | struct i2c_client *client; | 62 | struct i2c_client *client; |
36 | struct backlight_device *bl; | 63 | struct backlight_device *bl; |
37 | struct device *dev; | 64 | struct device *dev; |
@@ -39,9 +66,15 @@ struct lp855x { | |||
39 | struct pwm_device *pwm; | 66 | struct pwm_device *pwm; |
40 | }; | 67 | }; |
41 | 68 | ||
42 | static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data) | 69 | static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data) |
70 | { | ||
71 | return i2c_smbus_write_byte_data(lp->client, reg, data); | ||
72 | } | ||
73 | |||
74 | static int lp855x_update_bit(struct lp855x *lp, u8 reg, u8 mask, u8 data) | ||
43 | { | 75 | { |
44 | int ret; | 76 | int ret; |
77 | u8 tmp; | ||
45 | 78 | ||
46 | ret = i2c_smbus_read_byte_data(lp->client, reg); | 79 | ret = i2c_smbus_read_byte_data(lp->client, reg); |
47 | if (ret < 0) { | 80 | if (ret < 0) { |
@@ -49,13 +82,11 @@ static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data) | |||
49 | return ret; | 82 | return ret; |
50 | } | 83 | } |
51 | 84 | ||
52 | *data = (u8)ret; | 85 | tmp = (u8)ret; |
53 | return 0; | 86 | tmp &= ~mask; |
54 | } | 87 | tmp |= data & mask; |
55 | 88 | ||
56 | static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data) | 89 | return lp855x_write_byte(lp, reg, tmp); |
57 | { | ||
58 | return i2c_smbus_write_byte_data(lp->client, reg, data); | ||
59 | } | 90 | } |
60 | 91 | ||
61 | static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr) | 92 | static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr) |
@@ -67,12 +98,16 @@ static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr) | |||
67 | case LP8551: | 98 | case LP8551: |
68 | case LP8552: | 99 | case LP8552: |
69 | case LP8553: | 100 | case LP8553: |
70 | start = EEPROM_START; | 101 | start = LP855X_EEPROM_START; |
71 | end = EEPROM_END; | 102 | end = LP855X_EEPROM_END; |
72 | break; | 103 | break; |
73 | case LP8556: | 104 | case LP8556: |
74 | start = EPROM_START; | 105 | start = LP8556_EPROM_START; |
75 | end = EPROM_END; | 106 | end = LP8556_EPROM_END; |
107 | break; | ||
108 | case LP8557: | ||
109 | start = LP8557_EPROM_START; | ||
110 | end = LP8557_EPROM_END; | ||
76 | break; | 111 | break; |
77 | default: | 112 | default: |
78 | return false; | 113 | return false; |
@@ -81,21 +116,76 @@ static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr) | |||
81 | return (addr >= start && addr <= end); | 116 | return (addr >= start && addr <= end); |
82 | } | 117 | } |
83 | 118 | ||
84 | static int lp855x_init_registers(struct lp855x *lp) | 119 | static int lp8557_bl_off(struct lp855x *lp) |
120 | { | ||
121 | /* BL_ON = 0 before updating EPROM settings */ | ||
122 | return lp855x_update_bit(lp, LP8557_BL_CMD, LP8557_BL_MASK, | ||
123 | LP8557_BL_OFF); | ||
124 | } | ||
125 | |||
126 | static int lp8557_bl_on(struct lp855x *lp) | ||
127 | { | ||
128 | /* BL_ON = 1 after updating EPROM settings */ | ||
129 | return lp855x_update_bit(lp, LP8557_BL_CMD, LP8557_BL_MASK, | ||
130 | LP8557_BL_ON); | ||
131 | } | ||
132 | |||
133 | static struct lp855x_device_config lp855x_dev_cfg = { | ||
134 | .reg_brightness = LP855X_BRIGHTNESS_CTRL, | ||
135 | .reg_devicectrl = LP855X_DEVICE_CTRL, | ||
136 | }; | ||
137 | |||
138 | static struct lp855x_device_config lp8557_dev_cfg = { | ||
139 | .reg_brightness = LP8557_BRIGHTNESS_CTRL, | ||
140 | .reg_devicectrl = LP8557_CONFIG, | ||
141 | .pre_init_device = lp8557_bl_off, | ||
142 | .post_init_device = lp8557_bl_on, | ||
143 | }; | ||
144 | |||
145 | /* | ||
146 | * Device specific configuration flow | ||
147 | * | ||
148 | * a) pre_init_device(optional) | ||
149 | * b) update the brightness register | ||
150 | * c) update device control register | ||
151 | * d) update ROM area(optional) | ||
152 | * e) post_init_device(optional) | ||
153 | * | ||
154 | */ | ||
155 | static int lp855x_configure(struct lp855x *lp) | ||
85 | { | 156 | { |
86 | u8 val, addr; | 157 | u8 val, addr; |
87 | int i, ret; | 158 | int i, ret; |
88 | struct lp855x_platform_data *pd = lp->pdata; | 159 | struct lp855x_platform_data *pd = lp->pdata; |
89 | 160 | ||
161 | switch (lp->chip_id) { | ||
162 | case LP8550 ... LP8556: | ||
163 | lp->cfg = &lp855x_dev_cfg; | ||
164 | break; | ||
165 | case LP8557: | ||
166 | lp->cfg = &lp8557_dev_cfg; | ||
167 | break; | ||
168 | default: | ||
169 | return -EINVAL; | ||
170 | } | ||
171 | |||
172 | if (lp->cfg->pre_init_device) { | ||
173 | ret = lp->cfg->pre_init_device(lp); | ||
174 | if (ret) { | ||
175 | dev_err(lp->dev, "pre init device err: %d\n", ret); | ||
176 | goto err; | ||
177 | } | ||
178 | } | ||
179 | |||
90 | val = pd->initial_brightness; | 180 | val = pd->initial_brightness; |
91 | ret = lp855x_write_byte(lp, BRIGHTNESS_CTRL, val); | 181 | ret = lp855x_write_byte(lp, lp->cfg->reg_brightness, val); |
92 | if (ret) | 182 | if (ret) |
93 | return ret; | 183 | goto err; |
94 | 184 | ||
95 | val = pd->device_control; | 185 | val = pd->device_control; |
96 | ret = lp855x_write_byte(lp, DEVICE_CTRL, val); | 186 | ret = lp855x_write_byte(lp, lp->cfg->reg_devicectrl, val); |
97 | if (ret) | 187 | if (ret) |
98 | return ret; | 188 | goto err; |
99 | 189 | ||
100 | if (pd->load_new_rom_data && pd->size_program) { | 190 | if (pd->load_new_rom_data && pd->size_program) { |
101 | for (i = 0; i < pd->size_program; i++) { | 191 | for (i = 0; i < pd->size_program; i++) { |
@@ -106,10 +196,21 @@ static int lp855x_init_registers(struct lp855x *lp) | |||
106 | 196 | ||
107 | ret = lp855x_write_byte(lp, addr, val); | 197 | ret = lp855x_write_byte(lp, addr, val); |
108 | if (ret) | 198 | if (ret) |
109 | return ret; | 199 | goto err; |
200 | } | ||
201 | } | ||
202 | |||
203 | if (lp->cfg->post_init_device) { | ||
204 | ret = lp->cfg->post_init_device(lp); | ||
205 | if (ret) { | ||
206 | dev_err(lp->dev, "post init device err: %d\n", ret); | ||
207 | goto err; | ||
110 | } | 208 | } |
111 | } | 209 | } |
112 | 210 | ||
211 | return 0; | ||
212 | |||
213 | err: | ||
113 | return ret; | 214 | return ret; |
114 | } | 215 | } |
115 | 216 | ||
@@ -151,7 +252,7 @@ static int lp855x_bl_update_status(struct backlight_device *bl) | |||
151 | 252 | ||
152 | } else if (mode == REGISTER_BASED) { | 253 | } else if (mode == REGISTER_BASED) { |
153 | u8 val = bl->props.brightness; | 254 | u8 val = bl->props.brightness; |
154 | lp855x_write_byte(lp, BRIGHTNESS_CTRL, val); | 255 | lp855x_write_byte(lp, lp->cfg->reg_brightness, val); |
155 | } | 256 | } |
156 | 257 | ||
157 | return 0; | 258 | return 0; |
@@ -159,16 +260,6 @@ static int lp855x_bl_update_status(struct backlight_device *bl) | |||
159 | 260 | ||
160 | static int lp855x_bl_get_brightness(struct backlight_device *bl) | 261 | static int lp855x_bl_get_brightness(struct backlight_device *bl) |
161 | { | 262 | { |
162 | struct lp855x *lp = bl_get_data(bl); | ||
163 | enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode; | ||
164 | |||
165 | if (mode == REGISTER_BASED) { | ||
166 | u8 val = 0; | ||
167 | |||
168 | lp855x_read_byte(lp, BRIGHTNESS_CTRL, &val); | ||
169 | bl->props.brightness = val; | ||
170 | } | ||
171 | |||
172 | return bl->props.brightness; | 263 | return bl->props.brightness; |
173 | } | 264 | } |
174 | 265 | ||
@@ -271,11 +362,10 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) | |||
271 | lp->chip_id = id->driver_data; | 362 | lp->chip_id = id->driver_data; |
272 | i2c_set_clientdata(cl, lp); | 363 | i2c_set_clientdata(cl, lp); |
273 | 364 | ||
274 | ret = lp855x_init_registers(lp); | 365 | ret = lp855x_configure(lp); |
275 | if (ret) { | 366 | if (ret) { |
276 | dev_err(lp->dev, "i2c communication err: %d", ret); | 367 | dev_err(lp->dev, "device config err: %d", ret); |
277 | if (mode == REGISTER_BASED) | 368 | goto err_dev; |
278 | goto err_dev; | ||
279 | } | 369 | } |
280 | 370 | ||
281 | ret = lp855x_backlight_register(lp); | 371 | ret = lp855x_backlight_register(lp); |
@@ -318,6 +408,7 @@ static const struct i2c_device_id lp855x_ids[] = { | |||
318 | {"lp8552", LP8552}, | 408 | {"lp8552", LP8552}, |
319 | {"lp8553", LP8553}, | 409 | {"lp8553", LP8553}, |
320 | {"lp8556", LP8556}, | 410 | {"lp8556", LP8556}, |
411 | {"lp8557", LP8557}, | ||
321 | { } | 412 | { } |
322 | }; | 413 | }; |
323 | MODULE_DEVICE_TABLE(i2c, lp855x_ids); | 414 | MODULE_DEVICE_TABLE(i2c, lp855x_ids); |
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c index 226d813edf01..c0b4b8f2de98 100644 --- a/drivers/video/backlight/ltv350qv.c +++ b/drivers/video/backlight/ltv350qv.c | |||
@@ -252,7 +252,7 @@ static int ltv350qv_probe(struct spi_device *spi) | |||
252 | if (ret) | 252 | if (ret) |
253 | goto out_unregister; | 253 | goto out_unregister; |
254 | 254 | ||
255 | dev_set_drvdata(&spi->dev, lcd); | 255 | spi_set_drvdata(spi, lcd); |
256 | 256 | ||
257 | return 0; | 257 | return 0; |
258 | 258 | ||
@@ -263,7 +263,7 @@ out_unregister: | |||
263 | 263 | ||
264 | static int ltv350qv_remove(struct spi_device *spi) | 264 | static int ltv350qv_remove(struct spi_device *spi) |
265 | { | 265 | { |
266 | struct ltv350qv *lcd = dev_get_drvdata(&spi->dev); | 266 | struct ltv350qv *lcd = spi_get_drvdata(spi); |
267 | 267 | ||
268 | ltv350qv_power(lcd, FB_BLANK_POWERDOWN); | 268 | ltv350qv_power(lcd, FB_BLANK_POWERDOWN); |
269 | lcd_device_unregister(lcd->ld); | 269 | lcd_device_unregister(lcd->ld); |
@@ -274,14 +274,14 @@ static int ltv350qv_remove(struct spi_device *spi) | |||
274 | #ifdef CONFIG_PM | 274 | #ifdef CONFIG_PM |
275 | static int ltv350qv_suspend(struct spi_device *spi, pm_message_t state) | 275 | static int ltv350qv_suspend(struct spi_device *spi, pm_message_t state) |
276 | { | 276 | { |
277 | struct ltv350qv *lcd = dev_get_drvdata(&spi->dev); | 277 | struct ltv350qv *lcd = spi_get_drvdata(spi); |
278 | 278 | ||
279 | return ltv350qv_power(lcd, FB_BLANK_POWERDOWN); | 279 | return ltv350qv_power(lcd, FB_BLANK_POWERDOWN); |
280 | } | 280 | } |
281 | 281 | ||
282 | static int ltv350qv_resume(struct spi_device *spi) | 282 | static int ltv350qv_resume(struct spi_device *spi) |
283 | { | 283 | { |
284 | struct ltv350qv *lcd = dev_get_drvdata(&spi->dev); | 284 | struct ltv350qv *lcd = spi_get_drvdata(spi); |
285 | 285 | ||
286 | return ltv350qv_power(lcd, FB_BLANK_UNBLANK); | 286 | return ltv350qv_power(lcd, FB_BLANK_UNBLANK); |
287 | } | 287 | } |
@@ -293,7 +293,7 @@ static int ltv350qv_resume(struct spi_device *spi) | |||
293 | /* Power down all displays on reboot, poweroff or halt */ | 293 | /* Power down all displays on reboot, poweroff or halt */ |
294 | static void ltv350qv_shutdown(struct spi_device *spi) | 294 | static void ltv350qv_shutdown(struct spi_device *spi) |
295 | { | 295 | { |
296 | struct ltv350qv *lcd = dev_get_drvdata(&spi->dev); | 296 | struct ltv350qv *lcd = spi_get_drvdata(spi); |
297 | 297 | ||
298 | ltv350qv_power(lcd, FB_BLANK_POWERDOWN); | 298 | ltv350qv_power(lcd, FB_BLANK_POWERDOWN); |
299 | } | 299 | } |
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c index af31c269baa6..627110163067 100644 --- a/drivers/video/backlight/omap1_bl.c +++ b/drivers/video/backlight/omap1_bl.c | |||
@@ -77,7 +77,7 @@ static void omapbl_blank(struct omap_backlight *bl, int mode) | |||
77 | static int omapbl_suspend(struct platform_device *pdev, pm_message_t state) | 77 | static int omapbl_suspend(struct platform_device *pdev, pm_message_t state) |
78 | { | 78 | { |
79 | struct backlight_device *dev = platform_get_drvdata(pdev); | 79 | struct backlight_device *dev = platform_get_drvdata(pdev); |
80 | struct omap_backlight *bl = dev_get_drvdata(&dev->dev); | 80 | struct omap_backlight *bl = bl_get_data(dev); |
81 | 81 | ||
82 | omapbl_blank(bl, FB_BLANK_POWERDOWN); | 82 | omapbl_blank(bl, FB_BLANK_POWERDOWN); |
83 | return 0; | 83 | return 0; |
@@ -86,7 +86,7 @@ static int omapbl_suspend(struct platform_device *pdev, pm_message_t state) | |||
86 | static int omapbl_resume(struct platform_device *pdev) | 86 | static int omapbl_resume(struct platform_device *pdev) |
87 | { | 87 | { |
88 | struct backlight_device *dev = platform_get_drvdata(pdev); | 88 | struct backlight_device *dev = platform_get_drvdata(pdev); |
89 | struct omap_backlight *bl = dev_get_drvdata(&dev->dev); | 89 | struct omap_backlight *bl = bl_get_data(dev); |
90 | 90 | ||
91 | omapbl_blank(bl, bl->powermode); | 91 | omapbl_blank(bl, bl->powermode); |
92 | return 0; | 92 | return 0; |
@@ -98,7 +98,7 @@ static int omapbl_resume(struct platform_device *pdev) | |||
98 | 98 | ||
99 | static int omapbl_set_power(struct backlight_device *dev, int state) | 99 | static int omapbl_set_power(struct backlight_device *dev, int state) |
100 | { | 100 | { |
101 | struct omap_backlight *bl = dev_get_drvdata(&dev->dev); | 101 | struct omap_backlight *bl = bl_get_data(dev); |
102 | 102 | ||
103 | omapbl_blank(bl, state); | 103 | omapbl_blank(bl, state); |
104 | bl->powermode = state; | 104 | bl->powermode = state; |
@@ -108,7 +108,7 @@ static int omapbl_set_power(struct backlight_device *dev, int state) | |||
108 | 108 | ||
109 | static int omapbl_update_status(struct backlight_device *dev) | 109 | static int omapbl_update_status(struct backlight_device *dev) |
110 | { | 110 | { |
111 | struct omap_backlight *bl = dev_get_drvdata(&dev->dev); | 111 | struct omap_backlight *bl = bl_get_data(dev); |
112 | 112 | ||
113 | if (bl->current_intensity != dev->props.brightness) { | 113 | if (bl->current_intensity != dev->props.brightness) { |
114 | if (bl->powermode == FB_BLANK_UNBLANK) | 114 | if (bl->powermode == FB_BLANK_UNBLANK) |
@@ -124,7 +124,7 @@ static int omapbl_update_status(struct backlight_device *dev) | |||
124 | 124 | ||
125 | static int omapbl_get_intensity(struct backlight_device *dev) | 125 | static int omapbl_get_intensity(struct backlight_device *dev) |
126 | { | 126 | { |
127 | struct omap_backlight *bl = dev_get_drvdata(&dev->dev); | 127 | struct omap_backlight *bl = bl_get_data(dev); |
128 | return bl->current_intensity; | 128 | return bl->current_intensity; |
129 | } | 129 | } |
130 | 130 | ||
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 069983ca49ff..f2f4c43d6e22 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c | |||
@@ -37,7 +37,7 @@ struct pwm_bl_data { | |||
37 | 37 | ||
38 | static int pwm_backlight_update_status(struct backlight_device *bl) | 38 | static int pwm_backlight_update_status(struct backlight_device *bl) |
39 | { | 39 | { |
40 | struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); | 40 | struct pwm_bl_data *pb = bl_get_data(bl); |
41 | int brightness = bl->props.brightness; | 41 | int brightness = bl->props.brightness; |
42 | int max = bl->props.max_brightness; | 42 | int max = bl->props.max_brightness; |
43 | 43 | ||
@@ -83,7 +83,7 @@ static int pwm_backlight_get_brightness(struct backlight_device *bl) | |||
83 | static int pwm_backlight_check_fb(struct backlight_device *bl, | 83 | static int pwm_backlight_check_fb(struct backlight_device *bl, |
84 | struct fb_info *info) | 84 | struct fb_info *info) |
85 | { | 85 | { |
86 | struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); | 86 | struct pwm_bl_data *pb = bl_get_data(bl); |
87 | 87 | ||
88 | return !pb->check_fb || pb->check_fb(pb->dev, info); | 88 | return !pb->check_fb || pb->check_fb(pb->dev, info); |
89 | } | 89 | } |
@@ -264,7 +264,7 @@ err_alloc: | |||
264 | static int pwm_backlight_remove(struct platform_device *pdev) | 264 | static int pwm_backlight_remove(struct platform_device *pdev) |
265 | { | 265 | { |
266 | struct backlight_device *bl = platform_get_drvdata(pdev); | 266 | struct backlight_device *bl = platform_get_drvdata(pdev); |
267 | struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); | 267 | struct pwm_bl_data *pb = bl_get_data(bl); |
268 | 268 | ||
269 | backlight_device_unregister(bl); | 269 | backlight_device_unregister(bl); |
270 | pwm_config(pb->pwm, 0, pb->period); | 270 | pwm_config(pb->pwm, 0, pb->period); |
@@ -278,7 +278,7 @@ static int pwm_backlight_remove(struct platform_device *pdev) | |||
278 | static int pwm_backlight_suspend(struct device *dev) | 278 | static int pwm_backlight_suspend(struct device *dev) |
279 | { | 279 | { |
280 | struct backlight_device *bl = dev_get_drvdata(dev); | 280 | struct backlight_device *bl = dev_get_drvdata(dev); |
281 | struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); | 281 | struct pwm_bl_data *pb = bl_get_data(bl); |
282 | 282 | ||
283 | if (pb->notify) | 283 | if (pb->notify) |
284 | pb->notify(pb->dev, 0); | 284 | pb->notify(pb->dev, 0); |
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c index 3e1c1135f6df..9c2677f0ef7d 100644 --- a/drivers/video/backlight/s6e63m0.c +++ b/drivers/video/backlight/s6e63m0.c | |||
@@ -9,28 +9,19 @@ | |||
9 | * under the terms of the GNU General Public License as published by the | 9 | * under the terms of the GNU General Public License as published by the |
10 | * Free Software Foundation; either version 2 of the License, or (at your | 10 | * Free Software Foundation; either version 2 of the License, or (at your |
11 | * option) any later version. | 11 | * option) any later version. |
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | */ | 12 | */ |
22 | 13 | ||
23 | #include <linux/wait.h> | 14 | #include <linux/backlight.h> |
24 | #include <linux/fb.h> | ||
25 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/fb.h> | ||
26 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
27 | #include <linux/spi/spi.h> | ||
28 | #include <linux/irq.h> | ||
29 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/irq.h> | ||
30 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
31 | #include <linux/lcd.h> | 21 | #include <linux/lcd.h> |
32 | #include <linux/backlight.h> | ||
33 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/spi/spi.h> | ||
24 | #include <linux/wait.h> | ||
34 | 25 | ||
35 | #include "s6e63m0_gamma.h" | 26 | #include "s6e63m0_gamma.h" |
36 | 27 | ||
@@ -43,8 +34,6 @@ | |||
43 | #define MIN_BRIGHTNESS 0 | 34 | #define MIN_BRIGHTNESS 0 |
44 | #define MAX_BRIGHTNESS 10 | 35 | #define MAX_BRIGHTNESS 10 |
45 | 36 | ||
46 | #define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) | ||
47 | |||
48 | struct s6e63m0 { | 37 | struct s6e63m0 { |
49 | struct device *dev; | 38 | struct device *dev; |
50 | struct spi_device *spi; | 39 | struct spi_device *spi; |
@@ -57,7 +46,7 @@ struct s6e63m0 { | |||
57 | struct lcd_platform_data *lcd_pd; | 46 | struct lcd_platform_data *lcd_pd; |
58 | }; | 47 | }; |
59 | 48 | ||
60 | static const unsigned short SEQ_PANEL_CONDITION_SET[] = { | 49 | static const unsigned short seq_panel_condition_set[] = { |
61 | 0xF8, 0x01, | 50 | 0xF8, 0x01, |
62 | DATA_ONLY, 0x27, | 51 | DATA_ONLY, 0x27, |
63 | DATA_ONLY, 0x27, | 52 | DATA_ONLY, 0x27, |
@@ -76,7 +65,7 @@ static const unsigned short SEQ_PANEL_CONDITION_SET[] = { | |||
76 | ENDDEF, 0x0000 | 65 | ENDDEF, 0x0000 |
77 | }; | 66 | }; |
78 | 67 | ||
79 | static const unsigned short SEQ_DISPLAY_CONDITION_SET[] = { | 68 | static const unsigned short seq_display_condition_set[] = { |
80 | 0xf2, 0x02, | 69 | 0xf2, 0x02, |
81 | DATA_ONLY, 0x03, | 70 | DATA_ONLY, 0x03, |
82 | DATA_ONLY, 0x1c, | 71 | DATA_ONLY, 0x1c, |
@@ -90,7 +79,7 @@ static const unsigned short SEQ_DISPLAY_CONDITION_SET[] = { | |||
90 | ENDDEF, 0x0000 | 79 | ENDDEF, 0x0000 |
91 | }; | 80 | }; |
92 | 81 | ||
93 | static const unsigned short SEQ_GAMMA_SETTING[] = { | 82 | static const unsigned short seq_gamma_setting[] = { |
94 | 0xfa, 0x00, | 83 | 0xfa, 0x00, |
95 | DATA_ONLY, 0x18, | 84 | DATA_ONLY, 0x18, |
96 | DATA_ONLY, 0x08, | 85 | DATA_ONLY, 0x08, |
@@ -119,7 +108,7 @@ static const unsigned short SEQ_GAMMA_SETTING[] = { | |||
119 | ENDDEF, 0x0000 | 108 | ENDDEF, 0x0000 |
120 | }; | 109 | }; |
121 | 110 | ||
122 | static const unsigned short SEQ_ETC_CONDITION_SET[] = { | 111 | static const unsigned short seq_etc_condition_set[] = { |
123 | 0xf6, 0x00, | 112 | 0xf6, 0x00, |
124 | DATA_ONLY, 0x8c, | 113 | DATA_ONLY, 0x8c, |
125 | DATA_ONLY, 0x07, | 114 | DATA_ONLY, 0x07, |
@@ -318,47 +307,47 @@ static const unsigned short SEQ_ETC_CONDITION_SET[] = { | |||
318 | ENDDEF, 0x0000 | 307 | ENDDEF, 0x0000 |
319 | }; | 308 | }; |
320 | 309 | ||
321 | static const unsigned short SEQ_ACL_ON[] = { | 310 | static const unsigned short seq_acl_on[] = { |
322 | /* ACL on */ | 311 | /* ACL on */ |
323 | 0xc0, 0x01, | 312 | 0xc0, 0x01, |
324 | 313 | ||
325 | ENDDEF, 0x0000 | 314 | ENDDEF, 0x0000 |
326 | }; | 315 | }; |
327 | 316 | ||
328 | static const unsigned short SEQ_ACL_OFF[] = { | 317 | static const unsigned short seq_acl_off[] = { |
329 | /* ACL off */ | 318 | /* ACL off */ |
330 | 0xc0, 0x00, | 319 | 0xc0, 0x00, |
331 | 320 | ||
332 | ENDDEF, 0x0000 | 321 | ENDDEF, 0x0000 |
333 | }; | 322 | }; |
334 | 323 | ||
335 | static const unsigned short SEQ_ELVSS_ON[] = { | 324 | static const unsigned short seq_elvss_on[] = { |
336 | /* ELVSS on */ | 325 | /* ELVSS on */ |
337 | 0xb1, 0x0b, | 326 | 0xb1, 0x0b, |
338 | 327 | ||
339 | ENDDEF, 0x0000 | 328 | ENDDEF, 0x0000 |
340 | }; | 329 | }; |
341 | 330 | ||
342 | static const unsigned short SEQ_ELVSS_OFF[] = { | 331 | static const unsigned short seq_elvss_off[] = { |
343 | /* ELVSS off */ | 332 | /* ELVSS off */ |
344 | 0xb1, 0x0a, | 333 | 0xb1, 0x0a, |
345 | 334 | ||
346 | ENDDEF, 0x0000 | 335 | ENDDEF, 0x0000 |
347 | }; | 336 | }; |
348 | 337 | ||
349 | static const unsigned short SEQ_STAND_BY_OFF[] = { | 338 | static const unsigned short seq_stand_by_off[] = { |
350 | 0x11, COMMAND_ONLY, | 339 | 0x11, COMMAND_ONLY, |
351 | 340 | ||
352 | ENDDEF, 0x0000 | 341 | ENDDEF, 0x0000 |
353 | }; | 342 | }; |
354 | 343 | ||
355 | static const unsigned short SEQ_STAND_BY_ON[] = { | 344 | static const unsigned short seq_stand_by_on[] = { |
356 | 0x10, COMMAND_ONLY, | 345 | 0x10, COMMAND_ONLY, |
357 | 346 | ||
358 | ENDDEF, 0x0000 | 347 | ENDDEF, 0x0000 |
359 | }; | 348 | }; |
360 | 349 | ||
361 | static const unsigned short SEQ_DISPLAY_ON[] = { | 350 | static const unsigned short seq_display_on[] = { |
362 | 0x29, COMMAND_ONLY, | 351 | 0x29, COMMAND_ONLY, |
363 | 352 | ||
364 | ENDDEF, 0x0000 | 353 | ENDDEF, 0x0000 |
@@ -406,8 +395,9 @@ static int s6e63m0_panel_send_sequence(struct s6e63m0 *lcd, | |||
406 | ret = s6e63m0_spi_write(lcd, wbuf[i], wbuf[i+1]); | 395 | ret = s6e63m0_spi_write(lcd, wbuf[i], wbuf[i+1]); |
407 | if (ret) | 396 | if (ret) |
408 | break; | 397 | break; |
409 | } else | 398 | } else { |
410 | udelay(wbuf[i+1]*1000); | 399 | msleep(wbuf[i+1]); |
400 | } | ||
411 | i += 2; | 401 | i += 2; |
412 | } | 402 | } |
413 | 403 | ||
@@ -457,12 +447,12 @@ static int s6e63m0_ldi_init(struct s6e63m0 *lcd) | |||
457 | { | 447 | { |
458 | int ret, i; | 448 | int ret, i; |
459 | const unsigned short *init_seq[] = { | 449 | const unsigned short *init_seq[] = { |
460 | SEQ_PANEL_CONDITION_SET, | 450 | seq_panel_condition_set, |
461 | SEQ_DISPLAY_CONDITION_SET, | 451 | seq_display_condition_set, |
462 | SEQ_GAMMA_SETTING, | 452 | seq_gamma_setting, |
463 | SEQ_ETC_CONDITION_SET, | 453 | seq_etc_condition_set, |
464 | SEQ_ACL_ON, | 454 | seq_acl_on, |
465 | SEQ_ELVSS_ON, | 455 | seq_elvss_on, |
466 | }; | 456 | }; |
467 | 457 | ||
468 | for (i = 0; i < ARRAY_SIZE(init_seq); i++) { | 458 | for (i = 0; i < ARRAY_SIZE(init_seq); i++) { |
@@ -478,8 +468,8 @@ static int s6e63m0_ldi_enable(struct s6e63m0 *lcd) | |||
478 | { | 468 | { |
479 | int ret = 0, i; | 469 | int ret = 0, i; |
480 | const unsigned short *enable_seq[] = { | 470 | const unsigned short *enable_seq[] = { |
481 | SEQ_STAND_BY_OFF, | 471 | seq_stand_by_off, |
482 | SEQ_DISPLAY_ON, | 472 | seq_display_on, |
483 | }; | 473 | }; |
484 | 474 | ||
485 | for (i = 0; i < ARRAY_SIZE(enable_seq); i++) { | 475 | for (i = 0; i < ARRAY_SIZE(enable_seq); i++) { |
@@ -495,43 +485,39 @@ static int s6e63m0_ldi_disable(struct s6e63m0 *lcd) | |||
495 | { | 485 | { |
496 | int ret; | 486 | int ret; |
497 | 487 | ||
498 | ret = s6e63m0_panel_send_sequence(lcd, SEQ_STAND_BY_ON); | 488 | ret = s6e63m0_panel_send_sequence(lcd, seq_stand_by_on); |
499 | 489 | ||
500 | return ret; | 490 | return ret; |
501 | } | 491 | } |
502 | 492 | ||
493 | static int s6e63m0_power_is_on(int power) | ||
494 | { | ||
495 | return power <= FB_BLANK_NORMAL; | ||
496 | } | ||
497 | |||
503 | static int s6e63m0_power_on(struct s6e63m0 *lcd) | 498 | static int s6e63m0_power_on(struct s6e63m0 *lcd) |
504 | { | 499 | { |
505 | int ret = 0; | 500 | int ret = 0; |
506 | struct lcd_platform_data *pd = NULL; | 501 | struct lcd_platform_data *pd; |
507 | struct backlight_device *bd = NULL; | 502 | struct backlight_device *bd; |
508 | 503 | ||
509 | pd = lcd->lcd_pd; | 504 | pd = lcd->lcd_pd; |
510 | if (!pd) { | ||
511 | dev_err(lcd->dev, "platform data is NULL.\n"); | ||
512 | return -EFAULT; | ||
513 | } | ||
514 | |||
515 | bd = lcd->bd; | 505 | bd = lcd->bd; |
516 | if (!bd) { | ||
517 | dev_err(lcd->dev, "backlight device is NULL.\n"); | ||
518 | return -EFAULT; | ||
519 | } | ||
520 | 506 | ||
521 | if (!pd->power_on) { | 507 | if (!pd->power_on) { |
522 | dev_err(lcd->dev, "power_on is NULL.\n"); | 508 | dev_err(lcd->dev, "power_on is NULL.\n"); |
523 | return -EFAULT; | 509 | return -EINVAL; |
524 | } else { | 510 | } else { |
525 | pd->power_on(lcd->ld, 1); | 511 | pd->power_on(lcd->ld, 1); |
526 | mdelay(pd->power_on_delay); | 512 | msleep(pd->power_on_delay); |
527 | } | 513 | } |
528 | 514 | ||
529 | if (!pd->reset) { | 515 | if (!pd->reset) { |
530 | dev_err(lcd->dev, "reset is NULL.\n"); | 516 | dev_err(lcd->dev, "reset is NULL.\n"); |
531 | return -EFAULT; | 517 | return -EINVAL; |
532 | } else { | 518 | } else { |
533 | pd->reset(lcd->ld); | 519 | pd->reset(lcd->ld); |
534 | mdelay(pd->reset_delay); | 520 | msleep(pd->reset_delay); |
535 | } | 521 | } |
536 | 522 | ||
537 | ret = s6e63m0_ldi_init(lcd); | 523 | ret = s6e63m0_ldi_init(lcd); |
@@ -558,14 +544,10 @@ static int s6e63m0_power_on(struct s6e63m0 *lcd) | |||
558 | 544 | ||
559 | static int s6e63m0_power_off(struct s6e63m0 *lcd) | 545 | static int s6e63m0_power_off(struct s6e63m0 *lcd) |
560 | { | 546 | { |
561 | int ret = 0; | 547 | int ret; |
562 | struct lcd_platform_data *pd = NULL; | 548 | struct lcd_platform_data *pd; |
563 | 549 | ||
564 | pd = lcd->lcd_pd; | 550 | pd = lcd->lcd_pd; |
565 | if (!pd) { | ||
566 | dev_err(lcd->dev, "platform data is NULL.\n"); | ||
567 | return -EFAULT; | ||
568 | } | ||
569 | 551 | ||
570 | ret = s6e63m0_ldi_disable(lcd); | 552 | ret = s6e63m0_ldi_disable(lcd); |
571 | if (ret) { | 553 | if (ret) { |
@@ -573,13 +555,9 @@ static int s6e63m0_power_off(struct s6e63m0 *lcd) | |||
573 | return -EIO; | 555 | return -EIO; |
574 | } | 556 | } |
575 | 557 | ||
576 | mdelay(pd->power_off_delay); | 558 | msleep(pd->power_off_delay); |
577 | 559 | ||
578 | if (!pd->power_on) { | 560 | pd->power_on(lcd->ld, 0); |
579 | dev_err(lcd->dev, "power_on is NULL.\n"); | ||
580 | return -EFAULT; | ||
581 | } else | ||
582 | pd->power_on(lcd->ld, 0); | ||
583 | 561 | ||
584 | return 0; | 562 | return 0; |
585 | } | 563 | } |
@@ -588,9 +566,9 @@ static int s6e63m0_power(struct s6e63m0 *lcd, int power) | |||
588 | { | 566 | { |
589 | int ret = 0; | 567 | int ret = 0; |
590 | 568 | ||
591 | if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) | 569 | if (s6e63m0_power_is_on(power) && !s6e63m0_power_is_on(lcd->power)) |
592 | ret = s6e63m0_power_on(lcd); | 570 | ret = s6e63m0_power_on(lcd); |
593 | else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) | 571 | else if (!s6e63m0_power_is_on(power) && s6e63m0_power_is_on(lcd->power)) |
594 | ret = s6e63m0_power_off(lcd); | 572 | ret = s6e63m0_power_off(lcd); |
595 | 573 | ||
596 | if (!ret) | 574 | if (!ret) |
@@ -760,7 +738,7 @@ static int s6e63m0_probe(struct spi_device *spi) | |||
760 | lcd->lcd_pd = spi->dev.platform_data; | 738 | lcd->lcd_pd = spi->dev.platform_data; |
761 | if (!lcd->lcd_pd) { | 739 | if (!lcd->lcd_pd) { |
762 | dev_err(&spi->dev, "platform data is NULL.\n"); | 740 | dev_err(&spi->dev, "platform data is NULL.\n"); |
763 | return -EFAULT; | 741 | return -EINVAL; |
764 | } | 742 | } |
765 | 743 | ||
766 | ld = lcd_device_register("s6e63m0", &spi->dev, lcd, &s6e63m0_lcd_ops); | 744 | ld = lcd_device_register("s6e63m0", &spi->dev, lcd, &s6e63m0_lcd_ops); |
@@ -788,7 +766,7 @@ static int s6e63m0_probe(struct spi_device *spi) | |||
788 | * know that. | 766 | * know that. |
789 | */ | 767 | */ |
790 | lcd->gamma_table_count = | 768 | lcd->gamma_table_count = |
791 | sizeof(gamma_table) / (MAX_GAMMA_LEVEL * sizeof(int)); | 769 | sizeof(gamma_table) / (MAX_GAMMA_LEVEL * sizeof(int *)); |
792 | 770 | ||
793 | ret = device_create_file(&(spi->dev), &dev_attr_gamma_mode); | 771 | ret = device_create_file(&(spi->dev), &dev_attr_gamma_mode); |
794 | if (ret < 0) | 772 | if (ret < 0) |
@@ -811,10 +789,11 @@ static int s6e63m0_probe(struct spi_device *spi) | |||
811 | lcd->power = FB_BLANK_POWERDOWN; | 789 | lcd->power = FB_BLANK_POWERDOWN; |
812 | 790 | ||
813 | s6e63m0_power(lcd, FB_BLANK_UNBLANK); | 791 | s6e63m0_power(lcd, FB_BLANK_UNBLANK); |
814 | } else | 792 | } else { |
815 | lcd->power = FB_BLANK_UNBLANK; | 793 | lcd->power = FB_BLANK_UNBLANK; |
794 | } | ||
816 | 795 | ||
817 | dev_set_drvdata(&spi->dev, lcd); | 796 | spi_set_drvdata(spi, lcd); |
818 | 797 | ||
819 | dev_info(&spi->dev, "s6e63m0 panel driver has been probed.\n"); | 798 | dev_info(&spi->dev, "s6e63m0 panel driver has been probed.\n"); |
820 | 799 | ||
@@ -827,7 +806,7 @@ out_lcd_unregister: | |||
827 | 806 | ||
828 | static int s6e63m0_remove(struct spi_device *spi) | 807 | static int s6e63m0_remove(struct spi_device *spi) |
829 | { | 808 | { |
830 | struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); | 809 | struct s6e63m0 *lcd = spi_get_drvdata(spi); |
831 | 810 | ||
832 | s6e63m0_power(lcd, FB_BLANK_POWERDOWN); | 811 | s6e63m0_power(lcd, FB_BLANK_POWERDOWN); |
833 | device_remove_file(&spi->dev, &dev_attr_gamma_table); | 812 | device_remove_file(&spi->dev, &dev_attr_gamma_table); |
@@ -839,44 +818,26 @@ static int s6e63m0_remove(struct spi_device *spi) | |||
839 | } | 818 | } |
840 | 819 | ||
841 | #if defined(CONFIG_PM) | 820 | #if defined(CONFIG_PM) |
842 | static unsigned int before_power; | ||
843 | |||
844 | static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg) | 821 | static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg) |
845 | { | 822 | { |
846 | int ret = 0; | 823 | struct s6e63m0 *lcd = spi_get_drvdata(spi); |
847 | struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); | ||
848 | 824 | ||
849 | dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); | 825 | dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); |
850 | 826 | ||
851 | before_power = lcd->power; | ||
852 | |||
853 | /* | 827 | /* |
854 | * when lcd panel is suspend, lcd panel becomes off | 828 | * when lcd panel is suspend, lcd panel becomes off |
855 | * regardless of status. | 829 | * regardless of status. |
856 | */ | 830 | */ |
857 | ret = s6e63m0_power(lcd, FB_BLANK_POWERDOWN); | 831 | return s6e63m0_power(lcd, FB_BLANK_POWERDOWN); |
858 | |||
859 | return ret; | ||
860 | } | 832 | } |
861 | 833 | ||
862 | static int s6e63m0_resume(struct spi_device *spi) | 834 | static int s6e63m0_resume(struct spi_device *spi) |
863 | { | 835 | { |
864 | int ret = 0; | 836 | struct s6e63m0 *lcd = spi_get_drvdata(spi); |
865 | struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); | ||
866 | |||
867 | /* | ||
868 | * after suspended, if lcd panel status is FB_BLANK_UNBLANK | ||
869 | * (at that time, before_power is FB_BLANK_UNBLANK) then | ||
870 | * it changes that status to FB_BLANK_POWERDOWN to get lcd on. | ||
871 | */ | ||
872 | if (before_power == FB_BLANK_UNBLANK) | ||
873 | lcd->power = FB_BLANK_POWERDOWN; | ||
874 | 837 | ||
875 | dev_dbg(&spi->dev, "before_power = %d\n", before_power); | 838 | lcd->power = FB_BLANK_POWERDOWN; |
876 | 839 | ||
877 | ret = s6e63m0_power(lcd, before_power); | 840 | return s6e63m0_power(lcd, FB_BLANK_UNBLANK); |
878 | |||
879 | return ret; | ||
880 | } | 841 | } |
881 | #else | 842 | #else |
882 | #define s6e63m0_suspend NULL | 843 | #define s6e63m0_suspend NULL |
@@ -886,7 +847,7 @@ static int s6e63m0_resume(struct spi_device *spi) | |||
886 | /* Power down all displays on reboot, poweroff or halt. */ | 847 | /* Power down all displays on reboot, poweroff or halt. */ |
887 | static void s6e63m0_shutdown(struct spi_device *spi) | 848 | static void s6e63m0_shutdown(struct spi_device *spi) |
888 | { | 849 | { |
889 | struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); | 850 | struct s6e63m0 *lcd = spi_get_drvdata(spi); |
890 | 851 | ||
891 | s6e63m0_power(lcd, FB_BLANK_POWERDOWN); | 852 | s6e63m0_power(lcd, FB_BLANK_POWERDOWN); |
892 | } | 853 | } |
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index ad2325f3d652..00162085eec0 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c | |||
@@ -390,7 +390,7 @@ static int tdo24m_probe(struct spi_device *spi) | |||
390 | if (IS_ERR(lcd->lcd_dev)) | 390 | if (IS_ERR(lcd->lcd_dev)) |
391 | return PTR_ERR(lcd->lcd_dev); | 391 | return PTR_ERR(lcd->lcd_dev); |
392 | 392 | ||
393 | dev_set_drvdata(&spi->dev, lcd); | 393 | spi_set_drvdata(spi, lcd); |
394 | err = tdo24m_power(lcd, FB_BLANK_UNBLANK); | 394 | err = tdo24m_power(lcd, FB_BLANK_UNBLANK); |
395 | if (err) | 395 | if (err) |
396 | goto out_unregister; | 396 | goto out_unregister; |
@@ -404,7 +404,7 @@ out_unregister: | |||
404 | 404 | ||
405 | static int tdo24m_remove(struct spi_device *spi) | 405 | static int tdo24m_remove(struct spi_device *spi) |
406 | { | 406 | { |
407 | struct tdo24m *lcd = dev_get_drvdata(&spi->dev); | 407 | struct tdo24m *lcd = spi_get_drvdata(spi); |
408 | 408 | ||
409 | tdo24m_power(lcd, FB_BLANK_POWERDOWN); | 409 | tdo24m_power(lcd, FB_BLANK_POWERDOWN); |
410 | lcd_device_unregister(lcd->lcd_dev); | 410 | lcd_device_unregister(lcd->lcd_dev); |
@@ -415,14 +415,14 @@ static int tdo24m_remove(struct spi_device *spi) | |||
415 | #ifdef CONFIG_PM | 415 | #ifdef CONFIG_PM |
416 | static int tdo24m_suspend(struct spi_device *spi, pm_message_t state) | 416 | static int tdo24m_suspend(struct spi_device *spi, pm_message_t state) |
417 | { | 417 | { |
418 | struct tdo24m *lcd = dev_get_drvdata(&spi->dev); | 418 | struct tdo24m *lcd = spi_get_drvdata(spi); |
419 | 419 | ||
420 | return tdo24m_power(lcd, FB_BLANK_POWERDOWN); | 420 | return tdo24m_power(lcd, FB_BLANK_POWERDOWN); |
421 | } | 421 | } |
422 | 422 | ||
423 | static int tdo24m_resume(struct spi_device *spi) | 423 | static int tdo24m_resume(struct spi_device *spi) |
424 | { | 424 | { |
425 | struct tdo24m *lcd = dev_get_drvdata(&spi->dev); | 425 | struct tdo24m *lcd = spi_get_drvdata(spi); |
426 | 426 | ||
427 | return tdo24m_power(lcd, FB_BLANK_UNBLANK); | 427 | return tdo24m_power(lcd, FB_BLANK_UNBLANK); |
428 | } | 428 | } |
@@ -434,7 +434,7 @@ static int tdo24m_resume(struct spi_device *spi) | |||
434 | /* Power down all displays on reboot, poweroff or halt */ | 434 | /* Power down all displays on reboot, poweroff or halt */ |
435 | static void tdo24m_shutdown(struct spi_device *spi) | 435 | static void tdo24m_shutdown(struct spi_device *spi) |
436 | { | 436 | { |
437 | struct tdo24m *lcd = dev_get_drvdata(&spi->dev); | 437 | struct tdo24m *lcd = spi_get_drvdata(spi); |
438 | 438 | ||
439 | tdo24m_power(lcd, FB_BLANK_POWERDOWN); | 439 | tdo24m_power(lcd, FB_BLANK_POWERDOWN); |
440 | } | 440 | } |
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c index 588682cc1614..2326fa810c59 100644 --- a/drivers/video/backlight/tosa_bl.c +++ b/drivers/video/backlight/tosa_bl.c | |||
@@ -54,7 +54,7 @@ static void tosa_bl_set_backlight(struct tosa_bl_data *data, int brightness) | |||
54 | static int tosa_bl_update_status(struct backlight_device *dev) | 54 | static int tosa_bl_update_status(struct backlight_device *dev) |
55 | { | 55 | { |
56 | struct backlight_properties *props = &dev->props; | 56 | struct backlight_properties *props = &dev->props; |
57 | struct tosa_bl_data *data = dev_get_drvdata(&dev->dev); | 57 | struct tosa_bl_data *data = bl_get_data(dev); |
58 | int power = max(props->power, props->fb_blank); | 58 | int power = max(props->power, props->fb_blank); |
59 | int brightness = props->brightness; | 59 | int brightness = props->brightness; |
60 | 60 | ||
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c index 96bae941585a..666fe2593ea4 100644 --- a/drivers/video/backlight/tosa_lcd.c +++ b/drivers/video/backlight/tosa_lcd.c | |||
@@ -193,7 +193,7 @@ static int tosa_lcd_probe(struct spi_device *spi) | |||
193 | return ret; | 193 | return ret; |
194 | 194 | ||
195 | data->spi = spi; | 195 | data->spi = spi; |
196 | dev_set_drvdata(&spi->dev, data); | 196 | spi_set_drvdata(spi, data); |
197 | 197 | ||
198 | ret = devm_gpio_request_one(&spi->dev, TOSA_GPIO_TG_ON, | 198 | ret = devm_gpio_request_one(&spi->dev, TOSA_GPIO_TG_ON, |
199 | GPIOF_OUT_INIT_LOW, "tg #pwr"); | 199 | GPIOF_OUT_INIT_LOW, "tg #pwr"); |
@@ -220,13 +220,13 @@ static int tosa_lcd_probe(struct spi_device *spi) | |||
220 | err_register: | 220 | err_register: |
221 | tosa_lcd_tg_off(data); | 221 | tosa_lcd_tg_off(data); |
222 | err_gpio_tg: | 222 | err_gpio_tg: |
223 | dev_set_drvdata(&spi->dev, NULL); | 223 | spi_set_drvdata(spi, NULL); |
224 | return ret; | 224 | return ret; |
225 | } | 225 | } |
226 | 226 | ||
227 | static int tosa_lcd_remove(struct spi_device *spi) | 227 | static int tosa_lcd_remove(struct spi_device *spi) |
228 | { | 228 | { |
229 | struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev); | 229 | struct tosa_lcd_data *data = spi_get_drvdata(spi); |
230 | 230 | ||
231 | lcd_device_unregister(data->lcd); | 231 | lcd_device_unregister(data->lcd); |
232 | 232 | ||
@@ -235,7 +235,7 @@ static int tosa_lcd_remove(struct spi_device *spi) | |||
235 | 235 | ||
236 | tosa_lcd_tg_off(data); | 236 | tosa_lcd_tg_off(data); |
237 | 237 | ||
238 | dev_set_drvdata(&spi->dev, NULL); | 238 | spi_set_drvdata(spi, NULL); |
239 | 239 | ||
240 | return 0; | 240 | return 0; |
241 | } | 241 | } |
@@ -243,7 +243,7 @@ static int tosa_lcd_remove(struct spi_device *spi) | |||
243 | #ifdef CONFIG_PM | 243 | #ifdef CONFIG_PM |
244 | static int tosa_lcd_suspend(struct spi_device *spi, pm_message_t state) | 244 | static int tosa_lcd_suspend(struct spi_device *spi, pm_message_t state) |
245 | { | 245 | { |
246 | struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev); | 246 | struct tosa_lcd_data *data = spi_get_drvdata(spi); |
247 | 247 | ||
248 | tosa_lcd_tg_off(data); | 248 | tosa_lcd_tg_off(data); |
249 | 249 | ||
@@ -252,7 +252,7 @@ static int tosa_lcd_suspend(struct spi_device *spi, pm_message_t state) | |||
252 | 252 | ||
253 | static int tosa_lcd_resume(struct spi_device *spi) | 253 | static int tosa_lcd_resume(struct spi_device *spi) |
254 | { | 254 | { |
255 | struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev); | 255 | struct tosa_lcd_data *data = spi_get_drvdata(spi); |
256 | 256 | ||
257 | tosa_lcd_tg_init(data); | 257 | tosa_lcd_tg_init(data); |
258 | if (POWER_IS_ON(data->lcd_power)) | 258 | if (POWER_IS_ON(data->lcd_power)) |
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c index 45e81b4cf8b4..84d582f591dc 100644 --- a/drivers/video/backlight/vgg2432a4.c +++ b/drivers/video/backlight/vgg2432a4.c | |||
@@ -208,12 +208,11 @@ static int vgg2432a4_lcd_init(struct ili9320 *lcd, | |||
208 | #ifdef CONFIG_PM | 208 | #ifdef CONFIG_PM |
209 | static int vgg2432a4_suspend(struct spi_device *spi, pm_message_t state) | 209 | static int vgg2432a4_suspend(struct spi_device *spi, pm_message_t state) |
210 | { | 210 | { |
211 | return ili9320_suspend(dev_get_drvdata(&spi->dev), state); | 211 | return ili9320_suspend(spi_get_drvdata(spi), state); |
212 | } | 212 | } |
213 | |||
214 | static int vgg2432a4_resume(struct spi_device *spi) | 213 | static int vgg2432a4_resume(struct spi_device *spi) |
215 | { | 214 | { |
216 | return ili9320_resume(dev_get_drvdata(&spi->dev)); | 215 | return ili9320_resume(spi_get_drvdata(spi)); |
217 | } | 216 | } |
218 | #else | 217 | #else |
219 | #define vgg2432a4_suspend NULL | 218 | #define vgg2432a4_suspend NULL |
@@ -242,12 +241,12 @@ static int vgg2432a4_probe(struct spi_device *spi) | |||
242 | 241 | ||
243 | static int vgg2432a4_remove(struct spi_device *spi) | 242 | static int vgg2432a4_remove(struct spi_device *spi) |
244 | { | 243 | { |
245 | return ili9320_remove(dev_get_drvdata(&spi->dev)); | 244 | return ili9320_remove(spi_get_drvdata(spi)); |
246 | } | 245 | } |
247 | 246 | ||
248 | static void vgg2432a4_shutdown(struct spi_device *spi) | 247 | static void vgg2432a4_shutdown(struct spi_device *spi) |
249 | { | 248 | { |
250 | ili9320_shutdown(dev_get_drvdata(&spi->dev)); | 249 | ili9320_shutdown(spi_get_drvdata(spi)); |
251 | } | 250 | } |
252 | 251 | ||
253 | static struct spi_driver vgg2432a4_driver = { | 252 | static struct spi_driver vgg2432a4_driver = { |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index fdefa8fd72c4..f8a61e210d2e 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -1242,8 +1242,16 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, | |||
1242 | if (!height || !width) | 1242 | if (!height || !width) |
1243 | return; | 1243 | return; |
1244 | 1244 | ||
1245 | if (sy < vc->vc_top && vc->vc_top == logo_lines) | 1245 | if (sy < vc->vc_top && vc->vc_top == logo_lines) { |
1246 | vc->vc_top = 0; | 1246 | vc->vc_top = 0; |
1247 | /* | ||
1248 | * If the font dimensions are not an integral of the display | ||
1249 | * dimensions then the ops->clear below won't end up clearing | ||
1250 | * the margins. Call clear_margins here in case the logo | ||
1251 | * bitmap stretched into the margin area. | ||
1252 | */ | ||
1253 | fbcon_clear_margins(vc, 0); | ||
1254 | } | ||
1247 | 1255 | ||
1248 | /* Split blits that cross physical y_wrap boundary */ | 1256 | /* Split blits that cross physical y_wrap boundary */ |
1249 | 1257 | ||
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c index 2ed97769aa6d..de9d4da0e3da 100644 --- a/drivers/video/exynos/exynos_dp_core.c +++ b/drivers/video/exynos/exynos_dp_core.c | |||
@@ -965,10 +965,11 @@ static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev) | |||
965 | 965 | ||
966 | static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) | 966 | static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) |
967 | { | 967 | { |
968 | struct device_node *dp_phy_node; | 968 | struct device_node *dp_phy_node = of_node_get(dp->dev->of_node); |
969 | u32 phy_base; | 969 | u32 phy_base; |
970 | int ret = 0; | ||
970 | 971 | ||
971 | dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy"); | 972 | dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy"); |
972 | if (!dp_phy_node) { | 973 | if (!dp_phy_node) { |
973 | dev_err(dp->dev, "could not find dptx-phy node\n"); | 974 | dev_err(dp->dev, "could not find dptx-phy node\n"); |
974 | return -ENODEV; | 975 | return -ENODEV; |
@@ -976,22 +977,28 @@ static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) | |||
976 | 977 | ||
977 | if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) { | 978 | if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) { |
978 | dev_err(dp->dev, "faild to get reg for dptx-phy\n"); | 979 | dev_err(dp->dev, "faild to get reg for dptx-phy\n"); |
979 | return -EINVAL; | 980 | ret = -EINVAL; |
981 | goto err; | ||
980 | } | 982 | } |
981 | 983 | ||
982 | if (of_property_read_u32(dp_phy_node, "samsung,enable-mask", | 984 | if (of_property_read_u32(dp_phy_node, "samsung,enable-mask", |
983 | &dp->enable_mask)) { | 985 | &dp->enable_mask)) { |
984 | dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n"); | 986 | dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n"); |
985 | return -EINVAL; | 987 | ret = -EINVAL; |
988 | goto err; | ||
986 | } | 989 | } |
987 | 990 | ||
988 | dp->phy_addr = ioremap(phy_base, SZ_4); | 991 | dp->phy_addr = ioremap(phy_base, SZ_4); |
989 | if (!dp->phy_addr) { | 992 | if (!dp->phy_addr) { |
990 | dev_err(dp->dev, "failed to ioremap dp-phy\n"); | 993 | dev_err(dp->dev, "failed to ioremap dp-phy\n"); |
991 | return -ENOMEM; | 994 | ret = -ENOMEM; |
995 | goto err; | ||
992 | } | 996 | } |
993 | 997 | ||
994 | return 0; | 998 | err: |
999 | of_node_put(dp_phy_node); | ||
1000 | |||
1001 | return ret; | ||
995 | } | 1002 | } |
996 | 1003 | ||
997 | static void exynos_dp_phy_init(struct exynos_dp_device *dp) | 1004 | static void exynos_dp_phy_init(struct exynos_dp_device *dp) |
@@ -1117,8 +1124,6 @@ static int exynos_dp_remove(struct platform_device *pdev) | |||
1117 | struct exynos_dp_platdata *pdata = pdev->dev.platform_data; | 1124 | struct exynos_dp_platdata *pdata = pdev->dev.platform_data; |
1118 | struct exynos_dp_device *dp = platform_get_drvdata(pdev); | 1125 | struct exynos_dp_device *dp = platform_get_drvdata(pdev); |
1119 | 1126 | ||
1120 | disable_irq(dp->irq); | ||
1121 | |||
1122 | flush_work(&dp->hotplug_work); | 1127 | flush_work(&dp->hotplug_work); |
1123 | 1128 | ||
1124 | if (pdev->dev.of_node) { | 1129 | if (pdev->dev.of_node) { |
@@ -1141,6 +1146,8 @@ static int exynos_dp_suspend(struct device *dev) | |||
1141 | struct exynos_dp_platdata *pdata = dev->platform_data; | 1146 | struct exynos_dp_platdata *pdata = dev->platform_data; |
1142 | struct exynos_dp_device *dp = dev_get_drvdata(dev); | 1147 | struct exynos_dp_device *dp = dev_get_drvdata(dev); |
1143 | 1148 | ||
1149 | disable_irq(dp->irq); | ||
1150 | |||
1144 | flush_work(&dp->hotplug_work); | 1151 | flush_work(&dp->hotplug_work); |
1145 | 1152 | ||
1146 | if (dev->of_node) { | 1153 | if (dev->of_node) { |
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c index 4a17cdccef34..fac7df6d1aba 100644 --- a/drivers/video/exynos/exynos_mipi_dsi.c +++ b/drivers/video/exynos/exynos_mipi_dsi.c | |||
@@ -338,7 +338,8 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev) | |||
338 | struct mipi_dsim_ddi *dsim_ddi; | 338 | struct mipi_dsim_ddi *dsim_ddi; |
339 | int ret = -EINVAL; | 339 | int ret = -EINVAL; |
340 | 340 | ||
341 | dsim = kzalloc(sizeof(struct mipi_dsim_device), GFP_KERNEL); | 341 | dsim = devm_kzalloc(&pdev->dev, sizeof(struct mipi_dsim_device), |
342 | GFP_KERNEL); | ||
342 | if (!dsim) { | 343 | if (!dsim) { |
343 | dev_err(&pdev->dev, "failed to allocate dsim object.\n"); | 344 | dev_err(&pdev->dev, "failed to allocate dsim object.\n"); |
344 | return -ENOMEM; | 345 | return -ENOMEM; |
@@ -352,13 +353,13 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev) | |||
352 | dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd; | 353 | dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd; |
353 | if (dsim_pd == NULL) { | 354 | if (dsim_pd == NULL) { |
354 | dev_err(&pdev->dev, "failed to get platform data for dsim.\n"); | 355 | dev_err(&pdev->dev, "failed to get platform data for dsim.\n"); |
355 | goto err_clock_get; | 356 | return -EINVAL; |
356 | } | 357 | } |
357 | /* get mipi_dsim_config. */ | 358 | /* get mipi_dsim_config. */ |
358 | dsim_config = dsim_pd->dsim_config; | 359 | dsim_config = dsim_pd->dsim_config; |
359 | if (dsim_config == NULL) { | 360 | if (dsim_config == NULL) { |
360 | dev_err(&pdev->dev, "failed to get dsim config data.\n"); | 361 | dev_err(&pdev->dev, "failed to get dsim config data.\n"); |
361 | goto err_clock_get; | 362 | return -EINVAL; |
362 | } | 363 | } |
363 | 364 | ||
364 | dsim->dsim_config = dsim_config; | 365 | dsim->dsim_config = dsim_config; |
@@ -366,41 +367,28 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev) | |||
366 | 367 | ||
367 | mutex_init(&dsim->lock); | 368 | mutex_init(&dsim->lock); |
368 | 369 | ||
369 | ret = regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies), supplies); | 370 | ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies), |
371 | supplies); | ||
370 | if (ret) { | 372 | if (ret) { |
371 | dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret); | 373 | dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret); |
372 | goto err_clock_get; | 374 | return ret; |
373 | } | 375 | } |
374 | 376 | ||
375 | dsim->clock = clk_get(&pdev->dev, "dsim0"); | 377 | dsim->clock = devm_clk_get(&pdev->dev, "dsim0"); |
376 | if (IS_ERR(dsim->clock)) { | 378 | if (IS_ERR(dsim->clock)) { |
377 | dev_err(&pdev->dev, "failed to get dsim clock source\n"); | 379 | dev_err(&pdev->dev, "failed to get dsim clock source\n"); |
378 | ret = -ENODEV; | 380 | return -ENODEV; |
379 | goto err_clock_get; | ||
380 | } | 381 | } |
381 | 382 | ||
382 | clk_enable(dsim->clock); | 383 | clk_enable(dsim->clock); |
383 | 384 | ||
384 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 385 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
385 | if (!res) { | ||
386 | dev_err(&pdev->dev, "failed to get io memory region\n"); | ||
387 | ret = -ENODEV; | ||
388 | goto err_platform_get; | ||
389 | } | ||
390 | |||
391 | dsim->res = request_mem_region(res->start, resource_size(res), | ||
392 | dev_name(&pdev->dev)); | ||
393 | if (!dsim->res) { | ||
394 | dev_err(&pdev->dev, "failed to request io memory region\n"); | ||
395 | ret = -ENOMEM; | ||
396 | goto err_mem_region; | ||
397 | } | ||
398 | 386 | ||
399 | dsim->reg_base = ioremap(res->start, resource_size(res)); | 387 | dsim->reg_base = devm_request_and_ioremap(&pdev->dev, res); |
400 | if (!dsim->reg_base) { | 388 | if (!dsim->reg_base) { |
401 | dev_err(&pdev->dev, "failed to remap io region\n"); | 389 | dev_err(&pdev->dev, "failed to remap io region\n"); |
402 | ret = -ENOMEM; | 390 | ret = -ENOMEM; |
403 | goto err_ioremap; | 391 | goto error; |
404 | } | 392 | } |
405 | 393 | ||
406 | mutex_init(&dsim->lock); | 394 | mutex_init(&dsim->lock); |
@@ -410,26 +398,27 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev) | |||
410 | if (!dsim_ddi) { | 398 | if (!dsim_ddi) { |
411 | dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n"); | 399 | dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n"); |
412 | ret = -EINVAL; | 400 | ret = -EINVAL; |
413 | goto err_bind; | 401 | goto error; |
414 | } | 402 | } |
415 | 403 | ||
416 | dsim->irq = platform_get_irq(pdev, 0); | 404 | dsim->irq = platform_get_irq(pdev, 0); |
417 | if (dsim->irq < 0) { | 405 | if (IS_ERR_VALUE(dsim->irq)) { |
418 | dev_err(&pdev->dev, "failed to request dsim irq resource\n"); | 406 | dev_err(&pdev->dev, "failed to request dsim irq resource\n"); |
419 | ret = -EINVAL; | 407 | ret = -EINVAL; |
420 | goto err_platform_get_irq; | 408 | goto error; |
421 | } | 409 | } |
422 | 410 | ||
423 | init_completion(&dsim_wr_comp); | 411 | init_completion(&dsim_wr_comp); |
424 | init_completion(&dsim_rd_comp); | 412 | init_completion(&dsim_rd_comp); |
425 | platform_set_drvdata(pdev, dsim); | 413 | platform_set_drvdata(pdev, dsim); |
426 | 414 | ||
427 | ret = request_irq(dsim->irq, exynos_mipi_dsi_interrupt_handler, | 415 | ret = devm_request_irq(&pdev->dev, dsim->irq, |
416 | exynos_mipi_dsi_interrupt_handler, | ||
428 | IRQF_SHARED, dev_name(&pdev->dev), dsim); | 417 | IRQF_SHARED, dev_name(&pdev->dev), dsim); |
429 | if (ret != 0) { | 418 | if (ret != 0) { |
430 | dev_err(&pdev->dev, "failed to request dsim irq\n"); | 419 | dev_err(&pdev->dev, "failed to request dsim irq\n"); |
431 | ret = -EINVAL; | 420 | ret = -EINVAL; |
432 | goto err_bind; | 421 | goto error; |
433 | } | 422 | } |
434 | 423 | ||
435 | /* enable interrupts */ | 424 | /* enable interrupts */ |
@@ -471,22 +460,8 @@ done: | |||
471 | 460 | ||
472 | return 0; | 461 | return 0; |
473 | 462 | ||
474 | err_bind: | 463 | error: |
475 | iounmap(dsim->reg_base); | ||
476 | |||
477 | err_ioremap: | ||
478 | release_mem_region(dsim->res->start, resource_size(dsim->res)); | ||
479 | |||
480 | err_mem_region: | ||
481 | release_resource(dsim->res); | ||
482 | |||
483 | err_platform_get: | ||
484 | clk_disable(dsim->clock); | 464 | clk_disable(dsim->clock); |
485 | clk_put(dsim->clock); | ||
486 | err_clock_get: | ||
487 | kfree(dsim); | ||
488 | |||
489 | err_platform_get_irq: | ||
490 | return ret; | 465 | return ret; |
491 | } | 466 | } |
492 | 467 | ||
@@ -496,13 +471,7 @@ static int exynos_mipi_dsi_remove(struct platform_device *pdev) | |||
496 | struct mipi_dsim_ddi *dsim_ddi, *next; | 471 | struct mipi_dsim_ddi *dsim_ddi, *next; |
497 | struct mipi_dsim_lcd_driver *dsim_lcd_drv; | 472 | struct mipi_dsim_lcd_driver *dsim_lcd_drv; |
498 | 473 | ||
499 | iounmap(dsim->reg_base); | ||
500 | |||
501 | clk_disable(dsim->clock); | 474 | clk_disable(dsim->clock); |
502 | clk_put(dsim->clock); | ||
503 | |||
504 | release_resource(dsim->res); | ||
505 | release_mem_region(dsim->res->start, resource_size(dsim->res)); | ||
506 | 475 | ||
507 | list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) { | 476 | list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) { |
508 | if (dsim_ddi) { | 477 | if (dsim_ddi) { |
@@ -518,9 +487,6 @@ static int exynos_mipi_dsi_remove(struct platform_device *pdev) | |||
518 | } | 487 | } |
519 | } | 488 | } |
520 | 489 | ||
521 | regulator_bulk_free(ARRAY_SIZE(supplies), supplies); | ||
522 | kfree(dsim); | ||
523 | |||
524 | return 0; | 490 | return 0; |
525 | } | 491 | } |
526 | 492 | ||
diff --git a/drivers/video/exynos/s6e8ax0.c b/drivers/video/exynos/s6e8ax0.c index 05d080b63bc0..ca2602413aa4 100644 --- a/drivers/video/exynos/s6e8ax0.c +++ b/drivers/video/exynos/s6e8ax0.c | |||
@@ -776,7 +776,7 @@ static int s6e8ax0_probe(struct mipi_dsim_lcd_device *dsim_dev) | |||
776 | int ret; | 776 | int ret; |
777 | u8 mtp_id[3] = {0, }; | 777 | u8 mtp_id[3] = {0, }; |
778 | 778 | ||
779 | lcd = kzalloc(sizeof(struct s6e8ax0), GFP_KERNEL); | 779 | lcd = devm_kzalloc(&dsim_dev->dev, sizeof(struct s6e8ax0), GFP_KERNEL); |
780 | if (!lcd) { | 780 | if (!lcd) { |
781 | dev_err(&dsim_dev->dev, "failed to allocate s6e8ax0 structure.\n"); | 781 | dev_err(&dsim_dev->dev, "failed to allocate s6e8ax0 structure.\n"); |
782 | return -ENOMEM; | 782 | return -ENOMEM; |
@@ -788,18 +788,17 @@ static int s6e8ax0_probe(struct mipi_dsim_lcd_device *dsim_dev) | |||
788 | 788 | ||
789 | mutex_init(&lcd->lock); | 789 | mutex_init(&lcd->lock); |
790 | 790 | ||
791 | ret = regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies); | 791 | ret = devm_regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies); |
792 | if (ret) { | 792 | if (ret) { |
793 | dev_err(lcd->dev, "Failed to get regulators: %d\n", ret); | 793 | dev_err(lcd->dev, "Failed to get regulators: %d\n", ret); |
794 | goto err_lcd_register; | 794 | return ret; |
795 | } | 795 | } |
796 | 796 | ||
797 | lcd->ld = lcd_device_register("s6e8ax0", lcd->dev, lcd, | 797 | lcd->ld = lcd_device_register("s6e8ax0", lcd->dev, lcd, |
798 | &s6e8ax0_lcd_ops); | 798 | &s6e8ax0_lcd_ops); |
799 | if (IS_ERR(lcd->ld)) { | 799 | if (IS_ERR(lcd->ld)) { |
800 | dev_err(lcd->dev, "failed to register lcd ops.\n"); | 800 | dev_err(lcd->dev, "failed to register lcd ops.\n"); |
801 | ret = PTR_ERR(lcd->ld); | 801 | return PTR_ERR(lcd->ld); |
802 | goto err_lcd_register; | ||
803 | } | 802 | } |
804 | 803 | ||
805 | lcd->bd = backlight_device_register("s6e8ax0-bl", lcd->dev, lcd, | 804 | lcd->bd = backlight_device_register("s6e8ax0-bl", lcd->dev, lcd, |
@@ -838,11 +837,6 @@ static int s6e8ax0_probe(struct mipi_dsim_lcd_device *dsim_dev) | |||
838 | 837 | ||
839 | err_backlight_register: | 838 | err_backlight_register: |
840 | lcd_device_unregister(lcd->ld); | 839 | lcd_device_unregister(lcd->ld); |
841 | |||
842 | err_lcd_register: | ||
843 | regulator_bulk_free(ARRAY_SIZE(supplies), supplies); | ||
844 | kfree(lcd); | ||
845 | |||
846 | return ret; | 840 | return ret; |
847 | } | 841 | } |
848 | 842 | ||
diff --git a/drivers/video/goldfishfb.c b/drivers/video/goldfishfb.c new file mode 100644 index 000000000000..489abb32fc04 --- /dev/null +++ b/drivers/video/goldfishfb.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Google, Inc. | ||
3 | * Copyright (C) 2012 Intel, Inc. | ||
4 | * | ||
5 | * This software is licensed under the terms of the GNU General Public | ||
6 | * License version 2, as published by the Free Software Foundation, and | ||
7 | * may be copied, distributed, and modified under those terms. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/string.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/mm.h> | ||
24 | #include <linux/fb.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/ioport.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | |||
30 | enum { | ||
31 | FB_GET_WIDTH = 0x00, | ||
32 | FB_GET_HEIGHT = 0x04, | ||
33 | FB_INT_STATUS = 0x08, | ||
34 | FB_INT_ENABLE = 0x0c, | ||
35 | FB_SET_BASE = 0x10, | ||
36 | FB_SET_ROTATION = 0x14, | ||
37 | FB_SET_BLANK = 0x18, | ||
38 | FB_GET_PHYS_WIDTH = 0x1c, | ||
39 | FB_GET_PHYS_HEIGHT = 0x20, | ||
40 | |||
41 | FB_INT_VSYNC = 1U << 0, | ||
42 | FB_INT_BASE_UPDATE_DONE = 1U << 1 | ||
43 | }; | ||
44 | |||
45 | struct goldfish_fb { | ||
46 | void __iomem *reg_base; | ||
47 | int irq; | ||
48 | spinlock_t lock; | ||
49 | wait_queue_head_t wait; | ||
50 | int base_update_count; | ||
51 | int rotation; | ||
52 | struct fb_info fb; | ||
53 | u32 cmap[16]; | ||
54 | }; | ||
55 | |||
56 | static irqreturn_t goldfish_fb_interrupt(int irq, void *dev_id) | ||
57 | { | ||
58 | unsigned long irq_flags; | ||
59 | struct goldfish_fb *fb = dev_id; | ||
60 | u32 status; | ||
61 | |||
62 | spin_lock_irqsave(&fb->lock, irq_flags); | ||
63 | status = readl(fb->reg_base + FB_INT_STATUS); | ||
64 | if (status & FB_INT_BASE_UPDATE_DONE) { | ||
65 | fb->base_update_count++; | ||
66 | wake_up(&fb->wait); | ||
67 | } | ||
68 | spin_unlock_irqrestore(&fb->lock, irq_flags); | ||
69 | return status ? IRQ_HANDLED : IRQ_NONE; | ||
70 | } | ||
71 | |||
72 | static inline u32 convert_bitfield(int val, struct fb_bitfield *bf) | ||
73 | { | ||
74 | unsigned int mask = (1 << bf->length) - 1; | ||
75 | |||
76 | return (val >> (16 - bf->length) & mask) << bf->offset; | ||
77 | } | ||
78 | |||
79 | static int | ||
80 | goldfish_fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, | ||
81 | unsigned int blue, unsigned int transp, struct fb_info *info) | ||
82 | { | ||
83 | struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb); | ||
84 | |||
85 | if (regno < 16) { | ||
86 | fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) | | ||
87 | convert_bitfield(blue, &fb->fb.var.blue) | | ||
88 | convert_bitfield(green, &fb->fb.var.green) | | ||
89 | convert_bitfield(red, &fb->fb.var.red); | ||
90 | return 0; | ||
91 | } else { | ||
92 | return 1; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | static int goldfish_fb_check_var(struct fb_var_screeninfo *var, | ||
97 | struct fb_info *info) | ||
98 | { | ||
99 | if ((var->rotate & 1) != (info->var.rotate & 1)) { | ||
100 | if ((var->xres != info->var.yres) || | ||
101 | (var->yres != info->var.xres) || | ||
102 | (var->xres_virtual != info->var.yres) || | ||
103 | (var->yres_virtual > info->var.xres * 2) || | ||
104 | (var->yres_virtual < info->var.xres)) { | ||
105 | return -EINVAL; | ||
106 | } | ||
107 | } else { | ||
108 | if ((var->xres != info->var.xres) || | ||
109 | (var->yres != info->var.yres) || | ||
110 | (var->xres_virtual != info->var.xres) || | ||
111 | (var->yres_virtual > info->var.yres * 2) || | ||
112 | (var->yres_virtual < info->var.yres)) { | ||
113 | return -EINVAL; | ||
114 | } | ||
115 | } | ||
116 | if ((var->xoffset != info->var.xoffset) || | ||
117 | (var->bits_per_pixel != info->var.bits_per_pixel) || | ||
118 | (var->grayscale != info->var.grayscale)) { | ||
119 | return -EINVAL; | ||
120 | } | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static int goldfish_fb_set_par(struct fb_info *info) | ||
125 | { | ||
126 | struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb); | ||
127 | if (fb->rotation != fb->fb.var.rotate) { | ||
128 | info->fix.line_length = info->var.xres * 2; | ||
129 | fb->rotation = fb->fb.var.rotate; | ||
130 | writel(fb->rotation, fb->reg_base + FB_SET_ROTATION); | ||
131 | } | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | |||
136 | static int goldfish_fb_pan_display(struct fb_var_screeninfo *var, | ||
137 | struct fb_info *info) | ||
138 | { | ||
139 | unsigned long irq_flags; | ||
140 | int base_update_count; | ||
141 | struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb); | ||
142 | |||
143 | spin_lock_irqsave(&fb->lock, irq_flags); | ||
144 | base_update_count = fb->base_update_count; | ||
145 | writel(fb->fb.fix.smem_start + fb->fb.var.xres * 2 * var->yoffset, | ||
146 | fb->reg_base + FB_SET_BASE); | ||
147 | spin_unlock_irqrestore(&fb->lock, irq_flags); | ||
148 | wait_event_timeout(fb->wait, | ||
149 | fb->base_update_count != base_update_count, HZ / 15); | ||
150 | if (fb->base_update_count == base_update_count) | ||
151 | pr_err("goldfish_fb_pan_display: timeout wating for base update\n"); | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int goldfish_fb_blank(int blank, struct fb_info *info) | ||
156 | { | ||
157 | struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb); | ||
158 | switch (blank) { | ||
159 | case FB_BLANK_NORMAL: | ||
160 | writel(1, fb->reg_base + FB_SET_BLANK); | ||
161 | break; | ||
162 | case FB_BLANK_UNBLANK: | ||
163 | writel(0, fb->reg_base + FB_SET_BLANK); | ||
164 | break; | ||
165 | } | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static struct fb_ops goldfish_fb_ops = { | ||
170 | .owner = THIS_MODULE, | ||
171 | .fb_check_var = goldfish_fb_check_var, | ||
172 | .fb_set_par = goldfish_fb_set_par, | ||
173 | .fb_setcolreg = goldfish_fb_setcolreg, | ||
174 | .fb_pan_display = goldfish_fb_pan_display, | ||
175 | .fb_blank = goldfish_fb_blank, | ||
176 | .fb_fillrect = cfb_fillrect, | ||
177 | .fb_copyarea = cfb_copyarea, | ||
178 | .fb_imageblit = cfb_imageblit, | ||
179 | }; | ||
180 | |||
181 | |||
182 | static int goldfish_fb_probe(struct platform_device *pdev) | ||
183 | { | ||
184 | int ret; | ||
185 | struct resource *r; | ||
186 | struct goldfish_fb *fb; | ||
187 | size_t framesize; | ||
188 | u32 width, height; | ||
189 | dma_addr_t fbpaddr; | ||
190 | |||
191 | fb = kzalloc(sizeof(*fb), GFP_KERNEL); | ||
192 | if (fb == NULL) { | ||
193 | ret = -ENOMEM; | ||
194 | goto err_fb_alloc_failed; | ||
195 | } | ||
196 | spin_lock_init(&fb->lock); | ||
197 | init_waitqueue_head(&fb->wait); | ||
198 | platform_set_drvdata(pdev, fb); | ||
199 | |||
200 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
201 | if (r == NULL) { | ||
202 | ret = -ENODEV; | ||
203 | goto err_no_io_base; | ||
204 | } | ||
205 | fb->reg_base = ioremap(r->start, PAGE_SIZE); | ||
206 | if (fb->reg_base == NULL) { | ||
207 | ret = -ENOMEM; | ||
208 | goto err_no_io_base; | ||
209 | } | ||
210 | |||
211 | fb->irq = platform_get_irq(pdev, 0); | ||
212 | if (fb->irq <= 0) { | ||
213 | ret = -ENODEV; | ||
214 | goto err_no_irq; | ||
215 | } | ||
216 | |||
217 | width = readl(fb->reg_base + FB_GET_WIDTH); | ||
218 | height = readl(fb->reg_base + FB_GET_HEIGHT); | ||
219 | |||
220 | fb->fb.fbops = &goldfish_fb_ops; | ||
221 | fb->fb.flags = FBINFO_FLAG_DEFAULT; | ||
222 | fb->fb.pseudo_palette = fb->cmap; | ||
223 | fb->fb.fix.type = FB_TYPE_PACKED_PIXELS; | ||
224 | fb->fb.fix.visual = FB_VISUAL_TRUECOLOR; | ||
225 | fb->fb.fix.line_length = width * 2; | ||
226 | fb->fb.fix.accel = FB_ACCEL_NONE; | ||
227 | fb->fb.fix.ypanstep = 1; | ||
228 | |||
229 | fb->fb.var.xres = width; | ||
230 | fb->fb.var.yres = height; | ||
231 | fb->fb.var.xres_virtual = width; | ||
232 | fb->fb.var.yres_virtual = height * 2; | ||
233 | fb->fb.var.bits_per_pixel = 16; | ||
234 | fb->fb.var.activate = FB_ACTIVATE_NOW; | ||
235 | fb->fb.var.height = readl(fb->reg_base + FB_GET_PHYS_HEIGHT); | ||
236 | fb->fb.var.width = readl(fb->reg_base + FB_GET_PHYS_WIDTH); | ||
237 | fb->fb.var.pixclock = 10000; | ||
238 | |||
239 | fb->fb.var.red.offset = 11; | ||
240 | fb->fb.var.red.length = 5; | ||
241 | fb->fb.var.green.offset = 5; | ||
242 | fb->fb.var.green.length = 6; | ||
243 | fb->fb.var.blue.offset = 0; | ||
244 | fb->fb.var.blue.length = 5; | ||
245 | |||
246 | framesize = width * height * 2 * 2; | ||
247 | fb->fb.screen_base = (char __force __iomem *)dma_alloc_coherent( | ||
248 | &pdev->dev, framesize, | ||
249 | &fbpaddr, GFP_KERNEL); | ||
250 | pr_debug("allocating frame buffer %d * %d, got %p\n", | ||
251 | width, height, fb->fb.screen_base); | ||
252 | if (fb->fb.screen_base == NULL) { | ||
253 | ret = -ENOMEM; | ||
254 | goto err_alloc_screen_base_failed; | ||
255 | } | ||
256 | fb->fb.fix.smem_start = fbpaddr; | ||
257 | fb->fb.fix.smem_len = framesize; | ||
258 | |||
259 | ret = fb_set_var(&fb->fb, &fb->fb.var); | ||
260 | if (ret) | ||
261 | goto err_fb_set_var_failed; | ||
262 | |||
263 | ret = request_irq(fb->irq, goldfish_fb_interrupt, IRQF_SHARED, | ||
264 | pdev->name, fb); | ||
265 | if (ret) | ||
266 | goto err_request_irq_failed; | ||
267 | |||
268 | writel(FB_INT_BASE_UPDATE_DONE, fb->reg_base + FB_INT_ENABLE); | ||
269 | goldfish_fb_pan_display(&fb->fb.var, &fb->fb); /* updates base */ | ||
270 | |||
271 | ret = register_framebuffer(&fb->fb); | ||
272 | if (ret) | ||
273 | goto err_register_framebuffer_failed; | ||
274 | return 0; | ||
275 | |||
276 | err_register_framebuffer_failed: | ||
277 | free_irq(fb->irq, fb); | ||
278 | err_request_irq_failed: | ||
279 | err_fb_set_var_failed: | ||
280 | dma_free_coherent(&pdev->dev, framesize, | ||
281 | (void *)fb->fb.screen_base, | ||
282 | fb->fb.fix.smem_start); | ||
283 | err_alloc_screen_base_failed: | ||
284 | err_no_irq: | ||
285 | iounmap(fb->reg_base); | ||
286 | err_no_io_base: | ||
287 | kfree(fb); | ||
288 | err_fb_alloc_failed: | ||
289 | return ret; | ||
290 | } | ||
291 | |||
292 | static int goldfish_fb_remove(struct platform_device *pdev) | ||
293 | { | ||
294 | size_t framesize; | ||
295 | struct goldfish_fb *fb = platform_get_drvdata(pdev); | ||
296 | |||
297 | framesize = fb->fb.var.xres_virtual * fb->fb.var.yres_virtual * 2; | ||
298 | unregister_framebuffer(&fb->fb); | ||
299 | free_irq(fb->irq, fb); | ||
300 | |||
301 | dma_free_coherent(&pdev->dev, framesize, (void *)fb->fb.screen_base, | ||
302 | fb->fb.fix.smem_start); | ||
303 | iounmap(fb->reg_base); | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | |||
308 | static struct platform_driver goldfish_fb_driver = { | ||
309 | .probe = goldfish_fb_probe, | ||
310 | .remove = goldfish_fb_remove, | ||
311 | .driver = { | ||
312 | .name = "goldfish_fb" | ||
313 | } | ||
314 | }; | ||
315 | |||
316 | module_platform_driver(goldfish_fb_driver); | ||
317 | |||
318 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/mmp/Kconfig b/drivers/video/mmp/Kconfig new file mode 100644 index 000000000000..e9ea39e13722 --- /dev/null +++ b/drivers/video/mmp/Kconfig | |||
@@ -0,0 +1,11 @@ | |||
1 | menuconfig MMP_DISP | ||
2 | tristate "Marvell MMP Display Subsystem support" | ||
3 | depends on CPU_PXA910 || CPU_MMP2 || CPU_MMP3 || CPU_PXA988 | ||
4 | help | ||
5 | Marvell Display Subsystem support. | ||
6 | |||
7 | if MMP_DISP | ||
8 | source "drivers/video/mmp/hw/Kconfig" | ||
9 | source "drivers/video/mmp/panel/Kconfig" | ||
10 | source "drivers/video/mmp/fb/Kconfig" | ||
11 | endif | ||
diff --git a/drivers/video/mmp/Makefile b/drivers/video/mmp/Makefile new file mode 100644 index 000000000000..a014cb358bf8 --- /dev/null +++ b/drivers/video/mmp/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-y += core.o hw/ panel/ fb/ | |||
diff --git a/drivers/video/mmp/core.c b/drivers/video/mmp/core.c new file mode 100644 index 000000000000..9ed83419038b --- /dev/null +++ b/drivers/video/mmp/core.c | |||
@@ -0,0 +1,258 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/mmp/common.c | ||
3 | * This driver is a common framework for Marvell Display Controller | ||
4 | * | ||
5 | * Copyright (C) 2012 Marvell Technology Group Ltd. | ||
6 | * Authors: Zhou Zhu <zzhu3@marvell.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/slab.h> | ||
24 | #include <linux/dma-mapping.h> | ||
25 | #include <linux/export.h> | ||
26 | #include <video/mmp_disp.h> | ||
27 | |||
28 | static struct mmp_overlay *path_get_overlay(struct mmp_path *path, | ||
29 | int overlay_id) | ||
30 | { | ||
31 | if (path && overlay_id < path->overlay_num) | ||
32 | return &path->overlays[overlay_id]; | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static int path_check_status(struct mmp_path *path) | ||
37 | { | ||
38 | int i; | ||
39 | for (i = 0; i < path->overlay_num; i++) | ||
40 | if (path->overlays[i].status) | ||
41 | return 1; | ||
42 | |||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | /* | ||
47 | * Get modelist write pointer of modelist. | ||
48 | * It also returns modelist number | ||
49 | * this function fetches modelist from phy/panel: | ||
50 | * for HDMI/parallel or dsi to hdmi cases, get from phy | ||
51 | * or get from panel | ||
52 | */ | ||
53 | static int path_get_modelist(struct mmp_path *path, | ||
54 | struct mmp_mode **modelist) | ||
55 | { | ||
56 | BUG_ON(!path || !modelist); | ||
57 | |||
58 | if (path->panel && path->panel->get_modelist) | ||
59 | return path->panel->get_modelist(path->panel, modelist); | ||
60 | |||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | /* | ||
65 | * panel list is used to pair panel/path when path/panel registered | ||
66 | * path list is used for both buffer driver and platdriver | ||
67 | * plat driver do path register/unregister | ||
68 | * panel driver do panel register/unregister | ||
69 | * buffer driver get registered path | ||
70 | */ | ||
71 | static LIST_HEAD(panel_list); | ||
72 | static LIST_HEAD(path_list); | ||
73 | static DEFINE_MUTEX(disp_lock); | ||
74 | |||
75 | /* | ||
76 | * mmp_register_panel - register panel to panel_list and connect to path | ||
77 | * @p: panel to be registered | ||
78 | * | ||
79 | * this function provides interface for panel drivers to register panel | ||
80 | * to panel_list and connect to path which matchs panel->plat_path_name. | ||
81 | * no error returns when no matching path is found as path register after | ||
82 | * panel register is permitted. | ||
83 | */ | ||
84 | void mmp_register_panel(struct mmp_panel *panel) | ||
85 | { | ||
86 | struct mmp_path *path; | ||
87 | |||
88 | mutex_lock(&disp_lock); | ||
89 | |||
90 | /* add */ | ||
91 | list_add_tail(&panel->node, &panel_list); | ||
92 | |||
93 | /* try to register to path */ | ||
94 | list_for_each_entry(path, &path_list, node) { | ||
95 | if (!strcmp(panel->plat_path_name, path->name)) { | ||
96 | dev_info(panel->dev, "connect to path %s\n", | ||
97 | path->name); | ||
98 | path->panel = panel; | ||
99 | break; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | mutex_unlock(&disp_lock); | ||
104 | } | ||
105 | EXPORT_SYMBOL_GPL(mmp_register_panel); | ||
106 | |||
107 | /* | ||
108 | * mmp_unregister_panel - unregister panel from panel_list and disconnect | ||
109 | * @p: panel to be unregistered | ||
110 | * | ||
111 | * this function provides interface for panel drivers to unregister panel | ||
112 | * from panel_list and disconnect from path. | ||
113 | */ | ||
114 | void mmp_unregister_panel(struct mmp_panel *panel) | ||
115 | { | ||
116 | struct mmp_path *path; | ||
117 | |||
118 | mutex_lock(&disp_lock); | ||
119 | list_del(&panel->node); | ||
120 | |||
121 | list_for_each_entry(path, &path_list, node) { | ||
122 | if (path->panel && path->panel == panel) { | ||
123 | dev_info(panel->dev, "disconnect from path %s\n", | ||
124 | path->name); | ||
125 | path->panel = NULL; | ||
126 | break; | ||
127 | } | ||
128 | } | ||
129 | mutex_unlock(&disp_lock); | ||
130 | } | ||
131 | EXPORT_SYMBOL_GPL(mmp_unregister_panel); | ||
132 | |||
133 | /* | ||
134 | * mmp_get_path - get path by name | ||
135 | * @p: path name | ||
136 | * | ||
137 | * this function checks path name in path_list and return matching path | ||
138 | * return NULL if no matching path | ||
139 | */ | ||
140 | struct mmp_path *mmp_get_path(const char *name) | ||
141 | { | ||
142 | struct mmp_path *path; | ||
143 | int found = 0; | ||
144 | |||
145 | mutex_lock(&disp_lock); | ||
146 | list_for_each_entry(path, &path_list, node) { | ||
147 | if (!strcmp(name, path->name)) { | ||
148 | found = 1; | ||
149 | break; | ||
150 | } | ||
151 | } | ||
152 | mutex_unlock(&disp_lock); | ||
153 | |||
154 | return found ? path : NULL; | ||
155 | } | ||
156 | EXPORT_SYMBOL_GPL(mmp_get_path); | ||
157 | |||
158 | /* | ||
159 | * mmp_register_path - init and register path by path_info | ||
160 | * @p: path info provided by display controller | ||
161 | * | ||
162 | * this function init by path info and register path to path_list | ||
163 | * this function also try to connect path with panel by name | ||
164 | */ | ||
165 | struct mmp_path *mmp_register_path(struct mmp_path_info *info) | ||
166 | { | ||
167 | int i; | ||
168 | size_t size; | ||
169 | struct mmp_path *path = NULL; | ||
170 | struct mmp_panel *panel; | ||
171 | |||
172 | size = sizeof(struct mmp_path) | ||
173 | + sizeof(struct mmp_overlay) * info->overlay_num; | ||
174 | path = kzalloc(size, GFP_KERNEL); | ||
175 | if (!path) | ||
176 | goto failed; | ||
177 | |||
178 | /* path set */ | ||
179 | mutex_init(&path->access_ok); | ||
180 | path->dev = info->dev; | ||
181 | path->id = info->id; | ||
182 | path->name = info->name; | ||
183 | path->output_type = info->output_type; | ||
184 | path->overlay_num = info->overlay_num; | ||
185 | path->plat_data = info->plat_data; | ||
186 | path->ops.set_mode = info->set_mode; | ||
187 | |||
188 | mutex_lock(&disp_lock); | ||
189 | /* get panel */ | ||
190 | list_for_each_entry(panel, &panel_list, node) { | ||
191 | if (!strcmp(info->name, panel->plat_path_name)) { | ||
192 | dev_info(path->dev, "get panel %s\n", panel->name); | ||
193 | path->panel = panel; | ||
194 | break; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | dev_info(path->dev, "register %s, overlay_num %d\n", | ||
199 | path->name, path->overlay_num); | ||
200 | |||
201 | /* default op set: if already set by driver, never cover it */ | ||
202 | if (!path->ops.check_status) | ||
203 | path->ops.check_status = path_check_status; | ||
204 | if (!path->ops.get_overlay) | ||
205 | path->ops.get_overlay = path_get_overlay; | ||
206 | if (!path->ops.get_modelist) | ||
207 | path->ops.get_modelist = path_get_modelist; | ||
208 | |||
209 | /* step3: init overlays */ | ||
210 | for (i = 0; i < path->overlay_num; i++) { | ||
211 | path->overlays[i].path = path; | ||
212 | path->overlays[i].id = i; | ||
213 | mutex_init(&path->overlays[i].access_ok); | ||
214 | path->overlays[i].ops = info->overlay_ops; | ||
215 | } | ||
216 | |||
217 | /* add to pathlist */ | ||
218 | list_add_tail(&path->node, &path_list); | ||
219 | |||
220 | mutex_unlock(&disp_lock); | ||
221 | return path; | ||
222 | |||
223 | failed: | ||
224 | kfree(path); | ||
225 | mutex_unlock(&disp_lock); | ||
226 | return NULL; | ||
227 | } | ||
228 | EXPORT_SYMBOL_GPL(mmp_register_path); | ||
229 | |||
230 | /* | ||
231 | * mmp_unregister_path - unregister and destory path | ||
232 | * @p: path to be destoried. | ||
233 | * | ||
234 | * this function registers path and destorys it. | ||
235 | */ | ||
236 | void mmp_unregister_path(struct mmp_path *path) | ||
237 | { | ||
238 | int i; | ||
239 | |||
240 | if (!path) | ||
241 | return; | ||
242 | |||
243 | mutex_lock(&disp_lock); | ||
244 | /* del from pathlist */ | ||
245 | list_del(&path->node); | ||
246 | |||
247 | /* deinit overlays */ | ||
248 | for (i = 0; i < path->overlay_num; i++) | ||
249 | mutex_destroy(&path->overlays[i].access_ok); | ||
250 | |||
251 | mutex_destroy(&path->access_ok); | ||
252 | |||
253 | kfree(path); | ||
254 | mutex_unlock(&disp_lock); | ||
255 | |||
256 | dev_info(path->dev, "de-register %s\n", path->name); | ||
257 | } | ||
258 | EXPORT_SYMBOL_GPL(mmp_unregister_path); | ||
diff --git a/drivers/video/mmp/fb/Kconfig b/drivers/video/mmp/fb/Kconfig new file mode 100644 index 000000000000..9b0141f105f5 --- /dev/null +++ b/drivers/video/mmp/fb/Kconfig | |||
@@ -0,0 +1,13 @@ | |||
1 | if MMP_DISP | ||
2 | |||
3 | config MMP_FB | ||
4 | bool "fb driver for Marvell MMP Display Subsystem" | ||
5 | depends on FB | ||
6 | select FB_CFB_FILLRECT | ||
7 | select FB_CFB_COPYAREA | ||
8 | select FB_CFB_IMAGEBLIT | ||
9 | default y | ||
10 | help | ||
11 | fb driver for Marvell MMP Display Subsystem | ||
12 | |||
13 | endif | ||
diff --git a/drivers/video/mmp/fb/Makefile b/drivers/video/mmp/fb/Makefile new file mode 100644 index 000000000000..709fd1f76abe --- /dev/null +++ b/drivers/video/mmp/fb/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_MMP_FB) += mmpfb.o | |||
diff --git a/drivers/video/mmp/fb/mmpfb.c b/drivers/video/mmp/fb/mmpfb.c new file mode 100644 index 000000000000..6d1fa96c5cc3 --- /dev/null +++ b/drivers/video/mmp/fb/mmpfb.c | |||
@@ -0,0 +1,685 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/mmp/fb/mmpfb.c | ||
3 | * Framebuffer driver for Marvell Display controller. | ||
4 | * | ||
5 | * Copyright (C) 2012 Marvell Technology Group Ltd. | ||
6 | * Authors: Zhou Zhu <zzhu3@marvell.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | * | ||
21 | */ | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/dma-mapping.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include "mmpfb.h" | ||
26 | |||
27 | static int var_to_pixfmt(struct fb_var_screeninfo *var) | ||
28 | { | ||
29 | /* | ||
30 | * Pseudocolor mode? | ||
31 | */ | ||
32 | if (var->bits_per_pixel == 8) | ||
33 | return PIXFMT_PSEUDOCOLOR; | ||
34 | |||
35 | /* | ||
36 | * Check for YUV422PLANAR. | ||
37 | */ | ||
38 | if (var->bits_per_pixel == 16 && var->red.length == 8 && | ||
39 | var->green.length == 4 && var->blue.length == 4) { | ||
40 | if (var->green.offset >= var->blue.offset) | ||
41 | return PIXFMT_YUV422P; | ||
42 | else | ||
43 | return PIXFMT_YVU422P; | ||
44 | } | ||
45 | |||
46 | /* | ||
47 | * Check for YUV420PLANAR. | ||
48 | */ | ||
49 | if (var->bits_per_pixel == 12 && var->red.length == 8 && | ||
50 | var->green.length == 2 && var->blue.length == 2) { | ||
51 | if (var->green.offset >= var->blue.offset) | ||
52 | return PIXFMT_YUV420P; | ||
53 | else | ||
54 | return PIXFMT_YVU420P; | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * Check for YUV422PACK. | ||
59 | */ | ||
60 | if (var->bits_per_pixel == 16 && var->red.length == 16 && | ||
61 | var->green.length == 16 && var->blue.length == 16) { | ||
62 | if (var->red.offset == 0) | ||
63 | return PIXFMT_YUYV; | ||
64 | else if (var->green.offset >= var->blue.offset) | ||
65 | return PIXFMT_UYVY; | ||
66 | else | ||
67 | return PIXFMT_VYUY; | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * Check for 565/1555. | ||
72 | */ | ||
73 | if (var->bits_per_pixel == 16 && var->red.length <= 5 && | ||
74 | var->green.length <= 6 && var->blue.length <= 5) { | ||
75 | if (var->transp.length == 0) { | ||
76 | if (var->red.offset >= var->blue.offset) | ||
77 | return PIXFMT_RGB565; | ||
78 | else | ||
79 | return PIXFMT_BGR565; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Check for 888/A888. | ||
85 | */ | ||
86 | if (var->bits_per_pixel <= 32 && var->red.length <= 8 && | ||
87 | var->green.length <= 8 && var->blue.length <= 8) { | ||
88 | if (var->bits_per_pixel == 24 && var->transp.length == 0) { | ||
89 | if (var->red.offset >= var->blue.offset) | ||
90 | return PIXFMT_RGB888PACK; | ||
91 | else | ||
92 | return PIXFMT_BGR888PACK; | ||
93 | } | ||
94 | |||
95 | if (var->bits_per_pixel == 32 && var->transp.offset == 24) { | ||
96 | if (var->red.offset >= var->blue.offset) | ||
97 | return PIXFMT_RGBA888; | ||
98 | else | ||
99 | return PIXFMT_BGRA888; | ||
100 | } else { | ||
101 | if (var->red.offset >= var->blue.offset) | ||
102 | return PIXFMT_RGB888UNPACK; | ||
103 | else | ||
104 | return PIXFMT_BGR888UNPACK; | ||
105 | } | ||
106 | |||
107 | /* fall through */ | ||
108 | } | ||
109 | |||
110 | return -EINVAL; | ||
111 | } | ||
112 | |||
113 | static void pixfmt_to_var(struct fb_var_screeninfo *var, int pix_fmt) | ||
114 | { | ||
115 | switch (pix_fmt) { | ||
116 | case PIXFMT_RGB565: | ||
117 | var->bits_per_pixel = 16; | ||
118 | var->red.offset = 11; var->red.length = 5; | ||
119 | var->green.offset = 5; var->green.length = 6; | ||
120 | var->blue.offset = 0; var->blue.length = 5; | ||
121 | var->transp.offset = 0; var->transp.length = 0; | ||
122 | break; | ||
123 | case PIXFMT_BGR565: | ||
124 | var->bits_per_pixel = 16; | ||
125 | var->red.offset = 0; var->red.length = 5; | ||
126 | var->green.offset = 5; var->green.length = 6; | ||
127 | var->blue.offset = 11; var->blue.length = 5; | ||
128 | var->transp.offset = 0; var->transp.length = 0; | ||
129 | break; | ||
130 | case PIXFMT_RGB888UNPACK: | ||
131 | var->bits_per_pixel = 32; | ||
132 | var->red.offset = 16; var->red.length = 8; | ||
133 | var->green.offset = 8; var->green.length = 8; | ||
134 | var->blue.offset = 0; var->blue.length = 8; | ||
135 | var->transp.offset = 0; var->transp.length = 0; | ||
136 | break; | ||
137 | case PIXFMT_BGR888UNPACK: | ||
138 | var->bits_per_pixel = 32; | ||
139 | var->red.offset = 0; var->red.length = 8; | ||
140 | var->green.offset = 8; var->green.length = 8; | ||
141 | var->blue.offset = 16; var->blue.length = 8; | ||
142 | var->transp.offset = 0; var->transp.length = 0; | ||
143 | break; | ||
144 | case PIXFMT_RGBA888: | ||
145 | var->bits_per_pixel = 32; | ||
146 | var->red.offset = 16; var->red.length = 8; | ||
147 | var->green.offset = 8; var->green.length = 8; | ||
148 | var->blue.offset = 0; var->blue.length = 8; | ||
149 | var->transp.offset = 24; var->transp.length = 8; | ||
150 | break; | ||
151 | case PIXFMT_BGRA888: | ||
152 | var->bits_per_pixel = 32; | ||
153 | var->red.offset = 0; var->red.length = 8; | ||
154 | var->green.offset = 8; var->green.length = 8; | ||
155 | var->blue.offset = 16; var->blue.length = 8; | ||
156 | var->transp.offset = 24; var->transp.length = 8; | ||
157 | break; | ||
158 | case PIXFMT_RGB888PACK: | ||
159 | var->bits_per_pixel = 24; | ||
160 | var->red.offset = 16; var->red.length = 8; | ||
161 | var->green.offset = 8; var->green.length = 8; | ||
162 | var->blue.offset = 0; var->blue.length = 8; | ||
163 | var->transp.offset = 0; var->transp.length = 0; | ||
164 | break; | ||
165 | case PIXFMT_BGR888PACK: | ||
166 | var->bits_per_pixel = 24; | ||
167 | var->red.offset = 0; var->red.length = 8; | ||
168 | var->green.offset = 8; var->green.length = 8; | ||
169 | var->blue.offset = 16; var->blue.length = 8; | ||
170 | var->transp.offset = 0; var->transp.length = 0; | ||
171 | break; | ||
172 | case PIXFMT_YUV420P: | ||
173 | var->bits_per_pixel = 12; | ||
174 | var->red.offset = 4; var->red.length = 8; | ||
175 | var->green.offset = 2; var->green.length = 2; | ||
176 | var->blue.offset = 0; var->blue.length = 2; | ||
177 | var->transp.offset = 0; var->transp.length = 0; | ||
178 | break; | ||
179 | case PIXFMT_YVU420P: | ||
180 | var->bits_per_pixel = 12; | ||
181 | var->red.offset = 4; var->red.length = 8; | ||
182 | var->green.offset = 0; var->green.length = 2; | ||
183 | var->blue.offset = 2; var->blue.length = 2; | ||
184 | var->transp.offset = 0; var->transp.length = 0; | ||
185 | break; | ||
186 | case PIXFMT_YUV422P: | ||
187 | var->bits_per_pixel = 16; | ||
188 | var->red.offset = 8; var->red.length = 8; | ||
189 | var->green.offset = 4; var->green.length = 4; | ||
190 | var->blue.offset = 0; var->blue.length = 4; | ||
191 | var->transp.offset = 0; var->transp.length = 0; | ||
192 | break; | ||
193 | case PIXFMT_YVU422P: | ||
194 | var->bits_per_pixel = 16; | ||
195 | var->red.offset = 8; var->red.length = 8; | ||
196 | var->green.offset = 0; var->green.length = 4; | ||
197 | var->blue.offset = 4; var->blue.length = 4; | ||
198 | var->transp.offset = 0; var->transp.length = 0; | ||
199 | break; | ||
200 | case PIXFMT_UYVY: | ||
201 | var->bits_per_pixel = 16; | ||
202 | var->red.offset = 8; var->red.length = 16; | ||
203 | var->green.offset = 4; var->green.length = 16; | ||
204 | var->blue.offset = 0; var->blue.length = 16; | ||
205 | var->transp.offset = 0; var->transp.length = 0; | ||
206 | break; | ||
207 | case PIXFMT_VYUY: | ||
208 | var->bits_per_pixel = 16; | ||
209 | var->red.offset = 8; var->red.length = 16; | ||
210 | var->green.offset = 0; var->green.length = 16; | ||
211 | var->blue.offset = 4; var->blue.length = 16; | ||
212 | var->transp.offset = 0; var->transp.length = 0; | ||
213 | break; | ||
214 | case PIXFMT_YUYV: | ||
215 | var->bits_per_pixel = 16; | ||
216 | var->red.offset = 0; var->red.length = 16; | ||
217 | var->green.offset = 4; var->green.length = 16; | ||
218 | var->blue.offset = 8; var->blue.length = 16; | ||
219 | var->transp.offset = 0; var->transp.length = 0; | ||
220 | break; | ||
221 | case PIXFMT_PSEUDOCOLOR: | ||
222 | var->bits_per_pixel = 8; | ||
223 | var->red.offset = 0; var->red.length = 8; | ||
224 | var->green.offset = 0; var->green.length = 8; | ||
225 | var->blue.offset = 0; var->blue.length = 8; | ||
226 | var->transp.offset = 0; var->transp.length = 0; | ||
227 | break; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | /* | ||
232 | * fb framework has its limitation: | ||
233 | * 1. input color/output color is not seprated | ||
234 | * 2. fb_videomode not include output color | ||
235 | * so for fb usage, we keep a output format which is not changed | ||
236 | * then it's added for mmpmode | ||
237 | */ | ||
238 | static void fbmode_to_mmpmode(struct mmp_mode *mode, | ||
239 | struct fb_videomode *videomode, int output_fmt) | ||
240 | { | ||
241 | u64 div_result = 1000000000000ll; | ||
242 | mode->name = videomode->name; | ||
243 | mode->refresh = videomode->refresh; | ||
244 | mode->xres = videomode->xres; | ||
245 | mode->yres = videomode->yres; | ||
246 | |||
247 | do_div(div_result, videomode->pixclock); | ||
248 | mode->pixclock_freq = (u32)div_result; | ||
249 | |||
250 | mode->left_margin = videomode->left_margin; | ||
251 | mode->right_margin = videomode->right_margin; | ||
252 | mode->upper_margin = videomode->upper_margin; | ||
253 | mode->lower_margin = videomode->lower_margin; | ||
254 | mode->hsync_len = videomode->hsync_len; | ||
255 | mode->vsync_len = videomode->vsync_len; | ||
256 | mode->hsync_invert = !!(videomode->sync & FB_SYNC_HOR_HIGH_ACT); | ||
257 | mode->vsync_invert = !!(videomode->sync & FB_SYNC_VERT_HIGH_ACT); | ||
258 | /* no defined flag in fb, use vmode>>3*/ | ||
259 | mode->invert_pixclock = !!(videomode->vmode & 8); | ||
260 | mode->pix_fmt_out = output_fmt; | ||
261 | } | ||
262 | |||
263 | static void mmpmode_to_fbmode(struct fb_videomode *videomode, | ||
264 | struct mmp_mode *mode) | ||
265 | { | ||
266 | u64 div_result = 1000000000000ll; | ||
267 | |||
268 | videomode->name = mode->name; | ||
269 | videomode->refresh = mode->refresh; | ||
270 | videomode->xres = mode->xres; | ||
271 | videomode->yres = mode->yres; | ||
272 | |||
273 | do_div(div_result, mode->pixclock_freq); | ||
274 | videomode->pixclock = (u32)div_result; | ||
275 | |||
276 | videomode->left_margin = mode->left_margin; | ||
277 | videomode->right_margin = mode->right_margin; | ||
278 | videomode->upper_margin = mode->upper_margin; | ||
279 | videomode->lower_margin = mode->lower_margin; | ||
280 | videomode->hsync_len = mode->hsync_len; | ||
281 | videomode->vsync_len = mode->vsync_len; | ||
282 | videomode->sync = (mode->hsync_invert ? FB_SYNC_HOR_HIGH_ACT : 0) | ||
283 | | (mode->vsync_invert ? FB_SYNC_VERT_HIGH_ACT : 0); | ||
284 | videomode->vmode = mode->invert_pixclock ? 8 : 0; | ||
285 | } | ||
286 | |||
287 | static int mmpfb_check_var(struct fb_var_screeninfo *var, | ||
288 | struct fb_info *info) | ||
289 | { | ||
290 | struct mmpfb_info *fbi = info->par; | ||
291 | |||
292 | if (var->bits_per_pixel == 8) | ||
293 | return -EINVAL; | ||
294 | /* | ||
295 | * Basic geometry sanity checks. | ||
296 | */ | ||
297 | if (var->xoffset + var->xres > var->xres_virtual) | ||
298 | return -EINVAL; | ||
299 | if (var->yoffset + var->yres > var->yres_virtual) | ||
300 | return -EINVAL; | ||
301 | |||
302 | /* | ||
303 | * Check size of framebuffer. | ||
304 | */ | ||
305 | if (var->xres_virtual * var->yres_virtual * | ||
306 | (var->bits_per_pixel >> 3) > fbi->fb_size) | ||
307 | return -EINVAL; | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf) | ||
313 | { | ||
314 | return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset; | ||
315 | } | ||
316 | |||
317 | static u32 to_rgb(u16 red, u16 green, u16 blue) | ||
318 | { | ||
319 | red >>= 8; | ||
320 | green >>= 8; | ||
321 | blue >>= 8; | ||
322 | |||
323 | return (red << 16) | (green << 8) | blue; | ||
324 | } | ||
325 | |||
326 | static int mmpfb_setcolreg(unsigned int regno, unsigned int red, | ||
327 | unsigned int green, unsigned int blue, | ||
328 | unsigned int trans, struct fb_info *info) | ||
329 | { | ||
330 | struct mmpfb_info *fbi = info->par; | ||
331 | u32 val; | ||
332 | |||
333 | if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16) { | ||
334 | val = chan_to_field(red, &info->var.red); | ||
335 | val |= chan_to_field(green, &info->var.green); | ||
336 | val |= chan_to_field(blue , &info->var.blue); | ||
337 | fbi->pseudo_palette[regno] = val; | ||
338 | } | ||
339 | |||
340 | if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) { | ||
341 | val = to_rgb(red, green, blue); | ||
342 | /* TODO */ | ||
343 | } | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static int mmpfb_pan_display(struct fb_var_screeninfo *var, | ||
349 | struct fb_info *info) | ||
350 | { | ||
351 | struct mmpfb_info *fbi = info->par; | ||
352 | struct mmp_addr addr; | ||
353 | |||
354 | memset(&addr, 0, sizeof(addr)); | ||
355 | addr.phys[0] = (var->yoffset * var->xres_virtual + var->xoffset) | ||
356 | * var->bits_per_pixel / 8 + fbi->fb_start_dma; | ||
357 | mmp_overlay_set_addr(fbi->overlay, &addr); | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int var_update(struct fb_info *info) | ||
363 | { | ||
364 | struct mmpfb_info *fbi = info->par; | ||
365 | struct fb_var_screeninfo *var = &info->var; | ||
366 | struct fb_videomode *m; | ||
367 | int pix_fmt; | ||
368 | |||
369 | /* set pix_fmt */ | ||
370 | pix_fmt = var_to_pixfmt(var); | ||
371 | if (pix_fmt < 0) | ||
372 | return -EINVAL; | ||
373 | pixfmt_to_var(var, pix_fmt); | ||
374 | fbi->pix_fmt = pix_fmt; | ||
375 | |||
376 | /* set var according to best video mode*/ | ||
377 | m = (struct fb_videomode *)fb_match_mode(var, &info->modelist); | ||
378 | if (!m) { | ||
379 | dev_err(fbi->dev, "set par: no match mode, use best mode\n"); | ||
380 | m = (struct fb_videomode *)fb_find_best_mode(var, | ||
381 | &info->modelist); | ||
382 | fb_videomode_to_var(var, m); | ||
383 | } | ||
384 | memcpy(&fbi->mode, m, sizeof(struct fb_videomode)); | ||
385 | |||
386 | /* fix to 2* yres */ | ||
387 | var->yres_virtual = var->yres * 2; | ||
388 | info->fix.visual = (pix_fmt == PIXFMT_PSEUDOCOLOR) ? | ||
389 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | ||
390 | info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; | ||
391 | info->fix.ypanstep = var->yres; | ||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static int mmpfb_set_par(struct fb_info *info) | ||
396 | { | ||
397 | struct mmpfb_info *fbi = info->par; | ||
398 | struct fb_var_screeninfo *var = &info->var; | ||
399 | struct mmp_addr addr; | ||
400 | struct mmp_win win; | ||
401 | struct mmp_mode mode; | ||
402 | int ret; | ||
403 | |||
404 | ret = var_update(info); | ||
405 | if (ret != 0) | ||
406 | return ret; | ||
407 | |||
408 | /* set window/path according to new videomode */ | ||
409 | fbmode_to_mmpmode(&mode, &fbi->mode, fbi->output_fmt); | ||
410 | mmp_path_set_mode(fbi->path, &mode); | ||
411 | |||
412 | memset(&win, 0, sizeof(win)); | ||
413 | win.xsrc = win.xdst = fbi->mode.xres; | ||
414 | win.ysrc = win.ydst = fbi->mode.yres; | ||
415 | win.pix_fmt = fbi->pix_fmt; | ||
416 | mmp_overlay_set_win(fbi->overlay, &win); | ||
417 | |||
418 | /* set address always */ | ||
419 | memset(&addr, 0, sizeof(addr)); | ||
420 | addr.phys[0] = (var->yoffset * var->xres_virtual + var->xoffset) | ||
421 | * var->bits_per_pixel / 8 + fbi->fb_start_dma; | ||
422 | mmp_overlay_set_addr(fbi->overlay, &addr); | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static void mmpfb_power(struct mmpfb_info *fbi, int power) | ||
428 | { | ||
429 | struct mmp_addr addr; | ||
430 | struct mmp_win win; | ||
431 | struct fb_var_screeninfo *var = &fbi->fb_info->var; | ||
432 | |||
433 | /* for power on, always set address/window again */ | ||
434 | if (power) { | ||
435 | memset(&win, 0, sizeof(win)); | ||
436 | win.xsrc = win.xdst = fbi->mode.xres; | ||
437 | win.ysrc = win.ydst = fbi->mode.yres; | ||
438 | win.pix_fmt = fbi->pix_fmt; | ||
439 | mmp_overlay_set_win(fbi->overlay, &win); | ||
440 | |||
441 | /* set address always */ | ||
442 | memset(&addr, 0, sizeof(addr)); | ||
443 | addr.phys[0] = fbi->fb_start_dma + | ||
444 | (var->yoffset * var->xres_virtual + var->xoffset) | ||
445 | * var->bits_per_pixel / 8; | ||
446 | mmp_overlay_set_addr(fbi->overlay, &addr); | ||
447 | } | ||
448 | mmp_overlay_set_onoff(fbi->overlay, power); | ||
449 | } | ||
450 | |||
451 | static int mmpfb_blank(int blank, struct fb_info *info) | ||
452 | { | ||
453 | struct mmpfb_info *fbi = info->par; | ||
454 | |||
455 | mmpfb_power(fbi, (blank == FB_BLANK_UNBLANK)); | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static struct fb_ops mmpfb_ops = { | ||
461 | .owner = THIS_MODULE, | ||
462 | .fb_blank = mmpfb_blank, | ||
463 | .fb_check_var = mmpfb_check_var, | ||
464 | .fb_set_par = mmpfb_set_par, | ||
465 | .fb_setcolreg = mmpfb_setcolreg, | ||
466 | .fb_pan_display = mmpfb_pan_display, | ||
467 | .fb_fillrect = cfb_fillrect, | ||
468 | .fb_copyarea = cfb_copyarea, | ||
469 | .fb_imageblit = cfb_imageblit, | ||
470 | }; | ||
471 | |||
472 | static int modes_setup(struct mmpfb_info *fbi) | ||
473 | { | ||
474 | struct fb_videomode *videomodes; | ||
475 | struct mmp_mode *mmp_modes; | ||
476 | struct fb_info *info = fbi->fb_info; | ||
477 | int videomode_num, i; | ||
478 | |||
479 | /* get videomodes from path */ | ||
480 | videomode_num = mmp_path_get_modelist(fbi->path, &mmp_modes); | ||
481 | if (!videomode_num) { | ||
482 | dev_warn(fbi->dev, "can't get videomode num\n"); | ||
483 | return 0; | ||
484 | } | ||
485 | /* put videomode list to info structure */ | ||
486 | videomodes = kzalloc(sizeof(struct fb_videomode) * videomode_num, | ||
487 | GFP_KERNEL); | ||
488 | if (!videomodes) { | ||
489 | dev_err(fbi->dev, "can't malloc video modes\n"); | ||
490 | return -ENOMEM; | ||
491 | } | ||
492 | for (i = 0; i < videomode_num; i++) | ||
493 | mmpmode_to_fbmode(&videomodes[i], &mmp_modes[i]); | ||
494 | fb_videomode_to_modelist(videomodes, videomode_num, &info->modelist); | ||
495 | |||
496 | /* set videomode[0] as default mode */ | ||
497 | memcpy(&fbi->mode, &videomodes[0], sizeof(struct fb_videomode)); | ||
498 | fbi->output_fmt = mmp_modes[0].pix_fmt_out; | ||
499 | fb_videomode_to_var(&info->var, &fbi->mode); | ||
500 | mmp_path_set_mode(fbi->path, &mmp_modes[0]); | ||
501 | |||
502 | kfree(videomodes); | ||
503 | return videomode_num; | ||
504 | } | ||
505 | |||
506 | static int fb_info_setup(struct fb_info *info, | ||
507 | struct mmpfb_info *fbi) | ||
508 | { | ||
509 | int ret = 0; | ||
510 | /* Initialise static fb parameters.*/ | ||
511 | info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | | ||
512 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; | ||
513 | info->node = -1; | ||
514 | strcpy(info->fix.id, fbi->name); | ||
515 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
516 | info->fix.type_aux = 0; | ||
517 | info->fix.xpanstep = 0; | ||
518 | info->fix.ypanstep = info->var.yres; | ||
519 | info->fix.ywrapstep = 0; | ||
520 | info->fix.accel = FB_ACCEL_NONE; | ||
521 | info->fix.smem_start = fbi->fb_start_dma; | ||
522 | info->fix.smem_len = fbi->fb_size; | ||
523 | info->fix.visual = (fbi->pix_fmt == PIXFMT_PSEUDOCOLOR) ? | ||
524 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | ||
525 | info->fix.line_length = info->var.xres_virtual * | ||
526 | info->var.bits_per_pixel / 8; | ||
527 | info->fbops = &mmpfb_ops; | ||
528 | info->pseudo_palette = fbi->pseudo_palette; | ||
529 | info->screen_base = fbi->fb_start; | ||
530 | info->screen_size = fbi->fb_size; | ||
531 | |||
532 | /* For FB framework: Allocate color map and Register framebuffer*/ | ||
533 | if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) | ||
534 | ret = -ENOMEM; | ||
535 | |||
536 | return ret; | ||
537 | } | ||
538 | |||
539 | static void fb_info_clear(struct fb_info *info) | ||
540 | { | ||
541 | fb_dealloc_cmap(&info->cmap); | ||
542 | } | ||
543 | |||
544 | static int mmpfb_probe(struct platform_device *pdev) | ||
545 | { | ||
546 | struct mmp_buffer_driver_mach_info *mi; | ||
547 | struct fb_info *info = 0; | ||
548 | struct mmpfb_info *fbi = 0; | ||
549 | int ret, modes_num; | ||
550 | |||
551 | mi = pdev->dev.platform_data; | ||
552 | if (mi == NULL) { | ||
553 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
554 | return -EINVAL; | ||
555 | } | ||
556 | |||
557 | /* initialize fb */ | ||
558 | info = framebuffer_alloc(sizeof(struct mmpfb_info), &pdev->dev); | ||
559 | if (info == NULL) | ||
560 | return -ENOMEM; | ||
561 | fbi = info->par; | ||
562 | if (!fbi) { | ||
563 | ret = -EINVAL; | ||
564 | goto failed; | ||
565 | } | ||
566 | |||
567 | /* init fb */ | ||
568 | fbi->fb_info = info; | ||
569 | platform_set_drvdata(pdev, fbi); | ||
570 | fbi->dev = &pdev->dev; | ||
571 | fbi->name = mi->name; | ||
572 | fbi->pix_fmt = mi->default_pixfmt; | ||
573 | pixfmt_to_var(&info->var, fbi->pix_fmt); | ||
574 | mutex_init(&fbi->access_ok); | ||
575 | |||
576 | /* get display path by name */ | ||
577 | fbi->path = mmp_get_path(mi->path_name); | ||
578 | if (!fbi->path) { | ||
579 | dev_err(&pdev->dev, "can't get the path %s\n", mi->path_name); | ||
580 | ret = -EINVAL; | ||
581 | goto failed_destroy_mutex; | ||
582 | } | ||
583 | |||
584 | dev_info(fbi->dev, "path %s get\n", fbi->path->name); | ||
585 | |||
586 | /* get overlay */ | ||
587 | fbi->overlay = mmp_path_get_overlay(fbi->path, mi->overlay_id); | ||
588 | if (!fbi->overlay) { | ||
589 | ret = -EINVAL; | ||
590 | goto failed_destroy_mutex; | ||
591 | } | ||
592 | /* set fetch used */ | ||
593 | mmp_overlay_set_fetch(fbi->overlay, mi->dmafetch_id); | ||
594 | |||
595 | modes_num = modes_setup(fbi); | ||
596 | if (modes_num < 0) { | ||
597 | ret = modes_num; | ||
598 | goto failed_destroy_mutex; | ||
599 | } | ||
600 | |||
601 | /* | ||
602 | * if get modes success, means not hotplug panels, use caculated buffer | ||
603 | * or use default size | ||
604 | */ | ||
605 | if (modes_num > 0) { | ||
606 | /* fix to 2* yres */ | ||
607 | info->var.yres_virtual = info->var.yres * 2; | ||
608 | |||
609 | /* Allocate framebuffer memory: size = modes xy *4 */ | ||
610 | fbi->fb_size = info->var.xres_virtual * info->var.yres_virtual | ||
611 | * info->var.bits_per_pixel / 8; | ||
612 | } else { | ||
613 | fbi->fb_size = MMPFB_DEFAULT_SIZE; | ||
614 | } | ||
615 | |||
616 | fbi->fb_start = dma_alloc_coherent(&pdev->dev, PAGE_ALIGN(fbi->fb_size), | ||
617 | &fbi->fb_start_dma, GFP_KERNEL); | ||
618 | if (fbi->fb_start == NULL) { | ||
619 | dev_err(&pdev->dev, "can't alloc framebuffer\n"); | ||
620 | ret = -ENOMEM; | ||
621 | goto failed_destroy_mutex; | ||
622 | } | ||
623 | memset(fbi->fb_start, 0, fbi->fb_size); | ||
624 | dev_info(fbi->dev, "fb %dk allocated\n", fbi->fb_size/1024); | ||
625 | |||
626 | /* fb power on */ | ||
627 | if (modes_num > 0) | ||
628 | mmpfb_power(fbi, 1); | ||
629 | |||
630 | ret = fb_info_setup(info, fbi); | ||
631 | if (ret < 0) | ||
632 | goto failed_free_buff; | ||
633 | |||
634 | ret = register_framebuffer(info); | ||
635 | if (ret < 0) { | ||
636 | dev_err(&pdev->dev, "Failed to register fb: %d\n", ret); | ||
637 | ret = -ENXIO; | ||
638 | goto failed_clear_info; | ||
639 | } | ||
640 | |||
641 | dev_info(fbi->dev, "loaded to /dev/fb%d <%s>.\n", | ||
642 | info->node, info->fix.id); | ||
643 | |||
644 | #ifdef CONFIG_LOGO | ||
645 | if (fbi->fb_start) { | ||
646 | fb_prepare_logo(info, 0); | ||
647 | fb_show_logo(info, 0); | ||
648 | } | ||
649 | #endif | ||
650 | |||
651 | return 0; | ||
652 | |||
653 | failed_clear_info: | ||
654 | fb_info_clear(info); | ||
655 | failed_free_buff: | ||
656 | dma_free_coherent(&pdev->dev, PAGE_ALIGN(fbi->fb_size), fbi->fb_start, | ||
657 | fbi->fb_start_dma); | ||
658 | failed_destroy_mutex: | ||
659 | mutex_destroy(&fbi->access_ok); | ||
660 | failed: | ||
661 | dev_err(fbi->dev, "mmp-fb: frame buffer device init failed\n"); | ||
662 | platform_set_drvdata(pdev, NULL); | ||
663 | |||
664 | framebuffer_release(info); | ||
665 | |||
666 | return ret; | ||
667 | } | ||
668 | |||
669 | static struct platform_driver mmpfb_driver = { | ||
670 | .driver = { | ||
671 | .name = "mmp-fb", | ||
672 | .owner = THIS_MODULE, | ||
673 | }, | ||
674 | .probe = mmpfb_probe, | ||
675 | }; | ||
676 | |||
677 | static int mmpfb_init(void) | ||
678 | { | ||
679 | return platform_driver_register(&mmpfb_driver); | ||
680 | } | ||
681 | module_init(mmpfb_init); | ||
682 | |||
683 | MODULE_AUTHOR("Zhou Zhu <zhou.zhu@marvell.com>"); | ||
684 | MODULE_DESCRIPTION("Framebuffer driver for Marvell displays"); | ||
685 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/mmp/fb/mmpfb.h b/drivers/video/mmp/fb/mmpfb.h new file mode 100644 index 000000000000..88c23c10a9ec --- /dev/null +++ b/drivers/video/mmp/fb/mmpfb.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/mmp/fb/mmpfb.h | ||
3 | * Framebuffer driver for Marvell Display controller. | ||
4 | * | ||
5 | * Copyright (C) 2012 Marvell Technology Group Ltd. | ||
6 | * Authors: Zhou Zhu <zzhu3@marvell.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef _MMP_FB_H_ | ||
24 | #define _MMP_FB_H_ | ||
25 | |||
26 | #include <video/mmp_disp.h> | ||
27 | #include <linux/fb.h> | ||
28 | |||
29 | /* LCD controller private state. */ | ||
30 | struct mmpfb_info { | ||
31 | struct device *dev; | ||
32 | int id; | ||
33 | const char *name; | ||
34 | |||
35 | struct fb_info *fb_info; | ||
36 | /* basicaly videomode is for output */ | ||
37 | struct fb_videomode mode; | ||
38 | int pix_fmt; | ||
39 | |||
40 | void *fb_start; | ||
41 | int fb_size; | ||
42 | dma_addr_t fb_start_dma; | ||
43 | |||
44 | struct mmp_overlay *overlay; | ||
45 | struct mmp_path *path; | ||
46 | |||
47 | struct mutex access_ok; | ||
48 | |||
49 | unsigned int pseudo_palette[16]; | ||
50 | int output_fmt; | ||
51 | }; | ||
52 | |||
53 | #define MMPFB_DEFAULT_SIZE (PAGE_ALIGN(1920 * 1080 * 4 * 2)) | ||
54 | #endif /* _MMP_FB_H_ */ | ||
diff --git a/drivers/video/mmp/hw/Kconfig b/drivers/video/mmp/hw/Kconfig new file mode 100644 index 000000000000..02f109a20cd0 --- /dev/null +++ b/drivers/video/mmp/hw/Kconfig | |||
@@ -0,0 +1,20 @@ | |||
1 | if MMP_DISP | ||
2 | |||
3 | config MMP_DISP_CONTROLLER | ||
4 | bool "mmp display controller hw support" | ||
5 | depends on CPU_PXA910 || CPU_MMP2 || CPU_MMP3 || CPU_PXA988 | ||
6 | default n | ||
7 | help | ||
8 | Marvell MMP display hw controller support | ||
9 | this controller is used on Marvell PXA910, | ||
10 | MMP2, MMP3, PXA988 chips | ||
11 | |||
12 | config MMP_DISP_SPI | ||
13 | bool "mmp display controller spi port" | ||
14 | depends on MMP_DISP_CONTROLLER && SPI_MASTER | ||
15 | default y | ||
16 | help | ||
17 | Marvell MMP display hw controller spi port support | ||
18 | will register as a spi master for panel usage | ||
19 | |||
20 | endif | ||
diff --git a/drivers/video/mmp/hw/Makefile b/drivers/video/mmp/hw/Makefile new file mode 100644 index 000000000000..0000a714fedf --- /dev/null +++ b/drivers/video/mmp/hw/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | obj-$(CONFIG_MMP_DISP_CONTROLLER) += mmp_ctrl.o | ||
2 | obj-$(CONFIG_MMP_DISP_SPI) += mmp_spi.o | ||
diff --git a/drivers/video/mmp/hw/mmp_ctrl.c b/drivers/video/mmp/hw/mmp_ctrl.c new file mode 100644 index 000000000000..4bd31b2af398 --- /dev/null +++ b/drivers/video/mmp/hw/mmp_ctrl.c | |||
@@ -0,0 +1,591 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/mmp/hw/mmp_ctrl.c | ||
3 | * Marvell MMP series Display Controller support | ||
4 | * | ||
5 | * Copyright (C) 2012 Marvell Technology Group Ltd. | ||
6 | * Authors: Guoqing Li <ligq@marvell.com> | ||
7 | * Lisa Du <cldu@marvell.com> | ||
8 | * Zhou Zhu <zzhu3@marvell.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
18 | * more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along with | ||
21 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
22 | * | ||
23 | */ | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/string.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/dma-mapping.h> | ||
34 | #include <linux/clk.h> | ||
35 | #include <linux/err.h> | ||
36 | #include <linux/vmalloc.h> | ||
37 | #include <linux/uaccess.h> | ||
38 | #include <linux/kthread.h> | ||
39 | #include <linux/io.h> | ||
40 | |||
41 | #include "mmp_ctrl.h" | ||
42 | |||
43 | static irqreturn_t ctrl_handle_irq(int irq, void *dev_id) | ||
44 | { | ||
45 | struct mmphw_ctrl *ctrl = (struct mmphw_ctrl *)dev_id; | ||
46 | u32 isr, imask, tmp; | ||
47 | |||
48 | isr = readl_relaxed(ctrl->reg_base + SPU_IRQ_ISR); | ||
49 | imask = readl_relaxed(ctrl->reg_base + SPU_IRQ_ENA); | ||
50 | |||
51 | do { | ||
52 | /* clear clock only */ | ||
53 | tmp = readl_relaxed(ctrl->reg_base + SPU_IRQ_ISR); | ||
54 | if (tmp & isr) | ||
55 | writel_relaxed(~isr, ctrl->reg_base + SPU_IRQ_ISR); | ||
56 | } while ((isr = readl(ctrl->reg_base + SPU_IRQ_ISR)) & imask); | ||
57 | |||
58 | return IRQ_HANDLED; | ||
59 | } | ||
60 | |||
61 | static u32 fmt_to_reg(struct mmp_overlay *overlay, int pix_fmt) | ||
62 | { | ||
63 | u32 link_config = path_to_path_plat(overlay->path)->link_config; | ||
64 | u32 rbswap, uvswap = 0, yuvswap = 0, | ||
65 | csc_en = 0, val = 0, | ||
66 | vid = overlay_is_vid(overlay); | ||
67 | |||
68 | switch (pix_fmt) { | ||
69 | case PIXFMT_RGB565: | ||
70 | case PIXFMT_RGB1555: | ||
71 | case PIXFMT_RGB888PACK: | ||
72 | case PIXFMT_RGB888UNPACK: | ||
73 | case PIXFMT_RGBA888: | ||
74 | rbswap = !(link_config & 0x1); | ||
75 | break; | ||
76 | case PIXFMT_VYUY: | ||
77 | case PIXFMT_YVU422P: | ||
78 | case PIXFMT_YVU420P: | ||
79 | rbswap = link_config & 0x1; | ||
80 | uvswap = 1; | ||
81 | break; | ||
82 | case PIXFMT_YUYV: | ||
83 | rbswap = link_config & 0x1; | ||
84 | yuvswap = 1; | ||
85 | break; | ||
86 | default: | ||
87 | rbswap = link_config & 0x1; | ||
88 | break; | ||
89 | } | ||
90 | |||
91 | switch (pix_fmt) { | ||
92 | case PIXFMT_RGB565: | ||
93 | case PIXFMT_BGR565: | ||
94 | val = 0; | ||
95 | break; | ||
96 | case PIXFMT_RGB1555: | ||
97 | case PIXFMT_BGR1555: | ||
98 | val = 0x1; | ||
99 | break; | ||
100 | case PIXFMT_RGB888PACK: | ||
101 | case PIXFMT_BGR888PACK: | ||
102 | val = 0x2; | ||
103 | break; | ||
104 | case PIXFMT_RGB888UNPACK: | ||
105 | case PIXFMT_BGR888UNPACK: | ||
106 | val = 0x3; | ||
107 | break; | ||
108 | case PIXFMT_RGBA888: | ||
109 | case PIXFMT_BGRA888: | ||
110 | val = 0x4; | ||
111 | break; | ||
112 | case PIXFMT_UYVY: | ||
113 | case PIXFMT_VYUY: | ||
114 | case PIXFMT_YUYV: | ||
115 | val = 0x5; | ||
116 | csc_en = 1; | ||
117 | break; | ||
118 | case PIXFMT_YUV422P: | ||
119 | case PIXFMT_YVU422P: | ||
120 | val = 0x6; | ||
121 | csc_en = 1; | ||
122 | break; | ||
123 | case PIXFMT_YUV420P: | ||
124 | case PIXFMT_YVU420P: | ||
125 | val = 0x7; | ||
126 | csc_en = 1; | ||
127 | break; | ||
128 | default: | ||
129 | break; | ||
130 | } | ||
131 | |||
132 | return (dma_palette(0) | dma_fmt(vid, val) | | ||
133 | dma_swaprb(vid, rbswap) | dma_swapuv(vid, uvswap) | | ||
134 | dma_swapyuv(vid, yuvswap) | dma_csc(vid, csc_en)); | ||
135 | } | ||
136 | |||
137 | static void dmafetch_set_fmt(struct mmp_overlay *overlay) | ||
138 | { | ||
139 | u32 tmp; | ||
140 | struct mmp_path *path = overlay->path; | ||
141 | tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id)); | ||
142 | tmp &= ~dma_mask(overlay_is_vid(overlay)); | ||
143 | tmp |= fmt_to_reg(overlay, overlay->win.pix_fmt); | ||
144 | writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id)); | ||
145 | } | ||
146 | |||
147 | static void overlay_set_win(struct mmp_overlay *overlay, struct mmp_win *win) | ||
148 | { | ||
149 | struct lcd_regs *regs = path_regs(overlay->path); | ||
150 | u32 pitch; | ||
151 | |||
152 | /* assert win supported */ | ||
153 | memcpy(&overlay->win, win, sizeof(struct mmp_win)); | ||
154 | |||
155 | mutex_lock(&overlay->access_ok); | ||
156 | pitch = win->xsrc * pixfmt_to_stride(win->pix_fmt); | ||
157 | writel_relaxed(pitch, ®s->g_pitch); | ||
158 | writel_relaxed((win->ysrc << 16) | win->xsrc, ®s->g_size); | ||
159 | writel_relaxed((win->ydst << 16) | win->xdst, ®s->g_size_z); | ||
160 | writel_relaxed(0, ®s->g_start); | ||
161 | |||
162 | dmafetch_set_fmt(overlay); | ||
163 | mutex_unlock(&overlay->access_ok); | ||
164 | } | ||
165 | |||
166 | static void dmafetch_onoff(struct mmp_overlay *overlay, int on) | ||
167 | { | ||
168 | u32 mask = overlay_is_vid(overlay) ? CFG_GRA_ENA_MASK : | ||
169 | CFG_DMA_ENA_MASK; | ||
170 | u32 enable = overlay_is_vid(overlay) ? CFG_GRA_ENA(1) : CFG_DMA_ENA(1); | ||
171 | u32 tmp; | ||
172 | struct mmp_path *path = overlay->path; | ||
173 | |||
174 | mutex_lock(&overlay->access_ok); | ||
175 | tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id)); | ||
176 | tmp &= ~mask; | ||
177 | tmp |= (on ? enable : 0); | ||
178 | writel(tmp, ctrl_regs(path) + dma_ctrl(0, path->id)); | ||
179 | mutex_unlock(&overlay->access_ok); | ||
180 | } | ||
181 | |||
182 | static void path_enabledisable(struct mmp_path *path, int on) | ||
183 | { | ||
184 | u32 tmp; | ||
185 | mutex_lock(&path->access_ok); | ||
186 | tmp = readl_relaxed(ctrl_regs(path) + LCD_SCLK(path)); | ||
187 | if (on) | ||
188 | tmp &= ~SCLK_DISABLE; | ||
189 | else | ||
190 | tmp |= SCLK_DISABLE; | ||
191 | writel_relaxed(tmp, ctrl_regs(path) + LCD_SCLK(path)); | ||
192 | mutex_unlock(&path->access_ok); | ||
193 | } | ||
194 | |||
195 | static void path_onoff(struct mmp_path *path, int on) | ||
196 | { | ||
197 | if (path->status == on) { | ||
198 | dev_info(path->dev, "path %s is already %s\n", | ||
199 | path->name, stat_name(path->status)); | ||
200 | return; | ||
201 | } | ||
202 | |||
203 | if (on) { | ||
204 | path_enabledisable(path, 1); | ||
205 | |||
206 | if (path->panel && path->panel->set_onoff) | ||
207 | path->panel->set_onoff(path->panel, 1); | ||
208 | } else { | ||
209 | if (path->panel && path->panel->set_onoff) | ||
210 | path->panel->set_onoff(path->panel, 0); | ||
211 | |||
212 | path_enabledisable(path, 0); | ||
213 | } | ||
214 | path->status = on; | ||
215 | } | ||
216 | |||
217 | static void overlay_set_onoff(struct mmp_overlay *overlay, int on) | ||
218 | { | ||
219 | if (overlay->status == on) { | ||
220 | dev_info(overlay_to_ctrl(overlay)->dev, "overlay %s is already %s\n", | ||
221 | overlay->path->name, stat_name(overlay->status)); | ||
222 | return; | ||
223 | } | ||
224 | overlay->status = on; | ||
225 | dmafetch_onoff(overlay, on); | ||
226 | if (overlay->path->ops.check_status(overlay->path) | ||
227 | != overlay->path->status) | ||
228 | path_onoff(overlay->path, on); | ||
229 | } | ||
230 | |||
231 | static void overlay_set_fetch(struct mmp_overlay *overlay, int fetch_id) | ||
232 | { | ||
233 | overlay->dmafetch_id = fetch_id; | ||
234 | } | ||
235 | |||
236 | static int overlay_set_addr(struct mmp_overlay *overlay, struct mmp_addr *addr) | ||
237 | { | ||
238 | struct lcd_regs *regs = path_regs(overlay->path); | ||
239 | |||
240 | /* FIXME: assert addr supported */ | ||
241 | memcpy(&overlay->addr, addr, sizeof(struct mmp_win)); | ||
242 | writel(addr->phys[0], ®s->g_0); | ||
243 | |||
244 | return overlay->addr.phys[0]; | ||
245 | } | ||
246 | |||
247 | static void path_set_mode(struct mmp_path *path, struct mmp_mode *mode) | ||
248 | { | ||
249 | struct lcd_regs *regs = path_regs(path); | ||
250 | u32 total_x, total_y, vsync_ctrl, tmp, sclk_src, sclk_div, | ||
251 | link_config = path_to_path_plat(path)->link_config; | ||
252 | |||
253 | /* FIXME: assert videomode supported */ | ||
254 | memcpy(&path->mode, mode, sizeof(struct mmp_mode)); | ||
255 | |||
256 | mutex_lock(&path->access_ok); | ||
257 | |||
258 | /* polarity of timing signals */ | ||
259 | tmp = readl_relaxed(ctrl_regs(path) + intf_ctrl(path->id)) & 0x1; | ||
260 | tmp |= mode->vsync_invert ? 0 : 0x8; | ||
261 | tmp |= mode->hsync_invert ? 0 : 0x4; | ||
262 | tmp |= link_config & CFG_DUMBMODE_MASK; | ||
263 | tmp |= CFG_DUMB_ENA(1); | ||
264 | writel_relaxed(tmp, ctrl_regs(path) + intf_ctrl(path->id)); | ||
265 | |||
266 | writel_relaxed((mode->yres << 16) | mode->xres, ®s->screen_active); | ||
267 | writel_relaxed((mode->left_margin << 16) | mode->right_margin, | ||
268 | ®s->screen_h_porch); | ||
269 | writel_relaxed((mode->upper_margin << 16) | mode->lower_margin, | ||
270 | ®s->screen_v_porch); | ||
271 | total_x = mode->xres + mode->left_margin + mode->right_margin + | ||
272 | mode->hsync_len; | ||
273 | total_y = mode->yres + mode->upper_margin + mode->lower_margin + | ||
274 | mode->vsync_len; | ||
275 | writel_relaxed((total_y << 16) | total_x, ®s->screen_size); | ||
276 | |||
277 | /* vsync ctrl */ | ||
278 | if (path->output_type == PATH_OUT_DSI) | ||
279 | vsync_ctrl = 0x01330133; | ||
280 | else | ||
281 | vsync_ctrl = ((mode->xres + mode->right_margin) << 16) | ||
282 | | (mode->xres + mode->right_margin); | ||
283 | writel_relaxed(vsync_ctrl, ®s->vsync_ctrl); | ||
284 | |||
285 | /* set pixclock div */ | ||
286 | sclk_src = clk_get_rate(path_to_ctrl(path)->clk); | ||
287 | sclk_div = sclk_src / mode->pixclock_freq; | ||
288 | if (sclk_div * mode->pixclock_freq < sclk_src) | ||
289 | sclk_div++; | ||
290 | |||
291 | dev_info(path->dev, "%s sclk_src %d sclk_div 0x%x pclk %d\n", | ||
292 | __func__, sclk_src, sclk_div, mode->pixclock_freq); | ||
293 | |||
294 | tmp = readl_relaxed(ctrl_regs(path) + LCD_SCLK(path)); | ||
295 | tmp &= ~CLK_INT_DIV_MASK; | ||
296 | tmp |= sclk_div; | ||
297 | writel_relaxed(tmp, ctrl_regs(path) + LCD_SCLK(path)); | ||
298 | |||
299 | mutex_unlock(&path->access_ok); | ||
300 | } | ||
301 | |||
302 | static struct mmp_overlay_ops mmphw_overlay_ops = { | ||
303 | .set_fetch = overlay_set_fetch, | ||
304 | .set_onoff = overlay_set_onoff, | ||
305 | .set_win = overlay_set_win, | ||
306 | .set_addr = overlay_set_addr, | ||
307 | }; | ||
308 | |||
309 | static void ctrl_set_default(struct mmphw_ctrl *ctrl) | ||
310 | { | ||
311 | u32 tmp, irq_mask; | ||
312 | |||
313 | /* | ||
314 | * LCD Global control(LCD_TOP_CTRL) should be configed before | ||
315 | * any other LCD registers read/write, or there maybe issues. | ||
316 | */ | ||
317 | tmp = readl_relaxed(ctrl->reg_base + LCD_TOP_CTRL); | ||
318 | tmp |= 0xfff0; | ||
319 | writel_relaxed(tmp, ctrl->reg_base + LCD_TOP_CTRL); | ||
320 | |||
321 | |||
322 | /* disable all interrupts */ | ||
323 | irq_mask = path_imasks(0) | err_imask(0) | | ||
324 | path_imasks(1) | err_imask(1); | ||
325 | tmp = readl_relaxed(ctrl->reg_base + SPU_IRQ_ENA); | ||
326 | tmp &= ~irq_mask; | ||
327 | tmp |= irq_mask; | ||
328 | writel_relaxed(tmp, ctrl->reg_base + SPU_IRQ_ENA); | ||
329 | } | ||
330 | |||
331 | static void path_set_default(struct mmp_path *path) | ||
332 | { | ||
333 | struct lcd_regs *regs = path_regs(path); | ||
334 | u32 dma_ctrl1, mask, tmp, path_config; | ||
335 | |||
336 | path_config = path_to_path_plat(path)->path_config; | ||
337 | |||
338 | /* Configure IOPAD: should be parallel only */ | ||
339 | if (PATH_OUT_PARALLEL == path->output_type) { | ||
340 | mask = CFG_IOPADMODE_MASK | CFG_BURST_MASK | CFG_BOUNDARY_MASK; | ||
341 | tmp = readl_relaxed(ctrl_regs(path) + SPU_IOPAD_CONTROL); | ||
342 | tmp &= ~mask; | ||
343 | tmp |= path_config; | ||
344 | writel_relaxed(tmp, ctrl_regs(path) + SPU_IOPAD_CONTROL); | ||
345 | } | ||
346 | |||
347 | /* Select path clock source */ | ||
348 | tmp = readl_relaxed(ctrl_regs(path) + LCD_SCLK(path)); | ||
349 | tmp &= ~SCLK_SRC_SEL_MASK; | ||
350 | tmp |= path_config; | ||
351 | writel_relaxed(tmp, ctrl_regs(path) + LCD_SCLK(path)); | ||
352 | |||
353 | /* | ||
354 | * Configure default bits: vsync triggers DMA, | ||
355 | * power save enable, configure alpha registers to | ||
356 | * display 100% graphics, and set pixel command. | ||
357 | */ | ||
358 | dma_ctrl1 = 0x2032ff81; | ||
359 | |||
360 | dma_ctrl1 |= CFG_VSYNC_INV_MASK; | ||
361 | writel_relaxed(dma_ctrl1, ctrl_regs(path) + dma_ctrl(1, path->id)); | ||
362 | |||
363 | /* Configure default register values */ | ||
364 | writel_relaxed(0x00000000, ®s->blank_color); | ||
365 | writel_relaxed(0x00000000, ®s->g_1); | ||
366 | writel_relaxed(0x00000000, ®s->g_start); | ||
367 | |||
368 | /* | ||
369 | * 1.enable multiple burst request in DMA AXI | ||
370 | * bus arbiter for faster read if not tv path; | ||
371 | * 2.enable horizontal smooth filter; | ||
372 | */ | ||
373 | if (PATH_PN == path->id) { | ||
374 | mask = CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK | ||
375 | | CFG_ARBFAST_ENA(1); | ||
376 | tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id)); | ||
377 | tmp |= mask; | ||
378 | writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id)); | ||
379 | } else if (PATH_TV == path->id) { | ||
380 | mask = CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK | ||
381 | | CFG_ARBFAST_ENA(1); | ||
382 | tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id)); | ||
383 | tmp &= ~mask; | ||
384 | tmp |= CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK; | ||
385 | writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id)); | ||
386 | } | ||
387 | } | ||
388 | |||
389 | static int path_init(struct mmphw_path_plat *path_plat, | ||
390 | struct mmp_mach_path_config *config) | ||
391 | { | ||
392 | struct mmphw_ctrl *ctrl = path_plat->ctrl; | ||
393 | struct mmp_path_info *path_info; | ||
394 | struct mmp_path *path = NULL; | ||
395 | |||
396 | dev_info(ctrl->dev, "%s: %s\n", __func__, config->name); | ||
397 | |||
398 | /* init driver data */ | ||
399 | path_info = kzalloc(sizeof(struct mmp_path_info), GFP_KERNEL); | ||
400 | if (!path_info) { | ||
401 | dev_err(ctrl->dev, "%s: unable to alloc path_info for %s\n", | ||
402 | __func__, config->name); | ||
403 | return 0; | ||
404 | } | ||
405 | path_info->name = config->name; | ||
406 | path_info->id = path_plat->id; | ||
407 | path_info->dev = ctrl->dev; | ||
408 | path_info->overlay_num = config->overlay_num; | ||
409 | path_info->overlay_ops = &mmphw_overlay_ops; | ||
410 | path_info->set_mode = path_set_mode; | ||
411 | path_info->plat_data = path_plat; | ||
412 | |||
413 | /* create/register platform device */ | ||
414 | path = mmp_register_path(path_info); | ||
415 | if (!path) { | ||
416 | kfree(path_info); | ||
417 | return 0; | ||
418 | } | ||
419 | path_plat->path = path; | ||
420 | path_plat->path_config = config->path_config; | ||
421 | path_plat->link_config = config->link_config; | ||
422 | path_set_default(path); | ||
423 | |||
424 | kfree(path_info); | ||
425 | return 1; | ||
426 | } | ||
427 | |||
428 | static void path_deinit(struct mmphw_path_plat *path_plat) | ||
429 | { | ||
430 | if (!path_plat) | ||
431 | return; | ||
432 | |||
433 | if (path_plat->path) | ||
434 | mmp_unregister_path(path_plat->path); | ||
435 | } | ||
436 | |||
437 | static int mmphw_probe(struct platform_device *pdev) | ||
438 | { | ||
439 | struct mmp_mach_plat_info *mi; | ||
440 | struct resource *res; | ||
441 | int ret, i, size, irq; | ||
442 | struct mmphw_path_plat *path_plat; | ||
443 | struct mmphw_ctrl *ctrl = NULL; | ||
444 | |||
445 | /* get resources from platform data */ | ||
446 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
447 | if (res == NULL) { | ||
448 | dev_err(&pdev->dev, "%s: no IO memory defined\n", __func__); | ||
449 | ret = -ENOENT; | ||
450 | goto failed; | ||
451 | } | ||
452 | |||
453 | irq = platform_get_irq(pdev, 0); | ||
454 | if (irq < 0) { | ||
455 | dev_err(&pdev->dev, "%s: no IRQ defined\n", __func__); | ||
456 | ret = -ENOENT; | ||
457 | goto failed; | ||
458 | } | ||
459 | |||
460 | /* get configs from platform data */ | ||
461 | mi = pdev->dev.platform_data; | ||
462 | if (mi == NULL || !mi->path_num || !mi->paths) { | ||
463 | dev_err(&pdev->dev, "%s: no platform data defined\n", __func__); | ||
464 | ret = -EINVAL; | ||
465 | goto failed; | ||
466 | } | ||
467 | |||
468 | /* allocate */ | ||
469 | size = sizeof(struct mmphw_ctrl) + sizeof(struct mmphw_path_plat) * | ||
470 | mi->path_num; | ||
471 | ctrl = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); | ||
472 | if (!ctrl) { | ||
473 | ret = -ENOMEM; | ||
474 | goto failed; | ||
475 | } | ||
476 | |||
477 | ctrl->name = mi->name; | ||
478 | ctrl->path_num = mi->path_num; | ||
479 | ctrl->dev = &pdev->dev; | ||
480 | ctrl->irq = irq; | ||
481 | platform_set_drvdata(pdev, ctrl); | ||
482 | mutex_init(&ctrl->access_ok); | ||
483 | |||
484 | /* map registers.*/ | ||
485 | if (!devm_request_mem_region(ctrl->dev, res->start, | ||
486 | resource_size(res), ctrl->name)) { | ||
487 | dev_err(ctrl->dev, | ||
488 | "can't request region for resource %pR\n", res); | ||
489 | ret = -EINVAL; | ||
490 | goto failed; | ||
491 | } | ||
492 | |||
493 | ctrl->reg_base = devm_ioremap_nocache(ctrl->dev, | ||
494 | res->start, resource_size(res)); | ||
495 | if (ctrl->reg_base == NULL) { | ||
496 | dev_err(ctrl->dev, "%s: res %x - %x map failed\n", __func__, | ||
497 | res->start, res->end); | ||
498 | ret = -ENOMEM; | ||
499 | goto failed; | ||
500 | } | ||
501 | |||
502 | /* request irq */ | ||
503 | ret = devm_request_irq(ctrl->dev, ctrl->irq, ctrl_handle_irq, | ||
504 | IRQF_SHARED, "lcd_controller", ctrl); | ||
505 | if (ret < 0) { | ||
506 | dev_err(ctrl->dev, "%s unable to request IRQ %d\n", | ||
507 | __func__, ctrl->irq); | ||
508 | ret = -ENXIO; | ||
509 | goto failed; | ||
510 | } | ||
511 | |||
512 | /* get clock */ | ||
513 | ctrl->clk = devm_clk_get(ctrl->dev, mi->clk_name); | ||
514 | if (IS_ERR(ctrl->clk)) { | ||
515 | dev_err(ctrl->dev, "unable to get clk %s\n", mi->clk_name); | ||
516 | ret = -ENOENT; | ||
517 | goto failed_get_clk; | ||
518 | } | ||
519 | clk_prepare_enable(ctrl->clk); | ||
520 | |||
521 | /* init global regs */ | ||
522 | ctrl_set_default(ctrl); | ||
523 | |||
524 | /* init pathes from machine info and register them */ | ||
525 | for (i = 0; i < ctrl->path_num; i++) { | ||
526 | /* get from config and machine info */ | ||
527 | path_plat = &ctrl->path_plats[i]; | ||
528 | path_plat->id = i; | ||
529 | path_plat->ctrl = ctrl; | ||
530 | |||
531 | /* path init */ | ||
532 | if (!path_init(path_plat, &mi->paths[i])) { | ||
533 | ret = -EINVAL; | ||
534 | goto failed_path_init; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | #ifdef CONFIG_MMP_DISP_SPI | ||
539 | ret = lcd_spi_register(ctrl); | ||
540 | if (ret < 0) | ||
541 | goto failed_path_init; | ||
542 | #endif | ||
543 | |||
544 | dev_info(ctrl->dev, "device init done\n"); | ||
545 | |||
546 | return 0; | ||
547 | |||
548 | failed_path_init: | ||
549 | for (i = 0; i < ctrl->path_num; i++) { | ||
550 | path_plat = &ctrl->path_plats[i]; | ||
551 | path_deinit(path_plat); | ||
552 | } | ||
553 | |||
554 | if (ctrl->clk) { | ||
555 | devm_clk_put(ctrl->dev, ctrl->clk); | ||
556 | clk_disable_unprepare(ctrl->clk); | ||
557 | } | ||
558 | failed_get_clk: | ||
559 | devm_free_irq(ctrl->dev, ctrl->irq, ctrl); | ||
560 | failed: | ||
561 | if (ctrl) { | ||
562 | if (ctrl->reg_base) | ||
563 | devm_iounmap(ctrl->dev, ctrl->reg_base); | ||
564 | devm_release_mem_region(ctrl->dev, res->start, | ||
565 | resource_size(res)); | ||
566 | devm_kfree(ctrl->dev, ctrl); | ||
567 | } | ||
568 | |||
569 | platform_set_drvdata(pdev, NULL); | ||
570 | dev_err(&pdev->dev, "device init failed\n"); | ||
571 | |||
572 | return ret; | ||
573 | } | ||
574 | |||
575 | static struct platform_driver mmphw_driver = { | ||
576 | .driver = { | ||
577 | .name = "mmp-disp", | ||
578 | .owner = THIS_MODULE, | ||
579 | }, | ||
580 | .probe = mmphw_probe, | ||
581 | }; | ||
582 | |||
583 | static int mmphw_init(void) | ||
584 | { | ||
585 | return platform_driver_register(&mmphw_driver); | ||
586 | } | ||
587 | module_init(mmphw_init); | ||
588 | |||
589 | MODULE_AUTHOR("Li Guoqing<ligq@marvell.com>"); | ||
590 | MODULE_DESCRIPTION("Framebuffer driver for mmp"); | ||
591 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/mmp/hw/mmp_ctrl.h b/drivers/video/mmp/hw/mmp_ctrl.h new file mode 100644 index 000000000000..6408d8ef3abb --- /dev/null +++ b/drivers/video/mmp/hw/mmp_ctrl.h | |||
@@ -0,0 +1,1974 @@ | |||
1 | /* | ||
2 | * drivers/video/mmp/hw/mmp_ctrl.h | ||
3 | * | ||
4 | * | ||
5 | * Copyright (C) 2012 Marvell Technology Group Ltd. | ||
6 | * Authors: Guoqing Li <ligq@marvell.com> | ||
7 | * Lisa Du <cldu@marvell.com> | ||
8 | * Zhou Zhu <zzhu3@marvell.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
18 | * more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along with | ||
21 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef _MMP_CTRL_H_ | ||
26 | #define _MMP_CTRL_H_ | ||
27 | |||
28 | #include <video/mmp_disp.h> | ||
29 | |||
30 | /* ------------< LCD register >------------ */ | ||
31 | struct lcd_regs { | ||
32 | /* TV patch register for MMP2 */ | ||
33 | /* 32 bit TV Video Frame0 Y Starting Address */ | ||
34 | #define LCD_TVD_START_ADDR_Y0 (0x0000) | ||
35 | /* 32 bit TV Video Frame0 U Starting Address */ | ||
36 | #define LCD_TVD_START_ADDR_U0 (0x0004) | ||
37 | /* 32 bit TV Video Frame0 V Starting Address */ | ||
38 | #define LCD_TVD_START_ADDR_V0 (0x0008) | ||
39 | /* 32 bit TV Video Frame0 Command Starting Address */ | ||
40 | #define LCD_TVD_START_ADDR_C0 (0x000C) | ||
41 | /* 32 bit TV Video Frame1 Y Starting Address Register*/ | ||
42 | #define LCD_TVD_START_ADDR_Y1 (0x0010) | ||
43 | /* 32 bit TV Video Frame1 U Starting Address Register*/ | ||
44 | #define LCD_TVD_START_ADDR_U1 (0x0014) | ||
45 | /* 32 bit TV Video Frame1 V Starting Address Register*/ | ||
46 | #define LCD_TVD_START_ADDR_V1 (0x0018) | ||
47 | /* 32 bit TV Video Frame1 Command Starting Address Register*/ | ||
48 | #define LCD_TVD_START_ADDR_C1 (0x001C) | ||
49 | /* 32 bit TV Video Y andC Line Length(Pitch)Register*/ | ||
50 | #define LCD_TVD_PITCH_YC (0x0020) | ||
51 | /* 32 bit TV Video U andV Line Length(Pitch)Register*/ | ||
52 | #define LCD_TVD_PITCH_UV (0x0024) | ||
53 | /* 32 bit TV Video Starting Point on Screen Register*/ | ||
54 | #define LCD_TVD_OVSA_HPXL_VLN (0x0028) | ||
55 | /* 32 bit TV Video Source Size Register*/ | ||
56 | #define LCD_TVD_HPXL_VLN (0x002C) | ||
57 | /* 32 bit TV Video Destination Size (After Zooming)Register*/ | ||
58 | #define LCD_TVDZM_HPXL_VLN (0x0030) | ||
59 | u32 v_y0; | ||
60 | u32 v_u0; | ||
61 | u32 v_v0; | ||
62 | u32 v_c0; | ||
63 | u32 v_y1; | ||
64 | u32 v_u1; | ||
65 | u32 v_v1; | ||
66 | u32 v_c1; | ||
67 | u32 v_pitch_yc; /* Video Y and C Line Length (Pitch) */ | ||
68 | u32 v_pitch_uv; /* Video U and V Line Length (Pitch) */ | ||
69 | u32 v_start; /* Video Starting Point on Screen */ | ||
70 | u32 v_size; /* Video Source Size */ | ||
71 | u32 v_size_z; /* Video Destination Size (After Zooming) */ | ||
72 | |||
73 | /* 32 bit TV Graphic Frame 0 Starting Address Register*/ | ||
74 | #define LCD_TVG_START_ADDR0 (0x0034) | ||
75 | /* 32 bit TV Graphic Frame 1 Starting Address Register*/ | ||
76 | #define LCD_TVG_START_ADDR1 (0x0038) | ||
77 | /* 32 bit TV Graphic Line Length(Pitch)Register*/ | ||
78 | #define LCD_TVG_PITCH (0x003C) | ||
79 | /* 32 bit TV Graphic Starting Point on Screen Register*/ | ||
80 | #define LCD_TVG_OVSA_HPXL_VLN (0x0040) | ||
81 | /* 32 bit TV Graphic Source Size Register*/ | ||
82 | #define LCD_TVG_HPXL_VLN (0x0044) | ||
83 | /* 32 bit TV Graphic Destination size (after Zooming)Register*/ | ||
84 | #define LCD_TVGZM_HPXL_VLN (0x0048) | ||
85 | u32 g_0; /* Graphic Frame 0/1 Starting Address */ | ||
86 | u32 g_1; | ||
87 | u32 g_pitch; /* Graphic Line Length (Pitch) */ | ||
88 | u32 g_start; /* Graphic Starting Point on Screen */ | ||
89 | u32 g_size; /* Graphic Source Size */ | ||
90 | u32 g_size_z; /* Graphic Destination Size (After Zooming) */ | ||
91 | |||
92 | /* 32 bit TV Hardware Cursor Starting Point on screen Register*/ | ||
93 | #define LCD_TVC_OVSA_HPXL_VLN (0x004C) | ||
94 | /* 32 bit TV Hardware Cursor Size Register */ | ||
95 | #define LCD_TVC_HPXL_VLN (0x0050) | ||
96 | u32 hc_start; /* Hardware Cursor */ | ||
97 | u32 hc_size; /* Hardware Cursor */ | ||
98 | |||
99 | /* 32 bit TV Total Screen Size Register*/ | ||
100 | #define LCD_TV_V_H_TOTAL (0x0054) | ||
101 | /* 32 bit TV Screen Active Size Register*/ | ||
102 | #define LCD_TV_V_H_ACTIVE (0x0058) | ||
103 | /* 32 bit TV Screen Horizontal Porch Register*/ | ||
104 | #define LCD_TV_H_PORCH (0x005C) | ||
105 | /* 32 bit TV Screen Vertical Porch Register*/ | ||
106 | #define LCD_TV_V_PORCH (0x0060) | ||
107 | u32 screen_size; /* Screen Total Size */ | ||
108 | u32 screen_active; /* Screen Active Size */ | ||
109 | u32 screen_h_porch; /* Screen Horizontal Porch */ | ||
110 | u32 screen_v_porch; /* Screen Vertical Porch */ | ||
111 | |||
112 | /* 32 bit TV Screen Blank Color Register*/ | ||
113 | #define LCD_TV_BLANKCOLOR (0x0064) | ||
114 | /* 32 bit TV Hardware Cursor Color1 Register*/ | ||
115 | #define LCD_TV_ALPHA_COLOR1 (0x0068) | ||
116 | /* 32 bit TV Hardware Cursor Color2 Register*/ | ||
117 | #define LCD_TV_ALPHA_COLOR2 (0x006C) | ||
118 | u32 blank_color; /* Screen Blank Color */ | ||
119 | u32 hc_Alpha_color1; /* Hardware Cursor Color1 */ | ||
120 | u32 hc_Alpha_color2; /* Hardware Cursor Color2 */ | ||
121 | |||
122 | /* 32 bit TV Video Y Color Key Control*/ | ||
123 | #define LCD_TV_COLORKEY_Y (0x0070) | ||
124 | /* 32 bit TV Video U Color Key Control*/ | ||
125 | #define LCD_TV_COLORKEY_U (0x0074) | ||
126 | /* 32 bit TV Video V Color Key Control*/ | ||
127 | #define LCD_TV_COLORKEY_V (0x0078) | ||
128 | u32 v_colorkey_y; /* Video Y Color Key Control */ | ||
129 | u32 v_colorkey_u; /* Video U Color Key Control */ | ||
130 | u32 v_colorkey_v; /* Video V Color Key Control */ | ||
131 | |||
132 | /* 32 bit TV VSYNC PulsePixel Edge Control Register*/ | ||
133 | #define LCD_TV_SEPXLCNT (0x007C) | ||
134 | u32 vsync_ctrl; /* VSYNC PulsePixel Edge Control */ | ||
135 | }; | ||
136 | |||
137 | #define intf_ctrl(id) ((id) ? (((id) & 1) ? LCD_TVIF_CTRL : \ | ||
138 | LCD_DUMB2_CTRL) : LCD_SPU_DUMB_CTRL) | ||
139 | #define dma_ctrl0(id) ((id) ? (((id) & 1) ? LCD_TV_CTRL0 : \ | ||
140 | LCD_PN2_CTRL0) : LCD_SPU_DMA_CTRL0) | ||
141 | #define dma_ctrl1(id) ((id) ? (((id) & 1) ? LCD_TV_CTRL1 : \ | ||
142 | LCD_PN2_CTRL1) : LCD_SPU_DMA_CTRL1) | ||
143 | #define dma_ctrl(ctrl1, id) (ctrl1 ? dma_ctrl1(id) : dma_ctrl0(id)) | ||
144 | |||
145 | /* 32 bit TV Path DMA Control 0*/ | ||
146 | #define LCD_TV_CTRL0 (0x0080) | ||
147 | /* 32 bit TV Path DMA Control 1*/ | ||
148 | #define LCD_TV_CTRL1 (0x0084) | ||
149 | /* 32 bit TV Path Video Contrast*/ | ||
150 | #define LCD_TV_CONTRAST (0x0088) | ||
151 | /* 32 bit TV Path Video Saturation*/ | ||
152 | #define LCD_TV_SATURATION (0x008C) | ||
153 | /* 32 bit TV Path Video Hue Adjust*/ | ||
154 | #define LCD_TV_CBSH_HUE (0x0090) | ||
155 | /* 32 bit TV Path TVIF Control Register */ | ||
156 | #define LCD_TVIF_CTRL (0x0094) | ||
157 | #define TV_VBLNK_VALID_EN (1 << 12) | ||
158 | |||
159 | /* 32 bit TV Path I/O Pad Control*/ | ||
160 | #define LCD_TVIOPAD_CTRL (0x0098) | ||
161 | /* 32 bit TV Path Cloc Divider */ | ||
162 | #define LCD_TCLK_DIV (0x009C) | ||
163 | |||
164 | #define LCD_SCLK(path) ((PATH_PN == path->id) ? LCD_CFG_SCLK_DIV :\ | ||
165 | ((PATH_TV == path->id) ? LCD_TCLK_DIV : LCD_PN2_SCLK_DIV)) | ||
166 | |||
167 | /* dither configure */ | ||
168 | #ifdef CONFIG_CPU_PXA988 | ||
169 | #define LCD_DITHER_CTRL (0x01EC) | ||
170 | #else | ||
171 | #define LCD_DITHER_CTRL (0x00A0) | ||
172 | #endif | ||
173 | |||
174 | #define DITHER_TBL_INDEX_SEL(s) ((s) << 16) | ||
175 | #define DITHER_MODE2(m) ((m) << 12) | ||
176 | #define DITHER_MODE2_SHIFT (12) | ||
177 | #define DITHER_4X8_EN2 (1 << 9) | ||
178 | #define DITHER_4X8_EN2_SHIFT (9) | ||
179 | #define DITHER_EN2 (1 << 8) | ||
180 | #define DITHER_MODE1(m) ((m) << 4) | ||
181 | #define DITHER_MODE1_SHIFT (4) | ||
182 | #define DITHER_4X8_EN1 (1 << 1) | ||
183 | #define DITHER_4X8_EN1_SHIFT (1) | ||
184 | #define DITHER_EN1 (1) | ||
185 | |||
186 | /* dither table data was fixed by video bpp of input and output*/ | ||
187 | #ifdef CONFIG_CPU_PXA988 | ||
188 | #define DITHER_TB_4X4_INDEX0 (0x6e4ca280) | ||
189 | #define DITHER_TB_4X4_INDEX1 (0x5d7f91b3) | ||
190 | #define DITHER_TB_4X8_INDEX0 (0xb391a280) | ||
191 | #define DITHER_TB_4X8_INDEX1 (0x7f5d6e4c) | ||
192 | #define DITHER_TB_4X8_INDEX2 (0x80a291b3) | ||
193 | #define DITHER_TB_4X8_INDEX3 (0x4c6e5d7f) | ||
194 | #define LCD_DITHER_TBL_DATA (0x01F0) | ||
195 | #else | ||
196 | #define DITHER_TB_4X4_INDEX0 (0x3b19f7d5) | ||
197 | #define DITHER_TB_4X4_INDEX1 (0x082ac4e6) | ||
198 | #define DITHER_TB_4X8_INDEX0 (0xf7d508e6) | ||
199 | #define DITHER_TB_4X8_INDEX1 (0x3b194c2a) | ||
200 | #define DITHER_TB_4X8_INDEX2 (0xc4e6d5f7) | ||
201 | #define DITHER_TB_4X8_INDEX3 (0x082a193b) | ||
202 | #define LCD_DITHER_TBL_DATA (0x00A4) | ||
203 | #endif | ||
204 | |||
205 | /* Video Frame 0&1 start address registers */ | ||
206 | #define LCD_SPU_DMA_START_ADDR_Y0 0x00C0 | ||
207 | #define LCD_SPU_DMA_START_ADDR_U0 0x00C4 | ||
208 | #define LCD_SPU_DMA_START_ADDR_V0 0x00C8 | ||
209 | #define LCD_CFG_DMA_START_ADDR_0 0x00CC /* Cmd address */ | ||
210 | #define LCD_SPU_DMA_START_ADDR_Y1 0x00D0 | ||
211 | #define LCD_SPU_DMA_START_ADDR_U1 0x00D4 | ||
212 | #define LCD_SPU_DMA_START_ADDR_V1 0x00D8 | ||
213 | #define LCD_CFG_DMA_START_ADDR_1 0x00DC /* Cmd address */ | ||
214 | |||
215 | /* YC & UV Pitch */ | ||
216 | #define LCD_SPU_DMA_PITCH_YC 0x00E0 | ||
217 | #define SPU_DMA_PITCH_C(c) ((c)<<16) | ||
218 | #define SPU_DMA_PITCH_Y(y) (y) | ||
219 | #define LCD_SPU_DMA_PITCH_UV 0x00E4 | ||
220 | #define SPU_DMA_PITCH_V(v) ((v)<<16) | ||
221 | #define SPU_DMA_PITCH_U(u) (u) | ||
222 | |||
223 | /* Video Starting Point on Screen Register */ | ||
224 | #define LCD_SPUT_DMA_OVSA_HPXL_VLN 0x00E8 | ||
225 | #define CFG_DMA_OVSA_VLN(y) ((y)<<16) /* 0~0xfff */ | ||
226 | #define CFG_DMA_OVSA_HPXL(x) (x) /* 0~0xfff */ | ||
227 | |||
228 | /* Video Size Register */ | ||
229 | #define LCD_SPU_DMA_HPXL_VLN 0x00EC | ||
230 | #define CFG_DMA_VLN(y) ((y)<<16) | ||
231 | #define CFG_DMA_HPXL(x) (x) | ||
232 | |||
233 | /* Video Size After zooming Register */ | ||
234 | #define LCD_SPU_DZM_HPXL_VLN 0x00F0 | ||
235 | #define CFG_DZM_VLN(y) ((y)<<16) | ||
236 | #define CFG_DZM_HPXL(x) (x) | ||
237 | |||
238 | /* Graphic Frame 0&1 Starting Address Register */ | ||
239 | #define LCD_CFG_GRA_START_ADDR0 0x00F4 | ||
240 | #define LCD_CFG_GRA_START_ADDR1 0x00F8 | ||
241 | |||
242 | /* Graphic Frame Pitch */ | ||
243 | #define LCD_CFG_GRA_PITCH 0x00FC | ||
244 | |||
245 | /* Graphic Starting Point on Screen Register */ | ||
246 | #define LCD_SPU_GRA_OVSA_HPXL_VLN 0x0100 | ||
247 | #define CFG_GRA_OVSA_VLN(y) ((y)<<16) | ||
248 | #define CFG_GRA_OVSA_HPXL(x) (x) | ||
249 | |||
250 | /* Graphic Size Register */ | ||
251 | #define LCD_SPU_GRA_HPXL_VLN 0x0104 | ||
252 | #define CFG_GRA_VLN(y) ((y)<<16) | ||
253 | #define CFG_GRA_HPXL(x) (x) | ||
254 | |||
255 | /* Graphic Size after Zooming Register */ | ||
256 | #define LCD_SPU_GZM_HPXL_VLN 0x0108 | ||
257 | #define CFG_GZM_VLN(y) ((y)<<16) | ||
258 | #define CFG_GZM_HPXL(x) (x) | ||
259 | |||
260 | /* HW Cursor Starting Point on Screen Register */ | ||
261 | #define LCD_SPU_HWC_OVSA_HPXL_VLN 0x010C | ||
262 | #define CFG_HWC_OVSA_VLN(y) ((y)<<16) | ||
263 | #define CFG_HWC_OVSA_HPXL(x) (x) | ||
264 | |||
265 | /* HW Cursor Size */ | ||
266 | #define LCD_SPU_HWC_HPXL_VLN 0x0110 | ||
267 | #define CFG_HWC_VLN(y) ((y)<<16) | ||
268 | #define CFG_HWC_HPXL(x) (x) | ||
269 | |||
270 | /* Total Screen Size Register */ | ||
271 | #define LCD_SPUT_V_H_TOTAL 0x0114 | ||
272 | #define CFG_V_TOTAL(y) ((y)<<16) | ||
273 | #define CFG_H_TOTAL(x) (x) | ||
274 | |||
275 | /* Total Screen Active Size Register */ | ||
276 | #define LCD_SPU_V_H_ACTIVE 0x0118 | ||
277 | #define CFG_V_ACTIVE(y) ((y)<<16) | ||
278 | #define CFG_H_ACTIVE(x) (x) | ||
279 | |||
280 | /* Screen H&V Porch Register */ | ||
281 | #define LCD_SPU_H_PORCH 0x011C | ||
282 | #define CFG_H_BACK_PORCH(b) ((b)<<16) | ||
283 | #define CFG_H_FRONT_PORCH(f) (f) | ||
284 | #define LCD_SPU_V_PORCH 0x0120 | ||
285 | #define CFG_V_BACK_PORCH(b) ((b)<<16) | ||
286 | #define CFG_V_FRONT_PORCH(f) (f) | ||
287 | |||
288 | /* Screen Blank Color Register */ | ||
289 | #define LCD_SPU_BLANKCOLOR 0x0124 | ||
290 | #define CFG_BLANKCOLOR_MASK 0x00FFFFFF | ||
291 | #define CFG_BLANKCOLOR_R_MASK 0x000000FF | ||
292 | #define CFG_BLANKCOLOR_G_MASK 0x0000FF00 | ||
293 | #define CFG_BLANKCOLOR_B_MASK 0x00FF0000 | ||
294 | |||
295 | /* HW Cursor Color 1&2 Register */ | ||
296 | #define LCD_SPU_ALPHA_COLOR1 0x0128 | ||
297 | #define CFG_HWC_COLOR1 0x00FFFFFF | ||
298 | #define CFG_HWC_COLOR1_R(red) ((red)<<16) | ||
299 | #define CFG_HWC_COLOR1_G(green) ((green)<<8) | ||
300 | #define CFG_HWC_COLOR1_B(blue) (blue) | ||
301 | #define CFG_HWC_COLOR1_R_MASK 0x000000FF | ||
302 | #define CFG_HWC_COLOR1_G_MASK 0x0000FF00 | ||
303 | #define CFG_HWC_COLOR1_B_MASK 0x00FF0000 | ||
304 | #define LCD_SPU_ALPHA_COLOR2 0x012C | ||
305 | #define CFG_HWC_COLOR2 0x00FFFFFF | ||
306 | #define CFG_HWC_COLOR2_R_MASK 0x000000FF | ||
307 | #define CFG_HWC_COLOR2_G_MASK 0x0000FF00 | ||
308 | #define CFG_HWC_COLOR2_B_MASK 0x00FF0000 | ||
309 | |||
310 | /* Video YUV Color Key Control */ | ||
311 | #define LCD_SPU_COLORKEY_Y 0x0130 | ||
312 | #define CFG_CKEY_Y2(y2) ((y2)<<24) | ||
313 | #define CFG_CKEY_Y2_MASK 0xFF000000 | ||
314 | #define CFG_CKEY_Y1(y1) ((y1)<<16) | ||
315 | #define CFG_CKEY_Y1_MASK 0x00FF0000 | ||
316 | #define CFG_CKEY_Y(y) ((y)<<8) | ||
317 | #define CFG_CKEY_Y_MASK 0x0000FF00 | ||
318 | #define CFG_ALPHA_Y(y) (y) | ||
319 | #define CFG_ALPHA_Y_MASK 0x000000FF | ||
320 | #define LCD_SPU_COLORKEY_U 0x0134 | ||
321 | #define CFG_CKEY_U2(u2) ((u2)<<24) | ||
322 | #define CFG_CKEY_U2_MASK 0xFF000000 | ||
323 | #define CFG_CKEY_U1(u1) ((u1)<<16) | ||
324 | #define CFG_CKEY_U1_MASK 0x00FF0000 | ||
325 | #define CFG_CKEY_U(u) ((u)<<8) | ||
326 | #define CFG_CKEY_U_MASK 0x0000FF00 | ||
327 | #define CFG_ALPHA_U(u) (u) | ||
328 | #define CFG_ALPHA_U_MASK 0x000000FF | ||
329 | #define LCD_SPU_COLORKEY_V 0x0138 | ||
330 | #define CFG_CKEY_V2(v2) ((v2)<<24) | ||
331 | #define CFG_CKEY_V2_MASK 0xFF000000 | ||
332 | #define CFG_CKEY_V1(v1) ((v1)<<16) | ||
333 | #define CFG_CKEY_V1_MASK 0x00FF0000 | ||
334 | #define CFG_CKEY_V(v) ((v)<<8) | ||
335 | #define CFG_CKEY_V_MASK 0x0000FF00 | ||
336 | #define CFG_ALPHA_V(v) (v) | ||
337 | #define CFG_ALPHA_V_MASK 0x000000FF | ||
338 | |||
339 | /* Graphics/Video DMA color key enable bits in LCD_TV_CTRL1 */ | ||
340 | #define CFG_CKEY_GRA 0x2 | ||
341 | #define CFG_CKEY_DMA 0x1 | ||
342 | |||
343 | /* Interlace mode enable bits in LCD_TV_CTRL1 */ | ||
344 | #define CFG_TV_INTERLACE_EN (1 << 22) | ||
345 | #define CFG_TV_NIB (1 << 0) | ||
346 | |||
347 | #define LCD_PN_SEPXLCNT 0x013c /* MMP2 */ | ||
348 | |||
349 | /* SPI Read Data Register */ | ||
350 | #define LCD_SPU_SPI_RXDATA 0x0140 | ||
351 | |||
352 | /* Smart Panel Read Data Register */ | ||
353 | #define LCD_SPU_ISA_RSDATA 0x0144 | ||
354 | #define ISA_RXDATA_16BIT_1_DATA_MASK 0x000000FF | ||
355 | #define ISA_RXDATA_16BIT_2_DATA_MASK 0x0000FF00 | ||
356 | #define ISA_RXDATA_16BIT_3_DATA_MASK 0x00FF0000 | ||
357 | #define ISA_RXDATA_16BIT_4_DATA_MASK 0xFF000000 | ||
358 | #define ISA_RXDATA_32BIT_1_DATA_MASK 0x00FFFFFF | ||
359 | |||
360 | #define LCD_SPU_DBG_ISA (0x0148) /* TTC */ | ||
361 | #define LCD_SPU_DMAVLD_YC (0x014C) | ||
362 | #define LCD_SPU_DMAVLD_UV (0x0150) | ||
363 | #define LCD_SPU_DMAVLD_UVSPU_GRAVLD (0x0154) | ||
364 | |||
365 | #define LCD_READ_IOPAD (0x0148) /* MMP2*/ | ||
366 | #define LCD_DMAVLD_YC (0x014C) | ||
367 | #define LCD_DMAVLD_UV (0x0150) | ||
368 | #define LCD_TVGGRAVLD_HLEN (0x0154) | ||
369 | |||
370 | /* HWC SRAM Read Data Register */ | ||
371 | #define LCD_SPU_HWC_RDDAT 0x0158 | ||
372 | |||
373 | /* Gamma Table SRAM Read Data Register */ | ||
374 | #define LCD_SPU_GAMMA_RDDAT 0x015c | ||
375 | #define CFG_GAMMA_RDDAT_MASK 0x000000FF | ||
376 | |||
377 | /* Palette Table SRAM Read Data Register */ | ||
378 | #define LCD_SPU_PALETTE_RDDAT 0x0160 | ||
379 | #define CFG_PALETTE_RDDAT_MASK 0x00FFFFFF | ||
380 | |||
381 | #define LCD_SPU_DBG_DMATOP (0x0164) /* TTC */ | ||
382 | #define LCD_SPU_DBG_GRATOP (0x0168) | ||
383 | #define LCD_SPU_DBG_TXCTRL (0x016C) | ||
384 | #define LCD_SPU_DBG_SLVTOP (0x0170) | ||
385 | #define LCD_SPU_DBG_MUXTOP (0x0174) | ||
386 | |||
387 | #define LCD_SLV_DBG (0x0164) /* MMP2 */ | ||
388 | #define LCD_TVDVLD_YC (0x0168) | ||
389 | #define LCD_TVDVLD_UV (0x016C) | ||
390 | #define LCD_TVC_RDDAT (0x0170) | ||
391 | #define LCD_TV_GAMMA_RDDAT (0x0174) | ||
392 | |||
393 | /* I/O Pads Input Read Only Register */ | ||
394 | #define LCD_SPU_IOPAD_IN 0x0178 | ||
395 | #define CFG_IOPAD_IN_MASK 0x0FFFFFFF | ||
396 | |||
397 | #define LCD_TV_PALETTE_RDDAT (0x0178) /* MMP2 */ | ||
398 | |||
399 | /* Reserved Read Only Registers */ | ||
400 | #define LCD_CFG_RDREG5F 0x017C | ||
401 | #define IRE_FRAME_CNT_MASK 0x000000C0 | ||
402 | #define IPE_FRAME_CNT_MASK 0x00000030 | ||
403 | #define GRA_FRAME_CNT_MASK 0x0000000C /* Graphic */ | ||
404 | #define DMA_FRAME_CNT_MASK 0x00000003 /* Video */ | ||
405 | |||
406 | #define LCD_FRAME_CNT (0x017C) /* MMP2 */ | ||
407 | |||
408 | /* SPI Control Register. */ | ||
409 | #define LCD_SPU_SPI_CTRL 0x0180 | ||
410 | #define CFG_SCLKCNT(div) ((div)<<24) /* 0xFF~0x2 */ | ||
411 | #define CFG_SCLKCNT_MASK 0xFF000000 | ||
412 | #define CFG_RXBITS(rx) (((rx) - 1)<<16) /* 0x1F~0x1 */ | ||
413 | #define CFG_RXBITS_MASK 0x00FF0000 | ||
414 | #define CFG_TXBITS(tx) (((tx) - 1)<<8) /* 0x1F~0x1 */ | ||
415 | #define CFG_TXBITS_MASK 0x0000FF00 | ||
416 | #define CFG_CLKINV(clk) ((clk)<<7) | ||
417 | #define CFG_CLKINV_MASK 0x00000080 | ||
418 | #define CFG_KEEPXFER(transfer) ((transfer)<<6) | ||
419 | #define CFG_KEEPXFER_MASK 0x00000040 | ||
420 | #define CFG_RXBITSTO0(rx) ((rx)<<5) | ||
421 | #define CFG_RXBITSTO0_MASK 0x00000020 | ||
422 | #define CFG_TXBITSTO0(tx) ((tx)<<4) | ||
423 | #define CFG_TXBITSTO0_MASK 0x00000010 | ||
424 | #define CFG_SPI_ENA(spi) ((spi)<<3) | ||
425 | #define CFG_SPI_ENA_MASK 0x00000008 | ||
426 | #define CFG_SPI_SEL(spi) ((spi)<<2) | ||
427 | #define CFG_SPI_SEL_MASK 0x00000004 | ||
428 | #define CFG_SPI_3W4WB(wire) ((wire)<<1) | ||
429 | #define CFG_SPI_3W4WB_MASK 0x00000002 | ||
430 | #define CFG_SPI_START(start) (start) | ||
431 | #define CFG_SPI_START_MASK 0x00000001 | ||
432 | |||
433 | /* SPI Tx Data Register */ | ||
434 | #define LCD_SPU_SPI_TXDATA 0x0184 | ||
435 | |||
436 | /* | ||
437 | 1. Smart Pannel 8-bit Bus Control Register. | ||
438 | 2. AHB Slave Path Data Port Register | ||
439 | */ | ||
440 | #define LCD_SPU_SMPN_CTRL 0x0188 | ||
441 | |||
442 | /* DMA Control 0 Register */ | ||
443 | #define LCD_SPU_DMA_CTRL0 0x0190 | ||
444 | #define CFG_NOBLENDING(nb) ((nb)<<31) | ||
445 | #define CFG_NOBLENDING_MASK 0x80000000 | ||
446 | #define CFG_GAMMA_ENA(gn) ((gn)<<30) | ||
447 | #define CFG_GAMMA_ENA_MASK 0x40000000 | ||
448 | #define CFG_CBSH_ENA(cn) ((cn)<<29) | ||
449 | #define CFG_CBSH_ENA_MASK 0x20000000 | ||
450 | #define CFG_PALETTE_ENA(pn) ((pn)<<28) | ||
451 | #define CFG_PALETTE_ENA_MASK 0x10000000 | ||
452 | #define CFG_ARBFAST_ENA(an) ((an)<<27) | ||
453 | #define CFG_ARBFAST_ENA_MASK 0x08000000 | ||
454 | #define CFG_HWC_1BITMOD(mode) ((mode)<<26) | ||
455 | #define CFG_HWC_1BITMOD_MASK 0x04000000 | ||
456 | #define CFG_HWC_1BITENA(mn) ((mn)<<25) | ||
457 | #define CFG_HWC_1BITENA_MASK 0x02000000 | ||
458 | #define CFG_HWC_ENA(cn) ((cn)<<24) | ||
459 | #define CFG_HWC_ENA_MASK 0x01000000 | ||
460 | #define CFG_DMAFORMAT(dmaformat) ((dmaformat)<<20) | ||
461 | #define CFG_DMAFORMAT_MASK 0x00F00000 | ||
462 | #define CFG_GRAFORMAT(graformat) ((graformat)<<16) | ||
463 | #define CFG_GRAFORMAT_MASK 0x000F0000 | ||
464 | /* for graphic part */ | ||
465 | #define CFG_GRA_FTOGGLE(toggle) ((toggle)<<15) | ||
466 | #define CFG_GRA_FTOGGLE_MASK 0x00008000 | ||
467 | #define CFG_GRA_HSMOOTH(smooth) ((smooth)<<14) | ||
468 | #define CFG_GRA_HSMOOTH_MASK 0x00004000 | ||
469 | #define CFG_GRA_TSTMODE(test) ((test)<<13) | ||
470 | #define CFG_GRA_TSTMODE_MASK 0x00002000 | ||
471 | #define CFG_GRA_SWAPRB(swap) ((swap)<<12) | ||
472 | #define CFG_GRA_SWAPRB_MASK 0x00001000 | ||
473 | #define CFG_GRA_SWAPUV(swap) ((swap)<<11) | ||
474 | #define CFG_GRA_SWAPUV_MASK 0x00000800 | ||
475 | #define CFG_GRA_SWAPYU(swap) ((swap)<<10) | ||
476 | #define CFG_GRA_SWAPYU_MASK 0x00000400 | ||
477 | #define CFG_GRA_SWAP_MASK 0x00001C00 | ||
478 | #define CFG_YUV2RGB_GRA(cvrt) ((cvrt)<<9) | ||
479 | #define CFG_YUV2RGB_GRA_MASK 0x00000200 | ||
480 | #define CFG_GRA_ENA(gra) ((gra)<<8) | ||
481 | #define CFG_GRA_ENA_MASK 0x00000100 | ||
482 | #define dma0_gfx_masks (CFG_GRAFORMAT_MASK | CFG_GRA_FTOGGLE_MASK | \ | ||
483 | CFG_GRA_HSMOOTH_MASK | CFG_GRA_TSTMODE_MASK | CFG_GRA_SWAP_MASK | \ | ||
484 | CFG_YUV2RGB_GRA_MASK | CFG_GRA_ENA_MASK) | ||
485 | /* for video part */ | ||
486 | #define CFG_DMA_FTOGGLE(toggle) ((toggle)<<7) | ||
487 | #define CFG_DMA_FTOGGLE_MASK 0x00000080 | ||
488 | #define CFG_DMA_HSMOOTH(smooth) ((smooth)<<6) | ||
489 | #define CFG_DMA_HSMOOTH_MASK 0x00000040 | ||
490 | #define CFG_DMA_TSTMODE(test) ((test)<<5) | ||
491 | #define CFG_DMA_TSTMODE_MASK 0x00000020 | ||
492 | #define CFG_DMA_SWAPRB(swap) ((swap)<<4) | ||
493 | #define CFG_DMA_SWAPRB_MASK 0x00000010 | ||
494 | #define CFG_DMA_SWAPUV(swap) ((swap)<<3) | ||
495 | #define CFG_DMA_SWAPUV_MASK 0x00000008 | ||
496 | #define CFG_DMA_SWAPYU(swap) ((swap)<<2) | ||
497 | #define CFG_DMA_SWAPYU_MASK 0x00000004 | ||
498 | #define CFG_DMA_SWAP_MASK 0x0000001C | ||
499 | #define CFG_YUV2RGB_DMA(cvrt) ((cvrt)<<1) | ||
500 | #define CFG_YUV2RGB_DMA_MASK 0x00000002 | ||
501 | #define CFG_DMA_ENA(video) (video) | ||
502 | #define CFG_DMA_ENA_MASK 0x00000001 | ||
503 | #define dma0_vid_masks (CFG_DMAFORMAT_MASK | CFG_DMA_FTOGGLE_MASK | \ | ||
504 | CFG_DMA_HSMOOTH_MASK | CFG_DMA_TSTMODE_MASK | CFG_DMA_SWAP_MASK | \ | ||
505 | CFG_YUV2RGB_DMA_MASK | CFG_DMA_ENA_MASK) | ||
506 | #define dma_palette(val) ((val ? 1 : 0) << 28) | ||
507 | #define dma_fmt(vid, val) ((val & 0xf) << ((vid) ? 20 : 16)) | ||
508 | #define dma_swaprb(vid, val) ((val ? 1 : 0) << ((vid) ? 4 : 12)) | ||
509 | #define dma_swapuv(vid, val) ((val ? 1 : 0) << ((vid) ? 3 : 11)) | ||
510 | #define dma_swapyuv(vid, val) ((val ? 1 : 0) << ((vid) ? 2 : 10)) | ||
511 | #define dma_csc(vid, val) ((val ? 1 : 0) << ((vid) ? 1 : 9)) | ||
512 | #define dma_hsmooth(vid, val) ((val ? 1 : 0) << ((vid) ? 6 : 14)) | ||
513 | #define dma_mask(vid) (dma_palette(1) | dma_fmt(vid, 0xf) | dma_csc(vid, 1) \ | ||
514 | | dma_swaprb(vid, 1) | dma_swapuv(vid, 1) | dma_swapyuv(vid, 1)) | ||
515 | |||
516 | /* DMA Control 1 Register */ | ||
517 | #define LCD_SPU_DMA_CTRL1 0x0194 | ||
518 | #define CFG_FRAME_TRIG(trig) ((trig)<<31) | ||
519 | #define CFG_FRAME_TRIG_MASK 0x80000000 | ||
520 | #define CFG_VSYNC_TRIG(trig) ((trig)<<28) | ||
521 | #define CFG_VSYNC_TRIG_MASK 0x70000000 | ||
522 | #define CFG_VSYNC_INV(inv) ((inv)<<27) | ||
523 | #define CFG_VSYNC_INV_MASK 0x08000000 | ||
524 | #define CFG_COLOR_KEY_MODE(cmode) ((cmode)<<24) | ||
525 | #define CFG_COLOR_KEY_MASK 0x07000000 | ||
526 | #define CFG_CARRY(carry) ((carry)<<23) | ||
527 | #define CFG_CARRY_MASK 0x00800000 | ||
528 | #define CFG_LNBUF_ENA(lnbuf) ((lnbuf)<<22) | ||
529 | #define CFG_LNBUF_ENA_MASK 0x00400000 | ||
530 | #define CFG_GATED_ENA(gated) ((gated)<<21) | ||
531 | #define CFG_GATED_ENA_MASK 0x00200000 | ||
532 | #define CFG_PWRDN_ENA(power) ((power)<<20) | ||
533 | #define CFG_PWRDN_ENA_MASK 0x00100000 | ||
534 | #define CFG_DSCALE(dscale) ((dscale)<<18) | ||
535 | #define CFG_DSCALE_MASK 0x000C0000 | ||
536 | #define CFG_ALPHA_MODE(amode) ((amode)<<16) | ||
537 | #define CFG_ALPHA_MODE_MASK 0x00030000 | ||
538 | #define CFG_ALPHA(alpha) ((alpha)<<8) | ||
539 | #define CFG_ALPHA_MASK 0x0000FF00 | ||
540 | #define CFG_PXLCMD(pxlcmd) (pxlcmd) | ||
541 | #define CFG_PXLCMD_MASK 0x000000FF | ||
542 | |||
543 | /* SRAM Control Register */ | ||
544 | #define LCD_SPU_SRAM_CTRL 0x0198 | ||
545 | #define CFG_SRAM_INIT_WR_RD(mode) ((mode)<<14) | ||
546 | #define CFG_SRAM_INIT_WR_RD_MASK 0x0000C000 | ||
547 | #define CFG_SRAM_ADDR_LCDID(id) ((id)<<8) | ||
548 | #define CFG_SRAM_ADDR_LCDID_MASK 0x00000F00 | ||
549 | #define CFG_SRAM_ADDR(addr) (addr) | ||
550 | #define CFG_SRAM_ADDR_MASK 0x000000FF | ||
551 | |||
552 | /* SRAM Write Data Register */ | ||
553 | #define LCD_SPU_SRAM_WRDAT 0x019C | ||
554 | |||
555 | /* SRAM RTC/WTC Control Register */ | ||
556 | #define LCD_SPU_SRAM_PARA0 0x01A0 | ||
557 | |||
558 | /* SRAM Power Down Control Register */ | ||
559 | #define LCD_SPU_SRAM_PARA1 0x01A4 | ||
560 | #define CFG_CSB_256x32(hwc) ((hwc)<<15) /* HWC */ | ||
561 | #define CFG_CSB_256x32_MASK 0x00008000 | ||
562 | #define CFG_CSB_256x24(palette) ((palette)<<14) /* Palette */ | ||
563 | #define CFG_CSB_256x24_MASK 0x00004000 | ||
564 | #define CFG_CSB_256x8(gamma) ((gamma)<<13) /* Gamma */ | ||
565 | #define CFG_CSB_256x8_MASK 0x00002000 | ||
566 | #define CFG_PDWN256x32(pdwn) ((pdwn)<<7) /* HWC */ | ||
567 | #define CFG_PDWN256x32_MASK 0x00000080 | ||
568 | #define CFG_PDWN256x24(pdwn) ((pdwn)<<6) /* Palette */ | ||
569 | #define CFG_PDWN256x24_MASK 0x00000040 | ||
570 | #define CFG_PDWN256x8(pdwn) ((pdwn)<<5) /* Gamma */ | ||
571 | #define CFG_PDWN256x8_MASK 0x00000020 | ||
572 | #define CFG_PDWN32x32(pdwn) ((pdwn)<<3) | ||
573 | #define CFG_PDWN32x32_MASK 0x00000008 | ||
574 | #define CFG_PDWN16x66(pdwn) ((pdwn)<<2) | ||
575 | #define CFG_PDWN16x66_MASK 0x00000004 | ||
576 | #define CFG_PDWN32x66(pdwn) ((pdwn)<<1) | ||
577 | #define CFG_PDWN32x66_MASK 0x00000002 | ||
578 | #define CFG_PDWN64x66(pdwn) (pdwn) | ||
579 | #define CFG_PDWN64x66_MASK 0x00000001 | ||
580 | |||
581 | /* Smart or Dumb Panel Clock Divider */ | ||
582 | #define LCD_CFG_SCLK_DIV 0x01A8 | ||
583 | #define SCLK_SRC_SEL(src) ((src)<<31) | ||
584 | #define SCLK_SRC_SEL_MASK 0x80000000 | ||
585 | #define SCLK_DISABLE (1<<28) | ||
586 | #define CLK_FRACDIV(frac) ((frac)<<16) | ||
587 | #define CLK_FRACDIV_MASK 0x0FFF0000 | ||
588 | #define DSI1_BITCLK_DIV(div) (div<<8) | ||
589 | #define DSI1_BITCLK_DIV_MASK 0x00000F00 | ||
590 | #define CLK_INT_DIV(div) (div) | ||
591 | #define CLK_INT_DIV_MASK 0x000000FF | ||
592 | |||
593 | /* Video Contrast Register */ | ||
594 | #define LCD_SPU_CONTRAST 0x01AC | ||
595 | #define CFG_BRIGHTNESS(bright) ((bright)<<16) | ||
596 | #define CFG_BRIGHTNESS_MASK 0xFFFF0000 | ||
597 | #define CFG_CONTRAST(contrast) (contrast) | ||
598 | #define CFG_CONTRAST_MASK 0x0000FFFF | ||
599 | |||
600 | /* Video Saturation Register */ | ||
601 | #define LCD_SPU_SATURATION 0x01B0 | ||
602 | #define CFG_C_MULTS(mult) ((mult)<<16) | ||
603 | #define CFG_C_MULTS_MASK 0xFFFF0000 | ||
604 | #define CFG_SATURATION(sat) (sat) | ||
605 | #define CFG_SATURATION_MASK 0x0000FFFF | ||
606 | |||
607 | /* Video Hue Adjust Register */ | ||
608 | #define LCD_SPU_CBSH_HUE 0x01B4 | ||
609 | #define CFG_SIN0(sin0) ((sin0)<<16) | ||
610 | #define CFG_SIN0_MASK 0xFFFF0000 | ||
611 | #define CFG_COS0(con0) (con0) | ||
612 | #define CFG_COS0_MASK 0x0000FFFF | ||
613 | |||
614 | /* Dump LCD Panel Control Register */ | ||
615 | #define LCD_SPU_DUMB_CTRL 0x01B8 | ||
616 | #define CFG_DUMBMODE(mode) ((mode)<<28) | ||
617 | #define CFG_DUMBMODE_MASK 0xF0000000 | ||
618 | #define CFG_LCDGPIO_O(data) ((data)<<20) | ||
619 | #define CFG_LCDGPIO_O_MASK 0x0FF00000 | ||
620 | #define CFG_LCDGPIO_ENA(gpio) ((gpio)<<12) | ||
621 | #define CFG_LCDGPIO_ENA_MASK 0x000FF000 | ||
622 | #define CFG_BIAS_OUT(bias) ((bias)<<8) | ||
623 | #define CFG_BIAS_OUT_MASK 0x00000100 | ||
624 | #define CFG_REVERSE_RGB(RGB) ((RGB)<<7) | ||
625 | #define CFG_REVERSE_RGB_MASK 0x00000080 | ||
626 | #define CFG_INV_COMPBLANK(blank) ((blank)<<6) | ||
627 | #define CFG_INV_COMPBLANK_MASK 0x00000040 | ||
628 | #define CFG_INV_COMPSYNC(sync) ((sync)<<5) | ||
629 | #define CFG_INV_COMPSYNC_MASK 0x00000020 | ||
630 | #define CFG_INV_HENA(hena) ((hena)<<4) | ||
631 | #define CFG_INV_HENA_MASK 0x00000010 | ||
632 | #define CFG_INV_VSYNC(vsync) ((vsync)<<3) | ||
633 | #define CFG_INV_VSYNC_MASK 0x00000008 | ||
634 | #define CFG_INV_HSYNC(hsync) ((hsync)<<2) | ||
635 | #define CFG_INV_HSYNC_MASK 0x00000004 | ||
636 | #define CFG_INV_PCLK(pclk) ((pclk)<<1) | ||
637 | #define CFG_INV_PCLK_MASK 0x00000002 | ||
638 | #define CFG_DUMB_ENA(dumb) (dumb) | ||
639 | #define CFG_DUMB_ENA_MASK 0x00000001 | ||
640 | |||
641 | /* LCD I/O Pads Control Register */ | ||
642 | #define SPU_IOPAD_CONTROL 0x01BC | ||
643 | #define CFG_GRA_VM_ENA(vm) ((vm)<<15) | ||
644 | #define CFG_GRA_VM_ENA_MASK 0x00008000 | ||
645 | #define CFG_DMA_VM_ENA(vm) ((vm)<<13) | ||
646 | #define CFG_DMA_VM_ENA_MASK 0x00002000 | ||
647 | #define CFG_CMD_VM_ENA(vm) ((vm)<<12) | ||
648 | #define CFG_CMD_VM_ENA_MASK 0x00001000 | ||
649 | #define CFG_CSC(csc) ((csc)<<8) | ||
650 | #define CFG_CSC_MASK 0x00000300 | ||
651 | #define CFG_BOUNDARY(size) ((size)<<5) | ||
652 | #define CFG_BOUNDARY_MASK 0x00000020 | ||
653 | #define CFG_BURST(len) ((len)<<4) | ||
654 | #define CFG_BURST_MASK 0x00000010 | ||
655 | #define CFG_IOPADMODE(iopad) (iopad) | ||
656 | #define CFG_IOPADMODE_MASK 0x0000000F | ||
657 | |||
658 | /* LCD Interrupt Control Register */ | ||
659 | #define SPU_IRQ_ENA 0x01C0 | ||
660 | #define DMA_FRAME_IRQ0_ENA(irq) ((irq)<<31) | ||
661 | #define DMA_FRAME_IRQ0_ENA_MASK 0x80000000 | ||
662 | #define DMA_FRAME_IRQ1_ENA(irq) ((irq)<<30) | ||
663 | #define DMA_FRAME_IRQ1_ENA_MASK 0x40000000 | ||
664 | #define DMA_FF_UNDERFLOW_ENA(ff) ((ff)<<29) | ||
665 | #define DMA_FF_UNDERFLOW_ENA_MASK 0x20000000 | ||
666 | #define AXI_BUS_ERROR_IRQ_ENA(irq) ((irq)<<28) | ||
667 | #define AXI_BUS_ERROR_IRQ_ENA_MASK 0x10000000 | ||
668 | #define GRA_FRAME_IRQ0_ENA(irq) ((irq)<<27) | ||
669 | #define GRA_FRAME_IRQ0_ENA_MASK 0x08000000 | ||
670 | #define GRA_FRAME_IRQ1_ENA(irq) ((irq)<<26) | ||
671 | #define GRA_FRAME_IRQ1_ENA_MASK 0x04000000 | ||
672 | #define GRA_FF_UNDERFLOW_ENA(ff) ((ff)<<25) | ||
673 | #define GRA_FF_UNDERFLOW_ENA_MASK 0x02000000 | ||
674 | #define VSYNC_IRQ_ENA(vsync_irq) ((vsync_irq)<<23) | ||
675 | #define VSYNC_IRQ_ENA_MASK 0x00800000 | ||
676 | #define DUMB_FRAMEDONE_ENA(fdone) ((fdone)<<22) | ||
677 | #define DUMB_FRAMEDONE_ENA_MASK 0x00400000 | ||
678 | #define TWC_FRAMEDONE_ENA(fdone) ((fdone)<<21) | ||
679 | #define TWC_FRAMEDONE_ENA_MASK 0x00200000 | ||
680 | #define HWC_FRAMEDONE_ENA(fdone) ((fdone)<<20) | ||
681 | #define HWC_FRAMEDONE_ENA_MASK 0x00100000 | ||
682 | #define SLV_IRQ_ENA(irq) ((irq)<<19) | ||
683 | #define SLV_IRQ_ENA_MASK 0x00080000 | ||
684 | #define SPI_IRQ_ENA(irq) ((irq)<<18) | ||
685 | #define SPI_IRQ_ENA_MASK 0x00040000 | ||
686 | #define PWRDN_IRQ_ENA(irq) ((irq)<<17) | ||
687 | #define PWRDN_IRQ_ENA_MASK 0x00020000 | ||
688 | #define AXI_LATENCY_TOO_LONG_IRQ_ENA(irq) ((irq)<<16) | ||
689 | #define AXI_LATENCY_TOO_LONG_IRQ_ENA_MASK 0x00010000 | ||
690 | #define CLEAN_SPU_IRQ_ISR(irq) (irq) | ||
691 | #define CLEAN_SPU_IRQ_ISR_MASK 0x0000FFFF | ||
692 | #define TV_DMA_FRAME_IRQ0_ENA(irq) ((irq)<<15) | ||
693 | #define TV_DMA_FRAME_IRQ0_ENA_MASK 0x00008000 | ||
694 | #define TV_DMA_FRAME_IRQ1_ENA(irq) ((irq)<<14) | ||
695 | #define TV_DMA_FRAME_IRQ1_ENA_MASK 0x00004000 | ||
696 | #define TV_DMA_FF_UNDERFLOW_ENA(unerrun) ((unerrun)<<13) | ||
697 | #define TV_DMA_FF_UNDERFLOW_ENA_MASK 0x00002000 | ||
698 | #define TVSYNC_IRQ_ENA(irq) ((irq)<<12) | ||
699 | #define TVSYNC_IRQ_ENA_MASK 0x00001000 | ||
700 | #define TV_FRAME_IRQ0_ENA(irq) ((irq)<<11) | ||
701 | #define TV_FRAME_IRQ0_ENA_MASK 0x00000800 | ||
702 | #define TV_FRAME_IRQ1_ENA(irq) ((irq)<<10) | ||
703 | #define TV_FRAME_IRQ1_ENA_MASK 0x00000400 | ||
704 | #define TV_GRA_FF_UNDERFLOW_ENA(unerrun) ((unerrun)<<9) | ||
705 | #define TV_GRA_FF_UNDERFLOW_ENA_MASK 0x00000200 | ||
706 | #define TV_FRAMEDONE_ENA(irq) ((irq)<<8) | ||
707 | #define TV_FRAMEDONE_ENA_MASK 0x00000100 | ||
708 | |||
709 | /* FIXME - JUST GUESS */ | ||
710 | #define PN2_DMA_FRAME_IRQ0_ENA(irq) ((irq)<<7) | ||
711 | #define PN2_DMA_FRAME_IRQ0_ENA_MASK 0x00000080 | ||
712 | #define PN2_DMA_FRAME_IRQ1_ENA(irq) ((irq)<<6) | ||
713 | #define PN2_DMA_FRAME_IRQ1_ENA_MASK 0x00000040 | ||
714 | #define PN2_DMA_FF_UNDERFLOW_ENA(ff) ((ff)<<5) | ||
715 | #define PN2_DMA_FF_UNDERFLOW_ENA_MASK 0x00000020 | ||
716 | #define PN2_GRA_FRAME_IRQ0_ENA(irq) ((irq)<<3) | ||
717 | #define PN2_GRA_FRAME_IRQ0_ENA_MASK 0x00000008 | ||
718 | #define PN2_GRA_FRAME_IRQ1_ENA(irq) ((irq)<<2) | ||
719 | #define PN2_GRA_FRAME_IRQ1_ENA_MASK 0x04000004 | ||
720 | #define PN2_GRA_FF_UNDERFLOW_ENA(ff) ((ff)<<1) | ||
721 | #define PN2_GRA_FF_UNDERFLOW_ENA_MASK 0x00000002 | ||
722 | #define PN2_VSYNC_IRQ_ENA(irq) ((irq)<<0) | ||
723 | #define PN2_SYNC_IRQ_ENA_MASK 0x00000001 | ||
724 | |||
725 | #define gf0_imask(id) ((id) ? (((id) & 1) ? TV_FRAME_IRQ0_ENA_MASK \ | ||
726 | : PN2_GRA_FRAME_IRQ0_ENA_MASK) : GRA_FRAME_IRQ0_ENA_MASK) | ||
727 | #define gf1_imask(id) ((id) ? (((id) & 1) ? TV_FRAME_IRQ1_ENA_MASK \ | ||
728 | : PN2_GRA_FRAME_IRQ1_ENA_MASK) : GRA_FRAME_IRQ1_ENA_MASK) | ||
729 | #define vsync_imask(id) ((id) ? (((id) & 1) ? TVSYNC_IRQ_ENA_MASK \ | ||
730 | : PN2_SYNC_IRQ_ENA_MASK) : VSYNC_IRQ_ENA_MASK) | ||
731 | #define vsync_imasks (vsync_imask(0) | vsync_imask(1)) | ||
732 | |||
733 | #define display_done_imask(id) ((id) ? (((id) & 1) ? TV_FRAMEDONE_ENA_MASK\ | ||
734 | : (PN2_DMA_FRAME_IRQ0_ENA_MASK | PN2_DMA_FRAME_IRQ1_ENA_MASK))\ | ||
735 | : DUMB_FRAMEDONE_ENA_MASK) | ||
736 | |||
737 | #define display_done_imasks (display_done_imask(0) | display_done_imask(1)) | ||
738 | |||
739 | #define vf0_imask(id) ((id) ? (((id) & 1) ? TV_DMA_FRAME_IRQ0_ENA_MASK \ | ||
740 | : PN2_DMA_FRAME_IRQ0_ENA_MASK) : DMA_FRAME_IRQ0_ENA_MASK) | ||
741 | #define vf1_imask(id) ((id) ? (((id) & 1) ? TV_DMA_FRAME_IRQ1_ENA_MASK \ | ||
742 | : PN2_DMA_FRAME_IRQ1_ENA_MASK) : DMA_FRAME_IRQ1_ENA_MASK) | ||
743 | |||
744 | #define gfx_imasks (gf0_imask(0) | gf1_imask(0) | gf0_imask(1) | \ | ||
745 | gf1_imask(1)) | ||
746 | #define vid_imasks (vf0_imask(0) | vf1_imask(0) | vf0_imask(1) | \ | ||
747 | vf1_imask(1)) | ||
748 | #define vid_imask(id) (display_done_imask(id)) | ||
749 | |||
750 | #define pn1_imasks (gf0_imask(0) | gf1_imask(0) | vsync_imask(0) | \ | ||
751 | display_done_imask(0) | vf0_imask(0) | vf1_imask(0)) | ||
752 | #define tv_imasks (gf0_imask(1) | gf1_imask(1) | vsync_imask(1) | \ | ||
753 | display_done_imask(1) | vf0_imask(1) | vf1_imask(1)) | ||
754 | #define path_imasks(id) ((id) ? (tv_imasks) : (pn1_imasks)) | ||
755 | |||
756 | /* error indications */ | ||
757 | #define vid_udflow_imask(id) ((id) ? (((id) & 1) ? \ | ||
758 | (TV_DMA_FF_UNDERFLOW_ENA_MASK) : (PN2_DMA_FF_UNDERFLOW_ENA_MASK)) : \ | ||
759 | (DMA_FF_UNDERFLOW_ENA_MASK)) | ||
760 | #define gfx_udflow_imask(id) ((id) ? (((id) & 1) ? \ | ||
761 | (TV_GRA_FF_UNDERFLOW_ENA_MASK) : (PN2_GRA_FF_UNDERFLOW_ENA_MASK)) : \ | ||
762 | (GRA_FF_UNDERFLOW_ENA_MASK)) | ||
763 | |||
764 | #define err_imask(id) (vid_udflow_imask(id) | gfx_udflow_imask(id) | \ | ||
765 | AXI_BUS_ERROR_IRQ_ENA_MASK | AXI_LATENCY_TOO_LONG_IRQ_ENA_MASK) | ||
766 | #define err_imasks (err_imask(0) | err_imask(1) | err_imask(2)) | ||
767 | /* LCD Interrupt Status Register */ | ||
768 | #define SPU_IRQ_ISR 0x01C4 | ||
769 | #define DMA_FRAME_IRQ0(irq) ((irq)<<31) | ||
770 | #define DMA_FRAME_IRQ0_MASK 0x80000000 | ||
771 | #define DMA_FRAME_IRQ1(irq) ((irq)<<30) | ||
772 | #define DMA_FRAME_IRQ1_MASK 0x40000000 | ||
773 | #define DMA_FF_UNDERFLOW(ff) ((ff)<<29) | ||
774 | #define DMA_FF_UNDERFLOW_MASK 0x20000000 | ||
775 | #define AXI_BUS_ERROR_IRQ(irq) ((irq)<<28) | ||
776 | #define AXI_BUS_ERROR_IRQ_MASK 0x10000000 | ||
777 | #define GRA_FRAME_IRQ0(irq) ((irq)<<27) | ||
778 | #define GRA_FRAME_IRQ0_MASK 0x08000000 | ||
779 | #define GRA_FRAME_IRQ1(irq) ((irq)<<26) | ||
780 | #define GRA_FRAME_IRQ1_MASK 0x04000000 | ||
781 | #define GRA_FF_UNDERFLOW(ff) ((ff)<<25) | ||
782 | #define GRA_FF_UNDERFLOW_MASK 0x02000000 | ||
783 | #define VSYNC_IRQ(vsync_irq) ((vsync_irq)<<23) | ||
784 | #define VSYNC_IRQ_MASK 0x00800000 | ||
785 | #define DUMB_FRAMEDONE(fdone) ((fdone)<<22) | ||
786 | #define DUMB_FRAMEDONE_MASK 0x00400000 | ||
787 | #define TWC_FRAMEDONE(fdone) ((fdone)<<21) | ||
788 | #define TWC_FRAMEDONE_MASK 0x00200000 | ||
789 | #define HWC_FRAMEDONE(fdone) ((fdone)<<20) | ||
790 | #define HWC_FRAMEDONE_MASK 0x00100000 | ||
791 | #define SLV_IRQ(irq) ((irq)<<19) | ||
792 | #define SLV_IRQ_MASK 0x00080000 | ||
793 | #define SPI_IRQ(irq) ((irq)<<18) | ||
794 | #define SPI_IRQ_MASK 0x00040000 | ||
795 | #define PWRDN_IRQ(irq) ((irq)<<17) | ||
796 | #define PWRDN_IRQ_MASK 0x00020000 | ||
797 | #define AXI_LATENCY_TOO_LONGR_IRQ(irq) ((irq)<<16) | ||
798 | #define AXI_LATENCY_TOO_LONGR_IRQ_MASK 0x00010000 | ||
799 | #define TV_DMA_FRAME_IRQ0(irq) ((irq)<<15) | ||
800 | #define TV_DMA_FRAME_IRQ0_MASK 0x00008000 | ||
801 | #define TV_DMA_FRAME_IRQ1(irq) ((irq)<<14) | ||
802 | #define TV_DMA_FRAME_IRQ1_MASK 0x00004000 | ||
803 | #define TV_DMA_FF_UNDERFLOW(unerrun) ((unerrun)<<13) | ||
804 | #define TV_DMA_FF_UNDERFLOW_MASK 0x00002000 | ||
805 | #define TVSYNC_IRQ(irq) ((irq)<<12) | ||
806 | #define TVSYNC_IRQ_MASK 0x00001000 | ||
807 | #define TV_FRAME_IRQ0(irq) ((irq)<<11) | ||
808 | #define TV_FRAME_IRQ0_MASK 0x00000800 | ||
809 | #define TV_FRAME_IRQ1(irq) ((irq)<<10) | ||
810 | #define TV_FRAME_IRQ1_MASK 0x00000400 | ||
811 | #define TV_GRA_FF_UNDERFLOW(unerrun) ((unerrun)<<9) | ||
812 | #define TV_GRA_FF_UNDERFLOW_MASK 0x00000200 | ||
813 | #define PN2_DMA_FRAME_IRQ0(irq) ((irq)<<7) | ||
814 | #define PN2_DMA_FRAME_IRQ0_MASK 0x00000080 | ||
815 | #define PN2_DMA_FRAME_IRQ1(irq) ((irq)<<6) | ||
816 | #define PN2_DMA_FRAME_IRQ1_MASK 0x00000040 | ||
817 | #define PN2_DMA_FF_UNDERFLOW(ff) ((ff)<<5) | ||
818 | #define PN2_DMA_FF_UNDERFLOW_MASK 0x00000020 | ||
819 | #define PN2_GRA_FRAME_IRQ0(irq) ((irq)<<3) | ||
820 | #define PN2_GRA_FRAME_IRQ0_MASK 0x00000008 | ||
821 | #define PN2_GRA_FRAME_IRQ1(irq) ((irq)<<2) | ||
822 | #define PN2_GRA_FRAME_IRQ1_MASK 0x04000004 | ||
823 | #define PN2_GRA_FF_UNDERFLOW(ff) ((ff)<<1) | ||
824 | #define PN2_GRA_FF_UNDERFLOW_MASK 0x00000002 | ||
825 | #define PN2_VSYNC_IRQ(irq) ((irq)<<0) | ||
826 | #define PN2_SYNC_IRQ_MASK 0x00000001 | ||
827 | |||
828 | /* LCD FIFO Depth register */ | ||
829 | #define LCD_FIFO_DEPTH 0x01c8 | ||
830 | #define VIDEO_FIFO(fi) ((fi) << 0) | ||
831 | #define VIDEO_FIFO_MASK 0x00000003 | ||
832 | #define GRAPHIC_FIFO(fi) ((fi) << 2) | ||
833 | #define GRAPHIC_FIFO_MASK 0x0000000c | ||
834 | |||
835 | /* read-only */ | ||
836 | #define DMA_FRAME_IRQ0_LEVEL_MASK 0x00008000 | ||
837 | #define DMA_FRAME_IRQ1_LEVEL_MASK 0x00004000 | ||
838 | #define DMA_FRAME_CNT_ISR_MASK 0x00003000 | ||
839 | #define GRA_FRAME_IRQ0_LEVEL_MASK 0x00000800 | ||
840 | #define GRA_FRAME_IRQ1_LEVEL_MASK 0x00000400 | ||
841 | #define GRA_FRAME_CNT_ISR_MASK 0x00000300 | ||
842 | #define VSYNC_IRQ_LEVEL_MASK 0x00000080 | ||
843 | #define DUMB_FRAMEDONE_LEVEL_MASK 0x00000040 | ||
844 | #define TWC_FRAMEDONE_LEVEL_MASK 0x00000020 | ||
845 | #define HWC_FRAMEDONE_LEVEL_MASK 0x00000010 | ||
846 | #define SLV_FF_EMPTY_MASK 0x00000008 | ||
847 | #define DMA_FF_ALLEMPTY_MASK 0x00000004 | ||
848 | #define GRA_FF_ALLEMPTY_MASK 0x00000002 | ||
849 | #define PWRDN_IRQ_LEVEL_MASK 0x00000001 | ||
850 | |||
851 | /* 32 bit LCD Interrupt Reset Status*/ | ||
852 | #define SPU_IRQ_RSR (0x01C8) | ||
853 | /* 32 bit Panel Path Graphic Partial Display Horizontal Control Register*/ | ||
854 | #define LCD_GRA_CUTHPXL (0x01CC) | ||
855 | /* 32 bit Panel Path Graphic Partial Display Vertical Control Register*/ | ||
856 | #define LCD_GRA_CUTVLN (0x01D0) | ||
857 | /* 32 bit TV Path Graphic Partial Display Horizontal Control Register*/ | ||
858 | #define LCD_TVG_CUTHPXL (0x01D4) | ||
859 | /* 32 bit TV Path Graphic Partial Display Vertical Control Register*/ | ||
860 | #define LCD_TVG_CUTVLN (0x01D8) | ||
861 | /* 32 bit LCD Global Control Register*/ | ||
862 | #define LCD_TOP_CTRL (0x01DC) | ||
863 | /* 32 bit LCD SQU Line Buffer Control Register 1*/ | ||
864 | #define LCD_SQULN1_CTRL (0x01E0) | ||
865 | /* 32 bit LCD SQU Line Buffer Control Register 2*/ | ||
866 | #define LCD_SQULN2_CTRL (0x01E4) | ||
867 | #define squln_ctrl(id) ((id) ? (((id) & 1) ? LCD_SQULN2_CTRL : \ | ||
868 | LCD_PN2_SQULN1_CTRL) : LCD_SQULN1_CTRL) | ||
869 | |||
870 | /* 32 bit LCD Mixed Overlay Control Register */ | ||
871 | #define LCD_AFA_ALL2ONE (0x01E8) | ||
872 | |||
873 | #define LCD_PN2_SCLK_DIV (0x01EC) | ||
874 | #define LCD_PN2_TCLK_DIV (0x01F0) | ||
875 | #define LCD_LVDS_SCLK_DIV_WR (0x01F4) | ||
876 | #define LCD_LVDS_SCLK_DIV_RD (0x01FC) | ||
877 | #define PN2_LCD_DMA_START_ADDR_Y0 (0x0200) | ||
878 | #define PN2_LCD_DMA_START_ADDR_U0 (0x0204) | ||
879 | #define PN2_LCD_DMA_START_ADDR_V0 (0x0208) | ||
880 | #define PN2_LCD_DMA_START_ADDR_C0 (0x020C) | ||
881 | #define PN2_LCD_DMA_START_ADDR_Y1 (0x0210) | ||
882 | #define PN2_LCD_DMA_START_ADDR_U1 (0x0214) | ||
883 | #define PN2_LCD_DMA_START_ADDR_V1 (0x0218) | ||
884 | #define PN2_LCD_DMA_START_ADDR_C1 (0x021C) | ||
885 | #define PN2_LCD_DMA_PITCH_YC (0x0220) | ||
886 | #define PN2_LCD_DMA_PITCH_UV (0x0224) | ||
887 | #define PN2_LCD_DMA_OVSA_HPXL_VLN (0x0228) | ||
888 | #define PN2_LCD_DMA_HPXL_VLN (0x022C) | ||
889 | #define PN2_LCD_DMAZM_HPXL_VLN (0x0230) | ||
890 | #define PN2_LCD_GRA_START_ADDR0 (0x0234) | ||
891 | #define PN2_LCD_GRA_START_ADDR1 (0x0238) | ||
892 | #define PN2_LCD_GRA_PITCH (0x023C) | ||
893 | #define PN2_LCD_GRA_OVSA_HPXL_VLN (0x0240) | ||
894 | #define PN2_LCD_GRA_HPXL_VLN (0x0244) | ||
895 | #define PN2_LCD_GRAZM_HPXL_VLN (0x0248) | ||
896 | #define PN2_LCD_HWC_OVSA_HPXL_VLN (0x024C) | ||
897 | #define PN2_LCD_HWC_HPXL_VLN (0x0250) | ||
898 | #define LCD_PN2_V_H_TOTAL (0x0254) | ||
899 | #define LCD_PN2_V_H_ACTIVE (0x0258) | ||
900 | #define LCD_PN2_H_PORCH (0x025C) | ||
901 | #define LCD_PN2_V_PORCH (0x0260) | ||
902 | #define LCD_PN2_BLANKCOLOR (0x0264) | ||
903 | #define LCD_PN2_ALPHA_COLOR1 (0x0268) | ||
904 | #define LCD_PN2_ALPHA_COLOR2 (0x026C) | ||
905 | #define LCD_PN2_COLORKEY_Y (0x0270) | ||
906 | #define LCD_PN2_COLORKEY_U (0x0274) | ||
907 | #define LCD_PN2_COLORKEY_V (0x0278) | ||
908 | #define LCD_PN2_SEPXLCNT (0x027C) | ||
909 | #define LCD_TV_V_H_TOTAL_FLD (0x0280) | ||
910 | #define LCD_TV_V_PORCH_FLD (0x0284) | ||
911 | #define LCD_TV_SEPXLCNT_FLD (0x0288) | ||
912 | |||
913 | #define LCD_2ND_ALPHA (0x0294) | ||
914 | #define LCD_PN2_CONTRAST (0x0298) | ||
915 | #define LCD_PN2_SATURATION (0x029c) | ||
916 | #define LCD_PN2_CBSH_HUE (0x02a0) | ||
917 | #define LCD_TIMING_EXT (0x02C0) | ||
918 | #define LCD_PN2_LAYER_ALPHA_SEL1 (0x02c4) | ||
919 | #define LCD_PN2_CTRL0 (0x02C8) | ||
920 | #define TV_LAYER_ALPHA_SEL1 (0x02cc) | ||
921 | #define LCD_SMPN2_CTRL (0x02D0) | ||
922 | #define LCD_IO_OVERL_MAP_CTRL (0x02D4) | ||
923 | #define LCD_DUMB2_CTRL (0x02d8) | ||
924 | #define LCD_PN2_CTRL1 (0x02DC) | ||
925 | #define PN2_IOPAD_CONTROL (0x02E0) | ||
926 | #define LCD_PN2_SQULN1_CTRL (0x02E4) | ||
927 | #define PN2_LCD_GRA_CUTHPXL (0x02e8) | ||
928 | #define PN2_LCD_GRA_CUTVLN (0x02ec) | ||
929 | #define LCD_PN2_SQULN2_CTRL (0x02F0) | ||
930 | #define ALL_LAYER_ALPHA_SEL (0x02F4) | ||
931 | |||
932 | /* pxa988 has different MASTER_CTRL from MMP3/MMP2 */ | ||
933 | #ifdef CONFIG_CPU_PXA988 | ||
934 | #define TIMING_MASTER_CONTROL (0x01F4) | ||
935 | #define MASTER_ENH(id) (1 << ((id) + 5)) | ||
936 | #define MASTER_ENV(id) (1 << ((id) + 6)) | ||
937 | #else | ||
938 | #define TIMING_MASTER_CONTROL (0x02F8) | ||
939 | #define MASTER_ENH(id) (1 << (id)) | ||
940 | #define MASTER_ENV(id) (1 << ((id) + 4)) | ||
941 | #endif | ||
942 | |||
943 | #define DSI_START_SEL_SHIFT(id) (((id) << 1) + 8) | ||
944 | #define timing_master_config(path, dsi_id, lcd_id) \ | ||
945 | (MASTER_ENH(path) | MASTER_ENV(path) | \ | ||
946 | (((lcd_id) + ((dsi_id) << 1)) << DSI_START_SEL_SHIFT(path))) | ||
947 | |||
948 | #define LCD_2ND_BLD_CTL (0x02Fc) | ||
949 | #define LVDS_SRC_MASK (3 << 30) | ||
950 | #define LVDS_SRC_SHIFT (30) | ||
951 | #define LVDS_FMT_MASK (1 << 28) | ||
952 | #define LVDS_FMT_SHIFT (28) | ||
953 | |||
954 | #define CLK_SCLK (1 << 0) | ||
955 | #define CLK_LVDS_RD (1 << 1) | ||
956 | #define CLK_LVDS_WR (1 << 2) | ||
957 | |||
958 | #define gra_partdisp_ctrl_hor(id) ((id) ? (((id) & 1) ? \ | ||
959 | LCD_TVG_CUTHPXL : PN2_LCD_GRA_CUTHPXL) : LCD_GRA_CUTHPXL) | ||
960 | #define gra_partdisp_ctrl_ver(id) ((id) ? (((id) & 1) ? \ | ||
961 | LCD_TVG_CUTVLN : PN2_LCD_GRA_CUTVLN) : LCD_GRA_CUTVLN) | ||
962 | |||
963 | /* | ||
964 | * defined Video Memory Color format for DMA control 0 register | ||
965 | * DMA0 bit[23:20] | ||
966 | */ | ||
967 | #define VMODE_RGB565 0x0 | ||
968 | #define VMODE_RGB1555 0x1 | ||
969 | #define VMODE_RGB888PACKED 0x2 | ||
970 | #define VMODE_RGB888UNPACKED 0x3 | ||
971 | #define VMODE_RGBA888 0x4 | ||
972 | #define VMODE_YUV422PACKED 0x5 | ||
973 | #define VMODE_YUV422PLANAR 0x6 | ||
974 | #define VMODE_YUV420PLANAR 0x7 | ||
975 | #define VMODE_SMPNCMD 0x8 | ||
976 | #define VMODE_PALETTE4BIT 0x9 | ||
977 | #define VMODE_PALETTE8BIT 0xa | ||
978 | #define VMODE_RESERVED 0xb | ||
979 | |||
980 | /* | ||
981 | * defined Graphic Memory Color format for DMA control 0 register | ||
982 | * DMA0 bit[19:16] | ||
983 | */ | ||
984 | #define GMODE_RGB565 0x0 | ||
985 | #define GMODE_RGB1555 0x1 | ||
986 | #define GMODE_RGB888PACKED 0x2 | ||
987 | #define GMODE_RGB888UNPACKED 0x3 | ||
988 | #define GMODE_RGBA888 0x4 | ||
989 | #define GMODE_YUV422PACKED 0x5 | ||
990 | #define GMODE_YUV422PLANAR 0x6 | ||
991 | #define GMODE_YUV420PLANAR 0x7 | ||
992 | #define GMODE_SMPNCMD 0x8 | ||
993 | #define GMODE_PALETTE4BIT 0x9 | ||
994 | #define GMODE_PALETTE8BIT 0xa | ||
995 | #define GMODE_RESERVED 0xb | ||
996 | |||
997 | /* | ||
998 | * define for DMA control 1 register | ||
999 | */ | ||
1000 | #define DMA1_FRAME_TRIG 31 /* bit location */ | ||
1001 | #define DMA1_VSYNC_MODE 28 | ||
1002 | #define DMA1_VSYNC_INV 27 | ||
1003 | #define DMA1_CKEY 24 | ||
1004 | #define DMA1_CARRY 23 | ||
1005 | #define DMA1_LNBUF_ENA 22 | ||
1006 | #define DMA1_GATED_ENA 21 | ||
1007 | #define DMA1_PWRDN_ENA 20 | ||
1008 | #define DMA1_DSCALE 18 | ||
1009 | #define DMA1_ALPHA_MODE 16 | ||
1010 | #define DMA1_ALPHA 08 | ||
1011 | #define DMA1_PXLCMD 00 | ||
1012 | |||
1013 | /* | ||
1014 | * defined for Configure Dumb Mode | ||
1015 | * DUMB LCD Panel bit[31:28] | ||
1016 | */ | ||
1017 | #define DUMB16_RGB565_0 0x0 | ||
1018 | #define DUMB16_RGB565_1 0x1 | ||
1019 | #define DUMB18_RGB666_0 0x2 | ||
1020 | #define DUMB18_RGB666_1 0x3 | ||
1021 | #define DUMB12_RGB444_0 0x4 | ||
1022 | #define DUMB12_RGB444_1 0x5 | ||
1023 | #define DUMB24_RGB888_0 0x6 | ||
1024 | #define DUMB_BLANK 0x7 | ||
1025 | |||
1026 | /* | ||
1027 | * defined for Configure I/O Pin Allocation Mode | ||
1028 | * LCD LCD I/O Pads control register bit[3:0] | ||
1029 | */ | ||
1030 | #define IOPAD_DUMB24 0x0 | ||
1031 | #define IOPAD_DUMB18SPI 0x1 | ||
1032 | #define IOPAD_DUMB18GPIO 0x2 | ||
1033 | #define IOPAD_DUMB16SPI 0x3 | ||
1034 | #define IOPAD_DUMB16GPIO 0x4 | ||
1035 | #define IOPAD_DUMB12 0x5 | ||
1036 | #define IOPAD_SMART18SPI 0x6 | ||
1037 | #define IOPAD_SMART16SPI 0x7 | ||
1038 | #define IOPAD_SMART8BOTH 0x8 | ||
1039 | #define IOPAD_DUMB18_SMART8 0x9 | ||
1040 | #define IOPAD_DUMB16_SMART8SPI 0xa | ||
1041 | #define IOPAD_DUMB16_SMART8GPIO 0xb | ||
1042 | #define IOPAD_DUMB16_DUMB16 0xc | ||
1043 | #define IOPAD_SMART8_SMART8 0xc | ||
1044 | |||
1045 | /* | ||
1046 | *defined for indicating boundary and cycle burst length | ||
1047 | */ | ||
1048 | #define CFG_BOUNDARY_1KB (1<<5) | ||
1049 | #define CFG_BOUNDARY_4KB (0<<5) | ||
1050 | #define CFG_CYC_BURST_LEN16 (1<<4) | ||
1051 | #define CFG_CYC_BURST_LEN8 (0<<4) | ||
1052 | |||
1053 | /* | ||
1054 | * defined Dumb Panel Clock Divider register | ||
1055 | * SCLK_Source bit[31] | ||
1056 | */ | ||
1057 | /* 0: PLL clock select*/ | ||
1058 | #define AXI_BUS_SEL 0x80000000 | ||
1059 | #define CCD_CLK_SEL 0x40000000 | ||
1060 | #define DCON_CLK_SEL 0x20000000 | ||
1061 | #define ENA_CLK_INT_DIV CONFIG_FB_DOVE_CLCD_SCLK_DIV | ||
1062 | #define IDLE_CLK_INT_DIV 0x1 /* idle Integer Divider */ | ||
1063 | #define DIS_CLK_INT_DIV 0x0 /* Disable Integer Divider */ | ||
1064 | |||
1065 | /* SRAM ID */ | ||
1066 | #define SRAMID_GAMMA_YR 0x0 | ||
1067 | #define SRAMID_GAMMA_UG 0x1 | ||
1068 | #define SRAMID_GAMMA_VB 0x2 | ||
1069 | #define SRAMID_PALATTE 0x3 | ||
1070 | #define SRAMID_HWC 0xf | ||
1071 | |||
1072 | /* SRAM INIT Read/Write */ | ||
1073 | #define SRAMID_INIT_READ 0x0 | ||
1074 | #define SRAMID_INIT_WRITE 0x2 | ||
1075 | #define SRAMID_INIT_DEFAULT 0x3 | ||
1076 | |||
1077 | /* | ||
1078 | * defined VSYNC selection mode for DMA control 1 register | ||
1079 | * DMA1 bit[30:28] | ||
1080 | */ | ||
1081 | #define VMODE_SMPN 0x0 | ||
1082 | #define VMODE_SMPNIRQ 0x1 | ||
1083 | #define VMODE_DUMB 0x2 | ||
1084 | #define VMODE_IPE 0x3 | ||
1085 | #define VMODE_IRE 0x4 | ||
1086 | |||
1087 | /* | ||
1088 | * defined Configure Alpha and Alpha mode for DMA control 1 register | ||
1089 | * DMA1 bit[15:08](alpha) / bit[17:16](alpha mode) | ||
1090 | */ | ||
1091 | /* ALPHA mode */ | ||
1092 | #define MODE_ALPHA_DMA 0x0 | ||
1093 | #define MODE_ALPHA_GRA 0x1 | ||
1094 | #define MODE_ALPHA_CFG 0x2 | ||
1095 | |||
1096 | /* alpha value */ | ||
1097 | #define ALPHA_NOGRAPHIC 0xFF /* all video, no graphic */ | ||
1098 | #define ALPHA_NOVIDEO 0x00 /* all graphic, no video */ | ||
1099 | #define ALPHA_GRAPHNVIDEO 0x0F /* Selects graphic & video */ | ||
1100 | |||
1101 | /* | ||
1102 | * defined Pixel Command for DMA control 1 register | ||
1103 | * DMA1 bit[07:00] | ||
1104 | */ | ||
1105 | #define PIXEL_CMD 0x81 | ||
1106 | |||
1107 | /* DSI */ | ||
1108 | /* DSI1 - 4 Lane Controller base */ | ||
1109 | #define DSI1_REGS_PHYSICAL_BASE 0xD420B800 | ||
1110 | /* DSI2 - 3 Lane Controller base */ | ||
1111 | #define DSI2_REGS_PHYSICAL_BASE 0xD420BA00 | ||
1112 | |||
1113 | /* DSI Controller Registers */ | ||
1114 | struct dsi_lcd_regs { | ||
1115 | #define DSI_LCD1_CTRL_0 0x100 /* DSI Active Panel 1 Control register 0 */ | ||
1116 | #define DSI_LCD1_CTRL_1 0x104 /* DSI Active Panel 1 Control register 1 */ | ||
1117 | u32 ctrl0; | ||
1118 | u32 ctrl1; | ||
1119 | u32 reserved1[2]; | ||
1120 | |||
1121 | #define DSI_LCD1_TIMING_0 0x110 /* Timing register 0 */ | ||
1122 | #define DSI_LCD1_TIMING_1 0x114 /* Timing register 1 */ | ||
1123 | #define DSI_LCD1_TIMING_2 0x118 /* Timing register 2 */ | ||
1124 | #define DSI_LCD1_TIMING_3 0x11C /* Timing register 3 */ | ||
1125 | #define DSI_LCD1_WC_0 0x120 /* Word Count register 0 */ | ||
1126 | #define DSI_LCD1_WC_1 0x124 /* Word Count register 1 */ | ||
1127 | #define DSI_LCD1_WC_2 0x128 /* Word Count register 2 */ | ||
1128 | u32 timing0; | ||
1129 | u32 timing1; | ||
1130 | u32 timing2; | ||
1131 | u32 timing3; | ||
1132 | u32 wc0; | ||
1133 | u32 wc1; | ||
1134 | u32 wc2; | ||
1135 | u32 reserved2[1]; | ||
1136 | u32 slot_cnt0; | ||
1137 | u32 slot_cnt1; | ||
1138 | u32 reserved3[2]; | ||
1139 | u32 status_0; | ||
1140 | u32 status_1; | ||
1141 | u32 status_2; | ||
1142 | u32 status_3; | ||
1143 | u32 status_4; | ||
1144 | }; | ||
1145 | |||
1146 | struct dsi_regs { | ||
1147 | #define DSI_CTRL_0 0x000 /* DSI control register 0 */ | ||
1148 | #define DSI_CTRL_1 0x004 /* DSI control register 1 */ | ||
1149 | u32 ctrl0; | ||
1150 | u32 ctrl1; | ||
1151 | u32 reserved1[2]; | ||
1152 | u32 irq_status; | ||
1153 | u32 irq_mask; | ||
1154 | u32 reserved2[2]; | ||
1155 | |||
1156 | #define DSI_CPU_CMD_0 0x020 /* DSI CPU packet command register 0 */ | ||
1157 | #define DSI_CPU_CMD_1 0x024 /* DSU CPU Packet Command Register 1 */ | ||
1158 | #define DSI_CPU_CMD_3 0x02C /* DSU CPU Packet Command Register 3 */ | ||
1159 | #define DSI_CPU_WDAT_0 0x030 /* DSI CUP */ | ||
1160 | u32 cmd0; | ||
1161 | u32 cmd1; | ||
1162 | u32 cmd2; | ||
1163 | u32 cmd3; | ||
1164 | u32 dat0; | ||
1165 | u32 status0; | ||
1166 | u32 status1; | ||
1167 | u32 status2; | ||
1168 | u32 status3; | ||
1169 | u32 status4; | ||
1170 | u32 reserved3[2]; | ||
1171 | |||
1172 | u32 smt_cmd; | ||
1173 | u32 smt_ctrl0; | ||
1174 | u32 smt_ctrl1; | ||
1175 | u32 reserved4[1]; | ||
1176 | |||
1177 | u32 rx0_status; | ||
1178 | |||
1179 | /* Rx Packet Header - data from slave device */ | ||
1180 | #define DSI_RX_PKT_HDR_0 0x064 | ||
1181 | u32 rx0_header; | ||
1182 | u32 rx1_status; | ||
1183 | u32 rx1_header; | ||
1184 | u32 rx_ctrl; | ||
1185 | u32 rx_ctrl1; | ||
1186 | u32 rx2_status; | ||
1187 | u32 rx2_header; | ||
1188 | u32 reserved5[1]; | ||
1189 | |||
1190 | u32 phy_ctrl1; | ||
1191 | #define DSI_PHY_CTRL_2 0x088 /* DSI DPHI Control Register 2 */ | ||
1192 | #define DSI_PHY_CTRL_3 0x08C /* DPHY Control Register 3 */ | ||
1193 | u32 phy_ctrl2; | ||
1194 | u32 phy_ctrl3; | ||
1195 | u32 phy_status0; | ||
1196 | u32 phy_status1; | ||
1197 | u32 reserved6[5]; | ||
1198 | u32 phy_status2; | ||
1199 | |||
1200 | #define DSI_PHY_RCOMP_0 0x0B0 /* DPHY Rcomp Control Register */ | ||
1201 | u32 phy_rcomp0; | ||
1202 | u32 reserved7[3]; | ||
1203 | #define DSI_PHY_TIME_0 0x0C0 /* DPHY Timing Control Register 0 */ | ||
1204 | #define DSI_PHY_TIME_1 0x0C4 /* DPHY Timing Control Register 1 */ | ||
1205 | #define DSI_PHY_TIME_2 0x0C8 /* DPHY Timing Control Register 2 */ | ||
1206 | #define DSI_PHY_TIME_3 0x0CC /* DPHY Timing Control Register 3 */ | ||
1207 | #define DSI_PHY_TIME_4 0x0D0 /* DPHY Timing Control Register 4 */ | ||
1208 | #define DSI_PHY_TIME_5 0x0D4 /* DPHY Timing Control Register 5 */ | ||
1209 | u32 phy_timing0; | ||
1210 | u32 phy_timing1; | ||
1211 | u32 phy_timing2; | ||
1212 | u32 phy_timing3; | ||
1213 | u32 phy_code_0; | ||
1214 | u32 phy_code_1; | ||
1215 | u32 reserved8[2]; | ||
1216 | u32 mem_ctrl; | ||
1217 | u32 tx_timer; | ||
1218 | u32 rx_timer; | ||
1219 | u32 turn_timer; | ||
1220 | u32 reserved9[4]; | ||
1221 | |||
1222 | #define DSI_LCD1_CTRL_0 0x100 /* DSI Active Panel 1 Control register 0 */ | ||
1223 | #define DSI_LCD1_CTRL_1 0x104 /* DSI Active Panel 1 Control register 1 */ | ||
1224 | #define DSI_LCD1_TIMING_0 0x110 /* Timing register 0 */ | ||
1225 | #define DSI_LCD1_TIMING_1 0x114 /* Timing register 1 */ | ||
1226 | #define DSI_LCD1_TIMING_2 0x118 /* Timing register 2 */ | ||
1227 | #define DSI_LCD1_TIMING_3 0x11C /* Timing register 3 */ | ||
1228 | #define DSI_LCD1_WC_0 0x120 /* Word Count register 0 */ | ||
1229 | #define DSI_LCD1_WC_1 0x124 /* Word Count register 1 */ | ||
1230 | #define DSI_LCD1_WC_2 0x128 /* Word Count register 2 */ | ||
1231 | struct dsi_lcd_regs lcd1; | ||
1232 | u32 reserved10[11]; | ||
1233 | struct dsi_lcd_regs lcd2; | ||
1234 | }; | ||
1235 | |||
1236 | #define DSI_LCD2_CTRL_0 0x180 /* DSI Active Panel 2 Control register 0 */ | ||
1237 | #define DSI_LCD2_CTRL_1 0x184 /* DSI Active Panel 2 Control register 1 */ | ||
1238 | #define DSI_LCD2_TIMING_0 0x190 /* Timing register 0 */ | ||
1239 | #define DSI_LCD2_TIMING_1 0x194 /* Timing register 1 */ | ||
1240 | #define DSI_LCD2_TIMING_2 0x198 /* Timing register 2 */ | ||
1241 | #define DSI_LCD2_TIMING_3 0x19C /* Timing register 3 */ | ||
1242 | #define DSI_LCD2_WC_0 0x1A0 /* Word Count register 0 */ | ||
1243 | #define DSI_LCD2_WC_1 0x1A4 /* Word Count register 1 */ | ||
1244 | #define DSI_LCD2_WC_2 0x1A8 /* Word Count register 2 */ | ||
1245 | |||
1246 | /* DSI_CTRL_0 0x0000 DSI Control Register 0 */ | ||
1247 | #define DSI_CTRL_0_CFG_SOFT_RST (1<<31) | ||
1248 | #define DSI_CTRL_0_CFG_SOFT_RST_REG (1<<30) | ||
1249 | #define DSI_CTRL_0_CFG_LCD1_TX_EN (1<<8) | ||
1250 | #define DSI_CTRL_0_CFG_LCD1_SLV (1<<4) | ||
1251 | #define DSI_CTRL_0_CFG_LCD1_EN (1<<0) | ||
1252 | |||
1253 | /* DSI_CTRL_1 0x0004 DSI Control Register 1 */ | ||
1254 | #define DSI_CTRL_1_CFG_EOTP (1<<8) | ||
1255 | #define DSI_CTRL_1_CFG_RSVD (2<<4) | ||
1256 | #define DSI_CTRL_1_CFG_LCD2_VCH_NO_MASK (3<<2) | ||
1257 | #define DSI_CTRL_1_CFG_LCD2_VCH_NO_SHIFT 2 | ||
1258 | #define DSI_CTRL_1_CFG_LCD1_VCH_NO_MASK (3<<0) | ||
1259 | #define DSI_CTRL_1_CFG_LCD1_VCH_NO_SHIFT 0 | ||
1260 | |||
1261 | /* DSI_LCD1_CTRL_1 0x0104 DSI Active Panel 1 Control Register 1 */ | ||
1262 | /* LCD 1 Vsync Reset Enable */ | ||
1263 | #define DSI_LCD1_CTRL_1_CFG_L1_VSYNC_RST_EN (1<<31) | ||
1264 | /* LCD 1 2K Pixel Buffer Mode Enable */ | ||
1265 | #define DSI_LCD1_CTRL_1_CFG_L1_M2K_EN (1<<30) | ||
1266 | /* Bit(s) DSI_LCD1_CTRL_1_RSRV_29_23 reserved */ | ||
1267 | /* Long Blanking Packet Enable */ | ||
1268 | #define DSI_LCD1_CTRL_1_CFG_L1_HLP_PKT_EN (1<<22) | ||
1269 | /* Extra Long Blanking Packet Enable */ | ||
1270 | #define DSI_LCD1_CTRL_1_CFG_L1_HEX_PKT_EN (1<<21) | ||
1271 | /* Front Porch Packet Enable */ | ||
1272 | #define DSI_LCD1_CTRL_1_CFG_L1_HFP_PKT_EN (1<<20) | ||
1273 | /* hact Packet Enable */ | ||
1274 | #define DSI_LCD1_CTRL_1_CFG_L1_HACT_PKT_EN (1<<19) | ||
1275 | /* Back Porch Packet Enable */ | ||
1276 | #define DSI_LCD1_CTRL_1_CFG_L1_HBP_PKT_EN (1<<18) | ||
1277 | /* hse Packet Enable */ | ||
1278 | #define DSI_LCD1_CTRL_1_CFG_L1_HSE_PKT_EN (1<<17) | ||
1279 | /* hsa Packet Enable */ | ||
1280 | #define DSI_LCD1_CTRL_1_CFG_L1_HSA_PKT_EN (1<<16) | ||
1281 | /* All Item Enable after Pixel Data */ | ||
1282 | #define DSI_LCD1_CTRL_1_CFG_L1_ALL_SLOT_EN (1<<15) | ||
1283 | /* Extra Long Packet Enable after Pixel Data */ | ||
1284 | #define DSI_LCD1_CTRL_1_CFG_L1_HEX_SLOT_EN (1<<14) | ||
1285 | /* Bit(s) DSI_LCD1_CTRL_1_RSRV_13_11 reserved */ | ||
1286 | /* Turn Around Bus at Last h Line */ | ||
1287 | #define DSI_LCD1_CTRL_1_CFG_L1_LAST_LINE_TURN (1<<10) | ||
1288 | /* Go to Low Power Every Frame */ | ||
1289 | #define DSI_LCD1_CTRL_1_CFG_L1_LPM_FRAME_EN (1<<9) | ||
1290 | /* Go to Low Power Every Line */ | ||
1291 | #define DSI_LCD1_CTRL_1_CFG_L1_LPM_LINE_EN (1<<8) | ||
1292 | /* Bit(s) DSI_LCD1_CTRL_1_RSRV_7_4 reserved */ | ||
1293 | /* DSI Transmission Mode for LCD 1 */ | ||
1294 | #define DSI_LCD1_CTRL_1_CFG_L1_BURST_MODE_SHIFT 2 | ||
1295 | #define DSI_LCD1_CTRL_1_CFG_L1_BURST_MODE_MASK (3<<2) | ||
1296 | /* LCD 1 Input Data RGB Mode for LCD 1 */ | ||
1297 | #define DSI_LCD2_CTRL_1_CFG_L1_RGB_TYPE_SHIFT 0 | ||
1298 | #define DSI_LCD2_CTRL_1_CFG_L1_RGB_TYPE_MASK (3<<2) | ||
1299 | |||
1300 | /* DSI_PHY_CTRL_2 0x0088 DPHY Control Register 2 */ | ||
1301 | /* Bit(s) DSI_PHY_CTRL_2_RSRV_31_12 reserved */ | ||
1302 | /* DPHY LP Receiver Enable */ | ||
1303 | #define DSI_PHY_CTRL_2_CFG_CSR_LANE_RESC_EN_MASK (0xf<<8) | ||
1304 | #define DSI_PHY_CTRL_2_CFG_CSR_LANE_RESC_EN_SHIFT 8 | ||
1305 | /* DPHY Data Lane Enable */ | ||
1306 | #define DSI_PHY_CTRL_2_CFG_CSR_LANE_EN_MASK (0xf<<4) | ||
1307 | #define DSI_PHY_CTRL_2_CFG_CSR_LANE_EN_SHIFT 4 | ||
1308 | /* DPHY Bus Turn Around */ | ||
1309 | #define DSI_PHY_CTRL_2_CFG_CSR_LANE_TURN_MASK (0xf) | ||
1310 | #define DSI_PHY_CTRL_2_CFG_CSR_LANE_TURN_SHIFT 0 | ||
1311 | |||
1312 | /* DSI_CPU_CMD_1 0x0024 DSI CPU Packet Command Register 1 */ | ||
1313 | /* Bit(s) DSI_CPU_CMD_1_RSRV_31_24 reserved */ | ||
1314 | /* LPDT TX Enable */ | ||
1315 | #define DSI_CPU_CMD_1_CFG_TXLP_LPDT_MASK (0xf<<20) | ||
1316 | #define DSI_CPU_CMD_1_CFG_TXLP_LPDT_SHIFT 20 | ||
1317 | /* ULPS TX Enable */ | ||
1318 | #define DSI_CPU_CMD_1_CFG_TXLP_ULPS_MASK (0xf<<16) | ||
1319 | #define DSI_CPU_CMD_1_CFG_TXLP_ULPS_SHIFT 16 | ||
1320 | /* Low Power TX Trigger Code */ | ||
1321 | #define DSI_CPU_CMD_1_CFG_TXLP_TRIGGER_CODE_MASK (0xffff) | ||
1322 | #define DSI_CPU_CMD_1_CFG_TXLP_TRIGGER_CODE_SHIFT 0 | ||
1323 | |||
1324 | /* DSI_PHY_TIME_0 0x00c0 DPHY Timing Control Register 0 */ | ||
1325 | /* Length of HS Exit Period in tx_clk_esc Cycles */ | ||
1326 | #define DSI_PHY_TIME_0_CFG_CSR_TIME_HS_EXIT_MASK (0xff<<24) | ||
1327 | #define DSI_PHY_TIME_0_CFG_CSR_TIME_HS_EXIT_SHIFT 24 | ||
1328 | /* DPHY HS Trail Period Length */ | ||
1329 | #define DSI_PHY_TIME_0_CFG_CSR_TIME_HS_TRAIL_MASK (0xff<<16) | ||
1330 | #define DSI_PHY_TIME_0_CFG_CSR_TIME_HS_TRAIL_SHIFT 16 | ||
1331 | /* DPHY HS Zero State Length */ | ||
1332 | #define DSI_PHY_TIME_0_CDG_CSR_TIME_HS_ZERO_MASK (0xff<<8) | ||
1333 | #define DSI_PHY_TIME_0_CDG_CSR_TIME_HS_ZERO_SHIFT 8 | ||
1334 | /* DPHY HS Prepare State Length */ | ||
1335 | #define DSI_PHY_TIME_0_CFG_CSR_TIME_HS_PREP_MASK (0xff) | ||
1336 | #define DSI_PHY_TIME_0_CFG_CSR_TIME_HS_PREP_SHIFT 0 | ||
1337 | |||
1338 | /* DSI_PHY_TIME_1 0x00c4 DPHY Timing Control Register 1 */ | ||
1339 | /* Time to Drive LP-00 by New Transmitter */ | ||
1340 | #define DSI_PHY_TIME_1_CFG_CSR_TIME_TA_GET_MASK (0xff<<24) | ||
1341 | #define DSI_PHY_TIME_1_CFG_CSR_TIME_TA_GET_SHIFT 24 | ||
1342 | /* Time to Drive LP-00 after Turn Request */ | ||
1343 | #define DSI_PHY_TIME_1_CFG_CSR_TIME_TA_GO_MASK (0xff<<16) | ||
1344 | #define DSI_PHY_TIME_1_CFG_CSR_TIME_TA_GO_SHIFT 16 | ||
1345 | /* DPHY HS Wakeup Period Length */ | ||
1346 | #define DSI_PHY_TIME_1_CFG_CSR_TIME_WAKEUP_MASK (0xffff) | ||
1347 | #define DSI_PHY_TIME_1_CFG_CSR_TIME_WAKEUP_SHIFT 0 | ||
1348 | |||
1349 | /* DSI_PHY_TIME_2 0x00c8 DPHY Timing Control Register 2 */ | ||
1350 | /* DPHY CLK Exit Period Length */ | ||
1351 | #define DSI_PHY_TIME_2_CFG_CSR_TIME_CK_EXIT_MASK (0xff<<24) | ||
1352 | #define DSI_PHY_TIME_2_CFG_CSR_TIME_CK_EXIT_SHIFT 24 | ||
1353 | /* DPHY CLK Trail Period Length */ | ||
1354 | #define DSI_PHY_TIME_2_CFG_CSR_TIME_CK_TRAIL_MASK (0xff<<16) | ||
1355 | #define DSI_PHY_TIME_2_CFG_CSR_TIME_CK_TRAIL_SHIFT 16 | ||
1356 | /* DPHY CLK Zero State Length */ | ||
1357 | #define DSI_PHY_TIME_2_CFG_CSR_TIME_CK_ZERO_MASK (0xff<<8) | ||
1358 | #define DSI_PHY_TIME_2_CFG_CSR_TIME_CK_ZERO_SHIFT 8 | ||
1359 | /* DPHY CLK LP Length */ | ||
1360 | #define DSI_PHY_TIME_2_CFG_CSR_TIME_CK_LPX_MASK (0xff) | ||
1361 | #define DSI_PHY_TIME_2_CFG_CSR_TIME_CK_LPX_SHIFT 0 | ||
1362 | |||
1363 | /* DSI_PHY_TIME_3 0x00cc DPHY Timing Control Register 3 */ | ||
1364 | /* Bit(s) DSI_PHY_TIME_3_RSRV_31_16 reserved */ | ||
1365 | /* DPHY LP Length */ | ||
1366 | #define DSI_PHY_TIME_3_CFG_CSR_TIME_LPX_MASK (0xff<<8) | ||
1367 | #define DSI_PHY_TIME_3_CFG_CSR_TIME_LPX_SHIFT 8 | ||
1368 | /* DPHY HS req to rdy Length */ | ||
1369 | #define DSI_PHY_TIME_3_CFG_CSR_TIME_REQRDY_MASK (0xff) | ||
1370 | #define DSI_PHY_TIME_3_CFG_CSR_TIME_REQRDY_SHIFT 0 | ||
1371 | |||
1372 | /* | ||
1373 | * DSI timings | ||
1374 | * PXA988 has diffrent ESC CLK with MMP2/MMP3 | ||
1375 | * it will be used in dsi_set_dphy() in pxa688_phy.c | ||
1376 | * as low power mode clock. | ||
1377 | */ | ||
1378 | #ifdef CONFIG_CPU_PXA988 | ||
1379 | #define DSI_ESC_CLK 52 /* Unit: Mhz */ | ||
1380 | #define DSI_ESC_CLK_T 19 /* Unit: ns */ | ||
1381 | #else | ||
1382 | #define DSI_ESC_CLK 66 /* Unit: Mhz */ | ||
1383 | #define DSI_ESC_CLK_T 15 /* Unit: ns */ | ||
1384 | #endif | ||
1385 | |||
1386 | /* LVDS */ | ||
1387 | /* LVDS_PHY_CTRL */ | ||
1388 | #define LVDS_PHY_CTL 0x2A4 | ||
1389 | #define LVDS_PLL_LOCK (1 << 31) | ||
1390 | #define LVDS_PHY_EXT_MASK (7 << 28) | ||
1391 | #define LVDS_PHY_EXT_SHIFT (28) | ||
1392 | #define LVDS_CLK_PHASE_MASK (0x7f << 16) | ||
1393 | #define LVDS_CLK_PHASE_SHIFT (16) | ||
1394 | #define LVDS_SSC_RESET_EXT (1 << 13) | ||
1395 | #define LVDS_SSC_MODE_DOWN_SPREAD (1 << 12) | ||
1396 | #define LVDS_SSC_EN (1 << 11) | ||
1397 | #define LVDS_PU_PLL (1 << 10) | ||
1398 | #define LVDS_PU_TX (1 << 9) | ||
1399 | #define LVDS_PU_IVREF (1 << 8) | ||
1400 | #define LVDS_CLK_SEL (1 << 7) | ||
1401 | #define LVDS_CLK_SEL_LVDS_PCLK (1 << 7) | ||
1402 | #define LVDS_PD_CH_MASK (0x3f << 1) | ||
1403 | #define LVDS_PD_CH(ch) ((ch) << 1) | ||
1404 | #define LVDS_RST (1 << 0) | ||
1405 | |||
1406 | #define LVDS_PHY_CTL_EXT 0x2A8 | ||
1407 | |||
1408 | /* LVDS_PHY_CTRL_EXT1 */ | ||
1409 | #define LVDS_SSC_RNGE_MASK (0x7ff << 16) | ||
1410 | #define LVDS_SSC_RNGE_SHIFT (16) | ||
1411 | #define LVDS_RESERVE_IN_MASK (0xf << 12) | ||
1412 | #define LVDS_RESERVE_IN_SHIFT (12) | ||
1413 | #define LVDS_TEST_MON_MASK (0x7 << 8) | ||
1414 | #define LVDS_TEST_MON_SHIFT (8) | ||
1415 | #define LVDS_POL_SWAP_MASK (0x3f << 0) | ||
1416 | #define LVDS_POL_SWAP_SHIFT (0) | ||
1417 | |||
1418 | /* LVDS_PHY_CTRL_EXT2 */ | ||
1419 | #define LVDS_TX_DIF_AMP_MASK (0xf << 24) | ||
1420 | #define LVDS_TX_DIF_AMP_SHIFT (24) | ||
1421 | #define LVDS_TX_DIF_CM_MASK (0x3 << 22) | ||
1422 | #define LVDS_TX_DIF_CM_SHIFT (22) | ||
1423 | #define LVDS_SELLV_TXCLK_MASK (0x1f << 16) | ||
1424 | #define LVDS_SELLV_TXCLK_SHIFT (16) | ||
1425 | #define LVDS_TX_CMFB_EN (0x1 << 15) | ||
1426 | #define LVDS_TX_TERM_EN (0x1 << 14) | ||
1427 | #define LVDS_SELLV_TXDATA_MASK (0x1f << 8) | ||
1428 | #define LVDS_SELLV_TXDATA_SHIFT (8) | ||
1429 | #define LVDS_SELLV_OP7_MASK (0x3 << 6) | ||
1430 | #define LVDS_SELLV_OP7_SHIFT (6) | ||
1431 | #define LVDS_SELLV_OP6_MASK (0x3 << 4) | ||
1432 | #define LVDS_SELLV_OP6_SHIFT (4) | ||
1433 | #define LVDS_SELLV_OP9_MASK (0x3 << 2) | ||
1434 | #define LVDS_SELLV_OP9_SHIFT (2) | ||
1435 | #define LVDS_STRESSTST_EN (0x1 << 0) | ||
1436 | |||
1437 | /* LVDS_PHY_CTRL_EXT3 */ | ||
1438 | #define LVDS_KVCO_MASK (0xf << 28) | ||
1439 | #define LVDS_KVCO_SHIFT (28) | ||
1440 | #define LVDS_CTUNE_MASK (0x3 << 26) | ||
1441 | #define LVDS_CTUNE_SHIFT (26) | ||
1442 | #define LVDS_VREG_IVREF_MASK (0x3 << 24) | ||
1443 | #define LVDS_VREG_IVREF_SHIFT (24) | ||
1444 | #define LVDS_VDDL_MASK (0xf << 20) | ||
1445 | #define LVDS_VDDL_SHIFT (20) | ||
1446 | #define LVDS_VDDM_MASK (0x3 << 18) | ||
1447 | #define LVDS_VDDM_SHIFT (18) | ||
1448 | #define LVDS_FBDIV_MASK (0xf << 8) | ||
1449 | #define LVDS_FBDIV_SHIFT (8) | ||
1450 | #define LVDS_REFDIV_MASK (0x7f << 0) | ||
1451 | #define LVDS_REFDIV_SHIFT (0) | ||
1452 | |||
1453 | /* LVDS_PHY_CTRL_EXT4 */ | ||
1454 | #define LVDS_SSC_FREQ_DIV_MASK (0xffff << 16) | ||
1455 | #define LVDS_SSC_FREQ_DIV_SHIFT (16) | ||
1456 | #define LVDS_INTPI_MASK (0xf << 12) | ||
1457 | #define LVDS_INTPI_SHIFT (12) | ||
1458 | #define LVDS_VCODIV_SEL_SE_MASK (0xf << 8) | ||
1459 | #define LVDS_VCODIV_SEL_SE_SHIFT (8) | ||
1460 | #define LVDS_RESET_INTP_EXT (0x1 << 7) | ||
1461 | #define LVDS_VCO_VRNG_MASK (0x7 << 4) | ||
1462 | #define LVDS_VCO_VRNG_SHIFT (4) | ||
1463 | #define LVDS_PI_EN (0x1 << 3) | ||
1464 | #define LVDS_ICP_MASK (0x7 << 0) | ||
1465 | #define LVDS_ICP_SHIFT (0) | ||
1466 | |||
1467 | /* LVDS_PHY_CTRL_EXT5 */ | ||
1468 | #define LVDS_FREQ_OFFSET_MASK (0x1ffff << 15) | ||
1469 | #define LVDS_FREQ_OFFSET_SHIFT (15) | ||
1470 | #define LVDS_FREQ_OFFSET_VALID (0x1 << 2) | ||
1471 | #define LVDS_FREQ_OFFSET_MODE_CK_DIV4_OUT (0x1 << 1) | ||
1472 | #define LVDS_FREQ_OFFSET_MODE_EN (0x1 << 0) | ||
1473 | |||
1474 | /* VDMA */ | ||
1475 | struct vdma_ch_regs { | ||
1476 | #define VDMA_DC_SADDR_1 0x320 | ||
1477 | #define VDMA_DC_SADDR_2 0x3A0 | ||
1478 | #define VDMA_DC_SZ_1 0x324 | ||
1479 | #define VDMA_DC_SZ_2 0x3A4 | ||
1480 | #define VDMA_CTRL_1 0x328 | ||
1481 | #define VDMA_CTRL_2 0x3A8 | ||
1482 | #define VDMA_SRC_SZ_1 0x32C | ||
1483 | #define VDMA_SRC_SZ_2 0x3AC | ||
1484 | #define VDMA_SA_1 0x330 | ||
1485 | #define VDMA_SA_2 0x3B0 | ||
1486 | #define VDMA_DA_1 0x334 | ||
1487 | #define VDMA_DA_2 0x3B4 | ||
1488 | #define VDMA_SZ_1 0x338 | ||
1489 | #define VDMA_SZ_2 0x3B8 | ||
1490 | u32 dc_saddr; | ||
1491 | u32 dc_size; | ||
1492 | u32 ctrl; | ||
1493 | u32 src_size; | ||
1494 | u32 src_addr; | ||
1495 | u32 dst_addr; | ||
1496 | u32 dst_size; | ||
1497 | #define VDMA_PITCH_1 0x33C | ||
1498 | #define VDMA_PITCH_2 0x3BC | ||
1499 | #define VDMA_ROT_CTRL_1 0x340 | ||
1500 | #define VDMA_ROT_CTRL_2 0x3C0 | ||
1501 | #define VDMA_RAM_CTRL0_1 0x344 | ||
1502 | #define VDMA_RAM_CTRL0_2 0x3C4 | ||
1503 | #define VDMA_RAM_CTRL1_1 0x348 | ||
1504 | #define VDMA_RAM_CTRL1_2 0x3C8 | ||
1505 | u32 pitch; | ||
1506 | u32 rot_ctrl; | ||
1507 | u32 ram_ctrl0; | ||
1508 | u32 ram_ctrl1; | ||
1509 | |||
1510 | }; | ||
1511 | struct vdma_regs { | ||
1512 | #define VDMA_ARBR_CTRL 0x300 | ||
1513 | #define VDMA_IRQR 0x304 | ||
1514 | #define VDMA_IRQM 0x308 | ||
1515 | #define VDMA_IRQS 0x30C | ||
1516 | #define VDMA_MDMA_ARBR_CTRL 0x310 | ||
1517 | u32 arbr_ctr; | ||
1518 | u32 irq_raw; | ||
1519 | u32 irq_mask; | ||
1520 | u32 irq_status; | ||
1521 | u32 mdma_arbr_ctrl; | ||
1522 | u32 reserved[3]; | ||
1523 | |||
1524 | struct vdma_ch_regs ch1; | ||
1525 | u32 reserved2[21]; | ||
1526 | struct vdma_ch_regs ch2; | ||
1527 | }; | ||
1528 | |||
1529 | /* CMU */ | ||
1530 | #define CMU_PIP_DE_H_CFG 0x0008 | ||
1531 | #define CMU_PRI1_H_CFG 0x000C | ||
1532 | #define CMU_PRI2_H_CFG 0x0010 | ||
1533 | #define CMU_ACE_MAIN_DE1_H_CFG 0x0014 | ||
1534 | #define CMU_ACE_MAIN_DE2_H_CFG 0x0018 | ||
1535 | #define CMU_ACE_PIP_DE1_H_CFG 0x001C | ||
1536 | #define CMU_ACE_PIP_DE2_H_CFG 0x0020 | ||
1537 | #define CMU_PIP_DE_V_CFG 0x0024 | ||
1538 | #define CMU_PRI_V_CFG 0x0028 | ||
1539 | #define CMU_ACE_MAIN_DE_V_CFG 0x002C | ||
1540 | #define CMU_ACE_PIP_DE_V_CFG 0x0030 | ||
1541 | #define CMU_BAR_0_CFG 0x0034 | ||
1542 | #define CMU_BAR_1_CFG 0x0038 | ||
1543 | #define CMU_BAR_2_CFG 0x003C | ||
1544 | #define CMU_BAR_3_CFG 0x0040 | ||
1545 | #define CMU_BAR_4_CFG 0x0044 | ||
1546 | #define CMU_BAR_5_CFG 0x0048 | ||
1547 | #define CMU_BAR_6_CFG 0x004C | ||
1548 | #define CMU_BAR_7_CFG 0x0050 | ||
1549 | #define CMU_BAR_8_CFG 0x0054 | ||
1550 | #define CMU_BAR_9_CFG 0x0058 | ||
1551 | #define CMU_BAR_10_CFG 0x005C | ||
1552 | #define CMU_BAR_11_CFG 0x0060 | ||
1553 | #define CMU_BAR_12_CFG 0x0064 | ||
1554 | #define CMU_BAR_13_CFG 0x0068 | ||
1555 | #define CMU_BAR_14_CFG 0x006C | ||
1556 | #define CMU_BAR_15_CFG 0x0070 | ||
1557 | #define CMU_BAR_CTRL 0x0074 | ||
1558 | #define PATTERN_TOTAL 0x0078 | ||
1559 | #define PATTERN_ACTIVE 0x007C | ||
1560 | #define PATTERN_FRONT_PORCH 0x0080 | ||
1561 | #define PATTERN_BACK_PORCH 0x0084 | ||
1562 | #define CMU_CLK_CTRL 0x0088 | ||
1563 | |||
1564 | #define CMU_ICSC_M_C0_L 0x0900 | ||
1565 | #define CMU_ICSC_M_C0_H 0x0901 | ||
1566 | #define CMU_ICSC_M_C1_L 0x0902 | ||
1567 | #define CMU_ICSC_M_C1_H 0x0903 | ||
1568 | #define CMU_ICSC_M_C2_L 0x0904 | ||
1569 | #define CMU_ICSC_M_C2_H 0x0905 | ||
1570 | #define CMU_ICSC_M_C3_L 0x0906 | ||
1571 | #define CMU_ICSC_M_C3_H 0x0907 | ||
1572 | #define CMU_ICSC_M_C4_L 0x0908 | ||
1573 | #define CMU_ICSC_M_C4_H 0x0909 | ||
1574 | #define CMU_ICSC_M_C5_L 0x090A | ||
1575 | #define CMU_ICSC_M_C5_H 0x090B | ||
1576 | #define CMU_ICSC_M_C6_L 0x090C | ||
1577 | #define CMU_ICSC_M_C6_H 0x090D | ||
1578 | #define CMU_ICSC_M_C7_L 0x090E | ||
1579 | #define CMU_ICSC_M_C7_H 0x090F | ||
1580 | #define CMU_ICSC_M_C8_L 0x0910 | ||
1581 | #define CMU_ICSC_M_C8_H 0x0911 | ||
1582 | #define CMU_ICSC_M_O1_0 0x0914 | ||
1583 | #define CMU_ICSC_M_O1_1 0x0915 | ||
1584 | #define CMU_ICSC_M_O1_2 0x0916 | ||
1585 | #define CMU_ICSC_M_O2_0 0x0918 | ||
1586 | #define CMU_ICSC_M_O2_1 0x0919 | ||
1587 | #define CMU_ICSC_M_O2_2 0x091A | ||
1588 | #define CMU_ICSC_M_O3_0 0x091C | ||
1589 | #define CMU_ICSC_M_O3_1 0x091D | ||
1590 | #define CMU_ICSC_M_O3_2 0x091E | ||
1591 | #define CMU_ICSC_P_C0_L 0x0920 | ||
1592 | #define CMU_ICSC_P_C0_H 0x0921 | ||
1593 | #define CMU_ICSC_P_C1_L 0x0922 | ||
1594 | #define CMU_ICSC_P_C1_H 0x0923 | ||
1595 | #define CMU_ICSC_P_C2_L 0x0924 | ||
1596 | #define CMU_ICSC_P_C2_H 0x0925 | ||
1597 | #define CMU_ICSC_P_C3_L 0x0926 | ||
1598 | #define CMU_ICSC_P_C3_H 0x0927 | ||
1599 | #define CMU_ICSC_P_C4_L 0x0928 | ||
1600 | #define CMU_ICSC_P_C4_H 0x0929 | ||
1601 | #define CMU_ICSC_P_C5_L 0x092A | ||
1602 | #define CMU_ICSC_P_C5_H 0x092B | ||
1603 | #define CMU_ICSC_P_C6_L 0x092C | ||
1604 | #define CMU_ICSC_P_C6_H 0x092D | ||
1605 | #define CMU_ICSC_P_C7_L 0x092E | ||
1606 | #define CMU_ICSC_P_C7_H 0x092F | ||
1607 | #define CMU_ICSC_P_C8_L 0x0930 | ||
1608 | #define CMU_ICSC_P_C8_H 0x0931 | ||
1609 | #define CMU_ICSC_P_O1_0 0x0934 | ||
1610 | #define CMU_ICSC_P_O1_1 0x0935 | ||
1611 | #define CMU_ICSC_P_O1_2 0x0936 | ||
1612 | #define CMU_ICSC_P_O2_0 0x0938 | ||
1613 | #define CMU_ICSC_P_O2_1 0x0939 | ||
1614 | #define CMU_ICSC_P_O2_2 0x093A | ||
1615 | #define CMU_ICSC_P_O3_0 0x093C | ||
1616 | #define CMU_ICSC_P_O3_1 0x093D | ||
1617 | #define CMU_ICSC_P_O3_2 0x093E | ||
1618 | #define CMU_BR_M_EN 0x0940 | ||
1619 | #define CMU_BR_M_TH1_L 0x0942 | ||
1620 | #define CMU_BR_M_TH1_H 0x0943 | ||
1621 | #define CMU_BR_M_TH2_L 0x0944 | ||
1622 | #define CMU_BR_M_TH2_H 0x0945 | ||
1623 | #define CMU_ACE_M_EN 0x0950 | ||
1624 | #define CMU_ACE_M_WFG1 0x0951 | ||
1625 | #define CMU_ACE_M_WFG2 0x0952 | ||
1626 | #define CMU_ACE_M_WFG3 0x0953 | ||
1627 | #define CMU_ACE_M_TH0 0x0954 | ||
1628 | #define CMU_ACE_M_TH1 0x0955 | ||
1629 | #define CMU_ACE_M_TH2 0x0956 | ||
1630 | #define CMU_ACE_M_TH3 0x0957 | ||
1631 | #define CMU_ACE_M_TH4 0x0958 | ||
1632 | #define CMU_ACE_M_TH5 0x0959 | ||
1633 | #define CMU_ACE_M_OP0_L 0x095A | ||
1634 | #define CMU_ACE_M_OP0_H 0x095B | ||
1635 | #define CMU_ACE_M_OP5_L 0x095C | ||
1636 | #define CMU_ACE_M_OP5_H 0x095D | ||
1637 | #define CMU_ACE_M_GB2 0x095E | ||
1638 | #define CMU_ACE_M_GB3 0x095F | ||
1639 | #define CMU_ACE_M_MS1 0x0960 | ||
1640 | #define CMU_ACE_M_MS2 0x0961 | ||
1641 | #define CMU_ACE_M_MS3 0x0962 | ||
1642 | #define CMU_BR_P_EN 0x0970 | ||
1643 | #define CMU_BR_P_TH1_L 0x0972 | ||
1644 | #define CMU_BR_P_TH1_H 0x0973 | ||
1645 | #define CMU_BR_P_TH2_L 0x0974 | ||
1646 | #define CMU_BR_P_TH2_H 0x0975 | ||
1647 | #define CMU_ACE_P_EN 0x0980 | ||
1648 | #define CMU_ACE_P_WFG1 0x0981 | ||
1649 | #define CMU_ACE_P_WFG2 0x0982 | ||
1650 | #define CMU_ACE_P_WFG3 0x0983 | ||
1651 | #define CMU_ACE_P_TH0 0x0984 | ||
1652 | #define CMU_ACE_P_TH1 0x0985 | ||
1653 | #define CMU_ACE_P_TH2 0x0986 | ||
1654 | #define CMU_ACE_P_TH3 0x0987 | ||
1655 | #define CMU_ACE_P_TH4 0x0988 | ||
1656 | #define CMU_ACE_P_TH5 0x0989 | ||
1657 | #define CMU_ACE_P_OP0_L 0x098A | ||
1658 | #define CMU_ACE_P_OP0_H 0x098B | ||
1659 | #define CMU_ACE_P_OP5_L 0x098C | ||
1660 | #define CMU_ACE_P_OP5_H 0x098D | ||
1661 | #define CMU_ACE_P_GB2 0x098E | ||
1662 | #define CMU_ACE_P_GB3 0x098F | ||
1663 | #define CMU_ACE_P_MS1 0x0990 | ||
1664 | #define CMU_ACE_P_MS2 0x0991 | ||
1665 | #define CMU_ACE_P_MS3 0x0992 | ||
1666 | #define CMU_FTDC_M_EN 0x09A0 | ||
1667 | #define CMU_FTDC_P_EN 0x09A1 | ||
1668 | #define CMU_FTDC_INLOW_L 0x09A2 | ||
1669 | #define CMU_FTDC_INLOW_H 0x09A3 | ||
1670 | #define CMU_FTDC_INHIGH_L 0x09A4 | ||
1671 | #define CMU_FTDC_INHIGH_H 0x09A5 | ||
1672 | #define CMU_FTDC_OUTLOW_L 0x09A6 | ||
1673 | #define CMU_FTDC_OUTLOW_H 0x09A7 | ||
1674 | #define CMU_FTDC_OUTHIGH_L 0x09A8 | ||
1675 | #define CMU_FTDC_OUTHIGH_H 0x09A9 | ||
1676 | #define CMU_FTDC_YLOW 0x09AA | ||
1677 | #define CMU_FTDC_YHIGH 0x09AB | ||
1678 | #define CMU_FTDC_CH1 0x09AC | ||
1679 | #define CMU_FTDC_CH2_L 0x09AE | ||
1680 | #define CMU_FTDC_CH2_H 0x09AF | ||
1681 | #define CMU_FTDC_CH3_L 0x09B0 | ||
1682 | #define CMU_FTDC_CH3_H 0x09B1 | ||
1683 | #define CMU_FTDC_1_C00_6 0x09B2 | ||
1684 | #define CMU_FTDC_1_C01_6 0x09B8 | ||
1685 | #define CMU_FTDC_1_C11_6 0x09BE | ||
1686 | #define CMU_FTDC_1_C10_6 0x09C4 | ||
1687 | #define CMU_FTDC_1_OFF00_6 0x09CA | ||
1688 | #define CMU_FTDC_1_OFF10_6 0x09D0 | ||
1689 | #define CMU_HS_M_EN 0x0A00 | ||
1690 | #define CMU_HS_M_AX1_L 0x0A02 | ||
1691 | #define CMU_HS_M_AX1_H 0x0A03 | ||
1692 | #define CMU_HS_M_AX2_L 0x0A04 | ||
1693 | #define CMU_HS_M_AX2_H 0x0A05 | ||
1694 | #define CMU_HS_M_AX3_L 0x0A06 | ||
1695 | #define CMU_HS_M_AX3_H 0x0A07 | ||
1696 | #define CMU_HS_M_AX4_L 0x0A08 | ||
1697 | #define CMU_HS_M_AX4_H 0x0A09 | ||
1698 | #define CMU_HS_M_AX5_L 0x0A0A | ||
1699 | #define CMU_HS_M_AX5_H 0x0A0B | ||
1700 | #define CMU_HS_M_AX6_L 0x0A0C | ||
1701 | #define CMU_HS_M_AX6_H 0x0A0D | ||
1702 | #define CMU_HS_M_AX7_L 0x0A0E | ||
1703 | #define CMU_HS_M_AX7_H 0x0A0F | ||
1704 | #define CMU_HS_M_AX8_L 0x0A10 | ||
1705 | #define CMU_HS_M_AX8_H 0x0A11 | ||
1706 | #define CMU_HS_M_AX9_L 0x0A12 | ||
1707 | #define CMU_HS_M_AX9_H 0x0A13 | ||
1708 | #define CMU_HS_M_AX10_L 0x0A14 | ||
1709 | #define CMU_HS_M_AX10_H 0x0A15 | ||
1710 | #define CMU_HS_M_AX11_L 0x0A16 | ||
1711 | #define CMU_HS_M_AX11_H 0x0A17 | ||
1712 | #define CMU_HS_M_AX12_L 0x0A18 | ||
1713 | #define CMU_HS_M_AX12_H 0x0A19 | ||
1714 | #define CMU_HS_M_AX13_L 0x0A1A | ||
1715 | #define CMU_HS_M_AX13_H 0x0A1B | ||
1716 | #define CMU_HS_M_AX14_L 0x0A1C | ||
1717 | #define CMU_HS_M_AX14_H 0x0A1D | ||
1718 | #define CMU_HS_M_H1_H14 0x0A1E | ||
1719 | #define CMU_HS_M_S1_S14 0x0A2C | ||
1720 | #define CMU_HS_M_GL 0x0A3A | ||
1721 | #define CMU_HS_M_MAXSAT_RGB_Y_L 0x0A3C | ||
1722 | #define CMU_HS_M_MAXSAT_RGB_Y_H 0x0A3D | ||
1723 | #define CMU_HS_M_MAXSAT_RCR_L 0x0A3E | ||
1724 | #define CMU_HS_M_MAXSAT_RCR_H 0x0A3F | ||
1725 | #define CMU_HS_M_MAXSAT_RCB_L 0x0A40 | ||
1726 | #define CMU_HS_M_MAXSAT_RCB_H 0x0A41 | ||
1727 | #define CMU_HS_M_MAXSAT_GCR_L 0x0A42 | ||
1728 | #define CMU_HS_M_MAXSAT_GCR_H 0x0A43 | ||
1729 | #define CMU_HS_M_MAXSAT_GCB_L 0x0A44 | ||
1730 | #define CMU_HS_M_MAXSAT_GCB_H 0x0A45 | ||
1731 | #define CMU_HS_M_MAXSAT_BCR_L 0x0A46 | ||
1732 | #define CMU_HS_M_MAXSAT_BCR_H 0x0A47 | ||
1733 | #define CMU_HS_M_MAXSAT_BCB_L 0x0A48 | ||
1734 | #define CMU_HS_M_MAXSAT_BCB_H 0x0A49 | ||
1735 | #define CMU_HS_M_ROFF_L 0x0A4A | ||
1736 | #define CMU_HS_M_ROFF_H 0x0A4B | ||
1737 | #define CMU_HS_M_GOFF_L 0x0A4C | ||
1738 | #define CMU_HS_M_GOFF_H 0x0A4D | ||
1739 | #define CMU_HS_M_BOFF_L 0x0A4E | ||
1740 | #define CMU_HS_M_BOFF_H 0x0A4F | ||
1741 | #define CMU_HS_P_EN 0x0A50 | ||
1742 | #define CMU_HS_P_AX1_L 0x0A52 | ||
1743 | #define CMU_HS_P_AX1_H 0x0A53 | ||
1744 | #define CMU_HS_P_AX2_L 0x0A54 | ||
1745 | #define CMU_HS_P_AX2_H 0x0A55 | ||
1746 | #define CMU_HS_P_AX3_L 0x0A56 | ||
1747 | #define CMU_HS_P_AX3_H 0x0A57 | ||
1748 | #define CMU_HS_P_AX4_L 0x0A58 | ||
1749 | #define CMU_HS_P_AX4_H 0x0A59 | ||
1750 | #define CMU_HS_P_AX5_L 0x0A5A | ||
1751 | #define CMU_HS_P_AX5_H 0x0A5B | ||
1752 | #define CMU_HS_P_AX6_L 0x0A5C | ||
1753 | #define CMU_HS_P_AX6_H 0x0A5D | ||
1754 | #define CMU_HS_P_AX7_L 0x0A5E | ||
1755 | #define CMU_HS_P_AX7_H 0x0A5F | ||
1756 | #define CMU_HS_P_AX8_L 0x0A60 | ||
1757 | #define CMU_HS_P_AX8_H 0x0A61 | ||
1758 | #define CMU_HS_P_AX9_L 0x0A62 | ||
1759 | #define CMU_HS_P_AX9_H 0x0A63 | ||
1760 | #define CMU_HS_P_AX10_L 0x0A64 | ||
1761 | #define CMU_HS_P_AX10_H 0x0A65 | ||
1762 | #define CMU_HS_P_AX11_L 0x0A66 | ||
1763 | #define CMU_HS_P_AX11_H 0x0A67 | ||
1764 | #define CMU_HS_P_AX12_L 0x0A68 | ||
1765 | #define CMU_HS_P_AX12_H 0x0A69 | ||
1766 | #define CMU_HS_P_AX13_L 0x0A6A | ||
1767 | #define CMU_HS_P_AX13_H 0x0A6B | ||
1768 | #define CMU_HS_P_AX14_L 0x0A6C | ||
1769 | #define CMU_HS_P_AX14_H 0x0A6D | ||
1770 | #define CMU_HS_P_H1_H14 0x0A6E | ||
1771 | #define CMU_HS_P_S1_S14 0x0A7C | ||
1772 | #define CMU_HS_P_GL 0x0A8A | ||
1773 | #define CMU_HS_P_MAXSAT_RGB_Y_L 0x0A8C | ||
1774 | #define CMU_HS_P_MAXSAT_RGB_Y_H 0x0A8D | ||
1775 | #define CMU_HS_P_MAXSAT_RCR_L 0x0A8E | ||
1776 | #define CMU_HS_P_MAXSAT_RCR_H 0x0A8F | ||
1777 | #define CMU_HS_P_MAXSAT_RCB_L 0x0A90 | ||
1778 | #define CMU_HS_P_MAXSAT_RCB_H 0x0A91 | ||
1779 | #define CMU_HS_P_MAXSAT_GCR_L 0x0A92 | ||
1780 | #define CMU_HS_P_MAXSAT_GCR_H 0x0A93 | ||
1781 | #define CMU_HS_P_MAXSAT_GCB_L 0x0A94 | ||
1782 | #define CMU_HS_P_MAXSAT_GCB_H 0x0A95 | ||
1783 | #define CMU_HS_P_MAXSAT_BCR_L 0x0A96 | ||
1784 | #define CMU_HS_P_MAXSAT_BCR_H 0x0A97 | ||
1785 | #define CMU_HS_P_MAXSAT_BCB_L 0x0A98 | ||
1786 | #define CMU_HS_P_MAXSAT_BCB_H 0x0A99 | ||
1787 | #define CMU_HS_P_ROFF_L 0x0A9A | ||
1788 | #define CMU_HS_P_ROFF_H 0x0A9B | ||
1789 | #define CMU_HS_P_GOFF_L 0x0A9C | ||
1790 | #define CMU_HS_P_GOFF_H 0x0A9D | ||
1791 | #define CMU_HS_P_BOFF_L 0x0A9E | ||
1792 | #define CMU_HS_P_BOFF_H 0x0A9F | ||
1793 | #define CMU_GLCSC_M_C0_L 0x0AA0 | ||
1794 | #define CMU_GLCSC_M_C0_H 0x0AA1 | ||
1795 | #define CMU_GLCSC_M_C1_L 0x0AA2 | ||
1796 | #define CMU_GLCSC_M_C1_H 0x0AA3 | ||
1797 | #define CMU_GLCSC_M_C2_L 0x0AA4 | ||
1798 | #define CMU_GLCSC_M_C2_H 0x0AA5 | ||
1799 | #define CMU_GLCSC_M_C3_L 0x0AA6 | ||
1800 | #define CMU_GLCSC_M_C3_H 0x0AA7 | ||
1801 | #define CMU_GLCSC_M_C4_L 0x0AA8 | ||
1802 | #define CMU_GLCSC_M_C4_H 0x0AA9 | ||
1803 | #define CMU_GLCSC_M_C5_L 0x0AAA | ||
1804 | #define CMU_GLCSC_M_C5_H 0x0AAB | ||
1805 | #define CMU_GLCSC_M_C6_L 0x0AAC | ||
1806 | #define CMU_GLCSC_M_C6_H 0x0AAD | ||
1807 | #define CMU_GLCSC_M_C7_L 0x0AAE | ||
1808 | #define CMU_GLCSC_M_C7_H 0x0AAF | ||
1809 | #define CMU_GLCSC_M_C8_L 0x0AB0 | ||
1810 | #define CMU_GLCSC_M_C8_H 0x0AB1 | ||
1811 | #define CMU_GLCSC_M_O1_1 0x0AB4 | ||
1812 | #define CMU_GLCSC_M_O1_2 0x0AB5 | ||
1813 | #define CMU_GLCSC_M_O1_3 0x0AB6 | ||
1814 | #define CMU_GLCSC_M_O2_1 0x0AB8 | ||
1815 | #define CMU_GLCSC_M_O2_2 0x0AB9 | ||
1816 | #define CMU_GLCSC_M_O2_3 0x0ABA | ||
1817 | #define CMU_GLCSC_M_O3_1 0x0ABC | ||
1818 | #define CMU_GLCSC_M_O3_2 0x0ABD | ||
1819 | #define CMU_GLCSC_M_O3_3 0x0ABE | ||
1820 | #define CMU_GLCSC_P_C0_L 0x0AC0 | ||
1821 | #define CMU_GLCSC_P_C0_H 0x0AC1 | ||
1822 | #define CMU_GLCSC_P_C1_L 0x0AC2 | ||
1823 | #define CMU_GLCSC_P_C1_H 0x0AC3 | ||
1824 | #define CMU_GLCSC_P_C2_L 0x0AC4 | ||
1825 | #define CMU_GLCSC_P_C2_H 0x0AC5 | ||
1826 | #define CMU_GLCSC_P_C3_L 0x0AC6 | ||
1827 | #define CMU_GLCSC_P_C3_H 0x0AC7 | ||
1828 | #define CMU_GLCSC_P_C4_L 0x0AC8 | ||
1829 | #define CMU_GLCSC_P_C4_H 0x0AC9 | ||
1830 | #define CMU_GLCSC_P_C5_L 0x0ACA | ||
1831 | #define CMU_GLCSC_P_C5_H 0x0ACB | ||
1832 | #define CMU_GLCSC_P_C6_L 0x0ACC | ||
1833 | #define CMU_GLCSC_P_C6_H 0x0ACD | ||
1834 | #define CMU_GLCSC_P_C7_L 0x0ACE | ||
1835 | #define CMU_GLCSC_P_C7_H 0x0ACF | ||
1836 | #define CMU_GLCSC_P_C8_L 0x0AD0 | ||
1837 | #define CMU_GLCSC_P_C8_H 0x0AD1 | ||
1838 | #define CMU_GLCSC_P_O1_1 0x0AD4 | ||
1839 | #define CMU_GLCSC_P_O1_2 0x0AD5 | ||
1840 | #define CMU_GLCSC_P_O1_3 0x0AD6 | ||
1841 | #define CMU_GLCSC_P_O2_1 0x0AD8 | ||
1842 | #define CMU_GLCSC_P_O2_2 0x0AD9 | ||
1843 | #define CMU_GLCSC_P_O2_3 0x0ADA | ||
1844 | #define CMU_GLCSC_P_O3_1 0x0ADC | ||
1845 | #define CMU_GLCSC_P_O3_2 0x0ADD | ||
1846 | #define CMU_GLCSC_P_O3_3 0x0ADE | ||
1847 | #define CMU_PIXVAL_M_EN 0x0AE0 | ||
1848 | #define CMU_PIXVAL_P_EN 0x0AE1 | ||
1849 | |||
1850 | #define CMU_CLK_CTRL_TCLK 0x0 | ||
1851 | #define CMU_CLK_CTRL_SCLK 0x2 | ||
1852 | #define CMU_CLK_CTRL_MSK 0x2 | ||
1853 | #define CMU_CLK_CTRL_ENABLE 0x1 | ||
1854 | |||
1855 | #define LCD_TOP_CTRL_TV 0x2 | ||
1856 | #define LCD_TOP_CTRL_PN 0x0 | ||
1857 | #define LCD_TOP_CTRL_SEL_MSK 0x2 | ||
1858 | #define LCD_IO_CMU_IN_SEL_MSK (0x3 << 20) | ||
1859 | #define LCD_IO_CMU_IN_SEL_TV 0 | ||
1860 | #define LCD_IO_CMU_IN_SEL_PN 1 | ||
1861 | #define LCD_IO_CMU_IN_SEL_PN2 2 | ||
1862 | #define LCD_IO_TV_OUT_SEL_MSK (0x3 << 26) | ||
1863 | #define LCD_IO_PN_OUT_SEL_MSK (0x3 << 24) | ||
1864 | #define LCD_IO_PN2_OUT_SEL_MSK (0x3 << 28) | ||
1865 | #define LCD_IO_TV_OUT_SEL_NON 3 | ||
1866 | #define LCD_IO_PN_OUT_SEL_NON 3 | ||
1867 | #define LCD_IO_PN2_OUT_SEL_NON 3 | ||
1868 | #define LCD_TOP_CTRL_CMU_ENABLE 0x1 | ||
1869 | #define LCD_IO_OVERL_MSK 0xC00000 | ||
1870 | #define LCD_IO_OVERL_TV 0x0 | ||
1871 | #define LCD_IO_OVERL_LCD1 0x400000 | ||
1872 | #define LCD_IO_OVERL_LCD2 0xC00000 | ||
1873 | #define HINVERT_MSK 0x4 | ||
1874 | #define VINVERT_MSK 0x8 | ||
1875 | #define HINVERT_LEN 0x2 | ||
1876 | #define VINVERT_LEN 0x3 | ||
1877 | |||
1878 | #define CMU_CTRL 0x88 | ||
1879 | #define CMU_CTRL_A0_MSK 0x6 | ||
1880 | #define CMU_CTRL_A0_TV 0x0 | ||
1881 | #define CMU_CTRL_A0_LCD1 0x1 | ||
1882 | #define CMU_CTRL_A0_LCD2 0x2 | ||
1883 | #define CMU_CTRL_A0_HDMI 0x3 | ||
1884 | |||
1885 | #define ICR_DRV_ROUTE_OFF 0x0 | ||
1886 | #define ICR_DRV_ROUTE_TV 0x1 | ||
1887 | #define ICR_DRV_ROUTE_LCD1 0x2 | ||
1888 | #define ICR_DRV_ROUTE_LCD2 0x3 | ||
1889 | |||
1890 | enum { | ||
1891 | PATH_PN = 0, | ||
1892 | PATH_TV, | ||
1893 | PATH_P2, | ||
1894 | }; | ||
1895 | |||
1896 | /* | ||
1897 | * mmp path describes part of mmp path related info: | ||
1898 | * which is hiden in display driver and not exported to buffer driver | ||
1899 | */ | ||
1900 | struct mmphw_ctrl; | ||
1901 | struct mmphw_path_plat { | ||
1902 | int id; | ||
1903 | struct mmphw_ctrl *ctrl; | ||
1904 | struct mmp_path *path; | ||
1905 | u32 path_config; | ||
1906 | u32 link_config; | ||
1907 | }; | ||
1908 | |||
1909 | /* mmp ctrl describes mmp controller related info */ | ||
1910 | struct mmphw_ctrl { | ||
1911 | /* platform related, get from config */ | ||
1912 | const char *name; | ||
1913 | int irq; | ||
1914 | void *reg_base; | ||
1915 | struct clk *clk; | ||
1916 | |||
1917 | /* sys info */ | ||
1918 | struct device *dev; | ||
1919 | |||
1920 | /* state */ | ||
1921 | int open_count; | ||
1922 | int status; | ||
1923 | struct mutex access_ok; | ||
1924 | |||
1925 | /*pathes*/ | ||
1926 | int path_num; | ||
1927 | struct mmphw_path_plat path_plats[0]; | ||
1928 | }; | ||
1929 | |||
1930 | static inline int overlay_is_vid(struct mmp_overlay *overlay) | ||
1931 | { | ||
1932 | return overlay->dmafetch_id & 1; | ||
1933 | } | ||
1934 | |||
1935 | static inline struct mmphw_path_plat *path_to_path_plat(struct mmp_path *path) | ||
1936 | { | ||
1937 | return (struct mmphw_path_plat *)path->plat_data; | ||
1938 | } | ||
1939 | |||
1940 | static inline struct mmphw_ctrl *path_to_ctrl(struct mmp_path *path) | ||
1941 | { | ||
1942 | return path_to_path_plat(path)->ctrl; | ||
1943 | } | ||
1944 | |||
1945 | static inline struct mmphw_ctrl *overlay_to_ctrl(struct mmp_overlay *overlay) | ||
1946 | { | ||
1947 | return path_to_ctrl(overlay->path); | ||
1948 | } | ||
1949 | |||
1950 | static inline void *ctrl_regs(struct mmp_path *path) | ||
1951 | { | ||
1952 | return path_to_ctrl(path)->reg_base; | ||
1953 | } | ||
1954 | |||
1955 | /* path regs, for regs symmetrical for both pathes */ | ||
1956 | static inline struct lcd_regs *path_regs(struct mmp_path *path) | ||
1957 | { | ||
1958 | if (path->id == PATH_PN) | ||
1959 | return (struct lcd_regs *)(ctrl_regs(path) + 0xc0); | ||
1960 | else if (path->id == PATH_TV) | ||
1961 | return (struct lcd_regs *)ctrl_regs(path); | ||
1962 | else if (path->id == PATH_P2) | ||
1963 | return (struct lcd_regs *)(ctrl_regs(path) + 0x200); | ||
1964 | else { | ||
1965 | dev_err(path->dev, "path id %d invalid\n", path->id); | ||
1966 | BUG_ON(1); | ||
1967 | return NULL; | ||
1968 | } | ||
1969 | } | ||
1970 | |||
1971 | #ifdef CONFIG_MMP_DISP_SPI | ||
1972 | extern int lcd_spi_register(struct mmphw_ctrl *ctrl); | ||
1973 | #endif | ||
1974 | #endif /* _MMP_CTRL_H_ */ | ||
diff --git a/drivers/video/mmp/hw/mmp_spi.c b/drivers/video/mmp/hw/mmp_spi.c new file mode 100644 index 000000000000..e62ca7bf0d5e --- /dev/null +++ b/drivers/video/mmp/hw/mmp_spi.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/mmp/hw/mmp_spi.c | ||
3 | * using the spi in LCD controler for commands send | ||
4 | * | ||
5 | * Copyright (C) 2012 Marvell Technology Group Ltd. | ||
6 | * Authors: Guoqing Li <ligq@marvell.com> | ||
7 | * Lisa Du <cldu@marvell.com> | ||
8 | * Zhou Zhu <zzhu3@marvell.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
18 | * more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along with | ||
21 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
22 | * | ||
23 | */ | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/spi/spi.h> | ||
29 | #include "mmp_ctrl.h" | ||
30 | |||
31 | /** | ||
32 | * spi_write - write command to the SPI port | ||
33 | * @data: can be 8/16/32-bit, MSB justified data to write. | ||
34 | * @len: data length. | ||
35 | * | ||
36 | * Wait bus transfer complete IRQ. | ||
37 | * The caller is expected to perform the necessary locking. | ||
38 | * | ||
39 | * Returns: | ||
40 | * %-ETIMEDOUT timeout occurred | ||
41 | * 0 success | ||
42 | */ | ||
43 | static inline int lcd_spi_write(struct spi_device *spi, u32 data) | ||
44 | { | ||
45 | int timeout = 100000, isr, ret = 0; | ||
46 | u32 tmp; | ||
47 | void *reg_base = | ||
48 | *(void **)spi_master_get_devdata(spi->master); | ||
49 | |||
50 | /* clear ISR */ | ||
51 | writel_relaxed(~SPI_IRQ_MASK, reg_base + SPU_IRQ_ISR); | ||
52 | |||
53 | switch (spi->bits_per_word) { | ||
54 | case 8: | ||
55 | writel_relaxed((u8)data, reg_base + LCD_SPU_SPI_TXDATA); | ||
56 | break; | ||
57 | case 16: | ||
58 | writel_relaxed((u16)data, reg_base + LCD_SPU_SPI_TXDATA); | ||
59 | break; | ||
60 | case 32: | ||
61 | writel_relaxed((u32)data, reg_base + LCD_SPU_SPI_TXDATA); | ||
62 | break; | ||
63 | default: | ||
64 | dev_err(&spi->dev, "Wrong spi bit length\n"); | ||
65 | } | ||
66 | |||
67 | /* SPI start to send command */ | ||
68 | tmp = readl_relaxed(reg_base + LCD_SPU_SPI_CTRL); | ||
69 | tmp &= ~CFG_SPI_START_MASK; | ||
70 | tmp |= CFG_SPI_START(1); | ||
71 | writel(tmp, reg_base + LCD_SPU_SPI_CTRL); | ||
72 | |||
73 | isr = readl_relaxed(reg_base + SPU_IRQ_ISR); | ||
74 | while (!(isr & SPI_IRQ_ENA_MASK)) { | ||
75 | udelay(100); | ||
76 | isr = readl_relaxed(reg_base + SPU_IRQ_ISR); | ||
77 | if (!--timeout) { | ||
78 | ret = -ETIMEDOUT; | ||
79 | dev_err(&spi->dev, "spi cmd send time out\n"); | ||
80 | break; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | tmp = readl_relaxed(reg_base + LCD_SPU_SPI_CTRL); | ||
85 | tmp &= ~CFG_SPI_START_MASK; | ||
86 | tmp |= CFG_SPI_START(0); | ||
87 | writel_relaxed(tmp, reg_base + LCD_SPU_SPI_CTRL); | ||
88 | |||
89 | writel_relaxed(~SPI_IRQ_MASK, reg_base + SPU_IRQ_ISR); | ||
90 | |||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | static int lcd_spi_setup(struct spi_device *spi) | ||
95 | { | ||
96 | void *reg_base = | ||
97 | *(void **)spi_master_get_devdata(spi->master); | ||
98 | u32 tmp; | ||
99 | |||
100 | tmp = CFG_SCLKCNT(16) | | ||
101 | CFG_TXBITS(spi->bits_per_word) | | ||
102 | CFG_SPI_SEL(1) | CFG_SPI_ENA(1) | | ||
103 | CFG_SPI_3W4WB(1); | ||
104 | writel(tmp, reg_base + LCD_SPU_SPI_CTRL); | ||
105 | |||
106 | /* | ||
107 | * After set mode it need a time to pull up the spi singals, | ||
108 | * or it would cause the wrong waveform when send spi command, | ||
109 | * especially on pxa910h | ||
110 | */ | ||
111 | tmp = readl_relaxed(reg_base + SPU_IOPAD_CONTROL); | ||
112 | if ((tmp & CFG_IOPADMODE_MASK) != IOPAD_DUMB18SPI) | ||
113 | writel_relaxed(IOPAD_DUMB18SPI | | ||
114 | (tmp & ~CFG_IOPADMODE_MASK), | ||
115 | reg_base + SPU_IOPAD_CONTROL); | ||
116 | udelay(20); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static int lcd_spi_one_transfer(struct spi_device *spi, struct spi_message *m) | ||
121 | { | ||
122 | struct spi_transfer *t; | ||
123 | int i; | ||
124 | |||
125 | list_for_each_entry(t, &m->transfers, transfer_list) { | ||
126 | switch (spi->bits_per_word) { | ||
127 | case 8: | ||
128 | for (i = 0; i < t->len; i++) | ||
129 | lcd_spi_write(spi, ((u8 *)t->tx_buf)[i]); | ||
130 | break; | ||
131 | case 16: | ||
132 | for (i = 0; i < t->len/2; i++) | ||
133 | lcd_spi_write(spi, ((u16 *)t->tx_buf)[i]); | ||
134 | break; | ||
135 | case 32: | ||
136 | for (i = 0; i < t->len/4; i++) | ||
137 | lcd_spi_write(spi, ((u32 *)t->tx_buf)[i]); | ||
138 | break; | ||
139 | default: | ||
140 | dev_err(&spi->dev, "Wrong spi bit length\n"); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | m->status = 0; | ||
145 | if (m->complete) | ||
146 | m->complete(m->context); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | int lcd_spi_register(struct mmphw_ctrl *ctrl) | ||
151 | { | ||
152 | struct spi_master *master; | ||
153 | void **p_regbase; | ||
154 | int err; | ||
155 | |||
156 | master = spi_alloc_master(ctrl->dev, sizeof(void *)); | ||
157 | if (!master) { | ||
158 | dev_err(ctrl->dev, "unable to allocate SPI master\n"); | ||
159 | return -ENOMEM; | ||
160 | } | ||
161 | p_regbase = spi_master_get_devdata(master); | ||
162 | *p_regbase = ctrl->reg_base; | ||
163 | |||
164 | /* set bus num to 5 to avoid conflict with other spi hosts */ | ||
165 | master->bus_num = 5; | ||
166 | master->num_chipselect = 1; | ||
167 | master->setup = lcd_spi_setup; | ||
168 | master->transfer = lcd_spi_one_transfer; | ||
169 | |||
170 | err = spi_register_master(master); | ||
171 | if (err < 0) { | ||
172 | dev_err(ctrl->dev, "unable to register SPI master\n"); | ||
173 | spi_master_put(master); | ||
174 | return err; | ||
175 | } | ||
176 | |||
177 | dev_info(&master->dev, "registered\n"); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
diff --git a/drivers/video/mmp/panel/Kconfig b/drivers/video/mmp/panel/Kconfig new file mode 100644 index 000000000000..4b2c4f457b11 --- /dev/null +++ b/drivers/video/mmp/panel/Kconfig | |||
@@ -0,0 +1,6 @@ | |||
1 | config MMP_PANEL_TPOHVGA | ||
2 | bool "tpohvga panel TJ032MD01BW support" | ||
3 | depends on SPI_MASTER | ||
4 | default n | ||
5 | help | ||
6 | tpohvga panel support | ||
diff --git a/drivers/video/mmp/panel/Makefile b/drivers/video/mmp/panel/Makefile new file mode 100644 index 000000000000..2f91611c7e5e --- /dev/null +++ b/drivers/video/mmp/panel/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_MMP_PANEL_TPOHVGA) += tpo_tj032md01bw.o | |||
diff --git a/drivers/video/mmp/panel/tpo_tj032md01bw.c b/drivers/video/mmp/panel/tpo_tj032md01bw.c new file mode 100644 index 000000000000..998978b08f5e --- /dev/null +++ b/drivers/video/mmp/panel/tpo_tj032md01bw.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/mmp/panel/tpo_tj032md01bw.c | ||
3 | * active panel using spi interface to do init | ||
4 | * | ||
5 | * Copyright (C) 2012 Marvell Technology Group Ltd. | ||
6 | * Authors: Guoqing Li <ligq@marvell.com> | ||
7 | * Lisa Du <cldu@marvell.com> | ||
8 | * Zhou Zhu <zzhu3@marvell.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
18 | * more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along with | ||
21 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/string.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/err.h> | ||
33 | #include <linux/spi/spi.h> | ||
34 | #include <video/mmp_disp.h> | ||
35 | |||
36 | static u16 init[] = { | ||
37 | 0x0801, | ||
38 | 0x0800, | ||
39 | 0x0200, | ||
40 | 0x0304, | ||
41 | 0x040e, | ||
42 | 0x0903, | ||
43 | 0x0b18, | ||
44 | 0x0c53, | ||
45 | 0x0d01, | ||
46 | 0x0ee0, | ||
47 | 0x0f01, | ||
48 | 0x1058, | ||
49 | 0x201e, | ||
50 | 0x210a, | ||
51 | 0x220a, | ||
52 | 0x231e, | ||
53 | 0x2400, | ||
54 | 0x2532, | ||
55 | 0x2600, | ||
56 | 0x27ac, | ||
57 | 0x2904, | ||
58 | 0x2aa2, | ||
59 | 0x2b45, | ||
60 | 0x2c45, | ||
61 | 0x2d15, | ||
62 | 0x2e5a, | ||
63 | 0x2fff, | ||
64 | 0x306b, | ||
65 | 0x310d, | ||
66 | 0x3248, | ||
67 | 0x3382, | ||
68 | 0x34bd, | ||
69 | 0x35e7, | ||
70 | 0x3618, | ||
71 | 0x3794, | ||
72 | 0x3801, | ||
73 | 0x395d, | ||
74 | 0x3aae, | ||
75 | 0x3bff, | ||
76 | 0x07c9, | ||
77 | }; | ||
78 | |||
79 | static u16 poweroff[] = { | ||
80 | 0x07d9, | ||
81 | }; | ||
82 | |||
83 | struct tpohvga_plat_data { | ||
84 | void (*plat_onoff)(int status); | ||
85 | struct spi_device *spi; | ||
86 | }; | ||
87 | |||
88 | static void tpohvga_onoff(struct mmp_panel *panel, int status) | ||
89 | { | ||
90 | struct tpohvga_plat_data *plat = panel->plat_data; | ||
91 | int ret; | ||
92 | |||
93 | if (status) { | ||
94 | plat->plat_onoff(1); | ||
95 | |||
96 | ret = spi_write(plat->spi, init, sizeof(init)); | ||
97 | if (ret < 0) | ||
98 | dev_warn(panel->dev, "init cmd failed(%d)\n", ret); | ||
99 | } else { | ||
100 | ret = spi_write(plat->spi, poweroff, sizeof(poweroff)); | ||
101 | if (ret < 0) | ||
102 | dev_warn(panel->dev, "poweroff cmd failed(%d)\n", ret); | ||
103 | |||
104 | plat->plat_onoff(0); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | static struct mmp_mode mmp_modes_tpohvga[] = { | ||
109 | [0] = { | ||
110 | .pixclock_freq = 10394400, | ||
111 | .refresh = 60, | ||
112 | .xres = 320, | ||
113 | .yres = 480, | ||
114 | .hsync_len = 10, | ||
115 | .left_margin = 15, | ||
116 | .right_margin = 10, | ||
117 | .vsync_len = 2, | ||
118 | .upper_margin = 4, | ||
119 | .lower_margin = 2, | ||
120 | .invert_pixclock = 1, | ||
121 | .pix_fmt_out = PIXFMT_RGB565, | ||
122 | }, | ||
123 | }; | ||
124 | |||
125 | static int tpohvga_get_modelist(struct mmp_panel *panel, | ||
126 | struct mmp_mode **modelist) | ||
127 | { | ||
128 | *modelist = mmp_modes_tpohvga; | ||
129 | return 1; | ||
130 | } | ||
131 | |||
132 | static struct mmp_panel panel_tpohvga = { | ||
133 | .name = "tpohvga", | ||
134 | .panel_type = PANELTYPE_ACTIVE, | ||
135 | .get_modelist = tpohvga_get_modelist, | ||
136 | .set_onoff = tpohvga_onoff, | ||
137 | }; | ||
138 | |||
139 | static int tpohvga_probe(struct spi_device *spi) | ||
140 | { | ||
141 | struct mmp_mach_panel_info *mi; | ||
142 | int ret; | ||
143 | struct tpohvga_plat_data *plat_data; | ||
144 | |||
145 | /* get configs from platform data */ | ||
146 | mi = spi->dev.platform_data; | ||
147 | if (mi == NULL) { | ||
148 | dev_err(&spi->dev, "%s: no platform data defined\n", __func__); | ||
149 | return -EINVAL; | ||
150 | } | ||
151 | |||
152 | /* setup spi related info */ | ||
153 | spi->bits_per_word = 16; | ||
154 | ret = spi_setup(spi); | ||
155 | if (ret < 0) { | ||
156 | dev_err(&spi->dev, "spi setup failed %d", ret); | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | plat_data = kzalloc(sizeof(*plat_data), GFP_KERNEL); | ||
161 | if (plat_data == NULL) | ||
162 | return -ENOMEM; | ||
163 | |||
164 | plat_data->spi = spi; | ||
165 | plat_data->plat_onoff = mi->plat_set_onoff; | ||
166 | panel_tpohvga.plat_data = plat_data; | ||
167 | panel_tpohvga.plat_path_name = mi->plat_path_name; | ||
168 | panel_tpohvga.dev = &spi->dev; | ||
169 | |||
170 | mmp_register_panel(&panel_tpohvga); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static struct spi_driver panel_tpohvga_driver = { | ||
176 | .driver = { | ||
177 | .name = "tpo-hvga", | ||
178 | .owner = THIS_MODULE, | ||
179 | }, | ||
180 | .probe = tpohvga_probe, | ||
181 | }; | ||
182 | module_spi_driver(panel_tpohvga_driver); | ||
183 | |||
184 | MODULE_AUTHOR("Lisa Du<cldu@marvell.com>"); | ||
185 | MODULE_DESCRIPTION("Panel driver for tpohvga"); | ||
186 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 736887208574..cfdb380ec81e 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c | |||
@@ -1306,7 +1306,7 @@ static int mx3fb_unmap_video_memory(struct fb_info *fbi) | |||
1306 | dma_free_writecombine(fbi->device, fbi->fix.smem_len, | 1306 | dma_free_writecombine(fbi->device, fbi->fix.smem_len, |
1307 | fbi->screen_base, fbi->fix.smem_start); | 1307 | fbi->screen_base, fbi->fix.smem_start); |
1308 | 1308 | ||
1309 | fbi->screen_base = 0; | 1309 | fbi->screen_base = NULL; |
1310 | mutex_lock(&fbi->mm_lock); | 1310 | mutex_lock(&fbi->mm_lock); |
1311 | fbi->fix.smem_start = 0; | 1311 | fbi->fix.smem_start = 0; |
1312 | fbi->fix.smem_len = 0; | 1312 | fbi->fix.smem_len = 0; |