diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/busses/i2c-pxa.c | 29 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_cm_x270.c | 15 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_mainstone.c | 13 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_sharpsl.c | 12 | ||||
-rw-r--r-- | drivers/usb/gadget/pxa27x_udc.c | 5 | ||||
-rw-r--r-- | drivers/usb/gadget/pxa27x_udc.h | 8 | ||||
-rw-r--r-- | drivers/usb/gadget/pxa2xx_udc.c | 10 | ||||
-rw-r--r-- | drivers/usb/host/ohci-pxa27x.c | 3 | ||||
-rw-r--r-- | drivers/video/backlight/Kconfig | 7 | ||||
-rw-r--r-- | drivers/video/backlight/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/backlight/pwm_bl.c | 185 |
11 files changed, 233 insertions, 55 deletions
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index eb26d2aca8b4..dde6ce963a19 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -944,32 +944,6 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = { | |||
944 | .functionality = i2c_pxa_functionality, | 944 | .functionality = i2c_pxa_functionality, |
945 | }; | 945 | }; |
946 | 946 | ||
947 | static void i2c_pxa_enable(struct platform_device *dev) | ||
948 | { | ||
949 | if (cpu_is_pxa27x()) { | ||
950 | switch (dev->id) { | ||
951 | case 0: | ||
952 | pxa_gpio_mode(GPIO117_I2CSCL_MD); | ||
953 | pxa_gpio_mode(GPIO118_I2CSDA_MD); | ||
954 | break; | ||
955 | case 1: | ||
956 | local_irq_disable(); | ||
957 | PCFR |= PCFR_PI2CEN; | ||
958 | local_irq_enable(); | ||
959 | break; | ||
960 | } | ||
961 | } | ||
962 | } | ||
963 | |||
964 | static void i2c_pxa_disable(struct platform_device *dev) | ||
965 | { | ||
966 | if (cpu_is_pxa27x() && dev->id == 1) { | ||
967 | local_irq_disable(); | ||
968 | PCFR &= ~PCFR_PI2CEN; | ||
969 | local_irq_enable(); | ||
970 | } | ||
971 | } | ||
972 | |||
973 | #define res_len(r) ((r)->end - (r)->start + 1) | 947 | #define res_len(r) ((r)->end - (r)->start + 1) |
974 | static int i2c_pxa_probe(struct platform_device *dev) | 948 | static int i2c_pxa_probe(struct platform_device *dev) |
975 | { | 949 | { |
@@ -1035,7 +1009,6 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
1035 | #endif | 1009 | #endif |
1036 | 1010 | ||
1037 | clk_enable(i2c->clk); | 1011 | clk_enable(i2c->clk); |
1038 | i2c_pxa_enable(dev); | ||
1039 | 1012 | ||
1040 | if (plat) { | 1013 | if (plat) { |
1041 | i2c->adap.class = plat->class; | 1014 | i2c->adap.class = plat->class; |
@@ -1079,7 +1052,6 @@ eadapt: | |||
1079 | free_irq(irq, i2c); | 1052 | free_irq(irq, i2c); |
1080 | ereqirq: | 1053 | ereqirq: |
1081 | clk_disable(i2c->clk); | 1054 | clk_disable(i2c->clk); |
1082 | i2c_pxa_disable(dev); | ||
1083 | iounmap(i2c->reg_base); | 1055 | iounmap(i2c->reg_base); |
1084 | eremap: | 1056 | eremap: |
1085 | clk_put(i2c->clk); | 1057 | clk_put(i2c->clk); |
@@ -1102,7 +1074,6 @@ static int __exit i2c_pxa_remove(struct platform_device *dev) | |||
1102 | 1074 | ||
1103 | clk_disable(i2c->clk); | 1075 | clk_disable(i2c->clk); |
1104 | clk_put(i2c->clk); | 1076 | clk_put(i2c->clk); |
1105 | i2c_pxa_disable(dev); | ||
1106 | 1077 | ||
1107 | iounmap(i2c->reg_base); | 1078 | iounmap(i2c->reg_base); |
1108 | release_mem_region(i2c->iobase, i2c->iosize); | 1079 | release_mem_region(i2c->iobase, i2c->iosize); |
diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c index e7ab060ff118..f123fce65f2e 100644 --- a/drivers/pcmcia/pxa2xx_cm_x270.c +++ b/drivers/pcmcia/pxa2xx_cm_x270.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <pcmcia/ss.h> | 19 | #include <pcmcia/ss.h> |
20 | #include <asm/hardware.h> | 20 | #include <asm/hardware.h> |
21 | #include <asm/mach-types.h> | ||
21 | 22 | ||
22 | #include <asm/arch/pxa-regs.h> | 23 | #include <asm/arch/pxa-regs.h> |
23 | #include <asm/arch/pxa2xx-gpio.h> | 24 | #include <asm/arch/pxa2xx-gpio.h> |
@@ -130,7 +131,7 @@ static void cmx270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) | |||
130 | } | 131 | } |
131 | 132 | ||
132 | 133 | ||
133 | static struct pcmcia_low_level cmx270_pcmcia_ops = { | 134 | static struct pcmcia_low_level cmx270_pcmcia_ops __initdata = { |
134 | .owner = THIS_MODULE, | 135 | .owner = THIS_MODULE, |
135 | .hw_init = cmx270_pcmcia_hw_init, | 136 | .hw_init = cmx270_pcmcia_hw_init, |
136 | .hw_shutdown = cmx270_pcmcia_shutdown, | 137 | .hw_shutdown = cmx270_pcmcia_shutdown, |
@@ -147,15 +148,21 @@ static int __init cmx270_pcmcia_init(void) | |||
147 | { | 148 | { |
148 | int ret; | 149 | int ret; |
149 | 150 | ||
151 | if (!machine_is_armcore()) | ||
152 | return -ENODEV; | ||
153 | |||
150 | cmx270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); | 154 | cmx270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); |
151 | 155 | ||
152 | if (!cmx270_pcmcia_device) | 156 | if (!cmx270_pcmcia_device) |
153 | return -ENOMEM; | 157 | return -ENOMEM; |
154 | 158 | ||
155 | cmx270_pcmcia_device->dev.platform_data = &cmx270_pcmcia_ops; | 159 | ret = platform_device_add_data(cmx270_pcmcia_device, &cmx270_pcmcia_ops, |
160 | sizeof(cmx270_pcmcia_ops)); | ||
156 | 161 | ||
157 | printk(KERN_INFO "Registering cm-x270 PCMCIA interface.\n"); | 162 | if (ret == 0) { |
158 | ret = platform_device_add(cmx270_pcmcia_device); | 163 | printk(KERN_INFO "Registering cm-x270 PCMCIA interface.\n"); |
164 | ret = platform_device_add(cmx270_pcmcia_device); | ||
165 | } | ||
159 | 166 | ||
160 | if (ret) | 167 | if (ret) |
161 | platform_device_put(cmx270_pcmcia_device); | 168 | platform_device_put(cmx270_pcmcia_device); |
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c index 145b85e0f02c..92d1cc33808c 100644 --- a/drivers/pcmcia/pxa2xx_mainstone.c +++ b/drivers/pcmcia/pxa2xx_mainstone.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <pcmcia/ss.h> | 22 | #include <pcmcia/ss.h> |
23 | 23 | ||
24 | #include <asm/hardware.h> | 24 | #include <asm/hardware.h> |
25 | #include <asm/mach-types.h> | ||
25 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
26 | 27 | ||
27 | #include <asm/arch/pxa-regs.h> | 28 | #include <asm/arch/pxa-regs.h> |
@@ -136,7 +137,7 @@ static void mst_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) | |||
136 | { | 137 | { |
137 | } | 138 | } |
138 | 139 | ||
139 | static struct pcmcia_low_level mst_pcmcia_ops = { | 140 | static struct pcmcia_low_level mst_pcmcia_ops __initdata = { |
140 | .owner = THIS_MODULE, | 141 | .owner = THIS_MODULE, |
141 | .hw_init = mst_pcmcia_hw_init, | 142 | .hw_init = mst_pcmcia_hw_init, |
142 | .hw_shutdown = mst_pcmcia_hw_shutdown, | 143 | .hw_shutdown = mst_pcmcia_hw_shutdown, |
@@ -153,13 +154,17 @@ static int __init mst_pcmcia_init(void) | |||
153 | { | 154 | { |
154 | int ret; | 155 | int ret; |
155 | 156 | ||
157 | if (!machine_is_mainstone()) | ||
158 | return -ENODEV; | ||
159 | |||
156 | mst_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); | 160 | mst_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); |
157 | if (!mst_pcmcia_device) | 161 | if (!mst_pcmcia_device) |
158 | return -ENOMEM; | 162 | return -ENOMEM; |
159 | 163 | ||
160 | mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops; | 164 | ret = platform_device_add_data(mst_pcmcia_device, &mst_pcmcia_ops, |
161 | 165 | sizeof(mst_pcmcia_ops)); | |
162 | ret = platform_device_add(mst_pcmcia_device); | 166 | if (ret == 0) |
167 | ret = platform_device_add(mst_pcmcia_device); | ||
163 | 168 | ||
164 | if (ret) | 169 | if (ret) |
165 | platform_device_put(mst_pcmcia_device); | 170 | platform_device_put(mst_pcmcia_device); |
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index d5c33bd78d68..d71f93d45833 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c | |||
@@ -222,7 +222,7 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) | |||
222 | sharpsl_pcmcia_init_reset(skt); | 222 | sharpsl_pcmcia_init_reset(skt); |
223 | } | 223 | } |
224 | 224 | ||
225 | static struct pcmcia_low_level sharpsl_pcmcia_ops = { | 225 | static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = { |
226 | .owner = THIS_MODULE, | 226 | .owner = THIS_MODULE, |
227 | .hw_init = sharpsl_pcmcia_hw_init, | 227 | .hw_init = sharpsl_pcmcia_hw_init, |
228 | .hw_shutdown = sharpsl_pcmcia_hw_shutdown, | 228 | .hw_shutdown = sharpsl_pcmcia_hw_shutdown, |
@@ -261,10 +261,12 @@ static int __init sharpsl_pcmcia_init(void) | |||
261 | if (!sharpsl_pcmcia_device) | 261 | if (!sharpsl_pcmcia_device) |
262 | return -ENOMEM; | 262 | return -ENOMEM; |
263 | 263 | ||
264 | sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops; | 264 | ret = platform_device_add_data(sharpsl_pcmcia_device, |
265 | sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev; | 265 | &sharpsl_pcmcia_ops, sizeof(sharpsl_pcmcia_ops)); |
266 | 266 | if (ret == 0) { | |
267 | ret = platform_device_add(sharpsl_pcmcia_device); | 267 | sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev; |
268 | ret = platform_device_add(sharpsl_pcmcia_device); | ||
269 | } | ||
268 | 270 | ||
269 | if (ret) | 271 | if (ret) |
270 | platform_device_put(sharpsl_pcmcia_device); | 272 | platform_device_put(sharpsl_pcmcia_device); |
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 499b7a23f351..40d6b580f152 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <linux/usb.h> | 38 | #include <linux/usb.h> |
39 | #include <linux/usb/ch9.h> | 39 | #include <linux/usb/ch9.h> |
40 | #include <linux/usb/gadget.h> | 40 | #include <linux/usb/gadget.h> |
41 | 41 | #include <asm/arch/pxa2xx-regs.h> /* FIXME: for PSSR */ | |
42 | #include <asm/arch/udc.h> | 42 | #include <asm/arch/udc.h> |
43 | 43 | ||
44 | #include "pxa27x_udc.h" | 44 | #include "pxa27x_udc.h" |
@@ -2359,7 +2359,8 @@ static int pxa_udc_resume(struct platform_device *_dev) | |||
2359 | * Software must configure the USB OTG pad, UDC, and UHC | 2359 | * Software must configure the USB OTG pad, UDC, and UHC |
2360 | * to the state they were in before entering sleep mode. | 2360 | * to the state they were in before entering sleep mode. |
2361 | */ | 2361 | */ |
2362 | PSSR |= PSSR_OTGPH; | 2362 | if (cpu_is_pxa27x()) |
2363 | PSSR |= PSSR_OTGPH; | ||
2363 | 2364 | ||
2364 | return 0; | 2365 | return 0; |
2365 | } | 2366 | } |
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 97453db924ff..1d1b7936ee11 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h | |||
@@ -484,12 +484,4 @@ static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget) | |||
484 | #define ep_warn(ep, fmt, arg...) \ | 484 | #define ep_warn(ep, fmt, arg...) \ |
485 | dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg) | 485 | dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg) |
486 | 486 | ||
487 | /* | ||
488 | * Cannot include pxa-regs.h, as register names are similar. | ||
489 | * So PSSR is redefined here. This should be removed once UDC registers will | ||
490 | * be gone from pxa-regs.h. | ||
491 | */ | ||
492 | #define PSSR __REG(0x40F00004) /* Power Manager Sleep Status */ | ||
493 | #define PSSR_OTGPH (1 << 6) /* OTG Peripheral Hold */ | ||
494 | |||
495 | #endif /* __LINUX_USB_GADGET_PXA27X_H */ | 487 | #endif /* __LINUX_USB_GADGET_PXA27X_H */ |
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 08f699b1fc57..63db96adc0b0 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c | |||
@@ -46,19 +46,25 @@ | |||
46 | #include <linux/err.h> | 46 | #include <linux/err.h> |
47 | #include <linux/seq_file.h> | 47 | #include <linux/seq_file.h> |
48 | #include <linux/debugfs.h> | 48 | #include <linux/debugfs.h> |
49 | #include <linux/io.h> | ||
49 | 50 | ||
50 | #include <asm/byteorder.h> | 51 | #include <asm/byteorder.h> |
51 | #include <asm/dma.h> | 52 | #include <asm/dma.h> |
52 | #include <asm/gpio.h> | 53 | #include <asm/gpio.h> |
53 | #include <asm/io.h> | ||
54 | #include <asm/system.h> | 54 | #include <asm/system.h> |
55 | #include <asm/mach-types.h> | 55 | #include <asm/mach-types.h> |
56 | #include <asm/unaligned.h> | 56 | #include <asm/unaligned.h> |
57 | #include <asm/hardware.h> | ||
58 | 57 | ||
59 | #include <linux/usb/ch9.h> | 58 | #include <linux/usb/ch9.h> |
60 | #include <linux/usb/gadget.h> | 59 | #include <linux/usb/gadget.h> |
61 | 60 | ||
61 | /* | ||
62 | * This driver is PXA25x only. Grab the right register definitions. | ||
63 | */ | ||
64 | #ifdef CONFIG_ARCH_PXA | ||
65 | #include <asm/arch/pxa25x-udc.h> | ||
66 | #endif | ||
67 | |||
62 | #include <asm/mach/udc_pxa2xx.h> | 68 | #include <asm/mach/udc_pxa2xx.h> |
63 | 69 | ||
64 | 70 | ||
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 70b0d4b459e7..08b27d6bbd43 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/mach-types.h> | 27 | #include <asm/mach-types.h> |
28 | #include <asm/hardware.h> | 28 | #include <asm/hardware.h> |
29 | #include <asm/arch/pxa-regs.h> | 29 | #include <asm/arch/pxa-regs.h> |
30 | #include <asm/arch/pxa2xx-regs.h> /* FIXME: for PSSR */ | ||
30 | #include <asm/arch/ohci.h> | 31 | #include <asm/arch/ohci.h> |
31 | 32 | ||
32 | #define PXA_UHC_MAX_PORTNUM 3 | 33 | #define PXA_UHC_MAX_PORTNUM 3 |
@@ -104,7 +105,7 @@ static int pxa27x_start_hc(struct device *dev) | |||
104 | UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE); | 105 | UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE); |
105 | 106 | ||
106 | /* Clear any OTG Pin Hold */ | 107 | /* Clear any OTG Pin Hold */ |
107 | if (PSSR & PSSR_OTGPH) | 108 | if (cpu_is_pxa27x() && (PSSR & PSSR_OTGPH)) |
108 | PSSR |= PSSR_OTGPH; | 109 | PSSR |= PSSR_OTGPH; |
109 | 110 | ||
110 | return 0; | 111 | return 0; |
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index dcd8073c2369..30bf7f2f1635 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
@@ -112,3 +112,10 @@ config BACKLIGHT_CARILLO_RANCH | |||
112 | help | 112 | help |
113 | If you have a Intel LE80578 (Carillo Ranch) say Y to enable the | 113 | If you have a Intel LE80578 (Carillo Ranch) say Y to enable the |
114 | backlight driver. | 114 | backlight driver. |
115 | |||
116 | config BACKLIGHT_PWM | ||
117 | tristate "Generic PWM based Backlight Driver" | ||
118 | depends on BACKLIGHT_CLASS_DEVICE && HAVE_PWM | ||
119 | help | ||
120 | If you have a LCD backlight adjustable by PWM, say Y to enable | ||
121 | this driver. | ||
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 33f6c7cecc73..b51a7cd12500 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile | |||
@@ -10,3 +10,4 @@ obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o | |||
10 | obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o | 10 | obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o |
11 | obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o | 11 | obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o |
12 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o | 12 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o |
13 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o | ||
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c new file mode 100644 index 000000000000..6338d0e2fe07 --- /dev/null +++ b/drivers/video/backlight/pwm_bl.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/backlight/pwm_bl.c | ||
3 | * | ||
4 | * simple PWM based backlight control, board code has to setup | ||
5 | * 1) pin configuration so PWM waveforms can output | ||
6 | * 2) platform_data casts to the PWM id (0/1/2/3 on PXA) | ||
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 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/fb.h> | ||
18 | #include <linux/backlight.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/pwm.h> | ||
21 | #include <linux/pwm_backlight.h> | ||
22 | |||
23 | struct pwm_bl_data { | ||
24 | struct pwm_device *pwm; | ||
25 | unsigned int period; | ||
26 | int (*notify)(int brightness); | ||
27 | }; | ||
28 | |||
29 | static int pwm_backlight_update_status(struct backlight_device *bl) | ||
30 | { | ||
31 | struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); | ||
32 | int brightness = bl->props.brightness; | ||
33 | int max = bl->props.max_brightness; | ||
34 | |||
35 | if (bl->props.power != FB_BLANK_UNBLANK) | ||
36 | brightness = 0; | ||
37 | |||
38 | if (bl->props.fb_blank != FB_BLANK_UNBLANK) | ||
39 | brightness = 0; | ||
40 | |||
41 | if (pb->notify) | ||
42 | brightness = pb->notify(brightness); | ||
43 | |||
44 | if (brightness == 0) { | ||
45 | pwm_config(pb->pwm, 0, pb->period); | ||
46 | pwm_disable(pb->pwm); | ||
47 | } else { | ||
48 | pwm_config(pb->pwm, brightness * pb->period / max, pb->period); | ||
49 | pwm_enable(pb->pwm); | ||
50 | } | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | static int pwm_backlight_get_brightness(struct backlight_device *bl) | ||
55 | { | ||
56 | return bl->props.brightness; | ||
57 | } | ||
58 | |||
59 | static struct backlight_ops pwm_backlight_ops = { | ||
60 | .update_status = pwm_backlight_update_status, | ||
61 | .get_brightness = pwm_backlight_get_brightness, | ||
62 | }; | ||
63 | |||
64 | static int pwm_backlight_probe(struct platform_device *pdev) | ||
65 | { | ||
66 | struct platform_pwm_backlight_data *data = pdev->dev.platform_data; | ||
67 | struct backlight_device *bl; | ||
68 | struct pwm_bl_data *pb; | ||
69 | int ret; | ||
70 | |||
71 | if (!data) | ||
72 | return -EINVAL; | ||
73 | |||
74 | if (data->init) { | ||
75 | ret = data->init(&pdev->dev); | ||
76 | if (ret < 0) | ||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | pb = kzalloc(sizeof(*pb), GFP_KERNEL); | ||
81 | if (!pb) { | ||
82 | ret = -ENOMEM; | ||
83 | goto err_alloc; | ||
84 | } | ||
85 | |||
86 | pb->period = data->pwm_period_ns; | ||
87 | pb->notify = data->notify; | ||
88 | |||
89 | pb->pwm = pwm_request(data->pwm_id, "backlight"); | ||
90 | if (IS_ERR(pb->pwm)) { | ||
91 | dev_err(&pdev->dev, "unable to request PWM for backlight\n"); | ||
92 | ret = PTR_ERR(pb->pwm); | ||
93 | goto err_pwm; | ||
94 | } | ||
95 | |||
96 | bl = backlight_device_register(pdev->name, &pdev->dev, | ||
97 | pb, &pwm_backlight_ops); | ||
98 | if (IS_ERR(bl)) { | ||
99 | dev_err(&pdev->dev, "failed to register backlight\n"); | ||
100 | ret = PTR_ERR(bl); | ||
101 | goto err_bl; | ||
102 | } | ||
103 | |||
104 | bl->props.max_brightness = data->max_brightness; | ||
105 | bl->props.brightness = data->dft_brightness; | ||
106 | backlight_update_status(bl); | ||
107 | |||
108 | platform_set_drvdata(pdev, bl); | ||
109 | return 0; | ||
110 | |||
111 | err_bl: | ||
112 | pwm_free(pb->pwm); | ||
113 | err_pwm: | ||
114 | kfree(pb); | ||
115 | err_alloc: | ||
116 | if (data->exit) | ||
117 | data->exit(&pdev->dev); | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static int pwm_backlight_remove(struct platform_device *pdev) | ||
122 | { | ||
123 | struct platform_pwm_backlight_data *data = pdev->dev.platform_data; | ||
124 | struct backlight_device *bl = platform_get_drvdata(pdev); | ||
125 | struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); | ||
126 | |||
127 | backlight_device_unregister(bl); | ||
128 | pwm_config(pb->pwm, 0, pb->period); | ||
129 | pwm_disable(pb->pwm); | ||
130 | pwm_free(pb->pwm); | ||
131 | kfree(pb); | ||
132 | if (data->exit) | ||
133 | data->exit(&pdev->dev); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | #ifdef CONFIG_PM | ||
138 | static int pwm_backlight_suspend(struct platform_device *pdev, | ||
139 | pm_message_t state) | ||
140 | { | ||
141 | struct backlight_device *bl = platform_get_drvdata(pdev); | ||
142 | struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); | ||
143 | |||
144 | pwm_config(pb->pwm, 0, pb->period); | ||
145 | pwm_disable(pb->pwm); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int pwm_backlight_resume(struct platform_device *pdev) | ||
150 | { | ||
151 | struct backlight_device *bl = platform_get_drvdata(pdev); | ||
152 | |||
153 | backlight_update_status(bl); | ||
154 | return 0; | ||
155 | } | ||
156 | #else | ||
157 | #define pwm_backlight_suspend NULL | ||
158 | #define pwm_backlight_resume NULL | ||
159 | #endif | ||
160 | |||
161 | static struct platform_driver pwm_backlight_driver = { | ||
162 | .driver = { | ||
163 | .name = "pwm-backlight", | ||
164 | .owner = THIS_MODULE, | ||
165 | }, | ||
166 | .probe = pwm_backlight_probe, | ||
167 | .remove = pwm_backlight_remove, | ||
168 | .suspend = pwm_backlight_suspend, | ||
169 | .resume = pwm_backlight_resume, | ||
170 | }; | ||
171 | |||
172 | static int __init pwm_backlight_init(void) | ||
173 | { | ||
174 | return platform_driver_register(&pwm_backlight_driver); | ||
175 | } | ||
176 | module_init(pwm_backlight_init); | ||
177 | |||
178 | static void __exit pwm_backlight_exit(void) | ||
179 | { | ||
180 | platform_driver_unregister(&pwm_backlight_driver); | ||
181 | } | ||
182 | module_exit(pwm_backlight_exit); | ||
183 | |||
184 | MODULE_DESCRIPTION("PWM based Backlight Driver"); | ||
185 | MODULE_LICENSE("GPL"); | ||