dai驱动通常对应cpu的一个或几个I2S/PCM接口,与snd_soc_platform一样,dai驱动也是实现为一个platform driver,
实现一个dai驱动大致可以分为以下几个步骤:

定义一个snd_soc_dai_driver结构的实例;
通过API snd_soc_register_dais,注册snd_soc_dai实例;
实现snd_soc_dai_driver结构中的probe、suspend等回调;
实现snd_soc_dai_driver结构中的snd_soc_dai_ops字段中的回调函数;
struct snd_soc_dai_driver {/* DAI description */const char *name;unsigned int id;int ac97_control;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 */bool compress_dai;/* 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 *);
};
static int __init mtk_dai_stub_init(void)
{int ret;soc_mtk_dai_dev = platform_device_alloc(MT_SOC_DAI_NAME , -1);ret = platform_device_add(soc_mtk_dai_dev);return platform_driver_register(&mtk_dai_stub_driver);
}
/*static struct platform_driver mtk_dai_stub_driver = {//Linux platform driver.probe  = mtk_dai_stub_dev_probe,.remove = mtk_dai_stub_dev_remove,.driver = {.name = MT_SOC_DAI_NAME,.owner = THIS_MODULE,},
};
static struct snd_soc_dai_ops mtk_dai_stub_ops = {.startup    = multimedia_startup,
};
static struct snd_soc_dai_driver mtk_dai_stub_dai[] = {//cpu dai driver{.playback = {.stream_name = MT_SOC_I2SDL1_STREAM_NAME,.rates = SNDRV_PCM_RATE_8000_192000,.formats = SND_SOC_ADV_MT_FMTS,.channels_min = 1,.channels_max = 2,.rate_min = 8000,.rate_max = 192000,},.name = MT_SOC_I2S0DL1_NAME,.ops = &mtk_dai_stub_ops,},......
}
static const struct snd_soc_component_driver mt_dai_component = {//CPU DAI的所属的component driver对象.name       = MT_SOC_DAI_NAME,
};*/
static int mtk_dai_stub_dev_probe(struct platform_device *pdev)
{int rc = 0;pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);if (pdev->dev.of_node)dev_set_name(&pdev->dev, "%s", MT_SOC_DAI_NAME);rc = snd_soc_register_component(&pdev->dev, &mt_dai_component,mtk_dai_stub_dai, ARRAY_SIZE(mtk_dai_stub_dai));return rc;
}
int snd_soc_register_component(struct device *dev,const struct snd_soc_component_driver *cmpnt_drv,struct snd_soc_dai_driver *dai_drv,int num_dai)
{struct snd_soc_component *cmpnt;int ret;cmpnt = kzalloc(sizeof(*cmpnt), GFP_KERNEL);//创建CPU DAI所属的component对象ret = snd_soc_component_initialize(cmpnt, cmpnt_drv, dev);cmpnt->ignore_pmdown_time = true;cmpnt->registered_as_component = true;ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, true);//将CPU DAI保存到component->dai_list链表中snd_soc_component_add(cmpnt);//将component保存到全局对象component_list中return 0;
}

创建CPU DAI所属的component对象

static int snd_soc_component_initialize(struct snd_soc_component *component,const struct snd_soc_component_driver *driver, struct device *dev)
{struct snd_soc_dapm_context *dapm;component->name = fmt_single_name(dev, &component->id);component->dev = dev;component->driver = driver;//保存mt_dai_componentcomponent->probe = component->driver->probe;//component driver对象没有实现probe函数component->remove = component->driver->remove;if (!component->dapm_ptr)component->dapm_ptr = &component->dapm;dapm = component->dapm_ptr;dapm->dev = dev;dapm->component = component;dapm->bias_level = SND_SOC_BIAS_OFF;dapm->idle_bias_off = true;if (driver->seq_notifier)dapm->seq_notifier = snd_soc_component_seq_notifier;if (driver->stream_event)dapm->stream_event = snd_soc_component_stream_event;component->controls = driver->controls;component->num_controls = driver->num_controls;component->dapm_widgets = driver->dapm_widgets;component->num_dapm_widgets = driver->num_dapm_widgets;component->dapm_routes = driver->dapm_routes;component->num_dapm_routes = driver->num_dapm_routes;INIT_LIST_HEAD(&component->dai_list);mutex_init(&component->io_mutex);return 0;
}

将CPU DAI保存到component->dai_list链表中

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;component->dai_drv = dai_drv;component->num_dai = count;for (i = 0; i < count; i++) {dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);if (count == 1 && legacy_dai_naming) {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;}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);}return 0;
}

将component保存到全局对象component_list中

static void snd_soc_component_add(struct snd_soc_component *component)
{mutex_lock(&client_mutex);snd_soc_component_add_unlocked(component);mutex_unlock(&client_mutex);
}
static void snd_soc_component_add_unlocked(struct snd_soc_component *component)
{if (!component->write && !component->read)snd_soc_component_init_regmap(component);list_add(&component->list, &component_list);
}

Android音频驱动-ASOC之CPU DAI相关推荐

  1. Linux/Android 音频驱动从概念到 APP

    这里写自定义目录标题 前言 硬件介绍 Codec 通用结构 ADC 框图 DAC 框图 常用数字接口 其他相关术语 Codec 实际结构 硬件原理图 芯片手册框图 软硬件对应示例 Codec 硬件逻辑 ...

  2. Android 音频驱动分析--A10

    A10+Android4.0 音频驱动(树莓派II 源码) linux-3.0目录 make ARCH=arm menuconfig 进到内核配置界面,可以看到   知道我们的配置项名字,然后进 目录 ...

  3. Android音频驱动学习(一) Audio HAL

    Hal加载过程 加载audio hal需要分三步 1.hw_get_module_by_class :加载hal module 2.audio_hw_device_open:调用audio devic ...

  4. android音频驱动目录,手机录音在哪个文件夹_安卓手机录音保存路径 - 驱动管家...

    安卓手机录音在哪个文件夹?几乎所有的手机都支持录音功能,虽然可以在录音机里面看到录音记录,想要将其拷贝出来却需要费一番心思去寻找,当然,我们也可以换一个思路,利用分享功能让安卓自动拷贝文件上传到指定客 ...

  5. Linux 音频驱动(一) ASoC音频框架简介

    目录 1. ALSA简介 2. ASoC音频驱动构成 3. PCM数据流 4. 数据结构简介 5. ASoC音频驱动注册流程 1. ALSA简介 Native ALSA Application:tin ...

  6. 音频2-ALSA/ASOC音频驱动框架

    计划分成下面8章来详细展开,后面再根据实际情况做调整. 1.基础知识(硬件,音频相关概念) 2.ALSA/ASOC音频驱动框架 3.codec 驱动dapm 相关(kcontrol.widget.ro ...

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

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

  8. Linux 音频驱动(二) ASoC音频驱动之Platform驱动

    目录 1. 简介 2. 源码分析 2.1. CPU DAI 2.1.1. 数据结构struct snd_soc_dai_driver 2.1.2. 注册CPU DAI:snd_soc_register ...

  9. Android音频框架之一 详解audioPolicy流程及HAL驱动加载与配置

    前言 此音频架构梳理笔记.主要是因工作上需要在 Android8.1 以上版本中,增加 snd-aloop 虚拟声卡做前期准备工作, 本篇文章提纲挈领的把音频框架主线梳理清晰,通过这篇文章能够清晰如下 ...

最新文章

  1. 多线程处理缓慢_华为昇腾,AI推理性能超越对手一倍:软件挖掘处理器全部潜力...
  2. AI造假 vs AI打假 终结“猫鼠游戏”不能只靠技术
  3. 学python要考什么证-这十个Python常用库,学习Python的你必须要知道!
  4. mysql5.7审计功能开启_MySQL5.7审计功能windows系统
  5. php 递归函数中静态变量,php递归,静态变量,匿名函数使用
  6. 远程办公:如何招聘有自驱力的员工?
  7. Intel 的 micro-architecture 发展历程
  8. php过滤只匹配中英文字符串
  9. c++小游戏合集(AI)
  10. houseoforange_hitcon_2016(unsortbin attack,fsop)
  11. number of items to replace is not a multiple of replacement length
  12. Git更换关联的远端分支
  13. 使用python编写LDPC编码
  14. FFmpeg视频解码流程详解及demo
  15. 美股互联网IPO集散地,正在成为过去式
  16. 前端UI大全(针对后台管理系统)
  17. 了解maven无法使用Scaner 找不到符号异常 c3p0 聚合 依赖 pom插入编译版本 锁定版本 无法输出结果 乱码 plugins报红 为mave项目配置创参数 Test命令 一些错误和经验
  18. android 6.0默认壁纸,我伙呆!安卓6.0壁纸竟然是这样得来的
  19. org.hibernate.AssertionFailure:collection[......] was not processed by flush()
  20. vins-fusion gps融合相关总结

热门文章

  1. 打印系统开发(24)——WinForm开发(45)——winform打印,自己设置打印纸张大小例如500*800px。应该怎么做呢?
  2. 手把手教你用Python替代Mapinfo更快查找两张表中距离最近的点
  3. 004测试用例(4)
  4. yolov5部署以及训练10种中药材分类数据集
  5. 物联网市场迎来大变局 BAT携手布局MQTT协议意欲何为?
  6. 电商商城之分类实现(重点)
  7. linux 应用程序 键盘,在基于 Web 的 VNC 应用程序中支持多种键盘布局
  8. 2021计算机保研夏令营、预推免英语问答
  9. vue 美团框架_GitHub - bxm0927/vue-meituan: 基于Vue 全家桶 (2.x)制作的美团外卖APP
  10. Stm32CubeMx 通过SPIflash做一个U盘