From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: George Karagounis <taterraster@gmail.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>,
Rodrigo Vivi <rodrigo.vivi@intel.com>,
Joonas Lahtinen <joonas.lahtinen@linux.intel.com>,
Tvrtko Ursulin <tursulin@ursulin.net>,
intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org,
George Karagounis <mail@taterr.org>
Subject: Re: [PATCH] drm/i915/display: Split i845 and i9xx cursor updates into arm/noarm
Date: Wed, 23 Sep 2026 17:11:27 +0300 [thread overview]
Message-ID: <arPeD2dcyUIEGGn3@intel.com> (raw)
In-Reply-To: <20260919173914.111150-1-mail@taterr.org>
On Sat, Sep 19, 2026 at 08:39:14PM +0300, George Karagounis wrote:
> There was a problem with the i845 and i9xx cursor update functions
> they handled both position updates and control/base/size updates in
> a single armed sequence. This prevented the cursor position from
> being updated asynchronously, which can make the cursor feel laggy
The noarm vs. arm split has nothing to do with that. What it does is
(slightly) reduce the amount of work we have to do inside the vblank
evasion critical section. And in order to do the split one has to
evaluate each an every register to confirm whether they are self
arming or not.
And as for the cursor we can't really do that because of the mailbox
updates being performed from the legacy cursor path. That is, when
performing mailbox updates the non-arming registers must also be
updated during the vblank evasion critical section or else they might
disarm the arming that was done by a previous update in the same frame.
The full legacy cursor fastpath would actually work fine there because
it does both the noarm+arm inside the critical section, but the
non-fastpath route for legacy_cursor_update==true does not so it
would need additional changes.
>
> To fix this i split the updates into two phases
> 1. noarm Calculates and writes the CURPOS register immediately.
> 2. arm Calculates and writes CURCNTR, CURBASE, and CURSIZE to
> latch the control and memory updates at vblank
>
> Also handled a hardware quirk on i9xx platforms where CURPOS requires
> a CURBASE write to arm the update. The arm phase now writes CURBASE
> even if only the position changed
>
> This resolves two inline TODOs and improves cursor responsiveness
>
> Signed-off-by: George Karagounis <mail@taterr.org>
> ---
> drivers/gpu/drm/i915/display/intel_cursor.c | 44 +++++++++++++++------
> 1 file changed, 33 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
> index 0673f16f6fd0..c12a7222f2f6 100644
> --- a/drivers/gpu/drm/i915/display/intel_cursor.c
> +++ b/drivers/gpu/drm/i915/display/intel_cursor.c
> @@ -270,14 +270,27 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state,
> return 0;
> }
>
> -/* TODO: split into noarm+arm pair */
> +static void i845_cursor_update_noarm(struct intel_dsb *dsb,
> + struct intel_plane *plane,
> + const struct intel_crtc_state *crtc_state,
> + const struct intel_plane_state *plane_state)
> +{
> + struct intel_display *display = to_intel_display(plane);
> + u32 pos = 0;
> +
> + if (plane_state && plane_state->uapi.visible)
> + pos = intel_cursor_position(crtc_state, plane_state, false);
> +
> + intel_de_write_fw(display, CURPOS(display, PIPE_A), pos);
> +}
> +
> static void i845_cursor_update_arm(struct intel_dsb *dsb,
> struct intel_plane *plane,
> const struct intel_crtc_state *crtc_state,
> const struct intel_plane_state *plane_state)
> {
> struct intel_display *display = to_intel_display(plane);
> - u32 cntl = 0, base = 0, pos = 0, size = 0;
> + u32 cntl = 0, base = 0, size = 0;
>
> if (plane_state && plane_state->uapi.visible) {
> unsigned int width = drm_rect_width(&plane_state->uapi.dst);
> @@ -289,7 +302,6 @@ static void i845_cursor_update_arm(struct intel_dsb *dsb,
> size = CURSOR_HEIGHT(height) | CURSOR_WIDTH(width);
>
> base = plane_state->surf;
> - pos = intel_cursor_position(crtc_state, plane_state, false);
> }
>
> /* On these chipsets we can only modify the base/size/stride
> @@ -301,14 +313,11 @@ static void i845_cursor_update_arm(struct intel_dsb *dsb,
> intel_de_write_fw(display, CURCNTR(display, PIPE_A), 0);
> intel_de_write_fw(display, CURBASE(display, PIPE_A), base);
> intel_de_write_fw(display, CURSIZE(display, PIPE_A), size);
> - intel_de_write_fw(display, CURPOS(display, PIPE_A), pos);
> intel_de_write_fw(display, CURCNTR(display, PIPE_A), cntl);
>
> plane->cursor.base = base;
> plane->cursor.size = size;
> plane->cursor.cntl = cntl;
> - } else {
> - intel_de_write_fw(display, CURPOS(display, PIPE_A), pos);
> }
> }
>
> @@ -645,7 +654,21 @@ static void skl_write_cursor_wm(struct intel_dsb *dsb,
> skl_cursor_ddb_reg_val(ddb));
> }
>
> -/* TODO: split into noarm+arm pair */
> +static void i9xx_cursor_update_noarm(struct intel_dsb *dsb,
> + struct intel_plane *plane,
> + const struct intel_crtc_state *crtc_state,
> + const struct intel_plane_state *plane_state)
> +{
> + struct intel_display *display = to_intel_display(plane);
> + enum pipe pipe = plane->pipe;
> + u32 pos = 0;
> +
> + if (plane_state && plane_state->uapi.visible)
> + pos = intel_cursor_position(crtc_state, plane_state, false);
> +
> + intel_de_write_dsb(display, dsb, CURPOS(display, pipe), pos);
> +}
> +
> static void i9xx_cursor_update_arm(struct intel_dsb *dsb,
> struct intel_plane *plane,
> const struct intel_crtc_state *crtc_state,
> @@ -653,7 +676,7 @@ static void i9xx_cursor_update_arm(struct intel_dsb *dsb,
> {
> struct intel_display *display = to_intel_display(plane);
> enum pipe pipe = plane->pipe;
> - u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
> + u32 cntl = 0, base = 0, fbc_ctl = 0;
>
> if (plane_state && plane_state->uapi.visible) {
> int width = drm_rect_width(&plane_state->uapi.dst);
> @@ -666,7 +689,6 @@ static void i9xx_cursor_update_arm(struct intel_dsb *dsb,
> fbc_ctl = CUR_FBC_EN | CUR_FBC_HEIGHT(height - 1);
>
> base = plane_state->surf;
> - pos = intel_cursor_position(crtc_state, plane_state, false);
> }
>
> /*
> @@ -703,14 +725,12 @@ static void i9xx_cursor_update_arm(struct intel_dsb *dsb,
> if (HAS_CUR_FBC(display))
> intel_de_write_dsb(display, dsb, CUR_FBC_CTL(display, pipe), fbc_ctl);
> intel_de_write_dsb(display, dsb, CURCNTR(display, pipe), cntl);
> - intel_de_write_dsb(display, dsb, CURPOS(display, pipe), pos);
> intel_de_write_dsb(display, dsb, CURBASE(display, pipe), base);
>
> plane->cursor.base = base;
> plane->cursor.size = fbc_ctl;
> plane->cursor.cntl = cntl;
> } else {
> - intel_de_write_dsb(display, dsb, CURPOS(display, pipe), pos);
> intel_de_write_dsb(display, dsb, CURBASE(display, pipe), base);
> }
> }
> @@ -1019,6 +1039,7 @@ intel_cursor_plane_create(struct intel_display *display,
> if (display->platform.i845g || display->platform.i865g) {
> cursor->max_stride = i845_cursor_max_stride;
> cursor->min_alignment = i845_cursor_min_alignment;
> + cursor->update_noarm = i845_cursor_update_noarm;
> cursor->update_arm = i845_cursor_update_arm;
> cursor->disable_arm = i845_cursor_disable_arm;
> cursor->get_hw_state = i845_cursor_get_hw_state;
> @@ -1036,6 +1057,7 @@ intel_cursor_plane_create(struct intel_display *display,
> if (intel_scanout_needs_vtd_wa(display))
> cursor->vtd_guard = 2;
>
> + cursor->update_noarm = i9xx_cursor_update_noarm;
> cursor->update_arm = i9xx_cursor_update_arm;
> cursor->disable_arm = i9xx_cursor_disable_arm;
> cursor->get_hw_state = i9xx_cursor_get_hw_state;
> --
> 2.55.0
--
Ville Syrjälä
Intel
next prev parent reply other threads:[~2026-09-23 14:11 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-19 17:39 [PATCH] drm/i915/display: Split i845 and i9xx cursor updates into arm/noarm George Karagounis
2026-09-21 7:11 ` sashiko-bot
2026-09-23 14:11 ` Ville Syrjälä [this message]
2026-09-24 16:25 ` George Karagounis
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=arPeD2dcyUIEGGn3@intel.com \
--to=ville.syrjala@linux.intel.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
--cc=jani.nikula@linux.intel.com \
--cc=joonas.lahtinen@linux.intel.com \
--cc=mail@taterr.org \
--cc=rodrigo.vivi@intel.com \
--cc=taterraster@gmail.com \
--cc=tursulin@ursulin.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox