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

Commit 6ee032ae 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 symmetry configuration"

parents 4a3ccc4a d737fd51
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -182,6 +182,10 @@ Optional properties:
				  be edge triggered. Otherwise, it is level triggered.
- qcom,hw-strobe-active-low	: Boolean property to select strobe signal polarity. If defined, hw-strobe
				  signal polarity is set to active-low, else it is active-high.
- qcom,symmetry-en	: Boolean property to specify if the flash LEDs under a
			  switch node are controlled symmetrically. This needs
			  to be specified if a group of flash LED channels are
			  connected to a single LED.
Example:
	qcom,leds@d300 {
		compatible = "qcom,qpnp-flash-led-v2";
@@ -302,6 +306,7 @@ Example:
			qcom,led-mask = <3>;
			qcom,default-led-trigger =
						"switch0_trigger";
			qcom,symmetry-en;
		};

		pmi8998_switch1: qcom,led_switch_1 {
+79 −1
Original line number Diff line number Diff line
@@ -171,6 +171,7 @@ enum flash_charger_mitigation {
};

enum flash_led_type {
	FLASH_LED_TYPE_UNKNOWN,
	FLASH_LED_TYPE_FLASH,
	FLASH_LED_TYPE_TORCH,
};
@@ -204,13 +205,13 @@ struct flash_node_data {
	int				prev_current_ma;
	u8				duration;
	u8				id;
	u8				type;
	u8				ires_idx;
	u8				default_ires_idx;
	u8				hdrm_val;
	u8				current_reg_val;
	u8				strobe_ctrl;
	u8				strobe_sel;
	enum flash_led_type		type;
	bool				led_on;
};

@@ -225,6 +226,7 @@ struct flash_switch_data {
	int				led_mask;
	bool				regulator_on;
	bool				enabled;
	bool				symmetry_en;
};

/*
@@ -1091,6 +1093,71 @@ static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode)
	return 0;
}

static int qpnp_flash_led_symmetry_config(struct flash_switch_data *snode)
{
	struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
	int i, total_curr_ma = 0, num_leds = 0, prgm_current_ma;
	enum flash_led_type type = FLASH_LED_TYPE_UNKNOWN;

	for (i = 0; i < led->num_fnodes; i++) {
		if (snode->led_mask & BIT(led->fnode[i].id)) {
			if (led->fnode[i].type == FLASH_LED_TYPE_FLASH &&
				led->fnode[i].led_on)
				type = FLASH_LED_TYPE_FLASH;

			if (led->fnode[i].type == FLASH_LED_TYPE_TORCH &&
				led->fnode[i].led_on)
				type = FLASH_LED_TYPE_TORCH;
		}
	}

	if (type == FLASH_LED_TYPE_UNKNOWN) {
		pr_err("Incorrect type possibly because of no active LEDs\n");
		return -EINVAL;
	}

	for (i = 0; i < led->num_fnodes; i++) {
		if ((snode->led_mask & BIT(led->fnode[i].id)) &&
			(led->fnode[i].type == type)) {
			total_curr_ma += led->fnode[i].current_ma;
			num_leds++;
		}
	}

	if (num_leds > 0 && total_curr_ma > 0) {
		prgm_current_ma = total_curr_ma / num_leds;
	} else {
		pr_err("Incorrect configuration, num_leds: %d total_curr_ma: %d\n",
			num_leds, total_curr_ma);
		return -EINVAL;
	}

	if (prgm_current_ma == 0) {
		pr_warn("prgm_curr_ma cannot be 0\n");
		return 0;
	}

	pr_debug("num_leds: %d total: %d prgm_curr_ma: %d\n", num_leds,
		total_curr_ma, prgm_current_ma);

	for (i = 0; i < led->num_fnodes; i++) {
		if (snode->led_mask & BIT(led->fnode[i].id) &&
			led->fnode[i].current_ma != prgm_current_ma &&
			led->fnode[i].type == type) {
			qpnp_flash_led_node_set(&led->fnode[i],
				prgm_current_ma);
			pr_debug("%s LED %d current: %d code: %d ires_ua: %d\n",
				(type == FLASH_LED_TYPE_FLASH) ?
					"flash" : "torch",
				led->fnode[i].id, prgm_current_ma,
				led->fnode[i].current_reg_val,
				led->fnode[i].ires_ua);
		}
	}

	return 0;
}

static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
{
	struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
@@ -1109,6 +1176,15 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
	}

	/* Iterate over all active leds for this switch node */
	if (snode->symmetry_en) {
		rc = qpnp_flash_led_symmetry_config(snode);
		if (rc < 0) {
			pr_err("Failed to configure current symmetrically, rc=%d\n",
				rc);
			return rc;
		}
	}

	val = 0;
	for (i = 0; i < led->num_fnodes; i++)
		if (led->fnode[i].led_on &&
@@ -1707,6 +1783,8 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
		return rc;
	}

	snode->symmetry_en = of_property_read_bool(node, "qcom,symmetry-en");

	if (snode->led_mask < 1 || snode->led_mask > 7) {
		pr_err("Invalid value for led-mask\n");
		return -EINVAL;