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

Commit c786712e authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: msm: Add support for Stereo EC Reference"

parents 9f99c83a ff694a93
Loading
Loading
Loading
Loading
+344 −7
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <soc/qcom/socinfo.h>
#include <linux/qdsp6v2/apr_tal.h>

#include "sound/q6core.h"
#include "sound/q6audio-v2.h"
#include "sound/apr_audio-v2.h"
#include "sound/q6afe-v2.h"
@@ -33,6 +34,9 @@

#define CMD_STATUS_SUCCESS 0
#define CMD_STATUS_FAIL 1
#define NUM_CHANNELS_MONO 1
#define NUM_CHANNELS_STEREO 2
#define CVP_VERSION_2 2

enum {
	VOC_TOKEN_NONE,
@@ -83,6 +87,11 @@ static int voice_send_cvp_device_channels_cmd(struct voice_data *v);
static int voice_send_cvp_media_format_cmd(struct voice_data *v,
					   uint32_t param_type);
static int voice_send_cvp_topology_commit_cmd(struct voice_data *v);
static int voice_send_cvp_channel_info_cmd(struct voice_data *v);
static int voice_send_cvp_channel_info_v2(struct voice_data *v,
					  uint32_t param_type);
static int voice_get_avcs_version_per_service(uint32_t service_id);


static int voice_cvs_stop_playback(struct voice_data *v);
static int voice_cvs_start_playback(struct voice_data *v);
@@ -3793,6 +3802,295 @@ int voc_unmap_rtac_block(uint32_t *mem_map_handle)
	return result;
}

static int voice_send_cvp_channel_info_v2(struct voice_data *v,
					  uint32_t param_type)
{
	int ret;
	struct cvp_set_channel_info_cmd_v2 cvp_set_channel_info_cmd;
	void *apr_cvp;
	u16 cvp_handle;
	struct vss_icommon_param_data_channel_info_v2_t
		*channel_info_param_data =
			&cvp_set_channel_info_cmd.
			cvp_set_ch_info_param_v2.param_data;
	struct vss_param_vocproc_dev_channel_info_t *channel_info =
			&channel_info_param_data->channel_info;

	if (v == NULL) {
		pr_err("%s: v is NULL\n", __func__);
		ret = -EINVAL;
		goto done;
	}

	apr_cvp = common.apr_q6_cvp;
	if (!apr_cvp) {
		pr_err("%s: apr_cvp is NULL\n", __func__);
		ret = -EINVAL;
		goto done;
	}

	cvp_handle = voice_get_cvp_handle(v);
	memset(&cvp_set_channel_info_cmd, 0, sizeof(cvp_set_channel_info_cmd));

	cvp_set_channel_info_cmd.hdr.hdr_field =
		APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
			      APR_PKT_VER);
	cvp_set_channel_info_cmd.hdr.pkt_size =
		APR_PKT_SIZE(APR_HDR_SIZE,
		sizeof(cvp_set_channel_info_cmd) - APR_HDR_SIZE);
	cvp_set_channel_info_cmd.hdr.src_svc = 0;
	cvp_set_channel_info_cmd.hdr.src_domain = APR_DOMAIN_APPS;
	cvp_set_channel_info_cmd.hdr.src_port =
		voice_get_idx_for_session(v->session_id);
	cvp_set_channel_info_cmd.hdr.dest_svc = 0;
	cvp_set_channel_info_cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
	cvp_set_channel_info_cmd.hdr.dest_port = cvp_handle;
	cvp_set_channel_info_cmd.hdr.token = 0;
	cvp_set_channel_info_cmd.hdr.opcode =  VSS_ICOMMON_CMD_SET_PARAM_V2;

	cvp_set_channel_info_cmd.cvp_set_ch_info_param_v2.mem_size =
			sizeof(struct vss_icommon_param_data_channel_info_v2_t);

	channel_info_param_data->module_id = VSS_MODULE_CVD_GENERIC;
	channel_info_param_data->param_size =
		sizeof(struct vss_param_vocproc_dev_channel_info_t);

	 /* Device specific data */
	switch (param_type) {
	case RX_PATH:
		channel_info_param_data->param_id =
			VSS_PARAM_VOCPROC_RX_CHANNEL_INFO;
		channel_info->num_channels = v->dev_rx.no_of_channels;
		channel_info->bits_per_sample = v->dev_rx.bits_per_sample;
		break;

	case TX_PATH:
		channel_info_param_data->param_id =
			VSS_PARAM_VOCPROC_TX_CHANNEL_INFO;
		channel_info->num_channels = v->dev_tx.no_of_channels;
		channel_info->bits_per_sample = v->dev_tx.bits_per_sample;
		break;

	case EC_REF_PATH:
		channel_info_param_data->param_id =
			VSS_PARAM_VOCPROC_EC_REF_CHANNEL_INFO;
		channel_info->num_channels = v->dev_rx.no_of_channels;
		channel_info->bits_per_sample = v->dev_rx.bits_per_sample;
		break;
	default:
		pr_err("%s: Invalid param type\n",
		       __func__);
		ret = -EINVAL;
		goto done;
	}

	if (channel_info->num_channels == NUM_CHANNELS_MONO) {
		channel_info->channel_mapping[0] = PCM_CHANNEL_FC;
	} else if (channel_info->num_channels == NUM_CHANNELS_STEREO) {
		channel_info->channel_mapping[0] = PCM_CHANNEL_FL;
		channel_info->channel_mapping[1] = PCM_CHANNEL_FR;
	} else {
		pr_err("%s: Unsupported num channels: %d\n",
		       __func__, channel_info->num_channels);
		ret = -EINVAL;
		goto done;
	}

	v->cvp_state = CMD_STATUS_FAIL;
	v->async_err = 0;
	ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_set_channel_info_cmd);
	if (ret < 0) {
		pr_err("%s: Failed to send VSS_ICOMMON_CMD_SET_PARAM_V2\n",
		       __func__);
		goto done;
	}

	ret = wait_event_timeout(v->cvp_wait,
				(v->cvp_state == CMD_STATUS_SUCCESS),
				 msecs_to_jiffies(TIMEOUT_MS));
	if (!ret) {
		pr_err("%s: wait_event timeout\n", __func__);
		ret = -ETIMEDOUT;
		goto done;
	}

	if (v->async_err > 0) {
		pr_err("%s: DSP returned error[%s] handle = %d\n", __func__,
		       adsp_err_get_err_str(v->async_err), cvp_handle);
		ret = adsp_err_get_lnx_err_code(v->async_err);
		goto done;
	}
	ret = 0;
done:
	return ret;
}

static int voice_send_cvp_channel_info_cmd(struct voice_data *v)
{
	int ret = 0;

	ret = voice_send_cvp_channel_info_v2(v, RX_PATH);
	if (ret < 0) {
		pr_err("%s: Error in sending cvp_channel_info RX: %d\n",
		       __func__, ret);
		goto done;
	}

	ret = voice_send_cvp_channel_info_v2(v, TX_PATH);
	if (ret < 0) {
		pr_err("%s: Error in sending cvp_channel_info TX: %d\n",
		       __func__, ret);
		goto done;
	}

	ret = voice_send_cvp_channel_info_v2(v, EC_REF_PATH);
	if (ret < 0) {
		pr_err("%s: Error in sending cvp_channel_info EC Ref: %d\n",
		       __func__, ret);
		goto done;
	}
done:
	return ret;
}

static int voice_send_cvp_mfc_config_v2(struct voice_data *v)
{
	int ret;
	struct cvp_set_mfc_config_cmd_v2 cvp_set_mfc_config_cmd;
	void *apr_cvp;
	u16 cvp_handle;
	struct vss_icommon_param_data_mfc_config_v2_t *cvp_config_param_data =
		&cvp_set_mfc_config_cmd.cvp_set_mfc_param_v2.param_data;
	struct vss_param_mfc_config_info_t *mfc_config_info =
		&cvp_config_param_data->mfc_config_info;

	if (v == NULL) {
		pr_err("%s: v is NULL\n", __func__);
		ret = -EINVAL;
		goto done;
	}

	apr_cvp  = common.apr_q6_cvp;
	if (!apr_cvp) {
		pr_err("%s: apr_cvp is NULL\n", __func__);
		ret = -EINVAL;
		goto done;
	}

	cvp_handle = voice_get_cvp_handle(v);
	memset(&cvp_set_mfc_config_cmd, 0, sizeof(cvp_set_mfc_config_cmd));

	cvp_set_mfc_config_cmd.hdr.hdr_field =
		APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
			      APR_PKT_VER);
	cvp_set_mfc_config_cmd.hdr.pkt_size =
		APR_PKT_SIZE(APR_HDR_SIZE,
		sizeof(cvp_set_mfc_config_cmd) - APR_HDR_SIZE);
	cvp_set_mfc_config_cmd.hdr.src_svc = 0;
	cvp_set_mfc_config_cmd.hdr.src_domain = APR_DOMAIN_APPS;
	cvp_set_mfc_config_cmd.hdr.src_port =
		voice_get_idx_for_session(v->session_id);
	cvp_set_mfc_config_cmd.hdr.dest_svc = 0;
	cvp_set_mfc_config_cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
	cvp_set_mfc_config_cmd.hdr.dest_port = cvp_handle;
	cvp_set_mfc_config_cmd.hdr.token = 0;
	cvp_set_mfc_config_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;
	cvp_set_mfc_config_cmd.cvp_set_mfc_param_v2.mem_size =
		sizeof(struct vss_icommon_param_data_mfc_config_v2_t);

	cvp_config_param_data->module_id = AUDPROC_MODULE_ID_MFC;
	cvp_config_param_data->param_id =
		AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
	cvp_config_param_data->param_size =
		sizeof(struct vss_param_mfc_config_info_t);

	mfc_config_info->num_channels = v->dev_rx.no_of_channels;
	mfc_config_info->bits_per_sample = 16;
	mfc_config_info->sample_rate = v->dev_rx.sample_rate;

	if (mfc_config_info->num_channels == NUM_CHANNELS_MONO) {
		mfc_config_info->channel_type[0] = PCM_CHANNEL_FC;
	} else if (mfc_config_info->num_channels == NUM_CHANNELS_STEREO) {
		mfc_config_info->channel_type[0] = PCM_CHANNEL_FL;
		mfc_config_info->channel_type[1] = PCM_CHANNEL_FR;
	} else {
		pr_err("%s: Unsupported num channels: %d\n",
		       __func__, mfc_config_info->num_channels);
		ret = -EINVAL;
		goto done;
	}

	v->cvp_state = CMD_STATUS_FAIL;
	v->async_err = 0;
	ret = apr_send_pkt(apr_cvp, (uint32_t *)&cvp_set_mfc_config_cmd);
	if (ret < 0) {
		pr_err("%s: Failed to send VSS_ICOMMON_CMD_SET_PARAM_V2 %d\n",
		       __func__, ret);
		goto done;
	}
	ret = wait_event_timeout(v->cvp_wait,
				(v->cvp_state == CMD_STATUS_SUCCESS),
				msecs_to_jiffies(TIMEOUT_MS));

	if (!ret) {
		pr_err("%s: wait_event timeout\n", __func__);
		ret = -ETIMEDOUT;
		goto done;
	}

	if (v->async_err > 0) {
		pr_err("%s: DSP returned error[%s] handle = %d\n", __func__,
		       adsp_err_get_err_str(v->async_err), cvp_handle);
		ret = adsp_err_get_lnx_err_code(v->async_err);
		goto done;
	}
	ret = 0;
done:
	return ret;
}

static int voice_send_cvp_mfc_config_cmd(struct voice_data *v)
{
	int ret = 0;

	if (common.cvp_version >= CVP_VERSION_2) {
		ret = voice_send_cvp_mfc_config_v2(v);
	} else {
		pr_warn("%s: CVP Version not supported\n", __func__);
		ret = -EINVAL;
	}

	return ret;
}

static int voice_get_avcs_version_per_service(uint32_t service_id)
{
	int ret = 0;
	size_t svc_size;
	struct avcs_fwk_ver_info ver_info = {{0}, NULL};

	if (service_id == AVCS_SERVICE_ID_ALL) {
		pr_err("%s: Invalid service id: %d", __func__,
		       AVCS_SERVICE_ID_ALL);
		return -EINVAL;
	}

	svc_size = sizeof(struct avs_svc_api_info);
	ver_info.services = kzalloc(svc_size, GFP_KERNEL);
	if (ver_info.services == NULL)
		return -ENOMEM;

	ret = q6core_get_service_version(service_id, &ver_info, svc_size);
	if (ret < 0)
		goto done;

	ret = ver_info.services[0].api_version;
	common.is_avcs_version_queried = true;
done:
	kfree(ver_info.services);
	return ret;
}

static int voice_setup_vocproc(struct voice_data *v)
{
	int ret = 0;
@@ -3803,6 +4101,18 @@ static int voice_setup_vocproc(struct voice_data *v)
		goto fail;
	}

	if (common.is_avcs_version_queried == false)
		common.cvp_version = voice_get_avcs_version_per_service(
				     APRV2_IDS_SERVICE_ID_ADSP_CVP_V);

	if (common.cvp_version < 0) {
		pr_err("%s: Invalid CVP version %d\n",
		       __func__, common.cvp_version);
		ret = -EINVAL;
		goto fail;
	}
	pr_debug("%s: CVP Version %d\n", __func__, common.cvp_version);

	ret = voice_send_cvp_media_fmt_info_cmd(v);
	if (ret < 0) {
		pr_err("%s: Set media format info failed err:%d\n", __func__,
@@ -3817,6 +4127,15 @@ static int voice_setup_vocproc(struct voice_data *v)
		goto fail;
	}

	/* Send MFC config only when the no of channels are more than 1 */
	if (v->dev_rx.no_of_channels > NUM_CHANNELS_MONO) {
		ret = voice_send_cvp_mfc_config_cmd(v);
		if (ret < 0) {
			pr_warn("%s: Set mfc config failed err:%d\n",
				__func__, ret);
		}
	}

	voice_send_cvs_register_cal_cmd(v);
	voice_send_cvp_register_dev_cfg_cmd(v);
	voice_send_cvp_register_cal_cmd(v);
@@ -3962,11 +4281,18 @@ static int voice_send_cvp_device_channels_cmd(struct voice_data *v)

static int voice_send_cvp_media_fmt_info_cmd(struct voice_data *v)
{
	int ret;
	int ret = 0;

	if (common.cvp_version < CVP_VERSION_2)
		ret = voice_send_cvp_device_channels_cmd(v);
	if (ret < 0)
	else
		ret = voice_send_cvp_channel_info_cmd(v);

	if (ret < 0) {
		pr_err("%s: Set channel info failed err: %d\n", __func__,
		       ret);
		goto done;
	}

	if (voice_get_cvd_int_version(common.cvd_version) >=
	    CVD_INT_VERSION_2_3) {
@@ -3994,7 +4320,7 @@ static int voice_send_cvp_media_format_cmd(struct voice_data *v,
	void *apr_cvp;
	u16 cvp_handle;
	struct vss_icommon_param_data_t *media_fmt_param_data =
		&cvp_set_media_format_cmd.cvp_set_param_v2.param_data;
		&cvp_set_media_format_cmd.cvp_set_media_param_v2.param_data;
	struct vss_param_endpoint_media_format_info_t *media_fmt_info =
		&media_fmt_param_data->media_format_info;

@@ -4032,7 +4358,7 @@ static int voice_send_cvp_media_format_cmd(struct voice_data *v,
	cvp_set_media_format_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;

	/* Fill param data */
	cvp_set_media_format_cmd.cvp_set_param_v2.mem_size =
	cvp_set_media_format_cmd.cvp_set_media_param_v2.mem_size =
		sizeof(struct vss_icommon_param_data_t);
	media_fmt_param_data->module_id = VSS_MODULE_CVD_GENERIC;
	media_fmt_param_data->param_size =
@@ -6197,6 +6523,15 @@ int voc_enable_device(uint32_t session_id)
			goto done;
		}

		/* Send MFC config only when the no of channels are > 1 */
		if (v->dev_rx.no_of_channels > NUM_CHANNELS_MONO) {
			ret = voice_send_cvp_mfc_config_cmd(v);
			if (ret < 0) {
				pr_warn("%s: Set mfc config failed err: %d\n",
					__func__, ret);
			}
		}

		voice_send_cvp_register_dev_cfg_cmd(v);
		voice_send_cvp_register_cal_cmd(v);
		voice_send_cvp_register_vol_cal_cmd(v);
@@ -7054,7 +7389,8 @@ static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv)
			case VSS_ICOMMON_CMD_SET_PARAM_V2:
				switch (data->token) {
				case VOC_SET_MEDIA_FORMAT_PARAM_TOKEN:
					pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2 called by voice_send_cvp_media_format_cmd\n",
				case VOC_GENERIC_SET_PARAM_TOKEN:
					pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2 called\n",
						__func__);
					v->cvp_state = CMD_STATUS_SUCCESS;
					v->async_err = ptr[1];
@@ -8566,7 +8902,8 @@ static int __init voice_init(void)
	common.default_vol_step_val = 0;
	common.default_vol_ramp_duration_ms = DEFAULT_VOLUME_RAMP_DURATION;
	common.default_mute_ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;

	common.cvp_version = 0;
	common.is_avcs_version_queried = false;
	/* Initialize EC Ref media format info */
	common.ec_ref_ext = false;
	common.ec_media_fmt_info.port_id = AFE_PORT_INVALID;
+116 −2
Original line number Diff line number Diff line
@@ -124,7 +124,7 @@ struct media_format_info {
};

enum {
	VOC_NO_SET_PARAM_TOKEN = 0,
	VOC_GENERIC_SET_PARAM_TOKEN = 0,
	VOC_RTAC_SET_PARAM_TOKEN,
	VOC_SET_MEDIA_FORMAT_PARAM_TOKEN,
	VOC_SET_PARAM_TOKEN_MAX
@@ -239,6 +239,19 @@ struct vss_param_endpoint_media_format_info_t {
	uint8_t channel_mapping[VSS_NUM_CHANNELS_MAX];
} __packed;

struct vss_param_vocproc_dev_channel_info_t {
	uint32_t num_channels;
	uint32_t bits_per_sample;
	uint8_t channel_mapping[VSS_NUM_CHANNELS_MAX];
} __packed;

struct vss_param_mfc_config_info_t {
	uint32_t sample_rate;
	uint16_t bits_per_sample;
	uint16_t num_channels;
	uint16_t channel_type[VSS_NUM_CHANNELS_MAX];
} __packed;

struct vss_icommon_param_data_t {
	/* Valid ID of the module. */
	uint32_t module_id;
@@ -260,6 +273,88 @@ struct vss_icommon_param_data_t {
	};
} __packed;

struct vss_icommon_param_data_channel_info_v2_t {
	/* Valid ID of the module. */
	uint32_t module_id;
	/* Valid ID of the parameter. */
	uint32_t param_id;
	/*
	 * Data size of the structure relating to the param_id/module_id
	 * combination in uint8_t bytes.
	 */
	uint16_t param_size;
	/* This field must be set to zero. */
	uint16_t reserved;
	struct vss_param_vocproc_dev_channel_info_t channel_info;
} __packed;

struct vss_icommon_cmd_set_param_channel_info_v2_t {
	/*
	 * Pointer to the unique identifier for an address (physical/virtual).
	 *
	 * If the parameter data payload is within the message payload
	 * (in-band), set this field to 0. The parameter data begins at the
	 * specified data payload address.
	 *
	 * If the parameter data is out-of-band, this field is the handle to
	 * the physical address in the shared memory that holds the parameter
	 * data.
	 */
	uint32_t mem_handle;
	/*
	 * Location of the parameter data payload.
	 *
	 * The payload is an array of vss_icommon_param_data_t. If the
	 * mem_handle is 0, this field is ignored.
	 */
	uint64_t mem_address;
	/* Size of the parameter data payload in bytes. */
	uint32_t mem_size;
	struct vss_icommon_param_data_channel_info_v2_t param_data;
} __packed;

struct vss_icommon_param_data_mfc_config_v2_t {
	/* Valid ID of the module. */
	uint32_t module_id;
	/* Valid ID of the parameter. */
	uint32_t param_id;
	/*
	 * Data size of the structure relating to the param_id/module_id
	 * combination in uint8_t bytes.
	 */
	uint16_t param_size;
	/* This field must be set to zero. */
	uint16_t reserved;
	struct vss_param_mfc_config_info_t mfc_config_info;
} __packed;

struct vss_icommon_cmd_set_param_mfc_config_v2_t {
	/*
	 * Pointer to the unique identifier for an address (physical/virtual).
	 *
	 * If the parameter data payload is within the message payload
	 * (in-band), set this field to 0. The parameter data begins at the
	 * specified data payload address.
	 *
	 * If the parameter data is out-of-band, this field is the handle to
	 * the physical address in the shared memory that holds the parameter
	 * data.
	 */

	uint32_t mem_handle;
	/*
	 * Location of the parameter data payload.
	 *
	 * The payload is an array of vss_icommon_param_data_t. If the
	 * mem_handle is 0, this field is ignored.
	 */
	uint64_t mem_address;
	/* Size of the parameter data payload in bytes. */
	uint32_t mem_size;

	struct vss_icommon_param_data_mfc_config_v2_t param_data;
} __packed;

/* Payload structure for the VSS_ICOMMON_CMD_SET_PARAM_V2 command. */
struct vss_icommon_cmd_set_param_v2_t {
	/*
@@ -674,6 +769,12 @@ struct vss_imemory_cmd_unmap_t {
#define VSS_IRECORD_MODE_TX_RX_MIXING			0x00010F7B
/* Select mixed Tx and Rx paths. */

#define VSS_PARAM_VOCPROC_TX_CHANNEL_INFO              0x0001328E

#define VSS_PARAM_VOCPROC_RX_CHANNEL_INFO              0x0001328F

#define VSS_PARAM_VOCPROC_EC_REF_CHANNEL_INFO          0x00013290

#define VSS_PARAM_TX_PORT_ENDPOINT_MEDIA_INFO		0x00013253

#define VSS_PARAM_RX_PORT_ENDPOINT_MEDIA_INFO		0x00013254
@@ -1485,7 +1586,18 @@ struct cvp_set_dev_channels_cmd {

struct cvp_set_media_format_cmd {
	struct apr_hdr hdr;
	struct vss_icommon_cmd_set_param_v2_t cvp_set_param_v2;
	struct vss_icommon_cmd_set_param_v2_t cvp_set_media_param_v2;
} __packed;

struct cvp_set_channel_info_cmd_v2 {
	struct apr_hdr hdr;
	struct vss_icommon_cmd_set_param_channel_info_v2_t
					cvp_set_ch_info_param_v2;
} __packed;

struct cvp_set_mfc_config_cmd_v2 {
	struct apr_hdr hdr;
	struct vss_icommon_cmd_set_param_mfc_config_v2_t cvp_set_mfc_param_v2;
} __packed;

struct cvp_set_vp3_data_cmd {
@@ -1756,6 +1868,8 @@ struct common_data {
	bool srvcc_rec_flag;
	bool is_destroy_cvd;
	char cvd_version[CVD_VERSION_STRING_MAX_SIZE];
	int cvp_version;
	bool is_avcs_version_queried;
	bool is_per_vocoder_cal_enabled;
	bool is_sound_focus_resp_success;
	bool is_source_tracking_resp_success;