Android音频驱动-ASOC之CPU DAI
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相关推荐
- Linux/Android 音频驱动从概念到 APP
这里写自定义目录标题 前言 硬件介绍 Codec 通用结构 ADC 框图 DAC 框图 常用数字接口 其他相关术语 Codec 实际结构 硬件原理图 芯片手册框图 软硬件对应示例 Codec 硬件逻辑 ...
- Android 音频驱动分析--A10
A10+Android4.0 音频驱动(树莓派II 源码) linux-3.0目录 make ARCH=arm menuconfig 进到内核配置界面,可以看到 知道我们的配置项名字,然后进 目录 ...
- Android音频驱动学习(一) Audio HAL
Hal加载过程 加载audio hal需要分三步 1.hw_get_module_by_class :加载hal module 2.audio_hw_device_open:调用audio devic ...
- android音频驱动目录,手机录音在哪个文件夹_安卓手机录音保存路径 - 驱动管家...
安卓手机录音在哪个文件夹?几乎所有的手机都支持录音功能,虽然可以在录音机里面看到录音记录,想要将其拷贝出来却需要费一番心思去寻找,当然,我们也可以换一个思路,利用分享功能让安卓自动拷贝文件上传到指定客 ...
- Linux 音频驱动(一) ASoC音频框架简介
目录 1. ALSA简介 2. ASoC音频驱动构成 3. PCM数据流 4. 数据结构简介 5. ASoC音频驱动注册流程 1. ALSA简介 Native ALSA Application:tin ...
- 音频2-ALSA/ASOC音频驱动框架
计划分成下面8章来详细展开,后面再根据实际情况做调整. 1.基础知识(硬件,音频相关概念) 2.ALSA/ASOC音频驱动框架 3.codec 驱动dapm 相关(kcontrol.widget.ro ...
- Linux 音频驱动(四) ASoC音频驱动之Machine驱动
目录 1. 基本介绍 2. 源码分析 2.1. Machine数据结构 struct snd_soc_dai_link 3. 声卡 3.1. 数据结构struct snd_soc_card 3.2. ...
- 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 ...
- Android音频框架之一 详解audioPolicy流程及HAL驱动加载与配置
前言 此音频架构梳理笔记.主要是因工作上需要在 Android8.1 以上版本中,增加 snd-aloop 虚拟声卡做前期准备工作, 本篇文章提纲挈领的把音频框架主线梳理清晰,通过这篇文章能够清晰如下 ...
最新文章
- 多线程处理缓慢_华为昇腾,AI推理性能超越对手一倍:软件挖掘处理器全部潜力...
- AI造假 vs AI打假 终结“猫鼠游戏”不能只靠技术
- 学python要考什么证-这十个Python常用库,学习Python的你必须要知道!
- mysql5.7审计功能开启_MySQL5.7审计功能windows系统
- php 递归函数中静态变量,php递归,静态变量,匿名函数使用
- 远程办公:如何招聘有自驱力的员工?
- Intel 的 micro-architecture 发展历程
- php过滤只匹配中英文字符串
- c++小游戏合集(AI)
- houseoforange_hitcon_2016(unsortbin attack,fsop)
- number of items to replace is not a multiple of replacement length
- Git更换关联的远端分支
- 使用python编写LDPC编码
- FFmpeg视频解码流程详解及demo
- 美股互联网IPO集散地,正在成为过去式
- 前端UI大全(针对后台管理系统)
- 了解maven无法使用Scaner 找不到符号异常 c3p0 聚合 依赖 pom插入编译版本 锁定版本 无法输出结果 乱码 plugins报红 为mave项目配置创参数 Test命令 一些错误和经验
- android 6.0默认壁纸,我伙呆!安卓6.0壁纸竟然是这样得来的
- org.hibernate.AssertionFailure:collection[......] was not processed by flush()
- vins-fusion gps融合相关总结
热门文章
- 打印系统开发(24)——WinForm开发(45)——winform打印,自己设置打印纸张大小例如500*800px。应该怎么做呢?
- 手把手教你用Python替代Mapinfo更快查找两张表中距离最近的点
- 004测试用例(4)
- yolov5部署以及训练10种中药材分类数据集
- 物联网市场迎来大变局 BAT携手布局MQTT协议意欲何为?
- 电商商城之分类实现(重点)
- linux 应用程序 键盘,在基于 Web 的 VNC 应用程序中支持多种键盘布局
- 2021计算机保研夏令营、预推免英语问答
- vue 美团框架_GitHub - bxm0927/vue-meituan: 基于Vue 全家桶 (2.x)制作的美团外卖APP
- Stm32CubeMx 通过SPIflash做一个U盘