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

Commit e137b4a2 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

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

parents f9443ce7 f8b640fb
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;
}