@@ -958,6 +958,10 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
else
plane->min_alignment = i9xx_plane_min_alignment;
+ /* FIXME undocumented for VLV/CHV so not sure what's actually needed */
+ if (intel_scanout_needs_vtd_wa(dev_priv))
+ plane->vtd_guard = 128;
+
if (IS_I830(dev_priv) || IS_I845G(dev_priv)) {
plane->update_arm = i830_plane_update_arm;
} else {
@@ -1019,6 +1019,9 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
else
cursor->min_alignment = i9xx_cursor_min_alignment;
+ if (intel_scanout_needs_vtd_wa(dev_priv))
+ cursor->vtd_guard = 2;
+
cursor->update_arm = i9xx_cursor_update_arm;
cursor->disable_arm = i9xx_cursor_disable_arm;
cursor->get_hw_state = i9xx_cursor_get_hw_state;
@@ -144,6 +144,7 @@ struct intel_framebuffer {
struct i915_address_space *dpt_vm;
unsigned int min_alignment;
+ unsigned int vtd_guard;
};
enum intel_hotplug_state {
@@ -1445,6 +1446,7 @@ struct intel_plane {
enum plane_id id;
enum pipe pipe;
bool need_async_flip_toggle_wa;
+ u8 vtd_guard;
u32 frontbuffer_bit;
struct {
@@ -1660,6 +1660,22 @@ static unsigned int intel_fb_min_alignment(const struct drm_framebuffer *fb)
return min_alignment;
}
+static unsigned int intel_fb_vtd_guard(const struct drm_framebuffer *fb)
+{
+ struct drm_i915_private *i915 = to_i915(fb->dev);
+ struct intel_plane *plane;
+ unsigned int vtd_guard = 0;
+
+ for_each_intel_plane(&i915->drm, plane) {
+ if (!drm_plane_has_format(&plane->base, fb->format->format, fb->modifier))
+ continue;
+
+ vtd_guard = max_t(unsigned int, vtd_guard, plane->vtd_guard);
+ }
+
+ return vtd_guard;
+}
+
int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *fb)
{
struct drm_gem_object *obj = intel_fb_bo(&fb->base);
@@ -1757,6 +1773,7 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *
}
fb->min_alignment = intel_fb_min_alignment(&fb->base);
+ fb->vtd_guard = intel_fb_vtd_guard(&fb->base);
return 0;
}
@@ -1765,15 +1782,13 @@ unsigned int intel_fb_view_vtd_guard(const struct drm_framebuffer *fb,
const struct intel_fb_view *view,
unsigned int rotation)
{
- struct drm_i915_private *i915 = to_i915(fb->dev);
unsigned int vtd_guard;
int color_plane;
- if (!intel_scanout_needs_vtd_wa(i915))
+ vtd_guard = to_intel_framebuffer(fb)->vtd_guard;
+ if (!vtd_guard)
return 0;
- vtd_guard = 168;
-
for (color_plane = 0; color_plane < fb->format->num_planes; color_plane++) {
unsigned int stride, tile;
@@ -1609,6 +1609,10 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
plane->min_alignment = vlv_plane_min_alignment;
plane->min_cdclk = vlv_plane_min_cdclk;
+ /* FIXME undocumented for VLV/CHV so not sure what's actually needed */
+ if (intel_scanout_needs_vtd_wa(dev_priv))
+ plane->vtd_guard = 128;
+
if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
formats = chv_pipe_b_sprite_formats;
num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
@@ -1635,6 +1639,9 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
plane->min_alignment = g4x_sprite_min_alignment;
+ if (intel_scanout_needs_vtd_wa(dev_priv))
+ plane->vtd_guard = 64;
+
formats = snb_sprite_formats;
num_formats = ARRAY_SIZE(snb_sprite_formats);
@@ -1649,6 +1656,9 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
plane->min_alignment = g4x_sprite_min_alignment;
plane->min_cdclk = g4x_sprite_min_cdclk;
+ if (intel_scanout_needs_vtd_wa(dev_priv))
+ plane->vtd_guard = 64;
+
if (IS_SANDYBRIDGE(dev_priv)) {
formats = snb_sprite_formats;
num_formats = ARRAY_SIZE(snb_sprite_formats);
@@ -2754,6 +2754,9 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
else
plane->min_alignment = skl_plane_min_alignment;
+ if (intel_scanout_needs_vtd_wa(dev_priv))
+ plane->vtd_guard = DISPLAY_VER(dev_priv) >= 10 ? 168 : 136;
+
if (DISPLAY_VER(dev_priv) >= 11) {
plane->update_noarm = icl_plane_update_noarm;
plane->update_arm = icl_plane_update_arm;