Merge remote-tracking branch 'asoc/fix/lm49453' into tmp
[cascardo/linux.git] / sound / soc / soc-core.c
index 9c768bc..2370063 100644 (file)
@@ -1255,6 +1255,8 @@ static int soc_post_component_init(struct snd_soc_card *card,
        INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients);
        ret = device_add(rtd->dev);
        if (ret < 0) {
+               /* calling put_device() here to free the rtd->dev */
+               put_device(rtd->dev);
                dev_err(card->dev,
                        "ASoC: failed to register runtime device: %d\n", ret);
                return ret;
@@ -1554,7 +1556,7 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num)
        /* unregister the rtd device */
        if (rtd->dev_registered) {
                device_remove_file(rtd->dev, &dev_attr_codec_reg);
-               device_del(rtd->dev);
+               device_unregister(rtd->dev);
                rtd->dev_registered = 0;
        }
 
@@ -2917,7 +2919,7 @@ int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
        platform_max = mc->platform_max;
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-       uinfo->count = 1;
+       uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
        uinfo->value.integer.min = 0;
        uinfo->value.integer.max = platform_max - min;
 
@@ -2941,12 +2943,14 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
                (struct soc_mixer_control *)kcontrol->private_value;
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        unsigned int reg = mc->reg;
+       unsigned int rreg = mc->rreg;
        unsigned int shift = mc->shift;
        int min = mc->min;
        int max = mc->max;
        unsigned int mask = (1 << fls(max)) - 1;
        unsigned int invert = mc->invert;
        unsigned int val, val_mask;
+       int ret;
 
        val = ((ucontrol->value.integer.value[0] + min) & mask);
        if (invert)
@@ -2954,7 +2958,21 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
        val_mask = mask << shift;
        val = val << shift;
 
-       return snd_soc_update_bits_locked(codec, reg, val_mask, val);
+       ret = snd_soc_update_bits_locked(codec, reg, val_mask, val);
+       if (ret != 0)
+               return ret;
+
+       if (snd_soc_volsw_is_stereo(mc)) {
+               val = ((ucontrol->value.integer.value[1] + min) & mask);
+               if (invert)
+                       val = max - val;
+               val_mask = mask << shift;
+               val = val << shift;
+
+               ret = snd_soc_update_bits_locked(codec, rreg, val_mask, val);
+       }
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
 
@@ -2974,6 +2992,7 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
                (struct soc_mixer_control *)kcontrol->private_value;
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        unsigned int reg = mc->reg;
+       unsigned int rreg = mc->rreg;
        unsigned int shift = mc->shift;
        int min = mc->min;
        int max = mc->max;
@@ -2988,6 +3007,16 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
        ucontrol->value.integer.value[0] =
                ucontrol->value.integer.value[0] - min;
 
+       if (snd_soc_volsw_is_stereo(mc)) {
+               ucontrol->value.integer.value[1] =
+                       (snd_soc_read(codec, rreg) >> shift) & mask;
+               if (invert)
+                       ucontrol->value.integer.value[1] =
+                               max - ucontrol->value.integer.value[1];
+               ucontrol->value.integer.value[1] =
+                       ucontrol->value.integer.value[1] - min;
+       }
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
@@ -4155,9 +4184,9 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
                ret = of_property_read_string_index(np, propname,
                        2 * i, &routes[i].sink);
                if (ret) {
-                       dev_err(card->dev, "ASoC: Property '%s' index %d"
-                               " could not be read: %d\n", propname, 2 * i,
-                               ret);
+                       dev_err(card->dev,
+                               "ASoC: Property '%s' index %d could not be read: %d\n",
+                               propname, 2 * i, ret);
                        kfree(routes);
                        return -EINVAL;
                }
@@ -4165,8 +4194,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
                        (2 * i) + 1, &routes[i].source);
                if (ret) {
                        dev_err(card->dev,
-                               "ASoC: Property '%s' index %d could not be"
-                               " read: %d\n", propname, (2 * i) + 1, ret);
+                               "ASoC: Property '%s' index %d could not be read: %d\n",
+                               propname, (2 * i) + 1, ret);
                        kfree(routes);
                        return -EINVAL;
                }