[PATCH] drm/i915: add support for Z-order of planes.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: "Yu(Alex) Dai" <yu.dai@xxxxxxxxx>

Add "zorder" property to crtc to control Z-order of sprite and
primary planes. The alpha channel of the planes can be enabled
or disabled during Z-order change.

Signed-off-by: Yu(Alex) Dai <yu.dai@xxxxxxxxx>
---
 drivers/gpu/drm/i915/i915_drv.h      |  1 +
 drivers/gpu/drm/i915/i915_reg.h      | 10 +++++
 drivers/gpu/drm/i915/intel_display.c | 51 +++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_drv.h     |  6 +++
 drivers/gpu/drm/i915/intel_sprite.c  | 81 ++++++++++++++++++++++++++++++++++--
 5 files changed, 142 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8c64831..7833479 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2581,6 +2581,7 @@ int i915_reg_read_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file);
 int i915_get_reset_stats_ioctl(struct drm_device *dev, void *data,
 			       struct drm_file *file);
+extern int i915_set_plane_zorder(struct drm_device *dev, u32 zorder);
 
 /* overlay */
 extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2f564ce..c9a9993 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3743,6 +3743,16 @@
 #define   SPRITE_INT_GAMMA_ENABLE	(1<<13)
 #define   SPRITE_TILED			(1<<10)
 #define   SPRITE_DEST_KEY		(1<<2)
+#define   SPRITE_FORCE_BOTTOM		(1<<2)
+#define   SPRITE_ZORDER_ENABLE		(1<<0)
+
+#define P1S1S2C1		0
+#define P1S2S1C1		8
+#define S2P1S1C1		1
+#define S2S1P1C1		9
+#define S1P1S2C1		4
+#define S1S2P1C1		6
+
 #define _SPRA_LINOFF		0x70284
 #define _SPRA_STRIDE		0x70288
 #define _SPRA_POS		0x7028c
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f19e6ea..8ddf6c2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2082,18 +2082,27 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 		break;
 	case DRM_FORMAT_XRGB1555:
 	case DRM_FORMAT_ARGB1555:
-		dspcntr |= DISPPLANE_BGRX555;
+		if (intel_crtc->primary_alpha)
+			dspcntr |= DISPPLANE_BGRA555;
+		else
+			dspcntr |= DISPPLANE_BGRX555;
 		break;
 	case DRM_FORMAT_RGB565:
 		dspcntr |= DISPPLANE_BGRX565;
 		break;
 	case DRM_FORMAT_XRGB8888:
 	case DRM_FORMAT_ARGB8888:
-		dspcntr |= DISPPLANE_BGRX888;
+		if (intel_crtc->primary_alpha)
+			dspcntr |= DISPPLANE_BGRA888;
+		else
+			dspcntr |= DISPPLANE_BGRX888;
 		break;
 	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_ABGR8888:
-		dspcntr |= DISPPLANE_RGBX888;
+		if (intel_crtc->primary_alpha)
+			dspcntr |= DISPPLANE_RGBA888;
+		else
+			dspcntr |= DISPPLANE_RGBX888;
 		break;
 	case DRM_FORMAT_XRGB2101010:
 	case DRM_FORMAT_ARGB2101010:
@@ -2101,7 +2110,10 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 		break;
 	case DRM_FORMAT_XBGR2101010:
 	case DRM_FORMAT_ABGR2101010:
-		dspcntr |= DISPPLANE_RGBX101010;
+		if (intel_crtc->primary_alpha)
+			dspcntr |= DISPPLANE_RGBA101010;
+		else
+			dspcntr |= DISPPLANE_RGBX101010;
 		break;
 	default:
 		BUG();
@@ -8258,6 +8270,9 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
 
 	intel_crtc_cursor_set(crtc, NULL, 0, 0, 0);
 
+	if (intel_crtc->zorder_property)
+		drm_property_destroy(dev, intel_crtc->zorder_property);
+
 	drm_crtc_cleanup(crtc);
 
 	kfree(intel_crtc);
@@ -10160,6 +10175,22 @@ out_config:
 	return ret;
 }
 
+static int intel_crtc_set_property(struct drm_crtc *crtc,
+				   struct drm_property *prop,
+				   uint64_t val)
+{
+	struct intel_crtc *icrtc = to_intel_crtc(crtc);
+	int ret = -ENOENT;
+
+	if (prop == icrtc->zorder_property) {
+		u32 zorder = (uint32_t)val;
+		icrtc->zorder = zorder;
+		ret = i915_set_plane_zorder(crtc->dev, zorder);
+	}
+
+	return ret;
+}
+
 static const struct drm_crtc_funcs intel_crtc_funcs = {
 	.cursor_set = intel_crtc_cursor_set,
 	.cursor_move = intel_crtc_cursor_move,
@@ -10167,6 +10198,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
 	.set_config = intel_crtc_set_config,
 	.destroy = intel_crtc_destroy,
 	.page_flip = intel_crtc_page_flip,
+	.set_property = intel_crtc_set_property,
 };
 
 static void intel_cpu_pll_init(struct drm_device *dev)
@@ -10274,6 +10306,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc;
+	struct drm_property *prop = 0;
 	int i;
 
 	intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
@@ -10306,6 +10339,16 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
 
 	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
+
+	intel_crtc->primary_alpha = false;
+	intel_crtc->sprite0_alpha = true;
+	intel_crtc->sprite1_alpha = true;
+
+	prop = drm_property_create(dev, 0, "zorder", 1);
+	if (prop)
+		drm_object_attach_property(&intel_crtc->base.base, prop, 0);
+
+	intel_crtc->zorder_property = prop;
 }
 
 enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a4ffc02..eb88959 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -371,6 +371,9 @@ struct intel_crtc {
 	bool new_enabled;
 
 	uint32_t ddi_pll_sel;
+	bool primary_alpha;
+	bool sprite0_alpha;
+	bool sprite1_alpha;
 
 	/* reset counter value when the last flip was submitted */
 	unsigned int reset_counter;
@@ -384,6 +387,9 @@ struct intel_crtc {
 		/* watermarks currently being used  */
 		struct intel_pipe_wm active;
 	} wm;
+
+	struct drm_property *zorder_property;
+	uint32_t zorder;
 };
 
 struct intel_plane_wm_parameters {
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 336ae6c..18f8200 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -37,6 +37,63 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
+int i915_set_plane_zorder(struct drm_device *dev, u32 order)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 val;
+	int s1_zorder, s1_bottom, s2_zorder, s2_bottom;
+	int pipe = (order >> 31) & 0x1;
+	int z_order = order & 0x000F;
+	struct intel_crtc *intel_crtc =
+			to_intel_crtc(dev_priv->plane_to_crtc_mapping[pipe]);
+
+	s1_zorder = (order >> 3) & 0x1;
+	s1_bottom = (order >> 2) & 0x1;
+	s2_zorder = (order >> 1) & 0x1;
+	s2_bottom = (order >> 0) & 0x1;
+
+	/* Clear the older Z-order */
+	val = I915_READ(SPCNTR(pipe, 0));
+	val &= ~(SPRITE_FORCE_BOTTOM | SPRITE_ZORDER_ENABLE);
+	I915_WRITE(SPCNTR(pipe, 0), val);
+
+	val = I915_READ(SPCNTR(pipe, 1));
+	val &= ~(SPRITE_FORCE_BOTTOM | SPRITE_ZORDER_ENABLE);
+	I915_WRITE(SPCNTR(pipe, 1), val);
+
+	/* Program new Z-order */
+	val = I915_READ(SPCNTR(pipe, 0));
+	if (s1_zorder)
+		val |= SPRITE_ZORDER_ENABLE;
+	if (s1_bottom)
+		val |= SPRITE_FORCE_BOTTOM;
+	I915_WRITE(SPCNTR(pipe, 0), val);
+
+	val = I915_READ(SPCNTR(pipe, 1));
+	if (s2_zorder)
+		val |= SPRITE_ZORDER_ENABLE;
+	if (s2_bottom)
+		val |= SPRITE_FORCE_BOTTOM;
+	I915_WRITE(SPCNTR(pipe, 1), val);
+
+	if (z_order != P1S1S2C1 && z_order != P1S2S1C1)
+		intel_crtc->primary_alpha = true;
+	else
+		intel_crtc->primary_alpha = false;
+
+	if (z_order != S1P1S2C1 && z_order != S1S2P1C1)
+		intel_crtc->sprite0_alpha = true;
+	else
+		intel_crtc->sprite0_alpha = false;
+
+	if (z_order != S2P1S1C1 && z_order != S2S1P1C1)
+		intel_crtc->sprite1_alpha = true;
+	else
+		intel_crtc->sprite1_alpha = false;
+
+	return 0;
+}
+
 static void
 vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 		 struct drm_framebuffer *fb,
@@ -50,10 +107,19 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 	struct intel_plane *intel_plane = to_intel_plane(dplane);
 	int pipe = intel_plane->pipe;
 	int plane = intel_plane->plane;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	u32 sprctl;
+	bool alpha = true;
 	unsigned long sprsurf_offset, linear_offset;
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
+	if (plane && intel_crtc->sprite1_alpha)
+		alpha = true;
+	else if (!plane && intel_crtc->sprite0_alpha)
+		alpha = true;
+	else
+		alpha = false;
+
 	sprctl = I915_READ(SPCNTR(pipe, plane));
 
 	/* Mask out pixel format bits in case we change it */
@@ -81,19 +147,28 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 		sprctl |= SP_FORMAT_BGRX8888;
 		break;
 	case DRM_FORMAT_ARGB8888:
-		sprctl |= SP_FORMAT_BGRA8888;
+		if (alpha)
+			sprctl |= SP_FORMAT_BGRA8888;
+		else
+			sprctl |= SP_FORMAT_BGRX8888;
 		break;
 	case DRM_FORMAT_XBGR2101010:
 		sprctl |= SP_FORMAT_RGBX1010102;
 		break;
 	case DRM_FORMAT_ABGR2101010:
-		sprctl |= SP_FORMAT_RGBA1010102;
+		if (alpha)
+			sprctl |= SP_FORMAT_RGBA1010102;
+		else
+			sprctl |= SP_FORMAT_RGBX1010102;
 		break;
 	case DRM_FORMAT_XBGR8888:
 		sprctl |= SP_FORMAT_RGBX8888;
 		break;
 	case DRM_FORMAT_ABGR8888:
-		sprctl |= SP_FORMAT_RGBA8888;
+		if (alpha)
+			sprctl |= SP_FORMAT_RGBA8888;
+		else
+			sprctl |= SP_FORMAT_RGBX8888;
 		break;
 	default:
 		/*
-- 
1.8.5.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux