sound: usb-audio: do not make URBs longer than sync packet interval
[safe/jmp/linux-2.6] / sound / usb / usbaudio.c
index 410be4a..fa3f7a1 100644 (file)
@@ -71,6 +71,7 @@ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
 static int nrpacks = 8;                /* max. number of packets per urb */
 static int async_unlink = 1;
 static int device_setup[SNDRV_CARDS]; /* device parameter for this card*/
+static int ignore_ctl_error;
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
@@ -88,7 +89,9 @@ module_param(async_unlink, bool, 0444);
 MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
 module_param_array(device_setup, int, NULL, 0444);
 MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
-
+module_param(ignore_ctl_error, bool, 0444);
+MODULE_PARM_DESC(ignore_ctl_error,
+                "Ignore errors from USB controller for mixer interfaces.");
 
 /*
  * debug the h/w constraints
@@ -104,7 +107,7 @@ MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
 #define MAX_PACKS_HS   (MAX_PACKS * 8) /* in high speed mode */
 #define MAX_URBS       8
 #define SYNC_URBS      4       /* always four urbs for sync */
-#define MIN_PACKS_URB  1       /* minimum 1 packet per urb */
+#define MAX_QUEUE      24      /* try not to exceed this queue length, in ms */
 
 struct audioformat {
        struct list_head list;
@@ -118,6 +121,7 @@ struct audioformat {
        unsigned char attributes;       /* corresponding attributes of cs endpoint */
        unsigned char endpoint;         /* endpoint */
        unsigned char ep_attr;          /* endpoint attributes */
+       unsigned char datainterval;     /* log_2 of data packet interval */
        unsigned int maxpacksize;       /* max. packet size */
        unsigned int rates;             /* rate bitmasks */
        unsigned int rate_min, rate_max;        /* min/max rates */
@@ -167,7 +171,6 @@ struct snd_usb_substream {
        unsigned int curframesize;      /* current packet size in frames (for capture) */
        unsigned int fill_max: 1;       /* fill max packet size always */
        unsigned int fmt_type;          /* USB audio format type (1-3) */
-       unsigned int packs_per_ms;      /* packets per millisecond (for playback) */
 
        unsigned int running: 1;        /* running status */
 
@@ -481,7 +484,7 @@ static int retire_playback_sync_urb_hs(struct snd_usb_substream *subs,
 }
 
 /*
- * process after E-Mu 0202/0404 high speed playback sync complete
+ * process after E-Mu 0202/0404/Tracker Pre high speed playback sync complete
  *
  * These devices return the number of samples per packet instead of the number
  * of samples per microframe.
@@ -522,7 +525,7 @@ static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
 /*
  * Prepare urb for streaming before playback starts or when paused.
  *
- * We don't have any data, so we send a frame of silence.
+ * 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,
@@ -534,13 +537,13 @@ static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
 
        offs = 0;
        urb->dev = ctx->subs->dev;
-       urb->number_of_packets = subs->packs_per_ms;
-       for (i = 0; i < subs->packs_per_ms; ++i) {
+       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,
               subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
@@ -604,9 +607,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
                                break;
                        }
                }
-               /* finish at the frame boundary at/after the period boundary */
-               if (period_elapsed &&
-                   (i & (subs->packs_per_ms - 1)) == subs->packs_per_ms - 1)
+               if (period_elapsed) /* finish at the period boundary */
                        break;
        }
        if (subs->hwptr_done + offs > runtime->buffer_size) {
@@ -626,6 +627,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
        subs->hwptr_done += offs;
        if (subs->hwptr_done >= runtime->buffer_size)
                subs->hwptr_done -= runtime->buffer_size;
+       runtime->delay += offs;
        spin_unlock_irqrestore(&subs->lock, flags);
        urb->transfer_buffer_length = offs * stride;
        if (period_elapsed)
@@ -635,12 +637,22 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
 
 /*
  * process after playback data complete
- * - nothing to do
+ * - 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;
 }
 
@@ -819,10 +831,6 @@ static const char *usb_error_string(int err)
                return "device disabled";
        case -EHOSTUNREACH:
                return "device suspended";
-#ifndef CONFIG_USB_EHCI_SPLIT_ISO
-       case -ENOSYS:
-               return "enable CONFIG_USB_EHCI_SPLIT_ISO to play through a hub";
-#endif
        case -EINVAL:
        case -EAGAIN:
        case -EFBIG:
@@ -845,7 +853,8 @@ static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *ru
                return -EBADFD;
 
        for (i = 0; i < subs->nurbs; i++) {
-               snd_assert(subs->dataurb[i].urb, return -EINVAL);
+               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;
@@ -853,7 +862,8 @@ static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *ru
        }
        if (subs->syncpipe) {
                for (i = 0; i < SYNC_URBS; i++) {
-                       snd_assert(subs->syncurb[i].urb, return -EINVAL);
+                       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;
@@ -1033,9 +1043,9 @@ static void release_substream_urbs(struct snd_usb_substream *subs, int force)
 static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int period_bytes,
                               unsigned int rate, unsigned int frame_bits)
 {
-       unsigned int maxsize, n, i;
+       unsigned int maxsize, i;
        int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
-       unsigned int npacks[MAX_URBS], urb_packs, total_packs, packs_per_ms;
+       unsigned int urb_packs, total_packs, packs_per_ms;
 
        /* calculate the frequency in 16.16 format */
        if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
@@ -1066,19 +1076,19 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
                packs_per_ms = 8 >> subs->datainterval;
        else
                packs_per_ms = 1;
-       subs->packs_per_ms = packs_per_ms;
 
        if (is_playback) {
-               urb_packs = nrpacks;
-               urb_packs = max(urb_packs, (unsigned int)MIN_PACKS_URB);
+               urb_packs = max(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, 1 << subs->syncinterval);
 
        /* decide how many packets to be used */
        if (is_playback) {
-               unsigned int minsize;
+               unsigned int minsize, maxpacks;
                /* determine how small a packet can be */
                minsize = (subs->freqn >> (16 - subs->datainterval))
                          * (frame_bits >> 3);
@@ -1087,13 +1097,17 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
                        minsize -= minsize >> 3;
                minsize = max(minsize, 1u);
                total_packs = (period_bytes + minsize - 1) / minsize;
-               /* round up to multiple of packs_per_ms */
-               total_packs = (total_packs + packs_per_ms - 1)
-                               & ~(packs_per_ms - 1);
                /* we need at least two URBs for queueing */
-               if (total_packs < 2 * MIN_PACKS_URB * packs_per_ms)
-                       total_packs = 2 * MIN_PACKS_URB * packs_per_ms;
+               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;
@@ -1101,31 +1115,11 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
                /* too much... */
                subs->nurbs = MAX_URBS;
                total_packs = MAX_URBS * urb_packs;
-       }
-       n = total_packs;
-       for (i = 0; i < subs->nurbs; i++) {
-               npacks[i] = n > urb_packs ? urb_packs : n;
-               n -= urb_packs;
-       }
-       if (subs->nurbs <= 1) {
+       } else if (subs->nurbs < 2) {
                /* too little - we need at least two packets
                 * to ensure contiguous playback/capture
                 */
                subs->nurbs = 2;
-               npacks[0] = (total_packs + 1) / 2;
-               npacks[1] = total_packs - npacks[0];
-       } else if (npacks[subs->nurbs-1] < MIN_PACKS_URB * packs_per_ms) {
-               /* the last packet is too small.. */
-               if (subs->nurbs > 2) {
-                       /* merge to the first one */
-                       npacks[0] += npacks[subs->nurbs - 1];
-                       subs->nurbs--;
-               } else {
-                       /* divide to two */
-                       subs->nurbs = 2;
-                       npacks[0] = (total_packs + 1) / 2;
-                       npacks[1] = total_packs - npacks[0];
-               }
        }
 
        /* allocate and initialize data urbs */
@@ -1133,7 +1127,8 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
                struct snd_urb_ctx *u = &subs->dataurb[i];
                u->index = i;
                u->subs = subs;
-               u->packets = npacks[i];
+               u->packets = (i + 1) * total_packs / subs->nurbs
+                       - i * total_packs / subs->nurbs;
                u->buffer_size = maxsize * u->packets;
                if (subs->fmt_type == USB_FORMAT_TYPE_II)
                        u->packets++; /* for transfer delimiter */
@@ -1291,14 +1286,14 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface,
                if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
                                           USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
                                           SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
-                       snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n",
+                       snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
                                   dev->devnum, iface, fmt->altsetting, rate, ep);
                        return err;
                }
                if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR,
                                           USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
                                           SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
-                       snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n",
+                       snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
                                   dev->devnum, iface, fmt->altsetting, ep);
                        return 0; /* some devices don't support reading */
                }
@@ -1325,10 +1320,12 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
        int err;
 
        iface = usb_ifnum_to_if(dev, fmt->iface);
-       snd_assert(iface, return -EINVAL);
+       if (WARN_ON(!iface))
+               return -EINVAL;
        alts = &iface->altsetting[fmt->altset_idx];
        altsd = get_iface_desc(alts);
-       snd_assert(altsd->bAlternateSetting == fmt->altsetting, return -EINVAL);
+       if (WARN_ON(altsd->bAlternateSetting != fmt->altsetting))
+               return -EINVAL;
 
        if (fmt == subs->cur_audiofmt)
                return 0;
@@ -1362,12 +1359,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
                subs->datapipe = usb_sndisocpipe(dev, ep);
        else
                subs->datapipe = usb_rcvisocpipe(dev, ep);
-       if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH &&
-           get_endpoint(alts, 0)->bInterval >= 1 &&
-           get_endpoint(alts, 0)->bInterval <= 4)
-               subs->datainterval = get_endpoint(alts, 0)->bInterval - 1;
-       else
-               subs->datainterval = 0;
+       subs->datainterval = fmt->datainterval;
        subs->syncpipe = subs->syncinterval = 0;
        subs->maxpacksize = fmt->maxpacksize;
        subs->fill_max = 0;
@@ -1428,9 +1420,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
        subs->cur_audiofmt = fmt;
 
 #if 0
-       printk("setting done: format = %d, rate = %d..%d, channels = %d\n",
+       printk(KERN_DEBUG
+              "setting done: format = %d, rate = %d..%d, channels = %d\n",
               fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels);
-       printk("  datapipe = 0x%0x, syncpipe = 0x%0x\n",
+       printk(KERN_DEBUG
+              "  datapipe = 0x%0x, syncpipe = 0x%0x\n",
               subs->datapipe, subs->syncpipe);
 #endif
 
@@ -1465,7 +1459,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
        channels = params_channels(hw_params);
        fmt = find_format(subs, format, rate, channels);
        if (!fmt) {
-               snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n",
+               snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n",
                           format, rate, channels);
                return -EINVAL;
        }
@@ -1539,6 +1533,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
        subs->hwptr_done = 0;
        subs->transfer_done = 0;
        subs->phase = 0;
+       runtime->delay = 0;
 
        /* clear urbs (to be sure) */
        deactivate_urbs(subs, 0, 1);
@@ -1578,11 +1573,15 @@ static struct snd_pcm_hardware snd_usb_hardware =
 #define hwc_debug(fmt, args...) /**/
 #endif
 
-static int hw_check_valid_format(struct snd_pcm_hw_params *params, struct audioformat *fp)
+static int hw_check_valid_format(struct snd_usb_substream *subs,
+                                struct snd_pcm_hw_params *params,
+                                struct audioformat *fp)
 {
        struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
        struct snd_interval *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
        struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+       struct snd_interval *pt = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME);
+       unsigned int ptime;
 
        /* check the format */
        if (!snd_mask_test(fmts, fp->format)) {
@@ -1603,6 +1602,14 @@ static int hw_check_valid_format(struct snd_pcm_hw_params *params, struct audiof
                hwc_debug("   > check: rate_max %d < min %d\n", fp->rate_max, it->min);
                return 0;
        }
+       /* check whether the period time is >= the data packet interval */
+       if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) {
+               ptime = 125 * (1 << fp->datainterval);
+               if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
+                       hwc_debug("   > check: ptime %u > max %u\n", ptime, pt->max);
+                       return 0;
+               }
+       }
        return 1;
 }
 
@@ -1621,7 +1628,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
        list_for_each(p, &subs->fmt_list) {
                struct audioformat *fp;
                fp = list_entry(p, struct audioformat, list);
-               if (!hw_check_valid_format(params, fp))
+               if (!hw_check_valid_format(subs, params, fp))
                        continue;
                if (changed++) {
                        if (rmin > fp->rate_min)
@@ -1675,7 +1682,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
        list_for_each(p, &subs->fmt_list) {
                struct audioformat *fp;
                fp = list_entry(p, struct audioformat, list);
-               if (!hw_check_valid_format(params, fp))
+               if (!hw_check_valid_format(subs, params, fp))
                        continue;
                if (changed++) {
                        if (rmin > fp->channels)
@@ -1728,7 +1735,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
        list_for_each(p, &subs->fmt_list) {
                struct audioformat *fp;
                fp = list_entry(p, struct audioformat, list);
-               if (!hw_check_valid_format(params, fp))
+               if (!hw_check_valid_format(subs, params, fp))
                        continue;
                fbits |= (1ULL << fp->format);
        }
@@ -1746,95 +1753,42 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
        return changed;
 }
 
-#define MAX_MASK       64
-
-/*
- * check whether the registered audio formats need special hw-constraints
- */
-static int check_hw_params_convention(struct snd_usb_substream *subs)
+static int hw_rule_period_time(struct snd_pcm_hw_params *params,
+                              struct snd_pcm_hw_rule *rule)
 {
-       int i;
-       u32 *channels;
-       u32 *rates;
-       u32 cmaster, rmaster;
-       u32 rate_min = 0, rate_max = 0;
-       struct list_head *p;
-       int err = 1;
-
-       channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
-       rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
-       if (!channels || !rates) {
-               err = -ENOMEM;
-               goto __out;
-       }
+       struct snd_usb_substream *subs = rule->private;
+       struct audioformat *fp;
+       struct snd_interval *it;
+       unsigned char min_datainterval;
+       unsigned int pmin;
+       int changed;
 
-       list_for_each(p, &subs->fmt_list) {
-               struct audioformat *f;
-               f = list_entry(p, struct audioformat, list);
-               /* unconventional channels? */
-               if (f->channels > 32)
-                       goto __out;
-               /* continuous rate min/max matches? */
-               if (f->rates & SNDRV_PCM_RATE_CONTINUOUS) {
-                       if (rate_min && f->rate_min != rate_min)
-                               goto __out;
-                       if (rate_max && f->rate_max != rate_max)
-                               goto __out;
-                       rate_min = f->rate_min;
-                       rate_max = f->rate_max;
-               }
-               /* combination of continuous rates and fixed rates? */
-               if (rates[f->format] & SNDRV_PCM_RATE_CONTINUOUS) {
-                       if (f->rates != rates[f->format])
-                               goto __out;
-               }
-               if (f->rates & SNDRV_PCM_RATE_CONTINUOUS) {
-                       if (rates[f->format] && rates[f->format] != f->rates)
-                               goto __out;
-               }
-               channels[f->format] |= (1 << f->channels);
-               rates[f->format] |= f->rates;
-               /* needs knot? */
-               if (f->rates & SNDRV_PCM_RATE_KNOT)
-                       goto __out;
-       }
-       /* check whether channels and rates match for all formats */
-       cmaster = rmaster = 0;
-       for (i = 0; i < MAX_MASK; i++) {
-               if (cmaster != channels[i] && cmaster && channels[i])
-                       goto __out;
-               if (rmaster != rates[i] && rmaster && rates[i])
-                       goto __out;
-               if (channels[i])
-                       cmaster = channels[i];
-               if (rates[i])
-                       rmaster = rates[i];
-       }
-       /* check whether channels match for all distinct rates */
-       memset(channels, 0, MAX_MASK * sizeof(u32));
-       list_for_each(p, &subs->fmt_list) {
-               struct audioformat *f;
-               f = list_entry(p, struct audioformat, list);
-               if (f->rates & SNDRV_PCM_RATE_CONTINUOUS)
+       it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME);
+       hwc_debug("hw_rule_period_time: (%u,%u)\n", it->min, it->max);
+       min_datainterval = 0xff;
+       list_for_each_entry(fp, &subs->fmt_list, list) {
+               if (!hw_check_valid_format(subs, params, fp))
                        continue;
-               for (i = 0; i < 32; i++) {
-                       if (f->rates & (1 << i))
-                               channels[i] |= (1 << f->channels);
-               }
+               min_datainterval = min(min_datainterval, fp->datainterval);
        }
-       cmaster = 0;
-       for (i = 0; i < 32; i++) {
-               if (cmaster != channels[i] && cmaster && channels[i])
-                       goto __out;
-               if (channels[i])
-                       cmaster = channels[i];
+       if (min_datainterval == 0xff) {
+               hwc_debug("  --> get emtpy\n");
+               it->empty = 1;
+               return -EINVAL;
        }
-       err = 0;
-
- __out:
-       kfree(channels);
-       kfree(rates);
-       return err;
+       pmin = 125 * (1 << min_datainterval);
+       changed = 0;
+       if (it->min < pmin) {
+               it->min = pmin;
+               it->openmin = 0;
+               changed = 1;
+       }
+       if (snd_interval_checkempty(it)) {
+               it->empty = 1;
+               return -EINVAL;
+       }
+       hwc_debug("  --> (%u,%u) (changed = %d)\n", it->min, it->max, changed);
+       return changed;
 }
 
 /*
@@ -1882,6 +1836,8 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
 static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs)
 {
        struct list_head *p;
+       unsigned int pt, ptmin;
+       int param_period_time_if_needed;
        int err;
 
        runtime->hw.formats = subs->formats;
@@ -1891,6 +1847,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
        runtime->hw.channels_min = 256;
        runtime->hw.channels_max = 0;
        runtime->hw.rates = 0;
+       ptmin = UINT_MAX;
        /* check min/max rates and channels */
        list_for_each(p, &subs->fmt_list) {
                struct audioformat *fp;
@@ -1909,42 +1866,54 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
                        runtime->hw.period_bytes_min = runtime->hw.period_bytes_max =
                                fp->frame_size;
                }
+               pt = 125 * (1 << fp->datainterval);
+               ptmin = min(ptmin, pt);
        }
 
-       /* set the period time minimum 1ms */
-       /* FIXME: high-speed mode allows 125us minimum period, but many parts
-        * in the current code assume the 1ms period.
-        */
+       param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
+       if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH)
+               /* full speed devices have fixed data packet interval */
+               ptmin = 1000;
+       if (ptmin == 1000)
+               /* if period time doesn't go below 1 ms, no rules needed */
+               param_period_time_if_needed = -1;
        snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
-                                    1000 * MIN_PACKS_URB,
-                                    /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX);
-
-       err = check_hw_params_convention(subs);
-       if (err < 0)
+                                    ptmin, UINT_MAX);
+
+       if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+                                      hw_rule_rate, subs,
+                                      SNDRV_PCM_HW_PARAM_FORMAT,
+                                      SNDRV_PCM_HW_PARAM_CHANNELS,
+                                      param_period_time_if_needed,
+                                      -1)) < 0)
                return err;
-       else if (err) {
-               hwc_debug("setting extra hw constraints...\n");
-               if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
-                                              hw_rule_rate, subs,
-                                              SNDRV_PCM_HW_PARAM_FORMAT,
-                                              SNDRV_PCM_HW_PARAM_CHANNELS,
-                                              -1)) < 0)
-                       return err;
-               if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-                                              hw_rule_channels, subs,
-                                              SNDRV_PCM_HW_PARAM_FORMAT,
-                                              SNDRV_PCM_HW_PARAM_RATE,
-                                              -1)) < 0)
-                       return err;
-               if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
-                                              hw_rule_format, subs,
-                                              SNDRV_PCM_HW_PARAM_RATE,
-                                              SNDRV_PCM_HW_PARAM_CHANNELS,
-                                              -1)) < 0)
-                       return err;
-               if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
+       if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+                                      hw_rule_channels, subs,
+                                      SNDRV_PCM_HW_PARAM_FORMAT,
+                                      SNDRV_PCM_HW_PARAM_RATE,
+                                      param_period_time_if_needed,
+                                      -1)) < 0)
+               return err;
+       if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
+                                      hw_rule_format, subs,
+                                      SNDRV_PCM_HW_PARAM_RATE,
+                                      SNDRV_PCM_HW_PARAM_CHANNELS,
+                                      param_period_time_if_needed,
+                                      -1)) < 0)
+               return err;
+       if (param_period_time_if_needed >= 0) {
+               err = snd_pcm_hw_rule_add(runtime, 0,
+                                         SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+                                         hw_rule_period_time, subs,
+                                         SNDRV_PCM_HW_PARAM_FORMAT,
+                                         SNDRV_PCM_HW_PARAM_CHANNELS,
+                                         SNDRV_PCM_HW_PARAM_RATE,
+                                         -1);
+               if (err < 0)
                        return err;
        }
+       if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
+               return err;
        return 0;
 }
 
@@ -2157,7 +2126,8 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
                fp = list_entry(p, struct audioformat, list);
                snd_iprintf(buffer, "  Interface %d\n", fp->iface);
                snd_iprintf(buffer, "    Altset %d\n", fp->altsetting);
-               snd_iprintf(buffer, "    Format: 0x%x\n", fp->format);
+               snd_iprintf(buffer, "    Format: %#x (%d bits)\n",
+                           fp->format, snd_pcm_format_width(fp->format));
                snd_iprintf(buffer, "    Channels: %d\n", fp->channels);
                snd_iprintf(buffer, "    Endpoint: %d %s (%s)\n",
                            fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
@@ -2176,8 +2146,11 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
                        }
                        snd_iprintf(buffer, "\n");
                }
+               if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
+                       snd_iprintf(buffer, "    Data packet interval: %d us\n",
+                                   125 * (1 << fp->datainterval));
                // snd_iprintf(buffer, "    Max Packet Size = %d\n", fp->maxpacksize);
-               // snd_iprintf(buffer, "    EP Attribute = 0x%x\n", fp->attributes);
+               // snd_iprintf(buffer, "    EP Attribute = %#x\n", fp->attributes);
        }
 }
 
@@ -2261,6 +2234,7 @@ static void init_substream(struct snd_usb_stream *as, int stream, struct audiofo
                switch (as->chip->usb_id) {
                case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */
                case USB_ID(0x041e, 0x3f04): /* E-Mu 0404 USB */
+               case USB_ID(0x041e, 0x3f0a): /* E-Mu Tracker Pre */
                        subs->ops.retire_sync = retire_playback_sync_urb_hs_emu;
                        break;
                }
@@ -2520,7 +2494,6 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
                 * build the rate table and bitmap flags
                 */
                int r, idx;
-               unsigned int nonzero_rates = 0;
 
                fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
                if (fp->rate_table == NULL) {
@@ -2528,24 +2501,27 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
                        return -1;
                }
 
-               fp->nr_rates = nr_rates;
-               fp->rate_min = fp->rate_max = combine_triple(&fmt[8]);
+               fp->nr_rates = 0;
+               fp->rate_min = fp->rate_max = 0;
                for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) {
                        unsigned int rate = combine_triple(&fmt[idx]);
+                       if (!rate)
+                               continue;
                        /* C-Media CM6501 mislabels its 96 kHz altsetting */
                        if (rate == 48000 && nr_rates == 1 &&
-                           chip->usb_id == USB_ID(0x0d8c, 0x0201) &&
+                           (chip->usb_id == USB_ID(0x0d8c, 0x0201) ||
+                            chip->usb_id == USB_ID(0x0d8c, 0x0102)) &&
                            fp->altsetting == 5 && fp->maxpacksize == 392)
                                rate = 96000;
-                       fp->rate_table[r] = rate;
-                       nonzero_rates |= rate;
-                       if (rate < fp->rate_min)
+                       fp->rate_table[fp->nr_rates] = rate;
+                       if (!fp->rate_min || rate < fp->rate_min)
                                fp->rate_min = rate;
-                       else if (rate > fp->rate_max)
+                       if (!fp->rate_max || rate > fp->rate_max)
                                fp->rate_max = rate;
                        fp->rates |= snd_pcm_rate_to_rate_bit(rate);
+                       fp->nr_rates++;
                }
-               if (!nonzero_rates) {
+               if (!fp->nr_rates) {
                        hwc_debug("All rates were zero. Skipping format!\n");
                        return -1;
                }
@@ -2615,7 +2591,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, struct audioformat
                fp->format = SNDRV_PCM_FORMAT_MPEG;
                break;
        default:
-               snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected.  processed as MPEG.\n",
+               snd_printd(KERN_INFO "%d:%u:%d : unknown format tag %#x is detected.  processed as MPEG.\n",
                           chip->dev->devnum, fp->iface, fp->altsetting, format);
                fp->format = SNDRV_PCM_FORMAT_MPEG;
                break;
@@ -2666,6 +2642,17 @@ static int parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp
        return 0;
 }
 
+static unsigned char parse_datainterval(struct snd_usb_audio *chip,
+                                       struct usb_host_interface *alts)
+{
+       if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH &&
+           get_endpoint(alts, 0)->bInterval >= 1 &&
+           get_endpoint(alts, 0)->bInterval <= 4)
+               return get_endpoint(alts, 0)->bInterval - 1;
+       else
+               return 0;
+}
+
 static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
                                         int iface, int altno);
 static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
@@ -2676,7 +2663,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
        struct usb_interface_descriptor *altsd;
        int i, altno, err, stream;
        int format;
-       struct audioformat *fp;
+       struct audioformat *fp = NULL;
        unsigned char *fmt, *csep;
        int num;
 
@@ -2749,6 +2736,18 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                        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[4] == 1 && fmt[5] == 2 && altno == 2 && num == 3 &&
+                   fp && fp->altsetting == 1 && fp->channels == 1 &&
+                   fp->format == SNDRV_PCM_FORMAT_S16_LE &&
+                   le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
+                                                       fp->maxpacksize * 2)
+                       continue;
+
                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)
@@ -2771,6 +2770,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                fp->altset_idx = i;
                fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
                fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
+               fp->datainterval = parse_datainterval(chip, alts);
                fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
                if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
                        fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
@@ -2813,7 +2813,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                        continue;
                }
 
-               snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint 0x%x\n", dev->devnum, iface_no, altno, fp->endpoint);
+               snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
                err = add_audio_endpoint(chip, stream, fp);
                if (err < 0) {
                        kfree(fp->rate_table);
@@ -2962,6 +2962,8 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
                return -EINVAL;
        }
        alts = &iface->altsetting[fp->altset_idx];
+       fp->datainterval = parse_datainterval(chip, alts);
+       fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
        usb_set_interface(chip->dev, fp->iface, 0);
        init_usb_pitch(chip->dev, fp->iface, alts, fp);
        init_usb_sample_rate(chip->dev, fp->iface, alts, fp, fp->rate_max);
@@ -2993,12 +2995,12 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
 }
 
 /*
- * Create a stream for an Edirol UA-700/UA-25 interface.  The only way
- * to detect the sample rate is by looking at wMaxPacketSize.
+ * Create a stream for an Edirol UA-700/UA-25/UA-4FX interface.  
+ * The only way to detect the sample rate is by looking at wMaxPacketSize.
  */
-static int create_ua700_ua25_quirk(struct snd_usb_audio *chip,
-                                  struct usb_interface *iface,
-                                  const struct snd_usb_audio_quirk *quirk)
+static int create_uaxx_quirk(struct snd_usb_audio *chip,
+                             struct usb_interface *iface,
+                             const struct snd_usb_audio_quirk *quirk)
 {
        static const struct audioformat ua_format = {
                .format = SNDRV_PCM_FORMAT_S24_3LE,
@@ -3013,8 +3015,8 @@ static int create_ua700_ua25_quirk(struct snd_usb_audio *chip,
        struct audioformat *fp;
        int stream, err;
 
-       /* both PCM and MIDI interfaces have 2 altsettings */
-       if (iface->num_altsetting != 2)
+       /* both PCM and MIDI interfaces have 2 or more altsettings */
+       if (iface->num_altsetting < 2)
                return -ENXIO;
        alts = &iface->altsetting[1];
        altsd = get_iface_desc(alts);
@@ -3028,20 +3030,20 @@ static int create_ua700_ua25_quirk(struct snd_usb_audio *chip,
                        .type = QUIRK_MIDI_FIXED_ENDPOINT,
                        .data = &ua700_ep
                };
-               static const struct snd_usb_midi_endpoint_info ua25_ep = {
+               static const struct snd_usb_midi_endpoint_info uaxx_ep = {
                        .out_cables = 0x0001,
                        .in_cables  = 0x0001
                };
-               static const struct snd_usb_audio_quirk ua25_quirk = {
+               static const struct snd_usb_audio_quirk uaxx_quirk = {
                        .type = QUIRK_MIDI_FIXED_ENDPOINT,
-                       .data = &ua25_ep
+                       .data = &uaxx_ep
                };
                if (chip->usb_id == USB_ID(0x0582, 0x002b))
                        return snd_usb_create_midi_interface(chip, iface,
                                                             &ua700_quirk);
                else
                        return snd_usb_create_midi_interface(chip, iface,
-                                                            &ua25_quirk);
+                                                            &uaxx_quirk);
        }
 
        if (altsd->bNumEndpoints != 1)
@@ -3055,6 +3057,7 @@ static int create_ua700_ua25_quirk(struct snd_usb_audio *chip,
        fp->iface = altsd->bInterfaceNumber;
        fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
        fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
+       fp->datainterval = 0;
        fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
 
        switch (fp->maxpacksize) {
@@ -3122,6 +3125,7 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip,
        fp->iface = altsd->bInterfaceNumber;
        fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
        fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
+       fp->datainterval = parse_datainterval(chip, alts);
        fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
        fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]);
 
@@ -3174,6 +3178,7 @@ static int create_ua101_quirk(struct snd_usb_audio *chip,
        fp->iface = altsd->bInterfaceNumber;
        fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
        fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
+       fp->datainterval = parse_datainterval(chip, alts);
        fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
        fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]);
 
@@ -3300,6 +3305,25 @@ static int snd_usb_cm106_boot_quirk(struct usb_device *dev)
        return snd_usb_cm106_write_int_reg(dev, 2, 0x8004);
 }
 
+/*
+ * C-Media CM6206 is based on CM106 with two additional
+ * registers that are not documented in the data sheet.
+ * Values here are chosen based on sniffing USB traffic
+ * under Windows.
+ */
+static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
+{
+       int err, reg;
+       int val[] = {0x200c, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000};
+
+       for (reg = 0; reg < ARRAY_SIZE(val); reg++) {
+               err = snd_usb_cm106_write_int_reg(dev, reg, val[reg]);
+               if (err < 0)
+                       return err;
+       }
+
+       return err;
+}
 
 /*
  * Setup quirks
@@ -3368,14 +3392,14 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
                [QUIRK_MIDI_YAMAHA] = snd_usb_create_midi_interface,
                [QUIRK_MIDI_MIDIMAN] = snd_usb_create_midi_interface,
                [QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface,
-               [QUIRK_MIDI_RAW] = snd_usb_create_midi_interface,
+               [QUIRK_MIDI_FASTLANE] = snd_usb_create_midi_interface,
                [QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface,
                [QUIRK_MIDI_CME] = snd_usb_create_midi_interface,
                [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
                [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
-               [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk,
                [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
                [QUIRK_AUDIO_EDIROL_UA101] = create_ua101_quirk,
+               [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk
        };
 
        if (quirk->type < QUIRK_TYPE_COUNT) {
@@ -3459,10 +3483,10 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
                return -ENXIO;
        }
 
-       card = snd_card_new(index[idx], id[idx], THIS_MODULE, 0);
-       if (card == NULL) {
+       err = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card);
+       if (err < 0) {
                snd_printk(KERN_ERR "cannot create card instance %d\n", idx);
-               return -ENOMEM;
+               return err;
        }
 
        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
@@ -3586,6 +3610,12 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
                        goto __err_val;
        }
 
+       /* C-Media CM6206 / CM106-Like Sound Device */
+       if (id == USB_ID(0x0d8c, 0x0102)) {
+               if (snd_usb_cm6206_boot_quirk(dev) < 0)
+                       goto __err_val;
+       }
+
        /*
         * found a config.  now register to ALSA
         */
@@ -3633,7 +3663,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
        if (err > 0) {
                /* create normal USB audio interfaces */
                if (snd_usb_create_streams(chip, ifnum) < 0 ||
-                   snd_usb_create_mixer(chip, ifnum) < 0) {
+                   snd_usb_create_mixer(chip, ifnum, ignore_ctl_error) < 0) {
                        goto __error;
                }
        }
@@ -3705,7 +3735,7 @@ static int usb_audio_probe(struct usb_interface *intf,
        void *chip;
        chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id);
        if (chip) {
-               dev_set_drvdata(&intf->dev, chip);
+               usb_set_intfdata(intf, chip);
                return 0;
        } else
                return -EIO;
@@ -3714,13 +3744,13 @@ static int usb_audio_probe(struct usb_interface *intf,
 static void usb_audio_disconnect(struct usb_interface *intf)
 {
        snd_usb_audio_disconnect(interface_to_usbdev(intf),
-                                dev_get_drvdata(&intf->dev));
+                                usb_get_intfdata(intf));
 }
 
 #ifdef CONFIG_PM
 static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 {
-       struct snd_usb_audio *chip = dev_get_drvdata(&intf->dev);
+       struct snd_usb_audio *chip = usb_get_intfdata(intf);
        struct list_head *p;
        struct snd_usb_stream *as;
 
@@ -3740,7 +3770,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 
 static int usb_audio_resume(struct usb_interface *intf)
 {
-       struct snd_usb_audio *chip = dev_get_drvdata(&intf->dev);
+       struct snd_usb_audio *chip = usb_get_intfdata(intf);
 
        if (chip == (void *)-1L)
                return 0;
@@ -3759,7 +3789,7 @@ static int usb_audio_resume(struct usb_interface *intf)
 
 static int __init snd_usb_audio_init(void)
 {
-       if (nrpacks < MIN_PACKS_URB || nrpacks > MAX_PACKS) {
+       if (nrpacks < 1 || nrpacks > MAX_PACKS) {
                printk(KERN_WARNING "invalid nrpacks value.\n");
                return -EINVAL;
        }