mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
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. Reported-by: Sven Neumann <s.neumann@raumfeld.com> Reported-by: Michael Hirsch <m.hirsch@raumfeld.com> Signed-off-by: Daniel Mack <daniel@caiaq.de> Acked-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Acked-by: Jarkko Nikula <jhnikula@gmail.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
@@ -224,7 +224,6 @@ struct snd_soc_dai {
|
|||||||
struct snd_soc_codec *codec;
|
struct snd_soc_codec *codec;
|
||||||
unsigned int active;
|
unsigned int active;
|
||||||
unsigned char pop_wait:1;
|
unsigned char pop_wait:1;
|
||||||
void *dma_data;
|
|
||||||
|
|
||||||
/* DAI private data */
|
/* DAI private data */
|
||||||
void *private_data;
|
void *private_data;
|
||||||
@@ -235,4 +234,21 @@ struct snd_soc_dai {
|
|||||||
struct list_head list;
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,
|
||||||
|
const struct snd_pcm_substream *ss)
|
||||||
|
{
|
||||||
|
return (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
|
||||||
|
dai->playback.dma_data : dai->capture.dma_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai,
|
||||||
|
const struct snd_pcm_substream *ss,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
|
dai->playback.dma_data = data;
|
||||||
|
else
|
||||||
|
dai->capture.dma_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -376,6 +376,7 @@ struct snd_soc_pcm_stream {
|
|||||||
unsigned int channels_min; /* min channels */
|
unsigned int channels_min; /* min channels */
|
||||||
unsigned int channels_max; /* max channels */
|
unsigned int channels_max; /* max channels */
|
||||||
unsigned int active; /* num of active users of the stream */
|
unsigned int active; /* num of active users of the stream */
|
||||||
|
void *dma_data; /* used by platform code */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SoC audio ops */
|
/* SoC audio ops */
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||||||
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
|
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
|
||||||
runtime->dma_bytes = params_buffer_bytes(params);
|
runtime->dma_bytes = params_buffer_bytes(params);
|
||||||
|
|
||||||
prtd->params = rtd->dai->cpu_dai->dma_data;
|
prtd->params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
|
||||||
prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
|
prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
|
||||||
|
|
||||||
prtd->dma_buffer = runtime->dma_addr;
|
prtd->dma_buffer = runtime->dma_addr;
|
||||||
|
|||||||
@@ -363,12 +363,12 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|||||||
ssc_p->dma_params[dir] = dma_params;
|
ssc_p->dma_params[dir] = dma_params;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The cpu_dai->dma_data field is only used to communicate the
|
* The snd_soc_pcm_stream->dma_data field is only used to communicate
|
||||||
* appropriate DMA parameters to the pcm driver hw_params()
|
* the appropriate DMA parameters to the pcm driver hw_params()
|
||||||
* function. It should not be used for other purposes
|
* function. It should not be used for other purposes
|
||||||
* as it is common to all substreams.
|
* as it is common to all substreams.
|
||||||
*/
|
*/
|
||||||
rtd->dai->cpu_dai->dma_data = dma_params;
|
snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_params);
|
||||||
|
|
||||||
channels = params_channels(params);
|
channels = params_channels(params);
|
||||||
|
|
||||||
|
|||||||
@@ -585,7 +585,8 @@ static int davinci_i2s_probe(struct platform_device *pdev)
|
|||||||
dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
|
dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
|
||||||
|
|
||||||
davinci_i2s_dai.private_data = dev;
|
davinci_i2s_dai.private_data = dev;
|
||||||
davinci_i2s_dai.dma_data = dev->dma_params;
|
davinci_i2s_dai.capture.dma_data = dev->dma_params;
|
||||||
|
davinci_i2s_dai.playback.dma_data = dev->dma_params;
|
||||||
ret = snd_soc_register_dai(&davinci_i2s_dai);
|
ret = snd_soc_register_dai(&davinci_i2s_dai);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto err_free_mem;
|
goto err_free_mem;
|
||||||
|
|||||||
@@ -917,7 +917,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
dma_data->channel = res->start;
|
dma_data->channel = res->start;
|
||||||
davinci_mcasp_dai[pdata->op_mode].private_data = dev;
|
davinci_mcasp_dai[pdata->op_mode].private_data = dev;
|
||||||
davinci_mcasp_dai[pdata->op_mode].dma_data = dev->dma_params;
|
davinci_mcasp_dai[pdata->op_mode].capture.dma_data = dev->dma_params;
|
||||||
|
davinci_mcasp_dai[pdata->op_mode].playback.dma_data = dev->dma_params;
|
||||||
davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev;
|
davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev;
|
||||||
ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]);
|
ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]);
|
||||||
|
|
||||||
|
|||||||
@@ -649,8 +649,10 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
|
|||||||
struct snd_pcm_hardware *ppcm;
|
struct snd_pcm_hardware *ppcm;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct davinci_pcm_dma_params *pa = rtd->dai->cpu_dai->dma_data;
|
struct davinci_pcm_dma_params *pa;
|
||||||
struct davinci_pcm_dma_params *params;
|
struct davinci_pcm_dma_params *params;
|
||||||
|
|
||||||
|
pa = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
|
||||||
if (!pa)
|
if (!pa)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
params = &pa[substream->stream];
|
params = &pa[substream->stream];
|
||||||
|
|||||||
@@ -222,7 +222,8 @@ static int davinci_vcif_probe(struct platform_device *pdev)
|
|||||||
davinci_vc->davinci_vcif.dma_rx_addr;
|
davinci_vc->davinci_vcif.dma_rx_addr;
|
||||||
|
|
||||||
davinci_vcif_dai.dev = &pdev->dev;
|
davinci_vcif_dai.dev = &pdev->dev;
|
||||||
davinci_vcif_dai.dma_data = davinci_vcif_dev->dma_params;
|
davinci_vcif_dai.capture.dma_data = davinci_vcif_dev->dma_params;
|
||||||
|
davinci_vcif_dai.playback.dma_data = davinci_vcif_dev->dma_params;
|
||||||
davinci_vcif_dai.private_data = davinci_vcif_dev;
|
davinci_vcif_dai.private_data = davinci_vcif_dev;
|
||||||
|
|
||||||
ret = snd_soc_register_dai(&davinci_vcif_dai);
|
ret = snd_soc_register_dai(&davinci_vcif_dai);
|
||||||
|
|||||||
@@ -83,11 +83,13 @@ static void snd_imx_dma_err_callback(int channel, void *data, int err)
|
|||||||
static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
|
static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct imx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
|
struct imx_pcm_dma_params *dma_params;
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
|
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
dma_params = snd_soc_get_dma_data(rtd->dai->cpu_dai, substream);
|
||||||
|
|
||||||
iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH);
|
iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH);
|
||||||
if (iprtd->dma < 0) {
|
if (iprtd->dma < 0) {
|
||||||
pr_err("Failed to claim the audio DMA\n");
|
pr_err("Failed to claim the audio DMA\n");
|
||||||
@@ -192,10 +194,12 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
|
|||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct imx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
|
struct imx_pcm_dma_params *dma_params;
|
||||||
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
|
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
dma_params = snd_soc_get_dma_data(rtd->dai->cpu_dai, substream);
|
||||||
|
|
||||||
iprtd->substream = substream;
|
iprtd->substream = substream;
|
||||||
iprtd->buf = (unsigned int *)substream->dma_buffer.area;
|
iprtd->buf = (unsigned int *)substream->dma_buffer.area;
|
||||||
iprtd->period_cnt = 0;
|
iprtd->period_cnt = 0;
|
||||||
|
|||||||
@@ -234,17 +234,20 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
|
|||||||
struct snd_soc_dai *cpu_dai)
|
struct snd_soc_dai *cpu_dai)
|
||||||
{
|
{
|
||||||
struct imx_ssi *ssi = cpu_dai->private_data;
|
struct imx_ssi *ssi = cpu_dai->private_data;
|
||||||
|
struct imx_pcm_dma_params *dma_data;
|
||||||
u32 reg, sccr;
|
u32 reg, sccr;
|
||||||
|
|
||||||
/* Tx/Rx config */
|
/* Tx/Rx config */
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
reg = SSI_STCCR;
|
reg = SSI_STCCR;
|
||||||
cpu_dai->dma_data = &ssi->dma_params_tx;
|
dma_data = &ssi->dma_params_tx;
|
||||||
} else {
|
} else {
|
||||||
reg = SSI_SRCCR;
|
reg = SSI_SRCCR;
|
||||||
cpu_dai->dma_data = &ssi->dma_params_rx;
|
dma_data = &ssi->dma_params_rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
|
||||||
|
|
||||||
sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK;
|
sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK;
|
||||||
|
|
||||||
/* DAI data (word) size */
|
/* DAI data (word) size */
|
||||||
|
|||||||
@@ -322,7 +322,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
|
|||||||
omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
|
omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
|
||||||
omap_mcbsp_dai_dma_params[id][substream->stream].data_type =
|
omap_mcbsp_dai_dma_params[id][substream->stream].data_type =
|
||||||
OMAP_DMA_DATA_TYPE_S16;
|
OMAP_DMA_DATA_TYPE_S16;
|
||||||
cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
|
|
||||||
|
snd_soc_dai_set_dma_data(cpu_dai, substream,
|
||||||
|
&omap_mcbsp_dai_dma_params[id][substream->stream]);
|
||||||
|
|
||||||
if (mcbsp_data->configured) {
|
if (mcbsp_data->configured) {
|
||||||
/* McBSP already configured by another stream */
|
/* McBSP already configured by another stream */
|
||||||
|
|||||||
@@ -150,7 +150,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
|
|||||||
int stream = substream->stream;
|
int stream = substream->stream;
|
||||||
int channels, err, link_mask = 0;
|
int channels, err, link_mask = 0;
|
||||||
|
|
||||||
cpu_dai->dma_data = &omap_mcpdm_dai_dma_params[stream];
|
snd_soc_dai_set_dma_data(cpu_dai, substream,
|
||||||
|
&omap_mcpdm_dai_dma_params[stream]);
|
||||||
|
|
||||||
channels = params_channels(params);
|
channels = params_channels(params);
|
||||||
switch (channels) {
|
switch (channels) {
|
||||||
|
|||||||
@@ -100,9 +100,11 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct omap_runtime_data *prtd = runtime->private_data;
|
struct omap_runtime_data *prtd = runtime->private_data;
|
||||||
struct omap_pcm_dma_data *dma_data = rtd->dai->cpu_dai->dma_data;
|
struct omap_pcm_dma_data *dma_data;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
|
||||||
|
|
||||||
/* return if this is a bufferless transfer e.g.
|
/* return if this is a bufferless transfer e.g.
|
||||||
* codec <--> BT codec or GSM modem -- lg FIXME */
|
* codec <--> BT codec or GSM modem -- lg FIXME */
|
||||||
if (!dma_data)
|
if (!dma_data)
|
||||||
|
|||||||
@@ -103,10 +103,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
|
|||||||
ssp_disable(&priv->dev);
|
ssp_disable(&priv->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu_dai->dma_data) {
|
kfree(snd_soc_dai_get_dma_data(cpu_dai, substream));
|
||||||
kfree(cpu_dai->dma_data);
|
snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
|
||||||
cpu_dai->dma_data = NULL;
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,10 +121,8 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
|
|||||||
clk_disable(priv->dev.ssp->clk);
|
clk_disable(priv->dev.ssp->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu_dai->dma_data) {
|
kfree(snd_soc_dai_get_dma_data(cpu_dai, substream));
|
||||||
kfree(cpu_dai->dma_data);
|
snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
|
||||||
cpu_dai->dma_data = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
@@ -538,19 +535,23 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
|
|||||||
u32 sspsp;
|
u32 sspsp;
|
||||||
int width = snd_pcm_format_physical_width(params_format(params));
|
int width = snd_pcm_format_physical_width(params_format(params));
|
||||||
int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf;
|
int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf;
|
||||||
|
struct pxa2xx_pcm_dma_params *dma_data;
|
||||||
|
|
||||||
|
dma_data = snd_soc_dai_get_dma_data(dai, substream);
|
||||||
|
|
||||||
/* generate correct DMA params */
|
/* generate correct DMA params */
|
||||||
if (cpu_dai->dma_data)
|
kfree(dma_data);
|
||||||
kfree(cpu_dai->dma_data);
|
|
||||||
|
|
||||||
/* Network mode with one active slot (ttsa == 1) can be used
|
/* Network mode with one active slot (ttsa == 1) can be used
|
||||||
* to force 16-bit frame width on the wire (for S16_LE), even
|
* to force 16-bit frame width on the wire (for S16_LE), even
|
||||||
* with two channels. Use 16-bit DMA transfers for this case.
|
* with two channels. Use 16-bit DMA transfers for this case.
|
||||||
*/
|
*/
|
||||||
cpu_dai->dma_data = ssp_get_dma_params(ssp,
|
dma_data = ssp_get_dma_params(ssp,
|
||||||
((chn == 2) && (ttsa != 1)) || (width == 32),
|
((chn == 2) && (ttsa != 1)) || (width == 32),
|
||||||
substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
|
substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
|
||||||
|
|
||||||
|
snd_soc_dai_set_dma_data(dai, substream, dma_data);
|
||||||
|
|
||||||
/* we can only change the settings if the port is not in use */
|
/* we can only change the settings if the port is not in use */
|
||||||
if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
|
if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -122,11 +122,14 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
|
|||||||
{
|
{
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||||
|
struct pxa2xx_pcm_dma_params *dma_data;
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out;
|
dma_data = &pxa2xx_ac97_pcm_stereo_out;
|
||||||
else
|
else
|
||||||
cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_in;
|
dma_data = &pxa2xx_ac97_pcm_stereo_in;
|
||||||
|
|
||||||
|
snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -137,11 +140,14 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
|
|||||||
{
|
{
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||||
|
struct pxa2xx_pcm_dma_params *dma_data;
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
|
dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
|
||||||
else
|
else
|
||||||
cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_in;
|
dma_data = &pxa2xx_ac97_pcm_aux_mono_in;
|
||||||
|
|
||||||
|
snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -156,7 +162,8 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
|
|||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
else
|
else
|
||||||
cpu_dai->dma_data = &pxa2xx_ac97_pcm_mic_mono_in;
|
snd_soc_dai_set_dma_data(cpu_dai, substream,
|
||||||
|
&pxa2xx_ac97_pcm_mic_mono_in);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
|
|||||||
{
|
{
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||||
|
struct pxa2xx_pcm_dma_params *dma_data;
|
||||||
|
|
||||||
BUG_ON(IS_ERR(clk_i2s));
|
BUG_ON(IS_ERR(clk_i2s));
|
||||||
clk_enable(clk_i2s);
|
clk_enable(clk_i2s);
|
||||||
@@ -171,9 +172,11 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
|
|||||||
pxa_i2s_wait();
|
pxa_i2s_wait();
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out;
|
dma_data = &pxa2xx_i2s_pcm_stereo_out;
|
||||||
else
|
else
|
||||||
cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_in;
|
dma_data = &pxa2xx_i2s_pcm_stereo_in;
|
||||||
|
|
||||||
|
snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
|
||||||
|
|
||||||
/* is port used by another stream */
|
/* is port used by another stream */
|
||||||
if (!(SACR0 & SACR0_ENB)) {
|
if (!(SACR0 & SACR0_ENB)) {
|
||||||
|
|||||||
@@ -25,9 +25,11 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
struct pxa2xx_runtime_data *prtd = runtime->private_data;
|
struct pxa2xx_runtime_data *prtd = runtime->private_data;
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
|
struct pxa2xx_pcm_dma_params *dma;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
dma = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
|
||||||
|
|
||||||
/* return if this is a bufferless transfer e.g.
|
/* return if this is a bufferless transfer e.g.
|
||||||
* codec <--> BT codec or GSM modem -- lg FIXME */
|
* codec <--> BT codec or GSM modem -- lg FIXME */
|
||||||
if (!dma)
|
if (!dma)
|
||||||
|
|||||||
@@ -224,11 +224,14 @@ static int s3c_ac97_hw_params(struct snd_pcm_substream *substream,
|
|||||||
{
|
{
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
|
||||||
|
struct s3c_dma_params *dma_data;
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
cpu_dai->dma_data = &s3c_ac97_pcm_out;
|
dma_data = &s3c_ac97_pcm_out;
|
||||||
else
|
else
|
||||||
cpu_dai->dma_data = &s3c_ac97_pcm_in;
|
dma_data = &s3c_ac97_pcm_in;
|
||||||
|
|
||||||
|
snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -238,8 +241,8 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||||||
{
|
{
|
||||||
u32 ac_glbctrl;
|
u32 ac_glbctrl;
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
int channel = ((struct s3c_dma_params *)
|
struct s3c_dma_params *dma_data =
|
||||||
rtd->dai->cpu_dai->dma_data)->channel;
|
snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
|
||||||
|
|
||||||
ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
|
ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||||
@@ -265,7 +268,7 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||||||
|
|
||||||
writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
|
writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
|
||||||
|
|
||||||
s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
|
s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -280,7 +283,7 @@ static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream,
|
|||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
else
|
else
|
||||||
cpu_dai->dma_data = &s3c_ac97_mic_in;
|
snd_soc_dai_set_dma_data(cpu_dai, substream, &s3c_ac97_mic_in);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -290,8 +293,8 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
|
|||||||
{
|
{
|
||||||
u32 ac_glbctrl;
|
u32 ac_glbctrl;
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
int channel = ((struct s3c_dma_params *)
|
struct s3c_dma_params *dma_data =
|
||||||
rtd->dai->cpu_dai->dma_data)->channel;
|
snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
|
||||||
|
|
||||||
ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
|
ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
|
||||||
ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK;
|
ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK;
|
||||||
@@ -311,7 +314,7 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
|
writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
|
||||||
|
|
||||||
s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
|
s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,10 +145,12 @@ static int s3c_dma_hw_params(struct snd_pcm_substream *substream,
|
|||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
struct s3c24xx_runtime_data *prtd = runtime->private_data;
|
struct s3c24xx_runtime_data *prtd = runtime->private_data;
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct s3c_dma_params *dma = rtd->dai->cpu_dai->dma_data;
|
|
||||||
unsigned long totbytes = params_buffer_bytes(params);
|
unsigned long totbytes = params_buffer_bytes(params);
|
||||||
|
struct s3c_dma_params *dma =
|
||||||
|
snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
|
||||||
pr_debug("Entered %s\n", __func__);
|
pr_debug("Entered %s\n", __func__);
|
||||||
|
|
||||||
/* return if this is a bufferless transfer e.g.
|
/* return if this is a bufferless transfer e.g.
|
||||||
|
|||||||
@@ -333,14 +333,17 @@ static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream,
|
|||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct snd_soc_dai_link *dai = rtd->dai;
|
struct snd_soc_dai_link *dai = rtd->dai;
|
||||||
struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai);
|
struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai);
|
||||||
|
struct s3c_dma_params *dma_data;
|
||||||
u32 iismod;
|
u32 iismod;
|
||||||
|
|
||||||
pr_debug("Entered %s\n", __func__);
|
pr_debug("Entered %s\n", __func__);
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
dai->cpu_dai->dma_data = i2s->dma_playback;
|
dma_data = i2s->dma_playback;
|
||||||
else
|
else
|
||||||
dai->cpu_dai->dma_data = i2s->dma_capture;
|
dma_data = i2s->dma_capture;
|
||||||
|
|
||||||
|
snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data);
|
||||||
|
|
||||||
/* Working copies of register */
|
/* Working copies of register */
|
||||||
iismod = readl(i2s->regs + S3C2412_IISMOD);
|
iismod = readl(i2s->regs + S3C2412_IISMOD);
|
||||||
@@ -372,8 +375,8 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||||||
int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
|
int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
|
||||||
unsigned long irqs;
|
unsigned long irqs;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int channel = ((struct s3c_dma_params *)
|
struct s3c_dma_params *dma_data =
|
||||||
rtd->dai->cpu_dai->dma_data)->channel;
|
snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
|
||||||
|
|
||||||
pr_debug("Entered %s\n", __func__);
|
pr_debug("Entered %s\n", __func__);
|
||||||
|
|
||||||
@@ -409,7 +412,7 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||||||
* of the auto reload mechanism of S3C24XX.
|
* of the auto reload mechanism of S3C24XX.
|
||||||
* This call won't bother S3C64XX.
|
* This call won't bother S3C64XX.
|
||||||
*/
|
*/
|
||||||
s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
|
s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user