ASoC: msm: enable group config for both tx and rx

Add support to enable group config for tdm tx and
rx ports. On platform where ebit is unsupported it
is expected to start tx and rx ports at a time.
Ensure to start both tdm tx and rx group as
group devices.

Change-Id: Idb995c8215ccad147612b85bf38b289fb24391f2
Signed-off-by: Bala Kishore Pati <balakishorepati@codeaurora.org>
diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c
index 85d5f94..023739e 100644
--- a/asoc/msm-dai-q6-v2.c
+++ b/asoc/msm-dai-q6-v2.c
@@ -235,6 +235,7 @@
 };
 
 static union afe_port_group_config group_cfg_tx;
+static union afe_port_group_config group_cfg_rx;
 
 struct msm_dai_q6_tdm_dai_data {
 	DECLARE_BITMAP(status_mask, STATUS_MAX);
@@ -6969,22 +6970,33 @@
 			custom_tdm_header->header[7]);
 	}
 
-	memcpy(&group_cfg_tx.group_cfg, &dai_data->group_cfg.group_cfg,
-			sizeof(dai_data->group_cfg.group_cfg));
-	memcpy(&group_cfg_tx.group_enable, &dai_data->group_cfg.group_enable,
-			sizeof(dai_data->group_cfg.group_enable));
-	memcpy(&group_cfg_tx.tdm_cfg, &dai_data->group_cfg.tdm_cfg,
-			sizeof(dai_data->group_cfg.tdm_cfg));
-	pr_debug("%s: TDM GROUP:\n"
-		"num_channels=%d sample_rate=%d bit_width=%d\n"
-		"nslots_per_frame=%d slot_width=%d slot_mask=0x%x\n",
-		__func__,
-		group_cfg_tx.tdm_cfg.num_channels,
-		group_cfg_tx.tdm_cfg.sample_rate,
-		group_cfg_tx.tdm_cfg.bit_width,
-		group_cfg_tx.tdm_cfg.nslots_per_frame,
-		group_cfg_tx.tdm_cfg.slot_width,
-		group_cfg_tx.tdm_cfg.slot_mask);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		group_cfg_tx.tdm_cfg.num_channels =
+			dai_data->group_cfg.tdm_cfg.num_channels;
+		group_cfg_tx.tdm_cfg.sample_rate =
+			dai_data->group_cfg.tdm_cfg.sample_rate;
+		group_cfg_tx.tdm_cfg.bit_width =
+			dai_data->group_cfg.tdm_cfg.bit_width;
+		group_cfg_tx.tdm_cfg.nslots_per_frame =
+			dai_data->group_cfg.tdm_cfg.nslots_per_frame;
+		group_cfg_tx.tdm_cfg.slot_width =
+			dai_data->group_cfg.tdm_cfg.slot_width;
+		group_cfg_tx.tdm_cfg.slot_mask =
+			dai_data->group_cfg.tdm_cfg.slot_mask;
+	} else {
+		group_cfg_rx.tdm_cfg.num_channels =
+			dai_data->group_cfg.tdm_cfg.num_channels;
+		group_cfg_rx.tdm_cfg.sample_rate =
+			dai_data->group_cfg.tdm_cfg.sample_rate;
+		group_cfg_rx.tdm_cfg.bit_width =
+			dai_data->group_cfg.tdm_cfg.bit_width;
+		group_cfg_rx.tdm_cfg.nslots_per_frame =
+			dai_data->group_cfg.tdm_cfg.nslots_per_frame;
+		group_cfg_rx.tdm_cfg.slot_width =
+			dai_data->group_cfg.tdm_cfg.slot_width;
+		group_cfg_rx.tdm_cfg.slot_mask =
+			dai_data->group_cfg.tdm_cfg.slot_mask;
+	}
 
 	return 0;
 }
@@ -6996,10 +7008,13 @@
 	struct msm_dai_q6_tdm_dai_data *dai_data =
 		dev_get_drvdata(dai->dev);
 	u16 group_id = dai_data->group_cfg.tdm_cfg.group_id;
+	u16 sec_group_id = 0;
 	int group_idx = 0;
+	int sec_group_idx = 0;
 	u16 prim_port_id = 0;
 	u16 sec_port_id = 0;
 	atomic_t *group_ref = NULL;
+	atomic_t *sec_group_ref = NULL;
 
 	group_idx = msm_dai_q6_get_group_idx(dai->id);
 	if (group_idx < 0) {
@@ -7027,7 +7042,8 @@
 				rc = msm_dai_q6_tdm_set_clk(dai_data,
 					dai->id, true);
 				if (rc < 0) {
-					dev_err(dai->dev, "%s: fail to enable AFE clk 0x%x\n",
+					dev_err(dai->dev,
+						"%s: AFE CLK enable fail 0x%x\n",
 						__func__, dai->id);
 					goto rtn;
 				}
@@ -7038,7 +7054,7 @@
 			 * is no group need for only one port
 			 */
 			if (dai_data->num_group_ports > 1) {
-				dev_dbg(dai->dev, "%s:enable RX afe group\n",
+				dev_dbg(dai->dev, "%s:enable afe group\n",
 					__func__);
 				rc = afe_port_group_enable(group_id,
 					&dai_data->group_cfg, true);
@@ -7061,12 +7077,64 @@
 
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 			prim_port_id = dai->id;
-			if (dai_data->afe_ebit_unsupported)
+			if (dai_data->afe_ebit_unsupported) {
 				sec_port_id = AFE_PORT_ID_PRIMARY_TDM_TX;
+				sec_group_id =
+					AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX;
+				sec_group_idx =
+					msm_dai_q6_get_group_idx(sec_group_id);
+				if (sec_group_idx < 0) {
+					dev_err(dai->dev, "%s port id 0x%x\n"
+						"not supported\n", __func__,
+						sec_group_id);
+					goto rtn;
+				}
+				sec_group_ref = &tdm_group_ref[sec_group_idx];
+				if (atomic_read(sec_group_ref) == 0) {
+					rc = afe_port_group_enable(
+							sec_group_id,
+							&group_cfg_tx,
+							true);
+					if (rc < 0) {
+						dev_err(dai->dev,
+							"%s:failed to\n"
+							"enable grp\n"
+							"%x\n", __func__,
+							group_id);
+						goto rtn;
+					}
+				}
+			}
 		} else {
 			prim_port_id = dai->id;
-			if (dai_data->afe_ebit_unsupported)
+			if (dai_data->afe_ebit_unsupported) {
 				sec_port_id = AFE_PORT_ID_PRIMARY_TDM_RX;
+				sec_group_id =
+					AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX;
+				sec_group_idx =
+					msm_dai_q6_get_group_idx(sec_group_id);
+				if (sec_group_idx < 0) {
+					dev_err(dai->dev, "%s port id 0x%x\n"
+						" not supported\n", __func__,
+						sec_group_id);
+					goto rtn;
+				}
+				sec_group_ref = &tdm_group_ref[sec_group_idx];
+				if (atomic_read(sec_group_ref) == 0) {
+					rc = afe_port_group_enable(
+								sec_group_id,
+								&group_cfg_rx,
+								true);
+					if (rc < 0) {
+						dev_err(dai->dev,
+							"%s:failed to\n"
+							"enable grp\n"
+							"%x\n", __func__,
+							group_id);
+						goto rtn;
+					}
+				}
+			}
 		}
 		dev_dbg(dai->dev, "\n%s:open prim port id %d TDM rate: %d\n"
 				"dai_data->port_cfg.tdm.slot_mask %x\n"
@@ -7112,7 +7180,7 @@
 			rc = afe_tdm_port_start(sec_port_id,
 						&dai_data->port_cfg,
 						dai_data->rate, 4);
-			if (IS_ERR_VALUE(rc)) {
+			if (rc < 0) {
 				if (atomic_read(group_ref) == 0) {
 					afe_port_group_enable(group_id,
 							NULL, false);
@@ -7124,7 +7192,7 @@
 			} else {
 				set_bit(STATUS_PORT_STARTED,
 				dai_data->status_mask);
-				atomic_inc(group_ref);
+				atomic_inc(sec_group_ref);
 			}
 
 		}
@@ -7146,10 +7214,13 @@
 	struct msm_dai_q6_tdm_dai_data *dai_data =
 		dev_get_drvdata(dai->dev);
 	u16 group_id = dai_data->group_cfg.tdm_cfg.group_id;
+	u16 sec_group_id = 0;
 	int group_idx = 0;
+	int sec_group_idx = 0;
 	u16 prim_port_id = 0;
 	u16 sec_port_id = 0;
 	atomic_t *group_ref = NULL;
+	atomic_t *sec_group_ref = NULL;
 
 	group_idx = msm_dai_q6_get_group_idx(dai->id);
 	if (group_idx < 0) {
@@ -7165,12 +7236,36 @@
 	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 			prim_port_id = dai->id;
-			if (dai_data->afe_ebit_unsupported)
+			if (dai_data->afe_ebit_unsupported) {
 				sec_port_id = AFE_PORT_ID_PRIMARY_TDM_TX;
+				sec_group_id =
+					AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX;
+				sec_group_idx =
+					msm_dai_q6_get_group_idx(sec_group_id);
+				if (sec_group_idx < 0) {
+					dev_err(dai->dev, "%s port id 0x%x\n"
+						"not supported\n",
+						__func__, sec_group_id);
+					return;
+				}
+				sec_group_ref = &tdm_group_ref[sec_group_idx];
+			}
 		} else {
 			prim_port_id = dai->id;
-			if (dai_data->afe_ebit_unsupported)
+			if (dai_data->afe_ebit_unsupported) {
 				sec_port_id = AFE_PORT_ID_PRIMARY_TDM_RX;
+				sec_group_id =
+					AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX;
+				sec_group_idx =
+					msm_dai_q6_get_group_idx(sec_group_id);
+				if (sec_group_idx < 0) {
+					dev_err(dai->dev, "%s port id 0x%x\n"
+						"not supported\n",
+						__func__, sec_group_id);
+					return;
+				}
+				sec_group_ref = &tdm_group_ref[sec_group_idx];
+			}
 		}
 
 		rc = afe_close(prim_port_id);
@@ -7181,10 +7276,11 @@
 
 		if (sec_port_id != 0) {
 			rc = afe_close(sec_port_id);
-			if (IS_ERR_VALUE(rc)) {
+			if (rc < 0) {
 				dev_err(dai->dev, "%s: fail AFE port 0x%x\n",
 					__func__, sec_port_id);
 			}
+			atomic_dec(sec_group_ref);
 		}
 
 		atomic_dec(group_ref);
@@ -7207,7 +7303,16 @@
 					__func__, dai->id);
 			}
 		}
-
+		if (dai_data->afe_ebit_unsupported) {
+			if (atomic_read(sec_group_ref) == 0) {
+				rc = afe_port_group_enable(sec_group_id,
+							NULL, false);
+				if (rc < 0) {
+					dev_err(dai->dev, "%s:failed to\n"
+					"enable grp %x\n", __func__, group_id);
+				}
+			}
+		}
 		/* TODO: need to monitor PCM/MI2S/TDM HW status */
 		/* NOTE: AFE should error out if HW resource contention */
 
@@ -9029,9 +9134,6 @@
 		tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_TX_1 ||
 		tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_TX_2 ||
 		tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_TX_3) {
-		dev_dbg(&pdev->dev, "Copy TX group config id %d\n", tdm_dev_id);
-		/*memcpy (&group_cfg_tx,&dai_data->group_cfg ,
-				sizeof(dai_data->group_cfg));*/
 		memcpy(&group_cfg_tx.group_cfg,
 			&dai_data->group_cfg.group_cfg,
 			sizeof(dai_data->group_cfg.group_cfg));
@@ -9046,6 +9148,24 @@
 			tdm_dev_id);
 	}
 
+	if (tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_RX ||
+		tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_RX_1 ||
+		tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_RX_2 ||
+		tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_RX_3) {
+		memcpy(&group_cfg_rx.group_cfg,
+			&dai_data->group_cfg.group_cfg,
+			sizeof(dai_data->group_cfg.group_cfg));
+		memcpy(&group_cfg_rx.group_enable,
+			&dai_data->group_cfg.group_enable,
+			sizeof(dai_data->group_cfg.group_enable));
+		memcpy(&group_cfg_rx.tdm_cfg,
+			&dai_data->group_cfg.tdm_cfg,
+			sizeof(dai_data->group_cfg.tdm_cfg));
+		dev_dbg(&pdev->dev,
+			"Copy RX group configuration Successfully tdm_id %d\n",
+			tdm_dev_id);
+	}
+
 	dev_set_drvdata(&pdev->dev, dai_data);
 
 	port_idx = msm_dai_q6_get_port_idx(tdm_dev_id);