Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: nau8825: Add driver for headset chip Nuvoton 8825

Sponsored-by: Google Chromium project
Signed-off-by: Anatol Pomozov <anatol.pomozov@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Anatol Pomozov and committed by
Mark Brown
34ca27f3 95291382

+1538
+102
Documentation/devicetree/bindings/sound/nau8825.txt
··· 1 + Nuvoton NAU8825 audio codec 2 + 3 + This device supports I2C only. 4 + 5 + Required properties: 6 + - compatible : Must be "nuvoton,nau8825" 7 + 8 + - reg : the I2C address of the device. This is either 0x1a (CSB=0) or 0x1b (CSB=1). 9 + 10 + Optional properties: 11 + - nuvoton,jkdet-enable: Enable jack detection via JKDET pin. 12 + - nuvoton,jkdet-pull-enable: Enable JKDET pin pull. If set - pin pull enabled, 13 + otherwise pin in high impedance state. 14 + - nuvoton,jkdet-pull-up: Pull-up JKDET pin. If set then JKDET pin is pull up, otherwise pull down. 15 + - nuvoton,jkdet-polarity: JKDET pin polarity. 0 - active high, 1 - active low. 16 + 17 + - nuvoton,vref-impedance: VREF Impedance selection 18 + 0 - Open 19 + 1 - 25 kOhm 20 + 2 - 125 kOhm 21 + 3 - 2.5 kOhm 22 + 23 + - nuvoton,micbias-voltage: Micbias voltage level. 24 + 0 - VDDA 25 + 1 - VDDA 26 + 2 - VDDA * 1.1 27 + 3 - VDDA * 1.2 28 + 4 - VDDA * 1.3 29 + 5 - VDDA * 1.4 30 + 6 - VDDA * 1.53 31 + 7 - VDDA * 1.53 32 + 33 + - nuvoton,sar-threshold-num: Number of buttons supported 34 + - nuvoton,sar-threshold: Impedance threshold for each button. Array that contains up to 8 buttons configuration. SAR value is calculated as 35 + SAR = 255 * MICBIAS / SAR_VOLTAGE * R / (2000 + R) 36 + where MICBIAS is configured by 'nuvoton,micbias-voltage', SAR_VOLTAGE is configured by 'nuvoton,sar-voltage', R - button impedance. 37 + Refer datasheet section 10.2 for more information about threshold calculation. 38 + 39 + - nuvoton,sar-hysteresis: Button impedance measurement hysteresis. 40 + 41 + - nuvoton,sar-voltage: Reference voltage for button impedance measurement. 42 + 0 - VDDA 43 + 1 - VDDA 44 + 2 - VDDA * 1.1 45 + 3 - VDDA * 1.2 46 + 4 - VDDA * 1.3 47 + 5 - VDDA * 1.4 48 + 6 - VDDA * 1.53 49 + 7 - VDDA * 1.53 50 + 51 + - nuvoton,sar-compare-time: SAR compare time 52 + 0 - 500 ns 53 + 1 - 1 us 54 + 2 - 2 us 55 + 3 - 4 us 56 + 57 + - nuvoton,sar-sampling-time: SAR sampling time 58 + 0 - 2 us 59 + 1 - 4 us 60 + 2 - 8 us 61 + 3 - 16 us 62 + 63 + - nuvoton,short-key-debounce: Button short key press debounce time. 64 + 0 - 30 ms 65 + 1 - 50 ms 66 + 2 - 100 ms 67 + 3 - 30 ms 68 + 69 + - nuvoton,jack-insert-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms 70 + - nuvoton,jack-eject-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms 71 + 72 + - clocks: list of phandle and clock specifier pairs according to common clock bindings for the 73 + clocks described in clock-names 74 + - clock-names: should include "mclk" for the MCLK master clock 75 + 76 + Example: 77 + 78 + headset: nau8825@1a { 79 + compatible = "nuvoton,nau8825"; 80 + reg = <0x1a>; 81 + interrupt-parent = <&gpio>; 82 + interrupts = <TEGRA_GPIO(E, 6) IRQ_TYPE_LEVEL_LOW>; 83 + nuvoton,jkdet-enable; 84 + nuvoton,jkdet-pull-enable; 85 + nuvoton,jkdet-pull-up; 86 + nuvoton,jkdet-polarity = <GPIO_ACTIVE_LOW>; 87 + nuvoton,vref-impedance = <2>; 88 + nuvoton,micbias-voltage = <6>; 89 + // Setup 4 buttons impedance according to Android specification 90 + nuvoton,sar-threshold-num = <4>; 91 + nuvoton,sar-threshold = <0xc 0x1e 0x38 0x60>; 92 + nuvoton,sar-hysteresis = <1>; 93 + nuvoton,sar-voltage = <0>; 94 + nuvoton,sar-compare-time = <0>; 95 + nuvoton,sar-sampling-time = <0>; 96 + nuvoton,short-key-debounce = <2>; 97 + nuvoton,jack-insert-debounce = <7>; 98 + nuvoton,jack-eject-debounce = <7>; 99 + 100 + clock-names = "mclk"; 101 + clocks = <&tegra_car TEGRA210_CLK_CLK_OUT_2>; 102 + };
+4
sound/soc/codecs/Kconfig
··· 79 79 select SND_SOC_MAX9877 if I2C 80 80 select SND_SOC_MC13783 if MFD_MC13XXX 81 81 select SND_SOC_ML26124 if I2C 82 + select SND_SOC_NAU8825 if I2C 82 83 select SND_SOC_PCM1681 if I2C 83 84 select SND_SOC_PCM1792A if SPI_MASTER 84 85 select SND_SOC_PCM3008 ··· 891 890 tristate 892 891 893 892 config SND_SOC_ML26124 893 + tristate 894 + 895 + config SND_SOC_NAU8825 894 896 tristate 895 897 896 898 config SND_SOC_TPA6130A2
+2
sound/soc/codecs/Makefile
··· 72 72 snd-soc-max9850-objs := max9850.o 73 73 snd-soc-mc13783-objs := mc13783.o 74 74 snd-soc-ml26124-objs := ml26124.o 75 + snd-soc-nau8825-objs := nau8825.o 75 76 snd-soc-pcm1681-objs := pcm1681.o 76 77 snd-soc-pcm1792a-codec-objs := pcm1792a.o 77 78 snd-soc-pcm3008-objs := pcm3008.o ··· 264 263 obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o 265 264 obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o 266 265 obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o 266 + obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o 267 267 obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o 268 268 obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o 269 269 obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
+1107
sound/soc/codecs/nau8825.c
··· 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");
+323
sound/soc/codecs/nau8825.h
··· 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__ */