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

Commit 680825f6 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: Update AMOLED_VOUT programming"

parents c5d69430 9b32ac8b
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -61,10 +61,13 @@ 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-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.
- qcom,avdd-mode-spmi: Boolean property to enable AMOLED_VOUT programming via SPMI. If not specified,
			AMOLED_VOUT is programmed via S-wire. This can be specified only for newer
			PMICs like pmicobalt/pm2falcon.
- qcom,avdd-target-voltage-mv: The voltage required for AMOLED_VOUT. Accepted values are in the range
				of 5650 to 7900 in steps of 150. Default value is 7600. Unit is in mV.
				For old revisions, accepted values are: 7900, 7600, 7300, 6400, 6100,
				5800.

Example:
	qcom,leds@d800 {
+116 −41
Original line number Diff line number Diff line
@@ -45,11 +45,13 @@
#define QPNP_WLED_SWITCH_FREQ_REG(b)	(b + 0x4C)
#define QPNP_WLED_OVP_REG(b)		(b + 0x4D)
#define QPNP_WLED_ILIM_REG(b)		(b + 0x4E)
#define QPNP_WLED_AMOLED_VOUT_REG(b)	(b + 0x4F)
#define QPNP_WLED_SOFTSTART_RAMP_DLY(b) (b + 0x53)
#define QPNP_WLED_VLOOP_COMP_RES_REG(b)	(b + 0x55)
#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_SWIRE_AVDD_REG(b)	(b + 0x5F)
#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)
@@ -196,12 +198,19 @@

#define NUM_SUPPORTED_AVDD_VOLTAGES	6
#define QPNP_WLED_DFLT_AVDD_MV		7600
#define QPNP_WLED_AVDD_MIN_MV		5650
#define QPNP_WLED_AVDD_MAX_MV		7900
#define QPNP_WLED_AVDD_STEP_MV		150
#define QPNP_WLED_AVDD_MIN_TRIM_VAL	0x0
#define QPNP_WLED_AVDD_MAX_TRIM_VAL	0xF
#define QPNP_WLED_AVDD_SEL_SPMI_BIT	BIT(7)
#define QPNP_WLED_AVDD_SET_BIT		BIT(4)

#define NUM_SUPPORTED_OVP_THRESHOLDS	4

#define QPNP_WLED_AVDD_MV_TO_REG(val) \
		((val - QPNP_WLED_AVDD_MIN_MV) / QPNP_WLED_AVDD_STEP_MV)

/* output feedback mode */
enum qpnp_wled_fdbk_op {
	QPNP_WLED_FDBK_AUTO,
@@ -288,6 +297,7 @@ static int qpnp_wled_ovp_thresholds_pmicobalt[NUM_SUPPORTED_OVP_THRESHOLDS] = {
 *  @ cons_sync_write_delay_us - delay between two consecutive writes to SYNC
 *  @ strings - supported list of strings
 *  @ num_strings - number of strings
 *  @ avdd_mode_spmi - enable avdd programming via spmi
 *  @ en_9b_dim_res - enable or disable 9bit dimming
 *  @ en_phase_stag - enable or disable phase staggering
 *  @ en_cabc - enable or disable cabc
@@ -330,6 +340,7 @@ struct qpnp_wled {
	u16			cons_sync_write_delay_us;
	u8			strings[QPNP_WLED_MAX_STRINGS];
	u8			num_strings;
	bool			avdd_mode_spmi;
	bool			en_9b_dim_res;
	bool			en_phase_stag;
	bool			en_cabc;
@@ -1089,6 +1100,102 @@ static int qpnp_wled_ovp_config(struct qpnp_wled *wled)
	return 0;
}

static int qpnp_wled_avdd_trim_config(struct qpnp_wled *wled)
{
	int rc, i;
	u8 reg;

	for (i = 0; i < NUM_SUPPORTED_AVDD_VOLTAGES; i++) {
		if (wled->avdd_target_voltage_mv ==
				qpnp_wled_avdd_target_voltages[i])
			break;
	}

	if (i == NUM_SUPPORTED_AVDD_VOLTAGES) {
		dev_err(&wled->pdev->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_masked_write_reg(wled, QPNP_WLED_OVP_MASK, &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_VAL ||
			(s8)reg > QPNP_WLED_AVDD_MAX_TRIM_VAL) {
		dev_dbg(&wled->pdev->dev,
			 "adjusted trim %d is not within range, capping it\n",
			 (s8)reg);
		if ((s8)reg < QPNP_WLED_AVDD_MIN_TRIM_VAL)
			reg = QPNP_WLED_AVDD_MIN_TRIM_VAL;
		else
			reg = QPNP_WLED_AVDD_MAX_TRIM_VAL;
	}

	reg &= QPNP_WLED_7P7_TRIM_MASK;
	rc = qpnp_wled_sec_write_reg(wled, reg,
			QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base));
	if (rc < 0)
		dev_err(&wled->pdev->dev, "Write to 7P7_TRIM register failed, rc=%d\n",
			rc);
	return rc;
}

static int qpnp_wled_avdd_mode_config(struct qpnp_wled *wled)
{
	int rc;
	u8 reg = 0;

	/*
	 * At present, configuring the mode to SPMI/SWIRE for controlling
	 * AVDD voltage is available only in pmicobalt/pm2falcon.
	 */
	if (wled->pmic_rev_id->pmic_subtype != PMICOBALT_SUBTYPE &&
		wled->pmic_rev_id->pmic_subtype != PM2FALCON_SUBTYPE)
		return 0;

	/* AMOLED_VOUT should be configured for AMOLED */
	if (!wled->disp_type_amoled)
		return 0;

	/* Configure avdd register */
	if (wled->avdd_target_voltage_mv > QPNP_WLED_AVDD_MAX_MV) {
		dev_dbg(&wled->pdev->dev, "Capping avdd target voltage to %d\n",
			QPNP_WLED_AVDD_MAX_MV);
		wled->avdd_target_voltage_mv = QPNP_WLED_AVDD_MAX_MV;
	} else if (wled->avdd_target_voltage_mv < QPNP_WLED_AVDD_MIN_MV) {
		dev_info(&wled->pdev->dev, "Capping avdd target voltage to %d\n",
			QPNP_WLED_AVDD_MIN_MV);
		wled->avdd_target_voltage_mv = QPNP_WLED_AVDD_MIN_MV;
	}

	reg = QPNP_WLED_AVDD_MV_TO_REG(wled->avdd_target_voltage_mv);

	if (wled->avdd_mode_spmi) {
		reg |= QPNP_WLED_AVDD_SEL_SPMI_BIT;
		rc = qpnp_wled_write_reg(wled, reg,
				QPNP_WLED_AMOLED_VOUT_REG(wled->ctrl_base));
	} else {
		rc = qpnp_wled_write_reg(wled, reg,
				QPNP_WLED_SWIRE_AVDD_REG(wled->ctrl_base));
	}

	if (rc < 0)
		dev_err(&wled->pdev->dev, "Write to VOUT/AVDD register failed, rc=%d\n",
			rc);
	return rc;
}

/* Configure WLED registers */
static int qpnp_wled_config(struct qpnp_wled *wled)
{
@@ -1199,49 +1306,14 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
	}

	if (is_avdd_trim_adjustment_required(wled)) {
		for (i = 0; i < NUM_SUPPORTED_AVDD_VOLTAGES; i++) {
			if (wled->avdd_target_voltage_mv ==
					qpnp_wled_avdd_target_voltages[i])
				break;
		}

		if (i == NUM_SUPPORTED_AVDD_VOLTAGES) {
			dev_err(&wled->pdev->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_masked_write_reg(wled, QPNP_WLED_OVP_MASK, &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)
		rc = qpnp_wled_avdd_trim_config(wled);
		if (rc < 0)
			return rc;

		reg += qpnp_wled_avdd_trim_adjustments[i];
		if ((s8)reg < QPNP_WLED_AVDD_MIN_TRIM_VAL ||
				(s8)reg > QPNP_WLED_AVDD_MAX_TRIM_VAL) {
			dev_info(&wled->pdev->dev,
				 "adjusted trim %d is not within range, capping it\n",
				 (s8)reg);
			if ((s8)reg < QPNP_WLED_AVDD_MIN_TRIM_VAL)
				reg = QPNP_WLED_AVDD_MIN_TRIM_VAL;
			else
				reg = QPNP_WLED_AVDD_MAX_TRIM_VAL;
	}

		reg &= QPNP_WLED_7P7_TRIM_MASK;
		rc = qpnp_wled_sec_write_reg(wled, reg,
				QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base));
		if (rc)
	rc = qpnp_wled_avdd_mode_config(wled);
	if (rc < 0)
		return rc;
	}

	/* Configure the MODULATION register */
	if (wled->mod_freq_khz <= QPNP_WLED_MOD_FREQ_1200_KHZ) {
@@ -1561,6 +1633,9 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
			return rc;
		}

		wled->avdd_mode_spmi = of_property_read_bool(pdev->dev.of_node,
				"qcom,avdd-mode-spmi");

		wled->avdd_target_voltage_mv = QPNP_WLED_DFLT_AVDD_MV;
		rc = of_property_read_u32(pdev->dev.of_node,
				"qcom,avdd-target-voltage-mv", &temp_val);