-
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: da903x: Add support for LEDs found on DA9030/DA9034
Signed-off-by: Mike Rapoport <mike@compulab.co.il> Signed-off-by: Eric Miao <eric.miao@marvell.com> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
- Loading branch information
Mike Rapoport
authored and
Richard Purdie
committed
Oct 20, 2008
1 parent
6da0b38
commit 9e84561
Showing
3 changed files
with
183 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,175 @@ | ||
/* | ||
* LEDs driver for Dialog Semiconductor DA9030/DA9034 | ||
* | ||
* Copyright (C) 2008 Compulab, Ltd. | ||
* Mike Rapoport <mike@compulab.co.il> | ||
* | ||
* Copyright (C) 2006-2008 Marvell International Ltd. | ||
* Eric Miao <eric.miao@marvell.com> | ||
* | ||
* 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/leds.h> | ||
#include <linux/mfd/da903x.h> | ||
|
||
#define DA9030_LED1_CONTROL 0x20 | ||
#define DA9030_LED2_CONTROL 0x21 | ||
#define DA9030_LED3_CONTROL 0x22 | ||
#define DA9030_LED4_CONTROL 0x23 | ||
#define DA9030_LEDPC_CONTROL 0x24 | ||
#define DA9030_MISC_CONTROL_A 0x26 /* Vibrator Control */ | ||
|
||
#define DA9034_LED1_CONTROL 0x35 | ||
#define DA9034_LED2_CONTROL 0x36 | ||
#define DA9034_VIBRA 0x40 | ||
|
||
struct da903x_led { | ||
struct led_classdev cdev; | ||
struct work_struct work; | ||
struct device *master; | ||
enum led_brightness new_brightness; | ||
int id; | ||
int flags; | ||
}; | ||
|
||
#define DA9030_LED_OFFSET(id) ((id) - DA9030_ID_LED_1) | ||
#define DA9034_LED_OFFSET(id) ((id) - DA9034_ID_LED_1) | ||
|
||
static void da903x_led_work(struct work_struct *work) | ||
{ | ||
struct da903x_led *led = container_of(work, struct da903x_led, work); | ||
uint8_t val; | ||
int offset; | ||
|
||
switch (led->id) { | ||
case DA9030_ID_LED_1: | ||
case DA9030_ID_LED_2: | ||
case DA9030_ID_LED_3: | ||
case DA9030_ID_LED_4: | ||
case DA9030_ID_LED_PC: | ||
offset = DA9030_LED_OFFSET(led->id); | ||
val = led->flags & ~0x87; | ||
val |= (led->new_brightness) ? 0x80 : 0; /* EN bit */ | ||
val |= (led->new_brightness >> 5) & 0x7; /* PWM<2:0> */ | ||
da903x_write(led->master, DA9030_LED1_CONTROL + offset, val); | ||
break; | ||
case DA9030_ID_VIBRA: | ||
val = led->flags & ~0x80; | ||
val |= (led->new_brightness) ? 0x80 : 0; /* EN bit */ | ||
da903x_write(led->master, DA9030_MISC_CONTROL_A, val); | ||
break; | ||
case DA9034_ID_LED_1: | ||
case DA9034_ID_LED_2: | ||
offset = DA9034_LED_OFFSET(led->id); | ||
val = (led->new_brightness * 0x5f / LED_FULL) & 0x7f; | ||
val |= (led->flags & DA9034_LED_RAMP) ? 0x80 : 0; | ||
da903x_write(led->master, DA9034_LED1_CONTROL + offset, val); | ||
break; | ||
case DA9034_ID_VIBRA: | ||
val = led->new_brightness & 0xfe; | ||
da903x_write(led->master, DA9034_VIBRA, val); | ||
break; | ||
} | ||
} | ||
|
||
static void da903x_led_set(struct led_classdev *led_cdev, | ||
enum led_brightness value) | ||
{ | ||
struct da903x_led *led; | ||
|
||
led = container_of(led_cdev, struct da903x_led, cdev); | ||
led->new_brightness = value; | ||
schedule_work(&led->work); | ||
} | ||
|
||
static int __devinit da903x_led_probe(struct platform_device *pdev) | ||
{ | ||
struct led_info *pdata = pdev->dev.platform_data; | ||
struct da903x_led *led; | ||
int id, ret; | ||
|
||
if (pdata == NULL) | ||
return 0; | ||
|
||
id = pdev->id; | ||
|
||
if (!((id >= DA9030_ID_LED_1 && id <= DA9030_ID_VIBRA) || | ||
(id >= DA9034_ID_LED_1 && id <= DA9034_ID_VIBRA))) { | ||
dev_err(&pdev->dev, "invalid LED ID (%d) specified\n", id); | ||
return -EINVAL; | ||
} | ||
|
||
led = kzalloc(sizeof(struct da903x_led), GFP_KERNEL); | ||
if (led == NULL) { | ||
dev_err(&pdev->dev, "failed to alloc memory for LED%d\n", id); | ||
return -ENOMEM; | ||
} | ||
|
||
led->cdev.name = pdata->name; | ||
led->cdev.default_trigger = pdata->default_trigger; | ||
led->cdev.brightness_set = da903x_led_set; | ||
led->cdev.brightness = LED_OFF; | ||
|
||
led->id = id; | ||
led->flags = pdata->flags; | ||
led->master = pdev->dev.parent; | ||
led->new_brightness = LED_OFF; | ||
|
||
INIT_WORK(&led->work, da903x_led_work); | ||
|
||
ret = led_classdev_register(led->master, &led->cdev); | ||
if (ret) { | ||
dev_err(&pdev->dev, "failed to register LED %d\n", id); | ||
goto err; | ||
} | ||
|
||
platform_set_drvdata(pdev, led); | ||
return 0; | ||
|
||
err: | ||
kfree(led); | ||
return ret; | ||
} | ||
|
||
static int __devexit da903x_led_remove(struct platform_device *pdev) | ||
{ | ||
struct da903x_led *led = platform_get_drvdata(pdev); | ||
|
||
led_classdev_unregister(&led->cdev); | ||
kfree(led); | ||
return 0; | ||
} | ||
|
||
static struct platform_driver da903x_led_driver = { | ||
.driver = { | ||
.name = "da903x-led", | ||
.owner = THIS_MODULE, | ||
}, | ||
.probe = da903x_led_probe, | ||
.remove = __devexit_p(da903x_led_remove), | ||
}; | ||
|
||
static int __init da903x_led_init(void) | ||
{ | ||
return platform_driver_register(&da903x_led_driver); | ||
} | ||
module_init(da903x_led_init); | ||
|
||
static void __exit da903x_led_exit(void) | ||
{ | ||
platform_driver_unregister(&da903x_led_driver); | ||
} | ||
module_exit(da903x_led_exit); | ||
|
||
MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034"); | ||
MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>" | ||
"Mike Rapoport <mike@compulab.co.il>"); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_ALIAS("platform:da903x-led"); |