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

Commit bc191d7e 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-flash-v2: Add support for LPG strobe" into msm-4.9

parents 294962f4 3f684b21
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -169,8 +169,15 @@ Optional properties:
                          sleep configuration defined for each pin or pin group.
- qcom,hw-strobe-gpio	: phandle to specify GPIO for hardware strobing. This is used when there is no
			  pinctrl support or PMIC GPIOs are used.
- qcom,hw-strobe-sel	: Boolean property to enable hardware strobe. If not defined, software strobe
			  will be used.
- qcom,strobe-sel	: Property to select strobe type. If not defined,
			  software strobe will be used. Allowed options are:
			  0 - SW strobe
			  1 - HW strobe
			  2 - LPG strobe
			  LPG strobe is supported only for LED3.
			  If LPG strobe is specified, then strobe control is
			  configured for active high and level triggered. Also
			  qcom,hw-strobe-option should be set to 1 or 2.
- qcom,hw-strobe-edge-trigger	: Boolean property to select trigger type. If defined, hw-strobe is set to
				  be edge triggered. Otherwise, it is level triggered.
- qcom,hw-strobe-active-low	: Boolean property to select strobe signal polarity. If defined, hw-strobe
+88 −22
Original line number Diff line number Diff line
@@ -63,11 +63,13 @@
#define	FLASH_LED_REG_MITIGATION_SEL(base)	(base + 0x6E)
#define	FLASH_LED_REG_MITIGATION_SW(base)	(base + 0x6F)
#define	FLASH_LED_REG_LMH_LEVEL(base)		(base + 0x70)
#define	FLASH_LED_REG_MULTI_STROBE_CTRL(base)	(base + 0x71)
#define	FLASH_LED_REG_LPG_INPUT_CTRL(base)	(base + 0x72)
#define	FLASH_LED_REG_CURRENT_DERATE_EN(base)	(base + 0x76)

#define	FLASH_LED_HDRM_VOL_MASK			GENMASK(7, 4)
#define	FLASH_LED_CURRENT_MASK			GENMASK(6, 0)
#define	FLASH_LED_ENABLE_MASK			GENMASK(2, 0)
#define	FLASH_LED_STROBE_MASK			GENMASK(1, 0)
#define	FLASH_HW_STROBE_MASK			GENMASK(2, 0)
#define	FLASH_LED_ISC_WARMUP_DELAY_MASK		GENMASK(1, 0)
#define	FLASH_LED_CURRENT_DERATE_EN_MASK	GENMASK(2, 0)
@@ -91,6 +93,9 @@
#define	THERMAL_DERATE_SLOW_SHIFT		4
#define	THERMAL_DERATE_SLOW_MASK		GENMASK(6, 4)
#define	THERMAL_DERATE_FAST_MASK		GENMASK(2, 0)
#define	LED1N2_FLASH_ONCE_ONLY_BIT		BIT(0)
#define	LED3_FLASH_ONCE_ONLY_BIT		BIT(1)
#define	LPG_INPUT_SEL_BIT			BIT(0)

#define	VPH_DROOP_DEBOUNCE_US_TO_VAL(val_us)	(val_us / 8)
#define	VPH_DROOP_HYST_MV_TO_VAL(val_mv)	(val_mv / 25)
@@ -174,6 +179,12 @@ enum {
	LED3,
};

enum strobe_type {
	SW_STROBE = 0,
	HW_STROBE,
	LPG_STROBE,
};

/*
 * Configurations for each individual LED
 */
@@ -194,7 +205,8 @@ struct flash_node_data {
	u8				ires;
	u8				hdrm_val;
	u8				current_reg_val;
	u8				trigger;
	u8				strobe_ctrl;
	u8				strobe_sel;
	bool				led_on;
};

@@ -232,6 +244,7 @@ struct flash_led_platform_data {
	int			thermal_thrsh1;
	int			thermal_thrsh2;
	int			thermal_thrsh3;
	int			hw_strobe_option;
	u32			led1n2_iclamp_low_ma;
	u32			led1n2_iclamp_mid_ma;
	u32			led3_iclamp_low_ma;
@@ -246,7 +259,6 @@ struct flash_led_platform_data {
	u8			chgr_mitigation_sel;
	u8			lmh_level;
	u8			iled_thrsh_val;
	u8			hw_strobe_option;
	bool			hdrm_auto_mode_en;
	bool			thermal_derate_en;
	bool			otst_ramp_bkup_en;
@@ -557,6 +569,28 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
			return rc;
	}

	if (led->pdata->hw_strobe_option > 0) {
		rc = qpnp_flash_led_masked_write(led,
				FLASH_LED_REG_STROBE_CFG(led->base),
				FLASH_LED_STROBE_MASK,
				led->pdata->hw_strobe_option);
		if (rc < 0)
			return rc;
	}

	if (led->fnode[LED3].strobe_sel == LPG_STROBE) {
		rc = qpnp_flash_led_masked_write(led,
			FLASH_LED_REG_MULTI_STROBE_CTRL(led->base),
			LED3_FLASH_ONCE_ONLY_BIT, 0);
		if (rc < 0)
			return rc;

		rc = qpnp_flash_led_masked_write(led,
			FLASH_LED_REG_LPG_INPUT_CTRL(led->base),
			LPG_INPUT_SEL_BIT, LPG_INPUT_SEL_BIT);
		if (rc < 0)
			return rc;
	}
	return 0;
}

@@ -981,7 +1015,7 @@ static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode)

		led->fnode[i].led_on = false;

		if (led->fnode[i].trigger & FLASH_LED_HW_SW_STROBE_SEL_BIT) {
		if (led->fnode[i].strobe_sel == HW_STROBE) {
			rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
					led->pdata->hw_strobe_option, false);
			if (rc < 0) {
@@ -1035,13 +1069,6 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
	if (rc < 0)
		return rc;

	rc = qpnp_flash_led_masked_write(led,
					FLASH_LED_REG_STROBE_CFG(led->base),
					FLASH_LED_ENABLE_MASK,
					led->pdata->hw_strobe_option);
	if (rc < 0)
		return rc;

	val = 0;
	for (i = 0; i < led->num_fnodes; i++) {
		if (!led->fnode[i].led_on ||
@@ -1049,13 +1076,13 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
			continue;

		addr_offset = led->fnode[i].id;
		if (led->fnode[i].trigger & FLASH_LED_HW_SW_STROBE_SEL_BIT)
			mask = FLASH_HW_STROBE_MASK;
		else
		if (led->fnode[i].strobe_sel == SW_STROBE)
			mask = FLASH_LED_HW_SW_STROBE_SEL_BIT;
		else
			mask = FLASH_HW_STROBE_MASK;
		rc = qpnp_flash_led_masked_write(led,
			FLASH_LED_REG_STROBE_CTRL(led->base + addr_offset),
			mask, led->fnode[i].trigger);
			mask, led->fnode[i].strobe_ctrl);
		if (rc < 0)
			return rc;

@@ -1073,7 +1100,7 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)

		val |= FLASH_LED_ENABLE << led->fnode[i].id;

		if (led->fnode[i].trigger & FLASH_LED_HW_SW_STROBE_SEL_BIT) {
		if (led->fnode[i].strobe_sel == HW_STROBE) {
			rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
					led->pdata->hw_strobe_option, true);
			if (rc < 0) {
@@ -1365,7 +1392,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
	const char *temp_string;
	int rc, min_ma;
	u32 val;
	bool strobe_sel = 0, edge_trigger = 0, active_high = 0;
	bool hw_strobe = 0, edge_trigger = 0, active_high = 0;

	fnode->pdev = led->pdev;
	fnode->cdev.brightness_set = qpnp_flash_led_brightness_set;
@@ -1484,14 +1511,52 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
		return rc;
	}

	strobe_sel = of_property_read_bool(node, "qcom,hw-strobe-sel");
	if (strobe_sel) {
	fnode->strobe_sel = SW_STROBE;
	rc = of_property_read_u32(node, "qcom,strobe-sel", &val);
	if (rc < 0) {
		if (rc != -EINVAL) {
			pr_err("Unable to read qcom,strobe-sel property\n");
			return rc;
		}
	} else {
		if (val < SW_STROBE || val > LPG_STROBE) {
			pr_err("Incorrect strobe selection specified %d\n",
				val);
			return -EINVAL;
		}
		fnode->strobe_sel = (u8)val;
	}

	/*
	 * LPG strobe is allowed only for LED3 and HW strobe option should be
	 * option 2 or 3.
	 */
	if (fnode->strobe_sel == LPG_STROBE) {
		if (led->pdata->hw_strobe_option ==
				FLASH_LED_HW_STROBE_OPTION_1) {
			pr_err("Incorrect strobe option for LPG strobe\n");
			return -EINVAL;
		}
		if (fnode->id != LED3) {
			pr_err("Incorrect LED chosen for LPG strobe\n");
			return -EINVAL;
		}
	}

	if (fnode->strobe_sel == HW_STROBE) {
		edge_trigger = of_property_read_bool(node,
						"qcom,hw-strobe-edge-trigger");
		active_high = !of_property_read_bool(node,
						"qcom,hw-strobe-active-low");
		hw_strobe = 1;
	} else if (fnode->strobe_sel == LPG_STROBE) {
		/* LPG strobe requires level trigger and active high */
		edge_trigger = 0;
		active_high =  1;
		hw_strobe = 1;
	}
	fnode->trigger = (strobe_sel << 2) | (edge_trigger << 1) | active_high;
	fnode->strobe_ctrl = (hw_strobe << 2) | (edge_trigger << 1) |
				active_high;

	rc = led_classdev_register(&led->pdev->dev, &fnode->cdev);
	if (rc < 0) {
@@ -1507,7 +1572,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
		fnode->strobe_pinctrl = NULL;
	}

	if (fnode->trigger & FLASH_LED_HW_SW_STROBE_SEL_BIT) {
	if (fnode->strobe_sel == HW_STROBE) {
		if (of_find_property(node, "qcom,hw-strobe-gpio", NULL)) {
			fnode->hw_strobe_gpio = of_get_named_gpio(node,
						"qcom,hw-strobe-gpio", 0);
@@ -1887,9 +1952,10 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,

	led->pdata->vph_droop_hysteresis <<= FLASH_LED_VPH_DROOP_HYST_SHIFT;

	led->pdata->hw_strobe_option = -EINVAL;
	rc = of_property_read_u32(node, "qcom,hw-strobe-option", &val);
	if (!rc) {
		led->pdata->hw_strobe_option = (u8)val;
		led->pdata->hw_strobe_option = val;
	} else if (rc != -EINVAL) {
		pr_err("Unable to parse hw strobe option, rc=%d\n", rc);
		return rc;