设计概述
功能:双声卡设计、播放音频的同时还能录音。
硬件设计
为了实现录音和播放互不干扰,所以硬件上的设计使用了两个codec(tlv320aic32x4),TX2则分别使用两组I2S、I2C接口,示意图如下:
双声卡驱动加载
在设备树添加声卡节点,需要添加及修改的节点有I2C、sound、dai-link-
以下是部分修改过的代码
tegra186-quill-common.dtsi 文件中
i2c@3180000 {
status = "okay";
aic32x4_1: tlv320aic32x4.2-0018@18 {
compatible = "ti,tlv320aic32x4";
status = "okay";
reg = <0x18>;
clocks = <&tegra_car TEGRA186_CLK_AUD_MCLK>;
clock-names = "mclk";
};
};
i2c@3160000 {
status = "okay";
aic32x4: tlv320aic32x4.0-0018@18 {
compatible = "ti,tlv320aic32x4";
status = "okay";
reg = <0x18>;
clocks = <&tegra_car TEGRA186_CLK_AUD_MCLK>;
clock-names = "mclk";
};
};
tegra_sound: sound {
compatible = "nvidia,tegra-audio-t186ref-mobile-rt565x";
nvidia,model = "tegra-snd-t186ref-mobile-rt565x";
nvidia,num-codec-link = <13>;
nvidia,num-clk = <8>;
nvidia,clk-rates = < 270950400 /* PLLA_x11025_RATE */
11289600 /* AUD_MCLK_x11025_RATE */
45158400 /* PLLA_OUT0_x11025_RATE */
45158400 /* AHUB_x11025_RATE */
245760000 /* PLLA_x8000_RATE */
12288000 /* AUD_MCLK_x8000_RATE */
49152000 /* PLLA_OUT0_x8000_RATE */
49152000 >;/* AHUB_x8000_RATE */
clocks = <&tegra_car TEGRA186_CLK_PLLP_OUT0>,
<&tegra_car TEGRA186_CLK_PLLA>,
<&tegra_car TEGRA186_CLK_PLL_A_OUT0>,
<&tegra_car TEGRA186_CLK_AHUB>,
<&tegra_car TEGRA186_CLK_CLK_M>,
<&tegra_car TEGRA186_CLK_AUD_MCLK>;
clock-names = "pll_p_out1", "pll_a", "pll_a_out0", "ahub",
"clk_m", "extern1";
resets = <&tegra_car TEGRA186_RESET_AUD_MCLK>;
reset-names = "extern1_rst";
status = "okay";
nvidia,audio-routing =
"z IN2_R", "z IN",
"z IN2_L", "z IN",
"z OUT", "z LOR",
"z OUT", "z LOL",
"y IN2_R", "y IN",
"y IN2_L", "y IN",
"y OUT", "y LOR",
"y OUT", "y LOL";
nvidia,xbar = <&tegra_axbar>;
//audio output
rt565x_dai_link: nvidia,dai-link-1 {
link-name = "ti-playback-i2s2";
cpu-dai = <&tegra_i2s2>;
codec-dai = <&aic32x4_1>;
cpu-dai-name = "I2S2";
codec-dai-name = "tlv320aic32x4-hifi";
tx-mask = <0xFF>;
rx-mask = <0xFF>;
format = "i2s";
bitclock-slave;
frame-slave;
bitclock-noninversion;
frame-noninversion;
bit-format = "s16_le";
bclk_ratio = <0>;
srate = <48000>;
num-channel = <1>;
ignore_suspend;
name-prefix = "z";
status = "okay";
};
// audio input
nvidia,dai-link-2 {
link-name = "ti-playback-i2s1";
cpu-dai = <&tegra_i2s1>;
codec-dai = <&aic32x4>;
cpu-dai-name = "I2S1";
codec-dai-name = "tlv320aic32x4-hifi";
tx-mask = <0xFF>;
rx-mask = <0xFF>;
format = "i2s";
bitclock-slave;
frame-slave;
bitclock-noninversion;
frame-noninversion;
bit-format = "s16_le";
bclk_ratio = <0>;
srate = <48000>;
num-channel = <1>;
ignore_suspend;
name-prefix = "y";
status = "okay";
};
nvidia,dai-link-3 {
link-name = "spdif-dit-2";
cpu-dai = <&tegra_i2s3>;
codec-dai = <&spdif_dit2>;
cpu-dai-name = "I2S3";
codec-dai-name = "dit-hifi";
format = "i2s";
bitclock-slave;
frame-slave;
bitclock-noninversion;
frame-noninversion;
bit-format = "s16_le";
bclk_ratio = <1>;
srate = <48000>;
num-channel = <2>;
ignore_suspend;
name-prefix = "z";
status = "disabled";
};
nvidia,dai-link-4 {
link-name = "spdif-dit-3";
cpu-dai = <&tegra_i2s4>;
codec-dai = <&spdif_dit3>;
cpu-dai-name = "I2S4";
codec-dai-name = "dit-hifi";
format = "i2s";
bitclock-slave;
frame-slave;
bitclock-noninversion;
frame-noninversion;
bit-format = "s16_le";
bclk_ratio = <1>;
srate = <48000>;
num-channel = <2>;
ignore_suspend;
name-prefix = "m";
status = "disabled";
};
nvidia,dai-link-5 {
link-name = "spdif-dit-4";
cpu-dai = <&tegra_i2s5>;
codec-dai = <&spdif_dit4>;
cpu-dai-name = "I2S5";
codec-dai-name = "dit-hifi";
format = "i2s";
bitclock-slave;
frame-slave;
bitclock-noninversion;
frame-noninversion;
bit-format = "s16_le";
bclk_ratio = <1>;
srate = <48000>;
num-channel = <2>;
ignore_suspend;
name-prefix = "n";
status = "disabled";
};
nvidia,dai-link-6 {
link-name = "spdif-dit-6";
cpu-dai = <&tegra_i2s6>;
codec-dai = <&spdif_dit6>;
cpu-dai-name = "I2S6";
codec-dai-name = "dit-hifi";
tx-mask = <0xFF>;
rx-mask = <0xFF>;
format = "dsp_a";
bitclock-slave;
frame-slave;
bitclock-inversion;
frame-noninversion;
bit-format = "s16_le";
bclk_ratio = <4>;
srate = <8000>;
num-channel = <1>;
ignore_suspend;
name-prefix = "o";
status = "disabled";
};
nvidia,dai-link-7 {
link-name = "spdif-dit-7";
cpu-dai = <&tegra_dmic1>;
codec-dai = <&spdif_dit7>;
cpu-dai-name = "DMIC1";
codec-dai-name = "dit-hifi";
format = "i2s";
bit-format = "s16_le";
srate = <48000>;
ignore_suspend;
num-channel = <2>;
name-prefix = "a";
status = "disabled";
};
nvidia,dai-link-8 {
link-name = "spdif-dit-8";
cpu-dai = <&tegra_dmic2>;
codec-dai = <&spdif_dit8>;
cpu-dai-name = "DMIC2";
codec-dai-name = "dit-hifi";
format = "i2s";
bit-format = "s16_le";
srate = <48000>;
ignore_suspend;
num-channel = <2>;
name-prefix = "b";
status = "disabled";
};
nvidia,dai-link-9 {
link-name = "spdif-dit-9";
cpu-dai = <&tegra_dmic3>;
codec-dai = <&spdif_dit9>;
cpu-dai-name = "DMIC3";
codec-dai-name = "dit-hifi";
format = "i2s";
bit-format = "s16_le";
srate = <48000>;
ignore_suspend;
num-channel = <2>;
name-prefix = "c";
status = "disabled";
};
nvidia,dai-link-10 {
link-name = "spdif-dit-10";
cpu-dai = <&tegra_dmic4>;
codec-dai = <&spdif_dit10>;
cpu-dai-name = "DMIC4";
codec-dai-name = "dit-hifi";
format = "i2s";
bit-format = "s16_le";
srate = <48000>;
ignore_suspend;
num-channel = <2>;
name-prefix = "d";
status = "disabled";
};
spdif_dai_link: nvidia,dai-link-11 {
link-name = "spdif-playback";
cpu-dai = <&tegra_spdif>;
codec-dai = <&spdif_dit11>;
cpu-dai-name = "SPDIF1-1";
codec-dai-name = "dit-hifi";
format = "i2s";
bit-format = "s16_le";
srate = <48000>;
num-channel = <2>;
ignore_suspend;
name-prefix = "e";
status = "disabled";
};
dspk_1_dai_link: nvidia,dai-link-12 {
link-name = "dspk-playback-r";
cpu-dai = <&tegra_dspk1>;
codec-dai = <&spdif_dit12>;
cpu-dai-name = "DSPK1";
codec-dai-name = "dit-hifi";
format = "i2s";
bit-format = "s16_le";
srate = <48000>;
num-channel = <2>;
ignore_suspend;
name-prefix = "d1";
status = "disabled";
};
dspk_2_dai_link: nvidia,dai-link-13 {
link-name = "dspk-playback-l";
cpu-dai = <&tegra_dspk2>;
codec-dai = <&spdif_dit13>;
cpu-dai-name = "DSPK2";
codec-dai-name = "dit-hifi";
format = "i2s";
bit-format = "s16_le";
srate = <48000>;
num-channel = <2>;
ignore_suspend;
name-prefix = "d2";
status = "disabled";
};
};
tegra_t186ref_mobile_rt565x.c 文件中
static int tegra_t186ref_dai_init(struct snd_soc_pcm_runtime *rtd,
int rate,
int channels,
u64 formats,
bool is_playback)
{
struct snd_soc_card *card = rtd->card;
struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
struct snd_soc_pcm_stream *dai_params;
unsigned int idx, clk_out_rate;
int err, codec_rate, clk_rate;
codec_rate = tegra_t186ref_srate_values[machine->rate_via_kcontrol];
clk_rate = (machine->rate_via_kcontrol) ? codec_rate : rate;
err = tegra_alt_asoc_utils_set_rate(&machine->audio_clock, clk_rate,
0, 0);
if (err < 0) {
dev_err(card->dev, "Can't configure clocks\n");
return err;
}
clk_out_rate = machine->audio_clock.clk_out_rate;
pr_debug("pll_a_out0 = %d Hz, aud_mclk = %d Hz, codec rate = %d Hz\n",
machine->audio_clock.set_mclk, clk_out_rate, clk_rate);
tegra_t186ref_set_params(card, machine, rate, channels, formats);
idx = tegra_machine_get_codec_dai_link_idx_t18x("ti-playback-i2s1");
/* check if idx has valid number */
if (idx != -EINVAL) {
dai_params =
(struct snd_soc_pcm_stream *)card->rtd[idx].dai_link->params;
dai_params->rate_min = clk_rate;
dai_params->formats = (machine->fmt_via_kcontrol == 2) ?
(1ULL << SNDRV_PCM_FORMAT_S32_LE) : formats;
if (!machine->is_codec_dummy) {
err = snd_soc_dai_set_sysclk(card->rtd[idx].codec_dai,
0, 12000000, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
}
}
}
idx = tegra_machine_get_codec_dai_link_idx_t18x("ti-playback-i2s2");
/* check if idx has valid number */
if (idx != -EINVAL) {
dai_params =
(struct snd_soc_pcm_stream *)card->rtd[idx].dai_link->params;
dai_params->rate_min = clk_rate;
dai_params->formats = (machine->fmt_via_kcontrol == 2) ?
(1ULL << SNDRV_PCM_FORMAT_S32_LE) : formats;
if (!machine->is_codec_dummy) {
err = snd_soc_dai_set_sysclk(card->rtd[idx].codec_dai,
0, 12000000, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(card->dev, "codec_dai clock not set\n");
return err;
}
}
}
return 0;
}
static void dai_link_setup(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
struct snd_soc_codec_conf *tegra_machine_codec_conf = NULL;
struct snd_soc_codec_conf *tegra_t186ref_codec_conf = NULL;
struct snd_soc_dai_link *tegra_machine_dai_links = NULL;
struct snd_soc_dai_link *tegra_t186ref_codec_links = NULL;
int i;
/* set new codec links and conf */
tegra_t186ref_codec_links = tegra_machine_new_codec_links(pdev,
tegra_t186ref_codec_links,
&machine->num_codec_links);
if (!tegra_t186ref_codec_links)
goto err_alloc_dai_link;
/* set codec init */
for (i = 0; i < machine->num_codec_links; i++) {
if (tegra_t186ref_codec_links[i].name) {
if (strstr(tegra_t186ref_codec_links[i].name,
"rt565x-playback"))
tegra_t186ref_codec_links[i].init = tegra_t186ref_init;
else if (strstr(tegra_t186ref_codec_links[i].name, "ti-playback-i2s1"))
tegra_t186ref_codec_links[i].init = tegra_t186ref_init;
else if (strstr(tegra_t186ref_codec_links[i].name, "ti-playback-i2s2"))
tegra_t186ref_codec_links[i].init = tegra_t186ref_init;
else if (strstr(tegra_t186ref_codec_links[i].name,
"dspk-playback-r"))
tegra_t186ref_codec_links[i].init = tegra_t186ref_dspk_init;
else if (strstr(tegra_t186ref_codec_links[i].name,
"dspk-playback-l"))
tegra_t186ref_codec_links[i].init = tegra_t186ref_dspk_init;
}
}
tegra_t186ref_codec_conf = tegra_machine_new_codec_conf(pdev,
tegra_t186ref_codec_conf,
&machine->num_codec_links);
if (!tegra_t186ref_codec_conf)
goto err_alloc_dai_link;
/* get the xbar dai link/codec conf structure */
tegra_machine_dai_links = tegra_machine_get_dai_link_t18x();
if (!tegra_machine_dai_links)
goto err_alloc_dai_link;
tegra_machine_codec_conf = tegra_machine_get_codec_conf_t18x();
if (!tegra_machine_codec_conf)
goto err_alloc_dai_link;
/* set ADMAIF dai_ops */
for (i = TEGRA186_DAI_LINK_ADMAIF1;
i <= TEGRA186_DAI_LINK_ADMAIF20; i++)
tegra_machine_set_dai_ops(i, &tegra_t186ref_ops);
/* set sfc dai_init */
tegra_machine_set_dai_init(TEGRA186_DAI_LINK_SFC1_RX,
&tegra_t186ref_sfc_init);
#if defined(CONFIG_SND_SOC_TEGRA210_ADSP_ALT)
/* set ADSP PCM/COMPR */
for (i = TEGRA186_DAI_LINK_ADSP_PCM1;
i <= TEGRA186_DAI_LINK_ADSP_PCM2; i++) {
tegra_machine_set_dai_ops(i, &tegra_t186ref_ops);
}
/* set ADSP COMPR */
for (i = TEGRA186_DAI_LINK_ADSP_COMPR1;
i <= TEGRA186_DAI_LINK_ADSP_COMPR2; i++) {
tegra_machine_set_dai_compr_ops(i,
&tegra_t186ref_compr_ops);
}
#endif
/* set ASRC params. The default is 2 channels */
for (i = 0; i < 6; i++) {
tegra_machine_set_dai_params(TEGRA186_DAI_LINK_ASRC1_TX1 + i,
(struct snd_soc_pcm_stream *)
&tegra_t186ref_asrc_link_params[i]);
tegra_machine_set_dai_params(TEGRA186_DAI_LINK_ASRC1_RX1 + i,
(struct snd_soc_pcm_stream *)
&tegra_t186ref_asrc_link_params[i]);
}
/* append t186ref specific dai_links */
card->num_links =
tegra_machine_append_dai_link_t18x(tegra_t186ref_codec_links,
2 * machine->num_codec_links);
tegra_machine_dai_links = tegra_machine_get_dai_link_t18x();
card->dai_link = tegra_machine_dai_links;
/* append t186ref specific codec_conf */
card->num_configs =
tegra_machine_append_codec_conf_t18x(tegra_t186ref_codec_conf,
machine->num_codec_links);
tegra_machine_codec_conf = tegra_machine_get_codec_conf_t18x();
card->codec_conf = tegra_machine_codec_conf;
return;
err_alloc_dai_link:
tegra_machine_remove_dai_link();
tegra_machine_remove_codec_conf();
return;
}
static int tegra_t186ref_driver_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct snd_soc_card *card = &snd_soc_tegra_t186ref;
struct tegra_t186ref *machine;
struct tegra_asoc_platform_data *pdata = NULL;
struct snd_soc_codec *codec = NULL;
int idx = 0;
int ret = 0;
const char *codec_dai_name;
if (!np) {
dev_err(&pdev->dev, "No device tree node for t186ref driver");
return -ENODEV;
}
machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_t186ref),
GFP_KERNEL);
if (!machine) {
dev_err(&pdev->dev, "Can't allocate t186ref struct\n");
ret = -ENOMEM;
goto err;
}
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, machine);
machine->is_codec_dummy = 0;
machine->audio_clock.clk_cdev1_state = 0;
machine->digital_reg = NULL;
machine->spk_reg = NULL;
machine->dmic_reg = NULL;
card->dapm.idle_bias_off = true;
ret = snd_soc_of_parse_card_name(card, "nvidia,model");
if (ret)
goto err;
ret = snd_soc_of_parse_audio_routing(card,
"nvidia,audio-routing");
if (ret)
goto err;
if (of_property_read_u32(np, "nvidia,num-clk",
&machine->audio_clock.num_clk) < 0) {
dev_err(&pdev->dev,
"Missing property nvidia,num-clk\n");
ret = -ENODEV;
goto err;
}
if (of_property_read_u32_array(np, "nvidia,clk-rates",
(u32 *)&machine->audio_clock.clk_rates,
machine->audio_clock.num_clk) < 0) {
dev_err(&pdev->dev,
"Missing property nvidia,clk-rates\n");
ret = -ENODEV;
goto err;
}
dai_link_setup(pdev);
#ifdef CONFIG_SWITCH
/* Addd h2w swith class support */
ret = tegra_alt_asoc_switch_register(&tegra_t186ref_headset_switch);
if (ret < 0)
goto err_alloc_dai_link;
#endif
pdata = devm_kzalloc(&pdev->dev,
sizeof(struct tegra_asoc_platform_data),
GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev,
"Can't allocate tegra_asoc_platform_data struct\n");
return -ENOMEM;
}
pdata->gpio_codec1 = pdata->gpio_codec2 = pdata->gpio_codec3 =
pdata->gpio_spkr_en = pdata->gpio_hp_mute =
pdata->gpio_int_mic_en = pdata->gpio_ext_mic_en = -1;
machine->pdata = pdata;
machine->pcard = card;
ret = tegra_alt_asoc_utils_init(&machine->audio_clock,
&pdev->dev,
card);
if (ret)
goto err_switch_unregister;
ret = tegra_alt_asoc_utils_set_parent(&machine->audio_clock, false);
if (ret){
dev_err(&pdev->dev, "tegra_alt_asoc_utils_set_parent failed (%d)\n",
ret);
goto err_switch_unregister;
}
ret = snd_soc_register_card(card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
ret);
goto err_fini_utils;
}
idx = tegra_machine_get_codec_dai_link_idx_t18x("ti-playback-i2s1");
/* check if idx has valid number */
if (idx == -EINVAL)
dev_warn(&pdev->dev, "codec link not defined - codec not part of sound card --i2s1");
else {
codec = card->rtd[idx].codec;
codec_dai_name = card->rtd[idx].dai_link->codec_dai_name;
dev_info(&pdev->dev,
"codec-dai \"%s\" registered\n", codec_dai_name);
if (!strcmp("dit-hifi", codec_dai_name)) {
dev_info(&pdev->dev, "This is a dummy codec\n");
machine->is_codec_dummy = 1;
}
}
idx = tegra_machine_get_codec_dai_link_idx_t18x("ti-playback-i2s2");
/* check if idx has valid number */
if (idx == -EINVAL)
dev_warn(&pdev->dev, "codec link not defined - codec not part of sound card --i2s2");
else {
codec = card->rtd[idx].codec;
codec_dai_name = card->rtd[idx].dai_link->codec_dai_name;
dev_info(&pdev->dev,
"codec-dai \"%s\" registered\n", codec_dai_name);
if (!strcmp("dit-hifi", codec_dai_name)) {
dev_info(&pdev->dev, "This is a dummy codec\n");
machine->is_codec_dummy = machine->is_codec_dummy|2;
}
}
return 0;
err_fini_utils:
tegra_alt_asoc_utils_fini(&machine->audio_clock);
err_switch_unregister:
#ifdef CONFIG_SWITCH
tegra_alt_asoc_switch_unregister(&tegra_t186ref_headset_switch);
#endif
err_alloc_dai_link:
tegra_machine_remove_dai_link();
tegra_machine_remove_codec_conf();
err:
return ret;
}
编译及烧写
由于音频驱动是以编译到内核的方式,所以以下步骤是以内核编译介绍
- 在TX2内核源码目录下顺序执行下列命令
- export CROSS_COMPILE=/gcc交叉编译工具路径
- export TEGRA_KERNEL_OUT=/编译后输出的路径
- export ARCH=arm64
- export $TEGRA_KERNEL_OUT tegra18_defconfig
- make $TEGRA_KERNEL_OUT zImage -j4
- make $TEGRA_KERNEL_OUT dtbs -j4
分别将生成的Image文件和dtb文件复制到JetPack3.3/64_TX2/Linux_for_Tegra/kernel文件夹下和JetPack3.3/64_TX2/Linux_for_Tegra/kernel/dtb文件夹下
cd 到JetPack3.3/64_TX2/Linux_for_Tegra目录下
- TX2进入recovery模式
- sudo ./flash.sh -r -k kernel/Image jetson-tx2 mmcblk0p1 //烧写system.img
- sudo ./flash.sh -r -k kernel-dtb jetson-tx2 mmcblk0p1 //烧写设备树dtb文件
调试及结果
调试方法:目的是实现录音与播放同时进行,所以要写一个测试demo脚本,将mic放在正在播放音乐的手机旁边,将speaker放在离mic远一些的地方,一遍录音一遍播放。
以下是测试demo脚本
RecordingAndPlayback.sh
#!bin/bash
amixer -C tegrasndt186ref sset 'ADMAIF2 Mux' 'I2S2'
amixer -C tegrasndt186ref sset 'I2S2 Mux' 'ADMAIF2'
amixer -C tegrasndt186ref sset 'ADMAIF3 Mux' 'I2S1'
amixer -C tegrasndt186ref sset 'I2S1 Mux' 'ADMAIF3'
amixer -C tegrasndt186ref cset name='I2S1 Channels' 2
amixer -C tegrasndt186ref cset name='I2S2 Channels' 2
amixer -C tegrasndt186ref cset name='I2S2 TX Stereo to mono conv' CH0
amixer -C tegrasndt186ref cset name='y Auto-mute Switch' 0
amixer -C tegrasndt186ref cset name='z Auto-mute Switch' 0
amixer -C tegrasndt186ref cset name='z HP DAC Playback Switch' 0
amixer -C tegrasndt186ref cset name='z HP Driver Gain Volume' 0
amixer -C tegrasndt186ref cset name='z HPL Output Mixer IN1_L Switch' 0
amixer -C tegrasndt186ref cset name='z HPL Output Mixer IN1_R Switch' 0
amixer -C tegrasndt186ref cset name='z HPL Output Mixer L_DAC Switch' 0
amixer -C tegrasndt186ref cset name='z HPL Output Mixer R_DAC Switch' 0
amixer -C tegrasndt186ref cset name='z LO DAC Playback Switch' 1
#0~60dB
amixer -C tegrasndt186ref cset name='z LO Driver Gain Volume' 30
amixer -C tegrasndt186ref cset name='z LOL Output Mixer L_DAC Switch' 1
amixer -C tegrasndt186ref cset name='z LOL Output Mixer R_DAC Switch' 1
# -63.5dB~24dB
amixer -C tegrasndt186ref cset name='z PCM Playback Volume' 60
amixer -C tegrasndt186ref cset name='z PGA Level Volume' 90
amixer -C tegrasndt186ref cset name='y PGA Level Volume' 90
amixer -C tegrasndt186ref cset name='y Mic PGA Switch' 0
amixer -C tegrasndt186ref cset name='z Mic PGA Switch' 0
amixer -C tegrasndt186ref cset name='y Right Input Mixer IN2_R P Switch' 1
amixer -C tegrasndt186ref cset name='Z Right Input Mixer IN2_R P Switch' 1
amixer -C tegrasndt186ref cset name='y Left Input Mixer IN2_L P Switch' 1
amixer -C tegrasndt186ref cset name='Z Left Input Mixer IN2_L P Switch' 1
amixer -C tegrasndt186ref cset name='z ADCFGA Left Mute Switch' 0
amixer -C tegrasndt186ref cset name='z ADCFGA Right Mute Switch' 0
amixer -C tegrasndt186ref cset name='y ADCFGA Left Mute Switch' 0
amixer -C tegrasndt186ref cset name='y ADCFGA Right Mute Switch' 0
arecord -D hw:tegrasndt186ref,2 -c 2 -r 48000 -f dat | aplay -D hw:tegrasndt186ref,1 -r 48000
链接
版权声明:本文为rendog原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。