ALSA driver--Asoc

來源:互聯網
上載者:User

標籤:alsa   util   controls   驅動   gfs   技術分享   音頻   控制項   int   

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);

 

ALSA driver--Asoc

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.