leds: aw2013_led: disable regulators when not needed

Turn off the LED regulators if brightness of all the LEDs that are
connected to the host is 0. This change is required to save the power
consumption.

Change-Id: I9bae343becb9a794a5ecc8ddf9c2edb3b5aecfce
Signed-off-by: Mao Li <maol@codeaurora.org>
This commit is contained in:
Mao Li 2015-03-18 05:37:24 -04:00
parent 4eb1898db5
commit 379ac98297
1 changed files with 30 additions and 96 deletions

View File

@ -61,7 +61,6 @@ struct aw2013_led {
struct regulator *vcc;
int num_leds;
int id;
bool suspended;
bool poweron;
};
@ -206,16 +205,17 @@ static void aw2013_brightness_work(struct work_struct *work)
brightness_work);
u8 val;
mutex_lock(&led->pdata->led->lock);
/* enable regulators if they are disabled */
if (!led->pdata->led->poweron) {
if (aw2013_power_on(led->pdata->led, true)) {
dev_err(&led->pdata->led->client->dev, "power on failed");
mutex_unlock(&led->pdata->led->lock);
return;
}
}
mutex_lock(&led->pdata->led->lock);
if (led->cdev.brightness > 0) {
if (led->cdev.brightness > led->cdev.max_brightness)
led->cdev.brightness = led->cdev.max_brightness;
@ -232,6 +232,20 @@ static void aw2013_brightness_work(struct work_struct *work)
aw2013_write(led, AW_REG_LED_ENABLE, val & (~(1 << led->id)));
}
aw2013_read(led, AW_REG_LED_ENABLE, &val);
/*
* If value in AW_REG_LED_ENABLE is 0, it means the RGB leds are
* all off. So we need to power it off.
*/
if (val == 0) {
if (aw2013_power_on(led->pdata->led, false)) {
dev_err(&led->pdata->led->client->dev,
"power off failed");
mutex_unlock(&led->pdata->led->lock);
return;
}
}
mutex_unlock(&led->pdata->led->lock);
}
@ -269,6 +283,19 @@ static void aw2013_led_blink_set(struct aw2013_led *led, unsigned long blinking)
aw2013_read(led, AW_REG_LED_ENABLE, &val);
aw2013_write(led, AW_REG_LED_ENABLE, val & (~(1 << led->id)));
}
aw2013_read(led, AW_REG_LED_ENABLE, &val);
/*
* If value in AW_REG_LED_ENABLE is 0, it means the RGB leds are
* all off. So we need to power it off.
*/
if (val == 0) {
if (aw2013_power_on(led->pdata->led, false)) {
dev_err(&led->pdata->led->client->dev,
"power off failed");
return;
}
}
}
static void aw2013_set_brightness(struct led_classdev *cdev,
@ -365,88 +392,6 @@ static int aw_2013_check_chipid(struct aw2013_led *led)
return -EINVAL;
}
#ifdef CONFIG_PM
static int aw2013_led_suspend(struct device *dev)
{
struct aw2013_led *led = dev_get_drvdata(dev);
int ret = 0;
u8 val;
if (led->suspended) {
dev_info(dev, "Already in suspend state\n");
return 0;
}
mutex_lock(&led->lock);
aw2013_read(led, AW_REG_LED_ENABLE, &val);
/*
* If value in AW_REG_LED_ENABLE is 0, it means the RGB leds are
* all off. So we need to power it off.
* If value in AW_REG_LED_ENABLE is not 0, that means LEDs are
* already turned on by upper layer, we keep them alive during
* suspend so as to support screen-off notification LED.
*/
if (val == 0) {
ret = aw2013_power_on(led, false);
if (ret) {
dev_err(dev, "power off failed");
mutex_unlock(&led->lock);
return ret;
}
}
led->suspended = true;
mutex_unlock(&led->lock);
return ret;
}
static int aw2013_led_resume(struct device *dev)
{
struct aw2013_led *led = dev_get_drvdata(dev);
int ret = 0;
if (!led->suspended) {
dev_info(dev, "Already in awake state\n");
return 0;
}
mutex_lock(&led->lock);
if (led->poweron) {
led->suspended = false;
mutex_unlock(&led->lock);
return 0;
}
ret = aw2013_power_on(led, true);
if (ret) {
dev_err(dev, "power on failed");
mutex_unlock(&led->lock);
return ret;
}
led->suspended = false;
mutex_unlock(&led->lock);
return ret;
}
static const struct dev_pm_ops aw2013_led_pm_ops = {
.suspend = aw2013_led_suspend,
.resume = aw2013_led_resume,
};
#else
static int aw2013_led_suspend(struct device *dev)
{
return 0;
}
static int aw2013_led_resume(struct device *dev)
{
return 0;
}
static const struct dev_pm_ops aw2013_led_pm_ops = {
};
#endif
static int aw2013_led_err_handle(struct aw2013_led *led_array,
int parsed_leds)
{
@ -642,16 +587,8 @@ static int aw2013_led_probe(struct i2c_client *client,
goto fail_parsed_node;
}
ret = aw2013_power_on(led_array, true);
if (ret) {
dev_err(&client->dev, "power on failed");
goto pwr_deinit;
}
return 0;
pwr_deinit:
aw2013_power_init(led_array, false);
fail_parsed_node:
aw2013_led_err_handle(led_array, num_leds);
free_led_arry:
@ -699,9 +636,6 @@ static struct i2c_driver aw2013_led_driver = {
.name = "aw2013_led",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(aw2013_match_table),
#ifdef CONFIG_PM
.pm = &aw2013_led_pm_ops,
#endif
},
.id_table = aw2013_led_id,
};