[PATCH 05/13] drm/i915: Make a copy of the calculated plane regs

ville.syrjala
2012-11-16T14:22:17Z

The register values are computed when the flip ioctl is issued, and
they're used only after we've waited for the GPU to finish rendering.
The computed values are store in the intel_crtc and intel_plane structs,
so issuing another flip before the previous one has been fully completed
would clobber those stored registers. Fix the problem by making a copy
of the calculated register values inside the intel_flip structure. The
copy is then used when it's time to commit the registers to the hardware.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 4 +++-
drivers/gpu/drm/i915/intel_atomic.c | 8 ++++++--
drivers/gpu/drm/i915/intel_display.c | 14 ++++++++------
drivers/gpu/drm/i915/intel_drv.h | 2 +-
drivers/gpu/drm/i915/intel_sprite.c | 24 ++++++++++++------------
5 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8aaf0ce..91e2dc6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -247,6 +247,8 @@ struct drm_i915_error_state {
struct intel_display_error_state *display;
};

+struct intel_plane_regs;
+
struct drm_i915_display_funcs {
bool (*fbc_enabled)(struct drm_device *dev);
void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval);
@@ -278,7 +280,7 @@ struct drm_i915_display_funcs {
int x, int y);
int (*calc_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
int x, int y);
- void (*commit_plane)(struct drm_crtc *crtc);
+ void (*commit_plane)(struct drm_crtc *crtc, const struct intel_plane_regs *regs);
/* clock updates for mode set */
/* cursor updates */
/* render clock increase/decrease */
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 7a0e315..0aa8c93 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -49,6 +49,8 @@ struct intel_flip {
struct intel_ring_buffer *ring;
u32 seqno;
unsigned int flip_seq;
+ /* FIXME need cursor regs too */
+ struct intel_plane_regs regs;
};

struct intel_plane_state {
@@ -1988,11 +1990,11 @@ static bool intel_flip_flip(struct drm_flip *flip,
struct drm_plane *plane = intel_flip->plane;
struct intel_plane *intel_plane = to_intel_plane(plane);

- intel_plane->commit(plane);
+ intel_plane->commit(plane, &intel_flip->regs);
} else {
struct drm_i915_private *dev_priv = dev->dev_private;

- dev_priv->display.commit_plane(crtc);
+ dev_priv->display.commit_plane(crtc, &intel_flip->regs);
}

if (intel_flip->has_cursor)
@@ -2339,6 +2341,7 @@ static void atomic_pipe_commit(struct drm_device *dev,
/* should already be checked so can't fail */
/* FIXME refactor the failing parts? */
dev_priv->display.calc_plane(crtc, crtc->fb, crtc->x, crtc->y);
+ intel_flip->regs = intel_crtc->primary_regs;

if (st->cursor_dirty) {
intel_flip->has_cursor = true;
@@ -2405,6 +2408,7 @@ static void atomic_pipe_commit(struct drm_device *dev,
}

intel_plane->calc(plane, plane->fb, &st->coords);
+ intel_flip->regs = intel_plane->regs;

if (st->old.fb)
intel_flip->old_fb_id = st->old.fb->base.id;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7537a2c..48eeed5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2030,13 +2030,13 @@ unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y,
return tile_rows * pitch * 8 + tiles * 4096;
}

-static void intel_commit_plane(struct drm_crtc *crtc)
+static void intel_commit_plane(struct drm_crtc *crtc,
+ const struct intel_plane_regs *regs)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int plane = intel_crtc->plane;
- const struct intel_plane_regs *regs = &intel_crtc->primary_regs;

I915_WRITE(DSPCNTR(plane), regs->cntr);
I915_WRITE(DSPSTRIDE(plane), regs->stride);
@@ -2153,15 +2153,16 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
int x, int y)
{
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int ret;

ret = i9xx_calc_plane(crtc, fb, x, y);
if (ret)
return ret;

- intel_commit_plane(crtc);
+ intel_commit_plane(crtc, &intel_crtc->primary_regs);

- POSTING_READ(DSPCNTR(to_intel_crtc(crtc)->plane));
+ POSTING_READ(DSPCNTR(intel_crtc->plane));

return 0;
}
@@ -2257,15 +2258,16 @@ static int ironlake_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *
int x, int y)
{
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int ret;

ret = ironlake_calc_plane(crtc, fb, x, y);
if (ret)
return ret;

- intel_commit_plane(crtc);
+ intel_commit_plane(crtc, &intel_crtc->primary_regs);

- POSTING_READ(DSPCNTR(to_intel_crtc(crtc)->plane));
+ POSTING_READ(DSPCNTR(intel_crtc->plane));

return 0;
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 617ba4d..9771a10 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -274,7 +274,7 @@ struct intel_plane {
void (*calc)(struct drm_plane *plane, struct drm_framebuffer *fb,
const struct intel_plane_coords *clip);
void (*prepare)(struct drm_plane *plane);
- void (*commit)(struct drm_plane *plane);
+ void (*commit)(struct drm_plane *plane, const struct intel_plane_regs *regs);
struct intel_plane_regs regs;
struct drm_flip_helper flip_helper;
};
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index ce3b950..d960e19 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -300,13 +300,13 @@ ivb_calc_plane(struct drm_plane *plane,
}

static void
-ivb_commit_plane(struct drm_plane *plane)
+ivb_commit_plane(struct drm_plane *plane,
+ const struct intel_plane_regs *regs)
{
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(plane);
int pipe = intel_plane->pipe;
- const struct intel_plane_regs *regs = &intel_plane->regs;

I915_WRITE(SPRKEYVAL(pipe), regs->keyval);
I915_WRITE(SPRKEYMAX(pipe), regs->keymaxval);
@@ -371,7 +371,7 @@ ivb_update_plane(struct drm_plane *plane,

ivb_calc_plane(plane, fb, coords);
ivb_prepare_plane(plane);
- ivb_commit_plane(plane);
+ ivb_commit_plane(plane, &intel_plane->regs);
POSTING_READ(SPRSURF(pipe));
}

@@ -387,7 +387,7 @@ ivb_disable_plane(struct drm_plane *plane)
regs->cntr &= ~SPRITE_ENABLE;
/* Can't leave the scaler enabled... */
regs->scale = 0;
- ivb_commit_plane(plane);
+ ivb_commit_plane(plane, regs);
POSTING_READ(SPRSURF(pipe));

dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
@@ -413,7 +413,7 @@ ivb_update_colorkey(struct drm_plane *plane,
else if (key->flags & I915_SET_COLORKEY_SOURCE)
regs->cntr |= SPRITE_SOURCE_KEY;

- ivb_commit_plane(plane);
+ ivb_commit_plane(plane, regs);
POSTING_READ(SPRKEYMSK(intel_plane->pipe));

return 0;
@@ -546,13 +546,13 @@ ilk_prepare_plane(struct drm_plane *plane)
}

static void
-ilk_commit_plane(struct drm_plane *plane)
+ilk_commit_plane(struct drm_plane *plane,
+ const struct intel_plane_regs *regs)
{
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(plane);
int pipe = intel_plane->pipe;
- const struct intel_plane_regs *regs = &intel_plane->regs;

I915_WRITE(DVSKEYVAL(pipe), regs->keyval);
I915_WRITE(DVSKEYMAX(pipe), regs->keymaxval);
@@ -579,7 +579,7 @@ ilk_update_plane(struct drm_plane *plane,

ilk_calc_plane(plane, fb, coords);
ilk_prepare_plane(plane);
- ilk_commit_plane(plane);
+ ilk_commit_plane(plane, &intel_plane->regs);
POSTING_READ(DVSSURF(pipe));
}

@@ -595,7 +595,7 @@ ilk_disable_plane(struct drm_plane *plane)
regs->cntr &= ~DVS_ENABLE;
/* Disable the scaler */
regs->scale = 0;
- ilk_commit_plane(plane);
+ ilk_commit_plane(plane, regs);
POSTING_READ(DVSSURF(pipe));
}

@@ -627,7 +627,7 @@ intel_enable_primary(struct drm_crtc *crtc)
intel_update_fbc(dev);

regs->cntr = I915_READ(reg) | DISPLAY_PLANE_ENABLE;
- dev_priv->display.commit_plane(crtc);
+ dev_priv->display.commit_plane(crtc, regs);
}

void
@@ -643,7 +643,7 @@ intel_disable_primary(struct drm_crtc *crtc)
return;

regs->cntr = I915_READ(reg) & ~DISPLAY_PLANE_ENABLE;
- dev_priv->display.commit_plane(crtc);
+ dev_priv->display.commit_plane(crtc, regs);

intel_crtc->primary_disabled = true;
intel_update_fbc(dev);
@@ -668,7 +668,7 @@ ilk_update_colorkey(struct drm_plane *plane,
else if (key->flags & I915_SET_COLORKEY_SOURCE)
regs->cntr |= DVS_SOURCE_KEY;

- ilk_commit_plane(plane);
+ ilk_commit_plane(plane, regs);
POSTING_READ(DVSKEYMSK(intel_plane->pipe));

return 0;