Merge "soc: swr-mstr: Avoid race condition during device up"
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index 5001b7f..d6a196b 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -428,7 +428,7 @@
{
struct bolero_priv *priv;
u16 mclk_mux0_macro, mclk_mux1_macro;
- int ret = 0;
+ int ret = 0, ret1 = 0;
if (!dev) {
pr_err("%s: dev is null\n", __func__);
@@ -468,24 +468,32 @@
dev_err(dev,
"%s: MCLK_MUX0 en failed for macro:%d mclk_mux0_macro:%d\n",
__func__, macro_id, mclk_mux0_macro);
- goto err;
+ /*
+ * for disable case, need to proceed still for mclk_mux1
+ * counter to decrement
+ */
+ if (enable)
+ goto err;
}
- ret = priv->macro_params[mclk_mux1_macro].mclk_fn(
+ /*
+ * need different return value as ret variable
+ * is used to track mclk_mux0 enable success or fail
+ */
+ ret1 = priv->macro_params[mclk_mux1_macro].mclk_fn(
priv->macro_params[mclk_mux1_macro].dev, enable);
- if (ret < 0) {
+ if (ret1 < 0)
dev_err(dev,
"%s: MCLK_MUX1 %s failed for macro:%d, mclk_mux1_macro:%d\n",
__func__,
enable ? "enable" : "disable",
macro_id, mclk_mux1_macro);
+ /* disable mclk_mux0 only if ret is success(0) */
+ if (!ret)
priv->macro_params[mclk_mux0_macro].mclk_fn(
priv->macro_params[mclk_mux0_macro].dev,
false);
+ if (enable && ret1)
goto err;
- }
- priv->macro_params[mclk_mux0_macro].mclk_fn(
- priv->macro_params[mclk_mux0_macro].dev,
- false);
break;
case MCLK_MUX_MAX:
default:
diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c
index 37cfefe..986375d 100644
--- a/asoc/codecs/bolero/rx-macro.c
+++ b/asoc/codecs/bolero/rx-macro.c
@@ -343,6 +343,7 @@
int rx_mclk_cnt;
bool is_native_on;
bool is_ear_mode_on;
+ bool dev_up;
u16 mclk_mux;
struct mutex mclk_lock;
struct mutex swr_clk_lock;
@@ -1087,16 +1088,20 @@
__func__);
return ret;
}
- if (rx_priv->rx_mclk_cnt++ == 0)
- iowrite32(0x1, rx_priv->rx_mclk_mode_muxsel);
+ if (rx_priv->rx_mclk_cnt++ == 0) {
+ if (rx_priv->dev_up)
+ iowrite32(0x1, rx_priv->rx_mclk_mode_muxsel);
+ }
} else {
if (rx_priv->rx_mclk_cnt <= 0) {
dev_dbg(dev, "%s:rx mclk already disabled\n", __func__);
rx_priv->rx_mclk_cnt = 0;
return 0;
}
- if (--rx_priv->rx_mclk_cnt == 0)
- iowrite32(0x0, rx_priv->rx_mclk_mode_muxsel);
+ if (--rx_priv->rx_mclk_cnt == 0) {
+ if (rx_priv->dev_up)
+ iowrite32(0x0, rx_priv->rx_mclk_mode_muxsel);
+ }
clk_disable_unprepare(rx_priv->rx_npl_clk);
clk_disable_unprepare(rx_priv->rx_core_clk);
}
@@ -1132,6 +1137,7 @@
rx_macro_wcd_clsh_imped_config(codec, data, false);
break;
case BOLERO_MACRO_EVT_SSR_DOWN:
+ rx_priv->dev_up = false;
swrm_wcd_notify(
rx_priv->swr_ctrl_data[0].rx_swr_pdev,
SWR_DEVICE_SSR_DOWN, NULL);
@@ -1140,6 +1146,12 @@
SWR_DEVICE_DOWN, NULL);
break;
case BOLERO_MACRO_EVT_SSR_UP:
+ rx_priv->dev_up = true;
+ /* enable&disable MCLK_MUX1 to reset GFMUX reg */
+ bolero_request_clock(rx_priv->dev,
+ RX_MACRO, MCLK_MUX1, true);
+ bolero_request_clock(rx_priv->dev,
+ RX_MACRO, MCLK_MUX1, false);
swrm_wcd_notify(
rx_priv->swr_ctrl_data[0].rx_swr_pdev,
SWR_DEVICE_SSR_UP, NULL);
@@ -3028,6 +3040,7 @@
dev_err(rx_dev, "%s: failed to add snd_ctls\n", __func__);
return ret;
}
+ rx_priv->dev_up = true;
snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF1 Playback");
snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF2 Playback");
snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF3 Playback");
diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c
index 9a6dff3..ec870ad 100644
--- a/asoc/codecs/bolero/wsa-macro.c
+++ b/asoc/codecs/bolero/wsa-macro.c
@@ -756,6 +756,11 @@
struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
int ret = 0;
+ if (regmap == NULL) {
+ dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
+ return -EINVAL;
+ }
+
dev_dbg(wsa_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
__func__, mclk_enable, dapm, wsa_priv->wsa_mclk_users);
@@ -2431,6 +2436,11 @@
struct wsa_macro_priv *wsa_priv = (struct wsa_macro_priv *) handle;
struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
+ if (regmap == NULL) {
+ dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
+ return -EINVAL;
+ }
+
mutex_lock(&wsa_priv->swr_clk_lock);
dev_dbg(wsa_priv->dev, "%s: swrm clock %s\n",
diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c
index 864aeda..8436605 100644
--- a/asoc/codecs/wcd937x/wcd937x.c
+++ b/asoc/codecs/wcd937x/wcd937x.c
@@ -166,7 +166,7 @@
char *prop, u8 path)
{
u32 *dt_array, map_size, map_length;
- u32 port_num, ch_mask, ch_rate, old_port_num = 0;
+ u32 port_num = 0, ch_mask, ch_rate, old_port_num = 0;
u32 slave_port_type, master_port_type;
u32 i, ch_iter = 0;
int ret = 0;
@@ -188,7 +188,8 @@
if (!of_find_property(dev->of_node, prop,
&map_size)) {
dev_err(dev, "missing port mapping prop %s\n", prop);
- goto err_pdata_fail;
+ ret = -EINVAL;
+ goto err;
}
map_length = map_size / (NUM_SWRS_DT_PARAMS * sizeof(u32));
@@ -197,13 +198,14 @@
if (!dt_array) {
ret = -ENOMEM;
- goto err_pdata_fail;
+ goto err;
}
ret = of_property_read_u32_array(dev->of_node, prop, dt_array,
NUM_SWRS_DT_PARAMS * map_length);
if (ret) {
dev_err(dev, "%s: Failed to read port mapping from prop %s\n",
__func__, prop);
+ ret = -EINVAL;
goto err_pdata_fail;
}
@@ -230,7 +232,8 @@
err_pdata_fail:
kfree(dt_array);
- return -EINVAL;
+err:
+ return ret;
}
static int wcd937x_tx_connect_port(struct snd_soc_codec *codec,
diff --git a/asoc/codecs/wcd937x/wcd937x_slave.c b/asoc/codecs/wcd937x/wcd937x_slave.c
index 252504f..baab26f 100644
--- a/asoc/codecs/wcd937x/wcd937x_slave.c
+++ b/asoc/codecs/wcd937x/wcd937x_slave.c
@@ -31,6 +31,11 @@
uint8_t devnum = 0;
struct swr_device *pdev = to_swr_device(dev);
+ if (pdev == NULL) {
+ dev_err(dev, "%s: pdev is NULL\n", __func__);
+ return -EINVAL;
+ }
+
wcd937x_slave = devm_kzalloc(&pdev->dev,
sizeof(struct wcd937x_slave_priv), GFP_KERNEL);
if (!wcd937x_slave)
@@ -59,6 +64,11 @@
struct wcd937x_slave_priv *wcd937x_slave = NULL;
struct swr_device *pdev = to_swr_device(dev);
+ if (pdev == NULL) {
+ dev_err(dev, "%s: pdev is NULL\n", __func__);
+ return;
+ }
+
wcd937x_slave = swr_get_dev_data(pdev);
if (!wcd937x_slave) {
dev_err(&pdev->dev, "%s: wcd937x_slave is NULL\n", __func__);
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 83bba1c..516b83f 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -1932,6 +1932,12 @@
if (test_bit(idx, &copp))
break;
+ if (idx >= MAX_COPPS_PER_PORT) {
+ pr_debug("%s: copp idx is invalid, exiting\n",
+ __func__);
+ mutex_unlock(&routing_lock);
+ return;
+ }
port_id = msm_bedais[reg].port_id;
topology = adm_get_topology_for_port_copp_idx(port_id,
idx);
@@ -22898,6 +22904,12 @@
for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
if (test_bit(idx, &copp))
break;
+
+ if (idx >= MAX_COPPS_PER_PORT) {
+ pr_debug("%s: copp idx is invalid, exiting\n",
+ __func__);
+ continue;
+ }
fdai->be_srate = bedai->sample_rate;
port_id = bedai->port_id;
topology = adm_get_topology_for_port_copp_idx(port_id,
diff --git a/dsp/q6adm.c b/dsp/q6adm.c
index 4e621a9..b9c11ac 100644
--- a/dsp/q6adm.c
+++ b/dsp/q6adm.c
@@ -2833,6 +2833,9 @@
(topology == VPM_TX_DM_RFECNS_COPP_TOPOLOGY))
rate = 16000;
+ if (topology == VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY)
+ channel_mode = 1;
+
/*
* Routing driver reuses the same adm for streams with the same
* app_type, sample_rate etc.
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index fe55341..ddcc101 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -4892,6 +4892,7 @@
#define COMPRESSED_PASSTHROUGH_DEFAULT_TOPOLOGY 0x0001076B
#define COMPRESSED_PASSTHROUGH_NONE_TOPOLOGY 0x00010774
#define VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY 0x00010F89
+#define VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY 0x10000003
#define VPM_TX_DM_FLUENCE_COPP_TOPOLOGY 0x00010F72
#define VPM_TX_QMIC_FLUENCE_COPP_TOPOLOGY 0x00010F75
#define VPM_TX_DM_RFECNS_COPP_TOPOLOGY 0x00010F86