diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index d51f07c73053..c6d332151436 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -6333,6 +6333,62 @@ struct asm_stream_cmd_get_pp_params_v2 { #define ASM_STREAM_CMD_SET_ENCDEC_PARAM 0x00010C10 +#define ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2 0x00013218 + +struct asm_stream_cmd_set_encdec_param_v2 { + u16 service_id; + /* 0 - ASM_ENCODER_SVC; 1 - ASM_DECODER_SVC */ + + u16 reserved; + + u32 param_id; + /* ID of the parameter. */ + + u32 param_size; + /* + * Data size of this parameter, in bytes. The size is a multiple + * of 4 bytes. + */ +} __packed; + +#define ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS 0x00013219 + +#define ASM_STREAM_CMD_ENCDEC_EVENTS 0x0001321A + +#define AVS_PARAM_ID_RTIC_SHARED_MEMORY_ADDR 0x00013237 + +struct avs_rtic_shared_mem_addr { + struct apr_hdr hdr; + struct asm_stream_cmd_set_encdec_param_v2 encdec; + u32 shm_buf_addr_lsw; + /* Lower 32 bit of the RTIC shared memory */ + + u32 shm_buf_addr_msw; + /* Upper 32 bit of the RTIC shared memory */ + + u32 buf_size; + /* Size of buffer */ + + u16 shm_buf_mem_pool_id; + /* ADSP_MEMORY_MAP_SHMEM8_4K_POOL */ + + u16 shm_buf_num_regions; + /* number of regions to map */ + + u32 shm_buf_flag; + /* buffer property flag */ + + struct avs_shared_map_region_payload map_region; + /* memory map region*/ +} __packed; + +#define AVS_PARAM_ID_RTIC_EVENT_ACK 0x00013238 + +struct avs_param_rtic_event_ack { + struct apr_hdr hdr; + struct asm_stream_cmd_set_encdec_param_v2 encdec; +} __packed; + #define ASM_PARAM_ID_ENCDEC_BITRATE 0x00010C13 struct asm_bitrate_param { diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index 29707b26644a..7b7de427735e 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -618,8 +618,13 @@ int q6asm_get_session_time_legacy(struct audio_client *ac, uint64_t *tstamp); int q6asm_send_audio_effects_params(struct audio_client *ac, char *params, uint32_t params_length); -int q6asm_send_stream_cmd(struct audio_client *ac, uint32_t opcode, - void *param, uint32_t params_length); +int q6asm_send_stream_cmd(struct audio_client *ac, + struct msm_adsp_event_data *data); + +int q6asm_send_ion_fd(struct audio_client *ac, int fd); + +int q6asm_send_rtic_event_ack(struct audio_client *ac, + void *param, uint32_t params_length); /* Client can set the IO mode to either AIO/SIO mode */ int q6asm_set_io_mode(struct audio_client *ac, uint32_t mode); diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index fd93a315c941..7a4f09c0fa34 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -725,7 +726,8 @@ static void compr_event_handler(uint32_t opcode, spin_unlock_irqrestore(&prtd->lock, flags); break; case ASM_STREAM_PP_EVENT: - pr_debug("%s: ASM_STREAM_PP_EVENT\n", __func__); + case ASM_STREAM_CMD_ENCDEC_EVENTS: + pr_debug("%s: ASM_STREAM_EVENT(0x%x)\n", __func__, opcode); rtd = cstream->private_data; if (!rtd) { pr_err("%s: rtd is NULL\n", __func__); @@ -738,7 +740,6 @@ static void compr_event_handler(uint32_t opcode, __func__, ret); return; } - break; case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY: case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY: { @@ -3616,7 +3617,8 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, snd_soc_component_get_drvdata(comp); struct snd_compr_stream *cstream = NULL; struct msm_compr_audio *prtd; - int ret = 0, param_length = 0; + int ret = 0; + struct msm_adsp_event_data *event_data = NULL; if (fe_id >= MSM_FRONTEND_DAI_MAX) { pr_err("%s Received invalid fe_id %lu\n", @@ -3627,20 +3629,131 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, cstream = pdata->cstream[fe_id]; if (cstream == NULL) { - pr_err("%s cstream is null.\n", __func__); + pr_err("%s cstream is null\n", __func__); ret = -EINVAL; goto done; } prtd = cstream->runtime->private_data; if (!prtd) { - pr_err("%s: prtd is null.\n", __func__); + pr_err("%s: prtd is null\n", __func__); ret = -EINVAL; goto done; } if (prtd->audio_client == NULL) { - pr_err("%s: audio_client is null.\n", __func__); + pr_err("%s: audio_client is null\n", __func__); + ret = -EINVAL; + goto done; + } + + event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data; + if ((event_data->event_type < ADSP_STREAM_PP_EVENT) || + (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) { + pr_err("%s: invalid event_type=%d", + __func__, event_data->event_type); + ret = -EINVAL; + goto done; + } + + if ((sizeof(struct msm_adsp_event_data) + event_data->payload_len) >= + sizeof(ucontrol->value.bytes.data)) { + pr_err("%s param length=%d exceeds limit", + __func__, event_data->payload_len); + ret = -EINVAL; + goto done; + } + + ret = q6asm_send_stream_cmd(prtd->audio_client, event_data); + if (ret < 0) + pr_err("%s: failed to send stream event cmd, err = %d\n", + __func__, ret); +done: + return ret; +} + +static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + unsigned long fe_id = kcontrol->private_value; + struct msm_compr_pdata *pdata = (struct msm_compr_pdata *) + snd_soc_component_get_drvdata(comp); + struct snd_compr_stream *cstream = NULL; + struct msm_compr_audio *prtd; + int fd; + int ret = 0; + + if (fe_id >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s Received out of bounds invalid fe_id %lu\n", + __func__, fe_id); + ret = -EINVAL; + goto done; + } + + cstream = pdata->cstream[fe_id]; + if (cstream == NULL) { + pr_err("%s cstream is null\n", __func__); + ret = -EINVAL; + goto done; + } + + prtd = cstream->runtime->private_data; + if (!prtd) { + pr_err("%s: prtd is null\n", __func__); + ret = -EINVAL; + goto done; + } + + if (prtd->audio_client == NULL) { + pr_err("%s: audio_client is null\n", __func__); + ret = -EINVAL; + goto done; + } + + memcpy(&fd, ucontrol->value.bytes.data, sizeof(fd)); + ret = q6asm_send_ion_fd(prtd->audio_client, fd); + if (ret < 0) + pr_err("%s: failed to register ion fd\n", __func__); +done: + return ret; +} + +static int msm_compr_rtic_event_ack_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + unsigned long fe_id = kcontrol->private_value; + struct msm_compr_pdata *pdata = (struct msm_compr_pdata *) + snd_soc_component_get_drvdata(comp); + struct snd_compr_stream *cstream = NULL; + struct msm_compr_audio *prtd; + int ret = 0; + int param_length = 0; + + if (fe_id >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s Received invalid fe_id %lu\n", + __func__, fe_id); + ret = -EINVAL; + goto done; + } + + cstream = pdata->cstream[fe_id]; + if (cstream == NULL) { + pr_err("%s cstream is null\n", __func__); + ret = -EINVAL; + goto done; + } + + prtd = cstream->runtime->private_data; + if (!prtd) { + pr_err("%s: prtd is null\n", __func__); + ret = -EINVAL; + goto done; + } + + if (prtd->audio_client == NULL) { + pr_err("%s: audio_client is null\n", __func__); ret = -EINVAL; goto done; } @@ -3655,12 +3768,11 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, goto done; } - ret = q6asm_send_stream_cmd(prtd->audio_client, - ASM_STREAM_CMD_REGISTER_PP_EVENTS, + ret = q6asm_send_rtic_event_ack(prtd->audio_client, ucontrol->value.bytes.data + sizeof(param_length), param_length); if (ret < 0) - pr_err("%s: failed to register pp event. err = %d\n", + pr_err("%s: failed to send rtic event ack, err = %d\n", __func__, ret); done: return ret; @@ -4234,6 +4346,96 @@ static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd) return 0; } +static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd) +{ + const char *mixer_ctl_name = "Playback ION FD"; + const char *deviceNo = "NN"; + char *mixer_str = NULL; + int ctl_len = 0, ret = 0; + struct snd_kcontrol_new fe_ion_fd_config_control[1] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "?", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = msm_adsp_stream_cmd_info, + .put = msm_compr_ion_fd_map_put, + .private_value = 0, + } + }; + + if (!rtd) { + pr_err("%s NULL rtd\n", __func__); + ret = -EINVAL; + goto done; + } + + ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; + mixer_str = kzalloc(ctl_len, GFP_KERNEL); + if (!mixer_str) { + ret = -ENOMEM; + goto done; + } + + snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); + fe_ion_fd_config_control[0].name = mixer_str; + fe_ion_fd_config_control[0].private_value = rtd->dai_link->be_id; + pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str); + ret = snd_soc_add_platform_controls(rtd->platform, + fe_ion_fd_config_control, + ARRAY_SIZE(fe_ion_fd_config_control)); + if (ret < 0) + pr_err("%s: failed to add ctl %s\n", __func__, mixer_str); + + kfree(mixer_str); +done: + return ret; +} + +static int msm_compr_add_event_ack_cmd_control(struct snd_soc_pcm_runtime *rtd) +{ + const char *mixer_ctl_name = "Playback Event Ack"; + const char *deviceNo = "NN"; + char *mixer_str = NULL; + int ctl_len = 0, ret = 0; + struct snd_kcontrol_new fe_event_ack_config_control[1] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "?", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = msm_adsp_stream_cmd_info, + .put = msm_compr_rtic_event_ack_put, + .private_value = 0, + } + }; + + if (!rtd) { + pr_err("%s NULL rtd\n", __func__); + ret = -EINVAL; + goto done; + } + + ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; + mixer_str = kzalloc(ctl_len, GFP_KERNEL); + if (!mixer_str) { + ret = -ENOMEM; + goto done; + } + + snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); + fe_event_ack_config_control[0].name = mixer_str; + fe_event_ack_config_control[0].private_value = rtd->dai_link->be_id; + pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str); + ret = snd_soc_add_platform_controls(rtd->platform, + fe_event_ack_config_control, + ARRAY_SIZE(fe_event_ack_config_control)); + if (ret < 0) + pr_err("%s: failed to add ctl %s\n", __func__, mixer_str); + + kfree(mixer_str); +done: + return ret; +} + static int msm_compr_new(struct snd_soc_pcm_runtime *rtd) { int rc; @@ -4257,6 +4459,16 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd) pr_err("%s: Could not add Compr ADSP Stream Callback Control\n", __func__); + rc = msm_compr_add_io_fd_cmd_control(rtd); + if (rc) + pr_err("%s: Could not add Compr ion fd Control\n", + __func__); + + rc = msm_compr_add_event_ack_cmd_control(rtd); + if (rc) + pr_err("%s: Could not add Compr event ack Control\n", + __func__); + rc = msm_compr_add_query_audio_effect_control(rtd); if (rc) pr_err("%s: Could not add Compr Query Audio Effect Control\n", diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index 8f43aee3974c..3be6567aefab 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -226,8 +227,9 @@ static void event_handler(uint32_t opcode, } break; } - case ASM_STREAM_PP_EVENT: { - pr_debug("%s: ASM_STREAM_PP_EVENT\n", __func__); + case ASM_STREAM_PP_EVENT: + case ASM_STREAM_CMD_ENCDEC_EVENTS: { + pr_debug("%s: ASM_STREAM_EVENT (0x%x)\n", __func__, opcode); if (!substream) { pr_err("%s: substream is NULL.\n", __func__); return; @@ -1075,7 +1077,8 @@ static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, struct msm_plat_data *pdata = dev_get_drvdata(platform->dev); struct snd_pcm_substream *substream; struct msm_audio *prtd; - int ret = 0, param_length = 0; + int ret = 0; + struct msm_adsp_event_data *event_data = NULL; if (!pdata) { pr_err("%s pdata is NULL\n", __func__); @@ -1103,22 +1106,26 @@ static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, goto done; } - memcpy(¶m_length, ucontrol->value.bytes.data, - sizeof(param_length)); - if ((param_length + sizeof(param_length)) - >= sizeof(ucontrol->value.bytes.data)) { - pr_err("%s param length=%d exceeds limit", - __func__, param_length); + event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data; + if ((event_data->event_type < ADSP_STREAM_PP_EVENT) || + (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) { + pr_err("%s: invalid event_type=%d", + __func__, event_data->event_type); ret = -EINVAL; goto done; } - ret = q6asm_send_stream_cmd(prtd->audio_client, - ASM_STREAM_CMD_REGISTER_PP_EVENTS, - ucontrol->value.bytes.data + sizeof(param_length), - param_length); + if ((sizeof(struct msm_adsp_event_data) + event_data->payload_len) >= + sizeof(ucontrol->value.bytes.data)) { + pr_err("%s param length=%d exceeds limit", + __func__, event_data->payload_len); + ret = -EINVAL; + goto done; + } + + ret = q6asm_send_stream_cmd(prtd->audio_client, event_data); if (ret < 0) - pr_err("%s: failed to register pp event. err = %d\n", + pr_err("%s: failed to send stream event cmd, err = %d\n", __func__, ret); done: return ret; diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 397001d85a69..24a4bc22086c 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -155,6 +155,13 @@ 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}; + +static uint32_t adsp_raise_event_opcode[] = {ASM_STREAM_PP_EVENT, + ASM_STREAM_CMD_ENCDEC_EVENTS}; + + static inline void q6asm_set_flag_in_token(union asm_token_struct *asm_token, int flag, int flag_offset) { @@ -1094,37 +1101,44 @@ fail: return NULL; } -int q6asm_send_stream_cmd(struct audio_client *ac, uint32_t opcode, - void *param, uint32_t params_length) +int q6asm_send_stream_cmd(struct audio_client *ac, + struct msm_adsp_event_data *data) { char *asm_params = NULL; struct apr_hdr hdr; int sz, rc; - if (!param || !ac) { + if (!data || !ac) { pr_err("%s: %s is NULL\n", __func__, - (!param) ? "param" : "ac"); + (!data) ? "data" : "ac"); rc = -EINVAL; goto done; } - sz = sizeof(struct apr_hdr) + params_length; + if (data->event_type >= ARRAY_SIZE(adsp_reg_event_opcode)) { + pr_err("%s: event %u out of boundary of array size of (%lu)\n", + __func__, data->event_type, + (long)ARRAY_SIZE(adsp_reg_event_opcode)); + rc = -EINVAL; + goto done; + } + + sz = sizeof(struct apr_hdr) + data->payload_len; asm_params = kzalloc(sz, GFP_KERNEL); if (!asm_params) { rc = -ENOMEM; goto done; } - q6asm_add_hdr_async(ac, &hdr, sizeof(struct apr_hdr) + - params_length, TRUE); + q6asm_add_hdr_async(ac, &hdr, sz, TRUE); atomic_set(&ac->cmd_state_pp, -1); - hdr.opcode = opcode; + hdr.opcode = adsp_reg_event_opcode[data->event_type]; memcpy(asm_params, &hdr, sizeof(struct apr_hdr)); memcpy(asm_params + sizeof(struct apr_hdr), - param, params_length); + data->payload, data->payload_len); rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params); if (rc < 0) { - pr_err("%s: audio adsp pp register failed\n", __func__); + pr_err("%s: stream event cmd apr pkt failed\n", __func__); rc = -EINVAL; goto fail_send_param; } @@ -1132,13 +1146,13 @@ int q6asm_send_stream_cmd(struct audio_client *ac, uint32_t opcode, rc = wait_event_timeout(ac->cmd_wait, (atomic_read(&ac->cmd_state_pp) >= 0), 1 * HZ); if (!rc) { - pr_err("%s: timeout, adsp pp register\n", __func__); + pr_err("%s: timeout for stream event cmd resp\n", __func__); rc = -ETIMEDOUT; goto fail_send_param; } if (atomic_read(&ac->cmd_state_pp) > 0) { - pr_err("%s: DSP returned error[%s] adsp pp register\n", + pr_err("%s: DSP returned error[%s] for stream event cmd\n", __func__, adsp_err_get_err_str( atomic_read(&ac->cmd_state_pp))); rc = adsp_err_get_lnx_err_code( @@ -1776,6 +1790,8 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) case ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK: case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2: case ASM_STREAM_CMD_SET_ENCDEC_PARAM: + case ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2: + case ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS: case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE: case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE: case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS: @@ -1790,7 +1806,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) __func__, payload[0], payload[1]); if (wakeup_flag) { if (payload[0] == - ASM_STREAM_CMD_SET_PP_PARAMS_V2) + ASM_STREAM_CMD_SET_PP_PARAMS_V2 + || payload[0] == + ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS) atomic_set(&ac->cmd_state_pp, payload[1]); else @@ -1800,7 +1818,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) } return 0; } - if (payload[0] == ASM_STREAM_CMD_SET_PP_PARAMS_V2) { + if (payload[0] == ASM_STREAM_CMD_SET_PP_PARAMS_V2 || + payload[0] == + ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS) { if (atomic_read(&ac->cmd_state_pp) && wakeup_flag) { atomic_set(&ac->cmd_state_pp, 0); @@ -2040,8 +2060,16 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) q6asm_process_mtmx_get_param_rsp(ac, (void *) payload); break; case ASM_STREAM_PP_EVENT: + case ASM_STREAM_CMD_ENCDEC_EVENTS: pr_debug("%s: ASM_STREAM_PP_EVENT payload[0][0x%x] payload[1][0x%x]", __func__, payload[0], payload[1]); + for (i = 0; i < ARRAY_SIZE(adsp_raise_event_opcode); i++) + if (adsp_raise_event_opcode[i] == data->opcode) + break; + + if (i >= ARRAY_SIZE(adsp_raise_event_opcode)) + return 0; + /* repack payload for asm_stream_pp_event * package is composed of event type + size + actual payload */ @@ -2052,10 +2080,10 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) if (!pp_event_package) return -ENOMEM; - pp_event_package->event_type = ASM_STREAM_PP_EVENT; + pp_event_package->event_type = i; pp_event_package->payload_len = payload_size; memcpy((void *)pp_event_package->payload, - data->payload, payload_size); + data->payload, payload_size); ac->cb(data->opcode, data->token, (void *)pp_event_package, ac->priv); kfree(pp_event_package); @@ -7128,6 +7156,156 @@ fail_cmd: return rc; } +int q6asm_send_ion_fd(struct audio_client *ac, int fd) +{ + struct ion_client *client; + struct ion_handle *handle; + ion_phys_addr_t paddr; + size_t pa_len = 0; + void *vaddr; + int ret; + int sz = 0; + struct avs_rtic_shared_mem_addr shm; + + if (ac == NULL) { + pr_err("%s: APR handle NULL\n", __func__); + ret = -EINVAL; + goto fail_cmd; + } + if (ac->apr == NULL) { + pr_err("%s: AC APR handle NULL\n", __func__); + ret = -EINVAL; + goto fail_cmd; + } + + ret = msm_audio_ion_import("audio_mem_client", + &client, + &handle, + fd, + NULL, + 0, + &paddr, + &pa_len, + &vaddr); + if (ret) { + pr_err("%s: audio ION import failed, rc = %d\n", + __func__, ret); + ret = -ENOMEM; + goto fail_cmd; + } + /* get payload length */ + sz = sizeof(struct avs_rtic_shared_mem_addr); + q6asm_add_hdr_async(ac, &shm.hdr, sz, TRUE); + atomic_set(&ac->cmd_state, -1); + shm.shm_buf_addr_lsw = lower_32_bits(paddr); + shm.shm_buf_addr_msw = msm_audio_populate_upper_32_bits(paddr); + shm.buf_size = pa_len; + shm.shm_buf_num_regions = 1; + shm.shm_buf_mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL; + shm.shm_buf_flag = 0x00; + shm.encdec.param_id = AVS_PARAM_ID_RTIC_SHARED_MEMORY_ADDR; + shm.encdec.param_size = sizeof(struct avs_rtic_shared_mem_addr) - + sizeof(struct apr_hdr) - + sizeof(struct asm_stream_cmd_set_encdec_param_v2); + shm.encdec.service_id = OUT; + shm.encdec.reserved = 0; + shm.map_region.shm_addr_lsw = shm.shm_buf_addr_lsw; + shm.map_region.shm_addr_msw = shm.shm_buf_addr_msw; + shm.map_region.mem_size_bytes = pa_len; + shm.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2; + ret = apr_send_pkt(ac->apr, (uint32_t *) &shm); + if (ret < 0) { + pr_err("%s: set-params send failed paramid[0x%x] rc %d\n", + __func__, shm.encdec.param_id, ret); + ret = -EINVAL; + goto fail_cmd; + } + + ret = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state) >= 0), 1*HZ); + if (!ret) { + pr_err("%s: timeout, shm.encdec paramid[0x%x]\n", __func__, + shm.encdec.param_id); + ret = -ETIMEDOUT; + goto fail_cmd; + } + if (atomic_read(&ac->cmd_state) > 0) { + pr_err("%s: DSP returned error[%s] shm.encdec paramid[0x%x]\n", + __func__, + adsp_err_get_err_str(atomic_read(&ac->cmd_state)), + shm.encdec.param_id); + ret = adsp_err_get_lnx_err_code(atomic_read(&ac->cmd_state)); + goto fail_cmd; + } + ret = 0; +fail_cmd: + return ret; +} + +int q6asm_send_rtic_event_ack(struct audio_client *ac, + void *param, uint32_t params_length) +{ + char *asm_params = NULL; + int sz, rc; + struct avs_param_rtic_event_ack ack; + + if (!param || !ac) { + pr_err("%s: %s is NULL\n", __func__, + (!param) ? "param" : "ac"); + rc = -EINVAL; + goto done; + } + + sz = sizeof(struct avs_param_rtic_event_ack) + params_length; + asm_params = kzalloc(sz, GFP_KERNEL); + if (!asm_params) { + rc = -ENOMEM; + goto done; + } + + q6asm_add_hdr_async(ac, &ack.hdr, + sizeof(struct avs_param_rtic_event_ack) + + params_length, TRUE); + atomic_set(&ac->cmd_state, -1); + ack.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2; + ack.encdec.param_id = AVS_PARAM_ID_RTIC_EVENT_ACK; + ack.encdec.param_size = params_length; + ack.encdec.reserved = 0; + ack.encdec.service_id = OUT; + memcpy(asm_params, &ack, sizeof(struct avs_param_rtic_event_ack)); + memcpy(asm_params + sizeof(struct avs_param_rtic_event_ack), + param, params_length); + rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params); + if (rc < 0) { + pr_err("%s: apr pkt failed for rtic event ack\n", __func__); + rc = -EINVAL; + goto fail_send_param; + } + + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state) >= 0), 1 * HZ); + if (!rc) { + pr_err("%s: timeout for rtic event ack cmd\n", __func__); + rc = -ETIMEDOUT; + goto fail_send_param; + } + + if (atomic_read(&ac->cmd_state) > 0) { + pr_err("%s: DSP returned error[%s] for rtic event ack cmd\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_send_param; + } + rc = 0; + +fail_send_param: + kfree(asm_params); +done: + return rc; +} + int q6asm_set_softpause(struct audio_client *ac, struct asm_softpause_params *pause_param) {