[Sound-open-firmware] [PATCH] apl-ssp: fix padding bit issues in I2S/LEFT_J mode

Jie, Yang yang.jie at intel.com
Fri Apr 13 06:34:48 CEST 2018


>-----Original Message-----
>From: sound-open-firmware-bounces at alsa-project.org [mailto:sound-open-
>firmware-bounces at alsa-project.org] On Behalf Of Pierre-Louis Bossart
>Sent: Friday, April 13, 2018 6:27 AM
>To: sound-open-firmware at alsa-project.org
>Cc: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
>Subject: [Sound-open-firmware] [PATCH] apl-ssp: fix padding bit issues in
>I2S/LEFT_J mode
>
>The current code doesn't work for I2S/LEFT_J when the slot width and number of
>valid bits don't match (e.g. 24 bit data in 32-bit slot).
>
>In I2S/LEFT_J mode, the padding is not at the end of the frame but at the end of
>each slot, and is evenly distributed between the two left and right phases.
>
>Fix by using DMYSTOP for I2S/LEFT_J, and only program SSPSP2 for DSP_A and
>DSP_B modes
>
>Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
>---
> src/drivers/apl-ssp.c | 79 ++++++++++++++++++++++++++++++++++++++++-------
>----
> 1 file changed, 63 insertions(+), 16 deletions(-)
>
>diff --git a/src/drivers/apl-ssp.c b/src/drivers/apl-ssp.c index a02d934..3a97cb8
>100644
>--- a/src/drivers/apl-ssp.c
>+++ b/src/drivers/apl-ssp.c
>@@ -107,6 +107,7 @@ static inline int ssp_set_config(struct dai *dai,
> 	uint32_t data_size;
> 	uint32_t start_delay;
> 	uint32_t frame_end_padding;
>+	uint32_t slot_end_padding;
> 	uint32_t frame_len = 0;
> 	uint32_t bdiv_min;
> 	uint32_t tft;
>@@ -299,6 +300,20 @@ static inline int ssp_set_config(struct dai *dai,
> 		goto out;
> 	}
>
>+	bdiv_min = config->ssp.tdm_slots * config->ssp.sample_valid_bits;
>+	if (bdiv < bdiv_min) {
>+		trace_ssp_error("ecc");
>+		ret = -EINVAL;
>+		goto out;
>+	}
>+
>+	frame_end_padding = bdiv - bdiv_min;
>+	if (frame_end_padding > SSPSP2_FEP_MASK) {
>+		trace_ssp_error("ecd");
>+		ret = -EINVAL;
>+		goto out;
>+	}
>+
> 	/* format */
> 	switch (config->format & SOF_DAI_FMT_FORMAT_MASK) {
> 	case SOF_DAI_FMT_I2S:
>@@ -325,6 +340,28 @@ static inline int ssp_set_config(struct dai *dai,
> 		sspsp |= SSPSP_SFRMP(inverted_frame);
> 		sspsp |= SSPSP_FSRT;
>
>+		/*
>+		 *  for I2S/LEFT_J, the padding has to happen at the end
>+		 * of each slot
>+		 */
>+		if (frame_end_padding % 2) {
>+			trace_ssp_error("ece");
>+			ret = -EINVAL;
>+			goto out;
>+		}
>+
>+		slot_end_padding = frame_end_padding / 2;
>+
>+		if (slot_end_padding > 15) {
>+			/* can't handle padding over 15 bits */
>+			trace_ssp_error("ecf");
>+			ret = -EINVAL;
>+			goto out;
>+		}
>+
>+		sspsp |= SSPSP_EDMYSTOP((slot_end_padding >> 2) & 0x3);
>+		sspsp |= SSPSP_DMYSTOP(slot_end_padding & 0x3);
>+
> 		break;
>
> 	case SOF_DAI_FMT_LEFT_J:
>@@ -353,6 +390,28 @@ static inline int ssp_set_config(struct dai *dai,
> 		 */
> 		sspsp |= SSPSP_SFRMP(!inverted_frame);
>
>+		/*
>+		 *  for I2S/LEFT_J, the padding has to happen at the end
>+		 * of each slot
>+		 */
>+		if (frame_end_padding % 2) {
>+			trace_ssp_error("ecg");
>+			ret = -EINVAL;
>+			goto out;
>+		}
>+
>+		slot_end_padding = frame_end_padding / 2;
>+
>+		if (slot_end_padding > 15) {
>+			/* can't handle padding over 15 bits */
>+			trace_ssp_error("ech");
>+			ret = -EINVAL;
>+			goto out;
>+		}
>+
>+		sspsp |= SSPSP_EDMYSTOP((slot_end_padding >> 2) & 0x3);
>+		sspsp |= SSPSP_DMYSTOP(slot_end_padding & 0x3);

We have already macros for those masks, just sent you a patch which you can combine with.

Thanks,
~Keyon

>+
> 		break;
> 	case SOF_DAI_FMT_DSP_A:
>
>@@ -375,6 +434,8 @@ static inline int ssp_set_config(struct dai *dai,
> 		active_tx_slots = hweight_32(config->ssp.tx_slots);
> 		active_rx_slots = hweight_32(config->ssp.rx_slots);
>
>+		sspsp2 |= (frame_end_padding & SSPSP2_FEP_MASK);
>+
> 		break;
> 	case SOF_DAI_FMT_DSP_B:
>
>@@ -396,6 +457,8 @@ static inline int ssp_set_config(struct dai *dai,
> 		active_tx_slots = hweight_32(config->ssp.tx_slots);
> 		active_rx_slots = hweight_32(config->ssp.rx_slots);
>
>+		sspsp2 |= (frame_end_padding & SSPSP2_FEP_MASK);
>+
> 		break;
> 	default:
> 		trace_ssp_error("eca");
>@@ -406,22 +469,6 @@ static inline int ssp_set_config(struct dai *dai,
> 	sspsp |= SSPSP_STRTDLY(start_delay);
> 	sspsp |= SSPSP_SFRMWDTH(frame_len);
>
>-	bdiv_min = config->ssp.tdm_slots * config->ssp.sample_valid_bits;
>-	if (bdiv < bdiv_min) {
>-		trace_ssp_error("ecc");
>-		ret = -EINVAL;
>-		goto out;
>-	}
>-
>-	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->ssp.sample_valid_bits;
>
> 	if (data_size > 16)
>--
>2.14.1
>
>_______________________________________________
>Sound-open-firmware mailing list
>Sound-open-firmware at alsa-project.org
>http://mailman.alsa-project.org/mailman/listinfo/sound-open-firmware


More information about the Sound-open-firmware mailing list