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]

Reply via email to