Merge "msm: cpr-regulator: Improve CPR interrupt handling"
diff --git a/drivers/usb/host/ice40-hcd.c b/drivers/usb/host/ice40-hcd.c
index 4d62a3e..7b0a789 100644
--- a/drivers/usb/host/ice40-hcd.c
+++ b/drivers/usb/host/ice40-hcd.c
@@ -1225,7 +1225,7 @@
{
struct ice40_hcd *ihcd = hcd_to_ihcd(hcd);
u8 ctrl0;
- int ret;
+ int ret, i;
pm_stay_awake(&ihcd->spi->dev);
trace_ice40_bus_resume(0); /* start */
@@ -1234,7 +1234,18 @@
* Re-program the previous settings. For now we need to
* update the device address only.
*/
- ice40_spi_load_fw(ihcd);
+
+ for (i = 0; i < 3; i++) {
+ ret = ice40_spi_load_fw(ihcd);
+ if (!ret)
+ break;
+ }
+
+ if (ret) {
+ pr_err("Load firmware failed with ret: %d\n", ret);
+ return ret;
+ }
+
ice40_spi_reg_write(ihcd, ihcd->devnum, FADDR_REG);
ihcd->wblen0 = ~0;
@@ -1492,7 +1503,7 @@
static int ice40_spi_load_fw(struct ice40_hcd *ihcd)
{
int ret, i;
- struct gpiomux_setting old_setting;
+ struct gpiomux_setting active_old_setting, suspend_old_setting;
ret = gpio_direction_output(ihcd->reset_gpio, 0);
if (ret < 0) {
@@ -1514,21 +1525,38 @@
* We temporarily override the chip select config to
* drive it low. The SPI bus needs to be locked down during
* this period to avoid other slave data going to our
- * bridge chip.
- *
+ * bridge chip. Disable the SPI runtime suspend for exclusive
+ * chip select access.
*/
+ pm_runtime_get_sync(ihcd->spi->master->dev.parent);
+
spi_bus_lock(ihcd->spi->master);
ret = msm_gpiomux_write(ihcd->slave_select_gpio, GPIOMUX_SUSPENDED,
- &slave_select_setting, &old_setting);
+ &slave_select_setting, &suspend_old_setting);
if (ret < 0) {
- pr_err("fail to select the slave %d\n", ret);
+ pr_err("fail to override suspend setting and select slave %d\n",
+ ret);
+ spi_bus_unlock(ihcd->spi->master);
+ pm_runtime_put_noidle(ihcd->spi->master->dev.parent);
+ goto out;
+ }
+
+ ret = msm_gpiomux_write(ihcd->slave_select_gpio, GPIOMUX_ACTIVE,
+ &slave_select_setting, &active_old_setting);
+ if (ret < 0) {
+ pr_err("fail to override active setting and select slave %d\n",
+ ret);
+ spi_bus_unlock(ihcd->spi->master);
+ pm_runtime_put_noidle(ihcd->spi->master->dev.parent);
goto out;
}
ret = ice40_spi_power_up(ihcd);
if (ret < 0) {
pr_err("fail to power up the chip\n");
+ spi_bus_unlock(ihcd->spi->master);
+ pm_runtime_put_noidle(ihcd->spi->master->dev.parent);
goto out;
}
@@ -1540,12 +1568,25 @@
usleep_range(1200, 1250);
ret = msm_gpiomux_write(ihcd->slave_select_gpio, GPIOMUX_SUSPENDED,
- &old_setting, NULL);
+ &suspend_old_setting, NULL);
if (ret < 0) {
- pr_err("fail to de-select the slave %d\n", ret);
+ pr_err("fail to rewrite suspend setting %d\n", ret);
+ spi_bus_unlock(ihcd->spi->master);
+ pm_runtime_put_noidle(ihcd->spi->master->dev.parent);
goto power_off;
}
+ ret = msm_gpiomux_write(ihcd->slave_select_gpio, GPIOMUX_ACTIVE,
+ &active_old_setting, NULL);
+ if (ret < 0) {
+ pr_err("fail to rewrite active setting %d\n", ret);
+ spi_bus_unlock(ihcd->spi->master);
+ pm_runtime_put_noidle(ihcd->spi->master->dev.parent);
+ goto power_off;
+ }
+
+ pm_runtime_put_noidle(ihcd->spi->master->dev.parent);
+
ret = spi_sync_locked(ihcd->spi, ihcd->fmsg);
spi_bus_unlock(ihcd->spi->master);
@@ -1884,6 +1925,13 @@
ihcd->port_flags |= (USB_PORT_STAT_C_CONNECTION << 16);
ihcd->pcd_pending = true;
usb_hcd_poll_rh_status(ihcd->hcd);
+ } else if (!strcmp(buf, "config_test")) {
+ ice40_spi_power_off(ihcd);
+ ret = ice40_spi_load_fw(ihcd);
+ if (ret) {
+ pr_err("config load failed\n");
+ goto out;
+ }
} else {
ret = -EINVAL;
goto out;
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 4b378a3..9ef2ea4 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -4260,6 +4260,10 @@
if (reg == TAIKO_A_RX_HPH_L_STATUS || reg == TAIKO_A_RX_HPH_R_STATUS)
return 1;
+ /* HPH PA Enable */
+ if (reg == TAIKO_A_RX_HPH_CNP_EN)
+ return 1;
+
if (reg == TAIKO_A_MBHC_INSERT_DET_STATUS)
return 1;
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
index b104a6b..eb3a0ba 100644
--- a/sound/soc/codecs/wcd9xxx-common.c
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -651,6 +651,29 @@
}
EXPORT_SYMBOL(wcd9xxx_restore_registers);
+static void wcd9xxx_dynamic_bypass_buck_ctrl(struct snd_soc_codec *cdc,
+ bool enable)
+{
+ int i;
+ const struct wcd9xxx_reg_mask_val reg_set[] = {
+ {WCD9XXX_A_BUCK_MODE_3, (0x1 << 3), (enable << 3)},
+ {WCD9XXX_A_BUCK_MODE_5, (0x1 << 1), (enable << 1)},
+ {WCD9XXX_A_BUCK_MODE_5, 0x1, enable}
+ };
+ if (!enable) {
+ snd_soc_update_bits(cdc, WCD9XXX_A_BUCK_MODE_1,
+ (0x1 << 3), 0x00);
+ snd_soc_update_bits(cdc, WCD9XXX_A_BUCK_MODE_4,
+ 0xFF, BUCK_VREF_2V);
+ }
+ for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+ snd_soc_update_bits(cdc, reg_set[i].reg, reg_set[i].mask,
+ reg_set[i].val);
+
+ /* 50us sleep is reqd. as per the class H HW design sequence */
+ usleep_range(BUCK_SETTLE_TIME_US, BUCK_SETTLE_TIME_US+10);
+}
+
static void wcd9xxx_set_buck_mode(struct snd_soc_codec *codec, u8 buck_vref)
{
int i;
@@ -807,6 +830,239 @@
__func__);
}
+static void wcd9xxx_ncp_bypass_enable(struct snd_soc_codec *cdc, bool enable)
+{
+ snd_soc_update_bits(cdc, WCD9XXX_A_NCP_STATIC, 0x10, (enable << 4));
+ /* 50us sleep is reqd. as per the class H HW design sequence */
+ usleep_range(BUCK_SETTLE_TIME_US, BUCK_SETTLE_TIME_US+10);
+}
+
+static void wcd9xxx_clsh_set_Iest(struct snd_soc_codec *codec,
+ u8 value)
+{
+ snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_5,
+ 0x01, (0x01 & 0x03));
+ snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_5,
+ 0xFC, (value << 2));
+}
+
+static void wcd9xxx_clsh_state_hph_ear(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ u8 req_state, bool is_enable)
+{
+ int compute_pa = 0;
+
+ dev_dbg(codec->dev, "%s: enter %s\n", __func__,
+ is_enable ? "enable" : "disable");
+
+ if (is_enable) {
+ /*
+ * The below check condition is required to make sure
+ * functions inside if condition will execute only once.
+ */
+ if ((clsh_d->state == WCD9XXX_CLSH_STATE_EAR) ||
+ (req_state == WCD9XXX_CLSH_STATE_EAR)) {
+ wcd9xxx_dynamic_bypass_buck_ctrl(codec, false);
+ wcd9xxx_ncp_bypass_enable(codec, true);
+ }
+ switch (req_state) {
+ case WCD9XXX_CLSH_STATE_HPHL:
+ compute_pa = CLSH_COMPUTE_HPH_L;
+ break;
+ case WCD9XXX_CLSH_STATE_HPHR:
+ compute_pa = CLSH_COMPUTE_HPH_R;
+ break;
+ case WCD9XXX_CLSH_STATE_EAR:
+ compute_pa = CLSH_COMPUTE_EAR;
+ break;
+ default:
+ dev_dbg(codec->dev,
+ "%s:Invalid state:0x%x,enable:0x%x\n",
+ __func__, req_state, is_enable);
+ break;
+ }
+ wcd9xxx_clsh_comp_req(codec, clsh_d, compute_pa, true);
+
+ dev_dbg(codec->dev, "%s: Enabled hph+ear mode clsh\n",
+ __func__);
+ } else {
+ switch (req_state) {
+ case WCD9XXX_CLSH_STATE_HPHL:
+ compute_pa = CLSH_COMPUTE_HPH_L;
+ break;
+ case WCD9XXX_CLSH_STATE_HPHR:
+ compute_pa = CLSH_COMPUTE_HPH_R;
+ break;
+ case WCD9XXX_CLSH_STATE_EAR:
+ compute_pa = CLSH_COMPUTE_EAR;
+ break;
+ default:
+ dev_dbg(codec->dev,
+ "%s:Invalid state:0x%x,enable:0x%x\n",
+ __func__, req_state, is_enable);
+ break;
+ }
+ wcd9xxx_clsh_comp_req(codec, clsh_d, compute_pa, false);
+
+ if (((clsh_d->state & (~req_state)) ==
+ WCD9XXX_CLSH_STATE_EAR) ||
+ (req_state == WCD9XXX_CLSH_STATE_EAR)) {
+ wcd9xxx_ncp_bypass_enable(codec, false);
+ wcd9xxx_dynamic_bypass_buck_ctrl(codec, true);
+ }
+ }
+}
+
+static void wcd9xxx_clsh_state_hph_lo(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ u8 req_state, bool is_enable)
+{
+
+ dev_dbg(codec->dev, "%s: enter %s\n", __func__,
+ is_enable ? "enable" : "disable");
+ if (is_enable) {
+ if ((clsh_d->state == WCD9XXX_CLSH_STATE_LO) ||
+ (req_state == WCD9XXX_CLSH_STATE_LO)) {
+ wcd9xxx_dynamic_bypass_buck_ctrl(codec, false);
+ wcd9xxx_enable_buck(codec, clsh_d, true);
+ wcd9xxx_set_fclk_get_ncp(codec, clsh_d,
+ NCP_FCLK_LEVEL_8);
+ if (req_state & WCD9XXX_CLSH_STATE_HPH_ST) {
+ wcd9xxx_ncp_bypass_enable(codec, true);
+ wcd9xxx_enable_clsh_block(codec, clsh_d, true);
+ wcd9xxx_chargepump_request(codec, true);
+ wcd9xxx_enable_anc_delay(codec, true);
+ }
+ }
+ if (req_state == WCD9XXX_CLSH_STATE_HPHL)
+ wcd9xxx_clsh_comp_req(codec, clsh_d,
+ CLSH_COMPUTE_HPH_L, true);
+ if (req_state == WCD9XXX_CLSH_STATE_HPHR)
+ wcd9xxx_clsh_comp_req(codec, clsh_d,
+ CLSH_COMPUTE_HPH_R, true);
+ } else {
+ switch (req_state) {
+ case WCD9XXX_CLSH_STATE_LO:
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
+ 0x20, 0x00);
+ wcd9xxx_dynamic_bypass_buck_ctrl(codec, true);
+ break;
+ case WCD9XXX_CLSH_STATE_HPHL:
+ wcd9xxx_clsh_comp_req(codec, clsh_d,
+ CLSH_COMPUTE_HPH_L, false);
+ break;
+ case WCD9XXX_CLSH_STATE_HPHR:
+ wcd9xxx_clsh_comp_req(codec, clsh_d,
+ CLSH_COMPUTE_HPH_R, false);
+ break;
+ default:
+ dev_dbg(codec->dev,
+ "%s:Invalid state:0x%x,enable:0x%x\n",
+ __func__, req_state, is_enable);
+ break;
+ }
+ if ((req_state == WCD9XXX_CLSH_STATE_LO) ||
+ ((clsh_d->state & (~req_state)) == WCD9XXX_CLSH_STATE_LO)) {
+ wcd9xxx_set_fclk_put_ncp(codec, clsh_d,
+ NCP_FCLK_LEVEL_8);
+ wcd9xxx_ncp_bypass_enable(codec, false);
+
+ if (req_state & WCD9XXX_CLSH_STATE_HPH_ST) {
+ usleep_range(BUCK_SETTLE_TIME_US,
+ BUCK_SETTLE_TIME_US + 10);
+ if (clsh_d->buck_mv ==
+ WCD9XXX_CDC_BUCK_MV_1P8) {
+ wcd9xxx_enable_buck(codec, clsh_d,
+ false);
+ wcd9xxx_ncp_bypass_enable(codec, true);
+ } else {
+ /*
+ *NCP settle time recommended by codec
+ *specification
+ */
+ usleep_range(NCP_SETTLE_TIME_US,
+ NCP_SETTLE_TIME_US + 10);
+ wcd9xxx_clsh_set_Iest(codec, 0x02);
+ }
+ snd_soc_update_bits(codec,
+ WCD9XXX_A_BUCK_MODE_1,
+ 0x04, 0x00);
+ snd_soc_update_bits(codec,
+ WCD9XXX_A_BUCK_MODE_4,
+ 0xFF, BUCK_VREF_1P8V);
+ }
+ }
+ }
+}
+
+static void wcd9xxx_clsh_state_ear_lo(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ u8 req_state, bool is_enable)
+{
+
+ dev_dbg(codec->dev, "%s: enter %s\n", __func__,
+ is_enable ? "enable" : "disable");
+ if (is_enable) {
+ wcd9xxx_dynamic_bypass_buck_ctrl(codec, false);
+ wcd9xxx_enable_buck(codec, clsh_d, true);
+ if (req_state & WCD9XXX_CLSH_STATE_EAR) {
+ wcd9xxx_set_fclk_get_ncp(codec, clsh_d,
+ NCP_FCLK_LEVEL_8);
+ wcd9xxx_ncp_bypass_enable(codec, true);
+ wcd9xxx_enable_clsh_block(codec, clsh_d, true);
+ wcd9xxx_chargepump_request(codec, true);
+ wcd9xxx_enable_anc_delay(codec, true);
+ wcd9xxx_clsh_comp_req(codec, clsh_d,
+ CLSH_COMPUTE_EAR, true);
+ }
+ } else {
+ wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
+ wcd9xxx_ncp_bypass_enable(codec, false);
+ if (req_state & WCD9XXX_CLSH_STATE_LO) {
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
+ 0x20, 0x00);
+ wcd9xxx_dynamic_bypass_buck_ctrl(codec, true);
+ } else if (req_state & WCD9XXX_CLSH_STATE_EAR) {
+ wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR,
+ false);
+ /*sleep 5ms*/
+ if (clsh_d->buck_mv == WCD9XXX_CDC_BUCK_MV_1P8) {
+ wcd9xxx_enable_buck(codec, clsh_d, false);
+ wcd9xxx_ncp_bypass_enable(codec, true);
+ } else {
+ /* NCP settle time recommended by codec spec */
+ usleep_range(NCP_SETTLE_TIME_US,
+ NCP_SETTLE_TIME_US + 10);
+ wcd9xxx_clsh_set_Iest(codec, 0x02);
+ }
+ snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1,
+ 0x04, 0x00);
+ snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_4,
+ 0xFF, BUCK_VREF_1P8V);
+ }
+ }
+}
+
+static void wcd9xxx_clsh_state_hph_ear_lo(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ u8 req_state, bool is_enable)
+{
+ dev_dbg(codec->dev, "%s: enter %s\n", __func__,
+ is_enable ? "enable" : "disable");
+
+ if (req_state & WCD9XXX_CLSH_STATE_HPHL)
+ wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L,
+ is_enable);
+
+ if (req_state & WCD9XXX_CLSH_STATE_HPHR)
+ wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R,
+ is_enable);
+
+ if (req_state & WCD9XXX_CLSH_STATE_EAR)
+ wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR,
+ is_enable);
+}
+
static void wcd9xxx_clsh_state_ear(struct snd_soc_codec *codec,
struct wcd9xxx_clsh_cdc_data *clsh_d,
u8 req_state, bool is_enable)
@@ -895,10 +1151,20 @@
pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
if (is_enable) {
- wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L, true);
- wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, true);
+ if (req_state == WCD9XXX_CLSH_STATE_HPHL)
+ wcd9xxx_clsh_comp_req(codec, clsh_d,
+ CLSH_COMPUTE_HPH_L, true);
+ if (req_state == WCD9XXX_CLSH_STATE_HPHR)
+ wcd9xxx_clsh_comp_req(codec, clsh_d,
+ CLSH_COMPUTE_HPH_R, true);
} else {
dev_dbg(codec->dev, "%s: stub fallback to hph_st\n", __func__);
+ if (req_state == WCD9XXX_CLSH_STATE_HPHL)
+ wcd9xxx_clsh_comp_req(codec, clsh_d,
+ CLSH_COMPUTE_HPH_L, false);
+ if (req_state == WCD9XXX_CLSH_STATE_HPHR)
+ wcd9xxx_clsh_comp_req(codec, clsh_d,
+ CLSH_COMPUTE_HPH_R, false);
}
}
@@ -952,6 +1218,47 @@
WARN_ON(1);
}
+/*
+ * Function: wcd9xxx_clsh_is_state_valid
+ * Params: state
+ * Description:
+ * Provides information on valid states of Class H configuration
+ */
+static int wcd9xxx_clsh_is_state_valid(u8 state)
+{
+ switch (state) {
+ case WCD9XXX_CLSH_STATE_IDLE:
+ case WCD9XXX_CLSH_STATE_EAR:
+ case WCD9XXX_CLSH_STATE_HPHL:
+ case WCD9XXX_CLSH_STATE_HPHR:
+ case WCD9XXX_CLSH_STATE_HPH_ST:
+ case WCD9XXX_CLSH_STATE_LO:
+ case WCD9XXX_CLSH_STATE_HPHL_EAR:
+ case WCD9XXX_CLSH_STATE_HPHR_EAR:
+ case WCD9XXX_CLSH_STATE_HPH_ST_EAR:
+ case WCD9XXX_CLSH_STATE_HPHL_LO:
+ case WCD9XXX_CLSH_STATE_HPHR_LO:
+ case WCD9XXX_CLSH_STATE_HPH_ST_LO:
+ case WCD9XXX_CLSH_STATE_EAR_LO:
+ case WCD9XXX_CLSH_STATE_HPHL_EAR_LO:
+ case WCD9XXX_CLSH_STATE_HPHR_EAR_LO:
+ case WCD9XXX_CLSH_STATE_HPH_ST_EAR_LO:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Function: wcd9xxx_clsh_fsm
+ * Params: codec, cdc_clsh_d, req_state, req_type, clsh_event
+ * Description:
+ * This function handles PRE DAC and POST DAC conditions of different devices
+ * and updates class H configuration of different combination of devices
+ * based on validity of their states. cdc_clsh_d will contain current
+ * class h state information
+ */
void wcd9xxx_clsh_fsm(struct snd_soc_codec *codec,
struct wcd9xxx_clsh_cdc_data *cdc_clsh_d,
u8 req_state, bool req_type, u8 clsh_event)
@@ -967,10 +1274,25 @@
old_state = cdc_clsh_d->state;
new_state = old_state | req_state;
- (*clsh_state_fp[req_state]) (codec, cdc_clsh_d, req_state,
+ if (!wcd9xxx_clsh_is_state_valid(new_state)) {
+ dev_dbg(codec->dev,
+ "%s: classH not a valid new state: %s\n",
+ __func__,
+ state_to_str(new_state, msg0, sizeof(msg0)));
+ return;
+ }
+ if (new_state == old_state) {
+ dev_dbg(codec->dev,
+ "%s: classH already in requested state: %s\n",
+ __func__,
+ state_to_str(new_state, msg0, sizeof(msg0)));
+ return;
+ }
+ (*clsh_state_fp[new_state]) (codec, cdc_clsh_d, req_state,
req_type);
cdc_clsh_d->state = new_state;
- dev_dbg(codec->dev, "%s: ClassH state transition from %s to %s\n",
+ dev_dbg(codec->dev,
+ "%s: ClassH state transition from %s to %s\n",
__func__, state_to_str(old_state, msg0, sizeof(msg0)),
state_to_str(cdc_clsh_d->state, msg1, sizeof(msg1)));
@@ -981,7 +1303,23 @@
new_state = old_state & (~req_state);
if (new_state < NUM_CLSH_STATES) {
- (*clsh_state_fp[req_state]) (codec, cdc_clsh_d,
+ if (!wcd9xxx_clsh_is_state_valid(old_state)) {
+ dev_dbg(codec->dev,
+ "%s:Invalid old state:%s\n",
+ __func__,
+ state_to_str(old_state, msg0,
+ sizeof(msg0)));
+ return;
+ }
+ if (new_state == old_state) {
+ dev_dbg(codec->dev,
+ "%s: clsH already in old state: %s\n",
+ __func__,
+ state_to_str(new_state, msg0,
+ sizeof(msg0)));
+ return;
+ }
+ (*clsh_state_fp[old_state]) (codec, cdc_clsh_d,
req_state,
req_type);
cdc_clsh_d->state = new_state;
@@ -992,7 +1330,7 @@
sizeof(msg1)));
} else {
- dev_dbg(codec->dev, "%s: wrong new state = %x\n",
+ dev_dbg(codec->dev, "%s:wrong new state=0x%x\n",
__func__, new_state);
}
} else if (!(cdc_clsh_d->state & WCD9XXX_CLSH_STATE_LO)) {
@@ -1023,6 +1361,23 @@
clsh_state_fp[WCD9XXX_CLSH_STATE_HPH_ST] =
wcd9xxx_clsh_state_hph_st;
clsh_state_fp[WCD9XXX_CLSH_STATE_LO] = wcd9xxx_clsh_state_lo;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_HPHL_EAR] =
+ wcd9xxx_clsh_state_hph_ear;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_HPHR_EAR] =
+ wcd9xxx_clsh_state_hph_ear;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_HPH_ST_EAR] =
+ wcd9xxx_clsh_state_hph_ear;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_HPHL_LO] = wcd9xxx_clsh_state_hph_lo;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_HPHR_LO] = wcd9xxx_clsh_state_hph_lo;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_HPH_ST_LO] =
+ wcd9xxx_clsh_state_hph_lo;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_EAR_LO] = wcd9xxx_clsh_state_ear_lo;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_HPHL_EAR_LO] =
+ wcd9xxx_clsh_state_hph_ear_lo;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_HPHR_EAR_LO] =
+ wcd9xxx_clsh_state_hph_ear_lo;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_HPH_ST_EAR_LO] =
+ wcd9xxx_clsh_state_hph_ear_lo;
}
EXPORT_SYMBOL_GPL(wcd9xxx_clsh_init);
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index 324f6e9..13f91ed 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -35,7 +35,7 @@
#define WCD9XXX_CLSH_STATE_HPHL (0x01 << 1)
#define WCD9XXX_CLSH_STATE_HPHR (0x01 << 2)
#define WCD9XXX_CLSH_STATE_LO (0x01 << 3)
-#define NUM_CLSH_STATES ((0x01 << 4) - 1)
+#define NUM_CLSH_STATES (0x01 << 4)
#define WCD9XXX_DMIC_SAMPLE_RATE_DIV_2 0x0
#define WCD9XXX_DMIC_SAMPLE_RATE_DIV_3 0x1
@@ -56,6 +56,34 @@
#define WCD9XXX_CLSH_STATE_HPH_ST (WCD9XXX_CLSH_STATE_HPHL | \
WCD9XXX_CLSH_STATE_HPHR)
+#define WCD9XXX_CLSH_STATE_HPHL_EAR (WCD9XXX_CLSH_STATE_HPHL | \
+ WCD9XXX_CLSH_STATE_EAR)
+#define WCD9XXX_CLSH_STATE_HPHR_EAR (WCD9XXX_CLSH_STATE_HPHR | \
+ WCD9XXX_CLSH_STATE_EAR)
+
+#define WCD9XXX_CLSH_STATE_HPH_ST_EAR (WCD9XXX_CLSH_STATE_HPH_ST | \
+ WCD9XXX_CLSH_STATE_EAR)
+
+#define WCD9XXX_CLSH_STATE_HPHL_LO (WCD9XXX_CLSH_STATE_HPHL | \
+ WCD9XXX_CLSH_STATE_LO)
+#define WCD9XXX_CLSH_STATE_HPHR_LO (WCD9XXX_CLSH_STATE_HPHR | \
+ WCD9XXX_CLSH_STATE_LO)
+
+#define WCD9XXX_CLSH_STATE_HPH_ST_LO (WCD9XXX_CLSH_STATE_HPH_ST | \
+ WCD9XXX_CLSH_STATE_LO)
+
+#define WCD9XXX_CLSH_STATE_EAR_LO (WCD9XXX_CLSH_STATE_EAR | \
+ WCD9XXX_CLSH_STATE_LO)
+
+#define WCD9XXX_CLSH_STATE_HPHL_EAR_LO (WCD9XXX_CLSH_STATE_HPHL | \
+ WCD9XXX_CLSH_STATE_EAR | \
+ WCD9XXX_CLSH_STATE_LO)
+#define WCD9XXX_CLSH_STATE_HPHR_EAR_LO (WCD9XXX_CLSH_STATE_HPHR | \
+ WCD9XXX_CLSH_STATE_EAR | \
+ WCD9XXX_CLSH_STATE_LO)
+#define WCD9XXX_CLSH_STATE_HPH_ST_EAR_LO (WCD9XXX_CLSH_STATE_HPH_ST | \
+ WCD9XXX_CLSH_STATE_EAR | \
+ WCD9XXX_CLSH_STATE_LO)
struct wcd9xxx_reg_mask_val {
u16 reg;