#navi(RTS7751R2D)
#contents

* SM501の制御 [#h88d1d25]

** Frame Bufferとは? [#mdf5ecea]
Linuxにおいてビデオメモリは/dev/fb*というデバイスによってアクセスできます。~
fbは通常のメモリデバイスで,memmapして読み書きすることができます。
-[[JF: Linux Kernel 2.2 Documentation: /usr/src/linux/Documentation/fb/framebuffer.txt :http://www.linux.or.jp/JF/JFdocs/kernel-docs-2.2/fb/framebuffer.txt.html]]
-[[Lunux Frame Buffer HOWTO:http://www.tldp.org/HOWTO/Framebuffer-HOWTO.html]]
-[[Linux フレームバッファを有効にする:http://www.kde.gr.jp/~ichi/qt/emb-framebuffer-howto.html]]
-[[Linux Kernel 2.2と2.4 のフレームバッファ:http://www.nk.rim.or.jp/~jun/linux/k22fb.html]]

/dev/fb*のさまざまな情報の取得や設定はioctlで行います。~
詳しくはinclude/linux/fb.hをみてくださいだそうです。~

CeLinuxではビデオを取り扱う枠組みとして伝統的なFrame bufferと,その上に構築された[[DirectFB:http://www.directfb.org/]]を考えているようです。~
最終的にはどちらか一方のみのサポートになるかもしれないそうです。
-[[Audio, video, and graphics specifications:http://tree.celinuxforum.org/pubwiki/moin.cgi/AudioVideoGraphicsSpec]]

** SM501 [#za7cd889]
[[SM501:http://www.siliconmotion.com/jp/sm501.htm]]は
[[シリコンモーション社:http://www.siliconmotion.com/jp/index.htm]]の誇る高性能省電力グラフィックコントローラVoyage GXファミリーです。~
Linux用の[[ドライバ:http://www.siliconmotion.com/jp/driverslist.htm]]が供給されています。

それとは別にCeLinuxにはkernel組み込みのフレームバッファドライバが提供されているようです。
SM501は7枚のフレームバッファを通じてアクセスされます。~
それぞれのフレームバッファは起動時に~
- celinux/drivers/video/voyager_alphafb.c
- celinux/drivers/video/voyager_crtcsrfb.c
- celinux/drivers/video/voyager_crtfb.c
- celinux/drivers/video/voyager_gxfb.c
- celinux/drivers/video/voyager_panelcsrfb.c
- celinux/drivers/video/voyager_valphafb.c
- celinux/drivers/video/voyager_videofb.c

によって初期化されます。~
IRQなどの低いレイヤーの初期は
- celinux/arch/sh/kernel/setup_voyagergx.c

によって行われます。~
USBについては
- celinux/drivers/usb/usb-ohci-voyagergx.c

です。

** SM501のレジスタ操作 [#cdd89f18]

SM501固有の機能はメモリにマップされたレジスタを操作することによって利用します。~
各レジスタのMMIOは
-celinux/drivers/video/voyager.h
-celinux/include/asm-sh/voyagergx_reg.h

で定義されています。

レジスタの操作はioctlによって行います。
ioctlを用いたコードをコンパイルするためにはターゲットアーキテクチャのasm以下のヘッダファイルが必要です。
 # cp -R celinux/include/asm-sh /usr/local/sh4-linux/include/asm

始めに/dev/fb/0をopenします。
 fd = open("/dev/fb/0", O_RDWR);
次に操作対象のレジスタがマップされたメモリアドレスを設定します。
 ioctl(fd, 0, address)
レジスタの内容を読み込むには
 int reg32;
 ioctl(fd, 1, &reg32)
とします。書き込むには
 ioctl(fd, 2, reg32)
とします。

** フレームバッファによるSM501の利用 [#z700e951]
SM501のグラフィック機能はLinux Frame bufferを通じて利用します。~
デバイススペシャルファイルは伝統的なスタイルの場合/dev/fb0-dev/fb6,~
devfsを用いた場合は/dev/fb/0-/dev/fb/6です。

フレームバッファ番号と対応するレイヤは以下の通りです。
|0|Graphics Layer|
|1|Video Layer|
|2|Video Alpha Layer|
|3|Alpha Layer|
|4|Hardware Cursor|
|5|CRT Graphics Layer|
|6|Hardware Cursor|
7枚のレイヤのうち,5-6とそれ以外は排他です。~
CRT display control registaerの第10bitがONのとき5および6が,OFFのときは0-4がそれぞれCRTに表示されます。

Video FBとVideo Alphaだけが拡大機能をもっています。~
拡大率はVideo Scale, Vide Initial Scale, およびVideo Alpha Scale Registerによって制御します。

Frame bufferのプログラムのためにはターゲットアーキテクチャのlinux以下のヘッダファイルが必要です。
 # cp -R celinux/include/linux /usr/local/sh4-linux/include

SM501のフレームバッファに画像を描画する手順は以下の通りです。

操作するフレームバッファデバイスを開きます。
 int fd;
 fd = open("/dev/fb/0, O_RDWR);

固定情報を取得します。
 struct fb_fix_screeninfo finfo;
 ioctl(fd, FBIOGET_FSCREENINFO, &finfo);

可変情報を取得します。
 struct fb_var_screeninfo vinfo;
 ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);

高さ,幅,色深度を取得します。
 int width = vinfo.xres;
 int height = vinfo.yres;
 int depth = vinfo.bits_per_pixel;

バイト単位の画像サイズを計算します。
 int size = width * height * depth / 8;

フレームバッファのVRAMをメモリにマッピングします。
 char *p = (char *) mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

原点座標を取得します。
 int ox = vinfo.xoffset;
 int oy = vinfo.yoffset;

画面上で1ライン分メモリアドレス増分を取得します。
 len = finfo.line_length;

画像を描画します。~
r:g:b = 5:6:5の16bit direct colorの場合の例です。
 for (int j = 0; j < height; ++j)
   for (int i = 0; i < width; ++i) {
      int index = (ox + i) * (depth / 8) + (oy + j) * len;
      *((unsigned short int *)(p * idx)) = (31 << 11) | (127 << 5) | 31;
   }

マッピングを解除します。
 munmap(p, size);

フレームバッファデバイスを閉じます。
 close(fd);

** 実験 [#mf161cd0]

*** [2004-07-23]第1次接触実験 [#fb0291e8]
RTS7751R2D Hundling Manualページにて配布されているvc.zipを入手。
 % sh4-linux-gcc vc.c -o vc
コンパイル成功。
 # ./vc
 IOCTL Address set error
へ? orz

*** [2004-07-23]第2次接触実験 [#h0f79887]

普通にfbにアクセスするコードを書いてみます。~
コードはLinux Frame Buffer HOWTOのやつほとんどそのままです。
 % sh4-linux-gcc test.c -o test
コンパイル成功。
 ~ # ./test
 len 1280
 width 640
 height 480
 depth 16
 ox 0
 oy 0
正常に実行できました。~
video_fbのサイズと色深度は取得できていようです。~
が,何も表示されません…orz~

*** [2004-07-25]第3次接触実験 [#uf3cda2b]
まずは何かCRTに表示させてみようということで,consoleをCRTにしてみます。

-General setup 
--[*] Overrite kernel command line string 
---Command line: "mem=64M root=/dev/nfs ip=bootp video=voyager_crt_fb"

で起動。シリアルコンソールから起動メッセージが消えました。が~
>
&size(16){''fH &color(red){28.7};kHz fV 54.8Hz''};

サポート外…orz~
なんの,RTS7751R → ダウンコンバータ → ビデオキャプチャカード → CRTで接続。~

#ref(celinux.jpg,center)

おおお。SuperHなペンギンとともに黄色い文字で起動メッセージがCRTに表示されました。~
USBキーボードか使用可能です。

*** [2004-07-26]第4次接触実験 [#tb2fa6ba]

オリジナルviewに似たようなインターフェースを持つview.cを実装してみました。
 # view 1 1
で/dev/fb1がONになります。~
緑色の画面になりました。
consoleのON/OFFもできますねえ。~
ただし,相変わらずダウンコーバータ経由ですorz

*** [2004-07-27]第5次接触実験 [#xdd89310]
フレームバッファをopenして,memmap,豆腐を描いてunmemapしみました。~
/dev/fb/0に対して実行するとコンソール画面にかさなって豆腐が,~
/dev/fb/1に対して実行するとビデオフレームバッファに豆腐が,~
それぞれ表示されました。ただし,後者はYUYV形式なので色がへんです。

水平同期周波数が足りない問題はとりあえずキニシナイ。

*** [2004-07-31]第6次接触実験 [#z1d8c0c4]
Power mode 0/1 clock関係のレジスタを操作できるようになりました。~
 Second PLL frequency: 336 MHz
 Power mode 0 clock
    V2XCLK frequency input select: 288 MHz
    V2XCLK fequencey divider: 6
    Dot clock 24.000000 MHz
 Power mode 1 clock
    V2XCLK frequency input select: 288 MHz
    V2XCLK fequencey divider: 6
    Dot clock 24.000000 MHz
が,操作してもまったく変化なし…orz

*** [2004-07-31]第7次接触実験 [#v9f2685f]
 Panel display control: 0000 0111 0000 0001 0011 0011 0000 0101
 Panel horizontal total: 831 pixels
 Panel horizontal display end: 639 pixels
 Panel horizontal sync width: 74 pixels
 Panel horizontal sync start: 651 pixels
水平同期周波数が低いのは水平画素数が多すぎるのではないでしょうか。
 # ./mod2 0x80024
 [0xb3e80024] 0x33f027f : 0000 0011 0011 1111 0000 0010 0111 1111
0x33f = 831を784 = 0x310に変更
 ~ # ./mod 0x80024 0x310027f
 [0xb3e80024] 0x310027f : 0000 0011 0001 0000 0000 0010 0111 1111
すると同じドットクロックでも水平同期周波数が向上。
 fH: 30.4kHz   fV: 58.0Hz
になり,無事CRTに画面が表示されました。ヽ(´ー`)ノ

*** [2004-08-02]第8次接触実験 [#nd548a58]
ふと気づく(←遅い)。~
Power Mode 0 Clock (+0x40)ってCRT display controler(+0x80200)の10bitをONにしたときだけ効果があるんじゃないだろうか!~
10bit ONでCRT Graphics Layer表示
 ./mod 0x80200 0x10305
Power Mode 1 Clockの20bit ONでsecond PLLに切り替え
 ./mod 0x44 0x9091801
その通りでしたヽ(´ー`)ノ。

じゃあPower Mode 1 Clockって何でしょう?~
変更しても意味ないようです。

それと,パネル出力のドットクロックはどこで制御しているのでしょう?

あとは気合で計算すれば任意の解像度が実現できる…かも。

*** [2004-08-03]第9次接触実験 [#l5f4b744]
CRT display parameters for XGA is set as follows.

Let CRT monitor display CRT buffers.
 ./mod 0x80200 0x10305
Set window width and offset to 128 bytes = 0x80
 ./mod 0x80208 0x8000800
Set horizontal total to 1327, and horizontal display end to 1023
 ./mod 8020c 0x52f03ff
Set horizontal sync width to 135, and horizontal sync start 1047
 ./mod 0x80210 0x870417
Set vertical total to 805, and vertical display end to 767
 ./mod 0x80214 0x32502ff   
Set vertical sync height to 5, and vertical sync start to 770
 ./mod 0x80218 0x50302
Set V2XCLK input select to 288MHz, and frequeyncy divider to 2
 ./mod 0x44 0x29011801

Unfortunately, it can not be accessed as XGA since Frame Buffer driver uses fixed VGA values... org

*** [2004-08-04]第10次接触実験 [#ma658168]
So the next step is kernel recompile after modification of voyager.h file.
 #define VOY_VRAM_TOP0   0xb0000000      //PANEL PLANE        1.5MB
 #define VOY_VRAM_TOP1   0xb0180000      //VIDEO PLANE 0      1.5MB
 #define VOY_VRAM_TOP2   0xb0300000      //VIDEO PLANE 1      1.5MB
 #define VOY_VRAM_TOP3   0xb0480000      //VIDEO ALPHA PLANE  1.5MB
 #define VOY_VRAM_TOP4   0xb0600000      //ALPHA PLANE        1.5MB
 #define VOY_VRAM_TOP5   0xb0610000      //PANEL CURSOR PLANE 64KB
 #define VOY_VRAM_TOP6   0xb0620000      //CRT PLANE          640KB
 #define VOY_VRAM_TOP7   0xb06c0000      //CRT CURSOR PLANE   rest

 #define XRES 1024
 #define YRES 768
Then, I could successfully show a 1024x768-sized image on my CRT monitor ヽ(´ι _`  )ノ

To back to VGA mode, use parameters as follows.
 ~ # ./mod 0x80208 0x5000500
 ~ # ./mod 0x8020c 0x33f027f
 ~ # ./mod 0x80210 0x4a028b
 ~ # ./mod 0x80214 0x20c01df
 ~ # ./mod 0x80218 0x201e9
 ~ # ./mod 0x44    0x9191801

Note that you can dynamically change the CRT resolution by setting SM501 registers properly,
though ''linux frame buffer-related information such as vinfo and finfo is no longer reliable.''~
You must get necessary information by means of memory mapped registers.

*** [2004-08-07]第11次接触実験 [#bc766eb8]
Set the bottom right location of the video plane to (319, 239).
 [0xb3e80054] 0x00ef013f : 0000 0000 1110 1111 0000 0001 0011 1111
Then only a rectangle region (0, 0) - (319, 239) is shown.

*** [2004-08-08]第12次接触実験 [#r9206061]
Set vertical and horizontal scaling factors to two.
 # ./mod 0x80058 0x04000400
Then the video content is expanded by a factor of two.

To disable scaling,
 # ./mod 0x80058 0x0


トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS