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

Commit fef9e150 authored by Amy Maloche's avatar Amy Maloche
Browse files

leds: leds-qpnp: Avoid OVP spike when disabling wled



Implement software workaround to avoid OVP spike when
WLED module is disabled.

Change-Id: I8468c4d2f0f82ab642932ea0a9c1d4687cc3d3db
Signed-off-by: default avatarAmy Maloche <amaloche@codeaurora.org>
parent 14a5d3a3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -23,7 +23,8 @@ WLED is primarily used as display backlight. Display subsystem uses
LED triggers for WLED to control the brightness as needed.

Optional properties for WLED:
- qcom,num-strings: number of wled strings supported
- qcom,num-strings: number of wled strings to be configured
- qcom,num-physical-strings: number of physical wled strings supported
- qcom,ovp-val: over voltage protection threshold,
		follows enum wled_ovp_threshold
- qcom,boost-curr-lim: boot currnet limit, follows enum wled_current_bost_limit
+1 −0
Original line number Diff line number Diff line
@@ -295,6 +295,7 @@
			qcom,switch-freq = <11>;
			qcom,ovp-val = <2>;
			qcom,num-strings = <3>;
			qcom,num-physical-strings = <3>;
			qcom,id = <0>;
		};
	};
+1 −0
Original line number Diff line number Diff line
@@ -293,6 +293,7 @@
			qcom,switch-freq = <11>;
			qcom,ovp-val = <2>;
			qcom,num-strings = <3>;
			qcom,num-physical-strings = <3>;
			qcom,id = <0>;
		};
	};
+1 −0
Original line number Diff line number Diff line
@@ -234,6 +234,7 @@
			qcom,switch-freq = <11>;
			qcom,ovp-val = <2>;
			qcom,num-strings = <3>;
			qcom,num-physical-strings = <3>;
			qcom,id = <0>;
		};
	};
+118 −3
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#define WLED_MOD_SRC_SEL_REG(base, n)	(WLED_FULL_SCALE_REG(base, n) + 0x01)

/* wled control registers */
#define WLED_OVP_INT_STATUS(base)		(base + 0x10)
#define WLED_BRIGHTNESS_CNTL_LSB(base, n)	(base + 0x40 + 2*n)
#define WLED_BRIGHTNESS_CNTL_MSB(base, n)	(base + 0x41 + 2*n)
#define WLED_MOD_CTRL_REG(base)			(base + 0x46)
@@ -46,8 +47,10 @@
#define WLED_CURR_SINK_MASK		0xE0
#define WLED_CURR_SINK_SHFT		0x05
#define WLED_DISABLE_ALL_SINKS		0x00
#define WLED_DISABLE_1_2_SINKS		0x80
#define WLED_SWITCH_FREQ_MASK		0x0F
#define WLED_OVP_VAL_MASK		0x03
#define WLED_OVP_INT_MASK		0x02
#define WLED_OVP_VAL_BIT_SHFT		0x00
#define WLED_BOOST_LIMIT_MASK		0x07
#define WLED_BOOST_LIMIT_BIT_SHFT	0x00
@@ -63,12 +66,16 @@
#define WLED_MAX_CURR			25
#define WLED_NO_CURRENT			0x00
#define WLED_OVP_DELAY			1000
#define WLED_OVP_DELAY_INT		200
#define WLED_OVP_DELAY_LOOP		100
#define WLED_MSB_MASK			0x0F
#define WLED_MAX_CURR_MASK		0x1F
#define WLED_OP_FDBCK_MASK		0x07
#define WLED_OP_FDBCK_BIT_SHFT		0x00
#define WLED_OP_FDBCK_DEFAULT		0x00

#define WLED_SET_ILIM_CODE		0x01

#define WLED_MAX_LEVEL			4095
#define WLED_8_BIT_MASK			0xFF
#define WLED_4_BIT_MASK			0x0F
@@ -79,9 +86,12 @@
#define WLED_SYNC_RESET_VAL		0x00

#define PMIC_VER_8026			0x04
#define PMIC_VER_8941			0x01
#define PMIC_VERSION_REG		0x0105

#define WLED_DEFAULT_STRINGS		0x01
#define WLED_THREE_STRINGS		0x03
#define WLED_MAX_TRIES			5
#define WLED_DEFAULT_OVP_VAL		0x02
#define WLED_BOOST_LIM_DEFAULT		0x03
#define WLED_CP_SEL_DEFAULT		0x00
@@ -332,7 +342,8 @@ struct pwm_config_data {

/**
 *  wled_config_data - wled configuration data
 *  @num_strings - number of wled strings supported
 *  @num_strings - number of wled strings to be configured
 *  @num_physical_strings - physical number of strings supported
 *  @ovp_val - over voltage protection threshold
 *  @boost_curr_lim - boot current limit
 *  @cp_select - high pole capacitance
@@ -343,6 +354,7 @@ struct pwm_config_data {
 */
struct wled_config_data {
	u8	num_strings;
	u8	num_physical_strings;
	u8	ovp_val;
	u8	boost_curr_lim;
	u8	cp_select;
@@ -552,8 +564,8 @@ static int qpnp_wled_sync(struct qpnp_led_data *led)

static int qpnp_wled_set(struct qpnp_led_data *led)
{
	int rc, duty, level;
	u8 val, i, num_wled_strings, sink_val;
	int rc, duty, level, tries = 0;
	u8 val, i, num_wled_strings, sink_val, ilim_val, ovp_val;

	num_wled_strings = led->wled_cfg->num_strings;

@@ -601,8 +613,75 @@ static int qpnp_wled_set(struct qpnp_led_data *led)
				return rc;
			}

			usleep(WLED_OVP_DELAY);
		} else if (led->wled_cfg->pmic_version == PMIC_VER_8941) {
			if (led->wled_cfg->num_physical_strings <=
					WLED_THREE_STRINGS) {
				val = WLED_DISABLE_1_2_SINKS;
				rc = spmi_ext_register_writel(
					led->spmi_dev->ctrl,
					led->spmi_dev->sid,
					WLED_CURR_SINK_REG(led->base), &val, 1);
				if (rc) {
					dev_err(&led->spmi_dev->dev,
						"WLED write sink reg failed");
					return rc;
				}

				rc = spmi_ext_register_readl(
					led->spmi_dev->ctrl,
					led->spmi_dev->sid,
					WLED_BOOST_LIMIT_REG(led->base),
					&ilim_val, 1);
				if (rc) {
					dev_err(&led->spmi_dev->dev,
						"Unable to read boost reg");
				}
				val = WLED_SET_ILIM_CODE;
				rc = spmi_ext_register_writel(
					led->spmi_dev->ctrl,
					led->spmi_dev->sid,
					WLED_BOOST_LIMIT_REG(led->base),
					&val, 1);
				if (rc) {
					dev_err(&led->spmi_dev->dev,
						"WLED write sink reg failed");
					return rc;
				}
				usleep(WLED_OVP_DELAY);
			} else {
				val = WLED_DISABLE_ALL_SINKS;
				rc = spmi_ext_register_writel(
					led->spmi_dev->ctrl,
					led->spmi_dev->sid,
					WLED_CURR_SINK_REG(led->base), &val, 1);
				if (rc) {
					dev_err(&led->spmi_dev->dev,
						"WLED write sink reg failed");
					return rc;
				}

				msleep(WLED_OVP_DELAY_INT);
				while (tries < WLED_MAX_TRIES) {
					rc = spmi_ext_register_readl(
						led->spmi_dev->ctrl,
						led->spmi_dev->sid,
						WLED_OVP_INT_STATUS(led->base),
						&ovp_val, 1);
					if (rc) {
						dev_err(&led->spmi_dev->dev,
						"Unable to read boost reg");
					}

					if (ovp_val & WLED_OVP_INT_MASK)
						break;

					msleep(WLED_OVP_DELAY_LOOP);
					tries++;
				}
				usleep(WLED_OVP_DELAY);
			}
		}

		val = WLED_BOOST_OFF;
		rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
@@ -633,6 +712,35 @@ static int qpnp_wled_set(struct qpnp_led_data *led)
			return rc;
		}

		if (led->wled_cfg->pmic_version == PMIC_VER_8941) {
			if (led->wled_cfg->num_physical_strings <=
					WLED_THREE_STRINGS) {
				rc = spmi_ext_register_writel(
					led->spmi_dev->ctrl,
					led->spmi_dev->sid,
					WLED_BOOST_LIMIT_REG(led->base),
					&ilim_val, 1);
				if (rc) {
					dev_err(&led->spmi_dev->dev,
						"WLED write sink reg failed");
					return rc;
				}
			} else {
				/* restore OVP to original value */
				rc = spmi_ext_register_writel(
					led->spmi_dev->ctrl,
					led->spmi_dev->sid,
					WLED_OVP_CFG_REG(led->base),
					&led->wled_cfg->ovp_val, 1);
				if (rc) {
					dev_err(&led->spmi_dev->dev,
						"WLED write sink reg failed");
					return rc;
				}
			}
		}

		/* re-enable all sinks */
		rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
			led->spmi_dev->sid, WLED_CURR_SINK_REG(led->base),
			&sink_val, 1);
@@ -2588,6 +2696,13 @@ static int qpnp_get_config_wled(struct qpnp_led_data *led,
	else if (rc != -EINVAL)
		return rc;

	led->wled_cfg->num_physical_strings = led->wled_cfg->num_strings;
	rc = of_property_read_u32(node, "qcom,num-physical-strings", &val);
	if (!rc)
		led->wled_cfg->num_physical_strings = (u8) val;
	else if (rc != -EINVAL)
		return rc;

	led->wled_cfg->ovp_val = WLED_DEFAULT_OVP_VAL;
	rc = of_property_read_u32(node, "qcom,ovp-val", &val);
	if (!rc)