summaryrefslogtreecommitdiff
path: root/sound/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/caiaq/caiaq-audio.c81
-rw-r--r--sound/usb/caiaq/caiaq-device.c4
-rw-r--r--sound/usb/usbaudio.c98
-rw-r--r--sound/usb/usbquirks.h75
4 files changed, 134 insertions, 124 deletions
diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c
index 9cc4cd8283f9..24970a5c888f 100644
--- a/sound/usb/caiaq/caiaq-audio.c
+++ b/sound/usb/caiaq/caiaq-audio.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006,2007 Daniel Mack, Karsten Wiese
+ * Copyright (c) 2006-2008 Daniel Mack, Karsten Wiese
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -39,7 +39,8 @@
#define BYTES_PER_SAMPLE 3
#define BYTES_PER_SAMPLE_USB 4
#define MAX_BUFFER_SIZE (128*1024)
-
+#define MAX_ENDPOINT_SIZE 512
+
#define ENDPOINT_CAPTURE 2
#define ENDPOINT_PLAYBACK 6
@@ -77,10 +78,15 @@ static void
deactivate_substream(struct snd_usb_caiaqdev *dev,
struct snd_pcm_substream *sub)
{
+ unsigned long flags;
+ spin_lock_irqsave(&dev->spinlock, flags);
+
if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
dev->sub_playback[sub->number] = NULL;
else
dev->sub_capture[sub->number] = NULL;
+
+ spin_unlock_irqrestore(&dev->spinlock, flags);
}
static int
@@ -97,13 +103,13 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
{
int i, ret;
- debug("stream_start(%p)\n", dev);
- spin_lock_irq(&dev->spinlock);
- if (dev->streaming) {
- spin_unlock_irq(&dev->spinlock);
+ debug("%s(%p)\n", __func__, dev);
+
+ if (dev->streaming)
return -EINVAL;
- }
+ memset(dev->sub_playback, 0, sizeof(dev->sub_playback));
+ memset(dev->sub_capture, 0, sizeof(dev->sub_capture));
dev->input_panic = 0;
dev->output_panic = 0;
dev->first_packet = 1;
@@ -112,37 +118,35 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
for (i = 0; i < N_URBS; i++) {
ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC);
if (ret) {
- log("unable to trigger initial read #%d! (ret = %d)\n",
- i, ret);
+ log("unable to trigger read #%d! (ret %d)\n", i, ret);
dev->streaming = 0;
- spin_unlock_irq(&dev->spinlock);
return -EPIPE;
}
}
- spin_unlock_irq(&dev->spinlock);
return 0;
}
static void stream_stop(struct snd_usb_caiaqdev *dev)
{
int i;
-
- debug("stream_stop(%p)\n", dev);
+
+ debug("%s(%p)\n", __func__, dev);
if (!dev->streaming)
return;
dev->streaming = 0;
+
for (i = 0; i < N_URBS; i++) {
- usb_unlink_urb(dev->data_urbs_in[i]);
- usb_unlink_urb(dev->data_urbs_out[i]);
+ usb_kill_urb(dev->data_urbs_in[i]);
+ usb_kill_urb(dev->data_urbs_out[i]);
}
}
static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream)
{
struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
- debug("snd_usb_caiaq_substream_open(%p)\n", substream);
+ debug("%s(%p)\n", __func__, substream);
substream->runtime->hw = dev->pcm_info;
snd_pcm_limit_hw_rates(substream->runtime);
return 0;
@@ -152,7 +156,7 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
{
struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
- debug("snd_usb_caiaq_substream_close(%p)\n", substream);
+ debug("%s(%p)\n", __func__, substream);
if (all_substreams_zero(dev->sub_playback) &&
all_substreams_zero(dev->sub_capture)) {
/* when the last client has stopped streaming,
@@ -160,24 +164,22 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
stream_stop(dev);
dev->pcm_info.rates = dev->samplerates;
}
-
+
return 0;
}
static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub,
struct snd_pcm_hw_params *hw_params)
{
- debug("snd_usb_caiaq_pcm_hw_params(%p)\n", sub);
+ debug("%s(%p)\n", __func__, sub);
return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params));
}
static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
{
struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
- debug("snd_usb_caiaq_pcm_hw_free(%p)\n", sub);
- spin_lock_irq(&dev->spinlock);
+ debug("%s(%p)\n", __func__, sub);
deactivate_substream(dev, sub);
- spin_unlock_irq(&dev->spinlock);
return snd_pcm_lib_free_pages(sub);
}
@@ -196,12 +198,12 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
- debug("snd_usb_caiaq_pcm_prepare(%p)\n", substream);
+ debug("%s(%p)\n", __func__, substream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1;
else
- dev->audio_in_buf_pos[index] = 0;
+ dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE;
if (dev->streaming)
return 0;
@@ -220,7 +222,10 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE)
* bytes_per_sample * CHANNELS_PER_STREAM * dev->n_streams;
-
+
+ if (bpp > MAX_ENDPOINT_SIZE)
+ bpp = MAX_ENDPOINT_SIZE;
+
ret = snd_usb_caiaq_set_audio_params(dev, runtime->rate,
runtime->sample_bits, bpp);
if (ret)
@@ -247,15 +252,11 @@ static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd)
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- spin_lock(&dev->spinlock);
activate_substream(dev, sub);
- spin_unlock(&dev->spinlock);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- spin_lock(&dev->spinlock);
deactivate_substream(dev, sub);
- spin_unlock(&dev->spinlock);
break;
default:
return -EINVAL;
@@ -328,8 +329,6 @@ static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
if (all_substreams_zero(dev->sub_capture))
return;
- spin_lock(&dev->spinlock);
-
for (i = 0; i < iso->actual_length;) {
for (stream = 0; stream < dev->n_streams; stream++, i++) {
sub = dev->sub_capture[stream];
@@ -345,8 +344,6 @@ static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
}
}
}
-
- spin_unlock(&dev->spinlock);
}
static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
@@ -358,8 +355,6 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
struct snd_pcm_substream *sub;
int stream, i;
- spin_lock(&dev->spinlock);
-
for (i = 0; i < iso->actual_length;) {
if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) {
for (stream = 0;
@@ -393,8 +388,6 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
}
}
}
-
- spin_unlock(&dev->spinlock);
}
static void read_in_urb(struct snd_usb_caiaqdev *dev,
@@ -418,8 +411,6 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev,
dev->input_panic ? "(input)" : "",
dev->output_panic ? "(output)" : "");
}
-
- check_for_elapsed_periods(dev, dev->sub_capture);
}
static void fill_out_urb(struct snd_usb_caiaqdev *dev,
@@ -429,8 +420,6 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
struct snd_pcm_substream *sub;
int stream, i;
-
- spin_lock(&dev->spinlock);
for (i = 0; i < iso->length;) {
for (stream = 0; stream < dev->n_streams; stream++, i++) {
@@ -456,9 +445,6 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
for (stream = 0; stream < dev->n_streams; stream++, i++)
usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i);
}
-
- spin_unlock(&dev->spinlock);
- check_for_elapsed_periods(dev, dev->sub_playback);
}
static void read_completed(struct urb *urb)
@@ -472,6 +458,7 @@ static void read_completed(struct urb *urb)
return;
dev = info->dev;
+
if (!dev->streaming)
return;
@@ -489,8 +476,12 @@ static void read_completed(struct urb *urb)
out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame;
if (len > 0) {
+ spin_lock(&dev->spinlock);
fill_out_urb(dev, out, &out->iso_frame_desc[outframe]);
read_in_urb(dev, urb, &urb->iso_frame_desc[frame]);
+ spin_unlock(&dev->spinlock);
+ check_for_elapsed_periods(dev, dev->sub_playback);
+ check_for_elapsed_periods(dev, dev->sub_capture);
send_it = 1;
}
@@ -696,7 +687,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev)
{
- debug("snd_usb_caiaq_audio_free (%p)\n", dev);
+ debug("%s(%p)\n", __func__, dev);
stream_stop(dev);
free_urbs(dev->data_urbs_in);
free_urbs(dev->data_urbs_out);
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
index 7c44a2c7f963..e97d8b2ac16a 100644
--- a/sound/usb/caiaq/caiaq-device.c
+++ b/sound/usb/caiaq/caiaq-device.c
@@ -42,7 +42,7 @@
#endif
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.2");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.6");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
"{Native Instruments, RigKontrol3},"
@@ -456,7 +456,7 @@ static void snd_disconnect(struct usb_interface *intf)
struct snd_usb_caiaqdev *dev;
struct snd_card *card = dev_get_drvdata(&intf->dev);
- debug("snd_disconnect(%p)\n", intf);
+ debug("%s(%p)\n", __func__, intf);
if (!card)
return;
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index f48838a078cb..410be4aff1ba 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -64,9 +64,10 @@ MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
-static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for this card */
-static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
+/* Vendor/product IDs for this card */
+static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
+static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
static int nrpacks = 8; /* max. number of packets per urb */
static int async_unlink = 1;
static int device_setup[SNDRV_CARDS]; /* device parameter for this card*/
@@ -687,7 +688,7 @@ static void snd_complete_urb(struct urb *urb)
int err = 0;
if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
- ! subs->running || /* can be stopped during retire callback */
+ !subs->running || /* can be stopped during retire callback */
(err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
(err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
clear_bit(ctx->index, &subs->active_mask);
@@ -710,7 +711,7 @@ static void snd_complete_sync_urb(struct urb *urb)
int err = 0;
if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
- ! subs->running || /* can be stopped during retire callback */
+ !subs->running || /* can be stopped during retire callback */
(err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
(err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
clear_bit(ctx->index + 16, &subs->active_mask);
@@ -740,7 +741,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s
vfree(runtime->dma_area);
}
runtime->dma_area = vmalloc(size);
- if (! runtime->dma_area)
+ if (!runtime->dma_area)
return -ENOMEM;
runtime->dma_bytes = size;
return 0;
@@ -772,12 +773,12 @@ static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sl
async = !can_sleep && async_unlink;
- if (! async && in_interrupt())
+ if (!async && in_interrupt())
return 0;
for (i = 0; i < subs->nurbs; i++) {
if (test_bit(i, &subs->active_mask)) {
- if (! test_and_set_bit(i, &subs->unlink_mask)) {
+ if (!test_and_set_bit(i, &subs->unlink_mask)) {
struct urb *u = subs->dataurb[i].urb;
if (async)
usb_unlink_urb(u);
@@ -789,7 +790,7 @@ static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sl
if (subs->syncpipe) {
for (i = 0; i < SYNC_URBS; i++) {
if (test_bit(i+16, &subs->active_mask)) {
- if (! test_and_set_bit(i+16, &subs->unlink_mask)) {
+ if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
struct urb *u = subs->syncurb[i].urb;
if (async)
usb_unlink_urb(u);
@@ -1137,12 +1138,12 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
if (subs->fmt_type == USB_FORMAT_TYPE_II)
u->packets++; /* for transfer delimiter */
u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
- if (! u->urb)
+ if (!u->urb)
goto out_of_memory;
u->urb->transfer_buffer =
usb_buffer_alloc(subs->dev, u->buffer_size, GFP_KERNEL,
&u->urb->transfer_dma);
- if (! u->urb->transfer_buffer)
+ if (!u->urb->transfer_buffer)
goto out_of_memory;
u->urb->pipe = subs->datapipe;
u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
@@ -1155,7 +1156,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
/* allocate and initialize sync urbs */
subs->syncbuf = usb_buffer_alloc(subs->dev, SYNC_URBS * 4,
GFP_KERNEL, &subs->sync_dma);
- if (! subs->syncbuf)
+ if (!subs->syncbuf)
goto out_of_memory;
for (i = 0; i < SYNC_URBS; i++) {
struct snd_urb_ctx *u = &subs->syncurb[i];
@@ -1163,7 +1164,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
u->subs = subs;
u->packets = 1;
u->urb = usb_alloc_urb(1, GFP_KERNEL);
- if (! u->urb)
+ if (!u->urb)
goto out_of_memory;
u->urb->transfer_buffer = subs->syncbuf + i * 4;
u->urb->transfer_dma = subs->sync_dma + i * 4;
@@ -1427,8 +1428,8 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
subs->cur_audiofmt = fmt;
#if 0
- printk("setting done: format = %d, rate = %d, channels = %d\n",
- fmt->format, fmt->rate, fmt->channels);
+ printk("setting done: format = %d, rate = %d..%d, channels = %d\n",
+ fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels);
printk(" datapipe = 0x%0x, syncpipe = 0x%0x\n",
subs->datapipe, subs->syncpipe);
#endif
@@ -1463,7 +1464,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
rate = params_rate(hw_params);
channels = params_channels(hw_params);
fmt = find_format(subs, format, rate, channels);
- if (! fmt) {
+ if (!fmt) {
snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n",
format, rate, channels);
return -EINVAL;
@@ -1584,7 +1585,7 @@ static int hw_check_valid_format(struct snd_pcm_hw_params *params, struct audiof
struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
/* check the format */
- if (! snd_mask_test(fmts, fp->format)) {
+ if (!snd_mask_test(fmts, fp->format)) {
hwc_debug(" > check: no supported format %d\n", fp->format);
return 0;
}
@@ -1620,7 +1621,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
list_for_each(p, &subs->fmt_list) {
struct audioformat *fp;
fp = list_entry(p, struct audioformat, list);
- if (! hw_check_valid_format(params, fp))
+ if (!hw_check_valid_format(params, fp))
continue;
if (changed++) {
if (rmin > fp->rate_min)
@@ -1633,7 +1634,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
}
}
- if (! changed) {
+ if (!changed) {
hwc_debug(" --> get empty\n");
it->empty = 1;
return -EINVAL;
@@ -1674,7 +1675,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
list_for_each(p, &subs->fmt_list) {
struct audioformat *fp;
fp = list_entry(p, struct audioformat, list);
- if (! hw_check_valid_format(params, fp))
+ if (!hw_check_valid_format(params, fp))
continue;
if (changed++) {
if (rmin > fp->channels)
@@ -1687,7 +1688,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
}
}
- if (! changed) {
+ if (!changed) {
hwc_debug(" --> get empty\n");
it->empty = 1;
return -EINVAL;
@@ -1727,7 +1728,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
list_for_each(p, &subs->fmt_list) {
struct audioformat *fp;
fp = list_entry(p, struct audioformat, list);
- if (! hw_check_valid_format(params, fp))
+ if (!hw_check_valid_format(params, fp))
continue;
fbits |= (1ULL << fp->format);
}
@@ -1736,7 +1737,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
oldbits[1] = fmt->bits[1];
fmt->bits[0] &= (u32)fbits;
fmt->bits[1] &= (u32)(fbits >> 32);
- if (! fmt->bits[0] && ! fmt->bits[1]) {
+ if (!fmt->bits[0] && !fmt->bits[1]) {
hwc_debug(" --> get empty\n");
return -EINVAL;
}
@@ -1762,8 +1763,10 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
- if (!channels || !rates)
+ if (!channels || !rates) {
+ err = -ENOMEM;
goto __out;
+ }
list_for_each(p, &subs->fmt_list) {
struct audioformat *f;
@@ -1916,7 +1919,10 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
1000 * MIN_PACKS_URB,
/*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX);
- if (check_hw_params_convention(subs)) {
+ err = check_hw_params_convention(subs);
+ if (err < 0)
+ return err;
+ else if (err) {
hwc_debug("setting extra hw constraints...\n");
if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
hw_rule_rate, subs,
@@ -2222,7 +2228,7 @@ static void proc_pcm_format_add(struct snd_usb_stream *stream)
struct snd_card *card = stream->chip->card;
sprintf(name, "stream%d", stream->pcm_index);
- if (! snd_card_proc_new(card, name, &entry))
+ if (!snd_card_proc_new(card, name, &entry))
snd_info_set_text_ops(entry, stream, proc_pcm_format_read);
}
@@ -2278,7 +2284,7 @@ static void free_substream(struct snd_usb_substream *subs)
{
struct list_head *p, *n;
- if (! subs->num_formats)
+ if (!subs->num_formats)
return; /* not initialized */
list_for_each_safe(p, n, &subs->fmt_list) {
struct audioformat *fp = list_entry(p, struct audioformat, list);
@@ -2328,7 +2334,7 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud
if (as->fmt_type != fp->fmt_type)
continue;
subs = &as->substream[stream];
- if (! subs->endpoint)
+ if (!subs->endpoint)
continue;
if (subs->endpoint == fp->endpoint) {
list_add_tail(&fp->list, &subs->fmt_list);
@@ -2354,7 +2360,7 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud
/* create a new pcm */
as = kzalloc(sizeof(*as), GFP_KERNEL);
- if (! as)
+ if (!as)
return -ENOMEM;
as->pcm_index = chip->pcm_devs;
as->chip = chip;
@@ -2463,11 +2469,12 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, struct audiofor
}
break;
case USB_AUDIO_FORMAT_PCM8:
- /* Dallas DS4201 workaround */
+ pcm_format = SNDRV_PCM_FORMAT_U8;
+
+ /* Dallas DS4201 workaround: it advertises U8 format, but really
+ supports S8. */
if (chip->usb_id == USB_ID(0x04fa, 0x4201))
pcm_format = SNDRV_PCM_FORMAT_S8;
- else
- pcm_format = SNDRV_PCM_FORMAT_U8;
break;
case USB_AUDIO_FORMAT_IEEE_FLOAT:
pcm_format = SNDRV_PCM_FORMAT_FLOAT_LE;
@@ -2671,12 +2678,23 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
int format;
struct audioformat *fp;
unsigned char *fmt, *csep;
+ int num;
dev = chip->dev;
/* parse the interface's altsettings */
iface = usb_ifnum_to_if(dev, iface_no);
- for (i = 0; i < iface->num_altsetting; i++) {
+
+ num = iface->num_altsetting;
+
+ /*
+ * Dallas DS4201 workaround: It presents 5 altsettings, but the last
+ * one misses syncpipe, and does not produce any sound.
+ */
+ if (chip->usb_id == USB_ID(0x04fa, 0x4201))
+ num = 4;
+
+ for (i = 0; i < num; i++) {
alts = &iface->altsetting[i];
altsd = get_iface_desc(alts);
/* skip invalid one */
@@ -3375,14 +3393,14 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
static void proc_audio_usbbus_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
struct snd_usb_audio *chip = entry->private_data;
- if (! chip->shutdown)
+ if (!chip->shutdown)
snd_iprintf(buffer, "%03d/%03d\n", chip->dev->bus->busnum, chip->dev->devnum);
}
static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
struct snd_usb_audio *chip = entry->private_data;
- if (! chip->shutdown)
+ if (!chip->shutdown)
snd_iprintf(buffer, "%04x:%04x\n",
USB_ID_VENDOR(chip->usb_id),
USB_ID_PRODUCT(chip->usb_id));
@@ -3391,9 +3409,9 @@ static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_
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))
+ if (!snd_card_proc_new(chip->card, "usbbus", &entry))
snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read);
- if (! snd_card_proc_new(chip->card, "usbid", &entry))
+ if (!snd_card_proc_new(chip->card, "usbid", &entry))
snd_info_set_text_ops(entry, chip, proc_audio_usbid_read);
}
@@ -3406,7 +3424,6 @@ static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
static int snd_usb_audio_free(struct snd_usb_audio *chip)
{
- usb_chip[chip->index] = NULL;
kfree(chip);
return 0;
}
@@ -3600,8 +3617,8 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
snd_card_set_dev(chip->card, &intf->dev);
break;
}
- if (! chip) {
- snd_printk(KERN_ERR "no available usb audio device\n");
+ if (!chip) {
+ printk(KERN_ERR "no available usb audio device\n");
goto __error;
}
}
@@ -3671,6 +3688,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
list_for_each(p, &chip->mixer_list) {
snd_usb_mixer_disconnect(p);
}
+ usb_chip[chip->index] = NULL;
mutex_unlock(&register_mutex);
snd_card_free_when_closed(card);
} else {
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 938dff5f9cef..82a8d14c26af 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -39,6 +39,30 @@
.idProduct = prod, \
.bInterfaceClass = USB_CLASS_VENDOR_SPEC
+/* Creative/E-Mu devices */
+{
+ USB_DEVICE(0x041e, 0x3010),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "Creative Labs",
+ .product_name = "Sound Blaster MP3+",
+ .ifnum = QUIRK_NO_INTERFACE
+ }
+},
+{
+ /* E-Mu 0202 USB */
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x041e,
+ .idProduct = 0x3f02,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+},
+{
+ /* E-Mu 0404 USB */
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x041e,
+ .idProduct = 0x3f04,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+},
+
/*
* Logitech QuickCam: bDeviceClass is vendor-specific, so generic interface
* class matches do not take effect without an explicit ID match.
@@ -97,19 +121,7 @@
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
},
-/* E-Mu devices */
-{
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x041e,
- .idProduct = 0x3f02,
- .bInterfaceClass = USB_CLASS_AUDIO,
-},
-{
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
- .idVendor = 0x041e,
- .idProduct = 0x3f04,
- .bInterfaceClass = USB_CLASS_AUDIO,
-},
+
/*
* Yamaha devices
*/
@@ -1165,19 +1177,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
},
-{
- USB_DEVICE(0x582, 0x00a6),
- .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
- .vendor_name = "Roland",
- .product_name = "Juno-G",
- .ifnum = 0,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const struct snd_usb_midi_endpoint_info) {
- .out_cables = 0x0001,
- .in_cables = 0x0001
- }
- }
-},
{ /*
* This quirk is for the "Advanced" modes of the Edirol UA-25.
* If the switch is not in an advanced setting, the UA-25 has
@@ -1336,6 +1335,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
/* TODO: add Edirol MD-P1 support */
{
+ USB_DEVICE(0x582, 0x00a6),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "Roland",
+ .product_name = "Juno-G",
+ .ifnum = 0,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const struct snd_usb_midi_endpoint_info) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
+ }
+ }
+},
+{
/* Roland SH-201 */
USB_DEVICE(0x0582, 0x00ad),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
@@ -1719,17 +1731,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
-{
- /* Creative Sound Blaster MP3+ */
- USB_DEVICE(0x041e, 0x3010),
- .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
- .vendor_name = "Creative Labs",
- .product_name = "Sound Blaster MP3+",
- .ifnum = QUIRK_NO_INTERFACE
- }
-
-},
-
/* Emagic devices */
{
USB_DEVICE(0x086a, 0x0001),