From c238fc0d7496e7d938af4a5925d0a5fade0478b2 Mon Sep 17 00:00:00 2001 From: Surendar Karka Date: Tue, 12 Feb 2019 12:46:05 +0530 Subject: [PATCH] asoc: enable TTP generator Add support to enable TTP generator in AFE. Change-Id: I0186dc18809b87a912a1c3ec9dd7fcd26aa726f5 Signed-off-by: Surendar Karka --- asoc/msm-dai-q6-v2.c | 142 +++++++++++++++++++++++++++++++++++-- dsp/q6afe.c | 99 ++++++++++++++++++++++++-- include/dsp/apr_audio-v2.h | 50 +++++++++++++ include/dsp/q6afe-v2.h | 5 ++ 4 files changed, 284 insertions(+), 12 deletions(-) diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c index 82a627aea035..2d98ec481b8c 100644 --- a/asoc/msm-dai-q6-v2.c +++ b/asoc/msm-dai-q6-v2.c @@ -232,6 +232,7 @@ struct msm_dai_q6_dai_data { 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; @@ -2229,6 +2230,7 @@ static int msm_dai_q6_prepare(struct snd_pcm_substream *substream, { 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) { @@ -2278,13 +2280,27 @@ static int msm_dai_q6_prepare(struct snd_pcm_substream *substream, 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); @@ -3668,6 +3684,91 @@ static int msm_dai_q6_afe_dec_cfg_put(struct snd_kcontrol *kcontrol, 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 | @@ -3695,6 +3796,27 @@ static const struct snd_kcontrol_new afe_dec_config_controls[] = { 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) { @@ -3918,6 +4040,12 @@ static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai) 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/dsp/q6afe.c b/dsp/q6afe.c index 97521002e9b2..39e67da2b884 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -3886,6 +3886,51 @@ exit: 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, @@ -4556,7 +4601,8 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, 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; @@ -4873,6 +4919,15 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, 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); @@ -4919,8 +4974,8 @@ fail_cmd: 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); @@ -4950,16 +5005,50 @@ int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config, 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) { diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index 7a686349a496..f3b7ade102ea 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -4728,6 +4728,56 @@ struct afe_enc_config { 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; diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h index 73a7cf872a61..035da1f4697a 100644 --- a/include/dsp/q6afe-v2.h +++ b/include/dsp/q6afe-v2.h @@ -400,6 +400,11 @@ int afe_port_start_v2(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); +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);