ALSA声卡驱动:

1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介

2.Linux ALSA声卡驱动之二:Platform

3. Linux ALSA声卡驱动之三:Platform之Cpu_dai

4. Linux ALSA声卡驱动之四:Codec 以及Codec_dai

5.Linux ALSA声卡驱动之五:Machine 以及ALSA声卡的注册

6.Linux ALSA声卡驱动之六:PCM的注册流程

7.Linux ALSA声卡驱动之七:录音(Capture) 调用流程

1.Platform驱动在ASoC中的作用

ASoC被分为Machine,Platform和Codec三大部件,Platform驱动的主要作用是完成音频数据的管理,最终通过CPU的数字音频接口(DAI)把音频数据传送给Codec进行处理,最终由Codec输出驱动耳机或者是喇叭的音信信号。在具体实现上,ASoC有把Platform驱动分为两个部分:snd_soc_platform_driver和snd_soc_dai_driver。其中,platform_driver负责管理音频数据,把音频数据通过dma或其他操作传送至cpu dai中,dai_driver则主要完成cpu一侧的dai的参数配置,同时也会通过一定的途径把必要的dma等参数与snd_soc_platform_driver进行交互

2.snd_soc_register_platform注册

  • snd_soc_register_platform时序图

  • snd_soc_register_platform相关的结构体关系图

2.2分析snd_soc_register_platform的执行流程和相关结构体

2.2.1   mtk-soc-pcm-capture.c      mtk_capture_probe函数  

static int mtk_capture_probe(struct platform_device *pdev)
{pr_warn("mtk_capture_probe\n");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)dev_set_name(&pdev->dev, "%s", MT_SOC_UL1_PCM);pr_warn("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
//platform的驱动注册return snd_soc_register_platform(&pdev->dev,&mtk_soc_platform);
}
  • struct device结构体
struct platform_device {const char   *name; //  平台设备的名字int       id;//   ID 是用来区分如果设备名字相同的时候(通过在后面添加一个数字来代表不同的设备,因为有时候有这种需求)bool      id_auto;struct device   dev;//   内置的device结构体u32        num_resources;//   资源结构体数量struct resource   *resource;const struct platform_device_id   *id_entry; //用来进行与设备驱动匹配用的id_table表char *driver_override; /* Driver name to force a match *//* MFD cell pointer */struct mfd_cell *mfd_cell;/* arch specific additions */struct pdev_archdata   archdata;
};
static struct snd_soc_platform_driver mtk_soc_platform = {.ops        = &mtk_afe_capture_ops,.probe      = mtk_afe_capture_probe,
};//驱动层的open close  ioctl 相关方法的具体实现
static struct snd_pcm_ops mtk_afe_capture_ops = {.open =     mtk_capture_pcm_open, //上层pcm_open  最终会调用这个函数.close =    mtk_capture_pcm_close,.ioctl =    snd_pcm_lib_ioctl,.hw_params =    mtk_capture_pcm_hw_params,.hw_free =  mtk_capture_pcm_hw_free,.prepare =  mtk_capture_pcm_prepare,.trigger =  mtk_capture_pcm_trigger,.pointer =  mtk_capture_pcm_pointer,.copy =     mtk_capture_pcm_copy,.silence =  mtk_capture_pcm_silence,.page =     mtk_capture_pcm_page,.mmap =     mtk_pcm_mmap,
};

2.2.2  snd_soc_register_platform函数

int snd_soc_register_platform(struct device *dev,const struct snd_soc_platform_driver *platform_drv)
{struct snd_soc_platform *platform;int ret;dev_dbg(dev, "ASoC: platform register %s\n", dev_name(dev));platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);//申请内存if (platform == NULL)return -ENOMEM;ret = snd_soc_add_platform(dev, platform, platform_drv);if (ret)kfree(platform);return ret;
}

 2.2.3  snd_soc_add_platform 函数做了如下事情:

               1.初始化platform->component和platform结构体:platform_drv和dev的值赋值给platform->component
              2.把platform->component添加到component_list,利用platform->list   把之前初始化完成的platform   添加到全局变量platform_list中,以供soc_bind_dai_link使用。

    


int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,const struct snd_soc_platform_driver *platform_drv)
{int ret;//初始化platform->componentret = snd_soc_component_initialize(&platform->component,&platform_drv->component_driver, dev);if (ret)return ret;platform->dev = dev;//snd_soc_platform 与device关联platform->driver = platform_drv;if (platform_drv->probe)platform->component.probe = snd_soc_platform_drv_probe;//与platform_drv->probe 的一样if (platform_drv->remove)platform->component.remove = snd_soc_platform_drv_remove;#ifdef CONFIG_DEBUG_FSplatform->component.debugfs_prefix = "platform";
#endifmutex_lock(&client_mutex);
//通过list_add(&component->list, &component_list)把platform->component添加到component_listsnd_soc_component_add_unlocked(&platform->component);list_add(&platform->list, &platform_list);//把platform加到platform_list列队中mutex_unlock(&client_mutex);dev_dbg(dev, "ASoC: Registered platform '%s'\n",platform->component.name);return 0;
}
static void snd_soc_component_add_unlocked(struct snd_soc_component *component)
{if (!component->write && !component->read) {if (!component->regmap)component->regmap = dev_get_regmap(component->dev, NULL);if (component->regmap)snd_soc_component_setup_regmap(component);}list_add(&component->list, &component_list);INIT_LIST_HEAD(&component->dobj_list);
}
  • snd_soc_component结构体

//当底层驱动注册platform、codec+codec dai、cpu dai时, 核心层都会创建一个对应的snd_soc_component,并且会挂到component_list 链表中
struct snd_soc_component {const char *name;  //这个跟device_driver->name 和snd_soc_component_driver->id有关,int id;const char *name_prefix;struct device *dev;struct snd_soc_card *card;unsigned int active;unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */unsigned int registered_as_component:1;//在snd_soc_register_component时修改为1struct list_head list;//用于把自己挂载到全局链表component_list下 ,component_list 实在soc-core 中保持的全局变量struct snd_soc_dai_driver *dai_drv;//dai  有可能是cpu dai 也有可能是 codec dai  是一个数组int num_dai;//dai 的数量const struct snd_soc_component_driver *driver;//指向下属的snd_soc_component_driver, 该结构体一般由底层平台驱动实现struct list_head dai_list;//链表头, 挂接snd_soc_dai->list   list_add(&dai->list, &component->dai_list)int (*read)(struct snd_soc_component *, unsigned int, unsigned int *);int (*write)(struct snd_soc_component *, unsigned int, unsigned int);struct regmap *regmap;int val_bytes;struct mutex io_mutex;/* attached dynamic objects */struct list_head dobj_list;#ifdef CONFIG_DEBUG_FSstruct dentry *debugfs_root;
#endif/** DO NOT use any of the fields below in drivers, they are temporary and* are going to be removed again soon. If you use them in driver code the* driver will be marked as BROKEN when these fields are removed.*//* Don't use these, use snd_soc_component_get_dapm() */struct snd_soc_dapm_context dapm;const struct snd_kcontrol_new *controls;unsigned int num_controls;const struct snd_soc_dapm_widget *dapm_widgets;unsigned int num_dapm_widgets;const struct snd_soc_dapm_route *dapm_routes;unsigned int num_dapm_routes;struct snd_soc_codec *codec;int (*probe)(struct snd_soc_component *);void (*remove)(struct snd_soc_component *);#ifdef CONFIG_DEBUG_FSvoid (*init_debugfs)(struct snd_soc_component *component);const char *debugfs_prefix;
#endif
};
  • snd_soc_platform结构体
struct snd_soc_platform {struct device *dev;const struct snd_soc_platform_driver *driver;struct list_head list;//添加到全局变量platform_liststruct snd_soc_component component;
};

总结:结合上面的时序图和结构体关系图,snd_soc_register_platform  把mtk_soc_platform和pdev->dev 的值赋值给snd_soc_platform(platform)和snd_soc_component(platform->component) 。并且通过list_add(&platform->list, &platform_list)  和list_add(&component->list, &component_list)把platform添加到platform_list全局链表中,platform->component添加到component_list全局链表。这两个全局链表在函数soc_bind_dai_link中被调用,soc_bind_dai_link是绑定cpu_dai 、codec_dai 、codec、platform。具体实现看machine章节

Linux ALSA声卡驱动之二:Platform相关推荐

  1. Linux ALSA声卡驱动之三:Platform之Cpu_dai

    ALSA声卡驱动: 1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介 2.Linux ALSA声卡驱动之二:Platform 3. Linux ALSA声卡驱动之三:Platf ...

  2. Linux ALSA声卡驱动之四:Codec 以及Codec_dai

    ALSA声卡驱动: 1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介 2.Linux ALSA声卡驱动之二:Platform 3. Linux ALSA声卡驱动之三:Platf ...

  3. Linux ALSA声卡驱动之五:Machine 以及ALSA声卡的注册

    ALSA声卡驱动: 1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介 2.Linux ALSA声卡驱动之二:Platform 3. Linux ALSA声卡驱动之三:Platf ...

  4. Linux ALSA声卡驱动之七:录音(Capture) 调用流程

    ALSA声卡驱动: 1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介 2.Linux ALSA声卡驱动之二:Platform 3. Linux ALSA声卡驱动之三:Platf ...

  5. Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介

    ALSA声卡驱动: 1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介 2.Linux ALSA声卡驱动之二:Platform 3. Linux ALSA声卡驱动之三:Platf ...

  6. Linux ALSA声卡驱动之八:ASoC架构中的Platform

    1.  Platform驱动在ASoC中的作用 前面几章内容已经说过,ASoC被分为Machine,Platform和Codec三大部件,Platform驱动的主要作用是完成音频数据的管理,最终通过C ...

  7. linux alsa声卡驱动原理分析- 设备打开过程和数据流程,linux alsa声卡驱动原理分析解析- 设备打开过程跟数据流程资料.ppt...

    linux alsa声卡驱动原理分析解析- 设备打开过程跟数据流程资料 Linux ALSA声卡驱动原理分析 -设备打开过程和数据流程;目 录;目 录;一.导 读;目 录;二.ALSA架构简介;二. ...

  8. Linux ALSA声卡驱动之五:移动设备中的ALSA(ASoC)

    1.  ASoC的由来 ASoC--ALSA System on Chip ,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系.在ASoc出现之前,内 ...

  9. Linux Alsa声卡驱动(1):简介

    引言: 往日工作中对于声卡驱动的调试也仅仅局限于编译供应商提供的codec及配置dts,并没有去深入了解声卡驱动,目前打算去好好研究一下,为了以后能更好的处理关于声卡驱动方面的问题.经过网上查阅资料发 ...

最新文章

  1. 关于一对多,多对多的多表查询的控制
  2. 第13章:项目合同管理(2)-章节重点
  3. Idea使用技巧总结(未完待续)
  4. java 生成objectid_【Java】唯一ID的几种生成方案
  5. 浅谈 EF CORE 迁移和实例化的几种方式
  6. CSS浏览器兼容性问题
  7. imagesLoaded-检测图片是否正确加载的js插件
  8. ubuntu下ffmpeg编译安装
  9. CTA策略02_boll
  10. 关于PHP的著作文献,著作类参考文献格式
  11. [CEOI2017]Mousetrap
  12. 在线CUR格式转换器
  13. yii mysql gii_yii中gii如何使用
  14. WorkBench简介
  15. Windows系统MySQL免安装下载配置
  16. nowcoder:[编程题] 头条校招(贪心)
  17. Walkthrough: Word 2007 XML 格式
  18. HTML——制作新闻网页
  19. 基于云开发创建(小程序云商城,基本页面的创建及动态代码的编写)
  20. python中 utf-8 和GBK 的关系

热门文章

  1. 一个人有没有领导力,就看这3点
  2. 怎么样关闭计算机的操作音,电脑报警音怎么关闭
  3. 常用的Python标准库有哪些
  4. Android自动手绘,圆你儿时画家梦!
  5. Bootstrap 标签 label
  6. 数据挖掘复习笔记第七章——聚类
  7. 毕业这五年走来,这些私藏Redis的最全知识点我贡献出来了
  8. python是人都能学会_人人都能学会的python编程教程15:高级特性2
  9. 使用Python对音频进行频谱分析
  10. 便利蜂是“冬眠”还是“假寐”,只有时间知道