- 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/.
135 lines
8.9 KiB
Markdown
135 lines
8.9 KiB
Markdown
# B9-LK audit — why the screen is black before Linux (read-only, 2026-10-03)
|
|
|
|
Nothing was patched, built or flashed. Sources:
|
|
- stock LK = `partitions/aboot.bin` → `bootchain/aboot-analysis/lk.bin`/`lk-arm.dis` (tools in `b9/b9a/`);
|
|
- lk1st/lk2nd = `lk2nd-build/src` (lk2nd 23.1, e9c8b217; the source of the aboot that is flashed now);
|
|
- UART logs `logs/uart/*`.
|
|
|
|
## 0. Correction to the premise: stock LK is NOT in the current chain
|
|
|
|
Since B5a (2026-09-30) `aboot` holds **our lk1st-aurora-autoboot** (built from the lk2nd tree, `ABOOT_STANDALONE=1`,
|
|
`LK2ND_DISPLAY=cont-splash`), not stock LK. The current chain is:
|
|
|
|
`PBL → SBL1 (stock) → lk1st (lk2nd code: lk2nd_init + extlinux in the same binary) → Linux`
|
|
|
|
Evidence: every current UART log has exactly one `[0] welcome to lk`, followed in the same LK by `lk2nd_init()` and
|
|
`Trying to boot 'b7c'/'b8f'/'b9c'`. Stock LK exists only as the backup `partitions/aboot.bin`.
|
|
The chain "stock LK → lk2nd" existed only once, in the 2026-09-29 test `logs/uart/lk2nd-boottest-20260929-203353.log`
|
|
(lk2nd in `recovery`).
|
|
|
|
## A. Exact stock display init chain (stock LK, disassembly)
|
|
|
|
```
|
|
app table 0x8f647da0 → aboot_init 0x8f614eec
|
|
→ read_device_info 0x8f614984
|
|
→ target_display_init 0x8f600eac(device.display_panel @0x8f64af94) ← UNCONDITIONAL, before any boot-mode decision
|
|
loop: gcdb_display_init 0x8f616918(rev, MDP_REV 12, fb 0x83200000)
|
|
→ oem_panel_select 0x8f600f20: panel_id := 1 (hardcoded, no ID read), prints "lcd_id == st7735s spi lcd";
|
|
id1 = qcom,mdss_spi_st7735s_wx144_128x128_cmd (19 cmds) [id0 = DSI st7796s 320p, id2 = SPI nv3023a]
|
|
→ pinfo.type = SPI_PANEL(13), power_func 0x8f6165e0, bl_func 0x8f616698
|
|
→ msm_display_init 0x8f60d624:
|
|
power_func: target_ldo_ctrl 0x8f600e98 (STUB, returns 0) → target_panel_reset 0x8f600bb8
|
|
(GPIO118: 1, 0 for 1 ms, 1, wait 120 ms) → "Panel power on done"
|
|
msm_display_config 0x8f60d2a0: "Config SPI PANEL." → spi_qup_init(BLSP1, QUP index 3 = 0x78b8000,
|
|
GPIO12-15 func1, 16 MHz, mode 3) → D/C GPIO116 → 19 commands (0x8f610b6c)
|
|
fbcon_setup 0x8f61642c (fb 0x83200000, 128x128 RGB565)
|
|
display_image_on_screen 0x8f61659c: splash partition has no "SPLASH!!" header (it is all zeros)
|
|
→ built-in 128x128 "4G LTE" image @0x8f64b004
|
|
msm_display_flush 0x8f60d46c (frame over SPI, D/C=1)
|
|
bl_func → target_backlight_ctrl 0x8f600b54: MPP4 0xa340=0x61, 0xa34c=7 (40 mA), 0xa346=0x80
|
|
→ … boot-mode decisions (fastboot / recovery / normal) come AFTER this
|
|
boot: cmdline += "mdss_mdp.panel=1:spi:0:qcom,mdss_spi_st7735s_wx144_128x128_cmd";
|
|
msm_display_off 0x8f60d78c: "Continuous splash enabled, keeping panel alive." (panel left on)
|
|
```
|
|
|
|
Conditions: none found. No alarm/charger/ffbm check guards the display call, so stock LK initialises the panel
|
|
**in every mode** (normal, recovery, fastboot, charger).
|
|
|
|
UART proof that it ran on this board:
|
|
- `[210] Panel power on done` / `[210] Config SPI PANEL.` in `coldboot-20260929-200018`, `preflight-recovery-…`, `lk2nd-boottest-…`;
|
|
- no "Send SPI … failed".
|
|
|
|
A visual confirmation that the logo appeared on stock firmware is still missing (operator question from B9A).
|
|
|
|
## B. Why the screen is black before Linux now
|
|
|
|
**The stock display code is not in the boot chain at all.** No flag or condition is switching it off.
|
|
lk1st (msm8916 build of the lk2nd tree) contains no SPI-panel code:
|
|
- `platform/msm_shared/rules.mk` builds `spi_qup.o`/`mdss_spi.o` only for `PLATFORM=msm8909` and `msm8952`.
|
|
- `LK2ND_DISPLAY=cont-splash` → `lk2nd/display/cont-splash/target_display.c` only *adopts* an MDP that is already running
|
|
(it checks `MDP_GDSCR`). Our panel never uses MDP, so even after stock LK it reports
|
|
`No continuous splash: MDP GDSC is not enabled` (seen in `lk2nd-boottest-…:74`).
|
|
- The alternative `LK2ND_DISPLAY=<panel>` mode = gcdb **DSI** panels (generated headers), no SPI.
|
|
- `lk2nd/device/2nd/spi-display.c` (re-use of a panel that a previous bootloader initialised) is built only when
|
|
`mdss_spi.o` is built, i.e. not for msm8916. It is also hard-coded to 240x320.
|
|
- The msm8916 clock table in lk2nd has only `gcc_blsp1_qup4_i2c_*`, no QUP4 SPI clocks.
|
|
`mdss_spi.c` is hard-wired to msm8909 (D/C = GPIO64, `SPI_QUP_ID 2`).
|
|
|
|
So nothing initialises the panel until Linux. RESET (GPIO118) stays at the SoC reset default (input, pull-down) until
|
|
panel-mipi-dbi probes at ~1.4 s of kernel time.
|
|
|
|
## C. What lk1st/lk2nd does with a panel that is already initialised
|
|
|
|
Checked in the lk2nd 23.1 source for msm8916:
|
|
- TLMM: only `target_volume_up()` configures the vol-up GPIO (when keys are checked). Nothing touches GPIO12-15/116/118.
|
|
- QUP4 / MPP4: not touched. `target/msm8916/target_display.c` (with its MTP-style MPP4 digital-output backlight) is
|
|
**filtered out** of the cont-splash build. `target_uninit()` only parks eMMC, crypto and CE clocks.
|
|
- Framebuffer: not adopted (no MDP); 0x83200000 is ordinary RAM to lk2nd.
|
|
|
|
So lk2nd **leaves the panel alone**: the GRAM keeps the image and the backlight stays as set. This matches the 2026-09-29
|
|
stock→lk2nd log, where lk2nd only printed the GDSC message.
|
|
|
|
Then Linux takes over:
|
|
- the panel's pinctrl keeps D/C/RESET as gpio outputs, and `reset-gpios` is requested OUT_HIGH (no glitch);
|
|
- the fbcon takeover modeset does a hardware reset and a full re-init at ~1.8 s, which replaces the logo;
|
|
- the gpio-backlight pinctrl state (`output-low`) switches MPP4 to 0x60 at probe → **backlight off from ~1.5 s until
|
|
aurora-display at ~8 s**;
|
|
- clk_disable_unused may gate the QUP4 clocks LK left on (harmless; spi-qup re-enables them).
|
|
|
|
L17: CAF `target/msm8916/target_display.c:608` says "The PMIC regulators needed for display are enabled in SBL. There is
|
|
no access to the regulators in LK." That explains the stock stub. But B9A measured **L17 OFF** in running Linux (who
|
|
turned it off is unknown: the RPM with no votes, or something later). The state at LK time is unproven.
|
|
|
|
## D. Smallest ways to get power → splash → Linux fbcon
|
|
|
|
There is no single condition or flag to flip: the stock code path is simply not present in lk1st.
|
|
|
|
1. **Port into lk1st/lk2nd (recommended).** Re-use the lk2nd tree's own CAF SPI stack (`spi_qup.c`, `mdss_spi.c`,
|
|
gcdb `SPI_PANEL` branch) for msm8916 with stock-LK parameters:
|
|
- build `spi_qup.o` + `mdss_spi.o` for msm8916;
|
|
- make D/C GPIO and QUP index parameters (116 / index 3);
|
|
- add `gcc_blsp1_qup4_spi_apps_clk(_src)` with a 16 MHz entry to the msm8916 clock table;
|
|
- add an ST7735S panel header (the verified 19 commands, reset sequence {1,0,1}/{1,1,120}, 128x128 RGB565);
|
|
- panel select;
|
|
- target reset on GPIO118;
|
|
- backlight as an MPP4 current sink 40 mA (the stock 0x61/7/0x80 sequence, not the MTP digital-output variant);
|
|
- LDO stub, as stock.
|
|
Optional: the stock logo (vendor artwork — do not publish).
|
|
2. **Restore stock LK as aboot + lk2nd as the 2nd stage in `boot`.** No code, but it reverts B5a and loses lk1st fastboot
|
|
(stock fastboot has only getvar/download). Compatibility of stock LK with the migrated TZ (DB410c) + qhypstub is untested,
|
|
and it needs two persistent writes. **Not recommended.**
|
|
|
|
## E. Risks of the handoff (variant 1)
|
|
|
|
- **L17 at LK time**: if SBL does not leave L17 on, LK can drive SPI but the panel shows nothing. The fix would be RPM
|
|
regulator code in LK (more porting). The test below settles this first.
|
|
- Wrong QUP/clock setup in LK can abort/hang LK → RAM test only, aboot untouched; recovery = power cycle.
|
|
- Handoff gap: Linux switches MPP4 off at gpio-backlight probe (~1.5 s) and re-inits the panel at fbcon takeover.
|
|
The visible sequence would be: logo (~0.3 s after power) → dark ~1.5 s → ~8 s console.
|
|
This can be fixed later on the Linux side (backlight default-on / output-high), not in LK.
|
|
- Boot time: +~0.3 s in LK (120 ms reset wait + 120 ms SLPOUT + ~20 ms frame).
|
|
- A later persistent step = reflashing aboot (B5a-style gates + `b5a/A4-rollback.sh`); needs its own GO.
|
|
|
|
## Proposed single non-persistent test (needs GO; it requires a build)
|
|
|
|
**B9L-RAM**: from the lk1st fastboot entered with RESET held at power-on, run `fastboot boot` of a **lk2nd 2nd-stage image**
|
|
(msm8916, lk2nd 23.1 + the variant-1 port), with no flashing.
|
|
- The lk2nd image initialises the panel (logo + MPP4 backlight), then chainloads the existing eMMC cache (B9C/B8F) → Linux.
|
|
- Pass = logo visible before the kernel; UART shows SPI init without errors; L17/QUP4 state is logged; Linux fbcon comes up
|
|
as in B9C.
|
|
- aboot, cache and eMMC are untouched.
|
|
|
|
Step 0 of the same session (no build needed): `fastboot boot lk2nd-build/out/lk2nd.img` (the existing unmodified 23.1, built with FORCE_FASTBOOT, so it stops in its own fastboot;
|
|
artifact). This proves that lk1st can chainload a 32-bit lk2nd image on the migrated TZ/qhypstub chain before any port work.
|
|
|
|
STOP.
|