diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2009-01-26 02:10:19 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-01-26 11:05:10 -0500 |
commit | 160389c8d21c8139a93191c2e5ca2273f311ed4e (patch) | |
tree | 7be9b7c475d23343ec41b7ef0f2d97e7fffbc7b0 /sound/usb | |
parent | 4d788e040b72d2a46ea3ba726b7fa0b65de06c88 (diff) |
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 <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/usbaudio.c | 29 |
1 files changed, 5 insertions, 24 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index f3d4de23fedf..44485b29f675 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) | |||
1035 | static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int period_bytes, | 1035 | static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int period_bytes, |
1036 | unsigned int rate, unsigned int frame_bits) | 1036 | unsigned int rate, unsigned int frame_bits) |
1037 | { | 1037 | { |
1038 | unsigned int maxsize, n, i; | 1038 | unsigned int maxsize, i; |
1039 | int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; | 1039 | int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; |
1040 | unsigned int npacks[MAX_URBS], urb_packs, total_packs, packs_per_ms; | 1040 | unsigned int urb_packs, total_packs, packs_per_ms; |
1041 | 1041 | ||
1042 | /* calculate the frequency in 16.16 format */ | 1042 | /* calculate the frequency in 16.16 format */ |
1043 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | 1043 | 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 | |||
1109 | /* too much... */ | 1109 | /* too much... */ |
1110 | subs->nurbs = MAX_URBS; | 1110 | subs->nurbs = MAX_URBS; |
1111 | total_packs = MAX_URBS * urb_packs; | 1111 | total_packs = MAX_URBS * urb_packs; |
1112 | } | 1112 | } else if (subs->nurbs < 2) { |
1113 | n = total_packs; | ||
1114 | for (i = 0; i < subs->nurbs; i++) { | ||
1115 | npacks[i] = n > urb_packs ? urb_packs : n; | ||
1116 | n -= urb_packs; | ||
1117 | } | ||
1118 | if (subs->nurbs <= 1) { | ||
1119 | /* too little - we need at least two packets | 1113 | /* too little - we need at least two packets |
1120 | * to ensure contiguous playback/capture | 1114 | * to ensure contiguous playback/capture |
1121 | */ | 1115 | */ |
1122 | subs->nurbs = 2; | 1116 | subs->nurbs = 2; |
1123 | npacks[0] = (total_packs + 1) / 2; | ||
1124 | npacks[1] = total_packs - npacks[0]; | ||
1125 | } else if (npacks[subs->nurbs-1] < MIN_PACKS_URB * packs_per_ms) { | ||
1126 | /* the last packet is too small.. */ | ||
1127 | if (subs->nurbs > 2) { | ||
1128 | /* merge to the first one */ | ||
1129 | npacks[0] += npacks[subs->nurbs - 1]; | ||
1130 | subs->nurbs--; | ||
1131 | } else { | ||
1132 | /* divide to two */ | ||
1133 | subs->nurbs = 2; | ||
1134 | npacks[0] = (total_packs + 1) / 2; | ||
1135 | npacks[1] = total_packs - npacks[0]; | ||
1136 | } | ||
1137 | } | 1117 | } |
1138 | 1118 | ||
1139 | /* allocate and initialize data urbs */ | 1119 | /* allocate and initialize data urbs */ |
@@ -1141,7 +1121,8 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri | |||
1141 | struct snd_urb_ctx *u = &subs->dataurb[i]; | 1121 | struct snd_urb_ctx *u = &subs->dataurb[i]; |
1142 | u->index = i; | 1122 | u->index = i; |
1143 | u->subs = subs; | 1123 | u->subs = subs; |
1144 | u->packets = npacks[i]; | 1124 | u->packets = (i + 1) * total_packs / subs->nurbs |
1125 | - i * total_packs / subs->nurbs; | ||
1145 | u->buffer_size = maxsize * u->packets; | 1126 | u->buffer_size = maxsize * u->packets; |
1146 | if (subs->fmt_type == USB_FORMAT_TYPE_II) | 1127 | if (subs->fmt_type == USB_FORMAT_TYPE_II) |
1147 | u->packets++; /* for transfer delimiter */ | 1128 | u->packets++; /* for transfer delimiter */ |