[Sound-open-firmware] [PATCH] cnl: ssp: fix ssp settings

Liam Girdwood liam.r.girdwood at linux.intel.com
Wed Mar 21 10:49:19 CET 2018


From: Tomasz Lauda <tomasz.lauda at linux.intel.com>

We change ssp settings in order to properly transmit and receive data:
1. Use frame end padding instead of dummy stop bits.
   This way alignment bits will be transmitted at the end of whole frame instead of every slot.
2. Disable receive without transmit mode.
3. Do not change the source for MCLK.
4. DSP_A format shouldn't have start delay.

Signed-off-by: Tomasz Lauda <tomasz.lauda at linux.intel.com>
---
 src/drivers/apl-ssp.c  | 30 +++++++++++++++++-------------
 src/include/reef/ssp.h |  3 ++-
 2 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/src/drivers/apl-ssp.c b/src/drivers/apl-ssp.c
index a863b448..81fe96c4 100644
--- a/src/drivers/apl-ssp.c
+++ b/src/drivers/apl-ssp.c
@@ -106,7 +106,7 @@ static inline int ssp_set_config(struct dai *dai,
 	uint32_t i2s_n;
 	uint32_t data_size;
 	uint32_t start_delay;
-	uint32_t dummy_stop;
+	uint32_t frame_end_padding;
 	uint32_t frame_len = 0;
 	uint32_t bdiv_min;
 	uint32_t tft;
@@ -138,13 +138,13 @@ static inline int ssp_set_config(struct dai *dai,
 	sscr0 = SSCR0_PSP | SSCR0_RIM | SSCR0_TIM;
 
 	/* sscr1 dynamic settings are SFRMDIR, SCLKDIR, SCFR */
-	sscr1 = SSCR1_TTE | SSCR1_TTELP | SSCR1_RWOT | SSCR1_TRAIL;
+	sscr1 = SSCR1_TTE | SSCR1_TTELP | SSCR1_TRAIL | SSCR1_RSRE | SSCR1_TSRE;
 
 	/* sscr2 dynamic setting is LJDFD */
 	sscr2 = SSCR2_SDFD | SSCR2_TURM1;
 
 	/* sscr3 dynamic settings are TFT, RFT */
-	sscr3 = 0;
+	sscr3 = SSCR3_TX(8) | SSCR3_RX(8);
 
 	/* sspsp dynamic settings are SCMODE, SFRMP, DMYSTRT, SFRMWDTH */
 	sspsp = 0;
@@ -283,7 +283,7 @@ static inline int ssp_set_config(struct dai *dai,
 		goto out;
 	}
 
-	/* must be enouch BCLKs for data */
+	/* must be enough BCLKs for data */
 	bdiv = config->bclk / config->fclk;
 	if (bdiv < config->sample_container_bits * config->num_slots) {
 		trace_ssp_error("ec8");
@@ -355,7 +355,7 @@ static inline int ssp_set_config(struct dai *dai,
 		break;
 	case SOF_DAI_FMT_DSP_A:
 
-		start_delay = 1;
+		start_delay = 0;
 
 		sscr0 |= SSCR0_MOD | SSCR0_FRDC(config->num_slots);
 
@@ -405,10 +405,6 @@ static inline int ssp_set_config(struct dai *dai,
 	sspsp |= SSPSP_STRTDLY(start_delay);
 	sspsp |= SSPSP_SFRMWDTH(frame_len);
 
-	/*
-	 * [dummy_start][valid_bits_slot[0...n-1]][dummy_stop],
-	 * but don't count dummy_start for dummy_stop calculation.
-	 */
 	bdiv_min = config->num_slots * config->sample_valid_bits;
 	if (bdiv < bdiv_min) {
 		trace_ssp_error("ecc");
@@ -416,10 +412,14 @@ static inline int ssp_set_config(struct dai *dai,
 		goto out;
 	}
 
-	dummy_stop = bdiv - bdiv_min;
-	sspsp |= SSPSP_DMYSTOP(SSPSP_DMYSTOP_MASK & dummy_stop);
-	sspsp |= SSPSP_EDMYSTOP(SSPSP_EDMYSTOP_MASK &
-				(dummy_stop >> SSPSP_DMYSTOP_BITS));
+	frame_end_padding = bdiv - bdiv_min;
+	if (frame_end_padding > SSPSP2_FEP_MASK) {
+		trace_ssp_error("ecd");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	sspsp2 |= (frame_end_padding & SSPSP2_FEP_MASK);
 
 	data_size = config->sample_valid_bits;
 
@@ -428,7 +428,11 @@ static inline int ssp_set_config(struct dai *dai,
 	else
 		sscr0 |= SSCR0_DSIZE(data_size);
 
+#ifdef CONFIG_CANNONLAKE
+	mdivc = 0x1;
+#else
 	mdivc = 0x00100001;
+#endif
 	/* bypass divider for MCLK */
 	mdivr = 0x00000fff;
 
diff --git a/src/include/reef/ssp.h b/src/include/reef/ssp.h
index 453aaabe..770d94cf 100644
--- a/src/include/reef/ssp.h
+++ b/src/include/reef/ssp.h
@@ -167,9 +167,10 @@ extern const struct dai_ops ssp_ops;
 #if defined CONFIG_APOLLOLAKE || defined CONFIG_CANNONLAKE
 #define SSPSP_EDMYSTOP(x)	((x) << 26)
 #define SSPSP_EDMYSTOP_MASK	0x7
+#define SSPSP2_FEP_MASK		0xff
 #define SSTSS		0x38
 #define SSCR2		0x40
-#define SSPSP2	0x44
+#define SSPSP2		0x44
 #define SSCR3		0x48
 #define SSIOC		0x4C
 
-- 
2.14.1



More information about the Sound-open-firmware mailing list