[Sound-open-firmware] [PATCH] apl-ssp: fix capture double speed issue

Keyon Jie yang.jie at linux.intel.com
Wed Mar 14 16:12:12 CET 2018


Previously TFT and RFT are set to 0s which means we are using
threshold level 1, where interrupt asserts for every valid bits
of each slot(e.g. for s16_le capture, interrupts assert for
each 16 bits), but DMAC will treat it as notification of one
full sample(e.g. 32 bits for s16_le stereo) and read those all
bits, this will lead to capture with double speed at format
s16_le stereo.

Here add handle for FIFO trigger Threshold level, set them to
bytes for each full sample(active_slots * valid_bits / 8), and
the issue is fixed.

Signed-off-by: Keyon Jie <yang.jie at linux.intel.com>
---
 src/drivers/apl-ssp.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/src/drivers/apl-ssp.c b/src/drivers/apl-ssp.c
index 1ee107c..ecf70fb 100644
--- a/src/drivers/apl-ssp.c
+++ b/src/drivers/apl-ssp.c
@@ -43,6 +43,19 @@
 #define trace_ssp_error(__e)	trace_error(TRACE_CLASS_SSP, __e)
 #define tracev_ssp(__e)	tracev_event(TRACE_CLASS_SSP, __e)
 
+/* FIXME: move this to a helper and optimize */
+static int hweight_32(uint32_t mask)
+{
+	int i;
+	int count = 0;
+
+	for (i = 0; i < 32; i++) {
+		count += mask & 1;
+		mask >>= 1;
+	}
+	return count;
+}
+
 /* save SSP context prior to entering D3 */
 static int ssp_context_store(struct dai *dai)
 {
@@ -96,6 +109,9 @@ static inline int ssp_set_config(struct dai *dai,
 	uint32_t dummy_stop;
 	uint32_t frame_len = 0;
 	uint32_t bdiv_min;
+	uint32_t active_tx_slots = 2;
+	uint32_t active_rx_slots = 2;
+
 	bool inverted_frame = false;
 	int ret = 0;
 
@@ -353,6 +369,9 @@ static inline int ssp_set_config(struct dai *dai,
 		sspsp |= SSPSP_SFRMP(!inverted_frame);
 		sspsp |= SSPSP_FSRT;
 
+		active_tx_slots = hweight_32(config->tx_slot_mask);
+		active_rx_slots = hweight_32(config->rx_slot_mask);
+
 		break;
 	case SOF_DAI_FMT_DSP_B:
 
@@ -371,6 +390,9 @@ static inline int ssp_set_config(struct dai *dai,
 		 */
 		sspsp |= SSPSP_SFRMP(!inverted_frame);
 
+		active_tx_slots = hweight_32(config->tx_slot_mask);
+		active_rx_slots = hweight_32(config->rx_slot_mask);
+
 		break;
 	default:
 		trace_ssp_error("eca");
@@ -408,6 +430,9 @@ static inline int ssp_set_config(struct dai *dai,
 	/* bypass divider for MCLK */
 	mdivr = 0x00000fff;
 
+	sscr3 |= SSCR3_TX(active_tx_slots * config->sample_valid_bits / 8) |
+		 SSCR3_RX(active_rx_slots * config->sample_valid_bits / 8);
+
 	trace_ssp("coe");
 	ssp_write(dai, SSCR0, sscr0);
 	ssp_write(dai, SSCR1, sscr1);
-- 
2.14.1



More information about the Sound-open-firmware mailing list