Files
build/patch/kernel/archive/sunxi-6.16/0003-drm-sun4i-Report-page-flip-after-vsync-is-complete-n.patch

112 lines
3.6 KiB
Diff

From aeb99ba3659e8147e9f01a5ddfd529f1e1b16358 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megi@xff.cz>
Date: Sat, 9 Aug 2025 14:47:14 +0200
Subject: [PATCH 3/3] drm: sun4i: Report page flip after vsync is complete, not
in the middle
See: https://xnux.eu/log/080.html
Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 26 ++++++++++++++++++++++++--
drivers/gpu/drm/sun4i/sun4i_tcon.h | 4 ++++
2 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 221df37406d8..25c8bff308f2 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -240,6 +240,9 @@ void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
if (enable)
val = mask;
+ if (!enable && tcon->quirks->vblank_delay)
+ hrtimer_cancel(&tcon->flip_timer);
+
regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, mask, val);
}
EXPORT_SYMBOL(sun4i_tcon_enable_vblank);
@@ -838,6 +841,17 @@ static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
spin_unlock_irqrestore(&dev->event_lock, flags);
}
+static enum hrtimer_restart sun4i_tcon_flip_timer_cb(struct hrtimer *timer)
+{
+ struct sun4i_tcon *tcon = container_of(timer,
+ struct sun4i_tcon, flip_timer);
+
+ drm_crtc_handle_vblank(&tcon->crtc->crtc);
+ sun4i_tcon_finish_page_flip(tcon->drm, tcon->crtc);
+
+ return HRTIMER_NORESTART;
+}
+
static irqreturn_t sun4i_tcon_handler(int irq, void *private)
{
struct sun4i_tcon *tcon = private;
@@ -853,8 +867,12 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private)
SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT)))
return IRQ_NONE;
- drm_crtc_handle_vblank(&scrtc->crtc);
- sun4i_tcon_finish_page_flip(drm, scrtc);
+ if (tcon->quirks->vblank_delay) {
+ hrtimer_start(&tcon->flip_timer, us_to_ktime(250), HRTIMER_MODE_REL);
+ } else {
+ drm_crtc_handle_vblank(&scrtc->crtc);
+ sun4i_tcon_finish_page_flip(drm, scrtc);
+ }
/* Acknowledge the interrupt */
regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG,
@@ -903,6 +921,9 @@ static int sun4i_tcon_init_irq(struct device *dev,
struct platform_device *pdev = to_platform_device(dev);
int irq, ret;
+ hrtimer_setup(&tcon->flip_timer, sun4i_tcon_flip_timer_cb,
+ CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
@@ -1616,6 +1637,7 @@ static const struct sun4i_tcon_quirks sun50i_a64_lcd_quirks = {
.restores_rate = true,
.dclk_min_div = 1,
.setup_lvds_phy = sun6i_tcon_setup_lvds_phy,
+ .vblank_delay = true,
};
static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 729d64b78846..2bf91fb4872c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -12,6 +12,7 @@
#include <drm/drm_crtc.h>
+#include <linux/hrtimer.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mod_devicetable.h>
@@ -252,6 +253,8 @@ struct sun4i_tcon_quirks {
bool polarity_in_ch0; /* some tcon1 channels have polarity bits in tcon0 pol register */
bool restores_rate; /* restores the initial rate when rate changes */
u8 dclk_min_div; /* minimum divider for TCON0 DCLK */
+ bool vblank_delay; /* delay page flip reporting for 250us (TCON report vblank
+ shortly before register flip) */
/* callback to handle tcon muxing options */
int (*set_mux)(struct sun4i_tcon *, const struct drm_encoder *);
@@ -289,6 +292,7 @@ struct sun4i_tcon {
/* Associated crtc */
struct sun4i_crtc *crtc;
+ struct hrtimer flip_timer;
int id;
--
2.51.0