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 | ||
