ASoC: s3c-i2s-v2 needs to declare a license for modular builds
[pandora-kernel.git] / sound / soc / soc-core.c
index 580a1a5..99712f6 100644 (file)
@@ -98,7 +98,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
        int err;
 
        codec->ac97->dev.bus = &ac97_bus_type;
-       codec->ac97->dev.parent = NULL;
+       codec->ac97->dev.parent = codec->card->dev;
        codec->ac97->dev.release = soc_ac97_device_release;
 
        dev_set_name(&codec->ac97->dev, "%d-%d:%s",
@@ -133,8 +133,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        mutex_lock(&pcm_mutex);
 
        /* startup the audio subsystem */
-       if (cpu_dai->ops.startup) {
-               ret = cpu_dai->ops.startup(substream, cpu_dai);
+       if (cpu_dai->ops->startup) {
+               ret = cpu_dai->ops->startup(substream, cpu_dai);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: can't open interface %s\n",
                                cpu_dai->name);
@@ -150,8 +150,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                }
        }
 
-       if (codec_dai->ops.startup) {
-               ret = codec_dai->ops.startup(substream, codec_dai);
+       if (codec_dai->ops->startup) {
+               ret = codec_dai->ops->startup(substream, codec_dai);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: can't open codec %s\n",
                                codec_dai->name);
@@ -247,8 +247,8 @@ codec_dai_err:
                platform->pcm_ops->close(substream);
 
 platform_err:
-       if (cpu_dai->ops.shutdown)
-               cpu_dai->ops.shutdown(substream, cpu_dai);
+       if (cpu_dai->ops->shutdown)
+               cpu_dai->ops->shutdown(substream, cpu_dai);
 out:
        mutex_unlock(&pcm_mutex);
        return ret;
@@ -340,11 +340,11 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                snd_soc_dai_digital_mute(codec_dai, 1);
 
-       if (cpu_dai->ops.shutdown)
-               cpu_dai->ops.shutdown(substream, cpu_dai);
+       if (cpu_dai->ops->shutdown)
+               cpu_dai->ops->shutdown(substream, cpu_dai);
 
-       if (codec_dai->ops.shutdown)
-               codec_dai->ops.shutdown(substream, codec_dai);
+       if (codec_dai->ops->shutdown)
+               codec_dai->ops->shutdown(substream, codec_dai);
 
        if (machine->ops && machine->ops->shutdown)
                machine->ops->shutdown(substream);
@@ -408,16 +408,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
                }
        }
 
-       if (codec_dai->ops.prepare) {
-               ret = codec_dai->ops.prepare(substream, codec_dai);
+       if (codec_dai->ops->prepare) {
+               ret = codec_dai->ops->prepare(substream, codec_dai);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: codec DAI prepare error\n");
                        goto out;
                }
        }
 
-       if (cpu_dai->ops.prepare) {
-               ret = cpu_dai->ops.prepare(substream, cpu_dai);
+       if (cpu_dai->ops->prepare) {
+               ret = cpu_dai->ops->prepare(substream, cpu_dai);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: cpu DAI prepare error\n");
                        goto out;
@@ -494,8 +494,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
-       if (codec_dai->ops.hw_params) {
-               ret = codec_dai->ops.hw_params(substream, params, codec_dai);
+       if (codec_dai->ops->hw_params) {
+               ret = codec_dai->ops->hw_params(substream, params, codec_dai);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: can't set codec %s hw params\n",
                                codec_dai->name);
@@ -503,8 +503,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
-       if (cpu_dai->ops.hw_params) {
-               ret = cpu_dai->ops.hw_params(substream, params, cpu_dai);
+       if (cpu_dai->ops->hw_params) {
+               ret = cpu_dai->ops->hw_params(substream, params, cpu_dai);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: interface %s hw params failed\n",
                                cpu_dai->name);
@@ -526,12 +526,12 @@ out:
        return ret;
 
 platform_err:
-       if (cpu_dai->ops.hw_free)
-               cpu_dai->ops.hw_free(substream, cpu_dai);
+       if (cpu_dai->ops->hw_free)
+               cpu_dai->ops->hw_free(substream, cpu_dai);
 
 interface_err:
-       if (codec_dai->ops.hw_free)
-               codec_dai->ops.hw_free(substream, codec_dai);
+       if (codec_dai->ops->hw_free)
+               codec_dai->ops->hw_free(substream, codec_dai);
 
 codec_err:
        if (machine->ops && machine->ops->hw_free)
@@ -570,11 +570,11 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
                platform->pcm_ops->hw_free(substream);
 
        /* now free hw params for the DAI's  */
-       if (codec_dai->ops.hw_free)
-               codec_dai->ops.hw_free(substream, codec_dai);
+       if (codec_dai->ops->hw_free)
+               codec_dai->ops->hw_free(substream, codec_dai);
 
-       if (cpu_dai->ops.hw_free)
-               cpu_dai->ops.hw_free(substream, cpu_dai);
+       if (cpu_dai->ops->hw_free)
+               cpu_dai->ops->hw_free(substream, cpu_dai);
 
        mutex_unlock(&pcm_mutex);
        return 0;
@@ -591,8 +591,8 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        struct snd_soc_dai *codec_dai = machine->codec_dai;
        int ret;
 
-       if (codec_dai->ops.trigger) {
-               ret = codec_dai->ops.trigger(substream, cmd, codec_dai);
+       if (codec_dai->ops->trigger) {
+               ret = codec_dai->ops->trigger(substream, cmd, codec_dai);
                if (ret < 0)
                        return ret;
        }
@@ -603,8 +603,8 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
                        return ret;
        }
 
-       if (cpu_dai->ops.trigger) {
-               ret = cpu_dai->ops.trigger(substream, cmd, cpu_dai);
+       if (cpu_dai->ops->trigger) {
+               ret = cpu_dai->ops->trigger(substream, cmd, cpu_dai);
                if (ret < 0)
                        return ret;
        }
@@ -645,8 +645,8 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
        /* mute any active DAC's */
        for (i = 0; i < card->num_links; i++) {
                struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
-               if (dai->ops.digital_mute && dai->playback.active)
-                       dai->ops.digital_mute(dai, 1);
+               if (dai->ops->digital_mute && dai->playback.active)
+                       dai->ops->digital_mute(dai, 1);
        }
 
        /* suspend all pcms */
@@ -741,8 +741,8 @@ static void soc_resume_deferred(struct work_struct *work)
        /* unmute any active DACs */
        for (i = 0; i < card->num_links; i++) {
                struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
-               if (dai->ops.digital_mute && dai->playback.active)
-                       dai->ops.digital_mute(dai, 0);
+               if (dai->ops->digital_mute && dai->playback.active)
+                       dai->ops->digital_mute(dai, 0);
        }
 
        for (i = 0; i < card->num_links; i++) {
@@ -767,11 +767,21 @@ static int soc_resume(struct platform_device *pdev)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_card *card = socdev->card;
+       struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai;
 
-       dev_dbg(socdev->dev, "scheduling resume work\n");
-
-       if (!schedule_work(&card->deferred_resume_work))
-               dev_err(socdev->dev, "resume work item may be lost\n");
+       /* 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
+        * due to I/O costs and anti-pop so handle them out of line.
+        */
+       if (cpu_dai->ac97_control) {
+               dev_dbg(socdev->dev, "Resuming AC97 immediately\n");
+               soc_resume_deferred(&card->deferred_resume_work);
+       } else {
+               dev_dbg(socdev->dev, "Scheduling resume work\n");
+               if (!schedule_work(&card->deferred_resume_work))
+                       dev_err(socdev->dev, "resume work item may be lost\n");
+       }
 
        return 0;
 }
@@ -1382,7 +1392,10 @@ int snd_soc_init_card(struct snd_soc_device *socdev)
 
        mutex_lock(&codec->mutex);
 #ifdef CONFIG_SND_SOC_AC97_BUS
-       if (ac97) {
+       /* Only instantiate AC97 if not already done by the adaptor
+        * for the generic AC97 subsystem.
+        */
+       if (ac97 && strcmp(codec->name, "AC97") != 0) {
                ret = soc_ac97_dev_register(codec);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: AC97 device register failed\n");
@@ -1429,7 +1442,8 @@ void snd_soc_free_pcms(struct snd_soc_device *socdev)
 #ifdef CONFIG_SND_SOC_AC97_BUS
        for (i = 0; i < codec->num_dai; i++) {
                codec_dai = &codec->dai[i];
-               if (codec_dai->ac97_control && codec->ac97) {
+               if (codec_dai->ac97_control && codec->ac97 &&
+                   strcmp(codec->name, "AC97") != 0) {
                        soc_ac97_dev_unregister(codec);
                        goto free_card;
                }
@@ -2048,8 +2062,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
 int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
        unsigned int freq, int dir)
 {
-       if (dai->ops.set_sysclk)
-               return dai->ops.set_sysclk(dai, clk_id, freq, dir);
+       if (dai->ops->set_sysclk)
+               return dai->ops->set_sysclk(dai, clk_id, freq, dir);
        else
                return -EINVAL;
 }
@@ -2068,8 +2082,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
 int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
        int div_id, int div)
 {
-       if (dai->ops.set_clkdiv)
-               return dai->ops.set_clkdiv(dai, div_id, div);
+       if (dai->ops->set_clkdiv)
+               return dai->ops->set_clkdiv(dai, div_id, div);
        else
                return -EINVAL;
 }
@@ -2087,8 +2101,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
 int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
        int pll_id, unsigned int freq_in, unsigned int freq_out)
 {
-       if (dai->ops.set_pll)
-               return dai->ops.set_pll(dai, pll_id, freq_in, freq_out);
+       if (dai->ops->set_pll)
+               return dai->ops->set_pll(dai, pll_id, freq_in, freq_out);
        else
                return -EINVAL;
 }
@@ -2103,8 +2117,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
  */
 int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
-       if (dai->ops.set_fmt)
-               return dai->ops.set_fmt(dai, fmt);
+       if (dai->ops->set_fmt)
+               return dai->ops->set_fmt(dai, fmt);
        else
                return -EINVAL;
 }
@@ -2122,8 +2136,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
 int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
        unsigned int mask, int slots)
 {
-       if (dai->ops.set_sysclk)
-               return dai->ops.set_tdm_slot(dai, mask, slots);
+       if (dai->ops->set_sysclk)
+               return dai->ops->set_tdm_slot(dai, mask, slots);
        else
                return -EINVAL;
 }
@@ -2138,8 +2152,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
  */
 int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
 {
-       if (dai->ops.set_sysclk)
-               return dai->ops.set_tristate(dai, tristate);
+       if (dai->ops->set_sysclk)
+               return dai->ops->set_tristate(dai, tristate);
        else
                return -EINVAL;
 }
@@ -2154,8 +2168,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
  */
 int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
 {
-       if (dai->ops.digital_mute)
-               return dai->ops.digital_mute(dai, mute);
+       if (dai->ops->digital_mute)
+               return dai->ops->digital_mute(dai, mute);
        else
                return -EINVAL;
 }
@@ -2208,6 +2222,9 @@ static int snd_soc_unregister_card(struct snd_soc_card *card)
        return 0;
 }
 
+static struct snd_soc_dai_ops null_dai_ops = {
+};
+
 /**
  * snd_soc_register_dai - Register a DAI with the ASoC core
  *
@@ -2222,6 +2239,9 @@ int snd_soc_register_dai(struct snd_soc_dai *dai)
        if (!dai->dev)
                printk(KERN_WARNING "No device for DAI %s\n", dai->name);
 
+       if (!dai->ops)
+               dai->ops = &null_dai_ops;
+
        INIT_LIST_HEAD(&dai->list);
 
        mutex_lock(&client_mutex);