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

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

Merge "leds: qpnp-wled: Fix configuration of avdd_trim registers"

parents d90b7dda a8136a02
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -54,7 +54,10 @@ Optional properties if 'qcom,disp-type-amoled' is mentioned in DT:
- qcom,loop-ea-gm	: control the gm for gm stage in control loop. default is 3.
- qcom,loop-comp-res-kohm	: control to select the compensation resistor in kohm. default is 320.
- qcom,vref-psm-mv	: reference psm voltage in mv. default for amoled is 450.
- qcom,avdd-trim-steps-from-center : The number of steps to trim the OVP threshold voltage. The possible values can be between -7 to 8.
- qcom,avdd-target-voltage-mv: The target voltage desired for the AVDD module in mV.
				The supported values are:
				7900, 7600, 7300, 6400, 6100, 5800.
				If not specified, default value used is 7600.

Example:
	qcom,leds@d800 {
+96 −28
Original line number Diff line number Diff line
@@ -46,10 +46,12 @@
#define QPNP_WLED_VLOOP_COMP_GM_REG(b)	(b + 0x56)
#define QPNP_WLED_PSM_CTRL_REG(b)	(b + 0x5B)
#define QPNP_WLED_SC_PRO_REG(b)		(b + 0x5E)
#define QPNP_WLED_CTRL_SPARE_REG(b)	(b + 0xDF)
#define QPNP_WLED_TEST1_REG(b)		(b + 0xE2)
#define QPNP_WLED_TEST4_REG(b)		(b + 0xE5)
#define QPNP_WLED_REF_7P7_TRIM_REG(b)	(b + 0xF2)

#define QPNP_WLED_7P7_TRIM_MASK		0xF
#define QPNP_WLED_EN_MASK		0x7F
#define QPNP_WLED_EN_SHIFT		7
#define QPNP_WLED_FDBK_OP_MASK		0xF8
@@ -76,9 +78,6 @@
#define QPNP_WLED_VREF_PSM_MAX_MV			750
#define QPNP_WLED_VREF_PSM_DFLT_AMOLED_MV		450
#define QPNP_WLED_PSM_CTRL_OVERWRITE			0x80
#define QPNP_WLED_AVDD_MIN_TRIM_VALUE			-7
#define QPNP_WLED_AVDD_MAX_TRIM_VALUE			8
#define QPNP_WLED_AVDD_TRIM_CENTER_VALUE		7

#define QPNP_WLED_ILIM_MASK		0xF8
#define QPNP_WLED_ILIM_MIN_MA		105
@@ -195,6 +194,12 @@
#define QPNP_WLED_MIN_MSLEEP		20
#define QPNP_WLED_SC_DLY_MS		20

#define NUM_SUPPORTED_AVDD_VOLTAGES		6
#define QPNP_WLED_AVDD_DEFAULT_VOLTAGE_MV	7600
#define QPNP_WLED_AVDD_MIN_TRIM_VALUE		0x0
#define QPNP_WLED_AVDD_MAX_TRIM_VALUE		0xF
#define QPNP_WLED_AVDD_SET_BIT			BIT(4)

/* output feedback mode */
enum qpnp_wled_fdbk_op {
	QPNP_WLED_FDBK_AUTO,
@@ -227,6 +232,18 @@ static u8 qpnp_wled_sink_dbg_regs[] = {
	0xe6,
};

static int qpnp_wled_avdd_target_voltages[NUM_SUPPORTED_AVDD_VOLTAGES] = {
	7900, 7600, 7300, 6400, 6100, 5800,
};

static u8 qpnp_wled_ovp_reg_settings[NUM_SUPPORTED_AVDD_VOLTAGES] = {
	0x0, 0x0, 0x1, 0x2, 0x2, 0x3,
};

static int qpnp_wled_avdd_trim_adjustments[NUM_SUPPORTED_AVDD_VOLTAGES] = {
	3, 0, -2, 7, 3, 3,
};

/**
 *  qpnp_wled - wed data structure
 *  @ cdev - led class device
@@ -238,7 +255,7 @@ static u8 qpnp_wled_sink_dbg_regs[] = {
 *  @ ovp_irq - over voltage protection irq
 *  @ sc_irq - short circuit irq
 *  @ sc_cnt - short circuit irq count
 *  @ avdd_trim_steps_from_center - number of steps to trim from center value
 *  @ avdd_target_voltage_mv - target voltage for AVDD module in mV
 *  @ ctrl_base - base address for wled ctrl
 *  @ sink_base - base address for wled sink
 *  @ ibb_base - base address for IBB(Inverting Buck Boost)
@@ -279,7 +296,7 @@ struct qpnp_wled {
	int ovp_irq;
	int sc_irq;
	u32 sc_cnt;
	u32 avdd_trim_steps_from_center;
	u32 avdd_target_voltage_mv;
	u16 ctrl_base;
	u16 sink_base;
	u16 mod_freq_khz;
@@ -338,6 +355,24 @@ static int qpnp_wled_write_reg(struct qpnp_wled *wled, u8 *data, u16 addr)
	return rc;
}

static int qpnp_wled_masked_write_reg(struct qpnp_wled *wled, u8 mask, u8 *data,
					u16 addr)
{
	u8 reg;
	int rc;

	rc = qpnp_wled_read_reg(wled, &reg, addr);
	if (rc < 0)
		return rc;

	reg &= ~mask;
	reg |= *data & mask;

	rc = qpnp_wled_write_reg(wled, &reg, addr);

	return rc;
}

static int qpnp_wled_sec_access(struct qpnp_wled *wled, u16 base_addr)
{
	int rc;
@@ -1094,29 +1129,58 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
	if (rc)
		return rc;

	if (wled->disp_type_amoled) {
		/* Configure avdd trim register */
		rc = qpnp_wled_sec_access(wled, wled->ctrl_base);
		if (rc)
	rc = qpnp_wled_read_reg(wled, &reg,
			QPNP_WLED_CTRL_SPARE_REG(wled->ctrl_base));
	if (rc < 0)
		return rc;

		/* Check if wled->avdd_trim_steps_from_center is negative */
		if ((s32)wled->avdd_trim_steps_from_center <
					QPNP_WLED_AVDD_MIN_TRIM_VALUE) {
			wled->avdd_trim_steps_from_center =
					QPNP_WLED_AVDD_MIN_TRIM_VALUE;
		} else if ((s32)wled->avdd_trim_steps_from_center >
						QPNP_WLED_AVDD_MAX_TRIM_VALUE) {
			wled->avdd_trim_steps_from_center =
					QPNP_WLED_AVDD_MAX_TRIM_VALUE;
	/*
	 * Configure TRIM_REG only if disp_type_amoled and it has
	 * not already been programmed by bootloader.
	 */
	if (wled->disp_type_amoled && !(reg & QPNP_WLED_AVDD_SET_BIT)) {
		for (i = 0; i < NUM_SUPPORTED_AVDD_VOLTAGES; i++) {
			if (wled->avdd_target_voltage_mv ==
					qpnp_wled_avdd_target_voltages[i])
				break;
		}
		reg = wled->avdd_trim_steps_from_center +
					QPNP_WLED_AVDD_TRIM_CENTER_VALUE;

		if (i == NUM_SUPPORTED_AVDD_VOLTAGES) {
			dev_err(&wled->spmi->dev,
				"Invalid avdd target voltage specified in device tree\n");
			return -EINVAL;
		}

		/* Update WLED_OVP register based on desired target voltage */
		reg = qpnp_wled_ovp_reg_settings[i];
		rc = qpnp_wled_write_reg(wled, &reg,
			QPNP_WLED_OVP_REG(wled->ctrl_base));
		if (rc)
			return rc;

		/* Update WLED_TRIM register based on desired target voltage */
		rc = qpnp_wled_read_reg(wled, &reg,
			QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base));
		if (rc)
			return rc;
		reg += qpnp_wled_avdd_trim_adjustments[i];
		if ((s8)reg < QPNP_WLED_AVDD_MIN_TRIM_VALUE ||
				(s8)reg > QPNP_WLED_AVDD_MAX_TRIM_VALUE) {
			dev_info(&wled->spmi->dev,
				 "adjusted trim %d is not within range, capping it\n",
				 (s8)reg);
			if ((s8)reg < QPNP_WLED_AVDD_MIN_TRIM_VALUE)
				reg = QPNP_WLED_AVDD_MIN_TRIM_VALUE;
			else
				reg = QPNP_WLED_AVDD_MAX_TRIM_VALUE;
		}
		rc = qpnp_wled_sec_access(wled, wled->ctrl_base);
		if (rc)
			return rc;
		rc = qpnp_wled_masked_write_reg(wled, QPNP_WLED_7P7_TRIM_MASK,
			&reg, QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base));
		if (rc)
			return rc;
	}

	/* Configure the MODULATION register */
@@ -1443,14 +1507,18 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
			return rc;
		}

		wled->avdd_trim_steps_from_center = 0;
		rc = of_property_read_u32(spmi->dev.of_node,
				"qcom,avdd-trim-steps-from-center", &temp_val);
				"qcom,avdd-target-voltage-mv", &temp_val);
		if (!rc) {
			wled->avdd_trim_steps_from_center = temp_val;
		} else if (rc != -EINVAL) {
			dev_err(&spmi->dev, "Unable to read avdd trim steps from center value\n");
			wled->avdd_target_voltage_mv = temp_val;
		} else {
			if (rc != -EINVAL)
				return rc;
			dev_info(&spmi->dev,
				 "qcom,avdd-target-voltage-mv not specified. Using default value of %d\n",
				 QPNP_WLED_AVDD_DEFAULT_VOLTAGE_MV);
			wled->avdd_target_voltage_mv =
				QPNP_WLED_AVDD_DEFAULT_VOLTAGE_MV;
		}
	}