audio驱动之codec和codec_dai

本文介绍了嵌入式设备中audio驱动的codec和codec_dai的作用,包括数字信号与模拟信号的转换、音频通路控制及信号处理。详细解析了驱动代码,涉及codec的注册、初始化以及数据交互过程,阐述了codec_dai在音频设备中的重要角色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平台 os版本 内核
MT6765 Android 9.0 kernel-4.9

在嵌入式设备中,codec的作用可以简单的分为4种:

  1. PCM等信号进行D/A转换,把数字的隐僻信号转换为模拟信号。
  2. micLinein或者其他输入源的模拟信号进行A/D转换,把模拟的声音信号转变为cpu能够处理的数字信号。
  3. 对音频通路进行控制,比如播放音乐,收听调频收音机,或者接听电话的时候,在不同个场景中,音频信号在codec内的流通路线是不一样的
  4. 对音频信号做出相应的处理,例如音量的控制,功率的放大等等。
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
### snd_soc_dai_link 结构体的定义与用法 `snd_soc_dai_link` 是 Linux ALSA ASoC (Advanced SoC Audio Architecture) 中的一个核心结构体,用于描述音频子系统的 DAI(Digital Audio Interface)链路关系。它连接了 Machine 驱动Codec 驱动以及 Platform 驱动之间的交互逻辑。 #### 定义 `snd_soc_dai_link` 的主要功能是配置管理一条具体的音频链路。它的典型定义如下: ```c struct snd_soc_dai_link { const char *name; /* DAI link 名字 */ const char *stream_name; /* 流名称 */ int num_codecs; /* Codec 数量 */ struct device_node *cpus; /* CPU DAI 设备节点 */ struct snd_soc_dai_driver *cpu_dai_drv; struct device_node *codecs; /* Codec DAI 设备节点 */ struct device_node *platforms; /* Platform 设备节点 */ unsigned int formats; /* 支持的 PCM 格式 */ unsigned int dpcm_playback; /* 是否支持 DPCM 播放 */ unsigned int dpcm_capture; /* 是否支持 DPCM 录制 */ }; ``` 上述字段的作用分别解释为: - `name`: 表示该链路的名字,通常用来区分不同的音频路径[^1]。 - `stream_name`: 描述流的具体名字,便于调试日志记录[^2]。 - `num_codecs`: 当前链路上使用的 codec 芯片数量。 - `cpus`, `codecs`, `platforms`: 这些字段指定了对应的设备树节点或者平台数据,表示 CPU、Codec Platform 的绑定关系。 - `formats`: 声明当前链路所支持的音频格式,例如 I2S 或者 DSP 等模式。 - `dpcm_playback/capture`: 控制是否启用动态 PCM 功能,主要用于低功耗场景下的优化。 #### 用法 在实际开发过程中,开发者需要根据硬件设计来填充这个结构体的内容。以下是常见的初始化方式: ```c static struct snd_soc_dai_link my_dai_links[] = { { .name = "My-CPU-DSP", .stream_name = "CPU-DSP Stream", .cpus = of_match_ptr(cpu_dai), .codecs = of_match_ptr(codec_dai), .platforms = of_match_ptr(platform_dev), .num_codecs = 1, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, .dpcm_playback = 1, .dpcm_capture = 1, }, }; ``` 在此例子中: - `.name` 设置为 `"My-CPU-DSP"`,表明这是特定的一条音频链路。 - 使用 `of_match_ptr()` 函数指定设备树中的匹配项,从而实现更灵活的硬件抽象。 - `.formats` 字段声明此链路可以处理 S16LE S24LE 数据格式。 最后,在机器驱动程序中将这些链路传递给声卡对象以便完成注册过程。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值