文章目录
平台 | os版本 | 内核 |
---|---|---|
MT6765 | Android 9.0 | kernel-4.9 |
Machine
驱动负责处理机器特有的一些控件和音频事件(例如,当播放音频时,需要先行打开一个PA
(即功率放大器);单独的Platform
和Codec
驱动是不能工作的,它必须由Machine
驱动把它们结合在一起才能完成整个设备的音频处理工作。
ASoC
的一切都从Machine
驱动开始,包括声卡的注册,绑定Platform
和Codec
驱动等等。
audio驱动相关结构体 | 注释 |
---|---|
snd_soc_dai_link | 音频链路描述及板级操作函数 |
入口函数所在文件:
./kernel-4.4/sound/soc/mediatek/common_int/mtk-soc-machine.c
module_init(mt_soc_snd_init);
static int __init mt_soc_snd_init(void)
{
int ret;
pr_debug("%s\n", __func__);
... /* 省略部分代码 */
ret = platform_driver_register(&mt_audio_driver);
pr_debug("-%s\n", __func__);
return ret;
}
模块初始化时,在入口函数mt_soc_snd_init
中通过platform_driver_register
注册了一个名字为"mtk-audio"
的平台设备。
/* ASoC platform driver */
#ifdef CONFIG_OF
static const struct of_device_id mt_audio_driver_dt_match[] = {
{
.compatible = "mediatek,audio",
},
{
} };
#endif
static struct platform_driver mt_audio_driver = {
.driver = {
.name = "mtk-audio",
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = mt_audio_driver_dt_match,
#endif
},
.probe = mt_soc_snd_probe,
.remove = mt_soc_snd_remove,
};
当of_match_table
与./kernel-4.9/arch/arm/boot/dts/mt6765.dts
文件中的
audio: audio@11220000 {
compatible = "mediatek,audio", "syscon";
reg = <0 0x11220000 0 0x1000>;
/* interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_LOW>; */
#clock-cells = <1>;
mediatek,btcvsd_snd = <&btcvsd_snd>;
};
compatible
中的字符串匹配成功后,会调用到相应的probe
函数。
/* probes a new socdev */
static int mt_soc_snd_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &mt_snd_soc_card_mt;
struct device_node *btcvsd_node;
int ret;
int daiLinkNum = 0;
/* 更新喇叭对应的 codec dai 名字和 codec 的名字 */
ret = mtk_spk_update_dai_link(mt_soc_extspk_dai, pdev);
if (ret) {
dev_err(&pdev->dev, "%s(), mtk_spk_update_dai_link error\n",
__func__);
return -EINVAL;
}
/* 获取外置的codec_dai的名字 */
get_ext_dai_codec_name();
pr_debug("mt_soc_snd_probe dai_link = %p\n",
mt_snd_soc_card_mt.dai_link);
/* DEAL WITH DAI LINK */
/* 将mt_soc_dai_common结构体中的内容拷贝给mt_soc_dai_component结构体 */
memcpy(mt_soc_dai_component, mt_soc_dai_common,
sizeof(mt_soc_dai_common));
/* 统计mt_soc_dai_common结构体中包含的dai link的数目 */
daiLinkNum += ARRAY_SIZE(mt_soc_dai_common);
#ifdef CONFIG_SND_SOC_MTK_BTCVSD
/* assign btcvsd platform_node */
/* 通过设备树获取btcvsd_node这个节点 */
btcvsd_node = of_parse_phandle(pdev->dev.of_node,
"mediatek,btcvsd_snd", 0);
if (!btcvsd_node) {
dev_err(&pdev->dev, "Property 'btcvsd_snd' missing or invalid\n");
return -EINVAL;
}
/* 将获取的节点保存到mt_soc_btcvsd_dai的platform_of_node 中作为平台节点 */
mt_soc_btcvsd_dai[0].platform_of_node = btcvsd_node;
/* 将mt_soc_btcvsd_dai添加到mt_soc_dai_component结构体中作为最后一个元素 */
memcpy(mt_soc_dai_component + daiLinkNum,
mt_soc_btcvsd_dai, sizeof(mt_soc_btcvsd_dai));
/* 重新统计 daiLinkNum 的数目 */
daiLinkNum += ARRAY_SIZE(mt_soc_btcvsd_dai);
#endif
/* 将mt_soc_exthp_dai添加到mt_soc_dai_component结构体中作为最后一个元素 */
memcpy(mt_soc_dai_component + daiLinkNum, mt_soc_exthp_dai,
sizeof(mt_soc_exthp_dai));
/* 重新统计 daiLinkNum 的数目 */
daiLinkNum += ARRAY_SIZE(mt_soc_exthp_dai);
/* 将mt_soc_extspk_dai添加到mt_soc_dai_component结构体中作为最后一个元素 */
memcpy(mt_soc_dai_component + daiLinkNum, mt_soc_extspk_dai,
sizeof(mt_soc_extspk_dai));
/* 重新统计 daiLinkNum 的数目 */
daiLinkNum += ARRAY_SIZE(mt_soc_extspk_dai);
/************************************************************
* 将已经保存了所有需要的 dai link 的 mt_soc_dai_component 结构体
* 放入 mt_snd_soc_card_mt 结构体的 dai_link 成员变量中
************************************************************/
mt_snd_soc_card_mt.dai_link = mt_soc_dai_component;
/*****************************************************
* 将已经保存了所有需要的 dai link 数量的变量daiLinkNum
* 放入 mt_snd_soc_card_mt 结构体的 num_links 成员变量中
*****************************************************/
mt_snd_soc_card_mt.num_links = daiLinkNum;
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
/* 调用alsa框架的标准函数来注册声卡,这里开始就是ALSA框架的那一套东西了 */
ret = devm_snd_soc_register_card(