diff options
-rw-r--r-- | sound/pci/cs5535audio/cs5535audio.h | 2 | ||||
-rw-r--r-- | sound/pci/cs5535audio/cs5535audio_olpc.c | 54 |
2 files changed, 26 insertions, 30 deletions
diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h index 31ecb33ffff9..22737fc9ed03 100644 --- a/sound/pci/cs5535audio/cs5535audio.h +++ b/sound/pci/cs5535audio/cs5535audio.h | |||
@@ -103,6 +103,7 @@ int snd_cs5535audio_resume(struct pci_dev *pci); | |||
103 | void __devinit olpc_prequirks(struct snd_card *card, | 103 | void __devinit olpc_prequirks(struct snd_card *card, |
104 | struct snd_ac97_template *ac97); | 104 | struct snd_ac97_template *ac97); |
105 | int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97); | 105 | int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97); |
106 | void olpc_analog_input(struct snd_ac97 *ac97, int on); | ||
106 | #else | 107 | #else |
107 | static inline void olpc_prequirks(struct snd_card *card, | 108 | static inline void olpc_prequirks(struct snd_card *card, |
108 | struct snd_ac97_template *ac97) { } | 109 | struct snd_ac97_template *ac97) { } |
@@ -110,6 +111,7 @@ static inline int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) | |||
110 | { | 111 | { |
111 | return 0; | 112 | return 0; |
112 | } | 113 | } |
114 | static inline void olpc_analog_input(struct snd_ac97 *ac97, int on) { } | ||
113 | #endif | 115 | #endif |
114 | 116 | ||
115 | int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio); | 117 | int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio); |
diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c index f20e74182725..597395e6e358 100644 --- a/sound/pci/cs5535audio/cs5535audio_olpc.c +++ b/sound/pci/cs5535audio/cs5535audio_olpc.c | |||
@@ -7,12 +7,29 @@ | |||
7 | #include <asm/olpc.h> | 7 | #include <asm/olpc.h> |
8 | #include "cs5535audio.h" | 8 | #include "cs5535audio.h" |
9 | 9 | ||
10 | /* OLPC has an additional feature on top of regular AD1888 codec | 10 | /* |
11 | features. This is support for an analog input mode. This is a | 11 | * OLPC has an additional feature on top of the regular AD1888 codec features. |
12 | 2 step process. First, to turn off the AD1888 codec bias voltage | 12 | * It has an Analog Input mode that is switched into (after disabling the |
13 | and high pass filter. Second, to tell the embedded controller to | 13 | * High Pass Filter) via GPIO. It is supported on B2 and later models. |
14 | reroute from a capacitive trace to a direct trace using an analog | 14 | */ |
15 | switch. The *_ec()s are what talk to that controller */ | 15 | void olpc_analog_input(struct snd_ac97 *ac97, int on) |
16 | { | ||
17 | int err; | ||
18 | |||
19 | /* update the High Pass Filter (via AC97_AD_TEST2) */ | ||
20 | err = snd_ac97_update_bits(ac97, AC97_AD_TEST2, | ||
21 | 1 << AC97_AD_HPFD_SHIFT, on << AC97_AD_HPFD_SHIFT); | ||
22 | if (err < 0) { | ||
23 | snd_printk(KERN_ERR "setting High Pass Filter - %d\n", err); | ||
24 | return; | ||
25 | } | ||
26 | |||
27 | /* set Analog Input through GPIO */ | ||
28 | if (on) | ||
29 | geode_gpio_set(OLPC_GPIO_MIC_AC, GPIO_OUTPUT_VAL); | ||
30 | else | ||
31 | geode_gpio_clear(OLPC_GPIO_MIC_AC, GPIO_OUTPUT_VAL); | ||
32 | } | ||
16 | 33 | ||
17 | static int snd_cs5535audio_ctl_info(struct snd_kcontrol *kcontrol, | 34 | static int snd_cs5535audio_ctl_info(struct snd_kcontrol *kcontrol, |
18 | struct snd_ctl_elem_info *uinfo) | 35 | struct snd_ctl_elem_info *uinfo) |
@@ -24,8 +41,6 @@ static int snd_cs5535audio_ctl_info(struct snd_kcontrol *kcontrol, | |||
24 | return 0; | 41 | return 0; |
25 | } | 42 | } |
26 | 43 | ||
27 | #define AD1888_VREFOUT_EN_BIT (1 << 2) | ||
28 | #define AD1888_HPF_EN_BIT (1 << 12) | ||
29 | static int snd_cs5535audio_ctl_get(struct snd_kcontrol *kcontrol, | 44 | static int snd_cs5535audio_ctl_get(struct snd_kcontrol *kcontrol, |
30 | struct snd_ctl_elem_value *ucontrol) | 45 | struct snd_ctl_elem_value *ucontrol) |
31 | { | 46 | { |
@@ -42,30 +57,9 @@ static int snd_cs5535audio_ctl_get(struct snd_kcontrol *kcontrol, | |||
42 | static int snd_cs5535audio_ctl_put(struct snd_kcontrol *kcontrol, | 57 | static int snd_cs5535audio_ctl_put(struct snd_kcontrol *kcontrol, |
43 | struct snd_ctl_elem_value *ucontrol) | 58 | struct snd_ctl_elem_value *ucontrol) |
44 | { | 59 | { |
45 | int err; | ||
46 | struct cs5535audio *cs5535au = snd_kcontrol_chip(kcontrol); | 60 | struct cs5535audio *cs5535au = snd_kcontrol_chip(kcontrol); |
47 | u8 value; | ||
48 | struct snd_ac97 *ac97 = cs5535au->ac97; | ||
49 | |||
50 | /* value is 1 if analog input is desired */ | ||
51 | value = ucontrol->value.integer.value[0]; | ||
52 | |||
53 | /* turns off High Pass Filter if 1 */ | ||
54 | if (value) | ||
55 | err = snd_ac97_update_bits(ac97, AC97_AD_TEST2, | ||
56 | AD1888_HPF_EN_BIT, AD1888_HPF_EN_BIT); | ||
57 | else | ||
58 | err = snd_ac97_update_bits(ac97, AC97_AD_TEST2, | ||
59 | AD1888_HPF_EN_BIT, 0); | ||
60 | if (err < 0) | ||
61 | snd_printk(KERN_ERR "Error updating AD_TEST2 %d\n", err); | ||
62 | |||
63 | /* B2 and newer writes directly to a GPIO pin */ | ||
64 | if (value) | ||
65 | geode_gpio_set(OLPC_GPIO_MIC_AC, GPIO_OUTPUT_VAL); | ||
66 | else | ||
67 | geode_gpio_clear(OLPC_GPIO_MIC_AC, GPIO_OUTPUT_VAL); | ||
68 | 61 | ||
62 | olpc_analog_input(cs5535au->ac97, ucontrol->value.integer.value[0]); | ||
69 | return 1; | 63 | return 1; |
70 | } | 64 | } |
71 | 65 | ||