aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/timer.c')
-rw-r--r--sound/core/timer.c268
1 files changed, 123 insertions, 145 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c
index dca817fc7894..aa1b15c155d1 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -305,8 +305,6 @@ int snd_timer_open(struct snd_timer_instance **ti,
305 return 0; 305 return 0;
306} 306}
307 307
308static int _snd_timer_stop(struct snd_timer_instance *timeri, int event);
309
310/* 308/*
311 * close a timer instance 309 * close a timer instance
312 */ 310 */
@@ -318,25 +316,14 @@ int snd_timer_close(struct snd_timer_instance *timeri)
318 if (snd_BUG_ON(!timeri)) 316 if (snd_BUG_ON(!timeri))
319 return -ENXIO; 317 return -ENXIO;
320 318
319 mutex_lock(&register_mutex);
320 list_del(&timeri->open_list);
321
321 /* force to stop the timer */ 322 /* force to stop the timer */
322 snd_timer_stop(timeri); 323 snd_timer_stop(timeri);
323 324
324 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { 325 timer = timeri->timer;
325 /* wait, until the active callback is finished */ 326 if (timer) {
326 spin_lock_irq(&slave_active_lock);
327 while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
328 spin_unlock_irq(&slave_active_lock);
329 udelay(10);
330 spin_lock_irq(&slave_active_lock);
331 }
332 spin_unlock_irq(&slave_active_lock);
333 mutex_lock(&register_mutex);
334 list_del(&timeri->open_list);
335 mutex_unlock(&register_mutex);
336 } else {
337 timer = timeri->timer;
338 if (snd_BUG_ON(!timer))
339 goto out;
340 /* wait, until the active callback is finished */ 327 /* wait, until the active callback is finished */
341 spin_lock_irq(&timer->lock); 328 spin_lock_irq(&timer->lock);
342 while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { 329 while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
@@ -345,11 +332,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
345 spin_lock_irq(&timer->lock); 332 spin_lock_irq(&timer->lock);
346 } 333 }
347 spin_unlock_irq(&timer->lock); 334 spin_unlock_irq(&timer->lock);
348 mutex_lock(&register_mutex); 335
349 list_del(&timeri->open_list);
350 if (list_empty(&timer->open_list_head) &&
351 timer->hw.close)
352 timer->hw.close(timer);
353 /* remove slave links */ 336 /* remove slave links */
354 spin_lock_irq(&slave_active_lock); 337 spin_lock_irq(&slave_active_lock);
355 spin_lock(&timer->lock); 338 spin_lock(&timer->lock);
@@ -363,18 +346,27 @@ int snd_timer_close(struct snd_timer_instance *timeri)
363 } 346 }
364 spin_unlock(&timer->lock); 347 spin_unlock(&timer->lock);
365 spin_unlock_irq(&slave_active_lock); 348 spin_unlock_irq(&slave_active_lock);
366 /* release a card refcount for safe disconnection */ 349
367 if (timer->card) 350 /* slave doesn't need to release timer resources below */
368 put_device(&timer->card->card_dev); 351 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
369 mutex_unlock(&register_mutex); 352 timer = NULL;
370 } 353 }
371 out: 354
372 if (timeri->private_free) 355 if (timeri->private_free)
373 timeri->private_free(timeri); 356 timeri->private_free(timeri);
374 kfree(timeri->owner); 357 kfree(timeri->owner);
375 kfree(timeri); 358 kfree(timeri);
376 if (timer) 359
360 if (timer) {
361 if (list_empty(&timer->open_list_head) && timer->hw.close)
362 timer->hw.close(timer);
363 /* release a card refcount for safe disconnection */
364 if (timer->card)
365 put_device(&timer->card->card_dev);
377 module_put(timer->module); 366 module_put(timer->module);
367 }
368
369 mutex_unlock(&register_mutex);
378 return 0; 370 return 0;
379} 371}
380 372
@@ -395,7 +387,6 @@ unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
395static void snd_timer_notify1(struct snd_timer_instance *ti, int event) 387static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
396{ 388{
397 struct snd_timer *timer; 389 struct snd_timer *timer;
398 unsigned long flags;
399 unsigned long resolution = 0; 390 unsigned long resolution = 0;
400 struct snd_timer_instance *ts; 391 struct snd_timer_instance *ts;
401 struct timespec tstamp; 392 struct timespec tstamp;
@@ -419,34 +410,66 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
419 return; 410 return;
420 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) 411 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
421 return; 412 return;
422 spin_lock_irqsave(&timer->lock, flags);
423 list_for_each_entry(ts, &ti->slave_active_head, active_list) 413 list_for_each_entry(ts, &ti->slave_active_head, active_list)
424 if (ts->ccallback) 414 if (ts->ccallback)
425 ts->ccallback(ts, event + 100, &tstamp, resolution); 415 ts->ccallback(ts, event + 100, &tstamp, resolution);
426 spin_unlock_irqrestore(&timer->lock, flags);
427} 416}
428 417
429static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri, 418/* start/continue a master timer */
430 unsigned long sticks) 419static int snd_timer_start1(struct snd_timer_instance *timeri,
420 bool start, unsigned long ticks)
431{ 421{
422 struct snd_timer *timer;
423 int result;
424 unsigned long flags;
425
426 timer = timeri->timer;
427 if (!timer)
428 return -EINVAL;
429
430 spin_lock_irqsave(&timer->lock, flags);
431 if (timer->card && timer->card->shutdown) {
432 result = -ENODEV;
433 goto unlock;
434 }
435 if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
436 SNDRV_TIMER_IFLG_START)) {
437 result = -EBUSY;
438 goto unlock;
439 }
440
441 if (start)
442 timeri->ticks = timeri->cticks = ticks;
443 else if (!timeri->cticks)
444 timeri->cticks = 1;
445 timeri->pticks = 0;
446
432 list_move_tail(&timeri->active_list, &timer->active_list_head); 447 list_move_tail(&timeri->active_list, &timer->active_list_head);
433 if (timer->running) { 448 if (timer->running) {
434 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) 449 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
435 goto __start_now; 450 goto __start_now;
436 timer->flags |= SNDRV_TIMER_FLG_RESCHED; 451 timer->flags |= SNDRV_TIMER_FLG_RESCHED;
437 timeri->flags |= SNDRV_TIMER_IFLG_START; 452 timeri->flags |= SNDRV_TIMER_IFLG_START;
438 return 1; /* delayed start */ 453 result = 1; /* delayed start */
439 } else { 454 } else {
440 timer->sticks = sticks; 455 if (start)
456 timer->sticks = ticks;
441 timer->hw.start(timer); 457 timer->hw.start(timer);
442 __start_now: 458 __start_now:
443 timer->running++; 459 timer->running++;
444 timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; 460 timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
445 return 0; 461 result = 0;
446 } 462 }
463 snd_timer_notify1(timeri, start ? SNDRV_TIMER_EVENT_START :
464 SNDRV_TIMER_EVENT_CONTINUE);
465 unlock:
466 spin_unlock_irqrestore(&timer->lock, flags);
467 return result;
447} 468}
448 469
449static int snd_timer_start_slave(struct snd_timer_instance *timeri) 470/* start/continue a slave timer */
471static int snd_timer_start_slave(struct snd_timer_instance *timeri,
472 bool start)
450{ 473{
451 unsigned long flags; 474 unsigned long flags;
452 475
@@ -460,88 +483,37 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri)
460 spin_lock(&timeri->timer->lock); 483 spin_lock(&timeri->timer->lock);
461 list_add_tail(&timeri->active_list, 484 list_add_tail(&timeri->active_list,
462 &timeri->master->slave_active_head); 485 &timeri->master->slave_active_head);
486 snd_timer_notify1(timeri, start ? SNDRV_TIMER_EVENT_START :
487 SNDRV_TIMER_EVENT_CONTINUE);
463 spin_unlock(&timeri->timer->lock); 488 spin_unlock(&timeri->timer->lock);
464 } 489 }
465 spin_unlock_irqrestore(&slave_active_lock, flags); 490 spin_unlock_irqrestore(&slave_active_lock, flags);
466 return 1; /* delayed start */ 491 return 1; /* delayed start */
467} 492}
468 493
469/* 494/* stop/pause a master timer */
470 * start the timer instance 495static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop)
471 */
472int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
473{ 496{
474 struct snd_timer *timer; 497 struct snd_timer *timer;
475 int result = -EINVAL; 498 int result = 0;
476 unsigned long flags; 499 unsigned long flags;
477 500
478 if (timeri == NULL || ticks < 1)
479 return -EINVAL;
480 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
481 result = snd_timer_start_slave(timeri);
482 if (result >= 0)
483 snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
484 return result;
485 }
486 timer = timeri->timer;
487 if (timer == NULL)
488 return -EINVAL;
489 if (timer->card && timer->card->shutdown)
490 return -ENODEV;
491 spin_lock_irqsave(&timer->lock, flags);
492 if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
493 SNDRV_TIMER_IFLG_START)) {
494 result = -EBUSY;
495 goto unlock;
496 }
497 timeri->ticks = timeri->cticks = ticks;
498 timeri->pticks = 0;
499 result = snd_timer_start1(timer, timeri, ticks);
500 unlock:
501 spin_unlock_irqrestore(&timer->lock, flags);
502 if (result >= 0)
503 snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
504 return result;
505}
506
507static int _snd_timer_stop(struct snd_timer_instance *timeri, int event)
508{
509 struct snd_timer *timer;
510 unsigned long flags;
511
512 if (snd_BUG_ON(!timeri))
513 return -ENXIO;
514
515 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
516 spin_lock_irqsave(&slave_active_lock, flags);
517 if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
518 spin_unlock_irqrestore(&slave_active_lock, flags);
519 return -EBUSY;
520 }
521 if (timeri->timer)
522 spin_lock(&timeri->timer->lock);
523 timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
524 list_del_init(&timeri->ack_list);
525 list_del_init(&timeri->active_list);
526 if (timeri->timer)
527 spin_unlock(&timeri->timer->lock);
528 spin_unlock_irqrestore(&slave_active_lock, flags);
529 goto __end;
530 }
531 timer = timeri->timer; 501 timer = timeri->timer;
532 if (!timer) 502 if (!timer)
533 return -EINVAL; 503 return -EINVAL;
534 spin_lock_irqsave(&timer->lock, flags); 504 spin_lock_irqsave(&timer->lock, flags);
535 if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | 505 if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
536 SNDRV_TIMER_IFLG_START))) { 506 SNDRV_TIMER_IFLG_START))) {
537 spin_unlock_irqrestore(&timer->lock, flags); 507 result = -EBUSY;
538 return -EBUSY; 508 goto unlock;
539 } 509 }
540 list_del_init(&timeri->ack_list); 510 list_del_init(&timeri->ack_list);
541 list_del_init(&timeri->active_list); 511 list_del_init(&timeri->active_list);
542 if (timer->card && timer->card->shutdown) { 512 if (timer->card && timer->card->shutdown)
543 spin_unlock_irqrestore(&timer->lock, flags); 513 goto unlock;
544 return 0; 514 if (stop) {
515 timeri->cticks = timeri->ticks;
516 timeri->pticks = 0;
545 } 517 }
546 if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) && 518 if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) &&
547 !(--timer->running)) { 519 !(--timer->running)) {
@@ -556,35 +528,60 @@ static int _snd_timer_stop(struct snd_timer_instance *timeri, int event)
556 } 528 }
557 } 529 }
558 timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); 530 timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
531 snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP :
532 SNDRV_TIMER_EVENT_CONTINUE);
533 unlock:
559 spin_unlock_irqrestore(&timer->lock, flags); 534 spin_unlock_irqrestore(&timer->lock, flags);
560 __end: 535 return result;
561 if (event != SNDRV_TIMER_EVENT_RESOLUTION) 536}
562 snd_timer_notify1(timeri, event); 537
538/* stop/pause a slave timer */
539static int snd_timer_stop_slave(struct snd_timer_instance *timeri, bool stop)
540{
541 unsigned long flags;
542
543 spin_lock_irqsave(&slave_active_lock, flags);
544 if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
545 spin_unlock_irqrestore(&slave_active_lock, flags);
546 return -EBUSY;
547 }
548 timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
549 if (timeri->timer) {
550 spin_lock(&timeri->timer->lock);
551 list_del_init(&timeri->ack_list);
552 list_del_init(&timeri->active_list);
553 snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP :
554 SNDRV_TIMER_EVENT_CONTINUE);
555 spin_unlock(&timeri->timer->lock);
556 }
557 spin_unlock_irqrestore(&slave_active_lock, flags);
563 return 0; 558 return 0;
564} 559}
565 560
566/* 561/*
562 * start the timer instance
563 */
564int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
565{
566 if (timeri == NULL || ticks < 1)
567 return -EINVAL;
568 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
569 return snd_timer_start_slave(timeri, true);
570 else
571 return snd_timer_start1(timeri, true, ticks);
572}
573
574/*
567 * stop the timer instance. 575 * stop the timer instance.
568 * 576 *
569 * do not call this from the timer callback! 577 * do not call this from the timer callback!
570 */ 578 */
571int snd_timer_stop(struct snd_timer_instance *timeri) 579int snd_timer_stop(struct snd_timer_instance *timeri)
572{ 580{
573 struct snd_timer *timer; 581 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
574 unsigned long flags; 582 return snd_timer_stop_slave(timeri, true);
575 int err; 583 else
576 584 return snd_timer_stop1(timeri, true);
577 err = _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_STOP);
578 if (err < 0)
579 return err;
580 timer = timeri->timer;
581 if (!timer)
582 return -EINVAL;
583 spin_lock_irqsave(&timer->lock, flags);
584 timeri->cticks = timeri->ticks;
585 timeri->pticks = 0;
586 spin_unlock_irqrestore(&timer->lock, flags);
587 return 0;
588} 585}
589 586
590/* 587/*
@@ -592,32 +589,10 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
592 */ 589 */
593int snd_timer_continue(struct snd_timer_instance *timeri) 590int snd_timer_continue(struct snd_timer_instance *timeri)
594{ 591{
595 struct snd_timer *timer;
596 int result = -EINVAL;
597 unsigned long flags;
598
599 if (timeri == NULL)
600 return result;
601 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) 592 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
602 return snd_timer_start_slave(timeri); 593 return snd_timer_start_slave(timeri, false);
603 timer = timeri->timer; 594 else
604 if (! timer) 595 return snd_timer_start1(timeri, false, 0);
605 return -EINVAL;
606 if (timer->card && timer->card->shutdown)
607 return -ENODEV;
608 spin_lock_irqsave(&timer->lock, flags);
609 if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
610 result = -EBUSY;
611 goto unlock;
612 }
613 if (!timeri->cticks)
614 timeri->cticks = 1;
615 timeri->pticks = 0;
616 result = snd_timer_start1(timer, timeri, timer->sticks);
617 unlock:
618 spin_unlock_irqrestore(&timer->lock, flags);
619 snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE);
620 return result;
621} 596}
622 597
623/* 598/*
@@ -625,7 +600,10 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
625 */ 600 */
626int snd_timer_pause(struct snd_timer_instance * timeri) 601int snd_timer_pause(struct snd_timer_instance * timeri)
627{ 602{
628 return _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_PAUSE); 603 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
604 return snd_timer_stop_slave(timeri, false);
605 else
606 return snd_timer_stop1(timeri, false);
629} 607}
630 608
631/* 609/*