]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - sound/usb/pcm.c
ALSA: usb-audio: Apply the sample rate quirk for Bose Companion 5
[linux.git] / sound / usb / pcm.c
index ff5ab24f3bd1f36013ffd343b39139d48a5feff8..a11c8150af58159265ae7544bdc05c6ae758ea41 100644 (file)
@@ -506,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) {
@@ -528,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);
@@ -785,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;
 
@@ -857,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);
 }
 
 /*
@@ -1735,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;
@@ -1767,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;
@@ -1781,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 = {
@@ -1793,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);
 }
 
@@ -1839,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);
 }