On Sun, 13 Dec 2015 19:49:58 +0100, Anssi Hannula wrote: > > AudioQuest DragonFly DAC reports a volume control range of 0..50 > (0x0000..0x0032) which in USB Audio means a range of 0 .. 0.2dB, which > is obviously incorrect and would cause software using the dB information > in e.g. volume sliders to have a massive volume difference in 100..102% > range. > > Commit 2d1cb7f658fb ("ALSA: usb-audio: add dB range mapping for some > devices") added a dB range mapping for it with range 0..50 dB. > > However, the actual volume mapping seems to be neither linear volume nor > linear dB scale, but instead quite close to the cubic mapping e.g. > alsamixer uses, with a range of approx. -53...0 dB. > > Replace the previous quirk with a custom dB mapping based on some basic > output measurements, using a 10-item range TLV (which will still fit in > alsa-lib MAX_TLV_RANGE_SIZE). > > Tested on AudioQuest DragonFly HW v1.2. The quirk is only applied if the > range is 0..50, so if this gets fixed/changed in later HW revisions it > will no longer be applied. > > v2: incorporated Takashi Iwai's suggestion for the quirk application > method > > Signed-off-by: Anssi Hannula <anssi.hannula@xxxxxx> > Cc: <stable@xxxxxxxxxxxxxxx> Applied, thanks. Takashi > --- > > It took a bit longer than expected for me to get back to this, but here > goes :) > > > sound/usb/mixer.c | 2 ++ > sound/usb/mixer_maps.c | 12 ------------ > sound/usb/mixer_quirks.c | 37 +++++++++++++++++++++++++++++++++++++ > sound/usb/mixer_quirks.h | 4 ++++ > 4 files changed, 43 insertions(+), 12 deletions(-) > > diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c > index f494dced3c11..4f85757009b3 100644 > --- a/sound/usb/mixer.c > +++ b/sound/usb/mixer.c > @@ -1354,6 +1354,8 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, > } > } > > + snd_usb_mixer_fu_apply_quirk(state->mixer, cval, unitid, kctl); > + > range = (cval->max - cval->min) / cval->res; > /* > * Are there devices with volume range more than 255? I use a bit more > diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c > index 6a803eff87f7..ddca6547399b 100644 > --- a/sound/usb/mixer_maps.c > +++ b/sound/usb/mixer_maps.c > @@ -348,13 +348,6 @@ static struct usbmix_name_map bose_companion5_map[] = { > { 0 } /* terminator */ > }; > > -/* Dragonfly DAC 1.2, the dB conversion factor is 1 instead of 256 */ > -static struct usbmix_dB_map dragonfly_1_2_dB = {0, 5000}; > -static struct usbmix_name_map dragonfly_1_2_map[] = { > - { 7, NULL, .dB = &dragonfly_1_2_dB }, > - { 0 } /* terminator */ > -}; > - > /* > * Control map entries > */ > @@ -470,11 +463,6 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { > .id = USB_ID(0x05a7, 0x1020), > .map = bose_companion5_map, > }, > - { > - /* Dragonfly DAC 1.2 */ > - .id = USB_ID(0x21b4, 0x0081), > - .map = dragonfly_1_2_map, > - }, > { 0 } /* terminator */ > }; > > diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c > index fe91184ce832..0ce888dceed0 100644 > --- a/sound/usb/mixer_quirks.c > +++ b/sound/usb/mixer_quirks.c > @@ -37,6 +37,7 @@ > #include <sound/control.h> > #include <sound/hwdep.h> > #include <sound/info.h> > +#include <sound/tlv.h> > > #include "usbaudio.h" > #include "mixer.h" > @@ -1825,3 +1826,39 @@ void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, > } > } > > +static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer, > + struct snd_kcontrol *kctl) > +{ > + /* Approximation using 10 ranges based on output measurement on hw v1.2. > + * This seems close to the cubic mapping e.g. alsamixer uses. */ > + static const DECLARE_TLV_DB_RANGE(scale, > + 0, 1, TLV_DB_MINMAX_ITEM(-5300, -4970), > + 2, 5, TLV_DB_MINMAX_ITEM(-4710, -4160), > + 6, 7, TLV_DB_MINMAX_ITEM(-3884, -3710), > + 8, 14, TLV_DB_MINMAX_ITEM(-3443, -2560), > + 15, 16, TLV_DB_MINMAX_ITEM(-2475, -2324), > + 17, 19, TLV_DB_MINMAX_ITEM(-2228, -2031), > + 20, 26, TLV_DB_MINMAX_ITEM(-1910, -1393), > + 27, 31, TLV_DB_MINMAX_ITEM(-1322, -1032), > + 32, 40, TLV_DB_MINMAX_ITEM(-968, -490), > + 41, 50, TLV_DB_MINMAX_ITEM(-441, 0), > + ); > + > + usb_audio_info(mixer->chip, "applying DragonFly dB scale quirk\n"); > + kctl->tlv.p = scale; > + kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; > + kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; > +} > + > +void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer, > + struct usb_mixer_elem_info *cval, int unitid, > + struct snd_kcontrol *kctl) > +{ > + switch (mixer->chip->usb_id) { > + case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */ > + if (unitid == 7 && cval->min == 0 && cval->max == 50) > + snd_dragonfly_quirk_db_scale(mixer, kctl); > + break; > + } > +} > + > diff --git a/sound/usb/mixer_quirks.h b/sound/usb/mixer_quirks.h > index bdbfab093816..177c329cd4dd 100644 > --- a/sound/usb/mixer_quirks.h > +++ b/sound/usb/mixer_quirks.h > @@ -9,5 +9,9 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, > void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, > int unitid); > > +void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer, > + struct usb_mixer_elem_info *cval, int unitid, > + struct snd_kcontrol *kctl); > + > #endif /* SND_USB_MIXER_QUIRKS_H */ > > -- > 2.3.10 > -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html