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.
    */

+#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