rockchip_ebc: set all pixels to IDLE when changing waveforms

and don't allow redraws when redraw_delay <= 0

Previously changing waveforms using redraw_delay=0 could cause pixels
to be stuck in what was previously their WAITING state without
shrinking clip_ongoing_or_waiting. The display would stay responsive,
but the refresh thread would occupy the CPU, causing the kernel to
warn about soft lockups.

This change resets all pixels to IDLE when modifying the LUT. At this
point all pixels are either IDLE or WAITING. Pixels that are intended
to be redrawn would become WAITING in the same iteration.
This commit is contained in:
hrdl 2025-05-05 21:30:00 +02:00 committed by Antoine Martin
parent d4d7f09528
commit 52943b19e2
3 changed files with 39 additions and 11 deletions

View file

@ -785,7 +785,7 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
bool skip_advance = false;
time_start_advance = ktime_get();
// All currently scheduled pixels have finished and we have a work item
// All currently scheduled pixels are IDLE or WAITING have finished and we have a work item
if (drm_rect_width(&clip_ongoing) <= 0 && work_item) {
// Refresh work item
spin_lock(&ebc->work_item_lock);
@ -840,6 +840,12 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
if (work_item & ROCKCHIP_EBC_WORK_ITEM_CHANGE_LUT) {
rockchip_ebc_change_lut(ebc);
print_lut(ebc);
// Reset inner and outer to make sure
// pixels that were WAITING stay
// valid. For simplicity, set to IDLE.
kernel_neon_begin();
rockchip_ebc_reset_inner_outer_neon(ebc);
kernel_neon_end();
}
if (work_item & ROCKCHIP_EBC_WORK_ITEM_INIT) {
clip_ongoing_or_waiting = ebc->screen_rect;
@ -912,23 +918,28 @@ static void rockchip_ebc_partial_refresh(struct rockchip_ebc *ebc,
pr_debug("%s ebc->driver_mode=%d enabling_mode=%d", __func__, ebc->driver_mode, enabling_mode);
if (drm_rect_width(&clip_ongoing_or_waiting) > 0 &&
!skip_advance) {
u8 force_hint = 0;
// Disable redraws of redraw_delay <= 0
u8 force_hint_mask = ebc->redraw_delay > 0 ? 0 : ROCKCHIP_EBC_HINT_REDRAW;
if (ebc->driver_mode == ROCKCHIP_EBC_DRIVER_MODE_FAST) {
kernel_neon_begin();
rockchip_ebc_schedule_advance_fast_neon(
ebc, prelim_target, hints,
phase_buffer, &clip_ongoing,
&clip_ongoing_or_waiting,
early_cancellation_addition, 0, 0, 0,
!no_schedule_until_clip_empty && !work_item);
ebc, prelim_target, hints, phase_buffer,
&clip_ongoing, &clip_ongoing_or_waiting,
early_cancellation_addition, 0,
force_hint, force_hint_mask,
!no_schedule_until_clip_empty &&
!work_item);
kernel_neon_end();
} else if (ebc->driver_mode == ROCKCHIP_EBC_DRIVER_MODE_NORMAL) {
kernel_neon_begin();
rockchip_ebc_schedule_advance_neon(
ebc, prelim_target, hints,
phase_buffer, &clip_ongoing,
&clip_ongoing_or_waiting,
early_cancellation_addition, 0, 0, 0,
!no_schedule_until_clip_empty && !work_item);
ebc, prelim_target, hints, phase_buffer,
&clip_ongoing, &clip_ongoing_or_waiting,
early_cancellation_addition, 0,
force_hint, force_hint_mask,
!no_schedule_until_clip_empty &&
!work_item);
kernel_neon_end();
}
}

View file

@ -243,6 +243,7 @@ void rockchip_ebc_blit_fb_r8_y4_hints_neon(const struct rockchip_ebc *ebc,
const struct drm_framebuffer *fb,
const struct drm_rect *src_clip);
void rockchip_ebc_reset_inner_outer_neon(const struct rockchip_ebc *ebc);
#define DRM_RECT_EMPTY_EXTANDABLE DRM_RECT_INIT(100000, 100000, -100000, -100000);

View file

@ -1231,6 +1231,22 @@ void rockchip_ebc_blit_fb_r8_y4_hints_neon(const struct rockchip_ebc *ebc,
}
EXPORT_SYMBOL(rockchip_ebc_blit_fb_r8_y4_hints_neon);
void rockchip_ebc_reset_inner_outer_neon(const struct rockchip_ebc *ebc)
{
u8 *packed_inner_outer_nextprev_line = ebc->packed_inner_outer_nextprev;
uint8x16_t q8_0x00 = vdupq_n_u8(0x00);
for (int i = 0; i < ebc->num_pixels; i += 16) {
uint8x16x3_t q8_inner_outer_nextprev = vld3q_u8(packed_inner_outer_nextprev_line);
uint8x16x3_t q8_inner_outer_nextprev_new = {
{ q8_0x00, q8_0x00, q8_inner_outer_nextprev.val[2] }
};
vst3q_u8(packed_inner_outer_nextprev_line,
q8_inner_outer_nextprev_new);
packed_inner_outer_nextprev_line += 48;
}
}
EXPORT_SYMBOL(rockchip_ebc_reset_inner_outer_neon);
MODULE_AUTHOR("hrdl <git@hrdl.eu>");
MODULE_DESCRIPTION("Rockchip EBC NEON functions");
MODULE_LICENSE("GPL v2");