struct drm_i915_gem_object *obj)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
+       unsigned int tiling = i915_gem_object_get_tiling(obj);
        int ret;
        u32 pitch_limit, stride_alignment;
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
        if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) {
-               /* Enforce that fb modifier and tiling mode match, but only for
-                * X-tiled. This is needed for FBC. */
-               if (!!(i915_gem_object_get_tiling(obj) == I915_TILING_X) !=
-                   !!(mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED)) {
+               /*
+                * If there's a fence, enforce that
+                * the fb modifier and tiling mode match.
+                */
+               if (tiling != I915_TILING_NONE &&
+                   tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
                        DRM_DEBUG("tiling_mode doesn't match fb modifier\n");
                        return -EINVAL;
                }
        } else {
-               if (i915_gem_object_get_tiling(obj) == I915_TILING_X)
+               if (tiling == I915_TILING_X) {
                        mode_cmd->modifier[0] = I915_FORMAT_MOD_X_TILED;
-               else if (i915_gem_object_get_tiling(obj) == I915_TILING_Y) {
+               } else if (tiling == I915_TILING_Y) {
                        DRM_DEBUG("No Y tiling for legacy addfb\n");
                        return -EINVAL;
                }
                return -EINVAL;
        }
 
+       /*
+        * gen2/3 display engine uses the fence if present,
+        * so the tiling mode must match the fb modifier exactly.
+        */
+       if (INTEL_INFO(dev_priv)->gen < 4 &&
+           tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
+               DRM_DEBUG("tiling_mode must match fb modifier exactly on gen2/3\n");
+               return -EINVAL;
+       }
+
        stride_alignment = intel_fb_stride_alignment(dev_priv,
                                                     mode_cmd->modifier[0],
                                                     mode_cmd->pixel_format);
                return -EINVAL;
        }
 
-       if (mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED &&
+       /*
+        * If there's a fence, enforce that
+        * the fb pitch and fence stride match.
+        */
+       if (tiling != I915_TILING_NONE &&
            mode_cmd->pitches[0] != i915_gem_object_get_stride(obj)) {
                DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n",
                          mode_cmd->pitches[0],