|
@@ -1175,6 +1175,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)
|
|
|
{
|
|
@@ -1204,6 +1235,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);
|
|
@@ -1216,11 +1257,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;
|
|
|
|