Merge "ASoC: wcd938x: Resolve noise during dmic record"
diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c
index 9e25e53..cee2a32 100644
--- a/asoc/codecs/wsa883x/wsa883x.c
+++ b/asoc/codecs/wsa883x/wsa883x.c
@@ -92,9 +92,10 @@
{WSA883X_DRE_CTL_0, 0xF0, 0x90},
{WSA883X_DRE_IDLE_DET_CTL, 0x10, 0x00},
{WSA883X_PDM_WD_CTL, 0x01, 0x01},
- {WSA883X_CURRENT_LIMIT, 0x78, 0x40},
+ {WSA883X_CURRENT_LIMIT, 0x78, 0x20},
{WSA883X_DRE_CTL_0, 0x07, 0x02},
- {WSA883X_VAGC_TIME, 0x03, 0x02},
+ {WSA883X_VAGC_TIME, 0x0F, 0x0F},
+ {WSA883X_VAGC_ATTN_LVL_3, 0x07, 0x02},
{WSA883X_VAGC_CTL, 0x01, 0x01},
{WSA883X_TAGC_CTL, 0x0E, 0x0A},
{WSA883X_TAGC_TIME, 0x0C, 0x0C},
diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c
index fdf61cf..b34202c 100644
--- a/asoc/msm-compress-q6-v2.c
+++ b/asoc/msm-compress-q6-v2.c
@@ -225,7 +225,7 @@
int stream_id);
static int msm_compr_set_render_mode(struct msm_compr_audio *prtd,
- uint32_t render_mode) {
+ uint32_t render_mode, int dir) {
int ret = -EINVAL;
struct audio_client *ac = prtd->audio_client;
@@ -250,7 +250,7 @@
goto exit;
}
- ret = q6asm_send_mtmx_strtr_render_mode(ac, render_mode);
+ ret = q6asm_send_mtmx_strtr_render_mode(ac, render_mode, dir);
if (ret) {
pr_err("%s, Render mode can't be set error %d\n", __func__,
ret);
@@ -324,6 +324,29 @@
return ret;
}
+static int msm_compr_set_ttp_offset(struct audio_client *ac,
+ uint32_t offset_lsw, uint32_t offset_msw, int dir)
+{
+ int ret = -EINVAL;
+ struct asm_session_mtmx_strtr_param_ttp_offset_t ttp_offset;
+ uint32_t param_id;
+
+ pr_debug("%s, ttp offset lsw 0x%x ttp offset msw 0x%x\n",
+ __func__, offset_lsw, offset_msw);
+
+ memset(&ttp_offset, 0,
+ sizeof(struct asm_session_mtmx_strtr_param_ttp_offset_t));
+ ttp_offset.ttp_offset_lsw = offset_lsw;
+ ttp_offset.ttp_offset_msw = offset_msw;
+ param_id = ASM_SESSION_MTMX_STRTR_PARAM_TTP_OFFSET;
+ ret = q6asm_send_mtmx_strtr_ttp_offset(ac, &ttp_offset, param_id, dir);
+ if (ret)
+ pr_err("%s, ttp offset can't be set error %d\n", __func__,
+ ret);
+
+ return ret;
+}
+
static int msm_compr_enable_adjust_session_clock(struct audio_client *ac,
bool enable)
{
@@ -3221,7 +3244,8 @@
__func__, metadata->value[0]);
prtd->gapless_state.initial_samples_drop = metadata->value[0];
} else if (metadata->key == SNDRV_COMPRESS_RENDER_MODE) {
- return msm_compr_set_render_mode(prtd, metadata->value[0]);
+ return msm_compr_set_render_mode(prtd, metadata->value[0],
+ cstream->direction);
} else if (metadata->key == SNDRV_COMPRESS_CLK_REC_MODE) {
return msm_compr_set_clk_rec_mode(ac, metadata->value[0]);
} else if (metadata->key == SNDRV_COMPRESS_RENDER_WINDOW) {
@@ -3242,6 +3266,9 @@
return msm_compr_adjust_session_clock(ac,
metadata->value[0],
metadata->value[1]);
+ } else if (metadata->key == SNDRV_COMPRESS_IN_TTP_OFFSET) {
+ return msm_compr_set_ttp_offset(ac, metadata->value[0],
+ metadata->value[1], cstream->direction);
}
return 0;
diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c
index a0d9895..4dd8c9c 100644
--- a/asoc/msm-dai-q6-v2.c
+++ b/asoc/msm-dai-q6-v2.c
@@ -232,6 +232,7 @@
u16 afe_tx_out_bitformat;
struct afe_enc_config enc_config;
struct afe_dec_config dec_config;
+ struct afe_ttp_config ttp_config;
union afe_port_config port_config;
u16 vi_feed_mono;
u32 xt_logging_disable;
@@ -2230,6 +2231,7 @@
{
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
int rc = 0;
+ uint16_t ttp_gen_enable = dai_data->ttp_config.ttp_gen_enable.enable;
if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
if (dai_data->enc_config.format != ENC_FMT_NONE) {
@@ -2279,13 +2281,27 @@
bitwidth = 0;
break;
}
- pr_debug("%s: calling AFE_PORT_START_V2 with dec format: %d\n",
- __func__, dai_data->dec_config.format);
- rc = afe_port_start_v2(dai->id, &dai_data->port_config,
- dai_data->rate,
- dai_data->afe_tx_out_channels,
- bitwidth,
- NULL, &dai_data->dec_config);
+
+ if (ttp_gen_enable == true) {
+ pr_debug("%s: calling AFE_PORT_START_V3 with dec format: %d\n",
+ __func__, dai_data->dec_config.format);
+ rc = afe_port_start_v3(dai->id,
+ &dai_data->port_config,
+ dai_data->rate,
+ dai_data->afe_tx_out_channels,
+ bitwidth,
+ NULL, &dai_data->dec_config,
+ &dai_data->ttp_config);
+ } else {
+ pr_debug("%s: calling AFE_PORT_START_V2 with dec format: %d\n",
+ __func__, dai_data->dec_config.format);
+ rc = afe_port_start_v2(dai->id,
+ &dai_data->port_config,
+ dai_data->rate,
+ dai_data->afe_tx_out_channels,
+ bitwidth,
+ NULL, &dai_data->dec_config);
+ }
if (rc < 0) {
pr_err("%s: fail to open AFE port 0x%x\n",
__func__, dai->id);
@@ -3669,6 +3685,91 @@
return ret;
}
+static int msm_dai_q6_afe_enable_ttp_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ uinfo->count = sizeof(struct afe_ttp_gen_enable_t);
+
+ return 0;
+}
+
+static int msm_dai_q6_afe_enable_ttp_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+ pr_debug("%s:\n", __func__);
+ if (!dai_data) {
+ pr_err("%s: Invalid dai data\n", __func__);
+ return -EINVAL;
+ }
+
+ memcpy(ucontrol->value.bytes.data,
+ &dai_data->ttp_config.ttp_gen_enable,
+ sizeof(struct afe_ttp_gen_enable_t));
+ return 0;
+}
+
+static int msm_dai_q6_afe_enable_ttp_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+ pr_debug("%s:\n", __func__);
+ if (!dai_data) {
+ pr_err("%s: Invalid dai data\n", __func__);
+ return -EINVAL;
+ }
+
+ memcpy(&dai_data->ttp_config.ttp_gen_enable,
+ ucontrol->value.bytes.data,
+ sizeof(struct afe_ttp_gen_enable_t));
+ return 0;
+}
+
+static int msm_dai_q6_afe_ttp_cfg_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ uinfo->count = sizeof(struct afe_ttp_gen_cfg_t);
+
+ return 0;
+}
+
+static int msm_dai_q6_afe_ttp_cfg_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+ pr_debug("%s:\n", __func__);
+ if (!dai_data) {
+ pr_err("%s: Invalid dai data\n", __func__);
+ return -EINVAL;
+ }
+
+ memcpy(ucontrol->value.bytes.data,
+ &dai_data->ttp_config.ttp_gen_cfg,
+ sizeof(struct afe_ttp_gen_cfg_t));
+ return 0;
+}
+
+static int msm_dai_q6_afe_ttp_cfg_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+ pr_debug("%s: Received ttp config\n", __func__);
+ if (!dai_data) {
+ pr_err("%s: Invalid dai data\n", __func__);
+ return -EINVAL;
+ }
+
+ memcpy(&dai_data->ttp_config.ttp_gen_cfg,
+ ucontrol->value.bytes.data, sizeof(struct afe_ttp_gen_cfg_t));
+ return 0;
+}
+
static const struct snd_kcontrol_new afe_dec_config_controls[] = {
{
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -3696,6 +3797,27 @@
msm_dai_q6_afe_output_bit_format_put),
};
+static const struct snd_kcontrol_new afe_ttp_config_controls[] = {
+ {
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE),
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "TTP Enable",
+ .info = msm_dai_q6_afe_enable_ttp_info,
+ .get = msm_dai_q6_afe_enable_ttp_get,
+ .put = msm_dai_q6_afe_enable_ttp_put,
+ },
+ {
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE),
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "AFE TTP config",
+ .info = msm_dai_q6_afe_ttp_cfg_info,
+ .get = msm_dai_q6_afe_ttp_cfg_get,
+ .put = msm_dai_q6_afe_ttp_cfg_put,
+ },
+};
+
static int msm_dai_q6_slim_rx_drift_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
@@ -3919,6 +4041,12 @@
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&afe_dec_config_controls[3],
dai_data));
+ rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&afe_ttp_config_controls[0],
+ dai_data));
+ rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&afe_ttp_config_controls[1],
+ dai_data));
break;
case RT_PROXY_DAI_001_RX:
rc = snd_ctl_add(dai->component->card->snd_card,
diff --git a/asoc/msm-lsm-client.c b/asoc/msm-lsm-client.c
index b6624f0..8a179fd 100644
--- a/asoc/msm-lsm-client.c
+++ b/asoc/msm-lsm-client.c
@@ -12,6 +12,7 @@
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/freezer.h>
+#include <linux/version.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
@@ -92,7 +93,7 @@
int xrun_count;
int xrun_index;
spinlock_t xrun_lock;
- struct wakeup_source ws;
+ struct wakeup_source *ws;
};
enum { /* lsm session states */
@@ -220,7 +221,7 @@
}
rtd = substream->private_data;
- pm_wakeup_ws_event(&prtd->ws, WAKELOCK_TIMEOUT, true);
+ pm_wakeup_ws_event(prtd->ws, WAKELOCK_TIMEOUT, true);
dev_dbg(rtd->dev, "%s: opcode %x\n", __func__, opcode);
switch (opcode) {
case LSM_DATA_EVENT_READ_DONE: {
@@ -235,13 +236,13 @@
"%s: EVENT_READ_DONE invalid callback, session %d callback %d payload %pK",
__func__, prtd->lsm_client->session,
token, read_done);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return;
}
if (atomic_read(&prtd->read_abort)) {
dev_dbg(rtd->dev,
"%s: read abort set skip data\n", __func__);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return;
}
if (!lsm_lab_buffer_sanity(prtd, read_done, &buf_index)) {
@@ -254,7 +255,7 @@
"%s: Invalid index %d buf_index max cnt %d\n",
__func__, buf_index,
prtd->lsm_client->out_hw_params.period_count);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return;
}
spin_lock_irqsave(&prtd->xrun_lock, flags);
@@ -292,7 +293,7 @@
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return;
}
status = (uint16_t)((uint8_t *)payload)[0];
@@ -308,7 +309,7 @@
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return;
}
status = (uint16_t)((uint8_t *)payload)[0];
@@ -324,7 +325,7 @@
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return;
}
event_ts_lsw = ((uint32_t *)payload)[0];
@@ -344,7 +345,7 @@
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return;
}
@@ -364,7 +365,7 @@
"LSM_SESSION_DETECTION_ENGINE_GENERIC_EVENT",
sizeof(struct snd_lsm_event_status) +
payload_size);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return;
}
@@ -379,7 +380,7 @@
dev_err(rtd->dev,
"%s: Failed to copy memory with invalid size = %d\n",
__func__, payload_size);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return;
}
prtd->event_avail = 1;
@@ -411,7 +412,7 @@
if (!temp) {
dev_err(rtd->dev, "%s: no memory for event status\n",
__func__);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return;
}
/*
@@ -438,7 +439,7 @@
dev_err(rtd->dev,
"%s: Failed to copy memory with invalid size = %d\n",
__func__, payload_size);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return;
}
} else {
@@ -1156,7 +1157,7 @@
dev_err(rtd->dev,
"%s: lsm open failed, %d\n",
__func__, ret);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return ret;
}
prtd->lsm_client->opened = true;
@@ -1504,14 +1505,14 @@
if (prtd->lsm_client->num_stages > 1) {
dev_err(rtd->dev, "%s: %s: not supported for multi stage session\n",
__func__, "LSM_LAB_CONTROL");
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return -EINVAL;
}
if (copy_from_user(&enable, arg, sizeof(enable))) {
dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n",
__func__, "LSM_LAB_CONTROL");
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return -EFAULT;
}
@@ -1566,7 +1567,7 @@
if (copy_from_user(&mode, arg, sizeof(mode))) {
dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n",
__func__, "LSM_SET_FWK_MODE_CONFIG");
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return -EFAULT;
}
@@ -1597,7 +1598,7 @@
if (copy_from_user(¶ms, arg, sizeof(params))) {
dev_err(rtd->dev, "%s: %s: copy_from_user failed\n",
__func__, "LSM_SET_INPUT_HW_PARAMS");
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return -EFAULT;
}
@@ -1624,7 +1625,7 @@
dev_err(rtd->dev, "%s: cmd 0x%x failed %d\n",
__func__, cmd, rc);
- __pm_relax(&prtd->ws);
+ __pm_relax(prtd->ws);
return rc;
}
@@ -2528,8 +2529,11 @@
prtd->lsm_client->event_type = LSM_DET_EVENT_TYPE_LEGACY;
prtd->lsm_client->fe_id = rtd->dai_link->id;
prtd->lsm_client->unprocessed_data = 0;
-
- wakeup_source_init(&prtd->ws, "lsm-client");
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 110))
+ prtd->ws = wakeup_source_register(rtd->dev, "lsm-client");
+#else
+ prtd->ws = wakeup_source_register("lsm-client");
+#endif
return 0;
}
@@ -2774,7 +2778,7 @@
q6lsm_client_free(prtd->lsm_client);
- wakeup_source_trash(&prtd->ws);
+ wakeup_source_unregister(prtd->ws);
spin_lock_irqsave(&prtd->event_lock, flags);
kfree(prtd->event_status);
prtd->event_status = NULL;
diff --git a/asoc/msm-transcode-loopback-q6-v2.c b/asoc/msm-transcode-loopback-q6-v2.c
index e20f0df..bba4ad7 100644
--- a/asoc/msm-transcode-loopback-q6-v2.c
+++ b/asoc/msm-transcode-loopback-q6-v2.c
@@ -613,7 +613,7 @@
}
static int msm_transcode_set_render_mode(struct msm_transcode_loopback *prtd,
- uint32_t render_mode)
+ uint32_t render_mode, int dir)
{
int ret = -EINVAL;
struct audio_client *ac = prtd->audio_client;
@@ -639,7 +639,7 @@
goto exit;
}
- ret = q6asm_send_mtmx_strtr_render_mode(ac, render_mode);
+ ret = q6asm_send_mtmx_strtr_render_mode(ac, render_mode, dir);
if (ret) {
pr_err("%s: Render mode can't be set error %d\n", __func__,
ret);
@@ -705,7 +705,8 @@
}
case SNDRV_COMPRESS_RENDER_MODE:
{
- rc = msm_transcode_set_render_mode(prtd, metadata->value[0]);
+ rc = msm_transcode_set_render_mode(prtd, metadata->value[0],
+ cstream->direction);
if (rc)
pr_err("%s: error setting render mode %d\n", __func__,
rc);
diff --git a/dsp/codecs/audio_utils.c b/dsp/codecs/audio_utils.c
index ac93413..33495b2 100644
--- a/dsp/codecs/audio_utils.c
+++ b/dsp/codecs/audio_utils.c
@@ -936,6 +936,7 @@
int audio_in_release(struct inode *inode, struct file *file)
{
+ unsigned long flags = 0;
struct q6audio_in *audio = file->private_data;
pr_info("%s: session id %d\n", __func__, audio->ac->session);
@@ -943,11 +944,11 @@
audio_in_disable(audio);
q6asm_audio_client_free(audio->ac);
mutex_unlock(&audio->lock);
- spin_lock(&enc_dec_lock);
+ spin_lock_irqsave(&enc_dec_lock, flags);
kfree(audio->enc_cfg);
kfree(audio->codec_cfg);
kfree(audio);
file->private_data = NULL;
- spin_unlock(&enc_dec_lock);
+ spin_unlock_irqrestore(&enc_dec_lock, flags);
return 0;
}
diff --git a/dsp/codecs/audio_utils_aio.c b/dsp/codecs/audio_utils_aio.c
index 93095e3..94be57d 100644
--- a/dsp/codecs/audio_utils_aio.c
+++ b/dsp/codecs/audio_utils_aio.c
@@ -588,6 +588,7 @@
int audio_aio_release(struct inode *inode, struct file *file)
{
+ unsigned long flags = 0;
struct q6audio_aio *audio = file->private_data;
pr_debug("%s[%pK]\n", __func__, audio);
@@ -631,11 +632,11 @@
#ifdef CONFIG_DEBUG_FS
debugfs_remove(audio->dentry);
#endif
- spin_lock(&enc_dec_lock);
+ spin_lock_irqsave(&enc_dec_lock, flags);
kfree(audio->codec_cfg);
kfree(audio);
file->private_data = NULL;
- spin_unlock(&enc_dec_lock);
+ spin_unlock_irqrestore(&enc_dec_lock, flags);
mutex_unlock(&lock);
return 0;
}
diff --git a/dsp/codecs/q6audio_v2.c b/dsp/codecs/q6audio_v2.c
index 6a402f5..51ff850 100644
--- a/dsp/codecs/q6audio_v2.c
+++ b/dsp/codecs/q6audio_v2.c
@@ -20,8 +20,9 @@
{
struct q6audio_in *audio = (struct q6audio_in *)priv;
unsigned long flags;
+ unsigned long en_de_flags;
- spin_lock(&enc_dec_lock);
+ spin_lock_irqsave(&enc_dec_lock, en_de_flags);
if (audio == NULL) {
pr_err("%s: failed to get q6audio value\n", __func__);
goto error;
@@ -64,7 +65,7 @@
}
spin_unlock_irqrestore(&audio->dsp_lock, flags);
error:
- spin_unlock(&enc_dec_lock);
+ spin_unlock_irqrestore(&enc_dec_lock, en_de_flags);
}
void audio_in_get_dsp_frames(void *priv,
diff --git a/dsp/codecs/q6audio_v2_aio.c b/dsp/codecs/q6audio_v2_aio.c
index ecd14da..d9dd29b 100644
--- a/dsp/codecs/q6audio_v2_aio.c
+++ b/dsp/codecs/q6audio_v2_aio.c
@@ -42,8 +42,9 @@
{
struct q6audio_aio *audio = (struct q6audio_aio *)priv;
union msm_audio_event_payload e_payload;
+ unsigned long flags = 0;
- spin_lock(&enc_dec_lock);
+ spin_lock_irqsave(&enc_dec_lock, flags);
if (audio == NULL) {
pr_err("%s: failed to get q6audio value\n", __func__);
goto error;
@@ -113,7 +114,7 @@
break;
}
error:
- spin_unlock(&enc_dec_lock);
+ spin_unlock_irqrestore(&enc_dec_lock, flags);
}
int extract_meta_out_info(struct q6audio_aio *audio,
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index 2586bd5..9d5908d 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -10,6 +10,7 @@
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/delay.h>
+#include <linux/version.h>
#include <dsp/msm_audio_ion.h>
#include <dsp/apr_audio-v2.h>
#include <dsp/audio_cal_utils.h>
@@ -98,7 +99,7 @@
};
struct wlock {
- struct wakeup_source ws;
+ struct wakeup_source *ws;
};
static struct wlock wl;
@@ -3924,6 +3925,51 @@
return ret;
}
+static int q6afe_send_ttp_config(u16 port_id,
+ union afe_port_config afe_config,
+ struct afe_ttp_config *ttp_cfg)
+{
+ struct afe_ttp_gen_enable_t ttp_gen_enable;
+ struct afe_ttp_gen_cfg_t ttp_gen_cfg;
+ struct param_hdr_v3 param_hdr;
+ int ret;
+
+ memset(&ttp_gen_enable, 0, sizeof(ttp_gen_enable));
+ memset(&ttp_gen_cfg, 0, sizeof(ttp_gen_cfg));
+ memset(¶m_hdr, 0, sizeof(param_hdr));
+
+ param_hdr.module_id = AFE_MODULE_ID_DECODER;
+ param_hdr.instance_id = INSTANCE_ID_0;
+
+ pr_debug("%s: Enable TTP generator\n", __func__);
+ ttp_gen_enable = ttp_cfg->ttp_gen_enable;
+ param_hdr.param_id = AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_STATE;
+ param_hdr.param_size = sizeof(struct afe_ttp_gen_enable_t);
+ ret = q6afe_pack_and_set_param_in_band(port_id,
+ q6audio_get_port_index(port_id),
+ param_hdr,
+ (u8 *) &ttp_gen_enable);
+ if (ret) {
+ pr_err("%s: AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_STATE for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto exit;
+ }
+
+ pr_debug("%s: sending TTP generator config\n", __func__);
+ ttp_gen_cfg = ttp_cfg->ttp_gen_cfg;
+ param_hdr.param_id = AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_CFG;
+ param_hdr.param_size = sizeof(struct afe_ttp_gen_cfg_t);
+ ret = q6afe_pack_and_set_param_in_band(port_id,
+ q6audio_get_port_index(port_id),
+ param_hdr,
+ (u8 *) &ttp_gen_cfg);
+ if (ret)
+ pr_err("%s: AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_CFG for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+exit:
+ return ret;
+}
+
static int q6afe_send_dec_config(u16 port_id,
union afe_port_config afe_config,
struct afe_dec_config *cfg,
@@ -4594,7 +4640,8 @@
u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
union afe_enc_config_data *enc_cfg,
u32 codec_format, u32 scrambler_mode, u32 mono_mode,
- struct afe_dec_config *dec_cfg)
+ struct afe_dec_config *dec_cfg,
+ struct afe_ttp_config *ttp_cfg)
{
union afe_port_config port_cfg;
struct param_hdr_v3 param_hdr;
@@ -4912,6 +4959,15 @@
goto fail_cmd;
}
}
+ if (ttp_cfg != NULL) {
+ ret = q6afe_send_ttp_config(port_id, *afe_config,
+ ttp_cfg);
+ if (ret) {
+ pr_err("%s: AFE TTP config for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto fail_cmd;
+ }
+ }
}
port_index = afe_get_port_index(port_id);
@@ -4958,8 +5014,8 @@
int afe_port_start(u16 port_id, union afe_port_config *afe_config,
u32 rate)
{
- return __afe_port_start(port_id, afe_config, rate,
- 0, 0, NULL, ASM_MEDIA_FMT_NONE, 0, 0, NULL);
+ return __afe_port_start(port_id, afe_config, rate, 0, 0, NULL,
+ ASM_MEDIA_FMT_NONE, 0, 0, NULL, NULL);
}
EXPORT_SYMBOL(afe_port_start);
@@ -4989,16 +5045,50 @@
afe_in_channels, afe_in_bit_width,
&enc_cfg->data, enc_cfg->format,
enc_cfg->scrambler_mode,
- enc_cfg->mono_mode, dec_cfg);
+ enc_cfg->mono_mode, dec_cfg, NULL);
else if (dec_cfg != NULL)
ret = __afe_port_start(port_id, afe_config, rate,
afe_in_channels, afe_in_bit_width,
- NULL, dec_cfg->format, 0, 0, dec_cfg);
+ NULL, dec_cfg->format, 0, 0,
+ dec_cfg, NULL);
return ret;
}
EXPORT_SYMBOL(afe_port_start_v2);
+/**
+ * afe_port_start_v3 - to configure AFE session with
+ * specified port configuration and encoder /decoder params
+ *
+ * @port_id: AFE port id number
+ * @afe_config: port configuration
+ * @rate: sampling rate of port
+ * @enc_cfg: AFE enc configuration information to setup encoder
+ * @afe_in_channels: AFE input channel configuration, this needs
+ * update only if input channel is differ from AFE output
+ * @dec_cfg: AFE dec configuration information to set up decoder
+ * @ttp_cfg: TTP generator configuration to enable TTP in AFE
+ *
+ * Returns 0 on success or error value on port start failure.
+ */
+int afe_port_start_v3(u16 port_id, union afe_port_config *afe_config,
+ u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
+ struct afe_enc_config *enc_cfg,
+ struct afe_dec_config *dec_cfg,
+ struct afe_ttp_config *ttp_cfg)
+{
+ int ret = 0;
+
+ if (dec_cfg != NULL && ttp_cfg != NULL)
+ ret = __afe_port_start(port_id, afe_config, rate,
+ afe_in_channels, afe_in_bit_width,
+ NULL, dec_cfg->format, 0, 0,
+ dec_cfg, ttp_cfg);
+
+ return ret;
+}
+EXPORT_SYMBOL(afe_port_start_v3);
+
int afe_get_port_index(u16 port_id)
{
switch (port_id) {
@@ -8960,7 +9050,7 @@
goto done;
if (cal_data->cal_info.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
- __pm_wakeup_event(&wl.ws, jiffies_to_msecs(WAKELOCK_TIMEOUT));
+ __pm_wakeup_event(wl.ws, jiffies_to_msecs(WAKELOCK_TIMEOUT));
mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
memcpy(&this_afe.prot_cfg, &cal_data->cal_info,
sizeof(this_afe.prot_cfg));
@@ -9166,7 +9256,7 @@
}
this_afe.initial_cal = 0;
mutex_unlock(&this_afe.cal_data[AFE_FB_SPKR_PROT_CAL]->lock);
- __pm_relax(&wl.ws);
+ __pm_relax(wl.ws);
done:
return ret;
}
@@ -9464,7 +9554,6 @@
init_waitqueue_head(&this_afe.wait_wakeup);
init_waitqueue_head(&this_afe.lpass_core_hw_wait);
init_waitqueue_head(&this_afe.clk_wait);
- wakeup_source_init(&wl.ws, "spkr-prot");
ret = afe_init_cal_data();
if (ret)
pr_err("%s: could not init cal data! %d\n", __func__, ret);
@@ -9474,8 +9563,12 @@
this_afe.uevent_data = kzalloc(sizeof(*(this_afe.uevent_data)), GFP_KERNEL);
if (!this_afe.uevent_data)
return -ENOMEM;
-
- /*
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 110))
+ wl.ws = wakeup_source_register(NULL, "spkr-prot");
+#else
+ wl.ws = wakeup_source_register("spkr-prot");
+#endif
+/*
* Set release function to cleanup memory related to kobject
* before initializing the kobject.
*/
@@ -9509,7 +9602,7 @@
mutex_destroy(&this_afe.afe_cmd_lock);
mutex_destroy(&this_afe.afe_apr_lock);
mutex_destroy(&this_afe.afe_clk_lock);
- wakeup_source_trash(&wl.ws);
+ wakeup_source_unregister(wl.ws);
}
/*
diff --git a/dsp/q6asm.c b/dsp/q6asm.c
index fef09c5..e56c7c5 100644
--- a/dsp/q6asm.c
+++ b/dsp/q6asm.c
@@ -10048,16 +10048,105 @@
EXPORT_SYMBOL(q6asm_send_mtmx_strtr_window);
/**
+ * q6asm_send_mtmx_strtr_ttp_offset -
+ * command to send matrix for ttp offset
+ *
+ * @ac: Audio client handle
+ * @ttp_offset: ttp offset params
+ * @param_id: param id for ttp offset
+ * @dir: RX or TX direction
+ *
+ * Returns 0 on success or error on failure
+ */
+int q6asm_send_mtmx_strtr_ttp_offset(struct audio_client *ac,
+ struct asm_session_mtmx_strtr_param_ttp_offset_t *ttp_offset,
+ uint32_t param_id, int dir)
+{
+ struct asm_mtmx_strtr_params matrix;
+ int sz = 0;
+ int rc = 0;
+
+ pr_debug("%s: ttp offset lsw is %d, ttp offset msw is %d\n", __func__,
+ ttp_offset->ttp_offset_lsw, ttp_offset->ttp_offset_msw);
+
+ if (!ac) {
+ pr_err("%s: audio client handle is NULL\n", __func__);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
+ if (ac->apr == NULL) {
+ pr_err("%s: ac->apr is NULL", __func__);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
+ memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params));
+ sz = sizeof(struct asm_mtmx_strtr_params);
+ q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
+ atomic_set(&ac->cmd_state, -1);
+ matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;
+
+ matrix.param.data_payload_addr_lsw = 0;
+ matrix.param.data_payload_addr_msw = 0;
+ matrix.param.mem_map_handle = 0;
+ matrix.param.data_payload_size =
+ sizeof(struct param_hdr_v1) +
+ sizeof(struct asm_session_mtmx_strtr_param_ttp_offset_t);
+ matrix.param.direction = dir;
+ matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
+ matrix.data.param_id = param_id;
+ matrix.data.param_size =
+ sizeof(struct asm_session_mtmx_strtr_param_ttp_offset_t);
+ matrix.data.reserved = 0;
+ memcpy(&(matrix.config.ttp_offset),
+ ttp_offset,
+ sizeof(struct asm_session_mtmx_strtr_param_ttp_offset_t));
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
+ if (rc < 0) {
+ pr_err("%s: ttp offset send failed paramid [0x%x]\n",
+ __func__, matrix.data.param_id);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!rc) {
+ pr_err("%s: timeout, ttp offset paramid[0x%x]\n",
+ __func__, matrix.data.param_id);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s]\n",
+ __func__, adsp_err_get_err_str(
+ atomic_read(&ac->cmd_state)));
+ rc = adsp_err_get_lnx_err_code(
+ atomic_read(&ac->cmd_state));
+ goto fail_cmd;
+ }
+ rc = 0;
+fail_cmd:
+ return rc;
+}
+EXPORT_SYMBOL(q6asm_send_mtmx_strtr_ttp_offset);
+
+/**
* q6asm_send_mtmx_strtr_render_mode -
* command to send matrix for render mode
*
* @ac: Audio client handle
* @render_mode: rendering mode
+ * @dir: RX or TX direction
*
* Returns 0 on success or error on failure
*/
int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac,
- uint32_t render_mode)
+ uint32_t render_mode, int dir)
{
struct asm_mtmx_strtr_params matrix;
struct asm_session_mtmx_strtr_param_render_mode_t render_param;
@@ -10101,7 +10190,7 @@
matrix.param.data_payload_size =
sizeof(struct param_hdr_v1) +
sizeof(struct asm_session_mtmx_strtr_param_render_mode_t);
- matrix.param.direction = 0; /* RX */
+ matrix.param.direction = dir;
matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
matrix.data.param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_MODE_CMD;
matrix.data.param_size =
diff --git a/dsp/usf.c b/dsp/usf.c
index e408c7d..d0f6ed3 100644
--- a/dsp/usf.c
+++ b/dsp/usf.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017, 2020, The Linux Foundation. All rights reserved.
*/
#include <linux/compat.h>
@@ -15,6 +15,7 @@
#include <linux/time.h>
#include <linux/kmemleak.h>
#include <linux/mutex.h>
+#include <linux/version.h>
#include <dsp/apr_audio-v2.h>
#include "q6usm.h"
#include "usf.h"
@@ -173,7 +174,7 @@
/* The opened devices container */
static atomic_t s_opened_devs[MAX_DEVS_NUMBER];
-static struct wakeup_source usf_wakeup_source;
+static struct wakeup_source *usf_wakeup_source;
#define USF_NAME_PREFIX "usf_"
#define USF_NAME_PREFIX_SIZE 4
@@ -442,7 +443,7 @@
case Q6USM_EVENT_READ_DONE:
pr_debug("%s: acquiring %d msec wake lock\n", __func__,
STAY_AWAKE_AFTER_READ_MSECS);
- __pm_wakeup_event(&usf_wakeup_source,
+ __pm_wakeup_event(usf_wakeup_source,
STAY_AWAKE_AFTER_READ_MSECS);
if (token == USM_WRONG_TOKEN)
usf_xx->usf_state = USF_ERROR_STATE;
@@ -2369,8 +2370,11 @@
usf = kzalloc(sizeof(struct usf_type), GFP_KERNEL);
if (usf == NULL)
return -ENOMEM;
-
- wakeup_source_init(&usf_wakeup_source, "usf");
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 110))
+ usf_wakeup_source = wakeup_source_register(NULL, "usf");
+#else
+ usf_wakeup_source = wakeup_source_register("usf");
+#endif
file->private_data = usf;
usf->dev_ind = dev_ind;
@@ -2401,7 +2405,7 @@
atomic_set(&s_opened_devs[usf->dev_ind], 0);
- wakeup_source_trash(&usf_wakeup_source);
+ wakeup_source_unregister(usf_wakeup_source);
mutex_unlock(&usf->mutex);
mutex_destroy(&usf->mutex);
kfree(usf);
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index 311c892..6814646 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -4732,6 +4732,56 @@
union afe_enc_config_data data;
};
+/*
+ * Enable TTP generator in AFE.
+ */
+#define AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_STATE 0x000132EF
+/*
+ * Configure TTP generator params in AFE.
+ */
+#define AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_CFG 0x000132F0
+#define MAX_TTP_OFFSET_PAIRS 4
+struct afe_ttp_gen_enable_t {
+ uint16_t enable;
+ uint16_t reserved;
+} __packed;
+
+struct afe_ttp_ssrc_offset_pair_t {
+ uint32_t ssrc;
+ uint32_t offset;
+} __packed;
+
+struct afe_ttp_gen_cfg_t {
+ uint32_t ttp_offset_default;
+ /*
+ * TTP offset uses for all other cases
+ * where no valid SSRC is received.
+ */
+ uint32_t settling_time;
+ /*
+ * If settling_mode==0x00: time in [us]
+ * after first received packet until
+ * packets are no longer dropped.
+ */
+ uint16_t settling_mode;
+ /*
+ * 0x00(Drop), 0x01(Settle)
+ */
+ uint16_t num_ssrc_offsets;
+ /*
+ * Number of SSRC/TTPOFFSET pairs to follow
+ */
+ struct afe_ttp_ssrc_offset_pair_t ssrc_ttp_offset[MAX_TTP_OFFSET_PAIRS];
+ /*
+ * Array of ssrc/offset pairs
+ */
+} __packed;
+
+struct afe_ttp_config {
+ struct afe_ttp_gen_enable_t ttp_gen_enable;
+ struct afe_ttp_gen_cfg_t ttp_gen_cfg;
+};
+
union afe_dec_config_data {
struct asm_sbc_dec_cfg_t sbc_config;
struct asm_aac_dec_cfg_v2_t aac_config;
@@ -12348,6 +12398,12 @@
*/
#define ASM_SESSION_MTMX_STRTR_PARAM_RENDER_WINDOW_END_V2 0x00010DD2
+/* Parameter used by #ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC to specify the
+ * ttp offset value. This parameter is supported only for a Set
+ * command (not a Get command) in the Tx direction
+ */
+#define ASM_SESSION_MTMX_STRTR_PARAM_TTP_OFFSET 0x00013228
+
/* Generic payload of the window parameters in the
* #ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC module.
* This payload is supported only for a Set command
@@ -12456,6 +12512,26 @@
u32 flags;
} __packed;
+struct asm_session_mtmx_strtr_param_ttp_offset_t {
+ uint32_t ttp_offset_lsw;
+ /* Lower 32 bits of the ttp_offset in microseconds. */
+
+ uint32_t ttp_offset_msw;
+ /* Upper 32 bits of the ttp_offset in microseconds.
+ *
+ * Internal default value is 0 for both values. The 64-bit number
+ * formed by ttp_offset_lsw and ttp_offset_lsw is treated as unsigned.
+ * In case of local DSP loopback when using start flag
+ * ASM_SESSION_CMD_RUN_START_TIME_RUN_WITH_TTP the max. ttp_offset
+ * value is limited by internal buffer constraints. Currently the
+ * limit is 200ms.
+
+ * This parameter can be set before or while an ASM stream is running,
+ * allowing “at-run-time” changes of the overall latency.
+ */
+
+} __packed;
+
/* Parameter used by #ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC which allows the
* audio client to specify the clock recovery mechanism that the audio DSP
* should use.
@@ -12527,6 +12603,7 @@
struct asm_session_mtmx_strtr_param_render_mode_t render_param;
struct asm_session_mtmx_strtr_param_clk_rec_t clk_rec_param;
struct asm_session_mtmx_param_adjust_session_time_ctl_t adj_time_param;
+ struct asm_session_mtmx_strtr_param_ttp_offset_t ttp_offset;
} __packed;
struct asm_mtmx_strtr_params {
diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h
index 3ff3028..55ae6be 100644
--- a/include/dsp/q6afe-v2.h
+++ b/include/dsp/q6afe-v2.h
@@ -402,6 +402,11 @@
u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
struct afe_enc_config *enc_config,
struct afe_dec_config *dec_config);
+int afe_port_start_v3(u16 port_id, union afe_port_config *afe_config,
+ u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
+ struct afe_enc_config *enc_config,
+ struct afe_dec_config *dec_config,
+ struct afe_ttp_config *ttp_config);
int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
int l_ch, int r_ch, u32 enable);
int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib);
diff --git a/include/dsp/q6asm-v2.h b/include/dsp/q6asm-v2.h
index 5ad8fb0..1a34161 100644
--- a/include/dsp/q6asm-v2.h
+++ b/include/dsp/q6asm-v2.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
*/
#ifndef __Q6_ASM_V2_H__
#define __Q6_ASM_V2_H__
@@ -726,9 +726,13 @@
struct asm_session_mtmx_strtr_param_window_v2_t *window_param,
uint32_t param_id);
+int q6asm_send_mtmx_strtr_ttp_offset(struct audio_client *ac,
+ struct asm_session_mtmx_strtr_param_ttp_offset_t *ttp_offset,
+ uint32_t param_id, int dir);
+
/* Configure DSP render mode */
int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac,
- uint32_t render_mode);
+ uint32_t render_mode, int dir);
/* Configure DSP clock recovery mode */
int q6asm_send_mtmx_strtr_clk_rec_mode(struct audio_client *ac,