ALSA driver--Asoc

ALSA Asoc框架如下图:

Asoc分为machine,platform,codec三大模块。关于machine,platform,codec的介绍参考自这里http://blog.csdn.net/droidphone/article/details/7165482

  • Machine  是指某一款机器,可以是某款设备,某款开发板,又或者是某款智能手机,由此可以看出Machine几乎是不可重用的,每个Machine上的硬件实现可能都不一样,CPU不一样,Codec不一样,音频的输入、输出设备也不一样,Machine为CPU、Codec、输入输出设备提供了一个载体。
  • Platform  一般是指某一个SoC平台,比如pxaxxx,s3cxxxx,omapxxx等等,与音频相关的通常包含该SoC中的时钟、DMA、I2S、PCM等等,只要指定了SoC,那么我们可以认为它会有一个对应的Platform,它只与SoC相关,与Machine无关,这样我们就可以把Platform抽象出来,使得同一款SoC不用做任何的改动,就可以用在不同的Machine中。实际上,把Platform认为是某个SoC更好理解。
  • Codec  字面上的意思就是编解码器,Codec里面包含了I2S接口、D/A、A/D、Mixer、PA(功放),通常包含多种输入(Mic、Line-in、I2S、PCM)和多个输出(耳机、喇叭、听筒,Line-out),Codec和Platform一样,是可重用的部件,同一个Codec可以被不同的Machine使用。嵌入式Codec通常通过I2C对内部的寄存器进行控制。

对应的会有machine, platform,codec driver。

Machine driver负责处理机器特有的一些控件和音频事件(例如,当播放音频时,需要先行打开一个放大器);单独的Platform和Codec驱动是不能工作的,它必须由Machine驱动把它们结合在一起才能完成整个设备的音频处理工作。

platform driver,它包含了该SoC平台的音频DMA和音频接口的配置和控制(I2S,PCM,AC97等等);它也不能包含任何与板子或机器相关的代码。

Codec driver,ASoC中的一个重要设计原则就是要求Codec驱动是平台无关的,它包含了一些音频的控件(Controls),音频接口,DAMP(动态音频电源管理)的定义和某些Codec IO功能。为了保证硬件无关性,任何特定于平台和机器的代码都要移到Platform和Machine驱动中。所有的Codec驱动都要提供以下特性:

  • Codec DAI 和 PCM的配置信息;
  • Codec的IO控制方式(I2C,SPI等);
  • Mixer和其他的音频控件;
  • Codec的ALSA音频操作接口;

也可以提供以下功能:

  • DAPM描述信息;
  • DAPM事件处理程序;
  • DAC数字静音控制

从数据结构看来,snd_soc_card代表着Machine驱动,snd_soc_platform则代表着Platform驱动,snd_soc_codec和soc_codec_device则代表了Codec驱动,而snd_soc_dai_link则负责连接Platform和Codec。

snd_soc_dai是snd_soc_platform和snd_soc_codec的数字音频接口,snd_soc_codec的dai为codec_dai,snd_soc_platform的dai为cpu_dai,snd_pcm是snd_soc_card实例化后注册的声卡类型.

下面以smdk_wm8580为例,看看再Asoc框架下的ALSA driver的编写。

static struct snd_soc_dai_link smdk_dai[] = {//snd_soc_dai_link中,指定了Platform、Codec、codec_dai、cpu_dai的名字
  [PRI_PLAYBACK] = { /* Primary Playback i/f */
    .name = "WM8580 PAIF RX",
    .stream_name = "Playback",
    .cpu_dai_name = "samsung-i2s.0",
    .codec_dai_name = "wm8580-hifi-playback",
    .platform_name = "samsung-i2s.0",
    .codec_name = "wm8580.0-001b",
    .dai_fmt = SMDK_DAI_FMT,
    .ops = &smdk_ops,
  },
  [PRI_CAPTURE] = { /* Primary Capture i/f */
    .name = "WM8580 PAIF TX",
    .stream_name = "Capture",
    .cpu_dai_name = "samsung-i2s.0",
    .codec_dai_name = "wm8580-hifi-capture",
    .platform_name = "samsung-i2s.0",
    .codec_name = "wm8580.0-001b",
    .dai_fmt = SMDK_DAI_FMT,
    .init = smdk_wm8580_init_paiftx,
    .ops = &smdk_ops,
  },
  [SEC_PLAYBACK] = { /* Sec_Fifo Playback i/f */
  .name = "Sec_FIFO TX",
  .stream_name = "Playback",
  .cpu_dai_name = "samsung-i2s-sec",
  .codec_dai_name = "wm8580-hifi-playback",
  .platform_name = "samsung-i2s-sec",
  .codec_name = "wm8580.0-001b",
  .dai_fmt = SMDK_DAI_FMT,
  .ops = &smdk_ops,
  },
};

static struct snd_soc_card smdk = {
  .name = "SMDK-I2S",
  .owner = THIS_MODULE,
  .dai_link = smdk_dai,
  .num_links = 2,

  .dapm_widgets = smdk_wm8580_dapm_widgets,
  .num_dapm_widgets = ARRAY_SIZE(smdk_wm8580_dapm_widgets),
  .dapm_routes = smdk_wm8580_audio_map,
  .num_dapm_routes = ARRAY_SIZE(smdk_wm8580_audio_map),
};

static struct platform_device *smdk_snd_device;

static int __init smdk_audio_init(void)
{
  int ret;
  char *str;

  if (machine_is_smdkc100()
  || machine_is_smdkv210() || machine_is_smdkc110()) {
    smdk.num_links = 3;
  } else if (machine_is_smdk6410()) {
    str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
    str[strlen(str) - 1] = ‘2‘;
    str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
    str[strlen(str) - 1] = ‘2‘;
  }

  smdk_snd_device = platform_device_alloc("soc-audio", -1);//创建platform device,device 名字为soc-audio
  if (!smdk_snd_device)
  return -ENOMEM;

  platform_set_drvdata(smdk_snd_device, &smdk);//将platform devcie的drvdata设置成snd_soc_card类型的smdk
  ret = platform_device_add(smdk_snd_device);//将platform device 加到platform bus中。

  if (ret)
  platform_device_put(smdk_snd_device);

  return ret;
}
module_init(smdk_audio_init);

static void __exit smdk_audio_exit(void)
{
  platform_device_unregister(smdk_snd_device);
}
module_exit(smdk_audio_exit);

上述代码主要是在init时,创建一个名字为soc-audio 的platform device, 并将platform device的drvdata设置成snd_soc_card类型的实例,最后将platform device 注册到platform bus中,注册过程主要在platform_device_add中,在前面介绍platform device 注册过程时,有讲到注册时,如果platform bus上有名字为soc-audio的driver,则调用driver的probe函数。

名字为soc-audio的driver定义在soc-core.c中,

static struct platform_driver soc_driver = {
  .driver = {
  .name = "soc-audio",//名字与上面的platform device相同。
  .pm = &snd_soc_pm_ops,
  },
  .probe = soc_probe,
  .remove = soc_remove,
};

static int __init snd_soc_init(void)
{
  snd_soc_debugfs_init();
  snd_soc_util_init();

  return platform_driver_register(&soc_driver);//注册platform driver:soc_driver.
}
module_init(snd_soc_init);

时间: 2024-10-04 07:55:01

ALSA driver--Asoc的相关文章

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

转自http://blog.csdn.net/droidphone/article/details/7165482 1.  ASoC的由来 ASoC--ALSA System on Chip ,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系.在ASoc出现之前,内核对于SoC中的音频已经有部分的支持,不过会有一些局限性: Codec驱动与SoC CPU的底层耦合过于紧密,这种不理想会导致代码的重复,例如,仅是wm8731的驱动,当时Linux中

ALSA driver --PCM device 创建过程

前面已经写过PCM device的创建框架,我们现在来看看PCM device是如何创建的. 在调用snd_pcm_new时就会创建一个snd_pcm类型的PCM device. struct snd_pcm { struct snd_card *card;//PCM device 说挂载的声卡 struct list_head list;//一个Card可能有多个PCM device,PCM device列表 int device; /* device number *///PCM devic

Linux ALSA 音频系统:逻辑设备篇

6. 声卡和 PCM 设备的建立过程 前面几章分析了 Codec.Platform.Machine 驱动的组成部分及其注册过程,这三者都是物理设备相关的,大家应该对音频物理链路有了一定的认知.接着分析音频驱动的中间层,由于这些并不是真正的物理设备,故我们称之为逻辑设备. PCM 逻辑设备,我们又习惯称之为 PCM 中间层或 pcm native,起着承上启下的作用:往上是与用户态接口的交互,实现音频数据在用户态和内核态之间的拷贝:往下是触发 codec.platform.machine 的操作函

Linux ALSA介绍

1. 介绍 ALSA(即Advanced Linux Sound Architecture), 是目前Linux的主流音频体系结构, 提供了音频和MIDI的支持, 其架构图如下所示 TIP: 笔者的代码分析基于linux-4.14.19 2. 初始化 系统启动中ALSA初始化过程如下 alsa_sound_init() /* 注册alsa字符设备 */ register_chrdev(116, "alsa", &snd_fops) /* 创建/proc/asound目录及下属v

ALSA driver--PCM

在介绍PCM 之前,我们先给出创建PCM实例的框架. #include <sound/pcm.h> .... /* hardware definition */ static struct snd_pcm_hardware snd_mychip_playback_hw = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMA

ALSA lib基本概念

1.channel 通道,即我们熟知的声道数.左/右声道,5.1channel等等 2.sample A sample is a single value that describes the amplitude of the audio signal at a single point in time, on a single channel. sample即一次采样,通常的sample bit指的是一个channnel上,一次采样的bit数(常见的sample bit 8/16/24/32b

高通Auido中ASOC的machine驱动

ASoC被分为Machine.Platform和Codec三大部分,其中的Machine驱动负责Platform和Codec之间的耦合以及部分和设备或板子特定的代码,再次引用上一节的内容:Machine驱动负责处理机器特有的一些控件和音频事件(例如,当播放音频时,需要先行打开一个放大器):单独的Platform和Codec驱动是不能工作的,它必须由Machine驱动把它们结合在一起才能完成整个设备的音频处理工作. ASoC的一切都从Machine驱动开始,包括声卡的注册,绑定Platform和C

嵌入式LAB 1:启动

嵌入式系统Lab 1 启动 1. 画出你所实际实施的连接示意图 2.给出实际拍摄的板卡连接照片 3.给出所用的器材的列表 pcduino(含电源).USB串口线.网线.SD卡.无线网卡 显示屏.鼠标.键盘.支持L2TP路由器.MacBook Air 4.给出得到的pcDuino启动时的输出文字,并逐行解释 U-Boot 2009.08 (Dec 25 2014 - 21:37:33) # U-Boot: Universal Boot Loader, 负责嵌入式 Linux 系统的引导 CPU:

如何在Ubuntu安装*.exe文件

下载及安装 若你使用 Debian 或者 Ubuntu 之类的发行版,只需要一个命令即可完成安装: apt-get install wine 若你使用的为其他发行版,请访问 http://winehq.org/site/download 查询安装方法[]Wine 的配置 运行 winecfg 即可,里面有详尽的配置. 注意:Wine 1.1.4 以上版本的 winecfg 已经是中文界面了.[]Wine 中文乱码的解决 Wine 1.1.4 以上版本的中文支持得到了极大改善.如果您在使用较低版本