msm: audio: qdsp6v2: Add codec support in mvs driver

Support for Qcelp-13k, EFR, FR, HR, G.711 modes in mvs driver.

Change-Id: I5b8f90388b2fc79ad6d9b6276d0dd29e3cc6ba80
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 1f8ce68..674cfe8 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/q6voice.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/q6voice.h
@@ -521,6 +521,8 @@
 #define VSS_NETWORK_ID_VOIP_WV				0x00011242
 
 /* Media types */
+#define VSS_MEDIA_ID_13K_MODEM		0x00010FC1
+/* Qcelp vocoder modem format */
 #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
@@ -531,6 +533,12 @@
 /* 80-VF690-47 UMTS AMR-NB vocoder modem format. */
 #define VSS_MEDIA_ID_AMR_WB_MODEM	0x00010FC7
 /* 80-VF690-47 UMTS AMR-WB vocoder modem format. */
+#define VSS_MEDIA_ID_EFR_MODEM		0x00010FC8
+/*EFR modem format */
+#define VSS_MEDIA_ID_FR_MODEM		0x00010FC9
+/*FR modem format */
+#define VSS_MEDIA_ID_HR_MODEM		0x00010FCA
+/*HR modem format */
 #define VSS_MEDIA_ID_PCM_NB		0x00010FCB
 /* Linear PCM (16-bit, little-endian). */
 #define VSS_MEDIA_ID_PCM_WB		0x00010FCC
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_mvs.c b/arch/arm/mach-msm/qdsp6v2/audio_mvs.c
index 0b4997c..6e7961c 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_mvs.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_mvs.c
@@ -205,6 +205,7 @@
 			break;
 		}
 
+		case MVS_MODE_G711:
 		case MVS_MODE_G711A: {
 			/* G711 frames are 10ms each, but the DSP works with
 			 * 20ms frames and sends two 10ms frames per buffer.
@@ -212,11 +213,16 @@
 			 * buffers.
 			 */
 			/* Remove the first DSP frame info header.
-			 * Header format:
+			 * Header format: G711A
 			 * Bits 0-1: Frame type
 			 * Bits 2-3: Frame rate
+			 *
+			 * Header format: G711
+			 * Bits 2-3: Frame rate
 			 */
-			buf_node->frame.header.frame_type = (*voc_pkt) & 0x03;
+			if (audio->mvs_mode == MVS_MODE_G711A)
+				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
@@ -247,7 +253,8 @@
 				 * Bits 0-1: Frame type
 				 * Bits 2-3: Frame rate
 				 */
-				buf_node->frame.header.frame_type =
+				if (audio->mvs_mode == MVS_MODE_G711A)
+					buf_node->frame.header.frame_type =
 							(*voc_pkt) & 0x03;
 				voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
@@ -271,6 +278,7 @@
 			break;
 		}
 
+		case MVS_MODE_IS733:
 		case MVS_MODE_4GV_NB:
 		case MVS_MODE_4GV_WB: {
 			/* Remove the DSP frame info header.
@@ -284,6 +292,32 @@
 			memcpy(&buf_node->frame.voc_pkt[0],
 				voc_pkt,
 				buf_node->frame.len);
+
+			list_add_tail(&buf_node->list, &audio->out_queue);
+			break;
+		}
+
+		case MVS_MODE_EFR:
+		case MVS_MODE_FR:
+		case MVS_MODE_HR: {
+			/*
+			 * Remove the DSP frame info header
+			 * Header Format
+			 * Bit 0: bfi unused for uplink
+			 * Bit 1-2: sid applies to both uplink and downlink
+			 * Bit 3: taf unused for uplink
+			 * MVS_MODE_HR
+			 * Bit 4: ufi unused for uplink
+			 */
+			buf_node->frame.header.gsm_frame_type.sid =
+						((*voc_pkt) & 0x06) >> 1;
+			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;
 		}
@@ -353,7 +387,6 @@
 		case MVS_MODE_IS127: {
 			/* Add the DSP frame info header. Header format:
 			 * Bits 0-3: Frame rate
-			 * Bits 4-7: Frame type
 			 */
 			*voc_pkt = buf_node->frame.header.packet_rate & 0x0F;
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
@@ -423,6 +456,7 @@
 			break;
 		}
 
+		case MVS_MODE_G711:
 		case MVS_MODE_G711A: {
 			/* G711 frames are 10ms each but the DSP expects 20ms
 			 * worth of data, so send two 10ms frames per buffer.
@@ -481,6 +515,7 @@
 			break;
 		}
 
+		case MVS_MODE_IS733:
 		case MVS_MODE_4GV_NB:
 		case MVS_MODE_4GV_WB: {
 			/* Add the DSP frame info header. Header format:
@@ -498,6 +533,48 @@
 			break;
 		}
 
+		case MVS_MODE_EFR:
+		case MVS_MODE_FR:
+		case MVS_MODE_HR: {
+			/*
+			 * Remove the DSP frame info header
+			 * Header Format
+			 * Bit 0: bfi applies only for downlink
+			 * Bit 1-2: sid applies for downlink and uplink
+			 * Bit 3: taf applies only for downlink
+			 * MVS_MODE_HR
+			 * Bit 4: ufi applies only for downlink
+			 */
+			*voc_pkt =
+				((buf_node->frame.header.gsm_frame_type.bfi
+					& 0x01) |
+				((buf_node->frame.header.gsm_frame_type.sid
+					& 0x03) << 1) |
+				((buf_node->frame.header.gsm_frame_type.taf
+					& 0x01) << 3));
+
+			if (audio->mvs_mode == MVS_MODE_HR) {
+				*voc_pkt = (*voc_pkt |
+				((buf_node->frame.header.gsm_frame_type.ufi
+				& 0x01) << 4) |
+				((0 & 0x07) << 5));
+			} else {
+				*voc_pkt = (*voc_pkt |
+				((0 & 0x0F) << 4));
+			}
+
+			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;
 
@@ -523,6 +600,10 @@
 	uint32_t media_type;
 
 	switch (mvs_mode) {
+	case MVS_MODE_IS733:
+		media_type = VSS_MEDIA_ID_13K_MODEM;
+		break;
+
 	case MVS_MODE_IS127:
 		media_type = VSS_MEDIA_ID_EVRC_MODEM;
 		break;
@@ -539,6 +620,18 @@
 		media_type = VSS_MEDIA_ID_AMR_NB_MODEM;
 		break;
 
+	case MVS_MODE_EFR:
+		media_type = VSS_MEDIA_ID_EFR_MODEM;
+		break;
+
+	case MVS_MODE_FR:
+		media_type = VSS_MEDIA_ID_FR_MODEM;
+		break;
+
+	case MVS_MODE_HR:
+		media_type = VSS_MEDIA_ID_HR_MODEM;
+		break;
+
 	case MVS_MODE_LINEAR_PCM:
 		media_type = VSS_MEDIA_ID_PCM_NB;
 		break;
@@ -555,6 +648,7 @@
 		media_type = VSS_MEDIA_ID_G729;
 		break;
 
+	case MVS_MODE_G711:
 	case MVS_MODE_G711A:
 		if (rate_type == MVS_G711A_MODE_MULAW)
 			media_type = VSS_MEDIA_ID_G711_MULAW;
@@ -580,10 +674,15 @@
 	uint32_t network_type;
 
 	switch (mvs_mode) {
+	case MVS_MODE_IS733:
 	case MVS_MODE_IS127:
 	case MVS_MODE_4GV_NB:
 	case MVS_MODE_AMR:
+	case MVS_MODE_EFR:
+	case MVS_MODE_FR:
+	case MVS_MODE_HR:
 	case MVS_MODE_LINEAR_PCM:
+	case MVS_MODE_G711:
 	case MVS_MODE_PCM:
 	case MVS_MODE_G729A:
 	case MVS_MODE_G711A:
diff --git a/arch/arm/mach-msm/qdsp6v2/q6voice.c b/arch/arm/mach-msm/qdsp6v2/q6voice.c
index 058e281..34169c0 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6voice.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6voice.c
@@ -1117,6 +1117,7 @@
 
 	/* Set encoder properties. */
 	switch (common.mvs_info.media_type) {
+	case VSS_MEDIA_ID_13K_MODEM:
 	case VSS_MEDIA_ID_4GV_NB_MODEM:
 	case VSS_MEDIA_ID_4GV_WB_MODEM:
 	case VSS_MEDIA_ID_EVRC_MODEM: {
@@ -1253,6 +1254,9 @@
 		break;
 	}
 
+	case VSS_MEDIA_ID_EFR_MODEM:
+	case VSS_MEDIA_ID_FR_MODEM:
+	case VSS_MEDIA_ID_HR_MODEM:
 	case VSS_MEDIA_ID_G729:
 	case VSS_MEDIA_ID_G711_ALAW:
 	case VSS_MEDIA_ID_G711_MULAW: {
diff --git a/include/linux/msm_audio_mvs.h b/include/linux/msm_audio_mvs.h
index c934aee..2813c8f 100644
--- a/include/linux/msm_audio_mvs.h
+++ b/include/linux/msm_audio_mvs.h
@@ -108,10 +108,18 @@
 
 #define MVS_MAX_VOC_PKT_SIZE 640
 
+struct gsm_header {
+	uint8_t bfi;
+	uint8_t sid;
+	uint8_t taf;
+	uint8_t ufi;
+};
+
 struct q6_msm_audio_mvs_frame {
 	union {
 	uint32_t frame_type;
 	uint32_t packet_rate;
+	struct gsm_header gsm_frame_type;
 	} header;
 	uint32_t len;
 	uint8_t voc_pkt[MVS_MAX_VOC_PKT_SIZE];