Merge pull request #181 from plbossart/fix/mdivc

apl-ssp: do not override common MDIVCTRL register
diff --git a/src/drivers/apl-ssp.c b/src/drivers/apl-ssp.c
index 36bb02c..1dd1386 100644
--- a/src/drivers/apl-ssp.c
+++ b/src/drivers/apl-ssp.c
@@ -576,8 +576,10 @@
 			goto out;
 	}
 
-	tft = MIN(8, sample_width * active_tx_slots);
-	rft = MIN(8, sample_width * active_rx_slots);
+	tft = MIN(SSP_FIFO_DEPTH - SSP_FIFO_WATERMARK,
+		  sample_width * active_tx_slots);
+	rft = MIN(SSP_FIFO_DEPTH - SSP_FIFO_WATERMARK,
+		  sample_width * active_rx_slots);
 
 	sscr3 |= SSCR3_TX(tft) | SSCR3_RX(rft);
 
diff --git a/src/drivers/byt-ssp.c b/src/drivers/byt-ssp.c
index a940ff9..4759d29 100644
--- a/src/drivers/byt-ssp.c
+++ b/src/drivers/byt-ssp.c
@@ -54,6 +54,32 @@
 	return count;
 }
 
+/* empty SSP receive FIFO */
+static void ssp_empty_rx_fifo(struct dai *dai)
+{
+	struct ssp_pdata *ssp = dai_get_drvdata(dai);
+	uint32_t sssr;
+	uint32_t entries;
+	uint32_t i;
+
+	spin_lock(&ssp->lock);
+
+	sssr = ssp_read(dai, SSSR);
+
+	/* clear interrupt */
+	if (sssr & SSSR_ROR)
+		ssp_write(dai, SSSR, sssr);
+
+	/* empty fifo */
+	if (sssr & SSSR_RNE) {
+		entries = SFIFOL_RFL(ssp_read(dai, SFIFOL));
+		for (i = 0; i < entries + 1; i++)
+			ssp_read(dai, SSDR);
+	}
+
+	spin_unlock(&ssp->lock);
+}
+
 /* save SSP context prior to entering D3 */
 static int ssp_context_store(struct dai *dai)
 {
@@ -500,6 +526,7 @@
 	if (direction == DAI_DIR_CAPTURE &&
 	    ssp->state[SOF_IPC_STREAM_CAPTURE] == COMP_STATE_ACTIVE) {
 		ssp_update_bits(dai, SSCR1, SSCR1_RSRE, 0);
+		ssp_empty_rx_fifo(dai);
 		ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PAUSED;
 		trace_ssp("Ss0");
 	}
@@ -598,6 +625,7 @@
 	platform_interrupt_unmask(ssp_irq(dai), 1);
 	interrupt_enable(ssp_irq(dai));
 
+	ssp_empty_rx_fifo(dai);
 	return 0;
 }
 
diff --git a/src/drivers/dmic.c b/src/drivers/dmic.c
index 47c966d..69ee2fd 100644
--- a/src/drivers/dmic.c
+++ b/src/drivers/dmic.c
@@ -1150,6 +1150,18 @@
 		goto finish;
 	}
 
+	if (prm->fifo_bits_a != 16 && prm->fifo_bits_a != 32) {
+		trace_dmic_error("fba");
+		ret = -EINVAL;
+		goto finish;
+	}
+
+	if (prm->fifo_bits_b != 16 && prm->fifo_bits_b != 32) {
+		trace_dmic_error("fbb");
+		ret = -EINVAL;
+		goto finish;
+	}
+
 	/* Match and select optimal decimators configuration for FIFOs A and B
 	 * paths. This setup phase is still abstract. Successful completion
 	 * points struct cfg to FIR coefficients and contains the scale value
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c
index 46988dc..d4f13bf 100644
--- a/src/drivers/dw-dma.c
+++ b/src/drivers/dw-dma.c
@@ -1188,6 +1188,8 @@
 			switch (next.size) {
 			case DMA_RELOAD_END:
 				p->chan[i].status = COMP_STATE_PREPARE;
+				p->chan[i].lli_current =
+					(struct dw_lli2 *)p->chan[i].lli_current->llp;
 				break;
 			case DMA_RELOAD_LLI:
 				dw_dma_chan_reload_lli(dma, i);
diff --git a/src/include/sof/ssp.h b/src/include/sof/ssp.h
index 8fa0df7..b5e8175 100644
--- a/src/include/sof/ssp.h
+++ b/src/include/sof/ssp.h
@@ -61,6 +61,7 @@
 	defined CONFIG_CHERRYTRAIL ||\
 	defined CONFIG_BROADWELL ||\
 	defined CONFIG_HASWELL
+#define SFIFOL		0x68
 #define SFIFOTT		0x6C
 #define SSCR3		0x70
 #define SSCR4		0x74
@@ -198,6 +199,10 @@
 #define SFIFOTT_TX(x)		((x) - 1)
 #define SFIFOTT_RX(x)		(((x) - 1) << 16)
 
+/* SFIFOL bits */
+#define SFIFOL_TFL(x)		((x) & 0xFFFF)
+#define SFIFOL_RFL(x)		((x) >> 16)
+
 #if defined CONFIG_APOLLOLAKE || defined CONFIG_CANNONLAKE ||\
 	defined CONFIG_HASWELL || defined CONFIG_BROADWELL
 #define SSTSA_TSEN			BIT(8)
diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h
index 62310d6..4cf569f 100644
--- a/src/include/uapi/ipc.h
+++ b/src/include/uapi/ipc.h
@@ -329,8 +329,8 @@
 	uint32_t fifo_fs_a;  /* FIFO A sample rate in Hz (8000..96000) */
 	uint32_t fifo_fs_b;  /* FIFO B sample rate in Hz (8000..96000) */
 	/* TODO: FIFO word lengths can be retrieved from SOF_DAI_FMT */
-	uint16_t fifo_bits_a; /* FIFO A word length (16 or 24) */
-	uint16_t fifo_bits_b; /* FIFO B word length (16 or 24) */
+	uint16_t fifo_bits_a; /* FIFO A word length (16 or 32) */
+	uint16_t fifo_bits_b; /* FIFO B word length (16 or 32) */
 	uint16_t duty_min;    /* Min. mic clock duty cycle in % (20..80) */
 	uint16_t duty_max;    /* Max. mic clock duty cycle in % (min..80) */
 	uint32_t num_pdm_active; /* Number of active controllers */
diff --git a/src/ipc/ipc.c b/src/ipc/ipc.c
index 3e23d9c..25d4471 100644
--- a/src/ipc/ipc.c
+++ b/src/ipc/ipc.c
@@ -333,8 +333,10 @@
 
 int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config)
 {
+	struct sof_ipc_comp_dai *dai;
 	struct ipc_comp_dev *icd;
 	struct list_item *clist;
+	struct comp_dev *dev;
 	int ret = 0;
 
 	/* for each component */
@@ -347,10 +349,20 @@
 			switch (icd->cd->comp.type) {
 			case SOF_COMP_DAI:
 			case SOF_COMP_SG_DAI:
-				ret = comp_dai_config(icd->cd, config);
-				if (ret < 0) {
-					trace_ipc_error("eCD");
-					return ret;
+				dev = icd->cd;
+				dai = (struct sof_ipc_comp_dai *)&dev->comp;
+
+				/*
+				 * set config if comp dai_index matches
+				 * config dai_index.
+				 */
+				if (dai->dai_index == config->dai_index &&
+				    dai->type == config->type) {
+					ret = comp_dai_config(dev, config);
+					if (ret < 0) {
+						trace_ipc_error("eCD");
+						return ret;
+					}
 				}
 				break;
 			default:
diff --git a/src/platform/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h
index aa78732..d611a1c 100644
--- a/src/platform/apollolake/include/platform/platform.h
+++ b/src/platform/apollolake/include/platform/platform.h
@@ -121,6 +121,12 @@
 /* minimal L1 exit time in cycles */
 #define PLATFORM_FORCE_L1_EXIT_TIME	585
 
+/* the SSP port fifo depth */
+#define SSP_FIFO_DEPTH		16
+
+/* the watermark for the SSP fifo depth setting */
+#define SSP_FIFO_WATERMARK	8
+
 /* Platform defined panic code */
 static inline void platform_panic(uint32_t p)
 {
diff --git a/src/platform/apollolake/include/platform/shim.h b/src/platform/apollolake/include/platform/shim.h
index 598f1c8..b18bb94 100644
--- a/src/platform/apollolake/include/platform/shim.h
+++ b/src/platform/apollolake/include/platform/shim.h
@@ -158,6 +158,19 @@
 
 #define SHIM_L2_MECS		(SHIM_BASE + 0xd0)
 
+#define SHIM_LPGPDMAC(x)	(0x1110 + (2 * x))
+#define SHIM_LPGPDMAC_CTLOSEL	(1 << 15)
+#define SHIM_LPGPDMAC_CHOSEL	(0xFF)
+
+#define SHIM_DSPIOPO		0x1118
+#define SHIM_DSPIOPO_DMICOSEL	(1 << 0)
+#define SHIM_DSPIOPO_I2SOSEL	(0x3F << 8)
+
+#define SHIM_GENO		0x111C
+#define SHIM_GENO_SHIMOSEL	(1 << 0)
+#define SHIM_GENO_MDIVOSEL	(1 << 1)
+#define SHIM_GENO_DIOPTOSEL	(1 << 2)
+
 #define SHIM_L2_CACHE_CTRL	(SHIM_BASE + 0x500)
 #define SHIM_L2_PREF_CFG	(SHIM_BASE + 0x508)
 #define SHIM_L2_CACHE_PREF	(SHIM_BASE + 0x510)
diff --git a/src/platform/apollolake/platform.c b/src/platform/apollolake/platform.c
index 684cc74..4c5173f 100644
--- a/src/platform/apollolake/platform.c
+++ b/src/platform/apollolake/platform.c
@@ -194,12 +194,30 @@
 	dcache_writeback_region((void *)HP_SRAM_WIN3_BASE, HP_SRAM_WIN3_SIZE);
 }
 
+/* init HW  */
+static void platform_init_hw(void)
+{
+	io_reg_write(SHIM_GENO, SHIM_GENO_SHIMOSEL |
+		     SHIM_GENO_MDIVOSEL | SHIM_GENO_DIOPTOSEL);
+
+	io_reg_write(SHIM_DSPIOPO,
+		     SHIM_DSPIOPO_DMICOSEL | SHIM_DSPIOPO_I2SOSEL);
+
+	io_reg_write(SHIM_LPGPDMAC(0),
+		     SHIM_LPGPDMAC_CHOSEL | SHIM_LPGPDMAC_CTLOSEL);
+	io_reg_write(SHIM_LPGPDMAC(1),
+		     SHIM_LPGPDMAC_CHOSEL | SHIM_LPGPDMAC_CTLOSEL);
+}
+
 int platform_init(struct sof *sof)
 {
 	struct dai *ssp;
 	struct dai *dmic0;
 	int i, ret;
 
+	trace_point(TRACE_BOOT_PLATFORM_ENTRY);
+	platform_init_hw();
+
 	platform_interrupt_init();
 
 	trace_point(TRACE_BOOT_PLATFORM_MBOX);
diff --git a/src/platform/cannonlake/include/platform/platform.h b/src/platform/cannonlake/include/platform/platform.h
index 67566b2..69b06e9 100644
--- a/src/platform/cannonlake/include/platform/platform.h
+++ b/src/platform/cannonlake/include/platform/platform.h
@@ -118,6 +118,12 @@
 /* minimal L1 exit time in cycles */
 #define PLATFORM_FORCE_L1_EXIT_TIME	482
 
+/* the SSP port fifo depth */
+#define SSP_FIFO_DEPTH		16
+
+/* the watermark for the SSP fifo depth setting */
+#define SSP_FIFO_WATERMARK	8
+
 /* Platform defined trace code */
 static inline void platform_panic(uint32_t p)
 {