diff --git a/drivers/leds/leds-pm8xxx.c b/drivers/leds/leds-pm8xxx.c index c3a55647080..aef6295db08 100644 --- a/drivers/leds/leds-pm8xxx.c +++ b/drivers/leds/leds-pm8xxx.c @@ -133,6 +133,11 @@ _rgb_led_blue << PM8XXX_ID_RGB_LED_BLUE, \ } +#define PM8XXX_PWM_CURRENT_4MA 4 +#define PM8XXX_PWM_CURRENT_8MA 8 +#define PM8XXX_PWM_CURRENT_12MA 12 + + /** * supported_leds - leds supported for each PMIC version * @version - version of PMIC @@ -795,7 +800,7 @@ static int __devinit get_init_value(struct pm8xxx_led_data *led, u8 *val) static int pm8xxx_led_pwm_configure(struct pm8xxx_led_data *led) { - int start_idx, idx_len, duty_us, rc; + int start_idx, idx_len, duty_us, rc, flags; led->pwm_dev = pwm_request(led->pwm_channel, led->cdev.name); @@ -808,6 +813,22 @@ static int pm8xxx_led_pwm_configure(struct pm8xxx_led_data *led) return -ENODEV; } + flags = PM8XXX_LED_PWM_FLAGS; + switch (led->max_current) { + case PM8XXX_PWM_CURRENT_4MA: + flags |= PM_PWM_BANK_LO; + break; + case PM8XXX_PWM_CURRENT_8MA: + flags |= PM_PWM_BANK_HI; + break; + case PM8XXX_PWM_CURRENT_12MA: + flags |= (PM_PWM_BANK_LO | PM_PWM_BANK_HI); + break; + default: + flags |= (PM_PWM_BANK_LO | PM_PWM_BANK_HI); + break; + } + if (led->pwm_duty_cycles != NULL) { start_idx = led->pwm_duty_cycles->start_idx; idx_len = led->pwm_duty_cycles->num_duty_pcts; @@ -825,7 +846,7 @@ static int pm8xxx_led_pwm_configure(struct pm8xxx_led_data *led) led->pwm_duty_cycles->duty_pcts, led->pwm_duty_cycles->duty_ms, start_idx, idx_len, 0, 0, - PM8XXX_LED_PWM_FLAGS); + flags); } else { duty_us = led->pwm_period_us; rc = pwm_config(led->pwm_dev, duty_us, led->pwm_period_us); diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c index caaba81cb5d..0388484e9b0 100644 --- a/drivers/mfd/pm8xxx-pwm.c +++ b/drivers/mfd/pm8xxx-pwm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -58,10 +58,11 @@ #define PM8XXX_PWM_DISABLE 0x3F /* PM8XXX LPG PWM */ +#define SSBI_REG_ADDR_LPG_BANK_LOW_EN 0x130 #define SSBI_REG_ADDR_LPG_CTL_BASE 0x13C #define SSBI_REG_ADDR_LPG_CTL(n) (SSBI_REG_ADDR_LPG_CTL_BASE + (n)) #define SSBI_REG_ADDR_LPG_BANK_SEL 0x143 -#define SSBI_REG_ADDR_LPG_BANK_EN 0x144 +#define SSBI_REG_ADDR_LPG_BANK_HIGH_EN 0x144 #define SSBI_REG_ADDR_LPG_LUT_CFG0 0x145 #define SSBI_REG_ADDR_LPG_LUT_CFG1 0x146 #define SSBI_REG_ADDR_LPG_TEST 0x147 @@ -206,13 +207,15 @@ struct pwm_device { struct pm8xxx_pwm_chip *chip; int bypass_lut; int dtest_mode_supported; + int banks; }; struct pm8xxx_pwm_chip { struct pwm_device *pwm_dev; u8 pwm_channels; u8 pwm_total_pre_divs; - u8 bank_mask; + u8 lo_bank_mask; + u8 hi_bank_mask; struct mutex pwm_mutex; struct device *dev; bool is_lpg_supported; @@ -259,18 +262,37 @@ static int pm8xxx_pwm_bank_enable(struct pwm_device *pwm, int enable) chip = pwm->chip; - if (enable) - reg = chip->bank_mask | (1 << pwm->pwm_id); - else - reg = chip->bank_mask & ~(1 << pwm->pwm_id); + if (pwm->banks & PM_PWM_BANK_LO) { + if (enable) + reg = chip->lo_bank_mask | (1 << pwm->pwm_id); + else + reg = chip->lo_bank_mask & ~(1 << pwm->pwm_id); - rc = pm8xxx_writeb(chip->dev->parent, SSBI_REG_ADDR_LPG_BANK_EN, reg); - if (rc) { - pr_err("pm8xxx_writeb(): rc=%d (Enable LPG Bank)\n", rc); - return rc; + rc = pm8xxx_writeb(chip->dev->parent, + SSBI_REG_ADDR_LPG_BANK_LOW_EN, reg); + if (rc) { + pr_err("pm8xxx_writeb(): Enable Bank Low =%d\n", rc); + return rc; + } + + chip->lo_bank_mask = reg; } - chip->bank_mask = reg; + if (pwm->banks & PM_PWM_BANK_HI) { + if (enable) + reg = chip->hi_bank_mask | (1 << pwm->pwm_id); + else + reg = chip->hi_bank_mask & ~(1 << pwm->pwm_id); + + rc = pm8xxx_writeb(chip->dev->parent, + SSBI_REG_ADDR_LPG_BANK_HIGH_EN, reg); + if (rc) { + pr_err("pm8xxx_writeb(): Enable Bank High =%d\n", rc); + return rc; + } + + chip->hi_bank_mask = reg; + } return 0; } @@ -1010,6 +1032,16 @@ int pm8xxx_pwm_lut_config(struct pwm_device *pwm, int period_us, period = &pwm->period; mutex_lock(&pwm->chip->pwm_mutex); + if (flags & PM_PWM_BANK_HI) + pwm->banks = PM_PWM_BANK_HI; + + if (flags & PM_PWM_BANK_LO) + pwm->banks |= PM_PWM_BANK_LO; + + /*Enable both banks if banks information is not shared.*/ + if (!pwm->banks) + pwm->banks |= (PM_PWM_BANK_LO | PM_PWM_BANK_HI); + if (!pwm->in_use) { pr_err("pwm_id: %d: stale handle?\n", pwm->pwm_id); rc = -EINVAL; diff --git a/include/linux/mfd/pm8xxx/pwm.h b/include/linux/mfd/pm8xxx/pwm.h index 6d95e3a4b57..47ebe06a16b 100644 --- a/include/linux/mfd/pm8xxx/pwm.h +++ b/include/linux/mfd/pm8xxx/pwm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,6 +32,9 @@ #define PM_PWM_LUT_NO_TABLE 0x100 +#define PM_PWM_BANK_LO 0x1000 +#define PM_PWM_BANK_HI 0x2000 + /** * PWM frequency/period control *