aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-08-03 11:59:36 -0400
committerTakashi Iwai <tiwai@suse.de>2012-09-06 12:08:30 -0400
commit833a493b7ed2eb8f9059338a0ebf06bebbb6ae93 (patch)
tree785dd0a6ad97fc13a100e409c8fd21e07872f64d
parent53775b0d0cb91ab217c9853efddc51597b58bbff (diff)
ALSA: ac97: Implement channel map workaround for ALC650
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>
-rw-r--r--include/sound/ac97_codec.h3
-rw-r--r--sound/pci/ac97/ac97_patch.c24
2 files changed, 26 insertions, 1 deletions
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 02cbb50225bb..4458b87649ff 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -422,6 +422,7 @@
422 */ 422 */
423 423
424struct snd_ac97; 424struct snd_ac97;
425struct snd_pcm_chmap;
425 426
426struct snd_ac97_build_ops { 427struct snd_ac97_build_ops {
427 int (*build_3d) (struct snd_ac97 *ac97); 428 int (*build_3d) (struct snd_ac97 *ac97);
@@ -528,6 +529,8 @@ struct snd_ac97 {
528 struct delayed_work power_work; 529 struct delayed_work power_work;
529#endif 530#endif
530 struct device dev; 531 struct device dev;
532
533 struct snd_pcm_chmap *chmaps[2]; /* channel-maps (optional) */
531}; 534};
532 535
533#define to_ac97_t(d) container_of(d, struct snd_ac97, dev) 536#define to_ac97_t(d) container_of(d, struct snd_ac97, dev)
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index a872d0a82976..66a3bc95fb84 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -2595,6 +2595,21 @@ static void alc650_update_jacks(struct snd_ac97 *ac97)
2595 shared ? 0 : 0x100); 2595 shared ? 0 : 0x100);
2596} 2596}
2597 2597
2598static int alc650_swap_surround_put(struct snd_kcontrol *kcontrol,
2599 struct snd_ctl_elem_value *ucontrol)
2600{
2601 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2602 struct snd_pcm_chmap *map = ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK];
2603
2604 if (map) {
2605 if (ucontrol->value.integer.value[0])
2606 map->chmap = snd_pcm_std_chmaps;
2607 else
2608 map->chmap = snd_pcm_alt_chmaps;
2609 }
2610 return snd_ac97_put_volsw(kcontrol, ucontrol);
2611}
2612
2598static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = { 2613static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = {
2599 AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0), 2614 AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
2600 AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0), 2615 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[] = {
2608 /* 9: Line-In/Surround share */ 2623 /* 9: Line-In/Surround share */
2609 /* 10: Mic/CLFE share */ 2624 /* 10: Mic/CLFE share */
2610 /* 11-13: in IEC958 controls */ 2625 /* 11-13: in IEC958 controls */
2611 AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0), 2626 {
2627 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2628 .name = "Swap Surround Slot",
2629 .info = snd_ac97_info_volsw,
2630 .get = snd_ac97_get_volsw,
2631 .put = alc650_swap_surround_put,
2632 .private_value = AC97_SINGLE_VALUE(AC97_ALC650_MULTICH, 14, 1, 0),
2633 },
2612#if 0 /* always set in patch_alc650 */ 2634#if 0 /* always set in patch_alc650 */
2613 AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0), 2635 AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
2614 AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0), 2636 AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),