diff options
| -rw-r--r-- | include/sound/ak4641.h | 26 | ||||
| -rw-r--r-- | sound/soc/codecs/Kconfig | 4 | ||||
| -rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/ak4641.c | 664 | ||||
| -rw-r--r-- | sound/soc/codecs/ak4641.h | 47 |
5 files changed, 743 insertions, 0 deletions
diff --git a/include/sound/ak4641.h b/include/sound/ak4641.h new file mode 100644 index 000000000000..96d1991c811d --- /dev/null +++ b/include/sound/ak4641.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | /* | ||
| 2 | * AK4641 ALSA SoC Codec driver | ||
| 3 | * | ||
| 4 | * Copyright 2009 Philipp Zabel | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef __AK4641_H | ||
| 12 | #define __AK4641_H | ||
| 13 | |||
| 14 | /** | ||
| 15 | * struct ak4641_platform_data - platform specific AK4641 configuration | ||
| 16 | * @gpio_power: GPIO to control external power to AK4641 | ||
| 17 | * @gpio_npdn: GPIO connected to AK4641 nPDN pin | ||
| 18 | * | ||
| 19 | * Both GPIO parameters are optional. | ||
| 20 | */ | ||
| 21 | struct ak4641_platform_data { | ||
| 22 | int gpio_power; | ||
| 23 | int gpio_npdn; | ||
| 24 | }; | ||
| 25 | |||
| 26 | #endif /* __AK4641_H */ | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 2a6971891d31..98175a096df2 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
| @@ -20,6 +20,7 @@ config SND_SOC_ALL_CODECS | |||
| 20 | select SND_SOC_ADS117X | 20 | select SND_SOC_ADS117X |
| 21 | select SND_SOC_AK4104 if SPI_MASTER | 21 | select SND_SOC_AK4104 if SPI_MASTER |
| 22 | select SND_SOC_AK4535 if I2C | 22 | select SND_SOC_AK4535 if I2C |
| 23 | select SND_SOC_AK4641 if I2C | ||
| 23 | select SND_SOC_AK4642 if I2C | 24 | select SND_SOC_AK4642 if I2C |
| 24 | select SND_SOC_AK4671 if I2C | 25 | select SND_SOC_AK4671 if I2C |
| 25 | select SND_SOC_ALC5623 if I2C | 26 | select SND_SOC_ALC5623 if I2C |
| @@ -139,6 +140,9 @@ config SND_SOC_AK4104 | |||
| 139 | config SND_SOC_AK4535 | 140 | config SND_SOC_AK4535 |
| 140 | tristate | 141 | tristate |
| 141 | 142 | ||
| 143 | config SND_SOC_AK4641 | ||
| 144 | tristate | ||
| 145 | |||
| 142 | config SND_SOC_AK4642 | 146 | config SND_SOC_AK4642 |
| 143 | tristate | 147 | tristate |
| 144 | 148 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 4cb2f42dbffa..fd8558406ef0 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
| @@ -7,6 +7,7 @@ snd-soc-ad73311-objs := ad73311.o | |||
| 7 | snd-soc-ads117x-objs := ads117x.o | 7 | snd-soc-ads117x-objs := ads117x.o |
| 8 | snd-soc-ak4104-objs := ak4104.o | 8 | snd-soc-ak4104-objs := ak4104.o |
| 9 | snd-soc-ak4535-objs := ak4535.o | 9 | snd-soc-ak4535-objs := ak4535.o |
| 10 | snd-soc-ak4641-objs := ak4641.o | ||
| 10 | snd-soc-ak4642-objs := ak4642.o | 11 | snd-soc-ak4642-objs := ak4642.o |
| 11 | snd-soc-ak4671-objs := ak4671.o | 12 | snd-soc-ak4671-objs := ak4671.o |
| 12 | snd-soc-cq93vc-objs := cq93vc.o | 13 | snd-soc-cq93vc-objs := cq93vc.o |
| @@ -97,6 +98,7 @@ obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | |||
| 97 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o | 98 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o |
| 98 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o | 99 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o |
| 99 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o | 100 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o |
| 101 | obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o | ||
| 100 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o | 102 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o |
| 101 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o | 103 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o |
| 102 | obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o | 104 | obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o |
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c new file mode 100644 index 000000000000..ed96f247c2da --- /dev/null +++ b/sound/soc/codecs/ak4641.c | |||
| @@ -0,0 +1,664 @@ | |||
| 1 | /* | ||
| 2 | * ak4641.c -- AK4641 ALSA Soc Audio driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Harald Welte <laforge@gnufiish.org> | ||
| 5 | * Copyright (C) 2011 Dmitry Artamonow <mad_soft@inbox.ru> | ||
| 6 | * | ||
| 7 | * Based on ak4535.c by Richard Purdie | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/gpio.h> | ||
| 18 | #include <linux/pm.h> | ||
| 19 | #include <linux/i2c.h> | ||
| 20 | #include <linux/platform_device.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <sound/core.h> | ||
| 23 | #include <sound/pcm.h> | ||
| 24 | #include <sound/pcm_params.h> | ||
| 25 | #include <sound/soc.h> | ||
| 26 | #include <sound/initval.h> | ||
| 27 | #include <sound/tlv.h> | ||
| 28 | #include <sound/ak4641.h> | ||
| 29 | |||
| 30 | #include "ak4641.h" | ||
| 31 | |||
| 32 | /* codec private data */ | ||
| 33 | struct ak4641_priv { | ||
| 34 | struct snd_soc_codec *codec; | ||
| 35 | unsigned int sysclk; | ||
| 36 | int deemph; | ||
| 37 | int playback_fs; | ||
| 38 | }; | ||
| 39 | |||
| 40 | /* | ||
| 41 | * ak4641 register cache | ||
| 42 | */ | ||
| 43 | static const u8 ak4641_reg[AK4641_CACHEREGNUM] = { | ||
| 44 | 0x00, 0x80, 0x00, 0x80, | ||
| 45 | 0x02, 0x00, 0x11, 0x05, | ||
| 46 | 0x00, 0x00, 0x36, 0x10, | ||
| 47 | 0x00, 0x00, 0x57, 0x00, | ||
| 48 | 0x88, 0x88, 0x08, 0x08 | ||
| 49 | }; | ||
| 50 | |||
| 51 | static const int deemph_settings[] = {44100, 0, 48000, 32000}; | ||
| 52 | |||
| 53 | static int ak4641_set_deemph(struct snd_soc_codec *codec) | ||
| 54 | { | ||
| 55 | struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); | ||
| 56 | int i, best = 0; | ||
| 57 | |||
| 58 | for (i = 0 ; i < ARRAY_SIZE(deemph_settings); i++) { | ||
| 59 | /* if deemphasis is on, select the nearest available rate */ | ||
| 60 | if (ak4641->deemph && deemph_settings[i] != 0 && | ||
| 61 | abs(deemph_settings[i] - ak4641->playback_fs) < | ||
| 62 | abs(deemph_settings[best] - ak4641->playback_fs)) | ||
| 63 | best = i; | ||
| 64 | |||
| 65 | if (!ak4641->deemph && deemph_settings[i] == 0) | ||
| 66 | best = i; | ||
| 67 | } | ||
| 68 | |||
| 69 | dev_dbg(codec->dev, "Set deemphasis %d\n", best); | ||
| 70 | |||
| 71 | return snd_soc_update_bits(codec, AK4641_DAC, 0x3, best); | ||
| 72 | } | ||
| 73 | |||
| 74 | static int ak4641_put_deemph(struct snd_kcontrol *kcontrol, | ||
| 75 | struct snd_ctl_elem_value *ucontrol) | ||
| 76 | { | ||
| 77 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 78 | struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); | ||
| 79 | int deemph = ucontrol->value.enumerated.item[0]; | ||
| 80 | |||
| 81 | if (deemph > 1) | ||
| 82 | return -EINVAL; | ||
| 83 | |||
| 84 | ak4641->deemph = deemph; | ||
| 85 | |||
| 86 | return ak4641_set_deemph(codec); | ||
| 87 | } | ||
| 88 | |||
| 89 | static int ak4641_get_deemph(struct snd_kcontrol *kcontrol, | ||
| 90 | struct snd_ctl_elem_value *ucontrol) | ||
| 91 | { | ||
| 92 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 93 | struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); | ||
| 94 | |||
| 95 | ucontrol->value.enumerated.item[0] = ak4641->deemph; | ||
| 96 | return 0; | ||
| 97 | }; | ||
| 98 | |||
| 99 | static const char *ak4641_mono_out[] = {"(L + R)/2", "Hi-Z"}; | ||
| 100 | static const char *ak4641_hp_out[] = {"Stereo", "Mono"}; | ||
| 101 | static const char *ak4641_mic_select[] = {"Internal", "External"}; | ||
| 102 | static const char *ak4641_mic_or_dac[] = {"Microphone", "Voice DAC"}; | ||
| 103 | |||
| 104 | |||
| 105 | static const DECLARE_TLV_DB_SCALE(mono_gain_tlv, -1700, 2300, 0); | ||
| 106 | static const DECLARE_TLV_DB_SCALE(mic_boost_tlv, 0, 2000, 0); | ||
| 107 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1050, 150, 0); | ||
| 108 | static const DECLARE_TLV_DB_SCALE(master_tlv, -12750, 50, 0); | ||
| 109 | static const DECLARE_TLV_DB_SCALE(mic_stereo_sidetone_tlv, -2700, 300, 0); | ||
| 110 | static const DECLARE_TLV_DB_SCALE(mic_mono_sidetone_tlv, -400, 400, 0); | ||
| 111 | static const DECLARE_TLV_DB_SCALE(capture_tlv, -800, 50, 0); | ||
| 112 | static const DECLARE_TLV_DB_SCALE(alc_tlv, -800, 50, 0); | ||
| 113 | static const DECLARE_TLV_DB_SCALE(aux_in_tlv, -2100, 300, 0); | ||
| 114 | |||
| 115 | |||
| 116 | static const struct soc_enum ak4641_mono_out_enum = | ||
| 117 | SOC_ENUM_SINGLE(AK4641_SIG1, 6, 2, ak4641_mono_out); | ||
| 118 | static const struct soc_enum ak4641_hp_out_enum = | ||
| 119 | SOC_ENUM_SINGLE(AK4641_MODE2, 2, 2, ak4641_hp_out); | ||
| 120 | static const struct soc_enum ak4641_mic_select_enum = | ||
| 121 | SOC_ENUM_SINGLE(AK4641_MIC, 1, 2, ak4641_mic_select); | ||
| 122 | static const struct soc_enum ak4641_mic_or_dac_enum = | ||
| 123 | SOC_ENUM_SINGLE(AK4641_BTIF, 4, 2, ak4641_mic_or_dac); | ||
| 124 | |||
| 125 | static const struct snd_kcontrol_new ak4641_snd_controls[] = { | ||
| 126 | SOC_ENUM("Mono 1 Output", ak4641_mono_out_enum), | ||
| 127 | SOC_SINGLE_TLV("Mono 1 Gain Volume", AK4641_SIG1, 7, 1, 1, | ||
| 128 | mono_gain_tlv), | ||
| 129 | SOC_ENUM("Headphone Output", ak4641_hp_out_enum), | ||
| 130 | SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0, | ||
| 131 | ak4641_get_deemph, ak4641_put_deemph), | ||
| 132 | |||
| 133 | SOC_SINGLE_TLV("Mic Boost Volume", AK4641_MIC, 0, 1, 0, mic_boost_tlv), | ||
| 134 | |||
| 135 | SOC_SINGLE("ALC Operation Time", AK4641_TIMER, 0, 3, 0), | ||
| 136 | SOC_SINGLE("ALC Recovery Time", AK4641_TIMER, 2, 3, 0), | ||
| 137 | SOC_SINGLE("ALC ZC Time", AK4641_TIMER, 4, 3, 0), | ||
| 138 | |||
| 139 | SOC_SINGLE("ALC 1 Switch", AK4641_ALC1, 5, 1, 0), | ||
| 140 | |||
| 141 | SOC_SINGLE_TLV("ALC Volume", AK4641_ALC2, 0, 71, 0, alc_tlv), | ||
| 142 | SOC_SINGLE("Left Out Enable Switch", AK4641_SIG2, 1, 1, 0), | ||
| 143 | SOC_SINGLE("Right Out Enable Switch", AK4641_SIG2, 0, 1, 0), | ||
| 144 | |||
| 145 | SOC_SINGLE_TLV("Capture Volume", AK4641_PGA, 0, 71, 0, capture_tlv), | ||
| 146 | |||
| 147 | SOC_DOUBLE_R_TLV("Master Playback Volume", AK4641_LATT, | ||
| 148 | AK4641_RATT, 0, 255, 1, master_tlv), | ||
| 149 | |||
| 150 | SOC_SINGLE_TLV("AUX In Volume", AK4641_VOL, 0, 15, 0, aux_in_tlv), | ||
| 151 | |||
| 152 | SOC_SINGLE("Equalizer Switch", AK4641_DAC, 2, 1, 0), | ||
| 153 | SOC_SINGLE_TLV("EQ1 100 Hz Volume", AK4641_EQLO, 0, 15, 1, eq_tlv), | ||
| 154 | SOC_SINGLE_TLV("EQ2 250 Hz Volume", AK4641_EQLO, 4, 15, 1, eq_tlv), | ||
| 155 | SOC_SINGLE_TLV("EQ3 1 kHz Volume", AK4641_EQMID, 0, 15, 1, eq_tlv), | ||
| 156 | SOC_SINGLE_TLV("EQ4 3.5 kHz Volume", AK4641_EQMID, 4, 15, 1, eq_tlv), | ||
| 157 | SOC_SINGLE_TLV("EQ5 10 kHz Volume", AK4641_EQHI, 0, 15, 1, eq_tlv), | ||
| 158 | }; | ||
| 159 | |||
| 160 | /* Mono 1 Mixer */ | ||
| 161 | static const struct snd_kcontrol_new ak4641_mono1_mixer_controls[] = { | ||
| 162 | SOC_DAPM_SINGLE_TLV("Mic Mono Sidetone Volume", AK4641_VOL, 7, 1, 0, | ||
| 163 | mic_mono_sidetone_tlv), | ||
| 164 | SOC_DAPM_SINGLE("Mic Mono Sidetone Switch", AK4641_SIG1, 4, 1, 0), | ||
| 165 | SOC_DAPM_SINGLE("Mono Playback Switch", AK4641_SIG1, 5, 1, 0), | ||
| 166 | }; | ||
| 167 | |||
| 168 | /* Stereo Mixer */ | ||
| 169 | static const struct snd_kcontrol_new ak4641_stereo_mixer_controls[] = { | ||
| 170 | SOC_DAPM_SINGLE_TLV("Mic Sidetone Volume", AK4641_VOL, 4, 7, 0, | ||
| 171 | mic_stereo_sidetone_tlv), | ||
| 172 | SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4641_SIG2, 4, 1, 0), | ||
| 173 | SOC_DAPM_SINGLE("Playback Switch", AK4641_SIG2, 7, 1, 0), | ||
| 174 | SOC_DAPM_SINGLE("Aux Bypass Switch", AK4641_SIG2, 5, 1, 0), | ||
| 175 | }; | ||
| 176 | |||
| 177 | /* Input Mixer */ | ||
| 178 | static const struct snd_kcontrol_new ak4641_input_mixer_controls[] = { | ||
| 179 | SOC_DAPM_SINGLE("Mic Capture Switch", AK4641_MIC, 2, 1, 0), | ||
| 180 | SOC_DAPM_SINGLE("Aux Capture Switch", AK4641_MIC, 5, 1, 0), | ||
| 181 | }; | ||
| 182 | |||
| 183 | /* Mic mux */ | ||
| 184 | static const struct snd_kcontrol_new ak4641_mic_mux_control = | ||
| 185 | SOC_DAPM_ENUM("Mic Select", ak4641_mic_select_enum); | ||
| 186 | |||
| 187 | /* Input mux */ | ||
| 188 | static const struct snd_kcontrol_new ak4641_input_mux_control = | ||
| 189 | SOC_DAPM_ENUM("Input Select", ak4641_mic_or_dac_enum); | ||
| 190 | |||
| 191 | /* mono 2 switch */ | ||
| 192 | static const struct snd_kcontrol_new ak4641_mono2_control = | ||
| 193 | SOC_DAPM_SINGLE("Switch", AK4641_SIG1, 0, 1, 0); | ||
| 194 | |||
| 195 | /* ak4641 dapm widgets */ | ||
| 196 | static const struct snd_soc_dapm_widget ak4641_dapm_widgets[] = { | ||
| 197 | SND_SOC_DAPM_MIXER("Stereo Mixer", SND_SOC_NOPM, 0, 0, | ||
| 198 | &ak4641_stereo_mixer_controls[0], | ||
| 199 | ARRAY_SIZE(ak4641_stereo_mixer_controls)), | ||
| 200 | SND_SOC_DAPM_MIXER("Mono1 Mixer", SND_SOC_NOPM, 0, 0, | ||
| 201 | &ak4641_mono1_mixer_controls[0], | ||
| 202 | ARRAY_SIZE(ak4641_mono1_mixer_controls)), | ||
| 203 | SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, | ||
| 204 | &ak4641_input_mixer_controls[0], | ||
| 205 | ARRAY_SIZE(ak4641_input_mixer_controls)), | ||
| 206 | SND_SOC_DAPM_MUX("Mic Mux", SND_SOC_NOPM, 0, 0, | ||
| 207 | &ak4641_mic_mux_control), | ||
| 208 | SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, | ||
| 209 | &ak4641_input_mux_control), | ||
| 210 | SND_SOC_DAPM_SWITCH("Mono 2 Enable", SND_SOC_NOPM, 0, 0, | ||
| 211 | &ak4641_mono2_control), | ||
| 212 | |||
| 213 | SND_SOC_DAPM_OUTPUT("LOUT"), | ||
| 214 | SND_SOC_DAPM_OUTPUT("ROUT"), | ||
| 215 | SND_SOC_DAPM_OUTPUT("MOUT1"), | ||
| 216 | SND_SOC_DAPM_OUTPUT("MOUT2"), | ||
| 217 | SND_SOC_DAPM_OUTPUT("MICOUT"), | ||
| 218 | |||
| 219 | SND_SOC_DAPM_ADC("ADC", "HiFi Capture", AK4641_PM1, 0, 0), | ||
| 220 | SND_SOC_DAPM_PGA("Mic", AK4641_PM1, 1, 0, NULL, 0), | ||
| 221 | SND_SOC_DAPM_PGA("AUX In", AK4641_PM1, 2, 0, NULL, 0), | ||
| 222 | SND_SOC_DAPM_PGA("Mono Out", AK4641_PM1, 3, 0, NULL, 0), | ||
| 223 | SND_SOC_DAPM_PGA("Line Out", AK4641_PM1, 4, 0, NULL, 0), | ||
| 224 | |||
| 225 | SND_SOC_DAPM_DAC("DAC", "HiFi Playback", AK4641_PM2, 0, 0), | ||
| 226 | SND_SOC_DAPM_PGA("Mono Out 2", AK4641_PM2, 3, 0, NULL, 0), | ||
| 227 | |||
| 228 | SND_SOC_DAPM_ADC("Voice ADC", "Voice Capture", AK4641_BTIF, 0, 0), | ||
| 229 | SND_SOC_DAPM_ADC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0), | ||
| 230 | |||
| 231 | SND_SOC_DAPM_MICBIAS("Mic Int Bias", AK4641_MIC, 3, 0), | ||
| 232 | SND_SOC_DAPM_MICBIAS("Mic Ext Bias", AK4641_MIC, 4, 0), | ||
| 233 | |||
| 234 | SND_SOC_DAPM_INPUT("MICIN"), | ||
| 235 | SND_SOC_DAPM_INPUT("MICEXT"), | ||
| 236 | SND_SOC_DAPM_INPUT("AUX"), | ||
| 237 | SND_SOC_DAPM_INPUT("AIN"), | ||
| 238 | }; | ||
| 239 | |||
| 240 | static const struct snd_soc_dapm_route ak4641_audio_map[] = { | ||
| 241 | /* Stereo Mixer */ | ||
| 242 | {"Stereo Mixer", "Playback Switch", "DAC"}, | ||
| 243 | {"Stereo Mixer", "Mic Sidetone Switch", "Input Mux"}, | ||
| 244 | {"Stereo Mixer", "Aux Bypass Switch", "AUX In"}, | ||
| 245 | |||
| 246 | /* Mono 1 Mixer */ | ||
| 247 | {"Mono1 Mixer", "Mic Mono Sidetone Switch", "Input Mux"}, | ||
| 248 | {"Mono1 Mixer", "Mono Playback Switch", "DAC"}, | ||
| 249 | |||
| 250 | /* Mic */ | ||
| 251 | {"Mic", NULL, "AIN"}, | ||
| 252 | {"Mic Mux", "Internal", "Mic Int Bias"}, | ||
| 253 | {"Mic Mux", "External", "Mic Ext Bias"}, | ||
| 254 | {"Mic Int Bias", NULL, "MICIN"}, | ||
| 255 | {"Mic Ext Bias", NULL, "MICEXT"}, | ||
| 256 | {"MICOUT", NULL, "Mic Mux"}, | ||
| 257 | |||
| 258 | /* Input Mux */ | ||
| 259 | {"Input Mux", "Microphone", "Mic"}, | ||
| 260 | {"Input Mux", "Voice DAC", "Voice DAC"}, | ||
| 261 | |||
| 262 | /* Line Out */ | ||
| 263 | {"LOUT", NULL, "Line Out"}, | ||
| 264 | {"ROUT", NULL, "Line Out"}, | ||
| 265 | {"Line Out", NULL, "Stereo Mixer"}, | ||
| 266 | |||
| 267 | /* Mono 1 Out */ | ||
| 268 | {"MOUT1", NULL, "Mono Out"}, | ||
| 269 | {"Mono Out", NULL, "Mono1 Mixer"}, | ||
| 270 | |||
| 271 | /* Mono 2 Out */ | ||
| 272 | {"MOUT2", NULL, "Mono 2 Enable"}, | ||
| 273 | {"Mono 2 Enable", "Switch", "Mono Out 2"}, | ||
| 274 | {"Mono Out 2", NULL, "Stereo Mixer"}, | ||
| 275 | |||
| 276 | {"Voice ADC", NULL, "Mono 2 Enable"}, | ||
| 277 | |||
| 278 | /* Aux In */ | ||
| 279 | {"AUX In", NULL, "AUX"}, | ||
| 280 | |||
| 281 | /* ADC */ | ||
| 282 | {"ADC", NULL, "Input Mixer"}, | ||
| 283 | {"Input Mixer", "Mic Capture Switch", "Mic"}, | ||
| 284 | {"Input Mixer", "Aux Capture Switch", "AUX In"}, | ||
| 285 | }; | ||
| 286 | |||
| 287 | static int ak4641_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
| 288 | int clk_id, unsigned int freq, int dir) | ||
| 289 | { | ||
| 290 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 291 | struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); | ||
| 292 | |||
| 293 | ak4641->sysclk = freq; | ||
| 294 | return 0; | ||
| 295 | } | ||
| 296 | |||
| 297 | static int ak4641_i2s_hw_params(struct snd_pcm_substream *substream, | ||
| 298 | struct snd_pcm_hw_params *params, | ||
| 299 | struct snd_soc_dai *dai) | ||
| 300 | { | ||
| 301 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 302 | struct snd_soc_codec *codec = rtd->codec; | ||
| 303 | struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); | ||
| 304 | int rate = params_rate(params), fs = 256; | ||
| 305 | u8 mode2; | ||
| 306 | |||
| 307 | if (rate) | ||
| 308 | fs = ak4641->sysclk / rate; | ||
| 309 | else | ||
| 310 | return -EINVAL; | ||
| 311 | |||
| 312 | /* set fs */ | ||
| 313 | switch (fs) { | ||
| 314 | case 1024: | ||
| 315 | mode2 = (0x2 << 5); | ||
| 316 | break; | ||
| 317 | case 512: | ||
| 318 | mode2 = (0x1 << 5); | ||
| 319 | break; | ||
| 320 | case 256: | ||
| 321 | mode2 = (0x0 << 5); | ||
| 322 | break; | ||
| 323 | default: | ||
| 324 | dev_err(codec->dev, "Error: unsupported fs=%d\n", fs); | ||
| 325 | return -EINVAL; | ||
| 326 | } | ||
| 327 | |||
| 328 | snd_soc_update_bits(codec, AK4641_MODE2, (0x3 << 5), mode2); | ||
| 329 | |||
| 330 | /* Update de-emphasis filter for the new rate */ | ||
| 331 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
| 332 | ak4641->playback_fs = rate; | ||
| 333 | ak4641_set_deemph(codec); | ||
| 334 | }; | ||
| 335 | |||
| 336 | return 0; | ||
| 337 | } | ||
| 338 | |||
| 339 | static int ak4641_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
| 340 | unsigned int fmt) | ||
| 341 | { | ||
| 342 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 343 | u8 btif; | ||
| 344 | |||
| 345 | /* interface format */ | ||
| 346 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
| 347 | case SND_SOC_DAIFMT_I2S: | ||
| 348 | btif = (0x3 << 5); | ||
| 349 | break; | ||
| 350 | case SND_SOC_DAIFMT_LEFT_J: | ||
| 351 | btif = (0x2 << 5); | ||
| 352 | break; | ||
| 353 | case SND_SOC_DAIFMT_DSP_A: /* MSB after FRM */ | ||
| 354 | btif = (0x0 << 5); | ||
| 355 | break; | ||
| 356 | case SND_SOC_DAIFMT_DSP_B: /* MSB during FRM */ | ||
| 357 | btif = (0x1 << 5); | ||
| 358 | break; | ||
| 359 | default: | ||
| 360 | return -EINVAL; | ||
| 361 | } | ||
| 362 | |||
| 363 | return snd_soc_update_bits(codec, AK4641_BTIF, (0x3 << 5), btif); | ||
| 364 | } | ||
| 365 | |||
| 366 | static int ak4641_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
| 367 | unsigned int fmt) | ||
| 368 | { | ||
| 369 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 370 | u8 mode1 = 0; | ||
| 371 | |||
| 372 | /* interface format */ | ||
| 373 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
| 374 | case SND_SOC_DAIFMT_I2S: | ||
| 375 | mode1 = 0x02; | ||
| 376 | break; | ||
| 377 | case SND_SOC_DAIFMT_LEFT_J: | ||
| 378 | mode1 = 0x01; | ||
| 379 | break; | ||
| 380 | default: | ||
| 381 | return -EINVAL; | ||
| 382 | } | ||
| 383 | |||
| 384 | return snd_soc_write(codec, AK4641_MODE1, mode1); | ||
| 385 | } | ||
| 386 | |||
| 387 | static int ak4641_mute(struct snd_soc_dai *dai, int mute) | ||
| 388 | { | ||
| 389 | struct snd_soc_codec *codec = dai->codec; | ||
| 390 | |||
| 391 | return snd_soc_update_bits(codec, AK4641_DAC, 0x20, mute ? 0x20 : 0); | ||
| 392 | } | ||
| 393 | |||
| 394 | static int ak4641_set_bias_level(struct snd_soc_codec *codec, | ||
| 395 | enum snd_soc_bias_level level) | ||
| 396 | { | ||
| 397 | struct ak4641_platform_data *pdata = codec->dev->platform_data; | ||
| 398 | int ret; | ||
| 399 | |||
| 400 | switch (level) { | ||
| 401 | case SND_SOC_BIAS_ON: | ||
| 402 | /* unmute */ | ||
| 403 | snd_soc_update_bits(codec, AK4641_DAC, 0x20, 0); | ||
| 404 | break; | ||
| 405 | case SND_SOC_BIAS_PREPARE: | ||
| 406 | /* mute */ | ||
| 407 | snd_soc_update_bits(codec, AK4641_DAC, 0x20, 0x20); | ||
| 408 | break; | ||
| 409 | case SND_SOC_BIAS_STANDBY: | ||
| 410 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
| 411 | if (pdata && gpio_is_valid(pdata->gpio_power)) | ||
| 412 | gpio_set_value(pdata->gpio_power, 1); | ||
| 413 | mdelay(1); | ||
| 414 | if (pdata && gpio_is_valid(pdata->gpio_npdn)) | ||
| 415 | gpio_set_value(pdata->gpio_npdn, 1); | ||
| 416 | mdelay(1); | ||
| 417 | |||
| 418 | ret = snd_soc_cache_sync(codec); | ||
| 419 | if (ret) { | ||
| 420 | dev_err(codec->dev, | ||
| 421 | "Failed to sync cache: %d\n", ret); | ||
| 422 | return ret; | ||
| 423 | } | ||
| 424 | } | ||
| 425 | snd_soc_update_bits(codec, AK4641_PM1, 0x80, 0x80); | ||
| 426 | snd_soc_update_bits(codec, AK4641_PM2, 0x80, 0); | ||
| 427 | break; | ||
| 428 | case SND_SOC_BIAS_OFF: | ||
| 429 | snd_soc_update_bits(codec, AK4641_PM1, 0x80, 0); | ||
| 430 | if (pdata && gpio_is_valid(pdata->gpio_npdn)) | ||
| 431 | gpio_set_value(pdata->gpio_npdn, 0); | ||
| 432 | if (pdata && gpio_is_valid(pdata->gpio_power)) | ||
| 433 | gpio_set_value(pdata->gpio_power, 0); | ||
| 434 | codec->cache_sync = 1; | ||
| 435 | break; | ||
| 436 | } | ||
| 437 | codec->dapm.bias_level = level; | ||
| 438 | return 0; | ||
| 439 | } | ||
| 440 | |||
| 441 | #define AK4641_RATES (SNDRV_PCM_RATE_8000_48000) | ||
| 442 | #define AK4641_RATES_BT (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | ||
| 443 | SNDRV_PCM_RATE_16000) | ||
| 444 | #define AK4641_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) | ||
| 445 | |||
| 446 | static struct snd_soc_dai_ops ak4641_i2s_dai_ops = { | ||
| 447 | .hw_params = ak4641_i2s_hw_params, | ||
| 448 | .set_fmt = ak4641_i2s_set_dai_fmt, | ||
| 449 | .digital_mute = ak4641_mute, | ||
| 450 | .set_sysclk = ak4641_set_dai_sysclk, | ||
| 451 | }; | ||
| 452 | |||
| 453 | static struct snd_soc_dai_ops ak4641_pcm_dai_ops = { | ||
| 454 | .hw_params = NULL, /* rates are controlled by BT chip */ | ||
| 455 | .set_fmt = ak4641_pcm_set_dai_fmt, | ||
| 456 | .digital_mute = ak4641_mute, | ||
| 457 | .set_sysclk = ak4641_set_dai_sysclk, | ||
| 458 | }; | ||
| 459 | |||
| 460 | struct snd_soc_dai_driver ak4641_dai[] = { | ||
| 461 | { | ||
| 462 | .name = "ak4641-hifi", | ||
| 463 | .id = 1, | ||
| 464 | .playback = { | ||
| 465 | .stream_name = "HiFi Playback", | ||
| 466 | .channels_min = 1, | ||
| 467 | .channels_max = 2, | ||
| 468 | .rates = AK4641_RATES, | ||
| 469 | .formats = AK4641_FORMATS, | ||
| 470 | }, | ||
| 471 | .capture = { | ||
| 472 | .stream_name = "HiFi Capture", | ||
| 473 | .channels_min = 1, | ||
| 474 | .channels_max = 2, | ||
| 475 | .rates = AK4641_RATES, | ||
| 476 | .formats = AK4641_FORMATS, | ||
| 477 | }, | ||
| 478 | .ops = &ak4641_i2s_dai_ops, | ||
| 479 | .symmetric_rates = 1, | ||
| 480 | }, | ||
| 481 | { | ||
| 482 | .name = "ak4641-voice", | ||
| 483 | .id = 1, | ||
| 484 | .playback = { | ||
| 485 | .stream_name = "Voice Playback", | ||
| 486 | .channels_min = 1, | ||
| 487 | .channels_max = 1, | ||
| 488 | .rates = AK4641_RATES_BT, | ||
| 489 | .formats = AK4641_FORMATS, | ||
| 490 | }, | ||
| 491 | .capture = { | ||
| 492 | .stream_name = "Voice Capture", | ||
| 493 | .channels_min = 1, | ||
| 494 | .channels_max = 1, | ||
| 495 | .rates = AK4641_RATES_BT, | ||
| 496 | .formats = AK4641_FORMATS, | ||
| 497 | }, | ||
| 498 | .ops = &ak4641_pcm_dai_ops, | ||
| 499 | .symmetric_rates = 1, | ||
| 500 | }, | ||
| 501 | }; | ||
| 502 | |||
| 503 | static int ak4641_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
| 504 | { | ||
| 505 | ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
| 506 | return 0; | ||
| 507 | } | ||
| 508 | |||
| 509 | static int ak4641_resume(struct snd_soc_codec *codec) | ||
| 510 | { | ||
| 511 | ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
| 512 | return 0; | ||
| 513 | } | ||
| 514 | |||
| 515 | static int ak4641_probe(struct snd_soc_codec *codec) | ||
| 516 | { | ||
| 517 | struct ak4641_platform_data *pdata = codec->dev->platform_data; | ||
| 518 | int ret; | ||
| 519 | |||
| 520 | |||
| 521 | if (pdata) { | ||
| 522 | if (gpio_is_valid(pdata->gpio_power)) { | ||
| 523 | ret = gpio_request_one(pdata->gpio_power, | ||
| 524 | GPIOF_OUT_INIT_LOW, "ak4641 power"); | ||
| 525 | if (ret) | ||
| 526 | goto err_out; | ||
| 527 | } | ||
| 528 | if (gpio_is_valid(pdata->gpio_npdn)) { | ||
| 529 | ret = gpio_request_one(pdata->gpio_npdn, | ||
| 530 | GPIOF_OUT_INIT_LOW, "ak4641 npdn"); | ||
| 531 | if (ret) | ||
| 532 | goto err_gpio; | ||
| 533 | |||
| 534 | udelay(1); /* > 150 ns */ | ||
| 535 | gpio_set_value(pdata->gpio_npdn, 1); | ||
| 536 | } | ||
| 537 | } | ||
| 538 | |||
| 539 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | ||
| 540 | if (ret != 0) { | ||
| 541 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
| 542 | goto err_register; | ||
| 543 | } | ||
| 544 | |||
| 545 | /* power on device */ | ||
| 546 | ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
| 547 | |||
| 548 | return 0; | ||
| 549 | |||
| 550 | err_register: | ||
| 551 | if (pdata) { | ||
| 552 | if (gpio_is_valid(pdata->gpio_power)) | ||
| 553 | gpio_set_value(pdata->gpio_power, 0); | ||
| 554 | if (gpio_is_valid(pdata->gpio_npdn)) | ||
| 555 | gpio_free(pdata->gpio_npdn); | ||
| 556 | } | ||
| 557 | err_gpio: | ||
| 558 | if (pdata && gpio_is_valid(pdata->gpio_power)) | ||
| 559 | gpio_free(pdata->gpio_power); | ||
| 560 | err_out: | ||
| 561 | return ret; | ||
| 562 | } | ||
| 563 | |||
| 564 | static int ak4641_remove(struct snd_soc_codec *codec) | ||
| 565 | { | ||
| 566 | struct ak4641_platform_data *pdata = codec->dev->platform_data; | ||
| 567 | |||
| 568 | ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
| 569 | |||
| 570 | if (pdata) { | ||
| 571 | if (gpio_is_valid(pdata->gpio_power)) { | ||
| 572 | gpio_set_value(pdata->gpio_power, 0); | ||
| 573 | gpio_free(pdata->gpio_power); | ||
| 574 | } | ||
| 575 | if (gpio_is_valid(pdata->gpio_npdn)) | ||
| 576 | gpio_free(pdata->gpio_npdn); | ||
| 577 | } | ||
| 578 | return 0; | ||
| 579 | } | ||
| 580 | |||
| 581 | |||
| 582 | static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { | ||
| 583 | .probe = ak4641_probe, | ||
| 584 | .remove = ak4641_remove, | ||
| 585 | .suspend = ak4641_suspend, | ||
| 586 | .resume = ak4641_resume, | ||
| 587 | .controls = ak4641_snd_controls, | ||
| 588 | .num_controls = ARRAY_SIZE(ak4641_snd_controls), | ||
| 589 | .dapm_widgets = ak4641_dapm_widgets, | ||
| 590 | .num_dapm_widgets = ARRAY_SIZE(ak4641_dapm_widgets), | ||
| 591 | .dapm_routes = ak4641_audio_map, | ||
| 592 | .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), | ||
| 593 | .set_bias_level = ak4641_set_bias_level, | ||
| 594 | .reg_cache_size = ARRAY_SIZE(ak4641_reg), | ||
| 595 | .reg_word_size = sizeof(u8), | ||
| 596 | .reg_cache_default = ak4641_reg, | ||
| 597 | .reg_cache_step = 1, | ||
| 598 | }; | ||
| 599 | |||
| 600 | |||
| 601 | static int __devinit ak4641_i2c_probe(struct i2c_client *i2c, | ||
| 602 | const struct i2c_device_id *id) | ||
| 603 | { | ||
| 604 | struct ak4641_priv *ak4641; | ||
| 605 | int ret; | ||
| 606 | |||
| 607 | ak4641 = kzalloc(sizeof(struct ak4641_priv), GFP_KERNEL); | ||
| 608 | if (!ak4641) | ||
| 609 | return -ENOMEM; | ||
| 610 | |||
| 611 | i2c_set_clientdata(i2c, ak4641); | ||
| 612 | |||
| 613 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_ak4641, | ||
| 614 | ak4641_dai, ARRAY_SIZE(ak4641_dai)); | ||
| 615 | if (ret < 0) | ||
| 616 | kfree(ak4641); | ||
| 617 | |||
| 618 | return ret; | ||
| 619 | } | ||
| 620 | |||
| 621 | static int __devexit ak4641_i2c_remove(struct i2c_client *i2c) | ||
| 622 | { | ||
| 623 | snd_soc_unregister_codec(&i2c->dev); | ||
| 624 | kfree(i2c_get_clientdata(i2c)); | ||
| 625 | return 0; | ||
| 626 | } | ||
| 627 | |||
| 628 | static const struct i2c_device_id ak4641_i2c_id[] = { | ||
| 629 | { "ak4641", 0 }, | ||
| 630 | { } | ||
| 631 | }; | ||
| 632 | MODULE_DEVICE_TABLE(i2c, ak4641_i2c_id); | ||
| 633 | |||
| 634 | static struct i2c_driver ak4641_i2c_driver = { | ||
| 635 | .driver = { | ||
| 636 | .name = "ak4641", | ||
| 637 | .owner = THIS_MODULE, | ||
| 638 | }, | ||
| 639 | .probe = ak4641_i2c_probe, | ||
| 640 | .remove = __devexit_p(ak4641_i2c_remove), | ||
| 641 | .id_table = ak4641_i2c_id, | ||
| 642 | }; | ||
| 643 | |||
| 644 | static int __init ak4641_modinit(void) | ||
| 645 | { | ||
| 646 | int ret; | ||
| 647 | |||
| 648 | ret = i2c_add_driver(&ak4641_i2c_driver); | ||
| 649 | if (ret != 0) | ||
| 650 | pr_err("Failed to register AK4641 I2C driver: %d\n", ret); | ||
| 651 | |||
| 652 | return ret; | ||
| 653 | } | ||
| 654 | module_init(ak4641_modinit); | ||
| 655 | |||
| 656 | static void __exit ak4641_exit(void) | ||
| 657 | { | ||
| 658 | i2c_del_driver(&ak4641_i2c_driver); | ||
| 659 | } | ||
| 660 | module_exit(ak4641_exit); | ||
| 661 | |||
| 662 | MODULE_DESCRIPTION("SoC AK4641 driver"); | ||
| 663 | MODULE_AUTHOR("Harald Welte <laforge@gnufiish.org>"); | ||
| 664 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ak4641.h b/sound/soc/codecs/ak4641.h new file mode 100644 index 000000000000..4a263248efea --- /dev/null +++ b/sound/soc/codecs/ak4641.h | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | /* | ||
| 2 | * ak4641.h -- AK4641 SoC Audio driver | ||
| 3 | * | ||
| 4 | * Copyright 2008 Harald Welte <laforge@gnufiish.org> | ||
| 5 | * | ||
| 6 | * Based on ak4535.h | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef _AK4641_H | ||
| 14 | #define _AK4641_H | ||
| 15 | |||
| 16 | /* AK4641 register space */ | ||
| 17 | |||
| 18 | #define AK4641_PM1 0x00 | ||
| 19 | #define AK4641_PM2 0x01 | ||
| 20 | #define AK4641_SIG1 0x02 | ||
| 21 | #define AK4641_SIG2 0x03 | ||
| 22 | #define AK4641_MODE1 0x04 | ||
| 23 | #define AK4641_MODE2 0x05 | ||
| 24 | #define AK4641_DAC 0x06 | ||
| 25 | #define AK4641_MIC 0x07 | ||
| 26 | #define AK4641_TIMER 0x08 | ||
| 27 | #define AK4641_ALC1 0x09 | ||
| 28 | #define AK4641_ALC2 0x0a | ||
| 29 | #define AK4641_PGA 0x0b | ||
| 30 | #define AK4641_LATT 0x0c | ||
| 31 | #define AK4641_RATT 0x0d | ||
| 32 | #define AK4641_VOL 0x0e | ||
| 33 | #define AK4641_STATUS 0x0f | ||
| 34 | #define AK4641_EQLO 0x10 | ||
| 35 | #define AK4641_EQMID 0x11 | ||
| 36 | #define AK4641_EQHI 0x12 | ||
| 37 | #define AK4641_BTIF 0x13 | ||
| 38 | |||
| 39 | #define AK4641_CACHEREGNUM 0x14 | ||
| 40 | |||
| 41 | |||
| 42 | |||
| 43 | #define AK4641_DAI_HIFI 0 | ||
| 44 | #define AK4641_DAI_VOICE 1 | ||
| 45 | |||
| 46 | |||
| 47 | #endif | ||
