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;