add support for target 3c24xx (more known as Openmoko GTA02 "Freerunner") and merge...
[openwrt.git] / target / linux / s3c24xx / patches / 0012-gta01-vibrator.patch.patch
1 From 51990833d84bdff24a384119a9ba0cf815edd683 Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Wed, 16 Jul 2008 14:44:49 +0100
4 Subject: [PATCH] gta01-vibrator.patch
5  This patch adds driver support for the vibator device of the FIC/OpenMoko
6  Neo1973 GSM phone. The driver uses the existing LED class driver framework,
7  since there's a lot of similarity between the LED and the vibrator function.
8
9 Signed-off-by: Harald Welte <laforge@openmoko.org>
10 ---
11  drivers/leds/Kconfig                 |    8 ++-
12  drivers/leds/Makefile                |    1 +
13  drivers/leds/leds-neo1973-vibrator.c |  181 ++++++++++++++++++++++++++++++++++
14  3 files changed, 189 insertions(+), 1 deletions(-)
15  create mode 100644 drivers/leds/leds-neo1973-vibrator.c
16
17 diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
18 index 86a369b..8c7d949 100644
19 --- a/drivers/leds/Kconfig
20 +++ b/drivers/leds/Kconfig
21 @@ -47,7 +47,7 @@ config LEDS_SPITZ
22  
23  config LEDS_S3C24XX
24         tristate "LED Support for Samsung S3C24XX GPIO LEDs"
25 -       depends on LEDS_CLASS && ARCH_S3C2410
26 +       depends on LEDS_CLASS && ARCH_S3C2410 && S3C2410_PWM
27         help
28           This option enables support for LEDs connected to GPIO lines
29           on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
30 @@ -147,6 +147,12 @@ config LEDS_CLEVO_MAIL
31           To compile this driver as a module, choose M here: the
32           module will be called leds-clevo-mail.
33  
34 +config LEDS_NEO1973_VIBRATOR
35 +       tristate "Vibrator Support for the FIC Neo1973 GSM phone"
36 +       depends on LEDS_CLASS && MACH_NEO1973
37 +       help
38 +         This option enables support for the vibrator on the FIC Neo1973.
39 +
40  comment "LED Triggers"
41  
42  config LEDS_TRIGGERS
43 diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
44 index 973d626..148fe51 100644
45 --- a/drivers/leds/Makefile
46 +++ b/drivers/leds/Makefile
47 @@ -21,6 +21,7 @@ obj-$(CONFIG_LEDS_CM_X270)              += leds-cm-x270.o
48  obj-$(CONFIG_LEDS_CLEVO_MAIL)          += leds-clevo-mail.o
49  obj-$(CONFIG_LEDS_HP6XX)               += leds-hp6xx.o
50  obj-$(CONFIG_LEDS_FSG)                 += leds-fsg.o
51 +obj-$(CONFIG_LEDS_NEO1973_VIBRATOR)    += leds-neo1973-vibrator.o
52  
53  # LED Triggers
54  obj-$(CONFIG_LEDS_TRIGGER_TIMER)       += ledtrig-timer.o
55 diff --git a/drivers/leds/leds-neo1973-vibrator.c b/drivers/leds/leds-neo1973-vibrator.c
56 new file mode 100644
57 index 0000000..0336e36
58 --- /dev/null
59 +++ b/drivers/leds/leds-neo1973-vibrator.c
60 @@ -0,0 +1,181 @@
61 +/*
62 + * LED driver for the vibrator of the FIC Neo1973 GSM Phone
63 + *
64 + * (C) 2006-2007 by OpenMoko, Inc.
65 + * Author: Harald Welte <laforge@openmoko.org>
66 + * All rights reserved.
67 + *
68 + * This program is free software; you can redistribute it and/or modify
69 + * it under the terms of the GNU General Public License version 2 as
70 + * published by the Free Software Foundation.
71 + *
72 + * Javi Roman <javiroman@kernel-labs.org>:
73 + *     Implement PWM support for GTA01Bv4 and later
74 + */
75 +
76 +#include <linux/kernel.h>
77 +#include <linux/init.h>
78 +#include <linux/platform_device.h>
79 +#include <linux/leds.h>
80 +#include <asm/hardware.h>
81 +#include <asm/mach-types.h>
82 +#include <asm/arch/pwm.h>
83 +#include <asm/arch/gta01.h>
84 +#include <asm/plat-s3c/regs-timer.h>
85 +
86 +#define COUNTER 64
87 +
88 +struct neo1973_vib_priv {
89 +       struct led_classdev cdev;
90 +       unsigned int gpio;
91 +       struct mutex mutex;
92 +       unsigned int has_pwm;
93 +       struct s3c2410_pwm pwm;
94 +};
95 +
96 +static void neo1973_vib_vib_set(struct led_classdev *led_cdev,
97 +               enum led_brightness value)
98 +{
99 +       struct neo1973_vib_priv *vp =
100 +               container_of(led_cdev, struct neo1973_vib_priv, cdev);
101 +
102 +       /*
103 +        * value == 255 -> 99% duty cycle (full power)
104 +        * value == 128 -> 50% duty cycle (medium power)
105 +        * value == 0 -> 0% duty cycle (zero power)
106 +        */
107 +       mutex_lock(&vp->mutex);
108 +       if (vp->has_pwm)
109 +               s3c2410_pwm_duty_cycle(value/4, &vp->pwm);
110 +       else {
111 +               if (value)
112 +                       s3c2410_gpio_setpin(vp->gpio, 1);
113 +               else
114 +                       s3c2410_gpio_setpin(vp->gpio, 0);
115 +       }
116 +
117 +       mutex_unlock(&vp->mutex);
118 +}
119 +
120 +static struct neo1973_vib_priv neo1973_vib_led = {
121 +       .cdev = {
122 +               .name = "neo1973:vibrator",
123 +               .brightness_set = neo1973_vib_vib_set,
124 +       },
125 +};
126 +
127 +static int neo1973_vib_init_hw(struct neo1973_vib_priv *vp)
128 +{
129 +       int rc;
130 +
131 +       rc = s3c2410_pwm_init(&vp->pwm);
132 +       if (rc)
133 +               return rc;
134 +
135 +       vp->pwm.timerid = PWM3;
136 +       /* use same prescaler as arch/arm/plat-s3c24xx/time.c */
137 +       vp->pwm.prescaler = (6 - 1) / 2;
138 +       vp->pwm.divider = S3C2410_TCFG1_MUX3_DIV2;
139 +       vp->pwm.counter = COUNTER;
140 +       vp->pwm.comparer = COUNTER;
141 +
142 +       rc = s3c2410_pwm_enable(&vp->pwm);
143 +       if (rc)
144 +               return rc;
145 +
146 +       s3c2410_pwm_start(&vp->pwm);
147 +
148 +       return 0;
149 +}
150 +
151 +#ifdef CONFIG_PM
152 +static int neo1973_vib_suspend(struct platform_device *dev, pm_message_t state)
153 +{
154 +       led_classdev_suspend(&neo1973_vib_led.cdev);
155 +       return 0;
156 +}
157 +
158 +static int neo1973_vib_resume(struct platform_device *dev)
159 +{
160 +       struct neo1973_vib_priv *vp = platform_get_drvdata(dev);
161 +
162 +       if (vp->has_pwm)
163 +               neo1973_vib_init_hw(vp);
164 +
165 +       led_classdev_resume(&neo1973_vib_led.cdev);
166 +
167 +       return 0;
168 +}
169 +#endif /* CONFIG_PM */
170 +
171 +static int __init neo1973_vib_probe(struct platform_device *pdev)
172 +{
173 +       struct resource *r;
174 +       int rc;
175 +
176 +       if (!machine_is_neo1973_gta01())
177 +               return -EIO;
178 +
179 +       r = platform_get_resource(pdev, 0, 0);
180 +       if (!r || !r->start)
181 +               return -EIO;
182 +
183 +       neo1973_vib_led.gpio = r->start;
184 +       platform_set_drvdata(pdev, &neo1973_vib_led);
185 +
186 +       /* TOUT3 */
187 +       if (neo1973_vib_led.gpio == S3C2410_GPB3) {
188 +               rc = neo1973_vib_init_hw(&neo1973_vib_led);
189 +               if (rc)
190 +                       return rc;
191 +
192 +               s3c2410_pwm_duty_cycle(0, &neo1973_vib_led.pwm);
193 +               s3c2410_gpio_cfgpin(neo1973_vib_led.gpio, S3C2410_GPB3_TOUT3);
194 +               neo1973_vib_led.has_pwm = 1;
195 +       }
196 +
197 +       mutex_init(&neo1973_vib_led.mutex);
198 +
199 +       return led_classdev_register(&pdev->dev, &neo1973_vib_led.cdev);
200 +}
201 +
202 +static int neo1973_vib_remove(struct platform_device *pdev)
203 +{
204 +       if (neo1973_vib_led.has_pwm)
205 +               s3c2410_pwm_disable(&neo1973_vib_led.pwm);
206 +
207 +       led_classdev_unregister(&neo1973_vib_led.cdev);
208 +
209 +       mutex_destroy(&neo1973_vib_led.mutex);
210 +
211 +       return 0;
212 +}
213 +
214 +static struct platform_driver neo1973_vib_driver = {
215 +       .probe          = neo1973_vib_probe,
216 +       .remove         = neo1973_vib_remove,
217 +#ifdef CONFIG_PM
218 +       .suspend        = neo1973_vib_suspend,
219 +       .resume         = neo1973_vib_resume,
220 +#endif
221 +       .driver         = {
222 +               .name           = "neo1973-vibrator",
223 +       },
224 +};
225 +
226 +static int __init neo1973_vib_init(void)
227 +{
228 +       return platform_driver_register(&neo1973_vib_driver);
229 +}
230 +
231 +static void __exit neo1973_vib_exit(void)
232 +{
233 +       platform_driver_unregister(&neo1973_vib_driver);
234 +}
235 +
236 +module_init(neo1973_vib_init);
237 +module_exit(neo1973_vib_exit);
238 +
239 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
240 +MODULE_DESCRIPTION("FIC Neo1973 vibrator driver");
241 +MODULE_LICENSE("GPL");
242 -- 
243 1.5.6.3
244