Audio on i.MX27 with tlv320aic23 over SSI/I2S

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Audio on i.MX27 with tlv320aic23 over SSI/I2S

1,428 Views
kesaco
Contributor II

Hi all,

I am working on enabling audio on an i.MX27 based platform where the CPU is linked to a tlv320aic23 audio codec via SSI.

If I do not make any mistake: The CPU has to be I2S-slave in order to communicate with the audio codec.

For now, I configure the codec with a serie of i2cset commands.

I know the hardware is working and the i2cset commands are operationnal because it works with an old Linux distribution based on 2.6.32.

But when I "aplay 1.wav", the call blocks and I ear nothing (distribution based on 4.1.15 kernel).

A view at the scope shows:

  • the CLK signal is always ticking (before and after the aplay command)
  • whereas the TXDAT line falls down right after and stays down until I manually interrupt (Ctrl-C) the aplay command.

There is a snippet of the device tree source:

sound {

    compatible = "eukrea,asoc-tlv320";

    eukrea,model = "Eukrea TLV320AIC23 audio codec";

    ssi-controller = <&ssi1>;

    fsl,mux-int-port = <1>;

    fsl,mux-ext-port = <3>;

};

[...]

&ssi1 {

    pinctrl-names = "default";

    pinctrl-0 = <&pinctrl_ssi4>;

    codec-handle = <&codec>;

    status = "okay";

};

[...]

&i2c1 {

    codec: codec@18 {

        compatible = "ti,tlv320aic23";

        clock-frequency = <4915000>;

        reg = <0x1a>;

    };

};

[...]

pinctrl_ssi4: ssi4grp {

    fsl,pins = <

        MX27_PAD_SSI4_CLK__SSI4_CLK 0x0

        MX27_PAD_SSI4_FS__SSI4_FS 0x0

        MX27_PAD_SSI4_RXDAT__SSI4_RXDAT 0x1 /* PUEN */

        MX27_PAD_SSI4_TXDAT__SSI4_TXDAT 0x1 /* PUEN */

    >;

};

BY adding printk's, I see right before the blocking situation, the functions fsl_ssi_trigger and fsl_ssi_tx_config (from sound/soc/fsl/fsl_ssi.c) are called, as well as the configuration functions from drivers/dma/imx-dma.c), but then nothing happends, even strace blocks on a poll call over /dev/snd/pcmC0D0p.

Playing WAVE 'audio/2.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono

[...]

open("/dev/snd/pcmC0D0p", O_RDWR|O_NONBLOCK|O_CLOEXEC) = 4

[...]

imx-dma 10001000.dma: imxdma_prep_dma_cyclic channel: 0 buf_len=32000 period_len=8000

imx-dma 10001000.dma: imxdma_xfer_desc channel: 0 sg=c7067d60 sgcount=4 total length=4294967295 dev_addr=0x10010000 (mem2dev)

imx-dma 10001000.dma:  imxdma_sg_next channel: 0 dst 0x10010000, src 0xa7150000, size 0x00001f40

[...]

poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1

I doubt the SSI link is in cause because when I disabled the DMA with the fsl,fiq-stream-filter property, I saw waves on the TXDAT line (although I got a critical kernel crash then).

Also, printk's revealed the SSI functions used are from sound/soc/fsl/fsl_ssi.c and not from imx-ssi.c, is it normal ?

Lastly, this comment from Documentation/devicetree/bindings/sound/fsl,ssi.txt got my attention:

Notes on fsl,playback-dma and fsl,capture-dma:

On SOCs that have an SSI, specific DMA channels are hard-wired for playback

and capture. On the MPC8610, for example, SSI1 must use DMA channel 0 for

playback and DMA channel 1 for capture. SSI2 must use DMA channel 2 for

playback and DMA channel 3 for capture. The developer can choose which

DMA controller to use, but the channels themselves are hard-wired. The

purpose of these two properties is to represent this hardware design.

But I could not figure out how to force the DMA channel (anyway after disabling another component I got the DMA channels 0 and 1) neither if it was actually the case on i.MX27 ?

So I am stuck here: calls to aplay never end and I have no sound coming from that codec. Any ideas are welcome !

Thank you for your time,

Miquèl

Labels (2)
0 Kudos
3 Replies

715 Views
joanxie
NXP TechSupport
NXP TechSupport

for how to configure ssi, pls refer to the enclosed application note as below

<http://cache.nxp.com/files/32bit/doc/app_note/AN2628.pdf?fsrch=1&sr=1&pageNum=1 >.

for how to configure the source code, pls refer to the

Chapter 21 Synchronous Serial Interface (SSI) Driver of enclosed Reference Manual

0 Kudos

715 Views
kesaco
Contributor II

Hi,

Thank you very much for this AN, it really helps to get things clear.

So now I am pretty sure my audio mux ils well configured, but it still does not work.

Actually, it seems SSI is not "digesting" the bytes brought by the cyclic DMA.

I rebased my work on top of the 4.1.18 (kernel-stable) branch with no luck.

I also dumped the i.MX27 clock registers but it seems the clocks related to DMA and SSI0 are enabled.

Any other idea ?

Miquèl

0 Kudos

715 Views
kesaco
Contributor II

I finally got my solution : i.MX27 DMA engine do not parse correctly the device tree (imx27.dtsi) so the DMA request channel is not filled into a imx_dma_data structure. Playback is DMA request 13. This is a workaround, not pretty but functionnal.

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c

index 0d48804..1b2c1b2 100644

--- a/sound/soc/fsl/fsl_ssi.c

+++ b/sound/soc/fsl/fsl_ssi.c

@@ -1055,8 +1055,26 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,

static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)

{

        struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);

+       struct imx_dma_data *dmadattx, *dmadatrx;

        if (ssi_private->soc->imx && ssi_private->use_dma) {

+               /* DTS is not parsed correctly so set manually DMA_REQUEST

+                  signals into imx_dma_data structures */

+               dmadattx = kmalloc(sizeof(struct imx_dma_data), GFP_KERNEL);

+               dmadatrx = kmalloc(sizeof(struct imx_dma_data), GFP_KERNEL);

+               if (!dmadatrx || !dmadattx)

+                       return -ENOMEM;

+

+               ssi_private->dma_params_tx.filter_data = dmadattx;

+               dmadattx->dma_request = 13;

+               dmadattx->dma_request2 = 15;

+               dmadattx->priority = DMA_PRIO_HIGH;

+

+               ssi_private->dma_params_rx.filter_data = dmadatrx;

+               dmadatrx->dma_request = 12;

+               dmadatrx->dma_request2 = 14;

+               dmadatrx->priority = DMA_PRIO_HIGH;

+

                dai->playback_dma_data = &ssi_private->dma_params_tx;

                dai->capture_dma_data = &ssi_private->dma_params_rx;

        }

Then I was able to ear audio but with regular DMA underruns (sound is jerky). The second problem is that between kernel 3.15 and 3.16, the flag NO_RESIDUE has been deleted there and the "RESIDUE" feature seems not to be supported by the i.MX27 DMA engine:

diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c

index 0db94f49..b1ff455 100644

--- a/sound/soc/fsl/imx-pcm-dma.c

+++ b/sound/soc/fsl/imx-pcm-dma.c

@@ -59,7 +59,8 @@ int imx_pcm_dma_init(struct platform_device *pdev)

{

        return devm_snd_dmaengine_pcm_register(&pdev->dev,

                &imx_dmaengine_pcm_config,

-               SND_DMAENGINE_PCM_FLAG_COMPAT);

+               SND_DMAENGINE_PCM_FLAG_COMPAT |

+               SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);

}

EXPORT_SYMBOL_GPL(imx_pcm_dma_init);

With these changes, sound is clear.

0 Kudos