aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/omap/omap-pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/omap/omap-pcm.c')
-rw-r--r--sound/soc/omap/omap-pcm.c53
1 files changed, 40 insertions, 13 deletions
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 84a1950880eb..5735945788bf 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -59,16 +59,31 @@ static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
59 struct omap_runtime_data *prtd = runtime->private_data; 59 struct omap_runtime_data *prtd = runtime->private_data;
60 unsigned long flags; 60 unsigned long flags;
61 61
62 if (cpu_is_omap1510()) { 62 if ((cpu_is_omap1510()) &&
63 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) {
63 /* 64 /*
64 * OMAP1510 doesn't support DMA chaining so have to restart 65 * OMAP1510 doesn't fully support DMA progress counter
65 * the transfer after all periods are transferred 66 * and there is no software emulation implemented yet,
67 * so have to maintain our own playback progress counter
68 * that can be used by omap_pcm_pointer() instead.
66 */ 69 */
67 spin_lock_irqsave(&prtd->lock, flags); 70 spin_lock_irqsave(&prtd->lock, flags);
71 if ((stat == OMAP_DMA_LAST_IRQ) &&
72 (prtd->period_index == runtime->periods - 1)) {
73 /* we are in sync, do nothing */
74 spin_unlock_irqrestore(&prtd->lock, flags);
75 return;
76 }
68 if (prtd->period_index >= 0) { 77 if (prtd->period_index >= 0) {
69 if (++prtd->period_index == runtime->periods) { 78 if (stat & OMAP_DMA_BLOCK_IRQ) {
79 /* end of buffer reached, loop back */
80 prtd->period_index = 0;
81 } else if (stat & OMAP_DMA_LAST_IRQ) {
82 /* update the counter for the last period */
83 prtd->period_index = runtime->periods - 1;
84 } else if (++prtd->period_index >= runtime->periods) {
85 /* end of buffer missed? loop back */
70 prtd->period_index = 0; 86 prtd->period_index = 0;
71 omap_start_dma(prtd->dma_ch);
72 } 87 }
73 } 88 }
74 spin_unlock_irqrestore(&prtd->lock, flags); 89 spin_unlock_irqrestore(&prtd->lock, flags);
@@ -100,7 +115,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
100 prtd->dma_data = dma_data; 115 prtd->dma_data = dma_data;
101 err = omap_request_dma(dma_data->dma_req, dma_data->name, 116 err = omap_request_dma(dma_data->dma_req, dma_data->name,
102 omap_pcm_dma_irq, substream, &prtd->dma_ch); 117 omap_pcm_dma_irq, substream, &prtd->dma_ch);
103 if (!err && !cpu_is_omap1510()) { 118 if (!err) {
104 /* 119 /*
105 * Link channel with itself so DMA doesn't need any 120 * Link channel with itself so DMA doesn't need any
106 * reprogramming while looping the buffer 121 * reprogramming while looping the buffer
@@ -119,8 +134,7 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream)
119 if (prtd->dma_data == NULL) 134 if (prtd->dma_data == NULL)
120 return 0; 135 return 0;
121 136
122 if (!cpu_is_omap1510()) 137 omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch);
123 omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch);
124 omap_free_dma(prtd->dma_ch); 138 omap_free_dma(prtd->dma_ch);
125 prtd->dma_data = NULL; 139 prtd->dma_data = NULL;
126 140
@@ -148,7 +162,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
148 */ 162 */
149 dma_params.data_type = OMAP_DMA_DATA_TYPE_S16; 163 dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
150 dma_params.trigger = dma_data->dma_req; 164 dma_params.trigger = dma_data->dma_req;
151 dma_params.sync_mode = OMAP_DMA_SYNC_ELEMENT; 165 dma_params.sync_mode = dma_data->sync_mode;
152 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 166 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
153 dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; 167 dma_params.src_amode = OMAP_DMA_AMODE_POST_INC;
154 dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT; 168 dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT;
@@ -174,7 +188,15 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
174 dma_params.frame_count = runtime->periods; 188 dma_params.frame_count = runtime->periods;
175 omap_set_dma_params(prtd->dma_ch, &dma_params); 189 omap_set_dma_params(prtd->dma_ch, &dma_params);
176 190
177 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ); 191 if ((cpu_is_omap1510()) &&
192 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
193 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ |
194 OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
195 else
196 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
197
198 omap_set_dma_src_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16);
199 omap_set_dma_dest_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16);
178 200
179 return 0; 201 return 0;
180} 202}
@@ -183,6 +205,7 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
183{ 205{
184 struct snd_pcm_runtime *runtime = substream->runtime; 206 struct snd_pcm_runtime *runtime = substream->runtime;
185 struct omap_runtime_data *prtd = runtime->private_data; 207 struct omap_runtime_data *prtd = runtime->private_data;
208 struct omap_pcm_dma_data *dma_data = prtd->dma_data;
186 unsigned long flags; 209 unsigned long flags;
187 int ret = 0; 210 int ret = 0;
188 211
@@ -192,6 +215,10 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
192 case SNDRV_PCM_TRIGGER_RESUME: 215 case SNDRV_PCM_TRIGGER_RESUME:
193 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 216 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
194 prtd->period_index = 0; 217 prtd->period_index = 0;
218 /* Configure McBSP internal buffer usage */
219 if (dma_data->set_threshold)
220 dma_data->set_threshold(substream);
221
195 omap_start_dma(prtd->dma_ch); 222 omap_start_dma(prtd->dma_ch);
196 break; 223 break;
197 224
@@ -288,7 +315,7 @@ static struct snd_pcm_ops omap_pcm_ops = {
288 .mmap = omap_pcm_mmap, 315 .mmap = omap_pcm_mmap,
289}; 316};
290 317
291static u64 omap_pcm_dmamask = DMA_BIT_MASK(32); 318static u64 omap_pcm_dmamask = DMA_BIT_MASK(64);
292 319
293static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, 320static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
294 int stream) 321 int stream)
@@ -330,7 +357,7 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm)
330 } 357 }
331} 358}
332 359
333int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, 360static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
334 struct snd_pcm *pcm) 361 struct snd_pcm *pcm)
335{ 362{
336 int ret = 0; 363 int ret = 0;
@@ -338,7 +365,7 @@ int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
338 if (!card->dev->dma_mask) 365 if (!card->dev->dma_mask)
339 card->dev->dma_mask = &omap_pcm_dmamask; 366 card->dev->dma_mask = &omap_pcm_dmamask;
340 if (!card->dev->coherent_dma_mask) 367 if (!card->dev->coherent_dma_mask)
341 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 368 card->dev->coherent_dma_mask = DMA_BIT_MASK(64);
342 369
343 if (dai->playback.channels_min) { 370 if (dai->playback.channels_min) {
344 ret = omap_pcm_preallocate_dma_buffer(pcm, 371 ret = omap_pcm_preallocate_dma_buffer(pcm,