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

Commit e54c87fe authored by Subbaraman Narayanamurthy's avatar Subbaraman Narayanamurthy
Browse files

leds: qti-tri-led: Control BOB_CONFIG_EXT_CTRL2_FORCE_EN for HR_LED



As per the hardware recommendation, BOB_CONFIG_EXT_CTRL2_FORCE_EN
needs to be controlled before enabling or disabling HR_LEDs.
Add support for that by doing PBS trigger through SDAM which is
available as a nvmem device.

Change-Id: Iaae6f5b86c7db014c2cbdf53054d7e3ac869c283
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent 7804c835
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -13,6 +13,18 @@ Qualcomm Technologies, Inc. PMIC chips.
	Value type: <prop-encoded-array>
	Definition: Register base of the TRI_LED module and length.

- nvmem-names:
	Usage: optional
	Value type: <string>
	Definition: Nvmem device name for SDAM to do PBS trigger. It must be
		defined as "pbs_sdam". This is required only for HR_LEDs.

- nvmem:
	Usage: optional
	Value type: <phandle>
	Definition: Phandle of the nvmem device name to access SDAM to do PBS
		trigger. This is required only for HR_LEDs.

Properties for child nodes:
- pwms:
	Usage: required
+69 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/nvmem-consumer.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
@@ -72,10 +73,12 @@ struct qpnp_tri_led_chip {
	struct device		*dev;
	struct regmap		*regmap;
	struct qpnp_led_dev	*leds;
	struct nvmem_device	*pbs_nvmem;
	struct mutex		bus_lock;
	int			num_leds;
	u16			reg_base;
	u8			subtype;
	u8			bitmap;
};

static int qpnp_tri_led_read(struct qpnp_tri_led_chip *chip, u16 addr, u8 *val)
@@ -128,10 +131,16 @@ static int __tri_led_config_pwm(struct qpnp_led_dev *led,
	return rc;
}

#define PBS_ENABLE	1
#define PBS_DISABLE	2
#define PBS_ARG		0x42
#define PBS_TRIG_CLR	0xE6
#define PBS_TRIG_SET	0xE5
static int __tri_led_set(struct qpnp_led_dev *led)
{
	int rc = 0;
	u8 val = 0, mask = 0;
	u8 val = 0, mask = 0, pbs_val;
	u8 prev_bitmap;

	rc = __tri_led_config_pwm(led, &led->pwm_setting);
	if (rc < 0) {
@@ -147,6 +156,51 @@ static int __tri_led_set(struct qpnp_led_dev *led)
	else
		val = mask;

	if (led->chip->subtype == TRILED_SUBTYPE_LED2H0L12 &&
		led->chip->pbs_nvmem) {
		/*
		 * Control BOB_CONFIG_EXT_CTRL2_FORCE_EN for HR_LED through
		 * PBS trigger. PBS trigger for enable happens if any one of
		 * LEDs are turned on. PBS trigger for disable happens only
		 * if both LEDs are turned off.
		 */

		prev_bitmap = led->chip->bitmap;
		if (val)
			led->chip->bitmap |= (1 << led->id);
		else
			led->chip->bitmap &= ~(1 << led->id);

		if (!(led->chip->bitmap & prev_bitmap)) {
			pbs_val = led->chip->bitmap ? PBS_ENABLE : PBS_DISABLE;
			rc = nvmem_device_write(led->chip->pbs_nvmem, PBS_ARG,
				1, &pbs_val);
			if (rc < 0) {
				dev_err(led->chip->dev, "Couldn't set PBS_ARG, rc=%d\n",
					rc);
				return rc;
			}

			pbs_val = 1;
			rc = nvmem_device_write(led->chip->pbs_nvmem,
				PBS_TRIG_CLR, 1, &pbs_val);
			if (rc < 0) {
				dev_err(led->chip->dev, "Couldn't set PBS_TRIG_CLR, rc=%d\n",
					rc);
				return rc;
			}

			pbs_val = 1;
			rc = nvmem_device_write(led->chip->pbs_nvmem,
				PBS_TRIG_SET, 1, &pbs_val);
			if (rc < 0) {
				dev_err(led->chip->dev, "Couldn't set PBS_TRIG_SET, rc=%d\n",
					rc);
				return rc;
			}
		}
	}

	rc = qpnp_tri_led_masked_write(led->chip, TRILED_REG_EN_CTL,
							mask, val);
	if (rc < 0)
@@ -379,6 +433,20 @@ static int qpnp_tri_led_parse_dt(struct qpnp_tri_led_chip *chip)
		return -EINVAL;
	}

	if (of_find_property(chip->dev->of_node, "nvmem", NULL)) {
		chip->pbs_nvmem = devm_nvmem_device_get(chip->dev, "pbs_sdam");
		if (IS_ERR_OR_NULL(chip->pbs_nvmem)) {
			rc = PTR_ERR(chip->pbs_nvmem);
			if (rc != -EPROBE_DEFER) {
				dev_err(chip->dev, "Couldn't get nvmem device, rc=%d\n",
					rc);
				return -ENODEV;
			}
			chip->pbs_nvmem = NULL;
			return rc;
		}
	}

	chip->leds = devm_kcalloc(chip->dev, chip->num_leds,
			sizeof(struct qpnp_led_dev), GFP_KERNEL);
	if (!chip->leds)