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

Commit 50c55359 authored by Dieter Luecking's avatar Dieter Luecking
Browse files

dsp: Update ADM driver to support 32 ch



ADM supports now up to 32 channels. Extend the
ADM Channel map structures from 8 to 32
channels.

Change-Id: I87b3e4cce850af92467b139da9df67fcdafaf0b0
Signed-off-by: default avatarDieter Luecking <dieterl@codeaurora.org>
Signed-off-by: default avatarMangesh Kunchamwar <mangeshk@codeaurora.org>
parent fa7687b2
Loading
Loading
Loading
Loading
+485 −95
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <dsp/q6adm-v2.h>
#include <dsp/q6audio-v2.h>
#include <dsp/q6afe-v2.h>
#include <dsp/q6core.h>
#include <dsp/audio_cal_utils.h>
#include <dsp/q6common.h>
#include <ipc/apr.h>
@@ -104,23 +105,31 @@ struct adm_ctl {
	int num_ec_ref_rx_chans;
	int ec_ref_rx_bit_width;
	int ec_ref_rx_sampling_rate;

	int native_mode;
};

static struct adm_ctl			this_adm;

struct adm_multi_ch_map {
	bool set_channel_map;
	char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
	char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
};

#define ADM_MCH_MAP_IDX_PLAYBACK 0
#define ADM_MCH_MAP_IDX_REC 1
static struct adm_multi_ch_map multi_ch_maps[2] = {
			{ false,
							{0, 0, 0, 0, 0, 0, 0, 0}
			{0, 0, 0, 0, 0, 0, 0, 0,
			 0, 0, 0, 0, 0, 0, 0, 0,
			 0, 0, 0, 0, 0, 0, 0, 0,
			 0, 0, 0, 0, 0, 0, 0, 0}
			},
			{ false,
							{0, 0, 0, 0, 0, 0, 0, 0}
			{0, 0, 0, 0, 0, 0, 0, 0,
			 0, 0, 0, 0, 0, 0, 0, 0,
			 0, 0, 0, 0, 0, 0, 0, 0,
			 0, 0, 0, 0, 0, 0, 0, 0}
			}
};

@@ -1303,7 +1312,7 @@ int adm_set_multi_ch_map(char *channel_map, int path)
	}

	memcpy(multi_ch_maps[idx].channel_mapping, channel_map,
		PCM_FORMAT_MAX_NUM_CHANNEL);
			PCM_FORMAT_MAX_NUM_CHANNEL_V8);
	multi_ch_maps[idx].set_channel_map = true;

	return 0;
@@ -1334,7 +1343,7 @@ int adm_get_multi_ch_map(char *channel_map, int path)

	if (multi_ch_maps[idx].set_channel_map) {
		memcpy(channel_map, multi_ch_maps[idx].channel_mapping,
		       PCM_FORMAT_MAX_NUM_CHANNEL);
				PCM_FORMAT_MAX_NUM_CHANNEL_V8);
	}

	return 0;
@@ -1581,6 +1590,7 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
			case ADM_CMD_DEVICE_OPEN_V5:
			case ADM_CMD_DEVICE_CLOSE_V5:
			case ADM_CMD_DEVICE_OPEN_V6:
			case ADM_CMD_DEVICE_OPEN_V8:
				pr_debug("%s: Basic callback received, wake up.\n",
					__func__);
				atomic_set(&this_adm.copp.stat[port_idx]
@@ -1680,7 +1690,8 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)

		switch (data->opcode) {
		case ADM_CMDRSP_DEVICE_OPEN_V5:
		case ADM_CMDRSP_DEVICE_OPEN_V6: {
		case ADM_CMDRSP_DEVICE_OPEN_V6:
		case ADM_CMDRSP_DEVICE_OPEN_V8: {
			struct adm_cmd_rsp_device_open_v5 *open =
			(struct adm_cmd_rsp_device_open_v5 *)data->payload;

@@ -2514,6 +2525,225 @@ int adm_arrange_mch_ep2_map(struct adm_cmd_device_open_v6 *open_v6,
	return rc;
}

static int adm_arrange_mch_map_v8(
		struct adm_device_endpoint_payload *ep_payload,
		int path,
		int channel_mode)
{
	int rc = 0, idx;

	memset(ep_payload->dev_channel_mapping,
			0, PCM_FORMAT_MAX_NUM_CHANNEL_V8);
	switch (path) {
	case ADM_PATH_PLAYBACK:
		idx = ADM_MCH_MAP_IDX_PLAYBACK;
		break;
	case ADM_PATH_LIVE_REC:
	case ADM_PATH_NONLIVE_REC:
		idx = ADM_MCH_MAP_IDX_REC;
		break;
	default:
		goto non_mch_path;
	};

	if ((ep_payload->dev_num_channel > 2) &&
			multi_ch_maps[idx].set_channel_map) {
		memcpy(ep_payload->dev_channel_mapping,
			multi_ch_maps[idx].channel_mapping,
			PCM_FORMAT_MAX_NUM_CHANNEL_V8);
	} else {
		if (channel_mode == 1) {
			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
		} else if (channel_mode == 2) {
			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
		} else if (channel_mode == 3) {
			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
		} else if (channel_mode == 4) {
			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
		} else if (channel_mode == 5) {
			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
		} else if (channel_mode == 6) {
			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
			ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
		} else if (channel_mode == 7) {
			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LFE;
			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
			ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
			ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_CS;
		} else if (channel_mode == 8) {
			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
			ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
			ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
			ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
		} else if (channel_mode == 10) {
			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
			ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
			ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
			ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
			ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
			ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
		} else if (channel_mode == 12) {
			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
			ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
			ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
			ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
			ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
			ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
			ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
			ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
		} else if (channel_mode == 16) {
			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
			ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
			ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
			ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
			ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
			ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
			ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
			ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
			ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
			ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
			ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
			ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
		} else {
			pr_err("%s: invalid num_chan %d\n", __func__,
				channel_mode);
			rc = -EINVAL;
			goto inval_ch_mod;
		}
	}

non_mch_path:
inval_ch_mod:
	return rc;
}

static int adm_arrange_mch_ep2_map_v8(
		struct adm_device_endpoint_payload *ep_payload,
		int channel_mode)
{
	int rc = 0;

	memset(ep_payload->dev_channel_mapping, 0,
	       PCM_FORMAT_MAX_NUM_CHANNEL_V8);

	if (channel_mode == 1) {
		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
	} else if (channel_mode == 2) {
		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
	} else if (channel_mode == 3) {
		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
	} else if (channel_mode == 4) {
		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
	} else if (channel_mode == 5) {
		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
		ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
	} else if (channel_mode == 6) {
		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
		ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
		ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
	} else if (channel_mode == 8) {
		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
		ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
		ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
		ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
		ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
	}  else if (channel_mode == 10) {
		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
		ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
		ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
		ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
		ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
		ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
		ep_payload->dev_channel_mapping[9] = PCM_CHANNELS;
	} else if (channel_mode == 12) {
		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
		ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
		ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
		ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
		ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
		ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
		ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
		ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
		ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
	} else if (channel_mode == 16) {
		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
		ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
		ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
		ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
		ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
		ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
		ep_payload->dev_channel_mapping[9] = PCM_CHANNELS;
		ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
		ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
		ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
		ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
		ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
		ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
	} else {
		pr_err("%s: invalid num_chan %d\n", __func__,
			channel_mode);
		rc = -EINVAL;
	}

	return rc;
}
/**
 * adm_open -
 *        command to send ADM open
@@ -2535,10 +2765,17 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
{
	struct adm_cmd_device_open_v5	open;
	struct adm_cmd_device_open_v6	open_v6;
	struct adm_cmd_device_open_v8	open_v8;
	struct adm_device_endpoint_payload ep1_payload;
	struct adm_device_endpoint_payload ep2_payload;
	int ep1_payload_size = 0;
	int ep2_payload_size = 0;
	int ret = 0;
	int port_idx, flags;
	int copp_idx = -1;
	int tmp_port = q6audio_get_port_id(port_id);
	void *adm_params = NULL;
	int param_size;

	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,
@@ -2550,6 +2787,11 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
		pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
		return -EINVAL;
	}
	if (channel_mode < 0 || channel_mode > 32) {
		pr_err("%s: Invalid channel number 0x%x\n",
				__func__, channel_mode);
		return -EINVAL;
	}

	if (this_adm.apr == NULL) {
		this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
@@ -2649,14 +2891,142 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,

			atomic_set(&this_adm.mem_map_index, ADM_SRS_TRUMEDIA);
			msm_dts_srs_tm_ion_memmap(&this_adm.outband_memmap);
		res = adm_memory_map_regions(&this_adm.outband_memmap.paddr, 0,
			res = adm_memory_map_regions(
					&this_adm.outband_memmap.paddr, 0,
			(uint32_t *)&this_adm.outband_memmap.size, 1);
			if (res < 0) {
				pr_err("%s: SRS adm_memory_map_regions failed! addr = 0x%pK, size = %d\n",
			 __func__, (void *)this_adm.outband_memmap.paddr,
					__func__,
					(void *)this_adm.outband_memmap.paddr,
					(uint32_t)this_adm.outband_memmap.size);
			}
		}


		if (q6core_get_avcs_api_version_per_service(
				APRV2_IDS_SERVICE_ID_ADSP_ADM_V) >=
					ADSP_ADM_API_VERSION_V3) {
			memset(&open_v8, 0, sizeof(open_v8));
			memset(&ep1_payload, 0, sizeof(ep1_payload));
			memset(&ep2_payload, 0, sizeof(ep2_payload));

			open_v8.hdr.hdr_field = APR_HDR_FIELD(
					APR_MSG_TYPE_SEQ_CMD,
					APR_HDR_LEN(APR_HDR_SIZE),
					APR_PKT_VER);
			open_v8.hdr.src_svc = APR_SVC_ADM;
			open_v8.hdr.src_domain = APR_DOMAIN_APPS;
			open_v8.hdr.src_port = tmp_port;
			open_v8.hdr.dest_svc = APR_SVC_ADM;
			open_v8.hdr.dest_domain = APR_DOMAIN_ADSP;
			open_v8.hdr.dest_port = tmp_port;
			open_v8.hdr.token = port_idx << 16 | copp_idx;
			open_v8.hdr.opcode = ADM_CMD_DEVICE_OPEN_V8;

			if (this_adm.native_mode != 0) {
				open_v8.flags = flags |
					(this_adm.native_mode << 11);
				this_adm.native_mode = 0;
			} else {
				open_v8.flags = flags;
			}
			open_v8.mode_of_operation = path;
			open_v8.endpoint_id_1 = tmp_port;
			open_v8.endpoint_id_2 = 0xFFFF;
			open_v8.endpoint_id_3 = 0xFFFF;

			if (this_adm.ec_ref_rx && (path != 1)) {
				open_v8.endpoint_id_2 = this_adm.ec_ref_rx;
				this_adm.ec_ref_rx = -1;
			}

			open_v8.topology_id = topology;
			open_v8.reserved = 0;

			/* variable endpoint payload */
			ep1_payload.dev_num_channel = channel_mode & 0x00FF;
			ep1_payload.bit_width = bit_width;
			ep1_payload.sample_rate  = rate;
			ret = adm_arrange_mch_map_v8(&ep1_payload, path,
					channel_mode);
			if (ret)
				return ret;

			pr_debug("%s: port_id=0x%x %x %x topology_id=0x%X flags %x ref_ch %x\n",
				__func__, open_v8.endpoint_id_1,
				open_v8.endpoint_id_2,
				open_v8.endpoint_id_3,
				open_v8.topology_id,
				open_v8.flags,
				this_adm.num_ec_ref_rx_chans);

			ep1_payload_size = 8 +
				roundup(ep1_payload.dev_num_channel, 4);
			param_size = sizeof(struct adm_cmd_device_open_v8)
				+ ep1_payload_size;
			atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);

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

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

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

				pr_debug("%s: adm open_v8 eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
					__func__,
					ep2_payload.dev_num_channel,
					ep2_payload.bit_width,
					ep2_payload.sample_rate);

				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;
			}

			adm_params = kzalloc(param_size, GFP_KERNEL);
			if (!adm_params)
				return -ENOMEM;
			open_v8.hdr.pkt_size = param_size;
			memcpy(adm_params, &open_v8, sizeof(open_v8));
			memcpy(adm_params + sizeof(open_v8),
					(void *)&ep1_payload,
					ep1_payload_size);
			memcpy(adm_params + sizeof(open_v8)
					+ ep1_payload_size,
					(void *)&ep2_payload,
					ep2_payload_size);

			ret = apr_send_pkt(this_adm.apr,
					(uint32_t *)adm_params);
			if (ret < 0) {
				pr_err("%s: port_id: 0x%x for[0x%x] failed %d for open_v8\n",
					__func__, tmp_port, port_id, ret);
				return -EINVAL;
			}
			kfree(adm_params);
		} else {

			open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
				APR_HDR_LEN(APR_HDR_SIZE),
				APR_PKT_VER);
@@ -2698,8 +3068,8 @@ 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) && (path != 1) &&
			(open.endpoint_id_2 != 0xFFFF)) {
			if ((this_adm.num_ec_ref_rx_chans != 0) &&
				(path != 1) && (open.endpoint_id_2 != 0xFFFF)) {
				memset(&open_v6, 0,
					sizeof(struct adm_cmd_device_open_v6));
				memcpy(&open_v6, &open,
@@ -2737,15 +3107,19 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
				if (ret)
					return ret;

			ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open_v6);
				ret = apr_send_pkt(this_adm.apr,
					(uint32_t *)&open_v6);
			} else {
			ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
				ret = apr_send_pkt(this_adm.apr,
					(uint32_t *)&open);
			}
			if (ret < 0) {
				pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
					__func__, tmp_port, port_id, ret);
				return -EINVAL;
			}
		}

		/* Wait for the callback with copp id */
		ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
			atomic_read(&this_adm.copp.stat
@@ -3080,6 +3454,22 @@ void adm_ec_ref_rx_sampling_rate(int sampling_rate)
}
EXPORT_SYMBOL(adm_ec_ref_rx_sampling_rate);

/**
 * adm_set_native_mode -
 *      Set adm channel native mode.
 *      If enabled matrix mixer will be
 *      running in native mode for channel
 *      configuration for this device session.
 *
 */
void adm_set_native_mode(int mode)
{
	this_adm.native_mode = mode;
	pr_debug("%s: enable native_mode :%d\n",
		__func__, this_adm.native_mode);
}
EXPORT_SYMBOL(adm_set_native_mode);

/**
 * adm_close -
 *        command to close ADM copp
+4 −1
Original line number Diff line number Diff line
@@ -57,7 +57,9 @@ enum {
};

#define MAX_COPPS_PER_PORT 0x8
#define ADM_MAX_CHANNELS 8
#define ADM_MAX_CHANNELS 32

#define ADSP_ADM_API_VERSION_V3 3

/* multiple copp per stream. */
struct route_payload {
@@ -208,4 +210,5 @@ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
			int channel_index);
void msm_dts_srs_acquire_lock(void);
void msm_dts_srs_release_lock(void);
void adm_set_native_mode(int mode);
#endif /* __Q6_ADM_V2_H__ */