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

Commit 79158a6e authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ARM: dts: msm: Enable auto-calibration for WLED on PM660/PMI8998"

parents fe82d332 f2e640cd
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.
+1 −0
Original line number Diff line number Diff line
@@ -269,6 +269,7 @@
			qcom,led-strings-list = [00 01 02];
			qcom,loop-auto-gm-en;
			qcom,pmic-revid = <&pm660l_revid>;
			qcom,auto-calibration-enable;
			status = "ok";
		};

+1 −0
Original line number Diff line number Diff line
@@ -563,6 +563,7 @@
			qcom,en-ext-pfet-sc-pro;
			qcom,pmic-revid = <&pmi8998_revid>;
			qcom,loop-auto-gm-en;
			qcom,auto-calibration-enable;
			status = "disabled";
		};

+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;