Merge "ASoC: msm: add support for new ADSP event APIs"
This commit is contained in:
commit
cf343cfb0f
5 changed files with 499 additions and 41 deletions
|
@ -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 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
|
#define ASM_PARAM_ID_ENCDEC_BITRATE 0x00010C13
|
||||||
|
|
||||||
struct asm_bitrate_param {
|
struct asm_bitrate_param {
|
||||||
|
|
|
@ -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,
|
int q6asm_send_audio_effects_params(struct audio_client *ac, char *params,
|
||||||
uint32_t params_length);
|
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);
|
void *param, uint32_t params_length);
|
||||||
|
|
||||||
/* Client can set the IO mode to either AIO/SIO mode */
|
/* Client can set the IO mode to either AIO/SIO mode */
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <asm/dma.h>
|
#include <asm/dma.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/msm_audio_ion.h>
|
#include <linux/msm_audio_ion.h>
|
||||||
|
#include <linux/msm_audio.h>
|
||||||
|
|
||||||
#include <sound/timer.h>
|
#include <sound/timer.h>
|
||||||
#include <sound/tlv.h>
|
#include <sound/tlv.h>
|
||||||
|
@ -742,7 +743,8 @@ static void compr_event_handler(uint32_t opcode,
|
||||||
spin_unlock_irqrestore(&prtd->lock, flags);
|
spin_unlock_irqrestore(&prtd->lock, flags);
|
||||||
break;
|
break;
|
||||||
case ASM_STREAM_PP_EVENT:
|
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;
|
rtd = cstream->private_data;
|
||||||
if (!rtd) {
|
if (!rtd) {
|
||||||
pr_err("%s: rtd is NULL\n", __func__);
|
pr_err("%s: rtd is NULL\n", __func__);
|
||||||
|
@ -755,7 +757,6 @@ static void compr_event_handler(uint32_t opcode,
|
||||||
__func__, ret);
|
__func__, ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
|
case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
|
||||||
case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY: {
|
case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY: {
|
||||||
|
@ -3588,7 +3589,8 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
|
||||||
snd_soc_component_get_drvdata(comp);
|
snd_soc_component_get_drvdata(comp);
|
||||||
struct snd_compr_stream *cstream = NULL;
|
struct snd_compr_stream *cstream = NULL;
|
||||||
struct msm_compr_audio *prtd;
|
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) {
|
if (fe_id >= MSM_FRONTEND_DAI_MAX) {
|
||||||
pr_err("%s Received invalid fe_id %lu\n",
|
pr_err("%s Received invalid fe_id %lu\n",
|
||||||
|
@ -3599,20 +3601,131 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
|
||||||
|
|
||||||
cstream = pdata->cstream[fe_id];
|
cstream = pdata->cstream[fe_id];
|
||||||
if (cstream == NULL) {
|
if (cstream == NULL) {
|
||||||
pr_err("%s cstream is null.\n", __func__);
|
pr_err("%s cstream is null\n", __func__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
prtd = cstream->runtime->private_data;
|
prtd = cstream->runtime->private_data;
|
||||||
if (!prtd) {
|
if (!prtd) {
|
||||||
pr_err("%s: prtd is null.\n", __func__);
|
pr_err("%s: prtd is null\n", __func__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prtd->audio_client == NULL) {
|
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;
|
ret = -EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -3627,12 +3740,11 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = q6asm_send_stream_cmd(prtd->audio_client,
|
ret = q6asm_send_rtic_event_ack(prtd->audio_client,
|
||||||
ASM_STREAM_CMD_REGISTER_PP_EVENTS,
|
|
||||||
ucontrol->value.bytes.data + sizeof(param_length),
|
ucontrol->value.bytes.data + sizeof(param_length),
|
||||||
param_length);
|
param_length);
|
||||||
if (ret < 0)
|
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);
|
__func__, ret);
|
||||||
done:
|
done:
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -4206,6 +4318,96 @@ static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
|
||||||
return 0;
|
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)
|
static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -4229,6 +4431,16 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
|
||||||
pr_err("%s: Could not add Compr ADSP Stream Callback Control\n",
|
pr_err("%s: Could not add Compr ADSP Stream Callback Control\n",
|
||||||
__func__);
|
__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);
|
rc = msm_compr_add_query_audio_effect_control(rtd);
|
||||||
if (rc)
|
if (rc)
|
||||||
pr_err("%s: Could not add Compr Query Audio Effect Control\n",
|
pr_err("%s: Could not add Compr Query Audio Effect Control\n",
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <asm/dma.h>
|
#include <asm/dma.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/msm_audio_ion.h>
|
#include <linux/msm_audio_ion.h>
|
||||||
|
#include <linux/msm_audio.h>
|
||||||
|
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <sound/tlv.h>
|
#include <sound/tlv.h>
|
||||||
|
@ -226,8 +227,9 @@ static void event_handler(uint32_t opcode,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ASM_STREAM_PP_EVENT: {
|
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);
|
||||||
if (!substream) {
|
if (!substream) {
|
||||||
pr_err("%s: substream is NULL.\n", __func__);
|
pr_err("%s: substream is NULL.\n", __func__);
|
||||||
return;
|
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 msm_plat_data *pdata = dev_get_drvdata(platform->dev);
|
||||||
struct snd_pcm_substream *substream;
|
struct snd_pcm_substream *substream;
|
||||||
struct msm_audio *prtd;
|
struct msm_audio *prtd;
|
||||||
int ret = 0, param_length = 0;
|
int ret = 0;
|
||||||
|
struct msm_adsp_event_data *event_data = NULL;
|
||||||
|
|
||||||
if (!pdata) {
|
if (!pdata) {
|
||||||
pr_err("%s pdata is NULL\n", __func__);
|
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;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(¶m_length, ucontrol->value.bytes.data,
|
event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
|
||||||
sizeof(param_length));
|
if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
|
||||||
if ((param_length + sizeof(param_length))
|
(event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
|
||||||
>= sizeof(ucontrol->value.bytes.data)) {
|
pr_err("%s: invalid event_type=%d",
|
||||||
pr_err("%s param length=%d exceeds limit",
|
__func__, event_data->event_type);
|
||||||
__func__, param_length);
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = q6asm_send_stream_cmd(prtd->audio_client,
|
if ((sizeof(struct msm_adsp_event_data) + event_data->payload_len) >=
|
||||||
ASM_STREAM_CMD_REGISTER_PP_EVENTS,
|
sizeof(ucontrol->value.bytes.data)) {
|
||||||
ucontrol->value.bytes.data + sizeof(param_length),
|
pr_err("%s param length=%d exceeds limit",
|
||||||
param_length);
|
__func__, event_data->payload_len);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = q6asm_send_stream_cmd(prtd->audio_client, event_data);
|
||||||
if (ret < 0)
|
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);
|
__func__, ret);
|
||||||
done:
|
done:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -155,6 +155,13 @@ static int out_cold_index;
|
||||||
static char *out_buffer;
|
static char *out_buffer;
|
||||||
static char *in_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,
|
static inline void q6asm_set_flag_in_token(union asm_token_struct *asm_token,
|
||||||
int flag, int flag_offset)
|
int flag, int flag_offset)
|
||||||
{
|
{
|
||||||
|
@ -1096,37 +1103,44 @@ fail:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int q6asm_send_stream_cmd(struct audio_client *ac, uint32_t opcode,
|
int q6asm_send_stream_cmd(struct audio_client *ac,
|
||||||
void *param, uint32_t params_length)
|
struct msm_adsp_event_data *data)
|
||||||
{
|
{
|
||||||
char *asm_params = NULL;
|
char *asm_params = NULL;
|
||||||
struct apr_hdr hdr;
|
struct apr_hdr hdr;
|
||||||
int sz, rc;
|
int sz, rc;
|
||||||
|
|
||||||
if (!param || !ac) {
|
if (!data || !ac) {
|
||||||
pr_err("%s: %s is NULL\n", __func__,
|
pr_err("%s: %s is NULL\n", __func__,
|
||||||
(!param) ? "param" : "ac");
|
(!data) ? "data" : "ac");
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto done;
|
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);
|
asm_params = kzalloc(sz, GFP_KERNEL);
|
||||||
if (!asm_params) {
|
if (!asm_params) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
q6asm_add_hdr_async(ac, &hdr, sizeof(struct apr_hdr) +
|
q6asm_add_hdr_async(ac, &hdr, sz, TRUE);
|
||||||
params_length, TRUE);
|
|
||||||
atomic_set(&ac->cmd_state_pp, -1);
|
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, &hdr, sizeof(struct apr_hdr));
|
||||||
memcpy(asm_params + 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);
|
rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
|
||||||
if (rc < 0) {
|
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;
|
rc = -EINVAL;
|
||||||
goto fail_send_param;
|
goto fail_send_param;
|
||||||
}
|
}
|
||||||
|
@ -1134,13 +1148,13 @@ int q6asm_send_stream_cmd(struct audio_client *ac, uint32_t opcode,
|
||||||
rc = wait_event_timeout(ac->cmd_wait,
|
rc = wait_event_timeout(ac->cmd_wait,
|
||||||
(atomic_read(&ac->cmd_state_pp) >= 0), 1 * HZ);
|
(atomic_read(&ac->cmd_state_pp) >= 0), 1 * HZ);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
pr_err("%s: timeout, adsp pp register\n", __func__);
|
pr_err("%s: timeout for stream event cmd resp\n", __func__);
|
||||||
rc = -ETIMEDOUT;
|
rc = -ETIMEDOUT;
|
||||||
goto fail_send_param;
|
goto fail_send_param;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_read(&ac->cmd_state_pp) > 0) {
|
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(
|
__func__, adsp_err_get_err_str(
|
||||||
atomic_read(&ac->cmd_state_pp)));
|
atomic_read(&ac->cmd_state_pp)));
|
||||||
rc = adsp_err_get_lnx_err_code(
|
rc = adsp_err_get_lnx_err_code(
|
||||||
|
@ -1779,6 +1793,8 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
|
||||||
case ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK:
|
case ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK:
|
||||||
case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2:
|
case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2:
|
||||||
case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
|
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_INITIAL_SILENCE:
|
||||||
case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
|
case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
|
||||||
case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS:
|
case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS:
|
||||||
|
@ -1793,7 +1809,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
|
||||||
__func__, payload[0], payload[1]);
|
__func__, payload[0], payload[1]);
|
||||||
if (wakeup_flag) {
|
if (wakeup_flag) {
|
||||||
if (payload[0] ==
|
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,
|
atomic_set(&ac->cmd_state_pp,
|
||||||
payload[1]);
|
payload[1]);
|
||||||
else
|
else
|
||||||
|
@ -1803,7 +1821,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
|
||||||
}
|
}
|
||||||
return 0;
|
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) &&
|
if (atomic_read(&ac->cmd_state_pp) &&
|
||||||
wakeup_flag) {
|
wakeup_flag) {
|
||||||
atomic_set(&ac->cmd_state_pp, 0);
|
atomic_set(&ac->cmd_state_pp, 0);
|
||||||
|
@ -2043,8 +2063,16 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
|
||||||
q6asm_process_mtmx_get_param_rsp(ac, (void *) payload);
|
q6asm_process_mtmx_get_param_rsp(ac, (void *) payload);
|
||||||
break;
|
break;
|
||||||
case ASM_STREAM_PP_EVENT:
|
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]",
|
pr_debug("%s: ASM_STREAM_PP_EVENT payload[0][0x%x] payload[1][0x%x]",
|
||||||
__func__, payload[0], payload[1]);
|
__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
|
/* repack payload for asm_stream_pp_event
|
||||||
* package is composed of event type + size + actual payload
|
* package is composed of event type + size + actual payload
|
||||||
*/
|
*/
|
||||||
|
@ -2055,7 +2083,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
|
||||||
if (!pp_event_package)
|
if (!pp_event_package)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
pp_event_package->event_type = ASM_STREAM_PP_EVENT;
|
pp_event_package->event_type = i;
|
||||||
pp_event_package->payload_len = payload_size;
|
pp_event_package->payload_len = payload_size;
|
||||||
memcpy((void *)pp_event_package->payload,
|
memcpy((void *)pp_event_package->payload,
|
||||||
data->payload, payload_size);
|
data->payload, payload_size);
|
||||||
|
@ -6898,6 +6926,156 @@ fail_cmd:
|
||||||
return rc;
|
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,
|
int q6asm_set_softpause(struct audio_client *ac,
|
||||||
struct asm_softpause_params *pause_param)
|
struct asm_softpause_params *pause_param)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue