Jetson Nano で Framebuffer Driver を使用する

# はじめに
<a href="https://qiita.com/kitazaki/items/676fdba01b0f145ba976">Jetson Nano / Xavier NX で SPI 接続ディスプレイ</a>が動くようになったので、Framebuffer Driver
を使用して静止画や動画を表示させてみました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/9cd30d2f-3b72-5437-c7f5-6de8e017c713.jpeg" width="32%"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/e351654f-68b7-6585-c4d9-e8cdccc5b6d4.jpeg" width="32%"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/f3da454d-d85d-227e-2059-f060e86af4cd.jpeg" width="32%">

<a href="https://youtu.be/oLkqew6Y2n0"><img width="47%" alt="スクリーンショット 2020-06-04 11.59.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ce194cab-00e1-ed3c-da4b-224d804f9a20.png"></a> <a href="https://youtu.be/dsgf3G5HEjg"><img width="47%" alt="スクリーンショット 2020-06-04 23.20.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ec876dfa-1505-5448-cf9f-d8f717254e0f.png">
</a>

## Framebuffer Driver とは
<a href="https://github.com/notro/fbtft">Linux Framebuffer drivers for small TFT LCD display modules</a> のことで、ラズパイでは SPI 接続のディスプレイにコンソールや X Windows の画面を表示する際にこのカーネルモジュールが利用されています。

## 環境
- Jetson Nano
 - JetPack4.3 (r32.3.1)
- SPI 接続ディスプレイ  
 - 1.3' 240*240 IPS ST7789 (CS ピン無し)

### 接続方法

| 1.3' 240*240 IPS ST7789 | Nano ピン番号 |
| --- | --- |
| GND | 6 (GND) |
| VCC | 1 (3.3V) |
| SCL (SPI clock line) | 23 (SCK) |
| SDA (SPI data line) | 19 (MOSI) |
| RES | 18 (GPIO 24)
| DC | 22 (GPIO 25)
| BLK (Backlight LED Kathode) | 13 (GPIO 27) |

https://qiita.com/kitazaki/items/676fdba01b0f145ba976


## 手順

### 1. SPI 有効化
JetPack 4.3 (r32.3.1) で追加された Jetson-IO tool を使用して I2S (aud_mclk、i2s5)、PWM (pwm1、pwm8)、SPI (spi1) を有効にします。
https://qiita.com/kitazaki/items/a445994f1f46a1b15f78

### 2. カーネル、カーネルモジュール (fbtft_driver) のビルド
JetsonHacks の <a href="https://github.com/JetsonHacksNano/buildKernelAndModules">buildKernelAndModules</a> ツールを使って Framebuffer Driver (fbtft_driver) を有効化してビルドします。
https://qiita.com/kitazaki/items/5fc6b2e8df2bfe03e9b5

.config に以下の行を追加します。

```text:.config
CONFIG_FB_TFT_FBTFT_DEVICE=m
```

カーネルをビルドする途中で質問された場合は m で答えます。

```bash
$ ./makeKernel.sh
Proposed source path: /usr/src/kernel/kernel-4.9
Source Target: /usr/src/
scripts/kconfig/conf  --silentoldconfig Kconfig
*
* Restart config...
*
*
* Support for small TFT LCD display modules
*
Support for small TFT LCD display modules (FB_TFT) [M/n/y] m
  FB driver for the AGM1264K-FL LCD display (FB_TFT_AGM1264K_FL) [N/m/?] (NEW) m
  FB driver for the BD663474 LCD Controller (FB_TFT_BD663474) [N/m/?] (NEW) m
  FB driver for the HX8340BN LCD Controller (FB_TFT_HX8340BN) [N/m/?] (NEW) m
  FB driver for the HX8347D LCD Controller (FB_TFT_HX8347D) [N/m/?] (NEW) m
  FB driver for the HX8353D LCD Controller (FB_TFT_HX8353D) [N/m/?] (NEW) m
  FB driver for the HX8357D LCD Controller (FB_TFT_HX8357D) [N/m/?] (NEW) m
  FB driver for the ILI9163 LCD Controller (FB_TFT_ILI9163) [N/m/?] (NEW) m
  FB driver for the ILI9320 LCD Controller (FB_TFT_ILI9320) [N/m/?] (NEW) m
  FB driver for the ILI9325 LCD Controller (FB_TFT_ILI9325) [N/m/?] (NEW) m
  FB driver for the ILI9340 LCD Controller (FB_TFT_ILI9340) [N/m/?] (NEW) m
  FB driver for the ILI9341 LCD Controller (FB_TFT_ILI9341) [M/n/?] m
  FB driver for the ILI9481 LCD Controller (FB_TFT_ILI9481) [N/m/?] (NEW) m
  FB driver for the ILI9486 LCD Controller (FB_TFT_ILI9486) [N/m/?] (NEW) m
  FB driver for the PCD8544 LCD Controller (FB_TFT_PCD8544) [N/m/?] (NEW) m
  FB driver for the RA8875 LCD Controller (FB_TFT_RA8875) [N/m/?] (NEW) m
  FB driver for the S6D02A1 LCD Controller (FB_TFT_S6D02A1) [N/m/?] (NEW) m
  FB driver for the S6D1211 LCD Controller (FB_TFT_S6D1121) [N/m/?] (NEW) m
  FB driver for the SSD1289 LCD Controller (FB_TFT_SSD1289) [N/m/?] (NEW) m
  FB driver for the SSD1305 OLED Controller (FB_TFT_SSD1305) [N/m/?] (NEW) m
  FB driver for the SSD1306 OLED Controller (FB_TFT_SSD1306) [N/m/?] (NEW) m
  FB driver for the SSD1325 OLED Controller (FB_TFT_SSD1325) [N/m/?] (NEW) m
  FB driver for the SSD1331 LCD Controller (FB_TFT_SSD1331) [N/m/?] (NEW) m
  FB driver for the SSD1351 LCD Controller (FB_TFT_SSD1351) [N/m/?] (NEW) m
  FB driver for the ST7735R LCD Controller (FB_TFT_ST7735R) [M/n/?] m
  FB driver for the ST7789V LCD Controller (FB_TFT_ST7789V) [M/n/?] m
  FB driver for tinylcd.com display (FB_TFT_TINYLCD) [M/n/?] m
  FB driver for the TLS8204 LCD Controller (FB_TFT_TLS8204) [M/n/?] m
  FB driver for the UC1611 LCD controller (FB_TFT_UC1611) [M/n/?] m
  FB driver for the UC1701 LCD Controller (FB_TFT_UC1701) [M/n/?] m
  FB driver for the uPD161704 LCD Controller (FB_TFT_UPD161704) [M/n/?] m
  FB driver for the WATTEROTT LCD Controller (FB_TFT_WATTEROTT) [M/n/?] m
  Generic FB driver for TFT LCD displays (FB_FLEX) [M/n/?] m
  Module to for adding FBTFT devices (FB_TFT_FBTFT_DEVICE) [M/n] m
#
# configuration written to .config
#
```

次にカーネルモジュールをビルドします。

```bash
$ ./makeModules.sh
```

ビルドが完了したら新しい Image を現在の Image にコピーして再起動します。

```bash
$ ./copyImage.sh
$ sudo reboot
```

### 3. カーネルモジュールの組み込み
(組み込み前)

```bash
$ lsmod
Module                  Size  Used by
zram                   29313  4
overlay                51662  0
nvgpu                1713284  20
spidev                 14507  0
bluedroid_pm           16059  0
ip_tables              21421  0
x_tables               38016  1 ip_tables

$ ls /dev/fb*
/dev/fb0
/dev/fb1
```

(組み込み)
1.3' 240*240 IPS ST7789 (CS ピン無し) を組み込む場合のコマンドです。
他のディスプレイを使用する場合は各パラメータ (fbtft_device モジュールの name=flexfb gpios=reset:15,dc:13,led:14 や flexfb の init=-1,0x11,../) の値が異なります。
また、gpios の各値 (GPIO 番号) はラズパイと異なるので<a href="https://qiita.com/kitazaki/items/961c80c7e497f6a2f4d9">ピンレイアウト比較表</a>で確認します。

```text
(ラズパイ)
gpios=reset:24,dc:25,led:27
↓
(Jetson Nano)
gpios=reset:15,dc:13,led:14
```

```bash
$ sudo modprobe fbtft_device name=flexfb gpios=reset:15,dc:13,led:14 speed=40000000 bgr=1 fps=60 custom=1 height=240 width=240 mode=3
$ sudo modprobe flexfb setaddrwin=0 width=240 height=240 init=-1,0x11,-2,120,-1,0x36,0x70,-1,0x3A,0x05,-1,0xB2,0x0C,0x0C,0x00,0x33,0x33,-1,0xB7,0x35,-1,0xBB,0x1A,-1,0xC0,0x2C,-1,0xC2,0x01,-1,0xC3,0x0B,-1,0xC4,0x20,-1,0xC6,0x0F,-1,0xD0,0xA4,0xA1,-1,0x21,-1,0xE0,0x00,0x19,0x1E,0x0A,0x09,0x15,0x3D,0x44,0x51,0x12,0x03,0x00,0x3F,0x3F,-1,0xE1,0x00,0x18,0x1E,0x0A,0x09,0x25,0x3F,0x43,0x52,0x33,0x03,0x00,0x3F,0x3F,-1,0x29,-3
```

(組み込み後)

```bash
$ lsmod
Module                  Size  Used by
fuse                  111691  2
flexfb                 17049  0
fbtft_device           51795  0
fbtft                  45781  2 fbtft_device,flexfb
zram                   29313  4
overlay                51662  0
nvgpu                1713284  3
spidev                 14507  0
bluedroid_pm           16059  0
ip_tables              21421  0
x_tables               38016  1 ip_tables

$ ls /dev/fb*
/dev/fb0
/dev/fb1
/dev/fb2
```

### 4. OS 起動時に自動で組み込む場合
/etc/modules にカーネルモジュールを追加します。

```bash
$ sudo vi /etc/modules
```

```text:/etc/modules
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.

# bluedroid_pm, supporting module for bluetooth
bluedroid_pm
# modules for camera HAL
nvhost_vi
# nvgpu module
nvgpu
# 追加
fbtft_device
flexfb
```

/etc/modprobe.d/fbtft.conf (新規作成) にパラメータを追加します。

```bash
$ sudo vi /etc/modprobe.d/fbtft.conf
```

```text:fbtft.conf
options fbtft_device name=flexfb gpios=reset:15,dc:13,led:14 speed=40000000 bgr=1 fps=60 custom=1 height=240 width=240 mode=3
options flexfb setaddrwin=0 width=240 height=240 init=-1,0x11,-2,120,-1,0x36,0x70,-1,0x3A,0x05,-1,0xB2,0x0C,0x0C,0x00,0x33,0x33,-1,0xB7,0x35,-1,0xBB,0x1A,-1,0xC0,0x2C,-1,0xC2,0x01,-1,0xC3,0x0B,-1,0xC4,0x20,-1,0xC6,0x0F,-1,0xD0,0xA4,0xA1,-1,0x21,-1,0xE0,0x00,0x19,0x1E,0x0A,0x09,0x15,0x3D,0x44,0x51,0x12,0x03,0x00,0x3F,0x3F,-1,0xE1,0x00,0x18,0x1E,0x0A,0x09,0x25,0x3F,0x43,0x52,0x33,0x03,0x00,0x3F,0x3F,-1,0x29,-3
```

## Framebuffer Driver のテスト

```bash
$ git clone https://git.kernel.org/pub/scm/linux/kernel/git/geert/fbtest.git
$ cd fbtest
$ make
$ ./fbtest --fbdev /dev/fb2
Using drawops cfb16 (16 bpp packed pixels)
Available visuals:
  Monochrome
  Grayscale 32
  Truecolor 5:6:5:0
Using visops truecolor
Running all tests
test001: PASSED
test002: PASSED
test003: PASSED
test004: PASSED
test005: PASSED
test006: PASSED
test008: PASSED
test009: PASSED
test010: PASSED
Benchmarking... 10x10 squares: 44.75 Mpixels/s
Benchmarking... 20x20 squares: 97.85 Mpixels/s
Benchmarking... 50x50 squares: 190.24 Mpixels/s
Benchmarking... 100x100 squares: 261.87 Mpixels/s
Benchmarking... 200x200 squares: 354.09 Mpixels/s
test012: PASSED
Benchmarking... R5 circles: 19.57 Mpixels/s
Benchmarking... R10 circles: 55.88 Mpixels/s
Benchmarking... R25 circles: 123.06 Mpixels/s
Benchmarking... R50 circles: 127.81 Mpixels/s
Benchmarking... R100 circles: 218.79 Mpixels/s
test013: PASSED
```

<a href="https://youtu.be/oLkqew6Y2n0"><img width="70%" alt="スクリーンショット 2020-06-04 11.59.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ce194cab-00e1-ed3c-da4b-224d804f9a20.png"></a>

## 静止画の表示

```bash
$ sudo apt install fbi
$ sudo fbi -d /dev/fb2 -T 1 -noverbose -a /usr/share/backgrounds/NVIDIA_Wallpaper.jpg 
$ sudo fbi -d /dev/fb2 -T 1 -noverbose -a /usr/share/backgrounds/NVIDIA_Logo.png 
$ sudo fbi -d /dev/fb2 -T 1 -noverbose -a /usr/share/backgrounds/NVIDIA_Login_Logo.png
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/9cd30d2f-3b72-5437-c7f5-6de8e017c713.jpeg" width="32%"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/e351654f-68b7-6585-c4d9-e8cdccc5b6d4.jpeg" width="32%"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/f3da454d-d85d-227e-2059-f060e86af4cd.jpeg" width="32%">


## 動画の再生

```bash
$ sudo apt install mplayer
$ wget http://fredrik.hubbe.net/plugger/test.mpg
$ mplayer -nolirc -vo fbdev:/dev/fb2 -vf scale=240:160 test.mpg
```

<a href="https://youtu.be/dsgf3G5HEjg"><img width="70%" alt="スクリーンショット 2020-06-04 23.20.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ec876dfa-1505-5448-cf9f-d8f717254e0f.png">