X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=sound%2Fsoc%2Fomap%2Fomap-pcm.c;h=b411eb460d02b61fdb32a33e6920ca78da5bda64;hb=d3ef3adfa;hp=690bfeaec4a0ee3b157b0ccb7a7ea1a1ea5e4189;hpb=b0e0c9e7f6d5764633e93944dafd896dd6097318;p=pandora-kernel.git diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 690bfeaec4a0..b411eb460d02 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -97,7 +97,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, prtd->dma_data = dma_data; err = omap_request_dma(dma_data->dma_req, dma_data->name, omap_pcm_dma_irq, substream, &prtd->dma_ch); - if (!cpu_is_omap1510()) { + if (!err & !cpu_is_omap1510()) { /* * Link channel with itself so DMA doesn't need any * reprogramming while looping the buffer @@ -147,12 +147,14 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) dma_params.src_or_dst_synch = OMAP_DMA_DST_SYNC; dma_params.src_start = runtime->dma_addr; dma_params.dst_start = dma_data->port_addr; + dma_params.dst_port = OMAP_DMA_PORT_MPUI; } else { dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT; dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC; dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC; dma_params.src_start = dma_data->port_addr; dma_params.dst_start = runtime->dma_addr; + dma_params.src_port = OMAP_DMA_PORT_MPUI; } /* * Set DMA transfer frame size equal to ALSA period size and frame @@ -166,6 +168,31 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ); + /* + * To handle realtime streaming sources properly, we need to be sure + * we have at least 2 periods of size larger than FIFO in the buffer + * to start playing without underflowing. This is because DMA is always + * ahead of playback by amount close to FIFO size and needs to have + * next period ready when previous one finishes transfering to FIFO. + */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && + runtime->periods > 1) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + int *mcbsp_bus_id = rtd->dai->cpu_dai->private_data; + int fifo_samples = (*mcbsp_bus_id == 1) ? 1024 : 256; + int period_samples, period_frames; + + period_samples = bytes_to_samples(runtime, + snd_pcm_lib_period_bytes(substream)); + if (period_samples < fifo_samples + runtime->channels) + period_samples = fifo_samples + runtime->channels; + period_frames = bytes_to_frames(runtime, + samples_to_bytes(runtime, period_samples)) * 2; + + if (runtime->start_threshold < period_frames) + runtime->start_threshold = period_frames; + } + return 0; } @@ -231,7 +258,7 @@ static int omap_pcm_open(struct snd_pcm_substream *substream) if (ret < 0) goto out; - prtd = kzalloc(sizeof(prtd), GFP_KERNEL); + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); if (prtd == NULL) { ret = -ENOMEM; goto out;