container_of(work, struct da7219_aad_priv, btn_det_work);
struct snd_soc_component *component = da7219_aad->component;
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+ struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
u8 statusa, micbias_ctrl;
bool micbias_up = false;
int retries = 0;
if (retries >= DA7219_AAD_MICBIAS_CHK_RETRIES)
dev_warn(component->dev, "Mic bias status check timed out");
+ da7219->micbias_on_event = true;
+
/*
* Mic bias pulse required to enable mic, must be done before enabling
* button detection to prevent erroneous button readings.
snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
DA7219_BUTTON_CONFIG_MASK, 0);
+ da7219->micbias_on_event = false;
+
/* Disable mic bias */
snd_soc_dapm_disable_pin(dapm, "Mic Bias");
snd_soc_dapm_sync(dapm);
* DAPM Events
*/
+static int da7219_mic_pga_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+ struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ if (da7219->micbias_on_event) {
+ /*
+ * Delay only for first capture after bias enabled to
+ * avoid possible DC offset related noise.
+ */
+ da7219->micbias_on_event = false;
+ msleep(da7219->mic_pga_delay);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
static int da7219_dai_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
SND_SOC_DAPM_INPUT("MIC"),
/* Input PGAs */
- SND_SOC_DAPM_PGA("Mic PGA", DA7219_MIC_1_CTRL,
- DA7219_MIC_1_AMP_EN_SHIFT, DA7219_NO_INVERT,
- NULL, 0),
- SND_SOC_DAPM_PGA("Mixin PGA", DA7219_MIXIN_L_CTRL,
- DA7219_MIXIN_L_AMP_EN_SHIFT, DA7219_NO_INVERT,
- NULL, 0),
+ SND_SOC_DAPM_PGA_E("Mic PGA", DA7219_MIC_1_CTRL,
+ DA7219_MIC_1_AMP_EN_SHIFT, DA7219_NO_INVERT,
+ NULL, 0, da7219_mic_pga_event, SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_E("Mixin PGA", DA7219_MIXIN_L_CTRL,
+ DA7219_MIXIN_L_AMP_EN_SHIFT, DA7219_NO_INVERT,
+ NULL, 0, da7219_settling_event, SND_SOC_DAPM_POST_PMU),
/* Input Filters */
SND_SOC_DAPM_ADC("ADC", NULL, DA7219_ADC_L_CTRL, DA7219_ADC_L_EN_SHIFT,
snd_soc_component_write(component, DA7219_MICBIAS_CTRL, micbias_lvl);
+ /*
+ * Calculate delay required to compensate for DC offset in
+ * Mic PGA, based on Mic Bias voltage.
+ */
+ da7219->mic_pga_delay = DA7219_MIC_PGA_BASE_DELAY +
+ (pdata->micbias_lvl *
+ DA7219_MIC_PGA_OFFSET_DELAY);
+
/* Mic */
switch (pdata->mic_amp_in_sel) {
case DA7219_MIC_AMP_IN_SEL_DIFF:
#define DA7219_SYS_STAT_CHECK_DELAY 50
/* Power up/down Delays */
-#define DA7219_SETTLING_DELAY 40
-#define DA7219_MIN_GAIN_DELAY 30
+#define DA7219_SETTLING_DELAY 40
+#define DA7219_MIN_GAIN_DELAY 30
+#define DA7219_MIC_PGA_BASE_DELAY 100
+#define DA7219_MIC_PGA_OFFSET_DELAY 40
enum da7219_clk_src {
DA7219_CLKSRC_MCLK = 0,
bool master;
bool alc_en;
+ bool micbias_on_event;
+ unsigned int mic_pga_delay;
u8 gain_ramp_ctrl;
};