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

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

pwm: pwm-qti-lpg: Add property for LPG channel synchronization



Add qcom,sync-channel-ids property for grouping the LPG channels which
are expected to be enabled with a synchronized pattern.

Change-Id: I1f5d83f2e6094771cb30d567d9d4d4476f1f3dc9
Signed-off-by: default avatarFenglin Wu <fenglinw@codeaurora.org>
parent da0130a5
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -40,6 +40,17 @@ device module in Qualcomm Technologies, Inc. PMIC chips.
		      channels. This property is required if any LPG channels
		      support LUT mode.

- qcom,sync-channel-ids:
	Usage: optional
	Value type: <prop-encoded-array>
	Definition: The hardware IDs of the LPG channel that required be
		      grouped together. These channels will share the same LUT
		      ramping configuration so that they will be enabled with a
		      synchronized pattern. If the LUT ramping configuration
		      differs for the channels grouped for synchronization,
		      configuration of the first channel will be applied for
		      all others.

Subnode is optional if LUT mode is not required, it's required if any LPG
channels expected to be supported in LUT mode.

@@ -114,6 +125,7 @@ Example:
		#pwm-cells = <2>;
		qcom,lut-patterns = <0 14 28 42 56 70 84 100
					100 84 70 56 42 28 14 0>;
		qcom,sync-channel-ids = <3 4 5>;
		lpg@3 {
			qcom,lpg-chan-id = <3>;
			qcom,ramp-step-ms = <200>;
+74 −2
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ struct qpnp_lpg_chip {
	struct qpnp_lpg_channel	*lpgs;
	struct qpnp_lpg_lut	*lut;
	struct mutex		bus_lock;
	u32			*lpg_group;
	u32			num_lpgs;
};

@@ -659,8 +660,9 @@ static int qpnp_lpg_pwm_src_enable(struct qpnp_lpg_channel *lpg, bool en)
{
	struct qpnp_lpg_chip *chip = lpg->chip;
	struct qpnp_lpg_lut *lut = chip->lut;
	struct pwm_device *pwm;
	u8 mask, val;
	int rc;
	int i, lpg_idx, rc;

	mask = LPG_PWM_SRC_SELECT_MASK | LPG_EN_LPG_OUT_BIT |
					LPG_EN_RAMP_GEN_MASK;
@@ -680,8 +682,31 @@ static int qpnp_lpg_pwm_src_enable(struct qpnp_lpg_channel *lpg, bool en)
	}

	if (lpg->src_sel == LUT_PATTERN && en) {
		mutex_lock(&lut->lock);
		val = 1 << lpg->lpg_idx;
		for (i = 0; i < chip->num_lpgs; i++) {
			if (chip->lpg_group == NULL)
				break;
			if (chip->lpg_group[i] == 0)
				break;
			lpg_idx = chip->lpg_group[i] - 1;
			pwm = &chip->pwm_chip.pwms[lpg_idx];
			if ((pwm_get_output_type(pwm) == PWM_OUTPUT_MODULATED)
						&& pwm_is_enabled(pwm)) {
				rc = qpnp_lpg_masked_write(&chip->lpgs[lpg_idx],
						REG_LPG_ENABLE_CONTROL,
						LPG_EN_LPG_OUT_BIT, 0);
				if (rc < 0)
					break;
				rc = qpnp_lpg_masked_write(&chip->lpgs[lpg_idx],
						REG_LPG_ENABLE_CONTROL,
						LPG_EN_LPG_OUT_BIT,
						LPG_EN_LPG_OUT_BIT);
				if (rc < 0)
					break;
				val |= 1 << lpg_idx;
			}
		}
		mutex_lock(&lut->lock);
		rc = qpnp_lut_write(lut, REG_LPG_LUT_RAMP_CONTROL, val);
		if (rc < 0)
			dev_err(chip->dev, "Write LPG_LUT_RAMP_CONTROL failed, rc=%d\n",
@@ -1146,6 +1171,53 @@ static int qpnp_lpg_parse_dt(struct qpnp_lpg_chip *chip)
				"qcom,ramp-toggle");
	}

	rc = of_property_count_elems_of_size(chip->dev->of_node,
			"qcom,sync-channel-ids", sizeof(u32));
	if (rc < 0)
		return 0;

	length = rc;
	if (length > chip->num_lpgs) {
		dev_err(chip->dev, "qcom,sync-channel-ids has too many channels: %d\n",
				length);
		return -EINVAL;
	}

	chip->lpg_group = devm_kcalloc(chip->dev, chip->num_lpgs,
			sizeof(u32), GFP_KERNEL);
	if (!chip->lpg_group)
		return -ENOMEM;

	rc = of_property_read_u32_array(chip->dev->of_node,
			"qcom,sync-channel-ids", chip->lpg_group, length);
	if (rc < 0) {
		dev_err(chip->dev, "Get qcom,sync-channel-ids failed, rc=%d\n",
				rc);
		return rc;
	}

	for (i = 0; i < length; i++) {
		if (chip->lpg_group[i] <= 0 ||
				chip->lpg_group[i] > chip->num_lpgs) {
			dev_err(chip->dev, "lpg_group[%d]: %d is not a valid channel\n",
					i, chip->lpg_group[i]);
			return -EINVAL;
		}
	}

	/*
	 * The LPG channel in the same group should have the same ramping
	 * configuration, so force to use the ramping configuration of the
	 * 1st LPG channel in the group for sychronization.
	 */
	lpg = &chip->lpgs[chip->lpg_group[0] - 1];
	ramp = &lpg->ramp_config;

	for (i = 1; i < length; i++) {
		lpg = &chip->lpgs[chip->lpg_group[i] - 1];
		memcpy(&lpg->ramp_config, ramp, sizeof(struct lpg_ramp_config));
	}

	return 0;
}