Loading sound/soc/codecs/wcd9330.c +27 −2 Original line number Diff line number Diff line Loading @@ -3230,8 +3230,8 @@ static int tomtom_hphl_dac_event(struct snd_soc_dapm_widget *w, if (!ret) wcd9xxx_clsh_imped_config(codec, impedl); else dev_err(codec->dev, "Failed to get mbhc impedance %d\n", ret); dev_dbg(codec->dev, "%s: Failed to get mbhc impedance %d\n", __func__, ret); break; case SND_SOC_DAPM_POST_PMD: break; Loading Loading @@ -6793,10 +6793,35 @@ static enum wcd9xxx_cdc_type tomtom_get_cdc_type(void) return WCD9XXX_CDC_TYPE_TOMTOM; } static bool tomtom_mbhc_ins_rem_status(struct snd_soc_codec *codec) { return snd_soc_read(codec, WCD9XXX_A_MBHC_INSERT_DET_STATUS) & (1 << 1); } static void tomtom_mbhc_micb_pulldown_ctrl(struct wcd9xxx_mbhc *mbhc, bool enable) { struct snd_soc_codec *codec = mbhc->codec; if (!enable) { /* Remove automatic pulldown on micbias */ snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x01, 0x00); } else { /* Enable automatic pulldown on micbias */ snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x01, 0x01); } } static const struct wcd9xxx_mbhc_cb mbhc_cb = { .get_cdc_type = tomtom_get_cdc_type, .setup_zdet = tomtom_setup_zdet, .compute_impedance = tomtom_compute_impedance, .insert_rem_status = tomtom_mbhc_ins_rem_status, .micbias_pulldown_ctrl = tomtom_mbhc_micb_pulldown_ctrl, .codec_rco_ctrl = tomtom_codec_internal_rco_ctrl, }; static const struct wcd9xxx_mbhc_intr cdc_intr_ids = { Loading sound/soc/codecs/wcd9xxx-mbhc.c +77 −40 Original line number Diff line number Diff line Loading @@ -306,11 +306,11 @@ static bool __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc, if (d->micb_mv != VDDIO_MICBIAS_MV) { cfilt_k_val = __wcd9xxx_resmgr_get_k_val(mbhc, VDDIO_MICBIAS_MV); usleep_range(10000, 10000); usleep_range(10000, 10100); snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_val, 0xFC, (cfilt_k_val << 2)); usleep_range(10000, 10000); usleep_range(10000, 10100); /* Threshods for insertion/removal */ snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B1_CTL, d->v_ins_hu[MBHC_V_IDX_VDDIO] & 0xFF); Loading Loading @@ -371,7 +371,7 @@ static bool __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc, snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_val, 0xFC, (cfilt_k_val << 2)); usleep_range(10000, 10000); usleep_range(10000, 10100); /* Revert threshods for insertion/removal */ snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B1_CTL, d->v_ins_hu[MBHC_V_IDX_CFILT] & 0xFF); Loading Loading @@ -735,7 +735,7 @@ static void wcd9xxx_clr_and_turnon_hph_padac(struct wcd9xxx_mbhc *mbhc) if (pa_turned_on) { pr_debug("%s: PA was turned off by MBHC and not by DAPM\n", __func__); usleep_range(wg_time * 1000, wg_time * 1000); usleep_range(wg_time * 1000, wg_time * 1000 + 50); } } Loading Loading @@ -796,7 +796,7 @@ static void wcd9xxx_set_and_turnoff_hph_padac(struct wcd9xxx_mbhc *mbhc) snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30, 0x00); snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_L_DAC_CTL, 0x80, 0x00); snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xC0, 0x00); usleep_range(wg_time * 1000, wg_time * 1000); usleep_range(wg_time * 1000, wg_time * 1000 + 50); } static void wcd9xxx_insert_detect_setup(struct wcd9xxx_mbhc *mbhc, bool ins) Loading Loading @@ -1036,9 +1036,9 @@ static short __wcd9xxx_codec_sta_dce(struct wcd9xxx_mbhc *mbhc, int dce, snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x2); usleep_range(mbhc->mbhc_data.t_sta_dce, mbhc->mbhc_data.t_sta_dce); mbhc->mbhc_data.t_sta_dce + 50); snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x4); usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce); usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce + 50); bias_value = wcd9xxx_read_dce_result(codec); } else { snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8, Loading @@ -1050,10 +1050,10 @@ static short __wcd9xxx_codec_sta_dce(struct wcd9xxx_mbhc *mbhc, int dce, snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x2); usleep_range(mbhc->mbhc_data.t_sta_dce, mbhc->mbhc_data.t_sta_dce); mbhc->mbhc_data.t_sta_dce + 50); snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2); usleep_range(mbhc->mbhc_data.t_sta, mbhc->mbhc_data.t_sta); mbhc->mbhc_data.t_sta + 50); bias_value = wcd9xxx_read_sta_result(codec); snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8, 0x8); Loading Loading @@ -1120,13 +1120,23 @@ static void wcd9xxx_mbhc_ctrl_clk_bandgap(struct wcd9xxx_mbhc *mbhc, WCD9XXX_BG_CLK_LOCK(mbhc->resmgr); wcd9xxx_resmgr_get_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE); if (mbhc->mbhc_cb && mbhc->mbhc_cb->codec_rco_ctrl) { WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr); mbhc->mbhc_cb->codec_rco_ctrl(mbhc->codec, true); } else { wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO); WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr); } } else { if (mbhc->mbhc_cb && mbhc->mbhc_cb->codec_rco_ctrl) { mbhc->mbhc_cb->codec_rco_ctrl(mbhc->codec, false); WCD9XXX_BG_CLK_LOCK(mbhc->resmgr); } else { WCD9XXX_BG_CLK_LOCK(mbhc->resmgr); wcd9xxx_resmgr_put_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO); } wcd9xxx_resmgr_put_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE); WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr); Loading Loading @@ -1268,23 +1278,31 @@ static void wcd9xxx_shutdown_hs_removal_detect(struct wcd9xxx_mbhc *mbhc) WCD9XXX_MBHC_CAL_GENERAL_PTR(mbhc->mbhc_cfg->calibration); /* Need MBHC clock */ if (mbhc->mbhc_cb && mbhc->mbhc_cb->codec_rco_ctrl) mbhc->mbhc_cb->codec_rco_ctrl(mbhc->codec, true); else { WCD9XXX_BG_CLK_LOCK(mbhc->resmgr); wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO); WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr); } snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x2); snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x6, 0x0); __wcd9xxx_switch_micbias(mbhc, 0, false, false); usleep_range(generic->t_shutdown_plug_rem, generic->t_shutdown_plug_rem); generic->t_shutdown_plug_rem + 50); snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xA, 0x8); if (mbhc->mbhc_cb && mbhc->mbhc_cb->codec_rco_ctrl) mbhc->mbhc_cb->codec_rco_ctrl(mbhc->codec, false); else { WCD9XXX_BG_CLK_LOCK(mbhc->resmgr); /* Put requested CLK back */ wcd9xxx_resmgr_put_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO); WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr); } snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x00); } Loading Loading @@ -1312,7 +1330,7 @@ static void wcd9xxx_codec_hphr_gnd_switch(struct snd_soc_codec *codec, bool on) { snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x01, on); if (on) usleep_range(5000, 5000); usleep_range(5000, 5100); } static void wcd9xxx_onoff_vddio_switch(struct wcd9xxx_mbhc *mbhc, bool on) Loading Loading @@ -1342,7 +1360,7 @@ exit: * when the micbias to vddio switch is enabled. */ if (on) usleep_range(10000, 10000); usleep_range(10000, 10100); } static int wcd9xxx_hphl_status(struct wcd9xxx_mbhc *mbhc) Loading Loading @@ -1912,11 +1930,14 @@ static bool wcd9xxx_swch_level_remove(struct wcd9xxx_mbhc *mbhc) if (mbhc->mbhc_cfg->gpio) return (gpio_get_value_cansleep(mbhc->mbhc_cfg->gpio) != mbhc->mbhc_cfg->gpio_level_insert); else if (mbhc->mbhc_cfg->insert_detect) else if (mbhc->mbhc_cfg->insert_detect) { if (mbhc->mbhc_cb && mbhc->mbhc_cb->insert_rem_status) return mbhc->mbhc_cb->insert_rem_status(mbhc->codec); else return snd_soc_read(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DET_STATUS) & (1 << 2); else } else WARN(1, "Invalid jack detection configuration\n"); return true; Loading Loading @@ -1978,7 +1999,8 @@ static int wcd9xxx_enable_hs_detect(struct wcd9xxx_mbhc *mbhc, snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x80, 0x80); usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid); usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid + WCD9XXX_USLEEP_RANGE_MARGIN_US); snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01, 0x00); Loading @@ -2001,7 +2023,8 @@ static int wcd9xxx_enable_hs_detect(struct wcd9xxx_mbhc *mbhc, plug_det->mic_current << 5); snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x80, 0x80); usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid); usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid + WCD9XXX_USLEEP_RANGE_MARGIN_US); snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x10, 0x10); Loading @@ -2017,7 +2040,8 @@ static int wcd9xxx_enable_hs_detect(struct wcd9xxx_mbhc *mbhc, snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x06, 0); usleep_range(generic->t_shutdown_plug_rem, generic->t_shutdown_plug_rem); generic->t_shutdown_plug_rem + WCD9XXX_USLEEP_RANGE_MARGIN_US); wcd9xxx_resmgr_enable_config_mode(mbhc->resmgr, 0); } else snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, Loading @@ -2030,7 +2054,8 @@ static int wcd9xxx_enable_hs_detect(struct wcd9xxx_mbhc *mbhc, if (!(snd_soc_read(codec, WCD9XXX_A_PIN_CTL_OE1) & 1)) { snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE1, 0x3, 0x3); usleep_range(generic->t_bg_fast_settle, generic->t_bg_fast_settle); generic->t_bg_fast_settle + WCD9XXX_USLEEP_RANGE_MARGIN_US); central_bias_enabled = 1; } Loading @@ -2038,7 +2063,8 @@ static int wcd9xxx_enable_hs_detect(struct wcd9xxx_mbhc *mbhc, if (snd_soc_read(codec, WCD9XXX_A_PIN_CTL_OE0) & 0x80) { snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE0, 0x10, 0); snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE0, 0x80, 0x80); usleep_range(generic->t_ldoh, generic->t_ldoh); usleep_range(generic->t_ldoh, generic->t_ldoh + WCD9XXX_USLEEP_RANGE_MARGIN_US); snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE0, 0x80, 0); if (central_bias_enabled) Loading Loading @@ -2584,7 +2610,8 @@ static void wcd9xxx_hs_remove_irq_noswch(struct wcd9xxx_mbhc *mbhc) } usleep_range(generic->t_shutdown_plug_rem, generic->t_shutdown_plug_rem); generic->t_shutdown_plug_rem + WCD9XXX_USLEEP_RANGE_MARGIN_US); /* If micbias is enabled, don't enable current source */ cs_enable = (((mbhc->mbhc_cfg->cs_enable_flags & Loading Loading @@ -3163,7 +3190,8 @@ static void wcd9xxx_swch_irq_handler(struct wcd9xxx_mbhc *mbhc) mbhc->in_swch_irq_handler = true; /* Wait here for debounce time */ usleep_range(SWCH_IRQ_DEBOUNCE_TIME_US, SWCH_IRQ_DEBOUNCE_TIME_US); usleep_range(SWCH_IRQ_DEBOUNCE_TIME_US, SWCH_IRQ_DEBOUNCE_TIME_US + WCD9XXX_USLEEP_RANGE_MARGIN_US); WCD9XXX_BCL_LOCK(mbhc->resmgr); Loading Loading @@ -3883,6 +3911,9 @@ static void wcd9xxx_mbhc_cal(struct wcd9xxx_mbhc *mbhc) snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00); if (mbhc->mbhc_cb && mbhc->mbhc_cb->micbias_pulldown_ctrl) mbhc->mbhc_cb->micbias_pulldown_ctrl(mbhc, false); /* * Micbias, CFILT, LDOH, MBHC MUX mode settings * to perform ADC calibration Loading Loading @@ -3962,7 +3993,8 @@ static void wcd9xxx_mbhc_cal(struct wcd9xxx_mbhc *mbhc) */ msleep(WCD9XXX_MUX_SWITCH_READY_WAIT_MS); snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x04); usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce); usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce + WCD9XXX_USLEEP_RANGE_MARGIN_US); mbhc->mbhc_data.dce_mb = wcd9xxx_read_dce_result(codec); /* STA Measurement for MB Voltage */ Loading @@ -3981,7 +4013,8 @@ static void wcd9xxx_mbhc_cal(struct wcd9xxx_mbhc *mbhc) */ msleep(WCD9XXX_MUX_SWITCH_READY_WAIT_MS); snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x02); usleep_range(mbhc->mbhc_data.t_sta, mbhc->mbhc_data.t_sta); usleep_range(mbhc->mbhc_data.t_sta, mbhc->mbhc_data.t_sta + WCD9XXX_USLEEP_RANGE_MARGIN_US); mbhc->mbhc_data.sta_mb = wcd9xxx_read_sta_result(codec); /* Restore default settings. */ Loading @@ -3993,11 +4026,14 @@ static void wcd9xxx_mbhc_cal(struct wcd9xxx_mbhc *mbhc) else snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x80, 0x80); usleep_range(100, 100); usleep_range(100, 110); if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mb_source) mbhc->mbhc_cb->enable_mb_source(codec, false, false); if (mbhc->mbhc_cb && mbhc->mbhc_cb->micbias_pulldown_ctrl) mbhc->mbhc_cb->micbias_pulldown_ctrl(mbhc, true); wcd9xxx_enable_irq(mbhc->resmgr->core_res, mbhc->intr_ids->dce_est_complete); wcd9xxx_turn_onoff_rel_detection(codec, true); Loading Loading @@ -4172,7 +4208,8 @@ static void wcd9xxx_mbhc_fw_read(struct work_struct *work) codec->dev); if (ret != 0) { usleep_range(FW_READ_TIMEOUT, FW_READ_TIMEOUT); usleep_range(FW_READ_TIMEOUT, FW_READ_TIMEOUT + WCD9XXX_USLEEP_RANGE_MARGIN_US); } else { pr_info("%s: MBHC Firmware read succesful\n", __func__); break; Loading sound/soc/codecs/wcd9xxx-mbhc.h +3 −0 Original line number Diff line number Diff line Loading @@ -285,6 +285,9 @@ struct wcd9xxx_mbhc_cb { int (*enable_mb_source) (struct snd_soc_codec *, bool, bool); void (*setup_int_rbias) (struct snd_soc_codec *, bool); void (*pull_mb_to_vddio) (struct snd_soc_codec *, bool); bool (*insert_rem_status) (struct snd_soc_codec *); void (*micbias_pulldown_ctrl) (struct wcd9xxx_mbhc *, bool); int (*codec_rco_ctrl) (struct snd_soc_codec *, bool); }; struct wcd9xxx_mbhc { Loading Loading
sound/soc/codecs/wcd9330.c +27 −2 Original line number Diff line number Diff line Loading @@ -3230,8 +3230,8 @@ static int tomtom_hphl_dac_event(struct snd_soc_dapm_widget *w, if (!ret) wcd9xxx_clsh_imped_config(codec, impedl); else dev_err(codec->dev, "Failed to get mbhc impedance %d\n", ret); dev_dbg(codec->dev, "%s: Failed to get mbhc impedance %d\n", __func__, ret); break; case SND_SOC_DAPM_POST_PMD: break; Loading Loading @@ -6793,10 +6793,35 @@ static enum wcd9xxx_cdc_type tomtom_get_cdc_type(void) return WCD9XXX_CDC_TYPE_TOMTOM; } static bool tomtom_mbhc_ins_rem_status(struct snd_soc_codec *codec) { return snd_soc_read(codec, WCD9XXX_A_MBHC_INSERT_DET_STATUS) & (1 << 1); } static void tomtom_mbhc_micb_pulldown_ctrl(struct wcd9xxx_mbhc *mbhc, bool enable) { struct snd_soc_codec *codec = mbhc->codec; if (!enable) { /* Remove automatic pulldown on micbias */ snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x01, 0x00); } else { /* Enable automatic pulldown on micbias */ snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x01, 0x01); } } static const struct wcd9xxx_mbhc_cb mbhc_cb = { .get_cdc_type = tomtom_get_cdc_type, .setup_zdet = tomtom_setup_zdet, .compute_impedance = tomtom_compute_impedance, .insert_rem_status = tomtom_mbhc_ins_rem_status, .micbias_pulldown_ctrl = tomtom_mbhc_micb_pulldown_ctrl, .codec_rco_ctrl = tomtom_codec_internal_rco_ctrl, }; static const struct wcd9xxx_mbhc_intr cdc_intr_ids = { Loading
sound/soc/codecs/wcd9xxx-mbhc.c +77 −40 Original line number Diff line number Diff line Loading @@ -306,11 +306,11 @@ static bool __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc, if (d->micb_mv != VDDIO_MICBIAS_MV) { cfilt_k_val = __wcd9xxx_resmgr_get_k_val(mbhc, VDDIO_MICBIAS_MV); usleep_range(10000, 10000); usleep_range(10000, 10100); snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_val, 0xFC, (cfilt_k_val << 2)); usleep_range(10000, 10000); usleep_range(10000, 10100); /* Threshods for insertion/removal */ snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B1_CTL, d->v_ins_hu[MBHC_V_IDX_VDDIO] & 0xFF); Loading Loading @@ -371,7 +371,7 @@ static bool __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc, snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_val, 0xFC, (cfilt_k_val << 2)); usleep_range(10000, 10000); usleep_range(10000, 10100); /* Revert threshods for insertion/removal */ snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B1_CTL, d->v_ins_hu[MBHC_V_IDX_CFILT] & 0xFF); Loading Loading @@ -735,7 +735,7 @@ static void wcd9xxx_clr_and_turnon_hph_padac(struct wcd9xxx_mbhc *mbhc) if (pa_turned_on) { pr_debug("%s: PA was turned off by MBHC and not by DAPM\n", __func__); usleep_range(wg_time * 1000, wg_time * 1000); usleep_range(wg_time * 1000, wg_time * 1000 + 50); } } Loading Loading @@ -796,7 +796,7 @@ static void wcd9xxx_set_and_turnoff_hph_padac(struct wcd9xxx_mbhc *mbhc) snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30, 0x00); snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_L_DAC_CTL, 0x80, 0x00); snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xC0, 0x00); usleep_range(wg_time * 1000, wg_time * 1000); usleep_range(wg_time * 1000, wg_time * 1000 + 50); } static void wcd9xxx_insert_detect_setup(struct wcd9xxx_mbhc *mbhc, bool ins) Loading Loading @@ -1036,9 +1036,9 @@ static short __wcd9xxx_codec_sta_dce(struct wcd9xxx_mbhc *mbhc, int dce, snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x2); usleep_range(mbhc->mbhc_data.t_sta_dce, mbhc->mbhc_data.t_sta_dce); mbhc->mbhc_data.t_sta_dce + 50); snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x4); usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce); usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce + 50); bias_value = wcd9xxx_read_dce_result(codec); } else { snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8, Loading @@ -1050,10 +1050,10 @@ static short __wcd9xxx_codec_sta_dce(struct wcd9xxx_mbhc *mbhc, int dce, snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x2); usleep_range(mbhc->mbhc_data.t_sta_dce, mbhc->mbhc_data.t_sta_dce); mbhc->mbhc_data.t_sta_dce + 50); snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2); usleep_range(mbhc->mbhc_data.t_sta, mbhc->mbhc_data.t_sta); mbhc->mbhc_data.t_sta + 50); bias_value = wcd9xxx_read_sta_result(codec); snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8, 0x8); Loading Loading @@ -1120,13 +1120,23 @@ static void wcd9xxx_mbhc_ctrl_clk_bandgap(struct wcd9xxx_mbhc *mbhc, WCD9XXX_BG_CLK_LOCK(mbhc->resmgr); wcd9xxx_resmgr_get_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE); if (mbhc->mbhc_cb && mbhc->mbhc_cb->codec_rco_ctrl) { WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr); mbhc->mbhc_cb->codec_rco_ctrl(mbhc->codec, true); } else { wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO); WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr); } } else { if (mbhc->mbhc_cb && mbhc->mbhc_cb->codec_rco_ctrl) { mbhc->mbhc_cb->codec_rco_ctrl(mbhc->codec, false); WCD9XXX_BG_CLK_LOCK(mbhc->resmgr); } else { WCD9XXX_BG_CLK_LOCK(mbhc->resmgr); wcd9xxx_resmgr_put_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO); } wcd9xxx_resmgr_put_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE); WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr); Loading Loading @@ -1268,23 +1278,31 @@ static void wcd9xxx_shutdown_hs_removal_detect(struct wcd9xxx_mbhc *mbhc) WCD9XXX_MBHC_CAL_GENERAL_PTR(mbhc->mbhc_cfg->calibration); /* Need MBHC clock */ if (mbhc->mbhc_cb && mbhc->mbhc_cb->codec_rco_ctrl) mbhc->mbhc_cb->codec_rco_ctrl(mbhc->codec, true); else { WCD9XXX_BG_CLK_LOCK(mbhc->resmgr); wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO); WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr); } snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x2); snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x6, 0x0); __wcd9xxx_switch_micbias(mbhc, 0, false, false); usleep_range(generic->t_shutdown_plug_rem, generic->t_shutdown_plug_rem); generic->t_shutdown_plug_rem + 50); snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xA, 0x8); if (mbhc->mbhc_cb && mbhc->mbhc_cb->codec_rco_ctrl) mbhc->mbhc_cb->codec_rco_ctrl(mbhc->codec, false); else { WCD9XXX_BG_CLK_LOCK(mbhc->resmgr); /* Put requested CLK back */ wcd9xxx_resmgr_put_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO); WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr); } snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x00); } Loading Loading @@ -1312,7 +1330,7 @@ static void wcd9xxx_codec_hphr_gnd_switch(struct snd_soc_codec *codec, bool on) { snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x01, on); if (on) usleep_range(5000, 5000); usleep_range(5000, 5100); } static void wcd9xxx_onoff_vddio_switch(struct wcd9xxx_mbhc *mbhc, bool on) Loading Loading @@ -1342,7 +1360,7 @@ exit: * when the micbias to vddio switch is enabled. */ if (on) usleep_range(10000, 10000); usleep_range(10000, 10100); } static int wcd9xxx_hphl_status(struct wcd9xxx_mbhc *mbhc) Loading Loading @@ -1912,11 +1930,14 @@ static bool wcd9xxx_swch_level_remove(struct wcd9xxx_mbhc *mbhc) if (mbhc->mbhc_cfg->gpio) return (gpio_get_value_cansleep(mbhc->mbhc_cfg->gpio) != mbhc->mbhc_cfg->gpio_level_insert); else if (mbhc->mbhc_cfg->insert_detect) else if (mbhc->mbhc_cfg->insert_detect) { if (mbhc->mbhc_cb && mbhc->mbhc_cb->insert_rem_status) return mbhc->mbhc_cb->insert_rem_status(mbhc->codec); else return snd_soc_read(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DET_STATUS) & (1 << 2); else } else WARN(1, "Invalid jack detection configuration\n"); return true; Loading Loading @@ -1978,7 +1999,8 @@ static int wcd9xxx_enable_hs_detect(struct wcd9xxx_mbhc *mbhc, snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x80, 0x80); usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid); usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid + WCD9XXX_USLEEP_RANGE_MARGIN_US); snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01, 0x00); Loading @@ -2001,7 +2023,8 @@ static int wcd9xxx_enable_hs_detect(struct wcd9xxx_mbhc *mbhc, plug_det->mic_current << 5); snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x80, 0x80); usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid); usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid + WCD9XXX_USLEEP_RANGE_MARGIN_US); snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x10, 0x10); Loading @@ -2017,7 +2040,8 @@ static int wcd9xxx_enable_hs_detect(struct wcd9xxx_mbhc *mbhc, snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x06, 0); usleep_range(generic->t_shutdown_plug_rem, generic->t_shutdown_plug_rem); generic->t_shutdown_plug_rem + WCD9XXX_USLEEP_RANGE_MARGIN_US); wcd9xxx_resmgr_enable_config_mode(mbhc->resmgr, 0); } else snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, Loading @@ -2030,7 +2054,8 @@ static int wcd9xxx_enable_hs_detect(struct wcd9xxx_mbhc *mbhc, if (!(snd_soc_read(codec, WCD9XXX_A_PIN_CTL_OE1) & 1)) { snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE1, 0x3, 0x3); usleep_range(generic->t_bg_fast_settle, generic->t_bg_fast_settle); generic->t_bg_fast_settle + WCD9XXX_USLEEP_RANGE_MARGIN_US); central_bias_enabled = 1; } Loading @@ -2038,7 +2063,8 @@ static int wcd9xxx_enable_hs_detect(struct wcd9xxx_mbhc *mbhc, if (snd_soc_read(codec, WCD9XXX_A_PIN_CTL_OE0) & 0x80) { snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE0, 0x10, 0); snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE0, 0x80, 0x80); usleep_range(generic->t_ldoh, generic->t_ldoh); usleep_range(generic->t_ldoh, generic->t_ldoh + WCD9XXX_USLEEP_RANGE_MARGIN_US); snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE0, 0x80, 0); if (central_bias_enabled) Loading Loading @@ -2584,7 +2610,8 @@ static void wcd9xxx_hs_remove_irq_noswch(struct wcd9xxx_mbhc *mbhc) } usleep_range(generic->t_shutdown_plug_rem, generic->t_shutdown_plug_rem); generic->t_shutdown_plug_rem + WCD9XXX_USLEEP_RANGE_MARGIN_US); /* If micbias is enabled, don't enable current source */ cs_enable = (((mbhc->mbhc_cfg->cs_enable_flags & Loading Loading @@ -3163,7 +3190,8 @@ static void wcd9xxx_swch_irq_handler(struct wcd9xxx_mbhc *mbhc) mbhc->in_swch_irq_handler = true; /* Wait here for debounce time */ usleep_range(SWCH_IRQ_DEBOUNCE_TIME_US, SWCH_IRQ_DEBOUNCE_TIME_US); usleep_range(SWCH_IRQ_DEBOUNCE_TIME_US, SWCH_IRQ_DEBOUNCE_TIME_US + WCD9XXX_USLEEP_RANGE_MARGIN_US); WCD9XXX_BCL_LOCK(mbhc->resmgr); Loading Loading @@ -3883,6 +3911,9 @@ static void wcd9xxx_mbhc_cal(struct wcd9xxx_mbhc *mbhc) snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00); if (mbhc->mbhc_cb && mbhc->mbhc_cb->micbias_pulldown_ctrl) mbhc->mbhc_cb->micbias_pulldown_ctrl(mbhc, false); /* * Micbias, CFILT, LDOH, MBHC MUX mode settings * to perform ADC calibration Loading Loading @@ -3962,7 +3993,8 @@ static void wcd9xxx_mbhc_cal(struct wcd9xxx_mbhc *mbhc) */ msleep(WCD9XXX_MUX_SWITCH_READY_WAIT_MS); snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x04); usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce); usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce + WCD9XXX_USLEEP_RANGE_MARGIN_US); mbhc->mbhc_data.dce_mb = wcd9xxx_read_dce_result(codec); /* STA Measurement for MB Voltage */ Loading @@ -3981,7 +4013,8 @@ static void wcd9xxx_mbhc_cal(struct wcd9xxx_mbhc *mbhc) */ msleep(WCD9XXX_MUX_SWITCH_READY_WAIT_MS); snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x02); usleep_range(mbhc->mbhc_data.t_sta, mbhc->mbhc_data.t_sta); usleep_range(mbhc->mbhc_data.t_sta, mbhc->mbhc_data.t_sta + WCD9XXX_USLEEP_RANGE_MARGIN_US); mbhc->mbhc_data.sta_mb = wcd9xxx_read_sta_result(codec); /* Restore default settings. */ Loading @@ -3993,11 +4026,14 @@ static void wcd9xxx_mbhc_cal(struct wcd9xxx_mbhc *mbhc) else snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x80, 0x80); usleep_range(100, 100); usleep_range(100, 110); if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mb_source) mbhc->mbhc_cb->enable_mb_source(codec, false, false); if (mbhc->mbhc_cb && mbhc->mbhc_cb->micbias_pulldown_ctrl) mbhc->mbhc_cb->micbias_pulldown_ctrl(mbhc, true); wcd9xxx_enable_irq(mbhc->resmgr->core_res, mbhc->intr_ids->dce_est_complete); wcd9xxx_turn_onoff_rel_detection(codec, true); Loading Loading @@ -4172,7 +4208,8 @@ static void wcd9xxx_mbhc_fw_read(struct work_struct *work) codec->dev); if (ret != 0) { usleep_range(FW_READ_TIMEOUT, FW_READ_TIMEOUT); usleep_range(FW_READ_TIMEOUT, FW_READ_TIMEOUT + WCD9XXX_USLEEP_RANGE_MARGIN_US); } else { pr_info("%s: MBHC Firmware read succesful\n", __func__); break; Loading
sound/soc/codecs/wcd9xxx-mbhc.h +3 −0 Original line number Diff line number Diff line Loading @@ -285,6 +285,9 @@ struct wcd9xxx_mbhc_cb { int (*enable_mb_source) (struct snd_soc_codec *, bool, bool); void (*setup_int_rbias) (struct snd_soc_codec *, bool); void (*pull_mb_to_vddio) (struct snd_soc_codec *, bool); bool (*insert_rem_status) (struct snd_soc_codec *); void (*micbias_pulldown_ctrl) (struct wcd9xxx_mbhc *, bool); int (*codec_rco_ctrl) (struct snd_soc_codec *, bool); }; struct wcd9xxx_mbhc { Loading