summaryrefslogtreecommitdiff
path: root/sound/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/misc/ua101.c28
-rw-r--r--sound/usb/mixer.c120
2 files changed, 90 insertions, 58 deletions
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index 67bec761244..c0609c21030 100644
--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -459,7 +459,8 @@ static void kill_stream_urbs(struct ua101_stream *stream)
unsigned int i;
for (i = 0; i < stream->queue_length; ++i)
- usb_kill_urb(&stream->urbs[i]->urb);
+ if (stream->urbs[i])
+ usb_kill_urb(&stream->urbs[i]->urb);
}
static int enable_iso_interface(struct ua101 *ua, unsigned int intf_index)
@@ -484,6 +485,9 @@ static void disable_iso_interface(struct ua101 *ua, unsigned int intf_index)
{
struct usb_host_interface *alts;
+ if (!ua->intf[intf_index])
+ return;
+
alts = ua->intf[intf_index]->cur_altsetting;
if (alts->desc.bAlternateSetting != 0) {
int err = usb_set_interface(ua->dev,
@@ -1144,27 +1148,37 @@ static void free_stream_urbs(struct ua101_stream *stream)
{
unsigned int i;
- for (i = 0; i < stream->queue_length; ++i)
+ for (i = 0; i < stream->queue_length; ++i) {
kfree(stream->urbs[i]);
+ stream->urbs[i] = NULL;
+ }
}
static void free_usb_related_resources(struct ua101 *ua,
struct usb_interface *interface)
{
unsigned int i;
+ struct usb_interface *intf;
+ mutex_lock(&ua->mutex);
free_stream_urbs(&ua->capture);
free_stream_urbs(&ua->playback);
+ mutex_unlock(&ua->mutex);
free_stream_buffers(ua, &ua->capture);
free_stream_buffers(ua, &ua->playback);
- for (i = 0; i < ARRAY_SIZE(ua->intf); ++i)
- if (ua->intf[i]) {
- usb_set_intfdata(ua->intf[i], NULL);
- if (ua->intf[i] != interface)
+ for (i = 0; i < ARRAY_SIZE(ua->intf); ++i) {
+ mutex_lock(&ua->mutex);
+ intf = ua->intf[i];
+ ua->intf[i] = NULL;
+ mutex_unlock(&ua->mutex);
+ if (intf) {
+ usb_set_intfdata(intf, NULL);
+ if (intf != interface)
usb_driver_release_interface(&ua101_driver,
- ua->intf[i]);
+ intf);
}
+ }
}
static void ua101_card_free(struct snd_card *card)
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index cdd19d7fe50..0de7cbd99ea 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -765,10 +765,60 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
* interface to ALSA control for feature/mixer units
*/
+/* volume control quirks */
+static void volume_control_quirks(struct usb_mixer_elem_info *cval,
+ struct snd_kcontrol *kctl)
+{
+ switch (cval->mixer->chip->usb_id) {
+ case USB_ID(0x0471, 0x0101):
+ case USB_ID(0x0471, 0x0104):
+ case USB_ID(0x0471, 0x0105):
+ case USB_ID(0x0672, 0x1041):
+ /* quirk for UDA1321/N101.
+ * note that detection between firmware 2.1.1.7 (N101)
+ * and later 2.1.1.21 is not very clear from datasheets.
+ * I hope that the min value is -15360 for newer firmware --jk
+ */
+ if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
+ cval->min == -15616) {
+ snd_printk(KERN_INFO
+ "set volume quirk for UDA1321/N101 chip\n");
+ cval->max = -256;
+ }
+ break;
+
+ case USB_ID(0x046d, 0x09a4):
+ if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
+ snd_printk(KERN_INFO
+ "set volume quirk for QuickCam E3500\n");
+ cval->min = 6080;
+ cval->max = 8768;
+ cval->res = 192;
+ }
+ break;
+
+ case USB_ID(0x046d, 0x0808):
+ case USB_ID(0x046d, 0x0809):
+ case USB_ID(0x046d, 0x0991):
+ /* Most audio usb devices lie about volume resolution.
+ * Most Logitech webcams have res = 384.
+ * Proboly there is some logitech magic behind this number --fishor
+ */
+ if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
+ snd_printk(KERN_INFO
+ "set resolution quirk: cval->res = 384\n");
+ cval->res = 384;
+ }
+ break;
+
+ }
+}
+
/*
* retrieve the minimum and maximum values for the specified control
*/
-static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
+static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
+ int default_min, struct snd_kcontrol *kctl)
{
/* for failsafe */
cval->min = default_min;
@@ -844,6 +894,9 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
cval->initialized = 1;
}
+ if (kctl)
+ volume_control_quirks(cval, kctl);
+
/* USB descriptions contain the dB scale in 1/256 dB unit
* while ALSA TLV contains in 1/100 dB unit
*/
@@ -864,6 +917,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
return 0;
}
+#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)
@@ -881,8 +935,17 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 1;
} else {
- if (! cval->initialized)
- get_min_max(cval, 0);
+ if (!cval->initialized) {
+ get_min_max_with_quirks(cval, 0, kcontrol);
+ if (cval->initialized && cval->dBmin >= cval->dBmax) {
+ kcontrol->vd[0].access &=
+ ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
+ snd_ctl_notify(cval->mixer->chip->card,
+ SNDRV_CTL_EVENT_MASK_INFO,
+ &kcontrol->id);
+ }
+ }
uinfo->value.integer.min = 0;
uinfo->value.integer.max =
(cval->max - cval->min + cval->res - 1) / cval->res;
@@ -1036,9 +1099,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
cval->ch_readonly = readonly_mask;
}
- /* get min/max values */
- get_min_max(cval, 0);
-
/* 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. */
@@ -1060,6 +1120,9 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
len = snd_usb_copy_string_desc(state, nameid,
kctl->id.name, sizeof(kctl->id.name));
+ /* get min/max values */
+ get_min_max_with_quirks(cval, 0, kctl);
+
switch (control) {
case UAC_FU_MUTE:
case UAC_FU_VOLUME:
@@ -1109,51 +1172,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
break;
}
- /* volume control quirks */
- switch (state->chip->usb_id) {
- case USB_ID(0x0471, 0x0101):
- case USB_ID(0x0471, 0x0104):
- case USB_ID(0x0471, 0x0105):
- case USB_ID(0x0672, 0x1041):
- /* quirk for UDA1321/N101.
- * note that detection between firmware 2.1.1.7 (N101)
- * and later 2.1.1.21 is not very clear from datasheets.
- * I hope that the min value is -15360 for newer firmware --jk
- */
- if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
- cval->min == -15616) {
- snd_printk(KERN_INFO
- "set volume quirk for UDA1321/N101 chip\n");
- cval->max = -256;
- }
- break;
-
- case USB_ID(0x046d, 0x09a4):
- if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- snd_printk(KERN_INFO
- "set volume quirk for QuickCam E3500\n");
- cval->min = 6080;
- cval->max = 8768;
- cval->res = 192;
- }
- break;
-
- case USB_ID(0x046d, 0x0808):
- case USB_ID(0x046d, 0x0809):
- case USB_ID(0x046d, 0x0991):
- /* Most audio usb devices lie about volume resolution.
- * Most Logitech webcams have res = 384.
- * Proboly there is some logitech magic behind this number --fishor
- */
- if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- snd_printk(KERN_INFO
- "set resolution quirk: cval->res = 384\n");
- cval->res = 384;
- }
- break;
-
- }
-
range = (cval->max - cval->min) / cval->res;
/* 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