X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=sound%2Fsoc%2Fsoc-core.c;h=e148db940cfc77ecb4521df7191909f00e672761;hb=cab0936aac8aa907c6bb814c2cf26385478f254b;hp=e6a67b58f296ec6269fc7c1ea833a5a1728bf7eb;hpb=41f81e88e01eb959f439f8537c58078e4bfc5291;p=linux-2.6-omap-h63xx.git diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e6a67b58f29..e148db940cf 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -288,16 +287,25 @@ static void close_delayed_work(struct work_struct *work) /* are we waiting on this codec DAI stream */ if (codec_dai->pop_wait == 1) { + /* power down the codec to D1 if no longer active */ + if (codec->active == 0) { + dbg("pop wq D1 %s %s\n", codec->name, + codec_dai->playback.stream_name); + snd_soc_dapm_device_event(socdev, + SNDRV_CTL_POWER_D1); + } + codec_dai->pop_wait = 0; - snd_soc_dapm_stream_event(codec, codec_dai->playback.stream_name, + snd_soc_dapm_stream_event(codec, + codec_dai->playback.stream_name, SND_SOC_DAPM_STREAM_STOP); /* power down the codec power domain if no longer active */ if (codec->active == 0) { dbg("pop wq D3 %s %s\n", codec->name, codec_dai->playback.stream_name); - if (codec->dapm_event) - codec->dapm_event(codec, SNDRV_CTL_POWER_D3hot); + snd_soc_dapm_device_event(socdev, + SNDRV_CTL_POWER_D3hot); } } } @@ -353,12 +361,12 @@ static int soc_codec_close(struct snd_pcm_substream *substream) } else { /* capture streams can be powered down now */ snd_soc_dapm_stream_event(codec, - codec_dai->capture.stream_name, SND_SOC_DAPM_STREAM_STOP); + codec_dai->capture.stream_name, + SND_SOC_DAPM_STREAM_STOP); - if (codec->active == 0 && codec_dai->pop_wait == 0){ - if (codec->dapm_event) - codec->dapm_event(codec, SNDRV_CTL_POWER_D3hot); - } + if (codec->active == 0 && codec_dai->pop_wait == 0) + snd_soc_dapm_device_event(socdev, + SNDRV_CTL_POWER_D3hot); } mutex_unlock(&pcm_mutex); @@ -433,8 +441,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) /* no delayed work - do we need to power up codec */ if (codec->dapm_state != SNDRV_CTL_POWER_D0) { - if (codec->dapm_event) - codec->dapm_event(codec, SNDRV_CTL_POWER_D1); + snd_soc_dapm_device_event(socdev, SNDRV_CTL_POWER_D1); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) snd_soc_dapm_stream_event(codec, @@ -445,8 +452,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) codec_dai->capture.stream_name, SND_SOC_DAPM_STREAM_START); - if (codec->dapm_event) - codec->dapm_event(codec, SNDRV_CTL_POWER_D0); + snd_soc_dapm_device_event(socdev, SNDRV_CTL_POWER_D0); if (codec_dai->dai_ops.digital_mute) codec_dai->dai_ops.digital_mute(codec_dai, 0); @@ -639,6 +645,10 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state) dai->dai_ops.digital_mute(dai, 1); } + /* suspend all pcms */ + for (i = 0; i < machine->num_links; i++) + snd_pcm_suspend_all(machine->dai_link[i].pcm); + if (machine->suspend_pre) machine->suspend_pre(pdev, state); @@ -829,6 +839,7 @@ static int soc_remove(struct platform_device *pdev) static struct platform_driver soc_driver = { .driver = { .name = "soc-audio", + .owner = THIS_MODULE, }, .probe = soc_probe, .remove = soc_remove, @@ -873,6 +884,7 @@ static int soc_new_pcm(struct snd_soc_device *socdev, return ret; } + dai_link->pcm = pcm; pcm->private_data = rtd; soc_pcm_ops.mmap = socdev->platform->pcm_ops->mmap; soc_pcm_ops.pointer = socdev->platform->pcm_ops->pointer; @@ -1090,7 +1102,6 @@ int snd_soc_register_card(struct snd_soc_device *socdev) struct snd_soc_machine *machine = socdev->machine; int ret = 0, i, ac97 = 0, err = 0; - mutex_lock(&codec->mutex); for(i = 0; i < machine->num_links; i++) { if (socdev->machine->dai_link[i].init) { err = socdev->machine->dai_link[i].init(codec); @@ -1116,12 +1127,14 @@ int snd_soc_register_card(struct snd_soc_device *socdev) goto out; } + mutex_lock(&codec->mutex); #ifdef CONFIG_SND_SOC_AC97_BUS if (ac97) { ret = soc_ac97_dev_register(codec); if (ret < 0) { printk(KERN_ERR "asoc: AC97 device register failed\n"); snd_card_free(codec->card); + mutex_unlock(&codec->mutex); goto out; } } @@ -1134,8 +1147,10 @@ int snd_soc_register_card(struct snd_soc_device *socdev) err = device_create_file(socdev->dev, &dev_attr_codec_reg); if (err < 0) printk(KERN_WARNING "asoc: failed to add codec sysfs entries\n"); -out: + mutex_unlock(&codec->mutex); + +out: return ret; } EXPORT_SYMBOL_GPL(snd_soc_register_card); @@ -1215,7 +1230,6 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, memcpy(&template, _template, sizeof(template)); if (long_name) template.name = long_name; - template.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; template.index = 0; return snd_ctl_new1(&template, data); @@ -1350,13 +1364,16 @@ EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext); int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - int mask = kcontrol->private_value; + int max = kcontrol->private_value; + + if (max == 1) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + else + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->type = - mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; + uinfo->value.integer.max = max; return 0; } EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); @@ -1373,15 +1390,18 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - int mask = (kcontrol->private_value >> 16) & 0xff; + int max = (kcontrol->private_value >> 16) & 0xff; int shift = (kcontrol->private_value >> 8) & 0x0f; int rshift = (kcontrol->private_value >> 12) & 0x0f; - uinfo->type = - mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; + if (max == 1) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + else + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = shift == rshift ? 1 : 2; uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; + uinfo->value.integer.max = max; return 0; } EXPORT_SYMBOL_GPL(snd_soc_info_volsw); @@ -1402,7 +1422,8 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0x0f; int rshift = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; + int max = (kcontrol->private_value >> 16) & 0xff; + int mask = (1 << fls(max)) - 1; int invert = (kcontrol->private_value >> 24) & 0x01; ucontrol->value.integer.value[0] = @@ -1412,10 +1433,10 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, (snd_soc_read(codec, reg) >> rshift) & mask; if (invert) { ucontrol->value.integer.value[0] = - mask - ucontrol->value.integer.value[0]; + max - ucontrol->value.integer.value[0]; if (shift != rshift) ucontrol->value.integer.value[1] = - mask - ucontrol->value.integer.value[1]; + max - ucontrol->value.integer.value[1]; } return 0; @@ -1438,25 +1459,24 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, int reg = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0x0f; int rshift = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; + int max = (kcontrol->private_value >> 16) & 0xff; + int mask = (1 << fls(max)) - 1; int invert = (kcontrol->private_value >> 24) & 0x01; - int err; unsigned short val, val2, val_mask; val = (ucontrol->value.integer.value[0] & mask); if (invert) - val = mask - val; + val = max - val; val_mask = mask << shift; val = val << shift; if (shift != rshift) { val2 = (ucontrol->value.integer.value[1] & mask); if (invert) - val2 = mask - val2; + val2 = max - val2; val_mask |= mask << rshift; val |= val2 << rshift; } - err = snd_soc_update_bits(codec, reg, val_mask, val); - return err; + return snd_soc_update_bits(codec, reg, val_mask, val); } EXPORT_SYMBOL_GPL(snd_soc_put_volsw); @@ -1473,13 +1493,16 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw); int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - int mask = (kcontrol->private_value >> 12) & 0xff; + int max = (kcontrol->private_value >> 12) & 0xff; + + if (max == 1) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + else + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->type = - mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; + uinfo->value.integer.max = max; return 0; } EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r); @@ -1500,7 +1523,8 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, int reg = kcontrol->private_value & 0xff; int reg2 = (kcontrol->private_value >> 24) & 0xff; int shift = (kcontrol->private_value >> 8) & 0x0f; - int mask = (kcontrol->private_value >> 12) & 0xff; + int max = (kcontrol->private_value >> 12) & 0xff; + int mask = (1<private_value >> 20) & 0x01; ucontrol->value.integer.value[0] = @@ -1509,9 +1533,9 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, (snd_soc_read(codec, reg2) >> shift) & mask; if (invert) { ucontrol->value.integer.value[0] = - mask - ucontrol->value.integer.value[0]; + max - ucontrol->value.integer.value[0]; ucontrol->value.integer.value[1] = - mask - ucontrol->value.integer.value[1]; + max - ucontrol->value.integer.value[1]; } return 0; @@ -1534,7 +1558,8 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, int reg = kcontrol->private_value & 0xff; int reg2 = (kcontrol->private_value >> 24) & 0xff; int shift = (kcontrol->private_value >> 8) & 0x0f; - int mask = (kcontrol->private_value >> 12) & 0xff; + int max = (kcontrol->private_value >> 12) & 0xff; + int mask = (1 << fls(max)) - 1; int invert = (kcontrol->private_value >> 20) & 0x01; int err; unsigned short val, val2, val_mask; @@ -1544,8 +1569,8 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, val2 = (ucontrol->value.integer.value[1] & mask); if (invert) { - val = mask - val; - val2 = mask - val2; + val = max - val; + val2 = max - val2; } val = val << shift; @@ -1577,3 +1602,4 @@ module_exit(snd_soc_exit); MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); MODULE_DESCRIPTION("ALSA SoC Core"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:soc-audio");