08.音频系统:第003课_Linux音频驱动程序:第003节_RK3399声卡驱动移植_combine

该小节我们讲解一下开发板RK3399声卡rt5651的移植,主要分为4个部分,platfrom,codec,machine,dts(设备树)。
首先我们从设备树开始讲起,当然在讲解之前,我们先来体验下声卡的效果,第一种方法,就不多说了,直操作系统的录音软件。
第二中方法是通过命令录音,播音:
录音(tinycap):
用法:
tinycap file.wav [-D card] [-d device] [-c channels] [-r rate] [-b bits] [-pperiod_size] [-n n_periods]
示例:
tinycap /sdcard/rec.wav -D 0 -d 0 –c 2 –r 44100 –b 16 –p 1024–n 3
播音(tinyplay):
用法: tinyplay file.wav [-D card] [-d device] [-p period_size] [-n n_periods]
示例:tinyplay /sdcard/test44.wav -D 0 -d 0 -p 1024 -n 3
Playing sample: 2 ch, 44100 hz, 32 bit

通过以上两个命令就是实现播放或者录制声音了,下面我们先来看看设备树。

设备树

在rk3399-excavator-sapphire.dtsi文件中:

	rt5651-sound {
		status = "okay";
		compatible = "simple-audio-card";
		/*指定声卡传输数据格式,是通过"i2s"*/
		simple-audio-card,format = "i2s";
		/*声卡的名字为realtek,rt5651-codec,可以通过*/
		simple-audio-card,name = "realtek,rt5651-codec";
		/*猜测是混合声音的时钟信号*/
		simple-audio-card,mclk-fs = <256>;
		/*声音的部件,麦克风,耳机等等*/
		simple-audio-card,widgets =
			"Microphone", "Mic Jack",
			"Headphone", "Headphone Jack";
		/*/*声音的部件,第一个指定的是接收器,第二个指定的是接收员*/*/
		simple-audio-card,routing =
			"Mic Jack", "MICBIAS1",
			"IN1P", "Mic Jack",
			"Headphone Jack", "HPOL",
			"Headphone Jack", "HPOR";
		/*根据我们的原理图,可以知道,传输数据的i2s为i2s0*/
		simple-audio-card,cpu {
			sound-dai = <&i2s0>;
		};
		/*rt5651为我们编码器的节点*/
		simple-audio-card,codec {
			sound-dai = <&rt5651>;
		};
	};
&i2c1 {
	status = "okay";
	i2c-scl-rising-time-ns = <300>;
	i2c-scl-falling-time-ns = <15>;
	/*编码器节点*/
	rt5651: rt5651@1a {
		status = "okay";
		#sound-dai-cells = <0>;
		compatible = "rockchip,rt5651";
		reg = <0x1a>;
		clocks = <&cru SCLK_I2S_8CH_OUT>;
		clock-names = "mclk";
		pinctrl-names = "default";
		pinctrl-0 = <&i2s_8ch_mclk>;
		/*扬声器使能引脚*/
		spk-con-gpio = <&gpio0 11 GPIO_ACTIVE_HIGH>;
		/*监测是否有耳机插入*/
		hp-det-gpio = <&gpio4 28 GPIO_ACTIVE_LOW>;
	};
};

想要详simple-audio-card设备相关的知识,可以查看源码中的simple-card.c文档,其实使用ASoC音频驱动框架有两种设备树的写法,我们的开发板使用的是第一种写法。至于为什么选择第一种,有兴趣的通知可以深入的了解一下(一般来说有多个编码器即codec才会使用第二种方法)。
首先我们看到是rt5651-sound节点,系统会根据该节点去创建一个声卡,即/dev/snd下的节点。通过
cat /proc/asound/cards
指令我们可以查看我们所有的声卡
在这里插入图片描述
可以知道,虽然只有一个编码器,但是却出现了3个声卡。具体细节后续为大家讲解。下面我们讲解一下codec。

codec

我们的开发板,对应的编码器codec驱动文件为rt5651.c文件,我们从入口函数开始:

static const struct snd_soc_dai_ops rt5651_aif_dai_ops = {
	.hw_params = rt5651_hw_params,
	.set_fmt = rt5651_set_dai_fmt,
	.set_sysclk = rt5651_set_dai_sysclk,
	.set_pll = rt5651_set_dai_pll,
};

static struct snd_soc_dai_driver rt5651_dai[] = {
	{
		.name = "rt5651-aif1",
		.id = RT5651_AIF1,
		.playback = {
			.stream_name = "AIF1 Playback",
			.channels_min = 1,
			.channels_max = 2,
			.rates = RT5651_STEREO_RATES,
			.formats = RT5651_FORMATS,
		},
		.capture = {
			.stream_name = "AIF1 Capture",
			.channels_min = 1,
			.channels_max = 2,
			.rates = RT5651_STEREO_RATES,
			.formats = RT5651_FORMATS,
		},
		.ops = &rt5651_aif_dai_ops,
	},
	{
		.name = "rt5651-aif2",
		.id = RT5651_AIF2,
		.playback = {
			.stream_name = "AIF2 Playback",
			.channels_min = 1,
			.channels_max = 2,
			.rates = RT5651_STEREO_RATES,
			.formats = RT5651_FORMATS,
		},
		.capture = {
			.stream_name = "AIF2 Capture",
			.channels_min = 1,
			.channels_max = 2,
			.rates = RT5651_STEREO_RATES,
			.formats = RT5651_FORMATS,
		},
		.ops = &rt5651_aif_dai_ops,
	},
};

static struct snd_soc_codec_driver soc_codec_dev_rt5651 = {
	.probe = rt5651_probe,
	.suspend = rt5651_suspend,
	.resume = rt5651_resume,
	.set_bias_level = rt5651_set_bias_level,
	.idle_bias_off = true,
	.controls = rt5651_snd_controls,
	.num_controls = ARRAY_SIZE(rt5651_snd_controls),
	.dapm_widgets = rt5651_dapm_widgets,
	.num_dapm_widgets = ARRAY_SIZE(rt5651_dapm_widgets),
	.dapm_routes = rt5651_dapm_routes,
	.num_dapm_routes = ARRAY_SIZE(rt5651_dapm_routes),
};
static int rt5651_i2c_probe(struct i2c_client *i2c,const struct i2c_device_id *id)
	snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5651,rt5651_dai, ARRAY_SIZE(rt5651_dai));

其实,编写一个codec启动我们只要实现snd_soc_dai_driver,snd_soc_codec_driver这两个结构体,然代用snd_soc_register_codec进行注册即可。下面我们看看platform。

platform

machine

在上小节我们分析的rockchip-rt5651-tc358749x.c文件,是没有执行的,那么他的machine是怎么实现的呢?如下匹配到设备树compatible = “simple-audio-card”

/*匹配到设备树compatible = "simple-audio-card";之后执行该函数*/
static int asoc_simple_card_probe(struct platform_device *pdev)
	/*判断有几个"simple-audio-card,dai-link"属性,前面提到有两个方法,如果没有改属性,则为第一种方法,存在"simple-audio-card,dai-link"节点为第二种方法*/
	if (np && of_get_child_by_name(np, "simple-audio-card,dai-link"))
	ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card);
		ret = snd_soc_register_card(card);
			/*在该函数内,会做很多工作,如绑定dai等等*/
			ret = snd_soc_instantiate_card(card);
				/*绑定完成之后创建一个声卡,此时没有生成设备节点*/
				ret = snd_card_new(card->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,card->owner, 0, &card->snd_card);
				/*调用snd_card_register注册之后,生成设备节点*/
				ret = snd_card_register(card->snd_card);

是不是特别的熟悉,回到了我们之前上小节的machine,这样我们就能通过设备树去配置machine了。
平台的代码就不进行粘贴复制了,在后续的小节,如果时间充裕,会为大家详细讲解。

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江南才尽,年少无知!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值