概要
NanoPi-NEO2およびNanoPi-NEO Plus2 のI2S出力において下記を対応。
- I2S MCLK の出力
- PCM-384kHz, 768kHz, 1536kHz 出力
- 24bit再生時のバグ(音小さいし割れる)対応
- 8kHz再生時のバグ(16kHzで再生されてしまう)対応
大雑把な手順は、LinuxのKernelソース弄ってNanoPi-NEO2上でコンパイル。
成功するとPA6のピンからMCLKが出力されます。そして、768kHz 対応します。
NanoPi-NEO(Allwinner H3系)の場合は、H3のDatasheet上出力できません。
(が、もしかしたらこっそり繋がっている可能性は0では無いハズ)
関連シリーズ紹介
参考にさせて頂いたサイト
- Patchwork ALSA: Add rate defines for 352k8 and 384k
- NanoPi NEO2 I2S AUDIO でMCLKを出すメモ
- NanoPi NEO2 I2S AUDIO 24bit再生でNG メモ
- added: 384k playback support
- ASoC: bcm2835: Support additional samplerates up to 384kHz
前提
対象マシーン | NanoPi-NEO2 / NanoPi-NEO Plus2 / NanoPi-NEO Core2 |
クロスコンパイル環境 | 不要 |
Official Rom Image | nanopi-neo2_FriendlyCore-Xenial_4.14.0_20171208.img.zip |
Linux Kernel ver | Linux kernel source 4.14.0 |
nanopi-neo2_FriendlyCore-Xenial_4.14.0_20171208.img.zip で無効になったI2S
たぶん、4.11.2 → 4.14.0 の際のマージミスが原因です。。(汗
menuconfigで見ると、A10 I2S が有効になっていて、sun8i I2Sが無効になっています。
それと同時にPCM5102aも無効になっていると思われますので、DeviceTreeとのUnmatchでI2Sだめなのかも。。。
ソースは
arch/arm64/configs/sunxi_arm64_defconfig
の3551行目。
sound/soc/sunxi/Kconfig
をみると
select SND_SOC_GENERIC_DMAENGINE_PCM
select SND_SOC_PCM5102A
とあるので、合わせて修正すれば良いのですが未検証のため素直にmenuconfigします。。。
menuconfig での違いは以下の通り。
■ linux_4.11.2_20170707
■ linux_4.14.0_20171212
手順
LinuxのカーネルコンパイルまでをNanoPi上でやってしまいます。
面倒なCrossCompile環境構築が不要ですが、その代わり時間かかります。
大体1時間~2時間くらい掛かりますが、一度コンパイルすれば、その後の差分コンパイルは最短2分程度からスタートです。
初期セットアップ
Official ROM Image を取得
nanopi-neo2_FriendlyCore-Xenial_4.14.0_20171208.img.zip
MicroSDに書き込み。NanoPi-NEO2起動して初期セットアップ
timedatectl set-timezone Asia/Tokyo
apt update
apt upgrade
npi-config はまだ実行しない。(どうせDeviceTree弄るので)
カーネルソースの準備
KernelSourceがwgetだと取得困難になったので、Sambaで共有フォルダ作り転送する。
Sambaの準備
apt install samba
nano /etc/samba/smb.conf
----------------------------------------------------
・
・
・
・
↓末尾に追加
[Home]
comment = share folder
path = /root
public = yes
writable = yes
guest ok = yes
guest only = yes
create mode = 0777
directory mode = 0777
----------------------------------------------------
chmod 777 /root
systemctl enable smbd
systemctl start smbd
LinuxKernelのソース取得&転送
PCかなんかでダウンロードして、Samba経由でNanoPi-NEO2に転送し、解凍する。
cd ~
tar xf linux_4.14.0_20171212.tar.gz
mv linux linux_4.14.0_20171212
https://github.com/friendlyarm/linux.git
からgit cloneの方法もあるが、上記のほうが確実かな。
差分ファイル上書き
に差分ファイルだけをまとめたので、上記で展開したKernel sourceに上書き。
パッチ適用でも、Samba経由でもなんでもやりやすい方法で上書きします。
git clone https://github.com/blue777/NanoPi-NEO2-I2S_MCLK/
cp NanoPi-NEO2-I2S_MCLK/linux_4.14.0_20171212/* linux_4.14.0_20171212 -r
rm NanoPi-NEO2-I2S_MCLK -r
Linuxカーネルのコンパイル
apt-get install libncurses5-dev libncursesw5-dev bc
cd linux_4.14.0_20171212
touch .scmversion
make sunxi_arm64_defconfig
make menuconfig
なぜかI2Sが無効になったのでmenuconfigで
Allwinner A10 I2S Support → 無効化
Allwinner sun8i I2S Support → 有効化
したうえでコンパイル。
ついでに、iSCSI Initiator over TCP/IPも有功にしておく(笑
Device Drivers ---> [enter]
Sound card support ---> [enter]
Advanced Linux Sound Archtecture --> [enter]
ALSA for SoC audio support [enter]
Allwinner SoC Audio support ---> [enter]
< > Allwinner A10 I2S Support [n]
<*> Allwinner sun8i I2S Support [y]
-----
Device Drivers ---> [enter]
SCSI device support ---> [enter]
SCSI low-level drivers --> [y][enter]
<*> iSCSI Initiator over TCP/IP [y]
make -j4
mkdir /boot/old
mv /boot/Image /boot/old
mv /boot/*.dtb /boot/old
cp arch/arm64/boot/Image /boot/
cp arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi*.dtb /boot/
reboot
DeviceTree関係が更新されているので、再起動後あらためて、
npi-config で I2Sを有効化します。
解説
オリジナルソース(4.14.0)からの修正差分は以下の通り。
ほぼほぼ参考にさせて頂いた内容のままです。
MCLK出力対応と384kHz対応
ファイル毎に変更概要を書くと以下の感じ。
なお、I2Sの有効化は、MenuConfigで実施のためソース修正無し。
File | 変更 |
---|---|
arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi.dtsi | MCLK出力対応(DeviceTreeでPin変更) |
arch/arm64/boot/dts/allwinner/sunxi-h3-h5.dtsi | MCLK出力対応(DeviceTreeでPin変更) |
drivers/pinctrl/sunxi/pinctrl-sun50i-h5.c | MCLKピンファンクション定義追加 |
include/sound/pcm.h | 384kHz追加(ALSA側) |
sound/core/pcm_native.c | 384kHz追加(ALSA側) |
sound/soc/codecs/pcm5102a.c | 384kHz追加(DAC側) |
sound/soc/sunxi/sun8i-i2s.c | 384kHz追加(I2S出力部側)、24bit時にRightFitされる問題修正 |
DeviceTree周りの対応において、PA6が2.8 inch resistive touch screen LCD 240x320 for PiのタッチパネルのChipSelect用に使用されていますので、同時に有効化はできません。
DeviceTreeは大元で修正しているため、NanoPi-NEO2 / NanoPi-NEO Plus2 / NanoPi-NEO Core2 にまとめて対応できます。
768kHz対応
ファイル毎に変更概要を書くと以下の通りです。
File | 変更 |
---|---|
include/sound/pcm.h | 768kHz追加(ALSA側) |
sound/core/pcm_native.c | 768kHz追加(ALSA側) |
sound/soc/codecs/pcm5102a.c | 768kHz追加(DAC側) |
sound/soc/sunxi/sun8i-i2s.c | 768kHz追加(I2S出力部側)、MCLKを49MHz設定追加 |
基本的に768kHz系の定義を追加と、
MCLKが24MHzクラスだと、768kHz再生時に32fsとなってしまうため、16bit再生までしかできなくなります。
32bit再生したいので、768kHz 64fsとなる49MHzクラスとなるように修正します。
また、pcm5102aは、768kHz対応していませんが、とりあえず NanoPi-NEO2のI2S出力として768kHz出ればよいので pcm5102aのソースを弄っちゃいます。悪しからず。
1536 kHz, 8kHz 対応
8kHzは、MLCKの分周の問題で16kHz出力されていたのでついでに直します。
ファイル毎に変更概要を書くと以下の通りです。
File | 変更 |
---|---|
include/sound/pcm.h | オリジナル戻した(ALSA側) |
sound/core/pcm_native.c | オリジナルに戻した(ALSA側) |
sound/soc/codecs/pcm5102a.c | 1536kHz追加(DAC側) |
sound/soc/sunxi/sun8i-i2s.c | 1536kHz追加(I2S出力部側)、MCLK計算部をちゃんと実装 |
include/sound/pcm.hとsound/core/pcm_native.cは、ALSA開発チームが192kHzを超える周波数への対応をしないことを表明しているようですので、SNDRV_PCM_RATE_CONTINUOUS で対応するようにし、元の定義に戻しています。
再生周波数とMCLKの目標周波数は以下になっています。
Sampling freq. | MLCK target freq. |
---|---|
44.1k, 88.2k, 176.4k, 352.8k | 22,579,200 |
48k, 96k, 192k, 384k | 24,576,000 |
705.6k | 45,158,400 |
768k | 49,152,000 |
1411.2k | 90,316,800 |
1536k | 98,304,000 |
結果
MCLK
NanoPi-NEO Plus2
44.1kHz系
正直、思ったより綺麗です。
Rise Time も良好では無いでしょうか。
ジッタも画像レベルではOKです(笑
48.0kHz系
画像上のジッタは 0.5ns くらいでしょうか。。。そこまでひどいクロックでは無さそうです。
ただし、オシロスコープ自体は 1Gsps ですので、観測限界を超えてます。
NanoPi-NEO2
44.1kHz系
48.0kHz系
352.8 kHz再生時
NanoPi-NEO2
LRCK
384kHz 再生時
NanoPi-NEO2
LRCK
768kHz再生時
NanoPi-NEO Plus2
MCLK
768kHz * 64fs = 49,152,000 [Hz] に対し、49.1453 [MHz]なので、0.0137%ほどのズレ。
オシロもついてきていないようで、波形の細かな部分は落ちてきています。
LRCKとBCK
ちゃんと、64fsで出ています。
LRCKとDATA
ちゃんと32bitぎっちり詰まっています♪♪
LRCK 768kHz は良いね!
1536kHz 再生時
NanoPi-NEO2
MCLK
オシロついていかず、完全にSine波です。。。
LRCK と BCK
LRCK と DATA
再生データは24bitなので、後半8bitは出てません。
hw_params
352.8 kHz再生時
root@NanoPi-NEO2:~# cat /proc/asound/card0/pcm0p/sub0/hw_params
access: RW_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 352800 (352800/1)
period_size: 44100
buffer_size: 176400
384kHz再生時
root@NanoPi-NEO2:~# cat /proc/asound/card0/pcm0p/sub0/hw_params
access: RW_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 384000 (384000/1)
period_size: 48000
buffer_size: 192000
768 kHz再生時
root@NanoPi-NEO-Plus2:~# cat /proc/asound/card1/pcm0p/sub0/hw_params
access: RW_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 768000 (768000/1)
period_size: 32768
buffer_size: 131072
bufferサイズが384kHz時より小さくなっているのは気になりますが、音飛びしていないようなので保留。
1536kHz再生時
root@NanoPi-NEO-Plus2:~# cat /proc/asound/card1/pcm0p/sub0/hw_params
access: RW_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 1536000 (1536000/1)
period_size: 32768
buffer_size: 131072
ここまでくるとDSDかと錯覚させる領域。。。
でもPCMなんです!
mpd.conf
24bitが正しく処理できるようになったので、暫定対策として入れていた32bitへの強制アップサンプリング指定が不要になりました。
■今まで
audio_output {
type "alsa"
name "HanoHat PCM5102a"
device "hw:sndsun8ii2sdac,0"
mixer_type "software"
format "*:32:2"
replay_gain_handler "software"
}
■これから
audio_output {
type "alsa"
name "HanoHat PCM5102a"
device "hw:sndsun8ii2sdac,0"
mixer_type "none"
}
結果(DAC系)
PCM5102のMCLK入力
PCM5102はMCLKが入力されていない場合、内部でMCLKを自動生成しますが、あえて外部から入力してみました。
結果、わずかに分解能向上するようです。
ただし、これに関してはプラシーボの可能性もあります(笑
また、768kHzの信号入力に関しては、MCLKの外部入力・内部生成に関らず、いずれも再生不可(音でない)でした。
AK4495SEQ を使う
eBayで購入したAK4495SEQのI2S DACボード。
MCLKが必要で、BLCKと同期している必要があるため、ようやく使えるようになります。
使えるDACが増えるのは、良いね!
スペックは、PCM:768kHz 32bit、DSD: 2.8MHz, 5.6M になっています。
PCM 768kHzに関しては、すんなり音出ました。
AK4495SEQのDatasheet上、MCLKの49MHzにおいては対応できない場合(モード)もあると記載がありましたが、普通に音出てくれました。
DSDに関しては、Nanopi-NEOが素のDSD(AK4495がそのままで受け付けてくれる状態での)出力は無理なので、
DoPでI2Sして、I2SからDSDの変換基盤(LRCKに応じてデータを分配)を作れば大丈夫に思えます。
そしてなんと!PCM-1536kHzも音出るようです。
ただ、曲の冒頭でプチプチ言いますので、DAC側でのクロック検出に問題が生じているのかもしれません。
もちろん、正式サポート外ですので、自己責任で。
あと、8kHzは音出ませんでした。(笑
AK4495のサポート範囲は、あくまでも32kHz~768kHzです。
最後に
H5のDatasheetを見ると、
- AUDIO_PLLは、20MHz~200MHz
- I2Sは100MHz
と言っているので、実は768kHzも行けそうです。
この場合、
- LRCK = 768kHz
- BCK = LRCK * 32 * 2 = 49,152,000 Hz
- MCLK = BCK
が基準になります。
768kHz対応したので、書き直しです(笑
と言っているので、実は 1536kHzも行けそうです。
この場合、
- LRCK = 1536 kHz
- BCK = LRCK * 32 [bit] * 2[ch] = 98,304,000 Hz
- MCLK = BCK
が基準になります。
これが、NanoPi-NEOの対応限界となります。
おまけ
各ファイルフォーマットの仕様
(主にWikiより)
Format | Max frequency | Max bit depth |
---|---|---|
FLAC | 655.3 kHz | 32 bit |
ALAC | 384 kHz | 32 bit |
AAC | 96 kHz | ? |
mp3 | 48 kHz | ? |
.wav | 4.2 GHz | 65535 bit |
FLACで対応していないとなると、768 kHzは配信用としてはあまりなさそうですね。
完全にマスタリング用でしょうかね。
しかし、wavの対応範囲がすごいですね(笑
ただしファイルサイズ上限4GBが付きまといますが。