2012年1月12日 星期四

Linux sound ALSA soc kernel 文件略讀

主要參考 Documentation/sound/alsa/soc/ 目錄中的文件

    Documentation/sound/alsa/soc/overview.txt
    Codec driver: 包括 audio control, interface, DAPM define, I/O function
    sound/soc/codecs/twl6040.c

    Platform driver: audio DMA and DAI(I2S, PCM, AC97)
    sound/soc/omap/omap-mcbsp.c DMA 控制, DAI system clock

    Machine driver: SoC machine board control and audio event
    sound/soc/omap/sdp4430.c DAI 控制
        1.  Amplifier 控制
        2.  snd_soc_card 註冊為 platform device
        3.  DAI system clock 控制跟 DAI 初始化設定

    Documentation/sound/alsa/soc/DAI.txt
    講 soc codec 常用的 AC97, I2S, PCM 三種 Digital Audio Interface

    Documentation/sound/alsa/soc/clocking.txt
    audio 相關的 clock 描述:
    Master clock, MCLK, SYSCLK
        derived from crystal(fixed), PLL(configurable), CPU clock(configurable)
        to produce correct playback and capture sample rates

    DAI clock
        1.  DAI clock is driven by Bit Clock(BCLK)
        to drive digital audio data between CPU and codec


        2.  frame clock(LRC Left Right Clock, FRAME), is sample rate
        to signal start of audio frame

        3.  BCLK(Bit Clock) 的產生依 CPU 與 audio codec 設定不同而改變
            BCLK = MCLK / x
                or
            BCLK = LRC * x
                or
            BCLK = LRC * Channels * Word size

        4.  BCLK 越慢越能達到節電源的效果
        5.  audio codec 也可以產生 BCLK,通常比 cpu 更精準

    Documentation/sound/alsa/soc/codec.txt
    ASoC codec driver 是通用、不相依於硬體的抽象層,用來設定播放或錄音。
    其中不應有相依於軟硬體平台的程式碼。硬體平台相關程式碼應該放在 platform driver 與 machine driver 中。

    codec driver 必須提供的功能:
    1.  Codec DAI 與 PCM 設定 snd_soc_codec_dai structure
    包括 stream name, channel, rate, format

    2.  Codec control IO
    control_data 指向 i2c/spi/ac97
    reg_cache 指向 codec register map
    read/write 指向 i2c/spi/ac97 的 read/write 介面

    3.  Mixer 與聲音控制
    定義 include/sound/control.h 中的  struct snd_kcontrol_new 內容,可以使用以下 macro:
    include/sound/soc.h 定義的 kcontrol builders macro,如 SOC_SINGLE() 等
    可以建立一個 xname ,以便控制如 Playback Volume 等的暫存器。

    4.  Codec Audio operation
    需要實作 snd_soc_ops 提供的介面,參考

    5.  DAPM 描述
    Dynamic Audio Power Management 描述 codec 元件的電源與控制的暫存器,可以參考 Documentation/sound/alsa/soc/dapm.txt

    6.  DAPM 事件處理
    用來處理 codec domain 與 cpu domain 的事件呼叫,註冊所需的 callback function 即可,是實際執行 power saving 的函式。
164 Power states:-
165
166     SNDRV_CTL_POWER_D0: /* full On */
167     /* vref/mid, clk and osc on, active */
168
169     SNDRV_CTL_POWER_D1: /* partial On */
170     SNDRV_CTL_POWER_D2: /* partial On */
171
172     SNDRV_CTL_POWER_D3hot: /* Off, with power */
173     /* everything off except vref/vmid, inactive */
174
175     SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
176
    sound/soc/soc-core.c 有實作。呼叫 snd_power_wait() snd_power_change_state()

    7.  Codec DAC 數位靜音控制
    可用在啟動 DACs 之前的數位靜音,避免系統雜音。可確保不會有數位聲音資料傳到 DACs,可以註冊 include/sound/soc-dai.h 其中 struct snd_soc_dai_ops {} 所定義的 digital_mute callback 讓系統呼叫。

    另外系統也有預設定義靜音介面 snd_soc_dai_digital_mute()

    Documentation/sound/alsa/soc/machine.txt
    machine 或稱 board driver 就是將 platform driver 與 codec driver 連結的程式碼,會使用 struct snd_soc_card 在 linux kernel 註冊一個 platform device,提供 probe, remove...介面
  
    DAI 的控制使用 struct snd_soc_dai_link 連接 codec driver 與 cpu DAIs,可用來初始化 DAI system clock 等 DAI 所需的初始化動作,如 machine audio map 跟 codec audio map,或是有未連接的 codec 腳位設定等...snd_soc_dai_link 設定 codec<->CPU 之間的 DAI
    比如:
 58 /* corgi digital audio interface glue - connects codec <--> CPU */
 59 static struct snd_soc_dai_link corgi_dai = {
 60     .name = "WM8731",
 61     .stream_name = "WM8731",
 62     .cpu_dai_name = "pxa-is2-dai",
 63     .codec_dai_name = "wm8731-hifi",
 64     .platform_name = "pxa-pcm-audio",
 65     .codec_name = "wm8713-codec.0-001a",
 66     .init = corgi_wm8731_init,
 67     .ops = &corgi_ops,
 68 };
 69
 70 struct snd_soc_card 再跟 snd_soc_dai_link 連結.
 71
 72 /* corgi audio machine driver */
 73 static struct snd_soc_card snd_soc_corgi = {
 74     .name = "Corgi",
 75     .dai_link = &corgi_dai,
 76     .num_links = 1,
 77 };
 78

    Machine power map 可以擴充 codec power map 成為 audio power map 的一部份,可達到自動開關  speaker/HP amplifiers 等 audio path。machine init function 可以連接 codec 腳位到 jack socket,請參考 soc/pxa/spitz.c 與 dapm.txt

    Machine 的混音器 mixer 控制

Linux kernel alsa 版本查看方式
        1.  linux kernel source code
        include/sound/version.h
        #define CONFIG_SND_VERSION "1.0.21"

        2.  linux run time /proc file
        cat /proc/asound/version

Linux kernel alsa driver 所產生的 /sys 介面 device 檔案,最後會再透過 user space 的 mdev 或 udev (ueventd in android?) 生成 /dev/controlC0 或 /dev/snd/controlC0 等介面,供 alsa lib 與 alsa utility 使用。