Raspberry Pi ZeroのI2S DACとポップノイズの関係 その2 まっとうにMUTE制御
概要
- NosPiDAC Zeroなどで音楽を楽しんでいるときに気になるポップノイズについて調べたこと・やったことをメモ。
- その2はCodecドライバを修正し、外部MUTE制御との連動を試してみます。
- 外部MUTE制御用のサンプルコード付。
- MUTE機能つきのHPA IC(MAX9722とか)やオペアンプ(OPA1622とか)などで利用できます。
MUTE制御について
- ALSAではCodecに対してポップ抑制用にMUTE Callbackを用意している。
- MUTE関連のCallbackはdigital_muteとmute_streamの2種類
- digital_muteはstream関係なくCallbackされる。mute_stream callbackを登録すると呼ばれない
- mute_streamはstream番号指定でのMUTE制御。録再別とかチャネル別でMUTEできるとかかな?
- とりあえずはdigital_muteを使えば良さそう。
- このMute Callbackを利用してGPIOからHPAのMUTEを制御してポップノイズを抑制できるかを確認してみる。
仕込み
- 改造ベースはNosPiDac Zero 1543 HPAを使用
- HPA ICのMAX9722のShutdownピンにGPIO出力を接続
- NosPiDACのMAX9722 ShutdownピンはVCCに接続されているため、あらかじめカッターなどでパターンをカットする必要があり
- PCM5102Aドライバを改造してdigital_mute CallbackでGPIO出力を制御するように改造
結果
- 曲間でプチる
- I2Sドライバはそのままで、CodecドライバのMUTE制御だけでポップノイズを防ぐことはできない。
- MUTE CallbackでMute解除通知後の処理に何かまずいのが居そう。
- Mute Callbackの様子
- 再生開始・停止でMute Callbackが飛んでくる
- prepare時にMute CallbackでMute解除を通知
- close(shutdownの前)時にMute CallbackでMuteを通知
- 曲間ではMute解除通知しかこない(Mute通知は来ない)
- trigger start/stop時にはMute Callbackは呼ばれない
- 曲間では trigger(stop) - > prepare -> trigger(start)の順で動くため、prepare実行時のMute解除のみ通知される模様
- 再生開始・停止でMute Callbackが飛んでくる
今度はCallシーケンスを洗って、どこでプチってるか確認します。
なお、曲再生中にMAX9722のShutdownピンを直接制御してみたところ、ゼロクロス付近ではノイズなし。ゼロクロスから離れていると少々プチノイズが出る感じとなりました。ゼロクロス検出無しのMute回路なので、ここはまあスペック通りかな。
外部MUTE制御サンプル
- 今回テストに使用した、PCM5102Aドライバを改造してMUTE信号をGPIO出力するサンプルを乗っけておきます。
- GPIO4にMUTE信号を出力します。Active Low出力なので、LでMUTE、Hでミュート解除になります。
- prepare時(MUTE解除)とclose時(MUTE)にMUTE制御が飛んできます。
diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c index 8ba322a00363..960d7b83e6ea --- a/sound/soc/codecs/pcm5102a.c +++ b/sound/soc/codecs/pcm5102a.c @@ -14,11 +14,42 @@ * General Public License for more details. */ #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/gpio.h> #include <sound/soc.h> +static int null_set_dai_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + + pr_debug("%s mute = %d\n", __FUNCTION__, mute); + + if (mute) { + gpio_set_value(4, 0); + } else { + gpio_set_value(4, 1); + } + + return 0; +} + +static struct snd_soc_dai_ops null_dai_ops = { + .digital_mute = null_set_dai_mute, +}; static struct snd_soc_dai_driver pcm5102a_dai = { .name = "pcm5102a-hifi", @@ -26,16 +57,20 @@ static struct snd_soc_dai_driver pcm5102a_dai = { .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE }, + .ops = &null_dai_ops, }; static struct snd_soc_codec_driver soc_codec_dev_pcm5102a; static int pcm5102a_probe(struct platform_device *pdev) { + gpio_request_one(4, GPIOF_OUT_INIT_LOW, "CODEC MUTE"); + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pcm5102a, &pcm5102a_dai, 1); }
- サンプルドライバではGPIO決めうちにしているけど、device treeで外部から制御させるように作ると良いかもしれない。
Raspberry Pi ZeroでRJフォーマットDACを鳴らす方法のメモ
概要
- TDA1545AやTDA1543AなどRJフォーマットを採用しているDACをRaspberry Piで鳴らす方法のメモです。
- NosPiDACでTDA1545Aを鳴らしたかったので、調査・検証してみました。
仕組み
- 通常ALSAのSoCドライバではdai linkを設定するdriverでPCMフォーマットを設定しているのでそこを直す
- Raspberry PiのI2S DAC出力を構成するドライバは下記の三種
- sound/soc/bcm/bcm2835-i2s.c (dai driver)
- sound/soc/bcm/hifiberry_dac.c (dai link driver)
- sound/soc/codecs/pcm5102a.c (codec driver)
- なので、hifiberry_dac.cを修正します。
注意事項
- Raspberry PiのI2Sドライバは再生ストリームのbit depthと出力bit depthを調整する機能がありません。
- 再生ストリームのbit depthが出力bit depthになってしまっているようです。
- RJ16bitのDACを使う場合には、再生bit depthを16bitにしてください。
- mpdなどで再生bit depthを16bit固定にしてあげるのが簡単です。
- /etc/mpd.confを下記のように設定 audio_output_format "*:16:*"
- RJ24bit / RJ32bitに関しては未確認です。
- RJ32bitはLJ設定32bit固定でも鳴りそうですね。
ソースDiff
diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c index ee9f13395354..221a8dc820b4 --- a/sound/soc/bcm/hifiberry_dac.c +++ b/sound/soc/bcm/hifiberry_dac.c @@ -53,7 +53,8 @@ static struct snd_soc_dai_link snd_rpi_hifiberry_dac_dai[] = { .codec_dai_name = "pcm5102a-hifi", .platform_name = "bcm2708-i2s.0", .codec_name = "pcm5102a-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + .dai_fmt = SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &snd_rpi_hifiberry_dac_ops, .init = snd_rpi_hifiberry_dac_init,
備考
Raspberry Pi ZeroのI2S DACとポップノイズの関係 その1 力技でポップノイズを抑制
概要
NosPiDAC Zeroなどで音楽を楽しんでいるときに気になるポップノイズについて調べたこと・やったことをメモ。
ポップノイズは再生・停止・曲間で発生します。
- 発生メカニズムが確定では無いですが、RPi ZeroのI2SドライバがI2Sのクロックを止めることから発生しているようです。
- 2018/07/31追記 クロックだけではなくTXONも影響してそう
- 本内容は暫定対処です。もっと良い対応方法が無いか引き続き研究中です。
I2Sクロック制御
ポップノイズ発生シーケンスおさらい
- ALSAからのcallbackを追っていきます
- 再生開始
- startup PCMブロックのEnable
- hw_params サンプリングレートを設定・ここでPLLやLRCLKの分周比を設定
- prepare FIFOクリア
- trigger start 一曲目再生 クロックオン ★ここでプチ音
- ここで曲送り
- trigger stop 一曲目停止 クロックオフ
- prepare FIFOクリア
- trigger start 二曲目再生 クロックオン ★ここでプチ音
- ここで再生停止
- trigger stop 二曲目停止 クロックオフ
- shutdown PCMブロックのDisable/クロックオフ
- 再生再開
- trigger stop 空うち
- startup PCMブロックのEnable
- hw_params サンプリングレートを設定・ここでPLLやLRCLKの分周比を設定
- prepare FIFOクリア
- trigger start 二曲目再生再開 クロックオン ★ここでプチ音
- trigger stop 二曲目停止 クロックオフ
- shutdown PCMブロックのDisable/クロックオフ
クロックを止まらないようにしてみる
- そんなわけで、I2Sがクロックを止めようとする制御を全部コメントアウトしてみる。
- ポイントはbcm2835_i2s_hw_paramsでTXON時にはreturn 0する処理をつぶすこと。これをやらないと、サンプリングレートが変わってもクロックを変更してくれません。
- デメリットは再生停止してもクロックを供給し続けるので、再生停止時の消費電力が上がります。
- また、TXON状態のままになるので、途中で録音しようとしてもエラーになりそう。
- 再生専用機なら問題は少ないかな?
- 現在このコードがじんそんさんのNosPiDAC Zero用 Moode Audioに適用されています。
diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index d5f73a8ab893..b2773fb1ce20 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -357,8 +357,8 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, */ regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg); - if (csreg & (BCM2835_I2S_TXON | BCM2835_I2S_RXON)) - return 0; +// if (csreg & (BCM2835_I2S_TXON | BCM2835_I2S_RXON)) +// return 0; data_length = params_width(params); data_delay = 0; @@ -652,17 +655,19 @@ static void bcm2835_i2s_stop(struct bcm2835_i2s_dev *dev, { uint32_t mask; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) mask = BCM2835_I2S_RXON; else mask = BCM2835_I2S_TXON; - regmap_update_bits(dev->i2s_regmap, - BCM2835_I2S_CS_A_REG, mask, 0); +// regmap_update_bits(dev->i2s_regmap, +// BCM2835_I2S_CS_A_REG, mask, 0); /* Stop also the clock when not SND_SOC_DAIFMT_CONT */ - if (!dai->active && !(dev->fmt & SND_SOC_DAIFMT_CONT)) - bcm2835_i2s_stop_clock(dev); +// if (!dai->active && !(dev->fmt & SND_SOC_DAIFMT_CONT)) +// bcm2835_i2s_stop_clock(dev); } @@ -735,14 +742,14 @@ static void bcm2835_i2s_shutdown(struct snd_pcm_substream *substream, return; /* Disable the module */ - regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, - BCM2835_I2S_EN, 0); +// regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, +// BCM2835_I2S_EN, 0); /* * Stopping clock is necessary, because stop does * not stop the clock when SND_SOC_DAIFMT_CONT */ - bcm2835_i2s_stop_clock(dev); +// bcm2835_i2s_stop_clock(dev); }
改造後シーケンスおさらい
- クロック停止処理削除
- 再生開始
- startup
- hw_param
- prepare
- trigger start 一曲目再生 クロックオン ★ここでプチ音
- ここで曲送り
- trigger stop 一曲目停止 クロック止めない
- prepare
- trigger start 二曲目再生
- ここで再生停止
- trigger stop 二曲目停止 クロック止めない
- shutdown クロック止めない
- 再生再開
- trigger stop 空うち
- startup PCMブロックのEnable
- hw_params サンプリングレートを設定・ここでPLLやLRCLKの分周比を設定
- prepare FIFOクリア
- trigger start 二曲目再生再開
- trigger stop 二曲目停止 クロック止めない
- shutdown クロック止めない
改造後シーケンス+rc.localで無音再生
無音再生の追加
- 最初の曲で出るポップノイズを抑制するため、起動中に無音再生することでI2Sのクロック出力を開始する試み
SoXのplayコマンドを使って、400HzのSine波を-100dB(無音までゲインを下げる)で再生する処理を追加してます。
以下をRPi MoodeAudio上で実行する
sudo apt update sudo apt install sox
- エディタでrc.localを開く
sudo vi /etc/rc.local
- exit 0の前あたりに下記を追加
/usr/bin/play -n synth 1 sine 400 gain -100 &
- SHIFT + ZZなどで保存して終了
シーケンス
- 事前に無音音声再生&クロック停止削除
- 無音再生開始
- startup
- hw_param
- prepare
- trigger start 無音再生 クロックオン ★ここでプチ音(無音再生なので軽微)
- trigger stop 無音再生停止
- shutdown クロック止めない
- 再生開始
- trigger stop 空うち
- startup PCMブロックのEnable
- hw_params サンプリングレートを設定・ここでPLLやLRCLKの分周比を設定
- prepare
- trigger start 一曲目再生
- trigger stop 一曲目停止 クロック止めない
- prepare
- trigger start 二曲目再生
- trigger stop 二曲目停止 クロック止めない
- shutdown クロック止めない
- 再生再開
- trigger stop 空うち
- startup PCMブロックのEnable
- hw_params サンプリングレートを設定・ここでPLLやLRCLKの分周比を設定
- prepare FIFOクリア
- trigger start 二曲目再生再開
- trigger stop 二曲目停止 クロック止めない
- shutdown クロック止めない
備考
- SND_SOC_DAIFMT_CONTでtrigger stopのクロック停止を抑制できそう。
- ただ、このフラグを立てるのはhifiberry_dac.cを直さなきゃいけないので、1ファイルの差し替えで済むので現行のままがお手軽かも。
NanoPi Neo2のビルド環境構築(公式サイトからToolchain取得)
概要
- 過去記事でNEO2用のビルド環境構築を解説したけど、MediafireからToolchainを持ってきたりでちょっと怪しい感じだったので、Linaroから直接Toolchainをとってきてビルドする手順を確認したのでメモします。
- Ubuntu 18.04LTS AMD64環境で確認しました。32bit環境は未確認
Build関連パッケージのインストール
- ビルドするならまずはbuild-essentialを入れる。gcc, g++, make, libc-devあたりを纏めてインストールしてくれる仮想パッケージ。
$ sudo apt install build-essential
Toolchainの取得と展開
- Linaroのサイトからツールチェインを取得。
- ポイントは6.x系を選ぶこと。7.x系からはABIが変わる?とかで互換性が無いとか。
- 取ってきて/opt以下にバラします。
$ wget https://releases.linaro.org/components/toolchain/binaries/6.4-2017.11/aarch64-linux-gnu/gcc-linaro-6.4.1-2017.11-x86_64_aarch64-linux-gnu.tar.xz $ sudo mkdir -p /opt/linaro/toolchain/ $ sudo tar xvf aarch64-linux-gnu/gcc-linaro-6.4.1-2017.11-x86_64_aarch64-linux-gnu.tar.xz -C /opt/linaro/toolchain/
- 未確認ですが、32bitだと下記をDLしてください。
https://releases.linaro.org/components/toolchain/binaries/6.4-2017.11/aarch64-linux-gnu/gcc-linaro-6.4.1-2017.11-i686_aarch64-linux-gnu.tar.xz
パスを通す
$ export PATH=/opt/linaro/toolchain/gcc-linaro-6.4.1-2017.11-x86_64_aarch64-linux-gnu/bin:$PATH
gitでカーネルを持ってきて、4.11ブランチをcheckout
- 公式カーネルの場合
$ git clone https://github.com/friendlyarm/linux.git
$ cd linux
$ git checkout sunxi-4.11.y
- 拙作Audioカーネルの場合
$ git clone https://github.com/tkztkztkz/linux.git
$ cd linux
$ git checkout npi-audio-4.11.y
ビルド
$ make sunxi_arm64_defconfig ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- $ make Image dtbs modules ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
モジュールを集める
$ make modules_install ARCH=arm64 INSTALL_MOD_PATH=./mod_root/ $ cd mod_root $ tar cvfz ../modules.tar.gz ./
ターゲットにコピー
- 出来上がったarch/arm64/boot/ImageをNanoPi NEO2の/bootにコピー
- dtbはarch/arm64/boot/dts/allwinner/あたりに生成されます。これも必要なものをコピー
- modules.tar.gzをターゲット(NEO2)のrootに展開。下記コマンドはNEO2上で実行すること。
$ sudo tar xvfz modules.tar.gz -C /
次回から
- パスを通してビルドしてターゲットにコピーするだけです。
- モジュールはカーネルのマイナーバージョンが同じなら2度目以降は全コピー不要。修正したものがあれば手動でコピーしてください。
moode audioのカーネルをクロスビルドする手順メモ
- moode audioで使用しているRaspbianのカーネルイメージをクロスビルドするにあたっていろいろハマったのでメモして置きます。
- Ubuntu 18.04LTS AMD64環境で確認
- ターゲットはRaspberry Pi Zero用。RPi3とか64bitの奴はツールチェインやビルドオプションが変わるはず。
1. toolchainとkernelをとってくる
git clone https://github.com/raspberrypi/tools git clone https://github.com/raspberrypi/linux
2. toolchainにパスを通す
$ vim rpisetup export PATH=`pwd`/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:$PATH export ARCH=arm export CROSS_COMPILE=arm-linux-gnueabihf-
って感じで環境変数を書いたファイルを作成して
source ./rpisetup
とかして読み込む。毎回コマンドラインでexportしても良いです。お好きな方法で。
3. kernel hashを探す
- まずはmoode audioのプロパティを見て使用しているカーネルを探す。
- https://github.com/moode-player/mosbuild
modbuild.properties ファイルの中身を見る
ここにKERNEL_HASHがある
4. kernel git hashを探す
- と、言うことで、rpi-firmwareからgit hashを探す
- github.com/Hexxeh/rpi-firmware/raw/${KERNEL_HASH}/git_hash を見る
上の例で言うと こんな感じ。 https://raw.githubusercontent.com/Hexxeh/rpi-firmware/171c962793f7a39a6798ce374d9d63ab0cbecf8c/git_hash
- 例えば、4.14.32+ のgit_hashはこんな感じ。
- b6e99accda7519a48dfd38992d31baefb56b0e10
5. rpi kernelを指定のバージョンでチェックアウトする
- git_hashのハッシュでcheckoutする。これでやっとmoode audioで使ってるバージョンのkernelが取得できる。
cd linux git checkout b6e99accda7519a48dfd38992d31baefb56b0e10
6. configを実機から持ってくる場合(任意)
- RPi実機でconfigsをロードしてconfig.gzをクロスビルド環境に持ってきておく
modprobe configs scp /proc/config.gz hoge とかで実機からビルドマシンに吸い上げる。 zcat config.gz > .config でlinuxディレクトリ配下に展開しておく
7. buildする
- あとはビルドするだけ
- .configを実機から持ってきてる場合はoldconfigで。デフォルト設定でビルドするならbcmrpi_defconfigで。
KERNEL=kernel make oldconfig or make bcmrpi_defconfig make -j8 zImage modules dtbs
編集履歴
NanoPi Neo2用 Volumio2
NanoPi Neo2 Volumio2 release
- NanoPi Neo2 I2S Audio Kernelを適用したVolumio2です。
- バージョンはv2.413を採用しています。
- 2018/1012追記
- ロット変更なのか、ブートローダを更新しないと起動しないNEO2があるようです。
- もし、動作しないようであれば、下記ツイートの暫定版をお試しください。
どうやら古いブートローダでは起動しないNanoPi NEO2が出回ってるっぽい。DRAMでも変わったのかな?
— __tkz__ (@__tkz__) October 12, 2018
拙作のNEO2用Volumio2が起動しないNEO2をお持ちの方は、次ツイートの暫定対策版をお試しください。
特徴
- I2S + MCLK出力可能
- I2S 16bit長(32fs固定)出力対応
- RJ 24bit(64fs)/ RJ 16bit(64fs)/ RJ 16bit(32fs)出力対応
- HiFiBerry DAC+ PRO or compatible対応
- AK4490/4495/4497/4493対応
- DACが対応していれば、768kHzや1536kHzの再生が可能
- 詳しくはNanoPi Neo2 I2S Audio Kernelを参照ください
既知の問題
- DSD to PCM変換でサンプリングレートが上がりすぎる
- I2Sの再生サンプリングレート上限が1536kHzとなっているため、DSD to PCM変換時の再生レートが高くなります。
- DSD64 352.8kHz
- DSD128 705.6kHz
- DSD256 1411.2kHz
- I2S Driver or Codec Driver側にて上限設定する方法を検討中です。
- I2Sの再生サンプリングレート上限が1536kHzとなっているため、DSD to PCM変換時の再生レートが高くなります。
- 高負荷時にカーネルクラッシュ
- mpdで高サンプリングレートにアップサンプリングしたり、DSD to PCM変換時に多く発生
- 暫定対応でクロックの上限を1.08GHzから816MHzに落としています。Core電圧1.1Vでは816MHzが安全とのこと。
- U-bootでの話題ですがこの辺に情報が。https://groups.google.com/forum/#!topic/linux-sunxi/t7WcMaB3OZY
- 再起動(reboot)でこける時がある
- Linux Kernel 4.14へのアップデート時に解消予定
- sdのレギュレータ制御不正
- 標準でsshdが有効になっていません
http://volumio.local/dev or http://ipaddress/dev
で開発者モードに入り有効化してください。
制約など
- 本Volumio2はNanoPi Neo2 I2S Audio Kernel評価用に作成したものです。
- Volumio2の使い方については他のサイトを参照ください。
- Volumio2への機能追加などをリクエストを頂いても基本的には対応できません。
- ビルド手順を下の方に書いてますので、ぜひいろいろカスタムしてみてください。
使い方
バイナリダウンロード
書き込みと起動
- windowsならrufus、linuxならddなどでSDカードにイメージを書き込んでください。
- 初回起動はSDカードのresizeが走るため2-10分程度かかります。途中で電源を落とさないようしてください。
動作モードの切り替え方
- デフォルトではI2S genericとなっています。
- その他のモードで使う場合には、dtbファイルを差し替えて機能の切り替えを行ってください。
- NanoPi Neo2のbootスクリプトは、defaultではsun50i-h5-nanopi-neo2.dtbで起動するので、sun50i-h5-nanopi-neo2.dtbへ上書きしてやるのが簡単です。
- 下記はNEO2にSSHで接続orシリアルコンソール時の差し替え例で、sun50i-h5-nanopi-neo2-i2s-generic.dtbを使う場合の設定方法です。
$cd /boot $ cp sun50i-h5-nanopi-neo2-i2s-generic.dtb sun50i-h5-nanopi-neo2.dtb
- dtbの種類と動作モードはNanoPi Neo2 Audio Kernelのdtbファイルと動作モードの紹介を参照のこと。
ソースコード
- Volumioビルドシステム
- https://github.com/tkztkztkz/Build
- platformの取得先を下記のリポジトリに変更
- Kernel/modulesバイナリイメージ
- https://github.com/tkztkztkz/nanopineo2-platform
- Kernel及びmodulesをAudio Kernelに差し替え
ビルド手順メモ
$ git clone https://github.com/tkztkztkz/Build.git $ cd Build $ sudo ./build.sh -b armv7 -d nanopineo2 -v 2.413
- Ubuntu 16.04LTSにてビルドを確認済みです。18.04LTSではビルドに失敗することを確認しています。
- ビルドに必要なパッケージはVolumioのドキュメントを参照ください。参考までにこちらでは下記を実行しました。
sudo apt install git squashfs-tools kpartx multistrap qemu-user-static samba debootstrap parted dosfstools qemu binfmt-support qemu-utils build-essential
NanoPi Neo2 I2S Audio Kernel alpha1 release
これは何?
- NanoPi Neo2用のカーネルにI2Sオーディオ関連のパッチを当てたものになります。
- カーネルのみのリリースとなります。音を出すにはSoXやmpdなどを自力で導入する必要があります。
手軽に音を出したい方は、本カーネルを適用したVolumio2を作成予定ですので、それまでお待ちください。
標準のカーネルに加えて下記の修正が施してあります
- 特定sampling resolutionで音が出ない問題の修正(24bitでノイズになるなど)
- MCLK出力の有効化
- 768/1536kHzのサンプリングレートに対応
- HifiBerry DAC+ PRO or 互換ボードに対応
- PCM Right Justified16/24bit出力に対応
- BCLK外部クロック駆動など特殊動作に対応
baseは4.11になります。
現在はalpha3にアップデート済みです。
ダウンロード・使い方
バイナリダウンロード
- githubにカーネル・dtb・モジュールを固めたものをPushしています。(alpha3へのリンクに差し替えました)
- https://github.com/tkztkztkz/nanopineo2-platform/raw/master/nanopineo2/kernel/npi_audio_kernel_1807_alpha3.zip
メーカ提供 UbuntuCoreの場合
- FriendlyArm提供のUbuntuCore ImageをSDに書き込む
- PC上でもターゲット上でも構わないので、/bootのImageを上記からダウンロードしたもので上書きする
- ターゲット上でmodulesを展開する
# tar xvfz npi_audio_modules_1807_alpha3.tgz -C / or $ sudo tar xvfz npi_audio_modules_1807_alpha3.tgz -C /
- 再起動でAudio Kernelに差し替わります
動作モードの切り替え方
- dtbファイルを差し替えて機能の切り替えを行ってください。
- NanoPi Neo2のbootスクリプトは、defaultではsun50i-h5-nanopi-neo2.dtbで起動するので、sun50i-h5-nanopi-neo2.dtbへ上書きしてやるのが簡単です。
$ cd /boot $ cp sun50i-h5-nanopi-neo2-i2s-generic.dtb sun50i-h5-nanopi-neo2.dtb
- dtbの種類と動作モードは下の方で説明していますのでご確認ください。
ソースコード
- https://github.com/tkztkztkz/linux
- ブランチ npi-audio-4.11.y
- ビルドしたタグ alpha1
制約など
- npi-configは実行しない方が良いです。dtbを書き換える項目を実行すると起動不可になる可能性があります。
- Linuxカーネルですので、自由にfork・改造などして頂いて構いません。
- 音楽再生ディストリビューションや独自ディストリビューションへの組み込みも歓迎します。作成されたディストリビューションを公開する際には、ご連絡頂けますと嬉しいです。カーネルデバッグの際に活用したいと思います。
dtbファイルと動作モードの紹介
通常利用向けdtb
- I2S Generic
sun50i-h5-nanopi-neo2-i2s-generic.dtb sun50i-h5-nanopi-neo2-i2s-generic_32fs.dtb
- I2S Generic + MCLK
- MCLK出力に対応します。MCLKはPA6に出力します。
- デフォルトは64fsは32bit長固定とします。16/24bit再生時、LSBは0パディングします。
- 32fsは16bit長固定とします。
- PCM179X/AK449XなどのMCLKが必要なI2S DACの接続に利用します。
- 出力されるMCLKの周波数とサンプリングレートの対応は以下の通りです。
サンプリングレート | MCLK周波数 |
---|---|
48/96/192/384kHz | 24.576MHz |
44.1/88.2/176.4/352.8kHz | 22.5792MHz |
768kHz | 49.152MHz |
1536kHz | 98.304MHz |
sun50i-h5-nanopi-neo2-i2s-generic_mclk.dtb sun50i-h5-nanopi-neo2-i2s-generic_mclk_32fs.dtb
- HiFiBerry DAC+ Pro or compatible
sun50i-h5-nanopi-neo2-i2s-dacpluspro.dtb sun50i-h5-nanopi-neo2-i2s-dacpluspro_slave.dtb
- PCM RJ16/RJ24bit
sun50i-h5-nanopi-neo2-pcm_rj16_32fs_mclk.dtb sun50i-h5-nanopi-neo2-pcm_rj16_64fs_mclk.dtb sun50i-h5-nanopi-neo2-pcm_rj24_64fs_mclk.dtb
実験向けdtb
- I2S CBM_CFS fixed clock mode 実験用
- 外部から固定BCLKを入力するモードです。
- 水晶発振器などを利用して、NanoPi Neo2及びDACのBCLKにクロックを入力してください。
- LRCLKはNanoPi NEO2にて生成します。
- MCLKは出力できません。
- 64fs固定です。(dtsを編集すれば32fs/48fsも設定可)
- 24.576MHz入力で32bit 384kHz固定
- 12.288MHz入力で32bit 192kHz固定
- mpdなどでリサンプリングを有効にして利用することを想定しています。
- クロックに合ったサンプリングレートで再生しない場合、音程が正しく出力されません。
sun50i-h5-nanopi-neo2-i2s-cbmcfs_bclkin.dtb
- I2S Generic + MCLK less than 100MHz 実験用
- MCLKに100MHz未満で設定可能な最大周波数を設定
- ES9018SでMCLKをNanoPi Neo2から入力する場合に使用します。
- I2C制御はしませんので、ES9018Sはデフォルト動作とさせるか外部マイコンで制御または、i2c-toolsなどで制御が必要です。
sun50i-h5-nanopi-neo2-i2s-generic_mclk_lt100m.dtb
- I2S Generic + MCLK less than 50MHz 実験用
- MCLKに50MHz未満で設定可能な最大周波数を設定
- PCM5102A/ES9023Pなどで、MCLKをNanoPi Neo2から入力する場合に使用します。
- MCLKのクロックによって音が変化するか実験するときにどうぞ
sun50i-h5-nanopi-neo2-i2s-generic_mclk_lt50m.dtb
今後の予定(あくまで予定です)
- Volumio2のNanoPi Neo2版提供(本カーネル導入済み)
- beta版ではbaseバージョンを最新の4.14にアップデート
- rt patchの取り込み
- オーディオフォーマット対応のリファクタリング
もしかしたらやるかも
- 外部I2S Master基板の製作とドライバ作成