linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / sound / usb / usbaudio.c
index 1b7f499..d501338 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/usb.h>
 #include <linux/vmalloc.h>
 #include <linux/moduleparam.h>
-#include <linux/mutex.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/pcm.h>
@@ -70,7 +69,6 @@ static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for
 static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */
 static int nrpacks = 4;                /* max. number of packets per urb */
 static int async_unlink = 1;
-static int device_setup[SNDRV_CARDS]; /* device parameter for this card*/
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
@@ -86,8 +84,6 @@ module_param(nrpacks, int, 0644);
 MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
 module_param(async_unlink, bool, 0444);
 MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
-module_param_array(device_setup, int, NULL, 0444);
-MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
 
 
 /*
@@ -206,7 +202,7 @@ struct snd_usb_stream {
  * the all interfaces on the same card as one sound device.
  */
 
-static DEFINE_MUTEX(register_mutex);
+static DECLARE_MUTEX(register_mutex);
 static struct snd_usb_audio *usb_chip[SNDRV_CARDS];
 
 
@@ -479,18 +475,6 @@ static int retire_playback_sync_urb_hs(struct snd_usb_substream *subs,
        return 0;
 }
 
-/* determine the number of frames in the next packet */
-static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
-{
-       if (subs->fill_max)
-               return subs->maxframesize;
-       else {
-               subs->phase = (subs->phase & 0xffff)
-                       + (subs->freqm << subs->datainterval);
-               return min(subs->phase >> 16, subs->maxframesize);
-       }
-}
-
 /*
  * Prepare urb for streaming before playback starts.
  *
@@ -508,7 +492,16 @@ static int prepare_startup_playback_urb(struct snd_usb_substream *subs,
        urb->dev = ctx->subs->dev;
        urb->number_of_packets = subs->packs_per_ms;
        for (i = 0; i < subs->packs_per_ms; ++i) {
-               counts = snd_usb_audio_next_packet_size(subs);
+               /* calculate the size of a packet */
+               if (subs->fill_max)
+                       counts = subs->maxframesize; /* fixed */
+               else {
+                       subs->phase = (subs->phase & 0xffff)
+                               + (subs->freqm << subs->datainterval);
+                       counts = subs->phase >> 16;
+                       if (counts > subs->maxframesize)
+                               counts = subs->maxframesize;
+               }
                urb->iso_frame_desc[i].offset = offs * stride;
                urb->iso_frame_desc[i].length = counts * stride;
                offs += counts;
@@ -545,7 +538,16 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
        urb->number_of_packets = 0;
        spin_lock_irqsave(&subs->lock, flags);
        for (i = 0; i < ctx->packets; i++) {
-               counts = snd_usb_audio_next_packet_size(subs);
+               /* calculate the size of a packet */
+               if (subs->fill_max)
+                       counts = subs->maxframesize; /* fixed */
+               else {
+                       subs->phase = (subs->phase & 0xffff)
+                               + (subs->freqm << subs->datainterval);
+                       counts = subs->phase >> 16;
+                       if (counts > subs->maxframesize)
+                               counts = subs->maxframesize;
+               }
                /* set up descriptor */
                urb->iso_frame_desc[i].offset = offs * stride;
                urb->iso_frame_desc[i].length = counts * stride;
@@ -723,9 +725,10 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s
 static int snd_pcm_free_vmalloc_buffer(struct snd_pcm_substream *subs)
 {
        struct snd_pcm_runtime *runtime = subs->runtime;
-
-       vfree(runtime->dma_area);
-       runtime->dma_area = NULL;
+       if (runtime->dma_area) {
+               vfree(runtime->dma_area);
+               runtime->dma_area = NULL;
+       }
        return 0;
 }
 
@@ -776,35 +779,6 @@ static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sl
 }
 
 
-static const char *usb_error_string(int err)
-{
-       switch (err) {
-       case -ENODEV:
-               return "no device";
-       case -ENOENT:
-               return "endpoint not enabled";
-       case -EPIPE:
-               return "endpoint stalled";
-       case -ENOSPC:
-               return "not enough bandwidth";
-       case -ESHUTDOWN:
-               return "device disabled";
-       case -EHOSTUNREACH:
-               return "device suspended";
-#ifndef CONFIG_USB_EHCI_SPLIT_ISO
-       case -ENOSYS:
-               return "enable CONFIG_USB_EHCI_SPLIT_ISO to play through a hub";
-#endif
-       case -EINVAL:
-       case -EAGAIN:
-       case -EFBIG:
-       case -EMSGSIZE:
-               return "internal error";
-       default:
-               return "unknown error";
-       }
-}
-
 /*
  * set up and start data/sync urbs
  */
@@ -837,22 +811,16 @@ static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *ru
        subs->unlink_mask = 0;
        subs->running = 1;
        for (i = 0; i < subs->nurbs; i++) {
-               err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC);
-               if (err < 0) {
-                       snd_printk(KERN_ERR "cannot submit datapipe "
-                                  "for urb %d, error %d: %s\n",
-                                  i, err, usb_error_string(err));
+               if ((err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC)) < 0) {
+                       snd_printk(KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err);
                        goto __error;
                }
                set_bit(i, &subs->active_mask);
        }
        if (subs->syncpipe) {
                for (i = 0; i < SYNC_URBS; i++) {
-                       err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC);
-                       if (err < 0) {
-                               snd_printk(KERN_ERR "cannot submit syncpipe "
-                                          "for urb %d, error %d: %s\n",
-                                          i, err, usb_error_string(err));
+                       if ((err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC)) < 0) {
+                               snd_printk(KERN_ERR "cannot submit syncpipe for urb %d, err = %d\n", i, err);
                                goto __error;
                        }
                        set_bit(i + 16, &subs->active_mask);
@@ -1422,8 +1390,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
        channels = params_channels(hw_params);
        fmt = find_format(subs, format, rate, channels);
        if (! fmt) {
-               snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n",
-                          format, rate, channels);
+               snd_printd(KERN_DEBUG "cannot set format: format = %s, rate = %d, channels = %d\n",
+                          snd_pcm_format_name(format), rate, channels);
                return -EINVAL;
        }
 
@@ -2049,8 +2017,6 @@ static struct usb_driver usb_audio_driver = {
 };
 
 
-#if defined(CONFIG_PROCFS) && defined(CONFIG_SND_VERBOSE_PROCFS)
-
 /*
  * proc interface for list the supported pcm formats
  */
@@ -2066,7 +2032,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
                fp = list_entry(p, struct audioformat, list);
                snd_iprintf(buffer, "  Interface %d\n", fp->iface);
                snd_iprintf(buffer, "    Altset %d\n", fp->altsetting);
-               snd_iprintf(buffer, "    Format: 0x%x\n", fp->format);
+               snd_iprintf(buffer, "    Format: %s\n", snd_pcm_format_name(fp->format));
                snd_iprintf(buffer, "    Channels: %d\n", fp->channels);
                snd_iprintf(buffer, "    Endpoint: %d %s (%s)\n",
                            fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
@@ -2138,16 +2104,9 @@ static void proc_pcm_format_add(struct snd_usb_stream *stream)
 
        sprintf(name, "stream%d", stream->pcm_index);
        if (! snd_card_proc_new(card, name, &entry))
-               snd_info_set_text_ops(entry, stream, proc_pcm_format_read);
-}
-
-#else
-
-static inline void proc_pcm_format_add(struct snd_usb_stream *stream)
-{
+               snd_info_set_text_ops(entry, stream, 1024, proc_pcm_format_read);
 }
 
-#endif
 
 /*
  * initialize the substream instance.
@@ -2260,9 +2219,10 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud
        }
 
        /* create a new pcm */
-       as = kzalloc(sizeof(*as), GFP_KERNEL);
+       as = kmalloc(sizeof(*as), GFP_KERNEL);
        if (! as)
                return -ENOMEM;
+       memset(as, 0, sizeof(*as));
        as->pcm_index = chip->pcm_devs;
        as->chip = chip;
        as->fmt_type = fp->fmt_type;
@@ -2549,8 +2509,6 @@ static int parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp
        return 0;
 }
 
-static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
-                                        int iface, int altno);
 static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
 {
        struct usb_device *dev;
@@ -2585,12 +2543,6 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
                        SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
                altno = altsd->bAlternateSetting;
-       
-               /* audiophile usb: skip altsets incompatible with device_setup
-                */
-               if (chip->usb_id == USB_ID(0x0763, 0x2003) && 
-                   audiophile_skip_setting_quirk(chip, iface_no, altno))
-                       continue;
 
                /* get audio formats */
                fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, AS_GENERAL);
@@ -2626,18 +2578,18 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                if (!csep && altsd->bNumEndpoints >= 2)
                        csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
                if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) {
-                       snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
-                                  " class specific endpoint descriptor\n",
+                       snd_printk(KERN_ERR "%d:%u:%d : no or invalid class specific endpoint descriptor\n",
                                   dev->devnum, iface_no, altno);
-                       csep = NULL;
+                       continue;
                }
 
-               fp = kzalloc(sizeof(*fp), GFP_KERNEL);
+               fp = kmalloc(sizeof(*fp), GFP_KERNEL);
                if (! fp) {
                        snd_printk(KERN_ERR "cannot malloc\n");
                        return -ENOMEM;
                }
 
+               memset(fp, 0, sizeof(*fp));
                fp->iface = iface_no;
                fp->altsetting = altno;
                fp->altset_idx = i;
@@ -2647,7 +2599,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
                        fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
                                        * (fp->maxpacksize & 0x7ff);
-               fp->attributes = csep ? csep[3] : 0;
+               fp->attributes = csep[3];
 
                /* some quirks for attributes here */
 
@@ -2685,7 +2637,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                        continue;
                }
 
-               snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint 0x%x\n", dev->devnum, iface_no, altno, fp->endpoint);
+               snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint 0x%x\n", dev->devnum, iface_no, i, fp->endpoint);
                err = add_audio_endpoint(chip, stream, fp);
                if (err < 0) {
                        kfree(fp->rate_table);
@@ -2979,7 +2931,7 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip,
                return -ENXIO;
        alts = &iface->altsetting[1];
        altsd = get_iface_desc(alts);
-       if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE ||
+       if (alts->extralen != 11 || alts->extra[1] != CS_AUDIO_INTERFACE ||
            altsd->bNumEndpoints != 1)
                return -ENXIO;
 
@@ -3093,71 +3045,6 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
        return 0;
 }
 
-/*
- * C-Media CM106/CM106+ have four 16-bit internal registers that are nicely
- * documented in the device's data sheet.
- */
-static int snd_usb_cm106_write_int_reg(struct usb_device *dev, int reg, u16 value)
-{
-       u8 buf[4];
-       buf[0] = 0x20;
-       buf[1] = value & 0xff;
-       buf[2] = (value >> 8) & 0xff;
-       buf[3] = reg;
-       return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION,
-                              USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
-                              0, 0, &buf, 4, 1000);
-}
-
-static int snd_usb_cm106_boot_quirk(struct usb_device *dev)
-{
-       /*
-        * Enable line-out driver mode, set headphone source to front
-        * channels, enable stereo mic.
-        */
-       return snd_usb_cm106_write_int_reg(dev, 2, 0x8004);
-}
-
-
-/*
- * Setup quirks
- */
-#define AUDIOPHILE_SET                 0x01 /* if set, parse device_setup */
-#define AUDIOPHILE_SET_DTS              0x02 /* if set, enable DTS Digital Output */
-#define AUDIOPHILE_SET_96K              0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */
-#define AUDIOPHILE_SET_24B             0x08 /* 24bits sample if set, 16bits otherwise */
-#define AUDIOPHILE_SET_DI              0x10 /* if set, enable Digital Input */
-#define AUDIOPHILE_SET_MASK            0x1F /* bit mask for setup value */
-#define AUDIOPHILE_SET_24B_48K_DI      0x19 /* value for 24bits+48KHz+Digital Input */
-#define AUDIOPHILE_SET_24B_48K_NOTDI   0x09 /* value for 24bits+48KHz+No Digital Input */
-#define AUDIOPHILE_SET_16B_48K_DI      0x11 /* value for 16bits+48KHz+Digital Input */
-#define AUDIOPHILE_SET_16B_48K_NOTDI   0x01 /* value for 16bits+48KHz+No Digital Input */
-
-static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
-                                        int iface, int altno)
-{
-       if (device_setup[chip->index] & AUDIOPHILE_SET) {
-               if ((device_setup[chip->index] & AUDIOPHILE_SET_DTS)
-                   && altno != 6)
-                       return 1; /* skip this altsetting */
-               if ((device_setup[chip->index] & AUDIOPHILE_SET_96K)
-                   && altno != 1)
-                       return 1; /* skip this altsetting */
-               if ((device_setup[chip->index] & AUDIOPHILE_SET_MASK) ==
-                   AUDIOPHILE_SET_24B_48K_DI && altno != 2)
-                       return 1; /* skip this altsetting */
-               if ((device_setup[chip->index] & AUDIOPHILE_SET_MASK) ==
-                   AUDIOPHILE_SET_24B_48K_NOTDI && altno != 3)
-                       return 1; /* skip this altsetting */
-               if ((device_setup[chip->index] & AUDIOPHILE_SET_MASK) ==
-                   AUDIOPHILE_SET_16B_48K_DI && altno != 4)
-                       return 1; /* skip this altsetting */
-               if ((device_setup[chip->index] & AUDIOPHILE_SET_MASK) ==
-                   AUDIOPHILE_SET_16B_48K_NOTDI && altno != 5)
-                       return 1; /* skip this altsetting */
-       }       
-       return 0; /* keep this altsetting */
-}
 
 /*
  * audio-interface quirks
@@ -3183,7 +3070,7 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
                [QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface,
                [QUIRK_MIDI_RAW] = snd_usb_create_midi_interface,
                [QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface,
-               [QUIRK_MIDI_CME] = snd_usb_create_midi_interface,
+               [QUIRK_MIDI_MIDITECH] = snd_usb_create_midi_interface,
                [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
                [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
                [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk,
@@ -3222,9 +3109,9 @@ static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
 {
        struct snd_info_entry *entry;
        if (! snd_card_proc_new(chip->card, "usbbus", &entry))
-               snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read);
+               snd_info_set_text_ops(entry, chip, 1024, proc_audio_usbbus_read);
        if (! snd_card_proc_new(chip->card, "usbid", &entry))
-               snd_info_set_text_ops(entry, chip, proc_audio_usbid_read);
+               snd_info_set_text_ops(entry, chip, 1024, proc_audio_usbid_read);
 }
 
 /*
@@ -3389,19 +3276,13 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
                        goto __err_val;
        }
 
-       /* C-Media CM106 / Turtle Beach Audio Advantage Roadie */
-       if (id == USB_ID(0x10f5, 0x0200)) {
-               if (snd_usb_cm106_boot_quirk(dev) < 0)
-                       goto __err_val;
-       }
-
        /*
         * found a config.  now register to ALSA
         */
 
        /* check whether it's already registered */
        chip = NULL;
-       mutex_lock(&register_mutex);
+       down(&register_mutex);
        for (i = 0; i < SNDRV_CARDS; i++) {
                if (usb_chip[i] && usb_chip[i]->dev == dev) {
                        if (usb_chip[i]->shutdown) {
@@ -3454,13 +3335,13 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
 
        usb_chip[chip->index] = chip;
        chip->num_interfaces++;
-       mutex_unlock(&register_mutex);
+       up(&register_mutex);
        return chip;
 
  __error:
        if (chip && !chip->num_interfaces)
                snd_card_free(chip->card);
-       mutex_unlock(&register_mutex);
+       up(&register_mutex);
  __err_val:
        return NULL;
 }
@@ -3480,7 +3361,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
 
        chip = ptr;
        card = chip->card;
-       mutex_lock(&register_mutex);
+       down(&register_mutex);
        chip->shutdown = 1;
        chip->num_interfaces--;
        if (chip->num_interfaces <= 0) {
@@ -3498,10 +3379,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
                        snd_usb_mixer_disconnect(p);
                }
                usb_chip[chip->index] = NULL;
-               mutex_unlock(&register_mutex);
+               up(&register_mutex);
                snd_card_free(card);
        } else {
-               mutex_unlock(&register_mutex);
+               up(&register_mutex);
        }
 }