1. MIPI Data 전송방식
MIPI-DSI Hardware 구조
ST MIPI-DSI 구조 (필독 자세한 설명이 나옴)
MIPI 관련내용
MIPI의 기본전송방식은 크게 Long Packet/ Short Packet 구조로 두개로 나누어지며, 세부적으로 Data ID에 따라 변경이 된다.
https://www.st.com/resource/en/application_note/dm00287601-dsi-host-on-stm32f469-479-stm32f7x8-x9-and-stm32l4r9-s9-mcus-stmicroelectronics.pdf |
- PH(Packet Header): Header는 ECC로 검증이가능
- Data Paylod
- PF(Packet Footer): Checksum으로 전체 Data가 검증가능
만약 S/W에서 MIPI 전송오류가 발생한다면, ECC or Checksum Error가 발생할 것이며, 이는 곳 MIPI가 고속 Serial 통신이므로,
HW 관련부분을 점검해봐야 할 것이다.
- 일반적인 HS(High Speed )모드 전송 방식
- Short Packet 전송 HS Mode
- Long Packet 전송 HS Mode (2 Lane)
1.1 Long Packet 과 Short Packet
MIPI에서 알아야 할 기본구조 전송방식이며, DataID 값도 같이 알아야 정확한 이해가 가능하다.
- Long Packet
- SoT(Start Of Transmission)
- Data ID(Virtual Channel ID) : 1byte
- Word Count: 2 bytes (Payload Size)
- ECC: 1 byte
- Data: Payload
- CheckSum: 2bytes
- EoT(End Of Transmission)
Kernel(drivers/gpu/drm/drm_mipi_dsi.c)
mipi_dsi_packet_format_is_long ( 이 함수를 보면 long packet의 종류를 파악)
- Short Packet
- SoT(Start Of Transmission)
- Data ID(Virtual Channel ID) : 1 byte
- Data 1/2: 2 bytes
- ECC: 1byte
- EoT(End Of Transmission)
Kernel (drivers/gpu/drm/drm_mipi_dsi.c)
mipi_dsi_packet_format_is_short ( 이 함수를 보면 short packet의 종류를 파악)
https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/drm_mipi_dsi.c#L369
https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/drm_mipi_dsi.c#L369
long/short packet (mipi_dsi_msg *msg ) 자체가 packet header 와 payload 가 포함됨
1.2 Packet 의 Data ID의 구조
- DI(Data ID) 에서 Virtual Channel ID 사용
- Virtual ID로 Logical Channel 구분
- Virtual Channel로 구성
1.2.1 Data ID->Data Type 의 값
- Data ID-> Data Type Class
아래와 같이 Data Type의 종류를 간단히 보고 세부 값들을 보자.
- Data Type 의 다양한 값의 의미
- Video: Display 관련 Video Signal
- Both: Master /Slave 동시사용
- Command: Master에서 주로 Command를 주는 것
- DCS: DCI 기반으로 DCS로 Display Command 가능
- VD(Video Display Packet)
- GN(General Packet)
상위 Data ID (DI) 값과 동일하며, Linux Source에서 동일하며, 상위 값 이외에도 다양하게 확장중이며, 아래와 같이 각 함수마다 호출되는 곳이 다르다. (주의)
- Linux Kernel 의 Data Type 값
//include/video/mipi_display.h /* MIPI DSI Processor-to-Peripheral transaction types */ enum { MIPI_DSI_V_SYNC_START = 0x01, MIPI_DSI_V_SYNC_END = 0x11, MIPI_DSI_H_SYNC_START = 0x21, MIPI_DSI_H_SYNC_END = 0x31, MIPI_DSI_COMPRESSION_MODE = 0x07, //mipi_dsi_compression_mode() MIPI_DSI_END_OF_TRANSMISSION = 0x08, //주의 SOT는 없어도 EOT는 별도로 존재 MIPI_DSI_COLOR_MODE_OFF = 0x02, MIPI_DSI_COLOR_MODE_ON = 0x12, MIPI_DSI_SHUTDOWN_PERIPHERAL = 0x22, //mipi_dsi_shutdown_peripheral() MIPI_DSI_TURN_ON_PERIPHERAL = 0x32, //mipi_dsi_turn_on_peripheral() MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM = 0x03, //mipi_dsi_generic_write -> mipi_dsi_device_transfer() MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM = 0x13, //mipi_dsi_generic_write -> mipi_dsi_device_transfer() MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM = 0x23, //mipi_dsi_generic_write -> mipi_dsi_device_transfer() MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM = 0x04, //mipi_dsi_generic_read -> mipi_dsi_device_transfer() MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM = 0x14, //mipi_dsi_generic_read -> mipi_dsi_device_transfer() MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM = 0x24, //mipi_dsi_generic_read -> mipi_dsi_device_transfer() MIPI_DSI_DCS_SHORT_WRITE = 0x05, //mipi_dsi_dcs_write_buffer->mipi_dsi_device_transfer() MIPI_DSI_DCS_SHORT_WRITE_PARAM = 0x15, //mipi_dsi_dcs_write_buffer->mipi_dsi_device_transfer() MIPI_DSI_DCS_READ = 0x06, MIPI_DSI_EXECUTE_QUEUE = 0x16, MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE = 0x37, //mipi_dsi_set_maximum_return_packet_size() MIPI_DSI_NULL_PACKET = 0x09, MIPI_DSI_BLANKING_PACKET = 0x19, MIPI_DSI_GENERIC_LONG_WRITE = 0x29, //mipi_dsi_generic_write MIPI_DSI_DCS_LONG_WRITE = 0x39, // mipi_dsi_dcs_write_buffer MIPI_DSI_PICTURE_PARAMETER_SET = 0x0a, //mipi_dsi_picture_parameter_set()->pps정의 MIPI_DSI_COMPRESSED_PIXEL_STREAM = 0x0b, MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20 = 0x0c, MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24 = 0x1c, MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16 = 0x2c, MIPI_DSI_PACKED_PIXEL_STREAM_30 = 0x0d, MIPI_DSI_PACKED_PIXEL_STREAM_36 = 0x1d, MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12 = 0x3d, MIPI_DSI_PACKED_PIXEL_STREAM_16 = 0x0e, MIPI_DSI_PACKED_PIXEL_STREAM_18 = 0x1e, MIPI_DSI_PIXEL_STREAM_3BYTE_18 = 0x2e, MIPI_DSI_PACKED_PIXEL_STREAM_24 = 0x3e, };
Kernel (include/video/mipi_display.h)
상위값으로 Data ID 값을 확인
1.3 DSI-DCS(Display Command Set)
DCS를 비롯하여, 모든 Data는 상위 Long Packet 과 Short Packet 구조를 가지고 있으며, DCS도 아래와 같이 Long Packet / Short Packet으로 구분
- DCS(Display Command Set)
Data ID만 변경하면 Long Packet/ Short Packet 구분되어 Header 구성되며, Payload에 DCS가 전달되는 구조임 (아래그림참조)
- DCS Command는 아래 참조 (Linux Kernel)
//include/video/mipi_display.h /* MIPI DCS commands */ enum { MIPI_DCS_NOP = 0x00, MIPI_DCS_SOFT_RESET = 0x01, MIPI_DCS_GET_COMPRESSION_MODE = 0x03, MIPI_DCS_GET_DISPLAY_ID = 0x04, MIPI_DCS_GET_ERROR_COUNT_ON_DSI = 0x05, MIPI_DCS_GET_RED_CHANNEL = 0x06, MIPI_DCS_GET_GREEN_CHANNEL = 0x07, MIPI_DCS_GET_BLUE_CHANNEL = 0x08, MIPI_DCS_GET_DISPLAY_STATUS = 0x09, MIPI_DCS_GET_POWER_MODE = 0x0A, MIPI_DCS_GET_ADDRESS_MODE = 0x0B, MIPI_DCS_GET_PIXEL_FORMAT = 0x0C, MIPI_DCS_GET_DISPLAY_MODE = 0x0D, MIPI_DCS_GET_SIGNAL_MODE = 0x0E, MIPI_DCS_GET_DIAGNOSTIC_RESULT = 0x0F, MIPI_DCS_ENTER_SLEEP_MODE = 0x10, MIPI_DCS_EXIT_SLEEP_MODE = 0x11, MIPI_DCS_ENTER_PARTIAL_MODE = 0x12, MIPI_DCS_ENTER_NORMAL_MODE = 0x13, MIPI_DCS_GET_IMAGE_CHECKSUM_RGB = 0x14, MIPI_DCS_GET_IMAGE_CHECKSUM_CT = 0x15, MIPI_DCS_EXIT_INVERT_MODE = 0x20, MIPI_DCS_ENTER_INVERT_MODE = 0x21, MIPI_DCS_SET_GAMMA_CURVE = 0x26, MIPI_DCS_SET_DISPLAY_OFF = 0x28, MIPI_DCS_SET_DISPLAY_ON = 0x29, MIPI_DCS_SET_COLUMN_ADDRESS = 0x2A, MIPI_DCS_SET_PAGE_ADDRESS = 0x2B, MIPI_DCS_WRITE_MEMORY_START = 0x2C, MIPI_DCS_WRITE_LUT = 0x2D, MIPI_DCS_READ_MEMORY_START = 0x2E, MIPI_DCS_SET_PARTIAL_ROWS = 0x30, /* MIPI DCS 1.02 - MIPI_DCS_SET_PARTIAL_AREA before that */ MIPI_DCS_SET_PARTIAL_COLUMNS = 0x31, MIPI_DCS_SET_SCROLL_AREA = 0x33, MIPI_DCS_SET_TEAR_OFF = 0x34, MIPI_DCS_SET_TEAR_ON = 0x35, MIPI_DCS_SET_ADDRESS_MODE = 0x36, MIPI_DCS_SET_SCROLL_START = 0x37, MIPI_DCS_EXIT_IDLE_MODE = 0x38, MIPI_DCS_ENTER_IDLE_MODE = 0x39, MIPI_DCS_SET_PIXEL_FORMAT = 0x3A, MIPI_DCS_WRITE_MEMORY_CONTINUE = 0x3C, MIPI_DCS_SET_3D_CONTROL = 0x3D, MIPI_DCS_READ_MEMORY_CONTINUE = 0x3E, MIPI_DCS_GET_3D_CONTROL = 0x3F, MIPI_DCS_SET_VSYNC_TIMING = 0x40, MIPI_DCS_SET_TEAR_SCANLINE = 0x44, MIPI_DCS_GET_SCANLINE = 0x45, MIPI_DCS_SET_DISPLAY_BRIGHTNESS = 0x51, /* MIPI DCS 1.3 */ MIPI_DCS_GET_DISPLAY_BRIGHTNESS = 0x52, /* MIPI DCS 1.3 */ MIPI_DCS_WRITE_CONTROL_DISPLAY = 0x53, /* MIPI DCS 1.3 */ MIPI_DCS_GET_CONTROL_DISPLAY = 0x54, /* MIPI DCS 1.3 */ MIPI_DCS_WRITE_POWER_SAVE = 0x55, /* MIPI DCS 1.3 */ MIPI_DCS_GET_POWER_SAVE = 0x56, /* MIPI DCS 1.3 */ MIPI_DCS_SET_CABC_MIN_BRIGHTNESS = 0x5E, /* MIPI DCS 1.3 */ MIPI_DCS_GET_CABC_MIN_BRIGHTNESS = 0x5F, /* MIPI DCS 1.3 */ MIPI_DCS_READ_DDB_START = 0xA1, MIPI_DCS_READ_PPS_START = 0xA2, MIPI_DCS_READ_DDB_CONTINUE = 0xA8, MIPI_DCS_READ_PPS_CONTINUE = 0xA9, };
Kernel (include/video/mipi_display.h)
- DCS 로 제어는 아래의 함수이용
- mipi_dsi_dcs_write
- mipi_dsi_dcs_write_buffer
1.4 일반적인 DSI Write
우선 LCD Initial Code는 이전에 병렬에서 맞춰주던 Hsync/Vsync를 비롯하여, LCD의 Data Format 및 기타 설정을 위해서 MIPI Interface로 설정을 해준다.
- 일반적인으로 DSI 사용되는 함수
- mipi_dsi_generic_write
- mipi_dsi_generic_read
상위 함수를 이용하여 자동으로 Long or Short 선택되어 Header가 구성되어 read/write 되지만, 상위 Data ID는 상위에 정해짐
반드시 LCD Datasheet를 참조하여, Payload에 들어가는 Header에 Data ID도 확인가능하다며 확인하자.
본인이 LCD Spec에서 DCS Command 사용여부에 맞게 선택해서 함수도 맞게 넣어 개발하는 것이 맞을 것이라고 본다.
- mipi_dsi_dcs_write_buffer : DCS + Payload
- mipi_dsi_generic_write : Payload
- 기타 MIPI-DSI Debug 관련내용
2. GPU의 DRM (Direct Rendering Manager)
처음 DRM의 약자를 Digital Right Management로 착각했으며, 예전에 HDMI Device Driver 개발당시 HDCP와 유사한 기능이라고 착각했다.
DRM은 GPU기반으로 빠른 Rendering을 지원하기 위해서 제공해주는 기능이며, 이전에 Frame buffer Driver만 개발했던 나에게 다소 생소했는데,
각 여러 Layer들을 쉽게 Rotate/Scale/Crop/Overlay되는 것을 보고 이 기능에 조금 놀라웠다.
이전에 TI DSP기반으로했던, Davinci의 경우 Scale 과 Crop은 가능했던걸로 기억하지만, 많은 Layer들은 제어하지는 못했는데, DRM은 GPU를 통해서 다양한 기능을 제공한다.
한마디로 GPU에서 확장된 Frame Buffer라고 생각하면 될 것 같으며, Overlay 기능역시 GPU에 따라 다른 것 같다.
- FrameBuffer 와 DRM(Direct Rendering Manager) 비교
Kernel DRM Driver 기본구조
Kernel GPU DRM-KMS(Kernel Mode Setting)
상위 MIPI-DSI의 HW Dispaly 관련 출력설정
Kernel GPU DRM-Memory 관리
2.1 각 Chip Vendor들의 DRM
DRM Driver 전체 Source
Kernel GPU NXP DRM
Kernel GPU Broadcom의 (Video Core4)
Kernel GPU NVIDIA의 DRM
TI사의 DSS와 DRM 부분
2.2 Frame Buffer vs DRM 기반의 Pannel
- Frame Buffer LCD Initial Code
- DRM 기반의 LCD Initial Code
DRM기반의 실제 Panel Driver들의 다양한 예제이며, SPI와 I2C 및 GPIO와도 연결되어 구성되므로 참고
DRM(Direct Rendering Manager)로 GPU기반으로 DBI (이전의 ST 칩의 DBI라고 생각하면됨)
mipi_dsi_dcs_xxx 함수들은 내부적으로 dcs command를 호출
- i.MX 의 경우 i.MX6는 Framebuffer Driver
Table 64. MIPI DSI Driver Files // Frame buffer 기반 Driver 와 DRM 기반 Driver들 File Description drveirs/video/fbdev/mxc/mipi_dsi.c MIPI DSI IP Frame buffer driver source file drivers/video/fbdev/mxc/mipi_dsi.h MIPI DSI IP Frame bufferdriver header file drivers/video/fbdev/mxc/mxcfb_hx8369_wvga.c MIPI DSI Frame bufferDisplay Panel driver source file drivers/video/fbdev/mxc/mipi_dsi_samsung.c MIPI DSI Frame buffer Samsung source file drivers/video/fbdev/mxc/mipi_dsi_northwest.c MIPI DSI Frame buffer Northwest source file drivers/video/fbdev/mxc/mxcfb_hx8363_wvga.c i.MX 7 Frame buffer Truly WVGA Panel TFT3P5581E drivers/video/fbdev/mxc/mxcfb_hx8369_wvga.c i.MX 6 Frame buffer Truly WVGA sync panel drivers/video/fbdev/mxc/mxcfb_otm808b_wvga.c Truly Frame buffer WVGA Panel TFT3P5079E
- i.MX의 경우 i.MX 8은 DRM Driver
drivers/gpu/drm/imx/sec_mipi_dsmi-imx.c Samsung DRM driver drivers/gpu/drm/imx/nwl_dsi-imx.c Northwest DRM driver
i.MX MIPI DSI Info
https://community.nxp.com/t5/i-MX-Processors/MIPI-DSI-panel-support-on-iMX8M-Mini/m-p/1001986
https://community.nxp.com/t5/i-MX-Processors/MIPI-DSI-panel-support-on-iMX8M-Mini/m-p/1001986
Device Tree