diff options
Diffstat (limited to 'sound/usb/usx2y')
-rw-r--r-- | sound/usb/usx2y/us122l.c | 11 | ||||
-rw-r--r-- | sound/usb/usx2y/usbusx2y.c | 13 | ||||
-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 |
5 files changed, 73 insertions, 89 deletions
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 999550bbad40..cf5dc33f4a6d 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c | |||
@@ -535,7 +535,9 @@ static void snd_us122l_free(struct snd_card *card) | |||
535 | snd_us122l_card_used[index] = 0; | 535 | snd_us122l_card_used[index] = 0; |
536 | } | 536 | } |
537 | 537 | ||
538 | static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) | 538 | static int usx2y_create_card(struct usb_device *device, |
539 | struct usb_interface *intf, | ||
540 | struct snd_card **cardp) | ||
539 | { | 541 | { |
540 | int dev; | 542 | int dev; |
541 | struct snd_card *card; | 543 | struct snd_card *card; |
@@ -546,8 +548,8 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) | |||
546 | break; | 548 | break; |
547 | if (dev >= SNDRV_CARDS) | 549 | if (dev >= SNDRV_CARDS) |
548 | return -ENODEV; | 550 | return -ENODEV; |
549 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, | 551 | err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE, |
550 | sizeof(struct us122l), &card); | 552 | sizeof(struct us122l), &card); |
551 | if (err < 0) | 553 | if (err < 0) |
552 | return err; | 554 | return err; |
553 | snd_us122l_card_used[US122L(card)->card_index = dev] = 1; | 555 | snd_us122l_card_used[US122L(card)->card_index = dev] = 1; |
@@ -578,11 +580,10 @@ static int us122l_usb_probe(struct usb_interface *intf, | |||
578 | struct snd_card *card; | 580 | struct snd_card *card; |
579 | int err; | 581 | int err; |
580 | 582 | ||
581 | err = usx2y_create_card(device, &card); | 583 | err = usx2y_create_card(device, intf, &card); |
582 | if (err < 0) | 584 | if (err < 0) |
583 | return err; | 585 | return err; |
584 | 586 | ||
585 | snd_card_set_dev(card, &intf->dev); | ||
586 | if (!us122l_create_card(card)) { | 587 | if (!us122l_create_card(card)) { |
587 | snd_card_free(card); | 588 | snd_card_free(card); |
588 | return -EINVAL; | 589 | return -EINVAL; |
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 5a51b18c50fe..91e0e2a4808c 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c | |||
@@ -332,7 +332,9 @@ static struct usb_device_id snd_usX2Y_usb_id_table[] = { | |||
332 | { /* terminator */ } | 332 | { /* terminator */ } |
333 | }; | 333 | }; |
334 | 334 | ||
335 | static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp) | 335 | static int usX2Y_create_card(struct usb_device *device, |
336 | struct usb_interface *intf, | ||
337 | struct snd_card **cardp) | ||
336 | { | 338 | { |
337 | int dev; | 339 | int dev; |
338 | struct snd_card * card; | 340 | struct snd_card * card; |
@@ -343,15 +345,15 @@ static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp) | |||
343 | break; | 345 | break; |
344 | if (dev >= SNDRV_CARDS) | 346 | if (dev >= SNDRV_CARDS) |
345 | return -ENODEV; | 347 | return -ENODEV; |
346 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, | 348 | err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE, |
347 | sizeof(struct usX2Ydev), &card); | 349 | sizeof(struct usX2Ydev), &card); |
348 | if (err < 0) | 350 | if (err < 0) |
349 | return err; | 351 | return err; |
350 | snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1; | 352 | snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1; |
351 | card->private_free = snd_usX2Y_card_private_free; | 353 | card->private_free = snd_usX2Y_card_private_free; |
352 | usX2Y(card)->dev = device; | 354 | usX2Y(card)->dev = device; |
353 | init_waitqueue_head(&usX2Y(card)->prepare_wait_queue); | 355 | init_waitqueue_head(&usX2Y(card)->prepare_wait_queue); |
354 | mutex_init(&usX2Y(card)->prepare_mutex); | 356 | mutex_init(&usX2Y(card)->pcm_mutex); |
355 | INIT_LIST_HEAD(&usX2Y(card)->midi_list); | 357 | INIT_LIST_HEAD(&usX2Y(card)->midi_list); |
356 | strcpy(card->driver, "USB "NAME_ALLCAPS""); | 358 | strcpy(card->driver, "USB "NAME_ALLCAPS""); |
357 | sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); | 359 | sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); |
@@ -382,10 +384,9 @@ static int usX2Y_usb_probe(struct usb_device *device, | |||
382 | le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) | 384 | le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) |
383 | return -EINVAL; | 385 | return -EINVAL; |
384 | 386 | ||
385 | err = usX2Y_create_card(device, &card); | 387 | err = usX2Y_create_card(device, intf, &card); |
386 | if (err < 0) | 388 | if (err < 0) |
387 | return err; | 389 | return err; |
388 | snd_card_set_dev(card, &intf->dev); | ||
389 | if ((err = usX2Y_hwdep_new(card, device)) < 0 || | 390 | if ((err = usX2Y_hwdep_new(card, device)) < 0 || |
390 | (err = snd_card_register(card)) < 0) { | 391 | (err = snd_card_register(card)) < 0) { |
391 | snd_card_free(card); | 392 | snd_card_free(card); |
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 | ||