mirror of
https://github.com/torvalds/linux.git
synced 2024-11-18 01:51:53 +00:00
[ALSA] usb-audio: schedule high speed URBs with 1 ms alignment
USB generic driver The EHCI driver doesn't interrupt more than once per millisecond, and organizes all iso transfers with frame-sized ITDs, so we can (try to) be more efficient by aligning all URBs on frame boundaries. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
This commit is contained in:
parent
71d848ca00
commit
a93bf99077
@ -893,7 +893,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
|
|||||||
{
|
{
|
||||||
unsigned int maxsize, n, i;
|
unsigned int maxsize, n, i;
|
||||||
int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
|
int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
|
||||||
unsigned int npacks[MAX_URBS], urb_packs, total_packs;
|
unsigned int npacks[MAX_URBS], urb_packs, total_packs, packs_per_ms;
|
||||||
|
|
||||||
/* calculate the frequency in 16.16 format */
|
/* calculate the frequency in 16.16 format */
|
||||||
if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
|
if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
|
||||||
@ -920,14 +920,18 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
|
|||||||
else
|
else
|
||||||
subs->curpacksize = maxsize;
|
subs->curpacksize = maxsize;
|
||||||
|
|
||||||
|
if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
|
||||||
|
packs_per_ms = 8 >> subs->datainterval;
|
||||||
|
else
|
||||||
|
packs_per_ms = 1;
|
||||||
|
|
||||||
if (is_playback) {
|
if (is_playback) {
|
||||||
urb_packs = nrpacks;
|
urb_packs = nrpacks;
|
||||||
urb_packs = max(urb_packs, (unsigned int)MIN_PACKS_URB);
|
urb_packs = max(urb_packs, (unsigned int)MIN_PACKS_URB);
|
||||||
urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
|
urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
|
||||||
} else
|
} else
|
||||||
urb_packs = 1;
|
urb_packs = 1;
|
||||||
if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
|
urb_packs *= packs_per_ms;
|
||||||
urb_packs = (urb_packs * 8) >> subs->datainterval;
|
|
||||||
|
|
||||||
/* allocate a temporary buffer for playback */
|
/* allocate a temporary buffer for playback */
|
||||||
if (is_playback) {
|
if (is_playback) {
|
||||||
@ -949,8 +953,12 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
|
|||||||
minsize -= minsize >> 2;
|
minsize -= minsize >> 2;
|
||||||
minsize = max(minsize, 1u);
|
minsize = max(minsize, 1u);
|
||||||
total_packs = (period_bytes + minsize - 1) / minsize;
|
total_packs = (period_bytes + minsize - 1) / minsize;
|
||||||
if (total_packs < 2 * MIN_PACKS_URB)
|
/* round up to multiple of packs_per_ms */
|
||||||
total_packs = 2 * MIN_PACKS_URB;
|
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 {
|
} else {
|
||||||
total_packs = MAX_URBS * urb_packs;
|
total_packs = MAX_URBS * urb_packs;
|
||||||
}
|
}
|
||||||
@ -972,7 +980,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
|
|||||||
subs->nurbs = 2;
|
subs->nurbs = 2;
|
||||||
npacks[0] = (total_packs + 1) / 2;
|
npacks[0] = (total_packs + 1) / 2;
|
||||||
npacks[1] = total_packs - npacks[0];
|
npacks[1] = total_packs - npacks[0];
|
||||||
} else if (npacks[subs->nurbs-1] < MIN_PACKS_URB) {
|
} else if (npacks[subs->nurbs-1] < MIN_PACKS_URB * packs_per_ms) {
|
||||||
/* the last packet is too small.. */
|
/* the last packet is too small.. */
|
||||||
if (subs->nurbs > 2) {
|
if (subs->nurbs > 2) {
|
||||||
/* merge to the first one */
|
/* merge to the first one */
|
||||||
|
Loading…
Reference in New Issue
Block a user