Linux v6.18.37 · DRM · 디스플레이 전송

Linux MIPI DSI: 전송 요청에서 패킷 헤더까지

명령의 종류와 길이를 고르는 일, 헤더 바이트를 만드는 일, 실제 링크로 전송하는 일은 서로 다른 단계입니다.

요청 구조체를 만들었다고 전송이 끝난 것은 아닙니다

mipi_dsi_msg는 가상 채널 channel, 트랜잭션 종류 type, 전송 옵션 flags, 송수신 버퍼와 길이를 담습니다. 이 구조체 자체가 PHY에서 관찰한 바이트열은 아닙니다. 카메라의 CSI-2 프레임 수신을 다루는 V4L2 버퍼 경로와도 구분해야 합니다.

  1. DCS 또는 generic 쓰기 함수

    송신 데이터 길이로 메시지의 data type을 고릅니다.

  2. mipi_dsi_device_transfer()

    호스트의 .transfer()가 없으면 -ENOSYS를 반환합니다. 장치에 MIPI_DSI_MODE_LPM이 설정돼 있으면 메시지에 MIPI_DSI_MSG_USE_LPM을 추가한 뒤 콜백을 호출합니다.

  3. 호스트 드라이버

    컨트롤러별 전송을 수행합니다. mipi_dsi_create_packet() 사용 여부와 이후 FIFO·DMA·오류 처리는 호스트 구현을 따라야 합니다.

공통 진입점이 패킷 생성 함수를 자동으로 먼저 호출하는 구조는 아닙니다. 또한 콜백은 호스트의 전원 상태와 무관하게 호출될 수 있으므로, 전원이 필요한 구현은 사용 가능한 상태를 확보해야 합니다. 성공 반환값의 계약은 쓰기에서 보낸 데이터 바이트 수, 읽기에서 받은 데이터 바이트 수입니다. 이를 선로의 헤더·CRC를 포함한 총 바이트 수나 화면 표시 성공으로 해석하지 않습니다.

DCS와 generic은 같은 길이여도 타입이 다릅니다

아래 길이는 함수에 넘긴 송신 버퍼의 바이트 수입니다. mipi_dsi_dcs_write_buffer()에서는 DCS 명령 바이트도 길이에 포함됩니다. 명령을 제외한 파라미터 수와 혼동하지 않습니다.

고정 버전의 쓰기 함수 선택
송신 길이DCS write bufferGeneric write
0-EINVALshort, 0x03
1short, 0x05short, 0x13
2short + parameter, 0x15short, 0x23
3 이상long, 0x39long, 0x29

타입이 선택됐다고 해서 임의 길이의 데이터가 모든 컨트롤러·패널에서 허용되는 것은 아닙니다. 패널의 명령 의미와 호스트의 전송 크기 제한은 별도로 확인합니다. 이 표는 읽기 요청, 영상 스트림과 모든 DSI 타입을 나열한 전체 사양표가 아닙니다.

바이트 계산 예시

채널 2, DCS long write 0x39, 송신 길이 3이면 (2 << 6) | 0x39 = 0xB9이므로 헤더는 B9 03 00 00입니다. payload 길이는 3, 이 구조체의 size는 7입니다. payload의 명령이 특정 패널에 유효하다는 뜻은 아닙니다.

모두 실제로 전송하지 않은 소프트웨어 예시
요청채널송신 바이트중간 헤더payload 길이 / size
DCS long2AA BB CCB9 03 00 003 / 7
DCS short01105 11 00 000 / 4
DCS short + parameter151 8055 51 80 000 / 4
Generic short, 0 byte0없음03 00 00 000 / 4

다음 JavaScript는 표의 쓰기 타입과 헤더 배치를 확인하는 참고 모델입니다. Linux 드라이버를 실행하는 코드가 아니며 데이터 길이를 0–65535로 제한합니다. 이 제한과 입력 검사는 예시의 추가 조건으로, 공통 C 함수가 똑같은 검사를 한다는 뜻이 아닙니다.

function writePacket(kind, channel, data) {
  if (!['dcs', 'generic'].includes(kind) ||
      !Number.isInteger(channel) || channel < 0 || channel > 3 ||
      !(data instanceof Uint8Array) || data.length > 65535)
    throw new RangeError('outside reference model');
  const n = data.length;
  if (kind === 'dcs' && n === 0) throw new RangeError('empty DCS');
  const type = kind === 'dcs'
    ? (n === 1 ? 0x05 : n === 2 ? 0x15 : 0x39)
    : (n === 0 ? 0x03 : n === 1 ? 0x13 : n === 2 ? 0x23 : 0x29);
  const isLong = n > 2;
  const header = new Uint8Array([
    (channel << 6) | type,
    isLong ? n & 255 : (data[0] ?? 0),
    isLong ? (n >> 8) & 255 : (data[1] ?? 0),
    0
  ]);
  return {type, header, payload: isLong ? data : null,
          payloadLength: isLong ? n : 0, size: 4 + (isLong ? n : 0)};
}

패킷 생성에 성공해도 확인되지 않는 것

  • 완전한 길이 검증: 고정 C 함수는 short 타입의 tx_len > 2를 여기서 거절하지 않고 첫 두 바이트만 취합니다. Long의 길이도 헤더에는 하위 16비트만 들어가지만 payload_length에는 전체 tx_len을 넣습니다. 임의 메시지의 길이 일관성을 이 함수 하나가 보장한다고 가정하지 않습니다.
  • 버퍼 수명: Long payload는 복사본이 아니라 원래 버퍼를 가리킵니다. 메시지·패킷을 만들었다고 해서 버퍼를 곧바로 해제해도 되는 것은 아닙니다. 사용 중인 호스트의 전송·완료 계약을 따라야 합니다.
  • 실제 링크 오류: ECC 위치가 0이라는 관찰만으로 PHY·배선·패널의 오류 원인을 알 수 없습니다. 호스트의 상태·오류 보고, 패널 응답과 해당 부품의 설정·전원 조건을 구분해 조사합니다.

코드와 표는 타입 선택·바이트 순서·길이 경계·payload 참조 관계를 자동 검사했습니다. 커널의 C 함수를 실행하거나 실제 DSI 호스트·패널을 구동한 시험, PHY 캡처, 회원 전용 MIPI 사양 전체 검토는 수행하지 않았습니다.

English summary (not a full translation)

A Linux DSI message is a host transfer request, not a captured wire packet. DCS and generic write helpers select different types by buffer length. In Linux v6.18.37, the common packet builder puts channel/type in byte 0 and a length or two data bytes in bytes 1–2. It leaves the ECC byte uncomputed and counts only header plus payload. Payload storage is borrowed. The reference model adds input limits; it does not prove hardware behavior or reproduce all kernel validation.

분석 기준

Linux v6.18.37, 고정 커밋 0c503cf3dde2e53614f05261ece12f9d3d4c3c20의 다음 세 파일을 대조했습니다. 다른 버전·호스트의 동작은 다시 확인해야 합니다.