Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* '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
This commit is contained in:
commit
df1efe6f87
@ -202,6 +202,9 @@ struct snd_soc_dapm_path;
|
|||||||
struct snd_soc_dapm_pin;
|
struct snd_soc_dapm_pin;
|
||||||
struct snd_soc_dapm_route;
|
struct snd_soc_dapm_route;
|
||||||
|
|
||||||
|
int dapm_reg_event(struct snd_soc_dapm_widget *w,
|
||||||
|
struct snd_kcontrol *kcontrol, int event);
|
||||||
|
|
||||||
/* dapm controls */
|
/* dapm controls */
|
||||||
int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_value *ucontrol);
|
struct snd_ctl_elem_value *ucontrol);
|
||||||
|
@ -132,12 +132,17 @@ struct fsl_dma_private {
|
|||||||
* Since each link descriptor has a 32-bit byte count field, we set
|
* 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
|
* period_bytes_max to the largest 32-bit number. We also have no maximum
|
||||||
* number of periods.
|
* 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 = {
|
static const struct snd_pcm_hardware fsl_dma_hardware = {
|
||||||
|
|
||||||
.info = SNDRV_PCM_INFO_INTERLEAVED |
|
.info = SNDRV_PCM_INFO_INTERLEAVED |
|
||||||
SNDRV_PCM_INFO_MMAP |
|
SNDRV_PCM_INFO_MMAP |
|
||||||
SNDRV_PCM_INFO_MMAP_VALID,
|
SNDRV_PCM_INFO_MMAP_VALID |
|
||||||
|
SNDRV_PCM_INFO_JOINT_DUPLEX,
|
||||||
.formats = FSLDMA_PCM_FORMATS,
|
.formats = FSLDMA_PCM_FORMATS,
|
||||||
.rates = FSLDMA_PCM_RATES,
|
.rates = FSLDMA_PCM_RATES,
|
||||||
.rate_min = 5512,
|
.rate_min = 5512,
|
||||||
|
@ -67,6 +67,8 @@
|
|||||||
* @ssi: pointer to the SSI's registers
|
* @ssi: pointer to the SSI's registers
|
||||||
* @ssi_phys: physical address of the SSI registers
|
* @ssi_phys: physical address of the SSI registers
|
||||||
* @irq: IRQ of this SSI
|
* @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
|
* @dev: struct device pointer
|
||||||
* @playback: the number of playback streams opened
|
* @playback: the number of playback streams opened
|
||||||
* @capture: the number of capture streams opened
|
* @capture: the number of capture streams opened
|
||||||
@ -79,6 +81,8 @@ struct fsl_ssi_private {
|
|||||||
struct ccsr_ssi __iomem *ssi;
|
struct ccsr_ssi __iomem *ssi;
|
||||||
dma_addr_t ssi_phys;
|
dma_addr_t ssi_phys;
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
|
struct snd_pcm_substream *first_stream;
|
||||||
|
struct snd_pcm_substream *second_stream;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
unsigned int playback;
|
unsigned int playback;
|
||||||
unsigned int capture;
|
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)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
ssi_private->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 fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
|
||||||
|
|
||||||
struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
|
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);
|
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;
|
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_RESUME:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
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 {
|
} 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
|
* 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)
|
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||||
ssi_private->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
|
* If this is the last active substream, disable the SSI and release
|
||||||
* the IRQ.
|
* the IRQ.
|
||||||
|
@ -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 */
|
/* 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 */
|
/* set = unmute headphone */
|
||||||
locomo_gpio_write(&poodle_locomo_device.dev,
|
locomo_gpio_write(&poodle_locomo_device.dev,
|
||||||
POODLE_LOCOMO_GPIO_MUTE_L, 1);
|
POODLE_LOCOMO_GPIO_MUTE_L, 1);
|
||||||
locomo_gpio_write(&poodle_locomo_device.dev,
|
locomo_gpio_write(&poodle_locomo_device.dev,
|
||||||
POODLE_LOCOMO_GPIO_MUTE_R, 1);
|
POODLE_LOCOMO_GPIO_MUTE_R, 1);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int poodle_hw_params(struct snd_pcm_substream *substream,
|
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),
|
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,
|
SOC_ENUM_EXT("Jack Function", poodle_enum[0], poodle_get_jack,
|
||||||
poodle_set_jack),
|
poodle_set_jack),
|
||||||
SOC_ENUM_EXT("Speaker Function", poodle_enum[1], poodle_get_spk,
|
SOC_ENUM_EXT("Speaker Function", poodle_enum[1], poodle_get_spk,
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include <asm/arch/pxa-regs.h>
|
#include <asm/arch/pxa-regs.h>
|
||||||
#include <asm/arch/hardware.h>
|
#include <asm/arch/hardware.h>
|
||||||
#include <asm/arch/audio.h>
|
#include <asm/arch/audio.h>
|
||||||
#include <asm/arch/tosa.h>
|
|
||||||
|
|
||||||
#include "../codecs/wm9712.h"
|
#include "../codecs/wm9712.h"
|
||||||
#include "pxa2xx-pcm.h"
|
#include "pxa2xx-pcm.h"
|
||||||
|
@ -470,6 +470,7 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dapm_reg_event);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan each dapm widget for complete audio path.
|
* Scan each dapm widget for complete audio path.
|
||||||
|
Loading…
Reference in New Issue
Block a user