Merge branch 'topic/asoc' into topic/remove-irqf_disable
authorTakashi Iwai <tiwai@suse.de>
Thu, 22 Sep 2011 07:56:12 +0000 (09:56 +0200)
committerTakashi Iwai <tiwai@suse.de>
Thu, 22 Sep 2011 07:56:12 +0000 (09:56 +0200)
88 files changed:
Documentation/DocBook/writing-an-alsa-driver.tmpl
include/linux/usb/ch9.h
include/sound/mpu401.h
include/sound/pcm.h
sound/aoa/codecs/onyx.c
sound/aoa/fabrics/layout.c
sound/core/control.c
sound/core/pcm_lib.c
sound/core/timer.c
sound/drivers/mpu401/mpu401.c
sound/drivers/mpu401/mpu401_uart.c
sound/firewire/isight.c
sound/isa/ad1816a/ad1816a.c
sound/isa/als100.c
sound/isa/azt2320.c
sound/isa/cmi8330.c
sound/isa/cs423x/cs4231.c
sound/isa/cs423x/cs4236.c
sound/isa/es1688/es1688.c
sound/isa/es18xx.c
sound/isa/galaxy/galaxy.c
sound/isa/gus/gusextreme.c
sound/isa/msnd/msnd_pinnacle.c
sound/isa/opl3sa2.c
sound/isa/opti9xx/miro.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/isa/sb/jazz16.c
sound/isa/sb/sb16.c
sound/isa/sc6000.c
sound/isa/sscape.c
sound/isa/wavefront/wavefront.c
sound/oss/pas2_pcm.c
sound/oss/pss.c
sound/pci/Kconfig
sound/pci/ac97/ac97_patch.c
sound/pci/als4000.c
sound/pci/asihpi/hpicmn.c
sound/pci/au88x0/au88x0_mpu401.c
sound/pci/azt3328.c
sound/pci/cmipci.c
sound/pci/ctxfi/ctpcm.c
sound/pci/ctxfi/ctsrc.c
sound/pci/ctxfi/ctvmem.h
sound/pci/emu10k1/emupcm.c
sound/pci/es1938.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/alc268_quirks.c
sound/pci/hda/alc269_quirks.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_eld.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/ice1712/ice1712.c
sound/pci/maestro3.c
sound/pci/oxygen/oxygen_lib.c
sound/pci/oxygen/xonar_pcm179x.c
sound/pci/riptide/riptide.c
sound/pci/rme9652/hdspm.c
sound/pci/sonicvibes.c
sound/pci/trident/trident.c
sound/pci/via82xx.c
sound/pci/ymfpci/ymfpci.c
sound/pci/ymfpci/ymfpci_main.c
sound/ppc/keywest.c
sound/usb/Makefile
sound/usb/caiaq/audio.c
sound/usb/caiaq/device.h
sound/usb/caiaq/input.c
sound/usb/card.c
sound/usb/card.h
sound/usb/endpoint.c
sound/usb/endpoint.h
sound/usb/midi.c
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/pcm.c
sound/usb/pcm.h
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/stream.c [new file with mode: 0644]
sound/usb/stream.h [new file with mode: 0644]
sound/usb/urb.c [deleted file]
sound/usb/urb.h [deleted file]
sound/usb/usbaudio.h

index 598c22f..5de23c0 100644 (file)
@@ -4288,7 +4288,7 @@ struct _snd_pcm_runtime {
 <![CDATA[
   struct snd_rawmidi *rmidi;
   snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
-                      irq, irq_flags, &rmidi);
+                      irq, &rmidi);
 ]]>
           </programlisting>
         </informalexample>
@@ -4343,6 +4343,13 @@ struct _snd_pcm_runtime {
        by itself to start processing the output stream in the irq handler.
        </para>
 
+       <para>
+       If the MPU-401 interface shares its interrupt with the other logical
+       devices on the card, set <constant>MPU401_INFO_IRQ_HOOK</constant>
+       (see <link linkend="midi-interface-interrupt-handler"><citetitle>
+       below</citetitle></link>).
+       </para>
+
       <para>
         Usually, the port address corresponds to the command port and
         port + 1 corresponds to the data port. If not, you may change
@@ -4375,14 +4382,12 @@ struct _snd_pcm_runtime {
       </para>
 
       <para>
-        The 6th argument specifies the irq number for UART. If the irq
-      is already allocated, pass 0 to the 7th argument
-      (<parameter>irq_flags</parameter>). Otherwise, pass the flags
-      for irq allocation 
-      (<constant>SA_XXX</constant> bits) to it, and the irq will be
-      reserved by the mpu401-uart layer. If the card doesn't generate
-      UART interrupts, pass -1 as the irq number. Then a timer
-      interrupt will be invoked for polling. 
+       The 6th argument specifies the ISA irq number that will be
+       allocated.  If no interrupt is to be allocated (because your
+       code is already allocating a shared interrupt, or because the
+       device does not use interrupts), pass -1 instead.
+       For a MPU-401 device without an interrupt, a polling timer
+       will be used instead.
       </para>
     </section>
 
@@ -4390,12 +4395,13 @@ struct _snd_pcm_runtime {
       <title>Interrupt Handler</title>
       <para>
         When the interrupt is allocated in
-      <function>snd_mpu401_uart_new()</function>, the private
-      interrupt handler is used, hence you don't have anything else to do
-      than creating the mpu401 stuff. Otherwise, you have to call
-      <function>snd_mpu401_uart_interrupt()</function> explicitly when
-      a UART interrupt is invoked and checked in your own interrupt
-      handler.  
+      <function>snd_mpu401_uart_new()</function>, an exclusive ISA
+      interrupt handler is automatically used, hence you don't have
+      anything else to do than creating the mpu401 stuff.  Otherwise, you
+      have to set <constant>MPU401_INFO_IRQ_HOOK</constant>, and call
+      <function>snd_mpu401_uart_interrupt()</function> explicitly from your
+      own interrupt handler when it has determined that a UART interrupt
+      has occurred.
       </para>
 
       <para>
index 0fd3fbd..f302535 100644 (file)
@@ -377,12 +377,6 @@ struct usb_endpoint_descriptor {
 #define USB_ENDPOINT_NUMBER_MASK       0x0f    /* in bEndpointAddress */
 #define USB_ENDPOINT_DIR_MASK          0x80
 
-#define USB_ENDPOINT_SYNCTYPE          0x0c
-#define USB_ENDPOINT_SYNC_NONE         (0 << 2)
-#define USB_ENDPOINT_SYNC_ASYNC                (1 << 2)
-#define USB_ENDPOINT_SYNC_ADAPTIVE     (2 << 2)
-#define USB_ENDPOINT_SYNC_SYNC         (3 << 2)
-
 #define USB_ENDPOINT_XFERTYPE_MASK     0x03    /* in bmAttributes */
 #define USB_ENDPOINT_XFER_CONTROL      0
 #define USB_ENDPOINT_XFER_ISOC         1
@@ -390,6 +384,17 @@ struct usb_endpoint_descriptor {
 #define USB_ENDPOINT_XFER_INT          3
 #define USB_ENDPOINT_MAX_ADJUSTABLE    0x80
 
+#define USB_ENDPOINT_SYNCTYPE          0x0c
+#define USB_ENDPOINT_SYNC_NONE         (0 << 2)
+#define USB_ENDPOINT_SYNC_ASYNC                (1 << 2)
+#define USB_ENDPOINT_SYNC_ADAPTIVE     (2 << 2)
+#define USB_ENDPOINT_SYNC_SYNC         (3 << 2)
+
+#define USB_ENDPOINT_USAGE_MASK                0x30
+#define USB_ENDPOINT_USAGE_DATA                0x00
+#define USB_ENDPOINT_USAGE_FEEDBACK    0x10
+#define USB_ENDPOINT_USAGE_IMPLICIT_FB 0x20    /* Implicit feedback Data endpoint */
+
 /*-------------------------------------------------------------------------*/
 
 /**
index 1f1d53f..20230db 100644 (file)
 #define MPU401_INFO_INTEGRATED (1 << 2)        /* integrated h/w port */
 #define MPU401_INFO_MMIO       (1 << 3)        /* MMIO access */
 #define MPU401_INFO_TX_IRQ     (1 << 4)        /* independent TX irq */
+#define MPU401_INFO_IRQ_HOOK   (1 << 5)        /* mpu401 irq handler is called
+                                                  from driver irq handler */
 #define MPU401_INFO_NO_ACK     (1 << 6)        /* No ACK cmd needed */
+#define MPU401_INFO_USE_TIMER  (1 << 15)       /* internal */
 
 #define MPU401_MODE_BIT_INPUT          0
 #define MPU401_MODE_BIT_OUTPUT         1
@@ -73,8 +76,7 @@ struct snd_mpu401 {
        unsigned long port;             /* base port of MPU-401 chip */
        unsigned long cport;            /* port + 1 (usually) */
        struct resource *res;           /* port resource */
-       int irq;                        /* IRQ number of MPU-401 chip (-1 = poll) */
-       int irq_flags;
+       int irq;                        /* IRQ number of MPU-401 chip */
 
        unsigned long mode;             /* MPU401_MODE_XXXX */
        int timer_invoked;
@@ -131,7 +133,6 @@ int snd_mpu401_uart_new(struct snd_card *card,
                        unsigned long port,
                        unsigned int info_flags,
                        int irq,
-                       int irq_flags,
                        struct snd_rawmidi ** rrawmidi);
 
 #endif /* __SOUND_MPU401_H */
index 57e71fa..dc36f75 100644 (file)
@@ -825,6 +825,8 @@ int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime,
 int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
                               unsigned int cond,
                               snd_pcm_hw_param_t var);
+int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime,
+                              unsigned int base_rate);
 int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime,
                        unsigned int cond,
                        int var,
index 3687a6c..762af68 100644 (file)
@@ -1067,7 +1067,6 @@ static int onyx_i2c_probe(struct i2c_client *client,
        printk(KERN_DEBUG PFX "created and attached onyx instance\n");
        return 0;
  fail:
-       i2c_set_clientdata(client, NULL);
        kfree(onyx);
        return -ENODEV;
 }
@@ -1112,8 +1111,7 @@ static int onyx_i2c_remove(struct i2c_client *client)
 
        aoa_codec_unregister(&onyx->codec);
        of_node_put(onyx->codec.node);
-       if (onyx->codec_info)
-               kfree(onyx->codec_info);
+       kfree(onyx->codec_info);
        kfree(onyx);
        return 0;
 }
index 3fd1a7e..552b97a 100644 (file)
@@ -1073,10 +1073,10 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
        sdev->pcmid = -1;
        list_del(&ldev->list);
        layouts_list_items--;
+       kfree(ldev);
  outnodev:
        of_node_put(sound);
        layout_device = NULL;
-       kfree(ldev);
        return -ENODEV;
 }
 
index f8c5be4..dc2a440 100644 (file)
@@ -1072,8 +1072,8 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
        long private_size;
        struct user_element *ue;
        int idx, err;
-       
-       if (card->user_ctl_count >= MAX_USER_CONTROLS)
+
+       if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS)
                return -ENOMEM;
        if (info->count < 1)
                return -EINVAL;
index 86d0caf..95d1e78 100644 (file)
@@ -1399,6 +1399,32 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
 
 EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
 
+static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params,
+                                          struct snd_pcm_hw_rule *rule)
+{
+       unsigned int base_rate = (unsigned int)(uintptr_t)rule->private;
+       struct snd_interval *rate;
+
+       rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+       return snd_interval_list(rate, 1, &base_rate, 0);
+}
+
+/**
+ * snd_pcm_hw_rule_noresample - add a rule to allow disabling hw resampling
+ * @runtime: PCM runtime instance
+ * @base_rate: the rate at which the hardware does not resample
+ */
+int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime,
+                              unsigned int base_rate)
+{
+       return snd_pcm_hw_rule_add(runtime, SNDRV_PCM_HW_PARAMS_NORESAMPLE,
+                                  SNDRV_PCM_HW_PARAM_RATE,
+                                  snd_pcm_hw_rule_noresample_func,
+                                  (void *)(uintptr_t)base_rate,
+                                  SNDRV_PCM_HW_PARAM_RATE, -1);
+}
+EXPORT_SYMBOL(snd_pcm_hw_rule_noresample);
+
 static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params,
                                  snd_pcm_hw_param_t var)
 {
@@ -1761,6 +1787,10 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
        snd_pcm_uframes_t avail = 0;
        long wait_time, tout;
 
+       init_waitqueue_entry(&wait, current);
+       set_current_state(TASK_INTERRUPTIBLE);
+       add_wait_queue(&runtime->tsleep, &wait);
+
        if (runtime->no_period_wakeup)
                wait_time = MAX_SCHEDULE_TIMEOUT;
        else {
@@ -1771,16 +1801,32 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
                }
                wait_time = msecs_to_jiffies(wait_time * 1000);
        }
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&runtime->tsleep, &wait);
+
        for (;;) {
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
                }
+
+               /*
+                * We need to check if space became available already
+                * (and thus the wakeup happened already) first to close
+                * the race of space already having become available.
+                * This check must happen after been added to the waitqueue
+                * and having current state be INTERRUPTIBLE.
+                */
+               if (is_playback)
+                       avail = snd_pcm_playback_avail(runtime);
+               else
+                       avail = snd_pcm_capture_avail(runtime);
+               if (avail >= runtime->twake)
+                       break;
                snd_pcm_stream_unlock_irq(substream);
-               tout = schedule_timeout_interruptible(wait_time);
+
+               tout = schedule_timeout(wait_time);
+
                snd_pcm_stream_lock_irq(substream);
+               set_current_state(TASK_INTERRUPTIBLE);
                switch (runtime->status->state) {
                case SNDRV_PCM_STATE_SUSPENDED:
                        err = -ESTRPIPE;
@@ -1806,14 +1852,9 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
                        err = -EIO;
                        break;
                }
-               if (is_playback)
-                       avail = snd_pcm_playback_avail(runtime);
-               else
-                       avail = snd_pcm_capture_avail(runtime);
-               if (avail >= runtime->twake)
-                       break;
        }
  _endloop:
+       set_current_state(TASK_RUNNING);
        remove_wait_queue(&runtime->tsleep, &wait);
        *availp = avail;
        return err;
index 7c1cbf0..67ebf1c 100644 (file)
@@ -328,6 +328,8 @@ int snd_timer_close(struct snd_timer_instance *timeri)
                mutex_unlock(&register_mutex);
        } else {
                timer = timeri->timer;
+               if (snd_BUG_ON(!timer))
+                       goto out;
                /* wait, until the active callback is finished */
                spin_lock_irq(&timer->lock);
                while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
@@ -353,6 +355,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
                }
                mutex_unlock(&register_mutex);
        }
+ out:
        if (timeri->private_free)
                timeri->private_free(timeri);
        kfree(timeri->owner);
@@ -531,6 +534,8 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
        if (err < 0)
                return err;
        timer = timeri->timer;
+       if (!timer)
+               return -EINVAL;
        spin_lock_irqsave(&timer->lock, flags);
        timeri->cticks = timeri->ticks;
        timeri->pticks = 0;
index 149d05a..1c02852 100644 (file)
@@ -86,8 +86,7 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard)
        }
 
        err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0,
-                                 irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0,
-                                 NULL);
+                                 irq[dev], NULL);
        if (err < 0) {
                printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
                goto _err;
index 2af0999..9d01c18 100644 (file)
@@ -3,7 +3,7 @@
  *  Routines for control of MPU-401 in UART mode
  *
  *  MPU-401 supports UART mode which is not capable generate transmit
- *  interrupts thus output is done via polling. Also, if irq < 0, then
+ *  interrupts thus output is done via polling. Without interrupt,
  *  input is done also via polling. Do not expect good performance.
  *
  *
@@ -374,7 +374,7 @@ snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
                        /* first time - flush FIFO */
                        while (max-- > 0)
                                mpu->read(mpu, MPU401D(mpu));
-                       if (mpu->irq < 0)
+                       if (mpu->info_flags & MPU401_INFO_USE_TIMER)
                                snd_mpu401_uart_add_timer(mpu, 1);
                }
                
@@ -383,7 +383,7 @@ snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
                snd_mpu401_uart_input_read(mpu);
                spin_unlock_irqrestore(&mpu->input_lock, flags);
        } else {
-               if (mpu->irq < 0)
+               if (mpu->info_flags & MPU401_INFO_USE_TIMER)
                        snd_mpu401_uart_remove_timer(mpu, 1);
                clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
        }
@@ -496,7 +496,7 @@ static struct snd_rawmidi_ops snd_mpu401_uart_input =
 static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
 {
        struct snd_mpu401 *mpu = rmidi->private_data;
-       if (mpu->irq_flags && mpu->irq >= 0)
+       if (mpu->irq >= 0)
                free_irq(mpu->irq, (void *) mpu);
        release_and_free_resource(mpu->res);
        kfree(mpu);
@@ -509,8 +509,7 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
  * @hardware: the hardware type, MPU401_HW_XXXX
  * @port: the base address of MPU401 port
  * @info_flags: bitflags MPU401_INFO_XXX
- * @irq: the irq number, -1 if no interrupt for mpu
- * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved.
+ * @irq: the ISA irq number, -1 if not to be allocated
  * @rrawmidi: the pointer to store the new rawmidi instance
  *
  * Creates a new MPU-401 instance.
@@ -525,7 +524,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
                        unsigned short hardware,
                        unsigned long port,
                        unsigned int info_flags,
-                       int irq, int irq_flags,
+                       int irq,
                        struct snd_rawmidi ** rrawmidi)
 {
        struct snd_mpu401 *mpu;
@@ -577,8 +576,8 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
                mpu->cport = port + 2;
        else
                mpu->cport = port + 1;
-       if (irq >= 0 && irq_flags) {
-               if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags,
+       if (irq >= 0) {
+               if (request_irq(irq, snd_mpu401_uart_interrupt, IRQF_DISABLED,
                                "MPU401 UART", (void *) mpu)) {
                        snd_printk(KERN_ERR "mpu401_uart: "
                                   "unable to grab IRQ %d\n", irq);
@@ -586,9 +585,10 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
                        return -EBUSY;
                }
        }
+       if (irq < 0 && !(info_flags & MPU401_INFO_IRQ_HOOK))
+               info_flags |= MPU401_INFO_USE_TIMER;
        mpu->info_flags = info_flags;
        mpu->irq = irq;
-       mpu->irq_flags = irq_flags;
        if (card->shortname[0])
                snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI",
                         card->shortname);
index 4400308..cd094ec 100644 (file)
@@ -51,7 +51,6 @@ struct isight {
        struct fw_unit *unit;
        struct fw_device *device;
        u64 audio_base;
-       struct fw_address_handler iris_handler;
        struct snd_pcm_substream *pcm;
        struct mutex mutex;
        struct iso_packets_buffer buffer;
index 3cb75bc..a87a2b5 100644 (file)
@@ -204,7 +204,7 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard
 
        if (mpu_port[dev] > 0) {
                if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
-                                       mpu_port[dev], 0, mpu_irq[dev], IRQF_DISABLED,
+                                       mpu_port[dev], 0, mpu_irq[dev],
                                        NULL) < 0)
                        printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", mpu_port[dev]);
        }
index 20becc8..706effd 100644 (file)
@@ -256,7 +256,6 @@ static int __devinit snd_card_als100_probe(int dev,
                                        mpu_type,
                                        mpu_port[dev], 0, 
                                        mpu_irq[dev],
-                                       mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0,
                                        NULL) < 0)
                        snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]);
        }
index aac8dc1..b7bdbf3 100644 (file)
@@ -234,8 +234,7 @@ static int __devinit snd_card_azt2320_probe(int dev,
        if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
                if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320,
                                mpu_port[dev], 0,
-                               mpu_irq[dev], IRQF_DISABLED,
-                               NULL) < 0)
+                               mpu_irq[dev], NULL) < 0)
                        snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]);
        }
 
index fe79a16..dca69f8 100644 (file)
@@ -597,7 +597,7 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
        if (mpuport[dev] != SNDRV_AUTO_PORT) {
                if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
                                        mpuport[dev], 0, mpuirq[dev],
-                                       IRQF_DISABLED, NULL) < 0)
+                                       NULL) < 0)
                        printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n",
                                mpuport[dev]);
        }
index cb9153e..409fa0a 100644 (file)
@@ -131,7 +131,6 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
                        mpu_irq[n] = -1;
                if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232,
                                        mpu_port[n], 0, mpu_irq[n],
-                                       mpu_irq[n] >= 0 ? IRQF_DISABLED : 0,
                                        NULL) < 0)
                        dev_warn(dev, "MPU401 not detected\n");
        }
index 999dc1e..0dbde46 100644 (file)
@@ -449,8 +449,7 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
                        mpu_irq[dev] = -1;
                if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232,
                                        mpu_port[dev], 0,
-                                       mpu_irq[dev],
-                                       mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0, NULL) < 0)
+                                       mpu_irq[dev], NULL) < 0)
                        printk(KERN_WARNING IDENT ": MPU401 not detected\n");
        }
 
index 0cde813..5493e9e 100644 (file)
@@ -174,7 +174,7 @@ static int __devinit snd_es1688_probe(struct snd_card *card, unsigned int n)
                        chip->mpu_port > 0) {
                error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
                                chip->mpu_port, 0,
-                               mpu_irq[n], IRQF_DISABLED, NULL);
+                               mpu_irq[n], NULL);
                if (error < 0)
                        return error;
        }
index fb4d6b3..aeee8f8 100644 (file)
@@ -2160,8 +2160,8 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
 
        if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
                err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
-                                         mpu_port[dev], 0,
-                                         irq[dev], 0, &chip->rmidi);
+                                         mpu_port[dev], MPU401_INFO_IRQ_HOOK,
+                                         -1, &chip->rmidi);
                if (err < 0)
                        return err;
        }
index ee54df0..e51d324 100644 (file)
@@ -585,8 +585,7 @@ static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n)
 
        if (mpu_port[n] >= 0) {
                err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
-                                         mpu_port[n], 0, mpu_irq[n],
-                                         IRQF_DISABLED, NULL);
+                                         mpu_port[n], 0, mpu_irq[n], NULL);
                if (err < 0)
                        goto error;
        }
index 008e8e5..c4733c0 100644 (file)
@@ -317,8 +317,7 @@ static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n)
 
        if (es1688->mpu_port >= 0x300) {
                error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
-                               es1688->mpu_port, 0,
-                               mpu_irq[n], IRQF_DISABLED, NULL);
+                               es1688->mpu_port, 0, mpu_irq[n], NULL);
                if (error < 0)
                        goto out;
        }
index 91d6023..0961e2c 100644 (file)
@@ -600,7 +600,7 @@ static int __devinit snd_msnd_attach(struct snd_card *card)
                                          mpu_io[0],
                                          MPU401_MODE_INPUT |
                                          MPU401_MODE_OUTPUT,
-                                         mpu_irq[0], IRQF_DISABLED,
+                                         mpu_irq[0],
                                          &chip->rmidi);
                if (err < 0) {
                        printk(KERN_ERR LOGNAME
index 9b915e2..de99f47 100644 (file)
@@ -707,8 +707,9 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
        }
        if (midi_port[dev] >= 0x300 && midi_port[dev] < 0x340) {
                if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_OPL3SA2,
-                                              midi_port[dev], 0,
-                                              xirq, 0, &chip->rmidi)) < 0)
+                                              midi_port[dev],
+                                              MPU401_INFO_IRQ_HOOK, -1,
+                                              &chip->rmidi)) < 0)
                        return err;
        }
        sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
index 8c24102..d94d0f3 100644 (file)
@@ -1377,8 +1377,7 @@ static int __devinit snd_miro_probe(struct snd_card *card)
                rmidi = NULL;
        else {
                error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
-                               mpu_port, 0, miro->mpu_irq, IRQF_DISABLED,
-                               &rmidi);
+                               mpu_port, 0, miro->mpu_irq, &rmidi);
                if (error < 0)
                        snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n",
                                   mpu_port);
index c35dc68..346e12b 100644 (file)
@@ -914,7 +914,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
                rmidi = NULL;
        else {
                error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
-                               mpu_port, 0, mpu_irq, IRQF_DISABLED, &rmidi);
+                               mpu_port, 0, mpu_irq, &rmidi);
                if (error)
                        snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n",
                                   mpu_port);
index 8ccbcdd..54e3c2c 100644 (file)
@@ -322,7 +322,6 @@ static int __devinit snd_jazz16_probe(struct device *devptr, unsigned int dev)
                                        MPU401_HW_MPU401,
                                        mpu_port[dev], 0,
                                        mpu_irq[dev],
-                                       mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0,
                                        NULL) < 0)
                        snd_printk(KERN_ERR "no MPU-401 device at 0x%lx\n",
                                        mpu_port[dev]);
index 4d1c5a3..237f8bd 100644 (file)
@@ -394,8 +394,9 @@ static int __devinit snd_sb16_probe(struct snd_card *card, int dev)
 
        if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
                if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB,
-                                              chip->mpu_port, 0,
-                                              xirq, 0, &chip->rmidi)) < 0)
+                                              chip->mpu_port,
+                                              MPU401_INFO_IRQ_HOOK, -1,
+                                              &chip->rmidi)) < 0)
                        return err;
                chip->rmidi_callback = snd_mpu401_uart_interrupt;
        }
index 9a8bbf6..207c161 100644 (file)
@@ -658,8 +658,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
                if (snd_mpu401_uart_new(card, 0,
                                        MPU401_HW_MPU401,
                                        mpu_port[dev], 0,
-                                       mpu_irq[dev], IRQF_DISABLED,
-                                       NULL) < 0)
+                                       mpu_irq[dev], NULL) < 0)
                        snd_printk(KERN_ERR "no MPU-401 device at 0x%lx ?\n",
                                        mpu_port[dev]);
        }
index e2d5d2d..f2379e1 100644 (file)
@@ -825,8 +825,7 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum,
        int err;
 
        err = snd_mpu401_uart_new(card, devnum, MPU401_HW_MPU401, port,
-                                 MPU401_INFO_INTEGRATED, irq, IRQF_DISABLED,
-                                 &rawmidi);
+                                 MPU401_INFO_INTEGRATED, irq, &rawmidi);
        if (err == 0) {
                struct snd_mpu401 *mpu = rawmidi->private_data;
                mpu->open_input = mpu401_open;
index 711670e..83f291d 100644 (file)
@@ -449,8 +449,7 @@ snd_wavefront_probe (struct snd_card *card, int dev)
        if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) {
                err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232,
                                          cs4232_mpu_port[dev], 0,
-                                         cs4232_mpu_irq[dev], IRQF_DISABLED,
-                                         NULL);
+                                         cs4232_mpu_irq[dev], NULL);
                if (err < 0) {
                        snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n");
                        return err;
index 8f7d175..6f13ab4 100644 (file)
@@ -63,13 +63,13 @@ static int pcm_set_speed(int arg)
 
        if (pcm_channels & 2)
        {
-               foo = ((CLOCK_TICK_RATE / 2) + (arg / 2)) / arg;
-               arg = ((CLOCK_TICK_RATE / 2) + (foo / 2)) / foo;
+               foo = ((PIT_TICK_RATE / 2) + (arg / 2)) / arg;
+               arg = ((PIT_TICK_RATE / 2) + (foo / 2)) / foo;
        }
        else
        {
-               foo = (CLOCK_TICK_RATE + (arg / 2)) / arg;
-               arg = (CLOCK_TICK_RATE + (foo / 2)) / foo;
+               foo = (PIT_TICK_RATE + (arg / 2)) / arg;
+               arg = (PIT_TICK_RATE + (foo / 2)) / foo;
        }
 
        pcm_speed = arg;
index 9b800ce..2fc0624 100644 (file)
@@ -673,7 +673,8 @@ static void configure_nonsound_components(void)
 
        if (pss_cdrom_port == -1) {     /* If cdrom port enablation wasn't requested */
                printk(KERN_INFO "PSS: CDROM port not enabled.\n");
-       } else if (check_region(pss_cdrom_port, 2)) {
+       } else if (!request_region(pss_cdrom_port, 2, "PSS CDROM")) {
+               pss_cdrom_port = -1;
                printk(KERN_ERR "PSS: CDROM I/O port conflict.\n");
        } else {
                set_io_base(devc, CONF_CDROM, pss_cdrom_port);
@@ -1232,7 +1233,8 @@ static void __exit cleanup_pss(void)
                if(pssmpu)
                        unload_pss_mpu(&cfg_mpu);
                unload_pss(&cfg);
-       }
+       } else if (pss_cdrom_port != -1)
+               release_region(pss_cdrom_port, 2);
 
        if(!pss_keep_settings)  /* Keep hardware settings if asked */
        {
index 50abf5b..8816804 100644 (file)
@@ -1,5 +1,10 @@
 # ALSA PCI drivers
 
+config SND_TEA575X
+       tristate
+       depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2
+       default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2
+
 menuconfig SND_PCI
        bool "PCI sound devices"
        depends on PCI
@@ -563,11 +568,6 @@ config SND_FM801_TEA575X_BOOL
          FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and
          SF64-PCR) into the snd-fm801 driver.
 
-config SND_TEA575X
-       tristate
-       depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2
-       default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2
-
 source "sound/pci/hda/Kconfig"
 
 config SND_HDSP
index 200c9a1..a872d0a 100644 (file)
@@ -1909,6 +1909,7 @@ static unsigned int ad1981_jacks_whitelist[] = {
        0x103c0944, /* HP nc6220 */
        0x103c0934, /* HP nc8220 */
        0x103c006d, /* HP nx9105 */
+       0x103c300d, /* HP Compaq dc5100 SFF(PT003AW) */
        0x17340088, /* FSC Scenic-W */
        0 /* end */
 };
index a9c1af3..0462869 100644 (file)
@@ -931,8 +931,9 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
 
        if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000,
                                        iobase + ALS4K_IOB_30_MIDI_DATA,
-                                       MPU401_INFO_INTEGRATED,
-                                       pci->irq, 0, &chip->rmidi)) < 0) {
+                                       MPU401_INFO_INTEGRATED |
+                                       MPU401_INFO_IRQ_HOOK,
+                                       -1, &chip->rmidi)) < 0) {
                printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n",
                                iobase + ALS4K_IOB_30_MIDI_DATA);
                goto out_err;
index 65b7ca1..bd47521 100644 (file)
@@ -631,13 +631,12 @@ struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
        if (!p_cache)
                return NULL;
 
-       p_cache->p_info =
-               kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL);
+       p_cache->p_info = kzalloc(sizeof(*p_cache->p_info) * control_count,
+                                 GFP_KERNEL);
        if (!p_cache->p_info) {
                kfree(p_cache);
                return NULL;
        }
-       memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count);
        p_cache->cache_size_in_bytes = size_in_bytes;
        p_cache->control_count = control_count;
        p_cache->p_cache = p_dsp_control_buffer;
index 0dc8d25..e6c6a0f 100644 (file)
@@ -84,7 +84,7 @@ static int __devinit snd_vortex_midi(vortex_t * vortex)
 #ifdef VORTEX_MPU401_LEGACY
        if ((temp =
             snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_MPU401, 0x330,
-                                0, 0, 0, &rmidi)) != 0) {
+                                MPU401_INFO_IRQ_HOOK, -1, &rmidi)) != 0) {
                hwwrite(vortex->mmio, VORTEX_CTRL,
                        (hwread(vortex->mmio, VORTEX_CTRL) &
                         ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
@@ -94,8 +94,8 @@ static int __devinit snd_vortex_midi(vortex_t * vortex)
        port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA);
        if ((temp =
             snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port,
-                                MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO,
-                                0, 0, &rmidi)) != 0) {
+                                MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO |
+                                MPU401_INFO_IRQ_HOOK, -1, &rmidi)) != 0) {
                hwwrite(vortex->mmio, VORTEX_CTRL,
                        (hwread(vortex->mmio, VORTEX_CTRL) &
                         ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
index e4d76a2..d24fe42 100644 (file)
@@ -2625,16 +2625,19 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        int err;
 
        snd_azf3328_dbgcallenter();
-       if (dev >= SNDRV_CARDS)
-               return -ENODEV;
+       if (dev >= SNDRV_CARDS) {
+               err = -ENODEV;
+               goto out;
+       }
        if (!enable[dev]) {
                dev++;
-               return -ENOENT;
+               err = -ENOENT;
+               goto out;
        }
 
        err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
        if (err < 0)
-               return err;
+               goto out;
 
        strcpy(card->driver, "AZF3328");
        strcpy(card->shortname, "Aztech AZF3328 (PCI168)");
@@ -2649,8 +2652,9 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
           since our hardware ought to be similar, thus use same ID. */
        err = snd_mpu401_uart_new(
                card, 0,
-               MPU401_HW_AZT2320, chip->mpu_io, MPU401_INFO_INTEGRATED,
-               pci->irq, 0, &chip->rmidi
+               MPU401_HW_AZT2320, chip->mpu_io,
+               MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
+               -1, &chip->rmidi
        );
        if (err < 0) {
                snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n",
index 9cf99fb..da9c732 100644 (file)
@@ -3228,8 +3228,9 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
                if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
                                               iomidi,
                                               (integrated_midi ?
-                                               MPU401_INFO_INTEGRATED : 0),
-                                              cm->irq, 0, &cm->rmidi)) < 0) {
+                                               MPU401_INFO_INTEGRATED : 0) |
+                                              MPU401_INFO_IRQ_HOOK,
+                                              -1, &cm->rmidi)) < 0) {
                        printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi);
                }
        }
index 457d211..2c86226 100644 (file)
@@ -404,7 +404,7 @@ int ct_alsa_pcm_create(struct ct_atc *atc,
        int err;
        int playback_count, capture_count;
 
-       playback_count = (IEC958 == device) ? 1 : 8;
+       playback_count = (IEC958 == device) ? 1 : 256;
        capture_count = (FRONT == device) ? 1 : 0;
        err = snd_pcm_new(atc->card, "ctxfi", device,
                          playback_count, capture_count, &pcm);
index c749fa7..e134b3a 100644 (file)
@@ -20,7 +20,7 @@
 #include "cthardware.h"
 #include <linux/slab.h>
 
-#define SRC_RESOURCE_NUM       64
+#define SRC_RESOURCE_NUM       256
 #define SRCIMP_RESOURCE_NUM    256
 
 static unsigned int conj_mask;
index b23adfc..e6da60e 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef CTVMEM_H
 #define CTVMEM_H
 
-#define CT_PTP_NUM     1       /* num of device page table pages */
+#define CT_PTP_NUM     4       /* num of device page table pages */
 
 #include <linux/mutex.h>
 #include <linux/list.h>
index 622bace..e22b8e2 100644 (file)
@@ -1146,6 +1146,11 @@ static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream)
                kfree(epcm);
                return err;
        }
+       err = snd_pcm_hw_rule_noresample(runtime, 48000);
+       if (err < 0) {
+               kfree(epcm);
+               return err;
+       }
        mix = &emu->pcm_mixer[substream->number];
        for (i = 0; i < 4; i++)
                mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i;
index 26a5a2f..718a264 100644 (file)
@@ -1854,8 +1854,9 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci,
                }
        }
        if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
-                               chip->mpu_port, MPU401_INFO_INTEGRATED,
-                               chip->irq, 0, &chip->rmidi) < 0) {
+                               chip->mpu_port,
+                               MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
+                               -1, &chip->rmidi) < 0) {
                printk(KERN_ERR "es1938: unable to initialize MPU-401\n");
        } else {
                // this line is vital for MIDI interrupt handling on ess-solo1
index 99ea932..407e4ab 100644 (file)
@@ -2843,8 +2843,9 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci,
        if (enable_mpu[dev]) {
                if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
                                               chip->io_port + ESM_MPU401_PORT,
-                                              MPU401_INFO_INTEGRATED,
-                                              chip->irq, 0, &chip->rmidi)) < 0) {
+                                              MPU401_INFO_INTEGRATED |
+                                              MPU401_INFO_IRQ_HOOK,
+                                              -1, &chip->rmidi)) < 0) {
                        printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n");
                }
        }
index f9123f0..c55b1b3 100644 (file)
@@ -1306,8 +1306,9 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
        }
        if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801,
                                       FM801_REG(chip, MPU401_DATA),
-                                      MPU401_INFO_INTEGRATED,
-                                      chip->irq, 0, &chip->rmidi)) < 0) {
+                                      MPU401_INFO_INTEGRATED |
+                                      MPU401_INFO_IRQ_HOOK,
+                                      -1, &chip->rmidi)) < 0) {
                snd_card_free(card);
                return err;
        }
index be58bf2..2e5876c 100644 (file)
@@ -476,8 +476,8 @@ static const struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
 
 static const struct alc_config_preset alc268_presets[] = {
        [ALC267_QUANTA_IL1] = {
-               .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer,
-                           alc268_capture_nosrc_mixer },
+               .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_nosrc_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc267_quanta_il1_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -492,8 +492,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_3ST] = {
-               .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_base_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
                .dac_nids = alc268_dac_nids,
@@ -507,8 +507,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .input_mux = &alc268_capture_source,
        },
        [ALC268_TOSHIBA] = {
-               .mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_toshiba_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_toshiba_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -525,8 +525,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_ACER] = {
-               .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_acer_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_acer_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -543,8 +543,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_ACER_DMIC] = {
-               .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_acer_dmic_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_acer_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -561,9 +561,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_ACER_ASPIRE_ONE] = {
-               .mixers = { alc268_acer_aspire_one_mixer,
-                           alc268_beep_mixer,
-                           alc268_capture_nosrc_mixer },
+               .mixers = { alc268_acer_aspire_one_mixer, alc268_beep_mixer},
+               .cap_mixer = alc268_capture_nosrc_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_acer_aspire_one_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -579,8 +578,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_DELL] = {
-               .mixers = { alc268_dell_mixer, alc268_beep_mixer,
-                           alc268_capture_nosrc_mixer },
+               .mixers = { alc268_dell_mixer, alc268_beep_mixer},
+               .cap_mixer = alc268_capture_nosrc_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_dell_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -596,8 +595,8 @@ static const struct alc_config_preset alc268_presets[] = {
                .init_hook = alc_inithook,
        },
        [ALC268_ZEPTO] = {
-               .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
-                           alc268_beep_mixer },
+               .mixers = { alc268_base_mixer, alc268_beep_mixer },
+               .cap_mixer = alc268_capture_alt_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_toshiba_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -616,7 +615,8 @@ static const struct alc_config_preset alc268_presets[] = {
        },
 #ifdef CONFIG_SND_DEBUG
        [ALC268_TEST] = {
-               .mixers = { alc268_test_mixer, alc268_capture_mixer },
+               .mixers = { alc268_test_mixer },
+               .cap_mixer = alc268_capture_mixer,
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_volume_init_verbs,
                                alc268_beep_init_verbs },
index 14fdcf2..5ac0e21 100644 (file)
@@ -531,17 +531,10 @@ static const struct snd_pci_quirk alc269_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC),
-       SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC),
-       SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
-                     ALC269_DMIC),
-       SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
-                     ALC269_DMIC),
-       SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC),
-       SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC),
        SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO),
        SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
        SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC),
index 3e7850c..f3aefef 100644 (file)
@@ -579,9 +579,13 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
                return -1;
        }
        recursive++;
-       for (i = 0; i < nums; i++)
+       for (i = 0; i < nums; i++) {
+               unsigned int type = get_wcaps_type(get_wcaps(codec, conn[i]));
+               if (type == AC_WID_PIN || type == AC_WID_AUD_OUT)
+                       continue;
                if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0)
                        return i;
+       }
        return -1;
 }
 EXPORT_SYMBOL_HDA(snd_hda_get_conn_index);
index 28ce17d..c34f730 100644 (file)
@@ -144,25 +144,17 @@ static int cea_sampling_frequencies[8] = {
        SNDRV_PCM_RATE_192000,  /* 7: 192000Hz */
 };
 
-static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, hda_nid_t nid,
+static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid,
                                        int byte_index)
 {
        unsigned int val;
 
        val = snd_hda_codec_read(codec, nid, 0,
                                        AC_VERB_GET_HDMI_ELDD, byte_index);
-
 #ifdef BE_PARANOID
        printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val);
 #endif
-
-       if ((val & AC_ELDD_ELD_VALID) == 0) {
-               snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n",
-                                                               byte_index);
-               val = 0;
-       }
-
-       return val & AC_ELDD_ELD_DATA;
+       return val;
 }
 
 #define GRAB_BITS(buf, byte, lowbit, bits)             \
@@ -344,11 +336,26 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
        if (!buf)
                return -ENOMEM;
 
-       for (i = 0; i < size; i++)
-               buf[i] = hdmi_get_eld_byte(codec, nid, i);
+       for (i = 0; i < size; i++) {
+               unsigned int val = hdmi_get_eld_data(codec, nid, i);
+               if (!(val & AC_ELDD_ELD_VALID)) {
+                       if (!i) {
+                               snd_printd(KERN_INFO
+                                          "HDMI: invalid ELD data\n");
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       snd_printd(KERN_INFO
+                                 "HDMI: invalid ELD data byte %d\n", i);
+                       val = 0;
+               } else
+                       val &= AC_ELDD_ELD_DATA;
+               buf[i] = val;
+       }
 
        ret = hdmi_update_eld(eld, buf, size);
 
+error:
        kfree(buf);
        return ret;
 }
index 47d6ffc..c45f3e6 100644 (file)
@@ -375,7 +375,7 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx)
 static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
                         unsigned int *idxp)
 {
-       int i;
+       int i, idx;
        hda_nid_t nid;
 
        nid = codec->start_nid;
@@ -384,9 +384,11 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
                type = get_wcaps_type(get_wcaps(codec, nid));
                if (type != AC_WID_AUD_IN)
                        continue;
-               *idxp = snd_hda_get_conn_index(codec, nid, pin, false);
-               if (*idxp >= 0)
+               idx = snd_hda_get_conn_index(codec, nid, pin, false);
+               if (idx >= 0) {
+                       *idxp = idx;
                        return nid;
+               }
        }
        return 0;
 }
@@ -533,7 +535,7 @@ static int add_volume(struct hda_codec *codec, const char *name,
                      int index, unsigned int pval, int dir,
                      struct snd_kcontrol **kctlp)
 {
-       char tmp[32];
+       char tmp[44];
        struct snd_kcontrol_new knew =
                HDA_CODEC_VOLUME_IDX(tmp, index, 0, 0, HDA_OUTPUT);
        knew.private_value = pval;
index 502fc94..7696d05 100644 (file)
@@ -3348,6 +3348,8 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t pin,
 
 #define MAX_AUTO_DACS  5
 
+#define DAC_SLAVE_FLAG 0x8000  /* filled dac is a slave */
+
 /* fill analog DAC list from the widget tree */
 static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs)
 {
@@ -3370,16 +3372,26 @@ static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs)
 /* fill pin_dac_pair list from the pin and dac list */
 static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins,
                              int num_pins, hda_nid_t *dacs, int *rest,
-                             struct pin_dac_pair *filled, int type)
+                             struct pin_dac_pair *filled, int nums, 
+                             int type)
 {
-       int i, nums;
+       int i, start = nums;
 
-       nums = 0;
-       for (i = 0; i < num_pins; i++) {
+       for (i = 0; i < num_pins; i++, nums++) {
                filled[nums].pin = pins[i];
                filled[nums].type = type;
                filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest);
-               nums++;
+               if (filled[nums].dac) 
+                       continue;
+               if (filled[start].dac && get_connection_index(codec, pins[i], filled[start].dac) >= 0) {
+                       filled[nums].dac = filled[start].dac | DAC_SLAVE_FLAG;
+                       continue;
+               }
+               if (filled[0].dac && get_connection_index(codec, pins[i], filled[0].dac) >= 0) {
+                       filled[nums].dac = filled[0].dac | DAC_SLAVE_FLAG;
+                       continue;
+               }
+               snd_printdd("Failed to find a DAC for pin 0x%x", pins[i]);
        }
        return nums;
 }
@@ -3395,19 +3407,19 @@ static void cx_auto_parse_output(struct hda_codec *codec)
        rest = fill_cx_auto_dacs(codec, dacs);
        /* parse all analog output pins */
        nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs,
-                                 dacs, &rest, spec->dac_info,
-                                 AUTO_PIN_LINE_OUT);
-       nums += fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs,
-                                 dacs, &rest, spec->dac_info + nums,
-                                 AUTO_PIN_HP_OUT);
-       nums += fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs,
-                                 dacs, &rest, spec->dac_info + nums,
-                                 AUTO_PIN_SPEAKER_OUT);
+                         dacs, &rest, spec->dac_info, 0,
+                         AUTO_PIN_LINE_OUT);
+       nums = fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs,
+                         dacs, &rest, spec->dac_info, nums,
+                         AUTO_PIN_HP_OUT);
+       nums = fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs,
+                         dacs, &rest, spec->dac_info, nums,
+                         AUTO_PIN_SPEAKER_OUT);
        spec->dac_info_filled = nums;
        /* fill multiout struct */
        for (i = 0; i < nums; i++) {
                hda_nid_t dac = spec->dac_info[i].dac;
-               if (!dac)
+               if (!dac || (dac & DAC_SLAVE_FLAG))
                        continue;
                switch (spec->dac_info[i].type) {
                case AUTO_PIN_LINE_OUT:
@@ -3862,7 +3874,7 @@ static void cx_auto_parse_input(struct hda_codec *codec)
        }
        if (imux->num_items >= 2 && cfg->num_inputs == imux->num_items)
                cx_auto_check_auto_mic(codec);
-       if (imux->num_items > 1 && !spec->auto_mic) {
+       if (imux->num_items > 1) {
                for (i = 1; i < imux->num_items; i++) {
                        if (spec->imux_info[i].adc != spec->imux_info[0].adc) {
                                spec->adc_switching = 1;
@@ -4035,6 +4047,8 @@ static void cx_auto_init_output(struct hda_codec *codec)
                nid = spec->dac_info[i].dac;
                if (!nid)
                        nid = spec->multiout.dac_nids[0];
+               else if (nid & DAC_SLAVE_FLAG)
+                       nid &= ~DAC_SLAVE_FLAG;
                select_connection(codec, spec->dac_info[i].pin, nid);
        }
        if (spec->auto_mute) {
@@ -4167,9 +4181,11 @@ static int try_add_pb_volume(struct hda_codec *codec, hda_nid_t dac,
                             hda_nid_t pin, const char *name, int idx)
 {
        unsigned int caps;
-       caps = query_amp_caps(codec, dac, HDA_OUTPUT);
-       if (caps & AC_AMPCAP_NUM_STEPS)
-               return cx_auto_add_pb_volume(codec, dac, name, idx);
+       if (dac && !(dac & DAC_SLAVE_FLAG)) {
+               caps = query_amp_caps(codec, dac, HDA_OUTPUT);
+               if (caps & AC_AMPCAP_NUM_STEPS)
+                       return cx_auto_add_pb_volume(codec, dac, name, idx);
+       }
        caps = query_amp_caps(codec, pin, HDA_OUTPUT);
        if (caps & AC_AMPCAP_NUM_STEPS)
                return cx_auto_add_pb_volume(codec, pin, name, idx);
@@ -4191,8 +4207,7 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
        for (i = 0; i < spec->dac_info_filled; i++) {
                const char *label;
                int idx, type;
-               if (!spec->dac_info[i].dac)
-                       continue;
+               hda_nid_t dac = spec->dac_info[i].dac;
                type = spec->dac_info[i].type;
                if (type == AUTO_PIN_LINE_OUT)
                        type = spec->autocfg.line_out_type;
@@ -4211,7 +4226,7 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
                        idx = num_spk++;
                        break;
                }
-               err = try_add_pb_volume(codec, spec->dac_info[i].dac,
+               err = try_add_pb_volume(codec, dac,
                                        spec->dac_info[i].pin,
                                        label, idx);
                if (err < 0)
index e125c60..7cabd73 100644 (file)
@@ -565,11 +565,11 @@ static void alc_hp_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
-       if (!spec->automute)
-               return;
        spec->jack_present =
                detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
                             spec->autocfg.hp_pins);
+       if (!spec->automute)
+               return;
        update_speakers(codec);
 }
 
@@ -578,11 +578,11 @@ static void alc_line_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
-       if (!spec->automute || !spec->detect_line)
-               return;
        spec->line_jack_present =
                detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
                             spec->autocfg.line_out_pins);
+       if (!spec->automute || !spec->detect_line)
+               return;
        update_speakers(codec);
 }
 
@@ -1784,6 +1784,7 @@ static const char * const alc_slave_vols[] = {
        "Speaker Playback Volume",
        "Mono Playback Volume",
        "Line-Out Playback Volume",
+       "PCM Playback Volume",
        NULL,
 };
 
@@ -1798,6 +1799,7 @@ static const char * const alc_slave_sws[] = {
        "Mono Playback Switch",
        "IEC958 Playback Switch",
        "Line-Out Playback Switch",
+       "PCM Playback Switch",
        NULL,
 };
 
@@ -3081,16 +3083,22 @@ static void alc_auto_init_multi_out(struct hda_codec *codec)
 static void alc_auto_init_extra_out(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t pin;
+       hda_nid_t pin, dac;
 
        pin = spec->autocfg.hp_pins[0];
-       if (pin)
-               alc_auto_set_output_and_unmute(codec, pin, PIN_HP,
-                                                 spec->multiout.hp_nid);
+       if (pin) {
+               dac = spec->multiout.hp_nid;
+               if (!dac)
+                       dac = spec->multiout.dac_nids[0];
+               alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
+       }
        pin = spec->autocfg.speaker_pins[0];
-       if (pin)
-               alc_auto_set_output_and_unmute(codec, pin, PIN_OUT,
-                                       spec->multiout.extra_out_nid[0]);
+       if (pin) {
+               dac = spec->multiout.extra_out_nid[0];
+               if (!dac)
+                       dac = spec->multiout.dac_nids[0];
+               alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
+       }
 }
 
 /*
@@ -4484,6 +4492,22 @@ static void alc269_fixup_pcm_44k(struct hda_codec *codec,
        spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
 }
 
+static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
+                                    const struct alc_fixup *fix, int action)
+{
+       int coef;
+
+       if (action != ALC_FIXUP_ACT_INIT)
+               return;
+       /* The digital-mic unit sends PDM (differential signal) instead of
+        * the standard PCM, thus you can't record a valid mono stream as is.
+        * Below is a workaround specific to ALC269 to control the dmic
+        * signal source as mono.
+        */
+       coef = alc_read_coef_idx(codec, 0x07);
+       alc_write_coef_idx(codec, 0x07, coef | 0x80);
+}
+
 enum {
        ALC269_FIXUP_SONY_VAIO,
        ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -4494,6 +4518,7 @@ enum {
        ALC275_FIXUP_SONY_HWEQ,
        ALC271_FIXUP_DMIC,
        ALC269_FIXUP_PCM_44K,
+       ALC269_FIXUP_STEREO_DMIC,
 };
 
 static const struct alc_fixup alc269_fixups[] = {
@@ -4556,10 +4581,19 @@ static const struct alc_fixup alc269_fixups[] = {
                .type = ALC_FIXUP_FUNC,
                .v.func = alc269_fixup_pcm_44k,
        },
+       [ALC269_FIXUP_STEREO_DMIC] = {
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc269_fixup_stereo_dmic,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
+       SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
        SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
index aa376b5..5145b66 100644 (file)
@@ -673,6 +673,7 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
 static int stac_vrefout_set(struct hda_codec *codec,
                                        hda_nid_t nid, unsigned int new_vref)
 {
@@ -696,6 +697,7 @@ static int stac_vrefout_set(struct hda_codec *codec,
 
        return 1;
 }
+#endif
 
 static unsigned int stac92xx_vref_set(struct hda_codec *codec,
                                        hda_nid_t nid, unsigned int new_vref)
index 84d8798..4ebfbd8 100644 (file)
@@ -2084,7 +2084,7 @@ static int via_auto_create_speaker_ctls(struct hda_codec *codec)
        struct via_spec *spec = codec->spec;
        struct nid_path *path;
        bool check_dac;
-       hda_nid_t pin, dac;
+       hda_nid_t pin, dac = 0;
        int err;
 
        pin = spec->autocfg.speaker_pins[0];
index 0ccc0eb..8531b98 100644 (file)
@@ -2748,8 +2748,9 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
        if (!c->no_mpu401) {
                err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
                        ICEREG(ice, MPU1_CTRL),
-                       (c->mpu401_1_info_flags | MPU401_INFO_INTEGRATED),
-                       ice->irq, 0, &ice->rmidi[0]);
+                       c->mpu401_1_info_flags |
+                       MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
+                       -1, &ice->rmidi[0]);
                if (err < 0) {
                        snd_card_free(card);
                        return err;
@@ -2764,8 +2765,9 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
                        /*  2nd port used  */
                        err = snd_mpu401_uart_new(card, 1, MPU401_HW_ICE1712,
                                ICEREG(ice, MPU2_CTRL),
-                               (c->mpu401_2_info_flags | MPU401_INFO_INTEGRATED),
-                               ice->irq, 0, &ice->rmidi[1]);
+                               c->mpu401_2_info_flags |
+                               MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
+                               -1, &ice->rmidi[1]);
 
                        if (err < 0) {
                                snd_card_free(card);
index 0378126..2fd4bf2 100644 (file)
@@ -2820,8 +2820,8 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        /* TODO enable MIDI IRQ and I/O */
        err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401,
                                  chip->iobase + MPU401_DATA_PORT,
-                                 MPU401_INFO_INTEGRATED,
-                                 chip->irq, 0, &chip->rmidi);
+                                 MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
+                                 -1, &chip->rmidi);
        if (err < 0)
                printk(KERN_WARNING "maestro3: no MIDI support.\n");
 #endif
index 82311fc..53e5508 100644 (file)
@@ -678,15 +678,15 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
                goto err_card;
 
        if (chip->model.device_config & (MIDI_OUTPUT | MIDI_INPUT)) {
-               unsigned int info_flags = MPU401_INFO_INTEGRATED;
+               unsigned int info_flags =
+                               MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK;
                if (chip->model.device_config & MIDI_OUTPUT)
                        info_flags |= MPU401_INFO_OUTPUT;
                if (chip->model.device_config & MIDI_INPUT)
                        info_flags |= MPU401_INFO_INPUT;
                err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
                                          chip->addr + OXYGEN_MPU401,
-                                         info_flags, 0, 0,
-                                         &chip->midi);
+                                         info_flags, -1, &chip->midi);
                if (err < 0)
                        goto err_card;
        }
index 32d096c..8433aa7 100644 (file)
@@ -1074,6 +1074,7 @@ static const struct oxygen_model model_xonar_st = {
        .device_config = PLAYBACK_0_TO_I2S |
                         PLAYBACK_1_TO_SPDIF |
                         CAPTURE_0_FROM_I2S_2 |
+                        CAPTURE_1_FROM_SPDIF |
                         AC97_FMIC_SWITCH,
        .dac_channels_pcm = 2,
        .dac_channels_mixer = 2,
index e34ae14..88cc776 100644 (file)
@@ -2109,7 +2109,7 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                val = mpu_port[dev];
                pci_write_config_word(chip->pci, PCI_EXT_MPU_Base, val);
                err = snd_mpu401_uart_new(card, 0, MPU401_HW_RIPTIDE,
-                                         val, 0, chip->irq, 0,
+                                         val, MPU401_INFO_IRQ_HOOK, -1,
                                          &chip->rmidi);
                if (err < 0)
                        snd_printk(KERN_WARNING
index 6edc67c..214110d 100644 (file)
@@ -1241,10 +1241,30 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
        return rate;
 }
 
+/* return latency in samples per period */
+static int hdspm_get_latency(struct hdspm *hdspm)
+{
+       int n;
+
+       n = hdspm_decode_latency(hdspm->control_register);
+
+       /* Special case for new RME cards with 32 samples period size.
+        * The three latency bits in the control register
+        * (HDSP_LatencyMask) encode latency values of 64 samples as
+        * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7
+        * denotes 8192 samples, but on new cards like RayDAT or AIO,
+        * it corresponds to 32 samples.
+        */
+       if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type))
+               n = -1;
+
+       return 1 << (n + 6);
+}
+
 /* Latency function */
 static inline void hdspm_compute_period_size(struct hdspm *hdspm)
 {
-       hdspm->period_bytes = 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
+       hdspm->period_bytes = 4 * hdspm_get_latency(hdspm);
 }
 
 
@@ -1303,12 +1323,27 @@ static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
 
        spin_lock_irq(&s->lock);
 
-       frames >>= 7;
-       n = 0;
-       while (frames) {
-               n++;
-               frames >>= 1;
+       if (32 == frames) {
+               /* Special case for new RME cards like RayDAT/AIO which
+                * support period sizes of 32 samples. Since latency is
+                * encoded in the three bits of HDSP_LatencyMask, we can only
+                * have values from 0 .. 7. While 0 still means 64 samples and
+                * 6 represents 4096 samples on all cards, 7 represents 8192
+                * on older cards and 32 samples on new cards.
+                *
+                * In other words, period size in samples is calculated by
+                * 2^(n+6) with n ranging from 0 .. 7.
+                */
+               n = 7;
+       } else {
+               frames >>= 7;
+               n = 0;
+               while (frames) {
+                       n++;
+                       frames >>= 1;
+               }
        }
+
        s->control_register &= ~HDSPM_LatencyMask;
        s->control_register |= hdspm_encode_latency(n);
 
@@ -1339,6 +1374,10 @@ static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
                break;
        case MADIface:
                freq_const = 131072000000000ULL;
+               break;
+       default:
+               snd_BUG();
+               return 0;
        }
 
        return div_u64(freq_const, period);
@@ -1356,16 +1395,19 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
 
        switch (hdspm->io_type) {
        case MADIface:
-         n = 131072000000000ULL;  /* 125 MHz */
-         break;
+               n = 131072000000000ULL;  /* 125 MHz */
+               break;
        case MADI:
        case AES32:
-         n = 110069313433624ULL;  /* 105 MHz */
-         break;
+               n = 110069313433624ULL;  /* 105 MHz */
+               break;
        case RayDAT:
        case AIO:
-         n = 104857600000000ULL;  /* 100 MHz */
-         break;
+               n = 104857600000000ULL;  /* 100 MHz */
+               break;
+       default:
+               snd_BUG();
+               return;
        }
 
        n = div_u64(n, rate);
@@ -4794,8 +4836,7 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
 
        snd_iprintf(buffer, "--- Settings ---\n");
 
-       x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
-                                                       HDSPM_LatencyMask));
+       x = hdspm_get_latency(hdspm);
 
        snd_iprintf(buffer,
                "Size (Latency): %d samples (2 periods of %lu bytes)\n",
@@ -4958,8 +4999,7 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
 
        snd_iprintf(buffer, "--- Settings ---\n");
 
-       x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
-                               HDSPM_LatencyMask));
+       x = hdspm_get_latency(hdspm);
 
        snd_iprintf(buffer,
                    "Size (Latency): %d samples (2 periods of %lu bytes)\n",
@@ -5665,19 +5705,6 @@ static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static unsigned int period_sizes_old[] = {
-       64, 128, 256, 512, 1024, 2048, 4096
-};
-
-static unsigned int period_sizes_new[] = {
-       32, 64, 128, 256, 512, 1024, 2048, 4096
-};
-
-/* RayDAT and AIO always have a buffer of 16384 samples per channel */
-static unsigned int raydat_aio_buffer_sizes[] = {
-       16384
-};
-
 static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
        .info = (SNDRV_PCM_INFO_MMAP |
                 SNDRV_PCM_INFO_MMAP_VALID |
@@ -5696,8 +5723,8 @@ static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
        .channels_max = HDSPM_MAX_CHANNELS,
        .buffer_bytes_max =
            HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
-       .period_bytes_min = (64 * 4),
-       .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
+       .period_bytes_min = (32 * 4),
+       .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
        .periods_min = 2,
        .periods_max = 512,
        .fifo_size = 0
@@ -5721,31 +5748,13 @@ static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
        .channels_max = HDSPM_MAX_CHANNELS,
        .buffer_bytes_max =
            HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
-       .period_bytes_min = (64 * 4),
-       .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
+       .period_bytes_min = (32 * 4),
+       .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
        .periods_min = 2,
        .periods_max = 512,
        .fifo_size = 0
 };
 
-static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = {
-       .count = ARRAY_SIZE(period_sizes_old),
-       .list = period_sizes_old,
-       .mask = 0
-};
-
-static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = {
-       .count = ARRAY_SIZE(period_sizes_new),
-       .list = period_sizes_new,
-       .mask = 0
-};
-
-static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = {
-       .count = ARRAY_SIZE(raydat_aio_buffer_sizes),
-       .list = raydat_aio_buffer_sizes,
-       .mask = 0
-};
-
 static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
                                           struct snd_pcm_hw_rule *rule)
 {
@@ -5946,26 +5955,29 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
        spin_unlock_irq(&hdspm->lock);
 
        snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+       snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
 
        switch (hdspm->io_type) {
        case AIO:
        case RayDAT:
-               snd_pcm_hw_constraint_list(runtime, 0,
-                               SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
-                               &hw_constraints_period_sizes_new);
-               snd_pcm_hw_constraint_list(runtime, 0,
-                               SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
-                               &hw_constraints_raydat_io_buffer);
-
+               snd_pcm_hw_constraint_minmax(runtime,
+                                            SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+                                            32, 4096);
+               /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */
+               snd_pcm_hw_constraint_minmax(runtime,
+                                            SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+                                            16384, 16384);
                break;
 
        default:
-               snd_pcm_hw_constraint_list(runtime, 0,
-                               SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
-                               &hw_constraints_period_sizes_old);
+               snd_pcm_hw_constraint_minmax(runtime,
+                                            SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+                                            64, 8192);
+               break;
        }
 
        if (AES32 == hdspm->io_type) {
+               runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
                snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                &hdspm_hw_constraints_aes32_sample_rates);
        } else {
@@ -6018,24 +6030,28 @@ static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
        spin_unlock_irq(&hdspm->lock);
 
        snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+       snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+
        switch (hdspm->io_type) {
        case AIO:
        case RayDAT:
-         snd_pcm_hw_constraint_list(runtime, 0,
-                                    SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
-                                    &hw_constraints_period_sizes_new);
-         snd_pcm_hw_constraint_list(runtime, 0,
-                                    SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
-                                    &hw_constraints_raydat_io_buffer);
-         break;
+               snd_pcm_hw_constraint_minmax(runtime,
+                                            SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+                                            32, 4096);
+               snd_pcm_hw_constraint_minmax(runtime,
+                                            SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+                                            16384, 16384);
+               break;
 
        default:
-         snd_pcm_hw_constraint_list(runtime, 0,
-                                    SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
-                                    &hw_constraints_period_sizes_old);
+               snd_pcm_hw_constraint_minmax(runtime,
+                                            SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+                                            64, 8192);
+               break;
        }
 
        if (AES32 == hdspm->io_type) {
+               runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
                snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                &hdspm_hw_constraints_aes32_sample_rates);
        } else {
index 2571a67..c500816 100644 (file)
@@ -1493,9 +1493,10 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci,
                return err;
        }
        if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES,
-                                      sonic->midi_port, MPU401_INFO_INTEGRATED,
-                                      sonic->irq, 0,
-                                      &midi_uart)) < 0) {
+                                      sonic->midi_port,
+                                      MPU401_INFO_INTEGRATED |
+                                      MPU401_INFO_IRQ_HOOK,
+                                      -1, &midi_uart)) < 0) {
                snd_card_free(card);
                return err;
        }
index d8a128f..5e707ef 100644 (file)
@@ -148,8 +148,9 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
        if (trident->device != TRIDENT_DEVICE_ID_SI7018 &&
            (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
                                       trident->midi_port,
-                                      MPU401_INFO_INTEGRATED,
-                                      trident->irq, 0, &trident->rmidi)) < 0) {
+                                      MPU401_INFO_INTEGRATED |
+                                      MPU401_INFO_IRQ_HOOK,
+                                      -1, &trident->rmidi)) < 0) {
                snd_card_free(card);
                return err;
        }
index f03fd62..c3656ff 100644 (file)
@@ -1175,6 +1175,7 @@ static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev,
        struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
        struct via_rate_lock *ratep;
+       bool use_src = false;
 
        runtime->hw = snd_via82xx_hw;
        
@@ -1196,6 +1197,7 @@ static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev,
                                     SNDRV_PCM_RATE_8000_48000);
                runtime->hw.rate_min = 8000;
                runtime->hw.rate_max = 48000;
+               use_src = true;
        } else if (! ratep->rate) {
                int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC;
                runtime->hw.rates = chip->ac97->rates[idx];
@@ -1212,6 +1214,12 @@ static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev,
        if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
                return err;
 
+       if (use_src) {
+               err = snd_pcm_hw_rule_noresample(runtime, 48000);
+               if (err < 0)
+                       return err;
+       }
+
        runtime->private_data = viadev;
        viadev->substream = substream;
 
@@ -2068,8 +2076,9 @@ static int __devinit snd_via686_init_misc(struct via82xx *chip)
        pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg);
        if (chip->mpu_res) {
                if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A,
-                                       mpu_port, MPU401_INFO_INTEGRATED,
-                                       chip->irq, 0, &chip->rmidi) < 0) {
+                                       mpu_port, MPU401_INFO_INTEGRATED |
+                                       MPU401_INFO_IRQ_HOOK, -1,
+                                       &chip->rmidi) < 0) {
                        printk(KERN_WARNING "unable to initialize MPU-401"
                               " at 0x%lx, skipping\n", mpu_port);
                        legacy &= ~VIA_FUNC_ENABLE_MIDI;
index 511d576..3253b04 100644 (file)
@@ -305,8 +305,9 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
        if (chip->mpu_res) {
                if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI,
                                               mpu_port[dev],
-                                              MPU401_INFO_INTEGRATED,
-                                              pci->irq, 0, &chip->rawmidi)) < 0) {
+                                              MPU401_INFO_INTEGRATED |
+                                              MPU401_INFO_IRQ_HOOK,
+                                              -1, &chip->rawmidi)) < 0) {
                        printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]);
                        legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */
                        pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
index f3260e6..66ea71b 100644 (file)
@@ -897,6 +897,18 @@ static int snd_ymfpci_playback_open_1(struct snd_pcm_substream *substream)
        struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_ymfpci_pcm *ypcm;
+       int err;
+
+       runtime->hw = snd_ymfpci_playback;
+       /* FIXME? True value is 256/48 = 5.33333 ms */
+       err = snd_pcm_hw_constraint_minmax(runtime,
+                                          SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+                                          5334, UINT_MAX);
+       if (err < 0)
+               return err;
+       err = snd_pcm_hw_rule_noresample(runtime, 48000);
+       if (err < 0)
+               return err;
 
        ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL);
        if (ypcm == NULL)
@@ -904,11 +916,8 @@ static int snd_ymfpci_playback_open_1(struct snd_pcm_substream *substream)
        ypcm->chip = chip;
        ypcm->type = PLAYBACK_VOICE;
        ypcm->substream = substream;
-       runtime->hw = snd_ymfpci_playback;
        runtime->private_data = ypcm;
        runtime->private_free = snd_ymfpci_pcm_free_substream;
-       /* FIXME? True value is 256/48 = 5.33333 ms */
-       snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 5333, UINT_MAX);
        return 0;
 }
 
@@ -1013,6 +1022,18 @@ static int snd_ymfpci_capture_open(struct snd_pcm_substream *substream,
        struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_ymfpci_pcm *ypcm;
+       int err;
+
+       runtime->hw = snd_ymfpci_capture;
+       /* FIXME? True value is 256/48 = 5.33333 ms */
+       err = snd_pcm_hw_constraint_minmax(runtime,
+                                          SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+                                          5334, UINT_MAX);
+       if (err < 0)
+               return err;
+       err = snd_pcm_hw_rule_noresample(runtime, 48000);
+       if (err < 0)
+               return err;
 
        ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL);
        if (ypcm == NULL)
@@ -1022,9 +1043,6 @@ static int snd_ymfpci_capture_open(struct snd_pcm_substream *substream,
        ypcm->substream = substream;    
        ypcm->capture_bank_number = capture_bank_number;
        chip->capture_substream[capture_bank_number] = substream;
-       runtime->hw = snd_ymfpci_capture;
-       /* FIXME? True value is 256/48 = 5.33333 ms */
-       snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 5333, UINT_MAX);
        runtime->private_data = ypcm;
        runtime->private_free = snd_ymfpci_pcm_free_substream;
        snd_ymfpci_hw_start(chip);
@@ -1615,7 +1633,7 @@ YMFPCI_DOUBLE("ADC Playback Volume", 0, YDSXGR_PRIADCOUTVOL),
 YMFPCI_DOUBLE("ADC Capture Volume", 0, YDSXGR_PRIADCLOOPVOL),
 YMFPCI_DOUBLE("ADC Playback Volume", 1, YDSXGR_SECADCOUTVOL),
 YMFPCI_DOUBLE("ADC Capture Volume", 1, YDSXGR_SECADCLOOPVOL),
-YMFPCI_DOUBLE("FM Legacy Volume", 0, YDSXGR_LEGACYOUTVOL),
+YMFPCI_DOUBLE("FM Legacy Playback Volume", 0, YDSXGR_LEGACYOUTVOL),
 YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ", PLAYBACK,VOLUME), 0, YDSXGR_ZVOUTVOL),
 YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("", CAPTURE,VOLUME), 0, YDSXGR_ZVLOOPVOL),
 YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ",PLAYBACK,VOLUME), 1, YDSXGR_SPDIFOUTVOL),
index 8f064c7..4080bec 100644 (file)
@@ -82,7 +82,6 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
 
 static int keywest_remove(struct i2c_client *client)
 {
-       i2c_set_clientdata(client, NULL);
        if (! keywest_ctx)
                return 0;
        if (client == keywest_ctx->client)
index cf9ed66..ac256dc 100644 (file)
@@ -3,16 +3,16 @@
 #
 
 snd-usb-audio-objs :=  card.o \
+                       clock.o \
+                       endpoint.o \
+                       format.o \
+                       helper.o \
                        mixer.o \
                        mixer_quirks.o \
+                       pcm.o \
                        proc.o \
                        quirks.o \
-                       format.o \
-                       endpoint.o \
-                       urb.o \
-                       pcm.o \
-                       helper.o \
-                       clock.o
+                       stream.o
 
 snd-usbmidi-lib-objs := midi.o
 
index d0d493c..2cf87f5 100644 (file)
@@ -139,8 +139,12 @@ static void stream_stop(struct snd_usb_caiaqdev *dev)
 
        for (i = 0; i < N_URBS; i++) {
                usb_kill_urb(dev->data_urbs_in[i]);
-               usb_kill_urb(dev->data_urbs_out[i]);
+
+               if (test_bit(i, &dev->outurb_active_mask))
+                       usb_kill_urb(dev->data_urbs_out[i]);
        }
+
+       dev->outurb_active_mask = 0;
 }
 
 static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream)
@@ -612,8 +616,9 @@ static void read_completed(struct urb *urb)
 {
        struct snd_usb_caiaq_cb_info *info = urb->context;
        struct snd_usb_caiaqdev *dev;
-       struct urb *out;
-       int frame, len, send_it = 0, outframe = 0;
+       struct urb *out = NULL;
+       int i, frame, len, send_it = 0, outframe = 0;
+       size_t offset = 0;
 
        if (urb->status || !info)
                return;
@@ -623,7 +628,17 @@ static void read_completed(struct urb *urb)
        if (!dev->streaming)
                return;
 
-       out = dev->data_urbs_out[info->index];
+       /* find an unused output urb that is unused */
+       for (i = 0; i < N_URBS; i++)
+               if (test_and_set_bit(i, &dev->outurb_active_mask) == 0) {
+                       out = dev->data_urbs_out[i];
+                       break;
+               }
+
+       if (!out) {
+               log("Unable to find an output urb to use\n");
+               goto requeue;
+       }
 
        /* read the recently received packet and send back one which has
         * the same layout */
@@ -634,7 +649,8 @@ static void read_completed(struct urb *urb)
                len = urb->iso_frame_desc[outframe].actual_length;
                out->iso_frame_desc[outframe].length = len;
                out->iso_frame_desc[outframe].actual_length = 0;
-               out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame;
+               out->iso_frame_desc[outframe].offset = offset;
+               offset += len;
 
                if (len > 0) {
                        spin_lock(&dev->spinlock);
@@ -650,11 +666,15 @@ static void read_completed(struct urb *urb)
        }
 
        if (send_it) {
-               out->number_of_packets = FRAMES_PER_URB;
+               out->number_of_packets = outframe;
                out->transfer_flags = URB_ISO_ASAP;
                usb_submit_urb(out, GFP_ATOMIC);
+       } else {
+               struct snd_usb_caiaq_cb_info *oinfo = out->context;
+               clear_bit(oinfo->index, &dev->outurb_active_mask);
        }
 
+requeue:
        /* re-submit inbound urb */
        for (frame = 0; frame < FRAMES_PER_URB; frame++) {
                urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame;
@@ -676,6 +696,8 @@ static void write_completed(struct urb *urb)
                dev->output_running = 1;
                wake_up(&dev->prepare_wait_queue);
        }
+
+       clear_bit(info->index, &dev->outurb_active_mask);
 }
 
 static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret)
@@ -827,6 +849,9 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
        if (!dev->data_cb_info)
                return -ENOMEM;
 
+       dev->outurb_active_mask = 0;
+       BUILD_BUG_ON(N_URBS > (sizeof(dev->outurb_active_mask) * 8));
+
        for (i = 0; i < N_URBS; i++) {
                dev->data_cb_info[i].dev = dev;
                dev->data_cb_info[i].index = i;
index b2b3101..3f9c633 100644 (file)
@@ -96,6 +96,7 @@ struct snd_usb_caiaqdev {
        int input_panic, output_panic, warned;
        char *audio_in_buf, *audio_out_buf;
        unsigned int samplerates, bpp;
+       unsigned long outurb_active_mask;
 
        struct snd_pcm_substream *sub_playback[MAX_STREAMS];
        struct snd_pcm_substream *sub_capture[MAX_STREAMS];
index 4432ef7..a213813 100644 (file)
@@ -30,7 +30,7 @@ static unsigned short keycode_ak1[] =  { KEY_C, KEY_B, KEY_A };
 static unsigned short keycode_rk2[] =  { KEY_1, KEY_2, KEY_3, KEY_4,
                                         KEY_5, KEY_6, KEY_7 };
 static unsigned short keycode_rk3[] =  { KEY_1, KEY_2, KEY_3, KEY_4,
-                                        KEY_5, KEY_6, KEY_7, KEY_5, KEY_6 };
+                                        KEY_5, KEY_6, KEY_7, KEY_8, KEY_9 };
 
 static unsigned short keycode_kore[] = {
        KEY_FN_F1,      /* "menu"               */
index 781d9e6..d2a79d1 100644 (file)
@@ -65,9 +65,9 @@
 #include "helper.h"
 #include "debug.h"
 #include "pcm.h"
-#include "urb.h"
 #include "format.h"
 #include "power.h"
+#include "stream.h"
 
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("USB Audio");
@@ -185,7 +185,7 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
                return -EINVAL;
        }
 
-       if (! snd_usb_parse_audio_endpoints(chip, interface)) {
+       if (! snd_usb_parse_audio_interface(chip, interface)) {
                usb_set_interface(dev, interface, 0); /* reset the current interface */
                usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L);
                return -EINVAL;
index ae4251d..a39edcc 100644 (file)
@@ -94,6 +94,8 @@ struct snd_usb_substream {
        spinlock_t lock;
 
        struct snd_urb_ops ops;         /* callbacks (must be filled at init) */
+       int last_frame_number;          /* stored frame number */
+       int last_delay;                 /* stored delay */
 };
 
 struct snd_usb_stream {
index 7c0d21e..81c6ede 100644 (file)
  *
  */
 
+#include <linux/gfp.h>
 #include <linux/init.h>
-#include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/usb/audio.h>
-#include <linux/usb/audio-v2.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
 
 #include "usbaudio.h"
+#include "helper.h"
 #include "card.h"
-#include "proc.h"
-#include "quirks.h"
 #include "endpoint.h"
-#include "urb.h"
 #include "pcm.h"
-#include "helper.h"
-#include "format.h"
-#include "clock.h"
 
 /*
- * free a substream
+ * convert a sampling rate into our full speed format (fs/1000 in Q16.16)
+ * this will overflow at approx 524 kHz
  */
-static void free_substream(struct snd_usb_substream *subs)
+static inline unsigned get_usb_full_speed_rate(unsigned int rate)
 {
-       struct list_head *p, *n;
-
-       if (!subs->num_formats)
-               return; /* not initialized */
-       list_for_each_safe(p, n, &subs->fmt_list) {
-               struct audioformat *fp = list_entry(p, struct audioformat, list);
-               kfree(fp->rate_table);
-               kfree(fp);
-       }
-       kfree(subs->rate_list.list);
+       return ((rate << 13) + 62) / 125;
 }
 
+/*
+ * convert a sampling rate into USB high speed format (fs/8000 in Q16.16)
+ * this will overflow at approx 4 MHz
+ */
+static inline unsigned get_usb_high_speed_rate(unsigned int rate)
+{
+       return ((rate << 10) + 62) / 125;
+}
 
 /*
- * free a usb stream instance
+ * unlink active urbs.
  */
-static void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
+static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sleep)
 {
-       free_substream(&stream->substream[0]);
-       free_substream(&stream->substream[1]);
-       list_del(&stream->list);
-       kfree(stream);
+       struct snd_usb_audio *chip = subs->stream->chip;
+       unsigned int i;
+       int async;
+
+       subs->running = 0;
+
+       if (!force && subs->stream->chip->shutdown) /* to be sure... */
+               return -EBADFD;
+
+       async = !can_sleep && chip->async_unlink;
+
+       if (!async && in_interrupt())
+               return 0;
+
+       for (i = 0; i < subs->nurbs; i++) {
+               if (test_bit(i, &subs->active_mask)) {
+                       if (!test_and_set_bit(i, &subs->unlink_mask)) {
+                               struct urb *u = subs->dataurb[i].urb;
+                               if (async)
+                                       usb_unlink_urb(u);
+                               else
+                                       usb_kill_urb(u);
+                       }
+               }
+       }
+       if (subs->syncpipe) {
+               for (i = 0; i < SYNC_URBS; i++) {
+                       if (test_bit(i+16, &subs->active_mask)) {
+                               if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
+                                       struct urb *u = subs->syncurb[i].urb;
+                                       if (async)
+                                               usb_unlink_urb(u);
+                                       else
+                                               usb_kill_urb(u);
+                               }
+                       }
+               }
+       }
+       return 0;
 }
 
-static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
+
+/*
+ * release a urb data
+ */
+static void release_urb_ctx(struct snd_urb_ctx *u)
 {
-       struct snd_usb_stream *stream = pcm->private_data;
-       if (stream) {
-               stream->pcm = NULL;
-               snd_usb_audio_stream_free(stream);
+       if (u->urb) {
+               if (u->buffer_size)
+                       usb_free_coherent(u->subs->dev, u->buffer_size,
+                                       u->urb->transfer_buffer,
+                                       u->urb->transfer_dma);
+               usb_free_urb(u->urb);
+               u->urb = NULL;
        }
 }
 
+/*
+ *  wait until all urbs are processed.
+ */
+static int wait_clear_urbs(struct snd_usb_substream *subs)
+{
+       unsigned long end_time = jiffies + msecs_to_jiffies(1000);
+       unsigned int i;
+       int alive;
+
+       do {
+               alive = 0;
+               for (i = 0; i < subs->nurbs; i++) {
+                       if (test_bit(i, &subs->active_mask))
+                               alive++;
+               }
+               if (subs->syncpipe) {
+                       for (i = 0; i < SYNC_URBS; i++) {
+                               if (test_bit(i + 16, &subs->active_mask))
+                                       alive++;
+                       }
+               }
+               if (! alive)
+                       break;
+               schedule_timeout_uninterruptible(1);
+       } while (time_before(jiffies, end_time));
+       if (alive)
+               snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
+       return 0;
+}
 
 /*
- * add this endpoint to the chip instance.
- * if a stream with the same endpoint already exists, append to it.
- * if not, create a new pcm stream.
+ * release a substream
  */
-int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct audioformat *fp)
+void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force)
 {
-       struct list_head *p;
-       struct snd_usb_stream *as;
-       struct snd_usb_substream *subs;
-       struct snd_pcm *pcm;
-       int err;
+       int i;
+
+       /* stop urbs (to be sure) */
+       deactivate_urbs(subs, force, 1);
+       wait_clear_urbs(subs);
+
+       for (i = 0; i < MAX_URBS; i++)
+               release_urb_ctx(&subs->dataurb[i]);
+       for (i = 0; i < SYNC_URBS; i++)
+               release_urb_ctx(&subs->syncurb[i]);
+       usb_free_coherent(subs->dev, SYNC_URBS * 4,
+                       subs->syncbuf, subs->sync_dma);
+       subs->syncbuf = NULL;
+       subs->nurbs = 0;
+}
 
-       list_for_each(p, &chip->pcm_list) {
-               as = list_entry(p, struct snd_usb_stream, list);
-               if (as->fmt_type != fp->fmt_type)
-                       continue;
-               subs = &as->substream[stream];
-               if (!subs->endpoint)
-                       continue;
-               if (subs->endpoint == fp->endpoint) {
-                       list_add_tail(&fp->list, &subs->fmt_list);
-                       subs->num_formats++;
-                       subs->formats |= fp->formats;
-                       return 0;
+/*
+ * complete callback from data urb
+ */
+static void snd_complete_urb(struct urb *urb)
+{
+       struct snd_urb_ctx *ctx = urb->context;
+       struct snd_usb_substream *subs = ctx->subs;
+       struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
+       int err = 0;
+
+       if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
+           !subs->running || /* can be stopped during retire callback */
+           (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
+           (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+               clear_bit(ctx->index, &subs->active_mask);
+               if (err < 0) {
+                       snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err);
+                       snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
                }
        }
-       /* look for an empty stream */
-       list_for_each(p, &chip->pcm_list) {
-               as = list_entry(p, struct snd_usb_stream, list);
-               if (as->fmt_type != fp->fmt_type)
-                       continue;
-               subs = &as->substream[stream];
-               if (subs->endpoint)
-                       continue;
-               err = snd_pcm_new_stream(as->pcm, stream, 1);
-               if (err < 0)
-                       return err;
-               snd_usb_init_substream(as, stream, fp);
-               return 0;
+}
+
+
+/*
+ * complete callback from sync urb
+ */
+static void snd_complete_sync_urb(struct urb *urb)
+{
+       struct snd_urb_ctx *ctx = urb->context;
+       struct snd_usb_substream *subs = ctx->subs;
+       struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
+       int err = 0;
+
+       if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
+           !subs->running || /* can be stopped during retire callback */
+           (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
+           (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+               clear_bit(ctx->index + 16, &subs->active_mask);
+               if (err < 0) {
+                       snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err);
+                       snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+               }
        }
+}
+
 
-       /* create a new pcm */
-       as = kzalloc(sizeof(*as), GFP_KERNEL);
-       if (!as)
-               return -ENOMEM;
-       as->pcm_index = chip->pcm_devs;
-       as->chip = chip;
-       as->fmt_type = fp->fmt_type;
-       err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
-                         stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
-                         stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
-                         &pcm);
-       if (err < 0) {
-               kfree(as);
-               return err;
+/*
+ * initialize a substream for plaback/capture
+ */
+int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
+                               unsigned int period_bytes,
+                               unsigned int rate,
+                               unsigned int frame_bits)
+{
+       unsigned int maxsize, i;
+       int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
+       unsigned int urb_packs, total_packs, packs_per_ms;
+       struct snd_usb_audio *chip = subs->stream->chip;
+
+       /* calculate the frequency in 16.16 format */
+       if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
+               subs->freqn = get_usb_full_speed_rate(rate);
+       else
+               subs->freqn = get_usb_high_speed_rate(rate);
+       subs->freqm = subs->freqn;
+       subs->freqshift = INT_MIN;
+       /* calculate max. frequency */
+       if (subs->maxpacksize) {
+               /* whatever fits into a max. size packet */
+               maxsize = subs->maxpacksize;
+               subs->freqmax = (maxsize / (frame_bits >> 3))
+                               << (16 - subs->datainterval);
+       } else {
+               /* no max. packet size: just take 25% higher than nominal */
+               subs->freqmax = subs->freqn + (subs->freqn >> 2);
+               maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3))
+                               >> (16 - subs->datainterval);
        }
-       as->pcm = pcm;
-       pcm->private_data = as;
-       pcm->private_free = snd_usb_audio_pcm_free;
-       pcm->info_flags = 0;
-       if (chip->pcm_devs > 0)
-               sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
+       subs->phase = 0;
+
+       if (subs->fill_max)
+               subs->curpacksize = subs->maxpacksize;
        else
-               strcpy(pcm->name, "USB Audio");
+               subs->curpacksize = maxsize;
 
-       snd_usb_init_substream(as, stream, fp);
+       if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
+               packs_per_ms = 8 >> subs->datainterval;
+       else
+               packs_per_ms = 1;
+
+       if (is_playback) {
+               urb_packs = max(chip->nrpacks, 1);
+               urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
+       } else
+               urb_packs = 1;
+       urb_packs *= packs_per_ms;
+       if (subs->syncpipe)
+               urb_packs = min(urb_packs, 1U << subs->syncinterval);
+
+       /* decide how many packets to be used */
+       if (is_playback) {
+               unsigned int minsize, maxpacks;
+               /* determine how small a packet can be */
+               minsize = (subs->freqn >> (16 - subs->datainterval))
+                         * (frame_bits >> 3);
+               /* with sync from device, assume it can be 12% lower */
+               if (subs->syncpipe)
+                       minsize -= minsize >> 3;
+               minsize = max(minsize, 1u);
+               total_packs = (period_bytes + minsize - 1) / minsize;
+               /* we need at least two URBs for queueing */
+               if (total_packs < 2) {
+                       total_packs = 2;
+               } else {
+                       /* and we don't want too long a queue either */
+                       maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
+                       total_packs = min(total_packs, maxpacks);
+               }
+       } else {
+               while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
+                       urb_packs >>= 1;
+               total_packs = MAX_URBS * urb_packs;
+       }
+       subs->nurbs = (total_packs + urb_packs - 1) / urb_packs;
+       if (subs->nurbs > MAX_URBS) {
+               /* too much... */
+               subs->nurbs = MAX_URBS;
+               total_packs = MAX_URBS * urb_packs;
+       } else if (subs->nurbs < 2) {
+               /* too little - we need at least two packets
+                * to ensure contiguous playback/capture
+                */
+               subs->nurbs = 2;
+       }
 
-       list_add(&as->list, &chip->pcm_list);
-       chip->pcm_devs++;
+       /* allocate and initialize data urbs */
+       for (i = 0; i < subs->nurbs; i++) {
+               struct snd_urb_ctx *u = &subs->dataurb[i];
+               u->index = i;
+               u->subs = subs;
+               u->packets = (i + 1) * total_packs / subs->nurbs
+                       - i * total_packs / subs->nurbs;
+               u->buffer_size = maxsize * u->packets;
+               if (subs->fmt_type == UAC_FORMAT_TYPE_II)
+                       u->packets++; /* for transfer delimiter */
+               u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
+               if (!u->urb)
+                       goto out_of_memory;
+               u->urb->transfer_buffer =
+                       usb_alloc_coherent(subs->dev, u->buffer_size,
+                                          GFP_KERNEL, &u->urb->transfer_dma);
+               if (!u->urb->transfer_buffer)
+                       goto out_of_memory;
+               u->urb->pipe = subs->datapipe;
+               u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+               u->urb->interval = 1 << subs->datainterval;
+               u->urb->context = u;
+               u->urb->complete = snd_complete_urb;
+       }
+
+       if (subs->syncpipe) {
+               /* allocate and initialize sync urbs */
+               subs->syncbuf = usb_alloc_coherent(subs->dev, SYNC_URBS * 4,
+                                                GFP_KERNEL, &subs->sync_dma);
+               if (!subs->syncbuf)
+                       goto out_of_memory;
+               for (i = 0; i < SYNC_URBS; i++) {
+                       struct snd_urb_ctx *u = &subs->syncurb[i];
+                       u->index = i;
+                       u->subs = subs;
+                       u->packets = 1;
+                       u->urb = usb_alloc_urb(1, GFP_KERNEL);
+                       if (!u->urb)
+                               goto out_of_memory;
+                       u->urb->transfer_buffer = subs->syncbuf + i * 4;
+                       u->urb->transfer_dma = subs->sync_dma + i * 4;
+                       u->urb->transfer_buffer_length = 4;
+                       u->urb->pipe = subs->syncpipe;
+                       u->urb->transfer_flags = URB_ISO_ASAP |
+                                                URB_NO_TRANSFER_DMA_MAP;
+                       u->urb->number_of_packets = 1;
+                       u->urb->interval = 1 << subs->syncinterval;
+                       u->urb->context = u;
+                       u->urb->complete = snd_complete_sync_urb;
+               }
+       }
+       return 0;
 
-       snd_usb_proc_pcm_format_add(as);
+out_of_memory:
+       snd_usb_release_substream_urbs(subs, 0);
+       return -ENOMEM;
+}
 
+/*
+ * prepare urb for full speed capture sync pipe
+ *
+ * fill the length and offset of each urb descriptor.
+ * the fixed 10.14 frequency is passed through the pipe.
+ */
+static int prepare_capture_sync_urb(struct snd_usb_substream *subs,
+                                   struct snd_pcm_runtime *runtime,
+                                   struct urb *urb)
+{
+       unsigned char *cp = urb->transfer_buffer;
+       struct snd_urb_ctx *ctx = urb->context;
+
+       urb->dev = ctx->subs->dev; /* we need to set this at each time */
+       urb->iso_frame_desc[0].length = 3;
+       urb->iso_frame_desc[0].offset = 0;
+       cp[0] = subs->freqn >> 2;
+       cp[1] = subs->freqn >> 10;
+       cp[2] = subs->freqn >> 18;
        return 0;
 }
 
-static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
-                                        struct usb_host_interface *alts,
-                                        int protocol, int iface_no)
+/*
+ * prepare urb for high speed capture sync pipe
+ *
+ * fill the length and offset of each urb descriptor.
+ * the fixed 12.13 frequency is passed as 16.16 through the pipe.
+ */
+static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs,
+                                      struct snd_pcm_runtime *runtime,
+                                      struct urb *urb)
 {
-       /* parsed with a v1 header here. that's ok as we only look at the
-        * header first which is the same for both versions */
-       struct uac_iso_endpoint_descriptor *csep;
-       struct usb_interface_descriptor *altsd = get_iface_desc(alts);
-       int attributes = 0;
-
-       csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
-
-       /* Creamware Noah has this descriptor after the 2nd endpoint */
-       if (!csep && altsd->bNumEndpoints >= 2)
-               csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
-
-       if (!csep || csep->bLength < 7 ||
-           csep->bDescriptorSubtype != UAC_EP_GENERAL) {
-               snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
-                          " class specific endpoint descriptor\n",
-                          chip->dev->devnum, iface_no,
-                          altsd->bAlternateSetting);
-               return 0;
-       }
+       unsigned char *cp = urb->transfer_buffer;
+       struct snd_urb_ctx *ctx = urb->context;
+
+       urb->dev = ctx->subs->dev; /* we need to set this at each time */
+       urb->iso_frame_desc[0].length = 4;
+       urb->iso_frame_desc[0].offset = 0;
+       cp[0] = subs->freqn;
+       cp[1] = subs->freqn >> 8;
+       cp[2] = subs->freqn >> 16;
+       cp[3] = subs->freqn >> 24;
+       return 0;
+}
 
-       if (protocol == UAC_VERSION_1) {
-               attributes = csep->bmAttributes;
-       } else {
-               struct uac2_iso_endpoint_descriptor *csep2 =
-                       (struct uac2_iso_endpoint_descriptor *) csep;
+/*
+ * process after capture sync complete
+ * - nothing to do
+ */
+static int retire_capture_sync_urb(struct snd_usb_substream *subs,
+                                  struct snd_pcm_runtime *runtime,
+                                  struct urb *urb)
+{
+       return 0;
+}
 
-               attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
+/*
+ * prepare urb for capture data pipe
+ *
+ * fill the offset and length of each descriptor.
+ *
+ * we use a temporary buffer to write the captured data.
+ * since the length of written data is determined by host, we cannot
+ * write onto the pcm buffer directly...  the data is thus copied
+ * later at complete callback to the global buffer.
+ */
+static int prepare_capture_urb(struct snd_usb_substream *subs,
+                              struct snd_pcm_runtime *runtime,
+                              struct urb *urb)
+{
+       int i, offs;
+       struct snd_urb_ctx *ctx = urb->context;
+
+       offs = 0;
+       urb->dev = ctx->subs->dev; /* we need to set this at each time */
+       for (i = 0; i < ctx->packets; i++) {
+               urb->iso_frame_desc[i].offset = offs;
+               urb->iso_frame_desc[i].length = subs->curpacksize;
+               offs += subs->curpacksize;
+       }
+       urb->transfer_buffer_length = offs;
+       urb->number_of_packets = ctx->packets;
+       return 0;
+}
 
-               /* emulate the endpoint attributes of a v1 device */
-               if (csep2->bmControls & UAC2_CONTROL_PITCH)
-                       attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
+/*
+ * process after capture complete
+ *
+ * copy the data from each desctiptor to the pcm buffer, and
+ * update the current position.
+ */
+static int retire_capture_urb(struct snd_usb_substream *subs,
+                             struct snd_pcm_runtime *runtime,
+                             struct urb *urb)
+{
+       unsigned long flags;
+       unsigned char *cp;
+       int i;
+       unsigned int stride, frames, bytes, oldptr;
+       int period_elapsed = 0;
+
+       stride = runtime->frame_bits >> 3;
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+               if (urb->iso_frame_desc[i].status) {
+                       snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
+                       // continue;
+               }
+               bytes = urb->iso_frame_desc[i].actual_length;
+               frames = bytes / stride;
+               if (!subs->txfr_quirk)
+                       bytes = frames * stride;
+               if (bytes % (runtime->sample_bits >> 3) != 0) {
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+                       int oldbytes = bytes;
+#endif
+                       bytes = frames * stride;
+                       snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
+                                                       oldbytes, bytes);
+               }
+               /* update the current pointer */
+               spin_lock_irqsave(&subs->lock, flags);
+               oldptr = subs->hwptr_done;
+               subs->hwptr_done += bytes;
+               if (subs->hwptr_done >= runtime->buffer_size * stride)
+                       subs->hwptr_done -= runtime->buffer_size * stride;
+               frames = (bytes + (oldptr % stride)) / stride;
+               subs->transfer_done += frames;
+               if (subs->transfer_done >= runtime->period_size) {
+                       subs->transfer_done -= runtime->period_size;
+                       period_elapsed = 1;
+               }
+               spin_unlock_irqrestore(&subs->lock, flags);
+               /* copy a data chunk */
+               if (oldptr + bytes > runtime->buffer_size * stride) {
+                       unsigned int bytes1 =
+                                       runtime->buffer_size * stride - oldptr;
+                       memcpy(runtime->dma_area + oldptr, cp, bytes1);
+                       memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
+               } else {
+                       memcpy(runtime->dma_area + oldptr, cp, bytes);
+               }
        }
+       if (period_elapsed)
+               snd_pcm_period_elapsed(subs->pcm_substream);
+       return 0;
+}
 
-       return attributes;
+/*
+ * Process after capture complete when paused.  Nothing to do.
+ */
+static int retire_paused_capture_urb(struct snd_usb_substream *subs,
+                                    struct snd_pcm_runtime *runtime,
+                                    struct urb *urb)
+{
+       return 0;
 }
 
-static struct uac2_input_terminal_descriptor *
-       snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
-                                              int terminal_id)
+
+/*
+ * prepare urb for playback sync pipe
+ *
+ * set up the offset and length to receive the current frequency.
+ */
+static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
+                                    struct snd_pcm_runtime *runtime,
+                                    struct urb *urb)
 {
-       struct uac2_input_terminal_descriptor *term = NULL;
+       struct snd_urb_ctx *ctx = urb->context;
+
+       urb->dev = ctx->subs->dev; /* we need to set this at each time */
+       urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize);
+       urb->iso_frame_desc[0].offset = 0;
+       return 0;
+}
 
-       while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
-                                              ctrl_iface->extralen,
-                                              term, UAC_INPUT_TERMINAL))) {
-               if (term->bTerminalID == terminal_id)
-                       return term;
+/*
+ * process after playback sync complete
+ *
+ * Full speed devices report feedback values in 10.14 format as samples per
+ * frame, high speed devices in 16.16 format as samples per microframe.
+ * Because the Audio Class 1 spec was written before USB 2.0, many high speed
+ * devices use a wrong interpretation, some others use an entirely different
+ * format.  Therefore, we cannot predict what format any particular device uses
+ * and must detect it automatically.
+ */
+static int retire_playback_sync_urb(struct snd_usb_substream *subs,
+                                   struct snd_pcm_runtime *runtime,
+                                   struct urb *urb)
+{
+       unsigned int f;
+       int shift;
+       unsigned long flags;
+
+       if (urb->iso_frame_desc[0].status != 0 ||
+           urb->iso_frame_desc[0].actual_length < 3)
+               return 0;
+
+       f = le32_to_cpup(urb->transfer_buffer);
+       if (urb->iso_frame_desc[0].actual_length == 3)
+               f &= 0x00ffffff;
+       else
+               f &= 0x0fffffff;
+       if (f == 0)
+               return 0;
+
+       if (unlikely(subs->freqshift == INT_MIN)) {
+               /*
+                * The first time we see a feedback value, determine its format
+                * by shifting it left or right until it matches the nominal
+                * frequency value.  This assumes that the feedback does not
+                * differ from the nominal value more than +50% or -25%.
+                */
+               shift = 0;
+               while (f < subs->freqn - subs->freqn / 4) {
+                       f <<= 1;
+                       shift++;
+               }
+               while (f > subs->freqn + subs->freqn / 2) {
+                       f >>= 1;
+                       shift--;
+               }
+               subs->freqshift = shift;
+       }
+       else if (subs->freqshift >= 0)
+               f <<= subs->freqshift;
+       else
+               f >>= -subs->freqshift;
+
+       if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) {
+               /*
+                * If the frequency looks valid, set it.
+                * This value is referred to in prepare_playback_urb().
+                */
+               spin_lock_irqsave(&subs->lock, flags);
+               subs->freqm = f;
+               spin_unlock_irqrestore(&subs->lock, flags);
+       } else {
+               /*
+                * Out of range; maybe the shift value is wrong.
+                * Reset it so that we autodetect again the next time.
+                */
+               subs->freqshift = INT_MIN;
        }
 
-       return NULL;
+       return 0;
 }
 
-static struct uac2_output_terminal_descriptor *
-       snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
-                                               int terminal_id)
+/* determine the number of frames in the next packet */
+static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
 {
-       struct uac2_output_terminal_descriptor *term = NULL;
-
-       while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
-                                              ctrl_iface->extralen,
-                                              term, UAC_OUTPUT_TERMINAL))) {
-               if (term->bTerminalID == terminal_id)
-                       return term;
+       if (subs->fill_max)
+               return subs->maxframesize;
+       else {
+               subs->phase = (subs->phase & 0xffff)
+                       + (subs->freqm << subs->datainterval);
+               return min(subs->phase >> 16, subs->maxframesize);
        }
+}
 
-       return NULL;
+/*
+ * Prepare urb for streaming before playback starts or when paused.
+ *
+ * We don't have any data, so we send silence.
+ */
+static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
+                                      struct snd_pcm_runtime *runtime,
+                                      struct urb *urb)
+{
+       unsigned int i, offs, counts;
+       struct snd_urb_ctx *ctx = urb->context;
+       int stride = runtime->frame_bits >> 3;
+
+       offs = 0;
+       urb->dev = ctx->subs->dev;
+       for (i = 0; i < ctx->packets; ++i) {
+               counts = snd_usb_audio_next_packet_size(subs);
+               urb->iso_frame_desc[i].offset = offs * stride;
+               urb->iso_frame_desc[i].length = counts * stride;
+               offs += counts;
+       }
+       urb->number_of_packets = ctx->packets;
+       urb->transfer_buffer_length = offs * stride;
+       memset(urb->transfer_buffer,
+              runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
+              offs * stride);
+       return 0;
 }
 
-int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
+/*
+ * prepare urb for playback data pipe
+ *
+ * Since a URB can handle only a single linear buffer, we must use double
+ * buffering when the data to be transferred overflows the buffer boundary.
+ * To avoid inconsistencies when updating hwptr_done, we use double buffering
+ * for all URBs.
+ */
+static int prepare_playback_urb(struct snd_usb_substream *subs,
+                               struct snd_pcm_runtime *runtime,
+                               struct urb *urb)
 {
-       struct usb_device *dev;
-       struct usb_interface *iface;
-       struct usb_host_interface *alts;
-       struct usb_interface_descriptor *altsd;
-       int i, altno, err, stream;
-       int format = 0, num_channels = 0;
-       struct audioformat *fp = NULL;
-       int num, protocol, clock = 0;
-       struct uac_format_type_i_continuous_descriptor *fmt;
+       int i, stride;
+       unsigned int counts, frames, bytes;
+       unsigned long flags;
+       int period_elapsed = 0;
+       struct snd_urb_ctx *ctx = urb->context;
+
+       stride = runtime->frame_bits >> 3;
+
+       frames = 0;
+       urb->dev = ctx->subs->dev; /* we need to set this at each time */
+       urb->number_of_packets = 0;
+       spin_lock_irqsave(&subs->lock, flags);
+       for (i = 0; i < ctx->packets; i++) {
+               counts = snd_usb_audio_next_packet_size(subs);
+               /* set up descriptor */
+               urb->iso_frame_desc[i].offset = frames * stride;
+               urb->iso_frame_desc[i].length = counts * stride;
+               frames += counts;
+               urb->number_of_packets++;
+               subs->transfer_done += counts;
+               if (subs->transfer_done >= runtime->period_size) {
+                       subs->transfer_done -= runtime->period_size;
+                       period_elapsed = 1;
+                       if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
+                               if (subs->transfer_done > 0) {
+                                       /* FIXME: fill-max mode is not
+                                        * supported yet */
+                                       frames -= subs->transfer_done;
+                                       counts -= subs->transfer_done;
+                                       urb->iso_frame_desc[i].length =
+                                               counts * stride;
+                                       subs->transfer_done = 0;
+                               }
+                               i++;
+                               if (i < ctx->packets) {
+                                       /* add a transfer delimiter */
+                                       urb->iso_frame_desc[i].offset =
+                                               frames * stride;
+                                       urb->iso_frame_desc[i].length = 0;
+                                       urb->number_of_packets++;
+                               }
+                               break;
+                       }
+               }
+               if (period_elapsed) /* finish at the period boundary */
+                       break;
+       }
+       bytes = frames * stride;
+       if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
+               /* err, the transferred area goes over buffer boundary. */
+               unsigned int bytes1 =
+                       runtime->buffer_size * stride - subs->hwptr_done;
+               memcpy(urb->transfer_buffer,
+                      runtime->dma_area + subs->hwptr_done, bytes1);
+               memcpy(urb->transfer_buffer + bytes1,
+                      runtime->dma_area, bytes - bytes1);
+       } else {
+               memcpy(urb->transfer_buffer,
+                      runtime->dma_area + subs->hwptr_done, bytes);
+       }
+       subs->hwptr_done += bytes;
+       if (subs->hwptr_done >= runtime->buffer_size * stride)
+               subs->hwptr_done -= runtime->buffer_size * stride;
+
+       /* update delay with exact number of samples queued */
+       runtime->delay = subs->last_delay;
+       runtime->delay += frames;
+       subs->last_delay = runtime->delay;
+
+       /* realign last_frame_number */
+       subs->last_frame_number = usb_get_current_frame_number(subs->dev);
+       subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
+
+       spin_unlock_irqrestore(&subs->lock, flags);
+       urb->transfer_buffer_length = bytes;
+       if (period_elapsed)
+               snd_pcm_period_elapsed(subs->pcm_substream);
+       return 0;
+}
 
-       dev = chip->dev;
+/*
+ * process after playback data complete
+ * - decrease the delay count again
+ */
+static int retire_playback_urb(struct snd_usb_substream *subs,
+                              struct snd_pcm_runtime *runtime,
+                              struct urb *urb)
+{
+       unsigned long flags;
+       int stride = runtime->frame_bits >> 3;
+       int processed = urb->transfer_buffer_length / stride;
+       int est_delay;
 
-       /* parse the interface's altsettings */
-       iface = usb_ifnum_to_if(dev, iface_no);
+       spin_lock_irqsave(&subs->lock, flags);
 
-       num = iface->num_altsetting;
+       est_delay = snd_usb_pcm_delay(subs, runtime->rate);
+       /* update delay with exact number of samples played */
+       if (processed > subs->last_delay)
+               subs->last_delay = 0;
+       else
+               subs->last_delay -= processed;
+       runtime->delay = subs->last_delay;
 
        /*
-        * Dallas DS4201 workaround: It presents 5 altsettings, but the last
-        * one misses syncpipe, and does not produce any sound.
+        * Report when delay estimate is off by more than 2ms.
+        * The error should be lower than 2ms since the estimate relies
+        * on two reads of a counter updated every ms.
         */
-       if (chip->usb_id == USB_ID(0x04fa, 0x4201))
-               num = 4;
-
-       for (i = 0; i < num; i++) {
-               alts = &iface->altsetting[i];
-               altsd = get_iface_desc(alts);
-               protocol = altsd->bInterfaceProtocol;
-               /* skip invalid one */
-               if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
-                    altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
-                   (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
-                    altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) ||
-                   altsd->bNumEndpoints < 1 ||
-                   le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
-                       continue;
-               /* must be isochronous */
-               if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
-                   USB_ENDPOINT_XFER_ISOC)
-                       continue;
-               /* check direction */
-               stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
-                       SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-               altno = altsd->bAlternateSetting;
-
-               if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
-                       continue;
-
-               /* get audio formats */
-               switch (protocol) {
-               default:
-                       snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n",
-                                   dev->devnum, iface_no, altno, protocol);
-                       protocol = UAC_VERSION_1;
-                       /* fall through */
-
-               case UAC_VERSION_1: {
-                       struct uac1_as_header_descriptor *as =
-                               snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
-
-                       if (!as) {
-                               snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
-                                          dev->devnum, iface_no, altno);
-                               continue;
-                       }
+       if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
+               snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
+                       est_delay, subs->last_delay);
 
-                       if (as->bLength < sizeof(*as)) {
-                               snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
-                                          dev->devnum, iface_no, altno);
-                               continue;
-                       }
+       spin_unlock_irqrestore(&subs->lock, flags);
+       return 0;
+}
 
-                       format = le16_to_cpu(as->wFormatTag); /* remember the format value */
-                       break;
-               }
+static const char *usb_error_string(int err)
+{
+       switch (err) {
+       case -ENODEV:
+               return "no device";
+       case -ENOENT:
+               return "endpoint not enabled";
+       case -EPIPE:
+               return "endpoint stalled";
+       case -ENOSPC:
+               return "not enough bandwidth";
+       case -ESHUTDOWN:
+               return "device disabled";
+       case -EHOSTUNREACH:
+               return "device suspended";
+       case -EINVAL:
+       case -EAGAIN:
+       case -EFBIG:
+       case -EMSGSIZE:
+               return "internal error";
+       default:
+               return "unknown error";
+       }
+}
 
-               case UAC_VERSION_2: {
-                       struct uac2_input_terminal_descriptor *input_term;
-                       struct uac2_output_terminal_descriptor *output_term;
-                       struct uac2_as_header_descriptor *as =
-                               snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+/*
+ * set up and start data/sync urbs
+ */
+static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime)
+{
+       unsigned int i;
+       int err;
 
-                       if (!as) {
-                               snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
-                                          dev->devnum, iface_no, altno);
-                               continue;
+       if (subs->stream->chip->shutdown)
+               return -EBADFD;
+
+       for (i = 0; i < subs->nurbs; i++) {
+               if (snd_BUG_ON(!subs->dataurb[i].urb))
+                       return -EINVAL;
+               if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) {
+                       snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i);
+                       goto __error;
+               }
+       }
+       if (subs->syncpipe) {
+               for (i = 0; i < SYNC_URBS; i++) {
+                       if (snd_BUG_ON(!subs->syncurb[i].urb))
+                               return -EINVAL;
+                       if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) {
+                               snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i);
+                               goto __error;
                        }
+               }
+       }
 
-                       if (as->bLength < sizeof(*as)) {
-                               snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
-                                          dev->devnum, iface_no, altno);
-                               continue;
+       subs->active_mask = 0;
+       subs->unlink_mask = 0;
+       subs->running = 1;
+       for (i = 0; i < subs->nurbs; i++) {
+               err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC);
+               if (err < 0) {
+                       snd_printk(KERN_ERR "cannot submit datapipe "
+                                  "for urb %d, error %d: %s\n",
+                                  i, err, usb_error_string(err));
+                       goto __error;
+               }
+               set_bit(i, &subs->active_mask);
+       }
+       if (subs->syncpipe) {
+               for (i = 0; i < SYNC_URBS; i++) {
+                       err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC);
+                       if (err < 0) {
+                               snd_printk(KERN_ERR "cannot submit syncpipe "
+                                          "for urb %d, error %d: %s\n",
+                                          i, err, usb_error_string(err));
+                               goto __error;
                        }
+                       set_bit(i + 16, &subs->active_mask);
+               }
+       }
+       return 0;
 
-                       num_channels = as->bNrChannels;
-                       format = le32_to_cpu(as->bmFormats);
+ __error:
+       // snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
+       deactivate_urbs(subs, 0, 0);
+       return -EPIPE;
+}
 
-                       /* lookup the terminal associated to this interface
-                        * to extract the clock */
-                       input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-                                                                           as->bTerminalLink);
-                       if (input_term) {
-                               clock = input_term->bCSourceID;
-                               break;
-                       }
 
-                       output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
-                                                                             as->bTerminalLink);
-                       if (output_term) {
-                               clock = output_term->bCSourceID;
-                               break;
-                       }
+/*
+ */
+static struct snd_urb_ops audio_urb_ops[2] = {
+       {
+               .prepare =      prepare_nodata_playback_urb,
+               .retire =       retire_playback_urb,
+               .prepare_sync = prepare_playback_sync_urb,
+               .retire_sync =  retire_playback_sync_urb,
+       },
+       {
+               .prepare =      prepare_capture_urb,
+               .retire =       retire_capture_urb,
+               .prepare_sync = prepare_capture_sync_urb,
+               .retire_sync =  retire_capture_sync_urb,
+       },
+};
 
-                       snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n",
-                                  dev->devnum, iface_no, altno, as->bTerminalLink);
-                       continue;
-               }
-               }
+/*
+ * initialize the substream instance.
+ */
 
-               /* get format type */
-               fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE);
-               if (!fmt) {
-                       snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n",
-                                  dev->devnum, iface_no, altno);
-                       continue;
-               }
-               if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
-                   ((protocol == UAC_VERSION_2) && (fmt->bLength != 6))) {
-                       snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
-                                  dev->devnum, iface_no, altno);
-                       continue;
-               }
+void snd_usb_init_substream(struct snd_usb_stream *as,
+                           int stream, struct audioformat *fp)
+{
+       struct snd_usb_substream *subs = &as->substream[stream];
+
+       INIT_LIST_HEAD(&subs->fmt_list);
+       spin_lock_init(&subs->lock);
+
+       subs->stream = as;
+       subs->direction = stream;
+       subs->dev = as->chip->dev;
+       subs->txfr_quirk = as->chip->txfr_quirk;
+       subs->ops = audio_urb_ops[stream];
+       if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH)
+               subs->ops.prepare_sync = prepare_capture_sync_urb_hs;
+
+       snd_usb_set_pcm_ops(as->pcm, stream);
+
+       list_add_tail(&fp->list, &subs->fmt_list);
+       subs->formats |= fp->formats;
+       subs->endpoint = fp->endpoint;
+       subs->num_formats++;
+       subs->fmt_type = fp->fmt_type;
+}
 
-               /*
-                * Blue Microphones workaround: The last altsetting is identical
-                * with the previous one, except for a larger packet size, but
-                * is actually a mislabeled two-channel setting; ignore it.
-                */
-               if (fmt->bNrChannels == 1 &&
-                   fmt->bSubframeSize == 2 &&
-                   altno == 2 && num == 3 &&
-                   fp && fp->altsetting == 1 && fp->channels == 1 &&
-                   fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
-                   protocol == UAC_VERSION_1 &&
-                   le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
-                                                       fp->maxpacksize * 2)
-                       continue;
-
-               fp = kzalloc(sizeof(*fp), GFP_KERNEL);
-               if (! fp) {
-                       snd_printk(KERN_ERR "cannot malloc\n");
-                       return -ENOMEM;
-               }
+int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_usb_substream *subs = substream->runtime->private_data;
 
-               fp->iface = iface_no;
-               fp->altsetting = altno;
-               fp->altset_idx = i;
-               fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
-               fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
-               fp->datainterval = snd_usb_parse_datainterval(chip, alts);
-               fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
-               /* num_channels is only set for v2 interfaces */
-               fp->channels = num_channels;
-               if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
-                       fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
-                                       * (fp->maxpacksize & 0x7ff);
-               fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
-               fp->clock = clock;
-
-               /* some quirks for attributes here */
-
-               switch (chip->usb_id) {
-               case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
-                       /* Optoplay sets the sample rate attribute although
-                        * it seems not supporting it in fact.
-                        */
-                       fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE;
-                       break;
-               case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
-               case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
-                       /* doesn't set the sample rate attribute, but supports it */
-                       fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
-                       break;
-               case USB_ID(0x0763, 0x2001):  /* M-Audio Quattro USB */
-               case USB_ID(0x0763, 0x2012):  /* M-Audio Fast Track Pro USB */
-               case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
-               case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
-                                               an older model 77d:223) */
-               /*
-                * plantronics headset and Griffin iMic have set adaptive-in
-                * although it's really not...
-                */
-                       fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE;
-                       if (stream == SNDRV_PCM_STREAM_PLAYBACK)
-                               fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE;
-                       else
-                               fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC;
-                       break;
-               }
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               subs->ops.prepare = prepare_playback_urb;
+               return 0;
+       case SNDRV_PCM_TRIGGER_STOP:
+               return deactivate_urbs(subs, 0, 0);
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               subs->ops.prepare = prepare_nodata_playback_urb;
+               return 0;
+       }
 
-               /* ok, let's parse further... */
-               if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
-                       kfree(fp->rate_table);
-                       kfree(fp);
-                       fp = NULL;
-                       continue;
-               }
+       return -EINVAL;
+}
 
-               snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
-               err = snd_usb_add_audio_endpoint(chip, stream, fp);
-               if (err < 0) {
-                       kfree(fp->rate_table);
-                       kfree(fp);
-                       return err;
-               }
-               /* try to set the interface... */
-               usb_set_interface(chip->dev, iface_no, altno);
-               snd_usb_init_pitch(chip, iface_no, alts, fp);
-               snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
+int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_usb_substream *subs = substream->runtime->private_data;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               subs->ops.retire = retire_capture_urb;
+               return start_urbs(subs, substream->runtime);
+       case SNDRV_PCM_TRIGGER_STOP:
+               return deactivate_urbs(subs, 0, 0);
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               subs->ops.retire = retire_paused_capture_urb;
+               return 0;
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               subs->ops.retire = retire_capture_urb;
+               return 0;
        }
+
+       return -EINVAL;
+}
+
+int snd_usb_substream_prepare(struct snd_usb_substream *subs,
+                             struct snd_pcm_runtime *runtime)
+{
+       /* clear urbs (to be sure) */
+       deactivate_urbs(subs, 0, 1);
+       wait_clear_urbs(subs);
+
+       /* for playback, submit the URBs now; otherwise, the first hwptr_done
+        * updates for all URBs would happen at the same time when starting */
+       if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
+               subs->ops.prepare = prepare_nodata_playback_urb;
+               return start_urbs(subs, runtime);
+       }
+
        return 0;
 }
 
index 64dd0db..88eb63a 100644 (file)
@@ -1,11 +1,21 @@
 #ifndef __USBAUDIO_ENDPOINT_H
 #define __USBAUDIO_ENDPOINT_H
 
-int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip,
-                                 int iface_no);
+void snd_usb_init_substream(struct snd_usb_stream *as,
+                           int stream,
+                           struct audioformat *fp);
 
-int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip,
-                              int stream,
-                              struct audioformat *fp);
+int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
+                               unsigned int period_bytes,
+                               unsigned int rate,
+                               unsigned int frame_bits);
+
+void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force);
+
+int snd_usb_substream_prepare(struct snd_usb_substream *subs,
+                             struct snd_pcm_runtime *runtime);
+
+int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd);
+int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd);
 
 #endif /* __USBAUDIO_ENDPOINT_H */
index f928910..e21f026 100644 (file)
@@ -816,6 +816,22 @@ static struct usb_protocol_ops snd_usbmidi_raw_ops = {
        .output = snd_usbmidi_raw_output,
 };
 
+/*
+ * FTDI protocol: raw MIDI bytes, but input packets have two modem status bytes.
+ */
+
+static void snd_usbmidi_ftdi_input(struct snd_usb_midi_in_endpoint* ep,
+                                  uint8_t* buffer, int buffer_length)
+{
+       if (buffer_length > 2)
+               snd_usbmidi_input_data(ep, 0, buffer + 2, buffer_length - 2);
+}
+
+static struct usb_protocol_ops snd_usbmidi_ftdi_ops = {
+       .input = snd_usbmidi_ftdi_input,
+       .output = snd_usbmidi_raw_output,
+};
+
 static void snd_usbmidi_us122l_input(struct snd_usb_midi_in_endpoint *ep,
                                     uint8_t *buffer, int buffer_length)
 {
@@ -2163,6 +2179,17 @@ int snd_usbmidi_create(struct snd_card *card,
                /* endpoint 1 is input-only */
                endpoints[1].out_cables = 0;
                break;
+       case QUIRK_MIDI_FTDI:
+               umidi->usb_protocol_ops = &snd_usbmidi_ftdi_ops;
+
+               /* set baud rate to 31250 (48 MHz / 16 / 96) */
+               err = usb_control_msg(umidi->dev, usb_sndctrlpipe(umidi->dev, 0),
+                                     3, 0x40, 0x60, 0, NULL, 0, 1000);
+               if (err < 0)
+                       break;
+
+               err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+               break;
        default:
                snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
                err = -ENXIO;
index c22fa76..78a5abd 100644 (file)
@@ -152,6 +152,7 @@ static inline void check_mapped_dB(const struct usbmix_name_map *p,
        if (p && p->dB) {
                cval->dBmin = p->dB->min;
                cval->dBmax = p->dB->max;
+               cval->initialized = 1;
        }
 }
 
@@ -880,8 +881,17 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
                uinfo->value.integer.min = 0;
                uinfo->value.integer.max = 1;
        } else {
-               if (! cval->initialized)
-                       get_min_max(cval,  0);
+               if (!cval->initialized) {
+                       get_min_max(cval, 0);
+                       if (cval->initialized && cval->dBmin >= cval->dBmax) {
+                               kcontrol->vd[0].access &= 
+                                       ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+                                         SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
+                               snd_ctl_notify(cval->mixer->chip->card,
+                                              SNDRV_CTL_EVENT_MASK_INFO,
+                                              &kcontrol->id);
+                       }
+               }
                uinfo->value.integer.min = 0;
                uinfo->value.integer.max =
                        (cval->max - cval->min + cval->res - 1) / cval->res;
@@ -1092,7 +1102,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
                                " Switch" : " Volume");
                if (control == UAC_FU_VOLUME) {
                        check_mapped_dB(map, cval);
-                       if (cval->dBmin < cval->dBmax) {
+                       if (cval->dBmin < cval->dBmax || !cval->initialized) {
                                kctl->tlv.c = mixer_vol_tlv;
                                kctl->vd[0].access |= 
                                        SNDRV_CTL_ELEM_ACCESS_TLV_READ |
@@ -1191,6 +1201,11 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
 
        if (state->mixer->protocol == UAC_VERSION_1) {
                csize = hdr->bControlSize;
+               if (!csize) {
+                       snd_printdd(KERN_ERR "usbaudio: unit %u: "
+                                   "invalid bControlSize == 0\n", unitid);
+                       return -EINVAL;
+               }
                channels = (hdr->bLength - 7) / csize - 1;
                bmaControls = hdr->bmaControls;
        } else {
@@ -1934,15 +1949,13 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
        struct mixer_build state;
        int err;
        const struct usbmix_ctl_map *map;
-       struct usb_host_interface *hostif;
        void *p;
 
-       hostif = mixer->chip->ctrl_intf;
        memset(&state, 0, sizeof(state));
        state.chip = mixer->chip;
        state.mixer = mixer;
-       state.buffer = hostif->extra;
-       state.buflen = hostif->extralen;
+       state.buffer = mixer->hostif->extra;
+       state.buflen = mixer->hostif->extralen;
 
        /* check the mapping table */
        for (map = usbmix_ctl_maps; map->id; map++) {
@@ -1955,7 +1968,8 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
        }
 
        p = NULL;
-       while ((p = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, p, UAC_OUTPUT_TERMINAL)) != NULL) {
+       while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen,
+                                           p, UAC_OUTPUT_TERMINAL)) != NULL) {
                if (mixer->protocol == UAC_VERSION_1) {
                        struct uac1_output_terminal_descriptor *desc = p;
 
@@ -2162,17 +2176,15 @@ int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
 /* create the handler for the optional status interrupt endpoint */
 static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
 {
-       struct usb_host_interface *hostif;
        struct usb_endpoint_descriptor *ep;
        void *transfer_buffer;
        int buffer_length;
        unsigned int epnum;
 
-       hostif = mixer->chip->ctrl_intf;
        /* we need one interrupt input endpoint */
-       if (get_iface_desc(hostif)->bNumEndpoints < 1)
+       if (get_iface_desc(mixer->hostif)->bNumEndpoints < 1)
                return 0;
-       ep = get_endpoint(hostif, 0);
+       ep = get_endpoint(mixer->hostif, 0);
        if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_int(ep))
                return 0;
 
@@ -2202,7 +2214,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
        };
        struct usb_mixer_interface *mixer;
        struct snd_info_entry *entry;
-       struct usb_host_interface *host_iface;
        int err;
 
        strcpy(chip->card->mixername, "USB Mixer");
@@ -2219,8 +2230,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
                return -ENOMEM;
        }
 
-       host_iface = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
-       switch (get_iface_desc(host_iface)->bInterfaceProtocol) {
+       mixer->hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
+       switch (get_iface_desc(mixer->hostif)->bInterfaceProtocol) {
        case UAC_VERSION_1:
        default:
                mixer->protocol = UAC_VERSION_1;
index ae1a14d..81b2d8a 100644 (file)
@@ -3,6 +3,7 @@
 
 struct usb_mixer_interface {
        struct snd_usb_audio *chip;
+       struct usb_host_interface *hostif;
        struct list_head list;
        unsigned int ignore_ctl_error;
        struct urb *urb;
index b8dcbf4..b5bc870 100644 (file)
 #include "card.h"
 #include "quirks.h"
 #include "debug.h"
-#include "urb.h"
+#include "endpoint.h"
 #include "helper.h"
 #include "pcm.h"
 #include "clock.h"
 #include "power.h"
 
+/* return the estimated delay based on USB frame counters */
+snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
+                                   unsigned int rate)
+{
+       int current_frame_number;
+       int frame_diff;
+       int est_delay;
+
+       current_frame_number = usb_get_current_frame_number(subs->dev);
+       /*
+        * HCD implementations use different widths, use lower 8 bits.
+        * The delay will be managed up to 256ms, which is more than
+        * enough
+        */
+       frame_diff = (current_frame_number - subs->last_frame_number) & 0xff;
+
+       /* Approximation based on number of samples per USB frame (ms),
+          some truncation for 44.1 but the estimate is good enough */
+       est_delay =  subs->last_delay - (frame_diff * rate / 1000);
+       if (est_delay < 0)
+               est_delay = 0;
+       return est_delay;
+}
+
 /*
  * return the current pcm pointer.  just based on the hwptr_done value.
  */
@@ -45,6 +69,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
        subs = (struct snd_usb_substream *)substream->runtime->private_data;
        spin_lock(&subs->lock);
        hwptr_done = subs->hwptr_done;
+       substream->runtime->delay = snd_usb_pcm_delay(subs,
+                                               substream->runtime->rate);
        spin_unlock(&subs->lock);
        return hwptr_done / (substream->runtime->frame_bits >> 3);
 }
@@ -417,6 +443,8 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
        subs->hwptr_done = 0;
        subs->transfer_done = 0;
        subs->phase = 0;
+       subs->last_delay = 0;
+       subs->last_frame_number = 0;
        runtime->delay = 0;
 
        return snd_usb_substream_prepare(subs, runtime);
index ed3e283..df7a003 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef __USBAUDIO_PCM_H
 #define __USBAUDIO_PCM_H
 
+snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
+                                   unsigned int rate);
+
 void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream);
 
 int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
index dba0b7f..b61945f 100644 (file)
        .idProduct = prod, \
        .bInterfaceClass = USB_CLASS_VENDOR_SPEC
 
+/* FTDI devices */
+{
+       USB_DEVICE(0x0403, 0xb8d8),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "STARR LABS", */
+               /* .product_name = "Starr Labs MIDI USB device", */
+               .ifnum = 0,
+               .type = QUIRK_MIDI_FTDI
+       }
+},
+
 /* Creative/Toshiba Multimedia Center SB-0500 */
 {
        USB_DEVICE(0x041e, 0x3048),
@@ -1677,6 +1688,20 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       /* Added support for Roland UM-ONE which differs from UM-1 */
+       USB_DEVICE(0x0582, 0x012a),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "ROLAND", */
+               /* .product_name = "UM-ONE", */
+               .ifnum = 0,
+               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+               .data = & (const struct snd_usb_midi_endpoint_info) {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0003
+               }
+       }
+},
 {
        USB_DEVICE(0x0582, 0x011e),
        .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
@@ -1707,6 +1732,40 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       USB_DEVICE(0x0582, 0x0130),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "BOSS", */
+               /* .product_name = "MICRO BR-80", */
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const struct snd_usb_midi_endpoint_info) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 
 /* Guillemot devices */
 {
@@ -2417,6 +2476,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .idProduct = 0x1020,
 },
 
+/* KeithMcMillen Stringport */
+{
+       USB_DEVICE(0x1f38, 0x0001),
+       .bInterfaceClass = USB_CLASS_AUDIO,
+},
+
 /* Miditech devices */
 {
        USB_DEVICE(0x4752, 0x0011),
index 77762c9..556edea 100644 (file)
@@ -34,6 +34,7 @@
 #include "endpoint.h"
 #include "pcm.h"
 #include "clock.h"
+#include "stream.h"
 
 /*
  * handle the quirks for the contained interfaces
@@ -106,7 +107,7 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
 
        alts = &iface->altsetting[0];
        altsd = get_iface_desc(alts);
-       err = snd_usb_parse_audio_endpoints(chip, altsd->bInterfaceNumber);
+       err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber);
        if (err < 0) {
                snd_printk(KERN_ERR "cannot setup if %d: error %d\n",
                           altsd->bInterfaceNumber, err);
@@ -147,7 +148,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 
        stream = (fp->endpoint & USB_DIR_IN)
                ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-       err = snd_usb_add_audio_endpoint(chip, stream, fp);
+       err = snd_usb_add_audio_stream(chip, stream, fp);
        if (err < 0) {
                kfree(fp);
                kfree(rate_table);
@@ -254,7 +255,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
 
        stream = (fp->endpoint & USB_DIR_IN)
                ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-       err = snd_usb_add_audio_endpoint(chip, stream, fp);
+       err = snd_usb_add_audio_stream(chip, stream, fp);
        if (err < 0) {
                kfree(fp);
                return err;
@@ -306,6 +307,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
                [QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
                [QUIRK_MIDI_CME] = create_any_midi_quirk,
                [QUIRK_MIDI_AKAI] = create_any_midi_quirk,
+               [QUIRK_MIDI_FTDI] = create_any_midi_quirk,
                [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
                [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
                [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
@@ -426,7 +428,7 @@ static int snd_usb_cm106_boot_quirk(struct usb_device *dev)
  */
 static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
 {
-       int err, reg;
+       int err  = 0, reg;
        int val[] = {0x2004, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000};
 
        for (reg = 0; reg < ARRAY_SIZE(val); reg++) {
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
new file mode 100644 (file)
index 0000000..5ff8010
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/audio-v2.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "usbaudio.h"
+#include "card.h"
+#include "proc.h"
+#include "quirks.h"
+#include "endpoint.h"
+#include "pcm.h"
+#include "helper.h"
+#include "format.h"
+#include "clock.h"
+#include "stream.h"
+
+/*
+ * free a substream
+ */
+static void free_substream(struct snd_usb_substream *subs)
+{
+       struct list_head *p, *n;
+
+       if (!subs->num_formats)
+               return; /* not initialized */
+       list_for_each_safe(p, n, &subs->fmt_list) {
+               struct audioformat *fp = list_entry(p, struct audioformat, list);
+               kfree(fp->rate_table);
+               kfree(fp);
+       }
+       kfree(subs->rate_list.list);
+}
+
+
+/*
+ * free a usb stream instance
+ */
+static void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
+{
+       free_substream(&stream->substream[0]);
+       free_substream(&stream->substream[1]);
+       list_del(&stream->list);
+       kfree(stream);
+}
+
+static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
+{
+       struct snd_usb_stream *stream = pcm->private_data;
+       if (stream) {
+               stream->pcm = NULL;
+               snd_usb_audio_stream_free(stream);
+       }
+}
+
+
+/*
+ * add this endpoint to the chip instance.
+ * if a stream with the same endpoint already exists, append to it.
+ * if not, create a new pcm stream.
+ */
+int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
+                            int stream,
+                            struct audioformat *fp)
+{
+       struct list_head *p;
+       struct snd_usb_stream *as;
+       struct snd_usb_substream *subs;
+       struct snd_pcm *pcm;
+       int err;
+
+       list_for_each(p, &chip->pcm_list) {
+               as = list_entry(p, struct snd_usb_stream, list);
+               if (as->fmt_type != fp->fmt_type)
+                       continue;
+               subs = &as->substream[stream];
+               if (!subs->endpoint)
+                       continue;
+               if (subs->endpoint == fp->endpoint) {
+                       list_add_tail(&fp->list, &subs->fmt_list);
+                       subs->num_formats++;
+                       subs->formats |= fp->formats;
+                       return 0;
+               }
+       }
+       /* look for an empty stream */
+       list_for_each(p, &chip->pcm_list) {
+               as = list_entry(p, struct snd_usb_stream, list);
+               if (as->fmt_type != fp->fmt_type)
+                       continue;
+               subs = &as->substream[stream];
+               if (subs->endpoint)
+                       continue;
+               err = snd_pcm_new_stream(as->pcm, stream, 1);
+               if (err < 0)
+                       return err;
+               snd_usb_init_substream(as, stream, fp);
+               return 0;
+       }
+
+       /* create a new pcm */
+       as = kzalloc(sizeof(*as), GFP_KERNEL);
+       if (!as)
+               return -ENOMEM;
+       as->pcm_index = chip->pcm_devs;
+       as->chip = chip;
+       as->fmt_type = fp->fmt_type;
+       err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
+                         stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
+                         stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
+                         &pcm);
+       if (err < 0) {
+               kfree(as);
+               return err;
+       }
+       as->pcm = pcm;
+       pcm->private_data = as;
+       pcm->private_free = snd_usb_audio_pcm_free;
+       pcm->info_flags = 0;
+       if (chip->pcm_devs > 0)
+               sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
+       else
+               strcpy(pcm->name, "USB Audio");
+
+       snd_usb_init_substream(as, stream, fp);
+
+       list_add(&as->list, &chip->pcm_list);
+       chip->pcm_devs++;
+
+       snd_usb_proc_pcm_format_add(as);
+
+       return 0;
+}
+
+static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
+                                        struct usb_host_interface *alts,
+                                        int protocol, int iface_no)
+{
+       /* parsed with a v1 header here. that's ok as we only look at the
+        * header first which is the same for both versions */
+       struct uac_iso_endpoint_descriptor *csep;
+       struct usb_interface_descriptor *altsd = get_iface_desc(alts);
+       int attributes = 0;
+
+       csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
+
+       /* Creamware Noah has this descriptor after the 2nd endpoint */
+       if (!csep && altsd->bNumEndpoints >= 2)
+               csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
+
+       if (!csep || csep->bLength < 7 ||
+           csep->bDescriptorSubtype != UAC_EP_GENERAL) {
+               snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
+                          " class specific endpoint descriptor\n",
+                          chip->dev->devnum, iface_no,
+                          altsd->bAlternateSetting);
+               return 0;
+       }
+
+       if (protocol == UAC_VERSION_1) {
+               attributes = csep->bmAttributes;
+       } else {
+               struct uac2_iso_endpoint_descriptor *csep2 =
+                       (struct uac2_iso_endpoint_descriptor *) csep;
+
+               attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
+
+               /* emulate the endpoint attributes of a v1 device */
+               if (csep2->bmControls & UAC2_CONTROL_PITCH)
+                       attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
+       }
+
+       return attributes;
+}
+
+static struct uac2_input_terminal_descriptor *
+       snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+                                              int terminal_id)
+{
+       struct uac2_input_terminal_descriptor *term = NULL;
+
+       while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
+                                              ctrl_iface->extralen,
+                                              term, UAC_INPUT_TERMINAL))) {
+               if (term->bTerminalID == terminal_id)
+                       return term;
+       }
+
+       return NULL;
+}
+
+static struct uac2_output_terminal_descriptor *
+       snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+                                               int terminal_id)
+{
+       struct uac2_output_terminal_descriptor *term = NULL;
+
+       while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
+                                              ctrl_iface->extralen,
+                                              term, UAC_OUTPUT_TERMINAL))) {
+               if (term->bTerminalID == terminal_id)
+                       return term;
+       }
+
+       return NULL;
+}
+
+int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
+{
+       struct usb_device *dev;
+       struct usb_interface *iface;
+       struct usb_host_interface *alts;
+       struct usb_interface_descriptor *altsd;
+       int i, altno, err, stream;
+       int format = 0, num_channels = 0;
+       struct audioformat *fp = NULL;
+       int num, protocol, clock = 0;
+       struct uac_format_type_i_continuous_descriptor *fmt;
+
+       dev = chip->dev;
+
+       /* parse the interface's altsettings */
+       iface = usb_ifnum_to_if(dev, iface_no);
+
+       num = iface->num_altsetting;
+
+       /*
+        * Dallas DS4201 workaround: It presents 5 altsettings, but the last
+        * one misses syncpipe, and does not produce any sound.
+        */
+       if (chip->usb_id == USB_ID(0x04fa, 0x4201))
+               num = 4;
+
+       for (i = 0; i < num; i++) {
+               alts = &iface->altsetting[i];
+               altsd = get_iface_desc(alts);
+               protocol = altsd->bInterfaceProtocol;
+               /* skip invalid one */
+               if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
+                    altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
+                   (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
+                    altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) ||
+                   altsd->bNumEndpoints < 1 ||
+                   le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
+                       continue;
+               /* must be isochronous */
+               if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
+                   USB_ENDPOINT_XFER_ISOC)
+                       continue;
+               /* check direction */
+               stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
+                       SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
+               altno = altsd->bAlternateSetting;
+
+               if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
+                       continue;
+
+               /* get audio formats */
+               switch (protocol) {
+               default:
+                       snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n",
+                                   dev->devnum, iface_no, altno, protocol);
+                       protocol = UAC_VERSION_1;
+                       /* fall through */
+
+               case UAC_VERSION_1: {
+                       struct uac1_as_header_descriptor *as =
+                               snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+
+                       if (!as) {
+                               snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
+                                          dev->devnum, iface_no, altno);
+                               continue;
+                       }
+
+                       if (as->bLength < sizeof(*as)) {
+                               snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
+                                          dev->devnum, iface_no, altno);
+                               continue;
+                       }
+
+                       format = le16_to_cpu(as->wFormatTag); /* remember the format value */
+                       break;
+               }
+
+               case UAC_VERSION_2: {
+                       struct uac2_input_terminal_descriptor *input_term;
+                       struct uac2_output_terminal_descriptor *output_term;
+                       struct uac2_as_header_descriptor *as =
+                               snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+
+                       if (!as) {
+                               snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
+                                          dev->devnum, iface_no, altno);
+                               continue;
+                       }
+
+                       if (as->bLength < sizeof(*as)) {
+                               snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
+                                          dev->devnum, iface_no, altno);
+                               continue;
+                       }
+
+                       num_channels = as->bNrChannels;
+                       format = le32_to_cpu(as->bmFormats);
+
+                       /* lookup the terminal associated to this interface
+                        * to extract the clock */
+                       input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
+                                                                           as->bTerminalLink);
+                       if (input_term) {
+                               clock = input_term->bCSourceID;
+                               break;
+                       }
+
+                       output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
+                                                                             as->bTerminalLink);
+                       if (output_term) {
+                               clock = output_term->bCSourceID;
+                               break;
+                       }
+
+                       snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n",
+                                  dev->devnum, iface_no, altno, as->bTerminalLink);
+                       continue;
+               }
+               }
+
+               /* get format type */
+               fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE);
+               if (!fmt) {
+                       snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n",
+                                  dev->devnum, iface_no, altno);
+                       continue;
+               }
+               if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
+                   ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
+                       snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
+                                  dev->devnum, iface_no, altno);
+                       continue;
+               }
+
+               /*
+                * Blue Microphones workaround: The last altsetting is identical
+                * with the previous one, except for a larger packet size, but
+                * is actually a mislabeled two-channel setting; ignore it.
+                */
+               if (fmt->bNrChannels == 1 &&
+                   fmt->bSubframeSize == 2 &&
+                   altno == 2 && num == 3 &&
+                   fp && fp->altsetting == 1 && fp->channels == 1 &&
+                   fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
+                   protocol == UAC_VERSION_1 &&
+                   le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
+                                                       fp->maxpacksize * 2)
+                       continue;
+
+               fp = kzalloc(sizeof(*fp), GFP_KERNEL);
+               if (! fp) {
+                       snd_printk(KERN_ERR "cannot malloc\n");
+                       return -ENOMEM;
+               }
+
+               fp->iface = iface_no;
+               fp->altsetting = altno;
+               fp->altset_idx = i;
+               fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
+               fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
+               fp->datainterval = snd_usb_parse_datainterval(chip, alts);
+               fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
+               /* num_channels is only set for v2 interfaces */
+               fp->channels = num_channels;
+               if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
+                       fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
+                                       * (fp->maxpacksize & 0x7ff);
+               fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
+               fp->clock = clock;
+
+               /* some quirks for attributes here */
+
+               switch (chip->usb_id) {
+               case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
+                       /* Optoplay sets the sample rate attribute although
+                        * it seems not supporting it in fact.
+                        */
+                       fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE;
+                       break;
+               case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
+               case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
+                       /* doesn't set the sample rate attribute, but supports it */
+                       fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
+                       break;
+               case USB_ID(0x0763, 0x2001):  /* M-Audio Quattro USB */
+               case USB_ID(0x0763, 0x2012):  /* M-Audio Fast Track Pro USB */
+               case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
+               case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
+                                               an older model 77d:223) */
+               /*
+                * plantronics headset and Griffin iMic have set adaptive-in
+                * although it's really not...
+                */
+                       fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE;
+                       if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+                               fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE;
+                       else
+                               fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC;
+                       break;
+               }
+
+               /* ok, let's parse further... */
+               if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
+                       kfree(fp->rate_table);
+                       kfree(fp);
+                       fp = NULL;
+                       continue;
+               }
+
+               snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
+               err = snd_usb_add_audio_stream(chip, stream, fp);
+               if (err < 0) {
+                       kfree(fp->rate_table);
+                       kfree(fp);
+                       return err;
+               }
+               /* try to set the interface... */
+               usb_set_interface(chip->dev, iface_no, altno);
+               snd_usb_init_pitch(chip, iface_no, alts, fp);
+               snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
+       }
+       return 0;
+}
+
diff --git a/sound/usb/stream.h b/sound/usb/stream.h
new file mode 100644 (file)
index 0000000..c97f679
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __USBAUDIO_STREAM_H
+#define __USBAUDIO_STREAM_H
+
+int snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
+                                 int iface_no);
+
+int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
+                            int stream,
+                            struct audioformat *fp);
+
+#endif /* __USBAUDIO_STREAM_H */
+
diff --git a/sound/usb/urb.c b/sound/usb/urb.c
deleted file mode 100644 (file)
index e184349..0000000
+++ /dev/null
@@ -1,941 +0,0 @@
-/*
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/usb/audio.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-
-#include "usbaudio.h"
-#include "helper.h"
-#include "card.h"
-#include "urb.h"
-#include "pcm.h"
-
-/*
- * convert a sampling rate into our full speed format (fs/1000 in Q16.16)
- * this will overflow at approx 524 kHz
- */
-static inline unsigned get_usb_full_speed_rate(unsigned int rate)
-{
-       return ((rate << 13) + 62) / 125;
-}
-
-/*
- * convert a sampling rate into USB high speed format (fs/8000 in Q16.16)
- * this will overflow at approx 4 MHz
- */
-static inline unsigned get_usb_high_speed_rate(unsigned int rate)
-{
-       return ((rate << 10) + 62) / 125;
-}
-
-/*
- * unlink active urbs.
- */
-static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sleep)
-{
-       struct snd_usb_audio *chip = subs->stream->chip;
-       unsigned int i;
-       int async;
-
-       subs->running = 0;
-
-       if (!force && subs->stream->chip->shutdown) /* to be sure... */
-               return -EBADFD;
-
-       async = !can_sleep && chip->async_unlink;
-
-       if (!async && in_interrupt())
-               return 0;
-
-       for (i = 0; i < subs->nurbs; i++) {
-               if (test_bit(i, &subs->active_mask)) {
-                       if (!test_and_set_bit(i, &subs->unlink_mask)) {
-                               struct urb *u = subs->dataurb[i].urb;
-                               if (async)
-                                       usb_unlink_urb(u);
-                               else
-                                       usb_kill_urb(u);
-                       }
-               }
-       }
-       if (subs->syncpipe) {
-               for (i = 0; i < SYNC_URBS; i++) {
-                       if (test_bit(i+16, &subs->active_mask)) {
-                               if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
-                                       struct urb *u = subs->syncurb[i].urb;
-                                       if (async)
-                                               usb_unlink_urb(u);
-                                       else
-                                               usb_kill_urb(u);
-                               }
-                       }
-               }
-       }
-       return 0;
-}
-
-
-/*
- * release a urb data
- */
-static void release_urb_ctx(struct snd_urb_ctx *u)
-{
-       if (u->urb) {
-               if (u->buffer_size)
-                       usb_free_coherent(u->subs->dev, u->buffer_size,
-                                       u->urb->transfer_buffer,
-                                       u->urb->transfer_dma);
-               usb_free_urb(u->urb);
-               u->urb = NULL;
-       }
-}
-
-/*
- *  wait until all urbs are processed.
- */
-static int wait_clear_urbs(struct snd_usb_substream *subs)
-{
-       unsigned long end_time = jiffies + msecs_to_jiffies(1000);
-       unsigned int i;
-       int alive;
-
-       do {
-               alive = 0;
-               for (i = 0; i < subs->nurbs; i++) {
-                       if (test_bit(i, &subs->active_mask))
-                               alive++;
-               }
-               if (subs->syncpipe) {
-                       for (i = 0; i < SYNC_URBS; i++) {
-                               if (test_bit(i + 16, &subs->active_mask))
-                                       alive++;
-                       }
-               }
-               if (! alive)
-                       break;
-               schedule_timeout_uninterruptible(1);
-       } while (time_before(jiffies, end_time));
-       if (alive)
-               snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
-       return 0;
-}
-
-/*
- * release a substream
- */
-void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force)
-{
-       int i;
-
-       /* stop urbs (to be sure) */
-       deactivate_urbs(subs, force, 1);
-       wait_clear_urbs(subs);
-
-       for (i = 0; i < MAX_URBS; i++)
-               release_urb_ctx(&subs->dataurb[i]);
-       for (i = 0; i < SYNC_URBS; i++)
-               release_urb_ctx(&subs->syncurb[i]);
-       usb_free_coherent(subs->dev, SYNC_URBS * 4,
-                       subs->syncbuf, subs->sync_dma);
-       subs->syncbuf = NULL;
-       subs->nurbs = 0;
-}
-
-/*
- * complete callback from data urb
- */
-static void snd_complete_urb(struct urb *urb)
-{
-       struct snd_urb_ctx *ctx = urb->context;
-       struct snd_usb_substream *subs = ctx->subs;
-       struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
-       int err = 0;
-
-       if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
-           !subs->running || /* can be stopped during retire callback */
-           (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
-           (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-               clear_bit(ctx->index, &subs->active_mask);
-               if (err < 0) {
-                       snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err);
-                       snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-               }
-       }
-}
-
-
-/*
- * complete callback from sync urb
- */
-static void snd_complete_sync_urb(struct urb *urb)
-{
-       struct snd_urb_ctx *ctx = urb->context;
-       struct snd_usb_substream *subs = ctx->subs;
-       struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
-       int err = 0;
-
-       if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
-           !subs->running || /* can be stopped during retire callback */
-           (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
-           (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-               clear_bit(ctx->index + 16, &subs->active_mask);
-               if (err < 0) {
-                       snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err);
-                       snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-               }
-       }
-}
-
-
-/*
- * initialize a substream for plaback/capture
- */
-int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
-                               unsigned int period_bytes,
-                               unsigned int rate,
-                               unsigned int frame_bits)
-{
-       unsigned int maxsize, i;
-       int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
-       unsigned int urb_packs, total_packs, packs_per_ms;
-       struct snd_usb_audio *chip = subs->stream->chip;
-
-       /* calculate the frequency in 16.16 format */
-       if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
-               subs->freqn = get_usb_full_speed_rate(rate);
-       else
-               subs->freqn = get_usb_high_speed_rate(rate);
-       subs->freqm = subs->freqn;
-       subs->freqshift = INT_MIN;
-       /* calculate max. frequency */
-       if (subs->maxpacksize) {
-               /* whatever fits into a max. size packet */
-               maxsize = subs->maxpacksize;
-               subs->freqmax = (maxsize / (frame_bits >> 3))
-                               << (16 - subs->datainterval);
-       } else {
-               /* no max. packet size: just take 25% higher than nominal */
-               subs->freqmax = subs->freqn + (subs->freqn >> 2);
-               maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3))
-                               >> (16 - subs->datainterval);
-       }
-       subs->phase = 0;
-
-       if (subs->fill_max)
-               subs->curpacksize = subs->maxpacksize;
-       else
-               subs->curpacksize = maxsize;
-
-       if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
-               packs_per_ms = 8 >> subs->datainterval;
-       else
-               packs_per_ms = 1;
-
-       if (is_playback) {
-               urb_packs = max(chip->nrpacks, 1);
-               urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
-       } else
-               urb_packs = 1;
-       urb_packs *= packs_per_ms;
-       if (subs->syncpipe)
-               urb_packs = min(urb_packs, 1U << subs->syncinterval);
-
-       /* decide how many packets to be used */
-       if (is_playback) {
-               unsigned int minsize, maxpacks;
-               /* determine how small a packet can be */
-               minsize = (subs->freqn >> (16 - subs->datainterval))
-                         * (frame_bits >> 3);
-               /* with sync from device, assume it can be 12% lower */
-               if (subs->syncpipe)
-                       minsize -= minsize >> 3;
-               minsize = max(minsize, 1u);
-               total_packs = (period_bytes + minsize - 1) / minsize;
-               /* we need at least two URBs for queueing */
-               if (total_packs < 2) {
-                       total_packs = 2;
-               } else {
-                       /* and we don't want too long a queue either */
-                       maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
-                       total_packs = min(total_packs, maxpacks);
-               }
-       } else {
-               while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
-                       urb_packs >>= 1;
-               total_packs = MAX_URBS * urb_packs;
-       }
-       subs->nurbs = (total_packs + urb_packs - 1) / urb_packs;
-       if (subs->nurbs > MAX_URBS) {
-               /* too much... */
-               subs->nurbs = MAX_URBS;
-               total_packs = MAX_URBS * urb_packs;
-       } else if (subs->nurbs < 2) {
-               /* too little - we need at least two packets
-                * to ensure contiguous playback/capture
-                */
-               subs->nurbs = 2;
-       }
-
-       /* allocate and initialize data urbs */
-       for (i = 0; i < subs->nurbs; i++) {
-               struct snd_urb_ctx *u = &subs->dataurb[i];
-               u->index = i;
-               u->subs = subs;
-               u->packets = (i + 1) * total_packs / subs->nurbs
-                       - i * total_packs / subs->nurbs;
-               u->buffer_size = maxsize * u->packets;
-               if (subs->fmt_type == UAC_FORMAT_TYPE_II)
-                       u->packets++; /* for transfer delimiter */
-               u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
-               if (!u->urb)
-                       goto out_of_memory;
-               u->urb->transfer_buffer =
-                       usb_alloc_coherent(subs->dev, u->buffer_size,
-                                          GFP_KERNEL, &u->urb->transfer_dma);
-               if (!u->urb->transfer_buffer)
-                       goto out_of_memory;
-               u->urb->pipe = subs->datapipe;
-               u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-               u->urb->interval = 1 << subs->datainterval;
-               u->urb->context = u;
-               u->urb->complete = snd_complete_urb;
-       }
-
-       if (subs->syncpipe) {
-               /* allocate and initialize sync urbs */
-               subs->syncbuf = usb_alloc_coherent(subs->dev, SYNC_URBS * 4,
-                                                GFP_KERNEL, &subs->sync_dma);
-               if (!subs->syncbuf)
-                       goto out_of_memory;
-               for (i = 0; i < SYNC_URBS; i++) {
-                       struct snd_urb_ctx *u = &subs->syncurb[i];
-                       u->index = i;
-                       u->subs = subs;
-                       u->packets = 1;
-                       u->urb = usb_alloc_urb(1, GFP_KERNEL);
-                       if (!u->urb)
-                               goto out_of_memory;
-                       u->urb->transfer_buffer = subs->syncbuf + i * 4;
-                       u->urb->transfer_dma = subs->sync_dma + i * 4;
-                       u->urb->transfer_buffer_length = 4;
-                       u->urb->pipe = subs->syncpipe;
-                       u->urb->transfer_flags = URB_ISO_ASAP |
-                                                URB_NO_TRANSFER_DMA_MAP;
-                       u->urb->number_of_packets = 1;
-                       u->urb->interval = 1 << subs->syncinterval;
-                       u->urb->context = u;
-                       u->urb->complete = snd_complete_sync_urb;
-               }
-       }
-       return 0;
-
-out_of_memory:
-       snd_usb_release_substream_urbs(subs, 0);
-       return -ENOMEM;
-}
-
-/*
- * prepare urb for full speed capture sync pipe
- *
- * fill the length and offset of each urb descriptor.
- * the fixed 10.14 frequency is passed through the pipe.
- */
-static int prepare_capture_sync_urb(struct snd_usb_substream *subs,
-                                   struct snd_pcm_runtime *runtime,
-                                   struct urb *urb)
-{
-       unsigned char *cp = urb->transfer_buffer;
-       struct snd_urb_ctx *ctx = urb->context;
-
-       urb->dev = ctx->subs->dev; /* we need to set this at each time */
-       urb->iso_frame_desc[0].length = 3;
-       urb->iso_frame_desc[0].offset = 0;
-       cp[0] = subs->freqn >> 2;
-       cp[1] = subs->freqn >> 10;
-       cp[2] = subs->freqn >> 18;
-       return 0;
-}
-
-/*
- * prepare urb for high speed capture sync pipe
- *
- * fill the length and offset of each urb descriptor.
- * the fixed 12.13 frequency is passed as 16.16 through the pipe.
- */
-static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs,
-                                      struct snd_pcm_runtime *runtime,
-                                      struct urb *urb)
-{
-       unsigned char *cp = urb->transfer_buffer;
-       struct snd_urb_ctx *ctx = urb->context;
-
-       urb->dev = ctx->subs->dev; /* we need to set this at each time */
-       urb->iso_frame_desc[0].length = 4;
-       urb->iso_frame_desc[0].offset = 0;
-       cp[0] = subs->freqn;
-       cp[1] = subs->freqn >> 8;
-       cp[2] = subs->freqn >> 16;
-       cp[3] = subs->freqn >> 24;
-       return 0;
-}
-
-/*
- * process after capture sync complete
- * - nothing to do
- */
-static int retire_capture_sync_urb(struct snd_usb_substream *subs,
-                                  struct snd_pcm_runtime *runtime,
-                                  struct urb *urb)
-{
-       return 0;
-}
-
-/*
- * prepare urb for capture data pipe
- *
- * fill the offset and length of each descriptor.
- *
- * we use a temporary buffer to write the captured data.
- * since the length of written data is determined by host, we cannot
- * write onto the pcm buffer directly...  the data is thus copied
- * later at complete callback to the global buffer.
- */
-static int prepare_capture_urb(struct snd_usb_substream *subs,
-                              struct snd_pcm_runtime *runtime,
-                              struct urb *urb)
-{
-       int i, offs;
-       struct snd_urb_ctx *ctx = urb->context;
-
-       offs = 0;
-       urb->dev = ctx->subs->dev; /* we need to set this at each time */
-       for (i = 0; i < ctx->packets; i++) {
-               urb->iso_frame_desc[i].offset = offs;
-               urb->iso_frame_desc[i].length = subs->curpacksize;
-               offs += subs->curpacksize;
-       }
-       urb->transfer_buffer_length = offs;
-       urb->number_of_packets = ctx->packets;
-       return 0;
-}
-
-/*
- * process after capture complete
- *
- * copy the data from each desctiptor to the pcm buffer, and
- * update the current position.
- */
-static int retire_capture_urb(struct snd_usb_substream *subs,
-                             struct snd_pcm_runtime *runtime,
-                             struct urb *urb)
-{
-       unsigned long flags;
-       unsigned char *cp;
-       int i;
-       unsigned int stride, frames, bytes, oldptr;
-       int period_elapsed = 0;
-
-       stride = runtime->frame_bits >> 3;
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-               if (urb->iso_frame_desc[i].status) {
-                       snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
-                       // continue;
-               }
-               bytes = urb->iso_frame_desc[i].actual_length;
-               frames = bytes / stride;
-               if (!subs->txfr_quirk)
-                       bytes = frames * stride;
-               if (bytes % (runtime->sample_bits >> 3) != 0) {
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-                       int oldbytes = bytes;
-#endif
-                       bytes = frames * stride;
-                       snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
-                                                       oldbytes, bytes);
-               }
-               /* update the current pointer */
-               spin_lock_irqsave(&subs->lock, flags);
-               oldptr = subs->hwptr_done;
-               subs->hwptr_done += bytes;
-               if (subs->hwptr_done >= runtime->buffer_size * stride)
-                       subs->hwptr_done -= runtime->buffer_size * stride;
-               frames = (bytes + (oldptr % stride)) / stride;
-               subs->transfer_done += frames;
-               if (subs->transfer_done >= runtime->period_size) {
-                       subs->transfer_done -= runtime->period_size;
-                       period_elapsed = 1;
-               }
-               spin_unlock_irqrestore(&subs->lock, flags);
-               /* copy a data chunk */
-               if (oldptr + bytes > runtime->buffer_size * stride) {
-                       unsigned int bytes1 =
-                                       runtime->buffer_size * stride - oldptr;
-                       memcpy(runtime->dma_area + oldptr, cp, bytes1);
-                       memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
-               } else {
-                       memcpy(runtime->dma_area + oldptr, cp, bytes);
-               }
-       }
-       if (period_elapsed)
-               snd_pcm_period_elapsed(subs->pcm_substream);
-       return 0;
-}
-
-/*
- * Process after capture complete when paused.  Nothing to do.
- */
-static int retire_paused_capture_urb(struct snd_usb_substream *subs,
-                                    struct snd_pcm_runtime *runtime,
-                                    struct urb *urb)
-{
-       return 0;
-}
-
-
-/*
- * prepare urb for playback sync pipe
- *
- * set up the offset and length to receive the current frequency.
- */
-static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
-                                    struct snd_pcm_runtime *runtime,
-                                    struct urb *urb)
-{
-       struct snd_urb_ctx *ctx = urb->context;
-
-       urb->dev = ctx->subs->dev; /* we need to set this at each time */
-       urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize);
-       urb->iso_frame_desc[0].offset = 0;
-       return 0;
-}
-
-/*
- * process after playback sync complete
- *
- * Full speed devices report feedback values in 10.14 format as samples per
- * frame, high speed devices in 16.16 format as samples per microframe.
- * Because the Audio Class 1 spec was written before USB 2.0, many high speed
- * devices use a wrong interpretation, some others use an entirely different
- * format.  Therefore, we cannot predict what format any particular device uses
- * and must detect it automatically.
- */
-static int retire_playback_sync_urb(struct snd_usb_substream *subs,
-                                   struct snd_pcm_runtime *runtime,
-                                   struct urb *urb)
-{
-       unsigned int f;
-       int shift;
-       unsigned long flags;
-
-       if (urb->iso_frame_desc[0].status != 0 ||
-           urb->iso_frame_desc[0].actual_length < 3)
-               return 0;
-
-       f = le32_to_cpup(urb->transfer_buffer);
-       if (urb->iso_frame_desc[0].actual_length == 3)
-               f &= 0x00ffffff;
-       else
-               f &= 0x0fffffff;
-       if (f == 0)
-               return 0;
-
-       if (unlikely(subs->freqshift == INT_MIN)) {
-               /*
-                * The first time we see a feedback value, determine its format
-                * by shifting it left or right until it matches the nominal
-                * frequency value.  This assumes that the feedback does not
-                * differ from the nominal value more than +50% or -25%.
-                */
-               shift = 0;
-               while (f < subs->freqn - subs->freqn / 4) {
-                       f <<= 1;
-                       shift++;
-               }
-               while (f > subs->freqn + subs->freqn / 2) {
-                       f >>= 1;
-                       shift--;
-               }
-               subs->freqshift = shift;
-       }
-       else if (subs->freqshift >= 0)
-               f <<= subs->freqshift;
-       else
-               f >>= -subs->freqshift;
-
-       if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) {
-               /*
-                * If the frequency looks valid, set it.
-                * This value is referred to in prepare_playback_urb().
-                */
-               spin_lock_irqsave(&subs->lock, flags);
-               subs->freqm = f;
-               spin_unlock_irqrestore(&subs->lock, flags);
-       } else {
-               /*
-                * Out of range; maybe the shift value is wrong.
-                * Reset it so that we autodetect again the next time.
-                */
-               subs->freqshift = INT_MIN;
-       }
-
-       return 0;
-}
-
-/* determine the number of frames in the next packet */
-static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
-{
-       if (subs->fill_max)
-               return subs->maxframesize;
-       else {
-               subs->phase = (subs->phase & 0xffff)
-                       + (subs->freqm << subs->datainterval);
-               return min(subs->phase >> 16, subs->maxframesize);
-       }
-}
-
-/*
- * Prepare urb for streaming before playback starts or when paused.
- *
- * We don't have any data, so we send silence.
- */
-static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
-                                      struct snd_pcm_runtime *runtime,
-                                      struct urb *urb)
-{
-       unsigned int i, offs, counts;
-       struct snd_urb_ctx *ctx = urb->context;
-       int stride = runtime->frame_bits >> 3;
-
-       offs = 0;
-       urb->dev = ctx->subs->dev;
-       for (i = 0; i < ctx->packets; ++i) {
-               counts = snd_usb_audio_next_packet_size(subs);
-               urb->iso_frame_desc[i].offset = offs * stride;
-               urb->iso_frame_desc[i].length = counts * stride;
-               offs += counts;
-       }
-       urb->number_of_packets = ctx->packets;
-       urb->transfer_buffer_length = offs * stride;
-       memset(urb->transfer_buffer,
-              runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
-              offs * stride);
-       return 0;
-}
-
-/*
- * prepare urb for playback data pipe
- *
- * Since a URB can handle only a single linear buffer, we must use double
- * buffering when the data to be transferred overflows the buffer boundary.
- * To avoid inconsistencies when updating hwptr_done, we use double buffering
- * for all URBs.
- */
-static int prepare_playback_urb(struct snd_usb_substream *subs,
-                               struct snd_pcm_runtime *runtime,
-                               struct urb *urb)
-{
-       int i, stride;
-       unsigned int counts, frames, bytes;
-       unsigned long flags;
-       int period_elapsed = 0;
-       struct snd_urb_ctx *ctx = urb->context;
-
-       stride = runtime->frame_bits >> 3;
-
-       frames = 0;
-       urb->dev = ctx->subs->dev; /* we need to set this at each time */
-       urb->number_of_packets = 0;
-       spin_lock_irqsave(&subs->lock, flags);
-       for (i = 0; i < ctx->packets; i++) {
-               counts = snd_usb_audio_next_packet_size(subs);
-               /* set up descriptor */
-               urb->iso_frame_desc[i].offset = frames * stride;
-               urb->iso_frame_desc[i].length = counts * stride;
-               frames += counts;
-               urb->number_of_packets++;
-               subs->transfer_done += counts;
-               if (subs->transfer_done >= runtime->period_size) {
-                       subs->transfer_done -= runtime->period_size;
-                       period_elapsed = 1;
-                       if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
-                               if (subs->transfer_done > 0) {
-                                       /* FIXME: fill-max mode is not
-                                        * supported yet */
-                                       frames -= subs->transfer_done;
-                                       counts -= subs->transfer_done;
-                                       urb->iso_frame_desc[i].length =
-                                               counts * stride;
-                                       subs->transfer_done = 0;
-                               }
-                               i++;
-                               if (i < ctx->packets) {
-                                       /* add a transfer delimiter */
-                                       urb->iso_frame_desc[i].offset =
-                                               frames * stride;
-                                       urb->iso_frame_desc[i].length = 0;
-                                       urb->number_of_packets++;
-                               }
-                               break;
-                       }
-               }
-               if (period_elapsed) /* finish at the period boundary */
-                       break;
-       }
-       bytes = frames * stride;
-       if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
-               /* err, the transferred area goes over buffer boundary. */
-               unsigned int bytes1 =
-                       runtime->buffer_size * stride - subs->hwptr_done;
-               memcpy(urb->transfer_buffer,
-                      runtime->dma_area + subs->hwptr_done, bytes1);
-               memcpy(urb->transfer_buffer + bytes1,
-                      runtime->dma_area, bytes - bytes1);
-       } else {
-               memcpy(urb->transfer_buffer,
-                      runtime->dma_area + subs->hwptr_done, bytes);
-       }
-       subs->hwptr_done += bytes;
-       if (subs->hwptr_done >= runtime->buffer_size * stride)
-               subs->hwptr_done -= runtime->buffer_size * stride;
-       runtime->delay += frames;
-       spin_unlock_irqrestore(&subs->lock, flags);
-       urb->transfer_buffer_length = bytes;
-       if (period_elapsed)
-               snd_pcm_period_elapsed(subs->pcm_substream);
-       return 0;
-}
-
-/*
- * process after playback data complete
- * - decrease the delay count again
- */
-static int retire_playback_urb(struct snd_usb_substream *subs,
-                              struct snd_pcm_runtime *runtime,
-                              struct urb *urb)
-{
-       unsigned long flags;
-       int stride = runtime->frame_bits >> 3;
-       int processed = urb->transfer_buffer_length / stride;
-
-       spin_lock_irqsave(&subs->lock, flags);
-       if (processed > runtime->delay)
-               runtime->delay = 0;
-       else
-               runtime->delay -= processed;
-       spin_unlock_irqrestore(&subs->lock, flags);
-       return 0;
-}
-
-static const char *usb_error_string(int err)
-{
-       switch (err) {
-       case -ENODEV:
-               return "no device";
-       case -ENOENT:
-               return "endpoint not enabled";
-       case -EPIPE:
-               return "endpoint stalled";
-       case -ENOSPC:
-               return "not enough bandwidth";
-       case -ESHUTDOWN:
-               return "device disabled";
-       case -EHOSTUNREACH:
-               return "device suspended";
-       case -EINVAL:
-       case -EAGAIN:
-       case -EFBIG:
-       case -EMSGSIZE:
-               return "internal error";
-       default:
-               return "unknown error";
-       }
-}
-
-/*
- * set up and start data/sync urbs
- */
-static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime)
-{
-       unsigned int i;
-       int err;
-
-       if (subs->stream->chip->shutdown)
-               return -EBADFD;
-
-       for (i = 0; i < subs->nurbs; i++) {
-               if (snd_BUG_ON(!subs->dataurb[i].urb))
-                       return -EINVAL;
-               if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) {
-                       snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i);
-                       goto __error;
-               }
-       }
-       if (subs->syncpipe) {
-               for (i = 0; i < SYNC_URBS; i++) {
-                       if (snd_BUG_ON(!subs->syncurb[i].urb))
-                               return -EINVAL;
-                       if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) {
-                               snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i);
-                               goto __error;
-                       }
-               }
-       }
-
-       subs->active_mask = 0;
-       subs->unlink_mask = 0;
-       subs->running = 1;
-       for (i = 0; i < subs->nurbs; i++) {
-               err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC);
-               if (err < 0) {
-                       snd_printk(KERN_ERR "cannot submit datapipe "
-                                  "for urb %d, error %d: %s\n",
-                                  i, err, usb_error_string(err));
-                       goto __error;
-               }
-               set_bit(i, &subs->active_mask);
-       }
-       if (subs->syncpipe) {
-               for (i = 0; i < SYNC_URBS; i++) {
-                       err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC);
-                       if (err < 0) {
-                               snd_printk(KERN_ERR "cannot submit syncpipe "
-                                          "for urb %d, error %d: %s\n",
-                                          i, err, usb_error_string(err));
-                               goto __error;
-                       }
-                       set_bit(i + 16, &subs->active_mask);
-               }
-       }
-       return 0;
-
- __error:
-       // snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
-       deactivate_urbs(subs, 0, 0);
-       return -EPIPE;
-}
-
-
-/*
- */
-static struct snd_urb_ops audio_urb_ops[2] = {
-       {
-               .prepare =      prepare_nodata_playback_urb,
-               .retire =       retire_playback_urb,
-               .prepare_sync = prepare_playback_sync_urb,
-               .retire_sync =  retire_playback_sync_urb,
-       },
-       {
-               .prepare =      prepare_capture_urb,
-               .retire =       retire_capture_urb,
-               .prepare_sync = prepare_capture_sync_urb,
-               .retire_sync =  retire_capture_sync_urb,
-       },
-};
-
-/*
- * initialize the substream instance.
- */
-
-void snd_usb_init_substream(struct snd_usb_stream *as,
-                           int stream, struct audioformat *fp)
-{
-       struct snd_usb_substream *subs = &as->substream[stream];
-
-       INIT_LIST_HEAD(&subs->fmt_list);
-       spin_lock_init(&subs->lock);
-
-       subs->stream = as;
-       subs->direction = stream;
-       subs->dev = as->chip->dev;
-       subs->txfr_quirk = as->chip->txfr_quirk;
-       subs->ops = audio_urb_ops[stream];
-       if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH)
-               subs->ops.prepare_sync = prepare_capture_sync_urb_hs;
-
-       snd_usb_set_pcm_ops(as->pcm, stream);
-
-       list_add_tail(&fp->list, &subs->fmt_list);
-       subs->formats |= fp->formats;
-       subs->endpoint = fp->endpoint;
-       subs->num_formats++;
-       subs->fmt_type = fp->fmt_type;
-}
-
-int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       struct snd_usb_substream *subs = substream->runtime->private_data;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               subs->ops.prepare = prepare_playback_urb;
-               return 0;
-       case SNDRV_PCM_TRIGGER_STOP:
-               return deactivate_urbs(subs, 0, 0);
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               subs->ops.prepare = prepare_nodata_playback_urb;
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
-int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       struct snd_usb_substream *subs = substream->runtime->private_data;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               subs->ops.retire = retire_capture_urb;
-               return start_urbs(subs, substream->runtime);
-       case SNDRV_PCM_TRIGGER_STOP:
-               return deactivate_urbs(subs, 0, 0);
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               subs->ops.retire = retire_paused_capture_urb;
-               return 0;
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               subs->ops.retire = retire_capture_urb;
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
-int snd_usb_substream_prepare(struct snd_usb_substream *subs,
-                             struct snd_pcm_runtime *runtime)
-{
-       /* clear urbs (to be sure) */
-       deactivate_urbs(subs, 0, 1);
-       wait_clear_urbs(subs);
-
-       /* for playback, submit the URBs now; otherwise, the first hwptr_done
-        * updates for all URBs would happen at the same time when starting */
-       if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
-               subs->ops.prepare = prepare_nodata_playback_urb;
-               return start_urbs(subs, runtime);
-       }
-
-       return 0;
-}
-
diff --git a/sound/usb/urb.h b/sound/usb/urb.h
deleted file mode 100644 (file)
index 888da38..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __USBAUDIO_URB_H
-#define __USBAUDIO_URB_H
-
-void snd_usb_init_substream(struct snd_usb_stream *as,
-                           int stream,
-                           struct audioformat *fp);
-
-int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
-                               unsigned int period_bytes,
-                               unsigned int rate,
-                               unsigned int frame_bits);
-
-void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force);
-
-int snd_usb_substream_prepare(struct snd_usb_substream *subs,
-                             struct snd_pcm_runtime *runtime);
-
-int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd);
-int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd);
-
-#endif /* __USBAUDIO_URB_H */
index 1e79986..3e2b035 100644 (file)
@@ -80,6 +80,7 @@ enum quirk_type {
        QUIRK_MIDI_CME,
        QUIRK_MIDI_AKAI,
        QUIRK_MIDI_US122L,
+       QUIRK_MIDI_FTDI,
        QUIRK_AUDIO_STANDARD_INTERFACE,
        QUIRK_AUDIO_FIXED_ENDPOINT,
        QUIRK_AUDIO_EDIROL_UAXX,