From b7eb4a06e9980973755b7e95a6d97fb8decbf8fd Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 26 Jan 2009 08:08:34 +0100 Subject: sound: usb-audio: use normal number of frames for no-data URBs When sending a silence URB (before playback has started, or when it is paused), use the number of frames that would be normally sent instead of a single frame so that the rate at which completion interrupts arrive is consistent. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c709b956322..417d557ed64 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -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, @@ -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, -- cgit v1.2.3 From 4d788e040b72d2a46ea3ba726b7fa0b65de06c88 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 26 Jan 2009 08:09:28 +0100 Subject: sound: usb-audio: limit playback queue length Once our URBs contain enough packets, queueing more URBs does not give us any additional underrun protection (as we use double-buffering) but just increases latency unnecessarily. Therefore, we try to limit the queue length to some reasonable value. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 417d557ed64..f3d4de23fed 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -108,6 +108,7 @@ MODULE_PARM_DESC(ignore_ctl_error, #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; @@ -1079,7 +1080,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); @@ -1094,6 +1095,12 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri /* 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; + else { + /* and we don't want too long a queue either */ + maxpacks = max((unsigned int)MAX_QUEUE, urb_packs * 2); + if (total_packs > maxpacks * packs_per_ms) + total_packs = maxpacks * packs_per_ms; + } } else { total_packs = MAX_URBS * urb_packs; } -- cgit v1.2.3 From 160389c8d21c8139a93191c2e5ca2273f311ed4e Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 26 Jan 2009 08:10:19 +0100 Subject: sound: usb-audio: make URB sizes more equal Distribute the packets evenly among the URBs, instead of making all URBs except the last one to have the maximum size. This makes the timing of pointer updates more regular and removes some special cases from the code. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index f3d4de23fed..44485b29f67 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1035,9 +1035,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) @@ -1109,31 +1109,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 */ @@ -1141,7 +1121,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 */ -- cgit v1.2.3 From b9d710b3c530ed91e8683933fe94c7605d175bf5 Mon Sep 17 00:00:00 2001 From: Andreas Bergmeier Date: Sat, 24 Jan 2009 12:15:14 +0100 Subject: ALSA: usbaudio - use printf format instead of hardcoding it Rather use printf format instead of hardcoding prefix like 0x. A next step would be to predefine certain formats. Signed-off-by: Andreas Bergmeier Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 44485b29f67..4636926d12d 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1280,14 +1280,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 */ } @@ -1456,7 +1456,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; } @@ -2148,7 +2148,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, @@ -2168,7 +2168,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); } } @@ -2607,7 +2607,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; @@ -2805,7 +2805,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); -- cgit v1.2.3 From 54530bded6ecf22d683423b66fc3cd6dddb249aa Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 5 Feb 2009 15:55:18 +0100 Subject: ALSA: usb - Add missing KERN_* prefix to printk Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 4636926d12d..c69cc6e4f54 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1419,9 +1419,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 -- cgit v1.2.3 From f3990e610a157e9c36af85a75bc66260dff31f40 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Fri, 20 Feb 2009 09:32:40 +0100 Subject: sound: usb-audio: remove MIN_PACKS_URB Remove the MIN_PACKS_URB symbol because other limits can force the number of packets down to one, regardless of the value of this symbol, and nobody has ever changed it anyway. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c69cc6e4f54..2b24496ddec 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -107,7 +107,6 @@ 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 { @@ -1071,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; @@ -1093,9 +1091,9 @@ 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; - else { + 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((unsigned int)MAX_QUEUE, urb_packs * 2); if (total_packs > maxpacks * packs_per_ms) @@ -1909,7 +1907,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); @@ -3753,7 +3751,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; } -- cgit v1.2.3 From eab2b553c3d3ed20698c4a9c7e049a60b804e2f5 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 2 Mar 2009 11:45:50 +0100 Subject: sound: usb-audio: fix rules check for 32-channel devices When storing the channel numbers used by a format, and if the device happens to support 32 channels, the code would try to store 1<<32 in a 32-bit value. Since no valid format can have zero channels, we can use 1<<(channels-1) instead of 1< Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 2b24496ddec..f853b627cf4 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1783,7 +1783,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) @@ -1810,7 +1810,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; -- cgit v1.2.3 From b1c86bb807448701400abc6eb8e958475ab5424b Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 2 Mar 2009 12:06:28 +0100 Subject: sound: usb-audio: fix queue length check for high speed devices When checking for the maximum queue length, we have to take into account that MAX_QUEUE is measured in milliseconds (i.e., frames) while the unit of urb_packs is whatever data packet interval the device uses (possibly less than one frame when using high speed devices). Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound/usb/usbaudio.c') diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index f853b627cf4..defe9913cbb 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1095,9 +1095,8 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri total_packs = 2 * packs_per_ms; } else { /* and we don't want too long a queue either */ - maxpacks = max((unsigned int)MAX_QUEUE, urb_packs * 2); - if (total_packs > maxpacks * packs_per_ms) - total_packs = maxpacks * packs_per_ms; + maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2); + total_packs = min(total_packs, maxpacks); } } else { total_packs = MAX_URBS * urb_packs; -- cgit v1.2.3