Panel never blanks: ana38401 disable/unprepare are deliberate no-ops #10

Open
opened 2026-08-21 12:59:43 +00:00 by kit · 0 comments
Owner

When Plasma puts the display to sleep the panel stays lit. DRM does its part correctly — the connector reports dpms: Off, enabled: disabled — but the panel driver ignores it.

Root cause (two things stack)

1. disable/unprepare are intentionally empty (drivers/gpu/drm/panel/panel-samsung-ana38401.c):

static int ana38401_disable(struct drm_panel *panel)
{
	/* handover mode: never send 28h - we cannot re-init afterwards */
	return 0;
}
static int ana38401_unprepare(struct drm_panel *panel)
{
	/* handover mode: keep reset deasserted and vdd up */
	return 0;
}

Deliberate, from the era when the panel init was fragile and a display-off could not be recovered from (see the dark-panel post-mortem, MAINLINE-NOTES 2026-08-19/20).

2. It's an emissive AMOLED, so brightness is the light — there is no backlight to cut — and disable doesn't touch brightness either. Every pixel keeps emitting.

Brightness is not a usable substitute — measured

Writing 0 to /sys/class/backlight/panel/brightness returns EINVAL, reads back 0, and the screen stays lit (visually confirmed). ana38401_bl_update_status() snaps any requested level to the nearest entry in ana38401_br_levels[], whose lowest is bl = 10 — the dimmest stock level, not off. There is no zero/off entry, so brightness cannot blank the panel.

Fix

Send display-off (28h) in disable and display-on (29h) in enable — and only those. Specifically not sleep-in (10h), and no re-init:

  • 28h/29h gate emission only. They do not clear GRAM, drop the TCON config, or disturb the DSI link, so there is nothing to re-initialize afterwards.
  • The failure the comment refers to came from the full cold-init path, which is a different operation. Display init is stable now (see 2026-08-20 "DISPLAY SOLVED"), so the no-op is most likely stale caution.

Why this matters beyond the annoyance

  • Real power saving: on an emissive panel, display-off is close to the whole panel budget. This is effectively a prerequisite for #3 (s2idle / battery life) being measurable — and for #9, since there is nothing to measure with until the fuel gauge lands.
  • Plasma's idle/power management stops being cosmetic.

Test plan (do NOT test blind)

If 29h fails to bring the panel back, the result is a dark panel — the exact recovery scenario that cost several sessions. So:

  1. Build a boot image with 28h/29h wired into disable/enable.
  2. Test with the U-Boot serial console reachable (gts6l-reboot console) and SD autoboot in place, so a failure is diagnosable rather than a black rectangle.
  3. Exercise it via dpms on the connector directly before letting Plasma's idle timer drive it.
  4. Fallback if 29h alone is insufficient: have enable fall through to the known-good full init path.

Deliberately not attempted live during the 2026-08-21 session for that reason.

When Plasma puts the display to sleep the panel **stays lit**. DRM does its part correctly — the connector reports `dpms: Off`, `enabled: disabled` — but the panel driver ignores it. ## Root cause (two things stack) **1. `disable`/`unprepare` are intentionally empty** (`drivers/gpu/drm/panel/panel-samsung-ana38401.c`): ```c static int ana38401_disable(struct drm_panel *panel) { /* handover mode: never send 28h - we cannot re-init afterwards */ return 0; } static int ana38401_unprepare(struct drm_panel *panel) { /* handover mode: keep reset deasserted and vdd up */ return 0; } ``` Deliberate, from the era when the panel init was fragile and a display-off could not be recovered from (see the dark-panel post-mortem, MAINLINE-NOTES 2026-08-19/20). **2. It's an emissive AMOLED**, so brightness *is* the light — there is no backlight to cut — and `disable` doesn't touch brightness either. Every pixel keeps emitting. ## Brightness is not a usable substitute — measured Writing `0` to `/sys/class/backlight/panel/brightness` returns `EINVAL`, reads back 0, and **the screen stays lit** (visually confirmed). `ana38401_bl_update_status()` snaps any requested level to the *nearest* entry in `ana38401_br_levels[]`, whose lowest is `bl = 10` — the dimmest stock level, not off. There is no zero/off entry, so brightness cannot blank the panel. ## Fix Send **display-off (`28h`) in `disable`** and **display-on (`29h`) in `enable`** — and *only* those. Specifically **not** sleep-in (`10h`), and no re-init: - `28h`/`29h` gate emission only. They do not clear GRAM, drop the TCON config, or disturb the DSI link, so there is nothing to re-initialize afterwards. - The failure the comment refers to came from the full cold-init path, which is a different operation. Display init is stable now (see 2026-08-20 "DISPLAY SOLVED"), so the no-op is most likely stale caution. ## Why this matters beyond the annoyance - Real power saving: on an emissive panel, display-off is close to the whole panel budget. This is effectively a prerequisite for #3 (s2idle / battery life) being measurable — and for #9, since there is nothing to measure with until the fuel gauge lands. - Plasma's idle/power management stops being cosmetic. ## Test plan (do NOT test blind) If `29h` fails to bring the panel back, the result is a dark panel — the exact recovery scenario that cost several sessions. So: 1. Build a boot image with `28h`/`29h` wired into `disable`/`enable`. 2. Test with the **U-Boot serial console reachable** (`gts6l-reboot console`) and SD autoboot in place, so a failure is diagnosable rather than a black rectangle. 3. Exercise it via `dpms` on the connector directly before letting Plasma's idle timer drive it. 4. Fallback if `29h` alone is insufficient: have `enable` fall through to the known-good full init path. Deliberately not attempted live during the 2026-08-21 session for that reason.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kit/linux-gts6l#10
No description provided.