diff options
Diffstat (limited to 'sound/usb/usx2y')
| -rw-r--r-- | sound/usb/usx2y/us122l.c | 15 | ||||
| -rw-r--r-- | sound/usb/usx2y/usbusx2y.c | 21 | ||||
| -rw-r--r-- | sound/usb/usx2y/usbusx2y.h | 2 | ||||
| -rw-r--r-- | sound/usb/usx2y/usbusx2yaudio.c | 86 | ||||
| -rw-r--r-- | sound/usb/usx2y/usx2yhwdeppcm.c | 83 |
5 files changed, 87 insertions, 120 deletions
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index d0323a693ba..cf5dc33f4a6 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -262,7 +262,9 @@ static int usb_stream_hwdep_mmap(struct snd_hwdep *hw, } area->vm_ops = &usb_stream_hwdep_vm_ops; - area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; + area->vm_flags |= VM_DONTDUMP; + if (!read) + area->vm_flags |= VM_DONTEXPAND; area->vm_private_data = us122l; atomic_inc(&us122l->mmap_count); out: @@ -533,7 +535,9 @@ static void snd_us122l_free(struct snd_card *card) snd_us122l_card_used[index] = 0; } -static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) +static int usx2y_create_card(struct usb_device *device, + struct usb_interface *intf, + struct snd_card **cardp) { int dev; struct snd_card *card; @@ -544,8 +548,8 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) break; if (dev >= SNDRV_CARDS) return -ENODEV; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct us122l), &card); + err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct us122l), &card); if (err < 0) return err; snd_us122l_card_used[US122L(card)->card_index = dev] = 1; @@ -576,11 +580,10 @@ static int us122l_usb_probe(struct usb_interface *intf, struct snd_card *card; int err; - err = usx2y_create_card(device, &card); + err = usx2y_create_card(device, intf, &card); if (err < 0) return err; - snd_card_set_dev(card, &intf->dev); if (!us122l_create_card(card)) { snd_card_free(card); return -EINVAL; diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 1f9bbd55553..91e0e2a4808 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -305,11 +305,9 @@ static void usX2Y_unlinkSeq(struct snd_usX2Y_AsyncSeq *S) { int i; for (i = 0; i < URBS_AsyncSeq; ++i) { - if (S[i].urb) { - usb_kill_urb(S->urb[i]); - usb_free_urb(S->urb[i]); - S->urb[i] = NULL; - } + usb_kill_urb(S->urb[i]); + usb_free_urb(S->urb[i]); + S->urb[i] = NULL; } kfree(S->buffer); } @@ -334,7 +332,9 @@ static struct usb_device_id snd_usX2Y_usb_id_table[] = { { /* terminator */ } }; -static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp) +static int usX2Y_create_card(struct usb_device *device, + struct usb_interface *intf, + struct snd_card **cardp) { int dev; struct snd_card * card; @@ -345,15 +345,15 @@ static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp) break; if (dev >= SNDRV_CARDS) return -ENODEV; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct usX2Ydev), &card); + err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct usX2Ydev), &card); if (err < 0) return err; snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1; card->private_free = snd_usX2Y_card_private_free; usX2Y(card)->dev = device; init_waitqueue_head(&usX2Y(card)->prepare_wait_queue); - mutex_init(&usX2Y(card)->prepare_mutex); + mutex_init(&usX2Y(card)->pcm_mutex); INIT_LIST_HEAD(&usX2Y(card)->midi_list); strcpy(card->driver, "USB "NAME_ALLCAPS""); sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); @@ -384,10 +384,9 @@ static int usX2Y_usb_probe(struct usb_device *device, le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) return -EINVAL; - err = usX2Y_create_card(device, &card); + err = usX2Y_create_card(device, intf, &card); if (err < 0) return err; - snd_card_set_dev(card, &intf->dev); if ((err = usX2Y_hwdep_new(card, device)) < 0 || (err = snd_card_register(card)) < 0) { snd_card_free(card); diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h index e43c0a86441..6ae6b080693 100644 --- a/sound/usb/usx2y/usbusx2y.h +++ b/sound/usb/usx2y/usbusx2y.h @@ -36,7 +36,7 @@ struct usX2Ydev { unsigned int rate, format; int chip_status; - struct mutex prepare_mutex; + struct mutex pcm_mutex; struct us428ctls_sharedmem *us428ctls_sharedmem; int wait_iso_frame; wait_queue_head_t us428ctls_wait_queue_head; diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 4967fe9c938..a63330dd140 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -273,7 +273,11 @@ static void usX2Y_clients_stop(struct usX2Ydev *usX2Y) struct snd_usX2Y_substream *subs = usX2Y->subs[s]; if (subs) { if (atomic_read(&subs->state) >= state_PRERUNNING) { + unsigned long flags; + + snd_pcm_stream_lock_irqsave(subs->pcm_substream, flags); snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock_irqrestore(subs->pcm_substream, flags); } for (u = 0; u < NRURBS; u++) { struct urb *urb = subs->urb[u]; @@ -295,19 +299,6 @@ static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y, usX2Y_clients_stop(usX2Y); } -static void usX2Y_error_sequence(struct usX2Ydev *usX2Y, - struct snd_usX2Y_substream *subs, struct urb *urb) -{ - snd_printk(KERN_ERR -"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" -"Most probably some urb of usb-frame %i is still missing.\n" -"Cause could be too long delays in usb-hcd interrupt handling.\n", - usb_get_current_frame_number(usX2Y->dev), - subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", - usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame); - usX2Y_clients_stop(usX2Y); -} - static void i_usX2Y_urb_complete(struct urb *urb) { struct snd_usX2Y_substream *subs = urb->context; @@ -324,12 +315,9 @@ static void i_usX2Y_urb_complete(struct urb *urb) usX2Y_error_urb_status(usX2Y, subs, urb); return; } - if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF))) - subs->completed_urb = urb; - else { - usX2Y_error_sequence(usX2Y, subs, urb); - return; - } + + subs->completed_urb = urb; + { struct snd_usX2Y_substream *capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE], *playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; @@ -764,36 +752,44 @@ static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream, unsigned int rate = params_rate(hw_params); snd_pcm_format_t format = params_format(hw_params); struct snd_card *card = substream->pstr->pcm->card; - struct list_head *list; + struct usX2Ydev *dev = usX2Y(card); + int i; + mutex_lock(&usX2Y(card)->pcm_mutex); snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params); - // all pcm substreams off one usX2Y have to operate at the same rate & format - list_for_each(list, &card->devices) { - struct snd_device *dev; - struct snd_pcm *pcm; - int s; - dev = snd_device(list); - if (dev->type != SNDRV_DEV_PCM) + /* all pcm substreams off one usX2Y have to operate at the same + * rate & format + */ + for (i = 0; i < dev->pcm_devs * 2; i++) { + struct snd_usX2Y_substream *subs = dev->subs[i]; + struct snd_pcm_substream *test_substream; + + if (!subs) + continue; + test_substream = subs->pcm_substream; + if (!test_substream || test_substream == substream || + !test_substream->runtime) continue; - pcm = dev->device_data; - for (s = 0; s < 2; ++s) { - struct snd_pcm_substream *test_substream; - test_substream = pcm->streams[s].substream; - if (test_substream && test_substream != substream && - test_substream->runtime && - ((test_substream->runtime->format && - test_substream->runtime->format != format) || - (test_substream->runtime->rate && - test_substream->runtime->rate != rate))) - return -EINVAL; + if ((test_substream->runtime->format && + test_substream->runtime->format != format) || + (test_substream->runtime->rate && + test_substream->runtime->rate != rate)) { + err = -EINVAL; + goto error; } } - if (0 > (err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)))) { + + err = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (err < 0) { snd_printk(KERN_ERR "snd_pcm_lib_malloc_pages(%p, %i) returned %i\n", substream, params_buffer_bytes(hw_params), err); - return err; + goto error; } - return 0; + + error: + mutex_unlock(&usX2Y(card)->pcm_mutex); + return err; } /* @@ -803,7 +799,7 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_usX2Y_substream *subs = runtime->private_data; - mutex_lock(&subs->usX2Y->prepare_mutex); + mutex_lock(&subs->usX2Y->pcm_mutex); snd_printdd("snd_usX2Y_hw_free(%p)\n", substream); if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { @@ -824,7 +820,7 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream) usX2Y_urbs_release(subs); } } - mutex_unlock(&subs->usX2Y->prepare_mutex); + mutex_unlock(&subs->usX2Y->pcm_mutex); return snd_pcm_lib_free_pages(substream); } /* @@ -841,7 +837,7 @@ static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream) int err = 0; snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); - mutex_lock(&usX2Y->prepare_mutex); + mutex_lock(&usX2Y->pcm_mutex); usX2Y_subs_prepare(subs); // Start hardware streams // SyncStream first.... @@ -861,7 +857,7 @@ static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream) err = usX2Y_urbs_start(subs); up_prepare_mutex: - mutex_unlock(&usX2Y->prepare_mutex); + mutex_unlock(&usX2Y->pcm_mutex); return err; } diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index f2a1acdc4d8..90766a92e7f 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -244,13 +244,8 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb) usX2Y_error_urb_status(usX2Y, subs, urb); return; } - if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF))) - subs->completed_urb = urb; - else { - usX2Y_error_sequence(usX2Y, subs, urb); - return; - } + subs->completed_urb = urb; capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; capsubs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; @@ -363,7 +358,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct snd_usX2Y_substream *subs = runtime->private_data, *cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; - mutex_lock(&subs->usX2Y->prepare_mutex); + mutex_lock(&subs->usX2Y->pcm_mutex); snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream); if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { @@ -392,7 +387,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream) usX2Y_usbpcm_urbs_release(cap_subs2); } } - mutex_unlock(&subs->usX2Y->prepare_mutex); + mutex_unlock(&subs->usX2Y->pcm_mutex); return snd_pcm_lib_free_pages(substream); } @@ -498,7 +493,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream) memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); } - mutex_lock(&usX2Y->prepare_mutex); + mutex_lock(&usX2Y->pcm_mutex); usX2Y_subs_prepare(subs); // Start hardware streams // SyncStream first.... @@ -539,7 +534,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream) usX2Y->hwdep_pcm_shm->capture_iso_start = -1; up_prepare_mutex: - mutex_unlock(&usX2Y->prepare_mutex); + mutex_unlock(&usX2Y->pcm_mutex); return err; } @@ -605,59 +600,30 @@ static struct snd_pcm_ops snd_usX2Y_usbpcm_ops = }; -static int usX2Y_pcms_lock_check(struct snd_card *card) +static int usX2Y_pcms_busy_check(struct snd_card *card) { - struct list_head *list; - struct snd_device *dev; - struct snd_pcm *pcm; - int err = 0; - list_for_each(list, &card->devices) { - dev = snd_device(list); - if (dev->type != SNDRV_DEV_PCM) - continue; - pcm = dev->device_data; - mutex_lock(&pcm->open_mutex); - } - list_for_each(list, &card->devices) { - int s; - dev = snd_device(list); - if (dev->type != SNDRV_DEV_PCM) - continue; - pcm = dev->device_data; - for (s = 0; s < 2; ++s) { - struct snd_pcm_substream *substream; - substream = pcm->streams[s].substream; - if (substream && SUBSTREAM_BUSY(substream)) - err = -EBUSY; - } - } - return err; -} - + struct usX2Ydev *dev = usX2Y(card); + int i; -static void usX2Y_pcms_unlock(struct snd_card *card) -{ - struct list_head *list; - struct snd_device *dev; - struct snd_pcm *pcm; - list_for_each(list, &card->devices) { - dev = snd_device(list); - if (dev->type != SNDRV_DEV_PCM) - continue; - pcm = dev->device_data; - mutex_unlock(&pcm->open_mutex); + for (i = 0; i < dev->pcm_devs * 2; i++) { + struct snd_usX2Y_substream *subs = dev->subs[i]; + if (subs && subs->pcm_substream && + SUBSTREAM_BUSY(subs->pcm_substream)) + return -EBUSY; } + return 0; } - static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) { - // we need to be the first struct snd_card *card = hw->card; - int err = usX2Y_pcms_lock_check(card); - if (0 == err) + int err; + + mutex_lock(&usX2Y(card)->pcm_mutex); + err = usX2Y_pcms_busy_check(card); + if (!err) usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; - usX2Y_pcms_unlock(card); + mutex_unlock(&usX2Y(card)->pcm_mutex); return err; } @@ -665,10 +631,13 @@ static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) { struct snd_card *card = hw->card; - int err = usX2Y_pcms_lock_check(card); - if (0 == err) + int err; + + mutex_lock(&usX2Y(card)->pcm_mutex); + err = usX2Y_pcms_busy_check(card); + if (!err) usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; - usX2Y_pcms_unlock(card); + mutex_unlock(&usX2Y(card)->pcm_mutex); return err; } |
