Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 04540527 authored by Kuirong Wang's avatar Kuirong Wang Committed by Banajit Goswami
Browse files

ASoC: msm: add support for new ADSP event APIs



Add support to handle new ADSP ASM stream event APIs for
different applications.

Change-Id: Id1e7b9b2841449ceb70099722d834b51c198f04e
Signed-off-by: default avatarKuirong Wang <kuirongw@codeaurora.org>
Signed-off-by: default avatarVidyakumar Athota <vathota@codeaurora.org>
parent a19e1a58
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -6334,6 +6334,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 {
+7 −2
Original line number Diff line number Diff line
@@ -619,7 +619,12 @@ 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,
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 */
+221 −9
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <asm/dma.h>
#include <linux/dma-mapping.h>
#include <linux/msm_audio_ion.h>
#include <linux/msm_audio.h>

#include <sound/timer.h>
#include <sound/tlv.h>
@@ -744,7 +745,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__);
@@ -757,7 +759,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: {
@@ -3599,7 +3600,119 @@ 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",
			__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;
	}

	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",
@@ -3610,20 +3723,20 @@ 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;
	}
@@ -3638,12 +3751,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;
@@ -4208,6 +4320,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->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->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;
@@ -4231,6 +4433,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",
+20 −13
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <asm/dma.h>
#include <linux/dma-mapping.h>
#include <linux/msm_audio_ion.h>
#include <linux/msm_audio.h>

#include <linux/of_device.h>
#include <sound/tlv.h>
@@ -227,8 +228,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(&param_length, ucontrol->value.bytes.data,
		sizeof(param_length));
	if ((param_length + sizeof(param_length))
		>= sizeof(ucontrol->value.bytes.data)) {
	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__, param_length);
			__func__, event_data->payload_len);
		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);
	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;
+194 −16
Original line number Diff line number Diff line
@@ -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)
{
@@ -1093,37 +1100,44 @@ void *q6asm_mmap_apr_reg(void)
	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;
	}
@@ -1131,13 +1145,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(
@@ -1772,6 +1786,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:
@@ -1786,7 +1802,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
@@ -1796,7 +1814,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);
@@ -2037,8 +2057,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
		 */
@@ -2049,7 +2077,7 @@ 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);
@@ -6886,6 +6914,156 @@ int q6asm_set_aptx_dec_bt_addr(struct audio_client *ac,
	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)
{