This patch against the current backport (please also apply to 2.3)
fixes a problem with "short writes" and mostly undoes earlier changes
to find_format which are conceptually wrong and broke just about every
audio application with the Dallas chip (likely also with the philips chip,
but I didn't try)
Tom
--- audio.c.orig Sat May 13 14:45:11 2000
+++ audio.c Sat May 13 17:30:08 2000
@@ -3,7 +3,7 @@
/*
* audio.c -- USB Audio Class driver
*
- * Copyright (C) 1999
+ * Copyright (C) 1999, 2000
* Alan Cox ([EMAIL PROTECTED])
* Thomas Sailer ([EMAIL PROTECTED])
*
@@ -59,6 +59,19 @@
* 1999-12-20: Fix bad bug in conversion to per interface probing.
* disconnect was called multiple times for the audio device,
* leading to a premature freeing of the audio structures
+ * 2000-05-13: I don't remember who changed the find_format routine,
+ * but the change was completely broken for the Dallas
+ * chip. Anyway taking sampling rate into account in find_format
+ * is bad and should not be done unless there are devices with
+ * completely broken audio descriptors. Unless someone shows
+ * me such a descriptor, I will not allow find_format to
+ * take the sampling rate into account.
+ * Also, the former find_format made:
+ * - mpg123 play mono instead of stereo
+ * - sox completely fail for wav's with sample rates < 44.1kHz
+ * for the Dallas chip.
+ * Also fix a rather long standing problem with applications that
+ * use "small" writes producing no sound at all.
*
*/
@@ -441,9 +454,9 @@
db->bufsize = nr << PAGE_SHIFT;
db->ready = 1;
printk(KERN_DEBUG "dmabuf_init: bytepersec %d bufs %d ossfragshift %d
ossmaxfrags %d "
- "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d\n",
+ "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x\n",
bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift,
db->fragsize,
- db->numfrag, db->dmasize, db->bufsize);
+ db->numfrag, db->dmasize, db->bufsize, db->format);
return 0;
}
@@ -973,6 +986,8 @@
}
spin_lock_irqsave(&as->lock, flags);
}
+ if (u->dma.count <= 0 && !u->dma.mapped)
+ return 0;
u->flags |= FLG_RUNNING;
if (!(u->flags & FLG_URB0RUNNING)) {
urb = &u->durb[0].urb;
@@ -1332,6 +1347,8 @@
}
spin_lock_irqsave(&as->lock, flags);
}
+ if (u->dma.count <= 0 && !u->dma.mapped)
+ return 0;
u->flags |= FLG_RUNNING;
if (!(u->flags & FLG_URB0RUNNING)) {
urb = &u->durb[0].urb;
@@ -1395,27 +1412,26 @@
/* --------------------------------------------------------------------- */
-static unsigned int find_format(struct audioformat *afp, unsigned int nr, unsigned
int fmt, unsigned int rate)
+static unsigned int find_format(struct audioformat *afp, unsigned int nr, unsigned
+int fmt)
{
unsigned int i;
- /* first find an exact match, taking both format and sample rate into account,
- but ignore stereo bit */
- for (i = 0; i < nr; i++) {
- if (afp[i].format == (fmt & ~AFMT_STEREO) && rate >= afp[i].sratelo &&
rate <= afp[i].sratehi)
+ /* first find an exact match */
+ for (i = 0; i < nr; i++)
+ if (afp[i].format == fmt)
return i;
- }
-
/* second find a match with the same stereo/mono and 8bit/16bit property */
for (i = 0; i < nr; i++)
if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt) &&
- !AFMT_IS16BIT(afp[i].format) == !AFMT_IS16BIT(fmt) &&
- rate >= afp[i].sratelo && rate <= afp[i].sratehi)
+ !AFMT_IS16BIT(afp[i].format) == !AFMT_IS16BIT(fmt))
return i;
/* third find a match with the same number of channels */
for (i = 0; i < nr; i++)
- if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt) &&
- rate >= afp[i].sratelo && rate <= afp[i].sratehi)
+ if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt))
+ return i;
+ /* fourth find an exact match, taking format into account, but ignore stereo
+bit */
+ for (i = 0; i < nr; i++)
+ if (!((afp[i].format ^ fmt) & ~AFMT_STEREO))
return i;
/* return failure */
return -1;
@@ -1438,7 +1454,7 @@
return 0;
iface = &config->interface[u->interface];
- fmtnr = find_format(as->fmtin, as->numfmtin, d->format, d->srate);
+ fmtnr = find_format(as->fmtin, as->numfmtin, d->format);
if (fmtnr < 0) {
printk(KERN_ERR "usbaudio: set_format_in(): failed to find desired
format/speed combination.\n");
return -1;
@@ -1465,7 +1481,9 @@
d->srate = fmt->sratelo;
if (d->srate > fmt->sratehi)
d->srate = fmt->sratehi;
-printk(KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n",
alts->bInterfaceNumber, fmt->altsetting);
+#if 1
+ printk(KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n",
+alts->bInterfaceNumber, fmt->altsetting);
+#endif
if (usb_set_interface(dev, alts->bInterfaceNumber, fmt->altsetting) < 0) {
printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d
interface %d altsetting %d\n",
dev->devnum, u->interface, fmt->altsetting);
@@ -1525,7 +1543,7 @@
return 0;
iface = &config->interface[u->interface];
- fmtnr = find_format(as->fmtout, as->numfmtout, d->format, d->srate);
+ fmtnr = find_format(as->fmtout, as->numfmtout, d->format);
if (fmtnr < 0) {
printk(KERN_ERR "usbaudio: set_format_out(): failed to find desired
format/speed combination.\n");
return -1;
@@ -1559,7 +1577,9 @@
d->srate = fmt->sratelo;
if (d->srate > fmt->sratehi)
d->srate = fmt->sratehi;
-printk(KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n",
alts->bInterfaceNumber, fmt->altsetting);
+#if 1
+ printk(KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n",
+alts->bInterfaceNumber, fmt->altsetting);
+#endif
if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) {
printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d
interface %d altsetting %d\n",
dev->devnum, u->interface, fmt->altsetting);
@@ -1927,6 +1947,7 @@
if (as->usbout.dma.mapped || !as->usbout.dma.ready)
return 0;
+ usbout_start(as);
add_wait_queue(&as->usbout.dma.wait, &wait);
for (;;) {
__set_current_state(TASK_INTERRUPTIBLE);
@@ -2033,6 +2054,7 @@
ssize_t ret = 0;
unsigned long flags;
unsigned int ptr;
+ unsigned int start_thr;
int cnt, err;
if (ppos != &file->f_pos)
@@ -2043,10 +2065,11 @@
return ret;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
+ start_thr = (as->usbout.dma.srate << AFMT_BYTESSHIFT(as->usbout.dma.format)) /
+(1000 / (3 * DESCFRAMES));
add_wait_queue(&as->usbout.dma.wait, &wait);
while (count > 0) {
#if 0
- printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u
wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%x\n",
+ printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u
+wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%lx\n",
count, as->usbout.dma.count, as->usbout.dma.rdptr,
as->usbout.dma.wrptr, as->usbout.dma.dmasize, as->usbout.dma.fragsize,
as->usbout.flags, current->state);
#endif
@@ -2097,7 +2120,7 @@
count -= cnt;
buffer += cnt;
ret += cnt;
- if (usbout_start(as)) {
+ if (as->usbout.dma.count >= start_thr && usbout_start(as)) {
if (!ret)
ret = -ENODEV;
break;
@@ -2522,17 +2545,6 @@
/* --------------------------------------------------------------------- */
-/*
- * TO DO in order to get to the point of building an OSS interface
- * structure, let alone playing music..
- *
- * Use kmalloc/kfree for the descriptors we build
- * Write the descriptor->OSS convertor code
- * Figure how we deal with mixers
- * Check alternate configurations. For now assume we will find one
- * zero bandwidth (idle) config and one or more live one pers interface.
- */
-
static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum);
static void usb_audio_disconnect(struct usb_device *dev, void *ptr);
@@ -2540,25 +2552,11 @@
"audio",
usb_audio_probe,
usb_audio_disconnect,
- /*{ NULL, NULL }, */ LIST_HEAD_INIT(usb_audio_driver.driver_list),
+ LIST_HEAD_INIT(usb_audio_driver.driver_list),
NULL,
0
};
-
-#if 0
-static int usb_audio_irq(int state, void *buffer, int len, void *dev_id)
-{
-#if 0
- struct usb_audio_device *aud = (struct usb_audio_device *)dev_id;
-
- printk(KERN_DEBUG "irq on %p\n", aud);
-#endif
-
- return 1;
-}
-#endif
-
static void *find_descriptor(void *descstart, unsigned int desclen, void *after,
u8 dtype, int iface, int altsetting)
{
@@ -3556,11 +3554,6 @@
unregister_sound_mixer(ms->dev_mixer);
ms->dev_mixer = -1;
}
-#if 0
- if(aud->irq_handle)
- usb_release_irq(dev, aud->irq_handle, aud->irqpipe);
- aud->irq_handle = NULL;
-#endif
release(s);
wake_up(&open_wait);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]