Part Number: AM5728
Other Parts Discussed in Thread: BEAGLEBOARD-X15
I've been developing software on a custom development board connected to BeagleBoard-X15 via its four extension connectors.
It features:
- Two identical "Audio Processor" ICs that can send/receive I2S signal. They have bus/clock connection in between, which might let them be seen as a single IC.
- A "Codec" IC that handles analog audio in/out. It's hardwired properly and there are no software control (like I2C) over it.
- All ICs share bit/word clock sourcing from "Audio Processor 1".
Now I'm facing the following situation:
- Playing audio with "aplay -D hw:CARD=AP -c 2 S32_LE -r 44100 audio.wav" through McASP6 (AXR1) to "Audio Processor (SDI0 -> BUS/CLK -> SDO1)", then to "Codec (SDI -> AOUT)" works fine.
- Recording audio with "arecord -D hw:CARD=AP -c 2 -f S32_LE -r 44100 audio.wav" from "Audio Processor 1 (SDO0)" (it can sound by itself) to McASP6 (AXR0) also works fine.
- Recording audio with "arecord -D hw:CARD=AP -c 2 -f S32_LE -r 44100 audio.wav" from "Codec (SDO)" to McASP6 (AXR2) also works fine (tested with McASP6 AXR0 set as INACTIVE in the device tree).
- But recording audio with "arecord -D hw:CARD=ADINPUT -c 2 -f S32_LE -r 44100 audio.wav" through "Codec (AIN -> SDO)" to McASP7 (AXR1) doesn't work well (I can hear the source audio but with intermittent noise).
What I just want to is to record source audio from "Codec" via McASP7 (AXR1), not via McASP6 (AXR2) for some reason. Are there any hints for this issue?
I'm also experiencing the similar issue for McASP7 as posted on E2E at e2e.ti.com/.../966376 (no reply yet). And the solution worked as well but the noise didn't go out.
The kernel version is linux-4.19.94+gitAUTOINC+be5389fd85-gbe5389fd85 from TI AM57xx processor SDK 06.03.00.106 built for am57xx-evm with the following modifications (related parts only).
am57xx-custom.dts:
mcasp6_pins_default: mcasp6_pins_default {
pinctrl-single,pins = <
DRA7XX_CORE_IOPAD(0x36bc, (PIN_INPUT_PULLDOWN | MUX_MODE1)) /* G13: mcasp1_axr2.mcasp6_axr2 */
DRA7XX_CORE_IOPAD(0x36d4, (PIN_INPUT_PULLDOWN | MUX_MODE1)) /* B12: mcasp1_axr8.mcasp6_axr0 */
DRA7XX_CORE_IOPAD(0x36d8, (PIN_OUTPUT_PULLDOWN | MUX_MODE1)) /* A11: mcasp1_axr9.mcasp6_axr1 */
DRA7XX_CORE_IOPAD(0x36dc, (PIN_INPUT_PULLDOWN | MUX_MODE1)) /* B13: mcasp1_axr10.mcasp6_aclkx */
DRA7XX_CORE_IOPAD(0x36e0, (PIN_INPUT_PULLDOWN | MUX_MODE1)) /* A12: mcasp1_axr11.mcasp6_fsx */
>;
};
mcasp7_pins_default: mcasp7_pins_default {
pinctrl-single,pins = <
DRA7XX_CORE_IOPAD(0x36e8, (PIN_INPUT_PULLDOWN | MUX_MODE1)) /* A13: mcasp1_axr13.mcasp7_axr1 */
DRA7XX_CORE_IOPAD(0x36ec, (PIN_INPUT_PULLDOWN | MUX_MODE1)) /* G14: mcasp1_axr14.mcasp7_aclkx */
//DRA7XX_CORE_IOPAD(0x36ec, (PIN_INPUT_PULLDOWN | MUX_MODE2)) /* G14: mcasp1_axr14.mcasp7_aclkr */
DRA7XX_CORE_IOPAD(0x36f0, (PIN_INPUT_PULLDOWN | MUX_MODE1)) /* F14: mcasp1_axr15.mcasp7_fsx */
//DRA7XX_CORE_IOPAD(0x36f0, (PIN_INPUT_PULLDOWN | MUX_MODE2)) /* F14: mcasp1_axr15.mcasp7_fsr */
>;
};
&mcasp6 {
status = "okay";
pinctrl-names ="default";
pinctrl-0 = <&mcasp6_pins_default>;
#sound-dai-cells = <0>;
assigned-clocks = <&l4per_clkctrl DRA7_MCASP6_CLKCTRL 24>;
assigned-clock-parents = <&sys_clkin2>;
op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
/* 4 serializers */
serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
2 1 2 0
>;
tx-num-evt = <32>;
rx-num-evt = <32>;
};
&mcasp7 {
status = "okay";
pinctrl-names ="default";
pinctrl-0 = <&mcasp7_pins_default>;
#sound-dai-cells = <0>;
assigned-clocks = <&l4per_clkctrl DRA7_MCASP7_CLKCTRL 24>;
assigned-clock-parents = <&sys_clkin2>;
op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
/* 4 serializers */
serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
0 2 0 0
>;
tx-num-evt = <32>;
rx-num-evt = <32>;
};
aliases {
sound2 = &sound2;
sound3 = &sound3;
};
board_ap: board_ap {
compatible = "vendor,board-ap";
#sound-dai-cells = <0>;
status = "okay";
};
board_adinput: board_adinput {
compatible = "vendor,board-adinput";
#sound-dai-cells = <0>;
status = "okay";
};
sound2: sound2 {
compatible = "simple-audio-card";
status = "okay";
simple-audio-card,name = "AP";
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&sound2_master>;
simple-audio-card,frame-master = <&sound2_master>;
//simple-audio-card,bitclock-inversion;
//simple-audio-card,frame-inversion;
simple-audio-card,cpu {
sound-dai = <&mcasp6>;
};
sound2_master: simple-audio-card,codec {
sound-dai = <&board_ap>;
};
};
sound3: sound3 {
compatible = "simple-audio-card";
status = "okay";
simple-audio-card,name = "ADINPUT";
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&sound3_master>;
simple-audio-card,frame-master = <&sound3_master>;
//simple-audio-card,bitclock-inversion;
//simple-audio-card,frame-inversion;
simple-audio-card,cpu {
sound-dai = <&mcasp7>;
};
sound3_master: simple-audio-card,codec {
sound-dai = <&board_adinput>;
};
};
sound/soc/codecs/board.c:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/soc.h>
static int board_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params,
struct snd_soc_dai *soc_dai)
{
return 0;
}
static int board_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
return 0;
}
static int board_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
return 0;
}
static int board_set_dai_tristate(struct snd_soc_dai *codec_dai,
int tristate)
{
return 0;
}
static struct snd_soc_dai_ops board_dai_ops = {
.hw_params = board_hw_params,
.set_sysclk = board_set_dai_sysclk,
.set_fmt = board_set_dai_fmt,
.set_tristate = board_set_dai_tristate,
};
static struct snd_soc_dai_driver board_ap_dai = {
.name = "board-hifi1",
.playback = {
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_44100,
.rate_min = 44100,
.rate_max = 44100,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.sig_bits = 24,
},
.capture = {
.channels_min = 2,
//.channels_max = 4,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_44100,
.rate_min = 44100,
.rate_max = 44100,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.sig_bits = 24,
},
.ops = &board_dai_ops,
};
static struct snd_soc_dai_driver board_adinput_dai = {
.name = "board-hifi2",
.capture = {
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_44100,
.rate_min = 44100,
.rate_max = 44100,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.sig_bits = 24,
},
.ops = &board_dai_ops,
};
static struct snd_soc_component_driver soc_component_dev_board = {
.idle_bias_on = 0,
.use_pmdown_time = 0,
.endianness = 0,
.non_legacy_dai_naming = 0,
};
static int board_probe(struct platform_device *pdev)
{
if (of_property_match_string(pdev->dev.of_node, "compatible", "vendor,board-ap") >= 0)
return devm_snd_soc_register_component(&pdev->dev, &soc_component_dev_board,
&board_ap_dai, 1);
else
return devm_snd_soc_register_component(&pdev->dev, &soc_component_dev_board,
&board_adinput_dai, 1);
}
static const struct of_device_id board_of_match[] = {
{ .compatible = "vendor,board-ap", },
{ .compatible = "vendor,board-adinput", },
{ }
};
MODULE_DEVICE_TABLE(of, board_of_match);
static struct platform_driver board_codec_driver = {
.probe = board_probe,
.driver = {
.name = "board-codec",
.of_match_table = board_of_match,
},
};
module_platform_driver(board_codec_driver);
