From patchwork Fri Apr 18 21:04:21 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rodrigo Vivi X-Patchwork-Id: 4018521 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 407BDBFF02 for ; Fri, 18 Apr 2014 21:04:45 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 20A072038D for ; Fri, 18 Apr 2014 21:04:44 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id EF919202E6 for ; Fri, 18 Apr 2014 21:04:42 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 969046ECF1; Fri, 18 Apr 2014 14:04:42 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-pb0-f50.google.com (mail-pb0-f50.google.com [209.85.160.50]) by gabe.freedesktop.org (Postfix) with ESMTP id 639B26ECF2 for ; Fri, 18 Apr 2014 14:04:40 -0700 (PDT) Received: by mail-pb0-f50.google.com with SMTP id md12so1813931pbc.9 for ; Fri, 18 Apr 2014 14:04:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=fJ7pelH7S6G1yugfy7/lHAmXLgesJ6IQO3sDkLU/5uo=; b=PHlbnIxOaKRkhjnfEsl8hkLfvY4F2hFnHXn87Gi5wIBWcJBHfzTXz9HEkLeptwasGC oj/dt3HgOZVsX1W/fznSowxT3BpMdFst01MMOtxxN+KjhmtJGENA37eP0IMpAXGbgWid kWXBFUB2rVwfSJhVgJwcrHSA/+T9DYHW2BJWPIhVjynWETKzXhzE4zanUOEyWLq0RoOl akrnokvbBuJFeT9WqwBRFA3TJTbff10OehPwYkHztg3QcIfxX3g1qmpFyBHV5EIe2xBd NMzjyD8H7gsRx1U3VcSFjInKlDwhe0qEJXrsWQ3i2r8UodzFCIR79mZkc5/LG7ro0dCO Iyaw== X-Received: by 10.68.227.4 with SMTP id rw4mr24388765pbc.3.1397855080249; Fri, 18 Apr 2014 14:04:40 -0700 (PDT) Received: from localhost (jfdmzpr03-ext.jf.intel.com. [134.134.139.72]) by mx.google.com with ESMTPSA id ja8sm61846700pbd.3.2014.04.18.14.04.39 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 Apr 2014 14:04:39 -0700 (PDT) From: Rodrigo Vivi To: intel-gfx@lists.freedesktop.org Date: Fri, 18 Apr 2014 18:04:21 -0300 Message-Id: <1397855070-4480-6-git-send-email-rodrigo.vivi@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1397855070-4480-1-git-send-email-rodrigo.vivi@gmail.com> References: <1397855070-4480-1-git-send-email-rodrigo.vivi@gmail.com> Cc: "Yu\(Alex\) Dai" Subject: [Intel-gfx] [PATCH 05/14] drm/i915: add support for Z-order of planes X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: "Yu(Alex) Dai" Add "zorder" property to crtc to control Z-order of sprite and primary planes. The plane tag is packed into the 64 bits value in the order of from bottom (lower bits) to top (higher bits). Four bits are used for each plane tag. It can support up to 16 planes. The alpha channel of the plane is set during Z-order change. If a plane is put to the bottom, its alpha channel is off. Otherwise, its alpha channel is on. Signed-off-by: Yu(Alex) Dai Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 3 + drivers/gpu/drm/i915/intel_display.c | 58 +++++++++++++++-- drivers/gpu/drm/i915/intel_drv.h | 6 ++ drivers/gpu/drm/i915/intel_sprite.c | 119 ++++++++++++++++++++++++++++++++++- include/uapi/drm/i915_drm.h | 6 ++ 6 files changed, 186 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7d6acb4..6e14de9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2516,6 +2516,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_crtc *crtc, uint64_t 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 8f84555..8c382a5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3881,6 +3881,9 @@ enum punit_power_well { #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 _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 cd68a24..d245cca 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2169,18 +2169,27 @@ static int i9xx_update_primary_plane(struct drm_crtc *crtc, 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: @@ -2188,7 +2197,10 @@ static int i9xx_update_primary_plane(struct drm_crtc *crtc, 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(); @@ -8470,6 +8482,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); @@ -10422,6 +10437,27 @@ 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 && prop == icrtc->zorder_property) { + /* Simply return if no change in zorder */ + if (icrtc->zorder == val) + return 0; + + ret = i915_set_plane_zorder(crtc, val); + + if (!ret) + icrtc->zorder = val; + } + + return ret; +} + static const struct drm_crtc_funcs intel_crtc_funcs = { .cursor_set = intel_crtc_cursor_set, .cursor_move = intel_crtc_cursor_move, @@ -10429,6 +10465,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) @@ -10536,6 +10573,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) { struct drm_i915_private *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); @@ -10568,6 +10606,18 @@ 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; + + if (IS_VALLEYVIEW(dev)) + 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 c551472..c684427 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -387,6 +387,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; @@ -400,6 +403,9 @@ struct intel_crtc { /* watermarks currently being used */ struct intel_pipe_wm active; } wm; + + struct drm_property *zorder_property; + uint64_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..fb495d9 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -37,6 +37,101 @@ #include #include "i915_drv.h" +static int vlv_set_plane_zorder(struct drm_crtc *crtc, uint64_t order) +{ + struct drm_i915_private *dev_priv = crtc->dev->dev_private; + u32 val; + int s1_zorder = 0, s1_bottom = 0, s2_zorder = 0, s2_bottom = 0; + unsigned int i, z_order[I915_PLANE_MAX_NUM]; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + + /* Get plane order from bottom (lower bits) to top (higher bits) */ + for (i = 0; i < I915_PLANE_MAX_NUM; i++) + z_order[i] = (order >> (i*4)) & 0xF; + + /* The top layer must be cursor */ + if (z_order[i-1] != I915_PLANE_CURSOR) + return -EINVAL; + + /* No duplicated setting */ + if (z_order[0] == z_order[1] || + z_order[0] == z_order[2] || + z_order[1] == z_order[2]) + return -EINVAL; + + switch (z_order[0]) { + case I915_PLANE_PRIMARY: + if (z_order[1] == I915_PLANE_SPRITE_B) + s1_zorder = 1; + break; + case I915_PLANE_SPRITE_A: + s1_bottom = 1; + if (z_order[1] == I915_PLANE_SPRITE_B) + s2_zorder = 1; + break; + case I915_PLANE_SPRITE_B: + s2_bottom = 1; + if (z_order[1] == I915_PLANE_SPRITE_A) + s1_zorder = 1; + break; + default: + return -EINVAL; + } + + /* 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 a plane is not at bottom, the alpha channel should be on. */ + if (z_order[0] != I915_PLANE_PRIMARY) + intel_crtc->primary_alpha = true; + else + intel_crtc->primary_alpha = false; + + if (z_order[0] != I915_PLANE_SPRITE_A) + intel_crtc->sprite0_alpha = true; + else + intel_crtc->sprite0_alpha = false; + + if (z_order[0] != I915_PLANE_SPRITE_B) + intel_crtc->sprite1_alpha = true; + else + intel_crtc->sprite1_alpha = false; + + return 0; +} + +int i915_set_plane_zorder(struct drm_crtc *crtc, uint64_t val) +{ + int ret = -ENOENT; + + if (IS_VALLEYVIEW(crtc->dev)) + ret = vlv_set_plane_zorder(crtc, val); + + return ret; +} + static void vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, struct drm_framebuffer *fb, @@ -50,10 +145,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 +185,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: /* diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 8a3e4ef00..3f6eb90 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -1050,4 +1050,10 @@ struct drm_i915_reset_stats { __u32 pad; }; +#define I915_PLANE_PRIMARY 0 +#define I915_PLANE_SPRITE_A 1 +#define I915_PLANE_SPRITE_B 2 +#define I915_PLANE_CURSOR 3 +#define I915_PLANE_MAX_NUM (I915_PLANE_CURSOR + 1) + #endif /* _UAPI_I915_DRM_H_ */