This is FIC GTA01 Vibrator driver with PWM functions.
-Javi
diff -uprN -X dontdiff linux-2.6.22.5/drivers/leds/Kconfig linux-2.6.22.5.new/drivers/leds/Kconfig
--- linux-2.6.22.5/drivers/leds/Kconfig 2007-09-02 14:17:48.000000000 +0200
+++ linux-2.6.22.5.new/drivers/leds/Kconfig 2007-09-15 12:28:31.000000000 +0200
@@ -59,7 +59,7 @@ config LEDS_TOSA
config LEDS_S3C24XX
tristate "LED Support for Samsung S3C24XX GPIO LEDs"
- depends on LEDS_CLASS && ARCH_S3C2410
+ depends on LEDS_CLASS && ARCH_S3C2410 && S3C2410_PWM
help
This option enables support for LEDs connected to GPIO lines
on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
diff -uprN -X dontdiff linux-2.6.22.5/drivers/leds/leds-gta01.c linux-2.6.22.5.new/drivers/leds/leds-gta01.c
--- linux-2.6.22.5/drivers/leds/leds-gta01.c 2007-09-02 14:17:48.000000000 +0200
+++ linux-2.6.22.5.new/drivers/leds/leds-gta01.c 2007-09-16 19:42:24.000000000 +0200
@@ -9,7 +9,8 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * TODO: Implement PWM support for GTA01Bv4 and later
+ * Javi Roman <[EMAIL PROTECTED]>:
+ * Implement PWM support for GTA01Bv4 and later
*/
#include <linux/kernel.h>
@@ -20,11 +21,17 @@
#include <asm/mach-types.h>
#include <asm/arch/gta01.h>
+#include <asm/arch/s3c2410-pwm.h>
+
+#define COUNTER 256
+
struct gta01_vib_priv
{
- struct led_classdev cdev;
+ struct led_classdev cdev;
unsigned int gpio;
+ struct mutex mutex;
unsigned int has_pwm;
+ struct s3c2410_pwm_t *pwm;
};
static inline struct gta01_vib_priv *pdev_to_vpriv(struct platform_device *dev)
@@ -37,14 +44,29 @@ static inline struct gta01_vib_priv *to_
return dev_get_drvdata(led_cdev->class_dev->dev);
}
-static void gta01vib_vib_set(struct led_classdev *led_cdev, enum led_brightness value)
+static void gta01vib_vib_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
{
struct gta01_vib_priv *vp = to_vpriv(led_cdev);
- if (value)
- s3c2410_gpio_setpin(vp->gpio, 1);
- else
- s3c2410_gpio_setpin(vp->gpio, 0);
+ /*
+ * value == 255 -> 99% duty cycle (full voltage)
+ * value == 128 -> 50% duty cycle (middle voltage)
+ * value == 0 -> 0% duty cycle (zero voltage)
+ */
+ mutex_lock(&vp->mutex);
+ if (vp->has_pwm) {
+ printk(KERN_INFO "updated duty cycle: %d\n", value);
+ s3c2410_pwm_duty_cycle(value, vp->pwm);
+ s3c2410_gpio_cfgpin(vp->gpio, S3C2410_GPB3_TOUT3);
+ } else {
+ if (value)
+ s3c2410_gpio_setpin(vp->gpio, 1);
+ else
+ s3c2410_gpio_setpin(vp->gpio, 0);
+ }
+
+ mutex_unlock(&vp->mutex);
}
static struct led_classdev gta01_vib_led = {
@@ -66,7 +88,23 @@ static int gta01vib_resume(struct platfo
}
#endif
-static int gta01vib_probe(struct platform_device *pdev)
+static void gta01vib_init_hw(struct platform_device *pdev)
+{
+ struct gta01_vib_priv *vp = pdev_to_vpriv(pdev);
+
+ vp->pwm->timerid= PWM3;
+ vp->pwm->prescaler = 0x0000;
+ vp->pwm->divider = S3C2410_TCFG1_MUX3_DIV8;
+ vp->pwm->counter = COUNTER;
+ vp->pwm->comparer = COUNTER;
+
+ s3c2410_pwm_enable(vp->pwm);
+ s3c2410_pwm_start(vp->pwm);
+
+ return;
+}
+
+static int __init gta01vib_probe(struct platform_device *pdev)
{
struct gta01_vib_priv *vp;
struct resource *r;
@@ -86,9 +124,23 @@ static int gta01vib_probe(struct platfor
vp->gpio = r->start;
- if (vp->gpio == S3C2410_GPB3)
+ /* TOUT3 */
+ if (vp->gpio == S3C2410_GPB3) {
vp->has_pwm = 1;
+ vp->pwm = s3c2410_pwm_alloc();
+ if (!vp->pwm) {
+ printk(KERN_WARNING "PWM enabling failed.\n");
+ return -1;
+ }
+
+ gta01vib_init_hw(pdev);
+ }
+
+ mutex_init(&vp->mutex);
+
+ printk(KERN_INFO "GTA01 Vibrator Driver Initialized.\n");
+
return led_classdev_register(&pdev->dev, >a01_vib_led);
}
@@ -96,10 +148,17 @@ static int gta01vib_remove(struct platfo
{
struct gta01_vib_priv *vp = pdev_to_vpriv(pdev);
+ if (vp->has_pwm)
+ s3c2410_pwm_disable(vp->pwm);
+
led_classdev_unregister(>a01_vib_led);
platform_set_drvdata(pdev, NULL);
kfree(vp);
+ mutex_destroy(&vp->mutex);
+
+ printk(KERN_INFO "GTA01 Vibrator Driver Unloaded\n");
+
return 0;
}