From a65837dce6a2d4061ebfccfb6a8e4234b5c98ef5 Mon Sep 17 00:00:00 2001 From: mokopatches Date: Wed, 19 Nov 2008 17:03:16 +0000 Subject: gta02-leds.patch --- drivers/leds/Kconfig | 6 + drivers/leds/Makefile | 1 + drivers/leds/leds-neo1973-gta02.c | 226 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 drivers/leds/leds-neo1973-gta02.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 8f41ae002d1..4435859beca 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -171,6 +171,12 @@ config LEDS_NEO1973_VIBRATOR help This option enables support for the vibrator on the FIC Neo1973. +config LEDS_NEO1973_GTA02 + tristate "LED Support for the FIC Neo1973 (GTA02)" + depends on LEDS_CLASS && MACH_NEO1973_GTA02 + help + This option enables support for the LEDs on the FIC Neo1973. + comment "LED Triggers" config LEDS_TRIGGERS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index a2a92bdcf6a..40bd128f2de 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o obj-$(CONFIG_LEDS_HP_DISK) += leds-hp-disk.o obj-$(CONFIG_LEDS_NEO1973_VIBRATOR) += leds-neo1973-vibrator.o +obj-$(CONFIG_LEDS_NEO1973_GTA02) += leds-neo1973-gta02.o # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/drivers/leds/leds-neo1973-gta02.c b/drivers/leds/leds-neo1973-gta02.c new file mode 100644 index 00000000000..bf1d5407025 --- /dev/null +++ b/drivers/leds/leds-neo1973-gta02.c @@ -0,0 +1,226 @@ +/* + * LED driver for the FIC Neo1973 GTA02 GSM phone + * + * (C) 2006-2007 by OpenMoko, Inc. + * Author: Harald Welte + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_LEDS 3 +#define COUNTER 256 + +struct gta02_led_priv +{ + struct mutex mutex; + struct led_classdev cdev; + struct s3c2410_pwm pwm; + unsigned int gpio; + unsigned int has_pwm; +}; + +struct gta02_led_bundle +{ + int num_leds; + struct gta02_led_priv led[MAX_LEDS]; +}; + +static inline struct gta02_led_priv *to_priv(struct led_classdev *led_cdev) +{ + return container_of(led_cdev, struct gta02_led_priv, cdev); +} + +static inline struct gta02_led_bundle *to_bundle(struct led_classdev *led_cdev) +{ + return dev_get_drvdata(led_cdev->dev); +} + +static void gta02led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct gta02_led_priv *lp = to_priv(led_cdev); + + /* + * value == 255 -> 99% duty cycle (full power) + * value == 128 -> 50% duty cycle (medium power) + * value == 0 -> 0% duty cycle (zero power) + */ + mutex_lock(&lp->mutex); + if (lp->has_pwm) { + s3c2410_pwm_duty_cycle(value, &lp->pwm); + } else { + if (value) + s3c2410_gpio_setpin(lp->gpio, 1); + else + s3c2410_gpio_setpin(lp->gpio, 0); + } + mutex_unlock(&lp->mutex); +} + +#ifdef CONFIG_PM +static int gta02led_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct gta02_led_bundle *bundle = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < bundle->num_leds; i++) + led_classdev_suspend(&bundle->led[i].cdev); + + return 0; +} + +static int gta02led_resume(struct platform_device *pdev) +{ + struct gta02_led_bundle *bundle = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < bundle->num_leds; i++) + led_classdev_resume(&bundle->led[i].cdev); + + return 0; +} +#endif + +static int __init gta02led_probe(struct platform_device *pdev) +{ + int i, rc; + struct gta02_led_bundle *bundle; + + if (!machine_is_neo1973_gta02()) + return -EIO; + + bundle = kzalloc(sizeof(struct gta02_led_bundle), GFP_KERNEL); + if (!bundle) + return -ENOMEM; + platform_set_drvdata(pdev, bundle); + + for (i = 0; i < pdev->num_resources; i++) { + struct gta02_led_priv *lp; + struct resource *r; + + if (i >= MAX_LEDS) + break; + + r = platform_get_resource(pdev, 0, i); + if (!r || !r->start || !r->name) + continue; + + lp = &bundle->led[i]; + + lp->gpio = r->start; + lp->cdev.name = r->name; + lp->cdev.brightness_set = gta02led_set; + + switch (lp->gpio) { + case S3C2410_GPB0: + lp->has_pwm = 1; + lp->pwm.timerid = PWM0; + s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB0_TOUT0); + break; + case S3C2410_GPB1: + lp->has_pwm = 1; + lp->pwm.timerid = PWM1; + s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB1_TOUT1); + break; + case S3C2410_GPB2: + lp->has_pwm = 1; + lp->pwm.timerid = PWM2; + s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB2_TOUT2); + break; + case S3C2410_GPB3: + lp->has_pwm = 1; + lp->pwm.timerid = PWM3; + s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPB3_TOUT3); + break; + default: + break; + } + + lp->pwm.prescaler = 0; + lp->pwm.divider = S3C2410_TCFG1_MUX3_DIV8; + lp->pwm.counter = COUNTER; + lp->pwm.comparer = COUNTER; + s3c2410_pwm_enable(&lp->pwm); + s3c2410_pwm_start(&lp->pwm); + + switch (lp->gpio) { + case S3C2410_GPB0: + case S3C2410_GPB1: + case S3C2410_GPB2: + lp->has_pwm = 0; + s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPIO_OUTPUT); + s3c2410_gpio_setpin(lp->gpio, 0); + break; + default: + break; + } + + mutex_init(&lp->mutex); + rc = led_classdev_register(&pdev->dev, &lp->cdev); + } + + return 0; +} + +static int gta02led_remove(struct platform_device *pdev) +{ + struct gta02_led_bundle *bundle = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < bundle->num_leds; i++) { + struct gta02_led_priv *lp = &bundle->led[i]; + if (lp->has_pwm) + s3c2410_pwm_disable(&lp->pwm); + + led_classdev_unregister(&lp->cdev); + mutex_destroy(&lp->mutex); + } + + platform_set_drvdata(pdev, NULL); + kfree(bundle); + + return 0; +} + +static struct platform_driver gta02led_driver = { + .probe = gta02led_probe, + .remove = gta02led_remove, +#ifdef CONFIG_PM + .suspend = gta02led_suspend, + .resume = gta02led_resume, +#endif + .driver = { + .name = "gta02-led", + }, +}; + +static int __init gta02led_init(void) +{ + return platform_driver_register(>a02led_driver); +} + +static void __exit gta02led_exit(void) +{ + platform_driver_unregister(>a02led_driver); +} + +module_init(gta02led_init); +module_exit(gta02led_exit); + +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("FIC Neo1973 GTA02 LED driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3