動態 PCM

描述

動態 PCM 允許 ALSA PCM 裝置在 PCM 流執行時將其 PCM 音訊數字路由到各種數字端點。例如,PCM0 可以將數字音訊路由到 I2S DAI0、I2S DAI1 或 PDM DAI2。這對於公開多個 ALSA PCM 並能路由到多個 DAI 的片上系統 (SoC) DSP 驅動程式非常有用。

DPCM 執行時路由由 ALSA 混音器設定決定,其方式與 ASoC 編解碼器驅動程式中模擬訊號的路由方式相同。DPCM 使用表示 DSP 內部音訊路徑的 DAPM 圖,並使用混音器設定來確定每個 ALSA PCM 使用的路徑。

DPCM 無需任何修改即可重用所有現有元件的編解碼器、平臺和 DAI 驅動程式。

基於 SoC DSP 的電話音訊系統

考慮以下電話音訊子系統。本文件中的所有示例都將以此為例 :-

| Front End PCMs    |  SoC DSP  | Back End DAIs | Audio devices |

                    *************
PCM0 <------------> *           * <----DAI0-----> Codec Headset
                    *           *
PCM1 <------------> *           * <----DAI1-----> Codec Speakers
                    *   DSP     *
PCM2 <------------> *           * <----DAI2-----> MODEM
                    *           *
PCM3 <------------> *           * <----DAI3-----> BT
                    *           *
                    *           * <----DAI4-----> DMIC
                    *           *
                    *           * <----DAI5-----> FM
                    *************

此圖顯示了一個簡單的智慧手機音訊子系統。它支援藍牙、FM 數字廣播、揚聲器、耳機插孔、數字麥克風和蜂窩調變解調器。此音效卡公開 4 個 DSP 前端 (FE) ALSA PCM 裝置並支援 6 個後端 (BE) DAI。每個 FE PCM 都可以將音訊資料數字路由到任何 BE DAI。FE PCM 裝置也可以將音訊路由到多個 BE DAI。

示例 - DPCM 將播放從 DAI0 切換到 DAI1

音訊正在耳機播放。過了一會兒,使用者取下耳機,音訊繼續在揚聲器上播放。

PCM0 到耳機的播放流程如下所示 :-

                    *************
PCM0 <============> *           * <====DAI0=====> Codec Headset
                    *           *
PCM1 <------------> *           * <----DAI1-----> Codec Speakers
                    *   DSP     *
PCM2 <------------> *           * <----DAI2-----> MODEM
                    *           *
PCM3 <------------> *           * <----DAI3-----> BT
                    *           *
                    *           * <----DAI4-----> DMIC
                    *           *
                    *           * <----DAI5-----> FM
                    *************

使用者從插孔中移除耳機,因此現在必須使用揚聲器 :-

                    *************
PCM0 <============> *           * <----DAI0-----> Codec Headset
                    *           *
PCM1 <------------> *           * <====DAI1=====> Codec Speakers
                    *   DSP     *
PCM2 <------------> *           * <----DAI2-----> MODEM
                    *           *
PCM3 <------------> *           * <----DAI3-----> BT
                    *           *
                    *           * <----DAI4-----> DMIC
                    *           *
                    *           * <----DAI5-----> FM
                    *************

音訊驅動程式處理過程如下 :-

  1. 機器驅動程式接收到插孔拔出事件。

  2. 機器驅動程式或音訊 HAL 停用耳機路徑。

  3. 由於耳機路徑已停用,DPCM 對 DAI0 執行 PCM trigger(stop)、hw_free()、shutdown() 操作。

  4. 機器驅動程式或音訊 HAL 啟用揚聲器路徑。

  5. 由於路徑已啟用,DPCM 對 DAI1 揚聲器執行 PCM ops 的 startup()、hw_params()、prepare() 和 trigger(start) 操作。

在此示例中,機器驅動程式或使用者空間音訊 HAL 可以更改路由,然後 DPCM 將負責管理 DAI PCM 操作,以啟用或停用鏈路。在此轉換過程中音訊播放不會停止。

DPCM 機器驅動程式

啟用 DPCM 的 ASoC 機器驅動程式與普通機器驅動程式類似,但我們還需要 :-

  1. 定義 FE 和 BE DAI 鏈路。

  2. 定義任何 FE/BE PCM 操作。

  3. 定義部件圖連線。

FE/BE PCM 操作

上面的 BE 還公開了一些 PCM 操作和一個 fixup 回撥。fixup 回撥由機器驅動程式用於根據 FE hw 引數(重新)配置 DAI。即 DSP 可以對 FE 到 BE 進行 SRC 或 ASRC。

例如,DSP 將所有 FE hw 引數轉換為以 48k、16bit、立體聲的固定速率執行,用於 DAI0。這意味著 DAI0 的所有 FE hw_params 都必須在機器驅動程式中固定,以便 DAI 無論 FE 配置如何都能以所需配置執行。

static int dai0_fixup(struct snd_soc_pcm_runtime *rtd,
                      struct snd_pcm_hw_params *params)
{
      struct snd_interval *rate = hw_param_interval(params,
                      SNDRV_PCM_HW_PARAM_RATE);
      struct snd_interval *channels = hw_param_interval(params,
                                              SNDRV_PCM_HW_PARAM_CHANNELS);

      /* The DSP will convert the FE rate to 48k, stereo */
      rate->min = rate->max = 48000;
      channels->min = channels->max = 2;

      /* set DAI0 to 16 bit */
      params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
      return 0;
}

其他 PCM 操作與常規 DAI 鏈路相同。根據需要使用。

部件圖連線

BE DAI 鏈路通常在初始化時由 ASoC DAPM 核心連線到圖中。但是,如果 BE 編解碼器或 BE DAI 是虛擬的,則必須在驅動程式中明確設定 :-

/* BE for codec Headset -  DAI0 is dummy and managed by DSP FW */
{"DAI0 CODEC IN", NULL, "AIF1 Capture"},
{"AIF1 Playback", NULL, "DAI0 CODEC OUT"},

編寫 DPCM DSP 驅動程式

DPCM DSP 驅動程式看起來很像一個標準的平臺類 ASoC 驅動程式,並結合了編解碼器類驅動程式的元素。DSP 平臺驅動程式必須實現 :-

  1. 前端 PCM DAI - 即 struct snd_soc_dai_driver。

  2. 顯示從 FE DAI 到 BE 的 DSP 音訊路由的 DAPM 圖。

  3. 來自 DSP 圖的 DAPM 部件。

  4. 用於增益、路由等的混音器。

  5. DMA 配置。

  6. BE AIF 部件。

第 6 項對於將音訊路由到 DSP 外部很重要。需要為每個 BE 和每個流方向定義 AIF。例如,對於上面的 BE DAI0,我們將有 :-

SND_SOC_DAPM_AIF_IN("DAI0 RX", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("DAI0 TX", NULL, 0, SND_SOC_NOPM, 0, 0),

BE AIF 用於將 DSP 圖連線到其他元件驅動程式(例如編解碼器圖)的圖。

無主機 PCM 流

無主機 PCM 流是指不透過主機 CPU 路由的流。一個例子是從聽筒到調變解調器的電話呼叫。

                    *************
PCM0 <------------> *           * <----DAI0-----> Codec Headset
                    *           *
PCM1 <------------> *           * <====DAI1=====> Codec Speakers/Mic
                    *   DSP     *
PCM2 <------------> *           * <====DAI2=====> MODEM
                    *           *
PCM3 <------------> *           * <----DAI3-----> BT
                    *           *
                    *           * <----DAI4-----> DMIC
                    *           *
                    *           * <----DAI5-----> FM
                    *************

在這種情況下,PCM 資料透過 DSP 路由。在此用例中,主機 CPU 僅用於控制,並且可以在流執行時進入休眠狀態。

主機可以透過以下方式控制無主機鏈路 :-

  1. 將鏈路配置為 CODEC <-> CODEC 樣式鏈路。在這種情況下,鏈路透過 DAPM 圖的狀態啟用或停用。這通常意味著有一個混音器控制,可用於連線或斷開兩個 DAI 之間的路徑。

  2. 無主機 FE。此 FE 與 DAPM 圖上的 BE DAI 鏈路有虛擬連線。然後由 FE 執行控制作為常規 PCM 操作。此方法對 DAI 鏈路提供更多控制,但需要更多的使用者空間程式碼來控制鏈路。除非您的硬體需要更精細的 PCM 操作序列,否則建議使用 CODEC<->CODEC。

無主機 FE

DAI 鏈路由不讀取或寫入任何 PCM 資料的 FE 啟用。這意味著建立一個新的 FE,該 FE 透過虛擬路徑連線到兩個 DAI 鏈路。當 FE PCM 啟動時,DAI 鏈路將啟動;當 FE PCM 停止時,DAI 鏈路將停止。請注意,在此配置中,FE PCM 無法讀取或寫入資料。