summaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/caiaq/caiaq-device.c22
-rw-r--r--sound/usb/usbaudio.c106
-rw-r--r--sound/usb/usbmidi.c1
-rw-r--r--sound/usb/usbmixer.c164
-rw-r--r--sound/usb/usbmixer_maps.c26
-rw-r--r--sound/usb/usbquirks.h10
-rw-r--r--sound/usb/usx2y/us122l.c59
-rw-r--r--sound/usb/usx2y/usX2Yhwdep.c15
-rw-r--r--sound/usb/usx2y/usb_stream.c2
-rw-r--r--sound/usb/usx2y/usbusx2y.c56
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.h2
11 files changed, 256 insertions, 207 deletions
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
index 771c523b3fc..cf573a982fd 100644
--- a/sound/usb/caiaq/caiaq-device.c
+++ b/sound/usb/caiaq/caiaq-device.c
@@ -356,9 +356,10 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev)
log("Unable to set up control system (ret=%d)\n", ret);
}
-static struct snd_card* create_card(struct usb_device* usb_dev)
+static int create_card(struct usb_device* usb_dev, struct snd_card **cardp)
{
int devnum;
+ int err;
struct snd_card *card;
struct snd_usb_caiaqdev *dev;
@@ -367,12 +368,12 @@ static struct snd_card* create_card(struct usb_device* usb_dev)
break;
if (devnum >= SNDRV_CARDS)
- return NULL;
+ return -ENODEV;
- card = snd_card_new(index[devnum], id[devnum], THIS_MODULE,
- sizeof(struct snd_usb_caiaqdev));
- if (!card)
- return NULL;
+ err = snd_card_create(index[devnum], id[devnum], THIS_MODULE,
+ sizeof(struct snd_usb_caiaqdev), &card);
+ if (err < 0)
+ return err;
dev = caiaqdev(card);
dev->chip.dev = usb_dev;
@@ -382,7 +383,8 @@ static struct snd_card* create_card(struct usb_device* usb_dev)
spin_lock_init(&dev->spinlock);
snd_card_set_dev(card, &usb_dev->dev);
- return card;
+ *cardp = card;
+ return 0;
}
static int __devinit init_card(struct snd_usb_caiaqdev *dev)
@@ -461,10 +463,10 @@ static int __devinit snd_probe(struct usb_interface *intf,
struct snd_card *card;
struct usb_device *device = interface_to_usbdev(intf);
- card = create_card(device);
+ ret = create_card(device, &card);
- if (!card)
- return -ENOMEM;
+ if (ret < 0)
+ return ret;
usb_set_intfdata(intf, card);
ret = init_card(caiaqdev(card));
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index c709b956322..c2db0f95968 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -107,7 +107,7 @@ MODULE_PARM_DESC(ignore_ctl_error,
#define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */
#define MAX_URBS 8
#define SYNC_URBS 4 /* always four urbs for sync */
-#define MIN_PACKS_URB 1 /* minimum 1 packet per urb */
+#define MAX_QUEUE 24 /* try not to exceed this queue length, in ms */
struct audioformat {
struct list_head list;
@@ -525,7 +525,7 @@ static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
/*
* Prepare urb for streaming before playback starts or when paused.
*
- * We don't have any data, so we send a frame of silence.
+ * We don't have any data, so we send silence.
*/
static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
struct snd_pcm_runtime *runtime,
@@ -537,13 +537,13 @@ static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
offs = 0;
urb->dev = ctx->subs->dev;
- urb->number_of_packets = subs->packs_per_ms;
- for (i = 0; i < subs->packs_per_ms; ++i) {
+ for (i = 0; i < ctx->packets; ++i) {
counts = snd_usb_audio_next_packet_size(subs);
urb->iso_frame_desc[i].offset = offs * stride;
urb->iso_frame_desc[i].length = counts * stride;
offs += counts;
}
+ urb->number_of_packets = ctx->packets;
urb->transfer_buffer_length = offs * stride;
memset(urb->transfer_buffer,
subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
@@ -1034,9 +1034,9 @@ static void release_substream_urbs(struct snd_usb_substream *subs, int force)
static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int period_bytes,
unsigned int rate, unsigned int frame_bits)
{
- unsigned int maxsize, n, i;
+ unsigned int maxsize, i;
int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
- unsigned int npacks[MAX_URBS], urb_packs, total_packs, packs_per_ms;
+ unsigned int urb_packs, total_packs, packs_per_ms;
/* calculate the frequency in 16.16 format */
if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
@@ -1070,8 +1070,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
subs->packs_per_ms = packs_per_ms;
if (is_playback) {
- urb_packs = nrpacks;
- urb_packs = max(urb_packs, (unsigned int)MIN_PACKS_URB);
+ urb_packs = max(nrpacks, 1);
urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
} else
urb_packs = 1;
@@ -1079,7 +1078,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
/* decide how many packets to be used */
if (is_playback) {
- unsigned int minsize;
+ unsigned int minsize, maxpacks;
/* determine how small a packet can be */
minsize = (subs->freqn >> (16 - subs->datainterval))
* (frame_bits >> 3);
@@ -1092,8 +1091,13 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
total_packs = (total_packs + packs_per_ms - 1)
& ~(packs_per_ms - 1);
/* we need at least two URBs for queueing */
- if (total_packs < 2 * MIN_PACKS_URB * packs_per_ms)
- total_packs = 2 * MIN_PACKS_URB * packs_per_ms;
+ if (total_packs < 2 * packs_per_ms) {
+ total_packs = 2 * packs_per_ms;
+ } else {
+ /* and we don't want too long a queue either */
+ maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
+ total_packs = min(total_packs, maxpacks);
+ }
} else {
total_packs = MAX_URBS * urb_packs;
}
@@ -1102,31 +1106,11 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
/* too much... */
subs->nurbs = MAX_URBS;
total_packs = MAX_URBS * urb_packs;
- }
- n = total_packs;
- for (i = 0; i < subs->nurbs; i++) {
- npacks[i] = n > urb_packs ? urb_packs : n;
- n -= urb_packs;
- }
- if (subs->nurbs <= 1) {
+ } else if (subs->nurbs < 2) {
/* too little - we need at least two packets
* to ensure contiguous playback/capture
*/
subs->nurbs = 2;
- npacks[0] = (total_packs + 1) / 2;
- npacks[1] = total_packs - npacks[0];
- } else if (npacks[subs->nurbs-1] < MIN_PACKS_URB * packs_per_ms) {
- /* the last packet is too small.. */
- if (subs->nurbs > 2) {
- /* merge to the first one */
- npacks[0] += npacks[subs->nurbs - 1];
- subs->nurbs--;
- } else {
- /* divide to two */
- subs->nurbs = 2;
- npacks[0] = (total_packs + 1) / 2;
- npacks[1] = total_packs - npacks[0];
- }
}
/* allocate and initialize data urbs */
@@ -1134,7 +1118,8 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
struct snd_urb_ctx *u = &subs->dataurb[i];
u->index = i;
u->subs = subs;
- u->packets = npacks[i];
+ u->packets = (i + 1) * total_packs / subs->nurbs
+ - i * total_packs / subs->nurbs;
u->buffer_size = maxsize * u->packets;
if (subs->fmt_type == USB_FORMAT_TYPE_II)
u->packets++; /* for transfer delimiter */
@@ -1292,14 +1277,14 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface,
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n",
+ snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
dev->devnum, iface, fmt->altsetting, rate, ep);
return err;
}
if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR,
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
- snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n",
+ snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
dev->devnum, iface, fmt->altsetting, ep);
return 0; /* some devices don't support reading */
}
@@ -1431,9 +1416,11 @@ 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..%d, channels = %d\n",
+ printk(KERN_DEBUG
+ "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",
+ printk(KERN_DEBUG
+ " datapipe = 0x%0x, syncpipe = 0x%0x\n",
subs->datapipe, subs->syncpipe);
#endif
@@ -1468,7 +1455,7 @@ 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",
+ snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n",
format, rate, channels);
return -EINVAL;
}
@@ -1795,7 +1782,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
if (rates[f->format] && rates[f->format] != f->rates)
goto __out;
}
- channels[f->format] |= (1 << f->channels);
+ channels[f->format] |= 1 << (f->channels - 1);
rates[f->format] |= f->rates;
/* needs knot? */
if (f->rates & SNDRV_PCM_RATE_KNOT)
@@ -1822,7 +1809,7 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
continue;
for (i = 0; i < 32; i++) {
if (f->rates & (1 << i))
- channels[i] |= (1 << f->channels);
+ channels[i] |= 1 << (f->channels - 1);
}
}
cmaster = 0;
@@ -1919,7 +1906,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
* in the current code assume the 1ms period.
*/
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
- 1000 * MIN_PACKS_URB,
+ 1000,
/*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX);
err = check_hw_params_convention(subs);
@@ -2160,7 +2147,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: %#x\n", fp->format);
snd_iprintf(buffer, " Channels: %d\n", fp->channels);
snd_iprintf(buffer, " Endpoint: %d %s (%s)\n",
fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
@@ -2180,7 +2167,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
snd_iprintf(buffer, "\n");
}
// snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize);
- // snd_iprintf(buffer, " EP Attribute = 0x%x\n", fp->attributes);
+ // snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes);
}
}
@@ -2524,7 +2511,6 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
* build the rate table and bitmap flags
*/
int r, idx;
- unsigned int nonzero_rates = 0;
fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
if (fp->rate_table == NULL) {
@@ -2532,24 +2518,27 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
return -1;
}
- fp->nr_rates = nr_rates;
- fp->rate_min = fp->rate_max = combine_triple(&fmt[8]);
+ fp->nr_rates = 0;
+ fp->rate_min = fp->rate_max = 0;
for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) {
unsigned int rate = combine_triple(&fmt[idx]);
+ if (!rate)
+ continue;
/* C-Media CM6501 mislabels its 96 kHz altsetting */
if (rate == 48000 && nr_rates == 1 &&
- chip->usb_id == USB_ID(0x0d8c, 0x0201) &&
+ (chip->usb_id == USB_ID(0x0d8c, 0x0201) ||
+ chip->usb_id == USB_ID(0x0d8c, 0x0102)) &&
fp->altsetting == 5 && fp->maxpacksize == 392)
rate = 96000;
- fp->rate_table[r] = rate;
- nonzero_rates |= rate;
- if (rate < fp->rate_min)
+ fp->rate_table[fp->nr_rates] = rate;
+ if (!fp->rate_min || rate < fp->rate_min)
fp->rate_min = rate;
- else if (rate > fp->rate_max)
+ if (!fp->rate_max || rate > fp->rate_max)
fp->rate_max = rate;
fp->rates |= snd_pcm_rate_to_rate_bit(rate);
+ fp->nr_rates++;
}
- if (!nonzero_rates) {
+ if (!fp->nr_rates) {
hwc_debug("All rates were zero. Skipping format!\n");
return -1;
}
@@ -2619,7 +2608,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, struct audioformat
fp->format = SNDRV_PCM_FORMAT_MPEG;
break;
default:
- snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected. processed as MPEG.\n",
+ snd_printd(KERN_INFO "%d:%u:%d : unknown format tag %#x is detected. processed as MPEG.\n",
chip->dev->devnum, fp->iface, fp->altsetting, format);
fp->format = SNDRV_PCM_FORMAT_MPEG;
break;
@@ -2817,7 +2806,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 %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
err = add_audio_endpoint(chip, stream, fp);
if (err < 0) {
kfree(fp->rate_table);
@@ -2966,6 +2955,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
return -EINVAL;
}
alts = &iface->altsetting[fp->altset_idx];
+ fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
usb_set_interface(chip->dev, fp->iface, 0);
init_usb_pitch(chip->dev, fp->iface, alts, fp);
init_usb_sample_rate(chip->dev, fp->iface, alts, fp, fp->rate_max);
@@ -3463,10 +3453,10 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
return -ENXIO;
}
- card = snd_card_new(index[idx], id[idx], THIS_MODULE, 0);
- if (card == NULL) {
+ err = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card);
+ if (err < 0) {
snd_printk(KERN_ERR "cannot create card instance %d\n", idx);
- return -ENOMEM;
+ return err;
}
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
@@ -3763,7 +3753,7 @@ static int usb_audio_resume(struct usb_interface *intf)
static int __init snd_usb_audio_init(void)
{
- if (nrpacks < MIN_PACKS_URB || nrpacks > MAX_PACKS) {
+ if (nrpacks < 1 || nrpacks > MAX_PACKS) {
printk(KERN_WARNING "invalid nrpacks value.\n");
return -EINVAL;
}
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 320641ab5be..26bad373fe6 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -1625,6 +1625,7 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi,
}
ep_info.out_ep = get_endpoint(hostif, 2)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ ep_info.out_interval = 0;
ep_info.out_cables = endpoint->out_cables & 0x5555;
err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]);
if (err < 0)
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 00397c8a765..ecb58e7a624 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -66,6 +66,7 @@ static const struct rc_config {
{ USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */
{ USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */
{ USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */
+ { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */
};
struct usb_mixer_interface {
@@ -78,7 +79,6 @@ struct usb_mixer_interface {
/* Sound Blaster remote control stuff */
const struct rc_config *rc_cfg;
- unsigned long rc_hwdep_open;
u32 rc_code;
wait_queue_head_t rc_waitq;
struct urb *rc_urb;
@@ -110,6 +110,8 @@ struct mixer_build {
const struct usbmix_selector_map *selector_map;
};
+#define MAX_CHANNELS 10 /* max logical channels */
+
struct usb_mixer_elem_info {
struct usb_mixer_interface *mixer;
struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */
@@ -120,6 +122,8 @@ struct usb_mixer_elem_info {
int channels;
int val_type;
int min, max, res;
+ int cached;
+ int cache_val[MAX_CHANNELS];
u8 initialized;
};
@@ -181,8 +185,6 @@ enum {
USB_PROC_DCR_RELEASE = 6,
};
-#define MAX_CHANNELS 10 /* max logical channels */
-
/*
* manual mapping of mixer names
@@ -219,7 +221,10 @@ static int check_ignored_ctl(struct mixer_build *state, int unitid, int control)
for (p = state->map; p->id; p++) {
if (p->id == unitid && ! p->name &&
(! control || ! p->control || control == p->control)) {
- // printk("ignored control %d:%d\n", unitid, control);
+ /*
+ printk(KERN_DEBUG "ignored control %d:%d\n",
+ unitid, control);
+ */
return 1;
}
}
@@ -376,11 +381,35 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *
}
/* channel = 0: master, 1 = first channel */
-static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value)
+static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval,
+ int channel, int *value)
{
return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value);
}
+static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
+ int channel, int index, int *value)
+{
+ int err;
+
+ if (cval->cached & (1 << channel)) {
+ *value = cval->cache_val[index];
+ return 0;
+ }
+ err = get_cur_mix_raw(cval, channel, value);
+ if (err < 0) {
+ if (!cval->mixer->ignore_ctl_error)
+ snd_printd(KERN_ERR "cannot get current value for "
+ "control %d ch %d: err = %d\n",
+ cval->control, channel, err);
+ return err;
+ }
+ cval->cached |= 1 << channel;
+ cval->cache_val[index] = *value;
+ return 0;
+}
+
+
/*
* set a mixer value
*/
@@ -412,9 +441,17 @@ static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int v
return set_ctl_value(cval, SET_CUR, validx, value);
}
-static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value)
+static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
+ int index, int value)
{
- return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value);
+ int err;
+ err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel,
+ value);
+ if (err < 0)
+ return err;
+ cval->cached |= 1 << channel;
+ cval->cache_val[index] = value;
+ return 0;
}
/*
@@ -718,7 +755,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
if (cval->min + cval->res < cval->max) {
int last_valid_res = cval->res;
int saved, test, check;
- get_cur_mix_value(cval, minchn, &saved);
+ get_cur_mix_raw(cval, minchn, &saved);
for (;;) {
test = saved;
if (test < cval->max)
@@ -726,8 +763,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
else
test -= cval->res;
if (test < cval->min || test > cval->max ||
- set_cur_mix_value(cval, minchn, test) ||
- get_cur_mix_value(cval, minchn, &check)) {
+ set_cur_mix_value(cval, minchn, 0, test) ||
+ get_cur_mix_raw(cval, minchn, &check)) {
cval->res = last_valid_res;
break;
}
@@ -735,7 +772,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
break;
cval->res *= 2;
}
- set_cur_mix_value(cval, minchn, saved);
+ set_cur_mix_value(cval, minchn, 0, saved);
}
cval->initialized = 1;
@@ -775,35 +812,25 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
struct usb_mixer_elem_info *cval = kcontrol->private_data;
int c, cnt, val, err;
+ ucontrol->value.integer.value[0] = cval->min;
if (cval->cmask) {
cnt = 0;
for (c = 0; c < MAX_CHANNELS; c++) {
- if (cval->cmask & (1 << c)) {
- err = get_cur_mix_value(cval, c + 1, &val);
- if (err < 0) {
- if (cval->mixer->ignore_ctl_error) {
- ucontrol->value.integer.value[0] = cval->min;
- return 0;
- }
- snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err);
- return err;
- }
- val = get_relative_value(cval, val);
- ucontrol->value.integer.value[cnt] = val;
- cnt++;
- }
+ if (!(cval->cmask & (1 << c)))
+ continue;
+ err = get_cur_mix_value(cval, c + 1, cnt, &val);
+ if (err < 0)
+ return cval->mixer->ignore_ctl_error ? 0 : err;
+ val = get_relative_value(cval, val);
+ ucontrol->value.integer.value[cnt] = val;
+ cnt++;
}
+ return 0;
} else {
/* master channel */
- err = get_cur_mix_value(cval, 0, &val);
- if (err < 0) {
- if (cval->mixer->ignore_ctl_error) {
- ucontrol->value.integer.value[0] = cval->min;
- return 0;
- }
- snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err);
- return err;
- }
+ err = get_cur_mix_value(cval, 0, 0, &val);
+ if (err < 0)
+ return cval->mixer->ignore_ctl_error ? 0 : err;
val = get_relative_value(cval, val);
ucontrol->value.integer.value[0] = val;
}
@@ -820,34 +847,28 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
if (cval->cmask) {
cnt = 0;
for (c = 0; c < MAX_CHANNELS; c++) {
- if (cval->cmask & (1 << c)) {
- err = get_cur_mix_value(cval, c + 1, &oval);
- if (err < 0) {
- if (cval->mixer->ignore_ctl_error)
- return 0;
- return err;
- }
- val = ucontrol->value.integer.value[cnt];
- val = get_abs_value(cval, val);
- if (oval != val) {
- set_cur_mix_value(cval, c + 1, val);
- changed = 1;
- }
- get_cur_mix_value(cval, c + 1, &val);
- cnt++;
+ if (!(cval->cmask & (1 << c)))
+ continue;
+ err = get_cur_mix_value(cval, c + 1, cnt, &oval);
+ if (err < 0)
+ return cval->mixer->ignore_ctl_error ? 0 : err;
+ val = ucontrol->value.integer.value[cnt];
+ val = get_abs_value(cval, val);
+ if (oval != val) {
+ set_cur_mix_value(cval, c + 1, cnt, val);
+ changed = 1;
}
+ cnt++;
}
} else {
/* master channel */
- err = get_cur_mix_value(cval, 0, &oval);
- if (err < 0 && cval->mixer->ignore_ctl_error)
- return 0;
+ err = get_cur_mix_value(cval, 0, 0, &oval);
if (err < 0)
- return err;
+ return cval->mixer->ignore_ctl_error ? 0 : err;
val = ucontrol->value.integer.value[0];
val = get_abs_value(cval, val);
if (val != oval) {
- set_cur_mix_value(cval, 0, val);
+ set_cur_mix_value(cval, 0, 0, val);
changed = 1;
}
}
@@ -1706,7 +1727,8 @@ static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
break;
/* live24ext: 4 = line-in jack */
case 3: /* hp-out jack (may actuate Mute) */
- if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
+ if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
+ mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id);
break;
default:
@@ -1797,24 +1819,6 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb)
wake_up(&mixer->rc_waitq);
}
-static int snd_usb_sbrc_hwdep_open(struct snd_hwdep *hw, struct file *file)
-{
- struct usb_mixer_interface *mixer = hw->private_data;
-
- if (test_and_set_bit(0, &mixer->rc_hwdep_open))
- return -EBUSY;
- return 0;
-}
-
-static int snd_usb_sbrc_hwdep_release(struct snd_hwdep *hw, struct file *file)
-{
- struct usb_mixer_interface *mixer = hw->private_data;
-
- clear_bit(0, &mixer->rc_hwdep_open);
- smp_mb__after_clear_bit();
- return 0;
-}
-
static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf,
long count, loff_t *offset)
{
@@ -1867,9 +1871,8 @@ static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC;
hwdep->private_data = mixer;
hwdep->ops.read = snd_usb_sbrc_hwdep_read;
- hwdep->ops.open = snd_usb_sbrc_hwdep_open;
- hwdep->ops.release = snd_usb_sbrc_hwdep_release;
hwdep->ops.poll = snd_usb_sbrc_hwdep_poll;
+ hwdep->exclusive = 1;
mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!mixer->rc_urb)
@@ -1956,8 +1959,9 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
int i, err;
for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
- if (i > 1 && /* Live24ext has 2 LEDs only */
- mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
+ if (i > 1 && /* Live24ext has 2 LEDs only */
+ (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
+ mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
break;
err = snd_ctl_add(mixer->chip->card,
snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
@@ -1994,7 +1998,8 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020))
jacks = jacks_audigy2nx;
- else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
+ else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
+ mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
jacks = jacks_live24ext;
else
return;
@@ -2044,7 +2049,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
goto _error;
if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) ||
- mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) {
+ mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
+ mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) {
struct snd_info_entry *entry;
if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c
index d755be0ad81..3e5d66cf1f5 100644
--- a/sound/usb/usbmixer_maps.c
+++ b/sound/usb/usbmixer_maps.c
@@ -261,6 +261,22 @@ static struct usbmix_name_map aureon_51_2_map[] = {
{} /* terminator */
};
+static struct usbmix_name_map scratch_live_map[] = {
+ /* 1: IT Line 1 (USB streaming) */
+ /* 2: OT Line 1 (Speaker) */
+ /* 3: IT Line 1 (Line connector) */
+ { 4, "Line 1 In" }, /* FU */
+ /* 5: OT Line 1 (USB streaming) */
+ /* 6: IT Line 2 (USB streaming) */
+ /* 7: OT Line 2 (Speaker) */
+ /* 8: IT Line 2 (Line connector) */
+ { 9, "Line 2 In" }, /* FU */
+ /* 10: OT Line 2 (USB streaming) */
+ /* 11: IT Mic (Line connector) */
+ /* 12: OT Mic (USB streaming) */
+ { 0 } /* terminator */
+};
+
/*
* Control map entries
*/
@@ -285,6 +301,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
.map = live24ext_map,
},
{
+ .id = USB_ID(0x041e, 0x3048),
+ .map = audigy2nx_map,
+ .selector_map = audigy2nx_selectors,
+ },
+ {
/* Hercules DJ Console (Windows Edition) */
.id = USB_ID(0x06f8, 0xb000),
.ignore_ctl_error = 1,
@@ -311,6 +332,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
.id = USB_ID(0x0ccd, 0x0028),
.map = aureon_51_2_map,
},
+ {
+ .id = USB_ID(0x13e5, 0x0001),
+ .map = scratch_live_map,
+ .ignore_ctl_error = 1,
+ },
{ 0 } /* terminator */
};
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 5d8ef09b9dc..647ef502965 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -39,6 +39,16 @@
.idProduct = prod, \
.bInterfaceClass = USB_CLASS_VENDOR_SPEC
+/* Creative/Toshiba Multimedia Center SB-0500 */
+{
+ USB_DEVICE(0x041e, 0x3048),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "Toshiba",
+ .product_name = "SB-0500",
+ .ifnum = QUIRK_NO_INTERFACE
+ }
+},
+
/* Creative/E-Mu devices */
{
USB_DEVICE(0x041e, 0x3010),
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index 73e59f4403a..98276aafefe 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -478,19 +478,21 @@ static bool us122l_create_card(struct snd_card *card)
return true;
}
-static struct snd_card *usx2y_create_card(struct usb_device *device)
+static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp)
{
int dev;
struct snd_card *card;
+ int err;
+
for (dev = 0; dev < SNDRV_CARDS; ++dev)
if (enable[dev] && !snd_us122l_card_used[dev])
break;
if (dev >= SNDRV_CARDS)
- return NULL;
- card = snd_card_new(index[dev], id[dev], THIS_MODULE,
- sizeof(struct us122l));
- if (!card)
- return NULL;
+ return -ENODEV;
+ err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+ sizeof(struct us122l), &card);
+ if (err < 0)
+ return err;
snd_us122l_card_used[US122L(card)->chip.index = dev] = 1;
US122L(card)->chip.dev = device;
@@ -509,46 +511,57 @@ static struct snd_card *usx2y_create_card(struct usb_device *device)
US122L(card)->chip.dev->devnum
);
snd_card_set_dev(card, &device->dev);
- return card;
+ *cardp = card;
+ return 0;
}
-static void *us122l_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *device_id)
+static int us122l_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *device_id,
+ struct snd_card **cardp)
{
struct usb_device *device = interface_to_usbdev(intf);
- struct snd_card *card = usx2y_create_card(device);
+ struct snd_card *card;
+ int err;
- if (!card)
- return NULL;
+ err = usx2y_create_card(device, &card);
+ if (err < 0)
+ return err;
- if (!us122l_create_card(card) ||
- snd_card_register(card) < 0) {
+ if (!us122l_create_card(card)) {
snd_card_free(card);
- return NULL;
+ return -EINVAL;
+ }
+
+ err = snd_card_register(card);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
}
usb_get_dev(device);
- return card;
+ *cardp = card;
+ return 0;
}
static int snd_us122l_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct snd_card *card;
+ int err;
+
snd_printdd(KERN_DEBUG"%p:%i\n",
intf, intf->cur_altsetting->desc.bInterfaceNumber);
if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
return 0;
- card = us122l_usb_probe(usb_get_intf(intf), id);
-
- if (card) {
- usb_set_intfdata(intf, card);
- return 0;
+ err = us122l_usb_probe(usb_get_intf(intf), id, &card);
+ if (err < 0) {
+ usb_put_intf(intf);
+ return err;
}
- usb_put_intf(intf);
- return -EIO;
+ usb_set_intfdata(intf, card);
+ return 0;
}
static void snd_us122l_disconnect(struct usb_interface *intf)
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
index 1558a5c4094..4af8740db71 100644
--- a/sound/usb/usx2y/usX2Yhwdep.c
+++ b/sound/usb/usx2y/usX2Yhwdep.c
@@ -30,9 +30,6 @@
#include "usbusx2y.h"
#include "usX2Yhwdep.h"
-int usX2Y_hwdep_pcm_new(struct snd_card *card);
-
-
static int snd_us428ctls_vm_fault(struct vm_area_struct *area,
struct vm_fault *vmf)
{
@@ -106,16 +103,6 @@ static unsigned int snd_us428ctls_poll(struct snd_hwdep *hw, struct file *file,
}
-static int snd_usX2Y_hwdep_open(struct snd_hwdep *hw, struct file *file)
-{
- return 0;
-}
-
-static int snd_usX2Y_hwdep_release(struct snd_hwdep *hw, struct file *file)
-{
- return 0;
-}
-
static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw,
struct snd_hwdep_dsp_status *info)
{
@@ -267,8 +254,6 @@ int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device)
hw->iface = SNDRV_HWDEP_IFACE_USX2Y;
hw->private_data = usX2Y(card);
- hw->ops.open = snd_usX2Y_hwdep_open;
- hw->ops.release = snd_usX2Y_hwdep_release;
hw->ops.dsp_status = snd_usX2Y_hwdep_dsp_status;
hw->ops.dsp_load = snd_usX2Y_hwdep_dsp_load;
hw->ops.mmap = snd_us428ctls_mmap;
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c
index 70b96355ca4..24393dafcb6 100644
--- a/sound/usb/usx2y/usb_stream.c
+++ b/sound/usb/usx2y/usb_stream.c
@@ -557,7 +557,7 @@ static void stream_start(struct usb_stream_kernel *sk,
s->idle_insize -= max_diff - max_diff_0;
s->idle_insize += urb_size - s->period_size;
if (s->idle_insize < 0) {
- snd_printk("%i %i %i\n",
+ snd_printk(KERN_WARNING "%i %i %i\n",
s->idle_insize, urb_size, s->period_size);
return;
} else if (s->idle_insize == 0) {
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index 11639bd72a5..5ce0da23ee9 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -227,9 +227,9 @@ static void i_usX2Y_In04Int(struct urb *urb)
if (usX2Y->US04) {
if (0 == usX2Y->US04->submitted)
- do
+ do {
err = usb_submit_urb(usX2Y->US04->urb[usX2Y->US04->submitted++], GFP_ATOMIC);
- while (!err && usX2Y->US04->submitted < usX2Y->US04->len);
+ } while (!err && usX2Y->US04->submitted < usX2Y->US04->len);
} else
if (us428ctls && us428ctls->p4outLast >= 0 && us428ctls->p4outLast < N_us428_p4out_BUFS) {
if (us428ctls->p4outLast != us428ctls->p4outSent) {
@@ -333,18 +333,21 @@ static struct usb_device_id snd_usX2Y_usb_id_table[] = {
{ /* terminator */ }
};
-static struct snd_card *usX2Y_create_card(struct usb_device *device)
+static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp)
{
int dev;
struct snd_card * card;
+ int err;
+
for (dev = 0; dev < SNDRV_CARDS; ++dev)
if (enable[dev] && !snd_usX2Y_card_used[dev])
break;
if (dev >= SNDRV_CARDS)
- return NULL;
- card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct usX2Ydev));
- if (!card)
- return NULL;
+ return -ENODEV;
+ err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+ sizeof(struct usX2Ydev), &card);
+ if (err < 0)
+ return err;
snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1;
card->private_free = snd_usX2Y_card_private_free;
usX2Y(card)->chip.dev = device;
@@ -362,26 +365,36 @@ static struct snd_card *usX2Y_create_card(struct usb_device *device)
usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum
);
snd_card_set_dev(card, &device->dev);
- return card;
+ *cardp = card;
+ return 0;
}
-static void *usX2Y_usb_probe(struct usb_device *device, struct usb_interface *intf, const struct usb_device_id *device_id)
+static int usX2Y_usb_probe(struct usb_device *device,
+ struct usb_interface *intf,
+ const struct usb_device_id *device_id,
+ struct snd_card **cardp)
{
int err;
struct snd_card * card;
+
+ *cardp = NULL;
if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 ||
(le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 &&
le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 &&
- le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428) ||
- !(card = usX2Y_create_card(device)))
- return NULL;
+ le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428))
+ return -EINVAL;
+
+ err = usX2Y_create_card(device, &card);
+ if (err < 0)
+ return err;
if ((err = usX2Y_hwdep_new(card, device)) < 0 ||
(err = snd_card_register(card)) < 0) {
snd_card_free(card);
- return NULL;
+ return err;
}
- return card;
+ *cardp = card;
+ return 0;
}
/*
@@ -389,13 +402,14 @@ static void *usX2Y_usb_probe(struct usb_device *device, struct usb_interface *in
*/
static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
- void *chip;
- chip = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id);
- if (chip) {
- usb_set_intfdata(intf, chip);
- return 0;
- } else
- return -EIO;
+ struct snd_card *card;
+ int err;
+
+ err = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id, &card);
+ if (err < 0)
+ return err;
+ dev_set_drvdata(&intf->dev, card);
+ return 0;
}
static void snd_usX2Y_disconnect(struct usb_interface *intf)
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.h b/sound/usb/usx2y/usx2yhwdeppcm.h
index c3382fdc386..9c4fb84b2aa 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.h
+++ b/sound/usb/usx2y/usx2yhwdeppcm.h
@@ -18,3 +18,5 @@ struct snd_usX2Y_hwdep_pcm_shm {
volatile unsigned captured_iso_frames;
int capture_iso_start;
};
+
+int usX2Y_hwdep_pcm_new(struct snd_card *card);