Merge "dsp: Add spinlock to protect audio client"
diff --git a/asoc/bengal.c b/asoc/bengal.c
index 1ab7f99..ec73cc9 100644
--- a/asoc/bengal.c
+++ b/asoc/bengal.c
@@ -5030,6 +5030,33 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
},
+ /* Proxy Tx BACK END DAI Link */
+ {
+ .name = LPASS_BE_PROXY_TX,
+ .stream_name = "Proxy Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.8195",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .id = MSM_BACKEND_DAI_PROXY_TX,
+ .ignore_suspend = 1,
+ },
+ /* Proxy Rx BACK END DAI Link */
+ {
+ .name = LPASS_BE_PROXY_RX,
+ .stream_name = "Proxy Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.8194",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .id = MSM_BACKEND_DAI_PROXY_RX,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
{
.name = LPASS_BE_USB_AUDIO_RX,
.stream_name = "USB Audio Playback",
diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c
index eb7cb88..70b0126 100644
--- a/asoc/codecs/bolero/rx-macro.c
+++ b/asoc/codecs/bolero/rx-macro.c
@@ -1908,7 +1908,12 @@
0x40, 0x40);
break;
case INTERP_HPHR:
- snd_soc_component_update_bits(component,
+ if (rx_priv->is_ear_mode_on)
+ snd_soc_component_update_bits(component,
+ BOLERO_CDC_RX_CLSH_HPH_V_PA,
+ 0x3F, 0x39);
+ else
+ snd_soc_component_update_bits(component,
BOLERO_CDC_RX_CLSH_HPH_V_PA,
0x3F, 0x1C);
snd_soc_component_update_bits(component,
diff --git a/asoc/codecs/csra66x0/csra66x0.c b/asoc/codecs/csra66x0/csra66x0.c
index e0e702f..9cdbbda 100644
--- a/asoc/codecs/csra66x0/csra66x0.c
+++ b/asoc/codecs/csra66x0/csra66x0.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/init.h>
#include <linux/delay.h>
@@ -602,6 +602,25 @@
{"PGA", NULL, "DAC"},
{"SPKR", NULL, "PGA"},
};
+/*
+ * csra66x0_hw_free_mute - Update csra66x0 mute register
+ *
+ * @component - csra66x0 component
+ *
+ */
+void csra66x0_hw_free_mute(struct snd_soc_component *component)
+{
+ int val = 0;
+
+ if (component == NULL)
+ return;
+
+ val = snd_soc_component_read32(component,
+ CSRA66X0_MISC_CONTROL_STATUS_1_FA);
+ snd_soc_component_write(component, CSRA66X0_MISC_CONTROL_STATUS_1_FA,
+ val | 0x04);
+}
+EXPORT_SYMBOL(csra66x0_hw_free_mute);
static int csra66x0_wait_for_config_state(struct snd_soc_component *component)
{
diff --git a/asoc/codecs/csra66x0/csra66x0.h b/asoc/codecs/csra66x0/csra66x0.h
index 04d9ef8..2bde3cc 100644
--- a/asoc/codecs/csra66x0/csra66x0.h
+++ b/asoc/codecs/csra66x0/csra66x0.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/
#ifndef _CSRA66X0_H
@@ -226,4 +226,6 @@
#define FAULT_STATUS_TEMP 0x10
#define FAULT_STATUS_PROTECT 0x20
+
+void csra66x0_hw_free_mute(struct snd_soc_component *component);
#endif /* _CSRA66X0_H */
diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c
index 1f4146a..30ad7e3 100644
--- a/asoc/codecs/wcd937x/wcd937x.c
+++ b/asoc/codecs/wcd937x/wcd937x.c
@@ -570,7 +570,8 @@
snd_soc_component_update_bits(component,
WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L,
0x0F, 0x06);
- snd_soc_component_update_bits(component,
+ if (wcd937x->comp1_enable)
+ snd_soc_component_update_bits(component,
WCD937X_DIGITAL_CDC_COMP_CTL_0,
0x02, 0x02);
usleep_range(5000, 5010);
@@ -588,6 +589,10 @@
snd_soc_component_update_bits(component,
WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L,
0x0F, 0x01);
+ if (wcd937x->comp1_enable)
+ snd_soc_component_update_bits(component,
+ WCD937X_DIGITAL_CDC_COMP_CTL_0,
+ 0x02, 0x00);
break;
};
return 0;
diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c
index 36c18ea..abd3106 100644
--- a/asoc/codecs/wcd938x/wcd938x.c
+++ b/asoc/codecs/wcd938x/wcd938x.c
@@ -657,8 +657,10 @@
WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 0x04, 0x04);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x01);
- snd_soc_component_update_bits(component,
- WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x02, 0x02);
+ if (wcd938x->comp1_enable)
+ snd_soc_component_update_bits(component,
+ WCD938X_DIGITAL_CDC_COMP_CTL_0,
+ 0x02, 0x02);
}
/* 5 msec delay as per HW requirement */
usleep_range(5000, 5010);
@@ -683,8 +685,10 @@
WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 0x04, 0x00);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x00);
- snd_soc_component_update_bits(component,
- WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x02, 0x00);
+ if (wcd938x->comp1_enable)
+ snd_soc_component_update_bits(component,
+ WCD938X_DIGITAL_CDC_COMP_CTL_0,
+ 0x02, 0x00);
}
snd_soc_component_update_bits(component,
WCD938X_ANA_EAR_COMPANDER_CTL, 0x80, 0x00);
diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c
index 1e6757d..9e25e53 100644
--- a/asoc/codecs/wsa883x/wsa883x.c
+++ b/asoc/codecs/wsa883x/wsa883x.c
@@ -238,8 +238,13 @@
if (!is_swr_slave_reg_readable(i))
continue;
swr_read(pdev, pdev->dev_num, i, ®_val, 1);
- len = snprintf(tmp_buf, 25, "0x%.3x: 0x%.2x\n", i,
+ len = snprintf(tmp_buf, sizeof(tmp_buf), "0x%.3x: 0x%.2x\n", i,
(reg_val & 0xFF));
+ if (len < 0) {
+ pr_err("%s: fail to fill the buffer\n", __func__);
+ total = -EFAULT;
+ goto copy_err;
+ }
if ((total + len) >= count - 1)
break;
if (copy_to_user((ubuf + total), tmp_buf, len)) {
diff --git a/asoc/kona.c b/asoc/kona.c
index 4382689..7560fa9 100644
--- a/asoc/kona.c
+++ b/asoc/kona.c
@@ -31,6 +31,7 @@
#include "asoc/wcd-mbhc-v2.h"
#include "codecs/wcd938x/wcd938x-mbhc.h"
#include "codecs/wsa881x.h"
+#include "codecs/wsa883x/wsa883x.h"
#include "codecs/wcd938x/wcd938x.h"
#include "codecs/bolero/bolero-cdc.h"
#include <dt-bindings/sound/audio-codec-port-types.h>
@@ -7570,9 +7571,14 @@
if (!strcmp(component->name_prefix, "SpkrLeft")) {
dev_dbg(component->dev, "%s: setting left ch map to codec %s\n",
__func__, component->name);
- wsa881x_set_channel_map(component, &spkleft_ports[0],
- WSA881X_MAX_SWR_PORTS, &ch_mask[0],
- &ch_rate[0], &spkleft_port_types[0]);
+ if (strnstr(component->name, "wsa883x", sizeof(component->name)))
+ wsa883x_set_channel_map(component, &spkleft_ports[0],
+ WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+ &ch_rate[0], &spkleft_port_types[0]);
+ else
+ wsa881x_set_channel_map(component, &spkleft_ports[0],
+ WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+ &ch_rate[0], &spkleft_port_types[0]);
if (dapm->component) {
snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN");
snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR");
@@ -7580,9 +7586,14 @@
} else if (!strcmp(component->name_prefix, "SpkrRight")) {
dev_dbg(component->dev, "%s: setting right ch map to codec %s\n",
__func__, component->name);
- wsa881x_set_channel_map(component, &spkright_ports[0],
- WSA881X_MAX_SWR_PORTS, &ch_mask[0],
- &ch_rate[0], &spkright_port_types[0]);
+ if (strnstr(component->name, "wsa883x", sizeof(component->name)))
+ wsa883x_set_channel_map(component, &spkright_ports[0],
+ WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+ &ch_rate[0], &spkright_port_types[0]);
+ else
+ wsa881x_set_channel_map(component, &spkright_ports[0],
+ WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+ &ch_rate[0], &spkright_port_types[0]);
if (dapm->component) {
snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN");
snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR");
@@ -7605,8 +7616,12 @@
}
pdata->codec_root = entry;
}
- wsa881x_codec_info_create_codec_entry(pdata->codec_root,
- component);
+ if (strnstr(component->name, "wsa883x", sizeof(component->name)))
+ wsa883x_codec_info_create_codec_entry(pdata->codec_root,
+ component);
+ else
+ wsa881x_codec_info_create_codec_entry(pdata->codec_root,
+ component);
err:
return ret;
}
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 70e2ebf..d4fbe39 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -30222,6 +30222,50 @@
msm_aptx_dec_license_control_put),
};
+static int msm_routing_get_pll_clk_drift(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return 0;
+}
+
+static int msm_routing_put_pll_clk_drift(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u16 port_id = 0;
+ int32_t clk_drift = 0;
+ uint32_t clk_reset = 0;
+ int be_idx, ret = -EINVAL;
+
+ be_idx = ucontrol->value.integer.value[0];
+ clk_drift = ucontrol->value.integer.value[1];
+ clk_reset = ucontrol->value.integer.value[2];
+
+ if (be_idx < 0 && be_idx >= MSM_BACKEND_DAI_MAX) {
+ pr_err("%s: Invalid be id %d\n", __func__, be_idx);
+ return -EINVAL;
+ }
+
+ if (!msm_bedais[be_idx].active && !clk_reset) {
+ pr_err("%s:BE is not active %d, cannot set clock drift\n",
+ __func__, be_idx);
+ return -EINVAL;
+ }
+
+ port_id = msm_bedais[be_idx].port_id;
+ pr_debug("%s: clk drift %d be idx %d clk reset %d port id 0x%x\n",
+ __func__, clk_drift, be_idx, clk_reset, port_id);
+ ret = afe_set_pll_clk_drift(port_id, clk_drift, clk_reset);
+ if (ret < 0)
+ pr_err("%s: failed to set pll clk drift\n", __func__);
+
+ return ret;
+}
+
+static const struct snd_kcontrol_new pll_clk_drift_controls[] = {
+ SOC_SINGLE_MULTI_EXT("PLL config data", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+ 0, 128, msm_routing_get_pll_clk_drift, msm_routing_put_pll_clk_drift),
+};
+
static int msm_routing_put_port_chmap_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -30522,6 +30566,9 @@
port_multi_channel_map_mixer_controls,
ARRAY_SIZE(port_multi_channel_map_mixer_controls));
+ snd_soc_add_component_controls(component, pll_clk_drift_controls,
+ ARRAY_SIZE(pll_clk_drift_controls));
+
return 0;
}
diff --git a/asoc/qcs405.c b/asoc/qcs405.c
index b76728c..241305c 100644
--- a/asoc/qcs405.c
+++ b/asoc/qcs405.c
@@ -6552,6 +6552,36 @@
return ret;
}
+static int msm_mi2s_snd_hw_free(struct snd_pcm_substream *substream)
+{
+ int i, data_format = 0;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ int index = rtd->cpu_dai->id;
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_component *component;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ data_format = mi2s_rx_cfg[index].data_format;
+ else
+ data_format = mi2s_tx_cfg[index].data_format;
+
+ pr_debug("%s(): substream = %s stream = %d\n", __func__,
+ substream->name, substream->stream);
+
+ /* Call csra mute function if data format is DSD, else return */
+ if (data_format != AFE_DSD_DATA)
+ return 0;
+
+ for (i = 0; i < card->num_aux_devs; i++) {
+ component =
+ soc_find_component(card->aux_dev[i].codec_of_node,
+ NULL);
+ csra66x0_hw_free_mute(component);
+ }
+
+ return 0;
+}
+
static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
{
int ret;
@@ -6902,6 +6932,7 @@
static struct snd_soc_ops msm_mi2s_be_ops = {
.startup = msm_mi2s_snd_startup,
+ .hw_free = msm_mi2s_snd_hw_free,
.shutdown = msm_mi2s_snd_shutdown,
};
diff --git a/dsp/audio_cal_utils.c b/dsp/audio_cal_utils.c
index 7e243e8..fab5186 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-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/slab.h>
#include <linux/fs.h>
@@ -57,6 +57,7 @@
case ADM_AUDPROC_CAL_TYPE:
case ADM_LSM_AUDPROC_CAL_TYPE:
case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
+ case ADM_AUDPROC_PERSISTENT_CAL_TYPE:
size = sizeof(struct audio_cal_info_audproc);
break;
case ADM_AUDVOL_CAL_TYPE:
@@ -211,6 +212,7 @@
case ADM_AUDPROC_CAL_TYPE:
case ADM_LSM_AUDPROC_CAL_TYPE:
case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
+ case ADM_AUDPROC_PERSISTENT_CAL_TYPE:
size = sizeof(struct audio_cal_type_audproc);
break;
case ADM_AUDVOL_CAL_TYPE:
diff --git a/dsp/codecs/audio_alac.c b/dsp/codecs/audio_alac.c
index a3e473f..dbe9399 100644
--- a/dsp/codecs/audio_alac.c
+++ b/dsp/codecs/audio_alac.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/types.h>
@@ -10,6 +10,7 @@
static struct miscdevice audio_alac_misc;
static struct ws_mgr audio_alac_ws_mgr;
+#ifdef CONFIG_DEBUG_FS
static const struct file_operations audio_alac_debug_fops = {
.read = audio_aio_debug_read,
.open = audio_aio_debug_open,
@@ -20,6 +21,7 @@
return debugfs_create_file(name, S_IFREG | 0444,
NULL, (void *)data, &audio_alac_debug_fops);
}
+#endif
static int alac_channel_map(u8 *channel_mapping, uint32_t channels);
@@ -323,10 +325,12 @@
}
snprintf(name, sizeof(name), "msm_alac_%04x", audio->ac->session);
+#ifdef CONFIG_DEBUG_FS
audio->dentry = config_debugfs_create_file(name, (void *)audio);
if (IS_ERR_OR_NULL(audio->dentry))
pr_debug("debugfs_create_file failed\n");
+#endif
pr_debug("%s:alacdec success mode[%d]session[%d]\n", __func__,
audio->feedback,
audio->ac->session);
diff --git a/dsp/codecs/audio_ape.c b/dsp/codecs/audio_ape.c
index 319828b..939f1e1 100644
--- a/dsp/codecs/audio_ape.c
+++ b/dsp/codecs/audio_ape.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/types.h>
@@ -10,6 +10,7 @@
static struct miscdevice audio_ape_misc;
static struct ws_mgr audio_ape_ws_mgr;
+#ifdef CONFIG_DEBUG_FS
static const struct file_operations audio_ape_debug_fops = {
.read = audio_aio_debug_read,
.open = audio_aio_debug_open,
@@ -19,6 +20,7 @@
return debugfs_create_file(name, S_IFREG | 0444,
NULL, (void *)data, &audio_ape_debug_fops);
}
+#endif
static long audio_ioctl_shared(struct file *file, unsigned int cmd,
void *arg)
@@ -305,10 +307,12 @@
}
snprintf(name, sizeof(name), "msm_ape_%04x", audio->ac->session);
+#ifdef CONFIG_DEBUG_FS
audio->dentry = config_debugfs_create_file(name, (void *)audio);
if (IS_ERR_OR_NULL(audio->dentry))
pr_debug("debugfs_create_file failed\n");
+#endif
pr_debug("%s:apedec success mode[%d]session[%d]\n", __func__,
audio->feedback,
audio->ac->session);
diff --git a/dsp/codecs/audio_g711alaw.c b/dsp/codecs/audio_g711alaw.c
index 27d7fe0..2aca8e1 100644
--- a/dsp/codecs/audio_g711alaw.c
+++ b/dsp/codecs/audio_g711alaw.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2016-2017, 2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, 2019-2020 The Linux Foundation. All rights reserved.
*/
#include <linux/types.h>
@@ -10,6 +10,7 @@
static struct miscdevice audio_g711alaw_misc;
static struct ws_mgr audio_g711_ws_mgr;
+#ifdef CONFIG_DEBUG_FS
static const struct file_operations audio_g711_debug_fops = {
.read = audio_aio_debug_read,
.open = audio_aio_debug_open,
@@ -20,6 +21,7 @@
return debugfs_create_file(name, S_IFREG | 0444,
NULL, (void *)data, &audio_g711_debug_fops);
}
+#endif
static int g711_channel_map(u8 *channel_mapping, uint32_t channels);
@@ -278,10 +280,12 @@
}
snprintf(name, sizeof(name), "msm_g711_%04x", audio->ac->session);
+#ifdef CONFIG_DEBUG_FS
audio->dentry = config_debugfs_create_file(name, (void *)audio);
if (IS_ERR_OR_NULL(audio->dentry))
pr_debug("%s: debugfs_create_file failed\n", __func__);
+#endif
pr_debug("%s: g711dec success mode[%d]session[%d]\n", __func__,
audio->feedback,
audio->ac->session);
diff --git a/dsp/codecs/audio_g711mlaw.c b/dsp/codecs/audio_g711mlaw.c
index 57c7f1a..623c7a0 100644
--- a/dsp/codecs/audio_g711mlaw.c
+++ b/dsp/codecs/audio_g711mlaw.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2016-2017, 2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, 2019-2020 The Linux Foundation. All rights reserved.
*/
#include <linux/types.h>
@@ -10,6 +10,7 @@
static struct miscdevice audio_g711mlaw_misc;
static struct ws_mgr audio_g711_ws_mgr;
+#ifdef CONFIG_DEBUG_FS
static const struct file_operations audio_g711_debug_fops = {
.read = audio_aio_debug_read,
.open = audio_aio_debug_open,
@@ -20,6 +21,7 @@
return debugfs_create_file(name, S_IFREG | 0444,
NULL, (void *)data, &audio_g711_debug_fops);
}
+#endif
static int g711_channel_map(u8 *channel_mapping, uint32_t channels);
@@ -277,10 +279,12 @@
}
snprintf(name, sizeof(name), "msm_g711_%04x", audio->ac->session);
+#ifdef CONFIG_DEBUG_FS
audio->dentry = config_debugfs_create_file(name, (void *)audio);
if (IS_ERR_OR_NULL(audio->dentry))
pr_debug("%s: debugfs_create_file failed\n", __func__);
+#endif
pr_debug("%s: g711dec success mode[%d]session[%d]\n", __func__,
audio->feedback,
audio->ac->session);
diff --git a/dsp/q6adm.c b/dsp/q6adm.c
index a2f644f..8791e28 100644
--- a/dsp/q6adm.c
+++ b/dsp/q6adm.c
@@ -2149,7 +2149,8 @@
if (cal_index == ADM_AUDPROC_CAL ||
cal_index == ADM_LSM_AUDPROC_CAL ||
- cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
+ cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL ||
+ cal_index == ADM_AUDPROC_PERSISTENT_CAL) {
audproc_cal_info = cal_block->cal_info;
if ((audproc_cal_info->path == path) &&
(cal_block->cal_data.size > 0))
@@ -2187,7 +2188,8 @@
if (cal_index == ADM_AUDPROC_CAL ||
cal_index == ADM_LSM_AUDPROC_CAL ||
- cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
+ cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL ||
+ cal_index == ADM_AUDPROC_PERSISTENT_CAL) {
audproc_cal_info = cal_block->cal_info;
if ((audproc_cal_info->path == path) &&
(audproc_cal_info->app_type == app_type) &&
@@ -2228,7 +2230,8 @@
if (cal_index == ADM_AUDPROC_CAL ||
cal_index == ADM_LSM_AUDPROC_CAL ||
- cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
+ cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL||
+ cal_index == ADM_AUDPROC_PERSISTENT_CAL) {
audproc_cal_info = cal_block->cal_info;
if ((audproc_cal_info->path == path) &&
(audproc_cal_info->app_type == app_type) &&
@@ -2319,6 +2322,9 @@
if (passthr_mode != LISTEN) {
send_adm_cal_type(ADM_AUDPROC_CAL, path, port_id, copp_idx,
perf_mode, app_type, acdb_id, sample_rate);
+ send_adm_cal_type(ADM_AUDPROC_PERSISTENT_CAL, path,
+ port_id, copp_idx, perf_mode, app_type,
+ acdb_id, sample_rate);
} else {
send_adm_cal_type(ADM_LSM_AUDPROC_CAL, path, port_id, copp_idx,
perf_mode, app_type, acdb_id, sample_rate);
@@ -4136,6 +4142,9 @@
case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
ret = ADM_LSM_AUDPROC_PERSISTENT_CAL;
break;
+ case ADM_AUDPROC_PERSISTENT_CAL_TYPE:
+ ret = ADM_AUDPROC_PERSISTENT_CAL;
+ break;
default:
pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
}
@@ -4363,6 +4372,12 @@
adm_set_cal, NULL, NULL} },
{adm_map_cal_data, adm_unmap_cal_data,
cal_utils_match_buf_num} },
+
+ {{ADM_AUDPROC_PERSISTENT_CAL_TYPE,
+ {adm_alloc_cal, adm_dealloc_cal, NULL,
+ adm_set_cal, NULL, NULL} },
+ {adm_map_cal_data, adm_unmap_cal_data,
+ cal_utils_match_buf_num} },
};
pr_debug("%s:\n", __func__);
@@ -4924,7 +4939,15 @@
rc = -ENOMEM;
goto unlock;
}
- } else if (cal_index == ADM_AUDVOL_CAL) {
+ } else if (cal_index == ADM_AUDPROC_PERSISTENT_CAL) {
+ if (cal_block->cal_data.size > AUD_PROC_PERSIST_BLOCK_SIZE) {
+ pr_err("%s:persist invalid size exp/actual[%zd, %d]\n",
+ __func__, cal_block->cal_data.size, *size);
+ rc = -ENOMEM;
+ goto unlock;
+ }
+ }
+ else if (cal_index == ADM_AUDVOL_CAL) {
if (cal_block->cal_data.size > AUD_VOL_BLOCK_SIZE) {
pr_err("%s:aud_vol:invalid size exp/actual[%zd, %d]\n",
__func__, cal_block->cal_data.size, *size);
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index 3b26c0c..2586bd5 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -174,6 +174,43 @@
uint32_t v_vali_flag;
};
+struct afe_clkinfo_per_port {
+ u16 port_id; /* AFE port ID */
+ uint32_t clk_id; /* Clock ID */
+};
+
+struct afe_clkinfo_per_port clkinfo_per_port[] = {
+ { AFE_PORT_ID_PRIMARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
+ { AFE_PORT_ID_SECONDARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT},
+ { AFE_PORT_ID_TERTIARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT},
+ { AFE_PORT_ID_QUATERNARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT},
+ { AFE_PORT_ID_QUINARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT},
+ { AFE_PORT_ID_SENARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT},
+ { AFE_PORT_ID_PRIMARY_PCM_RX, Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT},
+ { AFE_PORT_ID_SECONDARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEC_PCM_IBIT},
+ { AFE_PORT_ID_TERTIARY_PCM_RX, Q6AFE_LPASS_CLK_ID_TER_PCM_IBIT},
+ { AFE_PORT_ID_QUATERNARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUAD_PCM_IBIT},
+ { AFE_PORT_ID_QUINARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUIN_PCM_IBIT},
+ { AFE_PORT_ID_SENARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEN_PCM_IBIT},
+ { AFE_PORT_ID_PRIMARY_TDM_RX, Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT},
+ { AFE_PORT_ID_SECONDARY_TDM_RX, Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT},
+ { AFE_PORT_ID_TERTIARY_TDM_RX, Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT},
+ { AFE_PORT_ID_QUATERNARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT},
+ { AFE_PORT_ID_QUINARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUIN_TDM_IBIT},
+ { AFE_PORT_ID_PRIMARY_SPDIF_RX,
+ AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_OUTPUT_CORE},
+ { AFE_PORT_ID_PRIMARY_SPDIF_TX,
+ AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_INPUT_CORE},
+ { AFE_PORT_ID_SECONDARY_SPDIF_RX,
+ AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_OUTPUT_CORE},
+ { AFE_PORT_ID_SECONDARY_SPDIF_TX,
+ AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_INPUT_CORE},
+ { AFE_PORT_ID_PRIMARY_META_MI2S_RX,
+ Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
+ { AFE_PORT_ID_SECONDARY_META_MI2S_RX,
+ Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
+};
+
static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
static unsigned long afe_configured_cmd;
@@ -7843,6 +7880,156 @@
}
EXPORT_SYMBOL(afe_set_lpass_clock);
+static int afe_get_port_idx(u16 port_id)
+{
+ u16 afe_port = 0;
+ int i = -EINVAL;
+
+ pr_debug("%s: port id 0x%x\n", __func__, port_id);
+
+ if ((port_id >= AFE_PORT_ID_TDM_PORT_RANGE_START) &&
+ (port_id <= AFE_PORT_ID_TDM_PORT_RANGE_END))
+ afe_port = port_id & 0xFFF0;
+ else if ((port_id == AFE_PORT_ID_PRIMARY_SPDIF_RX) ||
+ (port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX) ||
+ (port_id == AFE_PORT_ID_SECONDARY_SPDIF_RX) ||
+ (port_id == AFE_PORT_ID_SECONDARY_SPDIF_TX))
+ afe_port = port_id;
+ else
+ afe_port = port_id & 0xFFFE;
+
+ for (i = 0; i < ARRAY_SIZE(clkinfo_per_port); i++) {
+ if (afe_port == clkinfo_per_port[i].port_id) {
+ pr_debug("%s: idx 0x%x port id 0x%x\n", __func__,
+ i, afe_port);
+ return i;
+ }
+ }
+
+ pr_debug("%s: cannot get idx for port id 0x%x\n", __func__,
+ afe_port);
+
+ return -EINVAL;
+}
+
+static int afe_get_clk_id(u16 port_id)
+{
+ u16 afe_port = 0;
+ uint32_t clk_id = -EINVAL;
+ int idx = 0;
+
+ idx = afe_get_port_idx(port_id);
+ if (idx < 0) {
+ pr_err("%s: cannot get clock id for port id 0x%x\n", __func__,
+ afe_port);
+ return -EINVAL;
+ }
+
+ clk_id = clkinfo_per_port[idx].clk_id;
+ pr_debug("%s: clk id 0x%x port id 0x%x\n", __func__, clk_id,
+ afe_port);
+
+ return clk_id;
+}
+
+/**
+ * afe_set_clk_id - Update clock id for AFE port
+ *
+ * @port_id: AFE port id
+ * @clk_id: CLock ID
+ *
+ * Returns 0 on success, appropriate error code otherwise
+ */
+int afe_set_clk_id(u16 port_id, uint32_t clk_id)
+{
+ u16 afe_port = 0;
+ int idx = 0;
+
+ idx = afe_get_port_idx(port_id);
+ if (idx < 0) {
+ pr_debug("%s: cannot set clock id for port id 0x%x\n", __func__,
+ afe_port);
+ return -EINVAL;
+ }
+
+ clkinfo_per_port[idx].clk_id = clk_id;
+ pr_debug("%s: updated clk id 0x%x port id 0x%x\n", __func__,
+ clkinfo_per_port[idx].clk_id, afe_port);
+
+ return 0;
+}
+EXPORT_SYMBOL(afe_set_clk_id);
+
+/**
+ * afe_set_pll_clk_drift - Set audio interface PLL clock drift
+ *
+ * @port_id: AFE port id
+ * @set_clk_drift: clk drift to adjust PLL
+ * @clk_reset: reset Interface clock to original value
+ *
+ * Returns 0 on success, appropriate error code otherwise
+ */
+int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift,
+ uint32_t clk_reset)
+{
+ struct afe_set_clk_drift clk_drift;
+ struct param_hdr_v3 param_hdr;
+ uint32_t clk_id;
+ int index = 0, ret = 0;
+
+ memset(¶m_hdr, 0, sizeof(param_hdr));
+ memset(&clk_drift, 0, sizeof(clk_drift));
+
+ index = q6audio_get_port_index(port_id);
+ if (index < 0 || index >= AFE_MAX_PORTS) {
+ pr_err("%s: index[%d] invalid!\n", __func__, index);
+ return -EINVAL;
+ }
+
+ ret = afe_q6_interface_prepare();
+ if (ret != 0) {
+ pr_err_ratelimited("%s: Q6 interface prepare failed %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ clk_id = afe_get_clk_id(port_id);
+ if (clk_id < 0) {
+ pr_err("%s: cannot get clk id for port id 0x%x\n",
+ __func__, port_id);
+ return -EINVAL;
+ }
+
+ if (clk_id & 0x01) {
+ pr_err("%s: cannot adjust clock drift for external clock id 0x%x\n",
+ __func__, clk_id);
+ return -EINVAL;
+ }
+
+ clk_drift.clk_drift = set_clk_drift;
+ clk_drift.clk_reset = clk_reset;
+ clk_drift.clk_id = clk_id;
+ pr_debug("%s: clk id = 0x%x clk drift = %d clk reset = %d port id 0x%x\n",
+ __func__, clk_drift.clk_id, clk_drift.clk_drift,
+ clk_drift.clk_reset, port_id);
+
+ mutex_lock(&this_afe.afe_clk_lock);
+ param_hdr.module_id = AFE_MODULE_CLOCK_SET;
+ param_hdr.instance_id = INSTANCE_ID_0;
+ param_hdr.param_id = AFE_PARAM_ID_CLOCK_ADJUST;
+ param_hdr.param_size = sizeof(struct afe_set_clk_drift);
+
+ ret = q6afe_svc_pack_and_set_param_in_band(index, param_hdr,
+ (u8 *) &clk_drift);
+ if (ret < 0)
+ pr_err_ratelimited("%s: AFE PLL clk drift failed with ret %d\n",
+ __func__, ret);
+
+ mutex_unlock(&this_afe.afe_clk_lock);
+ return ret;
+}
+EXPORT_SYMBOL(afe_set_pll_clk_drift);
+
/**
* afe_set_lpass_clk_cfg - Set AFE clk config
*
@@ -7929,6 +8116,10 @@
return -EINVAL;
}
+ ret = afe_set_clk_id(port_id, cfg->clk_id);
+ if (ret < 0)
+ pr_debug("%s: afe_set_clk_id fail %d\n", __func__, ret);
+
ret = afe_set_lpass_clk_cfg(index, cfg);
if (ret)
pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n",
diff --git a/dsp/q6asm.c b/dsp/q6asm.c
index 6b0a377..fef09c5 100644
--- a/dsp/q6asm.c
+++ b/dsp/q6asm.c
@@ -145,56 +145,6 @@
};
static struct generic_get_data_ *generic_get_data;
-#ifdef CONFIG_DEBUG_FS
-#define OUT_BUFFER_SIZE 56
-#define IN_BUFFER_SIZE 24
-
-static struct timeval out_cold_tv;
-static struct timeval out_warm_tv;
-static struct timeval out_cont_tv;
-static struct timeval in_cont_tv;
-static long out_enable_flag;
-static long in_enable_flag;
-static struct dentry *out_dentry;
-static struct dentry *in_dentry;
-static int in_cont_index;
-/*This var is used to keep track of first write done for cold output latency */
-static int out_cold_index;
-static char *out_buffer;
-static char *in_buffer;
-
-static uint32_t adsp_reg_event_opcode[] = {
- ASM_STREAM_CMD_REGISTER_PP_EVENTS,
- ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS,
- ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE };
-
-static uint32_t adsp_raise_event_opcode[] = {
- ASM_STREAM_PP_EVENT,
- ASM_STREAM_CMD_ENCDEC_EVENTS,
- ASM_IEC_61937_MEDIA_FMT_EVENT };
-
-static int is_adsp_reg_event(uint32_t cmd)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(adsp_reg_event_opcode); i++) {
- if (cmd == adsp_reg_event_opcode[i])
- return i;
- }
- return -EINVAL;
-}
-
-static int is_adsp_raise_event(uint32_t cmd)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(adsp_raise_event_opcode); i++) {
- if (cmd == adsp_raise_event_opcode[i])
- return i;
- }
- return -EINVAL;
-}
-
static inline void q6asm_set_flag_in_token(union asm_token_struct *asm_token,
int flag, int flag_offset)
{
@@ -277,6 +227,56 @@
}
EXPORT_SYMBOL(q6asm_get_stream_id_from_token);
+static uint32_t adsp_reg_event_opcode[] = {
+ ASM_STREAM_CMD_REGISTER_PP_EVENTS,
+ ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS,
+ ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE };
+
+static int is_adsp_reg_event(uint32_t cmd)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(adsp_reg_event_opcode); i++) {
+ if (cmd == adsp_reg_event_opcode[i])
+ return i;
+ }
+ return -EINVAL;
+}
+
+static uint32_t adsp_raise_event_opcode[] = {
+ ASM_STREAM_PP_EVENT,
+ ASM_STREAM_CMD_ENCDEC_EVENTS,
+ ASM_IEC_61937_MEDIA_FMT_EVENT };
+
+static int is_adsp_raise_event(uint32_t cmd)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(adsp_raise_event_opcode); i++) {
+ if (cmd == adsp_raise_event_opcode[i])
+ return i;
+ }
+ return -EINVAL;
+}
+
+#ifdef CONFIG_DEBUG_FS
+#define OUT_BUFFER_SIZE 56
+#define IN_BUFFER_SIZE 24
+
+static struct timeval out_cold_tv;
+static struct timeval out_warm_tv;
+static struct timeval out_cont_tv;
+static struct timeval in_cont_tv;
+static long out_enable_flag;
+static long in_enable_flag;
+static struct dentry *out_dentry;
+static struct dentry *in_dentry;
+static int in_cont_index;
+/*This var is used to keep track of first write done for cold output latency */
+static int out_cold_index;
+static char *out_buffer;
+static char *in_buffer;
+
static int audio_output_latency_dbgfs_open(struct inode *inode,
struct file *file)
{
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index 7d56a4d..5ac7751 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -11766,6 +11766,35 @@
#define AFE_MODULE_CLOCK_SET 0x0001028F
#define AFE_PARAM_ID_CLOCK_SET 0x00010290
+struct afe_set_clk_drift {
+ /*
+ * Clock ID
+ * @values
+ * - 0x100 to 0x10E
+ * - 0x200 to 0x20C
+ * - 0x500 to 0x505
+ */
+ uint32_t clk_id;
+
+ /*
+ * Clock drift (in PPB) to be set.
+ * @values
+ * - need to get values from DSP team
+ */
+ int32_t clk_drift;
+
+ /*
+ * Clock rest.
+ * @values
+ * - 1 -- Reset PLL with the original frequency
+ * - 0 -- Adjust the clock with the clk drift value
+ */
+ uint32_t clk_reset;
+} __packed;
+
+/* This param id is used to adjust audio interface PLL*/
+#define AFE_PARAM_ID_CLOCK_ADJUST 0x000102C6
+
enum afe_lpass_digital_clk_src {
Q6AFE_LPASS_DIGITAL_ROOT_INVALID,
Q6AFE_LPASS_DIGITAL_ROOT_PRI_MI2S_OSR,
diff --git a/include/dsp/q6adm-v2.h b/include/dsp/q6adm-v2.h
index 53514c3..644855d 100644
--- a/include/dsp/q6adm-v2.h
+++ b/include/dsp/q6adm-v2.h
@@ -35,6 +35,7 @@
ADM_SRS_TRUMEDIA,
ADM_RTAC_AUDVOL_CAL,
ADM_LSM_AUDPROC_PERSISTENT_CAL,
+ ADM_AUDPROC_PERSISTENT_CAL,
ADM_MAX_CAL_TYPES
};
diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h
index 76617a9..3ff3028 100644
--- a/include/dsp/q6afe-v2.h
+++ b/include/dsp/q6afe-v2.h
@@ -487,6 +487,9 @@
void (*afe_cb_wakeup_irq)(void *handle));
int afe_get_doa_tracking_mon(u16 port_id,
struct doa_tracking_mon_param *doa_tracking_data);
+int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift,
+ uint32_t clk_reset);
+int afe_set_clk_id(u16 port_id, uint32_t clk_id);
enum {
AFE_LPASS_CORE_HW_BLOCK_ID_NONE,
diff --git a/ipc/apr.c b/ipc/apr.c
index 0ea2694..5476187 100644
--- a/ipc/apr.c
+++ b/ipc/apr.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2010-2014, 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, 2016-2020 The Linux Foundation. All rights reserved.
*/
#include <linux/kernel.h>
@@ -1117,9 +1117,9 @@
}
#else
static int __init apr_debug_init(void)
-(
+{
return 0;
-)
+}
#endif
static void apr_cleanup(void)
@@ -1140,7 +1140,9 @@
mutex_destroy(&client[i][j].svc[k].m_lock);
}
}
+#ifdef CONFIG_DEBUG_FS
debugfs_remove(debugfs_apr_debug);
+#endif
}
static int apr_probe(struct platform_device *pdev)
diff --git a/ipc/apr_vm.c b/ipc/apr_vm.c
index f94e3a2..1b66013 100644
--- a/ipc/apr_vm.c
+++ b/ipc/apr_vm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2010-2014, 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, 2016-2020 The Linux Foundation. All rights reserved.
*/
#include <linux/kernel.h>
@@ -1308,9 +1308,9 @@
}
#else
static int __init apr_debug_init(void)
-(
+{
return 0;
-)
+}
#endif
static void apr_cleanup(void)
@@ -1331,7 +1331,9 @@
mutex_destroy(&client[i][j].svc[k].m_lock);
}
}
+#ifdef CONFIG_DEBUG_FS
debugfs_remove(debugfs_apr_debug);
+#endif
}
static int apr_probe(struct platform_device *pdev)