Commit e2b83294 authored by Imre Deak's avatar Imre Deak
Browse files

drm/i915: Add a table with a descriptor for all i915 modifiers



Add a table describing all the framebuffer modifiers used by i915 at one
place. This has the benefit of deduplicating the listing of supported
modifiers for each platform and checking the support of these modifiers
on a given plane. This also simplifies in a similar way getting some
attribute for a modifier, for instance checking if the modifier is a
CCS modifier type.

While at it drop the cursor plane filtering from skl_plane_has_rc_ccs(),
as the cursor plane is registered with DRM core elsewhere.

v1: Unchanged.
v2:
- Keep the plane caps calculation in the plane code and pass an enum
  with these caps to intel_fb_get_modifiers(). (Ville)
- Get the modifiers calling intel_fb_get_modifiers() in i9xx_plane.c as
  well.
v3:
- s/.id/.modifier/ (Ville)
- Keep modifier_desc vs. plane_cap filter conditions consistent. (Ville)
- Drop redundant cursor plane check from skl_plane_has_rc_ccs(). (Ville)
- Use from, until display version fields in modifier_desc instead of a mask. (Jani)
- Unexport struct intel_modifier_desc, separate its decl and init. (Jani)
- Remove enum pipe, plane_id forward decls from intel_fb.h, which are
  not needed after v2.
v4:
- Reuse IS_DISPLAY_VER() instead of open-coding it. (Jani)
- Preserve the current modifier order exposed to user space. (Ville)
v5: Use }, { on one line to seperate the descriptor array elements. (Jani)

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarImre Deak <imre.deak@intel.com>
Reviewed-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com> (v3)
Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-2-imre.deak@intel.com
parent 171c555c
Loading
Loading
Loading
Loading
+10 −20
Original line number Diff line number Diff line
@@ -60,22 +60,11 @@ static const u32 vlv_primary_formats[] = {
	DRM_FORMAT_XBGR16161616F,
};

static const u64 i9xx_format_modifiers[] = {
	I915_FORMAT_MOD_X_TILED,
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
					    u32 format, u64 modifier)
{
	switch (modifier) {
	case DRM_FORMAT_MOD_LINEAR:
	case I915_FORMAT_MOD_X_TILED:
		break;
	default:
	if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
		return false;
	}

	switch (format) {
	case DRM_FORMAT_C8:
@@ -92,13 +81,8 @@ static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
					    u32 format, u64 modifier)
{
	switch (modifier) {
	case DRM_FORMAT_MOD_LINEAR:
	case I915_FORMAT_MOD_X_TILED:
		break;
	default:
	if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
		return false;
	}

	switch (format) {
	case DRM_FORMAT_C8:
@@ -768,6 +752,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
	struct intel_plane *plane;
	const struct drm_plane_funcs *plane_funcs;
	unsigned int supported_rotations;
	const u64 *modifiers;
	const u32 *formats;
	int num_formats;
	int ret, zpos;
@@ -875,21 +860,26 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
		plane->disable_flip_done = ilk_primary_disable_flip_done;
	}

	modifiers = intel_fb_plane_get_modifiers(dev_priv, PLANE_HAS_TILING);

	if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
					       0, plane_funcs,
					       formats, num_formats,
					       i9xx_format_modifiers,
					       modifiers,
					       DRM_PLANE_TYPE_PRIMARY,
					       "primary %c", pipe_name(pipe));
	else
		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
					       0, plane_funcs,
					       formats, num_formats,
					       i9xx_format_modifiers,
					       modifiers,
					       DRM_PLANE_TYPE_PRIMARY,
					       "plane %c",
					       plane_name(plane->i9xx_plane));

	kfree(modifiers);

	if (ret)
		goto fail;

+11 −8
Original line number Diff line number Diff line
@@ -28,11 +28,6 @@ static const u32 intel_cursor_formats[] = {
	DRM_FORMAT_ARGB8888,
};

static const u64 cursor_format_modifiers[] = {
	DRM_FORMAT_MOD_LINEAR,
	DRM_FORMAT_MOD_INVALID
};

static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
{
	struct drm_i915_private *dev_priv =
@@ -605,8 +600,10 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
					      u32 format, u64 modifier)
{
	return modifier == DRM_FORMAT_MOD_LINEAR &&
		format == DRM_FORMAT_ARGB8888;
	if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
		return false;

	return format == DRM_FORMAT_ARGB8888;
}

static int
@@ -754,6 +751,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
{
	struct intel_plane *cursor;
	int ret, zpos;
	u64 *modifiers;

	cursor = intel_plane_alloc();
	if (IS_ERR(cursor))
@@ -784,13 +782,18 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
	if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
		cursor->cursor.size = ~0;

	modifiers = intel_fb_plane_get_modifiers(dev_priv, PLANE_HAS_NO_CAPS);

	ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
				       0, &intel_cursor_plane_funcs,
				       intel_cursor_formats,
				       ARRAY_SIZE(intel_cursor_formats),
				       cursor_format_modifiers,
				       modifiers,
				       DRM_PLANE_TYPE_CURSOR,
				       "cursor %c", pipe_name(pipe));

	kfree(modifiers);

	if (ret)
		goto fail;

+0 −1
Original line number Diff line number Diff line
@@ -1336,7 +1336,6 @@ struct intel_plane {
	enum plane_id id;
	enum pipe pipe;
	bool has_fbc;
	bool has_ccs;
	bool need_async_flip_disable_wa;
	u32 frontbuffer_bit;

+144 −0
Original line number Diff line number Diff line
@@ -13,6 +13,150 @@

#define check_array_bounds(i915, a, i) drm_WARN_ON(&(i915)->drm, (i) >= ARRAY_SIZE(a))

struct intel_modifier_desc {
	u64 modifier;
	struct {
		u8 from;
		u8 until;
	} display_ver;
#define DISPLAY_VER_ALL		{ 0, -1 }

	u8 is_linear:1;

	struct {
#define INTEL_CCS_RC		BIT(0)
#define INTEL_CCS_RC_CC		BIT(1)
#define INTEL_CCS_MC		BIT(2)

#define INTEL_CCS_ANY		(INTEL_CCS_RC | INTEL_CCS_RC_CC | INTEL_CCS_MC)
		u8 type:3;
	} ccs;
};

static const struct intel_modifier_desc intel_modifiers[] = {
	{
		.modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
		.display_ver = { 12, 13 },

		.ccs.type = INTEL_CCS_MC,
	}, {
		.modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
		.display_ver = { 12, 13 },

		.ccs.type = INTEL_CCS_RC,
	}, {
		.modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
		.display_ver = { 12, 13 },

		.ccs.type = INTEL_CCS_RC_CC,
	}, {
		.modifier = I915_FORMAT_MOD_Yf_TILED_CCS,
		.display_ver = { 9, 11 },

		.ccs.type = INTEL_CCS_RC,
	}, {
		.modifier = I915_FORMAT_MOD_Y_TILED_CCS,
		.display_ver = { 9, 11 },

		.ccs.type = INTEL_CCS_RC,
	}, {
		.modifier = I915_FORMAT_MOD_Yf_TILED,
		.display_ver = { 9, 11 },
	}, {
		.modifier = I915_FORMAT_MOD_Y_TILED,
		.display_ver = { 9, 13 },
	}, {
		.modifier = I915_FORMAT_MOD_X_TILED,
		.display_ver = DISPLAY_VER_ALL,
	}, {
		.modifier = DRM_FORMAT_MOD_LINEAR,
		.display_ver = DISPLAY_VER_ALL,

		.is_linear = true,
	},
};

static bool is_ccs_type_modifier(const struct intel_modifier_desc *md, u8 ccs_type)
{
	return md->ccs.type & ccs_type;
}

static bool plane_has_modifier(struct drm_i915_private *i915,
			       enum intel_plane_caps plane_caps,
			       const struct intel_modifier_desc *md)
{
	if (!IS_DISPLAY_VER(i915, md->display_ver.from, md->display_ver.until))
		return false;

	if (!md->is_linear &&
	    !(plane_caps & PLANE_HAS_TILING))
		return false;

	if (is_ccs_type_modifier(md, INTEL_CCS_RC | INTEL_CCS_RC_CC) &&
	    !(plane_caps & PLANE_HAS_CCS_RC))
		return false;

	if (is_ccs_type_modifier(md, INTEL_CCS_MC) &&
	    !(plane_caps & PLANE_HAS_CCS_MC))
		return false;

	return true;
}

/**
 * intel_fb_plane_get_modifiers: Get the modifiers for the given platform and plane capabilities
 * @i915: i915 device instance
 * @plane_caps: capabilities for the plane the modifiers are queried for
 *
 * Returns:
 * Returns the list of modifiers allowed by the @i915 platform and @plane_caps.
 * The caller must free the returned buffer.
 */
u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915,
				  enum intel_plane_caps plane_caps)
{
	u64 *list, *p;
	int count = 1;		/* +1 for invalid modifier terminator */
	int i;

	for (i = 0; i < ARRAY_SIZE(intel_modifiers); i++) {
		if (plane_has_modifier(i915, plane_caps, &intel_modifiers[i]))
			count++;
	}

	list = kmalloc_array(count, sizeof(*list), GFP_KERNEL);
	if (drm_WARN_ON(&i915->drm, !list))
		return NULL;

	p = list;
	for (i = 0; i < ARRAY_SIZE(intel_modifiers); i++) {
		if (plane_has_modifier(i915, plane_caps, &intel_modifiers[i]))
			*p++ = intel_modifiers[i].modifier;
	}
	*p++ = DRM_FORMAT_MOD_INVALID;

	return list;
}

/**
 * intel_fb_plane_supports_modifier: Determine if a modifier is supported by the given plane
 * @plane: Plane to check the modifier support for
 * @modifier: The modifier to check the support for
 *
 * Returns:
 * %true if the @modifier is supported on @plane.
 */
bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier)
{
	int i;

	for (i = 0; i < plane->base.modifier_count; i++)
		if (plane->base.modifiers[i] == modifier)
			return true;

	return false;
}

bool is_ccs_plane(const struct drm_framebuffer *fb, int plane)
{
	if (!is_ccs_modifier(fb->modifier))
+13 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#ifndef __INTEL_FB_H__
#define __INTEL_FB_H__

#include <linux/bits.h>
#include <linux/types.h>

struct drm_device;
@@ -16,13 +17,25 @@ struct drm_i915_private;
struct drm_mode_fb_cmd2;
struct intel_fb_view;
struct intel_framebuffer;
struct intel_plane;
struct intel_plane_state;

enum intel_plane_caps {
	PLANE_HAS_NO_CAPS = 0,
	PLANE_HAS_TILING = BIT(0),
	PLANE_HAS_CCS_RC = BIT(1),
	PLANE_HAS_CCS_MC = BIT(2),
};

bool is_ccs_plane(const struct drm_framebuffer *fb, int plane);
bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane);
bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane);
bool is_semiplanar_uv_plane(const struct drm_framebuffer *fb, int color_plane);

u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915,
				  enum intel_plane_caps plane_caps);
bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier);

bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane);

int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane);
Loading