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

Pierre-Louis Bossart pierre-louis.bossart at linux.intel.com
Thu Mar 15 13:08:00 CET 2018



On 03/15/2018 07:01 AM, Keyon Jie wrote:
> 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 | 45 +++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 45 insertions(+)
>
> diff --git a/src/drivers/apl-ssp.c b/src/drivers/apl-ssp.c
> index 1ee107c..a863b44 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,11 @@ static inline int ssp_set_config(struct dai *dai,
>   	uint32_t dummy_stop;
>   	uint32_t frame_len = 0;
>   	uint32_t bdiv_min;
> +	uint32_t tft;
> +	uint32_t rft;
> +	uint32_t active_tx_slots = 2;
> +	uint32_t active_rx_slots = 2;
> +
>   	bool inverted_frame = false;
>   	int ret = 0;
>   
> @@ -353,6 +371,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 +392,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 +432,27 @@ static inline int ssp_set_config(struct dai *dai,
>   	/* bypass divider for MCLK */
>   	mdivr = 0x00000fff;
>   
> +	/* setting TFT and RFT */
> +	switch (config->sample_valid_bits) {
> +	case 16:
> +		/* use 2 bytes for each slot */
> +		tft = active_tx_slots * 2;
> +		rft = active_rx_slots * 2;
> +		break;
> +	case 24:
> +	case 32:
> +		/* use 4 bytes for each slot */
> +		tft = active_tx_slots * 4;
> +		rft = active_rx_slots * 4;
> +		break;
> +	default:
> +		trace_ssp_error("ecd");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	sscr3 |= SSCR3_TX(tft) | SSCR3_RX(rft);
Looks good enough to me, we may want to come back and revisit watermark 
levels later. Some implementations use half of the FIFO, some fill/empty 
it as soon as possible, not sure what makes sense and if it needs to be 
configured differently for specific applications, e.g. if you want ultra 
low latency.

> +
>   	trace_ssp("coe");
>   	ssp_write(dai, SSCR0, sscr0);
>   	ssp_write(dai, SSCR1, sscr1);



More information about the Sound-open-firmware mailing list