aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_sprite.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2017-03-09 17:44:33 +0200
committerVille Syrjälä <ville.syrjala@linux.intel.com>2017-03-13 21:15:06 +0200
commitdd584fc0711a28fb338bf66a623178e468c82272 (patch)
tree9019cadca3737f4ecbaf2281116d8eec5c75445e /drivers/gpu/drm/i915/intel_sprite.c
parentdrm/i915: Organize plane register writes into tighter bunches (diff)
downloadlinux-dev-dd584fc0711a28fb338bf66a623178e468c82272.tar.xz
linux-dev-dd584fc0711a28fb338bf66a623178e468c82272.zip
drm/i915: Use I915_READ_FW for plane updates
Optimize the plane register accesses a little bit by grabbing the uncore lock manually across the entire pile of accesses and using I915_READ_FW(). This helps keep the pipe update vblank evade critical section below our 100 usec deadline, particularly with lockdep enabled. And in general we want to keep that critical section as short as possible as it's executed with interrupts disabled. Not all plane updates currently happen from within the vblank evade critical section, so we must use the irqsave/irqrestore variants of the spinlock functions in the plane hooks. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170309154434.29303-5-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sprite.c')
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c228
1 files changed, 134 insertions, 94 deletions
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 532db7d62290..b931d0bd7a64 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -230,6 +230,7 @@ skl_update_plane(struct drm_plane *drm_plane,
uint32_t y = plane_state->main.y;
uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
+ unsigned long irqflags;
plane_ctl = PLANE_CTL_ENABLE;
@@ -255,22 +256,24 @@ skl_update_plane(struct drm_plane *drm_plane,
crtc_w--;
crtc_h--;
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
if (IS_GEMINILAKE(dev_priv)) {
- I915_WRITE(PLANE_COLOR_CTL(pipe, plane_id),
- PLANE_COLOR_PIPE_GAMMA_ENABLE |
- PLANE_COLOR_PIPE_CSC_ENABLE |
- PLANE_COLOR_PLANE_GAMMA_DISABLE);
+ I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id),
+ PLANE_COLOR_PIPE_GAMMA_ENABLE |
+ PLANE_COLOR_PIPE_CSC_ENABLE |
+ PLANE_COLOR_PLANE_GAMMA_DISABLE);
}
if (key->flags) {
- I915_WRITE(PLANE_KEYVAL(pipe, plane_id), key->min_value);
- I915_WRITE(PLANE_KEYMAX(pipe, plane_id), key->max_value);
- I915_WRITE(PLANE_KEYMSK(pipe, plane_id), key->channel_mask);
+ I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
+ I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value);
+ I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), key->channel_mask);
}
- I915_WRITE(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
- I915_WRITE(PLANE_STRIDE(pipe, plane_id), stride);
- I915_WRITE(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
+ I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
+ I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
+ I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
/* program plane scaler */
if (plane_state->scaler_id >= 0) {
@@ -279,22 +282,24 @@ skl_update_plane(struct drm_plane *drm_plane,
scaler = &crtc_state->scaler_state.scalers[scaler_id];
- I915_WRITE(SKL_PS_CTRL(pipe, scaler_id),
- PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode);
- I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
- I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
- I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id),
- ((crtc_w + 1) << 16)|(crtc_h + 1));
+ I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
+ PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode);
+ I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
+ I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
+ I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id),
+ ((crtc_w + 1) << 16)|(crtc_h + 1));
- I915_WRITE(PLANE_POS(pipe, plane_id), 0);
+ I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);
} else {
- I915_WRITE(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
+ I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
}
- I915_WRITE(PLANE_CTL(pipe, plane_id), plane_ctl);
- I915_WRITE(PLANE_SURF(pipe, plane_id),
- intel_plane_ggtt_offset(plane_state) + surf_addr);
- POSTING_READ(PLANE_SURF(pipe, plane_id));
+ I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
+ I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
+ intel_plane_ggtt_offset(plane_state) + surf_addr);
+ POSTING_READ_FW(PLANE_SURF(pipe, plane_id));
+
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static void
@@ -305,11 +310,16 @@ skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
struct intel_plane *intel_plane = to_intel_plane(dplane);
enum plane_id plane_id = intel_plane->id;
enum pipe pipe = intel_plane->pipe;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
- I915_WRITE(PLANE_CTL(pipe, plane_id), 0);
+ I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
- I915_WRITE(PLANE_SURF(pipe, plane_id), 0);
- POSTING_READ(PLANE_SURF(pipe, plane_id));
+ I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
+ POSTING_READ_FW(PLANE_SURF(pipe, plane_id));
+
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static void
@@ -332,23 +342,23 @@ chv_update_csc(struct intel_plane *intel_plane, uint32_t format)
* Cb and Cr apparently come in as signed already, so no
* need for any offset. For Y we need to remove the offset.
*/
- I915_WRITE(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(-64));
- I915_WRITE(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
- I915_WRITE(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
-
- I915_WRITE(SPCSCC01(plane_id), SPCSC_C1(4769) | SPCSC_C0(6537));
- I915_WRITE(SPCSCC23(plane_id), SPCSC_C1(-3330) | SPCSC_C0(0));
- I915_WRITE(SPCSCC45(plane_id), SPCSC_C1(-1605) | SPCSC_C0(4769));
- I915_WRITE(SPCSCC67(plane_id), SPCSC_C1(4769) | SPCSC_C0(0));
- I915_WRITE(SPCSCC8(plane_id), SPCSC_C0(8263));
-
- I915_WRITE(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(940) | SPCSC_IMIN(64));
- I915_WRITE(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
- I915_WRITE(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
-
- I915_WRITE(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
- I915_WRITE(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
- I915_WRITE(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
+ I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(-64));
+ I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
+ I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
+
+ I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(4769) | SPCSC_C0(6537));
+ I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(-3330) | SPCSC_C0(0));
+ I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(-1605) | SPCSC_C0(4769));
+ I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(4769) | SPCSC_C0(0));
+ I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(8263));
+
+ I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(940) | SPCSC_IMIN(64));
+ I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
+ I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
+
+ I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
+ I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
+ I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
}
static void
@@ -374,6 +384,7 @@ vlv_update_plane(struct drm_plane *dplane,
uint32_t y = plane_state->base.src.y1 >> 16;
uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
+ unsigned long irqflags;
sprctl = SP_ENABLE;
@@ -456,29 +467,33 @@ vlv_update_plane(struct drm_plane *dplane,
linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
chv_update_csc(intel_plane, fb->format->format);
if (key->flags) {
- I915_WRITE(SPKEYMINVAL(pipe, plane_id), key->min_value);
- I915_WRITE(SPKEYMAXVAL(pipe, plane_id), key->max_value);
- I915_WRITE(SPKEYMSK(pipe, plane_id), key->channel_mask);
+ I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
+ I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
+ I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
}
- I915_WRITE(SPSTRIDE(pipe, plane_id), fb->pitches[0]);
- I915_WRITE(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
+ I915_WRITE_FW(SPSTRIDE(pipe, plane_id), fb->pitches[0]);
+ I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
if (fb->modifier == I915_FORMAT_MOD_X_TILED)
- I915_WRITE(SPTILEOFF(pipe, plane_id), (y << 16) | x);
+ I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
else
- I915_WRITE(SPLINOFF(pipe, plane_id), linear_offset);
+ I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
- I915_WRITE(SPCONSTALPHA(pipe, plane_id), 0);
+ I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
- I915_WRITE(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
- I915_WRITE(SPCNTR(pipe, plane_id), sprctl);
- I915_WRITE(SPSURF(pipe, plane_id),
- intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
- POSTING_READ(SPSURF(pipe, plane_id));
+ I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
+ I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
+ I915_WRITE_FW(SPSURF(pipe, plane_id),
+ intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
+ POSTING_READ_FW(SPSURF(pipe, plane_id));
+
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static void
@@ -489,11 +504,16 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
struct intel_plane *intel_plane = to_intel_plane(dplane);
enum pipe pipe = intel_plane->pipe;
enum plane_id plane_id = intel_plane->id;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
- I915_WRITE(SPCNTR(pipe, plane_id), 0);
+ I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
- I915_WRITE(SPSURF(pipe, plane_id), 0);
- POSTING_READ(SPSURF(pipe, plane_id));
+ I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
+ POSTING_READ_FW(SPSURF(pipe, plane_id));
+
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static void
@@ -518,6 +538,7 @@ ivb_update_plane(struct drm_plane *plane,
uint32_t y = plane_state->base.src.y1 >> 16;
uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
+ unsigned long irqflags;
sprctl = SPRITE_ENABLE;
@@ -590,31 +611,35 @@ ivb_update_plane(struct drm_plane *plane,
linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
if (key->flags) {
- I915_WRITE(SPRKEYVAL(pipe), key->min_value);
- I915_WRITE(SPRKEYMAX(pipe), key->max_value);
- I915_WRITE(SPRKEYMSK(pipe), key->channel_mask);
+ I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
+ I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
+ I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
}
- I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
- I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
+ I915_WRITE_FW(SPRSTRIDE(pipe), fb->pitches[0]);
+ I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
* register */
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
- I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
+ I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
else if (fb->modifier == I915_FORMAT_MOD_X_TILED)
- I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
+ I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
else
- I915_WRITE(SPRLINOFF(pipe), linear_offset);
+ I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
- I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
+ I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
if (intel_plane->can_scale)
- I915_WRITE(SPRSCALE(pipe), sprscale);
- I915_WRITE(SPRCTL(pipe), sprctl);
- I915_WRITE(SPRSURF(pipe),
- intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
- POSTING_READ(SPRSURF(pipe));
+ I915_WRITE_FW(SPRSCALE(pipe), sprscale);
+ I915_WRITE_FW(SPRCTL(pipe), sprctl);
+ I915_WRITE_FW(SPRSURF(pipe),
+ intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
+ POSTING_READ_FW(SPRSURF(pipe));
+
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static void
@@ -624,14 +649,19 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_plane *intel_plane = to_intel_plane(plane);
int pipe = intel_plane->pipe;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
- I915_WRITE(SPRCTL(pipe), 0);
+ I915_WRITE_FW(SPRCTL(pipe), 0);
/* Can't leave the scaler enabled... */
if (intel_plane->can_scale)
- I915_WRITE(SPRSCALE(pipe), 0);
+ I915_WRITE_FW(SPRSCALE(pipe), 0);
- I915_WRITE(SPRSURF(pipe), 0);
- POSTING_READ(SPRSURF(pipe));
+ I915_WRITE_FW(SPRSURF(pipe), 0);
+ POSTING_READ_FW(SPRSURF(pipe));
+
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static void
@@ -656,6 +686,7 @@ ilk_update_plane(struct drm_plane *plane,
uint32_t y = plane_state->base.src.y1 >> 16;
uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
+ unsigned long irqflags;
dvscntr = DVS_ENABLE;
@@ -722,26 +753,30 @@ ilk_update_plane(struct drm_plane *plane,
linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
if (key->flags) {
- I915_WRITE(DVSKEYVAL(pipe), key->min_value);
- I915_WRITE(DVSKEYMAX(pipe), key->max_value);
- I915_WRITE(DVSKEYMSK(pipe), key->channel_mask);
+ I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
+ I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
+ I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
}
- I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
- I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
+ I915_WRITE_FW(DVSSTRIDE(pipe), fb->pitches[0]);
+ I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
if (fb->modifier == I915_FORMAT_MOD_X_TILED)
- I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
+ I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
else
- I915_WRITE(DVSLINOFF(pipe), linear_offset);
-
- I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
- I915_WRITE(DVSSCALE(pipe), dvsscale);
- I915_WRITE(DVSCNTR(pipe), dvscntr);
- I915_WRITE(DVSSURF(pipe),
- intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
- POSTING_READ(DVSSURF(pipe));
+ I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
+
+ I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
+ I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
+ I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
+ I915_WRITE_FW(DVSSURF(pipe),
+ intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
+ POSTING_READ_FW(DVSSURF(pipe));
+
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static void
@@ -751,13 +786,18 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_plane *intel_plane = to_intel_plane(plane);
int pipe = intel_plane->pipe;
+ unsigned long irqflags;
- I915_WRITE(DVSCNTR(pipe), 0);
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+ I915_WRITE_FW(DVSCNTR(pipe), 0);
/* Disable the scaler */
- I915_WRITE(DVSSCALE(pipe), 0);
+ I915_WRITE_FW(DVSSCALE(pipe), 0);
+
+ I915_WRITE_FW(DVSSURF(pipe), 0);
+ POSTING_READ_FW(DVSSURF(pipe));
- I915_WRITE(DVSSURF(pipe), 0);
- POSTING_READ(DVSSURF(pipe));
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static int