Raspberry Pi CM4とCSI-2接続HDMI入力基板で音も取る
mzyy94
by mzyy94
18 分間で読めます

カテゴリー

タグ

2年前に投稿したHDMI入力をRaspberry Piで取り込む記事では映像しか取得していませんでしたが、このHDMI入力基板には音声も取り込めるチップTC358743が搭載されています。 取り込める端子は購入したHDMI入力基板にもちゃんと用意されていたので、ピンヘッダを取り付けて信号を見たりしたものの、音声出力が正常に取得できませんでした。 この問題をあれこれ探し回って解決した記録を残しておきます。

目次

  1. HDMI入力基板で音声も取り出そうとした2020
  2. HDMI入力基板 H2C-RPI-B01とTC358743XBG
  3. I2S (Inter-IC Sound Bus)
  4. 音声を取り出す最初の挑戦(2020年4月)
    1. ハードウェアの配線
    2. Raspberry Pi OSのファームウェア設定
      1. Device Tree
      2. Device Tree Overlay
    3. 音声出力信号の取り込み
  5. 音声を取り出すリベンジ
    1. 足りない配線とI2S APLLパッチ
      1. ユニバーサル基板に実装
    2. 再度録音に挑戦
  6. reTerminalやCM4で使えるようにする
  7. まとめ

HDMI入力基板で音声も取り出そうとした2020

実は当時、ブログ記事を投稿する直前まで音声出力が正しく得られないかどうかを色々と試行錯誤していました。参考リンクにその調査に使ったリンクが一部残してあります。 しかし一筋縄ではいかず音声出力を得ることはできなかったため、その時に書いていた下書きをボツにしていました。 しばらくして解決したものの、記事を完成させるモチベーションもなくお蔵入りになる予定でしたが、ちょうどreTerminal拡張モジュールコンテストHDMI入力モジュールとして応募したこともあって、ゴミ箱から拾ってきて記事として完成させました。 なので内容としては2年前の記録になりますが、ブラッシュアップしてあります。

なお、当時はBullseyeベースの新しいRaspberry Pi OSは登場していなかったこともあり、この記事の内容は全てBusterベースのRaspberry Pi OSでの動作を記しています。また、本記事執筆時(2022/02/26)の最新版である以下の構成で動作確認をし直しています。

OS: Raspberry Pi OS

Raspberry Pi OS (Legacy) with desktop
Release date: January 28th 2022
ハードウェア: Raspberry Pi 4B

Hardware	: BCM2711
Revision	: c03112
Model		: Raspberry Pi 4 Model B Rev 1.2
カーネル: 5.10.63-v7l+

Linux raspberrypi 5.10.63-v7l+ #1496 SMP Wed Dec 1 15:58:56 GMT 2021 armv7l GNU/Linux
ファームウェア: Dec 1 2021 15:02:46

Dec  1 2021 15:02:46 
Copyright (c) 2012 Broadcom
version 71bd3109023a0c8575585ba87cbb374d2eeb038f (clean) (release) (start_x)


HDMI入力基板 H2C-RPI-B01とTC358743XBG

以前の記事で使ったHDMI入力基板、H2C-RPI-B01はRaspbianRaspberry Pi OSの標準ドライバで処理され、接続するだけでRaspberry Pi Camera Moduleと同様のV4L2デバイスとして認識され、映像入力を扱えました。 何もしなくても動いたのは良かったのですが、何もしなかったためにCamera Moduleと同様に映像しか扱えませんでした。

H2C-RPI-B01に搭載されているチップであるTC358743XBGは、実はHDMI音声入力が扱えます。データシートにはI2Sバス規格で音声データのやりとりをすると書かれています。

TC358743XBG_datasheet_en_20171026 p.1

引用元: TC358743XBG_datasheet_en_20171026.pdf TC358743XBG | HDMI® インターフェースブリッジ | 東芝デバイス&ストレージ株式会社 | 日本

I2S (Inter-IC Sound Bus)

I2SはInter-IC Soundという音声通信バス規格のことです。

I²S - Wikipedia

NXP Semiconductorsが1986年に仕様を定義したものですが、オリジナルの仕様書はインターネットの海に沈没してしまっていて、アーカイブしか見つけられません。

I2SBUS.pdf - Internet Archive

4つのピンでクロックとデータをやりとりするシリアルバス規格であり、日本語版Wikipediaの記事に要約が書かれています。

Inter-IC Sound - Wikipedia

Raspberry PiのGPIO端子は音声入力と出力の両方に対応しており、PCM_で始まるラベルのついているピン(GPIO 18,19,20,21)がI2Sです。

Raspberry Pi pinout

引用元: GPIO and the 40-pin Header - Raspberry Pi Documentation

音声を取り出す最初の挑戦(2020年4月)

I2Sのハードウェア接続とファームウェア設定を行い、音声の取り込みに挑戦していきます。

ハードウェアの配線

HDMI入力基板の出力ピンとRaspberry Pi 40ピンヘッダーのI2Sのピンとを接続します。

HDMI入力基板には10ピンの入出力端子を取り付けられるスルーホールが用意されています。 H2C-RPI-B01以外の類似品をいくつも買ってみましたが、同じTC358743XBGを搭載する基板には大抵あります。

HDMIボードピン

少し離れたところに各スルーホールの機能を記すシルクがありますが、それを参考にして下表の通り接続します。

HDMI入力基板シルク Raspberry Pi ピン番号 Raspberry Pi GPIO
SCK 12 PCM_CLK(GPIO 18)
WFS 35 PCM_FS(GPIO 19)
SD 38 PCM_DIN(GPIO 20)

Raspberry Pi OSのファームウェア設定

I2Sの配線を済ませただけでは音声入力を扱えないので、ファームウェアの設定とドライバのロードをさせます。

Device Tree

Linuxがドライバをロードする時、接続されているデバイス情報を元に適切なドライバを選択しています。 接続デバイスを管理するのがDevice Treeというハードウェア構成情報です。Device Treeは /proc/device-tree のprocファイルシステムを覗くと、だいたいどんなものが認識されているかがわかります。文献は以下に詳しいです。

TC358743のドライバであるmedia/i2c/tc358743.cは、次のようにデバイスを見つけてドライバの初期化(probe)を行います。

static const struct of_device_id tc358743_of_match[] = {
	{ .compatible = "toshiba,tc358743" },
	{},
};
MODULE_DEVICE_TABLE(of, tc358743_of_match);

linux/drivers/media/i2c/tc358743.c#L2255-L2259

compatibleに”toshiba,tc358743”と記載のあるデバイスがあれば、tc358743のドライバが読み込まれるということです。 ただ、何も設定をしていないRaspberry Pi OSではそのような記載のあるデバイスはなく、Camera Moduleのvc04_services/bcm2835-camera.cがドライバとして読み込まれてしまっています。

linux/bcm2835-camera.c at 1.20220120 · raspberrypi/linux

Camera Moduleのドライバではなく、TC358743のドライバであるmedia/i2c/tc358743.cをロードさせるために、Device Treeを上書きしてファームウェアを設定します。

Device Tree Overlay

Device Treeを上書きする機能の名はDevice Tree Overlay。そのまんまです。 RaspbianRaspberry Pi OSではこれを読み込むことで、Device Treeを上書きできます。 Raspberry Pi OSには、 /boot/overlays にDevice Tree Overlayの構成ファイル、Device Tree Blob Overlay(.dtbo)が格納されています。

firmware/boot/overlays at 1.20220120 · raspberrypi/firmware

Blobと名前に含まれるように、バイナリファイルにコンパイルされたものですが、これらのソースコードはraspberrypi/linuxの /arch/arm/boot/dts/overlays にあります。

linux/arch/arm/boot/dts/overlays at 1.20220120 · raspberrypi/linux

この中にtc358743向けのoverlayが存在し、次のように書かれています。

		__overlay__ {
			#address-cells = <1>;
			#size-cells = <0>;
			status = "okay";

			tc358743@0f {
				compatible = "toshiba,tc358743";
				reg = <0x0f>;
				status = "okay";

linux/tc358743-overlay.dts at 1.20220120 · raspberrypi/linux

compatible = "toshiba,tc358743";とあるので、このdtboを読み込めばtc358743がデバイスとして認識され、ドライバが読み込まれるということです。

ただ、これだけでは音声入力を扱うことはできません。 HDMI入力基板と音声をI2Sでやり取りするには、音声インターフェースのDevice Tree定義とドライバの読み込みが必要です。 TC358743XBGのI2S用の定義も、RaspbianRaspberry Pi OSのDevice Tree Overlayに用意されています。

linux/tc358743-audio-overlay.dts at 1.20220120 · raspberrypi/linux

これらのDevice Tree OverlayとI2Sを扱うパラメーター設定を/boot/config.txtに記述する方法を深く理解しながら/boot/config.txtに追記します。

dtparam=i2s=on
dtparam=audio=on
dtoverlay=tc358743
dtoverlay=tc358743-audio

これで再起動すると、lsmoddmesgmedia/i2c/tc358743.c のドライバーが読み込まれていることが確認できます。 overlayが正しく読み込まれているかどうかは、sudo vcdbg log msgなどで確認できます。

pi@raspberrypi:~ $ dmesg | grep tc358743
[    4.137243] tc358743 0-000f: tc358743 found @ 0x1e (bcm2835 I2C adapter)
pi@raspberrypi:~ $ lsmod | grep tc358743
tc358743               40960  1
v4l2_dv_timings        36864  2 bcm2835_unicam,tc358743
v4l2_fwnode            20480  2 bcm2835_unicam,tc358743
v4l2_common            16384  3 bcm2835_unicam,bcm2835_v4l2,tc358743
videodev              200704  9 bcm2835_unicam,v4l2_fwnode,bcm2835_codec,v4l2_common,videobuf2_common,bcm2835_v4l2,v4l2_mem2mem,videobuf2_v4l2,tc358743
media                  36864  5 bcm2835_unicam,bcm2835_codec,videodev,v4l2_mem2mem,tc358743
pi@raspberrypi:~ $ ls /dev/video*
/dev/video0  /dev/video10  /dev/video11  /dev/video12
pi@raspberrypi:~ $ 

音声出力信号の取り込み

ファームウェアとハードウェアの設定を済ませ、I2Sでの音声信号を取り出していきます。

TC358743は通常のI2Sオーディオデバイスとは違って、音声信号の制御などをCSI-2を通るI2Cで指示してあげる必要があります。 この制御に関してフォーラムに情報がありました。

HDMI to CSI-2 TC358743 I2S Audio - Raspberry Pi Forums

細かい操作はドライバでやってくれるので、v4l2で大体の設定をすれば良いようです。

pi@raspberrypi:~ $ wget https://raw.githubusercontent.com/mzyy94/ns-remote/master/720P30EDID.txt
pi@raspberrypi:~ $ v4l2-ctl --set-edid=file=720P30EDID.txt
pi@raspberrypi:~ $ v4l2-ctl --set-dv-bt-timings query

ここまでできたら、HDMIに接続しているデバイスから音声を出力してみると、v4l2-ctl --list-ctrlsのaudio_presentがvalue=1になってることが確認できるはずです。

I2S device detected

pi@raspberrypi:~ $ v4l2-ctl --list-ctrls

User Controls

            audio_sampling_rate 0x00981980 (int)    : min=0 max=768000 step=1 default=0 value=48000 flags=read-only
                  audio_present 0x00981981 (bool)   : default=0 value=1 flags=read-only

Digital Video Controls

                  power_present 0x00a00964 (bitmask): max=0x00000001 default=0x00000000 value=0x00000001 flags=read-only

この状態になったら、あとは取り込むだけ。ただ、いざI2Sオーディオ入力を録音しようと試みるも、一向にデータはやってきません。 そして何やらエラーが出ているようです。

pi@raspberrypi:~ $ sudo dmesg -C
pi@raspberrypi:~ $ arecord -D plughw:1 -c1 -r 48000 -f S32_LE -t wav -V mono rec.wav
Recording WAVE '/tmp/rec.wav' : Signed 32 bit Little Endian, Rate 48000 Hz, Mono
^CAborted by signal Interrupt...
arecord: pcm_read:2145: read error: Interrupted system call
pi@raspberrypi:~ $ dmesg
[  560.152152] bcm2835-i2s fe203000.i2s: I2S SYNC error!
pi@raspberrypi:~ $ 

I2Sのクロック周りで同期が取れないようなエラーです。オシロスコープでI2S信号を観測したところ、確かに波形がおかしく基板上に問題がありそうだということがわかったのです。

色々と試行錯誤していた時にオシロスコープを燃やしてしまったのでHDMI入力基板からの音声入力は諦め、UAC Gadget経由でお茶を濁すことにしたのでした。

音声を取り出すリベンジ

UAC Gadgetから音声入力をする記事でお茶を濁して数ヶ月経った頃、Raspberry Pi Forumsに類似品のHDMI入力基板で音声が取り込めない問題をハードウェア的にパッチを当てて解決する方法が投稿されました。

[UPDATED, SOLVED] Why “cheap” Chinese HDMI-to-CSI2 adapters (e.g.18810-1 C779) don’t provide I2S sound - Raspberry Pi Forums

これによってパッチを当てれば信号が得られるということがわかったので、試すことにしました。

足りない配線とI2S APLLパッチ

TC358743でI2S信号を正しく扱うための配線は、Functional Specificationなる仕様書に書かれているらしいのです。 「らしい」というのは、その仕様書は東芝とNDAを結ばないと手に入れられないもので、現物を確認できていないからです。

NDA下にある書類ということで、インターネットの海にはなかなか流れていなんですが、数字の末尾が3→9になった兄弟チップであるTC358749XBGの仕様書はFireflyが放流してくれています。

(U18)TC358749XBG_V074.pdf

これを参考にしてパッチを作っていきます。

Raspberry Pi Forumsの投稿によると、I2Sの信号がおかしいのは音声信号の位相同期回路(PLL)が実装されていないことによるとのこと。 このAudio PLLに関する機能仕様を兄弟チップのTC358749XBGの仕様書から探してみると、次のような回路を用意すればいいというのがわかりました。

APLL circuit schematic

抵抗値や静電容量は他のTC358シリーズの仕様をいくつも読み漁って推定したものです。

ユニバーサル基板に実装

先ほどの回路図のうち、C3とC6はH2C-RPI-B01に実装されているのでそれ以外の配線を行い、次のように配置しました。

APLL circuit board

これをユニバーサル基板に実装し、フォーラムにある類似基板の解析結果を参考にしながらH2C-RPI-B01につなげていきます。

patch circuit

patch on H2C-RPI-B01

再度録音に挑戦

前回の挑戦と同じくして、Device Tree Overlayの設定とv4l2の設定を済ませarecordで録音したところ、ちゃんとレベルメーターでも音声が入力していることを確認でき、きれいに録音されたファイルも出来上がって大成功でした。

re arecord

reTerminalやCM4で使えるようにする

Raspberry Pi 4Bで無事に録音できたので、さてケースに収めてreTerminalの拡張モジュールにするぞ!と意気込んだものの、CSI-2に通るI2Cがうまく通信できずにreTerminalでは動作してくれませんでした。

tc358743-load-failed

pi@raspberrypi:~ $ dmesg | grep tc3
[   10.534939] tc358743 10-000f: i2c_rd: reading register 0x0 from 0xf failed
[   10.534957] tc358743 10-000f: not a TC358743 on address 0x1e

I2Cの設定を変えてみたりエラーメッセージやCompute Module特有の2つのCSI-2について調べてみたりすると、ずばり解決につながるフォーラムの投稿に行き当たりました。

Two B102 TC358743 simultaneously on CM4 - Raspberry Pi Forums

CM3/CM4ではMIPI CSI-2のバスが二つあり、そのうちCSI0で動作させるにはDevice TreeのI2Cバスを変更する必要があるとのことでした。 フォーラムの投稿はちょっと古いので最新のファームウェアに合うように修正してみたところ、ちゃんと認識され録音できるようになりました。 パッチはGitHubにおいておきました。

reTerminal-HDMI-input/overlays at master · mzyy94/reTerminal-HDMI-input

まとめ

やっとこれでHDMI入力拡張モジュールとして機能する形にできました。今回の成果も以下のリポジトリでまとめておいたので、興味ある物好きな人は参考にどうぞ。

mzyy94/reTerminal-HDMI-input: HDMI input expansion module for reTerminal

ちなみにこのパッチが組み込まれた音声も取れる格安HDMI入力基板が今年の1月に発売されていたことを、今まさにこの記事を書いている最中に知りました。 少しばかり高いですが、わざわざAPLLパッチを作る必要はありません。これまでの苦労とは一体。。。:sob:

bought-x630

南無

Amazon | Geekworm Raspberry Pi Hdmi to CSI-2 (Hdmi入力の最大1080p/25fps)X630 拡張ボード、Raspberry Pi 4B/3B+/3B/Pi Zero/Zero Wに適用 | Geekworm | ベアボーンPC 通販

Hdmi対応にCSI 2モジュール、X630 hdmi CSI 2のためのラズベリーパイ4B/3B +/3B/パイゼロ|Demo Board Accessories| - AliExpress