aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2009-12-18 12:48:50 -0500
committerTakashi Iwai <tiwai@suse.de>2009-12-18 14:31:13 -0500
commitd6a89fefa50feda5516cd5210ad0008a44632b52 (patch)
tree58d21a68c34ad2d85b1f3fc3b7eb3bc1c3009a89 /sound
parenta08d56583f6b87e2981d1b6e9ee891bdc741cc44 (diff)
ALSA: AACI: switch to per-pcm locking
We can use finer-grained locking, which makes things easier when we gain DMA support. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/arm/aaci.c49
-rw-r--r--sound/arm/aaci.h2
2 files changed, 30 insertions, 21 deletions
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index b377370af2d7..c5699863643b 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -172,14 +172,15 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
172 return v; 172 return v;
173} 173}
174 174
175static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun) 175static inline void
176aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask)
176{ 177{
177 u32 val; 178 u32 val;
178 int timeout = 5000; 179 int timeout = 5000;
179 180
180 do { 181 do {
181 val = readl(aacirun->base + AACI_SR); 182 val = readl(aacirun->base + AACI_SR);
182 } while (val & (SR_TXB|SR_RXB) && timeout--); 183 } while (val & mask && timeout--);
183} 184}
184 185
185 186
@@ -208,8 +209,10 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
208 writel(0, aacirun->base + AACI_IE); 209 writel(0, aacirun->base + AACI_IE);
209 return; 210 return;
210 } 211 }
211 ptr = aacirun->ptr;
212 212
213 spin_lock(&aacirun->lock);
214
215 ptr = aacirun->ptr;
213 do { 216 do {
214 unsigned int len = aacirun->fifosz; 217 unsigned int len = aacirun->fifosz;
215 u32 val; 218 u32 val;
@@ -217,9 +220,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
217 if (aacirun->bytes <= 0) { 220 if (aacirun->bytes <= 0) {
218 aacirun->bytes += aacirun->period; 221 aacirun->bytes += aacirun->period;
219 aacirun->ptr = ptr; 222 aacirun->ptr = ptr;
220 spin_unlock(&aaci->lock); 223 spin_unlock(&aacirun->lock);
221 snd_pcm_period_elapsed(aacirun->substream); 224 snd_pcm_period_elapsed(aacirun->substream);
222 spin_lock(&aaci->lock); 225 spin_lock(&aacirun->lock);
223 } 226 }
224 if (!(aacirun->cr & CR_EN)) 227 if (!(aacirun->cr & CR_EN))
225 break; 228 break;
@@ -245,7 +248,10 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
245 ptr = aacirun->start; 248 ptr = aacirun->start;
246 } 249 }
247 } while(1); 250 } while(1);
251
248 aacirun->ptr = ptr; 252 aacirun->ptr = ptr;
253
254 spin_unlock(&aacirun->lock);
249 } 255 }
250 256
251 if (mask & ISR_URINTR) { 257 if (mask & ISR_URINTR) {
@@ -263,6 +269,8 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
263 return; 269 return;
264 } 270 }
265 271
272 spin_lock(&aacirun->lock);
273
266 ptr = aacirun->ptr; 274 ptr = aacirun->ptr;
267 do { 275 do {
268 unsigned int len = aacirun->fifosz; 276 unsigned int len = aacirun->fifosz;
@@ -271,9 +279,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
271 if (aacirun->bytes <= 0) { 279 if (aacirun->bytes <= 0) {
272 aacirun->bytes += aacirun->period; 280 aacirun->bytes += aacirun->period;
273 aacirun->ptr = ptr; 281 aacirun->ptr = ptr;
274 spin_unlock(&aaci->lock); 282 spin_unlock(&aacirun->lock);
275 snd_pcm_period_elapsed(aacirun->substream); 283 snd_pcm_period_elapsed(aacirun->substream);
276 spin_lock(&aaci->lock); 284 spin_lock(&aacirun->lock);
277 } 285 }
278 if (!(aacirun->cr & CR_EN)) 286 if (!(aacirun->cr & CR_EN))
279 break; 287 break;
@@ -301,6 +309,8 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
301 } while (1); 309 } while (1);
302 310
303 aacirun->ptr = ptr; 311 aacirun->ptr = ptr;
312
313 spin_unlock(&aacirun->lock);
304 } 314 }
305} 315}
306 316
@@ -310,7 +320,6 @@ static irqreturn_t aaci_irq(int irq, void *devid)
310 u32 mask; 320 u32 mask;
311 int i; 321 int i;
312 322
313 spin_lock(&aaci->lock);
314 mask = readl(aaci->base + AACI_ALLINTS); 323 mask = readl(aaci->base + AACI_ALLINTS);
315 if (mask) { 324 if (mask) {
316 u32 m = mask; 325 u32 m = mask;
@@ -320,7 +329,6 @@ static irqreturn_t aaci_irq(int irq, void *devid)
320 } 329 }
321 } 330 }
322 } 331 }
323 spin_unlock(&aaci->lock);
324 332
325 return mask ? IRQ_HANDLED : IRQ_NONE; 333 return mask ? IRQ_HANDLED : IRQ_NONE;
326} 334}
@@ -580,7 +588,7 @@ static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
580 ie &= ~(IE_URIE|IE_TXIE); 588 ie &= ~(IE_URIE|IE_TXIE);
581 writel(ie, aacirun->base + AACI_IE); 589 writel(ie, aacirun->base + AACI_IE);
582 aacirun->cr &= ~CR_EN; 590 aacirun->cr &= ~CR_EN;
583 aaci_chan_wait_ready(aacirun); 591 aaci_chan_wait_ready(aacirun, SR_TXB);
584 writel(aacirun->cr, aacirun->base + AACI_TXCR); 592 writel(aacirun->cr, aacirun->base + AACI_TXCR);
585} 593}
586 594
@@ -588,7 +596,7 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
588{ 596{
589 u32 ie; 597 u32 ie;
590 598
591 aaci_chan_wait_ready(aacirun); 599 aaci_chan_wait_ready(aacirun, SR_TXB);
592 aacirun->cr |= CR_EN; 600 aacirun->cr |= CR_EN;
593 601
594 ie = readl(aacirun->base + AACI_IE); 602 ie = readl(aacirun->base + AACI_IE);
@@ -599,12 +607,12 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
599 607
600static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) 608static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
601{ 609{
602 struct aaci *aaci = substream->private_data;
603 struct aaci_runtime *aacirun = substream->runtime->private_data; 610 struct aaci_runtime *aacirun = substream->runtime->private_data;
604 unsigned long flags; 611 unsigned long flags;
605 int ret = 0; 612 int ret = 0;
606 613
607 spin_lock_irqsave(&aaci->lock, flags); 614 spin_lock_irqsave(&aacirun->lock, flags);
615
608 switch (cmd) { 616 switch (cmd) {
609 case SNDRV_PCM_TRIGGER_START: 617 case SNDRV_PCM_TRIGGER_START:
610 aaci_pcm_playback_start(aacirun); 618 aaci_pcm_playback_start(aacirun);
@@ -631,7 +639,8 @@ static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cm
631 default: 639 default:
632 ret = -EINVAL; 640 ret = -EINVAL;
633 } 641 }
634 spin_unlock_irqrestore(&aaci->lock, flags); 642
643 spin_unlock_irqrestore(&aacirun->lock, flags);
635 644
636 return ret; 645 return ret;
637} 646}
@@ -666,7 +675,7 @@ static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun)
666{ 675{
667 u32 ie; 676 u32 ie;
668 677
669 aaci_chan_wait_ready(aacirun); 678 aaci_chan_wait_ready(aacirun, SR_RXB);
670 679
671 ie = readl(aacirun->base + AACI_IE); 680 ie = readl(aacirun->base + AACI_IE);
672 ie &= ~(IE_ORIE | IE_RXIE); 681 ie &= ~(IE_ORIE | IE_RXIE);
@@ -681,7 +690,7 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)
681{ 690{
682 u32 ie; 691 u32 ie;
683 692
684 aaci_chan_wait_ready(aacirun); 693 aaci_chan_wait_ready(aacirun, SR_RXB);
685 694
686#ifdef DEBUG 695#ifdef DEBUG
687 /* RX Timeout value: bits 28:17 in RXCR */ 696 /* RX Timeout value: bits 28:17 in RXCR */
@@ -698,12 +707,11 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)
698 707
699static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) 708static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
700{ 709{
701 struct aaci *aaci = substream->private_data;
702 struct aaci_runtime *aacirun = substream->runtime->private_data; 710 struct aaci_runtime *aacirun = substream->runtime->private_data;
703 unsigned long flags; 711 unsigned long flags;
704 int ret = 0; 712 int ret = 0;
705 713
706 spin_lock_irqsave(&aaci->lock, flags); 714 spin_lock_irqsave(&aacirun->lock, flags);
707 715
708 switch (cmd) { 716 switch (cmd) {
709 case SNDRV_PCM_TRIGGER_START: 717 case SNDRV_PCM_TRIGGER_START:
@@ -732,7 +740,7 @@ static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd
732 ret = -EINVAL; 740 ret = -EINVAL;
733 } 741 }
734 742
735 spin_unlock_irqrestore(&aaci->lock, flags); 743 spin_unlock_irqrestore(&aacirun->lock, flags);
736 744
737 return ret; 745 return ret;
738} 746}
@@ -933,7 +941,6 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
933 941
934 aaci = card->private_data; 942 aaci = card->private_data;
935 mutex_init(&aaci->ac97_sem); 943 mutex_init(&aaci->ac97_sem);
936 spin_lock_init(&aaci->lock);
937 aaci->card = card; 944 aaci->card = card;
938 aaci->dev = dev; 945 aaci->dev = dev;
939 946
@@ -1020,12 +1027,14 @@ static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id)
1020 /* 1027 /*
1021 * Playback uses AACI channel 0 1028 * Playback uses AACI channel 0
1022 */ 1029 */
1030 spin_lock_init(&aaci->playback.lock);
1023 aaci->playback.base = aaci->base + AACI_CSCH1; 1031 aaci->playback.base = aaci->base + AACI_CSCH1;
1024 aaci->playback.fifo = aaci->base + AACI_DR1; 1032 aaci->playback.fifo = aaci->base + AACI_DR1;
1025 1033
1026 /* 1034 /*
1027 * Capture uses AACI channel 0 1035 * Capture uses AACI channel 0
1028 */ 1036 */
1037 spin_lock_init(&aaci->capture.lock);
1029 aaci->capture.base = aaci->base + AACI_CSCH1; 1038 aaci->capture.base = aaci->base + AACI_CSCH1;
1030 aaci->capture.fifo = aaci->base + AACI_DR1; 1039 aaci->capture.fifo = aaci->base + AACI_DR1;
1031 1040
diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h
index 924f69c1c44c..6a4a2eebdda1 100644
--- a/sound/arm/aaci.h
+++ b/sound/arm/aaci.h
@@ -202,6 +202,7 @@
202struct aaci_runtime { 202struct aaci_runtime {
203 void __iomem *base; 203 void __iomem *base;
204 void __iomem *fifo; 204 void __iomem *fifo;
205 spinlock_t lock;
205 206
206 struct ac97_pcm *pcm; 207 struct ac97_pcm *pcm;
207 int pcm_open; 208 int pcm_open;
@@ -232,7 +233,6 @@ struct aaci {
232 struct snd_ac97 *ac97; 233 struct snd_ac97 *ac97;
233 234
234 u32 maincr; 235 u32 maincr;
235 spinlock_t lock;
236 236
237 struct aaci_runtime playback; 237 struct aaci_runtime playback;
238 struct aaci_runtime capture; 238 struct aaci_runtime capture;