msm: audio: qdsp6v2: Add 4GV wb/nb support in mvs driver

Support for 4GV-wb mode and 4GV-nb mode in mvs driver
and add support for min-max rate.

Change-Id: Iacd33ecfbdf278eb59b3e662c725d21fb60e4ab3
Signed-off-by: Chaithanya Krishna Bacharaju <chaithan@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/q6voice.h b/arch/arm/mach-msm/include/mach/qdsp6v2/q6voice.h
index fb6e22e..1f8ce68 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/q6voice.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/q6voice.h
@@ -523,6 +523,10 @@
 /* Media types */
 #define VSS_MEDIA_ID_EVRC_MODEM		0x00010FC2
 /* 80-VF690-47 CDMA enhanced variable rate vocoder modem format. */
+#define VSS_MEDIA_ID_4GV_NB_MODEM  0x00010FC3
+/* 4GV Narrowband modem format */
+#define VSS_MEDIA_ID_4GV_WB_MODEM  0x00010FC4
+/* 4GV Wideband modem format */
 #define VSS_MEDIA_ID_AMR_NB_MODEM	0x00010FC6
 /* 80-VF690-47 UMTS AMR-NB vocoder modem format. */
 #define VSS_MEDIA_ID_AMR_WB_MODEM	0x00010FC7
@@ -652,12 +656,17 @@
 			 uint32_t *pkt_len,
 			 void *private_data);
 
+struct q_min_max_rate {
+	uint32_t min_rate;
+	uint32_t max_rate;
+};
 
 struct mvs_driver_info {
 	uint32_t media_type;
 	uint32_t rate;
 	uint32_t network_type;
 	uint32_t dtx_mode;
+	struct q_min_max_rate q_min_max_rate;
 	ul_cb_fn ul_cb;
 	dl_cb_fn dl_cb;
 	void *private_data;
@@ -750,7 +759,8 @@
 void voice_config_vocoder(uint32_t media_type,
 			  uint32_t rate,
 			  uint32_t network_type,
-			  uint32_t dtx_mode);
+			  uint32_t dtx_mode,
+			  struct q_min_max_rate q_min_max_rate);
 
 int voice_start_record(uint32_t rec_mode, uint32_t set);
 
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_mvs.c b/arch/arm/mach-msm/qdsp6v2/audio_mvs.c
index 2dae9a8..0b4997c 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_mvs.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_mvs.c
@@ -38,7 +38,7 @@
 
 struct audio_mvs_buf_node {
 	struct list_head list;
-	struct msm_audio_mvs_frame frame;
+	struct q6_msm_audio_mvs_frame frame;
 };
 
 struct audio_mvs_info_type {
@@ -47,6 +47,7 @@
 	uint32_t mvs_mode;
 	uint32_t rate_type;
 	uint32_t dtx_mode;
+	struct q_min_max_rate min_max_rate;
 
 	struct list_head in_queue;
 	struct list_head free_in_queue;
@@ -110,7 +111,8 @@
 			 * Bits 0-3: Frame rate
 			 * Bits 4-7: Frame type
 			 */
-			buf_node->frame.frame_type = ((*voc_pkt) & 0xF0) >> 4;
+			buf_node->frame.header.frame_type =
+						((*voc_pkt) & 0xF0) >> 4;
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 			buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
@@ -124,7 +126,7 @@
 		}
 
 		case MVS_MODE_IS127: {
-			buf_node->frame.frame_type = 0;
+			buf_node->frame.header.packet_rate = (*voc_pkt) & 0x0F;
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 			buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
@@ -147,7 +149,7 @@
 			 * Header format:
 			 * Bits 0-1: Frame type
 			 */
-			buf_node->frame.frame_type = (*voc_pkt) & 0x03;
+			buf_node->frame.header.frame_type = (*voc_pkt) & 0x03;
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 			/* There are two frames in the buffer. Length of the
@@ -177,7 +179,8 @@
 				 * Header format:
 				 * Bits 0-1: Frame type
 				 */
-				buf_node->frame.frame_type = (*voc_pkt) & 0x03;
+				buf_node->frame.header.frame_type =
+							(*voc_pkt) & 0x03;
 				voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 				/* There are two frames in the buffer. Length
@@ -213,7 +216,7 @@
 			 * Bits 0-1: Frame type
 			 * Bits 2-3: Frame rate
 			 */
-			buf_node->frame.frame_type = (*voc_pkt) & 0x03;
+			buf_node->frame.header.frame_type = (*voc_pkt) & 0x03;
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 			/* There are two frames in the buffer. Length of the
@@ -244,7 +247,8 @@
 				 * Bits 0-1: Frame type
 				 * Bits 2-3: Frame rate
 				 */
-				buf_node->frame.frame_type = (*voc_pkt) & 0x03;
+				buf_node->frame.header.frame_type =
+							(*voc_pkt) & 0x03;
 				voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 				/* There are two frames in the buffer. Length
@@ -267,8 +271,25 @@
 			break;
 		}
 
+		case MVS_MODE_4GV_NB:
+		case MVS_MODE_4GV_WB: {
+			/* Remove the DSP frame info header.
+			 * Header format:
+			 * Bits 0-3: frame rate
+			 */
+			buf_node->frame.header.packet_rate = (*voc_pkt) & 0x0F;
+			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+			buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
+
+			memcpy(&buf_node->frame.voc_pkt[0],
+				voc_pkt,
+				buf_node->frame.len);
+			list_add_tail(&buf_node->list, &audio->out_queue);
+			break;
+		}
+
 		default: {
-			buf_node->frame.frame_type = 0;
+			buf_node->frame.header.frame_type = 0;
 
 			buf_node->frame.len = pkt_len;
 
@@ -314,8 +335,9 @@
 			 * Bits 0-3: Frame rate
 			 * Bits 4-7: Frame type
 			 */
-			*voc_pkt = ((buf_node->frame.frame_type & 0x0F) << 4) |
-				   (rate_type & 0x0F);
+			*voc_pkt =
+			    ((buf_node->frame.header.frame_type & 0x0F) << 4) |
+			    (rate_type & 0x0F);
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 			*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
@@ -333,7 +355,7 @@
 			 * Bits 0-3: Frame rate
 			 * Bits 4-7: Frame type
 			 */
-			*voc_pkt = rate_type & 0x0F;
+			*voc_pkt = buf_node->frame.header.packet_rate & 0x0F;
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 			*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
@@ -353,7 +375,7 @@
 			/* Add the first DSP frame info header. Header format:
 			 * Bits 0-1: Frame type
 			 */
-			*voc_pkt = buf_node->frame.frame_type & 0x03;
+			*voc_pkt = buf_node->frame.header.frame_type & 0x03;
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 			*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
@@ -376,7 +398,8 @@
 				 * Header format:
 				 * Bits 0-1: Frame type
 				 */
-				*voc_pkt = buf_node->frame.frame_type & 0x03;
+				*voc_pkt = buf_node->frame.header.frame_type
+						& 0x03;
 				voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 				*pkt_len = *pkt_len +
@@ -409,7 +432,7 @@
 			 * Bits 2-3: Frame rate
 			 */
 			*voc_pkt = ((rate_type & 0x0F) << 2) |
-				   (buf_node->frame.frame_type & 0x03);
+				   (buf_node->frame.header.frame_type & 0x03);
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 			*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
@@ -434,7 +457,7 @@
 				 * Bits 2-3: Frame rate
 				 */
 				*voc_pkt = ((rate_type & 0x0F) << 2) |
-					   (buf_node->frame.frame_type & 0x03);
+				     (buf_node->frame.header.frame_type & 0x03);
 				voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 				*pkt_len = *pkt_len +
@@ -458,6 +481,23 @@
 			break;
 		}
 
+		case MVS_MODE_4GV_NB:
+		case MVS_MODE_4GV_WB: {
+			/* Add the DSP frame info header. Header format:
+			 * Bits 0-3 : Frame rate
+			*/
+			*voc_pkt = buf_node->frame.header.packet_rate & 0x0F;
+			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+			*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
+
+			memcpy(voc_pkt,
+				&buf_node->frame.voc_pkt[0],
+				buf_node->frame.len);
+
+			list_add_tail(&buf_node->list, &audio->free_in_queue);
+			break;
+		}
+
 		default: {
 			*pkt_len = buf_node->frame.len;
 
@@ -487,6 +527,14 @@
 		media_type = VSS_MEDIA_ID_EVRC_MODEM;
 		break;
 
+	case MVS_MODE_4GV_NB:
+		media_type = VSS_MEDIA_ID_4GV_NB_MODEM;
+		break;
+
+	case MVS_MODE_4GV_WB:
+		media_type = VSS_MEDIA_ID_4GV_WB_MODEM;
+		break;
+
 	case MVS_MODE_AMR:
 		media_type = VSS_MEDIA_ID_AMR_NB_MODEM;
 		break;
@@ -533,6 +581,7 @@
 
 	switch (mvs_mode) {
 	case MVS_MODE_IS127:
+	case MVS_MODE_4GV_NB:
 	case MVS_MODE_AMR:
 	case MVS_MODE_LINEAR_PCM:
 	case MVS_MODE_PCM:
@@ -541,6 +590,7 @@
 		network_type = VSS_NETWORK_ID_VOIP_NB;
 		break;
 
+	case MVS_MODE_4GV_WB:
 	case MVS_MODE_AMR_WB:
 	case MVS_MODE_PCM_WB:
 		network_type = VSS_NETWORK_ID_VOIP_WB;
@@ -576,7 +626,8 @@
 		    audio_mvs_get_media_type(audio->mvs_mode, audio->rate_type),
 		    audio_mvs_get_rate(audio->mvs_mode, audio->rate_type),
 		    audio_mvs_get_network_type(audio->mvs_mode),
-		    audio->dtx_mode);
+		    audio->dtx_mode,
+		    audio->min_max_rate);
 
 		audio->state = AUDIO_MVS_STARTED;
 	} else {
@@ -729,7 +780,7 @@
 		if ((audio->state == AUDIO_MVS_STARTED) &&
 		    (!list_empty(&audio->out_queue))) {
 
-			if (count >= sizeof(struct msm_audio_mvs_frame)) {
+			if (count >= sizeof(struct q6_msm_audio_mvs_frame)) {
 				buf_node = list_first_entry(&audio->out_queue,
 						struct audio_mvs_buf_node,
 						list);
@@ -737,11 +788,11 @@
 
 				rc = copy_to_user(buf,
 					&buf_node->frame,
-					sizeof(struct msm_audio_mvs_frame));
+					sizeof(struct q6_msm_audio_mvs_frame));
 
 				if (rc == 0) {
 					rc = buf_node->frame.len +
-					    sizeof(buf_node->frame.frame_type) +
+					    sizeof(buf_node->frame.header) +
 					    sizeof(buf_node->frame.len);
 				} else {
 					pr_err("%s: Copy to user retuned %d",
@@ -755,7 +806,7 @@
 			} else {
 				pr_err("%s: Read count %d < sizeof(frame) %d",
 				       __func__, count,
-				       sizeof(struct msm_audio_mvs_frame));
+				       sizeof(struct q6_msm_audio_mvs_frame));
 
 				rc = -ENOMEM;
 			}
@@ -799,7 +850,7 @@
 		mutex_lock(&audio->in_lock);
 
 		if (audio->state == AUDIO_MVS_STARTED) {
-			if (count <= sizeof(struct msm_audio_mvs_frame)) {
+			if (count <= sizeof(struct q6_msm_audio_mvs_frame)) {
 				if (!list_empty(&audio->free_in_queue)) {
 					buf_node =
 					list_first_entry(&audio->free_in_queue,
@@ -818,7 +869,7 @@
 			} else {
 				pr_err("%s: Write count %d < sizeof(frame) %d",
 				       __func__, count,
-				       sizeof(struct msm_audio_mvs_frame));
+				       sizeof(struct q6_msm_audio_mvs_frame));
 
 				rc = -ENOMEM;
 			}
@@ -863,7 +914,8 @@
 		config.mvs_mode = audio->mvs_mode;
 		config.rate_type = audio->rate_type;
 		config.dtx_mode = audio->dtx_mode;
-
+		config.min_max_rate.min_rate = audio->min_max_rate.min_rate;
+		config.min_max_rate.max_rate = audio->min_max_rate.max_rate;
 		mutex_unlock(&audio->lock);
 
 		rc = copy_to_user((void *)arg, &config, sizeof(config));
@@ -888,6 +940,10 @@
 				audio->mvs_mode = config.mvs_mode;
 				audio->rate_type = config.rate_type;
 				audio->dtx_mode = config.dtx_mode;
+				audio->min_max_rate.min_rate =
+						config.min_max_rate.min_rate;
+				audio->min_max_rate.max_rate =
+						config.min_max_rate.max_rate;
 			} else {
 				pr_err("%s: Set confg called in state %d\n",
 				       __func__, audio->state);
diff --git a/arch/arm/mach-msm/qdsp6v2/q6voice.c b/arch/arm/mach-msm/qdsp6v2/q6voice.c
index 7472849..1ab615a 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6voice.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6voice.c
@@ -1117,10 +1117,12 @@
 
 	/* Set encoder properties. */
 	switch (common.mvs_info.media_type) {
+	case VSS_MEDIA_ID_4GV_NB_MODEM:
+	case VSS_MEDIA_ID_4GV_WB_MODEM:
 	case VSS_MEDIA_ID_EVRC_MODEM: {
 		struct cvs_set_cdma_enc_minmax_rate_cmd cvs_set_cdma_rate;
 
-		pr_info("%s: Setting EVRC min-max rate\n", __func__);
+		pr_info("%s: Setting CDMA min-max rate\n", __func__);
 
 		cvs_set_cdma_rate.hdr.hdr_field =
 				APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -1133,14 +1135,16 @@
 		cvs_set_cdma_rate.hdr.token = 0;
 		cvs_set_cdma_rate.hdr.opcode =
 				VSS_ISTREAM_CMD_CDMA_SET_ENC_MINMAX_RATE;
-		cvs_set_cdma_rate.cdma_rate.min_rate = common.mvs_info.rate;
-		cvs_set_cdma_rate.cdma_rate.max_rate = common.mvs_info.rate;
+		cvs_set_cdma_rate.cdma_rate.min_rate =
+				common.mvs_info.q_min_max_rate.min_rate;
+		cvs_set_cdma_rate.cdma_rate.max_rate =
+				common.mvs_info.q_min_max_rate.max_rate;
 
 		v->cvs_state = CMD_STATUS_FAIL;
 
 		ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_cdma_rate);
 		if (ret < 0) {
-			pr_err("%s: Error %d sending SET_EVRC_MINMAX_RATE\n",
+			pr_err("%s: Error %d sending CDMA_SET_ENC_MINMAX_RATE\n",
 			       __func__, ret);
 
 			goto done;
@@ -1156,6 +1160,10 @@
 			goto done;
 		}
 
+		if ((common.mvs_info.media_type == VSS_MEDIA_ID_4GV_NB_MODEM) ||
+		(common.mvs_info.media_type == VSS_MEDIA_ID_4GV_WB_MODEM))
+			ret = voice_set_dtx(v);
+
 		break;
 	}
 
@@ -2472,12 +2480,14 @@
 void voice_config_vocoder(uint32_t media_type,
 			  uint32_t rate,
 			  uint32_t network_type,
-			  uint32_t dtx_mode)
+			  uint32_t dtx_mode,
+			  struct q_min_max_rate q_min_max_rate)
 {
 	common.mvs_info.media_type = media_type;
 	common.mvs_info.rate = rate;
 	common.mvs_info.network_type = network_type;
 	common.mvs_info.dtx_mode = dtx_mode;
+	common.mvs_info.q_min_max_rate = q_min_max_rate;
 }
 
 static int32_t modem_mvm_callback(struct apr_client_data *data, void *priv)
diff --git a/include/linux/msm_audio_mvs.h b/include/linux/msm_audio_mvs.h
index 37a6ee7..c934aee 100644
--- a/include/linux/msm_audio_mvs.h
+++ b/include/linux/msm_audio_mvs.h
@@ -94,14 +94,30 @@
 	MVS_G729A_ERASURE
 };
 
+struct min_max_rate {
+	uint32_t min_rate;
+	uint32_t max_rate;
+};
+
 struct msm_audio_mvs_config {
 	uint32_t mvs_mode;
 	uint32_t rate_type;
+	struct min_max_rate min_max_rate;
 	uint32_t dtx_mode;
 };
 
 #define MVS_MAX_VOC_PKT_SIZE 640
 
+struct q6_msm_audio_mvs_frame {
+	union {
+	uint32_t frame_type;
+	uint32_t packet_rate;
+	} header;
+	uint32_t len;
+	uint8_t voc_pkt[MVS_MAX_VOC_PKT_SIZE];
+
+};
+
 struct msm_audio_mvs_frame {
 	uint32_t frame_type;
 	uint32_t len;