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

Commit 3d40e46b authored by Fenglin Wu's avatar Fenglin Wu Committed by Gerrit - the friendly Code Review server
Browse files

pwm: pwm-qpnp: Re-enable PWM output after changing mode



commit c8d3578f ("pwm: pwm-qpnp: Ignore changing period setting if
it's not requested") had fixed an issue to avoid glitches seen in PWM
output when the PWM period is not changed and the duty cycle alone is
changed. However, that didn't fix the issue completely when the LPG
channel operation mode might be configured differently even when the
duty cycle is changed and the period is unchanged. This will lead to LPG
channel getting configured to operate in a wrong mode. Fix this by
enabling PWM output whenever there is a change in the mode for LPG
channel requested by the client.

CRs-Fixed: 2070945
Change-Id: Ida6145a7cb9016e9e9116fbcd6b8ba3f6c5b3bc1
Signed-off-by: default avatarFenglin Wu <fenglinw@codeaurora.org>
parent f1ead4e3
Loading
Loading
Loading
Loading
+43 −24
Original line number Diff line number Diff line
@@ -328,6 +328,7 @@ struct qpnp_pwm_chip {
	bool			enabled;
	struct _qpnp_pwm_config	pwm_config;
	struct	qpnp_lpg_config	lpg_config;
	enum pm_pwm_mode	pwm_mode;
	spinlock_t		lpg_lock;
	enum qpnp_lpg_revision	revision;
	u8			sub_type;
@@ -1314,12 +1315,10 @@ after_table_write:
	return rc;
}

/* lpg_lock should be held while calling _pwm_enable() */
static int _pwm_enable(struct qpnp_pwm_chip *chip)
{
	int rc = 0;
	unsigned long flags;

	spin_lock_irqsave(&chip->lpg_lock, flags);

	if (QPNP_IS_PWM_CONFIG_SELECTED(
		chip->qpnp_lpg_registers[QPNP_ENABLE_CONTROL]) ||
@@ -1332,8 +1331,21 @@ static int _pwm_enable(struct qpnp_pwm_chip *chip)
	if (!rc)
		chip->enabled = true;

	spin_unlock_irqrestore(&chip->lpg_lock, flags);
	return rc;
}

/* lpg_lock should be held while calling _pwm_change_mode() */
static int _pwm_change_mode(struct qpnp_pwm_chip *chip, enum pm_pwm_mode mode)
{
	int rc;

	if (mode == PM_PWM_MODE_LPG)
		rc = qpnp_configure_lpg_control(chip);
	else
		rc = qpnp_configure_pwm_control(chip);

	if (rc)
		pr_err("Failed to change the mode\n");
	return rc;
}

@@ -1410,11 +1422,15 @@ static int qpnp_pwm_enable(struct pwm_chip *pwm_chip,
{
	int rc;
	struct qpnp_pwm_chip *chip = qpnp_pwm_from_pwm_chip(pwm_chip);
	unsigned long flags;

	spin_lock_irqsave(&chip->lpg_lock, flags);
	rc = _pwm_enable(chip);
	if (rc)
		pr_err("Failed to enable PWM channel: %d\n", chip->channel_id);

	spin_unlock_irqrestore(&chip->lpg_lock, flags);

	return rc;
}

@@ -1452,20 +1468,6 @@ static void qpnp_pwm_disable(struct pwm_chip *pwm_chip,
					chip->channel_id);
}

static int _pwm_change_mode(struct qpnp_pwm_chip *chip, enum pm_pwm_mode mode)
{
	int rc;

	if (mode)
		rc = qpnp_configure_lpg_control(chip);
	else
		rc = qpnp_configure_pwm_control(chip);

	if (rc)
		pr_err("Failed to change the mode\n");
	return rc;
}

/**
 * pwm_change_mode - Change the PWM mode configuration
 * @pwm: the PWM device
@@ -1490,7 +1492,22 @@ int pwm_change_mode(struct pwm_device *pwm, enum pm_pwm_mode mode)
	chip = qpnp_pwm_from_pwm_dev(pwm);

	spin_lock_irqsave(&chip->lpg_lock, flags);
	if (chip->pwm_mode != mode) {
		rc = _pwm_change_mode(chip, mode);
		if (rc) {
			pr_err("Failed to change mode: %d, rc=%d\n", mode, rc);
			goto unlock;
		}
		chip->pwm_mode = mode;
		if (chip->enabled) {
			rc = _pwm_enable(chip);
			if (rc) {
				pr_err("Failed to enable PWM, rc=%d\n", rc);
				goto unlock;
			}
		}
	}
unlock:
	spin_unlock_irqrestore(&chip->lpg_lock, flags);

	return rc;
@@ -1894,7 +1911,7 @@ out:
static int qpnp_parse_dt_config(struct platform_device *pdev,
					struct qpnp_pwm_chip *chip)
{
	int			rc, enable, lut_entry_size, list_size, i;
	int			rc, mode, lut_entry_size, list_size, i;
	const char		*label;
	const __be32		*prop;
	u32			size;
@@ -2078,18 +2095,20 @@ static int qpnp_parse_dt_config(struct platform_device *pdev,
		}
	}

	rc = of_property_read_u32(of_node, "qcom,mode-select", &enable);
	rc = of_property_read_u32(of_node, "qcom,mode-select", &mode);
	if (rc)
		goto read_opt_props;

	if ((enable == PM_PWM_MODE_PWM && found_pwm_subnode == 0) ||
		(enable == PM_PWM_MODE_LPG && found_lpg_subnode == 0)) {
	if (mode > PM_PWM_MODE_LPG ||
		(mode == PM_PWM_MODE_PWM && found_pwm_subnode == 0) ||
		(mode == PM_PWM_MODE_LPG && found_lpg_subnode == 0)) {
		dev_err(&pdev->dev, "%s: Invalid mode select\n", __func__);
		rc = -EINVAL;
		goto out;
	}

	_pwm_change_mode(chip, enable);
	chip->pwm_mode = mode;
	_pwm_change_mode(chip, mode);
	_pwm_enable(chip);

read_opt_props: