Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[pandora-kernel.git] / sound / soc / codecs / tpa6130a2.c
index 31f67b5..99b70e5 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/slab.h>
 #include <sound/tpa6130a2-plat.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 
 static struct i2c_client *tpa6130a2_client;
 
-#define TPA6130A2_NUM_SUPPLIES 2
-static const char *tpa6130a2_supply_names[TPA6130A2_NUM_SUPPLIES] = {
-       "CPVSS",
-       "Vdd",
-};
-
-static const char *tpa6140a2_supply_names[TPA6130A2_NUM_SUPPLIES] = {
-       "HPVdd",
-       "AVdd",
-};
-
-#define TPA6130A2_GAIN_MAX     0x3f
-#define TPA6140A2_GAIN_MAX     0x1f
-
 /* This struct is used to save the context */
 struct tpa6130a2_data {
        struct mutex mutex;
        unsigned char regs[TPA6130A2_CACHEREGNUM];
-       struct regulator_bulk_data supplies[TPA6130A2_NUM_SUPPLIES];
+       struct regulator *supply;
        int power_gpio;
        unsigned char power_state;
        enum tpa_model id;
-       int gain_limit;
 };
 
 static int tpa6130a2_i2c_read(int reg)
@@ -139,11 +125,10 @@ static int tpa6130a2_power(int power)
                if (data->power_gpio >= 0)
                        gpio_set_value(data->power_gpio, 1);
 
-               ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies),
-                                           data->supplies);
+               ret = regulator_enable(data->supply);
                if (ret != 0) {
                        dev_err(&tpa6130a2_client->dev,
-                               "Failed to enable supplies: %d\n", ret);
+                               "Failed to enable supply: %d\n", ret);
                        goto exit;
                }
 
@@ -164,11 +149,10 @@ static int tpa6130a2_power(int power)
                if (data->power_gpio >= 0)
                        gpio_set_value(data->power_gpio, 0);
 
-               ret = regulator_bulk_disable(ARRAY_SIZE(data->supplies),
-                                            data->supplies);
+               ret = regulator_disable(data->supply);
                if (ret != 0) {
                        dev_err(&tpa6130a2_client->dev,
-                               "Failed to disable supplies: %d\n", ret);
+                               "Failed to disable supply: %d\n", ret);
                        goto exit;
                }
 
@@ -180,41 +164,7 @@ exit:
        return ret;
 }
 
-static int tpa6130a2_info_volsw(struct snd_kcontrol *kcontrol,
-               struct snd_ctl_elem_info *uinfo)
-{
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       struct tpa6130a2_data *data;
-
-       BUG_ON(tpa6130a2_client == NULL);
-       data = i2c_get_clientdata(tpa6130a2_client);
-
-       mutex_lock(&data->mutex);
-       switch (mc->reg) {
-       case TPA6130A2_REG_VOL_MUTE:
-               if (data->gain_limit != mc->max)
-                       mc->max = data->gain_limit;
-               break;
-       default:
-               dev_err(&tpa6130a2_client->dev,
-                       "Invalid register: 0x02%x\n", mc->reg);
-               goto out;
-       }
-       if (unlikely(mc->max == 1))
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       else
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-
-       uinfo->count = 1;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = mc->max;
-out:
-       mutex_unlock(&data->mutex);
-       return 0;
-}
-
-static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol,
+static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_value *ucontrol)
 {
        struct soc_mixer_control *mc =
@@ -222,7 +172,8 @@ static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol,
        struct tpa6130a2_data *data;
        unsigned int reg = mc->reg;
        unsigned int shift = mc->shift;
-       unsigned int mask = mc->max;
+       int max = mc->max;
+       unsigned int mask = (1 << fls(max)) - 1;
        unsigned int invert = mc->invert;
 
        BUG_ON(tpa6130a2_client == NULL);
@@ -235,13 +186,13 @@ static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol,
 
        if (invert)
                ucontrol->value.integer.value[0] =
-                       mask - ucontrol->value.integer.value[0];
+                       max - ucontrol->value.integer.value[0];
 
        mutex_unlock(&data->mutex);
        return 0;
 }
 
-static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol,
+static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_value *ucontrol)
 {
        struct soc_mixer_control *mc =
@@ -249,7 +200,8 @@ static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol,
        struct tpa6130a2_data *data;
        unsigned int reg = mc->reg;
        unsigned int shift = mc->shift;
-       unsigned int mask = mc->max;
+       int max = mc->max;
+       unsigned int mask = (1 << fls(max)) - 1;
        unsigned int invert = mc->invert;
        unsigned int val = (ucontrol->value.integer.value[0] & mask);
        unsigned int val_reg;
@@ -258,7 +210,7 @@ static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol,
        data = i2c_get_clientdata(tpa6130a2_client);
 
        if (invert)
-               val = mask - val;
+               val = max - val;
 
        mutex_lock(&data->mutex);
 
@@ -277,15 +229,6 @@ static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol,
        return 1;
 }
 
-#define SOC_SINGLE_EXT_TLV_TPA(xname, xreg, xshift, xmax, xinvert, tlv_array) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
-                SNDRV_CTL_ELEM_ACCESS_READWRITE,\
-       .tlv.p = (tlv_array), \
-       .info = tpa6130a2_info_volsw, \
-       .get = tpa6130a2_get_reg, .put = tpa6130a2_set_reg, \
-       .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
-
 /*
  * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going
  * down in gain.
@@ -305,9 +248,10 @@ static const unsigned int tpa6130_tlv[] = {
 };
 
 static const struct snd_kcontrol_new tpa6130a2_controls[] = {
-       SOC_SINGLE_EXT_TLV_TPA("TPA6130A2 Headphone Playback Volume",
-                       TPA6130A2_REG_VOL_MUTE, 0, TPA6130A2_GAIN_MAX, 0,
-                       tpa6130_tlv),
+       SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume",
+                      TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0,
+                      tpa6130a2_get_volsw, tpa6130a2_put_volsw,
+                      tpa6130_tlv),
 };
 
 static const unsigned int tpa6140_tlv[] = {
@@ -318,9 +262,10 @@ static const unsigned int tpa6140_tlv[] = {
 };
 
 static const struct snd_kcontrol_new tpa6140a2_controls[] = {
-       SOC_SINGLE_EXT_TLV_TPA("TPA6140A2 Headphone Playback Volume",
-                       TPA6130A2_REG_VOL_MUTE, 1, TPA6140A2_GAIN_MAX, 0,
-                       tpa6140_tlv),
+       SOC_SINGLE_EXT_TLV("TPA6140A2 Headphone Playback Volume",
+                      TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0,
+                      tpa6130a2_get_volsw, tpa6130a2_put_volsw,
+                      tpa6140_tlv),
 };
 
 /*
@@ -414,8 +359,8 @@ static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
                        0, 0, tpa6130a2_supply_event,
                        SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
        /* Outputs */
-       SND_SOC_DAPM_HP("TPA6130A2 Headphone Left", NULL),
-       SND_SOC_DAPM_HP("TPA6130A2 Headphone Right", NULL),
+       SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Left"),
+       SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Right"),
 };
 
 static const struct snd_soc_dapm_route audio_map[] = {
@@ -454,7 +399,8 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
        struct device *dev;
        struct tpa6130a2_data *data;
        struct tpa6130a2_platform_data *pdata;
-       int i, ret;
+       const char *regulator;
+       int ret;
 
        dev = &client->dev;
 
@@ -496,40 +442,21 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
        }
 
        switch (data->id) {
+       default:
+               dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
+                        pdata->id);
        case TPA6130A2:
-               for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
-                       data->supplies[i].supply = tpa6130a2_supply_names[i];
-               if (pdata->limit_gain > 0 &&
-                   pdata->limit_gain < TPA6130A2_GAIN_MAX)
-                       data->gain_limit = pdata->limit_gain;
-               else
-                       data->gain_limit = TPA6130A2_GAIN_MAX;
+               regulator = "Vdd";
                break;
        case TPA6140A2:
-               for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
-                       data->supplies[i].supply = tpa6140a2_supply_names[i];;
-               if (pdata->limit_gain > 0 &&
-                   pdata->limit_gain < TPA6140A2_GAIN_MAX)
-                       data->gain_limit = pdata->limit_gain;
-               else
-                       data->gain_limit = TPA6140A2_GAIN_MAX;
+               regulator = "AVdd";
                break;
-       default:
-               dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
-                        pdata->id);
-               for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
-                       data->supplies[i].supply = tpa6130a2_supply_names[i];
-               if (pdata->limit_gain > 0 &&
-                   pdata->limit_gain < TPA6130A2_GAIN_MAX)
-                       data->gain_limit = pdata->limit_gain;
-               else
-                       data->gain_limit = TPA6130A2_GAIN_MAX;
        }
 
-       ret = regulator_bulk_get(dev, ARRAY_SIZE(data->supplies),
-                                data->supplies);
-       if (ret != 0) {
-               dev_err(dev, "Failed to request supplies: %d\n", ret);
+       data->supply = regulator_get(dev, regulator);
+       if (IS_ERR(data->supply)) {
+               ret = PTR_ERR(data->supply);
+               dev_err(dev, "Failed to request supply: %d\n", ret);
                goto err_regulator;
        }
 
@@ -552,7 +479,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
        return 0;
 
 err_power:
-       regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies);
+       regulator_put(data->supply);
 err_regulator:
        if (data->power_gpio >= 0)
                gpio_free(data->power_gpio);
@@ -573,7 +500,7 @@ static int __devexit tpa6130a2_remove(struct i2c_client *client)
        if (data->power_gpio >= 0)
                gpio_free(data->power_gpio);
 
-       regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies);
+       regulator_put(data->supply);
 
        kfree(data);
        tpa6130a2_client = NULL;