diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/usb/usx2y/usbusx2y.c | 2 | ||||
-rw-r--r-- | sound/usb/usx2y/usbusx2y.h | 2 | ||||
-rw-r--r-- | sound/usb/usx2y/usbusx2yaudio.c | 60 | ||||
-rw-r--r-- | sound/usb/usx2y/usx2yhwdeppcm.c | 76 |
4 files changed, 61 insertions, 79 deletions
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index e38c87302b15..91e0e2a4808c 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c | |||
@@ -353,7 +353,7 @@ static int usX2Y_create_card(struct usb_device *device, | |||
353 | card->private_free = snd_usX2Y_card_private_free; | 353 | card->private_free = snd_usX2Y_card_private_free; |
354 | usX2Y(card)->dev = device; | 354 | usX2Y(card)->dev = device; |
355 | init_waitqueue_head(&usX2Y(card)->prepare_wait_queue); | 355 | init_waitqueue_head(&usX2Y(card)->prepare_wait_queue); |
356 | mutex_init(&usX2Y(card)->prepare_mutex); | 356 | mutex_init(&usX2Y(card)->pcm_mutex); |
357 | INIT_LIST_HEAD(&usX2Y(card)->midi_list); | 357 | INIT_LIST_HEAD(&usX2Y(card)->midi_list); |
358 | strcpy(card->driver, "USB "NAME_ALLCAPS""); | 358 | strcpy(card->driver, "USB "NAME_ALLCAPS""); |
359 | sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); | 359 | sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); |
diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h index e43c0a86441a..6ae6b0806938 100644 --- a/sound/usb/usx2y/usbusx2y.h +++ b/sound/usb/usx2y/usbusx2y.h | |||
@@ -36,7 +36,7 @@ struct usX2Ydev { | |||
36 | unsigned int rate, | 36 | unsigned int rate, |
37 | format; | 37 | format; |
38 | int chip_status; | 38 | int chip_status; |
39 | struct mutex prepare_mutex; | 39 | struct mutex pcm_mutex; |
40 | struct us428ctls_sharedmem *us428ctls_sharedmem; | 40 | struct us428ctls_sharedmem *us428ctls_sharedmem; |
41 | int wait_iso_frame; | 41 | int wait_iso_frame; |
42 | wait_queue_head_t us428ctls_wait_queue_head; | 42 | wait_queue_head_t us428ctls_wait_queue_head; |
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 6234a51625b1..a63330dd1407 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c | |||
@@ -752,36 +752,44 @@ static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream, | |||
752 | unsigned int rate = params_rate(hw_params); | 752 | unsigned int rate = params_rate(hw_params); |
753 | snd_pcm_format_t format = params_format(hw_params); | 753 | snd_pcm_format_t format = params_format(hw_params); |
754 | struct snd_card *card = substream->pstr->pcm->card; | 754 | struct snd_card *card = substream->pstr->pcm->card; |
755 | struct list_head *list; | 755 | struct usX2Ydev *dev = usX2Y(card); |
756 | int i; | ||
756 | 757 | ||
758 | mutex_lock(&usX2Y(card)->pcm_mutex); | ||
757 | snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params); | 759 | snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params); |
758 | // all pcm substreams off one usX2Y have to operate at the same rate & format | 760 | /* all pcm substreams off one usX2Y have to operate at the same |
759 | list_for_each(list, &card->devices) { | 761 | * rate & format |
760 | struct snd_device *dev; | 762 | */ |
761 | struct snd_pcm *pcm; | 763 | for (i = 0; i < dev->pcm_devs * 2; i++) { |
762 | int s; | 764 | struct snd_usX2Y_substream *subs = dev->subs[i]; |
763 | dev = snd_device(list); | 765 | struct snd_pcm_substream *test_substream; |
764 | if (dev->type != SNDRV_DEV_PCM) | 766 | |
767 | if (!subs) | ||
768 | continue; | ||
769 | test_substream = subs->pcm_substream; | ||
770 | if (!test_substream || test_substream == substream || | ||
771 | !test_substream->runtime) | ||
765 | continue; | 772 | continue; |
766 | pcm = dev->device_data; | 773 | if ((test_substream->runtime->format && |
767 | for (s = 0; s < 2; ++s) { | 774 | test_substream->runtime->format != format) || |
768 | struct snd_pcm_substream *test_substream; | 775 | (test_substream->runtime->rate && |
769 | test_substream = pcm->streams[s].substream; | 776 | test_substream->runtime->rate != rate)) { |
770 | if (test_substream && test_substream != substream && | 777 | err = -EINVAL; |
771 | test_substream->runtime && | 778 | goto error; |
772 | ((test_substream->runtime->format && | ||
773 | test_substream->runtime->format != format) || | ||
774 | (test_substream->runtime->rate && | ||
775 | test_substream->runtime->rate != rate))) | ||
776 | return -EINVAL; | ||
777 | } | 779 | } |
778 | } | 780 | } |
779 | if (0 > (err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)))) { | 781 | |
782 | err = snd_pcm_lib_malloc_pages(substream, | ||
783 | params_buffer_bytes(hw_params)); | ||
784 | if (err < 0) { | ||
780 | snd_printk(KERN_ERR "snd_pcm_lib_malloc_pages(%p, %i) returned %i\n", | 785 | snd_printk(KERN_ERR "snd_pcm_lib_malloc_pages(%p, %i) returned %i\n", |
781 | substream, params_buffer_bytes(hw_params), err); | 786 | substream, params_buffer_bytes(hw_params), err); |
782 | return err; | 787 | goto error; |
783 | } | 788 | } |
784 | return 0; | 789 | |
790 | error: | ||
791 | mutex_unlock(&usX2Y(card)->pcm_mutex); | ||
792 | return err; | ||
785 | } | 793 | } |
786 | 794 | ||
787 | /* | 795 | /* |
@@ -791,7 +799,7 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream) | |||
791 | { | 799 | { |
792 | struct snd_pcm_runtime *runtime = substream->runtime; | 800 | struct snd_pcm_runtime *runtime = substream->runtime; |
793 | struct snd_usX2Y_substream *subs = runtime->private_data; | 801 | struct snd_usX2Y_substream *subs = runtime->private_data; |
794 | mutex_lock(&subs->usX2Y->prepare_mutex); | 802 | mutex_lock(&subs->usX2Y->pcm_mutex); |
795 | snd_printdd("snd_usX2Y_hw_free(%p)\n", substream); | 803 | snd_printdd("snd_usX2Y_hw_free(%p)\n", substream); |
796 | 804 | ||
797 | if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { | 805 | if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { |
@@ -812,7 +820,7 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream) | |||
812 | usX2Y_urbs_release(subs); | 820 | usX2Y_urbs_release(subs); |
813 | } | 821 | } |
814 | } | 822 | } |
815 | mutex_unlock(&subs->usX2Y->prepare_mutex); | 823 | mutex_unlock(&subs->usX2Y->pcm_mutex); |
816 | return snd_pcm_lib_free_pages(substream); | 824 | return snd_pcm_lib_free_pages(substream); |
817 | } | 825 | } |
818 | /* | 826 | /* |
@@ -829,7 +837,7 @@ static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream) | |||
829 | int err = 0; | 837 | int err = 0; |
830 | snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); | 838 | snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); |
831 | 839 | ||
832 | mutex_lock(&usX2Y->prepare_mutex); | 840 | mutex_lock(&usX2Y->pcm_mutex); |
833 | usX2Y_subs_prepare(subs); | 841 | usX2Y_subs_prepare(subs); |
834 | // Start hardware streams | 842 | // Start hardware streams |
835 | // SyncStream first.... | 843 | // SyncStream first.... |
@@ -849,7 +857,7 @@ static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream) | |||
849 | err = usX2Y_urbs_start(subs); | 857 | err = usX2Y_urbs_start(subs); |
850 | 858 | ||
851 | up_prepare_mutex: | 859 | up_prepare_mutex: |
852 | mutex_unlock(&usX2Y->prepare_mutex); | 860 | mutex_unlock(&usX2Y->pcm_mutex); |
853 | return err; | 861 | return err; |
854 | } | 862 | } |
855 | 863 | ||
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 814d0e887c62..90766a92e7fd 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c | |||
@@ -358,7 +358,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream) | |||
358 | struct snd_pcm_runtime *runtime = substream->runtime; | 358 | struct snd_pcm_runtime *runtime = substream->runtime; |
359 | struct snd_usX2Y_substream *subs = runtime->private_data, | 359 | struct snd_usX2Y_substream *subs = runtime->private_data, |
360 | *cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; | 360 | *cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; |
361 | mutex_lock(&subs->usX2Y->prepare_mutex); | 361 | mutex_lock(&subs->usX2Y->pcm_mutex); |
362 | snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream); | 362 | snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream); |
363 | 363 | ||
364 | if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { | 364 | if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { |
@@ -387,7 +387,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream) | |||
387 | usX2Y_usbpcm_urbs_release(cap_subs2); | 387 | usX2Y_usbpcm_urbs_release(cap_subs2); |
388 | } | 388 | } |
389 | } | 389 | } |
390 | mutex_unlock(&subs->usX2Y->prepare_mutex); | 390 | mutex_unlock(&subs->usX2Y->pcm_mutex); |
391 | return snd_pcm_lib_free_pages(substream); | 391 | return snd_pcm_lib_free_pages(substream); |
392 | } | 392 | } |
393 | 393 | ||
@@ -493,7 +493,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream) | |||
493 | memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); | 493 | memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); |
494 | } | 494 | } |
495 | 495 | ||
496 | mutex_lock(&usX2Y->prepare_mutex); | 496 | mutex_lock(&usX2Y->pcm_mutex); |
497 | usX2Y_subs_prepare(subs); | 497 | usX2Y_subs_prepare(subs); |
498 | // Start hardware streams | 498 | // Start hardware streams |
499 | // SyncStream first.... | 499 | // SyncStream first.... |
@@ -534,7 +534,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream) | |||
534 | usX2Y->hwdep_pcm_shm->capture_iso_start = -1; | 534 | usX2Y->hwdep_pcm_shm->capture_iso_start = -1; |
535 | 535 | ||
536 | up_prepare_mutex: | 536 | up_prepare_mutex: |
537 | mutex_unlock(&usX2Y->prepare_mutex); | 537 | mutex_unlock(&usX2Y->pcm_mutex); |
538 | return err; | 538 | return err; |
539 | } | 539 | } |
540 | 540 | ||
@@ -600,59 +600,30 @@ static struct snd_pcm_ops snd_usX2Y_usbpcm_ops = | |||
600 | }; | 600 | }; |
601 | 601 | ||
602 | 602 | ||
603 | static int usX2Y_pcms_lock_check(struct snd_card *card) | 603 | static int usX2Y_pcms_busy_check(struct snd_card *card) |
604 | { | 604 | { |
605 | struct list_head *list; | 605 | struct usX2Ydev *dev = usX2Y(card); |
606 | struct snd_device *dev; | 606 | int i; |
607 | struct snd_pcm *pcm; | ||
608 | int err = 0; | ||
609 | list_for_each(list, &card->devices) { | ||
610 | dev = snd_device(list); | ||
611 | if (dev->type != SNDRV_DEV_PCM) | ||
612 | continue; | ||
613 | pcm = dev->device_data; | ||
614 | mutex_lock(&pcm->open_mutex); | ||
615 | } | ||
616 | list_for_each(list, &card->devices) { | ||
617 | int s; | ||
618 | dev = snd_device(list); | ||
619 | if (dev->type != SNDRV_DEV_PCM) | ||
620 | continue; | ||
621 | pcm = dev->device_data; | ||
622 | for (s = 0; s < 2; ++s) { | ||
623 | struct snd_pcm_substream *substream; | ||
624 | substream = pcm->streams[s].substream; | ||
625 | if (substream && SUBSTREAM_BUSY(substream)) | ||
626 | err = -EBUSY; | ||
627 | } | ||
628 | } | ||
629 | return err; | ||
630 | } | ||
631 | |||
632 | 607 | ||
633 | static void usX2Y_pcms_unlock(struct snd_card *card) | 608 | for (i = 0; i < dev->pcm_devs * 2; i++) { |
634 | { | 609 | struct snd_usX2Y_substream *subs = dev->subs[i]; |
635 | struct list_head *list; | 610 | if (subs && subs->pcm_substream && |
636 | struct snd_device *dev; | 611 | SUBSTREAM_BUSY(subs->pcm_substream)) |
637 | struct snd_pcm *pcm; | 612 | return -EBUSY; |
638 | list_for_each(list, &card->devices) { | ||
639 | dev = snd_device(list); | ||
640 | if (dev->type != SNDRV_DEV_PCM) | ||
641 | continue; | ||
642 | pcm = dev->device_data; | ||
643 | mutex_unlock(&pcm->open_mutex); | ||
644 | } | 613 | } |
614 | return 0; | ||
645 | } | 615 | } |
646 | 616 | ||
647 | |||
648 | static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) | 617 | static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) |
649 | { | 618 | { |
650 | // we need to be the first | ||
651 | struct snd_card *card = hw->card; | 619 | struct snd_card *card = hw->card; |
652 | int err = usX2Y_pcms_lock_check(card); | 620 | int err; |
653 | if (0 == err) | 621 | |
622 | mutex_lock(&usX2Y(card)->pcm_mutex); | ||
623 | err = usX2Y_pcms_busy_check(card); | ||
624 | if (!err) | ||
654 | usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; | 625 | usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; |
655 | usX2Y_pcms_unlock(card); | 626 | mutex_unlock(&usX2Y(card)->pcm_mutex); |
656 | return err; | 627 | return err; |
657 | } | 628 | } |
658 | 629 | ||
@@ -660,10 +631,13 @@ static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) | |||
660 | static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) | 631 | static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) |
661 | { | 632 | { |
662 | struct snd_card *card = hw->card; | 633 | struct snd_card *card = hw->card; |
663 | int err = usX2Y_pcms_lock_check(card); | 634 | int err; |
664 | if (0 == err) | 635 | |
636 | mutex_lock(&usX2Y(card)->pcm_mutex); | ||
637 | err = usX2Y_pcms_busy_check(card); | ||
638 | if (!err) | ||
665 | usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; | 639 | usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; |
666 | usX2Y_pcms_unlock(card); | 640 | mutex_unlock(&usX2Y(card)->pcm_mutex); |
667 | return err; | 641 | return err; |
668 | } | 642 | } |
669 | 643 | ||