diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-01-07 14:17:00 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-01-07 14:17:00 +1100 |
commit | a228f3b761172cfd46381c7cfdac267004a7bb4e (patch) | |
tree | a6947effc82f8b2534a3c381177b0184c3434837 /drivers | |
parent | 091374ab6d0630047e6a3d0d671c7fa7c3459efb (diff) | |
parent | a4b89b319a6ed5b5e0fd460bb11632d4cbd91980 (diff) |
Merge remote branch 'voltage/for-next'
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/regulator/core.c | 48 | ||||
-rw-r--r-- | drivers/regulator/lp3971.c | 10 | ||||
-rw-r--r-- | drivers/regulator/mc13783-regulator.c | 345 | ||||
-rw-r--r-- | drivers/regulator/wm8350-regulator.c | 46 |
4 files changed, 406 insertions, 43 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 686ef270ecf7..5a3509b835f4 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -19,6 +19,7 @@ #include <linux/err.h> #include <linux/mutex.h> #include <linux/suspend.h> +#include <linux/delay.h> #include <linux/regulator/consumer.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> @@ -1084,6 +1085,13 @@ overflow_err: return NULL; } +static int _regulator_get_enable_time(struct regulator_dev *rdev) +{ + if (!rdev->desc->ops->enable_time) + return 0; + return rdev->desc->ops->enable_time(rdev); +} + /* Internal regulator request function */ static struct regulator *_regulator_get(struct device *dev, const char *id, int exclusive) @@ -1251,7 +1259,7 @@ static int _regulator_can_change_status(struct regulator_dev *rdev) /* locks held by regulator_enable() */ static int _regulator_enable(struct regulator_dev *rdev) { - int ret; + int ret, delay; /* do we need to enable the supply regulator first */ if (rdev->supply) { @@ -1275,13 +1283,34 @@ static int _regulator_enable(struct regulator_dev *rdev) if (!_regulator_can_change_status(rdev)) return -EPERM; - if (rdev->desc->ops->enable) { - ret = rdev->desc->ops->enable(rdev); - if (ret < 0) - return ret; - } else { + if (!rdev->desc->ops->enable) return -EINVAL; + + /* Query before enabling in case configuration + * dependant. */ + ret = _regulator_get_enable_time(rdev); + if (ret >= 0) { + delay = ret; + } else { + printk(KERN_WARNING + "%s: enable_time() failed for %s: %d\n", + __func__, rdev_get_name(rdev), + ret); + delay = 0; } + + /* Allow the regulator to ramp; it would be useful + * to extend this for bulk operations so that the + * regulators can ramp together. */ + ret = rdev->desc->ops->enable(rdev); + if (ret < 0) + return ret; + + if (delay >= 1000) + mdelay(delay / 1000); + else if (delay) + udelay(delay); + } else if (ret < 0) { printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n", __func__, rdev_get_name(rdev), ret); @@ -1341,6 +1370,9 @@ static int _regulator_disable(struct regulator_dev *rdev) __func__, rdev_get_name(rdev)); return ret; } + + _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, + NULL); } /* decrease our supplies ref count and disable if required */ @@ -1399,8 +1431,8 @@ static int _regulator_force_disable(struct regulator_dev *rdev) return ret; } /* notify other consumers that power has been forced off */ - _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE, - NULL); + _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | + REGULATOR_EVENT_DISABLE, NULL); } /* decrease our supplies ref count and disable if required */ diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 76d08c282f9c..9416f0cac1b3 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -54,7 +54,7 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val); #define LP3971_BUCK2_BASE 0x29 #define LP3971_BUCK3_BASE 0x32 -const static int buck_base_addr[] = { +static const int buck_base_addr[] = { LP3971_BUCK1_BASE, LP3971_BUCK2_BASE, LP3971_BUCK3_BASE, @@ -63,7 +63,7 @@ const static int buck_base_addr[] = { #define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x]) #define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1) -const static int buck_voltage_map[] = { +static const int buck_voltage_map[] = { 0, 800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500, 1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800, @@ -96,17 +96,17 @@ const static int buck_voltage_map[] = { #define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2) #define LDO_VOL_CONTR_MASK 0x0f -const static int ldo45_voltage_map[] = { +static const int ldo45_voltage_map[] = { 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300, }; -const static int ldo123_voltage_map[] = { +static const int ldo123_voltage_map[] = { 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, }; -const static int *ldo_voltage_map[] = { +static const int *ldo_voltage_map[] = { ldo123_voltage_map, /* LDO1 */ ldo123_voltage_map, /* LDO2 */ ldo123_voltage_map, /* LDO3 */ diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 39c495300045..a40e35ab8555 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -2,6 +2,7 @@ * Regulator Driver for Freescale MC13783 PMIC * * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> + * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,11 +17,44 @@ #include <linux/init.h> #include <linux/err.h> -#define MC13783_REG_SWITCHERS4 28 -#define MC13783_REG_SWITCHERS4_PLLEN (1 << 18) - #define MC13783_REG_SWITCHERS5 29 #define MC13783_REG_SWITCHERS5_SW3EN (1 << 20) +#define MC13783_REG_SWITCHERS5_SW3VSEL 18 +#define MC13783_REG_SWITCHERS5_SW3VSEL_M (3 << 18) + +#define MC13783_REG_REGULATORSETTING0 30 +#define MC13783_REG_REGULATORSETTING0_VIOLOVSEL 2 +#define MC13783_REG_REGULATORSETTING0_VDIGVSEL 4 +#define MC13783_REG_REGULATORSETTING0_VGENVSEL 6 +#define MC13783_REG_REGULATORSETTING0_VRFDIGVSEL 9 +#define MC13783_REG_REGULATORSETTING0_VRFREFVSEL 11 +#define MC13783_REG_REGULATORSETTING0_VRFCPVSEL 13 +#define MC13783_REG_REGULATORSETTING0_VSIMVSEL 14 +#define MC13783_REG_REGULATORSETTING0_VESIMVSEL 15 +#define MC13783_REG_REGULATORSETTING0_VCAMVSEL 16 + +#define MC13783_REG_REGULATORSETTING0_VIOLOVSEL_M (3 << 2) +#define MC13783_REG_REGULATORSETTING0_VDIGVSEL_M (3 << 4) +#define MC13783_REG_REGULATORSETTING0_VGENVSEL_M (7 << 6) +#define MC13783_REG_REGULATORSETTING0_VRFDIGVSEL_M (3 << 9) +#define MC13783_REG_REGULATORSETTING0_VRFREFVSEL_M (3 << 11) +#define MC13783_REG_REGULATORSETTING0_VRFCPVSEL_M (1 << 13) +#define MC13783_REG_REGULATORSETTING0_VSIMVSEL_M (1 << 14) +#define MC13783_REG_REGULATORSETTING0_VESIMVSEL_M (1 << 15) +#define MC13783_REG_REGULATORSETTING0_VCAMVSEL_M (7 << 16) + +#define MC13783_REG_REGULATORSETTING1 31 +#define MC13783_REG_REGULATORSETTING1_VVIBVSEL 0 +#define MC13783_REG_REGULATORSETTING1_VRF1VSEL 2 +#define MC13783_REG_REGULATORSETTING1_VRF2VSEL 4 +#define MC13783_REG_REGULATORSETTING1_VMMC1VSEL 6 +#define MC13783_REG_REGULATORSETTING1_VMMC2VSEL 9 + +#define MC13783_REG_REGULATORSETTING1_VVIBVSEL_M (3 << 0) +#define MC13783_REG_REGULATORSETTING1_VRF1VSEL_M (3 << 2) +#define MC13783_REG_REGULATORSETTING1_VRF2VSEL_M (3 << 4) +#define MC13783_REG_REGULATORSETTING1_VMMC1VSEL_M (7 << 6) +#define MC13783_REG_REGULATORSETTING1_VMMC2VSEL_M (7 << 9) #define MC13783_REG_REGULATORMODE0 32 #define MC13783_REG_REGULATORMODE0_VAUDIOEN (1 << 0) @@ -53,14 +87,88 @@ struct mc13783_regulator { struct regulator_desc desc; int reg; int enable_bit; + int vsel_reg; + int vsel_shift; + int vsel_mask; + int const *voltages; +}; + +/* Voltage Values */ +static const int const mc13783_sw3_val[] = { + 5000000, 5000000, 5000000, 5500000, +}; + +static const int const mc13783_vaudio_val[] = { + 2775000, +}; + +static const int const mc13783_viohi_val[] = { + 2775000, +}; + +static const int const mc13783_violo_val[] = { + 1200000, 1300000, 1500000, 1800000, +}; + +static const int const mc13783_vdig_val[] = { + 1200000, 1300000, 1500000, 1800000, +}; + +static const int const mc13783_vgen_val[] = { + 1200000, 1300000, 1500000, 1800000, + 1100000, 2000000, 2775000, 2400000, +}; + +static const int const mc13783_vrfdig_val[] = { + 1200000, 1500000, 1800000, 1875000, +}; + +static const int const mc13783_vrfref_val[] = { + 2475000, 2600000, 2700000, 2775000, +}; + +static const int const mc13783_vrfcp_val[] = { + 2700000, 2775000, +}; + +static const int const mc13783_vsim_val[] = { + 1800000, 2900000, 3000000, +}; + +static const int const mc13783_vesim_val[] = { + 1800000, 2900000, +}; + +static const int const mc13783_vcam_val[] = { + 1500000, 1800000, 2500000, 2550000, + 2600000, 2750000, 2800000, 3000000, +}; + +static const int const mc13783_vrfbg_val[] = { + 1250000, +}; + +static const int const mc13783_vvib_val[] = { + 1300000, 1800000, 2000000, 3000000, +}; + +static const int const mc13783_vmmc_val[] = { + 1600000, 1800000, 2000000, 2600000, + 2700000, 2800000, 2900000, 3000000, +}; + +static const int const mc13783_vrf_val[] = { + 1500000, 1875000, 2700000, 2775000, }; static struct regulator_ops mc13783_regulator_ops; +static struct regulator_ops mc13783_fixed_regulator_ops; -#define MC13783_DEFINE(prefix, _name, _reg) \ +#define MC13783_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages) \ [MC13783_ ## prefix ## _ ## _name] = { \ .desc = { \ .name = #prefix "_" #_name, \ + .n_voltages = ARRAY_SIZE(_voltages), \ .ops = &mc13783_regulator_ops, \ .type = REGULATOR_VOLTAGE, \ .id = MC13783_ ## prefix ## _ ## _name, \ @@ -68,36 +176,83 @@ static struct regulator_ops mc13783_regulator_ops; }, \ .reg = MC13783_REG_ ## _reg, \ .enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \ + .vsel_reg = MC13783_REG_ ## _vsel_reg, \ + .vsel_shift = MC13783_REG_ ## _vsel_reg ## _ ## _name ## VSEL,\ + .vsel_mask = MC13783_REG_ ## _vsel_reg ## _ ## _name ## VSEL_M,\ + .voltages = _voltages, \ } -#define MC13783_DEFINE_SW(_name, _reg) MC13783_DEFINE(SW, _name, _reg) -#define MC13783_DEFINE_REGU(_name, _reg) MC13783_DEFINE(REGU, _name, _reg) +#define MC13783_FIXED_DEFINE(prefix, _name, _reg, _voltages) \ + [MC13783_ ## prefix ## _ ## _name] = { \ + .desc = { \ + .name = #prefix "_" #_name, \ + .n_voltages = ARRAY_SIZE(_voltages), \ + .ops = &mc13783_fixed_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MC13783_ ## prefix ## _ ## _name, \ + .owner = THIS_MODULE, \ + }, \ + .reg = MC13783_REG_ ## _reg, \ + .enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \ + .voltages = _voltages, \ + } + +#define MC13783_GPO_DEFINE(prefix, _name, _reg) \ + [MC13783_ ## prefix ## _ ## _name] = { \ + .desc = { \ + .name = #prefix "_" #_name, \ + .ops = &mc13783_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MC13783_ ## prefix ## _ ## _name, \ + .owner = THIS_MODULE, \ + }, \ + .reg = MC13783_REG_ ## _reg, \ + .enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \ + } + +#define MC13783_DEFINE_SW(_name, _reg, _vsel_reg, _voltages) \ + MC13783_DEFINE(SW, _name, _reg, _vsel_reg, _voltages) +#define MC13783_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages) \ + MC13783_DEFINE(REGU, _name, _reg, _vsel_reg, _voltages) static struct mc13783_regulator mc13783_regulators[] = { - MC13783_DEFINE_SW(SW3, SWITCHERS5), - MC13783_DEFINE_SW(PLL, SWITCHERS4), - - MC13783_DEFINE_REGU(VAUDIO, REGULATORMODE0), - MC13783_DEFINE_REGU(VIOHI, REGULATORMODE0), - MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0), - MC13783_DEFINE_REGU(VDIG, REGULATORMODE0), - MC13783_DEFINE_REGU(VGEN, REGULATORMODE0), - MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0), - MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0), - MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0), - MC13783_DEFINE_REGU(VSIM, REGULATORMODE1), - MC13783_DEFINE_REGU(VESIM, REGULATORMODE1), - MC13783_DEFINE_REGU(VCAM, REGULATORMODE1), - MC13783_DEFINE_REGU(VRFBG, REGULATORMODE1), - MC13783_DEFINE_REGU(VVIB, REGULATORMODE1), - MC13783_DEFINE_REGU(VRF1, REGULATORMODE1), - MC13783_DEFINE_REGU(VRF2, REGULATORMODE1), - MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1), - MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1), - MC13783_DEFINE_REGU(GPO1, POWERMISC), - MC13783_DEFINE_REGU(GPO2, POWERMISC), - MC13783_DEFINE_REGU(GPO3, POWERMISC), - MC13783_DEFINE_REGU(GPO4, POWERMISC), + MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val), + + MC13783_FIXED_DEFINE(REGU, VAUDIO, REGULATORMODE0, mc13783_vaudio_val), + MC13783_FIXED_DEFINE(REGU, VIOHI, REGULATORMODE0, mc13783_viohi_val), + MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0, \ + mc13783_violo_val), + MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, \ + mc13783_vdig_val), + MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0, \ + mc13783_vgen_val), + MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0, \ + mc13783_vrfdig_val), + MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0, \ + mc13783_vrfref_val), + MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0, \ + mc13783_vrfcp_val), + MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0, \ + mc13783_vsim_val), + MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0, \ + mc13783_vesim_val), + MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, \ + mc13783_vcam_val), + MC13783_FIXED_DEFINE(REGU, VRFBG, REGULATORMODE1, mc13783_vrfbg_val), + MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1, \ + mc13783_vvib_val), + MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1, \ + mc13783_vrf_val), + MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1, \ + mc13783_vrf_val), + MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1, \ + mc13783_vmmc_val), + MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1, \ + mc13783_vmmc_val), + MC13783_GPO_DEFINE(REGU, GPO1, POWERMISC), + MC13783_GPO_DEFINE(REGU, GPO2, POWERMISC), + MC13783_GPO_DEFINE(REGU, GPO3, POWERMISC), + MC13783_GPO_DEFINE(REGU, GPO4, POWERMISC), }; struct mc13783_regulator_priv { @@ -154,10 +309,140 @@ static int mc13783_regulator_is_enabled(struct regulator_dev *rdev) return (val & mc13783_regulators[id].enable_bit) != 0; } +static int mc13783_regulator_list_voltage(struct regulator_dev *rdev, + unsigned selector) +{ + int id = rdev_get_id(rdev); + + if (selector >= mc13783_regulators[id].desc.n_voltages) + return -EINVAL; + + return mc13783_regulators[id].voltages[selector]; +} + +static int mc13783_get_best_voltage_index(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + int reg_id = rdev_get_id(rdev); + int i; + int bestmatch; + int bestindex; + + /* + * Locate the minimum voltage fitting the criteria on + * this regulator. The switchable voltages are not + * in strict falling order so we need to check them + * all for the best match. + */ + bestmatch = INT_MAX; + bestindex = -1; + for (i = 0; i < mc13783_regulators[reg_id].desc.n_voltages; i++) { + if (mc13783_regulators[reg_id].voltages[i] >= min_uV && + mc13783_regulators[reg_id].voltages[i] < bestmatch) { + bestmatch = mc13783_regulators[reg_id].voltages[i]; + bestindex = i; + } + } + + if (bestindex < 0 || bestmatch > max_uV) { + dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n", + min_uV, max_uV); + return -EINVAL; + } + return bestindex; +} + +static int mc13783_regulator_set_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); + int value, id = rdev_get_id(rdev); + int ret; + + dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", + __func__, id, min_uV, max_uV); + + /* Find the best index */ + value = mc13783_get_best_voltage_index(rdev, min_uV, max_uV); + dev_dbg(rdev_get_dev(rdev), "%s best value: %d \n", __func__, value); + if (value < 0) + return value; + + mc13783_lock(priv->mc13783); + ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].vsel_reg, + mc13783_regulators[id].vsel_mask, + value << mc13783_regulators[id].vsel_shift); + mc13783_unlock(priv->mc13783); + + return ret; +} + +static int mc13783_regulator_get_voltage(struct regulator_dev *rdev) +{ + struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); + int ret, id = rdev_get_id(rdev); + unsigned int val; + + dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); + + mc13783_lock(priv->mc13783); + ret = mc13783_reg_read(priv->mc13783, + mc13783_regulators[id].vsel_reg, &val); + mc13783_unlock(priv->mc13783); + + if (ret) + return ret; + + val = (val & mc13783_regulators[id].vsel_mask) + >> mc13783_regulators[id].vsel_shift; + + dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); + + BUG_ON(val < 0 || val > mc13783_regulators[id].desc.n_voltages); + + return mc13783_regulators[id].voltages[val]; +} + static struct regulator_ops mc13783_regulator_ops = { .enable = mc13783_regulator_enable, .disable = mc13783_regulator_disable, .is_enabled = mc13783_regulator_is_enabled, + .list_voltage = mc13783_regulator_list_voltage, + .set_voltage = mc13783_regulator_set_voltage, + .get_voltage = mc13783_regulator_get_voltage, +}; + +static int mc13783_fixed_regulator_set_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + int id = rdev_get_id(rdev); + + dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", + __func__, id, min_uV, max_uV); + + if (min_uV > mc13783_regulators[id].voltages[0] && + max_uV < mc13783_regulators[id].voltages[0]) + return 0; + else + return -EINVAL; +} + +static int mc13783_fixed_regulator_get_voltage(struct regulator_dev *rdev) +{ + int id = rdev_get_id(rdev); + + dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); + + return mc13783_regulators[id].voltages[0]; +} + +static struct regulator_ops mc13783_fixed_regulator_ops = { + .enable = mc13783_regulator_enable, + .disable = mc13783_regulator_disable, + .is_enabled = mc13783_regulator_is_enabled, + .list_voltage = mc13783_regulator_list_voltage, + .set_voltage = mc13783_fixed_regulator_set_voltage, + .get_voltage = mc13783_fixed_regulator_get_voltage, }; static int __devinit mc13783_regulator_probe(struct platform_device *pdev) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 0764a0b60658..8e90acf1a183 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -290,6 +290,51 @@ static int wm8350_isink_is_enabled(struct regulator_dev *rdev) return -EINVAL; } +static int wm8350_isink_enable_time(struct regulator_dev *rdev) +{ + struct wm8350 *wm8350 = rdev_get_drvdata(rdev); + int isink = rdev_get_id(rdev); + int reg; + + switch (isink) { + case WM8350_ISINK_A: + reg = wm8350_reg_read(wm8350, WM8350_CSA_FLASH_CONTROL); + break; + case WM8350_ISINK_B: + reg = wm8350_reg_read(wm8350, WM8350_CSB_FLASH_CONTROL); + break; + default: + return -EINVAL; + } + + if (reg & WM8350_CS1_FLASH_MODE) { + switch (reg & WM8350_CS1_ON_RAMP_MASK) { + case 0: + return 0; + case 1: + return 1950; + case 2: + return 3910; + case 3: + return 7800; + } + } else { + switch (reg & WM8350_CS1_ON_RAMP_MASK) { + case 0: + return 0; + case 1: + return 250000; + case 2: + return 500000; + case 3: + return 1000000; + } + } + + return -EINVAL; +} + + int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode, u16 trigger, u16 duration, u16 on_ramp, u16 off_ramp, u16 drive) @@ -1221,6 +1266,7 @@ static struct regulator_ops wm8350_isink_ops = { .enable = wm8350_isink_enable, .disable = wm8350_isink_disable, .is_enabled = wm8350_isink_is_enabled, + .enable_time = wm8350_isink_enable_time, }; static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { |