summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2020-03-19 19:30:57 -0700
committerLinux Build Service Account <lnxbuild@localhost>2020-03-19 19:30:57 -0700
commit3b497dc42c40b14bd740efa7dc023a9c87f14176 (patch)
treec5fd5048f1fa30abc2c95ad16055c786e7030d3f
parentac42fe0d68e839d0240031ae0d91ff3975b9bc5c (diff)
parentb51434354d9c6d47fd5cfa04eb71353cbd9aac0b (diff)
downloadmsm-extra-3b497dc42c40b14bd740efa7dc023a9c87f14176.tar.gz
Merge b51434354d9c6d47fd5cfa04eb71353cbd9aac0b on remote branch
Change-Id: Iee7de7e9ab5fa01478b68a82bb2d77b22e3f21dc
-rw-r--r--4.0/asoc/codecs/bolero/bolero-cdc.c58
-rw-r--r--4.0/asoc/codecs/bolero/rx-macro.c7
-rw-r--r--4.0/asoc/codecs/bolero/tx-macro.c105
-rw-r--r--4.0/asoc/codecs/bolero/va-macro.c213
-rw-r--r--4.0/asoc/codecs/bolero/wsa-macro.c7
-rw-r--r--4.0/asoc/codecs/wcd-mbhc-adc.c1
-rw-r--r--4.0/asoc/codecs/wcd-mbhc-v2.c22
-rw-r--r--4.0/asoc/codecs/wcd937x/wcd937x-mbhc.h3
-rw-r--r--4.0/asoc/codecs/wcd937x/wcd937x.c13
-rw-r--r--4.0/asoc/codecs/wcd938x/internal.h1
-rw-r--r--4.0/asoc/codecs/wcd938x/wcd938x.c176
-rw-r--r--4.0/asoc/msm-dai-q6-v2.c1
-rw-r--r--4.0/asoc/msm-lsm-client.c36
-rw-r--r--4.0/asoc/msm-pcm-loopback-v2.c18
-rw-r--r--4.0/asoc/msm-pcm-q6-noirq.c4
-rw-r--r--4.0/asoc/msm-pcm-q6-v2.c6
-rw-r--r--4.0/dsp/codecs/audio_native.c5
-rw-r--r--4.0/dsp/codecs/audio_utils.c5
-rw-r--r--4.0/dsp/codecs/audio_utils_aio.c4
-rw-r--r--4.0/dsp/codecs/q6audio_common.h4
-rw-r--r--4.0/dsp/codecs/q6audio_v2.c9
-rw-r--r--4.0/dsp/codecs/q6audio_v2_aio.c7
-rw-r--r--4.0/dsp/msm_audio_ion_vm.c3
-rw-r--r--4.0/dsp/q6afe.c2
-rw-r--r--4.0/dsp/q6asm.c19
-rw-r--r--4.0/include/soc/soundwire.h7
-rw-r--r--4.0/include/soc/swr-wcd.h1
-rw-r--r--4.0/soc/pinctrl-lpi.c2
-rw-r--r--4.0/soc/swr-mstr-ctrl.c277
-rw-r--r--4.0/soc/swr-mstr-ctrl.h5
-rw-r--r--asoc/codecs/bolero/tx-macro.c40
-rw-r--r--dsp/q6lsm.c2
32 files changed, 805 insertions, 258 deletions
diff --git a/4.0/asoc/codecs/bolero/bolero-cdc.c b/4.0/asoc/codecs/bolero/bolero-cdc.c
index ce646fcc..5ddc674e 100644
--- a/4.0/asoc/codecs/bolero/bolero-cdc.c
+++ b/4.0/asoc/codecs/bolero/bolero-cdc.c
@@ -99,24 +99,32 @@ static int __bolero_reg_read(struct bolero_priv *priv,
goto ssr_err;
}
- if (priv->macro_params[VA_MACRO].dev)
+ if (priv->macro_params[VA_MACRO].dev) {
pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev);
+ if (!bolero_check_core_votes(priv->macro_params[VA_MACRO].dev))
+ goto ssr_err;
+ }
- /* Request Clk before register access */
- ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+ if (priv->version < BOLERO_VERSION_2_0) {
+ /* Request Clk before register access */
+ ret = bolero_clk_rsc_request_clock(
+ priv->macro_params[macro_id].dev,
priv->macro_params[macro_id].default_clk_id,
priv->macro_params[macro_id].clk_id_req,
true);
- if (ret < 0) {
- dev_err_ratelimited(priv->dev,
- "%s: Failed to enable clock, ret:%d\n", __func__, ret);
- goto err;
+ if (ret < 0) {
+ dev_err_ratelimited(priv->dev,
+ "%s: Failed to enable clock, ret:%d\n",
+ __func__, ret);
+ goto err;
+ }
}
bolero_ahb_read_device(
priv->macro_params[macro_id].io_base, reg, val);
- bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+ if (priv->version < BOLERO_VERSION_2_0)
+ bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
priv->macro_params[macro_id].default_clk_id,
priv->macro_params[macro_id].clk_id_req,
false);
@@ -143,24 +151,32 @@ static int __bolero_reg_write(struct bolero_priv *priv,
ret = -EINVAL;
goto ssr_err;
}
- if (priv->macro_params[VA_MACRO].dev)
+ if (priv->macro_params[VA_MACRO].dev) {
pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev);
+ if (!bolero_check_core_votes(priv->macro_params[VA_MACRO].dev))
+ goto ssr_err;
+ }
- /* Request Clk before register access */
- ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+ if (priv->version < BOLERO_VERSION_2_0) {
+ /* Request Clk before register access */
+ ret = bolero_clk_rsc_request_clock(
+ priv->macro_params[macro_id].dev,
priv->macro_params[macro_id].default_clk_id,
priv->macro_params[macro_id].clk_id_req,
true);
- if (ret < 0) {
- dev_err_ratelimited(priv->dev,
- "%s: Failed to enable clock, ret:%d\n", __func__, ret);
- goto err;
+ if (ret < 0) {
+ dev_err_ratelimited(priv->dev,
+ "%s: Failed to enable clock, ret:%d\n",
+ __func__, ret);
+ goto err;
+ }
}
bolero_ahb_write_device(
priv->macro_params[macro_id].io_base, reg, val);
- bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+ if (priv->version < BOLERO_VERSION_2_0)
+ bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
priv->macro_params[macro_id].default_clk_id,
priv->macro_params[macro_id].clk_id_req,
false);
@@ -1078,6 +1094,7 @@ int bolero_register_event_listener(struct snd_soc_codec *codec,
return ret;
}
EXPORT_SYMBOL(bolero_register_event_listener);
+
static int bolero_soc_codec_probe(struct snd_soc_codec *codec)
{
struct bolero_priv *priv = dev_get_drvdata(codec->dev);
@@ -1276,6 +1293,13 @@ static int bolero_probe(struct platform_device *pdev)
__func__);
ret = 0;
}
+ if (priv->version == BOLERO_VERSION_2_1) {
+ bolero_reg_access[TX_MACRO] = bolero_tx_reg_access_v2;
+ bolero_reg_access[VA_MACRO] = bolero_va_reg_access_v2;
+ } else if (priv->version == BOLERO_VERSION_2_0) {
+ bolero_reg_access[VA_MACRO] = bolero_va_reg_access_v3;
+ }
+
priv->dev = &pdev->dev;
priv->dev_up = true;
priv->initial_boot = true;
@@ -1342,6 +1366,7 @@ static int bolero_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
int bolero_runtime_resume(struct device *dev)
{
struct bolero_priv *priv = dev_get_drvdata(dev->parent);
@@ -1423,6 +1448,7 @@ int bolero_runtime_suspend(struct device *dev)
return 0;
}
EXPORT_SYMBOL(bolero_runtime_suspend);
+#endif /* CONFIG_PM */
bool bolero_check_core_votes(struct device *dev)
{
diff --git a/4.0/asoc/codecs/bolero/rx-macro.c b/4.0/asoc/codecs/bolero/rx-macro.c
index aaf39dd9..cfba3d5b 100644
--- a/4.0/asoc/codecs/bolero/rx-macro.c
+++ b/4.0/asoc/codecs/bolero/rx-macro.c
@@ -1367,9 +1367,6 @@ static int rx_macro_event_handler(struct snd_soc_codec *codec, u16 event,
if (rx_priv->swr_ctrl_data) {
swrm_wcd_notify(
rx_priv->swr_ctrl_data[0].rx_swr_pdev,
- SWR_DEVICE_DOWN, NULL);
- swrm_wcd_notify(
- rx_priv->swr_ctrl_data[0].rx_swr_pdev,
SWR_DEVICE_SSR_DOWN, NULL);
}
if ((!pm_runtime_enabled(rx_dev) ||
@@ -4048,6 +4045,10 @@ static const struct of_device_id rx_macro_dt_match[] = {
};
static const struct dev_pm_ops bolero_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(
+ pm_runtime_force_suspend,
+ pm_runtime_force_resume
+ )
SET_RUNTIME_PM_OPS(
bolero_runtime_suspend,
bolero_runtime_resume,
diff --git a/4.0/asoc/codecs/bolero/tx-macro.c b/4.0/asoc/codecs/bolero/tx-macro.c
index 4da74cce..8acb6405 100644
--- a/4.0/asoc/codecs/bolero/tx-macro.c
+++ b/4.0/asoc/codecs/bolero/tx-macro.c
@@ -376,9 +376,6 @@ static int tx_macro_event_handler(struct snd_soc_codec *codec, u16 event,
if (tx_priv->swr_ctrl_data) {
swrm_wcd_notify(
tx_priv->swr_ctrl_data[0].tx_swr_pdev,
- SWR_DEVICE_DOWN, NULL);
- swrm_wcd_notify(
- tx_priv->swr_ctrl_data[0].tx_swr_pdev,
SWR_DEVICE_SSR_DOWN, NULL);
}
if ((!pm_runtime_enabled(tx_dev) ||
@@ -439,19 +436,26 @@ static int is_amic_enabled(struct snd_soc_codec *codec, int decimator)
{
u16 adc_mux_reg = 0, adc_reg = 0;
u16 adc_n = BOLERO_ADC_MAX;
+ bool ret = false;
+ struct device *tx_dev = NULL;
+ struct tx_macro_priv *tx_priv = NULL;
+ if (!tx_macro_get_data(codec, &tx_dev, &tx_priv, __func__))
+ return ret;
adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
if (snd_soc_read(codec, adc_mux_reg) & SWR_MIC) {
+ if (tx_priv->version == BOLERO_VERSION_2_1)
+ return true;
adc_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
adc_n = snd_soc_read(codec, adc_reg) &
TX_MACRO_SWR_MIC_MUX_SEL_MASK;
- if (adc_n >= BOLERO_ADC_MAX)
- adc_n = BOLERO_ADC_MAX;
+ if (adc_n < BOLERO_ADC_MAX)
+ return true;
}
- return adc_n;
+ return ret;
}
static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
@@ -462,7 +466,7 @@ static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
struct snd_soc_codec *codec = NULL;
u16 dec_cfg_reg = 0, hpf_gate_reg = 0;
u8 hpf_cut_off_freq = 0;
- u16 adc_n = 0;
+ u16 adc_reg = 0, adc_n = 0;
hpf_delayed_work = to_delayed_work(work);
hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
@@ -478,8 +482,11 @@ static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
dev_dbg(codec->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
__func__, hpf_work->decimator, hpf_cut_off_freq);
- adc_n = is_amic_enabled(codec, hpf_work->decimator);
- if (adc_n < BOLERO_ADC_MAX) {
+ if (is_amic_enabled(codec, hpf_work->decimator)) {
+ adc_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+ TX_MACRO_ADC_MUX_CFG_OFFSET * hpf_work->decimator;
+ adc_n = snd_soc_read(codec, adc_reg) &
+ TX_MACRO_SWR_MIC_MUX_SEL_MASK;
/* analog mic clear TX hold */
bolero_clear_amic_tx_hold(codec->dev, adc_n);
snd_soc_update_bits(codec,
@@ -829,6 +836,8 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
int unmute_delay = TX_MACRO_DMIC_UNMUTE_DELAY_MS;
struct device *tx_dev = NULL;
struct tx_macro_priv *tx_priv = NULL;
+ u16 adc_mux_reg = 0, adc_reg = 0, adc_n = 0;
+ u16 dmic_clk_reg = 0;
if (!tx_macro_get_data(codec, &tx_dev, &tx_priv, __func__))
return -EINVAL;
@@ -849,6 +858,22 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+ TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+ if (snd_soc_read(codec, adc_mux_reg) & SWR_MIC) {
+ adc_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+ TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+ adc_n = snd_soc_read(codec, adc_reg) &
+ TX_MACRO_SWR_MIC_MUX_SEL_MASK;
+ if (adc_n >= BOLERO_ADC_MAX) {
+ dmic_clk_reg =
+ BOLERO_CDC_TX_TOP_CSR_SWR_DMIC0_CTL +
+ ((adc_n - 5) / 2) * 4;
+ snd_soc_update_bits(codec,
+ dmic_clk_reg,
+ 0x0E, tx_priv->dmic_clk_div << 0x1);
+ }
+ }
snd_soc_update_bits(codec,
dec_cfg_reg, 0x06, tx_priv->dec_mode[decimator] <<
TX_MACRO_ADC_MODE_CFG0_SHIFT);
@@ -857,12 +882,14 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
break;
case SND_SOC_DAPM_POST_PMU:
snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x20, 0x20);
- snd_soc_update_bits(codec, hpf_gate_reg, 0x01, 0x00);
- /*
- * Minimum 1 clk cycle delay is required as per HW spec
- */
- usleep_range(1000, 1010);
-
+ if (!(is_amic_enabled(codec, decimator) < BOLERO_ADC_MAX)) {
+ snd_soc_update_bits(codec,
+ hpf_gate_reg, 0x01, 0x00);
+ /*
+ * Minimum 1 clk cycle delay is required as per HW spec
+ */
+ usleep_range(1000, 1010);
+ }
hpf_cut_off_freq = (snd_soc_read(codec, dec_cfg_reg) &
TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq =
@@ -873,26 +900,30 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
TX_HPF_CUT_OFF_FREQ_MASK,
CF_MIN_3DB_150HZ << 5);
- if (is_amic_enabled(codec, decimator) < BOLERO_ADC_MAX) {
+ if (is_amic_enabled(codec, decimator)) {
hpf_delay = TX_MACRO_AMIC_HPF_DELAY_MS;
unmute_delay = TX_MACRO_AMIC_UNMUTE_DELAY_MS;
}
if (tx_unmute_delay < unmute_delay)
tx_unmute_delay = unmute_delay;
/* schedule work queue to Remove Mute */
- schedule_delayed_work(&tx_priv->tx_mute_dwork[decimator].dwork,
- msecs_to_jiffies(tx_unmute_delay));
+ queue_delayed_work(system_freezable_wq,
+ &tx_priv->tx_mute_dwork[decimator].dwork,
+ msecs_to_jiffies(tx_unmute_delay));
if (tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq !=
CF_MIN_3DB_150HZ) {
schedule_delayed_work(
&tx_priv->tx_hpf_work[decimator].dwork,
msecs_to_jiffies(hpf_delay));
- snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x02);
+ snd_soc_update_bits(codec,
+ hpf_gate_reg, 0x03, 0x02);
+ if (!is_amic_enabled(codec, decimator))
+ snd_soc_update_bits(codec,
+ hpf_gate_reg, 0x03, 0x00);
/*
* Minimum 1 clk cycle delay is required as per HW spec
*/
usleep_range(1000, 1010);
- snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x00);
snd_soc_update_bits(codec,
hpf_gate_reg, 0x01, 0x01);
/*
@@ -923,15 +954,21 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
snd_soc_update_bits(codec, dec_cfg_reg,
TX_HPF_CUT_OFF_FREQ_MASK,
hpf_cut_off_freq << 5);
- snd_soc_update_bits(codec, hpf_gate_reg,
- 0x02, 0x02);
+ if (is_amic_enabled(codec, decimator))
+ snd_soc_update_bits(codec,
+ hpf_gate_reg,
+ 0x03, 0x02);
+ else
+ snd_soc_update_bits(codec,
+ hpf_gate_reg,
+ 0x03, 0x03);
/*
* Minimum 1 clk cycle delay is required
* as per HW spec
*/
usleep_range(1000, 1010);
snd_soc_update_bits(codec, hpf_gate_reg,
- 0x02, 0x00);
+ 0x03, 0x01);
}
}
cancel_delayed_work_sync(
@@ -2292,7 +2329,8 @@ static int tx_macro_register_event_listener(struct snd_soc_codec *codec,
"%s: priv is null for macro!\n", __func__);
return -EINVAL;
}
- if (tx_priv->swr_ctrl_data && !tx_priv->tx_swr_clk_cnt) {
+ if (tx_priv->swr_ctrl_data &&
+ (!tx_priv->tx_swr_clk_cnt || !tx_priv->va_swr_clk_cnt)) {
if (enable) {
ret = swrm_wcd_notify(
tx_priv->swr_ctrl_data[0].tx_swr_pdev,
@@ -2377,11 +2415,11 @@ static int tx_macro_tx_va_mclk_enable(struct tx_macro_priv *tx_priv,
BOLERO_CDC_TX_TOP_CSR_FREQ_MCLK,
0x01, 0x01);
regmap_update_bits(regmap,
- BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+ BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
0x01, 0x01);
regmap_update_bits(regmap,
- BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
- 0x01, 0x01);
+ BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+ 0x01, 0x01);
}
tx_priv->tx_mclk_users++;
}
@@ -2437,14 +2475,15 @@ static int tx_macro_tx_va_mclk_enable(struct tx_macro_priv *tx_priv,
tx_priv->tx_mclk_users--;
if (tx_priv->tx_mclk_users == 0) {
regmap_update_bits(regmap,
- BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
- 0x01, 0x00);
+ BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+ 0x01, 0x00);
regmap_update_bits(regmap,
- BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+ BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
0x01, 0x00);
}
+
bolero_clk_rsc_fs_gen_request(tx_priv->dev,
- false);
+ false);
ret = bolero_clk_rsc_request_clock(tx_priv->dev,
TX_CORE_CLK,
VA_CORE_CLK,
@@ -3172,6 +3211,10 @@ static const struct of_device_id tx_macro_dt_match[] = {
};
static const struct dev_pm_ops bolero_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(
+ pm_runtime_force_suspend,
+ pm_runtime_force_resume
+ )
SET_RUNTIME_PM_OPS(
bolero_runtime_suspend,
bolero_runtime_resume,
diff --git a/4.0/asoc/codecs/bolero/va-macro.c b/4.0/asoc/codecs/bolero/va-macro.c
index f5aad258..dba081e7 100644
--- a/4.0/asoc/codecs/bolero/va-macro.c
+++ b/4.0/asoc/codecs/bolero/va-macro.c
@@ -201,6 +201,10 @@ static int va_macro_clk_div_get(struct snd_soc_codec *codec)
if (!va_macro_get_data(codec, &va_dev, &va_priv, __func__))
return -EINVAL;
+ if ((va_priv->version == BOLERO_VERSION_2_1)
+ && !va_priv->lpi_enable
+ && (va_priv->dmic_clk_div == VA_MACRO_CLK_DIV_16))
+ return VA_MACRO_CLK_DIV_8;
return va_priv->dmic_clk_div;
}
@@ -221,19 +225,19 @@ static int va_macro_mclk_enable(struct va_macro_priv *va_priv,
mutex_lock(&va_priv->mclk_lock);
if (mclk_enable) {
+ ret = bolero_clk_rsc_request_clock(va_priv->dev,
+ va_priv->default_clk_id,
+ va_priv->clk_id,
+ true);
+ if (ret < 0) {
+ dev_err(va_priv->dev,
+ "%s: va request clock en failed\n",
+ __func__);
+ goto exit;
+ }
+ bolero_clk_rsc_fs_gen_request(va_priv->dev,
+ true);
if (va_priv->va_mclk_users == 0) {
- ret = bolero_clk_rsc_request_clock(va_priv->dev,
- va_priv->default_clk_id,
- va_priv->clk_id,
- true);
- if (ret < 0) {
- dev_err(va_priv->dev,
- "%s: va request clock en failed\n",
- __func__);
- goto exit;
- }
- bolero_clk_rsc_fs_gen_request(va_priv->dev,
- true);
regcache_mark_dirty(regmap);
regcache_sync_region(regmap,
VA_START_OFFSET,
@@ -248,14 +252,12 @@ static int va_macro_mclk_enable(struct va_macro_priv *va_priv,
goto exit;
}
va_priv->va_mclk_users--;
- if (va_priv->va_mclk_users == 0) {
- bolero_clk_rsc_fs_gen_request(va_priv->dev,
- false);
- bolero_clk_rsc_request_clock(va_priv->dev,
- va_priv->default_clk_id,
- va_priv->clk_id,
- false);
- }
+ bolero_clk_rsc_fs_gen_request(va_priv->dev,
+ false);
+ bolero_clk_rsc_request_clock(va_priv->dev,
+ va_priv->default_clk_id,
+ va_priv->clk_id,
+ false);
}
exit:
mutex_unlock(&va_priv->mclk_lock);
@@ -322,9 +324,6 @@ static int va_macro_event_handler(struct snd_soc_codec *codec, u16 event,
if (va_priv->swr_ctrl_data) {
swrm_wcd_notify(
va_priv->swr_ctrl_data[0].va_swr_pdev,
- SWR_DEVICE_DOWN, NULL);
- swrm_wcd_notify(
- va_priv->swr_ctrl_data[0].va_swr_pdev,
SWR_DEVICE_SSR_DOWN, NULL);
}
if ((!pm_runtime_enabled(va_dev) ||
@@ -343,12 +342,11 @@ static int va_macro_event_handler(struct snd_soc_codec *codec, u16 event,
return 0;
}
-static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
+static int va_macro_swr_clk_event_v2(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec =
snd_soc_dapm_to_codec(w->dapm);
- int ret = 0;
struct device *va_dev = NULL;
struct va_macro_priv *va_priv = NULL;
@@ -356,13 +354,46 @@ static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
return -EINVAL;
dev_dbg(va_dev, "%s: event = %d\n", __func__, event);
+
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
va_priv->va_swr_clk_cnt++;
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ va_priv->va_swr_clk_cnt--;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec =
+ snd_soc_dapm_to_codec(w->dapm);
+ int ret = 0;
+ struct device *va_dev = NULL;
+ struct va_macro_priv *va_priv = NULL;
+ int clk_src = 0;
+
+ if (!va_macro_get_data(codec, &va_dev, &va_priv, __func__))
+ return -EINVAL;
+
+ dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n",
+ __func__, event, va_priv->lpi_enable);
+
+ if (!va_priv->lpi_enable)
+ return ret;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
if (va_priv->swr_ctrl_data) {
+ clk_src = CLK_SRC_VA_RCG;
ret = swrm_wcd_notify(
va_priv->swr_ctrl_data[0].va_swr_pdev,
- SWR_REQ_CLK_SWITCH, NULL);
+ SWR_REQ_CLK_SWITCH, &clk_src);
if (ret)
dev_dbg(va_dev, "%s: clock switch failed\n",
__func__);
@@ -374,14 +405,14 @@ static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
msm_cdc_pinctrl_set_wakeup_capable(
va_priv->va_swr_gpio_p, true);
if (va_priv->swr_ctrl_data) {
+ clk_src = CLK_SRC_TX_RCG;
ret = swrm_wcd_notify(
va_priv->swr_ctrl_data[0].va_swr_pdev,
- SWR_REQ_CLK_SWITCH, NULL);
+ SWR_REQ_CLK_SWITCH, &clk_src);
if (ret)
dev_dbg(va_dev, "%s: clock switch failed\n",
__func__);
}
- va_priv->va_swr_clk_cnt--;
break;
default:
dev_err(va_priv->dev,
@@ -404,8 +435,10 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w,
dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n",
__func__, event, va_priv->lpi_enable);
+
if (!va_priv->lpi_enable)
return ret;
+
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (va_priv->lpass_audio_hw_vote) {
@@ -469,6 +502,7 @@ static int va_macro_mclk_event(struct snd_soc_dapm_widget *w,
int ret = 0;
struct device *va_dev = NULL;
struct va_macro_priv *va_priv = NULL;
+ int clk_src = 0;
if (!va_macro_get_data(codec, &va_dev, &va_priv, __func__))
return -EINVAL;
@@ -490,9 +524,22 @@ static int va_macro_mclk_event(struct snd_soc_dapm_widget *w,
break;
case SND_SOC_DAPM_POST_PMD:
if (va_priv->lpi_enable) {
- if (bolero_tx_clk_switch(codec, CLK_SRC_TX_RCG))
+ if (va_priv->version == BOLERO_VERSION_2_1) {
+ if (va_priv->swr_ctrl_data) {
+ clk_src = CLK_SRC_TX_RCG;
+ ret = swrm_wcd_notify(
+ va_priv->swr_ctrl_data[0].va_swr_pdev,
+ SWR_REQ_CLK_SWITCH, &clk_src);
+ if (ret)
+ dev_dbg(va_dev,
+ "%s: clock switch failed\n",
+ __func__);
+ }
+ } else if (bolero_tx_clk_switch(codec,
+ CLK_SRC_TX_RCG)) {
dev_dbg(va_dev, "%s: clock switch failed\n",
__func__);
+ }
va_macro_mclk_enable(va_priv, 0, true);
} else {
bolero_tx_mclk_enable(codec, 0);
@@ -736,19 +783,26 @@ static int is_amic_enabled(struct snd_soc_codec *codec, int decimator)
{
u16 adc_mux_reg = 0, adc_reg = 0;
u16 adc_n = BOLERO_ADC_MAX;
+ bool ret = false;
+ struct device *va_dev = NULL;
+ struct va_macro_priv *va_priv = NULL;
+ if (!va_macro_get_data(codec, &va_dev, &va_priv, __func__))
+ return ret;
adc_mux_reg = BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1 +
VA_MACRO_ADC_MUX_CFG_OFFSET * decimator;
if (snd_soc_read(codec, adc_mux_reg) & SWR_MIC) {
+ if (va_priv->version == BOLERO_VERSION_2_1)
+ return true;
adc_reg = BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0 +
VA_MACRO_ADC_MUX_CFG_OFFSET * decimator;
adc_n = snd_soc_read(codec, adc_reg) &
VA_MACRO_SWR_MIC_MUX_SEL_MASK;
- if (adc_n >= BOLERO_ADC_MAX)
- adc_n = BOLERO_ADC_MAX;
+ if (adc_n < BOLERO_ADC_MAX)
+ return true;
}
- return adc_n;
+ return ret;
}
static void va_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
@@ -759,7 +813,7 @@ static void va_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
struct snd_soc_codec *codec;
u16 dec_cfg_reg, hpf_gate_reg;
u8 hpf_cut_off_freq;
- u16 adc_n = 0;
+ u16 adc_reg = 0, adc_n = 0;
hpf_delayed_work = to_delayed_work(work);
hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
@@ -775,8 +829,11 @@ static void va_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
dev_dbg(va_priv->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
__func__, hpf_work->decimator, hpf_cut_off_freq);
- adc_n = is_amic_enabled(codec, hpf_work->decimator);
- if (adc_n < BOLERO_ADC_MAX) {
+ if (is_amic_enabled(codec, hpf_work->decimator)) {
+ adc_reg = BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0 +
+ VA_MACRO_ADC_MUX_CFG_OFFSET * hpf_work->decimator;
+ adc_n = snd_soc_read(codec, adc_reg) &
+ VA_MACRO_SWR_MIC_MUX_SEL_MASK;
/* analog mic clear TX hold */
bolero_clear_amic_tx_hold(codec->dev, adc_n);
snd_soc_update_bits(codec,
@@ -1070,48 +1127,52 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w,
case SND_SOC_DAPM_POST_PMU:
/* Enable TX CLK */
snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x20, 0x20);
- snd_soc_update_bits(codec, hpf_gate_reg, 0x01, 0x00);
+ if (!(is_amic_enabled(codec, decimator) < BOLERO_ADC_MAX)) {
+ snd_soc_update_bits(codec,
+ hpf_gate_reg, 0x01, 0x00);
/*
* Minimum 1 clk cycle delay is required as per HW spec
*/
usleep_range(1000, 1010);
-
- hpf_cut_off_freq = (snd_soc_read(codec, dec_cfg_reg) &
+ }
+ hpf_cut_off_freq = (snd_soc_read(
+ codec, dec_cfg_reg) &
TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
va_priv->va_hpf_work[decimator].hpf_cut_off_freq =
hpf_cut_off_freq;
- if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
+ if (hpf_cut_off_freq != CF_MIN_3DB_150HZ)
snd_soc_update_bits(codec, dec_cfg_reg,
TX_HPF_CUT_OFF_FREQ_MASK,
CF_MIN_3DB_150HZ << 5);
- }
- if (is_amic_enabled(codec, decimator) < BOLERO_ADC_MAX) {
+ if (is_amic_enabled(codec, decimator)) {
hpf_delay = BOLERO_CDC_VA_TX_AMIC_HPF_DELAY_MS;
unmute_delay = BOLERO_CDC_VA_TX_AMIC_UNMUTE_DELAY_MS;
if (va_tx_unmute_delay < unmute_delay)
va_tx_unmute_delay = unmute_delay;
}
snd_soc_update_bits(codec,
- hpf_gate_reg, 0x03, 0x03);
+ hpf_gate_reg, 0x03, 0x02);
+ if (!is_amic_enabled(codec, decimator))
+ snd_soc_update_bits(codec,
+ hpf_gate_reg, 0x03, 0x00);
/*
* Minimum 1 clk cycle delay is required as per HW spec
*/
usleep_range(1000, 1010);
snd_soc_update_bits(codec,
- hpf_gate_reg, 0x02, 0x00);
- snd_soc_update_bits(codec,
- hpf_gate_reg, 0x01, 0x01);
+ hpf_gate_reg, 0x03, 0x01);
/*
* 6ms delay is required as per HW spec
*/
usleep_range(6000, 6010);
/* schedule work queue to Remove Mute */
- schedule_delayed_work(&va_priv->va_mute_dwork[decimator].dwork,
- msecs_to_jiffies(va_tx_unmute_delay));
+ queue_delayed_work(system_freezable_wq,
+ &va_priv->va_mute_dwork[decimator].dwork,
+ msecs_to_jiffies(va_tx_unmute_delay));
if (va_priv->va_hpf_work[decimator].hpf_cut_off_freq !=
CF_MIN_3DB_150HZ)
- schedule_delayed_work(
+ queue_delayed_work(system_freezable_wq,
&va_priv->va_hpf_work[decimator].dwork,
msecs_to_jiffies(hpf_delay));
/* apply gain after decimator is enabled */
@@ -1125,18 +1186,25 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w,
if (cancel_delayed_work_sync(
&va_priv->va_hpf_work[decimator].dwork)) {
if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
- snd_soc_update_bits(codec, dec_cfg_reg,
- TX_HPF_CUT_OFF_FREQ_MASK,
- hpf_cut_off_freq << 5);
- snd_soc_update_bits(codec, hpf_gate_reg,
- 0x02, 0x02);
+ snd_soc_update_bits(codec,
+ dec_cfg_reg,
+ TX_HPF_CUT_OFF_FREQ_MASK,
+ hpf_cut_off_freq << 5);
+ if (is_amic_enabled(codec, decimator))
+ snd_soc_update_bits(codec,
+ hpf_gate_reg,
+ 0x03, 0x02);
+ else
+ snd_soc_update_bits(codec,
+ hpf_gate_reg,
+ 0x03, 0x03);
/*
* Minimum 1 clk cycle delay is required
* as per HW spec
*/
usleep_range(1000, 1010);
snd_soc_update_bits(codec, hpf_gate_reg,
- 0x02, 0x00);
+ 0x03, 0x01);
}
}
cancel_delayed_work_sync(
@@ -1831,6 +1899,10 @@ static const struct snd_soc_dapm_widget va_macro_dapm_widgets_v2[] = {
SND_SOC_DAPM_SUPPLY_S("VA_TX_SWR_CLK", 0, SND_SOC_NOPM, 0, 0,
va_macro_tx_swr_clk_event_v2,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", 0, SND_SOC_NOPM, 0, 0,
+ va_macro_swr_clk_event_v2,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
};
static const struct snd_soc_dapm_widget va_macro_dapm_widgets_v3[] = {
@@ -2157,6 +2229,12 @@ static const struct snd_soc_dapm_route va_audio_map_v3[] = {
{"VA SMIC MUX3", "SWR_MIC11", "VA SWR_MIC11"},
};
+static const struct snd_soc_dapm_route va_audio_map_v2[] = {
+ {"VA_AIF1 CAP", NULL, "VA_SWR_CLK"},
+ {"VA_AIF2 CAP", NULL, "VA_SWR_CLK"},
+ {"VA_AIF3 CAP", NULL, "VA_SWR_CLK"},
+};
+
static const struct snd_soc_dapm_route va_audio_map[] = {
{"VA_AIF1 CAP", NULL, "VA_MCLK"},
{"VA_AIF2 CAP", NULL, "VA_MCLK"},
@@ -2455,6 +2533,8 @@ static const struct snd_kcontrol_new va_macro_snd_controls_common[] = {
SOC_SINGLE_SX_TLV("VA_DEC1 Volume",
BOLERO_CDC_VA_TX1_TX_VOL_CTL,
0, -84, 40, digital_gain),
+ SOC_SINGLE_EXT("LPI Enable", 0, 0, 1, 0,
+ va_macro_lpi_get, va_macro_lpi_put),
};
static const struct snd_kcontrol_new va_macro_snd_controls_v3[] = {
@@ -2594,14 +2674,25 @@ static int va_macro_init(struct snd_soc_codec *codec)
__func__);
return ret;
}
- if (va_priv->version == BOLERO_VERSION_2_0)
+ if (va_priv->version == BOLERO_VERSION_2_0) {
ret = snd_soc_dapm_add_routes(dapm,
va_audio_map_v3,
ARRAY_SIZE(va_audio_map_v3));
- if (ret < 0) {
- dev_err(va_dev, "%s: Failed to add routes\n",
- __func__);
- return ret;
+ if (ret < 0) {
+ dev_err(va_dev, "%s: Failed to add routes\n",
+ __func__);
+ return ret;
+ }
+ }
+ if (va_priv->version == BOLERO_VERSION_2_1) {
+ ret = snd_soc_dapm_add_routes(dapm,
+ va_audio_map_v2,
+ ARRAY_SIZE(va_audio_map_v2));
+ if (ret < 0) {
+ dev_err(va_dev, "%s: Failed to add routes\n",
+ __func__);
+ return ret;
+ }
}
} else {
ret = snd_soc_dapm_add_routes(dapm, va_audio_map,
@@ -3095,6 +3186,10 @@ static const struct of_device_id va_macro_dt_match[] = {
};
static const struct dev_pm_ops bolero_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(
+ pm_runtime_force_suspend,
+ pm_runtime_force_resume
+ )
SET_RUNTIME_PM_OPS(
bolero_runtime_suspend,
bolero_runtime_resume,
diff --git a/4.0/asoc/codecs/bolero/wsa-macro.c b/4.0/asoc/codecs/bolero/wsa-macro.c
index a524a0a8..18f78e23 100644
--- a/4.0/asoc/codecs/bolero/wsa-macro.c
+++ b/4.0/asoc/codecs/bolero/wsa-macro.c
@@ -991,9 +991,6 @@ static int wsa_macro_event_handler(struct snd_soc_codec *codec, u16 event,
if (wsa_priv->swr_ctrl_data) {
swrm_wcd_notify(
wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
- SWR_DEVICE_DOWN, NULL);
- swrm_wcd_notify(
- wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
SWR_DEVICE_SSR_DOWN, NULL);
}
if ((!pm_runtime_enabled(wsa_dev) ||
@@ -3173,6 +3170,10 @@ static const struct of_device_id wsa_macro_dt_match[] = {
};
static const struct dev_pm_ops bolero_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(
+ pm_runtime_force_suspend,
+ pm_runtime_force_resume
+ )
SET_RUNTIME_PM_OPS(
bolero_runtime_suspend,
bolero_runtime_resume,
diff --git a/4.0/asoc/codecs/wcd-mbhc-adc.c b/4.0/asoc/codecs/wcd-mbhc-adc.c
index 9eb5ed0f..eb2d9431 100644
--- a/4.0/asoc/codecs/wcd-mbhc-adc.c
+++ b/4.0/asoc/codecs/wcd-mbhc-adc.c
@@ -1111,6 +1111,7 @@ static irqreturn_t wcd_mbhc_adc_hs_ins_irq(int irq, void *data)
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_ISRC_EN, 0);
mbhc->is_extn_cable = true;
mbhc->btn_press_intr = false;
+ mbhc->force_linein = false;
wcd_mbhc_adc_detect_plug_type(mbhc);
WCD_MBHC_RSC_UNLOCK(mbhc);
pr_debug("%s: leave\n", __func__);
diff --git a/4.0/asoc/codecs/wcd-mbhc-v2.c b/4.0/asoc/codecs/wcd-mbhc-v2.c
index 94dc5436..0f3d74bd 100644
--- a/4.0/asoc/codecs/wcd-mbhc-v2.c
+++ b/4.0/asoc/codecs/wcd-mbhc-v2.c
@@ -630,11 +630,12 @@ void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
}
mbhc->hph_type = WCD_MBHC_HPH_NONE;
mbhc->zl = mbhc->zr = 0;
- pr_debug("%s: Reporting removal (%x)\n",
- __func__, mbhc->hph_status);
- wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
- 0, WCD_MBHC_JACK_MASK);
-
+ if (!mbhc->force_linein) {
+ pr_debug("%s: Reporting removal (%x)\n",
+ __func__, mbhc->hph_status);
+ wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
+ 0, WCD_MBHC_JACK_MASK);
+ }
if (mbhc->hph_status == SND_JACK_LINEOUT) {
pr_debug("%s: Enable micbias\n", __func__);
@@ -728,6 +729,10 @@ void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
mbhc->hph_status |= jack_type;
+ if (jack_type == SND_JACK_HEADPHONE &&
+ mbhc->mbhc_cb->mbhc_micb_ramp_control)
+ mbhc->mbhc_cb->mbhc_micb_ramp_control(codec, false);
+
pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
jack_type, mbhc->hph_status);
wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
@@ -918,6 +923,10 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
else
pr_info("%s: hs_detect_plug work not cancelled\n", __func__);
+ /* Enable micbias ramp */
+ if (mbhc->mbhc_cb->mbhc_micb_ramp_control)
+ mbhc->mbhc_cb->mbhc_micb_ramp_control(codec, true);
+
if (mbhc->mbhc_cb->micbias_enable_status)
micbias1 = mbhc->mbhc_cb->micbias_enable_status(mbhc,
MIC_BIAS_1);
@@ -1411,9 +1420,6 @@ static int wcd_mbhc_initialise(struct wcd_mbhc *mbhc)
/* Button Debounce set to 16ms */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_DBNC, 2);
- /* Enable micbias ramp */
- if (mbhc->mbhc_cb->mbhc_micb_ramp_control)
- mbhc->mbhc_cb->mbhc_micb_ramp_control(codec, true);
/* enable bias */
mbhc->mbhc_cb->mbhc_bias(codec, true);
/* enable MBHC clock */
diff --git a/4.0/asoc/codecs/wcd937x/wcd937x-mbhc.h b/4.0/asoc/codecs/wcd937x/wcd937x-mbhc.h
index 34a73585..e70d4b61 100644
--- a/4.0/asoc/codecs/wcd937x/wcd937x-mbhc.h
+++ b/4.0/asoc/codecs/wcd937x/wcd937x-mbhc.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/
#ifndef __WCD937X_MBHC_H__
#define __WCD937X_MBHC_H__
@@ -51,7 +51,6 @@ static inline int wcd937x_mbhc_post_ssr_init(struct wcd937x_mbhc *mbhc,
static inline void wcd937x_mbhc_ssr_down(struct wcd937x_mbhc *mbhc,
struct snd_soc_component *component)
{
- return 0;
}
static inline int wcd937x_mbhc_get_impedance(struct wcd937x_mbhc *wcd937x_mbhc,
uint32_t *zl, uint32_t *zr)
diff --git a/4.0/asoc/codecs/wcd937x/wcd937x.c b/4.0/asoc/codecs/wcd937x/wcd937x.c
index b6c7757f..47d5e16d 100644
--- a/4.0/asoc/codecs/wcd937x/wcd937x.c
+++ b/4.0/asoc/codecs/wcd937x/wcd937x.c
@@ -1396,7 +1396,7 @@ int wcd937x_micbias_control(struct snd_soc_codec *codec,
snd_soc_update_bits(codec, WCD937X_MICB2_TEST_CTL_2, 0x01, 0x01);
snd_soc_update_bits(codec, WCD937X_MICB3_TEST_CTL_2, 0x01, 0x01);
snd_soc_update_bits(codec, micb_reg, 0xC0, 0x40);
- if (post_on_event && wcd937x->mbhc)
+ if (post_on_event)
blocking_notifier_call_chain(
&wcd937x->mbhc->notifier, post_on_event,
&wcd937x->mbhc->wcd_mbhc);
@@ -1520,14 +1520,13 @@ static int wcd937x_event_notify(struct notifier_block *block,
break;
case BOLERO_WCD_EVT_SSR_UP:
wcd937x_reset(wcd937x->dev);
+ /* allow reset to take effect */
+ usleep_range(10000, 10010);
wcd937x_get_logical_addr(wcd937x->tx_swr_dev);
wcd937x_get_logical_addr(wcd937x->rx_swr_dev);
+ wcd937x_init_reg(codec);
regcache_mark_dirty(wcd937x->regmap);
regcache_sync(wcd937x->regmap);
- /* Enable surge protection */
- snd_soc_update_bits(codec,
- WCD937X_HPH_SURGE_HPHLR_SURGE_EN,
- 0xFF, 0xD9);
/* Initialize MBHC module */
mbhc = &wcd937x->mbhc->wcd_mbhc;
ret = wcd937x_mbhc_post_ssr_init(wcd937x->mbhc, codec);
@@ -1630,6 +1629,7 @@ static int wcd937x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,
{
return __wcd937x_codec_enable_micbias_pullup(w, event);
}
+
static int wcd937x_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -2379,7 +2379,8 @@ static int wcd937x_soc_codec_probe(struct snd_soc_codec *codec)
wcd937x->codec = codec;
snd_soc_codec_init_regmap(codec, wcd937x->regmap);
- variant = (snd_soc_read(codec, WCD937X_DIGITAL_EFUSE_REG_0) & 0x0E) >> 1;
+ variant = (snd_soc_read(codec, WCD937X_DIGITAL_EFUSE_REG_0) & 0x1E)
+ >> 1;
wcd937x->variant = variant;
wcd937x->fw_data = devm_kzalloc(codec->dev,
diff --git a/4.0/asoc/codecs/wcd938x/internal.h b/4.0/asoc/codecs/wcd938x/internal.h
index f3563fff..a1c0fa78 100644
--- a/4.0/asoc/codecs/wcd938x/internal.h
+++ b/4.0/asoc/codecs/wcd938x/internal.h
@@ -70,6 +70,7 @@ struct wcd938x_priv {
bool comp1_enable;
bool comp2_enable;
bool ldoh;
+ bool bcs_dis;
struct irq_domain *virq;
struct wcd_irq_info irq_info;
u32 rx_clk_cnt;
diff --git a/4.0/asoc/codecs/wcd938x/wcd938x.c b/4.0/asoc/codecs/wcd938x/wcd938x.c
index 94c3aa54..c60028ca 100644
--- a/4.0/asoc/codecs/wcd938x/wcd938x.c
+++ b/4.0/asoc/codecs/wcd938x/wcd938x.c
@@ -68,6 +68,16 @@ enum {
ADC_MODE_ULP2,
};
+static u8 tx_mode_bit[] = {
+ [ADC_MODE_INVALID] = 0x00,
+ [ADC_MODE_HIFI] = 0x01,
+ [ADC_MODE_LO_HIF] = 0x02,
+ [ADC_MODE_NORMAL] = 0x04,
+ [ADC_MODE_LP] = 0x08,
+ [ADC_MODE_ULP1] = 0x10,
+ [ADC_MODE_ULP2] = 0x20,
+};
+
static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
@@ -140,31 +150,63 @@ static int wcd938x_swr_slv_get_current_bank(struct swr_device *dev, u8 devnum)
return ((bank & 0x40) ? 1: 0);
}
-static int wcd938x_swr_slv_set_host_clk_div2(struct swr_device *dev,
- u8 devnum, int bank)
+static int wcd938x_get_clk_rate(int mode)
{
- u8 val = (bank ? 1 : 0);
+ int rate;
- return (swr_write(dev, devnum,
- (SWR_SCP_HOST_CLK_DIV2_CTL_BANK + (0x10 * bank)), &val));
+ switch (mode) {
+ case ADC_MODE_ULP2:
+ rate = SWR_CLK_RATE_0P6MHZ;
+ break;
+ case ADC_MODE_ULP1:
+ rate = SWR_CLK_RATE_1P2MHZ;
+ break;
+ case ADC_MODE_LP:
+ rate = SWR_CLK_RATE_4P8MHZ;
+ break;
+ case ADC_MODE_NORMAL:
+ case ADC_MODE_LO_HIF:
+ case ADC_MODE_HIFI:
+ case ADC_MODE_INVALID:
+ default:
+ rate = SWR_CLK_RATE_9P6MHZ;
+ break;
+ }
+
+ return rate;
}
static int wcd938x_set_swr_clk_rate(struct snd_soc_codec *codec,
- int mode, int bank)
+ int rate, int bank)
{
u8 mask = (bank ? 0xF0 : 0x0F);
u8 val = 0;
- if ((mode == ADC_MODE_ULP1) || (mode == ADC_MODE_ULP2))
+ switch (rate) {
+ case SWR_CLK_RATE_0P6MHZ:
val = (bank ? 0x60 : 0x06);
- else
+ break;
+ case SWR_CLK_RATE_1P2MHZ:
+ val = (bank ? 0x50 : 0x05);
+ break;
+ case SWR_CLK_RATE_2P4MHZ:
+ val = (bank ? 0x30 : 0x03);
+ break;
+ case SWR_CLK_RATE_4P8MHZ:
+ val = (bank ? 0x10 : 0x01);
+ break;
+ case SWR_CLK_RATE_9P6MHZ:
+ default:
val = 0x00;
-
- snd_soc_update_bits(codec, WCD938X_DIGITAL_SWR_TX_CLK_RATE,
+ break;
+ }
+ snd_soc_update_bits(codec,
+ WCD938X_DIGITAL_SWR_TX_CLK_RATE,
mask, val);
return 0;
}
+
static int wcd938x_init_reg(struct snd_soc_codec *codec)
{
snd_soc_update_bits(codec, WCD938X_SLEEP_CTL, 0x0E, 0x0E);
@@ -222,6 +264,11 @@ static int wcd938x_init_reg(struct snd_soc_codec *codec)
WCD938X_MICB4_TEST_CTL_1, 0xE0, 0xE0);
snd_soc_update_bits(codec,
WCD938X_TX_3_4_TEST_BLK_EN2, 0x01, 0x00);
+ snd_soc_update_bits(codec, WCD938X_SLEEP_CTL, 0x0E,
+ ((snd_soc_read(codec,
+ WCD938X_DIGITAL_EFUSE_REG_30) & 0x07) << 1));
+ snd_soc_update_bits(codec,
+ WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0);
return 0;
}
@@ -351,7 +398,8 @@ err_port_map:
}
static int wcd938x_tx_connect_port(struct snd_soc_codec *codec,
- u8 slv_port_type, u8 enable)
+ u8 slv_port_type, int clk_rate,
+ u8 enable)
{
struct wcd938x_priv *wcd938x = snd_soc_codec_get_drvdata(codec);
u8 port_id, num_ch, ch_mask, port_type;
@@ -362,6 +410,8 @@ static int wcd938x_tx_connect_port(struct snd_soc_codec *codec,
ret = wcd938x_set_port_params(codec, slv_port_type, &port_id,
&num_ch, &ch_mask, &ch_rate,
&port_type, CODEC_TX);
+ if (clk_rate)
+ ch_rate = clk_rate;
if (ret)
return ret;
@@ -1299,10 +1349,12 @@ static int wcd938x_codec_enable_dmic(struct snd_soc_dapm_widget *w,
/* enable clock scaling */
snd_soc_update_bits(codec,
WCD938X_DIGITAL_CDC_DMIC_CTL, 0x06, 0x06);
- wcd938x_tx_connect_port(codec, DMIC0 + (w->shift), true);
+ wcd938x_tx_connect_port(codec, DMIC0 + (w->shift),
+ SWR_CLK_RATE_2P4MHZ, true);
break;
case SND_SOC_DAPM_POST_PMD:
- wcd938x_tx_connect_port(codec, DMIC0 + (w->shift), false);
+ wcd938x_tx_connect_port(codec, DMIC0 + (w->shift), 0,
+ false);
snd_soc_update_bits(codec,
WCD938X_DIGITAL_CDC_AMIC_CTL,
(0x01 << dmic_ctl_shift),
@@ -1423,32 +1475,54 @@ static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
struct wcd938x_priv *wcd938x = snd_soc_codec_get_drvdata(codec);
int ret = 0;
int bank = 0;
- int mode = 0;
+ u8 mode = 0;
+ int i = 0;
+ int rate = 0;
+
+ bank = (wcd938x_swr_slv_get_current_bank(wcd938x->tx_swr_dev,
+ wcd938x->tx_swr_dev->dev_num) ? 0 : 1);
- bank = wcd938x_swr_slv_get_current_bank(wcd938x->tx_swr_dev,
- wcd938x->tx_swr_dev->dev_num);
- wcd938x_swr_slv_set_host_clk_div2(wcd938x->tx_swr_dev,
- wcd938x->tx_swr_dev->dev_num, bank);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ if (strnstr(w->name, "ADC", sizeof("ADC"))) {
+ if (test_bit(WCD_ADC1, &wcd938x->status_mask))
+ mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC1]];
+ if (test_bit(WCD_ADC2, &wcd938x->status_mask))
+ mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC2]];
+ if (test_bit(WCD_ADC3, &wcd938x->status_mask))
+ mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC3]];
+ if (test_bit(WCD_ADC4, &wcd938x->status_mask))
+ mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC4]];
+
+ if (mode != 0) {
+ for (i = 0; i < ADC_MODE_ULP2; i++) {
+ if (mode & (1 << i)) {
+ i++;
+ break;
+ }
+ }
+ }
+ rate = wcd938x_get_clk_rate(i);
+ wcd938x_set_swr_clk_rate(codec, mode, bank);
+ }
ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
wcd938x->tx_swr_dev->dev_num,
true);
- if (test_bit(WCD_ADC1, &wcd938x->status_mask))
- mode |= wcd938x->tx_mode[WCD_ADC1];
- if (test_bit(WCD_ADC2, &wcd938x->status_mask))
- mode |= wcd938x->tx_mode[WCD_ADC2];
- if (test_bit(WCD_ADC3, &wcd938x->status_mask))
- mode |= wcd938x->tx_mode[WCD_ADC3];
- if (test_bit(WCD_ADC4, &wcd938x->status_mask))
- mode |= wcd938x->tx_mode[WCD_ADC4];
- wcd938x_set_swr_clk_rate(codec, mode, bank);
+ if (strnstr(w->name, "ADC", sizeof("ADC"))) {
+ /* Copy clk settings to active bank */
+ wcd938x_set_swr_clk_rate(codec, rate, !bank);
+ }
break;
case SND_SOC_DAPM_POST_PMD:
+ if (strnstr(w->name, "ADC", sizeof("ADC"))) {
+ rate = wcd938x_get_clk_rate(ADC_MODE_INVALID);
+ wcd938x_set_swr_clk_rate(codec, rate, !bank);
+ }
ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
wcd938x->tx_swr_dev->dev_num,
false);
- wcd938x_set_swr_clk_rate(codec, ADC_MODE_INVALID, bank);
+ if (strnstr(w->name, "ADC", sizeof("ADC")))
+ wcd938x_set_swr_clk_rate(codec, rate, bank);
break;
};
@@ -1495,6 +1569,7 @@ static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w,
struct snd_soc_codec *codec =
snd_soc_dapm_to_codec(w->dapm);
struct wcd938x_priv *wcd938x = snd_soc_codec_get_drvdata(codec);
+ int clk_rate = 0;
dev_dbg(codec->dev, "%s wname: %s event: %d\n", __func__,
w->name, event);
@@ -1505,21 +1580,26 @@ static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w,
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x08);
snd_soc_update_bits(codec,
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
-
set_bit(w->shift, &wcd938x->status_mask);
- /* Enable BCS for Headset mic */
+ clk_rate = wcd938x_get_clk_rate(wcd938x->tx_mode[w->shift]);
+ /* Enable BCS for Headset mic */
if (w->shift == 1 && !(snd_soc_read(codec,
WCD938X_TX_NEW_AMIC_MUX_CFG) & 0x80)) {
- wcd938x_tx_connect_port(codec, MBHC, true);
+ if (!wcd938x->bcs_dis)
+ wcd938x_tx_connect_port(codec, MBHC,
+ SWR_CLK_RATE_4P8MHZ, true);
set_bit(AMIC2_BCS_ENABLE, &wcd938x->status_mask);
}
- wcd938x_tx_connect_port(codec, ADC1 + (w->shift), true);
+ wcd938x_tx_connect_port(codec, ADC1 + (w->shift), clk_rate,
+ true);
break;
case SND_SOC_DAPM_POST_PMD:
- wcd938x_tx_connect_port(codec, ADC1 + (w->shift), false);
+ wcd938x_tx_connect_port(codec, ADC1 + (w->shift), 0, false);
if (w->shift == 1 &&
test_bit(AMIC2_BCS_ENABLE, &wcd938x->status_mask)) {
- wcd938x_tx_connect_port(codec, MBHC, false);
+ if (!wcd938x->bcs_dis)
+ wcd938x_tx_connect_port(codec, MBHC, 0,
+ false);
clear_bit(AMIC2_BCS_ENABLE, &wcd938x->status_mask);
}
snd_soc_update_bits(codec,
@@ -2334,6 +2414,30 @@ static int wcd938x_ldoh_put(struct snd_kcontrol *kcontrol,
return 0;
}
+static int wcd938x_bcs_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec =
+ snd_soc_kcontrol_codec(kcontrol);
+ struct wcd938x_priv *wcd938x = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = wcd938x->bcs_dis;
+
+ return 0;
+}
+
+static int wcd938x_bcs_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec =
+ snd_soc_kcontrol_codec(kcontrol);
+ struct wcd938x_priv *wcd938x = snd_soc_codec_get_drvdata(codec);
+
+ wcd938x->bcs_dis = ucontrol->value.integer.value[0];
+
+ return 0;
+}
+
static const char * const tx_mode_mux_text_wcd9380[] = {
"ADC_INVALID", "ADC_HIFI", "ADC_LO_HIF", "ADC_NORMAL", "ADC_LP",
};
@@ -2417,10 +2521,12 @@ static const struct snd_kcontrol_new wcd938x_snd_controls[] = {
wcd938x_get_compander, wcd938x_set_compander),
SOC_SINGLE_EXT("HPHR_COMP Switch", SND_SOC_NOPM, 1, 1, 0,
wcd938x_get_compander, wcd938x_set_compander),
-
SOC_SINGLE_EXT("LDOH Enable", SND_SOC_NOPM, 0, 1, 0,
wcd938x_ldoh_get, wcd938x_ldoh_put),
+ SOC_SINGLE_EXT("ADC2_BCS Disable", SND_SOC_NOPM, 0, 1, 0,
+ wcd938x_bcs_get, wcd938x_bcs_put),
+
SOC_SINGLE_TLV("HPHL Volume", WCD938X_HPH_L_EN, 0, 20, 1, line_gain),
SOC_SINGLE_TLV("HPHR Volume", WCD938X_HPH_R_EN, 0, 20, 1, line_gain),
SOC_SINGLE_TLV("ADC1 Volume", WCD938X_ANA_TX_CH1, 0, 20, 0,
diff --git a/4.0/asoc/msm-dai-q6-v2.c b/4.0/asoc/msm-dai-q6-v2.c
index e9d354b8..bf9c4c5b 100644
--- a/4.0/asoc/msm-dai-q6-v2.c
+++ b/4.0/asoc/msm-dai-q6-v2.c
@@ -1285,6 +1285,7 @@ static int msm_dai_q6_island_mode_put(struct snd_kcontrol *kcontrol,
u16 port_id = (u16)kcontrol->private_value;
pr_debug("%s: island mode = %d\n", __func__, value);
+ trace_printk("%s: island mode = %d\n", __func__, value);
afe_set_island_mode_cfg(port_id, value);
return 0;
diff --git a/4.0/asoc/msm-lsm-client.c b/4.0/asoc/msm-lsm-client.c
index 208a8a63..d6fd86cc 100644
--- a/4.0/asoc/msm-lsm-client.c
+++ b/4.0/asoc/msm-lsm-client.c
@@ -25,12 +25,15 @@
#include <dsp/q6lsm.h>
#include "msm-pcm-routing-v2.h"
+
#define CAPTURE_MIN_NUM_PERIODS 2
#define CAPTURE_MAX_NUM_PERIODS 8
#define CAPTURE_MAX_PERIOD_SIZE 61440
#define CAPTURE_MIN_PERIOD_SIZE 320
#define LISTEN_MAX_STATUS_PAYLOAD_SIZE 256
+#define WAKELOCK_TIMEOUT 2000
+
#define LAB_BUFFER_ALLOC 1
#define LAB_BUFFER_DEALLOC 0
@@ -88,6 +91,7 @@ struct lsm_priv {
int xrun_count;
int xrun_index;
spinlock_t xrun_lock;
+ struct wakeup_source ws;
};
enum { /* lsm session states */
@@ -215,6 +219,8 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
}
rtd = substream->private_data;
+ pm_wakeup_ws_event(&prtd->ws, WAKELOCK_TIMEOUT, true);
+ dev_dbg(rtd->dev, "%s: opcode %x\n", __func__, opcode);
switch (opcode) {
case LSM_DATA_EVENT_READ_DONE: {
int rc;
@@ -228,11 +234,13 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
"%s: EVENT_READ_DONE invalid callback, session %d callback %d payload %pK",
__func__, prtd->lsm_client->session,
token, read_done);
+ __pm_relax(&prtd->ws);
return;
}
if (atomic_read(&prtd->read_abort)) {
dev_dbg(rtd->dev,
"%s: read abort set skip data\n", __func__);
+ __pm_relax(&prtd->ws);
return;
}
if (!lsm_lab_buffer_sanity(prtd, read_done, &buf_index)) {
@@ -245,6 +253,7 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
"%s: Invalid index %d buf_index max cnt %d\n",
__func__, buf_index,
prtd->lsm_client->out_hw_params.period_count);
+ __pm_relax(&prtd->ws);
return;
}
spin_lock_irqsave(&prtd->xrun_lock, flags);
@@ -282,6 +291,7 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
+ __pm_relax(&prtd->ws);
return;
}
status = (uint16_t)((uint8_t *)payload)[0];
@@ -297,13 +307,14 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
+ __pm_relax(&prtd->ws);
return;
}
status = (uint16_t)((uint8_t *)payload)[0];
payload_size = (uint16_t)((uint8_t *)payload)[1];
index = 2;
dev_dbg(rtd->dev,
- "%s: event detect status = %d payload size = %d\n",
+ "%s: event detect status_v2 = %d payload size = %d\n",
__func__, status, payload_size);
break;
@@ -312,6 +323,7 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
+ __pm_relax(&prtd->ws);
return;
}
event_ts_lsw = ((uint32_t *)payload)[0];
@@ -331,6 +343,7 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
+ __pm_relax(&prtd->ws);
return;
}
@@ -350,6 +363,7 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
"LSM_SESSION_DETECTION_ENGINE_GENERIC_EVENT",
sizeof(struct snd_lsm_event_status) +
payload_size);
+ __pm_relax(&prtd->ws);
return;
}
@@ -364,6 +378,7 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
dev_err(rtd->dev,
"%s: Failed to copy memory with invalid size = %d\n",
__func__, payload_size);
+ __pm_relax(&prtd->ws);
return;
}
prtd->event_avail = 1;
@@ -388,12 +403,14 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
opcode == LSM_SESSION_EVENT_DETECTION_STATUS_V2 ||
opcode == LSM_SESSION_EVENT_DETECTION_STATUS_V3) {
spin_lock_irqsave(&prtd->event_lock, flags);
+ dev_dbg(rtd->dev, "%s: detection status\n", __func__);
temp = krealloc(prtd->event_status,
sizeof(struct snd_lsm_event_status_v3) +
payload_size, GFP_ATOMIC);
if (!temp) {
dev_err(rtd->dev, "%s: no memory for event status\n",
__func__);
+ __pm_relax(&prtd->ws);
return;
}
/*
@@ -413,12 +430,15 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
payload_size);
prtd->event_avail = 1;
spin_unlock_irqrestore(&prtd->event_lock, flags);
+ dev_dbg(rtd->dev, "%s: wakeup event_wait\n",
+ __func__);
wake_up(&prtd->event_wait);
} else {
spin_unlock_irqrestore(&prtd->event_lock, flags);
dev_err(rtd->dev,
"%s: Failed to copy memory with invalid size = %d\n",
__func__, payload_size);
+ __pm_relax(&prtd->ws);
return;
}
} else {
@@ -430,6 +450,7 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
if (substream->timer_running)
snd_timer_interrupt(substream->timer, 1);
}
+ dev_dbg(rtd->dev, "%s: leave\n", __func__);
}
static int msm_lsm_lab_buffer_alloc(struct lsm_priv *lsm, int alloc)
@@ -1069,6 +1090,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
prtd = runtime->private_data;
rtd = substream->private_data;
+ dev_dbg(rtd->dev, "%s: enter, cmd %x\n", __func__, cmd);
switch (cmd) {
case SNDRV_LSM_SET_SESSION_DATA:
case SNDRV_LSM_SET_SESSION_DATA_V2:
@@ -1134,6 +1156,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
dev_err(rtd->dev,
"%s: lsm open failed, %d\n",
__func__, ret);
+ __pm_relax(&prtd->ws);
return ret;
}
prtd->lsm_client->opened = true;
@@ -1269,7 +1292,8 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
uint32_t ts_lsw, ts_msw;
uint16_t status = 0, payload_size = 0;
- dev_dbg(rtd->dev, "%s: Get event status\n", __func__);
+ dev_dbg(rtd->dev, "%s: Get event status cmd %xx\n",
+ __func__, cmd);
atomic_set(&prtd->event_wait_stop, 0);
/*
@@ -1282,6 +1306,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
(cmpxchg(&prtd->event_avail, 1, 0) ||
(xchg = atomic_cmpxchg(&prtd->event_wait_stop,
1, 0))));
+ dev_dbg(rtd->dev, "%s: wait event is done\n", __func__);
mutex_lock(&prtd->lsm_api_lock);
dev_dbg(rtd->dev, "%s: wait_event_freezable %d event_wait_stop %d\n",
__func__, rc, xchg);
@@ -1480,12 +1505,14 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
if (prtd->lsm_client->num_stages > 1) {
dev_err(rtd->dev, "%s: %s: not supported for multi stage session\n",
__func__, "LSM_LAB_CONTROL");
+ __pm_relax(&prtd->ws);
return -EINVAL;
}
if (copy_from_user(&enable, arg, sizeof(enable))) {
dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n",
__func__, "LSM_LAB_CONTROL");
+ __pm_relax(&prtd->ws);
return -EFAULT;
}
@@ -1540,6 +1567,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
if (copy_from_user(&mode, arg, sizeof(mode))) {
dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n",
__func__, "LSM_SET_FWK_MODE_CONFIG");
+ __pm_relax(&prtd->ws);
return -EFAULT;
}
@@ -1570,6 +1598,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
if (copy_from_user(&params, arg, sizeof(params))) {
dev_err(rtd->dev, "%s: %s: copy_from_user failed\n",
__func__, "LSM_SET_INPUT_HW_PARAMS");
+ __pm_relax(&prtd->ws);
return -EFAULT;
}
@@ -1596,6 +1625,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
dev_err(rtd->dev, "%s: cmd 0x%x failed %d\n",
__func__, cmd, rc);
+ __pm_relax(&prtd->ws);
return rc;
}
@@ -2500,6 +2530,7 @@ static int msm_lsm_open(struct snd_pcm_substream *substream)
prtd->lsm_client->fe_id = rtd->dai_link->id;
prtd->lsm_client->unprocessed_data = 0;
+ wakeup_source_init(&prtd->ws, "lsm-client");
return 0;
}
@@ -2744,6 +2775,7 @@ static int msm_lsm_close(struct snd_pcm_substream *substream)
q6lsm_client_free(prtd->lsm_client);
+ wakeup_source_trash(&prtd->ws);
spin_lock_irqsave(&prtd->event_lock, flags);
kfree(prtd->event_status);
prtd->event_status = NULL;
diff --git a/4.0/asoc/msm-pcm-loopback-v2.c b/4.0/asoc/msm-pcm-loopback-v2.c
index 3fdced03..8ad8120c 100644
--- a/4.0/asoc/msm-pcm-loopback-v2.c
+++ b/4.0/asoc/msm-pcm-loopback-v2.c
@@ -242,7 +242,6 @@ static int msm_pcm_open(struct snd_pcm_substream *substream)
struct msm_pcm_loopback *pcm = NULL;
int ret = 0;
uint16_t bits_per_sample = 16;
- struct msm_pcm_routing_evt event;
struct asm_session_mtmx_strtr_param_window_v2_t asm_mtmx_strtr_window;
uint32_t param_id;
struct msm_pcm_pdata *pdata;
@@ -264,10 +263,6 @@ static int msm_pcm_open(struct snd_pcm_substream *substream)
dev_dbg(rtd->platform->dev, "%s: pcm out open: %d,%d\n", __func__,
pcm->instance, substream->stream);
if (pcm->instance == 2) {
- struct snd_soc_pcm_runtime *soc_pcm_rx =
- pcm->playback_substream->private_data;
- struct snd_soc_pcm_runtime *soc_pcm_tx =
- pcm->capture_substream->private_data;
if (pcm->audio_client != NULL)
stop_pcm(pcm);
@@ -299,15 +294,6 @@ static int msm_pcm_open(struct snd_pcm_substream *substream)
mutex_unlock(&pcm->lock);
return -ENOMEM;
}
- event.event_func = msm_pcm_route_event_handler;
- event.priv_data = (void *) pcm;
- msm_pcm_routing_reg_phy_stream(soc_pcm_tx->dai_link->id,
- pcm->audio_client->perf_mode,
- pcm->session_id, pcm->capture_substream->stream);
- msm_pcm_routing_reg_phy_stream_v2(soc_pcm_rx->dai_link->id,
- pcm->audio_client->perf_mode,
- pcm->session_id, pcm->playback_substream->stream,
- event);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
pcm->playback_substream = substream;
ret = pcm_loopback_set_volume(pcm, pcm->volume);
@@ -541,6 +527,10 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol,
struct msm_pcm_loopback *prtd;
pr_debug("%s\n", __func__);
+ if (!vol) {
+ pr_err("%s: vol is NULL\n", __func__);
+ return -ENODEV;
+ }
if ((!substream) || (!substream->runtime)) {
pr_debug("%s substream or runtime not found\n", __func__);
rc = -ENODEV;
diff --git a/4.0/asoc/msm-pcm-q6-noirq.c b/4.0/asoc/msm-pcm-q6-noirq.c
index e394f37d..eb8a974e 100644
--- a/4.0/asoc/msm-pcm-q6-noirq.c
+++ b/4.0/asoc/msm-pcm-q6-noirq.c
@@ -710,6 +710,10 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol,
struct msm_audio *prtd;
pr_debug("%s\n", __func__);
+ if (!vol) {
+ pr_err("%s: vol is NULL\n", __func__);
+ return -ENODEV;
+ }
if (!substream) {
pr_err("%s: substream not found\n", __func__);
return -ENODEV;
diff --git a/4.0/asoc/msm-pcm-q6-v2.c b/4.0/asoc/msm-pcm-q6-v2.c
index 64ffe97e..507c0d85 100644
--- a/4.0/asoc/msm-pcm-q6-v2.c
+++ b/4.0/asoc/msm-pcm-q6-v2.c
@@ -1465,6 +1465,10 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol,
struct msm_audio *prtd;
pr_debug("%s\n", __func__);
+ if (!vol) {
+ pr_err("%s: vol is NULL\n", __func__);
+ return -ENODEV;
+ }
if (!substream) {
pr_err("%s substream not found\n", __func__);
return -ENODEV;
@@ -1508,6 +1512,7 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol,
pr_err("%s: substream not found\n", __func__);
return -ENODEV;
}
+
soc_prtd = substream->private_data;
if (!substream->runtime || !soc_prtd) {
pr_err("%s: substream runtime or private_data not found\n",
@@ -1728,7 +1733,6 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
(char)(ucontrol->value.integer.value[i]);
/* update chmixer_pspd chmap cached with routing driver as well */
- rtd = substream->private_data;
if (rtd) {
fe_id = rtd->dai_link->id;
chmixer_pspd = pdata ?
diff --git a/4.0/dsp/codecs/audio_native.c b/4.0/dsp/codecs/audio_native.c
index 93370295..6e249145 100644
--- a/4.0/dsp/codecs/audio_native.c
+++ b/4.0/dsp/codecs/audio_native.c
@@ -1,12 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2020, The Linux Foundation. All rights reserved.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include "audio_utils.h"
+spinlock_t enc_dec_lock;
+
static int __init audio_native_init(void)
{
aac_in_init();
@@ -31,6 +33,7 @@ static int __init audio_native_init(void)
g711alaw_in_init();
g711mlaw_in_init();
qcelp_in_init();
+ spin_lock_init(&enc_dec_lock);
return 0;
}
diff --git a/4.0/dsp/codecs/audio_utils.c b/4.0/dsp/codecs/audio_utils.c
index 26e9b0b3..ac934132 100644
--- a/4.0/dsp/codecs/audio_utils.c
+++ b/4.0/dsp/codecs/audio_utils.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2010-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
@@ -943,8 +943,11 @@ int audio_in_release(struct inode *inode, struct file *file)
audio_in_disable(audio);
q6asm_audio_client_free(audio->ac);
mutex_unlock(&audio->lock);
+ spin_lock(&enc_dec_lock);
kfree(audio->enc_cfg);
kfree(audio->codec_cfg);
kfree(audio);
+ file->private_data = NULL;
+ spin_unlock(&enc_dec_lock);
return 0;
}
diff --git a/4.0/dsp/codecs/audio_utils_aio.c b/4.0/dsp/codecs/audio_utils_aio.c
index febbd2a6..67fdc06f 100644
--- a/4.0/dsp/codecs/audio_utils_aio.c
+++ b/4.0/dsp/codecs/audio_utils_aio.c
@@ -1,6 +1,6 @@
/* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2020, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -630,9 +630,11 @@ int audio_aio_release(struct inode *inode, struct file *file)
#ifdef CONFIG_DEBUG_FS
debugfs_remove(audio->dentry);
#endif
+ spin_lock(&enc_dec_lock);
kfree(audio->codec_cfg);
kfree(audio);
file->private_data = NULL;
+ spin_unlock(&enc_dec_lock);
mutex_unlock(&lock);
return 0;
}
diff --git a/4.0/dsp/codecs/q6audio_common.h b/4.0/dsp/codecs/q6audio_common.h
index c37813ed..67003fea 100644
--- a/4.0/dsp/codecs/q6audio_common.h
+++ b/4.0/dsp/codecs/q6audio_common.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2012-2014, 2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 2017, 2020 The Linux Foundation. All rights reserved.
*/
@@ -9,7 +9,7 @@
#include <dsp/apr_audio-v2.h>
#include <dsp/q6asm-v2.h>
-
+extern spinlock_t enc_dec_lock;
void q6_audio_cb(uint32_t opcode, uint32_t token,
uint32_t *payload, void *priv);
diff --git a/4.0/dsp/codecs/q6audio_v2.c b/4.0/dsp/codecs/q6audio_v2.c
index c98ef1c4..6a402f53 100644
--- a/4.0/dsp/codecs/q6audio_v2.c
+++ b/4.0/dsp/codecs/q6audio_v2.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2012-2013, 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2015-2017, 2020 The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
@@ -21,6 +21,11 @@ void q6asm_in_cb(uint32_t opcode, uint32_t token,
struct q6audio_in *audio = (struct q6audio_in *)priv;
unsigned long flags;
+ spin_lock(&enc_dec_lock);
+ if (audio == NULL) {
+ pr_err("%s: failed to get q6audio value\n", __func__);
+ goto error;
+ }
pr_debug("%s:session id %d: opcode[0x%x]\n", __func__,
audio->ac->session, opcode);
@@ -58,6 +63,8 @@ void q6asm_in_cb(uint32_t opcode, uint32_t token,
break;
}
spin_unlock_irqrestore(&audio->dsp_lock, flags);
+error:
+ spin_unlock(&enc_dec_lock);
}
void audio_in_get_dsp_frames(void *priv,
diff --git a/4.0/dsp/codecs/q6audio_v2_aio.c b/4.0/dsp/codecs/q6audio_v2_aio.c
index ea8b84de..ecd14dad 100644
--- a/4.0/dsp/codecs/q6audio_v2_aio.c
+++ b/4.0/dsp/codecs/q6audio_v2_aio.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2012-2018, 2020, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
@@ -43,9 +43,10 @@ void audio_aio_cb(uint32_t opcode, uint32_t token,
struct q6audio_aio *audio = (struct q6audio_aio *)priv;
union msm_audio_event_payload e_payload;
+ spin_lock(&enc_dec_lock);
if (audio == NULL) {
pr_err("%s: failed to get q6audio value\n", __func__);
- return;
+ goto error;
}
switch (opcode) {
case ASM_DATA_EVENT_WRITE_DONE_V2:
@@ -111,6 +112,8 @@ void audio_aio_cb(uint32_t opcode, uint32_t token,
default:
break;
}
+error:
+ spin_unlock(&enc_dec_lock);
}
int extract_meta_out_info(struct q6audio_aio *audio,
diff --git a/4.0/dsp/msm_audio_ion_vm.c b/4.0/dsp/msm_audio_ion_vm.c
index f9635b33..a8440375 100644
--- a/4.0/dsp/msm_audio_ion_vm.c
+++ b/4.0/dsp/msm_audio_ion_vm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/init.h>
@@ -564,6 +564,7 @@ static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr,
if (rc) {
pr_err("%s: failed to do smmu map, err = %d\n",
__func__, rc);
+ msm_audio_dma_buf_unmap((struct dma_buf *) handle);
goto err;
}
}
diff --git a/4.0/dsp/q6afe.c b/4.0/dsp/q6afe.c
index 9659e74a..16d15678 100644
--- a/4.0/dsp/q6afe.c
+++ b/4.0/dsp/q6afe.c
@@ -7020,7 +7020,7 @@ static int afe_sidetone_iir(u16 tx_port_id)
* Set IIR enable params
*/
param_hdr.module_id = mid;
- param_hdr.param_id = INSTANCE_ID_0;
+ param_hdr.instance_id = INSTANCE_ID_0;
param_hdr.param_id = AFE_PARAM_ID_ENABLE;
param_hdr.param_size = sizeof(enable);
enable.enable = iir_enable;
diff --git a/4.0/dsp/q6asm.c b/4.0/dsp/q6asm.c
index 0bbfc728..8314df74 100644
--- a/4.0/dsp/q6asm.c
+++ b/4.0/dsp/q6asm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -2551,7 +2551,7 @@ void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size,
/* To make it more robust, we could loop and get the
* next avail buf, its risky though
*/
- pr_err("%s: Next buf idx[0x%x] not available, dir[%d]\n",
+ pr_debug("%s: Next buf idx[0x%x] not available, dir[%d]\n",
__func__, idx, dir);
mutex_unlock(&port->lock);
return NULL;
@@ -10906,14 +10906,25 @@ EXPORT_SYMBOL(q6asm_get_path_delay);
int q6asm_get_apr_service_id(int session_id)
{
+ int service_id;
+
pr_debug("%s:\n", __func__);
if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) {
pr_err("%s: invalid session_id = %d\n", __func__, session_id);
return -EINVAL;
}
-
- return ((struct apr_svc *)(session[session_id].ac)->apr)->id;
+ mutex_lock(&session[session_id].mutex_lock_per_session);
+ if (session[session_id].ac != NULL)
+ if ((session[session_id].ac)->apr != NULL) {
+ service_id = ((struct apr_svc *)
+ (session[session_id].ac)->apr)->id;
+ mutex_unlock(
+ &session[session_id].mutex_lock_per_session);
+ return service_id;
+ }
+ mutex_unlock(&session[session_id].mutex_lock_per_session);
+ return -EINVAL;
}
uint8_t q6asm_get_asm_stream_id(int session_id)
diff --git a/4.0/include/soc/soundwire.h b/4.0/include/soc/soundwire.h
index 59e7d417..37a00c75 100644
--- a/4.0/include/soc/soundwire.h
+++ b/4.0/include/soc/soundwire.h
@@ -10,6 +10,13 @@
#include <linux/mod_devicetable.h>
#include <linux/irqdomain.h>
+#define SWR_CLK_RATE_0P6MHZ 600000
+#define SWR_CLK_RATE_1P2MHZ 1200000
+#define SWR_CLK_RATE_2P4MHZ 2400000
+#define SWR_CLK_RATE_4P8MHZ 4800000
+#define SWR_CLK_RATE_9P6MHZ 9600000
+#define SWR_CLK_RATE_11P2896MHZ 1128960
+
extern struct bus_type soundwire_type;
/* Soundwire supports max. of 8 channels per port */
diff --git a/4.0/include/soc/swr-wcd.h b/4.0/include/soc/swr-wcd.h
index 4ec50944..0c091278 100644
--- a/4.0/include/soc/swr-wcd.h
+++ b/4.0/include/soc/swr-wcd.h
@@ -32,6 +32,7 @@ struct swr_mstr_port {
};
#define MCLK_FREQ 9600000
+#define MCLK_FREQ_LP 600000
#define MCLK_FREQ_NATIVE 11289600
#if (IS_ENABLED(CONFIG_SOUNDWIRE_WCD_CTRL) || \
diff --git a/4.0/soc/pinctrl-lpi.c b/4.0/soc/pinctrl-lpi.c
index 2b9e52e9..4df9791c 100644
--- a/4.0/soc/pinctrl-lpi.c
+++ b/4.0/soc/pinctrl-lpi.c
@@ -497,6 +497,7 @@ int lpi_pinctrl_suspend(struct device *dev)
{
int ret = 0;
+ trace_printk("%s: system suspend\n", __func__);
dev_dbg(dev, "%s: system suspend\n", __func__);
if ((!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev))) {
@@ -533,6 +534,7 @@ static struct notifier_block service_nb = {
static void lpi_pinctrl_ssr_disable(struct device *dev, void *data)
{
+ trace_printk("%s: enter\n", __func__);
lpi_dev_up = false;
lpi_pinctrl_suspend(dev);
}
diff --git a/4.0/soc/swr-mstr-ctrl.c b/4.0/soc/swr-mstr-ctrl.c
index 17b9ed79..23ccd234 100644
--- a/4.0/soc/swr-mstr-ctrl.c
+++ b/4.0/soc/swr-mstr-ctrl.c
@@ -25,6 +25,8 @@
#include "swrm_registers.h"
#include "swr-mstr-ctrl.h"
+#define SWR_NUM_PORTS 4 /* TODO - Get this info from DT */
+
#define SWRM_FRAME_SYNC_SEL 4000 /* 4KHz */
#define SWRM_FRAME_SYNC_SEL_NATIVE 3675 /* 3.675KHz */
#define SWRM_SYSTEM_RESUME_TIMEOUT_MS 700
@@ -94,6 +96,42 @@ static void swrm_unlock_sleep(struct swr_mstr_ctrl *swrm);
static u32 swr_master_read(struct swr_mstr_ctrl *swrm, unsigned int reg_addr);
static void swr_master_write(struct swr_mstr_ctrl *swrm, u16 reg_addr, u32 val);
+
+static u8 swrm_get_clk_div(int mclk_freq, int bus_clk_freq)
+{
+ int clk_div = 0;
+ u8 div_val = 0;
+
+ if (!mclk_freq || !bus_clk_freq)
+ return 0;
+
+ clk_div = (mclk_freq / bus_clk_freq);
+
+ switch (clk_div) {
+ case 32:
+ div_val = 5;
+ break;
+ case 16:
+ div_val = 4;
+ break;
+ case 8:
+ div_val = 3;
+ break;
+ case 4:
+ div_val = 2;
+ break;
+ case 2:
+ div_val = 1;
+ break;
+ case 1:
+ default:
+ div_val = 0;
+ break;
+ }
+
+ return div_val;
+}
+
static bool swrm_is_msm_variant(int val)
{
return (val == SWRM_VERSION_1_3);
@@ -326,33 +364,77 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm,
{
int ret = 0;
+ mutex_lock(&swrm->devlock);
if (core_type == LPASS_HW_CORE) {
if (swrm->lpass_core_hw_vote) {
if (enable) {
- ret =
- clk_prepare_enable(swrm->lpass_core_hw_vote);
- if (ret < 0)
- dev_err(swrm->dev,
- "%s:lpass core hw enable failed\n",
- __func__);
- } else
- clk_disable_unprepare(swrm->lpass_core_hw_vote);
+ if (!swrm->dev_up) {
+ dev_dbg(swrm->dev, "%s: device is down or SSR state\n",
+ __func__);
+ trace_printk("%s: device is down or SSR state\n",
+ __func__);
+ mutex_unlock(&swrm->devlock);
+ return -ENODEV;
+ }
+ if (++swrm->hw_core_clk_en == 1) {
+ ret =
+ clk_prepare_enable(
+ swrm->lpass_core_hw_vote);
+ if (ret < 0) {
+ dev_err(swrm->dev,
+ "%s:lpass core hw enable failed\n",
+ __func__);
+ --swrm->hw_core_clk_en;
+ }
+ }
+ } else {
+ --swrm->hw_core_clk_en;
+ if (swrm->hw_core_clk_en < 0)
+ swrm->hw_core_clk_en = 0;
+ else if (swrm->hw_core_clk_en == 0)
+ clk_disable_unprepare(
+ swrm->lpass_core_hw_vote);
+ }
}
}
if (core_type == LPASS_AUDIO_CORE) {
if (swrm->lpass_core_audio) {
if (enable) {
- ret =
- clk_prepare_enable(swrm->lpass_core_audio);
- if (ret < 0)
- dev_err(swrm->dev,
- "%s:lpass audio hw enable failed\n",
- __func__);
- } else
- clk_disable_unprepare(swrm->lpass_core_audio);
+ if (!swrm->dev_up) {
+ dev_dbg(swrm->dev, "%s: device is down or SSR state\n",
+ __func__);
+ trace_printk("%s: device is down or SSR state\n",
+ __func__);
+ mutex_unlock(&swrm->devlock);
+ return -ENODEV;
+ }
+ if (++swrm->aud_core_clk_en == 1) {
+ ret =
+ clk_prepare_enable(
+ swrm->lpass_core_audio);
+ if (ret < 0) {
+ dev_err(swrm->dev,
+ "%s:lpass audio hw enable failed\n",
+ __func__);
+ --swrm->aud_core_clk_en;
+ }
+ }
+ } else {
+ --swrm->aud_core_clk_en;
+ if (swrm->aud_core_clk_en < 0)
+ swrm->aud_core_clk_en = 0;
+ else if (swrm->aud_core_clk_en == 0)
+ clk_disable_unprepare(
+ swrm->lpass_core_audio);
+ }
}
}
+ mutex_unlock(&swrm->devlock);
+ dev_dbg(swrm->dev, "%s: hw_clk_en: %d audio_core_clk_en: %d\n",
+ __func__, swrm->hw_core_clk_en, swrm->aud_core_clk_en);
+ trace_printk("%s: hw_clk_en: %d audio_core_clk_en: %d\n",
+ __func__, swrm->hw_core_clk_en, swrm->aud_core_clk_en);
return ret;
}
@@ -959,6 +1041,49 @@ end:
return is_removed;
}
+int swrm_get_clk_div_rate(int mclk_freq, int bus_clk_freq)
+{
+ if (!bus_clk_freq)
+ return mclk_freq;
+
+ if (mclk_freq == SWR_CLK_RATE_9P6MHZ) {
+ if (bus_clk_freq <= SWR_CLK_RATE_0P6MHZ)
+ bus_clk_freq = SWR_CLK_RATE_0P6MHZ;
+ else if (bus_clk_freq <= SWR_CLK_RATE_1P2MHZ)
+ bus_clk_freq = SWR_CLK_RATE_1P2MHZ;
+ else if (bus_clk_freq <= SWR_CLK_RATE_2P4MHZ)
+ bus_clk_freq = SWR_CLK_RATE_2P4MHZ;
+ else if (bus_clk_freq <= SWR_CLK_RATE_4P8MHZ)
+ bus_clk_freq = SWR_CLK_RATE_4P8MHZ;
+ else if (bus_clk_freq <= SWR_CLK_RATE_9P6MHZ)
+ bus_clk_freq = SWR_CLK_RATE_9P6MHZ;
+ } else if (mclk_freq == SWR_CLK_RATE_11P2896MHZ)
+ bus_clk_freq = SWR_CLK_RATE_11P2896MHZ;
+
+ return bus_clk_freq;
+}
+
+static int swrm_update_bus_clk(struct swr_mstr_ctrl *swrm)
+{
+ int ret = 0;
+ int agg_clk = 0;
+ int i;
+
+ for (i = 0; i < SWR_MSTR_PORT_LEN; i++)
+ agg_clk += swrm->mport_cfg[i].ch_rate;
+
+ if (agg_clk)
+ swrm->bus_clk = swrm_get_clk_div_rate(swrm->mclk_freq,
+ agg_clk);
+ else
+ swrm->bus_clk = swrm->mclk_freq;
+
+ dev_dbg(swrm->dev, "%s: all_port_clk: %d, bus_clk: %d\n",
+ __func__, agg_clk, swrm->bus_clk);
+
+ return ret;
+}
+
static void swrm_disable_ports(struct swr_master *master,
u8 bank)
{
@@ -1225,13 +1350,15 @@ static void swrm_apply_port_config(struct swr_master *master)
static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
{
u8 bank;
- u32 value, n_row, n_col;
+ u32 value = 0, n_row = 0, n_col = 0;
u32 row = 0, col = 0;
+ int bus_clk_div_factor;
int ret;
u8 ssp_period = 0;
struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK |
SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK |
+ SWRM_MCP_FRAME_CTRL_BANK_CLK_DIV_VALUE_BMSK |
SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK);
u8 inactive_bank;
int frame_sync = SWRM_FRAME_SYNC_SEL;
@@ -1292,13 +1419,17 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
clear_bit(DISABLE_PENDING, &swrm->port_req_pending);
swrm_disable_ports(master, bank);
}
- dev_dbg(swrm->dev, "%s: enable: %d, cfg_devs: %d\n",
- __func__, enable, swrm->num_cfg_devs);
+ dev_dbg(swrm->dev, "%s: enable: %d, cfg_devs: %d freq %d\n",
+ __func__, enable, swrm->num_cfg_devs, swrm->mclk_freq);
if (enable) {
/* set col = 16 */
n_col = SWR_MAX_COL;
col = SWRM_COL_16;
+ if (swrm->bus_clk == MCLK_FREQ_LP) {
+ n_col = SWR_MIN_COL;
+ col = SWRM_COL_02;
+ }
} else {
/*
* Do not change to col = 2 if there are still active ports
@@ -1313,25 +1444,26 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
}
/* Use default 50 * x, frame shape. Change based on mclk */
if (swrm->mclk_freq == MCLK_FREQ_NATIVE) {
- dev_dbg(swrm->dev, "setting 64 x %d frameshape\n",
- n_col ? 16 : 2);
+ dev_dbg(swrm->dev, "setting 64 x %d frameshape\n", col);
n_row = SWR_ROW_64;
row = SWRM_ROW_64;
frame_sync = SWRM_FRAME_SYNC_SEL_NATIVE;
} else {
- dev_dbg(swrm->dev, "setting 50 x %d frameshape\n",
- n_col ? 16 : 2);
+ dev_dbg(swrm->dev, "setting 50 x %d frameshape\n", col);
n_row = SWR_ROW_50;
row = SWRM_ROW_50;
frame_sync = SWRM_FRAME_SYNC_SEL;
}
ssp_period = swrm_get_ssp_period(swrm, row, col, frame_sync);
- dev_dbg(swrm->dev, "%s: ssp_period: %d\n", __func__, ssp_period);
-
+ bus_clk_div_factor = swrm_get_clk_div(swrm->mclk_freq, swrm->bus_clk);
+ dev_dbg(swrm->dev, "%s: ssp_period: %d, bus_clk_div:%d\n",
+ __func__, ssp_period, bus_clk_div_factor);
value = swr_master_read(swrm, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank));
value &= (~mask);
value |= ((n_row << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) |
(n_col << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) |
+ (bus_clk_div_factor <<
+ SWRM_MCP_FRAME_CTRL_BANK_CLK_DIV_VALUE_SHFT) |
((ssp_period - 1) << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
swr_master_write(swrm, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value);
@@ -1435,6 +1567,11 @@ static int swrm_connect_port(struct swr_master *master,
mport->port_en = true;
mport->req_ch |= mstr_ch_msk;
master->port_en_mask |= (1 << mstr_port_id);
+ if (swrm->clk_stop_mode0_supp &&
+ (mport->ch_rate < portinfo->ch_rate[i])) {
+ mport->ch_rate = portinfo->ch_rate[i];
+ swrm_update_bus_clk(swrm);
+ }
}
master->num_port += portinfo->num_port;
set_bit(ENABLE_PENDING, &swrm->port_req_pending);
@@ -1497,6 +1634,10 @@ static int swrm_disconnect_port(struct swr_master *master,
}
port_req->req_ch &= ~portinfo->ch_en[i];
mport->req_ch &= ~mstr_ch_mask;
+ if (swrm->clk_stop_mode0_supp && !mport->req_ch) {
+ mport->ch_rate = 0;
+ swrm_update_bus_clk(swrm);
+ }
}
master->num_port -= portinfo->num_port;
set_bit(DISABLE_PENDING, &swrm->port_req_pending);
@@ -1869,6 +2010,11 @@ handle_irq:
dev_err_ratelimited(swrm->dev,
"%s: SWR bus clsh detected\n",
__func__);
+ swrm->intr_mask &=
+ ~SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET;
+ swr_master_write(swrm,
+ SWR_MSTR_RX_SWRM_CPU_INTERRUPT_EN,
+ swrm->intr_mask);
break;
case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW:
dev_dbg(swrm->dev, "%s: SWR read FIFO overflow\n",
@@ -2142,22 +2288,15 @@ static void swrm_device_wakeup_vote(struct swr_master *mstr)
dev_err(swrm->dev, "%s Failed to hold suspend\n", __func__);
return;
}
- if (++swrm->hw_core_clk_en == 1)
- if (swrm_request_hw_vote(swrm, LPASS_HW_CORE, true)) {
- dev_err(swrm->dev, "%s:lpass core hw enable failed\n",
- __func__);
- --swrm->hw_core_clk_en;
- }
- if ( ++swrm->aud_core_clk_en == 1)
- if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) {
- dev_err(swrm->dev, "%s:lpass audio hw enable failed\n",
- __func__);
- --swrm->aud_core_clk_en;
- }
- dev_dbg(swrm->dev, "%s: hw_clk_en: %d audio_core_clk_en: %d\n",
- __func__, swrm->hw_core_clk_en, swrm->aud_core_clk_en);
- trace_printk("%s: hw_clk_en: %d audio_core_clk_en: %d\n",
- __func__, swrm->hw_core_clk_en, swrm->aud_core_clk_en);
+ mutex_lock(&swrm->reslock);
+ if (swrm_request_hw_vote(swrm, LPASS_HW_CORE, true))
+ dev_err(swrm->dev, "%s:lpass core hw enable failed\n",
+ __func__);
+ if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true))
+ dev_err(swrm->dev, "%s:lpass audio hw enable failed\n",
+ __func__);
+ mutex_unlock(&swrm->reslock);
+
pm_runtime_get_sync(swrm->dev);
}
@@ -2172,22 +2311,11 @@ static void swrm_device_wakeup_unvote(struct swr_master *mstr)
}
pm_runtime_mark_last_busy(swrm->dev);
pm_runtime_put_autosuspend(swrm->dev);
- dev_dbg(swrm->dev, "%s: hw_clk_en: %d audio_core_clk_en: %d\n",
- __func__, swrm->hw_core_clk_en, swrm->aud_core_clk_en);
-
- trace_printk("%s: hw_clk_en: %d audio_core_clk_en: %d\n",
- __func__, swrm->hw_core_clk_en, swrm->aud_core_clk_en);
- --swrm->aud_core_clk_en;
- if (swrm->aud_core_clk_en < 0)
- swrm->aud_core_clk_en = 0;
- else if (swrm->aud_core_clk_en == 0)
- swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false);
- --swrm->hw_core_clk_en;
- if (swrm->hw_core_clk_en < 0)
- swrm->hw_core_clk_en = 0;
- else if (swrm->hw_core_clk_en == 0)
- swrm_request_hw_vote(swrm, LPASS_HW_CORE, false);
+ mutex_lock(&swrm->reslock);
+ swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false);
+ swrm_request_hw_vote(swrm, LPASS_HW_CORE, false);
+ mutex_unlock(&swrm->reslock);
swrm_unlock_sleep(swrm);
}
@@ -2421,9 +2549,10 @@ static int swrm_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "%s: Looking up %s property failed\n",
__func__, "qcom,swr-num-dev");
} else {
- if (swrm->num_dev > SWR_MAX_SLAVE_DEVICES) {
+ if (swrm->num_dev > SWRM_NUM_AUTO_ENUM_SLAVES) {
dev_err(&pdev->dev, "%s: num_dev %d > max limit %d\n",
- __func__, swrm->num_dev, SWR_MAX_SLAVE_DEVICES);
+ __func__, swrm->num_dev,
+ SWRM_NUM_AUTO_ENUM_SLAVES);
ret = -EINVAL;
goto err_pdata_fail;
}
@@ -2890,7 +3019,23 @@ static int swrm_runtime_suspend(struct device *dev)
mutex_unlock(&swrm->reslock);
enable_bank_switch(swrm, 0, SWR_ROW_50, SWR_MIN_COL);
mutex_lock(&swrm->reslock);
- swrm_clk_pause(swrm);
+ if (!swrm->clk_stop_mode0_supp) {
+ swrm_clk_pause(swrm);
+ } else {
+ /* Mask bus clash interrupt */
+ swrm->intr_mask &= ~((u32)0x08);
+ swr_master_write(swrm,
+ SWRM_INTERRUPT_MASK_ADDR,
+ swrm->intr_mask);
+ swr_master_write(swrm,
+ SWR_MSTR_RX_SWRM_CPU_INTERRUPT_EN,
+ swrm->intr_mask);
+ mutex_unlock(&swrm->reslock);
+ /* clock stop sequence */
+ swrm_cmd_fifo_wr_cmd(swrm, 0x2, 0xF, 0xF,
+ SWRS_SCP_CONTROL);
+ mutex_lock(&swrm->reslock);
+ }
swr_master_write(swrm, SWRM_COMP_CFG_ADDR, 0x00);
list_for_each_entry(swr_dev, &mstr->devices, dev_list) {
ret = swr_device_down(swr_dev);
@@ -3166,12 +3311,19 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
break;
case SWR_DEVICE_SSR_DOWN:
trace_printk("%s: swr device down called\n", __func__);
+ mutex_lock(&swrm->mlock);
+ if (swrm->state == SWR_MSTR_DOWN)
+ dev_dbg(swrm->dev, "%s:SWR master is already Down:%d\n",
+ __func__, swrm->state);
+ else
+ swrm_device_down(&pdev->dev);
mutex_lock(&swrm->devlock);
swrm->dev_up = false;
mutex_unlock(&swrm->devlock);
mutex_lock(&swrm->reslock);
swrm->state = SWR_MSTR_SSR;
mutex_unlock(&swrm->reslock);
+ mutex_unlock(&swrm->mlock);
break;
case SWR_DEVICE_SSR_UP:
/* wait for clk voting to be zero */
@@ -3214,7 +3366,12 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
mutex_lock(&swrm->reslock);
list_for_each_entry(swr_dev, &mstr->devices, dev_list) {
ret = swr_reset_device(swr_dev);
- if (ret) {
+ if (ret == -ENODEV) {
+ dev_dbg_ratelimited(swrm->dev,
+ "%s slave reset not implemented\n",
+ __func__);
+ ret = 0;
+ } else if (ret) {
dev_err(swrm->dev,
"%s: failed to reset swr device %d\n",
__func__, swr_dev->dev_num);
diff --git a/4.0/soc/swr-mstr-ctrl.h b/4.0/soc/swr-mstr-ctrl.h
index 85f3e364..ce0b64d5 100644
--- a/4.0/soc/swr-mstr-ctrl.h
+++ b/4.0/soc/swr-mstr-ctrl.h
@@ -26,6 +26,7 @@
#define SWR_ROW_48 0
#define SWR_ROW_50 1
#define SWR_ROW_64 3
+#define SWR_COL_04 1 /* Cols = 4 */
#define SWR_MAX_COL 7 /* Cols = 16 */
#define SWR_MIN_COL 0 /* Cols = 2 */
@@ -42,7 +43,7 @@
#define SWR_MAX_CH_PER_PORT 8
-#define SWR_MAX_SLAVE_DEVICES 11
+#define SWRM_NUM_AUTO_ENUM_SLAVES 6
enum {
SWR_MSTR_PAUSE,
@@ -81,7 +82,6 @@ struct swrm_mports {
bool port_en;
u8 ch_en;
u8 req_ch;
- u8 ch_rate;
u8 offset1;
u8 offset2;
u8 sinterval;
@@ -91,6 +91,7 @@ struct swrm_mports {
u8 blk_pack_mode;
u8 word_length;
u8 lane_ctrl;
+ u32 ch_rate;
};
struct swrm_port_type {
diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index 534cd2d9..883f8107 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2020, 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
@@ -818,6 +818,28 @@ static int tx_macro_enable_micbias(struct snd_soc_dapm_widget *w,
return 0;
}
+/* Cutoff frequency for high pass filter */
+static const char * const cf_text[] = {
+ "CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
+};
+
+static SOC_ENUM_SINGLE_DECL(cf_dec0_enum, BOLERO_CDC_TX0_TX_PATH_CFG0, 5,
+ cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec1_enum, BOLERO_CDC_TX1_TX_PATH_CFG0, 5,
+ cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec2_enum, BOLERO_CDC_TX2_TX_PATH_CFG0, 5,
+ cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec3_enum, BOLERO_CDC_TX3_TX_PATH_CFG0, 5,
+ cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec4_enum, BOLERO_CDC_TX4_TX_PATH_CFG0, 5,
+ cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec5_enum, BOLERO_CDC_TX5_TX_PATH_CFG0, 5,
+ cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec6_enum, BOLERO_CDC_TX6_TX_PATH_CFG0, 5,
+ cf_text);
+static SOC_ENUM_SINGLE_DECL(cf_dec7_enum, BOLERO_CDC_TX7_TX_PATH_CFG0, 5,
+ cf_text);
+
static int tx_macro_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -1478,6 +1500,22 @@ static const struct snd_kcontrol_new tx_macro_snd_controls[] = {
BOLERO_CDC_TX7_TX_VOL_CTL,
0, -84, 40, digital_gain),
+ SOC_ENUM("TX0 HPF cut off", cf_dec0_enum),
+
+ SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
+
+ SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
+
+ SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
+
+ SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
+
+ SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
+
+ SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
+
+ SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
+
SOC_SINGLE_EXT("DEC0_BCS Switch", SND_SOC_NOPM, 0, 1, 0,
tx_macro_get_bcs, tx_macro_set_bcs),
};
diff --git a/dsp/q6lsm.c b/dsp/q6lsm.c
index a1bbd0bd..aa864ddb 100644
--- a/dsp/q6lsm.c
+++ b/dsp/q6lsm.c
@@ -369,9 +369,9 @@ void q6lsm_client_free(struct lsm_client *client)
pr_err("%s: Invalid Session %d\n", __func__, client->session);
return;
}
- mutex_lock(&session_lock);
apr_deregister(client->apr);
client->mmap_apr = NULL;
+ mutex_lock(&session_lock);
q6lsm_session_free(client);
q6lsm_mmap_apr_dereg();
mutex_destroy(&client->cmd_lock);