ALSA: ac97: Implement channel map workaround for ALC650
authorTakashi Iwai <tiwai@suse.de>
Fri, 3 Aug 2012 15:59:36 +0000 (17:59 +0200)
committerTakashi Iwai <tiwai@suse.de>
Thu, 6 Sep 2012 16:08:30 +0000 (18:08 +0200)
ALC650 has a channel swap option between surround and CLFE channels,
so we need to tweak the channel maps dynamically depending on the
register bit.

Now struct snd_ac97 can contain chmap pointers for playback and
capture.  The driver may store these and let ac97 driver changing the
channel mapping dynamically.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/ac97_codec.h
sound/pci/ac97/ac97_patch.c

index 02cbb50..4458b87 100644 (file)
  */
 
 struct snd_ac97;
+struct snd_pcm_chmap;
 
 struct snd_ac97_build_ops {
        int (*build_3d) (struct snd_ac97 *ac97);
@@ -528,6 +529,8 @@ struct snd_ac97 {
        struct delayed_work power_work;
 #endif
        struct device dev;
+
+       struct snd_pcm_chmap *chmaps[2]; /* channel-maps (optional) */
 };
 
 #define to_ac97_t(d) container_of(d, struct snd_ac97, dev)
index a872d0a..66a3bc9 100644 (file)
@@ -2595,6 +2595,21 @@ static void alc650_update_jacks(struct snd_ac97 *ac97)
                             shared ? 0 : 0x100);
 }
 
+static int alc650_swap_surround_put(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+       struct snd_pcm_chmap *map = ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK];
+
+       if (map) {
+               if (ucontrol->value.integer.value[0])
+                       map->chmap = snd_pcm_std_chmaps;
+               else
+                       map->chmap = snd_pcm_alt_chmaps;
+       }
+       return snd_ac97_put_volsw(kcontrol, ucontrol);
+}
+
 static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = {
        AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
        AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
@@ -2608,7 +2623,14 @@ static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = {
        /* 9: Line-In/Surround share */
        /* 10: Mic/CLFE share */
        /* 11-13: in IEC958 controls */
-       AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Swap Surround Slot",
+               .info = snd_ac97_info_volsw,
+               .get = snd_ac97_get_volsw,
+               .put = alc650_swap_surround_put,
+               .private_value =  AC97_SINGLE_VALUE(AC97_ALC650_MULTICH, 14, 1, 0),
+       },
 #if 0 /* always set in patch_alc650 */
        AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
        AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),