[Intel-gfx] [PATCH] drm/i915: add support for Z-order of planes.
Matt Roper
matthew.d.roper at intel.com
Wed Feb 26 01:19:29 CET 2014
On Thu, Feb 20, 2014 at 04:11:14PM -0800, yu.dai at intel.com wrote:
> 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>
It seems like this is pretty VLV-specific at the moment. Aren't you
going to be writing bogus register values if you try to set this
property on a non-VLV platform?
I'm not sure if any of the other non-VLV platforms supported by i915
today can change plane z-orders or not, but this is likely to be
possible and useful on future platforms (or non-Intel platforms) as
well, which may have a different number of overall planes and different
ways of programming them.
Would it make more sense to move the z-order value to a plane property
so that the interface scales to any number of planes? If you just set
an integer value as a per-plane zorder-value, the code that actually
programs the hardware can go collect the values for each plane, sort
them to determine an order, and figure out what that translates to in
terms of platform-specific register programming. This would lend itself
nicely to the "check/calculate" step of the atomic/nuclear operation
once those interfaces land.
Matt
> ---
> 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Matt Roper
Graphics Software Engineer
ISG Platform Enabling & Development
Intel Corporation
(916) 356-2795
More information about the Intel-gfx
mailing list