Jetson Orin Nanoのカーネルビルド環境(TC358743基板に対応)

## はじめに

今回は、以下の基板をJetson Orin Nanoに接続して画像を取得できるように、Linuxカーネルの
カスタマイズを行ってみたいと思います。

![TC358743基板.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/998321/c53fa9ab-42f6-0483-0cb7-e0066368a223.jpeg)

この基板、2020年7月頃にJetson Nanoに接続して試用していたものを引っ張り出して来ました。
[Mzyy94さん](https://www.mzyy94.com/)の以下のページでも紹介されているものです。
搭載されているのは、TOSHIBAさんのTC358743という、HDMI to MIPI-CSI2 ブリッジチップです。

[HDMI入力をRaspberry Piで駆使する | 犬アイコンのみっきー](https://www.mzyy94.com/blog/2020/04/10/raspberrypi-hdmi-input/)

まず、物理的に接続するには、別記事[「Jetson Orin Nanoの使い始め(カメラ導入編)」](https://qiita.com/MakotoA67/items/a0be9753f3fe53899a45)でも紹介しました、[15-pin to 22-pin conversion cable(15ピン-22ピン変換ケーブル)](https://amzn.to/3vqE1uJ)が必要となります。

![JetsonOrinNanoとTC358743基板.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/998321/1606ac40-2010-99c7-f52e-e2b61a1f336d.jpeg)

これで、Jetson Orin NanoとTC358743基板とは物理的には接続できました。また、TC358743基板のHDMIのコネクタで、Windows PCとHDMIケーブルで接続しています。

少し前に、**R35.4.1**でも動作確認していたのですが、紹介するのが遅れているうちに、JetPack 5.1.3 (L4T **R35.5.0**)が2/23にリリースされていました。なので、どうせなら、ということで、その新しいバージョンで動作確認をしました。

<details><summary>JetPack 5.1.3のセットアップについて</summary>

別記事[「Jetson Orin Nanoの使い始め(初期セットアップ編)」](https://qiita.com/MakotoA67/items/a4156d87fcfc5f621722)に書きましたが、R35.5.0以前の環境から、R35.5.0にアップデートに、SD Card Methodにてセットアップすると、中途半端な状態になるようなので、最初は、SDK Manager Methodでセットアップして下さい。

</details>

そして、NVIDIA Developer Forumの以下のスレッドにて、TC358743を用いたキャプチャについて議論がされておりましたので、そこにアップされているソースファイルを使用します。

https://forums.developer.nvidia.com/t/orin-nano-and-tc358743-capture-issue/271644

## カーネルのビルド環境構築

Jetson Nanoにて色々検討していた時代は、NVIDIAやJetsonHacksのページに沿って、自分なりにアレンジした形で手動でmakeしていましたが、今回、[@kitazakiさん](https://qiita.com/kitazaki)などが使っておられた[buildKernelAndModules](https://github.com/JetsonHacksNano/buildKernelAndModules)というツールが気に入って私も使うようになりましたので、それベースで説明してみます。

まず、デフォルトの状態を確認しておきましょう。

```
$ uname -a
Linux orin-nano-dev-02 5.10.192-tegra #1 SMP PREEMPT Mon Feb 19 20:19:53 PST 2024 aarch64 aarch64 aarch64 GNU/Linux
$ cat /etc/nv_tegra_release
# R35 (release), REVISION: 5.0, GCID: 35550185, BOARD: t186ref, EABI: aarch64, DATE: Tue Feb 20 04:46:31 UTC 2024
```

**R35.5.0**であることがわかります。

```
$ sudo dmesg |grep imx
[   15.639801] imx219 9-0010: tegracam sensor driver:imx219_v2.0.6
[   15.651393] imx219 9-0010: imx219_board_setup: error during i2c read probe (-121)
[   15.667298] imx219 9-0010: board setup failed
[   15.673491] imx219: probe of 9-0010 failed with error -121
[   15.680012] imx219 10-0010: tegracam sensor driver:imx219_v2.0.6
[   15.694740] imx219 10-0010: imx219_board_setup: error during i2c read probe (-121)
[   15.719616] imx219 10-0010: board setup failed
[   15.736129] imx219: probe of 10-0010 failed with error -121
```

ブート時のログを確認すると、上記のように、2つのカメラコネクタ(J20:CAM0, J21:CAM1)のどちらに対しても、imx219の検知処理が動作する状態になっています。

ここから、Linuxカーネルのカスタマイズするために、そのビルド環境を用意します。

### ツールの取得

[buildKernelAndModules](https://github.com/JetsonHacksNano/buildKernelAndModules)ツールをgitにて取得します。(~/work/gitの下でgit cloneしたとします)

```shell
$ git clone https://github.com/JetsonHacksNano/buildKernelAndModules
Cloning into 'buildKernelAndModules'...
remote: Enumerating objects: 149, done.
remote: Counting objects: 100% (35/35), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 149 (delta 30), reused 26 (delta 26), pack-reused 114
Receiving objects: 100% (149/149), 41.24 KiB | 2.42 MiB/s, done.
Resolving deltas: 100% (91/91), done.$ cd buildKernelAndModules/
```

### スクリプトファイルの若干の変更

L4T **R35.1.0**までしか対応していないようなので、最新の環境に対応するため、若干、スクリプトファイルを変更します。変更するファイルは以下の2つです。

* scripts/jetson_variables
* scripts/getKernelSources.sh

```
$ cd buildKernelAndModules/
$ cp -p scripts/jetson_variables scripts/jetson_variables.org
$ vi scripts/jetson_variables
$ diff scripts/jetson_variables scripts/jetson_variables.org
33,34d32
<         "35.5.0") JETSON_JETPACK="5.1.3" ;;
<         "35.4.1") JETSON_JETPACK="5.1.2" ;;
$ cp -p scripts/getKernelSources.sh scripts/getKernelSources.sh.org
$ vi scripts/getKernelSources.sh
$ diff scripts/getKernel
Sources.sh scripts/getKernelSources.sh.org
23,24d22
<   ["35.5.0"]="https://developer.nvidia.com/embedded/l4t/r35_release_v5.0/sources/public_sources.tbz2"
<   ["35.4.1"]="https://developer.nvidia.com/embedded/l4t/r35_release_v4.1/sources/public_sources.tbz2"
```

ここでは、一応、**R35.4.1**と**R35.5.0**の2つのバージョンに対する記述を追加していますが、/etc/nv_tegra_releaseが参照されて、それに対応されるソースファイルがダウンロードされるようになっていますので、現在使用しているJetson Orin Nanoにて使用しているバージョンの**R35.5.0**に対応する行だけ追加しても大丈夫です。

あと、ソースファイル一式が置かれている場所をURLで記述している形ですが、今までも置き場所がちょこちょこと変わっていますので、今後、また新しいバージョンで使うときには、その変更に合わせてURLを追加していく必要があるかもしれません。(例えば、今、JetPack 6.0 DPというバージョンがありますが、このバージョンでは、カーネルモジュールなどが別ファイルに分かれていたりするので、そのままではだめ、など。)

### ソースファイル一式の取得

実際にスクリプトを実行してソースファイル一式をダウンロードします。

```
$ ./getKernelSources.sh

Jetpack 5.1.3 [L4T 35.5.0]
Kernel Release: 5.10
Placing kernel source into /usr/src/
...略...
nvcommon_build.sh
nvbuild.sh
/usr/src/kernel/kernel-5.10
```

また、[「はじめに」](https://qiita.com/drafts#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)で予告した通り、ソースコードは、Forumにアップされていたもの(**tc358743-orin.zip**)を使います。~/work/の下に置いたとして、

```
$ cd ~/work/
$ unzip tc358743-orin.zip
$ sudo cp -p tc358743-orin/tc358743.c /usr/src/kernel/kernel-5.10/drivers/media/i2c/
$ sudo cp -p tc358743-orin/tc358743_regs.h /usr/src/kernel/kernel-5.10/drivers/media/i2c/
$ sudo cp -p tc358743-orin/tc358743.h /usr/src/kernel/kernel-5.10/include/media/i2c/
$ cd ~/work/git/buildKernelAndModules/
```

などと、getKernelSources.shによって配置されたソースツリー内にて、それぞれのファイルの存在する場所にコピーします。

### カーネルのカスタマイズ

次に、カーネルのカスタマイズに進みます。通常のカスタマイズでは、以下のように**editConfig.sh**を使用してメニューから必要なカスタマイズを選択することになります。スクリプトの内部では`make menuconfig`が実行されます。

```
$ ./editConfig.sh
```

ただし、今回は、TC358743のドライバを有効にしようとしていますが、上記の方法で表示されるメニューにはTC358743向けの項目は(多分)現れないようなので、**その代わりに**、次のように、手動で.configを編集する方法を採ります。

```
$ cd /usr/src/kernel/kernel-5.10/
$ sudo cp -p .config .config.org
$ sudo vi .config
$ diff .config .config.org
4625c4625
< CONFIG_VIDEO_TC358743=m
---
> # CONFIG_VIDEO_TC358743 is not set
$ cd ~/work/git/buildKernelAndModules/
```

上記のdiffの結果のように、`CONFIG_VIDEO_TC358743=m`とすることで、TC358743用のドライバを有効にしています。`=y`はスタティックにカーネルに組み込むのに対して、`=m`は動的にロード/アンロードできるようにカーネルモジュールとしての形態とすることを意味します。

### カーネルのビルド

次に、カーネルのビルドに進みます。

ここで、デフォルト状態でそのままカーネルのビルドに進むと、途中で、

```
scripts/extract-cert.c:21:10: fatal error: openssl/bio.h: そのようなファイルやディレクトリはありません
   21 | #include <openssl/bio.h>
      |          ^~~~~~~~~~~~~~~
compilation terminated.

```

などとエラーになりますので、先に、以下のように、**libssl-dev**をインストールします。

```
$ sudo apt install libssl-dev
```

ようやく、**makeKernel.sh**スクリプトを用いてカーネルのビルドを実行します。途中で、コンフィグを変更したことにより、いくつか質問されますが、ENTERキーを押しておけば大丈夫です。

```
$ ./makeKernels.sh
Proposed source path: /usr/src/kernel/kernel-5.10
Source Target: /usr/src/
  SYNC    include/config/auto.conf.cmd
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/confdata.o
  HOSTCC  scripts/kconfig/expr.o
  LEX     scripts/kconfig/lexer.lex.c
  YACC    scripts/kconfig/parser.tab.[ch]
  HOSTCC  scripts/kconfig/preprocess.o
  HOSTCC  scripts/kconfig/symbol.o
  HOSTCC  scripts/kconfig/util.o
  HOSTCC  scripts/kconfig/lexer.lex.o
  HOSTCC  scripts/kconfig/parser.tab.o
  HOSTLD  scripts/kconfig/conf
*
* Restart config...
*
*
* Video decoders
*
Analog Devices ADV7180 decoder (VIDEO_ADV7180) [N/m/y/?] n
Analog Devices ADV7183 decoder (VIDEO_ADV7183) [N/m/y/?] n
Analog Devices ADV748x decoder (VIDEO_ADV748X) [N/m/y/?] n
Analog Devices ADV7604 decoder (VIDEO_ADV7604) [N/m/y/?] n
Analog Devices ADV7842 decoder (VIDEO_ADV7842) [N/m/y/?] n
BT819A VideoStream decoder (VIDEO_BT819) [N/m/y/?] n
BT856 VideoStream decoder (VIDEO_BT856) [N/m/y/?] n
BT866 VideoStream decoder (VIDEO_BT866) [N/m/y/?] n
KS0127 video decoder (VIDEO_KS0127) [N/m/y/?] n
OKI ML86V7667 video decoder (VIDEO_ML86V7667) [N/m/y/?] n
Philips SAA7110 video decoder (VIDEO_SAA7110) [N/m/y/?] n
Philips SAA7111/3/4/5 video decoders (VIDEO_SAA711X) [N/m/y/?] n
Toshiba TC358743 decoder (VIDEO_TC358743) [M/n/y/?] m
  Enable Toshiba TC358743 CEC support (VIDEO_TC358743_CEC) [N/y/?] (NEW)
Texas Instruments TVP514x video decoder (VIDEO_TVP514X) [N/m/y/?] n
Texas Instruments TVP5150 video decoder (VIDEO_TVP5150) [N/m/y/?] n
Texas Instruments TVP7002 video decoder (VIDEO_TVP7002) [N/m/y/?] n
Techwell TW2804 multiple video decoder (VIDEO_TW2804) [N/m/y/?] n
Techwell TW9903 video decoder (VIDEO_TW9903) [N/m/y/?] n
Techwell TW9906 video decoder (VIDEO_TW9906) [N/m/y/?] n
Techwell TW9910 video decoder (VIDEO_TW9910) [N/m/y/?] n
vpx3220a, vpx3216b & vpx3214c video decoders (VIDEO_VPX3220) [N/m/y/?] n
Maxim MAX9286 GMSL deserializer support (VIDEO_MAX9286) [N/m/y/?] n
*
* Video and audio decoders
*
Philips SAA7171/3/4 audio/video decoders (VIDEO_SAA717X) [N/m/y/?] n
Conexant CX2584x audio/video decoders (VIDEO_CX25840) [N/m/y/?] n
  WRAP    arch/arm64/include/generated/uapi/asm/kvm_para.h
  WRAP    arch/arm64/include/generated/uapi/asm/errno.h
  WRAP    arch/arm64/include/generated/uapi/asm/ioctl.h
  WRAP    arch/arm64/include/generated/uapi/asm/ioctls.h
  WRAP    arch/arm64/include/generated/uapi/asm/ipcbuf.h
  WRAP    arch/arm64/include/generated/uapi/asm/msgbuf.h
  WRAP    arch/arm64/include/generated/uapi/asm/poll.h
  WRAP    arch/arm64/include/generated/uapi/asm/resource.h
  WRAP    arch/arm64/include/generated/uapi/asm/sembuf.h
  WRAP    arch/arm64/include/generated/uapi/asm/shmbuf.h
  WRAP    arch/arm64/include/generated/uapi/asm/siginfo.h
  WRAP    arch/arm64/include/generated/uapi/asm/socket.h
  WRAP    arch/arm64/include/generated/uapi/asm/sockios.h
  WRAP    arch/arm64/include/generated/uapi/asm/stat.h
  WRAP    arch/arm64/include/generated/uapi/asm/swab.h
  WRAP    arch/arm64/include/generated/uapi/asm/termbits.h
  WRAP    arch/arm64/include/generated/uapi/asm/termios.h
  WRAP    arch/arm64/include/generated/uapi/asm/types.h
  WRAP    arch/arm64/include/generated/asm/early_ioremap.h
  WRAP    arch/arm64/include/generated/asm/mcs_spinlock.h
  WRAP    arch/arm64/include/generated/asm/qrwlock.h
  WRAP    arch/arm64/include/generated/asm/qspinlock.h
  WRAP    arch/arm64/include/generated/asm/set_memory.h
  WRAP    arch/arm64/include/generated/asm/user.h
  WRAP    arch/arm64/include/generated/asm/bugs.h
  WRAP    arch/arm64/include/generated/asm/delay.h
  WRAP    arch/arm64/include/generated/asm/div64.h
  WRAP    arch/arm64/include/generated/asm/dma-mapping.h
  WRAP    arch/arm64/include/generated/asm/dma.h
  WRAP    arch/arm64/include/generated/asm/emergency-restart.h
  WRAP    arch/arm64/include/generated/asm/hw_irq.h
  WRAP    arch/arm64/include/generated/asm/irq_regs.h
  UPD     include/config/kernel.release
  WRAP    arch/arm64/include/generated/asm/kdebug.h
  WRAP    arch/arm64/include/generated/asm/kmap_types.h
  UPD     include/generated/uapi/linux/version.h
  WRAP    arch/arm64/include/generated/asm/local.h
  WRAP    arch/arm64/include/generated/asm/local64.h
  WRAP    arch/arm64/include/generated/asm/mm-arch-hooks.h
  WRAP    arch/arm64/include/generated/asm/mmiowb.h
  WRAP    arch/arm64/include/generated/asm/msi.h
  WRAP    arch/arm64/include/generated/asm/rwonce.h
  WRAP    arch/arm64/include/generated/asm/switch_to.h
  WRAP    arch/arm64/include/generated/asm/serial.h
  WRAP    arch/arm64/include/generated/asm/unaligned.h
  WRAP    arch/arm64/include/generated/asm/vga.h
  UPD     include/generated/utsrelease.h
  HOSTCC  scripts/dtc/dtc.o
  HOSTCC  scripts/dtc/flattree.o
  HOSTCC  scripts/dtc/fstree.o
  HOSTCC  scripts/dtc/data.o
  HOSTCC  scripts/dtc/livetree.o
  HOSTCC  scripts/dtc/treesource.o
  HOSTCC  scripts/dtc/srcpos.o
  HOSTCC  scripts/dtc/checks.o
  HOSTCC  scripts/dtc/util.o
  LEX     scripts/dtc/dtc-lexer.lex.c
  YACC    scripts/dtc/dtc-parser.tab.[ch]
  HOSTCC  scripts/dtc/dtc-lexer.lex.o
  HOSTCC  scripts/dtc/dtc-parser.tab.o
  HOSTLD  scripts/dtc/dtc
  HOSTCC  scripts/kallsyms
  HOSTCC  scripts/sorttable
  HOSTCC  scripts/asn1_compiler
  HOSTCC  scripts/genksyms/genksyms.o
  HOSTCC  scripts/selinux/genheaders/genheaders
  HOSTCC  scripts/selinux/mdp/mdp
  YACC    scripts/genksyms/parse.tab.[ch]
  LEX     scripts/genksyms/lex.lex.c
  HOSTCC  scripts/genksyms/parse.tab.o
  HOSTCC  scripts/genksyms/lex.lex.o
  HOSTCC  scripts/sign-file
  HOSTCC  scripts/extract-cert
...(中略)...
  CC      drivers/platform/tegra/clocks-config.o
  CC      drivers/platform/tegra/tegra-fsicom.o
  CC      drivers/platform/tegra/tegra-epl.o
  CC      drivers/platform/tegra/tegra-uss-io-proxy.o
  AR      drivers/platform/tegra/built-in.a
  AR      drivers/platform/built-in.a
  AR      drivers/built-in.a
  GEN     .version
  CHK     include/generated/compile.h
  LD      vmlinux.o
  MODPOST vmlinux.symvers
  MODINFO modules.builtin.modinfo
  GEN     modules.builtin
  LD      .tmp_vmlinux.kallsyms1
  KSYMS   .tmp_vmlinux.kallsyms1.S
  AS      .tmp_vmlinux.kallsyms1.S
  LD      .tmp_vmlinux.kallsyms2
  KSYMS   .tmp_vmlinux.kallsyms2.S
  AS      .tmp_vmlinux.kallsyms2.S
  LD      vmlinux
  SORTTAB vmlinux
  SYSMAP  System.map
  OBJCOPY arch/arm64/boot/Image

real    22m37.174s
user    90m29.109s
sys     11m33.879s
Image make successful
Image file is here:
/usr/src/kernel/kernel-5.10/arch/arm64/boot/Image
```

しばらく時間はかかりますが、カーネルイメージのファイルがどこに出力されたかのメッセージが表示されてビルドは完了します。

### カーネルイメージのインストール

次に、元のカーネルイメージをバックアップしつつ、**copyImage.sh**を用いて、ビルドしたイメージをシステム領域にコピーします。

```
$ sudo cp -p /boot/Image /boot/Image.org
$ ./copyImage.sh
```

### カーネルモジュールのビルド及びインストール

次に、カーネルモジュールのビルドに進みます。**makeModules.sh**を使用しますが、このスクリプトは、makeKernel.shとは異なり、いきなりシステム領域にコピーしてしまうので、ここでは、カーネルモジュールもディレクトリごとバックアップした上で、makeModules.shを実行しておきます。

```
$ sudo cp -rp /lib/modules/5.10.192-tegra /lib/modules/5.10.192-tegra.org
$ ./makeModules.sh
Proposed source path: /usr/src/kernel/kernel-5.10
Source Target: /usr/src/
  CALL    scripts/atomic/check-atomics.sh
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  CC [M]  fs/quota/quota_v2.o
  CC [M]  arch/arm64/crypto/sha1-ce-glue.o
  AS [M]  arch/arm64/crypto/sha1-ce-core.o
  CC [M]  fs/quota/quota_tree.o
...(中略)...
  LD [M]  sound/soc/tegra/snd-soc-tegra210-ope.ko
  LD [M]  sound/soc/tegra/snd-soc-tegra210-sfc.ko
  LD [M]  sound/tegra-safety-audio/safety-i2s.ko

real    34m20.617s
user    132m3.403s
sys     17m47.919s
Modules make successful
  INSTALL arch/arm64/crypto/aes-arm64.ko
  INSTALL arch/arm64/crypto/aes-ce-blk.ko
  INSTALL arch/arm64/crypto/aes-ce-ccm.ko
...(中略)...
  INSTALL sound/soc/tegra/snd-soc-tegra210-ope.ko
  INSTALL sound/soc/tegra/snd-soc-tegra210-sfc.ko
  INSTALL sound/tegra-safety-audio/safety-i2s.ko
  DEPMOD  5.10.192-tegra
```

ここで一旦リブートしておきます。

```
$ sudo reboot
```

unameで確認すると、以下のように、今、ビルドしたものでブートしていることがわかります。

```
$ uname -a
Linux orin-nano-dev-02 5.10.192-tegra #1 SMP PREEMPT Mon Mar 4 10:23:39 JST 2024 aarch64 aarch64 aarch64 GNU/Linux
```

今回、**TC358743**のカーネルモジュールを追加しましたので、以下のように、**tc358743.ko**が生成され、システム領域に配置されています。(makeModules.shにて)

```
$ ls -las /lib/modules/5.10.192-tegra/kernel/drivers/media/i2c/tc358743.ko
804 -rw-r--r-- 1 root root 822689  3月  4 11:56 /lib/modules/5.10.192-tegra/kernel/drivers/media/i2c/tc358743.ko
```

カーネルモジュールtc358743.koをインストールしたわけですが、この時点ではまだ、dmesgなどで確認しても、上で最初に確認したデフォルトの状態と同じく、**imx219**の検知処理が動いている状態のままです。

```
$ sudo dmesg |grep imx
[   17.483366] imx219 9-0010: tegracam sensor driver:imx219_v2.0.6
[   17.505398] imx219 9-0010: imx219_board_setup: error during i2c read probe (-121)
[   17.519361] imx219 9-0010: board setup failed
[   17.523958] imx219: probe of 9-0010 failed with error -121
[   17.529991] imx219 10-0010: tegracam sensor driver:imx219_v2.0.6
[   17.546893] imx219 10-0010: imx219_board_setup: error during i2c read probe (-121)
[   17.559813] imx219 10-0010: board setup failed
[   17.564448] imx219: probe of 10-0010 failed with error -121
```

この後、tc358743に対する検知処理が動作するように環境をセットアップする必要があります。

### デバイスツリー環境について

次に、TC358743に対する検知処理が動作するように、デバイスツリーの環境を作成及び更新します。

私が以前にJetson NanoにてTC358743を試用したときには、以下のGithubでの情報に助けられました。

[TC358743 Jetson Nano driver and device tree | GitHub](https://gist.github.com/olesia-kochergina/c2af863c250c748c3c58dbb7acfe84bf)

その当時、そのREADME.mdのセクション"Update-device-tree"に書かれている方法にそのまま従って、なんとかデバイスツリーのファイルを生成し、それをなんとか書き込んで、TC358743を認識させることに成功したという経緯がありました。

このときは、上記方法の通り、デフォルトのimx219のデバイスツリー環境を消してしまって、TC358743の環境で上書きしてしまう、というやり方でした。

今回は、[uzunaさん](https://qiita.com/uzuna)の以下のページを参考にさせてもらい、デフォルトのIMX219やIMX477の設定環境は残しつつ、Device Tree OverlayでTC358743を認識させる、という形でやってみましたので、その方法をここでは紹介します。

[Jetsonのカメラドライバを書く[I2C編] - Qiita](https://qiita.com/uzuna/items/693cabb800173f2175f5)

### デバイスツリーの作成

上記uzunaさんの記事で、**IMX708**に関するデバイスツリーのファイルの作成の仕方をほぼ真似して、**IMX477**のファイルをベースに、

* tegra234-camera-toshiba-tc358743.dtsi
* tegra234-p3768-camera-toshiba-tc358743.dtsi

を作成し、/usr/src/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/に置きます。

ここで、ポイントのリストアップだけしておきます。(説明が荒くてすみません)

* compatibleを"toshiba,tc358743"に変更
* i2cのアドレスを0x0fに変更
* TC358743には関係のないmode0やmode1の記述削除
* i2c@1にrefclk_hzの設定を追加
* i2c@1に、クロック関連の設定を追加

また、tegra234-p3768-0000-a0.dtsiにtegra234-p3768-camera-toshiba-tc358743.dtsiのinclude行を入れることで、キャリアボード全体のデバイスツリーに追加したことになります。

```
$ diff /usr/src/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3768-0000-a0.dtsi /usr/src/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb/tegra234-p3768-0000-a0.dtsi.org
19d18
< #include "tegra234-p3768-camera-toshiba-tc358743.dtsi"
```

また、これも、IMX708に関するデバイスツリーオーバレイの作成の仕方を真似して、IMX477のファイルをベースに、TC358743用Device Tree Overlayファイルの、

* tegra234-p3767-camera-p3768-tc358743.dts

を作成し、/usr/src/hardware/nvidia/platform/t23x/p3768/kernel-dts/に配置して、かつ、そのエントリをMakefileに追加します。

```
$ sudo cp -p /usr/src/hardware/nvidia/platform/t23x/p3768/kernel-dts/Makefile /usr/src/hardware/nvidia/platform/t23x/p3768/kernel-dts/Makefile.org
$ sudo vi /usr/src/hardware/nvidia/platform/t23x/p3768/kernel-dts/Makefile
$ diff /usr/src/hardware/nvidia/platform/t23x/p3768/kernel-dts/Makefile /usr/src/hardware/nvidia/platform/t23x/p3768/kernel-dts/Makefile.org
42d41
< dtbo-$(BUILD_ENABLE) += tegra234-p3767-camera-p3768-tc358743.dtbo
```

なお、ここで使用したデバイスツリーファイルなどは、とりあえず、GitHubの[JetsonOrinNano](https://github.com/MakotoA67/JetsonOrinNano)に置いています。

### デバイスツリーのビルド

makeKernel.shを参考に**makeDtbs.sh**を作成して、それを実行します。(スクリプト内の実体は`make dtbs`です。

```
$ ./makeDtbs.sh
Proposed source path: /usr/src/kernel/kernel-5.10
Source Target: /usr/src/
...(中略)...
real    0m16.999s
user    0m29.649s
sys     0m9.149s
DTBs make successful
DTB files are here:
/usr/src/kernel/kernel-5.10/arch/arm64/boot/dts/nvidia/
```

### デバイスツリーファイルのインストール

**copyDtbs.sh**にて、ベースのdtbファイル(tegra234-p3767-0003-p3768-0000-a0.dtb)と、Device Tree Overlayのファイル(tegra234-p3767-camera-p3768-tc358743.dtbo)とをシステム領域にコピーします。

```
$ sudo cp -p /boot/dtb/kernel_tegra234-p3767-0003-p3768-0000-a0.dtb /boot/dtb/kernel_tegra234-p3767-0003-p3768-0000-a0.dtb.org
$ ./copyDtbs.sh
```

### Jetson-IOを用いて

最後に、***Jetson-IO***ツールを使用して、デフォルトの環境とは別に、用意したDevice Tree Overlayにより、デバイスツリー環境をTC358743を使えるように上書きする方法を説明します。

```shell
$ sudo /opt/nvidia/jetson-io/jetson-io.py
```

と、jetson-io.pyを実行して、[Configure Jetson 24pin CSI Connector]→[Configure for compatible hardware]と選択すると、

![Screenshot from 2024-03-05 13-13-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/998321/6ebba8c4-b5da-c214-ba2a-a3a93b7236b6.png)

と、"Camera TC358743-C"という項目が現れますので、それを選択し、[Save pin changes]→[Save and reboot to reconfigure pins]と選択すると、

![Screenshot from 2024-03-05 13-16-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/998321/0491322d-1651-478c-8e1b-c80e6fdcc389.png)

という最終画面になります。ENTERキーなど、適当にキーを叩くとリブートして、次の起動からは、TC358743基板が使えるようになっているはずです。

ちなみに、ここで、"Camera TC358743-C"という項目が現れるようになったのは、上述の**copyDtbs.sh**にて、/boot/にtegra234-p3767-camera-p3768-tc358743.dtboをコピーしたことによる効果です。そして、"Camera TC358743-C"という文字列は、デバイスツリーのソースファイルtegra234-p3767-camera-p3768-tc358743.dtsの中の、

```
       overlay-name = "Camera TC358743-C";
       jetson-header-name = "Jetson 24pin CSI Connector";
```

という記述の効果、ということになります。

### 動作確認例

```shell
$ gst-launch-1.0 v4l2src device=/dev/video0 ! 'video/x-raw,format=UYVY,width=1920,height=1080,framerate=30/1' ! nvvidconv ! video/x-raw ! xvimagesink sync=0
```

などと実行すると、以下のスクリーンショットのように、Windows PCの外部モニタとして動作する状態になります。

(今、丁度、この記事を編集しているウィンドウを「Jetson Orin NanoとTC358743基板とで実現している外部モニタもどき」に表示してみているところです。)

![Screenshot from 2024-03-05 13-45-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/998321/12581835-ea38-984f-5110-bdf173fe0f64.png)

書き忘れていましたが、Windows PC側でのディスプレイの詳細設定で、リフレッシュレートを60Hzではなく30Hzに落とさないと正常に動作しませんでした。あまりちゃんと考察できていませんが。

## おわりに

この記事では、Jetson Orin Nanoで、TC358743(HDMI To MIPI-CSI2ブリッジチップ)搭載基板を用いて、PCの外部モニタ動作をさせてみることをテーマに、Linuxカーネル環境のビルド環境の構築及びその動作確認例を紹介してみました。

後で、もう少し補足説明を追加するかもしれません。とりあえず、ここで使用したデバイスファイルやスクリプトファイルなどは、GitHubの[JetsonOrinNano](https://github.com/MakotoA67/JetsonOrinNano)に置いています。とりあえずな置き方ですみません。