Message ID | CAG5mAdzci2hPUBzFo+k3+CorfzQZD9_knQ2TXw1db1KoBL5Eyw@mail.gmail.com (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
On Thu, Oct 29, 2015 at 12:06:16PM -0700, Caleb Crome wrote: > This actually is exactly what I'm seeing now. I'm seeing the > *startup* happening from the trigger starting up slipped. So this > does make perfect sense to me. I saw your problem in the other reply. And I suggested you to let DMA work first before SSI gets enabled. As SDMA in that case would transfer one burst length (16 if you applied my patch I sent you) and pause before SSI gets enabled. Then SSI would have enough data to send out without any startup issue. > It occurred to me that perhaps the problem has to do when exactly when > during the frame-sync period the fsl_ssi_trigger function was called. > Perhaps, if it's called near the end or beginning of a frame, somehow I don't know how you measured if it's before of after. But the frame should not start until trigger() gets call -- more clearly SSIEN and TE get enabled. From my point of view, you problem should be caused by SSI getting enabled without enough data in the FIFO. And that's what I just described in the previous paragraph and previous reply. > something gets messed up. (The docs for the SCR register imply some > of this, but it talks about either 2 or 6 bit clocks, so I'd expect > the error rate to be lower than 7% (more like 2.5%). > In addition, I have run about 20 minutes of audio with no slips or > problems, even though there have been aplay underruns. This is a > major step forward for me :-) It'd be better to avoid user space ALSA underun as it may skip some data.
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 73778c2..8cd8284 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -328,6 +328,41 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private, } } +/* + * wait for a frame sync. do this by enabling the SSI, + * then waiting for sync to happen, then disabling the SSI + * and put it back to the state it was at first + */ +static void wait_for_tfs(struct regmap *regs) +{ + u32 tfs; + u32 scr; + int maxcount = 100000; + regmap_read(regs, CCSR_SSI_SCR, &scr); + regmap_update_bits(regs, CCSR_SSI_SCR, 0x3, 0x3); + while(maxcount--) { + /* clear TFS bit */ + regmap_update_bits(regs, CCSR_SSI_SISR, CCSR_SSI_SISR_TFS, 0); + regmap_read(regs, CCSR_SSI_SISR, &tfs); + if ((tfs & CCSR_SSI_SISR_TFS)==0) + break; /* tfs went to 0 */ + } + if (maxcount < 0) { + printk(KERN_INFO "timed out 1, sisr = 0x%08x\n", tfs); + } + maxcount = 100000; + while(maxcount--) { + /* waiting for tfs to go to 1. */ + regmap_read(regs, CCSR_SSI_SISR, &tfs); + if ((tfs & CCSR_SSI_SISR_TFS)) + break; /* tfs went to 1 */ + } + if (maxcount < 0) { + printk(KERN_INFO "timed out 2\n"); + } + regmap_write(regs, CCSR_SSI_SCR, scr); +} + /* * Calculate the bits that have to be disabled for the current stream that is