Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5fe15c5f authored by Mao Li's avatar Mao Li Committed by Shantanu Jain
Browse files

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.

This patch is propagated from msm-3.10 kernel.
(commit: I9bae343becb9a794a5ecc8ddf9c2edb3b5aecfce)
leds: aw2013_led: disable regulators when not needed

Change-Id: I9bae343becb9a794a5ecc8ddf9c2edb3b5aecfce
Signed-off-by: default avatarMao Li <maol@codeaurora.org>
Signed-off-by: default avatarShantanu Jain <shjain@codeaurora.org>
parent e33d58ed
Loading
Loading
Loading
Loading
+30 −96
Original line number Diff line number Diff line
@@ -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,
@@ -366,88 +393,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,
};