From patchwork Mon Feb 27 11:52:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Zabel X-Patchwork-Id: 9593025 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BFBBE60453 for ; Mon, 27 Feb 2017 11:53:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B268F279E0 for ; Mon, 27 Feb 2017 11:53:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A696D280FC; Mon, 27 Feb 2017 11:53:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 39A63279E0 for ; Mon, 27 Feb 2017 11:53:02 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A8F3F6E3CA; Mon, 27 Feb 2017 11:52:59 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by gabe.freedesktop.org (Postfix) with ESMTPS id EE3BD6E3C9 for ; Mon, 27 Feb 2017 11:52:57 +0000 (UTC) Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7] helo=dude.pengutronix.de.) by metis.ext.pengutronix.de with esmtp (Exim 4.84_2) (envelope-from ) id 1ciJrM-0001ok-Ei; Mon, 27 Feb 2017 12:52:56 +0100 From: Philipp Zabel To: dri-devel@lists.freedesktop.org Subject: [PATCH 4/4] drm/imx: ipuv3-plane: add support for separate alpha planes Date: Mon, 27 Feb 2017 12:52:49 +0100 Message-Id: <20170227115249.28048-4-p.zabel@pengutronix.de> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170227115249.28048-1-p.zabel@pengutronix.de> References: <20170227115249.28048-1-p.zabel@pengutronix.de> X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: p.zabel@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: dri-devel@lists.freedesktop.org Cc: kernel@pengutronix.de X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP The IPUv3 can read 8-bit alpha values from a separate plane buffer using a companion IDMAC channel driven by the Alpha Transparency Controller (ATC) for the graphics channels. The conditional read mechanism allows to reduce memory bandwidth by skipping reads of color data for completely transparent bursts. Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/ipuv3-plane.c | 97 ++++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/imx/ipuv3-plane.h | 1 + 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 3a5db8d51bf3f..7ef6dab6e3ad4 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -57,6 +57,12 @@ static const uint32_t ipu_plane_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_NV16, DRM_FORMAT_RGB565, + DRM_FORMAT_RGB565_A8, + DRM_FORMAT_BGR565_A8, + DRM_FORMAT_RGB888_A8, + DRM_FORMAT_BGR888_A8, + DRM_FORMAT_RGBX8888_A8, + DRM_FORMAT_BGRX8888_A8, }; int ipu_plane_irq(struct ipu_plane *ipu_plane) @@ -126,11 +132,14 @@ void ipu_plane_put_resources(struct ipu_plane *ipu_plane) ipu_dmfc_put(ipu_plane->dmfc); if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch)) ipu_idmac_put(ipu_plane->ipu_ch); + if (!IS_ERR_OR_NULL(ipu_plane->alpha_ch)) + ipu_idmac_put(ipu_plane->alpha_ch); } int ipu_plane_get_resources(struct ipu_plane *ipu_plane) { int ret; + int alpha_ch; ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma); if (IS_ERR(ipu_plane->ipu_ch)) { @@ -139,6 +148,17 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane) return ret; } + alpha_ch = ipu_channel_alpha_channel(ipu_plane->dma); + if (alpha_ch >= 0) { + ipu_plane->alpha_ch = ipu_idmac_get(ipu_plane->ipu, alpha_ch); + if (IS_ERR(ipu_plane->alpha_ch)) { + ret = PTR_ERR(ipu_plane->alpha_ch); + DRM_ERROR("failed to get alpha idmac channel %d: %d\n", + alpha_ch, ret); + return ret; + } + } + ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma); if (IS_ERR(ipu_plane->dmfc)) { ret = PTR_ERR(ipu_plane->dmfc); @@ -162,12 +182,29 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane) return ret; } +static bool ipu_plane_separate_alpha(struct ipu_plane *ipu_plane) +{ + switch (ipu_plane->base.state->fb->format->format) { + case DRM_FORMAT_RGB565_A8: + case DRM_FORMAT_BGR565_A8: + case DRM_FORMAT_RGB888_A8: + case DRM_FORMAT_BGR888_A8: + case DRM_FORMAT_RGBX8888_A8: + case DRM_FORMAT_BGRX8888_A8: + return true; + default: + return false; + } +} + static void ipu_plane_enable(struct ipu_plane *ipu_plane) { if (ipu_plane->dp) ipu_dp_enable(ipu_plane->ipu); ipu_dmfc_enable_channel(ipu_plane->dmfc); ipu_idmac_enable_channel(ipu_plane->ipu_ch); + if (ipu_plane_separate_alpha(ipu_plane)) + ipu_idmac_enable_channel(ipu_plane->alpha_ch); if (ipu_plane->dp) ipu_dp_enable_channel(ipu_plane->dp); } @@ -181,6 +218,8 @@ void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel) if (ipu_plane->dp && disable_dp_channel) ipu_dp_disable_channel(ipu_plane->dp, false); ipu_idmac_disable_channel(ipu_plane->ipu_ch); + if (ipu_plane->alpha_ch) + ipu_idmac_disable_channel(ipu_plane->alpha_ch); ipu_dmfc_disable_channel(ipu_plane->dmfc); if (ipu_plane->dp) ipu_dp_disable(ipu_plane->ipu); @@ -223,7 +262,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, struct device *dev = plane->dev->dev; struct drm_framebuffer *fb = state->fb; struct drm_framebuffer *old_fb = old_state->fb; - unsigned long eba, ubo, vbo, old_ubo, old_vbo; + unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba; bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY); struct drm_rect clip; int hsub, vsub; @@ -354,6 +393,23 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, if (((state->src.x1 >> 16) & (hsub - 1)) || ((state->src.y1 >> 16) & (vsub - 1))) return -EINVAL; + break; + case DRM_FORMAT_RGB565_A8: + case DRM_FORMAT_BGR565_A8: + case DRM_FORMAT_RGB888_A8: + case DRM_FORMAT_BGR888_A8: + case DRM_FORMAT_RGBX8888_A8: + case DRM_FORMAT_BGRX8888_A8: + alpha_eba = drm_plane_state_to_eba(state, 1); + if (alpha_eba & 0x7) + return -EINVAL; + + if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) + return -EINVAL; + + if (old_fb && old_fb->pitches[1] != fb->pitches[1]) + crtc_state->mode_changed = true; + break; } return 0; @@ -378,6 +434,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, struct drm_framebuffer *fb = state->fb; struct drm_rect *dst = &state->dst; unsigned long eba, ubo, vbo; + unsigned long alpha_eba = 0; enum ipu_color_space ics; int active; @@ -390,6 +447,12 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); + if (ipu_plane_separate_alpha(ipu_plane)) { + active = ipu_idmac_get_current_buffer(ipu_plane->alpha_ch); + ipu_cpmem_set_buffer(ipu_plane->alpha_ch, !active, + alpha_eba); + ipu_idmac_select_buffer(ipu_plane->alpha_ch, !active); + } return; } @@ -415,6 +478,12 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, case DRM_FORMAT_ABGR8888: case DRM_FORMAT_RGBA8888: case DRM_FORMAT_BGRA8888: + case DRM_FORMAT_RGB565_A8: + case DRM_FORMAT_BGR565_A8: + case DRM_FORMAT_RGB888_A8: + case DRM_FORMAT_BGR888_A8: + case DRM_FORMAT_RGBX8888_A8: + case DRM_FORMAT_BGRX8888_A8: ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false); break; default: @@ -465,6 +534,32 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, "phy = %lu %lu, x = %d, y = %d", eba, ubo, state->src.x1 >> 16, state->src.y1 >> 16); break; + case DRM_FORMAT_RGB565_A8: + case DRM_FORMAT_BGR565_A8: + case DRM_FORMAT_RGB888_A8: + case DRM_FORMAT_BGR888_A8: + case DRM_FORMAT_RGBX8888_A8: + case DRM_FORMAT_BGRX8888_A8: + alpha_eba = drm_plane_state_to_eba(state, 1); + + dev_dbg(ipu_plane->base.dev->dev, "phys = %lu %lu, x = %d, y = %d", + eba, alpha_eba, state->src.x1 >> 16, state->src.y1 >> 16); + + ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, 16); + + ipu_cpmem_zero(ipu_plane->alpha_ch); + ipu_cpmem_set_resolution(ipu_plane->alpha_ch, + drm_rect_width(&state->src) >> 16, + drm_rect_height(&state->src) >> 16); + ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8); + ipu_cpmem_set_high_priority(ipu_plane->alpha_ch); + ipu_idmac_set_double_buffer(ipu_plane->alpha_ch, 1); + ipu_cpmem_set_stride(ipu_plane->alpha_ch, + state->fb->pitches[1]); + ipu_cpmem_set_burstsize(ipu_plane->alpha_ch, 16); + ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 0, alpha_eba); + ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 1, alpha_eba); + break; default: dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d", eba, state->src.x1 >> 16, state->src.y1 >> 16); diff --git a/drivers/gpu/drm/imx/ipuv3-plane.h b/drivers/gpu/drm/imx/ipuv3-plane.h index 0e2a723ff9816..596b24ddbf657 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.h +++ b/drivers/gpu/drm/imx/ipuv3-plane.h @@ -18,6 +18,7 @@ struct ipu_plane { struct ipu_soc *ipu; struct ipuv3_channel *ipu_ch; + struct ipuv3_channel *alpha_ch; struct dmfc_channel *dmfc; struct ipu_dp *dp;