lvds ディスプレイへの mipi_dsi インターフェイス (GM8775C)

目次


序文

この記事では主に、mipi DSI プロトコル、mipi のデバッグ記録、mipi-to-LVDS アダプタ チップ GM8775C のデバッグ記録について説明します。

シナリオ: 当社は LVDS に mipi dsi インターフェイスを使用する必要があるため、GM8775C アダプター チップを使用する必要があります。このチップはデュアルチャネルです。つまり、2 つの LVDS 画面を外部接続できます。しかし、弊社はLVDSスクリーンを1つだけ外部に接続しています。もちろん、それはあなたの回路との接続方法に依存します。

分析: この場合、2 つのモジュールをデバッグする必要があります。1 つは mipi スクリーン エンド、もう 1 つは GM8775C 変換チップ エンドです。GM8775C にはドライバー コードがありません。自分で書いて追加する必要がありますが、これもそれは実際にはI2Cデバイスであるため、非常に簡単です。


1. MIPI_DSI プロトコルの紹介

MIPI-DSI は、DPI (Display Pixel Interface、Display Pixel Interface)、DBI (Display Bus Interface、Display Bus Interface)、および DCS (Display Command Set、Display Command Set) と互換性があり、ピクセルを送信するディスプレイ技術に適用されるシリアル インターフェイスです。周辺機器への情報または命令をシリアルに送信し、周辺機器からステータス情報またはピクセル情報を読み取り、データ パケット形式、エラー訂正およびエラー検出メカニズムを含む、送信中に独自の独立した通信プロトコルを利用できます。

MIPI-DSI には 2 つの動作モードがあります: 高速モードと低速モード. すべてのデータ チャネル (1 ~ 4 セットのデータ チャネルは単方向の高速伝送に使用できますが、最初のデータ チャネルのみが低速度伝送に使用できます。 - 高速双方向伝送 (データラインが 4 本の場合、data0 は低速モードで双方向伝送に使用できますが、data1-data3 は一方向にのみ伝送できます) 周辺ステータス情報、ピクセルフォーマットおよびその他の情報は最初のデータ チャネルを介して返されます. クロック チャネルが使用されます. データを送信する過程で, 同期クロック信号が送信されます (厳密に言えば, 低速モードでは, 通常はパラメータが送信されるか、周辺機器のステータスが読み取られます, クロック同期低速モードでは、データチャネルは必要ありません。低速モードでは、差動信号自体を使用して同期を実現できます)。

1.用語解説

1. DCS (DisplayCommandSet): DCS は、コマンド モードのディスプレイ モジュール用に標準化されたコマンド セットです。

• DSI、CSI (DisplaySerialInterface、CameraSerialInterface

  • DSI は、プロセッサとディスプレイ モジュール間の高速シリアル インターフェイスを定義します。

  • CSI は、プロセッサとカメラ モジュール間の高速シリアル インターフェイスを定義します。

• D-PHY: DSI および CSI の物理層定義を提供します。

 2. DSI の階層構造

DSI は、D-PHY、DSI、および DCS 仕様に対応する 4 つの層に分割されており、層構造図は次のとおりです。 • PHY は、
伝送媒体、入出力回路、クロックおよび信号メカニズムを定義します。
• レーン管理層: データ フローを各レーンに送信および収集します。
• 低レベル プロトコル レイヤ: フレーム化、解析、およびエラー検出の方法を定義します。
• アプリケーション層: 高レベルのエンコーディングと解析データ フローについて説明します。

3. コマンドおよびビデオ モード
• DSI 互換ペリフェラルは、コマンドまたはビデオ動作モードをサポートします。モードは、ペリフェラル アーキテクチャによって決定されます
ホストは、コマンドを通じて周辺機器を間接的に制御します。コマンド モードは双方向インターフェイスを使用します。
• ビデオ モードとは、ホストからペリフェラルへのリアルタイム ピクセル ストリーミングを指します。このモードは、高速でのみ送信できます。複雑さを軽減し、コストを節約するために、ビデオ モードのみを使用するシステムには単方向データ パスが 1 つしかない場合があります。

4. 3つのメインレーンタイプ

  • 一方通行のクロックレーン

  • 単方向データレーン

  •双方向データレーン

5. D-PHY 送信モード

  • 低電力シグナリング モード (制御用): 10MHz (最大)

  • 高速 (High-Speed) 信号モード (高速データ伝送用): 80Mbps ~ 1Gbps/Lane

• D-PHY 低レベル プロトコルでは、データの最小単位は 1 バイトであると規定されています。

  • データを送信するときは、下位ビットが最初に来て、上位ビットが続く必要があります。

• モバイル アプリケーション向け D-PHY

  • DSI: ディスプレイ シリアル インターフェイス

     • 1 つのクロック レーン、1 つまたは複数のデータ レーン 

  • CSI: カメラ シリアル インターフェイス

6.レーンモジュール

• PHY は D-PHY (レーン モジュール) で構成されます。

• D-PHY には以下が含まれる場合があります。

  • 低電力送信機 (LP-TX) 

  • 低電力受信機 (LP-RX)

  • 高速送信機 (HS-TX)  

  • 高速受信機 (HS-RX)

  • 低消費電力競合検出器 (LP-CD)

7. 3 つのメインレーン タイプ

  • 一方通行のクロックレーン

    • マスター:HS-TX、LP-TX

    • スレーブ:HS-RX、LP-RX

  • 単方向データレーン

    • マスター:HS-TX、LP-TX

    • スレーブ:HS-RX、LP-RX

  •双方向データレーン

    • マスター、スレーブ:HS-TX、LP-TX、HS-RX、LP-RX、LP-CD

8. レーンの状態と電圧

  • レーンの状態 

    • LP-00、LP-01、LP-10、LP-11 (シングルエンド)

    • HS-0、HS-1 (差動)

  • レーン電圧 (標準) 

    •LP:0-1.2V

    • HS:100~300mV (200mV)

2. DSI応用回路の階層化

MIPI-DSI は、アプリケーション層、プロトコル層、チャネル管理層、物理層の 4 つの層に分かれていますMIPI-DSI はインターフェースに適用される通信プロトコルであり、その全体の回路作業は、プロトコルによって定義される各層と連携します。以下に示すように:

アプリケーション層:アプリケーションモジュールのニーズに応じて、送信されたコマンドとデータは最初にエンコードされ、送信側でMIPI-DSIで指定された形式に変換され、受信したデータはアプリケーションモジュールがサポートするデータ形式に復元されます受信側でのシーケンス要件。 

プロトコル層: 情報伝送は、長いデータ パケットと短いデータ パケットを含むデータ パケット形式を採用します。データを送信する際には、情報の種類や内容に応じてデータを圧縮し、ECCコードの生成とCRCコードの付加を完了させます。データを受信すると、ECCコードとCRCコードに従ってデータパケット全体に対してエラー検出と訂正が実行され、パケットヘッダーとデータコンテンツのデコードが完了し、合理的にアプリケーション層に送信されます。

チャネル管理層: 設計によって設定された N 個 (最大 4 個) のデータ チャネルに従って、この層は、送信するデータをチャネルの順序に従って N 個のグループに分割し、対応するデータ チャネルに送信できるようにします。データチャネルを介してスレーブ側に同時に送信されます。受信側で、このレイヤーが行う必要があるのは、受信した N セットのデータを結合して、元のデータ シーケンスを復元することです。 

物理層: 低速送信要求を受信すると、論理回路は送信する命令またはデータをシリアル化し、高スイングの低電力レベルの出力を制御して低電力送信要求を実行し、送信要求をシリアル化します。命令またはデータがチャネルにロードされると、受信側は送信モードを認識して、シリアル データのパラレル変換を完了します。高速要求を受け取った後、回路は高速送信要求用の高スイングおよび低消費電力レベルを送信し、差動ドライブ モジュールをドライブして、チャネルをシリアル変換した後、低スイング信号で送信します。高速モード後、同期信号が正しく検出され、シリアルからパラレルへの変換後に高速シリアルデータが正常に受信されます。また、マスターとスレーブ間でバスの制御権を交換することができ、送信側はバス放棄要求を送信し、受信側は要求を受けてバスを制御し、応答を開始する、全体のプロセスは TA (ターンアラウンド) です。手術。ホストがスレーブが受信したデータを取得したり、表示モジュールのパラメーターや表示データを読み取ったりする必要がある場合、ホストは TA 操作を開始し、スレーブがデータを送信してバス制御を返すと、自動的に TA 操作を開始します。(一般に、これはインタラクティブなプロセスであり、TCP の 3 方向ハンドシェイクと 4 方向ウェーブに少し似ています。相互作用のプロセスでは、いくつかの指示が送信され、応答データの特定のパフォーマンスは特定のモジュール分析に依存します。波形で解析されたデータにも使用できます。)

MIPI-DSI 物理層 (D-PHY プロトコル)

        プロトコル全体の物理層では、マスター エンドとスレーブ エンドの間で同期接続が使用され、クロック チャネルは高速クロックの送信に使用され、1 つまたは複数のデータ チャネルは低電力データ信号の送信に使用されます。または高速データ信号。各チャネルは 2 本の相互接続ワイヤを使用してマスター エンドとスレーブ エンド間の接続を実現し、高速モードと低速 ESCAPE モードをサポートします。高速モードでは、送信機はチャネルの 2 つの相互接続ラインのみを同時に駆動し、200mV などの低振幅差動信号を出力します; 1.2V などの比較的大きな振幅。
                            

重要な要約:

       

信号には、高速モード状態 (HS) と低速モード状態 (LP) の 2 つの動作状態があります。
物理層はハードウェア信号 (タイミング) を制御するためのもので、MIPI-DSI の 2 つの信号タイプ: クロック レーン、2 つのライン、1 つの Dp、Dn。
データ レーン、2 本のライン、1 つの Dp、Dn; 要件に応じて複数のデータ レーンがあり、少なくとも 1 つのレーン (lane0)、最大で 4 つのレーン (lane0、lane1、lane2、lan3) のうち、lane0 のみが双方向 (低前述のように、高速モードは双方向、高速モードは一方向のみ、その他は一方向のみ (高速モードは一方向) です。

相互接続線の両端は、ドライブユニットとレシーバユニットです。ドライブユニットには差動送信モジュール (HS_TX) と低電力シングルエンド送信モジュール (LP_TX) があり、受信ユニットには差動受信モジュール (HS_RX) と低電力シングルエンド受信モジュール (LP_RX) があります。 .

データレーンレベル:

低速モード LP: 0 ~ 1.2 V、アイドル レベル (LP11) Dp、Dn は 1.2 V。
高速モード HS: 100-300mV (200mV)
データ チャネル ステータス テーブル図:

         データ チャネルには HS-0、HS-1、LP00、LP01、LP10、LP11 の 6 つの状態があり、
HS-0 は高速モードのデータ レーンの Dp がローであることを示し、Dn ビットはLP01 は低速モードでのデータ レーンの Dp を示し、LP01 は Low で、Dn は High です。システムの電源投入後、LP11 は約 100us (ハードウェアの初期化) の間残り、その後停止状態に入ります. モード間の遷移はこの状態に戻る必要があります. 一般的な制御状態も LP11 状態です. モード間の変換については後述する。これらの 6 つの状態が言及されたので、写真を添付する必要があります。6 つの状態遷移図は次のとおりです。

差動伝送モジュール (HS_TX) は相互接続ラインを差動信号で駆動し、高速チャネルには差動 0 と差動 1 の 2 つの状態があります。低電力シングルエンド送信モジュール (LP_TX) は 2 つの相互接続ラインを個別に駆動し、チャネルには LP00、LP01、LP10、および LP11 の 4 つの異なる状態があります。プロトコルは具体的にライン レベルを定義し、高速モード、制御モード、ESCAPE モードの 3 つの動作モードを設定します。チャネルはデフォルトで制御モードになり、回線は STOP 状態になります。チャネルが高速モードまたは ESCAPE モードに入る必要がある場合、送信モジュールはライン LP01 または LP10 を駆動して、受信側に要求を送信する必要があります。要求シーケンスが送信された後、対応する作業モードが実行され、LP11 が送信されて終了し、STOP 制御状態に戻ります。受信側は常に LP-RX 受信を行い、回線レベルを検出し、チャネルの動作モードを明確にする必要があります。

特定の操作プロセス:

 • データレーンの 3 つの動作モード 

    •エスケープモード、ハイスピード(バースト)モード、コントロールモード

  • 制御モードの停止状態から発生する可能性のあるイベントは次のとおりです。 

    • エスケープモード要求 (LP-11→LP-10→LP-00→LP-01→LP-00)

    • ハイスピードモードリクエスト (LP-11→LP-01→LP-00)

    • 引き取り依頼 (LP-11→LP-10→LP-00→LP-10→LP-00)

  • エスケープ モードは、LP 状態のデータ レーンの特別な操作です。 

    • このモードでは、いくつかの追加機能を入力できます: LPDT、ULPS、トリガー

    •データレーンはLP-11→LP-10→LP-00→LP-01→LP-00でエスケープモードに入る

    • エスケープ モードになると、送信者は要求されたアクションに応答するために 8 ビット コマンドを送信する必要があります。

    • Escape mode 使用Spaced-One-Hot Encoding

  • 超低電力状態 (超低電力状態)
    • この状態では、ラインは空の状態 (LP-00) です
  • クロック レーンの超低電力状態
    • クロック レーンは LP-11 を通過します→LP-10→LP-00 で ULPS 状態に入ります
    • LP-10 → TWAKEUP → LP-11 でこの状態から抜けます。最小 TWAKEUP 時間は 1ms です。

  ・高速データ転送
    ・高速シリアルデータを送ることを高速データ転送またはバースト(burst)と呼ぶ

    • すべてのレーン ゲートは同期して開始し、異なる時間に終了する場合があります。
    • クロックは高速モードにする必要があります。

  • 各動作モードでの伝送プロセス

    •エスケープモードに入るプロセス:LP-11→LP-10→LP-00→LP-01→LP-00→エントリーコード→LPD(10MHz) •エスケープモードから出るプロセス:LP-10→LP-11
    •
    高速モード移行処理: LP-11→LP-01→LP-00→SoT(00011101)→HSD (80Mbps~1Gbps)
    高速モード移行処理: EoT→LP-11
    制御モード - BTA 送信処理 (マスタースレーブ交換時、マスターが送信するコマンドパラメータとして): LP-11→LP-10→LP-00→LP-10→LP-00 ・コントロールモード ・BTA受信処理(ACKはスレーブ機
    のマスターへの応答 コマンドパラメータ): LP-00→LP-10→LP-11

注: 上記の TCP の 3 ウェイ ハンドシェイクと 4 ウェイ ハンドシェイクに少し似ていますか?

以下に続きます!! ! ! ! ! ! ! !

マスターとスレーブ間のデータ伝送は同期方式であり、DDR モード、つまりダブルエッジ トリガーであり、クロック周波数を変更せずにデータ伝送速度を 2 倍にし、帯域幅リソースをより効果的に使用できます。ホストの物理層は、チャネル管理層から分配されたデータをシリアルに差動信号に変換してデータラインに送出すると同時に差動クロックを生成し、各データチャネルは最大 4 チャネルで並列に送信されます。および帯域幅の要件に応じて、最低 1 つのチャネル。スレーブの物理層は、差動シリアル ビット ストリームから 0 または 1 をキャプチャする役割を果たします。 -bit データを送信し、チャネル管理レイヤーに送信します。同時に、水平同期信号と垂直同期信号もデータパケットから検出できます。高速クロックが必要なHSモード、高速クロックを必要としないLPモードは差動信号線のみで、この時のクロックは差動線Dpの排他的論理和で得られるとDn

                                                             HSモード(高速モードタイミングチャート)

                                                             LP モード (低電力モードのタイミング図)        

ここで、ダイアグラムを注意深く分析し、上記のプロセスと比較する必要があります。すると、すぐに明らかになります。! 、 いいやつ、私は実際にイディオムを使いました、はははは!! ! !

まだまだ分からないことがたくさんあると思いますので、今後ゆっくり更新していきます!! 最初にメインコースをサーブします。! ! !

2.MIPI デバッグ

         MIPI 側のコードは、そのアーキテクチャに触れる必要はありません. 最も重要なことは、dts ファイルの構成です. 言うことはあまりありません, サービスしましょう! ! !

#include <dt-bindings/display/media-bus-format.h>


/*---------mipi-dsi------------------*/

&dsi0_in_vp0 {
	status = "disabled";
};

&dsi0_in_vp1 {
        status = "okay";
};

&mipi_dphy0 {
        status = "okay";
};

&mipi_dphy1 {
        status = "disabled";
};

&route_dsi0 {
        status = "okay";
	connect = <&vp1_out_dsi0>;
};

&dsi0 {
	//rockchip,lane-rate = <1000>;
        status = "okay";
	dsi0_panel: panel@0 {
		compatible = "simple-panel-dsi";
		reg = <0>;
		//power-supply = <&vcc3v3_lcd0_n>;
		//reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>;
		enable-gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>;
		pinctrl-0 = <&lcd_pwr_en_mipi &lcd_blk_en_mipi>;
		pinctrl-names = "default";
		backlight = <&backlight>;
		reset-delay-ms = <10>;
		enable-delay-ms = <10>;
		prepare-delay-ms = <5>;
		init-delay-ms = <20> ;
		unprepare-delay-ms = <10>;
		disable-delay-ms = <10>;
		dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
			MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET)>;
		dsi,format = <MIPI_DSI_FMT_RGB888>;
		dsi,lanes  = <4>;
		panel-init-sequence = [
					39 02 04 FF 98 81 03
					15 02 02 01 00
					15 02 02 02 00
					15 02 02 03 53    
					15 02 02 04 53    
					15 02 02 05 13
					15 02 02 06 04
					15 02 02 07 02
					15 02 02 08 02
					15 02 02 09 00
					15 02 02 0a 00
					15 02 02 0b 00
					15 02 02 0c 00
					15 02 02 0d 00
					15 02 02 0e 00
					15 02 02 0f 00
					15 02 02 10 00
					15 02 02 11 00
					15 02 02 12 00
					15 02 02 13 00
					15 02 02 14 00
					15 02 02 15 05  //gpm
					15 02 02 16 05  //gpm
					15 02 02 17 03  //gpm
					15 02 02 18 03  //gpm
					15 02 02 19 00
					15 02 02 1a 00
					15 02 02 1b 00
					15 02 02 1c 00
					15 02 02 1d 00
					15 02 02 1e c0
					15 02 02 1f 00
					15 02 02 20 02
					15 02 02 21 09
					15 02 02 22 00
					15 02 02 23 00
					15 02 02 24 00
					15 02 02 25 00
					15 02 02 26 00
					15 02 02 27 00
					15 02 02 28 55
					15 02 02 29 03
					15 02 02 2a 00
					15 02 02 2b 00
					15 02 02 2c 00
					15 02 02 2d 00
					15 02 02 2e 00
					15 02 02 2f 00
					15 02 02 30 00
					15 02 02 31 00
					15 02 02 32 00
					15 02 02 33 00
					15 02 02 34 00
					15 02 02 35 00
					15 02 02 36 00
					15 02 02 37 00
					15 02 02 38 3C
					15 02 02 39 00
					15 02 02 3a 00
					15 02 02 3b 00
					15 02 02 3c 00
					15 02 02 3d 00
					15 02 02 3e 00
					15 02 02 3f 00
					15 02 02 40 00
					15 02 02 41 00
					15 02 02 42 00
					15 02 02 43 00
					15 02 02 44 00
					15 02 02 50 01
					15 02 02 51 23
					15 02 02 52 45
					15 02 02 53 67
					15 02 02 54 89
					15 02 02 55 ab
					15 02 02 56 01
					15 02 02 57 23
					15 02 02 58 45
					15 02 02 59 67
					15 02 02 5a 89
					15 02 02 5b ab
					15 02 02 5c cd
					15 02 02 5d ef
					15 02 02 5e 01
					15 02 02 5f 0A     //FW_CGOUT_L[1] RESE_ODD
					15 02 02 60 02     //FW_CGOUT_L[2] VSSG_ODD
					15 02 02 61 02     //FW_CGOUT_L[3] VSSG_ODD
					15 02 02 62 08     //FW_CGOUT_L[4] STV2_ODD
					15 02 02 63 15     //FW_CGOUT_L[5] VDD2_ODD
					15 02 02 64 14     //FW_CGOUT_L[6] VDD1_ODD
					15 02 02 65 02     //FW_CGOUT_L[7]
					15 02 02 66 11     //FW_CGOUT_L[8] CK11
					15 02 02 67 10     //FW_CGOUT_L[9] CK9
					15 02 02 68 02     //FW_CGOUT_L[10]
					15 02 02 69 0F     //FW_CGOUT_L[11] CK7
					15 02 02 6a 0E     //FW_CGOUT_L[12] CK5
					15 02 02 6b 02     //FW_CGOUT_L[13]   
					15 02 02 6c 0D     //FW_CGOUT_L[14] CK3  
					15 02 02 6d 0C     //FW_CGOUT_L[15] CK1  
					15 02 02 6e 06     //FW_CGOUT_L[16] STV1_ODD  
					15 02 02 6f 02     //FW_CGOUT_L[17]   
					15 02 02 70 02     //FW_CGOUT_L[18]   
					15 02 02 71 02     //FW_CGOUT_L[19]   
					15 02 02 72 02     //FW_CGOUT_L[20]   
					15 02 02 73 02     //FW_CGOUT_L[21]   
					15 02 02 74 02     //FW_CGOUT_L[22]   
					15 02 02 75 0A     //BW_CGOUT_L[1]   RESE_ODD 
					15 02 02 76 02     //BW_CGOUT_L[2]   VSSG_ODD 
					15 02 02 77 02     //BW_CGOUT_L[3]   VSSG_ODD  
					15 02 02 78 06     //BW_CGOUT_L[4]   STV2_ODD 
					15 02 02 79 15     //BW_CGOUT_L[5]   VDD2_ODD 
					15 02 02 7a 14     //BW_CGOUT_L[6]   VDD1_ODD 
					15 02 02 7b 02     //BW_CGOUT_L[7]    
					15 02 02 7c 10     //BW_CGOUT_L[8]   CK11 
					15 02 02 7d 11     //BW_CGOUT_L[9]   CK9 
					15 02 02 7e 02     //BW_CGOUT_L[10]   
					15 02 02 7f 0C     //BW_CGOUT_L[11]  CK7
					15 02 02 80 0D     //BW_CGOUT_L[12]  CK5 
					15 02 02 81 02     //BW_CGOUT_L[13]   
					15 02 02 82 0E     //BW_CGOUT_L[14]  CK3 
					15 02 02 83 0F     //BW_CGOUT_L[15]  CK1 
					15 02 02 84 08     //BW_CGOUT_L[16]  STV1_ODD 
					15 02 02 85 02     //BW_CGOUT_L[17]   
					15 02 02 86 02     //BW_CGOUT_L[18]   
					15 02 02 87 02     //BW_CGOUT_L[19]   
					15 02 02 88 02     //BW_CGOUT_L[20]   
					15 02 02 89 02     //BW_CGOUT_L[21]   
					15 02 02 8A 02     //BW_CGOUT_L[22] 
					39 02 04 FF 98 81 04 	//self test  15 00 02 2F 01
					15 02 02 3B C0     // ILI4003D sel 
					15 02 02 6C 15
					15 02 02 6E 30     //VGH 16V   vgh Clamp level
					15 02 02 6F 33     //Pump ratio VGH=VSPX3 VGL=VSNX2
					15 02 02 8D 1F   // VGL clamp -12.03    LCD SPEC -12
					15 02 02 3A A4     //power saving
					15 02 02 35 17    // Source OP drive time
					15 02 02 87 BA
					15 02 02 26 76
					15 02 02 B2 D1
					15 02 02 B5 07
					15 02 02 88 0B
					15 02 02 21 30
					39 02 04 FF 98 81 01
					15 02 02 22 0A
					15 02 02 31 09   //zig-zag type1 09
					15 02 02 40 33   //for ext_cpck_sel
					15 02 02 42 44   //VGHL-CLK-SELA   VGHL-CLK-SELB
					15 02 02 53 2E  // FW VCOM
					15 02 02 55 88  // BW VCOM
					15 02 02 50 95    //Source 4.5, 95    AE 4.8
					15 02 02 51 95    //Source -4.5 95    AE -4.8
					15 02 02 60 30
					15 02 02 2E C8
					15 02 02 A0 0F        //VP255Gamma P
					15 02 02 A1 19               //VP251
					15 02 02 A2 28              //VP247
					15 02 02 A3 12              //VP243
					15 02 02 A4 14               //VP239
					15 02 02 A5 26               //VP231
					15 02 02 A6 1A               //VP219
					15 02 02 A7 1C               //VP203
					15 02 02 A8 7C               //VP175
					15 02 02 A9 1D               //VP144
					15 02 02 AA 2A               //VP111
					15 02 02 AB 6A               //VP80
					15 02 02 AC 18               //VP52
					15 02 02 AD 17               //VP36
					15 02 02 AE 4B               //VP24
					15 02 02 AF 21               //VP16
					15 02 02 B0 26               //VP12
					15 02 02 B1 4B               //VP8
					15 02 02 B2 6C               //VP4
					15 02 02 B3 3F               //VP0
					15 02 02 C0 01         //VN255 GAMMA N
					15 02 02 C1 18               //VN251
					15 02 02 C2 26               //VN247
					15 02 02 C3 0F              //VN243
					15 02 02 C4 12               //VN239
					15 02 02 C5 23               //VN231
					15 02 02 C6 18               //VN219
					15 02 02 C7 1C               //VN203
					15 02 02 C8 76               //VN175
					15 02 02 C9 1A               //VN144
					15 02 02 CA 26               //VN111
					15 02 02 CB 63               //VN80
					15 02 02 CC 1B              //VN52
					15 02 02 CD 1A               //VN36
					15 02 02 CE 4E               //VN24
					15 02 02 CF 21              //VN16
					15 02 02 D0 29               //VN12
					15 02 02 D1 47               //VN8
					15 02 02 D2 6A               //VN4
					15 02 02 D3 3F               //VN0
					39 02 04 FF 98 81 00
					05 02 01 35               //TE OUT
					05 78 01 11        //sleep out
					05 05 01 29        //display on
				];

		panel-exit-sequence = [
					05 16 01 28
					05 78 01 10
				];



               disp_timings0: display-timings {
                        native-mode = <&dsi0_timing0>;
                        dsi0_timing0: timing0 {
						clock-frequency = <145000000>;//mipi时钟的算法,根据如下的配置算出来的,如果不准确,或者时钟太低会导致屏闪的问题出现。
dsi clock = H-total * V-total * fps*位深 / lane numberl / 2  
          =(HSYNC+HBP+HACTIVE+HFP)*(VSYNC+VBP+VACTIVE+VFP) * 60 * 24 / 4 / 2 
						hactive = <1920>;//行有效像素
						vactive = <1200>;//场有效像素
						hback-porch = <12>;//行后肩
						hfront-porch = <128>;//行前肩
						hsync-len = <20>;//行同步
						vback-porch = <20>;//场后肩
						vfront-porch = <19>;//场前肩
						vsync-len = <4>;//场同步
						hsync-active = <0>;
						vsync-active = <0>;
						de-active = <0>;
						pixelclk-active = <0>;
						swap-rb = <0>;
						swap-rg = <0>;
						swap-gb = <0>;
                    };
                };

		ports {
			#address-cells = <1>;
			#size-cells = <0>;

			port@0 {
				reg = <0>;
				panel_in_dsi: endpoint {
					remote-endpoint = <&dsi_out_panel>;
				};
			};
		};
	};

	ports {
		#address-cells = <1>;
		#size-cells = <0>;

		port@1 {
			reg = <1>;
			dsi_out_panel: endpoint {
				remote-endpoint = <&panel_in_dsi>;
			};
		};
	};
};
&pinctrl {
	mipi_gpio {
		lcd_pwr_en_mipi:lcd_pwr_en_mipi {
			rockchip,pins = <0 RK_PC7 RK_FUNC_GPIO &pcfg_output_high>;
		};
		lcd_blk_en_mipi:lcd_blk_en_mipi {
			rockchip,pins = <3 RK_PA1 RK_FUNC_GPIO &pcfg_output_high>;
		};
	};

};






&i2c1 { //这是I2C的dts配置,我GM8775C是挂载到I2C1上的。
	status = "okay";
	
       gm8775c@2c {
               compatible = "gm8775c,mipi_to_lvds";
               reg = <0x2c>;
               status = "okay";
       };
}

3. GM8775Cの紹介とドライバファイルの書き方

       

        GM8775C には GM8775C_A1.1__IIC20190819.exe があり、構成ファイル、レジスタ、およびレジスタ内の対応する値を生成するために使用されます. 最初は、シェル スクリプトを介して i2c のアドレスを介して構成ファイルを書きましたが、一度電源を切ると、レジスタの値がデフォルト値に戻ります(ただし、デバッグするときは、より便利なシェルスクリプト方法を使用する必要があります。シェルスクリプトとその使用方法に関する記事が私の中にあります外部 LVDS 画面が明るくないため、GM8775C_A1.1__IIC20190819 によって生成されたファイルをドライバーにロードし、I2C ドライバーを自分で作成する必要があります。これは比較的簡単です。

         上記の構成は、独自の LVDS 画面のパラメーターに従って構成されます。そして、私の画面は上の図のいくつかの構成パラメーターです。

次はGM8775Cのドライバファイルです。

#include <linux/clk.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/of_gpio.h>
#include <linux/proc_fs.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/regmap.h>

#define REGISTER_NUM 34

struct gm8775c_priv {
	struct regmap *regmap;
	struct i2c_client *client;
	
};

//Modify screen parameters and modify default values
static const struct reg_default gm8775c_reg_defaults[] = {   
		{0x00,0xAA},
		{0x48,0x02},
		{0xB6,0x20},
		{0x01,0x80},
		{0x02,0xB0},
		{0x03,0x47},
		{0x04,0x80},
		{0x05,0x14},
		{0x06,0x0C},
		{0x07,0x00},
	    {0x08,0x13},
		{0x09,0x04},
		{0x0A,0x14},
		{0x0B,0x82},
		{0x0C,0x14},
		{0x0D,0x01},
		{0x0E,0x80},
		{0x0F,0x20},
		{0x10,0x20},
		{0x11,0x03},
		{0x12,0x1B},
		{0x13,0x63},
		{0x14,0x32},
		{0x15,0x10},
		{0x16,0x40},
		{0x17,0x00},
		{0x18,0x32},
		{0x19,0x10},
     	{0x1A,0x40},
		{0x1B,0x00},
		{0x1E,0x46},
		{0x51,0x30},
		{0x1F,0x10},
		{0x2A,0x01},
};

static int gm8775c_read(u8 reg, u8 * rt_value, struct i2c_client *client)
{
	int ret;
	u8 read_cmd[3] = { 0 };
	u8 cmd_len = 0;

	read_cmd[0] = reg;
	cmd_len = 1;

	if (client->adapter == NULL)
		printk("gm8775c_read client->adapter==NULL\n");

	ret = i2c_master_send(client, read_cmd, cmd_len);
	if (ret != cmd_len) {
		printk("gm8775c_read error1\n");
		return -1;
	}

	ret = i2c_master_recv(client, rt_value, 1);
	if (ret != 1) {
		printk("gm8775c_read error2, ret = %d.\n", ret);
		return -1;
	}

	return 0;
}

static int gm8775c_write(u8 reg, unsigned char value, struct i2c_client *client)
{
	int ret = 0;
	u8 write_cmd[2] = { 0 };

	write_cmd[0] = reg;
	write_cmd[1] = value;

	ret = i2c_master_send(client, write_cmd, 2);
	if (ret != 2) {
		printk("gm8775c_write error->[REG-0x%02x,val-0x%02x]\n",
		       reg, value);
		return -1;
	}

	return 0;
}

static const struct of_device_id gm8775_of_match[] = { 
	{
		.compatible = "gm8775c,mipi_to_lvds",
	}, 
	{ }
};
MODULE_DEVICE_TABLE(of, gm8775_of_match);

static const struct i2c_device_id gm8775_i2c_id[] = {
	{"GM8775C_MTL", 0},
	{}
};

static ssize_t gm8775c_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	int val=0, flag=0;
	u8 i=0, reg, num, value_w, value_r;

	
	struct gm8775c_priv *gm8775c = dev_get_drvdata(dev);
	
	val = simple_strtol(buf, NULL, 16);
	flag = (val >> 16) & 0xFF;
	
	if (flag) {
		reg = (val >> 8) & 0xFF;
		value_w = val & 0xFF;
		printk("\nWrite: start REG:0x%02x,val:0x%02x,count:0x%02x\n", reg, value_w, flag);
		while(flag--) {
			gm8775c_write(reg, value_w,  gm8775c->client);
			printk("Write 0x%02x to REG:0x%02x\n", value_w, reg);
			reg++;
		}
	} else {
		reg = (val >> 8) & 0xFF;
		num = val & 0xff;
		printk("\nRead: start REG:0x%02x,count:0x%02x\n", reg, num);
		do {
			value_r = 0;
			gm8775c_read(reg, &value_r, gm8775c->client);
			printk("REG[0x%02x]: 0x%02x;  ", reg, value_r);
			reg++;
			i++;
			if ((i==num) || (i%4==0))	printk("\n");
		} while (i<num);
	}
	
	return count;
}

static ssize_t gm8775c_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	printk("echo flag|reg|val > gm8775c\n");
	printk("eg read star addres=0x06,count 0x10:echo 0610 >gm8775c\n");
	printk("eg write star addres=0x90,value=0x3c,count=4:echo 4903c >gm8775c\n");
	return 0;
}

static DEVICE_ATTR(gm8775c, 0644, gm8775c_show, gm8775c_store);

static struct attribute *egm8775c_debug_attrs[] = {
	&dev_attr_gm8775c.attr,
	NULL,
};

static struct attribute_group gm8775c_debug_attr_group = {
	.name   = "gm8775c_debug",
	.attrs  = egm8775c_debug_attrs,
};

/*
 *****************************************************************************
 *
 *	Driver Interface
 *
 *****************************************************************************
 */

static int gm8775c_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	struct gm8775c_priv *gm8775c;
	int i;	
	int ret;
	
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
						 I2C_FUNC_SMBUS_BYTE_DATA)) {
			dev_err(&adapter->dev, "doesn't support I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK\n");
			return -ENODEV;
		}
	
	gm8775c = devm_kzalloc(&client->dev, sizeof(*gm8775c), GFP_KERNEL);
	if (!gm8775c)
		return -ENOMEM;
	
  	gm8775c->client = client;
	i2c_set_clientdata(client, gm8775c);
	for(i = 0;i < REGISTER_NUM; i++)
			gm8775c_write(gm8775c_reg_defaults[i].reg, gm8775c_reg_defaults[i].def, gm8775c->client);	

	ret = sysfs_create_group(&client->dev.kobj, &gm8775c_debug_attr_group);
	if (ret) {
		pr_err("failed to create attr group\n");
	}
	
	return ret;
}

static int gm8775c_remove(struct i2c_client *client)
{ 
	return 0;
}

static struct i2c_driver gm8775c_driver = {
	.driver = {
		.name = "gm8775c-mipi-to-lvds",
		.of_match_table = of_match_ptr(gm8775_of_match),
	},
	.probe = gm8775c_probe,
	.remove = gm8775c_remove,
	.id_table = gm8775_i2c_id,
};

static int __init gm8775c_modinit(void)
{
	int ret;
	ret = i2c_add_driver(&gm8775c_driver);
	if (ret != 0)
		printk("Failed to register gm8775c i2c driver : %d \n", ret);
	return ret;
}
late_initcall(gm8775c_modinit);

static void __exit gm8775c_exit(void)
{
	i2c_del_driver(&gm8775c_driver);
}

module_exit(gm8775c_exit);


//module_i2c_driver(gm8775c_driver);

MODULE_AUTHOR("Alexander Bigga <[email protected]>");
MODULE_DESCRIPTION("ST Microelectronics M41T80 series RTC I2C Client Driver");
MODULE_LICENSE("GPL");

要約する

        GM8775C ハードウェア接続は、システムの電源をオフにすることなく、可能な限りシステムに接続する必要があります。そうしないと、画面の電源をオフにした後でも、初期化するために対処する必要があります。

        上記の.exeファイルにはテストモードがあります.テストモードで画面をオンにできれば、8775C側の回路に問題がないことが証明されます.mipi側の構成ファイルのパラメータと8775C 側は正しいです。一致することができます。

        注: まず、mipi 端子から出力される信号が mipi 画面を点灯できることを確認してから、GM8775C 端子の問題を検討してください。

おすすめ

転載: blog.csdn.net/qq_48709036/article/details/124296103