From b39574b943cb656bdb132c5d1e6a9ccdbdd29ded Mon Sep 17 00:00:00 2001 From: Kogara Naveen Kumar Date: Mon, 7 Nov 2022 18:16:44 +0530 Subject: [PATCH 1/5] asoc : modify spf_machine_dlkm module name for GVM Suggested-by: Ahamed Rasim. Change-Id : I642ddf5fd475ba5e6a1f27ab60339c0287fe5678 --- asoc/Kbuild | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/asoc/Kbuild b/asoc/Kbuild index 6bfe53412acb..6014ba9c5634 100755 --- a/asoc/Kbuild +++ b/asoc/Kbuild @@ -329,8 +329,8 @@ machine_dlkm-y := $(MACHINE_OBJS) obj-$(CONFIG_SND_SOC_CPE) += cpe_lsm_dlkm.o cpe_lsm_dlkm-y := $(CPE_LSM_OBJS) -obj-$(CONFIG_SND_SOC_GVM_AUTO_SPF) += spf_machine_dlkm.o -spf_machine_dlkm-y := $(SPF_MACHINE_OBJS) +obj-$(CONFIG_SND_SOC_GVM_AUTO_SPF) += gvm_spf_machine_dlkm.o +gvm_spf_machine_dlkm-y := $(SPF_MACHINE_OBJS) # inject some build related information DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" From 457009dc9409bf87cea33b0c50c36e36fe50436a Mon Sep 17 00:00:00 2001 From: Jiazai Wu Date: Thu, 17 Nov 2022 12:11:31 +0800 Subject: [PATCH 2/5] uapi:align msm_audio_ar.h with AR need to align msm_audio_ar.h with AR. Change-Id: Ib3d7bad7e2e3b1320927d1d2ce7f891bfd7bd065 --- include/uapi/audio/linux/msm_audio_ar.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/uapi/audio/linux/msm_audio_ar.h b/include/uapi/audio/linux/msm_audio_ar.h index 5edce37bb6d8..32dec4d63185 100644 --- a/include/uapi/audio/linux/msm_audio_ar.h +++ b/include/uapi/audio/linux/msm_audio_ar.h @@ -113,7 +113,11 @@ #define AUDIO_PM_RELAX _IOW(AUDIO_IOCTL_MAGIC, 106, unsigned int) #define AUDIO_REGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 107, struct msm_audio_ion_info) #define AUDIO_DEREGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 108, struct msm_audio_ion_info) -#define AUDIO_MAX_COMMON_IOCTL_NUM 109 +#define IOCTL_MAP_HYP_ASSIGN _IOW(AUDIO_IOCTL_MAGIC, 109, int) +#define IOCTL_UNMAP_HYP_ASSIGN _IOW(AUDIO_IOCTL_MAGIC, 110, int) +#define IOCTL_MAP_HYP_ASSIGN_V2 _IOW(AUDIO_IOCTL_MAGIC, 111, int) +#define IOCTL_UNMAP_HYP_ASSIGN_V2 _IOW(AUDIO_IOCTL_MAGIC, 112, int) +#define AUDIO_MAX_COMMON_IOCTL_NUM 113 #define HANDSET_MIC 0x01 From 73e13435c9432c1a1bc95c8adf6c361d4cd24312 Mon Sep 17 00:00:00 2001 From: Hari Krishna chowdary Yennana Date: Fri, 23 Sep 2022 19:28:58 +0530 Subject: [PATCH 3/5] asoc: Update wcd937x codec driver controls Amic2 recording is failing due to missing of mixer controls. Change is to add support of ADC and DMIC control for swr master channel map. Change-Id: I0377ec84a49d2eaa390872a29e2d8cf8909794b1 Signed-off-by: Hari Krishna Chowdary Yennana --- asoc/codecs/wcd937x/wcd937x.c | 3 ++- asoc/codecs/wcd937x/wcd937x.h | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c index a7b3a5a0e8d4..c002574d26b2 100644 --- a/asoc/codecs/wcd937x/wcd937x.c +++ b/asoc/codecs/wcd937x/wcd937x.c @@ -2074,7 +2074,8 @@ const char * const tx_master_ch_text[] = { "ZERO", "SWRM_TX1_CH1", "SWRM_TX1_CH2", "SWRM_TX1_CH3", "SWRM_TX1_CH4", "SWRM_TX2_CH1", "SWRM_TX2_CH2", "SWRM_TX2_CH3", "SWRM_TX2_CH4", "SWRM_TX3_CH1", "SWRM_TX3_CH2", "SWRM_TX3_CH3", "SWRM_TX3_CH4", - "SWRM_PCM_IN", + "SWRM_PCM_IN", "ADC1", "ADC3", "ADC4", "DMIC0", "DMIC1", "DMIC2", + "DMIC4", "DMIC5", "DMIC6", "DMIC7", }; const struct soc_enum tx_master_ch_enum = diff --git a/asoc/codecs/wcd937x/wcd937x.h b/asoc/codecs/wcd937x/wcd937x.h index c97ee78254ad..a868eeb32b9a 100644 --- a/asoc/codecs/wcd937x/wcd937x.h +++ b/asoc/codecs/wcd937x/wcd937x.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2018, 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _WCD937X_H @@ -50,6 +51,16 @@ static int wcd937x_swr_master_ch_map[] = { SWRM_TX3_CH3, SWRM_TX3_CH4, SWRM_PCM_IN, + ADC1, + ADC3, + ADC4, + DMIC0, + DMIC1, + DMIC2, + DMIC4, + DMIC5, + DMIC6, + DMIC7, }; #ifdef CONFIG_SND_SOC_WCD937X From 66c053253b7bd5a2395735906d3402a53498f54e Mon Sep 17 00:00:00 2001 From: Soumya Managoli Date: Thu, 3 Nov 2022 16:51:00 +0530 Subject: [PATCH 4/5] dsp: Remove lock in voice_map_cal_memory voice_map_cal_memory is already under locked context of common_lock from fn voc_register_vocproc_vol_table from where it is invoked. Remove locking the same lock again in voice_map_cal_memory to avoid deadlock. Change-Id: Ibd6c7169377418c7bda3310a0e422279fd4e7295 --- dsp/q6voice.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dsp/q6voice.c b/dsp/q6voice.c index e7f7646b7eea..1f3b1448fb8d 100644 --- a/dsp/q6voice.c +++ b/dsp/q6voice.c @@ -3850,7 +3850,6 @@ static int voice_map_cal_memory(struct cal_block_data *cal_block, goto done; } - mutex_lock(&common.common_lock); v = &common.voice[voc_index]; result = voice_map_memory_physical_cmd(v, @@ -3864,12 +3863,10 @@ static int voice_map_cal_memory(struct cal_block_data *cal_block, &cal_block->cal_data.paddr, cal_block->map_data.map_size); - goto done_unlock; + goto done; } cal_block->map_data.q6map_handle = common.cal_mem_handle; -done_unlock: - mutex_unlock(&common.common_lock); done: return result; } From 7581982cee85c8e652bfefe7ddf997e6f4577307 Mon Sep 17 00:00:00 2001 From: Srinivasa Reddy M N Date: Thu, 20 Oct 2022 17:59:48 +0530 Subject: [PATCH 5/5] ASoC: Add support "adm cmd register" and "adm pp" events Added support for "ADM_CMD_REGISTER_EVENT" and "ADM_PP_EVENT" events. Signed-off-by: Srinivasa Reddy M N Change-Id: I80d8dc6d9fccdac67ea616d19415aa2133a3f370 --- asoc/msm-pcm-q6-v2.c | 29 ++- asoc/msm-pcm-routing-auto.c | 339 +++++++++++++++++++++++++++ asoc/msm-pcm-routing-v2.c | 50 ++++ asoc/msm-pcm-routing-v2.h | 3 + asoc/msm-qti-pp-config.c | 211 +++++++++++++++++ asoc/msm-qti-pp-config.h | 8 + dsp/q6adm.c | 186 +++++++++++++++ include/dsp/apr_audio-v2.h | 29 +++ include/dsp/q6adm-v2.h | 7 + include/uapi/audio/linux/msm_audio.h | 14 ++ 10 files changed, 875 insertions(+), 1 deletion(-) mode change 100755 => 100644 asoc/msm-pcm-routing-auto.c mode change 100755 => 100644 asoc/msm-pcm-routing-v2.c mode change 100755 => 100644 include/dsp/apr_audio-v2.h diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c index 3d337efc98c1..1dfa857be5ea 100644 --- a/asoc/msm-pcm-q6-v2.c +++ b/asoc/msm-pcm-q6-v2.c @@ -565,6 +565,8 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream) uint16_t format = 0; uint16_t req_format = 0; uint16_t input_file_format = 0; + int port_id = 0, copp_idx = -1; + bool found = false; if (!component) { pr_err("%s: component is NULL\n", __func__); @@ -691,6 +693,15 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream) return ret; } + found = msm_pcm_routing_get_portid_copp_idx(soc_prtd->dai_link->id, + SESSION_TYPE_RX, &port_id, &copp_idx); + if (found) { + q6adm_update_rtd_info(soc_prtd, port_id, copp_idx, + soc_prtd->dai_link->id, 1); + } else { + pr_err("%s: copp_idx not found\n", __func__); + } + /*Format block is configure with input file bits_per_sample*/ switch (input_file_format) { case SNDRV_PCM_FORMAT_S32_LE: @@ -1070,8 +1081,10 @@ static int msm_pcm_open(struct snd_pcm_substream *substream) prtd->reset_event = false; runtime->private_data = prtd; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { msm_adsp_init_mixer_ctl_pp_event_queue(soc_prtd); + msm_adsp_init_mixer_ctl_adm_pp_event_queue(soc_prtd); + } /* Vote to update the Rx thread priority to RT Thread for playback */ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) && @@ -1189,6 +1202,8 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) uint32_t timeout; int dir = 0; int ret = 0; + int port_id = 0, copp_idx = -1; + bool found = false; pr_debug("%s: cmd_pending 0x%lx\n", __func__, prtd->cmd_pending); @@ -1239,9 +1254,21 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) prtd->audio_client); q6asm_audio_client_free(prtd->audio_client); } + + found = msm_pcm_routing_get_portid_copp_idx(soc_prtd->dai_link->id, + SESSION_TYPE_RX, &port_id, &copp_idx); + if (found) { + q6adm_update_rtd_info(soc_prtd, port_id, copp_idx, + soc_prtd->dai_link->id, 0); + q6adm_clear_callback(); + } else { + pr_err("%s: copp_idx not found\n", __func__); + } + msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id, SNDRV_PCM_STREAM_PLAYBACK); msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd); + msm_adsp_clean_mixer_ctl_adm_pp_event_queue(soc_prtd); kfree(prtd); runtime->private_data = NULL; mutex_unlock(&pdata->lock); diff --git a/asoc/msm-pcm-routing-auto.c b/asoc/msm-pcm-routing-auto.c old mode 100755 new mode 100644 index 4eccb8c4f398..f8e15f51fc24 --- a/asoc/msm-pcm-routing-auto.c +++ b/asoc/msm-pcm-routing-auto.c @@ -103,6 +103,10 @@ static int afe_loopback_tx_port_id = -1; static struct msm_pcm_channel_mixer ec_ref_chmix_cfg[MSM_FRONTEND_DAI_MAX]; static struct msm_ec_ref_port_cfg ec_ref_port_cfg; +static uint32_t adm_pp_reg_event_opcode[] = { + ADM_CMD_REGISTER_EVENT +}; + #define WEIGHT_0_DB 0x4000 /* all the FEs which can support channel mixer */ static struct msm_pcm_channel_mixer channel_mixer[MSM_FRONTEND_DAI_MM_SIZE]; @@ -2418,6 +2422,56 @@ int msm_pcm_routing_set_channel_mixer_runtime(int be_id, int session_id, } EXPORT_SYMBOL(msm_pcm_routing_set_channel_mixer_runtime); +/* + * msm_pcm_routing_get_portid_copp_idx: + * update the port_id and copp_idx for a given + * fe_id + * + * @fe_id: front end id + * @session_type: indicates session is of type TX or RX + * port: port_id to be updated as output + * copp_idx: copp_idx is updated as output + * @stream_type: indicates either Audio or Listen stream type + */ +bool msm_pcm_routing_get_portid_copp_idx(int fe_id, + int session_type, int *port, int *copp_idx) +{ + int idx = 0; + bool found = false; + int be_index = 0, port_id = 0; + + pr_debug("%s:fe_id[%d] sess_type [%d]\n", + __func__, fe_id, session_type); + if (!is_mm_lsm_fe_id(fe_id)) { + /* bad ID assigned in machine driver */ + pr_err("%s: bad MM ID %d\n", __func__, fe_id); + return -EINVAL; + } + + for (be_index = 0; be_index < MSM_BACKEND_DAI_MAX; be_index++) { + port_id = msm_bedais[be_index].port_id; + if (!msm_bedais[be_index].active || + !test_bit(fe_id, &msm_bedais[be_index].fe_sessions[0])) + continue; + + for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) { + unsigned long copp_id = + session_copp_map[fe_id][session_type][be_index]; + if (test_bit(idx, &copp_id)) { + pr_debug("%s: port_id: %d, copp_idx:%d\n", + __func__, port_id, idx); + *port = port_id; + *copp_idx = idx; + found = true; + break; + } + } + } + + return found; +} +EXPORT_SYMBOL(msm_pcm_routing_get_portid_copp_idx); + int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, int dspst_id, int stream_type) { @@ -32481,6 +32535,273 @@ static void msm_routing_unload_topology(uint32_t topology_id) } +static int msm_audio_get_copp_idx_from_port_id(int port_id, int session_type, + int *copp_idx) +{ + int i = 0, idx = 0, be_idx = 0; + int ret = 0; + unsigned long copp = 0; + + pr_debug("%s: Enter, port_id=%d\n", __func__, port_id); + + ret = q6audio_validate_port(port_id); + if (ret < 0) { + pr_err("%s: port validation failed id 0x%x ret %d\n", + __func__, port_id, ret); + + ret = -EINVAL; + goto done; + } + + for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) { + if (msm_bedais[be_idx].port_id == port_id) + break; + } + if (be_idx >= MSM_BACKEND_DAI_MAX) { + pr_err("%s: Invalid be id %d\n", __func__, be_idx); + + ret = -EINVAL; + goto done; + } + + for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions[0], + MSM_FRONTEND_DAI_MAX) { + if (!(is_mm_lsm_fe_id(i) && + route_check_fe_id_adm_support(i))) + continue; + + for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) { + copp = session_copp_map[i] + [session_type][be_idx]; + if (test_bit(idx, &copp)) + break; + } + if (idx >= MAX_COPPS_PER_PORT) + continue; + else + break; + } + if (i >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s: Invalid FE, exiting\n", __func__); + + ret = -EINVAL; + goto done; + } + *copp_idx = idx; + pr_debug("%s: copp_idx=%d\n", __func__, *copp_idx); + +done: + return ret; +} + +static int msm_routing_put_copp_dtmf_module_enable + (struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + uint8_t *be_id = NULL, be_id_val = 0; + int copp_idx = -1, port_id = 0; + struct param_hdr_v3 param_hdr = {0}; + int rc = 0; + u32 flag = (bool)ucontrol->value.integer.value[0]; + + be_id = (uint8_t *)ucontrol->value.bytes.data; + be_id_val = *be_id; + + if((be_id_val < 0) || (be_id_val >= MSM_BACKEND_DAI_MAX)) { + pr_err("%s: received invalid be_id %lu\n", __func__, be_id_val); + return -EINVAL; + } + + port_id = msm_bedais[be_id_val].port_id; + rc = msm_audio_get_copp_idx_from_port_id(port_id, SESSION_TYPE_RX, + &copp_idx); + + if (rc) { + pr_err(" %s:failure in getting copp_idx\n", __func__); + return rc; + } + + memset(¶m_hdr, 0, sizeof(param_hdr)); + param_hdr.module_id = AUDPROC_MODULE_ID_DTMF_DETECTION; + param_hdr.instance_id = INSTANCE_ID_0; + param_hdr.param_id = AUDPROC_PARAM_ID_ENABLE; + param_hdr.param_size = 4; + + rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr, + (u8 *)&flag); + if (rc) + pr_err("%s: Failed to set adm_pack_and_set_one_pp_param, err %d\n", + __func__, rc); + + return rc; + +} + +static const struct snd_kcontrol_new copp_dtmf_detect_enable_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1 COPP DTMF Detect Enable", SND_SOC_NOPM, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, NULL, + msm_routing_put_copp_dtmf_module_enable), + SOC_SINGLE_EXT("MultiMedia6 COPP DTMF Detect Enable", SND_SOC_NOPM, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, NULL, + msm_routing_put_copp_dtmf_module_enable), + SOC_SINGLE_EXT("MultiMedia21 COPP DTMF Detect Enable", SND_SOC_NOPM, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, NULL, + msm_routing_put_copp_dtmf_module_enable), +}; + +static int adsp_copp_event_handler(uint32_t opcode, + uint32_t token_adm, uint32_t *payload, void *priv) +{ + struct snd_soc_pcm_runtime *rtd = priv; + int ret = 0; + + if (!rtd) { + pr_err("%s: rtd is NULL\n", __func__); + return -EINVAL; + } + + ret = msm_adsp_copp_inform_mixer_ctl(rtd, payload); + if (ret) { + pr_err("%s: failed to inform mixer ctrl. err = %d\n", + __func__, ret); + return -EINVAL; + } + + return ret; +} + +static int msm_routing_get_copp_callback_event(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + uint32_t payload_size = 0; + struct dsp_adm_callback_list *oldest_event = NULL; + unsigned long spin_flags = 0; + struct dsp_adm_callback_prtd *kctl_prtd = NULL; + int ret = 0; + + kctl_prtd = (struct dsp_adm_callback_prtd *) + kcontrol->private_data; + + if (kctl_prtd == NULL) { + pr_err("%s: ADM PP event queue is not initialized.\n", + __func__); + ret = -EINVAL; + goto done; + } + + spin_lock_irqsave(&kctl_prtd->prtd_spin_lock, spin_flags); + pr_debug("%s: %d events in queue.\n", __func__, kctl_prtd->event_count); + if (list_empty(&kctl_prtd->event_queue)) { + pr_err("%s: ADM PP event queue is empty.\n", __func__); + ret = -EINVAL; + spin_unlock_irqrestore(&kctl_prtd->prtd_spin_lock, spin_flags); + goto done; + } + + oldest_event = list_first_entry(&kctl_prtd->event_queue, + struct dsp_adm_callback_list, list); + list_del(&oldest_event->list); + kctl_prtd->event_count--; + spin_unlock_irqrestore(&kctl_prtd->prtd_spin_lock, spin_flags); + + payload_size = oldest_event->event.payload_len; + pr_debug("%s: event fetched: type %d length %d\n", + __func__, oldest_event->event.event_type, + oldest_event->event.payload_len); + memcpy(ucontrol->value.bytes.data, &oldest_event->event, + sizeof(struct msm_adsp_event_data) + payload_size); + kfree(oldest_event); + +done: + return ret; +} + +static int msm_routing_put_copp_callback_event(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s\n", __func__); + return 0; +} + +static int msm_copp_callback_event_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = + sizeof(((struct snd_ctl_elem_value *)0)->value.bytes.data); + + return 0; +} + +static const struct snd_kcontrol_new copp_callback_event_controls[] = { + { + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "ADSP COPP Callback Event", + .info = msm_copp_callback_event_info, + .get = msm_routing_get_copp_callback_event, + .put = msm_routing_put_copp_callback_event, + }, +}; + +int msm_copp_event_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = + sizeof(((struct snd_ctl_elem_value *)0)->value.bytes.data); + + return 0; +} + +static int msm_routing_get_copp_event_cmd(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s\n", __func__); + return 0; +} + +static int msm_routing_put_copp_event_cmd(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct msm_adm_event_data *ev = NULL; + int be_id = 0, ret = 0, param_size = 0, opcode = 0; + int copp_idx = -1, port_id = 0; + + ev = (struct msm_adm_event_data *)ucontrol->value.bytes.data; + param_size = ev->payload_length - sizeof(struct module_info_data); + opcode = adm_pp_reg_event_opcode[(ev->event_type) + - ADSP_ADM_SERVICE_ID]; + be_id = ev->mod_info.be_id; + port_id = msm_bedais[be_id].port_id; + + pr_debug("%s: port_id= 0x%x, be_id=%d\n", __func__,port_id, be_id); + + ret = msm_audio_get_copp_idx_from_port_id(port_id, SESSION_TYPE_RX, + &copp_idx); + + if (ret) { + pr_debug("%s:failure in getting copp_idx\n", __func__); + return ret; + } + + q6adm_register_callback(&adsp_copp_event_handler); + q6adm_send_event_register_cmd(port_id, copp_idx, (u8 *) (ev->payload), + param_size, opcode); + return ret; +} + +static const struct snd_kcontrol_new copp_event_controls[] = { + { + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "COPP Event Cmd", + .info = msm_copp_event_info, + .get = msm_routing_get_copp_event_cmd, + .put = msm_routing_put_copp_event_cmd, + }, +}; + static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -33661,6 +33982,7 @@ static void snd_soc_dapm_add_routes_aux_pcm(struct snd_soc_component *component) /* Not used but frame seems to require it */ static int msm_routing_probe(struct snd_soc_component *component) { + struct snd_kcontrol *kctl = NULL; snd_soc_dapm_new_controls(&component->dapm, msm_qdsp6_widgets, ARRAY_SIZE(msm_qdsp6_widgets)); @@ -33718,10 +34040,27 @@ static int msm_routing_probe(struct snd_soc_component *component) ARRAY_SIZE(asrc_config_controls)); snd_soc_add_component_controls(component, asrc_start_controls, ARRAY_SIZE(asrc_start_controls)); + snd_soc_add_component_controls(component, + copp_dtmf_detect_enable_mixer_controls, + ARRAY_SIZE(copp_dtmf_detect_enable_mixer_controls)); + #ifdef CONFIG_MSM_INTERNAL_MCLK snd_soc_add_component_controls(component, internal_mclk_control, ARRAY_SIZE(internal_mclk_control)); #endif + snd_soc_add_component_controls(component, copp_callback_event_controls, + ARRAY_SIZE(copp_callback_event_controls)); + snd_soc_add_component_controls(component, copp_event_controls, + ARRAY_SIZE(copp_event_controls)); + + kctl = snd_soc_card_get_kcontrol(component->dapm.card, + "ADSP COPP Callback Event"); + if (!kctl) { + pr_err("%s: failed to get kctl %s.\n", __func__, + "ADSP COPP Callback Event"); + return -EINVAL; + } + kctl->private_data = NULL; return 0; } diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c old mode 100755 new mode 100644 index 3849f6470242..6ec26e7d53b9 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -2458,6 +2458,56 @@ int msm_pcm_routing_set_channel_mixer_runtime(int be_id, int session_id, } EXPORT_SYMBOL(msm_pcm_routing_set_channel_mixer_runtime); +/* + * msm_pcm_routing_get_portid_copp_idx: + * update the port_id and copp_idx for a given + * fe_id + * + * @fe_id: front end id + * @session_type: indicates session is of type TX or RX + * port: port_id to be updated as output + * copp_idx: copp_idx is updated as output + * @stream_type: indicates either Audio or Listen stream type + */ +bool msm_pcm_routing_get_portid_copp_idx(int fe_id, + int session_type, int *port, int *copp_idx) +{ + int idx = 0; + bool found = false; + int be_index = 0, port_id = 0; + + pr_debug("%s:fe_id[%d] sess_type [%d]\n", + __func__, fe_id, session_type); + if (!is_mm_lsm_fe_id(fe_id)) { + /* bad ID assigned in machine driver */ + pr_err("%s: bad MM ID %d\n", __func__, fe_id); + return -EINVAL; + } + + for (be_index = 0; be_index < MSM_BACKEND_DAI_MAX; be_index++) { + port_id = msm_bedais[be_index].port_id; + if (!msm_bedais[be_index].active || + !test_bit(fe_id, &msm_bedais[be_index].fe_sessions[0])) + continue; + + for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) { + unsigned long copp_id = + session_copp_map[fe_id][session_type][be_index]; + if (test_bit(idx, &copp_id)) { + pr_debug("%s: port_id: %d, copp_idx:%d\n", + __func__, port_id, idx); + *port = port_id; + *copp_idx = idx; + found = true; + break; + } + } + } + + return found; +} +EXPORT_SYMBOL(msm_pcm_routing_get_portid_copp_idx); + int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, int dspst_id, int stream_type) { diff --git a/asoc/msm-pcm-routing-v2.h b/asoc/msm-pcm-routing-v2.h index 752fe58c1ec5..d57851b7bec4 100644 --- a/asoc/msm-pcm-routing-v2.h +++ b/asoc/msm-pcm-routing-v2.h @@ -897,4 +897,7 @@ int snd_pcm_add_usr_ctls(struct snd_pcm *pcm, int stream, unsigned long private_value, struct snd_pcm_usr **info_ret); #endif + +bool msm_pcm_routing_get_portid_copp_idx(int fe_id, + int session_type, int *port_id, int *copp_idx); #endif /*_MSM_PCM_H*/ diff --git a/asoc/msm-qti-pp-config.c b/asoc/msm-qti-pp-config.c index 2e62922dc805..cdc0f38168f5 100644 --- a/asoc/msm-qti-pp-config.c +++ b/asoc/msm-qti-pp-config.c @@ -1207,6 +1207,217 @@ done: return ret; } +int msm_adsp_init_mixer_ctl_adm_pp_event_queue(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_kcontrol *kctl = NULL; + char *mixer_str = NULL; + int ctl_len = 0, ret = 0; + const char *mixer_ctl_name = DSP_ADM_CALLBACK; + struct dsp_adm_callback_prtd *kctl_prtd = NULL; + + if (!rtd) { + pr_err("%s: rtd is NULL\n", __func__); + ret = -EINVAL; + goto done; + } + + ctl_len = strlen(mixer_ctl_name) + 1; + mixer_str = kzalloc(ctl_len, GFP_KERNEL); + if (!mixer_str) { + ret = -EINVAL; + goto done; + } + + snprintf(mixer_str, ctl_len, "%s", mixer_ctl_name); + kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str); + kfree(mixer_str); + if (!kctl) { + pr_err("%s: failed to get kctl.\n", __func__); + ret = -EINVAL; + goto done; + } + + if (kctl->private_data != NULL) { + pr_err("%s: kctl_prtd is not NULL at initialization.\n", + __func__); + return -EINVAL; + } + + kctl_prtd = kzalloc(sizeof(struct dsp_adm_callback_prtd), + GFP_KERNEL); + if (!kctl_prtd) { + ret = -ENOMEM; + goto done; + } + + spin_lock_init(&kctl_prtd->prtd_spin_lock); + INIT_LIST_HEAD(&kctl_prtd->event_queue); + kctl_prtd->event_count = 0; + kctl->private_data = kctl_prtd; + +done: + return ret; +} + +int msm_adsp_clean_mixer_ctl_adm_pp_event_queue(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_kcontrol *kctl = NULL; + char *mixer_str = NULL; + int ctl_len = 0, ret = 0; + struct dsp_adm_callback_list *node = NULL, *n = NULL; + unsigned long spin_flags = 0; + const char *mixer_ctl_name = DSP_ADM_CALLBACK; + struct dsp_adm_callback_prtd *kctl_prtd = NULL; + + if (!rtd) { + pr_err("%s: rtd is NULL\n", __func__); + ret = -EINVAL; + goto done; + } + + ctl_len = strlen(mixer_ctl_name) + 1; + mixer_str = kzalloc(ctl_len, GFP_KERNEL); + if (!mixer_str) { + ret = -EINVAL; + goto done; + } + + snprintf(mixer_str, ctl_len, "%s", mixer_ctl_name); + kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str); + kfree(mixer_str); + if (!kctl) { + pr_err("%s: failed to get kctl.\n", __func__); + ret = -EINVAL; + goto done; + } + + kctl_prtd = (struct dsp_adm_callback_prtd *) + kctl->private_data; + if (kctl_prtd != NULL) { + spin_lock_irqsave(&kctl_prtd->prtd_spin_lock, spin_flags); + /* clean the queue */ + list_for_each_entry_safe(node, n, + &kctl_prtd->event_queue, list) { + list_del(&node->list); + kctl_prtd->event_count--; + pr_debug("%s: %d remaining events after del.\n", + __func__, kctl_prtd->event_count); + kfree(node); + } + spin_unlock_irqrestore(&kctl_prtd->prtd_spin_lock, spin_flags); + } + + kfree(kctl_prtd); + kctl->private_data = NULL; + +done: + return ret; +} + +int msm_adsp_copp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd, + uint32_t *payload) +{ + /* adsp adm pp event notifier */ + struct snd_kcontrol *kctl = NULL; + struct snd_ctl_elem_value control = {0}; + char *mixer_str = NULL; + int ctl_len = 0, ret = 0; + struct dsp_adm_callback_list *new_event = NULL; + struct dsp_adm_callback_list *oldest_event = NULL; + unsigned long spin_flags = 0; + struct dsp_adm_callback_prtd *kctl_prtd = NULL; + struct msm_adsp_event_data *event_data = NULL; + const char *mixer_ctl_name = DSP_ADM_CALLBACK; + struct snd_ctl_elem_info kctl_info = {0}; + + if (!rtd || !payload) { + pr_err("%s: %s is NULL\n", __func__, + (!rtd) ? "rtd" : "payload"); + ret = -EINVAL; + goto done; + } + + if (rtd->card->snd_card == NULL) { + pr_err("%s: snd_card is null.\n", __func__); + ret = -EINVAL; + goto done; + } + + ctl_len = strlen(mixer_ctl_name) + 1; + mixer_str = kzalloc(ctl_len, GFP_ATOMIC); + if (!mixer_str) { + ret = -EINVAL; + goto done; + } + + snprintf(mixer_str, ctl_len, "%s", mixer_ctl_name); + kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str); + kfree(mixer_str); + if (!kctl) { + pr_err("%s: failed to get kctl.\n", __func__); + ret = -EINVAL; + goto done; + } + + event_data = (struct msm_adsp_event_data *)payload; + kctl->info(kctl, &kctl_info); + if (sizeof(struct msm_adsp_event_data) + + event_data->payload_len > kctl_info.count) { + pr_err("%s: payload length exceeds limit of %u bytes.\n", + __func__, kctl_info.count); + ret = -EINVAL; + goto done; + } + + kctl_prtd = (struct dsp_adm_callback_prtd *) + kctl->private_data; + if (kctl_prtd == NULL) { + /* queue is not initialized */ + ret = -EINVAL; + pr_err("%s: event queue is not initialized.\n", __func__); + goto done; + } + + new_event = kzalloc(sizeof(struct dsp_adm_callback_list) + + event_data->payload_len + sizeof(uint32_t), + GFP_ATOMIC); + if (new_event == NULL) { + ret = -ENOMEM; + goto done; + } + memcpy((void *)&new_event->event, (void *)payload, + event_data->payload_len + + sizeof(struct msm_adsp_event_data)); + + + spin_lock_irqsave(&kctl_prtd->prtd_spin_lock, spin_flags); + while (kctl_prtd->event_count >= DSP_ADM_CALLBACK_QUEUE_SIZE) { + pr_info("%s: queue of size %d is full. delete oldest one.\n", + __func__, DSP_ADM_CALLBACK_QUEUE_SIZE); + oldest_event = list_first_entry(&kctl_prtd->event_queue, + struct dsp_adm_callback_list, list); + pr_info("%s: event deleted: type %d length %d\n", + __func__, oldest_event->event.event_type, + oldest_event->event.payload_len); + list_del(&oldest_event->list); + kctl_prtd->event_count--; + kfree(oldest_event); + } + + list_add_tail(&new_event->list, &kctl_prtd->event_queue); + kctl_prtd->event_count++; + spin_unlock_irqrestore(&kctl_prtd->prtd_spin_lock, spin_flags); + + control.id = kctl->id; + + snd_ctl_notify(rtd->card->snd_card, + SNDRV_CTL_EVENT_MASK_INFO, + &control.id); + +done: + return ret; +} + int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd, uint32_t *payload) { diff --git a/asoc/msm-qti-pp-config.h b/asoc/msm-qti-pp-config.h index 7fddb9f49840..b91746e34d36 100644 --- a/asoc/msm-qti-pp-config.h +++ b/asoc/msm-qti-pp-config.h @@ -9,6 +9,14 @@ #include #define DSP_BIT_WIDTH_MIXER_CTL "ASM Bit Width" #ifdef CONFIG_QTI_PP + +int msm_adsp_adm_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd, + uint32_t *payload); +int msm_adsp_init_mixer_ctl_adm_pp_event_queue(struct snd_soc_pcm_runtime *rtd); +int msm_adsp_clean_mixer_ctl_adm_pp_event_queue( + struct snd_soc_pcm_runtime *rtd); +int msm_adsp_copp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd, + uint32_t *payload); int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd, uint32_t *payload); int msm_adsp_init_mixer_ctl_pp_event_queue(struct snd_soc_pcm_runtime *rtd); diff --git a/dsp/q6adm.c b/dsp/q6adm.c index eae22f7c528f..f2ae327ee554 100644 --- a/dsp/q6adm.c +++ b/dsp/q6adm.c @@ -52,6 +52,9 @@ enum adm_cal_status { ADM_STATUS_MAX, }; +typedef int (*adm_cb)(uint32_t opcode, uint32_t token, + uint32_t *pp_event_package, void *pvt); + struct adm_copp { atomic_t id[AFE_MAX_PORTS][MAX_COPPS_PER_PORT]; @@ -71,6 +74,8 @@ struct adm_copp { uint32_t adm_delay[AFE_MAX_PORTS][MAX_COPPS_PER_PORT]; unsigned long adm_status[AFE_MAX_PORTS][MAX_COPPS_PER_PORT]; atomic_t token[AFE_MAX_PORTS][MAX_COPPS_PER_PORT]; + adm_cb cb; + void *priv[AFE_MAX_PORTS][MAX_COPPS_PER_PORT][MAX_FE_ID]; }; struct source_tracking_data { @@ -163,6 +168,93 @@ static int adm_arrange_mch_map_v8( int channel_mode, int port_idx); +static uint32_t adm_pp_raise_event_opcode[] = { + ADM_PP_EVENT }; + +int q6adm_send_event_register_cmd(int port_id, int copp_idx, u8 *data, + int param_size, int opcode) +{ + struct adm_register_event *adm_reg_params = NULL; + int ret = 0, port_idx = 0, sz = 0; + + port_id = afe_convert_virtual_to_portid(port_id); + port_idx = adm_validate_and_get_port_index(port_id); + if (port_idx < 0) { + pr_err("%s: Invalid port_id %#x\n", __func__, port_id); + return -EINVAL; + } + + sz = sizeof(struct apr_hdr) + param_size; + adm_reg_params = kzalloc(sz, GFP_KERNEL); + + if (!adm_reg_params) + return -ENOMEM; + + memcpy(adm_reg_params->payload, data, param_size); + + adm_reg_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + adm_reg_params->hdr.src_svc = APR_SVC_ADM; + adm_reg_params->hdr.src_domain = APR_DOMAIN_APPS; + adm_reg_params->hdr.src_port = port_id; + adm_reg_params->hdr.dest_svc = APR_SVC_ADM; + adm_reg_params->hdr.dest_domain = APR_DOMAIN_ADSP; + adm_reg_params->hdr.dest_port = + atomic_read(&this_adm.copp.id[port_idx][copp_idx]); + adm_reg_params->hdr.token = port_idx << 16 | copp_idx; + adm_reg_params->hdr.opcode = opcode; + adm_reg_params->hdr.pkt_size = sz; + + atomic_set(&this_adm.copp.stat[port_idx][copp_idx], 0); + ret = apr_send_pkt(this_adm.apr, (uint32_t *)adm_reg_params); + if (ret < 0) { + pr_err("%s: Set adm register params failed port %d rc %d\n", + __func__, port_id, ret); + ret = -EINVAL; + goto fail_cmd; + } + + ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx], + atomic_read( + &this_adm.copp.stat[port_idx][copp_idx]) >= 0, + msecs_to_jiffies(TIMEOUT_MS)); + if (!ret) { + pr_err("%s: set params timed out port = %d\n", + __func__, port_id); + ret = -ETIMEDOUT; + goto fail_cmd; + } + ret = 0; +fail_cmd: + kfree(adm_reg_params); + + return ret; +} +EXPORT_SYMBOL(q6adm_send_event_register_cmd); + + +static int is_adsp_adm_raise_event(uint32_t cmd) +{ + int i = 0; + for (i = 0; i < ARRAY_SIZE(adm_pp_raise_event_opcode); i++) { + if (cmd == adm_pp_raise_event_opcode[i]) + return i; + } + return -EINVAL; +} + +void q6adm_register_callback(void *cb) +{ + this_adm.copp.cb = cb; +} +EXPORT_SYMBOL(q6adm_register_callback); + +void q6adm_clear_callback(void) +{ + this_adm.copp.cb = NULL; +} +EXPORT_SYMBOL(q6adm_clear_callback); + /** * adm_validate_and_get_port_index - * validate given port id @@ -1578,6 +1670,9 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) int port_idx, copp_idx, idx, client_id; int num_modules; int ret; + int payload_size = 0, i = 0; + struct msm_adsp_event_data *pp_event_package = NULL; + struct adm_usr_info usr_data = {0}; if (data == NULL) { pr_err("%s: data parameter is null\n", __func__); @@ -1749,6 +1844,13 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) pr_err("%s: ADM get topo list error = %d\n", __func__, payload[1]); break; + case ADM_CMD_REGISTER_EVENT: + pr_debug("%s:ADM_CMD_REGISTER_EVENT\n", + __func__); + if (payload[1] != 0) + pr_err("%s: ADM_CMD_REGISTER_EVENT error = %d\n", + __func__, payload[1]); + break; default: pr_err("%s: Unknown Cmd: 0x%x\n", __func__, payload[0]); @@ -1859,6 +1961,63 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) atomic_set(&this_adm.adm_stat, 0); wake_up(&this_adm.adm_wait); break; + case ADM_PP_EVENT: + if (data->payload_size < (2 * sizeof(uint32_t))) { + pr_err("%s: payload has invalid size %d\n", + __func__, data->payload_size); + return -EINVAL; + } + + pr_debug("%s: ADM_PP_EVENT payload[0][0x%x] payload[1][0x%x]\n", + __func__, payload[0], payload[1]); + + ret = is_adsp_adm_raise_event(data->opcode); + + if (ret < 0) + return 0; + + /* + * repack payload for adm_copp_pp_event + * package is composed of event type + size + payload + */ + payload_size = data->payload_size; + pp_event_package = kzalloc(payload_size + + sizeof(struct msm_adsp_event_data) + , GFP_ATOMIC); + + if (!pp_event_package) + return -ENOMEM; + + pp_event_package->event_type = ret + + ADSP_ADM_SERVICE_ID; + usr_data.service_id = ADSP_ADM_SERVICE_ID; + usr_data.token_coppidx = data->token; + + pp_event_package->payload_len = data->payload_size + + sizeof(struct adm_usr_info); + + memcpy((void *)pp_event_package->payload, &(usr_data), + sizeof(struct adm_usr_info)); + + memcpy((void *)pp_event_package->payload + + sizeof(struct adm_usr_info), + data->payload, data->payload_size); + if (this_adm.copp.cb) { + for (i = 0; i < MAX_FE_ID; i++) { + if (this_adm.copp.priv[port_idx] + [copp_idx][i]) { + pr_debug("%s: calling adm callback for feid %d port_idx %d copp_idx %d\n", + __func__, i, port_idx, copp_idx); + this_adm.copp.cb(data->opcode, + data->token, + (void *)pp_event_package, + this_adm.copp.priv[port_idx] + [copp_idx][i]); + } + } + } + kfree(pp_event_package); + break; default: pr_err("%s: Unknown cmd:0x%x\n", __func__, data->opcode); @@ -3006,6 +3165,33 @@ static int adm_arrange_mch_ep2_map_v8( return rc; } +int q6adm_update_rtd_info(void *rtd, int port_id, + int copp_idx, int fe_id, int enable) +{ + int port_idx = 0; + + port_id = q6audio_convert_virtual_to_portid(port_id); + port_idx = adm_validate_and_get_port_index(port_id); + + if (port_idx < 0) { + pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id); + return -EINVAL; + } + + pr_debug("%s: port_id %#x copp_idx %d fe_id %d enable %d\n", + __func__, port_id, copp_idx, fe_id, enable); + + if (enable) { + this_adm.copp.priv[port_idx][copp_idx][fe_id] = rtd; + } + else { + this_adm.copp.priv[port_idx][copp_idx][fe_id] = NULL; + } + + return 0; +} +EXPORT_SYMBOL(q6adm_update_rtd_info); + static int adm_copp_set_ec_ref_mfc_cfg_v2(int port_id, int copp_idx, int sample_rate, int bps, struct msm_pcm_channel_mixer *cfg) diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h old mode 100755 new mode 100644 index b6bdfeaa2aa5..f1c73e5087b8 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -30,6 +30,11 @@ struct param_outband { /* Instance ID definitions */ #define INSTANCE_ID_0 0x0000 +struct adm_register_event { + struct apr_hdr hdr; + __u8 payload[0]; +} __packed; + struct mem_mapping_hdr { /* * LSW of parameter data payload address. Supported values: any. @@ -135,6 +140,10 @@ struct module_instance_info { #define ADM_CMD_MATRIX_MAP_ROUTINGS_V5 0x00010325 #define ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5 0x0001033D + +#define ADM_CMD_REGISTER_EVENT 0x00010365 +#define ADM_PP_EVENT 0x00010366 + /* Enumeration for an audio Rx matrix ID.*/ #define ADM_MATRIX_ID_AUDIO_RX 0 @@ -671,6 +680,26 @@ struct dsp_stream_callback_prtd { spinlock_t prtd_spin_lock; }; +#define DSP_ADM_CALLBACK "ADSP COPP Callback Event" +#define DSP_ADM_CALLBACK_QUEUE_SIZE 1024 + +struct dsp_adm_callback_list { + struct list_head list; + struct msm_adsp_event_data event; +}; + +struct adm_usr_info { + u32 service_id; + u32 reserved; + u32 token_coppidx; +}; + +struct dsp_adm_callback_prtd { + uint16_t event_count; + struct list_head event_queue; + spinlock_t prtd_spin_lock; +}; + /* set customized mixing on matrix mixer */ #define ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5 0x00010344 struct adm_cmd_set_pspd_mtmx_strtr_params_v5 { diff --git a/include/dsp/q6adm-v2.h b/include/dsp/q6adm-v2.h index d6c20a962c64..a010b56cb5ac 100644 --- a/include/dsp/q6adm-v2.h +++ b/include/dsp/q6adm-v2.h @@ -16,6 +16,7 @@ #include #define MAX_MODULES_IN_TOPO 16 +#define MAX_FE_ID 33 #define ADM_GET_TOPO_MODULE_LIST_LENGTH\ ((MAX_MODULES_IN_TOPO + 1) * sizeof(uint32_t)) #define ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH \ @@ -246,4 +247,10 @@ void adm_set_native_mode(int mode); int adm_set_ffecns_freeze_event(bool ffecns_freeze_event); int adm_apr_send_pkt(void *data, wait_queue_head_t *wait, int port_idx, int copp_idx, int opcode); +void q6adm_register_callback(void *cb); +void q6adm_clear_callback(void); +int q6adm_send_event_register_cmd(int port_id, int copp_idx, u8 *data, + int param_size, int opcode); +int q6adm_update_rtd_info(void *rtd, int port_id, + int copp_idx, int fe_id, int enable); #endif /* __Q6_ADM_V2_H__ */ diff --git a/include/uapi/audio/linux/msm_audio.h b/include/uapi/audio/linux/msm_audio.h index c072b1363b9d..dda50ebc7fe1 100644 --- a/include/uapi/audio/linux/msm_audio.h +++ b/include/uapi/audio/linux/msm_audio.h @@ -456,6 +456,7 @@ struct msm_hwacc_effects_config { #define ADSP_STREAM_ENCDEC_EVENT 1 #define ADSP_STREAM_IEC_61937_FMT_UPDATE_EVENT 2 #define ADSP_STREAM_EVENT_MAX 3 +#define ADSP_ADM_SERVICE_ID 3 struct msm_adsp_event_data { __u32 event_type; @@ -463,4 +464,17 @@ struct msm_adsp_event_data { __u8 payload[0]; }; +struct module_info_data { + __u32 module_id; + __u32 instance_id; + __u32 be_id; + __u32 fe_id; +}; + +struct msm_adm_event_data { + __u32 event_type; + __u32 payload_length; + struct module_info_data mod_info; + __u8 payload[0]; +}; #endif