From: "Yu(Alex) Dai" <yu....@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....@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 | 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@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to