aboutsummaryrefslogtreecommitdiffstats
path: root/sound/drivers/aloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/drivers/aloop.c')
-rw-r--r--sound/drivers/aloop.c52
1 files changed, 27 insertions, 25 deletions
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 0fe6d64ff840..3d822328d383 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -120,7 +120,6 @@ struct loopback_pcm {
120 unsigned int last_drift; 120 unsigned int last_drift;
121 unsigned long last_jiffies; 121 unsigned long last_jiffies;
122 struct timer_list timer; 122 struct timer_list timer;
123 spinlock_t timer_lock;
124}; 123};
125 124
126static struct platform_device *devices[SNDRV_CARDS]; 125static struct platform_device *devices[SNDRV_CARDS];
@@ -166,12 +165,12 @@ static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm)
166 return get_setup(dpcm)->rate_shift; 165 return get_setup(dpcm)->rate_shift;
167} 166}
168 167
168/* call in cable->lock */
169static void loopback_timer_start(struct loopback_pcm *dpcm) 169static void loopback_timer_start(struct loopback_pcm *dpcm)
170{ 170{
171 unsigned long tick; 171 unsigned long tick;
172 unsigned int rate_shift = get_rate_shift(dpcm); 172 unsigned int rate_shift = get_rate_shift(dpcm);
173 173
174 spin_lock(&dpcm->timer_lock);
175 if (rate_shift != dpcm->pcm_rate_shift) { 174 if (rate_shift != dpcm->pcm_rate_shift) {
176 dpcm->pcm_rate_shift = rate_shift; 175 dpcm->pcm_rate_shift = rate_shift;
177 dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size); 176 dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size);
@@ -184,15 +183,13 @@ static void loopback_timer_start(struct loopback_pcm *dpcm)
184 tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; 183 tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
185 dpcm->timer.expires = jiffies + tick; 184 dpcm->timer.expires = jiffies + tick;
186 add_timer(&dpcm->timer); 185 add_timer(&dpcm->timer);
187 spin_unlock(&dpcm->timer_lock);
188} 186}
189 187
188/* call in cable->lock */
190static inline void loopback_timer_stop(struct loopback_pcm *dpcm) 189static inline void loopback_timer_stop(struct loopback_pcm *dpcm)
191{ 190{
192 spin_lock(&dpcm->timer_lock);
193 del_timer(&dpcm->timer); 191 del_timer(&dpcm->timer);
194 dpcm->timer.expires = 0; 192 dpcm->timer.expires = 0;
195 spin_unlock(&dpcm->timer_lock);
196} 193}
197 194
198#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) 195#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK)
@@ -274,8 +271,8 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
274 spin_lock(&cable->lock); 271 spin_lock(&cable->lock);
275 cable->running |= stream; 272 cable->running |= stream;
276 cable->pause &= ~stream; 273 cable->pause &= ~stream;
277 spin_unlock(&cable->lock);
278 loopback_timer_start(dpcm); 274 loopback_timer_start(dpcm);
275 spin_unlock(&cable->lock);
279 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 276 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
280 loopback_active_notify(dpcm); 277 loopback_active_notify(dpcm);
281 break; 278 break;
@@ -283,23 +280,23 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
283 spin_lock(&cable->lock); 280 spin_lock(&cable->lock);
284 cable->running &= ~stream; 281 cable->running &= ~stream;
285 cable->pause &= ~stream; 282 cable->pause &= ~stream;
286 spin_unlock(&cable->lock);
287 loopback_timer_stop(dpcm); 283 loopback_timer_stop(dpcm);
284 spin_unlock(&cable->lock);
288 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 285 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
289 loopback_active_notify(dpcm); 286 loopback_active_notify(dpcm);
290 break; 287 break;
291 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 288 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
292 spin_lock(&cable->lock); 289 spin_lock(&cable->lock);
293 cable->pause |= stream; 290 cable->pause |= stream;
294 spin_unlock(&cable->lock);
295 loopback_timer_stop(dpcm); 291 loopback_timer_stop(dpcm);
292 spin_unlock(&cable->lock);
296 break; 293 break;
297 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 294 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
298 spin_lock(&cable->lock); 295 spin_lock(&cable->lock);
299 dpcm->last_jiffies = jiffies; 296 dpcm->last_jiffies = jiffies;
300 cable->pause &= ~stream; 297 cable->pause &= ~stream;
301 spin_unlock(&cable->lock);
302 loopback_timer_start(dpcm); 298 loopback_timer_start(dpcm);
299 spin_unlock(&cable->lock);
303 break; 300 break;
304 default: 301 default:
305 return -EINVAL; 302 return -EINVAL;
@@ -477,6 +474,7 @@ static inline void bytepos_finish(struct loopback_pcm *dpcm,
477 dpcm->buf_pos %= dpcm->pcm_buffer_size; 474 dpcm->buf_pos %= dpcm->pcm_buffer_size;
478} 475}
479 476
477/* call in cable->lock */
480static unsigned int loopback_pos_update(struct loopback_cable *cable) 478static unsigned int loopback_pos_update(struct loopback_cable *cable)
481{ 479{
482 struct loopback_pcm *dpcm_play = 480 struct loopback_pcm *dpcm_play =
@@ -485,9 +483,7 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
485 cable->streams[SNDRV_PCM_STREAM_CAPTURE]; 483 cable->streams[SNDRV_PCM_STREAM_CAPTURE];
486 unsigned long delta_play = 0, delta_capt = 0; 484 unsigned long delta_play = 0, delta_capt = 0;
487 unsigned int running, count1, count2; 485 unsigned int running, count1, count2;
488 unsigned long flags;
489 486
490 spin_lock_irqsave(&cable->lock, flags);
491 running = cable->running ^ cable->pause; 487 running = cable->running ^ cable->pause;
492 if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { 488 if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
493 delta_play = jiffies - dpcm_play->last_jiffies; 489 delta_play = jiffies - dpcm_play->last_jiffies;
@@ -529,32 +525,39 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
529 bytepos_finish(dpcm_play, count1); 525 bytepos_finish(dpcm_play, count1);
530 bytepos_finish(dpcm_capt, count1); 526 bytepos_finish(dpcm_capt, count1);
531 unlock: 527 unlock:
532 spin_unlock_irqrestore(&cable->lock, flags);
533 return running; 528 return running;
534} 529}
535 530
536static void loopback_timer_function(unsigned long data) 531static void loopback_timer_function(unsigned long data)
537{ 532{
538 struct loopback_pcm *dpcm = (struct loopback_pcm *)data; 533 struct loopback_pcm *dpcm = (struct loopback_pcm *)data;
539 unsigned int running; 534 unsigned long flags;
540 535
541 running = loopback_pos_update(dpcm->cable); 536 spin_lock_irqsave(&dpcm->cable->lock, flags);
542 if (running & (1 << dpcm->substream->stream)) { 537 if (loopback_pos_update(dpcm->cable) & (1 << dpcm->substream->stream)) {
543 loopback_timer_start(dpcm); 538 loopback_timer_start(dpcm);
544 if (dpcm->period_update_pending) { 539 if (dpcm->period_update_pending) {
545 dpcm->period_update_pending = 0; 540 dpcm->period_update_pending = 0;
541 spin_unlock_irqrestore(&dpcm->cable->lock, flags);
542 /* need to unlock before calling below */
546 snd_pcm_period_elapsed(dpcm->substream); 543 snd_pcm_period_elapsed(dpcm->substream);
544 return;
547 } 545 }
548 } 546 }
547 spin_unlock_irqrestore(&dpcm->cable->lock, flags);
549} 548}
550 549
551static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) 550static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream)
552{ 551{
553 struct snd_pcm_runtime *runtime = substream->runtime; 552 struct snd_pcm_runtime *runtime = substream->runtime;
554 struct loopback_pcm *dpcm = runtime->private_data; 553 struct loopback_pcm *dpcm = runtime->private_data;
554 snd_pcm_uframes_t pos;
555 555
556 spin_lock(&dpcm->cable->lock);
556 loopback_pos_update(dpcm->cable); 557 loopback_pos_update(dpcm->cable);
557 return bytes_to_frames(runtime, dpcm->buf_pos); 558 pos = dpcm->buf_pos;
559 spin_unlock(&dpcm->cable->lock);
560 return bytes_to_frames(runtime, pos);
558} 561}
559 562
560static struct snd_pcm_hardware loopback_pcm_hardware = 563static struct snd_pcm_hardware loopback_pcm_hardware =
@@ -672,7 +675,6 @@ static int loopback_open(struct snd_pcm_substream *substream)
672 dpcm->substream = substream; 675 dpcm->substream = substream;
673 setup_timer(&dpcm->timer, loopback_timer_function, 676 setup_timer(&dpcm->timer, loopback_timer_function,
674 (unsigned long)dpcm); 677 (unsigned long)dpcm);
675 spin_lock_init(&dpcm->timer_lock);
676 678
677 cable = loopback->cables[substream->number][dev]; 679 cable = loopback->cables[substream->number][dev];
678 if (!cable) { 680 if (!cable) {
@@ -772,8 +774,8 @@ static struct snd_pcm_ops loopback_capture_ops = {
772 .mmap = snd_pcm_lib_mmap_vmalloc, 774 .mmap = snd_pcm_lib_mmap_vmalloc,
773}; 775};
774 776
775static int __devinit loopback_pcm_new(struct loopback *loopback, 777static int loopback_pcm_new(struct loopback *loopback,
776 int device, int substreams) 778 int device, int substreams)
777{ 779{
778 struct snd_pcm *pcm; 780 struct snd_pcm *pcm;
779 int err; 781 int err;
@@ -947,7 +949,7 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol,
947 return 0; 949 return 0;
948} 950}
949 951
950static struct snd_kcontrol_new loopback_controls[] __devinitdata = { 952static struct snd_kcontrol_new loopback_controls[] = {
951{ 953{
952 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 954 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
953 .name = "PCM Rate Shift 100000", 955 .name = "PCM Rate Shift 100000",
@@ -996,7 +998,7 @@ static struct snd_kcontrol_new loopback_controls[] __devinitdata = {
996} 998}
997}; 999};
998 1000
999static int __devinit loopback_mixer_new(struct loopback *loopback, int notify) 1001static int loopback_mixer_new(struct loopback *loopback, int notify)
1000{ 1002{
1001 struct snd_card *card = loopback->card; 1003 struct snd_card *card = loopback->card;
1002 struct snd_pcm *pcm; 1004 struct snd_pcm *pcm;
@@ -1109,7 +1111,7 @@ static void print_cable_info(struct snd_info_entry *entry,
1109 mutex_unlock(&loopback->cable_lock); 1111 mutex_unlock(&loopback->cable_lock);
1110} 1112}
1111 1113
1112static int __devinit loopback_proc_new(struct loopback *loopback, int cidx) 1114static int loopback_proc_new(struct loopback *loopback, int cidx)
1113{ 1115{
1114 char name[32]; 1116 char name[32];
1115 struct snd_info_entry *entry; 1117 struct snd_info_entry *entry;
@@ -1130,7 +1132,7 @@ static int __devinit loopback_proc_new(struct loopback *loopback, int cidx)
1130 1132
1131#endif 1133#endif
1132 1134
1133static int __devinit loopback_probe(struct platform_device *devptr) 1135static int loopback_probe(struct platform_device *devptr)
1134{ 1136{
1135 struct snd_card *card; 1137 struct snd_card *card;
1136 struct loopback *loopback; 1138 struct loopback *loopback;
@@ -1175,7 +1177,7 @@ static int __devinit loopback_probe(struct platform_device *devptr)
1175 return err; 1177 return err;
1176} 1178}
1177 1179
1178static int __devexit loopback_remove(struct platform_device *devptr) 1180static int loopback_remove(struct platform_device *devptr)
1179{ 1181{
1180 snd_card_free(platform_get_drvdata(devptr)); 1182 snd_card_free(platform_get_drvdata(devptr));
1181 platform_set_drvdata(devptr, NULL); 1183 platform_set_drvdata(devptr, NULL);
@@ -1213,7 +1215,7 @@ static SIMPLE_DEV_PM_OPS(loopback_pm, loopback_suspend, loopback_resume);
1213 1215
1214static struct platform_driver loopback_driver = { 1216static struct platform_driver loopback_driver = {
1215 .probe = loopback_probe, 1217 .probe = loopback_probe,
1216 .remove = __devexit_p(loopback_remove), 1218 .remove = loopback_remove,
1217 .driver = { 1219 .driver = {
1218 .name = SND_LOOPBACK_DRIVER, 1220 .name = SND_LOOPBACK_DRIVER,
1219 .owner = THIS_MODULE, 1221 .owner = THIS_MODULE,