cnl: ssp: fix ssp settings

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>
This commit is contained in:
Tomasz Lauda 2018-03-15 17:05:44 +01:00 committed by Liam Girdwood
parent 856f768e3a
commit 4c1d449543
2 changed files with 19 additions and 14 deletions

View File

@ -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;

View File

@ -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