uzbek-plus/b9/b9a/decode-panel.py
q 4a7224c41f B9: built-in display (ST7735S SPI) in Linux and persistent B9C cache
- B9A: read-only audit of stock LK/DT: the panel is an ST7735S 128x128 on SPI (BLSP1 QUP4,
  16 MHz, mode 3, D/C GPIO116, RESET GPIO118), backlight = PM8916 MPP4 current sink 40 mA.
- B9B: upstream panel-mipi-dbi with the stock init sequence as firmware; MPP4 sink via pinctrl
  + gpio-backlight; first light with correct colours/orientation/offsets.
- B9C: fbcon (6x8, 21x16) on tty1 + getty, UART console kept, aurora-display service;
  cache B9C b9ce13c9 written and verified, cold boots with LTE + Wi-Fi + display.
- B9L (RAM only): lk2nd second stage with an msm8916 SPI panel port shows a picture before Linux.
- Sanitizer: whitelist for b8/ and b9/.
2026-10-03 01:45:02 +03:00

45 lines
2.2 KiB
Python

#!/usr/bin/env python3
"""B9A read-only: decode the ST7735S init sequence from (a) stock LK lk.bin command table and
(b) stock dtb_01 qcom,mdss-spi-on-command, and compare them byte-for-byte.
LK table (gcdb mdss_spi_cmd, 16 B each): u32 size, u32 payload_ptr, u32 wait_ms, u8 cmds_post_tg.
DT format (msm-3.10 mdss_spi_panel): repeated [wait_ms, len, cmd, params...]; wait applies after the command.
usage: decode-panel.py lk.bin dtb_01.dts"""
import re, struct, sys
BASE = 0x8f600000
lk = open(sys.argv[1], 'rb').read()
dts = open(sys.argv[2]).read()
NAMES = {0x01: 'SWRESET', 0x11: 'SLPOUT', 0x20: 'INVOFF', 0x21: 'INVON', 0x28: 'DISPOFF', 0x29: 'DISPON',
0x2a: 'CASET', 0x2b: 'RASET', 0x2c: 'RAMWR', 0x36: 'MADCTL', 0x3a: 'COLMOD', 0xb1: 'FRMCTR1',
0xb2: 'FRMCTR2', 0xb3: 'FRMCTR3', 0xb4: 'INVCTR', 0xc0: 'PWCTR1', 0xc1: 'PWCTR2', 0xc2: 'PWCTR3',
0xc3: 'PWCTR4', 0xc4: 'PWCTR5', 0xc5: 'VMCTR1', 0xe0: 'GMCTRP1', 0xe1: 'GMCTRN1', 0x10: 'SLPIN'}
def lk_cmds(table, n):
out = []
for i in range(n):
size, ptr, wait, post = struct.unpack_from('<IIIB', lk, table - BASE + 16 * i)
out.append((bytes(lk[ptr - BASE:ptr - BASE + size]), wait))
return out
def dt_cmds(node, prop):
m = re.search(re.escape(node) + r' \{.*?' + re.escape(prop) + r' = \[([0-9a-f ]+)\];', dts, re.S)
b = bytes.fromhex(m.group(1)); out = []; i = 0
while i < len(b):
wait, ln = b[i], b[i + 1]; out.append((b[i + 2:i + 2 + ln], wait)); i += 2 + ln
return out
def show(title, cmds):
print(f'== {title}: {len(cmds)} commands')
for i, (p, w) in enumerate(cmds):
print(f' {i:2d} {p[0]:02x} {NAMES.get(p[0], "?"):8s} {p[1:].hex(" "):48s} wait={w} ms')
lkc = lk_cmds(0x8f64849c, 19) # st7735s table, count 19 (pinfo+0xf4/+0xf0, panel_id 1 branch)
dtc = dt_cmds('qcom,mdss_spi_st7735s_wx144_128x128_cmd', 'qcom,mdss-spi-on-command')
show('stock LK st7735s (0x8f64849c)', lkc)
show('stock dtb_01 st7735s on-command', dtc)
print('LK == DT (payload+wait):', lkc == dtc)
for i, (a, b) in enumerate(zip(lkc, dtc)):
if a != b:
print(' diff at', i, a, b)
show('stock dtb_01 st7735s off-command', dt_cmds('qcom,mdss_spi_st7735s_wx144_128x128_cmd', 'qcom,mdss-spi-off-command'))