diff options
author | Wallace Wang <r59996@freescale.com> | 2009-06-15 14:52:35 +0800 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2009-10-13 11:03:56 -0400 |
commit | e0bff9f4dae194032b4a012b00446df3768221ee (patch) | |
tree | 4c72f71097e6d187a2431be795a3dbfe8853fc2d /sound | |
parent | cdbd3b0b898e64a2f1c630c84ace0f5da40d8e6b (diff) |
ENGR00096014-1 ASRC-ESAI per_2_per transfer
Add ASRC-ESAI p2p transfer support
Signed-off-by: Wallace Wang <r59996@freescale.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/imx/imx-3stack-wm8580.c | 139 | ||||
-rw-r--r-- | sound/soc/imx/imx-pcm.c | 305 | ||||
-rw-r--r-- | sound/soc/imx/imx-pcm.h | 19 |
3 files changed, 342 insertions, 121 deletions
diff --git a/sound/soc/imx/imx-3stack-wm8580.c b/sound/soc/imx/imx-3stack-wm8580.c index 4d24b48eed48..5c09fa27a964 100644 --- a/sound/soc/imx/imx-3stack-wm8580.c +++ b/sound/soc/imx/imx-3stack-wm8580.c @@ -34,6 +34,38 @@ #include "imx-esai.h" #include "../codecs/wm8580.h" +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) +#include <linux/mxc_asrc.h> +#endif + +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) +static unsigned int asrc_rates[] = { + 0, + 8000, + 11025, + 16000, + 22050, + 32000, + 44100, + 48000, + 64000, + 88200, + 96000, + 176400, + 192000, +}; + +struct asrc_esai { + unsigned int cpu_dai_rates; + unsigned int codec_dai_rates; + enum asrc_pair_index asrc_index; + unsigned int output_sample_rate; +}; + +static struct asrc_esai asrc_esai_data; + +#endif + struct imx_3stack_pcm_state { int lr_clk_active; }; @@ -46,6 +78,20 @@ static struct imx_3stack_pcm_state clk_state; static int imx_3stack_startup(struct snd_pcm_substream *substream) { clk_state.lr_clk_active++; +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) + if (asrc_esai_data.output_sample_rate != 0) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai_link *pcm_link = rtd->dai; + struct snd_soc_dai *cpu_dai = pcm_link->cpu_dai; + struct snd_soc_dai *codec_dai = pcm_link->codec_dai; + asrc_esai_data.cpu_dai_rates = cpu_dai->playback.rates; + asrc_esai_data.codec_dai_rates = codec_dai->playback.rates; + cpu_dai->playback.rates = + SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT; + codec_dai->playback.rates = + SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT; + } +#endif return 0; } @@ -56,6 +102,15 @@ static void imx_3stack_shutdown(struct snd_pcm_substream *substream) struct snd_soc_dai_link *pcm_link = rtd->dai; struct snd_soc_dai *codec_dai = pcm_link->codec_dai; +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) + if (asrc_esai_data.output_sample_rate != 0) { + struct snd_soc_dai *cpu_dai = pcm_link->cpu_dai; + codec_dai->playback.rates = asrc_esai_data.codec_dai_rates; + cpu_dai->playback.rates = asrc_esai_data.cpu_dai_rates; + asrc_release_pair(asrc_esai_data.asrc_index); + } +#endif + /* disable the PLL if there are no active Tx or Rx channels */ if (!codec_dai->active) snd_soc_dai_set_pll(codec_dai, 0, 0, 0); @@ -76,6 +131,40 @@ static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream, if (clk_state.lr_clk_active > 1) return 0; +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) + if (asrc_esai_data.output_sample_rate != 0) { + unsigned int asrc_input_rate = rate; + unsigned int channel = params_channels(params); + struct mxc_runtime_data *pcm_data = + substream->runtime->private_data; + struct asrc_config config; + int retVal = 0;; + + retVal = asrc_req_pair(channel, &asrc_esai_data.asrc_index); + if (retVal < 0) { + pr_err("Fail to request asrc pair\n"); + return -1; + } + + config.pair = asrc_esai_data.asrc_index; + config.channel_num = channel; + config.input_sample_rate = asrc_input_rate; + config.output_sample_rate = asrc_esai_data.output_sample_rate; + config.inclk = INCLK_NONE; + config.word_width = 32; + config.outclk = OUTCLK_ESAI_TX; + retVal = asrc_config_pair(&config); + if (retVal < 0) { + pr_err("Fail to config asrc\n"); + asrc_release_pair(asrc_esai_data.asrc_index); + return retVal; + } + rate = asrc_esai_data.output_sample_rate; + pcm_data->asrc_index = asrc_esai_data.asrc_index; + pcm_data->asrc_enable = 1; + } +#endif + switch (rate) { case 8000: lrclk_ratio = 5; @@ -192,9 +281,59 @@ static const struct snd_soc_dapm_route audio_map[] = { }; +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) +static int asrc_func; + +static const char *asrc_function[] = + { "disable", "8KHz", "11.025KHz", "16KHz", "22.05KHz", "32KHz", "44.1KHz", + "48KHz", "64KHz", "88.2KHz", "96KHz", "176.4KHz", "192KHz" +}; + +static const struct soc_enum asrc_enum[] = { + SOC_ENUM_SINGLE_EXT(13, asrc_function), +}; + +static int asrc_get_rate(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.enumerated.item[0] = asrc_func; + return 0; +} + +static int asrc_set_rate(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + if (asrc_func == ucontrol->value.enumerated.item[0]) + return 0; + + asrc_func = ucontrol->value.enumerated.item[0]; + asrc_esai_data.output_sample_rate = asrc_rates[asrc_func]; + + return 1; +} + +static const struct snd_kcontrol_new asrc_controls[] = { + SOC_ENUM_EXT("ASRC", asrc_enum[0], asrc_get_rate, + asrc_set_rate), +}; + +#endif + static int imx_3stack_wm8580_init(struct snd_soc_codec *codec) { +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) + int i; + int ret; + for (i = 0; i < ARRAY_SIZE(asrc_controls); i++) { + ret = snd_ctl_add(codec->card, + snd_soc_cnew(&asrc_controls[i], codec, NULL)); + if (ret < 0) + return ret; + } + asrc_esai_data.output_sample_rate = asrc_rates[asrc_func]; +#endif + snd_soc_dapm_new_controls(codec, imx_3stack_dapm_widgets, ARRAY_SIZE(imx_3stack_dapm_widgets)); diff --git a/sound/soc/imx/imx-pcm.c b/sound/soc/imx/imx-pcm.c index 1f4ddc965e99..8f98b5af4b3b 100644 --- a/sound/soc/imx/imx-pcm.c +++ b/sound/soc/imx/imx-pcm.c @@ -34,6 +34,10 @@ #include "imx-ssi.h" #include "imx-esai.h" +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) +#include <linux/mxc_asrc.h> +#endif + #ifdef CONFIG_SND_MXC_SOC_IRAM static bool UseIram = 1; #else @@ -68,15 +72,6 @@ static const struct snd_pcm_hardware imx_pcm_hardware = { .fifo_size = 0, }; -struct mxc_runtime_data { - int dma_ch; - spinlock_t dma_lock; - int active, period, periods; - int dma_wchannel; - int dma_active; - int dma_alloc; -}; - static uint32_t audio_iram_phys_base_addr; static void *audio_iram_virt_base_addr; @@ -123,7 +118,7 @@ static int imx_iram_audio_playback_mmap(struct snd_pcm_substream *substream, phys_addr - physical address of iram buffer returns - virtual address of the iram buffer or NULL if fail */ -static void *imx_iram_init(dma_addr_t * phys_addr, size_t bytes) +static void *imx_iram_init(dma_addr_t *phys_addr, size_t bytes) { void *iram_base; @@ -146,93 +141,111 @@ static void imx_iram_free(void) iounmap(audio_iram_virt_base_addr); } -static int imx_get_sdma_transfer(int format, int dai_port, int stream_type) +static int imx_get_sdma_transfer(int format, int dai_port, + struct snd_pcm_substream *substream) { int transfer = -1; - if (dai_port == IMX_DAI_SSI0) { - if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) { - if (format == SNDRV_PCM_FORMAT_S16_LE) - transfer = MXC_DMA_SSI1_16BIT_TX0; - else if (format == SNDRV_PCM_FORMAT_S24_LE) - transfer = MXC_DMA_SSI1_24BIT_TX0; - else if (format == SNDRV_PCM_FORMAT_S20_3LE) - transfer = MXC_DMA_SSI1_24BIT_TX0; - } else { - if (format == SNDRV_PCM_FORMAT_S16_LE) - transfer = MXC_DMA_SSI1_16BIT_RX0; - else if (format == SNDRV_PCM_FORMAT_S24_LE) - transfer = MXC_DMA_SSI1_24BIT_RX0; - else if (format == SNDRV_PCM_FORMAT_S20_3LE) - transfer = MXC_DMA_SSI1_24BIT_RX0; - } - } else if (dai_port == IMX_DAI_SSI1) { - if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) { - if (format == SNDRV_PCM_FORMAT_S16_LE) - transfer = MXC_DMA_SSI1_16BIT_TX1; - else if (format == SNDRV_PCM_FORMAT_S24_LE) - transfer = MXC_DMA_SSI1_24BIT_TX1; - else if (format == SNDRV_PCM_FORMAT_S20_3LE) - transfer = MXC_DMA_SSI1_24BIT_TX1; - } else { - if (format == SNDRV_PCM_FORMAT_S16_LE) - transfer = MXC_DMA_SSI1_16BIT_RX1; - else if (format == SNDRV_PCM_FORMAT_S24_LE) - transfer = MXC_DMA_SSI1_24BIT_RX1; - else if (format == SNDRV_PCM_FORMAT_S20_3LE) - transfer = MXC_DMA_SSI1_24BIT_RX1; - } - } else if (dai_port == IMX_DAI_SSI2) { - if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) { - if (format == SNDRV_PCM_FORMAT_S16_LE) - transfer = MXC_DMA_SSI2_16BIT_TX0; - else if (format == SNDRV_PCM_FORMAT_S24_LE) - transfer = MXC_DMA_SSI2_24BIT_TX0; - else if (format == SNDRV_PCM_FORMAT_S20_3LE) - transfer = MXC_DMA_SSI2_24BIT_TX0; - } else { - if (format == SNDRV_PCM_FORMAT_S16_LE) - transfer = MXC_DMA_SSI2_16BIT_RX0; - else if (format == SNDRV_PCM_FORMAT_S24_LE) - transfer = MXC_DMA_SSI2_24BIT_RX0; - else if (format == SNDRV_PCM_FORMAT_S20_3LE) - transfer = MXC_DMA_SSI2_24BIT_RX0; - } - } else if (dai_port == IMX_DAI_SSI3) { - if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) { - if (format == SNDRV_PCM_FORMAT_S16_LE) - transfer = MXC_DMA_SSI2_16BIT_TX1; - else if (format == SNDRV_PCM_FORMAT_S24_LE) - transfer = MXC_DMA_SSI2_24BIT_TX1; - else if (format == SNDRV_PCM_FORMAT_S20_3LE) - transfer = MXC_DMA_SSI2_24BIT_TX1; - } else { - if (format == SNDRV_PCM_FORMAT_S16_LE) - transfer = MXC_DMA_SSI2_16BIT_RX1; - else if (format == SNDRV_PCM_FORMAT_S24_LE) - transfer = MXC_DMA_SSI2_24BIT_RX1; - else if (format == SNDRV_PCM_FORMAT_S20_3LE) - transfer = MXC_DMA_SSI2_24BIT_RX1; +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) + struct snd_pcm_runtime *runtime = substream->runtime; + struct mxc_runtime_data *prtd = runtime->private_data; + if (prtd->asrc_enable == 1) { + if (dai_port & IMX_DAI_ESAI_TX) { + if (prtd->asrc_index == 0) + transfer = MXC_DMA_ASRCA_ESAI; + else if (prtd->asrc_index == 1) + transfer = MXC_DMA_ASRCB_ESAI; + else + transfer = MXC_DMA_ASRCC_ESAI; } - } else if ((dai_port & IMX_DAI_ESAI_TX) - || (dai_port & IMX_DAI_ESAI_RX)) { - if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) { - if (format == SNDRV_PCM_FORMAT_S16_LE) - transfer = MXC_DMA_ESAI_16BIT_TX; - else if (format == SNDRV_PCM_FORMAT_S24_LE) - transfer = MXC_DMA_ESAI_24BIT_TX; - else if (format == SNDRV_PCM_FORMAT_S20_3LE) - transfer = MXC_DMA_ESAI_24BIT_TX; - } else { - if (format == SNDRV_PCM_FORMAT_S16_LE) - transfer = MXC_DMA_ESAI_16BIT_RX; - else if (format == SNDRV_PCM_FORMAT_S24_LE) - transfer = MXC_DMA_ESAI_24BIT_RX; - else if (format == SNDRV_PCM_FORMAT_S20_3LE) - transfer = MXC_DMA_ESAI_24BIT_RX; + } else { +#endif + + if (dai_port == IMX_DAI_SSI0) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (format == SNDRV_PCM_FORMAT_S16_LE) + transfer = MXC_DMA_SSI1_16BIT_TX0; + else if (format == SNDRV_PCM_FORMAT_S24_LE) + transfer = MXC_DMA_SSI1_24BIT_TX0; + else if (format == SNDRV_PCM_FORMAT_S20_3LE) + transfer = MXC_DMA_SSI1_24BIT_TX0; + } else { + if (format == SNDRV_PCM_FORMAT_S16_LE) + transfer = MXC_DMA_SSI1_16BIT_RX0; + else if (format == SNDRV_PCM_FORMAT_S24_LE) + transfer = MXC_DMA_SSI1_24BIT_RX0; + else if (format == SNDRV_PCM_FORMAT_S20_3LE) + transfer = MXC_DMA_SSI1_24BIT_RX0; + } + } else if (dai_port == IMX_DAI_SSI1) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (format == SNDRV_PCM_FORMAT_S16_LE) + transfer = MXC_DMA_SSI1_16BIT_TX1; + else if (format == SNDRV_PCM_FORMAT_S24_LE) + transfer = MXC_DMA_SSI1_24BIT_TX1; + else if (format == SNDRV_PCM_FORMAT_S20_3LE) + transfer = MXC_DMA_SSI1_24BIT_TX1; + } else { + if (format == SNDRV_PCM_FORMAT_S16_LE) + transfer = MXC_DMA_SSI1_16BIT_RX1; + else if (format == SNDRV_PCM_FORMAT_S24_LE) + transfer = MXC_DMA_SSI1_24BIT_RX1; + else if (format == SNDRV_PCM_FORMAT_S20_3LE) + transfer = MXC_DMA_SSI1_24BIT_RX1; + } + } else if (dai_port == IMX_DAI_SSI2) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (format == SNDRV_PCM_FORMAT_S16_LE) + transfer = MXC_DMA_SSI2_16BIT_TX0; + else if (format == SNDRV_PCM_FORMAT_S24_LE) + transfer = MXC_DMA_SSI2_24BIT_TX0; + else if (format == SNDRV_PCM_FORMAT_S20_3LE) + transfer = MXC_DMA_SSI2_24BIT_TX0; + } else { + if (format == SNDRV_PCM_FORMAT_S16_LE) + transfer = MXC_DMA_SSI2_16BIT_RX0; + else if (format == SNDRV_PCM_FORMAT_S24_LE) + transfer = MXC_DMA_SSI2_24BIT_RX0; + else if (format == SNDRV_PCM_FORMAT_S20_3LE) + transfer = MXC_DMA_SSI2_24BIT_RX0; + } + } else if (dai_port == IMX_DAI_SSI3) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (format == SNDRV_PCM_FORMAT_S16_LE) + transfer = MXC_DMA_SSI2_16BIT_TX1; + else if (format == SNDRV_PCM_FORMAT_S24_LE) + transfer = MXC_DMA_SSI2_24BIT_TX1; + else if (format == SNDRV_PCM_FORMAT_S20_3LE) + transfer = MXC_DMA_SSI2_24BIT_TX1; + } else { + if (format == SNDRV_PCM_FORMAT_S16_LE) + transfer = MXC_DMA_SSI2_16BIT_RX1; + else if (format == SNDRV_PCM_FORMAT_S24_LE) + transfer = MXC_DMA_SSI2_24BIT_RX1; + else if (format == SNDRV_PCM_FORMAT_S20_3LE) + transfer = MXC_DMA_SSI2_24BIT_RX1; + } + } else if ((dai_port & IMX_DAI_ESAI_TX) + || (dai_port & IMX_DAI_ESAI_RX)) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (format == SNDRV_PCM_FORMAT_S16_LE) + transfer = MXC_DMA_ESAI_16BIT_TX; + else if (format == SNDRV_PCM_FORMAT_S24_LE) + transfer = MXC_DMA_ESAI_24BIT_TX; + else if (format == SNDRV_PCM_FORMAT_S20_3LE) + transfer = MXC_DMA_ESAI_24BIT_TX; + } else { + if (format == SNDRV_PCM_FORMAT_S16_LE) + transfer = MXC_DMA_ESAI_16BIT_RX; + else if (format == SNDRV_PCM_FORMAT_S24_LE) + transfer = MXC_DMA_ESAI_24BIT_RX; + else if (format == SNDRV_PCM_FORMAT_S20_3LE) + transfer = MXC_DMA_ESAI_24BIT_RX; + } } +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) } - +#endif return transfer; } @@ -252,8 +265,8 @@ static int dma_new_period(struct snd_pcm_substream *substream) dbg("period pos ALSA %x DMA %x\n", runtime->periods, prtd->period); dbg("period size ALSA %x DMA %x Offset %x dmasize %x\n", - (unsigned int)runtime->period_size, runtime->dma_bytes, - offset, dma_size); + (unsigned int)runtime->period_size, + runtime->dma_bytes, offset, dma_size); dbg("DMA addr %x\n", runtime->dma_addr + offset); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -266,13 +279,13 @@ static int dma_new_period(struct snd_pcm_substream *substream) sdma_request.num_of_bytes = dma_size; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - mxc_dma_config(prtd->dma_wchannel, &sdma_request, 1, - MXC_DMA_MODE_WRITE); + mxc_dma_config(prtd->dma_wchannel, + &sdma_request, 1, MXC_DMA_MODE_WRITE); ret = mxc_dma_enable(prtd->dma_wchannel); } else { - mxc_dma_config(prtd->dma_wchannel, &sdma_request, 1, - MXC_DMA_MODE_READ); + mxc_dma_config(prtd->dma_wchannel, + &sdma_request, 1, MXC_DMA_MODE_READ); ret = mxc_dma_enable(prtd->dma_wchannel); } prtd->dma_active = 1; @@ -313,8 +326,39 @@ static int imx_pcm_prepare(struct snd_pcm_substream *substream) /* only allocate the DMA chn once */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) + if (prtd->asrc_enable == 1) { + struct dma_channel_info info; + mxc_dma_requestbuf_t sdma_request; + info.asrc.channs = runtime->channels; + if (prtd->dma_asrc) { + mxc_dma_free(prtd->dma_asrc); + prtd->dma_asrc = 0; + } + memset(&sdma_request, 0, sizeof(mxc_dma_requestbuf_t)); + /* num_of_bytes can be set any value except for zero */ + sdma_request.num_of_bytes = 0x40; + channel = + mxc_dma_request_ext(prtd->dma_ch, + "ALSA TX SDMA", &info); + + mxc_dma_config(channel, &sdma_request, + 1, MXC_DMA_MODE_WRITE); + prtd->dma_asrc = channel; + if (prtd->asrc_index == 0) + prtd->dma_ch = MXC_DMA_ASRC_A_RX; + else if (prtd->asrc_index == 1) + prtd->dma_ch = MXC_DMA_ASRC_B_RX; + else + prtd->dma_ch = MXC_DMA_ASRC_C_RX; + + channel = + mxc_dma_request(MXC_DMA_ASRC_A_RX, "ALSA ASRC RX"); + } else + channel = mxc_dma_request(prtd->dma_ch, "ALSA TX SDMA"); +#else channel = mxc_dma_request(prtd->dma_ch, "ALSA TX SDMA"); +#endif if (channel < 0) { pr_err("imx-pcm: error requesting \ a write dma channel\n"); @@ -341,16 +385,16 @@ static int imx_pcm_prepare(struct snd_pcm_substream *substream) return 0; } -static int imx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) +static int imx_pcm_hw_params(struct snd_pcm_substream + *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct mxc_runtime_data *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; - prtd->dma_ch = imx_get_sdma_transfer(params_format(params), - rtd->dai->cpu_dai->id, - substream->stream); + prtd->dma_ch = + imx_get_sdma_transfer(params_format(params), + rtd->dai->cpu_dai->id, substream); if (prtd->dma_ch < 0) { printk(KERN_ERR "imx-pcm: invaild sdma transfer type"); @@ -372,6 +416,12 @@ static int imx_pcm_hw_free(struct snd_pcm_substream *substream) prtd->dma_wchannel = 0; prtd->dma_alloc = 0; } +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) + if ((prtd->asrc_enable == 1) && prtd->dma_asrc) { + mxc_dma_free(prtd->dma_asrc); + prtd->dma_asrc = 0; + } +#endif return 0; } @@ -389,11 +439,23 @@ static int imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) prtd->active = 1; ret = dma_new_period(substream); ret = dma_new_period(substream); +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) + if (prtd->asrc_enable == 1) { + ret = mxc_dma_enable(prtd->dma_asrc); + asrc_start_conv(prtd->asrc_index); + } +#endif break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: prtd->active = 0; +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) + if (prtd->asrc_enable == 1) { + mxc_dma_disable(prtd->dma_asrc); + asrc_stop_conv(prtd->asrc_index); + } +#endif break; default: ret = -EINVAL; @@ -403,7 +465,9 @@ static int imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return ret; } -static snd_pcm_uframes_t imx_pcm_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t imx_pcm_pointer(struct + snd_pcm_substream + *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct mxc_runtime_data *prtd = runtime->private_data; @@ -466,12 +530,14 @@ imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) if (dev_data) ext_ram = dev_data->ext_ram; - if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) || ext_ram - || !UseIram) { - ret = dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); + if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) + || ext_ram || !UseIram) { + ret = + dma_mmap_writecombine(substream->pcm->card-> + dev, vma, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); return ret; } else return imx_iram_audio_playback_mmap(substream, vma); @@ -508,8 +574,9 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) buf->private_data = NULL; if ((stream == SNDRV_PCM_STREAM_CAPTURE) || ext_ram || !UseIram) - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); + buf->area = + dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); else buf->area = imx_iram_init(&buf->addr, size); @@ -545,9 +612,10 @@ static void imx_pcm_free_dma_buffers(struct snd_pcm *pcm) if (!buf->area) continue; - if ((stream == SNDRV_PCM_STREAM_CAPTURE) || ext_ram || !UseIram) - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); + if ((stream == SNDRV_PCM_STREAM_CAPTURE) + || ext_ram || !UseIram) + dma_free_writecombine(pcm->card->dev, + buf->bytes, buf->area, buf->addr); else imx_iram_free(); buf->area = NULL; @@ -556,8 +624,8 @@ static void imx_pcm_free_dma_buffers(struct snd_pcm *pcm) static u64 imx_pcm_dmamask = 0xffffffff; -static int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, - struct snd_pcm *pcm) +static int imx_pcm_new(struct snd_card *card, + struct snd_soc_dai *dai, struct snd_pcm *pcm) { int ret = 0; @@ -579,7 +647,7 @@ static int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, if (ret) goto out; } -out: + out: return ret; } @@ -589,6 +657,7 @@ struct snd_soc_platform imx_soc_platform = { .pcm_new = imx_pcm_new, .pcm_free = imx_pcm_free_dma_buffers, }; + EXPORT_SYMBOL_GPL(imx_soc_platform); MODULE_AUTHOR("Liam Girdwood"); diff --git a/sound/soc/imx/imx-pcm.h b/sound/soc/imx/imx-pcm.h index 3c3334453ec7..c22a42b70364 100644 --- a/sound/soc/imx/imx-pcm.h +++ b/sound/soc/imx/imx-pcm.h @@ -1,6 +1,9 @@ /* * imx-pcm.h :- ASoC platform header for Freescale i.MX * + * Copyright 2006 Wolfson Microelectronics PLC. + * Copyright 2006, 2009 Freescale Semiconductor, Inc. All Rights Reserved. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -60,9 +63,19 @@ #define AUDMUX_CNMCR_CNTHI(x) (((x) & 0xff) << 8) #define AUDMUX_CNMCR_CNTLOW(x) (((x) & 0xff) << 0) -struct mxc_pcm_dma_params { - char *name; /* stream identifier */ - dma_channel_params params; + +struct mxc_runtime_data { + int dma_ch; + spinlock_t dma_lock; + int active, period, periods; + int dma_wchannel; + int dma_active; + int dma_alloc; +#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) + int dma_asrc; + int asrc_index; + int asrc_enable; +#endif }; extern struct snd_soc_platform imx_soc_platform; |