mipi_dsi interface to lvds display (GM8775C)

Table of contents


foreword

This article mainly explains the mipi DSI protocol, the debugging record of mipi, and the debugging record of the mipi-to-LVDS adapter chip GM8775C.

Scenario: Since our company needs to use the mipi dsi interface for LVDS, we need to use the GM8775C adapter chip. The chip is dual-channel, which means that two LVDS screens can be connected externally. But our company only connects one LVDS screen externally, of course it depends on the connection method with your circuit.

Analysis: In this case, we need to debug two modules, one is the mipi screen end, the other end is the GM8775C conversion chip end, and GM8775C has no driver code, we need to write and add it ourselves, but this is also very simple, because it is actually It is an I2C device.


1. Introduction to MIPI_DSI protocol

MIPI-DSI is a serial interface applied to display technology, compatible with DPI (Display Pixel Interface, Display Pixel Interface), DBI (Display Bus Interface, Display Bus Interface) and DCS (Display Command Set, Display Command Set), to Send pixel information or instructions to peripherals in a serial manner, and read status information or pixel information from peripherals, and enjoy its own independent communication protocol during transmission, including data packet format and error correction and error detection mechanism.

MIPI-DSI has two working modes: high-speed mode and low-speed mode. All data channels (1~4 sets of data channels can be used for unidirectional high-speed transmission, but only the first data channel can be used for low-speed bidirectional transmission (if it is If there are 4 data lines, data0 can be used for two-way transmission in low-speed mode, while data1-data3 can only be transmitted in one direction). Peripheral status information, pixel format and other information are returned through the first data channel. The clock channel is used In the process of transmitting data, synchronous clock signals are transmitted (strictly speaking, in low-speed mode, parameters are generally sent or peripheral status is read, and clock synchronization is not required in low-speed mode, because the data channel In a low-speed mode, synchronization can be achieved by using a differential signal itself).

1. Explanation of terms

1. DCS (DisplayCommandSet): DCS is a standardized command set for display modules in command mode.

• DSI, CSI (DisplaySerialInterface, CameraSerialInterface

  • DSI defines a high-speed serial interface between the processor and the display module.

  • CSI defines a high-speed serial interface between the processor and the camera module.

• D-PHY: Provides physical layer definitions for DSI and CSI

 2. DSI hierarchical structure

DSI is divided into four layers, corresponding to D-PHY, DSI, and DCS specifications, and the layered structure diagram is as follows:
• PHY defines the transmission medium, input/output circuits, and clock and signal mechanisms.
• Lane Management layer: Send and collect data flow to each lane.
• Low Level Protocol layer: defines how to frame and parse and error detection.
• Application layer: describes high-level encoding and parsing data flow.

3. Command and Video mode
• DSI-compatible peripherals support Command or Video operation mode, which mode is determined by the peripheral architecture
• Command mode refers to sending commands and data to the controller with display buffer. The host indirectly controls the peripherals through commands. Command mode uses a bidirectional interface.
• Video mode refers to the real-time pixel streaming from the host to the peripheral. This mode can only transmit at high speed. To reduce complexity and save cost, systems that only use Video mode may have only one unidirectional data path.

4. Three main lane types

  • One-way clock Lane

  • Unidirectional Data Lane

  • Bidirectional Data Lane

5. D-PHY transmission mode

  • Low-Power signaling mode (for control): 10MHz (max)

  • High-speed (High-Speed) signal mode (for high-speed data transmission): 80Mbps ~ 1Gbps/Lane

• The D-PHY low-level protocol stipulates that the minimum data unit is one byte

  • When sending data, the low bit must come first, and the high bit must follow.

• D-PHY for mobile applications

  • DSI: Display Serial Interface

     • One clock lane, one or more data lanes 

  • CSI: Camera Serial Interface

6. Lane module

• PHY consists of D-PHY (Lane module)

• D-PHY may contain:

  • Low Power Transmitter (LP-TX) 

  • Low Power Receiver (LP-RX)

  • High Speed ​​Transmitter (HS-TX)  

  • High Speed ​​Receiver (HS-RX)

  • Low Power Contention Detector (LP-CD)

7. Three main lane types

  • One-way clock Lane

    • Master:HS-TX, LP-TX

    • Slave:HS-RX, LP-RX

  • Unidirectional Data Lane

    • Master:HS-TX, LP-TX

    • Slave:HS-RX, LP-RX

  • Bidirectional Data Lane

    • Master, Slave:HS-TX, LP-TX, HS-RX, LP-RX, LP-CD

8. Lane status and voltage

  • Lane status 

    • LP-00, LP-01, LP-10, LP-11 (single-ended)

    • HS-0, HS-1 (differential)

  • Lane voltage (typical) 

    • LP:0-1.2V

    • HS:100-300mV (200mV)

2. Layering of DSI application circuits

MIPI-DSI is divided into four layers: application layer , protocol layer, channel management layer, and physical layer. MIPI-DSI is a communication protocol applied to the interface, and its overall circuit work cooperates with each layer defined by the protocol. As shown below:

Application layer : According to the needs of the application module, the sent command and data are initially encoded and converted into the format specified by MIPI-DSI at the sending end, and the received data is restored to the data format supported by the application module at the receiving end. sequence requirements. 

Protocol layer : Information transmission adopts data packet format, including long data packet and short data packet. When sending data, the data is compressed according to the information type and content, and the generation of ECC code and the addition of CRC code are completed. When receiving data, the error detection and correction is performed on the entire data packet according to the ECC code and CRC code, and the decoding of the packet header and data content is completed and sent to the application layer reasonably.

Channel management layer : According to the N (at most 4) data channels set by the design, this layer divides the data to be sent into N groups according to the order of the channels and sends them to the corresponding data channels so that they can be sent simultaneously through the data channels to the slave side. At the receiving end, what this layer needs to do is to combine the received N sets of data to restore the original data sequence. 

Physical layer : When receiving a low-speed transmission request, the logic circuit serializes the instruction or data to be sent, and controls the output of a high-swing low-power level to perform a low-power transmission request, and then serializes the instruction or data Loaded to the channel, the receiving end recognizes the transmission mode to complete the parallel conversion of serial data. After receiving a high-speed request, the circuit sends a high-swing and low-power consumption level for high-speed transmission request, and then drives the differential drive module to transmit on the channel with a low-swing signal after serial conversion of the data to be sent, and the receiving end recognizes After the high-speed mode, the synchronous signal is detected correctly, and the high-speed serial data is successfully received after serial-to-parallel conversion. In addition, the bus control right can be exchanged between the master and the slave. The sender sends a bus abandonment request, and the receiver controls the bus to initiate a response after receiving the request. The overall process is a TA (turn around) operation. When the host needs to obtain the data received by the slave or read the parameters of the display module or display data, the host initiates a TA operation, and automatically initiates the TA operation after the slave sends data to return the bus control. (In general, it is an interactive process, a bit like TCP three-way handshake and four-way wave. In the process of interaction, some instructions will be sent, and the specific performance of the response data depends on the specific module analysis. It can also be used in the data analyzed in the waveform.)

MIPI-DSI physical layer (D-PHY protocol)

        In the physical layer of the entire protocol, a synchronous connection is used between the master end and the slave end, the clock channel is used to transmit high-speed clocks, and one or more data channels are used to transmit low-power data signals or high-speed data signals. Each channel utilizes two interconnection wires to realize the connection between the master end and the slave end, and supports high-speed mode and low-speed ESCAPE mode. In high-speed mode, the transmitter drives the only two interconnect lines of the channel at the same time, outputting low-swing differential signals, such as 200mV; Relatively large amplitude, such as 1.2V.
                            

Key summary:

       

The signal has two working states, high-speed mode state (HS) and low-speed mode state (LP).
The physical layer is to control the hardware signal (timing), MIPI-DSI two signal types: clock lane, two lines, one Dp, Dn.
Data lane, two lines, one Dp, Dn; there are multiple data lanes according to requirements, at least one lane (lane0), at most 4 lanes (lane0, lane1, lane2, lan3), of which only lane0 is bidirectional (low speed mode bidirectional , high-speed mode can only be one-way), others can only be one-way (high-speed mode one-way), as we mentioned before.

The two ends of the interconnection line are the drive unit and the receiver unit. The drive unit has a differential transmission module (HS_TX) and a low-power single-ended transmission module (LP_TX), and the receiving unit has a differential reception module (HS_RX) and a low-power single-ended reception module (LP_RX).

Data lane level:

Low-speed mode LP: 0-1.2V, idle level (LP11) Dp, Dn is 1.2V.
High-speed mode HS: 100-300mV (200mV)
data channel status table diagram:

         The data channel has 6 states: HS-0, HS-1, LP00, LP01, LP10, LP11.
Among them, HS-0 indicates that the Dp of the data lane in high-speed mode is low, and the Dn bit is high, and LP01 indicates the Dp of the data lane in low-speed mode. is low and Dn is high. After the system is powered on, LP11 remains for about 100us (hardware initialization), and then enters the stop state. The transition between modes must return to this state. The general control state is also the LP11 state. Conversion between modes will be described later. Now that these 6 states are mentioned, a picture has to be attached. The six state transition diagrams are as follows:

The differential transmission module (HS_TX) drives the interconnection line with a differential signal, and there are two states on the high-speed channel: differential-0 and differential-1. The low-power single-ended transmit module (LP_TX) drives two interconnect lines independently, and there are four different states on the channel: LP00, LP01, LP10, and LP11. The protocol defines specifically the line level and sets three working modes: high-speed mode, control mode and ESCAPE mode. The channel defaults to control mode, and the line is in STOP state. When the channel needs to enter high-speed mode or ESCAPE mode, the sending module needs to drive the line LP01 or LP10 to send a request to the receiving end. After the request sequence is sent, the corresponding working mode will be carried out, and the LP11 will be sent to exit and return to the STOP control state. The receiving end needs to perform LP-RX reception at all times, detect the line level and clarify the working mode of the channel.

The specific operation process:

 • Three operation modes of Data Lane 

    • Escape mode, High-Speed(Burst) mode, Control mode

  • The possible events from the stop state of the control mode are: 

    • Escape mode request (LP-11→LP-10→LP-00→LP-01→LP-00)

    • High-Speed mode request (LP-11→LP-01→LP-00)

    • Turnaround request (LP-11→LP-10→LP-00→LP-10→LP-00)

  •  Escape mode is a special operation of data Lane in LP state 

    • In this mode, some extra functions can be entered: LPDT, ULPS, Trigger

    •Data Lane enters Escape mode through LP-11→LP-10→LP-00→LP-01→LP-00

    • Once in Escape mode, the sender must send an 8-bit command to respond to the requested action

    • Escape mode Use Spaced-One-Hot Encoding

  • Ultra-Low Power State (Ultra-Low Power State)
    • In this state, the lines are in an empty state (LP-00)
  • The ultra-low power state of the clock Lane
    • The clock Lane passes through LP-11→LP-10→LP- 00 to enter ULPS state
    • Exit this state through LP-10 → TWAKEUP → LP-11, the minimum TWAKEUP time is 1ms

  • High-speed data transfer
    • The act of sending high-speed serial data is called high-speed data transfer or burst (burst)

    • All Lanes gates start synchronously and may end at different times.
    • The clock should be in high-speed mode

  • Transmission process in each mode of operation

    •The process of entering Escape mode: LP-11→LP-10→LP-00→LP-01→LP-00→Entry Code → LPD (10MHz) •The process of exiting Escape mode: LP-10→LP-11
    •
    Enter Process of high speed mode: LP-11→LP-01→LP-00→SoT(00011101)→HSD (80Mbps ~ 1Gbps)
    Process of exiting high speed mode: EoT→LP-11
    Control mode - BTA transmission process (the process When master-slave exchange, as the command parameter sent by the master): LP-11→LP-10→LP-00→LP-10→LP-00 • Control mode - BTA
    receiving process (ACK is the slave machine’s response to the master Command parameters): LP-00→LP-10→LP-11

Note: Is it a bit like the TCP three-way handshake and four-way handshake I mentioned above?

Continue below! ! ! ! ! ! ! ! !

The data transmission between the master and the slave is in a synchronous manner, and it is in DDR mode, that is, double-edge triggering ; this can double the data transmission rate without changing the clock frequency, and use bandwidth resources more effectively. The physical layer of the host serially converts the data distributed by the channel management layer into differential signals and sends them to the data line, and generates differential clocks at the same time. Each data channel is sent in parallel, with a maximum of 4 channels and a minimum of 1 channel , depending on bandwidth requirements. The physical layer of the slave is responsible for capturing 0 or 1 from the differential serial bit stream, that is, when Dp is higher than Dn, it is 1, and when Dn is higher than Dp, it is 0, and then forms 8-bit data and sends it to the channel management layer. At the same time, the horizontal synchronization signal and vertical synchronization signal can also be detected from the data packet. The HS mode needs to rely on a high-speed clock, and the LP mode does not need a high-speed clock, only a differential signal line is required. The clock at this time is obtained by the exclusive OR of the differential lines Dp and Dn .

                                                             HS mode (high speed mode timing chart)

                                                             LP Mode (Low Power Mode Timing Diagram)        

Here you need to carefully analyze the diagram, and then make a comparison with the process we mentioned above, and you will find it suddenly clear! ! , Good guy, I actually used an idiom, hahahaha! ! ! !

I feel that there is still a lot to know, so I will update it slowly in the future! ! Serve the main course first. ! ! !

2. MIPI debugging

         The code on the MIPI side does not require us to touch its architecture. The most important thing is the configuration of the dts file. Not much to say, let’s serve! ! !

#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. Introduction to GM8775C and writing of driver files

       

        GM8775C will have a GM8775C_A1.1__IIC20190819.exe, which is used to generate configuration files, registers and the corresponding values ​​in the registers. At first, I wrote the configuration file through the address of the i2c through the shell script, but once the power is off , the value in the register is restored to the default value (but when we debug, we need to use the shell script method, which is more convenient. There are articles related to shell script and how to use it in my blog), which will lead to The external LVDS screen is not bright, so we need to load the file generated by GM8775C_A1.1__IIC20190819 into the driver, and write an I2C driver by ourselves, which is relatively simple.

         The above configuration is configured according to the parameters of your own LVDS screen. And my screen is some configuration parameters in the picture above.

Next is the driver file of 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");

Summarize

        The GM8775C hardware connection should be connected to it as far as possible without powering off the system, so that it cannot be powered off, otherwise, after the power off of the screen, we still need to deal with it to initialize it.

        The .exe file mentioned above has a test mode. If your test mode can turn on the screen, it proves that there is no problem with the circuit on your 8775C side. You need to analyze whether the configuration file parameters on the mipi side and the 8775C side are correct. able to match.

        Note: First, ensure that the signal output from the mipi terminal can light up the mipi screen, and then consider the problem at the GM8775C terminal.

Guess you like

Origin blog.csdn.net/qq_48709036/article/details/124296103