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

Commit c8f85b42 authored by Fenglin Wu's avatar Fenglin Wu
Browse files

leds: qpnp-wled: Add support to configure AUTO_GM settings



WLED in pmicobalt supports AUTO_GM configuration in CTRL_VLOOP_COMP_GM
register. Add two properties to enable auto-gm and set auto-gm threshold.
Meanwhile, move "qcom,loop-ea-gm" property outside of AMOLED constraint
because WLED in LCD mode also support it.

CRs-Fixed: 1081738
Change-Id: Iee99e9d1b999c84ece075d2f17e9cdf6aef9a2ac
Signed-off-by: default avatarFenglin Wu <fenglinw@codeaurora.org>
parent e146a328
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -68,9 +68,12 @@ Optional properties for WLED:
- qcom,cons-sync-write-delay-us : Specify in 'us' the duration of delay between two consecutive writes to
				  SYNC register.
- qcom,sc-deb-cycles	: debounce time for short circuit detection
- qcom,loop-ea-gm	: control the gm for gm stage in control loop. default is 3.
- qcom,loop-auto-gm-en	: A boolean property to specify if auto gm is enabled.
- qcom,loop-auto-gm-thresh	: Specify auto gm threshold if "loop-auto-gm-en" is defined.
				  Supported values are: 0 - 3.

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-mode-spmi: Boolean property to enable AMOLED_VOUT programming via SPMI. If not specified,
+96 −30
Original line number Diff line number Diff line
@@ -69,11 +69,18 @@
#define QPNP_WLED_LOOP_COMP_RES_STEP_KOHM		20
#define QPNP_WLED_LOOP_COMP_RES_MIN_KOHM		20
#define QPNP_WLED_LOOP_COMP_RES_MAX_KOHM		320
#define QPNP_WLED_VLOOP_COMP_GM_MASK			0xF0
#define QPNP_WLED_VLOOP_COMP_GM_MASK			GENMASK(3, 0)
#define QPNP_WLED_VLOOP_COMP_GM_OVERWRITE		0x80
#define QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED		0x03
#define QPNP_WLED_VLOOP_COMP_AUTO_GM_EN			BIT(6)
#define QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_MASK	GENMASK(5, 4)
#define QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_SHIFT	4
#define QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED_PMI8994	0x03
#define QPNP_WLED_LOOP_GM_DFLT_AMOLED_PMICOBALT		0x09
#define QPNP_WLED_LOOP_GM_DFLT_WLED			0x09
#define QPNP_WLED_LOOP_EA_GM_MIN			0x0
#define QPNP_WLED_LOOP_EA_GM_MAX			0xF
#define QPNP_WLED_LOOP_AUTO_GM_THRESH_MAX		3
#define QPNP_WLED_LOOP_AUTO_GM_DFLT_THRESH		1
#define QPNP_WLED_VREF_PSM_MASK				0xF8
#define QPNP_WLED_VREF_PSM_STEP_MV			50
#define QPNP_WLED_VREF_PSM_MIN_MV			400
@@ -319,6 +326,8 @@ static struct wled_vref_setting vref_setting_pmicobalt = {
 *  @ cons_sync_write_delay_us - delay between two consecutive writes to SYNC
 *  @ strings - supported list of strings
 *  @ num_strings - number of strings
 *  @ loop_auto_gm_thresh - the clamping level for auto gm
 *  @ loop_auto_gm_en - select if auto gm is enabled
 *  @ 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
@@ -362,6 +371,8 @@ struct qpnp_wled {
	u16			cons_sync_write_delay_us;
	u8			strings[QPNP_WLED_MAX_STRINGS];
	u8			num_strings;
	u8			loop_auto_gm_thresh;
	bool			loop_auto_gm_en;
	bool			avdd_mode_spmi;
	bool			en_9b_dim_res;
	bool			en_phase_stag;
@@ -987,24 +998,6 @@ static int qpnp_wled_set_disp(struct qpnp_wled *wled, u16 base_addr)
		if (rc)
			return rc;

		/* Configure the LOOP COMP GM register for AMOLED */
		if (wled->loop_ea_gm < QPNP_WLED_LOOP_EA_GM_MIN)
			wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MIN;
		else if (wled->loop_ea_gm > QPNP_WLED_LOOP_EA_GM_MAX)
			wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MAX;

		rc = qpnp_wled_read_reg(wled, &reg,
				QPNP_WLED_VLOOP_COMP_GM_REG(wled->ctrl_base));
		if (rc < 0)
			return rc;

		reg &= QPNP_WLED_VLOOP_COMP_GM_MASK;
		reg |= (wled->loop_ea_gm | QPNP_WLED_VLOOP_COMP_GM_OVERWRITE);
		rc = qpnp_wled_write_reg(wled, reg,
				QPNP_WLED_VLOOP_COMP_GM_REG(wled->ctrl_base));
		if (rc)
			return rc;

		/* Configure the CTRL TEST4 register for AMOLED */
		rc = qpnp_wled_read_reg(wled, &reg,
				QPNP_WLED_TEST4_REG(wled->ctrl_base));
@@ -1084,6 +1077,45 @@ static bool is_avdd_trim_adjustment_required(struct qpnp_wled *wled)
	return !(reg & QPNP_WLED_AVDD_SET_BIT);
}

static int qpnp_wled_gm_config(struct qpnp_wled *wled)
{
	int rc;
	u8 mask = 0, reg = 0;

	/* Configure the LOOP COMP GM register */
	if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE ||
			wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE) {
		if (wled->loop_auto_gm_en)
			reg |= QPNP_WLED_VLOOP_COMP_AUTO_GM_EN;

		if (wled->loop_auto_gm_thresh >
				QPNP_WLED_LOOP_AUTO_GM_THRESH_MAX)
			wled->loop_auto_gm_thresh =
				QPNP_WLED_LOOP_AUTO_GM_THRESH_MAX;

		reg |= wled->loop_auto_gm_thresh <<
			QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_SHIFT;
		mask |= QPNP_WLED_VLOOP_COMP_AUTO_GM_EN |
			QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_MASK;
	}

	if (wled->loop_ea_gm < QPNP_WLED_LOOP_EA_GM_MIN)
		wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MIN;
	else if (wled->loop_ea_gm > QPNP_WLED_LOOP_EA_GM_MAX)
		wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MAX;

	reg |= wled->loop_ea_gm | QPNP_WLED_VLOOP_COMP_GM_OVERWRITE;
	mask |= QPNP_WLED_VLOOP_COMP_GM_MASK |
		QPNP_WLED_VLOOP_COMP_GM_OVERWRITE;

	rc = qpnp_wled_masked_write_reg(wled, mask, &reg,
			QPNP_WLED_VLOOP_COMP_GM_REG(wled->ctrl_base));
	if (rc)
		pr_err("write VLOOP_COMP_GM_REG failed, rc=%d]\n", rc);

	return rc;
}

static int qpnp_wled_ovp_config(struct qpnp_wled *wled)
{
	int rc, i, *ovp_table;
@@ -1317,6 +1349,13 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
		return rc;
	}

	/* Configure VLOOP_COMP_GM register */
	rc = qpnp_wled_gm_config(wled);
	if (rc < 0) {
		pr_err("Error in configureing wled gm, rc=%d\n", rc);
		return rc;
	}

	/* Configure the ILIM register */
	rc = qpnp_wled_ilim_config(wled);
	if (rc < 0) {
@@ -1689,16 +1728,6 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
			return rc;
		}

		wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED;
		rc = of_property_read_u32(pdev->dev.of_node,
				"qcom,loop-ea-gm", &temp_val);
		if (!rc) {
			wled->loop_ea_gm = temp_val;
		} else if (rc != -EINVAL) {
			dev_err(&pdev->dev, "Unable to read loop-ea-gm\n");
			return rc;
		}

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

@@ -1713,6 +1742,43 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
		}
	}

	if (wled->disp_type_amoled) {
		if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE ||
			wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE)
			wled->loop_ea_gm =
				QPNP_WLED_LOOP_GM_DFLT_AMOLED_PMICOBALT;
		else
			wled->loop_ea_gm =
				QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED_PMI8994;
	} else {
		wled->loop_ea_gm = QPNP_WLED_LOOP_GM_DFLT_WLED;
	}

	rc = of_property_read_u32(pdev->dev.of_node,
			"qcom,loop-ea-gm", &temp_val);
	if (!rc) {
		wled->loop_ea_gm = temp_val;
	} else if (rc != -EINVAL) {
		dev_err(&pdev->dev, "Unable to read loop-ea-gm\n");
		return rc;
	}

	if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE ||
		wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE) {
		wled->loop_auto_gm_en =
			of_property_read_bool(pdev->dev.of_node,
					"qcom,loop-auto-gm-en");
		wled->loop_auto_gm_thresh = QPNP_WLED_LOOP_AUTO_GM_DFLT_THRESH;
		rc = of_property_read_u8(pdev->dev.of_node,
				"qcom,loop-auto-gm-thresh",
				&wled->loop_auto_gm_thresh);
		if (rc && rc != -EINVAL) {
			dev_err(&pdev->dev,
				"Unable to read loop-auto-gm-thresh\n");
			return rc;
		}
	}

	wled->sc_deb_cycles = QPNP_WLED_SC_DEB_CYCLES_DFLT;
	rc = of_property_read_u32(pdev->dev.of_node,
			"qcom,sc-deb-cycles", &temp_val);