ASoC: msm: qdsp6: Add new AFE API supported by q6

Add new I2S AFE API command to q6 to support multiple
audio formats to I2S port including L-PCM, compressed,
L-PCM packed in IEC-60958, and compressed in IEC-60958.

Change-Id: Ia4a902d750a62bd183f45d1d72359596822be6dd
Signed-off-by: Kuirong Wang <kuirongw@codeaurora.org>
diff --git a/arch/arm/mach-msm/qdsp6v2/snddev_icodec.c b/arch/arm/mach-msm/qdsp6v2/snddev_icodec.c
index a1bdcfd..216d982 100644
--- a/arch/arm/mach-msm/qdsp6v2/snddev_icodec.c
+++ b/arch/arm/mach-msm/qdsp6v2/snddev_icodec.c
@@ -367,6 +367,7 @@
 	afe_config.mi2s.channel = afe_channel_mode;
 	afe_config.mi2s.bitwidth = 16;
 	afe_config.mi2s.line = 1;
+	afe_config.mi2s.format = MSM_AFE_I2S_FORMAT_LPCM;
 	if (msm_codec_i2s_slave_mode)
 		afe_config.mi2s.ws = 0;
 	else
@@ -485,6 +486,7 @@
 	afe_config.mi2s.channel = afe_channel_mode;
 	afe_config.mi2s.bitwidth = 16;
 	afe_config.mi2s.line = 1;
+	afe_config.mi2s.format = MSM_AFE_I2S_FORMAT_LPCM;
 	if (msm_codec_i2s_slave_mode)
 		afe_config.mi2s.ws = 0;
 	else
diff --git a/arch/arm/mach-msm/qdsp6v2/snddev_mi2s.c b/arch/arm/mach-msm/qdsp6v2/snddev_mi2s.c
index db27d9e..a99b600 100644
--- a/arch/arm/mach-msm/qdsp6v2/snddev_mi2s.c
+++ b/arch/arm/mach-msm/qdsp6v2/snddev_mi2s.c
@@ -313,6 +313,8 @@
 		goto error_invalid_data;
 	}
 	afe_config.mi2s.ws = 1;
+	afe_config.mi2s.format = MSM_AFE_I2S_FORMAT_LPCM;
+
 	rc = afe_open(snddev_mi2s_data->copp_id, &afe_config,
 		dev_info->sample_rate);
 
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 85da871..5408a52 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -225,7 +225,8 @@
 				/* i2s stereo = 3 */
 	u16	ws;		/* 0, word select signal from external source */
 				/* 1, word select signal from internal source */
-	u16	reserved;
+	u16	format;	/* don't touch this field if it is not for */
+				/* AFE_PORT_CMD_I2S_CONFIG opcode */
 } __attribute__ ((packed));
 
 struct afe_port_hdmi_cfg {
@@ -298,6 +299,7 @@
 #define AFE_PORT_AUDIO_IF_CONFIG 0x000100d3
 #define AFE_PORT_AUDIO_SLIM_SCH_CONFIG 0x000100e4
 #define AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG	0x000100D9
+#define AFE_PORT_CMD_I2S_CONFIG	0x000100E7
 
 union afe_port_config {
 	struct afe_port_pcm_cfg           pcm;
diff --git a/include/sound/q6afe.h b/include/sound/q6afe.h
index 2d0f53f..9893075 100644
--- a/include/sound/q6afe.h
+++ b/include/sound/q6afe.h
@@ -21,6 +21,11 @@
 #define MSM_AFE_6CHANNELS   6
 #define MSM_AFE_8CHANNELS   8
 
+#define MSM_AFE_I2S_FORMAT_LPCM		0
+#define MSM_AFE_I2S_FORMAT_COMPR		1
+#define MSM_AFE_I2S_FORMAT_IEC60958_LPCM	2
+#define MSM_AFE_I2S_FORMAT_IEC60958_COMPR	3
+
 #define MSM_AFE_PORT_TYPE_RX 0
 #define MSM_AFE_PORT_TYPE_TX 1
 
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index bac432d..535f39b 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -77,6 +77,7 @@
 		if (data->opcode == APR_BASIC_RSP_RESULT) {
 			switch (payload[0]) {
 			case AFE_PORT_AUDIO_IF_CONFIG:
+			case AFE_PORT_CMD_I2S_CONFIG:
 			case AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG:
 			case AFE_PORT_AUDIO_SLIM_SCH_CONFIG:
 			case AFE_PORT_CMD_STOP:
@@ -444,6 +445,26 @@
 		case SLIMBUS_4_TX:
 			config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
 		break;
+		case MI2S_TX:
+		case MI2S_RX:
+		case SECONDARY_I2S_RX:
+		case SECONDARY_I2S_TX:
+		case PRIMARY_I2S_RX:
+		case PRIMARY_I2S_TX:
+			/* AFE_PORT_CMD_I2S_CONFIG command is not supported
+			 * in the LPASS EL 1.0. So we have to distiguish
+			 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
+			 * AFE_PORT_AUDIO_IF_CONFIG	to use. If the format
+			 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
+			 * to make the backward compatible.
+			 */
+			pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
+					 afe_config->mi2s.format);
+			if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
+				config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+			else
+				config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
+		break;
 		default:
 			config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
 		break;
@@ -533,7 +554,43 @@
 	config.hdr.src_port = 0;
 	config.hdr.dest_port = 0;
 	config.hdr.token = 0;
-	config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+	switch (port_id) {
+	case SLIMBUS_0_RX:
+	case SLIMBUS_0_TX:
+	case SLIMBUS_1_RX:
+	case SLIMBUS_1_TX:
+	case SLIMBUS_2_RX:
+	case SLIMBUS_2_TX:
+	case SLIMBUS_3_RX:
+	case SLIMBUS_3_TX:
+	case SLIMBUS_4_RX:
+	case SLIMBUS_4_TX:
+		config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
+	break;
+	case MI2S_TX:
+	case MI2S_RX:
+	case SECONDARY_I2S_RX:
+	case SECONDARY_I2S_TX:
+	case PRIMARY_I2S_RX:
+	case PRIMARY_I2S_TX:
+		/* AFE_PORT_CMD_I2S_CONFIG command is not supported
+		 * in the LPASS EL 1.0. So we have to distiguish
+		 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
+		 * AFE_PORT_AUDIO_IF_CONFIG	to use. If the format
+		 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
+		 * to make the backward compatible.
+		 */
+		pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
+				 afe_config->mi2s.format);
+		if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
+			config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+		else
+			config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
+	break;
+	default:
+		config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+	break;
+	}
 
 	if (afe_validate_port(port_id) < 0) {