diff options
| -rw-r--r-- | drivers/leds/leds-qpnp.c | 29 | ||||
| -rw-r--r-- | drivers/pwm/pwm-qpnp.c | 67 |
2 files changed, 72 insertions, 24 deletions
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c index ab0e4f99ebb9..e3cfffb5c563 100644 --- a/drivers/leds/leds-qpnp.c +++ b/drivers/leds/leds-qpnp.c @@ -875,6 +875,14 @@ static int qpnp_mpp_set(struct qpnp_led_data *led) } if (led->mpp_cfg->pwm_mode == PWM_MODE) { /*config pwm for brightness scaling*/ + rc = pwm_change_mode(led->mpp_cfg->pwm_cfg->pwm_dev, + PM_PWM_MODE_PWM); + if (rc < 0) { + dev_err(&led->pdev->dev, + "Failed to set PWM mode, rc = %d\n", + rc); + return rc; + } period_us = led->mpp_cfg->pwm_cfg->pwm_period_us; if (period_us > INT_MAX / NSEC_PER_USEC) { duty_us = (period_us * led->cdev.brightness) / @@ -1581,6 +1589,14 @@ static int qpnp_kpdbl_set(struct qpnp_led_data *led) } if (led->kpdbl_cfg->pwm_cfg->mode == PWM_MODE) { + rc = pwm_change_mode(led->kpdbl_cfg->pwm_cfg->pwm_dev, + PM_PWM_MODE_PWM); + if (rc < 0) { + dev_err(&led->pdev->dev, + "Failed to set PWM mode, rc = %d\n", + rc); + return rc; + } period_us = led->kpdbl_cfg->pwm_cfg->pwm_period_us; if (period_us > INT_MAX / NSEC_PER_USEC) { duty_us = (period_us * led->cdev.brightness) / @@ -1702,6 +1718,14 @@ static int qpnp_rgb_set(struct qpnp_led_data *led) led->rgb_cfg->pwm_cfg->mode = led->rgb_cfg->pwm_cfg->default_mode; if (led->rgb_cfg->pwm_cfg->mode == PWM_MODE) { + rc = pwm_change_mode(led->rgb_cfg->pwm_cfg->pwm_dev, + PM_PWM_MODE_PWM); + if (rc < 0) { + dev_err(&led->pdev->dev, + "Failed to set PWM mode, rc = %d\n", + rc); + return rc; + } period_us = led->rgb_cfg->pwm_cfg->pwm_period_us; if (period_us > INT_MAX / NSEC_PER_USEC) { duty_us = (period_us * led->cdev.brightness) / @@ -2136,6 +2160,11 @@ static int qpnp_pwm_init(struct pwm_config_data *pwm_cfg, dev_err(&pdev->dev, "Failed to configure pwm LUT\n"); return rc; } + rc = pwm_change_mode(pwm_cfg->pwm_dev, PM_PWM_MODE_LPG); + if (rc < 0) { + dev_err(&pdev->dev, "Failed to set LPG mode\n"); + return rc; + } } } else { dev_err(&pdev->dev, "Invalid PWM device\n"); diff --git a/drivers/pwm/pwm-qpnp.c b/drivers/pwm/pwm-qpnp.c index e46b1d583f40..2531b74b4588 100644 --- a/drivers/pwm/pwm-qpnp.c +++ b/drivers/pwm/pwm-qpnp.c @@ -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); - rc = _pwm_change_mode(chip, mode); + 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: |
