Codec drivers and alsa support for custom cape with sta321mp

409 views
Skip to first unread message

Robin Scheibler

unread,
May 24, 2015, 3:38:43 AM5/24/15
to beagl...@googlegroups.com
Dear all,

I have created a custom cape around the STA321MP chip from ST Microelectronics. It has 6 MEMS microphones and outputs them on an I2S bus with 3 data lines. I am trying to use mcasp0 on the boneblack side to receive the data. I am now to the point where the codec configuration happens correctly (I can see the i2s signals with a logic analyzer) and a soundcard is detected. However, when I try to record sound with arecord, I get the following error:

root@beaglebone:~# arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: EVM [STA321MP EVM], device 0: STA321MP sta321mp-audio-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
root@beaglebone:~# arecord -D hw:0,0 -f S24_LE -c 6 -r 44100 -t wav test.wav
Recording WAVE 'test.wav' : Signed 24 bit Little Endian, Rate 44100 Hz, Channels 6
arecord: pcm_read:1801: read error: Input/output error

Let me know provide more details.
  • The codec is frame and bit clocks master
  • The connection to mcasp0 is the following:
    • Bit clock <=> P9_12 (mcasp0_aclkr_mux3)
    • Frame sync clock (L/R) <=>  P9_27 (mcasp0_fsr)
    • Data <=> P9_28 (mcasp0_axr2)
    • Data <=> P9_30 (mcasp0_axr0)
    • Data <=> P9_25 (mcasp0_axr3)
  • I am using kernel 3.14.41 (because 3.8 doesn't have support for mcasp with >2 channels)
  • I am using dtb-builder to add my device to the device tree

All the code I have added to the kernel (codec and machine code) and to the device tree is on github. Here are the links to the specific changes I have made.

kernel: https://github.com/fakufaku/linux/commit/3a6680960412ef0fc3fbcc6f2c0021350039cc92

device tree: https://github.com/fakufaku/dtb-rebuilder/commit/127dbf3c82c78cc602058308ed72978b170c99a6

It is my first time trying to code audio driver so please be indulgent :) I have spent a lot of time on this but it seems I am now completely stuck. I'd really appreciate some help. I'd be happy to provide more clarifications on anything.

One thing I do not understand is if I need to add mixer bindings. And also the audio routing (jack vs codec pins, etc).

Thank you in advance!
Robin

Jack Fisher

unread,
May 24, 2015, 12:30:21 PM5/24/15
to beagl...@googlegroups.com
On Sunday, May 24, 2015 at 12:38:43 AM UTC-7, Robin Scheibler wrote:
> Dear all,
>
> I have created a custom cape around the STA321MP chip from ST Microelectronics. It has 6 MEMS microphones and outputs them on an I2S bus with 3 data lines. I am trying to use mcasp0 on the boneblack side to receive the data. I am now to the point where the codec configuration happens correctly (I can see the i2s signals with a logic analyzer) and a soundcard is detected. However, when I try to record sound with arecord, I get the following error:
>
> root@beaglebone:~# arecord -l
> **** List of CAPTURE Hardware Devices ****
> card 0: EVM [STA321MP EVM], device 0: STA321MP sta321mp-audio-0 []
>   Subdevices: 1/1
>   Subdevice #0: subdevice #0
> root@beaglebone:~# arecord -D hw:0,0 -f S24_LE -c 6 -r 44100 -t wav test.wav
> Recording WAVE 'test.wav' : Signed 24 bit Little Endian, Rate 44100 Hz, Channels 6
> arecord: pcm_read:1801: read error: Input/output error
>
>
> Let me know provide more details.
> The codec is frame and bit clocks masterThe connection to mcasp0 is the following:Bit clock <=> P9_12 (mcasp0_aclkr_mux3)Frame sync clock (L/R) <=>  P9_27 (mcasp0_fsr)Data <=> P9_28 (mcasp0_axr2)
> Data <=> P9_30 (mcasp0_axr0)Data <=> P9_25 (mcasp0_axr3)I am using kernel 3.14.41 (because 3.8 doesn't have support for mcasp with >2 channels)I am using dtb-builder to add my device to the device tree
> All the code I have added to the kernel (codec and machine code) and to the device tree is on github. Here are the links to the specific changes I have made.
> kernel: https://github.com/fakufaku/linux/commit/3a6680960412ef0fc3fbcc6f2c0021350039cc92
>
> device tree: https://github.com/fakufaku/dtb-rebuilder/commit/127dbf3c82c78cc602058308ed72978b170c99a6
> It is my first time trying to code audio driver so please be indulgent :) I have spent a lot of time on this but it seems I am now completely stuck. I'd really appreciate some help. I'd be happy to provide more clarifications on anything.
> One thing I do not understand is if I need to add mixer bindings. And also the audio routing (jack vs codec pins, etc).
>
> Thank you in advance!
> Robin

Hey Robin,
I first must say I don't have an answer for you. The reason I am writing is I have in mind to self-publish a free online open-source and organic BBB hacking book, working title "hackin' black" (think AC/DC!). Your topic is broadly interesting, really cool, and relevant as heck. So if you are willing, I would like to include the solution in "hackin' black" when you get it sorted?

Think about it, and think of how helpful a free book like that would have been to you right now!

Respectfully,

JF

Jack Fisher

unread,
May 24, 2015, 12:37:23 PM5/24/15
to beagl...@googlegroups.com
BTW,

Your link is broken, here is the page I found -
http://www.st.com/web/en/catalog/sense_power/SC1756
Which chip is it, I see no 321mp?

Jack

Robin Scheibler

unread,
May 24, 2015, 4:10:08 PM5/24/15
to beagl...@googlegroups.com
Hi Jack,

Thanks for the interest. Sure, I'd be happy to share the solution. I'm planning to also release the schematics and PCB when things are working out.

The data sheet for the STA321MP is here: http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00046002.pdf
Thanks for catching that.

Cheers,
Robin

Robin Scheibler

unread,
Aug 25, 2015, 3:18:48 AM8/25/15
to BeagleBoard

After a lot of effort, I have finally solved this.


The problem was that the mcasp module can operate with synchronous or asynchronous transmit and receive clocks. The default setting hardcoded in the linux mcasp driver is synchronous. That means that both receive and transmit use the transmit clock signals FSX and ACLKX.


My board was sending the frame sync and bit clock only to the receive clock. I could solve the problem by rewiring the circuit.

Rick Mann

unread,
Aug 25, 2015, 4:02:15 AM8/25/15
to beagl...@googlegroups.com, Robin Scheibler
Robin, do you think it would be similarly easy to get a TI tas5731m chip to work? http://www.ti.com/lit/ds/symlink/tas5731m.pdf
> --
> For more options, visit http://beagleboard.org/discuss
> ---
> You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.


--
Rick Mann
rm...@latencyzero.com


Faku Faku

unread,
Aug 25, 2015, 5:17:42 AM8/25/15
to Rick Mann, beagl...@googlegroups.com
Hi Rick,

I think it should not be too difficult. I have mainly followed this
tutorial to get the driver going:

http://processors.wiki.ti.com/index.php/Sitara_Linux_Audio_DAC_Example

In my case things were a bit tricky because I needed to enable 6
channels in mcasp0 and the current mainstream BBB kernel (~3.8.67) had
only support for 2 channels. I had to move to 3.14 but then lost
support for the device tree overlay. In your case since you only want
two channels, it should be no problem. Just follow the guide :)

Cheers,
Robin

pablo7f...@gmail.com

unread,
Jan 7, 2016, 2:28:37 PM1/7/16
to BeagleBoard
Hi Robin:

I'm doing a similar project, but with a PCM3168 codec... I also followed the guide http://processors.wiki.ti.com/index.php/Sitara_Linux_Audio_DAC_Example
Anyway there are lots of things that are not very clear for me...

In my case, i use codec as clock slave, and synch, so the problem you had should not affect to me... But when i try to record it says:

 arecord -D hw:0,0 -f S24_LE -c 1 -r 96000 -t wav test.wav
Recording WAVE 'test.wav' : Signed 24 bit Little Endian, Rate 96000 Hz, Mono
arecord: set_params:1239: Channels count non available

Could you help me?

Robin Scheibler

unread,
Jan 7, 2016, 3:31:59 PM1/7/16
to beagl...@googlegroups.com
Hi Pablo,

With McASP it is not possible to capture less than 2 channels. Try with -c 2 argument.

Best,
Robin

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to a topic in the Google Groups "BeagleBoard" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/beagleboard/pptZ_9PTqMY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to beagleboard...@googlegroups.com.

Pablo Fonovich

unread,
Jan 7, 2016, 8:26:31 PM1/7/16
to beagl...@googlegroups.com
Thanks very much, that was a problem. But now another error appears: "davinci_evm sound: ASoC: machine hw_params failed: -524". Do you know what it means, or where can i find the meaning? I assume this means there is something wrong when i created the pcm3168_hw_params in the alsa machine layer... but i don't know the problem... where did you look for info? only in that TI guide? I attach my files, and if is not much trouble for you i would be grateful if you help me...

i've noticed that some functions you used in davinci_evm.c where not explained in that guide... and it's very difficult for a noob like me in this subject for understainding what to do... I've just based my pcm3168.c in another driver, and i really don't quite understand much of what is going on, nor found any simple documentation about it. If you could give me some hints it would be great!

Thanks very much..
pcm3168.c
davinci-evm.c

Pablo Fonovich

unread,
Jan 7, 2016, 8:26:34 PM1/7/16
to beagl...@googlegroups.com
sorry, the message also states:

arecord: set_params:1297: Unable to install hw params:
ACCESS:  RW_INTERLEAVED
FORMAT:  S24_LE
SUBFORMAT:  STD
SAMPLE_BITS: 32
FRAME_BITS: 128
CHANNELS: 4
RATE: 96000
PERIOD_TIME: (21333 21334)
PERIOD_SIZE: 2048
PERIOD_BYTES: 32768
PERIODS: 4
BUFFER_TIME: (85333 85334)
BUFFER_SIZE: 8192
BUFFER_BYTES: 131072
TICK_TIME: 0
# aplay -f S24_LE -r 96000 ../Yam*wav
Warning: format is changed to S16_LE
Playing WAVE '../Yamaha-TG100-Ocarina-C5.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
[  102.291787] davinci_evm sound: ASoC: machine hw_params failed: -524
aplay: set_params:1297: Unable to install hw params:
ACCESS:  RW_INTERLEAVED
FORMAT:  S16_LE
SUBFORMAT:  STD
SAMPLE_BITS: 16
FRAME_BITS: 32
CHANNELS: 2
RATE: 44100
PERIOD_TIME: (125011 125012)
PERIOD_SIZE: 5513
PERIOD_BYTES: 22052
PERIODS: 4
BUFFER_TIME: (500045 500046)
BUFFER_SIZE: 22052
BUFFER_BYTES: 88208
TICK_TIME: 0

Robin Scheibler

unread,
Jan 8, 2016, 5:04:01 PM1/8/16
to beagl...@googlegroups.com
Hi Pablo,

What is the kernel version you are using ? I have finally used kernel 3.14 because in 3.8 it seems that the mcasp driver implementation could not support more than two channels.

I was in the same position as you. I mostly dug as much as possible from TI documentation and also read the drivers for other chipsets in the kernel code. Then, I also used
the sitara am355xx data sheet to understand how McASP works. It took me quite some time to piece together how things work. Still now I do not fully understand. The problem is that there is no proper documentation for the ALSA SoC wrt embedded platforms such as the BBB.

Note that the TI example code might not be for exactly the same kernel version you are using. There might be discrepancies.

I suggest you run a search on the source code to find where the error “ASoC: machine hw_params failed” is generated. You can add printk statements in your code so that you can later check in the kernel log that things are happening as you expect.

Cheers,
Robin

Pablo Fonovich

unread,
Jan 8, 2016, 5:22:16 PM1/8/16
to beagl...@googlegroups.com
Thanks Robin,
Im using latest stable kernel, think is 4.2, i can check when i get home... i will add printk statements, as you suggested...
Another question. I inted to use one mcasp serializer for 4 channels... in the am335x datasheet it seems possible, so i configured 4 tdm slots in the device tree instead of 2, but if i try to record with -c 6 it says again the "channels count non available". Do you know if its possible? its quite frustrating to work without propper documentation, but in need this project to get my title...

And last thing, where you able to get alsamixer working?
Thanks very much

Robin Scheibler

unread,
Jan 8, 2016, 5:49:48 PM1/8/16
to beagl...@googlegroups.com
Hi Pablo,

I don’t know for 4.2. Try to read the sound/alsa/soc/davinci/davinci-mcasp.c file to understand which functionalities are implemented. I used the kernel from Robert C Nelson’s repo on github.

After a quick search on google, I saw you are not the first person to attempt to connect this codec to the BBB.
Maybe you can try to contact this Wendelin Klimann.

BTW, this PCM3168 seems like a very neat chip. What exactly are you building ?

Cheers,
Robin

Robin Scheibler

unread,
Jan 8, 2016, 5:51:44 PM1/8/16
to beagl...@googlegroups.com

Pablo Fonovich

unread,
Jan 9, 2016, 6:45:41 PM1/9/16
to beagl...@googlegroups.com
Hi Robin:
I intend to implement a portable multitrack recorder, that's why i choose this codec, it has many inputs and outputs, good sample rate and bit resolution, and all in a single chip.
I can't find wendelin's mail direction, so i think i'll just write to that posts, but they are a bit old i think. I have already looked at them, but i was more confused by that time, perhaps now i can understand a bit more.

If i find out anything i will continue posting here, so if someone is interested in this project can look at ti...

Please if you find any documentation tell me!

Thanks

Pablo Fonovich

unread,
Jan 9, 2016, 8:23:16 PM1/9/16
to beagl...@googlegroups.com
Hi Robin:
with printk statements, i've isolated the error to this instruction:

ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);

but i don't know what is wrong... the sysclk variable is:

unsigned int sysclk = ((struct snd_soc_card_drvdata_davinci *)
               snd_soc_card_get_drvdata(soc_card))->sysclk;
Just linke in the evm_hw_params

I've noticed that you used:

ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_IN);

If i'm getting it right, this is to set the cpu_dai sysclock, but i dont get why you used 0 in the frequency parameter. Also you never used the function to set the codec_dai sysclk... Is it not necessary? I'll try commenting this line



Robin Scheibler

unread,
Jan 10, 2016, 11:55:11 AM1/10/16
to beagl...@googlegroups.com
Hi Pablo,

On 10 janv. 2016, at 01:48, Pablo Fonovich <pablo7f...@gmail.com> wrote:

Hi Robin:
with printk statements, i've isolated the error to this instruction:

ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);

but i don't know what is wrong... the sysclk variable is:

unsigned int sysclk = ((struct snd_soc_card_drvdata_davinci *)
               snd_soc_card_get_drvdata(soc_card))->sysclk;
Just linke in the evm_hw_params

What value of sysclk are you providing ?


I've noticed that you used:

ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_IN);

If i'm getting it right, this is to set the cpu_dai sysclock, but i dont get why you used 0 in the frequency parameter. Also you never used the function to set the codec_dai sysclk... Is it not necessary? I'll try commenting this line

In my case, MCLK is provided to the chipset by an external crystal. Thus there is no sysclk for me. BCLK and LRCLK are also provided by the chipset to McASP.

Best,
Robin

Pablo Fonovich

unread,
Jan 10, 2016, 2:09:12 PM1/10/16
to beagl...@googlegroups.com

Hi: im using 24Mhz, that is provided by de beaglebone... i used printk to see that sysclk value and it is correct... i get the value as is stated in the evm_hw_params function.
I dont see why the function returns error... but is there a list of error codes to see what -524 means?
Thanks very much

Robin Scheibler

unread,
Jan 11, 2016, 3:12:30 AM1/11/16
to beagl...@googlegroups.com
Hi Pablo,

I took a look at your code.

static int pcm3168_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *soc_card = rtd->card;
struct platform_device *pdev = to_platform_device(soc_card->dev);
int ret = 0;
unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *)
  snd_soc_card_get_drvdata(soc_card))->sysclk;

/* set the codec system clock */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;

/* set the CPU system clock */
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;

return 0;
}

I see that you are calling snd_soc_dai_set_sysclk for both codec_dai and cpu_dai. I think that is the error. In your case codec_dai is the PCM3168 chip and cpu_dai is the processor McASP module. Sysclk only makes sense for McASP as far as I understand. Try commenting out 

/* set the codec system clock */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;

I would also suggest you read up about the McASP clock generation structure in the sitara documentation (~7000 pages document available from TI). This helped me understand how the McASP module works.

Another resource I used is the linux cross-reference http://lxr.free-electrons.com/
I used it to look up where functions are defined and what they do.

Cheers,
Robin

Pablo Fonovich

unread,
Jan 11, 2016, 3:40:07 PM1/11/16
to beagl...@googlegroups.com
Hi:
Thanks for your suggestions!
i've already commented that line, as i said in the mail when i isolated the problem to that function... the error persist but now in:


ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;

I'm using the linux-cross-reference, that's how i find out what each parameter means, but perhaps i still dont quite understand what the function really does.

I've also read the mcasp section of the am335x datasheet when i was doing the PCB for the codec, but i should re-read it, as many things where not clear for me at that moment, and perhaps now they make a little more sense. Anyway, the problem and same error code persists, now in that other line...

Thanks for your help! i'll post any progress i make
 

Pablo Fonovich

unread,
Jan 12, 2016, 4:01:02 PM1/12/16
to beagl...@googlegroups.com
Hi Robin:

I realized that although i was commenting the line you said, i was using and old image of the compiled kernel, and that was why i kept getting the same error! My bad... Now that is working, but i have an error in the line:

ret = regmap_update_bits(priv->regmap, PCM3168_DAC_FMT_CONTROL, 0x0f, val);

on my pcm3168.c file... ret gets the value -128 (error code). I use this function to update some register on the codec... i suspected that my i2c connection is not working properly, so i commented this line (althoug i'm not sure if an error in i2c causes this function to crash) and finally the arecord command works gives no error, but records nothing :(

That was somehow expected, as my codec is not geting it's regmap updated... One of this days i will use an ozscope to see if the signals out of the i2c of the beaglebone are right... If you came up with some idea please tell me... you've been of great help...

P.D: have you got alsamixer working in your project?

Robin Scheibler

unread,
Feb 12, 2016, 10:17:27 AM2/12/16
to beagl...@googlegroups.com
Hi Pablo,

Any progress with your board ?

Also, to answer your question, I got the alsamixer working. You have to add a number of macros for predefined controls corresponding to register to update in the codec. You can see it directly in my code:



static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1);
static const struct snd_kcontrol_new sta321mp_snd_controls[] = {
SOC_SINGLE("Master Switch", STA321MP_MMUTE, 0, 1, 1),
SOC_SINGLE_TLV("Master Volume", STA321MP_MVOL, 0, 0xff, 1, mvol_tlv),
SOC_DOUBLE_R("Ch1 Capture Switch", STA321MP_C1VTMB, STA321MP_C2VTMB, 7, 1, 1),
SOC_DOUBLE_R("Ch2 Capture Switch", STA321MP_C3VTMB, STA321MP_C4VTMB, 7, 1, 1),
SOC_DOUBLE_R("Ch3 Capture Switch", STA321MP_C5VTMB, STA321MP_C6VTMB, 7, 1, 1),
SOC_DOUBLE_R_TLV("Ch1 Capture Volume", STA321MP_C1VOL, STA321MP_C2VOL, 0, 0xff, 1, chvol_tlv),
SOC_DOUBLE_R_TLV("Ch2 Capture Volume", STA321MP_C3VOL, STA321MP_C4VOL, 0, 0xff, 1, chvol_tlv),
SOC_DOUBLE_R_TLV("Ch3 Capture Volume", STA321MP_C5VOL, STA321MP_C6VOL, 0, 0xff, 1, chvol_tlv),
};

This implements volume control for all six capture channels, as well as mute switches.

Best,
Robin

Pablo Fonovich

unread,
Feb 13, 2016, 5:14:23 PM2/13/16
to beagl...@googlegroups.com
Hi robin!

By this time, i was writting a guide to get a custom linux os to boot in the beaglebone... and i was quite busy with that...

In my project, the drivers seems to be working properly, although i can't use regmap_update_bits function... i'm not sure, but i think it has something to do with the i2c communications that seems not to be working... If it has to update registers through i2c and this is not working, it makes sense that that functions returns error... i think that for that same reazon, alsamixer is not working... i've made the structures you told me, but i keep getting "input output error" when i try to "alsamixer"

Anyway, the university is closed till march here (we are on holydays) so i can't get the equipmet to test the hardware, and i don't own any right now (too expensive for me).

One main issue i'm having and that i can't solve is that i can record only 4 channels with arecord...
I configured 2 serializers as input, and 4 tdm slots on each in the device tree... but if i "arecord -c 6" it says "no channel count avaliable"... i'm starting to think that arecord recors from only one serializer... i would need to record an arbitrary channel if it's possible, and i think i should write an alsa application for this...

But more important right now seems to be this: Do you think is possible that alsamixer and  regmap_update_bits are not working cause of i2c problem?

Thanks for everything
Pablo


Pablo Fonovich

unread,
Mar 27, 2016, 10:02:18 AM3/27/16
to beagl...@googlegroups.com
Hi Robin:

After working hard, i'm sure that i'm having some hardware problems, cause driver seems to work but get no output. This led me to trying to communicate with the codec via i2c and i could not... So either my chip is dead or i'm having hardware trouble that i could not detect in the whole past week...

So i had the idea of using the same codec you did, to get something to work... if it's not much trouble, could you share with me the schematics of your hardware? and could i use the drivers you wrote?

It's very frustrating working so much and having hardware fails...

another thing i wanted to ask, do you know if alsamixer may not work if i2c communication is not possible? Cause i always get I/O error... although i wrote al needed (i think) structures

Thanks for everything

Pablo

Robin Scheibler

unread,
Apr 12, 2016, 7:58:21 AM4/12/16
to beagl...@googlegroups.com
Hi Pablo,

Sure, that should be no problem.

My files are actually already online. The license for it is CC-BY-SA (https://creativecommons.org/licenses/by-sa/4.0/legalcode). I need to update the readme to make this clear though. This means you’re free to use it, as long as proper attribution is done.

The repository is


I used Eagle CAD to design the board.

Let me know if you have any question.

Cheers,
Robin
Reply all
Reply to author
Forward
0 new messages