lsm: add support for ADSP multi stage VA
Enhance APIs to get instance id and stage info from userspace, required for multi-stage Voice Activation in ADSP. Change-Id: Ie39a3d002a56fb8df0c241089a50d55ef700a538 Signed-off-by: Dhananjay Kumar <dhakumar@codeaurora.org>
This commit is contained in:
@@ -42,6 +42,9 @@
|
||||
#define LAB_BUFFER_ALLOC 1
|
||||
#define LAB_BUFFER_DEALLOC 0
|
||||
|
||||
#define LSM_IS_LAST_STAGE(client, stage_idx) \
|
||||
(client->num_stages == (stage_idx + 1))
|
||||
|
||||
static struct snd_pcm_hardware msm_pcm_hardware_capture = {
|
||||
.info = (SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
@@ -463,7 +466,7 @@ done:
|
||||
}
|
||||
|
||||
static int msm_lsm_set_epd(struct snd_pcm_substream *substream,
|
||||
struct lsm_params_info *p_info)
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct lsm_priv *prtd = runtime->private_data;
|
||||
@@ -499,7 +502,7 @@ done:
|
||||
}
|
||||
|
||||
static int msm_lsm_set_mode(struct snd_pcm_substream *substream,
|
||||
struct lsm_params_info *p_info)
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct lsm_priv *prtd = runtime->private_data;
|
||||
@@ -535,7 +538,7 @@ done:
|
||||
}
|
||||
|
||||
static int msm_lsm_set_gain(struct snd_pcm_substream *substream,
|
||||
struct lsm_params_info *p_info)
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct lsm_priv *prtd = runtime->private_data;
|
||||
@@ -571,7 +574,7 @@ done:
|
||||
}
|
||||
|
||||
static int msm_lsm_set_conf(struct snd_pcm_substream *substream,
|
||||
struct lsm_params_info *p_info)
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct lsm_priv *prtd = runtime->private_data;
|
||||
@@ -608,18 +611,17 @@ static int msm_lsm_set_conf(struct snd_pcm_substream *substream,
|
||||
}
|
||||
|
||||
static int msm_lsm_reg_model(struct snd_pcm_substream *substream,
|
||||
struct lsm_params_info *p_info)
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct lsm_priv *prtd = runtime->private_data;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
int rc = 0;
|
||||
u8 *snd_model_ptr;
|
||||
size_t offset;
|
||||
struct lsm_sound_model *sm = NULL;
|
||||
size_t offset = sizeof(union param_hdrs);
|
||||
|
||||
rc = q6lsm_snd_model_buf_alloc(prtd->lsm_client,
|
||||
p_info->param_size,
|
||||
true);
|
||||
p_info->param_size, p_info);
|
||||
if (rc) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: snd_model buf alloc failed, size = %d\n",
|
||||
@@ -633,9 +635,9 @@ static int msm_lsm_reg_model(struct snd_pcm_substream *substream,
|
||||
* For set_param, advance the sound model data with the
|
||||
* number of bytes required by param_data.
|
||||
*/
|
||||
snd_model_ptr = ((u8 *) prtd->lsm_client->sound_model.data) + offset;
|
||||
|
||||
if (copy_from_user(snd_model_ptr,
|
||||
sm = &prtd->lsm_client->stage_cfg[p_info->stage_idx].sound_model;
|
||||
if (copy_from_user((u8 *)sm->data + offset,
|
||||
p_info->param_data, p_info->param_size)) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: copy_from_user for snd_model failed, size = %d\n",
|
||||
@@ -654,12 +656,12 @@ static int msm_lsm_reg_model(struct snd_pcm_substream *substream,
|
||||
return rc;
|
||||
|
||||
err_copy:
|
||||
q6lsm_snd_model_buf_free(prtd->lsm_client);
|
||||
q6lsm_snd_model_buf_free(prtd->lsm_client, p_info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_lsm_dereg_model(struct snd_pcm_substream *substream,
|
||||
struct lsm_params_info *p_info)
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct lsm_priv *prtd = runtime->private_data;
|
||||
@@ -673,13 +675,13 @@ static int msm_lsm_dereg_model(struct snd_pcm_substream *substream,
|
||||
"%s: Failed to set det_mode param, err = %d\n",
|
||||
__func__, rc);
|
||||
|
||||
q6lsm_snd_model_buf_free(prtd->lsm_client);
|
||||
q6lsm_snd_model_buf_free(prtd->lsm_client, p_info);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_lsm_set_custom(struct snd_pcm_substream *substream,
|
||||
struct lsm_params_info *p_info)
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct lsm_priv *prtd = runtime->private_data;
|
||||
@@ -712,8 +714,96 @@ err_ret:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_lsm_check_and_set_lab_controls(struct snd_pcm_substream *substream,
|
||||
u32 enable, struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct lsm_priv *prtd = runtime->private_data;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct lsm_hw_params *out_hw_params = &prtd->lsm_client->out_hw_params;
|
||||
u8 chmap[out_hw_params->num_chs];
|
||||
u32 ch_idx;
|
||||
int rc = 0, stage_idx = p_info->stage_idx;
|
||||
|
||||
if (prtd->lsm_client->stage_cfg[stage_idx].lab_enable == enable) {
|
||||
dev_dbg(rtd->dev, "%s: Lab for session %d, stage %d already %s\n",
|
||||
__func__, prtd->lsm_client->session,
|
||||
stage_idx, enable ? "enabled" : "disabled");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = q6lsm_lab_control(prtd->lsm_client, enable, p_info);
|
||||
if (rc) {
|
||||
dev_err(rtd->dev, "%s: Failed to set lab_control param, err = %d\n",
|
||||
__func__, rc);
|
||||
return rc;
|
||||
} else {
|
||||
if (LSM_IS_LAST_STAGE(prtd->lsm_client, stage_idx)) {
|
||||
rc = msm_lsm_lab_buffer_alloc(prtd,
|
||||
enable ? LAB_BUFFER_ALLOC : LAB_BUFFER_DEALLOC);
|
||||
if (rc) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: msm_lsm_lab_buffer_alloc failed rc %d for %s\n",
|
||||
__func__, rc, enable ? "ALLOC" : "DEALLOC");
|
||||
return rc;
|
||||
} else {
|
||||
/* set client level flag based on last stage control */
|
||||
prtd->lsm_client->lab_enable = enable;
|
||||
}
|
||||
}
|
||||
if (!rc)
|
||||
prtd->lsm_client->stage_cfg[stage_idx].lab_enable = enable;
|
||||
}
|
||||
|
||||
memset(chmap, 0, out_hw_params->num_chs);
|
||||
/*
|
||||
* First channel to be read from lab is always the
|
||||
* best channel (0xff). For second channel onwards,
|
||||
* the channel indices are 0, 1, .. etc
|
||||
*/
|
||||
chmap[0] = 0xFF;
|
||||
for (ch_idx = 1; ch_idx < out_hw_params->num_chs; ch_idx++)
|
||||
chmap[ch_idx] = ch_idx - 1;
|
||||
|
||||
rc = q6lsm_lab_out_ch_cfg(prtd->lsm_client, chmap, p_info);
|
||||
if (rc)
|
||||
dev_err(rtd->dev, "%s: Failed to set lab out ch cfg %d\n",
|
||||
__func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_lsm_set_lab_control(struct snd_pcm_substream *substream,
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct lsm_priv *prtd = runtime->private_data;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_lsm_lab_control lab_ctrl;
|
||||
int rc = 0;
|
||||
|
||||
if (p_info->param_size != sizeof(lab_ctrl))
|
||||
return -EINVAL;
|
||||
|
||||
if (prtd->lsm_client->started) {
|
||||
dev_err(rtd->dev, "%s: lab control sent after start\n", __func__);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (copy_from_user(&lab_ctrl, p_info->param_data,
|
||||
p_info->param_size)) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: copy_from_user failed for lab_control params, size = %d\n",
|
||||
__func__, p_info->param_size);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
rc = msm_lsm_check_and_set_lab_controls(substream, lab_ctrl.enable, p_info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_lsm_set_poll_enable(struct snd_pcm_substream *substream,
|
||||
struct lsm_params_info *p_info)
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct lsm_priv *prtd = runtime->private_data;
|
||||
@@ -761,7 +851,7 @@ done:
|
||||
}
|
||||
|
||||
static int msm_lsm_set_det_event_type(struct snd_pcm_substream *substream,
|
||||
struct lsm_params_info *p_info)
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct snd_lsm_det_event_type det_event_type;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
@@ -801,22 +891,26 @@ done:
|
||||
}
|
||||
|
||||
static int msm_lsm_process_params(struct snd_pcm_substream *substream,
|
||||
struct snd_lsm_module_params *p_data,
|
||||
void *params)
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct lsm_priv *prtd = runtime->private_data;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct lsm_params_info *p_info;
|
||||
int i;
|
||||
int rc = 0;
|
||||
|
||||
p_info = (struct lsm_params_info *) params;
|
||||
|
||||
for (i = 0; i < p_data->num_params; i++) {
|
||||
dev_dbg(rtd->dev,
|
||||
"%s: param (%d), module_id = 0x%x, param_id = 0x%x, param_size = 0x%x, param_type = 0x%x\n",
|
||||
__func__, i, p_info->module_id,
|
||||
p_info->param_id, p_info->param_size,
|
||||
p_info->param_type);
|
||||
"%s: mid=0x%x, pid=0x%x, iid=0x%x, stage_idx=%d, size=0x%x, type=%d\n",
|
||||
__func__, p_info->module_id, p_info->param_id, p_info->instance_id,
|
||||
p_info->stage_idx, p_info->param_size, p_info->param_type);
|
||||
|
||||
if (!prtd->lsm_client ||
|
||||
prtd->lsm_client->num_stages <= p_info->stage_idx) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: invalid stage_idx(%d) for client(%p) having num_stages(%d)\n",
|
||||
__func__, p_info->stage_idx, prtd->lsm_client,
|
||||
prtd->lsm_client ? prtd->lsm_client->num_stages : 0);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (p_info->param_type) {
|
||||
case LSM_ENDPOINT_DETECT_THRESHOLD:
|
||||
@@ -846,6 +940,9 @@ static int msm_lsm_process_params(struct snd_pcm_substream *substream,
|
||||
case LSM_DET_EVENT_TYPE:
|
||||
rc = msm_lsm_set_det_event_type(substream, p_info);
|
||||
break;
|
||||
case LSM_LAB_CONTROL:
|
||||
rc = msm_lsm_set_lab_control(substream, p_info);
|
||||
break;
|
||||
default:
|
||||
dev_err(rtd->dev,
|
||||
"%s: Invalid param_type %d\n",
|
||||
@@ -856,10 +953,6 @@ static int msm_lsm_process_params(struct snd_pcm_substream *substream,
|
||||
if (rc) {
|
||||
pr_err("%s: set_param fail for param_type %d\n",
|
||||
__func__, p_info->param_type);
|
||||
return rc;
|
||||
}
|
||||
|
||||
p_info++;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -897,12 +990,14 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
|
||||
int ret;
|
||||
struct snd_lsm_sound_model_v2 snd_model_v2;
|
||||
struct snd_lsm_session_data session_data;
|
||||
int rc = 0;
|
||||
struct snd_lsm_session_data_v2 ses_data_v2 = {0};
|
||||
int rc = 0, stage_idx;
|
||||
int xchg = 0;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
struct lsm_priv *prtd;
|
||||
struct snd_lsm_detection_params det_params;
|
||||
uint8_t *confidence_level = NULL;
|
||||
uint32_t max_detection_stages_supported = LSM_MAX_STAGES_PER_SESSION;
|
||||
|
||||
if (!substream || !substream->private_data) {
|
||||
pr_err("%s: Invalid %s\n", __func__,
|
||||
@@ -916,15 +1011,26 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_LSM_SET_SESSION_DATA:
|
||||
case SNDRV_LSM_SET_SESSION_DATA_V2:
|
||||
|
||||
if (cmd == SNDRV_LSM_SET_SESSION_DATA) {
|
||||
dev_dbg(rtd->dev, "%s: set session data\n", __func__);
|
||||
if (copy_from_user(&session_data, arg,
|
||||
sizeof(session_data))) {
|
||||
rc = copy_from_user(&session_data, arg, sizeof(session_data));
|
||||
if (!rc) {
|
||||
ses_data_v2.app_id = session_data.app_id;
|
||||
ses_data_v2.num_stages = 1;
|
||||
}
|
||||
} else {
|
||||
dev_dbg(rtd->dev, "%s: set session data_v2\n", __func__);
|
||||
rc = copy_from_user(&ses_data_v2, arg, sizeof(ses_data_v2));
|
||||
}
|
||||
if (rc) {
|
||||
dev_err(rtd->dev, "%s: %s: copy_from_user failed\n",
|
||||
__func__, "LSM_SET_SESSION_DATA");
|
||||
__func__, "LSM_SET_SESSION_DATA(_V2)");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (session_data.app_id != LSM_VOICE_WAKEUP_APP_ID_V2) {
|
||||
if (ses_data_v2.app_id != LSM_VOICE_WAKEUP_APP_ID_V2) {
|
||||
dev_err(rtd->dev,
|
||||
"%s:Invalid App id %d for Listen client\n",
|
||||
__func__, session_data.app_id);
|
||||
@@ -932,9 +1038,38 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
|
||||
break;
|
||||
}
|
||||
|
||||
prtd->lsm_client->app_id = session_data.app_id;
|
||||
ret = q6lsm_open(prtd->lsm_client,
|
||||
prtd->lsm_client->app_id);
|
||||
/*
|
||||
* Before validating num_stages from user argument.
|
||||
* Check ADSP support for multi-stage session,
|
||||
* and reset max_detection_stages_supported to "1" if required.
|
||||
*/
|
||||
if (!q6lsm_adsp_supports_multi_stage_detection()) {
|
||||
dev_dbg(rtd->dev,
|
||||
"%s: multi-stage session not supported by adsp\n", __func__);
|
||||
max_detection_stages_supported = 1;
|
||||
}
|
||||
|
||||
if (ses_data_v2.num_stages <= 0 ||
|
||||
ses_data_v2.num_stages > max_detection_stages_supported) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: Unsupported number of stages req(%d)/max(%d)\n",
|
||||
__func__, ses_data_v2.num_stages,
|
||||
max_detection_stages_supported);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
prtd->lsm_client->app_id = ses_data_v2.app_id;
|
||||
prtd->lsm_client->num_stages = ses_data_v2.num_stages;
|
||||
for (stage_idx = LSM_STAGE_INDEX_FIRST;
|
||||
stage_idx < ses_data_v2.num_stages; stage_idx++) {
|
||||
prtd->lsm_client->stage_cfg[stage_idx].app_type =
|
||||
ses_data_v2.stage_info[stage_idx].app_type;
|
||||
prtd->lsm_client->stage_cfg[stage_idx].lpi_enable =
|
||||
ses_data_v2.stage_info[stage_idx].lpi_enable;
|
||||
}
|
||||
|
||||
ret = q6lsm_open(prtd->lsm_client, ses_data_v2.app_id);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: lsm open failed, %d\n",
|
||||
@@ -942,12 +1077,24 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
|
||||
return ret;
|
||||
}
|
||||
prtd->lsm_client->opened = true;
|
||||
dev_dbg(rtd->dev, "%s: Session_ID = %d, APP ID = %d\n",
|
||||
dev_dbg(rtd->dev, "%s: Session_ID = %d, APP ID = %d, Num stages %d\n",
|
||||
__func__,
|
||||
prtd->lsm_client->session,
|
||||
prtd->lsm_client->app_id);
|
||||
prtd->lsm_client->app_id,
|
||||
prtd->lsm_client->num_stages);
|
||||
break;
|
||||
case SNDRV_LSM_REG_SND_MODEL_V2:
|
||||
case SNDRV_LSM_REG_SND_MODEL_V2: {
|
||||
/*
|
||||
* With multi-stage support sm buff allocation/free usage param info
|
||||
* to check stage index for which this sound model is being set, and
|
||||
* to check whether sm data is sent using set param command or not.
|
||||
* Hence, set param ids to '0' to indicate allocation is for legacy
|
||||
* reg_sm cmd, where buffer for param header need not be allocated,
|
||||
* also set stage index to LSM_STAGE_INDEX_FIRST.
|
||||
*/
|
||||
struct lsm_params_info_v2 p_info = {0};
|
||||
p_info.stage_idx = LSM_STAGE_INDEX_FIRST;
|
||||
|
||||
dev_dbg(rtd->dev, "%s: Registering sound model V2\n",
|
||||
__func__);
|
||||
memcpy(&snd_model_v2, arg,
|
||||
@@ -962,20 +1109,21 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
|
||||
break;
|
||||
}
|
||||
rc = q6lsm_snd_model_buf_alloc(prtd->lsm_client,
|
||||
snd_model_v2.data_size, false);
|
||||
snd_model_v2.data_size, &p_info);
|
||||
if (rc) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: q6lsm buffer alloc failed V2, size %d\n",
|
||||
__func__, snd_model_v2.data_size);
|
||||
break;
|
||||
}
|
||||
if (copy_from_user(prtd->lsm_client->sound_model.data,
|
||||
if (copy_from_user(
|
||||
prtd->lsm_client->stage_cfg[stage_idx].sound_model.data,
|
||||
snd_model_v2.data, snd_model_v2.data_size)) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: copy from user data failed\n"
|
||||
"data %pK size %d\n", __func__,
|
||||
snd_model_v2.data, snd_model_v2.data_size);
|
||||
q6lsm_snd_model_buf_free(prtd->lsm_client);
|
||||
q6lsm_snd_model_buf_free(prtd->lsm_client, &p_info);
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
@@ -1004,13 +1152,13 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
|
||||
"%s: Register snd Model v2 failed =%d\n",
|
||||
__func__, rc);
|
||||
kfree(confidence_level);
|
||||
q6lsm_snd_model_buf_free(prtd->lsm_client);
|
||||
q6lsm_snd_model_buf_free(prtd->lsm_client, &p_info);
|
||||
}
|
||||
|
||||
kfree(prtd->lsm_client->confidence_levels);
|
||||
prtd->lsm_client->confidence_levels = NULL;
|
||||
break;
|
||||
|
||||
}
|
||||
case SNDRV_LSM_SET_PARAMS:
|
||||
dev_dbg(rtd->dev, "%s: set_params\n", __func__);
|
||||
memcpy(&det_params, arg,
|
||||
@@ -1260,10 +1408,14 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
|
||||
break;
|
||||
}
|
||||
case SNDRV_LSM_LAB_CONTROL: {
|
||||
struct lsm_hw_params *out_hw_params =
|
||||
&prtd->lsm_client->out_hw_params;
|
||||
u8 chmap[out_hw_params->num_chs];
|
||||
u32 enable, ch_idx;
|
||||
u32 enable = 0;
|
||||
struct lsm_params_info_v2 p_info = {0};
|
||||
|
||||
if (prtd->lsm_client->num_stages > 1) {
|
||||
dev_err(rtd->dev, "%s: %s: not supported for multi stage session\n",
|
||||
__func__, "LSM_LAB_CONTROL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (copy_from_user(&enable, arg, sizeof(enable))) {
|
||||
dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n",
|
||||
@@ -1281,53 +1433,19 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
|
||||
break;
|
||||
}
|
||||
|
||||
if (prtd->lsm_client->lab_enable == enable) {
|
||||
dev_dbg(rtd->dev,
|
||||
"%s: Lab for session %d already %s\n",
|
||||
__func__, prtd->lsm_client->session,
|
||||
enable ? "enabled" : "disabled");
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = q6lsm_lab_control(prtd->lsm_client, enable);
|
||||
if (rc) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: ioctl %s failed rc %d to %s lab for session %d\n",
|
||||
__func__, "SNDRV_LAB_CONTROL", rc,
|
||||
enable ? "enable" : "disable",
|
||||
prtd->lsm_client->session);
|
||||
break;
|
||||
}
|
||||
|
||||
rc = msm_lsm_lab_buffer_alloc(prtd,
|
||||
enable ? LAB_BUFFER_ALLOC
|
||||
: LAB_BUFFER_DEALLOC);
|
||||
if (rc) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: msm_lsm_lab_buffer_alloc failed rc %d for %s",
|
||||
__func__, rc,
|
||||
enable ? "ALLOC" : "DEALLOC");
|
||||
break;
|
||||
}
|
||||
|
||||
prtd->lsm_client->lab_enable = enable;
|
||||
memset(chmap, 0, out_hw_params->num_chs);
|
||||
/*
|
||||
* First channel to be read from lab is always the
|
||||
* best channel (0xff). For second channel onwards,
|
||||
* the channel indices are 0, 1, .. etc
|
||||
* With multi-stage support lab control needs to set param info
|
||||
* specifying stage index for which this lab control is issued,
|
||||
* along with values of module/instance ids applicable for the stage.
|
||||
* Hence, set param info with default lab module/instance ids, and
|
||||
* set stage index to LSM_STAGE_INDEX_FIRST.
|
||||
*/
|
||||
chmap[0] = 0xFF;
|
||||
for (ch_idx = 1; ch_idx < out_hw_params->num_chs; ch_idx++)
|
||||
chmap[ch_idx] = ch_idx - 1;
|
||||
|
||||
rc = q6lsm_lab_out_ch_cfg(prtd->lsm_client, chmap);
|
||||
if (rc)
|
||||
dev_err(rtd->dev,
|
||||
"%s: Failed to set lab out ch cfg %d\n",
|
||||
__func__, rc);
|
||||
|
||||
p_info.param_type = LSM_LAB_CONTROL;
|
||||
p_info.module_id = LSM_MODULE_ID_LAB;
|
||||
p_info.instance_id = INSTANCE_ID_0;
|
||||
p_info.stage_idx = LSM_STAGE_INDEX_FIRST;
|
||||
p_info.param_size = 0;
|
||||
rc = msm_lsm_check_and_set_lab_controls(substream, enable, &p_info);
|
||||
break;
|
||||
}
|
||||
case SNDRV_LSM_STOP_LAB:
|
||||
@@ -1476,6 +1594,16 @@ struct lsm_params_info_32 {
|
||||
uint32_t param_type;
|
||||
};
|
||||
|
||||
struct lsm_params_info_v2_32 {
|
||||
u32 module_id;
|
||||
u32 param_id;
|
||||
u32 param_size;
|
||||
compat_uptr_t param_data;
|
||||
uint32_t param_type;
|
||||
u16 instance_id;
|
||||
u16 stage_idx;
|
||||
};
|
||||
|
||||
struct snd_lsm_module_params_32 {
|
||||
compat_uptr_t params;
|
||||
u32 num_params;
|
||||
@@ -1491,6 +1619,8 @@ enum {
|
||||
_IOW('U', 0x0B, struct snd_lsm_module_params_32),
|
||||
SNDRV_LSM_EVENT_STATUS_V3_32 =
|
||||
_IOW('U', 0x0F, struct snd_lsm_event_status_v3_32),
|
||||
SNDRV_LSM_SET_MODULE_PARAMS_V2_32 =
|
||||
_IOW('U', 0x13, struct snd_lsm_module_params_32),
|
||||
};
|
||||
|
||||
static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
||||
@@ -1760,19 +1890,20 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
||||
break;
|
||||
}
|
||||
|
||||
case SNDRV_LSM_SET_MODULE_PARAMS_32: {
|
||||
case SNDRV_LSM_SET_MODULE_PARAMS_32:
|
||||
case SNDRV_LSM_SET_MODULE_PARAMS_V2_32: {
|
||||
struct snd_lsm_module_params_32 p_data_32;
|
||||
struct snd_lsm_module_params p_data;
|
||||
u8 *params, *params32;
|
||||
size_t p_size;
|
||||
struct lsm_params_info_32 *p_info_32;
|
||||
struct lsm_params_info *p_info;
|
||||
int i;
|
||||
u8 *params32;
|
||||
size_t expected_size = 0, count;
|
||||
struct lsm_params_info_32 *p_info_32 = NULL;
|
||||
struct lsm_params_info_v2_32 *p_info_v2_32 = NULL;
|
||||
struct lsm_params_info_v2 p_info;
|
||||
|
||||
if (!prtd->lsm_client->use_topology) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: %s: not supported if not using topology\n",
|
||||
__func__, "SET_MODULE_PARAMS_32");
|
||||
__func__, "SET_MODULE_PARAMS(_V2)_32");
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
@@ -1781,7 +1912,7 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
||||
sizeof(p_data_32))) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: %s: copy_from_user failed, size = %zd\n",
|
||||
__func__, "SET_MODULE_PARAMS_32",
|
||||
__func__, "SET_MODULE_PARAMS(_V2)_32",
|
||||
sizeof(p_data_32));
|
||||
err = -EFAULT;
|
||||
goto done;
|
||||
@@ -1794,79 +1925,85 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
||||
if (p_data.num_params > LSM_PARAMS_MAX) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: %s: Invalid num_params %d\n",
|
||||
__func__, "SET_MODULE_PARAMS_32",
|
||||
__func__, "SET_MODULE_PARAMS(_V2)_32",
|
||||
p_data.num_params);
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (p_data.data_size !=
|
||||
(p_data.num_params * sizeof(struct lsm_params_info_32))) {
|
||||
expected_size = (cmd == SNDRV_LSM_SET_MODULE_PARAMS_32) ?
|
||||
p_data.num_params * sizeof(struct lsm_params_info_32) :
|
||||
p_data.num_params * sizeof(struct lsm_params_info_v2_32);
|
||||
|
||||
if (p_data.data_size != expected_size) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: %s: Invalid size %d\n",
|
||||
__func__, "SET_MODULE_PARAMS_32",
|
||||
__func__, "SET_MODULE_PARAMS(_V2)_32",
|
||||
p_data.data_size);
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
p_size = sizeof(struct lsm_params_info_32) *
|
||||
p_data.num_params;
|
||||
|
||||
params32 = kzalloc(p_size, GFP_KERNEL);
|
||||
params32 = kzalloc(p_data.data_size, GFP_KERNEL);
|
||||
if (!params32) {
|
||||
err = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
p_size = sizeof(struct lsm_params_info) * p_data.num_params;
|
||||
params = kzalloc(p_size, GFP_KERNEL);
|
||||
if (!params) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: no memory for params, size = %zd\n",
|
||||
__func__, p_size);
|
||||
kfree(params32);
|
||||
err = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (copy_from_user(params32, p_data.params,
|
||||
p_data.data_size)) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: %s: copy_from_user failed, size = %d\n",
|
||||
__func__, "params32", p_data.data_size);
|
||||
kfree(params32);
|
||||
kfree(params);
|
||||
err = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (cmd == SNDRV_LSM_SET_MODULE_PARAMS_32)
|
||||
p_info_32 = (struct lsm_params_info_32 *) params32;
|
||||
p_info = (struct lsm_params_info *) params;
|
||||
for (i = 0; i < p_data.num_params; i++) {
|
||||
p_info->module_id = p_info_32->module_id;
|
||||
p_info->param_id = p_info_32->param_id;
|
||||
p_info->param_size = p_info_32->param_size;
|
||||
p_info->param_data = compat_ptr(p_info_32->param_data);
|
||||
p_info->param_type = p_info_32->param_type;
|
||||
else
|
||||
p_info_v2_32 = (struct lsm_params_info_v2_32 *) params32;
|
||||
|
||||
for (count = 0; count < p_data.num_params; count++) {
|
||||
if (cmd == SNDRV_LSM_SET_MODULE_PARAMS_32) {
|
||||
p_info.module_id = p_info_32->module_id;
|
||||
p_info.param_id = p_info_32->param_id;
|
||||
p_info.param_size = p_info_32->param_size;
|
||||
p_info.param_data = compat_ptr(p_info_32->param_data);
|
||||
p_info.param_type = p_info_32->param_type;
|
||||
|
||||
p_info.instance_id = INSTANCE_ID_0;
|
||||
p_info.stage_idx = LSM_STAGE_INDEX_FIRST;
|
||||
|
||||
p_info_32++;
|
||||
p_info++;
|
||||
} else {
|
||||
p_info.module_id = p_info_v2_32->module_id;
|
||||
p_info.param_id = p_info_v2_32->param_id;
|
||||
p_info.param_size = p_info_v2_32->param_size;
|
||||
p_info.param_data = compat_ptr(p_info_v2_32->param_data);
|
||||
p_info.param_type = p_info_v2_32->param_type;
|
||||
|
||||
p_info.instance_id = p_info_v2_32->instance_id;
|
||||
p_info.stage_idx = p_info_v2_32->stage_idx;
|
||||
|
||||
p_info_v2_32++;
|
||||
}
|
||||
|
||||
err = msm_lsm_process_params(substream,
|
||||
&p_data, params);
|
||||
err = msm_lsm_process_params(substream, &p_info);
|
||||
if (err)
|
||||
dev_err(rtd->dev,
|
||||
"%s: Failed to process params, err = %d\n",
|
||||
__func__, err);
|
||||
kfree(params);
|
||||
"%s: Failed to process param, type%d stage=%d err=%d\n",
|
||||
__func__, p_info.param_type, p_info.stage_idx, err);
|
||||
}
|
||||
|
||||
kfree(params32);
|
||||
break;
|
||||
}
|
||||
case SNDRV_LSM_REG_SND_MODEL_V2:
|
||||
case SNDRV_LSM_SET_PARAMS:
|
||||
case SNDRV_LSM_SET_MODULE_PARAMS:
|
||||
case SNDRV_LSM_SET_MODULE_PARAMS_V2:
|
||||
/*
|
||||
* In ideal cases, the compat_ioctl should never be called
|
||||
* with the above unlocked ioctl commands. Print error
|
||||
@@ -1970,15 +2107,19 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
||||
goto done;
|
||||
}
|
||||
|
||||
case SNDRV_LSM_SET_MODULE_PARAMS: {
|
||||
case SNDRV_LSM_SET_MODULE_PARAMS:
|
||||
case SNDRV_LSM_SET_MODULE_PARAMS_V2: {
|
||||
struct snd_lsm_module_params p_data;
|
||||
size_t p_size;
|
||||
struct lsm_params_info *temp_ptr_info = NULL;
|
||||
struct lsm_params_info_v2 info_v2;
|
||||
struct lsm_params_info_v2 *ptr_info_v2 = NULL, *temp_ptr_info_v2 = NULL;
|
||||
size_t p_size = 0, count;
|
||||
u8 *params;
|
||||
|
||||
if (!prtd->lsm_client->use_topology) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: %s: not supported if not using topology\n",
|
||||
__func__, "SET_MODULE_PARAMS");
|
||||
__func__, "SET_MODULE_PARAMS(_V2)");
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
@@ -1995,20 +2136,22 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
||||
if (p_data.num_params > LSM_PARAMS_MAX) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: %s: Invalid num_params %d\n",
|
||||
__func__, "SET_MODULE_PARAMS",
|
||||
__func__, "SET_MODULE_PARAMS(_V2)",
|
||||
p_data.num_params);
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
p_size = p_data.num_params *
|
||||
sizeof(struct lsm_params_info);
|
||||
if (cmd == SNDRV_LSM_SET_MODULE_PARAMS)
|
||||
p_size = p_data.num_params * sizeof(struct lsm_params_info);
|
||||
else
|
||||
p_size = p_data.num_params * sizeof(struct lsm_params_info_v2);
|
||||
|
||||
if (p_data.data_size != p_size) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: %s: Invalid size %zd\n",
|
||||
__func__, "SET_MODULE_PARAMS", p_size);
|
||||
|
||||
"%s: %s: Invalid data_size(%zd) against expected(%zd)\n",
|
||||
__func__, "SET_MODULE_PARAMS(_V2)",
|
||||
p_data.data_size, p_size);
|
||||
err = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
@@ -2023,17 +2166,43 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
||||
p_data.data_size)) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: %s: copy_from_user failed, size = %d\n",
|
||||
__func__, "params", p_data.data_size);
|
||||
__func__, "set module params", p_data.data_size);
|
||||
kfree(params);
|
||||
err = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
err = msm_lsm_process_params(substream, &p_data, params);
|
||||
if (cmd == SNDRV_LSM_SET_MODULE_PARAMS)
|
||||
temp_ptr_info = (struct lsm_params_info *)params;
|
||||
else
|
||||
temp_ptr_info_v2 = (struct lsm_params_info_v2 *)params;
|
||||
|
||||
for (count = 0; count < p_data.num_params; count++) {
|
||||
if (cmd == SNDRV_LSM_SET_MODULE_PARAMS) {
|
||||
/* convert to V2 param info struct from legacy param info */
|
||||
info_v2.module_id = temp_ptr_info->module_id;
|
||||
info_v2.param_id = temp_ptr_info->param_id;
|
||||
info_v2.param_size = temp_ptr_info->param_size;
|
||||
info_v2.param_data = temp_ptr_info->param_data;
|
||||
info_v2.param_type = temp_ptr_info->param_type;
|
||||
|
||||
info_v2.instance_id = INSTANCE_ID_0;
|
||||
info_v2.stage_idx = LSM_STAGE_INDEX_FIRST;
|
||||
|
||||
ptr_info_v2 = &info_v2;
|
||||
temp_ptr_info++;
|
||||
} else {
|
||||
/* Just copy the pointer as user already provided v2 params */
|
||||
ptr_info_v2 = temp_ptr_info_v2;
|
||||
temp_ptr_info_v2++;
|
||||
}
|
||||
err = msm_lsm_process_params(substream, ptr_info_v2);
|
||||
if (err)
|
||||
dev_err(rtd->dev,
|
||||
"%s: %s: Failed to set params, err = %d\n",
|
||||
__func__, "SET_MODULE_PARAMS", err);
|
||||
"%s: Failed to process param, type%d stage=%d err=%d\n",
|
||||
__func__, ptr_info_v2->param_type,
|
||||
ptr_info_v2->stage_idx, err);
|
||||
}
|
||||
kfree(params);
|
||||
break;
|
||||
}
|
||||
|
505
dsp/q6lsm.c
505
dsp/q6lsm.c
@@ -87,7 +87,8 @@ static spinlock_t lsm_session_lock;
|
||||
static struct lsm_client *lsm_session[LSM_MAX_SESSION_ID + 1];
|
||||
|
||||
static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv);
|
||||
static int q6lsm_send_cal(struct lsm_client *client, u32 set_params_opcode);
|
||||
static int q6lsm_send_cal(struct lsm_client *client,
|
||||
u32 set_params_opcode, struct lsm_params_info_v2 *p_info);
|
||||
static int q6lsm_memory_map_regions(struct lsm_client *client,
|
||||
dma_addr_t dma_addr_p, uint32_t dma_buf_sz,
|
||||
uint32_t *mmap_p);
|
||||
@@ -166,6 +167,7 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
|
||||
case LSM_SESSION_CMD_EOB:
|
||||
case LSM_SESSION_CMD_READ:
|
||||
case LSM_SESSION_CMD_OPEN_TX_V2:
|
||||
case LSM_SESSION_CMD_OPEN_TX_V3:
|
||||
case LSM_CMD_ADD_TOPOLOGIES:
|
||||
case LSM_SESSION_CMD_SET_PARAMS_V2:
|
||||
case LSM_SESSION_CMD_SET_PARAMS_V3:
|
||||
@@ -689,6 +691,94 @@ done:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int q6lsm_get_topology_for_app_type(struct lsm_client *client,
|
||||
int app_type, uint32_t *topology)
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
struct cal_block_data *cal_block = NULL;
|
||||
struct audio_cal_info_lsm_top *lsm_top;
|
||||
struct list_head *ptr;
|
||||
|
||||
if (lsm_common.cal_data[LSM_TOP_IDX] == NULL) {
|
||||
pr_err("%s: LSM_TOP_IDX invalid\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
mutex_lock(&lsm_common.cal_data[LSM_TOP_IDX]->lock);
|
||||
list_for_each(ptr, &lsm_common.cal_data[LSM_TOP_IDX]->cal_blocks) {
|
||||
cal_block = list_entry(ptr, struct cal_block_data, list);
|
||||
if (!cal_block) {
|
||||
pr_err("%s: Cal block for LSM_TOP_IDX not found\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
|
||||
lsm_top = (struct audio_cal_info_lsm_top *) cal_block->cal_info;
|
||||
if (!lsm_top) {
|
||||
pr_err("%s: cal_info for LSM_TOP_IDX not found\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
|
||||
pr_debug("%s: checking topology 0x%x, app_type 0x%x\n",
|
||||
__func__, lsm_top->topology, lsm_top->app_type);
|
||||
|
||||
if (app_type == 0 || lsm_top->app_type == app_type) {
|
||||
*topology = lsm_top->topology;
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&lsm_common.cal_data[LSM_TOP_IDX]->lock);
|
||||
|
||||
pr_debug("%s: found topology_id = 0x%x, app_type = 0x%x\n",
|
||||
__func__, *topology, app_type);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int q6lsm_do_open_v3(struct lsm_client *client)
|
||||
{
|
||||
int rc, app_type;
|
||||
struct lsm_stream_cmd_open_tx_v3 *open_v3;
|
||||
size_t cmd_size = 0, stage_idx = LSM_STAGE_INDEX_FIRST;
|
||||
uint32_t topology_id = 0, *uint32_ptr = NULL;
|
||||
|
||||
cmd_size = sizeof(struct lsm_stream_cmd_open_tx_v3);
|
||||
cmd_size += client->num_stages * sizeof(struct lsm_stream_stage_info);
|
||||
open_v3 = kzalloc(cmd_size, GFP_KERNEL);
|
||||
if (!open_v3)
|
||||
return -ENOMEM;
|
||||
|
||||
q6lsm_add_hdr(client, &open_v3->hdr, cmd_size, true);
|
||||
open_v3->hdr.opcode = LSM_SESSION_CMD_OPEN_TX_V3;
|
||||
open_v3->num_stages = client->num_stages;
|
||||
uint32_ptr = &open_v3->num_stages;
|
||||
uint32_ptr++;
|
||||
|
||||
for (; stage_idx < client->num_stages; stage_idx++) {
|
||||
app_type = client->stage_cfg[stage_idx].app_type;
|
||||
rc = q6lsm_get_topology_for_app_type(client, app_type, &topology_id);
|
||||
if (rc) {
|
||||
pr_err("%s: failed to get topology for stage %d\n",
|
||||
__func__, stage_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
*uint32_ptr++ = topology_id;
|
||||
*uint32_ptr++ = client->stage_cfg[stage_idx].lpi_enable;
|
||||
}
|
||||
|
||||
rc = q6lsm_apr_send_pkt(client, client->apr, open_v3, true, NULL);
|
||||
if (rc)
|
||||
pr_err("%s: open_v3 failed, err = %d\n", __func__, rc);
|
||||
else
|
||||
client->use_topology = true;
|
||||
|
||||
kfree(open_v3);
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
static int q6lsm_do_open_v2(struct lsm_client *client,
|
||||
uint16_t app_id)
|
||||
{
|
||||
@@ -722,9 +812,8 @@ static int q6lsm_do_open_v2(struct lsm_client *client,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
pr_debug("%s: topology_id = 0x%x, acdb_id = 0x%x, app_type = 0x%x\n",
|
||||
__func__, lsm_top->topology, lsm_top->acdb_id,
|
||||
lsm_top->app_type);
|
||||
pr_debug("%s: topology_id = 0x%x, app_type = 0x%x\n",
|
||||
__func__, lsm_top->topology, lsm_top->app_type);
|
||||
|
||||
if (lsm_top->topology == 0) {
|
||||
pr_err("%s: toplogy id not sent for app_type 0x%x\n",
|
||||
@@ -764,26 +853,41 @@ done:
|
||||
*
|
||||
*/
|
||||
void q6lsm_sm_set_param_data(struct lsm_client *client,
|
||||
struct lsm_params_info *p_info,
|
||||
struct lsm_params_info_v2 *p_info,
|
||||
size_t *offset)
|
||||
{
|
||||
struct param_hdr_v3 param_hdr;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
struct lsm_sound_model *sm;
|
||||
|
||||
sm = &client->stage_cfg[p_info->stage_idx].sound_model;
|
||||
memset(¶m_hdr, 0, sizeof(param_hdr));
|
||||
|
||||
param_hdr.module_id = p_info->module_id;
|
||||
param_hdr.instance_id = INSTANCE_ID_0;
|
||||
param_hdr.instance_id = p_info->instance_id;
|
||||
param_hdr.param_id = p_info->param_id;
|
||||
param_hdr.param_size = client->sound_model.size;
|
||||
param_hdr.param_size = sm->size;
|
||||
|
||||
ret = q6lsm_pack_params(client->sound_model.data, ¶m_hdr,
|
||||
ret = q6lsm_pack_params(sm->data, ¶m_hdr,
|
||||
NULL, offset, LSM_SESSION_CMD_SET_PARAMS_V2);
|
||||
if (ret)
|
||||
pr_err("%s: Failed to pack params, error %d\n", __func__, ret);
|
||||
}
|
||||
EXPORT_SYMBOL(q6lsm_sm_set_param_data);
|
||||
|
||||
/**
|
||||
* q6lsm_support_multi_stage_detection -
|
||||
* check for multi-stage support in adsp lsm framework service
|
||||
*
|
||||
* Returns true if multi-stage support available, else false
|
||||
*/
|
||||
bool q6lsm_adsp_supports_multi_stage_detection(void)
|
||||
{
|
||||
return q6core_get_avcs_api_version_per_service(
|
||||
APRV2_IDS_SERVICE_ID_ADSP_LSM_V) >= LSM_API_VERSION_V3;
|
||||
}
|
||||
EXPORT_SYMBOL(q6lsm_adsp_supports_multi_stage_detection);
|
||||
|
||||
/**
|
||||
* q6lsm_open -
|
||||
* command to open LSM session
|
||||
@@ -807,9 +911,13 @@ int q6lsm_open(struct lsm_client *client, uint16_t app_id)
|
||||
}
|
||||
|
||||
/* Try to open with topology first */
|
||||
if ((client->stage_cfg[LSM_STAGE_INDEX_FIRST].app_type != 0) &&
|
||||
q6lsm_adsp_supports_multi_stage_detection())
|
||||
rc = q6lsm_do_open_v3(client);
|
||||
else
|
||||
rc = q6lsm_do_open_v2(client, app_id);
|
||||
if (!rc)
|
||||
/* open_v2 was successful */
|
||||
/* open_v2/v3 was successful */
|
||||
goto done;
|
||||
|
||||
pr_debug("%s: try without topology\n",
|
||||
@@ -1183,6 +1291,7 @@ int q6lsm_set_data(struct lsm_client *client,
|
||||
{
|
||||
struct param_hdr_v3 param_hdr;
|
||||
int rc = 0;
|
||||
struct lsm_params_info_v2 p_info = {0};
|
||||
|
||||
memset(¶m_hdr, 0, sizeof(param_hdr));
|
||||
|
||||
@@ -1228,7 +1337,8 @@ int q6lsm_set_data(struct lsm_client *client,
|
||||
goto err_ret;
|
||||
}
|
||||
|
||||
rc = q6lsm_send_cal(client, LSM_SESSION_CMD_SET_PARAMS);
|
||||
p_info.stage_idx = LSM_STAGE_INDEX_FIRST;
|
||||
rc = q6lsm_send_cal(client, LSM_SESSION_CMD_SET_PARAMS, &p_info);
|
||||
if (rc) {
|
||||
pr_err("%s: Failed to send calibration data %d\n",
|
||||
__func__, rc);
|
||||
@@ -1254,6 +1364,7 @@ int q6lsm_register_sound_model(struct lsm_client *client,
|
||||
{
|
||||
int rc;
|
||||
struct lsm_cmd_reg_snd_model cmd;
|
||||
struct lsm_sound_model *sm;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
rc = q6lsm_set_data(client, mode, detectfailure);
|
||||
@@ -1263,18 +1374,19 @@ int q6lsm_register_sound_model(struct lsm_client *client,
|
||||
return rc;
|
||||
}
|
||||
|
||||
sm = &client->stage_cfg[LSM_STAGE_INDEX_FIRST].sound_model;
|
||||
|
||||
q6lsm_add_hdr(client, &cmd.hdr, sizeof(cmd), true);
|
||||
cmd.hdr.opcode = LSM_SESSION_CMD_REGISTER_SOUND_MODEL;
|
||||
cmd.model_addr_lsw = lower_32_bits(client->sound_model.phys);
|
||||
cmd.model_addr_msw = msm_audio_populate_upper_32_bits(
|
||||
client->sound_model.phys);
|
||||
cmd.model_size = client->sound_model.size;
|
||||
cmd.model_addr_lsw = lower_32_bits(sm->phys);
|
||||
cmd.model_addr_msw = msm_audio_populate_upper_32_bits(sm->phys);
|
||||
cmd.model_size = sm->size;
|
||||
/* read updated mem_map_handle by q6lsm_mmapcallback */
|
||||
rmb();
|
||||
cmd.mem_map_handle = client->sound_model.mem_map_handle;
|
||||
cmd.mem_map_handle = sm->mem_map_handle;
|
||||
|
||||
pr_debug("%s: addr %pK, size %d, handle 0x%x\n", __func__,
|
||||
&client->sound_model.phys, cmd.model_size, cmd.mem_map_handle);
|
||||
&sm->phys, cmd.model_size, cmd.mem_map_handle);
|
||||
rc = q6lsm_apr_send_pkt(client, client->apr, &cmd, true, NULL);
|
||||
if (rc)
|
||||
pr_err("%s: Failed cmd op[0x%x]rc[%d]\n", __func__,
|
||||
@@ -1298,6 +1410,16 @@ int q6lsm_deregister_sound_model(struct lsm_client *client)
|
||||
{
|
||||
int rc;
|
||||
struct lsm_cmd_reg_snd_model cmd;
|
||||
/*
|
||||
* With multi-stage support sm buff allocation/free usage param info
|
||||
* to check stage index for which this sound model is being set, and
|
||||
* to check whether sm data is sent using set param command or not.
|
||||
* Hence, set param ids to '0' to indicate allocation is for legacy
|
||||
* reg_sm cmd, where buffer for param header need not be allocated,
|
||||
* also set stage index to LSM_STAGE_INDEX_FIRST.
|
||||
*/
|
||||
struct lsm_params_info_v2 p_info = {0};
|
||||
p_info.stage_idx = LSM_STAGE_INDEX_FIRST;
|
||||
|
||||
if (!client) {
|
||||
pr_err("APR handle NULL\n");
|
||||
@@ -1325,7 +1447,7 @@ int q6lsm_deregister_sound_model(struct lsm_client *client)
|
||||
pr_debug("%s: Deregister sound model succeeded\n", __func__);
|
||||
}
|
||||
|
||||
q6lsm_snd_model_buf_free(client);
|
||||
q6lsm_snd_model_buf_free(client, &p_info);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -1425,11 +1547,11 @@ static int q6lsm_memory_unmap_regions(struct lsm_client *client,
|
||||
}
|
||||
|
||||
static int q6lsm_send_cal(struct lsm_client *client,
|
||||
u32 set_params_opcode)
|
||||
u32 set_params_opcode, struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc = 0, stage_idx = p_info->stage_idx;
|
||||
struct mem_mapping_hdr mem_hdr;
|
||||
struct cal_block_data *cal_block = NULL;
|
||||
dma_addr_t lsm_cal_phy_addr;
|
||||
|
||||
memset(&mem_hdr, 0, sizeof(mem_hdr));
|
||||
|
||||
@@ -1439,40 +1561,132 @@ static int q6lsm_send_cal(struct lsm_client *client,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (lsm_common.cal_data[LSM_CAL_IDX] == NULL)
|
||||
goto done;
|
||||
|
||||
mutex_lock(&lsm_common.cal_data[LSM_CAL_IDX]->lock);
|
||||
cal_block = cal_utils_get_only_cal_block(
|
||||
lsm_common.cal_data[LSM_CAL_IDX]);
|
||||
|
||||
if (!cal_block || cal_block->cal_data.size <= 0) {
|
||||
pr_debug("%s: No cal to send!\n", __func__);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (cal_block->cal_data.size != client->lsm_cal_size) {
|
||||
pr_err("%s: Cal size %zd doesn't match lsm cal size %d\n",
|
||||
__func__, cal_block->cal_data.size,
|
||||
client->lsm_cal_size);
|
||||
rc = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
/* Cache mmap address, only map once or if new addr */
|
||||
lsm_cal_phy_addr = client->stage_cfg[stage_idx].cal_info.phys;
|
||||
if (lsm_cal_phy_addr != 0) {
|
||||
lsm_common.common_client[client->session].session = client->session;
|
||||
mem_hdr.data_payload_addr_lsw = lower_32_bits(client->lsm_cal_phy_addr);
|
||||
mem_hdr.data_payload_addr_lsw = lower_32_bits(lsm_cal_phy_addr);
|
||||
mem_hdr.data_payload_addr_msw =
|
||||
msm_audio_populate_upper_32_bits(client->lsm_cal_phy_addr);
|
||||
mem_hdr.mem_map_handle = client->sound_model.mem_map_handle;
|
||||
msm_audio_populate_upper_32_bits(lsm_cal_phy_addr);
|
||||
mem_hdr.mem_map_handle =
|
||||
client->stage_cfg[stage_idx].cal_info.mem_map_handle;
|
||||
|
||||
pr_debug("%s: Cal Size = %zd", __func__, cal_block->cal_data.size);
|
||||
rc = q6lsm_set_params(client, &mem_hdr, NULL, cal_block->cal_data.size,
|
||||
set_params_opcode);
|
||||
rc = q6lsm_set_params(client, &mem_hdr, NULL,
|
||||
client->stage_cfg[stage_idx].cal_info.size, set_params_opcode);
|
||||
if (rc)
|
||||
pr_err("%s: Failed set_params, rc %d\n", __func__, rc);
|
||||
unlock:
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int q6lsm_snd_cal_free(struct lsm_client *client,
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
int rc = 0, stage_idx = p_info->stage_idx;
|
||||
struct lsm_cal_data_info *cal = NULL;
|
||||
|
||||
if (!client->stage_cfg[stage_idx].cal_info.data)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&client->cmd_lock);
|
||||
cal = &client->stage_cfg[stage_idx].cal_info;
|
||||
if (cal->mem_map_handle != 0) {
|
||||
rc = q6lsm_memory_unmap_regions(client, cal->mem_map_handle);
|
||||
if (rc)
|
||||
pr_err("%s: CMD Memory_unmap_regions failed %d\n",
|
||||
__func__, rc);
|
||||
cal->mem_map_handle = 0;
|
||||
}
|
||||
msm_audio_ion_free(cal->dma_buf);
|
||||
cal->dma_buf = NULL;
|
||||
cal->data = NULL;
|
||||
cal->phys = 0;
|
||||
mutex_unlock(&client->cmd_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int q6lsm_snd_cal_alloc(struct lsm_client *client,
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
int rc = 0;
|
||||
size_t len = 0, total_mem = 0;
|
||||
struct lsm_cal_data_info *cal = NULL;
|
||||
struct cal_block_data *cal_block = NULL;
|
||||
struct audio_cal_info_lsm *lsm_cal_info = NULL;
|
||||
struct list_head *ptr = NULL;
|
||||
int app_type, stage_idx = p_info->stage_idx;
|
||||
bool cal_block_found = false;
|
||||
|
||||
app_type = client->stage_cfg[stage_idx].app_type;
|
||||
pr_debug("%s: app_type %d, stage_idx %d\n",
|
||||
__func__, app_type, stage_idx);
|
||||
|
||||
mutex_lock(&client->cmd_lock);
|
||||
mutex_lock(&lsm_common.cal_data[LSM_CAL_IDX]->lock);
|
||||
list_for_each(ptr, &lsm_common.cal_data[LSM_CAL_IDX]->cal_blocks) {
|
||||
cal_block = list_entry(ptr, struct cal_block_data, list);
|
||||
lsm_cal_info = (struct audio_cal_info_lsm *)
|
||||
(cal_block) ? cal_block->cal_info : NULL;
|
||||
if ((cal_block && cal_block->cal_data.paddr) &&
|
||||
(lsm_cal_info != NULL) &&
|
||||
(app_type == 0 || app_type == lsm_cal_info->app_type)) {
|
||||
cal_block_found = true;
|
||||
len = cal_block->cal_data.size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cal_block_found) {
|
||||
pr_info("%s: cal not found for stage_idx %d\n", __func__, stage_idx);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
pr_debug("%s: cal size is 0, for stage_idx %d\n", __func__, stage_idx);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
cal = &client->stage_cfg[stage_idx].cal_info;
|
||||
if (cal->data) {
|
||||
pr_debug("%s: cal data for stage_idx(%d) is already set \n",
|
||||
__func__, stage_idx);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
cal->size = len;
|
||||
total_mem = PAGE_ALIGN(len);
|
||||
pr_debug("%s: cal info data size %zd Total mem %zd, stage_idx %d\n",
|
||||
__func__, len, total_mem, stage_idx);
|
||||
|
||||
rc = msm_audio_ion_alloc(&cal->dma_buf, total_mem,
|
||||
&cal->phys, &len, &cal->data);
|
||||
if (rc) {
|
||||
pr_err("%s: Audio ION alloc is failed for stage_idx %d, rc = %d\n",
|
||||
__func__, stage_idx, rc);
|
||||
cal->dma_buf = NULL;
|
||||
cal->data = NULL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(cal->data, (uint32_t *)cal_block->cal_data.kvaddr, cal->size);
|
||||
mutex_unlock(&lsm_common.cal_data[LSM_CAL_IDX]->lock);
|
||||
done:
|
||||
mutex_unlock(&client->cmd_lock);
|
||||
rc = q6lsm_memory_map_regions(client, cal->phys, len, &cal->mem_map_handle);
|
||||
if (rc) {
|
||||
pr_err("%s: CMD Memory_map_regions failed for stage_idx %d, rc = %d\n",
|
||||
__func__, stage_idx, rc);
|
||||
cal->mem_map_handle = 0;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&client->cmd_lock);
|
||||
mutex_unlock(&lsm_common.cal_data[LSM_CAL_IDX]->lock);
|
||||
fail:
|
||||
q6lsm_snd_cal_free(client, p_info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1481,12 +1695,15 @@ done:
|
||||
* Free memory for LSM snd model
|
||||
*
|
||||
* @client: LSM client handle
|
||||
* @p_info: sound model param info
|
||||
*
|
||||
* Returns 0 on success or error on failure
|
||||
*/
|
||||
int q6lsm_snd_model_buf_free(struct lsm_client *client)
|
||||
int q6lsm_snd_model_buf_free(struct lsm_client *client,
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
int rc;
|
||||
int rc = 0, stage_idx = p_info->stage_idx;
|
||||
struct lsm_sound_model *sm = NULL;
|
||||
|
||||
pr_debug("%s: Session id %d\n", __func__, client->session);
|
||||
if (CHECK_SESSION(client->session)) {
|
||||
@@ -1494,22 +1711,25 @@ int q6lsm_snd_model_buf_free(struct lsm_client *client)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!client->stage_cfg[stage_idx].sound_model.data)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&client->cmd_lock);
|
||||
rc = q6lsm_memory_unmap_regions(client,
|
||||
client->sound_model.mem_map_handle);
|
||||
sm = &client->stage_cfg[stage_idx].sound_model;
|
||||
if (sm->mem_map_handle != 0) {
|
||||
rc = q6lsm_memory_unmap_regions(client, sm->mem_map_handle);
|
||||
if (rc)
|
||||
pr_err("%s: CMD Memory_unmap_regions failed %d\n",
|
||||
__func__, rc);
|
||||
|
||||
if (client->sound_model.data) {
|
||||
msm_audio_ion_free(client->sound_model.dma_buf);
|
||||
client->sound_model.dma_buf = NULL;
|
||||
client->sound_model.data = NULL;
|
||||
client->sound_model.phys = 0;
|
||||
client->lsm_cal_phy_addr = 0;
|
||||
client->lsm_cal_size = 0;
|
||||
sm->mem_map_handle = 0;
|
||||
}
|
||||
msm_audio_ion_free(sm->dma_buf);
|
||||
sm->dma_buf = NULL;
|
||||
sm->data = NULL;
|
||||
sm->phys = 0;
|
||||
mutex_unlock(&client->cmd_lock);
|
||||
|
||||
rc = q6lsm_snd_cal_free(client, p_info);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(q6lsm_snd_model_buf_free);
|
||||
@@ -1551,7 +1771,6 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
|
||||
apr_reset(lsm_common.apr);
|
||||
lsm_common.apr = NULL;
|
||||
atomic_set(&lsm_common.apr_users, 0);
|
||||
lsm_common.common_client[sid].lsm_cal_phy_addr = 0;
|
||||
cal_utils_clear_cal_block_q6maps(LSM_MAX_CAL_IDX,
|
||||
lsm_common.cal_data);
|
||||
lsm_common.set_custom_topology = 1;
|
||||
@@ -1623,109 +1842,73 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
|
||||
*
|
||||
* @client: LSM client handle
|
||||
* @len: size of sound model
|
||||
* @allocate_module_data: flag to allocate for set_param payload
|
||||
* @p_info: sound model param info
|
||||
* p_info->param_id != 0 when using set param to register sound model
|
||||
*
|
||||
* Returns 0 on success or error on failure
|
||||
*/
|
||||
int q6lsm_snd_model_buf_alloc(struct lsm_client *client, size_t len,
|
||||
bool allocate_module_data)
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
struct cal_block_data *cal_block = NULL;
|
||||
|
||||
size_t pad_zero = 0, total_mem = 0;
|
||||
int rc = -EINVAL, stage_idx = p_info->stage_idx;
|
||||
size_t total_mem = 0;
|
||||
struct lsm_sound_model *sm = NULL;
|
||||
|
||||
if (!client || len <= LSM_ALIGN_BOUNDARY)
|
||||
return rc;
|
||||
|
||||
pr_debug("%s:Snd Model len = %zd, stage idx %d\n",
|
||||
__func__, len, stage_idx);
|
||||
|
||||
mutex_lock(&client->cmd_lock);
|
||||
|
||||
mutex_lock(&lsm_common.cal_data[LSM_CAL_IDX]->lock);
|
||||
cal_block = cal_utils_get_only_cal_block(
|
||||
lsm_common.cal_data[LSM_CAL_IDX]);
|
||||
if (cal_block == NULL)
|
||||
goto fail;
|
||||
|
||||
pr_debug("%s:Snd Model len = %zd cal size %zd phys addr %pK", __func__,
|
||||
len, cal_block->cal_data.size,
|
||||
&cal_block->cal_data.paddr);
|
||||
if (!cal_block->cal_data.paddr) {
|
||||
pr_err("%s: No LSM calibration set for session", __func__);
|
||||
rc = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
if (!client->sound_model.data) {
|
||||
|
||||
sm = &client->stage_cfg[stage_idx].sound_model;
|
||||
if (!sm->data) {
|
||||
/*
|
||||
* if sound module is sent as set_param
|
||||
* If sound model is sent as set_param, i.e. param_id != 0,
|
||||
* Then memory needs to be allocated for
|
||||
* set_param payload as well.
|
||||
*/
|
||||
if (allocate_module_data)
|
||||
if (p_info->param_id != 0)
|
||||
len += sizeof(union param_hdrs);
|
||||
|
||||
client->sound_model.size = len;
|
||||
pad_zero = (LSM_ALIGN_BOUNDARY -
|
||||
(len % LSM_ALIGN_BOUNDARY));
|
||||
if ((len > SIZE_MAX - pad_zero) ||
|
||||
(len + pad_zero >
|
||||
SIZE_MAX - cal_block->cal_data.size)) {
|
||||
pr_err("%s: invalid allocation size, len = %zd, pad_zero =%zd, cal_size = %zd\n",
|
||||
__func__, len, pad_zero,
|
||||
cal_block->cal_data.size);
|
||||
rc = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
total_mem = PAGE_ALIGN(pad_zero + len +
|
||||
cal_block->cal_data.size);
|
||||
pr_debug("%s: Pad zeros sound model %zd Total mem %zd\n",
|
||||
__func__, pad_zero, total_mem);
|
||||
rc = msm_audio_ion_alloc(&client->sound_model.dma_buf,
|
||||
total_mem,
|
||||
&client->sound_model.phys,
|
||||
&len,
|
||||
&client->sound_model.data);
|
||||
sm->size = len;
|
||||
total_mem = PAGE_ALIGN(len);
|
||||
pr_debug("%s: sm param size %zd Total mem %zd, stage_idx %d\n",
|
||||
__func__, len, total_mem, stage_idx);
|
||||
rc = msm_audio_ion_alloc(&sm->dma_buf, total_mem,
|
||||
&sm->phys, &len, &sm->data);
|
||||
if (rc) {
|
||||
pr_err("%s: Audio ION alloc is failed, rc = %d\n",
|
||||
__func__, rc);
|
||||
pr_err("%s: Audio ION alloc is failed, rc = %d, stage_idx = %d\n",
|
||||
__func__, rc, stage_idx);
|
||||
goto fail;
|
||||
}
|
||||
pr_debug("%s: Length = %zd\n", __func__, len);
|
||||
client->lsm_cal_phy_addr = (pad_zero +
|
||||
client->sound_model.phys +
|
||||
client->sound_model.size);
|
||||
client->lsm_cal_size = cal_block->cal_data.size;
|
||||
memcpy((client->sound_model.data + pad_zero +
|
||||
client->sound_model.size),
|
||||
(uint32_t *)cal_block->cal_data.kvaddr, client->lsm_cal_size);
|
||||
pr_debug("%s: Copy cal start virt_addr %pK phy_addr %pK\n"
|
||||
"Offset cal virtual Addr %pK\n", __func__,
|
||||
client->sound_model.data, &client->sound_model.phys,
|
||||
(pad_zero + client->sound_model.data +
|
||||
client->sound_model.size));
|
||||
} else {
|
||||
pr_err("%s: sound model busy\n", __func__);
|
||||
pr_err("%s: sound model busy, stage_idx %d\n", __func__, stage_idx);
|
||||
rc = -EBUSY;
|
||||
goto fail;
|
||||
}
|
||||
mutex_unlock(&lsm_common.cal_data[LSM_CAL_IDX]->lock);
|
||||
mutex_unlock(&client->cmd_lock);
|
||||
|
||||
rc = q6lsm_memory_map_regions(client, client->sound_model.phys,
|
||||
len,
|
||||
&client->sound_model.mem_map_handle);
|
||||
rc = q6lsm_memory_map_regions(client, sm->phys, len, &sm->mem_map_handle);
|
||||
if (rc) {
|
||||
pr_err("%s: CMD Memory_map_regions failed %d\n", __func__, rc);
|
||||
goto exit;
|
||||
pr_err("%s: CMD Memory_map_regions failed %d, stage_idx %d\n",
|
||||
__func__, rc, stage_idx);
|
||||
sm->mem_map_handle = 0;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
mutex_unlock(&lsm_common.cal_data[LSM_CAL_IDX]->lock);
|
||||
mutex_unlock(&client->cmd_lock);
|
||||
exit:
|
||||
q6lsm_snd_model_buf_free(client);
|
||||
|
||||
rc = q6lsm_snd_cal_alloc(client, p_info);
|
||||
if (rc) {
|
||||
pr_err("%s: cal alloc failed %d, stage_idx %d\n",
|
||||
__func__, rc, stage_idx);
|
||||
goto fail_1;
|
||||
}
|
||||
return rc;
|
||||
|
||||
fail:
|
||||
mutex_unlock(&client->cmd_lock);
|
||||
fail_1:
|
||||
q6lsm_snd_model_buf_free(client, p_info);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(q6lsm_snd_model_buf_alloc);
|
||||
@@ -1811,7 +1994,7 @@ static int q6lsm_send_param_gain(struct lsm_client *client, u16 gain,
|
||||
* Returns 0 on success or error on failure
|
||||
*/
|
||||
int q6lsm_set_one_param(struct lsm_client *client,
|
||||
struct lsm_params_info *p_info, void *data,
|
||||
struct lsm_params_info_v2 *p_info, void *data,
|
||||
uint32_t param_type)
|
||||
{
|
||||
struct param_hdr_v3 param_info;
|
||||
@@ -1822,7 +2005,7 @@ int q6lsm_set_one_param(struct lsm_client *client,
|
||||
switch (param_type) {
|
||||
case LSM_ENDPOINT_DETECT_THRESHOLD: {
|
||||
param_info.module_id = p_info->module_id;
|
||||
param_info.instance_id = INSTANCE_ID_0;
|
||||
param_info.instance_id = p_info->instance_id;
|
||||
param_info.param_id = p_info->param_id;
|
||||
rc = q6lsm_send_param_epd_thres(client, data, ¶m_info);
|
||||
if (rc)
|
||||
@@ -1847,7 +2030,7 @@ int q6lsm_set_one_param(struct lsm_client *client,
|
||||
client->mode |= det_mode->detect_failure << 2;
|
||||
|
||||
param_info.module_id = p_info->module_id;
|
||||
param_info.instance_id = INSTANCE_ID_0;
|
||||
param_info.instance_id = p_info->instance_id;
|
||||
param_info.param_id = p_info->param_id;
|
||||
|
||||
rc = q6lsm_send_param_opmode(client, ¶m_info,
|
||||
@@ -1861,7 +2044,7 @@ int q6lsm_set_one_param(struct lsm_client *client,
|
||||
case LSM_GAIN: {
|
||||
struct snd_lsm_gain *lsm_gain = (struct snd_lsm_gain *) data;
|
||||
param_info.module_id = p_info->module_id;
|
||||
param_info.instance_id = INSTANCE_ID_0;
|
||||
param_info.instance_id = p_info->instance_id;
|
||||
param_info.param_id = p_info->param_id;
|
||||
rc = q6lsm_send_param_gain(client, lsm_gain->gain, ¶m_info);
|
||||
if (rc)
|
||||
@@ -1872,7 +2055,7 @@ int q6lsm_set_one_param(struct lsm_client *client,
|
||||
|
||||
case LSM_MIN_CONFIDENCE_LEVELS:
|
||||
param_info.module_id = p_info->module_id;
|
||||
param_info.instance_id = INSTANCE_ID_0;
|
||||
param_info.instance_id = p_info->instance_id;
|
||||
param_info.param_id = p_info->param_id;
|
||||
rc = q6lsm_send_confidence_levels(
|
||||
client, ¶m_info, LSM_SESSION_CMD_SET_PARAMS_V2);
|
||||
@@ -1884,7 +2067,7 @@ int q6lsm_set_one_param(struct lsm_client *client,
|
||||
struct snd_lsm_poll_enable *lsm_poll_enable =
|
||||
(struct snd_lsm_poll_enable *) data;
|
||||
param_info.module_id = p_info->module_id;
|
||||
param_info.instance_id = INSTANCE_ID_0;
|
||||
param_info.instance_id = p_info->instance_id;
|
||||
param_info.param_id = p_info->param_id;
|
||||
rc = q6lsm_send_param_polling_enable(
|
||||
client, lsm_poll_enable->poll_en, ¶m_info,
|
||||
@@ -1898,6 +2081,7 @@ int q6lsm_set_one_param(struct lsm_client *client,
|
||||
case LSM_REG_SND_MODEL: {
|
||||
struct mem_mapping_hdr mem_hdr;
|
||||
u32 payload_size;
|
||||
struct lsm_sound_model *sm = NULL;
|
||||
|
||||
memset(&mem_hdr, 0, sizeof(mem_hdr));
|
||||
|
||||
@@ -1908,12 +2092,14 @@ int q6lsm_set_one_param(struct lsm_client *client,
|
||||
payload_size = p_info->param_size +
|
||||
sizeof(struct param_hdr_v2);
|
||||
|
||||
sm = &client->stage_cfg[p_info->stage_idx].sound_model;
|
||||
|
||||
mem_hdr.data_payload_addr_lsw =
|
||||
lower_32_bits(client->sound_model.phys);
|
||||
lower_32_bits(sm->phys);
|
||||
mem_hdr.data_payload_addr_msw =
|
||||
msm_audio_populate_upper_32_bits(
|
||||
client->sound_model.phys),
|
||||
mem_hdr.mem_map_handle = client->sound_model.mem_map_handle;
|
||||
sm->phys),
|
||||
mem_hdr.mem_map_handle = sm->mem_map_handle;
|
||||
|
||||
rc = q6lsm_set_params(client, &mem_hdr, NULL, payload_size,
|
||||
LSM_SESSION_CMD_SET_PARAMS_V2);
|
||||
@@ -1923,7 +2109,7 @@ int q6lsm_set_one_param(struct lsm_client *client,
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = q6lsm_send_cal(client, LSM_SESSION_CMD_SET_PARAMS);
|
||||
rc = q6lsm_send_cal(client, LSM_SESSION_CMD_SET_PARAMS, p_info);
|
||||
if (rc)
|
||||
pr_err("%s: Failed to send lsm cal, err = %d\n",
|
||||
__func__, rc);
|
||||
@@ -1932,7 +2118,7 @@ int q6lsm_set_one_param(struct lsm_client *client,
|
||||
|
||||
case LSM_DEREG_SND_MODEL: {
|
||||
param_info.module_id = p_info->module_id;
|
||||
param_info.instance_id = INSTANCE_ID_0;
|
||||
param_info.instance_id = p_info->instance_id;
|
||||
param_info.param_id = p_info->param_id;
|
||||
param_info.param_size = 0;
|
||||
rc = q6lsm_pack_and_set_params(client, ¶m_info, NULL,
|
||||
@@ -1967,7 +2153,7 @@ int q6lsm_set_one_param(struct lsm_client *client,
|
||||
(struct snd_lsm_det_event_type *)data;
|
||||
|
||||
param_info.module_id = p_info->module_id;
|
||||
param_info.instance_id = INSTANCE_ID_0;
|
||||
param_info.instance_id = p_info->instance_id;
|
||||
param_info.param_id = p_info->param_id;
|
||||
param_info.param_size = sizeof(det_event_type);
|
||||
|
||||
@@ -2044,10 +2230,12 @@ EXPORT_SYMBOL(q6lsm_close);
|
||||
*
|
||||
* @client: LSM client handle
|
||||
* @enable: bool flag to enable or disable LAB on DSP
|
||||
* @p_info: param info to be used for sending lab control param
|
||||
*
|
||||
* Returns 0 on success or error on failure
|
||||
*/
|
||||
int q6lsm_lab_control(struct lsm_client *client, u32 enable)
|
||||
int q6lsm_lab_control(struct lsm_client *client, u32 enable,
|
||||
struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
struct lsm_param_lab_enable lab_enable;
|
||||
struct param_hdr_v3 lab_enable_hdr;
|
||||
@@ -2066,8 +2254,8 @@ int q6lsm_lab_control(struct lsm_client *client, u32 enable)
|
||||
}
|
||||
|
||||
/* enable/disable lab on dsp */
|
||||
lab_enable_hdr.module_id = LSM_MODULE_ID_LAB;
|
||||
lab_enable_hdr.instance_id = INSTANCE_ID_0;
|
||||
lab_enable_hdr.module_id = p_info->module_id;
|
||||
lab_enable_hdr.instance_id = p_info->instance_id;
|
||||
lab_enable_hdr.param_id = LSM_PARAM_ID_LAB_ENABLE;
|
||||
lab_enable_hdr.param_size = sizeof(lab_enable);
|
||||
lab_enable.enable = (enable) ? 1 : 0;
|
||||
@@ -2082,8 +2270,8 @@ int q6lsm_lab_control(struct lsm_client *client, u32 enable)
|
||||
goto exit;
|
||||
|
||||
/* lab session is being enabled set the config values */
|
||||
lab_config_hdr.module_id = LSM_MODULE_ID_LAB;
|
||||
lab_config_hdr.instance_id = INSTANCE_ID_0;
|
||||
lab_config_hdr.module_id = p_info->module_id;
|
||||
lab_config_hdr.instance_id = p_info->instance_id;
|
||||
lab_config_hdr.param_id = LSM_PARAM_ID_LAB_CONFIG;
|
||||
lab_config_hdr.param_size = sizeof(lab_config);
|
||||
lab_config.minor_version = 1;
|
||||
@@ -2114,11 +2302,12 @@ EXPORT_SYMBOL(q6lsm_lab_control);
|
||||
* @client: LSM client handle
|
||||
* @ch_map: Channel map indicating the order
|
||||
* of channels to be configured.
|
||||
* @p_info: param info to be used for sending lab config param
|
||||
*
|
||||
* Returns 0 on success or error on failure
|
||||
*/
|
||||
int q6lsm_lab_out_ch_cfg(struct lsm_client *client,
|
||||
u8 *ch_map)
|
||||
u8 *ch_map, struct lsm_params_info_v2 *p_info)
|
||||
{
|
||||
u8 *param_buf;
|
||||
struct lsm_param_lab_out_ch_cfg *lab_out_cfg;
|
||||
@@ -2144,8 +2333,8 @@ int q6lsm_lab_out_ch_cfg(struct lsm_client *client,
|
||||
lab_out_cfg->channel_indices[i] = ch_map[i];
|
||||
|
||||
memset(&lab_out_cfg_hdr, 0, sizeof(lab_out_cfg_hdr));
|
||||
lab_out_cfg_hdr.module_id = LSM_MODULE_ID_LAB;
|
||||
lab_out_cfg_hdr.instance_id = INSTANCE_ID_0;
|
||||
lab_out_cfg_hdr.module_id = p_info->module_id;
|
||||
lab_out_cfg_hdr.instance_id = p_info->instance_id;
|
||||
lab_out_cfg_hdr.param_id = LSM_PARAM_ID_LAB_OUTPUT_CHANNEL_CONFIG;
|
||||
lab_out_cfg_hdr.param_size = param_len;
|
||||
|
||||
|
@@ -9949,6 +9949,7 @@ struct avcs_fwk_ver_info {
|
||||
#define LSM_SESSION_CMD_EOB (0x00012A89)
|
||||
#define LSM_SESSION_CMD_READ (0x00012A8A)
|
||||
#define LSM_SESSION_CMD_OPEN_TX_V2 (0x00012A8B)
|
||||
#define LSM_SESSION_CMD_OPEN_TX_V3 (0x00012A95)
|
||||
#define LSM_CMD_ADD_TOPOLOGIES (0x00012A8C)
|
||||
|
||||
#define LSM_SESSION_EVENT_DETECTION_STATUS (0x00012B00)
|
||||
|
@@ -26,6 +26,8 @@
|
||||
#define LSM_MAX_NUM_CHANNELS 8
|
||||
#define LSM_V3P0_MAX_NUM_CHANNELS 9
|
||||
|
||||
#define LSM_API_VERSION_V3 3
|
||||
|
||||
typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token,
|
||||
uint32_t *payload, void *priv);
|
||||
|
||||
@@ -60,6 +62,24 @@ struct lsm_hw_params {
|
||||
u16 num_chs;
|
||||
};
|
||||
|
||||
struct lsm_cal_data_info {
|
||||
dma_addr_t phys;
|
||||
void *data;
|
||||
size_t size;
|
||||
struct dma_buf *dma_buf;
|
||||
uint32_t mem_map_handle;
|
||||
};
|
||||
|
||||
struct lsm_stage_config {
|
||||
uint32_t app_type;
|
||||
uint32_t topology_id;
|
||||
bool lpi_enable;
|
||||
bool lab_enable;
|
||||
struct lsm_sound_model sound_model;
|
||||
struct lsm_cal_data_info cal_info;
|
||||
};
|
||||
|
||||
|
||||
struct lsm_client {
|
||||
int session;
|
||||
lsm_app_cb cb;
|
||||
@@ -68,7 +88,6 @@ struct lsm_client {
|
||||
struct apr_svc *apr;
|
||||
struct apr_svc *mmap_apr;
|
||||
struct mutex cmd_lock;
|
||||
struct lsm_sound_model sound_model;
|
||||
wait_queue_head_t cmd_wait;
|
||||
uint32_t cmd_err_code;
|
||||
uint16_t mode;
|
||||
@@ -77,8 +96,6 @@ struct lsm_client {
|
||||
uint8_t *confidence_levels;
|
||||
bool opened;
|
||||
bool started;
|
||||
dma_addr_t lsm_cal_phy_addr;
|
||||
uint32_t lsm_cal_size;
|
||||
uint32_t app_id;
|
||||
bool lab_enable;
|
||||
bool lab_started;
|
||||
@@ -91,6 +108,8 @@ struct lsm_client {
|
||||
int perf_mode;
|
||||
uint32_t event_mode;
|
||||
uint32_t event_type;
|
||||
uint32_t num_stages;
|
||||
struct lsm_stage_config stage_cfg[LSM_MAX_STAGES_PER_SESSION];
|
||||
};
|
||||
|
||||
struct lsm_stream_cmd_open_tx {
|
||||
@@ -105,6 +124,17 @@ struct lsm_stream_cmd_open_tx_v2 {
|
||||
uint32_t topology_id;
|
||||
} __packed;
|
||||
|
||||
struct lsm_stream_stage_info {
|
||||
uint32_t topology_id;
|
||||
uint32_t island_enable;
|
||||
} __packed;
|
||||
|
||||
struct lsm_stream_cmd_open_tx_v3 {
|
||||
struct apr_hdr hdr;
|
||||
uint32_t num_stages;
|
||||
struct lsm_stream_stage_info stage_info[0];
|
||||
} __packed;
|
||||
|
||||
struct lsm_custom_topologies {
|
||||
struct apr_hdr hdr;
|
||||
uint32_t data_payload_addr_lsw;
|
||||
@@ -242,8 +272,9 @@ int q6lsm_open(struct lsm_client *client, uint16_t app_id);
|
||||
int q6lsm_start(struct lsm_client *client, bool wait);
|
||||
int q6lsm_stop(struct lsm_client *client, bool wait);
|
||||
int q6lsm_snd_model_buf_alloc(struct lsm_client *client, size_t len,
|
||||
bool allocate_module_data);
|
||||
int q6lsm_snd_model_buf_free(struct lsm_client *client);
|
||||
struct lsm_params_info_v2 *p_info);
|
||||
int q6lsm_snd_model_buf_free(struct lsm_client *client,
|
||||
struct lsm_params_info_v2 *p_info);
|
||||
int q6lsm_close(struct lsm_client *client);
|
||||
int q6lsm_register_sound_model(struct lsm_client *client,
|
||||
enum lsm_detection_mode mode,
|
||||
@@ -254,19 +285,22 @@ int q6lsm_set_data(struct lsm_client *client,
|
||||
int q6lsm_deregister_sound_model(struct lsm_client *client);
|
||||
void set_lsm_port(int lsm_port);
|
||||
int get_lsm_port(void);
|
||||
int q6lsm_lab_control(struct lsm_client *client, u32 enable);
|
||||
int q6lsm_lab_control(struct lsm_client *client, u32 enable,
|
||||
struct lsm_params_info_v2 *p_info);
|
||||
int q6lsm_stop_lab(struct lsm_client *client);
|
||||
int q6lsm_read(struct lsm_client *client, struct lsm_cmd_read *read);
|
||||
int q6lsm_lab_buffer_alloc(struct lsm_client *client, bool alloc);
|
||||
int q6lsm_set_one_param(struct lsm_client *client,
|
||||
struct lsm_params_info *p_info, void *data,
|
||||
struct lsm_params_info_v2 *p_info, void *data,
|
||||
uint32_t param_type);
|
||||
void q6lsm_sm_set_param_data(struct lsm_client *client,
|
||||
struct lsm_params_info *p_info,
|
||||
struct lsm_params_info_v2 *p_info,
|
||||
size_t *offset);
|
||||
int q6lsm_set_port_connected(struct lsm_client *client);
|
||||
int q6lsm_set_fwk_mode_cfg(struct lsm_client *client, uint32_t event_mode);
|
||||
int q6lsm_set_media_fmt_params(struct lsm_client *client);
|
||||
int q6lsm_set_media_fmt_v2_params(struct lsm_client *client);
|
||||
int q6lsm_lab_out_ch_cfg(struct lsm_client *client, u8 *ch_map);
|
||||
int q6lsm_lab_out_ch_cfg(struct lsm_client *client, u8 *ch_map,
|
||||
struct lsm_params_info_v2 *p_info);
|
||||
bool q6lsm_adsp_supports_multi_stage_detection(void);
|
||||
#endif /* __Q6LSM_H__ */
|
||||
|
Reference in New Issue
Block a user