diff options
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r-- | sound/usb/pcm.c | 80 |
1 files changed, 33 insertions, 47 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 33cd26763c0e..0e4eab96e23e 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -348,6 +348,9 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, ep = 0x84; ifnum = 0; goto add_sync_ep_from_ifnum; + case USB_ID(0x0582, 0x01d8): /* BOSS Katana */ + /* BOSS Katana amplifiers do not need quirks */ + return 0; } if (attr == USB_ENDPOINT_SYNC_ASYNC && @@ -367,7 +370,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, add_sync_ep_from_ifnum: iface = usb_ifnum_to_if(dev, ifnum); - if (!iface || iface->num_altsetting == 0) + if (!iface || iface->num_altsetting < 2) return -EINVAL; alts = &iface->altsetting[1]; @@ -503,15 +506,15 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) if (WARN_ON(!iface)) return -EINVAL; alts = usb_altnum_to_altsetting(iface, fmt->altsetting); - altsd = get_iface_desc(alts); - if (WARN_ON(altsd->bAlternateSetting != fmt->altsetting)) + if (WARN_ON(!alts)) return -EINVAL; + altsd = get_iface_desc(alts); - if (fmt == subs->cur_audiofmt) + if (fmt == subs->cur_audiofmt && !subs->need_setup_fmt) return 0; /* close the old interface */ - if (subs->interface >= 0 && subs->interface != fmt->iface) { + if (subs->interface >= 0 && (subs->interface != fmt->iface || subs->need_setup_fmt)) { if (!subs->stream->chip->keep_iface) { err = usb_set_interface(subs->dev, subs->interface, 0); if (err < 0) { @@ -525,6 +528,9 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) subs->altset_idx = 0; } + if (subs->need_setup_fmt) + subs->need_setup_fmt = false; + /* set interface */ if (iface->cur_altsetting != alts) { err = snd_usb_select_mode_quirk(subs, fmt); @@ -782,12 +788,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, if (ret) return ret; - if (snd_usb_use_vmalloc) - ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - else - ret = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); + ret = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); if (ret < 0) goto stop_pipeline; @@ -854,10 +856,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) snd_usb_unlock_shutdown(subs->stream->chip); } - if (snd_usb_use_vmalloc) - return snd_pcm_lib_free_vmalloc_buffer(substream); - else - return snd_pcm_lib_free_pages(substream); + return snd_pcm_lib_free_pages(substream); } /* @@ -1732,6 +1731,13 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea subs->data_endpoint->retire_data_urb = retire_playback_urb; subs->running = 0; return 0; + case SNDRV_PCM_TRIGGER_SUSPEND: + if (subs->stream->chip->setup_fmt_after_resume_quirk) { + stop_endpoints(subs, true); + subs->need_setup_fmt = true; + return 0; + } + break; } return -EINVAL; @@ -1764,6 +1770,13 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream subs->data_endpoint->retire_data_urb = retire_capture_urb; subs->running = 1; return 0; + case SNDRV_PCM_TRIGGER_SUSPEND: + if (subs->stream->chip->setup_fmt_after_resume_quirk) { + stop_endpoints(subs, true); + subs->need_setup_fmt = true; + return 0; + } + break; } return -EINVAL; @@ -1778,7 +1791,6 @@ static const struct snd_pcm_ops snd_usb_playback_ops = { .prepare = snd_usb_pcm_prepare, .trigger = snd_usb_substream_playback_trigger, .pointer = snd_usb_pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, }; static const struct snd_pcm_ops snd_usb_capture_ops = { @@ -1790,43 +1802,14 @@ static const struct snd_pcm_ops snd_usb_capture_ops = { .prepare = snd_usb_pcm_prepare, .trigger = snd_usb_substream_capture_trigger, .pointer = snd_usb_pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, -}; - -static const struct snd_pcm_ops snd_usb_playback_dev_ops = { - .open = snd_usb_pcm_open, - .close = snd_usb_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_usb_hw_params, - .hw_free = snd_usb_hw_free, - .prepare = snd_usb_pcm_prepare, - .trigger = snd_usb_substream_playback_trigger, - .pointer = snd_usb_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -static const struct snd_pcm_ops snd_usb_capture_dev_ops = { - .open = snd_usb_pcm_open, - .close = snd_usb_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_usb_hw_params, - .hw_free = snd_usb_hw_free, - .prepare = snd_usb_pcm_prepare, - .trigger = snd_usb_substream_capture_trigger, - .pointer = snd_usb_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, }; void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream) { const struct snd_pcm_ops *ops; - if (snd_usb_use_vmalloc) - ops = stream == SNDRV_PCM_STREAM_PLAYBACK ? + ops = stream == SNDRV_PCM_STREAM_PLAYBACK ? &snd_usb_playback_ops : &snd_usb_capture_ops; - else - ops = stream == SNDRV_PCM_STREAM_PLAYBACK ? - &snd_usb_playback_dev_ops : &snd_usb_capture_dev_ops; snd_pcm_set_ops(pcm, stream, ops); } @@ -1836,7 +1819,10 @@ void snd_usb_preallocate_buffer(struct snd_usb_substream *subs) struct snd_pcm_substream *s = pcm->streams[subs->direction].substream; struct device *dev = subs->dev->bus->controller; - if (!snd_usb_use_vmalloc) + if (snd_usb_use_vmalloc) + snd_pcm_lib_preallocate_pages(s, SNDRV_DMA_TYPE_VMALLOC, + NULL, 0, 0); + else snd_pcm_lib_preallocate_pages(s, SNDRV_DMA_TYPE_DEV_SG, dev, 64*1024, 512*1024); } |