aboutsummaryrefslogtreecommitdiff
path: root/sound/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/6fire/chip.c15
-rw-r--r--sound/usb/6fire/comm.c4
-rw-r--r--sound/usb/6fire/control.c18
-rw-r--r--sound/usb/6fire/firmware.c70
-rw-r--r--sound/usb/6fire/midi.c12
-rw-r--r--sound/usb/6fire/pcm.c46
-rw-r--r--sound/usb/Kconfig14
-rw-r--r--sound/usb/Makefile2
-rw-r--r--sound/usb/bcd2000/Makefile3
-rw-r--r--sound/usb/bcd2000/bcd2000.c461
-rw-r--r--sound/usb/caiaq/control.c92
-rw-r--r--sound/usb/caiaq/device.c31
-rw-r--r--sound/usb/caiaq/device.h5
-rw-r--r--sound/usb/card.c114
-rw-r--r--sound/usb/card.h13
-rw-r--r--sound/usb/clock.c65
-rw-r--r--sound/usb/endpoint.c215
-rw-r--r--sound/usb/endpoint.h5
-rw-r--r--sound/usb/format.c74
-rw-r--r--sound/usb/helper.c1
-rw-r--r--sound/usb/hiface/chip.c10
-rw-r--r--sound/usb/hiface/pcm.c6
-rw-r--r--sound/usb/midi.c45
-rw-r--r--sound/usb/misc/ua101.c7
-rw-r--r--sound/usb/mixer.c623
-rw-r--r--sound/usb/mixer.h7
-rw-r--r--sound/usb/mixer_maps.c19
-rw-r--r--sound/usb/mixer_quirks.c102
-rw-r--r--sound/usb/pcm.c123
-rw-r--r--sound/usb/quirks-table.h176
-rw-r--r--sound/usb/quirks.c75
-rw-r--r--sound/usb/stream.c83
-rw-r--r--sound/usb/usbaudio.h11
-rw-r--r--sound/usb/usx2y/us122l.c15
-rw-r--r--sound/usb/usx2y/usbusx2y.c13
-rw-r--r--sound/usb/usx2y/usbusx2y.h2
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c82
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c83
38 files changed, 1885 insertions, 857 deletions
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
index c39c7797846..dcddfc354ba 100644
--- a/sound/usb/6fire/chip.c
+++ b/sound/usb/6fire/chip.c
@@ -101,12 +101,12 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
usb_set_intfdata(intf, chips[i]);
mutex_unlock(&register_mutex);
return 0;
- } else if (regidx < 0)
+ } else if (!devices[i] && regidx < 0)
regidx = i;
}
if (regidx < 0) {
mutex_unlock(&register_mutex);
- snd_printk(KERN_ERR PREFIX "too many cards registered.\n");
+ dev_err(&intf->dev, "too many cards registered.\n");
return -ENODEV;
}
devices[regidx] = device;
@@ -121,20 +121,19 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
/* if we are here, card can be registered in alsa. */
if (usb_set_interface(device, 0, 0) != 0) {
- snd_printk(KERN_ERR PREFIX "can't set first interface.\n");
+ dev_err(&intf->dev, "can't set first interface.\n");
return -EIO;
}
- ret = snd_card_create(index[regidx], id[regidx], THIS_MODULE,
- sizeof(struct sfire_chip), &card);
+ ret = snd_card_new(&intf->dev, index[regidx], id[regidx],
+ THIS_MODULE, sizeof(struct sfire_chip), &card);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "cannot create alsa card.\n");
+ dev_err(&intf->dev, "cannot create alsa card.\n");
return ret;
}
strcpy(card->driver, "6FireUSB");
strcpy(card->shortname, "TerraTec DMX6FireUSB");
sprintf(card->longname, "%s at %d:%d", card->shortname,
device->bus->busnum, device->devnum);
- snd_card_set_dev(card, &intf->dev);
chip = card->private_data;
chips[regidx] = chip;
@@ -169,7 +168,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
ret = snd_card_register(card);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "cannot register card.");
+ dev_err(&intf->dev, "cannot register card.");
usb6fire_chip_destroy(chip);
return ret;
}
diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c
index 23452ee617e..161215d78d9 100644
--- a/sound/usb/6fire/comm.c
+++ b/sound/usb/6fire/comm.c
@@ -51,7 +51,7 @@ static void usb6fire_comm_receiver_handler(struct urb *urb)
urb->status = 0;
urb->actual_length = 0;
if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
- snd_printk(KERN_WARNING PREFIX
+ dev_warn(&urb->dev->dev,
"comm data receiver aborted.\n");
}
}
@@ -179,7 +179,7 @@ int usb6fire_comm_init(struct sfire_chip *chip)
if (ret < 0) {
kfree(rt->receiver_buffer);
kfree(rt);
- snd_printk(KERN_ERR PREFIX "cannot create comm data receiver.");
+ dev_err(&chip->dev->dev, "cannot create comm data receiver.");
return ret;
}
chip->comm = rt;
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c
index f6434c24572..184e3987ac2 100644
--- a/sound/usb/6fire/control.c
+++ b/sound/usb/6fire/control.c
@@ -194,7 +194,8 @@ static int usb6fire_control_output_vol_put(struct snd_kcontrol *kcontrol,
int changed = 0;
if (ch > 4) {
- snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+ dev_err(&rt->chip->dev->dev,
+ "Invalid channel in volume control.");
return -EINVAL;
}
@@ -222,7 +223,8 @@ static int usb6fire_control_output_vol_get(struct snd_kcontrol *kcontrol,
unsigned int ch = kcontrol->private_value;
if (ch > 4) {
- snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+ dev_err(&rt->chip->dev->dev,
+ "Invalid channel in volume control.");
return -EINVAL;
}
@@ -240,7 +242,8 @@ static int usb6fire_control_output_mute_put(struct snd_kcontrol *kcontrol,
u8 value = 0;
if (ch > 4) {
- snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+ dev_err(&rt->chip->dev->dev,
+ "Invalid channel in volume control.");
return -EINVAL;
}
@@ -265,7 +268,8 @@ static int usb6fire_control_output_mute_get(struct snd_kcontrol *kcontrol,
u8 value = rt->output_mute >> ch;
if (ch > 4) {
- snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+ dev_err(&rt->chip->dev->dev,
+ "Invalid channel in volume control.");
return -EINVAL;
}
@@ -594,14 +598,14 @@ int usb6fire_control_init(struct sfire_chip *chip)
ret = usb6fire_control_add_virtual(rt, chip->card,
"Master Playback Volume", vol_elements);
if (ret) {
- snd_printk(KERN_ERR PREFIX "cannot add control.\n");
+ dev_err(&chip->dev->dev, "cannot add control.\n");
kfree(rt);
return ret;
}
ret = usb6fire_control_add_virtual(rt, chip->card,
"Master Playback Switch", mute_elements);
if (ret) {
- snd_printk(KERN_ERR PREFIX "cannot add control.\n");
+ dev_err(&chip->dev->dev, "cannot add control.\n");
kfree(rt);
return ret;
}
@@ -611,7 +615,7 @@ int usb6fire_control_init(struct sfire_chip *chip)
ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt));
if (ret < 0) {
kfree(rt);
- snd_printk(KERN_ERR PREFIX "cannot add control.\n");
+ dev_err(&chip->dev->dev, "cannot add control.\n");
return ret;
}
i++;
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c
index 780bf3f62d2..3b02e54b8f6 100644
--- a/sound/usb/6fire/firmware.c
+++ b/sound/usb/6fire/firmware.c
@@ -219,16 +219,16 @@ static int usb6fire_fw_ezusb_upload(
ret = request_firmware(&fw, fwname, &device->dev);
if (ret < 0) {
kfree(rec);
- snd_printk(KERN_ERR PREFIX "error requesting ezusb "
- "firmware %s.\n", fwname);
+ dev_err(&intf->dev,
+ "error requesting ezusb firmware %s.\n", fwname);
return ret;
}
ret = usb6fire_fw_ihex_init(fw, rec);
if (ret < 0) {
kfree(rec);
release_firmware(fw);
- snd_printk(KERN_ERR PREFIX "error validating ezusb "
- "firmware %s.\n", fwname);
+ dev_err(&intf->dev,
+ "error validating ezusb firmware %s.\n", fwname);
return ret;
}
/* upload firmware image */
@@ -237,8 +237,9 @@ static int usb6fire_fw_ezusb_upload(
if (ret < 0) {
kfree(rec);
release_firmware(fw);
- snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
- "firmware %s: begin message.\n", fwname);
+ dev_err(&intf->dev,
+ "unable to upload ezusb firmware %s: begin message.\n",
+ fwname);
return ret;
}
@@ -248,8 +249,9 @@ static int usb6fire_fw_ezusb_upload(
if (ret < 0) {
kfree(rec);
release_firmware(fw);
- snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
- "firmware %s: data urb.\n", fwname);
+ dev_err(&intf->dev,
+ "unable to upload ezusb firmware %s: data urb.\n",
+ fwname);
return ret;
}
}
@@ -260,8 +262,9 @@ static int usb6fire_fw_ezusb_upload(
ret = usb6fire_fw_ezusb_write(device, 0xa0, postaddr,
postdata, postlen);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
- "firmware %s: post urb.\n", fwname);
+ dev_err(&intf->dev,
+ "unable to upload ezusb firmware %s: post urb.\n",
+ fwname);
return ret;
}
}
@@ -269,8 +272,9 @@ static int usb6fire_fw_ezusb_upload(
data = 0x00; /* resume ezusb cpu */
ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
- "firmware %s: end message.\n", fwname);
+ dev_err(&intf->dev,
+ "unable to upload ezusb firmware %s: end message.\n",
+ fwname);
return ret;
}
return 0;
@@ -292,7 +296,7 @@ static int usb6fire_fw_fpga_upload(
ret = request_firmware(&fw, fwname, &device->dev);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "unable to get fpga firmware %s.\n",
+ dev_err(&intf->dev, "unable to get fpga firmware %s.\n",
fwname);
kfree(buffer);
return -EIO;
@@ -305,8 +309,8 @@ static int usb6fire_fw_fpga_upload(
if (ret < 0) {
kfree(buffer);
release_firmware(fw);
- snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: "
- "begin urb.\n");
+ dev_err(&intf->dev,
+ "unable to upload fpga firmware: begin urb.\n");
return ret;
}
@@ -318,8 +322,8 @@ static int usb6fire_fw_fpga_upload(
if (ret < 0) {
release_firmware(fw);
kfree(buffer);
- snd_printk(KERN_ERR PREFIX "unable to upload fpga "
- "firmware: fw urb.\n");
+ dev_err(&intf->dev,
+ "unable to upload fpga firmware: fw urb.\n");
return ret;
}
}
@@ -328,8 +332,8 @@ static int usb6fire_fw_fpga_upload(
ret = usb6fire_fw_ezusb_write(device, 9, 0, NULL, 0);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: "
- "end urb.\n");
+ dev_err(&intf->dev,
+ "unable to upload fpga firmware: end urb.\n");
return ret;
}
return 0;
@@ -338,7 +342,7 @@ static int usb6fire_fw_fpga_upload(
/* check, if the firmware version the devices has currently loaded
* is known by this driver. 'version' needs to have 4 bytes version
* info data. */
-static int usb6fire_fw_check(u8 *version)
+static int usb6fire_fw_check(struct usb_interface *intf, const u8 *version)
{
int i;
@@ -346,7 +350,7 @@ static int usb6fire_fw_check(u8 *version)
if (!memcmp(version, known_fw_versions + i, 2))
return 0;
- snd_printk(KERN_ERR PREFIX "invalid fimware version in device: %4ph. "
+ dev_err(&intf->dev, "invalid fimware version in device: %4ph. "
"please reconnect to power. if this failure "
"still happens, check your firmware installation.",
version);
@@ -364,16 +368,16 @@ int usb6fire_fw_init(struct usb_interface *intf)
ret = usb6fire_fw_ezusb_read(device, 1, 0, buffer, 8);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "unable to receive device "
- "firmware state.\n");
+ dev_err(&intf->dev,
+ "unable to receive device firmware state.\n");
return ret;
}
if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55) {
- snd_printk(KERN_ERR PREFIX "unknown device firmware state "
- "received from device: ");
+ dev_err(&intf->dev,
+ "unknown device firmware state received from device:");
for (i = 0; i < 8; i++)
- snd_printk("%02x ", buffer[i]);
- snd_printk("\n");
+ printk(KERN_CONT "%02x ", buffer[i]);
+ printk(KERN_CONT "\n");
return -EIO;
}
/* do we need fpga loader ezusb firmware? */
@@ -386,7 +390,7 @@ int usb6fire_fw_init(struct usb_interface *intf)
}
/* do we need fpga firmware and application ezusb firmware? */
else if (buffer[3] == 0x02) {
- ret = usb6fire_fw_check(buffer + 4);
+ ret = usb6fire_fw_check(intf, buffer + 4);
if (ret < 0)
return ret;
ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin");
@@ -402,14 +406,14 @@ int usb6fire_fw_init(struct usb_interface *intf)
}
/* all fw loaded? */
else if (buffer[3] == 0x03)
- return usb6fire_fw_check(buffer + 4);
+ return usb6fire_fw_check(intf, buffer + 4);
/* unknown data? */
else {
- snd_printk(KERN_ERR PREFIX "unknown device firmware state "
- "received from device: ");
+ dev_err(&intf->dev,
+ "unknown device firmware state received from device: ");
for (i = 0; i < 8; i++)
- snd_printk("%02x ", buffer[i]);
- snd_printk("\n");
+ printk(KERN_CONT "%02x ", buffer[i]);
+ printk(KERN_CONT "\n");
return -EIO;
}
return 0;
diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c
index f3dd7266c39..3d410969553 100644
--- a/sound/usb/6fire/midi.c
+++ b/sound/usb/6fire/midi.c
@@ -41,8 +41,9 @@ static void usb6fire_midi_out_handler(struct urb *urb)
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret < 0)
- snd_printk(KERN_ERR PREFIX "midi out urb "
- "submit failed: %d\n", ret);
+ dev_err(&urb->dev->dev,
+ "midi out urb submit failed: %d\n",
+ ret);
} else /* no more data to transmit */
rt->out = NULL;
}
@@ -94,8 +95,9 @@ static void usb6fire_midi_out_trigger(
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret < 0)
- snd_printk(KERN_ERR PREFIX "midi out urb "
- "submit failed: %d\n", ret);
+ dev_err(&urb->dev->dev,
+ "midi out urb submit failed: %d\n",
+ ret);
else
rt->out = alsa_sub;
}
@@ -181,7 +183,7 @@ int usb6fire_midi_init(struct sfire_chip *chip)
if (ret < 0) {
kfree(rt->out_buffer);
kfree(rt);
- snd_printk(KERN_ERR PREFIX "unable to create midi.\n");
+ dev_err(&chip->dev->dev, "unable to create midi.\n");
return ret;
}
rt->instance->private_data = rt;
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c
index b5eb97fdc84..ba40489b2de 100644
--- a/sound/usb/6fire/pcm.c
+++ b/sound/usb/6fire/pcm.c
@@ -79,32 +79,35 @@ static int usb6fire_pcm_set_rate(struct pcm_runtime *rt)
ctrl_rt->usb_streaming = false;
ret = ctrl_rt->update_streaming(ctrl_rt);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "error stopping streaming while "
- "setting samplerate %d.\n", rates[rt->rate]);
+ dev_err(&rt->chip->dev->dev,
+ "error stopping streaming while setting samplerate %d.\n",
+ rates[rt->rate]);
return ret;
}
ret = ctrl_rt->set_rate(ctrl_rt, rt->rate);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n",
- rates[rt->rate]);
+ dev_err(&rt->chip->dev->dev,
+ "error setting samplerate %d.\n",
+ rates[rt->rate]);
return ret;
}
ret = ctrl_rt->set_channels(ctrl_rt, OUT_N_CHANNELS, IN_N_CHANNELS,
false, false);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "error initializing channels "
- "while setting samplerate %d.\n",
- rates[rt->rate]);
+ dev_err(&rt->chip->dev->dev,
+ "error initializing channels while setting samplerate %d.\n",
+ rates[rt->rate]);
return ret;
}
ctrl_rt->usb_streaming = true;
ret = ctrl_rt->update_streaming(ctrl_rt);
if (ret < 0) {
- snd_printk(KERN_ERR PREFIX "error starting streaming while "
- "setting samplerate %d.\n", rates[rt->rate]);
+ dev_err(&rt->chip->dev->dev,
+ "error starting streaming while setting samplerate %d.\n",
+ rates[rt->rate]);
return ret;
}
@@ -124,7 +127,7 @@ static struct pcm_substream *usb6fire_pcm_get_substream(
return &rt->playback;
else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE)
return &rt->capture;
- snd_printk(KERN_ERR PREFIX "error getting pcm substream slot.\n");
+ dev_err(&rt->chip->dev->dev, "error getting pcm substream slot.\n");
return NULL;
}
@@ -257,7 +260,7 @@ static void usb6fire_pcm_playback(struct pcm_substream *sub,
else if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE)
dest = (u32 *) (urb->buffer);
else {
- snd_printk(KERN_ERR PREFIX "Unknown sample format.");
+ dev_err(&rt->chip->dev->dev, "Unknown sample format.");
return;
}
@@ -307,8 +310,8 @@ static void usb6fire_pcm_in_urb_handler(struct urb *usb_urb)
}
if (rt->stream_state == STREAM_DISABLED) {
- snd_printk(KERN_ERR PREFIX "internal error: "
- "stream disabled in in-urb handler.\n");
+ dev_err(&rt->chip->dev->dev,
+ "internal error: stream disabled in in-urb handler.\n");
return;
}
@@ -410,7 +413,7 @@ static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub)
if (!sub) {
mutex_unlock(&rt->stream_mutex);
- snd_printk(KERN_ERR PREFIX "invalid stream type.\n");
+ dev_err(&rt->chip->dev->dev, "invalid stream type.\n");
return -EINVAL;
}
@@ -481,8 +484,9 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
break;
if (rt->rate == ARRAY_SIZE(rates)) {
mutex_unlock(&rt->stream_mutex);
- snd_printk("invalid rate %d in prepare.\n",
- alsa_rt->rate);
+ dev_err(&rt->chip->dev->dev,
+ "invalid rate %d in prepare.\n",
+ alsa_rt->rate);
return -EINVAL;
}
@@ -494,8 +498,8 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
ret = usb6fire_pcm_stream_start(rt);
if (ret) {
mutex_unlock(&rt->stream_mutex);
- snd_printk(KERN_ERR PREFIX
- "could not start pcm stream.\n");
+ dev_err(&rt->chip->dev->dev,
+ "could not start pcm stream.\n");
return ret;
}
}
@@ -650,7 +654,7 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
if (ret < 0) {
usb6fire_pcm_buffers_destroy(rt);
kfree(rt);
- snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n");
+ dev_err(&chip->dev->dev, "cannot create pcm instance.\n");
return ret;
}
@@ -662,8 +666,8 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
if (ret) {
usb6fire_pcm_buffers_destroy(rt);
kfree(rt);
- snd_printk(KERN_ERR PREFIX
- "error preallocating pcm buffers.\n");
+ dev_err(&chip->dev->dev,
+ "error preallocating pcm buffers.\n");
return ret;
}
rt->instance = pcm;
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index de9408b83f7..d393153c474 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -14,6 +14,7 @@ config SND_USB_AUDIO
select SND_HWDEP
select SND_RAWMIDI
select SND_PCM
+ select BITREVERSE
help
Say Y here to include support for USB audio and USB MIDI
devices.
@@ -146,5 +147,18 @@ config SND_USB_HIFACE
To compile this driver as a module, choose M here: the module
will be called snd-usb-hiface.
+config SND_BCD2000
+ tristate "Behringer BCD2000 MIDI driver"
+ select SND_RAWMIDI
+ help
+ Say Y here to include MIDI support for the Behringer BCD2000 DJ
+ controller.
+
+ Audio support is still work-in-progress at
+ https://github.com/anyc/snd-usb-bcd2000
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-bcd2000.
+
endif # SND_USB
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index abe668f660d..2b92f0dcbc4 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -23,4 +23,4 @@ obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o
obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o
obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o
-obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/
+obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/
diff --git a/sound/usb/bcd2000/Makefile b/sound/usb/bcd2000/Makefile
new file mode 100644
index 00000000000..f09ccc0af6f
--- /dev/null
+++ b/sound/usb/bcd2000/Makefile
@@ -0,0 +1,3 @@
+snd-bcd2000-y := bcd2000.o
+
+obj-$(CONFIG_SND_BCD2000) += snd-bcd2000.o \ No newline at end of file
diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c
new file mode 100644
index 00000000000..820d6ca8c45
--- /dev/null
+++ b/sound/usb/bcd2000/bcd2000.c
@@ -0,0 +1,461 @@
+/*
+ * Behringer BCD2000 driver
+ *
+ * Copyright (C) 2014 Mario Kicherer (dev@kicherer.org)
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/bitmap.h>
+#include <linux/usb.h>
+#include <linux/usb/audio.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+
+#define PREFIX "snd-bcd2000: "
+#define BUFSIZE 64
+
+static struct usb_device_id id_table[] = {
+ { USB_DEVICE(0x1397, 0x00bd) },
+ { },
+};
+
+static unsigned char device_cmd_prefix[] = {0x03, 0x00};
+
+static unsigned char bcd2000_init_sequence[] = {
+ 0x07, 0x00, 0x00, 0x00, 0x78, 0x48, 0x1c, 0x81,
+ 0xc4, 0x00, 0x00, 0x00, 0x5e, 0x53, 0x4a, 0xf7,
+ 0x18, 0xfa, 0x11, 0xff, 0x6c, 0xf3, 0x90, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x18, 0xfa, 0x11, 0xff, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf2, 0x34, 0x4a, 0xf7,
+ 0x18, 0xfa, 0x11, 0xff
+};
+
+struct bcd2000 {
+ struct usb_device *dev;
+ struct snd_card *card;
+ struct usb_interface *intf;
+ int card_index;
+
+ int midi_out_active;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *midi_receive_substream;
+ struct snd_rawmidi_substream *midi_out_substream;
+
+ unsigned char midi_in_buf[BUFSIZE];
+ unsigned char midi_out_buf[BUFSIZE];
+
+ struct urb *midi_out_urb;
+ struct urb *midi_in_urb;
+
+ struct usb_anchor anchor;
+};
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+
+static DEFINE_MUTEX(devices_mutex);
+DECLARE_BITMAP(devices_used, SNDRV_CARDS);
+static struct usb_driver bcd2000_driver;
+
+#ifdef CONFIG_SND_DEBUG
+static void bcd2000_dump_buffer(const char *prefix, const char *buf, int len)
+{
+ print_hex_dump(KERN_DEBUG, prefix,
+ DUMP_PREFIX_NONE, 16, 1,
+ buf, len, false);
+}
+#else
+static void bcd2000_dump_buffer(const char *prefix, const char *buf, int len) {}
+#endif
+
+static int bcd2000_midi_input_open(struct snd_rawmidi_substream *substream)
+{
+ return 0;
+}
+
+static int bcd2000_midi_input_close(struct snd_rawmidi_substream *substream)
+{
+ return 0;
+}
+
+/* (de)register midi substream from client */
+static void bcd2000_midi_input_trigger(struct snd_rawmidi_substream *substream,
+ int up)
+{
+ struct bcd2000 *bcd2k = substream->rmidi->private_data;
+ bcd2k->midi_receive_substream = up ? substream : NULL;
+}
+
+static void bcd2000_midi_handle_input(struct bcd2000 *bcd2k,
+ const unsigned char *buf, unsigned int buf_len)
+{
+ unsigned int payload_length, tocopy;
+ struct snd_rawmidi_substream *midi_receive_substream;
+
+ midi_receive_substream = ACCESS_ONCE(bcd2k->midi_receive_substream);
+ if (!midi_receive_substream)
+ return;
+
+ bcd2000_dump_buffer(PREFIX "received from device: ", buf, buf_len);
+
+ if (buf_len < 2)
+ return;
+
+ payload_length = buf[0];
+
+ /* ignore packets without payload */
+ if (payload_length == 0)
+ return;
+
+ tocopy = min(payload_length, buf_len-1);
+
+ bcd2000_dump_buffer(PREFIX "sending to userspace: ",
+ &buf[1], tocopy);
+
+ snd_rawmidi_receive(midi_receive_substream,
+ &buf[1], tocopy);
+}
+
+static void bcd2000_midi_send(struct bcd2000 *bcd2k)
+{
+ int len, ret;
+ struct snd_rawmidi_substream *midi_out_substream;
+
+ BUILD_BUG_ON(sizeof(device_cmd_prefix) >= BUFSIZE);
+
+ midi_out_substream = ACCESS_ONCE(bcd2k->midi_out_substream);
+ if (!midi_out_substream)
+ return;
+
+ /* copy command prefix bytes */
+ memcpy(bcd2k->midi_out_buf, device_cmd_prefix,
+ sizeof(device_cmd_prefix));
+
+ /*
+ * get MIDI packet and leave space for command prefix
+ * and payload length
+ */
+ len = snd_rawmidi_transmit(midi_out_substream,
+ bcd2k->midi_out_buf + 3, BUFSIZE - 3);
+
+ if (len < 0)
+ dev_err(&bcd2k->dev->dev, "%s: snd_rawmidi_transmit error %d\n",
+ __func__, len);
+
+ if (len <= 0)
+ return;
+
+ /* set payload length */
+ bcd2k->midi_out_buf[2] = len;
+ bcd2k->midi_out_urb->transfer_buffer_length = BUFSIZE;
+
+ bcd2000_dump_buffer(PREFIX "sending to device: ",
+ bcd2k->midi_out_buf, len+3);
+
+ /* send packet to the BCD2000 */
+ ret = usb_submit_urb(bcd2k->midi_out_urb, GFP_ATOMIC);
+ if (ret < 0)
+ dev_err(&bcd2k->dev->dev, PREFIX
+ "%s (%p): usb_submit_urb() failed, ret=%d, len=%d\n",
+ __func__, midi_out_substream, ret, len);
+ else
+ bcd2k->midi_out_active = 1;
+}
+
+static int bcd2000_midi_output_open(struct snd_rawmidi_substream *substream)
+{
+ return 0;
+}
+
+static int bcd2000_midi_output_close(struct snd_rawmidi_substream *substream)
+{
+ struct bcd2000 *bcd2k = substream->rmidi->private_data;
+
+ if (bcd2k->midi_out_active) {
+ usb_kill_urb(bcd2k->midi_out_urb);
+ bcd2k->midi_out_active = 0;
+ }
+
+ return 0;
+}
+
+/* (de)register midi substream from client */
+static void bcd2000_midi_output_trigger(struct snd_rawmidi_substream *substream,
+ int up)
+{
+ struct bcd2000 *bcd2k = substream->rmidi->private_data;
+
+ if (up) {
+ bcd2k->midi_out_substream = substream;
+ /* check if there is data userspace wants to send */
+ if (!bcd2k->midi_out_active)
+ bcd2000_midi_send(bcd2k);
+ } else {
+ bcd2k->midi_out_substream = NULL;
+ }
+}
+
+static void bcd2000_output_complete(struct urb *urb)
+{
+ struct bcd2000 *bcd2k = urb->context;
+
+ bcd2k->midi_out_active = 0;
+
+ if (urb->status)
+ dev_warn(&urb->dev->dev,
+ PREFIX "output urb->status: %d\n", urb->status);
+
+ if (urb->status == -ESHUTDOWN)
+ return;
+
+ /* check if there is more data userspace wants to send */
+ bcd2000_midi_send(bcd2k);
+}
+
+static void bcd2000_input_complete(struct urb *urb)
+{
+ int ret;
+ struct bcd2000 *bcd2k = urb->context;
+
+ if (urb->status)
+ dev_warn(&urb->dev->dev,
+ PREFIX "input urb->status: %i\n", urb->status);
+
+ if (!bcd2k || urb->status == -ESHUTDOWN)
+ return;
+
+ if (urb->actual_length > 0)
+ bcd2000_midi_handle_input(bcd2k, urb->transfer_buffer,
+ urb->actual_length);
+
+ /* return URB to device */
+ ret = usb_submit_urb(bcd2k->midi_in_urb, GFP_ATOMIC);
+ if (ret < 0)
+ dev_err(&bcd2k->dev->dev, PREFIX
+ "%s: usb_submit_urb() failed, ret=%d\n",
+ __func__, ret);
+}
+
+static struct snd_rawmidi_ops bcd2000_midi_output = {
+ .open = bcd2000_midi_output_open,
+ .close = bcd2000_midi_output_close,
+ .trigger = bcd2000_midi_output_trigger,
+};
+
+static struct snd_rawmidi_ops bcd2000_midi_input = {
+ .open = bcd2000_midi_input_open,
+ .close = bcd2000_midi_input_close,
+ .trigger = bcd2000_midi_input_trigger,
+};
+
+static void bcd2000_init_device(struct bcd2000 *bcd2k)
+{
+ int ret;
+
+ init_usb_anchor(&bcd2k->anchor);
+ usb_anchor_urb(bcd2k->midi_out_urb, &bcd2k->anchor);
+ usb_anchor_urb(bcd2k->midi_in_urb, &bcd2k->anchor);
+
+ /* copy init sequence into buffer */
+ memcpy(bcd2k->midi_out_buf, bcd2000_init_sequence, 52);
+ bcd2k->midi_out_urb->transfer_buffer_length = 52;
+
+ /* submit sequence */
+ ret = usb_submit_urb(bcd2k->midi_out_urb, GFP_KERNEL);
+ if (ret < 0)
+ dev_err(&bcd2k->dev->dev, PREFIX
+ "%s: usb_submit_urb() out failed, ret=%d: ",
+ __func__, ret);
+ else
+ bcd2k->midi_out_active = 1;
+
+ /* pass URB to device to enable button and controller events */
+ ret = usb_submit_urb(bcd2k->midi_in_urb, GFP_KERNEL);
+ if (ret < 0)
+ dev_err(&bcd2k->dev->dev, PREFIX
+ "%s: usb_submit_urb() in failed, ret=%d: ",
+ __func__, ret);
+
+ /* ensure initialization is finished */
+ usb_wait_anchor_empty_timeout(&bcd2k->anchor, 1000);
+}
+
+static int bcd2000_init_midi(struct bcd2000 *bcd2k)
+{
+ int ret;
+ struct snd_rawmidi *rmidi;
+
+ ret = snd_rawmidi_new(bcd2k->card, bcd2k->card->shortname, 0,
+ 1, /* output */
+ 1, /* input */
+ &rmidi);
+
+ if (ret < 0)
+ return ret;
+
+ strlcpy(rmidi->name, bcd2k->card->shortname, sizeof(rmidi->name));
+
+ rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
+ rmidi->private_data = bcd2k;
+
+ rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
+ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
+ &bcd2000_midi_output);
+
+ rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
+ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+ &bcd2000_midi_input);
+
+ bcd2k->rmidi = rmidi;
+
+ bcd2k->midi_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+ bcd2k->midi_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ if (!bcd2k->midi_in_urb || !bcd2k->midi_out_urb) {
+ dev_err(&bcd2k->dev->dev, PREFIX "usb_alloc_urb failed\n");
+ return -ENOMEM;
+ }
+
+ usb_fill_int_urb(bcd2k->midi_in_urb, bcd2k->dev,
+ usb_rcvintpipe(bcd2k->dev, 0x81),
+ bcd2k->midi_in_buf, BUFSIZE,
+ bcd2000_input_complete, bcd2k, 1);
+
+ usb_fill_int_urb(bcd2k->midi_out_urb, bcd2k->dev,
+ usb_sndintpipe(bcd2k->dev, 0x1),
+ bcd2k->midi_out_buf, BUFSIZE,
+ bcd2000_output_complete, bcd2k, 1);
+
+ bcd2000_init_device(bcd2k);
+
+ return 0;
+}
+
+static void bcd2000_free_usb_related_resources(struct bcd2000 *bcd2k,
+ struct usb_interface *interface)
+{
+ /* usb_kill_urb not necessary, urb is aborted automatically */
+
+ usb_free_urb(bcd2k->midi_out_urb);
+ usb_free_urb(bcd2k->midi_in_urb);
+
+ if (bcd2k->intf) {
+ usb_set_intfdata(bcd2k->intf, NULL);
+ bcd2k->intf = NULL;
+ }
+}
+
+static int bcd2000_probe(struct usb_interface *interface,
+ const struct usb_device_id *usb_id)
+{
+ struct snd_card *card;
+ struct bcd2000 *bcd2k;
+ unsigned int card_index;
+ char usb_path[32];
+ int err;
+
+ mutex_lock(&devices_mutex);
+
+ for (card_index = 0; card_index < SNDRV_CARDS; ++card_index)
+ if (!test_bit(card_index, devices_used))
+ break;
+
+ if (card_index >= SNDRV_CARDS) {
+ mutex_unlock(&devices_mutex);
+ return -ENOENT;
+ }
+
+ err = snd_card_new(&interface->dev, index[card_index], id[card_index],
+ THIS_MODULE, sizeof(*bcd2k), &card);
+ if (err < 0) {
+ mutex_unlock(&devices_mutex);
+ return err;
+ }
+
+ bcd2k = card->private_data;
+ bcd2k->dev = interface_to_usbdev(interface);
+ bcd2k->card = card;
+ bcd2k->card_index = card_index;
+ bcd2k->intf = interface;
+
+ snd_card_set_dev(card, &interface->dev);
+
+ strncpy(card->driver, "snd-bcd2000", sizeof(card->driver));
+ strncpy(card->shortname, "BCD2000", sizeof(card->shortname));
+ usb_make_path(bcd2k->dev, usb_path, sizeof(usb_path));
+ snprintf(bcd2k->card->longname, sizeof(bcd2k->card->longname),
+ "Behringer BCD2000 at %s",
+ usb_path);
+
+ err = bcd2000_init_midi(bcd2k);
+ if (err < 0)
+ goto probe_error;
+
+ err = snd_card_register(card);
+ if (err < 0)
+ goto probe_error;
+
+ usb_set_intfdata(interface, bcd2k);
+ set_bit(card_index, devices_used);
+
+ mutex_unlock(&devices_mutex);
+ return 0;
+
+probe_error:
+ dev_info(&bcd2k->dev->dev, PREFIX "error during probing");
+ bcd2000_free_usb_related_resources(bcd2k, interface);
+ snd_card_free(card);
+ mutex_unlock(&devices_mutex);
+ return err;
+}
+
+static void bcd2000_disconnect(struct usb_interface *interface)
+{
+ struct bcd2000 *bcd2k = usb_get_intfdata(interface);
+
+ if (!bcd2k)
+ return;
+
+ mutex_lock(&devices_mutex);
+
+ /* make sure that userspace cannot create new requests */
+ snd_card_disconnect(bcd2k->card);
+
+ bcd2000_free_usb_related_resources(bcd2k, interface);
+
+ clear_bit(bcd2k->card_index, devices_used);
+
+ snd_card_free_when_closed(bcd2k->card);
+
+ mutex_unlock(&devices_mutex);
+}
+
+static struct usb_driver bcd2000_driver = {
+ .name = "snd-bcd2000",
+ .probe = bcd2000_probe,
+ .disconnect = bcd2000_disconnect,
+ .id_table = id_table,
+};
+
+module_usb_driver(bcd2000_driver);
+
+MODULE_DEVICE_TABLE(usb, id_table);
+MODULE_AUTHOR("Mario Kicherer, dev@kicherer.org");
+MODULE_DESCRIPTION("Behringer BCD2000 driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c
index ae6b50f9ed5..f65fc0987cf 100644
--- a/sound/usb/caiaq/control.c
+++ b/sound/usb/caiaq/control.c
@@ -28,6 +28,7 @@
#include "control.h"
#define CNT_INTVAL 0x10000
+#define MASCHINE_BANK_SIZE 32
static int control_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
@@ -105,6 +106,10 @@ static int control_put(struct snd_kcontrol *kcontrol,
USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1))
cmd = EP1_CMD_DIMM_LEDS;
+ if (cdev->chip.usb_id ==
+ USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER))
+ cmd = EP1_CMD_DIMM_LEDS;
+
if (pos & CNT_INTVAL) {
int i = pos & ~CNT_INTVAL;
@@ -121,6 +126,20 @@ static int control_put(struct snd_kcontrol *kcontrol,
usb_sndbulkpipe(cdev->chip.dev, 8),
cdev->ep8_out_buf, sizeof(cdev->ep8_out_buf),
&actual_len, 200);
+ } else if (cdev->chip.usb_id ==
+ USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER)) {
+
+ int bank = 0;
+ int offset = 0;
+
+ if (i >= MASCHINE_BANK_SIZE) {
+ bank = 0x1e;
+ offset = MASCHINE_BANK_SIZE;
+ }
+
+ snd_usb_caiaq_send_command_bank(cdev, cmd, bank,
+ cdev->control_state + offset,
+ MASCHINE_BANK_SIZE);
} else {
snd_usb_caiaq_send_command(cdev, cmd,
cdev->control_state, sizeof(cdev->control_state));
@@ -490,6 +509,74 @@ static struct caiaq_controller kontrols4_controller[] = {
{ "LED: FX2: Mode", 133 | CNT_INTVAL },
};
+static struct caiaq_controller maschine_controller[] = {
+ { "LED: Pad 1", 3 | CNT_INTVAL },
+ { "LED: Pad 2", 2 | CNT_INTVAL },
+ { "LED: Pad 3", 1 | CNT_INTVAL },
+ { "LED: Pad 4", 0 | CNT_INTVAL },
+ { "LED: Pad 5", 7 | CNT_INTVAL },
+ { "LED: Pad 6", 6 | CNT_INTVAL },
+ { "LED: Pad 7", 5 | CNT_INTVAL },
+ { "LED: Pad 8", 4 | CNT_INTVAL },
+ { "LED: Pad 9", 11 | CNT_INTVAL },
+ { "LED: Pad 10", 10 | CNT_INTVAL },
+ { "LED: Pad 11", 9 | CNT_INTVAL },
+ { "LED: Pad 12", 8 | CNT_INTVAL },
+ { "LED: Pad 13", 15 | CNT_INTVAL },
+ { "LED: Pad 14", 14 | CNT_INTVAL },
+ { "LED: Pad 15", 13 | CNT_INTVAL },
+ { "LED: Pad 16", 12 | CNT_INTVAL },
+
+ { "LED: Mute", 16 | CNT_INTVAL },
+ { "LED: Solo", 17 | CNT_INTVAL },
+ { "LED: Select", 18 | CNT_INTVAL },
+ { "LED: Duplicate", 19 | CNT_INTVAL },
+ { "LED: Navigate", 20 | CNT_INTVAL },
+ { "LED: Pad Mode", 21 | CNT_INTVAL },
+ { "LED: Pattern", 22 | CNT_INTVAL },
+ { "LED: Scene", 23 | CNT_INTVAL },
+
+ { "LED: Shift", 24 | CNT_INTVAL },
+ { "LED: Erase", 25 | CNT_INTVAL },
+ { "LED: Grid", 26 | CNT_INTVAL },
+ { "LED: Right Bottom", 27 | CNT_INTVAL },
+ { "LED: Rec", 28 | CNT_INTVAL },
+ { "LED: Play", 29 | CNT_INTVAL },
+ { "LED: Left Bottom", 32 | CNT_INTVAL },
+ { "LED: Restart", 33 | CNT_INTVAL },
+
+ { "LED: Group A", 41 | CNT_INTVAL },
+ { "LED: Group B", 40 | CNT_INTVAL },
+ { "LED: Group C", 37 | CNT_INTVAL },
+ { "LED: Group D", 36 | CNT_INTVAL },
+ { "LED: Group E", 39 | CNT_INTVAL },
+ { "LED: Group F", 38 | CNT_INTVAL },
+ { "LED: Group G", 35 | CNT_INTVAL },
+ { "LED: Group H", 34 | CNT_INTVAL },
+
+ { "LED: Auto Write", 42 | CNT_INTVAL },
+ { "LED: Snap", 43 | CNT_INTVAL },
+ { "LED: Right Top", 44 | CNT_INTVAL },
+ { "LED: Left Top", 45 | CNT_INTVAL },
+ { "LED: Sampling", 46 | CNT_INTVAL },
+ { "LED: Browse", 47 | CNT_INTVAL },
+ { "LED: Step", 48 | CNT_INTVAL },
+ { "LED: Control", 49 | CNT_INTVAL },
+
+ { "LED: Top Button 1", 57 | CNT_INTVAL },
+ { "LED: Top Button 2", 56 | CNT_INTVAL },
+ { "LED: Top Button 3", 55 | CNT_INTVAL },
+ { "LED: Top Button 4", 54 | CNT_INTVAL },
+ { "LED: Top Button 5", 53 | CNT_INTVAL },
+ { "LED: Top Button 6", 52 | CNT_INTVAL },
+ { "LED: Top Button 7", 51 | CNT_INTVAL },
+ { "LED: Top Button 8", 50 | CNT_INTVAL },
+
+ { "LED: Note Repeat", 58 | CNT_INTVAL },
+
+ { "Backlight Display", 59 | CNT_INTVAL }
+};
+
static int add_controls(struct caiaq_controller *c, int num,
struct snd_usb_caiaqdev *cdev)
{
@@ -553,6 +640,11 @@ int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *cdev)
ret = add_controls(kontrols4_controller,
ARRAY_SIZE(kontrols4_controller), cdev);
break;
+
+ case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
+ ret = add_controls(maschine_controller,
+ ARRAY_SIZE(maschine_controller), cdev);
+ break;
}
return ret;
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 1a61dd12fe3..b871ba407e4 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -235,6 +235,31 @@ int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *cdev,
cdev->ep1_out_buf, len+1, &actual_len, 200);
}
+int snd_usb_caiaq_send_command_bank(struct snd_usb_caiaqdev *cdev,
+ unsigned char command,
+ unsigned char bank,
+ const unsigned char *buffer,
+ int len)
+{
+ int actual_len;
+ struct usb_device *usb_dev = cdev->chip.dev;
+
+ if (!usb_dev)
+ return -EIO;
+
+ if (len > EP1_BUFSIZE - 2)
+ len = EP1_BUFSIZE - 2;
+
+ if (buffer && len > 0)
+ memcpy(cdev->ep1_out_buf+2, buffer, len);
+
+ cdev->ep1_out_buf[0] = command;
+ cdev->ep1_out_buf[1] = bank;
+
+ return usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, 1),
+ cdev->ep1_out_buf, len+2, &actual_len, 200);
+}
+
int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *cdev,
int rate, int depth, int bpp)
{
@@ -393,8 +418,9 @@ static int create_card(struct usb_device *usb_dev,
if (devnum >= SNDRV_CARDS)
return -ENODEV;
- err = snd_card_create(index[devnum], id[devnum], THIS_MODULE,
- sizeof(struct snd_usb_caiaqdev), &card);
+ err = snd_card_new(&intf->dev,
+ index[devnum], id[devnum], THIS_MODULE,
+ sizeof(struct snd_usb_caiaqdev), &card);
if (err < 0)
return err;
@@ -404,7 +430,6 @@ static int create_card(struct usb_device *usb_dev,
cdev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor),
le16_to_cpu(usb_dev->descriptor.idProduct));
spin_lock_init(&cdev->spinlock);
- snd_card_set_dev(card, &intf->dev);
*cardp = card;
return 0;
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h
index ad102fac694..ab0f7520a99 100644
--- a/sound/usb/caiaq/device.h
+++ b/sound/usb/caiaq/device.h
@@ -128,5 +128,10 @@ int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *cdev,
unsigned char command,
const unsigned char *buffer,
int len);
+int snd_usb_caiaq_send_command_bank(struct snd_usb_caiaqdev *cdev,
+ unsigned char command,
+ unsigned char bank,
+ const unsigned char *buffer,
+ int len);
#endif /* CAIAQ_DEVICE_H */
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 64952e2d3ed..a09e5f3519e 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -79,7 +79,6 @@ static bool 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 device_setup[SNDRV_CARDS]; /* device parameter for this card */
static bool ignore_ctl_error;
static bool autoclock = true;
@@ -94,8 +93,6 @@ module_param_array(vid, int, NULL, 0444);
MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device.");
module_param_array(pid, int, NULL, 0444);
MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
-module_param(nrpacks, int, 0644);
-MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
module_param_array(device_setup, int, NULL, 0444);
MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
module_param(ignore_ctl_error, bool, 0444);
@@ -142,8 +139,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
struct usb_interface *iface = usb_ifnum_to_if(dev, interface);
if (!iface) {
- snd_printk(KERN_ERR "%d:%u:%d : does not exist\n",
- dev->devnum, ctrlif, interface);
+ dev_err(&dev->dev, "%u:%d : does not exist\n",
+ ctrlif, interface);
return -EINVAL;
}
@@ -168,8 +165,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
}
if (usb_interface_claimed(iface)) {
- snd_printdd(KERN_INFO "%d:%d:%d: skipping, already claimed\n",
- dev->devnum, ctrlif, interface);
+ dev_dbg(&dev->dev, "%d:%d: skipping, already claimed\n",
+ ctrlif, interface);
return -EINVAL;
}
@@ -179,8 +176,9 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
int err = snd_usbmidi_create(chip->card, iface,
&chip->midi_list, NULL);
if (err < 0) {
- snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n",
- dev->devnum, ctrlif, interface);
+ dev_err(&dev->dev,
+ "%u:%d: cannot create sequencer device\n",
+ ctrlif, interface);
return -EINVAL;
}
usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L);
@@ -191,14 +189,15 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING) {
- snd_printdd(KERN_ERR "%d:%u:%d: skipping non-supported interface %d\n",
- dev->devnum, ctrlif, interface, altsd->bInterfaceClass);
+ dev_dbg(&dev->dev,
+ "%u:%d: skipping non-supported interface %d\n",
+ ctrlif, interface, altsd->bInterfaceClass);
/* skip non-supported classes */
return -EINVAL;
}
if (snd_usb_get_speed(dev) == USB_SPEED_LOW) {
- snd_printk(KERN_ERR "low speed audio streaming not supported\n");
+ dev_err(&dev->dev, "low speed audio streaming not supported\n");
return -EINVAL;
}
@@ -231,26 +230,27 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
protocol = altsd->bInterfaceProtocol;
if (!control_header) {
- snd_printk(KERN_ERR "cannot find UAC_HEADER\n");
+ dev_err(&dev->dev, "cannot find UAC_HEADER\n");
return -EINVAL;
}
switch (protocol) {
default:
- snd_printdd(KERN_WARNING "unknown interface protocol %#02x, assuming v1\n",
- protocol);
+ dev_warn(&dev->dev,
+ "unknown interface protocol %#02x, assuming v1\n",
+ protocol);
/* fall through */
case UAC_VERSION_1: {
struct uac1_ac_header_descriptor *h1 = control_header;
if (!h1->bInCollection) {
- snd_printk(KERN_INFO "skipping empty audio interface (v1)\n");
+ dev_info(&dev->dev, "skipping empty audio interface (v1)\n");
return -EINVAL;
}
if (h1->bLength < sizeof(*h1) + h1->bInCollection) {
- snd_printk(KERN_ERR "invalid UAC_HEADER (v1)\n");
+ dev_err(&dev->dev, "invalid UAC_HEADER (v1)\n");
return -EINVAL;
}
@@ -280,7 +280,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
}
if (!assoc) {
- snd_printk(KERN_ERR "Audio class v2 interfaces need an interface association\n");
+ dev_err(&dev->dev, "Audio class v2 interfaces need an interface association\n");
return -EINVAL;
}
@@ -307,6 +307,11 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
static int snd_usb_audio_free(struct snd_usb_audio *chip)
{
+ struct list_head *p, *n;
+
+ list_for_each_safe(p, n, &chip->ep_list)
+ snd_usb_endpoint_free(p);
+
mutex_destroy(&chip->mutex);
kfree(chip);
return 0;
@@ -331,7 +336,8 @@ static void remove_trailing_spaces(char *str)
/*
* create a chip instance and set its names.
*/
-static int snd_usb_audio_create(struct usb_device *dev, int idx,
+static int snd_usb_audio_create(struct usb_interface *intf,
+ struct usb_device *dev, int idx,
const struct snd_usb_audio_quirk *quirk,
struct snd_usb_audio **rchip)
{
@@ -349,16 +355,18 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
case USB_SPEED_LOW:
case USB_SPEED_FULL:
case USB_SPEED_HIGH:
+ case USB_SPEED_WIRELESS:
case USB_SPEED_SUPER:
break;
default:
- snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev));
+ dev_err(&dev->dev, "unknown device speed %d\n", snd_usb_get_speed(dev));
return -ENXIO;
}
- err = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card);
+ err = snd_card_new(&intf->dev, index[idx], id[idx], THIS_MODULE,
+ 0, &card);
if (err < 0) {
- snd_printk(KERN_ERR "cannot create card instance %d\n", idx);
+ dev_err(&dev->dev, "cannot create card instance %d\n", idx);
return err;
}
@@ -374,7 +382,6 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
chip->dev = dev;
chip->card = card;
chip->setup = device_setup[idx];
- chip->nrpacks = nrpacks;
chip->autoclock = autoclock;
chip->probing = 1;
@@ -500,7 +507,7 @@ snd_usb_audio_probe(struct usb_device *dev,
for (i = 0; i < SNDRV_CARDS; i++) {
if (usb_chip[i] && usb_chip[i]->dev == dev) {
if (usb_chip[i]->shutdown) {
- snd_printk(KERN_ERR "USB device is in the shutdown state, cannot create a card instance\n");
+ dev_err(&dev->dev, "USB device is in the shutdown state, cannot create a card instance\n");
goto __error;
}
chip = usb_chip[i];
@@ -516,15 +523,15 @@ snd_usb_audio_probe(struct usb_device *dev,
if (enable[i] && ! usb_chip[i] &&
(vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
(pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) {
- if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) {
+ if (snd_usb_audio_create(intf, dev, i, quirk,
+ &chip) < 0) {
goto __error;
}
- snd_card_set_dev(chip->card, &intf->dev);
chip->pm_intf = intf;
break;
}
if (!chip) {
- printk(KERN_ERR "no available usb audio device\n");
+ dev_err(&dev->dev, "no available usb audio device\n");
goto __error;
}
}
@@ -583,7 +590,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
struct snd_usb_audio *chip)
{
struct snd_card *card;
- struct list_head *p, *n;
+ struct list_head *p;
if (chip == (void *)-1L)
return;
@@ -596,14 +603,16 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
mutex_lock(&register_mutex);
chip->num_interfaces--;
if (chip->num_interfaces <= 0) {
+ struct snd_usb_endpoint *ep;
+
snd_card_disconnect(card);
/* release the pcm resources */
list_for_each(p, &chip->pcm_list) {
snd_usb_stream_disconnect(p);
}
/* release the endpoint resources */
- list_for_each_safe(p, n, &chip->ep_list) {
- snd_usb_endpoint_free(p);
+ list_for_each_entry(ep, &chip->ep_list, list) {
+ snd_usb_endpoint_release(ep);
}
/* release the midi resources */
list_for_each(p, &chip->midi_list) {
@@ -649,7 +658,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
int err = -ENODEV;
down_read(&chip->shutdown_rwsem);
- if (chip->probing)
+ if (chip->probing && chip->in_pm)
err = 0;
else if (!chip->shutdown)
err = usb_autopm_get_interface(chip->pm_intf);
@@ -661,7 +670,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
void snd_usb_autosuspend(struct snd_usb_audio *chip)
{
down_read(&chip->shutdown_rwsem);
- if (!chip->shutdown && !chip->probing)
+ if (!chip->shutdown && !chip->probing && !chip->in_pm)
usb_autopm_put_interface(chip->pm_intf);
up_read(&chip->shutdown_rwsem);
}
@@ -693,13 +702,14 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
chip->autosuspended = 1;
}
- list_for_each_entry(mixer, &chip->mixer_list, list)
- snd_usb_mixer_inactivate(mixer);
+ if (chip->num_suspended_intf == 1)
+ list_for_each_entry(mixer, &chip->mixer_list, list)
+ snd_usb_mixer_suspend(mixer);
return 0;
}
-static int usb_audio_resume(struct usb_interface *intf)
+static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
{
struct snd_usb_audio *chip = usb_get_intfdata(intf);
struct usb_mixer_interface *mixer;
@@ -709,12 +719,14 @@ static int usb_audio_resume(struct usb_interface *intf)
return 0;
if (--chip->num_suspended_intf)
return 0;
+
+ chip->in_pm = 1;
/*
* ALSA leaves material resumption to user space
* we just notify and restart the mixers
*/
list_for_each_entry(mixer, &chip->mixer_list, list) {
- err = snd_usb_mixer_activate(mixer);
+ err = snd_usb_mixer_resume(mixer, reset_resume);
if (err < 0)
goto err_out;
}
@@ -724,11 +736,23 @@ static int usb_audio_resume(struct usb_interface *intf)
chip->autosuspended = 0;
err_out:
+ chip->in_pm = 0;
return err;
}
+
+static int usb_audio_resume(struct usb_interface *intf)
+{
+ return __usb_audio_resume(intf, false);
+}
+
+static int usb_audio_reset_resume(struct usb_interface *intf)
+{
+ return __usb_audio_resume(intf, true);
+}
#else
#define usb_audio_suspend NULL
#define usb_audio_resume NULL
+#define usb_audio_reset_resume NULL
#endif /* CONFIG_PM */
static struct usb_device_id usb_audio_ids [] = {
@@ -750,23 +774,9 @@ static struct usb_driver usb_audio_driver = {
.disconnect = usb_audio_disconnect,
.suspend = usb_audio_suspend,
.resume = usb_audio_resume,
+ .reset_resume = usb_audio_reset_resume,
.id_table = usb_audio_ids,
.supports_autosuspend = 1,
};
-static int __init snd_usb_audio_init(void)
-{
- if (nrpacks < 1 || nrpacks > MAX_PACKS) {
- printk(KERN_WARNING "invalid nrpacks value.\n");
- return -EINVAL;
- }
- return usb_register(&usb_audio_driver);
-}
-
-static void __exit snd_usb_audio_cleanup(void)
-{
- usb_deregister(&usb_audio_driver);
-}
-
-module_init(snd_usb_audio_init);
-module_exit(snd_usb_audio_cleanup);
+module_usb_driver(usb_audio_driver);
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 5ecacaa90b5..97acb906acc 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -2,11 +2,11 @@
#define __USBAUDIO_CARD_H
#define MAX_NR_RATES 1024
-#define MAX_PACKS 20
+#define MAX_PACKS 6 /* per URB */
#define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */
-#define MAX_URBS 8
+#define MAX_URBS 12
#define SYNC_URBS 4 /* always four urbs for sync */
-#define MAX_QUEUE 24 /* try not to exceed this queue length, in ms */
+#define MAX_QUEUE 18 /* try not to exceed this queue length, in ms */
struct audioformat {
struct list_head list;
@@ -87,15 +87,17 @@ struct snd_usb_endpoint {
unsigned int phase; /* phase accumulator */
unsigned int maxpacksize; /* max packet size in bytes */
unsigned int maxframesize; /* max packet size in frames */
+ unsigned int max_urb_frames; /* max URB size in frames */
unsigned int curpacksize; /* current packet size in bytes (for capture) */
unsigned int curframesize; /* current packet size in frames (for capture) */
unsigned int syncmaxsize; /* sync endpoint packet size */
unsigned int fill_max:1; /* fill max packet size always */
+ unsigned int udh01_fb_quirk:1; /* corrupted feedback data */
unsigned int datainterval; /* log_2 of data packet interval */
unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */
unsigned char silence_value;
unsigned int stride;
- int iface, alt_idx;
+ int iface, altsetting;
int skip_packets; /* quirks for devices to ignore the first n packets
in a stream */
@@ -116,6 +118,8 @@ struct snd_usb_substream {
unsigned int channels_max; /* max channels in the all audiofmts */
unsigned int cur_rate; /* current rate (for hw_params callback) */
unsigned int period_bytes; /* current period bytes (for hw_params callback) */
+ unsigned int period_frames; /* current frames per period */
+ unsigned int buffer_periods; /* current periods per buffer */
unsigned int altset_idx; /* USB data format: index of alternate setting */
unsigned int txfr_quirk:1; /* allow sub-frame alignment */
unsigned int fmt_type; /* USB audio format type (1-3) */
@@ -125,6 +129,7 @@ struct snd_usb_substream {
unsigned int hwptr_done; /* processed byte position in the buffer */
unsigned int transfer_done; /* processed frames since last period update */
+ unsigned int frame_limit; /* limits number of packets in URB */
/* data and sync endpoints for this stream */
unsigned int ep_num; /* the endpoint number */
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index 86f80c60b21..03fed6611d9 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -115,9 +115,9 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i
return ret;
if (ret != sizeof(pin)) {
- snd_printk(KERN_ERR
- "usb-audio:%d: setting selector (id %d) unexpected length %d\n",
- chip->dev->devnum, selector_id, ret);
+ usb_audio_err(chip,
+ "setting selector (id %d) unexpected length %d\n",
+ selector_id, ret);
return -EINVAL;
}
@@ -126,9 +126,9 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i
return ret;
if (ret != pin) {
- snd_printk(KERN_ERR
- "usb-audio:%d: setting selector (id %d) to %x failed (current: %d)\n",
- chip->dev->devnum, selector_id, pin, ret);
+ usb_audio_err(chip,
+ "setting selector (id %d) to %x failed (current: %d)\n",
+ selector_id, pin, ret);
return -EINVAL;
}
@@ -158,7 +158,8 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
&data, sizeof(data));
if (err < 0) {
- snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n",
+ dev_warn(&dev->dev,
+ "%s(): cannot get clock validity for id %d\n",
__func__, source_id);
return 0;
}
@@ -177,9 +178,9 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
entity_id &= 0xff;
if (test_and_set_bit(entity_id, visited)) {
- snd_printk(KERN_WARNING
- "%s(): recursive clock topology detected, id %d.\n",
- __func__, entity_id);
+ usb_audio_warn(chip,
+ "%s(): recursive clock topology detected, id %d.\n",
+ __func__, entity_id);
return -EINVAL;
}
@@ -188,8 +189,9 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
if (source) {
entity_id = source->bClockID;
if (validate && !uac_clock_source_is_valid(chip, entity_id)) {
- snd_printk(KERN_ERR "usb-audio:%d: clock source %d is not valid, cannot use\n",
- chip->dev->devnum, entity_id);
+ usb_audio_err(chip,
+ "clock source %d is not valid, cannot use\n",
+ entity_id);
return -ENXIO;
}
return entity_id;
@@ -208,7 +210,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
/* Selector values are one-based */
if (ret > selector->bNrInPins || ret < 1) {
- snd_printk(KERN_ERR
+ usb_audio_err(chip,
"%s(): selector reported illegal value, id %d, ret %d\n",
__func__, selector->bClockID, ret);
@@ -237,9 +239,9 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
if (err < 0)
continue;
- snd_printk(KERN_INFO
- "usb-audio:%d: found and selected valid clock source %d\n",
- chip->dev->devnum, ret);
+ usb_audio_info(chip,
+ "found and selected valid clock source %d\n",
+ ret);
return ret;
}
@@ -296,8 +298,8 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
data, sizeof(data))) < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
- dev->devnum, iface, fmt->altsetting, rate, ep);
+ dev_err(&dev->dev, "%d:%d: cannot set freq %d to ep %#x\n",
+ iface, fmt->altsetting, rate, ep);
return err;
}
@@ -305,14 +307,14 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
data, sizeof(data))) < 0) {
- snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
- dev->devnum, iface, fmt->altsetting, ep);
+ dev_err(&dev->dev, "%d:%d: cannot get freq at ep %#x\n",
+ iface, fmt->altsetting, ep);
return 0; /* some devices don't support reading */
}
crate = data[0] | (data[1] << 8) | (data[2] << 16);
if (crate != rate) {
- snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
+ dev_warn(&dev->dev, "current rate %d is different from the runtime rate %d\n", crate, rate);
// runtime->rate = crate;
}
@@ -332,8 +334,8 @@ static int get_sample_rate_v2(struct snd_usb_audio *chip, int iface,
snd_usb_ctrl_intf(chip) | (clock << 8),
&data, sizeof(data));
if (err < 0) {
- snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2): err %d\n",
- dev->devnum, iface, altsetting, err);
+ dev_warn(&dev->dev, "%d:%d: cannot get freq (v2): err %d\n",
+ iface, altsetting, err);
return 0;
}
@@ -369,8 +371,9 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
snd_usb_ctrl_intf(chip) | (clock << 8),
&data, sizeof(data));
if (err < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2): err %d\n",
- dev->devnum, iface, fmt->altsetting, rate, err);
+ usb_audio_err(chip,
+ "%d:%d: cannot set freq %d (v2): err %d\n",
+ iface, fmt->altsetting, rate, err);
return err;
}
@@ -381,14 +384,14 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
if (cur_rate != rate) {
if (!writeable) {
- snd_printk(KERN_WARNING
- "%d:%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n",
- dev->devnum, iface, fmt->altsetting, rate, cur_rate);
+ usb_audio_warn(chip,
+ "%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n",
+ iface, fmt->altsetting, rate, cur_rate);
return -ENXIO;
}
- snd_printd(KERN_WARNING
- "current rate %d is different from the runtime rate %d\n",
- cur_rate, rate);
+ usb_audio_dbg(chip,
+ "current rate %d is different from the runtime rate %d\n",
+ cur_rate, rate);
}
/* Some devices doesn't respond to sample rate changes while the
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 93e970f2b3c..114e3e7ff51 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -33,7 +33,6 @@
#include "pcm.h"
#include "quirks.h"
-#define EP_FLAG_ACTIVATED 0
#define EP_FLAG_RUNNING 1
#define EP_FLAG_STOPPING 2
@@ -334,8 +333,9 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
err = usb_submit_urb(ctx->urb, GFP_ATOMIC);
if (err < 0)
- snd_printk(KERN_ERR "Unable to submit urb #%d: %d (urb %p)\n",
- ctx->index, err, ctx->urb);
+ usb_audio_err(ep->chip,
+ "Unable to submit urb #%d: %d (urb %p)\n",
+ ctx->index, err, ctx->urb);
else
set_bit(ctx->index, &ep->active_mask);
}
@@ -388,7 +388,7 @@ static void snd_complete_urb(struct urb *urb)
if (err == 0)
return;
- snd_printk(KERN_ERR "cannot submit urb (err = %d)\n", err);
+ usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err);
//snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
exit_clear:
@@ -426,14 +426,15 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
list_for_each_entry(ep, &chip->ep_list, list) {
if (ep->ep_num == ep_num &&
ep->iface == alts->desc.bInterfaceNumber &&
- ep->alt_idx == alts->desc.bAlternateSetting) {
- snd_printdd(KERN_DEBUG "Re-using EP %x in iface %d,%d @%p\n",
- ep_num, ep->iface, ep->alt_idx, ep);
+ ep->altsetting == alts->desc.bAlternateSetting) {
+ usb_audio_dbg(ep->chip,
+ "Re-using EP %x in iface %d,%d @%p\n",
+ ep_num, ep->iface, ep->altsetting, ep);
goto __exit_unlock;
}
}
- snd_printdd(KERN_DEBUG "Creating new %s %s endpoint #%x\n",
+ usb_audio_dbg(chip, "Creating new %s %s endpoint #%x\n",
is_playback ? "playback" : "capture",
type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync",
ep_num);
@@ -447,7 +448,7 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
ep->type = type;
ep->ep_num = ep_num;
ep->iface = alts->desc.bInterfaceNumber;
- ep->alt_idx = alts->desc.bAlternateSetting;
+ ep->altsetting = alts->desc.bAlternateSetting;
INIT_LIST_HEAD(&ep->ready_playback_urbs);
ep_num &= USB_ENDPOINT_NUMBER_MASK;
@@ -470,6 +471,10 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
ep->syncinterval = 3;
ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
+
+ if (chip->usb_id == USB_ID(0x0644, 0x8038) /* TEAC UD-H01 */ &&
+ ep->syncmaxsize == 4)
+ ep->udh01_fb_quirk = 1;
}
list_add_tail(&ep->list, &chip->ep_list);
@@ -497,8 +502,9 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
} while (time_before(jiffies, end_time));
if (alive)
- snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n",
- alive, ep->ep_num);
+ usb_audio_err(ep->chip,
+ "timeout: still %d active urbs on EP #%x\n",
+ alive, ep->ep_num);
clear_bit(EP_FLAG_STOPPING, &ep->flags);
return 0;
@@ -574,11 +580,14 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
snd_pcm_format_t pcm_format,
unsigned int channels,
unsigned int period_bytes,
+ unsigned int frames_per_period,
+ unsigned int periods_per_buffer,
struct audioformat *fmt,
struct snd_usb_endpoint *sync_ep)
{
- unsigned int maxsize, i, urb_packs, total_packs, packs_per_ms;
- int is_playback = usb_pipeout(ep->pipe);
+ unsigned int maxsize, minsize, packs_per_ms, max_packs_per_urb;
+ unsigned int max_packs_per_period, urbs_per_period, urb_packs;
+ unsigned int max_urbs, i;
int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels;
if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) {
@@ -611,58 +620,81 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
else
ep->curpacksize = maxsize;
- if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL)
+ if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) {
packs_per_ms = 8 >> ep->datainterval;
- else
- packs_per_ms = 1;
-
- if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) {
- urb_packs = max(ep->chip->nrpacks, 1);
- urb_packs = min(urb_packs, (unsigned int) MAX_PACKS);
+ max_packs_per_urb = MAX_PACKS_HS;
} else {
- urb_packs = 1;
+ packs_per_ms = 1;
+ max_packs_per_urb = MAX_PACKS;
}
+ if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
+ max_packs_per_urb = min(max_packs_per_urb,
+ 1U << sync_ep->syncinterval);
+ max_packs_per_urb = max(1u, max_packs_per_urb >> ep->datainterval);
- urb_packs *= packs_per_ms;
+ /*
+ * Capture endpoints need to use small URBs because there's no way
+ * to tell in advance where the next period will end, and we don't
+ * want the next URB to complete much after the period ends.
+ *
+ * Playback endpoints with implicit sync much use the same parameters
+ * as their corresponding capture endpoint.
+ */
+ if (usb_pipein(ep->pipe) ||
+ snd_usb_endpoint_implicit_feedback_sink(ep)) {
- if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
- urb_packs = min(urb_packs, 1U << sync_ep->syncinterval);
+ urb_packs = packs_per_ms;
+ /*
+ * Wireless devices can poll at a max rate of once per 4ms.
+ * For dataintervals less than 5, increase the packet count to
+ * allow the host controller to use bursting to fill in the
+ * gaps.
+ */
+ if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_WIRELESS) {
+ int interval = ep->datainterval;
+ while (interval < 5) {
+ urb_packs <<= 1;
+ ++interval;
+ }
+ }
+ /* make capture URBs <= 1 ms and smaller than a period */
+ urb_packs = min(max_packs_per_urb, urb_packs);
+ while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
+ urb_packs >>= 1;
+ ep->nurbs = MAX_URBS;
- /* decide how many packets to be used */
- if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) {
- unsigned int minsize, maxpacks;
+ /*
+ * Playback endpoints without implicit sync are adjusted so that
+ * a period fits as evenly as possible in the smallest number of
+ * URBs. The total number of URBs is adjusted to the size of the
+ * ALSA buffer, subject to the MAX_URBS and MAX_QUEUE limits.
+ */
+ } else {
/* determine how small a packet can be */
- minsize = (ep->freqn >> (16 - ep->datainterval))
- * (frame_bits >> 3);
+ minsize = (ep->freqn >> (16 - ep->datainterval)) *
+ (frame_bits >> 3);
/* with sync from device, assume it can be 12% lower */
if (sync_ep)
minsize -= minsize >> 3;
minsize = max(minsize, 1u);
- total_packs = (period_bytes + minsize - 1) / minsize;
- /* we need at least two URBs for queueing */
- if (total_packs < 2) {
- total_packs = 2;
- } 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 {
- while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
- urb_packs >>= 1;
- total_packs = MAX_URBS * urb_packs;
- }
- ep->nurbs = (total_packs + urb_packs - 1) / urb_packs;
- if (ep->nurbs > MAX_URBS) {
- /* too much... */
- ep->nurbs = MAX_URBS;
- total_packs = MAX_URBS * urb_packs;
- } else if (ep->nurbs < 2) {
- /* too little - we need at least two packets
- * to ensure contiguous playback/capture
- */
- ep->nurbs = 2;
+ /* how many packets will contain an entire ALSA period? */
+ max_packs_per_period = DIV_ROUND_UP(period_bytes, minsize);
+
+ /* how many URBs will contain a period? */
+ urbs_per_period = DIV_ROUND_UP(max_packs_per_period,
+ max_packs_per_urb);
+ /* how many packets are needed in each URB? */
+ urb_packs = DIV_ROUND_UP(max_packs_per_period, urbs_per_period);
+
+ /* limit the number of frames in a single URB */
+ ep->max_urb_frames = DIV_ROUND_UP(frames_per_period,
+ urbs_per_period);
+
+ /* try to use enough URBs to contain an entire ALSA buffer */
+ max_urbs = min((unsigned) MAX_URBS,
+ MAX_QUEUE * packs_per_ms / urb_packs);
+ ep->nurbs = min(max_urbs, urbs_per_period * periods_per_buffer);
}
/* allocate and initialize data urbs */
@@ -670,8 +702,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
struct snd_urb_ctx *u = &ep->urb[i];
u->index = i;
u->ep = ep;
- u->packets = (i + 1) * total_packs / ep->nurbs
- - i * total_packs / ep->nurbs;
+ u->packets = urb_packs;
u->buffer_size = maxsize * u->packets;
if (fmt->fmt_type == UAC_FORMAT_TYPE_II)
@@ -703,8 +734,7 @@ out_of_memory:
/*
* configure a sync endpoint
*/
-static int sync_ep_set_params(struct snd_usb_endpoint *ep,
- struct audioformat *fmt)
+static int sync_ep_set_params(struct snd_usb_endpoint *ep)
{
int i;
@@ -748,6 +778,8 @@ out_of_memory:
* @pcm_format: the audio fomat.
* @channels: the number of audio channels.
* @period_bytes: the number of bytes in one alsa period.
+ * @period_frames: the number of frames in one alsa period.
+ * @buffer_periods: the number of periods in one alsa buffer.
* @rate: the frame rate.
* @fmt: the USB audio format information
* @sync_ep: the sync endpoint to use, if any
@@ -760,6 +792,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
snd_pcm_format_t pcm_format,
unsigned int channels,
unsigned int period_bytes,
+ unsigned int period_frames,
+ unsigned int buffer_periods,
unsigned int rate,
struct audioformat *fmt,
struct snd_usb_endpoint *sync_ep)
@@ -767,8 +801,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
int err;
if (ep->use_count != 0) {
- snd_printk(KERN_WARNING "Unable to change format on ep #%x: already in use\n",
- ep->ep_num);
+ usb_audio_warn(ep->chip,
+ "Unable to change format on ep #%x: already in use\n",
+ ep->ep_num);
return -EBUSY;
}
@@ -793,17 +828,19 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
switch (ep->type) {
case SND_USB_ENDPOINT_TYPE_DATA:
err = data_ep_set_params(ep, pcm_format, channels,
- period_bytes, fmt, sync_ep);
+ period_bytes, period_frames,
+ buffer_periods, fmt, sync_ep);
break;
case SND_USB_ENDPOINT_TYPE_SYNC:
- err = sync_ep_set_params(ep, fmt);
+ err = sync_ep_set_params(ep);
break;
default:
err = -EINVAL;
}
- snd_printdd(KERN_DEBUG "Setting params for ep #%x (type %d, %d urbs), ret=%d\n",
- ep->ep_num, ep->type, ep->nurbs, err);
+ usb_audio_dbg(ep->chip,
+ "Setting params for ep #%x (type %d, %d urbs), ret=%d\n",
+ ep->ep_num, ep->type, ep->nurbs, err);
return err;
}
@@ -878,8 +915,9 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep)
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) {
- snd_printk(KERN_ERR "cannot submit urb %d, error %d: %s\n",
- i, err, usb_error_string(err));
+ usb_audio_err(ep->chip,
+ "cannot submit urb %d, error %d: %s\n",
+ i, err, usb_error_string(err));
goto __error;
}
set_bit(i, &ep->active_mask);
@@ -931,28 +969,34 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
*
* @ep: the endpoint to deactivate
*
- * If the endpoint is not currently in use, this functions will select the
- * alternate interface setting 0 for the interface of this endpoint.
+ * If the endpoint is not currently in use, this functions will
+ * deactivate its associated URBs.
*
* In case of any active users, this functions does nothing.
- *
- * Returns an error if usb_set_interface() failed, 0 in all other
- * cases.
*/
-int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
+void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
{
if (!ep)
- return -EINVAL;
-
- deactivate_urbs(ep, true);
- wait_clear_urbs(ep);
+ return;
if (ep->use_count != 0)
- return 0;
+ return;
- clear_bit(EP_FLAG_ACTIVATED, &ep->flags);
+ deactivate_urbs(ep, true);
+ wait_clear_urbs(ep);
+}
- return 0;
+/**
+ * snd_usb_endpoint_release: Tear down an snd_usb_endpoint
+ *
+ * @ep: the endpoint to release
+ *
+ * This function does not care for the endpoint's use count but will tear
+ * down all the streaming URBs immediately.
+ */
+void snd_usb_endpoint_release(struct snd_usb_endpoint *ep)
+{
+ release_urbs(ep, 1);
}
/**
@@ -960,15 +1004,13 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
*
* @ep: the list header of the endpoint to free
*
- * This function does not care for the endpoint's use count but will tear
- * down all the streaming URBs immediately and free all resources.
+ * This free all resources of the given ep.
*/
void snd_usb_endpoint_free(struct list_head *head)
{
struct snd_usb_endpoint *ep;
ep = list_entry(head, struct snd_usb_endpoint, list);
- release_urbs(ep, 1);
kfree(ep);
}
@@ -1078,7 +1120,16 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
if (f == 0)
return;
- if (unlikely(ep->freqshift == INT_MIN)) {
+ if (unlikely(sender->udh01_fb_quirk)) {
+ /*
+ * The TEAC UD-H01 firmware sometimes changes the feedback value
+ * by +/- 0x1.0000.
+ */
+ if (f < ep->freqn - 0x8000)
+ f += 0x10000;
+ else if (f > ep->freqn + 0x8000)
+ f -= 0x10000;
+ } else if (unlikely(ep->freqshift == INT_MIN)) {
/*
* The first time we see a feedback value, determine its format
* by shifting it left or right until it matches the nominal
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 2287adf5ca5..e61ee5c356a 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -12,6 +12,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
snd_pcm_format_t pcm_format,
unsigned int channels,
unsigned int period_bytes,
+ unsigned int period_frames,
+ unsigned int buffer_periods,
unsigned int rate,
struct audioformat *fmt,
struct snd_usb_endpoint *sync_ep);
@@ -20,7 +22,8 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep);
void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep);
void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
-int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
+void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
+void snd_usb_endpoint_release(struct snd_usb_endpoint *ep);
void snd_usb_endpoint_free(struct list_head *head);
int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep);
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 3525231c6b9..8bcc87cf566 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -74,8 +74,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
if ((pcm_formats == 0) &&
(format == 0 || format == (1 << UAC_FORMAT_TYPE_I_UNDEFINED))) {
/* some devices don't define this correctly... */
- snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n",
- chip->dev->devnum, fp->iface, fp->altsetting);
+ usb_audio_info(chip, "%u:%d : format type 0 is detected, processed as PCM\n",
+ fp->iface, fp->altsetting);
format = 1 << UAC_FORMAT_TYPE_I_PCM;
}
if (format & (1 << UAC_FORMAT_TYPE_I_PCM)) {
@@ -83,9 +83,9 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
sample_width == 24 && sample_bytes == 2)
sample_bytes = 3;
else if (sample_width > sample_bytes * 8) {
- snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n",
- chip->dev->devnum, fp->iface, fp->altsetting,
- sample_width, sample_bytes);
+ usb_audio_info(chip, "%u:%d : sample bitwidth %d in over sample bytes %d\n",
+ fp->iface, fp->altsetting,
+ sample_width, sample_bytes);
}
/* check the format byte size */
switch (sample_bytes) {
@@ -108,9 +108,10 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
pcm_formats |= SNDRV_PCM_FMTBIT_S32_LE;
break;
default:
- snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n",
- chip->dev->devnum, fp->iface, fp->altsetting,
- sample_width, sample_bytes);
+ usb_audio_info(chip,
+ "%u:%d : unsupported sample bitwidth %d in %d bytes\n",
+ fp->iface, fp->altsetting,
+ sample_width, sample_bytes);
break;
}
}
@@ -132,8 +133,9 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
pcm_formats |= SNDRV_PCM_FMTBIT_MU_LAW;
}
if (format & ~0x3f) {
- snd_printk(KERN_INFO "%d:%u:%d : unsupported format bits %#x\n",
- chip->dev->devnum, fp->iface, fp->altsetting, format);
+ usb_audio_info(chip,
+ "%u:%d : unsupported format bits %#x\n",
+ fp->iface, fp->altsetting, format);
}
pcm_formats |= snd_usb_interface_dsd_format_quirks(chip, fp, sample_bytes);
@@ -158,8 +160,9 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
int nr_rates = fmt[offset];
if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
- chip->dev->devnum, fp->iface, fp->altsetting);
+ usb_audio_err(chip,
+ "%u:%d : invalid UAC_FORMAT_TYPE desc\n",
+ fp->iface, fp->altsetting);
return -EINVAL;
}
@@ -171,7 +174,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
if (fp->rate_table == NULL) {
- snd_printk(KERN_ERR "cannot malloc\n");
+ usb_audio_err(chip, "cannot malloc\n");
return -ENOMEM;
}
@@ -189,8 +192,10 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
chip->usb_id == USB_ID(0x0ccd, 0x00b1)) &&
fp->altsetting == 5 && fp->maxpacksize == 392)
rate = 96000;
- /* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */
- if (rate == 16000 && chip->usb_id == USB_ID(0x041e, 0x4068))
+ /* Creative VF0420/VF0470 Live Cams report 16 kHz instead of 8kHz */
+ if (rate == 16000 &&
+ (chip->usb_id == USB_ID(0x041e, 0x4064) ||
+ chip->usb_id == USB_ID(0x041e, 0x4068)))
rate = 8000;
fp->rate_table[fp->nr_rates] = rate;
@@ -220,7 +225,8 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
* get to know how many sample rates we have to expect.
* Then fp->rate_table can be allocated and filled.
*/
-static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
+static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip,
+ struct audioformat *fp, int nr_triplets,
const unsigned char *data)
{
int i, nr_rates = 0;
@@ -259,7 +265,7 @@ static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
nr_rates++;
if (nr_rates >= MAX_NR_RATES) {
- snd_printk(KERN_ERR "invalid uac2 rates\n");
+ usb_audio_err(chip, "invalid uac2 rates\n");
break;
}
@@ -285,7 +291,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
int clock = snd_usb_clock_find_source(chip, fp->clock, false);
if (clock < 0) {
- snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n",
+ dev_err(&dev->dev,
+ "%s(): unable to find clock source (clock %d)\n",
__func__, clock);
goto err;
}
@@ -298,7 +305,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
tmp, sizeof(tmp));
if (ret < 0) {
- snd_printk(KERN_ERR "%s(): unable to retrieve number of sample rates (clock %d)\n",
+ dev_err(&dev->dev,
+ "%s(): unable to retrieve number of sample rates (clock %d)\n",
__func__, clock);
goto err;
}
@@ -319,7 +327,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
data, data_size);
if (ret < 0) {
- snd_printk(KERN_ERR "%s(): unable to retrieve sample rate range (clock %d)\n",
+ dev_err(&dev->dev,
+ "%s(): unable to retrieve sample rate range (clock %d)\n",
__func__, clock);
ret = -EINVAL;
goto err_free;
@@ -330,7 +339,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
* will have to deal with. */
kfree(fp->rate_table);
fp->rate_table = NULL;
- fp->nr_rates = parse_uac2_sample_rate_range(fp, nr_triplets, data);
+ fp->nr_rates = parse_uac2_sample_rate_range(chip, fp, nr_triplets, data);
if (fp->nr_rates == 0) {
/* SNDRV_PCM_RATE_CONTINUOUS */
@@ -346,7 +355,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
/* Call the triplet parser again, but this time, fp->rate_table is
* allocated, so the rates will be stored */
- parse_uac2_sample_rate_range(fp, nr_triplets, data);
+ parse_uac2_sample_rate_range(chip, fp, nr_triplets, data);
err_free:
kfree(data);
@@ -406,8 +415,9 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
}
if (fp->channels < 1) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n",
- chip->dev->devnum, fp->iface, fp->altsetting, fp->channels);
+ usb_audio_err(chip,
+ "%u:%d : invalid channels %d\n",
+ fp->iface, fp->altsetting, fp->channels);
return -EINVAL;
}
@@ -433,8 +443,9 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
fp->formats = SNDRV_PCM_FMTBIT_MPEG;
break;
default:
- 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);
+ usb_audio_info(chip,
+ "%u:%d : unknown format tag %#x is detected. processed as MPEG.\n",
+ fp->iface, fp->altsetting, format);
fp->formats = SNDRV_PCM_FMTBIT_MPEG;
break;
}
@@ -447,7 +458,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
struct uac_format_type_ii_discrete_descriptor *fmt = _fmt;
brate = le16_to_cpu(fmt->wMaxBitRate);
framesize = le16_to_cpu(fmt->wSamplesPerFrame);
- snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
+ usb_audio_info(chip, "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
fp->frame_size = framesize;
ret = parse_audio_format_rates_v1(chip, fp, _fmt, 8); /* fmt[8..] sample rates */
break;
@@ -456,7 +467,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
struct uac_format_type_ii_ext_descriptor *fmt = _fmt;
brate = le16_to_cpu(fmt->wMaxBitRate);
framesize = le16_to_cpu(fmt->wSamplesPerFrame);
- snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
+ usb_audio_info(chip, "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
fp->frame_size = framesize;
ret = parse_audio_format_rates_v2(chip, fp);
break;
@@ -482,9 +493,10 @@ int snd_usb_parse_audio_format(struct snd_usb_audio *chip,
err = parse_audio_format_ii(chip, fp, format, fmt);
break;
default:
- snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n",
- chip->dev->devnum, fp->iface, fp->altsetting,
- fmt->bFormatType);
+ usb_audio_info(chip,
+ "%u:%d : format type %d is not supported yet\n",
+ fp->iface, fp->altsetting,
+ fmt->bFormatType);
return -ENOTSUPP;
}
fp->fmt_type = fmt->bFormatType;
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index 620902463c6..51ed1ac825f 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -118,6 +118,7 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
{
switch (snd_usb_get_speed(chip->dev)) {
case USB_SPEED_HIGH:
+ case USB_SPEED_WIRELESS:
case USB_SPEED_SUPER:
if (get_endpoint(alts, 0)->bInterval >= 1 &&
get_endpoint(alts, 0)->bInterval <= 4)
diff --git a/sound/usb/hiface/chip.c b/sound/usb/hiface/chip.c
index b0dcb3924ce..2670d646bda 100644
--- a/sound/usb/hiface/chip.c
+++ b/sound/usb/hiface/chip.c
@@ -64,7 +64,8 @@ struct hiface_vendor_quirk {
u8 extra_freq;
};
-static int hiface_chip_create(struct usb_device *device, int idx,
+static int hiface_chip_create(struct usb_interface *intf,
+ struct usb_device *device, int idx,
const struct hiface_vendor_quirk *quirk,
struct hiface_chip **rchip)
{
@@ -76,7 +77,8 @@ static int hiface_chip_create(struct usb_device *device, int idx,
*rchip = NULL;
/* if we are here, card can be registered in alsa. */
- ret = snd_card_create(index[idx], id[idx], THIS_MODULE, sizeof(*chip), &card);
+ ret = snd_card_new(&intf->dev, index[idx], id[idx], THIS_MODULE,
+ sizeof(*chip), &card);
if (ret < 0) {
dev_err(&device->dev, "cannot create alsa card.\n");
return ret;
@@ -132,12 +134,10 @@ static int hiface_chip_probe(struct usb_interface *intf,
goto err;
}
- ret = hiface_chip_create(device, i, quirk, &chip);
+ ret = hiface_chip_create(intf, device, i, quirk, &chip);
if (ret < 0)
goto err;
- snd_card_set_dev(chip->card, &intf->dev);
-
ret = hiface_pcm_init(chip, quirk ? quirk->extra_freq : 0);
if (ret < 0)
goto err_chip_destroy;
diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c
index c21a3df9a0d..2c44139b404 100644
--- a/sound/usb/hiface/pcm.c
+++ b/sound/usb/hiface/pcm.c
@@ -110,7 +110,7 @@ static const struct snd_pcm_hardware pcm_hw = {
#define HIFACE_RATE_96000 0x4a
#define HIFACE_RATE_176400 0x40
#define HIFACE_RATE_192000 0x48
-#define HIFACE_RATE_352000 0x58
+#define HIFACE_RATE_352800 0x58
#define HIFACE_RATE_384000 0x68
static int hiface_pcm_set_rate(struct pcm_runtime *rt, unsigned int rate)
@@ -141,8 +141,8 @@ static int hiface_pcm_set_rate(struct pcm_runtime *rt, unsigned int rate)
case 192000:
rate_value = HIFACE_RATE_192000;
break;
- case 352000:
- rate_value = HIFACE_RATE_352000;
+ case 352800:
+ rate_value = HIFACE_RATE_352800;
break;
case 384000:
rate_value = HIFACE_RATE_384000;
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index b901f468b67..9da74d2e8ee 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -191,16 +191,16 @@ static int snd_usbmidi_submit_urb(struct urb* urb, gfp_t flags)
{
int err = usb_submit_urb(urb, flags);
if (err < 0 && err != -ENODEV)
- snd_printk(KERN_ERR "usb_submit_urb: %d\n", err);
+ dev_err(&urb->dev->dev, "usb_submit_urb: %d\n", err);
return err;
}
/*
* Error handling for URB completion functions.
*/
-static int snd_usbmidi_urb_error(int status)
+static int snd_usbmidi_urb_error(const struct urb *urb)
{
- switch (status) {
+ switch (urb->status) {
/* manually unlinked, or device gone */
case -ENOENT:
case -ECONNRESET:
@@ -213,7 +213,7 @@ static int snd_usbmidi_urb_error(int status)
case -EILSEQ:
return -EIO;
default:
- snd_printk(KERN_ERR "urb status %d\n", status);
+ dev_err(&urb->dev->dev, "urb status %d\n", urb->status);
return 0; /* continue */
}
}
@@ -227,7 +227,7 @@ static void snd_usbmidi_input_data(struct snd_usb_midi_in_endpoint* ep, int port
struct usbmidi_in_port* port = &ep->ports[portidx];
if (!port->substream) {
- snd_printd("unexpected port %d!\n", portidx);
+ dev_dbg(&ep->umidi->dev->dev, "unexpected port %d!\n", portidx);
return;
}
if (!test_bit(port->substream->number, &ep->umidi->input_triggered))
@@ -259,7 +259,7 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb)
ep->umidi->usb_protocol_ops->input(ep, urb->transfer_buffer,
urb->actual_length);
} else {
- int err = snd_usbmidi_urb_error(urb->status);
+ int err = snd_usbmidi_urb_error(urb);
if (err < 0) {
if (err != -ENODEV) {
ep->error_resubmit = 1;
@@ -289,7 +289,7 @@ static void snd_usbmidi_out_urb_complete(struct urb* urb)
}
spin_unlock(&ep->buffer_lock);
if (urb->status < 0) {
- int err = snd_usbmidi_urb_error(urb->status);
+ int err = snd_usbmidi_urb_error(urb);
if (err < 0) {
if (err != -ENODEV)
mod_timer(&ep->umidi->error_timer,
@@ -1668,7 +1668,7 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi,
struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number);
if (!substream) {
- snd_printd(KERN_ERR "substream %d:%d not found\n", stream, number);
+ dev_err(&umidi->dev->dev, "substream %d:%d not found\n", stream, number);
return;
}
@@ -1717,7 +1717,7 @@ static int snd_usbmidi_create_endpoints(struct snd_usb_midi* umidi,
}
}
}
- snd_printdd(KERN_INFO "created %d output and %d input ports\n",
+ dev_dbg(&umidi->dev->dev, "created %d output and %d input ports\n",
out_ports, in_ports);
return 0;
}
@@ -1747,10 +1747,11 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
ms_header->bLength >= 7 &&
ms_header->bDescriptorType == USB_DT_CS_INTERFACE &&
ms_header->bDescriptorSubtype == UAC_HEADER)
- snd_printdd(KERN_INFO "MIDIStreaming version %02x.%02x\n",
+ dev_dbg(&umidi->dev->dev, "MIDIStreaming version %02x.%02x\n",
ms_header->bcdMSC[1], ms_header->bcdMSC[0]);
else
- snd_printk(KERN_WARNING "MIDIStreaming interface descriptor not found\n");
+ dev_warn(&umidi->dev->dev,
+ "MIDIStreaming interface descriptor not found\n");
epidx = 0;
for (i = 0; i < intfd->bNumEndpoints; ++i) {
@@ -1767,7 +1768,8 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
if (usb_endpoint_dir_out(ep)) {
if (endpoints[epidx].out_ep) {
if (++epidx >= MIDI_MAX_ENDPOINTS) {
- snd_printk(KERN_WARNING "too many endpoints\n");
+ dev_warn(&umidi->dev->dev,
+ "too many endpoints\n");
break;
}
}
@@ -1782,12 +1784,13 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
*/
endpoints[epidx].out_interval = 1;
endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
- snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n",
+ dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n",
ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
} else {
if (endpoints[epidx].in_ep) {
if (++epidx >= MIDI_MAX_ENDPOINTS) {
- snd_printk(KERN_WARNING "too many endpoints\n");
+ dev_warn(&umidi->dev->dev,
+ "too many endpoints\n");
break;
}
}
@@ -1797,7 +1800,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW)
endpoints[epidx].in_interval = 1;
endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
- snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n",
+ dev_dbg(&umidi->dev->dev, "EP %02X: %d jack(s)\n",
ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
}
}
@@ -1865,7 +1868,7 @@ static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi* umidi)
(get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
return;
- snd_printdd(KERN_INFO "switching to altsetting %d with int ep\n",
+ dev_dbg(&umidi->dev->dev, "switching to altsetting %d with int ep\n",
intfd->bAlternateSetting);
usb_set_interface(umidi->dev, intfd->bInterfaceNumber,
intfd->bAlternateSetting);
@@ -2047,25 +2050,25 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi,
* input bulk endpoints (at indices 1 and 3) which aren't used.
*/
if (intfd->bNumEndpoints < (endpoint->out_cables > 0x0001 ? 5 : 3)) {
- snd_printdd(KERN_ERR "not enough endpoints\n");
+ dev_dbg(&umidi->dev->dev, "not enough endpoints\n");
return -ENOENT;
}
epd = get_endpoint(hostif, 0);
if (!usb_endpoint_dir_in(epd) || !usb_endpoint_xfer_int(epd)) {
- snd_printdd(KERN_ERR "endpoint[0] isn't interrupt\n");
+ dev_dbg(&umidi->dev->dev, "endpoint[0] isn't interrupt\n");
return -ENXIO;
}
epd = get_endpoint(hostif, 2);
if (!usb_endpoint_dir_out(epd) || !usb_endpoint_xfer_bulk(epd)) {
- snd_printdd(KERN_ERR "endpoint[2] isn't bulk output\n");
+ dev_dbg(&umidi->dev->dev, "endpoint[2] isn't bulk output\n");
return -ENXIO;
}
if (endpoint->out_cables > 0x0001) {
epd = get_endpoint(hostif, 4);
if (!usb_endpoint_dir_out(epd) ||
!usb_endpoint_xfer_bulk(epd)) {
- snd_printdd(KERN_ERR "endpoint[4] isn't bulk output\n");
+ dev_dbg(&umidi->dev->dev, "endpoint[4] isn't bulk output\n");
return -ENXIO;
}
}
@@ -2289,7 +2292,7 @@ int snd_usbmidi_create(struct snd_card *card,
err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
break;
default:
- snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
+ dev_err(&umidi->dev->dev, "invalid quirk type %d\n", quirk->type);
err = -ENXIO;
break;
}
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index 509315937f2..a1bab149df4 100644
--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -1243,8 +1243,9 @@ static int ua101_probe(struct usb_interface *interface,
mutex_unlock(&devices_mutex);
return -ENOENT;
}
- err = snd_card_create(index[card_index], id[card_index], THIS_MODULE,
- sizeof(*ua), &card);
+ err = snd_card_new(&interface->dev,
+ index[card_index], id[card_index], THIS_MODULE,
+ sizeof(*ua), &card);
if (err < 0) {
mutex_unlock(&devices_mutex);
return err;
@@ -1283,8 +1284,6 @@ static int ua101_probe(struct usb_interface *interface,
}
}
- snd_card_set_dev(card, &interface->dev);
-
err = detect_usb_format(ua);
if (err < 0)
goto probe_error;
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 95558ef4a7a..0b728d886f0 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -162,7 +162,7 @@ static int check_mapped_selector_name(struct mixer_build *state, int unitid,
{
const struct usbmix_selector_map *p;
- if (! state->selector_map)
+ if (!state->selector_map)
return 0;
for (p = state->selector_map; p->id; p++) {
if (p->id == unitid && index < p->count)
@@ -174,7 +174,8 @@ static int check_mapped_selector_name(struct mixer_build *state, int unitid,
/*
* find an audio control unit with the given unit id
*/
-static void *find_audio_control_unit(struct mixer_build *state, unsigned char unit)
+static void *find_audio_control_unit(struct mixer_build *state,
+ unsigned char unit)
{
/* we just parse the header */
struct uac_feature_unit_descriptor *hdr = NULL;
@@ -194,7 +195,8 @@ static void *find_audio_control_unit(struct mixer_build *state, unsigned char un
/*
* copy a string with the given id
*/
-static int snd_usb_copy_string_desc(struct mixer_build *state, int index, char *buf, int maxlen)
+static int snd_usb_copy_string_desc(struct mixer_build *state,
+ int index, char *buf, int maxlen)
{
int len = usb_string(state->chip->dev, index, buf, maxlen - 1);
buf[len] = 0;
@@ -253,7 +255,7 @@ static int convert_bytes_value(struct usb_mixer_elem_info *cval, int val)
static int get_relative_value(struct usb_mixer_elem_info *cval, int val)
{
- if (! cval->res)
+ if (!cval->res)
cval->res = 1;
if (val < cval->min)
return 0;
@@ -267,7 +269,7 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val)
{
if (val < 0)
return cval->min;
- if (! cval->res)
+ if (!cval->res)
cval->res = 1;
val *= cval->res;
val += cval->min;
@@ -281,7 +283,8 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val)
* retrieve a mixer value
*/
-static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
+static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
+ int validx, int *value_ret)
{
struct snd_usb_audio *chip = cval->mixer->chip;
unsigned char buf[2];
@@ -292,6 +295,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
err = snd_usb_autoresume(cval->mixer->chip);
if (err < 0)
return -EIO;
+
down_read(&chip->shutdown_rwsem);
while (timeout-- > 0) {
if (chip->shutdown)
@@ -305,8 +309,9 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
goto out;
}
}
- snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
- request, validx, idx, cval->val_type);
+ usb_audio_dbg(chip,
+ "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
+ request, validx, idx, cval->val_type);
err = -EINVAL;
out:
@@ -315,10 +320,11 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
return err;
}
-static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
+static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,
+ int validx, int *value_ret)
{
struct snd_usb_audio *chip = cval->mixer->chip;
- unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
+ unsigned char buf[2 + 3 * sizeof(__u16)]; /* enough space for one range */
unsigned char *val;
int idx = 0, ret, size;
__u8 bRequest;
@@ -338,9 +344,9 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
goto error;
down_read(&chip->shutdown_rwsem);
- if (chip->shutdown)
+ if (chip->shutdown) {
ret = -ENODEV;
- else {
+ } else {
idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
@@ -351,8 +357,9 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
if (ret < 0) {
error:
- snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
- request, validx, idx, cval->val_type);
+ usb_audio_err(chip,
+ "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
+ request, validx, idx, cval->val_type);
return ret;
}
@@ -380,7 +387,8 @@ error:
return 0;
}
-static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
+static int get_ctl_value(struct usb_mixer_elem_info *cval, int request,
+ int validx, int *value_ret)
{
validx += cval->idx_off;
@@ -389,7 +397,8 @@ static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int vali
get_ctl_value_v2(cval, request, validx, value_ret);
}
-static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *value)
+static int get_cur_ctl_value(struct usb_mixer_elem_info *cval,
+ int validx, int *value)
{
return get_ctl_value(cval, UAC_GET_CUR, validx, value);
}
@@ -398,7 +407,9 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *
static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval,
int channel, int *value)
{
- return get_ctl_value(cval, UAC_GET_CUR, (cval->control << 8) | channel, value);
+ return get_ctl_value(cval, UAC_GET_CUR,
+ (cval->control << 8) | channel,
+ value);
}
static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
@@ -413,8 +424,9 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
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);
+ usb_audio_dbg(cval->mixer->chip,
+ "cannot get current value for control %d ch %d: err = %d\n",
+ cval->control, channel, err);
return err;
}
cval->cached |= 1 << channel;
@@ -422,7 +434,6 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
return 0;
}
-
/*
* set a mixer value
*/
@@ -444,7 +455,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
/* FIXME */
if (request != UAC_SET_CUR) {
- snd_printdd(KERN_WARNING "RANGE setting not yet supported\n");
+ usb_audio_dbg(chip, "RANGE setting not yet supported\n");
return -EINVAL;
}
@@ -470,8 +481,8 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
goto out;
}
}
- snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
- request, validx, idx, cval->val_type, buf[0], buf[1]);
+ usb_audio_dbg(chip, "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
+ request, validx, idx, cval->val_type, buf[0], buf[1]);
err = -EINVAL;
out:
@@ -480,7 +491,8 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
return err;
}
-static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value)
+static int set_cur_ctl_value(struct usb_mixer_elem_info *cval,
+ int validx, int value)
{
return snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, validx, value);
}
@@ -494,13 +506,15 @@ static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
cval->ch_readonly & (1 << (channel - 1));
if (read_only) {
- snd_printdd(KERN_INFO "%s(): channel %d of control %d is read_only\n",
+ usb_audio_dbg(cval->mixer->chip,
+ "%s(): channel %d of control %d is read_only\n",
__func__, channel, cval->control);
return 0;
}
- err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel,
- value);
+ err = snd_usb_mixer_set_ctl_value(cval,
+ UAC_SET_CUR, (cval->control << 8) | channel,
+ value);
if (err < 0)
return err;
cval->cached |= 1 << channel;
@@ -537,13 +551,13 @@ static int parse_audio_unit(struct mixer_build *state, int unitid);
* check if the input/output channel routing is enabled on the given bitmap.
* used for mixer unit parser
*/
-static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_outs)
+static int check_matrix_bitmap(unsigned char *bmap,
+ int ich, int och, int num_outs)
{
int idx = ich * num_outs + och;
return bmap[idx >> 3] & (0x80 >> (idx & 7));
}
-
/*
* add an alsa control element
* search and increment the index until an empty slot is found.
@@ -560,7 +574,8 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
while (snd_ctl_find_id(mixer->chip->card, &kctl->id))
kctl->id.index++;
if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) {
- snd_printd(KERN_ERR "cannot add control (err = %d)\n", err);
+ usb_audio_dbg(mixer->chip, "cannot add control (err = %d)\n",
+ err);
return err;
}
cval->elem_id = &kctl->id;
@@ -569,7 +584,6 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
return 0;
}
-
/*
* get a terminal name string
*/
@@ -623,7 +637,8 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm
struct iterm_name_combo *names;
if (iterm->name)
- return snd_usb_copy_string_desc(state, iterm->name, name, maxlen);
+ return snd_usb_copy_string_desc(state, iterm->name,
+ name, maxlen);
/* virtual type - not a real terminal */
if (iterm->type >> 16) {
@@ -631,13 +646,17 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm
return 0;
switch (iterm->type >> 16) {
case UAC_SELECTOR_UNIT:
- strcpy(name, "Selector"); return 8;
+ strcpy(name, "Selector");
+ return 8;
case UAC1_PROCESSING_UNIT:
- strcpy(name, "Process Unit"); return 12;
+ strcpy(name, "Process Unit");
+ return 12;
case UAC1_EXTENSION_UNIT:
- strcpy(name, "Ext Unit"); return 8;
+ strcpy(name, "Ext Unit");
+ return 8;
case UAC_MIXER_UNIT:
- strcpy(name, "Mixer"); return 5;
+ strcpy(name, "Mixer");
+ return 5;
default:
return sprintf(name, "Unit %d", iterm->id);
}
@@ -645,29 +664,35 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm
switch (iterm->type & 0xff00) {
case 0x0100:
- strcpy(name, "PCM"); return 3;
+ strcpy(name, "PCM");
+ return 3;
case 0x0200:
- strcpy(name, "Mic"); return 3;
+ strcpy(name, "Mic");
+ return 3;
case 0x0400:
- strcpy(name, "Headset"); return 7;
+ strcpy(name, "Headset");
+ return 7;
case 0x0500:
- strcpy(name, "Phone"); return 5;
+ strcpy(name, "Phone");
+ return 5;
}
- for (names = iterm_names; names->type; names++)
+ for (names = iterm_names; names->type; names++) {
if (names->type == iterm->type) {
strcpy(name, names->name);
return strlen(names->name);
}
+ }
+
return 0;
}
-
/*
* parse the source unit recursively until it reaches to a terminal
* or a branched unit.
*/
-static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term)
+static int check_input_term(struct mixer_build *state, int id,
+ struct usb_audio_term *term)
{
int err;
void *p1;
@@ -762,7 +787,6 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
return -ENODEV;
}
-
/*
* Feature Unit
*/
@@ -790,7 +814,6 @@ static struct usb_feature_control_info audio_feature_info[] = {
{ "Phase Inverter Control", USB_MIXER_BOOLEAN },
};
-
/* private_free callback */
static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
{
@@ -798,7 +821,6 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
kctl->private_data = NULL;
}
-
/*
* interface to ALSA control for feature/mixer units
*/
@@ -807,7 +829,8 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
static void volume_control_quirks(struct usb_mixer_elem_info *cval,
struct snd_kcontrol *kctl)
{
- switch (cval->mixer->chip->usb_id) {
+ struct snd_usb_audio *chip = cval->mixer->chip;
+ switch (chip->usb_id) {
case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
if (strcmp(kctl->id.name, "Effect Duration") == 0) {
@@ -839,8 +862,8 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
if (strcmp(kctl->id.name, "Effect Duration") == 0) {
- snd_printk(KERN_INFO
- "usb-audio: set quirk for FTU Effect Duration\n");
+ usb_audio_info(chip,
+ "set quirk for FTU Effect Duration\n");
cval->min = 0x0000;
cval->max = 0x7f00;
cval->res = 0x0100;
@@ -848,8 +871,8 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
}
if (strcmp(kctl->id.name, "Effect Volume") == 0 ||
strcmp(kctl->id.name, "Effect Feedback Volume") == 0) {
- snd_printk(KERN_INFO
- "usb-audio: set quirks for FTU Effect Feedback/Volume\n");
+ usb_audio_info(chip,
+ "set quirks for FTU Effect Feedback/Volume\n");
cval->min = 0x00;
cval->max = 0x7f;
break;
@@ -867,7 +890,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
*/
if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
cval->min == -15616) {
- snd_printk(KERN_INFO
+ usb_audio_info(chip,
"set volume quirk for UDA1321/N101 chip\n");
cval->max = -256;
}
@@ -875,7 +898,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
case USB_ID(0x046d, 0x09a4):
if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- snd_printk(KERN_INFO
+ usb_audio_info(chip,
"set volume quirk for QuickCam E3500\n");
cval->min = 6080;
cval->max = 8768;
@@ -883,6 +906,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
}
break;
+ case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */
case USB_ID(0x046d, 0x0808):
case USB_ID(0x046d, 0x0809):
case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */
@@ -895,12 +919,11 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
* Proboly there is some logitech magic behind this number --fishor
*/
if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- snd_printk(KERN_INFO
+ usb_audio_info(chip,
"set resolution quirk: cval->res = 384\n");
cval->res = 384;
}
break;
-
}
}
@@ -931,22 +954,28 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
}
if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
- snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n",
- cval->id, snd_usb_ctrl_intf(cval->mixer->chip), cval->control, cval->id);
+ usb_audio_err(cval->mixer->chip,
+ "%d:%d: cannot get min/max values for control %d (id %d)\n",
+ cval->id, snd_usb_ctrl_intf(cval->mixer->chip),
+ cval->control, cval->id);
return -EINVAL;
}
- if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
+ if (get_ctl_value(cval, UAC_GET_RES,
+ (cval->control << 8) | minchn,
+ &cval->res) < 0) {
cval->res = 1;
} else {
int last_valid_res = cval->res;
while (cval->res > 1) {
if (snd_usb_mixer_set_ctl_value(cval, UAC_SET_RES,
- (cval->control << 8) | minchn, cval->res / 2) < 0)
+ (cval->control << 8) | minchn,
+ cval->res / 2) < 0)
break;
cval->res /= 2;
}
- if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0)
+ if (get_ctl_value(cval, UAC_GET_RES,
+ (cval->control << 8) | minchn, &cval->res) < 0)
cval->res = last_valid_res;
}
if (cval->res == 0)
@@ -1010,7 +1039,8 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
#define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL)
/* get a feature/mixer unit info */
-static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
struct usb_mixer_elem_info *cval = kcontrol->private_data;
@@ -1044,7 +1074,8 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
}
/* get the current value from feature/mixer unit */
-static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct usb_mixer_elem_info *cval = kcontrol->private_data;
int c, cnt, val, err;
@@ -1075,7 +1106,8 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
}
/* put the current value to feature/mixer unit */
-static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct usb_mixer_elem_info *cval = kcontrol->private_data;
int c, cnt, val, oval, err;
@@ -1129,36 +1161,39 @@ static struct snd_kcontrol_new usb_feature_unit_ctl_ro = {
.put = NULL,
};
-/* This symbol is exported in order to allow the mixer quirks to
- * hook up to the standard feature unit control mechanism */
+/*
+ * This symbol is exported in order to allow the mixer quirks to
+ * hook up to the standard feature unit control mechanism
+ */
struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl;
/*
* build a feature control
*/
-
static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str)
{
return strlcat(kctl->id.name, str, sizeof(kctl->id.name));
}
-/* A lot of headsets/headphones have a "Speaker" mixer. Make sure we
- rename it to "Headphone". We determine if something is a headphone
- similar to how udev determines form factor. */
+/*
+ * A lot of headsets/headphones have a "Speaker" mixer. Make sure we
+ * rename it to "Headphone". We determine if something is a headphone
+ * similar to how udev determines form factor.
+ */
static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
struct snd_card *card)
{
const char *names_to_check[] = {
"Headset", "headset", "Headphone", "headphone", NULL};
const char **s;
- bool found = 0;
+ bool found = false;
if (strcmp("Speaker", kctl->id.name))
return;
for (s = names_to_check; *s; s++)
if (strstr(card->shortname, *s)) {
- found = 1;
+ found = true;
break;
}
@@ -1194,10 +1229,8 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
return;
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
- if (! cval) {
- snd_printk(KERN_ERR "cannot malloc kcontrol\n");
+ if (!cval)
return;
- }
cval->mixer = state->mixer;
cval->id = unitid;
cval->control = control;
@@ -1215,16 +1248,18 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
cval->ch_readonly = readonly_mask;
}
- /* if all channels in the mask are marked read-only, make the control
+ /*
+ * If all channels in the mask are marked read-only, make the control
* read-only. set_cur_mix_value() will check the mask again and won't
- * issue write commands to read-only channels. */
+ * issue write commands to read-only channels.
+ */
if (cval->channels == readonly_mask)
kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval);
else
kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
- if (! kctl) {
- snd_printk(KERN_ERR "cannot malloc kcontrol\n");
+ if (!kctl) {
+ usb_audio_err(state->chip, "cannot malloc kcontrol\n");
kfree(cval);
return;
}
@@ -1232,48 +1267,53 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
mapped_name = len != 0;
- if (! len && nameid)
+ if (!len && nameid)
len = snd_usb_copy_string_desc(state, nameid,
kctl->id.name, sizeof(kctl->id.name));
switch (control) {
case UAC_FU_MUTE:
case UAC_FU_VOLUME:
- /* determine the control name. the rule is:
+ /*
+ * determine the control name. the rule is:
* - if a name id is given in descriptor, use it.
* - if the connected input can be determined, then use the name
* of terminal type.
* - if the connected output can be determined, use it.
* - otherwise, anonymous name.
*/
- if (! len) {
- len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 1);
- if (! len)
- len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 1);
- if (! len)
- len = snprintf(kctl->id.name, sizeof(kctl->id.name),
+ if (!len) {
+ len = get_term_name(state, iterm, kctl->id.name,
+ sizeof(kctl->id.name), 1);
+ if (!len)
+ len = get_term_name(state, &state->oterm,
+ kctl->id.name,
+ sizeof(kctl->id.name), 1);
+ if (!len)
+ len = snprintf(kctl->id.name,
+ sizeof(kctl->id.name),
"Feature %d", unitid);
}
if (!mapped_name)
check_no_speaker_on_headset(kctl, state->mixer->chip->card);
- /* determine the stream direction:
+ /*
+ * determine the stream direction:
* if the connected output is USB stream, then it's likely a
* capture stream. otherwise it should be playback (hopefully :)
*/
- if (! mapped_name && ! (state->oterm.type >> 16)) {
- if ((state->oterm.type & 0xff00) == 0x0100) {
+ if (!mapped_name && !(state->oterm.type >> 16)) {
+ if ((state->oterm.type & 0xff00) == 0x0100)
len = append_ctl_name(kctl, " Capture");
- } else {
+ else
len = append_ctl_name(kctl, " Playback");
- }
}
append_ctl_name(kctl, control == UAC_FU_MUTE ?
" Switch" : " Volume");
break;
default:
- if (! len)
+ if (!len)
strlcpy(kctl->id.name, audio_feature_info[control-1].name,
sizeof(kctl->id.name));
break;
@@ -1293,33 +1333,35 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
}
range = (cval->max - cval->min) / cval->res;
- /* Are there devices with volume range more than 255? I use a bit more
+ /*
+ * Are there devices with volume range more than 255? I use a bit more
* to be sure. 384 is a resolution magic number found on Logitech
* devices. It will definitively catch all buggy Logitech devices.
*/
if (range > 384) {
- snd_printk(KERN_WARNING "usb_audio: Warning! Unlikely big "
- "volume range (=%u), cval->res is probably wrong.",
- range);
- snd_printk(KERN_WARNING "usb_audio: [%d] FU [%s] ch = %d, "
- "val = %d/%d/%d", cval->id,
- kctl->id.name, cval->channels,
- cval->min, cval->max, cval->res);
- }
-
- snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
- cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
+ usb_audio_warn(state->chip,
+ "Warning! Unlikely big volume range (=%u), "
+ "cval->res is probably wrong.",
+ range);
+ usb_audio_warn(state->chip, "[%d] FU [%s] ch = %d, "
+ "val = %d/%d/%d", cval->id,
+ kctl->id.name, cval->channels,
+ cval->min, cval->max, cval->res);
+ }
+
+ usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
+ cval->id, kctl->id.name, cval->channels,
+ cval->min, cval->max, cval->res);
snd_usb_mixer_add_control(state->mixer, kctl);
}
-
-
/*
* parse a feature unit
*
* most of controls are defined here.
*/
-static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void *_ftr)
+static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
+ void *_ftr)
{
int channels, i, j;
struct usb_audio_term iterm;
@@ -1331,16 +1373,17 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
if (state->mixer->protocol == UAC_VERSION_1) {
csize = hdr->bControlSize;
if (!csize) {
- snd_printdd(KERN_ERR "usbaudio: unit %u: "
- "invalid bControlSize == 0\n", unitid);
+ usb_audio_dbg(state->chip,
+ "unit %u: invalid bControlSize == 0\n",
+ unitid);
return -EINVAL;
}
channels = (hdr->bLength - 7) / csize - 1;
bmaControls = hdr->bmaControls;
if (hdr->bLength < 7 + csize) {
- snd_printk(KERN_ERR "usbaudio: unit %u: "
- "invalid UAC_FEATURE_UNIT descriptor\n",
- unitid);
+ usb_audio_err(state->chip,
+ "unit %u: invalid UAC_FEATURE_UNIT descriptor\n",
+ unitid);
return -EINVAL;
}
} else {
@@ -1349,9 +1392,9 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
channels = (hdr->bLength - 6) / 4 - 1;
bmaControls = ftr->bmaControls;
if (hdr->bLength < 6 + csize) {
- snd_printk(KERN_ERR "usbaudio: unit %u: "
- "invalid UAC_FEATURE_UNIT descriptor\n",
- unitid);
+ usb_audio_err(state->chip,
+ "unit %u: invalid UAC_FEATURE_UNIT descriptor\n",
+ unitid);
return -EINVAL;
}
}
@@ -1369,14 +1412,14 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
/* master configuration quirks */
switch (state->chip->usb_id) {
case USB_ID(0x08bb, 0x2702):
- snd_printk(KERN_INFO
- "usbmixer: master volume quirk for PCM2702 chip\n");
+ usb_audio_info(state->chip,
+ "usbmixer: master volume quirk for PCM2702 chip\n");
/* disable non-functional volume control */
master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME);
break;
case USB_ID(0x1130, 0xf211):
- snd_printk(KERN_INFO
- "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n");
+ usb_audio_info(state->chip,
+ "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n");
/* disable non-functional volume control */
channels = 0;
break;
@@ -1392,15 +1435,25 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
for (i = 0; i < 10; i++) {
unsigned int ch_bits = 0;
for (j = 0; j < channels; j++) {
- unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize);
+ unsigned int mask;
+
+ mask = snd_usb_combine_bytes(bmaControls +
+ csize * (j+1), csize);
if (mask & (1 << i))
ch_bits |= (1 << j);
}
/* audio class v1 controls are never read-only */
- if (ch_bits & 1) /* the first channel must be set (for ease of programming) */
- build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, 0);
+
+ /*
+ * The first channel must be set
+ * (for ease of programming).
+ */
+ if (ch_bits & 1)
+ build_feature_ctl(state, _ftr, ch_bits, i,
+ &iterm, unitid, 0);
if (master_bits & (1 << i))
- build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, 0);
+ build_feature_ctl(state, _ftr, 0, i, &iterm,
+ unitid, 0);
}
} else { /* UAC_VERSION_2 */
for (i = 0; i < ARRAY_SIZE(audio_feature_info); i++) {
@@ -1408,7 +1461,10 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
unsigned int ch_read_only = 0;
for (j = 0; j < channels; j++) {
- unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize);
+ unsigned int mask;
+
+ mask = snd_usb_combine_bytes(bmaControls +
+ csize * (j+1), csize);
if (uac2_control_is_readable(mask, i)) {
ch_bits |= (1 << j);
if (!uac2_control_is_writeable(mask, i))
@@ -1416,12 +1472,22 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
}
}
- /* NOTE: build_feature_ctl() will mark the control read-only if all channels
- * are marked read-only in the descriptors. Otherwise, the control will be
- * reported as writeable, but the driver will not actually issue a write
- * command for read-only channels */
- if (ch_bits & 1) /* the first channel must be set (for ease of programming) */
- build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, ch_read_only);
+ /*
+ * NOTE: build_feature_ctl() will mark the control
+ * read-only if all channels are marked read-only in
+ * the descriptors. Otherwise, the control will be
+ * reported as writeable, but the driver will not
+ * actually issue a write command for read-only
+ * channels.
+ */
+
+ /*
+ * The first channel must be set
+ * (for ease of programming).
+ */
+ if (ch_bits & 1)
+ build_feature_ctl(state, _ftr, ch_bits, i,
+ &iterm, unitid, ch_read_only);
if (uac2_control_is_readable(master_bits, i))
build_feature_ctl(state, _ftr, 0, i, &iterm, unitid,
!uac2_control_is_writeable(master_bits, i));
@@ -1431,7 +1497,6 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
return 0;
}
-
/*
* Mixer Unit
*/
@@ -1442,7 +1507,6 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
* the callbacks are identical with feature unit.
* input channel number (zero based) is given in control field instead.
*/
-
static void build_mixer_unit_ctl(struct mixer_build *state,
struct uac_mixer_unit_descriptor *desc,
int in_pin, int in_ch, int unitid,
@@ -1459,7 +1523,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
return;
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
- if (! cval)
+ if (!cval)
return;
cval->mixer = state->mixer;
@@ -1467,7 +1531,9 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
cval->control = in_ch + 1; /* based on 1 */
cval->val_type = USB_MIXER_S16;
for (i = 0; i < num_outs; i++) {
- if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc, state->mixer->protocol), in_ch, i, num_outs)) {
+ __u8 *c = uac_mixer_unit_bmControls(desc, state->mixer->protocol);
+
+ if (check_matrix_bitmap(c, in_ch, i, num_outs)) {
cval->cmask |= (1 << i);
cval->channels++;
}
@@ -1477,43 +1543,48 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
get_min_max(cval, 0);
kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
- if (! kctl) {
- snd_printk(KERN_ERR "cannot malloc kcontrol\n");
+ if (!kctl) {
+ usb_audio_err(state->chip, "cannot malloc kcontrol\n");
kfree(cval);
return;
}
kctl->private_free = usb_mixer_elem_free;
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
- if (! len)
- len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0);
- if (! len)
+ if (!len)
+ len = get_term_name(state, iterm, kctl->id.name,
+ sizeof(kctl->id.name), 0);
+ if (!len)
len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1);
append_ctl_name(kctl, " Volume");
- snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
+ usb_audio_dbg(state->chip, "[%d] MU [%s] ch = %d, val = %d/%d\n",
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
snd_usb_mixer_add_control(state->mixer, kctl);
}
-
/*
* parse a mixer unit
*/
-static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *raw_desc)
+static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
+ void *raw_desc)
{
struct uac_mixer_unit_descriptor *desc = raw_desc;
struct usb_audio_term iterm;
int input_pins, num_ins, num_outs;
int pin, ich, err;
- if (desc->bLength < 11 || ! (input_pins = desc->bNrInPins) || ! (num_outs = uac_mixer_unit_bNrChannels(desc))) {
- snd_printk(KERN_ERR "invalid MIXER UNIT descriptor %d\n", unitid);
+ if (desc->bLength < 11 || !(input_pins = desc->bNrInPins) ||
+ !(num_outs = uac_mixer_unit_bNrChannels(desc))) {
+ usb_audio_err(state->chip,
+ "invalid MIXER UNIT descriptor %d\n",
+ unitid);
return -EINVAL;
}
/* no bmControls field (e.g. Maya44) -> ignore */
if (desc->bLength <= 10 + input_pins) {
- snd_printdd(KERN_INFO "MU %d has no bmControls field\n", unitid);
+ usb_audio_dbg(state->chip, "MU %d has no bmControls field\n",
+ unitid);
return 0;
}
@@ -1527,12 +1598,14 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *r
if (err < 0)
return err;
num_ins += iterm.channels;
- for (; ich < num_ins; ++ich) {
+ for (; ich < num_ins; ich++) {
int och, ich_has_controls = 0;
- for (och = 0; och < num_outs; ++och) {
- if (check_matrix_bitmap(uac_mixer_unit_bmControls(desc, state->mixer->protocol),
- ich, och, num_outs)) {
+ for (och = 0; och < num_outs; och++) {
+ __u8 *c = uac_mixer_unit_bmControls(desc,
+ state->mixer->protocol);
+
+ if (check_matrix_bitmap(c, ich, och, num_outs)) {
ich_has_controls = 1;
break;
}
@@ -1545,13 +1618,13 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *r
return 0;
}
-
/*
* Processing Unit / Extension Unit
*/
/* get callback for processing/extension unit */
-static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct usb_mixer_elem_info *cval = kcontrol->private_data;
int err, val;
@@ -1569,7 +1642,8 @@ static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_
}
/* put callback for processing/extension unit */
-static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct usb_mixer_elem_info *cval = kcontrol->private_data;
int val, oval, err;
@@ -1598,7 +1672,6 @@ static struct snd_kcontrol_new mixer_procunit_ctl = {
.put = mixer_ctl_procunit_put,
};
-
/*
* predefined data for processing units
*/
@@ -1689,10 +1762,13 @@ static struct procunit_info extunits[] = {
{ USB_XU_DEVICE_OPTIONS, "AnalogueIn Soft Limit", soft_limit_xu_info },
{ 0 }
};
+
/*
* build a processing/extension unit
*/
-static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw_desc, struct procunit_info *list, char *name)
+static int build_audio_procunit(struct mixer_build *state, int unitid,
+ void *raw_desc, struct procunit_info *list,
+ char *name)
{
struct uac_processing_unit_descriptor *desc = raw_desc;
int num_ins = desc->bNrInPins;
@@ -1712,7 +1788,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw
if (desc->bLength < 13 || desc->bLength < 13 + num_ins ||
desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) {
- snd_printk(KERN_ERR "invalid %s descriptor (id %d)\n", name, unitid);
+ usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
return -EINVAL;
}
@@ -1725,22 +1801,20 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw
for (info = list; info && info->type; info++)
if (info->type == type)
break;
- if (! info || ! info->type)
+ if (!info || !info->type)
info = &default_info;
for (valinfo = info->values; valinfo->control; valinfo++) {
__u8 *controls = uac_processing_unit_bmControls(desc, state->mixer->protocol);
- if (! (controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1))))
+ if (!(controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1))))
continue;
map = find_map(state, unitid, valinfo->control);
if (check_ignored_ctl(map))
continue;
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
- if (! cval) {
- snd_printk(KERN_ERR "cannot malloc kcontrol\n");
+ if (!cval)
return -ENOMEM;
- }
cval->mixer = state->mixer;
cval->id = unitid;
cval->control = valinfo->control;
@@ -1757,7 +1831,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw
cval->initialized = 1;
} else {
if (type == USB_XU_CLOCK_RATE) {
- /* E-Mu USB 0404/0202/TrackerPre/0204
+ /*
+ * E-Mu USB 0404/0202/TrackerPre/0204
* samplerate control quirk
*/
cval->min = 0;
@@ -1769,59 +1844,69 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw
}
kctl = snd_ctl_new1(&mixer_procunit_ctl, cval);
- if (! kctl) {
- snd_printk(KERN_ERR "cannot malloc kcontrol\n");
+ if (!kctl) {
kfree(cval);
return -ENOMEM;
}
kctl->private_free = usb_mixer_elem_free;
- if (check_mapped_name(map, kctl->id.name,
- sizeof(kctl->id.name)))
+ if (check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name))) {
/* nothing */ ;
- else if (info->name)
+ } else if (info->name) {
strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name));
- else {
+ } else {
nameid = uac_processing_unit_iProcessing(desc, state->mixer->protocol);
len = 0;
if (nameid)
- len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name));
- if (! len)
+ len = snd_usb_copy_string_desc(state, nameid,
+ kctl->id.name,
+ sizeof(kctl->id.name));
+ if (!len)
strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
}
append_ctl_name(kctl, " ");
append_ctl_name(kctl, valinfo->suffix);
- snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
- cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
- if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0)
+ usb_audio_dbg(state->chip,
+ "[%d] PU [%s] ch = %d, val = %d/%d\n",
+ cval->id, kctl->id.name, cval->channels,
+ cval->min, cval->max);
+
+ err = snd_usb_mixer_add_control(state->mixer, kctl);
+ if (err < 0)
return err;
}
return 0;
}
-
-static int parse_audio_processing_unit(struct mixer_build *state, int unitid, void *raw_desc)
+static int parse_audio_processing_unit(struct mixer_build *state, int unitid,
+ void *raw_desc)
{
- return build_audio_procunit(state, unitid, raw_desc, procunits, "Processing Unit");
+ return build_audio_procunit(state, unitid, raw_desc,
+ procunits, "Processing Unit");
}
-static int parse_audio_extension_unit(struct mixer_build *state, int unitid, void *raw_desc)
+static int parse_audio_extension_unit(struct mixer_build *state, int unitid,
+ void *raw_desc)
{
- /* Note that we parse extension units with processing unit descriptors.
- * That's ok as the layout is the same */
- return build_audio_procunit(state, unitid, raw_desc, extunits, "Extension Unit");
+ /*
+ * Note that we parse extension units with processing unit descriptors.
+ * That's ok as the layout is the same.
+ */
+ return build_audio_procunit(state, unitid, raw_desc,
+ extunits, "Extension Unit");
}
-
/*
* Selector Unit
*/
-/* info callback for selector unit
+/*
+ * info callback for selector unit
* use an enumerator type for routing
*/
-static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
struct usb_mixer_elem_info *cval = kcontrol->private_data;
const char **itemlist = (const char **)kcontrol->private_value;
@@ -1832,7 +1917,8 @@ static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl
}
/* get callback for selector unit */
-static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct usb_mixer_elem_info *cval = kcontrol->private_data;
int val, err;
@@ -1851,7 +1937,8 @@ static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_
}
/* put callback for selector unit */
-static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct usb_mixer_elem_info *cval = kcontrol->private_data;
int val, oval, err;
@@ -1880,8 +1967,8 @@ static struct snd_kcontrol_new mixer_selectunit_ctl = {
.put = mixer_ctl_selector_put,
};
-
-/* private free callback.
+/*
+ * private free callback.
* free both private_data and private_value
*/
static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl)
@@ -1906,7 +1993,8 @@ static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl)
/*
* parse a selector unit
*/
-static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void *raw_desc)
+static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
+ void *raw_desc)
{
struct uac_selector_unit_descriptor *desc = raw_desc;
unsigned int i, nameid, len;
@@ -1917,7 +2005,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
char **namelist;
if (!desc->bNrInPins || desc->bLength < 5 + desc->bNrInPins) {
- snd_printk(KERN_ERR "invalid SELECTOR UNIT descriptor %d\n", unitid);
+ usb_audio_err(state->chip,
+ "invalid SELECTOR UNIT descriptor %d\n", unitid);
return -EINVAL;
}
@@ -1934,10 +2023,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
return 0;
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
- if (! cval) {
- snd_printk(KERN_ERR "cannot malloc kcontrol\n");
+ if (!cval)
return -ENOMEM;
- }
cval->mixer = state->mixer;
cval->id = unitid;
cval->val_type = USB_MIXER_U8;
@@ -1953,8 +2040,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
cval->control = 0;
namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL);
- if (! namelist) {
- snd_printk(KERN_ERR "cannot malloc\n");
+ if (!namelist) {
kfree(cval);
return -ENOMEM;
}
@@ -1963,8 +2049,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
struct usb_audio_term iterm;
len = 0;
namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL);
- if (! namelist[i]) {
- snd_printk(KERN_ERR "cannot malloc\n");
+ if (!namelist[i]) {
while (i--)
kfree(namelist[i]);
kfree(namelist);
@@ -1976,12 +2061,12 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
if (! len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0)
len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0);
if (! len)
- sprintf(namelist[i], "Input %d", i);
+ sprintf(namelist[i], "Input %u", i);
}
kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval);
if (! kctl) {
- snd_printk(KERN_ERR "cannot malloc kcontrol\n");
+ usb_audio_err(state->chip, "cannot malloc kcontrol\n");
kfree(namelist);
kfree(cval);
return -ENOMEM;
@@ -1994,11 +2079,12 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
if (len)
;
else if (nameid)
- snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name));
+ snd_usb_copy_string_desc(state, nameid, kctl->id.name,
+ sizeof(kctl->id.name));
else {
len = get_term_name(state, &state->oterm,
kctl->id.name, sizeof(kctl->id.name), 0);
- if (! len)
+ if (!len)
strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
@@ -2009,7 +2095,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
append_ctl_name(kctl, " Playback Source");
}
- snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
+ usb_audio_dbg(state->chip, "[%d] SU [%s] items = %d\n",
cval->id, kctl->id.name, desc->bNrInPins);
if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0)
return err;
@@ -2017,7 +2103,6 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
return 0;
}
-
/*
* parse an audio unit recursively
*/
@@ -2031,7 +2116,7 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
p1 = find_audio_control_unit(state, unitid);
if (!p1) {
- snd_printk(KERN_ERR "usbaudio: unit %d not found!\n", unitid);
+ usb_audio_err(state->chip, "unit %d not found!\n", unitid);
return -EINVAL;
}
@@ -2061,7 +2146,8 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
case UAC2_EXTENSION_UNIT_V2:
return parse_audio_extension_unit(state, unitid, p1);
default:
- snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
+ usb_audio_err(state->chip,
+ "unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
return -EINVAL;
}
}
@@ -2114,14 +2200,16 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
}
p = NULL;
- while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen,
+ while ((p = snd_usb_find_csint_desc(mixer->hostif->extra,
+ mixer->hostif->extralen,
p, UAC_OUTPUT_TERMINAL)) != NULL) {
if (mixer->protocol == UAC_VERSION_1) {
struct uac1_output_terminal_descriptor *desc = p;
if (desc->bLength < sizeof(*desc))
continue; /* invalid descriptor? */
- set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */
+ /* mark terminal ID as visited */
+ set_bit(desc->bTerminalID, state.unitbitmap);
state.oterm.id = desc->bTerminalID;
state.oterm.type = le16_to_cpu(desc->wTerminalType);
state.oterm.name = desc->iTerminal;
@@ -2133,7 +2221,8 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
if (desc->bLength < sizeof(*desc))
continue; /* invalid descriptor? */
- set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */
+ /* mark terminal ID as visited */
+ set_bit(desc->bTerminalID, state.unitbitmap);
state.oterm.id = desc->bTerminalID;
state.oterm.type = le16_to_cpu(desc->wTerminalType);
state.oterm.name = desc->iTerminal;
@@ -2141,7 +2230,10 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
if (err < 0 && err != -EINVAL)
return err;
- /* for UAC2, use the same approach to also add the clock selectors */
+ /*
+ * For UAC2, use the same approach to also add the
+ * clock selectors
+ */
err = parse_audio_unit(&state, desc->bCSourceID);
if (err < 0 && err != -EINVAL)
return err;
@@ -2209,8 +2301,9 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
__u8 channel = value & 0xff;
if (channel >= MAX_CHANNELS) {
- snd_printk(KERN_DEBUG "%s(): bogus channel number %d\n",
- __func__, channel);
+ usb_audio_dbg(mixer->chip,
+ "%s(): bogus channel number %d\n",
+ __func__, channel);
return;
}
@@ -2239,8 +2332,9 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
break;
default:
- snd_printk(KERN_DEBUG "unknown attribute %d in interrupt\n",
- attribute);
+ usb_audio_dbg(mixer->chip,
+ "unknown attribute %d in interrupt\n",
+ attribute);
break;
} /* switch */
}
@@ -2261,7 +2355,7 @@ static void snd_usb_mixer_interrupt(struct urb *urb)
for (status = urb->transfer_buffer;
len >= sizeof(*status);
len -= sizeof(*status), status++) {
- snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n",
+ dev_dbg(&urb->dev->dev, "status interrupt: %02x %02x\n",
status->bStatusType,
status->bOriginator);
@@ -2293,32 +2387,14 @@ static void snd_usb_mixer_interrupt(struct urb *urb)
}
requeue:
- if (ustatus != -ENOENT && ustatus != -ECONNRESET && ustatus != -ESHUTDOWN) {
+ if (ustatus != -ENOENT &&
+ ustatus != -ECONNRESET &&
+ ustatus != -ESHUTDOWN) {
urb->dev = mixer->chip->dev;
usb_submit_urb(urb, GFP_ATOMIC);
}
}
-/* stop any bus activity of a mixer */
-void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer)
-{
- usb_kill_urb(mixer->urb);
- usb_kill_urb(mixer->rc_urb);
-}
-
-int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
-{
- int err;
-
- if (mixer->urb) {
- err = usb_submit_urb(mixer->urb, GFP_NOIO);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
/* create the handler for the optional status interrupt endpoint */
static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
{
@@ -2393,7 +2469,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
snd_usb_mixer_apply_create_quirk(mixer);
- err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops);
+ err = snd_device_new(chip->card, SNDRV_DEV_CODEC, mixer, &dev_ops);
if (err < 0)
goto _error;
@@ -2417,3 +2493,82 @@ void snd_usb_mixer_disconnect(struct list_head *p)
usb_kill_urb(mixer->urb);
usb_kill_urb(mixer->rc_urb);
}
+
+#ifdef CONFIG_PM
+/* stop any bus activity of a mixer */
+static void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer)
+{
+ usb_kill_urb(mixer->urb);
+ usb_kill_urb(mixer->rc_urb);
+}
+
+static int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
+{
+ int err;
+
+ if (mixer->urb) {
+ err = usb_submit_urb(mixer->urb, GFP_NOIO);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer)
+{
+ snd_usb_mixer_inactivate(mixer);
+ return 0;
+}
+
+static int restore_mixer_value(struct usb_mixer_elem_info *cval)
+{
+ int c, err, idx;
+
+ if (cval->cmask) {
+ idx = 0;
+ for (c = 0; c < MAX_CHANNELS; c++) {
+ if (!(cval->cmask & (1 << c)))
+ continue;
+ if (cval->cached & (1 << c)) {
+ err = set_cur_mix_value(cval, c + 1, idx,
+ cval->cache_val[idx]);
+ if (err < 0)
+ return err;
+ }
+ idx++;
+ }
+ } else {
+ /* master */
+ if (cval->cached) {
+ err = set_cur_mix_value(cval, 0, 0, *cval->cache_val);
+ if (err < 0)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
+{
+ struct usb_mixer_elem_info *cval;
+ int id, err;
+
+ /* FIXME: any mixer quirks? */
+
+ if (reset_resume) {
+ /* restore cached mixer values */
+ for (id = 0; id < MAX_ID_ELEMS; id++) {
+ for (cval = mixer->id_elems[id]; cval;
+ cval = cval->next_id_elem) {
+ err = restore_mixer_value(cval);
+ if (err < 0)
+ return err;
+ }
+ }
+ }
+
+ return snd_usb_mixer_activate(mixer);
+}
+#endif
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index aab80df201b..73b1f649447 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -63,8 +63,6 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
int request, int validx, int value_set);
-void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer);
-int snd_usb_mixer_activate(struct usb_mixer_interface *mixer);
int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
struct snd_kcontrol *kctl);
@@ -72,4 +70,9 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *_tlv);
+#ifdef CONFIG_PM
+int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer);
+int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume);
+#endif
+
#endif /* __USBMIXER_H */
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index cc2dd1f0dec..d1d72ff5034 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -322,6 +322,17 @@ static struct usbmix_name_map hercules_usb51_map[] = {
{ 0 } /* terminator */
};
+/* Plantronics Gamecom 780 has a broken volume control, better to disable it */
+static struct usbmix_name_map gamecom780_map[] = {
+ { 9, NULL }, /* FU, speaker out */
+ {}
+};
+
+static const struct usbmix_name_map kef_x300a_map[] = {
+ { 10, NULL }, /* firmware locks up (?) when we try to access this FU */
+ { 0 }
+};
+
/*
* Control map entries
*/
@@ -358,6 +369,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
.id = USB_ID(0x046d, 0x09a4),
.ignore_ctl_error = 1,
},
+ { /* Plantronics GameCom 780 */
+ .id = USB_ID(0x047f, 0xc010),
+ .map = gamecom780_map,
+ },
{
/* Hercules DJ Console (Windows Edition) */
.id = USB_ID(0x06f8, 0xb000),
@@ -409,6 +424,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
.id = USB_ID(0x200c, 0x1018),
.map = ebox44_map,
},
+ {
+ .id = USB_ID(0x27ac, 0x1000),
+ .map = kef_x300a_map,
+ },
{ 0 } /* terminator */
};
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index d42a584cf82..f119a41ed9a 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -433,6 +433,89 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
}
}
+/* EMU0204 */
+static int snd_emu0204_ch_switch_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static const char *texts[2] = {"1/2",
+ "3/4"
+ };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item > 1)
+ uinfo->value.enumerated.item = 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+
+ return 0;
+}
+
+static int snd_emu0204_ch_switch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.enumerated.item[0] = kcontrol->private_value;
+ return 0;
+}
+
+static int snd_emu0204_ch_switch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+ unsigned int value = ucontrol->value.enumerated.item[0];
+ int err, changed;
+ unsigned char buf[2];
+
+ if (value > 1)
+ return -EINVAL;
+
+ buf[0] = 0x01;
+ buf[1] = value ? 0x02 : 0x01;
+
+ changed = value != kcontrol->private_value;
+ down_read(&mixer->chip->shutdown_rwsem);
+ if (mixer->chip->shutdown) {
+ err = -ENODEV;
+ goto out;
+ }
+ err = snd_usb_ctl_msg(mixer->chip->dev,
+ usb_sndctrlpipe(mixer->chip->dev, 0), UAC_SET_CUR,
+ USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+ 0x0400, 0x0e00, buf, 2);
+ out:
+ up_read(&mixer->chip->shutdown_rwsem);
+ if (err < 0)
+ return err;
+ kcontrol->private_value = value;
+ return changed;
+}
+
+
+static struct snd_kcontrol_new snd_emu0204_controls[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Front Jack Channels",
+ .info = snd_emu0204_ch_switch_info,
+ .get = snd_emu0204_ch_switch_get,
+ .put = snd_emu0204_ch_switch_put,
+ .private_value = 0,
+ },
+};
+
+static int snd_emu0204_controls_create(struct usb_mixer_interface *mixer)
+{
+ int i, err;
+
+ for (i = 0; i < ARRAY_SIZE(snd_emu0204_controls); ++i) {
+ err = snd_ctl_add(mixer->chip->card,
+ snd_ctl_new1(&snd_emu0204_controls[i], mixer));
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
/* ASUS Xonar U1 / U3 controls */
static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol,
@@ -517,8 +600,8 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
up_read(&mixer->chip->shutdown_rwsem);
if (ret < 0) {
- snd_printk(KERN_ERR
- "unable to issue vendor read request (ret = %d)", ret);
+ dev_err(&dev->dev,
+ "unable to issue vendor read request (ret = %d)", ret);
return ret;
}
@@ -548,8 +631,8 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
up_read(&mixer->chip->shutdown_rwsem);
if (ret < 0) {
- snd_printk(KERN_ERR
- "unable to issue vendor write request (ret = %d)", ret);
+ dev_err(&dev->dev,
+ "unable to issue vendor write request (ret = %d)", ret);
return ret;
}
@@ -1520,7 +1603,7 @@ static int snd_microii_controls_create(struct usb_mixer_interface *mixer)
return err;
}
- return err;
+ return 0;
}
int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
@@ -1545,6 +1628,13 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
snd_audigy2nx_proc_read);
break;
+ /* EMU0204 */
+ case USB_ID(0x041e, 0x3f19):
+ err = snd_emu0204_controls_create(mixer);
+ if (err < 0)
+ break;
+ break;
+
case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C400 */
err = snd_c400_create_mixer(mixer);
@@ -1609,7 +1699,7 @@ void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id);
break;
default:
- snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid);
+ usb_audio_dbg(mixer->chip, "memory change in unknown unit %d\n", unitid);
break;
}
}
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index b375d58871e..c62a1659106 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -166,8 +166,8 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep,
data, sizeof(data))) < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n",
- dev->devnum, iface, ep);
+ usb_audio_err(chip, "%d:%d: cannot set enable PITCH\n",
+ iface, ep);
return err;
}
@@ -187,8 +187,8 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface,
USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
UAC2_EP_CS_PITCH << 8, 0,
data, sizeof(data))) < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH (v2)\n",
- dev->devnum, iface, fmt->altsetting);
+ usb_audio_err(chip, "%d:%d: cannot set enable PITCH (v2)\n",
+ iface, fmt->altsetting);
return err;
}
@@ -226,7 +226,7 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep)
if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
struct snd_usb_endpoint *ep = subs->data_endpoint;
- snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep);
+ dev_dbg(&subs->dev->dev, "Starting data EP @%p\n", ep);
ep->data_subs = subs;
err = snd_usb_endpoint_start(ep, can_sleep);
@@ -241,21 +241,21 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep)
struct snd_usb_endpoint *ep = subs->sync_endpoint;
if (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
- subs->data_endpoint->alt_idx != subs->sync_endpoint->alt_idx) {
+ subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting) {
err = usb_set_interface(subs->dev,
subs->sync_endpoint->iface,
- subs->sync_endpoint->alt_idx);
+ subs->sync_endpoint->altsetting);
if (err < 0) {
- snd_printk(KERN_ERR
- "%d:%d:%d: cannot set interface (%d)\n",
- subs->dev->devnum,
+ clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
+ dev_err(&subs->dev->dev,
+ "%d:%d: cannot set interface (%d)\n",
subs->sync_endpoint->iface,
- subs->sync_endpoint->alt_idx, err);
+ subs->sync_endpoint->altsetting, err);
return -EIO;
}
}
- snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep);
+ dev_dbg(&subs->dev->dev, "Starting sync EP @%p\n", ep);
ep->sync_slave = subs->data_endpoint;
err = snd_usb_endpoint_start(ep, can_sleep);
@@ -282,22 +282,6 @@ static void stop_endpoints(struct snd_usb_substream *subs, bool wait)
}
}
-static int deactivate_endpoints(struct snd_usb_substream *subs)
-{
- int reta, retb;
-
- reta = snd_usb_endpoint_deactivate(subs->sync_endpoint);
- retb = snd_usb_endpoint_deactivate(subs->data_endpoint);
-
- if (reta < 0)
- return reta;
-
- if (retb < 0)
- return retb;
-
- return 0;
-}
-
static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
unsigned int altsetting,
struct usb_host_interface **alts,
@@ -425,8 +409,9 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC ||
(get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
get_endpoint(alts, 1)->bSynchAddress != 0)) {
- snd_printk(KERN_ERR "%d:%d:%d : invalid sync pipe. bmAttributes %02x, bLength %d, bSynchAddress %02x\n",
- dev->devnum, fmt->iface, fmt->altsetting,
+ dev_err(&dev->dev,
+ "%d:%d : invalid sync pipe. bmAttributes %02x, bLength %d, bSynchAddress %02x\n",
+ fmt->iface, fmt->altsetting,
get_endpoint(alts, 1)->bmAttributes,
get_endpoint(alts, 1)->bLength,
get_endpoint(alts, 1)->bSynchAddress);
@@ -436,8 +421,9 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
((is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) ||
(!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) {
- snd_printk(KERN_ERR "%d:%d:%d : invalid sync pipe. is_playback %d, ep %02x, bSynchAddress %02x\n",
- dev->devnum, fmt->iface, fmt->altsetting,
+ dev_err(&dev->dev,
+ "%d:%d : invalid sync pipe. is_playback %d, ep %02x, bSynchAddress %02x\n",
+ fmt->iface, fmt->altsetting,
is_playback, ep, get_endpoint(alts, 0)->bSynchAddress);
return -EINVAL;
}
@@ -484,8 +470,9 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
if (subs->interface >= 0 && subs->interface != fmt->iface) {
err = usb_set_interface(subs->dev, subs->interface, 0);
if (err < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed (%d)\n",
- dev->devnum, fmt->iface, fmt->altsetting, err);
+ dev_err(&dev->dev,
+ "%d:%d: return to setting 0 failed (%d)\n",
+ fmt->iface, fmt->altsetting, err);
return -EIO;
}
subs->interface = -1;
@@ -497,12 +484,13 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
subs->altset_idx != fmt->altset_idx) {
err = usb_set_interface(dev, fmt->iface, fmt->altsetting);
if (err < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed (%d)\n",
- dev->devnum, fmt->iface, fmt->altsetting, err);
+ dev_err(&dev->dev,
+ "%d:%d: usb_set_interface failed (%d)\n",
+ fmt->iface, fmt->altsetting, err);
return -EIO;
}
- snd_printdd(KERN_INFO "setting usb interface %d:%d\n",
- fmt->iface, fmt->altsetting);
+ dev_dbg(&dev->dev, "setting usb interface %d:%d\n",
+ fmt->iface, fmt->altsetting);
subs->interface = fmt->iface;
subs->altset_idx = fmt->altset_idx;
@@ -538,20 +526,23 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
* - Requested PCM format is not supported.
* - Requested sample rate is not supported.
*/
-static int match_endpoint_audioformats(struct audioformat *fp,
- struct audioformat *match, int rate,
- snd_pcm_format_t pcm_format)
+static int match_endpoint_audioformats(struct snd_usb_substream *subs,
+ struct audioformat *fp,
+ struct audioformat *match, int rate,
+ snd_pcm_format_t pcm_format)
{
int i;
int score = 0;
if (fp->channels < 1) {
- snd_printdd("%s: (fmt @%p) no channels\n", __func__, fp);
+ dev_dbg(&subs->dev->dev,
+ "%s: (fmt @%p) no channels\n", __func__, fp);
return 0;
}
if (!(fp->formats & pcm_format_to_bits(pcm_format))) {
- snd_printdd("%s: (fmt @%p) no match for format %d\n", __func__,
+ dev_dbg(&subs->dev->dev,
+ "%s: (fmt @%p) no match for format %d\n", __func__,
fp, pcm_format);
return 0;
}
@@ -563,7 +554,8 @@ static int match_endpoint_audioformats(struct audioformat *fp,
}
}
if (!score) {
- snd_printdd("%s: (fmt @%p) no match for rate %d\n", __func__,
+ dev_dbg(&subs->dev->dev,
+ "%s: (fmt @%p) no match for rate %d\n", __func__,
fp, rate);
return 0;
}
@@ -571,7 +563,8 @@ static int match_endpoint_audioformats(struct audioformat *fp,
if (fp->channels == match->channels)
score++;
- snd_printdd("%s: (fmt @%p) score %d\n", __func__, fp, score);
+ dev_dbg(&subs->dev->dev,
+ "%s: (fmt @%p) score %d\n", __func__, fp, score);
return score;
}
@@ -595,13 +588,15 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
subs->pcm_format,
subs->channels,
subs->period_bytes,
+ 0, 0,
subs->cur_rate,
subs->cur_audiofmt,
NULL);
/* Try to find the best matching audioformat. */
list_for_each_entry(fp, &sync_subs->fmt_list, list) {
- int score = match_endpoint_audioformats(fp, subs->cur_audiofmt,
+ int score = match_endpoint_audioformats(subs,
+ fp, subs->cur_audiofmt,
subs->cur_rate, subs->pcm_format);
if (score > cur_score) {
@@ -611,7 +606,8 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
}
if (unlikely(sync_fp == NULL)) {
- snd_printk(KERN_ERR "%s: no valid audioformat for sync ep %x found\n",
+ dev_err(&subs->dev->dev,
+ "%s: no valid audioformat for sync ep %x found\n",
__func__, sync_subs->ep_num);
return -EINVAL;
}
@@ -623,7 +619,8 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
if (sync_fp->channels != subs->channels) {
sync_period_bytes = (subs->period_bytes / subs->channels) *
sync_fp->channels;
- snd_printdd("%s: adjusted sync ep period bytes (%d -> %d)\n",
+ dev_dbg(&subs->dev->dev,
+ "%s: adjusted sync ep period bytes (%d -> %d)\n",
__func__, subs->period_bytes, sync_period_bytes);
}
@@ -631,6 +628,7 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
subs->pcm_format,
sync_fp->channels,
sync_period_bytes,
+ 0, 0,
subs->cur_rate,
sync_fp,
NULL);
@@ -653,6 +651,8 @@ static int configure_endpoint(struct snd_usb_substream *subs)
subs->pcm_format,
subs->channels,
subs->period_bytes,
+ subs->period_frames,
+ subs->buffer_periods,
subs->cur_rate,
subs->cur_audiofmt,
subs->sync_endpoint);
@@ -689,12 +689,15 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
subs->pcm_format = params_format(hw_params);
subs->period_bytes = params_period_bytes(hw_params);
+ subs->period_frames = params_period_size(hw_params);
+ subs->buffer_periods = params_periods(hw_params);
subs->channels = params_channels(hw_params);
subs->cur_rate = params_rate(hw_params);
fmt = find_format(subs);
if (!fmt) {
- snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n",
+ dev_dbg(&subs->dev->dev,
+ "cannot set format: format = %#x, rate = %d, channels = %d\n",
subs->pcm_format, subs->cur_rate, subs->channels);
return -EINVAL;
}
@@ -730,7 +733,8 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
down_read(&subs->stream->chip->shutdown_rwsem);
if (!subs->stream->chip->shutdown) {
stop_endpoints(subs, true);
- deactivate_endpoints(subs);
+ snd_usb_endpoint_deactivate(subs->sync_endpoint);
+ snd_usb_endpoint_deactivate(subs->data_endpoint);
}
up_read(&subs->stream->chip->shutdown_rwsem);
return snd_pcm_lib_free_vmalloc_buffer(substream);
@@ -750,7 +754,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
int ret;
if (! subs->cur_audiofmt) {
- snd_printk(KERN_ERR "usbaudio: no format is specified!\n");
+ dev_err(&subs->dev->dev, "no format is specified!\n");
return -ENXIO;
}
@@ -1243,7 +1247,8 @@ static void retire_capture_urb(struct snd_usb_substream *subs,
for (i = 0; i < urb->number_of_packets; i++) {
cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset + subs->pkt_offset_adj;
if (urb->iso_frame_desc[i].status && printk_ratelimit()) {
- snd_printdd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
+ dev_dbg(&subs->dev->dev, "frame %d active: %d\n",
+ i, urb->iso_frame_desc[i].status);
// continue;
}
bytes = urb->iso_frame_desc[i].actual_length;
@@ -1253,7 +1258,8 @@ static void retire_capture_urb(struct snd_usb_substream *subs,
if (bytes % (runtime->sample_bits >> 3) != 0) {
int oldbytes = bytes;
bytes = frames * stride;
- snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
+ dev_warn(&subs->dev->dev,
+ "Corrected urb data len. %d->%d\n",
oldbytes, bytes);
}
/* update the current pointer */
@@ -1363,6 +1369,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
frames = 0;
urb->number_of_packets = 0;
spin_lock_irqsave(&subs->lock, flags);
+ subs->frame_limit += ep->max_urb_frames;
for (i = 0; i < ctx->packets; i++) {
if (ctx->packet_size[i])
counts = ctx->packet_size[i];
@@ -1377,6 +1384,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
subs->transfer_done += counts;
if (subs->transfer_done >= runtime->period_size) {
subs->transfer_done -= runtime->period_size;
+ subs->frame_limit = 0;
period_elapsed = 1;
if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
if (subs->transfer_done > 0) {
@@ -1399,8 +1407,10 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
break;
}
}
- if (period_elapsed &&
- !snd_usb_endpoint_implicit_feedback_sink(subs->data_endpoint)) /* finish at the period boundary */
+ /* finish at the period boundary or after enough frames */
+ if ((period_elapsed ||
+ subs->transfer_done >= subs->frame_limit) &&
+ !snd_usb_endpoint_implicit_feedback_sink(ep))
break;
}
bytes = frames * ep->stride;
@@ -1492,7 +1502,8 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
* on two reads of a counter updated every ms.
*/
if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
- snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
+ dev_dbg_ratelimited(&subs->dev->dev,
+ "delay: estimated %d, actual %d\n",
est_delay, subs->last_delay);
if (!subs->running) {
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index f5f0595ef9c..f652b10ce90 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -72,22 +72,21 @@
}
},
-/* Creative/Toshiba Multimedia Center SB-0500 */
+/* Creative/E-Mu devices */
{
- USB_DEVICE(0x041e, 0x3048),
+ USB_DEVICE(0x041e, 0x3010),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
- .vendor_name = "Toshiba",
- .product_name = "SB-0500",
+ .vendor_name = "Creative Labs",
+ .product_name = "Sound Blaster MP3+",
.ifnum = QUIRK_NO_INTERFACE
}
},
-
-/* Creative/E-Mu devices */
+/* Creative/Toshiba Multimedia Center SB-0500 */
{
- USB_DEVICE(0x041e, 0x3010),
+ USB_DEVICE(0x041e, 0x3048),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
- .vendor_name = "Creative Labs",
- .product_name = "Sound Blaster MP3+",
+ .vendor_name = "Toshiba",
+ .product_name = "SB-0500",
.ifnum = QUIRK_NO_INTERFACE
}
},
@@ -2521,6 +2520,46 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
+ USB_DEVICE(0x1235, 0x0010),
+ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+ .vendor_name = "Focusrite",
+ .product_name = "Saffire 6 USB",
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 4,
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+ .endpoint = 0x01,
+ .ep_attr = USB_ENDPOINT_XFER_ISOC,
+ .rates = SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000,
+ .rate_min = 44100,
+ .rate_max = 48000,
+ .nr_rates = 2,
+ .rate_table = (unsigned int[]) {
+ 44100, 48000
+ }
+ }
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_MIDI_RAW_BYTES
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
+{
USB_DEVICE(0x1235, 0x0018),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Novation",
@@ -2569,6 +2608,57 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.type = QUIRK_MIDI_NOVATION
}
},
+{
+ /*
+ * Focusrite Scarlett 18i6
+ *
+ * Avoid mixer creation, which otherwise fails because some of
+ * the interface descriptor subtypes for interface 0 are
+ * unknown. That should be fixed or worked-around but this at
+ * least allows the device to be used successfully with a DAW
+ * and an external mixer. See comments below about other
+ * ignored interfaces.
+ */
+ USB_DEVICE(0x1235, 0x8004),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "Focusrite",
+ .product_name = "Scarlett 18i6",
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = & (const struct snd_usb_audio_quirk[]) {
+ {
+ /* InterfaceSubClass 1 (Control Device) */
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ /* InterfaceSubClass 1 (Control Device) */
+ .ifnum = 3,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 4,
+ .type = QUIRK_MIDI_STANDARD_INTERFACE
+ },
+ {
+ /* InterfaceSubClass 1 (Device Firmware Update) */
+ .ifnum = 5,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
/* Access Music devices */
{
@@ -2671,7 +2761,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7240),
+ USB_DEVICE_VENDOR_SPEC(0x2040, 0x7210),
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2679,13 +2769,13 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "Hauppauge",
- .product_name = "HVR-850",
+ .product_name = "HVR-950Q",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_AUDIO_ALIGN_TRANSFER,
}
},
{
- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7210),
+ USB_DEVICE_VENDOR_SPEC(0x2040, 0x7217),
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2699,7 +2789,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7217),
+ USB_DEVICE_VENDOR_SPEC(0x2040, 0x721b),
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2713,7 +2803,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
- USB_DEVICE_VENDOR_SPEC(0x2040, 0x721b),
+ USB_DEVICE_VENDOR_SPEC(0x2040, 0x721e),
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2727,7 +2817,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
- USB_DEVICE_VENDOR_SPEC(0x2040, 0x721e),
+ USB_DEVICE_VENDOR_SPEC(0x2040, 0x721f),
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2741,7 +2831,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
- USB_DEVICE_VENDOR_SPEC(0x2040, 0x721f),
+ USB_DEVICE_VENDOR_SPEC(0x2040, 0x7240),
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2749,7 +2839,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "Hauppauge",
- .product_name = "HVR-950Q",
+ .product_name = "HVR-850",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_AUDIO_ALIGN_TRANSFER,
}
@@ -3054,58 +3144,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/*
- * Focusrite Scarlett 18i6
- *
- * Avoid mixer creation, which otherwise fails because some of
- * the interface descriptor subtypes for interface 0 are
- * unknown. That should be fixed or worked-around but this at
- * least allows the device to be used successfully with a DAW
- * and an external mixer. See comments below about other
- * ignored interfaces.
- */
- USB_DEVICE(0x1235, 0x8004),
- .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
- .vendor_name = "Focusrite",
- .product_name = "Scarlett 18i6",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = & (const struct snd_usb_audio_quirk[]) {
- {
- /* InterfaceSubClass 1 (Control Device) */
- .ifnum = 0,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 1,
- .type = QUIRK_AUDIO_STANDARD_INTERFACE
- },
- {
- .ifnum = 2,
- .type = QUIRK_AUDIO_STANDARD_INTERFACE
- },
- {
- /* InterfaceSubClass 1 (Control Device) */
- .ifnum = 3,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 4,
- .type = QUIRK_MIDI_STANDARD_INTERFACE
- },
- {
- /* InterfaceSubClass 1 (Device Firmware Update) */
- .ifnum = 5,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = -1
- }
- }
- }
-},
-
-{
- /*
* Some USB MIDI devices don't have an audio control interface,
* so we have to grab MIDI streaming interfaces here.
*/
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 0df9ede99df..7c57f2268dd 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -110,7 +110,7 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
altsd = get_iface_desc(alts);
err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber);
if (err < 0) {
- snd_printk(KERN_ERR "cannot setup if %d: error %d\n",
+ usb_audio_err(chip, "cannot setup if %d: error %d\n",
altsd->bInterfaceNumber, err);
return err;
}
@@ -135,7 +135,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL);
if (!fp) {
- snd_printk(KERN_ERR "cannot memdup\n");
+ usb_audio_err(chip, "cannot memdup\n");
return -ENOMEM;
}
if (fp->nr_rates > MAX_NR_RATES) {
@@ -464,7 +464,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
fp->rate_max = fp->rate_min = 96000;
break;
default:
- snd_printk(KERN_ERR "unknown sample rate\n");
+ usb_audio_err(chip, "unknown sample rate\n");
kfree(fp);
return -ENXIO;
}
@@ -536,7 +536,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
if (quirk->type < QUIRK_TYPE_COUNT) {
return quirk_funcs[quirk->type](chip, iface, driver, quirk);
} else {
- snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
+ usb_audio_err(chip, "invalid quirk type %d\n", quirk->type);
return -ENXIO;
}
}
@@ -555,18 +555,21 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
if (le16_to_cpu(get_cfg_desc(config)->wTotalLength) == EXTIGY_FIRMWARE_SIZE_OLD ||
le16_to_cpu(get_cfg_desc(config)->wTotalLength) == EXTIGY_FIRMWARE_SIZE_NEW) {
- snd_printdd("sending Extigy boot sequence...\n");
+ dev_dbg(&dev->dev, "sending Extigy boot sequence...\n");
/* Send message to force it to reconnect with full interface. */
err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev,0),
0x10, 0x43, 0x0001, 0x000a, NULL, 0);
- if (err < 0) snd_printdd("error sending boot message: %d\n", err);
+ if (err < 0)
+ dev_dbg(&dev->dev, "error sending boot message: %d\n", err);
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&dev->descriptor, sizeof(dev->descriptor));
config = dev->actconfig;
- if (err < 0) snd_printdd("error usb_get_descriptor: %d\n", err);
+ if (err < 0)
+ dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
err = usb_reset_configuration(dev);
- if (err < 0) snd_printdd("error usb_reset_configuration: %d\n", err);
- snd_printdd("extigy_boot: new boot length = %d\n",
+ if (err < 0)
+ dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
+ dev_dbg(&dev->dev, "extigy_boot: new boot length = %d\n",
le16_to_cpu(get_cfg_desc(config)->wTotalLength));
return -ENODEV; /* quit this anyway */
}
@@ -594,7 +597,7 @@ static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev)
int err;
if (dev->actconfig->desc.bConfigurationValue == 1) {
- snd_printk(KERN_INFO "usb-audio: "
+ dev_info(&dev->dev,
"Fast Track Pro switching to config #2\n");
/* This function has to be available by the usb core module.
* if it is not avialable the boot quirk has to be left out
@@ -603,14 +606,15 @@ static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev)
*/
err = usb_driver_set_configuration(dev, 2);
if (err < 0)
- snd_printdd("error usb_driver_set_configuration: %d\n",
- err);
+ dev_dbg(&dev->dev,
+ "error usb_driver_set_configuration: %d\n",
+ err);
/* Always return an error, so that we stop creating a device
that will just be destroyed and recreated with a new
configuration */
return -ENODEV;
} else
- snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n");
+ dev_info(&dev->dev, "Fast Track Pro config OK\n");
return 0;
}
@@ -660,10 +664,23 @@ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
return err;
}
+/* quirk for Plantronics GameCom 780 with CM6302 chip */
+static int snd_usb_gamecon780_boot_quirk(struct usb_device *dev)
+{
+ /* set the initial volume and don't change; other values are either
+ * too loud or silent due to firmware bug (bko#65251)
+ */
+ u8 buf[2] = { 0x74, 0xdc };
+ return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
+ USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+ UAC_FU_VOLUME << 8, 9 << 8, buf, 2);
+}
+
/*
* Novation Twitch DJ controller
+ * Focusrite Novation Saffire 6 USB audio card
*/
-static int snd_usb_twitch_boot_quirk(struct usb_device *dev)
+static int snd_usb_novation_boot_quirk(struct usb_device *dev)
{
/* preemptively set up the device because otherwise the
* raw MIDI endpoints are not active */
@@ -766,11 +783,11 @@ static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
fwsize = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
if (fwsize != MBOX2_FIRMWARE_SIZE) {
- snd_printk(KERN_ERR "usb-audio: Invalid firmware size=%d.\n", fwsize);
+ dev_err(&dev->dev, "Invalid firmware size=%d.\n", fwsize);
return -ENODEV;
}
- snd_printd("usb-audio: Sending Digidesign Mbox 2 boot sequence...\n");
+ dev_dbg(&dev->dev, "Sending Digidesign Mbox 2 boot sequence...\n");
count = 0;
bootresponse[0] = MBOX2_BOOT_LOADING;
@@ -781,32 +798,32 @@ static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
0x85, 0xc0, 0x0001, 0x0000, &bootresponse, 0x0012);
if (bootresponse[0] == MBOX2_BOOT_READY)
break;
- snd_printd("usb-audio: device not ready, resending boot sequence...\n");
+ dev_dbg(&dev->dev, "device not ready, resending boot sequence...\n");
count++;
}
if (bootresponse[0] != MBOX2_BOOT_READY) {
- snd_printk(KERN_ERR "usb-audio: Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse[0]);
+ dev_err(&dev->dev, "Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse[0]);
return -ENODEV;
}
- snd_printdd("usb-audio: device initialised!\n");
+ dev_dbg(&dev->dev, "device initialised!\n");
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&dev->descriptor, sizeof(dev->descriptor));
config = dev->actconfig;
if (err < 0)
- snd_printd("error usb_get_descriptor: %d\n", err);
+ dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
err = usb_reset_configuration(dev);
if (err < 0)
- snd_printd("error usb_reset_configuration: %d\n", err);
- snd_printdd("mbox2_boot: new boot length = %d\n",
+ dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
+ dev_dbg(&dev->dev, "mbox2_boot: new boot length = %d\n",
le16_to_cpu(get_cfg_desc(config)->wTotalLength));
mbox2_setup_48_24_magic(dev);
- snd_printk(KERN_INFO "usb-audio: Digidesign Mbox 2: 24bit 48kHz");
+ dev_info(&dev->dev, "Digidesign Mbox 2: 24bit 48kHz");
return 0; /* Successful boot */
}
@@ -852,7 +869,7 @@ static int quattro_skip_setting_quirk(struct snd_usb_audio *chip,
return 1; /* skip this altsetting */
}
}
- snd_printdd(KERN_INFO
+ usb_audio_dbg(chip,
"using altsetting %d for interface %d config %d\n",
altno, iface, chip->setup);
return 0; /* keep this altsetting */
@@ -919,7 +936,7 @@ static int fasttrackpro_skip_setting_quirk(struct snd_usb_audio *chip,
return 1;
}
- snd_printdd(KERN_INFO
+ usb_audio_dbg(chip,
"using altsetting %d for interface %d config %d\n",
altno, iface, chip->setup);
return 0; /* keep this altsetting */
@@ -972,9 +989,9 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
/* Digidesign Mbox 2 */
return snd_usb_mbox2_boot_quirk(dev);
- case USB_ID(0x1235, 0x0018):
- /* Focusrite Novation Twitch */
- return snd_usb_twitch_boot_quirk(dev);
+ case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */
+ case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
+ return snd_usb_novation_boot_quirk(dev);
case USB_ID(0x133e, 0x0815):
/* Access Music VirusTI Desktop */
@@ -986,6 +1003,8 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
return snd_usb_nativeinstruments_boot_quirk(dev);
case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */
return snd_usb_fasttrackpro_boot_quirk(dev);
+ case USB_ID(0x047f, 0xc010): /* Plantronics Gamecom 780 */
+ return snd_usb_gamecon780_boot_quirk(dev);
}
return 0;
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index c4339f97226..310a3822d2b 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -273,16 +273,14 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
SNDRV_CHMAP_TSL, /* top side left */
SNDRV_CHMAP_TSR, /* top side right */
SNDRV_CHMAP_BC, /* bottom center */
- SNDRV_CHMAP_BLC, /* bottom left center */
- SNDRV_CHMAP_BRC, /* bottom right center */
+ SNDRV_CHMAP_RLC, /* back left of center */
+ SNDRV_CHMAP_RRC, /* back right of center */
0 /* terminator */
};
struct snd_pcm_chmap_elem *chmap;
const unsigned int *maps;
int c;
- if (!bits)
- return NULL;
if (channels > ARRAY_SIZE(chmap->map))
return NULL;
@@ -293,9 +291,19 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps;
chmap->channels = channels;
c = 0;
- for (; bits && *maps; maps++, bits >>= 1) {
- if (bits & 1)
- chmap->map[c++] = *maps;
+
+ if (bits) {
+ for (; bits && *maps; maps++, bits >>= 1)
+ if (bits & 1)
+ chmap->map[c++] = *maps;
+ } else {
+ /* If we're missing wChannelConfig, then guess something
+ to make sure the channel map is not skipped entirely */
+ if (channels == 1)
+ chmap->map[c++] = SNDRV_CHMAP_MONO;
+ else
+ for (; c < channels && *maps; maps++)
+ chmap->map[c++] = *maps;
}
for (; c < channels; c++)
@@ -403,10 +411,9 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
if (!csep || csep->bLength < 7 ||
csep->bDescriptorSubtype != UAC_EP_GENERAL) {
- snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
- " class specific endpoint descriptor\n",
- chip->dev->devnum, iface_no,
- altsd->bAlternateSetting);
+ usb_audio_warn(chip,
+ "%u:%d : no or invalid class specific endpoint descriptor\n",
+ iface_no, altsd->bAlternateSetting);
return 0;
}
@@ -525,8 +532,8 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
/* get audio formats */
switch (protocol) {
default:
- snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n",
- dev->devnum, iface_no, altno, protocol);
+ dev_dbg(&dev->dev, "%u:%d: unknown interface protocol %#02x, assuming v1\n",
+ iface_no, altno, protocol);
protocol = UAC_VERSION_1;
/* fall through */
@@ -536,14 +543,16 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
struct uac_input_terminal_descriptor *iterm;
if (!as) {
- snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
- dev->devnum, iface_no, altno);
+ dev_err(&dev->dev,
+ "%u:%d : UAC_AS_GENERAL descriptor not found\n",
+ iface_no, altno);
continue;
}
if (as->bLength < sizeof(*as)) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
- dev->devnum, iface_no, altno);
+ dev_err(&dev->dev,
+ "%u:%d : invalid UAC_AS_GENERAL desc\n",
+ iface_no, altno);
continue;
}
@@ -566,19 +575,22 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
if (!as) {
- snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
- dev->devnum, iface_no, altno);
+ dev_err(&dev->dev,
+ "%u:%d : UAC_AS_GENERAL descriptor not found\n",
+ iface_no, altno);
continue;
}
if (as->bLength < sizeof(*as)) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
- dev->devnum, iface_no, altno);
+ dev_err(&dev->dev,
+ "%u:%d : invalid UAC_AS_GENERAL desc\n",
+ iface_no, altno);
continue;
}
num_channels = as->bNrChannels;
format = le32_to_cpu(as->bmFormats);
+ chconfig = le32_to_cpu(as->bmChannelConfig);
/* lookup the terminal associated to this interface
* to extract the clock */
@@ -586,7 +598,8 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
as->bTerminalLink);
if (input_term) {
clock = input_term->bCSourceID;
- chconfig = le32_to_cpu(input_term->bmChannelConfig);
+ if (!chconfig && (num_channels == input_term->bNrChannels))
+ chconfig = le32_to_cpu(input_term->bmChannelConfig);
break;
}
@@ -597,8 +610,9 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
break;
}
- snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n",
- dev->devnum, iface_no, altno, as->bTerminalLink);
+ dev_err(&dev->dev,
+ "%u:%d : bogus bTerminalLink %d\n",
+ iface_no, altno, as->bTerminalLink);
continue;
}
}
@@ -606,14 +620,16 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
/* get format type */
fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE);
if (!fmt) {
- snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n",
- dev->devnum, iface_no, altno);
+ dev_err(&dev->dev,
+ "%u:%d : no UAC_FORMAT_TYPE desc\n",
+ iface_no, altno);
continue;
}
if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
- dev->devnum, iface_no, altno);
+ dev_err(&dev->dev,
+ "%u:%d : invalid UAC_FORMAT_TYPE desc\n",
+ iface_no, altno);
continue;
}
@@ -634,7 +650,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
fp = kzalloc(sizeof(*fp), GFP_KERNEL);
if (! fp) {
- snd_printk(KERN_ERR "cannot malloc\n");
+ dev_err(&dev->dev, "cannot malloc\n");
return -ENOMEM;
}
@@ -652,7 +668,6 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
* (fp->maxpacksize & 0x7ff);
fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
fp->clock = clock;
- fp->chmap = convert_chmap(num_channels, chconfig, protocol);
/* some quirks for attributes here */
@@ -688,13 +703,17 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
/* ok, let's parse further... */
if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream) < 0) {
kfree(fp->rate_table);
- kfree(fp->chmap);
kfree(fp);
fp = NULL;
continue;
}
- snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
+ /* Create chmap */
+ if (fp->channels != num_channels)
+ chconfig = 0;
+ fp->chmap = convert_chmap(fp->channels, chconfig, protocol);
+
+ dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint);
err = snd_usb_add_audio_stream(chip, stream, fp);
if (err < 0) {
kfree(fp->rate_table);
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index caabe9b3af4..91d0380431b 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -40,6 +40,7 @@ struct snd_usb_audio {
struct rw_semaphore shutdown_rwsem;
unsigned int shutdown:1;
unsigned int probing:1;
+ unsigned int in_pm:1;
unsigned int autosuspended:1;
unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
@@ -55,12 +56,20 @@ struct snd_usb_audio {
struct list_head mixer_list; /* list of mixer interfaces */
int setup; /* from the 'device_setup' module param */
- int nrpacks; /* from the 'nrpacks' module param */
bool autoclock; /* from the 'autoclock' module param */
struct usb_host_interface *ctrl_intf; /* the audio control interface */
};
+#define usb_audio_err(chip, fmt, args...) \
+ dev_err(&(chip)->dev->dev, fmt, ##args)
+#define usb_audio_warn(chip, fmt, args...) \
+ dev_warn(&(chip)->dev->dev, fmt, ##args)
+#define usb_audio_info(chip, fmt, args...) \
+ dev_info(&(chip)->dev->dev, fmt, ##args)
+#define usb_audio_dbg(chip, fmt, args...) \
+ dev_dbg(&(chip)->dev->dev, fmt, ##args)
+
/*
* Information about devices with broken descriptors
*/
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index d0323a693ba..cf5dc33f4a6 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -262,7 +262,9 @@ static int usb_stream_hwdep_mmap(struct snd_hwdep *hw,
}
area->vm_ops = &usb_stream_hwdep_vm_ops;
- area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+ area->vm_flags |= VM_DONTDUMP;
+ if (!read)
+ area->vm_flags |= VM_DONTEXPAND;
area->vm_private_data = us122l;
atomic_inc(&us122l->mmap_count);
out:
@@ -533,7 +535,9 @@ static void snd_us122l_free(struct snd_card *card)
snd_us122l_card_used[index] = 0;
}
-static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp)
+static int usx2y_create_card(struct usb_device *device,
+ struct usb_interface *intf,
+ struct snd_card **cardp)
{
int dev;
struct snd_card *card;
@@ -544,8 +548,8 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp)
break;
if (dev >= SNDRV_CARDS)
return -ENODEV;
- err = snd_card_create(index[dev], id[dev], THIS_MODULE,
- sizeof(struct us122l), &card);
+ err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct us122l), &card);
if (err < 0)
return err;
snd_us122l_card_used[US122L(card)->card_index = dev] = 1;
@@ -576,11 +580,10 @@ static int us122l_usb_probe(struct usb_interface *intf,
struct snd_card *card;
int err;
- err = usx2y_create_card(device, &card);
+ err = usx2y_create_card(device, intf, &card);
if (err < 0)
return err;
- snd_card_set_dev(card, &intf->dev);
if (!us122l_create_card(card)) {
snd_card_free(card);
return -EINVAL;
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index 5a51b18c50f..91e0e2a4808 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -332,7 +332,9 @@ static struct usb_device_id snd_usX2Y_usb_id_table[] = {
{ /* terminator */ }
};
-static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp)
+static int usX2Y_create_card(struct usb_device *device,
+ struct usb_interface *intf,
+ struct snd_card **cardp)
{
int dev;
struct snd_card * card;
@@ -343,15 +345,15 @@ static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp)
break;
if (dev >= SNDRV_CARDS)
return -ENODEV;
- err = snd_card_create(index[dev], id[dev], THIS_MODULE,
- sizeof(struct usX2Ydev), &card);
+ err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE,
+ sizeof(struct usX2Ydev), &card);
if (err < 0)
return err;
snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1;
card->private_free = snd_usX2Y_card_private_free;
usX2Y(card)->dev = device;
init_waitqueue_head(&usX2Y(card)->prepare_wait_queue);
- mutex_init(&usX2Y(card)->prepare_mutex);
+ mutex_init(&usX2Y(card)->pcm_mutex);
INIT_LIST_HEAD(&usX2Y(card)->midi_list);
strcpy(card->driver, "USB "NAME_ALLCAPS"");
sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
@@ -382,10 +384,9 @@ static int usX2Y_usb_probe(struct usb_device *device,
le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428))
return -EINVAL;
- err = usX2Y_create_card(device, &card);
+ err = usX2Y_create_card(device, intf, &card);
if (err < 0)
return err;
- snd_card_set_dev(card, &intf->dev);
if ((err = usX2Y_hwdep_new(card, device)) < 0 ||
(err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h
index e43c0a86441..6ae6b080693 100644
--- a/sound/usb/usx2y/usbusx2y.h
+++ b/sound/usb/usx2y/usbusx2y.h
@@ -36,7 +36,7 @@ struct usX2Ydev {
unsigned int rate,
format;
int chip_status;
- struct mutex prepare_mutex;
+ struct mutex pcm_mutex;
struct us428ctls_sharedmem *us428ctls_sharedmem;
int wait_iso_frame;
wait_queue_head_t us428ctls_wait_queue_head;
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 63fb5219f0f..a63330dd140 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -299,19 +299,6 @@ static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y,
usX2Y_clients_stop(usX2Y);
}
-static void usX2Y_error_sequence(struct usX2Ydev *usX2Y,
- struct snd_usX2Y_substream *subs, struct urb *urb)
-{
- snd_printk(KERN_ERR
-"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n"
-"Most probably some urb of usb-frame %i is still missing.\n"
-"Cause could be too long delays in usb-hcd interrupt handling.\n",
- usb_get_current_frame_number(usX2Y->dev),
- subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
- usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame);
- usX2Y_clients_stop(usX2Y);
-}
-
static void i_usX2Y_urb_complete(struct urb *urb)
{
struct snd_usX2Y_substream *subs = urb->context;
@@ -328,12 +315,9 @@ static void i_usX2Y_urb_complete(struct urb *urb)
usX2Y_error_urb_status(usX2Y, subs, urb);
return;
}
- if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF)))
- subs->completed_urb = urb;
- else {
- usX2Y_error_sequence(usX2Y, subs, urb);
- return;
- }
+
+ subs->completed_urb = urb;
+
{
struct snd_usX2Y_substream *capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE],
*playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
@@ -768,36 +752,44 @@ static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream,
unsigned int rate = params_rate(hw_params);
snd_pcm_format_t format = params_format(hw_params);
struct snd_card *card = substream->pstr->pcm->card;
- struct list_head *list;
+ struct usX2Ydev *dev = usX2Y(card);
+ int i;
+ mutex_lock(&usX2Y(card)->pcm_mutex);
snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params);
- // all pcm substreams off one usX2Y have to operate at the same rate & format
- list_for_each(list, &card->devices) {
- struct snd_device *dev;
- struct snd_pcm *pcm;
- int s;
- dev = snd_device(list);
- if (dev->type != SNDRV_DEV_PCM)
+ /* all pcm substreams off one usX2Y have to operate at the same
+ * rate & format
+ */
+ for (i = 0; i < dev->pcm_devs * 2; i++) {
+ struct snd_usX2Y_substream *subs = dev->subs[i];
+ struct snd_pcm_substream *test_substream;
+
+ if (!subs)
+ continue;
+ test_substream = subs->pcm_substream;
+ if (!test_substream || test_substream == substream ||
+ !test_substream->runtime)
continue;
- pcm = dev->device_data;
- for (s = 0; s < 2; ++s) {
- struct snd_pcm_substream *test_substream;
- test_substream = pcm->streams[s].substream;
- if (test_substream && test_substream != substream &&
- test_substream->runtime &&
- ((test_substream->runtime->format &&
- test_substream->runtime->format != format) ||
- (test_substream->runtime->rate &&
- test_substream->runtime->rate != rate)))
- return -EINVAL;
+ if ((test_substream->runtime->format &&
+ test_substream->runtime->format != format) ||
+ (test_substream->runtime->rate &&
+ test_substream->runtime->rate != rate)) {
+ err = -EINVAL;
+ goto error;
}
}
- if (0 > (err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)))) {
+
+ err = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ if (err < 0) {
snd_printk(KERN_ERR "snd_pcm_lib_malloc_pages(%p, %i) returned %i\n",
substream, params_buffer_bytes(hw_params), err);
- return err;
+ goto error;
}
- return 0;
+
+ error:
+ mutex_unlock(&usX2Y(card)->pcm_mutex);
+ return err;
}
/*
@@ -807,7 +799,7 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_usX2Y_substream *subs = runtime->private_data;
- mutex_lock(&subs->usX2Y->prepare_mutex);
+ mutex_lock(&subs->usX2Y->pcm_mutex);
snd_printdd("snd_usX2Y_hw_free(%p)\n", substream);
if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
@@ -828,7 +820,7 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream)
usX2Y_urbs_release(subs);
}
}
- mutex_unlock(&subs->usX2Y->prepare_mutex);
+ mutex_unlock(&subs->usX2Y->pcm_mutex);
return snd_pcm_lib_free_pages(substream);
}
/*
@@ -845,7 +837,7 @@ static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream)
int err = 0;
snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream);
- mutex_lock(&usX2Y->prepare_mutex);
+ mutex_lock(&usX2Y->pcm_mutex);
usX2Y_subs_prepare(subs);
// Start hardware streams
// SyncStream first....
@@ -865,7 +857,7 @@ static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream)
err = usX2Y_urbs_start(subs);
up_prepare_mutex:
- mutex_unlock(&usX2Y->prepare_mutex);
+ mutex_unlock(&usX2Y->pcm_mutex);
return err;
}
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index f2a1acdc4d8..90766a92e7f 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -244,13 +244,8 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb)
usX2Y_error_urb_status(usX2Y, subs, urb);
return;
}
- if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF)))
- subs->completed_urb = urb;
- else {
- usX2Y_error_sequence(usX2Y, subs, urb);
- return;
- }
+ subs->completed_urb = urb;
capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
capsubs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
@@ -363,7 +358,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_usX2Y_substream *subs = runtime->private_data,
*cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
- mutex_lock(&subs->usX2Y->prepare_mutex);
+ mutex_lock(&subs->usX2Y->pcm_mutex);
snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream);
if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
@@ -392,7 +387,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream)
usX2Y_usbpcm_urbs_release(cap_subs2);
}
}
- mutex_unlock(&subs->usX2Y->prepare_mutex);
+ mutex_unlock(&subs->usX2Y->pcm_mutex);
return snd_pcm_lib_free_pages(substream);
}
@@ -498,7 +493,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream)
memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm));
}
- mutex_lock(&usX2Y->prepare_mutex);
+ mutex_lock(&usX2Y->pcm_mutex);
usX2Y_subs_prepare(subs);
// Start hardware streams
// SyncStream first....
@@ -539,7 +534,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream)
usX2Y->hwdep_pcm_shm->capture_iso_start = -1;
up_prepare_mutex:
- mutex_unlock(&usX2Y->prepare_mutex);
+ mutex_unlock(&usX2Y->pcm_mutex);
return err;
}
@@ -605,59 +600,30 @@ static struct snd_pcm_ops snd_usX2Y_usbpcm_ops =
};
-static int usX2Y_pcms_lock_check(struct snd_card *card)
+static int usX2Y_pcms_busy_check(struct snd_card *card)
{
- struct list_head *list;
- struct snd_device *dev;
- struct snd_pcm *pcm;
- int err = 0;
- list_for_each(list, &card->devices) {
- dev = snd_device(list);
- if (dev->type != SNDRV_DEV_PCM)
- continue;
- pcm = dev->device_data;
- mutex_lock(&pcm->open_mutex);
- }
- list_for_each(list, &card->devices) {
- int s;
- dev = snd_device(list);
- if (dev->type != SNDRV_DEV_PCM)
- continue;
- pcm = dev->device_data;
- for (s = 0; s < 2; ++s) {
- struct snd_pcm_substream *substream;
- substream = pcm->streams[s].substream;
- if (substream && SUBSTREAM_BUSY(substream))
- err = -EBUSY;
- }
- }
- return err;
-}
-
+ struct usX2Ydev *dev = usX2Y(card);
+ int i;
-static void usX2Y_pcms_unlock(struct snd_card *card)
-{
- struct list_head *list;
- struct snd_device *dev;
- struct snd_pcm *pcm;
- list_for_each(list, &card->devices) {
- dev = snd_device(list);
- if (dev->type != SNDRV_DEV_PCM)
- continue;
- pcm = dev->device_data;
- mutex_unlock(&pcm->open_mutex);
+ for (i = 0; i < dev->pcm_devs * 2; i++) {
+ struct snd_usX2Y_substream *subs = dev->subs[i];
+ if (subs && subs->pcm_substream &&
+ SUBSTREAM_BUSY(subs->pcm_substream))
+ return -EBUSY;
}
+ return 0;
}
-
static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file)
{
- // we need to be the first
struct snd_card *card = hw->card;
- int err = usX2Y_pcms_lock_check(card);
- if (0 == err)
+ int err;
+
+ mutex_lock(&usX2Y(card)->pcm_mutex);
+ err = usX2Y_pcms_busy_check(card);
+ if (!err)
usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS;
- usX2Y_pcms_unlock(card);
+ mutex_unlock(&usX2Y(card)->pcm_mutex);
return err;
}
@@ -665,10 +631,13 @@ static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file)
static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file)
{
struct snd_card *card = hw->card;
- int err = usX2Y_pcms_lock_check(card);
- if (0 == err)
+ int err;
+
+ mutex_lock(&usX2Y(card)->pcm_mutex);
+ err = usX2Y_pcms_busy_check(card);
+ if (!err)
usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS;
- usX2Y_pcms_unlock(card);
+ mutex_unlock(&usX2Y(card)->pcm_mutex);
return err;
}