Merge "asoc: qcs405: fix pop at end of DSD playback"
diff --git a/Android.mk b/Android.mk
index f5b8931..e0d3f0f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -60,3 +60,8 @@
$(shell rm -rf $(PRODUCT_OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/wcd937x/Module.symvers)
include $(MY_LOCAL_PATH)/asoc/codecs/wcd937x/Android.mk
endif
+
+ifeq ($(call is-board-platform-in-list, lito),true)
+$(shell rm -rf $(PRODUCT_OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/wsa883x/Module.symvers)
+include $(MY_LOCAL_PATH)/asoc/codecs/wsa883x/Android.mk
+endif
\ No newline at end of file
diff --git a/asoc/bengal.c b/asoc/bengal.c
index 1ab7f99..ec73cc9 100644
--- a/asoc/bengal.c
+++ b/asoc/bengal.c
@@ -5030,6 +5030,33 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
},
+ /* Proxy Tx BACK END DAI Link */
+ {
+ .name = LPASS_BE_PROXY_TX,
+ .stream_name = "Proxy Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.8195",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .id = MSM_BACKEND_DAI_PROXY_TX,
+ .ignore_suspend = 1,
+ },
+ /* Proxy Rx BACK END DAI Link */
+ {
+ .name = LPASS_BE_PROXY_RX,
+ .stream_name = "Proxy Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.8194",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .id = MSM_BACKEND_DAI_PROXY_RX,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
{
.name = LPASS_BE_USB_AUDIO_RX,
.stream_name = "USB Audio Playback",
diff --git a/asoc/codecs/Kbuild b/asoc/codecs/Kbuild
index 7a2cfcd..5ab7c3b 100644
--- a/asoc/codecs/Kbuild
+++ b/asoc/codecs/Kbuild
@@ -227,6 +227,7 @@
obj-y += wcd938x/
obj-y += bolero/
obj-y += rouleur/
+ obj-y += wsa883x/
endif
# Module information used by KBuild framework
obj-$(CONFIG_WCD9XXX_CODEC_CORE) += wcd_core_dlkm.o
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index 2db0c5b..417b34d 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -14,6 +14,7 @@
#include <soc/snd_event.h>
#include <linux/pm_runtime.h>
#include <soc/swr-common.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
#include "bolero-cdc.h"
#include "internal.h"
#include "bolero-clk-rsc.h"
@@ -1367,6 +1368,7 @@
return 0;
}
+#ifdef CONFIG_PM
int bolero_runtime_resume(struct device *dev)
{
struct bolero_priv *priv = dev_get_drvdata(dev->parent);
@@ -1379,7 +1381,7 @@
}
if (priv->core_hw_vote_count == 0) {
- ret = clk_prepare_enable(priv->lpass_core_hw_vote);
+ ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_core_hw_vote);
if (ret < 0) {
dev_err(dev, "%s:lpass core hw enable failed\n",
__func__);
@@ -1397,7 +1399,7 @@
}
if (priv->core_audio_vote_count == 0) {
- ret = clk_prepare_enable(priv->lpass_audio_hw_vote);
+ ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_audio_hw_vote);
if (ret < 0) {
dev_err(dev, "%s:lpass audio hw enable failed\n",
__func__);
@@ -1422,7 +1424,8 @@
mutex_lock(&priv->vote_lock);
if (priv->lpass_core_hw_vote != NULL) {
if (--priv->core_hw_vote_count == 0)
- clk_disable_unprepare(priv->lpass_core_hw_vote);
+ digital_cdc_rsc_mgr_hw_vote_disable(
+ priv->lpass_core_hw_vote);
if (priv->core_hw_vote_count < 0)
priv->core_hw_vote_count = 0;
} else {
@@ -1434,7 +1437,8 @@
if (priv->lpass_audio_hw_vote != NULL) {
if (--priv->core_audio_vote_count == 0)
- clk_disable_unprepare(priv->lpass_audio_hw_vote);
+ digital_cdc_rsc_mgr_hw_vote_disable(
+ priv->lpass_audio_hw_vote);
if (priv->core_audio_vote_count < 0)
priv->core_audio_vote_count = 0;
} else {
@@ -1448,6 +1452,7 @@
return 0;
}
EXPORT_SYMBOL(bolero_runtime_suspend);
+#endif /* CONFIG_PM */
bool bolero_check_core_votes(struct device *dev)
{
diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c
index ea1a374..70b0126 100644
--- a/asoc/codecs/bolero/rx-macro.c
+++ b/asoc/codecs/bolero/rx-macro.c
@@ -1908,7 +1908,12 @@
0x40, 0x40);
break;
case INTERP_HPHR:
- snd_soc_component_update_bits(component,
+ if (rx_priv->is_ear_mode_on)
+ snd_soc_component_update_bits(component,
+ BOLERO_CDC_RX_CLSH_HPH_V_PA,
+ 0x3F, 0x39);
+ else
+ snd_soc_component_update_bits(component,
BOLERO_CDC_RX_CLSH_HPH_V_PA,
0x3F, 0x1C);
snd_soc_component_update_bits(component,
@@ -4135,6 +4140,10 @@
};
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/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index 9fe19c1..121f56d 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -496,8 +496,6 @@
hpf_cut_off_freq << 5);
snd_soc_component_update_bits(component, hpf_gate_reg,
0x03, 0x02);
- /* Minimum 1 clk cycle delay is required as per HW spec */
- usleep_range(1000, 1010);
snd_soc_component_update_bits(component, hpf_gate_reg,
0x03, 0x01);
} else {
@@ -980,11 +978,12 @@
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(
+ queue_delayed_work(system_freezable_wq,
&tx_priv->tx_hpf_work[decimator].dwork,
msecs_to_jiffies(hpf_delay));
snd_soc_component_update_bits(component,
@@ -992,10 +991,6 @@
if (!is_amic_enabled(component, decimator))
snd_soc_component_update_bits(component,
hpf_gate_reg, 0x03, 0x00);
- /*
- * Minimum 1 clk cycle delay is required as per HW spec
- */
- usleep_range(1000, 1010);
snd_soc_component_update_bits(component,
hpf_gate_reg, 0x03, 0x01);
/*
@@ -3297,6 +3292,10 @@
};
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/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c
index 85d4ae3..a947a28 100644
--- a/asoc/codecs/bolero/va-macro.c
+++ b/asoc/codecs/bolero/va-macro.c
@@ -16,6 +16,7 @@
#include <asoc/msm-cdc-pinctrl.h>
#include <soc/swr-common.h>
#include <soc/swr-wcd.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
#include "bolero-cdc.h"
#include "bolero-cdc-registers.h"
#include "bolero-clk-rsc.h"
@@ -444,7 +445,8 @@
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (va_priv->lpass_audio_hw_vote) {
- ret = clk_prepare_enable(va_priv->lpass_audio_hw_vote);
+ ret = digital_cdc_rsc_mgr_hw_vote_enable(
+ va_priv->lpass_audio_hw_vote);
if (ret)
dev_err(va_dev,
"%s: lpass audio hw enable failed\n",
@@ -467,7 +469,8 @@
if (bolero_tx_clk_switch(component, CLK_SRC_TX_RCG))
dev_dbg(va_dev, "%s: clock switch failed\n",__func__);
if (va_priv->lpass_audio_hw_vote)
- clk_disable_unprepare(va_priv->lpass_audio_hw_vote);
+ digital_cdc_rsc_mgr_hw_vote_disable(
+ va_priv->lpass_audio_hw_vote);
break;
default:
dev_err(va_priv->dev,
@@ -1183,11 +1186,12 @@
*/
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 */
@@ -3208,6 +3212,10 @@
};
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/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c
index e97d746..2ab2e8a 100644
--- a/asoc/codecs/bolero/wsa-macro.c
+++ b/asoc/codecs/bolero/wsa-macro.c
@@ -3244,6 +3244,10 @@
};
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/asoc/codecs/msm-cdc-supply.c b/asoc/codecs/msm-cdc-supply.c
index 220da9d..831562f 100644
--- a/asoc/codecs/msm-cdc-supply.c
+++ b/asoc/codecs/msm-cdc-supply.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/kernel.h>
@@ -119,6 +119,47 @@
}
/*
+ * msm_cdc_is_ondemand_supply:
+ * return if ondemand supply true or not
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ * @supply_name: supply name to be checked
+ *
+ * Return true/false
+ */
+bool msm_cdc_is_ondemand_supply(struct device *dev,
+ struct regulator_bulk_data *supplies,
+ struct cdc_regulator *cdc_vreg,
+ int num_supplies,
+ char *supply_name)
+{
+ bool rc = false;
+ int ret, i;
+
+ if ((!supply_name) || (!supplies)) {
+ pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
+ __func__);
+ return rc;
+ }
+ /* input parameter validation */
+ ret = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+ if (ret)
+ return rc;
+
+ for (i = 0; i < num_supplies; i++) {
+ if (cdc_vreg[i].ondemand &&
+ !strcmp(cdc_vreg[i].name, supply_name))
+ return true;
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL(msm_cdc_is_ondemand_supply);
+
+/*
* msm_cdc_disable_ondemand_supply:
* Disable codec ondemand supply
*
diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c
index 5c3f14f..30ad7e3 100644
--- a/asoc/codecs/wcd937x/wcd937x.c
+++ b/asoc/codecs/wcd937x/wcd937x.c
@@ -37,6 +37,8 @@
#define WCD937X_VERSION_ENTRY_SIZE 32
#define EAR_RX_PATH_AUX 1
+#define NUM_ATTEMPTS 5
+
enum {
CODEC_TX = 0,
CODEC_RX,
@@ -568,7 +570,8 @@
snd_soc_component_update_bits(component,
WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L,
0x0F, 0x06);
- snd_soc_component_update_bits(component,
+ if (wcd937x->comp1_enable)
+ snd_soc_component_update_bits(component,
WCD937X_DIGITAL_CDC_COMP_CTL_0,
0x02, 0x02);
usleep_range(5000, 5010);
@@ -586,6 +589,10 @@
snd_soc_component_update_bits(component,
WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L,
0x0F, 0x01);
+ if (wcd937x->comp1_enable)
+ snd_soc_component_update_bits(component,
+ WCD937X_DIGITAL_CDC_COMP_CTL_0,
+ 0x02, 0x00);
break;
};
return 0;
@@ -1447,7 +1454,7 @@
mutex_unlock(&wcd937x->ana_tx_clk_lock);
if (wcd937x->micb_ref[micb_index] == 1) {
snd_soc_component_update_bits(component,
- WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0xE0, 0xE0);
+ WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0xF0, 0xF0);
snd_soc_component_update_bits(component,
WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
snd_soc_component_update_bits(component,
@@ -1535,14 +1542,18 @@
{
int ret = 0;
uint8_t devnum = 0;
+ int num_retry = NUM_ATTEMPTS;
- ret = swr_get_logical_dev_num(swr_dev, swr_dev->addr, &devnum);
- if (ret) {
- dev_err(&swr_dev->dev,
- "%s get devnum %d for dev addr %lx failed\n",
- __func__, devnum, swr_dev->addr);
- return ret;
- }
+ do {
+ ret = swr_get_logical_dev_num(swr_dev, swr_dev->addr, &devnum);
+ if (ret) {
+ dev_err(&swr_dev->dev,
+ "%s get devnum %d for dev addr %lx failed\n",
+ __func__, devnum, swr_dev->addr);
+ /* retry after 1ms */
+ usleep_range(1000, 1010);
+ }
+ } while (ret && --num_retry);
swr_dev->dev_num = devnum;
return 0;
}
diff --git a/asoc/codecs/wcd938x/internal.h b/asoc/codecs/wcd938x/internal.h
index c59d5b8..f8a47fd 100644
--- a/asoc/codecs/wcd938x/internal.h
+++ b/asoc/codecs/wcd938x/internal.h
@@ -155,8 +155,8 @@
enum {
/* INTR_CTRL_INT_MASK_0 */
- WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET = 0,
- WCD938X_IRQ_MBHC_BUTTON_PRESS_DET,
+ WCD938X_IRQ_MBHC_BUTTON_PRESS_DET = 0,
+ WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET,
WCD938X_IRQ_MBHC_ELECT_INS_REM_DET,
WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
WCD938X_IRQ_MBHC_SW_DET,
diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c
index 8ade1d9..abd3106 100644
--- a/asoc/codecs/wcd938x/wcd938x.c
+++ b/asoc/codecs/wcd938x/wcd938x.c
@@ -657,8 +657,10 @@
WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 0x04, 0x04);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x01);
- snd_soc_component_update_bits(component,
- WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x02, 0x02);
+ if (wcd938x->comp1_enable)
+ snd_soc_component_update_bits(component,
+ WCD938X_DIGITAL_CDC_COMP_CTL_0,
+ 0x02, 0x02);
}
/* 5 msec delay as per HW requirement */
usleep_range(5000, 5010);
@@ -683,8 +685,10 @@
WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 0x04, 0x00);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x00);
- snd_soc_component_update_bits(component,
- WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x02, 0x00);
+ if (wcd938x->comp1_enable)
+ snd_soc_component_update_bits(component,
+ WCD938X_DIGITAL_CDC_COMP_CTL_0,
+ 0x02, 0x00);
}
snd_soc_component_update_bits(component,
WCD938X_ANA_EAR_COMPANDER_CTL, 0x80, 0x00);
@@ -777,7 +781,7 @@
usleep_range(100, 110);
set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
snd_soc_component_update_bits(component,
- WCD938X_DIGITAL_PDM_WD_CTL1, 0x17, 0x13);
+ WCD938X_DIGITAL_PDM_WD_CTL1, 0x07, 0x03);
break;
case SND_SOC_DAPM_POST_PMU:
/*
@@ -857,7 +861,7 @@
snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
0x10, 0x00);
snd_soc_component_update_bits(component,
- WCD938X_DIGITAL_PDM_WD_CTL1, 0x17, 0x00);
+ WCD938X_DIGITAL_PDM_WD_CTL1, 0x07, 0x00);
wcd_cls_h_fsm(component, &wcd938x->clsh_info,
WCD_CLSH_EVENT_POST_PA,
WCD_CLSH_STATE_HPHR,
@@ -913,7 +917,7 @@
usleep_range(100, 110);
set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
snd_soc_component_update_bits(component,
- WCD938X_DIGITAL_PDM_WD_CTL0, 0x17, 0x13);
+ WCD938X_DIGITAL_PDM_WD_CTL0, 0x07, 0x03);
break;
case SND_SOC_DAPM_POST_PMU:
/*
@@ -993,7 +997,7 @@
snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
0x20, 0x00);
snd_soc_component_update_bits(component,
- WCD938X_DIGITAL_PDM_WD_CTL0, 0x17, 0x00);
+ WCD938X_DIGITAL_PDM_WD_CTL0, 0x07, 0x00);
wcd_cls_h_fsm(component, &wcd938x->clsh_info,
WCD_CLSH_EVENT_POST_PA,
WCD_CLSH_STATE_HPHL,
@@ -1026,7 +1030,7 @@
wcd938x->rx_swr_dev->dev_num,
true);
snd_soc_component_update_bits(component,
- WCD938X_DIGITAL_PDM_WD_CTL2, 0x05, 0x05);
+ WCD938X_DIGITAL_PDM_WD_CTL2, 0x01, 0x01);
break;
case SND_SOC_DAPM_POST_PMU:
/* 1 msec delay as per HW requirement */
@@ -1054,7 +1058,7 @@
/* 1 msec delay as per HW requirement */
usleep_range(1000, 1010);
snd_soc_component_update_bits(component,
- WCD938X_DIGITAL_PDM_WD_CTL2, 0x05, 0x00);
+ WCD938X_DIGITAL_PDM_WD_CTL2, 0x01, 0x00);
wcd_cls_h_fsm(component, &wcd938x->clsh_info,
WCD_CLSH_EVENT_POST_PA,
WCD_CLSH_STATE_AUX,
@@ -1098,11 +1102,11 @@
if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_PDM_WD_CTL2,
- 0x05, 0x05);
+ 0x01, 0x01);
else
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_PDM_WD_CTL0,
- 0x17, 0x13);
+ 0x07, 0x03);
if (!wcd938x->comp1_enable)
snd_soc_component_update_bits(component,
WCD938X_ANA_EAR_COMPANDER_CTL, 0x80, 0x80);
@@ -1157,11 +1161,11 @@
if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_PDM_WD_CTL2,
- 0x05, 0x00);
+ 0x01, 0x00);
else
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_PDM_WD_CTL0,
- 0x17, 0x00);
+ 0x07, 0x00);
wcd_cls_h_fsm(component, &wcd938x->clsh_info,
WCD_CLSH_EVENT_POST_PA,
WCD_CLSH_STATE_EAR,
@@ -1878,7 +1882,7 @@
wcd938x->micb_ref[micb_index]++;
if (wcd938x->micb_ref[micb_index] == 1) {
snd_soc_component_update_bits(component,
- WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0xE0, 0xE0);
+ WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0xF0, 0xF0);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
snd_soc_component_update_bits(component,
@@ -2360,6 +2364,67 @@
return 0;
}
+static int wcd938x_codec_enable_vdd_buck(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *component =
+ snd_soc_dapm_to_component(w->dapm);
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+ struct wcd938x_pdata *pdata = NULL;
+ int ret = 0;
+
+ pdata = dev_get_platdata(wcd938x->dev);
+
+ if (!pdata) {
+ dev_err(component->dev, "%s: pdata is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!msm_cdc_is_ondemand_supply(wcd938x->dev,
+ wcd938x->supplies,
+ pdata->regulator,
+ pdata->num_supplies,
+ "cdc-vdd-buck"))
+ return 0;
+
+ dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+ w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (test_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask)) {
+ dev_dbg(component->dev,
+ "%s: buck already in enabled state\n",
+ __func__);
+ clear_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask);
+ return 0;
+ }
+ ret = msm_cdc_enable_ondemand_supply(wcd938x->dev,
+ wcd938x->supplies,
+ pdata->regulator,
+ pdata->num_supplies,
+ "cdc-vdd-buck");
+ if (ret == -EINVAL) {
+ dev_err(component->dev, "%s: vdd buck is not enabled\n",
+ __func__);
+ return ret;
+ }
+ clear_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask);
+ /*
+ * 200us sleep is required after LDO is enabled as per
+ * HW requirement
+ */
+ usleep_range(200, 250);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ set_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask);
+ break;
+ }
+ return 0;
+}
+
+
static int wcd938x_ldoh_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -2779,6 +2844,10 @@
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("VDD_BUCK", SND_SOC_NOPM, 0, 0,
+ wcd938x_codec_enable_vdd_buck,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
SND_SOC_DAPM_SUPPLY_S("CLS_H_PORT", 1, SND_SOC_NOPM, 0, 0,
wcd938x_enable_clsh,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
@@ -2936,6 +3005,7 @@
{"DMIC8_OUTPUT", NULL, "DMIC8_MIXER"},
{"DMIC8_MIXER", "Switch", "DMIC8"},
+ {"IN1_HPHL", NULL, "VDD_BUCK"},
{"IN1_HPHL", NULL, "CLS_H_PORT"},
{"RX1", NULL, "IN1_HPHL"},
{"RDAC1", NULL, "RX1"},
@@ -2943,6 +3013,7 @@
{"HPHL PGA", NULL, "HPHL_RDAC"},
{"HPHL", NULL, "HPHL PGA"},
+ {"IN2_HPHR", NULL, "VDD_BUCK"},
{"IN2_HPHR", NULL, "CLS_H_PORT"},
{"RX2", NULL, "IN2_HPHR"},
{"RDAC2", NULL, "RX2"},
@@ -2950,6 +3021,7 @@
{"HPHR PGA", NULL, "HPHR_RDAC"},
{"HPHR", NULL, "HPHR PGA"},
+ {"IN3_AUX", NULL, "VDD_BUCK"},
{"IN3_AUX", NULL, "CLS_H_PORT"},
{"RX3", NULL, "IN3_AUX"},
{"RDAC4", NULL, "RX3"},
@@ -3792,6 +3864,37 @@
#ifdef CONFIG_PM_SLEEP
static int wcd938x_suspend(struct device *dev)
{
+ struct wcd938x_priv *wcd938x = NULL;
+ int ret = 0;
+ struct wcd938x_pdata *pdata = NULL;
+
+ if (!dev)
+ return -ENODEV;
+
+ wcd938x = dev_get_drvdata(dev);
+ if (!wcd938x)
+ return -EINVAL;
+
+ pdata = dev_get_platdata(wcd938x->dev);
+
+ if (!pdata) {
+ dev_err(dev, "%s: pdata is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ if (test_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask)) {
+ ret = msm_cdc_disable_ondemand_supply(wcd938x->dev,
+ wcd938x->supplies,
+ pdata->regulator,
+ pdata->num_supplies,
+ "cdc-vdd-buck");
+ if (ret == -EINVAL) {
+ dev_err(dev, "%s: vdd buck is not disabled\n",
+ __func__);
+ return 0;
+ }
+ clear_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask);
+ }
return 0;
}
diff --git a/asoc/codecs/wsa881x-analog.c b/asoc/codecs/wsa881x-analog.c
index 038e338..fe8a5b9 100644
--- a/asoc/codecs/wsa881x-analog.c
+++ b/asoc/codecs/wsa881x-analog.c
@@ -398,9 +398,14 @@
snd_soc_component_update_bits(component,
WSA881X_BOOST_SLOPE_COMP_ISENSE_FB,
0x03, 0x00);
- snd_soc_component_update_bits(component,
- WSA881X_BOOST_PRESET_OUT1,
- 0xF0, 0x70);
+ if (snd_soc_component_read32(component, WSA881X_OTP_REG_0))
+ snd_soc_component_update_bits(component,
+ WSA881X_BOOST_PRESET_OUT1,
+ 0xF0, 0x70);
+ else
+ snd_soc_component_update_bits(component,
+ WSA881X_BOOST_PRESET_OUT1,
+ 0xF0, 0xB0);
snd_soc_component_update_bits(component,
WSA881X_ANA_CTL, 0x03, 0x01);
snd_soc_component_update_bits(component,
diff --git a/asoc/codecs/wsa883x/Android.mk b/asoc/codecs/wsa883x/Android.mk
index 66056e8..42ad517 100644
--- a/asoc/codecs/wsa883x/Android.mk
+++ b/asoc/codecs/wsa883x/Android.mk
@@ -9,7 +9,7 @@
AUDIO_CHIPSET := audio
# Build/Package only in case of supported target
-ifeq ($(call is-board-platform-in-list,lahaina),true)
+ifeq ($(call is-board-platform-in-list,lahaina lito),true)
LOCAL_PATH := $(call my-dir)
diff --git a/asoc/codecs/wsa883x/Kbuild b/asoc/codecs/wsa883x/Kbuild
index 4eb844a..ac608b4 100644
--- a/asoc/codecs/wsa883x/Kbuild
+++ b/asoc/codecs/wsa883x/Kbuild
@@ -18,6 +18,10 @@
include $(AUDIO_ROOT)/config/lahainaauto.conf
INCS += -include $(AUDIO_ROOT)/config/lahainaautoconf.h
endif
+ ifeq ($(CONFIG_ARCH_LITO), y)
+ include $(AUDIO_ROOT)/config/litoauto.conf
+ INCS += -include $(AUDIO_ROOT)/config/litoautoconf.h
+ endif
endif
# As per target team, build is done as follows:
diff --git a/asoc/codecs/wsa883x/internal.h b/asoc/codecs/wsa883x/internal.h
index 2384043..1863aac 100644
--- a/asoc/codecs/wsa883x/internal.h
+++ b/asoc/codecs/wsa883x/internal.h
@@ -1,11 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
*/
#ifndef WSA883X_INTERNAL_H
#define WSA883X_INTERNAL_H
+#include <asoc/wcd-irq.h>
#include "wsa883x.h"
#include "wsa883x-registers.h"
@@ -25,7 +26,11 @@
#define WSA883X_DRV_NAME "wsa883x-codec"
#define WSA883X_NUM_RETRY 5
-#define WSA883X_VERSION_ENTRY_SIZE 27
+#define WSA883X_VERSION_ENTRY_SIZE 32
+#define WSA883X_VARIANT_ENTRY_SIZE 32
+
+#define WSA883X_VERSION_1_0 0
+#define WSA883X_VERSION_1_1 1
enum {
G_18DB = 0,
@@ -60,12 +65,13 @@
BOLERO_WSA_EVT_PA_OFF_PRE_SSR,
BOLERO_WSA_EVT_SSR_DOWN,
BOLERO_WSA_EVT_SSR_UP,
+ BOLERO_WSA_EVT_PA_ON_POST_FSCLK,
};
struct wsa_ctrl_platform_data {
- void *handle,
+ void *handle;
int (*update_wsa_event)(void *handle, u16 event, u32 data);
- int (*register_notifier)(void *handle, struct notifer_block *nblock,
+ int (*register_notifier)(void *handle, struct notifier_block *nblock,
bool enable);
};
@@ -97,10 +103,13 @@
struct mutex res_lock;
struct snd_info_entry *entry;
struct snd_info_entry *version_entry;
+ struct snd_info_entry *variant_entry;
struct device_node *wsa_rst_np;
int pa_mute;
int curr_temp;
int variant;
+ int version;
+ u8 pa_gain;
struct irq_domain *virq;
struct wcd_irq_info irq_info;
#ifdef CONFIG_DEBUG_FS
@@ -116,8 +125,11 @@
void *handle;
int (*register_notifier)(void *handle,
struct notifier_block *nblock, bool enable);
+ struct delayed_work vbat_work;
+ struct cdc_regulator *regulator;
+ int num_supplies;
+ struct regulator_bulk_data *supplies;
+ unsigned long status_mask;
};
-static int32_t wsa883x_resource_acquire(struct snd_soc_component *component,
- bool enable);
#endif /* WSA883X_INTERNAL_H */
diff --git a/asoc/codecs/wsa883x/wsa883x-registers.h b/asoc/codecs/wsa883x/wsa883x-registers.h
index 7e518d2..6450a45 100644
--- a/asoc/codecs/wsa883x/wsa883x-registers.h
+++ b/asoc/codecs/wsa883x/wsa883x-registers.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2019-2020, The Linux Foundation. All rights reserved.
*/
#ifndef WSA883X_REGISTERS_H
@@ -15,7 +15,7 @@
RD_WR_REG,
};
-#define WSA883X_ANA_BG_TSADC_BASE (WSA883X_BASE+0x00000000)
+#define WSA883X_ANA_BG_TSADC_BASE (WSA883X_BASE+0x00000001)
#define WSA883X_REF_CTRL (WSA883X_ANA_BG_TSADC_BASE+0x0000)
#define WSA883X_TEST_CTL_0 (WSA883X_ANA_BG_TSADC_BASE+0x0001)
#define WSA883X_BIAS_0 (WSA883X_ANA_BG_TSADC_BASE+0x0002)
@@ -69,8 +69,8 @@
#define WSA883X_SPKR_DRV_LF_MASK_DCC_CTL (WSA883X_ANA_SPK_TOP_BASE+0x000F)
#define WSA883X_SPKR_DRV_LF_MISC_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0010)
#define WSA883X_SPKR_DRV_LF_REG_GAIN (WSA883X_ANA_SPK_TOP_BASE+0x0011)
-#define WSA883X_SPKR_DRV_LF_OS_CAL_CTL1 (WSA883X_ANA_SPK_TOP_BASE+0x0012)
-#define WSA883X_SPKR_DRV_LF_OS_CAL_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0013)
+#define WSA883X_SPKR_DRV_OS_CAL_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0012)
+#define WSA883X_SPKR_DRV_OS_CAL_CTL1 (WSA883X_ANA_SPK_TOP_BASE+0x0013)
#define WSA883X_SPKR_PWM_CLK_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0014)
#define WSA883X_SPKR_PDRV_HS_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0015)
#define WSA883X_SPKR_PDRV_LS_CTL (WSA883X_ANA_SPK_TOP_BASE+0x0016)
@@ -81,7 +81,7 @@
#define WSA883X_PA_STATUS1 (WSA883X_ANA_SPK_TOP_BASE+0x001B)
#define WSA883X_PA_STATUS2 (WSA883X_ANA_SPK_TOP_BASE+0x001C)
-#define WSA883X_ANA_BOOST_BASE (WSA883X_BASE+0x00000045)
+#define WSA883X_ANA_BOOST_BASE (WSA883X_BASE+0x00000043)
#define WSA883X_EN_CTRL (WSA883X_ANA_BOOST_BASE+0x0000)
#define WSA883X_CURRENT_LIMIT (WSA883X_ANA_BOOST_BASE+0x0001)
#define WSA883X_IBIAS1 (WSA883X_ANA_BOOST_BASE+0x0002)
@@ -92,34 +92,35 @@
#define WSA883X_STABILITY_CTRL2 (WSA883X_ANA_BOOST_BASE+0x0007)
#define WSA883X_PWRSTAGE_CTRL1 (WSA883X_ANA_BOOST_BASE+0x0008)
#define WSA883X_PWRSTAGE_CTRL2 (WSA883X_ANA_BOOST_BASE+0x0009)
-#define WSA883X_UVLO (WSA883X_ANA_BOOST_BASE+0x000A)
-#define WSA883X_SEQUENCE_CTRL (WSA883X_ANA_BOOST_BASE+0x000B)
+#define WSA883X_BYPASS_1 (WSA883X_ANA_BOOST_BASE+0x000A)
+#define WSA883X_BYPASS_2 (WSA883X_ANA_BOOST_BASE+0x000B)
#define WSA883X_ZX_CTRL_1 (WSA883X_ANA_BOOST_BASE+0x000C)
#define WSA883X_ZX_CTRL_2 (WSA883X_ANA_BOOST_BASE+0x000D)
#define WSA883X_MISC1 (WSA883X_ANA_BOOST_BASE+0x000E)
#define WSA883X_MISC2 (WSA883X_ANA_BOOST_BASE+0x000F)
#define WSA883X_GMAMP_SUP1 (WSA883X_ANA_BOOST_BASE+0x0010)
#define WSA883X_PWRSTAGE_CTRL3 (WSA883X_ANA_BOOST_BASE+0x0011)
-#define WSA883X_PRSTAGE_CTRL4 (WSA883X_ANA_BOOST_BASE+0x0012)
-#define WSA883X_SPARE1 (WSA883X_ANA_BOOST_BASE+0x0013)
+#define WSA883X_PWRSTAGE_CTRL4 (WSA883X_ANA_BOOST_BASE+0x0012)
+#define WSA883X_TEST1 (WSA883X_ANA_BOOST_BASE+0x0013)
+#define WSA883X_SPARE1 (WSA883X_ANA_BOOST_BASE+0x0014)
+#define WSA883X_SPARE2 (WSA883X_ANA_BOOST_BASE+0x0015)
#define WSA883X_ANA_PON_LDOL_BASE (WSA883X_BASE+0x00000059)
#define WSA883X_PON_CTL_0 (WSA883X_ANA_PON_LDOL_BASE+0x0000)
#define WSA883X_PON_CLT_1 (WSA883X_ANA_PON_LDOL_BASE+0x0001)
#define WSA883X_PON_CTL_2 (WSA883X_ANA_PON_LDOL_BASE+0x0002)
#define WSA883X_PON_CTL_3 (WSA883X_ANA_PON_LDOL_BASE+0x0003)
-#define WSA883X_PON_CTL_4 (WSA883X_ANA_PON_LDOL_BASE+0x0004)
-#define WSA883X_CKWD_CTL_0 (WSA883X_ANA_PON_LDOL_BASE+0x0005)
-#define WSA883X_CKWD_CTL_1 (WSA883X_ANA_PON_LDOL_BASE+0x0006)
-#define WSA883X_CKWD_CTL_2 (WSA883X_ANA_PON_LDOL_BASE+0x0007)
-#define WSA883X_CKSK_CTL_0 (WSA883X_ANA_PON_LDOL_BASE+0x0008)
+#define WSA883X_CKWD_CTL_0 (WSA883X_ANA_PON_LDOL_BASE+0x0004)
+#define WSA883X_CKWD_CTL_1 (WSA883X_ANA_PON_LDOL_BASE+0x0005)
+#define WSA883X_CKWD_CTL_2 (WSA883X_ANA_PON_LDOL_BASE+0x0006)
+#define WSA883X_CKSK_CTL_0 (WSA883X_ANA_PON_LDOL_BASE+0x0007)
+#define WSA883X_PADSW_CTL_0 (WSA883X_ANA_PON_LDOL_BASE+0x0008)
#define WSA883X_TEST_0 (WSA883X_ANA_PON_LDOL_BASE+0x0009)
#define WSA883X_TEST_1 (WSA883X_ANA_PON_LDOL_BASE+0x000A)
#define WSA883X_STATUS_0 (WSA883X_ANA_PON_LDOL_BASE+0x000B)
#define WSA883X_STATUS_1 (WSA883X_ANA_PON_LDOL_BASE+0x000C)
#define WSA883X_DIG_CTRL_BASE (WSA883X_BASE+0x00000400)
-#define WSA883X_PAGE_REGISTER (WSA883X_DIG_CTRL_BASE+0x0000)
#define WSA883X_CHIP_ID0 (WSA883X_DIG_CTRL_BASE+0x0001)
#define WSA883X_CHIP_ID1 (WSA883X_DIG_CTRL_BASE+0x0002)
#define WSA883X_CHIP_ID2 (WSA883X_DIG_CTRL_BASE+0x0003)
@@ -130,6 +131,7 @@
#define WSA883X_CDC_PATH_MODE (WSA883X_DIG_CTRL_BASE+0x0008)
#define WSA883X_CDC_CLK_CTL (WSA883X_DIG_CTRL_BASE+0x0009)
#define WSA883X_SWR_RESET_EN (WSA883X_DIG_CTRL_BASE+0x000A)
+#define WSA883X_RESET_CTL (WSA883X_DIG_CTRL_BASE+0x000B)
#define WSA883X_PA_FSM_CTL (WSA883X_DIG_CTRL_BASE+0x0010)
#define WSA883X_PA_FSM_TIMER0 (WSA883X_DIG_CTRL_BASE+0x0011)
#define WSA883X_PA_FSM_TIMER1 (WSA883X_DIG_CTRL_BASE+0x0012)
@@ -137,6 +139,7 @@
#define WSA883X_PA_FSM_ERR_COND (WSA883X_DIG_CTRL_BASE+0x0014)
#define WSA883X_PA_FSM_MSK (WSA883X_DIG_CTRL_BASE+0x0015)
#define WSA883X_PA_FSM_BYP (WSA883X_DIG_CTRL_BASE+0x0016)
+#define WSA883X_PA_FSM_DBG (WSA883X_DIG_CTRL_BASE+0x0017)
#define WSA883X_TADC_VALUE_CTL (WSA883X_DIG_CTRL_BASE+0x0020)
#define WSA883X_TEMP_DETECT_CTL (WSA883X_DIG_CTRL_BASE+0x0021)
#define WSA883X_TEMP_MSB (WSA883X_DIG_CTRL_BASE+0x0022)
@@ -208,8 +211,10 @@
#define WSA883X_WAVG_PER_2_3 (WSA883X_DIG_CTRL_BASE+0x0068)
#define WSA883X_WAVG_PER_4_5 (WSA883X_DIG_CTRL_BASE+0x0069)
#define WSA883X_WAVG_PER_6_7 (WSA883X_DIG_CTRL_BASE+0x006A)
+#define WSA883X_WAVG_STA (WSA883X_DIG_CTRL_BASE+0x006B)
#define WSA883X_DRE_CTL_0 (WSA883X_DIG_CTRL_BASE+0x006C)
#define WSA883X_DRE_CTL_1 (WSA883X_DIG_CTRL_BASE+0x006D)
+#define WSA883X_DRE_IDLE_DET_CTL (WSA883X_DIG_CTRL_BASE+0x006E)
#define WSA883X_CLSH_CTL_0 (WSA883X_DIG_CTRL_BASE+0x0070)
#define WSA883X_CLSH_CTL_1 (WSA883X_DIG_CTRL_BASE+0x0071)
#define WSA883X_CLSH_V_HD_PA (WSA883X_DIG_CTRL_BASE+0x0072)
@@ -249,26 +254,28 @@
#define WSA883X_I2C_SLAVE_CTL (WSA883X_DIG_CTRL_BASE+0x0097)
#define WSA883X_PDM_TEST_MODE (WSA883X_DIG_CTRL_BASE+0x00A0)
#define WSA883X_ATE_TEST_MODE (WSA883X_DIG_CTRL_BASE+0x00A1)
-#define WSA883X_DRE_TEST (WSA883X_DIG_CTRL_BASE+0x00A2)
#define WSA883X_DIG_DEBUG_MODE (WSA883X_DIG_CTRL_BASE+0x00A3)
#define WSA883X_DIG_DEBUG_SEL (WSA883X_DIG_CTRL_BASE+0x00A4)
#define WSA883X_DIG_DEBUG_EN (WSA883X_DIG_CTRL_BASE+0x00A5)
#define WSA883X_SWR_HM_TEST0 (WSA883X_DIG_CTRL_BASE+0x00A6)
#define WSA883X_SWR_HM_TEST1 (WSA883X_DIG_CTRL_BASE+0x00A7)
#define WSA883X_SWR_PAD_CTL (WSA883X_DIG_CTRL_BASE+0x00A8)
-#define WSA883X_TEMP_DETECT_DBG_CTL (WSA883X_DIG_CTRL_BASE+0x00A9)
-#define WSA883X_TEMP_DEBUG_MSB (WSA883X_DIG_CTRL_BASE+0x00AA)
-#define WSA883X_TEMP_DEBUG_LSB (WSA883X_DIG_CTRL_BASE+0x00AB)
+#define WSA883X_TADC_DETECT_DBG_CTL (WSA883X_DIG_CTRL_BASE+0x00A9)
+#define WSA883X_TADC_DEBUG_MSB (WSA883X_DIG_CTRL_BASE+0x00AA)
+#define WSA883X_TADC_DEBUG_LSB (WSA883X_DIG_CTRL_BASE+0x00AB)
#define WSA883X_SAMPLE_EDGE_SEL (WSA883X_DIG_CTRL_BASE+0x00AC)
-#define WSA883X_TEST_MODE_CTL (WSA883X_DIG_CTRL_BASE+0x00AD)
-#define WSA883X_IOPAD_CTL (WSA883X_DIG_CTRL_BASE+0x00AE)
-#define WSA883X_SPARE_0 (WSA883X_DIG_CTRL_BASE+0x00B0)
-#define WSA883X_SPARE_1 (WSA883X_DIG_CTRL_BASE+0x00B1)
-#define WSA883X_SPARE_2 (WSA883X_DIG_CTRL_BASE+0x00B2)
+#define WSA883X_SWR_EDGE_SEL (WSA883X_DIG_CTRL_BASE+0x00AD)
+#define WSA883X_TEST_MODE_CTL (WSA883X_DIG_CTRL_BASE+0x00AE)
+#define WSA883X_IOPAD_CTL (WSA883X_DIG_CTRL_BASE+0x00AF)
+#define WSA883X_ANA_CSR_DBG_ADD (WSA883X_DIG_CTRL_BASE+0x00B0)
+#define WSA883X_ANA_CSR_DBG_CTL (WSA883X_DIG_CTRL_BASE+0x00B1)
+#define WSA883X_SPARE_R (WSA883X_DIG_CTRL_BASE+0x00BC)
+#define WSA883X_SPARE_0 (WSA883X_DIG_CTRL_BASE+0x00BD)
+#define WSA883X_SPARE_1 (WSA883X_DIG_CTRL_BASE+0x00BE)
+#define WSA883X_SPARE_2 (WSA883X_DIG_CTRL_BASE+0x00BF)
#define WSA883X_SCODE (WSA883X_DIG_CTRL_BASE+0x00C0)
#define WSA883X_DIG_TRIM_BASE (WSA883X_BASE+0x00000500)
-#define WSA883X_PAGE_REGISTER (WSA883X_DIG_TRIM_BASE+0x0000)
#define WSA883X_OTP_REG_0 (WSA883X_DIG_TRIM_BASE+0x0080)
#define WSA883X_OTP_REG_1 (WSA883X_DIG_TRIM_BASE+0x0081)
#define WSA883X_OTP_REG_2 (WSA883X_DIG_TRIM_BASE+0x0082)
@@ -301,7 +308,10 @@
#define WSA883X_OTP_REG_29 (WSA883X_DIG_TRIM_BASE+0x009D)
#define WSA883X_OTP_REG_30 (WSA883X_DIG_TRIM_BASE+0x009E)
#define WSA883X_OTP_REG_31 (WSA883X_DIG_TRIM_BASE+0x009F)
-#define WSA883X_OTP_REG_SCODE (WSA883X_DIG_TRIM_BASE+0x00A0)
+#define WSA883X_OTP_REG_32 (WSA883X_DIG_TRIM_BASE+0x00A0)
+#define WSA883X_OTP_REG_33 (WSA883X_DIG_TRIM_BASE+0x00A1)
+#define WSA883X_OTP_REG_34 (WSA883X_DIG_TRIM_BASE+0x00A2)
+#define WSA883X_OTP_REG_35 (WSA883X_DIG_TRIM_BASE+0x00A3)
#define WSA883X_OTP_REG_63 (WSA883X_DIG_TRIM_BASE+0x00BF)
#define WSA883X_DIG_EMEM_BASE (WSA883X_BASE+0x000005C0)
diff --git a/asoc/codecs/wsa883x/wsa883x-regmap.c b/asoc/codecs/wsa883x/wsa883x-regmap.c
index 8394e9c..b55fbad 100644
--- a/asoc/codecs/wsa883x/wsa883x-regmap.c
+++ b/asoc/codecs/wsa883x/wsa883x-regmap.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2015-2016, 2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 2019-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/regmap.h>
@@ -11,100 +11,101 @@
extern const u8 wsa883x_reg_access[WSA883X_NUM_REGISTERS];
static struct reg_default wsa883x_defaults[] = {
- {WSA883X_REF_CTRL, 0x6C},
+ {WSA883X_REF_CTRL, 0xD5},
{WSA883X_TEST_CTL_0, 0x06},
{WSA883X_BIAS_0, 0xD2},
{WSA883X_OP_CTL, 0xE0},
- {WSA883X_IREF_CTL, 0x58},
+ {WSA883X_IREF_CTL, 0x57},
{WSA883X_ISENS_CTL, 0x47},
{WSA883X_CLK_CTL, 0x87},
{WSA883X_TEST_CTL_1, 0x00},
{WSA883X_BIAS_1, 0x51},
- {WSA883X_ADC_CTL, 0x03},
+ {WSA883X_ADC_CTL, 0x01},
{WSA883X_DOUT_MSB, 0x00},
{WSA883X_DOUT_LSB, 0x00},
- {WSA883X_VBAT_SNS, 0x00},
- {WSA883X_ITRIM_CODE, 0x1F},
- {WSA883X_EN, 0x00},
+ {WSA883X_VBAT_SNS, 0x40},
+ {WSA883X_ITRIM_CODE, 0x9F},
+ {WSA883X_EN, 0x20},
{WSA883X_OVERRIDE1, 0x00},
{WSA883X_OVERRIDE2, 0x08},
{WSA883X_VSENSE1, 0xD3},
{WSA883X_ISENSE1, 0xD4},
{WSA883X_ISENSE2, 0x20},
{WSA883X_ISENSE_CAL, 0x00},
- {WSA883X_MISC, 0x00},
+ {WSA883X_MISC, 0x08},
{WSA883X_ADC_0, 0x00},
{WSA883X_ADC_1, 0x00},
- {WSA883X_ADC_2, 0x00},
- {WSA883X_ADC_3, 0x00},
- {WSA883X_ADC_4, 0x45},
- {WSA883X_ADC_5, 0x20},
- {WSA883X_ADC_6, 0x10},
- {WSA883X_ADC_7, 0x00},
+ {WSA883X_ADC_2, 0x40},
+ {WSA883X_ADC_3, 0x80},
+ {WSA883X_ADC_4, 0x25},
+ {WSA883X_ADC_5, 0x25},
+ {WSA883X_ADC_6, 0x08},
+ {WSA883X_ADC_7, 0x81},
{WSA883X_STATUS, 0x00},
- {WSA883X_DAC_CTRL_REG, 0x41},
+ {WSA883X_DAC_CTRL_REG, 0x53},
{WSA883X_DAC_EN_DEBUG_REG, 0x00},
{WSA883X_DAC_OPAMP_BIAS1_REG, 0x48},
{WSA883X_DAC_OPAMP_BIAS2_REG, 0x48},
- {WSA883X_DAC_VCM_CTRL_REG, 0x0B},
- {WSA883X_DAC_VOLTAGE_CTRL_REG, 0x05},
+ {WSA883X_DAC_VCM_CTRL_REG, 0x88},
+ {WSA883X_DAC_VOLTAGE_CTRL_REG, 0xA5},
{WSA883X_ATEST1_REG, 0x00},
{WSA883X_ATEST2_REG, 0x00},
- {WSA883X_SPKR_TOP_BIAS_REG1, 0x4A},
+ {WSA883X_SPKR_TOP_BIAS_REG1, 0x6A},
{WSA883X_SPKR_TOP_BIAS_REG2, 0x65},
{WSA883X_SPKR_TOP_BIAS_REG3, 0x55},
{WSA883X_SPKR_TOP_BIAS_REG4, 0xA9},
- {WSA883X_SPKR_CLIP_DET_REG, 0x00},
+ {WSA883X_SPKR_CLIP_DET_REG, 0x9C},
{WSA883X_SPKR_DRV_LF_BLK_EN, 0x0F},
{WSA883X_SPKR_DRV_LF_EN, 0x0A},
{WSA883X_SPKR_DRV_LF_MASK_DCC_CTL, 0x00},
- {WSA883X_SPKR_DRV_LF_MISC_CTL, 0x32},
+ {WSA883X_SPKR_DRV_LF_MISC_CTL, 0x3A},
{WSA883X_SPKR_DRV_LF_REG_GAIN, 0x00},
- {WSA883X_SPKR_DRV_LF_OS_CAL_CTL1, 0x90},
- {WSA883X_SPKR_DRV_LF_OS_CAL_CTL, 0x00},
+ {WSA883X_SPKR_DRV_OS_CAL_CTL, 0x00},
+ {WSA883X_SPKR_DRV_OS_CAL_CTL1, 0x90},
{WSA883X_SPKR_PWM_CLK_CTL, 0x00},
- {WSA883X_SPKR_PDRV_HS_CTL, 0x50},
+ {WSA883X_SPKR_PDRV_HS_CTL, 0x52},
{WSA883X_SPKR_PDRV_LS_CTL, 0x48},
- {WSA883X_SPKR_PWRSTG_DBG, 0x00},
- {WSA883X_SPKR_OCP_CTL, 0x00},
- {WSA883X_SPKR_BBM_CTL, 0x90},
+ {WSA883X_SPKR_PWRSTG_DBG, 0x08},
+ {WSA883X_SPKR_OCP_CTL, 0xE2},
+ {WSA883X_SPKR_BBM_CTL, 0x92},
{WSA883X_PA_STATUS0, 0x00},
{WSA883X_PA_STATUS1, 0x00},
- {WSA883X_PA_STATUS2, 0x00},
- {WSA883X_EN_CTRL, 0x54},
- {WSA883X_CURRENT_LIMIT, 0x90},
+ {WSA883X_PA_STATUS2, 0x80},
+ {WSA883X_EN_CTRL, 0x44},
+ {WSA883X_CURRENT_LIMIT, 0xCC},
{WSA883X_IBIAS1, 0x00},
{WSA883X_IBIAS2, 0x00},
{WSA883X_IBIAS3, 0x00},
- {WSA883X_LDO_PROG, 0x2A},
+ {WSA883X_LDO_PROG, 0x02},
{WSA883X_STABILITY_CTRL1, 0x8E},
- {WSA883X_STABILITY_CTRL2, 0x00},
- {WSA883X_PWRSTAGE_CTRL1, 0x00},
- {WSA883X_PWRSTAGE_CTRL2, 0x40},
- {WSA883X_UVLO, 0xE9},
- {WSA883X_SEQUENCE_CTRL, 0x11},
+ {WSA883X_STABILITY_CTRL2, 0x10},
+ {WSA883X_PWRSTAGE_CTRL1, 0x06},
+ {WSA883X_PWRSTAGE_CTRL2, 0x00},
+ {WSA883X_BYPASS_1, 0x19},
+ {WSA883X_BYPASS_2, 0x13},
{WSA883X_ZX_CTRL_1, 0xF0},
- {WSA883X_ZX_CTRL_2, 0x06},
- {WSA883X_MISC1, 0x02},
- {WSA883X_MISC2, 0x81},
- {WSA883X_GMAMP_SUP1, 0x84},
- {WSA883X_PWRSTAGE_CTRL3, 0x14},
- {WSA883X_PRSTAGE_CTRL4, 0x5F},
+ {WSA883X_ZX_CTRL_2, 0x04},
+ {WSA883X_MISC1, 0x06},
+ {WSA883X_MISC2, 0xA0},
+ {WSA883X_GMAMP_SUP1, 0x82},
+ {WSA883X_PWRSTAGE_CTRL3, 0x39},
+ {WSA883X_PWRSTAGE_CTRL4, 0x5F},
+ {WSA883X_TEST1, 0x00},
{WSA883X_SPARE1, 0x00},
- {WSA883X_PON_CTL_0, 0xE3},
- {WSA883X_PON_CLT_1, 0x70},
- {WSA883X_PON_CTL_2, 0x00},
- {WSA883X_PON_CTL_3, 0x00},
- {WSA883X_PON_CTL_4, 0x00},
+ {WSA883X_SPARE2, 0x00},
+ {WSA883X_PON_CTL_0, 0x10},
+ {WSA883X_PON_CLT_1, 0xE0},
+ {WSA883X_PON_CTL_2, 0x90},
+ {WSA883X_PON_CTL_3, 0x70},
{WSA883X_CKWD_CTL_0, 0x34},
- {WSA883X_CKWD_CTL_1, 0x80},
+ {WSA883X_CKWD_CTL_1, 0x0F},
{WSA883X_CKWD_CTL_2, 0x00},
- {WSA883X_CKSK_CTL_0, 0x0A},
+ {WSA883X_CKSK_CTL_0, 0x00},
+ {WSA883X_PADSW_CTL_0, 0x00},
{WSA883X_TEST_0, 0x00},
{WSA883X_TEST_1, 0x00},
{WSA883X_STATUS_0, 0x00},
{WSA883X_STATUS_1, 0x00},
- {WSA883X_PAGE_REGISTER, 0x00},
{WSA883X_CHIP_ID0, 0x00},
{WSA883X_CHIP_ID1, 0x00},
{WSA883X_CHIP_ID2, 0x02},
@@ -115,13 +116,15 @@
{WSA883X_CDC_PATH_MODE, 0x00},
{WSA883X_CDC_CLK_CTL, 0xFF},
{WSA883X_SWR_RESET_EN, 0x00},
+ {WSA883X_RESET_CTL, 0x00},
{WSA883X_PA_FSM_CTL, 0x00},
{WSA883X_PA_FSM_TIMER0, 0x80},
{WSA883X_PA_FSM_TIMER1, 0x80},
{WSA883X_PA_FSM_STA, 0x00},
{WSA883X_PA_FSM_ERR_COND, 0x00},
{WSA883X_PA_FSM_MSK, 0x00},
- {WSA883X_PA_FSM_BYP, 0x00},
+ {WSA883X_PA_FSM_BYP, 0x01},
+ {WSA883X_PA_FSM_DBG, 0x00},
{WSA883X_TADC_VALUE_CTL, 0x03},
{WSA883X_TEMP_DETECT_CTL, 0x01},
{WSA883X_TEMP_MSB, 0x00},
@@ -193,15 +196,17 @@
{WSA883X_WAVG_PER_2_3, 0x88},
{WSA883X_WAVG_PER_4_5, 0x88},
{WSA883X_WAVG_PER_6_7, 0x88},
- {WSA883X_DRE_CTL_0, 0x30},
- {WSA883X_DRE_CTL_1, 0x20},
+ {WSA883X_WAVG_STA, 0x00},
+ {WSA883X_DRE_CTL_0, 0x70},
+ {WSA883X_DRE_CTL_1, 0x08},
+ {WSA883X_DRE_IDLE_DET_CTL, 0x1F},
{WSA883X_CLSH_CTL_0, 0x37},
{WSA883X_CLSH_CTL_1, 0x81},
{WSA883X_CLSH_V_HD_PA, 0x0F},
{WSA883X_CLSH_V_PA_MIN, 0x00},
{WSA883X_CLSH_OVRD_VAL, 0x00},
{WSA883X_CLSH_HARD_MAX, 0xFF},
- {WSA883X_CLSH_SOFT_MAX, 0xFF},
+ {WSA883X_CLSH_SOFT_MAX, 0xF5},
{WSA883X_CLSH_SIG_DP, 0x00},
{WSA883X_TAGC_CTL, 0x10},
{WSA883X_TAGC_TIME, 0x20},
@@ -212,18 +217,18 @@
{WSA883X_VAGC_ATTN_LVL_1_2, 0x21},
{WSA883X_VAGC_ATTN_LVL_3, 0x03},
{WSA883X_INTR_MODE, 0x00},
- {WSA883X_INTR_MASK0, 0x1B},
- {WSA883X_INTR_MASK1, 0x03},
+ {WSA883X_INTR_MASK0, 0x90},
+ {WSA883X_INTR_MASK1, 0x00},
{WSA883X_INTR_STATUS0, 0x00},
{WSA883X_INTR_STATUS1, 0x00},
{WSA883X_INTR_CLEAR0, 0x00},
- {WSA883X_INTR_CLEAR1, 0x03},
+ {WSA883X_INTR_CLEAR1, 0x00},
{WSA883X_INTR_LEVEL0, 0x00},
- {WSA883X_INTR_LEVEL1, 0x03},
+ {WSA883X_INTR_LEVEL1, 0x00},
{WSA883X_INTR_SET0, 0x00},
- {WSA883X_INTR_SET1, 0x03},
+ {WSA883X_INTR_SET1, 0x00},
{WSA883X_INTR_TEST0, 0x00},
- {WSA883X_INTR_TEST1, 0x03},
+ {WSA883X_INTR_TEST1, 0x00},
{WSA883X_OTP_CTRL0, 0x00},
{WSA883X_OTP_CTRL1, 0x00},
{WSA883X_HDRIVE_CTL_GROUP1, 0x00},
@@ -234,25 +239,27 @@
{WSA883X_I2C_SLAVE_CTL, 0x00},
{WSA883X_PDM_TEST_MODE, 0x00},
{WSA883X_ATE_TEST_MODE, 0x00},
- {WSA883X_DRE_TEST, 0x00},
{WSA883X_DIG_DEBUG_MODE, 0x00},
{WSA883X_DIG_DEBUG_SEL, 0x00},
{WSA883X_DIG_DEBUG_EN, 0x00},
{WSA883X_SWR_HM_TEST0, 0x08},
{WSA883X_SWR_HM_TEST1, 0x00},
- {WSA883X_SWR_PAD_CTL, 0x45},
- {WSA883X_TEMP_DETECT_DBG_CTL, 0x00},
- {WSA883X_TEMP_DEBUG_MSB, 0x00},
- {WSA883X_TEMP_DEBUG_LSB, 0x00},
+ {WSA883X_SWR_PAD_CTL, 0x37},
+ {WSA883X_TADC_DETECT_DBG_CTL, 0x00},
+ {WSA883X_TADC_DEBUG_MSB, 0x00},
+ {WSA883X_TADC_DEBUG_LSB, 0x00},
{WSA883X_SAMPLE_EDGE_SEL, 0x7F},
- {WSA883X_TEST_MODE_CTL, 0x00},
+ {WSA883X_SWR_EDGE_SEL, 0x00},
+ {WSA883X_TEST_MODE_CTL, 0x04},
{WSA883X_IOPAD_CTL, 0x00},
+ {WSA883X_ANA_CSR_DBG_ADD, 0x00},
+ {WSA883X_ANA_CSR_DBG_CTL, 0x12},
+ {WSA883X_SPARE_R, 0x00},
{WSA883X_SPARE_0, 0x00},
{WSA883X_SPARE_1, 0x00},
{WSA883X_SPARE_2, 0x00},
{WSA883X_SCODE, 0x00},
- {WSA883X_PAGE_REGISTER, 0x00},
- {WSA883X_OTP_REG_0, 0x01},
+ {WSA883X_OTP_REG_0, 0x05},
{WSA883X_OTP_REG_1, 0xFF},
{WSA883X_OTP_REG_2, 0xC0},
{WSA883X_OTP_REG_3, 0xFF},
@@ -276,15 +283,18 @@
{WSA883X_OTP_REG_21, 0xFF},
{WSA883X_OTP_REG_22, 0xFF},
{WSA883X_OTP_REG_23, 0xFF},
- {WSA883X_OTP_REG_24, 0x03},
- {WSA883X_OTP_REG_25, 0x01},
+ {WSA883X_OTP_REG_24, 0x37},
+ {WSA883X_OTP_REG_25, 0x3F},
{WSA883X_OTP_REG_26, 0x03},
- {WSA883X_OTP_REG_27, 0x11},
- {WSA883X_OTP_REG_28, 0x3F},
- {WSA883X_OTP_REG_29, 0x3F},
- {WSA883X_OTP_REG_30, 0x01},
- {WSA883X_OTP_REG_31, 0x01},
- {WSA883X_OTP_REG_SCODE, 0x00},
+ {WSA883X_OTP_REG_27, 0x00},
+ {WSA883X_OTP_REG_28, 0x00},
+ {WSA883X_OTP_REG_29, 0x00},
+ {WSA883X_OTP_REG_30, 0x00},
+ {WSA883X_OTP_REG_31, 0x03},
+ {WSA883X_OTP_REG_32, 0x00},
+ {WSA883X_OTP_REG_33, 0xFF},
+ {WSA883X_OTP_REG_34, 0x00},
+ {WSA883X_OTP_REG_35, 0x00},
{WSA883X_OTP_REG_63, 0x40},
{WSA883X_EMEM_0, 0x00},
{WSA883X_EMEM_1, 0x00},
@@ -377,7 +387,7 @@
!(wsa883x_reg_access[WSA883X_REG(reg)] & WR_REG));
}
-struct regmap_config wsa881x_regmap_config = {
+struct regmap_config wsa883x_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
diff --git a/asoc/codecs/wsa883x/wsa883x-tables.c b/asoc/codecs/wsa883x/wsa883x-tables.c
index 16b0a88..c693097 100644
--- a/asoc/codecs/wsa883x/wsa883x-tables.c
+++ b/asoc/codecs/wsa883x/wsa883x-tables.c
@@ -1,13 +1,13 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
*/
#include <linux/regmap.h>
#include <linux/device.h>
#include "wsa883x-registers.h"
-const u8 wsa883x_reg_readable[WSA883X_NUM_REGISTERS] = {
+const u8 wsa883x_reg_access[WSA883X_NUM_REGISTERS] = {
[WSA883X_REG(WSA883X_REF_CTRL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_TEST_CTL_0)] = RD_WR_REG,
[WSA883X_REG(WSA883X_BIAS_0)] = RD_WR_REG,
@@ -57,14 +57,14 @@
[WSA883X_REG(WSA883X_SPKR_DRV_LF_MASK_DCC_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SPKR_DRV_LF_MISC_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SPKR_DRV_LF_REG_GAIN)] = RD_WR_REG,
- [WSA883X_REG(WSA883X_SPKR_DRV_LF_OS_CAL_CTL1)] = RD_WR_REG,
- [WSA883X_REG(WSA883X_SPKR_DRV_LF_OS_CAL_CTL)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_SPKR_DRV_OS_CAL_CTL)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_SPKR_DRV_OS_CAL_CTL1)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SPKR_PWM_CLK_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SPKR_PDRV_HS_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SPKR_PDRV_LS_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SPKR_PWRSTG_DBG)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SPKR_OCP_CTL)] = RD_WR_REG,
- [WSA883X_REG(WSA883X_SPKR_BBM_CTL)] = RD_REG,
+ [WSA883X_REG(WSA883X_SPKR_BBM_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PA_STATUS0)] = RD_REG,
[WSA883X_REG(WSA883X_PA_STATUS1)] = RD_REG,
[WSA883X_REG(WSA883X_PA_STATUS2)] = RD_REG,
@@ -78,30 +78,31 @@
[WSA883X_REG(WSA883X_STABILITY_CTRL2)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PWRSTAGE_CTRL1)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PWRSTAGE_CTRL2)] = RD_WR_REG,
- [WSA883X_REG(WSA883X_UVLO)] = RD_WR_REG,
- [WSA883X_REG(WSA883X_SEQUENCE_CTRL)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_BYPASS_1)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_BYPASS_2)] = RD_WR_REG,
[WSA883X_REG(WSA883X_ZX_CTRL_1)] = RD_WR_REG,
[WSA883X_REG(WSA883X_ZX_CTRL_2)] = RD_WR_REG,
[WSA883X_REG(WSA883X_MISC1)] = RD_WR_REG,
[WSA883X_REG(WSA883X_MISC2)] = RD_WR_REG,
[WSA883X_REG(WSA883X_GMAMP_SUP1)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PWRSTAGE_CTRL3)] = RD_WR_REG,
- [WSA883X_REG(WSA883X_PRSTAGE_CTRL4)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_PWRSTAGE_CTRL4)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_TEST1)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SPARE1)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_SPARE2)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PON_CTL_0)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PON_CLT_1)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PON_CTL_2)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PON_CTL_3)] = RD_WR_REG,
- [WSA883X_REG(WSA883X_PON_CTL_4)] = RD_WR_REG,
[WSA883X_REG(WSA883X_CKWD_CTL_0)] = RD_WR_REG,
[WSA883X_REG(WSA883X_CKWD_CTL_1)] = RD_WR_REG,
[WSA883X_REG(WSA883X_CKWD_CTL_2)] = RD_WR_REG,
[WSA883X_REG(WSA883X_CKSK_CTL_0)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_PADSW_CTL_0)] = RD_WR_REG,
[WSA883X_REG(WSA883X_TEST_0)] = RD_WR_REG,
[WSA883X_REG(WSA883X_TEST_1)] = RD_WR_REG,
[WSA883X_REG(WSA883X_STATUS_0)] = RD_REG,
[WSA883X_REG(WSA883X_STATUS_1)] = RD_REG,
- [WSA883X_REG(WSA883X_PAGE_REGISTER)] = RD_WR_REG,
[WSA883X_REG(WSA883X_CHIP_ID0)] = RD_REG,
[WSA883X_REG(WSA883X_CHIP_ID1)] = RD_REG,
[WSA883X_REG(WSA883X_CHIP_ID2)] = RD_REG,
@@ -112,6 +113,7 @@
[WSA883X_REG(WSA883X_CDC_PATH_MODE)] = RD_WR_REG,
[WSA883X_REG(WSA883X_CDC_CLK_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SWR_RESET_EN)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_RESET_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PA_FSM_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PA_FSM_TIMER0)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PA_FSM_TIMER1)] = RD_WR_REG,
@@ -119,6 +121,7 @@
[WSA883X_REG(WSA883X_PA_FSM_ERR_COND)] = RD_REG,
[WSA883X_REG(WSA883X_PA_FSM_MSK)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PA_FSM_BYP)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_PA_FSM_DBG)] = RD_WR_REG,
[WSA883X_REG(WSA883X_TADC_VALUE_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_TEMP_DETECT_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_TEMP_MSB)] = RD_REG,
@@ -190,8 +193,10 @@
[WSA883X_REG(WSA883X_WAVG_PER_2_3)] = RD_WR_REG,
[WSA883X_REG(WSA883X_WAVG_PER_4_5)] = RD_WR_REG,
[WSA883X_REG(WSA883X_WAVG_PER_6_7)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_WAVG_STA)] = RD_REG,
[WSA883X_REG(WSA883X_DRE_CTL_0)] = RD_WR_REG,
[WSA883X_REG(WSA883X_DRE_CTL_1)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_DRE_IDLE_DET_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_CLSH_CTL_0)] = RD_WR_REG,
[WSA883X_REG(WSA883X_CLSH_CTL_1)] = RD_WR_REG,
[WSA883X_REG(WSA883X_CLSH_V_HD_PA)] = RD_WR_REG,
@@ -231,24 +236,26 @@
[WSA883X_REG(WSA883X_I2C_SLAVE_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_PDM_TEST_MODE)] = RD_WR_REG,
[WSA883X_REG(WSA883X_ATE_TEST_MODE)] = RD_REG,
- [WSA883X_REG(WSA883X_DRE_TEST)] = RD_WR_REG,
[WSA883X_REG(WSA883X_DIG_DEBUG_MODE)] = RD_WR_REG,
[WSA883X_REG(WSA883X_DIG_DEBUG_SEL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_DIG_DEBUG_EN)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SWR_HM_TEST0)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SWR_HM_TEST1)] = RD_REG,
[WSA883X_REG(WSA883X_SWR_PAD_CTL)] = RD_WR_REG,
- [WSA883X_REG(WSA883X_TEMP_DETECT_DBG_CTL)] = RD_WR_REG,
- [WSA883X_REG(WSA883X_TEMP_DEBUG_MSB)] = RD_WR_REG,
- [WSA883X_REG(WSA883X_TEMP_DEBUG_LSB)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_TADC_DETECT_DBG_CTL)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_TADC_DEBUG_MSB)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_TADC_DEBUG_LSB)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SAMPLE_EDGE_SEL)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_SWR_EDGE_SEL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_TEST_MODE_CTL)] = RD_WR_REG,
[WSA883X_REG(WSA883X_IOPAD_CTL)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_ANA_CSR_DBG_ADD)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_ANA_CSR_DBG_CTL)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_SPARE_R)] = RD_REG,
[WSA883X_REG(WSA883X_SPARE_0)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SPARE_1)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SPARE_2)] = RD_WR_REG,
[WSA883X_REG(WSA883X_SCODE)] = RD_WR_REG,
- [WSA883X_REG(WSA883X_PAGE_REGISTER)] = RD_WR_REG,
[WSA883X_REG(WSA883X_OTP_REG_0)] = RD_WR_REG,
[WSA883X_REG(WSA883X_OTP_REG_1)] = RD_WR_REG,
[WSA883X_REG(WSA883X_OTP_REG_2)] = RD_WR_REG,
@@ -280,8 +287,11 @@
[WSA883X_REG(WSA883X_OTP_REG_28)] = RD_WR_REG,
[WSA883X_REG(WSA883X_OTP_REG_29)] = RD_WR_REG,
[WSA883X_REG(WSA883X_OTP_REG_30)] = RD_WR_REG,
- [WSA883X_REG(WSA883X_OTP_REG_31)] = RD_REG,
- [WSA883X_REG(WSA883X_OTP_REG_SCODE)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_OTP_REG_31)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_OTP_REG_32)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_OTP_REG_33)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_OTP_REG_34)] = RD_WR_REG,
+ [WSA883X_REG(WSA883X_OTP_REG_35)] = RD_WR_REG,
[WSA883X_REG(WSA883X_OTP_REG_63)] = RD_WR_REG,
[WSA883X_REG(WSA883X_EMEM_0)] = RD_WR_REG,
[WSA883X_REG(WSA883X_EMEM_1)] = RD_WR_REG,
diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c
index 08f6858..9e25e53 100644
--- a/asoc/codecs/wsa883x/wsa883x.c
+++ b/asoc/codecs/wsa883x/wsa883x.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
#include <linux/regmap.h>
#include <linux/debugfs.h>
#include <soc/soundwire.h>
@@ -25,6 +26,7 @@
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include <asoc/msm-cdc-pinctrl.h>
+#include <asoc/msm-cdc-supply.h>
#include "wsa883x.h"
#include "internal.h"
@@ -34,6 +36,13 @@
#define HIGH_TEMP_THRESHOLD 45
#define TEMP_INVALID 0xFFFF
#define WSA883X_TEMP_RETRY 3
+#define WSA883X_VBAT_TIMER_SEC 2
+
+static int wsa883x_vbat_timer_sec = WSA883X_VBAT_TIMER_SEC;
+module_param(wsa883x_vbat_timer_sec, int, 0664);
+MODULE_PARM_DESC(wsa883x_vbat_timer_sec, "timer for VBAT monitor polling");
+
+#define DRV_NAME "wsa-codec"
enum {
WSA_4OHMS =4,
@@ -51,6 +60,56 @@
u8 dmeas_lsb;
};
+struct wsa_reg_mask_val {
+ u16 reg;
+ u8 mask;
+ u8 val;
+};
+
+static const struct wsa_reg_mask_val reg_init[] = {
+ {WSA883X_PA_FSM_BYP, 0x01, 0x00},
+ {WSA883X_CDC_SPK_DSM_A2_0, 0xFF, 0x0A},
+ {WSA883X_CDC_SPK_DSM_A2_1, 0x0F, 0x08},
+ {WSA883X_CDC_SPK_DSM_A3_0, 0xFF, 0xF3},
+ {WSA883X_CDC_SPK_DSM_A3_1, 0x07, 0x07},
+ {WSA883X_CDC_SPK_DSM_A4_0, 0xFF, 0x79},
+ {WSA883X_CDC_SPK_DSM_A4_1, 0x03, 0x02},
+ {WSA883X_CDC_SPK_DSM_A5_0, 0xFF, 0x0B},
+ {WSA883X_CDC_SPK_DSM_A5_1, 0x03, 0x02},
+ {WSA883X_CDC_SPK_DSM_A6_0, 0xFF, 0x8A},
+ {WSA883X_CDC_SPK_DSM_A7_0, 0xFF, 0x9B},
+ {WSA883X_CDC_SPK_DSM_C_0, 0xFF, 0x68},
+ {WSA883X_CDC_SPK_DSM_C_1, 0xFF, 0x54},
+ {WSA883X_CDC_SPK_DSM_C_2, 0xFF, 0xF2},
+ {WSA883X_CDC_SPK_DSM_C_3, 0x3F, 0x20},
+ {WSA883X_CDC_SPK_DSM_R1, 0xFF, 0x83},
+ {WSA883X_CDC_SPK_DSM_R2, 0xFF, 0x7F},
+ {WSA883X_CDC_SPK_DSM_R3, 0xFF, 0x9D},
+ {WSA883X_CDC_SPK_DSM_R4, 0xFF, 0x82},
+ {WSA883X_CDC_SPK_DSM_R5, 0xFF, 0x8B},
+ {WSA883X_CDC_SPK_DSM_R6, 0xFF, 0x9B},
+ {WSA883X_CDC_SPK_DSM_R7, 0xFF, 0x3F},
+ {WSA883X_DRE_CTL_0, 0xF0, 0x90},
+ {WSA883X_DRE_IDLE_DET_CTL, 0x10, 0x00},
+ {WSA883X_PDM_WD_CTL, 0x01, 0x01},
+ {WSA883X_CURRENT_LIMIT, 0x78, 0x40},
+ {WSA883X_DRE_CTL_0, 0x07, 0x02},
+ {WSA883X_VAGC_TIME, 0x03, 0x02},
+ {WSA883X_VAGC_CTL, 0x01, 0x01},
+ {WSA883X_TAGC_CTL, 0x0E, 0x0A},
+ {WSA883X_TAGC_TIME, 0x0C, 0x0C},
+ {WSA883X_TAGC_E2E_GAIN, 0x1F, 0x02},
+ {WSA883X_TEMP_CONFIG0, 0x07, 0x02},
+ {WSA883X_TEMP_CONFIG1, 0x07, 0x02},
+ {WSA883X_OTP_REG_1, 0xFF, 0x49},
+ {WSA883X_OTP_REG_2, 0xC0, 0x80},
+ {WSA883X_OTP_REG_3, 0xFF, 0xC9},
+ {WSA883X_OTP_REG_4, 0xC0, 0x40},
+ {WSA883X_TAGC_CTL, 0x01, 0x01},
+ {WSA883X_CKWD_CTL_0, 0x60, 0x00},
+ {WSA883X_CKWD_CTL_1, 0x1F, 0x1B},
+};
+
static int wsa883x_get_temperature(struct snd_soc_component *component,
int *temp);
enum {
@@ -59,6 +118,10 @@
};
enum {
+ SPKR_STATUS = 0,
+};
+
+enum {
WSA883X_IRQ_INT_SAF2WAR = 0,
WSA883X_IRQ_INT_WAR2SAF,
WSA883X_IRQ_INT_DISABLE,
@@ -69,6 +132,7 @@
WSA883X_IRQ_INT_INTR_PIN,
WSA883X_IRQ_INT_UVLO,
WSA883X_IRQ_INT_PA_ON_ERR,
+ WSA883X_NUM_IRQS,
};
static const struct regmap_irq wsa883x_irqs[WSA883X_NUM_IRQS] = {
@@ -174,8 +238,13 @@
if (!is_swr_slave_reg_readable(i))
continue;
swr_read(pdev, pdev->dev_num, i, ®_val, 1);
- len = snprintf(tmp_buf, 25, "0x%.3x: 0x%.2x\n", i,
+ len = snprintf(tmp_buf, sizeof(tmp_buf), "0x%.3x: 0x%.2x\n", i,
(reg_val & 0xFF));
+ if (len < 0) {
+ pr_err("%s: fail to fill the buffer\n", __func__);
+ total = -EFAULT;
+ goto copy_err;
+ }
if ((total + len) >= count - 1)
break;
if (copy_to_user((ubuf + total), tmp_buf, len)) {
@@ -334,6 +403,14 @@
};
#endif
+static void wsa883x_regcache_sync(struct wsa883x_priv *wsa883x)
+{
+ mutex_lock(&wsa883x->res_lock);
+ regcache_mark_dirty(wsa883x->regmap);
+ regcache_sync(wsa883x->regmap);
+ mutex_unlock(&wsa883x->res_lock);
+}
+
static irqreturn_t wsa883x_saf2war_handle_irq(int irq, void *data)
{
pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
@@ -535,7 +612,17 @@
return -EINVAL;
}
- len = snprintf(buffer, sizeof(buffer), "WSA883X-SOUNDWIRE_1_0\n");
+ switch (wsa883x->version) {
+ case WSA883X_VERSION_1_0:
+ len = snprintf(buffer, sizeof(buffer), "WSA883X_1_0\n");
+ break;
+ case WSA883X_VERSION_1_1:
+ len = snprintf(buffer, sizeof(buffer), "WSA883X_1_1\n");
+ break;
+ default:
+ len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
+ break;
+ }
return simple_read_from_buffer(buf, count, &pos, buffer, len);
}
@@ -544,6 +631,41 @@
.read = wsa883x_codec_version_read,
};
+static ssize_t wsa883x_variant_read(struct snd_info_entry *entry,
+ void *file_private_data,
+ struct file *file,
+ char __user *buf, size_t count,
+ loff_t pos)
+{
+ struct wsa883x_priv *wsa883x;
+ char buffer[WSA883X_VARIANT_ENTRY_SIZE];
+ int len = 0;
+
+ wsa883x = (struct wsa883x_priv *) entry->private_data;
+ if (!wsa883x) {
+ pr_err("%s: wsa883x priv is null\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (wsa883x->variant) {
+ case WSA8830:
+ len = snprintf(buffer, sizeof(buffer), "WSA8830\n");
+ break;
+ case WSA8835:
+ len = snprintf(buffer, sizeof(buffer), "WSA8835\n");
+ break;
+ default:
+ len = snprintf(buffer, sizeof(buffer), "UNDEFINED\n");
+ break;
+ }
+
+ return simple_read_from_buffer(buf, count, &pos, buffer, len);
+}
+
+static struct snd_info_entry_ops wsa883x_variant_ops = {
+ .read = wsa883x_variant_read,
+};
+
/*
* wsa883x_codec_info_create_codec_entry - creates wsa883x module
* @codec_root: The parent directory
@@ -558,6 +680,7 @@
struct snd_soc_component *component)
{
struct snd_info_entry *version_entry;
+ struct snd_info_entry *variant_entry;
struct wsa883x_priv *wsa883x;
struct snd_soc_card *card;
char name[80];
@@ -566,11 +689,17 @@
return -EINVAL;
wsa883x = snd_soc_component_get_drvdata(component);
+ if (wsa883x->entry) {
+ dev_dbg(wsa883x->dev,
+ "%s:wsa883x module already created\n", __func__);
+ return 0;
+ }
card = component->card;
- snprintf(name, sizeof(name), "%s.%x", "wsa883x",
- (u32)wsa883x->swr_slave->addr);
- wsa883x->entry = snd_info_create_subdir(codec_root->module,
+ snprintf(name, sizeof(name), "%s.%llx", "wsa883x",
+ wsa883x->swr_slave->addr);
+
+ wsa883x->entry = snd_info_create_module_entry(codec_root->module,
(const char *)name,
codec_root);
if (!wsa883x->entry) {
@@ -579,12 +708,19 @@
return -ENOMEM;
}
+ wsa883x->entry->mode = S_IFDIR | 0555;
+ if (snd_info_register(wsa883x->entry) < 0) {
+ snd_info_free_entry(wsa883x->entry);
+ return -ENOMEM;
+ }
+
version_entry = snd_info_create_card_entry(card->snd_card,
"version",
wsa883x->entry);
if (!version_entry) {
dev_dbg(component->dev, "%s: failed to create wsa883x version entry\n",
__func__);
+ snd_info_free_entry(wsa883x->entry);
return -ENOMEM;
}
@@ -595,22 +731,40 @@
if (snd_info_register(version_entry) < 0) {
snd_info_free_entry(version_entry);
+ snd_info_free_entry(wsa883x->entry);
return -ENOMEM;
}
wsa883x->version_entry = version_entry;
+ variant_entry = snd_info_create_card_entry(card->snd_card,
+ "variant",
+ wsa883x->entry);
+ if (!variant_entry) {
+ dev_dbg(component->dev,
+ "%s: failed to create wsa883x variant entry\n",
+ __func__);
+ snd_info_free_entry(version_entry);
+ snd_info_free_entry(wsa883x->entry);
+ return -ENOMEM;
+ }
+
+ variant_entry->private_data = wsa883x;
+ variant_entry->size = WSA883X_VARIANT_ENTRY_SIZE;
+ variant_entry->content = SNDRV_INFO_CONTENT_DATA;
+ variant_entry->c.ops = &wsa883x_variant_ops;
+
+ if (snd_info_register(variant_entry) < 0) {
+ snd_info_free_entry(variant_entry);
+ snd_info_free_entry(version_entry);
+ snd_info_free_entry(wsa883x->entry);
+ return -ENOMEM;
+ }
+ wsa883x->variant_entry = variant_entry;
+
return 0;
}
EXPORT_SYMBOL(wsa883x_codec_info_create_codec_entry);
-static void wsa883x_regcache_sync(struct wsa883x_priv *wsa883x)
-{
- mutex_lock(&wsa883x->res_lock);
- regcache_mark_dirty(wsa883x->regmap);
- regcache_sync(wsa883x->regmap);
- mutex_unlock(&wsa883x->res_lock);
-}
-
static int wsa883x_get_compander(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -774,16 +928,8 @@
&port_type[0]);
break;
case SND_SOC_DAPM_POST_PMU:
- swr_slvdev_datapath_control(wsa883x->swr_slave,
- wsa883x->swr_slave->dev_num,
- true);
break;
case SND_SOC_DAPM_PRE_PMD:
- swr_slvdev_datapath_control(wsa883x->swr_slave,
- wsa883x->swr_slave->dev_num,
- false);
- break;
- case SND_SOC_DAPM_POST_PMD:
wsa883x_set_port(component, SWR_DAC_PORT,
&port_id[num_port], &num_ch[num_port],
&ch_mask[num_port], &ch_rate[num_port],
@@ -807,6 +953,15 @@
swr_disconnect_port(wsa883x->swr_slave, &port_id[0], num_port,
&ch_mask[0], &port_type[0]);
break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (swr_set_device_group(wsa883x->swr_slave, SWR_GROUP_NONE))
+ dev_err(component->dev,
+ "%s: set num ch failed\n", __func__);
+
+ swr_slvdev_datapath_control(wsa883x->swr_slave,
+ wsa883x->swr_slave->dev_num,
+ false);
+ break;
default:
break;
}
@@ -819,21 +974,39 @@
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
- int min_gain, max_gain;
dev_dbg(component->dev, "%s: %s %d\n", __func__, w->name, event);
switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- /* TODO Vote for Global PA */
- break;
-
case SND_SOC_DAPM_POST_PMU:
+ swr_slvdev_datapath_control(wsa883x->swr_slave,
+ wsa883x->swr_slave->dev_num,
+ true);
+ wcd_enable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD);
/* Force remove group */
swr_remove_from_group(wsa883x->swr_slave,
wsa883x->swr_slave->dev_num);
+ snd_soc_component_update_bits(component,
+ WSA883X_VBAT_ADC_FLT_CTL,
+ 0x0E, 0x06);
+ snd_soc_component_update_bits(component,
+ WSA883X_VBAT_ADC_FLT_CTL,
+ 0x01, 0x01);
+ schedule_delayed_work(&wsa883x->vbat_work,
+ msecs_to_jiffies(wsa883x_vbat_timer_sec * 1000));
+ set_bit(SPKR_STATUS, &wsa883x->status_mask);
break;
- case SND_SOC_DAPM_POST_PMD:
- /* TODO Unvote for Global PA */
+ case SND_SOC_DAPM_PRE_PMD:
+ cancel_delayed_work_sync(&wsa883x->vbat_work);
+ snd_soc_component_update_bits(component,
+ WSA883X_VBAT_ADC_FLT_CTL,
+ 0x01, 0x00);
+ snd_soc_component_update_bits(component,
+ WSA883X_VBAT_ADC_FLT_CTL,
+ 0x0E, 0x00);
+ snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL,
+ 0x01, 0x00);
+ wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD);
+ clear_bit(SPKR_STATUS, &wsa883x->status_mask);
break;
}
return 0;
@@ -884,10 +1057,14 @@
static void wsa883x_codec_init(struct snd_soc_component *component)
{
struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+ int i;
if (!wsa883x)
return;
+ for (i = 0; i < ARRAY_SIZE(reg_init); i++)
+ snd_soc_component_update_bits(component, reg_init[i].reg,
+ reg_init[i].mask, reg_init[i].val);
}
static int32_t wsa883x_temp_reg_read(struct snd_soc_component *component,
@@ -929,7 +1106,6 @@
static int wsa883x_get_temperature(struct snd_soc_component *component,
int *temp)
{
- struct snd_soc_component *component;
struct wsa_temp_register reg;
int dmeas, d1, d2;
int ret = 0;
@@ -943,7 +1119,7 @@
return -EINVAL;
do {
- ret = wsa883x_temp_reg_read(component, ®)
+ ret = wsa883x_temp_reg_read(component, ®);
if (ret) {
pr_err("%s: temp read failed: %d, current temp: %d\n",
__func__, ret, wsa883x->curr_temp);
@@ -996,10 +1172,42 @@
return ret;
}
+static void wsa883x_vbat_monitor_work(struct work_struct *work)
+{
+ struct wsa883x_priv *wsa883x;
+ struct delayed_work *dwork;
+ struct snd_soc_component *component;
+ u16 val = 0, vbat_code = 0;
+ int vbat_val = 0;
+
+ dwork = to_delayed_work(work);
+ wsa883x = container_of(dwork, struct wsa883x_priv, vbat_work);
+ component = wsa883x->component;
+
+ val = snd_soc_component_read32(component, WSA883X_VBAT_DIN_MSB);
+ vbat_code = (val << 2);
+ val = (snd_soc_component_read32(component, WSA883X_VBAT_DIN_LSB)
+ & 0xC0);
+ vbat_code |= (val >> 6);
+ vbat_val = ((vbat_code * 5) / 1023);
+ dev_dbg(component->dev, "%s: instant vbat code = %d val = %d\n",
+ __func__, vbat_code, vbat_val);
+
+ val = snd_soc_component_read32(component, WSA883X_VBAT_DOUT);
+ vbat_val = ((val * 5) / 255);
+
+ dev_dbg(component->dev, "%s: low pass vbat code = %d val = %d\n",
+ __func__, val, vbat_val);
+
+ schedule_delayed_work(&wsa883x->vbat_work,
+ msecs_to_jiffies(wsa883x_vbat_timer_sec * 1000));
+}
+
static int wsa883x_codec_probe(struct snd_soc_component *component)
{
struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
struct swr_device *dev;
+ int variant = 0, version = 0;
if (!wsa883x)
return -EINVAL;
@@ -1007,8 +1215,18 @@
dev = wsa883x->swr_slave;
wsa883x->component = component;
+
+ variant = (snd_soc_component_read32(component, WSA883X_OTP_REG_0)
+ & 0x0F);
+ wsa883x->variant = variant;
+
+ version = (snd_soc_component_read32(component, WSA883X_CHIP_ID0)
+ & 0xFF);
+ wsa883x->version = version;
+
wsa883x_codec_init(component);
wsa883x->global_pa_cnt = 0;
+ INIT_DELAYED_WORK(&wsa883x->vbat_work, wsa883x_vbat_monitor_work);
return 0;
}
@@ -1055,6 +1273,45 @@
return ret;
}
+static int wsa883x_swr_up(struct wsa883x_priv *wsa883x)
+{
+ int ret;
+
+ ret = wsa883x_gpio_ctrl(wsa883x, true);
+ if (ret)
+ dev_err(wsa883x->dev, "%s: Failed to enable gpio\n", __func__);
+
+ return ret;
+}
+
+static int wsa883x_swr_down(struct wsa883x_priv *wsa883x)
+{
+ int ret;
+
+ ret = wsa883x_gpio_ctrl(wsa883x, false);
+ if (ret)
+ dev_err(wsa883x->dev, "%s: Failed to disable gpio\n", __func__);
+
+ return ret;
+}
+
+static int wsa883x_swr_reset(struct wsa883x_priv *wsa883x)
+{
+ u8 retry = WSA883X_NUM_RETRY;
+ u8 devnum = 0;
+ struct swr_device *pdev;
+
+ pdev = wsa883x->swr_slave;
+ while (swr_get_logical_dev_num(pdev, pdev->addr, &devnum) && retry--) {
+ /* Retry after 1 msec delay */
+ usleep_range(1000, 1100);
+ }
+ pdev->dev_num = devnum;
+ wsa883x_regcache_sync(wsa883x);
+
+ return 0;
+}
+
static int wsa883x_event_notify(struct notifier_block *nb,
unsigned long val, void *ptr)
{
@@ -1067,23 +1324,70 @@
switch (event) {
case BOLERO_WSA_EVT_PA_OFF_PRE_SSR:
+ if (delayed_work_pending(&wsa883x->vbat_work))
+ cancel_delayed_work_sync(&wsa883x->vbat_work);
snd_soc_component_update_bits(wsa883x->component,
- WSA883X_SPKR_DRV_GAIN,
- 0xF0, 0xC0);
- snd_soc_component_update_bits(wsa883x->component,
- WSA883X_SPKR_DRV_EN,
- 0x80, 0x00);
+ WSA883X_PA_FSM_CTL,
+ 0x01, 0x00);
+ wsa883x_swr_down(wsa883x);
+ break;
+
+ case BOLERO_WSA_EVT_SSR_UP:
+ wsa883x_swr_up(wsa883x);
+ /* Add delay to allow enumerate */
+ usleep_range(20000, 20010);
+ wsa883x_swr_reset(wsa883x);
+ break;
+
+ case BOLERO_WSA_EVT_PA_ON_POST_FSCLK:
+ if (test_bit(SPKR_STATUS, &wsa883x->status_mask))
+ snd_soc_component_update_bits(wsa883x->component,
+ WSA883X_PA_FSM_CTL,
+ 0x01, 0x01);
break;
default:
+ dev_dbg(wsa883x->dev, "%s: unknown event %d\n",
+ __func__, event);
break;
}
return 0;
}
-static int wsa883x_swr_probe(struct swr_device *pdev)
+static int wsa883x_enable_supplies(struct device * dev,
+ struct wsa883x_priv *priv)
{
int ret = 0;
+
+ /* Parse power supplies */
+ msm_cdc_get_power_supplies(dev, &priv->regulator,
+ &priv->num_supplies);
+ if (!priv->regulator || (priv->num_supplies <= 0)) {
+ dev_err(dev, "%s: no power supplies defined\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = msm_cdc_init_supplies(dev, &priv->supplies,
+ priv->regulator, priv->num_supplies);
+ if (!priv->supplies) {
+ dev_err(dev, "%s: Cannot init wsa supplies\n",
+ __func__);
+ return ret;
+ }
+
+ ret = msm_cdc_enable_static_supplies(dev, priv->supplies,
+ priv->regulator,
+ priv->num_supplies);
+ if (ret)
+ dev_err(dev, "%s: wsa static supply enable failed!\n",
+ __func__);
+
+ return ret;
+}
+
+static int wsa883x_swr_probe(struct swr_device *pdev)
+{
+ int ret = 0, i = 0;
struct wsa883x_priv *wsa883x;
u8 devnum = 0;
bool pin_state_current = false;
@@ -1094,6 +1398,10 @@
if (!wsa883x)
return -ENOMEM;
+ ret = wsa883x_enable_supplies(&pdev->dev, wsa883x);
+ if (ret)
+ return -EINVAL;
+
wsa883x->wsa_rst_np = of_parse_phandle(pdev->dev.of_node,
"qcom,spkr-sd-n-node", 0);
if (!wsa883x->wsa_rst_np) {
@@ -1109,10 +1417,10 @@
* soundwire auto enumeration of slave devices as
* as per HW requirement.
*/
- usleep_range(5000, 5010);
+ usleep_range(20000, 20010);
ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum);
if (ret) {
- dev_dbg(&pdev->dev,
+ dev_err(&pdev->dev,
"%s get devnum %d for dev addr %lx failed\n",
__func__, devnum, pdev->addr);
goto dev_err;
@@ -1136,7 +1444,7 @@
wsa883x->irq_info.wcd_regmap_irq_chip = &wsa883x_regmap_irq_chip;
wsa883x->irq_info.codec_name = "WSA883X";
wsa883x->irq_info.regmap = wsa883x->regmap;
- wsa883x->irq_info.dev = dev;
+ wsa883x->irq_info.dev = &pdev->dev;
ret = wcd_irq_init(&wsa883x->irq_info, &wsa883x->virq);
if (ret) {
@@ -1157,15 +1465,23 @@
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_OCP,
"WSA OCP", wsa883x_ocp_handle_irq, NULL);
+ wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_OCP);
+
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLIP,
"WSA CLIP", wsa883x_clip_handle_irq, NULL);
+ wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLIP);
+
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD,
"WSA PDM WD", wsa883x_pdm_wd_handle_irq, NULL);
+ wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD);
+
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLK_WD,
"WSA CLK WD", wsa883x_clk_wd_handle_irq, NULL);
+ wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLK_WD);
+
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_INTR_PIN,
"WSA EXT INT", wsa883x_ext_int_handle_irq, NULL);
@@ -1176,6 +1492,8 @@
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR,
"WSA PA ERR", wsa883x_pa_on_err_handle_irq, NULL);
+ wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR);
+
ret = snd_soc_register_component(&pdev->dev, &soc_codec_dev_wsa883x,
NULL, 0);
if (ret) {
diff --git a/asoc/kona.c b/asoc/kona.c
index a97590f..7560fa9 100644
--- a/asoc/kona.c
+++ b/asoc/kona.c
@@ -31,6 +31,7 @@
#include "asoc/wcd-mbhc-v2.h"
#include "codecs/wcd938x/wcd938x-mbhc.h"
#include "codecs/wsa881x.h"
+#include "codecs/wsa883x/wsa883x.h"
#include "codecs/wcd938x/wcd938x.h"
#include "codecs/bolero/bolero-cdc.h"
#include <dt-bindings/sound/audio-codec-port-types.h>
@@ -3691,6 +3692,46 @@
SOC_ENUM_EXT("USB_AUDIO_TX SampleRate", usb_tx_sample_rate,
usb_audio_tx_sample_rate_get,
usb_audio_tx_sample_rate_put),
+ SOC_ENUM_EXT("USB_AUDIO_RX Format", usb_rx_format,
+ usb_audio_rx_format_get, usb_audio_rx_format_put),
+ SOC_ENUM_EXT("USB_AUDIO_TX Format", usb_tx_format,
+ usb_audio_tx_format_get, usb_audio_tx_format_put),
+ SOC_ENUM_EXT("USB_AUDIO_RX Channels", usb_rx_chs,
+ usb_audio_rx_ch_get, usb_audio_rx_ch_put),
+ SOC_ENUM_EXT("USB_AUDIO_TX Channels", usb_tx_chs,
+ usb_audio_tx_ch_get, usb_audio_tx_ch_put),
+ SOC_ENUM_EXT("PROXY_RX Channels", proxy_rx_chs,
+ proxy_rx_ch_get, proxy_rx_ch_put),
+ SOC_ENUM_EXT("Display Port RX Channels", ext_disp_rx_chs,
+ ext_disp_rx_ch_get, ext_disp_rx_ch_put),
+ SOC_ENUM_EXT("Display Port RX Bit Format", ext_disp_rx_format,
+ ext_disp_rx_format_get, ext_disp_rx_format_put),
+ SOC_ENUM_EXT("Display Port RX SampleRate", ext_disp_rx_sample_rate,
+ ext_disp_rx_sample_rate_get,
+ ext_disp_rx_sample_rate_put),
+ SOC_ENUM_EXT("Display Port1 RX Channels", ext_disp_rx_chs,
+ ext_disp_rx_ch_get, ext_disp_rx_ch_put),
+ SOC_ENUM_EXT("Display Port1 RX Bit Format", ext_disp_rx_format,
+ ext_disp_rx_format_get, ext_disp_rx_format_put),
+ SOC_ENUM_EXT("Display Port1 RX SampleRate", ext_disp_rx_sample_rate,
+ ext_disp_rx_sample_rate_get,
+ ext_disp_rx_sample_rate_put),
+ SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
+ msm_bt_sample_rate_get,
+ msm_bt_sample_rate_put),
+ SOC_ENUM_EXT("BT SampleRate RX", bt_sample_rate_rx,
+ msm_bt_sample_rate_rx_get,
+ msm_bt_sample_rate_rx_put),
+ SOC_ENUM_EXT("BT SampleRate TX", bt_sample_rate_tx,
+ msm_bt_sample_rate_tx_get,
+ msm_bt_sample_rate_tx_put),
+ SOC_ENUM_EXT("AFE_LOOPBACK_TX Channels", afe_loopback_tx_chs,
+ afe_loopback_tx_ch_get, afe_loopback_tx_ch_put),
+ SOC_ENUM_EXT("VI_FEED_TX Channels", vi_feed_tx_chs,
+ msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
+};
+
+static const struct snd_kcontrol_new msm_tdm_snd_controls[] = {
SOC_ENUM_EXT("PRI_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
tdm_rx_sample_rate_get,
tdm_rx_sample_rate_put),
@@ -3727,82 +3768,6 @@
SOC_ENUM_EXT("SEN_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
tdm_tx_sample_rate_get,
tdm_tx_sample_rate_put),
- SOC_ENUM_EXT("PRIM_AUX_PCM_RX SampleRate", prim_aux_pcm_rx_sample_rate,
- aux_pcm_rx_sample_rate_get,
- aux_pcm_rx_sample_rate_put),
- SOC_ENUM_EXT("SEC_AUX_PCM_RX SampleRate", sec_aux_pcm_rx_sample_rate,
- aux_pcm_rx_sample_rate_get,
- aux_pcm_rx_sample_rate_put),
- SOC_ENUM_EXT("TERT_AUX_PCM_RX SampleRate", tert_aux_pcm_rx_sample_rate,
- aux_pcm_rx_sample_rate_get,
- aux_pcm_rx_sample_rate_put),
- SOC_ENUM_EXT("QUAT_AUX_PCM_RX SampleRate", quat_aux_pcm_rx_sample_rate,
- aux_pcm_rx_sample_rate_get,
- aux_pcm_rx_sample_rate_put),
- SOC_ENUM_EXT("QUIN_AUX_PCM_RX SampleRate", quin_aux_pcm_rx_sample_rate,
- aux_pcm_rx_sample_rate_get,
- aux_pcm_rx_sample_rate_put),
- SOC_ENUM_EXT("SEN_AUX_PCM_RX SampleRate", sen_aux_pcm_rx_sample_rate,
- aux_pcm_rx_sample_rate_get,
- aux_pcm_rx_sample_rate_put),
- SOC_ENUM_EXT("PRIM_AUX_PCM_TX SampleRate", prim_aux_pcm_tx_sample_rate,
- aux_pcm_tx_sample_rate_get,
- aux_pcm_tx_sample_rate_put),
- SOC_ENUM_EXT("SEC_AUX_PCM_TX SampleRate", sec_aux_pcm_tx_sample_rate,
- aux_pcm_tx_sample_rate_get,
- aux_pcm_tx_sample_rate_put),
- SOC_ENUM_EXT("TERT_AUX_PCM_TX SampleRate", tert_aux_pcm_tx_sample_rate,
- aux_pcm_tx_sample_rate_get,
- aux_pcm_tx_sample_rate_put),
- SOC_ENUM_EXT("QUAT_AUX_PCM_TX SampleRate", quat_aux_pcm_tx_sample_rate,
- aux_pcm_tx_sample_rate_get,
- aux_pcm_tx_sample_rate_put),
- SOC_ENUM_EXT("QUIN_AUX_PCM_TX SampleRate", quin_aux_pcm_tx_sample_rate,
- aux_pcm_tx_sample_rate_get,
- aux_pcm_tx_sample_rate_put),
- SOC_ENUM_EXT("SEN_AUX_PCM_TX SampleRate", sen_aux_pcm_tx_sample_rate,
- aux_pcm_tx_sample_rate_get,
- aux_pcm_tx_sample_rate_put),
- SOC_ENUM_EXT("PRIM_MI2S_RX SampleRate", prim_mi2s_rx_sample_rate,
- mi2s_rx_sample_rate_get,
- mi2s_rx_sample_rate_put),
- SOC_ENUM_EXT("SEC_MI2S_RX SampleRate", sec_mi2s_rx_sample_rate,
- mi2s_rx_sample_rate_get,
- mi2s_rx_sample_rate_put),
- SOC_ENUM_EXT("TERT_MI2S_RX SampleRate", tert_mi2s_rx_sample_rate,
- mi2s_rx_sample_rate_get,
- mi2s_rx_sample_rate_put),
- SOC_ENUM_EXT("QUAT_MI2S_RX SampleRate", quat_mi2s_rx_sample_rate,
- mi2s_rx_sample_rate_get,
- mi2s_rx_sample_rate_put),
- SOC_ENUM_EXT("QUIN_MI2S_RX SampleRate", quin_mi2s_rx_sample_rate,
- mi2s_rx_sample_rate_get,
- mi2s_rx_sample_rate_put),
- SOC_ENUM_EXT("SEN_MI2S_RX SampleRate", sen_mi2s_rx_sample_rate,
- mi2s_rx_sample_rate_get,
- mi2s_rx_sample_rate_put),
- SOC_ENUM_EXT("PRIM_MI2S_TX SampleRate", prim_mi2s_tx_sample_rate,
- mi2s_tx_sample_rate_get,
- mi2s_tx_sample_rate_put),
- SOC_ENUM_EXT("SEC_MI2S_TX SampleRate", sec_mi2s_tx_sample_rate,
- mi2s_tx_sample_rate_get,
- mi2s_tx_sample_rate_put),
- SOC_ENUM_EXT("TERT_MI2S_TX SampleRate", tert_mi2s_tx_sample_rate,
- mi2s_tx_sample_rate_get,
- mi2s_tx_sample_rate_put),
- SOC_ENUM_EXT("QUAT_MI2S_TX SampleRate", quat_mi2s_tx_sample_rate,
- mi2s_tx_sample_rate_get,
- mi2s_tx_sample_rate_put),
- SOC_ENUM_EXT("QUIN_MI2S_TX SampleRate", quin_mi2s_tx_sample_rate,
- mi2s_tx_sample_rate_get,
- mi2s_tx_sample_rate_put),
- SOC_ENUM_EXT("SEN_MI2S_TX SampleRate", sen_mi2s_tx_sample_rate,
- mi2s_tx_sample_rate_get,
- mi2s_tx_sample_rate_put),
- SOC_ENUM_EXT("USB_AUDIO_RX Format", usb_rx_format,
- usb_audio_rx_format_get, usb_audio_rx_format_put),
- SOC_ENUM_EXT("USB_AUDIO_TX Format", usb_tx_format,
- usb_audio_tx_format_get, usb_audio_tx_format_put),
SOC_ENUM_EXT("PRI_TDM_RX_0 Format", tdm_rx_format,
tdm_rx_format_get,
tdm_rx_format_put),
@@ -3839,60 +3804,6 @@
SOC_ENUM_EXT("SEN_TDM_TX_0 Format", tdm_tx_format,
tdm_tx_format_get,
tdm_tx_format_put),
- SOC_ENUM_EXT("PRIM_AUX_PCM_RX Format", aux_pcm_rx_format,
- msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
- SOC_ENUM_EXT("SEC_AUX_PCM_RX Format", aux_pcm_rx_format,
- msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
- SOC_ENUM_EXT("TERT_AUX_PCM_RX Format", aux_pcm_rx_format,
- msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
- SOC_ENUM_EXT("QUAT_AUX_PCM_RX Format", aux_pcm_rx_format,
- msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
- SOC_ENUM_EXT("QUIN_AUX_PCM_RX Format", aux_pcm_rx_format,
- msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
- SOC_ENUM_EXT("SEN_AUX_PCM_RX Format", aux_pcm_rx_format,
- msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
- SOC_ENUM_EXT("PRIM_AUX_PCM_TX Format", aux_pcm_tx_format,
- msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
- SOC_ENUM_EXT("SEC_AUX_PCM_TX Format", aux_pcm_tx_format,
- msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
- SOC_ENUM_EXT("TERT_AUX_PCM_TX Format", aux_pcm_tx_format,
- msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
- SOC_ENUM_EXT("QUAT_AUX_PCM_TX Format", aux_pcm_tx_format,
- msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
- SOC_ENUM_EXT("QUIN_AUX_PCM_TX Format", aux_pcm_tx_format,
- msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
- SOC_ENUM_EXT("SEN_AUX_PCM_TX Format", aux_pcm_tx_format,
- msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
- SOC_ENUM_EXT("PRIM_MI2S_RX Format", mi2s_rx_format,
- msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
- SOC_ENUM_EXT("SEC_MI2S_RX Format", mi2s_rx_format,
- msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
- SOC_ENUM_EXT("TERT_MI2S_RX Format", mi2s_rx_format,
- msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
- SOC_ENUM_EXT("QUAT_MI2S_RX Format", mi2s_rx_format,
- msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
- SOC_ENUM_EXT("QUIN_MI2S_RX Format", mi2s_rx_format,
- msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
- SOC_ENUM_EXT("SEN_MI2S_RX Format", mi2s_rx_format,
- msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
- SOC_ENUM_EXT("PRIM_MI2S_TX Format", mi2s_tx_format,
- msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
- SOC_ENUM_EXT("SEC_MI2S_TX Format", mi2s_tx_format,
- msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
- SOC_ENUM_EXT("TERT_MI2S_TX Format", mi2s_tx_format,
- msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
- SOC_ENUM_EXT("QUAT_MI2S_TX Format", mi2s_tx_format,
- msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
- SOC_ENUM_EXT("QUIN_MI2S_TX Format", mi2s_tx_format,
- msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
- SOC_ENUM_EXT("SEN_MI2S_TX Format", mi2s_tx_format,
- msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
- SOC_ENUM_EXT("USB_AUDIO_RX Channels", usb_rx_chs,
- usb_audio_rx_ch_get, usb_audio_rx_ch_put),
- SOC_ENUM_EXT("USB_AUDIO_TX Channels", usb_tx_chs,
- usb_audio_tx_ch_get, usb_audio_tx_ch_put),
- SOC_ENUM_EXT("PROXY_RX Channels", proxy_rx_chs,
- proxy_rx_ch_get, proxy_rx_ch_put),
SOC_ENUM_EXT("PRI_TDM_RX_0 Channels", tdm_rx_chs,
tdm_rx_ch_get,
tdm_rx_ch_put),
@@ -3929,6 +3840,134 @@
SOC_ENUM_EXT("SEN_TDM_TX_0 Channels", tdm_tx_chs,
tdm_tx_ch_get,
tdm_tx_ch_put),
+ SOC_SINGLE_MULTI_EXT("TDM Slot Map", SND_SOC_NOPM, 0, 255, 0,
+ TDM_MAX_SLOTS + MAX_PATH, NULL, tdm_slot_map_put),
+};
+
+static const struct snd_kcontrol_new msm_auxpcm_snd_controls[] = {
+ SOC_ENUM_EXT("PRIM_AUX_PCM_RX SampleRate", prim_aux_pcm_rx_sample_rate,
+ aux_pcm_rx_sample_rate_get,
+ aux_pcm_rx_sample_rate_put),
+ SOC_ENUM_EXT("SEC_AUX_PCM_RX SampleRate", sec_aux_pcm_rx_sample_rate,
+ aux_pcm_rx_sample_rate_get,
+ aux_pcm_rx_sample_rate_put),
+ SOC_ENUM_EXT("TERT_AUX_PCM_RX SampleRate", tert_aux_pcm_rx_sample_rate,
+ aux_pcm_rx_sample_rate_get,
+ aux_pcm_rx_sample_rate_put),
+ SOC_ENUM_EXT("QUAT_AUX_PCM_RX SampleRate", quat_aux_pcm_rx_sample_rate,
+ aux_pcm_rx_sample_rate_get,
+ aux_pcm_rx_sample_rate_put),
+ SOC_ENUM_EXT("QUIN_AUX_PCM_RX SampleRate", quin_aux_pcm_rx_sample_rate,
+ aux_pcm_rx_sample_rate_get,
+ aux_pcm_rx_sample_rate_put),
+ SOC_ENUM_EXT("SEN_AUX_PCM_RX SampleRate", sen_aux_pcm_rx_sample_rate,
+ aux_pcm_rx_sample_rate_get,
+ aux_pcm_rx_sample_rate_put),
+ SOC_ENUM_EXT("PRIM_AUX_PCM_TX SampleRate", prim_aux_pcm_tx_sample_rate,
+ aux_pcm_tx_sample_rate_get,
+ aux_pcm_tx_sample_rate_put),
+ SOC_ENUM_EXT("SEC_AUX_PCM_TX SampleRate", sec_aux_pcm_tx_sample_rate,
+ aux_pcm_tx_sample_rate_get,
+ aux_pcm_tx_sample_rate_put),
+ SOC_ENUM_EXT("TERT_AUX_PCM_TX SampleRate", tert_aux_pcm_tx_sample_rate,
+ aux_pcm_tx_sample_rate_get,
+ aux_pcm_tx_sample_rate_put),
+ SOC_ENUM_EXT("QUAT_AUX_PCM_TX SampleRate", quat_aux_pcm_tx_sample_rate,
+ aux_pcm_tx_sample_rate_get,
+ aux_pcm_tx_sample_rate_put),
+ SOC_ENUM_EXT("QUIN_AUX_PCM_TX SampleRate", quin_aux_pcm_tx_sample_rate,
+ aux_pcm_tx_sample_rate_get,
+ aux_pcm_tx_sample_rate_put),
+ SOC_ENUM_EXT("SEN_AUX_PCM_TX SampleRate", sen_aux_pcm_tx_sample_rate,
+ aux_pcm_tx_sample_rate_get,
+ aux_pcm_tx_sample_rate_put),
+ SOC_ENUM_EXT("PRIM_AUX_PCM_RX Format", aux_pcm_rx_format,
+ msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+ SOC_ENUM_EXT("SEC_AUX_PCM_RX Format", aux_pcm_rx_format,
+ msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+ SOC_ENUM_EXT("TERT_AUX_PCM_RX Format", aux_pcm_rx_format,
+ msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+ SOC_ENUM_EXT("QUAT_AUX_PCM_RX Format", aux_pcm_rx_format,
+ msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+ SOC_ENUM_EXT("QUIN_AUX_PCM_RX Format", aux_pcm_rx_format,
+ msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+ SOC_ENUM_EXT("SEN_AUX_PCM_RX Format", aux_pcm_rx_format,
+ msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+ SOC_ENUM_EXT("PRIM_AUX_PCM_TX Format", aux_pcm_tx_format,
+ msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+ SOC_ENUM_EXT("SEC_AUX_PCM_TX Format", aux_pcm_tx_format,
+ msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+ SOC_ENUM_EXT("TERT_AUX_PCM_TX Format", aux_pcm_tx_format,
+ msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+ SOC_ENUM_EXT("QUAT_AUX_PCM_TX Format", aux_pcm_tx_format,
+ msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+ SOC_ENUM_EXT("QUIN_AUX_PCM_TX Format", aux_pcm_tx_format,
+ msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+ SOC_ENUM_EXT("SEN_AUX_PCM_TX Format", aux_pcm_tx_format,
+ msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+};
+
+static const struct snd_kcontrol_new msm_mi2s_snd_controls[] = {
+ SOC_ENUM_EXT("PRIM_MI2S_RX SampleRate", prim_mi2s_rx_sample_rate,
+ mi2s_rx_sample_rate_get,
+ mi2s_rx_sample_rate_put),
+ SOC_ENUM_EXT("SEC_MI2S_RX SampleRate", sec_mi2s_rx_sample_rate,
+ mi2s_rx_sample_rate_get,
+ mi2s_rx_sample_rate_put),
+ SOC_ENUM_EXT("TERT_MI2S_RX SampleRate", tert_mi2s_rx_sample_rate,
+ mi2s_rx_sample_rate_get,
+ mi2s_rx_sample_rate_put),
+ SOC_ENUM_EXT("QUAT_MI2S_RX SampleRate", quat_mi2s_rx_sample_rate,
+ mi2s_rx_sample_rate_get,
+ mi2s_rx_sample_rate_put),
+ SOC_ENUM_EXT("QUIN_MI2S_RX SampleRate", quin_mi2s_rx_sample_rate,
+ mi2s_rx_sample_rate_get,
+ mi2s_rx_sample_rate_put),
+ SOC_ENUM_EXT("SEN_MI2S_RX SampleRate", sen_mi2s_rx_sample_rate,
+ mi2s_rx_sample_rate_get,
+ mi2s_rx_sample_rate_put),
+ SOC_ENUM_EXT("PRIM_MI2S_TX SampleRate", prim_mi2s_tx_sample_rate,
+ mi2s_tx_sample_rate_get,
+ mi2s_tx_sample_rate_put),
+ SOC_ENUM_EXT("SEC_MI2S_TX SampleRate", sec_mi2s_tx_sample_rate,
+ mi2s_tx_sample_rate_get,
+ mi2s_tx_sample_rate_put),
+ SOC_ENUM_EXT("TERT_MI2S_TX SampleRate", tert_mi2s_tx_sample_rate,
+ mi2s_tx_sample_rate_get,
+ mi2s_tx_sample_rate_put),
+ SOC_ENUM_EXT("QUAT_MI2S_TX SampleRate", quat_mi2s_tx_sample_rate,
+ mi2s_tx_sample_rate_get,
+ mi2s_tx_sample_rate_put),
+ SOC_ENUM_EXT("QUIN_MI2S_TX SampleRate", quin_mi2s_tx_sample_rate,
+ mi2s_tx_sample_rate_get,
+ mi2s_tx_sample_rate_put),
+ SOC_ENUM_EXT("SEN_MI2S_TX SampleRate", sen_mi2s_tx_sample_rate,
+ mi2s_tx_sample_rate_get,
+ mi2s_tx_sample_rate_put),
+ SOC_ENUM_EXT("PRIM_MI2S_RX Format", mi2s_rx_format,
+ msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+ SOC_ENUM_EXT("SEC_MI2S_RX Format", mi2s_rx_format,
+ msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+ SOC_ENUM_EXT("TERT_MI2S_RX Format", mi2s_rx_format,
+ msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+ SOC_ENUM_EXT("QUAT_MI2S_RX Format", mi2s_rx_format,
+ msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+ SOC_ENUM_EXT("QUIN_MI2S_RX Format", mi2s_rx_format,
+ msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+ SOC_ENUM_EXT("SEN_MI2S_RX Format", mi2s_rx_format,
+ msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+ SOC_ENUM_EXT("PRIM_MI2S_TX Format", mi2s_tx_format,
+ msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+ SOC_ENUM_EXT("SEC_MI2S_TX Format", mi2s_tx_format,
+ msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+ SOC_ENUM_EXT("TERT_MI2S_TX Format", mi2s_tx_format,
+ msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+ SOC_ENUM_EXT("QUAT_MI2S_TX Format", mi2s_tx_format,
+ msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+ SOC_ENUM_EXT("QUIN_MI2S_TX Format", mi2s_tx_format,
+ msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+ SOC_ENUM_EXT("SEN_MI2S_TX Format", mi2s_tx_format,
+ msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
SOC_ENUM_EXT("PRIM_MI2S_RX Channels", prim_mi2s_rx_chs,
msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
SOC_ENUM_EXT("SEC_MI2S_RX Channels", sec_mi2s_rx_chs,
@@ -3953,35 +3992,6 @@
msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
SOC_ENUM_EXT("SEN_MI2S_TX Channels", sen_mi2s_tx_chs,
msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
- SOC_ENUM_EXT("Display Port RX Channels", ext_disp_rx_chs,
- ext_disp_rx_ch_get, ext_disp_rx_ch_put),
- SOC_ENUM_EXT("Display Port RX Bit Format", ext_disp_rx_format,
- ext_disp_rx_format_get, ext_disp_rx_format_put),
- SOC_ENUM_EXT("Display Port RX SampleRate", ext_disp_rx_sample_rate,
- ext_disp_rx_sample_rate_get,
- ext_disp_rx_sample_rate_put),
- SOC_ENUM_EXT("Display Port1 RX Channels", ext_disp_rx_chs,
- ext_disp_rx_ch_get, ext_disp_rx_ch_put),
- SOC_ENUM_EXT("Display Port1 RX Bit Format", ext_disp_rx_format,
- ext_disp_rx_format_get, ext_disp_rx_format_put),
- SOC_ENUM_EXT("Display Port1 RX SampleRate", ext_disp_rx_sample_rate,
- ext_disp_rx_sample_rate_get,
- ext_disp_rx_sample_rate_put),
- SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
- msm_bt_sample_rate_get,
- msm_bt_sample_rate_put),
- SOC_ENUM_EXT("BT SampleRate RX", bt_sample_rate_rx,
- msm_bt_sample_rate_rx_get,
- msm_bt_sample_rate_rx_put),
- SOC_ENUM_EXT("BT SampleRate TX", bt_sample_rate_tx,
- msm_bt_sample_rate_tx_get,
- msm_bt_sample_rate_tx_put),
- SOC_ENUM_EXT("AFE_LOOPBACK_TX Channels", afe_loopback_tx_chs,
- afe_loopback_tx_ch_get, afe_loopback_tx_ch_put),
- SOC_ENUM_EXT("VI_FEED_TX Channels", vi_feed_tx_chs,
- msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
- SOC_SINGLE_MULTI_EXT("TDM Slot Map", SND_SOC_NOPM, 0, 255, 0,
- TDM_MAX_SLOTS + MAX_PATH, NULL, tdm_slot_map_put),
};
static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -5313,6 +5323,45 @@
tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
}
+#ifndef CONFIG_TDM_DISABLE
+static void msm_add_tdm_snd_controls(struct snd_soc_component *component)
+{
+ snd_soc_add_component_controls(component, msm_tdm_snd_controls,
+ ARRAY_SIZE(msm_tdm_snd_controls));
+}
+#else
+static void msm_add_tdm_snd_controls(struct snd_soc_component *component)
+{
+ return;
+}
+#endif
+
+#ifndef CONFIG_MI2S_DISABLE
+static void msm_add_mi2s_snd_controls(struct snd_soc_component *component)
+{
+ snd_soc_add_component_controls(component, msm_mi2s_snd_controls,
+ ARRAY_SIZE(msm_mi2s_snd_controls));
+}
+#else
+static void msm_add_mi2s_snd_controls(struct snd_soc_component *component)
+{
+ return;
+}
+#endif
+
+#ifndef CONFIG_AUXPCM_DISABLE
+static void msm_add_auxpcm_snd_controls(struct snd_soc_component *component)
+{
+ snd_soc_add_component_controls(component, msm_auxpcm_snd_controls,
+ ARRAY_SIZE(msm_auxpcm_snd_controls));
+}
+#else
+static void msm_add_auxpcm_snd_controls(struct snd_soc_component *component)
+{
+ return;
+}
+#endif
+
static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
int ret = -EINVAL;
@@ -5348,6 +5397,10 @@
return ret;
}
+ msm_add_tdm_snd_controls(component);
+ msm_add_mi2s_snd_controls(component);
+ msm_add_auxpcm_snd_controls(component);
+
snd_soc_dapm_new_controls(dapm, msm_int_dapm_widgets,
ARRAY_SIZE(msm_int_dapm_widgets));
@@ -6244,6 +6297,10 @@
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ignore_suspend = 1,
},
+};
+
+
+static struct snd_soc_dai_link msm_tdm_be_dai_links[] = {
{
.name = LPASS_BE_PRI_TDM_RX_0,
.stream_name = "Primary TDM0 Playback",
@@ -7120,7 +7177,8 @@
ARRAY_SIZE(ext_disp_be_dai_link) +
ARRAY_SIZE(msm_wcn_be_dai_links) +
ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link) +
- ARRAY_SIZE(msm_wcn_btfm_be_dai_links)];
+ ARRAY_SIZE(msm_wcn_btfm_be_dai_links) +
+ ARRAY_SIZE(msm_tdm_be_dai_links)];
static int msm_populate_dai_link_component_of_node(
struct snd_soc_card *card)
@@ -7437,6 +7495,16 @@
ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link);
}
+ rc = of_property_read_u32(dev->of_node, "qcom,tdm-audio-intf",
+ &val);
+ if (!rc && val) {
+ memcpy(msm_kona_dai_links + total_links,
+ msm_tdm_be_dai_links,
+ sizeof(msm_tdm_be_dai_links));
+ total_links +=
+ ARRAY_SIZE(msm_tdm_be_dai_links);
+ }
+
rc = of_property_read_u32(dev->of_node, "qcom,wcn-btfm",
&wcn_btfm_intf);
if (rc) {
@@ -7503,9 +7571,14 @@
if (!strcmp(component->name_prefix, "SpkrLeft")) {
dev_dbg(component->dev, "%s: setting left ch map to codec %s\n",
__func__, component->name);
- wsa881x_set_channel_map(component, &spkleft_ports[0],
- WSA881X_MAX_SWR_PORTS, &ch_mask[0],
- &ch_rate[0], &spkleft_port_types[0]);
+ if (strnstr(component->name, "wsa883x", sizeof(component->name)))
+ wsa883x_set_channel_map(component, &spkleft_ports[0],
+ WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+ &ch_rate[0], &spkleft_port_types[0]);
+ else
+ wsa881x_set_channel_map(component, &spkleft_ports[0],
+ WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+ &ch_rate[0], &spkleft_port_types[0]);
if (dapm->component) {
snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN");
snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR");
@@ -7513,9 +7586,14 @@
} else if (!strcmp(component->name_prefix, "SpkrRight")) {
dev_dbg(component->dev, "%s: setting right ch map to codec %s\n",
__func__, component->name);
- wsa881x_set_channel_map(component, &spkright_ports[0],
- WSA881X_MAX_SWR_PORTS, &ch_mask[0],
- &ch_rate[0], &spkright_port_types[0]);
+ if (strnstr(component->name, "wsa883x", sizeof(component->name)))
+ wsa883x_set_channel_map(component, &spkright_ports[0],
+ WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+ &ch_rate[0], &spkright_port_types[0]);
+ else
+ wsa881x_set_channel_map(component, &spkright_ports[0],
+ WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+ &ch_rate[0], &spkright_port_types[0]);
if (dapm->component) {
snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN");
snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR");
@@ -7538,8 +7616,12 @@
}
pdata->codec_root = entry;
}
- wsa881x_codec_info_create_codec_entry(pdata->codec_root,
- component);
+ if (strnstr(component->name, "wsa883x", sizeof(component->name)))
+ wsa883x_codec_info_create_codec_entry(pdata->codec_root,
+ component);
+ else
+ wsa881x_codec_info_create_codec_entry(pdata->codec_root,
+ component);
err:
return ret;
}
diff --git a/asoc/msm-pcm-loopback-v2.c b/asoc/msm-pcm-loopback-v2.c
index 86e8c81..4c00c72 100644
--- a/asoc/msm-pcm-loopback-v2.c
+++ b/asoc/msm-pcm-loopback-v2.c
@@ -1,5 +1,5 @@
// 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>
@@ -568,11 +568,15 @@
{
int rc = 0;
struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
- struct snd_pcm_substream *substream =
- vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ struct snd_pcm_substream *substream = NULL;
struct msm_pcm_loopback *prtd;
pr_debug("%s\n", __func__);
+ if (!vol) {
+ pr_err("%s: vol is NULL\n", __func__);
+ return -ENODEV;
+ }
+ substream = vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
if ((!substream) || (!substream->runtime)) {
pr_debug("%s substream or runtime not found\n", __func__);
rc = -ENODEV;
diff --git a/asoc/msm-pcm-q6-noirq.c b/asoc/msm-pcm-q6-noirq.c
index 12a1f12..8fb6f7c 100644
--- a/asoc/msm-pcm-q6-noirq.c
+++ b/asoc/msm-pcm-q6-noirq.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/init.h>
@@ -720,13 +720,17 @@
{
struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
struct msm_plat_data *pdata = NULL;
- struct snd_pcm_substream *substream =
- vol->pcm->streams[vol->stream].substream;
+ struct snd_pcm_substream *substream = NULL;
struct snd_soc_pcm_runtime *soc_prtd = NULL;
struct snd_soc_component *component = NULL;
struct msm_audio *prtd;
pr_debug("%s\n", __func__);
+ if (!vol) {
+ pr_err("%s: vol is NULL\n", __func__);
+ return -ENODEV;
+ }
+ substream = vol->pcm->streams[vol->stream].substream;
if (!substream) {
pr_err("%s substream not found\n", __func__);
return -ENODEV;
diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c
index 60e84cb..c22c39b 100644
--- a/asoc/msm-pcm-q6-v2.c
+++ b/asoc/msm-pcm-q6-v2.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
*/
@@ -1514,13 +1514,17 @@
{
struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
struct msm_plat_data *pdata = NULL;
- struct snd_pcm_substream *substream =
- vol->pcm->streams[vol->stream].substream;
+ struct snd_pcm_substream *substream = NULL;
struct snd_soc_pcm_runtime *soc_prtd = NULL;
struct snd_soc_component *component = NULL;
struct msm_audio *prtd;
pr_debug("%s\n", __func__);
+ if (!vol) {
+ pr_err("%s: vol is NULL\n", __func__);
+ return -ENODEV;
+ }
+ substream = vol->pcm->streams[vol->stream].substream;
if (!substream) {
pr_err("%s substream not found\n", __func__);
return -ENODEV;
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 70e2ebf..d4fbe39 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -30222,6 +30222,50 @@
msm_aptx_dec_license_control_put),
};
+static int msm_routing_get_pll_clk_drift(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return 0;
+}
+
+static int msm_routing_put_pll_clk_drift(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u16 port_id = 0;
+ int32_t clk_drift = 0;
+ uint32_t clk_reset = 0;
+ int be_idx, ret = -EINVAL;
+
+ be_idx = ucontrol->value.integer.value[0];
+ clk_drift = ucontrol->value.integer.value[1];
+ clk_reset = ucontrol->value.integer.value[2];
+
+ if (be_idx < 0 && be_idx >= MSM_BACKEND_DAI_MAX) {
+ pr_err("%s: Invalid be id %d\n", __func__, be_idx);
+ return -EINVAL;
+ }
+
+ if (!msm_bedais[be_idx].active && !clk_reset) {
+ pr_err("%s:BE is not active %d, cannot set clock drift\n",
+ __func__, be_idx);
+ return -EINVAL;
+ }
+
+ port_id = msm_bedais[be_idx].port_id;
+ pr_debug("%s: clk drift %d be idx %d clk reset %d port id 0x%x\n",
+ __func__, clk_drift, be_idx, clk_reset, port_id);
+ ret = afe_set_pll_clk_drift(port_id, clk_drift, clk_reset);
+ if (ret < 0)
+ pr_err("%s: failed to set pll clk drift\n", __func__);
+
+ return ret;
+}
+
+static const struct snd_kcontrol_new pll_clk_drift_controls[] = {
+ SOC_SINGLE_MULTI_EXT("PLL config data", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+ 0, 128, msm_routing_get_pll_clk_drift, msm_routing_put_pll_clk_drift),
+};
+
static int msm_routing_put_port_chmap_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -30522,6 +30566,9 @@
port_multi_channel_map_mixer_controls,
ARRAY_SIZE(port_multi_channel_map_mixer_controls));
+ snd_soc_add_component_controls(component, pll_clk_drift_controls,
+ ARRAY_SIZE(pll_clk_drift_controls));
+
return 0;
}
diff --git a/config/bengalauto.conf b/config/bengalauto.conf
index 0478eca..cd614f6 100644
--- a/config/bengalauto.conf
+++ b/config/bengalauto.conf
@@ -27,6 +27,7 @@
CONFIG_VA_MACRO=m
CONFIG_RX_MACRO=m
CONFIG_TX_MACRO=m
+CONFIG_DIGITAL_CDC_RSC_MGR=m
CONFIG_SND_SOC_WCD_IRQ=m
CONFIG_SND_SOC_WCD937X=m
CONFIG_SND_SOC_WCD937X_SLAVE=m
diff --git a/config/bengalautoconf.h b/config/bengalautoconf.h
index 3e72903..83cca08 100644
--- a/config/bengalautoconf.h
+++ b/config/bengalautoconf.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
*/
#define CONFIG_PINCTRL_LPI 1
@@ -31,6 +31,7 @@
#define CONFIG_VA_MACRO 1
#define CONFIG_RX_MACRO 1
#define CONFIG_TX_MACRO 1
+#define CONFIG_DIGITAL_CDC_RSC_MGR 1
#define CONFIG_SND_SOC_WCD_IRQ 1
#define CONFIG_SND_SOC_WCD937X 1
#define CONFIG_SND_SOC_WCD937X_SLAVE 1
diff --git a/config/konaauto.conf b/config/konaauto.conf
index 03e0541..74ca2d4 100644
--- a/config/konaauto.conf
+++ b/config/konaauto.conf
@@ -36,3 +36,4 @@
export CONFIG_SND_SOC_KONA=m
export CONFIG_SND_EVENT=m
export CONFIG_VOICE_MHI=m
+export CONFIG_DIGITAL_CDC_RSC_MGR=m
diff --git a/config/konaautoconf.h b/config/konaautoconf.h
index f932236..e489b41 100644
--- a/config/konaautoconf.h
+++ b/config/konaautoconf.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.
*/
#define CONFIG_PINCTRL_LPI 1
@@ -40,3 +40,4 @@
#define CONFIG_SND_SOC_KONA 1
#define CONFIG_SND_EVENT 1
#define CONFIG_VOICE_MHI 1
+#define CONFIG_DIGITAL_CDC_RSC_MGR 1
diff --git a/config/litoauto.conf b/config/litoauto.conf
index 12bb1df..d0030bb 100644
--- a/config/litoauto.conf
+++ b/config/litoauto.conf
@@ -3,6 +3,7 @@
CONFIG_SND_SOC_WCD9XXX_V2=m
CONFIG_SND_SOC_WCD_MBHC=m
CONFIG_SND_SOC_WSA881X=m
+CONFIG_SND_SOC_WSA883X=m
CONFIG_WCD9XXX_CODEC_CORE_V2=m
CONFIG_MSM_CDC_PINCTRL=m
CONFIG_MSM_QDSP6V2_CODECS=m
@@ -29,6 +30,7 @@
CONFIG_VA_MACRO=m
CONFIG_RX_MACRO=m
CONFIG_TX_MACRO=m
+CONFIG_DIGITAL_CDC_RSC_MGR=m
CONFIG_SND_SOC_WCD_IRQ=m
CONFIG_SND_SOC_WCD938X=m
CONFIG_SND_SOC_WCD938X_SLAVE=m
diff --git a/config/litoautoconf.h b/config/litoautoconf.h
index 0cfdab2..322ac73 100644
--- a/config/litoautoconf.h
+++ b/config/litoautoconf.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
*/
#define CONFIG_PINCTRL_LPI 1
@@ -7,6 +7,7 @@
#define CONFIG_SND_SOC_WCD9XXX_V2 1
#define CONFIG_SND_SOC_WCD_MBHC 1
#define CONFIG_SND_SOC_WSA881X 1
+#define CONFIG_SND_SOC_WSA883X 1
#define CONFIG_WCD9XXX_CODEC_CORE_V2 1
#define CONFIG_MSM_CDC_PINCTRL 1
#define CONFIG_MSM_QDSP6V2_CODECS 1
@@ -33,6 +34,7 @@
#define CONFIG_VA_MACRO 1
#define CONFIG_RX_MACRO 1
#define CONFIG_TX_MACRO 1
+#define CONFIG_DIGITAL_CDC_RSC_MGR 1
#define CONFIG_SND_SOC_WCD_IRQ 1
#define CONFIG_SND_SOC_WCD938X 1
#define CONFIG_SND_SOC_WCD938X_SLAVE 1
diff --git a/dsp/Kbuild b/dsp/Kbuild
index 006de44..43180e7 100644
--- a/dsp/Kbuild
+++ b/dsp/Kbuild
@@ -184,6 +184,10 @@
Q6_OBJS += voice_mhi.o
endif
+ifdef CONFIG_DIGITAL_CDC_RSC_MGR
+ Q6_OBJS += digital-cdc-rsc-mgr.o
+endif
+
LINUX_INC += -Iinclude/linux
INCS += $(COMMON_INC) \
diff --git a/dsp/digital-cdc-rsc-mgr.c b/dsp/digital-cdc-rsc-mgr.c
new file mode 100644
index 0000000..4206523
--- /dev/null
+++ b/dsp/digital-cdc-rsc-mgr.c
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/ratelimit.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
+
+struct mutex hw_vote_lock;
+static bool is_init_done;
+
+/**
+ * digital_cdc_rsc_mgr_hw_vote_enable - Enables hw vote in DSP
+ *
+ * @vote_handle: vote handle for which voting needs to be done
+ *
+ * Returns 0 on success or -EINVAL/error code on failure
+ */
+int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle)
+{
+ int ret = 0;
+
+ if (!is_init_done || vote_handle == NULL) {
+ pr_err_ratelimited("%s: init failed or vote handle NULL\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&hw_vote_lock);
+ ret = clk_prepare_enable(vote_handle);
+ mutex_unlock(&hw_vote_lock);
+
+ pr_debug("%s: return %d\n", __func__, ret);
+ trace_printk("%s: return %d\n", __func__, ret);
+ return ret;
+}
+EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_enable);
+
+/**
+ * digital_cdc_rsc_mgr_hw_vote_disable - Disables hw vote in DSP
+ *
+ * @vote_handle: vote handle for which voting needs to be disabled
+ *
+ */
+void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle)
+{
+ if (!is_init_done || vote_handle == NULL) {
+ pr_err_ratelimited("%s: init failed or vote handle NULL\n",
+ __func__);
+ return;
+ }
+
+ mutex_lock(&hw_vote_lock);
+ clk_disable_unprepare(vote_handle);
+ mutex_unlock(&hw_vote_lock);
+ trace_printk("%s\n", __func__);
+}
+EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_disable);
+
+/**
+ * digital_cdc_rsc_mgr_hw_vote_reset - Resets hw vote count
+ *
+ */
+void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle)
+{
+ int count = 0;
+
+ if (!is_init_done || vote_handle == NULL) {
+ pr_err_ratelimited("%s: init failed or vote handle NULL\n",
+ __func__);
+ return;
+ }
+
+ mutex_lock(&hw_vote_lock);
+ while (__clk_is_enabled(vote_handle)) {
+ clk_disable_unprepare(vote_handle);
+ count++;
+ }
+ pr_debug("%s: Vote count after SSR: %d\n", __func__, count);
+ trace_printk("%s: Vote count after SSR: %d\n", __func__, count);
+
+ while (count--)
+ clk_prepare_enable(vote_handle);
+ mutex_unlock(&hw_vote_lock);
+}
+EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_reset);
+
+void digital_cdc_rsc_mgr_init()
+{
+ mutex_init(&hw_vote_lock);
+ is_init_done = true;
+}
+
+void digital_cdc_rsc_mgr_exit()
+{
+ mutex_destroy(&hw_vote_lock);
+ is_init_done = false;
+}
diff --git a/dsp/q6_init.c b/dsp/q6_init.c
index fb18741..e990f2a 100644
--- a/dsp/q6_init.c
+++ b/dsp/q6_init.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2017, 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2019-2020 The Linux Foundation. All rights reserved.
*/
#include <linux/kernel.h>
@@ -24,11 +24,13 @@
avtimer_init();
msm_mdf_init();
voice_mhi_init();
+ digital_cdc_rsc_mgr_init();
return 0;
}
static void __exit audio_q6_exit(void)
{
+ digital_cdc_rsc_mgr_exit();
msm_mdf_exit();
avtimer_exit();
audio_slimslave_exit();
diff --git a/dsp/q6_init.h b/dsp/q6_init.h
index 4df2e03..77ba743 100644
--- a/dsp/q6_init.h
+++ b/dsp/q6_init.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
*/
#ifndef __Q6_INIT_H__
@@ -80,5 +80,19 @@
return;
}
#endif
+
+#ifdef CONFIG_DIGITAL_CDC_RSC_MGR
+void digital_cdc_rsc_mgr_init(void);
+void digital_cdc_rsc_mgr_exit(void);
+#else
+static inline void digital_cdc_rsc_mgr_init(void)
+{
+}
+
+static inline void digital_cdc_rsc_mgr_exit(void)
+{
+}
+#endif /* CONFIG_DIGITAL_CDC_RSC_MGR */
+
#endif
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index 3b26c0c..2586bd5 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -174,6 +174,43 @@
uint32_t v_vali_flag;
};
+struct afe_clkinfo_per_port {
+ u16 port_id; /* AFE port ID */
+ uint32_t clk_id; /* Clock ID */
+};
+
+struct afe_clkinfo_per_port clkinfo_per_port[] = {
+ { AFE_PORT_ID_PRIMARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
+ { AFE_PORT_ID_SECONDARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT},
+ { AFE_PORT_ID_TERTIARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT},
+ { AFE_PORT_ID_QUATERNARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT},
+ { AFE_PORT_ID_QUINARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT},
+ { AFE_PORT_ID_SENARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT},
+ { AFE_PORT_ID_PRIMARY_PCM_RX, Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT},
+ { AFE_PORT_ID_SECONDARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEC_PCM_IBIT},
+ { AFE_PORT_ID_TERTIARY_PCM_RX, Q6AFE_LPASS_CLK_ID_TER_PCM_IBIT},
+ { AFE_PORT_ID_QUATERNARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUAD_PCM_IBIT},
+ { AFE_PORT_ID_QUINARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUIN_PCM_IBIT},
+ { AFE_PORT_ID_SENARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEN_PCM_IBIT},
+ { AFE_PORT_ID_PRIMARY_TDM_RX, Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT},
+ { AFE_PORT_ID_SECONDARY_TDM_RX, Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT},
+ { AFE_PORT_ID_TERTIARY_TDM_RX, Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT},
+ { AFE_PORT_ID_QUATERNARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT},
+ { AFE_PORT_ID_QUINARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUIN_TDM_IBIT},
+ { AFE_PORT_ID_PRIMARY_SPDIF_RX,
+ AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_OUTPUT_CORE},
+ { AFE_PORT_ID_PRIMARY_SPDIF_TX,
+ AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_INPUT_CORE},
+ { AFE_PORT_ID_SECONDARY_SPDIF_RX,
+ AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_OUTPUT_CORE},
+ { AFE_PORT_ID_SECONDARY_SPDIF_TX,
+ AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_INPUT_CORE},
+ { AFE_PORT_ID_PRIMARY_META_MI2S_RX,
+ Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
+ { AFE_PORT_ID_SECONDARY_META_MI2S_RX,
+ Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
+};
+
static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
static unsigned long afe_configured_cmd;
@@ -7843,6 +7880,156 @@
}
EXPORT_SYMBOL(afe_set_lpass_clock);
+static int afe_get_port_idx(u16 port_id)
+{
+ u16 afe_port = 0;
+ int i = -EINVAL;
+
+ pr_debug("%s: port id 0x%x\n", __func__, port_id);
+
+ if ((port_id >= AFE_PORT_ID_TDM_PORT_RANGE_START) &&
+ (port_id <= AFE_PORT_ID_TDM_PORT_RANGE_END))
+ afe_port = port_id & 0xFFF0;
+ else if ((port_id == AFE_PORT_ID_PRIMARY_SPDIF_RX) ||
+ (port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX) ||
+ (port_id == AFE_PORT_ID_SECONDARY_SPDIF_RX) ||
+ (port_id == AFE_PORT_ID_SECONDARY_SPDIF_TX))
+ afe_port = port_id;
+ else
+ afe_port = port_id & 0xFFFE;
+
+ for (i = 0; i < ARRAY_SIZE(clkinfo_per_port); i++) {
+ if (afe_port == clkinfo_per_port[i].port_id) {
+ pr_debug("%s: idx 0x%x port id 0x%x\n", __func__,
+ i, afe_port);
+ return i;
+ }
+ }
+
+ pr_debug("%s: cannot get idx for port id 0x%x\n", __func__,
+ afe_port);
+
+ return -EINVAL;
+}
+
+static int afe_get_clk_id(u16 port_id)
+{
+ u16 afe_port = 0;
+ uint32_t clk_id = -EINVAL;
+ int idx = 0;
+
+ idx = afe_get_port_idx(port_id);
+ if (idx < 0) {
+ pr_err("%s: cannot get clock id for port id 0x%x\n", __func__,
+ afe_port);
+ return -EINVAL;
+ }
+
+ clk_id = clkinfo_per_port[idx].clk_id;
+ pr_debug("%s: clk id 0x%x port id 0x%x\n", __func__, clk_id,
+ afe_port);
+
+ return clk_id;
+}
+
+/**
+ * afe_set_clk_id - Update clock id for AFE port
+ *
+ * @port_id: AFE port id
+ * @clk_id: CLock ID
+ *
+ * Returns 0 on success, appropriate error code otherwise
+ */
+int afe_set_clk_id(u16 port_id, uint32_t clk_id)
+{
+ u16 afe_port = 0;
+ int idx = 0;
+
+ idx = afe_get_port_idx(port_id);
+ if (idx < 0) {
+ pr_debug("%s: cannot set clock id for port id 0x%x\n", __func__,
+ afe_port);
+ return -EINVAL;
+ }
+
+ clkinfo_per_port[idx].clk_id = clk_id;
+ pr_debug("%s: updated clk id 0x%x port id 0x%x\n", __func__,
+ clkinfo_per_port[idx].clk_id, afe_port);
+
+ return 0;
+}
+EXPORT_SYMBOL(afe_set_clk_id);
+
+/**
+ * afe_set_pll_clk_drift - Set audio interface PLL clock drift
+ *
+ * @port_id: AFE port id
+ * @set_clk_drift: clk drift to adjust PLL
+ * @clk_reset: reset Interface clock to original value
+ *
+ * Returns 0 on success, appropriate error code otherwise
+ */
+int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift,
+ uint32_t clk_reset)
+{
+ struct afe_set_clk_drift clk_drift;
+ struct param_hdr_v3 param_hdr;
+ uint32_t clk_id;
+ int index = 0, ret = 0;
+
+ memset(¶m_hdr, 0, sizeof(param_hdr));
+ memset(&clk_drift, 0, sizeof(clk_drift));
+
+ index = q6audio_get_port_index(port_id);
+ if (index < 0 || index >= AFE_MAX_PORTS) {
+ pr_err("%s: index[%d] invalid!\n", __func__, index);
+ return -EINVAL;
+ }
+
+ ret = afe_q6_interface_prepare();
+ if (ret != 0) {
+ pr_err_ratelimited("%s: Q6 interface prepare failed %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ clk_id = afe_get_clk_id(port_id);
+ if (clk_id < 0) {
+ pr_err("%s: cannot get clk id for port id 0x%x\n",
+ __func__, port_id);
+ return -EINVAL;
+ }
+
+ if (clk_id & 0x01) {
+ pr_err("%s: cannot adjust clock drift for external clock id 0x%x\n",
+ __func__, clk_id);
+ return -EINVAL;
+ }
+
+ clk_drift.clk_drift = set_clk_drift;
+ clk_drift.clk_reset = clk_reset;
+ clk_drift.clk_id = clk_id;
+ pr_debug("%s: clk id = 0x%x clk drift = %d clk reset = %d port id 0x%x\n",
+ __func__, clk_drift.clk_id, clk_drift.clk_drift,
+ clk_drift.clk_reset, port_id);
+
+ mutex_lock(&this_afe.afe_clk_lock);
+ param_hdr.module_id = AFE_MODULE_CLOCK_SET;
+ param_hdr.instance_id = INSTANCE_ID_0;
+ param_hdr.param_id = AFE_PARAM_ID_CLOCK_ADJUST;
+ param_hdr.param_size = sizeof(struct afe_set_clk_drift);
+
+ ret = q6afe_svc_pack_and_set_param_in_band(index, param_hdr,
+ (u8 *) &clk_drift);
+ if (ret < 0)
+ pr_err_ratelimited("%s: AFE PLL clk drift failed with ret %d\n",
+ __func__, ret);
+
+ mutex_unlock(&this_afe.afe_clk_lock);
+ return ret;
+}
+EXPORT_SYMBOL(afe_set_pll_clk_drift);
+
/**
* afe_set_lpass_clk_cfg - Set AFE clk config
*
@@ -7929,6 +8116,10 @@
return -EINVAL;
}
+ ret = afe_set_clk_id(port_id, cfg->clk_id);
+ if (ret < 0)
+ pr_debug("%s: afe_set_clk_id fail %d\n", __func__, ret);
+
ret = afe_set_lpass_clk_cfg(index, cfg);
if (ret)
pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n",
diff --git a/dsp/q6lsm.c b/dsp/q6lsm.c
index 66883ba..a77ffd3 100644
--- a/dsp/q6lsm.c
+++ b/dsp/q6lsm.c
@@ -2393,7 +2393,7 @@
lab_config_hdr.param_id = LSM_PARAM_ID_LAB_CONFIG;
lab_config_hdr.param_size = sizeof(lab_config);
lab_config.minor_version = 1;
- lab_config.wake_up_latency_ms = 250;
+ lab_config.wake_up_latency_ms = 40;
rc = q6lsm_pack_and_set_params(client, &lab_config_hdr,
(uint8_t *) &lab_config,
LSM_SESSION_CMD_SET_PARAMS);
diff --git a/include/asoc/msm-cdc-supply.h b/include/asoc/msm-cdc-supply.h
index c6aacf6..cff1a4a 100644
--- a/include/asoc/msm-cdc-supply.h
+++ b/include/asoc/msm-cdc-supply.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2016, 2018-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016, 2018-2020 The Linux Foundation. All rights reserved.
*/
#ifndef __CODEC_POWER_SUPPLY_H__
@@ -21,6 +21,10 @@
extern int msm_cdc_get_power_supplies(struct device *dev,
struct cdc_regulator **cdc_vreg,
int *total_num_supplies);
+extern bool msm_cdc_is_ondemand_supply(struct device *dev,
+ struct regulator_bulk_data *supplies,
+ struct cdc_regulator *cdc_vreg,
+ int num_supplies, char *supply_name);
extern int msm_cdc_disable_ondemand_supply(struct device *dev,
struct regulator_bulk_data *supplies,
struct cdc_regulator *cdc_vreg,
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index 7d56a4d..5ac7751 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -11766,6 +11766,35 @@
#define AFE_MODULE_CLOCK_SET 0x0001028F
#define AFE_PARAM_ID_CLOCK_SET 0x00010290
+struct afe_set_clk_drift {
+ /*
+ * Clock ID
+ * @values
+ * - 0x100 to 0x10E
+ * - 0x200 to 0x20C
+ * - 0x500 to 0x505
+ */
+ uint32_t clk_id;
+
+ /*
+ * Clock drift (in PPB) to be set.
+ * @values
+ * - need to get values from DSP team
+ */
+ int32_t clk_drift;
+
+ /*
+ * Clock rest.
+ * @values
+ * - 1 -- Reset PLL with the original frequency
+ * - 0 -- Adjust the clock with the clk drift value
+ */
+ uint32_t clk_reset;
+} __packed;
+
+/* This param id is used to adjust audio interface PLL*/
+#define AFE_PARAM_ID_CLOCK_ADJUST 0x000102C6
+
enum afe_lpass_digital_clk_src {
Q6AFE_LPASS_DIGITAL_ROOT_INVALID,
Q6AFE_LPASS_DIGITAL_ROOT_PRI_MI2S_OSR,
diff --git a/include/dsp/digital-cdc-rsc-mgr.h b/include/dsp/digital-cdc-rsc-mgr.h
new file mode 100644
index 0000000..685cd5c
--- /dev/null
+++ b/include/dsp/digital-cdc-rsc-mgr.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef DIGITAL_CDC_RSC_MGR_H
+#define DIGITAL_CDC_RSC_MGR_H
+
+#ifdef CONFIG_DIGITAL_CDC_RSC_MGR
+
+int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle);
+void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle);
+void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle);
+
+#else
+
+static inline int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle)
+{
+ return 0;
+}
+
+static inline void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle)
+{
+}
+
+static inline void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle)
+{
+}
+
+#endif /* CONFIG_DIGITAL_CDC_RSC_MGR */
+
+#endif /* DIGITAL_CDC_RSC_MGR_H */
diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h
index 76617a9..3ff3028 100644
--- a/include/dsp/q6afe-v2.h
+++ b/include/dsp/q6afe-v2.h
@@ -487,6 +487,9 @@
void (*afe_cb_wakeup_irq)(void *handle));
int afe_get_doa_tracking_mon(u16 port_id,
struct doa_tracking_mon_param *doa_tracking_data);
+int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift,
+ uint32_t clk_reset);
+int afe_set_clk_id(u16 port_id, uint32_t clk_id);
enum {
AFE_LPASS_CORE_HW_BLOCK_ID_NONE,
diff --git a/include/uapi/linux/msm_audio_calibration.h b/include/uapi/linux/msm_audio_calibration.h
index 35b5960..e8ba1b3 100644
--- a/include/uapi/linux/msm_audio_calibration.h
+++ b/include/uapi/linux/msm_audio_calibration.h
@@ -104,6 +104,7 @@
ADM_LSM_TOPOLOGY_CAL_TYPE,
ADM_LSM_AUDPROC_CAL_TYPE,
ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE,
+ ADM_AUDPROC_PERSISTENT_CAL_TYPE,
MAX_CAL_TYPES,
};
@@ -117,6 +118,7 @@
#define ADM_LSM_TOPOLOGY_CAL_TYPE ADM_LSM_TOPOLOGY_CAL_TYPE
#define ADM_LSM_AUDPROC_CAL_TYPE ADM_LSM_AUDPROC_CAL_TYPE
#define ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE
+#define ADM_AUDPROC_PERSISTENT_CAL_TYPE ADM_AUDPROC_PERSISTENT_CAL_TYPE
#define LSM_CAL_TYPES
#define TOPOLOGY_SPECIFIC_CHANNEL_INFO
diff --git a/soc/pinctrl-lpi.c b/soc/pinctrl-lpi.c
index c3d2326..0b0eef5 100644
--- a/soc/pinctrl-lpi.c
+++ b/soc/pinctrl-lpi.c
@@ -16,6 +16,7 @@
#include <linux/clk.h>
#include <linux/bitops.h>
#include <soc/snd_event.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
#include <linux/pm_runtime.h>
#include <dsp/audio_notifier.h>
@@ -469,6 +470,7 @@
unsigned long opcode, void *ptr)
{
static bool initial_boot = true;
+ struct lpi_gpio_state *state = dev_get_drvdata(lpi_dev);
pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode);
@@ -484,6 +486,17 @@
case AUDIO_NOTIFIER_SERVICE_UP:
if (initial_boot)
initial_boot = false;
+
+ /* Reset HW votes after SSR */
+ if (!lpi_dev_up) {
+ if (state->lpass_core_hw_vote)
+ digital_cdc_rsc_mgr_hw_vote_reset(
+ state->lpass_core_hw_vote);
+ if (state->lpass_audio_hw_vote)
+ digital_cdc_rsc_mgr_hw_vote_reset(
+ state->lpass_audio_hw_vote);
+ }
+
lpi_dev_up = true;
snd_event_notify(lpi_dev, SND_EVENT_UP);
break;
@@ -870,7 +883,7 @@
}
mutex_lock(&state->core_hw_vote_lock);
- ret = clk_prepare_enable(hw_vote);
+ ret = digital_cdc_rsc_mgr_hw_vote_enable(hw_vote);
if (ret < 0) {
pm_runtime_set_autosuspend_delay(dev,
LPI_AUTO_SUSPEND_DELAY_ERROR);
@@ -906,7 +919,7 @@
mutex_lock(&state->core_hw_vote_lock);
if (state->core_hw_vote_status) {
- clk_disable_unprepare(hw_vote);
+ digital_cdc_rsc_mgr_hw_vote_disable(hw_vote);
state->core_hw_vote_status = false;
}
mutex_unlock(&state->core_hw_vote_lock);
diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c
index 4aa5c0c..6358437 100644
--- a/soc/swr-mstr-ctrl.c
+++ b/soc/swr-mstr-ctrl.c
@@ -22,6 +22,7 @@
#include <soc/swr-common.h>
#include <linux/regmap.h>
#include <dsp/msm-audio-event-notify.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
#include "swrm_registers.h"
#include "swr-mstr-ctrl.h"
@@ -378,8 +379,8 @@
}
if (++swrm->hw_core_clk_en == 1) {
ret =
- clk_prepare_enable(
- swrm->lpass_core_hw_vote);
+ digital_cdc_rsc_mgr_hw_vote_enable(
+ swrm->lpass_core_hw_vote);
if (ret < 0) {
dev_err(swrm->dev,
"%s:lpass core hw enable failed\n",
@@ -392,8 +393,8 @@
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);
+ digital_cdc_rsc_mgr_hw_vote_disable(
+ swrm->lpass_core_hw_vote);
}
}
}
@@ -410,8 +411,8 @@
}
if (++swrm->aud_core_clk_en == 1) {
ret =
- clk_prepare_enable(
- swrm->lpass_core_audio);
+ digital_cdc_rsc_mgr_hw_vote_enable(
+ swrm->lpass_core_audio);
if (ret < 0) {
dev_err(swrm->dev,
"%s:lpass audio hw enable failed\n",
@@ -424,8 +425,8 @@
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);
+ digital_cdc_rsc_mgr_hw_vote_disable(
+ swrm->lpass_core_audio);
}
}
}
@@ -615,10 +616,10 @@
for (i = 0; i < length; i++) {
/* wait for FIFO WR command to complete to avoid overflow */
/*
- * Reduce sleep from 100us to 10us to meet KPIs
+ * Reduce sleep from 100us to 50us to meet KPIs
* This still meets the hardware spec
*/
- usleep_range(10, 12);
+ usleep_range(50, 55);
swr_master_write(swrm, reg_addr[i], val[i]);
}
mutex_unlock(&swrm->iolock);
@@ -1340,9 +1341,9 @@
dev_dbg(swrm->dev, "%s: enter bank: %d master_ports: %d\n",
__func__, bank, master->num_port);
-
- swrm_cmd_fifo_wr_cmd(swrm, 0x01, 0xF, 0x00,
- SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(bank));
+ if (!swrm->disable_div2_clk_switch)
+ swrm_cmd_fifo_wr_cmd(swrm, 0x01, 0xF, 0x00,
+ SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(bank));
swrm_copy_data_port_config(master, bank);
}
@@ -1908,7 +1909,6 @@
return IRQ_NONE;
}
- mutex_lock(&swrm->ssr_lock);
mutex_lock(&swrm->reslock);
if (swrm_request_hw_vote(swrm, LPASS_HW_CORE, true)) {
ret = IRQ_NONE;
@@ -2025,6 +2025,11 @@
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",
@@ -2122,7 +2127,6 @@
swrm_request_hw_vote(swrm, LPASS_HW_CORE, false);
exit:
mutex_unlock(&swrm->reslock);
- mutex_unlock(&swrm->ssr_lock);
swrm_unlock_sleep(swrm);
trace_printk("%s exit\n", __func__);
return ret;
@@ -2644,6 +2648,7 @@
swrm->state = SWR_MSTR_UP;
swrm->ipc_wakeup = false;
swrm->ipc_wakeup_triggered = false;
+ swrm->disable_div2_clk_switch = FALSE;
init_completion(&swrm->reset);
init_completion(&swrm->broadcast);
init_completion(&swrm->clk_off_complete);
@@ -2655,7 +2660,6 @@
mutex_init(&swrm->clklock);
mutex_init(&swrm->devlock);
mutex_init(&swrm->pm_lock);
- mutex_init(&swrm->ssr_lock);
swrm->wlock_holders = 0;
swrm->pm_state = SWRM_PM_SLEEPABLE;
init_waitqueue_head(&swrm->pm_wq);
@@ -2666,6 +2670,12 @@
for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++)
INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list);
+ if (of_property_read_u32(pdev->dev.of_node,
+ "qcom,disable-div2-clk-switch",
+ &swrm->disable_div2_clk_switch)) {
+ swrm->disable_div2_clk_switch = FALSE;
+ }
+
/* Register LPASS core hw vote */
lpass_core_hw_vote = devm_clk_get(&pdev->dev, "lpass_core_hw_vote");
if (IS_ERR(lpass_core_hw_vote)) {
@@ -2804,7 +2814,6 @@
mutex_destroy(&swrm->iolock);
mutex_destroy(&swrm->clklock);
mutex_destroy(&swrm->pm_lock);
- mutex_destroy(&swrm->ssr_lock);
pm_qos_remove_request(&swrm->pm_qos_req);
err_pdata_fail:
@@ -2838,7 +2847,6 @@
mutex_destroy(&swrm->clklock);
mutex_destroy(&swrm->force_down_lock);
mutex_destroy(&swrm->pm_lock);
- mutex_destroy(&swrm->ssr_lock);
pm_qos_remove_request(&swrm->pm_qos_req);
devm_kfree(&pdev->dev, swrm);
return 0;
@@ -3325,7 +3333,6 @@
break;
case SWR_DEVICE_SSR_DOWN:
trace_printk("%s: swr device down called\n", __func__);
- mutex_lock(&swrm->ssr_lock);
mutex_lock(&swrm->mlock);
if (swrm->state == SWR_MSTR_DOWN)
dev_dbg(swrm->dev, "%s:SWR master is already Down:%d\n",
@@ -3334,12 +3341,13 @@
swrm_device_down(&pdev->dev);
mutex_lock(&swrm->devlock);
swrm->dev_up = false;
+ swrm->hw_core_clk_en = 0;
+ swrm->aud_core_clk_en = 0;
mutex_unlock(&swrm->devlock);
mutex_lock(&swrm->reslock);
swrm->state = SWR_MSTR_SSR;
mutex_unlock(&swrm->reslock);
mutex_unlock(&swrm->mlock);
- mutex_unlock(&swrm->ssr_lock);
break;
case SWR_DEVICE_SSR_UP:
/* wait for clk voting to be zero */
diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h
index 0fac80e..ec5bbd2 100644
--- a/soc/swr-mstr-ctrl.h
+++ b/soc/swr-mstr-ctrl.h
@@ -126,7 +126,6 @@
struct mutex reslock;
struct mutex pm_lock;
struct mutex irq_lock;
- struct mutex ssr_lock;
u32 swrm_base_reg;
char __iomem *swrm_dig_base;
char __iomem *swrm_hctl_reg;
@@ -181,6 +180,7 @@
int hw_core_clk_en;
int aud_core_clk_en;
int clk_src;
+ u32 disable_div2_clk_switch;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_swrm_dent;
struct dentry *debugfs_peek;