Merge "ASoC: wcd938x: Update routing for HDR recording"
diff --git a/asoc/codecs/audio-ext-clk-up.c b/asoc/codecs/audio-ext-clk-up.c
index 0384e71..e6e68ad 100644
--- a/asoc/codecs/audio-ext-clk-up.c
+++ b/asoc/codecs/audio-ext-clk-up.c
@@ -27,6 +27,7 @@
AUDIO_EXT_CLK_LPASS6,
AUDIO_EXT_CLK_LPASS7,
AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE,
+ AUDIO_EXT_CLK_LPASS8,
AUDIO_EXT_CLK_LPASS_MAX,
AUDIO_EXT_CLK_EXTERNAL_PLL = AUDIO_EXT_CLK_LPASS_MAX,
AUDIO_EXT_CLK_MAX,
@@ -326,6 +327,17 @@
.mult = 1,
.div = 1,
.hw.init = &(struct clk_init_data){
+ .name = "audio_lpass_mclk8",
+ .ops = &audio_ext_clk_ops,
+ },
+ },
+ },
+ {
+ .pnctrl_info = {NULL},
+ .fact = {
+ .mult = 1,
+ .div = 1,
+ .hw.init = &(struct clk_init_data){
.name = "audio_external_pll_clk",
.ops = &audio_ext_clk_ops,
},
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index 7bf6295..217fa5f 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -1049,13 +1049,11 @@
{
struct bolero_priv *priv = dev_get_drvdata(dev->parent);
- mutex_lock(&priv->clk_lock);
if (priv->lpass_core_hw_vote != NULL)
clk_disable_unprepare(priv->lpass_core_hw_vote);
else
dev_dbg(dev, "%s: Invalid lpass core hw node\n",
__func__);
- mutex_unlock(&priv->clk_lock);
return 0;
}
EXPORT_SYMBOL(bolero_runtime_suspend);
diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index 58f3689..98ee1e7 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -691,7 +691,7 @@
CF_MIN_3DB_150HZ) {
schedule_delayed_work(
&tx_priv->tx_hpf_work[decimator].dwork,
- msecs_to_jiffies(300));
+ msecs_to_jiffies(50));
snd_soc_component_update_bits(component,
hpf_gate_reg, 0x02, 0x02);
/*
diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c
index f8df0b7..8789fce 100644
--- a/asoc/codecs/bolero/va-macro.c
+++ b/asoc/codecs/bolero/va-macro.c
@@ -595,7 +595,7 @@
CF_MIN_3DB_150HZ)
schedule_delayed_work(
&va_priv->va_hpf_work[decimator].dwork,
- msecs_to_jiffies(300));
+ msecs_to_jiffies(50));
/* apply gain after decimator is enabled */
snd_soc_component_write(component, tx_gain_ctl_reg,
snd_soc_component_read32(component, tx_gain_ctl_reg));
@@ -1632,7 +1632,7 @@
}
va_io_base = devm_ioremap(&pdev->dev, va_base_addr,
- VA_MAX_OFFSET);
+ VA_MACRO_MAX_OFFSET);
if (!va_io_base) {
dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
return -EINVAL;
diff --git a/asoc/codecs/wcd-clsh.c b/asoc/codecs/wcd-clsh.c
index fd30148..0f403ac 100644
--- a/asoc/codecs/wcd-clsh.c
+++ b/asoc/codecs/wcd-clsh.c
@@ -219,6 +219,9 @@
if ((enable && (++clsh_d->flyback_users == 1)) ||
(!enable && (--clsh_d->flyback_users == 0))) {
snd_soc_component_update_bits(component,
+ WCD9XXX_FLYBACK_VNEG_CTRL_1,
+ 0xE0, 0xE0);
+ snd_soc_component_update_bits(component,
WCD9XXX_ANA_RX_SUPPLIES,
(1 << 6), (enable << 6));
/*
diff --git a/asoc/codecs/wcd-spi.c b/asoc/codecs/wcd-spi.c
index 35b0d93..145c4df 100644
--- a/asoc/codecs/wcd-spi.c
+++ b/asoc/codecs/wcd-spi.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*/
#include <linux/init.h>
@@ -8,6 +8,7 @@
#include <linux/of.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/bitops.h>
#include <linux/spi/spi.h>
#include <linux/regmap.h>
@@ -152,6 +153,10 @@
/* Buffers to hold memory used for transfers */
void *tx_buf;
void *rx_buf;
+
+ /* DMA handles for transfer buffers */
+ dma_addr_t tx_dma;
+ dma_addr_t rx_dma;
};
enum xfer_request {
@@ -1371,17 +1376,20 @@
spi_message_add_tail(&wcd_spi->xfer2[1], &wcd_spi->msg2);
/* Pre-allocate the buffers */
- wcd_spi->tx_buf = kzalloc(WCD_SPI_RW_MAX_BUF_SIZE,
- GFP_KERNEL | GFP_DMA);
+ wcd_spi->tx_buf = dma_zalloc_coherent(&spi->dev,
+ WCD_SPI_RW_MAX_BUF_SIZE,
+ &wcd_spi->tx_dma, GFP_KERNEL);
if (!wcd_spi->tx_buf) {
ret = -ENOMEM;
goto done;
}
- wcd_spi->rx_buf = kzalloc(WCD_SPI_RW_MAX_BUF_SIZE,
- GFP_KERNEL | GFP_DMA);
+ wcd_spi->rx_buf = dma_zalloc_coherent(&spi->dev,
+ WCD_SPI_RW_MAX_BUF_SIZE,
+ &wcd_spi->rx_dma, GFP_KERNEL);
if (!wcd_spi->rx_buf) {
- kfree(wcd_spi->tx_buf);
+ dma_free_coherent(&spi->dev, WCD_SPI_RW_MAX_BUF_SIZE,
+ wcd_spi->tx_buf, wcd_spi->tx_dma);
wcd_spi->tx_buf = NULL;
ret = -ENOMEM;
goto done;
@@ -1408,8 +1416,10 @@
spi_transfer_del(&wcd_spi->xfer2[0]);
spi_transfer_del(&wcd_spi->xfer2[1]);
- kfree(wcd_spi->tx_buf);
- kfree(wcd_spi->rx_buf);
+ dma_free_coherent(&spi->dev, WCD_SPI_RW_MAX_BUF_SIZE,
+ wcd_spi->tx_buf, wcd_spi->tx_dma);
+ dma_free_coherent(&spi->dev, WCD_SPI_RW_MAX_BUF_SIZE,
+ wcd_spi->rx_buf, wcd_spi->rx_dma);
wcd_spi->tx_buf = NULL;
wcd_spi->rx_buf = NULL;
}
@@ -1445,6 +1455,7 @@
mutex_init(&wcd_spi->xfer_mutex);
INIT_DELAYED_WORK(&wcd_spi->clk_dwork, wcd_spi_clk_work);
init_completion(&wcd_spi->resume_comp);
+ arch_setup_dma_ops(&spi->dev, 0, 0, NULL, true);
wcd_spi->spi = spi;
spi_set_drvdata(spi, wcd_spi);
diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c
index beb4b17..0836bc0 100644
--- a/asoc/codecs/wcd937x/wcd937x.c
+++ b/asoc/codecs/wcd937x/wcd937x.c
@@ -567,6 +567,8 @@
WCD937X_DIGITAL_CDC_COMP_CTL_0,
0x02, 0x02);
usleep_range(5000, 5010);
+ snd_soc_component_update_bits(component, WCD937X_FLYBACK_EN,
+ 0x04, 0x00);
wcd_cls_h_fsm(component, &wcd937x->clsh_info,
WCD_CLSH_EVENT_PRE_DAC,
WCD_CLSH_STATE_EAR,
@@ -942,6 +944,8 @@
WCD_CLSH_EVENT_POST_PA,
WCD_CLSH_STATE_EAR,
hph_mode);
+ snd_soc_component_update_bits(component, WCD937X_FLYBACK_EN,
+ 0x04, 0x04);
if (wcd937x->ear_rx_path & EAR_RX_PATH_AUX)
snd_soc_component_update_bits(component,
WCD937X_DIGITAL_PDM_WD_CTL2,
diff --git a/asoc/codecs/wcd938x/wcd938x-slave.c b/asoc/codecs/wcd938x/wcd938x-slave.c
index b7c0230..ec42b0d 100644
--- a/asoc/codecs/wcd938x/wcd938x-slave.c
+++ b/asoc/codecs/wcd938x/wcd938x-slave.c
@@ -22,6 +22,11 @@
uint8_t devnum = 0;
struct swr_device *pdev = to_swr_device(dev);
+ if (!pdev) {
+ pr_err("%s: invalid swr device handle\n", __func__);
+ return -EINVAL;
+ }
+
ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum);
if (ret) {
dev_dbg(&pdev->dev,
diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c
index fbc745a..8ab4a7c 100644
--- a/asoc/codecs/wcd938x/wcd938x.c
+++ b/asoc/codecs/wcd938x/wcd938x.c
@@ -177,7 +177,7 @@
u8 *port_type, u8 path)
{
int i, j;
- u8 num_ports;
+ u8 num_ports = 0;
struct codec_port_info (*map)[MAX_PORT][MAX_CH_PER_PORT];
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
@@ -190,6 +190,10 @@
map = &wcd938x->tx_port_mapping;
num_ports = wcd938x->num_tx_ports;
break;
+ default:
+ dev_err(component->dev, "%s Invalid path selected %u\n",
+ __func__, path);
+ return -EINVAL;
}
for (i = 0; i <= num_ports; i++) {
@@ -217,11 +221,11 @@
char *prop, u8 path)
{
u32 *dt_array, map_size, map_length;
- u32 port_num, ch_mask, ch_rate, old_port_num = 0;
+ u32 port_num = 0, ch_mask, ch_rate, old_port_num = 0;
u32 slave_port_type, master_port_type;
u32 i, ch_iter = 0;
int ret = 0;
- u8 *num_ports;
+ u8 *num_ports = NULL;
struct codec_port_info (*map)[MAX_PORT][MAX_CH_PER_PORT];
struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);
@@ -234,6 +238,10 @@
map = &wcd938x->tx_port_mapping;
num_ports = &wcd938x->num_tx_ports;
break;
+ default:
+ dev_err(dev, "%s Invalid path selected %u\n",
+ __func__, path);
+ return -EINVAL;
}
if (!of_find_property(dev->of_node, prop,
@@ -532,6 +540,8 @@
WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x02, 0x02);
/* 5 msec delay as per HW requirement */
usleep_range(5000, 5010);
+ snd_soc_component_update_bits(component, WCD938X_FLYBACK_EN,
+ 0x04, 0x00);
wcd_cls_h_fsm(component, &wcd938x->clsh_info,
WCD_CLSH_EVENT_PRE_DAC,
WCD_CLSH_STATE_EAR,
@@ -824,6 +834,8 @@
WCD_CLSH_EVENT_POST_PA,
WCD_CLSH_STATE_EAR,
hph_mode);
+ snd_soc_component_update_bits(component, WCD938X_FLYBACK_EN,
+ 0x04, 0x04);
break;
};
return ret;
diff --git a/asoc/kona.c b/asoc/kona.c
index fd5c9a7..704951c 100644
--- a/asoc/kona.c
+++ b/asoc/kona.c
@@ -2297,7 +2297,7 @@
{
int ch_num = cdc_dma_get_port_idx(kcontrol);
- if (ch_num < 0) {
+ if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
return ch_num;
}
@@ -2313,7 +2313,7 @@
{
int ch_num = cdc_dma_get_port_idx(kcontrol);
- if (ch_num < 0) {
+ if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
return ch_num;
}
@@ -2330,7 +2330,7 @@
{
int ch_num = cdc_dma_get_port_idx(kcontrol);
- if (ch_num < 0) {
+ if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
return ch_num;
}
@@ -2363,7 +2363,7 @@
int rc = 0;
int ch_num = cdc_dma_get_port_idx(kcontrol);
- if (ch_num < 0) {
+ if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
return ch_num;
}
@@ -2498,7 +2498,7 @@
{
int ch_num = cdc_dma_get_port_idx(kcontrol);
- if (ch_num < 0) {
+ if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
return ch_num;
}
@@ -2516,7 +2516,7 @@
{
int ch_num = cdc_dma_get_port_idx(kcontrol);
- if (ch_num < 0) {
+ if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
return ch_num;
}
diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c
index be10bc1..179a95e 100644
--- a/asoc/msm-compress-q6-v2.c
+++ b/asoc/msm-compress-q6-v2.c
@@ -363,12 +363,17 @@
}
rtd = cstream->private_data;
prtd = cstream->runtime->private_data;
- component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
- if (!rtd || !component || !prtd || !prtd->audio_client) {
+ if (!rtd || !prtd || !prtd->audio_client) {
pr_err("%s: invalid rtd, prtd or audio client", __func__);
return rc;
}
+ component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+ if (!component) {
+ pr_err("%s: invalid component\n", __func__);
+ return rc;
+ }
+
pdata = snd_soc_component_get_drvdata(component);
if (prtd->compr_passthr != LEGACY_PCM) {
@@ -1810,12 +1815,16 @@
}
runtime = cstream->runtime;
soc_prtd = cstream->private_data;
- component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
- if (!runtime || !soc_prtd || !component) {
- pr_err("%s runtime or soc_prtd or component is null\n",
+ if (!runtime || !soc_prtd) {
+ pr_err("%s runtime or soc_prtd is null\n",
__func__);
return 0;
}
+ component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
+ if (!component) {
+ pr_err("%s component is null\n", __func__);
+ return 0;
+ }
prtd = runtime->private_data;
if (!prtd) {
pr_err("%s prtd is null\n", __func__);
@@ -1913,12 +1922,16 @@
}
runtime = cstream->runtime;
soc_prtd = cstream->private_data;
- component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
- if (!runtime || !soc_prtd || !component) {
- pr_err("%s runtime or soc_prtd or component is null\n",
- __func__);
+ if (!runtime || !soc_prtd) {
+ pr_err("%s runtime or soc_prtd is null\n", __func__);
return 0;
}
+ component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
+ if (!component) {
+ pr_err("%s component is null\n", __func__);
+ return 0;
+ }
+
prtd = runtime->private_data;
if (!prtd) {
pr_err("%s prtd is null\n", __func__);
@@ -2687,13 +2700,22 @@
pr_debug("%s: open_write stream_id %d bits_per_sample %d",
__func__, stream_id, bits_per_sample);
- rc = q6asm_stream_open_write_v4(prtd->audio_client,
+
+ if (q6core_get_avcs_api_version_per_service(
+ APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
+ ADSP_ASM_API_VERSION_V2)
+ rc = q6asm_stream_open_write_v5(prtd->audio_client,
+ prtd->codec, bits_per_sample,
+ stream_id,
+ prtd->gapless_state.use_dsp_gapless_mode);
+ else
+ rc = q6asm_stream_open_write_v4(prtd->audio_client,
prtd->codec, bits_per_sample,
stream_id,
prtd->gapless_state.use_dsp_gapless_mode);
if (rc < 0) {
- pr_err("%s: Session out open failed for gapless\n",
- __func__);
+ pr_err("%s: Session out open failed for gapless [%d]\n",
+ __func__, rc);
break;
}
@@ -2788,12 +2810,10 @@
rc = q6asm_get_session_time(
prtd->audio_client, &prtd->marker_timestamp);
if (rc < 0) {
- pr_err("%s: Get Session Time return =%lld\n",
- __func__, timestamp);
if (atomic_read(&prtd->error))
return -ENETRESET;
else
- return -EAGAIN;
+ return rc;
}
}
} else {
@@ -4712,6 +4732,11 @@
chmixer_pspd->in_ch_map[i] =
pdata->ch_map[fe_id]->channel_map[i];
} else {
+ if (chmixer_pspd->input_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
+ pr_err("%s: Invalid channel count %d\n",
+ __func__, chmixer_pspd->input_channel);
+ return -EINVAL;
+ }
q6asm_map_channels(asm_ch_map,
chmixer_pspd->input_channel, false);
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
@@ -4726,6 +4751,11 @@
chmixer_pspd->out_ch_map[i] =
pdata->ch_map[fe_id]->channel_map[i];
} else {
+ if (chmixer_pspd->output_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
+ pr_err("%s: Invalid channel count %d\n",
+ __func__, chmixer_pspd->output_channel);
+ return -EINVAL;
+ }
q6asm_map_channels(asm_ch_map,
chmixer_pspd->output_channel, false);
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c
index ac23857..5803356 100644
--- a/asoc/msm-dai-q6-v2.c
+++ b/asoc/msm-dai-q6-v2.c
@@ -16,6 +16,7 @@
#include <sound/pcm_params.h>
#include <dsp/apr_audio-v2.h>
#include <dsp/q6afe-v2.h>
+#include <dsp/sp_params.h>
#include <dsp/q6core.h>
#include "msm-dai-q6-v2.h"
#include <asoc/core.h>
@@ -10538,6 +10539,17 @@
clear_bit(STATUS_PORT_STARTED, dai_data->hwfree_status);
}
+/* all ports with same WSA requirement can use this digital mute API */
+static int msm_dai_q6_spk_digital_mute(struct snd_soc_dai *dai,
+ int mute)
+{
+ int port_id = dai->id;
+
+ if (mute)
+ afe_get_sp_xt_logging_data(port_id);
+
+ return 0;
+}
static struct snd_soc_dai_ops msm_dai_q6_cdc_dma_ops = {
.prepare = msm_dai_q6_cdc_dma_prepare,
@@ -10546,6 +10558,14 @@
.set_channel_map = msm_dai_q6_cdc_dma_set_channel_map,
};
+static struct snd_soc_dai_ops msm_dai_q6_cdc_wsa_dma_ops = {
+ .prepare = msm_dai_q6_cdc_dma_prepare,
+ .hw_params = msm_dai_q6_cdc_dma_hw_params,
+ .shutdown = msm_dai_q6_cdc_dma_shutdown,
+ .set_channel_map = msm_dai_q6_cdc_dma_set_channel_map,
+ .digital_mute = msm_dai_q6_spk_digital_mute,
+};
+
static struct snd_soc_dai_driver msm_dai_q6_cdc_dma_dai[] = {
{
.playback = {
@@ -10568,7 +10588,7 @@
.rate_max = 384000,
},
.name = "WSA_CDC_DMA_RX_0",
- .ops = &msm_dai_q6_cdc_dma_ops,
+ .ops = &msm_dai_q6_cdc_wsa_dma_ops,
.id = AFE_PORT_ID_WSA_CODEC_DMA_RX_0,
.probe = msm_dai_q6_dai_cdc_dma_probe,
.remove = msm_dai_q6_dai_cdc_dma_remove,
@@ -10620,7 +10640,7 @@
.rate_max = 384000,
},
.name = "WSA_CDC_DMA_RX_1",
- .ops = &msm_dai_q6_cdc_dma_ops,
+ .ops = &msm_dai_q6_cdc_wsa_dma_ops,
.id = AFE_PORT_ID_WSA_CODEC_DMA_RX_1,
.probe = msm_dai_q6_dai_cdc_dma_probe,
.remove = msm_dai_q6_dai_cdc_dma_remove,
diff --git a/asoc/msm-lsm-client.c b/asoc/msm-lsm-client.c
index 379b5e5..b101b37 100644
--- a/asoc/msm-lsm-client.c
+++ b/asoc/msm-lsm-client.c
@@ -1390,8 +1390,8 @@
dev_dbg(rtd->dev, "%s: Starting LSM client session\n",
__func__);
if (!prtd->lsm_client->started) {
- ret = q6lsm_start(prtd->lsm_client, true);
- if (!ret) {
+ rc = q6lsm_start(prtd->lsm_client, true);
+ if (!rc) {
prtd->lsm_client->started = true;
dev_dbg(rtd->dev, "%s: LSM client session started\n",
__func__);
@@ -1407,19 +1407,19 @@
if (prtd->lsm_client->lab_enable) {
atomic_set(&prtd->read_abort, 1);
if (prtd->lsm_client->lab_started) {
- ret = q6lsm_stop_lab(prtd->lsm_client);
- if (ret)
+ rc = q6lsm_stop_lab(prtd->lsm_client);
+ if (rc)
dev_err(rtd->dev,
- "%s: stop lab failed ret %d\n",
- __func__, ret);
+ "%s: stop lab failed rc %d\n",
+ __func__, rc);
prtd->lsm_client->lab_started = false;
}
}
- ret = q6lsm_stop(prtd->lsm_client, true);
- if (!ret)
+ rc = q6lsm_stop(prtd->lsm_client, true);
+ if (!rc)
dev_dbg(rtd->dev,
"%s: LSM client session stopped %d\n",
- __func__, ret);
+ __func__, rc);
prtd->lsm_client->started = false;
}
break;
@@ -2593,6 +2593,25 @@
dev_dbg(rtd->dev, "%s\n", __func__);
if (prtd->lsm_client->started) {
+ if (prtd->lsm_client->lab_enable) {
+ atomic_set(&prtd->read_abort, 1);
+ if (prtd->lsm_client->lab_started) {
+ ret = q6lsm_stop_lab(prtd->lsm_client);
+ if (ret)
+ dev_err(rtd->dev,
+ "%s: stop lab failed ret %d\n",
+ __func__, ret);
+ prtd->lsm_client->lab_started = false;
+ }
+ if (prtd->lsm_client->lab_buffer) {
+ ret = msm_lsm_lab_buffer_alloc(prtd,
+ LAB_BUFFER_DEALLOC);
+ if (ret)
+ dev_err(rtd->dev,
+ "%s: lab buffer dealloc failed ret %d\n",
+ __func__, ret);
+ }
+ }
ret = q6lsm_stop(prtd->lsm_client, true);
if (ret)
dev_err(rtd->dev,
diff --git a/asoc/msm-pcm-loopback-v2.c b/asoc/msm-pcm-loopback-v2.c
index a686984..4834e81 100644
--- a/asoc/msm-pcm-loopback-v2.c
+++ b/asoc/msm-pcm-loopback-v2.c
@@ -809,6 +809,11 @@
if (chmixer_pspd->enable) {
if (session_type == SESSION_TYPE_RX &&
!chmixer_pspd->override_in_ch_map) {
+ if (chmixer_pspd->input_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
+ pr_err("%s: Invalid channel count %d\n",
+ __func__, chmixer_pspd->input_channel);
+ return -EINVAL;
+ }
q6asm_map_channels(asm_ch_map,
chmixer_pspd->input_channel, false);
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
@@ -817,6 +822,11 @@
reset_override_in_ch_map = true;
} else if (session_type == SESSION_TYPE_TX &&
!chmixer_pspd->override_out_ch_map) {
+ if (chmixer_pspd->output_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
+ pr_err("%s: Invalid channel count %d\n",
+ __func__, chmixer_pspd->output_channel);
+ return -EINVAL;
+ }
q6asm_map_channels(asm_ch_map,
chmixer_pspd->output_channel, false);
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c
index bea58c9..a087dd8 100644
--- a/asoc/msm-pcm-q6-v2.c
+++ b/asoc/msm-pcm-q6-v2.c
@@ -1604,7 +1604,7 @@
struct snd_soc_pcm_runtime *rtd = NULL;
struct msm_plat_data *pdata = NULL;
struct msm_pcm_channel_mixer *chmixer_pspd = NULL;
- struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_component *component = NULL;
u64 fe_id = 0;
pr_debug("%s", __func__);
@@ -1624,18 +1624,21 @@
/* update chmixer_pspd chmap cached with routing driver as well */
rtd = substream->private_data;
if (rtd) {
- fe_id = rtd->dai_link->id;
- pdata = (struct msm_plat_data *)
- dev_get_drvdata(component->dev);
- chmixer_pspd = pdata ?
- pdata->chmixer_pspd[fe_id][SESSION_TYPE_RX] : NULL;
+ component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+ if (component) {
+ fe_id = rtd->dai_link->id;
+ pdata = (struct msm_plat_data *)
+ dev_get_drvdata(component->dev);
+ chmixer_pspd = pdata ?
+ pdata->chmixer_pspd[fe_id][SESSION_TYPE_RX] : NULL;
- if (chmixer_pspd && chmixer_pspd->enable) {
- for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
- chmixer_pspd->in_ch_map[i] = prtd->channel_map[i];
- chmixer_pspd->override_in_ch_map = true;
- msm_pcm_routing_set_channel_mixer_cfg(fe_id,
- SESSION_TYPE_RX, chmixer_pspd);
+ if (chmixer_pspd && chmixer_pspd->enable) {
+ for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
+ chmixer_pspd->in_ch_map[i] = prtd->channel_map[i];
+ chmixer_pspd->override_in_ch_map = true;
+ msm_pcm_routing_set_channel_mixer_cfg(fe_id,
+ SESSION_TYPE_RX, chmixer_pspd);
+ }
}
}
}
@@ -1939,6 +1942,11 @@
chmixer_pspd->in_ch_map[i] =
pdata->ch_map[fe_id]->channel_map[i];
} else {
+ if (chmixer_pspd->input_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
+ pr_err("%s: Invalid channel count %d\n",
+ __func__, chmixer_pspd->input_channel);
+ return -EINVAL;
+ }
q6asm_map_channels(asm_ch_map,
chmixer_pspd->input_channel, false);
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
@@ -1954,6 +1962,11 @@
chmixer_pspd->out_ch_map[i] =
pdata->ch_map[fe_id]->channel_map[i];
} else {
+ if (chmixer_pspd->output_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
+ pr_err("%s: Invalid channel count %d\n",
+ __func__, chmixer_pspd->output_channel);
+ return -EINVAL;
+ }
q6asm_map_channels(asm_ch_map,
chmixer_pspd->output_channel, false);
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index f913c58..5a75609 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -1114,7 +1114,8 @@
static struct cal_block_data *msm_routing_find_topology(int path,
int app_type,
int acdb_id,
- int cal_index)
+ int cal_index,
+ bool exact)
{
struct list_head *ptr, *next;
struct cal_block_data *cal_block = NULL;
@@ -1139,9 +1140,29 @@
return cal_block;
}
}
- pr_debug("%s: Can't find topology for path %d, app %d, acdb_id %d defaulting to search by path\n",
- __func__, path, app_type, acdb_id);
- return msm_routing_find_topology_by_path(path, cal_index);
+ pr_debug("%s: Can't find topology for path %d, app %d, "
+ "acdb_id %d %s\n", __func__, path, app_type, acdb_id,
+ exact ? "fail" : "defaulting to search by path");
+ return exact ? NULL : msm_routing_find_topology_by_path(path,
+ cal_index);
+}
+
+static int msm_routing_find_topology_on_index(int session_type, int app_type,
+ int acdb_dev_id, int idx,
+ bool exact)
+{
+ int topology = -EINVAL;
+ struct cal_block_data *cal_block = NULL;
+
+ mutex_lock(&cal_data[idx]->lock);
+ cal_block = msm_routing_find_topology(session_type, app_type,
+ acdb_dev_id, idx, exact);
+ if (cal_block != NULL) {
+ topology = ((struct audio_cal_info_adm_top *)
+ cal_block->cal_info)->topology;
+ }
+ mutex_unlock(&cal_data[idx]->lock);
+ return topology;
}
/*
@@ -1153,7 +1174,6 @@
int be_id)
{
int topology = NULL_COPP_TOPOLOGY;
- struct cal_block_data *cal_block = NULL;
int app_type = 0, acdb_dev_id = 0;
pr_debug("%s: fedai_id %d, session_type %d, be_id %d\n",
@@ -1166,31 +1186,22 @@
acdb_dev_id =
fe_dai_app_type_cfg[fedai_id][session_type][be_id].acdb_dev_id;
- mutex_lock(&cal_data[ADM_TOPOLOGY_CAL_TYPE_IDX]->lock);
- cal_block = msm_routing_find_topology(session_type, app_type,
- acdb_dev_id,
- ADM_TOPOLOGY_CAL_TYPE_IDX);
- if (cal_block != NULL) {
- topology = ((struct audio_cal_info_adm_top *)
- cal_block->cal_info)->topology;
- cal_utils_mark_cal_used(cal_block);
- mutex_unlock(&cal_data[ADM_TOPOLOGY_CAL_TYPE_IDX]->lock);
- } else {
- mutex_unlock(&cal_data[ADM_TOPOLOGY_CAL_TYPE_IDX]->lock);
-
- pr_debug("%s: Check for LSM topology\n", __func__);
- mutex_lock(&cal_data[ADM_LSM_TOPOLOGY_CAL_TYPE_IDX]->lock);
- cal_block = msm_routing_find_topology(session_type, app_type,
- acdb_dev_id,
- ADM_LSM_TOPOLOGY_CAL_TYPE_IDX);
- if (cal_block != NULL) {
- topology = ((struct audio_cal_info_adm_top *)
- cal_block->cal_info)->topology;
- cal_utils_mark_cal_used(cal_block);
- }
- mutex_unlock(&cal_data[ADM_LSM_TOPOLOGY_CAL_TYPE_IDX]->lock);
+ pr_debug("%s: Check for exact LSM topology\n", __func__);
+ topology = msm_routing_find_topology_on_index(session_type,
+ app_type,
+ acdb_dev_id,
+ ADM_LSM_TOPOLOGY_CAL_TYPE_IDX,
+ true /*exact*/);
+ if (topology < 0) {
+ pr_debug("%s: Check for compatible topology\n", __func__);
+ topology = msm_routing_find_topology_on_index(session_type,
+ app_type,
+ acdb_dev_id,
+ ADM_TOPOLOGY_CAL_TYPE_IDX,
+ false /*exact*/);
+ if (topology < 0)
+ topology = NULL_COPP_TOPOLOGY;
}
-
done:
pr_debug("%s: Using topology %d\n", __func__, topology);
return topology;
diff --git a/asoc/msm-transcode-loopback-q6-v2.c b/asoc/msm-transcode-loopback-q6-v2.c
index 9980874..67bdc75 100644
--- a/asoc/msm-transcode-loopback-q6-v2.c
+++ b/asoc/msm-transcode-loopback-q6-v2.c
@@ -435,7 +435,15 @@
mutex_lock(&trans->lock);
rtd = snd_pcm_substream_chip(cstream);
+ if (!rtd) {
+ pr_err("%s: rtd is NULL\n", __func__);
+ return -EINVAL;
+ }
component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+ if (!component) {
+ pr_err("%s: component is NULL\n", __func__);
+ return -EINVAL;
+ }
pdata = snd_soc_component_get_drvdata(component);
if (cstream->direction == SND_COMPRESS_PLAYBACK) {
@@ -606,7 +614,15 @@
}
rtd = snd_pcm_substream_chip(cstream);
+ if (!rtd) {
+ pr_err("%s: rtd is NULL\n", __func__);
+ return -EINVAL;
+ }
component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+ if (!component) {
+ pr_err("%s: component is NULL\n", __func__);
+ return -EINVAL;
+ }
pdata = snd_soc_component_get_drvdata(component);
prtd = cstream->runtime->private_data;
diff --git a/asoc/sm6150.c b/asoc/sm6150.c
index 84e05c8..11bb611 100644
--- a/asoc/sm6150.c
+++ b/asoc/sm6150.c
@@ -4760,28 +4760,6 @@
afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
}
-static int msm_config_hph_en0_gpio(struct snd_soc_component *component, bool high)
-{
- struct snd_soc_card *card = component->card;
- struct msm_asoc_mach_data *pdata;
- int val;
-
- if (!card)
- return 0;
-
- pdata = snd_soc_card_get_drvdata(card);
- if (!pdata || !gpio_is_valid(pdata->hph_en0_gpio))
- return 0;
-
- val = gpio_get_value_cansleep(pdata->hph_en0_gpio);
- if ((!!val) == high)
- return 0;
-
- gpio_direction_output(pdata->hph_en0_gpio, (int)high);
-
- return 1;
-}
-
static int msm_audrx_tavil_init(struct snd_soc_pcm_runtime *rtd)
{
int ret = 0;
@@ -5103,7 +5081,6 @@
pdata->codec_root = entry;
}
tasha_codec_info_create_codec_entry(pdata->codec_root, component);
- tasha_mbhc_zdet_gpio_ctrl(msm_config_hph_en0_gpio, component);
codec_reg_done = true;
return 0;
diff --git a/dsp/Kbuild b/dsp/Kbuild
index 195502a..daf0b30 100644
--- a/dsp/Kbuild
+++ b/dsp/Kbuild
@@ -91,11 +91,16 @@
Q6_OBJS += msm_audio_ion.o
Q6_OBJS += avtimer.o
Q6_OBJS += q6_init.o
-
endif
+
+ifdef CONFIG_XT_LOGGING
+ Q6_OBJS += sp_params.o
+endif
+
ifdef CONFIG_WCD9XXX_CODEC_CORE
Q6_OBJS += audio_slimslave.o
endif
+
ifdef CONFIG_DTS_SRS_TM
Q6_OBJS += msm-dts-srs-tm-config.o
endif
diff --git a/dsp/audio_cal_utils.c b/dsp/audio_cal_utils.c
index 19c71fc..7e243e8 100644
--- a/dsp/audio_cal_utils.c
+++ b/dsp/audio_cal_utils.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*/
#include <linux/slab.h>
#include <linux/fs.h>
@@ -16,6 +16,7 @@
size_t get_cal_info_size(int32_t cal_type)
{
size_t size = 0;
+ size_t size1 = 0, size2 = 0;
switch (cal_type) {
case CVP_VOC_RX_TOPOLOGY_CAL_TYPE:
@@ -93,8 +94,11 @@
* Since get and set parameter structures are different in size
* use the maximum size of get and set parameter structure
*/
- size = max(sizeof(struct audio_cal_info_sp_th_vi_ftm_cfg),
+ size1 = max(sizeof(struct audio_cal_info_sp_th_vi_ftm_cfg),
sizeof(struct audio_cal_info_sp_th_vi_param));
+ size2 = max(sizeof(struct audio_cal_info_sp_th_vi_v_vali_cfg),
+ sizeof(struct audio_cal_info_sp_th_vi_v_vali_param));
+ size = max(size1, size2);
break;
case AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE:
/*
diff --git a/dsp/q6_init.c b/dsp/q6_init.c
index 1078c57..fb18741 100644
--- a/dsp/q6_init.c
+++ b/dsp/q6_init.c
@@ -14,6 +14,7 @@
rtac_init();
adm_init();
afe_init();
+ spk_params_init();
q6asm_init();
q6lsm_init();
voice_init();
@@ -37,6 +38,7 @@
q6lsm_exit();
q6asm_exit();
afe_exit();
+ spk_params_exit();
adm_exit();
rtac_exit();
audio_cal_exit();
diff --git a/dsp/q6_init.h b/dsp/q6_init.h
index e7ad19b..4df2e03 100644
--- a/dsp/q6_init.h
+++ b/dsp/q6_init.h
@@ -30,6 +30,18 @@
return;
}
#endif
+#ifdef CONFIG_XT_LOGGING
+int spk_params_init(void);
+void spk_params_exit(void);
+#else
+static inline int spk_params_init(void)
+{
+ return 0;
+}
+static inline void spk_params_exit(void)
+{
+}
+#endif
void avtimer_exit(void);
void msm_audio_ion_exit(void);
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index 62d4851..fd66571 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -59,6 +59,16 @@
[FBSP_FAILED] = "failed"
};
+enum v_vali_state {
+ V_VALI_FAILED,
+ V_VALI_SUCCESS,
+ V_VALI_INCORRECT_OP_MODE,
+ V_VALI_INACTIVE,
+ V_VALI_WARMUP,
+ V_VALI_IN_PROGRESS,
+ MAX_V_VALI_STATE
+};
+
enum {
USE_CALIBRATED_R0TO,
USE_SAFE_R0TO
@@ -72,7 +82,8 @@
enum {
Q6AFE_MSM_SPKR_PROCESSING = 0,
Q6AFE_MSM_SPKR_CALIBRATION,
- Q6AFE_MSM_SPKR_FTM_MODE
+ Q6AFE_MSM_SPKR_FTM_MODE,
+ Q6AFE_MSM_SPKR_V_VALI_MODE
};
enum {
@@ -124,9 +135,12 @@
struct audio_cal_info_spk_prot_cfg prot_cfg;
struct afe_spkr_prot_calib_get_resp calib_data;
struct audio_cal_info_sp_th_vi_ftm_cfg th_ftm_cfg;
+ struct audio_cal_info_sp_th_vi_v_vali_cfg v_vali_cfg;
struct audio_cal_info_sp_ex_vi_ftm_cfg ex_ftm_cfg;
struct afe_sp_th_vi_get_param_resp th_vi_resp;
+ struct afe_sp_th_vi_v_vali_get_param_resp th_vi_v_vali_resp;
struct afe_sp_ex_vi_get_param_resp ex_vi_resp;
+ struct afe_sp_rx_tmax_xmax_logging_resp xt_logging_resp;
struct afe_av_dev_drift_get_param_resp av_dev_drift_resp;
struct afe_doa_tracking_mon_get_param_resp doa_tracking_mon_resp;
int vi_tx_port;
@@ -144,6 +158,9 @@
struct vad_config vad_cfg[AFE_MAX_PORTS];
struct work_struct afe_dc_work;
struct notifier_block event_notifier;
+ /* FTM spk params */
+ uint32_t initial_cal;
+ uint32_t v_vali_flag;
};
static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
@@ -165,6 +182,51 @@
struct audio_cal_hw_delay_entry *entry);
static int remap_cal_data(struct cal_block_data *cal_block, int cal_index);
+int afe_get_spk_initial_cal(void)
+{
+ return this_afe.initial_cal;
+}
+
+void afe_get_spk_r0(int *spk_r0)
+{
+ uint16_t i = 0;
+
+ for (; i < SP_V2_NUM_MAX_SPKRS; i++)
+ spk_r0[i] = this_afe.prot_cfg.r0[i];
+}
+
+void afe_get_spk_t0(int *spk_t0)
+{
+ uint16_t i = 0;
+
+ for (; i < SP_V2_NUM_MAX_SPKRS; i++)
+ spk_t0[i] = this_afe.prot_cfg.t0[i];
+}
+
+int afe_get_spk_v_vali_flag(void)
+{
+ return this_afe.v_vali_flag;
+}
+
+void afe_get_spk_v_vali_sts(int *spk_v_vali_sts)
+{
+ uint16_t i = 0;
+
+ for (; i < SP_V2_NUM_MAX_SPKRS; i++)
+ spk_v_vali_sts[i] =
+ this_afe.th_vi_v_vali_resp.param.status[i];
+}
+
+void afe_set_spk_initial_cal(int initial_cal)
+{
+ this_afe.initial_cal = initial_cal;
+}
+
+void afe_set_spk_v_vali_flag(int v_vali_flag)
+{
+ this_afe.v_vali_flag = v_vali_flag;
+}
+
int afe_get_topology(int port_id)
{
int topology;
@@ -364,10 +426,19 @@
expected_size += sizeof(struct afe_sp_th_vi_ftm_params);
data_dest = (u32 *) &this_afe.th_vi_resp;
break;
+ case AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_PARAMS:
+ expected_size += sizeof(struct afe_sp_th_vi_v_vali_params);
+ data_dest = (u32 *) &this_afe.th_vi_v_vali_resp;
+ break;
case AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS:
expected_size += sizeof(struct afe_sp_ex_vi_ftm_params);
data_dest = (u32 *) &this_afe.ex_vi_resp;
break;
+ case AFE_PARAM_ID_SP_RX_TMAX_XMAX_LOGGING:
+ expected_size += sizeof(
+ struct afe_sp_rx_tmax_xmax_logging_param);
+ data_dest = (u32 *) &this_afe.xt_logging_resp;
+ break;
default:
pr_err("%s: Unrecognized param ID %d\n", __func__,
param_hdr.param_id);
@@ -1606,10 +1677,12 @@
break;
/*
* AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2 is same as
- * AFE_PARAM_ID_SP_V2_TH_VI_MODE_CFG
+ * AFE_PARAM_ID_SP_V2_TH_VI_MODE_CFG. V_VALI_CFG uses
+ * same module TH_VI.
*/
case AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG_V2:
case AFE_PARAM_ID_SP_V2_TH_VI_FTM_CFG:
+ case AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_CFG:
param_info.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
break;
case AFE_PARAM_ID_SP_V2_EX_VI_MODE_CFG:
@@ -1737,6 +1810,10 @@
if (this_afe.th_ftm_cfg.mode == MSM_SPKR_PROT_IN_FTM_MODE)
afe_spk_config.vi_proc_cfg.operation_mode =
Q6AFE_MSM_SPKR_FTM_MODE;
+ else if (this_afe.v_vali_cfg.mode ==
+ MSM_SPKR_PROT_IN_V_VALI_MODE)
+ afe_spk_config.vi_proc_cfg.operation_mode =
+ Q6AFE_MSM_SPKR_V_VALI_MODE;
afe_spk_config.vi_proc_cfg.minor_version = 1;
afe_spk_config.vi_proc_cfg.r0_cali_q24[SP_V2_SPKR_1] =
(uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_1];
@@ -1789,6 +1866,25 @@
&afe_spk_config))
pr_err("%s: th vi ftm cfg failed\n", __func__);
this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
+ } else if ((this_afe.v_vali_cfg.mode ==
+ MSM_SPKR_PROT_IN_V_VALI_MODE) &&
+ (this_afe.vi_tx_port == port_id)) {
+ afe_spk_config.th_vi_v_vali_cfg.minor_version = 1;
+ afe_spk_config.th_vi_v_vali_cfg.wait_time_ms[SP_V2_SPKR_1] =
+ this_afe.v_vali_cfg.wait_time[SP_V2_SPKR_1];
+ afe_spk_config.th_vi_v_vali_cfg.wait_time_ms[SP_V2_SPKR_2] =
+ this_afe.v_vali_cfg.wait_time[SP_V2_SPKR_2];
+ afe_spk_config.th_vi_v_vali_cfg.vali_time_ms[SP_V2_SPKR_1] =
+ this_afe.v_vali_cfg.vali_time[SP_V2_SPKR_1];
+ afe_spk_config.th_vi_v_vali_cfg.vali_time_ms[SP_V2_SPKR_2] =
+ this_afe.v_vali_cfg.vali_time[SP_V2_SPKR_2];
+
+ if (afe_spk_prot_prepare(port_id, 0,
+ AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_CFG,
+ &afe_spk_config))
+ pr_err("%s: th vi v-vali cfg failed\n", __func__);
+
+ this_afe.v_vali_cfg.mode = MSM_SPKR_PROT_DISABLED;
}
mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
@@ -7453,6 +7549,46 @@
}
EXPORT_SYMBOL(q6afe_check_osr_clk_freq);
+static int afe_get_sp_th_vi_v_vali_data(
+ struct afe_sp_th_vi_v_vali_get_param *th_vi_v_vali)
+{
+ struct param_hdr_v3 param_hdr;
+ int port = SLIMBUS_4_TX;
+ int ret = -EINVAL;
+
+ if (!th_vi_v_vali) {
+ pr_err("%s: Invalid params\n", __func__);
+ goto done;
+ }
+ if (this_afe.vi_tx_port != -1)
+ port = this_afe.vi_tx_port;
+
+ memset(¶m_hdr, 0, sizeof(param_hdr));
+
+ param_hdr.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
+ param_hdr.instance_id = INSTANCE_ID_0;
+ param_hdr.param_id = AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_PARAMS;
+ param_hdr.param_size = sizeof(struct afe_sp_th_vi_v_vali_params);
+
+ ret = q6afe_get_params(port, NULL, ¶m_hdr);
+ if (ret) {
+ pr_err("%s: Failed to get TH VI V-Vali data\n", __func__);
+ goto done;
+ }
+
+ th_vi_v_vali->pdata = param_hdr;
+ memcpy(&th_vi_v_vali->param, &this_afe.th_vi_v_vali_resp.param,
+ sizeof(this_afe.th_vi_v_vali_resp.param));
+ pr_debug("%s: Vrms %d %d status %d %d\n", __func__,
+ th_vi_v_vali->param.vrms_q24[SP_V2_SPKR_1],
+ th_vi_v_vali->param.vrms_q24[SP_V2_SPKR_2],
+ th_vi_v_vali->param.status[SP_V2_SPKR_1],
+ th_vi_v_vali->param.status[SP_V2_SPKR_2]);
+ ret = 0;
+done:
+ return ret;
+}
+
int afe_get_sp_th_vi_ftm_data(struct afe_sp_th_vi_get_param *th_vi)
{
struct param_hdr_v3 param_hdr;
@@ -7539,6 +7675,57 @@
}
/**
+ * afe_get_sp_rx_tmax_xmax_logging_data -
+ * command to get excursion logging data from DSP
+ *
+ * @xt_logging: excursion logging params
+ * @port: AFE port ID
+ *
+ * Returns 0 on success or error on failure
+ */
+int afe_get_sp_rx_tmax_xmax_logging_data(
+ struct afe_sp_rx_tmax_xmax_logging_param *xt_logging,
+ u16 port_id)
+{
+ struct param_hdr_v3 param_hdr;
+ int ret = -EINVAL;
+
+ if (!xt_logging) {
+ pr_err("%s: Invalid params\n", __func__);
+ goto done;
+ }
+
+ memset(¶m_hdr, 0, sizeof(param_hdr));
+
+ param_hdr.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX;
+ param_hdr.instance_id = INSTANCE_ID_0;
+ param_hdr.param_id = AFE_PARAM_ID_SP_RX_TMAX_XMAX_LOGGING;
+ param_hdr.param_size = sizeof(struct afe_sp_rx_tmax_xmax_logging_param);
+
+ ret = q6afe_get_params(port_id, NULL, ¶m_hdr);
+ if (ret < 0) {
+ pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
+ __func__, port_id, param_hdr.param_id, ret);
+ goto done;
+ }
+
+ memcpy(xt_logging, &this_afe.xt_logging_resp.param,
+ sizeof(this_afe.xt_logging_resp.param));
+ pr_debug("%s: max_excursion %d %d count_exceeded_excursion %d %d max_temperature %d %d count_exceeded_temperature %d %d\n",
+ __func__, xt_logging->max_excursion[SP_V2_SPKR_1],
+ xt_logging->max_excursion[SP_V2_SPKR_2],
+ xt_logging->count_exceeded_excursion[SP_V2_SPKR_1],
+ xt_logging->count_exceeded_excursion[SP_V2_SPKR_2],
+ xt_logging->max_temperature[SP_V2_SPKR_1],
+ xt_logging->max_temperature[SP_V2_SPKR_2],
+ xt_logging->count_exceeded_temperature[SP_V2_SPKR_1],
+ xt_logging->count_exceeded_temperature[SP_V2_SPKR_2]);
+done:
+ return ret;
+}
+EXPORT_SYMBOL(afe_get_sp_rx_tmax_xmax_logging_data);
+
+/**
* afe_get_av_dev_drift -
* command to retrieve AV drift
*
@@ -7654,9 +7841,9 @@
memcpy(&calib_resp->res_cfg, &this_afe.calib_data.res_cfg,
sizeof(this_afe.calib_data.res_cfg));
pr_info("%s: state %s resistance %d %d\n", __func__,
- fbsp_state[calib_resp->res_cfg.th_vi_ca_state],
- calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_1],
- calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_2]);
+ fbsp_state[calib_resp->res_cfg.th_vi_ca_state],
+ calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_1],
+ calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_2]);
ret = 0;
fail_cmd:
return ret;
@@ -7952,21 +8139,57 @@
return ret;
}
+static int afe_set_cal_sp_th_vi_v_vali_cfg(int32_t cal_type, size_t data_size,
+ void *data)
+{
+ int ret = 0;
+ struct audio_cal_type_sp_th_vi_v_vali_cfg *cal_data = data;
+
+ if (cal_data == NULL || data_size != sizeof(*cal_data))
+ goto done;
+
+ memcpy(&this_afe.v_vali_cfg, &cal_data->cal_info,
+ sizeof(this_afe.v_vali_cfg));
+done:
+ return ret;
+}
+
static int afe_set_cal_sp_th_vi_ftm_cfg(int32_t cal_type, size_t data_size,
void *data)
{
int ret = 0;
struct audio_cal_type_sp_th_vi_ftm_cfg *cal_data = data;
- if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
- cal_data == NULL ||
- data_size != sizeof(*cal_data))
+ if (cal_data == NULL || data_size != sizeof(*cal_data))
goto done;
- pr_debug("%s: cal_type = %d\n", __func__, cal_type);
- mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
memcpy(&this_afe.th_ftm_cfg, &cal_data->cal_info,
sizeof(this_afe.th_ftm_cfg));
+done:
+ return ret;
+}
+
+static int afe_set_cal_sp_th_vi_cfg(int32_t cal_type, size_t data_size,
+ void *data)
+{
+ int ret = 0;
+ struct audio_cal_type_sp_th_vi_ftm_cfg *cal_data = data;
+ uint32_t mode;
+
+ if (cal_data == NULL ||
+ this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL)
+ goto done;
+
+ mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
+ mode = cal_data->cal_info.mode;
+ pr_debug("%s: cal_type = %d, mode = %d\n", __func__, cal_type, mode);
+ if (mode == MSM_SPKR_PROT_IN_FTM_MODE) {
+ ret = afe_set_cal_sp_th_vi_ftm_cfg(cal_type,
+ data_size, data);
+ } else if (mode == MSM_SPKR_PROT_IN_V_VALI_MODE) {
+ ret = afe_set_cal_sp_th_vi_v_vali_cfg(cal_type,
+ data_size, data);
+ }
mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
done:
return ret;
@@ -8017,6 +8240,42 @@
return ret;
}
+static int afe_get_cal_sp_th_vi_v_vali_param(int32_t cal_type, size_t data_size,
+ void *data)
+{
+ int i, ret = 0;
+ struct audio_cal_type_sp_th_vi_v_vali_param *cal_data = data;
+ struct afe_sp_th_vi_v_vali_get_param th_vi_v_vali;
+
+ if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
+ cal_data == NULL ||
+ data_size != sizeof(*cal_data))
+ goto done;
+
+ for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
+ cal_data->cal_info.status[i] = -EINVAL;
+ cal_data->cal_info.vrms_q24[i] = -1;
+ }
+ if (!afe_get_sp_th_vi_v_vali_data(&th_vi_v_vali)) {
+ for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
+ pr_debug("%s: v-vali param status = %d\n",
+ __func__, th_vi_v_vali.param.status[i]);
+ if (th_vi_v_vali.param.status[i] ==
+ V_VALI_IN_PROGRESS) {
+ cal_data->cal_info.status[i] = -EAGAIN;
+ } else if (th_vi_v_vali.param.status[i] ==
+ V_VALI_SUCCESS) {
+ cal_data->cal_info.status[i] = V_VALI_SUCCESS;
+ cal_data->cal_info.vrms_q24[i] =
+ th_vi_v_vali.param.vrms_q24[i];
+ }
+ }
+ }
+ this_afe.v_vali_flag = 0;
+done:
+ return ret;
+}
+
static int afe_get_cal_sp_th_vi_ftm_param(int32_t cal_type, size_t data_size,
void *data)
{
@@ -8024,13 +8283,11 @@
struct audio_cal_type_sp_th_vi_param *cal_data = data;
struct afe_sp_th_vi_get_param th_vi;
- pr_debug("%s: cal_type = %d\n", __func__, cal_type);
if (this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL ||
cal_data == NULL ||
data_size != sizeof(*cal_data))
goto done;
- mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
for (i = 0; i < SP_V2_NUM_MAX_SPKRS; i++) {
cal_data->cal_info.status[i] = -EINVAL;
cal_data->cal_info.r_dc_q24[i] = -1;
@@ -8051,11 +8308,34 @@
}
}
}
- mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
done:
return ret;
}
+static int afe_get_cal_sp_th_vi_param(int32_t cal_type, size_t data_size,
+ void *data)
+{
+ struct audio_cal_type_sp_th_vi_param *cal_data = data;
+ uint32_t mode;
+ int ret = 0;
+
+ if (cal_data == NULL ||
+ this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL)
+ return 0;
+
+ mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
+ mode = cal_data->cal_info.mode;
+ pr_debug("%s: cal_type = %d,mode = %d\n", __func__, cal_type, mode);
+ if (mode == MSM_SPKR_PROT_IN_V_VALI_MODE)
+ ret = afe_get_cal_sp_th_vi_v_vali_param(cal_type,
+ data_size, data);
+ else
+ ret = afe_get_cal_sp_th_vi_ftm_param(cal_type,
+ data_size, data);
+ mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL]->lock);
+ return ret;
+}
+
static int afe_get_cal_sp_ex_vi_ftm_param(int32_t cal_type, size_t data_size,
void *data)
{
@@ -8154,6 +8434,7 @@
cal_data->cal_info.r0[SP_V2_SPKR_1] = -1;
cal_data->cal_info.r0[SP_V2_SPKR_2] = -1;
}
+ this_afe.initial_cal = 0;
mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
__pm_relax(&wl.ws);
done:
@@ -8313,8 +8594,8 @@
cal_utils_match_buf_num} },
{{AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE,
- {NULL, NULL, NULL, afe_set_cal_sp_th_vi_ftm_cfg,
- afe_get_cal_sp_th_vi_ftm_param, NULL} },
+ {NULL, NULL, NULL, afe_set_cal_sp_th_vi_cfg,
+ afe_get_cal_sp_th_vi_param, NULL} },
{NULL, NULL, cal_utils_match_buf_num} },
{{AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE,
@@ -8546,6 +8827,12 @@
return -EINVAL;
}
+ ret = afe_q6_interface_prepare();
+ if(ret) {
+ pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
+ return ret;
+ }
+
mutex_lock(&this_afe.afe_cmd_lock);
memset(cmd_ptr, 0, sizeof(hw_vote_cfg));
@@ -8621,6 +8908,12 @@
&hw_vote_cfg;
int ret = 0;
+ ret = afe_q6_interface_prepare();
+ if(ret) {
+ pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
+ return ret;
+ }
+
mutex_lock(&this_afe.afe_cmd_lock);
memset(cmd_ptr, 0, sizeof(hw_vote_cfg));
diff --git a/dsp/q6asm.c b/dsp/q6asm.c
index 934fc58..6681dcb 100644
--- a/dsp/q6asm.c
+++ b/dsp/q6asm.c
@@ -1950,9 +1950,10 @@
data->dest_port);
if ((data->opcode != ASM_DATA_EVENT_RENDERED_EOS) &&
(data->opcode != ASM_DATA_EVENT_EOS) &&
+ (data->opcode != ASM_SESSION_EVENTX_OVERFLOW) &&
(data->opcode != ASM_SESSION_EVENT_RX_UNDERFLOW)) {
- if (payload == NULL) {
- pr_err("%s: payload is null\n", __func__);
+ if (payload == NULL || (data->payload_size < (2 * sizeof(uint32_t)))) {
+ pr_err("%s: payload is null or invalid size[%d]\n", __func__, data->payload_size);
spin_unlock_irqrestore(
&(session[session_id].session_lock), flags);
return -EINVAL;
@@ -2165,6 +2166,16 @@
}
spin_lock_irqsave(&port->dsp_lock, dsp_flags);
buf_index = asm_token._token.buf_index;
+ if (buf_index < 0 || buf_index >= port->max_buf_cnt) {
+ pr_debug("%s: Invalid buffer index %u\n",
+ __func__, buf_index);
+ spin_unlock_irqrestore(&port->dsp_lock,
+ dsp_flags);
+ spin_unlock_irqrestore(
+ &(session[session_id].session_lock),
+ flags);
+ return -EINVAL;
+ }
if ( data->payload_size >= 2 * sizeof(uint32_t) &&
(lower_32_bits(port->buf[buf_index].phys) !=
payload[0] ||
@@ -2267,6 +2278,16 @@
}
spin_lock_irqsave(&port->dsp_lock, dsp_flags);
buf_index = asm_token._token.buf_index;
+ if (buf_index < 0 || buf_index >= port->max_buf_cnt) {
+ pr_debug("%s: Invalid buffer index %u\n",
+ __func__, buf_index);
+ spin_unlock_irqrestore(&port->dsp_lock,
+ dsp_flags);
+ spin_unlock_irqrestore(
+ &(session[session_id].session_lock),
+ flags);
+ return -EINVAL;
+ }
port->buf[buf_index].used = 0;
if (lower_32_bits(port->buf[buf_index].phys) !=
payload[READDONE_IDX_BUFADD_LSW] ||
@@ -4265,6 +4286,12 @@
return -EINVAL;
}
+ if (config->channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__,
+ config->channels);
+ return -EINVAL;
+ }
+
bufsz = config->bufsz;
bufcnt = config->bufcnt;
num_watermarks = 0;
@@ -4664,6 +4691,11 @@
custom_size = enc_generic->reserved[1];
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: session[%d] size[%d] res[2]=[%d] res[3]=[%d]\n",
__func__, ac->session, custom_size, enc_generic->reserved[2],
enc_generic->reserved[3]);
@@ -4882,6 +4914,12 @@
u8 *channel_mapping;
int rc = 0;
+ if (num_channels > MAX_CHAN_MAP_CHANNELS) {
+ pr_err("%s: Invalid channel count %d\n", __func__,
+ num_channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: Session %d, num_channels = %d\n",
__func__, ac->session, num_channels);
q6asm_add_hdr(ac, &chan_map.hdr, sizeof(chan_map), TRUE);
@@ -4964,6 +5002,12 @@
goto fail_cmd;
}
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels,
bits_per_sample, sample_word_size);
@@ -5066,6 +5110,12 @@
goto fail_cmd;
}
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels,
bits_per_sample, sample_word_size);
@@ -5166,6 +5216,12 @@
goto fail_cmd;
}
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels,
bits_per_sample, sample_word_size);
@@ -5263,6 +5319,11 @@
return -EINVAL;
}
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
ac->session, rate, channels);
@@ -5478,9 +5539,13 @@
struct asm_multi_channel_pcm_enc_cfg_v2 enc_cfg;
u8 *channel_mapping;
u32 frames_per_buf = 0;
-
int rc = 0;
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
ac->session, rate, channels);
@@ -6098,6 +6163,11 @@
u8 *channel_mapping;
int rc = 0;
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
channels);
@@ -6181,6 +6251,11 @@
u8 *channel_mapping;
int rc;
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels,
bits_per_sample, sample_word_size);
@@ -6265,6 +6340,11 @@
u8 *channel_mapping;
int rc;
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels,
bits_per_sample, sample_word_size);
@@ -6352,6 +6432,11 @@
u8 *channel_mapping;
int rc;
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels,
bits_per_sample, sample_word_size);
@@ -6604,6 +6689,11 @@
u8 *channel_mapping;
int rc = 0;
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
channels);
@@ -6672,6 +6762,11 @@
u8 *channel_mapping;
int rc;
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels,
bits_per_sample, sample_word_size);
@@ -6744,6 +6839,11 @@
u8 *channel_mapping;
int rc;
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels,
bits_per_sample, sample_word_size);
@@ -6818,6 +6918,11 @@
u8 *channel_mapping;
int rc;
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels,
bits_per_sample, sample_word_size);
@@ -7010,6 +7115,11 @@
u8 *channel_mapping;
int rc = 0;
+ if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
+ pr_err("%s: Invalid channel count %d\n", __func__, channels);
+ return -EINVAL;
+ }
+
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]\n",
__func__, ac->session, rate,
channels, bits_per_sample);
@@ -9644,16 +9754,17 @@
ac->session, mtmx_params.hdr.opcode);
rc = apr_send_pkt(ac->apr, (uint32_t *) &mtmx_params);
if (rc < 0) {
- pr_err("%s: Commmand 0x%x failed %d\n", __func__,
- mtmx_params.hdr.opcode, rc);
- goto fail_cmd;
+ dev_err_ratelimited(ac->dev, "%s: Get Session Time failed %d\n",
+ __func__, rc);
+ return rc;
}
+
rc = wait_event_timeout(ac->time_wait,
(atomic_read(&ac->time_flag) == 0),
msecs_to_jiffies(TIMEOUT_MS));
if (!rc) {
pr_err("%s: timeout in getting session time from DSP\n",
- __func__);
+ __func__);
goto fail_cmd;
}
diff --git a/dsp/q6voice.c b/dsp/q6voice.c
index bb2bbdf..e36e18b 100644
--- a/dsp/q6voice.c
+++ b/dsp/q6voice.c
@@ -7332,7 +7332,7 @@
static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
{
- uint32_t *ptr = NULL;
+ uint32_t *ptr = NULL, min_payload_size = 0;
struct common_data *c = NULL;
struct voice_data *v = NULL;
struct vss_evt_voice_activity *voice_act_update = NULL;
@@ -7400,7 +7400,7 @@
}
if (data->opcode == APR_BASIC_RSP_RESULT) {
- if (data->payload_size) {
+ if (data->payload_size >= sizeof(ptr[0]) * 2) {
ptr = data->payload;
pr_debug("%x %x\n", ptr[0], ptr[1]);
@@ -7470,7 +7470,13 @@
} else if (data->opcode == VSS_IMEMORY_RSP_MAP) {
pr_debug("%s, Revd VSS_IMEMORY_RSP_MAP response\n", __func__);
- if (data->payload_size && data->token == VOIP_MEM_MAP_TOKEN) {
+ if (data->payload_size < sizeof(ptr[0])) {
+ pr_err("%s: payload has invalid size[%d]\n", __func__,
+ data->payload_size);
+ return -EINVAL;
+ }
+
+ if (data->token == VOIP_MEM_MAP_TOKEN) {
ptr = data->payload;
if (ptr[0]) {
v->shmem_info.mem_handle = ptr[0];
@@ -7537,10 +7543,13 @@
pr_debug("%s: Received VSS_IVERSION_RSP_GET\n", __func__);
if (data->payload_size) {
+ min_payload_size = min_t(u32, (int)data->payload_size,
+ CVD_VERSION_STRING_MAX_SIZE);
version_rsp =
(struct vss_iversion_rsp_get_t *)data->payload;
memcpy(common.cvd_version, version_rsp->version,
- CVD_VERSION_STRING_MAX_SIZE);
+ min_payload_size);
+ common.cvd_version[min_payload_size - 1] = '\0';
pr_debug("%s: CVD Version = %s\n",
__func__, common.cvd_version);
@@ -7740,6 +7749,11 @@
cvs_voc_pkt = v->shmem_info.sh_buf.buf[1].data;
if (cvs_voc_pkt != NULL && common.mvs_info.ul_cb != NULL) {
+ if (v->shmem_info.sh_buf.buf[1].size <
+ ((3 * sizeof(uint32_t)) + cvs_voc_pkt[2])) {
+ pr_err("%s: invalid voc pkt size\n", __func__);
+ return -EINVAL;
+ }
/* cvs_voc_pkt[0] contains tx timestamp */
common.mvs_info.ul_cb((uint8_t *)&cvs_voc_pkt[3],
cvs_voc_pkt[2],
@@ -7908,7 +7922,7 @@
}
if (data->opcode == APR_BASIC_RSP_RESULT) {
- if (data->payload_size) {
+ if (data->payload_size >= (2 * sizeof(uint32_t))) {
ptr = data->payload;
pr_debug("%x %x\n", ptr[0], ptr[1]);
diff --git a/dsp/sp_params.c b/dsp/sp_params.c
new file mode 100644
index 0000000..ed6d2eb
--- /dev/null
+++ b/dsp/sp_params.c
@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ */
+
+#include <dsp/q6audio-v2.h>
+#include <dsp/q6afe-v2.h>
+#include <linux/msm_audio_calibration.h>
+#include <dsp/sp_params.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+/* export or show spk params at /sys/class/spk_params/cal_data */
+#define SPK_PARAMS "spk_params"
+#define CLASS_NAME "cal_data"
+#define BUF_SZ 20
+#define Q27 (1<<27)
+#define Q22 (1<<22)
+
+struct afe_spk_ctl {
+ struct class *p_class;
+ struct device *p_dev;
+ struct afe_sp_rx_tmax_xmax_logging_param xt_logging;
+ int32_t max_temperature_rd[SP_V2_NUM_MAX_SPKR];
+};
+struct afe_spk_ctl this_afe_spk;
+
+static ssize_t sp_count_exceeded_temperature_l_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t ret = 0;
+
+ ret = snprintf(buf, BUF_SZ, "%d\n",
+ this_afe_spk.xt_logging.count_exceeded_temperature[SP_V2_SPKR_1]);
+ this_afe_spk.xt_logging.count_exceeded_temperature[SP_V2_SPKR_1] = 0;
+ return ret;
+}
+static DEVICE_ATTR(count_exceeded_temperature, 0644,
+ sp_count_exceeded_temperature_l_show, NULL);
+
+static ssize_t sp_count_exceeded_temperature_r_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t ret = 0;
+
+ ret = snprintf(buf, BUF_SZ, "%d\n",
+ this_afe_spk.xt_logging.count_exceeded_temperature[SP_V2_SPKR_2]);
+ this_afe_spk.xt_logging.count_exceeded_temperature[SP_V2_SPKR_2] = 0;
+ return ret;
+}
+static DEVICE_ATTR(count_exceeded_temperature_r, 0644,
+ sp_count_exceeded_temperature_r_show, NULL);
+
+static ssize_t sp_count_exceeded_excursion_l_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t ret = 0;
+
+ ret = snprintf(buf, BUF_SZ, "%d\n",
+ this_afe_spk.xt_logging.count_exceeded_excursion[SP_V2_SPKR_1]);
+ this_afe_spk.xt_logging.count_exceeded_excursion[SP_V2_SPKR_1] = 0;
+ return ret;
+}
+static DEVICE_ATTR(count_exceeded_excursion, 0644,
+ sp_count_exceeded_excursion_l_show, NULL);
+
+static ssize_t sp_count_exceeded_excursion_r_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t ret = 0;
+
+ ret = snprintf(buf, BUF_SZ, "%d\n",
+ this_afe_spk.xt_logging.count_exceeded_excursion[SP_V2_SPKR_2]);
+ this_afe_spk.xt_logging.count_exceeded_excursion[SP_V2_SPKR_2] = 0;
+ return ret;
+}
+static DEVICE_ATTR(count_exceeded_excursion_r, 0644,
+ sp_count_exceeded_excursion_r_show, NULL);
+
+static ssize_t sp_max_excursion_l_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t ret = 0;
+ int32_t ex_val_frac;
+ float ex_val;
+ int32_t ex_q27 = this_afe_spk.xt_logging.max_excursion[SP_V2_SPKR_1];
+
+ ex_val = (ex_q27 * 1.0)/Q27;
+ ex_val_frac = ex_val * 100;
+ ret = snprintf(buf, BUF_SZ, "%d.%02d\n", 0, ex_val_frac);
+ this_afe_spk.xt_logging.max_excursion[SP_V2_SPKR_1] = 0;
+ return ret;
+}
+static DEVICE_ATTR(max_excursion, 0644, sp_max_excursion_l_show, NULL);
+
+static ssize_t sp_max_excursion_r_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t ret = 0;
+ int32_t ex_val_frac;
+ float ex_val;
+ int32_t ex_q27 = this_afe_spk.xt_logging.max_excursion[SP_V2_SPKR_2];
+
+ ex_val = (ex_q27 * 1.0)/Q27;
+ ex_val_frac = ex_val * 100;
+ ret = snprintf(buf, BUF_SZ, "%d.%02d\n", 0, ex_val_frac);
+ this_afe_spk.xt_logging.max_excursion[SP_V2_SPKR_2] = 0;
+ return ret;
+}
+static DEVICE_ATTR(max_excursion_r, 0644, sp_max_excursion_r_show, NULL);
+
+static ssize_t sp_max_temperature_l_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t ret = 0;
+
+ ret = snprintf(buf, BUF_SZ, "%d\n",
+ this_afe_spk.xt_logging.max_temperature[SP_V2_SPKR_1]/Q22);
+ this_afe_spk.xt_logging.max_temperature[SP_V2_SPKR_1] = 0;
+ return ret;
+}
+static DEVICE_ATTR(max_temperature, 0644, sp_max_temperature_l_show, NULL);
+
+static ssize_t sp_max_temperature_r_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t ret = 0;
+
+ ret = snprintf(buf, BUF_SZ, "%d\n",
+ this_afe_spk.xt_logging.max_temperature[SP_V2_SPKR_2]/Q22);
+ this_afe_spk.xt_logging.max_temperature[SP_V2_SPKR_2] = 0;
+ return ret;
+}
+static DEVICE_ATTR(max_temperature_r, 0644, sp_max_temperature_r_show, NULL);
+
+static ssize_t sp_max_temperature_rd_l_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, BUF_SZ, "%d\n",
+ this_afe_spk.max_temperature_rd[SP_V2_SPKR_1]/Q22);
+}
+static DEVICE_ATTR(max_temperature_rd, 0644,
+ sp_max_temperature_rd_l_show, NULL);
+
+static ssize_t sp_max_temperature_rd_r_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, BUF_SZ, "%d\n",
+ this_afe_spk.max_temperature_rd[SP_V2_SPKR_2]/Q22);
+}
+static DEVICE_ATTR(max_temperature_rd_r, 0644,
+ sp_max_temperature_rd_r_show, NULL);
+
+static ssize_t q6afe_initial_cal_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, BUF_SZ, "%d\n", afe_get_spk_initial_cal());
+}
+
+static ssize_t q6afe_initial_cal_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int initial_cal = 0;
+
+ if (!kstrtou32(buf, 0, &initial_cal)) {
+ initial_cal = initial_cal > 0 ? 1 : 0;
+ if (initial_cal == afe_get_spk_initial_cal())
+ dev_dbg(dev, "%s: same value already present\n",
+ __func__);
+ else
+ afe_set_spk_initial_cal(initial_cal);
+ }
+ return size;
+}
+
+static DEVICE_ATTR(initial_cal, 0644,
+ q6afe_initial_cal_show, q6afe_initial_cal_store);
+
+static ssize_t q6afe_v_vali_flag_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, BUF_SZ, "%d\n", afe_get_spk_v_vali_flag());
+}
+
+static ssize_t q6afe_v_vali_flag_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int v_vali_flag = 0;
+
+ if (!kstrtou32(buf, 0, &v_vali_flag)) {
+ v_vali_flag = v_vali_flag > 0 ? 1 : 0;
+ if (v_vali_flag == afe_get_spk_v_vali_flag())
+ dev_dbg(dev, "%s: same value already present\n",
+ __func__);
+ else
+ afe_set_spk_v_vali_flag(v_vali_flag);
+ }
+ return size;
+}
+
+static DEVICE_ATTR(v_vali_flag, 0644,
+ q6afe_v_vali_flag_show, q6afe_v_vali_flag_store);
+
+static ssize_t q6afe_spk_r0_l_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int r0[SP_V2_NUM_MAX_SPKRS];
+
+ afe_get_spk_r0(r0);
+ return snprintf(buf, BUF_SZ, "%d\n", r0[SP_V2_SPKR_1]);
+}
+
+static DEVICE_ATTR(spk_r0, 0644, q6afe_spk_r0_l_show, NULL);
+
+static ssize_t q6afe_spk_t0_l_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int t0[SP_V2_NUM_MAX_SPKRS];
+
+ afe_get_spk_t0(t0);
+ return snprintf(buf, BUF_SZ, "%d\n", t0[SP_V2_SPKR_1]);
+}
+
+static DEVICE_ATTR(spk_t0, 0644, q6afe_spk_t0_l_show, NULL);
+
+static ssize_t q6afe_spk_r0_r_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int r0[SP_V2_NUM_MAX_SPKRS];
+
+ afe_get_spk_r0(r0);
+ return snprintf(buf, BUF_SZ, "%d\n", r0[SP_V2_SPKR_2]);
+}
+
+static DEVICE_ATTR(spk_r0_r, 0644, q6afe_spk_r0_r_show, NULL);
+
+static ssize_t q6afe_spk_t0_r_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int t0[SP_V2_NUM_MAX_SPKRS];
+
+ afe_get_spk_t0(t0);
+ return snprintf(buf, BUF_SZ, "%d\n", t0[SP_V2_SPKR_2]);
+}
+
+static DEVICE_ATTR(spk_t0_r, 0644, q6afe_spk_t0_r_show, NULL);
+
+static ssize_t q6afe_spk_v_vali_l_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int v_vali_sts[SP_V2_NUM_MAX_SPKRS];
+
+ afe_get_spk_v_vali_sts(v_vali_sts);
+ return snprintf(buf, BUF_SZ, "%d\n", v_vali_sts[SP_V2_SPKR_1]);
+}
+
+static DEVICE_ATTR(spk_v_vali_status, 0644, q6afe_spk_v_vali_l_show, NULL);
+
+static ssize_t q6afe_spk_v_vali_r_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int v_vali_sts[SP_V2_NUM_MAX_SPKRS];
+
+ afe_get_spk_v_vali_sts(v_vali_sts);
+ return snprintf(buf, BUF_SZ, "%d\n", v_vali_sts[SP_V2_SPKR_2]);
+}
+
+static DEVICE_ATTR(spk_v_vali_r_status, 0644, q6afe_spk_v_vali_r_show, NULL);
+
+static struct attribute *afe_spk_cal_attr[] = {
+ &dev_attr_max_excursion.attr,
+ &dev_attr_max_excursion_r.attr,
+ &dev_attr_max_temperature.attr,
+ &dev_attr_max_temperature_r.attr,
+ &dev_attr_count_exceeded_excursion.attr,
+ &dev_attr_count_exceeded_excursion_r.attr,
+ &dev_attr_count_exceeded_temperature.attr,
+ &dev_attr_count_exceeded_temperature_r.attr,
+ &dev_attr_max_temperature_rd.attr,
+ &dev_attr_max_temperature_rd_r.attr,
+ &dev_attr_initial_cal.attr,
+ &dev_attr_spk_r0.attr,
+ &dev_attr_spk_t0.attr,
+ &dev_attr_spk_r0_r.attr,
+ &dev_attr_spk_t0_r.attr,
+ &dev_attr_v_vali_flag.attr,
+ &dev_attr_spk_v_vali_status.attr,
+ &dev_attr_spk_v_vali_r_status.attr,
+ NULL,
+};
+
+static struct attribute_group afe_spk_cal_attr_grp = {
+ .attrs = afe_spk_cal_attr,
+};
+
+
+/**
+ * afe_get_sp_xt_logging_data -
+ * to get excursion logging data from DSP
+ *
+ * @port: AFE port ID
+ *
+ * Returns 0 on success or error on failure
+ */
+int afe_get_sp_xt_logging_data(u16 port_id)
+{
+ int ret = 0;
+ struct afe_sp_rx_tmax_xmax_logging_param xt_logging_data;
+
+ ret = afe_get_sp_rx_tmax_xmax_logging_data(&xt_logging_data, port_id);
+ if (ret) {
+ pr_err("%s Excursion logging fail\n", __func__);
+ return ret;
+ }
+ /* storing max sp param value */
+ if (this_afe_spk.xt_logging.max_temperature[SP_V2_SPKR_1] <
+ xt_logging_data.max_temperature[SP_V2_SPKR_1])
+ this_afe_spk.xt_logging.max_temperature[SP_V2_SPKR_1] =
+ xt_logging_data.max_temperature[SP_V2_SPKR_1];
+
+
+ if (this_afe_spk.xt_logging.max_temperature[SP_V2_SPKR_2] <
+ xt_logging_data.max_temperature[SP_V2_SPKR_2])
+ this_afe_spk.xt_logging.max_temperature[SP_V2_SPKR_2] =
+ xt_logging_data.max_temperature[SP_V2_SPKR_2];
+
+
+ /* update temp for max_temperature_rd node */
+ if (this_afe_spk.max_temperature_rd[SP_V2_SPKR_1] <
+ xt_logging_data.max_temperature[SP_V2_SPKR_1])
+ this_afe_spk.max_temperature_rd[SP_V2_SPKR_1] =
+ xt_logging_data.max_temperature[SP_V2_SPKR_1];
+
+ if (this_afe_spk.max_temperature_rd[SP_V2_SPKR_2] <
+ xt_logging_data.max_temperature[SP_V2_SPKR_2])
+ this_afe_spk.max_temperature_rd[SP_V2_SPKR_2] =
+ xt_logging_data.max_temperature[SP_V2_SPKR_2];
+
+
+ if (this_afe_spk.xt_logging.max_excursion[SP_V2_SPKR_1] <
+ xt_logging_data.max_excursion[SP_V2_SPKR_1])
+ this_afe_spk.xt_logging.max_excursion[SP_V2_SPKR_1] =
+ xt_logging_data.max_excursion[SP_V2_SPKR_1];
+
+ if (this_afe_spk.xt_logging.max_excursion[SP_V2_SPKR_2] <
+ xt_logging_data.max_excursion[SP_V2_SPKR_2])
+ this_afe_spk.xt_logging.max_excursion[SP_V2_SPKR_2] =
+ xt_logging_data.max_excursion[SP_V2_SPKR_2];
+
+ if (this_afe_spk.xt_logging.count_exceeded_temperature[SP_V2_SPKR_1] <
+ xt_logging_data.count_exceeded_temperature[SP_V2_SPKR_1])
+ this_afe_spk.xt_logging.count_exceeded_temperature[SP_V2_SPKR_1]
+ += xt_logging_data.count_exceeded_temperature[SP_V2_SPKR_1];
+
+ if (this_afe_spk.xt_logging.count_exceeded_temperature[SP_V2_SPKR_2] <
+ xt_logging_data.count_exceeded_temperature[SP_V2_SPKR_2])
+ this_afe_spk.xt_logging.count_exceeded_temperature[SP_V2_SPKR_2]
+ += xt_logging_data.count_exceeded_temperature[SP_V2_SPKR_2];
+
+ if (this_afe_spk.xt_logging.count_exceeded_excursion[SP_V2_SPKR_1] <
+ xt_logging_data.count_exceeded_excursion[SP_V2_SPKR_1])
+ this_afe_spk.xt_logging.count_exceeded_excursion[SP_V2_SPKR_1]
+ += xt_logging_data.count_exceeded_excursion[SP_V2_SPKR_1];
+
+ if (this_afe_spk.xt_logging.count_exceeded_excursion[SP_V2_SPKR_2] <
+ xt_logging_data.count_exceeded_excursion[SP_V2_SPKR_2])
+ this_afe_spk.xt_logging.count_exceeded_excursion[SP_V2_SPKR_2]
+ += xt_logging_data.count_exceeded_excursion[SP_V2_SPKR_2];
+
+ return ret;
+}
+EXPORT_SYMBOL(afe_get_sp_xt_logging_data);
+
+int __init spk_params_init(void)
+{
+ /* initialize xt param value with 0 */
+ this_afe_spk.xt_logging.max_temperature[SP_V2_SPKR_1] = 0;
+ this_afe_spk.xt_logging.max_temperature[SP_V2_SPKR_2] = 0;
+ this_afe_spk.xt_logging.max_excursion[SP_V2_SPKR_1] = 0;
+ this_afe_spk.xt_logging.max_excursion[SP_V2_SPKR_2] = 0;
+ this_afe_spk.xt_logging.count_exceeded_temperature[SP_V2_SPKR_1] = 0;
+ this_afe_spk.xt_logging.count_exceeded_temperature[SP_V2_SPKR_2] = 0;
+ this_afe_spk.xt_logging.count_exceeded_excursion[SP_V2_SPKR_1] = 0;
+ this_afe_spk.xt_logging.count_exceeded_excursion[SP_V2_SPKR_2] = 0;
+
+ this_afe_spk.p_class = class_create(THIS_MODULE, SPK_PARAMS);
+ if (this_afe_spk.p_class) {
+ this_afe_spk.p_dev = device_create(this_afe_spk.p_class, NULL,
+ 1, NULL, CLASS_NAME);
+ if (!IS_ERR(this_afe_spk.p_dev)) {
+ if (sysfs_create_group(&this_afe_spk.p_dev->kobj,
+ &afe_spk_cal_attr_grp))
+ pr_err("%s: Failed to create sysfs group\n",
+ __func__);
+ }
+ }
+ return 0;
+}
+
+void spk_params_exit(void)
+{
+ pr_debug("%s\n", __func__);
+}
diff --git a/include/asoc/wcd9xxx_registers.h b/include/asoc/wcd9xxx_registers.h
index cf3c408..731b72f 100644
--- a/include/asoc/wcd9xxx_registers.h
+++ b/include/asoc/wcd9xxx_registers.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*/
#ifndef _WCD9XXX_REGISTERS_H
@@ -12,6 +12,7 @@
#define WCD9XXX_ANA_HPH (WCD9XXX_BASE_ADDRESS+0x009)
#define WCD9XXX_CLASSH_MODE_2 (WCD9XXX_BASE_ADDRESS+0x098)
#define WCD9XXX_CLASSH_MODE_3 (WCD9XXX_BASE_ADDRESS+0x099)
+#define WCD9XXX_FLYBACK_VNEG_CTRL_1 (WCD9XXX_BASE_ADDRESS+0x0A5)
#define WCD9XXX_FLYBACK_VNEG_CTRL_4 (WCD9XXX_BASE_ADDRESS+0x0A8)
#define WCD9XXX_FLYBACK_VNEGDAC_CTRL_2 (WCD9XXX_BASE_ADDRESS+0x0AF)
#define WCD9XXX_RX_BIAS_HPH_LOWPOWER (WCD9XXX_BASE_ADDRESS+0x0BF)
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index d2cab24..62ff28b 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -10408,6 +10408,7 @@
#define AFE_PARAM_ID_SP_RX_LIMITER_TH 0x000102B1
#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
struct asm_fbsp_mode_rx_cfg {
uint32_t minor_version;
@@ -10468,6 +10469,8 @@
#define AFE_PARAM_ID_SP_V2_TH_VI_MODE_CFG 0x0001026B
#define AFE_PARAM_ID_SP_V2_TH_VI_FTM_CFG 0x0001029F
#define AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS 0x000102A0
+#define AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_CFG 0x000102BF
+#define AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_PARAMS 0x000102C0
struct afe_sp_th_vi_mode_cfg {
uint32_t minor_version;
@@ -10557,6 +10560,51 @@
struct afe_sp_th_vi_ftm_params param;
} __packed;
+struct afe_sp_th_vi_v_vali_cfg {
+ uint32_t minor_version;
+ uint32_t wait_time_ms[SP_V2_NUM_MAX_SPKR];
+ /*
+ * Wait time to heat up speaker before collecting statistics
+ * for V validation mode in ms.
+ * values 100 to 1000 ms
+ */
+ uint32_t vali_time_ms[SP_V2_NUM_MAX_SPKR];
+ /*
+ * duration for which V VALIDATION statistics are collected in ms.
+ * values 1000 to 3000 ms
+ */
+} __packed;
+
+struct afe_sp_th_vi_v_vali_params {
+ uint32_t minor_version;
+ uint32_t vrms_q24[SP_V2_NUM_MAX_SPKR];
+ /*
+ * Vrms value in q24 format
+ * values [0 33554432] Q24 (0 - 2Vrms)
+ */
+ uint32_t status[SP_V2_NUM_MAX_SPKR];
+ /*
+ * v-vali packet status
+ * 0 - Failed.
+ * 1 - Success.
+ * 2 - Incorrect operation mode.This status is returned
+ * when GET_PARAM is called in non v-vali Mode
+ * 3 - Inactive mode -- Port is not yet started.
+ * 4 - Wait state. wait_time_ms has not yet elapsed
+ * 5 - In progress state. ftm_time_ms has not yet elapsed.
+ */
+} __packed;
+
+struct afe_sp_th_vi_v_vali_get_param {
+ struct param_hdr_v3 pdata;
+ struct afe_sp_th_vi_v_vali_params param;
+} __packed;
+
+struct afe_sp_th_vi_v_vali_get_param_resp {
+ uint32_t status;
+ struct param_hdr_v3 pdata;
+ struct afe_sp_th_vi_v_vali_params param;
+} __packed;
#define AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI 0x0001026F
#define AFE_PARAM_ID_SP_V2_EX_VI_MODE_CFG 0x000102A1
@@ -10618,6 +10666,33 @@
*/
} __packed;
+struct afe_sp_rx_tmax_xmax_logging_param {
+ /*
+ * Maximum excursion since the last grasp of xmax in mm.
+ */
+ int32_t max_excursion[SP_V2_NUM_MAX_SPKR];
+ /*
+ * Number of periods when the monitored excursion exceeds to and
+ * stays at Xmax during logging_count_period.
+ */
+ uint32_t count_exceeded_excursion[SP_V2_NUM_MAX_SPKR];
+ /*
+ * Maximum temperature since the last grasp of tmax in C.
+ */
+ int32_t max_temperature[SP_V2_NUM_MAX_SPKR];
+ /*
+ * Number of periods when the monitored temperature exceeds to and
+ * stays at Tmax during logging_count_period
+ */
+ uint32_t count_exceeded_temperature[SP_V2_NUM_MAX_SPKR];
+} __packed;
+
+struct afe_sp_rx_tmax_xmax_logging_resp {
+ uint32_t status;
+ struct param_hdr_v3 pdata;
+ struct afe_sp_rx_tmax_xmax_logging_param param;
+} __packed;
+
struct afe_sp_ex_vi_get_param {
struct param_hdr_v3 pdata;
struct afe_sp_ex_vi_ftm_params param;
@@ -10641,6 +10716,7 @@
struct asm_mode_vi_proc_cfg mode_vi_proc_cfg;
struct afe_sp_th_vi_mode_cfg th_vi_mode_cfg;
struct afe_sp_th_vi_ftm_cfg th_vi_ftm_cfg;
+ struct afe_sp_th_vi_v_vali_cfg th_vi_v_vali_cfg;
struct afe_sp_ex_vi_mode_cfg ex_vi_mode_cfg;
struct afe_sp_ex_vi_ftm_cfg ex_vi_ftm_cfg;
struct afe_sp_rx_limiter_th_param limiter_th_cfg;
diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h
index 413edc1..c5b7e3e 100644
--- a/include/dsp/q6afe-v2.h
+++ b/include/dsp/q6afe-v2.h
@@ -446,6 +446,9 @@
void afe_set_routing_callback(routing_cb cb);
int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats,
u16 port);
+int afe_get_sp_rx_tmax_xmax_logging_data(
+ struct afe_sp_rx_tmax_xmax_logging_param *xt_logging,
+ u16 port_id);
int afe_cal_init_hwdep(void *card);
int afe_send_port_island_mode(u16 port_id);
int afe_send_cmd_wakeup_register(void *handle, bool enable);
@@ -491,4 +494,11 @@
int afe_vote_lpass_core_hw(uint32_t hw_block_id, char *client_name,
uint32_t *client_handle);
int afe_unvote_lpass_core_hw(uint32_t hw_block_id, uint32_t client_handle);
+int afe_get_spk_initial_cal(void);
+void afe_get_spk_r0(int *spk_r0);
+void afe_get_spk_t0(int *spk_t0);
+int afe_get_spk_v_vali_flag(void);
+void afe_get_spk_v_vali_sts(int *spk_v_vali_sts);
+void afe_set_spk_initial_cal(int initial_cal);
+void afe_set_spk_v_vali_flag(int v_vali_flag);
#endif /* __Q6AFE_V2_H__ */
diff --git a/include/dsp/sp_params.h b/include/dsp/sp_params.h
new file mode 100644
index 0000000..ddc756e
--- /dev/null
+++ b/include/dsp/sp_params.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __SP_PARAMS_H__
+#define __SP_PARAMS_H__
+
+#if IS_ENABLED(CONFIG_XT_LOGGING)
+int afe_get_sp_xt_logging_data(u16 port_id);
+#else
+static inline int afe_get_sp_xt_logging_data(u16 port_id)
+{
+ return 0;
+}
+#endif
+
+#endif /* __SP_PARAMS_H__ */
+
diff --git a/include/uapi/Android.mk b/include/uapi/Android.mk
index b8c209a..f19a6c2 100644
--- a/include/uapi/Android.mk
+++ b/include/uapi/Android.mk
@@ -15,6 +15,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := audio_kernel_headers
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_PREBUILT_INT_KERNEL)
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
GEN := $(addprefix $(UAPI_OUT)/,$(AUDIO_KERNEL_HEADERS))
$(GEN): $(KERNEL_USR)
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index f6af2bf..9b93abe 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -18,3 +18,4 @@
header-y += msm_audio_g711.h
header-y += msm_audio_g711_dec.h
header-y += mfd/
+header-y += wcd-spi-ac-params.h
diff --git a/include/uapi/linux/msm_audio_calibration.h b/include/uapi/linux/msm_audio_calibration.h
index 9bd64aa..35b5960 100644
--- a/include/uapi/linux/msm_audio_calibration.h
+++ b/include/uapi/linux/msm_audio_calibration.h
@@ -294,9 +294,11 @@
MSM_SPKR_PROT_DISABLED,
MSM_SPKR_PROT_NOT_CALIBRATED,
MSM_SPKR_PROT_PRE_CALIBRATED,
- MSM_SPKR_PROT_IN_FTM_MODE
+ MSM_SPKR_PROT_IN_FTM_MODE,
+ MSM_SPKR_PROT_IN_V_VALI_MODE
};
#define MSM_SPKR_PROT_IN_FTM_MODE MSM_SPKR_PROT_IN_FTM_MODE
+#define MSM_SPKR_PROT_IN_V_VALI_MODE MSM_SPKR_PROT_IN_V_VALI_MODE
enum msm_spkr_count {
SP_V2_SPKR_1,
@@ -321,14 +323,37 @@
};
struct audio_cal_info_sp_th_vi_ftm_cfg {
- uint32_t wait_time[SP_V2_NUM_MAX_SPKRS];
- uint32_t ftm_time[SP_V2_NUM_MAX_SPKRS];
+ /*
+ * mode should be first param, add new params later to this.
+ * we use this mode(first 4 bytes) to differentiate
+ * whether it is TH_VI FTM or v-validation.
+ */
uint32_t mode;
/*
* 0 - normal running mode
* 1 - Calibration
* 2 - FTM mode
*/
+ uint32_t wait_time[SP_V2_NUM_MAX_SPKRS];
+ uint32_t ftm_time[SP_V2_NUM_MAX_SPKRS];
+};
+
+struct audio_cal_info_sp_th_vi_v_vali_cfg {
+ /*
+ * mode should be first param, add new params later to this.
+ * we use this mode(first 4 bytes) to differentiate
+ * whether it is TH_VI FTM or v-validation.
+ */
+ uint32_t mode;
+ /*
+ * 0 - normal running mode
+ * 1 - Calibration
+ * 2 - FTM mode
+ * 3 - V-Validation mode
+ */
+ uint32_t wait_time[SP_V2_NUM_MAX_SPKRS];
+ uint32_t vali_time[SP_V2_NUM_MAX_SPKRS];
+
};
struct audio_cal_info_sp_ex_vi_ftm_cfg {
@@ -349,11 +374,28 @@
};
struct audio_cal_info_sp_th_vi_param {
+ /*
+ * mode should be first param, add new params later to this.
+ * we use this mode(first 4 bytes) to differentiate
+ * whether it is TH_VI FTM or v-validation.
+ */
+ uint32_t mode;
int32_t r_dc_q24[SP_V2_NUM_MAX_SPKRS];
int32_t temp_q22[SP_V2_NUM_MAX_SPKRS];
int32_t status[SP_V2_NUM_MAX_SPKRS];
};
+struct audio_cal_info_sp_th_vi_v_vali_param {
+ /*
+ * mode should be first param, add new params later to this.
+ * we use this mode(first 4 bytes) to differentiate
+ * whether it is TH_VI FTM or v-validation.
+ */
+ uint32_t mode;
+ uint32_t vrms_q24[SP_V2_NUM_MAX_SPKRS];
+ int32_t status[SP_V2_NUM_MAX_SPKRS];
+};
+
struct audio_cal_info_msm_spk_prot_status {
int32_t r0[SP_V2_NUM_MAX_SPKRS];
int32_t status;
@@ -589,6 +631,17 @@
struct audio_cal_type_sp_th_vi_ftm_cfg cal_type;
};
+struct audio_cal_type_sp_th_vi_v_vali_cfg {
+ struct audio_cal_type_header cal_hdr;
+ struct audio_cal_data cal_data;
+ struct audio_cal_info_sp_th_vi_v_vali_cfg cal_info;
+};
+
+struct audio_cal_sp_th_vi_v_vali_cfg {
+ struct audio_cal_header hdr;
+ struct audio_cal_type_sp_th_vi_v_vali_cfg cal_type;
+};
+
struct audio_cal_type_sp_ex_vi_ftm_cfg {
struct audio_cal_type_header cal_hdr;
struct audio_cal_data cal_data;
@@ -731,6 +784,17 @@
struct audio_cal_header hdr;
struct audio_cal_type_sp_th_vi_param cal_type;
};
+
+struct audio_cal_type_sp_th_vi_v_vali_param {
+ struct audio_cal_type_header cal_hdr;
+ struct audio_cal_data cal_data;
+ struct audio_cal_info_sp_th_vi_v_vali_param cal_info;
+};
+
+struct audio_cal_sp_th_vi_v_vali_param {
+ struct audio_cal_header hdr;
+ struct audio_cal_type_sp_th_vi_v_vali_param cal_type;
+};
struct audio_cal_type_sp_ex_vi_param {
struct audio_cal_type_header cal_hdr;
struct audio_cal_data cal_data;
diff --git a/include/uapi/linux/wcd-spi-ac-params.h b/include/uapi/linux/wcd-spi-ac-params.h
new file mode 100644
index 0000000..e397bf2
--- /dev/null
+++ b/include/uapi/linux/wcd-spi-ac-params.h
@@ -0,0 +1,52 @@
+#ifndef __UAPI_WCD_SPI_AC_PARAMS_H__
+#define __UAPI_WCD_SPI_AC_PARAMS_H__
+
+#include <linux/types.h>
+
+#define WCD_SPI_AC_CMD_CONC_BEGIN 0x01
+#define WCD_SPI_AC_CMD_CONC_END 0x02
+#define WCD_SPI_AC_CMD_BUF_DATA 0x03
+
+#define WCD_SPI_AC_MAX_BUFFERS 2
+#define WCD_SPI_AC_MAX_CH_PER_BUF 8
+
+#define WCD_SPI_AC_CLIENT_CDEV_NAME "wcd-spi-ac-client"
+#define WCD_SPI_AC_PROCFS_DIR_NAME "wcd-spi-ac"
+#define WCD_SPI_AC_PROCFS_STATE_NAME "svc-state"
+
+/*
+ * wcd_spi_ac_buf_data:
+ * Buffer address for one buffer. Should have data
+ * for all the channels. If channels are unused, the
+ * value must be NULL.
+ *
+ * @addr:
+ * Address where each channel of the buffer starts.
+ */
+struct wcd_spi_ac_buf_data {
+ __u32 addr[WCD_SPI_AC_MAX_CH_PER_BUF];
+} __packed;
+
+/*
+ * wcd_spi_ac_write_cmd:
+ * Data sent to the driver's write interface should
+ * be packed in this format.
+ *
+ * @cmd_type:
+ * Indicates the type of command that is sent. Should
+ * be one of the valid commands defined with
+ * WCD_SPI_AC_CMD_*
+ * @payload:
+ * No payload for:
+ * WCD_SPI_AC_CMD_CONC_BEGIN
+ * WCD_SPI_AC_CMD_CONC_END
+ * Upto WCD_SPI_AC_MAX_BUFFERS of type
+ * struct wcd_spi_ac_buf_data for:
+ * WCD_SPI_AC_CMD_BUF_DATA
+ */
+struct wcd_spi_ac_write_cmd {
+ __u32 cmd_type;
+ __u8 payload[0];
+} __packed;
+
+#endif /* end of __UAPI_WCD_SPI_AC_PARAMS_H__ */
diff --git a/ipc/apr.c b/ipc/apr.c
index ec05d3b..fbb1f32 100644
--- a/ipc/apr.c
+++ b/ipc/apr.c
@@ -364,7 +364,8 @@
unsigned long flags;
if (!handle || !buf) {
- pr_err("APR: Wrong parameters\n");
+ pr_err("APR: Wrong parameters for %s\n",
+ !handle ? "handle" : "buf");
return -EINVAL;
}
if (svc->need_reset) {
@@ -636,6 +637,12 @@
pr_err("APR: Wrong paket size\n");
return;
}
+
+ if (hdr->pkt_size < hdr_size) {
+ pr_err("APR: Packet size less than header size\n");
+ return;
+ }
+
msg_type = hdr->hdr_field;
msg_type = (msg_type >> 0x08) & 0x0003;
if (msg_type >= APR_MSG_TYPE_MAX && msg_type != APR_BASIC_RSP_RESULT) {
diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c
index f9dbc24..8d82ff1 100644
--- a/soc/swr-mstr-ctrl.c
+++ b/soc/swr-mstr-ctrl.c
@@ -448,11 +448,16 @@
mutex_lock(&swrm->iolock);
val = swrm_get_packed_reg_val(&swrm->rcmd_id, len, dev_addr, reg_addr);
- /* wait for FIFO RD to complete to avoid overflow */
- usleep_range(100, 105);
- swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
- /* wait for FIFO RD CMD complete to avoid overflow */
- usleep_range(250, 255);
+ if (swrm->read) {
+ /* skip delay if read is handled in platform driver */
+ swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
+ } else {
+ /* wait for FIFO RD to complete to avoid overflow */
+ usleep_range(100, 105);
+ swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
+ /* wait for FIFO RD CMD complete to avoid overflow */
+ usleep_range(250, 255);
+ }
retry_read:
*cmd_data = swr_master_read(swrm, SWRM_CMD_FIFO_RD_FIFO_ADDR);
dev_dbg(swrm->dev, "%s: reg: 0x%x, cmd_id: 0x%x, rcmd_id: 0x%x, \
@@ -496,8 +501,12 @@
dev_num: 0x%x, cmd_data: 0x%x\n", __func__,
reg_addr, cmd_id, swrm->wcmd_id,dev_addr, cmd_data);
swr_master_write(swrm, SWRM_CMD_FIFO_WR_CMD, val);
- /* wait for FIFO WR command to complete to avoid overflow */
- usleep_range(250, 255);
+ /*
+ * wait for FIFO WR command to complete to avoid overflow
+ * skip delay if write is handled in platform driver.
+ */
+ if(!swrm->write)
+ usleep_range(250, 255);
if (cmd_id == 0xF) {
/*
* sleep for 10ms for MSM soundwire variant to allow broadcast