aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/omap/omap-mcbsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/omap/omap-mcbsp.c')
-rw-r--r--sound/soc/omap/omap-mcbsp.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 6e855080e6e..580de5a8dba 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -139,28 +139,59 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {
static const unsigned long omap34xx_mcbsp_port[][2] = {};
#endif
+static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+ int samples = snd_pcm_lib_period_bytes(substream) >> 1;
+
+ /* Configure McBSP internal buffer usage */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, samples - 1);
+ else
+ omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, samples - 1);
+}
+
static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+ int bus_id = mcbsp_data->bus_id;
int err = 0;
- if (cpu_is_omap343x() && mcbsp_data->bus_id == 1) {
+ if (!cpu_dai->active)
+ err = omap_mcbsp_request(bus_id);
+
+ if (cpu_is_omap343x()) {
+ int max_period;
+
/*
* McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer.
* Set constraint for minimum buffer size to the same than FIFO
* size in order to avoid underruns in playback startup because
* HW is keeping the DMA request active until FIFO is filled.
*/
+ if (bus_id == 1)
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ 4096, UINT_MAX);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ max_period = omap_mcbsp_get_max_tx_threshold(bus_id);
+ else
+ max_period = omap_mcbsp_get_max_rx_threshold(bus_id);
+
+ max_period++;
+ max_period <<= 1;
+
snd_pcm_hw_constraint_minmax(substream->runtime,
- SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4096, UINT_MAX);
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+ 32, max_period);
}
- if (!cpu_dai->active)
- err = omap_mcbsp_request(mcbsp_data->bus_id);
-
return err;
}
@@ -220,7 +251,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
- int wlen, channels, wpf;
+ int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
unsigned long port;
unsigned int format;
@@ -236,6 +267,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
} else if (cpu_is_omap343x()) {
dma = omap24xx_dma_reqs[bus_id][substream->stream];
port = omap34xx_mcbsp_port[bus_id][substream->stream];
+ omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold =
+ omap_mcbsp_set_threshold;
+ sync_mode = OMAP_DMA_SYNC_FRAME;
} else {
return -ENODEV;
}
@@ -243,6 +277,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
substream->stream ? "Audio Capture" : "Audio Playback";
omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
+ omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
if (mcbsp_data->configured) {