Author: Taketoshi Sano <kgh12351@nifty.ne.jp>
Title: Modeline in XF86Config
$Revision: 1.9 $, ($Date: 1999/05/11 00:09:43 $)

「"Modeline" 行について」

XFree86 を使用する場合、モニターの仕様に応じて、表示画面の
解像度や走査周波数を制御するための "Modeline" 行を設定ファイル
である XF86Config に記載する必要があります。

この "Modeline" 行の意味は、標準構成なら XFree86 のアーカイブに
含まれている /usr/X11R6/lib/X11/doc/VideoModes.doc で説明されて
います。また man XF86Config としても説明を読むことができます。

(VideoModes.doc や XF86Config の日本語訳もあります。
 後述の xjman プロジェクトに関する説明を参照してください)

「"Modeline" 行の構成要素」

XF86Config の "Modeline" 行に書かれている内容を簡単にまとめると、

  1) Modeline (画面モードの指定)：キーワードです。

  2) "name" (モード名) ： 
     複数のモードを記述する際にそれぞれを区別するための名前。
     通常 "800x600" , "640x480" などの解像度を名前に付けるが
     これは単にわかりやすくするためであって、 "modeA", "modeB"
     などと名前を付けても間違いではありません。

  3) DotClock (ドットクロック)：最初の数値。説明は付録を参照。

  4) horizontal timing (水平方向同期のタイミング設定) ：
     2 番目から 5 番目までの 4 つの数値。説明は付録を参照。

  5) vertical timing (垂直方向同期のタイミング設定)：
     6 番目から 9 番目までの 4 つの数値。説明は付録を参照。

  6) Flags (フラッグ)：細かい動作の指定。説明は man XF86Config

の 6 つに分類できます。場合によっては HSkew という 7 番目の
項目が必要になるらしいですが、ほとんど見たことが無いので、
これについては省略します。

さて 1) はキーワードなので変更できないし、 2) の指定についても
問題になることはまず無いでしょう。また 6) についてもとりあえず
置いておきましょう。

ここでは、 3), 4), 5) の数値をどうやって決めるべきか、
という点について考えてみます。 

(それぞれの数値の持つ意味については付録 A を参照してください。
 また具体的な数値については後述する例題を参考にしてください)

「ドットクロックと同期タイミング」

まず、自分が使うモニターの仕様から、水平および垂直同期周波数、
それにビデオ信号帯域幅の値はわかっているものとします。
また設定したい画面解像度 (水平 / 垂直) も決まっているものと
します。

(これらの用語の意味は上記の VideoModes.doc を参照して下さい)

これらを

 モニター (CRT/LCD) の水平同期周波数： MHsync
 モニター (CRT/LCD) の垂直同期周波数： MVsync
 モニター (CRT/LCD) のビデオ信号帯域幅: MVB

 設定したい画面解像度 (水平方向) : Hres
 設定したい画面解像度 (垂直方向) : Vres

と表記します。

一方、 "Modeline" 行で指定するべき数値を

Modeline "modeA" clockval Hres HsyncS HsyncE HFL Vres VsyncS VsyncE VFL

として表記します。見てわかるように、 "Modeline" 行で指定する数値の
うち 2 個所は、設定したい画面解像度をそのまま指定します。

さて、次にすることは HFL, clockval, VFL を決めることです。

とりあえず初期値として、 Hres × 1.25 を計算し、得られた数値を
もっとも近い 8 の倍数に丸めて HFL とします。これを前提として、

 「ドットクロック」÷「水平方向の全ドット数、つまり水平フレーム長」
  ＝「ビデオカードが出力する水平方向の走査数、つまり水平同期周波数」

という関係から (ビデオカードが使用する水平同期周波数とモニター仕様
上の水平同期周波数との意味の違いを把握しておいて下さい) 
ドットクロックの数値を

  clockval [MHz] = MHsync [kHz] × HFL (ドット数) ÷ 1000 (単位換算)

と設定します。ここでまず

 clockval < MVB (モニターの仕様による制限)

 clockval < [Maximum allowed dotclock] (ビデオカードによる制限)

を確認しておいてください。

次に、

 「ドットクロック」÷「水平方向の全ドット数、つまり水平フレーム長」
  ÷「垂直方向の全ドット数、つまり垂直フレーム長」
  ＝「ビデオカードが出力する垂直方向の走査数、つまり垂直同期周波数」

という関係から (ここでもビデオカードが使用する垂直同期周波数と
モニター仕様上の垂直同期周波数との意味の違いを把握しておいて下さい)
 VFL の数値を

  VFL = clockval [MHz] ÷ HFL (ドット数) ÷ Vsync [kHz] × 1000 (単位換算)

とします。答は切り上げて整数にして下さい。
これは 8 の倍数に丸める必要はありません。

  注：
      この式でわかるとおり、 HFL を変更した場合には、変更後の HFL に
      合わせて VFL も計算し直す必要があります。注意して下さい。

ここで、 VFL > (Vres × 1.05) になっていれば dotclock, HFL, VFL の
初期値としては充分です。あとはとりあえず

 HsyncS = Hres + ( (HFL - Hres) ÷ 3 )
 HsyncE = HFL  - ( (HFL - Hres) ÷ 3 )

 VsyncS = Vres + ( (VFL - Vres) ÷ 3 )
 VsyncE = VFL  - ( (VFL - Vres) ÷ 3 )

とでもしておきましょう。(数値はすべて整数になるよう切り上げて下さい)
実はこの 4 つの数値の決め方はかなりいい加減です。たぶんこれでは
ちゃんとした位置に表示されないでしょう。もっと良い計算式を提案できる
人は是非連絡して下さい。

では何故このようないい加減な決め方をここに書いているかというと、
 "xvidtune" という便利なツールがあるからです。

上の 4 つの数値 (HsyncS, HsyncE, VsyncS, VsyncE) は下記の付録に
簡単に説明してありますが、水平、垂直それぞれの「同期信号開始位置」
「同期信号終了位置」を示します。これらの数値は表示される画面の位置
に大きく影響します。

画面が左にズレている場合、水平同期信号の位置 (horizontal timing の
中央の 2 つの数値) を 8 の倍数ずつ増やします。逆の場合は減らします。
上にズレている場合は、垂直同期信号の位置 (vertical timing の中央の 
2 つの数値) をすこし減らします。(垂直信号は 8 の倍数でなくても良い) 
逆の場合は増やします。

実際には、画像位置の調整や表示サイズの調整はエディタでモードラインの
数値を編集しながら試行錯誤するより、 xvidtune というツールを使ったほうが
ずっと便利で簡単です。このツールで最適なモードラインを見つけてその数値を
メモしておき、後で 1 回だけモードラインを編集すれば良いのです。これで
何度も X を再起動したりする手間が省けます。

ということで、とりあえず dotclock, Hres, HFL, Vres, VFL について
ある程度妥当な初期値を決められれば、あとは xvidtune で調整すること
でそれなりの "Modeline" 行を作り出せるはずです。
自分が使っているハードウェアに合わせた "Modeline" 行を、是非自分で
計算して作ってみて下さい。

  注:
  すくなくとも 3.3 以降の XF86_SVGA の C&T ドライバーでは
  オプション "use_modeline" を使って明示的に指定しない場合は、
   "ModeLine" 行で指定された数値のうち 3) の DotClock だけを
  使い、それ以外の 4), 5) で指定された数値は使いません。
   (ただしとりあえず指定はしないとマズイです。詳細は XFree86 の
    ドキュメントである README.chips を読んで下さい)

  注:
  実際に数値の入った ModeLine のサンプルが欲しい人は、 XFree86 の
  附属文書である /usr/X11R6/lib/X11/doc/Monitors を見てみると
  良いでしょう。 XF86Config で指定する Monitor セクションの内容が
  モニターの機種別に並んでいます。


「付録 A: ドットクロックと同期タイミングについての説明」

上記の 3) DotClock, 4) horizontal timing, 5) vertical timing
のそれぞれについて、もうすこし詳しく説明すると以下のようになります。

3) DotClock ：ビデオカードから出力される映像信号が 1 秒間に
   どれだけのドット (1 画素) を走査 (スキャン) できるかを
   表す周波数 (ドットクロック / DotClock)。
   XF86Config での単位は MHz (メガヘルツ)。

    注:
    モニターの内部構造から言えば、厳密には「ドット (発光点)」
    と「画素 (画面上の位置を示す最小単位)」が同じ意味を持つのは
    モノクロモニターの場合であり、 R/G/B の 3 つの「ドット」から
    ひとつの「画素」が構成されるカラーモニターの場合にはドットと
    画素は別の概念になります。

    ただし XFree86 を使う場合、例えば C&T ドライバでは LCD と CRT の
    同時表示における問題を考慮して、  XF86Config 中では「ドット」と
    「画素」が同じ意味を持つとして考えてほぼ問題は生じないように
    作られています。詳細は次の注を参照のこと。

   なお、最近のカードの場合はプログラマブルクロックジェネレータを
   使えることが多いのですが、この場合には最初に挙げた資料で説明されて
   いる帯域幅 (Maximum allowed dot-clock: 最高許容ドットクロック) より
   低い任意の周波数で動作させることができます。

   この「帯域幅」は、例えば XFree86 の XF86_SVGA が出すメッセージに

   (--) SVGA: Maximum allowed dot-clock: 135.000 MHz

   という行の中で示されています。

   注:
      液晶ディスプレイ (LCD) を使ったノートマシンの場合、
      ビデオチップに対してビデオメモリから LCD への転送クロックを
      与えることがあります。この場合プログラムすべきなのはドット単位
      のクロックです。

      たとえば、8 bpp、16 bpp、24 bpp をそれぞれ同じスキャンレート
      で表示しようとすれば、16 bpp では 8 bpp の時の倍、24 bpp では
      3 倍のクロックを与える必要があります。

      LCD から CRT に切替えた時、この「ドットクロック」をそのまま
      DAC 経由で CRT に与えるとオーバークロックで CRT に表示できず
      困った事になることがあります。この点を解決するため、C&T ドライバ
      では指定されたクロックにピクセルあたりのバイト数を乗じて LCD を
      使う際のメモリ転送クロックとしています。
      これにより、LCD と CRT に一つのモードラインで対応できる事になります。
      (詳細はコードを確認してください)

      最近の XFree86 では複数のモードラインが使えるかもしれないので、
      この様な工夫は必要ないかもしれません。このあたりもグラフィック
      ドライバーによって異なる可能性があるためコードの確認が必要です。

4) horizontal timing : 最初の数値は表示部分の水平方向のドット数
    (水平解像度)、 2 番目の数値は水平同期信号の開始ドット、 
    3 番目の数値は水平同期信号の終了ドット、 4 番目の数値は表示部、
   空白部 (同期信号を含む)を合わせた水平方向の全ドット数です。
    4 番目の数値を「水平フレーム長」と呼びます。この水平方向の 4 つの
   数値はすべて 8 の倍数にしておく必要があります。

   注:
      XFree86-Video-Timing-HOWTO によると、ここで「 8 の倍数」にする
      のは「 8 ビットレジスタを持ち、左に 3 ビットずらして 11 ビットの
      値を得るような SVGA と S3 の VGA 制御装置において有効」だから
      だそうです。ハードウェアによっては 8 の倍数にする必要が無いかも
      しれないそうです。確認される場合は at your own risk でどうぞ。

    horizontal timing の関係を図にすると、下のようになります。

                    |<-------------- HFL -------------->|
     HD   ------+   +-------------------------------+   +---------
                |   |                               |   |
                ~~~~~                               ~~~~~
                hsync                               hsync

     DENA --+          +------------------------+          +------
            |          |                        |          |
            ~~~~~~~~~~~                         ~~~~~~~~~~~
                    |<>|<--------- HR --------->|<->|   |<>|
                    HBP                         HFP HSP HBP|
                       |<-------------- HFL -------------->|


                 1.    |----------------------->| HR
                 2.    |--------------------------->| HR+HFP
                 3.    |------------------------------->| HFL-HBP
                 4.    |---------------------------------->| HFL

   ただし、

    HR (Horizontal Resolution) : 
       表示部分の水平方向のドット数 (水平解像度)

    HSP or hsync (Horizontal Sync) : 水平同期信号

    HFP (Horizontal frontporch) : フロントポーチ
       表示信号の終了から水平同期信号 (hsync) の開始まで。

    HBP (Horizontal Backporch) : バックポーチ
       水平同期信号 (hsync) が終了してから表示信号の開始
       (次の HFL の開始) まで。

    HFL (Horizontal Frame Length) ：水平フレーム長
       表示部、空白部 (同期信号を含む) を合わせた水平方向の全ドット数。

     ここで重要なことは、「ドットクロックを水平フレーム長で割って得られる
     数値がモニターの仕様に記載された水平同期周波数上限を超えてはいけない」
     ということです。

     また、マルチシンクモニターでない場合 (固定同期周波数の場合)、
     「ドットクロックを水平フレーム長で割って得られる数値がモニターの
     仕様にある水平同期周波数とほぼ同じでないときれいな表示が得られない」
     ということも覚えておく必要があります。ちなみに内蔵 LCD の場合は
      XF86Config を作成する場合、通常固定同期周波数として考えておけば
     良いでしょう。 
     (アナログ接続の外付け LCD ではマルチシンク対応のものもあります)

5) vertical timing : "horizontal timing" と同様に、最初の数値は表示部分
   の垂直ライン数 (垂直解像度)、 2 番目の数値は垂直同期信号の開始ライン、
   3 番目の数値は垂直同期信号の終了ライン、 4 番目の数値は表示部、空白部
   (同期信号を含む)を合わせた垂直方向の全ライン数です。
   4 番目の数値を「垂直フレーム長」と呼びます。

    vertical timing についても、 horizontal timing と同様に、
   下の図のようになります。

                    |<-------------- VFL -------------->|
     VD   ------+   +-------------------------------+   +---------
                |   |                               |   |
                ~~~~~                               ~~~~~
                vsync                              vsync

     DENA --+          +------------------------+          +------
            |          |                        |          |
            ~~~~~~~~~~~                         ~~~~~~~~~~~
                    |<>|<--------- VR --------->|<->|   |<>|
                    VBP                         VFP VSP VBP|
                       |<-------------- VFL -------------->|

                 1.    |----------------------->| VR
                 2.    |--------------------------->| VR+VFP
                 3.    |------------------------------->| VFL-VBP
                 4.    |---------------------------------->| VFL

   ただし、

    VR (Vertical Resolution) : 
       表示部分の垂直方向のドット数 (垂直解像度)

    VSP or vsync (Vertical Sync) : 垂直同期信号

    VFP (Vertical frontporch) : フロントポーチ
       表示信号の終了から垂直同期信号 (vsync) の開始まで。

    VBP (Vertical backporch) : バックポーチ
       垂直同期信号 (vsync) が終了してから表示信号の開始
       (次の VFL の開始) まで。

    VFL (Vertical Frame Length) ：垂直フレーム長
       表示部、空白部 (同期信号を含む) を合わせた垂直方向の全ドット数。

     ところで垂直同期と水平同期の関係は、下図のように示すことができます。

                     |<-------------- VFL -------------->|
      VD   ------+   +-------------------------------+   +---------
                 |   |                               |   |
                 ~~~~~                               ~~~~~
                        HFL
      DENA +++          ++++++++++++++++++++++++++          +++++++
           |||          ||||||||||||||||||||||||||          |||||||
             ~~~~~~~~~~~                         ~~~~~~~~~~~
     
     DENAの細かい縦線の間が、1 水平期間 (HFL) になります。
      VFL を基準にすると、 HFL は極めて短い時間なので、
     ただの線と同じに見えてしまいます。

「付録 B: 例題」

  (以下の情報は小木曽直門 (ogiso@use-net.co.jp) さんから
   提供されたものです。)

   Q:
      Toshiba TECRA 720CT, XFree86 Version 3.3.3 の環境で
      XF86_SVGA server を使って 1024x768 pixel, 16bpp を
      表示できません。

   A: 
      最初に XF86Setup による変更か、
      エディタによる XF86Config ファイルの編集などの
      方法によって

Option "fast_dram" 
Set_MemClk 38.000

を設定して下さい。

これは memory clock （以下 MomoryClk）を default 値より
速くするための設定です。これによって Maximum allowed dot-clock
(以下 Max Dotclock) が大きくなり Modeline の DotClock 値を
大きくすることができます。
Max Dotclock、MaxDClk、MemoryClk の関係については
/usr/X11R6/lib/X11/doc にある README.chips の

5. The Full Story on Clock Limitations

を御覧下さい。

TECRA 720CT が使っているチップは CT65550 (5V) であり、
上記の文書によるとこのチップの仕様は

MaxDClk = 110 
MemoryClk = 38 

となっているため "Set_MemClk 38.000" とします。

またこの章には 16bpp では Max Dotclock が 53.2 と
書かれています。実際 X を起動してみると

Maximum allowed dot-clock: 53.197 MHz

となっています。この理屈も上記の 5 章の計算式を見れば分かります。

さて、

Modeline の DotClock < Max Dotclock

でなければなりません。これより大きな値を設定すると

(--) SVGA: Clock for mode "1024x768" is too high for the configured hardware.
           Limit is  53.197 MHz

となり X を起動できなくなります。そこで DotClock = 53 として

Modeline  "1024x768"   53.00 1024 1032 1176 1344 768 771 777 806

と設定すれば良いでしょう。しかしこのままでも

Fatal server error:
No valid modes found.

となって X を起動できないことがあります。
これは HorizSync と VertRefres の幅が小さすぎることが原因で

HorizSync       30-69
VertRefresh     40-87

に設定することで解決します。
この最大値をむやみに大きくすることはお勧めできません。
本来ならば

DotClock < Maximum Video Bandwidth (MVB)

を確認すれば HorizSync と VertRefres の最大値
を注意する必要はなくなるのですが、

http://www.csd.toshiba.com/tais/csd/support/files/

などのスペック表を見ても LCD のビデオ信号帯域幅について
は載っていませんので、この URL の 
Tecra 720 CDT Video Mode Information に記述されている 
Vertical Refresh Rate と Horizontal Refresh Rate の最大値を
設定しています。

これにより不注意に DotClock を設定したことによる LCD の損傷を
防ぐ保険となります。ただし外部 CRT を御使いの場合はその CRT の MVB に
依存しますのでこの限りではありません。

また少なくとも 3.3 以降のXF86_SVGA の C&T ドライバーでは

Option  "use_modeline"

を使って明示的に指定しない場合は、"ModeLine" 行で指定された数値のうち
 DotClock だけを使い、それ以外の数値は使いません。

従って DotClock 以下はあまり気にしなくても良いですが
適当な値は設定しなければなりません。

「謝辞」

この文書は、 XFree86-Video-Timings-HOWTO をベースとして
そこから自分が一番知りたかったことを抜き出そうという意図で
作成されました。オリジナルの文書を作成された ESR 氏、また
それを日本語に翻訳された岡本一幸氏に謝意を表します。

この文書に含まれる図は Laptop-X-ml にかんめい氏が投稿された
内容を頂いたものです。使用を許可して頂き、また文書の内容に
ついてもいろいろとアドバイスをして下さったかんめい氏に謝意を
表します。

実際にこの文書を使ってみた経験から、 例題をフィードバックして
下さった小木曽直門氏にも謝意を表します。これによって説明の
不足していた点を補うことができました。

そして、 XFree86 に集まってサーバーの開発に貢献している開発者たち、
特に私が日頃お世話になっている David Bateman さんをはじめとした
C&T ドライバーの開発者たちにも謝意を表します。
彼らがいなければ、私がこの文書を作成することも無かったでしょう。

「参考」

 X Japanese Documentation Project (xjman project) が作成、公開
している xjman-0.3 には XF86Config の man page の日本語訳、
また xjdoc-0.2 には VidModes (XFree86-Video-Timings-HOWTO) の
日本語訳が含まれています。(現在 xjdoc-0.3 の公開に向けて作業中)

まだαリリースですが、それなりに役に立つはずですので是非ご利用下さい。 
(内容に関しての御意見があればフィードバックをお願いします)
一次配布場所は次のとおりです。

 <http://xjman.dsl.gr.jp/xjman-0.3.tar.gz> (約 1MB)
 <http://xjman.dsl.gr.jp/xjdoc-0.2.tar.gz> (約 500KB)

ちなみに xjman-0.3 については FreeBSD の ports、
 Debian の package がそれぞれ作成されています。

