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:
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
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
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
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.