dsp: adm: Add support for port specific channel map

Add multi channel map support per afe port.

Change-Id: Ib032d1c81d918417f516131f11c500e4f6668b39
Signed-off-by: Rohit kumar <rohitkr@codeaurora.org>
diff --git a/dsp/q6adm.c b/dsp/q6adm.c
index e42e329..03fa6a6 100644
--- a/dsp/q6adm.c
+++ b/dsp/q6adm.c
@@ -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
@@ -125,6 +125,8 @@
 							}
 };
 
+static struct adm_multi_ch_map port_channel_map[AFE_MAX_PORTS];
+
 static int adm_get_parameters[MAX_COPPS_PER_PORT * ADM_GET_PARAMETER_LENGTH];
 static int adm_module_topo_list[
 	MAX_COPPS_PER_PORT * ADM_GET_TOPO_MODULE_LIST_LENGTH];
@@ -1459,6 +1461,31 @@
 }
 EXPORT_SYMBOL(adm_get_multi_ch_map);
 
+/**
+ * adm_set_port_multi_ch_map -
+ *        Update port specific channel map info
+ *
+ * @channel_map: pointer with channel map info
+ * @port_id: port for which chmap is set
+ */
+void adm_set_port_multi_ch_map(char *channel_map, int port_id)
+{
+	int port_idx;
+
+	port_id = q6audio_convert_virtual_to_portid(port_id);
+	port_idx = adm_validate_and_get_port_index(port_id);
+
+	if (port_idx < 0) {
+		pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
+		return;
+	}
+
+	memcpy(port_channel_map[port_idx].channel_mapping, channel_map,
+			PCM_FORMAT_MAX_NUM_CHANNEL);
+	port_channel_map[port_idx].set_channel_map = true;
+}
+EXPORT_SYMBOL(adm_set_port_multi_ch_map);
+
 static void adm_reset_data(void)
 {
 	int i, j;
@@ -2441,7 +2468,7 @@
 EXPORT_SYMBOL(adm_connect_afe_port);
 
 int adm_arrange_mch_map(struct adm_cmd_device_open_v5 *open, int path,
-			 int channel_mode)
+			 int channel_mode, int port_idx)
 {
 	int rc = 0, idx;
 
@@ -2457,10 +2484,18 @@
 	default:
 		goto non_mch_path;
 	};
-	if ((open->dev_num_channel > 2) && multi_ch_maps[idx].set_channel_map) {
-		memcpy(open->dev_channel_mapping,
-			multi_ch_maps[idx].channel_mapping,
-			PCM_FORMAT_MAX_NUM_CHANNEL);
+
+	if ((open->dev_num_channel > 2) &&
+		(port_channel_map[port_idx].set_channel_map ||
+		 multi_ch_maps[idx].set_channel_map)) {
+		if (port_channel_map[port_idx].set_channel_map)
+			memcpy(open->dev_channel_mapping,
+				port_channel_map[port_idx].channel_mapping,
+				PCM_FORMAT_MAX_NUM_CHANNEL);
+		else
+			memcpy(open->dev_channel_mapping,
+				multi_ch_maps[idx].channel_mapping,
+				PCM_FORMAT_MAX_NUM_CHANNEL);
 	} else {
 		if (channel_mode == 1) {
 			open->dev_channel_mapping[0] = PCM_CHANNEL_FC;
@@ -2750,7 +2785,8 @@
 			(rate != ULL_SUPPORTED_SAMPLE_RATE));
 		open.sample_rate  = rate;
 
-		ret = adm_arrange_mch_map(&open, path, channel_mode);
+		ret = adm_arrange_mch_map(&open, path, channel_mode,
+					  port_idx);
 
 		if (ret)
 			return ret;
@@ -2898,7 +2934,7 @@
 		atomic_read(&this_adm.copp.channels[port_idx][copp_idx]);
 
 	rc = adm_arrange_mch_map(&open, ADM_PATH_PLAYBACK,
-		mfc_cfg.num_channels);
+		mfc_cfg.num_channels, port_idx);
 	if (rc < 0) {
 		pr_err("%s: unable to get channal map\n", __func__);
 		goto fail_cmd;
@@ -3212,6 +3248,7 @@
 		return -EINVAL;
 	}
 
+	port_channel_map[port_idx].set_channel_map = false;
 	if (this_adm.copp.adm_delay[port_idx][copp_idx] && perf_mode
 		== LEGACY_PCM_MODE) {
 		atomic_set(&this_adm.copp.adm_delay_stat[port_idx][copp_idx],
diff --git a/include/dsp/q6adm-v2.h b/include/dsp/q6adm-v2.h
index 5308b6e..fcd426c 100644
--- a/include/dsp/q6adm-v2.h
+++ b/include/dsp/q6adm-v2.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
@@ -134,6 +134,8 @@
 
 int adm_get_multi_ch_map(char *channel_map, int path);
 
+void adm_set_port_multi_ch_map(char *channel_map, int port_id);
+
 int adm_validate_and_get_port_index(int port_id);
 
 int adm_get_default_copp_idx(int port_id);