diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-01-07 20:40:36 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-01-07 20:40:36 +0000 |
commit | 9d97ee1b5401698ede224888028ca64f399fdae1 (patch) | |
tree | 54aa01c9027866ca81a11e756ab1c77913c459bd /firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c | |
parent | 2093bb021f357913ff9280c7d4e21568e3fc4575 (diff) | |
download | rockbox-9d97ee1b5401698ede224888028ca64f399fdae1.tar.gz rockbox-9d97ee1b5401698ede224888028ca64f399fdae1.zip |
Gigabeat S/i.MX31: Take care of an interrupt priority inversion that can happen during PCM callback lockout when DVFS switches frequecies during the lockout, preventing a thread from unlocking the callback until DVFS finishes, causing an SSI FIFO underrun. Hadn't thought of an acceptable way to deal with it before.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28996 a1c6a512-1295-4272-9138-f99709370657
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.c | 51 |
1 files changed, 35 insertions, 16 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 50c7da943e..c8c1283d12 100644 --- a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c | |||
@@ -109,20 +109,33 @@ static void play_dma_callback(void) | |||
109 | 109 | ||
110 | void pcm_play_lock(void) | 110 | void pcm_play_lock(void) |
111 | { | 111 | { |
112 | /* Need to prevent DVFS from causing interrupt priority inversion if audio | ||
113 | * is locked and a DVFS interrupt fires, blocking reenabling of audio by a | ||
114 | * low-priority mode for at least the duration of the lengthy DVFS routine. | ||
115 | * Not really an issue with state changes but lockout when playing. | ||
116 | * | ||
117 | * Keep direct use of DVFS code away from here though. This could provide | ||
118 | * more services in the future anyway. */ | ||
119 | kernel_audio_locking(true); | ||
112 | ++dma_play_data.locked; | 120 | ++dma_play_data.locked; |
113 | } | 121 | } |
114 | 122 | ||
115 | void pcm_play_unlock(void) | 123 | void pcm_play_unlock(void) |
116 | { | 124 | { |
117 | if (--dma_play_data.locked == 0 && dma_play_data.state != 0) | 125 | if (--dma_play_data.locked == 0) |
118 | { | 126 | { |
119 | int oldstatus = disable_irq_save(); | 127 | if (dma_play_data.state != 0) |
120 | int pending = dma_play_data.callback_pending; | 128 | { |
121 | dma_play_data.callback_pending = 0; | 129 | int oldstatus = disable_irq_save(); |
122 | restore_irq(oldstatus); | 130 | int pending = dma_play_data.callback_pending; |
123 | 131 | dma_play_data.callback_pending = 0; | |
124 | if (pending != 0) | 132 | restore_irq(oldstatus); |
125 | play_dma_callback(); | 133 | |
134 | if (pending != 0) | ||
135 | play_dma_callback(); | ||
136 | } | ||
137 | |||
138 | kernel_audio_locking(false); | ||
126 | } | 139 | } |
127 | } | 140 | } |
128 | 141 | ||
@@ -442,20 +455,26 @@ static void rec_dma_callback(void) | |||
442 | 455 | ||
443 | void pcm_rec_lock(void) | 456 | void pcm_rec_lock(void) |
444 | { | 457 | { |
458 | kernel_audio_locking(true); | ||
445 | ++dma_rec_data.locked; | 459 | ++dma_rec_data.locked; |
446 | } | 460 | } |
447 | 461 | ||
448 | void pcm_rec_unlock(void) | 462 | void pcm_rec_unlock(void) |
449 | { | 463 | { |
450 | if (--dma_rec_data.locked == 0 && dma_rec_data.state != 0) | 464 | if (--dma_rec_data.locked == 0) |
451 | { | 465 | { |
452 | int oldstatus = disable_irq_save(); | 466 | if (dma_rec_data.state != 0) |
453 | int pending = dma_rec_data.callback_pending; | 467 | { |
454 | dma_rec_data.callback_pending = 0; | 468 | int oldstatus = disable_irq_save(); |
455 | restore_irq(oldstatus); | 469 | int pending = dma_rec_data.callback_pending; |
456 | 470 | dma_rec_data.callback_pending = 0; | |
457 | if (pending != 0) | 471 | restore_irq(oldstatus); |
458 | rec_dma_callback(); | 472 | |
473 | if (pending != 0) | ||
474 | rec_dma_callback(); | ||
475 | } | ||
476 | |||
477 | kernel_audio_locking(false); | ||
459 | } | 478 | } |
460 | } | 479 | } |
461 | 480 | ||