[3/4] drm/i915: Add format modifiers for Intel

Submitted by Ben Widawsky on June 23, 2017, 4:45 p.m.

Details

Message ID 20170623164544.7362-4-ben@bwidawsk.net
State New
Headers show
Series "Blobifiers (FKA GET_PLANE2)" ( rev: 2 1 ) in Intel GFX

Not browsing as part of any series.

Commit Message

Ben Widawsky June 23, 2017, 4:45 p.m.
This was based on a patch originally by Kristian. It has been modified
pretty heavily to use the new callbacks from the previous patch.

v2:
  - Add LINEAR and Yf modifiers to list (Ville)
  - Combine i8xx and i965 into one list of formats (Ville)
  - Allow 1010102 formats for Y/Yf tiled (Ville)

v3:
  - Handle cursor formats (Ville)
  - Put handling for LINEAR in the mod_support functions (Ville)

v4:
  - List each modifier explicitly in supported modifiers (Ville)
  - Handle the CURSOR plane (Ville)

v5:
  - Split out cursor and sprite handling (Ville)

v6:
  - Actually use the sprite funcs (Emil)
  - Use unreachable (Emil)

v7:
  - Only allow Intel modifiers and LINEAR (Ben)

v8
  - Fix spite assert introduced in v6 (Daniel)

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Kristian H. Kristensen <hoegsberg@gmail.com>
Cc: Emil Velikov <emil.l.velikov@gmail.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_display.c | 136 +++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_sprite.c  |  82 ++++++++++++++++++++-
 2 files changed, 211 insertions(+), 7 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7d55c5e3df28..877a51514c61 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -72,6 +72,12 @@  static const uint32_t i965_primary_formats[] = {
 	DRM_FORMAT_XBGR2101010,
 };
 
+static const uint64_t i9xx_format_modifiers[] = {
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
 static const uint32_t skl_primary_formats[] = {
 	DRM_FORMAT_C8,
 	DRM_FORMAT_RGB565,
@@ -87,11 +93,24 @@  static const uint32_t skl_primary_formats[] = {
 	DRM_FORMAT_VYUY,
 };
 
+static const uint64_t skl_format_modifiers[] = {
+	I915_FORMAT_MOD_Yf_TILED,
+	I915_FORMAT_MOD_Y_TILED,
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
 /* Cursor formats */
 static const uint32_t intel_cursor_formats[] = {
 	DRM_FORMAT_ARGB8888,
 };
 
+static const uint64_t cursor_format_modifiers[] = {
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
 static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
 				struct intel_crtc_state *pipe_config);
 static void ironlake_pch_clock_get(struct intel_crtc *crtc,
@@ -13810,6 +13829,108 @@  void intel_plane_destroy(struct drm_plane *plane)
 	kfree(to_intel_plane(plane));
 }
 
+static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
+{
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_XRGB8888:
+		return modifier == DRM_FORMAT_MOD_LINEAR ||
+			modifier == I915_FORMAT_MOD_X_TILED;
+	default:
+		return false;
+	}
+}
+
+static bool i965_mod_supported(uint32_t format, uint64_t modifier)
+{
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+		return modifier == DRM_FORMAT_MOD_LINEAR ||
+			modifier == I915_FORMAT_MOD_X_TILED;
+	default:
+		return false;
+	}
+}
+
+static bool skl_mod_supported(uint32_t format, uint64_t modifier)
+{
+	switch (format) {
+	case DRM_FORMAT_C8:
+		switch (modifier) {
+		case DRM_FORMAT_MOD_LINEAR:
+		case I915_FORMAT_MOD_X_TILED:
+		case I915_FORMAT_MOD_Y_TILED:
+			return true;
+		default:
+			return false;
+		}
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+		/* All i915 modifiers are fine */
+		switch (modifier) {
+		case DRM_FORMAT_MOD_LINEAR:
+		case I915_FORMAT_MOD_X_TILED:
+		case I915_FORMAT_MOD_Y_TILED:
+		case I915_FORMAT_MOD_Yf_TILED:
+			return true;
+		default:
+			return false;
+		}
+	default:
+		return false;
+	}
+}
+
+static bool intel_primary_plane_format_mod_supported(struct drm_plane *plane,
+						     uint32_t format,
+						     uint64_t modifier)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->dev);
+
+	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
+		return false;
+
+	if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL &&
+	    modifier != DRM_FORMAT_MOD_LINEAR)
+		return false;
+
+
+	if (INTEL_GEN(dev_priv) >= 9)
+		return skl_mod_supported(format, modifier);
+	else if (INTEL_GEN(dev_priv) >= 4)
+		return i965_mod_supported(format, modifier);
+	else
+		return i8xx_mod_supported(format, modifier);
+
+	unreachable();
+}
+
+static bool intel_cursor_plane_format_mod_supported(struct drm_plane *plane,
+						    uint32_t format,
+						    uint64_t modifier)
+{
+	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
+		return false;
+
+	return modifier == DRM_FORMAT_MOD_LINEAR && format == DRM_FORMAT_ARGB8888;
+}
+
 const struct drm_plane_funcs intel_plane_funcs = {
 	.update_plane = drm_atomic_helper_update_plane,
 	.disable_plane = drm_atomic_helper_disable_plane,
@@ -13819,6 +13940,7 @@  const struct drm_plane_funcs intel_plane_funcs = {
 	.atomic_set_property = intel_plane_atomic_set_property,
 	.atomic_duplicate_state = intel_plane_duplicate_state,
 	.atomic_destroy_state = intel_plane_destroy_state,
+	.format_mod_supported = intel_primary_plane_format_mod_supported,
 };
 
 static int
@@ -13954,6 +14076,7 @@  static const struct drm_plane_funcs intel_cursor_plane_funcs = {
 	.atomic_set_property = intel_plane_atomic_set_property,
 	.atomic_duplicate_state = intel_plane_duplicate_state,
 	.atomic_destroy_state = intel_plane_destroy_state,
+	.format_mod_supported = intel_cursor_plane_format_mod_supported,
 };
 
 static struct intel_plane *
@@ -13964,6 +14087,7 @@  intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 	const uint32_t *intel_primary_formats;
 	unsigned int supported_rotations;
 	unsigned int num_formats;
+	const uint64_t *intel_format_modifiers;
 	int ret;
 
 	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
@@ -14002,18 +14126,21 @@  intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 	if (INTEL_GEN(dev_priv) >= 9) {
 		intel_primary_formats = skl_primary_formats;
 		num_formats = ARRAY_SIZE(skl_primary_formats);
+		intel_format_modifiers = skl_format_modifiers;
 
 		primary->update_plane = skylake_update_primary_plane;
 		primary->disable_plane = skylake_disable_primary_plane;
 	} else if (INTEL_GEN(dev_priv) >= 4) {
 		intel_primary_formats = i965_primary_formats;
 		num_formats = ARRAY_SIZE(i965_primary_formats);
+		intel_format_modifiers = i9xx_format_modifiers;
 
 		primary->update_plane = i9xx_update_primary_plane;
 		primary->disable_plane = i9xx_disable_primary_plane;
 	} else {
 		intel_primary_formats = i8xx_primary_formats;
 		num_formats = ARRAY_SIZE(i8xx_primary_formats);
+		intel_format_modifiers = i9xx_format_modifiers;
 
 		primary->update_plane = i9xx_update_primary_plane;
 		primary->disable_plane = i9xx_disable_primary_plane;
@@ -14023,21 +14150,21 @@  intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
-					       NULL,
+					       intel_format_modifiers,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "plane 1%c", pipe_name(pipe));
 	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
-					       NULL,
+					       intel_format_modifiers,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "primary %c", pipe_name(pipe));
 	else
 		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
 					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
-					       NULL,
+					       intel_format_modifiers,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "plane %c", plane_name(primary->plane));
 	if (ret)
@@ -14123,7 +14250,8 @@  intel_cursor_plane_create(struct drm_i915_private *dev_priv,
 				       0, &intel_cursor_plane_funcs,
 				       intel_cursor_formats,
 				       ARRAY_SIZE(intel_cursor_formats),
-				       NULL, DRM_PLANE_TYPE_CURSOR,
+				       cursor_format_modifiers,
+				       DRM_PLANE_TYPE_CURSOR,
 				       "cursor %c", pipe_name(pipe));
 	if (ret)
 		goto fail;
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 15bb43787eb5..e80834cb1f4c 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -30,6 +30,7 @@ 
  * support.
  */
 #include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_rect.h>
@@ -1043,6 +1044,12 @@  static const uint32_t g4x_plane_formats[] = {
 	DRM_FORMAT_VYUY,
 };
 
+static const uint64_t i9xx_plane_format_modifiers[] = {
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
 static const uint32_t snb_plane_formats[] = {
 	DRM_FORMAT_XBGR8888,
 	DRM_FORMAT_XRGB8888,
@@ -1078,6 +1085,68 @@  static uint32_t skl_plane_formats[] = {
 	DRM_FORMAT_VYUY,
 };
 
+static const uint64_t skl_plane_format_modifiers[] = {
+	I915_FORMAT_MOD_Yf_TILED,
+	I915_FORMAT_MOD_Y_TILED,
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
+static bool intel_sprite_plane_format_mod_supported(struct drm_plane *plane,
+                                                    uint32_t format,
+                                                    uint64_t modifier)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->dev);
+
+	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
+		return false;
+
+	BUG_ON(plane->type != DRM_PLANE_TYPE_OVERLAY);
+
+	if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL &&
+	    modifier != DRM_FORMAT_MOD_LINEAR)
+		return false;
+
+	switch (format) {
+		case DRM_FORMAT_XBGR2101010:
+		case DRM_FORMAT_ABGR2101010:
+			if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+				return true;
+			break;
+		case DRM_FORMAT_RGB565:
+		case DRM_FORMAT_ABGR8888:
+		case DRM_FORMAT_ARGB8888:
+			if (INTEL_GEN(dev_priv) >= 9 || IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+				return true;
+			break;
+		case DRM_FORMAT_XBGR8888:
+			if (INTEL_GEN(dev_priv) >= 6)
+				return true;
+			break;
+		case DRM_FORMAT_XRGB8888:
+		case DRM_FORMAT_YUYV:
+		case DRM_FORMAT_YVYU:
+		case DRM_FORMAT_UYVY:
+		case DRM_FORMAT_VYUY:
+			return true;
+	}
+
+	return false;
+}
+
+const struct drm_plane_funcs intel_sprite_plane_funcs = {
+        .update_plane = drm_atomic_helper_update_plane,
+        .disable_plane = drm_atomic_helper_disable_plane,
+        .destroy = intel_plane_destroy,
+        .set_property = drm_atomic_helper_plane_set_property,
+        .atomic_get_property = intel_plane_atomic_get_property,
+        .atomic_set_property = intel_plane_atomic_set_property,
+        .atomic_duplicate_state = intel_plane_duplicate_state,
+        .atomic_destroy_state = intel_plane_destroy_state,
+        .format_mod_supported = intel_sprite_plane_format_mod_supported,
+};
+
 struct intel_plane *
 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 			  enum pipe pipe, int plane)
@@ -1086,6 +1155,7 @@  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 	struct intel_plane_state *state = NULL;
 	unsigned long possible_crtcs;
 	const uint32_t *plane_formats;
+	const uint64_t *modifiers;
 	unsigned int supported_rotations;
 	int num_plane_formats;
 	int ret;
@@ -1112,6 +1182,7 @@  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
 		plane_formats = skl_plane_formats;
 		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
+		modifiers = skl_plane_format_modifiers;
 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		intel_plane->can_scale = false;
 		intel_plane->max_downscale = 1;
@@ -1121,6 +1192,7 @@  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
 		plane_formats = vlv_plane_formats;
 		num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
+		modifiers = i9xx_plane_format_modifiers;
 	} else if (INTEL_GEN(dev_priv) >= 7) {
 		if (IS_IVYBRIDGE(dev_priv)) {
 			intel_plane->can_scale = true;
@@ -1135,6 +1207,7 @@  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
 		plane_formats = snb_plane_formats;
 		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+		modifiers = i9xx_plane_format_modifiers;
 	} else {
 		intel_plane->can_scale = true;
 		intel_plane->max_downscale = 16;
@@ -1142,6 +1215,7 @@  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 		intel_plane->update_plane = g4x_update_plane;
 		intel_plane->disable_plane = g4x_disable_plane;
 
+		modifiers = i9xx_plane_format_modifiers;
 		if (IS_GEN6(dev_priv)) {
 			plane_formats = snb_plane_formats;
 			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
@@ -1174,15 +1248,17 @@  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
 	if (INTEL_GEN(dev_priv) >= 9)
 		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
-					       possible_crtcs, &intel_plane_funcs,
+					       possible_crtcs, &intel_sprite_plane_funcs,
 					       plane_formats, num_plane_formats,
-					       NULL, DRM_PLANE_TYPE_OVERLAY,
+					       modifiers,
+					       DRM_PLANE_TYPE_OVERLAY,
 					       "plane %d%c", plane + 2, pipe_name(pipe));
 	else
 		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
 					       possible_crtcs, &intel_plane_funcs,
 					       plane_formats, num_plane_formats,
-					       NULL, DRM_PLANE_TYPE_OVERLAY,
+					       modifiers,
+					       DRM_PLANE_TYPE_OVERLAY,
 					       "sprite %c", sprite_name(pipe, plane));
 	if (ret)
 		goto fail;

Comments

On 23 June 2017 at 17:45, Ben Widawsky <ben@bwidawsk.net> wrote:
> This was based on a patch originally by Kristian. It has been modified
> pretty heavily to use the new callbacks from the previous patch.
>
> v2:
>   - Add LINEAR and Yf modifiers to list (Ville)
>   - Combine i8xx and i965 into one list of formats (Ville)
>   - Allow 1010102 formats for Y/Yf tiled (Ville)
>
> v3:
>   - Handle cursor formats (Ville)
>   - Put handling for LINEAR in the mod_support functions (Ville)
>
> v4:
>   - List each modifier explicitly in supported modifiers (Ville)
>   - Handle the CURSOR plane (Ville)
>
> v5:
>   - Split out cursor and sprite handling (Ville)
>
> v6:
>   - Actually use the sprite funcs (Emil)
>   - Use unreachable (Emil)
>
> v7:
>   - Only allow Intel modifiers and LINEAR (Ben)
>
> v8
>   - Fix spite assert introduced in v6 (Daniel)
>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Kristian H. Kristensen <hoegsberg@gmail.com>
> Cc: Emil Velikov <emil.l.velikov@gmail.com>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 136 +++++++++++++++++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_sprite.c  |  82 ++++++++++++++++++++-
>  2 files changed, 211 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7d55c5e3df28..877a51514c61 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -72,6 +72,12 @@ static const uint32_t i965_primary_formats[] = {
>         DRM_FORMAT_XBGR2101010,
>  };
>
> +static const uint64_t i9xx_format_modifiers[] = {
> +       I915_FORMAT_MOD_X_TILED,
> +       DRM_FORMAT_MOD_LINEAR,
> +       DRM_FORMAT_MOD_INVALID
> +};
> +
>  static const uint32_t skl_primary_formats[] = {
>         DRM_FORMAT_C8,
>         DRM_FORMAT_RGB565,
> @@ -87,11 +93,24 @@ static const uint32_t skl_primary_formats[] = {
>         DRM_FORMAT_VYUY,
>  };
>
> +static const uint64_t skl_format_modifiers[] = {
> +       I915_FORMAT_MOD_Yf_TILED,
> +       I915_FORMAT_MOD_Y_TILED,
> +       I915_FORMAT_MOD_X_TILED,
> +       DRM_FORMAT_MOD_LINEAR,
> +       DRM_FORMAT_MOD_INVALID
> +};
> +
>  /* Cursor formats */
>  static const uint32_t intel_cursor_formats[] = {
>         DRM_FORMAT_ARGB8888,
>  };
>
> +static const uint64_t cursor_format_modifiers[] = {
> +       DRM_FORMAT_MOD_LINEAR,
> +       DRM_FORMAT_MOD_INVALID
> +};
> +
>  static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
>                                 struct intel_crtc_state *pipe_config);
>  static void ironlake_pch_clock_get(struct intel_crtc *crtc,
> @@ -13810,6 +13829,108 @@ void intel_plane_destroy(struct drm_plane *plane)
>         kfree(to_intel_plane(plane));
>  }
>
> +static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
> +{
> +       switch (format) {
> +       case DRM_FORMAT_C8:
> +       case DRM_FORMAT_RGB565:
> +       case DRM_FORMAT_XRGB1555:
> +       case DRM_FORMAT_XRGB8888:
> +               return modifier == DRM_FORMAT_MOD_LINEAR ||
> +                       modifier == I915_FORMAT_MOD_X_TILED;
> +       default:
> +               return false;
> +       }
> +}
> +
> +static bool i965_mod_supported(uint32_t format, uint64_t modifier)
> +{
> +       switch (format) {
> +       case DRM_FORMAT_C8:
> +       case DRM_FORMAT_RGB565:
> +       case DRM_FORMAT_XRGB8888:
> +       case DRM_FORMAT_XBGR8888:
> +       case DRM_FORMAT_XRGB2101010:
> +       case DRM_FORMAT_XBGR2101010:
> +               return modifier == DRM_FORMAT_MOD_LINEAR ||
> +                       modifier == I915_FORMAT_MOD_X_TILED;
> +       default:
> +               return false;
> +       }
> +}
> +
> +static bool skl_mod_supported(uint32_t format, uint64_t modifier)
> +{
> +       switch (format) {
> +       case DRM_FORMAT_C8:
> +               switch (modifier) {
> +               case DRM_FORMAT_MOD_LINEAR:
> +               case I915_FORMAT_MOD_X_TILED:
> +               case I915_FORMAT_MOD_Y_TILED:
> +                       return true;
> +               default:
> +                       return false;
> +               }
> +       case DRM_FORMAT_RGB565:
> +       case DRM_FORMAT_XRGB8888:
> +       case DRM_FORMAT_XBGR8888:
> +       case DRM_FORMAT_ARGB8888:
> +       case DRM_FORMAT_ABGR8888:
> +       case DRM_FORMAT_XRGB2101010:
> +       case DRM_FORMAT_XBGR2101010:
> +       case DRM_FORMAT_YUYV:
> +       case DRM_FORMAT_YVYU:
> +       case DRM_FORMAT_UYVY:
> +       case DRM_FORMAT_VYUY:
> +               /* All i915 modifiers are fine */
> +               switch (modifier) {
> +               case DRM_FORMAT_MOD_LINEAR:
> +               case I915_FORMAT_MOD_X_TILED:
> +               case I915_FORMAT_MOD_Y_TILED:
> +               case I915_FORMAT_MOD_Yf_TILED:
> +                       return true;
> +               default:
> +                       return false;
> +               }
> +       default:
> +               return false;
> +       }
> +}
> +
> +static bool intel_primary_plane_format_mod_supported(struct drm_plane *plane,
> +                                                    uint32_t format,
> +                                                    uint64_t modifier)
> +{
> +       struct drm_i915_private *dev_priv = to_i915(plane->dev);
> +
> +       if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
> +               return false;
> +
> +       if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL &&
Using ">> 56" seem a bit magical. Alternative solution is to introduce
DRM_FORMAT_MOD_VENDOR_MASK or even
"if (!(modifier & DRM_FORMAT_MOD_VENDOR_INTEL) ..."

Regardless, patch looks good and is
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>

-Emil
On Fri, Jun 23, 2017 at 09:45:43AM -0700, Ben Widawsky wrote:
> This was based on a patch originally by Kristian. It has been modified
> pretty heavily to use the new callbacks from the previous patch.
> 
> v2:
>   - Add LINEAR and Yf modifiers to list (Ville)
>   - Combine i8xx and i965 into one list of formats (Ville)
>   - Allow 1010102 formats for Y/Yf tiled (Ville)
> 
> v3:
>   - Handle cursor formats (Ville)
>   - Put handling for LINEAR in the mod_support functions (Ville)
> 
> v4:
>   - List each modifier explicitly in supported modifiers (Ville)
>   - Handle the CURSOR plane (Ville)
> 
> v5:
>   - Split out cursor and sprite handling (Ville)
> 
> v6:
>   - Actually use the sprite funcs (Emil)
>   - Use unreachable (Emil)
> 
> v7:
>   - Only allow Intel modifiers and LINEAR (Ben)
> 
> v8
>   - Fix spite assert introduced in v6 (Daniel)
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Kristian H. Kristensen <hoegsberg@gmail.com>
> Cc: Emil Velikov <emil.l.velikov@gmail.com>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 136 +++++++++++++++++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_sprite.c  |  82 ++++++++++++++++++++-
>  2 files changed, 211 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7d55c5e3df28..877a51514c61 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -72,6 +72,12 @@ static const uint32_t i965_primary_formats[] = {
>  	DRM_FORMAT_XBGR2101010,
>  };
>  
> +static const uint64_t i9xx_format_modifiers[] = {
> +	I915_FORMAT_MOD_X_TILED,
> +	DRM_FORMAT_MOD_LINEAR,
> +	DRM_FORMAT_MOD_INVALID
> +};
> +
>  static const uint32_t skl_primary_formats[] = {
>  	DRM_FORMAT_C8,
>  	DRM_FORMAT_RGB565,
> @@ -87,11 +93,24 @@ static const uint32_t skl_primary_formats[] = {
>  	DRM_FORMAT_VYUY,
>  };
>  
> +static const uint64_t skl_format_modifiers[] = {
> +	I915_FORMAT_MOD_Yf_TILED,
> +	I915_FORMAT_MOD_Y_TILED,
> +	I915_FORMAT_MOD_X_TILED,
> +	DRM_FORMAT_MOD_LINEAR,
> +	DRM_FORMAT_MOD_INVALID
> +};
> +
>  /* Cursor formats */
>  static const uint32_t intel_cursor_formats[] = {
>  	DRM_FORMAT_ARGB8888,
>  };
>  
> +static const uint64_t cursor_format_modifiers[] = {
> +	DRM_FORMAT_MOD_LINEAR,
> +	DRM_FORMAT_MOD_INVALID
> +};
> +
>  static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
>  				struct intel_crtc_state *pipe_config);
>  static void ironlake_pch_clock_get(struct intel_crtc *crtc,
> @@ -13810,6 +13829,108 @@ void intel_plane_destroy(struct drm_plane *plane)
>  	kfree(to_intel_plane(plane));
>  }
>  
> +static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
> +{
> +	switch (format) {
> +	case DRM_FORMAT_C8:
> +	case DRM_FORMAT_RGB565:
> +	case DRM_FORMAT_XRGB1555:
> +	case DRM_FORMAT_XRGB8888:
> +		return modifier == DRM_FORMAT_MOD_LINEAR ||
> +			modifier == I915_FORMAT_MOD_X_TILED;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool i965_mod_supported(uint32_t format, uint64_t modifier)
> +{
> +	switch (format) {
> +	case DRM_FORMAT_C8:
> +	case DRM_FORMAT_RGB565:
> +	case DRM_FORMAT_XRGB8888:
> +	case DRM_FORMAT_XBGR8888:
> +	case DRM_FORMAT_XRGB2101010:
> +	case DRM_FORMAT_XBGR2101010:
> +		return modifier == DRM_FORMAT_MOD_LINEAR ||
> +			modifier == I915_FORMAT_MOD_X_TILED;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool skl_mod_supported(uint32_t format, uint64_t modifier)
> +{
> +	switch (format) {
> +	case DRM_FORMAT_C8:
> +		switch (modifier) {
> +		case DRM_FORMAT_MOD_LINEAR:
> +		case I915_FORMAT_MOD_X_TILED:
> +		case I915_FORMAT_MOD_Y_TILED:
> +			return true;
> +		default:
> +			return false;
> +		}
> +	case DRM_FORMAT_RGB565:
> +	case DRM_FORMAT_XRGB8888:
> +	case DRM_FORMAT_XBGR8888:
> +	case DRM_FORMAT_ARGB8888:
> +	case DRM_FORMAT_ABGR8888:
> +	case DRM_FORMAT_XRGB2101010:
> +	case DRM_FORMAT_XBGR2101010:
> +	case DRM_FORMAT_YUYV:
> +	case DRM_FORMAT_YVYU:
> +	case DRM_FORMAT_UYVY:
> +	case DRM_FORMAT_VYUY:
> +		/* All i915 modifiers are fine */
> +		switch (modifier) {
> +		case DRM_FORMAT_MOD_LINEAR:
> +		case I915_FORMAT_MOD_X_TILED:
> +		case I915_FORMAT_MOD_Y_TILED:
> +		case I915_FORMAT_MOD_Yf_TILED:
> +			return true;
> +		default:
> +			return false;
> +		}
> +	default:
> +		return false;
> +	}
> +}

I think I might bikeshed that as 

skl_mod_supported()
{
	switch (format) {
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_ARGB8888:
	case DRM_FORMAT_ABGR8888:
	case DRM_FORMAT_RGB565:
	case DRM_FORMAT_XRGB2101010:
	case DRM_FORMAT_XBGR2101010:
	case DRM_FORMAT_YUYV:
	case DRM_FORMAT_YVYU:
	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_VYUY:
		if (modifier == I915_FORMAT_MOD_Yf_TILED)
			return true;
		/* fall through */
	case DRM_FORMAT_C8:
		if (modifier == DRM_FORMAT_MOD_LINEAR ||
		    modifier == I915_FORMAT_MOD_X_TILED ||
		    modifier == I915_FORMAT_MOD_Y_TILED)
			return true;
		/* fall through */
	default:
		return false;
	}
}

The CCS modifiers should then slide in very neatly after the 8888
formats.

> +
> +static bool intel_primary_plane_format_mod_supported(struct drm_plane *plane,
> +						     uint32_t format,
> +						     uint64_t modifier)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(plane->dev);
> +
> +	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
> +		return false;
> +
> +	if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL &&
> +	    modifier != DRM_FORMAT_MOD_LINEAR)
> +		return false;
> +
> +
> +	if (INTEL_GEN(dev_priv) >= 9)
> +		return skl_mod_supported(format, modifier);
> +	else if (INTEL_GEN(dev_priv) >= 4)
> +		return i965_mod_supported(format, modifier);
> +	else
> +		return i8xx_mod_supported(format, modifier);
> +
> +	unreachable();
> +}
> +
> +static bool intel_cursor_plane_format_mod_supported(struct drm_plane *plane,
> +						    uint32_t format,
> +						    uint64_t modifier)
> +{
> +	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
> +		return false;
> +
> +	return modifier == DRM_FORMAT_MOD_LINEAR && format == DRM_FORMAT_ARGB8888;
> +}
> +
>  const struct drm_plane_funcs intel_plane_funcs = {

That can be made static now. And maybe rename to intel_primary_plane_funcs.

>  	.update_plane = drm_atomic_helper_update_plane,
>  	.disable_plane = drm_atomic_helper_disable_plane,
> @@ -13819,6 +13940,7 @@ const struct drm_plane_funcs intel_plane_funcs = {
>  	.atomic_set_property = intel_plane_atomic_set_property,
>  	.atomic_duplicate_state = intel_plane_duplicate_state,
>  	.atomic_destroy_state = intel_plane_destroy_state,
> +	.format_mod_supported = intel_primary_plane_format_mod_supported,
>  };
>  
>  static int
> @@ -13954,6 +14076,7 @@ static const struct drm_plane_funcs intel_cursor_plane_funcs = {
>  	.atomic_set_property = intel_plane_atomic_set_property,
>  	.atomic_duplicate_state = intel_plane_duplicate_state,
>  	.atomic_destroy_state = intel_plane_destroy_state,
> +	.format_mod_supported = intel_cursor_plane_format_mod_supported,
>  };
>  
>  static struct intel_plane *
> @@ -13964,6 +14087,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>  	const uint32_t *intel_primary_formats;
>  	unsigned int supported_rotations;
>  	unsigned int num_formats;
> +	const uint64_t *intel_format_modifiers;

Just 'modifiers' or 'format_modifiers' seems sufficient.

>  	int ret;
>  
>  	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> @@ -14002,18 +14126,21 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>  	if (INTEL_GEN(dev_priv) >= 9) {
>  		intel_primary_formats = skl_primary_formats;
>  		num_formats = ARRAY_SIZE(skl_primary_formats);
> +		intel_format_modifiers = skl_format_modifiers;
>  
>  		primary->update_plane = skylake_update_primary_plane;
>  		primary->disable_plane = skylake_disable_primary_plane;
>  	} else if (INTEL_GEN(dev_priv) >= 4) {
>  		intel_primary_formats = i965_primary_formats;
>  		num_formats = ARRAY_SIZE(i965_primary_formats);
> +		intel_format_modifiers = i9xx_format_modifiers;
>  
>  		primary->update_plane = i9xx_update_primary_plane;
>  		primary->disable_plane = i9xx_disable_primary_plane;
>  	} else {
>  		intel_primary_formats = i8xx_primary_formats;
>  		num_formats = ARRAY_SIZE(i8xx_primary_formats);
> +		intel_format_modifiers = i9xx_format_modifiers;
>  
>  		primary->update_plane = i9xx_update_primary_plane;
>  		primary->disable_plane = i9xx_disable_primary_plane;
> @@ -14023,21 +14150,21 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>  					       0, &intel_plane_funcs,
>  					       intel_primary_formats, num_formats,
> -					       NULL,
> +					       intel_format_modifiers,
>  					       DRM_PLANE_TYPE_PRIMARY,
>  					       "plane 1%c", pipe_name(pipe));
>  	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>  					       0, &intel_plane_funcs,
>  					       intel_primary_formats, num_formats,
> -					       NULL,
> +					       intel_format_modifiers,
>  					       DRM_PLANE_TYPE_PRIMARY,
>  					       "primary %c", pipe_name(pipe));
>  	else
>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>  					       0, &intel_plane_funcs,
>  					       intel_primary_formats, num_formats,
> -					       NULL,
> +					       intel_format_modifiers,
>  					       DRM_PLANE_TYPE_PRIMARY,
>  					       "plane %c", plane_name(primary->plane));
>  	if (ret)
> @@ -14123,7 +14250,8 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
>  				       0, &intel_cursor_plane_funcs,
>  				       intel_cursor_formats,
>  				       ARRAY_SIZE(intel_cursor_formats),
> -				       NULL, DRM_PLANE_TYPE_CURSOR,
> +				       cursor_format_modifiers,
> +				       DRM_PLANE_TYPE_CURSOR,
>  				       "cursor %c", pipe_name(pipe));
>  	if (ret)
>  		goto fail;
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 15bb43787eb5..e80834cb1f4c 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -30,6 +30,7 @@
>   * support.
>   */
>  #include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_fourcc.h>
>  #include <drm/drm_rect.h>
> @@ -1043,6 +1044,12 @@ static const uint32_t g4x_plane_formats[] = {
>  	DRM_FORMAT_VYUY,
>  };
>  
> +static const uint64_t i9xx_plane_format_modifiers[] = {
> +	I915_FORMAT_MOD_X_TILED,
> +	DRM_FORMAT_MOD_LINEAR,
> +	DRM_FORMAT_MOD_INVALID
> +};
> +
>  static const uint32_t snb_plane_formats[] = {
>  	DRM_FORMAT_XBGR8888,
>  	DRM_FORMAT_XRGB8888,
> @@ -1078,6 +1085,68 @@ static uint32_t skl_plane_formats[] = {
>  	DRM_FORMAT_VYUY,
>  };
>  
> +static const uint64_t skl_plane_format_modifiers[] = {
> +	I915_FORMAT_MOD_Yf_TILED,
> +	I915_FORMAT_MOD_Y_TILED,
> +	I915_FORMAT_MOD_X_TILED,
> +	DRM_FORMAT_MOD_LINEAR,
> +	DRM_FORMAT_MOD_INVALID
> +};
> +
> +static bool intel_sprite_plane_format_mod_supported(struct drm_plane *plane,
> +                                                    uint32_t format,
> +                                                    uint64_t modifier)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(plane->dev);
> +
> +	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
> +		return false;
> +
> +	BUG_ON(plane->type != DRM_PLANE_TYPE_OVERLAY);
> +
> +	if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL &&
> +	    modifier != DRM_FORMAT_MOD_LINEAR)
> +		return false;
> +
> +	switch (format) {
> +		case DRM_FORMAT_XBGR2101010:
> +		case DRM_FORMAT_ABGR2101010:
> +			if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +				return true;
> +			break;
> +		case DRM_FORMAT_RGB565:
> +		case DRM_FORMAT_ABGR8888:
> +		case DRM_FORMAT_ARGB8888:
> +			if (INTEL_GEN(dev_priv) >= 9 || IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +				return true;
> +			break;
> +		case DRM_FORMAT_XBGR8888:
> +			if (INTEL_GEN(dev_priv) >= 6)
> +				return true;
> +			break;
> +		case DRM_FORMAT_XRGB8888:
> +		case DRM_FORMAT_YUYV:
> +		case DRM_FORMAT_YVYU:
> +		case DRM_FORMAT_UYVY:
> +		case DRM_FORMAT_VYUY:
> +			return true;
> +	}
> +
> +	return false;
> +}

This looks quite alien compared to the primary plane code. Rather
hard to parse, and it doesn't actually check the modifiers per
format like the primary plane and cursor code does.

So I'd split it up into g4x,snb,vlb,skl variants just like the
primary plane code does.

> +
> +const struct drm_plane_funcs intel_sprite_plane_funcs = {

static

> +        .update_plane = drm_atomic_helper_update_plane,
> +        .disable_plane = drm_atomic_helper_disable_plane,
> +        .destroy = intel_plane_destroy,
> +        .set_property = drm_atomic_helper_plane_set_property,
> +        .atomic_get_property = intel_plane_atomic_get_property,
> +        .atomic_set_property = intel_plane_atomic_set_property,
> +        .atomic_duplicate_state = intel_plane_duplicate_state,
> +        .atomic_destroy_state = intel_plane_destroy_state,
> +        .format_mod_supported = intel_sprite_plane_format_mod_supported,
> +};
> +
>  struct intel_plane *
>  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  			  enum pipe pipe, int plane)
> @@ -1086,6 +1155,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  	struct intel_plane_state *state = NULL;
>  	unsigned long possible_crtcs;
>  	const uint32_t *plane_formats;
> +	const uint64_t *modifiers;
>  	unsigned int supported_rotations;
>  	int num_plane_formats;
>  	int ret;
> @@ -1112,6 +1182,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  
>  		plane_formats = skl_plane_formats;
>  		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
> +		modifiers = skl_plane_format_modifiers;
>  	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
>  		intel_plane->can_scale = false;
>  		intel_plane->max_downscale = 1;
> @@ -1121,6 +1192,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  
>  		plane_formats = vlv_plane_formats;
>  		num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
> +		modifiers = i9xx_plane_format_modifiers;
>  	} else if (INTEL_GEN(dev_priv) >= 7) {
>  		if (IS_IVYBRIDGE(dev_priv)) {
>  			intel_plane->can_scale = true;
> @@ -1135,6 +1207,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  
>  		plane_formats = snb_plane_formats;
>  		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
> +		modifiers = i9xx_plane_format_modifiers;
>  	} else {
>  		intel_plane->can_scale = true;
>  		intel_plane->max_downscale = 16;
> @@ -1142,6 +1215,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  		intel_plane->update_plane = g4x_update_plane;
>  		intel_plane->disable_plane = g4x_disable_plane;
>  
> +		modifiers = i9xx_plane_format_modifiers;
>  		if (IS_GEN6(dev_priv)) {
>  			plane_formats = snb_plane_formats;
>  			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
> @@ -1174,15 +1248,17 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>  
>  	if (INTEL_GEN(dev_priv) >= 9)
>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
> -					       possible_crtcs, &intel_plane_funcs,
> +					       possible_crtcs, &intel_sprite_plane_funcs,
>  					       plane_formats, num_plane_formats,
> -					       NULL, DRM_PLANE_TYPE_OVERLAY,
> +					       modifiers,
> +					       DRM_PLANE_TYPE_OVERLAY,
>  					       "plane %d%c", plane + 2, pipe_name(pipe));
>  	else
>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
>  					       possible_crtcs, &intel_plane_funcs,

sprite_plane_funcs

>  					       plane_formats, num_plane_formats,
> -					       NULL, DRM_PLANE_TYPE_OVERLAY,
> +					       modifiers,
> +					       DRM_PLANE_TYPE_OVERLAY,
>  					       "sprite %c", sprite_name(pipe, plane));
>  	if (ret)
>  		goto fail;
> -- 
> 2.13.1