[alsa-devel] at91 SoC Modifications
Hello:
Okay, so after probing the various pcm lines, I think I see that the format used for the pcm is a little bit off of what my codec likes to play nice. In my machine/codec driver, I see that I have some lines:
/* set cpu DAI configuration */ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
I believe this is where it is selecting the format. In at91-ssc.c, I see that this format is given as:
case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: /* * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. * * The SSC transmit and receive clocks are generated from the * MCK divider, and the BCLK signal is output on the SSC TK line. */ rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD) | (( 1 << 16) & AT91_SSC_STTDLY) | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START) | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO) | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS) | (( 0 << 16) & AT91_SSC_FSLEN) | (((channels - 1) << 8) & AT91_SSC_DATNB) | (( 1 << 7) & AT91_SSC_MSBF) | (( 0 << 5) & AT91_SSC_LOOP) | (((bits - 1) << 0) & AT91_SSC_DATALEN);
tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD) | (( 1 << 16) & AT91_SSC_STTDLY) | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START) | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO) | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
| (( 0 << 23) & AT91_SSC_FSDEN) | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS) | (( 0 << 16) & AT91_SSC_FSLEN) | (((channels - 1) << 8) & AT91_SSC_DATNB) | (( 1 << 7) & AT91_SSC_MSBF) | (( 0 << 5) & AT91_SSC_DATDEF) | (((bits - 1) << 0) & AT91_SSC_DATALEN);
break;
I should have caught this before--I spent enough time dealing with the HW registers. The simple ssc pcm driver I wrote sets the regs a little differently to get the peak performance out of the codec, e.g.
In RCMR, I have STTDLY=0, AT91_SSC_CKI_FALLING, AT91_SSC_CKS_PIN.
In RFMR everything looks okay except that I have FSOS_NONE as I borrow it from TF0
In TCMR the STTDLY=0 in mine
In TFMR I do nothing with the FSEDGE and FSDEN and I have FSLEN=7 and DATADEF=1.
So, I left with a decision. Do I add a mode or do I modify DSP A to fit my needs? I am not sure how much coding it would take to add a mode--I *do* know it would take little time to modify DSP A, but I am reluctant to make a change to something that is probably 'standard'.
Any thoughts on this?
Paul
Okay:
Working on my new format. Backed up at91-ssc.c and now writing a supplement to it including my new format, which I will dub SND_SOC_DAIFMT_PCM_L unless someone has an objection to that.
I need to define it in sound/soc.h I notice the other defs as:
#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */ #define SND_SOC_DAIFMT_RIGHT_J 1 /* Right justified mode */ #define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */ #define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM or LRC */ #define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM or LRC */ #define SND_SOC_DAIFMT_AC97 5 /* AC97 */
so, could I add a line:
#define SND_SOC_DAIFMT_PCM_L 6 /* PCM Long Sync Format*/
..without too many hassles? Just want to make sure i am not violating a standard or something.
Thanks.
Paul
On Wed, 2007-06-20 at 16:46 -0500, Paul Kavan wrote:
Okay:
Working on my new format. Backed up at91-ssc.c and now writing a supplement to it including my new format, which I will dub SND_SOC_DAIFMT_PCM_L unless someone has an objection to that.
I need to define it in sound/soc.h I notice the other defs as:
#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */ #define SND_SOC_DAIFMT_RIGHT_J 1 /* Right justified mode */ #define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */ #define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM or LRC */ #define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM or LRC */ #define SND_SOC_DAIFMT_AC97 5 /* AC97 */
so, could I add a line:
#define SND_SOC_DAIFMT_PCM_L 6 /* PCM Long Sync Format*/
..without too many hassles? Just want to make sure i am not violating a standard or something.
Do you have a link to any timing diagrams for this format ?
Liam
On 6/20/07, Paul Kavan pkavan@gmail.com wrote:
Hello:
Okay, so after probing the various pcm lines, I think I see that the format used for the pcm is a little bit off of what my codec likes to play nice. In my machine/codec driver, I see that I have some lines:
/* set cpu DAI configuration */ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
I believe this is where it is selecting the format. In at91-ssc.c, I see that this format is given as:
case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: /* * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. * * The SSC transmit and receive clocks are generated from the * MCK divider, and the BCLK signal is output on the SSC TK line. */ rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD) | (( 1 << 16) & AT91_SSC_STTDLY) | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START) | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO) | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS); rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) &
AT91_SSC_FSEDGE) | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS) | (( 0 << 16) & AT91_SSC_FSLEN) | (((channels - 1) << 8) & AT91_SSC_DATNB) | (( 1 << 7) & AT91_SSC_MSBF) | (( 0 << 5) & AT91_SSC_LOOP) | (((bits - 1) << 0) & AT91_SSC_DATALEN);
tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD) | (( 1 << 16) & AT91_SSC_STTDLY) | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START) | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO) | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS); tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) &
AT91_SSC_FSEDGE) | (( 0 << 23) & AT91_SSC_FSDEN) | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS) | (( 0 << 16) & AT91_SSC_FSLEN) | (((channels - 1) << 8) & AT91_SSC_DATNB) | (( 1 << 7) & AT91_SSC_MSBF) | (( 0 << 5) & AT91_SSC_DATDEF) | (((bits - 1) << 0) & AT91_SSC_DATALEN);
break;
I should have caught this before--I spent enough time dealing with the HW registers. The simple ssc pcm driver I wrote sets the regs a little differently to get the peak performance out of the codec, e.g.
In RCMR, I have STTDLY=0, AT91_SSC_CKI_FALLING, AT91_SSC_CKS_PIN.
In RFMR everything looks okay except that I have FSOS_NONE as I borrow it from TF0
In TCMR the STTDLY=0 in mine
In TFMR I do nothing with the FSEDGE and FSDEN and I have FSLEN=7 and DATADEF=1.
I did a test using a configuration that worked for my previous ssc driver and the clock and data lines now look a little more like what I would expect. The sine wave sounds a little better, but when I put in:
speaker-test -r8000 -f1000 -FS8 -tsine -l1
I am getting a sine wave that is at f=2k and but has some of the 1k wave in there. Hard to explain, so I will see if I can determine it mathematically and produce a waveform for you--I do not have the ability to export scope plots to a pc here (grrr), nor do I have a spectrum analyzer. What I am wondering about that is that my codec expects data in u-law companded format. Is that what speaker-test produces....I am guessing not.
With the clock and data lines looking fine, I think it is purely a software issue now. I am using the default conf still as I cannot make any other work. I am not savvy enough with alsa to determine what the problem could be with the conf file. That discussion is probably more appropriate to separate thread though.
Paul
If possible, I am more confused now then I was this morning--and that is after a lot of exploration and probing of the device.
The playback side of everything seems to work well for .raw files. I have some that I made with my old ssc polling driver. The sound fine using aplay with either the bare bones or the default alsa.conf file. However, I cannot use arecord at all. I am not sure why, but something is preventing the sync line from working during record. The sync line has a .3V,pp square that rides around 3V DC. The frequency is that of the bit clock ~256.4K. Now, when I playback a sample, the RF0 and RD0 look like they should.
I have RF0 and TF0 tied together and assume TF0 generates the sync. Also, I have TK0 and RK0 tied together and assume TK0 generates the clock. Could this be the problem.
Oh...and playback with PCM A (DSP_A) works fine, but no recording still. I get the same type of signal on RF0 as before with PCM A fmt. Does anyone have a sense if this is a ssc configuration problem or an alsa problem?
Thanks.
Paul
I have searched through at91-ssc.c and I cannot figure out why the record makes the pcm behave as it does. I am using PCM A, which configures the SSC as:
case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: /* * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. * * The SSC transmit and receive clocks are generated from the * MCK divider, and the BCLK signal is output on the SSC TK line. */ rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD) | (( 1 << 16) & AT91_SSC_STTDLY) | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START) | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO) | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS) | (( 0 << 16) & AT91_SSC_FSLEN) | (((channels - 1) << 8) & AT91_SSC_DATNB) | (( 1 << 7) & AT91_SSC_MSBF) | (( 0 << 5) & AT91_SSC_LOOP) | (((bits - 1) << 0) & AT91_SSC_DATALEN);
tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD) | (( 1 << 16) & AT91_SSC_STTDLY) | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START) | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO) | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) | (( 0 << 23) & AT91_SSC_FSDEN) | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS) | (( 0 << 16) & AT91_SSC_FSLEN) | (((channels - 1) << 8) & AT91_SSC_DATNB) | (( 1 << 7) & AT91_SSC_MSBF) | (( 0 << 5) & AT91_SSC_DATDEF) | (((bits - 1) << 0) & AT91_SSC_DATALEN);
break;
Which, while it puts my timing a little off, should allow a valid record if one has TF0 and RF0 connected and TK0 and RK0 connected. Has anyone seen this behavior before?
Looking at strace of arecord gives me a few lines I wonder about. I will attach the entire strace dump as a text file. The lines that give me pause are:
~ $ strace arecord -r8000 -traw -fS8 -d3 test.raw execve("/usr/bin/arecord", ["arecord", "-r8000", "-traw", "-fS8", "-d3", " test.raw"], [/* 7 vars */0 . . . .snip. stat("/usr/share/alsa/alsa.conf", {st_mode=S_IFREG|0644, st_size=8611, ...}) = 0 open("/usr/share/alsa/alsa.conf", O_RDONLY) = 3 ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbea17b04) = -1 ENOTTY (Inappropriate ioctl for device) brk(0x1e000) = 0x1e000 read(3, "#\n# ALSA library configuration "..., 4096) = 4096 brk(0x1f000) = 0x1f000 brk(0x20000) = 0x20000 brk(0x21000) = 0x21000 read(3, "r\n\t\t\t\tname defaults.pcm.device\n\t"..., 4096) = 4096 brk(0x22000) = 0x22000 brk(0x23000) = 0x23000 brk(0x24000) = 0x24000 brk(0x25000) = 0x25000 read(3, "{\n\t\t\t@func refer\n\t\t\tname default"..., 4096) = 419 read(3, "", 4096) = 0 close(3) .snip.
Not sure if the ioctl error on my alsa.conf is a big deal or not.
.snip. access("/etc/asound.conf", R_OK) = -1 ENOENT (No such file or directory) access("~/.asoundrc", R_OK) = -1 ENOENT (No such file or directory) .snip.
I thought I had read these files were not necessary for ALSA to work. Do I need one?
.snip. open("/usr/share/alsa/cards/aliases.conf", O_RDONLY) = 3 ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbea17a34) = -1 ENOTTY (Inappropriate ioctl for device) brk(0x26000) = 0x26000 read(3, "#\n# Define aliases for various "..., 4096) = 1273 open("/usr/share/alsa/pcm/default.conf", O_RDONLY) = 4 ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbea1799c) = -1 ENOTTY (Inappropriate ioctl for device) brk(0x27000) = 0x27000 read(4, "#\n# Default output\n#\n\npcm.!defau"..., 4096) = 762 brk(0x28000) = 0x28000 read(4, "", 4096) = 0 close(4) = 0 open("/usr/share/alsa/pcm/dmix.conf", O_RDONLY) = 4 ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbea1799c) = -1 ENOTTY (Inappropriate ioctl for device) brk(0x29000) = 0x29000 read(4, "#\n# dmix output\n#\n\npcm.!dmix {\n\t"..., 4096) = 1521 read(4, "", 4096) = 0 close(4) = 0 open("/usr/share/alsa/pcm/dsnoop.conf", O_RDONLY) = 4 ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbea1799c) = -1 ENOTTY (Inappropriate ioctl for device) brk(0x2a000) = 0x2a000 read(4, "#\n# dsnoop\n#\n\npcm.!dsnoop {\n\t@ar"..., 4096) = 1533 brk(0x2b000) = 0x2b000 read(4, "", 4096) = 0 close(4) = 0 read(3, "", 4096) = 0 close(3) .snip.
A lot of ioctl error messages. Again, not sure if they are a concern.
.snip. open("/dev/snd/controlC1", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC1", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC2", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC2", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC3", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC3", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC4", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC4", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC5", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC5", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC6", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC6", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC7", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC7", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC8", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC8", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC9", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC9", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC10", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC10", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC11", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC11", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC12", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC12", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC13", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC13", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC14", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC14", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC15", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC15", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC16", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC16", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC17", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC17", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC18", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC18", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC19", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC19", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC20", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC20", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC21", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC21", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC22", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC22", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC23", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC23", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC24", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC24", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC25", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC25", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC26", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC26", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC27", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC27", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC28", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC28", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC29", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC29", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC30", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC30", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/snd/controlC31", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/aloadC31", O_RDONLY) = -1 ENOENT (No such file or directory) .snip.
Not sure why it is trying to open a bunch of interfaces I do not have.
.snip. open("/dev/snd/controlC0", O_RDONLY) = 3 close(3) = 0 open("/dev/snd/controlC0", O_RDWR) = 3 ioctl(3, USBDEVFS_CONTROL, 0xbecba7d8) = 0 ioctl(3, 0x40045532, 0xbecba7e4) = 0 open("/dev/snd/pcmC0D0c", O_RDWR|O_NONBLOCK) = 4 close(3) = 0 ioctl(4, AGPIOC_ACQUIRE or APM_IOC_STANDBY, 0xbecba628) = 0 fcntl(4, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK) ioctl(4, AGPIOC_INFO, 0xbecba7d4) = 0 ioctl(4, AGPIOC_RELEASE or APM_IOC_SUSPEND, 0xbecba7cc) = 0 mmap2(NULL, 4096, PROT_READ, MAP_SHARED, 4, 0xfff80000) = -1 ENXIO (No such device or address) ioctl(4, 0xc0844123, 0xbecba748) = 0 fcntl(4, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK) fcntl(4, F_SETFL, O_RDWR) = 0 ioctl(4, AGPIOC_ACQUIRE or APM_IOC_STANDBY, 0xbecbacbc) = 0 rt_sigaction(SIGINT, {0x11530, [INT], SA_RESTART|0x4000000}, {SIG_DFL}, 8) = 0 rt_sigaction(SIGTERM, {0x11530, [TERM], SA_RESTART|0x4000000}, {SIG_DFL}, 8) = 0 rt_sigaction(SIGABRT, {0x11530, [ABRT], SA_RESTART|0x4000000}, {SIG_DFL}, 8) = 0 write(2, "Recording", 9Recording) = 9 write(2, " ", 1 ) = 1 write(2, "raw data", 8raw data) = 8 write(2, " '", 2 ') = 2 write(2, "test.raw", 8test.raw) = 8 write(2, "' : ", 4' : ) = 4 write(2, "Signed 8 bit", 12Signed 8 bit) = 12 write(2, ", ", 2, ) = 2 write(2, "Rate ", 5Rate ) = 5 write(2, "8000", 48000) = 4 write(2, " Hz, ", 5 Hz, ) = 5 write(2, "Mono", 4Mono) = 4 write(2, "\n", 1 ) = 1 ioctl(4, 0xc25c4110, 0xbecb8674) = 0 ioctl(4, 0xc25c4110, 0xbecb8674) = 0 ioctl(4, 0xc25c4110, 0xbecb8674) = 0 ioctl(4, 0xc25c4110, 0xbecb83e8) = 0 ioctl(4, 0xc25c4110, 0xbecb83e8) = 0 ioctl(4, 0xc25c4110, 0xbecb83e8) = 0 ioctl(4, 0xc25c4110, 0xbecb83e8) = 0 ioctl(4, 0xc25c4110, 0xbecb83e8) = 0 ioctl(4, 0xc25c4110, 0xbecb83e8) = 0 ioctl(4, 0xc25c4110, 0xbecb83e8) = 0 ioctl(4, 0xc25c4110, 0xbecb83e8) = 0 ioctl(4, 0xc25c4110, 0xbecb7eec) = 0 ioctl(4, 0xc25c4110, 0xbecb7eec) = 0 ioctl(4, 0xc25c4110, 0xbecb7eec) = 0 ioctl(4, 0xc25c4110, 0xbecb814c) = 0 ioctl(4, 0xc25c4110, 0xbecb814c) = 0 ioctl(4, 0xc25c4110, 0xbecb814c) = 0 ioctl(4, 0xc25c4110, 0xbecb7eec) = 0 ioctl(4, 0xc25c4110, 0xbecb7eec) = 0 ioctl(4, 0xc25c4110, 0xbecb7eec) = 0 ioctl(4, 0xc25c4110, 0xbecb814c) = 0 ioctl(4, 0xc25c4110, 0xbecb814c) = 0 ioctl(4, 0xc25c4110, 0xbecb814c) = 0 ioctl(4, 0xc25c4110, 0xbecb7eec) = 0 ioctl(4, 0xc25c4110, 0xbecb7eec) = 0 ioctl(4, 0xc25c4110, 0xbecb7eec) = 0 ioctl(4, 0xc25c4110, 0xbecb814c) = 0 ioctl(4, 0xc25c4110, 0xbecb814c) = 0 ioctl(4, 0xc25c4110, 0xbecb814c) = 0 ioctl(4, 0xc25c4110, 0xbecb85e4) = 0 ioctl(4, 0xc25c4110, 0xbecb85e4) = 0 ioctl(4, 0xc25c4110, 0xbecb85d8) = 0 ioctl(4, 0xc25c4110, 0xbecb898c) = 0 ioctl(4, 0xc25c4111, 0xbecb898c) = 0 ioctl(4, 0xc0844123, 0x24f58) = 0 ioctl(4, 0xc0684113, 0xbecb8554) = 0 ioctl(4, 0xc0844123, 0x24f58) = 0 ioctl(4, 0x4140, 0x400ba1a8) = 0 ioctl(4, 0xc0844123, 0x24f58) = 0 ioctl(4, 0xc0844123, 0x24f58) = 0 rmdir("test.raw") = -1 ENOTDIR (Not a directory) unlink("test.raw") = 0 open("test.raw", O_WRONLY|O_CREAT|O_LARGEFILE, 0644) = 3 ioctl(4, 0x800c4151, 0xbecb8c34) = -1 EIO (Input/output error) write(2, "arecord", 7arecord) = 7 write(2, ": ", 2: ) = 2 write(2, "pcm_read", 8pcm_read) = 8 write(2, ":", 1:) = 1 write(2, "1346", 41346) = 4 write(2, ": ", 2: ) = 2 write(2, "read error: ", 12read error: ) = 12 write(2, "Input/output error", 18Input/output error) = 18 write(2, "\n", 1 ) = 1 exit(1) = ? Process 754 detached .snip.
The final sequence here. Seems that when it tried some kind of ioctl on pcmC0D0c, it received an error. Perhaps this control signal is what is causing the HW problems with RF0.
Again, the full strace is attached. Not sure if this helps, I am trying my best to figure out what is wrong with RF0. I know it works as my polling ssc driver works just fine with both capture and playback.
If anyone has any clue to what I can try, look at, etc. please feel free to let me know.
Paul
*************************************** Paul David Kavan Project Engineer GRH Electronics, Inc. 402-734-4900 pkavan@gmail.com ***************************************
On Thu, 2007-06-21 at 14:10 -0500, Paul Kavan wrote:
The playback side of everything seems to work well for .raw files. I have some that I made with my old ssc polling driver. The sound fine using aplay with either the bare bones or the default alsa.conf file. However, I cannot use arecord at all. I am not sure why, but something is preventing the sync line from working during record. The sync line has a .3V,pp square that rides around 3V DC. The frequency is that of the bit clock ~256.4K. Now, when I playback a sample, the RF0 and RD0 look like they should.
I have RF0 and TF0 tied together and assume TF0 generates the sync. Also, I have TK0 and RK0 tied together and assume TK0 generates the clock. Could this be the problem.
Best not to assume here, check the Atmel datasheet wrt SSC clocking.
Oh...and playback with PCM A (DSP_A) works fine, but no recording still. I get the same type of signal on RF0 as before with PCM A fmt. Does anyone have a sense if this is a ssc configuration problem or an alsa problem?
It's probably not an alsa problem as playback works. If your SSC register settings for capture look correct then I'd check the hardware again.
Liam
I just don't think it is a hardware problem. I a polling ssc driver that works very nicely for this codec. However, it is polling and I do not want to rely on it when I have more of a load on the processor.
I have the machine/codec code and at91-ssc.c configured so that the registers and gpio should be set up identical to what I had before and it is not generating a proper sync signal with arecord. When I do strace on arecord it hangs at this first line before finishing.
ioctl(4, 0x800c4151, 0xbed9cc34) = -1 EIO (Input/output error) write(2, "arecord", 7arecord) = 7 write(2, ": ", 2: ) = 2 write(2, "pcm_read", 8pcm_read) = 8 write(2, ":", 1:) = 1 write(2, "1346", 41346) = 4 write(2, ": ", 2: ) = 2 write(2, "read error: ", 12read error: ) = 12 write(2, "Input/output error", 18Input/output error) = 18 write(2, "\n", 1 ) = 1 exit(1) = ?
Does anyone know what this line is doing? I think it might give a clue. The sync line still ripples at about .3V peak to peak with f=256k (Bit Clock Rate).
Frank: I modified the machine code so that RF0 and RK0 are set in the gpio. The only differences are that the sync line no longer tri-states after going trying to record and instead of seeing the ripple around 3V it is now around 200 mV.
Has anyone seen this behavior before?
Paul
Paul Kavan wrote:
I just don't think it is a hardware problem. I a polling ssc driver that works very nicely for this codec. However, it is polling and I do not want to rely on it when I have more of a load on the processor.
I have the machine/codec code and at91-ssc.c configured so that the registers and gpio should be set up identical to what I had before and it is not generating a proper sync signal with arecord. When I do strace on arecord it hangs at this first line before finishing.
ioctl(4, 0x800c4151, 0xbed9cc34) = -1 EIO (Input/output error) write(2, "arecord", 7arecord) = 7 write(2, ": ", 2: ) = 2 write(2, "pcm_read", 8pcm_read) = 8 write(2, ":", 1:) = 1 write(2, "1346", 41346) = 4 write(2, ": ", 2: ) = 2 write(2, "read error: ", 12read error: ) = 12 write(2, "Input/output error", 18Input/output error) = 18 write(2, "\n", 1 ) = 1 exit(1) = ?
Does anyone know what this line is doing? I think it might give a clue. The sync line still ripples at about .3V peak to peak with f=256k (Bit Clock Rate).
Sorry, I have no idea what that line is doing.
Frank: I modified the machine code so that RF0 and RK0 are set in the gpio. The only differences are that the sync line no longer tri-states after going trying to record and instead of seeing the ripple around 3V it is now around 200 mV.
Now that I think about, if you are using RK0 as an input and driving it from TK0, then you should be initializing the RK0 GPIO. On our board, the RK2 GPIO pin is not used since RK2 is generated internally from the TK2 clock signal (AT91_SSC_CKS_CLOCK), so there was no need to initialize it.
Also, the RF2 GPIO is not used on our board, because there is a single sync signal sent to the codec, and this is supplied by TF2.
Perhaps it would be useful to see a diagram of the connections between the SSC and codec on your board, including directions.
../fam
Perhaps it would be useful to see a diagram of the connections between the SSC and codec on your board, including directions.
Attached is a quick diagram. As far as the wiring, they only connect where you see a node connection....did not have a real circuit program handy. Let me know if you have questions on the diagram. I tried to make it as clear as possible.
I have the bitclocks and codec master clock tied together. Also, I have the frames tied together.
Thanks.
Paul
Paul Kavan wrote:
Perhaps it would be useful to see a diagram of the connections between the SSC and codec on your board, including directions.
Attached is a quick diagram. As far as the wiring, they only connect where you see a node connection....did not have a real circuit program handy. Let me know if you have questions on the diagram. I tried to make it as clear as possible.
I have the bitclocks and codec master clock tied together. Also, I have the frames tied together.
The diagram is clear except for the signal directions. I assume that all signals are outputs from SSC to codec except for RD0 - PCMT.
Could you please provide the settings that you are currently working with?
In particular, I would like to see how RFMR.FSOS is set. If TF0 is outputting the frame sync and tied to RF0, then you probably want RF0 configured as an input (RFMR.FSOS = None).
And if RF0 and RK0 are receiving signals on their GPIO lines, you do need to initialize the GPIO registers in your machine driver.
../fam
Hello all:
I have been struggling to determine why the sync line (TF0) behaves so strangely when in capture mode yet acts fine in playback mode. So far, no real clues. However, I do have a few questions. I have DATADEF set for TD0 set to 1. However, at the end of a playback it pulls to zero. Any clue why this might be happening?
Also, in the machine code, I set up some test code to printk back the gpio registers:
the code for the gpio is given as
#define AT91_PIO_TK0 (1 << (AT91_PIN_PB16 - PIN_BASE) % 32) #define AT91_PIO_TF0 (1 << (AT91_PIN_PB17 - PIN_BASE) % 32) #define AT91_PIO_TD0 (1 << (AT91_PIN_PB18 - PIN_BASE) % 32) #define AT91_PIO_RD0 (1 << (AT91_PIN_PB19 - PIN_BASE) % 32) #define AT91_PIO_RK0 (1 << (AT91_PIN_PB20 - PIN_BASE) % 32) #define AT91_PIO_RF0 (1 << (AT91_PIN_PB21 - PIN_BASE) % 32) . . . ssc_pio_lines = AT91_PIO_TF0 | AT91_PIO_TK0 | AT91_PIO_TD0 | AT91_PIO_RD0 /*| AT91_PIO_RK0 | AT91_PIO_RF0*/ ;
printk("SSC PIO LINES is 0x%x\n",ssc_pio_lines); /* Reset all PIO registers and assign lines to peripheral A */ at91_sys_write(AT91_PIOB + PIO_PDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_ODR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_IFDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_CODR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_IDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_MDDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_PUDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_ASR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_OWDR, ssc_pio_lines);
/*TEST CODE*/ printk("PIOB-PDR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_PDR)); printk("PIOB-ODR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_ODR)); printk("PIOB-IFDR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_IFDR)); printk("PIOB-CODR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_CODR)); printk("PIOB-IRD is set to %d\n",at91_sys_read(AT91_PIOB + PIO_IDR)); printk("PIOB-MDDR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_MDDR)); printk("PIOB-PUDR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_PUDR)); printk("PIOB-ASR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_ASR)); printk("PIOB-OWDR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_OWDR)); /*END OF TEST CODE*/
and the result at boot is:
AT91SAM9260EK W6811 Driver <1> w6811: W6811 PCM SoC Audio 0.1 asoc: W6811 <-> at91-ssc0 mapping ok SSC PIO LINES is 0xf0000 PIOB-PDR is set to 0 PIOB-ODR is set to 0 PIOB-IFDR is set to 0 PIOB-CODR is set to 0 PIOB-IRD is set to 0 PIOB-MDDR is set to 0 PIOB-PUDR is set to 0 PIOB-ASR is set to 0 PIOB-OWDR is set to 0
...why are all the registers set to 0?
I may have to try separating TF0/RF0 and TK0/RK0....but should not have to I do not think.
Paul
Paul Kavan wrote:
Hello all:
I have been struggling to determine why the sync line (TF0) behaves so strangely when in capture mode yet acts fine in playback mode. So far, no real clues. However, I do have a few questions. I have DATADEF set for TD0 set to 1. However, at the end of a playback it pulls to zero. Any clue why this might be happening?
Perhaps it is due to the SSC being reset when the playback channel is closed?
Also, in the machine code, I set up some test code to printk back the gpio registers:
the code for the gpio is given as
#define AT91_PIO_TK0 (1 << (AT91_PIN_PB16 - PIN_BASE) % 32) #define AT91_PIO_TF0 (1 << (AT91_PIN_PB17 - PIN_BASE) % 32) #define AT91_PIO_TD0 (1 << (AT91_PIN_PB18 - PIN_BASE) % 32) #define AT91_PIO_RD0 (1 << (AT91_PIN_PB19 - PIN_BASE) % 32) #define AT91_PIO_RK0 (1 << (AT91_PIN_PB20 - PIN_BASE) % 32) #define AT91_PIO_RF0 (1 << (AT91_PIN_PB21 - PIN_BASE) % 32) . . . ssc_pio_lines = AT91_PIO_TF0 | AT91_PIO_TK0 | AT91_PIO_TD0 | AT91_PIO_RD0 /*| AT91_PIO_RK0 | AT91_PIO_RF0*/ ;
printk("SSC PIO LINES is 0x%x\n",ssc_pio_lines);
/* Reset all PIO registers and assign lines to peripheral A */ at91_sys_write(AT91_PIOB + PIO_PDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_ODR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_IFDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_CODR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_IDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_MDDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_PUDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_ASR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_OWDR, ssc_pio_lines);
/*TEST CODE*/ printk("PIOB-PDR is set to %d\n",at91_sys_read(AT91_PIOB +
PIO_PDR)); printk("PIOB-ODR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_ODR)); printk("PIOB-IFDR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_IFDR)); printk("PIOB-CODR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_CODR)); printk("PIOB-IRD is set to %d\n",at91_sys_read(AT91_PIOB + PIO_IDR)); printk("PIOB-MDDR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_MDDR)); printk("PIOB-PUDR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_PUDR)); printk("PIOB-ASR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_ASR)); printk("PIOB-OWDR is set to %d\n",at91_sys_read(AT91_PIOB + PIO_OWDR)); /*END OF TEST CODE*/
and the result at boot is:
AT91SAM9260EK W6811 Driver <1> w6811: W6811 PCM SoC Audio 0.1 asoc: W6811 <-> at91-ssc0 mapping ok SSC PIO LINES is 0xf0000 PIOB-PDR is set to 0 PIOB-ODR is set to 0 PIOB-IFDR is set to 0 PIOB-CODR is set to 0 PIOB-IRD is set to 0 PIOB-MDDR is set to 0 PIOB-PUDR is set to 0 PIOB-ASR is set to 0 PIOB-OWDR is set to 0
...why are all the registers set to 0?
These registers are all write-only registers. You have to read their corresponding status registers to see what values are set.
../fam
On 6/25/07, Frank Mandarino fmandarino@endrelia.com wrote:
Paul Kavan wrote:
Hello all:
I have been struggling to determine why the sync line (TF0) behaves so strangely when in capture mode yet acts fine in playback mode. So far,
no
real clues. However, I do have a few questions. I have DATADEF set for
TD0
set to 1. However, at the end of a playback it pulls to zero. Any clue
why
this might be happening?
Perhaps it is due to the SSC being reset when the playback channel is closed?
Yes, that is probably the cause. Thanks.
Also, in the machine code, I set up some test code to printk back the gpio
registers:
the code for the gpio is given as
#define AT91_PIO_TK0 (1 << (AT91_PIN_PB16 - PIN_BASE) % 32) #define AT91_PIO_TF0 (1 << (AT91_PIN_PB17 - PIN_BASE) % 32) #define AT91_PIO_TD0 (1 << (AT91_PIN_PB18 - PIN_BASE) % 32) #define AT91_PIO_RD0 (1 << (AT91_PIN_PB19 - PIN_BASE) % 32) #define AT91_PIO_RK0 (1 << (AT91_PIN_PB20 - PIN_BASE) % 32) #define AT91_PIO_RF0 (1 << (AT91_PIN_PB21 - PIN_BASE) % 32) . . . ssc_pio_lines = AT91_PIO_TF0 | AT91_PIO_TK0 | AT91_PIO_TD0 | AT91_PIO_RD0 /*| AT91_PIO_RK0 | AT91_PIO_RF0*/ ;
printk("SSC PIO LINES is 0x%x\n",ssc_pio_lines);
/* Reset all PIO registers and assign lines to peripheral A */ at91_sys_write(AT91_PIOB + PIO_PDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_ODR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_IFDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_CODR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_IDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_MDDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_PUDR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_ASR, ssc_pio_lines); at91_sys_write(AT91_PIOB + PIO_OWDR, ssc_pio_lines);
/*TEST CODE*/ printk("PIOB-PDR is set to %d\n",at91_sys_read(AT91_PIOB +
PIO_PDR)); printk("PIOB-ODR is set to %d\n",at91_sys_read(AT91_PIOB +
PIO_ODR));
printk("PIOB-IFDR is set to %d\n",at91_sys_read(AT91_PIOB +
PIO_IFDR));
printk("PIOB-CODR is set to %d\n",at91_sys_read(AT91_PIOB +
PIO_CODR));
printk("PIOB-IRD is set to %d\n",at91_sys_read(AT91_PIOB +
PIO_IDR));
printk("PIOB-MDDR is set to %d\n",at91_sys_read(AT91_PIOB +
PIO_MDDR));
printk("PIOB-PUDR is set to %d\n",at91_sys_read(AT91_PIOB +
PIO_PUDR));
printk("PIOB-ASR is set to %d\n",at91_sys_read(AT91_PIOB +
PIO_ASR));
printk("PIOB-OWDR is set to %d\n",at91_sys_read(AT91_PIOB +
PIO_OWDR));
/*END OF TEST CODE*/
and the result at boot is:
AT91SAM9260EK W6811 Driver <1> w6811: W6811 PCM SoC Audio 0.1 asoc: W6811 <-> at91-ssc0 mapping ok SSC PIO LINES is 0xf0000 PIOB-PDR is set to 0 PIOB-ODR is set to 0 PIOB-IFDR is set to 0 PIOB-CODR is set to 0 PIOB-IRD is set to 0 PIOB-MDDR is set to 0 PIOB-PUDR is set to 0 PIOB-ASR is set to 0 PIOB-OWDR is set to 0
...why are all the registers set to 0?
These registers are all write-only registers. You have to read their corresponding status registers to see what values are set.
Is my face red? Missed that.....
../fam
-- Frank Mandarino fmandarino(a)endrelia.com Endrelia Technologies Inc. Toronto, Ontario, Canada
Hello all:
I may have to try separating TF0/RF0 and TK0/RK0....but should not have to I do not think.
I have officially decided to try this. I am rewriting some code to get this done and rewiring the board. Will let you know the result of this.
Paul
Well, I have fanned out all 6 SSC lines to the codec now and have them configured individually to create the desired effect. However, it is still buggy. TF0 now does not activate properly when in capture mode. I get the same type of waveform I received when I was using TF0 to attempt capture. Nothing seems to work correctly except playback....and only when I have TF0 sent to the codec's frame receive and send pins.....
I want to look through the SoC code to where the SSC is activated/reset so I can try to determine what is happening. I know the SSC works well with this codec and want to figure out what I need to do to modify the code to make it happen with ALSA as well. I hate the idea of going back to the drawing board and trying to write my driver so that it uses the PDC, but the ALSA SoC is simply not working well enough yet with the at91sam9260.
Does anyone know where I can find this code at?
Thanks.
Paul
On Mon, 2007-06-25 at 16:51 -0500, Paul Kavan wrote:
I want to look through the SoC code to where the SSC is activated/reset so I can try to determine what is happening. I know the SSC works well with this codec and want to figure out what I need to do to modify the code to make it happen with ALSA as well. I hate the idea of going back to the drawing board and trying to write my driver so that it uses the PDC, but the ALSA SoC is simply not working well enough yet with the at91sam9260.
Have you compared the difference between you polling driver SSC + codec settings to the SoC driver after trigger() ?
Any differences may indicate a reason for capture not working.
Also, please make sure that there is only 1 master driving each BCLK/LRC and that it's input clock source is running. Another thing to check is that SSC capture is set up to run async to SSC playback.
Liam
Paul Kavan wrote:
Well, I have fanned out all 6 SSC lines to the codec now and have them configured individually to create the desired effect. However, it is still buggy. TF0 now does not activate properly when in capture mode. I get the same type of waveform I received when I was using TF0 to attempt capture. Nothing seems to work correctly except playback....and only when I have TF0 sent to the codec's frame receive and send pins.....
I want to look through the SoC code to where the SSC is activated/reset so I can try to determine what is happening. I know the SSC works well with this codec and want to figure out what I need to do to modify the code to make it happen with ALSA as well. I hate the idea of going back to the drawing board and trying to write my driver so that it uses the PDC, but the ALSA SoC is simply not working well enough yet with the at91sam9260.
Does anyone know where I can find this code at?
All of the SSC code is contained in sound/soc/at91/at91-ssc.c in functions at91_ssc_hw_params() and at91_ssc_shutdown().
../fam
participants (3)
-
Frank Mandarino
-
Liam Girdwood
-
Paul Kavan