Custom Beaglebone black Audio cape with TLV320AIC3110

Hi,

I am trying to design a cape with TLV320AIC3110 for Beaglebone black using I2c2 and Mcasp0. I have compiled the driver into the kernel and modified the device tree. This is my procedure.

ubuntu@arm:~$ uname -r
3.15.10-bone8

1- Driver:
I am using the driver in /sound/soc/codecs/tlc320aic31xx.c

`

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index d1929de…1c300a5 100644
— a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -19,7 +19,7 @@

  • high performance codec which provides a stereo DAC, a mono ADC,
  • and mono/stereo Class-D speaker driver.
    */

Hi,

I am trying to design a cape with TLV320AIC3110 for Beaglebone black using I2c2 and Mcasp0. I have compiled the driver into the kernel and modified the device tree. This is my procedure.

ubuntu@arm:~$ uname -r
3.15.10-bone8

1- Driver:
I am using the driver in /sound/soc/codecs/tlc320aic31xx.c

`

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index d1929de…1c300a5 100644
— a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -19,7 +19,7 @@

  • high performance codec which provides a stereo DAC, a mono ADC,
  • and mono/stereo Class-D speaker driver.
    */

+#define DEBUG
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>

`
2- Edit Kconfig

`

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index f0e8401…19036e3 100644
— a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -461,7 +461,8 @@ config SND_SOC_TLV320AIC26
depends on SPI

config SND_SOC_TLV320AIC31XX

  • tristate
  • tristate “TI TLV320AIC31xx class D codecs”
  • depends on I2C

config SND_SOC_TLV320AIC32X4
tristate

`

3- ALSA Machine Layer Configuration:

Create a DAI (digital audio interface) Link structure. This should allow a specific configuration for the McASP to be called when Linux is directed to play audio to the TLV320AIC31XX. For Sitara McASP machine layer driver is found at sound/soc/davinci/davinci-evm.c

`

diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index cab98a5…41db457 100644
— a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -8,7 +8,7 @@

  • it under the terms of the GNU General Public License version 2 as
  • published by the Free Software Foundation.
    */

+#define DEBUG
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/timer.h>
@@ -98,6 +98,13 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets
SND_SOC_DAPM_LINE(“Line In”, NULL),
};

+static const struct snd_soc_dapm_widget aic31xx_dapm_widgets = {

  • SND_SOC_DAPM_HP(“Headphone Jack”, NULL),
  • SND_SOC_DAPM_SPK(“Speaker”, NULL),
  • SND_SOC_DAPM_MIC(“Mic Jack”, NULL),
    +};

/* davinci-evm machine audio_mapnections to the codec pins /
static const struct snd_soc_dapm_route audio_map[] = {
/
Headphone connected to HPLOUT, HPROUT */
@@ -120,6 +127,7 @@ static const struct snd_soc_dapm_route audio_map = {
{“LINE2R”, NULL, “Line In”},
};

/* Logic for a aic3x as connected on a davinci-evm */
static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
{
@@ -150,6 +158,42 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}

+/* Logic for a aic31xx as connected on a davinci-evm */
+static int evm_aic31xx_init (struct snd_soc_pcm_runtime *rtd)
+{

  • struct snd_soc_codec *codec = rtd->codec;

  • struct snd_soc_dapm_context *dapm = &codec->dapm;

  • struct device_node *np = codec->card->dev->of_node;

  • int ret;

  • /* Add davinci-evm specific widgets */

  • snd_soc_dapm_new_controls(dapm, aic31xx_dapm_widgets,

  • ARRAY_SIZE(aic31xx_dapm_widgets));

  • if (np) {

  • ret = snd_soc_of_parse_audio_routing(codec->card, "ti,audio-rou

  • if (ret)

  • return ret;

  • }
    +/*
    +else {
    +*/

  • /* Set up davinci-evm specific audio path audio_map /
    +/

  • snd_soc_dapm_add_routes(&card->dapm, audio_map,

  • ARRAY_SIZE(audio_map));

  • }
    +*/

  • /* not connected */

  • /* snd_soc_dapm_nc_pin(&codec->dapm, “MONO_LOUT”);

  • snd_soc_dapm_nc_pin(&codec->dapm, “HPLCOM”);

  • snd_soc_dapm_nc_pin(&codec->dapm, “HPRCOM”);
    +*/

  • return 0;
    +}

/* davinci-evm digital audio interface glue - connects codec ↔ CPU */
static struct snd_soc_dai_link dm6446_evm_dai = {
.name = “TLV320AIC3X”,
@@ -250,6 +294,8 @@ static struct snd_soc_dai_link da850_evm_dai = {
SND_SOC_DAIFMT_IB_NF,
};

/* davinci dm6446 evm audio machine driver /
/

  • ASP0 in DM6446 EVM is clocked by U55, as configured by
    @@ -343,16 +389,33 @@ static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
    .stream_name = “AIC3X”,
    .codec_dai_name = “tlv320aic3x-hifi”,
    .ops = &evm_ops,
  • .init = evm_aic3x_init,
  • .init = evm_aic3x_init,
    .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
    SND_SOC_DAIFMT_IB_NF,
    };

+/*Modified evm_dai_tlv320aic3x() for aic3110 */
+static struct snd_soc_dai_link evm_dai_tlv320aic3110 = {

  • .name = “TLV320AIC3110”,
  • .stream_name = “AIC3110”, /* What should I put here? */
  • .codec_dai_name = “tlv320aic31xx-hifi”,
  • .ops = &evm_ops,
  • .init = evm_aic31xx_init,
  • .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
  • SND_SOC_DAIFMT_IB_NF,
    +};

static const struct of_device_id davinci_evm_dt_ids = {
{
.compatible = “ti,da830-evm-audio”,

  • .data = (void *) &evm_dai_tlv320aic3x,
  • .data = (void ) &evm_dai_tlv320aic3x,
    +/
    .data = (void ) &evm_dai_tlv320aic3110,/
    },
  • {
  • .compatible = “ti,TLV320AIC3110-audio”,
  • .data = (void *) &evm_dai_tlv320aic3110,
  • },

{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids);

`
4-Add TLV320AIC3110_SOC_EVM build option.

`

— a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -13,7 +13,7 @@ config SND_DAVINCI_SOC_VCIF

config SND_DAVINCI_SOC_GENERIC_EVM
tristate

  • select SND_SOC_TLV320AIC3X
  • select SND_SOC_TLV320AIC31XX
    select SND_DAVINCI_SOC_MCASP

config SND_AM33XX_SOC_EVM
@@ -22,7 +22,7 @@ config SND_AM33XX_SOC_EVM
select SND_DAVINCI_SOC_GENERIC_EVM
help
Say Y or M if you want to add support for SoC audio on AM33XX

  • boards using McASP and TLV320AIC3X codec. For example AM335X-EVM,
  • boards using McASP and TLV320AIC31XX codec. For example AM335X-EVM,
    AM335X-EVMSK, and BeagelBone with AudioCape boards have this
    setup.

`

5- Adding Device tree entries:
For Beaglebone Black KERNEL/arch/arm/boot/dts/am335x-boneblack.dts is used so we modify it to add the sound card.

`

— a/arch/arm/boot/dts/am335x-boneblack.dts
+++ b/arch/arm/boot/dts/am335x-boneblack.dts
@@ -64,6 +64,11 @@
/* Pins: P9.24, P9.28, P9.29, P9.31, P9.30 /
/
#include “am335x-bone-audio.dtsi” */

+/*Customized Audio codec TLV320AIC31XX.C /
+#include “am335x-bone-tlv320aic31xx.dtsi”
+
+
+
/
http://elinux.org/CircuitCo:BeagleBone_LCD3 /
/
#include “am335x-bone-lcd3-01-00a2.dtsi” */

`
6- CreateKERNEL/arch/arm/boot/dts/am335x-bone-tlv320aic31xx.dtsi

`

#include <dt-bindings/sound/tlv320aic31xx-micbias.h>

&i2c2 {
tlv320aic3110: tlv320aic3110@18 {
compatible =“ti,tlv320aic3110” ;
reg = <0x18>;
ai31xx-micbias-vg = <1>;
status = “okay”;
/* Regulators /
/
This might be eddited */
HPVDD-supply = <&ldo4_reg>;
SPRVDD-supply = <&ldo4_reg>;
SPLVDD-supply = <&ldo4_reg>;
AVDD-supply = <&ldo4_reg>;
IOVDD-supply = <&ldo4_reg>;
DVDD-supply = <&vbat>;
};
};

&mcasp0 {
pinctrl-names = “default”;
pinctrl-0 = <&mcasp0_pins_audio>;
status = “okay”;
op-mode = <0>; /* MCASP_IIS_MODE /
tdm-slots = <2>;
num-serializer = <16>;
serial-dir = < /
0: INACTIVE, 1: TX, 2: RX */
2 0 1 0
0 0 0 0
0 0 0 0
0 0 0 0

;
tx-num-evt = <1>;
rx-num-evt = <1>;
};

/ {
sound {
compatible = “ti,TLV320AIC3110-audio”;
ti,model = “DA830 EVM”;
ti,audio-codec = <&tlv320aic3110>;
ti,mcasp-controller = <&mcasp0>;
ti,codec-clock-rate = <12000000>;
ti,audio-routing =
/* Source Sink /
/
output in driver*/
/* Speaker connections /
“Headphone Jack”, “HPL”,
“Headphone Jack”, “HPR”,
“Speaker”, “SPL”,
“Speaker”, “SPR”,
“Mic Jack”, “MICBIAS”,
/
Microphone connections /
/
input in driver */
“MIC1LP”, “Mic Jack”,
“MIC1RP”, “Mic Jack”,
“MIC1LM”, “Mic Jack”;
};
};

`

If you look at Documentation/devicetree/bindings/sound/davinci-evm-audio.txt, you will see:

“MIC3L”, “Mic Bias 2V”
“MIC3R”, “Mic Bias 2V”
“Mic Bias 2V”, “Mic Jack"

Regards,
John

Alex, I, too am looking to develop an audio application using a BBB, but know very little about Linux audio (I’m a capable-enough hardware engineer, and have lots of software development experience on iOS/OS X and numerous small processors, bare-metal, but not a ton of Linux). I essentially want to build a “radio,” so I’ll be developing a cape with audio out and amplifier. Your choice of IC might be adequate, or I’ll find some other I2S chip (is I2S the same as your “I2c2”?). My cape will also have some additional electronics for interfacing the rest of my “radio’s” user interface.

Could I ask you additional questions as I get further into this?

Thanks!

I'm developing a clock-radio device using a USB sound card and a USB radio tuner.
Since it is a one-off project, I decided to use existing USB devices:

ADS RDX-155-EF Instant FM Music - $7.50
Plugable USB Audio Adapter - $7.95

Just a suggestion.

Thanks, Peter. I'm doing something similar for the first pass of this, but if it works out, I'll want to make the cape so I can make a few more (they are intended to be gifts for special people), and so others can do the same.

Mine doesn't actually have a radio or clock in it. It's just an appliance that plays MP3s.

Hi Rick,

I am hardware engineer too; Sounds like we are in the same boat:)

I essentially want to build a “radio,” so I’ll be developing a cape with audio out and amplifier

I would recommend you to have look at TLV320AIC3100 with class D 4ohm speaker driver. It saves you amplifier design for driving speakers and has stereo Headphone ports. Needless to say, with class D amplifier you get the lowest power consumption possible compared to class AB etc.
If you need stereo speaker output consider TLV320AIC3110.

(is I2S the same as your “I2c2”?)

No, TI calls I2S, Inter IC Sound, McASP which is a four wire bus. I2C is Inter-Integrated Circuit and is a two wire bus. For codec you need both of them. You need I2C for programming the registers and I2S for transmission of voice.

Could I ask you additional questions as I get further into this?

That’s what forum is for. It is pretty simple. Just connect your I2C and I2S to micros I2C and McASP, do the procedure that I wrote above, and you are done.

Best regards,

-Alex

Just by the audio cape and you are done for MP3 player.

regards,

-A.

Which audio cape? I only know about this one: http://elinux.org/CircuitCo:Audio_Cape_RevB, which can't power a speaker.

Hi Rick,

I am hardware engineer too; Sounds like we are in the same boat:)

I essentially want to build a "radio," so I'll be developing a cape with audio out and amplifier

I would recommend you to have look at TLV320AIC3100 with class D 4ohm speaker driver. It saves you amplifier design for driving speakers and has stereo Headphone ports. Needless to say, with class D amplifier you get the lowest power consumption possible compared to class AB etc.
If you need stereo speaker output consider TLV320AIC3110.

Okay, good. I found that IC in my research, thought it might be useful.

(is I2S the same as your "I2c2"?)
No, TI calls I2S, Inter IC Sound, McASP which is a four wire bus. I2C is Inter-Integrated Circuit and is a two wire bus. For codec you need both of them. You need I2C for programming the registers and I2S for transmission of voice.

I realized after reading more that "i2c2" must've been the Sitara's I2C bus #2, and that I2S support was provided by McASP.

Could I ask you additional questions as I get further into this?
That's what forum is for. It is pretty simple. Just connect your I2C and I2S to micros I2C and McASP, do the procedure that I wrote above, and you are done.

Awesome, thanks!

If your radio mean FM and AM without DAB , i recommend TEF6657

If with DAB ,TEF7741 DIRANA2 is better choice ,and this is a very general chip in audio CAR

BTW , I had write a demo version TEF6657 audio driver ,

About the TLVAIC3104 , Its only have about 2w amplifier ,

for a 25x4 w amplifier , Your 5v2A power is not enough .

No AM or FM here; the BBB will provide all the audio data.

NXP will have the Audio codec chip and FM/AM/DAB combined
Since your will build another cape , do you mean this ?
maybe you can consider about this