ALSA: ctxfi - Make volume controls more intuitive
authorTakashi Iwai <tiwai@suse.de>
Mon, 8 Jun 2009 11:50:18 +0000 (13:50 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 8 Jun 2009 11:50:18 +0000 (13:50 +0200)
Change the volume control to dB scale (as the raw data seems so).
Also added the TLV dB-scale information.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/ctxfi/ctmixer.c

index fac783f585fcee61a448c0ea4e45f76d43fde46d..796156e4bd385081bde26793a63ef77362d651aa 100644 (file)
 
 #include "ctmixer.h"
 #include "ctamixer.h"
+#include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/asoundef.h>
 #include <sound/pcm.h>
-#include <linux/slab.h>
+#include <sound/tlv.h>
 
 enum CT_SUM_CTL {
        SUM_IN_F,
@@ -292,6 +293,7 @@ set_switch_state(struct ct_mixer *mixer,
                mixer->switch_state &= ~(0x1 << (type - SWH_MIXER_START));
 }
 
+#if 0 /* not used */
 /* Map integer value ranging from 0 to 65535 to 14-bit float value ranging
  * from 2^-6 to (1+1023/1024) */
 static unsigned int uint16_to_float14(unsigned int x)
@@ -331,6 +333,12 @@ static unsigned int float14_to_uint16(unsigned int x)
 
        return x;
 }
+#endif /* not used */
+
+#define VOL_SCALE      0x1c
+#define VOL_MAX                0x100
+
+static const DECLARE_TLV_DB_SCALE(ct_vol_db_scale, -6400, 25, 1);
 
 static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol,
                                   struct snd_ctl_elem_info *uinfo)
@@ -338,8 +346,7 @@ static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol,
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = 2;
        uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 43690;
-       uinfo->value.integer.step = 128;
+       uinfo->value.integer.max = VOL_MAX;
 
        return 0;
 }
@@ -349,15 +356,18 @@ static int ct_alsa_mix_volume_get(struct snd_kcontrol *kcontrol,
 {
        struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
        enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
-       struct amixer *amixer = NULL;
-       int i = 0;
+       struct amixer *amixer;
+       int i, val;
 
        for (i = 0; i < 2; i++) {
                amixer = ((struct ct_mixer *)atc->mixer)->
                                                amixers[type*CHN_NUM+i];
-               /* Convert 14-bit float-point scale to 16-bit integer volume */
-               ucontrol->value.integer.value[i] =
-               (float14_to_uint16(amixer->ops->get_scale(amixer)) & 0xffff);
+               val = amixer->ops->get_scale(amixer) / VOL_SCALE;
+               if (val < 0)
+                       val = 0;
+               else if (val > VOL_MAX)
+                       val = VOL_MAX;
+               ucontrol->value.integer.value[i] = val;
        }
 
        return 0;
@@ -369,16 +379,19 @@ static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol,
        struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
        struct ct_mixer *mixer = atc->mixer;
        enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
-       struct amixer *amixer = NULL;
-       int i = 0, j = 0, change = 0, val = 0;
+       struct amixer *amixer;
+       int i, j, val, oval, change = 0;
 
        for (i = 0; i < 2; i++) {
-               /* Convert 16-bit integer volume to 14-bit float-point scale */
-               val = (ucontrol->value.integer.value[i] & 0xffff);
+               val = ucontrol->value.integer.value[i];
+               if (val < 0)
+                       val = 0;
+               else if (val > VOL_MAX)
+                       val = VOL_MAX;
+               val *= VOL_SCALE;
                amixer = mixer->amixers[type*CHN_NUM+i];
-               if ((float14_to_uint16(amixer->ops->get_scale(amixer)) & 0xff80)
-                               != (val & 0xff80)) {
-                       val = uint16_to_float14(val);
+               oval = amixer->ops->get_scale(amixer);
+               if (val != oval) {
                        amixer->ops->set_scale(amixer, val);
                        amixer->ops->commit_write(amixer);
                        change = 1;
@@ -398,11 +411,13 @@ static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol,
 }
 
 static struct snd_kcontrol_new vol_ctl = {
-       .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
        .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
        .info           = ct_alsa_mix_volume_info,
        .get            = ct_alsa_mix_volume_get,
-       .put            = ct_alsa_mix_volume_put
+       .put            = ct_alsa_mix_volume_put,
+       .tlv            = { .p =  ct_vol_db_scale },
 };
 
 static void