Revert "Merge "Revert "ASoC: wcd9310: Fix headset detect..."" into msm-3.0"
This reverts commit 7646faf1a40035956809b4e6c54eb66fc0acc24e, reversing
changes made to 98b77c0f2f46ae9182169051c74c990ea80e5c5d.
Change-Id: Id088ae9d36c3a0084ae49468ad0ff26c3c8fb135
Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org>
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index e636bb7..a2b8797 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -208,7 +208,8 @@
};
enum tabla_mbhc_plug_type {
- PLUG_TYPE_NONE = 0,
+ PLUG_TYPE_INVALID = -1,
+ PLUG_TYPE_NONE,
PLUG_TYPE_HEADSET,
PLUG_TYPE_HEADPHONE,
PLUG_TYPE_HIGH_HPH,
@@ -308,11 +309,6 @@
*/
struct mutex codec_resource_lock;
- /* Used to override the rule "invalid headset
- * when microphone voltage is too high"
- */
- bool mbhc_inval_hs_range_override;
-
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_poke;
struct dentry *debugfs_mbhc;
@@ -2408,14 +2404,17 @@
int vddio_switch, bool restartpolling,
bool checkpolling)
{
- struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
int cfilt_k_val;
+ bool override;
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
if (vddio_switch && !tabla->mbhc_micbias_switched &&
(!checkpolling || tabla->mbhc_polling_active)) {
if (restartpolling)
tabla_codec_pause_hs_polling(codec);
- tabla_turn_onoff_override(codec, true);
+ override = snd_soc_read(codec, TABLA_A_CDC_MBHC_B1_CTL) & 0x04;
+ if (!override)
+ tabla_turn_onoff_override(codec, true);
/* Adjust threshold if Mic Bias voltage changes */
if (tabla->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
cfilt_k_val = tabla_find_k_value(
@@ -2440,7 +2439,8 @@
0x80, 0x80);
snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg,
0x10, 0x00);
- tabla_turn_onoff_override(codec, false);
+ if (!override)
+ tabla_turn_onoff_override(codec, false);
if (restartpolling)
tabla_codec_start_hs_polling(codec);
@@ -5807,7 +5807,7 @@
}
static bool tabla_is_invalid_insertion_range(struct snd_soc_codec *codec,
- s32 mic_volt)
+ s32 mic_volt, bool highhph)
{
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
bool invalid = false;
@@ -5817,7 +5817,7 @@
* needs to be considered as invalid
*/
v_hs_max = tabla_get_current_v_hs_max(tabla);
- if (!tabla->mbhc_inval_hs_range_override && (mic_volt > v_hs_max))
+ if (!highhph && (mic_volt > v_hs_max))
invalid = true;
else if (mic_volt < tabla->mbhc_data.v_inval_ins_high &&
(mic_volt > tabla->mbhc_data.v_inval_ins_low))
@@ -5838,40 +5838,6 @@
return false;
}
-static bool tabla_codec_is_invalid_plug(struct snd_soc_codec *codec,
- s32 mic_mv[MBHC_NUM_DCE_PLUG_DETECT],
- enum tabla_mbhc_plug_type
- plug_type[MBHC_NUM_DCE_PLUG_DETECT])
-{
- int i;
- bool r = false;
- struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
- struct tabla_mbhc_plug_type_cfg *plug_type_ptr =
- TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla->mbhc_cfg.calibration);
- s16 v_hs_max = tabla_get_current_v_hs_max(tabla);
-
- for (i = 0 ; i < MBHC_NUM_DCE_PLUG_DETECT && !r; i++) {
- if (mic_mv[i] < plug_type_ptr->v_no_mic)
- plug_type[i] = PLUG_TYPE_HEADPHONE;
- else if (mic_mv[i] < v_hs_max)
- plug_type[i] = PLUG_TYPE_HEADSET;
- else if (mic_mv[i] > v_hs_max)
- plug_type[i] = PLUG_TYPE_HIGH_HPH;
-
- r = tabla_is_invalid_insertion_range(codec, mic_mv[i]);
- if (!r && i > 0) {
- if (plug_type[i-1] != plug_type[i])
- r = true;
- else
- r = tabla_is_inval_insert_delta(codec,
- mic_mv[i], mic_mv[i - 1],
- TABLA_MBHC_FAKE_INS_DELTA_MV);
- }
- }
-
- return r;
-}
-
/* called under codec_resource_lock acquisition */
void tabla_find_plug_and_report(struct snd_soc_codec *codec,
enum tabla_mbhc_plug_type plug_type)
@@ -5934,15 +5900,127 @@
tabla->mbhc_cfg.gpio_level_insert);
}
+/* called under codec_resource_lock acquisition */
+static void tabla_codec_hphr_gnd_switch(struct snd_soc_codec *codec, bool on)
+{
+ snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x01, on);
+ if (on)
+ usleep_range(5000, 5000);
+}
+
+/* called under codec_resource_lock acquisition and mbhc override = 1 */
+static enum tabla_mbhc_plug_type
+tabla_codec_get_plug_type(struct snd_soc_codec *codec, bool highhph)
+{
+ int i;
+ bool gndswitch, vddioswitch;
+ int scaled;
+ struct tabla_mbhc_plug_type_cfg *plug_type_ptr;
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+ const bool vddio = (tabla->mbhc_data.micb_mv != VDDIO_MICBIAS_MV);
+ int num_det = (MBHC_NUM_DCE_PLUG_DETECT + vddio);
+ enum tabla_mbhc_plug_type plug_type[num_det];
+ s16 mb_v[num_det];
+ s32 mic_mv[num_det];
+ bool inval = false;
+
+ /* make sure override is on */
+ WARN_ON(!(snd_soc_read(codec, TABLA_A_CDC_MBHC_B1_CTL) & 0x04));
+
+ /* performs DCEs for N times
+ * 1st: check if voltage is in invalid range
+ * 2nd - N-2nd: check voltage range and delta
+ * N-1st: check voltage range, delta with HPHR GND switch
+ * Nth: check voltage range with VDDIO switch if micbias V != vddio V*/
+ for (i = 0; i < num_det && !inval; i++) {
+ gndswitch = (i == (num_det - 1 - vddio));
+ vddioswitch = (vddio && (i == num_det - 1));
+ if (i == 0) {
+ mb_v[i] = tabla_codec_setup_hs_polling(codec);
+ mic_mv[i] = tabla_codec_sta_dce_v(codec, 1 , mb_v[i]);
+ inval = tabla_is_invalid_insertion_range(codec,
+ mic_mv[i],
+ highhph);
+ scaled = mic_mv[i];
+ } else if (vddioswitch) {
+ __tabla_codec_switch_micbias(tabla->codec, 1, false,
+ false);
+ mb_v[i] = __tabla_codec_sta_dce(codec, 1, true, true);
+ mic_mv[i] = tabla_codec_sta_dce_v(codec, 1 , mb_v[i]);
+ scaled = tabla_scale_v_micb_vddio(tabla, mic_mv[i],
+ false);
+ inval = (tabla_is_invalid_insertion_range(codec,
+ mic_mv[i],
+ highhph) ||
+ tabla_is_inval_insert_delta(codec, scaled,
+ mic_mv[i - 1],
+ TABLA_MBHC_FAKE_INS_DELTA_SCALED_MV));
+ __tabla_codec_switch_micbias(tabla->codec, 0, false,
+ false);
+ } else {
+ if (gndswitch)
+ tabla_codec_hphr_gnd_switch(codec, true);
+ mb_v[i] = __tabla_codec_sta_dce(codec, 1, true, true);
+ mic_mv[i] = tabla_codec_sta_dce_v(codec, 1 , mb_v[i]);
+ inval = (tabla_is_invalid_insertion_range(codec,
+ mic_mv[i],
+ highhph) ||
+ tabla_is_inval_insert_delta(codec, mic_mv[i],
+ mic_mv[i - 1],
+ TABLA_MBHC_FAKE_INS_DELTA_SCALED_MV));
+ if (gndswitch)
+ tabla_codec_hphr_gnd_switch(codec, false);
+ scaled = mic_mv[i];
+ }
+ pr_debug("%s: DCE #%d, %04x, V %d, scaled V %d, GND %d, "
+ "invalid %d\n", __func__,
+ i + 1, mb_v[i] & 0xffff, mic_mv[i], scaled, gndswitch,
+ inval);
+ }
+
+ plug_type_ptr =
+ TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla->mbhc_cfg.calibration);
+ plug_type[0] = PLUG_TYPE_INVALID;
+ for (i = 0; !inval && i < num_det; i++) {
+ /*
+ * If we are here, means none of the all
+ * measurements are fake, continue plug type detection.
+ * If all three measurements do not produce same
+ * plug type, restart insertion detection
+ */
+ if (mic_mv[i] < plug_type_ptr->v_no_mic) {
+ plug_type[i] = PLUG_TYPE_HEADPHONE;
+ pr_debug("%s: Detect attempt %d, detected Headphone\n",
+ __func__, i);
+ } else if (highhph && (mic_mv[i] > plug_type_ptr->v_hs_max)) {
+ plug_type[i] = PLUG_TYPE_HIGH_HPH;
+ pr_debug("%s: Detect attempt %d, detected High "
+ "Headphone\n", __func__, i);
+ } else {
+ plug_type[i] = PLUG_TYPE_HEADSET;
+ pr_debug("%s: Detect attempt %d, detected Headset\n",
+ __func__, i);
+ }
+
+ if (i > 0 && (plug_type[i - 1] != plug_type[i])) {
+ pr_err("%s: Detect attempt %d and %d are not same",
+ __func__, i - 1, i);
+ plug_type[0] = PLUG_TYPE_INVALID;
+ inval = true;
+ break;
+ }
+ }
+
+ return plug_type[0];
+}
+
static void tabla_hs_correct_gpio_plug(struct work_struct *work)
{
struct tabla_priv *tabla;
struct snd_soc_codec *codec;
- int retry = 0, i;
+ int retry = 0;
bool correction = false;
- s32 mic_mv[MBHC_NUM_DCE_PLUG_DETECT];
- short mb_v[MBHC_NUM_DCE_PLUG_DETECT];
- enum tabla_mbhc_plug_type plug_type[MBHC_NUM_DCE_PLUG_DETECT];
+ enum tabla_mbhc_plug_type plug_type;
unsigned long timeout;
tabla = container_of(work, struct tabla_priv, hs_correct_plug_work);
@@ -5979,24 +6057,17 @@
/* can race with removal interrupt */
TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
- for (i = 0; i < MBHC_NUM_DCE_PLUG_DETECT; i++) {
- mb_v[i] = __tabla_codec_sta_dce(codec, 1, true, true);
- mic_mv[i] = tabla_codec_sta_dce_v(codec, 1 , mb_v[i]);
- pr_debug("%s : DCE run %d, mic_mv = %d(%x)\n",
- __func__, retry, mic_mv[i], mb_v[i]);
- }
+ plug_type = tabla_codec_get_plug_type(codec, true);
TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
- if (tabla_codec_is_invalid_plug(codec, mic_mv, plug_type)) {
+ if (plug_type == PLUG_TYPE_INVALID) {
pr_debug("Invalid plug in attempt # %d\n", retry);
if (retry == NUM_ATTEMPTS_TO_REPORT &&
tabla->current_plug == PLUG_TYPE_NONE) {
tabla_codec_report_plug(codec, 1,
SND_JACK_HEADPHONE);
}
- } else if (!tabla_codec_is_invalid_plug(codec, mic_mv,
- plug_type) &&
- plug_type[0] == PLUG_TYPE_HEADPHONE) {
+ } else if (plug_type == PLUG_TYPE_HEADPHONE) {
pr_debug("Good headphone detected, continue polling mic\n");
if (tabla->current_plug == PLUG_TYPE_NONE) {
tabla_codec_report_plug(codec, 1,
@@ -6006,10 +6077,10 @@
TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
/* Turn off override */
tabla_turn_onoff_override(codec, false);
- tabla_find_plug_and_report(codec, plug_type[0]);
+ tabla_find_plug_and_report(codec, plug_type);
TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
pr_debug("Attempt %d found correct plug %d\n", retry,
- plug_type[0]);
+ plug_type);
correction = true;
break;
}
@@ -6029,24 +6100,12 @@
static void tabla_codec_decide_gpio_plug(struct snd_soc_codec *codec)
{
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
- short mb_v[MBHC_NUM_DCE_PLUG_DETECT];
- s32 mic_mv[MBHC_NUM_DCE_PLUG_DETECT];
- enum tabla_mbhc_plug_type plug_type[MBHC_NUM_DCE_PLUG_DETECT];
- int i;
+ enum tabla_mbhc_plug_type plug_type;
pr_debug("%s: enter\n", __func__);
tabla_turn_onoff_override(codec, true);
- mb_v[0] = tabla_codec_setup_hs_polling(codec);
- mic_mv[0] = tabla_codec_sta_dce_v(codec, 1, mb_v[0]);
- pr_debug("%s: DCE run 1, mic_mv = %d\n", __func__, mic_mv[0]);
-
- for (i = 1; i < MBHC_NUM_DCE_PLUG_DETECT; i++) {
- mb_v[i] = __tabla_codec_sta_dce(codec, 1, true, true);
- mic_mv[i] = tabla_codec_sta_dce_v(codec, 1 , mb_v[i]);
- pr_debug("%s: DCE run %d, mic_mv = %d\n", __func__, i + 1,
- mic_mv[i]);
- }
+ plug_type = tabla_codec_get_plug_type(codec, true);
tabla_turn_onoff_override(codec, false);
if (tabla_hs_gpio_level_remove(tabla)) {
@@ -6055,48 +6114,26 @@
return;
}
- if (tabla_codec_is_invalid_plug(codec, mic_mv, plug_type)) {
+ if (plug_type == PLUG_TYPE_INVALID) {
tabla_schedule_hs_detect_plug(tabla);
- } else if (plug_type[0] == PLUG_TYPE_HEADPHONE) {
+ } else if (plug_type == PLUG_TYPE_HEADPHONE) {
tabla_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
tabla_schedule_hs_detect_plug(tabla);
} else {
- pr_debug("%s: Valid plug found, determine plug type\n",
- __func__);
- tabla_find_plug_and_report(codec, plug_type[0]);
- }
-}
-
-/* called under codec_resource_lock acquisition */
-static void tabla_codec_hphr_gnd_switch(struct snd_soc_codec *codec, bool on)
-{
- struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
-
- if (tabla->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
- snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x01, on);
- if (on)
- usleep_range(5000, 5000);
+ pr_debug("%s: Valid plug found, determine plug type %d\n",
+ __func__, plug_type);
+ tabla_find_plug_and_report(codec, plug_type);
}
}
/* called under codec_resource_lock acquisition */
static void tabla_codec_detect_plug_type(struct snd_soc_codec *codec)
{
- int i;
- bool gndswitch, vddioswitch;
- int scaled;
+ enum tabla_mbhc_plug_type plug_type;
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
const struct tabla_mbhc_plug_detect_cfg *plug_det =
TABLA_MBHC_CAL_PLUG_DET_PTR(tabla->mbhc_cfg.calibration);
- struct tabla_mbhc_plug_type_cfg *plug_type_ptr;
- const bool vddio = (tabla->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
- !tabla->mbhc_micbias_switched);
- int num_det = (MBHC_NUM_DCE_PLUG_DETECT + vddio);
- enum tabla_mbhc_plug_type plug_type[num_det];
- short mb_v[num_det];
- s32 mic_mv[num_det];
- bool inval = false;
/* Turn on the override,
* tabla_codec_setup_hs_polling requires override on */
@@ -6119,84 +6156,11 @@
return;
}
- /* performs DCEs for N times
- * 1st: check if voltage is in invalid range
- * 2nd - N-2nd: check voltage range and delta
- * N-1st: check voltage range, delta with HPHR GND switch
- * Nth: check voltage range with VDDIO switch if micbias V != vddio V*/
- for (i = 0; i < num_det && !inval; i++) {
- gndswitch = (i == (num_det - 1 - vddio));
- vddioswitch = (vddio && (i == num_det - 1));
- if (i == 0) {
- mb_v[i] = tabla_codec_setup_hs_polling(codec);
- mic_mv[i] = tabla_codec_sta_dce_v(codec, 1 , mb_v[i]);
- inval = tabla_is_invalid_insertion_range(codec,
- mic_mv[i]);
- scaled = mic_mv[i];
- } else if (vddioswitch) {
- __tabla_codec_switch_micbias(tabla->codec, 1, false,
- false);
- mb_v[i] = __tabla_codec_sta_dce(codec, 1, true, true);
- mic_mv[i] = tabla_codec_sta_dce_v(codec, 1 , mb_v[i]);
- scaled = tabla_scale_v_micb_vddio(tabla, mic_mv[i],
- false);
- inval = (tabla_is_invalid_insertion_range(codec,
- mic_mv[i]) ||
- tabla_is_inval_insert_delta(codec, scaled,
- mic_mv[i - 1],
- TABLA_MBHC_FAKE_INS_DELTA_SCALED_MV));
- __tabla_codec_switch_micbias(tabla->codec, 0, false,
- false);
- } else {
- if (gndswitch)
- tabla_codec_hphr_gnd_switch(codec, true);
- mb_v[i] = __tabla_codec_sta_dce(codec, 1, true, true);
- mic_mv[i] = tabla_codec_sta_dce_v(codec, 1 , mb_v[i]);
- inval = (tabla_is_invalid_insertion_range(codec,
- mic_mv[i]) ||
- tabla_is_inval_insert_delta(codec, mic_mv[i],
- mic_mv[i - 1],
- TABLA_MBHC_FAKE_INS_DELTA_SCALED_MV));
- if (gndswitch)
- tabla_codec_hphr_gnd_switch(codec, false);
- scaled = mic_mv[i];
- }
- pr_debug("%s: DCE #%d, %04x, V %d, scaled V %d, GND %d, "
- "invalid %d\n", __func__,
- i + 1, mb_v[i] & 0xffff, mic_mv[i], scaled, gndswitch,
- inval);
- }
+ plug_type = tabla_codec_get_plug_type(codec, tabla->mbhc_cfg.gpio ?
+ true : false);
tabla_turn_onoff_override(codec, false);
- plug_type_ptr =
- TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla->mbhc_cfg.calibration);
-
- for (i = 0; !inval && i < num_det; i++) {
- /*
- * If we are here, means none of the all
- * measurements are fake, continue plug type detection.
- * If all three measurements do not produce same
- * plug type, restart insertion detection
- */
- if (mic_mv[i] < plug_type_ptr->v_no_mic) {
- plug_type[i] = PLUG_TYPE_HEADPHONE;
- pr_debug("%s: Detect attempt %d, detected Headphone\n",
- __func__, i);
- } else {
- plug_type[i] = PLUG_TYPE_HEADSET;
- pr_debug("%s: Detect attempt %d, detected Headset\n",
- __func__, i);
- }
-
- if (i > 0 && (plug_type[i - 1] != plug_type[i])) {
- pr_err("%s: Detect attempt %d and %d are not same",
- __func__, i - 1, i);
- inval = true;
- break;
- }
- }
-
- if (inval) {
+ if (plug_type == PLUG_TYPE_INVALID) {
pr_debug("%s: Invalid plug type detected\n", __func__);
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL,
0x02, 0x02);
@@ -6204,12 +6168,12 @@
tabla_codec_enable_hs_detect(codec, 1,
MBHC_USE_MB_TRIGGER |
MBHC_USE_HPHL_TRIGGER, false);
- } else if (plug_type[0] == PLUG_TYPE_HEADPHONE) {
+ } else if (plug_type == PLUG_TYPE_HEADPHONE) {
pr_debug("%s: Headphone Detected\n", __func__);
tabla_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
tabla_codec_cleanup_hs_polling(codec);
tabla_codec_enable_hs_detect(codec, 0, 0, false);
- } else if (plug_type[0] == PLUG_TYPE_HEADSET) {
+ } else if (plug_type == PLUG_TYPE_HEADSET) {
pr_debug("%s: Headset detected\n", __func__);
tabla_codec_report_plug(codec, 1, SND_JACK_HEADSET);
@@ -6679,7 +6643,6 @@
tabla->mbhc_cfg.mclk_cb_fn(codec, 0, false);
tabla_codec_calibrate_hs_polling(codec);
if (!tabla->mbhc_cfg.gpio) {
- tabla->mbhc_inval_hs_range_override = false;
rc = tabla_codec_enable_hs_detect(codec, 1,
MBHC_USE_MB_TRIGGER |
MBHC_USE_HPHL_TRIGGER,
@@ -6689,7 +6652,6 @@
pr_err("%s: Failed to setup MBHC detection\n",
__func__);
} else {
- tabla->mbhc_inval_hs_range_override = true;
/* Enable Mic Bias pull down and HPH Switch to GND */
snd_soc_update_bits(codec,
tabla->mbhc_bias_regs.ctl_reg, 0x01,
@@ -6747,13 +6709,11 @@
tabla->mbhc_cfg.mclk_cb_fn(codec, 0, false);
tabla_codec_calibrate_hs_polling(codec);
if (!tabla->mbhc_cfg.gpio) {
- tabla->mbhc_inval_hs_range_override = false;
rc = tabla_codec_enable_hs_detect(codec, 1,
MBHC_USE_MB_TRIGGER |
MBHC_USE_HPHL_TRIGGER,
false);
} else {
- tabla->mbhc_inval_hs_range_override = true;
/* Enable Mic Bias pull down and HPH Switch to GND */
snd_soc_update_bits(codec,
tabla->mbhc_bias_regs.ctl_reg, 0x01,