From patchwork Sun Jun 3 22:00:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 924765 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-tegra-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="J45kI3xa"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40zX9q5nPnz9ry1 for ; Mon, 4 Jun 2018 08:02:39 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751552AbeFCWCZ (ORCPT ); Sun, 3 Jun 2018 18:02:25 -0400 Received: from mail-lf0-f66.google.com ([209.85.215.66]:34136 "EHLO mail-lf0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751476AbeFCWCV (ORCPT ); Sun, 3 Jun 2018 18:02:21 -0400 Received: by mail-lf0-f66.google.com with SMTP id o9-v6so22188665lfk.1; Sun, 03 Jun 2018 15:02:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=fskeSwf2IqWYOe4vGnjVXrxRwOqGU4rMNmp5pb4aJ8Y=; b=J45kI3xaj0jaxf+L9D+BRfWzV4m4Kt2W5iEtqC9pp7frqurTFYnX3C3J8u4qYZy/n3 BXrQDSYJnl/gk7Np/U6tr64Afg2/KFdI76ZVELtWFSSby5fWB4sztsAqmugsAztsJ61F o+MLunZ4AP6D1VAJcKRDMbdjkKuKtRkHEShFF6LGfAzpfvvRrOp1X0l5KD9Q7UFUrAiW nQuO5yOQGWO6DA1xA6uNmdtBzx58TSqQ5LjxGECSOFUxlGNSpEeiZMXmu0lnH3HkSMq2 KfNKr2W+xbfA/eyo+NewbELSMlCdbk4vFA0QWM3ZmqOVi9xJBlKK1dTNRE9xRS2w9a4+ rDaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=fskeSwf2IqWYOe4vGnjVXrxRwOqGU4rMNmp5pb4aJ8Y=; b=iMCaMWUWr40OP+b0kXwCPQZ60n+Z79pdOXDNcPiZWiDgpHNNtwXeO76w0nwvs4iWH/ YokUoHhVQgqkjZz8WLyeZ/9AmQR3s/wxRA+SoIHM7NeHbd3VGWbMFwD9zViDwingwKqn 1uXLICb0E+kEhg73uIRg39G0d3YSrA8MKMksBgq0HJoNsWlal/NY2x9MuWChBR7yCCtg SbcAtkvPkxPApV/bFFAX5SLWCH69vEEJKMUFoBYx2JU5Q3Q5v0gNpG8uUX7pEYseIigl GIQLR6AAoDAwQO73V0V4vT26va6Y/fLLnDfJkzIiCUbbNgHIccXomW4+Cfw8Qgbwbfdb YMtA== X-Gm-Message-State: ALKqPwfvm7dCOHUPN2b47IvSqrZp2f/NP75iGfBI9fw4VDIeoLrOUNvb oGZbzuEv/RN+Aan6rSQXDTE= X-Google-Smtp-Source: ADUXVKLb6adVpbuz95MZjdrTLnggh7ZZQfPm3bdteuIC65WCfsEbTVLqu/CkoGHVkjtE6S38mQTTRQ== X-Received: by 2002:a2e:486:: with SMTP id a6-v6mr13661481ljf.86.1528063339569; Sun, 03 Jun 2018 15:02:19 -0700 (PDT) Received: from localhost.localdomain ([109.252.91.41]) by smtp.gmail.com with ESMTPSA id a19-v6sm1513489lff.84.2018.06.03.15.02.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 03 Jun 2018 15:02:18 -0700 (PDT) From: Dmitry Osipenko To: Laurent Pinchart , =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= , Thierry Reding , Neil Armstrong , Maxime Ripard , dri-devel@lists.freedesktop.org, Paul Kocialkowski Cc: linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Russell King , Ben Skeggs , Sinclair Yeh , Thomas Hellstrom , Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH v3 2/2] drm/tegra: plane: Implement generic colorkey property for older Tegra's Date: Mon, 4 Jun 2018 01:00:59 +0300 Message-Id: <20180603220059.17670-3-digetx@gmail.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180603220059.17670-1-digetx@gmail.com> References: <20180603220059.17670-1-digetx@gmail.com> Sender: linux-tegra-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-tegra@vger.kernel.org For the starter a minimal color keying support is implemented, which is enough to provide userspace like Opentegra Xorg driver with ability to support color keying by the XVideo extension. Signed-off-by: Dmitry Osipenko --- drivers/gpu/drm/tegra/dc.c | 25 +++++++++ drivers/gpu/drm/tegra/dc.h | 7 +++ drivers/gpu/drm/tegra/plane.c | 102 ++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index c3afe7b2237e..685a0fedb01d 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -162,6 +162,7 @@ static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane) u32 foreground = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255) | BLEND_COLOR_KEY_NONE; u32 blendnokey = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255); + enum drm_plane_colorkey_mode mode; struct tegra_plane_state *state; u32 blending[2]; unsigned int i; @@ -171,7 +172,15 @@ static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane) tegra_plane_writel(plane, foreground, DC_WIN_BLEND_1WIN); state = to_tegra_plane_state(plane->base.state); + mode = plane->base.state->colorkey.mode; + /* setup color keying */ + if (mode == DRM_PLANE_COLORKEY_MODE_FOREGROUND_CLIP) { + /* color key matched areas are transparent */ + foreground = background[0] | BLEND_COLOR_KEY_0; + } + + /* setup alpha blending */ if (state->opaque) { /* * Since custom fix-weight blending isn't utilized and weight @@ -792,6 +801,11 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm, dev_err(dc->dev, "failed to create rotation property: %d\n", err); + if (dc->soc->has_legacy_blending) + drm_plane_create_colorkey_properties(&plane->base, + BIT(DRM_PLANE_COLORKEY_MODE_DISABLED) | + BIT(DRM_PLANE_COLORKEY_MODE_FOREGROUND_CLIP)); + return &plane->base; } @@ -1077,6 +1091,11 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, dev_err(dc->dev, "failed to create rotation property: %d\n", err); + if (dc->soc->has_legacy_blending) + drm_plane_create_colorkey_properties(&plane->base, + BIT(DRM_PLANE_COLORKEY_MODE_DISABLED) | + BIT(DRM_PLANE_COLORKEY_MODE_FOREGROUND_CLIP)); + return &plane->base; } @@ -1187,6 +1206,7 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc) copy->pclk = state->pclk; copy->div = state->div; copy->planes = state->planes; + copy->ckey = state->ckey; return ©->base; } @@ -1917,6 +1937,11 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc, struct tegra_dc *dc = to_tegra_dc(crtc); u32 value; + if (dc->soc->has_legacy_blending) { + tegra_dc_writel(dc, state->ckey.min, DC_DISP_COLOR_KEY0_LOWER); + tegra_dc_writel(dc, state->ckey.max, DC_DISP_COLOR_KEY0_UPPER); + } + value = state->planes << 8 | GENERAL_UPDATE; tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL); diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index e96f582ca692..14ed31f0ff37 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h @@ -18,6 +18,11 @@ struct tegra_output; +struct tegra_dc_color_key_state { + u32 min; + u32 max; +}; + struct tegra_dc_state { struct drm_crtc_state base; @@ -26,6 +31,8 @@ struct tegra_dc_state { unsigned int div; u32 planes; + + struct tegra_dc_color_key_state ckey; }; static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state) diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c index d068e8aa3553..b8f05fd6ffcc 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c @@ -465,6 +465,104 @@ static int tegra_plane_setup_transparency(struct tegra_plane *tegra, return 0; } +static u32 tegra_plane_convert_colorkey_format(u64 value) +{ + /* convert ARGB16161616 to ARGB8888 */ + u16 a = (value >> 48) & 0xFFFF; + u16 r = (value >> 32) & 0xFFFF; + u16 g = (value >> 16) & 0xFFFF; + u16 b = (value >> 0) & 0xFFFF; + + a = min_t(u16, 0xff, a / 256); + r = min_t(u16, 0xff, r / 256); + g = min_t(u16, 0xff, g / 256); + b = min_t(u16, 0xff, b / 256); + + return (a << 24) | (r << 16) | (g << 8) | b; +} + +static bool tegra_plane_format_invalid_for_colorkey( + struct drm_plane_state *state) +{ + /* + * Older Tegra's do not support alpha channel matching. It should + * be possible to support certain cases where planes format has alpha + * channel, but for simplicity these cases currently are unsupported. + */ + if (state->fb && __drm_format_has_alpha(state->fb->format->format)) + return true; + + return false; +} + +static int tegra_plane_setup_colorkey(struct tegra_plane *tegra, + struct tegra_plane_state *tegra_state) +{ + enum drm_plane_colorkey_mode mode; + struct drm_plane_state *old_plane; + struct drm_crtc_state *crtc_state; + struct tegra_dc_state *dc_state; + struct drm_plane_state *state; + u64 min, max; + + mode = tegra_state->base.colorkey.mode; + min = tegra_state->base.colorkey.min; + max = tegra_state->base.colorkey.max; + + /* no need to proceed if color keying is disabled */ + if (mode == DRM_PLANE_COLORKEY_MODE_DISABLED) + return 0; + + state = &tegra_state->base; + old_plane = drm_atomic_get_old_plane_state(state->state, &tegra->base); + + /* + * Currently color keying implemented for the middle plane only + * to simplify things. + */ + if (state->normalized_zpos != 1) { + /* foreground-clip has no effect when applied to bottom plane */ + if (state->normalized_zpos == 0) + return 0; + + return -EINVAL; + } + + /* + * There is no need to proceed, adding CRTC and other planes to + * the atomic update, if color keying state is unchanged. + */ + if (old_plane && + old_plane->colorkey.mode == mode && + old_plane->colorkey.min == min && + old_plane->colorkey.max == max) + return 0; + + /* convert color key values to HW format */ + min = tegra_plane_convert_colorkey_format(min); + max = tegra_plane_convert_colorkey_format(max); + + /* validate planes format */ + if (tegra_plane_format_invalid_for_colorkey(state)) + return -EINVAL; + + /* + * Tegra's HW stores color key values within CRTC, hence adjust + * planes CRTC atomic state. + */ + crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + dc_state = to_dc_state(crtc_state); + + /* update CRTC's color key state */ + dc_state->ckey.min = min; + dc_state->ckey.max = max; + + return 0; +} + int tegra_plane_setup_legacy_state(struct tegra_plane *tegra, struct tegra_plane_state *state) { @@ -478,5 +576,9 @@ int tegra_plane_setup_legacy_state(struct tegra_plane *tegra, if (err < 0) return err; + err = tegra_plane_setup_colorkey(tegra, state); + if (err < 0) + return err; + return 0; }