diff options
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 195 |
1 files changed, 65 insertions, 130 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index bd20154e8b3..a5d3685a5d3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1055,6 +1055,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; @@ -1070,9 +1073,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; @@ -1317,6 +1317,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); @@ -1429,6 +1430,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), @@ -1457,6 +1480,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); @@ -1477,6 +1502,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; @@ -2227,7 +2253,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. */ @@ -2237,8 +2264,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; @@ -2249,7 +2274,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; @@ -2261,7 +2286,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. */ @@ -2272,6 +2298,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; @@ -2280,13 +2307,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]; } @@ -2300,7 +2332,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. */ @@ -2311,143 +2344,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 @@ -2895,6 +2829,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); |