Jetson-TX2双声卡TLV320AIC32x4 alsa实现同时录音与播放

Jetson-TX2双声卡TLV320AIC32x4 alsa实现同时录音与播放

设计概述

功能:双声卡设计、播放音频的同时还能录音。

硬件设计

为了实现录音和播放互不干扰,所以硬件上的设计使用了两个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

链接

TX2双声卡驱动及测试demo源码文件

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 首先,要手动安装Jetson TX2中的CUDA和CuDNN,需要按照以下步骤进行操作: 1. 下载CUDA Toolkit: - 首先,通过NVIDIA官方网站下载适用于Jetson TX2的CUDA Toolkit。 - 在下载页面上选择与您的Jetson TX2版本相对应的CUDA Toolkit版本,并下载该版本的.run文件。 2. 安装CUDA Toolkit: - 将下载的CUDA Toolkit文件拷贝到Jetson TX2设备上。 - 打开终端,进入到CUDA Toolkit文件所在的目录。 - 运行以下命令,以设置安装选项并启动安装过程: ``` chmod +x cuda_<version>_linux.run sudo ./cuda_<version>_linux.run ``` - 按照安装向导的指示进行操作,接受许可协议并选择相应的安装选项。 - 完成安装后,根据提示将必要的环境变量添加到系统配置文件中(如~/.bashrc)。 3. 下载CuDNN库文件: - 访问NVIDIA官方网站并下载与安装的CUDA Toolkit版本相对应的CuDNN库文件。 - 将下载的CuDNN库文件拷贝到Jetson TX2设备上。 4. 安装CuDNN库文件: - 将CuDNN库文件解压到一个指定目录中,例如'/usr/local/cuda/'。 - 打开终端,进入CuDNN库文件所在的目录。 - 运行以下命令以将CuDNN库文件拷贝到CUDA Toolkit的安装目录中: ``` sudo cp cuda/include/cudnn.h /usr/local/cuda/include/ sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64/ sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn* ``` 5. 配置环境变量: - 打开终端,编辑~/.bashrc文件: ``` nano ~/.bashrc ``` - 在文件末尾添加以下内容,并保存退出: ``` export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64 export CUDA_HOME=/usr/local/cuda ``` - 运行以下命令使环境变量配置生效: ``` source ~/.bashrc ``` 完成以上步骤后,您应该成功地手动安装了Jetson TX2中的CUDA和CuDNN。您可以通过在终端上运行`nvcc -V`来验证CUDA是否正确安装,并通过运行`cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2`来验证CuDNN是否正确安装。 ### 回答2: 首先,Jetson TX2是一款高性能边缘计算设备,用于深度学习、AI和计算机视觉等领域。CUDA和cuDNN是用于加速计算的关键软件,在Jetson TX2上手动安装这两个软件需要以下步骤: 1. 下载CUDA和cuDNN:首先,从NVIDIA官方网站下载适用于Jetson TX2的CUDA和cuDNN版本。确保选择与Jetson TX2硬件兼容的版本。 2. 安装CUDA:将下载的CUDA安装包复制到Jetson TX2上,并解压缩文件。然后,运行安装脚本来设置CUDA环境变量并安装CUDA。 3. 配置环境变量:为了正确地配置CUDA和cuDNN,需要设置环境变量。在终端中输入以下命令以打开.bashrc文件: ``` sudo nano ~/.bashrc ``` 然后,在文件的末尾添加以下行: ``` export CUDA_HOME=/usr/local/cuda export PATH=/usr/local/cuda/bin:${PATH} export LD_LIBRARY_PATH=/usr/local/cuda/lib64:${LD_LIBRARY_PATH} ``` 保存并关闭文件,然后运行以下命令以使更改生效: ``` source ~/.bashrc ``` 4. 安装cuDNN:将下载的cuDNN安装包复制到Jetson TX2上,并解压缩文件。然后,将cuDNN库文件复制到CUDA的安装目录中。使用以下命令完成此操作: ``` sudo cp cuda/include/cudnn.h /usr/local/cuda/include sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64 sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn* ``` 5. 验证安装:在终端中运行以下命令以验证CUDA和cuDNN是否安装成功: ``` nvcc -V ``` 如果输出中显示了CUDA版本信息,则说明CUDA安装成功。然后,可以使用深度学习框架(如TensorFlow,PyTorch等)来验证cuDNN的安装。 这些是手动安装CUDA和cuDNN的基本步骤。确保按照官方文档和说明进行操作,并根据自己的需求进行相应的配置和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值