[Intel-gfx] [PATCH v2] drm/i915: add support for Z-order of planes.
yu.dai at intel.com
yu.dai at intel.com
Sat Feb 22 01:15:39 CET 2014
From: "Yu(Alex) Dai" <yu.dai at intel.com>
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 at intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/i915_reg.h | 10 +++++
drivers/gpu/drm/i915/intel_display.c | 60 ++++++++++++++++++++++++--
drivers/gpu/drm/i915/intel_drv.h | 6 +++
drivers/gpu/drm/i915/intel_sprite.c | 81 ++++++++++++++++++++++++++++++++++--
5 files changed, 151 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..2916536 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,31 @@ 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;
+
+ /* Bit 31 for pipe and 0~3 for order */
+ if (zorder & ~0x8000000F)
+ return -EINVAL;
+
+ /* Simply return if no change in zorder */
+ if (icrtc->zorder == zorder)
+ return 0;
+
+ 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 +10207,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 +10315,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 +10348,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
More information about the Intel-gfx
mailing list