一 dai驱动简介

dai驱动用于驱动component上的音频接口,dai驱动通常不会单独存在,dai驱动会与component驱动一起注册。
在注册codec时,就要求提供dai驱动,而platform驱动在编写时也会根据需要,在注册platform驱动的同时调用devm_snd_soc_register_componentsnd_soc_register_dais来为dai驱动单独注册。
这两个函数的差异就是snd_soc_register_dais需要自己创建一个component,而devm_snd_soc_register_component则会自动为dai创建一个单独的component。

dai driver用于管理数字音频接口,所以dai驱动中除了管理接口的函数,还会有各种音频属性,如采样率,位宽等。
dai按方向可以分为playback和capture两种,一个dai driver可以同时有playback和Capture两种接口。

二 dai驱动重要结构体

dai driver有2个重要的结构体struct snd_soc_dai_driver和dai的操作函数struct snd_soc_dai_ops

struct snd_soc_dai_driver {/* DAI description */const char *name;unsigned int id;unsigned int base;/* DAI driver callbacks */int (*probe)(struct snd_soc_dai *dai);int (*remove)(struct snd_soc_dai *dai);int (*suspend)(struct snd_soc_dai *dai);int (*resume)(struct snd_soc_dai *dai);/* compress dai */int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num);/* DAI is also used for the control bus */bool bus_control;/* ops */const struct snd_soc_dai_ops *ops;/* DAI capabilities */struct snd_soc_pcm_stream capture;struct snd_soc_pcm_stream playback;unsigned int symmetric_rates:1;unsigned int symmetric_channels:1;unsigned int symmetric_samplebits:1;/* probe ordering - for components with runtime dependencies */int probe_order;int remove_order;
};struct snd_soc_dai_ops {/** DAI clocking configuration, all optional.* Called by soc_card drivers, normally in their hw_params.*/int (*set_sysclk)(struct snd_soc_dai *dai,int clk_id, unsigned int freq, int dir);int (*set_pll)(struct snd_soc_dai *dai, int pll_id, int source,unsigned int freq_in, unsigned int freq_out);int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);int (*set_bclk_ratio)(struct snd_soc_dai *dai, unsigned int ratio);/** DAI format configuration* Called by soc_card drivers, normally in their hw_params.*/int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);int (*xlate_tdm_slot_mask)(unsigned int slots,unsigned int *tx_mask, unsigned int *rx_mask);int (*set_tdm_slot)(struct snd_soc_dai *dai,unsigned int tx_mask, unsigned int rx_mask,int slots, int slot_width);int (*set_channel_map)(struct snd_soc_dai *dai,unsigned int tx_num, unsigned int *tx_slot,unsigned int rx_num, unsigned int *rx_slot);int (*set_tristate)(struct snd_soc_dai *dai, int tristate);/** DAI digital mute - optional.* Called by soc-core to minimise any pops.*/int (*digital_mute)(struct snd_soc_dai *dai, int mute);int (*mute_stream)(struct snd_soc_dai *dai, int mute, int stream);/** ALSA PCM audio operations - all optional.* Called by soc-core during audio PCM operations.*/int (*startup)(struct snd_pcm_substream *,struct snd_soc_dai *);void (*shutdown)(struct snd_pcm_substream *,struct snd_soc_dai *);int (*hw_params)(struct snd_pcm_substream *,struct snd_pcm_hw_params *, struct snd_soc_dai *);int (*hw_free)(struct snd_pcm_substream *,struct snd_soc_dai *);int (*prepare)(struct snd_pcm_substream *,struct snd_soc_dai *);/** NOTE: Commands passed to the trigger function are not necessarily* compatible with the current state of the dai. For example this* sequence of commands is possible: START STOP STOP.* So do not unconditionally use refcounting functions in the trigger* function, e.g. clk_enable/disable.*/int (*trigger)(struct snd_pcm_substream *, int,struct snd_soc_dai *);int (*bespoke_trigger)(struct snd_pcm_substream *, int,struct snd_soc_dai *);/** For hardware based FIFO caused delay reporting.* Optional.*/snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,struct snd_soc_dai *);
};
  • name:dai的名字,在dai_link中就是依赖这个名字来指定dai接口
  • ops:接口操作函数,如果是I2S接口则是I2S的控制函数,PCM接口则是PCM的控制函数。
  • capture:描述dai接口的录音能力,指定声道数,采样率,位深等
  • playback:描述dai接口的播放能力
  • probe_order:初始化声卡时该component的probe函数调用顺序
  • remove_order:卸载时的顺序

dai的注册过程

dai注册的函数是snd_soc_register_dais

/*** snd_soc_register_dais - Register a DAI with the ASoC core** @component: The component the DAIs are registered for* @dai_drv: DAI driver to use for the DAIs* @count: Number of DAIs* @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the*                     parent's name.*/
static int snd_soc_register_dais(struct snd_soc_component *component,struct snd_soc_dai_driver *dai_drv, size_t count,bool legacy_dai_naming)
{struct device *dev = component->dev;struct snd_soc_dai *dai;unsigned int i;int ret;dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count);component->dai_drv = dai_drv;component->num_dai = count;for (i = 0; i < count; i++) {                                                                //可以一次注册多个daidai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);        //为dai分配内存if (dai == NULL) {ret = -ENOMEM;goto err;}/** Back in the old days when we still had component-less DAIs,* instead of having a static name, component-less DAIs would* inherit the name of the parent device so it is possible to* register multiple instances of the DAI. We still need to keep* the same naming style even though those DAIs are not* component-less anymore.*/if (count == 1 && legacy_dai_naming &&                              //格式化名称(dai_drv[i].id == 0 || dai_drv[i].name == NULL)) {dai->name = fmt_single_name(dev, &dai->id);} else {dai->name = fmt_multiple_name(dev, &dai_drv[i]);if (dai_drv[i].id)dai->id = dai_drv[i].id;elsedai->id = i;}if (dai->name == NULL) {kfree(dai);ret = -ENOMEM;goto err;}dai->component = component;dai->dev = dev;dai->driver = &dai_drv[i];if (!dai->driver->ops)dai->driver->ops = &null_dai_ops;list_add(&dai->list, &component->dai_list);                //把dai挂到component的dai_list链表上去dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);}return 0;err:snd_soc_unregister_dais(component);return ret;
}

dai driver的注册需要一个component,这个component可以是单独的component,也可以是和platform/codec共用

安卓声卡驱动:5.dai驱动相关推荐

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

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

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

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

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

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

  4. beast软件linux用法,声卡驱动设置 - 黑苹果驱动高手篇 MultiBeast用法进阶_Linux教程_Linux公社-Linux系统门户网站...

    声卡驱动设置 Audio自然是声卡驱动设置项,这个选项包括众多板载声卡驱动,选择之前最好仔细阅读描述文件,并选择正确的声卡型号. ▲ Realtek ALC8xx 项(包括ALC8xxHDA和Appl ...

  5. win7(windows7旗舰版)声卡High Definition Audio驱动 (安装失败)解决方法

    win7(windows7旗舰版)声卡High Definition Audio驱动 (安装失败)解决方案 前几天装了一下windows7体验一下,结果声卡驱动安装有问题,这电脑没声音我可没法活啊. ...

  6. 安卓驱动和linux驱动有什么不同

    安卓系统可以认为是定制化的linux系统. 因而安卓驱动就是linux驱动. 相对通常所说linux系统,安卓系统多了安卓专有驱动,多了JAVA虚拟机,JAVA虚拟机,虚拟机上的应用框架和框架之上的应 ...

  7. win7(windows7旗舰版)声卡High Definition Audio驱动(安装失败)解决方案(Thinkpad)

    申精, Definition, 声卡, 旗舰, Audio 你看到我这篇文章时候估计你快被windows7无法安装声卡驱动而崩溃了,呵呵,别急,这篇文章是你的救星,本人已经试验多台电脑,完美解决win ...

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

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

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

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

最新文章

  1. 如何查看Linux系统下程序运行时使用的库?
  2. 详细解读 Prometheus 的指标类型
  3. 处理JSON格式的数据
  4. cs4 php,php dreamweaver cs4
  5. 【性能优化】 之 10053 事件
  6. java实现rtsp转rtmp
  7. python中的参数
  8. Enews博客/CMS/双模式主题源码
  9. 第四篇:决策树分类算法原理分析与代码实现
  10. Template parse errors: The pipe 'translate' could not be found
  11. 程序员辞职回老家山洞写代码,二年敲了 45 万行!
  12. 宏碁掠夺者Predator首款RGB内存条即将发售,特挑三星B-Die颗粒
  13. 使用vba操作工作表,实现报表汇总
  14. 非华为电脑使用华为一碰传破解教程
  15. 微信共享停车场小程序开发设计方案
  16. HTML网页版雷电游戏
  17. p5.js 交互应用实战 —— 音乐可视化(案例)
  18. ClickHouse在工业互联网场景的OLAP平台建设实践
  19. 图论及其应用 2010年期末考试 答案 总结
  20. Screen.SetResolution 设置分辨率

热门文章

  1. python 2017年12月七学习笔记
  2. Springboot整合WebSocket实现网页版聊天,快来围观!
  3. stm32 薄膜键盘原理_6.4 STM32F103ZET独立按键功能深入剖析(神舟III号)
  4. ULua与Unity交互原理
  5. ccproject西西进度计划编制软件最新版11.35发布
  6. 项目管理中,项目干系人的角色和责任
  7. coreldraw2019天气滤镜_cdr2019下载-CorelDRAW2019下载-独木成林
  8. 利用EXCEL提取出生年月(格式自定义)、计算年龄、判断性别
  9. 浅谈系统架构设计-从架构设计原理、架构设计原则、架构设计方法展开
  10. 如何排除网络二层环路