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

Commit 9fd1fdf9 authored by Narsinga Rao Chella's avatar Narsinga Rao Chella Committed by Gerrit - the friendly Code Review server
Browse files

ASoC: msm: qdsp6v2: Add support for vocoder specific calibration



This change is needed to support Per-Vocoder Calibration feature.
It enables new calibration framework on ADSP when picked along with
corresponding changes from audio calibration driver, acdb data files
and ADSP. Backward compatibility is maintained such that the older
calibration framework will be used if any of the components are old.

Change-Id: Ie002e3e935c89c3368b3968c79bf3a6bec226ea1
Signed-off-by: default avatarNarsinga Rao Chella <nrchella@codeaurora.org>
parent 4c353a42
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -531,6 +531,37 @@ done:
	return ret;
}

static int msm_voice_cvd_version_info(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_info *uinfo)
{
	int ret = 0;

	pr_debug("%s:\n", __func__);

	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
	uinfo->count = CVD_VERSION_STRING_MAX_SIZE;

	return ret;
}

static int msm_voice_cvd_version_get(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
{
	char cvd_version[CVD_VERSION_STRING_MAX_SIZE] = CVD_VERSION_DEFAULT;
	int ret;

	pr_debug("%s:\n", __func__);

	ret = voc_get_cvd_version(cvd_version);

	if (ret)
		pr_err("%s: Error retrieving CVD version, error:%d\n",
			__func__, ret);

	memcpy(ucontrol->value.bytes.data, cvd_version, sizeof(cvd_version));

	return 0;
}
static struct snd_kcontrol_new msm_voice_controls[] = {
	SOC_SINGLE_MULTI_EXT("Voice Rx Device Mute", SND_SOC_NOPM, 0, VSID_MAX,
				0, 3, NULL, msm_voice_rx_device_mute_put),
@@ -547,6 +578,13 @@ static struct snd_kcontrol_new msm_voice_controls[] = {
	SOC_SINGLE_MULTI_EXT("Voice Topology Disable", SND_SOC_NOPM, 0,
			     VSID_MAX, 0, 2, NULL,
			     msm_voice_topology_disable_put),
	{
		.access = SNDRV_CTL_ELEM_ACCESS_READ,
		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,
		.name	= "CVD Version",
		.info	= msm_voice_cvd_version_info,
		.get	= msm_voice_cvd_version_get,
	},
};

static struct snd_pcm_ops msm_pcm_ops = {
+181 −10
Original line number Diff line number Diff line
@@ -2186,6 +2186,10 @@ static int voice_send_cvs_register_cal_cmd(struct voice_data *v)
				voice_get_idx_for_session(v->session_id);
	cvs_reg_cal_cmd.hdr.dest_port = voice_get_cvs_handle(v);
	cvs_reg_cal_cmd.hdr.token = 0;
	if (common.is_per_vocoder_cal_enabled)
		cvs_reg_cal_cmd.hdr.opcode =
			VSS_ISTREAM_CMD_REGISTER_STATIC_CALIBRATION_DATA;
	else
		cvs_reg_cal_cmd.hdr.opcode =
			VSS_ISTREAM_CMD_REGISTER_CALIBRATION_DATA_V2;

@@ -2248,6 +2252,10 @@ static int voice_send_cvs_deregister_cal_cmd(struct voice_data *v)
				voice_get_idx_for_session(v->session_id);
	cvs_dereg_cal_cmd.hdr.dest_port = voice_get_cvs_handle(v);
	cvs_dereg_cal_cmd.hdr.token = 0;
	if (common.is_per_vocoder_cal_enabled)
		cvs_dereg_cal_cmd.hdr.opcode =
			VSS_ISTREAM_CMD_DEREGISTER_STATIC_CALIBRATION_DATA;
	else
		cvs_dereg_cal_cmd.hdr.opcode =
			VSS_ISTREAM_CMD_DEREGISTER_CALIBRATION_DATA;

@@ -2444,6 +2452,10 @@ static int voice_send_cvp_register_cal_cmd(struct voice_data *v)
				voice_get_idx_for_session(v->session_id);
	cvp_reg_cal_cmd.hdr.dest_port = voice_get_cvp_handle(v);
	cvp_reg_cal_cmd.hdr.token = 0;
	if (common.is_per_vocoder_cal_enabled)
		cvp_reg_cal_cmd.hdr.opcode =
			VSS_IVOCPROC_CMD_REGISTER_STATIC_CALIBRATION_DATA;
	else
		cvp_reg_cal_cmd.hdr.opcode =
			VSS_IVOCPROC_CMD_REGISTER_CALIBRATION_DATA_V2;

@@ -2506,6 +2518,10 @@ static int voice_send_cvp_deregister_cal_cmd(struct voice_data *v)
				voice_get_idx_for_session(v->session_id);
	cvp_dereg_cal_cmd.hdr.dest_port = voice_get_cvp_handle(v);
	cvp_dereg_cal_cmd.hdr.token = 0;
	if (common.is_per_vocoder_cal_enabled)
		cvp_dereg_cal_cmd.hdr.opcode =
			VSS_IVOCPROC_CMD_DEREGISTER_STATIC_CALIBRATION_DATA;
	else
		cvp_dereg_cal_cmd.hdr.opcode =
			VSS_IVOCPROC_CMD_DEREGISTER_CALIBRATION_DATA;

@@ -2574,6 +2590,10 @@ static int voice_send_cvp_register_vol_cal_cmd(struct voice_data *v)
				voice_get_idx_for_session(v->session_id);
	cvp_reg_vol_cal_cmd.hdr.dest_port = voice_get_cvp_handle(v);
	cvp_reg_vol_cal_cmd.hdr.token = 0;
	if (common.is_per_vocoder_cal_enabled)
		cvp_reg_vol_cal_cmd.hdr.opcode =
			VSS_IVOCPROC_CMD_REGISTER_DYNAMIC_CALIBRATION_DATA;
	else
		cvp_reg_vol_cal_cmd.hdr.opcode =
			VSS_IVOCPROC_CMD_REGISTER_VOL_CALIBRATION_DATA;

@@ -2638,6 +2658,10 @@ static int voice_send_cvp_deregister_vol_cal_cmd(struct voice_data *v)
				voice_get_idx_for_session(v->session_id);
	cvp_dereg_vol_cal_cmd.hdr.dest_port = voice_get_cvp_handle(v);
	cvp_dereg_vol_cal_cmd.hdr.token = 0;
	if (common.is_per_vocoder_cal_enabled)
		cvp_dereg_vol_cal_cmd.hdr.opcode =
			VSS_IVOCPROC_CMD_DEREGISTER_DYNAMIC_CALIBRATION_DATA;
	else
		cvp_dereg_vol_cal_cmd.hdr.opcode =
			VSS_IVOCPROC_CMD_DEREGISTER_VOL_CALIBRATION_DATA;

@@ -5459,6 +5483,7 @@ static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
	struct common_data *c = NULL;
	struct voice_data *v = NULL;
	int i = 0;
	struct vss_iversion_rsp_get_t *version_rsp = NULL;

	if ((data == NULL) || (priv == NULL)) {
		pr_err("%s: data or priv is NULL\n", __func__);
@@ -5556,6 +5581,18 @@ static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
			case VSS_IMVM_CMD_PAUSE_VOICE:
			case VSS_IMVM_CMD_STANDBY_VOICE:
				pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
				v->mvm_state = CMD_STATUS_SUCCESS;
				wake_up(&v->mvm_wait);
				break;
			case VSS_IVERSION_CMD_GET:
				pr_debug("%s: Error retrieving CVD Version, error:%d\n",
					 __func__, ptr[1]);

				strlcpy(common.cvd_version, CVD_VERSION_0_0,
					sizeof(common.cvd_version));
				pr_debug("%s: Fall back to default value, CVD Version = %s\n",
					 __func__, common.cvd_version);

				v->mvm_state = CMD_STATUS_SUCCESS;
				wake_up(&v->mvm_wait);
				break;
@@ -5617,6 +5654,20 @@ static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
			pr_err("%s: Unknown mem map token %d\n",
			       __func__, data->token);
		}
	} else if (data->opcode == VSS_IVERSION_RSP_GET) {
		pr_debug("%s: Received VSS_IVERSION_RSP_GET\n", __func__);

		if (data->payload_size) {
			version_rsp =
				(struct vss_iversion_rsp_get_t *)data->payload;
			memcpy(common.cvd_version, version_rsp->version,
			       CVD_VERSION_STRING_MAX_SIZE);
			pr_debug("%s: CVD Version = %s\n",
				 __func__, common.cvd_version);

			v->mvm_state = CMD_STATUS_SUCCESS;
			wake_up(&v->mvm_wait);
		}
	}
	return 0;
}
@@ -5700,6 +5751,8 @@ static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv)
			case APRV2_IBASIC_CMD_DESTROY_SESSION:
			case VSS_ISTREAM_CMD_REGISTER_CALIBRATION_DATA_V2:
			case VSS_ISTREAM_CMD_DEREGISTER_CALIBRATION_DATA:
			case VSS_ISTREAM_CMD_REGISTER_STATIC_CALIBRATION_DATA:
			case VSS_ISTREAM_CMD_DEREGISTER_STATIC_CALIBRATION_DATA:
			case VSS_ICOMMON_CMD_MAP_MEMORY:
			case VSS_ICOMMON_CMD_UNMAP_MEMORY:
			case VSS_ICOMMON_CMD_SET_UI_PROPERTY:
@@ -5963,6 +6016,10 @@ static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv)
			case VSS_IVOCPROC_CMD_DEREGISTER_VOL_CALIBRATION_DATA:
			case VSS_IVOCPROC_CMD_REGISTER_CALIBRATION_DATA_V2:
			case VSS_IVOCPROC_CMD_DEREGISTER_CALIBRATION_DATA:
			case VSS_IVOCPROC_CMD_REGISTER_DYNAMIC_CALIBRATION_DATA:
		    case VSS_IVOCPROC_CMD_DEREGISTER_DYNAMIC_CALIBRATION_DATA:
			case VSS_IVOCPROC_CMD_REGISTER_STATIC_CALIBRATION_DATA:
		    case VSS_IVOCPROC_CMD_DEREGISTER_STATIC_CALIBRATION_DATA:
			case VSS_IVOCPROC_CMD_REGISTER_DEVICE_CONFIG:
			case VSS_IVOCPROC_CMD_DEREGISTER_DEVICE_CONFIG:
			case VSS_ICOMMON_CMD_MAP_MEMORY:
@@ -6380,6 +6437,108 @@ void voc_deregister_hpcm_evt_cb(void)
	common.hostpcm_info.private_data = NULL;
}

int voc_get_cvd_version(char *cvd_version)
{
	int ret = 0;
	struct apr_hdr cvd_version_get_cmd;
	struct voice_data *v = voice_get_session(VOICE_SESSION_VSID);
	void *apr_handle_mvm = NULL;

	if (strcmp(common.cvd_version, CVD_VERSION_DEFAULT)) {
		pr_debug("%s: Already attempted querying CVD version, return the cached value %s\n",
			 __func__, common.cvd_version);

		memcpy(cvd_version, common.cvd_version,
			CVD_VERSION_STRING_MAX_SIZE);
		goto done;
	}

	if (v == NULL) {
		pr_err("%s: invalid session_id 0x%x\n",
		       __func__, VOICE_SESSION_VSID);

		ret = -EINVAL;
		goto done;
	}

	mutex_lock(&common.common_lock);
	mutex_lock(&v->lock);

	/* Register callback to APR */
	if (apr_handle_mvm == NULL) {
		pr_debug("%s: Register MVM callback\n", __func__);

		apr_handle_mvm = apr_register("ADSP", "MVM",
					      qdsp_mvm_callback,
					      0xFFFFFFFF, &common);

		if (apr_handle_mvm == NULL) {
			pr_err("%s: Unable to register MVM\n", __func__);

			strlcpy(common.cvd_version, CVD_VERSION_0_0,
				sizeof(common.cvd_version));
			ret = -EINVAL;
			goto unlock;
		}
	}

	/* Send command to CVD to retrive Version */
	cvd_version_get_cmd.hdr_field = APR_HDR_FIELD(
				APR_MSG_TYPE_SEQ_CMD,
				APR_HDR_LEN(APR_HDR_SIZE),
				APR_PKT_VER);
	cvd_version_get_cmd.pkt_size = APR_PKT_SIZE(
				APR_HDR_SIZE,
				sizeof(cvd_version_get_cmd) -
				APR_HDR_SIZE);
	cvd_version_get_cmd.src_port =
		voice_get_idx_for_session(v->session_id);
	cvd_version_get_cmd.dest_port = 0;
	cvd_version_get_cmd.token = 0;
	cvd_version_get_cmd.opcode = VSS_IVERSION_CMD_GET;
	v->mvm_state = CMD_STATUS_FAIL;

	pr_debug("%s: send CVD version get cmd, pkt size = %d\n",
		 __func__, cvd_version_get_cmd.pkt_size);

	ret = apr_send_pkt(apr_handle_mvm,
			   (uint32_t *) &cvd_version_get_cmd);
	if (ret < 0) {
		pr_err("%s: Error sending command, fall back to default\n",
			__func__);

		strlcpy(common.cvd_version, CVD_VERSION_0_0,
			sizeof(common.cvd_version));
		goto unlock;
	}
	ret = wait_event_timeout(v->mvm_wait,
			(v->mvm_state == CMD_STATUS_SUCCESS),
			msecs_to_jiffies(TIMEOUT_MS));
	if (!ret) {
		pr_err("%s: wait_event timeout, fall back to default\n",
			__func__);

		strlcpy(common.cvd_version, CVD_VERSION_0_0,
			sizeof(common.cvd_version));
		ret = -EINVAL;
		goto unlock;
	}
	pr_debug("%s: CVD Version retrieved=%s\n",
		 __func__, common.cvd_version);

	ret = 0;
unlock:
	if (apr_handle_mvm != NULL) {
		apr_deregister(apr_handle_mvm);
		apr_handle_mvm = NULL;
	}
	memcpy(cvd_version, common.cvd_version, CVD_VERSION_STRING_MAX_SIZE);
	mutex_unlock(&v->lock);
	mutex_unlock(&common.common_lock);
done:
	return ret;
}

static int voice_alloc_cal_mem_map_table(void)
{
	int ret = 0;
@@ -6575,8 +6734,14 @@ static int voice_alloc_cal(int32_t cal_type,
{
	int ret = 0;
	int cal_index;
	int cal_version;

	pr_debug("%s\n", __func__);

	cal_version = cal_utils_get_cal_type_version(data);
	common.is_per_vocoder_cal_enabled =
			!!(cal_version & PER_VOCODER_CAL_BIT_MASK);

	cal_index = get_cal_type_index(cal_type);
	if (cal_index < 0) {
		pr_err("%s: Could not get cal index %d!\n",
@@ -6764,6 +6929,12 @@ static int __init voice_init(void)
	/* Initialize is low memory flag */
	common.is_destroy_cvd = false;

	/* Initialize CVD version */
	strlcpy(common.cvd_version, CVD_VERSION_DEFAULT,
		sizeof(common.cvd_version));
	/* Initialize Per-Vocoder Calibration flag */
	common.is_per_vocoder_cal_enabled = false;

	mutex_init(&common.common_lock);

	/* Initialize session id with vsid */
+25 −0
Original line number Diff line number Diff line
@@ -35,6 +35,20 @@
#define VOC_REC_DOWNLINK	0x01
#define VOC_REC_BOTH		0x02

#define VSS_IVERSION_CMD_GET                 0x00011378
#define VSS_IVERSION_RSP_GET                 0x00011379
#define CVD_VERSION_STRING_MAX_SIZE          31
#define CVD_VERSION_DEFAULT                  ""
#define CVD_VERSION_0_0                      "0.0"

int voc_get_cvd_version(char *);

/* Payload structure for the VSS_IVERSION_RSP_GET command response */
struct vss_iversion_rsp_get_t {
	char version[CVD_VERSION_STRING_MAX_SIZE];
	/* NULL-terminated version string */
};

enum {
	CVP_VOC_RX_TOPOLOGY_CAL = 0,
	CVP_VOC_TX_TOPOLOGY_CAL,
@@ -468,6 +482,9 @@ struct vss_imemory_cmd_unmap_t {

#define VSS_ISTREAM_CMD_DEREGISTER_CALIBRATION_DATA     0x0001127A

#define VSS_ISTREAM_CMD_REGISTER_STATIC_CALIBRATION_DATA        0x0001307D
#define VSS_ISTREAM_CMD_DEREGISTER_STATIC_CALIBRATION_DATA      0x0001307E

#define VSS_ISTREAM_CMD_SET_MEDIA_TYPE			0x00011186
/* Set media type on the stream. */

@@ -956,6 +973,12 @@ struct vss_istream_cmd_set_packet_exchange_mode_t {
#define VSS_IVOCPROC_CMD_REGISTER_VOL_CALIBRATION_DATA	0x00011374
#define VSS_IVOCPROC_CMD_DEREGISTER_VOL_CALIBRATION_DATA	0x00011375

#define VSS_IVOCPROC_CMD_REGISTER_STATIC_CALIBRATION_DATA       0x00013079
#define VSS_IVOCPROC_CMD_DEREGISTER_STATIC_CALIBRATION_DATA     0x0001307A

#define VSS_IVOCPROC_CMD_REGISTER_DYNAMIC_CALIBRATION_DATA      0x0001307B
#define VSS_IVOCPROC_CMD_DEREGISTER_DYNAMIC_CALIBRATION_DATA    0x0001307C

#define VSS_IVOCPROC_TOPOLOGY_ID_NONE			0x00010F70
#define VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS		0x00010F71
#define VSS_IVOCPROC_TOPOLOGY_ID_TX_DM_FLUENCE		0x00010F72
@@ -1503,6 +1526,8 @@ struct common_data {
	bool srvcc_rec_flag;
	bool is_destroy_cvd;
	bool is_vote_bms;
	char cvd_version[CVD_VERSION_STRING_MAX_SIZE];
	bool is_per_vocoder_cal_enabled;
};

struct voice_session_itr {