PERFORCE change 153538 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Tue Nov 25 09:51:34 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=153538
Change 153538 by hselasky at hselasky_laptop001 on 2008/11/25 17:50:46
Fix USB audio buffer handling for 24-bit audio devices.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb2/sound/uaudio2.c#19 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb2/sound/uaudio2.c#19 (text+ko) ====
@@ -92,10 +92,9 @@
static uint8_t uaudio_default_bits = 32;
static uint8_t uaudio_default_channels = 2;
+#define UAUDIO_MINFRAMES 16 /* must be factor of 8 due HS-USB */
#define UAUDIO_NCHANBUFS 2 /* number of outstanding request */
-#define UAUDIO_NFRAMES 25 /* ms of sound in each request */
#define UAUDIO_RECURSE_LIMIT 24 /* rounds */
-#define UAUDIO_DEFAULT_BUFSZ ((2 * 96000 * 4 * 2) / (1000 / UAUDIO_NCHANBUFS)) /* bytes */
#define MAKE_WORD(h,l) (((h) << 8) | (l))
#define BIT_TEST(bm,bno) (((bm)[(bno) / 8] >> (7 - ((bno) % 8))) & 1)
@@ -154,6 +153,7 @@
uint8_t *cur; /* current position in upper layer
* buffer */
+ uint32_t intr_size; /* in bytes */
uint32_t block_size;
uint32_t sample_rate;
uint32_t format;
@@ -376,13 +376,13 @@
static int32_t umidi_detach(device_t dev);
static const struct usb2_config
- uaudio_cfg_record_full_speed[UAUDIO_NCHANBUFS] = {
+ uaudio_cfg_record[UAUDIO_NCHANBUFS] = {
[0] = {
.type = UE_ISOCHRONOUS,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UAUDIO_NFRAMES,
+ .mh.frames = UAUDIO_MINFRAMES,
.mh.flags = {.short_xfer_ok = 1,},
.mh.callback = &uaudio_chan_record_callback,
},
@@ -392,43 +392,20 @@
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UAUDIO_NFRAMES,
+ .mh.frames = UAUDIO_MINFRAMES,
.mh.flags = {.short_xfer_ok = 1,},
.mh.callback = &uaudio_chan_record_callback,
},
};
static const struct usb2_config
- uaudio_cfg_record_high_speed[UAUDIO_NCHANBUFS] = {
- [0] = {
- .type = UE_ISOCHRONOUS,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_IN,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = (UAUDIO_NFRAMES * 8),
- .mh.flags = {.short_xfer_ok = 1,},
- .mh.callback = &uaudio_chan_record_callback,
- },
-
- [1] = {
- .type = UE_ISOCHRONOUS,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_IN,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = (UAUDIO_NFRAMES * 8),
- .mh.flags = {.short_xfer_ok = 1,},
- .mh.callback = &uaudio_chan_record_callback,
- },
-};
-
-static const struct usb2_config
- uaudio_cfg_play_full_speed[UAUDIO_NCHANBUFS] = {
+ uaudio_cfg_play[UAUDIO_NCHANBUFS] = {
[0] = {
.type = UE_ISOCHRONOUS,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UAUDIO_NFRAMES,
+ .mh.frames = UAUDIO_MINFRAMES,
.mh.flags = {.short_xfer_ok = 1,},
.mh.callback = &uaudio_chan_play_callback,
},
@@ -438,36 +415,13 @@
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UAUDIO_NFRAMES,
+ .mh.frames = UAUDIO_MINFRAMES,
.mh.flags = {.short_xfer_ok = 1,},
.mh.callback = &uaudio_chan_play_callback,
},
};
static const struct usb2_config
- uaudio_cfg_play_high_speed[UAUDIO_NCHANBUFS] = {
- [0] = {
- .type = UE_ISOCHRONOUS,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_OUT,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = (UAUDIO_NFRAMES * 8),
- .mh.flags = {.short_xfer_ok = 1,},
- .mh.callback = &uaudio_chan_play_callback,
- },
-
- [1] = {
- .type = UE_ISOCHRONOUS,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_OUT,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = (UAUDIO_NFRAMES * 8),
- .mh.flags = {.short_xfer_ok = 1,},
- .mh.callback = &uaudio_chan_play_callback,
- },
-};
-
-static const struct usb2_config
uaudio_mixer_config[1] = {
[0] = {
.type = UE_CONTROL,
@@ -693,10 +647,6 @@
struct uaudio_softc *sc = device_get_softc(device_get_parent(dev));
char status[SND_STATUSLEN];
- if (bootverbose) {
- device_printf(dev, "using a default buffer "
- "size of %u bytes\n", UAUDIO_DEFAULT_BUFSZ);
- }
uaudio_mixer_init(sc);
if (sc->sc_uq_audio_swap_lr) {
@@ -1054,16 +1004,13 @@
chan->iface_index = curidx;
chan->iface_alt_index = alt_index;
- chan->usb2_cfg =
- (ep_dir == UE_DIR_IN) ?
- ((fps == 1000) ?
- uaudio_cfg_record_full_speed :
- uaudio_cfg_record_high_speed) :
- ((fps == 1000) ?
- uaudio_cfg_play_full_speed :
- uaudio_cfg_play_high_speed);
+ if (ep_dir == UE_DIR_IN)
+ chan->usb2_cfg =
+ uaudio_cfg_record;
+ else
+ chan->usb2_cfg =
+ uaudio_cfg_play;
-
sample_size = ((chan->p_asf1d->bNrChannels *
chan->p_asf1d->bBitResolution) / 8);
@@ -1135,21 +1082,23 @@
{
struct uaudio_chan *ch = xfer->priv_sc;
uint32_t *p_len = xfer->frlengths;
- uint32_t total = (sndbuf_getblkcnt(ch->pcm_buf) *
- sndbuf_getblksz(ch->pcm_buf)) / 2;
+ uint32_t total;
uint32_t blockcount;
uint32_t n;
uint32_t offset;
/* allow dynamic sizing of play buffer */
+ total = ch->intr_size;
+
+ /* allow dynamic sizing of play buffer */
blockcount = total / ch->bytes_per_frame;
- /* align to 8 units */
- blockcount &= ~7;
+ /* align units */
+ blockcount -= (blockcount % UAUDIO_MINFRAMES);
/* range check - min */
if (blockcount == 0) {
- blockcount = 8;
+ blockcount = UAUDIO_MINFRAMES;
}
/* range check - max */
if (blockcount > xfer->max_frame_count) {
@@ -1225,21 +1174,23 @@
uint32_t *p_len = xfer->frlengths;
uint32_t n;
uint32_t m;
- uint32_t total = (sndbuf_getblkcnt(ch->pcm_buf) *
- sndbuf_getblksz(ch->pcm_buf)) / 2;
+ uint32_t total;
uint32_t blockcount;
uint32_t offset0;
uint32_t offset1;
/* allow dynamic sizing of play buffer */
+ total = ch->intr_size;
+
+ /* allow dynamic sizing of play buffer */
blockcount = total / ch->bytes_per_frame;
- /* align to 8 units */
- blockcount &= ~7;
+ /* align units */
+ blockcount -= (blockcount % UAUDIO_MINFRAMES);
/* range check - min */
if (blockcount == 0) {
- blockcount = 8;
+ blockcount = UAUDIO_MINFRAMES;
}
/* range check - max */
if (blockcount > xfer->max_frame_count) {
@@ -1321,21 +1272,30 @@
{
struct uaudio_chan *ch = ((dir == PCMDIR_PLAY) ?
&sc->sc_play_chan : &sc->sc_rec_chan);
+ uint32_t buf_size;
uint8_t endpoint;
uint8_t iface_index;
uint8_t alt_index;
usb2_error_t err;
- ch->buf = malloc(UAUDIO_DEFAULT_BUFSZ, M_DEVBUF, M_WAITOK | M_ZERO);
+ /* compute required buffer size */
+ buf_size = (ch->bytes_per_frame * UAUDIO_MINFRAMES);
+
+ /* setup interrupt interval */
+ ch->intr_size = buf_size;
+
+ /* double buffering */
+ buf_size *= 2;
+ ch->buf = malloc(buf_size, M_DEVBUF, M_WAITOK | M_ZERO);
if (ch->buf == NULL) {
goto error;
}
- if (sndbuf_setup(b, ch->buf, UAUDIO_DEFAULT_BUFSZ) != 0) {
+ if (sndbuf_setup(b, ch->buf, buf_size) != 0) {
goto error;
}
ch->start = ch->buf;
- ch->end = ch->buf + UAUDIO_DEFAULT_BUFSZ;
+ ch->end = ch->buf + buf_size;
ch->cur = ch->buf;
ch->pcm_ch = c;
ch->pcm_mtx = c->lock;
@@ -1432,26 +1392,14 @@
uaudio_chan_set_param_fragments(struct uaudio_chan *ch, uint32_t blocksize,
uint32_t blockcount)
{
- uint32_t max = sndbuf_getmaxsize(ch->pcm_buf);
+ /* we only support one size */
+ blocksize = ch->intr_size;
+ blockcount = 2;
- RANGE(blocksize, 128, max / 2);
-
- /*
- * Make sure that the blocksize is a factor of the number of bytes
- * we insert per isochronous frame.
- */
- blocksize += (ch->bytes_per_frame - blocksize) % ch->bytes_per_frame;
- if (blocksize > (max / 2)) {
- /* should not happen */
- DPRINTFN(0, "blocksize overflow!\n");
- blocksize = (max / 2);
- }
- blockcount = max / blocksize;
- RANGE(blockcount, 2, 512);
-
if ((sndbuf_getblksz(ch->pcm_buf) != blocksize) ||
(sndbuf_getblkcnt(ch->pcm_buf) != blockcount)) {
-
+ DPRINTFN(1, "resizing to %u x "
+ "%u bytes\n", blockcount, blocksize);
if (sndbuf_resize(ch->pcm_buf, blockcount, blocksize)) {
DPRINTFN(0, "failed to resize sound buffer, count=%u, "
"size=%u\n", blockcount, blocksize);
More information about the p4-projects
mailing list