diff options
Diffstat (limited to 'sound/usb/usbmixer.c')
-rw-r--r-- | sound/usb/usbmixer.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 491e975a0c87..e516d6adbb22 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <sound/control.h> | 37 | #include <sound/control.h> |
38 | #include <sound/hwdep.h> | 38 | #include <sound/hwdep.h> |
39 | #include <sound/info.h> | 39 | #include <sound/info.h> |
40 | #include <sound/tlv.h> | ||
40 | 41 | ||
41 | #include "usbaudio.h" | 42 | #include "usbaudio.h" |
42 | 43 | ||
@@ -416,6 +417,26 @@ static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channe | |||
416 | return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); | 417 | return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); |
417 | } | 418 | } |
418 | 419 | ||
420 | /* | ||
421 | * TLV callback for mixer volume controls | ||
422 | */ | ||
423 | static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
424 | unsigned int size, unsigned int __user *_tlv) | ||
425 | { | ||
426 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | ||
427 | DECLARE_TLV_DB_SCALE(scale, 0, 0, 0); | ||
428 | |||
429 | if (size < sizeof(scale)) | ||
430 | return -ENOMEM; | ||
431 | /* USB descriptions contain the dB scale in 1/256 dB unit | ||
432 | * while ALSA TLV contains in 1/100 dB unit | ||
433 | */ | ||
434 | scale[2] = (convert_signed_value(cval, cval->min) * 100) / 256; | ||
435 | scale[3] = (convert_signed_value(cval, cval->res) * 100) / 256; | ||
436 | if (copy_to_user(_tlv, scale, sizeof(scale))) | ||
437 | return -EFAULT; | ||
438 | return 0; | ||
439 | } | ||
419 | 440 | ||
420 | /* | 441 | /* |
421 | * parser routines begin here... | 442 | * parser routines begin here... |
@@ -933,6 +954,12 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, | |||
933 | } | 954 | } |
934 | strlcat(kctl->id.name + len, control == USB_FEATURE_MUTE ? " Switch" : " Volume", | 955 | strlcat(kctl->id.name + len, control == USB_FEATURE_MUTE ? " Switch" : " Volume", |
935 | sizeof(kctl->id.name)); | 956 | sizeof(kctl->id.name)); |
957 | if (control == USB_FEATURE_VOLUME) { | ||
958 | kctl->tlv.c = mixer_vol_tlv; | ||
959 | kctl->vd[0].access |= | ||
960 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
961 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | ||
962 | } | ||
936 | break; | 963 | break; |
937 | 964 | ||
938 | default: | 965 | default: |