ASoC: wm8955: Fix wrong value references for boolean kctl
[pandora-kernel.git] / sound / soc / soc-core.c
index ef69f5a..a25fa63 100644 (file)
@@ -106,7 +106,7 @@ static int format_register_str(struct snd_soc_codec *codec,
        if (wordsize + regsize + 2 + 1 != len)
                return -EINVAL;
 
-       ret = snd_soc_read(codec , reg);
+       ret = snd_soc_read(codec, reg);
        if (ret < 0) {
                memset(regbuf, 'X', regsize);
                regbuf[regsize] = '\0';
@@ -144,7 +144,7 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf,
                step = codec->driver->reg_cache_step;
 
        for (i = 0; i < codec->driver->reg_cache_size; i += step) {
-               if (codec->readable_register && !codec->readable_register(codec, i))
+               if (!snd_soc_codec_readable_register(codec, i))
                        continue;
                if (codec->driver->display_register) {
                        count += codec->driver->display_register(codec, buf + count,
@@ -245,7 +245,6 @@ static ssize_t codec_reg_write_file(struct file *file,
        size_t buf_size;
        char *start = buf;
        unsigned long reg, value;
-       int step = 1;
        struct snd_soc_codec *codec = file->private_data;
 
        buf_size = min(count, (sizeof(buf)-1));
@@ -253,9 +252,6 @@ static ssize_t codec_reg_write_file(struct file *file,
                return -EFAULT;
        buf[buf_size] = 0;
 
-       if (codec->driver->reg_cache_step)
-               step = codec->driver->reg_cache_step;
-
        while (*start == ' ')
                start++;
        reg = simple_strtoul(start, &start, 16);
@@ -713,6 +709,12 @@ int snd_soc_resume(struct device *dev)
        struct snd_soc_card *card = dev_get_drvdata(dev);
        int i, ac97_control = 0;
 
+       /* If the initialization of this soc device failed, there is no codec
+        * associated with it. Just bail out in this case.
+        */
+       if (list_empty(&card->codec_dev_list))
+               return 0;
+
        /* AC97 devices might have other drivers hanging off them so
         * need to resume immediately.  Other drivers don't have that
         * problem and may take a substantial amount of time to resume
@@ -957,6 +959,8 @@ static int soc_probe_codec(struct snd_soc_card *card,
                snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets,
                                          driver->num_dapm_widgets);
 
+       codec->dapm.idle_bias_off = driver->idle_bias_off;
+
        if (driver->probe) {
                ret = driver->probe(codec);
                if (ret < 0) {
@@ -1057,6 +1061,9 @@ static int soc_post_component_init(struct snd_soc_card *card,
        }
        rtd->card = card;
 
+       /* Make sure all DAPM widgets are instantiated */
+       snd_soc_dapm_new_widgets(&codec->dapm);
+
        /* machine controls, routes and widgets are not prefixed */
        temp = codec->name_prefix;
        codec->name_prefix = NULL;
@@ -1072,9 +1079,6 @@ static int soc_post_component_init(struct snd_soc_card *card,
        }
        codec->name_prefix = temp;
 
-       /* Make sure all DAPM widgets are instantiated */
-       snd_soc_dapm_new_widgets(&codec->dapm);
-
        /* register the rtd device */
        rtd->codec = codec;
        rtd->dev.parent = card->dev;
@@ -1319,6 +1323,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
        struct snd_soc_codec *codec;
        struct snd_soc_codec_conf *codec_conf;
        enum snd_soc_compress_type compress_type;
+       struct snd_soc_dai_link *dai_link;
        int ret, i, order;
 
        mutex_lock(&card->mutex);
@@ -1431,6 +1436,28 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
                snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
                                        card->num_dapm_routes);
 
+       snd_soc_dapm_new_widgets(&card->dapm);
+
+       for (i = 0; i < card->num_links; i++) {
+               dai_link = &card->dai_link[i];
+
+               if (dai_link->dai_fmt) {
+                       ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai,
+                                                 dai_link->dai_fmt);
+                       if (ret != 0)
+                               dev_warn(card->rtd[i].codec_dai->dev,
+                                        "Failed to set DAI format: %d\n",
+                                        ret);
+
+                       ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
+                                                 dai_link->dai_fmt);
+                       if (ret != 0)
+                               dev_warn(card->rtd[i].cpu_dai->dev,
+                                        "Failed to set DAI format: %d\n",
+                                        ret);
+               }
+       }
+
        snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
                 "%s", card->name);
        snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
@@ -1459,6 +1486,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
                }
        }
 
+       snd_soc_dapm_new_widgets(&card->dapm);
+
        ret = snd_card_register(card->snd_card);
        if (ret < 0) {
                printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
@@ -1479,6 +1508,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 #endif
 
        card->instantiated = 1;
+       snd_soc_dapm_sync(&card->dapm);
        mutex_unlock(&card->mutex);
        return;
 
@@ -2229,7 +2259,8 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
  * @kcontrol: mixer control
  * @uinfo: control element information
  *
- * Callback to provide information about a single mixer control.
+ * Callback to provide information about a single mixer control, or a double
+ * mixer control that spans 2 registers.
  *
  * Returns 0 for success.
  */
@@ -2239,8 +2270,6 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
        int platform_max;
-       unsigned int shift = mc->shift;
-       unsigned int rshift = mc->rshift;
 
        if (!mc->platform_max)
                mc->platform_max = mc->max;
@@ -2251,7 +2280,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
        else
                uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 
-       uinfo->count = shift == rshift ? 1 : 2;
+       uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
        uinfo->value.integer.min = 0;
        uinfo->value.integer.max = platform_max;
        return 0;
@@ -2263,7 +2292,8 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
  * @kcontrol: mixer control
  * @ucontrol: control element information
  *
- * Callback to get the value of a single mixer control.
+ * Callback to get the value of a single mixer control, or a double mixer
+ * control that spans 2 registers.
  *
  * Returns 0 for success.
  */
@@ -2274,6 +2304,7 @@ int snd_soc_get_volsw(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 reg2 = mc->rreg;
        unsigned int shift = mc->shift;
        unsigned int rshift = mc->rshift;
        int max = mc->max;
@@ -2282,13 +2313,18 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
 
        ucontrol->value.integer.value[0] =
                (snd_soc_read(codec, reg) >> shift) & mask;
-       if (shift != rshift)
-               ucontrol->value.integer.value[1] =
-                       (snd_soc_read(codec, reg) >> rshift) & mask;
-       if (invert) {
+       if (invert)
                ucontrol->value.integer.value[0] =
                        max - ucontrol->value.integer.value[0];
-               if (shift != rshift)
+
+       if (snd_soc_volsw_is_stereo(mc)) {
+               if (reg == reg2)
+                       ucontrol->value.integer.value[1] =
+                               (snd_soc_read(codec, reg) >> rshift) & mask;
+               else
+                       ucontrol->value.integer.value[1] =
+                               (snd_soc_read(codec, reg2) >> shift) & mask;
+               if (invert)
                        ucontrol->value.integer.value[1] =
                                max - ucontrol->value.integer.value[1];
        }
@@ -2302,7 +2338,8 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
  * @kcontrol: mixer control
  * @ucontrol: control element information
  *
- * Callback to set the value of a single mixer control.
+ * Callback to set the value of a single mixer control, or a double mixer
+ * control that spans 2 registers.
  *
  * Returns 0 for success.
  */
@@ -2313,143 +2350,44 @@ int snd_soc_put_volsw(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 reg2 = mc->rreg;
        unsigned int shift = mc->shift;
        unsigned int rshift = mc->rshift;
        int max = mc->max;
        unsigned int mask = (1 << fls(max)) - 1;
        unsigned int invert = mc->invert;
-       unsigned int val, val2, val_mask;
+       int err;
+       bool type_2r = 0;
+       unsigned int val2 = 0;
+       unsigned int val, val_mask;
 
        val = (ucontrol->value.integer.value[0] & mask);
        if (invert)
                val = max - val;
        val_mask = mask << shift;
        val = val << shift;
-       if (shift != rshift) {
+       if (snd_soc_volsw_is_stereo(mc)) {
                val2 = (ucontrol->value.integer.value[1] & mask);
                if (invert)
                        val2 = max - val2;
-               val_mask |= mask << rshift;
-               val |= val2 << rshift;
-       }
-       return snd_soc_update_bits_locked(codec, reg, val_mask, val);
-}
-EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
-
-/**
- * snd_soc_info_volsw_2r - double mixer info callback
- * @kcontrol: mixer control
- * @uinfo: control element information
- *
- * Callback to provide information about a double mixer control that
- * spans 2 codec registers.
- *
- * Returns 0 for success.
- */
-int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_info *uinfo)
-{
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       int platform_max;
-
-       if (!mc->platform_max)
-               mc->platform_max = mc->max;
-       platform_max = mc->platform_max;
-
-       if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       else
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-
-       uinfo->count = 2;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = platform_max;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
-
-/**
- * snd_soc_get_volsw_2r - double mixer get callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to get the value of a double mixer control that spans 2 registers.
- *
- * Returns 0 for success.
- */
-int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       unsigned int reg = mc->reg;
-       unsigned int reg2 = mc->rreg;
-       unsigned int shift = mc->shift;
-       int max = mc->max;
-       unsigned int mask = (1 << fls(max)) - 1;
-       unsigned int invert = mc->invert;
-
-       ucontrol->value.integer.value[0] =
-               (snd_soc_read(codec, reg) >> shift) & mask;
-       ucontrol->value.integer.value[1] =
-               (snd_soc_read(codec, reg2) >> shift) & mask;
-       if (invert) {
-               ucontrol->value.integer.value[0] =
-                       max - ucontrol->value.integer.value[0];
-               ucontrol->value.integer.value[1] =
-                       max - ucontrol->value.integer.value[1];
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r);
-
-/**
- * snd_soc_put_volsw_2r - double mixer set callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to set the value of a double mixer control that spans 2 registers.
- *
- * Returns 0 for success.
- */
-int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       unsigned int reg = mc->reg;
-       unsigned int reg2 = mc->rreg;
-       unsigned int shift = mc->shift;
-       int max = mc->max;
-       unsigned int mask = (1 << fls(max)) - 1;
-       unsigned int invert = mc->invert;
-       int err;
-       unsigned int val, val2, val_mask;
-
-       val_mask = mask << shift;
-       val = (ucontrol->value.integer.value[0] & mask);
-       val2 = (ucontrol->value.integer.value[1] & mask);
-
-       if (invert) {
-               val = max - val;
-               val2 = max - val2;
+               if (reg == reg2) {
+                       val_mask |= mask << rshift;
+                       val |= val2 << rshift;
+               } else {
+                       val2 = val2 << shift;
+                       type_2r = 1;
+               }
        }
-
-       val = val << shift;
-       val2 = val2 << shift;
-
        err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
        if (err < 0)
                return err;
 
-       err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
+       if (type_2r)
+               err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
+
        return err;
 }
-EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
+EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
 
 /**
  * snd_soc_info_volsw_s8 - signed mixer info callback
@@ -2680,7 +2618,7 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
        if (dai->driver && dai->driver->ops->set_sysclk)
                return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
        else if (dai->codec && dai->codec->driver->set_sysclk)
-               return dai->codec->driver->set_sysclk(dai->codec, clk_id,
+               return dai->codec->driver->set_sysclk(dai->codec, clk_id, 0,
                                                      freq, dir);
        else
                return -EINVAL;
@@ -2691,16 +2629,18 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
  * snd_soc_codec_set_sysclk - configure CODEC system or master clock.
  * @codec: CODEC
  * @clk_id: DAI specific clock ID
+ * @source: Source for the clock
  * @freq: new clock frequency in Hz
  * @dir: new clock direction - input/output.
  *
  * Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
  */
 int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
-       unsigned int freq, int dir)
+                            int source, unsigned int freq, int dir)
 {
        if (codec->driver->set_sysclk)
-               return codec->driver->set_sysclk(codec, clk_id, freq, dir);
+               return codec->driver->set_sysclk(codec, clk_id, source,
+                                                freq, dir);
        else
                return -EINVAL;
 }
@@ -2895,6 +2835,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
                card->rtd[i].dai_link = &card->dai_link[i];
 
        INIT_LIST_HEAD(&card->list);
+       INIT_LIST_HEAD(&card->dapm_dirty);
        card->instantiated = 0;
        mutex_init(&card->mutex);
 
@@ -3153,6 +3094,7 @@ int snd_soc_register_platform(struct device *dev,
        platform->driver = platform_drv;
        platform->dapm.dev = dev;
        platform->dapm.platform = platform;
+       platform->dapm.stream_event = platform_drv->stream_event;
 
        mutex_lock(&client_mutex);
        list_add(&platform->list, &platform_list);
@@ -3265,6 +3207,7 @@ int snd_soc_register_codec(struct device *dev,
        codec->dapm.dev = dev;
        codec->dapm.codec = codec;
        codec->dapm.seq_notifier = codec_drv->seq_notifier;
+       codec->dapm.stream_event = codec_drv->stream_event;
        codec->dev = dev;
        codec->driver = codec_drv;
        codec->num_dai = num_dai;