summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c53
1 files changed, 17 insertions, 36 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
index 76789a7dbd..7304bdcff3 100644
--- a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
@@ -104,7 +104,7 @@ static void play_dma_callback(void)
104 PCM_DMAST_ERR_DMA : PCM_DMAST_OK; 104 PCM_DMAST_ERR_DMA : PCM_DMAST_OK;
105 const void *addr; 105 const void *addr;
106 size_t size; 106 size_t size;
107 107
108 if (pcm_play_dma_complete_callback(status, &addr, &size)) 108 if (pcm_play_dma_complete_callback(status, &addr, &size))
109 { 109 {
110 play_start_dma(addr, size); 110 play_start_dma(addr, size);
@@ -114,33 +114,20 @@ static void play_dma_callback(void)
114 114
115void pcm_play_lock(void) 115void pcm_play_lock(void)
116{ 116{
117 /* Need to prevent DVFS from causing interrupt priority inversion if audio
118 * is locked and a DVFS interrupt fires, blocking reenabling of audio by a
119 * low-priority mode for at least the duration of the lengthy DVFS routine.
120 * Not really an issue with state changes but lockout when playing.
121 *
122 * Keep direct use of DVFS code away from here though. This could provide
123 * more services in the future anyway. */
124 kernel_audio_locking(true);
125 ++dma_play_data.locked; 117 ++dma_play_data.locked;
126} 118}
127 119
128void pcm_play_unlock(void) 120void pcm_play_unlock(void)
129{ 121{
130 if (--dma_play_data.locked == 0) 122 if (--dma_play_data.locked == 0 && dma_play_data.state != 0)
131 { 123 {
132 if (dma_play_data.state != 0) 124 int oldstatus = disable_irq_save();
133 { 125 int pending = dma_play_data.callback_pending;
134 int oldstatus = disable_irq_save(); 126 dma_play_data.callback_pending = 0;
135 int pending = dma_play_data.callback_pending; 127 restore_irq(oldstatus);
136 dma_play_data.callback_pending = 0; 128
137 restore_irq(oldstatus); 129 if (pending != 0)
138 130 play_dma_callback();
139 if (pending != 0)
140 play_dma_callback();
141 }
142
143 kernel_audio_locking(false);
144 } 131 }
145} 132}
146 133
@@ -368,26 +355,20 @@ static void rec_dma_callback(void)
368 355
369void pcm_rec_lock(void) 356void pcm_rec_lock(void)
370{ 357{
371 kernel_audio_locking(true);
372 ++dma_rec_data.locked; 358 ++dma_rec_data.locked;
373} 359}
374 360
375void pcm_rec_unlock(void) 361void pcm_rec_unlock(void)
376{ 362{
377 if (--dma_rec_data.locked == 0) 363 if (--dma_rec_data.locked == 0 && dma_rec_data.state != 0)
378 { 364 {
379 if (dma_rec_data.state != 0) 365 int oldstatus = disable_irq_save();
380 { 366 int pending = dma_rec_data.callback_pending;
381 int oldstatus = disable_irq_save(); 367 dma_rec_data.callback_pending = 0;
382 int pending = dma_rec_data.callback_pending; 368 restore_irq(oldstatus);
383 dma_rec_data.callback_pending = 0; 369
384 restore_irq(oldstatus); 370 if (pending != 0)
385 371 rec_dma_callback();
386 if (pending != 0)
387 rec_dma_callback();
388 }
389
390 kernel_audio_locking(false);
391 } 372 }
392} 373}
393 374