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

ASoC: codecs: Add da7219 codec driver

This adds support for the DA7219 audio codec with built-in advanced
accessory detect features.

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Adam Thomson and committed by
Mark Brown
6d817c0e c25c79b4

+3955
+99
include/sound/da7219-aad.h
··· 1 + /* 2 + * da7219-aad.h - DA7322 ASoC Codec AAD Driver Platform Data 3 + * 4 + * Copyright (c) 2015 Dialog Semiconductor Ltd. 5 + * 6 + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the 10 + * Free Software Foundation; either version 2 of the License, or (at your 11 + * option) any later version. 12 + */ 13 + 14 + #ifndef __DA7219_AAD_PDATA_H 15 + #define __DA7219_AAD_PDATA_H 16 + 17 + enum da7219_aad_micbias_pulse_lvl { 18 + DA7219_AAD_MICBIAS_PULSE_LVL_OFF = 0, 19 + DA7219_AAD_MICBIAS_PULSE_LVL_2_8V = 6, 20 + DA7219_AAD_MICBIAS_PULSE_LVL_2_9V, 21 + }; 22 + 23 + enum da7219_aad_btn_cfg { 24 + DA7219_AAD_BTN_CFG_2MS = 1, 25 + DA7219_AAD_BTN_CFG_5MS, 26 + DA7219_AAD_BTN_CFG_10MS, 27 + DA7219_AAD_BTN_CFG_50MS, 28 + DA7219_AAD_BTN_CFG_100MS, 29 + DA7219_AAD_BTN_CFG_200MS, 30 + DA7219_AAD_BTN_CFG_500MS, 31 + }; 32 + 33 + enum da7219_aad_mic_det_thr { 34 + DA7219_AAD_MIC_DET_THR_200_OHMS = 0, 35 + DA7219_AAD_MIC_DET_THR_500_OHMS, 36 + DA7219_AAD_MIC_DET_THR_750_OHMS, 37 + DA7219_AAD_MIC_DET_THR_1000_OHMS, 38 + }; 39 + 40 + enum da7219_aad_jack_ins_deb { 41 + DA7219_AAD_JACK_INS_DEB_5MS = 0, 42 + DA7219_AAD_JACK_INS_DEB_10MS, 43 + DA7219_AAD_JACK_INS_DEB_20MS, 44 + DA7219_AAD_JACK_INS_DEB_50MS, 45 + DA7219_AAD_JACK_INS_DEB_100MS, 46 + DA7219_AAD_JACK_INS_DEB_200MS, 47 + DA7219_AAD_JACK_INS_DEB_500MS, 48 + DA7219_AAD_JACK_INS_DEB_1S, 49 + }; 50 + 51 + enum da7219_aad_jack_det_rate { 52 + DA7219_AAD_JACK_DET_RATE_32_64MS = 0, 53 + DA7219_AAD_JACK_DET_RATE_64_128MS, 54 + DA7219_AAD_JACK_DET_RATE_128_256MS, 55 + DA7219_AAD_JACK_DET_RATE_256_512MS, 56 + }; 57 + 58 + enum da7219_aad_jack_rem_deb { 59 + DA7219_AAD_JACK_REM_DEB_1MS = 0, 60 + DA7219_AAD_JACK_REM_DEB_5MS, 61 + DA7219_AAD_JACK_REM_DEB_10MS, 62 + DA7219_AAD_JACK_REM_DEB_20MS, 63 + }; 64 + 65 + enum da7219_aad_btn_avg { 66 + DA7219_AAD_BTN_AVG_1 = 0, 67 + DA7219_AAD_BTN_AVG_2, 68 + DA7219_AAD_BTN_AVG_4, 69 + DA7219_AAD_BTN_AVG_8, 70 + }; 71 + 72 + enum da7219_aad_adc_1bit_rpt { 73 + DA7219_AAD_ADC_1BIT_RPT_1 = 0, 74 + DA7219_AAD_ADC_1BIT_RPT_2, 75 + DA7219_AAD_ADC_1BIT_RPT_4, 76 + DA7219_AAD_ADC_1BIT_RPT_8, 77 + }; 78 + 79 + struct da7219_aad_pdata { 80 + int irq; 81 + 82 + enum da7219_aad_micbias_pulse_lvl micbias_pulse_lvl; 83 + u32 micbias_pulse_time; 84 + enum da7219_aad_btn_cfg btn_cfg; 85 + enum da7219_aad_mic_det_thr mic_det_thr; 86 + enum da7219_aad_jack_ins_deb jack_ins_deb; 87 + enum da7219_aad_jack_det_rate jack_det_rate; 88 + enum da7219_aad_jack_rem_deb jack_rem_deb; 89 + 90 + u8 a_d_btn_thr; 91 + u8 d_b_btn_thr; 92 + u8 b_c_btn_thr; 93 + u8 c_mic_btn_thr; 94 + 95 + enum da7219_aad_btn_avg btn_avg; 96 + enum da7219_aad_adc_1bit_rpt adc_1bit_rpt; 97 + }; 98 + 99 + #endif /* __DA7219_AAD_PDATA_H */
+55
include/sound/da7219.h
··· 1 + /* 2 + * da7219.h - DA7219 ASoC Codec Driver Platform Data 3 + * 4 + * Copyright (c) 2015 Dialog Semiconductor 5 + * 6 + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the 10 + * Free Software Foundation; either version 2 of the License, or (at your 11 + * option) any later version. 12 + */ 13 + 14 + #ifndef __DA7219_PDATA_H 15 + #define __DA7219_PDATA_H 16 + 17 + /* LDO */ 18 + enum da7219_ldo_lvl_sel { 19 + DA7219_LDO_LVL_SEL_1_05V = 0, 20 + DA7219_LDO_LVL_SEL_1_10V, 21 + DA7219_LDO_LVL_SEL_1_20V, 22 + DA7219_LDO_LVL_SEL_1_40V, 23 + }; 24 + 25 + /* Mic Bias */ 26 + enum da7219_micbias_voltage { 27 + DA7219_MICBIAS_1_8V = 1, 28 + DA7219_MICBIAS_2_0V, 29 + DA7219_MICBIAS_2_2V, 30 + DA7219_MICBIAS_2_4V, 31 + DA7219_MICBIAS_2_6V, 32 + }; 33 + 34 + /* Mic input type */ 35 + enum da7219_mic_amp_in_sel { 36 + DA7219_MIC_AMP_IN_SEL_DIFF = 0, 37 + DA7219_MIC_AMP_IN_SEL_SE_P, 38 + DA7219_MIC_AMP_IN_SEL_SE_N, 39 + }; 40 + 41 + struct da7219_aad_pdata; 42 + 43 + struct da7219_pdata { 44 + /* Internal LDO */ 45 + enum da7219_ldo_lvl_sel ldo_lvl_sel; 46 + 47 + /* Mic */ 48 + enum da7219_micbias_voltage micbias_lvl; 49 + enum da7219_mic_amp_in_sel mic_amp_in_sel; 50 + 51 + /* AAD */ 52 + struct da7219_aad_pdata *aad_pdata; 53 + }; 54 + 55 + #endif /* __DA7219_PDATA_H */
+4
sound/soc/codecs/Kconfig
··· 57 57 select SND_SOC_CX20442 if TTY 58 58 select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI 59 59 select SND_SOC_DA7213 if I2C 60 + select SND_SOC_DA7219 if I2C 60 61 select SND_SOC_DA732X if I2C 61 62 select SND_SOC_DA9055 if I2C 62 63 select SND_SOC_DMIC ··· 429 428 tristate 430 429 431 430 config SND_SOC_DA7213 431 + tristate 432 + 433 + config SND_SOC_DA7219 432 434 tristate 433 435 434 436 config SND_SOC_DA732X
+2
sound/soc/codecs/Makefile
··· 49 49 snd-soc-cx20442-objs := cx20442.o 50 50 snd-soc-da7210-objs := da7210.o 51 51 snd-soc-da7213-objs := da7213.o 52 + snd-soc-da7219-objs := da7219.o da7219-aad.o 52 53 snd-soc-da732x-objs := da732x.o 53 54 snd-soc-da9055-objs := da9055.o 54 55 snd-soc-bt-sco-objs := bt-sco.o ··· 242 241 obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o 243 242 obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o 244 243 obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o 244 + obj-$(CONFIG_SND_SOC_DA7219) += snd-soc-da7219.o 245 245 obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o 246 246 obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o 247 247 obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o
+823
sound/soc/codecs/da7219-aad.c
··· 1 + /* 2 + * da7219-aad.c - Dialog DA7219 ALSA SoC AAD Driver 3 + * 4 + * Copyright (c) 2015 Dialog Semiconductor Ltd. 5 + * 6 + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the 10 + * Free Software Foundation; either version 2 of the License, or (at your 11 + * option) any later version. 12 + */ 13 + 14 + #include <linux/module.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/of_device.h> 17 + #include <linux/of_irq.h> 18 + #include <linux/pm_wakeirq.h> 19 + #include <linux/slab.h> 20 + #include <linux/delay.h> 21 + #include <linux/workqueue.h> 22 + #include <sound/soc.h> 23 + #include <sound/jack.h> 24 + #include <sound/da7219.h> 25 + 26 + #include "da7219.h" 27 + #include "da7219-aad.h" 28 + 29 + 30 + /* 31 + * Detection control 32 + */ 33 + 34 + void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack) 35 + { 36 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 37 + 38 + da7219->aad->jack = jack; 39 + da7219->aad->jack_inserted = false; 40 + 41 + /* Send an initial empty report */ 42 + snd_soc_jack_report(jack, 0, DA7219_AAD_REPORT_ALL_MASK); 43 + 44 + /* Enable/Disable jack detection */ 45 + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, 46 + DA7219_ACCDET_EN_MASK, 47 + (jack ? DA7219_ACCDET_EN_MASK : 0)); 48 + } 49 + EXPORT_SYMBOL_GPL(da7219_aad_jack_det); 50 + 51 + /* 52 + * Button/HPTest work 53 + */ 54 + 55 + static void da7219_aad_btn_det_work(struct work_struct *work) 56 + { 57 + struct da7219_aad_priv *da7219_aad = 58 + container_of(work, struct da7219_aad_priv, btn_det_work); 59 + struct snd_soc_codec *codec = da7219_aad->codec; 60 + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); 61 + u8 statusa, micbias_ctrl; 62 + bool micbias_up = false; 63 + int retries = 0; 64 + 65 + /* Drive headphones/lineout */ 66 + snd_soc_update_bits(codec, DA7219_HP_L_CTRL, 67 + DA7219_HP_L_AMP_OE_MASK, 68 + DA7219_HP_L_AMP_OE_MASK); 69 + snd_soc_update_bits(codec, DA7219_HP_R_CTRL, 70 + DA7219_HP_R_AMP_OE_MASK, 71 + DA7219_HP_R_AMP_OE_MASK); 72 + 73 + /* Make sure mic bias is up */ 74 + snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); 75 + snd_soc_dapm_sync(dapm); 76 + 77 + do { 78 + statusa = snd_soc_read(codec, DA7219_ACCDET_STATUS_A); 79 + if (statusa & DA7219_MICBIAS_UP_STS_MASK) 80 + micbias_up = true; 81 + else if (retries++ < DA7219_AAD_MICBIAS_CHK_RETRIES) 82 + msleep(DA7219_AAD_MICBIAS_CHK_DELAY); 83 + } while ((!micbias_up) && (retries < DA7219_AAD_MICBIAS_CHK_RETRIES)); 84 + 85 + if (retries >= DA7219_AAD_MICBIAS_CHK_RETRIES) 86 + dev_warn(codec->dev, "Mic bias status check timed out"); 87 + 88 + /* 89 + * Mic bias pulse required to enable mic, must be done before enabling 90 + * button detection to prevent erroneous button readings. 91 + */ 92 + if (da7219_aad->micbias_pulse_lvl && da7219_aad->micbias_pulse_time) { 93 + /* Pulse higher level voltage */ 94 + micbias_ctrl = snd_soc_read(codec, DA7219_MICBIAS_CTRL); 95 + snd_soc_update_bits(codec, DA7219_MICBIAS_CTRL, 96 + DA7219_MICBIAS1_LEVEL_MASK, 97 + da7219_aad->micbias_pulse_lvl); 98 + msleep(da7219_aad->micbias_pulse_time); 99 + snd_soc_write(codec, DA7219_MICBIAS_CTRL, micbias_ctrl); 100 + 101 + } 102 + 103 + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, 104 + DA7219_BUTTON_CONFIG_MASK, 105 + da7219_aad->btn_cfg); 106 + } 107 + 108 + static void da7219_aad_hptest_work(struct work_struct *work) 109 + { 110 + struct da7219_aad_priv *da7219_aad = 111 + container_of(work, struct da7219_aad_priv, hptest_work); 112 + struct snd_soc_codec *codec = da7219_aad->codec; 113 + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); 114 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 115 + 116 + u16 tonegen_freq_hptest; 117 + u8 accdet_cfg8; 118 + int report = 0; 119 + 120 + /* Lock DAPM and any Kcontrols that are affected by this test */ 121 + snd_soc_dapm_mutex_lock(dapm); 122 + mutex_lock(&da7219->lock); 123 + 124 + /* Bypass cache so it saves current settings */ 125 + regcache_cache_bypass(da7219->regmap, true); 126 + 127 + /* Make sure Tone Generator is disabled */ 128 + snd_soc_write(codec, DA7219_TONE_GEN_CFG1, 0); 129 + 130 + /* Enable HPTest block, 1KOhms check */ 131 + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8, 132 + DA7219_HPTEST_EN_MASK | DA7219_HPTEST_RES_SEL_MASK, 133 + DA7219_HPTEST_EN_MASK | 134 + DA7219_HPTEST_RES_SEL_1KOHMS); 135 + 136 + /* Set gains to 0db */ 137 + snd_soc_write(codec, DA7219_DAC_L_GAIN, DA7219_DAC_DIGITAL_GAIN_0DB); 138 + snd_soc_write(codec, DA7219_DAC_R_GAIN, DA7219_DAC_DIGITAL_GAIN_0DB); 139 + snd_soc_write(codec, DA7219_HP_L_GAIN, DA7219_HP_AMP_GAIN_0DB); 140 + snd_soc_write(codec, DA7219_HP_R_GAIN, DA7219_HP_AMP_GAIN_0DB); 141 + 142 + /* Disable DAC filters, EQs and soft mute */ 143 + snd_soc_update_bits(codec, DA7219_DAC_FILTERS1, DA7219_HPF_MODE_MASK, 144 + 0); 145 + snd_soc_update_bits(codec, DA7219_DAC_FILTERS4, DA7219_DAC_EQ_EN_MASK, 146 + 0); 147 + snd_soc_update_bits(codec, DA7219_DAC_FILTERS5, 148 + DA7219_DAC_SOFTMUTE_EN_MASK, 0); 149 + 150 + /* Enable HP left & right paths */ 151 + snd_soc_update_bits(codec, DA7219_CP_CTRL, DA7219_CP_EN_MASK, 152 + DA7219_CP_EN_MASK); 153 + snd_soc_update_bits(codec, DA7219_DIG_ROUTING_DAC, 154 + DA7219_DAC_L_SRC_MASK | DA7219_DAC_R_SRC_MASK, 155 + DA7219_DAC_L_SRC_TONEGEN | 156 + DA7219_DAC_R_SRC_TONEGEN); 157 + snd_soc_update_bits(codec, DA7219_DAC_L_CTRL, 158 + DA7219_DAC_L_EN_MASK | DA7219_DAC_L_MUTE_EN_MASK, 159 + DA7219_DAC_L_EN_MASK); 160 + snd_soc_update_bits(codec, DA7219_DAC_R_CTRL, 161 + DA7219_DAC_R_EN_MASK | DA7219_DAC_R_MUTE_EN_MASK, 162 + DA7219_DAC_R_EN_MASK); 163 + snd_soc_update_bits(codec, DA7219_MIXOUT_L_SELECT, 164 + DA7219_MIXOUT_L_MIX_SELECT_MASK, 165 + DA7219_MIXOUT_L_MIX_SELECT_MASK); 166 + snd_soc_update_bits(codec, DA7219_MIXOUT_R_SELECT, 167 + DA7219_MIXOUT_R_MIX_SELECT_MASK, 168 + DA7219_MIXOUT_R_MIX_SELECT_MASK); 169 + snd_soc_update_bits(codec, DA7219_DROUTING_ST_OUTFILT_1L, 170 + DA7219_OUTFILT_ST_1L_SRC_MASK, 171 + DA7219_DMIX_ST_SRC_OUTFILT1L); 172 + snd_soc_update_bits(codec, DA7219_DROUTING_ST_OUTFILT_1R, 173 + DA7219_OUTFILT_ST_1R_SRC_MASK, 174 + DA7219_DMIX_ST_SRC_OUTFILT1R); 175 + snd_soc_update_bits(codec, DA7219_MIXOUT_L_CTRL, 176 + DA7219_MIXOUT_L_AMP_EN_MASK, 177 + DA7219_MIXOUT_L_AMP_EN_MASK); 178 + snd_soc_update_bits(codec, DA7219_MIXOUT_R_CTRL, 179 + DA7219_MIXOUT_R_AMP_EN_MASK, 180 + DA7219_MIXOUT_R_AMP_EN_MASK); 181 + snd_soc_write(codec, DA7219_HP_L_CTRL, 182 + DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK); 183 + snd_soc_write(codec, DA7219_HP_R_CTRL, 184 + DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK); 185 + 186 + /* Configure & start Tone Generator */ 187 + snd_soc_write(codec, DA7219_TONE_GEN_ON_PER, DA7219_BEEP_ON_PER_MASK); 188 + tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ); 189 + regmap_raw_write(da7219->regmap, DA7219_TONE_GEN_FREQ1_L, 190 + &tonegen_freq_hptest, sizeof(tonegen_freq_hptest)); 191 + snd_soc_update_bits(codec, DA7219_TONE_GEN_CFG2, 192 + DA7219_SWG_SEL_MASK | DA7219_TONE_GEN_GAIN_MASK, 193 + DA7219_SWG_SEL_SRAMP | 194 + DA7219_TONE_GEN_GAIN_MINUS_15DB); 195 + snd_soc_write(codec, DA7219_TONE_GEN_CFG1, DA7219_START_STOPN_MASK); 196 + 197 + msleep(DA7219_AAD_HPTEST_PERIOD); 198 + 199 + /* Grab comparator reading */ 200 + accdet_cfg8 = snd_soc_read(codec, DA7219_ACCDET_CONFIG_8); 201 + if (accdet_cfg8 & DA7219_HPTEST_COMP_MASK) 202 + report |= SND_JACK_HEADPHONE; 203 + else 204 + report |= SND_JACK_LINEOUT; 205 + 206 + /* Stop tone generator */ 207 + snd_soc_write(codec, DA7219_TONE_GEN_CFG1, 0); 208 + 209 + msleep(DA7219_AAD_HPTEST_PERIOD); 210 + 211 + /* Restore original settings from cache */ 212 + regcache_mark_dirty(da7219->regmap); 213 + regcache_sync_region(da7219->regmap, DA7219_HP_L_CTRL, 214 + DA7219_HP_R_CTRL); 215 + regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_CTRL, 216 + DA7219_MIXOUT_R_CTRL); 217 + regcache_sync_region(da7219->regmap, DA7219_DROUTING_ST_OUTFILT_1L, 218 + DA7219_DROUTING_ST_OUTFILT_1R); 219 + regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_SELECT, 220 + DA7219_MIXOUT_R_SELECT); 221 + regcache_sync_region(da7219->regmap, DA7219_DAC_L_CTRL, 222 + DA7219_DAC_R_CTRL); 223 + regcache_sync_region(da7219->regmap, DA7219_DIG_ROUTING_DAC, 224 + DA7219_DIG_ROUTING_DAC); 225 + regcache_sync_region(da7219->regmap, DA7219_CP_CTRL, DA7219_CP_CTRL); 226 + regcache_sync_region(da7219->regmap, DA7219_DAC_FILTERS5, 227 + DA7219_DAC_FILTERS5); 228 + regcache_sync_region(da7219->regmap, DA7219_DAC_FILTERS4, 229 + DA7219_DAC_FILTERS1); 230 + regcache_sync_region(da7219->regmap, DA7219_HP_L_GAIN, 231 + DA7219_HP_R_GAIN); 232 + regcache_sync_region(da7219->regmap, DA7219_DAC_L_GAIN, 233 + DA7219_DAC_R_GAIN); 234 + regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_ON_PER, 235 + DA7219_TONE_GEN_ON_PER); 236 + regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_FREQ1_L, 237 + DA7219_TONE_GEN_FREQ1_U); 238 + regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_CFG1, 239 + DA7219_TONE_GEN_CFG2); 240 + 241 + regcache_cache_bypass(da7219->regmap, false); 242 + 243 + /* Disable HPTest block */ 244 + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8, 245 + DA7219_HPTEST_EN_MASK, 0); 246 + 247 + /* Drive Headphones/lineout */ 248 + snd_soc_update_bits(codec, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK, 249 + DA7219_HP_L_AMP_OE_MASK); 250 + snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK, 251 + DA7219_HP_R_AMP_OE_MASK); 252 + 253 + mutex_unlock(&da7219->lock); 254 + snd_soc_dapm_mutex_unlock(dapm); 255 + 256 + /* 257 + * Only send report if jack hasn't been removed during process, 258 + * otherwise it's invalid and we drop it. 259 + */ 260 + if (da7219_aad->jack_inserted) 261 + snd_soc_jack_report(da7219_aad->jack, report, 262 + SND_JACK_HEADSET | SND_JACK_LINEOUT); 263 + } 264 + 265 + 266 + /* 267 + * IRQ 268 + */ 269 + 270 + static irqreturn_t da7219_aad_irq_thread(int irq, void *data) 271 + { 272 + struct da7219_aad_priv *da7219_aad = data; 273 + struct snd_soc_codec *codec = da7219_aad->codec; 274 + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); 275 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 276 + u8 events[DA7219_AAD_IRQ_REG_MAX]; 277 + u8 statusa; 278 + int i, report = 0, mask = 0; 279 + 280 + /* Read current IRQ events */ 281 + regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A, 282 + events, DA7219_AAD_IRQ_REG_MAX); 283 + 284 + if (!events[DA7219_AAD_IRQ_REG_A] && !events[DA7219_AAD_IRQ_REG_B]) 285 + return IRQ_NONE; 286 + 287 + /* Read status register for jack insertion & type status */ 288 + statusa = snd_soc_read(codec, DA7219_ACCDET_STATUS_A); 289 + 290 + /* Clear events */ 291 + regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A, 292 + events, DA7219_AAD_IRQ_REG_MAX); 293 + 294 + dev_dbg(codec->dev, "IRQ events = 0x%x|0x%x, status = 0x%x\n", 295 + events[DA7219_AAD_IRQ_REG_A], events[DA7219_AAD_IRQ_REG_B], 296 + statusa); 297 + 298 + if (statusa & DA7219_JACK_INSERTION_STS_MASK) { 299 + /* Jack Insertion */ 300 + if (events[DA7219_AAD_IRQ_REG_A] & 301 + DA7219_E_JACK_INSERTED_MASK) { 302 + report |= SND_JACK_MECHANICAL; 303 + mask |= SND_JACK_MECHANICAL; 304 + da7219_aad->jack_inserted = true; 305 + } 306 + 307 + /* Jack type detection */ 308 + if (events[DA7219_AAD_IRQ_REG_A] & 309 + DA7219_E_JACK_DETECT_COMPLETE_MASK) { 310 + /* 311 + * If 4-pole, then enable button detection, else perform 312 + * HP impedance test to determine output type to report. 313 + * 314 + * We schedule work here as the tasks themselves can 315 + * take time to complete, and in particular for hptest 316 + * we want to be able to check if the jack was removed 317 + * during the procedure as this will invalidate the 318 + * result. By doing this as work, the IRQ thread can 319 + * handle a removal, and we can check at the end of 320 + * hptest if we have a valid result or not. 321 + */ 322 + if (statusa & DA7219_JACK_TYPE_STS_MASK) { 323 + report |= SND_JACK_HEADSET; 324 + mask |= SND_JACK_HEADSET | SND_JACK_LINEOUT; 325 + schedule_work(&da7219_aad->btn_det_work); 326 + } else { 327 + schedule_work(&da7219_aad->hptest_work); 328 + } 329 + } 330 + 331 + /* Button support for 4-pole jack */ 332 + if (statusa & DA7219_JACK_TYPE_STS_MASK) { 333 + for (i = 0; i < DA7219_AAD_MAX_BUTTONS; ++i) { 334 + /* Button Press */ 335 + if (events[DA7219_AAD_IRQ_REG_B] & 336 + (DA7219_E_BUTTON_A_PRESSED_MASK << i)) { 337 + report |= SND_JACK_BTN_0 >> i; 338 + mask |= SND_JACK_BTN_0 >> i; 339 + } 340 + } 341 + snd_soc_jack_report(da7219_aad->jack, report, mask); 342 + 343 + for (i = 0; i < DA7219_AAD_MAX_BUTTONS; ++i) { 344 + /* Button Release */ 345 + if (events[DA7219_AAD_IRQ_REG_B] & 346 + (DA7219_E_BUTTON_A_RELEASED_MASK >> i)) { 347 + report &= ~(SND_JACK_BTN_0 >> i); 348 + mask |= SND_JACK_BTN_0 >> i; 349 + } 350 + } 351 + } 352 + } else { 353 + /* Jack removal */ 354 + if (events[DA7219_AAD_IRQ_REG_A] & DA7219_E_JACK_REMOVED_MASK) { 355 + report = 0; 356 + mask |= DA7219_AAD_REPORT_ALL_MASK; 357 + da7219_aad->jack_inserted = false; 358 + 359 + /* Un-drive headphones/lineout */ 360 + snd_soc_update_bits(codec, DA7219_HP_R_CTRL, 361 + DA7219_HP_R_AMP_OE_MASK, 0); 362 + snd_soc_update_bits(codec, DA7219_HP_L_CTRL, 363 + DA7219_HP_L_AMP_OE_MASK, 0); 364 + 365 + /* Ensure button detection disabled */ 366 + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, 367 + DA7219_BUTTON_CONFIG_MASK, 0); 368 + 369 + /* Disable mic bias */ 370 + snd_soc_dapm_disable_pin(dapm, "Mic Bias"); 371 + snd_soc_dapm_sync(dapm); 372 + 373 + /* Cancel any pending work */ 374 + cancel_work_sync(&da7219_aad->btn_det_work); 375 + cancel_work_sync(&da7219_aad->hptest_work); 376 + } 377 + } 378 + 379 + snd_soc_jack_report(da7219_aad->jack, report, mask); 380 + 381 + return IRQ_HANDLED; 382 + } 383 + 384 + /* 385 + * DT to pdata conversion 386 + */ 387 + 388 + static enum da7219_aad_micbias_pulse_lvl 389 + da7219_aad_of_micbias_pulse_lvl(struct snd_soc_codec *codec, u32 val) 390 + { 391 + switch (val) { 392 + case 2800: 393 + return DA7219_AAD_MICBIAS_PULSE_LVL_2_8V; 394 + case 2900: 395 + return DA7219_AAD_MICBIAS_PULSE_LVL_2_9V; 396 + default: 397 + dev_warn(codec->dev, "Invalid micbias pulse level"); 398 + return DA7219_AAD_MICBIAS_PULSE_LVL_OFF; 399 + } 400 + } 401 + 402 + static enum da7219_aad_btn_cfg 403 + da7219_aad_of_btn_cfg(struct snd_soc_codec *codec, u32 val) 404 + { 405 + switch (val) { 406 + case 2: 407 + return DA7219_AAD_BTN_CFG_2MS; 408 + case 5: 409 + return DA7219_AAD_BTN_CFG_5MS; 410 + case 10: 411 + return DA7219_AAD_BTN_CFG_10MS; 412 + case 50: 413 + return DA7219_AAD_BTN_CFG_50MS; 414 + case 100: 415 + return DA7219_AAD_BTN_CFG_100MS; 416 + case 200: 417 + return DA7219_AAD_BTN_CFG_200MS; 418 + case 500: 419 + return DA7219_AAD_BTN_CFG_500MS; 420 + default: 421 + dev_warn(codec->dev, "Invalid button config"); 422 + return DA7219_AAD_BTN_CFG_10MS; 423 + } 424 + } 425 + 426 + static enum da7219_aad_mic_det_thr 427 + da7219_aad_of_mic_det_thr(struct snd_soc_codec *codec, u32 val) 428 + { 429 + switch (val) { 430 + case 200: 431 + return DA7219_AAD_MIC_DET_THR_200_OHMS; 432 + case 500: 433 + return DA7219_AAD_MIC_DET_THR_500_OHMS; 434 + case 750: 435 + return DA7219_AAD_MIC_DET_THR_750_OHMS; 436 + case 1000: 437 + return DA7219_AAD_MIC_DET_THR_1000_OHMS; 438 + default: 439 + dev_warn(codec->dev, "Invalid mic detect threshold"); 440 + return DA7219_AAD_MIC_DET_THR_500_OHMS; 441 + } 442 + } 443 + 444 + static enum da7219_aad_jack_ins_deb 445 + da7219_aad_of_jack_ins_deb(struct snd_soc_codec *codec, u32 val) 446 + { 447 + switch (val) { 448 + case 5: 449 + return DA7219_AAD_JACK_INS_DEB_5MS; 450 + case 10: 451 + return DA7219_AAD_JACK_INS_DEB_10MS; 452 + case 20: 453 + return DA7219_AAD_JACK_INS_DEB_20MS; 454 + case 50: 455 + return DA7219_AAD_JACK_INS_DEB_50MS; 456 + case 100: 457 + return DA7219_AAD_JACK_INS_DEB_100MS; 458 + case 200: 459 + return DA7219_AAD_JACK_INS_DEB_200MS; 460 + case 500: 461 + return DA7219_AAD_JACK_INS_DEB_500MS; 462 + case 1000: 463 + return DA7219_AAD_JACK_INS_DEB_1S; 464 + default: 465 + dev_warn(codec->dev, "Invalid jack insert debounce"); 466 + return DA7219_AAD_JACK_INS_DEB_20MS; 467 + } 468 + } 469 + 470 + static enum da7219_aad_jack_det_rate 471 + da7219_aad_of_jack_det_rate(struct snd_soc_codec *codec, const char *str) 472 + { 473 + if (!strcmp(str, "32ms_64ms")) { 474 + return DA7219_AAD_JACK_DET_RATE_32_64MS; 475 + } else if (!strcmp(str, "64ms_128ms")) { 476 + return DA7219_AAD_JACK_DET_RATE_64_128MS; 477 + } else if (!strcmp(str, "128ms_256ms")) { 478 + return DA7219_AAD_JACK_DET_RATE_128_256MS; 479 + } else if (!strcmp(str, "256ms_512ms")) { 480 + return DA7219_AAD_JACK_DET_RATE_256_512MS; 481 + } else { 482 + dev_warn(codec->dev, "Invalid jack detect rate"); 483 + return DA7219_AAD_JACK_DET_RATE_256_512MS; 484 + } 485 + } 486 + 487 + static enum da7219_aad_jack_rem_deb 488 + da7219_aad_of_jack_rem_deb(struct snd_soc_codec *codec, u32 val) 489 + { 490 + switch (val) { 491 + case 1: 492 + return DA7219_AAD_JACK_REM_DEB_1MS; 493 + case 5: 494 + return DA7219_AAD_JACK_REM_DEB_5MS; 495 + case 10: 496 + return DA7219_AAD_JACK_REM_DEB_10MS; 497 + case 20: 498 + return DA7219_AAD_JACK_REM_DEB_20MS; 499 + default: 500 + dev_warn(codec->dev, "Invalid jack removal debounce"); 501 + return DA7219_AAD_JACK_REM_DEB_1MS; 502 + } 503 + } 504 + 505 + static enum da7219_aad_btn_avg 506 + da7219_aad_of_btn_avg(struct snd_soc_codec *codec, u32 val) 507 + { 508 + switch (val) { 509 + case 1: 510 + return DA7219_AAD_BTN_AVG_1; 511 + case 2: 512 + return DA7219_AAD_BTN_AVG_2; 513 + case 4: 514 + return DA7219_AAD_BTN_AVG_4; 515 + case 8: 516 + return DA7219_AAD_BTN_AVG_8; 517 + default: 518 + dev_warn(codec->dev, "Invalid button average value"); 519 + return DA7219_AAD_BTN_AVG_2; 520 + } 521 + } 522 + 523 + static enum da7219_aad_adc_1bit_rpt 524 + da7219_aad_of_adc_1bit_rpt(struct snd_soc_codec *codec, u32 val) 525 + { 526 + switch (val) { 527 + case 1: 528 + return DA7219_AAD_ADC_1BIT_RPT_1; 529 + case 2: 530 + return DA7219_AAD_ADC_1BIT_RPT_2; 531 + case 4: 532 + return DA7219_AAD_ADC_1BIT_RPT_4; 533 + case 8: 534 + return DA7219_AAD_ADC_1BIT_RPT_8; 535 + default: 536 + dev_warn(codec->dev, "Invalid ADC 1-bit repeat value"); 537 + return DA7219_AAD_ADC_1BIT_RPT_1; 538 + } 539 + } 540 + 541 + static struct da7219_aad_pdata *da7219_aad_of_to_pdata(struct snd_soc_codec *codec) 542 + { 543 + struct device_node *np = codec->dev->of_node; 544 + struct device_node *aad_np = of_find_node_by_name(np, "da7219_aad"); 545 + struct da7219_aad_pdata *aad_pdata; 546 + const char *of_str; 547 + u32 of_val32; 548 + 549 + if (!aad_np) 550 + return NULL; 551 + 552 + aad_pdata = devm_kzalloc(codec->dev, sizeof(*aad_pdata), GFP_KERNEL); 553 + if (!aad_pdata) 554 + goto out; 555 + 556 + aad_pdata->irq = irq_of_parse_and_map(np, 0); 557 + 558 + if (of_property_read_u32(aad_np, "dlg,micbias-pulse-lvl", 559 + &of_val32) >= 0) 560 + aad_pdata->micbias_pulse_lvl = 561 + da7219_aad_of_micbias_pulse_lvl(codec, of_val32); 562 + else 563 + aad_pdata->micbias_pulse_lvl = DA7219_AAD_MICBIAS_PULSE_LVL_OFF; 564 + 565 + if (of_property_read_u32(aad_np, "dlg,micbias-pulse-time", 566 + &of_val32) >= 0) 567 + aad_pdata->micbias_pulse_time = of_val32; 568 + 569 + if (of_property_read_u32(aad_np, "dlg,btn-cfg", &of_val32) >= 0) 570 + aad_pdata->btn_cfg = da7219_aad_of_btn_cfg(codec, of_val32); 571 + else 572 + aad_pdata->btn_cfg = DA7219_AAD_BTN_CFG_10MS; 573 + 574 + if (of_property_read_u32(aad_np, "dlg,mic-det-thr", &of_val32) >= 0) 575 + aad_pdata->mic_det_thr = 576 + da7219_aad_of_mic_det_thr(codec, of_val32); 577 + else 578 + aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_500_OHMS; 579 + 580 + if (of_property_read_u32(aad_np, "dlg,jack-ins-deb", &of_val32) >= 0) 581 + aad_pdata->jack_ins_deb = 582 + da7219_aad_of_jack_ins_deb(codec, of_val32); 583 + else 584 + aad_pdata->jack_ins_deb = DA7219_AAD_JACK_INS_DEB_20MS; 585 + 586 + if (!of_property_read_string(aad_np, "dlg,jack-det-rate", &of_str)) 587 + aad_pdata->jack_det_rate = 588 + da7219_aad_of_jack_det_rate(codec, of_str); 589 + else 590 + aad_pdata->jack_det_rate = DA7219_AAD_JACK_DET_RATE_256_512MS; 591 + 592 + if (of_property_read_u32(aad_np, "dlg,jack-rem-deb", &of_val32) >= 0) 593 + aad_pdata->jack_rem_deb = 594 + da7219_aad_of_jack_rem_deb(codec, of_val32); 595 + else 596 + aad_pdata->jack_rem_deb = DA7219_AAD_JACK_REM_DEB_1MS; 597 + 598 + if (of_property_read_u32(aad_np, "dlg,a-d-btn-thr", &of_val32) >= 0) 599 + aad_pdata->a_d_btn_thr = (u8) of_val32; 600 + else 601 + aad_pdata->a_d_btn_thr = 0xA; 602 + 603 + if (of_property_read_u32(aad_np, "dlg,d-b-btn-thr", &of_val32) >= 0) 604 + aad_pdata->d_b_btn_thr = (u8) of_val32; 605 + else 606 + aad_pdata->d_b_btn_thr = 0x16; 607 + 608 + if (of_property_read_u32(aad_np, "dlg,b-c-btn-thr", &of_val32) >= 0) 609 + aad_pdata->b_c_btn_thr = (u8) of_val32; 610 + else 611 + aad_pdata->b_c_btn_thr = 0x21; 612 + 613 + if (of_property_read_u32(aad_np, "dlg,c-mic-btn-thr", &of_val32) >= 0) 614 + aad_pdata->c_mic_btn_thr = (u8) of_val32; 615 + else 616 + aad_pdata->c_mic_btn_thr = 0x3E; 617 + 618 + if (of_property_read_u32(aad_np, "dlg,btn-avg", &of_val32) >= 0) 619 + aad_pdata->btn_avg = da7219_aad_of_btn_avg(codec, of_val32); 620 + else 621 + aad_pdata->btn_avg = DA7219_AAD_BTN_AVG_2; 622 + 623 + if (of_property_read_u32(aad_np, "dlg,adc-1bit-rpt", &of_val32) >= 0) 624 + aad_pdata->adc_1bit_rpt = 625 + da7219_aad_of_adc_1bit_rpt(codec, of_val32); 626 + else 627 + aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1; 628 + 629 + out: 630 + of_node_put(aad_np); 631 + 632 + return aad_pdata; 633 + } 634 + 635 + static void da7219_aad_handle_pdata(struct snd_soc_codec *codec) 636 + { 637 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 638 + struct da7219_aad_priv *da7219_aad = da7219->aad; 639 + struct da7219_pdata *pdata = da7219->pdata; 640 + 641 + if ((pdata) && (pdata->aad_pdata)) { 642 + struct da7219_aad_pdata *aad_pdata = pdata->aad_pdata; 643 + u8 cfg, mask; 644 + 645 + da7219_aad->irq = aad_pdata->irq; 646 + 647 + switch (aad_pdata->micbias_pulse_lvl) { 648 + case DA7219_AAD_MICBIAS_PULSE_LVL_2_8V: 649 + case DA7219_AAD_MICBIAS_PULSE_LVL_2_9V: 650 + da7219_aad->micbias_pulse_lvl = 651 + (aad_pdata->micbias_pulse_lvl << 652 + DA7219_MICBIAS1_LEVEL_SHIFT); 653 + break; 654 + default: 655 + break; 656 + } 657 + 658 + da7219_aad->micbias_pulse_time = aad_pdata->micbias_pulse_time; 659 + 660 + switch (aad_pdata->btn_cfg) { 661 + case DA7219_AAD_BTN_CFG_2MS: 662 + case DA7219_AAD_BTN_CFG_5MS: 663 + case DA7219_AAD_BTN_CFG_10MS: 664 + case DA7219_AAD_BTN_CFG_50MS: 665 + case DA7219_AAD_BTN_CFG_100MS: 666 + case DA7219_AAD_BTN_CFG_200MS: 667 + case DA7219_AAD_BTN_CFG_500MS: 668 + da7219_aad->btn_cfg = (aad_pdata->btn_cfg << 669 + DA7219_BUTTON_CONFIG_SHIFT); 670 + } 671 + 672 + cfg = 0; 673 + mask = 0; 674 + switch (aad_pdata->mic_det_thr) { 675 + case DA7219_AAD_MIC_DET_THR_200_OHMS: 676 + case DA7219_AAD_MIC_DET_THR_500_OHMS: 677 + case DA7219_AAD_MIC_DET_THR_750_OHMS: 678 + case DA7219_AAD_MIC_DET_THR_1000_OHMS: 679 + cfg |= (aad_pdata->mic_det_thr << 680 + DA7219_MIC_DET_THRESH_SHIFT); 681 + mask |= DA7219_MIC_DET_THRESH_MASK; 682 + } 683 + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, mask, cfg); 684 + 685 + cfg = 0; 686 + mask = 0; 687 + switch (aad_pdata->jack_ins_deb) { 688 + case DA7219_AAD_JACK_INS_DEB_5MS: 689 + case DA7219_AAD_JACK_INS_DEB_10MS: 690 + case DA7219_AAD_JACK_INS_DEB_20MS: 691 + case DA7219_AAD_JACK_INS_DEB_50MS: 692 + case DA7219_AAD_JACK_INS_DEB_100MS: 693 + case DA7219_AAD_JACK_INS_DEB_200MS: 694 + case DA7219_AAD_JACK_INS_DEB_500MS: 695 + case DA7219_AAD_JACK_INS_DEB_1S: 696 + cfg |= (aad_pdata->jack_ins_deb << 697 + DA7219_JACKDET_DEBOUNCE_SHIFT); 698 + mask |= DA7219_JACKDET_DEBOUNCE_MASK; 699 + } 700 + switch (aad_pdata->jack_det_rate) { 701 + case DA7219_AAD_JACK_DET_RATE_32_64MS: 702 + case DA7219_AAD_JACK_DET_RATE_64_128MS: 703 + case DA7219_AAD_JACK_DET_RATE_128_256MS: 704 + case DA7219_AAD_JACK_DET_RATE_256_512MS: 705 + cfg |= (aad_pdata->jack_det_rate << 706 + DA7219_JACK_DETECT_RATE_SHIFT); 707 + mask |= DA7219_JACK_DETECT_RATE_MASK; 708 + } 709 + switch (aad_pdata->jack_rem_deb) { 710 + case DA7219_AAD_JACK_REM_DEB_1MS: 711 + case DA7219_AAD_JACK_REM_DEB_5MS: 712 + case DA7219_AAD_JACK_REM_DEB_10MS: 713 + case DA7219_AAD_JACK_REM_DEB_20MS: 714 + cfg |= (aad_pdata->jack_rem_deb << 715 + DA7219_JACKDET_REM_DEB_SHIFT); 716 + mask |= DA7219_JACKDET_REM_DEB_MASK; 717 + } 718 + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_2, mask, cfg); 719 + 720 + snd_soc_write(codec, DA7219_ACCDET_CONFIG_3, 721 + aad_pdata->a_d_btn_thr); 722 + snd_soc_write(codec, DA7219_ACCDET_CONFIG_4, 723 + aad_pdata->d_b_btn_thr); 724 + snd_soc_write(codec, DA7219_ACCDET_CONFIG_5, 725 + aad_pdata->b_c_btn_thr); 726 + snd_soc_write(codec, DA7219_ACCDET_CONFIG_6, 727 + aad_pdata->c_mic_btn_thr); 728 + 729 + cfg = 0; 730 + mask = 0; 731 + switch (aad_pdata->btn_avg) { 732 + case DA7219_AAD_BTN_AVG_1: 733 + case DA7219_AAD_BTN_AVG_2: 734 + case DA7219_AAD_BTN_AVG_4: 735 + case DA7219_AAD_BTN_AVG_8: 736 + cfg |= (aad_pdata->btn_avg << 737 + DA7219_BUTTON_AVERAGE_SHIFT); 738 + mask |= DA7219_BUTTON_AVERAGE_MASK; 739 + } 740 + switch (aad_pdata->adc_1bit_rpt) { 741 + case DA7219_AAD_ADC_1BIT_RPT_1: 742 + case DA7219_AAD_ADC_1BIT_RPT_2: 743 + case DA7219_AAD_ADC_1BIT_RPT_4: 744 + case DA7219_AAD_ADC_1BIT_RPT_8: 745 + cfg |= (aad_pdata->adc_1bit_rpt << 746 + DA7219_ADC_1_BIT_REPEAT_SHIFT); 747 + mask |= DA7219_ADC_1_BIT_REPEAT_MASK; 748 + } 749 + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_7, mask, cfg); 750 + } 751 + } 752 + 753 + 754 + /* 755 + * Init/Exit 756 + */ 757 + 758 + int da7219_aad_init(struct snd_soc_codec *codec) 759 + { 760 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 761 + struct da7219_aad_priv *da7219_aad; 762 + u8 mask[DA7219_AAD_IRQ_REG_MAX]; 763 + int ret; 764 + 765 + da7219_aad = devm_kzalloc(codec->dev, sizeof(*da7219_aad), GFP_KERNEL); 766 + if (!da7219_aad) 767 + return -ENOMEM; 768 + 769 + da7219->aad = da7219_aad; 770 + da7219_aad->codec = codec; 771 + 772 + /* Handle any DT/platform data */ 773 + if ((codec->dev->of_node) && (da7219->pdata)) 774 + da7219->pdata->aad_pdata = da7219_aad_of_to_pdata(codec); 775 + 776 + da7219_aad_handle_pdata(codec); 777 + 778 + /* Disable button detection */ 779 + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, 780 + DA7219_BUTTON_CONFIG_MASK, 0); 781 + 782 + INIT_WORK(&da7219_aad->btn_det_work, da7219_aad_btn_det_work); 783 + INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work); 784 + 785 + ret = request_threaded_irq(da7219_aad->irq, NULL, 786 + da7219_aad_irq_thread, 787 + IRQF_TRIGGER_LOW | IRQF_ONESHOT, 788 + "da7219-aad", da7219_aad); 789 + if (ret) { 790 + dev_err(codec->dev, "Failed to request IRQ: %d\n", ret); 791 + return ret; 792 + } 793 + 794 + /* Unmask AAD IRQs */ 795 + memset(mask, 0, DA7219_AAD_IRQ_REG_MAX); 796 + regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A, 797 + &mask, DA7219_AAD_IRQ_REG_MAX); 798 + 799 + return 0; 800 + } 801 + EXPORT_SYMBOL_GPL(da7219_aad_init); 802 + 803 + void da7219_aad_exit(struct snd_soc_codec *codec) 804 + { 805 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 806 + struct da7219_aad_priv *da7219_aad = da7219->aad; 807 + u8 mask[DA7219_AAD_IRQ_REG_MAX]; 808 + 809 + /* Mask off AAD IRQs */ 810 + memset(mask, DA7219_BYTE_MASK, DA7219_AAD_IRQ_REG_MAX); 811 + regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A, 812 + mask, DA7219_AAD_IRQ_REG_MAX); 813 + 814 + free_irq(da7219_aad->irq, da7219_aad); 815 + 816 + cancel_work_sync(&da7219_aad->btn_det_work); 817 + cancel_work_sync(&da7219_aad->hptest_work); 818 + } 819 + EXPORT_SYMBOL_GPL(da7219_aad_exit); 820 + 821 + MODULE_DESCRIPTION("ASoC DA7219 AAD Driver"); 822 + MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>"); 823 + MODULE_LICENSE("GPL");
+212
sound/soc/codecs/da7219-aad.h
··· 1 + /* 2 + * da7219-aad.h - DA7322 ASoC AAD Driver 3 + * 4 + * Copyright (c) 2015 Dialog Semiconductor Ltd. 5 + * 6 + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the 10 + * Free Software Foundation; either version 2 of the License, or (at your 11 + * option) any later version. 12 + */ 13 + 14 + #ifndef __DA7219_AAD_H 15 + #define __DA7219_AAD_H 16 + 17 + #include <linux/timer.h> 18 + #include <sound/soc.h> 19 + #include <sound/jack.h> 20 + #include <sound/da7219-aad.h> 21 + 22 + /* 23 + * Registers 24 + */ 25 + 26 + #define DA7219_ACCDET_STATUS_A 0xC0 27 + #define DA7219_ACCDET_STATUS_B 0xC1 28 + #define DA7219_ACCDET_IRQ_EVENT_A 0xC2 29 + #define DA7219_ACCDET_IRQ_EVENT_B 0xC3 30 + #define DA7219_ACCDET_IRQ_MASK_A 0xC4 31 + #define DA7219_ACCDET_IRQ_MASK_B 0xC5 32 + #define DA7219_ACCDET_CONFIG_1 0xC6 33 + #define DA7219_ACCDET_CONFIG_2 0xC7 34 + #define DA7219_ACCDET_CONFIG_3 0xC8 35 + #define DA7219_ACCDET_CONFIG_4 0xC9 36 + #define DA7219_ACCDET_CONFIG_5 0xCA 37 + #define DA7219_ACCDET_CONFIG_6 0xCB 38 + #define DA7219_ACCDET_CONFIG_7 0xCC 39 + #define DA7219_ACCDET_CONFIG_8 0xCD 40 + 41 + 42 + /* 43 + * Bit Fields 44 + */ 45 + 46 + /* DA7219_ACCDET_STATUS_A = 0xC0 */ 47 + #define DA7219_JACK_INSERTION_STS_SHIFT 0 48 + #define DA7219_JACK_INSERTION_STS_MASK (0x1 << 0) 49 + #define DA7219_JACK_TYPE_STS_SHIFT 1 50 + #define DA7219_JACK_TYPE_STS_MASK (0x1 << 1) 51 + #define DA7219_JACK_PIN_ORDER_STS_SHIFT 2 52 + #define DA7219_JACK_PIN_ORDER_STS_MASK (0x1 << 2) 53 + #define DA7219_MICBIAS_UP_STS_SHIFT 3 54 + #define DA7219_MICBIAS_UP_STS_MASK (0x1 << 3) 55 + 56 + /* DA7219_ACCDET_STATUS_B = 0xC1 */ 57 + #define DA7219_BUTTON_TYPE_STS_SHIFT 0 58 + #define DA7219_BUTTON_TYPE_STS_MASK (0xFF << 0) 59 + 60 + /* DA7219_ACCDET_IRQ_EVENT_A = 0xC2 */ 61 + #define DA7219_E_JACK_INSERTED_SHIFT 0 62 + #define DA7219_E_JACK_INSERTED_MASK (0x1 << 0) 63 + #define DA7219_E_JACK_REMOVED_SHIFT 1 64 + #define DA7219_E_JACK_REMOVED_MASK (0x1 << 1) 65 + #define DA7219_E_JACK_DETECT_COMPLETE_SHIFT 2 66 + #define DA7219_E_JACK_DETECT_COMPLETE_MASK (0x1 << 2) 67 + 68 + /* DA7219_ACCDET_IRQ_EVENT_B = 0xC3 */ 69 + #define DA7219_E_BUTTON_A_PRESSED_SHIFT 0 70 + #define DA7219_E_BUTTON_A_PRESSED_MASK (0x1 << 0) 71 + #define DA7219_E_BUTTON_B_PRESSED_SHIFT 1 72 + #define DA7219_E_BUTTON_B_PRESSED_MASK (0x1 << 1) 73 + #define DA7219_E_BUTTON_C_PRESSED_SHIFT 2 74 + #define DA7219_E_BUTTON_C_PRESSED_MASK (0x1 << 2) 75 + #define DA7219_E_BUTTON_D_PRESSED_SHIFT 3 76 + #define DA7219_E_BUTTON_D_PRESSED_MASK (0x1 << 3) 77 + #define DA7219_E_BUTTON_D_RELEASED_SHIFT 4 78 + #define DA7219_E_BUTTON_D_RELEASED_MASK (0x1 << 4) 79 + #define DA7219_E_BUTTON_C_RELEASED_SHIFT 5 80 + #define DA7219_E_BUTTON_C_RELEASED_MASK (0x1 << 5) 81 + #define DA7219_E_BUTTON_B_RELEASED_SHIFT 6 82 + #define DA7219_E_BUTTON_B_RELEASED_MASK (0x1 << 6) 83 + #define DA7219_E_BUTTON_A_RELEASED_SHIFT 7 84 + #define DA7219_E_BUTTON_A_RELEASED_MASK (0x1 << 7) 85 + 86 + /* DA7219_ACCDET_IRQ_MASK_A = 0xC4 */ 87 + #define DA7219_M_JACK_INSERTED_SHIFT 0 88 + #define DA7219_M_JACK_INSERTED_MASK (0x1 << 0) 89 + #define DA7219_M_JACK_REMOVED_SHIFT 1 90 + #define DA7219_M_JACK_REMOVED_MASK (0x1 << 1) 91 + #define DA7219_M_JACK_DETECT_COMPLETE_SHIFT 2 92 + #define DA7219_M_JACK_DETECT_COMPLETE_MASK (0x1 << 2) 93 + 94 + /* DA7219_ACCDET_IRQ_MASK_B = 0xC5 */ 95 + #define DA7219_M_BUTTON_A_PRESSED_SHIFT 0 96 + #define DA7219_M_BUTTON_A_PRESSED_MASK (0x1 << 0) 97 + #define DA7219_M_BUTTON_B_PRESSED_SHIFT 1 98 + #define DA7219_M_BUTTON_B_PRESSED_MASK (0x1 << 1) 99 + #define DA7219_M_BUTTON_C_PRESSED_SHIFT 2 100 + #define DA7219_M_BUTTON_C_PRESSED_MASK (0x1 << 2) 101 + #define DA7219_M_BUTTON_D_PRESSED_SHIFT 3 102 + #define DA7219_M_BUTTON_D_PRESSED_MASK (0x1 << 3) 103 + #define DA7219_M_BUTTON_D_RELEASED_SHIFT 4 104 + #define DA7219_M_BUTTON_D_RELEASED_MASK (0x1 << 4) 105 + #define DA7219_M_BUTTON_C_RELEASED_SHIFT 5 106 + #define DA7219_M_BUTTON_C_RELEASED_MASK (0x1 << 5) 107 + #define DA7219_M_BUTTON_B_RELEASED_SHIFT 6 108 + #define DA7219_M_BUTTON_B_RELEASED_MASK (0x1 << 6) 109 + #define DA7219_M_BUTTON_A_RELEASED_SHIFT 7 110 + #define DA7219_M_BUTTON_A_RELEASED_MASK (0x1 << 7) 111 + 112 + /* DA7219_ACCDET_CONFIG_1 = 0xC6 */ 113 + #define DA7219_ACCDET_EN_SHIFT 0 114 + #define DA7219_ACCDET_EN_MASK (0x1 << 0) 115 + #define DA7219_BUTTON_CONFIG_SHIFT 1 116 + #define DA7219_BUTTON_CONFIG_MASK (0x7 << 1) 117 + #define DA7219_MIC_DET_THRESH_SHIFT 4 118 + #define DA7219_MIC_DET_THRESH_MASK (0x3 << 4) 119 + #define DA7219_JACK_TYPE_DET_EN_SHIFT 6 120 + #define DA7219_JACK_TYPE_DET_EN_MASK (0x1 << 6) 121 + #define DA7219_PIN_ORDER_DET_EN_SHIFT 7 122 + #define DA7219_PIN_ORDER_DET_EN_MASK (0x1 << 7) 123 + 124 + /* DA7219_ACCDET_CONFIG_2 = 0xC7 */ 125 + #define DA7219_ACCDET_PAUSE_SHIFT 0 126 + #define DA7219_ACCDET_PAUSE_MASK (0x1 << 0) 127 + #define DA7219_JACKDET_DEBOUNCE_SHIFT 1 128 + #define DA7219_JACKDET_DEBOUNCE_MASK (0x7 << 1) 129 + #define DA7219_JACK_DETECT_RATE_SHIFT 4 130 + #define DA7219_JACK_DETECT_RATE_MASK (0x3 << 4) 131 + #define DA7219_JACKDET_REM_DEB_SHIFT 6 132 + #define DA7219_JACKDET_REM_DEB_MASK (0x3 << 6) 133 + 134 + /* DA7219_ACCDET_CONFIG_3 = 0xC8 */ 135 + #define DA7219_A_D_BUTTON_THRESH_SHIFT 0 136 + #define DA7219_A_D_BUTTON_THRESH_MASK (0xFF << 0) 137 + 138 + /* DA7219_ACCDET_CONFIG_4 = 0xC9 */ 139 + #define DA7219_D_B_BUTTON_THRESH_SHIFT 0 140 + #define DA7219_D_B_BUTTON_THRESH_MASK (0xFF << 0) 141 + 142 + /* DA7219_ACCDET_CONFIG_5 = 0xCA */ 143 + #define DA7219_B_C_BUTTON_THRESH_SHIFT 0 144 + #define DA7219_B_C_BUTTON_THRESH_MASK (0xFF << 0) 145 + 146 + /* DA7219_ACCDET_CONFIG_6 = 0xCB */ 147 + #define DA7219_C_MIC_BUTTON_THRESH_SHIFT 0 148 + #define DA7219_C_MIC_BUTTON_THRESH_MASK (0xFF << 0) 149 + 150 + /* DA7219_ACCDET_CONFIG_7 = 0xCC */ 151 + #define DA7219_BUTTON_AVERAGE_SHIFT 0 152 + #define DA7219_BUTTON_AVERAGE_MASK (0x3 << 0) 153 + #define DA7219_ADC_1_BIT_REPEAT_SHIFT 2 154 + #define DA7219_ADC_1_BIT_REPEAT_MASK (0x3 << 2) 155 + #define DA7219_PIN_ORDER_FORCE_SHIFT 4 156 + #define DA7219_PIN_ORDER_FORCE_MASK (0x1 << 4) 157 + #define DA7219_JACK_TYPE_FORCE_SHIFT 5 158 + #define DA7219_JACK_TYPE_FORCE_MASK (0x1 << 5) 159 + 160 + /* DA7219_ACCDET_CONFIG_8 = 0xCD */ 161 + #define DA7219_HPTEST_EN_SHIFT 0 162 + #define DA7219_HPTEST_EN_MASK (0x1 << 0) 163 + #define DA7219_HPTEST_RES_SEL_SHIFT 1 164 + #define DA7219_HPTEST_RES_SEL_MASK (0x3 << 1) 165 + #define DA7219_HPTEST_RES_SEL_1KOHMS (0x0 << 1) 166 + #define DA7219_HPTEST_COMP_SHIFT 4 167 + #define DA7219_HPTEST_COMP_MASK (0x1 << 4) 168 + 169 + 170 + #define DA7219_AAD_MAX_BUTTONS 4 171 + #define DA7219_AAD_REPORT_ALL_MASK (SND_JACK_MECHANICAL | \ 172 + SND_JACK_HEADSET | SND_JACK_LINEOUT | \ 173 + SND_JACK_BTN_0 | SND_JACK_BTN_1 | \ 174 + SND_JACK_BTN_2 | SND_JACK_BTN_3) 175 + 176 + #define DA7219_AAD_MICBIAS_CHK_DELAY 10 177 + #define DA7219_AAD_MICBIAS_CHK_RETRIES 5 178 + 179 + #define DA7219_AAD_HPTEST_RAMP_FREQ 0x28 180 + #define DA7219_AAD_HPTEST_PERIOD 65 181 + 182 + enum da7219_aad_event_regs { 183 + DA7219_AAD_IRQ_REG_A = 0, 184 + DA7219_AAD_IRQ_REG_B, 185 + DA7219_AAD_IRQ_REG_MAX, 186 + }; 187 + 188 + /* Private data */ 189 + struct da7219_aad_priv { 190 + struct snd_soc_codec *codec; 191 + int irq; 192 + 193 + u8 micbias_pulse_lvl; 194 + u32 micbias_pulse_time; 195 + 196 + u8 btn_cfg; 197 + 198 + struct work_struct btn_det_work; 199 + struct work_struct hptest_work; 200 + 201 + struct snd_soc_jack *jack; 202 + bool jack_inserted; 203 + }; 204 + 205 + /* AAD control */ 206 + void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack); 207 + 208 + /* Init/Exit */ 209 + int da7219_aad_init(struct snd_soc_codec *codec); 210 + void da7219_aad_exit(struct snd_soc_codec *codec); 211 + 212 + #endif /* __DA7219_AAD_H */
+1940
sound/soc/codecs/da7219.c
··· 1 + /* 2 + * da7219.c - DA7219 ALSA SoC Codec Driver 3 + * 4 + * Copyright (c) 2015 Dialog Semiconductor 5 + * 6 + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the 10 + * Free Software Foundation; either version 2 of the License, or (at your 11 + * option) any later version. 12 + */ 13 + 14 + #include <linux/clk.h> 15 + #include <linux/i2c.h> 16 + #include <linux/of_device.h> 17 + #include <linux/regmap.h> 18 + #include <linux/slab.h> 19 + #include <linux/pm.h> 20 + #include <linux/module.h> 21 + #include <linux/delay.h> 22 + #include <linux/regulator/consumer.h> 23 + #include <sound/pcm.h> 24 + #include <sound/pcm_params.h> 25 + #include <sound/soc.h> 26 + #include <sound/soc-dapm.h> 27 + #include <sound/initval.h> 28 + #include <sound/tlv.h> 29 + #include <asm/div64.h> 30 + 31 + #include <sound/da7219.h> 32 + #include "da7219.h" 33 + #include "da7219-aad.h" 34 + 35 + 36 + /* 37 + * TLVs and Enums 38 + */ 39 + 40 + /* Input TLVs */ 41 + static const DECLARE_TLV_DB_SCALE(da7219_mic_gain_tlv, -600, 600, 0); 42 + static const DECLARE_TLV_DB_SCALE(da7219_mixin_gain_tlv, -450, 150, 0); 43 + static const DECLARE_TLV_DB_SCALE(da7219_adc_dig_gain_tlv, -8325, 75, 0); 44 + static const DECLARE_TLV_DB_SCALE(da7219_alc_threshold_tlv, -9450, 150, 0); 45 + static const DECLARE_TLV_DB_SCALE(da7219_alc_gain_tlv, 0, 600, 0); 46 + static const DECLARE_TLV_DB_SCALE(da7219_alc_ana_gain_tlv, 0, 600, 0); 47 + static const DECLARE_TLV_DB_SCALE(da7219_sidetone_gain_tlv, -4200, 300, 0); 48 + static const DECLARE_TLV_DB_SCALE(da7219_tonegen_gain_tlv, -4500, 300, 0); 49 + 50 + /* Output TLVs */ 51 + static const DECLARE_TLV_DB_SCALE(da7219_dac_eq_band_tlv, -1050, 150, 0); 52 + 53 + static const DECLARE_TLV_DB_RANGE(da7219_dac_dig_gain_tlv, 54 + 0x0, 0x07, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), 55 + /* -77.25dB to 12dB */ 56 + 0x08, 0x7f, TLV_DB_SCALE_ITEM(-7725, 75, 0) 57 + ); 58 + 59 + static const DECLARE_TLV_DB_SCALE(da7219_dac_ng_threshold_tlv, -10200, 600, 0); 60 + static const DECLARE_TLV_DB_SCALE(da7219_hp_gain_tlv, -5700, 100, 0); 61 + 62 + /* Input Enums */ 63 + static const char * const da7219_alc_attack_rate_txt[] = { 64 + "7.33/fs", "14.66/fs", "29.32/fs", "58.64/fs", "117.3/fs", "234.6/fs", 65 + "469.1/fs", "938.2/fs", "1876/fs", "3753/fs", "7506/fs", "15012/fs", 66 + "30024/fs" 67 + }; 68 + 69 + static const struct soc_enum da7219_alc_attack_rate = 70 + SOC_ENUM_SINGLE(DA7219_ALC_CTRL2, DA7219_ALC_ATTACK_SHIFT, 71 + DA7219_ALC_ATTACK_MAX, da7219_alc_attack_rate_txt); 72 + 73 + static const char * const da7219_alc_release_rate_txt[] = { 74 + "28.66/fs", "57.33/fs", "114.6/fs", "229.3/fs", "458.6/fs", "917.1/fs", 75 + "1834/fs", "3668/fs", "7337/fs", "14674/fs", "29348/fs" 76 + }; 77 + 78 + static const struct soc_enum da7219_alc_release_rate = 79 + SOC_ENUM_SINGLE(DA7219_ALC_CTRL2, DA7219_ALC_RELEASE_SHIFT, 80 + DA7219_ALC_RELEASE_MAX, da7219_alc_release_rate_txt); 81 + 82 + static const char * const da7219_alc_hold_time_txt[] = { 83 + "62/fs", "124/fs", "248/fs", "496/fs", "992/fs", "1984/fs", "3968/fs", 84 + "7936/fs", "15872/fs", "31744/fs", "63488/fs", "126976/fs", 85 + "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" 86 + }; 87 + 88 + static const struct soc_enum da7219_alc_hold_time = 89 + SOC_ENUM_SINGLE(DA7219_ALC_CTRL3, DA7219_ALC_HOLD_SHIFT, 90 + DA7219_ALC_HOLD_MAX, da7219_alc_hold_time_txt); 91 + 92 + static const char * const da7219_alc_env_rate_txt[] = { 93 + "1/4", "1/16", "1/256", "1/65536" 94 + }; 95 + 96 + static const struct soc_enum da7219_alc_env_attack_rate = 97 + SOC_ENUM_SINGLE(DA7219_ALC_CTRL3, DA7219_ALC_INTEG_ATTACK_SHIFT, 98 + DA7219_ALC_INTEG_MAX, da7219_alc_env_rate_txt); 99 + 100 + static const struct soc_enum da7219_alc_env_release_rate = 101 + SOC_ENUM_SINGLE(DA7219_ALC_CTRL3, DA7219_ALC_INTEG_RELEASE_SHIFT, 102 + DA7219_ALC_INTEG_MAX, da7219_alc_env_rate_txt); 103 + 104 + static const char * const da7219_alc_anticlip_step_txt[] = { 105 + "0.034dB/fs", "0.068dB/fs", "0.136dB/fs", "0.272dB/fs" 106 + }; 107 + 108 + static const struct soc_enum da7219_alc_anticlip_step = 109 + SOC_ENUM_SINGLE(DA7219_ALC_ANTICLIP_CTRL, 110 + DA7219_ALC_ANTICLIP_STEP_SHIFT, 111 + DA7219_ALC_ANTICLIP_STEP_MAX, 112 + da7219_alc_anticlip_step_txt); 113 + 114 + /* Input/Output Enums */ 115 + static const char * const da7219_gain_ramp_rate_txt[] = { 116 + "Nominal Rate * 8", "Nominal Rate", "Nominal Rate / 8", 117 + "Nominal Rate / 16" 118 + }; 119 + 120 + static const struct soc_enum da7219_gain_ramp_rate = 121 + SOC_ENUM_SINGLE(DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_SHIFT, 122 + DA7219_GAIN_RAMP_RATE_MAX, da7219_gain_ramp_rate_txt); 123 + 124 + static const char * const da7219_hpf_mode_txt[] = { 125 + "Disabled", "Audio", "Voice" 126 + }; 127 + 128 + static const unsigned int da7219_hpf_mode_val[] = { 129 + DA7219_HPF_DISABLED, DA7219_HPF_AUDIO_EN, DA7219_HPF_VOICE_EN, 130 + }; 131 + 132 + static const struct soc_enum da7219_adc_hpf_mode = 133 + SOC_VALUE_ENUM_SINGLE(DA7219_ADC_FILTERS1, DA7219_HPF_MODE_SHIFT, 134 + DA7219_HPF_MODE_MASK, DA7219_HPF_MODE_MAX, 135 + da7219_hpf_mode_txt, da7219_hpf_mode_val); 136 + 137 + static const struct soc_enum da7219_dac_hpf_mode = 138 + SOC_VALUE_ENUM_SINGLE(DA7219_DAC_FILTERS1, DA7219_HPF_MODE_SHIFT, 139 + DA7219_HPF_MODE_MASK, DA7219_HPF_MODE_MAX, 140 + da7219_hpf_mode_txt, da7219_hpf_mode_val); 141 + 142 + static const char * const da7219_audio_hpf_corner_txt[] = { 143 + "2Hz", "4Hz", "8Hz", "16Hz" 144 + }; 145 + 146 + static const struct soc_enum da7219_adc_audio_hpf_corner = 147 + SOC_ENUM_SINGLE(DA7219_ADC_FILTERS1, 148 + DA7219_ADC_AUDIO_HPF_CORNER_SHIFT, 149 + DA7219_AUDIO_HPF_CORNER_MAX, 150 + da7219_audio_hpf_corner_txt); 151 + 152 + static const struct soc_enum da7219_dac_audio_hpf_corner = 153 + SOC_ENUM_SINGLE(DA7219_DAC_FILTERS1, 154 + DA7219_DAC_AUDIO_HPF_CORNER_SHIFT, 155 + DA7219_AUDIO_HPF_CORNER_MAX, 156 + da7219_audio_hpf_corner_txt); 157 + 158 + static const char * const da7219_voice_hpf_corner_txt[] = { 159 + "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" 160 + }; 161 + 162 + static const struct soc_enum da7219_adc_voice_hpf_corner = 163 + SOC_ENUM_SINGLE(DA7219_ADC_FILTERS1, 164 + DA7219_ADC_VOICE_HPF_CORNER_SHIFT, 165 + DA7219_VOICE_HPF_CORNER_MAX, 166 + da7219_voice_hpf_corner_txt); 167 + 168 + static const struct soc_enum da7219_dac_voice_hpf_corner = 169 + SOC_ENUM_SINGLE(DA7219_DAC_FILTERS1, 170 + DA7219_DAC_VOICE_HPF_CORNER_SHIFT, 171 + DA7219_VOICE_HPF_CORNER_MAX, 172 + da7219_voice_hpf_corner_txt); 173 + 174 + static const char * const da7219_tonegen_dtmf_key_txt[] = { 175 + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", 176 + "*", "#" 177 + }; 178 + 179 + static const struct soc_enum da7219_tonegen_dtmf_key = 180 + SOC_ENUM_SINGLE(DA7219_TONE_GEN_CFG1, DA7219_DTMF_REG_SHIFT, 181 + DA7219_DTMF_REG_MAX, da7219_tonegen_dtmf_key_txt); 182 + 183 + static const char * const da7219_tonegen_swg_sel_txt[] = { 184 + "Sum", "SWG1", "SWG2", "SWG1_1-Cos" 185 + }; 186 + 187 + static const struct soc_enum da7219_tonegen_swg_sel = 188 + SOC_ENUM_SINGLE(DA7219_TONE_GEN_CFG2, DA7219_SWG_SEL_SHIFT, 189 + DA7219_SWG_SEL_MAX, da7219_tonegen_swg_sel_txt); 190 + 191 + /* Output Enums */ 192 + static const char * const da7219_dac_softmute_rate_txt[] = { 193 + "1 Sample", "2 Samples", "4 Samples", "8 Samples", "16 Samples", 194 + "32 Samples", "64 Samples" 195 + }; 196 + 197 + static const struct soc_enum da7219_dac_softmute_rate = 198 + SOC_ENUM_SINGLE(DA7219_DAC_FILTERS5, DA7219_DAC_SOFTMUTE_RATE_SHIFT, 199 + DA7219_DAC_SOFTMUTE_RATE_MAX, 200 + da7219_dac_softmute_rate_txt); 201 + 202 + static const char * const da7219_dac_ng_setup_time_txt[] = { 203 + "256 Samples", "512 Samples", "1024 Samples", "2048 Samples" 204 + }; 205 + 206 + static const struct soc_enum da7219_dac_ng_setup_time = 207 + SOC_ENUM_SINGLE(DA7219_DAC_NG_SETUP_TIME, 208 + DA7219_DAC_NG_SETUP_TIME_SHIFT, 209 + DA7219_DAC_NG_SETUP_TIME_MAX, 210 + da7219_dac_ng_setup_time_txt); 211 + 212 + static const char * const da7219_dac_ng_rampup_txt[] = { 213 + "0.22ms/dB", "0.0138ms/dB" 214 + }; 215 + 216 + static const struct soc_enum da7219_dac_ng_rampup_rate = 217 + SOC_ENUM_SINGLE(DA7219_DAC_NG_SETUP_TIME, 218 + DA7219_DAC_NG_RAMPUP_RATE_SHIFT, 219 + DA7219_DAC_NG_RAMP_RATE_MAX, 220 + da7219_dac_ng_rampup_txt); 221 + 222 + static const char * const da7219_dac_ng_rampdown_txt[] = { 223 + "0.88ms/dB", "14.08ms/dB" 224 + }; 225 + 226 + static const struct soc_enum da7219_dac_ng_rampdown_rate = 227 + SOC_ENUM_SINGLE(DA7219_DAC_NG_SETUP_TIME, 228 + DA7219_DAC_NG_RAMPDN_RATE_SHIFT, 229 + DA7219_DAC_NG_RAMP_RATE_MAX, 230 + da7219_dac_ng_rampdown_txt); 231 + 232 + 233 + static const char * const da7219_cp_track_mode_txt[] = { 234 + "Largest Volume", "DAC Volume", "Signal Magnitude" 235 + }; 236 + 237 + static const unsigned int da7219_cp_track_mode_val[] = { 238 + DA7219_CP_MCHANGE_LARGEST_VOL, DA7219_CP_MCHANGE_DAC_VOL, 239 + DA7219_CP_MCHANGE_SIG_MAG 240 + }; 241 + 242 + static const struct soc_enum da7219_cp_track_mode = 243 + SOC_VALUE_ENUM_SINGLE(DA7219_CP_CTRL, DA7219_CP_MCHANGE_SHIFT, 244 + DA7219_CP_MCHANGE_REL_MASK, DA7219_CP_MCHANGE_MAX, 245 + da7219_cp_track_mode_txt, 246 + da7219_cp_track_mode_val); 247 + 248 + 249 + /* 250 + * Control Functions 251 + */ 252 + 253 + /* Locked Kcontrol calls */ 254 + static int da7219_volsw_locked_get(struct snd_kcontrol *kcontrol, 255 + struct snd_ctl_elem_value *ucontrol) 256 + { 257 + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 258 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 259 + int ret; 260 + 261 + mutex_lock(&da7219->lock); 262 + ret = snd_soc_get_volsw(kcontrol, ucontrol); 263 + mutex_unlock(&da7219->lock); 264 + 265 + return ret; 266 + } 267 + 268 + static int da7219_volsw_locked_put(struct snd_kcontrol *kcontrol, 269 + struct snd_ctl_elem_value *ucontrol) 270 + { 271 + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 272 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 273 + int ret; 274 + 275 + mutex_lock(&da7219->lock); 276 + ret = snd_soc_put_volsw(kcontrol, ucontrol); 277 + mutex_unlock(&da7219->lock); 278 + 279 + return ret; 280 + } 281 + 282 + static int da7219_enum_locked_get(struct snd_kcontrol *kcontrol, 283 + struct snd_ctl_elem_value *ucontrol) 284 + { 285 + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 286 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 287 + int ret; 288 + 289 + mutex_lock(&da7219->lock); 290 + ret = snd_soc_get_enum_double(kcontrol, ucontrol); 291 + mutex_unlock(&da7219->lock); 292 + 293 + return ret; 294 + } 295 + 296 + static int da7219_enum_locked_put(struct snd_kcontrol *kcontrol, 297 + struct snd_ctl_elem_value *ucontrol) 298 + { 299 + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 300 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 301 + int ret; 302 + 303 + mutex_lock(&da7219->lock); 304 + ret = snd_soc_put_enum_double(kcontrol, ucontrol); 305 + mutex_unlock(&da7219->lock); 306 + 307 + return ret; 308 + } 309 + 310 + /* ALC */ 311 + static void da7219_alc_calib(struct snd_soc_codec *codec) 312 + { 313 + u8 mic_ctrl, mixin_ctrl, adc_ctrl, calib_ctrl; 314 + 315 + /* Save current state of mic control register */ 316 + mic_ctrl = snd_soc_read(codec, DA7219_MIC_1_CTRL); 317 + 318 + /* Save current state of input mixer control register */ 319 + mixin_ctrl = snd_soc_read(codec, DA7219_MIXIN_L_CTRL); 320 + 321 + /* Save current state of input ADC control register */ 322 + adc_ctrl = snd_soc_read(codec, DA7219_ADC_L_CTRL); 323 + 324 + /* Enable then Mute MIC PGAs */ 325 + snd_soc_update_bits(codec, DA7219_MIC_1_CTRL, DA7219_MIC_1_AMP_EN_MASK, 326 + DA7219_MIC_1_AMP_EN_MASK); 327 + snd_soc_update_bits(codec, DA7219_MIC_1_CTRL, 328 + DA7219_MIC_1_AMP_MUTE_EN_MASK, 329 + DA7219_MIC_1_AMP_MUTE_EN_MASK); 330 + 331 + /* Enable input mixers unmuted */ 332 + snd_soc_update_bits(codec, DA7219_MIXIN_L_CTRL, 333 + DA7219_MIXIN_L_AMP_EN_MASK | 334 + DA7219_MIXIN_L_AMP_MUTE_EN_MASK, 335 + DA7219_MIXIN_L_AMP_EN_MASK); 336 + 337 + /* Enable input filters unmuted */ 338 + snd_soc_update_bits(codec, DA7219_ADC_L_CTRL, 339 + DA7219_ADC_L_MUTE_EN_MASK | DA7219_ADC_L_EN_MASK, 340 + DA7219_ADC_L_EN_MASK); 341 + 342 + /* Perform auto calibration */ 343 + snd_soc_update_bits(codec, DA7219_ALC_CTRL1, 344 + DA7219_ALC_AUTO_CALIB_EN_MASK, 345 + DA7219_ALC_AUTO_CALIB_EN_MASK); 346 + do { 347 + calib_ctrl = snd_soc_read(codec, DA7219_ALC_CTRL1); 348 + } while (calib_ctrl & DA7219_ALC_AUTO_CALIB_EN_MASK); 349 + 350 + /* If auto calibration fails, disable DC offset, hybrid ALC */ 351 + if (calib_ctrl & DA7219_ALC_CALIB_OVERFLOW_MASK) { 352 + dev_warn(codec->dev, 353 + "ALC auto calibration failed with overflow\n"); 354 + snd_soc_update_bits(codec, DA7219_ALC_CTRL1, 355 + DA7219_ALC_OFFSET_EN_MASK | 356 + DA7219_ALC_SYNC_MODE_MASK, 0); 357 + } else { 358 + /* Enable DC offset cancellation, hybrid mode */ 359 + snd_soc_update_bits(codec, DA7219_ALC_CTRL1, 360 + DA7219_ALC_OFFSET_EN_MASK | 361 + DA7219_ALC_SYNC_MODE_MASK, 362 + DA7219_ALC_OFFSET_EN_MASK | 363 + DA7219_ALC_SYNC_MODE_MASK); 364 + } 365 + 366 + /* Restore input filter control register to original state */ 367 + snd_soc_write(codec, DA7219_ADC_L_CTRL, adc_ctrl); 368 + 369 + /* Restore input mixer control registers to original state */ 370 + snd_soc_write(codec, DA7219_MIXIN_L_CTRL, mixin_ctrl); 371 + 372 + /* Restore MIC control registers to original states */ 373 + snd_soc_write(codec, DA7219_MIC_1_CTRL, mic_ctrl); 374 + } 375 + 376 + static int da7219_mixin_gain_put(struct snd_kcontrol *kcontrol, 377 + struct snd_ctl_elem_value *ucontrol) 378 + { 379 + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 380 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 381 + int ret; 382 + 383 + ret = snd_soc_put_volsw(kcontrol, ucontrol); 384 + 385 + /* 386 + * If ALC in operation and value of control has been updated, 387 + * make sure calibrated offsets are updated. 388 + */ 389 + if ((ret == 1) && (da7219->alc_en)) 390 + da7219_alc_calib(codec); 391 + 392 + return ret; 393 + } 394 + 395 + static int da7219_alc_sw_put(struct snd_kcontrol *kcontrol, 396 + struct snd_ctl_elem_value *ucontrol) 397 + { 398 + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 399 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 400 + 401 + 402 + /* Force ALC offset calibration if enabling ALC */ 403 + if ((ucontrol->value.integer.value[0]) && (!da7219->alc_en)) { 404 + da7219_alc_calib(codec); 405 + da7219->alc_en = false; 406 + } else { 407 + da7219->alc_en = false; 408 + } 409 + 410 + return snd_soc_put_volsw(kcontrol, ucontrol); 411 + } 412 + 413 + /* ToneGen */ 414 + static int da7219_tonegen_freq_get(struct snd_kcontrol *kcontrol, 415 + struct snd_ctl_elem_value *ucontrol) 416 + { 417 + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 418 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 419 + struct soc_mixer_control *mixer_ctrl = 420 + (struct soc_mixer_control *) kcontrol->private_value; 421 + unsigned int reg = mixer_ctrl->reg; 422 + u16 val; 423 + int ret; 424 + 425 + mutex_lock(&da7219->lock); 426 + ret = regmap_raw_read(da7219->regmap, reg, &val, sizeof(val)); 427 + mutex_unlock(&da7219->lock); 428 + 429 + if (ret) 430 + return ret; 431 + 432 + /* 433 + * Frequency value spans two 8-bit registers, lower then upper byte. 434 + * Therefore we need to convert to host endianness here. 435 + */ 436 + ucontrol->value.integer.value[0] = le16_to_cpu(val); 437 + 438 + return 0; 439 + } 440 + 441 + static int da7219_tonegen_freq_put(struct snd_kcontrol *kcontrol, 442 + struct snd_ctl_elem_value *ucontrol) 443 + { 444 + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); 445 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 446 + struct soc_mixer_control *mixer_ctrl = 447 + (struct soc_mixer_control *) kcontrol->private_value; 448 + unsigned int reg = mixer_ctrl->reg; 449 + u16 val; 450 + int ret; 451 + 452 + /* 453 + * Frequency value spans two 8-bit registers, lower then upper byte. 454 + * Therefore we need to convert to little endian here to align with 455 + * HW registers. 456 + */ 457 + val = cpu_to_le16(ucontrol->value.integer.value[0]); 458 + 459 + mutex_lock(&da7219->lock); 460 + ret = regmap_raw_write(da7219->regmap, reg, &val, sizeof(val)); 461 + mutex_unlock(&da7219->lock); 462 + 463 + return ret; 464 + } 465 + 466 + 467 + /* 468 + * KControls 469 + */ 470 + 471 + static const struct snd_kcontrol_new da7219_snd_controls[] = { 472 + /* Mics */ 473 + SOC_SINGLE_TLV("Mic Volume", DA7219_MIC_1_GAIN, 474 + DA7219_MIC_1_AMP_GAIN_SHIFT, DA7219_MIC_1_AMP_GAIN_MAX, 475 + DA7219_NO_INVERT, da7219_mic_gain_tlv), 476 + SOC_SINGLE("Mic Switch", DA7219_MIC_1_CTRL, 477 + DA7219_MIC_1_AMP_MUTE_EN_SHIFT, DA7219_SWITCH_EN_MAX, 478 + DA7219_INVERT), 479 + 480 + /* Mixer Input */ 481 + SOC_SINGLE_EXT_TLV("Mixin Volume", DA7219_MIXIN_L_GAIN, 482 + DA7219_MIXIN_L_AMP_GAIN_SHIFT, 483 + DA7219_MIXIN_L_AMP_GAIN_MAX, DA7219_NO_INVERT, 484 + snd_soc_get_volsw, da7219_mixin_gain_put, 485 + da7219_mixin_gain_tlv), 486 + SOC_SINGLE("Mixin Switch", DA7219_MIXIN_L_CTRL, 487 + DA7219_MIXIN_L_AMP_MUTE_EN_SHIFT, DA7219_SWITCH_EN_MAX, 488 + DA7219_INVERT), 489 + SOC_SINGLE("Mixin Gain Ramp Switch", DA7219_MIXIN_L_CTRL, 490 + DA7219_MIXIN_L_AMP_RAMP_EN_SHIFT, DA7219_SWITCH_EN_MAX, 491 + DA7219_NO_INVERT), 492 + SOC_SINGLE("Mixin ZC Gain Switch", DA7219_MIXIN_L_CTRL, 493 + DA7219_MIXIN_L_AMP_ZC_EN_SHIFT, DA7219_SWITCH_EN_MAX, 494 + DA7219_NO_INVERT), 495 + 496 + /* ADC */ 497 + SOC_SINGLE_TLV("Capture Digital Volume", DA7219_ADC_L_GAIN, 498 + DA7219_ADC_L_DIGITAL_GAIN_SHIFT, 499 + DA7219_ADC_L_DIGITAL_GAIN_MAX, DA7219_NO_INVERT, 500 + da7219_adc_dig_gain_tlv), 501 + SOC_SINGLE("Capture Digital Switch", DA7219_ADC_L_CTRL, 502 + DA7219_ADC_L_MUTE_EN_SHIFT, DA7219_SWITCH_EN_MAX, 503 + DA7219_INVERT), 504 + SOC_SINGLE("Capture Digital Gain Ramp Switch", DA7219_ADC_L_CTRL, 505 + DA7219_ADC_L_RAMP_EN_SHIFT, DA7219_SWITCH_EN_MAX, 506 + DA7219_NO_INVERT), 507 + 508 + /* ALC */ 509 + SOC_ENUM("ALC Attack Rate", da7219_alc_attack_rate), 510 + SOC_ENUM("ALC Release Rate", da7219_alc_release_rate), 511 + SOC_ENUM("ALC Hold Time", da7219_alc_hold_time), 512 + SOC_ENUM("ALC Envelope Attack Rate", da7219_alc_env_attack_rate), 513 + SOC_ENUM("ALC Envelope Release Rate", da7219_alc_env_release_rate), 514 + SOC_SINGLE_TLV("ALC Noise Threshold", DA7219_ALC_NOISE, 515 + DA7219_ALC_NOISE_SHIFT, DA7219_ALC_THRESHOLD_MAX, 516 + DA7219_INVERT, da7219_alc_threshold_tlv), 517 + SOC_SINGLE_TLV("ALC Min Threshold", DA7219_ALC_TARGET_MIN, 518 + DA7219_ALC_THRESHOLD_MIN_SHIFT, DA7219_ALC_THRESHOLD_MAX, 519 + DA7219_INVERT, da7219_alc_threshold_tlv), 520 + SOC_SINGLE_TLV("ALC Max Threshold", DA7219_ALC_TARGET_MAX, 521 + DA7219_ALC_THRESHOLD_MAX_SHIFT, DA7219_ALC_THRESHOLD_MAX, 522 + DA7219_INVERT, da7219_alc_threshold_tlv), 523 + SOC_SINGLE_TLV("ALC Max Attenuation", DA7219_ALC_GAIN_LIMITS, 524 + DA7219_ALC_ATTEN_MAX_SHIFT, DA7219_ALC_ATTEN_GAIN_MAX, 525 + DA7219_NO_INVERT, da7219_alc_gain_tlv), 526 + SOC_SINGLE_TLV("ALC Max Volume", DA7219_ALC_GAIN_LIMITS, 527 + DA7219_ALC_GAIN_MAX_SHIFT, DA7219_ALC_ATTEN_GAIN_MAX, 528 + DA7219_NO_INVERT, da7219_alc_gain_tlv), 529 + SOC_SINGLE_RANGE_TLV("ALC Min Analog Volume", DA7219_ALC_ANA_GAIN_LIMITS, 530 + DA7219_ALC_ANA_GAIN_MIN_SHIFT, 531 + DA7219_ALC_ANA_GAIN_MIN, DA7219_ALC_ANA_GAIN_MAX, 532 + DA7219_NO_INVERT, da7219_alc_ana_gain_tlv), 533 + SOC_SINGLE_RANGE_TLV("ALC Max Analog Volume", DA7219_ALC_ANA_GAIN_LIMITS, 534 + DA7219_ALC_ANA_GAIN_MAX_SHIFT, 535 + DA7219_ALC_ANA_GAIN_MIN, DA7219_ALC_ANA_GAIN_MAX, 536 + DA7219_NO_INVERT, da7219_alc_ana_gain_tlv), 537 + SOC_ENUM("ALC Anticlip Step", da7219_alc_anticlip_step), 538 + SOC_SINGLE("ALC Anticlip Switch", DA7219_ALC_ANTICLIP_CTRL, 539 + DA7219_ALC_ANTIPCLIP_EN_SHIFT, DA7219_SWITCH_EN_MAX, 540 + DA7219_NO_INVERT), 541 + SOC_SINGLE_EXT("ALC Switch", DA7219_ALC_CTRL1, DA7219_ALC_EN_SHIFT, 542 + DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT, 543 + snd_soc_get_volsw, da7219_alc_sw_put), 544 + 545 + /* Input High-Pass Filters */ 546 + SOC_ENUM("ADC HPF Mode", da7219_adc_hpf_mode), 547 + SOC_ENUM("ADC HPF Corner Audio", da7219_adc_audio_hpf_corner), 548 + SOC_ENUM("ADC HPF Corner Voice", da7219_adc_voice_hpf_corner), 549 + 550 + /* Sidetone Filter */ 551 + SOC_SINGLE_TLV("Sidetone Volume", DA7219_SIDETONE_GAIN, 552 + DA7219_SIDETONE_GAIN_SHIFT, DA7219_SIDETONE_GAIN_MAX, 553 + DA7219_NO_INVERT, da7219_sidetone_gain_tlv), 554 + SOC_SINGLE("Sidetone Switch", DA7219_SIDETONE_CTRL, 555 + DA7219_SIDETONE_MUTE_EN_SHIFT, DA7219_SWITCH_EN_MAX, 556 + DA7219_INVERT), 557 + 558 + /* Tone Generator */ 559 + SOC_SINGLE_EXT_TLV("ToneGen Volume", DA7219_TONE_GEN_CFG2, 560 + DA7219_TONE_GEN_GAIN_SHIFT, DA7219_TONE_GEN_GAIN_MAX, 561 + DA7219_NO_INVERT, da7219_volsw_locked_get, 562 + da7219_volsw_locked_put, da7219_tonegen_gain_tlv), 563 + SOC_ENUM_EXT("ToneGen DTMF Key", da7219_tonegen_dtmf_key, 564 + da7219_enum_locked_get, da7219_enum_locked_put), 565 + SOC_SINGLE_EXT("ToneGen DTMF Switch", DA7219_TONE_GEN_CFG1, 566 + DA7219_DTMF_EN_SHIFT, DA7219_SWITCH_EN_MAX, 567 + DA7219_NO_INVERT, da7219_volsw_locked_get, 568 + da7219_volsw_locked_put), 569 + SOC_ENUM_EXT("ToneGen Sinewave Gen Type", da7219_tonegen_swg_sel, 570 + da7219_enum_locked_get, da7219_enum_locked_put), 571 + SOC_SINGLE_EXT("ToneGen Sinewave1 Freq", DA7219_TONE_GEN_FREQ1_L, 572 + DA7219_FREQ1_L_SHIFT, DA7219_FREQ_MAX, DA7219_NO_INVERT, 573 + da7219_tonegen_freq_get, da7219_tonegen_freq_put), 574 + SOC_SINGLE_EXT("ToneGen Sinewave2 Freq", DA7219_TONE_GEN_FREQ2_L, 575 + DA7219_FREQ2_L_SHIFT, DA7219_FREQ_MAX, DA7219_NO_INVERT, 576 + da7219_tonegen_freq_get, da7219_tonegen_freq_put), 577 + SOC_SINGLE_EXT("ToneGen On Time", DA7219_TONE_GEN_ON_PER, 578 + DA7219_BEEP_ON_PER_SHIFT, DA7219_BEEP_ON_OFF_MAX, 579 + DA7219_NO_INVERT, da7219_volsw_locked_get, 580 + da7219_volsw_locked_put), 581 + SOC_SINGLE("ToneGen Off Time", DA7219_TONE_GEN_OFF_PER, 582 + DA7219_BEEP_OFF_PER_SHIFT, DA7219_BEEP_ON_OFF_MAX, 583 + DA7219_NO_INVERT), 584 + 585 + /* Gain ramping */ 586 + SOC_ENUM("Gain Ramp Rate", da7219_gain_ramp_rate), 587 + 588 + /* DAC High-Pass Filter */ 589 + SOC_ENUM_EXT("DAC HPF Mode", da7219_dac_hpf_mode, 590 + da7219_enum_locked_get, da7219_enum_locked_put), 591 + SOC_ENUM("DAC HPF Corner Audio", da7219_dac_audio_hpf_corner), 592 + SOC_ENUM("DAC HPF Corner Voice", da7219_dac_voice_hpf_corner), 593 + 594 + /* DAC 5-Band Equaliser */ 595 + SOC_SINGLE_TLV("DAC EQ Band1 Volume", DA7219_DAC_FILTERS2, 596 + DA7219_DAC_EQ_BAND1_SHIFT, DA7219_DAC_EQ_BAND_MAX, 597 + DA7219_NO_INVERT, da7219_dac_eq_band_tlv), 598 + SOC_SINGLE_TLV("DAC EQ Band2 Volume", DA7219_DAC_FILTERS2, 599 + DA7219_DAC_EQ_BAND2_SHIFT, DA7219_DAC_EQ_BAND_MAX, 600 + DA7219_NO_INVERT, da7219_dac_eq_band_tlv), 601 + SOC_SINGLE_TLV("DAC EQ Band3 Volume", DA7219_DAC_FILTERS3, 602 + DA7219_DAC_EQ_BAND3_SHIFT, DA7219_DAC_EQ_BAND_MAX, 603 + DA7219_NO_INVERT, da7219_dac_eq_band_tlv), 604 + SOC_SINGLE_TLV("DAC EQ Band4 Volume", DA7219_DAC_FILTERS3, 605 + DA7219_DAC_EQ_BAND4_SHIFT, DA7219_DAC_EQ_BAND_MAX, 606 + DA7219_NO_INVERT, da7219_dac_eq_band_tlv), 607 + SOC_SINGLE_TLV("DAC EQ Band5 Volume", DA7219_DAC_FILTERS4, 608 + DA7219_DAC_EQ_BAND5_SHIFT, DA7219_DAC_EQ_BAND_MAX, 609 + DA7219_NO_INVERT, da7219_dac_eq_band_tlv), 610 + SOC_SINGLE_EXT("DAC EQ Switch", DA7219_DAC_FILTERS4, 611 + DA7219_DAC_EQ_EN_SHIFT, DA7219_SWITCH_EN_MAX, 612 + DA7219_NO_INVERT, da7219_volsw_locked_get, 613 + da7219_volsw_locked_put), 614 + 615 + /* DAC Softmute */ 616 + SOC_ENUM("DAC Soft Mute Rate", da7219_dac_softmute_rate), 617 + SOC_SINGLE_EXT("DAC Soft Mute Switch", DA7219_DAC_FILTERS5, 618 + DA7219_DAC_SOFTMUTE_EN_SHIFT, DA7219_SWITCH_EN_MAX, 619 + DA7219_NO_INVERT, da7219_volsw_locked_get, 620 + da7219_volsw_locked_put), 621 + 622 + /* DAC Noise Gate */ 623 + SOC_ENUM("DAC NG Setup Time", da7219_dac_ng_setup_time), 624 + SOC_ENUM("DAC NG Rampup Rate", da7219_dac_ng_rampup_rate), 625 + SOC_ENUM("DAC NG Rampdown Rate", da7219_dac_ng_rampdown_rate), 626 + SOC_SINGLE_TLV("DAC NG Off Threshold", DA7219_DAC_NG_OFF_THRESH, 627 + DA7219_DAC_NG_OFF_THRESHOLD_SHIFT, 628 + DA7219_DAC_NG_THRESHOLD_MAX, DA7219_NO_INVERT, 629 + da7219_dac_ng_threshold_tlv), 630 + SOC_SINGLE_TLV("DAC NG On Threshold", DA7219_DAC_NG_ON_THRESH, 631 + DA7219_DAC_NG_ON_THRESHOLD_SHIFT, 632 + DA7219_DAC_NG_THRESHOLD_MAX, DA7219_NO_INVERT, 633 + da7219_dac_ng_threshold_tlv), 634 + SOC_SINGLE("DAC NG Switch", DA7219_DAC_NG_CTRL, DA7219_DAC_NG_EN_SHIFT, 635 + DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), 636 + 637 + /* DACs */ 638 + SOC_DOUBLE_R_EXT_TLV("Playback Digital Volume", DA7219_DAC_L_GAIN, 639 + DA7219_DAC_R_GAIN, DA7219_DAC_L_DIGITAL_GAIN_SHIFT, 640 + DA7219_DAC_DIGITAL_GAIN_MAX, DA7219_NO_INVERT, 641 + da7219_volsw_locked_get, da7219_volsw_locked_put, 642 + da7219_dac_dig_gain_tlv), 643 + SOC_DOUBLE_R_EXT("Playback Digital Switch", DA7219_DAC_L_CTRL, 644 + DA7219_DAC_R_CTRL, DA7219_DAC_L_MUTE_EN_SHIFT, 645 + DA7219_SWITCH_EN_MAX, DA7219_INVERT, 646 + da7219_volsw_locked_get, da7219_volsw_locked_put), 647 + SOC_DOUBLE_R("Playback Digital Gain Ramp Switch", DA7219_DAC_L_CTRL, 648 + DA7219_DAC_R_CTRL, DA7219_DAC_L_RAMP_EN_SHIFT, 649 + DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), 650 + 651 + /* CP */ 652 + SOC_ENUM("Charge Pump Track Mode", da7219_cp_track_mode), 653 + SOC_SINGLE("Charge Pump Threshold", DA7219_CP_VOL_THRESHOLD1, 654 + DA7219_CP_THRESH_VDD2_SHIFT, DA7219_CP_THRESH_VDD2_MAX, 655 + DA7219_NO_INVERT), 656 + 657 + /* Headphones */ 658 + SOC_DOUBLE_R_EXT_TLV("Headphone Volume", DA7219_HP_L_GAIN, 659 + DA7219_HP_R_GAIN, DA7219_HP_L_AMP_GAIN_SHIFT, 660 + DA7219_HP_AMP_GAIN_MAX, DA7219_NO_INVERT, 661 + da7219_volsw_locked_get, da7219_volsw_locked_put, 662 + da7219_hp_gain_tlv), 663 + SOC_DOUBLE_R_EXT("Headphone Switch", DA7219_HP_L_CTRL, DA7219_HP_R_CTRL, 664 + DA7219_HP_L_AMP_MUTE_EN_SHIFT, DA7219_SWITCH_EN_MAX, 665 + DA7219_INVERT, da7219_volsw_locked_get, 666 + da7219_volsw_locked_put), 667 + SOC_DOUBLE_R("Headphone Gain Ramp Switch", DA7219_HP_L_CTRL, 668 + DA7219_HP_R_CTRL, DA7219_HP_L_AMP_RAMP_EN_SHIFT, 669 + DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), 670 + SOC_DOUBLE_R("Headphone ZC Gain Switch", DA7219_HP_L_CTRL, 671 + DA7219_HP_R_CTRL, DA7219_HP_L_AMP_ZC_EN_SHIFT, 672 + DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), 673 + }; 674 + 675 + 676 + /* 677 + * DAPM Mux Controls 678 + */ 679 + 680 + static const char * const da7219_out_sel_txt[] = { 681 + "ADC", "Tone Generator", "DAIL", "DAIR" 682 + }; 683 + 684 + static const struct soc_enum da7219_out_dail_sel = 685 + SOC_ENUM_SINGLE(DA7219_DIG_ROUTING_DAI, 686 + DA7219_DAI_L_SRC_SHIFT, 687 + DA7219_OUT_SRC_MAX, 688 + da7219_out_sel_txt); 689 + 690 + static const struct snd_kcontrol_new da7219_out_dail_sel_mux = 691 + SOC_DAPM_ENUM("Out DAIL Mux", da7219_out_dail_sel); 692 + 693 + static const struct soc_enum da7219_out_dair_sel = 694 + SOC_ENUM_SINGLE(DA7219_DIG_ROUTING_DAI, 695 + DA7219_DAI_R_SRC_SHIFT, 696 + DA7219_OUT_SRC_MAX, 697 + da7219_out_sel_txt); 698 + 699 + static const struct snd_kcontrol_new da7219_out_dair_sel_mux = 700 + SOC_DAPM_ENUM("Out DAIR Mux", da7219_out_dair_sel); 701 + 702 + static const struct soc_enum da7219_out_dacl_sel = 703 + SOC_ENUM_SINGLE(DA7219_DIG_ROUTING_DAC, 704 + DA7219_DAC_L_SRC_SHIFT, 705 + DA7219_OUT_SRC_MAX, 706 + da7219_out_sel_txt); 707 + 708 + static const struct snd_kcontrol_new da7219_out_dacl_sel_mux = 709 + SOC_DAPM_ENUM("Out DACL Mux", da7219_out_dacl_sel); 710 + 711 + static const struct soc_enum da7219_out_dacr_sel = 712 + SOC_ENUM_SINGLE(DA7219_DIG_ROUTING_DAC, 713 + DA7219_DAC_R_SRC_SHIFT, 714 + DA7219_OUT_SRC_MAX, 715 + da7219_out_sel_txt); 716 + 717 + static const struct snd_kcontrol_new da7219_out_dacr_sel_mux = 718 + SOC_DAPM_ENUM("Out DACR Mux", da7219_out_dacr_sel); 719 + 720 + 721 + /* 722 + * DAPM Mixer Controls 723 + */ 724 + 725 + static const struct snd_kcontrol_new da7219_mixin_controls[] = { 726 + SOC_DAPM_SINGLE("Mic Switch", DA7219_MIXIN_L_SELECT, 727 + DA7219_MIXIN_L_MIX_SELECT_SHIFT, 728 + DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), 729 + }; 730 + 731 + static const struct snd_kcontrol_new da7219_mixout_l_controls[] = { 732 + SOC_DAPM_SINGLE("DACL Switch", DA7219_MIXOUT_L_SELECT, 733 + DA7219_MIXOUT_L_MIX_SELECT_SHIFT, 734 + DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), 735 + }; 736 + 737 + static const struct snd_kcontrol_new da7219_mixout_r_controls[] = { 738 + SOC_DAPM_SINGLE("DACR Switch", DA7219_MIXOUT_R_SELECT, 739 + DA7219_MIXOUT_R_MIX_SELECT_SHIFT, 740 + DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), 741 + }; 742 + 743 + #define DA7219_DMIX_ST_CTRLS(reg) \ 744 + SOC_DAPM_SINGLE("Out FilterL Switch", reg, \ 745 + DA7219_DMIX_ST_SRC_OUTFILT1L_SHIFT, \ 746 + DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), \ 747 + SOC_DAPM_SINGLE("Out FilterR Switch", reg, \ 748 + DA7219_DMIX_ST_SRC_OUTFILT1R_SHIFT, \ 749 + DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT), \ 750 + SOC_DAPM_SINGLE("Sidetone Switch", reg, \ 751 + DA7219_DMIX_ST_SRC_SIDETONE_SHIFT, \ 752 + DA7219_SWITCH_EN_MAX, DA7219_NO_INVERT) \ 753 + 754 + static const struct snd_kcontrol_new da7219_st_out_filtl_mix_controls[] = { 755 + DA7219_DMIX_ST_CTRLS(DA7219_DROUTING_ST_OUTFILT_1L), 756 + }; 757 + 758 + static const struct snd_kcontrol_new da7219_st_out_filtr_mix_controls[] = { 759 + DA7219_DMIX_ST_CTRLS(DA7219_DROUTING_ST_OUTFILT_1R), 760 + }; 761 + 762 + 763 + /* 764 + * DAPM Events 765 + */ 766 + 767 + static int da7219_dai_event(struct snd_soc_dapm_widget *w, 768 + struct snd_kcontrol *kcontrol, int event) 769 + { 770 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 771 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 772 + u8 pll_ctrl, pll_status; 773 + int i = 0; 774 + bool srm_lock = false; 775 + 776 + switch (event) { 777 + case SND_SOC_DAPM_PRE_PMU: 778 + if (da7219->master) 779 + /* Enable DAI clks for master mode */ 780 + snd_soc_update_bits(codec, DA7219_DAI_CLK_MODE, 781 + DA7219_DAI_CLK_EN_MASK, 782 + DA7219_DAI_CLK_EN_MASK); 783 + 784 + /* PC synchronised to DAI */ 785 + snd_soc_update_bits(codec, DA7219_PC_COUNT, 786 + DA7219_PC_FREERUN_MASK, 0); 787 + 788 + /* Slave mode, if SRM not enabled no need for status checks */ 789 + pll_ctrl = snd_soc_read(codec, DA7219_PLL_CTRL); 790 + if ((pll_ctrl & DA7219_PLL_MODE_MASK) != DA7219_PLL_MODE_SRM) 791 + return 0; 792 + 793 + /* Check SRM has locked */ 794 + do { 795 + pll_status = snd_soc_read(codec, DA7219_PLL_SRM_STS); 796 + if (pll_status & DA7219_PLL_SRM_STS_SRM_LOCK) { 797 + srm_lock = true; 798 + } else { 799 + ++i; 800 + msleep(50); 801 + } 802 + } while ((i < DA7219_SRM_CHECK_RETRIES) & (!srm_lock)); 803 + 804 + if (!srm_lock) 805 + dev_warn(codec->dev, "SRM failed to lock\n"); 806 + 807 + return 0; 808 + case SND_SOC_DAPM_POST_PMD: 809 + /* PC free-running */ 810 + snd_soc_update_bits(codec, DA7219_PC_COUNT, 811 + DA7219_PC_FREERUN_MASK, 812 + DA7219_PC_FREERUN_MASK); 813 + 814 + /* Disable DAI clks if in master mode */ 815 + if (da7219->master) 816 + snd_soc_update_bits(codec, DA7219_DAI_CLK_MODE, 817 + DA7219_DAI_CLK_EN_MASK, 0); 818 + return 0; 819 + default: 820 + return -EINVAL; 821 + } 822 + } 823 + 824 + 825 + /* 826 + * DAPM Widgets 827 + */ 828 + 829 + static const struct snd_soc_dapm_widget da7219_dapm_widgets[] = { 830 + /* Input Supplies */ 831 + SND_SOC_DAPM_SUPPLY("Mic Bias", DA7219_MICBIAS_CTRL, 832 + DA7219_MICBIAS1_EN_SHIFT, DA7219_NO_INVERT, 833 + NULL, 0), 834 + 835 + /* Inputs */ 836 + SND_SOC_DAPM_INPUT("MIC"), 837 + 838 + /* Input PGAs */ 839 + SND_SOC_DAPM_PGA("Mic PGA", DA7219_MIC_1_CTRL, 840 + DA7219_MIC_1_AMP_EN_SHIFT, DA7219_NO_INVERT, 841 + NULL, 0), 842 + SND_SOC_DAPM_PGA("Mixin PGA", DA7219_MIXIN_L_CTRL, 843 + DA7219_MIXIN_L_AMP_EN_SHIFT, DA7219_NO_INVERT, 844 + NULL, 0), 845 + 846 + /* Input Filters */ 847 + SND_SOC_DAPM_ADC("ADC", NULL, DA7219_ADC_L_CTRL, DA7219_ADC_L_EN_SHIFT, 848 + DA7219_NO_INVERT), 849 + 850 + /* Tone Generator */ 851 + SND_SOC_DAPM_SIGGEN("TONE"), 852 + SND_SOC_DAPM_PGA("Tone Generator", DA7219_TONE_GEN_CFG1, 853 + DA7219_START_STOPN_SHIFT, DA7219_NO_INVERT, NULL, 0), 854 + 855 + /* Sidetone Input */ 856 + SND_SOC_DAPM_ADC("Sidetone Filter", NULL, DA7219_SIDETONE_CTRL, 857 + DA7219_SIDETONE_EN_SHIFT, DA7219_NO_INVERT), 858 + 859 + /* Input Mixer Supply */ 860 + SND_SOC_DAPM_SUPPLY("Mixer In Supply", DA7219_MIXIN_L_CTRL, 861 + DA7219_MIXIN_L_MIX_EN_SHIFT, DA7219_NO_INVERT, 862 + NULL, 0), 863 + 864 + /* Input Mixer */ 865 + SND_SOC_DAPM_MIXER("Mixer In", SND_SOC_NOPM, 0, 0, 866 + da7219_mixin_controls, 867 + ARRAY_SIZE(da7219_mixin_controls)), 868 + 869 + /* Input Muxes */ 870 + SND_SOC_DAPM_MUX("Out DAIL Mux", SND_SOC_NOPM, 0, 0, 871 + &da7219_out_dail_sel_mux), 872 + SND_SOC_DAPM_MUX("Out DAIR Mux", SND_SOC_NOPM, 0, 0, 873 + &da7219_out_dair_sel_mux), 874 + 875 + /* DAI Supply */ 876 + SND_SOC_DAPM_SUPPLY("DAI", DA7219_DAI_CTRL, DA7219_DAI_EN_SHIFT, 877 + DA7219_NO_INVERT, da7219_dai_event, 878 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 879 + 880 + /* DAI */ 881 + SND_SOC_DAPM_AIF_OUT("DAIOUT", "Capture", 0, SND_SOC_NOPM, 0, 0), 882 + SND_SOC_DAPM_AIF_IN("DAIIN", "Playback", 0, SND_SOC_NOPM, 0, 0), 883 + 884 + /* Output Muxes */ 885 + SND_SOC_DAPM_MUX("Out DACL Mux", SND_SOC_NOPM, 0, 0, 886 + &da7219_out_dacl_sel_mux), 887 + SND_SOC_DAPM_MUX("Out DACR Mux", SND_SOC_NOPM, 0, 0, 888 + &da7219_out_dacr_sel_mux), 889 + 890 + /* Output Mixers */ 891 + SND_SOC_DAPM_MIXER("Mixer Out FilterL", SND_SOC_NOPM, 0, 0, 892 + da7219_mixout_l_controls, 893 + ARRAY_SIZE(da7219_mixout_l_controls)), 894 + SND_SOC_DAPM_MIXER("Mixer Out FilterR", SND_SOC_NOPM, 0, 0, 895 + da7219_mixout_r_controls, 896 + ARRAY_SIZE(da7219_mixout_r_controls)), 897 + 898 + /* Sidetone Mixers */ 899 + SND_SOC_DAPM_MIXER("ST Mixer Out FilterL", SND_SOC_NOPM, 0, 0, 900 + da7219_st_out_filtl_mix_controls, 901 + ARRAY_SIZE(da7219_st_out_filtl_mix_controls)), 902 + SND_SOC_DAPM_MIXER("ST Mixer Out FilterR", SND_SOC_NOPM, 0, 903 + 0, da7219_st_out_filtr_mix_controls, 904 + ARRAY_SIZE(da7219_st_out_filtr_mix_controls)), 905 + 906 + /* DACs */ 907 + SND_SOC_DAPM_DAC("DACL", NULL, DA7219_DAC_L_CTRL, DA7219_DAC_L_EN_SHIFT, 908 + DA7219_NO_INVERT), 909 + SND_SOC_DAPM_DAC("DACR", NULL, DA7219_DAC_R_CTRL, DA7219_DAC_R_EN_SHIFT, 910 + DA7219_NO_INVERT), 911 + 912 + /* Output PGAs */ 913 + SND_SOC_DAPM_PGA("Mixout Left PGA", DA7219_MIXOUT_L_CTRL, 914 + DA7219_MIXOUT_L_AMP_EN_SHIFT, DA7219_NO_INVERT, 915 + NULL, 0), 916 + SND_SOC_DAPM_PGA("Mixout Right PGA", DA7219_MIXOUT_R_CTRL, 917 + DA7219_MIXOUT_R_AMP_EN_SHIFT, DA7219_NO_INVERT, 918 + NULL, 0), 919 + SND_SOC_DAPM_PGA("Headphone Left PGA", DA7219_HP_L_CTRL, 920 + DA7219_HP_L_AMP_EN_SHIFT, DA7219_NO_INVERT, NULL, 0), 921 + SND_SOC_DAPM_PGA("Headphone Right PGA", DA7219_HP_R_CTRL, 922 + DA7219_HP_R_AMP_EN_SHIFT, DA7219_NO_INVERT, NULL, 0), 923 + 924 + /* Output Supplies */ 925 + SND_SOC_DAPM_SUPPLY("Charge Pump", DA7219_CP_CTRL, DA7219_CP_EN_SHIFT, 926 + DA7219_NO_INVERT, NULL, 0), 927 + 928 + /* Outputs */ 929 + SND_SOC_DAPM_OUTPUT("HPL"), 930 + SND_SOC_DAPM_OUTPUT("HPR"), 931 + }; 932 + 933 + 934 + /* 935 + * DAPM Mux Routes 936 + */ 937 + 938 + #define DA7219_OUT_DAI_MUX_ROUTES(name) \ 939 + {name, "ADC", "Mixer In"}, \ 940 + {name, "Tone Generator", "Tone Generator"}, \ 941 + {name, "DAIL", "DAIOUT"}, \ 942 + {name, "DAIR", "DAIOUT"} 943 + 944 + #define DA7219_OUT_DAC_MUX_ROUTES(name) \ 945 + {name, "ADC", "Mixer In"}, \ 946 + {name, "Tone Generator", "Tone Generator"}, \ 947 + {name, "DAIL", "DAIIN"}, \ 948 + {name, "DAIR", "DAIIN"} 949 + 950 + /* 951 + * DAPM Mixer Routes 952 + */ 953 + 954 + #define DA7219_DMIX_ST_ROUTES(name) \ 955 + {name, "Out FilterL Switch", "Mixer Out FilterL"}, \ 956 + {name, "Out FilterR Switch", "Mixer Out FilterR"}, \ 957 + {name, "Sidetone Switch", "Sidetone Filter"} 958 + 959 + 960 + /* 961 + * DAPM audio route definition 962 + */ 963 + 964 + static const struct snd_soc_dapm_route da7219_audio_map[] = { 965 + /* Input paths */ 966 + {"MIC", NULL, "Mic Bias"}, 967 + {"Mic PGA", NULL, "MIC"}, 968 + {"Mixin PGA", NULL, "Mic PGA"}, 969 + {"ADC", NULL, "Mixin PGA"}, 970 + 971 + {"Sidetone Filter", NULL, "ADC"}, 972 + {"Mixer In", NULL, "Mixer In Supply"}, 973 + {"Mixer In", "Mic Switch", "ADC"}, 974 + 975 + {"Tone Generator", NULL, "TONE"}, 976 + 977 + DA7219_OUT_DAI_MUX_ROUTES("Out DAIL Mux"), 978 + DA7219_OUT_DAI_MUX_ROUTES("Out DAIR Mux"), 979 + 980 + {"DAIOUT", NULL, "Out DAIL Mux"}, 981 + {"DAIOUT", NULL, "Out DAIR Mux"}, 982 + {"DAIOUT", NULL, "DAI"}, 983 + 984 + /* Output paths */ 985 + {"DAIIN", NULL, "DAI"}, 986 + 987 + DA7219_OUT_DAC_MUX_ROUTES("Out DACL Mux"), 988 + DA7219_OUT_DAC_MUX_ROUTES("Out DACR Mux"), 989 + 990 + {"Mixer Out FilterL", "DACL Switch", "Out DACL Mux"}, 991 + {"Mixer Out FilterR", "DACR Switch", "Out DACR Mux"}, 992 + 993 + DA7219_DMIX_ST_ROUTES("ST Mixer Out FilterL"), 994 + DA7219_DMIX_ST_ROUTES("ST Mixer Out FilterR"), 995 + 996 + {"DACL", NULL, "ST Mixer Out FilterL"}, 997 + {"DACR", NULL, "ST Mixer Out FilterR"}, 998 + 999 + {"Mixout Left PGA", NULL, "DACL"}, 1000 + {"Mixout Right PGA", NULL, "DACR"}, 1001 + 1002 + {"Headphone Left PGA", NULL, "Mixout Left PGA"}, 1003 + {"Headphone Right PGA", NULL, "Mixout Right PGA"}, 1004 + 1005 + {"HPL", NULL, "Headphone Left PGA"}, 1006 + {"HPR", NULL, "Headphone Right PGA"}, 1007 + 1008 + {"HPL", NULL, "Charge Pump"}, 1009 + {"HPR", NULL, "Charge Pump"}, 1010 + }; 1011 + 1012 + 1013 + /* 1014 + * DAI operations 1015 + */ 1016 + 1017 + static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai, 1018 + int clk_id, unsigned int freq, int dir) 1019 + { 1020 + struct snd_soc_codec *codec = codec_dai->codec; 1021 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1022 + int ret = 0; 1023 + 1024 + if ((da7219->clk_src == clk_id) && (da7219->mclk_rate == freq)) 1025 + return 0; 1026 + 1027 + if (((freq < 2000000) && (freq != 32768)) || (freq > 54000000)) { 1028 + dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", 1029 + freq); 1030 + return -EINVAL; 1031 + } 1032 + 1033 + switch (clk_id) { 1034 + case DA7219_CLKSRC_MCLK_SQR: 1035 + snd_soc_update_bits(codec, DA7219_PLL_CTRL, 1036 + DA7219_PLL_MCLK_SQR_EN_MASK, 1037 + DA7219_PLL_MCLK_SQR_EN_MASK); 1038 + break; 1039 + case DA7219_CLKSRC_MCLK: 1040 + snd_soc_update_bits(codec, DA7219_PLL_CTRL, 1041 + DA7219_PLL_MCLK_SQR_EN_MASK, 0); 1042 + break; 1043 + default: 1044 + dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id); 1045 + return -EINVAL; 1046 + } 1047 + 1048 + da7219->clk_src = clk_id; 1049 + 1050 + if (da7219->mclk) { 1051 + freq = clk_round_rate(da7219->mclk, freq); 1052 + ret = clk_set_rate(da7219->mclk, freq); 1053 + if (ret) { 1054 + dev_err(codec_dai->dev, "Failed to set clock rate %d\n", 1055 + freq); 1056 + return ret; 1057 + } 1058 + } 1059 + 1060 + da7219->mclk_rate = freq; 1061 + 1062 + return 0; 1063 + } 1064 + 1065 + static int da7219_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, 1066 + int source, unsigned int fref, unsigned int fout) 1067 + { 1068 + struct snd_soc_codec *codec = codec_dai->codec; 1069 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1070 + 1071 + u8 pll_ctrl, indiv_bits, indiv; 1072 + u8 pll_frac_top, pll_frac_bot, pll_integer; 1073 + u32 freq_ref; 1074 + u64 frac_div; 1075 + 1076 + /* Verify 32KHz, 2MHz - 54MHz MCLK provided, and set input divider */ 1077 + if (da7219->mclk_rate == 32768) { 1078 + indiv_bits = DA7219_PLL_INDIV_2_5_MHZ; 1079 + indiv = DA7219_PLL_INDIV_2_5_MHZ_VAL; 1080 + } else if (da7219->mclk_rate < 2000000) { 1081 + dev_err(codec->dev, "PLL input clock %d below valid range\n", 1082 + da7219->mclk_rate); 1083 + return -EINVAL; 1084 + } else if (da7219->mclk_rate <= 5000000) { 1085 + indiv_bits = DA7219_PLL_INDIV_2_5_MHZ; 1086 + indiv = DA7219_PLL_INDIV_2_5_MHZ_VAL; 1087 + } else if (da7219->mclk_rate <= 10000000) { 1088 + indiv_bits = DA7219_PLL_INDIV_5_10_MHZ; 1089 + indiv = DA7219_PLL_INDIV_5_10_MHZ_VAL; 1090 + } else if (da7219->mclk_rate <= 20000000) { 1091 + indiv_bits = DA7219_PLL_INDIV_10_20_MHZ; 1092 + indiv = DA7219_PLL_INDIV_10_20_MHZ_VAL; 1093 + } else if (da7219->mclk_rate <= 40000000) { 1094 + indiv_bits = DA7219_PLL_INDIV_20_40_MHZ; 1095 + indiv = DA7219_PLL_INDIV_20_40_MHZ_VAL; 1096 + } else if (da7219->mclk_rate <= 54000000) { 1097 + indiv_bits = DA7219_PLL_INDIV_40_54_MHZ; 1098 + indiv = DA7219_PLL_INDIV_40_54_MHZ_VAL; 1099 + } else { 1100 + dev_err(codec->dev, "PLL input clock %d above valid range\n", 1101 + da7219->mclk_rate); 1102 + return -EINVAL; 1103 + } 1104 + freq_ref = (da7219->mclk_rate / indiv); 1105 + pll_ctrl = indiv_bits; 1106 + 1107 + /* Configure PLL */ 1108 + switch (source) { 1109 + case DA7219_SYSCLK_MCLK: 1110 + pll_ctrl |= DA7219_PLL_MODE_BYPASS; 1111 + snd_soc_update_bits(codec, DA7219_PLL_CTRL, 1112 + DA7219_PLL_INDIV_MASK | 1113 + DA7219_PLL_MODE_MASK, pll_ctrl); 1114 + return 0; 1115 + case DA7219_SYSCLK_PLL: 1116 + pll_ctrl |= DA7219_PLL_MODE_NORMAL; 1117 + break; 1118 + case DA7219_SYSCLK_PLL_SRM: 1119 + pll_ctrl |= DA7219_PLL_MODE_SRM; 1120 + break; 1121 + case DA7219_SYSCLK_PLL_32KHZ: 1122 + pll_ctrl |= DA7219_PLL_MODE_32KHZ; 1123 + break; 1124 + default: 1125 + dev_err(codec->dev, "Invalid PLL config\n"); 1126 + return -EINVAL; 1127 + } 1128 + 1129 + /* Calculate dividers for PLL */ 1130 + pll_integer = fout / freq_ref; 1131 + frac_div = (u64)(fout % freq_ref) * 8192ULL; 1132 + do_div(frac_div, freq_ref); 1133 + pll_frac_top = (frac_div >> DA7219_BYTE_SHIFT) & DA7219_BYTE_MASK; 1134 + pll_frac_bot = (frac_div) & DA7219_BYTE_MASK; 1135 + 1136 + /* Write PLL config & dividers */ 1137 + snd_soc_write(codec, DA7219_PLL_FRAC_TOP, pll_frac_top); 1138 + snd_soc_write(codec, DA7219_PLL_FRAC_BOT, pll_frac_bot); 1139 + snd_soc_write(codec, DA7219_PLL_INTEGER, pll_integer); 1140 + snd_soc_update_bits(codec, DA7219_PLL_CTRL, 1141 + DA7219_PLL_INDIV_MASK | DA7219_PLL_MODE_MASK, 1142 + pll_ctrl); 1143 + 1144 + return 0; 1145 + } 1146 + 1147 + static int da7219_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 1148 + { 1149 + struct snd_soc_codec *codec = codec_dai->codec; 1150 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1151 + u8 dai_clk_mode = 0, dai_ctrl = 0; 1152 + 1153 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 1154 + case SND_SOC_DAIFMT_CBM_CFM: 1155 + da7219->master = true; 1156 + break; 1157 + case SND_SOC_DAIFMT_CBS_CFS: 1158 + da7219->master = false; 1159 + break; 1160 + default: 1161 + return -EINVAL; 1162 + } 1163 + 1164 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 1165 + case SND_SOC_DAIFMT_NB_NF: 1166 + break; 1167 + case SND_SOC_DAIFMT_NB_IF: 1168 + dai_clk_mode |= DA7219_DAI_WCLK_POL_INV; 1169 + break; 1170 + case SND_SOC_DAIFMT_IB_NF: 1171 + dai_clk_mode |= DA7219_DAI_CLK_POL_INV; 1172 + break; 1173 + case SND_SOC_DAIFMT_IB_IF: 1174 + dai_clk_mode |= DA7219_DAI_WCLK_POL_INV | 1175 + DA7219_DAI_CLK_POL_INV; 1176 + break; 1177 + default: 1178 + return -EINVAL; 1179 + } 1180 + 1181 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 1182 + case SND_SOC_DAIFMT_I2S: 1183 + dai_ctrl |= DA7219_DAI_FORMAT_I2S; 1184 + break; 1185 + case SND_SOC_DAIFMT_LEFT_J: 1186 + dai_ctrl |= DA7219_DAI_FORMAT_LEFT_J; 1187 + break; 1188 + case SND_SOC_DAIFMT_RIGHT_J: 1189 + dai_ctrl |= DA7219_DAI_FORMAT_RIGHT_J; 1190 + break; 1191 + case SND_SOC_DAIFMT_DSP_B: 1192 + dai_ctrl |= DA7219_DAI_FORMAT_DSP; 1193 + break; 1194 + default: 1195 + return -EINVAL; 1196 + } 1197 + 1198 + /* By default 64 BCLKs per WCLK is supported */ 1199 + dai_clk_mode |= DA7219_DAI_BCLKS_PER_WCLK_64; 1200 + 1201 + snd_soc_update_bits(codec, DA7219_DAI_CLK_MODE, 1202 + DA7219_DAI_BCLKS_PER_WCLK_MASK | 1203 + DA7219_DAI_CLK_POL_MASK | DA7219_DAI_WCLK_POL_MASK, 1204 + dai_clk_mode); 1205 + snd_soc_update_bits(codec, DA7219_DAI_CTRL, DA7219_DAI_FORMAT_MASK, 1206 + dai_ctrl); 1207 + 1208 + return 0; 1209 + } 1210 + 1211 + static int da7219_set_dai_tdm_slot(struct snd_soc_dai *dai, 1212 + unsigned int tx_mask, unsigned int rx_mask, 1213 + int slots, int slot_width) 1214 + { 1215 + struct snd_soc_codec *codec = dai->codec; 1216 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1217 + u8 dai_bclks_per_wclk; 1218 + u16 offset; 1219 + u32 frame_size; 1220 + 1221 + /* No channels enabled so disable TDM, revert to 64-bit frames */ 1222 + if (!tx_mask) { 1223 + snd_soc_update_bits(codec, DA7219_DAI_TDM_CTRL, 1224 + DA7219_DAI_TDM_CH_EN_MASK | 1225 + DA7219_DAI_TDM_MODE_EN_MASK, 0); 1226 + snd_soc_update_bits(codec, DA7219_DAI_CLK_MODE, 1227 + DA7219_DAI_BCLKS_PER_WCLK_MASK, 1228 + DA7219_DAI_BCLKS_PER_WCLK_64); 1229 + return 0; 1230 + } 1231 + 1232 + /* Check we have valid slots */ 1233 + if (fls(tx_mask) > DA7219_DAI_TDM_MAX_SLOTS) { 1234 + dev_err(codec->dev, "Invalid number of slots, max = %d\n", 1235 + DA7219_DAI_TDM_MAX_SLOTS); 1236 + return -EINVAL; 1237 + } 1238 + 1239 + /* Check we have a valid offset given */ 1240 + if (rx_mask > DA7219_DAI_OFFSET_MAX) { 1241 + dev_err(codec->dev, "Invalid slot offset, max = %d\n", 1242 + DA7219_DAI_OFFSET_MAX); 1243 + return -EINVAL; 1244 + } 1245 + 1246 + /* Calculate & validate frame size based on slot info provided. */ 1247 + frame_size = slots * slot_width; 1248 + switch (frame_size) { 1249 + case 32: 1250 + dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_32; 1251 + break; 1252 + case 64: 1253 + dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_64; 1254 + break; 1255 + case 128: 1256 + dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_128; 1257 + break; 1258 + case 256: 1259 + dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_256; 1260 + break; 1261 + default: 1262 + dev_err(codec->dev, "Invalid frame size %d\n", frame_size); 1263 + return -EINVAL; 1264 + } 1265 + 1266 + snd_soc_update_bits(codec, DA7219_DAI_CLK_MODE, 1267 + DA7219_DAI_BCLKS_PER_WCLK_MASK, 1268 + dai_bclks_per_wclk); 1269 + 1270 + offset = cpu_to_le16(rx_mask); 1271 + regmap_bulk_write(da7219->regmap, DA7219_DAI_OFFSET_LOWER, 1272 + &offset, sizeof(offset)); 1273 + 1274 + snd_soc_update_bits(codec, DA7219_DAI_TDM_CTRL, 1275 + DA7219_DAI_TDM_CH_EN_MASK | 1276 + DA7219_DAI_TDM_MODE_EN_MASK, 1277 + (tx_mask << DA7219_DAI_TDM_CH_EN_SHIFT) | 1278 + DA7219_DAI_TDM_MODE_EN_MASK); 1279 + 1280 + return 0; 1281 + } 1282 + 1283 + static int da7219_hw_params(struct snd_pcm_substream *substream, 1284 + struct snd_pcm_hw_params *params, 1285 + struct snd_soc_dai *dai) 1286 + { 1287 + struct snd_soc_codec *codec = dai->codec; 1288 + u8 dai_ctrl = 0, fs; 1289 + unsigned int channels; 1290 + 1291 + switch (params_width(params)) { 1292 + case 16: 1293 + dai_ctrl |= DA7219_DAI_WORD_LENGTH_S16_LE; 1294 + break; 1295 + case 20: 1296 + dai_ctrl |= DA7219_DAI_WORD_LENGTH_S20_LE; 1297 + break; 1298 + case 24: 1299 + dai_ctrl |= DA7219_DAI_WORD_LENGTH_S24_LE; 1300 + break; 1301 + case 32: 1302 + dai_ctrl |= DA7219_DAI_WORD_LENGTH_S32_LE; 1303 + break; 1304 + default: 1305 + return -EINVAL; 1306 + } 1307 + 1308 + channels = params_channels(params); 1309 + if ((channels < 1) | (channels > DA7219_DAI_CH_NUM_MAX)) { 1310 + dev_err(codec->dev, 1311 + "Invalid number of channels, only 1 to %d supported\n", 1312 + DA7219_DAI_CH_NUM_MAX); 1313 + return -EINVAL; 1314 + } 1315 + dai_ctrl |= channels << DA7219_DAI_CH_NUM_SHIFT; 1316 + 1317 + switch (params_rate(params)) { 1318 + case 8000: 1319 + fs = DA7219_SR_8000; 1320 + break; 1321 + case 11025: 1322 + fs = DA7219_SR_11025; 1323 + break; 1324 + case 12000: 1325 + fs = DA7219_SR_12000; 1326 + break; 1327 + case 16000: 1328 + fs = DA7219_SR_16000; 1329 + break; 1330 + case 22050: 1331 + fs = DA7219_SR_22050; 1332 + break; 1333 + case 24000: 1334 + fs = DA7219_SR_24000; 1335 + break; 1336 + case 32000: 1337 + fs = DA7219_SR_32000; 1338 + break; 1339 + case 44100: 1340 + fs = DA7219_SR_44100; 1341 + break; 1342 + case 48000: 1343 + fs = DA7219_SR_48000; 1344 + break; 1345 + case 88200: 1346 + fs = DA7219_SR_88200; 1347 + break; 1348 + case 96000: 1349 + fs = DA7219_SR_96000; 1350 + break; 1351 + default: 1352 + return -EINVAL; 1353 + } 1354 + 1355 + snd_soc_update_bits(codec, DA7219_DAI_CTRL, 1356 + DA7219_DAI_WORD_LENGTH_MASK | 1357 + DA7219_DAI_CH_NUM_MASK, 1358 + dai_ctrl); 1359 + snd_soc_write(codec, DA7219_SR, fs); 1360 + 1361 + return 0; 1362 + } 1363 + 1364 + static const struct snd_soc_dai_ops da7219_dai_ops = { 1365 + .hw_params = da7219_hw_params, 1366 + .set_sysclk = da7219_set_dai_sysclk, 1367 + .set_pll = da7219_set_dai_pll, 1368 + .set_fmt = da7219_set_dai_fmt, 1369 + .set_tdm_slot = da7219_set_dai_tdm_slot, 1370 + }; 1371 + 1372 + #define DA7219_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 1373 + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 1374 + 1375 + static struct snd_soc_dai_driver da7219_dai = { 1376 + .name = "da7219-hifi", 1377 + .playback = { 1378 + .stream_name = "Playback", 1379 + .channels_min = 1, 1380 + .channels_max = DA7219_DAI_CH_NUM_MAX, 1381 + .rates = SNDRV_PCM_RATE_8000_96000, 1382 + .formats = DA7219_FORMATS, 1383 + }, 1384 + .capture = { 1385 + .stream_name = "Capture", 1386 + .channels_min = 1, 1387 + .channels_max = DA7219_DAI_CH_NUM_MAX, 1388 + .rates = SNDRV_PCM_RATE_8000_96000, 1389 + .formats = DA7219_FORMATS, 1390 + }, 1391 + .ops = &da7219_dai_ops, 1392 + .symmetric_rates = 1, 1393 + .symmetric_channels = 1, 1394 + .symmetric_samplebits = 1, 1395 + }; 1396 + 1397 + 1398 + /* 1399 + * DT 1400 + */ 1401 + 1402 + static const struct of_device_id da7219_of_match[] = { 1403 + { .compatible = "dlg,da7219", }, 1404 + { } 1405 + }; 1406 + MODULE_DEVICE_TABLE(of, da7219_of_match); 1407 + 1408 + static enum da7219_ldo_lvl_sel da7219_of_ldo_lvl(struct snd_soc_codec *codec, 1409 + u32 val) 1410 + { 1411 + switch (val) { 1412 + case 1050: 1413 + return DA7219_LDO_LVL_SEL_1_05V; 1414 + case 1100: 1415 + return DA7219_LDO_LVL_SEL_1_10V; 1416 + case 1200: 1417 + return DA7219_LDO_LVL_SEL_1_20V; 1418 + case 1400: 1419 + return DA7219_LDO_LVL_SEL_1_40V; 1420 + default: 1421 + dev_warn(codec->dev, "Invalid LDO level"); 1422 + return DA7219_LDO_LVL_SEL_1_05V; 1423 + } 1424 + } 1425 + 1426 + static enum da7219_micbias_voltage 1427 + da7219_of_micbias_lvl(struct snd_soc_codec *codec, u32 val) 1428 + { 1429 + switch (val) { 1430 + case 1800: 1431 + return DA7219_MICBIAS_1_8V; 1432 + case 2000: 1433 + return DA7219_MICBIAS_2_0V; 1434 + case 2200: 1435 + return DA7219_MICBIAS_2_2V; 1436 + case 2400: 1437 + return DA7219_MICBIAS_2_4V; 1438 + case 2600: 1439 + return DA7219_MICBIAS_2_6V; 1440 + default: 1441 + dev_warn(codec->dev, "Invalid micbias level"); 1442 + return DA7219_MICBIAS_2_2V; 1443 + } 1444 + } 1445 + 1446 + static enum da7219_mic_amp_in_sel 1447 + da7219_of_mic_amp_in_sel(struct snd_soc_codec *codec, const char *str) 1448 + { 1449 + if (!strcmp(str, "diff")) { 1450 + return DA7219_MIC_AMP_IN_SEL_DIFF; 1451 + } else if (!strcmp(str, "se_p")) { 1452 + return DA7219_MIC_AMP_IN_SEL_SE_P; 1453 + } else if (!strcmp(str, "se_n")) { 1454 + return DA7219_MIC_AMP_IN_SEL_SE_N; 1455 + } else { 1456 + dev_warn(codec->dev, "Invalid mic input type selection"); 1457 + return DA7219_MIC_AMP_IN_SEL_DIFF; 1458 + } 1459 + } 1460 + 1461 + static struct da7219_pdata *da7219_of_to_pdata(struct snd_soc_codec *codec) 1462 + { 1463 + struct device_node *np = codec->dev->of_node; 1464 + struct da7219_pdata *pdata; 1465 + const char *of_str; 1466 + u32 of_val32; 1467 + 1468 + pdata = devm_kzalloc(codec->dev, sizeof(*pdata), GFP_KERNEL); 1469 + if (!pdata) 1470 + return NULL; 1471 + 1472 + if (of_property_read_u32(np, "dlg,ldo-lvl", &of_val32) >= 0) 1473 + pdata->ldo_lvl_sel = da7219_of_ldo_lvl(codec, of_val32); 1474 + 1475 + if (of_property_read_u32(np, "dlg,micbias-lvl", &of_val32) >= 0) 1476 + pdata->micbias_lvl = da7219_of_micbias_lvl(codec, of_val32); 1477 + else 1478 + pdata->micbias_lvl = DA7219_MICBIAS_2_2V; 1479 + 1480 + if (!of_property_read_string(np, "dlg,mic-amp-in-sel", &of_str)) 1481 + pdata->mic_amp_in_sel = da7219_of_mic_amp_in_sel(codec, of_str); 1482 + else 1483 + pdata->mic_amp_in_sel = DA7219_MIC_AMP_IN_SEL_DIFF; 1484 + 1485 + return pdata; 1486 + } 1487 + 1488 + 1489 + /* 1490 + * Codec driver functions 1491 + */ 1492 + 1493 + static int da7219_set_bias_level(struct snd_soc_codec *codec, 1494 + enum snd_soc_bias_level level) 1495 + { 1496 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1497 + 1498 + switch (level) { 1499 + case SND_SOC_BIAS_ON: 1500 + case SND_SOC_BIAS_PREPARE: 1501 + break; 1502 + case SND_SOC_BIAS_STANDBY: 1503 + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { 1504 + /* MCLK */ 1505 + clk_prepare_enable(da7219->mclk); 1506 + 1507 + /* Master bias */ 1508 + snd_soc_update_bits(codec, DA7219_REFERENCES, 1509 + DA7219_BIAS_EN_MASK, 1510 + DA7219_BIAS_EN_MASK); 1511 + 1512 + /* Enable Internal Digital LDO */ 1513 + snd_soc_update_bits(codec, DA7219_LDO_CTRL, 1514 + DA7219_LDO_EN_MASK, 1515 + DA7219_LDO_EN_MASK); 1516 + } 1517 + break; 1518 + case SND_SOC_BIAS_OFF: 1519 + /* Only disable if jack detection not active */ 1520 + if (!da7219->aad->jack) { 1521 + /* Bypass Internal Digital LDO */ 1522 + snd_soc_update_bits(codec, DA7219_LDO_CTRL, 1523 + DA7219_LDO_EN_MASK, 0); 1524 + 1525 + /* Master bias */ 1526 + snd_soc_update_bits(codec, DA7219_REFERENCES, 1527 + DA7219_BIAS_EN_MASK, 0); 1528 + } 1529 + 1530 + /* MCLK */ 1531 + clk_disable_unprepare(da7219->mclk); 1532 + break; 1533 + } 1534 + 1535 + return 0; 1536 + } 1537 + 1538 + static const char *da7219_supply_names[DA7219_NUM_SUPPLIES] = { 1539 + [DA7219_SUPPLY_VDD] = "VDD", 1540 + [DA7219_SUPPLY_VDDMIC] = "VDDMIC", 1541 + [DA7219_SUPPLY_VDDIO] = "VDDIO", 1542 + }; 1543 + 1544 + static int da7219_handle_supplies(struct snd_soc_codec *codec) 1545 + { 1546 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1547 + struct regulator *vddio; 1548 + u8 io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_2_5V_3_6V; 1549 + int i, ret; 1550 + 1551 + /* Get required supplies */ 1552 + for (i = 0; i < DA7219_NUM_SUPPLIES; ++i) 1553 + da7219->supplies[i].supply = da7219_supply_names[i]; 1554 + 1555 + ret = devm_regulator_bulk_get(codec->dev, DA7219_NUM_SUPPLIES, 1556 + da7219->supplies); 1557 + if (ret) 1558 + return ret; 1559 + 1560 + /* Determine VDDIO voltage provided */ 1561 + vddio = da7219->supplies[DA7219_SUPPLY_VDDIO].consumer; 1562 + ret = regulator_get_voltage(vddio); 1563 + if (ret < 1200000) 1564 + dev_warn(codec->dev, "Invalid VDDIO voltage\n"); 1565 + else if (ret < 2800000) 1566 + io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V; 1567 + 1568 + /* Enable main supplies */ 1569 + ret = regulator_bulk_enable(DA7219_NUM_SUPPLIES, da7219->supplies); 1570 + 1571 + /* Ensure device in active mode */ 1572 + snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, DA7219_SYSTEM_ACTIVE_MASK); 1573 + 1574 + /* Update IO voltage level range */ 1575 + snd_soc_write(codec, DA7219_IO_CTRL, io_voltage_lvl); 1576 + 1577 + return ret; 1578 + } 1579 + 1580 + static void da7219_handle_pdata(struct snd_soc_codec *codec) 1581 + { 1582 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1583 + struct da7219_pdata *pdata = da7219->pdata; 1584 + 1585 + if (pdata) { 1586 + u8 micbias_lvl = 0; 1587 + 1588 + /* Internal LDO */ 1589 + switch (pdata->ldo_lvl_sel) { 1590 + case DA7219_LDO_LVL_SEL_1_05V: 1591 + case DA7219_LDO_LVL_SEL_1_10V: 1592 + case DA7219_LDO_LVL_SEL_1_20V: 1593 + case DA7219_LDO_LVL_SEL_1_40V: 1594 + snd_soc_update_bits(codec, DA7219_LDO_CTRL, 1595 + DA7219_LDO_LEVEL_SELECT_MASK, 1596 + (pdata->ldo_lvl_sel << 1597 + DA7219_LDO_LEVEL_SELECT_SHIFT)); 1598 + break; 1599 + } 1600 + 1601 + /* Mic Bias voltages */ 1602 + switch (pdata->micbias_lvl) { 1603 + case DA7219_MICBIAS_1_8V: 1604 + case DA7219_MICBIAS_2_0V: 1605 + case DA7219_MICBIAS_2_2V: 1606 + case DA7219_MICBIAS_2_4V: 1607 + case DA7219_MICBIAS_2_6V: 1608 + micbias_lvl |= (pdata->micbias_lvl << 1609 + DA7219_MICBIAS1_LEVEL_SHIFT); 1610 + break; 1611 + } 1612 + 1613 + snd_soc_write(codec, DA7219_MICBIAS_CTRL, micbias_lvl); 1614 + 1615 + /* Mic */ 1616 + switch (pdata->mic_amp_in_sel) { 1617 + case DA7219_MIC_AMP_IN_SEL_DIFF: 1618 + case DA7219_MIC_AMP_IN_SEL_SE_P: 1619 + case DA7219_MIC_AMP_IN_SEL_SE_N: 1620 + snd_soc_write(codec, DA7219_MIC_1_SELECT, 1621 + pdata->mic_amp_in_sel); 1622 + break; 1623 + } 1624 + } 1625 + } 1626 + 1627 + static int da7219_probe(struct snd_soc_codec *codec) 1628 + { 1629 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1630 + int ret; 1631 + 1632 + mutex_init(&da7219->lock); 1633 + 1634 + /* Regulator configuration */ 1635 + ret = da7219_handle_supplies(codec); 1636 + if (ret) 1637 + return ret; 1638 + 1639 + /* Handle DT/Platform data */ 1640 + if (codec->dev->of_node) 1641 + da7219->pdata = da7219_of_to_pdata(codec); 1642 + else 1643 + da7219->pdata = dev_get_platdata(codec->dev); 1644 + 1645 + da7219_handle_pdata(codec); 1646 + 1647 + /* Check if MCLK provided */ 1648 + da7219->mclk = devm_clk_get(codec->dev, "mclk"); 1649 + if (IS_ERR(da7219->mclk)) { 1650 + if (PTR_ERR(da7219->mclk) != -ENOENT) 1651 + return PTR_ERR(da7219->mclk); 1652 + else 1653 + da7219->mclk = NULL; 1654 + } 1655 + 1656 + /* Default PC counter to free-running */ 1657 + snd_soc_update_bits(codec, DA7219_PC_COUNT, DA7219_PC_FREERUN_MASK, 1658 + DA7219_PC_FREERUN_MASK); 1659 + 1660 + /* Default gain ramping */ 1661 + snd_soc_update_bits(codec, DA7219_MIXIN_L_CTRL, 1662 + DA7219_MIXIN_L_AMP_RAMP_EN_MASK, 1663 + DA7219_MIXIN_L_AMP_RAMP_EN_MASK); 1664 + snd_soc_update_bits(codec, DA7219_ADC_L_CTRL, DA7219_ADC_L_RAMP_EN_MASK, 1665 + DA7219_ADC_L_RAMP_EN_MASK); 1666 + snd_soc_update_bits(codec, DA7219_DAC_L_CTRL, DA7219_DAC_L_RAMP_EN_MASK, 1667 + DA7219_DAC_L_RAMP_EN_MASK); 1668 + snd_soc_update_bits(codec, DA7219_DAC_R_CTRL, DA7219_DAC_R_RAMP_EN_MASK, 1669 + DA7219_DAC_R_RAMP_EN_MASK); 1670 + snd_soc_update_bits(codec, DA7219_HP_L_CTRL, 1671 + DA7219_HP_L_AMP_RAMP_EN_MASK, 1672 + DA7219_HP_L_AMP_RAMP_EN_MASK); 1673 + snd_soc_update_bits(codec, DA7219_HP_R_CTRL, 1674 + DA7219_HP_R_AMP_RAMP_EN_MASK, 1675 + DA7219_HP_R_AMP_RAMP_EN_MASK); 1676 + 1677 + /* Default infinite tone gen, start/stop by Kcontrol */ 1678 + snd_soc_write(codec, DA7219_TONE_GEN_CYCLES, DA7219_BEEP_CYCLES_MASK); 1679 + 1680 + /* Initialise AAD block */ 1681 + return da7219_aad_init(codec); 1682 + } 1683 + 1684 + static int da7219_remove(struct snd_soc_codec *codec) 1685 + { 1686 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1687 + 1688 + da7219_aad_exit(codec); 1689 + 1690 + /* Supplies */ 1691 + return regulator_bulk_disable(DA7219_NUM_SUPPLIES, da7219->supplies); 1692 + } 1693 + 1694 + #ifdef CONFIG_PM 1695 + static int da7219_suspend(struct snd_soc_codec *codec) 1696 + { 1697 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1698 + 1699 + snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); 1700 + 1701 + /* Put device into standby mode if jack detection disabled */ 1702 + if (!da7219->aad->jack) 1703 + snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, 0); 1704 + 1705 + return 0; 1706 + } 1707 + 1708 + static int da7219_resume(struct snd_soc_codec *codec) 1709 + { 1710 + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1711 + 1712 + /* Put device into active mode if previously pushed to standby */ 1713 + if (!da7219->aad->jack) 1714 + snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, 1715 + DA7219_SYSTEM_ACTIVE_MASK); 1716 + 1717 + snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); 1718 + 1719 + return 0; 1720 + } 1721 + #else 1722 + #define da7219_suspend NULL 1723 + #define da7219_resume NULL 1724 + #endif 1725 + 1726 + static struct snd_soc_codec_driver soc_codec_dev_da7219 = { 1727 + .probe = da7219_probe, 1728 + .remove = da7219_remove, 1729 + .suspend = da7219_suspend, 1730 + .resume = da7219_resume, 1731 + .set_bias_level = da7219_set_bias_level, 1732 + 1733 + .controls = da7219_snd_controls, 1734 + .num_controls = ARRAY_SIZE(da7219_snd_controls), 1735 + 1736 + .dapm_widgets = da7219_dapm_widgets, 1737 + .num_dapm_widgets = ARRAY_SIZE(da7219_dapm_widgets), 1738 + .dapm_routes = da7219_audio_map, 1739 + .num_dapm_routes = ARRAY_SIZE(da7219_audio_map), 1740 + }; 1741 + 1742 + 1743 + /* 1744 + * Regmap configs 1745 + */ 1746 + 1747 + static struct reg_default da7219_reg_defaults[] = { 1748 + { DA7219_MIC_1_SELECT, 0x00 }, 1749 + { DA7219_CIF_TIMEOUT_CTRL, 0x01 }, 1750 + { DA7219_SR_24_48, 0x00 }, 1751 + { DA7219_SR, 0x0A }, 1752 + { DA7219_CIF_I2C_ADDR_CFG, 0x02 }, 1753 + { DA7219_PLL_CTRL, 0x10 }, 1754 + { DA7219_PLL_FRAC_TOP, 0x00 }, 1755 + { DA7219_PLL_FRAC_BOT, 0x00 }, 1756 + { DA7219_PLL_INTEGER, 0x20 }, 1757 + { DA7219_DIG_ROUTING_DAI, 0x10 }, 1758 + { DA7219_DAI_CLK_MODE, 0x01 }, 1759 + { DA7219_DAI_CTRL, 0x28 }, 1760 + { DA7219_DAI_TDM_CTRL, 0x40 }, 1761 + { DA7219_DIG_ROUTING_DAC, 0x32 }, 1762 + { DA7219_DAI_OFFSET_LOWER, 0x00 }, 1763 + { DA7219_DAI_OFFSET_UPPER, 0x00 }, 1764 + { DA7219_REFERENCES, 0x00 }, 1765 + { DA7219_MIXIN_L_SELECT, 0x00 }, 1766 + { DA7219_MIXIN_L_GAIN, 0x03 }, 1767 + { DA7219_ADC_L_GAIN, 0x6F }, 1768 + { DA7219_ADC_FILTERS1, 0x80 }, 1769 + { DA7219_MIC_1_GAIN, 0x01 }, 1770 + { DA7219_SIDETONE_CTRL, 0x40 }, 1771 + { DA7219_SIDETONE_GAIN, 0x0E }, 1772 + { DA7219_DROUTING_ST_OUTFILT_1L, 0x01 }, 1773 + { DA7219_DROUTING_ST_OUTFILT_1R, 0x02 }, 1774 + { DA7219_DAC_FILTERS5, 0x00 }, 1775 + { DA7219_DAC_FILTERS2, 0x88 }, 1776 + { DA7219_DAC_FILTERS3, 0x88 }, 1777 + { DA7219_DAC_FILTERS4, 0x08 }, 1778 + { DA7219_DAC_FILTERS1, 0x80 }, 1779 + { DA7219_DAC_L_GAIN, 0x6F }, 1780 + { DA7219_DAC_R_GAIN, 0x6F }, 1781 + { DA7219_CP_CTRL, 0x20 }, 1782 + { DA7219_HP_L_GAIN, 0x39 }, 1783 + { DA7219_HP_R_GAIN, 0x39 }, 1784 + { DA7219_MIXOUT_L_SELECT, 0x00 }, 1785 + { DA7219_MIXOUT_R_SELECT, 0x00 }, 1786 + { DA7219_MICBIAS_CTRL, 0x03 }, 1787 + { DA7219_MIC_1_CTRL, 0x40 }, 1788 + { DA7219_MIXIN_L_CTRL, 0x40 }, 1789 + { DA7219_ADC_L_CTRL, 0x40 }, 1790 + { DA7219_DAC_L_CTRL, 0x40 }, 1791 + { DA7219_DAC_R_CTRL, 0x40 }, 1792 + { DA7219_HP_L_CTRL, 0x40 }, 1793 + { DA7219_HP_R_CTRL, 0x40 }, 1794 + { DA7219_MIXOUT_L_CTRL, 0x10 }, 1795 + { DA7219_MIXOUT_R_CTRL, 0x10 }, 1796 + { DA7219_CHIP_ID1, 0x23 }, 1797 + { DA7219_CHIP_ID2, 0x93 }, 1798 + { DA7219_CHIP_REVISION, 0x00 }, 1799 + { DA7219_LDO_CTRL, 0x00 }, 1800 + { DA7219_IO_CTRL, 0x00 }, 1801 + { DA7219_GAIN_RAMP_CTRL, 0x00 }, 1802 + { DA7219_PC_COUNT, 0x02 }, 1803 + { DA7219_CP_VOL_THRESHOLD1, 0x0E }, 1804 + { DA7219_DIG_CTRL, 0x00 }, 1805 + { DA7219_ALC_CTRL2, 0x00 }, 1806 + { DA7219_ALC_CTRL3, 0x00 }, 1807 + { DA7219_ALC_NOISE, 0x3F }, 1808 + { DA7219_ALC_TARGET_MIN, 0x3F }, 1809 + { DA7219_ALC_TARGET_MAX, 0x00 }, 1810 + { DA7219_ALC_GAIN_LIMITS, 0xFF }, 1811 + { DA7219_ALC_ANA_GAIN_LIMITS, 0x71 }, 1812 + { DA7219_ALC_ANTICLIP_CTRL, 0x00 }, 1813 + { DA7219_ALC_ANTICLIP_LEVEL, 0x00 }, 1814 + { DA7219_DAC_NG_SETUP_TIME, 0x00 }, 1815 + { DA7219_DAC_NG_OFF_THRESH, 0x00 }, 1816 + { DA7219_DAC_NG_ON_THRESH, 0x00 }, 1817 + { DA7219_DAC_NG_CTRL, 0x00 }, 1818 + { DA7219_TONE_GEN_CFG1, 0x00 }, 1819 + { DA7219_TONE_GEN_CFG2, 0x00 }, 1820 + { DA7219_TONE_GEN_CYCLES, 0x00 }, 1821 + { DA7219_TONE_GEN_FREQ1_L, 0x55 }, 1822 + { DA7219_TONE_GEN_FREQ1_U, 0x15 }, 1823 + { DA7219_TONE_GEN_FREQ2_L, 0x00 }, 1824 + { DA7219_TONE_GEN_FREQ2_U, 0x40 }, 1825 + { DA7219_TONE_GEN_ON_PER, 0x02 }, 1826 + { DA7219_TONE_GEN_OFF_PER, 0x01 }, 1827 + { DA7219_ACCDET_IRQ_MASK_A, 0x00 }, 1828 + { DA7219_ACCDET_IRQ_MASK_B, 0x00 }, 1829 + { DA7219_ACCDET_CONFIG_1, 0xD6 }, 1830 + { DA7219_ACCDET_CONFIG_2, 0x34 }, 1831 + { DA7219_ACCDET_CONFIG_3, 0x0A }, 1832 + { DA7219_ACCDET_CONFIG_4, 0x16 }, 1833 + { DA7219_ACCDET_CONFIG_5, 0x21 }, 1834 + { DA7219_ACCDET_CONFIG_6, 0x3E }, 1835 + { DA7219_ACCDET_CONFIG_7, 0x01 }, 1836 + { DA7219_SYSTEM_ACTIVE, 0x00 }, 1837 + }; 1838 + 1839 + static bool da7219_volatile_register(struct device *dev, unsigned int reg) 1840 + { 1841 + switch (reg) { 1842 + case DA7219_MIC_1_GAIN_STATUS: 1843 + case DA7219_MIXIN_L_GAIN_STATUS: 1844 + case DA7219_ADC_L_GAIN_STATUS: 1845 + case DA7219_DAC_L_GAIN_STATUS: 1846 + case DA7219_DAC_R_GAIN_STATUS: 1847 + case DA7219_HP_L_GAIN_STATUS: 1848 + case DA7219_HP_R_GAIN_STATUS: 1849 + case DA7219_CIF_CTRL: 1850 + case DA7219_PLL_SRM_STS: 1851 + case DA7219_ALC_CTRL1: 1852 + case DA7219_SYSTEM_MODES_INPUT: 1853 + case DA7219_SYSTEM_MODES_OUTPUT: 1854 + case DA7219_ALC_OFFSET_AUTO_M_L: 1855 + case DA7219_ALC_OFFSET_AUTO_U_L: 1856 + case DA7219_TONE_GEN_CFG1: 1857 + case DA7219_ACCDET_STATUS_A: 1858 + case DA7219_ACCDET_STATUS_B: 1859 + case DA7219_ACCDET_IRQ_EVENT_A: 1860 + case DA7219_ACCDET_IRQ_EVENT_B: 1861 + case DA7219_ACCDET_CONFIG_8: 1862 + case DA7219_SYSTEM_STATUS: 1863 + return 1; 1864 + default: 1865 + return 0; 1866 + } 1867 + } 1868 + 1869 + static const struct regmap_config da7219_regmap_config = { 1870 + .reg_bits = 8, 1871 + .val_bits = 8, 1872 + 1873 + .max_register = DA7219_SYSTEM_ACTIVE, 1874 + .reg_defaults = da7219_reg_defaults, 1875 + .num_reg_defaults = ARRAY_SIZE(da7219_reg_defaults), 1876 + .volatile_reg = da7219_volatile_register, 1877 + .cache_type = REGCACHE_RBTREE, 1878 + }; 1879 + 1880 + 1881 + /* 1882 + * I2C layer 1883 + */ 1884 + 1885 + static int da7219_i2c_probe(struct i2c_client *i2c, 1886 + const struct i2c_device_id *id) 1887 + { 1888 + struct da7219_priv *da7219; 1889 + int ret; 1890 + 1891 + da7219 = devm_kzalloc(&i2c->dev, sizeof(struct da7219_priv), 1892 + GFP_KERNEL); 1893 + if (!da7219) 1894 + return -ENOMEM; 1895 + 1896 + i2c_set_clientdata(i2c, da7219); 1897 + 1898 + da7219->regmap = devm_regmap_init_i2c(i2c, &da7219_regmap_config); 1899 + if (IS_ERR(da7219->regmap)) { 1900 + ret = PTR_ERR(da7219->regmap); 1901 + dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); 1902 + return ret; 1903 + } 1904 + 1905 + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da7219, 1906 + &da7219_dai, 1); 1907 + if (ret < 0) { 1908 + dev_err(&i2c->dev, "Failed to register da7219 codec: %d\n", 1909 + ret); 1910 + } 1911 + return ret; 1912 + } 1913 + 1914 + static int da7219_i2c_remove(struct i2c_client *client) 1915 + { 1916 + snd_soc_unregister_codec(&client->dev); 1917 + return 0; 1918 + } 1919 + 1920 + static const struct i2c_device_id da7219_i2c_id[] = { 1921 + { "da7219", }, 1922 + { } 1923 + }; 1924 + MODULE_DEVICE_TABLE(i2c, da7219_i2c_id); 1925 + 1926 + static struct i2c_driver da7219_i2c_driver = { 1927 + .driver = { 1928 + .name = "da7219", 1929 + .of_match_table = da7219_of_match, 1930 + }, 1931 + .probe = da7219_i2c_probe, 1932 + .remove = da7219_i2c_remove, 1933 + .id_table = da7219_i2c_id, 1934 + }; 1935 + 1936 + module_i2c_driver(da7219_i2c_driver); 1937 + 1938 + MODULE_DESCRIPTION("ASoC DA7219 Codec Driver"); 1939 + MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>"); 1940 + MODULE_LICENSE("GPL");
+820
sound/soc/codecs/da7219.h
··· 1 + /* 2 + * da7219.h - DA7219 ALSA SoC Codec Driver 3 + * 4 + * Copyright (c) 2015 Dialog Semiconductor 5 + * 6 + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the 10 + * Free Software Foundation; either version 2 of the License, or (at your 11 + * option) any later version. 12 + */ 13 + 14 + #ifndef __DA7219_H 15 + #define __DA7219_H 16 + 17 + #include <linux/regmap.h> 18 + #include <linux/regulator/consumer.h> 19 + #include <sound/da7219.h> 20 + 21 + /* 22 + * Registers 23 + */ 24 + 25 + #define DA7219_MIC_1_GAIN_STATUS 0x6 26 + #define DA7219_MIXIN_L_GAIN_STATUS 0x8 27 + #define DA7219_ADC_L_GAIN_STATUS 0xA 28 + #define DA7219_DAC_L_GAIN_STATUS 0xC 29 + #define DA7219_DAC_R_GAIN_STATUS 0xD 30 + #define DA7219_HP_L_GAIN_STATUS 0xE 31 + #define DA7219_HP_R_GAIN_STATUS 0xF 32 + #define DA7219_MIC_1_SELECT 0x10 33 + #define DA7219_CIF_TIMEOUT_CTRL 0x12 34 + #define DA7219_CIF_CTRL 0x13 35 + #define DA7219_SR_24_48 0x16 36 + #define DA7219_SR 0x17 37 + #define DA7219_CIF_I2C_ADDR_CFG 0x1B 38 + #define DA7219_PLL_CTRL 0x20 39 + #define DA7219_PLL_FRAC_TOP 0x22 40 + #define DA7219_PLL_FRAC_BOT 0x23 41 + #define DA7219_PLL_INTEGER 0x24 42 + #define DA7219_PLL_SRM_STS 0x25 43 + #define DA7219_DIG_ROUTING_DAI 0x2A 44 + #define DA7219_DAI_CLK_MODE 0x2B 45 + #define DA7219_DAI_CTRL 0x2C 46 + #define DA7219_DAI_TDM_CTRL 0x2D 47 + #define DA7219_DIG_ROUTING_DAC 0x2E 48 + #define DA7219_ALC_CTRL1 0x2F 49 + #define DA7219_DAI_OFFSET_LOWER 0x30 50 + #define DA7219_DAI_OFFSET_UPPER 0x31 51 + #define DA7219_REFERENCES 0x32 52 + #define DA7219_MIXIN_L_SELECT 0x33 53 + #define DA7219_MIXIN_L_GAIN 0x34 54 + #define DA7219_ADC_L_GAIN 0x36 55 + #define DA7219_ADC_FILTERS1 0x38 56 + #define DA7219_MIC_1_GAIN 0x39 57 + #define DA7219_SIDETONE_CTRL 0x3A 58 + #define DA7219_SIDETONE_GAIN 0x3B 59 + #define DA7219_DROUTING_ST_OUTFILT_1L 0x3C 60 + #define DA7219_DROUTING_ST_OUTFILT_1R 0x3D 61 + #define DA7219_DAC_FILTERS5 0x40 62 + #define DA7219_DAC_FILTERS2 0x41 63 + #define DA7219_DAC_FILTERS3 0x42 64 + #define DA7219_DAC_FILTERS4 0x43 65 + #define DA7219_DAC_FILTERS1 0x44 66 + #define DA7219_DAC_L_GAIN 0x45 67 + #define DA7219_DAC_R_GAIN 0x46 68 + #define DA7219_CP_CTRL 0x47 69 + #define DA7219_HP_L_GAIN 0x48 70 + #define DA7219_HP_R_GAIN 0x49 71 + #define DA7219_MIXOUT_L_SELECT 0x4B 72 + #define DA7219_MIXOUT_R_SELECT 0x4C 73 + #define DA7219_SYSTEM_MODES_INPUT 0x50 74 + #define DA7219_SYSTEM_MODES_OUTPUT 0x51 75 + #define DA7219_MICBIAS_CTRL 0x62 76 + #define DA7219_MIC_1_CTRL 0x63 77 + #define DA7219_MIXIN_L_CTRL 0x65 78 + #define DA7219_ADC_L_CTRL 0x67 79 + #define DA7219_DAC_L_CTRL 0x69 80 + #define DA7219_DAC_R_CTRL 0x6A 81 + #define DA7219_HP_L_CTRL 0x6B 82 + #define DA7219_HP_R_CTRL 0x6C 83 + #define DA7219_MIXOUT_L_CTRL 0x6E 84 + #define DA7219_MIXOUT_R_CTRL 0x6F 85 + #define DA7219_CHIP_ID1 0x81 86 + #define DA7219_CHIP_ID2 0x82 87 + #define DA7219_CHIP_REVISION 0x83 88 + #define DA7219_LDO_CTRL 0x90 89 + #define DA7219_IO_CTRL 0x91 90 + #define DA7219_GAIN_RAMP_CTRL 0x92 91 + #define DA7219_PC_COUNT 0x94 92 + #define DA7219_CP_VOL_THRESHOLD1 0x95 93 + #define DA7219_CP_DELAY 0x96 94 + #define DA7219_DIG_CTRL 0x99 95 + #define DA7219_ALC_CTRL2 0x9A 96 + #define DA7219_ALC_CTRL3 0x9B 97 + #define DA7219_ALC_NOISE 0x9C 98 + #define DA7219_ALC_TARGET_MIN 0x9D 99 + #define DA7219_ALC_TARGET_MAX 0x9E 100 + #define DA7219_ALC_GAIN_LIMITS 0x9F 101 + #define DA7219_ALC_ANA_GAIN_LIMITS 0xA0 102 + #define DA7219_ALC_ANTICLIP_CTRL 0xA1 103 + #define DA7219_ALC_ANTICLIP_LEVEL 0xA2 104 + #define DA7219_ALC_OFFSET_AUTO_M_L 0xA3 105 + #define DA7219_ALC_OFFSET_AUTO_U_L 0xA4 106 + #define DA7219_DAC_NG_SETUP_TIME 0xAF 107 + #define DA7219_DAC_NG_OFF_THRESH 0xB0 108 + #define DA7219_DAC_NG_ON_THRESH 0xB1 109 + #define DA7219_DAC_NG_CTRL 0xB2 110 + #define DA7219_TONE_GEN_CFG1 0xB4 111 + #define DA7219_TONE_GEN_CFG2 0xB5 112 + #define DA7219_TONE_GEN_CYCLES 0xB6 113 + #define DA7219_TONE_GEN_FREQ1_L 0xB7 114 + #define DA7219_TONE_GEN_FREQ1_U 0xB8 115 + #define DA7219_TONE_GEN_FREQ2_L 0xB9 116 + #define DA7219_TONE_GEN_FREQ2_U 0xBA 117 + #define DA7219_TONE_GEN_ON_PER 0xBB 118 + #define DA7219_TONE_GEN_OFF_PER 0xBC 119 + #define DA7219_SYSTEM_STATUS 0xE0 120 + #define DA7219_SYSTEM_ACTIVE 0xFD 121 + 122 + 123 + /* 124 + * Bit Fields 125 + */ 126 + 127 + #define DA7219_SWITCH_EN_MAX 0x1 128 + 129 + /* DA7219_MIC_1_GAIN_STATUS = 0x6 */ 130 + #define DA7219_MIC_1_AMP_GAIN_STATUS_SHIFT 0 131 + #define DA7219_MIC_1_AMP_GAIN_STATUS_MASK (0x7 << 0) 132 + #define DA7219_MIC_1_AMP_GAIN_MAX 0x7 133 + 134 + /* DA7219_MIXIN_L_GAIN_STATUS = 0x8 */ 135 + #define DA7219_MIXIN_L_AMP_GAIN_STATUS_SHIFT 0 136 + #define DA7219_MIXIN_L_AMP_GAIN_STATUS_MASK (0xF << 0) 137 + 138 + /* DA7219_ADC_L_GAIN_STATUS = 0xA */ 139 + #define DA7219_ADC_L_DIGITAL_GAIN_STATUS_SHIFT 0 140 + #define DA7219_ADC_L_DIGITAL_GAIN_STATUS_MASK (0x7F << 0) 141 + 142 + /* DA7219_DAC_L_GAIN_STATUS = 0xC */ 143 + #define DA7219_DAC_L_DIGITAL_GAIN_STATUS_SHIFT 0 144 + #define DA7219_DAC_L_DIGITAL_GAIN_STATUS_MASK (0x7F << 0) 145 + 146 + /* DA7219_DAC_R_GAIN_STATUS = 0xD */ 147 + #define DA7219_DAC_R_DIGITAL_GAIN_STATUS_SHIFT 0 148 + #define DA7219_DAC_R_DIGITAL_GAIN_STATUS_MASK (0x7F << 0) 149 + 150 + /* DA7219_HP_L_GAIN_STATUS = 0xE */ 151 + #define DA7219_HP_L_AMP_GAIN_STATUS_SHIFT 0 152 + #define DA7219_HP_L_AMP_GAIN_STATUS_MASK (0x3F << 0) 153 + 154 + /* DA7219_HP_R_GAIN_STATUS = 0xF */ 155 + #define DA7219_HP_R_AMP_GAIN_STATUS_SHIFT 0 156 + #define DA7219_HP_R_AMP_GAIN_STATUS_MASK (0x3F << 0) 157 + 158 + /* DA7219_MIC_1_SELECT = 0x10 */ 159 + #define DA7219_MIC_1_AMP_IN_SEL_SHIFT 0 160 + #define DA7219_MIC_1_AMP_IN_SEL_MASK (0x3 << 0) 161 + 162 + /* DA7219_CIF_TIMEOUT_CTRL = 0x12 */ 163 + #define DA7219_I2C_TIMEOUT_EN_SHIFT 0 164 + #define DA7219_I2C_TIMEOUT_EN_MASK (0x1 << 0) 165 + 166 + /* DA7219_CIF_CTRL = 0x13 */ 167 + #define DA7219_CIF_I2C_WRITE_MODE_SHIFT 0 168 + #define DA7219_CIF_I2C_WRITE_MODE_MASK (0x1 << 0) 169 + #define DA7219_CIF_REG_SOFT_RESET_SHIFT 7 170 + #define DA7219_CIF_REG_SOFT_RESET_MASK (0x1 << 7) 171 + 172 + /* DA7219_SR_24_48 = 0x16 */ 173 + #define DA7219_SR_24_48_SHIFT 0 174 + #define DA7219_SR_24_48_MASK (0x1 << 0) 175 + 176 + /* DA7219_SR = 0x17 */ 177 + #define DA7219_SR_SHIFT 0 178 + #define DA7219_SR_MASK (0xF << 0) 179 + #define DA7219_SR_8000 (0x01 << 0) 180 + #define DA7219_SR_11025 (0x02 << 0) 181 + #define DA7219_SR_12000 (0x03 << 0) 182 + #define DA7219_SR_16000 (0x05 << 0) 183 + #define DA7219_SR_22050 (0x06 << 0) 184 + #define DA7219_SR_24000 (0x07 << 0) 185 + #define DA7219_SR_32000 (0x09 << 0) 186 + #define DA7219_SR_44100 (0x0A << 0) 187 + #define DA7219_SR_48000 (0x0B << 0) 188 + #define DA7219_SR_88200 (0x0E << 0) 189 + #define DA7219_SR_96000 (0x0F << 0) 190 + 191 + /* DA7219_CIF_I2C_ADDR_CFG = 0x1B */ 192 + #define DA7219_CIF_I2C_ADDR_CFG_SHIFT 0 193 + #define DA7219_CIF_I2C_ADDR_CFG_MASK (0x3 << 0) 194 + 195 + /* DA7219_PLL_CTRL = 0x20 */ 196 + #define DA7219_PLL_INDIV_SHIFT 2 197 + #define DA7219_PLL_INDIV_MASK (0x7 << 2) 198 + #define DA7219_PLL_INDIV_2_5_MHZ (0x0 << 2) 199 + #define DA7219_PLL_INDIV_5_10_MHZ (0x1 << 2) 200 + #define DA7219_PLL_INDIV_10_20_MHZ (0x2 << 2) 201 + #define DA7219_PLL_INDIV_20_40_MHZ (0x3 << 2) 202 + #define DA7219_PLL_INDIV_40_54_MHZ (0x4 << 2) 203 + #define DA7219_PLL_MCLK_SQR_EN_SHIFT 5 204 + #define DA7219_PLL_MCLK_SQR_EN_MASK (0x1 << 5) 205 + #define DA7219_PLL_MODE_SHIFT 6 206 + #define DA7219_PLL_MODE_MASK (0x3 << 6) 207 + #define DA7219_PLL_MODE_BYPASS (0x0 << 6) 208 + #define DA7219_PLL_MODE_NORMAL (0x1 << 6) 209 + #define DA7219_PLL_MODE_SRM (0x2 << 6) 210 + #define DA7219_PLL_MODE_32KHZ (0x3 << 6) 211 + 212 + /* DA7219_PLL_FRAC_TOP = 0x22 */ 213 + #define DA7219_PLL_FBDIV_FRAC_TOP_SHIFT 0 214 + #define DA7219_PLL_FBDIV_FRAC_TOP_MASK (0x1F << 0) 215 + 216 + /* DA7219_PLL_FRAC_BOT = 0x23 */ 217 + #define DA7219_PLL_FBDIV_FRAC_BOT_SHIFT 0 218 + #define DA7219_PLL_FBDIV_FRAC_BOT_MASK (0xFF << 0) 219 + 220 + /* DA7219_PLL_INTEGER = 0x24 */ 221 + #define DA7219_PLL_FBDIV_INTEGER_SHIFT 0 222 + #define DA7219_PLL_FBDIV_INTEGER_MASK (0x7F << 0) 223 + 224 + /* DA7219_PLL_SRM_STS = 0x25 */ 225 + #define DA7219_PLL_SRM_STATE_SHIFT 0 226 + #define DA7219_PLL_SRM_STATE_MASK (0xF << 0) 227 + #define DA7219_PLL_SRM_STATUS_SHIFT 4 228 + #define DA7219_PLL_SRM_STATUS_MASK (0xF << 4) 229 + #define DA7219_PLL_SRM_STS_SRM_LOCK (0x1 << 7) 230 + 231 + /* DA7219_DIG_ROUTING_DAI = 0x2A */ 232 + #define DA7219_DAI_L_SRC_SHIFT 0 233 + #define DA7219_DAI_L_SRC_MASK (0x3 << 0) 234 + #define DA7219_DAI_R_SRC_SHIFT 4 235 + #define DA7219_DAI_R_SRC_MASK (0x3 << 4) 236 + #define DA7219_OUT_SRC_MAX 4 237 + 238 + /* DA7219_DAI_CLK_MODE = 0x2B */ 239 + #define DA7219_DAI_BCLKS_PER_WCLK_SHIFT 0 240 + #define DA7219_DAI_BCLKS_PER_WCLK_MASK (0x3 << 0) 241 + #define DA7219_DAI_BCLKS_PER_WCLK_32 (0x0 << 0) 242 + #define DA7219_DAI_BCLKS_PER_WCLK_64 (0x1 << 0) 243 + #define DA7219_DAI_BCLKS_PER_WCLK_128 (0x2 << 0) 244 + #define DA7219_DAI_BCLKS_PER_WCLK_256 (0x3 << 0) 245 + #define DA7219_DAI_CLK_POL_SHIFT 2 246 + #define DA7219_DAI_CLK_POL_MASK (0x1 << 2) 247 + #define DA7219_DAI_CLK_POL_INV (0x1 << 2) 248 + #define DA7219_DAI_WCLK_POL_SHIFT 3 249 + #define DA7219_DAI_WCLK_POL_MASK (0x1 << 3) 250 + #define DA7219_DAI_WCLK_POL_INV (0x1 << 3) 251 + #define DA7219_DAI_WCLK_TRI_STATE_SHIFT 4 252 + #define DA7219_DAI_WCLK_TRI_STATE_MASK (0x1 << 4) 253 + #define DA7219_DAI_CLK_EN_SHIFT 7 254 + #define DA7219_DAI_CLK_EN_MASK (0x1 << 7) 255 + 256 + /* DA7219_DAI_CTRL = 0x2C */ 257 + #define DA7219_DAI_FORMAT_SHIFT 0 258 + #define DA7219_DAI_FORMAT_MASK (0x3 << 0) 259 + #define DA7219_DAI_FORMAT_I2S (0x0 << 0) 260 + #define DA7219_DAI_FORMAT_LEFT_J (0x1 << 0) 261 + #define DA7219_DAI_FORMAT_RIGHT_J (0x2 << 0) 262 + #define DA7219_DAI_FORMAT_DSP (0x3 << 0) 263 + #define DA7219_DAI_WORD_LENGTH_SHIFT 2 264 + #define DA7219_DAI_WORD_LENGTH_MASK (0x3 << 2) 265 + #define DA7219_DAI_WORD_LENGTH_S16_LE (0x0 << 2) 266 + #define DA7219_DAI_WORD_LENGTH_S20_LE (0x1 << 2) 267 + #define DA7219_DAI_WORD_LENGTH_S24_LE (0x2 << 2) 268 + #define DA7219_DAI_WORD_LENGTH_S32_LE (0x3 << 2) 269 + #define DA7219_DAI_CH_NUM_SHIFT 4 270 + #define DA7219_DAI_CH_NUM_MASK (0x3 << 4) 271 + #define DA7219_DAI_CH_NUM_MAX 2 272 + #define DA7219_DAI_EN_SHIFT 7 273 + #define DA7219_DAI_EN_MASK (0x1 << 7) 274 + 275 + /* DA7219_DAI_TDM_CTRL = 0x2D */ 276 + #define DA7219_DAI_TDM_CH_EN_SHIFT 0 277 + #define DA7219_DAI_TDM_CH_EN_MASK (0x3 << 0) 278 + #define DA7219_DAI_OE_SHIFT 6 279 + #define DA7219_DAI_OE_MASK (0x1 << 6) 280 + #define DA7219_DAI_TDM_MODE_EN_SHIFT 7 281 + #define DA7219_DAI_TDM_MODE_EN_MASK (0x1 << 7) 282 + #define DA7219_DAI_TDM_MAX_SLOTS 2 283 + 284 + /* DA7219_DIG_ROUTING_DAC = 0x2E */ 285 + #define DA7219_DAC_L_SRC_SHIFT 0 286 + #define DA7219_DAC_L_SRC_MASK (0x3 << 0) 287 + #define DA7219_DAC_L_SRC_TONEGEN (0x1 << 0) 288 + #define DA7219_DAC_L_MONO_SHIFT 3 289 + #define DA7219_DAC_L_MONO_MASK (0x1 << 3) 290 + #define DA7219_DAC_R_SRC_SHIFT 4 291 + #define DA7219_DAC_R_SRC_MASK (0x3 << 4) 292 + #define DA7219_DAC_R_SRC_TONEGEN (0x1 << 4) 293 + #define DA7219_DAC_R_MONO_SHIFT 7 294 + #define DA7219_DAC_R_MONO_MASK (0x1 << 7) 295 + 296 + /* DA7219_ALC_CTRL1 = 0x2F */ 297 + #define DA7219_ALC_OFFSET_EN_SHIFT 0 298 + #define DA7219_ALC_OFFSET_EN_MASK (0x1 << 0) 299 + #define DA7219_ALC_SYNC_MODE_SHIFT 1 300 + #define DA7219_ALC_SYNC_MODE_MASK (0x1 << 1) 301 + #define DA7219_ALC_EN_SHIFT 3 302 + #define DA7219_ALC_EN_MASK (0x1 << 3) 303 + #define DA7219_ALC_AUTO_CALIB_EN_SHIFT 4 304 + #define DA7219_ALC_AUTO_CALIB_EN_MASK (0x1 << 4) 305 + #define DA7219_ALC_CALIB_OVERFLOW_SHIFT 5 306 + #define DA7219_ALC_CALIB_OVERFLOW_MASK (0x1 << 5) 307 + 308 + /* DA7219_DAI_OFFSET_LOWER = 0x30 */ 309 + #define DA7219_DAI_OFFSET_LOWER_SHIFT 0 310 + #define DA7219_DAI_OFFSET_LOWER_MASK (0xFF << 0) 311 + 312 + /* DA7219_DAI_OFFSET_UPPER = 0x31 */ 313 + #define DA7219_DAI_OFFSET_UPPER_SHIFT 0 314 + #define DA7219_DAI_OFFSET_UPPER_MASK (0x7 << 0) 315 + #define DA7219_DAI_OFFSET_MAX 0x2FF 316 + 317 + /* DA7219_REFERENCES = 0x32 */ 318 + #define DA7219_BIAS_EN_SHIFT 3 319 + #define DA7219_BIAS_EN_MASK (0x1 << 3) 320 + #define DA7219_VMID_FAST_CHARGE_SHIFT 4 321 + #define DA7219_VMID_FAST_CHARGE_MASK (0x1 << 4) 322 + 323 + /* DA7219_MIXIN_L_SELECT = 0x33 */ 324 + #define DA7219_MIXIN_L_MIX_SELECT_SHIFT 0 325 + #define DA7219_MIXIN_L_MIX_SELECT_MASK (0x1 << 0) 326 + 327 + /* DA7219_MIXIN_L_GAIN = 0x34 */ 328 + #define DA7219_MIXIN_L_AMP_GAIN_SHIFT 0 329 + #define DA7219_MIXIN_L_AMP_GAIN_MASK (0xF << 0) 330 + #define DA7219_MIXIN_L_AMP_GAIN_MAX 0xF 331 + 332 + /* DA7219_ADC_L_GAIN = 0x36 */ 333 + #define DA7219_ADC_L_DIGITAL_GAIN_SHIFT 0 334 + #define DA7219_ADC_L_DIGITAL_GAIN_MASK (0x7F << 0) 335 + #define DA7219_ADC_L_DIGITAL_GAIN_MAX 0x7F 336 + 337 + /* DA7219_ADC_FILTERS1 = 0x38 */ 338 + #define DA7219_ADC_VOICE_HPF_CORNER_SHIFT 0 339 + #define DA7219_ADC_VOICE_HPF_CORNER_MASK (0x7 << 0) 340 + #define DA7219_VOICE_HPF_CORNER_MAX 8 341 + #define DA7219_ADC_VOICE_EN_SHIFT 3 342 + #define DA7219_ADC_VOICE_EN_MASK (0x1 << 3) 343 + #define DA7219_ADC_AUDIO_HPF_CORNER_SHIFT 4 344 + #define DA7219_ADC_AUDIO_HPF_CORNER_MASK (0x3 << 4) 345 + #define DA7219_AUDIO_HPF_CORNER_MAX 4 346 + #define DA7219_ADC_HPF_EN_SHIFT 7 347 + #define DA7219_ADC_HPF_EN_MASK (0x1 << 7) 348 + #define DA7219_HPF_MODE_SHIFT 0 349 + #define DA7219_HPF_DISABLED ((0x0 << 3) | (0x0 << 7)) 350 + #define DA7219_HPF_AUDIO_EN ((0x0 << 3) | (0x1 << 7)) 351 + #define DA7219_HPF_VOICE_EN ((0x1 << 3) | (0x1 << 7)) 352 + #define DA7219_HPF_MODE_MASK ((0x1 << 3) | (0x1 << 7)) 353 + #define DA7219_HPF_MODE_MAX 3 354 + 355 + /* DA7219_MIC_1_GAIN = 0x39 */ 356 + #define DA7219_MIC_1_AMP_GAIN_SHIFT 0 357 + #define DA7219_MIC_1_AMP_GAIN_MASK (0x7 << 0) 358 + 359 + /* DA7219_SIDETONE_CTRL = 0x3A */ 360 + #define DA7219_SIDETONE_MUTE_EN_SHIFT 6 361 + #define DA7219_SIDETONE_MUTE_EN_MASK (0x1 << 6) 362 + #define DA7219_SIDETONE_EN_SHIFT 7 363 + #define DA7219_SIDETONE_EN_MASK (0x1 << 7) 364 + 365 + /* DA7219_SIDETONE_GAIN = 0x3B */ 366 + #define DA7219_SIDETONE_GAIN_SHIFT 0 367 + #define DA7219_SIDETONE_GAIN_MASK (0xF << 0) 368 + #define DA7219_SIDETONE_GAIN_MAX 0xE 369 + 370 + /* DA7219_DROUTING_ST_OUTFILT_1L = 0x3C */ 371 + #define DA7219_OUTFILT_ST_1L_SRC_SHIFT 0 372 + #define DA7219_OUTFILT_ST_1L_SRC_MASK (0x7 << 0) 373 + #define DA7219_DMIX_ST_SRC_OUTFILT1L_SHIFT 0 374 + #define DA7219_DMIX_ST_SRC_OUTFILT1R_SHIFT 1 375 + #define DA7219_DMIX_ST_SRC_SIDETONE_SHIFT 2 376 + #define DA7219_DMIX_ST_SRC_OUTFILT1L (0x1 << 0) 377 + #define DA7219_DMIX_ST_SRC_OUTFILT1R (0x1 << 1) 378 + 379 + /* DA7219_DROUTING_ST_OUTFILT_1R = 0x3D */ 380 + #define DA7219_OUTFILT_ST_1R_SRC_SHIFT 0 381 + #define DA7219_OUTFILT_ST_1R_SRC_MASK (0x7 << 0) 382 + 383 + /* DA7219_DAC_FILTERS5 = 0x40 */ 384 + #define DA7219_DAC_SOFTMUTE_RATE_SHIFT 4 385 + #define DA7219_DAC_SOFTMUTE_RATE_MASK (0x7 << 4) 386 + #define DA7219_DAC_SOFTMUTE_RATE_MAX 7 387 + #define DA7219_DAC_SOFTMUTE_EN_SHIFT 7 388 + #define DA7219_DAC_SOFTMUTE_EN_MASK (0x1 << 7) 389 + 390 + /* DA7219_DAC_FILTERS2 = 0x41 */ 391 + #define DA7219_DAC_EQ_BAND1_SHIFT 0 392 + #define DA7219_DAC_EQ_BAND1_MASK (0xF << 0) 393 + #define DA7219_DAC_EQ_BAND2_SHIFT 4 394 + #define DA7219_DAC_EQ_BAND2_MASK (0xF << 4) 395 + #define DA7219_DAC_EQ_BAND_MAX 0xF 396 + 397 + /* DA7219_DAC_FILTERS3 = 0x42 */ 398 + #define DA7219_DAC_EQ_BAND3_SHIFT 0 399 + #define DA7219_DAC_EQ_BAND3_MASK (0xF << 0) 400 + #define DA7219_DAC_EQ_BAND4_SHIFT 4 401 + #define DA7219_DAC_EQ_BAND4_MASK (0xF << 4) 402 + 403 + /* DA7219_DAC_FILTERS4 = 0x43 */ 404 + #define DA7219_DAC_EQ_BAND5_SHIFT 0 405 + #define DA7219_DAC_EQ_BAND5_MASK (0xF << 0) 406 + #define DA7219_DAC_EQ_EN_SHIFT 7 407 + #define DA7219_DAC_EQ_EN_MASK (0x1 << 7) 408 + 409 + /* DA7219_DAC_FILTERS1 = 0x44 */ 410 + #define DA7219_DAC_VOICE_HPF_CORNER_SHIFT 0 411 + #define DA7219_DAC_VOICE_HPF_CORNER_MASK (0x7 << 0) 412 + #define DA7219_DAC_VOICE_EN_SHIFT 3 413 + #define DA7219_DAC_VOICE_EN_MASK (0x1 << 3) 414 + #define DA7219_DAC_AUDIO_HPF_CORNER_SHIFT 4 415 + #define DA7219_DAC_AUDIO_HPF_CORNER_MASK (0x3 << 4) 416 + #define DA7219_DAC_HPF_EN_SHIFT 7 417 + #define DA7219_DAC_HPF_EN_MASK (0x1 << 7) 418 + 419 + /* DA7219_DAC_L_GAIN = 0x45 */ 420 + #define DA7219_DAC_L_DIGITAL_GAIN_SHIFT 0 421 + #define DA7219_DAC_L_DIGITAL_GAIN_MASK (0x7F << 0) 422 + #define DA7219_DAC_DIGITAL_GAIN_MAX 0x7F 423 + #define DA7219_DAC_DIGITAL_GAIN_0DB (0x6F << 0) 424 + 425 + /* DA7219_DAC_R_GAIN = 0x46 */ 426 + #define DA7219_DAC_R_DIGITAL_GAIN_SHIFT 0 427 + #define DA7219_DAC_R_DIGITAL_GAIN_MASK (0x7F << 0) 428 + 429 + /* DA7219_CP_CTRL = 0x47 */ 430 + #define DA7219_CP_MCHANGE_SHIFT 4 431 + #define DA7219_CP_MCHANGE_MASK (0x3 << 4) 432 + #define DA7219_CP_MCHANGE_REL_MASK 0x3 433 + #define DA7219_CP_MCHANGE_MAX 3 434 + #define DA7219_CP_MCHANGE_LARGEST_VOL 0x1 435 + #define DA7219_CP_MCHANGE_DAC_VOL 0x2 436 + #define DA7219_CP_MCHANGE_SIG_MAG 0x3 437 + #define DA7219_CP_EN_SHIFT 7 438 + #define DA7219_CP_EN_MASK (0x1 << 7) 439 + 440 + /* DA7219_HP_L_GAIN = 0x48 */ 441 + #define DA7219_HP_L_AMP_GAIN_SHIFT 0 442 + #define DA7219_HP_L_AMP_GAIN_MASK (0x3F << 0) 443 + #define DA7219_HP_AMP_GAIN_MAX 0x3F 444 + #define DA7219_HP_AMP_GAIN_0DB (0x39 << 0) 445 + 446 + /* DA7219_HP_R_GAIN = 0x49 */ 447 + #define DA7219_HP_R_AMP_GAIN_SHIFT 0 448 + #define DA7219_HP_R_AMP_GAIN_MASK (0x3F << 0) 449 + 450 + /* DA7219_MIXOUT_L_SELECT = 0x4B */ 451 + #define DA7219_MIXOUT_L_MIX_SELECT_SHIFT 0 452 + #define DA7219_MIXOUT_L_MIX_SELECT_MASK (0x1 << 0) 453 + 454 + /* DA7219_MIXOUT_R_SELECT = 0x4C */ 455 + #define DA7219_MIXOUT_R_MIX_SELECT_SHIFT 0 456 + #define DA7219_MIXOUT_R_MIX_SELECT_MASK (0x1 << 0) 457 + 458 + /* DA7219_SYSTEM_MODES_INPUT = 0x50 */ 459 + #define DA7219_MODE_SUBMIT_SHIFT 0 460 + #define DA7219_MODE_SUBMIT_MASK (0x1 << 0) 461 + #define DA7219_ADC_MODE_SHIFT 1 462 + #define DA7219_ADC_MODE_MASK (0x7F << 1) 463 + 464 + /* DA7219_SYSTEM_MODES_OUTPUT = 0x51 */ 465 + #define DA7219_MODE_SUBMIT_SHIFT 0 466 + #define DA7219_MODE_SUBMIT_MASK (0x1 << 0) 467 + #define DA7219_DAC_MODE_SHIFT 1 468 + #define DA7219_DAC_MODE_MASK (0x7F << 1) 469 + 470 + /* DA7219_MICBIAS_CTRL = 0x62 */ 471 + #define DA7219_MICBIAS1_LEVEL_SHIFT 0 472 + #define DA7219_MICBIAS1_LEVEL_MASK (0x7 << 0) 473 + #define DA7219_MICBIAS1_EN_SHIFT 3 474 + #define DA7219_MICBIAS1_EN_MASK (0x1 << 3) 475 + 476 + /* DA7219_MIC_1_CTRL = 0x63 */ 477 + #define DA7219_MIC_1_AMP_RAMP_EN_SHIFT 5 478 + #define DA7219_MIC_1_AMP_RAMP_EN_MASK (0x1 << 5) 479 + #define DA7219_MIC_1_AMP_MUTE_EN_SHIFT 6 480 + #define DA7219_MIC_1_AMP_MUTE_EN_MASK (0x1 << 6) 481 + #define DA7219_MIC_1_AMP_EN_SHIFT 7 482 + #define DA7219_MIC_1_AMP_EN_MASK (0x1 << 7) 483 + 484 + /* DA7219_MIXIN_L_CTRL = 0x65 */ 485 + #define DA7219_MIXIN_L_MIX_EN_SHIFT 3 486 + #define DA7219_MIXIN_L_MIX_EN_MASK (0x1 << 3) 487 + #define DA7219_MIXIN_L_AMP_ZC_EN_SHIFT 4 488 + #define DA7219_MIXIN_L_AMP_ZC_EN_MASK (0x1 << 4) 489 + #define DA7219_MIXIN_L_AMP_RAMP_EN_SHIFT 5 490 + #define DA7219_MIXIN_L_AMP_RAMP_EN_MASK (0x1 << 5) 491 + #define DA7219_MIXIN_L_AMP_MUTE_EN_SHIFT 6 492 + #define DA7219_MIXIN_L_AMP_MUTE_EN_MASK (0x1 << 6) 493 + #define DA7219_MIXIN_L_AMP_EN_SHIFT 7 494 + #define DA7219_MIXIN_L_AMP_EN_MASK (0x1 << 7) 495 + 496 + /* DA7219_ADC_L_CTRL = 0x67 */ 497 + #define DA7219_ADC_L_BIAS_SHIFT 0 498 + #define DA7219_ADC_L_BIAS_MASK (0x3 << 0) 499 + #define DA7219_ADC_L_RAMP_EN_SHIFT 5 500 + #define DA7219_ADC_L_RAMP_EN_MASK (0x1 << 5) 501 + #define DA7219_ADC_L_MUTE_EN_SHIFT 6 502 + #define DA7219_ADC_L_MUTE_EN_MASK (0x1 << 6) 503 + #define DA7219_ADC_L_EN_SHIFT 7 504 + #define DA7219_ADC_L_EN_MASK (0x1 << 7) 505 + 506 + /* DA7219_DAC_L_CTRL = 0x69 */ 507 + #define DA7219_DAC_L_RAMP_EN_SHIFT 5 508 + #define DA7219_DAC_L_RAMP_EN_MASK (0x1 << 5) 509 + #define DA7219_DAC_L_MUTE_EN_SHIFT 6 510 + #define DA7219_DAC_L_MUTE_EN_MASK (0x1 << 6) 511 + #define DA7219_DAC_L_EN_SHIFT 7 512 + #define DA7219_DAC_L_EN_MASK (0x1 << 7) 513 + 514 + /* DA7219_DAC_R_CTRL = 0x6A */ 515 + #define DA7219_DAC_R_RAMP_EN_SHIFT 5 516 + #define DA7219_DAC_R_RAMP_EN_MASK (0x1 << 5) 517 + #define DA7219_DAC_R_MUTE_EN_SHIFT 6 518 + #define DA7219_DAC_R_MUTE_EN_MASK (0x1 << 6) 519 + #define DA7219_DAC_R_EN_SHIFT 7 520 + #define DA7219_DAC_R_EN_MASK (0x1 << 7) 521 + 522 + /* DA7219_HP_L_CTRL = 0x6B */ 523 + #define DA7219_HP_L_AMP_MIN_GAIN_EN_SHIFT 2 524 + #define DA7219_HP_L_AMP_MIN_GAIN_EN_MASK (0x1 << 2) 525 + #define DA7219_HP_L_AMP_OE_SHIFT 3 526 + #define DA7219_HP_L_AMP_OE_MASK (0x1 << 3) 527 + #define DA7219_HP_L_AMP_ZC_EN_SHIFT 4 528 + #define DA7219_HP_L_AMP_ZC_EN_MASK (0x1 << 4) 529 + #define DA7219_HP_L_AMP_RAMP_EN_SHIFT 5 530 + #define DA7219_HP_L_AMP_RAMP_EN_MASK (0x1 << 5) 531 + #define DA7219_HP_L_AMP_MUTE_EN_SHIFT 6 532 + #define DA7219_HP_L_AMP_MUTE_EN_MASK (0x1 << 6) 533 + #define DA7219_HP_L_AMP_EN_SHIFT 7 534 + #define DA7219_HP_L_AMP_EN_MASK (0x1 << 7) 535 + 536 + /* DA7219_HP_R_CTRL = 0x6C */ 537 + #define DA7219_HP_R_AMP_MIN_GAIN_EN_SHIFT 2 538 + #define DA7219_HP_R_AMP_MIN_GAIN_EN_MASK (0x1 << 2) 539 + #define DA7219_HP_R_AMP_OE_SHIFT 3 540 + #define DA7219_HP_R_AMP_OE_MASK (0x1 << 3) 541 + #define DA7219_HP_R_AMP_ZC_EN_SHIFT 4 542 + #define DA7219_HP_R_AMP_ZC_EN_MASK (0x1 << 4) 543 + #define DA7219_HP_R_AMP_RAMP_EN_SHIFT 5 544 + #define DA7219_HP_R_AMP_RAMP_EN_MASK (0x1 << 5) 545 + #define DA7219_HP_R_AMP_MUTE_EN_SHIFT 6 546 + #define DA7219_HP_R_AMP_MUTE_EN_MASK (0x1 << 6) 547 + #define DA7219_HP_R_AMP_EN_SHIFT 7 548 + #define DA7219_HP_R_AMP_EN_MASK (0x1 << 7) 549 + 550 + /* DA7219_MIXOUT_L_CTRL = 0x6E */ 551 + #define DA7219_MIXOUT_L_AMP_EN_SHIFT 7 552 + #define DA7219_MIXOUT_L_AMP_EN_MASK (0x1 << 7) 553 + 554 + /* DA7219_MIXOUT_R_CTRL = 0x6F */ 555 + #define DA7219_MIXOUT_R_AMP_EN_SHIFT 7 556 + #define DA7219_MIXOUT_R_AMP_EN_MASK (0x1 << 7) 557 + 558 + /* DA7219_CHIP_ID1 = 0x81 */ 559 + #define DA7219_CHIP_ID1_SHIFT 0 560 + #define DA7219_CHIP_ID1_MASK (0xFF << 0) 561 + 562 + /* DA7219_CHIP_ID2 = 0x82 */ 563 + #define DA7219_CHIP_ID2_SHIFT 0 564 + #define DA7219_CHIP_ID2_MASK (0xFF << 0) 565 + 566 + /* DA7219_CHIP_REVISION = 0x83 */ 567 + #define DA7219_CHIP_MINOR_SHIFT 0 568 + #define DA7219_CHIP_MINOR_MASK (0xF << 0) 569 + #define DA7219_CHIP_MAJOR_SHIFT 4 570 + #define DA7219_CHIP_MAJOR_MASK (0xF << 4) 571 + 572 + /* DA7219_LDO_CTRL = 0x90 */ 573 + #define DA7219_LDO_LEVEL_SELECT_SHIFT 4 574 + #define DA7219_LDO_LEVEL_SELECT_MASK (0x3 << 4) 575 + #define DA7219_LDO_EN_SHIFT 7 576 + #define DA7219_LDO_EN_MASK (0x1 << 7) 577 + 578 + /* DA7219_IO_CTRL = 0x91 */ 579 + #define DA7219_IO_VOLTAGE_LEVEL_SHIFT 0 580 + #define DA7219_IO_VOLTAGE_LEVEL_MASK (0x1 << 0) 581 + #define DA7219_IO_VOLTAGE_LEVEL_2_5V_3_6V 0 582 + #define DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V 1 583 + 584 + /* DA7219_GAIN_RAMP_CTRL = 0x92 */ 585 + #define DA7219_GAIN_RAMP_RATE_SHIFT 0 586 + #define DA7219_GAIN_RAMP_RATE_MASK (0x3 << 0) 587 + #define DA7219_GAIN_RAMP_RATE_MAX 4 588 + 589 + /* DA7219_PC_COUNT = 0x94 */ 590 + #define DA7219_PC_FREERUN_SHIFT 0 591 + #define DA7219_PC_FREERUN_MASK (0x1 << 0) 592 + #define DA7219_PC_RESYNC_AUTO_SHIFT 1 593 + #define DA7219_PC_RESYNC_AUTO_MASK (0x1 << 1) 594 + 595 + /* DA7219_CP_VOL_THRESHOLD1 = 0x95 */ 596 + #define DA7219_CP_THRESH_VDD2_SHIFT 0 597 + #define DA7219_CP_THRESH_VDD2_MASK (0x3F << 0) 598 + #define DA7219_CP_THRESH_VDD2_MAX 0x3F 599 + 600 + /* DA7219_DIG_CTRL = 0x99 */ 601 + #define DA7219_DAC_L_INV_SHIFT 3 602 + #define DA7219_DAC_L_INV_MASK (0x1 << 3) 603 + #define DA7219_DAC_R_INV_SHIFT 7 604 + #define DA7219_DAC_R_INV_MASK (0x1 << 7) 605 + 606 + /* DA7219_ALC_CTRL2 = 0x9A */ 607 + #define DA7219_ALC_ATTACK_SHIFT 0 608 + #define DA7219_ALC_ATTACK_MASK (0xF << 0) 609 + #define DA7219_ALC_ATTACK_MAX 13 610 + #define DA7219_ALC_RELEASE_SHIFT 4 611 + #define DA7219_ALC_RELEASE_MASK (0xF << 4) 612 + #define DA7219_ALC_RELEASE_MAX 11 613 + 614 + /* DA7219_ALC_CTRL3 = 0x9B */ 615 + #define DA7219_ALC_HOLD_SHIFT 0 616 + #define DA7219_ALC_HOLD_MASK (0xF << 0) 617 + #define DA7219_ALC_HOLD_MAX 16 618 + #define DA7219_ALC_INTEG_ATTACK_SHIFT 4 619 + #define DA7219_ALC_INTEG_ATTACK_MASK (0x3 << 4) 620 + #define DA7219_ALC_INTEG_RELEASE_SHIFT 6 621 + #define DA7219_ALC_INTEG_RELEASE_MASK (0x3 << 6) 622 + #define DA7219_ALC_INTEG_MAX 4 623 + 624 + /* DA7219_ALC_NOISE = 0x9C */ 625 + #define DA7219_ALC_NOISE_SHIFT 0 626 + #define DA7219_ALC_NOISE_MASK (0x3F << 0) 627 + #define DA7219_ALC_THRESHOLD_MAX 0x3F 628 + 629 + /* DA7219_ALC_TARGET_MIN = 0x9D */ 630 + #define DA7219_ALC_THRESHOLD_MIN_SHIFT 0 631 + #define DA7219_ALC_THRESHOLD_MIN_MASK (0x3F << 0) 632 + 633 + /* DA7219_ALC_TARGET_MAX = 0x9E */ 634 + #define DA7219_ALC_THRESHOLD_MAX_SHIFT 0 635 + #define DA7219_ALC_THRESHOLD_MAX_MASK (0x3F << 0) 636 + 637 + /* DA7219_ALC_GAIN_LIMITS = 0x9F */ 638 + #define DA7219_ALC_ATTEN_MAX_SHIFT 0 639 + #define DA7219_ALC_ATTEN_MAX_MASK (0xF << 0) 640 + #define DA7219_ALC_GAIN_MAX_SHIFT 4 641 + #define DA7219_ALC_GAIN_MAX_MASK (0xF << 4) 642 + #define DA7219_ALC_ATTEN_GAIN_MAX 0xF 643 + 644 + /* DA7219_ALC_ANA_GAIN_LIMITS = 0xA0 */ 645 + #define DA7219_ALC_ANA_GAIN_MIN_SHIFT 0 646 + #define DA7219_ALC_ANA_GAIN_MIN_MASK (0x7 << 0) 647 + #define DA7219_ALC_ANA_GAIN_MIN 0x1 648 + #define DA7219_ALC_ANA_GAIN_MAX_SHIFT 4 649 + #define DA7219_ALC_ANA_GAIN_MAX_MASK (0x7 << 4) 650 + #define DA7219_ALC_ANA_GAIN_MAX 0x7 651 + 652 + /* DA7219_ALC_ANTICLIP_CTRL = 0xA1 */ 653 + #define DA7219_ALC_ANTICLIP_STEP_SHIFT 0 654 + #define DA7219_ALC_ANTICLIP_STEP_MASK (0x3 << 0) 655 + #define DA7219_ALC_ANTICLIP_STEP_MAX 4 656 + #define DA7219_ALC_ANTIPCLIP_EN_SHIFT 7 657 + #define DA7219_ALC_ANTIPCLIP_EN_MASK (0x1 << 7) 658 + 659 + /* DA7219_ALC_ANTICLIP_LEVEL = 0xA2 */ 660 + #define DA7219_ALC_ANTICLIP_LEVEL_SHIFT 0 661 + #define DA7219_ALC_ANTICLIP_LEVEL_MASK (0x7F << 0) 662 + 663 + /* DA7219_ALC_OFFSET_AUTO_M_L = 0xA3 */ 664 + #define DA7219_ALC_OFFSET_AUTO_M_L_SHIFT 0 665 + #define DA7219_ALC_OFFSET_AUTO_M_L_MASK (0xFF << 0) 666 + 667 + /* DA7219_ALC_OFFSET_AUTO_U_L = 0xA4 */ 668 + #define DA7219_ALC_OFFSET_AUTO_U_L_SHIFT 0 669 + #define DA7219_ALC_OFFSET_AUTO_U_L_MASK (0xF << 0) 670 + 671 + /* DA7219_DAC_NG_SETUP_TIME = 0xAF */ 672 + #define DA7219_DAC_NG_SETUP_TIME_SHIFT 0 673 + #define DA7219_DAC_NG_SETUP_TIME_MASK (0x3 << 0) 674 + #define DA7219_DAC_NG_SETUP_TIME_MAX 4 675 + #define DA7219_DAC_NG_RAMPUP_RATE_SHIFT 2 676 + #define DA7219_DAC_NG_RAMPUP_RATE_MASK (0x1 << 2) 677 + #define DA7219_DAC_NG_RAMPDN_RATE_SHIFT 3 678 + #define DA7219_DAC_NG_RAMPDN_RATE_MASK (0x1 << 3) 679 + #define DA7219_DAC_NG_RAMP_RATE_MAX 2 680 + 681 + /* DA7219_DAC_NG_OFF_THRESH = 0xB0 */ 682 + #define DA7219_DAC_NG_OFF_THRESHOLD_SHIFT 0 683 + #define DA7219_DAC_NG_OFF_THRESHOLD_MASK (0x7 << 0) 684 + #define DA7219_DAC_NG_THRESHOLD_MAX 0x7 685 + 686 + /* DA7219_DAC_NG_ON_THRESH = 0xB1 */ 687 + #define DA7219_DAC_NG_ON_THRESHOLD_SHIFT 0 688 + #define DA7219_DAC_NG_ON_THRESHOLD_MASK (0x7 << 0) 689 + 690 + /* DA7219_DAC_NG_CTRL = 0xB2 */ 691 + #define DA7219_DAC_NG_EN_SHIFT 7 692 + #define DA7219_DAC_NG_EN_MASK (0x1 << 7) 693 + 694 + /* DA7219_TONE_GEN_CFG1 = 0xB4 */ 695 + #define DA7219_DTMF_REG_SHIFT 0 696 + #define DA7219_DTMF_REG_MASK (0xF << 0) 697 + #define DA7219_DTMF_REG_MAX 16 698 + #define DA7219_DTMF_EN_SHIFT 4 699 + #define DA7219_DTMF_EN_MASK (0x1 << 4) 700 + #define DA7219_START_STOPN_SHIFT 7 701 + #define DA7219_START_STOPN_MASK (0x1 << 7) 702 + 703 + /* DA7219_TONE_GEN_CFG2 = 0xB5 */ 704 + #define DA7219_SWG_SEL_SHIFT 0 705 + #define DA7219_SWG_SEL_MASK (0x3 << 0) 706 + #define DA7219_SWG_SEL_MAX 4 707 + #define DA7219_SWG_SEL_SRAMP (0x3 << 0) 708 + #define DA7219_TONE_GEN_GAIN_SHIFT 4 709 + #define DA7219_TONE_GEN_GAIN_MASK (0xF << 4) 710 + #define DA7219_TONE_GEN_GAIN_MAX 0xF 711 + #define DA7219_TONE_GEN_GAIN_MINUS_9DB (0x3 << 4) 712 + #define DA7219_TONE_GEN_GAIN_MINUS_15DB (0x5 << 4) 713 + 714 + /* DA7219_TONE_GEN_CYCLES = 0xB6 */ 715 + #define DA7219_BEEP_CYCLES_SHIFT 0 716 + #define DA7219_BEEP_CYCLES_MASK (0x7 << 0) 717 + 718 + /* DA7219_TONE_GEN_FREQ1_L = 0xB7 */ 719 + #define DA7219_FREQ1_L_SHIFT 0 720 + #define DA7219_FREQ1_L_MASK (0xFF << 0) 721 + #define DA7219_FREQ_MAX 0xFFFF 722 + 723 + /* DA7219_TONE_GEN_FREQ1_U = 0xB8 */ 724 + #define DA7219_FREQ1_U_SHIFT 0 725 + #define DA7219_FREQ1_U_MASK (0xFF << 0) 726 + 727 + /* DA7219_TONE_GEN_FREQ2_L = 0xB9 */ 728 + #define DA7219_FREQ2_L_SHIFT 0 729 + #define DA7219_FREQ2_L_MASK (0xFF << 0) 730 + 731 + /* DA7219_TONE_GEN_FREQ2_U = 0xBA */ 732 + #define DA7219_FREQ2_U_SHIFT 0 733 + #define DA7219_FREQ2_U_MASK (0xFF << 0) 734 + 735 + /* DA7219_TONE_GEN_ON_PER = 0xBB */ 736 + #define DA7219_BEEP_ON_PER_SHIFT 0 737 + #define DA7219_BEEP_ON_PER_MASK (0x3F << 0) 738 + #define DA7219_BEEP_ON_OFF_MAX 0x3F 739 + 740 + /* DA7219_TONE_GEN_OFF_PER = 0xBC */ 741 + #define DA7219_BEEP_OFF_PER_SHIFT 0 742 + #define DA7219_BEEP_OFF_PER_MASK (0x3F << 0) 743 + 744 + /* DA7219_SYSTEM_STATUS = 0xE0 */ 745 + #define DA7219_SC1_BUSY_SHIFT 0 746 + #define DA7219_SC1_BUSY_MASK (0x1 << 0) 747 + #define DA7219_SC2_BUSY_SHIFT 1 748 + #define DA7219_SC2_BUSY_MASK (0x1 << 1) 749 + 750 + /* DA7219_SYSTEM_ACTIVE = 0xFD */ 751 + #define DA7219_SYSTEM_ACTIVE_SHIFT 0 752 + #define DA7219_SYSTEM_ACTIVE_MASK (0x1 << 0) 753 + 754 + 755 + /* 756 + * General defines & data 757 + */ 758 + 759 + /* Register inversion */ 760 + #define DA7219_NO_INVERT 0 761 + #define DA7219_INVERT 1 762 + 763 + /* Byte related defines */ 764 + #define DA7219_BYTE_SHIFT 8 765 + #define DA7219_BYTE_MASK 0xFF 766 + 767 + /* PLL Output Frequencies */ 768 + #define DA7219_PLL_FREQ_OUT_90316 90316800 769 + #define DA7219_PLL_FREQ_OUT_98304 98304000 770 + 771 + /* PLL Frequency Dividers */ 772 + #define DA7219_PLL_INDIV_2_5_MHZ_VAL 1 773 + #define DA7219_PLL_INDIV_5_10_MHZ_VAL 2 774 + #define DA7219_PLL_INDIV_10_20_MHZ_VAL 4 775 + #define DA7219_PLL_INDIV_20_40_MHZ_VAL 8 776 + #define DA7219_PLL_INDIV_40_54_MHZ_VAL 16 777 + 778 + /* SRM */ 779 + #define DA7219_SRM_CHECK_RETRIES 8 780 + 781 + enum da7219_clk_src { 782 + DA7219_CLKSRC_MCLK = 0, 783 + DA7219_CLKSRC_MCLK_SQR, 784 + }; 785 + 786 + enum da7219_sys_clk { 787 + DA7219_SYSCLK_MCLK = 0, 788 + DA7219_SYSCLK_PLL, 789 + DA7219_SYSCLK_PLL_SRM, 790 + DA7219_SYSCLK_PLL_32KHZ 791 + }; 792 + 793 + /* Regulators */ 794 + enum da7219_supplies { 795 + DA7219_SUPPLY_VDD = 0, 796 + DA7219_SUPPLY_VDDMIC, 797 + DA7219_SUPPLY_VDDIO, 798 + DA7219_NUM_SUPPLIES, 799 + }; 800 + 801 + struct da7219_aad_priv; 802 + 803 + /* Private data */ 804 + struct da7219_priv { 805 + struct da7219_aad_priv *aad; 806 + struct da7219_pdata *pdata; 807 + 808 + struct regulator_bulk_data supplies[DA7219_NUM_SUPPLIES]; 809 + struct regmap *regmap; 810 + struct mutex lock; 811 + 812 + struct clk *mclk; 813 + unsigned int mclk_rate; 814 + int clk_src; 815 + 816 + bool master; 817 + bool alc_en; 818 + }; 819 + 820 + #endif /* __DA7219_H */