diff options
Diffstat (limited to 'sound/usb/mixer.c')
-rw-r--r-- | sound/usb/mixer.c | 69 |
1 files changed, 63 insertions, 6 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 7df89b3d7ded..5e4775716607 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include "mixer.h" | 61 | #include "mixer.h" |
62 | #include "helper.h" | 62 | #include "helper.h" |
63 | #include "mixer_quirks.h" | 63 | #include "mixer_quirks.h" |
64 | #include "power.h" | ||
64 | 65 | ||
65 | #define MAX_ID_ELEMS 256 | 66 | #define MAX_ID_ELEMS 256 |
66 | 67 | ||
@@ -95,7 +96,7 @@ enum { | |||
95 | }; | 96 | }; |
96 | 97 | ||
97 | 98 | ||
98 | /*E-mu 0202(0404) eXtension Unit(XU) control*/ | 99 | /*E-mu 0202/0404/0204 eXtension Unit(XU) control*/ |
99 | enum { | 100 | enum { |
100 | USB_XU_CLOCK_RATE = 0xe301, | 101 | USB_XU_CLOCK_RATE = 0xe301, |
101 | USB_XU_CLOCK_SOURCE = 0xe302, | 102 | USB_XU_CLOCK_SOURCE = 0xe302, |
@@ -295,16 +296,22 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v | |||
295 | unsigned char buf[2]; | 296 | unsigned char buf[2]; |
296 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 297 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
297 | int timeout = 10; | 298 | int timeout = 10; |
299 | int err; | ||
298 | 300 | ||
301 | err = snd_usb_autoresume(cval->mixer->chip); | ||
302 | if (err < 0) | ||
303 | return -EIO; | ||
299 | while (timeout-- > 0) { | 304 | while (timeout-- > 0) { |
300 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, | 305 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, |
301 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 306 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
302 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 307 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
303 | buf, val_len, 100) >= val_len) { | 308 | buf, val_len, 100) >= val_len) { |
304 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); | 309 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); |
310 | snd_usb_autosuspend(cval->mixer->chip); | ||
305 | return 0; | 311 | return 0; |
306 | } | 312 | } |
307 | } | 313 | } |
314 | snd_usb_autosuspend(cval->mixer->chip); | ||
308 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 315 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
309 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); | 316 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); |
310 | return -EINVAL; | 317 | return -EINVAL; |
@@ -328,12 +335,18 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v | |||
328 | 335 | ||
329 | memset(buf, 0, sizeof(buf)); | 336 | memset(buf, 0, sizeof(buf)); |
330 | 337 | ||
338 | ret = snd_usb_autoresume(chip) ? -EIO : 0; | ||
339 | if (ret) | ||
340 | goto error; | ||
341 | |||
331 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, | 342 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, |
332 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 343 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
333 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 344 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
334 | buf, size, 1000); | 345 | buf, size, 1000); |
346 | snd_usb_autosuspend(chip); | ||
335 | 347 | ||
336 | if (ret < 0) { | 348 | if (ret < 0) { |
349 | error: | ||
337 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 350 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
338 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); | 351 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); |
339 | return ret; | 352 | return ret; |
@@ -413,7 +426,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
413 | { | 426 | { |
414 | struct snd_usb_audio *chip = cval->mixer->chip; | 427 | struct snd_usb_audio *chip = cval->mixer->chip; |
415 | unsigned char buf[2]; | 428 | unsigned char buf[2]; |
416 | int val_len, timeout = 10; | 429 | int val_len, err, timeout = 10; |
417 | 430 | ||
418 | if (cval->mixer->protocol == UAC_VERSION_1) { | 431 | if (cval->mixer->protocol == UAC_VERSION_1) { |
419 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 432 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
@@ -433,13 +446,19 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
433 | value_set = convert_bytes_value(cval, value_set); | 446 | value_set = convert_bytes_value(cval, value_set); |
434 | buf[0] = value_set & 0xff; | 447 | buf[0] = value_set & 0xff; |
435 | buf[1] = (value_set >> 8) & 0xff; | 448 | buf[1] = (value_set >> 8) & 0xff; |
449 | err = snd_usb_autoresume(chip); | ||
450 | if (err < 0) | ||
451 | return -EIO; | ||
436 | while (timeout-- > 0) | 452 | while (timeout-- > 0) |
437 | if (snd_usb_ctl_msg(chip->dev, | 453 | if (snd_usb_ctl_msg(chip->dev, |
438 | usb_sndctrlpipe(chip->dev, 0), request, | 454 | usb_sndctrlpipe(chip->dev, 0), request, |
439 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 455 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
440 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 456 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
441 | buf, val_len, 100) >= 0) | 457 | buf, val_len, 100) >= 0) { |
458 | snd_usb_autosuspend(chip); | ||
442 | return 0; | 459 | return 0; |
460 | } | ||
461 | snd_usb_autosuspend(chip); | ||
443 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", | 462 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", |
444 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); | 463 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); |
445 | return -EINVAL; | 464 | return -EINVAL; |
@@ -987,6 +1006,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
987 | struct snd_kcontrol *kctl; | 1006 | struct snd_kcontrol *kctl; |
988 | struct usb_mixer_elem_info *cval; | 1007 | struct usb_mixer_elem_info *cval; |
989 | const struct usbmix_name_map *map; | 1008 | const struct usbmix_name_map *map; |
1009 | unsigned int range; | ||
990 | 1010 | ||
991 | control++; /* change from zero-based to 1-based value */ | 1011 | control++; /* change from zero-based to 1-based value */ |
992 | 1012 | ||
@@ -1121,6 +1141,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1121 | } | 1141 | } |
1122 | break; | 1142 | break; |
1123 | 1143 | ||
1144 | case USB_ID(0x046d, 0x0808): | ||
1124 | case USB_ID(0x046d, 0x0809): | 1145 | case USB_ID(0x046d, 0x0809): |
1125 | case USB_ID(0x046d, 0x0991): | 1146 | case USB_ID(0x046d, 0x0991): |
1126 | /* Most audio usb devices lie about volume resolution. | 1147 | /* Most audio usb devices lie about volume resolution. |
@@ -1136,6 +1157,21 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1136 | 1157 | ||
1137 | } | 1158 | } |
1138 | 1159 | ||
1160 | range = (cval->max - cval->min) / cval->res; | ||
1161 | /* Are there devices with volume range more than 255? I use a bit more | ||
1162 | * to be sure. 384 is a resolution magic number found on Logitech | ||
1163 | * devices. It will definitively catch all buggy Logitech devices. | ||
1164 | */ | ||
1165 | if (range > 384) { | ||
1166 | snd_printk(KERN_WARNING "usb_audio: Warning! Unlikely big " | ||
1167 | "volume range (=%u), cval->res is probably wrong.", | ||
1168 | range); | ||
1169 | snd_printk(KERN_WARNING "usb_audio: [%d] FU [%s] ch = %d, " | ||
1170 | "val = %d/%d/%d", cval->id, | ||
1171 | kctl->id.name, cval->channels, | ||
1172 | cval->min, cval->max, cval->res); | ||
1173 | } | ||
1174 | |||
1139 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", | 1175 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", |
1140 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); | 1176 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); |
1141 | add_control_to_empty(state, kctl); | 1177 | add_control_to_empty(state, kctl); |
@@ -1566,7 +1602,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw | |||
1566 | cval->initialized = 1; | 1602 | cval->initialized = 1; |
1567 | } else { | 1603 | } else { |
1568 | if (type == USB_XU_CLOCK_RATE) { | 1604 | if (type == USB_XU_CLOCK_RATE) { |
1569 | /* E-Mu USB 0404/0202/TrackerPre | 1605 | /* E-Mu USB 0404/0202/TrackerPre/0204 |
1570 | * samplerate control quirk | 1606 | * samplerate control quirk |
1571 | */ | 1607 | */ |
1572 | cval->min = 0; | 1608 | cval->min = 0; |
@@ -2058,8 +2094,9 @@ static void snd_usb_mixer_interrupt(struct urb *urb) | |||
2058 | { | 2094 | { |
2059 | struct usb_mixer_interface *mixer = urb->context; | 2095 | struct usb_mixer_interface *mixer = urb->context; |
2060 | int len = urb->actual_length; | 2096 | int len = urb->actual_length; |
2097 | int ustatus = urb->status; | ||
2061 | 2098 | ||
2062 | if (urb->status != 0) | 2099 | if (ustatus != 0) |
2063 | goto requeue; | 2100 | goto requeue; |
2064 | 2101 | ||
2065 | if (mixer->protocol == UAC_VERSION_1) { | 2102 | if (mixer->protocol == UAC_VERSION_1) { |
@@ -2100,12 +2137,32 @@ static void snd_usb_mixer_interrupt(struct urb *urb) | |||
2100 | } | 2137 | } |
2101 | 2138 | ||
2102 | requeue: | 2139 | requeue: |
2103 | if (urb->status != -ENOENT && urb->status != -ECONNRESET) { | 2140 | if (ustatus != -ENOENT && ustatus != -ECONNRESET && ustatus != -ESHUTDOWN) { |
2104 | urb->dev = mixer->chip->dev; | 2141 | urb->dev = mixer->chip->dev; |
2105 | usb_submit_urb(urb, GFP_ATOMIC); | 2142 | usb_submit_urb(urb, GFP_ATOMIC); |
2106 | } | 2143 | } |
2107 | } | 2144 | } |
2108 | 2145 | ||
2146 | /* stop any bus activity of a mixer */ | ||
2147 | void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer) | ||
2148 | { | ||
2149 | usb_kill_urb(mixer->urb); | ||
2150 | usb_kill_urb(mixer->rc_urb); | ||
2151 | } | ||
2152 | |||
2153 | int snd_usb_mixer_activate(struct usb_mixer_interface *mixer) | ||
2154 | { | ||
2155 | int err; | ||
2156 | |||
2157 | if (mixer->urb) { | ||
2158 | err = usb_submit_urb(mixer->urb, GFP_NOIO); | ||
2159 | if (err < 0) | ||
2160 | return err; | ||
2161 | } | ||
2162 | |||
2163 | return 0; | ||
2164 | } | ||
2165 | |||
2109 | /* create the handler for the optional status interrupt endpoint */ | 2166 | /* create the handler for the optional status interrupt endpoint */ |
2110 | static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) | 2167 | static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) |
2111 | { | 2168 | { |