patch-2.3.99-pre9 linux/drivers/usb/audio.c
Next file: linux/drivers/usb/hub.c
Previous file: linux/drivers/usb/Config.in
Back to the patch index
Back to the overall index
- Lines: 262
- Date:
Mon May 15 11:38:19 2000
- Orig file:
v2.3.99-pre8/linux/drivers/usb/audio.c
- Orig date:
Thu May 11 15:30:08 2000
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/audio.c linux/drivers/usb/audio.c
@@ -3,7 +3,7 @@
/*
* audio.c -- USB Audio Class driver
*
- * Copyright (C) 1999
+ * Copyright (C) 1999, 2000
* Alan Cox (alan@lxorguk.ukuu.org.uk)
* Thomas Sailer (sailer@ife.ee.ethz.ch)
*
@@ -59,6 +59,21 @@
* 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.
+ * 2000-05-15: My fears came true, the Philips camera indeed has pretty stupid
+ * audio descriptors.
*
*/
@@ -441,9 +456,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 +988,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 +1349,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,30 +1414,39 @@
/* --------------------------------------------------------------------- */
-static unsigned int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int rate)
+static unsigned int format_goodness(struct audioformat *afp, unsigned int fmt, unsigned int srate)
{
- unsigned int i;
+ unsigned int g = 0;
+
+ if (srate < afp->sratelo)
+ g += afp->sratelo - srate;
+ if (srate > afp->sratehi)
+ g += srate - afp->sratehi;
+ if (AFMT_ISSTEREO(afp->format) && !AFMT_ISSTEREO(fmt))
+ g += 0x100000;
+ if (!AFMT_ISSTEREO(afp->format) && AFMT_ISSTEREO(fmt))
+ g += 0x400000;
+ if (AFMT_IS16BIT(afp->format) && !AFMT_IS16BIT(fmt))
+ g += 0x100000;
+ if (!AFMT_IS16BIT(afp->format) && AFMT_IS16BIT(fmt))
+ g += 0x400000;
+ return g;
+}
+
+static int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int srate)
+{
+ unsigned int i, g, gb = ~0;
+ int j = -1; /* default to failure */
- /* first find an exact match, taking both format and sample rate into account,
- but ignore stereo bit */
+ /* find "best" format (according to format_goodness) */
for (i = 0; i < nr; i++) {
- if (afp[i].format == (fmt & ~AFMT_STEREO) && rate >= afp[i].sratelo && rate <= afp[i].sratehi)
- return i;
+ g = format_goodness(&afp[i], fmt, srate);
+ if (g >= gb)
+ continue;
+ j = i;
+ gb = g;
}
-
- /* 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)
- 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)
- return i;
- /* return failure */
- return -1;
+ return j;
}
static int set_format_in(struct usb_audiodev *as)
@@ -1430,9 +1458,9 @@
struct usbin *u = &as->usbin;
struct dmabuf *d = &u->dma;
struct audioformat *fmt;
- unsigned int fmtnr, ep;
+ unsigned int ep;
unsigned char data[3];
- int ret;
+ int fmtnr, ret;
if (u->interface < 0 || u->interface >= config->bNumInterfaces)
return 0;
@@ -1465,7 +1493,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);
@@ -1517,9 +1547,9 @@
struct usbout *u = &as->usbout;
struct dmabuf *d = &u->dma;
struct audioformat *fmt;
- unsigned int fmtnr, ep;
+ unsigned int ep;
unsigned char data[3];
- int ret;
+ int fmtnr, ret;
if (u->interface < 0 || u->interface >= config->bNumInterfaces)
return 0;
@@ -1559,7 +1589,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 +1959,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 +2066,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 +2077,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 +2132,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;
@@ -2525,17 +2560,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);
@@ -2543,25 +2567,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)
{
@@ -3559,11 +3569,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);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)