Merge x86-64 update from Andi
[powerpc.git] / sound / pci / ac97 / ac97_patch.c
index b584172..de1c72a 100644 (file)
@@ -163,14 +163,24 @@ static int ac97_channel_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
                .private_value = 1, \
        }
 
+static inline int is_surround_on(ac97_t *ac97)
+{
+       return ac97->channel_mode >= 1;
+}
+
+static inline int is_clfe_on(ac97_t *ac97)
+{
+       return ac97->channel_mode >= 2;
+}
+
 static inline int is_shared_linein(ac97_t *ac97)
 {
-       return ! ac97->indep_surround && ac97->channel_mode >= 1;
+       return ! ac97->indep_surround && is_surround_on(ac97);
 }
 
 static inline int is_shared_micin(ac97_t *ac97)
 {
-       return ! ac97->indep_surround && ac97->channel_mode >= 2;
+       return ! ac97->indep_surround && is_clfe_on(ac97);
 }
 
 
@@ -1450,7 +1460,8 @@ int patch_ad1881(ac97_t * ac97)
        codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14));
        codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13));
 
-       snd_runtime_check(codecs[0] | codecs[1] | codecs[2], goto __end);
+       if (! (codecs[0] || codecs[1] || codecs[2]))
+               goto __end;
 
        for (idx = 0; idx < 3; idx++)
                if (ac97->spec.ad18xx.unchained[idx])
@@ -1753,12 +1764,13 @@ static int snd_ac97_ad1888_downmix_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
 
 static void ad1888_update_jacks(ac97_t *ac97)
 {
+       unsigned short val = 0;
+       if (! is_shared_linein(ac97))
+               val |= (1 << 12);
+       if (! is_shared_micin(ac97))
+               val |= (1 << 11);
        /* shared Line-In */
-       snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12,
-                            is_shared_linein(ac97) ? 0 : 1 << 12);
-       /* shared Mic */
-       snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11,
-                            is_shared_micin(ac97) ? 0 : 1 << 11);
+       snd_ac97_update_bits(ac97, AC97_AD_MISC, (1 << 11) | (1 << 12), val);
 }
 
 static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
@@ -1852,12 +1864,7 @@ static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = {
 
 static void ad1985_update_jacks(ac97_t *ac97)
 {
-       /* shared Line-In */
-       snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12,
-                            is_shared_linein(ac97) ? 0 : 1 << 12);
-       /* shared Mic */
-       snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11,
-                            is_shared_micin(ac97) ? 0 : 1 << 11);
+       ad1888_update_jacks(ac97);
        snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9,
                             is_shared_micin(ac97) ? 0 : 1 << 9);
 }
@@ -2134,7 +2141,13 @@ int patch_alc655(ac97_t * ac97)
 {
        unsigned int val;
 
-       ac97->spec.dev_flags = (ac97->id == 0x414c4780); /* ALC658 */
+       if (ac97->id == AC97_ID_ALC658) {
+               ac97->spec.dev_flags = 1; /* ALC658 */
+               if ((snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f) == 2) {
+                       ac97->id = AC97_ID_ALC658D;
+                       ac97->spec.dev_flags = 2;
+               }
+       }
 
        ac97->build_ops = &patch_alc655_ops;
 
@@ -2143,10 +2156,15 @@ int patch_alc655(ac97_t * ac97)
 
        /* adjust default values */
        val = snd_ac97_read(ac97, 0x7a); /* misc control */
-       if (ac97->id == 0x414c4780) /* ALC658 */
+       if (ac97->spec.dev_flags) /* ALC658 */
                val &= ~(1 << 1); /* Pin 47 is spdif input pin */
-       else /* ALC655 */
-               val |= (1 << 1); /* Pin 47 is spdif input pin */
+       else { /* ALC655 */
+               if (ac97->subsystem_vendor == 0x1462 &&
+                   ac97->subsystem_device == 0x0131) /* MSI S270 laptop */
+                       val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
+               else
+                       val |= (1 << 1); /* Pin 47 is spdif input pin */
+       }
        val &= ~(1 << 12); /* vref enable */
        snd_ac97_write_cache(ac97, 0x7a, val);
        /* set default: spdif-in enabled,
@@ -2159,6 +2177,11 @@ int patch_alc655(ac97_t * ac97)
        /* full DAC volume */
        snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
        snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
+
+       /* update undocumented bit... */
+       if (ac97->id == AC97_ID_ALC658D)
+               snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800);
+
        return 0;
 }
 
@@ -2426,21 +2449,37 @@ int patch_cm9739(ac97_t * ac97)
 
 static void cm9761_update_jacks(ac97_t *ac97)
 {
-       unsigned short surr_vals[2][2] = {
-               { 0x0008, 0x0400 }, /* off, on */
-               { 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */
+       /* FIXME: check the bits for each model
+        *        model 83 is confirmed to work
+        */
+       static unsigned short surr_on[3][2] = {
+               { 0x0008, 0x0000 }, /* 9761-78 & 82 */
+               { 0x0000, 0x0008 }, /* 9761-82 rev.B */
+               { 0x0000, 0x0008 }, /* 9761-83 */
        };
-       unsigned short clfe_vals[2][2] = {
-               { 0x2000, 0x1880 }, /* off, on */
-               { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */
+       static unsigned short clfe_on[3][2] = {
+               { 0x0000, 0x1000 }, /* 9761-78 & 82 */
+               { 0x1000, 0x0000 }, /* 9761-82 rev.B */
+               { 0x0000, 0x1000 }, /* 9761-83 */
        };
+       static unsigned short surr_shared[3][2] = {
+               { 0x0000, 0x0400 }, /* 9761-78 & 82 */
+               { 0x0000, 0x0400 }, /* 9761-82 rev.B */
+               { 0x0000, 0x0400 }, /* 9761-83 */
+       };
+       static unsigned short clfe_shared[3][2] = {
+               { 0x2000, 0x0880 }, /* 9761-78 & 82 */
+               { 0x0000, 0x2880 }, /* 9761-82 rev.B */
+               { 0x2000, 0x0800 }, /* 9761-83 */
+       };
+       unsigned short val = 0;
 
-       /* shared Line-In */
-       snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x0408,
-                            surr_vals[ac97->spec.dev_flags][is_shared_linein(ac97)]);
-       /* shared Mic */
-       snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3880,
-                            clfe_vals[ac97->spec.dev_flags][is_shared_micin(ac97)]);
+       val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)];
+       val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)];
+       val |= surr_shared[ac97->spec.dev_flags][is_shared_linein(ac97)];
+       val |= clfe_shared[ac97->spec.dev_flags][is_shared_micin(ac97)];
+
+       snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val);
 }
 
 static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = {
@@ -2535,7 +2574,7 @@ int patch_cm9761(ac97_t *ac97)
        snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808);
        snd_ac97_write_cache(ac97, AC97_PCM, 0x8808);
 
-       ac97->spec.dev_flags = 0; /* 1 = model 82 revision B */
+       ac97->spec.dev_flags = 0; /* 1 = model 82 revision B, 2 = model 83 */
        if (ac97->id == AC97_ID_CM9761_82) {
                unsigned short tmp;
                /* check page 1, reg 0x60 */
@@ -2544,7 +2583,8 @@ int patch_cm9761(ac97_t *ac97)
                tmp = snd_ac97_read(ac97, 0x60);
                ac97->spec.dev_flags = tmp & 1; /* revision B? */
                snd_ac97_write_cache(ac97, AC97_INT_PAGING, val);
-       }
+       } else if (ac97->id == AC97_ID_CM9761_83)
+               ac97->spec.dev_flags = 2;
 
        ac97->build_ops = &patch_cm9761_ops;
 
@@ -2736,7 +2776,11 @@ AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1)
 
 static int patch_si3036_specific(ac97_t * ac97)
 {
-       return patch_build_controls(ac97, snd_ac97_controls_si3036, ARRAY_SIZE(snd_ac97_controls_si3036));
+       int idx, err;
+       for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_si3036); idx++)
+               if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_si3036[idx], ac97))) < 0)
+                       return err;
+       return 0;
 }
 
 static struct snd_ac97_build_ops patch_si3036_ops = {