カーネルから複数のネイティブPCMデータストリームを結合し、それをTDMフレームにルーティングしてiMX 8M MiniのSAIインターフェイスを介して転送する方法

カーネルから複数のネイティブPCMデータストリームを結合し、それをTDMフレームにルーティングしてiMX 8M MiniのSAIインターフェイスを介して転送する方法

iMX8(PCM -48Kz、16ビット、2ch)で複数のオーディオストリーム(8ストリーム)を組み合わせようとしています。ユーザースペースのテストモードは、RAW PCMを含むwavファイルを再生するために8つのgst_launch / aplayインスタンスを同時に実行するのと似ています。
私が経験している問題は、iMX8に接続されているボードにオーディオをシャットダウンできるオーディオハードウェアデバイス(カード)がないことです。代わりに、オーディオ(PCM)はSAIインターフェイスにルーティングする必要があり、8ストリームのサンプルはTDMフレームに多重化され、iMX8のSAIインターフェイスを介して送信されます。 SAIラインはオーディオFPGAに接続され、TDM出力を逆多重化し、それをメインCPUボードに接続された異なるボードの8つのポートに送信します。 iMX8プロセッサ用のカーネルドライバソリューションを提供する必要があります。私たちはYoctoでiMX8M MiniアプリケーションプロセッサとLinux 4.14.98を使用しています。
私はALSAに初めて触れました。私の全体的な背景は、カーネルのビデオ/ディスプレイ/PCIサブシステムにあります。

ALSAの詳細を見ると、ALSAコア/ハードウェアアーキテクチャ全体がオーディオハードウェア終端を中心に構築されており、そのアーキテクチャは次のとおりです。Linux BSPでカスタムオーディオコーデックを移植する投稿者:Gopinath Srinivasan:
Alsaカーネルドライバー⟺[Coder / Dec⟺マシンドライバー⟺プラットフォームドライバー]⟺プロセッサーHW(オーディオ)。

私はできるだけ読んでみましたが、これが私が理解したことです。

ハードウェア機器がないからです。

  1. オーディオをカーネルに渡すためにsnd_dummyまたはsnd_aloop(dummy / aloopオーディオドライバを有効にするために使用されます)を有効にできますか?これらの機能を有効にしてSeller_testとaplayを実行してテストしましたが、アプリがクラッシュすることなく動作しているようです。
  2. コアからサンプルを読み込んで結合し、SAI FIFO(TDR/TFR)に書き込み、対応するBCLK/MCLKを設定します。おそらくこれを達成するために、SAIの非同期モードを使用できます。現在、Alsaドライバモデルでこのパスを有効にする方法がわかりません。

上記の方法についていくつかの質問があります。また、これがオーディオを処理する正しい方法かもしれないので、私が間違っている場合は修正してください。もう1つの問題は、SAIインターフェースから出てくるWCLK / MCLK / BCLK / TX0ラインを検索する以外にこれをテストする他の方法がないことです。それはまったく異なる質問です。いったんそこに行けば気になります。

私の質問は次のとおりです。

  1. この方法で始めるのは正しいですか?
  2. プラグイン(Dmix)について読みました。 DMIXプラグインはどのように機能しますか?この場合、このプラグインを使用して、confファイル(asoundrc、alsa.confなど)に書き込まれたいくつかの設定で、何とかTDM fifoに書き込まれる8つのポートとサンプルの両方を設定できますか?これがどのように機能するのかわかりません。いくつかの質問をします。これが意味があるかどうかわかりません。
  3. HWデバイスがないので、DTSでSAIを設定する方法は? snd_aloop/snd_dummyを使用するときにどのコーデックを有効にする必要がありますか(オーディオがカーネルに渡される方法だと仮定)ここのように。これはFreescale iMX8M Mini評価ボードに基づいています。
    sound-ak4458 {                                          
           compatible = "fsl,imx-audio-ak4458";            
           model = "ak4458-audio";                         
           audio-cpu = <&sai1>;                      <-------      
           audio-codec = <&ak4458_1>, <&ak4458_2>;         <--------
           ak4458,pdn-gpio = <&pca6416 4 GPIO_ACTIVE_HIGH>;
    };                                                      
    
  4. カーネルのalsaドライバにオーディオがどのように渡されますか?サンプルはioclts / sysfsを介してバッファに渡されるか、メモリに書き込まれるか(DMA?)、audioHW /コーデックからメモリ(DMA)を介して直接アクセスされるか、他の方法でアクセスされますか?
  5. ALSAは、この方法でデータを転送する必要がある場合、aloop.c/dummy.cドライバから直接SAIインタフェース(fsl_sai.c/h)にアクセスすることをサポートしますか?
  6. snd_dummyドライバを有効にすると、8つのサブデバイスが作成されます。ユーザースペースアプリケーションは、これら8つのサブデバイスを8つの異なるハードウェアポート(hw:0,0; ​​hw:0,1; hw:0,2など)として使用できますか、または8つの別々の開発ノード(hw: 0、0; hw:0,0; ​​hw:0,2など)? hw:1,0; hw:2,0など)をアプリケーションに送信しますか?後者が正しい場合は、仮想/ループドライバで別々の開発ノードを作成できますか?

私を正しい方向に導くのを助けてくれてありがとう。質問や詳細を追加する必要がある場合は、お知らせください。

答え1

dshareプラグインを使用して、8チャンネルで動作するTDMフレームを作成できました。ところが16チャンネルに増やそうとしたところ、ポーリング機能で再生が止まる問題が発生しました。バラより私の他の記事はここにあります。

/dev/snd/timer私はdshare / dmixプラグインが使用するのではなく、サーバーを使用する共有「share」プラグインを試しました。

ただし、複数のクライアントを同時に再生しようとすると、1つのクライアントを再生した後にオーディオデバイスの使用中にエラーが発生します。複数のソースを再生するには、設定ファイルに別のものが必要ですか?

よりasound.conf:

# Crestron DNA_AUDIO x specific configurations
# NOTE: this is for sharing multiple channels on a single (TDM) audio device
# with multple ALSA clients

# shared buffer for playback
pcm_slave.tdmshare {
    pcm "hw:0"
    channels 16
    rate 48000          # fixed, because all dshare devices must use the same samplerate.
    format S24_LE
}

# src1 shared pcm device and corresponding virtual playback device
pcm.src1_share {
    type share
    slave tdmshare
    bindings.0 0
    bindings.1 4
}
pcm.src1 {
    type plug
    slave.pcm "src1_share"
 hint {
                show {
                        @func refer
                        name defaults.namehint.basic
                }
                description "TDM 0 channel 0/1 for audio playback"
        }
}

# src2 shared pcm device and corresponding virtual playback device
pcm.src2_share {
    type share
    slave tdmshare
    bindings.0 8
    bindings.1 12
}
pcm.src2 {
    type plug
    slave.pcm "src2_share"
 hint {
                show {
                        @func refer
                        name defaults.namehint.basic
                }
                description "TDM 1 channel 2/3 for audio playback"
        }
}

# src3 shared pcm device and corresponding virtual playback device
pcm.src3_share {
    type share
    slave tdmshare
    bindings.0 1
    bindings.1 5
}
pcm.src3 {
    type plug
    slave.pcm "src3_share"
 hint {
                show {
                        @func refer
                        name defaults.namehint.basic
                }
                description "TDM 2 channel 4/5 for audio playback"
        }
}

# src4 shared pcm device and corresponding virtual playback device
pcm.src4_share {
    type share
    slave tdmshare
    bindings.0 9
    bindings.1 13
}
pcm.src4 {
    type plug
    slave.pcm "src4_share"
 hint {
                show {
                        @func refer
                        name defaults.namehint.basic
                }
                description "TDM 3 channel 6/7 for audio playback"
        }
}

# src5 shared pcm device and corresponding virtual playback device
pcm.src5_share {
    type share
    slave tdmshare
    bindings.0 2
    bindings.1 6
}
pcm.src5 {
    type plug
    slave.pcm "src5_share"
 hint {
                show {
                        @func refer
                        name defaults.namehint.basic
                }
                description "TDM 4 channel 8/9 for audio playback"
        }
}

# src6 shared pcm device and corresponding virtual playback device
pcm.src6_share {
    type share
    slave tdmshare
    bindings.0 10
    bindings.1 14
}
pcm.src6 {
    type plug
    slave.pcm "src6_share"
 hint {
                show {
                        @func refer
                        name defaults.namehint.basic
                }
                description "TDM 5channel 10/11 for audio playback"
        }
}

# src7 shared pcm device and corresponding virtual playback device
pcm.src7_share {
    type share
    slave tdmshare
    bindings.0 3
    bindings.1 7
}
pcm.src7 {
    type plug
    slave.pcm "src7_share"
 hint {
                show {
                        @func refer
                        name defaults.namehint.basic
                }
                description "TDM 6 channel 12/13 for audio playback"
        }
}

# src8 shared pcm device and corresponding virtual playback device
pcm.src8_share {
    type share
    slave tdmshare
    bindings.0 11
    bindings.1 15
}
pcm.src8 {
    type plug
    slave.pcm "src8_share"
 hint {
                show {
                        @func refer
                        name defaults.namehint.basic
                }
                description "TDM 7 channel 14/15 for audio playback"
        }
}

関連情報