forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
leds: simple driver for pwm driven LEDs
Add a simple driver for pwm driver LEDs. pwm_id and period can be defined in board file. It is developed for pxa, however it is probably generic enough to be used on other platforms with pwm. Signed-off-by: Luotao Fu <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Richard Purdie <[email protected]>
- Loading branch information
Showing
4 changed files
with
181 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
/* | ||
* linux/drivers/leds-pwm.c | ||
* | ||
* simple PWM based LED control | ||
* | ||
* Copyright 2009 Luotao Fu @ Pengutronix ([email protected]) | ||
* | ||
* based on leds-gpio.c by Raphael Assenat <[email protected]> | ||
* | ||
* 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 <linux/module.h> | ||
#include <linux/kernel.h> | ||
#include <linux/init.h> | ||
#include <linux/platform_device.h> | ||
#include <linux/fb.h> | ||
#include <linux/leds.h> | ||
#include <linux/err.h> | ||
#include <linux/pwm.h> | ||
#include <linux/leds_pwm.h> | ||
|
||
struct led_pwm_data { | ||
struct led_classdev cdev; | ||
struct pwm_device *pwm; | ||
unsigned int active_low; | ||
unsigned int period; | ||
unsigned int max_brightness; | ||
}; | ||
|
||
static void led_pwm_set(struct led_classdev *led_cdev, | ||
enum led_brightness brightness) | ||
{ | ||
struct led_pwm_data *led_dat = | ||
container_of(led_cdev, struct led_pwm_data, cdev); | ||
unsigned int max = led_dat->max_brightness; | ||
unsigned int period = led_dat->period; | ||
|
||
if (brightness == 0) { | ||
pwm_config(led_dat->pwm, 0, period); | ||
pwm_disable(led_dat->pwm); | ||
} else { | ||
pwm_config(led_dat->pwm, brightness * period / max, period); | ||
pwm_enable(led_dat->pwm); | ||
} | ||
} | ||
|
||
static int led_pwm_probe(struct platform_device *pdev) | ||
{ | ||
struct led_pwm_platform_data *pdata = pdev->dev.platform_data; | ||
struct led_pwm *cur_led; | ||
struct led_pwm_data *leds_data, *led_dat; | ||
int i, ret = 0; | ||
|
||
if (!pdata) | ||
return -EBUSY; | ||
|
||
leds_data = kzalloc(sizeof(struct led_pwm_data) * pdata->num_leds, | ||
GFP_KERNEL); | ||
if (!leds_data) | ||
return -ENOMEM; | ||
|
||
for (i = 0; i < pdata->num_leds; i++) { | ||
cur_led = &pdata->leds[i]; | ||
led_dat = &leds_data[i]; | ||
|
||
led_dat->pwm = pwm_request(cur_led->pwm_id, | ||
cur_led->name); | ||
if (IS_ERR(led_dat->pwm)) { | ||
dev_err(&pdev->dev, "unable to request PWM %d\n", | ||
cur_led->pwm_id); | ||
goto err; | ||
} | ||
|
||
led_dat->cdev.name = cur_led->name; | ||
led_dat->cdev.default_trigger = cur_led->default_trigger; | ||
led_dat->active_low = cur_led->active_low; | ||
led_dat->max_brightness = cur_led->max_brightness; | ||
led_dat->period = cur_led->pwm_period_ns; | ||
led_dat->cdev.brightness_set = led_pwm_set; | ||
led_dat->cdev.brightness = LED_OFF; | ||
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; | ||
|
||
ret = led_classdev_register(&pdev->dev, &led_dat->cdev); | ||
if (ret < 0) { | ||
pwm_free(led_dat->pwm); | ||
goto err; | ||
} | ||
} | ||
|
||
platform_set_drvdata(pdev, leds_data); | ||
|
||
return 0; | ||
|
||
err: | ||
if (i > 0) { | ||
for (i = i - 1; i >= 0; i--) { | ||
led_classdev_unregister(&leds_data[i].cdev); | ||
pwm_free(leds_data[i].pwm); | ||
} | ||
} | ||
|
||
kfree(leds_data); | ||
|
||
return ret; | ||
} | ||
|
||
static int __devexit led_pwm_remove(struct platform_device *pdev) | ||
{ | ||
int i; | ||
struct led_pwm_platform_data *pdata = pdev->dev.platform_data; | ||
struct led_pwm_data *leds_data; | ||
|
||
leds_data = platform_get_drvdata(pdev); | ||
|
||
for (i = 0; i < pdata->num_leds; i++) { | ||
led_classdev_unregister(&leds_data[i].cdev); | ||
pwm_free(leds_data[i].pwm); | ||
} | ||
|
||
kfree(leds_data); | ||
|
||
return 0; | ||
} | ||
|
||
static struct platform_driver led_pwm_driver = { | ||
.probe = led_pwm_probe, | ||
.remove = __devexit_p(led_pwm_remove), | ||
.driver = { | ||
.name = "leds_pwm", | ||
.owner = THIS_MODULE, | ||
}, | ||
}; | ||
|
||
static int __init led_pwm_init(void) | ||
{ | ||
return platform_driver_register(&led_pwm_driver); | ||
} | ||
|
||
static void __exit led_pwm_exit(void) | ||
{ | ||
platform_driver_unregister(&led_pwm_driver); | ||
} | ||
|
||
module_init(led_pwm_init); | ||
module_exit(led_pwm_exit); | ||
|
||
MODULE_AUTHOR("Luotao Fu <[email protected]>"); | ||
MODULE_DESCRIPTION("PWM LED driver for PXA"); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_ALIAS("platform:leds-pwm"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* | ||
* PWM LED driver data - see drivers/leds/leds-pwm.c | ||
*/ | ||
#ifndef __LINUX_LEDS_PWM_H | ||
#define __LINUX_LEDS_PWM_H | ||
|
||
struct led_pwm { | ||
const char *name; | ||
const char *default_trigger; | ||
unsigned pwm_id; | ||
u8 active_low; | ||
unsigned max_brightness; | ||
unsigned pwm_period_ns; | ||
}; | ||
|
||
struct led_pwm_platform_data { | ||
int num_leds; | ||
struct led_pwm *leds; | ||
}; | ||
|
||
#endif |