一 codec驱动简介

硬件上的Audio codec是一种能够对数字数据流进行编码或解码的设备。
codec的功能非常多,常见的有

  • 数模转换,解码时把数字信息解码成原本的模拟信号,编码时把模拟信号转为数字信号
  • 音频处理,EQ,混音,降噪等
  • 通路控制,控制输出通路接通

二 codec驱动重要结构体

和platform几乎一样,codec注册时也是需要提供一个driver结构体

/* codec driver */
struct snd_soc_codec_driver {/* driver ops */int (*probe)(struct snd_soc_codec *);int (*remove)(struct snd_soc_codec *);int (*suspend)(struct snd_soc_codec *);int (*resume)(struct snd_soc_codec *);struct snd_soc_component_driver component_driver;/* Default control and setup, added after probe() is run */const struct snd_kcontrol_new *controls;int num_controls;const struct snd_soc_dapm_widget *dapm_widgets;int num_dapm_widgets;const struct snd_soc_dapm_route *dapm_routes;int num_dapm_routes;/* codec wide operations */int (*set_sysclk)(struct snd_soc_codec *codec,int clk_id, int source, unsigned int freq, int dir);int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source,unsigned int freq_in, unsigned int freq_out);/* codec IO */struct regmap *(*get_regmap)(struct device *);unsigned int (*read)(struct snd_soc_codec *, unsigned int);int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);unsigned int reg_cache_size;short reg_cache_step;short reg_word_size;const void *reg_cache_default;/* codec bias level */int (*set_bias_level)(struct snd_soc_codec *,enum snd_soc_bias_level level);bool idle_bias_off;bool suspend_bias_off;void (*seq_notifier)(struct snd_soc_dapm_context *,enum snd_soc_dapm_type, int);bool ignore_pmdown_time;  /* Doesn't benefit from pmdown delay */
};

snd_soc_platform_driver差异还是很大的,由于codec driver只是接受cpu dai发过来的数据,不需要创建pcm设备所以没有pcm相关的函数。
同时相比platform驱动,多了controls,widgets,route这些成员,这些成员是用来做通路控制以及直接控制codec硬件寄存器的。
还有一些就是寄存器相关的成员,因为codec大多是通过I2C/SPI外挂,所以需要有封装具体的操作函数

  • controls:用于创建一些control控件,这些控件可以暴露给应用层,让应用层可以控制codec的行为
  • dapm_widgets:dapm的widget,用于封装control,用于实现自动上电下电
  • dapm_routes:dapm的route,用于将dapm widget联系起来组成一条条dapm链路
  • regmap:用I2C/SPI这种标准接口连接的codec可以将寄存器映射到虚拟内存上,访问起来比较简单

注册codec时,除了提供struct snd_soc_codec_driver结构体外,还需要提供struct snd_soc_dai_driver结构体。
platform驱动在注册时是不需要提供snd_soc_dai_driver的,但是codec驱动必须要,因为codec驱动的结构体snd_soc_codec_driver中只提供了对codec进行控制的读写函数,所以codec的音频数据相关的功能是强制放在dai driver的。

三 codec driver注册过程

要注册codec,我们需要提供两个结构体,struct snd_soc_codec_driver,以及snd_soc_dai_driver,其中snd_soc_codec_driver用来描述codec本身的属性,snd_soc_dai_driver则描述codec的dai接口的属性。
以s5pv4418开发板上的es8316举例

static struct snd_soc_dai_driver es8316_dai = {.name = "ES8316 HiFi",.playback = {.stream_name = "Playback",.channels_min = 1,.channels_max = 2,.rates = es8316_RATES,.formats = es8316_FORMATS,},.capture = {.stream_name = "Capture",.channels_min = 1,.channels_max = 2,.rates = es8316_RATES,.formats = es8316_FORMATS,},.ops = &es8316_ops,.symmetric_rates = 1,
};static struct snd_soc_codec_driver soc_codec_dev_es8316 = {.read  = es8316_read_reg_cache,.write = es8316_write,.probe = es8316_probe,.remove = es8316_remove,.suspend = es8316_suspend,.resume = es8316_resume,.set_bias_level = es8316_set_bias_level,.reg_cache_size = ARRAY_SIZE(es8316_reg),.reg_word_size = sizeof(u16),
};

随后就可以直接调用codec注册函数进行注册

ret = snd_soc_register_codec(&spi->dev,&soc_codec_dev_es8316, &es8316_dai, 1);

这个函数定义如下

int snd_soc_register_codec(struct device *dev,const struct snd_soc_codec_driver *codec_drv,struct snd_soc_dai_driver *dai_drv,int num_dai)
{struct snd_soc_dapm_context *dapm;struct snd_soc_codec *codec;struct snd_soc_dai *dai;int ret, i;dev_dbg(dev, "codec register %s\n", dev_name(dev));codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);if (codec == NULL)return -ENOMEM;codec->component.codec = codec;ret = snd_soc_component_initialize(&codec->component,               //创建一个component实例&codec_drv->component_driver, dev);if (ret)goto err_free;if (codec_drv->controls) {                                                                  //处理controlcodec->component.controls = codec_drv->controls;codec->component.num_controls = codec_drv->num_controls;}if (codec_drv->dapm_widgets) {                                                         //处理dapmcodec->component.dapm_widgets = codec_drv->dapm_widgets;codec->component.num_dapm_widgets = codec_drv->num_dapm_widgets;}if (codec_drv->dapm_routes) {codec->component.dapm_routes = codec_drv->dapm_routes;codec->component.num_dapm_routes = codec_drv->num_dapm_routes;}if (codec_drv->probe)codec->component.probe = snd_soc_codec_drv_probe;if (codec_drv->remove)codec->component.remove = snd_soc_codec_drv_remove;if (codec_drv->write)codec->component.write = snd_soc_codec_drv_write;if (codec_drv->read)codec->component.read = snd_soc_codec_drv_read;codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time;dapm = snd_soc_codec_get_dapm(codec);dapm->idle_bias_off = codec_drv->idle_bias_off;dapm->suspend_bias_off = codec_drv->suspend_bias_off;if (codec_drv->seq_notifier)dapm->seq_notifier = codec_drv->seq_notifier;if (codec_drv->set_bias_level)dapm->set_bias_level = snd_soc_codec_set_bias_level;codec->dev = dev;codec->driver = codec_drv;codec->component.val_bytes = codec_drv->reg_word_size;#ifdef CONFIG_DEBUG_FScodec->component.init_debugfs = soc_init_codec_debugfs;codec->component.debugfs_prefix = "codec";
#endifif (codec_drv->get_regmap)codec->component.regmap = codec_drv->get_regmap(dev);for (i = 0; i < num_dai; i++) {fixup_codec_formats(&dai_drv[i].playback);fixup_codec_formats(&dai_drv[i].capture);}ret = snd_soc_register_dais(&codec->component, dai_drv, num_dai, false);    //注册daiif (ret < 0) {dev_err(dev, "ASoC: Failed to register DAIs: %d\n", ret);goto err_cleanup;}list_for_each_entry(dai, &codec->component.dai_list, list)dai->codec = codec;mutex_lock(&client_mutex);snd_soc_component_add_unlocked(&codec->component);list_add(&codec->list, &codec_list);mutex_unlock(&client_mutex);dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n",codec->component.name);return 0;err_cleanup:snd_soc_component_cleanup(&codec->component);
err_free:kfree(codec);return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_register_codec);

codec的注册函数其实和platform的注册函数基本一样,也是创建一个component,然后把driver的变量拿过去,区别是codec的注册函数多了对cotroldapm,以及dai的处理。
在注册的最后,把codec挂到全局链表codec_list上。

codec也是以component的形式挂在声卡上的,也是在声卡初始化时进行初始化。

安卓声卡驱动:4.codec驱动相关推荐

  1. Linux 音频驱动(三) ASoC音频驱动之Codec驱动

    目录 1. 简介 2. 源码分析 2.1. Codec 2.1.1. 数据结构struct snd_soc_codec_driver 2.1.2. 注册Codec 2.2. Codec DAI 2.2 ...

  2. 安卓声卡驱动:1.ALSA简介

    一 概述 安卓内核采用的是Linux内核,所以安卓也沿用了Linux内核内置的音频子系统. Linux内核的音频子系统全称是Advanced Linux Sound Architecture,简称AL ...

  3. linux音频驱动修复工具,Linux声卡驱动(4)——音频驱动实战

    一.应用测试工具的使用 1.在external/tinyalsa下有以C语言实现的alsa的测试程序,编译后生成tinypcminfo tinyplay tinycap tinymix 四个elf格式 ...

  4. linux驱动:音频驱动(二)ASoc

    五.[ASoC声卡驱动框架] 1.ASoC将嵌入式设备的音频系统从软件层面划分为3个组件 1.1 codec驱动:音频编解码器驱动,与平台无关,实现音频控制项添加.音频接口实现.DAPM(动态音频电源 ...

  5. Linux 音频驱动(四) ASoC音频驱动之Machine驱动

    目录 1. 基本介绍 2. 源码分析 2.1. Machine数据结构 struct snd_soc_dai_link 3. 声卡 3.1. 数据结构struct snd_soc_card 3.2. ...

  6. 安卓声卡驱动:2.Machine驱动与声卡

    一 声卡简介 一个音频系统由硬件和驱动这些硬件的软件组成. 在一台设备上,如果硬件完整,且驱动硬件的软件全部初始化成功后,ALSA系统就会注册一个声卡,通过这个声卡,应用程序可以控制硬件设备的链路联通 ...

  7. 安卓声卡驱动:3.platform驱动

    一 platform驱动简介 按我的理解platform驱动在ALSA里面起管理FE的作用. 什么是FE,FE即Front End,与FE相对应的另一个名词时叫BE,即Back End. 通常认为音频 ...

  8. 安卓声卡驱动:5.dai驱动

    一 dai驱动简介 dai驱动用于驱动component上的音频接口,dai驱动通常不会单独存在,dai驱动会与component驱动一起注册. 在注册codec时,就要求提供dai驱动,而platf ...

  9. audio驱动之codec和codec_dai

    平台 os版本 内核 MT6765 Android 9.0 kernel-4.9 在嵌入式设备中,codec的作用可以简单的分为4种: 对PCM等信号进行D/A转换,把数字的隐僻信号转换为模拟信号. ...

最新文章

  1. Sklearn 损失函数如何应用到_Sklearn全复习(下)(持续更新)
  2. 解压缩文件命令linux
  3. iview weapp icon组件自定义图标 小程序
  4. shell -nginx启动脚本
  5. 三十五岁后,如何自学WEB前端编程
  6. PyTorch 1.0 中文文档:torch.distributed
  7. 安卓DialogFragment如何使用?
  8. Net窗体程序设计总结
  9. 运维系统分析工具ss,htop,dstat
  10. UFLDL机器学习 Andrew Ng-Deep Learning课程
  11. git 查看修改明细_Git(查看修改记录)
  12. SIR模型的应用 - Influence maximization in social networks based on TOPSIS(3)
  13. WSO2 ESB 5.0.0 配置 MySQL 数据源
  14. 项目合同管理 试题分析
  15. 声源级、接收电压灵敏度(接收带内响应)
  16. TANGENT_SPACE_ROTATION的解释
  17. win7声音小图标不见了,如何修复
  18. 探索 TDengine在《图码联侦》项目中的应用可行性及实践研究
  19. matlab移相法实现单边带调制,根据Matlab 单边带体系仿真研讨
  20. 嵌入式算法移植优化学习笔记5——CPU,GPU,TPU,NPU都是什么

热门文章

  1. [日语二级词汇]动词(7)
  2. 记录一次实现网盘间文件同步工具
  3. Smart Link相关学习
  4. 什么是长尾关键词567
  5. 课程设计:迷宫问题的求解
  6. 像用chrome一样,用Win10资源管理器(增加标签页)
  7. 宁波大学c语言理论考试试题科目一,科目一的理论考试试题及答案
  8. linux gnu grub,GNU GRUB命令的使用方法与GNU GRUB详细介绍
  9. Windows系统灵活使用自带的CMD控制台
  10. 第15讲 布尔函数标准型及化简