Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp699333imm; Sat, 26 May 2018 08:58:20 -0700 (PDT) X-Google-Smtp-Source: AB8JxZojOk2KQmZAJboWFaSCiK1b7xMKkPFzjCwz8wx6K/70d3oN8zlm90sZBAF89QiR/4tMdoIs X-Received: by 2002:a63:715d:: with SMTP id b29-v6mr5464542pgn.325.1527350300589; Sat, 26 May 2018 08:58:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527350300; cv=none; d=google.com; s=arc-20160816; b=s6jsDpXn3S0iSTNO39q1oBMH4GNV7nKyrHjWNlUtDk7NTPUUNEROqya+Xk1YBgPKcT B6BgNRZM4i+gESxWLKcqmarJIQ0R4dbD/tMcP2DKMdKMlNpeMRHiPDLYkKGrIL0ihgPK BwoUeep9m9rlPbgKeRSHd9pXPiR65j3sskLb+u/ukzRX8qhfg18SeegpxAQ8xkRt4LFh j3Cg8j8QCXvQnoa8W6aJaNNXD/gBfWFCPKwrCl0p+liNWDHJ4BWISCF5diK621RC6OnE htXNHLOKNsIkUhkfM1nKehXQDGRNEujoFW1pWNvSBvWBigX63m/piZaz//UoBkGZxiWw TUlQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=AfbmA4XXBSErzGN+oVE+PXRmsMaZB7ea0kS9W/9u5Ls=; b=Dulr4xjy+ohdCYw65nQ8UVcvo+BUASJ1KgrNpYlaEY2MspTDffubiALfbAc98Cwo7C S5Co4GTmjRZP12jUON1itUtFl/wXgUOsDwtrsu1ttX5eBXNw4kEuunAhtD5GVaXFZf5B k1bJ4ANwupzgO70/biNTdfrg5gkb1SBWW5UoanmIpFU9l36uLN8NDUxSowVGgJ9oKi99 zk2YzbER2HXpXAO93Z2TLh4YRHZWsUVT+uu+sZhTd1ZFePei/ndvqLqFQez09P92bxOT nZAiJ5C8C3mDbg1oZvqBtghGRgXF9ZbeAyozEgVFfv0q0e0dXhbF6jrQ4ypk9uBrGT6o hfUg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=jjRtZUa8; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v69-v6si204767pgd.499.2018.05.26.08.58.02; Sat, 26 May 2018 08:58:20 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=jjRtZUa8; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1032125AbeEZP5v (ORCPT + 99 others); Sat, 26 May 2018 11:57:51 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:37344 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1032050AbeEZP5r (ORCPT ); Sat, 26 May 2018 11:57:47 -0400 Received: by mail-wm0-f67.google.com with SMTP id l1-v6so21892401wmb.2; Sat, 26 May 2018 08:57:46 -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=AfbmA4XXBSErzGN+oVE+PXRmsMaZB7ea0kS9W/9u5Ls=; b=jjRtZUa859xogtK1lh/MvdS2luAD+vXKy9Mq5hbOVKZVy/AIBzkvNXXAQwShtza5E8 7+o5OX4VuCAtTqvwrJm9XVNDM29VnkYwEPyrUr9JoqCW1sTEGij5Dp7qyqG5XCDVwyVP udR4pe5ore4n9E/8Fj4PrXTnNkphElOvcEDGG45Q6bgWQ7ySW0fapZRfaTcLtmBIlr0m vkIFRhKC+sCgdXq/Avw0Gw5eohqvHsuAPVSJBhA8JJRjfbynx8jccBr/e7h/PDToeJ5R R8eWVAuO4DaBY7HNs14ooHhv8WboiDNygr4bJtupauWzlrZ7D6XyeBQHqUT/TAmINXLA ZqYA== 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=AfbmA4XXBSErzGN+oVE+PXRmsMaZB7ea0kS9W/9u5Ls=; b=cRAt710Sbgtd4aonZ4BaM8LbhjDtizqZsENWvEYff3Py5Ar07jsw7kOYbZJt536UvF cQsJneAh/61BGMyhA6Gn0/i6gHcUa+2R3urqdo0jEDnehlTHiZn62f2k+t+ahA8TGzyX 4wBZMuogf4OWFYBU7tJBePpGUClLTSG6SvNCJKXjOkk26w1Fcsej7BWlghOjSSw0PbOi eSHlS0N+r0TUfrJ1zJAIzfRVVP4xSfQbjAQaRa2fRcUsvRsUrBfO8TEMViB2xS8nDw7k tWi1pYsvh4KLEgJaMZafRSbNjxP54wniq0dFYxQMMyGf9zcGAQLTQoiQbZWFthw7CdmW e9CQ== X-Gm-Message-State: ALKqPwe3PHmCV5cJ+teKbHzkt3nLQyU7tC8+Pp32exy3vctRqu/MOaUy C1iSEFpIoGVDTXKouxMcIa8= X-Received: by 2002:a2e:93cf:: with SMTP id p15-v6mr4366145ljh.30.1527350265498; Sat, 26 May 2018 08:57:45 -0700 (PDT) Received: from localhost.localdomain (109-252-91-41.nat.spd-mgts.ru. [109.252.91.41]) by smtp.gmail.com with ESMTPSA id k23-v6sm2571010ljh.27.2018.05.26.08.57.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 26 May 2018 08:57:44 -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 Cc: linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Alexandru Gheorghe , 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 v2 2/2] drm/tegra: plane: Implement generic colorkey property for older Tegra's Date: Sat, 26 May 2018 18:56:23 +0300 Message-Id: <20180526155623.12610-3-digetx@gmail.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180526155623.12610-1-digetx@gmail.com> References: <20180526155623.12610-1-digetx@gmail.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Color keying allows to draw on top of overlapping planes, like for example on top of a video plane. Older Tegra's have a limited color keying capability, such that blending features are reduced when color keying is enabled. In particular dependent weighting isn't possible, meaning that cursors plane can't be displayed properly. In most cases it is more useful to display content on top of video overlay, so sacrificing mouse cursor in the area of three planes intersection with colorkey mismatch is a reasonable tradeoff. This patch implements the generic DRM colorkey property. For the starter a minimal color keying support is implemented, it 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 | 31 +++++++ drivers/gpu/drm/tegra/dc.h | 7 ++ drivers/gpu/drm/tegra/plane.c | 147 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/tegra/plane.h | 1 + 4 files changed, 186 insertions(+) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 31e12a9dfcb8..a5add64e40e2 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -172,6 +172,11 @@ static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane) state = to_tegra_plane_state(plane->base.state); + if (state->ckey_enabled) { + background[0] |= BLEND_COLOR_KEY_0; + background[2] |= BLEND_COLOR_KEY_0; + } + if (state->opaque) { /* * Since custom fix-weight blending isn't utilized and weight @@ -776,6 +781,11 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm, drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs); drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255); + if (dc->soc->has_legacy_blending) + drm_plane_create_colorkey_properties(&plane->base, + BIT(DRM_PLANE_COLORKEY_MODE_DISABLED) | + BIT(DRM_PLANE_COLORKEY_MODE_DST)); + return &plane->base; } @@ -1053,6 +1063,11 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs); drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255); + if (dc->soc->has_legacy_blending) + drm_plane_create_colorkey_properties(&plane->base, + BIT(DRM_PLANE_COLORKEY_MODE_DISABLED) | + BIT(DRM_PLANE_COLORKEY_MODE_DST)); + return &plane->base; } @@ -1153,6 +1168,7 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc) { struct tegra_dc_state *state = to_dc_state(crtc->state); struct tegra_dc_state *copy; + unsigned int i; copy = kmalloc(sizeof(*copy), GFP_KERNEL); if (!copy) @@ -1164,6 +1180,9 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc) copy->div = state->div; copy->planes = state->planes; + for (i = 0; i < 2; i++) + copy->ckey[i] = state->ckey[i]; + return ©->base; } @@ -1893,6 +1912,18 @@ 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[0].lower, DC_DISP_COLOR_KEY0_LOWER); + tegra_dc_writel(dc, + state->ckey[0].upper, DC_DISP_COLOR_KEY0_UPPER); + + tegra_dc_writel(dc, + state->ckey[1].lower, DC_DISP_COLOR_KEY1_LOWER); + tegra_dc_writel(dc, + state->ckey[1].upper, DC_DISP_COLOR_KEY1_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..8209cb7d598a 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 lower; + u32 upper; +}; + 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[2]; }; 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 0406c2ef432c..ba08b66d2499 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c @@ -57,6 +57,7 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane) copy->format = state->format; copy->swap = state->swap; copy->opaque = state->opaque; + copy->ckey_enabled = state->ckey_enabled; for (i = 0; i < 2; i++) copy->blending[i] = state->blending[i]; @@ -464,6 +465,148 @@ static int tegra_plane_setup_transparency(struct tegra_plane *tegra, return 0; } +static int tegra_plane_setup_colorkey(struct tegra_plane *tegra, + struct tegra_plane_state *tegra_state) +{ + struct drm_plane_state *state; + struct drm_plane_state *new_plane; + struct drm_plane_state *old_plane; + struct drm_crtc_state *crtc_state; + struct drm_crtc_state *new_crtc; + struct tegra_dc_state *dc_state; + struct drm_plane *plane; + unsigned int mode; + u32 min, max; + u32 format; + + /* at first check if plane has the colorkey property attached */ + if (!tegra->base.colorkey.mode_property) + return 0; + + format = tegra_state->base.colorkey.format; + mode = tegra_state->base.colorkey.mode; + min = tegra_state->base.colorkey.min; + max = tegra_state->base.colorkey.max; + + state = &tegra_state->base; + old_plane = drm_atomic_get_old_plane_state(state->state, &tegra->base); + + /* no need to proceed if color keying is (and was) disabled */ + if (mode == DRM_PLANE_COLORKEY_MODE_DISABLED && + (!old_plane || old_plane->colorkey.mode == mode)) + return 0; + + /* + * Currently color keying implemented only for the middle plane + * to simplify things, hence check the ordering. + */ + if (state->normalized_zpos != 1) { + if (mode == DRM_PLANE_COLORKEY_MODE_DISABLED) + goto update_planes; + + return -EINVAL; + } + + /* validate the color key mode */ + if (mode != DRM_PLANE_COLORKEY_MODE_DST) + return -EINVAL; + + /* validate the color key mask */ + if ((state->colorkey.mask & 0xFFFFFF) != 0xFFFFFF) + return -EINVAL; + + /* validate the replacement mask */ + if (state->colorkey.replacement_mask != 0) + return -EINVAL; + + /* validate the color key inversion mode */ + if (state->colorkey.inverted_match != true) + return -EINVAL; + + /* + * There is no need to proceed, adding CRTC and other planes to + * the atomic update, if color key value is unchanged. + */ + if (old_plane && + old_plane->colorkey.mode != DRM_PLANE_COLORKEY_MODE_DISABLED && + old_plane->colorkey.format == format && + old_plane->colorkey.min == min && + old_plane->colorkey.max == max) + return 0; + + /* validate pixel format and convert color key value if necessary */ + switch (format) { + case DRM_FORMAT_XBGR8888: +#define XBGR8888_to_XRGB8888(v) \ + ((((v) & 0xFF0000) >> 16) | ((v) & 0x00FF00) | (((v) & 0x0000FF) << 16)) + + min = XBGR8888_to_XRGB8888(min); + max = XBGR8888_to_XRGB8888(max); + break; + + case DRM_FORMAT_XRGB8888: + break; + + default: + return -EINVAL; + } + + /* + * Tegra's HW stores the 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); + + new_crtc = drm_atomic_get_new_crtc_state(state->state, state->crtc); + if (IS_ERR(new_crtc)) + return PTR_ERR(new_crtc); + + dc_state = to_dc_state(new_crtc); + + /* update CRTC's color key state */ + dc_state->ckey[0].lower = min; + dc_state->ckey[0].upper = max; + +update_planes: + /* + * Currently the only supported color keying mode is + * "dst-match-src-replace", i.e. in our case the actual matching + * is performed by the underlying plane. Hence setup the color + * matching for that plane and update other planes by including + * them into the atomic update. + */ + drm_for_each_plane(plane, tegra->base.dev) { + struct tegra_plane *p = to_tegra_plane(plane); + + /* skip this plane and planes on different CRTCs */ + if (p == tegra || p->dc != tegra->dc) + continue; + + state = drm_atomic_get_plane_state(state->state, plane); + if (IS_ERR(state)) + return PTR_ERR(state); + + new_plane = drm_atomic_get_new_plane_state(state->state, plane); + tegra_state = to_tegra_plane_state(new_plane); + + /* skip planes hovering this plane */ + if (new_plane->normalized_zpos > 1) { + tegra_state->ckey_enabled = false; + continue; + } + + /* update planes color keying state */ + if (mode == DRM_PLANE_COLORKEY_MODE_DISABLED) + tegra_state->ckey_enabled = false; + else + tegra_state->ckey_enabled = true; + } + + return 0; +} + int tegra_plane_setup_legacy_state(struct tegra_plane *tegra, struct tegra_plane_state *state) { @@ -477,5 +620,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; } diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h index 7360ddfafee8..617f57d98135 100644 --- a/drivers/gpu/drm/tegra/plane.h +++ b/drivers/gpu/drm/tegra/plane.h @@ -49,6 +49,7 @@ struct tegra_plane_state { /* used for legacy blending support only */ struct tegra_plane_legacy_blending_state blending[2]; bool opaque; + bool ckey_enabled; }; static inline struct tegra_plane_state * -- 2.17.0