Loading sound/usb/usbaudio.c +33 −46 Original line number Diff line number Diff line Loading @@ -107,7 +107,7 @@ MODULE_PARM_DESC(ignore_ctl_error, #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; Loading Loading @@ -525,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, Loading @@ -537,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, Loading Loading @@ -1034,9 +1034,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) Loading Loading @@ -1070,8 +1070,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri 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; Loading @@ -1079,7 +1078,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri /* 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); Loading @@ -1092,8 +1091,13 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri 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 * packs_per_ms) { total_packs = 2 * packs_per_ms; } 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 { total_packs = MAX_URBS * urb_packs; } Loading @@ -1102,31 +1106,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 */ Loading @@ -1134,7 +1118,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 */ Loading Loading @@ -1292,14 +1277,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 */ } Loading Loading @@ -1431,9 +1416,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 Loading Loading @@ -1468,7 +1455,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; } Loading Loading @@ -1795,7 +1782,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs) if (rates[f->format] && rates[f->format] != f->rates) goto __out; } channels[f->format] |= (1 << f->channels); channels[f->format] |= 1 << (f->channels - 1); rates[f->format] |= f->rates; /* needs knot? */ if (f->rates & SNDRV_PCM_RATE_KNOT) Loading @@ -1822,7 +1809,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs) continue; for (i = 0; i < 32; i++) { if (f->rates & (1 << i)) channels[i] |= (1 << f->channels); channels[i] |= 1 << (f->channels - 1); } } cmaster = 0; Loading Loading @@ -1919,7 +1906,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre * in the current code assume the 1ms period. */ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000 * MIN_PACKS_URB, 1000, /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX); err = check_hw_params_convention(subs); Loading Loading @@ -2160,7 +2147,7 @@ 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\n", fp->format); snd_iprintf(buffer, " Channels: %d\n", fp->channels); snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", fp->endpoint & USB_ENDPOINT_NUMBER_MASK, Loading @@ -2180,7 +2167,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s snd_iprintf(buffer, "\n"); } // 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); } } Loading Loading @@ -2621,7 +2608,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; Loading Loading @@ -2819,7 +2806,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); Loading Loading @@ -3766,7 +3753,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; } Loading sound/usb/usbmixer.c +84 −58 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ static const struct rc_config { { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */ { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ }; struct usb_mixer_interface { Loading Loading @@ -109,6 +110,8 @@ struct mixer_build { const struct usbmix_selector_map *selector_map; }; #define MAX_CHANNELS 10 /* max logical channels */ struct usb_mixer_elem_info { struct usb_mixer_interface *mixer; struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */ Loading @@ -119,6 +122,8 @@ struct usb_mixer_elem_info { int channels; int val_type; int min, max, res; int cached; int cache_val[MAX_CHANNELS]; u8 initialized; }; Loading Loading @@ -180,8 +185,6 @@ enum { USB_PROC_DCR_RELEASE = 6, }; #define MAX_CHANNELS 10 /* max logical channels */ /* * manual mapping of mixer names Loading Loading @@ -218,7 +221,10 @@ static int check_ignored_ctl(struct mixer_build *state, int unitid, int control) for (p = state->map; p->id; p++) { if (p->id == unitid && ! p->name && (! control || ! p->control || control == p->control)) { // printk("ignored control %d:%d\n", unitid, control); /* printk(KERN_DEBUG "ignored control %d:%d\n", unitid, control); */ return 1; } } Loading Loading @@ -375,11 +381,35 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int * } /* channel = 0: master, 1 = first channel */ static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value) static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, int channel, int *value) { return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value); } static int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int index, int *value) { int err; if (cval->cached & (1 << channel)) { *value = cval->cache_val[index]; return 0; } err = get_cur_mix_raw(cval, channel, value); if (err < 0) { if (!cval->mixer->ignore_ctl_error) snd_printd(KERN_ERR "cannot get current value for " "control %d ch %d: err = %d\n", cval->control, channel, err); return err; } cval->cached |= 1 << channel; cval->cache_val[index] = *value; return 0; } /* * set a mixer value */ Loading Loading @@ -411,9 +441,17 @@ static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int v return set_ctl_value(cval, SET_CUR, validx, value); } static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value) static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int index, int value) { return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); int err; err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); if (err < 0) return err; cval->cached |= 1 << channel; cval->cache_val[index] = value; return 0; } /* Loading Loading @@ -717,7 +755,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) if (cval->min + cval->res < cval->max) { int last_valid_res = cval->res; int saved, test, check; get_cur_mix_value(cval, minchn, &saved); get_cur_mix_raw(cval, minchn, &saved); for (;;) { test = saved; if (test < cval->max) Loading @@ -725,8 +763,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) else test -= cval->res; if (test < cval->min || test > cval->max || set_cur_mix_value(cval, minchn, test) || get_cur_mix_value(cval, minchn, &check)) { set_cur_mix_value(cval, minchn, 0, test) || get_cur_mix_raw(cval, minchn, &check)) { cval->res = last_valid_res; break; } Loading @@ -734,7 +772,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) break; cval->res *= 2; } set_cur_mix_value(cval, minchn, saved); set_cur_mix_value(cval, minchn, 0, saved); } cval->initialized = 1; Loading Loading @@ -774,35 +812,25 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e struct usb_mixer_elem_info *cval = kcontrol->private_data; int c, cnt, val, err; ucontrol->value.integer.value[0] = cval->min; if (cval->cmask) { cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { if (cval->cmask & (1 << c)) { err = get_cur_mix_value(cval, c + 1, &val); if (err < 0) { if (cval->mixer->ignore_ctl_error) { ucontrol->value.integer.value[0] = cval->min; return 0; } snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err); return err; } if (!(cval->cmask & (1 << c))) continue; err = get_cur_mix_value(cval, c + 1, cnt, &val); if (err < 0) return cval->mixer->ignore_ctl_error ? 0 : err; val = get_relative_value(cval, val); ucontrol->value.integer.value[cnt] = val; cnt++; } } return 0; } else { /* master channel */ err = get_cur_mix_value(cval, 0, &val); if (err < 0) { if (cval->mixer->ignore_ctl_error) { ucontrol->value.integer.value[0] = cval->min; return 0; } snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err); return err; } err = get_cur_mix_value(cval, 0, 0, &val); if (err < 0) return cval->mixer->ignore_ctl_error ? 0 : err; val = get_relative_value(cval, val); ucontrol->value.integer.value[0] = val; } Loading @@ -819,34 +847,28 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (cval->cmask) { cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { if (cval->cmask & (1 << c)) { err = get_cur_mix_value(cval, c + 1, &oval); if (err < 0) { if (cval->mixer->ignore_ctl_error) return 0; return err; } if (!(cval->cmask & (1 << c))) continue; err = get_cur_mix_value(cval, c + 1, cnt, &oval); if (err < 0) return cval->mixer->ignore_ctl_error ? 0 : err; val = ucontrol->value.integer.value[cnt]; val = get_abs_value(cval, val); if (oval != val) { set_cur_mix_value(cval, c + 1, val); set_cur_mix_value(cval, c + 1, cnt, val); changed = 1; } get_cur_mix_value(cval, c + 1, &val); cnt++; } } } else { /* master channel */ err = get_cur_mix_value(cval, 0, &oval); if (err < 0 && cval->mixer->ignore_ctl_error) return 0; err = get_cur_mix_value(cval, 0, 0, &oval); if (err < 0) return err; return cval->mixer->ignore_ctl_error ? 0 : err; val = ucontrol->value.integer.value[0]; val = get_abs_value(cval, val); if (val != oval) { set_cur_mix_value(cval, 0, val); set_cur_mix_value(cval, 0, 0, val); changed = 1; } } Loading Loading @@ -1705,7 +1727,8 @@ static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, break; /* live24ext: 4 = line-in jack */ case 3: /* hp-out jack (may actuate Mute) */ if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id); break; default: Loading Loading @@ -1937,7 +1960,8 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { if (i > 1 && /* Live24ext has 2 LEDs only */ mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) break; err = snd_ctl_add(mixer->chip->card, snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); Loading Loading @@ -1974,7 +1998,8 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname); if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) jacks = jacks_audigy2nx; else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) jacks = jacks_live24ext; else return; Loading Loading @@ -2024,7 +2049,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, goto _error; if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) { mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) { struct snd_info_entry *entry; if ((err = snd_audigy2nx_controls_create(mixer)) < 0) Loading sound/usb/usbmixer_maps.c +26 −0 Original line number Diff line number Diff line Loading @@ -261,6 +261,22 @@ static struct usbmix_name_map aureon_51_2_map[] = { {} /* terminator */ }; static struct usbmix_name_map scratch_live_map[] = { /* 1: IT Line 1 (USB streaming) */ /* 2: OT Line 1 (Speaker) */ /* 3: IT Line 1 (Line connector) */ { 4, "Line 1 In" }, /* FU */ /* 5: OT Line 1 (USB streaming) */ /* 6: IT Line 2 (USB streaming) */ /* 7: OT Line 2 (Speaker) */ /* 8: IT Line 2 (Line connector) */ { 9, "Line 2 In" }, /* FU */ /* 10: OT Line 2 (USB streaming) */ /* 11: IT Mic (Line connector) */ /* 12: OT Mic (USB streaming) */ { 0 } /* terminator */ }; /* * Control map entries */ Loading @@ -284,6 +300,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .id = USB_ID(0x041e, 0x3040), .map = live24ext_map, }, { .id = USB_ID(0x041e, 0x3048), .map = audigy2nx_map, .selector_map = audigy2nx_selectors, }, { /* Hercules DJ Console (Windows Edition) */ .id = USB_ID(0x06f8, 0xb000), Loading Loading @@ -311,6 +332,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .id = USB_ID(0x0ccd, 0x0028), .map = aureon_51_2_map, }, { .id = USB_ID(0x13e5, 0x0001), .map = scratch_live_map, .ignore_ctl_error = 1, }, { 0 } /* terminator */ }; sound/usb/usbquirks.h +10 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,16 @@ .idProduct = prod, \ .bInterfaceClass = USB_CLASS_VENDOR_SPEC /* Creative/Toshiba Multimedia Center SB-0500 */ { USB_DEVICE(0x041e, 0x3048), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { .vendor_name = "Toshiba", .product_name = "SB-0500", .ifnum = QUIRK_NO_INTERFACE } }, /* Creative/E-Mu devices */ { USB_DEVICE(0x041e, 0x3010), Loading sound/usb/usx2y/usb_stream.c +1 −1 Original line number Diff line number Diff line Loading @@ -557,7 +557,7 @@ static void stream_start(struct usb_stream_kernel *sk, s->idle_insize -= max_diff - max_diff_0; s->idle_insize += urb_size - s->period_size; if (s->idle_insize < 0) { snd_printk("%i %i %i\n", snd_printk(KERN_WARNING "%i %i %i\n", s->idle_insize, urb_size, s->period_size); return; } else if (s->idle_insize == 0) { Loading Loading
sound/usb/usbaudio.c +33 −46 Original line number Diff line number Diff line Loading @@ -107,7 +107,7 @@ MODULE_PARM_DESC(ignore_ctl_error, #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; Loading Loading @@ -525,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, Loading @@ -537,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, Loading Loading @@ -1034,9 +1034,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) Loading Loading @@ -1070,8 +1070,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri 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; Loading @@ -1079,7 +1078,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri /* 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); Loading @@ -1092,8 +1091,13 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri 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 * packs_per_ms) { total_packs = 2 * packs_per_ms; } 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 { total_packs = MAX_URBS * urb_packs; } Loading @@ -1102,31 +1106,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 */ Loading @@ -1134,7 +1118,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 */ Loading Loading @@ -1292,14 +1277,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 */ } Loading Loading @@ -1431,9 +1416,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 Loading Loading @@ -1468,7 +1455,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; } Loading Loading @@ -1795,7 +1782,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs) if (rates[f->format] && rates[f->format] != f->rates) goto __out; } channels[f->format] |= (1 << f->channels); channels[f->format] |= 1 << (f->channels - 1); rates[f->format] |= f->rates; /* needs knot? */ if (f->rates & SNDRV_PCM_RATE_KNOT) Loading @@ -1822,7 +1809,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs) continue; for (i = 0; i < 32; i++) { if (f->rates & (1 << i)) channels[i] |= (1 << f->channels); channels[i] |= 1 << (f->channels - 1); } } cmaster = 0; Loading Loading @@ -1919,7 +1906,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre * in the current code assume the 1ms period. */ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000 * MIN_PACKS_URB, 1000, /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX); err = check_hw_params_convention(subs); Loading Loading @@ -2160,7 +2147,7 @@ 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\n", fp->format); snd_iprintf(buffer, " Channels: %d\n", fp->channels); snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", fp->endpoint & USB_ENDPOINT_NUMBER_MASK, Loading @@ -2180,7 +2167,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s snd_iprintf(buffer, "\n"); } // 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); } } Loading Loading @@ -2621,7 +2608,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; Loading Loading @@ -2819,7 +2806,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); Loading Loading @@ -3766,7 +3753,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; } Loading
sound/usb/usbmixer.c +84 −58 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ static const struct rc_config { { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */ { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ }; struct usb_mixer_interface { Loading Loading @@ -109,6 +110,8 @@ struct mixer_build { const struct usbmix_selector_map *selector_map; }; #define MAX_CHANNELS 10 /* max logical channels */ struct usb_mixer_elem_info { struct usb_mixer_interface *mixer; struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */ Loading @@ -119,6 +122,8 @@ struct usb_mixer_elem_info { int channels; int val_type; int min, max, res; int cached; int cache_val[MAX_CHANNELS]; u8 initialized; }; Loading Loading @@ -180,8 +185,6 @@ enum { USB_PROC_DCR_RELEASE = 6, }; #define MAX_CHANNELS 10 /* max logical channels */ /* * manual mapping of mixer names Loading Loading @@ -218,7 +221,10 @@ static int check_ignored_ctl(struct mixer_build *state, int unitid, int control) for (p = state->map; p->id; p++) { if (p->id == unitid && ! p->name && (! control || ! p->control || control == p->control)) { // printk("ignored control %d:%d\n", unitid, control); /* printk(KERN_DEBUG "ignored control %d:%d\n", unitid, control); */ return 1; } } Loading Loading @@ -375,11 +381,35 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int * } /* channel = 0: master, 1 = first channel */ static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value) static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, int channel, int *value) { return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value); } static int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int index, int *value) { int err; if (cval->cached & (1 << channel)) { *value = cval->cache_val[index]; return 0; } err = get_cur_mix_raw(cval, channel, value); if (err < 0) { if (!cval->mixer->ignore_ctl_error) snd_printd(KERN_ERR "cannot get current value for " "control %d ch %d: err = %d\n", cval->control, channel, err); return err; } cval->cached |= 1 << channel; cval->cache_val[index] = *value; return 0; } /* * set a mixer value */ Loading Loading @@ -411,9 +441,17 @@ static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int v return set_ctl_value(cval, SET_CUR, validx, value); } static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value) static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int index, int value) { return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); int err; err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); if (err < 0) return err; cval->cached |= 1 << channel; cval->cache_val[index] = value; return 0; } /* Loading Loading @@ -717,7 +755,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) if (cval->min + cval->res < cval->max) { int last_valid_res = cval->res; int saved, test, check; get_cur_mix_value(cval, minchn, &saved); get_cur_mix_raw(cval, minchn, &saved); for (;;) { test = saved; if (test < cval->max) Loading @@ -725,8 +763,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) else test -= cval->res; if (test < cval->min || test > cval->max || set_cur_mix_value(cval, minchn, test) || get_cur_mix_value(cval, minchn, &check)) { set_cur_mix_value(cval, minchn, 0, test) || get_cur_mix_raw(cval, minchn, &check)) { cval->res = last_valid_res; break; } Loading @@ -734,7 +772,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) break; cval->res *= 2; } set_cur_mix_value(cval, minchn, saved); set_cur_mix_value(cval, minchn, 0, saved); } cval->initialized = 1; Loading Loading @@ -774,35 +812,25 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e struct usb_mixer_elem_info *cval = kcontrol->private_data; int c, cnt, val, err; ucontrol->value.integer.value[0] = cval->min; if (cval->cmask) { cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { if (cval->cmask & (1 << c)) { err = get_cur_mix_value(cval, c + 1, &val); if (err < 0) { if (cval->mixer->ignore_ctl_error) { ucontrol->value.integer.value[0] = cval->min; return 0; } snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err); return err; } if (!(cval->cmask & (1 << c))) continue; err = get_cur_mix_value(cval, c + 1, cnt, &val); if (err < 0) return cval->mixer->ignore_ctl_error ? 0 : err; val = get_relative_value(cval, val); ucontrol->value.integer.value[cnt] = val; cnt++; } } return 0; } else { /* master channel */ err = get_cur_mix_value(cval, 0, &val); if (err < 0) { if (cval->mixer->ignore_ctl_error) { ucontrol->value.integer.value[0] = cval->min; return 0; } snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err); return err; } err = get_cur_mix_value(cval, 0, 0, &val); if (err < 0) return cval->mixer->ignore_ctl_error ? 0 : err; val = get_relative_value(cval, val); ucontrol->value.integer.value[0] = val; } Loading @@ -819,34 +847,28 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (cval->cmask) { cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { if (cval->cmask & (1 << c)) { err = get_cur_mix_value(cval, c + 1, &oval); if (err < 0) { if (cval->mixer->ignore_ctl_error) return 0; return err; } if (!(cval->cmask & (1 << c))) continue; err = get_cur_mix_value(cval, c + 1, cnt, &oval); if (err < 0) return cval->mixer->ignore_ctl_error ? 0 : err; val = ucontrol->value.integer.value[cnt]; val = get_abs_value(cval, val); if (oval != val) { set_cur_mix_value(cval, c + 1, val); set_cur_mix_value(cval, c + 1, cnt, val); changed = 1; } get_cur_mix_value(cval, c + 1, &val); cnt++; } } } else { /* master channel */ err = get_cur_mix_value(cval, 0, &oval); if (err < 0 && cval->mixer->ignore_ctl_error) return 0; err = get_cur_mix_value(cval, 0, 0, &oval); if (err < 0) return err; return cval->mixer->ignore_ctl_error ? 0 : err; val = ucontrol->value.integer.value[0]; val = get_abs_value(cval, val); if (val != oval) { set_cur_mix_value(cval, 0, val); set_cur_mix_value(cval, 0, 0, val); changed = 1; } } Loading Loading @@ -1705,7 +1727,8 @@ static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, break; /* live24ext: 4 = line-in jack */ case 3: /* hp-out jack (may actuate Mute) */ if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id); break; default: Loading Loading @@ -1937,7 +1960,8 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { if (i > 1 && /* Live24ext has 2 LEDs only */ mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) break; err = snd_ctl_add(mixer->chip->card, snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); Loading Loading @@ -1974,7 +1998,8 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname); if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) jacks = jacks_audigy2nx; else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) jacks = jacks_live24ext; else return; Loading Loading @@ -2024,7 +2049,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, goto _error; if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) { mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) { struct snd_info_entry *entry; if ((err = snd_audigy2nx_controls_create(mixer)) < 0) Loading
sound/usb/usbmixer_maps.c +26 −0 Original line number Diff line number Diff line Loading @@ -261,6 +261,22 @@ static struct usbmix_name_map aureon_51_2_map[] = { {} /* terminator */ }; static struct usbmix_name_map scratch_live_map[] = { /* 1: IT Line 1 (USB streaming) */ /* 2: OT Line 1 (Speaker) */ /* 3: IT Line 1 (Line connector) */ { 4, "Line 1 In" }, /* FU */ /* 5: OT Line 1 (USB streaming) */ /* 6: IT Line 2 (USB streaming) */ /* 7: OT Line 2 (Speaker) */ /* 8: IT Line 2 (Line connector) */ { 9, "Line 2 In" }, /* FU */ /* 10: OT Line 2 (USB streaming) */ /* 11: IT Mic (Line connector) */ /* 12: OT Mic (USB streaming) */ { 0 } /* terminator */ }; /* * Control map entries */ Loading @@ -284,6 +300,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .id = USB_ID(0x041e, 0x3040), .map = live24ext_map, }, { .id = USB_ID(0x041e, 0x3048), .map = audigy2nx_map, .selector_map = audigy2nx_selectors, }, { /* Hercules DJ Console (Windows Edition) */ .id = USB_ID(0x06f8, 0xb000), Loading Loading @@ -311,6 +332,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .id = USB_ID(0x0ccd, 0x0028), .map = aureon_51_2_map, }, { .id = USB_ID(0x13e5, 0x0001), .map = scratch_live_map, .ignore_ctl_error = 1, }, { 0 } /* terminator */ };
sound/usb/usbquirks.h +10 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,16 @@ .idProduct = prod, \ .bInterfaceClass = USB_CLASS_VENDOR_SPEC /* Creative/Toshiba Multimedia Center SB-0500 */ { USB_DEVICE(0x041e, 0x3048), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { .vendor_name = "Toshiba", .product_name = "SB-0500", .ifnum = QUIRK_NO_INTERFACE } }, /* Creative/E-Mu devices */ { USB_DEVICE(0x041e, 0x3010), Loading
sound/usb/usx2y/usb_stream.c +1 −1 Original line number Diff line number Diff line Loading @@ -557,7 +557,7 @@ static void stream_start(struct usb_stream_kernel *sk, s->idle_insize -= max_diff - max_diff_0; s->idle_insize += urb_size - s->period_size; if (s->idle_insize < 0) { snd_printk("%i %i %i\n", snd_printk(KERN_WARNING "%i %i %i\n", s->idle_insize, urb_size, s->period_size); return; } else if (s->idle_insize == 0) { Loading