dsp: add support to set topology specific info in voice usecases

Add support to set number of channels and channel mapping to DSP
as per the info received from ACDB files along with topology
for a device in voice usecases instead of reading from
backend configuration. When topology specific channel info is
not supported, send the default no of channels and
channel mapping as per backend to support backward compatibility.

CRs-Fixed: 2110934
Change-Id: Iad512474fc25c906d97513f6648cd8ba6244eda1
Signed-off-by: Aditya Bavanari <abavanar@codeaurora.org>
diff --git a/dsp/q6voice.c b/dsp/q6voice.c
index fa910ca..983e0a2 100644
--- a/dsp/q6voice.c
+++ b/dsp/q6voice.c
@@ -2368,6 +2368,9 @@
 			&cvp_setdev_cmd.cvp_set_device_v2.tx_topology_id,
 			&cvp_setdev_cmd.cvp_set_device_v2.rx_topology_id);
 
+	voice_set_topology_specific_info(v, CVP_VOC_RX_TOPOLOGY_CAL);
+	voice_set_topology_specific_info(v, CVP_VOC_TX_TOPOLOGY_CAL);
+
 	cvp_setdev_cmd.cvp_set_device_v2.tx_port_id = v->dev_tx.port_id;
 	cvp_setdev_cmd.cvp_set_device_v2.rx_port_id = v->dev_rx.port_id;
 
@@ -2722,6 +2725,9 @@
 			&cvp_session_cmd.cvp_session.tx_topology_id,
 			&cvp_session_cmd.cvp_session.rx_topology_id);
 
+	voice_set_topology_specific_info(v, CVP_VOC_RX_TOPOLOGY_CAL);
+	voice_set_topology_specific_info(v, CVP_VOC_TX_TOPOLOGY_CAL);
+
 	cvp_session_cmd.cvp_session.direction = 2; /*tx and rx*/
 	cvp_session_cmd.cvp_session.tx_port_id = v->dev_tx.port_id;
 	cvp_session_cmd.cvp_session.rx_port_id = v->dev_rx.port_id;
@@ -3864,6 +3870,9 @@
 			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;
+		memcpy(&channel_info->channel_mapping,
+		       v->dev_rx.channel_mapping,
+		       VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
 		break;
 
 	case TX_PATH:
@@ -3871,6 +3880,9 @@
 			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;
+		memcpy(&channel_info->channel_mapping,
+		       v->dev_tx.channel_mapping,
+		       VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
 		break;
 
 	case EC_REF_PATH:
@@ -3878,6 +3890,9 @@
 			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;
+		memcpy(&channel_info->channel_mapping,
+		       v->dev_rx.channel_mapping,
+		       VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
 		break;
 	default:
 		pr_err("%s: Invalid param type\n",
@@ -3886,21 +3901,6 @@
 		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 if (channel_info->num_channels == NUM_CHANNELS_QUAD &&
-		   param_type == TX_PATH) {
-		channel_info->channel_mapping[0] = PCM_CHANNEL_FL;
-		channel_info->channel_mapping[1] = PCM_CHANNEL_FR;
-		channel_info->channel_mapping[2] = PCM_CHANNEL_LS;
-		channel_info->channel_mapping[3] = PCM_CHANNEL_RS;
-	} else {
-		pr_warn("%s: Unsupported num channels: %d for path: %d\n",
-			__func__, channel_info->num_channels, param_type);
-	}
 
 	v->cvp_state = CMD_STATUS_FAIL;
 	v->async_err = 0;
@@ -4110,16 +4110,9 @@
 	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_warn("%s: Unsupported num channels: %d\n",
-			__func__, mfc_config_info->num_channels);
-	}
+	memcpy(&mfc_config_info->channel_type,
+	       v->dev_rx.channel_mapping,
+	       VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
 
 	v->cvp_state = CMD_STATUS_FAIL;
 	v->async_err = 0;
@@ -8183,6 +8176,96 @@
 	return topology;
 }
 
+int voice_set_topology_specific_info(struct voice_data *v,
+				     uint32_t topology_idx)
+{
+	struct cal_block_data *cal_block = NULL;
+	int ret = 0;
+	uint32_t topo_channels;
+
+	if (common.cal_data[topology_idx] == NULL) {
+		pr_err("%s: cal type is NULL for cal index %x\n",
+			__func__, topology_idx);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	mutex_lock(&common.cal_data[topology_idx]->lock);
+	cal_block = cal_utils_get_only_cal_block(
+		common.cal_data[topology_idx]);
+	if (cal_block == NULL) {
+		pr_debug("%s: cal_block not found for cal index %x\n",
+			__func__, topology_idx);
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	if (topology_idx == CVP_VOC_RX_TOPOLOGY_CAL) {
+		topo_channels = ((struct audio_cal_info_voc_top *)
+				cal_block->cal_info)->num_channels;
+		if (topo_channels > 0) {
+			v->dev_rx.no_of_channels = topo_channels;
+			pr_debug("%s: Topology Rx no of channels: %d",
+				 __func__, v->dev_rx.no_of_channels);
+			memcpy(&v->dev_rx.channel_mapping,
+			       &((struct audio_cal_info_voc_top *)
+			       cal_block->cal_info)->channel_mapping,
+			       VSS_CHANNEL_MAPPING_SIZE);
+		} else {
+			pr_debug("%s: cal data is zero, default to Rx backend config\n",
+				 __func__);
+			if (v->dev_rx.no_of_channels == NUM_CHANNELS_MONO) {
+				v->dev_rx.channel_mapping[0] = PCM_CHANNEL_FC;
+			} else if (v->dev_rx.no_of_channels ==
+							NUM_CHANNELS_STEREO) {
+				v->dev_rx.channel_mapping[0] = PCM_CHANNEL_FL;
+				v->dev_rx.channel_mapping[1] = PCM_CHANNEL_FR;
+			} else {
+				pr_warn("%s: Unsupported Rx num channels: %d\n",
+					__func__, v->dev_rx.no_of_channels);
+			}
+		}
+	} else if (topology_idx == CVP_VOC_TX_TOPOLOGY_CAL) {
+		topo_channels = ((struct audio_cal_info_voc_top *)
+				cal_block->cal_info)->num_channels;
+		if (topo_channels > 0) {
+			v->dev_tx.no_of_channels = topo_channels;
+			pr_debug("%s: Topology Tx no of channels: %d",
+				 __func__, v->dev_tx.no_of_channels);
+			memcpy(&v->dev_tx.channel_mapping,
+			       &((struct audio_cal_info_voc_top *)
+			       cal_block->cal_info)->channel_mapping,
+			       VSS_CHANNEL_MAPPING_SIZE);
+		} else {
+			pr_debug("%s: cal data is zero, default to Tx backend config\n",
+				 __func__);
+			if (v->dev_tx.no_of_channels == NUM_CHANNELS_MONO) {
+				v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FC;
+			} else if (v->dev_tx.no_of_channels ==
+							NUM_CHANNELS_STEREO) {
+				v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FL;
+				v->dev_tx.channel_mapping[1] = PCM_CHANNEL_FR;
+			} else if (v->dev_tx.no_of_channels ==
+							NUM_CHANNELS_QUAD) {
+				v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FL;
+				v->dev_tx.channel_mapping[1] = PCM_CHANNEL_FR;
+				v->dev_tx.channel_mapping[2] = PCM_CHANNEL_LS;
+				v->dev_tx.channel_mapping[3] = PCM_CHANNEL_RS;
+			} else {
+				pr_warn("%s: Unsupported Tx num channels: %d\n",
+					__func__, v->dev_tx.no_of_channels);
+			}
+		}
+	} else {
+		pr_err("%s: topology index %x is invalid\n",
+		       __func__, topology_idx);
+	}
+unlock:
+	mutex_unlock(&common.cal_data[topology_idx]->lock);
+done:
+	return ret;
+}
+
 static int get_cal_type_index(int32_t cal_type)
 {
 	int ret = -EINVAL;
diff --git a/include/dsp/q6voice.h b/include/dsp/q6voice.h
index af7995a..a41a2db 100644
--- a/include/dsp/q6voice.h
+++ b/include/dsp/q6voice.h
@@ -2063,6 +2063,8 @@
 int voc_set_device_config(uint32_t session_id, uint8_t path_dir,
 			  struct media_format_info *finfo);
 uint32_t voice_get_topology(uint32_t topology_idx);
+int voice_set_topology_specific_info(struct voice_data *v,
+				     uint32_t topology_idx);
 int voc_set_sound_focus(struct sound_focus_param sound_focus_param);
 int voc_get_sound_focus(struct sound_focus_param *soundFocusData);
 int voc_get_source_tracking(struct source_tracking_param *sourceTrackingData);
diff --git a/include/uapi/linux/msm_audio_calibration.h b/include/uapi/linux/msm_audio_calibration.h
index 5a0b860..1696ae5 100644
--- a/include/uapi/linux/msm_audio_calibration.h
+++ b/include/uapi/linux/msm_audio_calibration.h
@@ -107,6 +107,8 @@
 
 #define AFE_SIDETONE_IIR_CAL_TYPE AFE_SIDETONE_IIR_CAL_TYPE
 
+#define TOPOLOGY_SPECIFIC_CHANNEL_INFO
+
 enum {
 	VERSION_0_0,
 };
@@ -376,9 +378,15 @@
 	int32_t		app_type;
 };
 
+#define VSS_NUM_CHANNELS_MAX	8
+
 struct audio_cal_info_voc_top {
 	int32_t		topology;
 	int32_t		acdb_id;
+#ifdef TOPOLOGY_SPECIFIC_CHANNEL_INFO
+	uint32_t	num_channels;
+	uint8_t		channel_mapping[VSS_NUM_CHANNELS_MAX];
+#endif
 };
 
 struct audio_cal_info_vocproc {