aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/pxa/pxa-ssp.c
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2010-03-22 05:11:15 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-04-05 14:14:11 -0400
commit5f712b2b73a9fc87fcc52124cfe8adefaa0c92f5 (patch)
tree0e7ab3cedba6b50cdf603c433b79ceebf23972b0 /sound/soc/pxa/pxa-ssp.c
parentd522ffbfb9fccf6eca283cd2e8b03cf3d21fb616 (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.c23
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;