0001
0002
0003
0004
0005
0006
0007
0008 #include <sound/core.h>
0009 #include <sound/info.h>
0010 #include <sound/control.h>
0011 #include <sound/ac97_codec.h>
0012 #include <linux/gpio.h>
0013
0014 #include <asm/olpc.h>
0015 #include "cs5535audio.h"
0016
0017 #define DRV_NAME "cs5535audio-olpc"
0018
0019
0020
0021
0022
0023
0024 void olpc_analog_input(struct snd_ac97 *ac97, int on)
0025 {
0026 int err;
0027
0028 if (!machine_is_olpc())
0029 return;
0030
0031
0032 err = snd_ac97_update_bits(ac97, AC97_AD_TEST2,
0033 1 << AC97_AD_HPFD_SHIFT, on << AC97_AD_HPFD_SHIFT);
0034 if (err < 0) {
0035 dev_err(ac97->bus->card->dev,
0036 "setting High Pass Filter - %d\n", err);
0037 return;
0038 }
0039
0040
0041 gpio_set_value(OLPC_GPIO_MIC_AC, on);
0042 }
0043
0044
0045
0046
0047 void olpc_mic_bias(struct snd_ac97 *ac97, int on)
0048 {
0049 int err;
0050
0051 if (!machine_is_olpc())
0052 return;
0053
0054 on = on ? 0 : 1;
0055 err = snd_ac97_update_bits(ac97, AC97_AD_MISC,
0056 1 << AC97_AD_VREFD_SHIFT, on << AC97_AD_VREFD_SHIFT);
0057 if (err < 0)
0058 dev_err(ac97->bus->card->dev, "setting MIC Bias - %d\n", err);
0059 }
0060
0061 static int olpc_dc_info(struct snd_kcontrol *kctl,
0062 struct snd_ctl_elem_info *uinfo)
0063 {
0064 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0065 uinfo->count = 1;
0066 uinfo->value.integer.min = 0;
0067 uinfo->value.integer.max = 1;
0068 return 0;
0069 }
0070
0071 static int olpc_dc_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v)
0072 {
0073 v->value.integer.value[0] = gpio_get_value(OLPC_GPIO_MIC_AC);
0074 return 0;
0075 }
0076
0077 static int olpc_dc_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v)
0078 {
0079 struct cs5535audio *cs5535au = snd_kcontrol_chip(kctl);
0080
0081 olpc_analog_input(cs5535au->ac97, v->value.integer.value[0]);
0082 return 1;
0083 }
0084
0085 static int olpc_mic_info(struct snd_kcontrol *kctl,
0086 struct snd_ctl_elem_info *uinfo)
0087 {
0088 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0089 uinfo->count = 1;
0090 uinfo->value.integer.min = 0;
0091 uinfo->value.integer.max = 1;
0092 return 0;
0093 }
0094
0095 static int olpc_mic_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v)
0096 {
0097 struct cs5535audio *cs5535au = snd_kcontrol_chip(kctl);
0098 struct snd_ac97 *ac97 = cs5535au->ac97;
0099 int i;
0100
0101 i = (snd_ac97_read(ac97, AC97_AD_MISC) >> AC97_AD_VREFD_SHIFT) & 0x1;
0102 v->value.integer.value[0] = i ? 0 : 1;
0103 return 0;
0104 }
0105
0106 static int olpc_mic_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v)
0107 {
0108 struct cs5535audio *cs5535au = snd_kcontrol_chip(kctl);
0109
0110 olpc_mic_bias(cs5535au->ac97, v->value.integer.value[0]);
0111 return 1;
0112 }
0113
0114 static const struct snd_kcontrol_new olpc_cs5535audio_ctls[] = {
0115 {
0116 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0117 .name = "DC Mode Enable",
0118 .info = olpc_dc_info,
0119 .get = olpc_dc_get,
0120 .put = olpc_dc_put,
0121 .private_value = 0,
0122 },
0123 {
0124 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0125 .name = "MIC Bias Enable",
0126 .info = olpc_mic_info,
0127 .get = olpc_mic_get,
0128 .put = olpc_mic_put,
0129 .private_value = 0,
0130 },
0131 };
0132
0133 void olpc_prequirks(struct snd_card *card,
0134 struct snd_ac97_template *ac97)
0135 {
0136 if (!machine_is_olpc())
0137 return;
0138
0139
0140 if (olpc_board_at_least(olpc_board_pre(0xb3)))
0141 ac97->scaps |= AC97_SCAP_INV_EAPD;
0142 }
0143
0144 int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
0145 {
0146 struct snd_ctl_elem_id elem;
0147 int i, err;
0148
0149 if (!machine_is_olpc())
0150 return 0;
0151
0152 if (gpio_request(OLPC_GPIO_MIC_AC, DRV_NAME)) {
0153 dev_err(card->dev, "unable to allocate MIC GPIO\n");
0154 return -EIO;
0155 }
0156 gpio_direction_output(OLPC_GPIO_MIC_AC, 0);
0157
0158
0159 memset(&elem, 0, sizeof(elem));
0160 elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
0161 strscpy(elem.name, "High Pass Filter Enable", sizeof(elem.name));
0162 snd_ctl_remove_id(card, &elem);
0163
0164
0165 memset(&elem, 0, sizeof(elem));
0166 elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
0167 strscpy(elem.name, "V_REFOUT Enable", sizeof(elem.name));
0168 snd_ctl_remove_id(card, &elem);
0169
0170
0171 for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) {
0172 err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i],
0173 ac97->private_data));
0174 if (err < 0)
0175 return err;
0176 }
0177
0178
0179 olpc_mic_bias(ac97, 0);
0180 return 0;
0181 }
0182
0183 void olpc_quirks_cleanup(void)
0184 {
0185 if (machine_is_olpc())
0186 gpio_free(OLPC_GPIO_MIC_AC);
0187 }