Commit b2d03b0d authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Move cursor position and base handling into the platform specific functions

Supposedly on some platforms we can get extra atomicity guarantees for
CURPOS if we write it between the CURCNTR and CURBASE. Let's move the
CURPOS handling into the platform specific hooks to make the possible
without having to pass the calculated CURPOS around. And while at it,
do the same for the CURBASE to avoid passing that either.

v2: Use I915_WRITE_FW() and grab uncore.lock
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> #v1
Link: http://patchwork.freedesktop.org/patch/msgid/20170327185546.2977-7-ville.syrjala@linux.intel.com
parent ed270223
...@@ -9203,11 +9203,13 @@ static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state, ...@@ -9203,11 +9203,13 @@ static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
CURSOR_STRIDE(stride); CURSOR_STRIDE(stride);
} }
static void i845_update_cursor(struct intel_plane *plane, u32 base, static void i845_update_cursor(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state) const struct intel_plane_state *plane_state)
{ {
struct drm_i915_private *dev_priv = to_i915(plane->base.dev); struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
uint32_t cntl = 0, size = 0; u32 cntl = 0, base = 0, pos = 0, size = 0;
unsigned long irqflags;
if (plane_state && plane_state->base.visible) { if (plane_state && plane_state->base.visible) {
unsigned int width = plane_state->base.crtc_w; unsigned int width = plane_state->base.crtc_w;
...@@ -9215,8 +9217,13 @@ static void i845_update_cursor(struct intel_plane *plane, u32 base, ...@@ -9215,8 +9217,13 @@ static void i845_update_cursor(struct intel_plane *plane, u32 base,
cntl = plane_state->ctl; cntl = plane_state->ctl;
size = (height << 12) | width; size = (height << 12) | width;
base = intel_cursor_base(plane_state);
pos = intel_cursor_position(plane_state);
} }
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
if (plane->cursor.cntl != 0 && if (plane->cursor.cntl != 0 &&
(plane->cursor.base != base || (plane->cursor.base != base ||
plane->cursor.size != size || plane->cursor.size != size ||
...@@ -9239,11 +9246,22 @@ static void i845_update_cursor(struct intel_plane *plane, u32 base, ...@@ -9239,11 +9246,22 @@ static void i845_update_cursor(struct intel_plane *plane, u32 base,
plane->cursor.size = size; plane->cursor.size = size;
} }
if (cntl)
I915_WRITE_FW(CURPOS(PIPE_A), pos);
if (plane->cursor.cntl != cntl) { if (plane->cursor.cntl != cntl) {
I915_WRITE_FW(CURCNTR(PIPE_A), cntl); I915_WRITE_FW(CURCNTR(PIPE_A), cntl);
POSTING_READ_FW(CURCNTR(PIPE_A)); POSTING_READ_FW(CURCNTR(PIPE_A));
plane->cursor.cntl = cntl; plane->cursor.cntl = cntl;
} }
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static void i845_disable_cursor(struct intel_plane *plane,
struct intel_crtc *crtc)
{
i845_update_cursor(plane, NULL, NULL);
} }
static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
...@@ -9282,53 +9300,46 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, ...@@ -9282,53 +9300,46 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
return cntl; return cntl;
} }
static void i9xx_update_cursor(struct intel_plane *plane, u32 base, static void i9xx_update_cursor(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state) const struct intel_plane_state *plane_state)
{ {
struct drm_i915_private *dev_priv = to_i915(plane->base.dev); struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum pipe pipe = plane->pipe; enum pipe pipe = plane->pipe;
uint32_t cntl = 0; u32 cntl = 0, base = 0, pos = 0;
unsigned long irqflags;
if (plane_state && plane_state->base.visible) if (plane_state && plane_state->base.visible) {
cntl = plane_state->ctl; cntl = plane_state->ctl;
base = intel_cursor_base(plane_state);
pos = intel_cursor_position(plane_state);
}
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
if (plane->cursor.cntl != cntl) { if (plane->cursor.cntl != cntl) {
I915_WRITE_FW(CURCNTR(pipe), cntl); I915_WRITE_FW(CURCNTR(pipe), cntl);
POSTING_READ_FW(CURCNTR(pipe)); POSTING_READ_FW(CURCNTR(pipe));
plane->cursor.cntl = cntl; plane->cursor.cntl = cntl;
} }
if (cntl)
I915_WRITE_FW(CURPOS(pipe), pos);
/* and commit changes on next vblank */ /* and commit changes on next vblank */
I915_WRITE_FW(CURBASE(pipe), base); I915_WRITE_FW(CURBASE(pipe), base);
POSTING_READ_FW(CURBASE(pipe)); POSTING_READ_FW(CURBASE(pipe));
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
plane->cursor.base = base; plane->cursor.base = base;
} }
/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ static void i9xx_disable_cursor(struct intel_plane *plane,
static void intel_crtc_update_cursor(struct intel_plane *plane, struct intel_crtc *crtc)
const struct intel_plane_state *plane_state)
{ {
struct drm_i915_private *dev_priv = to_i915(plane->base.dev); i9xx_update_cursor(plane, NULL, NULL);
enum pipe pipe = plane->pipe;
u32 pos = 0, base = 0;
unsigned long irqflags;
if (plane_state) {
base = intel_cursor_base(plane_state);
pos = intel_cursor_position(plane_state);
}
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
I915_WRITE_FW(CURPOS(pipe), pos);
if (IS_I845G(dev_priv) || IS_I865G(dev_priv))
i845_update_cursor(plane, base, plane_state);
else
i9xx_update_cursor(plane, base, plane_state);
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
} }
static bool cursor_size_ok(struct drm_i915_private *dev_priv, static bool cursor_size_ok(struct drm_i915_private *dev_priv,
...@@ -13726,23 +13737,9 @@ intel_check_cursor_plane(struct intel_plane *plane, ...@@ -13726,23 +13737,9 @@ intel_check_cursor_plane(struct intel_plane *plane,
return 0; return 0;
} }
static void
intel_disable_cursor_plane(struct intel_plane *plane,
struct intel_crtc *crtc)
{
intel_crtc_update_cursor(plane, NULL);
}
static void
intel_update_cursor_plane(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *state)
{
intel_crtc_update_cursor(plane, state);
}
static struct intel_plane * static struct intel_plane *
intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) intel_cursor_plane_create(struct drm_i915_private *dev_priv,
enum pipe pipe)
{ {
struct intel_plane *cursor = NULL; struct intel_plane *cursor = NULL;
struct intel_plane_state *state = NULL; struct intel_plane_state *state = NULL;
...@@ -13769,8 +13766,14 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) ...@@ -13769,8 +13766,14 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
cursor->id = PLANE_CURSOR; cursor->id = PLANE_CURSOR;
cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe); cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe);
cursor->check_plane = intel_check_cursor_plane; cursor->check_plane = intel_check_cursor_plane;
cursor->update_plane = intel_update_cursor_plane;
cursor->disable_plane = intel_disable_cursor_plane; if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
cursor->update_plane = i845_update_cursor;
cursor->disable_plane = i845_disable_cursor;
} else {
cursor->update_plane = i9xx_update_cursor;
cursor->disable_plane = i9xx_disable_cursor;
}
cursor->cursor.base = ~0; cursor->cursor.base = ~0;
cursor->cursor.cntl = ~0; cursor->cursor.cntl = ~0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment