diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/Kconfig | 4 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/codecs/nau8825.c | 1107 | ||||
-rw-r--r-- | sound/soc/codecs/nau8825.h | 323 |
4 files changed, 1436 insertions, 0 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0142396bb42c..cc60ab92b21d 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -79,6 +79,7 @@ config SND_SOC_ALL_CODECS | |||
79 | select SND_SOC_MAX9877 if I2C | 79 | select SND_SOC_MAX9877 if I2C |
80 | select SND_SOC_MC13783 if MFD_MC13XXX | 80 | select SND_SOC_MC13783 if MFD_MC13XXX |
81 | select SND_SOC_ML26124 if I2C | 81 | select SND_SOC_ML26124 if I2C |
82 | select SND_SOC_NAU8825 if I2C | ||
82 | select SND_SOC_PCM1681 if I2C | 83 | select SND_SOC_PCM1681 if I2C |
83 | select SND_SOC_PCM1792A if SPI_MASTER | 84 | select SND_SOC_PCM1792A if SPI_MASTER |
84 | select SND_SOC_PCM3008 | 85 | select SND_SOC_PCM3008 |
@@ -892,6 +893,9 @@ config SND_SOC_MC13783 | |||
892 | config SND_SOC_ML26124 | 893 | config SND_SOC_ML26124 |
893 | tristate | 894 | tristate |
894 | 895 | ||
896 | config SND_SOC_NAU8825 | ||
897 | tristate | ||
898 | |||
895 | config SND_SOC_TPA6130A2 | 899 | config SND_SOC_TPA6130A2 |
896 | tristate "Texas Instruments TPA6130A2 headphone amplifier" | 900 | tristate "Texas Instruments TPA6130A2 headphone amplifier" |
897 | depends on I2C | 901 | depends on I2C |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 7d7cc1b049c2..d7b0f41690b2 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -72,6 +72,7 @@ snd-soc-max98925-objs := max98925.o | |||
72 | snd-soc-max9850-objs := max9850.o | 72 | snd-soc-max9850-objs := max9850.o |
73 | snd-soc-mc13783-objs := mc13783.o | 73 | snd-soc-mc13783-objs := mc13783.o |
74 | snd-soc-ml26124-objs := ml26124.o | 74 | snd-soc-ml26124-objs := ml26124.o |
75 | snd-soc-nau8825-objs := nau8825.o | ||
75 | snd-soc-pcm1681-objs := pcm1681.o | 76 | snd-soc-pcm1681-objs := pcm1681.o |
76 | snd-soc-pcm1792a-codec-objs := pcm1792a.o | 77 | snd-soc-pcm1792a-codec-objs := pcm1792a.o |
77 | snd-soc-pcm3008-objs := pcm3008.o | 78 | snd-soc-pcm3008-objs := pcm3008.o |
@@ -263,6 +264,7 @@ obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o | |||
263 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o | 264 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o |
264 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o | 265 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o |
265 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o | 266 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o |
267 | obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o | ||
266 | obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o | 268 | obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o |
267 | obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o | 269 | obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o |
268 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o | 270 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o |
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c new file mode 100644 index 000000000000..f31a5008e879 --- /dev/null +++ b/sound/soc/codecs/nau8825.c | |||
@@ -0,0 +1,1107 @@ | |||
1 | /* | ||
2 | * Nuvoton NAU8825 audio codec driver | ||
3 | * | ||
4 | * Copyright 2015 Google Chromium project. | ||
5 | * Author: Anatol Pomozov <anatol@chromium.org> | ||
6 | * Copyright 2015 Nuvoton Technology Corp. | ||
7 | * Co-author: Meng-Huang Kuo <mhkuo@nuvoton.com> | ||
8 | * | ||
9 | * Licensed under the GPL-2. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <linux/regmap.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/clk.h> | ||
19 | |||
20 | #include <sound/initval.h> | ||
21 | #include <sound/tlv.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/jack.h> | ||
27 | |||
28 | |||
29 | #include "nau8825.h" | ||
30 | |||
31 | static const struct reg_default nau8825_reg_defaults[] = { | ||
32 | { NAU8825_REG_ENA_CTRL, 0x00ff }, | ||
33 | { NAU8825_REG_CLK_DIVIDER, 0x0050 }, | ||
34 | { NAU8825_REG_FLL1, 0x0 }, | ||
35 | { NAU8825_REG_FLL2, 0x3126 }, | ||
36 | { NAU8825_REG_FLL3, 0x0008 }, | ||
37 | { NAU8825_REG_FLL4, 0x0010 }, | ||
38 | { NAU8825_REG_FLL5, 0x0 }, | ||
39 | { NAU8825_REG_FLL6, 0x6000 }, | ||
40 | { NAU8825_REG_FLL_VCO_RSV, 0xf13c }, | ||
41 | { NAU8825_REG_HSD_CTRL, 0x000c }, | ||
42 | { NAU8825_REG_JACK_DET_CTRL, 0x0 }, | ||
43 | { NAU8825_REG_INTERRUPT_MASK, 0x0 }, | ||
44 | { NAU8825_REG_INTERRUPT_DIS_CTRL, 0xffff }, | ||
45 | { NAU8825_REG_SAR_CTRL, 0x0015 }, | ||
46 | { NAU8825_REG_KEYDET_CTRL, 0x0110 }, | ||
47 | { NAU8825_REG_VDET_THRESHOLD_1, 0x0 }, | ||
48 | { NAU8825_REG_VDET_THRESHOLD_2, 0x0 }, | ||
49 | { NAU8825_REG_VDET_THRESHOLD_3, 0x0 }, | ||
50 | { NAU8825_REG_VDET_THRESHOLD_4, 0x0 }, | ||
51 | { NAU8825_REG_GPIO34_CTRL, 0x0 }, | ||
52 | { NAU8825_REG_GPIO12_CTRL, 0x0 }, | ||
53 | { NAU8825_REG_TDM_CTRL, 0x0 }, | ||
54 | { NAU8825_REG_I2S_PCM_CTRL1, 0x000b }, | ||
55 | { NAU8825_REG_I2S_PCM_CTRL2, 0x8010 }, | ||
56 | { NAU8825_REG_LEFT_TIME_SLOT, 0x0 }, | ||
57 | { NAU8825_REG_RIGHT_TIME_SLOT, 0x0 }, | ||
58 | { NAU8825_REG_BIQ_CTRL, 0x0 }, | ||
59 | { NAU8825_REG_BIQ_COF1, 0x0 }, | ||
60 | { NAU8825_REG_BIQ_COF2, 0x0 }, | ||
61 | { NAU8825_REG_BIQ_COF3, 0x0 }, | ||
62 | { NAU8825_REG_BIQ_COF4, 0x0 }, | ||
63 | { NAU8825_REG_BIQ_COF5, 0x0 }, | ||
64 | { NAU8825_REG_BIQ_COF6, 0x0 }, | ||
65 | { NAU8825_REG_BIQ_COF7, 0x0 }, | ||
66 | { NAU8825_REG_BIQ_COF8, 0x0 }, | ||
67 | { NAU8825_REG_BIQ_COF9, 0x0 }, | ||
68 | { NAU8825_REG_BIQ_COF10, 0x0 }, | ||
69 | { NAU8825_REG_ADC_RATE, 0x0010 }, | ||
70 | { NAU8825_REG_DAC_CTRL1, 0x0001 }, | ||
71 | { NAU8825_REG_DAC_CTRL2, 0x0 }, | ||
72 | { NAU8825_REG_DAC_DGAIN_CTRL, 0x0 }, | ||
73 | { NAU8825_REG_ADC_DGAIN_CTRL, 0x00cf }, | ||
74 | { NAU8825_REG_MUTE_CTRL, 0x0 }, | ||
75 | { NAU8825_REG_HSVOL_CTRL, 0x0 }, | ||
76 | { NAU8825_REG_DACL_CTRL, 0x02cf }, | ||
77 | { NAU8825_REG_DACR_CTRL, 0x00cf }, | ||
78 | { NAU8825_REG_ADC_DRC_KNEE_IP12, 0x1486 }, | ||
79 | { NAU8825_REG_ADC_DRC_KNEE_IP34, 0x0f12 }, | ||
80 | { NAU8825_REG_ADC_DRC_SLOPES, 0x25ff }, | ||
81 | { NAU8825_REG_ADC_DRC_ATKDCY, 0x3457 }, | ||
82 | { NAU8825_REG_DAC_DRC_KNEE_IP12, 0x1486 }, | ||
83 | { NAU8825_REG_DAC_DRC_KNEE_IP34, 0x0f12 }, | ||
84 | { NAU8825_REG_DAC_DRC_SLOPES, 0x25f9 }, | ||
85 | { NAU8825_REG_DAC_DRC_ATKDCY, 0x3457 }, | ||
86 | { NAU8825_REG_IMM_MODE_CTRL, 0x0 }, | ||
87 | { NAU8825_REG_CLASSG_CTRL, 0x0 }, | ||
88 | { NAU8825_REG_OPT_EFUSE_CTRL, 0x0 }, | ||
89 | { NAU8825_REG_MISC_CTRL, 0x0 }, | ||
90 | { NAU8825_REG_BIAS_ADJ, 0x0 }, | ||
91 | { NAU8825_REG_TRIM_SETTINGS, 0x0 }, | ||
92 | { NAU8825_REG_ANALOG_CONTROL_1, 0x0 }, | ||
93 | { NAU8825_REG_ANALOG_CONTROL_2, 0x0 }, | ||
94 | { NAU8825_REG_ANALOG_ADC_1, 0x0011 }, | ||
95 | { NAU8825_REG_ANALOG_ADC_2, 0x0020 }, | ||
96 | { NAU8825_REG_RDAC, 0x0008 }, | ||
97 | { NAU8825_REG_MIC_BIAS, 0x0006 }, | ||
98 | { NAU8825_REG_BOOST, 0x0 }, | ||
99 | { NAU8825_REG_FEPGA, 0x0 }, | ||
100 | { NAU8825_REG_POWER_UP_CONTROL, 0x0 }, | ||
101 | { NAU8825_REG_CHARGE_PUMP, 0x0 }, | ||
102 | }; | ||
103 | |||
104 | static bool nau8825_readable_reg(struct device *dev, unsigned int reg) | ||
105 | { | ||
106 | switch (reg) { | ||
107 | case NAU8825_REG_ENA_CTRL: | ||
108 | case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV: | ||
109 | case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL: | ||
110 | case NAU8825_REG_INTERRUPT_MASK ... NAU8825_REG_KEYDET_CTRL: | ||
111 | case NAU8825_REG_VDET_THRESHOLD_1 ... NAU8825_REG_DACR_CTRL: | ||
112 | case NAU8825_REG_ADC_DRC_KNEE_IP12 ... NAU8825_REG_ADC_DRC_ATKDCY: | ||
113 | case NAU8825_REG_DAC_DRC_KNEE_IP12 ... NAU8825_REG_DAC_DRC_ATKDCY: | ||
114 | case NAU8825_REG_IMM_MODE_CTRL ... NAU8825_REG_IMM_RMS_R: | ||
115 | case NAU8825_REG_CLASSG_CTRL ... NAU8825_REG_OPT_EFUSE_CTRL: | ||
116 | case NAU8825_REG_MISC_CTRL: | ||
117 | case NAU8825_REG_I2C_DEVICE_ID ... NAU8825_REG_SARDOUT_RAM_STATUS: | ||
118 | case NAU8825_REG_BIAS_ADJ: | ||
119 | case NAU8825_REG_TRIM_SETTINGS ... NAU8825_REG_ANALOG_CONTROL_2: | ||
120 | case NAU8825_REG_ANALOG_ADC_1 ... NAU8825_REG_MIC_BIAS: | ||
121 | case NAU8825_REG_BOOST ... NAU8825_REG_FEPGA: | ||
122 | case NAU8825_REG_POWER_UP_CONTROL ... NAU8825_REG_GENERAL_STATUS: | ||
123 | return true; | ||
124 | default: | ||
125 | return false; | ||
126 | } | ||
127 | |||
128 | } | ||
129 | |||
130 | static bool nau8825_writeable_reg(struct device *dev, unsigned int reg) | ||
131 | { | ||
132 | switch (reg) { | ||
133 | case NAU8825_REG_RESET ... NAU8825_REG_ENA_CTRL: | ||
134 | case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV: | ||
135 | case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL: | ||
136 | case NAU8825_REG_INTERRUPT_MASK: | ||
137 | case NAU8825_REG_INT_CLR_KEY_STATUS ... NAU8825_REG_KEYDET_CTRL: | ||
138 | case NAU8825_REG_VDET_THRESHOLD_1 ... NAU8825_REG_DACR_CTRL: | ||
139 | case NAU8825_REG_ADC_DRC_KNEE_IP12 ... NAU8825_REG_ADC_DRC_ATKDCY: | ||
140 | case NAU8825_REG_DAC_DRC_KNEE_IP12 ... NAU8825_REG_DAC_DRC_ATKDCY: | ||
141 | case NAU8825_REG_IMM_MODE_CTRL: | ||
142 | case NAU8825_REG_CLASSG_CTRL ... NAU8825_REG_OPT_EFUSE_CTRL: | ||
143 | case NAU8825_REG_MISC_CTRL: | ||
144 | case NAU8825_REG_BIAS_ADJ: | ||
145 | case NAU8825_REG_TRIM_SETTINGS ... NAU8825_REG_ANALOG_CONTROL_2: | ||
146 | case NAU8825_REG_ANALOG_ADC_1 ... NAU8825_REG_MIC_BIAS: | ||
147 | case NAU8825_REG_BOOST ... NAU8825_REG_FEPGA: | ||
148 | case NAU8825_REG_POWER_UP_CONTROL ... NAU8825_REG_CHARGE_PUMP: | ||
149 | return true; | ||
150 | default: | ||
151 | return false; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static bool nau8825_volatile_reg(struct device *dev, unsigned int reg) | ||
156 | { | ||
157 | switch (reg) { | ||
158 | case NAU8825_REG_RESET: | ||
159 | case NAU8825_REG_IRQ_STATUS: | ||
160 | case NAU8825_REG_INT_CLR_KEY_STATUS: | ||
161 | case NAU8825_REG_IMM_RMS_L: | ||
162 | case NAU8825_REG_IMM_RMS_R: | ||
163 | case NAU8825_REG_I2C_DEVICE_ID: | ||
164 | case NAU8825_REG_SARDOUT_RAM_STATUS: | ||
165 | case NAU8825_REG_CHARGE_PUMP_INPUT_READ: | ||
166 | case NAU8825_REG_GENERAL_STATUS: | ||
167 | return true; | ||
168 | default: | ||
169 | return false; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static int nau8825_pump_event(struct snd_soc_dapm_widget *w, | ||
174 | struct snd_kcontrol *kcontrol, int event) | ||
175 | { | ||
176 | switch (event) { | ||
177 | case SND_SOC_DAPM_POST_PMU: | ||
178 | /* Prevent startup click by letting charge pump to ramp up */ | ||
179 | msleep(10); | ||
180 | break; | ||
181 | default: | ||
182 | return -EINVAL; | ||
183 | } | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static const char * const nau8825_adc_decimation[] = { | ||
189 | "32", "64", "128", "256" | ||
190 | }; | ||
191 | |||
192 | static const struct soc_enum nau8825_adc_decimation_enum = | ||
193 | SOC_ENUM_SINGLE(NAU8825_REG_ADC_RATE, NAU8825_ADC_SYNC_DOWN_SFT, | ||
194 | ARRAY_SIZE(nau8825_adc_decimation), nau8825_adc_decimation); | ||
195 | |||
196 | static const char * const nau8825_dac_oversampl[] = { | ||
197 | "64", "256", "128", "", "32" | ||
198 | }; | ||
199 | |||
200 | static const struct soc_enum nau8825_dac_oversampl_enum = | ||
201 | SOC_ENUM_SINGLE(NAU8825_REG_DAC_CTRL1, NAU8825_DAC_OVERSAMPLE_SFT, | ||
202 | ARRAY_SIZE(nau8825_dac_oversampl), nau8825_dac_oversampl); | ||
203 | |||
204 | static const DECLARE_TLV_DB_MINMAX_MUTE(adc_vol_tlv, -10300, 2400); | ||
205 | static const DECLARE_TLV_DB_MINMAX_MUTE(sidetone_vol_tlv, -4200, 0); | ||
206 | static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -5400, 0); | ||
207 | static const DECLARE_TLV_DB_MINMAX(fepga_gain_tlv, -100, 3600); | ||
208 | static const DECLARE_TLV_DB_MINMAX_MUTE(crosstalk_vol_tlv, -9600, 2400); | ||
209 | |||
210 | static const struct snd_kcontrol_new nau8825_controls[] = { | ||
211 | SOC_SINGLE_TLV("Mic Volume", NAU8825_REG_ADC_DGAIN_CTRL, | ||
212 | 0, 0xff, 0, adc_vol_tlv), | ||
213 | SOC_DOUBLE_TLV("Headphone Bypass Volume", NAU8825_REG_ADC_DGAIN_CTRL, | ||
214 | 12, 8, 0x0f, 0, sidetone_vol_tlv), | ||
215 | SOC_DOUBLE_TLV("Headphone Volume", NAU8825_REG_HSVOL_CTRL, | ||
216 | 6, 0, 0x3f, 1, dac_vol_tlv), | ||
217 | SOC_SINGLE_TLV("Frontend PGA Volume", NAU8825_REG_POWER_UP_CONTROL, | ||
218 | 8, 37, 0, fepga_gain_tlv), | ||
219 | SOC_DOUBLE_TLV("Headphone Crosstalk Volume", NAU8825_REG_DAC_DGAIN_CTRL, | ||
220 | 0, 8, 0xff, 0, crosstalk_vol_tlv), | ||
221 | |||
222 | SOC_ENUM("ADC Decimation Rate", nau8825_adc_decimation_enum), | ||
223 | SOC_ENUM("DAC Oversampling Rate", nau8825_dac_oversampl_enum), | ||
224 | }; | ||
225 | |||
226 | /* DAC Mux 0x33[9] and 0x34[9] */ | ||
227 | static const char * const nau8825_dac_src[] = { | ||
228 | "DACL", "DACR", | ||
229 | }; | ||
230 | |||
231 | static SOC_ENUM_SINGLE_DECL( | ||
232 | nau8825_dacl_enum, NAU8825_REG_DACL_CTRL, | ||
233 | NAU8825_DACL_CH_SEL_SFT, nau8825_dac_src); | ||
234 | |||
235 | static SOC_ENUM_SINGLE_DECL( | ||
236 | nau8825_dacr_enum, NAU8825_REG_DACR_CTRL, | ||
237 | NAU8825_DACR_CH_SEL_SFT, nau8825_dac_src); | ||
238 | |||
239 | static const struct snd_kcontrol_new nau8825_dacl_mux = | ||
240 | SOC_DAPM_ENUM("DACL Source", nau8825_dacl_enum); | ||
241 | |||
242 | static const struct snd_kcontrol_new nau8825_dacr_mux = | ||
243 | SOC_DAPM_ENUM("DACR Source", nau8825_dacr_enum); | ||
244 | |||
245 | |||
246 | static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = { | ||
247 | SND_SOC_DAPM_AIF_OUT("AIFTX", "Capture", 0, NAU8825_REG_I2S_PCM_CTRL2, | ||
248 | 15, 1), | ||
249 | |||
250 | SND_SOC_DAPM_INPUT("MIC"), | ||
251 | SND_SOC_DAPM_MICBIAS("MICBIAS", NAU8825_REG_MIC_BIAS, 8, 0), | ||
252 | |||
253 | SND_SOC_DAPM_PGA("Frontend PGA", NAU8825_REG_POWER_UP_CONTROL, 14, 0, | ||
254 | NULL, 0), | ||
255 | |||
256 | SND_SOC_DAPM_ADC("ADC", NULL, NAU8825_REG_ENA_CTRL, 8, 0), | ||
257 | SND_SOC_DAPM_SUPPLY("ADC Clock", NAU8825_REG_ENA_CTRL, 7, 0, NULL, 0), | ||
258 | SND_SOC_DAPM_SUPPLY("ADC Power", NAU8825_REG_ANALOG_ADC_2, 6, 0, NULL, | ||
259 | 0), | ||
260 | |||
261 | /* ADC for button press detection */ | ||
262 | SND_SOC_DAPM_ADC("SAR", NULL, NAU8825_REG_SAR_CTRL, | ||
263 | NAU8825_SAR_ADC_EN_SFT, 0), | ||
264 | |||
265 | SND_SOC_DAPM_DAC("ADACL", NULL, NAU8825_REG_RDAC, 12, 0), | ||
266 | SND_SOC_DAPM_DAC("ADACR", NULL, NAU8825_REG_RDAC, 13, 0), | ||
267 | SND_SOC_DAPM_SUPPLY("ADACL Clock", NAU8825_REG_RDAC, 8, 0, NULL, 0), | ||
268 | SND_SOC_DAPM_SUPPLY("ADACR Clock", NAU8825_REG_RDAC, 9, 0, NULL, 0), | ||
269 | |||
270 | SND_SOC_DAPM_DAC("DDACR", NULL, NAU8825_REG_ENA_CTRL, | ||
271 | NAU8825_ENABLE_DACR_SFT, 0), | ||
272 | SND_SOC_DAPM_DAC("DDACL", NULL, NAU8825_REG_ENA_CTRL, | ||
273 | NAU8825_ENABLE_DACL_SFT, 0), | ||
274 | SND_SOC_DAPM_SUPPLY("DDAC Clock", NAU8825_REG_ENA_CTRL, 6, 0, NULL, 0), | ||
275 | |||
276 | SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacl_mux), | ||
277 | SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacr_mux), | ||
278 | |||
279 | SND_SOC_DAPM_PGA("HP amp L", NAU8825_REG_CLASSG_CTRL, 1, 0, NULL, 0), | ||
280 | SND_SOC_DAPM_PGA("HP amp R", NAU8825_REG_CLASSG_CTRL, 2, 0, NULL, 0), | ||
281 | SND_SOC_DAPM_SUPPLY("HP amp power", NAU8825_REG_CLASSG_CTRL, 0, 0, NULL, | ||
282 | 0), | ||
283 | |||
284 | SND_SOC_DAPM_SUPPLY("Charge Pump", NAU8825_REG_CHARGE_PUMP, 5, 0, | ||
285 | nau8825_pump_event, SND_SOC_DAPM_POST_PMU), | ||
286 | |||
287 | SND_SOC_DAPM_PGA("Output Driver R Stage 1", | ||
288 | NAU8825_REG_POWER_UP_CONTROL, 5, 0, NULL, 0), | ||
289 | SND_SOC_DAPM_PGA("Output Driver L Stage 1", | ||
290 | NAU8825_REG_POWER_UP_CONTROL, 4, 0, NULL, 0), | ||
291 | SND_SOC_DAPM_PGA("Output Driver R Stage 2", | ||
292 | NAU8825_REG_POWER_UP_CONTROL, 3, 0, NULL, 0), | ||
293 | SND_SOC_DAPM_PGA("Output Driver L Stage 2", | ||
294 | NAU8825_REG_POWER_UP_CONTROL, 2, 0, NULL, 0), | ||
295 | SND_SOC_DAPM_PGA_S("Output Driver R Stage 3", 1, | ||
296 | NAU8825_REG_POWER_UP_CONTROL, 1, 0, NULL, 0), | ||
297 | SND_SOC_DAPM_PGA_S("Output Driver L Stage 3", 1, | ||
298 | NAU8825_REG_POWER_UP_CONTROL, 0, 0, NULL, 0), | ||
299 | |||
300 | SND_SOC_DAPM_PGA_S("Output DACL", 2, NAU8825_REG_CHARGE_PUMP, 8, 1, NULL, 0), | ||
301 | SND_SOC_DAPM_PGA_S("Output DACR", 2, NAU8825_REG_CHARGE_PUMP, 9, 1, NULL, 0), | ||
302 | |||
303 | SND_SOC_DAPM_OUTPUT("HPOL"), | ||
304 | SND_SOC_DAPM_OUTPUT("HPOR"), | ||
305 | }; | ||
306 | |||
307 | static const struct snd_soc_dapm_route nau8825_dapm_routes[] = { | ||
308 | {"Frontend PGA", NULL, "MIC"}, | ||
309 | {"ADC", NULL, "Frontend PGA"}, | ||
310 | {"ADC", NULL, "ADC Clock"}, | ||
311 | {"ADC", NULL, "ADC Power"}, | ||
312 | {"AIFTX", NULL, "ADC"}, | ||
313 | |||
314 | {"DDACL", NULL, "Playback"}, | ||
315 | {"DDACR", NULL, "Playback"}, | ||
316 | {"DDACL", NULL, "DDAC Clock"}, | ||
317 | {"DDACR", NULL, "DDAC Clock"}, | ||
318 | {"DACL Mux", "DACL", "DDACL"}, | ||
319 | {"DACL Mux", "DACR", "DDACR"}, | ||
320 | {"DACR Mux", "DACL", "DDACL"}, | ||
321 | {"DACR Mux", "DACR", "DDACR"}, | ||
322 | {"HP amp L", NULL, "DACL Mux"}, | ||
323 | {"HP amp R", NULL, "DACR Mux"}, | ||
324 | {"HP amp L", NULL, "HP amp power"}, | ||
325 | {"HP amp R", NULL, "HP amp power"}, | ||
326 | {"ADACL", NULL, "HP amp L"}, | ||
327 | {"ADACR", NULL, "HP amp R"}, | ||
328 | {"ADACL", NULL, "ADACL Clock"}, | ||
329 | {"ADACR", NULL, "ADACR Clock"}, | ||
330 | {"Output Driver L Stage 1", NULL, "ADACL"}, | ||
331 | {"Output Driver R Stage 1", NULL, "ADACR"}, | ||
332 | {"Output Driver L Stage 2", NULL, "Output Driver L Stage 1"}, | ||
333 | {"Output Driver R Stage 2", NULL, "Output Driver R Stage 1"}, | ||
334 | {"Output Driver L Stage 3", NULL, "Output Driver L Stage 2"}, | ||
335 | {"Output Driver R Stage 3", NULL, "Output Driver R Stage 2"}, | ||
336 | {"Output DACL", NULL, "Output Driver L Stage 3"}, | ||
337 | {"Output DACR", NULL, "Output Driver R Stage 3"}, | ||
338 | {"HPOL", NULL, "Output DACL"}, | ||
339 | {"HPOR", NULL, "Output DACR"}, | ||
340 | {"HPOL", NULL, "Charge Pump"}, | ||
341 | {"HPOR", NULL, "Charge Pump"}, | ||
342 | }; | ||
343 | |||
344 | static int nau8825_hw_params(struct snd_pcm_substream *substream, | ||
345 | struct snd_pcm_hw_params *params, | ||
346 | struct snd_soc_dai *dai) | ||
347 | { | ||
348 | struct snd_soc_codec *codec = dai->codec; | ||
349 | struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); | ||
350 | unsigned int val_len = 0; | ||
351 | |||
352 | switch (params_width(params)) { | ||
353 | case 16: | ||
354 | val_len |= NAU8825_I2S_DL_16; | ||
355 | break; | ||
356 | case 20: | ||
357 | val_len |= NAU8825_I2S_DL_20; | ||
358 | break; | ||
359 | case 24: | ||
360 | val_len |= NAU8825_I2S_DL_24; | ||
361 | break; | ||
362 | case 32: | ||
363 | val_len |= NAU8825_I2S_DL_32; | ||
364 | break; | ||
365 | default: | ||
366 | return -EINVAL; | ||
367 | } | ||
368 | |||
369 | regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1, | ||
370 | NAU8825_I2S_DL_MASK, val_len); | ||
371 | |||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
376 | { | ||
377 | struct snd_soc_codec *codec = codec_dai->codec; | ||
378 | struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); | ||
379 | unsigned int ctrl1_val = 0, ctrl2_val = 0; | ||
380 | |||
381 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
382 | case SND_SOC_DAIFMT_CBM_CFM: | ||
383 | ctrl2_val |= NAU8825_I2S_MS_MASTER; | ||
384 | break; | ||
385 | case SND_SOC_DAIFMT_CBS_CFS: | ||
386 | break; | ||
387 | default: | ||
388 | return -EINVAL; | ||
389 | } | ||
390 | |||
391 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
392 | case SND_SOC_DAIFMT_NB_NF: | ||
393 | break; | ||
394 | case SND_SOC_DAIFMT_IB_NF: | ||
395 | ctrl1_val |= NAU8825_I2S_BP_INV; | ||
396 | break; | ||
397 | default: | ||
398 | return -EINVAL; | ||
399 | } | ||
400 | |||
401 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
402 | case SND_SOC_DAIFMT_I2S: | ||
403 | ctrl1_val |= NAU8825_I2S_DF_I2S; | ||
404 | break; | ||
405 | case SND_SOC_DAIFMT_LEFT_J: | ||
406 | ctrl1_val |= NAU8825_I2S_DF_LEFT; | ||
407 | break; | ||
408 | case SND_SOC_DAIFMT_RIGHT_J: | ||
409 | ctrl1_val |= NAU8825_I2S_DF_RIGTH; | ||
410 | break; | ||
411 | case SND_SOC_DAIFMT_DSP_A: | ||
412 | ctrl1_val |= NAU8825_I2S_DF_PCM_AB; | ||
413 | break; | ||
414 | case SND_SOC_DAIFMT_DSP_B: | ||
415 | ctrl1_val |= NAU8825_I2S_DF_PCM_AB; | ||
416 | ctrl1_val |= NAU8825_I2S_PCMB_EN; | ||
417 | break; | ||
418 | default: | ||
419 | return -EINVAL; | ||
420 | } | ||
421 | |||
422 | regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1, | ||
423 | NAU8825_I2S_DL_MASK | NAU8825_I2S_DF_MASK | | ||
424 | NAU8825_I2S_BP_MASK | NAU8825_I2S_PCMB_MASK, | ||
425 | ctrl1_val); | ||
426 | regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2, | ||
427 | NAU8825_I2S_MS_MASK, ctrl2_val); | ||
428 | |||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static const struct snd_soc_dai_ops nau8825_dai_ops = { | ||
433 | .hw_params = nau8825_hw_params, | ||
434 | .set_fmt = nau8825_set_dai_fmt, | ||
435 | }; | ||
436 | |||
437 | #define NAU8825_RATES SNDRV_PCM_RATE_8000_192000 | ||
438 | #define NAU8825_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ | ||
439 | | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
440 | |||
441 | static struct snd_soc_dai_driver nau8825_dai = { | ||
442 | .name = "nau8825-hifi", | ||
443 | .playback = { | ||
444 | .stream_name = "Playback", | ||
445 | .channels_min = 1, | ||
446 | .channels_max = 2, | ||
447 | .rates = NAU8825_RATES, | ||
448 | .formats = NAU8825_FORMATS, | ||
449 | }, | ||
450 | .capture = { | ||
451 | .stream_name = "Capture", | ||
452 | .channels_min = 1, | ||
453 | .channels_max = 1, | ||
454 | .rates = NAU8825_RATES, | ||
455 | .formats = NAU8825_FORMATS, | ||
456 | }, | ||
457 | .ops = &nau8825_dai_ops, | ||
458 | }; | ||
459 | |||
460 | /** | ||
461 | * nau8825_enable_jack_detect - Specify a jack for event reporting | ||
462 | * | ||
463 | * @component: component to register the jack with | ||
464 | * @jack: jack to use to report headset and button events on | ||
465 | * | ||
466 | * After this function has been called the headset insert/remove and button | ||
467 | * events will be routed to the given jack. Jack can be null to stop | ||
468 | * reporting. | ||
469 | */ | ||
470 | int nau8825_enable_jack_detect(struct snd_soc_codec *codec, | ||
471 | struct snd_soc_jack *jack) | ||
472 | { | ||
473 | struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); | ||
474 | struct regmap *regmap = nau8825->regmap; | ||
475 | |||
476 | nau8825->jack = jack; | ||
477 | |||
478 | /* Ground HP Outputs[1:0], needed for headset auto detection | ||
479 | * Enable Automatic Mic/Gnd switching reading on insert interrupt[6] | ||
480 | */ | ||
481 | regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, | ||
482 | NAU8825_HSD_AUTO_MODE | NAU8825_SPKR_DWN1R | NAU8825_SPKR_DWN1L, | ||
483 | NAU8825_HSD_AUTO_MODE | NAU8825_SPKR_DWN1R | NAU8825_SPKR_DWN1L); | ||
484 | |||
485 | regmap_update_bits(regmap, NAU8825_REG_INTERRUPT_MASK, | ||
486 | NAU8825_IRQ_HEADSET_COMPLETE_EN | NAU8825_IRQ_EJECT_EN, 0); | ||
487 | |||
488 | return 0; | ||
489 | } | ||
490 | EXPORT_SYMBOL_GPL(nau8825_enable_jack_detect); | ||
491 | |||
492 | |||
493 | static bool nau8825_is_jack_inserted(struct regmap *regmap) | ||
494 | { | ||
495 | int status; | ||
496 | |||
497 | regmap_read(regmap, NAU8825_REG_I2C_DEVICE_ID, &status); | ||
498 | return !(status & NAU8825_GPIO2JD1); | ||
499 | } | ||
500 | |||
501 | static void nau8825_restart_jack_detection(struct regmap *regmap) | ||
502 | { | ||
503 | /* this will restart the entire jack detection process including MIC/GND | ||
504 | * switching and create interrupts. We have to go from 0 to 1 and back | ||
505 | * to 0 to restart. | ||
506 | */ | ||
507 | regmap_update_bits(regmap, NAU8825_REG_JACK_DET_CTRL, | ||
508 | NAU8825_JACK_DET_RESTART, NAU8825_JACK_DET_RESTART); | ||
509 | regmap_update_bits(regmap, NAU8825_REG_JACK_DET_CTRL, | ||
510 | NAU8825_JACK_DET_RESTART, 0); | ||
511 | } | ||
512 | |||
513 | static void nau8825_eject_jack(struct nau8825 *nau8825) | ||
514 | { | ||
515 | struct snd_soc_dapm_context *dapm = nau8825->dapm; | ||
516 | struct regmap *regmap = nau8825->regmap; | ||
517 | |||
518 | snd_soc_dapm_disable_pin(dapm, "SAR"); | ||
519 | snd_soc_dapm_disable_pin(dapm, "MICBIAS"); | ||
520 | /* Detach 2kOhm Resistors from MICBIAS to MICGND1/2 */ | ||
521 | regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS, | ||
522 | NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_JKR2, 0); | ||
523 | /* ground HPL/HPR, MICGRND1/2 */ | ||
524 | regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 0xf, 0xf); | ||
525 | |||
526 | snd_soc_dapm_sync(dapm); | ||
527 | } | ||
528 | |||
529 | static int nau8825_button_decode(int value) | ||
530 | { | ||
531 | int buttons = 0; | ||
532 | |||
533 | /* The chip supports up to 8 buttons, but ALSA defines only 6 buttons */ | ||
534 | if (value & BIT(0)) | ||
535 | buttons |= SND_JACK_BTN_0; | ||
536 | if (value & BIT(1)) | ||
537 | buttons |= SND_JACK_BTN_1; | ||
538 | if (value & BIT(2)) | ||
539 | buttons |= SND_JACK_BTN_2; | ||
540 | if (value & BIT(3)) | ||
541 | buttons |= SND_JACK_BTN_3; | ||
542 | if (value & BIT(4)) | ||
543 | buttons |= SND_JACK_BTN_4; | ||
544 | if (value & BIT(5)) | ||
545 | buttons |= SND_JACK_BTN_5; | ||
546 | |||
547 | return buttons; | ||
548 | } | ||
549 | |||
550 | static int nau8825_jack_insert(struct nau8825 *nau8825) | ||
551 | { | ||
552 | struct regmap *regmap = nau8825->regmap; | ||
553 | struct snd_soc_dapm_context *dapm = nau8825->dapm; | ||
554 | int jack_status_reg, mic_detected; | ||
555 | int type = 0; | ||
556 | |||
557 | regmap_read(regmap, NAU8825_REG_GENERAL_STATUS, &jack_status_reg); | ||
558 | mic_detected = (jack_status_reg >> 10) & 3; | ||
559 | |||
560 | switch (mic_detected) { | ||
561 | case 0: | ||
562 | /* no mic */ | ||
563 | type = SND_JACK_HEADPHONE; | ||
564 | break; | ||
565 | case 1: | ||
566 | dev_dbg(nau8825->dev, "OMTP (micgnd1) mic connected\n"); | ||
567 | type = SND_JACK_HEADSET; | ||
568 | |||
569 | /* Unground MICGND1 */ | ||
570 | regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 3 << 2, | ||
571 | 1 << 2); | ||
572 | /* Attach 2kOhm Resistor from MICBIAS to MICGND1 */ | ||
573 | regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS, | ||
574 | NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_JKR2, | ||
575 | NAU8825_MICBIAS_JKR2); | ||
576 | /* Attach SARADC to MICGND1 */ | ||
577 | regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL, | ||
578 | NAU8825_SAR_INPUT_MASK, | ||
579 | NAU8825_SAR_INPUT_JKR2); | ||
580 | |||
581 | snd_soc_dapm_force_enable_pin(dapm, "MICBIAS"); | ||
582 | snd_soc_dapm_force_enable_pin(dapm, "SAR"); | ||
583 | snd_soc_dapm_sync(dapm); | ||
584 | break; | ||
585 | case 2: | ||
586 | case 3: | ||
587 | dev_dbg(nau8825->dev, "CTIA (micgnd2) mic connected\n"); | ||
588 | type = SND_JACK_HEADSET; | ||
589 | |||
590 | /* Unground MICGND2 */ | ||
591 | regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 3 << 2, | ||
592 | 2 << 2); | ||
593 | /* Attach 2kOhm Resistor from MICBIAS to MICGND2 */ | ||
594 | regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS, | ||
595 | NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_JKR2, | ||
596 | NAU8825_MICBIAS_JKSLV); | ||
597 | /* Attach SARADC to MICGND2 */ | ||
598 | regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL, | ||
599 | NAU8825_SAR_INPUT_MASK, | ||
600 | NAU8825_SAR_INPUT_JKSLV); | ||
601 | |||
602 | snd_soc_dapm_force_enable_pin(dapm, "MICBIAS"); | ||
603 | snd_soc_dapm_force_enable_pin(dapm, "SAR"); | ||
604 | snd_soc_dapm_sync(dapm); | ||
605 | break; | ||
606 | } | ||
607 | |||
608 | if (type & SND_JACK_HEADPHONE) { | ||
609 | /* Unground HPL/R */ | ||
610 | regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 0x3, 0); | ||
611 | } | ||
612 | |||
613 | return type; | ||
614 | } | ||
615 | |||
616 | #define NAU8825_BUTTONS (SND_JACK_BTN_0 | SND_JACK_BTN_1 | \ | ||
617 | SND_JACK_BTN_2 | SND_JACK_BTN_3) | ||
618 | |||
619 | static irqreturn_t nau8825_interrupt(int irq, void *data) | ||
620 | { | ||
621 | struct nau8825 *nau8825 = (struct nau8825 *)data; | ||
622 | struct regmap *regmap = nau8825->regmap; | ||
623 | int active_irq, clear_irq = 0, event = 0, event_mask = 0; | ||
624 | |||
625 | regmap_read(regmap, NAU8825_REG_IRQ_STATUS, &active_irq); | ||
626 | |||
627 | if ((active_irq & NAU8825_JACK_EJECTION_IRQ_MASK) == | ||
628 | NAU8825_JACK_EJECTION_DETECTED) { | ||
629 | |||
630 | nau8825_eject_jack(nau8825); | ||
631 | event_mask |= SND_JACK_HEADSET; | ||
632 | clear_irq = NAU8825_JACK_EJECTION_IRQ_MASK; | ||
633 | } else if (active_irq & NAU8825_KEY_SHORT_PRESS_IRQ) { | ||
634 | int key_status; | ||
635 | |||
636 | regmap_read(regmap, NAU8825_REG_INT_CLR_KEY_STATUS, | ||
637 | &key_status); | ||
638 | |||
639 | /* upper 8 bits of the register are for short pressed keys, | ||
640 | * lower 8 bits - for long pressed buttons | ||
641 | */ | ||
642 | nau8825->button_pressed = nau8825_button_decode( | ||
643 | key_status >> 8); | ||
644 | |||
645 | event |= nau8825->button_pressed; | ||
646 | event_mask |= NAU8825_BUTTONS; | ||
647 | clear_irq = NAU8825_KEY_SHORT_PRESS_IRQ; | ||
648 | } else if (active_irq & NAU8825_KEY_RELEASE_IRQ) { | ||
649 | event_mask = NAU8825_BUTTONS; | ||
650 | clear_irq = NAU8825_KEY_RELEASE_IRQ; | ||
651 | } else if (active_irq & NAU8825_HEADSET_COMPLETION_IRQ) { | ||
652 | if (nau8825_is_jack_inserted(regmap)) { | ||
653 | event |= nau8825_jack_insert(nau8825); | ||
654 | } else { | ||
655 | dev_warn(nau8825->dev, "Headset completion IRQ fired but no headset connected\n"); | ||
656 | nau8825_eject_jack(nau8825); | ||
657 | } | ||
658 | |||
659 | event_mask |= SND_JACK_HEADSET; | ||
660 | clear_irq = NAU8825_HEADSET_COMPLETION_IRQ; | ||
661 | } | ||
662 | |||
663 | if (!clear_irq) | ||
664 | clear_irq = active_irq; | ||
665 | /* clears the rightmost interruption */ | ||
666 | regmap_write(regmap, NAU8825_REG_INT_CLR_KEY_STATUS, clear_irq); | ||
667 | |||
668 | if (event_mask) | ||
669 | snd_soc_jack_report(nau8825->jack, event, event_mask); | ||
670 | |||
671 | return IRQ_HANDLED; | ||
672 | } | ||
673 | |||
674 | static void nau8825_setup_buttons(struct nau8825 *nau8825) | ||
675 | { | ||
676 | struct regmap *regmap = nau8825->regmap; | ||
677 | |||
678 | regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL, | ||
679 | NAU8825_SAR_TRACKING_GAIN_MASK, | ||
680 | nau8825->sar_voltage << NAU8825_SAR_TRACKING_GAIN_SFT); | ||
681 | regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL, | ||
682 | NAU8825_SAR_COMPARE_TIME_MASK, | ||
683 | nau8825->sar_compare_time << NAU8825_SAR_COMPARE_TIME_SFT); | ||
684 | regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL, | ||
685 | NAU8825_SAR_SAMPLING_TIME_MASK, | ||
686 | nau8825->sar_sampling_time << NAU8825_SAR_SAMPLING_TIME_SFT); | ||
687 | |||
688 | regmap_update_bits(regmap, NAU8825_REG_KEYDET_CTRL, | ||
689 | NAU8825_KEYDET_LEVELS_NR_MASK, | ||
690 | (nau8825->sar_threshold_num - 1) << NAU8825_KEYDET_LEVELS_NR_SFT); | ||
691 | regmap_update_bits(regmap, NAU8825_REG_KEYDET_CTRL, | ||
692 | NAU8825_KEYDET_HYSTERESIS_MASK, | ||
693 | nau8825->sar_hysteresis << NAU8825_KEYDET_HYSTERESIS_SFT); | ||
694 | regmap_update_bits(regmap, NAU8825_REG_KEYDET_CTRL, | ||
695 | NAU8825_KEYDET_SHORTKEY_DEBOUNCE_MASK, | ||
696 | nau8825->key_debounce << NAU8825_KEYDET_SHORTKEY_DEBOUNCE_SFT); | ||
697 | |||
698 | regmap_write(regmap, NAU8825_REG_VDET_THRESHOLD_1, | ||
699 | (nau8825->sar_threshold[0] << 8) | nau8825->sar_threshold[1]); | ||
700 | regmap_write(regmap, NAU8825_REG_VDET_THRESHOLD_2, | ||
701 | (nau8825->sar_threshold[2] << 8) | nau8825->sar_threshold[3]); | ||
702 | regmap_write(regmap, NAU8825_REG_VDET_THRESHOLD_3, | ||
703 | (nau8825->sar_threshold[4] << 8) | nau8825->sar_threshold[5]); | ||
704 | regmap_write(regmap, NAU8825_REG_VDET_THRESHOLD_4, | ||
705 | (nau8825->sar_threshold[6] << 8) | nau8825->sar_threshold[7]); | ||
706 | |||
707 | /* Enable short press and release interruptions */ | ||
708 | regmap_update_bits(regmap, NAU8825_REG_INTERRUPT_MASK, | ||
709 | NAU8825_IRQ_KEY_SHORT_PRESS_EN | NAU8825_IRQ_KEY_RELEASE_EN, | ||
710 | 0); | ||
711 | } | ||
712 | |||
713 | static void nau8825_init_regs(struct nau8825 *nau8825) | ||
714 | { | ||
715 | struct regmap *regmap = nau8825->regmap; | ||
716 | |||
717 | /* Enable Bias/Vmid */ | ||
718 | regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, | ||
719 | NAU8825_BIAS_VMID, NAU8825_BIAS_VMID); | ||
720 | regmap_update_bits(nau8825->regmap, NAU8825_REG_BOOST, | ||
721 | NAU8825_GLOBAL_BIAS_EN, NAU8825_GLOBAL_BIAS_EN); | ||
722 | |||
723 | /* VMID Tieoff */ | ||
724 | regmap_update_bits(regmap, NAU8825_REG_BIAS_ADJ, | ||
725 | NAU8825_BIAS_VMID_SEL_MASK, | ||
726 | nau8825->vref_impedance << NAU8825_BIAS_VMID_SEL_SFT); | ||
727 | /* Disable Boost Driver, Automatic Short circuit protection enable */ | ||
728 | regmap_update_bits(regmap, NAU8825_REG_BOOST, | ||
729 | NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_G_DIS | | ||
730 | NAU8825_SHORT_SHUTDOWN_EN, | ||
731 | NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_G_DIS | | ||
732 | NAU8825_SHORT_SHUTDOWN_EN); | ||
733 | |||
734 | regmap_update_bits(regmap, NAU8825_REG_GPIO12_CTRL, | ||
735 | NAU8825_JKDET_OUTPUT_EN, | ||
736 | nau8825->jkdet_enable ? 0 : NAU8825_JKDET_OUTPUT_EN); | ||
737 | regmap_update_bits(regmap, NAU8825_REG_GPIO12_CTRL, | ||
738 | NAU8825_JKDET_PULL_EN, | ||
739 | nau8825->jkdet_pull_enable ? 0 : NAU8825_JKDET_PULL_EN); | ||
740 | regmap_update_bits(regmap, NAU8825_REG_GPIO12_CTRL, | ||
741 | NAU8825_JKDET_PULL_UP, | ||
742 | nau8825->jkdet_pull_up ? NAU8825_JKDET_PULL_UP : 0); | ||
743 | regmap_update_bits(regmap, NAU8825_REG_JACK_DET_CTRL, | ||
744 | NAU8825_JACK_POLARITY, | ||
745 | /* jkdet_polarity - 1 is for active-low */ | ||
746 | nau8825->jkdet_polarity ? 0 : NAU8825_JACK_POLARITY); | ||
747 | |||
748 | regmap_update_bits(regmap, NAU8825_REG_JACK_DET_CTRL, | ||
749 | NAU8825_JACK_INSERT_DEBOUNCE_MASK, | ||
750 | nau8825->jack_insert_debounce << NAU8825_JACK_INSERT_DEBOUNCE_SFT); | ||
751 | regmap_update_bits(regmap, NAU8825_REG_JACK_DET_CTRL, | ||
752 | NAU8825_JACK_EJECT_DEBOUNCE_MASK, | ||
753 | nau8825->jack_eject_debounce << NAU8825_JACK_EJECT_DEBOUNCE_SFT); | ||
754 | |||
755 | /* Mask unneeded IRQs: 1 - disable, 0 - enable */ | ||
756 | regmap_update_bits(regmap, NAU8825_REG_INTERRUPT_MASK, 0x7ff, 0x7ff); | ||
757 | |||
758 | regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS, | ||
759 | NAU8825_MICBIAS_VOLTAGE_MASK, nau8825->micbias_voltage); | ||
760 | |||
761 | if (nau8825->sar_threshold_num) | ||
762 | nau8825_setup_buttons(nau8825); | ||
763 | |||
764 | /* Default oversampling/decimations settings are unusable | ||
765 | * (audible hiss). Set it to something better. | ||
766 | */ | ||
767 | regmap_update_bits(regmap, NAU8825_REG_ADC_RATE, | ||
768 | NAU8825_ADC_SYNC_DOWN_MASK, NAU8825_ADC_SYNC_DOWN_128); | ||
769 | regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1, | ||
770 | NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_128); | ||
771 | } | ||
772 | |||
773 | static const struct regmap_config nau8825_regmap_config = { | ||
774 | .val_bits = 16, | ||
775 | .reg_bits = 16, | ||
776 | |||
777 | .max_register = NAU8825_REG_MAX, | ||
778 | .readable_reg = nau8825_readable_reg, | ||
779 | .writeable_reg = nau8825_writeable_reg, | ||
780 | .volatile_reg = nau8825_volatile_reg, | ||
781 | |||
782 | .cache_type = REGCACHE_RBTREE, | ||
783 | .reg_defaults = nau8825_reg_defaults, | ||
784 | .num_reg_defaults = ARRAY_SIZE(nau8825_reg_defaults), | ||
785 | }; | ||
786 | |||
787 | static int nau8825_codec_probe(struct snd_soc_codec *codec) | ||
788 | { | ||
789 | struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); | ||
790 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | ||
791 | |||
792 | nau8825->dapm = dapm; | ||
793 | |||
794 | /* The interrupt clock is gated by x1[10:8], | ||
795 | * one of them needs to be enabled all the time for | ||
796 | * interrupts to happen. | ||
797 | */ | ||
798 | snd_soc_dapm_force_enable_pin(dapm, "DDACR"); | ||
799 | snd_soc_dapm_sync(dapm); | ||
800 | |||
801 | /* Unmask interruptions. Handler uses dapm object so we can enable | ||
802 | * interruptions only after dapm is fully initialized. | ||
803 | */ | ||
804 | regmap_write(nau8825->regmap, NAU8825_REG_INTERRUPT_DIS_CTRL, 0); | ||
805 | nau8825_restart_jack_detection(nau8825->regmap); | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, | ||
811 | unsigned int freq) | ||
812 | { | ||
813 | struct regmap *regmap = nau8825->regmap; | ||
814 | int ret; | ||
815 | |||
816 | switch (clk_id) { | ||
817 | case NAU8825_CLK_MCLK: | ||
818 | regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, | ||
819 | NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_MCLK); | ||
820 | regmap_update_bits(regmap, NAU8825_REG_FLL6, NAU8825_DCO_EN, 0); | ||
821 | |||
822 | /* We selected MCLK source but the clock itself managed externally */ | ||
823 | if (!nau8825->mclk) | ||
824 | break; | ||
825 | |||
826 | if (!nau8825->mclk_freq) { | ||
827 | ret = clk_prepare_enable(nau8825->mclk); | ||
828 | if (ret) { | ||
829 | dev_err(nau8825->dev, "Unable to prepare codec mclk\n"); | ||
830 | return ret; | ||
831 | } | ||
832 | } | ||
833 | |||
834 | if (nau8825->mclk_freq != freq) { | ||
835 | nau8825->mclk_freq = freq; | ||
836 | |||
837 | freq = clk_round_rate(nau8825->mclk, freq); | ||
838 | ret = clk_set_rate(nau8825->mclk, freq); | ||
839 | if (ret) { | ||
840 | dev_err(nau8825->dev, "Unable to set mclk rate\n"); | ||
841 | return ret; | ||
842 | } | ||
843 | } | ||
844 | |||
845 | break; | ||
846 | case NAU8825_CLK_INTERNAL: | ||
847 | regmap_update_bits(regmap, NAU8825_REG_FLL6, NAU8825_DCO_EN, | ||
848 | NAU8825_DCO_EN); | ||
849 | regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, | ||
850 | NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_VCO); | ||
851 | |||
852 | if (nau8825->mclk_freq) { | ||
853 | clk_disable_unprepare(nau8825->mclk); | ||
854 | nau8825->mclk_freq = 0; | ||
855 | } | ||
856 | |||
857 | break; | ||
858 | default: | ||
859 | dev_err(nau8825->dev, "Invalid clock id (%d)\n", clk_id); | ||
860 | return -EINVAL; | ||
861 | } | ||
862 | |||
863 | dev_dbg(nau8825->dev, "Sysclk is %dHz and clock id is %d\n", freq, | ||
864 | clk_id); | ||
865 | return 0; | ||
866 | } | ||
867 | |||
868 | static int nau8825_set_sysclk(struct snd_soc_codec *codec, int clk_id, | ||
869 | int source, unsigned int freq, int dir) | ||
870 | { | ||
871 | struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); | ||
872 | |||
873 | return nau8825_configure_sysclk(nau8825, clk_id, freq); | ||
874 | } | ||
875 | |||
876 | static int nau8825_set_bias_level(struct snd_soc_codec *codec, | ||
877 | enum snd_soc_bias_level level) | ||
878 | { | ||
879 | struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); | ||
880 | int ret; | ||
881 | |||
882 | switch (level) { | ||
883 | case SND_SOC_BIAS_ON: | ||
884 | break; | ||
885 | |||
886 | case SND_SOC_BIAS_PREPARE: | ||
887 | break; | ||
888 | |||
889 | case SND_SOC_BIAS_STANDBY: | ||
890 | if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { | ||
891 | if (nau8825->mclk_freq) { | ||
892 | ret = clk_prepare_enable(nau8825->mclk); | ||
893 | if (ret) { | ||
894 | dev_err(nau8825->dev, "Unable to prepare codec mclk\n"); | ||
895 | return ret; | ||
896 | } | ||
897 | } | ||
898 | |||
899 | ret = regcache_sync(nau8825->regmap); | ||
900 | if (ret) { | ||
901 | dev_err(codec->dev, | ||
902 | "Failed to sync cache: %d\n", ret); | ||
903 | return ret; | ||
904 | } | ||
905 | } | ||
906 | |||
907 | break; | ||
908 | |||
909 | case SND_SOC_BIAS_OFF: | ||
910 | if (nau8825->mclk_freq) | ||
911 | clk_disable_unprepare(nau8825->mclk); | ||
912 | |||
913 | regcache_mark_dirty(nau8825->regmap); | ||
914 | break; | ||
915 | } | ||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | static struct snd_soc_codec_driver nau8825_codec_driver = { | ||
920 | .probe = nau8825_codec_probe, | ||
921 | .set_sysclk = nau8825_set_sysclk, | ||
922 | .set_bias_level = nau8825_set_bias_level, | ||
923 | .suspend_bias_off = true, | ||
924 | |||
925 | .controls = nau8825_controls, | ||
926 | .num_controls = ARRAY_SIZE(nau8825_controls), | ||
927 | .dapm_widgets = nau8825_dapm_widgets, | ||
928 | .num_dapm_widgets = ARRAY_SIZE(nau8825_dapm_widgets), | ||
929 | .dapm_routes = nau8825_dapm_routes, | ||
930 | .num_dapm_routes = ARRAY_SIZE(nau8825_dapm_routes), | ||
931 | }; | ||
932 | |||
933 | static void nau8825_reset_chip(struct regmap *regmap) | ||
934 | { | ||
935 | regmap_write(regmap, NAU8825_REG_RESET, 0x00); | ||
936 | regmap_write(regmap, NAU8825_REG_RESET, 0x00); | ||
937 | } | ||
938 | |||
939 | static int nau8825_read_device_properties(struct device *dev, | ||
940 | struct nau8825 *nau8825) { | ||
941 | |||
942 | nau8825->jkdet_enable = device_property_read_bool(dev, | ||
943 | "nuvoton,jkdet-enable"); | ||
944 | nau8825->jkdet_pull_enable = device_property_read_bool(dev, | ||
945 | "nuvoton,jkdet-pull-enable"); | ||
946 | nau8825->jkdet_pull_up = device_property_read_bool(dev, | ||
947 | "nuvoton,jkdet-pull-up"); | ||
948 | device_property_read_u32(dev, "nuvoton,jkdet-polarity", | ||
949 | &nau8825->jkdet_polarity); | ||
950 | device_property_read_u32(dev, "nuvoton,micbias-voltage", | ||
951 | &nau8825->micbias_voltage); | ||
952 | device_property_read_u32(dev, "nuvoton,vref-impedance", | ||
953 | &nau8825->vref_impedance); | ||
954 | device_property_read_u32(dev, "nuvoton,sar-threshold-num", | ||
955 | &nau8825->sar_threshold_num); | ||
956 | device_property_read_u32_array(dev, "nuvoton,sar-threshold", | ||
957 | nau8825->sar_threshold, nau8825->sar_threshold_num); | ||
958 | device_property_read_u32(dev, "nuvoton,sar-hysteresis", | ||
959 | &nau8825->sar_hysteresis); | ||
960 | device_property_read_u32(dev, "nuvoton,sar-voltage", | ||
961 | &nau8825->sar_voltage); | ||
962 | device_property_read_u32(dev, "nuvoton,sar-compare-time", | ||
963 | &nau8825->sar_compare_time); | ||
964 | device_property_read_u32(dev, "nuvoton,sar-sampling-time", | ||
965 | &nau8825->sar_sampling_time); | ||
966 | device_property_read_u32(dev, "nuvoton,short-key-debounce", | ||
967 | &nau8825->key_debounce); | ||
968 | device_property_read_u32(dev, "nuvoton,jack-insert-debounce", | ||
969 | &nau8825->jack_insert_debounce); | ||
970 | device_property_read_u32(dev, "nuvoton,jack-eject-debounce", | ||
971 | &nau8825->jack_eject_debounce); | ||
972 | |||
973 | nau8825->mclk = devm_clk_get(dev, "mclk"); | ||
974 | if (PTR_ERR(nau8825->mclk) == -EPROBE_DEFER) { | ||
975 | return -EPROBE_DEFER; | ||
976 | } else if (PTR_ERR(nau8825->mclk) == -ENOENT) { | ||
977 | /* The MCLK is managed externally or not used at all */ | ||
978 | nau8825->mclk = NULL; | ||
979 | dev_info(dev, "No 'mclk' clock found, assume MCLK is managed externally"); | ||
980 | } else if (IS_ERR(nau8825->mclk)) { | ||
981 | return -EINVAL; | ||
982 | } | ||
983 | |||
984 | return 0; | ||
985 | } | ||
986 | |||
987 | static int nau8825_setup_irq(struct nau8825 *nau8825) | ||
988 | { | ||
989 | struct regmap *regmap = nau8825->regmap; | ||
990 | int ret; | ||
991 | |||
992 | /* IRQ Output Enable */ | ||
993 | regmap_update_bits(regmap, NAU8825_REG_INTERRUPT_MASK, | ||
994 | NAU8825_IRQ_OUTPUT_EN, NAU8825_IRQ_OUTPUT_EN); | ||
995 | |||
996 | /* Enable internal VCO needed for interruptions */ | ||
997 | nau8825_configure_sysclk(nau8825, NAU8825_CLK_INTERNAL, 0); | ||
998 | |||
999 | /* Enable DDACR needed for interrupts | ||
1000 | * It is the same as force_enable_pin("DDACR") we do later | ||
1001 | */ | ||
1002 | regmap_update_bits(regmap, NAU8825_REG_ENA_CTRL, | ||
1003 | NAU8825_ENABLE_DACR, NAU8825_ENABLE_DACR); | ||
1004 | |||
1005 | /* Chip needs one FSCLK cycle in order to generate interrupts, | ||
1006 | * as we cannot guarantee one will be provided by the system. Turning | ||
1007 | * master mode on then off enables us to generate that FSCLK cycle | ||
1008 | * with a minimum of contention on the clock bus. | ||
1009 | */ | ||
1010 | regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2, | ||
1011 | NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_MASTER); | ||
1012 | regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2, | ||
1013 | NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_SLAVE); | ||
1014 | |||
1015 | ret = devm_request_threaded_irq(nau8825->dev, nau8825->irq, NULL, | ||
1016 | nau8825_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
1017 | "nau8825", nau8825); | ||
1018 | |||
1019 | if (ret) { | ||
1020 | dev_err(nau8825->dev, "Cannot request irq %d (%d)\n", | ||
1021 | nau8825->irq, ret); | ||
1022 | return ret; | ||
1023 | } | ||
1024 | |||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | static int nau8825_i2c_probe(struct i2c_client *i2c, | ||
1029 | const struct i2c_device_id *id) | ||
1030 | { | ||
1031 | struct device *dev = &i2c->dev; | ||
1032 | struct nau8825 *nau8825 = dev_get_platdata(&i2c->dev); | ||
1033 | int ret, value; | ||
1034 | |||
1035 | if (!nau8825) { | ||
1036 | nau8825 = devm_kzalloc(dev, sizeof(*nau8825), GFP_KERNEL); | ||
1037 | if (!nau8825) | ||
1038 | return -ENOMEM; | ||
1039 | ret = nau8825_read_device_properties(dev, nau8825); | ||
1040 | if (ret) | ||
1041 | return ret; | ||
1042 | } | ||
1043 | |||
1044 | i2c_set_clientdata(i2c, nau8825); | ||
1045 | |||
1046 | nau8825->regmap = devm_regmap_init_i2c(i2c, &nau8825_regmap_config); | ||
1047 | if (IS_ERR(nau8825->regmap)) | ||
1048 | return PTR_ERR(nau8825->regmap); | ||
1049 | nau8825->dev = dev; | ||
1050 | nau8825->irq = i2c->irq; | ||
1051 | |||
1052 | nau8825_reset_chip(nau8825->regmap); | ||
1053 | ret = regmap_read(nau8825->regmap, NAU8825_REG_I2C_DEVICE_ID, &value); | ||
1054 | if (ret < 0) { | ||
1055 | dev_err(dev, "Failed to read device id from the NAU8825: %d\n", | ||
1056 | ret); | ||
1057 | return ret; | ||
1058 | } | ||
1059 | if ((value & NAU8825_SOFTWARE_ID_MASK) != | ||
1060 | NAU8825_SOFTWARE_ID_NAU8825) { | ||
1061 | dev_err(dev, "Not a NAU8825 chip\n"); | ||
1062 | return -ENODEV; | ||
1063 | } | ||
1064 | |||
1065 | nau8825_init_regs(nau8825); | ||
1066 | |||
1067 | if (i2c->irq) | ||
1068 | nau8825_setup_irq(nau8825); | ||
1069 | |||
1070 | return snd_soc_register_codec(&i2c->dev, &nau8825_codec_driver, | ||
1071 | &nau8825_dai, 1); | ||
1072 | } | ||
1073 | |||
1074 | static int nau8825_i2c_remove(struct i2c_client *client) | ||
1075 | { | ||
1076 | snd_soc_unregister_codec(&client->dev); | ||
1077 | return 0; | ||
1078 | } | ||
1079 | |||
1080 | static const struct i2c_device_id nau8825_i2c_ids[] = { | ||
1081 | { "nau8825", 0 }, | ||
1082 | { } | ||
1083 | }; | ||
1084 | |||
1085 | #ifdef CONFIG_OF | ||
1086 | static const struct of_device_id nau8825_of_ids[] = { | ||
1087 | { .compatible = "nuvoton,nau8825", }, | ||
1088 | {} | ||
1089 | }; | ||
1090 | MODULE_DEVICE_TABLE(of, nau8825_of_ids); | ||
1091 | #endif | ||
1092 | |||
1093 | static struct i2c_driver nau8825_driver = { | ||
1094 | .driver = { | ||
1095 | .name = "nau8825", | ||
1096 | .owner = THIS_MODULE, | ||
1097 | .of_match_table = of_match_ptr(nau8825_of_ids), | ||
1098 | }, | ||
1099 | .probe = nau8825_i2c_probe, | ||
1100 | .remove = nau8825_i2c_remove, | ||
1101 | .id_table = nau8825_i2c_ids, | ||
1102 | }; | ||
1103 | module_i2c_driver(nau8825_driver); | ||
1104 | |||
1105 | MODULE_DESCRIPTION("ASoC nau8825 driver"); | ||
1106 | MODULE_AUTHOR("Anatol Pomozov <anatol@chromium.org>"); | ||
1107 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h new file mode 100644 index 000000000000..8774923502b4 --- /dev/null +++ b/sound/soc/codecs/nau8825.h | |||
@@ -0,0 +1,323 @@ | |||
1 | /* | ||
2 | * NAU8825 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright 2015 Google Inc. | ||
5 | * Author: Anatol Pomozov <anatol.pomozov@chrominium.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __NAU8825_H__ | ||
13 | #define __NAU8825_H__ | ||
14 | |||
15 | #define NAU8825_REG_RESET 0x00 | ||
16 | #define NAU8825_REG_ENA_CTRL 0x01 | ||
17 | #define NAU8825_REG_CLK_DIVIDER 0x03 | ||
18 | #define NAU8825_REG_FLL1 0x04 | ||
19 | #define NAU8825_REG_FLL2 0x05 | ||
20 | #define NAU8825_REG_FLL3 0x06 | ||
21 | #define NAU8825_REG_FLL4 0x07 | ||
22 | #define NAU8825_REG_FLL5 0x08 | ||
23 | #define NAU8825_REG_FLL6 0x09 | ||
24 | #define NAU8825_REG_FLL_VCO_RSV 0x0a | ||
25 | #define NAU8825_REG_HSD_CTRL 0x0c | ||
26 | #define NAU8825_REG_JACK_DET_CTRL 0x0d | ||
27 | #define NAU8825_REG_INTERRUPT_MASK 0x0f | ||
28 | #define NAU8825_REG_IRQ_STATUS 0x10 | ||
29 | #define NAU8825_REG_INT_CLR_KEY_STATUS 0x11 | ||
30 | #define NAU8825_REG_INTERRUPT_DIS_CTRL 0x12 | ||
31 | #define NAU8825_REG_SAR_CTRL 0x13 | ||
32 | #define NAU8825_REG_KEYDET_CTRL 0x14 | ||
33 | #define NAU8825_REG_VDET_THRESHOLD_1 0x15 | ||
34 | #define NAU8825_REG_VDET_THRESHOLD_2 0x16 | ||
35 | #define NAU8825_REG_VDET_THRESHOLD_3 0x17 | ||
36 | #define NAU8825_REG_VDET_THRESHOLD_4 0x18 | ||
37 | #define NAU8825_REG_GPIO34_CTRL 0x19 | ||
38 | #define NAU8825_REG_GPIO12_CTRL 0x1a | ||
39 | #define NAU8825_REG_TDM_CTRL 0x1b | ||
40 | #define NAU8825_REG_I2S_PCM_CTRL1 0x1c | ||
41 | #define NAU8825_REG_I2S_PCM_CTRL2 0x1d | ||
42 | #define NAU8825_REG_LEFT_TIME_SLOT 0x1e | ||
43 | #define NAU8825_REG_RIGHT_TIME_SLOT 0x1f | ||
44 | #define NAU8825_REG_BIQ_CTRL 0x20 | ||
45 | #define NAU8825_REG_BIQ_COF1 0x21 | ||
46 | #define NAU8825_REG_BIQ_COF2 0x22 | ||
47 | #define NAU8825_REG_BIQ_COF3 0x23 | ||
48 | #define NAU8825_REG_BIQ_COF4 0x24 | ||
49 | #define NAU8825_REG_BIQ_COF5 0x25 | ||
50 | #define NAU8825_REG_BIQ_COF6 0x26 | ||
51 | #define NAU8825_REG_BIQ_COF7 0x27 | ||
52 | #define NAU8825_REG_BIQ_COF8 0x28 | ||
53 | #define NAU8825_REG_BIQ_COF9 0x29 | ||
54 | #define NAU8825_REG_BIQ_COF10 0x2a | ||
55 | #define NAU8825_REG_ADC_RATE 0x2b | ||
56 | #define NAU8825_REG_DAC_CTRL1 0x2c | ||
57 | #define NAU8825_REG_DAC_CTRL2 0x2d | ||
58 | #define NAU8825_REG_DAC_DGAIN_CTRL 0x2f | ||
59 | #define NAU8825_REG_ADC_DGAIN_CTRL 0x30 | ||
60 | #define NAU8825_REG_MUTE_CTRL 0x31 | ||
61 | #define NAU8825_REG_HSVOL_CTRL 0x32 | ||
62 | #define NAU8825_REG_DACL_CTRL 0x33 | ||
63 | #define NAU8825_REG_DACR_CTRL 0x34 | ||
64 | #define NAU8825_REG_ADC_DRC_KNEE_IP12 0x38 | ||
65 | #define NAU8825_REG_ADC_DRC_KNEE_IP34 0x39 | ||
66 | #define NAU8825_REG_ADC_DRC_SLOPES 0x3a | ||
67 | #define NAU8825_REG_ADC_DRC_ATKDCY 0x3b | ||
68 | #define NAU8825_REG_DAC_DRC_KNEE_IP12 0x45 | ||
69 | #define NAU8825_REG_DAC_DRC_KNEE_IP34 0x46 | ||
70 | #define NAU8825_REG_DAC_DRC_SLOPES 0x47 | ||
71 | #define NAU8825_REG_DAC_DRC_ATKDCY 0x48 | ||
72 | #define NAU8825_REG_IMM_MODE_CTRL 0x4c | ||
73 | #define NAU8825_REG_IMM_RMS_L 0x4d | ||
74 | #define NAU8825_REG_IMM_RMS_R 0x4e | ||
75 | #define NAU8825_REG_CLASSG_CTRL 0x50 | ||
76 | #define NAU8825_REG_OPT_EFUSE_CTRL 0x51 | ||
77 | #define NAU8825_REG_MISC_CTRL 0x55 | ||
78 | #define NAU8825_REG_I2C_DEVICE_ID 0x58 | ||
79 | #define NAU8825_REG_SARDOUT_RAM_STATUS 0x59 | ||
80 | #define NAU8825_REG_BIAS_ADJ 0x66 | ||
81 | #define NAU8825_REG_TRIM_SETTINGS 0x68 | ||
82 | #define NAU8825_REG_ANALOG_CONTROL_1 0x69 | ||
83 | #define NAU8825_REG_ANALOG_CONTROL_2 0x6a | ||
84 | #define NAU8825_REG_ANALOG_ADC_1 0x71 | ||
85 | #define NAU8825_REG_ANALOG_ADC_2 0x72 | ||
86 | #define NAU8825_REG_RDAC 0x73 | ||
87 | #define NAU8825_REG_MIC_BIAS 0x74 | ||
88 | #define NAU8825_REG_BOOST 0x76 | ||
89 | #define NAU8825_REG_FEPGA 0x77 | ||
90 | #define NAU8825_REG_POWER_UP_CONTROL 0x7f | ||
91 | #define NAU8825_REG_CHARGE_PUMP 0x80 | ||
92 | #define NAU8825_REG_CHARGE_PUMP_INPUT_READ 0x81 | ||
93 | #define NAU8825_REG_GENERAL_STATUS 0x82 | ||
94 | #define NAU8825_REG_MAX NAU8825_REG_GENERAL_STATUS | ||
95 | |||
96 | /* ENA_CTRL (0x1) */ | ||
97 | #define NAU8825_ENABLE_DACR_SFT 10 | ||
98 | #define NAU8825_ENABLE_DACR (1 << NAU8825_ENABLE_DACR_SFT) | ||
99 | #define NAU8825_ENABLE_DACL_SFT 9 | ||
100 | #define NAU8825_ENABLE_ADC_SFT 8 | ||
101 | #define NAU8825_ENABLE_SAR_SFT 1 | ||
102 | |||
103 | /* CLK_DIVIDER (0x3) */ | ||
104 | #define NAU8825_CLK_SRC_SFT 15 | ||
105 | #define NAU8825_CLK_SRC_MASK (1 << NAU8825_CLK_SRC_SFT) | ||
106 | #define NAU8825_CLK_SRC_VCO (1 << NAU8825_CLK_SRC_SFT) | ||
107 | #define NAU8825_CLK_SRC_MCLK (0 << NAU8825_CLK_SRC_SFT) | ||
108 | |||
109 | /* FLL6 (0x9) */ | ||
110 | #define NAU8825_DCO_EN (1 << 15) | ||
111 | |||
112 | /* HSD_CTRL (0xc) */ | ||
113 | #define NAU8825_HSD_AUTO_MODE (1 << 6) | ||
114 | /* 0 - short to GND, 1 - open */ | ||
115 | #define NAU8825_SPKR_DWN1R (1 << 1) | ||
116 | #define NAU8825_SPKR_DWN1L (1 << 0) | ||
117 | |||
118 | /* JACK_DET_CTRL (0xd) */ | ||
119 | #define NAU8825_JACK_DET_RESTART (1 << 9) | ||
120 | #define NAU8825_JACK_INSERT_DEBOUNCE_SFT 5 | ||
121 | #define NAU8825_JACK_INSERT_DEBOUNCE_MASK (0x7 << NAU8825_JACK_INSERT_DEBOUNCE_SFT) | ||
122 | #define NAU8825_JACK_EJECT_DEBOUNCE_SFT 2 | ||
123 | #define NAU8825_JACK_EJECT_DEBOUNCE_MASK (0x7 << NAU8825_JACK_EJECT_DEBOUNCE_SFT) | ||
124 | #define NAU8825_JACK_POLARITY (1 << 1) /* 0 - active low, 1 - active high */ | ||
125 | |||
126 | /* INTERRUPT_MASK (0xf) */ | ||
127 | #define NAU8825_IRQ_OUTPUT_EN (1 << 11) | ||
128 | #define NAU8825_IRQ_HEADSET_COMPLETE_EN (1 << 10) | ||
129 | #define NAU8825_IRQ_KEY_RELEASE_EN (1 << 7) | ||
130 | #define NAU8825_IRQ_KEY_SHORT_PRESS_EN (1 << 5) | ||
131 | #define NAU8825_IRQ_EJECT_EN (1 << 2) | ||
132 | |||
133 | /* IRQ_STATUS (0x10) */ | ||
134 | #define NAU8825_HEADSET_COMPLETION_IRQ (1 << 10) | ||
135 | #define NAU8825_SHORT_CIRCUIT_IRQ (1 << 9) | ||
136 | #define NAU8825_IMPEDANCE_MEAS_IRQ (1 << 8) | ||
137 | #define NAU8825_KEY_IRQ_MASK (0x7 << 5) | ||
138 | #define NAU8825_KEY_RELEASE_IRQ (1 << 7) | ||
139 | #define NAU8825_KEY_LONG_PRESS_IRQ (1 << 6) | ||
140 | #define NAU8825_KEY_SHORT_PRESS_IRQ (1 << 5) | ||
141 | #define NAU8825_MIC_DETECTION_IRQ (1 << 4) | ||
142 | #define NAU8825_JACK_EJECTION_IRQ_MASK (3 << 2) | ||
143 | #define NAU8825_JACK_EJECTION_DETECTED (1 << 2) | ||
144 | #define NAU8825_JACK_INSERTION_IRQ_MASK (3 << 0) | ||
145 | #define NAU8825_JACK_INSERTION_DETECTED (1 << 0) | ||
146 | |||
147 | /* INTERRUPT_DIS_CTRL (0x12) */ | ||
148 | #define NAU8825_IRQ_HEADSET_COMPLETE_DIS (1 << 10) | ||
149 | #define NAU8825_IRQ_KEY_RELEASE_DIS (1 << 7) | ||
150 | #define NAU8825_IRQ_KEY_SHORT_PRESS_DIS (1 << 5) | ||
151 | #define NAU8825_IRQ_EJECT_DIS (1 << 2) | ||
152 | |||
153 | /* SAR_CTRL (0x13) */ | ||
154 | #define NAU8825_SAR_ADC_EN_SFT 12 | ||
155 | #define NAU8825_SAR_ADC_EN (1 << NAU8825_SAR_ADC_EN_SFT) | ||
156 | #define NAU8825_SAR_INPUT_MASK (1 << 11) | ||
157 | #define NAU8825_SAR_INPUT_JKSLV (1 << 11) | ||
158 | #define NAU8825_SAR_INPUT_JKR2 (0 << 11) | ||
159 | #define NAU8825_SAR_TRACKING_GAIN_SFT 8 | ||
160 | #define NAU8825_SAR_TRACKING_GAIN_MASK (0x7 << NAU8825_SAR_TRACKING_GAIN_SFT) | ||
161 | #define NAU8825_SAR_COMPARE_TIME_SFT 2 | ||
162 | #define NAU8825_SAR_COMPARE_TIME_MASK (3 << 2) | ||
163 | #define NAU8825_SAR_SAMPLING_TIME_SFT 0 | ||
164 | #define NAU8825_SAR_SAMPLING_TIME_MASK (3 << 0) | ||
165 | |||
166 | /* KEYDET_CTRL (0x14) */ | ||
167 | #define NAU8825_KEYDET_SHORTKEY_DEBOUNCE_SFT 12 | ||
168 | #define NAU8825_KEYDET_SHORTKEY_DEBOUNCE_MASK (0x3 << NAU8825_KEYDET_SHORTKEY_DEBOUNCE_SFT) | ||
169 | #define NAU8825_KEYDET_LEVELS_NR_SFT 8 | ||
170 | #define NAU8825_KEYDET_LEVELS_NR_MASK (0x7 << 8) | ||
171 | #define NAU8825_KEYDET_HYSTERESIS_SFT 0 | ||
172 | #define NAU8825_KEYDET_HYSTERESIS_MASK 0xf | ||
173 | |||
174 | /* GPIO12_CTRL (0x1a) */ | ||
175 | #define NAU8825_JKDET_PULL_UP (1 << 11) /* 0 - pull down, 1 - pull up */ | ||
176 | #define NAU8825_JKDET_PULL_EN (1 << 9) /* 0 - enable pull, 1 - disable */ | ||
177 | #define NAU8825_JKDET_OUTPUT_EN (1 << 8) /* 0 - enable input, 1 - enable output */ | ||
178 | |||
179 | /* I2S_PCM_CTRL1 (0x1c) */ | ||
180 | #define NAU8825_I2S_BP_SFT 7 | ||
181 | #define NAU8825_I2S_BP_MASK (1 << NAU8825_I2S_BP_SFT) | ||
182 | #define NAU8825_I2S_BP_INV (1 << NAU8825_I2S_BP_SFT) | ||
183 | #define NAU8825_I2S_PCMB_SFT 6 | ||
184 | #define NAU8825_I2S_PCMB_MASK (1 << NAU8825_I2S_PCMB_SFT) | ||
185 | #define NAU8825_I2S_PCMB_EN (1 << NAU8825_I2S_PCMB_SFT) | ||
186 | #define NAU8825_I2S_DL_SFT 2 | ||
187 | #define NAU8825_I2S_DL_MASK (0x3 << NAU8825_I2S_DL_SFT) | ||
188 | #define NAU8825_I2S_DL_16 (0 << NAU8825_I2S_DL_SFT) | ||
189 | #define NAU8825_I2S_DL_20 (1 << NAU8825_I2S_DL_SFT) | ||
190 | #define NAU8825_I2S_DL_24 (2 << NAU8825_I2S_DL_SFT) | ||
191 | #define NAU8825_I2S_DL_32 (3 << NAU8825_I2S_DL_SFT) | ||
192 | #define NAU8825_I2S_DF_SFT 0 | ||
193 | #define NAU8825_I2S_DF_MASK (0x3 << NAU8825_I2S_DF_SFT) | ||
194 | #define NAU8825_I2S_DF_RIGTH (0 << NAU8825_I2S_DF_SFT) | ||
195 | #define NAU8825_I2S_DF_LEFT (1 << NAU8825_I2S_DF_SFT) | ||
196 | #define NAU8825_I2S_DF_I2S (2 << NAU8825_I2S_DF_SFT) | ||
197 | #define NAU8825_I2S_DF_PCM_AB (3 << NAU8825_I2S_DF_SFT) | ||
198 | |||
199 | /* I2S_PCM_CTRL2 (0x1d) */ | ||
200 | #define NAU8825_I2S_TRISTATE (1 << 15) /* 0 - normal mode, 1 - Hi-Z output */ | ||
201 | #define NAU8825_I2S_MS_SFT 3 | ||
202 | #define NAU8825_I2S_MS_MASK (1 << NAU8825_I2S_MS_SFT) | ||
203 | #define NAU8825_I2S_MS_MASTER (1 << NAU8825_I2S_MS_SFT) | ||
204 | #define NAU8825_I2S_MS_SLAVE (0 << NAU8825_I2S_MS_SFT) | ||
205 | |||
206 | /* ADC_RATE (0x2b) */ | ||
207 | #define NAU8825_ADC_SYNC_DOWN_SFT 0 | ||
208 | #define NAU8825_ADC_SYNC_DOWN_MASK 0x3 | ||
209 | #define NAU8825_ADC_SYNC_DOWN_32 0 | ||
210 | #define NAU8825_ADC_SYNC_DOWN_64 1 | ||
211 | #define NAU8825_ADC_SYNC_DOWN_128 2 | ||
212 | #define NAU8825_ADC_SYNC_DOWN_256 3 | ||
213 | |||
214 | /* DAC_CTRL1 (0x2c) */ | ||
215 | #define NAU8825_DAC_CLIP_OFF (1 << 7) | ||
216 | #define NAU8825_DAC_OVERSAMPLE_SFT 0 | ||
217 | #define NAU8825_DAC_OVERSAMPLE_MASK 0x7 | ||
218 | #define NAU8825_DAC_OVERSAMPLE_64 0 | ||
219 | #define NAU8825_DAC_OVERSAMPLE_256 1 | ||
220 | #define NAU8825_DAC_OVERSAMPLE_128 2 | ||
221 | #define NAU8825_DAC_OVERSAMPLE_32 4 | ||
222 | |||
223 | /* MUTE_CTRL (0x31) */ | ||
224 | #define NAU8825_DAC_ZERO_CROSSING_EN (1 << 9) | ||
225 | #define NAU8825_DAC_SOFT_MUTE (1 << 9) | ||
226 | |||
227 | /* HSVOL_CTRL (0x32) */ | ||
228 | #define NAU8825_HP_MUTE (1 << 15) | ||
229 | |||
230 | /* DACL_CTRL (0x33) */ | ||
231 | #define NAU8825_DACL_CH_SEL_SFT 9 | ||
232 | |||
233 | /* DACR_CTRL (0x34) */ | ||
234 | #define NAU8825_DACR_CH_SEL_SFT 9 | ||
235 | |||
236 | /* I2C_DEVICE_ID (0x58) */ | ||
237 | #define NAU8825_GPIO2JD1 (1 << 7) | ||
238 | #define NAU8825_SOFTWARE_ID_MASK 0x3 | ||
239 | #define NAU8825_SOFTWARE_ID_NAU8825 0x0 | ||
240 | |||
241 | /* BIAS_ADJ (0x66) */ | ||
242 | #define NAU8825_BIAS_VMID (1 << 6) | ||
243 | #define NAU8825_BIAS_VMID_SEL_SFT 4 | ||
244 | #define NAU8825_BIAS_VMID_SEL_MASK (3 << NAU8825_BIAS_VMID_SEL_SFT) | ||
245 | |||
246 | /* ANALOG_CONTROL_2 (0x6a) */ | ||
247 | #define NAU8825_HP_NON_CLASSG_CURRENT_2xADJ (1 << 12) | ||
248 | #define NAU8825_DAC_CAPACITOR_MSB (1 << 1) | ||
249 | #define NAU8825_DAC_CAPACITOR_LSB (1 << 0) | ||
250 | |||
251 | /* ANALOG_ADC_2 (0x72) */ | ||
252 | #define NAU8825_ADC_VREFSEL_MASK (0x3 << 8) | ||
253 | #define NAU8825_ADC_VREFSEL_ANALOG (0 << 8) | ||
254 | #define NAU8825_ADC_VREFSEL_VMID (1 << 8) | ||
255 | #define NAU8825_ADC_VREFSEL_VMID_PLUS_0_5DB (2 << 8) | ||
256 | #define NAU8825_ADC_VREFSEL_VMID_PLUS_1DB (3 << 8) | ||
257 | #define NAU8825_POWERUP_ADCL (1 << 6) | ||
258 | |||
259 | /* MIC_BIAS (0x74) */ | ||
260 | #define NAU8825_MICBIAS_JKSLV (1 << 14) | ||
261 | #define NAU8825_MICBIAS_JKR2 (1 << 12) | ||
262 | #define NAU8825_MICBIAS_POWERUP_SFT 8 | ||
263 | #define NAU8825_MICBIAS_VOLTAGE_SFT 0 | ||
264 | #define NAU8825_MICBIAS_VOLTAGE_MASK 0x7 | ||
265 | |||
266 | /* BOOST (0x76) */ | ||
267 | #define NAU8825_PRECHARGE_DIS (1 << 13) | ||
268 | #define NAU8825_GLOBAL_BIAS_EN (1 << 12) | ||
269 | #define NAU8825_HP_BOOST_G_DIS (1 << 8) | ||
270 | #define NAU8825_SHORT_SHUTDOWN_EN (1 << 6) | ||
271 | |||
272 | /* POWER_UP_CONTROL (0x7f) */ | ||
273 | #define NAU8825_POWERUP_INTEGR_R (1 << 5) | ||
274 | #define NAU8825_POWERUP_INTEGR_L (1 << 4) | ||
275 | #define NAU8825_POWERUP_DRV_IN_R (1 << 3) | ||
276 | #define NAU8825_POWERUP_DRV_IN_L (1 << 2) | ||
277 | #define NAU8825_POWERUP_HP_DRV_R (1 << 1) | ||
278 | #define NAU8825_POWERUP_HP_DRV_L (1 << 0) | ||
279 | |||
280 | /* CHARGE_PUMP (0x80) */ | ||
281 | #define NAU8825_JAMNODCLOW (1 << 10) | ||
282 | #define NAU8825_POWER_DOWN_DACR (1 << 9) | ||
283 | #define NAU8825_POWER_DOWN_DACL (1 << 8) | ||
284 | #define NAU8825_CHANRGE_PUMP_EN (1 << 5) | ||
285 | |||
286 | |||
287 | /* System Clock Source */ | ||
288 | enum { | ||
289 | NAU8825_CLK_MCLK = 0, | ||
290 | NAU8825_CLK_INTERNAL, | ||
291 | }; | ||
292 | |||
293 | struct nau8825 { | ||
294 | struct device *dev; | ||
295 | struct regmap *regmap; | ||
296 | struct snd_soc_dapm_context *dapm; | ||
297 | struct snd_soc_jack *jack; | ||
298 | struct clk *mclk; | ||
299 | int irq; | ||
300 | int mclk_freq; /* 0 - mclk is disabled */ | ||
301 | int button_pressed; | ||
302 | int micbias_voltage; | ||
303 | int vref_impedance; | ||
304 | bool jkdet_enable; | ||
305 | bool jkdet_pull_enable; | ||
306 | bool jkdet_pull_up; | ||
307 | int jkdet_polarity; | ||
308 | int sar_threshold_num; | ||
309 | int sar_threshold[8]; | ||
310 | int sar_hysteresis; | ||
311 | int sar_voltage; | ||
312 | int sar_compare_time; | ||
313 | int sar_sampling_time; | ||
314 | int key_debounce; | ||
315 | int jack_insert_debounce; | ||
316 | int jack_eject_debounce; | ||
317 | }; | ||
318 | |||
319 | int nau8825_enable_jack_detect(struct snd_soc_codec *codec, | ||
320 | struct snd_soc_jack *jack); | ||
321 | |||
322 | |||
323 | #endif /* __NAU8825_H__ */ | ||