Merge remote-tracking branches 'regulator/topic/core', 'regulator/topic/regmap' and...
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Sat, 12 May 2012 10:09:47 +0000 (11:09 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Sat, 12 May 2012 10:09:47 +0000 (11:09 +0100)
1  2  3 
drivers/regulator/anatop-regulator.c
drivers/regulator/core.c
include/linux/mfd/rc5t583.h
sound/soc/codecs/sgtl5000.c

index 81fd606e47bc8d198d8bbab301b651e061d9a74d,17499a55113ddedd9f1c7a22588b6e3caeda0d77,8675c91ed21aa2ba0e66090ef2db1981a129c865..49b2112b0486120c5434f7e2295955202538387f
@@@@ -122,6 -122,6 -122,7 +122,7 @@@@ static int __devinit anatop_regulator_p
        struct anatop_regulator *sreg;
        struct regulator_init_data *initdata;
        struct anatop *anatopmfd = dev_get_drvdata(pdev->dev.parent);
++      struct regulator_config config = { };
        int ret = 0;
   
        initdata = of_get_regulator_init_data(dev, np);
        rdesc->type = REGULATOR_VOLTAGE;
        rdesc->owner = THIS_MODULE;
        sreg->mfd = anatopmfd;
 -      ret = of_property_read_u32(np, "reg", &sreg->control_reg);
 +      ret = of_property_read_u32(np, "anatop-reg-offset",
 +                                 &sreg->control_reg);
        if (ret) {
 -              dev_err(dev, "no reg property set\n");
 +              dev_err(dev, "no anatop-reg-offset property set\n");
                goto anatop_probe_end;
        }
        ret = of_property_read_u32(np, "anatop-vol-bit-width",
        rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage)
                / 25000 + 1;
   
++      config.dev = &pdev->dev;
++      config.init_data = initdata;
++      config.driver_data = sreg;
++      config.of_node = pdev->dev.of_node;
++ 
        /* register regulator */
--      rdev = regulator_register(rdesc, dev,
--                                initdata, sreg, pdev->dev.of_node);
++      rdev = regulator_register(rdesc, &config);
        if (IS_ERR(rdev)) {
                dev_err(dev, "failed to register %s\n",
                        rdesc->name);
@@@@ -214,7 -213,7 -219,7 +219,7 @@@@ static struct of_device_id __devinitdat
        { /* end */ }
   };
   
 --static struct platform_driver anatop_regulator = {
 ++static struct platform_driver anatop_regulator_driver = {
        .driver = {
                .name   = "anatop_regulator",
                .owner  = THIS_MODULE,
   
   static int __init anatop_regulator_init(void)
   {
 --     return platform_driver_register(&anatop_regulator);
 ++     return platform_driver_register(&anatop_regulator_driver);
   }
   postcore_initcall(anatop_regulator_init);
   
   static void __exit anatop_regulator_exit(void)
   {
 --     platform_driver_unregister(&anatop_regulator);
 ++     platform_driver_unregister(&anatop_regulator_driver);
   }
   module_exit(anatop_regulator_exit);
   
diff --combined drivers/regulator/core.c
index e70dd382a009a2db05d78087b6e0e588584e6b6e,4b2c02c519f05097095b7d2086e726afaba3b6ba,10fb252323fbb007ba6183f2ea0ae5cefed39e1f..aec7ad5cb2d326e798a395e2beadf8554c799136
   #include <linux/suspend.h>
   #include <linux/delay.h>
   #include <linux/of.h>
++ #include <linux/regmap.h>
   #include <linux/regulator/of_regulator.h>
   #include <linux/regulator/consumer.h>
   #include <linux/regulator/driver.h>
@@@@ -74,6 -74,7 -75,6 +75,7 @@@@ struct regulator_map 
   struct regulator {
        struct device *dev;
        struct list_head list;
+ +     unsigned int always_on:1;
        int uA_load;
        int min_uV;
        int max_uV;
@@@@ -155,6 -156,17 -156,6 +157,17 @@@@ static struct device_node *of_get_regul
        return regnode;
   }
   
+ +static int _regulator_can_change_status(struct regulator_dev *rdev)
+ +{
+ +     if (!rdev->constraints)
+ +             return 0;
+ +
+ +     if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
+ +             return 1;
+ +     else
+ +             return 0;
+ +}
+ +
   /* Platform voltage constraint check */
   static int regulator_check_voltage(struct regulator_dev *rdev,
                                   int *min_uV, int *max_uV)
@@@@ -649,7 -661,7 -650,7 +662,7 @@@@ static void drms_uA_update(struct regul
        /* get input voltage */
        input_uV = 0;
        if (rdev->supply)
- -             input_uV = _regulator_get_voltage(rdev);
+ +             input_uV = regulator_get_voltage(rdev->supply);
        if (input_uV <= 0)
                input_uV = rdev->constraints->input_uV;
        if (input_uV <= 0)
@@@@ -673,17 -685,14 -674,17 +686,14 @@@@ static int suspend_set_state(struct reg
        struct regulator_state *rstate)
   {
        int ret = 0;
- -     bool can_set_state;
- -
- -     can_set_state = rdev->desc->ops->set_suspend_enable &&
- -             rdev->desc->ops->set_suspend_disable;
   
        /* If we have no suspend mode configration don't set anything;
- -      * only warn if the driver actually makes the suspend mode
- -      * configurable.
+ +      * only warn if the driver implements set_suspend_voltage or
+ +      * set_suspend_mode callback.
         */
        if (!rstate->enabled && !rstate->disabled) {
- -             if (can_set_state)
+ +             if (rdev->desc->ops->set_suspend_voltage ||
+ +                 rdev->desc->ops->set_suspend_mode)
                        rdev_warn(rdev, "No configuration\n");
                return 0;
        }
                return -EINVAL;
        }
   
- -     if (!can_set_state) {
- -             rdev_err(rdev, "no way to set suspend state\n");
- -             return -EINVAL;
- -     }
- -
- -     if (rstate->enabled)
+ +     if (rstate->enabled && rdev->desc->ops->set_suspend_enable)
                ret = rdev->desc->ops->set_suspend_enable(rdev);
- -     else
+ +     else if (rstate->disabled && rdev->desc->ops->set_suspend_disable)
                ret = rdev->desc->ops->set_suspend_disable(rdev);
+ +     else /* OK if set_suspend_enable or set_suspend_disable is NULL */
+ +             ret = 0;
+ +
        if (ret < 0) {
                rdev_err(rdev, "failed to enabled/disable\n");
                return ret;
@@@@ -1146,6 -1153,15 -1147,6 +1154,15 @@@@ static struct regulator *create_regulat
                                   &regulator->max_uV);
        }
   
+ +     /*
+ +      * Check now if the regulator is an always on regulator - if
+ +      * it is then we don't need to do nearly so much work for
+ +      * enable/disable calls.
+ +      */
+ +     if (!_regulator_can_change_status(rdev) &&
+ +         _regulator_is_enabled(rdev))
+ +             regulator->always_on = true;
+ +
        mutex_unlock(&rdev->mutex);
        return regulator;
   link_name_err:
@@@@ -1169,26 -1185,52 -1170,26 +1186,52 @@@@ static int _regulator_get_enable_time(s
   }
   
   static struct regulator_dev *regulator_dev_lookup(struct device *dev,
- -                                                      const char *supply)
+ +                                               const char *supply,
+ +                                               int *ret)
   {
        struct regulator_dev *r;
        struct device_node *node;
+ +     struct regulator_map *map;
+ +     const char *devname = NULL;
   
        /* first do a dt based lookup */
        if (dev && dev->of_node) {
                node = of_get_regulator(dev, supply);
- -             if (node)
+ +             if (node) {
                        list_for_each_entry(r, &regulator_list, list)
                                if (r->dev.parent &&
                                        node == r->dev.of_node)
                                        return r;
+ +             } else {
+ +                     /*
+ +                      * If we couldn't even get the node then it's
+ +                      * not just that the device didn't register
+ +                      * yet, there's no node and we'll never
+ +                      * succeed.
+ +                      */
+ +                     *ret = -ENODEV;
+ +             }
        }
   
        /* if not found, try doing it non-dt way */
+ +     if (dev)
+ +             devname = dev_name(dev);
+ +
        list_for_each_entry(r, &regulator_list, list)
                if (strcmp(rdev_get_name(r), supply) == 0)
                        return r;
   
+ +     list_for_each_entry(map, &regulator_map_list, list) {
+ +             /* If the mapping has a device set up it must match */
+ +             if (map->dev_name &&
+ +                 (!devname || strcmp(map->dev_name, devname)))
+ +                     continue;
+ +
+ +             if (strcmp(map->supply, supply) == 0)
+ +                     return map->regulator;
+ +     }
+ +
+ +
        return NULL;
   }
   
@@@@ -1197,7 -1239,6 -1198,7 +1240,6 @@@@ static struct regulator *_regulator_get
                                        int exclusive)
   {
        struct regulator_dev *rdev;
- -     struct regulator_map *map;
        struct regulator *regulator = ERR_PTR(-EPROBE_DEFER);
        const char *devname = NULL;
        int ret;
   
        mutex_lock(&regulator_list_mutex);
   
- -     rdev = regulator_dev_lookup(dev, id);
+ +     rdev = regulator_dev_lookup(dev, id, &ret);
        if (rdev)
                goto found;
   
- -     list_for_each_entry(map, &regulator_map_list, list) {
- -             /* If the mapping has a device set up it must match */
- -             if (map->dev_name &&
- -                 (!devname || strcmp(map->dev_name, devname)))
- -                     continue;
- -
- -             if (strcmp(map->supply, id) == 0) {
- -                     rdev = map->regulator;
- -                     goto found;
- -             }
- -     }
- -
        if (board_wants_dummy_regulator) {
                rdev = dummy_regulator_rdev;
                goto found;
@@@@ -1435,17 -1464,6 -1436,17 +1465,6 @@@@ void devm_regulator_put(struct regulato
   }
   EXPORT_SYMBOL_GPL(devm_regulator_put);
   
- -static int _regulator_can_change_status(struct regulator_dev *rdev)
- -{
- -     if (!rdev->constraints)
- -             return 0;
- -
- -     if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
- -             return 1;
- -     else
- -             return 0;
- -}
- -
   /* locks held by regulator_enable() */
   static int _regulator_enable(struct regulator_dev *rdev)
   {
@@@@ -1525,6 -1543,9 -1526,6 +1544,9 @@@@ int regulator_enable(struct regulator *
        struct regulator_dev *rdev = regulator->rdev;
        int ret = 0;
   
+ +     if (regulator->always_on)
+ +             return 0;
+ +
        if (rdev->supply) {
                ret = regulator_enable(rdev->supply);
                if (ret != 0)
@@@@ -1603,6 -1624,9 -1604,6 +1625,9 @@@@ int regulator_disable(struct regulator 
        struct regulator_dev *rdev = regulator->rdev;
        int ret = 0;
   
+ +     if (regulator->always_on)
+ +             return 0;
+ +
        mutex_lock(&rdev->mutex);
        ret = _regulator_disable(rdev);
        mutex_unlock(&rdev->mutex);
@@@@ -1711,6 -1735,9 -1712,6 +1736,9 @@@@ int regulator_disable_deferred(struct r
        struct regulator_dev *rdev = regulator->rdev;
        int ret;
   
+ +     if (regulator->always_on)
+ +             return 0;
+ +
        mutex_lock(&rdev->mutex);
        rdev->deferred_disables++;
        mutex_unlock(&rdev->mutex);
   }
   EXPORT_SYMBOL_GPL(regulator_disable_deferred);
   
++ /**
++  * regulator_is_enabled_regmap - standard is_enabled() for regmap users
++  *
++  * @rdev: regulator to operate on
++  *
++  * Regulators that use regmap for their register I/O can set the
++  * enable_reg and enable_mask fields in their descriptor and then use
++  * this as their is_enabled operation, saving some code.
++  */
++ int regulator_is_enabled_regmap(struct regulator_dev *rdev)
++ {
++      unsigned int val;
++      int ret;
++ 
++      ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
++      if (ret != 0)
++              return ret;
++ 
++      return (val & rdev->desc->enable_mask) != 0;
++ }
++ EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
++ 
++ /**
++  * regulator_enable_regmap - standard enable() for regmap users
++  *
++  * @rdev: regulator to operate on
++  *
++  * Regulators that use regmap for their register I/O can set the
++  * enable_reg and enable_mask fields in their descriptor and then use
++  * this as their enable() operation, saving some code.
++  */
++ int regulator_enable_regmap(struct regulator_dev *rdev)
++ {
++      return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
++                                rdev->desc->enable_mask,
++                                rdev->desc->enable_mask);
++ }
++ EXPORT_SYMBOL_GPL(regulator_enable_regmap);
++ 
++ /**
++  * regulator_disable_regmap - standard disable() for regmap users
++  *
++  * @rdev: regulator to operate on
++  *
++  * Regulators that use regmap for their register I/O can set the
++  * enable_reg and enable_mask fields in their descriptor and then use
++  * this as their disable() operation, saving some code.
++  */
++ int regulator_disable_regmap(struct regulator_dev *rdev)
++ {
++      return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
++                                rdev->desc->enable_mask, 0);
++ }
++ EXPORT_SYMBOL_GPL(regulator_disable_regmap);
++ 
   static int _regulator_is_enabled(struct regulator_dev *rdev)
   {
        /* If we don't know then assume that the regulator is always on */
@@@@ -1749,6 -1776,9 -1805,6 +1832,9 @@@@ int regulator_is_enabled(struct regulat
   {
        int ret;
   
+ +     if (regulator->always_on)
+ +             return 1;
+ +
        mutex_lock(&regulator->rdev->mutex);
        ret = _regulator_is_enabled(regulator->rdev);
        mutex_unlock(&regulator->rdev->mutex);
@@@@ -1837,29 -1867,41 -1893,73 +1923,85 @@@@ int regulator_is_supported_voltage(stru
   }
   EXPORT_SYMBOL_GPL(regulator_is_supported_voltage);
   
++ /**
++  * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users
++  *
++  * @rdev: regulator to operate on
++  *
++  * Regulators that use regmap for their register I/O can set the
++  * vsel_reg and vsel_mask fields in their descriptor and then use this
++  * as their get_voltage_vsel operation, saving some code.
++  */
++ int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev)
++ {
++      unsigned int val;
++      int ret;
++ 
++      ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
++      if (ret != 0)
++              return ret;
++ 
++      val &= rdev->desc->vsel_mask;
++      val >>= ffs(rdev->desc->vsel_mask) - 1;
++ 
++      return val;
++ }
++ EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap);
++ 
++ /**
++  * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users
++  *
++  * @rdev: regulator to operate on
++  * @sel: Selector to set
++  *
++  * Regulators that use regmap for their register I/O can set the
++  * vsel_reg and vsel_mask fields in their descriptor and then use this
++  * as their set_voltage_vsel operation, saving some code.
++  */
++ int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel)
++ {
++      sel <<= ffs(rdev->desc->vsel_mask) - 1;
++ 
++      return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
++                                rdev->desc->vsel_mask, sel);
++ }
++ EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap);
++ 
   static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                                     int min_uV, int max_uV)
   {
        int ret;
        int delay = 0;
        unsigned int selector;
+ +     int old_selector = -1;
+ +     int best_val = INT_MAX;
   
        trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
   
        min_uV += rdev->constraints->uV_offset;
        max_uV += rdev->constraints->uV_offset;
   
+ +     /*
+ +      * If we can't obtain the old selector there is not enough
+ +      * info to call set_voltage_time_sel().
+ +      */
+ +     if (rdev->desc->ops->set_voltage_time_sel &&
+ +         rdev->desc->ops->get_voltage_sel) {
+ +             old_selector = rdev->desc->ops->get_voltage_sel(rdev);
+ +             if (old_selector < 0)
+ +                     return old_selector;
+ +     }
+ +
        if (rdev->desc->ops->set_voltage) {
                ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
                                                   &selector);
   
                if (rdev->desc->ops->list_voltage)
- -                     selector = rdev->desc->ops->list_voltage(rdev,
+ +                     best_val = rdev->desc->ops->list_voltage(rdev,
                                                                 selector);
                else
- -                     selector = -1;
+ +                     best_val = -1;
        } else if (rdev->desc->ops->set_voltage_sel) {
- -             int best_val = INT_MAX;
                int i;
   
                selector = 0;
                        }
                }
   
- -             /*
- -              * If we can't obtain the old selector there is not enough
- -              * info to call set_voltage_time_sel().
- -              */
- -             if (rdev->desc->ops->set_voltage_time_sel &&
- -                 rdev->desc->ops->get_voltage_sel) {
- -                     unsigned int old_selector = 0;
- -
- -                     ret = rdev->desc->ops->get_voltage_sel(rdev);
- -                     if (ret < 0)
- -                             return ret;
- -                     old_selector = ret;
- -                     ret = rdev->desc->ops->set_voltage_time_sel(rdev,
- -                                             old_selector, selector);
- -                     if (ret < 0)
- -                             rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", ret);
- -                     else
- -                             delay = ret;
- -             }
- -
- -             if (best_val != INT_MAX) {
+ +             if (best_val != INT_MAX)
                        ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
- -                     selector = best_val;
- -             } else {
+ +             else
                        ret = -EINVAL;
- -             }
        } else {
                ret = -EINVAL;
        }
   
+ +     /* Call set_voltage_time_sel if successfully obtained old_selector */
+ +     if (ret == 0 && old_selector >= 0 &&
+ +         rdev->desc->ops->set_voltage_time_sel) {
+ +
+ +             delay = rdev->desc->ops->set_voltage_time_sel(rdev,
+ +                                             old_selector, selector);
+ +             if (delay < 0) {
+ +                     rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n",
+ +                               delay);
+ +                     delay = 0;
+ +             }
+ +     }
+ +
        /* Insert any necessary delays */
        if (delay >= 1000) {
                mdelay(delay / 1000);
                _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
                                     NULL);
   
- -     trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector);
+ +     trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
   
        return ret;
   }
@@@@ -2324,6 -2357,9 -2424,6 +2457,9 @@@@ int regulator_set_optimum_mode(struct r
         */
        ret = -EINVAL;
   
+ +     if (!rdev->desc->ops->set_mode)
+ +             goto out;
+ +
        /* get output voltage */
        output_uV = _regulator_get_voltage(rdev);
        if (output_uV <= 0) {
@@@@ -2525,9 -2561,13 -2625,9 +2661,13 @@@@ int regulator_bulk_enable(int num_consu
        int i;
        int ret = 0;
   
- -     for (i = 0; i < num_consumers; i++)
- -             async_schedule_domain(regulator_bulk_enable_async,
- -                                   &consumers[i], &async_domain);
+ +     for (i = 0; i < num_consumers; i++) {
+ +             if (consumers[i].consumer->always_on)
+ +                     consumers[i].ret = 0;
+ +             else
+ +                     async_schedule_domain(regulator_bulk_enable_async,
+ +                                           &consumers[i], &async_domain);
+ +     }
   
        async_synchronize_full_domain(&async_domain);
   
@@@@ -2566,7 -2606,7 -2666,7 +2706,7 @@@@ int regulator_bulk_disable(int num_cons
                           struct regulator_bulk_data *consumers)
   {
        int i;
- -     int ret;
+ +     int ret, r;
   
        for (i = num_consumers - 1; i >= 0; --i) {
                ret = regulator_disable(consumers[i].consumer);
   
   err:
        pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
- -     for (++i; i < num_consumers; ++i)
- -             regulator_enable(consumers[i].consumer);
+ +     for (++i; i < num_consumers; ++i) {
+ +             r = regulator_enable(consumers[i].consumer);
+ +             if (r != 0)
+ +                     pr_err("Failed to reename %s: %d\n",
+ +                            consumers[i].supply, r);
+ +     }
   
        return ret;
   }
@@@@ -2756,10 -2800,6 -2856,10 +2900,6 @@@@ static int add_regulator_attributes(str
                        return status;
        }
   
- -     /* suspend mode constraints need multiple supporting methods */
- -     if (!(ops->set_suspend_enable && ops->set_suspend_disable))
- -             return status;
- -
        status = device_create_file(dev, &dev_attr_suspend_standby_state);
        if (status < 0)
                return status;
@@@@ -2820,28 -2860,28 -2920,29 +2960,29 @@@@ static void rdev_init_debugfs(struct re
   /**
    * regulator_register - register regulator
    * @regulator_desc: regulator to register
--  * @dev: struct device for the regulator
--  * @init_data: platform provided init data, passed through by driver
--  * @driver_data: private regulator data
--  * @of_node: OpenFirmware node to parse for device tree bindings (may be
--  *           NULL).
++  * @config: runtime configuration for regulator
    *
    * Called by regulator drivers to register a regulator.
    * Returns 0 on success.
    */
-- struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
--      struct device *dev, const struct regulator_init_data *init_data,
--      void *driver_data, struct device_node *of_node)
++ struct regulator_dev *
++ regulator_register(const struct regulator_desc *regulator_desc,
++                 const struct regulator_config *config)
   {
        const struct regulation_constraints *constraints = NULL;
++      const struct regulator_init_data *init_data;
        static atomic_t regulator_no = ATOMIC_INIT(0);
        struct regulator_dev *rdev;
++      struct device *dev;
        int ret, i;
        const char *supply = NULL;
   
--      if (regulator_desc == NULL)
++      if (regulator_desc == NULL || config == NULL)
                return ERR_PTR(-EINVAL);
   
++      dev = config->dev;
++      WARN_ON(!dev);
++ 
        if (regulator_desc->name == NULL || regulator_desc->ops == NULL)
                return ERR_PTR(-EINVAL);
   
                return ERR_PTR(-EINVAL);
        }
   
++      init_data = config->init_data;
++ 
        rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
        if (rdev == NULL)
                return ERR_PTR(-ENOMEM);
        mutex_lock(&regulator_list_mutex);
   
        mutex_init(&rdev->mutex);
--      rdev->reg_data = driver_data;
++      rdev->reg_data = config->driver_data;
        rdev->owner = regulator_desc->owner;
        rdev->desc = regulator_desc;
++      rdev->regmap = config->regmap;
        INIT_LIST_HEAD(&rdev->consumer_list);
        INIT_LIST_HEAD(&rdev->list);
        BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
   
        /* register with sysfs */
        rdev->dev.class = &regulator_class;
--      rdev->dev.of_node = of_node;
++      rdev->dev.of_node = config->of_node;
        rdev->dev.parent = dev;
        dev_set_name(&rdev->dev, "regulator.%d",
                     atomic_inc_return(&regulator_no) - 1);
        if (supply) {
                struct regulator_dev *r;
   
- -             r = regulator_dev_lookup(dev, supply);
+ +             r = regulator_dev_lookup(dev, supply, &ret);
   
                if (!r) {
                        dev_err(dev, "Failed to find supply %s\n", supply);
@@@@ -2992,14 -3032,14 -3096,14 +3136,14 @@@@ void regulator_unregister(struct regula
        if (rdev == NULL)
                return;
   
 +      if (rdev->supply)
 +              regulator_put(rdev->supply);
        mutex_lock(&regulator_list_mutex);
        debugfs_remove_recursive(rdev->debugfs);
        flush_work_sync(&rdev->disable_work.work);
        WARN_ON(rdev->open_count);
        unset_regulator_supplies(rdev);
        list_del(&rdev->list);
 -      if (rdev->supply)
 -              regulator_put(rdev->supply);
        kfree(rdev->constraints);
        device_unregister(&rdev->dev);
        mutex_unlock(&regulator_list_mutex);
index 0b64b19d81abf9e89e3d609f020e10e2ac9952b6,a2c61609d21dbf6ab5ffe386e2721e58ac388ffe,b2c1f442d4efcc1bb2894361651252b29195aac7..c42fe92a727dad134fadfbc7ee7bb661f8de5738
   
   #include <linux/mutex.h>
   #include <linux/types.h>
 ++#include <linux/regmap.h>
   
   #define RC5T583_MAX_REGS             0xF8
   
@@@@ -250,6 -249,6 -249,26 +250,26 @@@@ enum 
        RC5T583_EXT_PWRREQ2_CONTROL = 0x2,
   };
   
++ enum {
++      RC5T583_REGULATOR_DC0,
++      RC5T583_REGULATOR_DC1,
++      RC5T583_REGULATOR_DC2,
++      RC5T583_REGULATOR_DC3,
++      RC5T583_REGULATOR_LDO0,
++      RC5T583_REGULATOR_LDO1,
++      RC5T583_REGULATOR_LDO2,
++      RC5T583_REGULATOR_LDO3,
++      RC5T583_REGULATOR_LDO4,
++      RC5T583_REGULATOR_LDO5,
++      RC5T583_REGULATOR_LDO6,
++      RC5T583_REGULATOR_LDO7,
++      RC5T583_REGULATOR_LDO8,
++      RC5T583_REGULATOR_LDO9,
++ 
++      /* Should be last entry */
++      RC5T583_REGULATOR_MAX,
++ };
++ 
   struct rc5t583 {
        struct device   *dev;
        struct regmap   *regmap;
    * The board specific data is provided through this structure.
    * @irq_base: Irq base number on which this device registers their interrupts.
    * @enable_shutdown: Enable shutdown through the input pin "shutdown".
++  * @regulator_deepsleep_slot: The slot number on which device goes to sleep
++  *           in device sleep mode.
++  * @regulator_ext_pwr_control: External power request regulator control. The
++  *           regulator output enable/disable is controlled by the external
++  *           power request input state.
++  * @reg_init_data: Regulator init data.
    */
   
   struct rc5t583_platform_data {
        int             irq_base;
        bool            enable_shutdown;
++      int             regulator_deepsleep_slot[RC5T583_REGULATOR_MAX];
++      unsigned long   regulator_ext_pwr_control[RC5T583_REGULATOR_MAX];
++      struct regulator_init_data *reg_init_data[RC5T583_REGULATOR_MAX];
   };
   
 --int rc5t583_write(struct device *dev, u8 reg, uint8_t val);
 --int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val);
 --int rc5t583_set_bits(struct device *dev, unsigned int reg,
 --             unsigned int bit_mask);
 --int rc5t583_clear_bits(struct device *dev, unsigned int reg,
 --             unsigned int bit_mask);
 --int rc5t583_update(struct device *dev, unsigned int reg,
 --             unsigned int val, unsigned int mask);
 ++static inline int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val)
 ++{
 ++     struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
 ++     return regmap_write(rc5t583->regmap, reg, val);
 ++}
 ++
 ++static inline int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val)
 ++{
 ++     struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
 ++     unsigned int ival;
 ++     int ret;
 ++     ret = regmap_read(rc5t583->regmap, reg, &ival);
 ++     if (!ret)
 ++             *val = (uint8_t)ival;
 ++     return ret;
 ++}
 ++
 ++static inline int rc5t583_set_bits(struct device *dev, unsigned int reg,
 ++                     unsigned int bit_mask)
 ++{
 ++     struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
 ++     return regmap_update_bits(rc5t583->regmap, reg, bit_mask, bit_mask);
 ++}
 ++
 ++static inline int rc5t583_clear_bits(struct device *dev, unsigned int reg,
 ++                     unsigned int bit_mask)
 ++{
 ++     struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
 ++     return regmap_update_bits(rc5t583->regmap, reg, bit_mask, 0);
 ++}
 ++
 ++static inline int rc5t583_update(struct device *dev, unsigned int reg,
 ++             unsigned int val, unsigned int mask)
 ++{
 ++     struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
 ++     return regmap_update_bits(rc5t583->regmap, reg, mask, val);
 ++}
 ++
   int rc5t583_ext_power_req_config(struct device *dev, int deepsleep_id,
        int ext_pwr_req, int deepsleep_slot_nr);
   int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base);
index 8e92fb88ed090e594002407850e1275df4078577,d1926266fe00f4ae10003d9c632a07e4dcd68862,a554b0c8ad38c69760c0b61e28b3a06405feb06d..c395ec370445d61bfa7ce766331f8dd47a7b6139
@@@@ -143,11 -143,11 -143,11 +143,11 @@@@ static int mic_bias_event(struct snd_so
   }
   
   /*
 -- * using codec assist to small pop, hp_powerup or lineout_powerup
 -- * should stay setting until vag_powerup is fully ramped down,
 -- * vag fully ramped down require 400ms.
 ++ * As manual described, ADC/DAC only works when VAG powerup,
 ++ * So enabled VAG before ADC/DAC up.
 ++ * In power down case, we need wait 400ms when vag fully ramped down.
    */
 --static int small_pop_event(struct snd_soc_dapm_widget *w,
 ++static int power_vag_event(struct snd_soc_dapm_widget *w,
        struct snd_kcontrol *kcontrol, int event)
   {
        switch (event) {
                        SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP);
                break;
   
 --     case SND_SOC_DAPM_PRE_PMD:
 ++     case SND_SOC_DAPM_POST_PMD:
                snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
                        SGTL5000_VAG_POWERUP, 0);
                msleep(400);
@@@@ -201,8 -201,12 -201,12 +201,8 @@@@ static const struct snd_soc_dapm_widge
                                mic_bias_event,
                                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
   
 --     SND_SOC_DAPM_PGA_E("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0,
 --                     small_pop_event,
 --                     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
 --     SND_SOC_DAPM_PGA_E("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0,
 --                     small_pop_event,
 --                     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
 ++     SND_SOC_DAPM_PGA("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0),
 ++     SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0),
   
        SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux),
        SND_SOC_DAPM_MUX("Headphone Mux", SND_SOC_NOPM, 0, 0, &dac_mux),
                                0, SGTL5000_CHIP_DIG_POWER,
                                1, 0),
   
 --     SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0),
 ++     SND_SOC_DAPM_SUPPLY("VAG_POWER", SGTL5000_CHIP_ANA_POWER, 7, 0,
 ++                         power_vag_event,
 ++                         SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
   
 ++     SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0),
        SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0),
   };
   
@@@@ -230,11 -231,9 -231,9 +230,11 @@@@ static const struct snd_soc_dapm_route 
        {"Capture Mux", "LINE_IN", "LINE_IN"},  /* line_in --> adc_mux */
        {"Capture Mux", "MIC_IN", "MIC_IN"},    /* mic_in --> adc_mux */
   
 ++     {"ADC", NULL, "VAG_POWER"},
        {"ADC", NULL, "Capture Mux"},           /* adc_mux --> adc */
        {"AIFOUT", NULL, "ADC"},                /* adc --> i2s_out */
   
 ++     {"DAC", NULL, "VAG_POWER"},
        {"DAC", NULL, "AIFIN"},                 /* i2s-->dac,skip audio mux */
        {"Headphone Mux", "DAC", "DAC"},        /* dac --> hp_mux */
        {"LO", NULL, "DAC"},                    /* dac --> line_out */
@@@@ -809,6 -808,6 -808,7 +809,7 @@@@ static int ldo_regulator_register(struc
   {
        struct ldo_regulator *ldo;
        struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
++      struct regulator_config config = { };
   
        ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL);
   
        ldo->codec_data = codec;
        ldo->voltage = voltage;
   
--      ldo->dev = regulator_register(&ldo->desc, codec->dev,
--                                        init_data, ldo, NULL);
++      config.dev = codec->dev;
++      config.driver_data = ldo;
++      config.init_data = init_data;
++ 
++      ldo->dev = regulator_register(&ldo->desc, &config);
        if (IS_ERR(ldo->dev)) {
                int ret = PTR_ERR(ldo->dev);