From patchwork Sun Jun 3 22:00:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 924766 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="jMz1gTtT"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40zXBG1TRbz9ry1 for ; Mon, 4 Jun 2018 08:03:02 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751688AbeFCWCr (ORCPT ); Sun, 3 Jun 2018 18:02:47 -0400 Received: from mail-lf0-f65.google.com ([209.85.215.65]:44736 "EHLO mail-lf0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751282AbeFCWCU (ORCPT ); Sun, 3 Jun 2018 18:02:20 -0400 Received: by mail-lf0-f65.google.com with SMTP id 36-v6so20251309lfr.11; Sun, 03 Jun 2018 15:02:18 -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=5eYN9sBhSjHa1rX8ObeeHd3u09J6Np7SiIaEOrgeVSY=; b=jMz1gTtTt2fnKAozbR/tDUvzRPhYudvdzgCiP9tLnM1l9HXZiTofQLlDIcYjgdKBiS TK7RFCrIFErRNPuu2sD7xmYcRKaIAL9ShKZAyJKdllILF0rqZOGMBsERysL8iCj5OKjP Xq3hb4xaOZWGVsSM8mhVJGajyOxzgzZHICls56LA1aXRTiEZJL0ufRqeXPvfSFVODHjl tzVOEILrUU4GfiykTzY43EY9y4UomQlBeT/R4KDj/2iaDrzM+4ouF6DnlqEYJ/Dul5Rr VUwaPLu3mBbZUGWMtV6bpXofMND4yuN02+qSynJfDrGI1ILDn8K36CjmDSotX+75+B8G QMDg== 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=5eYN9sBhSjHa1rX8ObeeHd3u09J6Np7SiIaEOrgeVSY=; b=kwEBwVnbIx6Lh6QK8tFlKDK/1D4mg1uke3gYU2SaB2WRlsQ5oL0aEHr/5aX+SwJVJz NOkz9SNJKpME0HnDBtP6mXg89+M/01d3KCW3PKRz3dbVb7/bisJ0lvSTioDjy2qCGu3Q 5GYIJF9g6r3bTz0eE7PJ/zSULUxgYle2c5Gpz2KWF1hyzbL+9DaitYt52siVPOx0c+gm 28C6WwF7BfMHJ4Dm3Bi/JV27jrKrol7CuYywiVloo89kL9hWOQ175pXeTLgGpHimNSkx /QgsKG64P1hghFZp/vr27/O/pPKXms90M1++sl+kT2kj3i70p1/ivdmhOYOH21d0M1mD RNqw== X-Gm-Message-State: APt69E2pOEkM0I1n4ELI87dYk23P0Yt8KwlQxyqTDU9Dsl/CCExyuD0g QEZKvshzFwaOb1S8WRHDW5Q= X-Google-Smtp-Source: ADUXVKJIzoFjR861Xab8vQA+kn05bdKjc23VGRPsLqZKo6ahNQzkjqNfyUuhnQ9YkcbJTOEBdcY0GQ== X-Received: by 2002:a2e:8990:: with SMTP id c16-v6mr2014117lji.123.1528063338137; Sun, 03 Jun 2018 15:02:18 -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.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 03 Jun 2018 15:02:17 -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 1/2] drm: Add generic colorkey properties for DRM planes Date: Mon, 4 Jun 2018 01:00:58 +0300 Message-Id: <20180603220059.17670-2-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 From: Laurent Pinchart Color keying is the action of replacing pixels matching a given color (or range of colors) with transparent pixels in an overlay when performing blitting. Depending on the hardware capabilities, the matching pixel can either become fully transparent or gain adjustment of the pixels component values. Color keying is found in a large number of devices whose capabilities often differ, but they still have enough common features in range to standardize color key properties. This commit adds three generic DRM plane properties related to the color keying, providing initial color keying support. Signed-off-by: Laurent Pinchart Signed-off-by: Dmitry Osipenko --- drivers/gpu/drm/drm_atomic.c | 12 +++++ drivers/gpu/drm/drm_blend.c | 99 ++++++++++++++++++++++++++++++++++++ include/drm/drm_blend.h | 3 ++ include/drm/drm_plane.h | 53 +++++++++++++++++++ 4 files changed, 167 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 895741e9cd7d..b322cbed319b 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -799,6 +799,12 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, state->rotation = val; } else if (property == plane->zpos_property) { state->zpos = val; + } else if (property == plane->colorkey.mode_property) { + state->colorkey.mode = val; + } else if (property == plane->colorkey.min_property) { + state->colorkey.min = val; + } else if (property == plane->colorkey.max_property) { + state->colorkey.max = val; } else if (property == plane->color_encoding_property) { state->color_encoding = val; } else if (property == plane->color_range_property) { @@ -864,6 +870,12 @@ drm_atomic_plane_get_property(struct drm_plane *plane, *val = state->rotation; } else if (property == plane->zpos_property) { *val = state->zpos; + } else if (property == plane->colorkey.mode_property) { + *val = state->colorkey.mode; + } else if (property == plane->colorkey.min_property) { + *val = state->colorkey.min; + } else if (property == plane->colorkey.max_property) { + *val = state->colorkey.max; } else if (property == plane->color_encoding_property) { *val = state->color_encoding; } else if (property == plane->color_range_property) { diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c index a16a74d7e15e..12fed2ff65c8 100644 --- a/drivers/gpu/drm/drm_blend.c +++ b/drivers/gpu/drm/drm_blend.c @@ -107,6 +107,11 @@ * planes. Without this property the primary plane is always below the cursor * plane, and ordering between all other planes is undefined. * + * colorkey: + * Color keying is set up with drm_plane_create_colorkey_properties(). + * It adds support for replacing a range of colors with a transparent + * color in the plane. + * * Note that all the property extensions described here apply either to the * plane or the CRTC (e.g. for the background color, which currently is not * exposed and assumed to be black). @@ -448,3 +453,97 @@ int drm_atomic_normalize_zpos(struct drm_device *dev, return 0; } EXPORT_SYMBOL(drm_atomic_normalize_zpos); + +static const char * const plane_colorkey_mode_name[] = { + [DRM_PLANE_COLORKEY_MODE_DISABLED] = "disabled", + [DRM_PLANE_COLORKEY_MODE_FOREGROUND_CLIP] = "foreground-clip", +}; + +/** + * drm_plane_create_colorkey_properties - create colorkey properties + * @plane: drm plane + * @supported_modes: bitmask of supported color keying modes + * + * This function creates the generic color keying properties and attach them to + * the plane to enable color keying control for blending operations. + * + * Color keying is controlled by these properties: + * + * colorkey.mode: + * The mode is an enumerated property that controls how color keying + * operates. + * + * colorkey.min, colorkey.max: + * These two properties specify the colors that are treated as the color + * key. Pixel whose value is in the [min, max] range is the color key + * matching pixel. The minimum and maximum values are expressed as a + * 64-bit integer in ARGB16161616 format, where A is the alpha value and + * R, G and B correspond to the color components. Drivers shall convert + * ARGB16161616 value into appropriate format within planes atomic check. + * + * When a single color key is desired instead of a range, userspace shall + * set the min and max properties to the same value. + * + * Drivers return an error from their plane atomic check if range can't be + * handled. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_plane_create_colorkey_properties(struct drm_plane *plane, + u32 supported_modes) +{ + struct drm_prop_enum_list modes_list[DRM_PLANE_COLORKEY_MODES_NUM]; + struct drm_property *mode_prop; + struct drm_property *min_prop; + struct drm_property *max_prop; + unsigned int modes_num = 0; + unsigned int i; + + /* modes are driver-specific, build the list of supported modes */ + for (i = 0; i < DRM_PLANE_COLORKEY_MODES_NUM; i++) { + if (!(supported_modes & BIT(i))) + continue; + + modes_list[modes_num].name = plane_colorkey_mode_name[i]; + modes_list[modes_num].type = i; + modes_num++; + } + + /* at least one mode should be supported */ + if (!modes_num) + return -EINVAL; + + mode_prop = drm_property_create_enum(plane->dev, 0, "colorkey.mode", + modes_list, modes_num); + if (!mode_prop) + return -ENOMEM; + + min_prop = drm_property_create_range(plane->dev, 0, "colorkey.min", + 0, U64_MAX); + if (!min_prop) + goto err_destroy_mode_prop; + + max_prop = drm_property_create_range(plane->dev, 0, "colorkey.max", + 0, U64_MAX); + if (!max_prop) + goto err_destroy_min_prop; + + drm_object_attach_property(&plane->base, mode_prop, 0); + drm_object_attach_property(&plane->base, min_prop, 0); + drm_object_attach_property(&plane->base, max_prop, 0); + + plane->colorkey.mode_property = mode_prop; + plane->colorkey.min_property = min_prop; + plane->colorkey.max_property = max_prop; + + return 0; + +err_destroy_min_prop: + drm_property_destroy(plane->dev, min_prop); +err_destroy_mode_prop: + drm_property_destroy(plane->dev, mode_prop); + + return -ENOMEM; +} +EXPORT_SYMBOL(drm_plane_create_colorkey_properties); diff --git a/include/drm/drm_blend.h b/include/drm/drm_blend.h index 330c561c4c11..8e80d33b643e 100644 --- a/include/drm/drm_blend.h +++ b/include/drm/drm_blend.h @@ -52,4 +52,7 @@ int drm_plane_create_zpos_immutable_property(struct drm_plane *plane, unsigned int zpos); int drm_atomic_normalize_zpos(struct drm_device *dev, struct drm_atomic_state *state); + +int drm_plane_create_colorkey_properties(struct drm_plane *plane, + u32 supported_modes); #endif diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 26fa50c2a50e..9a621e1ccc47 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -32,6 +32,48 @@ struct drm_crtc; struct drm_printer; struct drm_modeset_acquire_ctx; +/** + * enum drm_plane_colorkey_mode - uapi plane colorkey mode enumeration + */ +enum drm_plane_colorkey_mode { + /** + * @DRM_PLANE_COLORKEY_MODE_DISABLED: + * + * No color matching performed in this mode. + */ + DRM_PLANE_COLORKEY_MODE_DISABLED, + + /** + * @DRM_PLANE_COLORKEY_MODE_FOREGROUND_CLIP: + * + * This mode is also known as a "green screen". Plane pixels are + * transparent in areas where pixels match a given color key range + * and there is a bottom (background) plane, in other cases plane + * pixels are unaffected. + * + */ + DRM_PLANE_COLORKEY_MODE_FOREGROUND_CLIP, + + /** + * @DRM_PLANE_COLORKEY_MODES_NUM: + * + * Total number of color keying modes. + */ + DRM_PLANE_COLORKEY_MODES_NUM, +}; + +/** + * struct drm_plane_colorkey_state - plane color keying state + * @colorkey.mode: color keying mode + * @colorkey.min: color key range minimum (in ARGB16161616 format) + * @colorkey.max: color key range maximum (in ARGB16161616 format) + */ +struct drm_plane_colorkey_state { + enum drm_plane_colorkey_mode mode; + u64 min; + u64 max; +}; + /** * struct drm_plane_state - mutable plane state * @plane: backpointer to the plane @@ -54,6 +96,7 @@ struct drm_modeset_acquire_ctx; * where N is the number of active planes for given crtc. Note that * the driver must set drm_mode_config.normalize_zpos or call * drm_atomic_normalize_zpos() to update this before it can be trusted. + * @colorkey: colorkey state * @src: clipped source coordinates of the plane (in 16.16) * @dst: clipped destination coordinates of the plane * @state: backpointer to global drm_atomic_state @@ -124,6 +167,9 @@ struct drm_plane_state { unsigned int zpos; unsigned int normalized_zpos; + /* Plane colorkey */ + struct drm_plane_colorkey_state colorkey; + /** * @color_encoding: * @@ -510,6 +556,7 @@ enum drm_plane_type { * @alpha_property: alpha property for this plane * @zpos_property: zpos property for this plane * @rotation_property: rotation property for this plane + * @colorkey: colorkey properties for this plane * @helper_private: mid-layer private data */ struct drm_plane { @@ -587,6 +634,12 @@ struct drm_plane { struct drm_property *zpos_property; struct drm_property *rotation_property; + struct { + struct drm_property *mode_property; + struct drm_property *min_property; + struct drm_property *max_property; + } colorkey; + /** * @color_encoding_property: * 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; }