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: 10445759 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 9F7B160375 for ; Mon, 4 Jun 2018 06:53:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8EF2928B45 for ; Mon, 4 Jun 2018 06:53:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8300228B51; Mon, 4 Jun 2018 06:53:52 +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=-5.2 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, FREEMAIL_FROM, MAILING_LIST_MULTI, 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 0CC7728B45 for ; Mon, 4 Jun 2018 06:53:52 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 77CD96E466; Mon, 4 Jun 2018 06:53:43 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-lf0-x244.google.com (mail-lf0-x244.google.com [IPv6:2a00:1450:4010:c07::244]) by gabe.freedesktop.org (Postfix) with ESMTPS id 233FB6E3A4 for ; Sun, 3 Jun 2018 22:02:21 +0000 (UTC) Received: by mail-lf0-x244.google.com with SMTP id i83-v6so10033235lfh.5 for ; Sun, 03 Jun 2018 15:02:21 -0700 (PDT) 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=qYqoftydtnAlqpSyV6fhIloem7t3N3UuyNCVDFfnOSn05Q93eLgCNCuWKzRum1CJG4 QIpuP6XW2p1QopzlYUTiCyyLndBoWlaSQIOSB4YY/uB170dJ8ktV5xhM9V0BIgRrJ8X9 wLq5EDbbsothl2R3+EOAqpEulUNzmpnlA92yUKJtuAOsacucVXTKY50TsnsFoVxezBCc UvPVKF5Yi6mQtg/kkXXSUmmadwEtie7yHctY2x5HgKikOLeAP5B0lr6WVk/X+6EOPYLW xz6OCq1oZ8yWaJVfOlFRKm5hmcG2oXZxChWEmM8TqjNI9/9lX9W7C90sUUFda4wVXHkj K6MA== X-Gm-Message-State: ALKqPwf4bxFOvudXEJ7MM+MU5zUDDvF/vPOyi22h8F3S2pNLRoHKU038 qy6QyNnZNQ4B4RzzCQJEwh0= 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?q?Ville=20Syrj=C3=A4l=C3=A4?= , Thierry Reding , Neil Armstrong , Maxime Ripard , dri-devel@lists.freedesktop.org, Paul Kocialkowski 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> X-Mailman-Approved-At: Mon, 04 Jun 2018 06:53:40 +0000 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Hellstrom , Russell King , linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Ben Skeggs , Rodrigo Vivi , linux-tegra@vger.kernel.org, linux-media@vger.kernel.org MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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; }