diff options
Diffstat (limited to 'sound/usb/usbmixer.c')
-rw-r--r-- | sound/usb/usbmixer.c | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 84526971e675..ab5a3ac2ac47 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -462,7 +462,7 @@ static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
462 | unsigned int size, unsigned int __user *_tlv) | 462 | unsigned int size, unsigned int __user *_tlv) |
463 | { | 463 | { |
464 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 464 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
465 | DECLARE_TLV_DB_SCALE(scale, 0, 0, 0); | 465 | DECLARE_TLV_DB_MINMAX(scale, 0, 0); |
466 | 466 | ||
467 | if (size < sizeof(scale)) | 467 | if (size < sizeof(scale)) |
468 | return -ENOMEM; | 468 | return -ENOMEM; |
@@ -470,7 +470,16 @@ static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
470 | * while ALSA TLV contains in 1/100 dB unit | 470 | * while ALSA TLV contains in 1/100 dB unit |
471 | */ | 471 | */ |
472 | scale[2] = (convert_signed_value(cval, cval->min) * 100) / 256; | 472 | scale[2] = (convert_signed_value(cval, cval->min) * 100) / 256; |
473 | scale[3] = (convert_signed_value(cval, cval->res) * 100) / 256; | 473 | scale[3] = (convert_signed_value(cval, cval->max) * 100) / 256; |
474 | if (scale[3] <= scale[2]) { | ||
475 | /* something is wrong; assume it's either from/to 0dB */ | ||
476 | if (scale[2] < 0) | ||
477 | scale[3] = 0; | ||
478 | else if (scale[2] > 0) | ||
479 | scale[2] = 0; | ||
480 | else /* totally crap, return an error */ | ||
481 | return -EINVAL; | ||
482 | } | ||
474 | if (copy_to_user(_tlv, scale, sizeof(scale))) | 483 | if (copy_to_user(_tlv, scale, sizeof(scale))) |
475 | return -EFAULT; | 484 | return -EFAULT; |
476 | return 0; | 485 | return 0; |
@@ -991,20 +1000,35 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, | |||
991 | break; | 1000 | break; |
992 | } | 1001 | } |
993 | 1002 | ||
994 | /* quirk for UDA1321/N101 */ | 1003 | /* volume control quirks */ |
995 | /* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */ | ||
996 | /* is not very clear from datasheets */ | ||
997 | /* I hope that the min value is -15360 for newer firmware --jk */ | ||
998 | switch (state->chip->usb_id) { | 1004 | switch (state->chip->usb_id) { |
999 | case USB_ID(0x0471, 0x0101): | 1005 | case USB_ID(0x0471, 0x0101): |
1000 | case USB_ID(0x0471, 0x0104): | 1006 | case USB_ID(0x0471, 0x0104): |
1001 | case USB_ID(0x0471, 0x0105): | 1007 | case USB_ID(0x0471, 0x0105): |
1002 | case USB_ID(0x0672, 0x1041): | 1008 | case USB_ID(0x0672, 0x1041): |
1009 | /* quirk for UDA1321/N101. | ||
1010 | * note that detection between firmware 2.1.1.7 (N101) | ||
1011 | * and later 2.1.1.21 is not very clear from datasheets. | ||
1012 | * I hope that the min value is -15360 for newer firmware --jk | ||
1013 | */ | ||
1003 | if (!strcmp(kctl->id.name, "PCM Playback Volume") && | 1014 | if (!strcmp(kctl->id.name, "PCM Playback Volume") && |
1004 | cval->min == -15616) { | 1015 | cval->min == -15616) { |
1005 | snd_printk(KERN_INFO "using volume control quirk for the UDA1321/N101 chip\n"); | 1016 | snd_printk(KERN_INFO |
1017 | "set volume quirk for UDA1321/N101 chip\n"); | ||
1006 | cval->max = -256; | 1018 | cval->max = -256; |
1007 | } | 1019 | } |
1020 | break; | ||
1021 | |||
1022 | case USB_ID(0x046d, 0x09a4): | ||
1023 | if (!strcmp(kctl->id.name, "Mic Capture Volume")) { | ||
1024 | snd_printk(KERN_INFO | ||
1025 | "set volume quirk for QuickCam E3500\n"); | ||
1026 | cval->min = 6080; | ||
1027 | cval->max = 8768; | ||
1028 | cval->res = 192; | ||
1029 | } | ||
1030 | break; | ||
1031 | |||
1008 | } | 1032 | } |
1009 | 1033 | ||
1010 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", | 1034 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", |