]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 1 Aug 2008 18:44:24 +0000 (11:44 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 1 Aug 2008 18:44:24 +0000 (11:44 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ALSA: ASoC: Export dapm_reg_event() fully
  ALSA: ASoC: Update Poodle to current ASoC API
  ALSA: asoc: restrict sample rate and size in Freescale MPC8610 sound drivers
  ALSA: sound/soc/pxa/tosa.c: removed duplicated include

include/sound/soc-dapm.h
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_ssi.c
sound/soc/pxa/poodle.c
sound/soc/pxa/tosa.c
sound/soc/soc-dapm.c

index 3030fdc6981d05b804ccb5e31d5d7d3fafd7565e..c1b26fcc0b5c81e8950c77230675bf9314b2c2a8 100644 (file)
@@ -202,6 +202,9 @@ struct snd_soc_dapm_path;
 struct snd_soc_dapm_pin;
 struct snd_soc_dapm_route;
 
+int dapm_reg_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event);
+
 /* dapm controls */
 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
index da2bc590286438fe7b000cea43e24baf4b6bb417..7ceea2bba1f597a6a873da3c81ca71932cfea5a8 100644 (file)
@@ -132,12 +132,17 @@ struct fsl_dma_private {
  * Since each link descriptor has a 32-bit byte count field, we set
  * period_bytes_max to the largest 32-bit number.  We also have no maximum
  * number of periods.
+ *
+ * Note that we specify SNDRV_PCM_INFO_JOINT_DUPLEX here, but only because a
+ * limitation in the SSI driver requires the sample rates for playback and
+ * capture to be the same.
  */
 static const struct snd_pcm_hardware fsl_dma_hardware = {
 
        .info                   = SNDRV_PCM_INFO_INTERLEAVED |
                                  SNDRV_PCM_INFO_MMAP |
-                                 SNDRV_PCM_INFO_MMAP_VALID,
+                                 SNDRV_PCM_INFO_MMAP_VALID |
+                                 SNDRV_PCM_INFO_JOINT_DUPLEX,
        .formats                = FSLDMA_PCM_FORMATS,
        .rates                  = FSLDMA_PCM_RATES,
        .rate_min               = 5512,
index 71bff33f5528fe5e34849c06bbc1e88b91fbbcbb..157a7895ffa1befbb2427b121f0bb493c0190b3d 100644 (file)
@@ -67,6 +67,8 @@
  * @ssi: pointer to the SSI's registers
  * @ssi_phys: physical address of the SSI registers
  * @irq: IRQ of this SSI
+ * @first_stream: pointer to the stream that was opened first
+ * @second_stream: pointer to second stream
  * @dev: struct device pointer
  * @playback: the number of playback streams opened
  * @capture: the number of capture streams opened
@@ -79,6 +81,8 @@ struct fsl_ssi_private {
        struct ccsr_ssi __iomem *ssi;
        dma_addr_t ssi_phys;
        unsigned int irq;
+       struct snd_pcm_substream *first_stream;
+       struct snd_pcm_substream *second_stream;
        struct device *dev;
        unsigned int playback;
        unsigned int capture;
@@ -342,6 +346,49 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream)
                 */
        }
 
+       if (!ssi_private->first_stream)
+               ssi_private->first_stream = substream;
+       else {
+               /* This is the second stream open, so we need to impose sample
+                * rate and maybe sample size constraints.  Note that this can
+                * cause a race condition if the second stream is opened before
+                * the first stream is fully initialized.
+                *
+                * We provide some protection by checking to make sure the first
+                * stream is initialized, but it's not perfect.  ALSA sometimes
+                * re-initializes the driver with a different sample rate or
+                * size.  If the second stream is opened before the first stream
+                * has received its final parameters, then the second stream may
+                * be constrained to the wrong sample rate or size.
+                *
+                * FIXME: This code does not handle opening and closing streams
+                * repeatedly.  If you open two streams and then close the first
+                * one, you may not be able to open another stream until you
+                * close the second one as well.
+                */
+               struct snd_pcm_runtime *first_runtime =
+                       ssi_private->first_stream->runtime;
+
+               if (!first_runtime->rate || !first_runtime->sample_bits) {
+                       dev_err(substream->pcm->card->dev,
+                               "set sample rate and size in %s stream first\n",
+                               substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+                               ? "capture" : "playback");
+                       return -EAGAIN;
+               }
+
+               snd_pcm_hw_constraint_minmax(substream->runtime,
+                       SNDRV_PCM_HW_PARAM_RATE,
+                       first_runtime->rate, first_runtime->rate);
+
+               snd_pcm_hw_constraint_minmax(substream->runtime,
+                       SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+                       first_runtime->sample_bits,
+                       first_runtime->sample_bits);
+
+               ssi_private->second_stream = substream;
+       }
+
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                ssi_private->playback++;
 
@@ -371,18 +418,16 @@ static int fsl_ssi_prepare(struct snd_pcm_substream *substream)
        struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
 
        struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
-       u32 wl;
 
-       wl = CCSR_SSI_SxCCR_WL(snd_pcm_format_width(runtime->format));
+       if (substream == ssi_private->first_stream) {
+               u32 wl;
 
-       clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
+               /* The SSI should always be disabled at this points (SSIEN=0) */
+               wl = CCSR_SSI_SxCCR_WL(snd_pcm_format_width(runtime->format));
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               /* In synchronous mode, the SSI uses STCCR for capture */
                clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
-       else
-               clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
-
-       setbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
+       }
 
        return 0;
 }
@@ -407,9 +452,13 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       setbits32(&ssi->scr, CCSR_SSI_SCR_TE);
+                       clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
+                       setbits32(&ssi->scr,
+                               CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE);
                } else {
-                       setbits32(&ssi->scr, CCSR_SSI_SCR_RE);
+                       clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
+                       setbits32(&ssi->scr,
+                               CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE);
 
                        /*
                         * I think we need this delay to allow time for the SSI
@@ -452,6 +501,11 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream)
        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
                ssi_private->capture--;
 
+       if (ssi_private->first_stream == substream)
+               ssi_private->first_stream = ssi_private->second_stream;
+
+       ssi_private->second_stream = NULL;
+
        /*
         * If this is the last active substream, disable the SSI and release
         * the IRQ.
index 65a4e9a8c39e18ec4dc0b45f44dd780ff6c54b36..d968cf71b569f9056d8668d333e1bdb9594d36fb 100644 (file)
@@ -85,17 +85,13 @@ static int poodle_startup(struct snd_pcm_substream *substream)
 }
 
 /* we need to unmute the HP at shutdown as the mute burns power on poodle */
-static int poodle_shutdown(struct snd_pcm_substream *substream)
+static void poodle_shutdown(struct snd_pcm_substream *substream)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->socdev->codec;
-
        /* set = unmute headphone */
        locomo_gpio_write(&poodle_locomo_device.dev,
                POODLE_LOCOMO_GPIO_MUTE_L, 1);
        locomo_gpio_write(&poodle_locomo_device.dev,
                POODLE_LOCOMO_GPIO_MUTE_R, 1);
-       return 0;
 }
 
 static int poodle_hw_params(struct snd_pcm_substream *substream,
@@ -232,7 +228,7 @@ static const struct soc_enum poodle_enum[] = {
        SOC_ENUM_SINGLE_EXT(2, spk_function),
 };
 
-static const snd_kcontrol_new_t wm8731_poodle_controls[] = {
+static const struct snd_kcontrol_new wm8731_poodle_controls[] = {
        SOC_ENUM_EXT("Jack Function", poodle_enum[0], poodle_get_jack,
                poodle_set_jack),
        SOC_ENUM_EXT("Speaker Function", poodle_enum[1], poodle_get_spk,
index fe6cca9c9e760c0424e627e1f208130e47f372ce..22971a0f040ea3c019d085ce98916590c32bf755 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/audio.h>
-#include <asm/arch/tosa.h>
 
 #include "../codecs/wm9712.h"
 #include "pxa2xx-pcm.h"
index 820347c9ae4bbc5d5281e981e94f0cd27d2e28ae..f9d100bc8479e970225c6f1274c824f3ee12dfee 100644 (file)
@@ -470,6 +470,7 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(dapm_reg_event);
 
 /*
  * Scan each dapm widget for complete audio path.