Merge branch 'topic/tlv-minmax' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Thu, 10 Sep 2009 13:33:06 +0000 (15:33 +0200)
committerTakashi Iwai <tiwai@suse.de>
Thu, 10 Sep 2009 13:33:06 +0000 (15:33 +0200)
* topic/tlv-minmax:
  ALSA: usb-audio - Correct bogus volume dB information
  ALSA: usb-audio - Use the new TLV_DB_MINMAX type
  ALSA: Add new TLV types for dBwith min/max

1  2 
sound/usb/usbmixer.c

diff --combined sound/usb/usbmixer.c
index ec9cdf986928cfd1ce1847b18e111fdb71552fba,539b427d08c6aca54ff1b0f1393bdbd3f55c6fef..df8969188d158d7217f9951f9173954d16c91d38
@@@ -423,7 -423,7 +423,7 @@@ static int set_ctl_value(struct usb_mix
        value_set = convert_bytes_value(cval, value_set);
        buf[0] = value_set & 0xff;
        buf[1] = (value_set >> 8) & 0xff;
 -      while (timeout -- > 0)
 +      while (timeout-- > 0)
                if (snd_usb_ctl_msg(cval->mixer->chip->dev,
                                    usb_sndctrlpipe(cval->mixer->chip->dev, 0),
                                    request,
@@@ -461,7 -461,7 +461,7 @@@ static int mixer_vol_tlv(struct snd_kco
                         unsigned int size, unsigned int __user *_tlv)
  {
        struct usb_mixer_elem_info *cval = kcontrol->private_data;
-       DECLARE_TLV_DB_SCALE(scale, 0, 0, 0);
+       DECLARE_TLV_DB_MINMAX(scale, 0, 0);
  
        if (size < sizeof(scale))
                return -ENOMEM;
         * while ALSA TLV contains in 1/100 dB unit
         */
        scale[2] = (convert_signed_value(cval, cval->min) * 100) / 256;
-       scale[3] = (convert_signed_value(cval, cval->res) * 100) / 256;
+       scale[3] = (convert_signed_value(cval, cval->max) * 100) / 256;
+       if (scale[3] <= scale[2]) {
+               /* something is wrong; assume it's either from/to 0dB */
+               if (scale[2] < 0)
+                       scale[3] = 0;
+               else if (scale[2] > 0)
+                       scale[2] = 0;
+               else /* totally crap, return an error */
+                       return -EINVAL;
+       }
        if (copy_to_user(_tlv, scale, sizeof(scale)))
                return -EFAULT;
        return 0;
@@@ -990,35 -999,20 +999,35 @@@ static void build_feature_ctl(struct mi
                break;
        }
  
 -      /* 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 */
 +      /* 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 "using volume control quirk for the UDA1321/N101 chip\n");
 +                      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;
 +
        }
  
        snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",