diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2014-03-19 19:00:44 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2014-03-19 19:00:43 -0700 |
| commit | c424d7b2835be3d3bf7debd44eaad1f3d70ac29c (patch) | |
| tree | a152b85291fbf436cc35a963e1633a6c5bf15c91 | |
| parent | b8c3cd1e9fba9d27aec07a9b58d8c551d7cccd16 (diff) | |
| parent | 00108816a480a272235abbf65490e3bd53e9ed04 (diff) | |
Merge "ASoC: wcd9330: Add support for plug insertion/removal detection"
| -rw-r--r-- | sound/soc/codecs/wcd9330.c | 29 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd9xxx-mbhc.c | 117 | ||||
| -rw-r--r-- | sound/soc/codecs/wcd9xxx-mbhc.h | 3 |
3 files changed, 107 insertions, 42 deletions
diff --git a/sound/soc/codecs/wcd9330.c b/sound/soc/codecs/wcd9330.c index 64956f9430c..c06474917ae 100644 --- a/sound/soc/codecs/wcd9330.c +++ b/sound/soc/codecs/wcd9330.c @@ -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; @@ -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 = { diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c index 0cf6130edbf..59902098050 100644 --- a/sound/soc/codecs/wcd9xxx-mbhc.c +++ b/sound/soc/codecs/wcd9xxx-mbhc.c @@ -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); @@ -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); @@ -701,7 +701,7 @@ static void wcd9xxx_clr_and_turnon_hph_padac(struct wcd9xxx_mbhc *mbhc) struct snd_soc_codec *codec = mbhc->codec; u8 wg_time; - wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) ; + wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME); wg_time += 1; if (test_and_clear_bit(WCD9XXX_HPHR_DAC_OFF_ACK, @@ -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); } } @@ -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) @@ -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, @@ -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); @@ -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); - wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, - WCD9XXX_CLK_RCO); - WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr); + 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 { - WCD9XXX_BG_CLK_LOCK(mbhc->resmgr); - wcd9xxx_resmgr_put_clk_block(mbhc->resmgr, - WCD9XXX_CLK_RCO); + 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); @@ -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 */ - WCD9XXX_BG_CLK_LOCK(mbhc->resmgr); - wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO); - WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr); + 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); - 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); + 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); } @@ -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) @@ -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) @@ -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) - return snd_soc_read(mbhc->codec, + 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; @@ -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); @@ -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); @@ -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, @@ -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; } @@ -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) @@ -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 & @@ -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); @@ -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 @@ -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 */ @@ -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. */ @@ -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); @@ -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; diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h index b287b435fd5..024fdcacbea 100644 --- a/sound/soc/codecs/wcd9xxx-mbhc.h +++ b/sound/soc/codecs/wcd9xxx-mbhc.h @@ -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 { |
