From 5c5dac2dbcc123fdf98a59a2ab2678808b3033ad Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Fri, 2 Oct 2026 10:30:58 +0200 Subject: [PATCH] rk27xx: clip LCD updates to the screen lcd_update_rect() took the rect as given. One reaching past the screen set a GRAM window off the panel, so the update showed nothing, and built one DMA descriptor per line into scr_llp[LCD_HEIGHT] - past its end for a rect taller than what is left of the screen. What follows scr_llp in memory is the PCM driver's locks and then all_queues, the kernel's queue list: a later broadcast posted to garbage. invadrox asks for such a rect every frame. On a Samsung YP-CP3 nothing of its playfield moved - aliens, bombs, the ship - and powering off afterwards took a data abort in queue_post() from interrupt context. Clip the rect to the screen, as other targets do, and do nothing if nothing is left. Every rk27xx screen is a multiple of 4 pixels each way, so aligning the clipped rect to 4 cannot take it past the edge. Co-Authored-By: Claude Opus 5.5 Change-Id: I1f8bf865251859cd223e208a807c9a9da76a0ba0 --- firmware/target/arm/rk27xx/lcdif-rk27xx.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/firmware/target/arm/rk27xx/lcdif-rk27xx.c b/firmware/target/arm/rk27xx/lcdif-rk27xx.c index 618b476480..c023482679 100644 --- a/firmware/target/arm/rk27xx/lcdif-rk27xx.c +++ b/firmware/target/arm/rk27xx/lcdif-rk27xx.c @@ -258,6 +258,27 @@ void lcd_update_rect(int x, int y, int width, int height) { int x_end, y_end, x_align, y_align; + /* Clip to the screen, as other targets do. A rect reaching past it + * set a GRAM window off the panel - nothing showed - and built more + * DMA descriptors than scr_llp[] holds, overwriting what follows it + * in memory: the kernel's queue list among it. */ + if (x < 0) + { + width += x; + x = 0; + } + if (y < 0) + { + height += y; + y = 0; + } + if (width > LCD_WIDTH - x) + width = LCD_WIDTH - x; + if (height > LCD_HEIGHT - y) + height = LCD_HEIGHT - y; + if (width <= 0 || height <= 0) + return; + /* min alowed transfer seems to be 4x4 pixels */ x_align = x & 3; y_align = y & 3;