From d49f70915c07c1a313e459d23fad61ddbeeb1bae Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 25 Apr 2013 15:15:00 +0100 Subject: drm/i915: Ivybridge is the odd one when it comes to pipe scalers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Between ivb, hsw and vlv, only Ivybridge has sprites with scaling capabilities. Also make max_downscale coherent with that. v2: Rebase on top of the recent ivb/vlv/hsw sprite scaling fixes. Signed-off-by: Damien Lespiau (v1) Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sprite.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_sprite.c') diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index c7d25c5dd4e6..18993ad93540 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -918,13 +918,15 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) break; case 7: - if (IS_HASWELL(dev) || IS_VALLEYVIEW(dev)) - intel_plane->can_scale = false; - else + if (IS_IVYBRIDGE(dev)) { intel_plane->can_scale = true; + intel_plane->max_downscale = 2; + } else { + intel_plane->can_scale = false; + intel_plane->max_downscale = 1; + } if (IS_VALLEYVIEW(dev)) { - intel_plane->max_downscale = 1; intel_plane->update_plane = vlv_update_plane; intel_plane->disable_plane = vlv_disable_plane; intel_plane->update_colorkey = vlv_update_colorkey; @@ -933,7 +935,6 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) plane_formats = vlv_plane_formats; num_plane_formats = ARRAY_SIZE(vlv_plane_formats); } else { - intel_plane->max_downscale = 2; intel_plane->update_plane = ivb_update_plane; intel_plane->disable_plane = ivb_disable_plane; intel_plane->update_colorkey = ivb_update_colorkey; -- cgit v1.2.3-59-g8ed1b From 1731693a5a372869d017e601a23b1ce2eb3135ed Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 24 Apr 2013 18:52:38 +0300 Subject: drm/i915: Implement proper clipping for video sprites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Properly clip the source when the destination gets clipped by the pipe dimensions. Sadly the video sprite hardware is rather limited so it can't do proper sub-pixel postitioning. Resort to truncating the source coordinates to (macro)pixel boundary. The scaling checks are done using the strict drm_region functions. Which means that an error is returned when the min/max scaling ratios are exceeded. Also do some additional checking against various hardware limits. v2: Truncate src coords instead of rounding to avoid increasing src viewport size, and adapt to changes in drm_calc_{h,v}scale(). v3: Adapt to drm_region->drm_rect rename. Fix misaligned crtc_w for packed YUV formats when scaling isn't supported. v4: Use stricter scaling checks, use drm_rect_equals() v5: If sprite is below min size, make it invisible instead returning an error. Use WARN_ON() instead if BUG_ON(), and add one to sanity check the src viewport size. v6: Add comments to remind about src and dst coordinate types Reviewed-by: Chris Wilson Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sprite.c | 196 +++++++++++++++++++++++++++--------- 1 file changed, 149 insertions(+), 47 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_sprite.c') diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 18993ad93540..87fe3b625c4b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "intel_drv.h" #include #include "i915_drv.h" @@ -583,6 +584,20 @@ ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key) key->flags = I915_SET_COLORKEY_NONE; } +static bool +format_is_yuv(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_YUYV: + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_YVYU: + return true; + default: + return false; + } +} + static int intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, @@ -600,9 +615,29 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); int ret = 0; - int x = src_x >> 16, y = src_y >> 16; - int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay; bool disable_primary = false; + bool visible; + int hscale, vscale; + int max_scale, min_scale; + int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); + struct drm_rect src = { + /* sample coordinates in 16.16 fixed point */ + .x1 = src_x, + .x2 = src_x + src_w, + .y1 = src_y, + .y2 = src_y + src_h, + }; + struct drm_rect dst = { + /* integer pixels */ + .x1 = crtc_x, + .x2 = crtc_x + crtc_w, + .y1 = crtc_y, + .y2 = crtc_y + crtc_h, + }; + const struct drm_rect clip = { + .x2 = crtc->mode.hdisplay, + .y2 = crtc->mode.vdisplay, + }; intel_fb = to_intel_framebuffer(fb); obj = intel_fb->obj; @@ -618,19 +653,23 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, intel_plane->src_w = src_w; intel_plane->src_h = src_h; - src_w = src_w >> 16; - src_h = src_h >> 16; - /* Pipe must be running... */ - if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE)) + if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE)) { + DRM_DEBUG_KMS("Pipe disabled\n"); return -EINVAL; + } - if (crtc_x >= primary_w || crtc_y >= primary_h) + /* Don't modify another pipe's plane */ + if (intel_plane->pipe != intel_crtc->pipe) { + DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); return -EINVAL; + } - /* Don't modify another pipe's plane */ - if (intel_plane->pipe != intel_crtc->pipe) + /* FIXME check all gen limits */ + if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) { + DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n"); return -EINVAL; + } /* Sprite planes can be linear or x-tiled surfaces */ switch (obj->tiling_mode) { @@ -638,55 +677,115 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, case I915_TILING_X: break; default: + DRM_DEBUG_KMS("Unsupported tiling mode\n"); return -EINVAL; } - /* - * Clamp the width & height into the visible area. Note we don't - * try to scale the source if part of the visible region is offscreen. - * The caller must handle that by adjusting source offset and size. - */ - if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) { - crtc_w += crtc_x; - crtc_x = 0; + max_scale = intel_plane->max_downscale << 16; + min_scale = intel_plane->can_scale ? 1 : (1 << 16); + + hscale = drm_rect_calc_hscale(&src, &dst, min_scale, max_scale); + if (hscale < 0) { + DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n"); + drm_rect_debug_print(&src, true); + drm_rect_debug_print(&dst, false); + + return hscale; } - if ((crtc_x + crtc_w) <= 0) /* Nothing to display */ - goto out; - if ((crtc_x + crtc_w) > primary_w) - crtc_w = primary_w - crtc_x; - if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) { - crtc_h += crtc_y; - crtc_y = 0; + vscale = drm_rect_calc_vscale(&src, &dst, min_scale, max_scale); + if (vscale < 0) { + DRM_DEBUG_KMS("Vertical scaling factor out of limits\n"); + drm_rect_debug_print(&src, true); + drm_rect_debug_print(&dst, false); + + return vscale; } - if ((crtc_y + crtc_h) <= 0) /* Nothing to display */ - goto out; - if (crtc_y + crtc_h > primary_h) - crtc_h = primary_h - crtc_y; - if (!crtc_w || !crtc_h) /* Again, nothing to display */ - goto out; + visible = drm_rect_clip_scaled(&src, &dst, &clip, hscale, vscale); - /* - * We may not have a scaler, eg. HSW does not have it any more - */ - if (!intel_plane->can_scale && (crtc_w != src_w || crtc_h != src_h)) - return -EINVAL; + crtc_x = dst.x1; + crtc_y = dst.y1; + crtc_w = drm_rect_width(&dst); + crtc_h = drm_rect_height(&dst); - /* - * We can take a larger source and scale it down, but - * only so much... 16x is the max on SNB. - */ - if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale) - return -EINVAL; + if (visible) { + /* Make the source viewport size an exact multiple of the scaling factors. */ + drm_rect_adjust_size(&src, + drm_rect_width(&dst) * hscale - drm_rect_width(&src), + drm_rect_height(&dst) * vscale - drm_rect_height(&src)); + + /* sanity check to make sure the src viewport wasn't enlarged */ + WARN_ON(src.x1 < (int) src_x || + src.y1 < (int) src_y || + src.x2 > (int) (src_x + src_w) || + src.y2 > (int) (src_y + src_h)); + + /* + * Hardware doesn't handle subpixel coordinates. + * Adjust to (macro)pixel boundary, but be careful not to + * increase the source viewport size, because that could + * push the downscaling factor out of bounds. + * + * FIXME Should we be really strict and reject the + * config if it results in non (macro)pixel aligned + * coords? + */ + src_x = src.x1 >> 16; + src_w = drm_rect_width(&src) >> 16; + src_y = src.y1 >> 16; + src_h = drm_rect_height(&src) >> 16; + + if (format_is_yuv(fb->pixel_format)) { + src_x &= ~1; + src_w &= ~1; + + /* + * Must keep src and dst the + * same if we can't scale. + */ + if (!intel_plane->can_scale) + crtc_w &= ~1; + + if (crtc_w == 0) + visible = false; + } + } + + /* Check size restrictions when scaling */ + if (visible && (src_w != crtc_w || src_h != crtc_h)) { + unsigned int width_bytes; + + WARN_ON(!intel_plane->can_scale); + + /* FIXME interlacing min height is 6 */ + + if (crtc_w < 3 || crtc_h < 3) + visible = false; + + if (src_w < 3 || src_h < 3) + visible = false; + + width_bytes = ((src_x * pixel_size) & 63) + src_w * pixel_size; + + if (src_w > 2048 || src_h > 2048 || + width_bytes > 4096 || fb->pitches[0] > 4096) { + DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); + return -EINVAL; + } + } + + dst.x1 = crtc_x; + dst.x2 = crtc_x + crtc_w; + dst.y1 = crtc_y; + dst.y2 = crtc_y + crtc_h; /* * If the sprite is completely covering the primary plane, * we can disable the primary and save power. */ - if ((crtc_x == 0) && (crtc_y == 0) && - (crtc_w == primary_w) && (crtc_h == primary_h)) - disable_primary = true; + disable_primary = drm_rect_equals(&dst, &clip); + WARN_ON(disable_primary && !visible); mutex_lock(&dev->struct_mutex); @@ -708,8 +807,12 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, if (!disable_primary) intel_enable_primary(crtc); - intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, - crtc_w, crtc_h, x, y, src_w, src_h); + if (visible) + intel_plane->update_plane(plane, fb, obj, + crtc_x, crtc_y, crtc_w, crtc_h, + src_x, src_y, src_w, src_h); + else + intel_plane->disable_plane(plane); if (disable_primary) intel_disable_primary(crtc); @@ -732,7 +835,6 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, out_unlock: mutex_unlock(&dev->struct_mutex); -out: return ret; } -- cgit v1.2.3-59-g8ed1b From 3c3686cd9700efefcfc24ab5910b3e5fffd0b069 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 24 Apr 2013 18:52:39 +0300 Subject: drm/i915: Relax the sprite scaling limits checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce the size of the the src/dst viewport to keep the scalign ratios in check. v2: Below min size sprite handling squashed to previous patch Reviewed-by: Chris Wilson Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sprite.c | 48 +++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_sprite.c') diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 87fe3b625c4b..19b9cb961b5a 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -681,26 +681,19 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, return -EINVAL; } + /* + * FIXME the following code does a bunch of fuzzy adjustments to the + * coordinates and sizes. We probably need some way to decide whether + * more strict checking should be done instead. + */ max_scale = intel_plane->max_downscale << 16; min_scale = intel_plane->can_scale ? 1 : (1 << 16); - hscale = drm_rect_calc_hscale(&src, &dst, min_scale, max_scale); - if (hscale < 0) { - DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n"); - drm_rect_debug_print(&src, true); - drm_rect_debug_print(&dst, false); - - return hscale; - } - - vscale = drm_rect_calc_vscale(&src, &dst, min_scale, max_scale); - if (vscale < 0) { - DRM_DEBUG_KMS("Vertical scaling factor out of limits\n"); - drm_rect_debug_print(&src, true); - drm_rect_debug_print(&dst, false); + hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale); + BUG_ON(hscale < 0); - return vscale; - } + vscale = drm_rect_calc_vscale_relaxed(&src, &dst, min_scale, max_scale); + BUG_ON(vscale < 0); visible = drm_rect_clip_scaled(&src, &dst, &clip, hscale, vscale); @@ -710,6 +703,25 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, crtc_h = drm_rect_height(&dst); if (visible) { + /* check again in case clipping clamped the results */ + hscale = drm_rect_calc_hscale(&src, &dst, min_scale, max_scale); + if (hscale < 0) { + DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n"); + drm_rect_debug_print(&src, true); + drm_rect_debug_print(&dst, false); + + return hscale; + } + + vscale = drm_rect_calc_vscale(&src, &dst, min_scale, max_scale); + if (vscale < 0) { + DRM_DEBUG_KMS("Vertical scaling factor out of limits\n"); + drm_rect_debug_print(&src, true); + drm_rect_debug_print(&dst, false); + + return vscale; + } + /* Make the source viewport size an exact multiple of the scaling factors. */ drm_rect_adjust_size(&src, drm_rect_width(&dst) * hscale - drm_rect_width(&src), @@ -726,10 +738,6 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, * Adjust to (macro)pixel boundary, but be careful not to * increase the source viewport size, because that could * push the downscaling factor out of bounds. - * - * FIXME Should we be really strict and reject the - * config if it results in non (macro)pixel aligned - * coords? */ src_x = src.x1 >> 16; src_w = drm_rect_width(&src) >> 16; -- cgit v1.2.3-59-g8ed1b From 4c4ff43a692b44c6e326f9f28208f3d78ea51f7e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 24 May 2013 11:59:17 -0300 Subject: drm/i915: add "enable" argument to intel_update_sprite_watermarks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because we want to call it from the "sprite disable" paths, since on Haswell we need to update the sprite watermarks when we disable sprites. For now, all this patch does is to add the "enable" argument and call intel_update_sprite_watermarks from inside ivb_disable_plane. This shouldn't change how the code behaves because on sandybridge_update_sprite_wm we just ignore the "!enable" case. The patches that implement Haswell watermarks will make use of the changes introduced by this patch. Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 11 ++++++++--- drivers/gpu/drm/i915/intel_sprite.c | 8 +++++--- 4 files changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_sprite.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f6419f40df38..e09c54c73a22 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -315,7 +315,8 @@ struct drm_i915_display_funcs { int (*get_fifo_size)(struct drm_device *dev, int plane); void (*update_wm)(struct drm_device *dev); void (*update_sprite_wm)(struct drm_device *dev, int pipe, - uint32_t sprite_width, int pixel_size); + uint32_t sprite_width, int pixel_size, + bool enable); void (*modeset_global_resources)(struct drm_device *dev); /* Returns the active state of the crtc, and if the crtc is active, * fills out the pipe-config with the hw state. */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 83b4fe4b7be0..3e6e5e7b089f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -731,7 +731,7 @@ extern void intel_ddi_init(struct drm_device *dev, enum port port); extern void intel_update_watermarks(struct drm_device *dev); extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe, uint32_t sprite_width, - int pixel_size); + int pixel_size, bool enable); extern unsigned long intel_gen4_compute_page_offset(int *x, int *y, unsigned int tiling_mode, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index fa4c818d4b00..3515efd049dd 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2195,7 +2195,8 @@ sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane, } static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe, - uint32_t sprite_width, int pixel_size) + uint32_t sprite_width, int pixel_size, + bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ @@ -2203,6 +2204,9 @@ static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe, int sprite_wm, reg; int ret; + if (!enable) + return; + switch (pipe) { case 0: reg = WM0_PIPEA_ILK; @@ -2314,13 +2318,14 @@ void intel_update_watermarks(struct drm_device *dev) } void intel_update_sprite_watermarks(struct drm_device *dev, int pipe, - uint32_t sprite_width, int pixel_size) + uint32_t sprite_width, int pixel_size, + bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; if (dev_priv->display.update_sprite_wm) dev_priv->display.update_sprite_wm(dev, pipe, sprite_width, - pixel_size); + pixel_size, enable); } static struct drm_i915_gem_object * diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 19b9cb961b5a..04d38d4d811a 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -114,7 +114,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb, crtc_w--; crtc_h--; - intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size); + intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true); I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x); @@ -268,7 +268,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, crtc_w--; crtc_h--; - intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size); + intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true); /* * IVB workaround: must disable low power watermarks for at least @@ -335,6 +335,8 @@ ivb_disable_plane(struct drm_plane *plane) dev_priv->sprite_scaling_enabled &= ~(1 << pipe); + intel_update_sprite_watermarks(dev, pipe, 0, 0, false); + /* potentially re-enable LP watermarks */ if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) intel_update_watermarks(dev); @@ -453,7 +455,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, crtc_w--; crtc_h--; - intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size); + intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true); dvsscale = 0; if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h) -- cgit v1.2.3-59-g8ed1b From bb53d4aeac59079240605ef9269166f204612b78 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 4 Jun 2013 13:49:04 +0300 Subject: drm/i915: Disable/restore all sprite planes around modeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disable/restore sprite planes around mode-set just like we do for the primary and cursor planes. Now that we have working sprite clipping, this actually works quite decently. Previosuly we didn't even bother to disable sprites when changing mode, which could lead to a corrupted sprite appearing on the screen after a modeset (at least on my IVB). Not sure if all hardware generations would be so forgiving when enabled sprites end up outside the pipe dimensons. v2: Disable rather than enable sprites in ironlake_crtc_disable() Signed-off-by: Ville Syrjälä Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 29 +++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_sprite.c | 8 ++++++++ 3 files changed, 38 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_sprite.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 62557ecc0eff..f084a1dd8f4d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3164,6 +3164,28 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc) } } +static void intel_enable_planes(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + struct intel_plane *intel_plane; + + list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head) + if (intel_plane->pipe == pipe) + intel_plane_restore(&intel_plane->base); +} + +static void intel_disable_planes(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + struct intel_plane *intel_plane; + + list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head) + if (intel_plane->pipe == pipe) + intel_plane_disable(&intel_plane->base); +} + static void ironlake_crtc_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -3219,6 +3241,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) intel_enable_pipe(dev_priv, pipe, intel_crtc->config.has_pch_encoder); intel_enable_plane(dev_priv, plane, pipe); + intel_enable_planes(crtc); intel_crtc_update_cursor(crtc, true); if (intel_crtc->config.has_pch_encoder) @@ -3327,6 +3350,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_enable_pipe(dev_priv, pipe, intel_crtc->config.has_pch_encoder); intel_enable_plane(dev_priv, plane, pipe); + intel_enable_planes(crtc); intel_crtc_update_cursor(crtc, true); hsw_enable_ips(intel_crtc); @@ -3391,6 +3415,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) intel_disable_fbc(dev); intel_crtc_update_cursor(crtc, false); + intel_disable_planes(crtc); intel_disable_plane(dev_priv, plane, pipe); intel_set_pch_fifo_underrun_reporting(dev, pipe, false); @@ -3473,6 +3498,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) hsw_disable_ips(intel_crtc); intel_crtc_update_cursor(crtc, false); + intel_disable_planes(crtc); intel_disable_plane(dev_priv, plane, pipe); if (intel_crtc->config.has_pch_encoder) @@ -3620,6 +3646,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) intel_enable_pipe(dev_priv, pipe, false); intel_enable_plane(dev_priv, plane, pipe); + intel_enable_planes(crtc); intel_crtc_update_cursor(crtc, true); intel_update_fbc(dev); @@ -3657,6 +3684,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) intel_enable_pipe(dev_priv, pipe, false); intel_enable_plane(dev_priv, plane, pipe); + intel_enable_planes(crtc); intel_crtc_update_cursor(crtc, true); if (IS_G4X(dev)) g4x_fixup_plane(dev_priv, pipe); @@ -3709,6 +3737,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) intel_crtc_dpms_overlay(intel_crtc, false); intel_crtc_update_cursor(crtc, false); + intel_disable_planes(crtc); intel_disable_plane(dev_priv, plane, pipe); intel_disable_pipe(dev_priv, pipe); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index eae3dbc4e3ee..6bbebf824078 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -633,6 +633,7 @@ extern void intel_connector_dpms(struct drm_connector *, int mode); extern bool intel_connector_get_hw_state(struct intel_connector *connector); extern void intel_modeset_check_state(struct drm_device *dev); extern void intel_plane_restore(struct drm_plane *plane); +extern void intel_plane_disable(struct drm_plane *plane); static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 04d38d4d811a..1fa5612a4572 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -957,6 +957,14 @@ void intel_plane_restore(struct drm_plane *plane) intel_plane->src_w, intel_plane->src_h); } +void intel_plane_disable(struct drm_plane *plane) +{ + if (!plane->crtc || !plane->fb) + return; + + intel_disable_plane(plane); +} + static const struct drm_plane_funcs intel_plane_funcs = { .update_plane = intel_update_plane, .disable_plane = intel_disable_plane, -- cgit v1.2.3-59-g8ed1b