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:
parent
4eb1898db5
commit
379ac98297
|
@ -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,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue