ALSA stereo playback issue - channels getting swapped - Colibri iMX6

Hello team,

For my application I needed to interleave two mono streams into a stereo, for quick test I am using the following pipeline with gst-launch:

gst-launch-1.0 -e interleave name=hp_i ! audioconvert ! alsasink
audiotestsrc wave=5 ! audioconvert ! “audio/x-raw,channels=1,channel-mask=(bitmask)0x1” ! queue ! hp_i.sink_0
audiotestsrc wave=0 freq=1000 ! audioconvert ! “audio/x-raw,channels=1,channel-mask=(bitmask)0x2” ! queue ! hp_i.sink_1

This pipeline appeared to work fine initially, but when repeatedly invoked, I noticed that sometimes audio from left channel is heard on right one and vice versa, I am using the primary headphone jack for playback. To isolate the problem between gstreamer elements and ALSA, I recorded the above stream with following pipeline:

gst-launch-1.0 -e interleave name=hp_i ! audioconvert ! wavenc ! filesink location=“stereo-test.wav” audiotestsrc wave=5 ! audioconvert ! queue ! “audio/x-raw,channels=1,channel-mask=(bitmask)0x1” ! hp_i.sink_0 audiotestsrc wave=0 freq=1000 ! audioconvert ! queue ! “audio/x-raw,channels=1,channel-mask=(bitmask)0x2” ! hp_i.sink_1

And cross verified the wave file with audacity, now with aplay stereo-test.wav also I am noticing the same channel swapping issue, out of 10 times at-least twice it is happening for me. Next I tried out the speaker-test program provided here, again the same observation, initial few attempts it appears to work fine but repeated playbacks will lead to channels getting swapped.
Is there a workaround for this problem?

Thanks,
Ravikiran

Hi

I tried to reproduce the issue without success.

Can you give some more information?

  • Do you have something other than the audio application running?
  • Do you have a screen attached? Resolution?
  • Do you stop with and then reexecute the same command line?
  • What is the intervall between stopping and then starting again?
  • Anything else which comes to mind?
  • Any change to the device-tree?
  • Does it get better if you disable DVFS? ‘root@colibri-imx6:~# cpufreq-set -f 996000’

Max

Hi Max,

–>Do you have something other than the audio application running?
Yes, I have a GUI application running, problem is reproducible even after closing the GUI app.

–>Do you have a screen attached? Resolution?
Yes, EDT 7" Display with 800x480px, I tried the gstreamer and speaker-test program without the display and issue is still reproducible.

–>Do you stop with and then reexecute the same command line?
Yes, to reproduce it , I just listen and if audio channel mapping is correct then I do CTRL-C and re-execute the same command line, in few attempts channel mappings will be swapped, so the interval between reexecutions is just a second. In real application with gstreamer, interval is quite large but still it does reproduces many times. Also the channel swapping happens only in the start i.e. if the “front-left” audio is coming on right channel of headphone then this mapping remains same until playback is stopped or closed.

–>What is the intervall between stopping and then starting again?
Previous answer

–>Anything else which comes to mind?
I did the following changes to the setup:
Enabled SPI device
Disabled UART_B to make more GPIOs available on IRIS board.
Changed the location of Wakeup pin source.
Updated u-boot to fix the DRAM 512MB size issue.

After reading your comments, I reverted the bsp image to original Colibri_iMX6_LinuxImageV2.6_20160826.tar.bz2 (kernel, fdt and rootfs) with EDT7" display and after boot problem is still reproducible with above gstreamer pipeline and speaker-test program.
A point I noticed, the name of BSP file is Colibri_iMX6_LinuxImageV2.6_20160826.tar.bz2 but the version displayed over login prompt is Colibri_iMX6_LinuxImageV2.6_20160630, attached screen-shot. I don’t know where this version discrepancy is coming from.

–>Any change to the device-tree?
Also attached modified device tree

–>Does it get better if you disable DVFS? ‘root@colibri-imx6:~# cpufreq-set -f 996000’
Nope, after setting the cpu frequency with or without display, issue is still reproducible.

In few days I will receive more Colibri iMX6+Iris boards, I will check whether this is reproducible on all setups.

Thanks,
Ravikiran

screen-shot and device tree file re-attached.
link text

Hi Max,

We could reproduce this problem in another setup of Colibri iMX6+Iris board with same bsp version, but there it is slightly better, swapping happens once in 30+ times.

After searching for similar issues over internet, all of them appears to be related I2S driver.
Links to some of them:

Hi

Thank you for the detailed answers.

I’m still unable to reproduce the issue.

The links you found all point to buffer under/overruns in the fifo.
This should not happen in the i.MX6 kernel used in V2.6 (and the latest V2.7 Beta) as the kernel there uses the double fifo mentioned in the community.nxp.com post.

I tried to automate the testing with the attached script. It records the sound and analyses the recorded file to see if the right channels is much louder than the left which it should. (note that it uses sox. ‘opkg update;opkg install sox’)

That never triggered the error, also if replacing the recording with a sleep and listening to the headphone output never showed the issue.

Does the script trigger the swapped channels at your end?

Max

P.S. When we take an image out of beta we just rename the tarball, thus inside the image there is still the build time of the original beta.

Hello Max,
Thanks for your response and test script.

On Iris board there is no line-in jack, so I will need modified cable to make connection between headphone jack and X9 header, this will take some time.

In the mean time, I modified your test script to automate the analysis part on computer. So the setup is, stereo aux cable connects between headphone of board to computer’s (ubuntu 16.04 LTS desktop) line-in jack. Now I run a play script on module and capture script on computer, scripts synchronize over network, the problem is easily reproducible here. Attached modified scripts and test result

Also I suggest that in your setup, cross connect the headphone output channels to line-in input channels, because I suspect that when playback channels are swapped then capture channels are also swapped so your test will always pass. By cross connecting, you will get “swapped” messages for correct playback and and “correct” message for swapped playback. Because now there are three crossings in path: playback, cable, and capture

Thanks.
Ravikiran

Hi,

I got the cable modified for headphone to X9 header, attached test results obtained from your test script (playback + capture on same board):
On one setup swapping during playback reproduction rate is 2/10, 33/100 (straight cable)
One second setup it is 2/100 (straight cable)

With cross cable connection also swapping was observed, so to completely rule out swapping in capture path I ran the the same test script on board but audio (tone+silence) was fed from computer to line-in on X9 header. No swapping observed in this case.

Based on observations till now this issue has nothing to do with CPU loading or display.

I guess changing boards may increase the probability of reproducing this issue on your side.

Regards,
Ravikiran

@bnrkiran

Hi Ravikiran

I used your scripts to have my PC as the independent judge rather than playing and recording on the same module.

Also with that setup I can not reproduce the issue on the module I tried before.

However I now changed to a module with the exact same mask version as can be seen from your photo.
With this I was able to ‘hear’ the issue and to detect it with your script (with an independent recorder) and with mine (with local recording). About 3 swapped runs out of 100.

I’m looking further into it.

Max

Hi Max,

That’s really a good news.
I have found some more observations in past few days, these might give you some hints:
Setup for this is again play on module and capture on PC.

  1. If I start a separate capture process (running throughout the test) on module and run the two scripts then result is either always correct or always swapped. Attached modified play script.

  2. While looking into kernel source code (BSPv2.6, Kernel v3.14), in file sound/soc/fsl/fsl_ssi.c, a note is mentioned regarding i.MX core, does this affects us?:

    • Some notes why imx-pcm-fiq is used instead of DMA on some boards:
    • The i.MX SSI core has some nasty limitations in AC97 mode. While most
    • sane processor vendors have a FIFO per AC97 slot, the i.MX has only
    • one FIFO which combines all valid receive slots. We cannot even select
    • which slots we want to receive. The WM9712 with which this driver
    • was developed with always sends GPIO status data in slot 12 which
    • we receive in our (PCM-) data stream. The only chance we have is to
    • manually skip this data in the FIQ handler. With sampling rates different
    • from 48000Hz not every frame has valid receive data, so the ratio
    • between pcm data and GPIO status data changes. Our FIQ handler is not
    • able to handle this, hence this driver only works with 48000Hz sampling
    • rate.
    • Reading and writing AC97 registers is another challenge. The core
    • provides us status bits when the read register is updated with another
    • value. When we read the same register two times (and the register still
    • contains the same value) these status bits are not set. We work
    • around this by not polling these bits but only wait a fixed delay.
      */

Regards,
Ravikiran

Hi Max,

Could you find any concrete solution or workaround for this problem? Please let us know.

Regards, Ravikiran

Hi Ravikiran

No solution as of yet.

Max

Hi Ravikiran,

I also reproduced the channel swap problem.

The following patch solves the issue for me:

Could you please try it and let me know if it fixes for you as well?

Thanks

Hi Fabio,

Thanks for sharing the patch.

It does solves the issue for me too, however the patch appears to be keeping the Tx and Rx path enabled all the time irrespective of audio application running in user space? If yes then hope across reboots this issue won’t show up because currently we are using a workaround of either keeping the capture process or playback process ON all the time but sometimes swapping happens on the very first attempt post reboot and it remains that way.
We will put this to test for few days on all our boards and confirm.

Regards,
Ravikiran

Hi Ravikiran,

Yes, both RX and TX are enabled. The idea came from this commit:

commit f8fdf5375e2005f238ce9b430724752a6e3d55cc
Author: Steffen Trumtrar
Date: Mon Aug 19 17:05:59 2013 +0200

ASoC: fsl-ssi: add SSIEN errata work around

The chip errata for the i.MX35, Rev.2 has the following errata:

ENGcm06222: SSI:Transmission does not take place in bit length early frame sync
        configuration

The workaround states, that TX_EN and SSI_EN bits should be set in the same
register write. As the next errata in the document (ENGcm06532) says to always
write RX_EN and TX_EN in the same register write in network mode.

Therefore include the whole write to
    CCSR_SSI_SCR_TE and CCSR_SSI_SCR_RE
into the write to
    CCSR_SSI_SCR_SSIEN

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Signed-off-by: Mark Brown <broonie@linaro.org>

, which applied the erratum only for AC97.

On my proposed patch I also apply to I2S mode.

Let us know how your stress tests behave in the next days.

Thanks

Hi Fabio,

Unfortunately our tests failed in first attempt, with this patch the capture path is not working. ‘arecord’ either fails with input/output error or there is no audio in captured file.

Earlier test passed because I listened to playback manually and used computer for automated capture, but with playback and capture on the same board test fails.

How did you verified this? Are you using the same test scripts of this thread or some other method.

Thanks for the errata pointer, I will look into it.

Regards,
Ravikiran

Hi Ravikiran,

Which kernel version are you using?

I am using 4.10.6 kernel and recording is working for me with my patch applied:

arecord -f cd | aplay -f cd

works correctly on my board.

Hello Fabio,

I am using bsp v2.6, Kernel v3.14.52: The patch you shared, its line number matches with the source in kernel v3.14 rather than 4.x kernel. So I thought it is for bsp v2.6.
On 3.14 kernel, arecord for some reason doesn’t capture any audio on first attempt (it just hangs) but it works fine from second attempt onwards.
But one out 5 times, post reboot channels got swapped on first attempt and remained that way until next reboot.

I updated the bsp to v2.7, Kernel v4.1.35.
Since 4.10.6 kernel is not yet part of toradex bsp images, I don’t want to add too many unknowns in our project. So I took the following piece of code from 4.10.6 plus your patch and added it 4.1.35.

config_done:
	/* Enabling of subunits is done after configuration */
	if (enable) {
                if (ssi_private->use_dma && (vals->scr & CCSR_SSI_SCR_TE)) {
			/*
			 * Be sure the Tx FIFO is filled when TE is set.
			 * Otherwise, there are some chances to start the
			 * playback with some void samples inserted first,
			 * generating a channel slip.
			 *
			 * First, SSIEN must be set, to let the FIFO be filled.
			 *
			 * Notes:
			 * - Limit this fix to the DMA case until FIQ cases can
			 *   be tested.
			 * - Limit the length of the busy loop to not lock the
			 *   system too long, even if 1-2 loops are sufficient
			 *   in general.
			 */
			int i;
			int max_loop = 100;
			regmap_update_bits(regs, CCSR_SSI_SCR,
					CCSR_SSI_SCR_SSIEN, CCSR_SSI_SCR_SSIEN);
			for (i = 0; i < max_loop; i++) {
				u32 sfcsr;
				regmap_read(regs, CCSR_SSI_SFCSR, &sfcsr);
				if (CCSR_SSI_SFCSR_TFCNT0(sfcsr))
					break;
			}
			if (i == max_loop) {
				dev_err(ssi_private->dev,
					"Timeout waiting TX FIFO filling\n");
			}
		}
		/* regmap_update_bits(regs, CCSR_SSI_SCR, vals->scr, vals->scr); */
                regmap_update_bits(regs, CCSR_SSI_SCR, 
                       CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE,
                       CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);

arecord is fine in this version, but one out of 10 times, swapping happens across reboots but result is no longer consistently swapped, it keeps on flipping for every playback. Attached [test result.]1

Thanks.

Could you try this fix instead against your clean 4.1 tree?

Please disregard the previous patches.

Looks like that the swap does not come from the ssi driver itself and it comes from the sgtl5000 codec instead.

This drive strength change fixes the swap for me:

Does this help on your case too?