[Sound-open-firmware] [PATCH] drivers: ssp: Improve SSP I2S and DSP mode generation from topology.
Improve support for I2S and DSP modes alongside using topology data to define the mode configuration. Add trace errors to reject any unsupported configurations.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/drivers/ssp.c | 75 +++++++++++++++++++++++++------------------------- src/include/reef/ssp.h | 20 +++++++++++++- 2 files changed, 56 insertions(+), 39 deletions(-)
diff --git a/src/drivers/ssp.c b/src/drivers/ssp.c index 1a1000a..0b7589a 100644 --- a/src/drivers/ssp.c +++ b/src/drivers/ssp.c @@ -69,8 +69,8 @@ static inline int ssp_set_config(struct dai *dai, struct sof_ipc_dai_config *config) { struct ssp_pdata *ssp = dai_get_drvdata(dai); - uint32_t sscr0, sscr1, sspsp, sfifott, mdiv, bdiv; - uint32_t stop_size, data_size; + uint32_t sscr0, sscr1, sscr2, sscr3, sspsp, sfifott, mdiv, bdiv; + uint32_t data_size, frame_len = 0; int ret = 0;
spin_lock(&ssp->lock); @@ -78,7 +78,7 @@ static inline int ssp_set_config(struct dai *dai, /* is playback/capture already running */ if (ssp->state[DAI_DIR_PLAYBACK] > SSP_STATE_IDLE || ssp->state[DAI_DIR_CAPTURE] > SSP_STATE_IDLE) { - trace_ssp_error("wsS"); + trace_ssp_error("ec1"); goto out; }
@@ -87,6 +87,8 @@ static inline int ssp_set_config(struct dai *dai, /* reset SSP settings */ sscr0 = 0; sscr1 = 0; + sscr2 = 0xc1; + sscr3 = 0x2c018; sspsp = 0;
ssp->config = *config; @@ -102,6 +104,7 @@ static inline int ssp_set_config(struct dai *dai, break; case SOF_DAI_FMT_CBS_CFS: sscr1 |= SSCR1_SCFR | SSCR1_RWOT; + sscr3 |= SSCR3_I2S_FRM_MST | SSCR3_I2S_CLK_MST; break; case SOF_DAI_FMT_CBM_CFS: sscr1 |= SSCR1_SFRMDIR; @@ -112,6 +115,7 @@ static inline int ssp_set_config(struct dai *dai, case SSP_CLK_DEFAULT: break; default: + trace_ssp_error("ec2"); ret = -EINVAL; goto out; } @@ -129,6 +133,7 @@ static inline int ssp_set_config(struct dai *dai, sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP; break; default: + trace_ssp_error("ec3"); ret = -EINVAL; goto out; } @@ -148,13 +153,14 @@ static inline int ssp_set_config(struct dai *dai, sscr0 |= SSCR0_NCS | SSCR0_MOD; break; default: + trace_ssp_error("ec4"); ret = -EINVAL; goto out; }
/* BCLK is generated from MCLK - must be divisable */ if (config->mclk % config->bclk) { - trace_ssp_error("ec1"); + trace_ssp_error("ec5"); ret = -EINVAL; goto out; } @@ -162,17 +168,17 @@ static inline int ssp_set_config(struct dai *dai, /* divisor must be within SCR range */ mdiv = (config->mclk / config->bclk)- 1; if (mdiv > (SSCR0_SCR_MASK >> 8)) { - trace_ssp_error("ec2"); + trace_ssp_error("ec6"); ret = -EINVAL; goto out; }
- /* set the divisor */ + /* set the SCR divisor */ sscr0 |= SSCR0_SCR(mdiv);
/* calc frame width based on BCLK and rate - must be divisable */ if (config->bclk % config->fclk) { - trace_ssp_error("ec3"); + trace_ssp_error("ec7"); ret = -EINVAL; goto out; } @@ -180,61 +186,60 @@ static inline int ssp_set_config(struct dai *dai, /* must be enouch BCLKs for data */ bdiv = config->bclk / config->fclk; if (bdiv < config->sample_container_bits * config->num_slots) { - trace_ssp_error("ec4"); + trace_ssp_error("ec8"); ret = -EINVAL; goto out; }
/* sample_container_bits must be <= 38 for SSP */ if (config->sample_container_bits > 38) { - trace_ssp_error("ec5"); + trace_ssp_error("ec9"); ret = -EINVAL; goto out; }
- trace_value(mdiv); - trace_value(bdiv); - /* format */ switch (config->format & SOF_DAI_FMT_FORMAT_MASK) { case SOF_DAI_FMT_I2S:
- /* calculate dummy stop size and include dummy start */ - stop_size = config->sample_container_bits - - (config->sample_valid_bits) - 1; - trace_value(stop_size); - if (stop_size > 3) { - trace_ssp_error("ec6"); - ret = -EINVAL; - goto out; - } + /* enable I2S mode */ + sscr3 |= SSCR3_I2S_ENA | SSCR3_I2S_TX_ENA | SSCR3_I2S_RX_ENA;
sscr0 |= SSCR0_PSP; sscr1 |= SSCR1_TRAIL; - sspsp |= SSPSP_SFRMWDTH(config->sample_container_bits); - /* subtract 1 for I2S start delay */ - sspsp |= SSPSP_SFRMDLY((config->sample_container_bits - 1) * 2); - sspsp |= SSPSP_DMYSTRT(1); - sspsp |= SSPSP_DMYSTOP(stop_size); + + /* set asserted frame length */ + frame_len = config->sample_container_bits; break; case SOF_DAI_FMT_DSP_A: - sspsp |= SSPSP_FSRT; + sscr0 |= SSCR0_PSP | SSCR0_MOD | SSCR0_FRDC(config->num_slots); + sscr1 |= SSCR1_TRAIL; + sspsp |= SSPSP_SFRMWDTH(1) | SSPSP_SFRMDLY(2); case SOF_DAI_FMT_DSP_B: - sscr0 |= SSCR0_PSP; + sscr0 |= SSCR0_PSP | SSCR0_MOD | SSCR0_FRDC(config->num_slots); sscr1 |= SSCR1_TRAIL; + sspsp |= SSPSP_SFRMWDTH(1); break; default: + trace_ssp_error("eca"); ret = -EINVAL; goto out; }
+ /* set frame length and slot mask in I2s & PCM modes */ + ssp_write(dai, SSCR4, + SSCR4_FRM_CLOCKS(config->sample_container_bits << 1)); + ssp_write(dai, SSCR5, SSCR5_FRM_ASRT_CLOCKS(frame_len)); + ssp_write(dai, SSTSA, config->tx_slot_mask); + ssp_write(dai, SSRSA, config->rx_slot_mask); + /* sample data size on SSP FIFO */ switch (config->sample_valid_bits) { case 16: /* 2 * 16bit packed into 32bit FIFO */ data_size = 32; break; default: - data_size = config->sample_valid_bits; + data_size = config->sample_container_bits; }
if (data_size > 16) @@ -242,20 +247,14 @@ static inline int ssp_set_config(struct dai *dai, else sscr0 |= SSCR0_DSIZE(data_size);
- /* watermarks - TODO: do we still need old sscr1 method ?? */ - sscr1 |= (SSCR1_TX(4) | SSCR1_RX(4)); - /* watermarks - (RFT + 1) should equal DMA SRC_MSIZE */ sfifott = (SFIFOTT_TX(8) | SFIFOTT_RX(8)); -#if 0 - if (dai->config.lbm) - sscr1 |= SSCR1_LBM; - else - sscr1 &= ~SSCR1_LBM; -#endif + trace_ssp("coe"); ssp_write(dai, SSCR0, sscr0); ssp_write(dai, SSCR1, sscr1); + ssp_write(dai, SSCR2, sscr2); + ssp_write(dai, SSCR3, sscr3); ssp_write(dai, SSPSP, sspsp); ssp_write(dai, SFIFOTT, sfifott);
diff --git a/src/include/reef/ssp.h b/src/include/reef/ssp.h index 7e557ed..42efb14 100644 --- a/src/include/reef/ssp.h +++ b/src/include/reef/ssp.h @@ -55,7 +55,11 @@ #define SSTSA 0x30 #define SSRSA 0x34 #define SSTSS 0x38 +#define SSCR2 0x40 #define SFIFOTT 0x6C +#define SSCR3 0x70 +#define SSCR4 0x74 +#define SSCR5 0x78
extern const struct dai_ops ssp_ops;
@@ -75,7 +79,7 @@ extern const struct dai_ops ssp_ops; #define SSCR0_NCS (1 << 21) #define SSCR0_RIM (1 << 22) #define SSCR0_TUM (1 << 23) -#define SSCR0_FRDC (0x07000000) +#define SSCR0_FRDC(x) ((x - 1) << 24) #define SSCR0_ACS (1 << 30) #define SSCR0_MOD (1 << 31)
@@ -127,6 +131,20 @@ extern const struct dai_ops ssp_ops; #define SSPSP_DMYSTOP(x) ((x) << 23) #define SSPSP_FSRT (1 << 25)
+/* SSCR3 bits */ +#define SSCR3_I2S_FRM_MST (1 << 0) +#define SSCR3_I2S_ENA (1 << 1) +#define SSCR3_I2S_FRM_POL (1 << 2) +#define SSCR3_I2S_TX_ENA (1 << 9) +#define SSCR3_I2S_RX_ENA (1 << 10) +#define SSCR3_I2S_CLK_MST (1 << 16) + +/* SSCR4 bits */ +#define SSCR4_FRM_CLOCKS(x) (x << 7) + +/* SSCR5 bits */ +#define SSCR5_FRM_ASRT_CLOCKS(x) ((x - 1) << 1) + /* SFIFOTT bits */ #define SFIFOTT_TX(x) (x - 1) #define SFIFOTT_RX(x) ((x - 1) << 16)
participants (1)
-
Liam Girdwood