From: Tomasz Lauda tomasz.lauda@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@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