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

Commit 6c188e55 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "lsm: add support for SVA multi sound model"

parents b434c07e 18ab3445
Loading
Loading
Loading
Loading
+321 −109
Original line number Diff line number Diff line
@@ -499,6 +499,34 @@ static int msm_lsm_get_conf_levels(struct lsm_client *client,
{
	int rc = 0;

	if (client->num_sound_models != 0) {
		if (client->num_keywords == 0) {
			pr_debug("%s: no number of confidence_values provided\n",
				 __func__);
			client->multi_snd_model_confidence_levels = NULL;
			goto done;
		}

		client->multi_snd_model_confidence_levels =
			kzalloc((sizeof(uint32_t) * client->num_keywords),
				 GFP_KERNEL);
		if (!client->multi_snd_model_confidence_levels) {
			pr_err("%s: No memory for confidence\n"
				"levels num of level from user = %d\n",
				__func__, client->num_keywords);
				rc = -ENOMEM;
				goto done;
		}

		if (copy_from_user((u8 *)client->multi_snd_model_confidence_levels,
				   conf_levels_ptr,
				   sizeof(uint32_t) * client->num_keywords)) {
			pr_err("%s: copy from user failed, number of keywords = %d\n",
			       __func__, client->num_keywords);
			rc = -EFAULT;
			goto copy_err;
		}
	} else {
		if (client->num_confidence_levels == 0) {
			pr_debug("%s: no confidence levels provided\n",
				 __func__);
@@ -525,12 +553,17 @@ static int msm_lsm_get_conf_levels(struct lsm_client *client,
			rc = -EFAULT;
			goto copy_err;
		}

	}
	return rc;

copy_err:
	if (client->num_sound_models != 0) {
		kfree(client->multi_snd_model_confidence_levels);
		client->multi_snd_model_confidence_levels = NULL;
	} else {
		kfree(client->confidence_levels);
		client->confidence_levels = NULL;
	}
done:
	return rc;

@@ -652,6 +685,37 @@ static int msm_lsm_set_conf(struct snd_pcm_substream *substream,
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	int rc = 0;

	if (p_info->param_type == LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS) {
		if (p_info->param_size > MAX_KEYWORDS_SUPPORTED) {
			dev_err(rtd->dev,
				"%s: invalid number of snd_model keywords %d, the max is %d\n",
				__func__, p_info->param_size, MAX_KEYWORDS_SUPPORTED);
			return -EINVAL;
		}

		prtd->lsm_client->num_keywords = p_info->param_size;
		rc = msm_lsm_get_conf_levels(prtd->lsm_client,
					     p_info->param_data);
		if (rc) {
			dev_err(rtd->dev,
				"%s: get_conf_levels failed for snd_model %d, err = %d\n",
				__func__, p_info->model_id, rc);
			return rc;
		}

		rc = q6lsm_set_one_param(prtd->lsm_client, p_info,
					 prtd->lsm_client->multi_snd_model_confidence_levels,
					 LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS);
		if (rc)
			dev_err(rtd->dev,
				"%s: Failed to set multi_snd_model_confidence_levels, err = %d\n",
				__func__, rc);

		if (prtd->lsm_client->multi_snd_model_confidence_levels) {
			kfree(prtd->lsm_client->multi_snd_model_confidence_levels);
			prtd->lsm_client->multi_snd_model_confidence_levels = NULL;
		}
	} else {
		if (p_info->param_size > MAX_NUM_CONFIDENCE) {
			dev_err(rtd->dev,
				"%s: invalid confidence levels %d\n",
@@ -682,6 +746,7 @@ static int msm_lsm_set_conf(struct snd_pcm_substream *substream,
			kfree(prtd->lsm_client->confidence_levels);
			prtd->lsm_client->confidence_levels = NULL;
		}
	}
	return rc;
}

@@ -691,27 +756,76 @@ static int msm_lsm_reg_model(struct snd_pcm_substream *substream,
	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;
	int rc = 0, stage_idx = p_info->stage_idx;
	struct lsm_sound_model *sm = NULL;
	size_t offset = sizeof(union param_hdrs);
	struct lsm_client *client = prtd->lsm_client;

	rc = q6lsm_snd_model_buf_alloc(prtd->lsm_client,
				       p_info->param_size, p_info);
	if (p_info->model_id != 0 &&
	    p_info->param_type == LSM_REG_MULTI_SND_MODEL) {
		sm = kzalloc(sizeof(*sm), GFP_KERNEL);
		if (sm == NULL) {
			dev_err(rtd->dev, "%s: snd_model kzalloc failed\n", __func__);
			return -ENOMEM;
		}

		INIT_LIST_HEAD(&sm->list);

		rc = q6lsm_snd_model_buf_alloc(client, p_info->param_size, p_info, sm);
		if (rc) {
			dev_err(rtd->dev, "%s: snd_model buf alloc failed, size = %d\n",
				__func__, p_info->param_size);
			goto err_buf_alloc;
		}

		q6lsm_sm_set_param_data(client, p_info, &offset, sm);

		/*
		 * For set_param, advance the sound model data with the
		 * number of bytes required by param_data.
		 */
		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 %d failed, size = %d\n",
				__func__, p_info->model_id, p_info->param_size);
			rc = -EFAULT;
			goto err_copy;
		}
		/* Add this sound model to the list of multi sound models */
		list_add_tail(&sm->list, &client->stage_cfg[stage_idx].sound_models);

		rc = q6lsm_set_one_param(client, p_info, NULL,
					 LSM_REG_MULTI_SND_MODEL);
		if (rc) {
			dev_err(rtd->dev,
			"%s: snd_model buf alloc failed, size = %d\n",
				"%s: Failed to register snd_model %d, err = %d\n",
				__func__, p_info->model_id, rc);
			goto err_copy;
		}

		client->num_sound_models++;
		dev_dbg(rtd->dev,
			"%s: registered snd_model: %d, total num of snd_model: %d\n",
			__func__, p_info->model_id, client->num_sound_models);
	} else if (p_info->model_id == 0 &&
		   p_info->param_type == LSM_REG_SND_MODEL) {
		sm = &client->stage_cfg[stage_idx].sound_model;

		rc = q6lsm_snd_model_buf_alloc(client, p_info->param_size, p_info, sm);
		if (rc) {
			dev_err(rtd->dev, "%s: snd_model buf alloc failed, size = %d\n",
				__func__, p_info->param_size);
			return rc;
		}

	q6lsm_sm_set_param_data(prtd->lsm_client, p_info, &offset);
		q6lsm_sm_set_param_data(client, p_info, &offset, sm);

		/*
		 * For set_param, advance the sound model data with the
		 * number of bytes required by param_data.
		 */

	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,
@@ -720,18 +834,27 @@ static int msm_lsm_reg_model(struct snd_pcm_substream *substream,
			rc = -EFAULT;
			goto err_copy;
		}
	rc = q6lsm_set_one_param(prtd->lsm_client, p_info, NULL,
				 LSM_REG_SND_MODEL);
		rc = q6lsm_set_one_param(client, p_info, NULL, LSM_REG_SND_MODEL);
		if (rc) {
		dev_err(rtd->dev,
			"%s: Failed to set sound_model, err = %d\n",
			dev_err(rtd->dev, "%s: Failed to register snd_model, err = %d\n",
				__func__, rc);
			goto err_copy;
		}
	} else {
		dev_err(rtd->dev,
			"%s: snd_model id %d is invalid for param type %d\n",
			__func__, p_info->model_id, p_info->param_type);
	}
	return rc;

err_copy:
	q6lsm_snd_model_buf_free(prtd->lsm_client, p_info);
	q6lsm_snd_model_buf_free(client, p_info, sm);
err_buf_alloc:
	if (p_info->model_id != 0) {
		list_del(&sm->list);
		kfree(sm);
		sm = NULL;
	}
	return rc;
}

@@ -741,16 +864,58 @@ static int msm_lsm_dereg_model(struct snd_pcm_substream *substream,
	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_sound_model *sm = NULL;
	struct lsm_client *client = prtd->lsm_client;
	int rc = 0;

	rc = q6lsm_set_one_param(prtd->lsm_client, p_info,
				 NULL, LSM_DEREG_SND_MODEL);
	if (p_info->model_id != 0 &&
		p_info->param_type == LSM_DEREG_MULTI_SND_MODEL) {
		list_for_each_entry(sm,
				   &client->stage_cfg[p_info->stage_idx].sound_models,
				   list) {
			dev_dbg(rtd->dev,
				"%s: current snd_model: %d, looking for snd_model %d\n",
				 __func__, sm->model_id, p_info->model_id);
			if (sm->model_id == p_info->model_id)
				break;
		}

		if (sm->model_id == p_info->model_id) {
			rc = q6lsm_set_one_param(client, p_info, NULL,
						 LSM_DEREG_MULTI_SND_MODEL);
			if (rc)
				dev_err(rtd->dev,
			"%s: Failed to set det_mode param, err = %d\n",
					"%s: Failed to deregister snd_model %d, err = %d\n",
					__func__, p_info->model_id, rc);

			q6lsm_snd_model_buf_free(client, p_info, sm);
			list_del(&sm->list);
			kfree(sm);
			sm = NULL;
			client->num_sound_models--;
		} else {
			rc = -EINVAL;
			dev_err(rtd->dev,
				"%s: Failed to find snd_model, invalid model_id %d\n",
				__func__, p_info->model_id);
		}
	} else if (p_info->model_id == 0 &&
		   p_info->param_type == LSM_DEREG_SND_MODEL) {
		rc = q6lsm_set_one_param(client, p_info, NULL,
					 LSM_DEREG_SND_MODEL);
		if (rc)
			dev_err(rtd->dev,
				"%s: Failed to deregister snd_model, err = %d\n",
				__func__, rc);

	q6lsm_snd_model_buf_free(prtd->lsm_client, p_info);
		sm = &client->stage_cfg[p_info->stage_idx].sound_model;
		q6lsm_snd_model_buf_free(client, p_info, sm);
	} else {
		rc = -EINVAL;
		dev_err(rtd->dev,
			"%s: snd_model id %d is invalid for param type %d\n",
			__func__, p_info->model_id, p_info->param_type);
	}

	return rc;
}
@@ -992,6 +1157,22 @@ static int msm_lsm_process_params(struct snd_pcm_substream *substream,
		return -EINVAL;
	}

	if (p_info->param_type == LSM_REG_MULTI_SND_MODEL &&
		prtd->lsm_client->num_sound_models == LSM_MAX_SOUND_MODELS_SUPPORTED) {
		dev_err(rtd->dev,
			"%s: maximum supported sound models(8) have already reached\n",
			__func__);
		return -EINVAL;
	}

	if (p_info->param_type == LSM_DEREG_MULTI_SND_MODEL &&
		prtd->lsm_client->num_sound_models == 0) {
		dev_err(rtd->dev,
			"%s: no available sound model to be deregistered\n",
			__func__);
		return -EINVAL;
	}

	switch (p_info->param_type) {
	case LSM_ENDPOINT_DETECT_THRESHOLD:
		rc = msm_lsm_set_epd(substream, p_info);
@@ -1003,12 +1184,15 @@ static int msm_lsm_process_params(struct snd_pcm_substream *substream,
		rc = msm_lsm_set_gain(substream, p_info);
		break;
	case LSM_MIN_CONFIDENCE_LEVELS:
	case LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS:
		rc = msm_lsm_set_conf(substream, p_info);
		break;
	case LSM_REG_SND_MODEL:
	case LSM_REG_MULTI_SND_MODEL:
		rc = msm_lsm_reg_model(substream, p_info);
		break;
	case LSM_DEREG_SND_MODEL:
	case LSM_DEREG_MULTI_SND_MODEL:
		rc = msm_lsm_dereg_model(substream, p_info);
		break;
	case LSM_CUSTOM_PARAMS:
@@ -1176,7 +1360,10 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
		 * also set stage index to LSM_STAGE_INDEX_FIRST.
		 */
		struct lsm_params_info_v2 p_info = {0};
		struct lsm_sound_model *sm = NULL;
		p_info.stage_idx = LSM_STAGE_INDEX_FIRST;
		p_info.param_type = LSM_DEREG_SND_MODEL;
		sm = &prtd->lsm_client->stage_cfg[p_info.stage_idx].sound_model;

		dev_dbg(rtd->dev, "%s: Registering sound model V2\n",
			__func__);
@@ -1192,21 +1379,20 @@ 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, &p_info);
					snd_model_v2.data_size, &p_info, sm);
		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->stage_cfg[p_info.stage_idx].sound_model.data,
				snd_model_v2.data, snd_model_v2.data_size)) {
		if (copy_from_user(sm->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, &p_info);
			q6lsm_snd_model_buf_free(prtd->lsm_client, &p_info, sm);
			rc = -EFAULT;
			break;
		}
@@ -1234,7 +1420,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
			dev_err(rtd->dev,
				"%s: Register snd Model v2 failed =%d\n",
			       __func__, rc);
			q6lsm_snd_model_buf_free(prtd->lsm_client, &p_info);
			q6lsm_snd_model_buf_free(prtd->lsm_client, &p_info, sm);
		}
		if (prtd->lsm_client->confidence_levels) {
			kfree(prtd->lsm_client->confidence_levels);
@@ -1697,6 +1883,7 @@ struct lsm_params_info_v2_32 {
	uint32_t param_type;
	u16 instance_id;
	u16 stage_idx;
	u32 model_id;
};

struct snd_lsm_module_params_32 {
@@ -2033,9 +2220,9 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,

		if (p_data.data_size != expected_size) {
			dev_err(rtd->dev,
				"%s: %s: Invalid size %d\n",
				"%s: %s: Invalid size %d, expected_size %d\n",
				__func__, "SET_MODULE_PARAMS(_V2)_32",
				p_data.data_size);
				p_data.data_size, expected_size);
			err = -EINVAL;
			goto done;
		}
@@ -2071,6 +2258,7 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,

				p_info.instance_id = INSTANCE_ID_0;
				p_info.stage_idx = LSM_STAGE_INDEX_FIRST;
				p_info.model_id = 0;

				p_info_32++;
			} else {
@@ -2082,6 +2270,14 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,

				p_info.instance_id = p_info_v2_32->instance_id;
				p_info.stage_idx = p_info_v2_32->stage_idx;
				/* set sound model id to 0 for backward compatibility */
				p_info.model_id = 0;

				if (LSM_REG_MULTI_SND_MODEL == p_info_v2_32->param_type ||
				    LSM_DEREG_MULTI_SND_MODEL == p_info_v2_32->param_type ||
				    LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS ==
								p_info_v2_32->param_type)
					p_info.model_id = p_info_v2_32->model_id;

				p_info_v2_32++;
			}
@@ -2208,7 +2404,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
	case SNDRV_LSM_SET_MODULE_PARAMS_V2: {
		struct snd_lsm_module_params p_data;
		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;
@@ -2277,26 +2472,37 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
		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;
				ptr_info_v2->module_id = temp_ptr_info->module_id;
				ptr_info_v2->param_id = temp_ptr_info->param_id;
				ptr_info_v2->param_size = temp_ptr_info->param_size;
				ptr_info_v2->param_data = temp_ptr_info->param_data;
				ptr_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->instance_id = INSTANCE_ID_0;
				ptr_info_v2->stage_idx = LSM_STAGE_INDEX_FIRST;
				ptr_info_v2->model_id = 0;

				ptr_info_v2 = &info_v2;
				temp_ptr_info++;
			} else {
				/* Just copy the pointer as user already provided v2 params */
				if (LSM_REG_MULTI_SND_MODEL != temp_ptr_info_v2->param_type ||
				    LSM_DEREG_MULTI_SND_MODEL !=
								temp_ptr_info_v2->param_type ||
				    LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS !=
								temp_ptr_info_v2->param_type) {
					/* set sound model id to 0 for backward compatibility */
					temp_ptr_info_v2->model_id = 0;
				}
				/*
				 * Just copy the pointer as user
				 * already provided sound model id
				 */
				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: Failed to process param, type%d stage=%d err=%d\n",
					"%s: Failed to process param, type=%d stage=%d err=%d\n",
					__func__, ptr_info_v2->param_type,
					ptr_info_v2->stage_idx, err);
		}
@@ -2464,7 +2670,7 @@ static int msm_lsm_open(struct snd_pcm_substream *substream)
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct lsm_priv *prtd;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	int ret = 0;
	int ret = 0, i;

	pr_debug("%s\n", __func__);
	prtd = kzalloc(sizeof(struct lsm_priv), GFP_KERNEL);
@@ -2530,6 +2736,12 @@ static int msm_lsm_open(struct snd_pcm_substream *substream)
	prtd->lsm_client->event_type = LSM_DET_EVENT_TYPE_LEGACY;
	prtd->lsm_client->fe_id = rtd->dai_link->id;
	prtd->lsm_client->unprocessed_data = 0;
	prtd->lsm_client->num_sound_models = 0;
	prtd->lsm_client->num_keywords = 0;
	prtd->lsm_client->multi_snd_model_confidence_levels = NULL;

	for (i = 0; i < LSM_MAX_STAGES_PER_SESSION; i++)
		INIT_LIST_HEAD(&prtd->lsm_client->stage_cfg[i].sound_models);

	prtd->ws = wakeup_source_register(rtd->dev, "lsm-client");

+163 −73
Original line number Diff line number Diff line
@@ -908,17 +908,15 @@ static int q6lsm_do_open_v2(struct lsm_client *client,
 * @client: LSM client handle
 * @p_info: param info
 * @offset: pointer to retrieve size
 *
 * @sm: pointer to sound model
 */
void q6lsm_sm_set_param_data(struct lsm_client *client,
			     struct lsm_params_info_v2 *p_info,
		size_t *offset)
			     size_t *offset, struct lsm_sound_model *sm)
{
	struct param_hdr_v3 param_hdr;
	int ret;
	struct lsm_sound_model *sm;

	sm = &client->stage_cfg[p_info->stage_idx].sound_model;
	memset(&param_hdr, 0, sizeof(param_hdr));

	param_hdr.module_id = p_info->module_id;
@@ -926,6 +924,8 @@ void q6lsm_sm_set_param_data(struct lsm_client *client,
	param_hdr.param_id = p_info->param_id;
	param_hdr.param_size = p_info->param_size;

	sm->model_id = p_info->model_id;

	ret = q6lsm_pack_params(sm->data, &param_hdr,
				NULL, offset, LSM_SESSION_CMD_SET_PARAMS_V2);
	if (ret)
@@ -1010,15 +1010,50 @@ EXPORT_SYMBOL(q6lsm_open);

static int q6lsm_send_confidence_levels(struct lsm_client *client,
					struct param_hdr_v3 *param_info,
					uint32_t set_param_opcode)
					uint32_t set_param_opcode, uint32_t model_id)
{
	struct lsm_param_confidence_levels *conf_levels = NULL;
	uint32_t num_conf_levels = client->num_confidence_levels;
	struct lsm_param_multi_snd_model_conf_levels *multi_sm_conf_levels = NULL;
	uint32_t num_keywords = client->num_keywords;
	uint8_t i = 0;
	uint8_t padd_size = 0;
	uint32_t param_size = 0;
	int rc = 0;

	if (model_id != 0) {
		/* No padding is need since the structure is always 4 byte aligend.
		 * The number "2" below represents the first two u32 variables in
		 * struct lsm_param_multi_snd_model_conf_levels.
		 */
		param_size = (2 + num_keywords) * sizeof(uint32_t);
		param_info->param_size = param_size;
		pr_debug("%s: Set Conf Levels PARAM SIZE: %d\n", __func__, param_size);

		multi_sm_conf_levels = kzalloc(param_size, GFP_KERNEL);
		if (!multi_sm_conf_levels)
			return -ENOMEM;

		multi_sm_conf_levels->model_id = model_id;
		multi_sm_conf_levels->num_keywords = num_keywords;
		pr_debug("%s: snd_model id: %d, num_keywords: %d\n",
			 __func__, model_id, num_keywords);

		memcpy(multi_sm_conf_levels->confidence_levels,
		       client->multi_snd_model_confidence_levels,
		       sizeof(uint32_t) * num_keywords);
		for (i = 0; i < num_keywords; i++)
			pr_debug("%s: Confidence_level[%d] = %d\n", __func__, i,
				 multi_sm_conf_levels->confidence_levels[i]);

		rc = q6lsm_pack_and_set_params(client, param_info,
					       (uint8_t *) multi_sm_conf_levels,
					       set_param_opcode);
		if (rc)
			pr_err("%s: Send multi_snd_model_conf_levels cmd failed, err %d\n",
			       __func__, rc);
		kfree(multi_sm_conf_levels);
	} else {
		/* Data must be 4 byte aligned so add any necessary padding. */
		padd_size = (4 - (num_conf_levels % 4)) - 1;
		param_size = (sizeof(uint8_t) + num_conf_levels + padd_size) *
@@ -1046,6 +1081,7 @@ static int q6lsm_send_confidence_levels(struct lsm_client *client,
			pr_err("%s: Send confidence_levels cmd failed, err = %d\n",
			       __func__, rc);
		kfree(conf_levels);
	}
	return rc;
}

@@ -1459,7 +1495,7 @@ int q6lsm_set_data(struct lsm_client *client,

	param_hdr.param_id = LSM_PARAM_ID_MIN_CONFIDENCE_LEVELS;
	rc = q6lsm_send_confidence_levels(client, &param_hdr,
					  LSM_SESSION_CMD_SET_PARAMS);
					  LSM_SESSION_CMD_SET_PARAMS, 0);
	if (rc) {
		pr_err("%s: Failed to send conf_levels, err = %d\n",
			__func__, rc);
@@ -1537,8 +1573,9 @@ EXPORT_SYMBOL(q6lsm_register_sound_model);
 */
int q6lsm_deregister_sound_model(struct lsm_client *client)
{
	int rc;
	int rc = 0;
	struct lsm_cmd_reg_snd_model cmd;
	struct lsm_sound_model *sm = NULL, *next = NULL;
	/*
	 * With multi-stage support sm buff allocation/free usage param info
	 * to check stage index for which this sound model is being set, and
@@ -1564,6 +1601,23 @@ int q6lsm_deregister_sound_model(struct lsm_client *client)
		return -EINVAL;
	}

	if (client->num_sound_models > 0) {
		p_info.param_type = LSM_DEREG_MULTI_SND_MODEL;
		list_for_each_entry_safe(sm, next,
				&client->stage_cfg[p_info.stage_idx].sound_models,
				list) {
			pr_debug("%s: current snd_model: %d, num of sound models left %d\n",
				 __func__, sm->model_id, client->num_sound_models);
			q6lsm_snd_model_buf_free(client, &p_info, sm);
			list_del(&sm->list);
			kfree(sm);
			sm = NULL;
			client->num_sound_models--;

			if (0 == client->num_sound_models)
				break;
		}
	} else {
		memset(&cmd, 0, sizeof(cmd));
		q6lsm_add_hdr(client, &cmd.hdr, sizeof(cmd.hdr), false);
		cmd.hdr.opcode = LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL;
@@ -1576,7 +1630,10 @@ int q6lsm_deregister_sound_model(struct lsm_client *client)
			pr_debug("%s: Deregister sound model succeeded\n", __func__);
		}

	q6lsm_snd_model_buf_free(client, &p_info);
		p_info.param_type = LSM_DEREG_SND_MODEL;
		sm = &client->stage_cfg[p_info.stage_idx].sound_model;
		q6lsm_snd_model_buf_free(client, &p_info, sm);
	}

	return rc;
}
@@ -1825,14 +1882,15 @@ static int q6lsm_snd_cal_alloc(struct lsm_client *client,
 *
 * @client: LSM client handle
 * @p_info: sound model param info
 * @sm: pointer to sound model
 *
 * Returns 0 on success or error on failure
 */
int q6lsm_snd_model_buf_free(struct lsm_client *client,
			struct lsm_params_info_v2 *p_info)
			     struct lsm_params_info_v2 *p_info,
			     struct lsm_sound_model *sm)
{
	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)) {
@@ -1840,11 +1898,11 @@ int q6lsm_snd_model_buf_free(struct lsm_client *client,
		return -EINVAL;
	}

	if (!client->stage_cfg[stage_idx].sound_model.data)
	if (p_info->param_type == LSM_DEREG_SND_MODEL &&
	    !client->stage_cfg[stage_idx].sound_model.data)
		return 0;

	mutex_lock(&client->cmd_lock);
	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)
@@ -1858,6 +1916,9 @@ int q6lsm_snd_model_buf_free(struct lsm_client *client,
	sm->phys = 0;
	mutex_unlock(&client->cmd_lock);

	if ((p_info->param_type == LSM_DEREG_MULTI_SND_MODEL &&
	    client->num_sound_models == 1) ||
	    p_info->param_type == LSM_DEREG_SND_MODEL)
		rc = q6lsm_snd_cal_free(client, p_info);
	return rc;
}
@@ -1980,20 +2041,20 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
 * Returns 0 on success or error on failure
 */
int q6lsm_snd_model_buf_alloc(struct lsm_client *client, size_t len,
			      struct lsm_params_info_v2 *p_info)
			      struct lsm_params_info_v2 *p_info,
			      struct lsm_sound_model *sm)
{
	int rc = -EINVAL, stage_idx = p_info->stage_idx;
	int model_id = p_info->model_id;
	size_t total_mem = 0;
	struct lsm_sound_model *sm = NULL;

	if (!client)
		return rc;

	pr_debug("%s:Snd Model len = %zd, stage idx %d\n",
			__func__, len, stage_idx);
	pr_debug("%s:Snd Model len %zd, stage_idx %d, model_id %d\n",
		 __func__, len, stage_idx, model_id);

	mutex_lock(&client->cmd_lock);
	sm = &client->stage_cfg[stage_idx].sound_model;
	if (!sm->data) {
		/*
		 * If sound model is sent as set_param, i.e. param_id != 0,
@@ -2040,7 +2101,7 @@ int q6lsm_snd_model_buf_alloc(struct lsm_client *client, size_t len,
fail:
	mutex_unlock(&client->cmd_lock);
fail_1:
	q6lsm_snd_model_buf_free(client, p_info);
	q6lsm_snd_model_buf_free(client, p_info, sm);
	return rc;
}
EXPORT_SYMBOL(q6lsm_snd_model_buf_alloc);
@@ -2126,8 +2187,8 @@ 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_v2 *p_info, void *data,
	uint32_t param_type)
			struct lsm_params_info_v2 *p_info,
			void *data, uint32_t param_type)
{
	struct param_hdr_v3 param_info;
	int rc = 0;
@@ -2186,14 +2247,19 @@ int q6lsm_set_one_param(struct lsm_client *client,
	}

	case LSM_MIN_CONFIDENCE_LEVELS:
	case LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS:
		param_info.module_id = p_info->module_id;
		param_info.instance_id = p_info->instance_id;
		param_info.param_id = p_info->param_id;
		rc = q6lsm_send_confidence_levels(
			client, &param_info, LSM_SESSION_CMD_SET_PARAMS_V2);
			client, &param_info, LSM_SESSION_CMD_SET_PARAMS_V2,
			p_info->model_id);
		if (rc)
			pr_err("%s: CONFIDENCE_LEVELS cmd failed, rc %d\n",
				 __func__, rc);
			pr_err("%s: %s cmd failed, rc %d\n",
				 __func__,
				 param_type == LSM_MIN_CONFIDENCE_LEVELS ?
				 "LSM_MIN_CONFIDENCE_LEVELS" :
				 "LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS", rc);
		break;
	case LSM_POLLING_ENABLE: {
		struct snd_lsm_poll_enable *lsm_poll_enable =
@@ -2210,7 +2276,8 @@ int q6lsm_set_one_param(struct lsm_client *client,
		break;
	}

	case LSM_REG_SND_MODEL: {
	case LSM_REG_SND_MODEL:
	case LSM_REG_MULTI_SND_MODEL: {
		struct mem_mapping_hdr mem_hdr;
		u32 payload_size;
		struct lsm_sound_model *sm = NULL;
@@ -2224,8 +2291,18 @@ int q6lsm_set_one_param(struct lsm_client *client,
			payload_size = p_info->param_size +
				       sizeof(struct param_hdr_v2);

		if (param_type == LSM_REG_MULTI_SND_MODEL) {
			list_for_each_entry(sm,
					    &client->stage_cfg[p_info->stage_idx].sound_models,
					    list) {
				pr_debug("%s: current snd_model: %d, looking for snd_model %d\n",
					__func__, sm->model_id, p_info->model_id);
				if (sm->model_id == p_info->model_id)
					break;
			}
		} else {
			sm = &client->stage_cfg[p_info->stage_idx].sound_model;

		}
		mem_hdr.data_payload_addr_lsw =
			lower_32_bits(sm->phys);
		mem_hdr.data_payload_addr_msw =
@@ -2236,28 +2313,41 @@ int q6lsm_set_one_param(struct lsm_client *client,
		rc = q6lsm_set_params(client, &mem_hdr, NULL, payload_size,
				      LSM_SESSION_CMD_SET_PARAMS_V2);
		if (rc) {
			pr_err("%s: REG_SND_MODEL failed, rc %d\n",
				__func__, rc);
			pr_err("%s: %s failed, rc %d\n",
				__func__, param_type == LSM_REG_SND_MODEL ?
				"LSM_REG_SND_MODEL" : "LSM_REG_MULTI_SND_MODEL", rc);
			return rc;
		}

		if (client->num_sound_models == 0) {
			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);
		}
		break;
	}

	case LSM_DEREG_SND_MODEL: {
	case LSM_DEREG_SND_MODEL:
	case LSM_DEREG_MULTI_SND_MODEL: {
		param_info.module_id = p_info->module_id;
		param_info.instance_id = p_info->instance_id;
		param_info.param_id = p_info->param_id;
		param_info.param_size = 0;

		if (param_type == LSM_DEREG_MULTI_SND_MODEL) {
			param_info.param_size = p_info->param_size;
			rc = q6lsm_pack_and_set_params(client, &param_info,
							(uint8_t *)&p_info->model_id,
							LSM_SESSION_CMD_SET_PARAMS_V2);
		} else {
			rc = q6lsm_pack_and_set_params(client, &param_info, NULL,
							LSM_SESSION_CMD_SET_PARAMS_V2);
		}
		if (rc)
			pr_err("%s: DEREG_SND_MODEL failed, rc %d\n",
				__func__, rc);
			pr_err("%s: %s failed, rc %d\n",
				__func__,  param_type == LSM_DEREG_SND_MODEL ?
				"LSM_DEREG_SND_MODEL" : "LSM_DEREG_MULTI_SND_MODEL", rc);
		break;
	}

+19 −4

File changed.

Preview size limit exceeded, changes collapsed.

+7 −2
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@

#include <linux/types.h>

#define SNDRV_LSM_VERSION SNDRV_PROTOCOL_VERSION(0, 3, 1)
#define SNDRV_LSM_VERSION SNDRV_PROTOCOL_VERSION(0, 3, 2)

#define LSM_MAX_STAGES_PER_SESSION 2
#define LSM_STAGE_INDEX_FIRST 0
@@ -33,7 +33,10 @@
#define LSM_POLLING_ENABLE (7)
#define LSM_DET_EVENT_TYPE (8)
#define LSM_LAB_CONTROL (9)
#define LSM_PARAMS_MAX (LSM_LAB_CONTROL + 1)
#define LSM_REG_MULTI_SND_MODEL (10)
#define LSM_DEREG_MULTI_SND_MODEL (11)
#define LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS (12)
#define LSM_PARAMS_MAX (LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS + 1)

#define LSM_EVENT_NON_TIME_STAMP_MODE (0)
#define LSM_EVENT_TIME_STAMP_MODE (1)
@@ -226,6 +229,7 @@ struct lsm_params_info {
 * Member variables applicable only to V2:
 * @instance_id: instance id of the param to which parameter is to be set
 * @stage_idx: detection stage for which the param is applicable
 * @model_id: an unique number to identify sound models in DSP
 */
struct lsm_params_info_v2 {
	__u32 module_id;
@@ -235,6 +239,7 @@ struct lsm_params_info_v2 {
	__u32 param_type;
	__u16 instance_id;
	__u16 stage_idx;
	__u32 model_id;
};

/*