From 8206ab8f22ca9772e899e34b7edbfbb91fda73e0 Mon Sep 17 00:00:00 2001 From: Qubot <1445788683@qq.com> Date: Fri, 5 Jun 2026 11:25:12 +0800 Subject: [PATCH] sun60iw2: keep HDMI active during kernel handoff --- board/sunxi/board_common.c | 2 +- drivers/video/drm/sunxi_drm_crtc.c | 25 ++++++++++++++- drivers/video/drm/sunxi_drm_drv.c | 51 ++++++++++++++++++++++++++++++ include/drm/drm_logo.h | 1 + 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/board/sunxi/board_common.c b/board/sunxi/board_common.c index 98716090..1ff25d43 100644 --- a/board/sunxi/board_common.c +++ b/board/sunxi/board_common.c @@ -900,7 +900,7 @@ void reset_misc(void) void board_quiesce_devices(void) { #ifdef CONFIG_SUNXI_DRM_SUPPORT - sunxi_drm_disable(); + sunxi_drm_handoff_to_kernel(); #endif sunxi_flash_flush(); /*modify 2 for nor to finally exit*/ diff --git a/drivers/video/drm/sunxi_drm_crtc.c b/drivers/video/drm/sunxi_drm_crtc.c index 10f82039..2485cb11 100644 --- a/drivers/video/drm/sunxi_drm_crtc.c +++ b/drivers/video/drm/sunxi_drm_crtc.c @@ -38,6 +38,7 @@ #define to_sunxi_plane(x) container_of(x, struct sunxi_drm_plane, plane) +static void sunxi_plane_atomic_update(struct drm_plane *plane); int sunxi_drm_crtc_get_hw_id(struct sunxi_drm_crtc *scrtc) { @@ -51,6 +52,19 @@ int sunxi_drm_crtc_get_hw_id(struct sunxi_drm_crtc *scrtc) int sunxi_plane_disable_plane(struct drm_plane *plane) { struct drm_plane_state *plane_state = plane->state; + struct sunxi_drm_plane *sunxi_plane = to_sunxi_plane(plane); + struct sunxi_drm_crtc *crtc = sunxi_plane->crtc; + struct display_channel_state *old_ch_state; + struct display_channel_state *ch_state; + struct display_state *state; + + if (!plane_state) { + plane->funcs->reset(plane); + plane_state = plane->state; + if (!plane_state) + return -ENOMEM; + } + plane_state->fb = NULL; plane_state->crtc_x = 0; plane_state->crtc_y = 0; @@ -60,7 +74,16 @@ int sunxi_plane_disable_plane(struct drm_plane *plane) plane_state->src_y = 0; plane_state->src_w = 0; plane_state->src_h = 0; - //tigger commit + + sunxi_plane_atomic_update(plane); + state = display_state_get_by_crtc(crtc); + if (state && crtc->funcs->flush) + crtc->funcs->flush(state); + + ch_state = to_display_channel_state(plane_state); + old_ch_state = to_display_channel_state(plane->old_state); + memcpy(old_ch_state, ch_state, sizeof(struct display_channel_state)); + return 0; } diff --git a/drivers/video/drm/sunxi_drm_drv.c b/drivers/video/drm/sunxi_drm_drv.c index 39eec536..075c1d32 100644 --- a/drivers/video/drm/sunxi_drm_drv.c +++ b/drivers/video/drm/sunxi_drm_drv.c @@ -1047,6 +1047,37 @@ static int display_set_plane(struct display_state *state) } +static int display_clear_plane_for_handoff(struct display_state *state) +{ + struct crtc_state *crtc_state = &state->crtc_state; + struct drm_mode_set_plane plane_req; + int ret; + + if (!state->is_init || !state->is_enable) + return 0; + + memset(&plane_req, 0, sizeof(plane_req)); + + plane_req.crtc_id = crtc_state->crtc_id; + plane_req.fb_id = -1; + plane_req.plane_id = drm_get_primary_plane_id(state->drm, + plane_req.crtc_id); + if (plane_req.plane_id < 0) { + DRM_ERROR("Failed to get primary plane for crtc %d\n", + plane_req.crtc_id); + return -ENODEV; + } + + ret = drm_mode_setplane(state->drm, &plane_req); + if (ret) { + DRM_ERROR("Failed to clear plane %d on crtc %d: %d\n", + plane_req.plane_id, plane_req.crtc_id, ret); + return ret; + } + + return 0; +} + static int display_enable(struct display_state *state) { struct crtc_state *crtc_state = &state->crtc_state; @@ -1511,6 +1542,26 @@ int sunxi_drm_disable(void) return 0; } +int sunxi_drm_handoff_to_kernel(void) +{ + struct display_state *state; + struct sunxi_drm_device *drm = sunxi_drm_device_get(); + int ret = 0; + + if (!drm || list_empty(&drm->display_list)) + return -1; + + sunxi_drm_for_each_display(state, drm) { + if (state->is_enable) { + ret = display_clear_plane_for_handoff(state); + if (ret) + return ret; + } + } + + return 0; +} + int sunxi_show_bmp(char *bmp) { struct display_state *s; diff --git a/include/drm/drm_logo.h b/include/drm/drm_logo.h index 53e6824f..c2dde920 100644 --- a/include/drm/drm_logo.h +++ b/include/drm/drm_logo.h @@ -26,6 +26,7 @@ int sunxi_show_bmp(char *name); int sunxi_show_bmp_and_backlight(char *name, char *reg); int sunxi_backlight_ctrl(char *reg); int sunxi_drm_disable(void); +int sunxi_drm_handoff_to_kernel(void); #ifdef __cplusplus } #endif