Loading sound/usb/usbaudio.c +120 −135 Original line number Original line Diff line number Diff line Loading @@ -121,6 +121,7 @@ struct audioformat { unsigned char attributes; /* corresponding attributes of cs endpoint */ unsigned char attributes; /* corresponding attributes of cs endpoint */ unsigned char endpoint; /* endpoint */ unsigned char endpoint; /* endpoint */ unsigned char ep_attr; /* endpoint attributes */ unsigned char ep_attr; /* endpoint attributes */ unsigned char datainterval; /* log_2 of data packet interval */ unsigned int maxpacksize; /* max. packet size */ unsigned int maxpacksize; /* max. packet size */ unsigned int rates; /* rate bitmasks */ unsigned int rates; /* rate bitmasks */ unsigned int rate_min, rate_max; /* min/max rates */ unsigned int rate_min, rate_max; /* min/max rates */ Loading Loading @@ -170,7 +171,6 @@ struct snd_usb_substream { unsigned int curframesize; /* current packet size in frames (for capture) */ unsigned int curframesize; /* current packet size in frames (for capture) */ unsigned int fill_max: 1; /* fill max packet size always */ unsigned int fill_max: 1; /* fill max packet size always */ unsigned int fmt_type; /* USB audio format type (1-3) */ 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 */ unsigned int running: 1; /* running status */ Loading Loading @@ -607,9 +607,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, break; break; } } } } /* finish at the frame boundary at/after the period boundary */ if (period_elapsed) /* finish at the period boundary */ if (period_elapsed && (i & (subs->packs_per_ms - 1)) == subs->packs_per_ms - 1) break; break; } } if (subs->hwptr_done + offs > runtime->buffer_size) { if (subs->hwptr_done + offs > runtime->buffer_size) { Loading Loading @@ -1067,7 +1065,6 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri packs_per_ms = 8 >> subs->datainterval; packs_per_ms = 8 >> subs->datainterval; else else packs_per_ms = 1; packs_per_ms = 1; subs->packs_per_ms = packs_per_ms; if (is_playback) { if (is_playback) { urb_packs = max(nrpacks, 1); urb_packs = max(nrpacks, 1); Loading @@ -1087,18 +1084,17 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri minsize -= minsize >> 3; minsize -= minsize >> 3; minsize = max(minsize, 1u); minsize = max(minsize, 1u); total_packs = (period_bytes + minsize - 1) / minsize; 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 */ /* we need at least two URBs for queueing */ if (total_packs < 2 * packs_per_ms) { if (total_packs < 2) { total_packs = 2 * packs_per_ms; total_packs = 2; } else { } else { /* and we don't want too long a queue either */ /* and we don't want too long a queue either */ maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2); maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2); total_packs = min(total_packs, maxpacks); total_packs = min(total_packs, maxpacks); } } } else { } else { while (urb_packs > 1 && urb_packs * maxsize >= period_bytes) urb_packs >>= 1; total_packs = MAX_URBS * urb_packs; total_packs = MAX_URBS * urb_packs; } } subs->nurbs = (total_packs + urb_packs - 1) / urb_packs; subs->nurbs = (total_packs + urb_packs - 1) / urb_packs; Loading Loading @@ -1350,12 +1346,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) subs->datapipe = usb_sndisocpipe(dev, ep); subs->datapipe = usb_sndisocpipe(dev, ep); else else subs->datapipe = usb_rcvisocpipe(dev, ep); subs->datapipe = usb_rcvisocpipe(dev, ep); if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH && subs->datainterval = fmt->datainterval; 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->syncpipe = subs->syncinterval = 0; subs->syncpipe = subs->syncinterval = 0; subs->maxpacksize = fmt->maxpacksize; subs->maxpacksize = fmt->maxpacksize; subs->fill_max = 0; subs->fill_max = 0; Loading Loading @@ -1568,11 +1559,15 @@ static struct snd_pcm_hardware snd_usb_hardware = #define hwc_debug(fmt, args...) /**/ #define hwc_debug(fmt, args...) /**/ #endif #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 *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_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_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 */ /* check the format */ if (!snd_mask_test(fmts, fp->format)) { if (!snd_mask_test(fmts, fp->format)) { Loading @@ -1593,6 +1588,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); hwc_debug(" > check: rate_max %d < min %d\n", fp->rate_max, it->min); return 0; 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; return 1; } } Loading @@ -1611,7 +1614,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params, list_for_each(p, &subs->fmt_list) { list_for_each(p, &subs->fmt_list) { struct audioformat *fp; struct audioformat *fp; fp = list_entry(p, struct audioformat, list); fp = list_entry(p, struct audioformat, list); if (!hw_check_valid_format(params, fp)) if (!hw_check_valid_format(subs, params, fp)) continue; continue; if (changed++) { if (changed++) { if (rmin > fp->rate_min) if (rmin > fp->rate_min) Loading Loading @@ -1665,7 +1668,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params, list_for_each(p, &subs->fmt_list) { list_for_each(p, &subs->fmt_list) { struct audioformat *fp; struct audioformat *fp; fp = list_entry(p, struct audioformat, list); fp = list_entry(p, struct audioformat, list); if (!hw_check_valid_format(params, fp)) if (!hw_check_valid_format(subs, params, fp)) continue; continue; if (changed++) { if (changed++) { if (rmin > fp->channels) if (rmin > fp->channels) Loading Loading @@ -1718,7 +1721,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params, list_for_each(p, &subs->fmt_list) { list_for_each(p, &subs->fmt_list) { struct audioformat *fp; struct audioformat *fp; fp = list_entry(p, struct audioformat, list); fp = list_entry(p, struct audioformat, list); if (!hw_check_valid_format(params, fp)) if (!hw_check_valid_format(subs, params, fp)) continue; continue; fbits |= (1ULL << fp->format); fbits |= (1ULL << fp->format); } } Loading @@ -1736,95 +1739,42 @@ static int hw_rule_format(struct snd_pcm_hw_params *params, return changed; return changed; } } #define MAX_MASK 64 static int hw_rule_period_time(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) /* * check whether the registered audio formats need special hw-constraints */ static int check_hw_params_convention(struct snd_usb_substream *subs) { { int i; struct snd_usb_substream *subs = rule->private; u32 *channels; struct audioformat *fp; u32 *rates; struct snd_interval *it; u32 cmaster, rmaster; unsigned char min_datainterval; u32 rate_min = 0, rate_max = 0; unsigned int pmin; struct list_head *p; int changed; 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; } list_for_each(p, &subs->fmt_list) { it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME); struct audioformat *f; hwc_debug("hw_rule_period_time: (%u,%u)\n", it->min, it->max); f = list_entry(p, struct audioformat, list); min_datainterval = 0xff; /* unconventional channels? */ list_for_each_entry(fp, &subs->fmt_list, list) { if (f->channels > 32) if (!hw_check_valid_format(subs, params, fp)) 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 - 1); 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) continue; continue; for (i = 0; i < 32; i++) { min_datainterval = min(min_datainterval, fp->datainterval); if (f->rates & (1 << i)) } channels[i] |= 1 << (f->channels - 1); if (min_datainterval == 0xff) { hwc_debug(" --> get emtpy\n"); it->empty = 1; return -EINVAL; } } pmin = 125 * (1 << min_datainterval); changed = 0; if (it->min < pmin) { it->min = pmin; it->openmin = 0; changed = 1; } } cmaster = 0; if (snd_interval_checkempty(it)) { for (i = 0; i < 32; i++) { it->empty = 1; if (cmaster != channels[i] && cmaster && channels[i]) return -EINVAL; goto __out; if (channels[i]) cmaster = channels[i]; } } err = 0; hwc_debug(" --> (%u,%u) (changed = %d)\n", it->min, it->max, changed); return changed; __out: kfree(channels); kfree(rates); return err; } } /* /* Loading Loading @@ -1872,6 +1822,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) static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs) { { struct list_head *p; struct list_head *p; unsigned int pt, ptmin; int param_period_time_if_needed; int err; int err; runtime->hw.formats = subs->formats; runtime->hw.formats = subs->formats; Loading @@ -1881,6 +1833,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre runtime->hw.channels_min = 256; runtime->hw.channels_min = 256; runtime->hw.channels_max = 0; runtime->hw.channels_max = 0; runtime->hw.rates = 0; runtime->hw.rates = 0; ptmin = UINT_MAX; /* check min/max rates and channels */ /* check min/max rates and channels */ list_for_each(p, &subs->fmt_list) { list_for_each(p, &subs->fmt_list) { struct audioformat *fp; struct audioformat *fp; Loading @@ -1899,42 +1852,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 = runtime->hw.period_bytes_min = runtime->hw.period_bytes_max = fp->frame_size; fp->frame_size; } } pt = 125 * (1 << fp->datainterval); ptmin = min(ptmin, pt); } } /* set the period time minimum 1ms */ param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; /* FIXME: high-speed mode allows 125us minimum period, but many parts if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH) * in the current code assume the 1ms period. /* 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, snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, ptmin, UINT_MAX); /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX); err = check_hw_params_convention(subs); if (err < 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, if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, hw_rule_rate, subs, hw_rule_rate, subs, SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_CHANNELS, SNDRV_PCM_HW_PARAM_CHANNELS, param_period_time_if_needed, -1)) < 0) -1)) < 0) return err; return err; if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, hw_rule_channels, subs, hw_rule_channels, subs, SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_RATE, SNDRV_PCM_HW_PARAM_RATE, param_period_time_if_needed, -1)) < 0) -1)) < 0) return err; return err; if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, hw_rule_format, subs, hw_rule_format, subs, SNDRV_PCM_HW_PARAM_RATE, SNDRV_PCM_HW_PARAM_RATE, SNDRV_PCM_HW_PARAM_CHANNELS, SNDRV_PCM_HW_PARAM_CHANNELS, param_period_time_if_needed, -1)) < 0) -1)) < 0) return err; return err; if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) 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; return err; } } if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) return err; return 0; return 0; } } Loading Loading @@ -2147,7 +2112,8 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s fp = list_entry(p, struct audioformat, list); fp = list_entry(p, struct audioformat, list); snd_iprintf(buffer, " Interface %d\n", fp->iface); snd_iprintf(buffer, " Interface %d\n", fp->iface); snd_iprintf(buffer, " Altset %d\n", fp->altsetting); snd_iprintf(buffer, " Altset %d\n", fp->altsetting); snd_iprintf(buffer, " Format: %#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, " Channels: %d\n", fp->channels); snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", fp->endpoint & USB_ENDPOINT_NUMBER_MASK, fp->endpoint & USB_ENDPOINT_NUMBER_MASK, Loading @@ -2166,6 +2132,9 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s } } snd_iprintf(buffer, "\n"); 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, " Max Packet Size = %d\n", fp->maxpacksize); // snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes); // snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes); } } Loading Loading @@ -2659,6 +2628,17 @@ static int parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp return 0; 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, static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip, int iface, int altno); int iface, int altno); static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) Loading Loading @@ -2764,6 +2744,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) fp->altset_idx = i; fp->altset_idx = i; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; 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->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) Loading Loading @@ -2955,6 +2936,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, return -EINVAL; return -EINVAL; } } alts = &iface->altsetting[fp->altset_idx]; alts = &iface->altsetting[fp->altset_idx]; fp->datainterval = parse_datainterval(chip, alts); fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); usb_set_interface(chip->dev, fp->iface, 0); usb_set_interface(chip->dev, fp->iface, 0); init_usb_pitch(chip->dev, fp->iface, alts, fp); init_usb_pitch(chip->dev, fp->iface, alts, fp); Loading Loading @@ -3049,6 +3031,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, fp->iface = altsd->bInterfaceNumber; fp->iface = altsd->bInterfaceNumber; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; fp->datainterval = 0; fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); switch (fp->maxpacksize) { switch (fp->maxpacksize) { Loading Loading @@ -3116,6 +3099,7 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip, fp->iface = altsd->bInterfaceNumber; fp->iface = altsd->bInterfaceNumber; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; 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->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]); fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]); Loading Loading @@ -3168,6 +3152,7 @@ static int create_ua101_quirk(struct snd_usb_audio *chip, fp->iface = altsd->bInterfaceNumber; fp->iface = altsd->bInterfaceNumber; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; 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->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]); fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]); Loading Loading
sound/usb/usbaudio.c +120 −135 Original line number Original line Diff line number Diff line Loading @@ -121,6 +121,7 @@ struct audioformat { unsigned char attributes; /* corresponding attributes of cs endpoint */ unsigned char attributes; /* corresponding attributes of cs endpoint */ unsigned char endpoint; /* endpoint */ unsigned char endpoint; /* endpoint */ unsigned char ep_attr; /* endpoint attributes */ unsigned char ep_attr; /* endpoint attributes */ unsigned char datainterval; /* log_2 of data packet interval */ unsigned int maxpacksize; /* max. packet size */ unsigned int maxpacksize; /* max. packet size */ unsigned int rates; /* rate bitmasks */ unsigned int rates; /* rate bitmasks */ unsigned int rate_min, rate_max; /* min/max rates */ unsigned int rate_min, rate_max; /* min/max rates */ Loading Loading @@ -170,7 +171,6 @@ struct snd_usb_substream { unsigned int curframesize; /* current packet size in frames (for capture) */ unsigned int curframesize; /* current packet size in frames (for capture) */ unsigned int fill_max: 1; /* fill max packet size always */ unsigned int fill_max: 1; /* fill max packet size always */ unsigned int fmt_type; /* USB audio format type (1-3) */ 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 */ unsigned int running: 1; /* running status */ Loading Loading @@ -607,9 +607,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, break; break; } } } } /* finish at the frame boundary at/after the period boundary */ if (period_elapsed) /* finish at the period boundary */ if (period_elapsed && (i & (subs->packs_per_ms - 1)) == subs->packs_per_ms - 1) break; break; } } if (subs->hwptr_done + offs > runtime->buffer_size) { if (subs->hwptr_done + offs > runtime->buffer_size) { Loading Loading @@ -1067,7 +1065,6 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri packs_per_ms = 8 >> subs->datainterval; packs_per_ms = 8 >> subs->datainterval; else else packs_per_ms = 1; packs_per_ms = 1; subs->packs_per_ms = packs_per_ms; if (is_playback) { if (is_playback) { urb_packs = max(nrpacks, 1); urb_packs = max(nrpacks, 1); Loading @@ -1087,18 +1084,17 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri minsize -= minsize >> 3; minsize -= minsize >> 3; minsize = max(minsize, 1u); minsize = max(minsize, 1u); total_packs = (period_bytes + minsize - 1) / minsize; 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 */ /* we need at least two URBs for queueing */ if (total_packs < 2 * packs_per_ms) { if (total_packs < 2) { total_packs = 2 * packs_per_ms; total_packs = 2; } else { } else { /* and we don't want too long a queue either */ /* and we don't want too long a queue either */ maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2); maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2); total_packs = min(total_packs, maxpacks); total_packs = min(total_packs, maxpacks); } } } else { } else { while (urb_packs > 1 && urb_packs * maxsize >= period_bytes) urb_packs >>= 1; total_packs = MAX_URBS * urb_packs; total_packs = MAX_URBS * urb_packs; } } subs->nurbs = (total_packs + urb_packs - 1) / urb_packs; subs->nurbs = (total_packs + urb_packs - 1) / urb_packs; Loading Loading @@ -1350,12 +1346,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) subs->datapipe = usb_sndisocpipe(dev, ep); subs->datapipe = usb_sndisocpipe(dev, ep); else else subs->datapipe = usb_rcvisocpipe(dev, ep); subs->datapipe = usb_rcvisocpipe(dev, ep); if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH && subs->datainterval = fmt->datainterval; 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->syncpipe = subs->syncinterval = 0; subs->syncpipe = subs->syncinterval = 0; subs->maxpacksize = fmt->maxpacksize; subs->maxpacksize = fmt->maxpacksize; subs->fill_max = 0; subs->fill_max = 0; Loading Loading @@ -1568,11 +1559,15 @@ static struct snd_pcm_hardware snd_usb_hardware = #define hwc_debug(fmt, args...) /**/ #define hwc_debug(fmt, args...) /**/ #endif #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 *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_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_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 */ /* check the format */ if (!snd_mask_test(fmts, fp->format)) { if (!snd_mask_test(fmts, fp->format)) { Loading @@ -1593,6 +1588,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); hwc_debug(" > check: rate_max %d < min %d\n", fp->rate_max, it->min); return 0; 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; return 1; } } Loading @@ -1611,7 +1614,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params, list_for_each(p, &subs->fmt_list) { list_for_each(p, &subs->fmt_list) { struct audioformat *fp; struct audioformat *fp; fp = list_entry(p, struct audioformat, list); fp = list_entry(p, struct audioformat, list); if (!hw_check_valid_format(params, fp)) if (!hw_check_valid_format(subs, params, fp)) continue; continue; if (changed++) { if (changed++) { if (rmin > fp->rate_min) if (rmin > fp->rate_min) Loading Loading @@ -1665,7 +1668,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params, list_for_each(p, &subs->fmt_list) { list_for_each(p, &subs->fmt_list) { struct audioformat *fp; struct audioformat *fp; fp = list_entry(p, struct audioformat, list); fp = list_entry(p, struct audioformat, list); if (!hw_check_valid_format(params, fp)) if (!hw_check_valid_format(subs, params, fp)) continue; continue; if (changed++) { if (changed++) { if (rmin > fp->channels) if (rmin > fp->channels) Loading Loading @@ -1718,7 +1721,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params, list_for_each(p, &subs->fmt_list) { list_for_each(p, &subs->fmt_list) { struct audioformat *fp; struct audioformat *fp; fp = list_entry(p, struct audioformat, list); fp = list_entry(p, struct audioformat, list); if (!hw_check_valid_format(params, fp)) if (!hw_check_valid_format(subs, params, fp)) continue; continue; fbits |= (1ULL << fp->format); fbits |= (1ULL << fp->format); } } Loading @@ -1736,95 +1739,42 @@ static int hw_rule_format(struct snd_pcm_hw_params *params, return changed; return changed; } } #define MAX_MASK 64 static int hw_rule_period_time(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) /* * check whether the registered audio formats need special hw-constraints */ static int check_hw_params_convention(struct snd_usb_substream *subs) { { int i; struct snd_usb_substream *subs = rule->private; u32 *channels; struct audioformat *fp; u32 *rates; struct snd_interval *it; u32 cmaster, rmaster; unsigned char min_datainterval; u32 rate_min = 0, rate_max = 0; unsigned int pmin; struct list_head *p; int changed; 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; } list_for_each(p, &subs->fmt_list) { it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME); struct audioformat *f; hwc_debug("hw_rule_period_time: (%u,%u)\n", it->min, it->max); f = list_entry(p, struct audioformat, list); min_datainterval = 0xff; /* unconventional channels? */ list_for_each_entry(fp, &subs->fmt_list, list) { if (f->channels > 32) if (!hw_check_valid_format(subs, params, fp)) 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 - 1); 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) continue; continue; for (i = 0; i < 32; i++) { min_datainterval = min(min_datainterval, fp->datainterval); if (f->rates & (1 << i)) } channels[i] |= 1 << (f->channels - 1); if (min_datainterval == 0xff) { hwc_debug(" --> get emtpy\n"); it->empty = 1; return -EINVAL; } } pmin = 125 * (1 << min_datainterval); changed = 0; if (it->min < pmin) { it->min = pmin; it->openmin = 0; changed = 1; } } cmaster = 0; if (snd_interval_checkempty(it)) { for (i = 0; i < 32; i++) { it->empty = 1; if (cmaster != channels[i] && cmaster && channels[i]) return -EINVAL; goto __out; if (channels[i]) cmaster = channels[i]; } } err = 0; hwc_debug(" --> (%u,%u) (changed = %d)\n", it->min, it->max, changed); return changed; __out: kfree(channels); kfree(rates); return err; } } /* /* Loading Loading @@ -1872,6 +1822,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) static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs) { { struct list_head *p; struct list_head *p; unsigned int pt, ptmin; int param_period_time_if_needed; int err; int err; runtime->hw.formats = subs->formats; runtime->hw.formats = subs->formats; Loading @@ -1881,6 +1833,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre runtime->hw.channels_min = 256; runtime->hw.channels_min = 256; runtime->hw.channels_max = 0; runtime->hw.channels_max = 0; runtime->hw.rates = 0; runtime->hw.rates = 0; ptmin = UINT_MAX; /* check min/max rates and channels */ /* check min/max rates and channels */ list_for_each(p, &subs->fmt_list) { list_for_each(p, &subs->fmt_list) { struct audioformat *fp; struct audioformat *fp; Loading @@ -1899,42 +1852,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 = runtime->hw.period_bytes_min = runtime->hw.period_bytes_max = fp->frame_size; fp->frame_size; } } pt = 125 * (1 << fp->datainterval); ptmin = min(ptmin, pt); } } /* set the period time minimum 1ms */ param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; /* FIXME: high-speed mode allows 125us minimum period, but many parts if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH) * in the current code assume the 1ms period. /* 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, snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, ptmin, UINT_MAX); /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX); err = check_hw_params_convention(subs); if (err < 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, if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, hw_rule_rate, subs, hw_rule_rate, subs, SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_CHANNELS, SNDRV_PCM_HW_PARAM_CHANNELS, param_period_time_if_needed, -1)) < 0) -1)) < 0) return err; return err; if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, hw_rule_channels, subs, hw_rule_channels, subs, SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_RATE, SNDRV_PCM_HW_PARAM_RATE, param_period_time_if_needed, -1)) < 0) -1)) < 0) return err; return err; if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, hw_rule_format, subs, hw_rule_format, subs, SNDRV_PCM_HW_PARAM_RATE, SNDRV_PCM_HW_PARAM_RATE, SNDRV_PCM_HW_PARAM_CHANNELS, SNDRV_PCM_HW_PARAM_CHANNELS, param_period_time_if_needed, -1)) < 0) -1)) < 0) return err; return err; if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) 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; return err; } } if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) return err; return 0; return 0; } } Loading Loading @@ -2147,7 +2112,8 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s fp = list_entry(p, struct audioformat, list); fp = list_entry(p, struct audioformat, list); snd_iprintf(buffer, " Interface %d\n", fp->iface); snd_iprintf(buffer, " Interface %d\n", fp->iface); snd_iprintf(buffer, " Altset %d\n", fp->altsetting); snd_iprintf(buffer, " Altset %d\n", fp->altsetting); snd_iprintf(buffer, " Format: %#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, " Channels: %d\n", fp->channels); snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", fp->endpoint & USB_ENDPOINT_NUMBER_MASK, fp->endpoint & USB_ENDPOINT_NUMBER_MASK, Loading @@ -2166,6 +2132,9 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s } } snd_iprintf(buffer, "\n"); 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, " Max Packet Size = %d\n", fp->maxpacksize); // snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes); // snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes); } } Loading Loading @@ -2659,6 +2628,17 @@ static int parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp return 0; 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, static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip, int iface, int altno); int iface, int altno); static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) Loading Loading @@ -2764,6 +2744,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) fp->altset_idx = i; fp->altset_idx = i; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; 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->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) Loading Loading @@ -2955,6 +2936,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, return -EINVAL; return -EINVAL; } } alts = &iface->altsetting[fp->altset_idx]; alts = &iface->altsetting[fp->altset_idx]; fp->datainterval = parse_datainterval(chip, alts); fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); usb_set_interface(chip->dev, fp->iface, 0); usb_set_interface(chip->dev, fp->iface, 0); init_usb_pitch(chip->dev, fp->iface, alts, fp); init_usb_pitch(chip->dev, fp->iface, alts, fp); Loading Loading @@ -3049,6 +3031,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, fp->iface = altsd->bInterfaceNumber; fp->iface = altsd->bInterfaceNumber; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; fp->datainterval = 0; fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); switch (fp->maxpacksize) { switch (fp->maxpacksize) { Loading Loading @@ -3116,6 +3099,7 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip, fp->iface = altsd->bInterfaceNumber; fp->iface = altsd->bInterfaceNumber; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; 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->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]); fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]); Loading Loading @@ -3168,6 +3152,7 @@ static int create_ua101_quirk(struct snd_usb_audio *chip, fp->iface = altsd->bInterfaceNumber; fp->iface = altsd->bInterfaceNumber; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; 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->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]); fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]); Loading