Merge tag 'drm-intel-next-2018-06-20' of git://anongit.freedesktop.org/drm/drm-intel...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / i915 / intel_sprite.c
index 1160bc3a1e8e445909baf89ac3e4d326312cb984..344c0e709b19ac5f73905cbc4265b57796a8522a 100644 (file)
@@ -1101,6 +1101,37 @@ intel_check_sprite_plane(struct intel_plane *plane,
        return 0;
 }
 
+static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
+{
+       return INTEL_GEN(dev_priv) >= 9;
+}
+
+static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
+                                const struct drm_intel_sprite_colorkey *set)
+{
+       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
+
+       *key = *set;
+
+       /*
+        * We want src key enabled on the
+        * sprite and not on the primary.
+        */
+       if (plane->id == PLANE_PRIMARY &&
+           set->flags & I915_SET_COLORKEY_SOURCE)
+               key->flags = 0;
+
+       /*
+        * On SKL+ we want dst key enabled on
+        * the primary and not on the sprite.
+        */
+       if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
+           set->flags & I915_SET_COLORKEY_DESTINATION)
+               key->flags = 0;
+}
+
 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
                                    struct drm_file *file_priv)
 {
@@ -1130,6 +1161,16 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
        if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
                return -ENOENT;
 
+       /*
+        * SKL+ only plane 2 can do destination keying against plane 1.
+        * Also multiple planes can't do destination keying on the same
+        * pipe simultaneously.
+        */
+       if (INTEL_GEN(dev_priv) >= 9 &&
+           to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
+           set->flags & I915_SET_COLORKEY_DESTINATION)
+               return -EINVAL;
+
        drm_modeset_acquire_init(&ctx, 0);
 
        state = drm_atomic_state_alloc(plane->dev);
@@ -1142,11 +1183,28 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
        while (1) {
                plane_state = drm_atomic_get_plane_state(state, plane);
                ret = PTR_ERR_OR_ZERO(plane_state);
-               if (!ret) {
-                       to_intel_plane_state(plane_state)->ckey = *set;
-                       ret = drm_atomic_commit(state);
+               if (!ret)
+                       intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
+
+               /*
+                * On some platforms we have to configure
+                * the dst colorkey on the primary plane.
+                */
+               if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
+                       struct intel_crtc *crtc =
+                               intel_get_crtc_for_pipe(dev_priv,
+                                                       to_intel_plane(plane)->pipe);
+
+                       plane_state = drm_atomic_get_plane_state(state,
+                                                                crtc->base.primary);
+                       ret = PTR_ERR_OR_ZERO(plane_state);
+                       if (!ret)
+                               intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
                }
 
+               if (!ret)
+                       ret = drm_atomic_commit(state);
+
                if (ret != -EDEADLK)
                        break;