Merge branch 'for-2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/asoc...
authorTakashi Iwai <tiwai@suse.de>
Tue, 23 Nov 2010 11:45:05 +0000 (12:45 +0100)
committerTakashi Iwai <tiwai@suse.de>
Tue, 23 Nov 2010 11:45:05 +0000 (12:45 +0100)
Conflicts:
sound/soc/codecs/tpa6130a2.c

sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/tpa6130a2.c
sound/soc/codecs/twl4030.c

index df726a5066e828eabfacafa225f232b4725ffc60..11a0a3d17055afafe60c4dc296de2d420eb9bf38 100644 (file)
@@ -61,6 +61,8 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {
        "DRVDD",        /* ADC Analog and Output Driver Voltage */
 };
 
+static LIST_HEAD(reset_list);
+
 struct aic3x_priv;
 
 struct aic3x_disable_nb {
@@ -77,6 +79,7 @@ struct aic3x_priv {
        struct aic3x_setup_data *setup;
        void *control_data;
        unsigned int sysclk;
+       struct list_head list;
        int master;
        int gpio_reset;
        int power;
@@ -1077,7 +1080,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
                 * Put codec to reset and require cache sync as at least one
                 * of the supplies was disabled
                 */
-               if (aic3x->gpio_reset >= 0)
+               if (gpio_is_valid(aic3x->gpio_reset))
                        gpio_set_value(aic3x->gpio_reset, 0);
                aic3x->codec->cache_sync = 1;
        }
@@ -1104,7 +1107,7 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
                if (!codec->cache_sync)
                        goto out;
 
-               if (aic3x->gpio_reset >= 0) {
+               if (gpio_is_valid(aic3x->gpio_reset)) {
                        udelay(1);
                        gpio_set_value(aic3x->gpio_reset, 1);
                }
@@ -1346,11 +1349,25 @@ static int aic3x_init(struct snd_soc_codec *codec)
        return 0;
 }
 
+static bool aic3x_is_shared_reset(struct aic3x_priv *aic3x)
+{
+       struct aic3x_priv *a;
+
+       list_for_each_entry(a, &reset_list, list) {
+               if (gpio_is_valid(aic3x->gpio_reset) &&
+                   aic3x->gpio_reset == a->gpio_reset)
+                       return true;
+       }
+
+       return false;
+}
+
 static int aic3x_probe(struct snd_soc_codec *codec)
 {
        struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
        int ret, i;
 
+       INIT_LIST_HEAD(&aic3x->list);
        codec->control_data = aic3x->control_data;
        aic3x->codec = codec;
        codec->dapm.idle_bias_off = 1;
@@ -1361,7 +1378,8 @@ static int aic3x_probe(struct snd_soc_codec *codec)
                return ret;
        }
 
-       if (aic3x->gpio_reset >= 0) {
+       if (gpio_is_valid(aic3x->gpio_reset) &&
+           !aic3x_is_shared_reset(aic3x)) {
                ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
                if (ret != 0)
                        goto err_gpio;
@@ -1407,6 +1425,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
                snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
 
        aic3x_add_widgets(codec);
+       list_add(&aic3x->list, &reset_list);
 
        return 0;
 
@@ -1416,7 +1435,8 @@ err_notif:
                                              &aic3x->disable_nb[i].nb);
        regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
 err_get:
-       if (aic3x->gpio_reset >= 0)
+       if (gpio_is_valid(aic3x->gpio_reset) &&
+           !aic3x_is_shared_reset(aic3x))
                gpio_free(aic3x->gpio_reset);
 err_gpio:
        return ret;
@@ -1428,7 +1448,9 @@ static int aic3x_remove(struct snd_soc_codec *codec)
        int i;
 
        aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       if (aic3x->gpio_reset >= 0) {
+       list_del(&aic3x->list);
+       if (gpio_is_valid(aic3x->gpio_reset) &&
+           !aic3x_is_shared_reset(aic3x)) {
                gpio_set_value(aic3x->gpio_reset, 0);
                gpio_free(aic3x->gpio_reset);
        }
index f9a92ea6b50aa8ca4a8a99246d0243424398a7ae..d69d2f5f957052a6f48e7032c9258215cc157d5a 100644 (file)
@@ -126,9 +126,6 @@ static int tpa6130a2_power(int power)
 
        mutex_lock(&data->mutex);
        if (power && !data->power_state) {
-               /* Power on */
-               if (data->power_gpio >= 0)
-                       gpio_set_value(data->power_gpio, 1);
 
                ret = regulator_enable(data->supply);
                if (ret != 0) {
@@ -136,6 +133,9 @@ static int tpa6130a2_power(int power)
                                "Failed to enable supply: %d\n", ret);
                        goto exit;
                }
+               /* Power on */
+               if (data->power_gpio >= 0)
+                       gpio_set_value(data->power_gpio, 1);
 
                data->power_state = 1;
                ret = tpa6130a2_initialize();
index f4602e8b67cc8c8c76837fe3d62a0563458833ae..50d3caf1191c6f316b6d360f7639f86777462dd0 100644 (file)
@@ -233,6 +233,16 @@ static int twl4030_write(struct snd_soc_codec *codec,
        return 0;
 }
 
+static inline void twl4030_wait_ms(int time)
+{
+       if (time < 60) {
+               time *= 1000;
+               usleep_range(time, time + 500);
+       } else {
+               msleep(time);
+       }
+}
+
 static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
 {
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
@@ -338,10 +348,14 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
        twl4030_write(codec, TWL4030_REG_ANAMICL,
                reg | TWL4030_CNCL_OFFSET_START);
 
-       /* wait for offset cancellation to complete */
+       /*
+        * Wait for offset cancellation to complete.
+        * Since this takes a while, do not slam the i2c.
+        * Start polling the status after ~20ms.
+        */
+       msleep(20);
        do {
-               /* this takes a little while, so don't slam i2c */
-               udelay(2000);
+               usleep_range(1000, 2000);
                twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
                                    TWL4030_REG_ANAMICL);
        } while ((i++ < 100) &&
@@ -725,9 +739,12 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
        /* Base values for ramp delay calculation: 2^19 - 2^26 */
        unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304,
                                    8388608, 16777216, 33554432, 67108864};
+       unsigned int delay;
 
        hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET);
        hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
+       delay = (ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
+               twl4030->sysclk) + 1;
 
        /* Enable external mute control, this dramatically reduces
         * the pop-noise */
@@ -751,16 +768,14 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
                hs_pop |= TWL4030_RAMP_EN;
                twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
                /* Wait ramp delay time + 1, so the VMID can settle */
-               mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
-                       twl4030->sysclk) + 1);
+               twl4030_wait_ms(delay);
        } else {
                /* Headset ramp-down _not_ according to
                 * the TRM, but in a way that it is working */
                hs_pop &= ~TWL4030_RAMP_EN;
                twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
                /* Wait ramp delay time + 1, so the VMID can settle */
-               mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
-                       twl4030->sysclk) + 1);
+               twl4030_wait_ms(delay);
                /* Bypass the reg_cache to mute the headset */
                twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
                                        hs_gain & (~0x0f),
@@ -835,7 +850,7 @@ static int digimic_event(struct snd_soc_dapm_widget *w,
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec);
 
        if (twl4030->digimic_delay)
-               mdelay(twl4030->digimic_delay);
+               twl4030_wait_ms(twl4030->digimic_delay);
        return 0;
 }
 
@@ -2258,9 +2273,12 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
 
 static int twl4030_soc_remove(struct snd_soc_codec *codec)
 {
+       struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
+
        /* Reset registers to their chip default before leaving */
        twl4030_reset_registers(codec);
        twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       kfree(twl4030);
        return 0;
 }
 
@@ -2292,10 +2310,7 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
 
 static int __devexit twl4030_codec_remove(struct platform_device *pdev)
 {
-       struct twl4030_priv *twl4030 = dev_get_drvdata(&pdev->dev);
-
        snd_soc_unregister_codec(&pdev->dev);
-       kfree(twl4030);
        return 0;
 }