平台 | os版本 | 内核 |
---|---|---|
MT6765 | Android 9.0 | kernel-4.9 |
在嵌入式设备中,codec
的作用可以简单的分为4种:
- 对
PCM
等信号进行D/A
转换,把数字的隐僻信号转换为模拟信号。 - 对
mic
、Linein
或者其他输入源的模拟信号进行A/D
转换,把模拟的声音信号转变为cpu
能够处理的数字信号。 - 对音频通路进行控制,比如播放音乐,收听调频收音机,或者接听电话的时候,在不同个场景中,音频信号在
codec
内的流通路线是不一样的 - 对音频信号做出相应的处理,例如音量的控制,功率的放大等等。
audio驱动相关结构体 | 注释 |
---|---|
snd_soc_codec_driver | 音频编解码芯片描述及操作函数,如控件/微件/音频路由的描述信息、时钟配置、IO 控制等 |
snd_soc_dai_driver | 这个结构体用来表示能够传输哪些格式的音频数据,并且提供了设置这些格式的函数 |
./kernel-4.9/sound/soc/mediatek/codec/mt6357/mtk-soc-codec-6357.c
module_init(mtk_mt6357_codec_init);
static int __init mtk_mt6357_codec_init(void)
{
pr_debug("%s:\n", __func__);
... /* 省略部分非关键代码 */
InitGlobalVarDefault();
/* 注册codec的平台驱动 */
return platform_driver_register(&mtk_codec_6357_driver);
}
#ifdef CONFIG_OF
static const struct of_device_id mt_soc_codec_63xx_of_ids[] = {
{
.compatible = "mediatek,mt_soc_codec_63xx",},
{
}
};
#endif
static struct platform_driver mtk_codec_6357_driver = {
.driver = {
.name = MT_SOC_CODEC_NAME,
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = mt_soc_codec_63xx_of_ids,
#endif
},
.probe = mtk_mt6357_codec_dev_probe,
.remove = mtk_mt6357_codec_dev_remove,
}
当of_match_table
与./kernel-4.9/arch/arm/boot/dts/mt6765.dts
文件中的
mt_soc_codec_name {
compatible = "mediatek,mt_soc_codec_63xx";
use_hp_depop_flow = <0>; /* select 1: use, 0: not use */
use_ul_260k = <0>; /* select 1: use, 0: not use */
};
compatible
中的字符串匹配成功后,会调用到相应的probe
函数。
函数所在文件:
./kernel-4.9/sound/soc/mediatek/codec/mt6357/mtk-soc-codec-6357.c
static int mtk_mt6357_codec_dev_probe(struct platform_device *pdev)
{
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
if (pdev->dev.dma_mask == NULL)
pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
if (pdev->dev.of_node) {
/* #define MT_SOC_CODEC_NAME "mt-soc-codec" */
/* 设置设备的名字 */
dev_set_name(&pdev->dev, "%s", MT_SOC_CODEC_NAME);
/* check if use hp depop flow */
of_property_read_u32(pdev->dev.of_node,
"use_hp_depop_flow",
&mUseHpDepopFlow);
pr_debug("%s(), use_hp_depop_flow = %d\n",
__func__, mUseHpDepopFlow);
} else {
pr_debug("%s(), pdev->dev.of_node = NULL!!!\n", __func__);
}
pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
/* 注册asoc框架中的codec驱动 */
return snd_soc_register_codec(&pdev->dev,
&soc_mtk_codec, mtk_6357_dai_codecs,
ARRAY_SIZE(mtk_6357_dai_codecs));
}
先分析注册的结构体soc_mtk_codec
,再分析用来注册的函数snd_soc_register_codec
结构体所在文件:
./kernel-4.9/sound/soc/mediatek/codec/mt6357/mtk-soc-codec-6357.c
static struct snd_soc_codec_driver soc_mtk_codec = {
.probe = mt6357_codec_probe,
.remove = mt6357_codec_remove,
.read = mt6357_read,
.write = mt6357_write,
};
函数所在文件:
./kernel-4.9/sound/soc/mediatek/codec/mt6357/mtk-soc-codec-6357.c
static int mt6357_codec_probe(struct snd_soc_codec *codec)
{
int ret;
pr_debug("%s()\n", __func__);
if (mInitCodec == true)
return 0;
/* add codec controls */
snd_soc_add_codec_controls(codec, mt6357_snd_controls,
ARRAY_SIZE(mt6357_snd_controls));
snd_soc_add_codec_controls(codec, mt6357_UL_Codec_controls,
ARRAY_SIZE