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: Dieter Luecking <dieterl@codeaurora.org>
Signed-off-by: Mangesh Kunchamwar <mangeshk@codeaurora.org>
Signed-off-by: Dhanalakshmi Siddani <dsiddani@codeaurora.org>
diff --git a/dsp/q6adm.c b/dsp/q6adm.c
index c313fdc..3877b1b 100644
--- a/dsp/q6adm.c
+++ b/dsp/q6adm.c
@@ -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 <ipc/apr.h>
 #include "adsp_err.h"
@@ -105,24 +106,32 @@
 	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}
-							},
-							{ false,
-							{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}
+			},
+			{ 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}
+			}
 };
 
 static struct adm_multi_ch_map port_channel_map[AFE_MAX_PORTS];
@@ -1423,7 +1432,7 @@
 	}
 
 	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;
@@ -1454,7 +1463,7 @@
 
 	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;
@@ -1622,6 +1631,7 @@
 			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]
@@ -1718,8 +1728,10 @@
 
 		switch (data->opcode) {
 		case ADM_CMDRSP_DEVICE_OPEN_V5:
-		case ADM_CMDRSP_DEVICE_OPEN_V6: {
-			struct adm_cmd_rsp_device_open_v5 *open = NULL;
+		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;
 
 			if (data->payload_size <
 				sizeof(struct adm_cmd_rsp_device_open_v5)) {
@@ -2643,6 +2655,225 @@
 	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
@@ -2665,10 +2896,17 @@
 {
 	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,
@@ -2680,6 +2918,11 @@
 		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,
@@ -2776,111 +3019,241 @@
 	if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) == 0) {
 		pr_debug("%s: open ADM: port_idx: %d, copp_idx: %d\n", __func__,
 			 port_idx, copp_idx);
-	if ((topology == SRS_TRUMEDIA_TOPOLOGY_ID) &&
-	     perf_mode == LEGACY_PCM_MODE) {
-		int res;
+		if ((topology == SRS_TRUMEDIA_TOPOLOGY_ID) &&
+		      perf_mode == LEGACY_PCM_MODE) {
+			int res;
 
-		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,
-		(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,
-		(uint32_t)this_adm.outband_memmap.size);
-		}
-	}
-		open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
-						   APR_HDR_LEN(APR_HDR_SIZE),
-						   APR_PKT_VER);
-		open.hdr.pkt_size = sizeof(open);
-		open.hdr.src_svc = APR_SVC_ADM;
-		open.hdr.src_domain = APR_DOMAIN_APPS;
-		open.hdr.src_port = tmp_port;
-		open.hdr.dest_svc = APR_SVC_ADM;
-		open.hdr.dest_domain = APR_DOMAIN_ADSP;
-		open.hdr.dest_port = tmp_port;
-		open.hdr.token = port_idx << 16 | copp_idx;
-		open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
-		open.flags = flags;
-		open.mode_of_operation = path;
-		open.endpoint_id_1 = tmp_port;
-		open.endpoint_id_2 = 0xFFFF;
-
-		if (this_adm.ec_ref_rx && (path != 1) &&
-		    (afe_get_port_type(tmp_port) == MSM_AFE_PORT_TYPE_TX)) {
-			open.endpoint_id_2 = this_adm.ec_ref_rx;
-			this_adm.ec_ref_rx = -1;
+			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,
+			(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,
+					(uint32_t)this_adm.outband_memmap.size);
+			}
 		}
 
-		open.topology_id = topology;
 
-		open.dev_num_channel = channel_mode & 0x00FF;
-		open.bit_width = bit_width;
-		WARN_ON((perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) &&
-			(rate != ULL_SUPPORTED_SAMPLE_RATE));
-		open.sample_rate  = rate;
+		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));
 
-		ret = adm_arrange_mch_map(&open, path, channel_mode,
-					  port_idx);
+			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 (ret)
-			return ret;
-
-		pr_debug("%s: port_id=0x%x rate=%d topology_id=0x%X\n",
-			__func__, open.endpoint_id_1, open.sample_rate,
-			open.topology_id);
-
-		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)) {
-			memset(&open_v6, 0,
-				sizeof(struct adm_cmd_device_open_v6));
-			memcpy(&open_v6, &open,
-				sizeof(struct adm_cmd_device_open_v5));
-			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;
-			this_adm.num_ec_ref_rx_chans = 0;
-
-			if (this_adm.ec_ref_rx_bit_width != 0) {
-				open_v6.bit_width_eid2 =
-					this_adm.ec_ref_rx_bit_width;
-				this_adm.ec_ref_rx_bit_width = 0;
+			if (this_adm.native_mode != 0) {
+				open_v8.flags = flags |
+					(this_adm.native_mode << 11);
+				this_adm.native_mode = 0;
 			} else {
-				open_v6.bit_width_eid2 = bit_width;
+				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;
 			}
 
-			if (this_adm.ec_ref_rx_sampling_rate != 0) {
-				open_v6.sample_rate_eid2 =
-					this_adm.ec_ref_rx_sampling_rate;
-				this_adm.ec_ref_rx_sampling_rate = 0;
-			} else {
-				open_v6.sample_rate_eid2 = rate;
-			}
+			open_v8.topology_id = topology;
+			open_v8.reserved = 0;
 
-			pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
-				__func__, open_v6.dev_num_channel_eid2,
-				open_v6.bit_width_eid2,
-				open_v6.sample_rate_eid2);
-
-			ret = adm_arrange_mch_ep2_map(&open_v6,
-				open_v6.dev_num_channel_eid2);
-
+			/* 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;
 
-			ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open_v6);
+			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 {
-			ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
+
+			open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE),
+				APR_PKT_VER);
+			open.hdr.pkt_size = sizeof(open);
+			open.hdr.src_svc = APR_SVC_ADM;
+			open.hdr.src_domain = APR_DOMAIN_APPS;
+			open.hdr.src_port = tmp_port;
+			open.hdr.dest_svc = APR_SVC_ADM;
+			open.hdr.dest_domain = APR_DOMAIN_ADSP;
+			open.hdr.dest_port = tmp_port;
+			open.hdr.token = port_idx << 16 | copp_idx;
+			open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
+			open.flags = flags;
+			open.mode_of_operation = path;
+			open.endpoint_id_1 = tmp_port;
+			open.endpoint_id_2 = 0xFFFF;
+
+			if (this_adm.ec_ref_rx && (path != 1)) {
+				open.endpoint_id_2 = this_adm.ec_ref_rx;
+				this_adm.ec_ref_rx = -1;
+			}
+
+			open.topology_id = topology;
+
+			open.dev_num_channel = channel_mode & 0x00FF;
+			open.bit_width = bit_width;
+			WARN_ON((perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) &&
+				(rate != ULL_SUPPORTED_SAMPLE_RATE));
+			open.sample_rate  = rate;
+
+			ret = adm_arrange_mch_map(&open, path, channel_mode,
+						  port_idx);
+			if (ret)
+				return ret;
+
+			pr_debug("%s: port_id=0x%x rate=%d topology_id=0x%X\n",
+				__func__, open.endpoint_id_1, open.sample_rate,
+				open.topology_id);
+
+			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)) {
+				memset(&open_v6, 0,
+					sizeof(struct adm_cmd_device_open_v6));
+				memcpy(&open_v6, &open,
+					sizeof(struct adm_cmd_device_open_v5));
+				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;
+				this_adm.num_ec_ref_rx_chans = 0;
+
+				if (this_adm.ec_ref_rx_bit_width != 0) {
+					open_v6.bit_width_eid2 =
+						this_adm.ec_ref_rx_bit_width;
+					this_adm.ec_ref_rx_bit_width = 0;
+				} else {
+					open_v6.bit_width_eid2 = bit_width;
+				}
+
+				if (this_adm.ec_ref_rx_sampling_rate != 0) {
+					open_v6.sample_rate_eid2 =
+					       this_adm.ec_ref_rx_sampling_rate;
+					this_adm.ec_ref_rx_sampling_rate = 0;
+				} 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,
+					open_v6.bit_width_eid2,
+					open_v6.sample_rate_eid2);
+
+				ret = adm_arrange_mch_ep2_map(&open_v6,
+					open_v6.dev_num_channel_eid2);
+
+				if (ret)
+					return ret;
+
+				ret = apr_send_pkt(this_adm.apr,
+					(uint32_t *)&open_v6);
+			} else {
+				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;
+			}
 		}
-		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
@@ -3252,6 +3625,22 @@
 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
  *
diff --git a/dsp/q6core.c b/dsp/q6core.c
index ea4a169..b3a2e5c 100644
--- a/dsp/q6core.c
+++ b/dsp/q6core.c
@@ -540,6 +540,42 @@
 }
 EXPORT_SYMBOL(q6core_get_service_version);
 
+static int q6core_get_avcs_fwk_version(void)
+{
+        int ret = 0;
+
+        mutex_lock(&(q6core_lcl.ver_lock));
+        pr_debug("%s: q6core_avcs_ver_info.status(%d)\n", __func__,
+                 q6core_lcl.q6core_avcs_ver_info.status);
+
+        switch (q6core_lcl.q6core_avcs_ver_info.status) {
+        case VER_QUERY_SUPPORTED:
+                pr_debug("%s: AVCS FWK version query already attempted\n",
+                         __func__);
+                break;
+        case VER_QUERY_UNSUPPORTED:
+                ret = -EOPNOTSUPP;
+                break;
+        case VER_QUERY_UNATTEMPTED:
+                pr_debug("%s: Attempting AVCS FWK version query\n", __func__);
+                if (q6core_is_adsp_ready()) {
+                        ret = q6core_send_get_avcs_fwk_ver_cmd();
+                } else {
+                        pr_err("%s: ADSP is not ready to query version\n",
+                               __func__);
+                        ret = -ENODEV;
+                }
+                break;
+        default:
+                pr_err("%s: Invalid version query status %d\n", __func__,
+                       q6core_lcl.q6core_avcs_ver_info.status);
+                ret = -EINVAL;
+                break;
+        }
+        mutex_unlock(&(q6core_lcl.ver_lock));
+        return ret;
+}
+
 size_t q6core_get_fwk_version_size(uint32_t service_id)
 {
 	int ret = 0;
@@ -598,6 +634,42 @@
 EXPORT_SYMBOL(q6core_get_fwk_version_size);
 
 /**
+ * q6core_get_avcs_version_per_service -
+ *       to get api version of a particular service
+ *
+ * @service_id: id of the service
+ *
+ * Returns valid version on success or error (negative value) on failure
+ */
+int q6core_get_avcs_api_version_per_service(uint32_t service_id)
+{
+        struct avcs_fwk_ver_info *cached_ver_info = NULL;
+        int i;
+        uint32_t num_services;
+        int ret = 0;
+
+        if (service_id == AVCS_SERVICE_ID_ALL)
+                return -EINVAL;
+
+        ret = q6core_get_avcs_fwk_version();
+        if (ret < 0) {
+                pr_err("%s: failure in getting AVCS version\n", __func__);
+                return ret;
+        }
+
+        cached_ver_info = q6core_lcl.q6core_avcs_ver_info.ver_info;
+        num_services = cached_ver_info->avcs_fwk_version.num_services;
+
+        for (i = 0; i < num_services; i++) {
+                if (cached_ver_info->services[i].service_id == service_id)
+                        return cached_ver_info->services[i].api_version;
+        }
+        pr_err("%s: No service matching service ID %d\n", __func__, service_id);
+        return -EINVAL;
+}
+EXPORT_SYMBOL(q6core_get_avcs_api_version_per_service);
+
+/**
  * core_set_license -
  *       command to set license for module
  *
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index 64380a5..ef24f63 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -111,6 +111,17 @@
  */
 #define ADM_CMD_DEVICE_OPEN_V6                      0x00010356
 
+/* This command allows a client to open a COPP/Voice Proc the
+*	way as ADM_CMD_DEVICE_OPEN_V8 but supports any number channel
+*	of configuration.
+*
+*	@return
+*	#ADM_CMDRSP_DEVICE_OPEN_V8 with the resulting status and
+*	COPP ID.
+*/
+#define ADM_CMD_DEVICE_OPEN_V8                      0x0001036A
+
+
 /* Definition for a low latency stream session. */
 #define ADM_LOW_LATENCY_DEVICE_SESSION			0x2000
 
@@ -389,6 +400,110 @@
  */
 } __packed;
 
+
+/* ADM device open endpoint payload the
+ *   #ADM_CMD_DEVICE_OPEN_V8 command.
+ */
+struct adm_device_endpoint_payload {
+	u16                  dev_num_channel;
+/* Number of channels the audio COPP sends to/receives from
+ * the endpoint.
+ * Supported values: 1 to 32.
+ * The value is ignored for the voice processor Tx block,
+ * where channel
+ * configuration is derived from the topology ID.
+ */
+
+	u16                  bit_width;
+/* Bit width (in bits) that the audio COPP sends to/receives
+ * from the
+ * endpoint. The value is ignored for the voice processing
+ * Tx block,
+ * where the PCM width is 16 bits.
+ */
+
+	u32                  sample_rate;
+/* Sampling rate at which the audio COPP/voice processor
+ * Tx block
+ * interfaces with the endpoint.
+ * Supported values for voice processor Tx: 8000, 16000,
+ * 48000 Hz
+ * Supported values for audio COPP: >0 and <=192 kHz
+ */
+
+	u8                    dev_channel_mapping[32];
+} __packed;
+
+/*  ADM device open command payload of the
+ *   #ADM_CMD_DEVICE_OPEN_V8 command.
+ */
+struct adm_cmd_device_open_v8 {
+	struct apr_hdr       hdr;
+	u16                  flags;
+/* Bit width Native mode enabled : 11th bit of flag parameter
+*  If 11th bit of flag is set then that means matrix mixer will be
+*  running in native mode for bit width for this device session.
+*
+*  Channel Native mode enabled : 12th bit of flag parameter
+*  If 12th bit of flag is set then that means matrix mixer will be
+*  running in native mode for channel configuration for this device session.
+*  All other bits are reserved; clients must set them to 0.
+*/
+	u16                  mode_of_operation;
+/* Specifies whether the COPP must be opened on the Tx or Rx
+ * path. Use the ADM_CMD_COPP_OPEN_MODE_OF_OPERATION_* macros for
+ * supported values and interpretation.
+ * Supported values:
+ * - 0x1 -- Rx path COPP
+ * - 0x2 -- Tx path live COPP
+ * - 0x3 -- Tx path nonlive COPP
+ * Live connections cause sample discarding in the Tx device
+ * matrix if the destination output ports do not pull them
+ * fast enough. Nonlive connections queue the samples
+ * indefinitely.
+ */
+	u32                  topology_id;
+/* Audio COPP topology ID; 32-bit GUID. */
+
+
+	u16                  endpoint_id_1;
+/* Logical and physical endpoint ID of the audio path.
+ * If the ID is a voice processor Tx block, it receives near
+ * samples.
+ * Supported values: Any pseudoport, AFE Rx port,
+ * or AFE Tx port For a list of valid IDs, refer to
+ * @xhyperref{Q4,[Q4]}.
+ * Q4 = Hexagon Multimedia: AFE Interface Specification
+ */
+
+	u16                  endpoint_id_2;
+/* Logical and physical endpoint ID 2 for a voice processor
+ * Tx block.
+ * This is not applicable to audio COPP.
+ * Supported values:
+ * - AFE Rx port
+ * - 0xFFFF -- Endpoint 2 is unavailable and the voice
+ * processor Tx
+ * block ignores this endpoint
+ * When the voice processor Tx block is created on the audio
+ * record path,
+ * it can receive far-end samples from an AFE Rx port if the
+ * voice call
+ * is active. The ID of the AFE port is provided in this
+ * field.
+ * For a list of valid IDs, refer @xhyperref{Q4,[Q4]}.
+ */
+
+	u16                  endpoint_id_3;
+/*
+ * Logical and physical endpoint ID of the audio path.
+ * This indicated afe rx port in ADM loopback use cases.
+ * In all other use cases this should be set to 0xffff
+ */
+
+	u16                  reserved;
+} __packed;
+
 /*
  *	This command allows the client to close a COPP and disconnect
  *	the device session.
@@ -530,6 +645,9 @@
 /* Returns the status and COPP ID to an #ADM_CMD_DEVICE_OPEN_V6 command. */
 #define ADM_CMDRSP_DEVICE_OPEN_V6                      0x00010357
 
+/* Returns the status and COPP ID to an #ADM_CMD_DEVICE_OPEN_V8 command. */
+#define ADM_CMDRSP_DEVICE_OPEN_V8                      0x0001036B
+
 /*  Payload of the #ADM_CMDRSP_DEVICE_OPEN_V6 message,
  *	which returns the
  *	status and COPP ID to an #ADM_CMD_DEVICE_OPEN_V6 command
@@ -4333,17 +4451,82 @@
  */
 #define PCM_CHANNEL_RRC  16
 
-/* Max valid channel map index */
+/* Second low frequency channel. */
+#define PCM_CHANNEL_LFE2 17
+
+/* Side left channel. */
+#define PCM_CHANNEL_SL   18
+
+/* Side right channel. */
+#define PCM_CHANNEL_SR   19
+
+/* Top front left channel. */
+#define PCM_CHANNEL_TFL  20
+
+/* Left vertical height channel. */
+#define PCM_CHANNEL_LVH  20
+
+/* Top front right channel. */
+#define PCM_CHANNEL_TFR  21
+
+/* Right vertical height channel. */
+#define PCM_CHANNEL_RVH  21
+
+/* Top center channel. */
+#define PCM_CHANNEL_TC   22
+
+/* Top back left channel. */
+#define PCM_CHANNEL_TBL  23
+
+/* Top back right channel. */
+#define PCM_CHANNEL_TBR  24
+
+/* Top side left channel. */
+#define PCM_CHANNEL_TSL  25
+
+/* Top side right channel. */
+#define PCM_CHANNEL_TSR  26
+
+/* Top back center channel. */
+#define PCM_CHANNEL_TBC  27
+
+/* Bottom front center channel. */
+#define PCM_CHANNEL_BFC  28
+
+/* Bottom front left channel. */
+#define PCM_CHANNEL_BFL  29
+
+/* Bottom front right channel. */
+#define PCM_CHANNEL_BFR  30
+
+/* Left wide channel. */
+#define PCM_CHANNEL_LW   31
+
+/* Right wide channel. */
+#define PCM_CHANNEL_RW   32
+
+/* Left side direct channel. */
+#define PCM_CHANNEL_LSD  33
+
+
+/* Right side direct channel. */
+#define PCM_CHANNEL_RSD  34
+
 #define PCM_MAX_CHMAP_ID PCM_CHANNEL_RRC
 
 #define PCM_FORMAT_MAX_NUM_CHANNEL  8
 
+/* Used for ADM_CMD_DEVICE_OPEN_V8 */
+#define PCM_FORMAT_MAX_NUM_CHANNEL_V8  32
+
 #define ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2 0x00010DA5
 
 #define ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 0x00010DDC
 
 #define ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V4 0x0001320C
 
+#define ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V5 0x00013222
+
 #define ASM_MEDIA_FMT_EVRCB_FS 0x00010BEF
 
 #define ASM_MEDIA_FMT_EVRCWB_FS 0x00010BF0
@@ -4558,6 +4741,56 @@
  */
 } __packed;
 
+
+struct asm_multi_channel_pcm_fmt_blk_v5 {
+	uint16_t                num_channels;
+/*
+ * Number of channels
+ * Supported values: 1 to 32
+ */
+
+	uint16_t                bits_per_sample;
+/*
+ * Number of bits per sample per channel
+ * Supported values: 16, 24, 32
+ */
+
+	uint32_t                sample_rate;
+/*
+ * Number of samples per second
+ * Supported values: 2000 to 48000, 96000,192000 Hz
+ */
+
+	uint16_t                is_signed;
+/* Flag that indicates that PCM samples are signed (1) */
+
+	uint16_t                sample_word_size;
+/*
+ * Size in bits of the word that holds a sample of a channel.
+ * Supported values: 12,24,32
+ */
+	uint16_t                endianness;
+/*
+ * Flag to indicate the endianness of the pcm sample
+ * Supported values: 0 - Little endian (all other formats)
+ *                   1 - Big endian (AIFF)
+ */
+	uint16_t                mode;
+/*
+ * Mode to provide additional info about the pcm input data.
+ * Supported values: 0 - Default QFs (Q15 for 16b, Q23 for packed 24b,
+ *                       Q31 for unpacked 24b or 32b)
+ *                  15 - for 16 bit
+ *                  23 - for 24b packed or 8.24 format
+ *                  31 - for 24b unpacked or 32bit
+ */
+
+	uint8_t                 channel_mapping[32];
+/*
+ * Each element, i, in the array describes channel i inside the buffer where
+ * 0 <= i < num_channels. Unused channels are set to 0.
+ */
+} __packed;
 /*
  * Payload of the multichannel PCM configuration parameters in
  * the ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 media format.
@@ -4578,6 +4811,16 @@
 	struct asm_multi_channel_pcm_fmt_blk_v4 param;
 } __packed;
 
+/*
+ * Payload of the multichannel PCM configuration parameters in
+ * the ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V5 media format.
+ */
+struct asm_multi_channel_pcm_fmt_blk_param_v5 {
+	struct apr_hdr hdr;
+	struct asm_data_cmd_media_fmt_update_v2 fmt_blk;
+	struct asm_multi_channel_pcm_fmt_blk_v5 param;
+} __packed;
+
 struct asm_stream_cmd_set_encdec_param {
 	u32                  param_id;
 	/* ID of the parameter. */
@@ -4615,6 +4858,78 @@
 
 /*
  * Payload of the multichannel PCM encoder configuration parameters in
+ * the ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V5 media format.
+ */
+struct asm_multi_channel_pcm_enc_cfg_v5 {
+	struct apr_hdr hdr;
+	struct asm_stream_cmd_set_encdec_param encdec;
+	struct asm_enc_cfg_blk_param_v2 encblk;
+	uint16_t num_channels;
+/*
+ * Number of PCM channels.
+ * @values
+ * - 0 -- Native mode
+ * - 1 -- 8 channels
+ * Native mode indicates that encoding must be performed with the number
+ * of channels at the input.
+ */
+	uint16_t  bits_per_sample;
+/*
+ * Number of bits per sample per channel.
+ * @values 16, 24
+ */
+	uint32_t  sample_rate;
+/*
+ * Number of samples per second.
+ * @values 0, 8000 to 48000 Hz
+ * A value of 0 indicates the native sampling rate. Encoding is
+ * performed at the input sampling rate.
+ */
+	uint16_t  is_signed;
+/*
+ * Flag that indicates the PCM samples are signed (1). Currently, only
+ * signed PCM samples are supported.
+ */
+	uint16_t    sample_word_size;
+/*
+ * The size in bits of the word that holds a sample of a channel.
+ * @values 16, 24, 32
+ * 16-bit samples are always placed in 16-bit words:
+ * sample_word_size = 1.
+ * 24-bit samples can be placed in 32-bit words or in consecutive
+ * 24-bit words.
+ * - If sample_word_size = 32, 24-bit samples are placed in the
+ * most significant 24 bits of a 32-bit word.
+ * - If sample_word_size = 24, 24-bit samples are placed in
+ * 24-bit words. @tablebulletend
+ */
+	uint16_t                endianness;
+/*
+ * Flag to indicate the endianness of the pcm sample
+ * Supported values: 0 - Little endian (all other formats)
+ *                   1 - Big endian (AIFF)
+ */
+	uint16_t                mode;
+/*
+ * Mode to provide additional info about the pcm input data.
+ * Supported values: 0 - Default QFs (Q15 for 16b, Q23 for packed 24b,
+ *                       Q31 for unpacked 24b or 32b)
+ *                  15 - for 16 bit
+ *                  23 - for 24b packed or 8.24 format
+ */
+	uint8_t   channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
+/*
+ * Channel mapping array expected at the encoder output.
+ * Channel[i] mapping describes channel i inside the buffer, where
+ * 0 @le i < num_channels. All valid used channels must be present at
+ * the beginning of the array.
+ * If Native mode is set for the channels, this field is ignored.
+ * @values See Section @xref{dox:PcmChannelDefs}
+ */
+} __packed;
+
+/*
+ * Payload of the multichannel PCM encoder configuration parameters in
  * the ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V4 media format.
  */
 
@@ -9654,6 +9969,8 @@
 /* LSM Specific */
 #define VW_FEAT_DIM					(39)
 
+#define APRV2_IDS_SERVICE_ID_ADSP_ASM_V			(0x7)
+#define APRV2_IDS_SERVICE_ID_ADSP_ADM_V			(0x8)
 #define APRV2_IDS_SERVICE_ID_ADSP_LSM_V			(0xD)
 #define APRV2_IDS_DOMAIN_ID_ADSP_V			(0x4)
 #define APRV2_IDS_DOMAIN_ID_APPS_V			(0x5)
diff --git a/include/dsp/q6adm-v2.h b/include/dsp/q6adm-v2.h
index fcd426c..4fa2eac 100644
--- a/include/dsp/q6adm-v2.h
+++ b/include/dsp/q6adm-v2.h
@@ -58,7 +58,9 @@
 };
 
 #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 {
@@ -195,4 +197,5 @@
 			char *ch_map);
 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__ */
diff --git a/include/dsp/q6core.h b/include/dsp/q6core.h
index 03a7b31..986f2ac 100644
--- a/include/dsp/q6core.h
+++ b/include/dsp/q6core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -35,6 +35,7 @@
 int q6core_init_uevent_data(struct audio_uevent_data *uevent_data, char *name);
 void q6core_destroy_uevent_data(struct audio_uevent_data *uevent_data);
 int q6core_send_uevent(struct audio_uevent_data *uevent_data, char *name);
+int q6core_get_avcs_api_version_per_service(uint32_t service_id);
 
 #define ADSP_CMD_SET_DTS_EAGLE_DATA_ID 0x00012919
 #define DTS_EAGLE_LICENSE_ID           0x00028346