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

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

Merge "dsp: adm: support adm open with ec_ref info"

parents 6eab62a0 b1950d5c
Loading
Loading
Loading
Loading
+206 −76
Original line number Diff line number Diff line
@@ -3006,15 +3006,21 @@ static int adm_arrange_mch_ep2_map_v8(
	return rc;
}

static int adm_copp_set_ec_ref_mfc_cfg(int port_id, int copp_idx,
static int adm_copp_set_ec_ref_mfc_cfg_v2(int port_id, int copp_idx,
					int sample_rate, int bps,
					int in_channels, int out_channels)
					struct msm_pcm_channel_mixer *cfg)
{
	struct audproc_mfc_param_media_fmt mfc_cfg;
	struct param_hdr_v3 param_hdr;
	u16 *chmixer_params = NULL;
	int rc = 0, i = 0, j = 0, param_index = 0, param_size = 0;
	struct adm_device_endpoint_payload ep_payload = {0, 0, 0, {0} };
	int in_channels, out_channels;

	if (!cfg)
		return -EINVAL;
	in_channels = cfg->input_channel;
	out_channels = cfg->output_channel;

	memset(&mfc_cfg, 0, sizeof(mfc_cfg));
	memset(&ep_payload, 0, sizeof(ep_payload));
@@ -3028,7 +3034,8 @@ static int adm_copp_set_ec_ref_mfc_cfg(int port_id, int copp_idx,
			bps, in_channels, out_channels);

	if (out_channels <= 0 || out_channels > AUDPROC_MFC_OUT_CHANNELS_MAX) {
		pr_err("%s: unsupported out channels=%d\n", __func__, out_channels);
		pr_err("%s: unsupported out channels=%d\n",
			 __func__, out_channels);
		return -EINVAL;
	}

@@ -3041,67 +3048,121 @@ static int adm_copp_set_ec_ref_mfc_cfg(int port_id, int copp_idx,
	mfc_cfg.num_channels = out_channels;

	ep_payload.dev_num_channel = out_channels;
	if (cfg && cfg->override_out_ch_map) {
		for (i = 0; i < out_channels; i++) {
			ep_payload.dev_channel_mapping[i] = cfg->out_ch_map[i];
			pr_debug("%s: out_ch_map[%d] = %d",
				__func__, i, ep_payload.dev_channel_mapping[i]);
		}
	} else {
		rc = adm_arrange_mch_ep2_map_v8(&ep_payload, out_channels);
		if (rc < 0) {
			pr_err("%s: unable to get map for out channels=%d\n",
					__func__, out_channels);
			return -EINVAL;
		}
	}

	for (i = 0; i < out_channels; i++)
		mfc_cfg.channel_type[i] = (uint16_t) ep_payload.dev_channel_mapping[i];
		mfc_cfg.channel_type[i] =
			(uint16_t) ep_payload.dev_channel_mapping[i];


	rc = adm_pack_and_set_one_pp_param(port_id, copp_idx,
				param_hdr, (uint8_t *) &mfc_cfg);
	if (rc) {
		pr_err("%s: Failed to set media format, err %d\n", __func__, rc);
		pr_err("%s: Failed to set media format, err %d\n",
			 __func__, rc);
		return rc;
	}

	/* 2. Send Channel Mixer params */
	param_size =  2 * (4 + out_channels + in_channels + (out_channels * in_channels));
	param_size =  2 * (4 + out_channels + in_channels +
			 (out_channels * in_channels));
	param_size = round_up(param_size, 4);
	param_hdr.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
	param_hdr.param_size = param_size;

	pr_debug("%s: chmixer param sz = %d\n", __func__, param_size);
	chmixer_params = kzalloc(param_size, GFP_KERNEL);
	if (!chmixer_params) {
	if (!chmixer_params)
		return -ENOMEM;
	}
	param_index = 2; /* param[0] and [1] represents chmixer rule(always 0) */

	/* param[0] and [1] represents chmixer rule(always 0) */
	param_index = 2;
	chmixer_params[param_index++] = out_channels;
	chmixer_params[param_index++] = in_channels;

	/* output channel map is same as one set in media format */
	for (i = 0; i < out_channels; i++)
		chmixer_params[param_index++] = ep_payload.dev_channel_mapping[i];
		chmixer_params[param_index++] =
			 ep_payload.dev_channel_mapping[i];

	/* input channel map should be same as one set for ep2 during copp open */
	/* input chmap should be same as one set for ep2 during copp open */
	ep_payload.dev_num_channel = in_channels;
	if (cfg && cfg->override_in_ch_map) {
		for (i = 0; i < in_channels; i++) {
			ep_payload.dev_channel_mapping[i] = cfg->in_ch_map[i];
			pr_debug("%s: in_ch_map[%d] = %d",
				__func__, i, ep_payload.dev_channel_mapping[i]);
		}
	} else {
		rc = adm_arrange_mch_ep2_map_v8(&ep_payload, in_channels);
		if (rc < 0) {
			pr_err("%s: unable to get in channal map\n", __func__);
			goto exit;
		}
	}
	for (i = 0; i < in_channels; i++)
		chmixer_params[param_index++] = ep_payload.dev_channel_mapping[i];
		chmixer_params[param_index++] =
			 ep_payload.dev_channel_mapping[i];

	for (i = 0; i < out_channels; i++)
		for (j = 0; j < in_channels; j++)
		chmixer_params[param_index++] = this_adm.ec_ref_chmixer_weights[i][j];
		for (j = 0; j < in_channels; j++) {
		chmixer_params[param_index++] = cfg->channel_weight[i][j];
		pr_debug("%s: ch_weight[%d][%d] = %d\n",
					 __func__, i, j, cfg->channel_weight[i][j]);
		}

	rc = adm_pack_and_set_one_pp_param(port_id, copp_idx,
				param_hdr, (uint8_t *) chmixer_params);
	if (rc)
		pr_err("%s: Failed to set chmixer params, err %d\n", __func__, rc);
		pr_err("%s: Failed to set chmixer params, err %d\n",
				 __func__, rc);

exit:
	kfree(chmixer_params);
	return rc;
}


static int adm_copp_set_ec_ref_mfc_cfg(int port_id, int copp_idx,
					int sample_rate, int bps,
					int in_channels, int out_channels)
{
	struct msm_pcm_channel_mixer *cfg = NULL;
	int rc =0, i, j;

	cfg =kzalloc(sizeof(struct msm_pcm_channel_mixer),
			GFP_KERNEL);
	if (!cfg) {
		pr_err("%s: fail to allocate memory\n", __func__);
		return -ENOMEM;
	}

	cfg->input_channel = in_channels;
	cfg->output_channel = out_channels;
	for (i = 0; i < out_channels; i++)
		for (j = 0; j < in_channels; j++)
			cfg->channel_weight[i][j] =
				this_adm.ec_ref_chmixer_weights[i][j];

	rc = adm_copp_set_ec_ref_mfc_cfg_v2(port_id, copp_idx,
					sample_rate, bps, cfg);
	kfree(cfg);
	return rc;
}

/**
 * adm_open -
 *        command to send ADM open
@@ -3122,6 +3183,38 @@ static int adm_copp_set_ec_ref_mfc_cfg(int port_id, int copp_idx,
int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
	     int perf_mode, uint16_t bit_width, int app_type, int acdb_id,
	     int session_type, uint32_t passthr_mode, uint32_t copp_token)
{
	return adm_open_v2(port_id, path, rate, channel_mode, topology,
			perf_mode, bit_width, app_type, acdb_id,
			session_type, passthr_mode, copp_token,
			NULL, NULL);
}
EXPORT_SYMBOL(adm_open);

/**
 * adm_open_v2 -
 *        command to send ADM open with ec_ref config
 *
 * @port_id: port id number
 * @path: direction or ADM path type
 * @rate: sample rate of session
 * @channel_mode: number of channels set
 * @topology: topology active for this session
 * @perf_mode: performance mode like LL/ULL/..
 * @bit_width: bit width to set for copp
 * @app_type: App type used for this session
 * @acdb_id: ACDB ID of this device
 * @session_type: type of session
 * @ec_ref_port_cfg: ec_ref port configuration
 * @ec_ref_chmix_cfg: ec_ref channel mixer configuration
 *
 * Returns 0 on success or error on failure
 */
int adm_open_v2(int port_id, int path, int rate, int channel_mode, int topology,
	     int perf_mode, uint16_t bit_width, int app_type, int acdb_id,
	     int session_type, uint32_t passthr_mode, uint32_t copp_token,
	     struct msm_ec_ref_port_cfg *ec_ref_port_cfg,
	    struct msm_pcm_channel_mixer *ec_ref_chmix_cfg)
{
	struct adm_cmd_device_open_v5	open;
	struct adm_cmd_device_open_v6	open_v6;
@@ -3136,7 +3229,23 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
	int tmp_port = q6audio_get_port_id(port_id);
	void *adm_params = NULL;
	int param_size;
	int num_ec_ref_rx_chans = this_adm.num_ec_ref_rx_chans;
	int i;

	int ec_ref_port_id = ec_ref_port_cfg ?
					ec_ref_port_cfg->port_id :
					this_adm.ec_ref_rx;

	int ec_ref_ch = ec_ref_port_cfg ?
					ec_ref_port_cfg->ch :
					this_adm.num_ec_ref_rx_chans;

	int ec_ref_bit = ec_ref_port_cfg ?
					ec_ref_port_cfg->bit_width :
					this_adm.ec_ref_rx_bit_width;

	int ec_ref_sampling_rate = ec_ref_port_cfg ?
					ec_ref_port_cfg->sampling_rate :
					this_adm.ec_ref_rx_sampling_rate;

	pr_debug("%s:port %#x path:%d rate:%d mode:%d perf_mode:%d,topo_id %d\n",
		 __func__, port_id, path, rate, channel_mode, perf_mode,
@@ -3227,7 +3336,8 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
		copp_idx = adm_get_idx_if_copp_exists(port_idx, topology,
						      perf_mode,
						      rate, bit_width,
						      app_type, session_type, copp_token);
						      app_type, session_type,
						      copp_token);

	if (copp_idx < 0) {
		copp_idx = adm_get_next_available_copp(port_idx);
@@ -3324,17 +3434,16 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
			open_v8.endpoint_id_2 = 0xFFFF;
			open_v8.endpoint_id_3 = 0xFFFF;

			if (((this_adm.ec_ref_rx & AFE_PORT_INVALID) !=
			if (((ec_ref_port_id & AFE_PORT_INVALID) !=
				AFE_PORT_INVALID) &&
				(path != ADM_PATH_PLAYBACK)) {
				if (this_adm.num_ec_ref_rx_chans != 0) {
				if (ec_ref_ch != 0) {
					open_v8.endpoint_id_2 =
						this_adm.ec_ref_rx;
					this_adm.ec_ref_rx = AFE_PORT_INVALID;
						ec_ref_port_id;
					ec_ref_port_id = AFE_PORT_INVALID;
				} else {
					pr_err("%s: EC channels not set %d\n",
						__func__,
						this_adm.num_ec_ref_rx_chans);
						__func__, ec_ref_ch);
					return -EINVAL;
				}
			}
@@ -3367,25 +3476,22 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
				+ ep1_payload_size;
			atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);

			if ((this_adm.num_ec_ref_rx_chans != 0)
			if ((ec_ref_ch != 0)
				&& (path != ADM_PATH_PLAYBACK)
				&& (open_v8.endpoint_id_2 != 0xFFFF)) {
				ep2_payload.dev_num_channel =
					this_adm.num_ec_ref_rx_chans;
					ec_ref_ch;

				if (this_adm.ec_ref_rx_bit_width != 0) {
					ep2_payload.bit_width =
						this_adm.ec_ref_rx_bit_width;
				} else {
				if (ec_ref_bit != 0)
					ep2_payload.bit_width = ec_ref_bit;
				else
					ep2_payload.bit_width = bit_width;
				}

				if (this_adm.ec_ref_rx_sampling_rate != 0) {
				if (ec_ref_sampling_rate != 0)
					ep2_payload.sample_rate =
					this_adm.ec_ref_rx_sampling_rate;
				} else {
						ec_ref_sampling_rate;
				else
					ep2_payload.sample_rate = rate;
				}

				pr_debug("%s: adm open_v8 eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
					__func__,
@@ -3393,11 +3499,22 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
					ep2_payload.bit_width,
					ep2_payload.sample_rate);

				ret = adm_arrange_mch_ep2_map_v8(&ep2_payload,
				if (ec_ref_chmix_cfg &&
					ec_ref_chmix_cfg->override_in_ch_map) {
					for (i = 0; i < ec_ref_ch; i++) {
						ep2_payload.dev_channel_mapping[i] =
							ec_ref_chmix_cfg->in_ch_map[i];
						pr_debug("%s: in_ch_map[%d] = %d",
							__func__, i,
							ep2_payload.dev_channel_mapping[i]);
					}
				} else {
					ret = adm_arrange_mch_ep2_map_v8(
						&ep2_payload,
						ep2_payload.dev_num_channel);

					if (ret)
						return ret;
				}
				ep2_payload_size = 8 +
					roundup(ep2_payload.dev_num_channel, 4);
				param_size += ep2_payload_size;
@@ -3412,7 +3529,7 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
					(void *)&ep1_payload,
					ep1_payload_size);

			if ((this_adm.num_ec_ref_rx_chans != 0)
			if ((ec_ref_ch != 0)
				&& (path != ADM_PATH_PLAYBACK)
				&& (open_v8.endpoint_id_2 != 0xFFFF)) {
				memcpy(adm_params + sizeof(open_v8)
@@ -3473,7 +3590,7 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,

			atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);

			if ((this_adm.num_ec_ref_rx_chans != 0) &&
			if ((ec_ref_ch != 0) &&
				(path != 1) && (open.endpoint_id_2 != 0xFFFF)) {
				memset(&open_v6, 0,
					sizeof(struct adm_cmd_device_open_v6));
@@ -3482,21 +3599,18 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
				open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
				open_v6.hdr.pkt_size = sizeof(open_v6);
				open_v6.dev_num_channel_eid2 =
					this_adm.num_ec_ref_rx_chans;
					ec_ref_ch;

				if (this_adm.ec_ref_rx_bit_width != 0) {
					open_v6.bit_width_eid2 =
						this_adm.ec_ref_rx_bit_width;
				} else {
				if (ec_ref_bit != 0)
					open_v6.bit_width_eid2 = ec_ref_bit;
				else
					open_v6.bit_width_eid2 = bit_width;
				}

				if (this_adm.ec_ref_rx_sampling_rate != 0) {
				if (ec_ref_sampling_rate != 0)
					open_v6.sample_rate_eid2 =
					       this_adm.ec_ref_rx_sampling_rate;
				} else {
						ec_ref_sampling_rate;
				else
					open_v6.sample_rate_eid2 = rate;
				}

				pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
					__func__, open_v6.dev_num_channel_eid2,
@@ -3527,24 +3641,40 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
	atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);

	/*
	 * Configure MFC(in ec_ref path) if chmixing param is applicable and set.
	 * Except channels and channel maps the media format config for this module
	 * should match with the COPP(EP1) config values.
	 * Configure MFC(in ec_ref path) if chmix param is applicable and set.
	 * Except channels and channel maps the media format config for this
	 * module should match with the COPP(EP1) config values.
	 */
	if (ec_ref_chmix_cfg) {
		if (path != ADM_PATH_PLAYBACK &&
			ec_ref_chmix_cfg->output_channel != 0 &&
			ec_ref_chmix_cfg->input_channel !=
				ec_ref_chmix_cfg->output_channel) {
			ret = adm_copp_set_ec_ref_mfc_cfg_v2(port_id, copp_idx,
					rate, bit_width, ec_ref_chmix_cfg);
			ec_ref_chmix_cfg->output_channel = 0;
			if (ret)
				pr_err("%s: set EC REF MFC cfg v2 failed, err %d\n",
				__func__, ret);
		}
	} else {
		if (path != ADM_PATH_PLAYBACK &&
			this_adm.num_ec_ref_rx_chans_downmixed != 0 &&
		num_ec_ref_rx_chans != this_adm.num_ec_ref_rx_chans_downmixed) {
			this_adm.num_ec_ref_rx_chans !=
				this_adm.num_ec_ref_rx_chans_downmixed) {
			ret = adm_copp_set_ec_ref_mfc_cfg(port_id, copp_idx,
				rate, bit_width, num_ec_ref_rx_chans,
				rate, bit_width, this_adm.num_ec_ref_rx_chans,
				this_adm.num_ec_ref_rx_chans_downmixed);
			this_adm.num_ec_ref_rx_chans_downmixed = 0;
			if (ret)
			pr_err("%s: set EC REF MFC cfg failed, err %d\n", __func__, ret);
				pr_err("%s: set EC REF MFC cfg failed, err %d\n",
					__func__, ret);
		}
	}

	return copp_idx;
}
EXPORT_SYMBOL(adm_open);
EXPORT_SYMBOL(adm_open_v2);

/**
 * adm_copp_mfc_cfg -
+15 −0
Original line number Diff line number Diff line
@@ -55,6 +55,14 @@ enum {

#define ADSP_ADM_API_VERSION_V3 3

struct msm_ec_ref_port_cfg {
	int rx;
	int port_id;
	int ch;
	int bit_width;
	int sampling_rate;
};

/* multiple copp per stream. */
struct route_payload {
	unsigned int copp_idx[MAX_COPPS_PER_PORT];
@@ -122,6 +130,13 @@ int adm_open(int port, int path, int rate, int mode, int topology,
			   int app_type, int acdbdev_id, int session_type,
			   uint32_t pass_thr, uint32_t copp_token);

int adm_open_v2(int port, int path, int rate, int mode, int topology,
			   int perf_mode, uint16_t bits_per_sample,
			   int app_type, int acdbdev_id, int session_type,
			   uint32_t pass_thr, uint32_t copp_token,
			   struct msm_ec_ref_port_cfg *ec_ref_port_cfg,
			   struct msm_pcm_channel_mixer *ec_ref_chmix_cfg);

int adm_map_rtac_block(struct rtac_cal_block_data *cal_block);

int adm_unmap_rtac_block(uint32_t *mem_map_handle);