From 6e31a5566eac77287f2c21624e8fb1b9857c8774 Mon Sep 17 00:00:00 2001 From: vhaudiquet Date: Sat, 29 Aug 2026 20:47:29 +0200 Subject: [PATCH] main: revive display pipeline at handoff (fix black screen) Root cause of the black screen, verified against the DEVICE's depthcharge (v0.0.22-10476, ChromeOS R93-era): display_cleanup() runs at CleanupOnHandoff before jumping to the payload and 1. clears the LBIO framebuffer to black, 2. drives DISP_PWM (GPIO 43) and EN_LCD_BL (GPIO 176) low, 3. disables the OVL engines (OVL_EN=0, OVL0_2L_EN=0). DSI/panel/MTCMOS remain up (panel poweroff only exists in 2025+ code), so the stub just undoes those three steps: re-enable both OVLs, set both backlight GPIOs, then paint. The OVL_L0_ADDR register still points at the menu framebuffer, which is the LBIO record address our parser already extracts. --- krane-fb-stub-payload.bin | Bin 159744 -> 159744 bytes krane-fb-stub.bin | Bin 18192 -> 18240 bytes main.c | 57 ++++++++++++++++++++++++++++++++++---- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/krane-fb-stub-payload.bin b/krane-fb-stub-payload.bin index 38bed8a609addd6603e33d7a609757ee8a988ede..9329efcbc1a917bd56f1684a844ca6a70ae8d476 100644 GIT binary patch delta 822 zcmZp8z}fJCbAt|ReX3Rp?~9f5x0iB1dtxpsex`q3vBrmMZ1d$+HY`;8`8e@{5?{-6 zVcXZC74F+@%i=_43WPq=T;-wDo%x5QyV3taYpB=vhEIy+o3c;oGcR8JT`r21@ALM{ z|9^yvNNcW9TfqPI?niz3?oO43i|>55T&L18>!*2rwSUW%zgoYV@{8&%mj7vUl@Kwq z@0Ai*dBo>QW&DjxD^u+M%&eYoX1cRoT;})9UAzf~Vm5A`7TZqAPb(^5k=hZK`0uXg z@t;q#kH6osTZwD7;LdaDeJ(R)j|*p9XqGN`uCqP$$tUHkqz1)^iZ8x%-zv(7WS3qQ zNSS#2lX#SI*!vr+CvIA!U|(7}xn3p8V0ZA|u+Ihh8J@E)Z<(8WmFv3C+-b2NN>|yk z=B&Q2z4!W${k(^-zRf%IFI`WI<94g1?aTIyKG%-_GI+10^D5WiEl=L!LqeLf&Mwis za&z5jQHOff0tKc?cQ=1p*VMfCZR4Ufd|{7Q`bRD1*(thQy~4_W8(-Z1`ZJ+xwC={t zs88>C`&mQzi?_99^O4zCx$a(UYg4Ffy7}5xY44P4a*e;gh5VBExo!VmMtAdNt?z@j zO<(_Teb&DoQ4>$G>v?|`cij|y6cJ!->uVTa9MP)8n=!dLr0jck&k+~Lf*{j_nc6Qr zZzWAxtfYR|eaGY(cO3LHpPmhsbCT}KP+7E-xh#j}jp8!z&4%pfe@u2@XPv^x&S}QL zz+l0^XtiUi0HZi#!(>Bt;pz6Cj69qyK#9Dp$(ov50~n1N#T@Ho5g-i*4%25c zGMX?k$ZkK+$heD{@!<3>Rz`CsN15q|Ss9I(nq;Pb2hxm(rfab=hBGnAY;R^`%w?=+ zcrfvjE<-~QL&Ks^j0}xI%s@615c4uH?BwNP+}WVjb%}uiB*(B*kzqj)qXWavhs?ZM z514sY<^TIX{SlB2Swe*`-dl%qTYNv+aw?bxOT3XN5O^P*F-}>TM{j4Tc)G9gvwwY|v9o-C_$oHOWm)@6Jr$Po)n_a35Z(GXKJw_X z=Qo!5^Ixu6wt6wA+DD-eG4FD8{(BY%8gy)W%A~BK>&?v`@v-jp!z97~>-?l&{gdIX z(w?=@@z>+|byMpq(%xpe*Ej^^sBKhxv3udP=(j4JaxodVZ|%;}-jdZM*qobmhG*-2 zcl*#{)q~I2XEyEJw*R}v^k4t$4_n)EFd5!EqxE)TOyKNd9)>B+nlaMX_OIA@cj>;n z(Yx0d&EHUJd_XTy$nb-#{~J+pmP;?$xFXMbru{Uo$YU0eh{|DN)SLW`{cMlxskcXO z6_knZ5qeK2y)%GcxXCW>lQs#mZ>Tv`~8bVOB;Xrbp7#zXNGTrRiF1jNwd4(%YNa7;_mD9x(H) zVrFOvVgh1CAg=oNf4UNo28lmpX3_%5l>)_J>OgXgKwJP7QwFj@dO>2@K(TlQ=Bpt5 p@Be>sklVIba4>p1Oh4_xD9SQH#`D|uCmxJ4-+?|hSmwZF00434Jw^Zk diff --git a/krane-fb-stub.bin b/krane-fb-stub.bin index a81aed5a928e922ac4fe7a3b55f04b101f6865a2..135e283b17f4250527aa98dc43d2b285bbb6238f 100755 GIT binary patch delta 214 zcmbQx$9SNRQBZ(^L4*MbI7}2YVPcTo=)Q}Y@!(`87IP*?naS2HModjIlk-`O7!OTe z#1hWLB(wQ9ODa7#$dPK4j+Adce%HD*xaA>5qVH7$2lJ3n~VZ2k{w!I29=N7^(+kHb^W1C>F24 W%y|_^T>ba|zxd`8Y#t614LAU#<3rZ~ delta 170 zcmX@m$2g&nQBZ(^L4*Mb2uu_-VRDe!=)Q}YQE@U8i#gLm>B-hCMof>SC+D*mF)B@7 z#1hVwB)$1JODF24d=-TM{r@ixa@6JzY#t5(@YOU| diff --git a/main.c b/main.c index 1433853..b7a818d 100644 --- a/main.c +++ b/main.c @@ -233,6 +233,48 @@ static void fill_screen(const struct fbinfo *f, u64 val) } } +/* ---- display revival ---------------------------------------------------- + * + * Verified against the DEVICE's depthcharge (v0.0.22-10476, 2021/2022): + * display_cleanup() runs at CleanupOnHandoff before jumping here: + * 1. clear_screen(black) — LBIO framebuffer painted black + * 2. backlight_update(false) — GPIO 43 (DISP_PWM) and GPIO 176 + * (EN_LCD_BL) driven low + * 3. mtk_display_stop() — OVL_EN=0 and OVL0_2L_EN=0 + * The DSI link, panel and display MTCMOS stay up (no panel poweroff in this + * firmware generation). So the stub just needs to undo exactly those three + * steps — no DSI/panel re-init required. + */ + +#define DISP_OVL0_BASE 0x14008000u +#define DISP_REG_OVL_EN 0x0F00u /* 2021 mtk_ddp.c */ +#define DISP_REG_OVL0_2L_EN 0x100Cu /* 2021 mtk_ddp.c */ + +#define GPIO_BASE 0x10005000u +/* GpioValRegs: val@0, set@4, rst@8, 16 bytes per 32-pin group */ +#define GPIO_DOUT_SET(pin) (GPIO_BASE + 0x140 + ((pin) / 32) * 16 + 4) +#define GPIO_DOUT_BIT(pin) (1u << ((pin) % 32)) + +#define PAD_DISP_PWM 43 /* DISP_PWM */ +#define PAD_EN_LCD_BL 176 /* PERIPHERAL_EN13 */ + +static void wr32(u64 addr, u32 val) +{ + *(volatile u32 *)addr = val; +} + +/* Undo depthcharge's display_cleanup() so our fills are visible. */ +static void display_revive(void) +{ + /* Same buffer depthcharge scanned out for the menu. */ + wr32(DISP_OVL0_BASE + DISP_REG_OVL_EN, 1); + wr32(DISP_OVL0_BASE + DISP_REG_OVL0_2L_EN, 1); + + /* Backlight on (both pins), matching kukui_backlight_update(true). */ + wr32(GPIO_DOUT_SET(PAD_DISP_PWM), GPIO_DOUT_BIT(PAD_DISP_PWM)); + wr32(GPIO_DOUT_SET(PAD_EN_LCD_BL), GPIO_DOUT_BIT(PAD_EN_LCD_BL)); +} + /* ---- main checkpoint sequence ------------------------------------------- */ static void checkpoint(const struct fbinfo *f, int r, int g, int b) @@ -248,17 +290,20 @@ void cmain(u64 dtb) u32 lbio_size; /* - * Parse everything first (instantaneous); see deviation note above. - * If either stage fails we halt having painted nothing — the screen - * keeps depthcharge's output, which identifies the failure stage. + * Parse everything first (instantaneous). On failure halt unpainted: + * depthcharge blacked the screen and disabled the OVL engine, so the + * failure signature is a black screen right after the menu. */ if (find_coreboot_reg((const void *)dtb, &lbio_addr, &lbio_size)) - halt(); /* stuck on depthcharge output */ + halt(); /* black screen: DTB parse failed */ if (find_framebuffer(lbio_addr, &fb)) - halt(); /* stuck on depthcharge output */ + halt(); /* black screen: LBIO/fb record bad */ - /* Checkpoint 1: red — we entered, parsed, and can draw. */ + /* Re-enable scanout + backlight, then paint. */ + display_revive(); + + /* Checkpoint 1: red — we entered, parsed, revived the display. */ checkpoint(&fb, 1, 0, 0); /* red */ /* Checkpoint 2: yellow — DTB stage. */ checkpoint(&fb, 1, 1, 0); /* yellow */