8
6

More than 5 years have passed since last update.

NanoPi-NEO2 の I2SでMCLK出力 & 384kHz, 768kHz, 1536kHz, 8kHz対応

Last updated at Posted at 2018-01-13

概要

NanoPi-NEO2およびNanoPi-NEO Plus2 のI2S出力において下記を対応。

  • I2S MCLK の出力
  • PCM-384kHz, 768kHz, 1536kHz 出力
  • 24bit再生時のバグ(音小さいし割れる)対応
  • 8kHz再生時のバグ(16kHzで再生されてしまう)対応

大雑把な手順は、LinuxのKernelソース弄ってNanoPi-NEO2上でコンパイル。

成功するとPA6のピンからMCLKが出力されます。そして、768kHz 対応します。

image.png

NanoPi-NEO(Allwinner H3系)の場合は、H3のDatasheet上出力できません。
(が、もしかしたらこっそり繋がっている可能性は0では無いハズ)

関連シリーズ紹介

参考にさせて頂いたサイト

前提

対象マシーン 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

image.png

■ linux_4.14.0_20171212

image.png

手順

LinuxのカーネルコンパイルまでをNanoPi上でやってしまいます。
面倒なCrossCompile環境構築が不要ですが、その代わり時間かかります。
大体1時間~2時間くらい掛かりますが、一度コンパイルすれば、その後の差分コンパイルは最短2分程度からスタートです。

初期セットアップ

Official ROM Image を取得
nanopi-neo2_FriendlyCore-Xenial_4.14.0_20171208.img.zip

MicroSDに書き込み。NanoPi-NEO2起動して初期セットアップ

NanoPi-NEO2
timedatectl set-timezone Asia/Tokyo
apt update
apt upgrade

npi-config はまだ実行しない。(どうせDeviceTree弄るので)

カーネルソースの準備

KernelSourceがwgetだと取得困難になったので、Sambaで共有フォルダ作り転送する。

Sambaの準備

NanoPi-NEO2
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のソース取得&転送

linux_4.14.0_20171212.tar.gz

PCかなんかでダウンロードして、Samba経由でNanoPi-NEO2に転送し、解凍する。

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経由でもなんでもやりやすい方法で上書きします。

NanoPi-NEO2
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カーネルのコンパイル

NanoPi-NEO2
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も有功にしておく(笑

menuconfig
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]
NanoPi-NEO2
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系

image.png

正直、思ったより綺麗です。
Rise Time も良好では無いでしょうか。
ジッタも画像レベルではOKです(笑

48.0kHz系

image.png

画像上のジッタは 0.5ns くらいでしょうか。。。そこまでひどいクロックでは無さそうです。
ただし、オシロスコープ自体は 1Gsps ですので、観測限界を超えてます。

NanoPi-NEO2

44.1kHz系

image.png

48.0kHz系

image.png

352.8 kHz再生時

NanoPi-NEO2

LRCK

image.png

384kHz 再生時

NanoPi-NEO2

LRCK

image.png

768kHz再生時

NanoPi-NEO Plus2

MCLK

768kHz * 64fs = 49,152,000 [Hz] に対し、49.1453 [MHz]なので、0.0137%ほどのズレ。
オシロもついてきていないようで、波形の細かな部分は落ちてきています。

image.png

LRCKとBCK

ちゃんと、64fsで出ています。

image.png

LRCKとDATA

ちゃんと32bitぎっちり詰まっています♪♪
LRCK 768kHz は良いね!

image.png

1536kHz 再生時

NanoPi-NEO2

MCLK

image.png

オシロついていかず、完全にSine波です。。。

LRCK と BCK

image.png

LRCK と DATA

image.png

再生データは24bitなので、後半8bitは出てません。

hw_params

352.8 kHz再生時

NanoPi-NEO2
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再生時

NanoPi-NEO2
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再生時

NanoPi-NEO_Plus2
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再生時

NanoPi-NEO_Plus2
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への強制アップサンプリング指定が不要になりました。

■今まで

/etc/mpd.conf
audio_output {
        type            "alsa"
        name            "HanoHat PCM5102a"
        device          "hw:sndsun8ii2sdac,0"
        mixer_type      "software"
        format          "*:32:2"
        replay_gain_handler "software"
}

■これから

/etc/mpd.conf
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が増えるのは、良いね!

_72D3251s.jpg

スペックは、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が付きまといますが。

8
6
9

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6