ASoC: wcd9xxx: Change implementation to use callbacks
To use common mbhc code across multiple codecs, use
callback functions instead of mbhc version for each
codec. This will make the codec driver to handle the
codec dependent changes.
Change-Id: I83e1bab17a64add05baa83b6956e05fa5920be8a
Signed-off-by: Simmi Pateriya <simmip@codeaurora.org>
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index af5b08f..6d48be0 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -73,6 +73,9 @@
#define TAPAN_SLIM_IRQ_OVERFLOW (1 << 0)
#define TAPAN_SLIM_IRQ_UNDERFLOW (1 << 1)
#define TAPAN_SLIM_IRQ_PORT_CLOSED (1 << 2)
+
+#define TAPAN_IRQ_MBHC_JACK_SWITCH 21
+
enum {
AIF1_PB = 0,
AIF1_CAP,
@@ -4448,6 +4451,72 @@
wcd9xxx_free_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS, tapan);
}
+
+static void tapan_enable_mux_bias_block(struct snd_soc_codec *codec)
+{
+ snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
+ 0x80, 0x00);
+}
+
+static void tapan_put_cfilt_fast_mode(struct snd_soc_codec *codec,
+ struct wcd9xxx_mbhc *mbhc)
+{
+ snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl,
+ 0x30, 0x30);
+}
+
+static void tapan_codec_specific_cal_setup(struct snd_soc_codec *codec,
+ struct wcd9xxx_mbhc *mbhc)
+{
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
+ 0x0C, 0x04);
+ snd_soc_update_bits(codec, WCD9XXX_A_TX_7_MBHC_EN, 0xE0, 0xE0);
+}
+
+static int tapan_get_jack_detect_irq(struct snd_soc_codec *codec)
+{
+ return TAPAN_IRQ_MBHC_JACK_SWITCH;
+}
+
+static struct wcd9xxx_cfilt_mode tapan_codec_switch_cfilt_mode(
+ struct wcd9xxx_mbhc *mbhc,
+ bool fast)
+{
+ struct snd_soc_codec *codec = mbhc->codec;
+ struct wcd9xxx_cfilt_mode cfilt_mode;
+
+ if (fast)
+ cfilt_mode.reg_mode_val = WCD9XXX_CFILT_EXT_PRCHG_EN;
+ else
+ cfilt_mode.reg_mode_val = WCD9XXX_CFILT_EXT_PRCHG_DSBL;
+
+ cfilt_mode.cur_mode_val =
+ snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl) & 0x30;
+ return cfilt_mode;
+}
+
+static void tapan_select_cfilt(struct snd_soc_codec *codec,
+ struct wcd9xxx_mbhc *mbhc)
+{
+ snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x60, 0x00);
+}
+
+static void tapan_free_irq(struct wcd9xxx_mbhc *mbhc)
+{
+ void *cdata = mbhc->codec->control_data;
+ wcd9xxx_free_irq(cdata, WCD9306_IRQ_MBHC_JACK_SWITCH, mbhc);
+}
+
+static const struct wcd9xxx_mbhc_cb mbhc_cb = {
+ .enable_mux_bias_block = tapan_enable_mux_bias_block,
+ .cfilt_fast_mode = tapan_put_cfilt_fast_mode,
+ .codec_specific_cal = tapan_codec_specific_cal_setup,
+ .jack_detect_irq = tapan_get_jack_detect_irq,
+ .switch_cfilt_mode = tapan_codec_switch_cfilt_mode,
+ .select_cfilt = tapan_select_cfilt,
+ .free_irq = tapan_free_irq,
+};
+
int tapan_hs_detect(struct snd_soc_codec *codec,
struct wcd9xxx_mbhc_config *mbhc_cfg)
{
@@ -4503,8 +4572,7 @@
rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
- WCD9XXX_MBHC_VERSION_TAPAN,
- rco_clk_rate);
+ &mbhc_cb, rco_clk_rate);
if (ret)
pr_err("%s: mbhc init failed %d\n", __func__, ret);
else
@@ -4576,8 +4644,8 @@
rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
- WCD9XXX_MBHC_VERSION_TAPAN,
- rco_clk_rate);
+ &mbhc_cb, rco_clk_rate);
+
if (ret) {
pr_err("%s: mbhc init failed %d\n", __func__, ret);
return ret;
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 49894ca..9d52592 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -6223,8 +6223,7 @@
ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
taiko_enable_mbhc_micbias,
- WCD9XXX_MBHC_VERSION_TAIKO,
- rco_clk_rate);
+ NULL, rco_clk_rate);
if (ret) {
pr_err("%s: mbhc init failed %d\n", __func__, ret);
} else {
@@ -6404,8 +6403,7 @@
/* init and start mbhc */
ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
taiko_enable_mbhc_micbias,
- WCD9XXX_MBHC_VERSION_TAIKO,
- rco_clk_rate);
+ NULL, rco_clk_rate);
if (ret) {
pr_err("%s: mbhc init failed %d\n", __func__, ret);
goto err_init;
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 618070b..cd11703 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -94,6 +94,8 @@
#define WCD9XXX_USLEEP_RANGE_MARGIN_US 1000
+#define WCD9XXX_IRQ_MBHC_JACK_SWITCH_DEFAULT 28
+
static bool detect_use_vddio_switch = true;
struct wcd9xxx_mbhc_detect {
@@ -150,64 +152,6 @@
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x04, on << 2);
}
-static int wcd9xxx_enable_mux_bias_block(struct snd_soc_codec *codec,
- struct wcd9xxx_mbhc *mbhc)
-{
- switch (mbhc->mbhc_version) {
- case WCD9XXX_MBHC_VERSION_TAIKO:
- snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
- 0x80, 0x80);
- break;
- case WCD9XXX_MBHC_VERSION_TAPAN:
- snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
- 0x80, 0x00);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int wcd9xxx_put_cfilt_fast_mode(struct snd_soc_codec *codec,
- struct wcd9xxx_mbhc *mbhc)
-{
- switch (mbhc->mbhc_version) {
- case WCD9XXX_MBHC_VERSION_TAIKO:
- snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl,
- 0x70, 0x00);
- break;
- case WCD9XXX_MBHC_VERSION_TAPAN:
- snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl,
- 0x70, 0x70);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int wcd9xxx_codec_specific_cal_setup(struct snd_soc_codec *codec,
- struct wcd9xxx_mbhc *mbhc)
-{
- switch (mbhc->mbhc_version) {
- case WCD9XXX_MBHC_VERSION_TAIKO:
- snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
- 0x04, 0x04);
- break;
- case WCD9XXX_MBHC_VERSION_TAPAN:
- snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
- 0x0C, 0x04);
- snd_soc_update_bits(codec, WCD9XXX_A_TX_7_MBHC_EN, 0xE0, 0xE0);
- /* Make sure the calibration is ON */
- snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_val,
- 0x02, 0x02);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
/* called under codec_resource_lock acquisition */
static void wcd9xxx_pause_hs_polling(struct wcd9xxx_mbhc *mbhc)
{
@@ -229,20 +173,18 @@
{
struct snd_soc_codec *codec = mbhc->codec;
int mbhc_state = mbhc->mbhc_state;
- int ret;
pr_debug("%s: enter\n", __func__);
if (!mbhc->polling_active) {
pr_debug("Polling is not active, do not start polling\n");
return;
}
-
snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x04);
- ret = wcd9xxx_enable_mux_bias_block(codec, mbhc);
- if (ret) {
- pr_err("%s: Error returned, ret: %d\n", __func__, ret);
- return;
- }
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mux_bias_block)
+ mbhc->mbhc_cb->enable_mux_bias_block(codec);
+ else
+ snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
+ 0x80, 0x80);
if (!mbhc->no_mic_headset_override &&
mbhc_state == MBHC_STATE_POTENTIAL) {
@@ -481,14 +423,18 @@
(mbhc->mbhc_data.v_brl >> 8) & 0xFF);
}
-static int wcd9xxx_codec_switch_cfilt_mode(struct wcd9xxx_mbhc *mbhc,
+static void wcd9xxx_codec_switch_cfilt_mode(struct wcd9xxx_mbhc *mbhc,
bool fast)
{
struct snd_soc_codec *codec = mbhc->codec;
+ struct wcd9xxx_cfilt_mode cfilt_mode;
u8 reg_mode_val, cur_mode_val;
- switch (mbhc->mbhc_version) {
- case WCD9XXX_MBHC_VERSION_TAIKO:
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->switch_cfilt_mode) {
+ cfilt_mode = mbhc->mbhc_cb->switch_cfilt_mode(mbhc, fast);
+ reg_mode_val = cfilt_mode.reg_mode_val;
+ cur_mode_val = cfilt_mode.cur_mode_val;
+ } else {
if (fast)
reg_mode_val = WCD9XXX_CFILT_FAST_MODE;
else
@@ -496,50 +442,21 @@
cur_mode_val =
snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl) & 0x40;
-
- if (cur_mode_val != reg_mode_val) {
- if (mbhc->polling_active)
- wcd9xxx_pause_hs_polling(mbhc);
- snd_soc_update_bits(codec,
- mbhc->mbhc_bias_regs.cfilt_ctl,
- 0x40, reg_mode_val);
- if (mbhc->polling_active)
- wcd9xxx_start_hs_polling(mbhc);
- pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
- cur_mode_val, reg_mode_val);
- } else {
- pr_debug("%s: CFILT Value is already %x\n",
- __func__, cur_mode_val);
- }
- break;
- case WCD9XXX_MBHC_VERSION_TAPAN:
- if (fast)
- reg_mode_val = WCD9XXX_CFILT_EXT_PRCHG_EN;
- else
- reg_mode_val = WCD9XXX_CFILT_EXT_PRCHG_DSBL;
-
- cur_mode_val =
- snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl) & 0x70;
-
- if (cur_mode_val != reg_mode_val) {
- if (mbhc->polling_active)
- wcd9xxx_pause_hs_polling(mbhc);
- snd_soc_update_bits(codec,
- mbhc->mbhc_bias_regs.cfilt_ctl,
- 0x70, reg_mode_val);
- if (mbhc->polling_active)
- wcd9xxx_start_hs_polling(mbhc);
- pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
- cur_mode_val, reg_mode_val);
- } else {
- pr_debug("%s: CFILT Value is already %x\n",
- __func__, cur_mode_val);
- }
- break;
- default:
- return -EINVAL;
}
- return 0;
+ if (cur_mode_val != reg_mode_val) {
+ if (mbhc->polling_active)
+ wcd9xxx_pause_hs_polling(mbhc);
+ snd_soc_update_bits(codec,
+ mbhc->mbhc_bias_regs.cfilt_ctl,
+ 0x40, reg_mode_val);
+ if (mbhc->polling_active)
+ wcd9xxx_start_hs_polling(mbhc);
+ pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
+ cur_mode_val, reg_mode_val);
+ } else {
+ pr_debug("%s: CFILT Value is already %x\n",
+ __func__, cur_mode_val);
+ }
}
static void wcd9xxx_jack_report(struct wcd9xxx_mbhc *mbhc,
@@ -1043,7 +960,6 @@
struct snd_soc_codec *codec = mbhc->codec;
short bias_value;
u8 cfilt_mode;
- int ret;
WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
@@ -1066,14 +982,19 @@
/* Make sure CFILT is in fast mode, save current mode */
cfilt_mode = snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl);
- ret = wcd9xxx_put_cfilt_fast_mode(codec, mbhc);
- if (ret)
- goto gen_err;
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->cfilt_fast_mode)
+ mbhc->mbhc_cb->cfilt_fast_mode(codec, mbhc);
+ else
+ snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl,
+ 0x70, 0x00);
+
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x04);
- ret = wcd9xxx_enable_mux_bias_block(codec, mbhc);
- if (ret)
- goto gen_err;
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mux_bias_block)
+ mbhc->mbhc_cb->enable_mux_bias_block(codec);
+ else
+ snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
+ 0x80, 0x80);
snd_soc_update_bits(codec, WCD9XXX_A_TX_7_MBHC_EN, 0x80, 0x80);
snd_soc_update_bits(codec, WCD9XXX_A_TX_7_MBHC_EN, 0x1F, 0x1C);
@@ -1094,10 +1015,6 @@
snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x13, 0x00);
return bias_value;
-
-gen_err:
- pr_err("%s: Error returned, ret: %d\n", __func__, ret);
- return ret;
}
static void wcd9xxx_shutdown_hs_removal_detect(struct wcd9xxx_mbhc *mbhc)
@@ -2927,7 +2844,6 @@
{
u8 cfilt_mode;
u16 reg0, reg1;
- int ret;
struct snd_soc_codec *codec = mbhc->codec;
pr_debug("%s: enter\n", __func__);
@@ -2944,21 +2860,30 @@
* Need to restore defaults once calculation is done.
*/
cfilt_mode = snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl);
- ret = wcd9xxx_put_cfilt_fast_mode(codec, mbhc);
- if (ret)
- goto gen_err;
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->cfilt_fast_mode)
+ mbhc->mbhc_cb->cfilt_fast_mode(codec, mbhc);
+ else
+ snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl,
+ 0x40, 0x00);
+
/*
* Micbias, CFILT, LDOH, MBHC MUX mode settings
* to perform ADC calibration
*/
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->select_cfilt)
+ mbhc->mbhc_cb->select_cfilt(codec, mbhc);
+ else
snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x60,
mbhc->mbhc_cfg->micbias << 5);
snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
snd_soc_update_bits(codec, WCD9XXX_A_LDO_H_MODE_1, 0x60, 0x60);
snd_soc_write(codec, WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0x78);
- ret = wcd9xxx_codec_specific_cal_setup(codec, mbhc);
- if (ret)
- goto gen_err;
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->codec_specific_cal)
+ mbhc->mbhc_cb->codec_specific_cal(codec, mbhc);
+ else
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
+ 0x04, 0x04);
+
/* Pull down micbias to ground */
reg0 = snd_soc_read(codec, mbhc->mbhc_bias_regs.ctl_reg);
snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 1, 1);
@@ -2967,9 +2892,11 @@
snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4, 1 << 0);
/* Connect the MUX to micbias */
snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x02);
- ret = wcd9xxx_enable_mux_bias_block(codec, mbhc);
- if (ret)
- goto gen_err;
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mux_bias_block)
+ mbhc->mbhc_cb->enable_mux_bias_block(codec);
+ else
+ snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
+ 0x80, 0x80);
/*
* Hardware that has external cap can delay mic bias ramping down up
* to 50ms.
@@ -2991,9 +2918,11 @@
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x0A);
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x02);
snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x02);
- ret = wcd9xxx_enable_mux_bias_block(codec, mbhc);
- if (ret)
- goto gen_err;
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mux_bias_block)
+ mbhc->mbhc_cb->enable_mux_bias_block(codec);
+ else
+ snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
+ 0x80, 0x80);
/*
* Hardware that has external cap can delay mic bias ramping down up
* to 50ms.
@@ -3008,9 +2937,11 @@
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x02);
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x02);
snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x02);
- ret = wcd9xxx_enable_mux_bias_block(codec, mbhc);
- if (ret)
- goto gen_err;
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mux_bias_block)
+ mbhc->mbhc_cb->enable_mux_bias_block(codec);
+ else
+ snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
+ 0x80, 0x80);
/*
* Hardware that has external cap can delay mic bias ramping down up
* to 50ms.
@@ -3024,19 +2955,17 @@
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
snd_soc_write(codec, mbhc->mbhc_bias_regs.cfilt_ctl, cfilt_mode);
snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x04);
- ret = wcd9xxx_enable_mux_bias_block(codec, mbhc);
- if (ret)
- goto gen_err;
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mux_bias_block)
+ mbhc->mbhc_cb->enable_mux_bias_block(codec);
+ else
+ snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
+ 0x80, 0x80);
usleep_range(100, 100);
wcd9xxx_enable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_POTENTIAL);
wcd9xxx_turn_onoff_rel_detection(codec, true);
pr_debug("%s: leave\n", __func__);
- return;
-
-gen_err:
- pr_err("%s: Error returned, ret: %d\n", __func__, ret);
}
static void wcd9xxx_mbhc_setup(struct wcd9xxx_mbhc *mbhc)
@@ -3095,8 +3024,14 @@
{
int ret = 0;
void *core = mbhc->resmgr->core;
+ struct snd_soc_codec *codec = mbhc->codec;
int jack_irq;
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->jack_detect_irq)
+ jack_irq = mbhc->mbhc_cb->jack_detect_irq(codec);
+ else
+ jack_irq = WCD9XXX_IRQ_MBHC_JACK_SWITCH_DEFAULT;
+
if (mbhc->mbhc_cfg->gpio) {
ret = request_threaded_irq(mbhc->mbhc_cfg->gpio_irq, NULL,
wcd9xxx_mech_plug_detect_irq,
@@ -3118,17 +3053,6 @@
snd_soc_update_bits(mbhc->codec, WCD9XXX_A_RX_HPH_OCP_CTL,
1 << 1, 1 << 1);
- switch (mbhc->mbhc_version) {
- case WCD9XXX_MBHC_VERSION_TAIKO:
- jack_irq = WCD9320_IRQ_MBHC_JACK_SWITCH;
- break;
- case WCD9XXX_MBHC_VERSION_TAPAN:
- jack_irq = WCD9306_IRQ_MBHC_JACK_SWITCH;
- break;
- default:
- return -EINVAL;
- }
-
ret = wcd9xxx_request_irq(core, jack_irq,
wcd9xxx_mech_plug_detect_irq,
"Jack Detect",
@@ -3357,7 +3281,7 @@
int wcd9xxx_mbhc_start(struct wcd9xxx_mbhc *mbhc,
struct wcd9xxx_mbhc_config *mbhc_cfg)
{
- int rc;
+ int rc = 0;
struct snd_soc_codec *codec = mbhc->codec;
pr_debug("%s: enter\n", __func__);
@@ -3381,10 +3305,13 @@
wcd9xxx_get_mbhc_micbias_regs(mbhc, &mbhc->mbhc_bias_regs);
/* Put CFILT in fast mode by default */
- rc = wcd9xxx_put_cfilt_fast_mode(codec, mbhc);
- if (rc)
- pr_err("%s: Error returned, ret: %d\n", __func__, rc);
- else if (!mbhc->mbhc_cfg->read_fw_bin)
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->cfilt_fast_mode)
+ mbhc->mbhc_cb->cfilt_fast_mode(codec, mbhc);
+ else
+ snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl,
+ 0x40, WCD9XXX_CFILT_FAST_MODE);
+
+ if (!mbhc->mbhc_cfg->read_fw_bin)
rc = wcd9xxx_init_and_calibrate(mbhc);
else
schedule_delayed_work(&mbhc->mbhc_firmware_dwork,
@@ -3612,7 +3539,7 @@
* Switch CFILT to slow mode if MBHC CFILT is being
* used.
*/
- ret = wcd9xxx_codec_switch_cfilt_mode(mbhc, false);
+ wcd9xxx_codec_switch_cfilt_mode(mbhc, false);
break;
case WCD9XXX_EVENT_POST_CFILT_1_OFF:
case WCD9XXX_EVENT_POST_CFILT_2_OFF:
@@ -3623,7 +3550,7 @@
* Switch CFILT to fast mode if MBHC CFILT is not
* used anymore.
*/
- ret = wcd9xxx_codec_switch_cfilt_mode(mbhc, true);
+ wcd9xxx_codec_switch_cfilt_mode(mbhc, true);
break;
/* System resume */
case WCD9XXX_EVENT_POST_RESUME:
@@ -3656,8 +3583,7 @@
int wcd9xxx_mbhc_init(struct wcd9xxx_mbhc *mbhc, struct wcd9xxx_resmgr *resmgr,
struct snd_soc_codec *codec,
int (*micbias_enable_cb) (struct snd_soc_codec*, bool),
- int version,
- int rco_clk_rate)
+ const struct wcd9xxx_mbhc_cb *mbhc_cb, int rco_clk_rate)
{
int ret;
void *core;
@@ -3681,8 +3607,8 @@
mbhc->resmgr = resmgr;
mbhc->resmgr->mbhc = mbhc;
mbhc->micbias_enable_cb = micbias_enable_cb;
- mbhc->mbhc_version = version;
mbhc->rco_clk_rate = rco_clk_rate;
+ mbhc->mbhc_cb = mbhc_cb;
if (mbhc->headset_jack.jack == NULL) {
ret = snd_soc_jack_new(codec, "Headset Jack", WCD9XXX_JACK_MASK,
@@ -3805,17 +3731,11 @@
wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_REMOVAL, mbhc);
wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_INSERTION, mbhc);
- switch (mbhc->mbhc_version) {
- case WCD9XXX_MBHC_VERSION_TAIKO:
- wcd9xxx_free_irq(cdata, WCD9320_IRQ_MBHC_JACK_SWITCH, mbhc);
- break;
- case WCD9XXX_MBHC_VERSION_TAPAN:
- wcd9xxx_free_irq(cdata, WCD9306_IRQ_MBHC_JACK_SWITCH, mbhc);
- break;
- default:
- pr_err("%s: irq free failed! Invalid MBHC version %d\n",
- __func__, mbhc->mbhc_version);
- }
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->free_irq)
+ mbhc->mbhc_cb->free_irq(mbhc);
+ else
+ wcd9xxx_free_irq(cdata, WCD9320_IRQ_MBHC_JACK_SWITCH,
+ mbhc);
wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, mbhc);
wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT, mbhc);
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index 71a62b2..02ecced 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.h
@@ -16,8 +16,8 @@
#define WCD9XXX_CFILT_FAST_MODE 0x00
#define WCD9XXX_CFILT_SLOW_MODE 0x40
-#define WCD9XXX_CFILT_EXT_PRCHG_EN 0x70
-#define WCD9XXX_CFILT_EXT_PRCHG_DSBL 0x40
+#define WCD9XXX_CFILT_EXT_PRCHG_EN 0x30
+#define WCD9XXX_CFILT_EXT_PRCHG_DSBL 0x00
struct mbhc_micbias_regs {
u16 cfilt_val;
@@ -61,12 +61,6 @@
s16 v_inval_ins_high;
};
-enum wcd9xxx_mbhc_version {
- WCD9XXX_MBHC_VERSION_UNKNOWN = 0,
- WCD9XXX_MBHC_VERSION_TAIKO,
- WCD9XXX_MBHC_VERSION_TAPAN,
-};
-
enum wcd9xxx_mbhc_plug_type {
PLUG_TYPE_INVALID = -1,
PLUG_TYPE_NONE,
@@ -218,6 +212,23 @@
bool (*swap_gnd_mic) (struct snd_soc_codec *);
};
+struct wcd9xxx_cfilt_mode {
+ u8 reg_mode_val;
+ u8 cur_mode_val;
+};
+
+struct wcd9xxx_mbhc_cb {
+ void (*enable_mux_bias_block) (struct snd_soc_codec *);
+ void (*cfilt_fast_mode) (struct snd_soc_codec *, struct wcd9xxx_mbhc *);
+ void (*codec_specific_cal) (struct snd_soc_codec *,
+ struct wcd9xxx_mbhc *);
+ int (*jack_detect_irq) (struct snd_soc_codec *);
+ struct wcd9xxx_cfilt_mode (*switch_cfilt_mode) (struct wcd9xxx_mbhc *,
+ bool);
+ void (*select_cfilt) (struct snd_soc_codec *, struct wcd9xxx_mbhc *);
+ void (*free_irq) (struct wcd9xxx_mbhc *);
+};
+
struct wcd9xxx_mbhc {
bool polling_active;
/* Delayed work to report long button press */
@@ -225,6 +236,7 @@
int buttons_pressed;
enum wcd9xxx_mbhc_state mbhc_state;
struct wcd9xxx_mbhc_config *mbhc_cfg;
+ const struct wcd9xxx_mbhc_cb *mbhc_cb;
struct mbhc_internal_cal_data mbhc_data;
@@ -279,8 +291,6 @@
bool micbias_enable;
int (*micbias_enable_cb) (struct snd_soc_codec*, bool);
- enum wcd9xxx_mbhc_version mbhc_version;
-
u32 rco_clk_rate;
#ifdef CONFIG_DEBUG_FS
@@ -349,7 +359,7 @@
int wcd9xxx_mbhc_init(struct wcd9xxx_mbhc *mbhc, struct wcd9xxx_resmgr *resmgr,
struct snd_soc_codec *codec,
int (*micbias_enable_cb) (struct snd_soc_codec*, bool),
- int version,
+ const struct wcd9xxx_mbhc_cb *mbhc_cb,
int rco_clk_rate);
void wcd9xxx_mbhc_deinit(struct wcd9xxx_mbhc *mbhc);
void *wcd9xxx_mbhc_cal_btn_det_mp(