summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilson Sung <wilsonsung@google.com>2021-03-19 17:27:07 +0800
committerWilson Sung <wilsonsung@google.com>2021-03-19 17:31:38 +0800
commite4ec5db336f06b9cd8d94a9e3af527b60dfa3973 (patch)
tree59714d26952a06278a16bd10e1d033b276264584
parent935f0b18ffed97fed2aa4de0a1ccb3152ad7c317 (diff)
parent8b44f642a7e2cd83939cc27cfc3c067abedfbde0 (diff)
downloadmsm-extra-e4ec5db336f06b9cd8d94a9e3af527b60dfa3973.tar.gz
Merge branch LA.UM.9.12.R1.11.00.00.597.108 into qcom-msm-4.19-7250-audio-drivers.lnx.4.0.r3
Change-Id: I0cef4ccfb5e280c4c21009fa9d1ea7f2ad7d2637
-rw-r--r--asoc/codecs/bolero/tx-macro.c16
-rw-r--r--asoc/codecs/bolero/va-macro.c20
-rw-r--r--asoc/codecs/bolero/wsa-macro.c14
-rw-r--r--asoc/codecs/wsa881x.c227
-rw-r--r--asoc/codecs/wsa883x/wsa883x.c80
-rw-r--r--asoc/codecs/wsa883x/wsa883x.h5
-rw-r--r--asoc/kona.c264
-rw-r--r--asoc/msm-pcm-q6-v2.c11
-rw-r--r--asoc/msm-pcm-routing-v2.c21
-rw-r--r--dsp/audio_cal_utils.c25
-rw-r--r--dsp/audio_calibration.c3
-rw-r--r--dsp/msm_audio_ion.c11
-rw-r--r--dsp/msm_audio_ion_vm.c10
-rw-r--r--dsp/q6afe.c230
-rw-r--r--dsp/q6asm.c6
-rw-r--r--dsp/q6lsm.c8
-rw-r--r--include/dsp/apr_audio-v2.h26
-rw-r--r--include/dsp/audio_cal_utils.h4
-rw-r--r--include/dsp/q6afe-v2.h4
-rw-r--r--soc/swr-mstr-ctrl.c34
-rw-r--r--soc/swr-mstr-ctrl.h4
21 files changed, 825 insertions, 198 deletions
diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index 158f3500..de04e1e9 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -234,11 +234,11 @@ static int tx_macro_mclk_enable(struct tx_macro_priv *tx_priv,
}
bolero_clk_rsc_fs_gen_request(tx_priv->dev,
true);
+ regcache_mark_dirty(regmap);
+ regcache_sync_region(regmap,
+ TX_START_OFFSET,
+ TX_MAX_OFFSET);
if (tx_priv->tx_mclk_users == 0) {
- regcache_mark_dirty(regmap);
- regcache_sync_region(regmap,
- TX_START_OFFSET,
- TX_MAX_OFFSET);
/* 9.6MHz MCLK, set value 0x00 if other frequency */
regmap_update_bits(regmap,
BOLERO_CDC_TX_TOP_CSR_FREQ_MCLK, 0x01, 0x01);
@@ -2445,11 +2445,7 @@ static int tx_macro_register_event_listener(struct snd_soc_component *component,
ret = swrm_wcd_notify(
tx_priv->swr_ctrl_data[0].tx_swr_pdev,
SWR_REGISTER_WAKEUP, NULL);
- msm_cdc_pinctrl_set_wakeup_capable(
- tx_priv->tx_swr_gpio_p, false);
} else {
- msm_cdc_pinctrl_set_wakeup_capable(
- tx_priv->tx_swr_gpio_p, true);
ret = swrm_wcd_notify(
tx_priv->swr_ctrl_data[0].tx_swr_pdev,
SWR_DEREGISTER_WAKEUP, NULL);
@@ -2484,6 +2480,8 @@ static int tx_macro_tx_va_mclk_enable(struct tx_macro_priv *tx_priv,
__func__);
goto exit;
}
+ msm_cdc_pinctrl_set_wakeup_capable(
+ tx_priv->tx_swr_gpio_p, false);
}
clk_tx_ret = bolero_clk_rsc_request_clock(tx_priv->dev,
@@ -2612,6 +2610,8 @@ tx_clk:
TX_CORE_CLK,
false);
if (tx_priv->swr_clk_users == 0) {
+ msm_cdc_pinctrl_set_wakeup_capable(
+ tx_priv->tx_swr_gpio_p, true);
ret = msm_cdc_pinctrl_select_sleep_state(
tx_priv->tx_swr_gpio_p);
if (ret < 0) {
diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c
index 5ce2ec12..2e369952 100644
--- a/asoc/codecs/bolero/va-macro.c
+++ b/asoc/codecs/bolero/va-macro.c
@@ -388,9 +388,6 @@ static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n",
__func__, event, va_priv->lpi_enable);
- if (!va_priv->lpi_enable)
- return ret;
-
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (va_priv->swr_ctrl_data) {
@@ -402,12 +399,8 @@ static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
dev_dbg(va_dev, "%s: clock switch failed\n",
__func__);
}
- msm_cdc_pinctrl_set_wakeup_capable(
- va_priv->va_swr_gpio_p, false);
break;
case SND_SOC_DAPM_POST_PMD:
- msm_cdc_pinctrl_set_wakeup_capable(
- va_priv->va_swr_gpio_p, true);
if (va_priv->swr_ctrl_data) {
clk_src = CLK_SRC_TX_RCG;
ret = swrm_wcd_notify(
@@ -441,9 +434,6 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w,
dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n",
__func__, event, va_priv->lpi_enable);
- if (!va_priv->lpi_enable)
- return ret;
-
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (va_priv->lpass_audio_hw_vote) {
@@ -563,9 +553,12 @@ static int va_macro_tx_va_mclk_enable(struct va_macro_priv *va_priv,
(enable ? "enable" : "disable"), va_priv->va_mclk_users);
if (enable) {
- if (va_priv->swr_clk_users == 0)
+ if (va_priv->swr_clk_users == 0) {
msm_cdc_pinctrl_select_active_state(
va_priv->va_swr_gpio_p);
+ msm_cdc_pinctrl_set_wakeup_capable(
+ va_priv->va_swr_gpio_p, false);
+ }
clk_tx_ret = bolero_clk_rsc_request_clock(va_priv->dev,
TX_CORE_CLK,
TX_CORE_CLK,
@@ -658,9 +651,12 @@ static int va_macro_tx_va_mclk_enable(struct va_macro_priv *va_priv,
TX_CORE_CLK,
TX_CORE_CLK,
false);
- if (va_priv->swr_clk_users == 0)
+ if (va_priv->swr_clk_users == 0) {
+ msm_cdc_pinctrl_set_wakeup_capable(
+ va_priv->va_swr_gpio_p, true);
msm_cdc_pinctrl_select_sleep_state(
va_priv->va_swr_gpio_p);
+ }
}
return 0;
diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c
index ca7391d0..5ace96db 100644
--- a/asoc/codecs/bolero/wsa-macro.c
+++ b/asoc/codecs/bolero/wsa-macro.c
@@ -445,8 +445,8 @@ static struct snd_soc_dai_driver wsa_macro_dai[] = {
static const struct wsa_macro_reg_mask_val wsa_macro_spkr_default[] = {
{BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80},
{BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80},
- {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01},
- {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01},
+ {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x1F, 0x19},
+ {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x1F, 0x19},
{BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x58},
{BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x58},
};
@@ -454,8 +454,8 @@ static const struct wsa_macro_reg_mask_val wsa_macro_spkr_default[] = {
static const struct wsa_macro_reg_mask_val wsa_macro_spkr_mode1[] = {
{BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x00},
{BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x00},
- {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x00},
- {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x00},
+ {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x1F, 0x18},
+ {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x1F, 0x18},
{BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x7C, 0x44},
{BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x7C, 0x44},
};
@@ -2744,10 +2744,10 @@ static const struct snd_soc_dapm_route wsa_audio_map[] = {
static const struct wsa_macro_reg_mask_val wsa_macro_reg_init[] = {
{BOLERO_CDC_WSA_BOOST0_BOOST_CFG1, 0x3F, 0x12},
{BOLERO_CDC_WSA_BOOST0_BOOST_CFG2, 0x1C, 0x08},
- {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x1E, 0x18},
+ {BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x1E, 0x0C},
{BOLERO_CDC_WSA_BOOST1_BOOST_CFG1, 0x3F, 0x12},
{BOLERO_CDC_WSA_BOOST1_BOOST_CFG2, 0x1C, 0x08},
- {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x1E, 0x18},
+ {BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x1E, 0x0C},
{BOLERO_CDC_WSA_BOOST0_BOOST_CTL, 0x70, 0x58},
{BOLERO_CDC_WSA_BOOST1_BOOST_CTL, 0x70, 0x58},
{BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08},
@@ -2758,8 +2758,6 @@ static const struct wsa_macro_reg_mask_val wsa_macro_reg_init[] = {
{BOLERO_CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
{BOLERO_CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
{BOLERO_CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
- {BOLERO_CDC_WSA_COMPANDER0_CTL3, 0x80, 0x80},
- {BOLERO_CDC_WSA_COMPANDER1_CTL3, 0x80, 0x80},
{BOLERO_CDC_WSA_COMPANDER0_CTL7, 0x01, 0x01},
{BOLERO_CDC_WSA_COMPANDER1_CTL7, 0x01, 0x01},
{BOLERO_CDC_WSA_RX0_RX_PATH_CFG0, 0x01, 0x01},
diff --git a/asoc/codecs/wsa881x.c b/asoc/codecs/wsa881x.c
index b23bc01f..52f29d88 100644
--- a/asoc/codecs/wsa881x.c
+++ b/asoc/codecs/wsa881x.c
@@ -109,6 +109,11 @@ struct wsa881x_priv {
int (*register_notifier)(void *handle,
struct notifier_block *nblock,
bool enable);
+ struct dentry *debugfs_dent;
+ struct dentry *debugfs_peek;
+ struct dentry *debugfs_poke;
+ struct dentry *debugfs_reg_dump;
+ unsigned int read_data;
};
/* from bolero to WSA events */
@@ -146,14 +151,6 @@ static int wsa881x_ocp_poll_timer_sec = WSA881X_OCP_CTL_POLL_TIMER_SEC;
module_param(wsa881x_ocp_poll_timer_sec, int, 0664);
MODULE_PARM_DESC(wsa881x_ocp_poll_timer_sec, "timer for ocp ctl polling");
-static struct wsa881x_priv *dbgwsa881x;
-static struct dentry *debugfs_wsa881x_dent;
-static struct dentry *debugfs_peek;
-static struct dentry *debugfs_poke;
-static struct dentry *debugfs_reg_dump;
-static unsigned int read_data;
-static unsigned int devnum;
-
static int32_t wsa881x_resource_acquire(struct snd_soc_component *component,
bool enable);
@@ -401,30 +398,28 @@ static bool is_swr_slv_reg_readable(int reg)
return ret;
}
-static ssize_t wsa881x_swrslave_reg_show(char __user *ubuf, size_t count,
- loff_t *ppos)
+static ssize_t wsa881x_swrslave_reg_show(struct swr_device *pdev, char __user *ubuf,
+ size_t count, loff_t *ppos)
{
int i, reg_val, len;
ssize_t total = 0;
char tmp_buf[SWR_SLV_MAX_BUF_LEN];
- if (!ubuf || !ppos || (devnum == 0))
+ if (!ubuf || !ppos)
return 0;
for (i = (((int) *ppos / BYTES_PER_LINE) + SWR_SLV_START_REG_ADDR);
- i <= SWR_SLV_MAX_REG_ADDR; i++) {
+ i <= SWR_SLV_MAX_REG_ADDR; i++) {
if (!is_swr_slv_reg_readable(i))
continue;
- swr_read(dbgwsa881x->swr_slave, devnum,
- i, &reg_val, 1);
- len = snprintf(tmp_buf, 25, "0x%.3x: 0x%.2x\n", i,
- (reg_val & 0xFF));
+ swr_read(pdev, pdev->dev_num, i, &reg_val, 1);
+ 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)) {
@@ -432,53 +427,84 @@ static ssize_t wsa881x_swrslave_reg_show(char __user *ubuf, size_t count,
total = -EFAULT;
goto copy_err;
}
- *ppos += len;
total += len;
+ *ppos += len;
}
copy_err:
+ *ppos = SWR_SLV_MAX_REG_ADDR * BYTES_PER_LINE;
return total;
}
+static ssize_t codec_debug_dump(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct swr_device *pdev;
+
+ if (!count || !file || !ppos || !ubuf)
+ return -EINVAL;
+
+ pdev = file->private_data;
+ if (!pdev)
+ return -EINVAL;
+
+ if (*ppos < 0)
+ return -EINVAL;
+
+ return wsa881x_swrslave_reg_show(pdev, ubuf, count, ppos);
+}
+
static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
char lbuf[SWR_SLV_RD_BUF_LEN];
- char *access_str;
- ssize_t ret_cnt;
+ struct swr_device *pdev = NULL;
+ struct wsa881x_priv *wsa881x = NULL;
if (!count || !file || !ppos || !ubuf)
return -EINVAL;
- access_str = file->private_data;
+ pdev = file->private_data;
+ if (!pdev)
+ return -EINVAL;
+
+ wsa881x = swr_get_dev_data(pdev);
+ if (!wsa881x)
+ return -EINVAL;
+
if (*ppos < 0)
return -EINVAL;
- if (!strcmp(access_str, "swrslave_peek")) {
- snprintf(lbuf, sizeof(lbuf), "0x%x\n", (read_data & 0xFF));
- ret_cnt = simple_read_from_buffer(ubuf, count, ppos, lbuf,
- strnlen(lbuf, 7));
- } else if (!strcmp(access_str, "swrslave_reg_dump")) {
- ret_cnt = wsa881x_swrslave_reg_show(ubuf, count, ppos);
- } else {
- pr_err("%s: %s not permitted to read\n", __func__, access_str);
- ret_cnt = -EPERM;
- }
- return ret_cnt;
+ snprintf(lbuf, sizeof(lbuf), "0x%x\n",
+ (wsa881x->read_data & 0xFF));
+
+ return simple_read_from_buffer(ubuf, count, ppos, lbuf,
+ strnlen(lbuf, 7));
}
-static ssize_t codec_debug_write(struct file *filp,
- const char __user *ubuf, size_t cnt, loff_t *ppos)
+static ssize_t codec_debug_peek_write(struct file *file,
+ const char __user *ubuf, size_t cnt, loff_t *ppos)
{
char lbuf[SWR_SLV_WR_BUF_LEN];
- int rc;
+ int rc = 0;
u32 param[5];
- char *access_str;
+ struct swr_device *pdev = NULL;
+ struct wsa881x_priv *wsa881x = NULL;
+
+ if (!cnt || !file || !ppos || !ubuf)
+ return -EINVAL;
+
+ pdev = file->private_data;
+ if (!pdev)
+ return -EINVAL;
- if (!filp || !ppos || !ubuf)
+ wsa881x = swr_get_dev_data(pdev);
+ if (!wsa881x)
+ return -EINVAL;
+
+ if (*ppos < 0)
return -EINVAL;
- access_str = filp->private_data;
if (cnt > sizeof(lbuf) - 1)
return -EINVAL;
@@ -487,32 +513,46 @@ static ssize_t codec_debug_write(struct file *filp,
return -EFAULT;
lbuf[cnt] = '\0';
- if (!strcmp(access_str, "swrslave_poke")) {
- /* write */
- rc = get_parameters(lbuf, param, 3);
- if ((param[0] <= SWR_SLV_MAX_REG_ADDR) && (param[1] <= 0xFF) &&
- (rc == 0))
- swr_write(dbgwsa881x->swr_slave, param[2],
- param[0], &param[1]);
- else
- rc = -EINVAL;
- } else if (!strcmp(access_str, "swrslave_peek")) {
- /* read */
- rc = get_parameters(lbuf, param, 2);
- if ((param[0] <= SWR_SLV_MAX_REG_ADDR) && (rc == 0))
- swr_read(dbgwsa881x->swr_slave, param[1],
- param[0], &read_data, 1);
- else
- rc = -EINVAL;
- } else if (!strcmp(access_str, "swrslave_reg_dump")) {
- /* reg dump */
- rc = get_parameters(lbuf, param, 1);
- if ((rc == 0) && (param[0] > 0) &&
- (param[0] <= SWR_SLV_MAX_DEVICES))
- devnum = param[0];
- else
- rc = -EINVAL;
- }
+ rc = get_parameters(lbuf, param, 1);
+ if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) && (rc == 0)))
+ return -EINVAL;
+ swr_read(pdev, pdev->dev_num, param[0], &wsa881x->read_data, 1);
+ if (rc == 0)
+ rc = cnt;
+ else
+ pr_err("%s: rc = %d\n", __func__, rc);
+
+ return rc;
+}
+
+static ssize_t codec_debug_write(struct file *file,
+ const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ char lbuf[SWR_SLV_WR_BUF_LEN];
+ int rc = 0;
+ u32 param[5];
+ struct swr_device *pdev;
+
+ if (!file || !ppos || !ubuf)
+ return -EINVAL;
+
+ pdev = file->private_data;
+ if (!pdev)
+ return -EINVAL;
+
+ if (cnt > sizeof(lbuf) - 1)
+ return -EINVAL;
+
+ rc = copy_from_user(lbuf, ubuf, cnt);
+ if (rc)
+ return -EFAULT;
+
+ lbuf[cnt] = '\0';
+ rc = get_parameters(lbuf, param, 2);
+ if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) &&
+ (param[1] <= 0xFF) && (rc == 0)))
+ return -EINVAL;
+ swr_write(pdev, pdev->dev_num, param[0], &param[1]);
if (rc == 0)
rc = cnt;
else
@@ -521,12 +561,21 @@ static ssize_t codec_debug_write(struct file *filp,
return rc;
}
-static const struct file_operations codec_debug_ops = {
+static const struct file_operations codec_debug_write_ops = {
.open = codec_debug_open,
.write = codec_debug_write,
+};
+
+static const struct file_operations codec_debug_read_ops = {
+ .open = codec_debug_open,
.read = codec_debug_read,
+ .write = codec_debug_peek_write,
};
+static const struct file_operations codec_debug_dump_ops = {
+ .open = codec_debug_open,
+ .read = codec_debug_dump,
+};
static void wsa881x_regcache_sync(struct wsa881x_priv *wsa881x)
{
mutex_lock(&wsa881x->res_lock);
@@ -1454,27 +1503,31 @@ static int wsa881x_swr_probe(struct swr_device *pdev)
wsa881x_gpio_ctrl(wsa881x, true);
wsa881x->state = WSA881X_DEV_UP;
- if (!debugfs_wsa881x_dent) {
- dbgwsa881x = wsa881x;
- debugfs_wsa881x_dent = debugfs_create_dir(
- "wsa881x_swr_slave", 0);
- if (!IS_ERR(debugfs_wsa881x_dent)) {
- debugfs_peek = debugfs_create_file("swrslave_peek",
- S_IFREG | 0444, debugfs_wsa881x_dent,
- (void *) "swrslave_peek",
- &codec_debug_ops);
-
- debugfs_poke = debugfs_create_file("swrslave_poke",
- S_IFREG | 0444, debugfs_wsa881x_dent,
- (void *) "swrslave_poke",
- &codec_debug_ops);
-
- debugfs_reg_dump = debugfs_create_file(
+ if (!wsa881x->debugfs_dent) {
+ wsa881x->debugfs_dent = debugfs_create_dir(
+ dev_name(&pdev->dev), 0);
+ if (!IS_ERR(wsa881x->debugfs_dent)) {
+ wsa881x->debugfs_peek =
+ debugfs_create_file("swrslave_peek",
+ S_IFREG | 0444,
+ wsa881x->debugfs_dent,
+ (void *) pdev,
+ &codec_debug_read_ops);
+
+ wsa881x->debugfs_poke =
+ debugfs_create_file("swrslave_poke",
+ S_IFREG | 0444,
+ wsa881x->debugfs_dent,
+ (void *) pdev,
+ &codec_debug_write_ops);
+
+ wsa881x->debugfs_reg_dump =
+ debugfs_create_file(
"swrslave_reg_dump",
S_IFREG | 0444,
- debugfs_wsa881x_dent,
- (void *) "swrslave_reg_dump",
- &codec_debug_ops);
+ wsa881x->debugfs_dent,
+ (void *) pdev,
+ &codec_debug_dump_ops);
}
}
@@ -1566,8 +1619,8 @@ static int wsa881x_swr_remove(struct swr_device *pdev)
if (wsa881x->register_notifier)
wsa881x->register_notifier(wsa881x->handle,
&wsa881x->bolero_nblock, false);
- debugfs_remove_recursive(debugfs_wsa881x_dent);
- debugfs_wsa881x_dent = NULL;
+ debugfs_remove_recursive(wsa881x->debugfs_dent);
+ wsa881x->debugfs_dent = NULL;
mutex_destroy(&wsa881x->res_lock);
mutex_destroy(&wsa881x->temp_lock);
snd_soc_unregister_component(&pdev->dev);
diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c
index 8a5e99e4..31ba5ba7 100644
--- a/asoc/codecs/wsa883x/wsa883x.c
+++ b/asoc/codecs/wsa883x/wsa883x.c
@@ -481,8 +481,33 @@ static irqreturn_t wsa883x_uvlo_handle_irq(int irq, void *data)
static irqreturn_t wsa883x_pa_on_err_handle_irq(int irq, void *data)
{
- pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
- __func__, irq);
+ u8 pa_fsm_sta = 0, pa_fsm_err = 0;
+ struct wsa883x_priv *wsa883x = data;
+ struct snd_soc_component *component = NULL;
+
+ if (!wsa883x)
+ return IRQ_NONE;
+
+ component = wsa883x->component;
+ if (!component)
+ return IRQ_NONE;
+
+ pa_fsm_sta = (snd_soc_component_read32(component, WSA883X_PA_FSM_STA)
+ & 0x70);
+
+ if (pa_fsm_sta)
+ pa_fsm_err = snd_soc_component_read32(component,
+ WSA883X_PA_FSM_ERR_COND);
+ pr_err_ratelimited("%s: irq: %d, pa_fsm_sta: %d, pa_fsm_err: %d\n",
+ __func__, irq, pa_fsm_sta, pa_fsm_err);
+
+ snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL,
+ 0x10, 0x00);
+ snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL,
+ 0x10, 0x10);
+ snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL,
+ 0x10, 0x00);
+
return IRQ_HANDLED;
}
@@ -770,6 +795,30 @@ int wsa883x_codec_info_create_codec_entry(struct snd_info_entry *codec_root,
}
EXPORT_SYMBOL(wsa883x_codec_info_create_codec_entry);
+/*
+ * wsa883x_codec_get_dev_num - returns swr device number
+ * @component: Codec instance
+ *
+ * Return: swr device number on success or negative error
+ * code on failure.
+ */
+int wsa883x_codec_get_dev_num(struct snd_soc_component *component)
+{
+ struct wsa883x_priv *wsa883x;
+
+ if (!component)
+ return -EINVAL;
+
+ wsa883x = snd_soc_component_get_drvdata(component);
+ if (!wsa883x) {
+ pr_err("%s: wsa883x component is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ return wsa883x->swr_slave->dev_num;
+}
+EXPORT_SYMBOL(wsa883x_codec_get_dev_num);
+
static int wsa883x_get_compander(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -993,9 +1042,16 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w,
0x01, 0x01);
/* Added delay as per HW sequence */
usleep_range(250, 300);
+ wcd_enable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR);
/* 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);
if (test_bit(SPKR_ADIE_LB, &wsa883x->status_mask))
snd_soc_component_update_bits(component,
WSA883X_PA_FSM_CTL, 0x01, 0x01);
@@ -1004,11 +1060,23 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w,
if (!test_bit(SPKR_ADIE_LB, &wsa883x->status_mask))
wcd_disable_irq(&wsa883x->irq_info,
WSA883X_IRQ_INT_PDM_WD);
+ 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);
+ snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL,
+ 0x10, 0x00);
+ snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL,
+ 0x10, 0x10);
snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL,
+ 0x10, 0x00);
+ snd_soc_component_update_bits(wsa883x->component, WSA883X_PDM_WD_CTL,
0x01, 0x00);
- snd_soc_component_update_bits(wsa883x->component,
- WSA883X_PDM_WD_CTL,
- 0x01, 0x00);
+ wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR);
clear_bit(SPKR_STATUS, &wsa883x->status_mask);
clear_bit(SPKR_ADIE_LB, &wsa883x->status_mask);
break;
@@ -1558,7 +1626,7 @@ static int wsa883x_swr_probe(struct swr_device *pdev)
"WSA UVLO", wsa883x_uvlo_handle_irq, NULL);
wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR,
- "WSA PA ERR", wsa883x_pa_on_err_handle_irq, NULL);
+ "WSA PA ERR", wsa883x_pa_on_err_handle_irq, wsa883x);
wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR);
diff --git a/asoc/codecs/wsa883x/wsa883x.h b/asoc/codecs/wsa883x/wsa883x.h
index e080134e..bb719831 100644
--- a/asoc/codecs/wsa883x/wsa883x.h
+++ b/asoc/codecs/wsa883x/wsa883x.h
@@ -21,6 +21,7 @@ int wsa883x_set_channel_map(struct snd_soc_component *component,
int wsa883x_codec_info_create_codec_entry(
struct snd_info_entry *codec_root,
struct snd_soc_component *component);
+int wsa883x_codec_get_dev_num(struct snd_soc_component *component);
#else
static int wsa883x_set_channel_map(struct snd_soc_component *component,
u8 *port, u8 num_port, unsigned int *ch_mask,
@@ -36,6 +37,10 @@ static int wsa883x_codec_info_create_codec_entry(
return 0;
}
+static int wsa883x_codec_get_dev_num(struct snd_soc_component *component)
+{
+ return 0;
+}
#endif
#endif /* _WSA883X_H */
diff --git a/asoc/kona.c b/asoc/kona.c
index 5192e3ec..f5d0ea8e 100644
--- a/asoc/kona.c
+++ b/asoc/kona.c
@@ -80,12 +80,16 @@
#define ADSP_STATE_READY_TIMEOUT_MS 3000
-#define WSA8810_NAME_1 "wsa881x.20170211"
-#define WSA8810_NAME_2 "wsa881x.20170212"
+#define WSA8810_NAME_1 "wsa881x.1020170211"
+#define WSA8810_NAME_2 "wsa881x.1020170212"
+#define WSA8815_NAME_1 "wsa881x.1021170213"
+#define WSA8815_NAME_2 "wsa881x.1021170214"
#define WCN_CDC_SLIM_RX_CH_MAX 2
#define WCN_CDC_SLIM_TX_CH_MAX 2
#define WCN_CDC_SLIM_TX_CH_MAX_LITO 3
+#define SWR_MAX_SLAVE_DEVICES 6
+
enum {
RX_PATH = 0,
TX_PATH,
@@ -193,7 +197,10 @@ struct msm_asoc_mach_data {
struct device_node *fsa_handle;
struct clk *lpass_audio_hw_vote;
int core_audio_vote_count;
+ u32 wsa_max_devs;
u32 tdm_max_slots; /* Max TDM slots used */
+ int (*get_wsa_dev_num)(struct snd_soc_component*);
+ struct afe_cps_hw_intf_cfg cps_config;
};
struct tdm_port {
@@ -2689,6 +2696,12 @@ static int msm_get_port_id(int be_id)
case MSM_BACKEND_DAI_SENARY_MI2S_TX:
afe_port_id = AFE_PORT_ID_SENARY_MI2S_TX;
break;
+ case MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0:
+ afe_port_id = AFE_PORT_ID_WSA_CODEC_DMA_RX_0;
+ break;
+ case MSM_BACKEND_DAI_WSA_CDC_DMA_TX_0:
+ afe_port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_0;
+ break;
case MSM_BACKEND_DAI_VA_CDC_DMA_TX_0:
afe_port_id = AFE_PORT_ID_VA_CODEC_DMA_TX_0;
break;
@@ -4900,6 +4913,121 @@ static int msm_snd_cdc_dma_startup(struct snd_pcm_substream *substream)
return ret;
}
+static void set_cps_config(struct snd_soc_pcm_runtime *rtd,
+ u32 num_ch, u32 ch_mask)
+{
+ int i = 0;
+ int val = 0;
+ u8 dev_num = 0;
+ int ch_configured = 0;
+ int j = 0;
+ int n = 0;
+ char wsa_cdc_name[DEV_NAME_STR_LEN];
+ struct snd_soc_component *component = NULL;
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ struct msm_asoc_mach_data *pdata =
+ snd_soc_card_get_drvdata(rtd->card);
+
+ if (!pdata) {
+ pr_err("%s: pdata is NULL\n", __func__);
+ return;
+ }
+
+ if (!num_ch) {
+ pr_err("%s: channel count is 0\n", __func__);
+ return;
+ }
+
+ if (!pdata->get_wsa_dev_num) {
+ pr_err("%s: get_wsa_dev_num is NULL\n", __func__);
+ return;
+ }
+
+ if (!pdata->cps_config.spkr_dep_cfg) {
+ pr_debug("%s: spkr_dep_cfg is NULL\n", __func__);
+ return;
+ }
+
+ if (!pdata->cps_config.hw_reg_cfg.lpass_wr_cmd_reg_phy_addr ||
+ !pdata->cps_config.hw_reg_cfg.lpass_rd_cmd_reg_phy_addr ||
+ !pdata->cps_config.hw_reg_cfg.lpass_rd_fifo_reg_phy_addr) {
+ pr_err("%s: cps static configuration is not set\n", __func__);
+ return;
+ }
+
+ pdata->cps_config.lpass_hw_intf_cfg_mode = 1;
+
+ while (ch_configured < num_ch) {
+ if (!(ch_mask & (1 << i))) {
+ i++;
+ continue;
+ }
+
+ snprintf(wsa_cdc_name, sizeof(wsa_cdc_name), "wsa-codec.%d",
+ i+1);
+
+ /* Use n to make sure both WSA components are retrieved */
+ /* When first WSA component is retrieved adjust looping
+ variable such that the next time only the remaining part
+ of the array is traversed */
+ for (j = n; j < rtd->card->num_aux_devs; j++)
+ {
+ if (msm_codec_conf[j].name_prefix != NULL ) {
+ if (strstr(msm_codec_conf[j].name_prefix,
+ "Left")) {
+ component = soc_find_component_locked(
+ msm_aux_dev[j].codec_of_node,
+ NULL);
+ n = j+1;
+ break;
+ }
+ else if (strstr(msm_codec_conf[j].name_prefix,
+ "Right")) {
+ component = soc_find_component_locked(
+ msm_aux_dev[j].codec_of_node,
+ NULL);
+ n = j+1;
+ break;
+ }
+ }
+ }
+
+ if (!component) {
+ pr_err("%s: %s component is NULL\n", __func__,
+ wsa_cdc_name);
+ return;
+ }
+
+ dev_num = pdata->get_wsa_dev_num(component);
+ if (dev_num < 0 || dev_num > SWR_MAX_SLAVE_DEVICES) {
+ pr_err("%s: invalid slave dev num : %d\n", __func__,
+ dev_num);
+ return;
+ }
+
+ /* Clear stale dev num info */
+ pdata->cps_config.spkr_dep_cfg[i].vbatt_pkd_reg_addr &= 0xFFFF;
+ pdata->cps_config.spkr_dep_cfg[i].temp_pkd_reg_addr &= 0xFFFF;
+
+ val = 0;
+
+ /* bits 20:23 carry swr device number */
+ val |= dev_num << 20;
+
+ /* bits 24:27 carry read length in bytes */
+ val |= 1 << 24;
+
+ /* Update dev num in packed reg addr */
+ pdata->cps_config.spkr_dep_cfg[i].vbatt_pkd_reg_addr |= val;
+ pdata->cps_config.spkr_dep_cfg[i].temp_pkd_reg_addr |= val;
+ i++;
+ ch_configured++;
+ }
+
+ afe_set_cps_config(msm_get_port_id(dai_link->id),
+ &pdata->cps_config, ch_mask);
+}
+
static int msm_snd_cdc_dma_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -4947,6 +5075,11 @@ static int msm_snd_cdc_dma_hw_params(struct snd_pcm_substream *substream,
goto err;
}
+ if (dai_link->id == MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0 ||
+ dai_link->id == MSM_BACKEND_DAI_WSA_CDC_DMA_RX_1) {
+ set_cps_config(rtd, user_set_rx_ch,
+ rx_ch_cdc_dma);
+ }
}
break;
}
@@ -5531,6 +5664,11 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
WSA_MACRO_SPKR_MODE_1);
wsa_macro_set_spkr_gain_offset(component,
WSA_MACRO_GAIN_OFFSET_M1P5_DB);
+ } else if (aux_comp->name != NULL && (
+ !strcmp(aux_comp->name, WSA8815_NAME_1) ||
+ !strcmp(aux_comp->name, WSA8815_NAME_2))) {
+ wsa_macro_set_spkr_mode(component,
+ WSA_MACRO_SPKR_MODE_DEFAULT);
}
}
}
@@ -8229,6 +8367,115 @@ static int msm_audio_ssr_register(struct device *dev)
return ret;
}
+static void parse_cps_configuration(struct platform_device *pdev,
+ struct msm_asoc_mach_data *pdata)
+{
+ int ret = 0;
+ int i = 0, j = 0;
+ u32 dt_values[MAX_CPS_LEVELS];
+
+ if (!pdev || !pdata || !pdata->wsa_max_devs)
+ return;
+
+ pdata->get_wsa_dev_num = wsa883x_codec_get_dev_num;
+ pdata->cps_config.hw_reg_cfg.num_spkr = pdata->wsa_max_devs;
+
+ ret = of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,cps_reg_phy_addr", dt_values,
+ sizeof(dt_values)/sizeof(dt_values[0]));
+ if (ret) {
+ dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
+ __func__, "qcom,cps_reg_phy_addr");
+ } else {
+ pdata->cps_config.hw_reg_cfg.lpass_wr_cmd_reg_phy_addr =
+ dt_values[0];
+ pdata->cps_config.hw_reg_cfg.lpass_rd_cmd_reg_phy_addr =
+ dt_values[1];
+ pdata->cps_config.hw_reg_cfg.lpass_rd_fifo_reg_phy_addr =
+ dt_values[2];
+ }
+
+ ret = of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,cps_threshold_levels", dt_values,
+ sizeof(dt_values)/sizeof(dt_values[0]) - 1);
+ if (ret) {
+ dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
+ __func__, "qcom,cps_threshold_levels");
+ } else {
+ pdata->cps_config.hw_reg_cfg.vbatt_lower2_threshold =
+ dt_values[0];
+ pdata->cps_config.hw_reg_cfg.vbatt_lower1_threshold =
+ dt_values[1];
+ }
+
+ pdata->cps_config.spkr_dep_cfg = devm_kzalloc(&pdev->dev,
+ sizeof(struct lpass_swr_spkr_dep_cfg_t)
+ * pdata->wsa_max_devs, GFP_KERNEL);
+ if (!pdata->cps_config.spkr_dep_cfg) {
+ dev_err(&pdev->dev, "%s: spkr dep cfg alloc failed\n", __func__);
+ return;
+ }
+ ret = of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,cps_wsa_vbatt_temp_reg_addr", dt_values,
+ sizeof(dt_values)/sizeof(dt_values[0]) - 1);
+ if (ret) {
+ dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
+ __func__, "qcom,cps_wsa_vbatt_temp_reg_addr");
+ } else {
+ for (i = 0; i < pdata->wsa_max_devs; i++) {
+ pdata->cps_config.spkr_dep_cfg[i].vbatt_pkd_reg_addr =
+ dt_values[0];
+ pdata->cps_config.spkr_dep_cfg[i].temp_pkd_reg_addr =
+ dt_values[1];
+ }
+ }
+
+ ret = of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,cps_normal_values", dt_values,
+ sizeof(dt_values)/sizeof(dt_values[0]));
+ if (ret) {
+ dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
+ __func__, "qcom,cps_normal_values");
+ } else {
+ for (i = 0; i < pdata->wsa_max_devs; i++) {
+ for (j = 0; j < MAX_CPS_LEVELS; j++) {
+ pdata->cps_config.spkr_dep_cfg[i].
+ value_normal_thrsd[j] = dt_values[j];
+ }
+ }
+ }
+
+ ret = of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,cps_lower1_values", dt_values,
+ sizeof(dt_values)/sizeof(dt_values[0]));
+ if (ret) {
+ dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
+ __func__, "qcom,cps_lower1_values");
+ } else {
+ for (i = 0; i < pdata->wsa_max_devs; i++) {
+ for (j = 0; j < MAX_CPS_LEVELS; j++) {
+ pdata->cps_config.spkr_dep_cfg[i].
+ value_low1_thrsd[j] = dt_values[j];
+ }
+ }
+ }
+
+ ret = of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,cps_lower2_values", dt_values,
+ sizeof(dt_values)/sizeof(dt_values[0]));
+ if (ret) {
+ dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
+ __func__, "qcom,cps_lower2_values");
+ } else {
+ for (i = 0; i < pdata->wsa_max_devs; i++) {
+ for (j = 0; j < MAX_CPS_LEVELS; j++) {
+ pdata->cps_config.spkr_dep_cfg[i].
+ value_low2_thrsd[j] = dt_values[j];
+ }
+ }
+ }
+}
+
static int msm_asoc_machine_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = NULL;
@@ -8300,6 +8547,15 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "%s: Sound card %s registered\n",
__func__, card->name);
+ /* Get maximum WSA device count for this platform */
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "qcom,wsa-max-devs", &pdata->wsa_max_devs);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: No DT match for wsa max devs\n",
+ __func__);
+ pdata->wsa_max_devs = 0;
+ }
+
ret = of_property_read_u32(pdev->dev.of_node, "qcom,tdm-max-slots",
&pdata->tdm_max_slots);
if (ret) {
@@ -8412,6 +8668,10 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
atomic_set(&(pdata->mi2s_gpio_ref_count[index]), 0);
}
+ /* parse cps configuration from dt */
+ if (of_property_read_bool(pdev->dev.of_node, "qcom,cps_reg_phy_addr"))
+ parse_cps_configuration(pdev, pdata);
+
/* Register LPASS audio hw vote */
lpass_audio_hw_vote = devm_clk_get(&pdev->dev, "lpass_audio_hw_vote");
if (IS_ERR(lpass_audio_hw_vote)) {
diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c
index de28f65a..e6a5c1a7 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-2020, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
*/
@@ -1007,9 +1007,12 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
xfer = size;
offset = prtd->in_frame_info[idx].offset;
pr_debug("Offset value = %d\n", offset);
- if (size == 0 || size < fbytes) {
- memset(bufptr + offset + size, 0, fbytes - size);
- size = xfer = fbytes;
+ if (size == 0 || size < prtd->pcm_count) {
+ memset(bufptr + offset + size, 0, prtd->pcm_count - size);
+ if (fbytes > prtd->pcm_count)
+ size = xfer = prtd->pcm_count;
+ else
+ size = xfer = fbytes;
}
if (copy_to_user(buf, bufptr+offset, xfer)) {
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 03603a2c..7aafe2b9 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/init.h>
@@ -3033,6 +3033,7 @@ static int msm_routing_lsm_port_put(struct snd_kcontrol *kcontrol,
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
int mux = ucontrol->value.enumerated.item[0];
int lsm_port = AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_TX;
+ int lsm_port_idx = 0;
u8 fe_idx = 0;
if (mux >= e->items) {
@@ -3042,6 +3043,7 @@ static int msm_routing_lsm_port_put(struct snd_kcontrol *kcontrol,
pr_debug("%s: LSM enable %ld\n", __func__,
ucontrol->value.integer.value[0]);
+ lsm_port_idx = ucontrol->value.integer.value[0];
switch (ucontrol->value.integer.value[0]) {
case 1:
lsm_port = AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_TX;
@@ -3098,6 +3100,10 @@ static int msm_routing_lsm_port_put(struct snd_kcontrol *kcontrol,
set_lsm_port(lsm_port);
msm_routing_get_lsm_fe_idx(kcontrol, &fe_idx);
lsm_port_index[fe_idx] = ucontrol->value.integer.value[0];
+ /* Set the default AFE LSM Port to 0xffff */
+ if(lsm_port_idx <= 0 || lsm_port_idx >= ARRAY_SIZE(lsm_port_text))
+ lsm_port = 0xffff;
+ afe_set_lsm_afe_port_id(fe_idx, lsm_port);
return 0;
}
@@ -22767,9 +22773,9 @@ static int msm_routing_put_app_type_cfg_control(struct snd_kcontrol *kcontrol,
memset(app_type_cfg, 0, MAX_APP_TYPES*
sizeof(struct msm_pcm_routing_app_type_data));
- if (num_app_types > MAX_APP_TYPES) {
- pr_err("%s: number of app types exceed the max supported\n",
- __func__);
+ if (num_app_types > MAX_APP_TYPES || num_app_types < 0) {
+ pr_err("%s: number of app types %d is invalid\n",
+ __func__, num_app_types);
return -EINVAL;
}
for (j = 0; j < num_app_types; j++) {
@@ -22973,9 +22979,10 @@ static int msm_routing_put_lsm_app_type_cfg_control(
int i = 0, j;
mutex_lock(&routing_lock);
- if (ucontrol->value.integer.value[0] > MAX_APP_TYPES) {
- pr_err("%s: number of app types exceed the max supported\n",
- __func__);
+ if (ucontrol->value.integer.value[0] < 0 ||
+ ucontrol->value.integer.value[0] > MAX_APP_TYPES) {
+ pr_err("%s: number of app types %ld is invalid\n",
+ __func__, ucontrol->value.integer.value[0]);
mutex_unlock(&routing_lock);
return -EINVAL;
}
diff --git a/dsp/audio_cal_utils.c b/dsp/audio_cal_utils.c
index 8e0d7e03..0f37fda4 100644
--- a/dsp/audio_cal_utils.c
+++ b/dsp/audio_cal_utils.c
@@ -10,6 +10,8 @@
#include <linux/mutex.h>
#include <dsp/audio_cal_utils.h>
+struct mutex cal_lock;
+
static int unmap_memory(struct cal_type_data *cal_type,
struct cal_block_data *cal_block);
@@ -946,7 +948,9 @@ int cal_utils_dealloc_cal(size_t data_size, void *data,
if (ret < 0)
goto err;
+ mutex_lock(&cal_lock);
delete_cal_block(cal_block);
+ mutex_unlock(&cal_lock);
err:
mutex_unlock(&cal_type->lock);
done:
@@ -1061,6 +1065,11 @@ void cal_utils_mark_cal_used(struct cal_block_data *cal_block)
}
EXPORT_SYMBOL(cal_utils_mark_cal_used);
+int __init cal_utils_init(void)
+{
+ mutex_init(&cal_lock);
+ return 0;
+}
/**
* cal_utils_is_cal_stale
*
@@ -1070,9 +1079,19 @@ EXPORT_SYMBOL(cal_utils_mark_cal_used);
*/
bool cal_utils_is_cal_stale(struct cal_block_data *cal_block)
{
- if ((cal_block) && (cal_block->cal_stale))
- return true;
+ bool ret = false;
- return false;
+ mutex_lock(&cal_lock);
+ if (!cal_block) {
+ pr_err("%s: cal_block is Null", __func__);
+ goto unlock;
+ }
+
+ if (cal_block->cal_stale)
+ ret = true;
+
+unlock:
+ mutex_unlock(&cal_lock);
+ return ret;
}
EXPORT_SYMBOL(cal_utils_is_cal_stale);
diff --git a/dsp/audio_calibration.c b/dsp/audio_calibration.c
index a5167be3..854d8821 100644
--- a/dsp/audio_calibration.c
+++ b/dsp/audio_calibration.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2014, 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016-2017, 2020, The Linux Foundation. All rights reserved.
*/
#include <linux/slab.h>
#include <linux/fs.h>
@@ -591,6 +591,7 @@ int __init audio_cal_init(void)
pr_debug("%s\n", __func__);
+ cal_utils_init();
memset(&audio_cal, 0, sizeof(audio_cal));
mutex_init(&audio_cal.common_lock);
for (; i < MAX_CAL_TYPES; i++) {
diff --git a/dsp/msm_audio_ion.c b/dsp/msm_audio_ion.c
index 566f8bf1..2bf02fca 100644
--- a/dsp/msm_audio_ion.c
+++ b/dsp/msm_audio_ion.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/init.h>
@@ -67,7 +67,7 @@ static int msm_audio_dma_buf_map(struct dma_buf *dma_buf,
dma_addr_t *addr, size_t *len)
{
- struct msm_audio_alloc_data *alloc_data;
+ struct msm_audio_alloc_data *alloc_data = NULL;
struct device *cb_dev;
unsigned long ionflag = 0;
int rc = 0;
@@ -133,6 +133,7 @@ detach_dma_buf:
alloc_data->attach);
free_alloc_data:
kfree(alloc_data);
+ alloc_data = NULL;
return rc;
}
@@ -170,6 +171,7 @@ static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf)
list_del(&(alloc_data->list));
kfree(alloc_data);
+ alloc_data = NULL;
break;
}
}
@@ -312,6 +314,11 @@ static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr,
{
int rc = 0;
+ if (!dma_buf || !paddr || !vaddr || !plen) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+
rc = msm_audio_ion_get_phys(dma_buf, paddr, plen);
if (rc) {
pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
diff --git a/dsp/msm_audio_ion_vm.c b/dsp/msm_audio_ion_vm.c
index 37b17b68..ed60c652 100644
--- a/dsp/msm_audio_ion_vm.c
+++ b/dsp/msm_audio_ion_vm.c
@@ -124,7 +124,7 @@ static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf,
dma_addr_t *addr, size_t *len)
{
- struct msm_audio_alloc_data *alloc_data;
+ struct msm_audio_alloc_data *alloc_data = NULL;
struct device *cb_dev;
unsigned long ionflag = 0;
int rc = 0;
@@ -189,6 +189,7 @@ detach_dma_buf:
dma_buf_detach(dma_buf, alloc_data->attach);
free_alloc_data:
kfree(alloc_data);
+ alloc_data = NULL;
return rc;
}
@@ -262,6 +263,7 @@ static int msm_audio_dma_buf_unmap(void *handle)
list_del(&(alloc_data->list));
kfree(alloc_data);
+ alloc_data = NULL;
break;
}
} else {
@@ -278,6 +280,7 @@ static int msm_audio_dma_buf_unmap(void *handle)
list_del(&(alloc_data->list));
kfree(alloc_data);
+ alloc_data = NULL;
break;
}
}
@@ -541,6 +544,11 @@ static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr,
{
int rc = 0;
+ if (!handle || !paddr || !vaddr || !plen) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+
rc = msm_audio_ion_get_phys((struct dma_buf*) handle, paddr, plen);
if (rc) {
pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index c9a5c95e..88124df9 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -27,6 +27,7 @@
#define AFE_CLK_TOKEN 1024
#define SP_V4_NUM_MAX_SPKRS SP_V2_NUM_MAX_SPKRS
+#define MAX_LSM_SESSIONS 8
struct afe_avcs_payload_port_mapping {
u16 port_id;
@@ -246,6 +247,10 @@ struct afe_ctl {
/* FTM spk params */
uint32_t initial_cal;
uint32_t v_vali_flag;
+ uint32_t num_spkrs;
+ uint32_t cps_ch_mask;
+ struct afe_cps_hw_intf_cfg *cps_config;
+ int lsm_afe_ports[MAX_LSM_SESSIONS];
};
struct afe_clkinfo_per_port {
@@ -300,6 +305,8 @@ bool afe_close_done[2] = {true, true};
#define SIZEOF_CFG_CMD(y) \
(sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
+static bool q6afe_is_afe_lsm_port(int port_id);
+
static void q6afe_unload_avcs_modules(u16 port_id, int index)
{
int ret = 0;
@@ -2172,6 +2179,70 @@ fail_cmd:
return ret;
}
+static int afe_send_cps_config(int src_port)
+{
+ int i = 0;
+ struct param_hdr_v3 param_info;
+ int ret = -EINVAL;
+ u8 *packed_payload = NULL;
+ int cpy_size = 0;
+ int ch_copied = 0;
+ size_t param_size = 0;
+
+ if ((-1 == this_afe.vi_tx_port) || (!this_afe.cps_ch_mask) ||
+ (!this_afe.cps_config)) {
+ pr_err("%s: speaker prot not configured for 0x%x\n", __func__,
+ src_port);
+ return -EINVAL;
+ }
+
+ param_size = sizeof(struct afe_cps_hw_intf_cfg) -
+ sizeof(this_afe.cps_config->spkr_dep_cfg) +
+ (sizeof(struct lpass_swr_spkr_dep_cfg_t)
+ * this_afe.num_spkrs);
+
+ this_afe.cps_config->hw_reg_cfg.num_spkr = this_afe.num_spkrs;
+ packed_payload = kzalloc(param_size, GFP_KERNEL);
+ if (packed_payload == NULL)
+ return -ENOMEM;
+
+ cpy_size = sizeof(struct afe_cps_hw_intf_cfg) -
+ sizeof(this_afe.cps_config->spkr_dep_cfg);
+ memcpy(packed_payload, this_afe.cps_config, cpy_size);
+
+ while (ch_copied < this_afe.num_spkrs) {
+ if (!(this_afe.cps_ch_mask & (1 << i))) {
+ i++;
+ continue;
+ }
+
+ memcpy(packed_payload + cpy_size,
+ &this_afe.cps_config->spkr_dep_cfg[i],
+ sizeof(struct lpass_swr_spkr_dep_cfg_t));
+ cpy_size += sizeof(struct lpass_swr_spkr_dep_cfg_t);
+ ch_copied++;
+ i++;
+ }
+
+ memset(&param_info, 0, sizeof(param_info));
+ param_info.module_id = AFE_MODULE_SPEAKER_PROTECTION_V4_RX;
+ param_info.instance_id = INSTANCE_ID_0;
+ param_info.param_id = AFE_PARAM_ID_CPS_LPASS_HW_INTF_CFG;
+ param_info.param_size = param_size;
+
+ ret = q6afe_pack_and_set_param_in_band(src_port,
+ q6audio_get_port_index(src_port),
+ param_info, packed_payload);
+ if (ret)
+ pr_err("%s: port = 0x%x param = 0x%x failed %d\n", __func__,
+ src_port, param_info.param_id, ret);
+
+ pr_debug("%s: config.pdata.param_id 0x%x status %d 0x%x\n", __func__,
+ param_info.param_id, ret, src_port);
+ kfree(packed_payload);
+ return ret;
+}
+
static int afe_spk_prot_prepare(int src_port, int dst_port, int param_id,
union afe_spkr_prot_config *prot_config, uint32_t param_size)
{
@@ -2312,6 +2383,7 @@ static void afe_send_cal_spv4_tx(int port_id)
struct afe_sp_v4_channel_v_vali_cfg *ch_v_vali_cfg;
struct afe_sp_v4_param_ex_vi_ftm_cfg *ex_vi_ftm_cfg;
struct afe_sp_v4_channel_ex_vi_ftm *ch_ex_vi_ftm_cfg;
+ uint32_t i = 0;
pr_debug("%s: Entry.. port_id %d\n", __func__, port_id);
@@ -2372,7 +2444,7 @@ static void afe_send_cal_spv4_tx(int port_id)
v4_vi_op_mode->th_r0t0_selection_flag[SP_V2_SPKR_2] =
USE_SAFE_R0TO;
}
- afe_spk_config.v4_vi_op_mode.num_speakers = SP_V2_NUM_MAX_SPKRS;
+ afe_spk_config.v4_vi_op_mode.num_speakers = this_afe.num_spkrs;
if (afe_spk_prot_prepare(port_id, 0,
AFE_PARAM_ID_SP_V4_VI_OP_MODE_CFG,
&afe_spk_config,
@@ -2381,7 +2453,7 @@ static void afe_send_cal_spv4_tx(int port_id)
__func__);
size = sizeof(struct afe_sp_v4_param_th_vi_r0t0_cfg) +
- (SP_V2_NUM_MAX_SPKRS * sizeof(struct afe_sp_v4_channel_r0t0));
+ (this_afe.num_spkrs * sizeof(struct afe_sp_v4_channel_r0t0));
tmp_ptr = kzalloc(size, GFP_KERNEL);
if (!tmp_ptr) {
mutex_unlock(
@@ -2395,15 +2467,13 @@ static void afe_send_cal_spv4_tx(int port_id)
ch_r0t0_cfg =
(struct afe_sp_v4_channel_r0t0 *)(th_vi_r0t0_cfg + 1);
- th_vi_r0t0_cfg->num_speakers = SP_V2_NUM_MAX_SPKRS;
- ch_r0t0_cfg[SP_V2_SPKR_1].r0_cali_q24 =
- (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_1];
- ch_r0t0_cfg[SP_V2_SPKR_2].r0_cali_q24 =
- (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_2];
- ch_r0t0_cfg[SP_V2_SPKR_1].t0_cali_q6 =
- (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_1];
- ch_r0t0_cfg[SP_V2_SPKR_2].t0_cali_q6 =
- (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_2];
+ th_vi_r0t0_cfg->num_speakers = this_afe.num_spkrs;
+ for (i = 0; i < this_afe.num_spkrs; i++) {
+ ch_r0t0_cfg[i].r0_cali_q24 =
+ (uint32_t) this_afe.prot_cfg.r0[i];
+ ch_r0t0_cfg[i].t0_cali_q6 =
+ (uint32_t) this_afe.prot_cfg.t0[i];
+ }
if (afe_spk_prot_prepare(port_id, 0,
AFE_PARAM_ID_SP_V4_VI_R0T0_CFG,
(union afe_spkr_prot_config *)tmp_ptr, size))
@@ -2418,7 +2488,7 @@ static void afe_send_cal_spv4_tx(int port_id)
(this_afe.vi_tx_port == port_id) &&
(this_afe.prot_cfg.sp_version >= AFE_API_VERSION_V9)) {
size = sizeof(struct afe_sp_v4_param_th_vi_ftm_cfg) +
- (SP_V2_NUM_MAX_SPKRS*sizeof(struct afe_sp_v4_channel_ftm_cfg));
+ (this_afe.num_spkrs * sizeof(struct afe_sp_v4_channel_ftm_cfg));
tmp_ptr = kzalloc(size, GFP_KERNEL);
if (!tmp_ptr) {
mutex_unlock(
@@ -2431,16 +2501,13 @@ static void afe_send_cal_spv4_tx(int port_id)
ch_ftm_cfg =
(struct afe_sp_v4_channel_ftm_cfg *)(th_vi_ftm_cfg+1);
- th_vi_ftm_cfg->num_ch = SP_V2_NUM_MAX_SPKRS;
- ch_ftm_cfg[SP_V2_SPKR_1].wait_time_ms =
- this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_1];
- ch_ftm_cfg[SP_V2_SPKR_2].wait_time_ms =
- this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_2];
- ch_ftm_cfg[SP_V2_SPKR_1].ftm_time_ms =
- this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_1];
- ch_ftm_cfg[SP_V2_SPKR_2].ftm_time_ms =
- this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_2];
-
+ th_vi_ftm_cfg->num_ch = this_afe.num_spkrs;
+ for (i = 0; i < this_afe.num_spkrs; i++) {
+ ch_ftm_cfg[i].wait_time_ms =
+ this_afe.th_ftm_cfg.wait_time[i];
+ ch_ftm_cfg[i].ftm_time_ms =
+ this_afe.th_ftm_cfg.ftm_time[i];
+ }
if (afe_spk_prot_prepare(port_id, 0,
AFE_PARAM_ID_SP_V4_TH_VI_FTM_CFG,
(union afe_spkr_prot_config *)tmp_ptr, size))
@@ -2452,8 +2519,8 @@ static void afe_send_cal_spv4_tx(int port_id)
MSM_SPKR_PROT_IN_V_VALI_MODE) &&
(this_afe.vi_tx_port == port_id)) {
size = sizeof(struct afe_sp_v4_param_th_vi_v_vali_cfg) +
- (SP_V2_NUM_MAX_SPKRS *
- sizeof(struct afe_sp_v4_channel_v_vali_cfg));
+ (this_afe.num_spkrs *
+ sizeof(struct afe_sp_v4_channel_v_vali_cfg));
tmp_ptr = kzalloc(size, GFP_KERNEL);
if (!tmp_ptr) {
mutex_unlock(
@@ -2467,16 +2534,13 @@ static void afe_send_cal_spv4_tx(int port_id)
ch_v_vali_cfg =
(struct afe_sp_v4_channel_v_vali_cfg *)(th_vi_v_vali_cfg + 1);
- th_vi_v_vali_cfg->num_ch = SP_V2_NUM_MAX_SPKRS;
- ch_v_vali_cfg[SP_V2_SPKR_1].wait_time_ms =
- this_afe.v_vali_cfg.wait_time[SP_V2_SPKR_1];
- ch_v_vali_cfg[SP_V2_SPKR_2].wait_time_ms =
- this_afe.v_vali_cfg.wait_time[SP_V2_SPKR_2];
- ch_v_vali_cfg[SP_V2_SPKR_1].vali_time_ms =
- this_afe.v_vali_cfg.vali_time[SP_V2_SPKR_1];
- ch_v_vali_cfg[SP_V2_SPKR_2].vali_time_ms =
- this_afe.v_vali_cfg.vali_time[SP_V2_SPKR_2];
-
+ th_vi_v_vali_cfg->num_ch = this_afe.num_spkrs;
+ for (i = 0; i < this_afe.num_spkrs; i++) {
+ ch_v_vali_cfg[i].wait_time_ms =
+ this_afe.v_vali_cfg.wait_time[i];
+ ch_v_vali_cfg[i].vali_time_ms =
+ this_afe.v_vali_cfg.vali_time[i];
+ }
if (afe_spk_prot_prepare(port_id, 0,
AFE_PARAM_ID_SP_V4_TH_VI_V_VALI_CFG,
(union afe_spkr_prot_config *)tmp_ptr, size))
@@ -2492,7 +2556,7 @@ static void afe_send_cal_spv4_tx(int port_id)
(this_afe.vi_tx_port == port_id) &&
(this_afe.prot_cfg.sp_version >= AFE_API_VERSION_V9)) {
size = sizeof(struct afe_sp_v4_param_ex_vi_ftm_cfg) +
- (SP_V2_NUM_MAX_SPKRS *
+ (this_afe.num_spkrs *
sizeof(struct afe_sp_v4_channel_ex_vi_ftm));
tmp_ptr = kzalloc(size, GFP_KERNEL);
if (!tmp_ptr) {
@@ -2514,17 +2578,14 @@ static void afe_send_cal_spv4_tx(int port_id)
sizeof(struct afe_sp_v4_param_ex_vi_mode_cfg)))
pr_info("%s: ex vi mode cfg failed\n", __func__);
- ex_vi_ftm_cfg->num_ch = SP_V2_NUM_MAX_SPKRS;
-
- ch_ex_vi_ftm_cfg[SP_V2_SPKR_1].wait_time_ms =
- this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_1];
- ch_ex_vi_ftm_cfg[SP_V2_SPKR_2].wait_time_ms =
- this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_2];
- ch_ex_vi_ftm_cfg[SP_V2_SPKR_1].ftm_time_ms =
- this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_1];
- ch_ex_vi_ftm_cfg[SP_V2_SPKR_2].ftm_time_ms =
- this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_2];
+ ex_vi_ftm_cfg->num_ch = this_afe.num_spkrs;
+ for (i = 0; i < this_afe.num_spkrs; i++) {
+ ch_ex_vi_ftm_cfg[i].wait_time_ms =
+ this_afe.ex_ftm_cfg.wait_time[i];
+ ch_ex_vi_ftm_cfg[i].ftm_time_ms =
+ this_afe.ex_ftm_cfg.ftm_time[i];
+ }
if (afe_spk_prot_prepare(port_id, 0,
AFE_PARAM_ID_SP_V4_EX_VI_FTM_CFG,
(union afe_spkr_prot_config *)tmp_ptr, size))
@@ -2954,7 +3015,7 @@ static int afe_send_port_topology_id(u16 port_id)
}
ret = afe_get_cal_topology_id(port_id, &topology_id, AFE_TOPOLOGY_CAL);
- if (ret < 0) {
+ if (ret < 0 && q6afe_is_afe_lsm_port(port_id)) {
pr_debug("%s: Check for LSM topology\n", __func__);
ret = afe_get_cal_topology_id(port_id, &topology_id,
AFE_LSM_TOPOLOGY_CAL);
@@ -3291,7 +3352,7 @@ static int send_afe_cal_type(int cal_index, int port_id)
this_afe.cal_data[cal_index]);
if (cal_block == NULL || cal_utils_is_cal_stale(cal_block)) {
- pr_err("%s cal_block not found!!\n", __func__);
+ pr_err_ratelimited("%s cal_block not found!!\n", __func__);
ret = -EINVAL;
goto unlock;
}
@@ -3327,7 +3388,7 @@ void afe_send_cal(u16 port_id)
if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) {
afe_send_cal_spkr_prot_tx(port_id);
ret = send_afe_cal_type(AFE_COMMON_TX_CAL, port_id);
- if (ret < 0)
+ if (ret < 0 && q6afe_is_afe_lsm_port(port_id))
send_afe_cal_type(AFE_LSM_TX_CAL, port_id);
} else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) {
send_afe_cal_type(AFE_COMMON_RX_CAL, port_id);
@@ -5277,6 +5338,11 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
afe_send_hw_delay(port_id, rate);
}
+ if ((this_afe.cps_config) &&
+ (this_afe.vi_rx_port == port_id)) {
+ afe_send_cps_config(port_id);
+ }
+
/* Start SW MAD module */
mad_type = afe_port_get_mad_type(port_id);
pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
@@ -8432,8 +8498,11 @@ int afe_close(int port_id)
* even if ramp down configuration failed it is not serious enough to
* warrant bailaing out.
*/
- if (afe_spk_ramp_dn_cfg(port_id) < 0)
- pr_err("%s: ramp down configuration failed\n", __func__);
+ if (q6core_get_avcs_api_version_per_service(
+ APRV2_IDS_SERVICE_ID_ADSP_AFE_V) < AFE_API_VERSION_V9) {
+ if (afe_spk_ramp_dn_cfg(port_id) < 0)
+ pr_err("%s: ramp down config failed\n", __func__);
+ }
stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
@@ -9574,6 +9643,7 @@ int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
this_afe.v4_ch_map_cfg.chan_info[index++] = 4;
}
this_afe.v4_ch_map_cfg.num_channels = index;
+ this_afe.num_spkrs = index / 2;
pr_debug("%s no of channels: %d\n", __func__, index);
this_afe.vi_tx_port = src_port;
this_afe.vi_rx_port = dst_port;
@@ -10609,6 +10679,8 @@ int __init afe_init(void)
init_waitqueue_head(&this_afe.wait_wakeup);
init_waitqueue_head(&this_afe.lpass_core_hw_wait);
init_waitqueue_head(&this_afe.clk_wait);
+ for (i = 0; i < MAX_LSM_SESSIONS; i++)
+ this_afe.lsm_afe_ports[i] = 0xffff;
ret = afe_init_cal_data();
if (ret)
pr_err("%s: could not init cal data! %d\n", __func__, ret);
@@ -10816,3 +10888,61 @@ done:
return ret;
}
EXPORT_SYMBOL(afe_unvote_lpass_core_hw);
+
+/**
+ * afe_set_cps_config -
+ * to set cps speaker protection configuration
+ *
+ * @src_port: source port to send configuration to
+ * @cps_config: cps speaker protection v4 configuration
+ * @ch_mask: channel mask
+ *
+ */
+void afe_set_cps_config(int src_port,
+ struct afe_cps_hw_intf_cfg *cps_config,
+ u32 ch_mask)
+{
+ this_afe.cps_config = NULL;
+ this_afe.cps_ch_mask = 0;
+
+ if (!cps_config) {
+ pr_err("%s: cps config is NULL\n", __func__);
+ return;
+ }
+
+ if (q6audio_validate_port(src_port) < 0) {
+ pr_err("%s: Invalid src port 0x%x\n", __func__, src_port);
+ return;
+ }
+
+ this_afe.cps_ch_mask = ch_mask;
+ this_afe.cps_config = cps_config;
+}
+EXPORT_SYMBOL(afe_set_cps_config);
+
+static bool q6afe_is_afe_lsm_port(int port_id)
+{
+ int i = 0;
+
+ for (i = 0; i < MAX_LSM_SESSIONS; i++) {
+ if (port_id == this_afe.lsm_afe_ports[i])
+ return true;
+ }
+ return false;
+}
+
+/**
+ * afe_set_lsm_afe_port_id -
+ * Update LSM AFE port
+ * idx: LSM port index
+ * lsm_port: LSM port id
+*/
+void afe_set_lsm_afe_port_id(int idx, int lsm_port)
+{
+ if (idx < 0 || idx >= MAX_LSM_SESSIONS) {
+ pr_err("%s: %d Invalid lsm port index\n", __func__, idx);
+ return;
+ }
+ this_afe.lsm_afe_ports[idx] = lsm_port;
+}
+EXPORT_SYMBOL(afe_set_lsm_afe_port_id);
diff --git a/dsp/q6asm.c b/dsp/q6asm.c
index 235cdbd4..2939599d 100644
--- a/dsp/q6asm.c
+++ b/dsp/q6asm.c
@@ -8486,6 +8486,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
if (mmap_region_cmd == NULL) {
rc = -EINVAL;
kfree(buffer_node);
+ buffer_node = NULL;
return rc;
}
mmap_regions = (struct avs_cmd_shared_mem_map_regions *)
@@ -8522,6 +8523,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
mmap_regions->hdr.opcode, rc);
rc = -EINVAL;
kfree(buffer_node);
+ buffer_node = NULL;
goto fail_cmd;
}
@@ -8533,6 +8535,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
pr_err("%s: timeout. waited for memory_map\n", __func__);
rc = -ETIMEDOUT;
kfree(buffer_node);
+ buffer_node = NULL;
goto fail_cmd;
}
if (atomic_read(&ac->mem_state) > 0) {
@@ -8542,6 +8545,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
rc = adsp_err_get_lnx_err_code(
atomic_read(&ac->mem_state));
kfree(buffer_node);
+ buffer_node = NULL;
goto fail_cmd;
}
mutex_lock(&ac->cmd_lock);
@@ -8561,6 +8565,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
rc = 0;
fail_cmd:
kfree(mmap_region_cmd);
+ mmap_region_cmd = NULL;
return rc;
}
EXPORT_SYMBOL(q6asm_memory_map_regions);
@@ -8656,6 +8661,7 @@ fail_cmd:
if (buf_node->buf_phys_addr == buf_add) {
list_del(&buf_node->list);
kfree(buf_node);
+ buf_node = NULL;
break;
}
}
diff --git a/dsp/q6lsm.c b/dsp/q6lsm.c
index cc57a253..857dad3f 100644
--- a/dsp/q6lsm.c
+++ b/dsp/q6lsm.c
@@ -2436,6 +2436,7 @@ int q6lsm_get_one_param(struct lsm_client *client,
{
struct param_hdr_v3 param_info;
int rc = 0;
+ bool iid_supported = q6common_is_instance_id_supported();
memset(&param_info, 0, sizeof(param_info));
@@ -2444,7 +2445,12 @@ int q6lsm_get_one_param(struct lsm_client *client,
param_info.module_id = p_info->module_id;
param_info.instance_id = p_info->instance_id;
param_info.param_id = p_info->param_id;
- param_info.param_size = p_info->param_size + sizeof(param_info);
+
+ if (iid_supported)
+ param_info.param_size = p_info->param_size + sizeof(struct param_hdr_v3);
+ else
+ param_info.param_size = p_info->param_size + sizeof(struct param_hdr_v2);
+
rc = q6lsm_get_params(client, NULL, &param_info);
if (rc) {
pr_err("%s: LSM_GET_CUSTOM_PARAMS failed, rc %d\n",
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index eed5652f..dc51307a 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -10,6 +10,9 @@
#include <ipc/apr.h>
#include <linux/msm_audio.h>
+/* number of threshold levels in speaker protection module */
+#define MAX_CPS_LEVELS 3
+
/* size of header needed for passing data out of band */
#define APR_CMD_OB_HDR_SZ 12
@@ -2364,6 +2367,28 @@ int16_t excursionf[AFE_SPKR_PROT_EXCURSIONF_LEN];
*/
} __packed;
+struct lpass_swr_spkr_dep_cfg_t {
+ uint32_t vbatt_pkd_reg_addr;
+ uint32_t temp_pkd_reg_addr;
+ uint32_t value_normal_thrsd[MAX_CPS_LEVELS];
+ uint32_t value_low1_thrsd[MAX_CPS_LEVELS];
+ uint32_t value_low2_thrsd[MAX_CPS_LEVELS];
+} __packed;
+
+struct lpass_swr_hw_reg_cfg_t {
+ uint32_t lpass_wr_cmd_reg_phy_addr;
+ uint32_t lpass_rd_cmd_reg_phy_addr;
+ uint32_t lpass_rd_fifo_reg_phy_addr;
+ uint32_t vbatt_lower1_threshold;
+ uint32_t vbatt_lower2_threshold;
+ uint32_t num_spkr;
+} __packed;
+
+struct afe_cps_hw_intf_cfg {
+ uint32_t lpass_hw_intf_cfg_mode;
+ struct lpass_swr_hw_reg_cfg_t hw_reg_cfg;
+ struct lpass_swr_spkr_dep_cfg_t *spkr_dep_cfg;
+} __packed;
#define AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER 0x000100E0
@@ -10784,6 +10809,7 @@ struct cmd_set_topologies {
#define AFE_PARAM_ID_FBSP_MODE_RX_CFG 0x0001021D
#define AFE_PARAM_ID_FBSP_PTONE_RAMP_CFG 0x00010260
#define AFE_PARAM_ID_SP_RX_TMAX_XMAX_LOGGING 0x000102BC
+#define AFE_PARAM_ID_CPS_LPASS_HW_INTF_CFG 0x000102EF
struct asm_fbsp_mode_rx_cfg {
uint32_t minor_version;
diff --git a/include/dsp/audio_cal_utils.h b/include/dsp/audio_cal_utils.h
index 06078150..99f619f2 100644
--- a/include/dsp/audio_cal_utils.h
+++ b/include/dsp/audio_cal_utils.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2014, 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2018, 2020, The Linux Foundation. All rights reserved.
*/
#ifndef _AUDIO_CAL_UTILS_H
#define _AUDIO_CAL_UTILS_H
@@ -95,4 +95,6 @@ int32_t cal_utils_get_cal_type_version(void *cal_type_data);
void cal_utils_mark_cal_used(struct cal_block_data *cal_block);
bool cal_utils_is_cal_stale(struct cal_block_data *cal_block);
+
+int cal_utils_init(void);
#endif
diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h
index 8b82069a..bd2cba69 100644
--- a/include/dsp/q6afe-v2.h
+++ b/include/dsp/q6afe-v2.h
@@ -432,6 +432,9 @@ int afe_pseudo_port_start_nowait(u16 port_id);
int afe_pseudo_port_stop_nowait(u16 port_id);
int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg);
int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg);
+void afe_set_cps_config(int src_port,
+ struct afe_cps_hw_intf_cfg *cps_config,
+ u32 ch_mask);
int afe_set_lpass_clk_cfg(int index, struct afe_clk_set *cfg);
int afe_set_digital_codec_core_clock(u16 port_id,
struct afe_digital_clk_cfg *cfg);
@@ -496,6 +499,7 @@ int afe_get_doa_tracking_mon(u16 port_id,
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);
+void afe_set_lsm_afe_port_id(int idx, int lsm_port);
enum {
AFE_LPASS_CORE_HW_BLOCK_ID_NONE,
diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c
index 7bf2f9a6..385e59fa 100644
--- a/soc/swr-mstr-ctrl.c
+++ b/soc/swr-mstr-ctrl.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/irq.h>
@@ -104,6 +104,7 @@ static void swrm_unlock_sleep(struct swr_mstr_ctrl *swrm);
static u32 swr_master_read(struct swr_mstr_ctrl *swrm, unsigned int reg_addr);
static void swr_master_write(struct swr_mstr_ctrl *swrm, u16 reg_addr, u32 val);
static int swrm_runtime_resume(struct device *dev);
+static void swrm_wait_for_fifo_avail(struct swr_mstr_ctrl *swrm, int swrm_rd_wr);
static u8 swrm_get_clk_div(int mclk_freq, int bus_clk_freq)
{
@@ -627,6 +628,9 @@ static int swr_master_bulk_write(struct swr_mstr_ctrl *swrm, u32 *reg_addr,
* This still meets the hardware spec
*/
usleep_range(50, 55);
+ if (reg_addr[i] == SWRM_CMD_FIFO_WR_CMD)
+ swrm_wait_for_fifo_avail(swrm,
+ SWRM_WR_CHECK_AVAIL);
swr_master_write(swrm, reg_addr[i], val[i]);
}
usleep_range(100, 110);
@@ -1755,10 +1759,12 @@ static void swrm_enable_slave_irq(struct swr_mstr_ctrl *swrm)
dev_dbg(swrm->dev, "%s: slave status: 0x%x\n", __func__, status);
for (i = 0; i < (swrm->master.num_dev + 1); i++) {
if (status & SWRM_MCP_SLV_STATUS_MASK) {
- swrm_cmd_fifo_rd_cmd(swrm, &temp, i, 0x0,
+ if (!swrm->clk_stop_wakeup) {
+ swrm_cmd_fifo_rd_cmd(swrm, &temp, i, 0x0,
SWRS_SCP_INT_STATUS_CLEAR_1, 1);
- swrm_cmd_fifo_wr_cmd(swrm, 0xFF, i, 0x0,
+ swrm_cmd_fifo_wr_cmd(swrm, 0xFF, i, 0x0,
SWRS_SCP_INT_STATUS_CLEAR_1);
+ }
swrm_cmd_fifo_wr_cmd(swrm, 0x4, i, 0x0,
SWRS_SCP_INT_STATUS_MASK_1);
}
@@ -2170,7 +2176,9 @@ handle_irq:
* re-enable Host IRQ and process slave pending
* interrupts, if any.
*/
+ swrm->clk_stop_wakeup = true;
swrm_enable_slave_irq(swrm);
+ swrm->clk_stop_wakeup = false;
}
break;
default:
@@ -2741,6 +2749,8 @@ static int swrm_probe(struct platform_device *pdev)
swrm->dev_up = true;
swrm->state = SWR_MSTR_UP;
swrm->ipc_wakeup = false;
+ swrm->enable_slave_irq = false;
+ swrm->clk_stop_wakeup = false;
swrm->ipc_wakeup_triggered = false;
swrm->disable_div2_clk_switch = FALSE;
init_completion(&swrm->reset);
@@ -3093,7 +3103,7 @@ exit:
swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false);
if (!hw_core_err)
swrm_request_hw_vote(swrm, LPASS_HW_CORE, false);
- if (swrm_clk_req_err)
+ if (swrm_clk_req_err || aud_core_err || hw_core_err)
pm_runtime_set_autosuspend_delay(&pdev->dev,
ERR_AUTO_SUSPEND_TIMER_VAL);
else
@@ -3123,6 +3133,10 @@ static int swrm_runtime_suspend(struct device *dev)
__func__, swrm->state);
dev_dbg(dev, "%s: pm_runtime: suspend state: %d\n",
__func__, swrm->state);
+ if (swrm->state == SWR_MSTR_SSR_RESET) {
+ swrm->state = SWR_MSTR_SSR;
+ return 0;
+ }
mutex_lock(&swrm->reslock);
mutex_lock(&swrm->force_down_lock);
current_state = swrm->state;
@@ -3477,6 +3491,18 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
dev_err(swrm->dev, "%s: clock voting not zero\n",
__func__);
+ if (swrm->state == SWR_MSTR_UP ||
+ pm_runtime_autosuspend_expiration(swrm->dev)) {
+ swrm->state = SWR_MSTR_SSR_RESET;
+ dev_dbg(swrm->dev,
+ "%s:suspend swr if active at SSR up\n",
+ __func__);
+ pm_runtime_set_autosuspend_delay(swrm->dev,
+ ERR_AUTO_SUSPEND_TIMER_VAL);
+ usleep_range(50000, 50100);
+ swrm->state = SWR_MSTR_SSR;
+ }
+
mutex_lock(&swrm->devlock);
swrm->dev_up = true;
mutex_unlock(&swrm->devlock);
diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h
index f5365923..1b707166 100644
--- a/soc/swr-mstr-ctrl.h
+++ b/soc/swr-mstr-ctrl.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SWR_WCD_CTRL_H
@@ -51,6 +51,7 @@ enum {
SWR_MSTR_UP,
SWR_MSTR_DOWN,
SWR_MSTR_SSR,
+ SWR_MSTR_SSR_RESET,
};
enum swrm_pm_state {
@@ -185,6 +186,7 @@ struct swr_mstr_ctrl {
u32 rd_fifo_depth;
u32 wr_fifo_depth;
bool enable_slave_irq;
+ bool clk_stop_wakeup;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_swrm_dent;
struct dentry *debugfs_peek;