]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - sound/soc/soc-core.c
Merge branch 'for-2.6.30' into for-2.6.31
[karo-tx-linux.git] / sound / soc / soc-core.c
index 6e710f705a749d5c3162c87cd47793ac68db006f..dd28009f8969c1f891696a4211cfb70d99cb61d3 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",
@@ -113,6 +113,35 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
 }
 #endif
 
+static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_card *card = socdev->card;
+       struct snd_soc_dai_link *machine = rtd->dai;
+       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
+       struct snd_soc_dai *codec_dai = machine->codec_dai;
+       int ret;
+
+       if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates ||
+           machine->symmetric_rates) {
+               dev_dbg(card->dev, "Symmetry forces %dHz rate\n", 
+                       machine->rate);
+
+               ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+                                                  SNDRV_PCM_HW_PARAM_RATE,
+                                                  machine->rate,
+                                                  machine->rate);
+               if (ret < 0) {
+                       dev_err(card->dev,
+                               "Unable to apply rate symmetry constraint: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 /*
  * Called by ALSA when a PCM substream is opened, the runtime->hw record is
  * then initialized and any private data can be allocated. This also calls
@@ -221,6 +250,13 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                goto machine_err;
        }
 
+       /* Symmetry only applies if we've already got an active stream. */
+       if (cpu_dai->active || codec_dai->active) {
+               ret = soc_pcm_apply_symmetry(substream);
+               if (ret != 0)
+                       goto machine_err;
+       }
+
        pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
        pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
        pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
@@ -521,6 +557,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
+       machine->rate = params_rate(params);
+
 out:
        mutex_unlock(&pcm_mutex);
        return ret;
@@ -767,11 +805,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;
 }