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

Commit 101e4ef4 authored by Anirudh Ghayal's avatar Anirudh Ghayal
Browse files

leds: qpnp-wled: Add auto-calibration logic for WLED



The auto-calibration logic checks if the current WLED sink
configuration is valid. It iterates through each sink
and checks if it causes an OVP fault. Based on this
information it detects and enables the valid sink
configuration.

Define 'qcom,auto-calibration-enable' to enable
auto-calibration.

CRs-Fixed: 2011194
Change-Id: If5e31d98db3e5dcab188a9d420f8f0e33bf2c16f
Signed-off-by: default avatarAnirudh Ghayal <aghayal@codeaurora.org>
parent 179ebcdb
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -78,6 +78,8 @@ Optional properties for WLED:
- qcom,lcd-psm-ctrl	: A boolean property to specify if PSM needs to be
			  controlled dynamically when WLED module is enabled
			  or disabled.
- qcom,auto-calibration-enable : A boolean property which enables auto-calibration
				 of the WLED sink configuration.

Optional properties if 'qcom,disp-type-amoled' is mentioned in DT:
- qcom,loop-comp-res-kohm	: control to select the compensation resistor in kohm. default is 320.
+323 −86
Original line number Diff line number Diff line
@@ -160,18 +160,19 @@
#define QPNP_WLED_MOD_EN_SHFT		7
#define QPNP_WLED_MOD_EN		1
#define QPNP_WLED_GATE_DRV_MASK		0xFE
#define QPNP_WLED_SYNC_DLY_MASK		0xF8
#define QPNP_WLED_SYNC_DLY_MASK		GENMASK(2, 0)
#define QPNP_WLED_SYNC_DLY_MIN_US	0
#define QPNP_WLED_SYNC_DLY_MAX_US	1400
#define QPNP_WLED_SYNC_DLY_STEP_US	200
#define QPNP_WLED_DEF_SYNC_DLY_US	400
#define QPNP_WLED_FS_CURR_MASK		0xF0
#define QPNP_WLED_FS_CURR_MASK		GENMASK(3, 0)
#define QPNP_WLED_FS_CURR_MIN_UA	0
#define QPNP_WLED_FS_CURR_MAX_UA	30000
#define QPNP_WLED_FS_CURR_STEP_UA	2500
#define QPNP_WLED_CABC_MASK		0x7F
#define QPNP_WLED_CABC_MASK		0x80
#define QPNP_WLED_CABC_SHIFT		7
#define QPNP_WLED_CURR_SINK_SHIFT	4
#define QPNP_WLED_CURR_SINK_MASK	GENMASK(7, 4)
#define QPNP_WLED_BRIGHT_LSB_MASK	0xFF
#define QPNP_WLED_BRIGHT_MSB_SHIFT	8
#define QPNP_WLED_BRIGHT_MSB_MASK	0x0F
@@ -208,12 +209,14 @@
#define QPNP_WLED_SEC_UNLOCK           0xA5

#define QPNP_WLED_MAX_STRINGS		4
#define QPNP_PM660_WLED_MAX_STRINGS	3
#define WLED_MAX_LEVEL_4095		4095
#define QPNP_WLED_RAMP_DLY_MS		20
#define QPNP_WLED_TRIGGER_NONE		"none"
#define QPNP_WLED_STR_SIZE		20
#define QPNP_WLED_MIN_MSLEEP		20
#define QPNP_WLED_SC_DLY_MS		20
#define QPNP_WLED_SOFT_START_DLY_US	10000

#define NUM_SUPPORTED_AVDD_VOLTAGES	6
#define QPNP_WLED_DFLT_AVDD_MV		7600
@@ -381,6 +384,8 @@ struct qpnp_wled {
	u16			ramp_ms;
	u16			ramp_step;
	u16			cons_sync_write_delay_us;
	u16			auto_calibration_ovp_count;
	u16			max_strings;
	u8			strings[QPNP_WLED_MAX_STRINGS];
	u8			num_strings;
	u8			loop_auto_gm_thresh;
@@ -396,6 +401,9 @@ struct qpnp_wled {
	bool			en_ext_pfet_sc_pro;
	bool			prev_state;
	bool			ovp_irq_disabled;
	bool			auto_calib_enabled;
	bool			auto_calib_done;
	ktime_t			start_ovp_fault_time;
};

/* helper to read a pmic register */
@@ -531,7 +539,7 @@ static int qpnp_wled_set_level(struct qpnp_wled *wled, int level)
	u8 reg;

	/* set brightness registers */
	for (i = 0; i < wled->num_strings; i++) {
	for (i = 0; i < wled->max_strings; i++) {
		reg = level & QPNP_WLED_BRIGHT_LSB_MASK;
		rc = qpnp_wled_write_reg(wled,
				QPNP_WLED_BRIGHT_LSB_REG(wled->sink_base,
@@ -600,7 +608,8 @@ static int qpnp_wled_module_en(struct qpnp_wled *wled,
	 * OVP interrupt disabled when the module is disabled.
	 */
	if (state) {
		usleep_range(10000, 11000);
		usleep_range(QPNP_WLED_SOFT_START_DLY_US,
				QPNP_WLED_SOFT_START_DLY_US + 1000);
		rc = qpnp_wled_psm_config(wled, false);
		if (rc < 0)
			return rc;
@@ -873,32 +882,25 @@ static ssize_t qpnp_wled_fs_curr_ua_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	struct qpnp_wled *wled = dev_get_drvdata(dev);
	int data, i, rc, temp;
	int data, i, rc;
	u8 reg;

	rc = kstrtoint(buf, 10, &data);
	if (rc)
		return rc;

	for (i = 0; i < wled->num_strings; i++) {
	for (i = 0; i < wled->max_strings; i++) {
		if (data < QPNP_WLED_FS_CURR_MIN_UA)
			data = QPNP_WLED_FS_CURR_MIN_UA;
		else if (data > QPNP_WLED_FS_CURR_MAX_UA)
			data = QPNP_WLED_FS_CURR_MAX_UA;

		rc = qpnp_wled_read_reg(wled,
				QPNP_WLED_FS_CURR_REG(wled->sink_base,
					wled->strings[i]), &reg);
		reg = data / QPNP_WLED_FS_CURR_STEP_UA;
		rc = qpnp_wled_masked_write_reg(wled,
			QPNP_WLED_FS_CURR_REG(wled->sink_base, i),
			QPNP_WLED_FS_CURR_MASK, reg);
		if (rc < 0)
			return rc;
		reg &= QPNP_WLED_FS_CURR_MASK;
		temp = data / QPNP_WLED_FS_CURR_STEP_UA;
		reg |= temp;
		rc = qpnp_wled_write_reg(wled,
				QPNP_WLED_FS_CURR_REG(wled->sink_base,
					wled->strings[i]), reg);
		if (rc)
			return rc;
	}

	wled->fs_curr_ua = data;
@@ -1090,6 +1092,229 @@ static int qpnp_wled_set_disp(struct qpnp_wled *wled, u16 base_addr)
	return 0;
}

#define AUTO_CALIB_BRIGHTNESS		16
static int wled_auto_calibrate(struct qpnp_wled *wled)
{
	int rc = 0, i;
	u8 reg = 0, sink_config = 0, sink_test = 0, sink_valid = 0, int_sts;

	mutex_lock(&wled->lock);

	/* disable OVP IRQ */
	if (wled->ovp_irq > 0 && !wled->ovp_irq_disabled) {
		disable_irq_nosync(wled->ovp_irq);
		wled->ovp_irq_disabled = true;
	}

	/* read configured sink configuration */
	rc = qpnp_wled_read_reg(wled,
		QPNP_WLED_CURR_SINK_REG(wled->sink_base), &sink_config);
	if (rc < 0) {
		pr_err("Failed to read SINK configuration rc=%d\n", rc);
		goto failed_calib;
	}

	/* disable the module before starting calibration */
	rc = qpnp_wled_masked_write_reg(wled,
			QPNP_WLED_MODULE_EN_REG(wled->ctrl_base),
			QPNP_WLED_MODULE_EN_MASK, 0);
	if (rc < 0) {
		pr_err("Failed to disable WLED module rc=%d\n", rc);
		goto failed_calib;
	}

	/* set low brightness across all sinks */
	rc = qpnp_wled_set_level(wled, AUTO_CALIB_BRIGHTNESS);
	if (rc < 0) {
		pr_err("Failed to set brightness for calibration rc=%d\n", rc);
		goto failed_calib;
	}

	/* disable all sinks */
	rc = qpnp_wled_write_reg(wled,
		 QPNP_WLED_CURR_SINK_REG(wled->sink_base), 0);
	if (rc < 0) {
		pr_err("Failed to disable all sinks rc=%d\n", rc);
		goto failed_calib;
	}

	rc = qpnp_wled_masked_write_reg(wled,
		QPNP_WLED_MODULE_EN_REG(wled->ctrl_base),
		QPNP_WLED_MODULE_EN_MASK,
		QPNP_WLED_MODULE_EN_MASK);
	if (rc < 0) {
		pr_err("Failed to enable WLED module rc=%d\n", rc);
		goto failed_calib;
	}
	/*
	 * Delay for the WLED soft-start, check the OVP status
	 * only after soft-start is complete
	 */
	usleep_range(QPNP_WLED_SOFT_START_DLY_US,
			QPNP_WLED_SOFT_START_DLY_US + 1000);

	/* iterate through the strings one by one */
	for (i = 0; i < wled->max_strings; i++) {
		sink_test = 1 << (QPNP_WLED_CURR_SINK_SHIFT + i);

		/* Enable feedback control */
		rc = qpnp_wled_write_reg(wled,
			QPNP_WLED_FDBK_OP_REG(wled->ctrl_base),
			i + 1);
		if (rc < 0) {
			pr_err("Failed to enable feedback for SINK %d rc = %d\n",
						i + 1, rc);
			goto failed_calib;
		}

		/* enable the sink */
		rc = qpnp_wled_write_reg(wled,
			QPNP_WLED_CURR_SINK_REG(wled->sink_base), sink_test);
		if (rc < 0) {
			pr_err("Failed to configure SINK %d rc=%d\n",
						i + 1, rc);
			goto failed_calib;
		}

		/* delay for WLED soft-start */
		usleep_range(QPNP_WLED_SOFT_START_DLY_US,
				QPNP_WLED_SOFT_START_DLY_US + 1000);

		rc = qpnp_wled_read_reg(wled,
			QPNP_WLED_INT_RT_STS(wled->ctrl_base), &int_sts);
		if (rc < 0) {
			pr_err("Error in reading WLED_INT_RT_STS rc=%d\n", rc);
			goto failed_calib;
		}

		if (int_sts & QPNP_WLED_OVP_FAULT_BIT)
			pr_debug("WLED OVP fault detected with SINK %d\n",
						i + 1);
		else
			sink_valid |= sink_test;
	}

	if (sink_valid == sink_config) {
		pr_debug("WLED auto-calibration complete, default sink-config=%x OK!\n",
						sink_config);
	} else {
		pr_warn("Invalid WLED default sink config=%x changing it to=%x\n",
						sink_config, sink_valid);
		sink_config = sink_valid;
	}

	if (!sink_config) {
		pr_warn("No valid WLED sinks found\n");
		goto failed_calib;
	}

	rc = qpnp_wled_masked_write_reg(wled,
			QPNP_WLED_MODULE_EN_REG(wled->ctrl_base),
			QPNP_WLED_MODULE_EN_MASK, 0);
	if (rc < 0) {
		pr_err("Failed to disable WLED module rc=%d\n", rc);
		goto failed_calib;
	}

	/* write the new sink configuration */
	rc = qpnp_wled_write_reg(wled,
			QPNP_WLED_CURR_SINK_REG(wled->sink_base), sink_config);
	if (rc < 0) {
		pr_err("Failed to reconfigure the default sink rc=%d\n", rc);
		goto failed_calib;
	}

	/* MODULATOR_EN setting for valid sinks */
	for (i = 0; i < wled->max_strings; i++) {
		if (sink_config & (1 << (QPNP_WLED_CURR_SINK_SHIFT + i)))
			reg = (QPNP_WLED_MOD_EN << QPNP_WLED_MOD_EN_SHFT);
		else
			reg = 0x0; /* disable modulator_en for unused sink */

		if (wled->dim_mode == QPNP_WLED_DIM_HYBRID)
			reg &= QPNP_WLED_GATE_DRV_MASK;
		else
			reg |= ~QPNP_WLED_GATE_DRV_MASK;

		rc = qpnp_wled_write_reg(wled,
			QPNP_WLED_MOD_EN_REG(wled->sink_base, i), reg);
		if (rc < 0) {
			pr_err("Failed to configure MODULATOR_EN rc=%d\n", rc);
			goto failed_calib;
		}
	}

	/* restore the feedback setting */
	rc = qpnp_wled_write_reg(wled,
			QPNP_WLED_FDBK_OP_REG(wled->ctrl_base),
			wled->fdbk_op);
	if (rc < 0) {
		pr_err("Failed to restore feedback setting rc=%d\n", rc);
		goto failed_calib;
	}

	/* restore  brightness */
	rc = qpnp_wled_set_level(wled, wled->cdev.brightness);
	if (rc < 0) {
		pr_err("Failed to set brightness after calibration rc=%d\n",
						rc);
		goto failed_calib;
	}

	rc = qpnp_wled_masked_write_reg(wled,
			QPNP_WLED_MODULE_EN_REG(wled->ctrl_base),
			QPNP_WLED_MODULE_EN_MASK,
			QPNP_WLED_MODULE_EN_MASK);
	if (rc < 0) {
		pr_err("Failed to enable WLED module rc=%d\n", rc);
		goto failed_calib;
	}

	/* delay for WLED soft-start */
	usleep_range(QPNP_WLED_SOFT_START_DLY_US,
			QPNP_WLED_SOFT_START_DLY_US + 1000);

failed_calib:
	if (wled->ovp_irq > 0 && wled->ovp_irq_disabled) {
		enable_irq(wled->ovp_irq);
		wled->ovp_irq_disabled = false;
	}
	mutex_unlock(&wled->lock);
	return rc;
}

#define WLED_AUTO_CAL_OVP_COUNT		5
#define WLED_AUTO_CAL_CNT_DLY_US	1000000	/* 1 second */
static bool qpnp_wled_auto_cal_required(struct qpnp_wled *wled)
{
	s64 elapsed_time_us;

	/*
	 * Check if the OVP fault was an occasional one
	 * or if its firing continuously, the latter qualifies
	 * for an auto-calibration check.
	 */
	if (!wled->auto_calibration_ovp_count) {
		wled->start_ovp_fault_time = ktime_get();
		wled->auto_calibration_ovp_count++;
	} else {
		elapsed_time_us = ktime_us_delta(ktime_get(),
				wled->start_ovp_fault_time);
		if (elapsed_time_us > WLED_AUTO_CAL_CNT_DLY_US)
			wled->auto_calibration_ovp_count = 0;
		else
			wled->auto_calibration_ovp_count++;

		if (wled->auto_calibration_ovp_count >=
				WLED_AUTO_CAL_OVP_COUNT) {
			wled->auto_calibration_ovp_count = 0;
			return true;
		}
	}

	return false;
}

/* ovp irq handler */
static irqreturn_t qpnp_wled_ovp_irq_handler(int irq, void *_wled)
{
@@ -1114,6 +1339,21 @@ static irqreturn_t qpnp_wled_ovp_irq_handler(int irq, void *_wled)
	if (fault_sts & (QPNP_WLED_OVP_FAULT_BIT | QPNP_WLED_ILIM_FAULT_BIT))
		pr_err("WLED OVP fault detected, int_sts=%x fault_sts= %x\n",
			int_sts, fault_sts);

	if (fault_sts & QPNP_WLED_OVP_FAULT_BIT) {
		if (wled->auto_calib_enabled && !wled->auto_calib_done) {
			if (qpnp_wled_auto_cal_required(wled)) {
				rc = wled_auto_calibrate(wled);
				if (rc < 0) {
					pr_err("Failed auto-calibration rc=%d\n",
							rc);
					return IRQ_HANDLED;
				}
				wled->auto_calib_done = true;
			}
		}
	}

	return IRQ_HANDLED;
}

@@ -1423,7 +1663,7 @@ static int qpnp_wled_vref_config(struct qpnp_wled *wled)
static int qpnp_wled_config(struct qpnp_wled *wled)
{
	int rc, i, temp;
	u8 reg = 0;
	u8 reg = 0, sink_en = 0, mask;

	/* Configure display type */
	rc = qpnp_wled_set_disp(wled, wled->ctrl_base);
@@ -1622,93 +1862,77 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
	rc = qpnp_wled_write_reg(wled, QPNP_WLED_CURR_SINK_REG(wled->sink_base),
			reg);

	for (i = 0; i < wled->num_strings; i++) {
		if (wled->strings[i] >= QPNP_WLED_MAX_STRINGS) {
			dev_err(&wled->pdev->dev, "Invalid string number\n");
			return -EINVAL;
		}

		/* MODULATOR */
		rc = qpnp_wled_read_reg(wled,
				QPNP_WLED_MOD_EN_REG(wled->sink_base,
					wled->strings[i]), &reg);
		if (rc < 0)
			return rc;
		reg &= QPNP_WLED_MOD_EN_MASK;
		reg |= (QPNP_WLED_MOD_EN << QPNP_WLED_MOD_EN_SHFT);

		if (wled->dim_mode == QPNP_WLED_DIM_HYBRID)
			reg &= QPNP_WLED_GATE_DRV_MASK;
		else
			reg |= ~QPNP_WLED_GATE_DRV_MASK;

		rc = qpnp_wled_write_reg(wled,
				QPNP_WLED_MOD_EN_REG(wled->sink_base,
					wled->strings[i]), reg);
		if (rc)
			return rc;

	for (i = 0; i < wled->max_strings; i++) {
		/* SYNC DELAY */
		if (wled->sync_dly_us > QPNP_WLED_SYNC_DLY_MAX_US)
			wled->sync_dly_us = QPNP_WLED_SYNC_DLY_MAX_US;

		rc = qpnp_wled_read_reg(wled,
				QPNP_WLED_SYNC_DLY_REG(wled->sink_base,
					wled->strings[i]), &reg);
		reg = wled->sync_dly_us / QPNP_WLED_SYNC_DLY_STEP_US;
		mask = QPNP_WLED_SYNC_DLY_MASK;
		rc = qpnp_wled_masked_write_reg(wled,
			QPNP_WLED_SYNC_DLY_REG(wled->sink_base, i),
			mask, reg);
		if (rc < 0)
			return rc;
		reg &= QPNP_WLED_SYNC_DLY_MASK;
		temp = wled->sync_dly_us / QPNP_WLED_SYNC_DLY_STEP_US;
		reg |= temp;
		rc = qpnp_wled_write_reg(wled,
				QPNP_WLED_SYNC_DLY_REG(wled->sink_base,
					wled->strings[i]), reg);
		if (rc)
			return rc;

		/* FULL SCALE CURRENT */
		if (wled->fs_curr_ua > QPNP_WLED_FS_CURR_MAX_UA)
			wled->fs_curr_ua = QPNP_WLED_FS_CURR_MAX_UA;

		rc = qpnp_wled_read_reg(wled,
				QPNP_WLED_FS_CURR_REG(wled->sink_base,
					wled->strings[i]), &reg);
		reg = wled->fs_curr_ua / QPNP_WLED_FS_CURR_STEP_UA;
		mask = QPNP_WLED_FS_CURR_MASK;
		rc = qpnp_wled_masked_write_reg(wled,
			QPNP_WLED_FS_CURR_REG(wled->sink_base, i),
			mask, reg);
		if (rc < 0)
			return rc;
		reg &= QPNP_WLED_FS_CURR_MASK;
		temp = wled->fs_curr_ua / QPNP_WLED_FS_CURR_STEP_UA;
		reg |= temp;
		rc = qpnp_wled_write_reg(wled,
				QPNP_WLED_FS_CURR_REG(wled->sink_base,
					wled->strings[i]), reg);
		if (rc)
			return rc;

		/* CABC */
		rc = qpnp_wled_read_reg(wled,
				QPNP_WLED_CABC_REG(wled->sink_base,
					wled->strings[i]), &reg);
		reg = wled->en_cabc ? (1  << QPNP_WLED_CABC_SHIFT) : 0;
		mask = QPNP_WLED_CABC_MASK;
		rc = qpnp_wled_masked_write_reg(wled,
			QPNP_WLED_CABC_REG(wled->sink_base, i),
			mask, reg);
		if (rc < 0)
			return rc;
		reg &= QPNP_WLED_CABC_MASK;
		reg |= (wled->en_cabc << QPNP_WLED_CABC_SHIFT);
		rc = qpnp_wled_write_reg(wled,
				QPNP_WLED_CABC_REG(wled->sink_base,
					wled->strings[i]), reg);
		if (rc)
			return rc;
	}

		/* Enable CURRENT SINK */
	/* Settings specific to valid sinks */
	for (i = 0; i < wled->num_strings; i++) {
		if (wled->strings[i] >= wled->max_strings) {
			dev_err(&wled->pdev->dev, "Invalid string number\n");
			return -EINVAL;
		}
		/* MODULATOR */
		rc = qpnp_wled_read_reg(wled,
				QPNP_WLED_CURR_SINK_REG(wled->sink_base), &reg);
			QPNP_WLED_MOD_EN_REG(wled->sink_base, i), &reg);
		if (rc < 0)
			return rc;
		temp = wled->strings[i] + QPNP_WLED_CURR_SINK_SHIFT;
		reg |= (1 << temp);
		reg &= QPNP_WLED_MOD_EN_MASK;
		reg |= (QPNP_WLED_MOD_EN << QPNP_WLED_MOD_EN_SHFT);

		if (wled->dim_mode == QPNP_WLED_DIM_HYBRID)
			reg &= QPNP_WLED_GATE_DRV_MASK;
		else
			reg |= ~QPNP_WLED_GATE_DRV_MASK;

		rc = qpnp_wled_write_reg(wled,
				QPNP_WLED_CURR_SINK_REG(wled->sink_base), reg);
			QPNP_WLED_MOD_EN_REG(wled->sink_base, i), reg);
		if (rc)
			return rc;

		/* SINK EN */
		temp = wled->strings[i] + QPNP_WLED_CURR_SINK_SHIFT;
		sink_en |= (1 << temp);
	}
	mask = QPNP_WLED_CURR_SINK_MASK;
	rc = qpnp_wled_masked_write_reg(wled,
		QPNP_WLED_CURR_SINK_REG(wled->sink_base),
		mask, sink_en);
	if (rc < 0) {
		dev_err(&wled->pdev->dev,
			"Failed to enable WLED sink config rc = %d\n", rc);
		return rc;
	}

	rc = qpnp_wled_sync_reg_toggle(wled);
@@ -1728,9 +1952,14 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
				wled->ovp_irq, rc);
			return rc;
		}
		rc = qpnp_wled_read_reg(wled,
				QPNP_WLED_MODULE_EN_REG(wled->ctrl_base), &reg);
		/* disable the OVP irq only if the module is not enabled */
		if (!rc && !(reg & QPNP_WLED_MODULE_EN_MASK)) {
			disable_irq(wled->ovp_irq);
			wled->ovp_irq_disabled = true;
		}
	}

	if (wled->sc_irq >= 0) {
		wled->sc_cnt = 0;
@@ -2091,11 +2320,16 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
	wled->en_cabc = of_property_read_bool(pdev->dev.of_node,
			"qcom,en-cabc");

	if (wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
		wled->max_strings = QPNP_PM660_WLED_MAX_STRINGS;
	else
		wled->max_strings = QPNP_WLED_MAX_STRINGS;

	prop = of_find_property(pdev->dev.of_node,
			"qcom,led-strings-list", &temp_val);
	if (!prop || !temp_val || temp_val > QPNP_WLED_MAX_STRINGS) {
		dev_err(&pdev->dev, "Invalid strings info, use default");
		wled->num_strings = QPNP_WLED_MAX_STRINGS;
		wled->num_strings = wled->max_strings;
		for (i = 0; i < wled->num_strings; i++)
			wled->strings[i] = i;
	} else {
@@ -2118,6 +2352,9 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)

	wled->lcd_psm_ctrl = of_property_read_bool(pdev->dev.of_node,
				"qcom,lcd-psm-ctrl");

	wled->auto_calib_enabled = of_property_read_bool(pdev->dev.of_node,
					"qcom,auto-calibration-enable");
	return 0;
}

@@ -2186,13 +2423,13 @@ static int qpnp_wled_probe(struct platform_device *pdev)
	}

	mutex_init(&wled->bus_lock);
	mutex_init(&wled->lock);
	rc = qpnp_wled_config(wled);
	if (rc) {
		dev_err(&pdev->dev, "wled config failed\n");
		return rc;
	}

	mutex_init(&wled->lock);
	INIT_WORK(&wled->work, qpnp_wled_work);
	wled->ramp_ms = QPNP_WLED_RAMP_DLY_MS;
	wled->ramp_step = 1;