# Task: proper MT8183 display pipeline bring-up (MIPI DSI host + PHY + BOE TV101WUM-NL6 panel driver) for U-Boot on the Lenovo IdeaPad Duet (google,krane sku176) You are taking over an in-progress U-Boot port on this machine. U-Boot already boots on the device with a working rotated vidconsole. Today's display path is a "scanout" driver that *revives* the display pipeline left running by the boot firmware (coreboot + depthcharge) instead of bringing it up itself. Your job is to add a real display pipeline: a MediaTek MT8183 MIPI DSI host driver, the MIPI TX PHY, and a proper driver for the panel (BOE TV101WUM-NL6), so U-Boot brings the panel up from scratch and no longer depends on firmware handoff. ## Hard requirement: upstreamable work Everything must be written to be sent to the U-Boot mailing list with minimal rework: - `scripts/checkpatch.pl` clean; Kconfig/Makefile style matching neighbouring drivers; DM/uclass APIs (`UCLASS_DSI_HOST`, `UCLASS_PANEL`, `VIDEO`, `vidconsole`). - Commit history: small, single-purpose, upstream-ready commits. Commit as you go; never leave the tree with a broken build. - Document every magic register with its source (Linux driver file or coreboot file you ported it from), in the style of the existing `drivers/video/mt8183_scanout.c`. - Board-specific glue stays in board code; common drivers stay generic. ## Where things are - U-Boot tree: `/home/vhaudiquet/u-boot` (mainline ~2026-08 + local `krane-updates` branch commits; HEAD has everything working — do not rebase or rewrite existing commits, add on top). - Previous bring-up research (read first — it contains device facts confirmed on the real hardware): `/home/vhaudiquet/krane-fb-stub/RESEARCH.md` and `/home/vhaudiquet/krane-fb-stub/U-BOOT.md`. - The current fallback display driver: `drivers/video/mt8183_scanout.c` — its header comment documents the platform handoff model and the OVL register facts. - Board files: `board/mediatek/mt8183/`, `configs/mt8183_kukui_krane_defconfig`. - Control DTB: OF_UPSTREAM, krane DTs at `dts/upstream/src/arm64/mediatek/mt8183-kukui*.dtsi` — the DSI host node and the panel child node (compatible `"boe,tv101wum-nl6"`) already exist there. Do not fork the DT; bind from it. - Toolchain: `aarch64-linux-gnu-gcc`. Build: `make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)`. - Network access works: fetch reference sources (see below) with curl from raw.kernel.org / github raw, e.g. `https://raw.githubusercontent.com/torvalds/linux/master/drivers/gpu/drm/panel/panel-boe-tv101wum.c`. - **The user flashes and tests on the real device.** You cannot test display output yourself. Build the payload, prepare exact flashing instructions (depthcharge-tools `mkdepthcharge` + `futility vbutil_kernel` + dd to `/dev/mmcblk0p1`, as used in this project), and instrument your code with clearly-prefixed serial prints (e.g. `[dsi] phase N`) so the user can report where bring-up stalls. ## Reference implementations to port from Fetch these (do not invent register values): 1. Linux panel driver (authoritative init sequence + timings for this panel): `drivers/gpu/drm/panel/panel-boe-tv101wum.c` — the `"boe,tv101wum-nl6"` entry: 1200x1920 @ 60Hz, 4 data lanes, DSC-less, init sequence of DSI commands, AVDD/AVEE supplies + reset GPIO handling. 2. Linux MIPI TX PHY (MT8183 variant): `drivers/phy/mediatek/phy-mtk-mipi-dsi-mt8183.c` (and the shared `phy-mtk-mipi-dsi.c` if the 8183 variant pulls from it). 3. Linux DSI host: `drivers/gpu/drm/mediatek/mtk_dsi.c` — register map for the DSI host block, timing parameter computation (phy timing, HPW/VPW etc.), command-mode panel init flow. 4. coreboot 4.14 (the generation on this device): `src/mainboard/google/kukui/display.c` and the kukui panel files, plus `src/soc/mediatek/mt8183/{dsi,mipi_tx,mmsys}.c` — a second opinion on sequencing and on which MMSYS gates/clocks matter. Note what coreboot does *not* touch: it relies on clocks already on at boot. 5. U-Boot's existing DSI infrastructure: `drivers/video/mipi_dsi.c` + `include/mipi_dsi.h` (CONFIG_VIDEO_MIPI_DSI helpers — use them for D-PHY timing computation and packet encoding), `drivers/video/dw_mipi_dsi.c` as an example DSI_HOST uclass driver, `drivers/video/panel_uclass.c` / `simple_panel.c` for the PANEL uclass. ## Confirmed hardware facts (verified on this device — do not re-derive) - Panel: BOE TV101WUM-NL6, 1200x1920 native portrait, 4-lane MIPI DSI, mounted rotated 270° in the chassis; the console is therefore used with `uc_priv->rot = 3` (see mt8183_scanout.c). - At payload entry the panel is *powered and initialized* (coreboot ran the full DSI init sequence), the DSI link is up, but depthcharge's `display_cleanup()` stopped the overlay engines and turned the backlight off. OVL0 base register block: `OVL_EN +0x0c`, `OVL0_2L_EN +0x100c`, `OVL_L0_ADDR +0x0f40` (layer-0 scanout address, still holds the last-used address across handoff). - Backlight: two dedicated GPIOs driven high — DISP_PWM (pin 43) and EN_LCD_BL (pin 176) on the MT8183 GPIO controller at 0x10005000 (dout set@+0x100, 16 bytes per 32-pin group). - Coreboot table: fixed at 0xffed9000 on this device (LB_TAG_FRAMEBUFFER record; physical_address may be 0, then OVL_L0_ADDR is authoritative). - The scanout framebuffer address is outside the DTB DRAM description; any buffer you allocate must be mapped with `mmu_map_region()` (see the existing driver) and *reserved* (see the FDT/LMB reservation pattern already in mt8183_scanout.c — reuse it for your own framebuffer). - `drivers/clk/mediatek/clk-mt8183.c` exists in-tree. CHECK which clocks it registers and whether the MMSYS display gates (OVL0, OVL0_2L, RDMA0, COLOR0, DSI0, and the MMSYS CG registers) are covered. If display gates are missing, either extend the clock driver (preferred, upstreamable) or sequence the MMSYS CG registers directly with documented offsets — pick one and justify. - Power domains (SCPSYS display domain) are on at handoff; for full cold bring-up you may need `mtk_scpsys` — check what exists in-tree (`drivers/power/domain/`); if absent, document the gap rather than half-implementing it. ## Architecture guidance (use judgment, document decisions) - New DSI host driver: `drivers/video/mtk_dsi.c` + `drivers/video/mtk_mipi_tx.c` (PHY), bound from the existing DSI node in the upstream krane DT. Use UCLASS_DSI_HOST ops (enable/phy_set_mode/dsi transfers) and the VIDEO_MIPI_DSI helpers. - Panel driver: `drivers/video/panel_boe_tv101wum.c`, UCLASS_PANEL, driven from the panel child node of the DSI node (compatible `"boe,tv101wum-nl6"`), porting the init sequence from the Linux panel driver. Supplies/reset GPIO handling via regulator uclass/GPIO uclass as described by the DT node. - Integrate with the video uclass: the display driver (`mt8183_scanout.c` or a successor) must decide between (a) full cold bring-up through your new pipeline and (b) the existing firmware-handoff revival path. Suggested shape: try full bring-up first; fall back to handoff revival if the panel fails to respond, logging which path was taken. Keep both paths Kconfig selectable so each can be tested in isolation. - The framebuffer you allocate for bring-up must be reserved exactly like the scanout buffer is today (FDT memreserve + LMB), or the kernel will corrupt it after handoff — this was a real bug, see commit 1ae771d9f90. - Endianness/format: VIDEO_BPP32 XRGB like today; `line_length` from the panel mode (1200 px * 4). ## Deliverables and acceptance criteria 1. DSI host + PHY + panel drivers in-tree, Kconfig-gated, krane defconfig selecting them; existing boot path unchanged when the fallback is chosen. 2. Full bring-up path verified on device by the user: with the fallback path disabled, the vidconsole comes up on the panel from cold (i.e. your code performs clock gating, PHY, DSI init, panel init sequence, framebuffer setup, backlight). Instrument each phase with serial prints and give the user a step-by-step test recipe; iterate on their serial reports. 3. `make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu-` builds clean; checkpatch clean; each commit compiles and is upstream-shaped. 4. `RESEARCH.md` in `/home/vhaudiquet/krane-fb-stub/` updated with numbered findings (what was ported from where, what you measured/guessed). 5. Final report: what works, what is untested, known gaps (e.g. missing SCPSYS cold-power sequencing if that applies). Work incrementally: fetch references, map the register model, write the PHY + DSI host first with bring-up prints, get the panel's first frame, then clean up into upstream-shaped commits.