]> Pileus Git - ~andy/linux/blobdiff - sound/pci/ac97/ac97_patch.c
[ALSA] Add TLV support to AC97 codec driver
[~andy/linux] / sound / pci / ac97 / ac97_patch.c
index 37c6be481c4a1d945b94625a26b0ae93a44c4884..392f6ccace5d2e172515cb64f60379d181eb2dc2 100644 (file)
@@ -32,6 +32,7 @@
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 #include <sound/ac97_codec.h>
 #include "ac97_patch.h"
 #include "ac97_id.h"
@@ -51,6 +52,20 @@ static int patch_build_controls(struct snd_ac97 * ac97, const struct snd_kcontro
        return 0;
 }
 
+/* replace with a new TLV */
+static void reset_tlv(struct snd_ac97 *ac97, const char *name,
+                     unsigned int *tlv)
+{
+       struct snd_ctl_elem_id sid;
+       struct snd_kcontrol *kctl;
+       memset(&sid, 0, sizeof(sid));
+       strcpy(sid.name, name);
+       sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       kctl = snd_ctl_find_id(ac97->bus->card, &sid);
+       if (kctl && kctl->tlv.p)
+               kctl->tlv.p = tlv;
+}
+
 /* set to the page, update bits and restore the page */
 static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
 {
@@ -1522,12 +1537,16 @@ static const struct snd_kcontrol_new snd_ac97_controls_ad1885[] = {
        AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
 };
 
+static DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0);
+
 static int patch_ad1885_specific(struct snd_ac97 * ac97)
 {
        int err;
 
        if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0)
                return err;
+       reset_tlv(ac97, "Headphone Playback Volume",
+                 db_scale_6bit_6db_max);
        return 0;
 }
 
@@ -1551,12 +1570,27 @@ int patch_ad1885(struct snd_ac97 * ac97)
        return 0;
 }
 
+static int patch_ad1886_specific(struct snd_ac97 * ac97)
+{
+       reset_tlv(ac97, "Headphone Playback Volume",
+                 db_scale_6bit_6db_max);
+       return 0;
+}
+
+static struct snd_ac97_build_ops patch_ad1886_build_ops = {
+       .build_specific = &patch_ad1886_specific,
+#ifdef CONFIG_PM
+       .resume = ad18xx_resume
+#endif
+};
+
 int patch_ad1886(struct snd_ac97 * ac97)
 {
        patch_ad1881(ac97);
        /* Presario700 workaround */
        /* for Jack Sense/SPDIF Register misetting causing */
        snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010);
+       ac97->build_ops = &patch_ad1886_build_ops;
        return 0;
 }
 
@@ -2015,6 +2049,8 @@ static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = {
        /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */
 };
 
+static DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0);
+
 static int patch_alc650_specific(struct snd_ac97 * ac97)
 {
        int err;
@@ -2025,6 +2061,9 @@ static int patch_alc650_specific(struct snd_ac97 * ac97)
                if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0)
                        return err;
        }
+       if (ac97->id != AC97_ID_ALC650F)
+               reset_tlv(ac97, "Master Playback Volume",
+                         db_scale_5bit_3db_max);
        return 0;
 }