aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2005-06-27 02:17:30 -0400
committerJaroslav Kysela <perex@suse.cz>2005-07-28 06:09:25 -0400
commit573567e07bb4470ff177f17d1adca3f3bd310221 (patch)
tree7a5853dd8f22f0117a9bee93252bac13ff57bd61 /sound
parentb0af0de5cb57c96b0c3d739005172152b7de0ce8 (diff)
[ALSA] usb-audio - high speed audio support
USB generic driver Add support for endpoints with bInterval > 1, and decoding of the wMaxPacketSize field of high-speed endpoints. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/usbaudio.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index b5e734d975e..facd9fc11c3 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -153,6 +153,7 @@ struct snd_usb_substream {
153 unsigned int format; /* USB data format */ 153 unsigned int format; /* USB data format */
154 unsigned int datapipe; /* the data i/o pipe */ 154 unsigned int datapipe; /* the data i/o pipe */
155 unsigned int syncpipe; /* 1 - async out or adaptive in */ 155 unsigned int syncpipe; /* 1 - async out or adaptive in */
156 unsigned int datainterval; /* log_2 of data packet interval */
156 unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ 157 unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */
157 unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */ 158 unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */
158 unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */ 159 unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */
@@ -518,7 +519,8 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
518 if (subs->fill_max) 519 if (subs->fill_max)
519 counts = subs->maxframesize; /* fixed */ 520 counts = subs->maxframesize; /* fixed */
520 else { 521 else {
521 subs->phase = (subs->phase & 0xffff) + subs->freqm; 522 subs->phase = (subs->phase & 0xffff)
523 + (subs->freqm << subs->datainterval);
522 counts = subs->phase >> 16; 524 counts = subs->phase >> 16;
523 if (counts > subs->maxframesize) 525 if (counts > subs->maxframesize)
524 counts = subs->maxframesize; 526 counts = subs->maxframesize;
@@ -899,16 +901,19 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
899 else 901 else
900 subs->freqn = get_usb_high_speed_rate(rate); 902 subs->freqn = get_usb_high_speed_rate(rate);
901 subs->freqm = subs->freqn; 903 subs->freqm = subs->freqn;
902 subs->freqmax = subs->freqn + (subs->freqn >> 2); /* max. allowed frequency */ 904 /* calculate max. frequency */
903 subs->phase = 0; 905 if (subs->maxpacksize) {
904 906 /* whatever fits into a max. size packet */
905 /* calculate the max. size of packet */
906 maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3)) >> 16;
907 if (subs->maxpacksize && maxsize > subs->maxpacksize) {
908 //snd_printd(KERN_DEBUG "maxsize %d is greater than defined size %d\n",
909 // maxsize, subs->maxpacksize);
910 maxsize = subs->maxpacksize; 907 maxsize = subs->maxpacksize;
908 subs->freqmax = (maxsize / (frame_bits >> 3))
909 << (16 - subs->datainterval);
910 } else {
911 /* no max. packet size: just take 25% higher than nominal */
912 subs->freqmax = subs->freqn + (subs->freqn >> 2);
913 maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3))
914 >> (16 - subs->datainterval);
911 } 915 }
916 subs->phase = 0;
912 917
913 if (subs->fill_max) 918 if (subs->fill_max)
914 subs->curpacksize = subs->maxpacksize; 919 subs->curpacksize = subs->maxpacksize;
@@ -918,7 +923,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
918 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) 923 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
919 urb_packs = nrpacks; 924 urb_packs = nrpacks;
920 else 925 else
921 urb_packs = nrpacks * 8; 926 urb_packs = (nrpacks * 8) >> subs->datainterval;
922 927
923 /* allocate a temporary buffer for playback */ 928 /* allocate a temporary buffer for playback */
924 if (is_playback) { 929 if (is_playback) {
@@ -991,7 +996,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
991 u->urb->pipe = subs->datapipe; 996 u->urb->pipe = subs->datapipe;
992 u->urb->transfer_flags = URB_ISO_ASAP; 997 u->urb->transfer_flags = URB_ISO_ASAP;
993 u->urb->number_of_packets = u->packets; 998 u->urb->number_of_packets = u->packets;
994 u->urb->interval = 1; 999 u->urb->interval = 1 << subs->datainterval;
995 u->urb->context = u; 1000 u->urb->context = u;
996 u->urb->complete = snd_usb_complete_callback(snd_complete_urb); 1001 u->urb->complete = snd_usb_complete_callback(snd_complete_urb);
997 } 1002 }
@@ -1195,6 +1200,12 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt)
1195 subs->datapipe = usb_sndisocpipe(dev, ep); 1200 subs->datapipe = usb_sndisocpipe(dev, ep);
1196 else 1201 else
1197 subs->datapipe = usb_rcvisocpipe(dev, ep); 1202 subs->datapipe = usb_rcvisocpipe(dev, ep);
1203 if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH &&
1204 get_endpoint(alts, 0)->bInterval >= 1 &&
1205 get_endpoint(alts, 0)->bInterval <= 4)
1206 subs->datainterval = get_endpoint(alts, 0)->bInterval - 1;
1207 else
1208 subs->datainterval = 0;
1198 subs->syncpipe = subs->syncinterval = 0; 1209 subs->syncpipe = subs->syncinterval = 0;
1199 subs->maxpacksize = fmt->maxpacksize; 1210 subs->maxpacksize = fmt->maxpacksize;
1200 subs->fill_max = 0; 1211 subs->fill_max = 0;
@@ -2492,8 +2503,10 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
2492 fp->altset_idx = i; 2503 fp->altset_idx = i;
2493 fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; 2504 fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
2494 fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; 2505 fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
2495 /* FIXME: decode wMaxPacketSize of high bandwith endpoints */
2496 fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); 2506 fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
2507 if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
2508 fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
2509 * (fp->maxpacksize & 0x7ff);
2497 fp->attributes = csep[3]; 2510 fp->attributes = csep[3];
2498 2511
2499 /* some quirks for attributes here */ 2512 /* some quirks for attributes here */