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