轉自:https://blog.csdn.net/qq_21186033/article/details/117655677
1 基本概念
HDA Codec結構將不同的codec functions描述成一系列參數化模塊。每個模塊(以及模塊的組合)為一個addressable node,每個node都可通過一系列只讀的capabilities(parameters)和一系列可讀寫的command(controls)來進行配置和操作。
Function Group分為Audio Function Group和Modem Function Group,function group中的節點又稱為widget。每個widget都有一個獨立的地址,用來對它進行控制(controls)或讀取widget狀態。
每個codec在初始化過程中都會被分配一個獨立的codec address(CAd)。codec中的每個節點都有一個獨立的node ID(NID)。CAd和NID的結合能夠為每個codec中的每個節點組合成一個獨立的地址。
每個widget只能屬於一個function group,且只能和同一個function group的widget連接;每個Widget都有一系列標准的parameters(capabilities)和controls(命令和狀態寄存器)
PCM是英文Pulse-code modulation的縮寫, PCM就是要把聲音從模擬轉換成數字信號的一種技術,他的原理簡單地說就是利用一個固定的頻率對模擬信號進行采樣,采樣后的信號在波形上看就像一串連續的幅值不一的脈沖,把這些脈沖的幅值按一定的精度進行量化,這些量化后的數值被連續地輸出、傳輸、處理或記錄到存儲介質中,所有這些組成了數字音頻的產生過程。
此Capabilitie(PCM信號)的重要參數包括的兩個重要指標:采樣頻率和量化精度。
播放音樂時,應用程序從存儲介質中讀取音頻數據(MP3、WMA、AAC......),經過解碼后,得到PCM數據,最終送到音頻驅動程序中。
在錄音時,音頻驅動不停地把采樣所得的PCM數據送回給應用程序,由應用程序完成壓縮、存儲等任務。
2 Audio Function Group分類
Audio Output Converter, 主要為DAC或S/PDIF OUT,節點的輸入端連接至codec中的HDA link Audio Input Converter, 主要為ADC或者S/PDIF IN,節點的輸出端連接至codec中的HDA link
Pin complex widget, 提供了Audio Function Group和其他Function Group的外部連接。HDMI或DP這樣的可以操作聲音的digital display connection,被歸類為digital pin widget。
Mixer, 混合器,在該種節點中,所有輸入端必須有相同的放大器參數(若沒有則必須全部沒有),若需要不同的輸入端有不同的放大器參數,則利用multiplexer來連接不同的輸入,再連接至mixer中。mixer的所有輸入均為硬連接,不能選擇只使用其中幾個,上面的那幾種節點可以。
Multiplexer, 多選器,對input的選擇依賴於一個connection selector來完成。
Power Widget,通過對任意widgets的組合提供電源狀態控制,來優化電源管理,與其他widget沒有硬件上的連接,但是會通過connection list來規定用來控制哪些widget。
Volume Knob Widget,對特定的輸出pin提供機械上的音量控制。該widget的connection list描述了哪些widget(主要是pin widget)的音量會被該widget控制。
3 HDA初始化及codec的枚舉
(1)控制器初始化
當HDA控制器在上電后,退出上電復位時,所有控制器寄存器將處於其上電默認狀態,並且鏈接將處於非活動狀態。啟動控制器的第一步是正確編程PCI PCI Express或其他系統總線接口。由於此操作特定於控制器實現,因此應遵循特定控制器的文檔。編程結束時,控制器應准備好在系統總線上傳輸數據。例如,當使用PCI時,中斷線 基址和其他PCI配置空間寄存器應正確編程。
當控制器第一次啟動時,Offset 08h: GCTL – Global Control寄存器CRST位為0,表示控制器處於復位狀態。將CRST位置一來復位HDA控制器,控制器將經歷一系列必要的步驟,以使自己脫離復位。鏈接被啟動,狀態機將自己初始化。
當硬件執行這些步驟時,CRST位將顯示為0。初始化完成后,CRST位的讀取將返回1,表示控制器現在已准備好工作。因此,在控制器退出復位后,軟件應等待CRST被讀取為1后再繼續。
(2) codec枚舉
當通過CRST啟用鏈路時,codec將檢測到重置信號的反斷言,並請求控制器進行狀態更改和枚舉。當控制器硬件檢測到這些請求時,它將向codec提供它們的唯一地址,並設置控制器STATESTS位,以指示在相應的SDATA\u INx信號上檢測到狀態更改事件。軟件可以使用這些位來確定連接到鏈接的codec的地址。給定位位置的1表示存在相關地址處的codec。
例如,值05h意味着有地址為0和2的codec連接到鏈接。從RESET#de斷言到codec請求枚舉最晚可長達25幀。在將CRST讀取為1之后,軟件必須等待至少521us(25幀),然后再假設codec已發出所有狀態更改請求並已由控制器注冊。這使codec有足夠的時間執行自我初始化。
如果軟件希望在連接新的codec時獲得中斷,例如在熱插拔事件期間,軟件可以將INTCTL寄存器中的CIE位設置為1,以啟用包括狀態更改事件的控制器中斷。當接收到中斷時,可以檢查STATESTS位,以確定先前未識別的codec是否請求狀態更改。
4 HDA與codec通信機制
一旦枚舉了附加的codec,就可以向codec發送命令以確定其功能。codec命令和控制描述了向codec發送控制信息和從codec接收控制信息的機制。命令和控制數據是低帶寬的異步數據,在鏈路上一次傳輸一個命令。無論是控制器的入站還是控制器的出站,都不能以任何方式確保定時。codec命令和控制由控制器通過兩個關鍵機制來處理,即命令出站環形緩沖區(CORB)和響應輸入環形緩沖區(RIRB)。軟件負責通過CORB控制和RIRB控制寄存器配置控制器的CORB和RIRB。
HDA控制器和codec的通信機制主要依賴於兩個機制:
CORB(Command Outbound Ring Buffer)和RIRB(Response Input Ring Buffer)。軟件通過CORB和RIRB相關寄存器們來對這兩個機制進行配置。
(1)PIO方式
1)將verb數據寫入Offset 60h: Immediate Command Output Interface寄存器中。
2)設置Offset 68h: Immediate Command Status寄存器的低倆位置1。
3)查看Offset 68h: Immediate Command Status寄存器的BIT0,確認數據寫入執行完畢。
4)從Offset 64h: Immediate Response Input Interface寄存器中將結果讀出來。
(2)DMA方式
1)Command Outbound Ring Buffer – CORB
a 數據交互
controller 用來發從命令給codec的機制。CORB是一個系統內存中的環形緩沖區,用於將軟件中發送的命令傳遞給連接在HDA鏈路上的codecs。另外有兩個硬件中的指針,Write Pointer和Read Pointer。寫指針是軟件用來告訴硬件CORB中最后一個有效的命令是哪個。而硬件通過讀指針來告訴軟件最后一個獲取的命令是哪個。(每向CORB中放入一個新命令,寫指針+1(軟件寫),硬件每處理一個CORB中的命令,讀指針+1(硬件寫))。HDA控制器中的DMA engine會不停的比較讀寫指針,當兩者不相同時,會不停的從buffer中獲取命令通過鏈路傳遞到codec上,直到讀寫指針的值相同。
注:
b Each entry in the CORB is also 32 bits long and matches the verb format.
c first commands will be placed at a offset of 4 bytes into the CORB buffer, as CORBWP will be 0, so CORBWP + 1 will indicate a 4-byte offset into the CORB.
2)Response Inbound Ring Buffer - RIRB
a RIRB數據交互
RIRB是codecs發送回復給controller的機制。同樣也是系統內存中的一個環形緩沖區,用來存儲連接在鏈路上的codec發送的response信息。回復可分為請求的(回復controller發送的命令)和自發的(codec直接發送,標記某些事件的)。軟件需要區分回復是來自哪個codec的,以及該回復是自發的還是請求的。同CORB相同,RIRB中也有Read Pointer和Write Pointer。讀指針僅被軟件所使用,用來記錄上一個從buffer中讀到的回復。寫指針在硬件中用來指明最后一個寫進buffer中的回復。controller可通過Interrupt和Polling兩種方式來通知軟件RIRB需要被讀了。
b Entry Format
The response passed from the codecs to the controller is 32 bits long. Each entry in the RIRB is 64 bits long.
5 HDA codec數據流
硬件框架如下圖:
Streams and Channels
HDA中通過抽象出streams和channels來描述link中傳輸的數據的方式。
stream是在系統內存和該數據的codec譯碼時創建的虛擬連接,由通過鏈路的單個DMA通道驅動。軟件負責創建和管理流。與流相關的關鍵參數,如流參數、通道數、數據格式、位深度等,由軟件定義。
channels就是我們很熟悉的聲道的概念,所以,一個立體音stream中包含L和R兩個channel。
上圖描述了上面提到的各個概念之間的關系。每個active stream必須連接到一個DMA引擎上,上面的stream 1,2,3都是active stream,其中1,3是output類型的 stream,2是input類型的stream.4就是一個inactive stream.
下圖描述了link、stream、channels之間的關系。
下圖描述了Link上數據流幀的格式:
注:Link上傳輸多個frames,每個frams的大小是固定的
CORB、RIRB是用來傳輸命令的,對應的數據的傳輸是通過BDL(Buffer Descriptor List)來管理的。BDL是由BDLE(Buffer Descriptor List Entries)組成的,BDL和BDLE的格式分別如下圖:
其中IOC(Interrupt on Completion),這個標志位決定着DMA傳輸一定數據后觸發中斷,中斷處理中會喚醒應用層阻塞式的寫數據線程。這個”一定數據量”其實就是我們在設置hw_params時設置的periods值,periods也就是我們將一大塊輸出緩存進行了均分出來的的一片片buffer。