diff options
author | Daniel Mack <daniel@caiaq.de> | 2010-03-22 05:11:15 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-04-05 14:14:11 -0400 |
commit | 5f712b2b73a9fc87fcc52124cfe8adefaa0c92f5 (patch) | |
tree | 0e7ab3cedba6b50cdf603c433b79ceebf23972b0 /sound/soc/pxa/pxa-ssp.c | |
parent | d522ffbfb9fccf6eca283cd2e8b03cf3d21fb616 (diff) |
ALSA: ASoC: move dma_data from snd_soc_dai to snd_soc_pcm_stream
This fixes a memory corruption when ASoC devices are used in
full-duplex mode. Specifically for pxa-ssp code, where this pointer
is dynamically allocated for each direction and destroyed upon each
stream start.
All other platforms are fixed blindly, I couldn't even compile-test
them. Sorry for any breakage I may have caused.
[Note that this is a backported version for 2.6.34.
Upstream commit is fd23b7dee]
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Reported-by: Sven Neumann <s.neumann@raumfeld.com>
Reported-by: Michael Hirsch <m.hirsch@raumfeld.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/pxa/pxa-ssp.c')
-rw-r--r-- | sound/soc/pxa/pxa-ssp.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 9e95e5117c88..6959c5199160 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c | |||
@@ -121,10 +121,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, | |||
121 | ssp_disable(ssp); | 121 | ssp_disable(ssp); |
122 | } | 122 | } |
123 | 123 | ||
124 | if (cpu_dai->dma_data) { | 124 | kfree(snd_soc_dai_get_dma_data(cpu_dai, substream)); |
125 | kfree(cpu_dai->dma_data); | 125 | snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); |
126 | cpu_dai->dma_data = NULL; | 126 | |
127 | } | ||
128 | return ret; | 127 | return ret; |
129 | } | 128 | } |
130 | 129 | ||
@@ -141,10 +140,8 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, | |||
141 | clk_disable(ssp->clk); | 140 | clk_disable(ssp->clk); |
142 | } | 141 | } |
143 | 142 | ||
144 | if (cpu_dai->dma_data) { | 143 | kfree(snd_soc_dai_get_dma_data(cpu_dai, substream)); |
145 | kfree(cpu_dai->dma_data); | 144 | snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); |
146 | cpu_dai->dma_data = NULL; | ||
147 | } | ||
148 | } | 145 | } |
149 | 146 | ||
150 | #ifdef CONFIG_PM | 147 | #ifdef CONFIG_PM |
@@ -569,19 +566,23 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, | |||
569 | u32 sspsp; | 566 | u32 sspsp; |
570 | int width = snd_pcm_format_physical_width(params_format(params)); | 567 | int width = snd_pcm_format_physical_width(params_format(params)); |
571 | int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf; | 568 | int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf; |
569 | struct pxa2xx_pcm_dma_params *dma_data; | ||
570 | |||
571 | dma_data = snd_soc_dai_get_dma_data(dai, substream); | ||
572 | 572 | ||
573 | /* generate correct DMA params */ | 573 | /* generate correct DMA params */ |
574 | if (cpu_dai->dma_data) | 574 | kfree(dma_data); |
575 | kfree(cpu_dai->dma_data); | ||
576 | 575 | ||
577 | /* Network mode with one active slot (ttsa == 1) can be used | 576 | /* Network mode with one active slot (ttsa == 1) can be used |
578 | * to force 16-bit frame width on the wire (for S16_LE), even | 577 | * to force 16-bit frame width on the wire (for S16_LE), even |
579 | * with two channels. Use 16-bit DMA transfers for this case. | 578 | * with two channels. Use 16-bit DMA transfers for this case. |
580 | */ | 579 | */ |
581 | cpu_dai->dma_data = ssp_get_dma_params(ssp, | 580 | dma_data = ssp_get_dma_params(ssp, |
582 | ((chn == 2) && (ttsa != 1)) || (width == 32), | 581 | ((chn == 2) && (ttsa != 1)) || (width == 32), |
583 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | 582 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK); |
584 | 583 | ||
584 | snd_soc_dai_set_dma_data(dai, substream, dma_data); | ||
585 | |||
585 | /* we can only change the settings if the port is not in use */ | 586 | /* we can only change the settings if the port is not in use */ |
586 | if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) | 587 | if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) |
587 | return 0; | 588 | return 0; |