|
@@ -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) {
|