From patchwork Mon Nov 4 22:12:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Pietrasiewicz X-Patchwork-Id: 11226615 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3632D139A for ; Mon, 4 Nov 2019 22:12:49 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 14122214D8 for ; Mon, 4 Nov 2019 22:12:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="mQ0S8r/B" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 14122214D8 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=collabora.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=dikYD+l6/0/mjLlb16WoL/U4GhWTnkLRGP143u/rWtk=; b=mQ0S8r/BNkINFESTD4Z/c1+yIC Vs3nT8bHSNEbDrDsiONM1oJGWlAyd9CFn1IaTpdODfoNg4gC42A18FYFbRipjVSPy4/XXfmvygPj0 MQJ6nYEd+Z1JCGugSpdfdJYnCZg4dyaNccXjchfK2LC2meXcUxSM8KiAJqu0fXAcaErpO3NjgIJIg R1yA9072rbc2k/mJbef2h1StGeYn6eQHqcVKRSHBdF3g9KtnqHyv64mNEPOJFhPWgf9FH6XdOnhmu DXQn2k01v22HeofJnMH4M8vEw24EU3dbaeYMKwVDpOMg4WvOTS0yeCtvnDjmsLUxK8URIUWDBFTu9 drfrCaeQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1iRkab-0006wn-Rd; Mon, 04 Nov 2019 22:12:45 +0000 Received: from bhuna.collabora.co.uk ([2a00:1098:0:82:1000:25:2eeb:e3e3]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1iRkaV-0006rK-Do for linux-rockchip@lists.infradead.org; Mon, 04 Nov 2019 22:12:42 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: andrzej.p) with ESMTPSA id 0CE9128BA65 From: Andrzej Pietrasiewicz To: dri-devel@lists.freedesktop.org Subject: [PATCHv2 1/4] drm/arm: Factor out generic afbc helpers Date: Mon, 4 Nov 2019 23:12:25 +0100 Message-Id: <20191104221228.3588-2-andrzej.p@collabora.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191104221228.3588-1-andrzej.p@collabora.com> References: <2485717.1SzL54aMiy@e123338-lin> <20191104221228.3588-1-andrzej.p@collabora.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191104_141239_718983_6A0FDA25 X-CRM114-Status: GOOD ( 14.35 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay lines X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ayan Halder , kernel@collabora.com, =?utf-8?q?Heiko?= =?utf-8?q?_St=C3=BCbner?= , David Airlie , Maarten Lankhorst , Liviu Dudau , Sandy Huang , Maxime Ripard , linux-rockchip@lists.infradead.org, James Wang , Daniel Vetter , Mihail Atanassov , Sean Paul , Brian Starkey MIME-Version: 1.0 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org These are useful for other users of afbc, e.g. rockchip. Signed-off-by: Andrzej Pietrasiewicz --- drivers/gpu/drm/Kconfig | 8 +++ drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/arm/Kconfig | 1 + drivers/gpu/drm/drm_afbc.c | 129 ++++++++++++++++++++++++++++++++++++ include/drm/drm_afbc.h | 36 ++++++++++ 5 files changed, 175 insertions(+) create mode 100644 drivers/gpu/drm/drm_afbc.c create mode 100644 include/drm/drm_afbc.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 36357a36a281..ae1ca5e02bfe 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -205,6 +205,14 @@ config DRM_SCHED tristate depends on DRM +config DRM_AFBC + tristate + depends on DRM + help + AFBC is a proprietary lossless image compression protocol and format. + It provides fine-grained random access and minimizes the amount of + data transferred between IP blocks. + source "drivers/gpu/drm/i2c/Kconfig" source "drivers/gpu/drm/arm/Kconfig" diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 9f1c7c486f88..3a5d092ea514 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -31,6 +31,7 @@ drm-$(CONFIG_OF) += drm_of.o drm-$(CONFIG_AGP) += drm_agpsupport.o drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o +drm-$(CONFIG_DRM_AFBC) += drm_afbc.o drm_vram_helper-y := drm_gem_vram_helper.o \ drm_vram_helper_common.o diff --git a/drivers/gpu/drm/arm/Kconfig b/drivers/gpu/drm/arm/Kconfig index a204103b3efb..25c3dc408cda 100644 --- a/drivers/gpu/drm/arm/Kconfig +++ b/drivers/gpu/drm/arm/Kconfig @@ -29,6 +29,7 @@ config DRM_MALI_DISPLAY select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER + select DRM_AFBC select VIDEOMODE_HELPERS help Choose this option if you want to compile the ARM Mali Display diff --git a/drivers/gpu/drm/drm_afbc.c b/drivers/gpu/drm/drm_afbc.c new file mode 100644 index 000000000000..010ca9eb0480 --- /dev/null +++ b/drivers/gpu/drm/drm_afbc.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) 2019 Collabora Ltd. + * + * author: Andrzej Pietrasiewicz + * + */ +#include + +#include +#include +#include +#include +#include +#include + +#define AFBC_HEADER_SIZE 16 + +bool drm_afbc_check_offset(struct drm_device *dev, + const struct drm_mode_fb_cmd2 *mode_cmd) +{ + if (mode_cmd->offsets[0] != 0) { + DRM_DEBUG_KMS("AFBC buffers' plane offset should be 0\n"); + return false; + } + + return true; +} +EXPORT_SYMBOL_GPL(drm_afbc_check_offset); + +bool drm_afbc_check_size_align(struct drm_device *dev, + const struct drm_mode_fb_cmd2 *mode_cmd) +{ + switch (mode_cmd->modifier[0] & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) { + case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16: + if ((mode_cmd->width % 16) || (mode_cmd->height % 16)) { + DRM_DEBUG_KMS( + "AFBC buffer must be aligned to 16 pixels\n" + ); + return false; + } + break; + case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8: + /* fall through */ + case AFBC_FORMAT_MOD_BLOCK_SIZE_64x4: + /* fall through */ + case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4: + /* fall through */ + default: + DRM_DEBUG_KMS("Unsupported AFBC block size\n"); + return false; + } + + return true; +} +EXPORT_SYMBOL_GPL(drm_afbc_check_size_align); + +bool drm_afbc_get_superblk_wh(u64 modifier, u32 *w, u32 *h) +{ + switch (modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) { + case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16: + *w = 16; + *h = 16; + break; + case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8: + *w = 32; + *h = 8; + break; + case AFBC_FORMAT_MOD_BLOCK_SIZE_64x4: + /* fall through */ + case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4: + /* fall through */ + default: + DRM_DEBUG_KMS("Invalid AFBC_FORMAT_MOD_BLOCK_SIZE: %lld.\n", + modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK); + return false; + } + return true; +} +EXPORT_SYMBOL_GPL(drm_afbc_get_superblk_wh); + +bool drm_afbc_check_fb_size_ret(u32 pitch, int bpp, + u32 w, u32 h, u32 superblk_w, u32 superblk_h, + size_t size, u32 offset, u32 hdr_align, + u32 *payload_off, u32 *total_size) +{ + int n_superblks = 0; + u32 superblk_sz = 0; + u32 afbc_size = 0; + + n_superblks = (w / superblk_w) * (h / superblk_h); + superblk_sz = (bpp * superblk_w * superblk_h) / BITS_PER_BYTE; + afbc_size = ALIGN(n_superblks * AFBC_HEADER_SIZE, hdr_align); + *payload_off = afbc_size; + + afbc_size += n_superblks * ALIGN(superblk_sz, AFBC_SUPERBLK_ALIGNMENT); + *total_size = afbc_size + offset; + + if ((w * bpp) != (pitch * BITS_PER_BYTE)) { + DRM_DEBUG_KMS("Invalid value of (pitch * BITS_PER_BYTE) (=%u) should be same as width (=%u) * bpp (=%u)\n", + pitch * BITS_PER_BYTE, w, bpp + ); + return false; + } + + if (size < afbc_size) { + DRM_DEBUG_KMS("buffer size (%zu) too small for AFBC buffer size = %u\n", + size, afbc_size + ); + + return false; + } + + return true; +} +EXPORT_SYMBOL(drm_afbc_check_fb_size_ret); + +bool drm_afbc_check_fb_size(u32 pitch, int bpp, + u32 w, u32 h, u32 superblk_w, u32 superblk_h, + size_t size, u32 offset, u32 hdr_align) +{ + u32 payload_offset, total_size; + + return drm_afbc_check_fb_size_ret(pitch, bpp, w, h, + superblk_w, superblk_h, + size, offset, hdr_align, + &payload_offset, &total_size); +} +EXPORT_SYMBOL(drm_afbc_check_fb_size); diff --git a/include/drm/drm_afbc.h b/include/drm/drm_afbc.h new file mode 100644 index 000000000000..b28ae2849f96 --- /dev/null +++ b/include/drm/drm_afbc.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) 2019 Collabora Ltd. + * + * author: Andrzej Pietrasiewicz + * + */ +#ifndef __DRM_AFBC_H__ +#define __DRM_AFBC_H__ + +#include + +struct drm_device; +struct drm_mode_fb_cmd2; +struct drm_gem_object; + +#define AFBC_SUPERBLK_ALIGNMENT 128 + +bool drm_afbc_check_offset(struct drm_device *dev, + const struct drm_mode_fb_cmd2 *mode_cmd); + +bool drm_afbc_check_size_align(struct drm_device *dev, + const struct drm_mode_fb_cmd2 *mode_cmd); + +bool drm_afbc_check_fb_size_ret(u32 pitch, int bpp, + u32 w, u32 h, u32 superblk_w, u32 superblk_h, + size_t size, u32 offset, u32 hdr_align, + u32 *payload_off, u32 *total_size); + +bool drm_afbc_check_fb_size(u32 pitch, int bpp, + u32 w, u32 h, u32 superblk_w, u32 superblk_h, + size_t size, u32 offset, u32 hdr_align); + +bool drm_afbc_get_superblk_wh(u64 modifier, u32 *w, u32 *h); + +#endif /* __DRM_AFBC_H__ */ From patchwork Mon Nov 4 22:12:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Pietrasiewicz X-Patchwork-Id: 11226609 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 86D4F1515 for ; Mon, 4 Nov 2019 22:12:46 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 652D6214D9 for ; Mon, 4 Nov 2019 22:12:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="iyOp41IX" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 652D6214D9 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=collabora.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=5GO6A+/2xW7YWYusAJehfOqSQgKHmkZ8qL7bYZwhiB0=; b=iyOp41IXc+cNDLwSSk1xqGdMYE ahH3vrfZYDG1rIY4tk37rHFYF+ojd7ugwgiB4ARbR5ocWlto2O8CMt5w//yopev7Wjcf8rJZ1HyR3 /J42IFvgEItNqHRqiVQKPIG8aJGRetIlIsjqOIRN42AF5UeRR3xKGagAQ3Bgx4u3LWTXsLXf4Ic2V wn+xRTxGx3QRrFkE4heLq64zJQT0sZRwox46ljFBHSgoXre9Vd7XrYMzhCr+eAl8I5M0wUqJFjAKN LHlK5eQxsZx1SfMFts0xkNK1VItKSDVCYauiMTMSAsltAimI/CssNC9P39uIvOGz0n4lPrjQ7I/m8 CcKTnDCw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1iRkaZ-0006uA-6Q; Mon, 04 Nov 2019 22:12:43 +0000 Received: from bhuna.collabora.co.uk ([2a00:1098:0:82:1000:25:2eeb:e3e3]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1iRkaV-0006rO-RV for linux-rockchip@lists.infradead.org; Mon, 04 Nov 2019 22:12:41 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: andrzej.p) with ESMTPSA id D30DB28BA68 From: Andrzej Pietrasiewicz To: dri-devel@lists.freedesktop.org Subject: [PATCHv2 2/4] drm/malidp: use afbc helpers Date: Mon, 4 Nov 2019 23:12:26 +0100 Message-Id: <20191104221228.3588-3-andrzej.p@collabora.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191104221228.3588-1-andrzej.p@collabora.com> References: <2485717.1SzL54aMiy@e123338-lin> <20191104221228.3588-1-andrzej.p@collabora.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191104_141240_146783_EF2A625B X-CRM114-Status: GOOD ( 11.15 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay lines X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ayan Halder , kernel@collabora.com, =?utf-8?q?Heiko?= =?utf-8?q?_St=C3=BCbner?= , David Airlie , Maarten Lankhorst , Liviu Dudau , Sandy Huang , Maxime Ripard , linux-rockchip@lists.infradead.org, James Wang , Daniel Vetter , Mihail Atanassov , Sean Paul , Brian Starkey MIME-Version: 1.0 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org There are afbc helpers available. Signed-off-by: Andrzej Pietrasiewicz --- drivers/gpu/drm/arm/malidp_drv.c | 66 ++++++-------------------------- 1 file changed, 12 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 37d92a06318e..ab93588cc8eb 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -35,8 +36,6 @@ #include "malidp_hw.h" #define MALIDP_CONF_VALID_TIMEOUT 250 -#define AFBC_HEADER_SIZE 16 -#define AFBC_SUPERBLK_ALIGNMENT 128 static void malidp_write_gamma_table(struct malidp_hw_device *hwdev, u32 data[MALIDP_COEFFTAB_NUM_COEFFS]) @@ -277,24 +276,8 @@ malidp_verify_afbc_framebuffer_caps(struct drm_device *dev, mode_cmd->modifier[0]) == false) return false; - if (mode_cmd->offsets[0] != 0) { - DRM_DEBUG_KMS("AFBC buffers' plane offset should be 0\n"); - return false; - } - - switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) { - case AFBC_SIZE_16X16: - if ((mode_cmd->width % 16) || (mode_cmd->height % 16)) { - DRM_DEBUG_KMS("AFBC buffers must be aligned to 16 pixels\n"); - return false; - } - break; - default: - DRM_DEBUG_KMS("Unsupported AFBC block size\n"); - return false; - } - - return true; + return drm_afbc_check_offset(dev, mode_cmd) && + drm_afbc_check_size_align(dev, mode_cmd); } static bool @@ -302,54 +285,29 @@ malidp_verify_afbc_framebuffer_size(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd) { - int n_superblocks = 0; const struct drm_format_info *info; struct drm_gem_object *objs = NULL; - u32 afbc_superblock_size = 0, afbc_superblock_height = 0; - u32 afbc_superblock_width = 0, afbc_size = 0; int bpp = 0; - - switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) { - case AFBC_SIZE_16X16: - afbc_superblock_height = 16; - afbc_superblock_width = 16; - break; - default: - DRM_DEBUG_KMS("AFBC superblock size is not supported\n"); - return false; - } + u32 w, h; info = drm_get_format_info(dev, mode_cmd); - - n_superblocks = (mode_cmd->width / afbc_superblock_width) * - (mode_cmd->height / afbc_superblock_height); - bpp = malidp_format_get_bpp(info->format); - afbc_superblock_size = (bpp * afbc_superblock_width * afbc_superblock_height) - / BITS_PER_BYTE; - - afbc_size = ALIGN(n_superblocks * AFBC_HEADER_SIZE, AFBC_SUPERBLK_ALIGNMENT); - afbc_size += n_superblocks * ALIGN(afbc_superblock_size, AFBC_SUPERBLK_ALIGNMENT); - - if ((mode_cmd->width * bpp) != (mode_cmd->pitches[0] * BITS_PER_BYTE)) { - DRM_DEBUG_KMS("Invalid value of (pitch * BITS_PER_BYTE) (=%u) " - "should be same as width (=%u) * bpp (=%u)\n", - (mode_cmd->pitches[0] * BITS_PER_BYTE), - mode_cmd->width, bpp); - return false; - } - objs = drm_gem_object_lookup(file, mode_cmd->handles[0]); if (!objs) { DRM_DEBUG_KMS("Failed to lookup GEM object\n"); return false; } - if (objs->size < afbc_size) { - DRM_DEBUG_KMS("buffer size (%zu) too small for AFBC buffer size = %u\n", - objs->size, afbc_size); + if (!drm_afbc_get_superblk_wh(mode_cmd->modifier[0], &w, &h)) + return false; + + if (!drm_afbc_check_fb_size(mode_cmd->pitches[0], bpp, + mode_cmd->width, mode_cmd->height, w, h, + objs->size, mode_cmd->offsets[0], + AFBC_SUPERBLK_ALIGNMENT)) { drm_gem_object_put_unlocked(objs); + return false; } From patchwork Mon Nov 4 22:12:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Pietrasiewicz X-Patchwork-Id: 11226607 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6E61C1864 for ; Mon, 4 Nov 2019 22:12:45 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4C4AA214D8 for ; Mon, 4 Nov 2019 22:12:45 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="LbWYRusK" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4C4AA214D8 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=collabora.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=P/ua8U/yoTHUeHWAuGxbE6Uv3DgyUBRYIyijPAUOmgE=; b=LbWYRusKmA8RAn0H4w8cs/KrW8 aGCDvuNaoRB5U57Wpi6pW7G5DGUzb26n4g+/6TuGUUwGTN1Z2OK1CLDgqYbve8TnJ3gT4YbJusnuQ 2ZxXKdF3Gt6kyLj//xlccwaYSRCDvs3YGG1gx8EItGw/9QeqQjnBN/wfoWvZxHlwJXsULUtcA6xwJ kdwEBaQoFWSn1+RXSKjlnxxiHH7onAzKooMbKteHLl4gCuUvwjv8mvM7h2tMVhz/nNK6wWoieC9RI dVn8xWbQ+/lLbL6x4OcSUTX1UN5V11o0kRU2ZSGBFaDtck+zplYVdYbAUjs/d4p6iCeVcjbsxnz2a CHrITtFg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1iRkaY-0006tb-O3; Mon, 04 Nov 2019 22:12:42 +0000 Received: from bhuna.collabora.co.uk ([2a00:1098:0:82:1000:25:2eeb:e3e3]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1iRkaV-0006rS-E4 for linux-rockchip@lists.infradead.org; Mon, 04 Nov 2019 22:12:41 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: andrzej.p) with ESMTPSA id A420228BA72 From: Andrzej Pietrasiewicz To: dri-devel@lists.freedesktop.org Subject: [PATCHv2 3/4] drm/komeda: use afbc helpers Date: Mon, 4 Nov 2019 23:12:27 +0100 Message-Id: <20191104221228.3588-4-andrzej.p@collabora.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191104221228.3588-1-andrzej.p@collabora.com> References: <2485717.1SzL54aMiy@e123338-lin> <20191104221228.3588-1-andrzej.p@collabora.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191104_141239_729928_141C2538 X-CRM114-Status: GOOD ( 11.21 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay lines X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ayan Halder , kernel@collabora.com, =?utf-8?q?Heiko?= =?utf-8?q?_St=C3=BCbner?= , David Airlie , Maarten Lankhorst , Liviu Dudau , Sandy Huang , Maxime Ripard , linux-rockchip@lists.infradead.org, James Wang , Daniel Vetter , Mihail Atanassov , Sean Paul , Brian Starkey MIME-Version: 1.0 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org There are afbc helpers available. Signed-off-by: Andrzej Pietrasiewicz --- .../arm/display/komeda/komeda_format_caps.h | 1 - .../arm/display/komeda/komeda_framebuffer.c | 44 +++++++------------ 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h b/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h index 32273cf18f7c..607eea80e60c 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h +++ b/drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h @@ -33,7 +33,6 @@ #define AFBC_TH_LAYOUT_ALIGNMENT 8 #define AFBC_HEADER_SIZE 16 -#define AFBC_SUPERBLK_ALIGNMENT 128 #define AFBC_SUPERBLK_PIXELS 256 #define AFBC_BODY_START_ALIGNMENT 1024 #define AFBC_TH_BODY_START_ALIGNMENT 4096 diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c index 1b01a625f40e..e9c87551a5b8 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c @@ -4,6 +4,7 @@ * Author: James.Qian.Wang * */ +#include #include #include #include @@ -43,8 +44,7 @@ komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file, struct drm_framebuffer *fb = &kfb->base; const struct drm_format_info *info = fb->format; struct drm_gem_object *obj; - u32 alignment_w = 0, alignment_h = 0, alignment_header, n_blocks, bpp; - u64 min_size; + u32 alignment_w = 0, alignment_h = 0, alignment_header, bpp; obj = drm_gem_object_lookup(file, mode_cmd->handles[0]); if (!obj) { @@ -52,19 +52,15 @@ komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file, return -ENOENT; } - switch (fb->modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) { - case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8: - alignment_w = 32; - alignment_h = 8; - break; - case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16: - alignment_w = 16; - alignment_h = 16; - break; - default: - WARN(1, "Invalid AFBC_FORMAT_MOD_BLOCK_SIZE: %lld.\n", - fb->modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK); - break; + if (!drm_afbc_get_superblk_wh(fb->modifier, &alignment_w, &alignment_h)) + return -EINVAL; + + if ((alignment_w != 16 || alignment_h != 16) && + (alignment_w != 32 || alignment_h != 8)) { + DRM_DEBUG_KMS("Unsupported afbc tile w/h [%d/%d]\n", + alignment_w, alignment_h); + + return -EINVAL; } /* tiled header afbc */ @@ -84,20 +80,14 @@ komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file, goto check_failed; } - n_blocks = (kfb->aligned_w * kfb->aligned_h) / AFBC_SUPERBLK_PIXELS; - kfb->offset_payload = ALIGN(n_blocks * AFBC_HEADER_SIZE, - alignment_header); - bpp = komeda_get_afbc_format_bpp(info, fb->modifier); - kfb->afbc_size = kfb->offset_payload + n_blocks * - ALIGN(bpp * AFBC_SUPERBLK_PIXELS / 8, - AFBC_SUPERBLK_ALIGNMENT); - min_size = kfb->afbc_size + fb->offsets[0]; - if (min_size > obj->size) { - DRM_DEBUG_KMS("afbc size check failed, obj_size: 0x%zx. min_size 0x%llx.\n", - obj->size, min_size); + + if (!drm_afbc_check_fb_size(mode_cmd->pitches[0], bpp, + mode_cmd->width, mode_cmd->height, + alignment_w, alignment_h, + obj->size, mode_cmd->offsets[0], + AFBC_SUPERBLK_ALIGNMENT)) goto check_failed; - } fb->obj[0] = obj; return 0; From patchwork Mon Nov 4 22:12:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Pietrasiewicz X-Patchwork-Id: 11226617 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7AD881864 for ; Mon, 4 Nov 2019 22:12:49 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 56DA1204EC for ; Mon, 4 Nov 2019 22:12:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="gXLCnMzw" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 56DA1204EC Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=collabora.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=BNb/PkybqqvkTU+V+ooV0FFBewbmrfpj8sd5h9TseP0=; b=gXLCnMzw+IZ4EqqG4f/DWIrHl8 7f84PE4KZA1FawXbqn8BofbalMtkCxBoB9V15T6OezXxr4jYo1nE6V73dGhrU5iuXs9q4eHM00tys dzaWNDISWXHV5ivWeZkerF+Q1tn6ReS4RPCuhHaGi2L7+AExLgKGk5UN81qjYSixiG3MoEetecRy5 OJDcFqO0Tgzq+XZZKYFENR9QyCl8QqlPXvgIDshYmIs7hzqGt7HnHh2jSa/OPEf/9qYViNatPwbQz 2dFC3uvSQdVwaD+9FjiVSzQ2yNmZy1FmAHWC1vucSmCRWLLSq5v/U3KsbCuKIDj/oxIyFcIfaP82t sLm9B8QQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1iRkac-0006xn-Mo; Mon, 04 Nov 2019 22:12:46 +0000 Received: from bhuna.collabora.co.uk ([2a00:1098:0:82:1000:25:2eeb:e3e3]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1iRkaW-0006re-Au for linux-rockchip@lists.infradead.org; Mon, 04 Nov 2019 22:12:43 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: andrzej.p) with ESMTPSA id 7F69B28BC1E From: Andrzej Pietrasiewicz To: dri-devel@lists.freedesktop.org Subject: [PATCHv2 4/4] drm/rockchip: Add support for afbc Date: Mon, 4 Nov 2019 23:12:28 +0100 Message-Id: <20191104221228.3588-5-andrzej.p@collabora.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191104221228.3588-1-andrzej.p@collabora.com> References: <2485717.1SzL54aMiy@e123338-lin> <20191104221228.3588-1-andrzej.p@collabora.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191104_141240_652458_9BDAE2F0 X-CRM114-Status: GOOD ( 18.36 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay lines X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ayan Halder , kernel@collabora.com, =?utf-8?q?Heiko?= =?utf-8?q?_St=C3=BCbner?= , David Airlie , Maarten Lankhorst , Liviu Dudau , Sandy Huang , Maxime Ripard , linux-rockchip@lists.infradead.org, James Wang , Daniel Vetter , Mihail Atanassov , Sean Paul , Brian Starkey , Mark Yao MIME-Version: 1.0 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org This patch adds support for afbc handling. afbc is a compressed format which reduces the necessary memory bandwidth. Co-developed-by: Mark Yao Signed-off-by: Mark Yao Signed-off-by: Andrzej Pietrasiewicz --- drivers/gpu/drm/rockchip/Kconfig | 1 + drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 42 ++++++ drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 141 +++++++++++++++++++- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 12 ++ drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 84 +++++++++++- 5 files changed, 276 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 6f4222f8beeb..ff491efc52a5 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -5,6 +5,7 @@ config DRM_ROCKCHIP select DRM_GEM_CMA_HELPER select DRM_KMS_HELPER select DRM_PANEL + select DRM_AFBC select VIDEOMODE_HELPERS select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP select DRM_DW_HDMI if ROCKCHIP_DW_HDMI diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index ca01234c037c..0aac3e596df1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -18,6 +19,8 @@ #include "rockchip_drm_fb.h" #include "rockchip_drm_gem.h" +#define ROCKCHIP_MAX_AFBC_WIDTH 2560 + static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = { .destroy = drm_gem_fb_destroy, .create_handle = drm_gem_fb_create_handle, @@ -29,9 +32,48 @@ rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cm struct drm_gem_object **obj, unsigned int num_planes) { struct drm_framebuffer *fb; + u32 w, h; int ret; int i; + if (mode_cmd->modifier[0]) { + const struct drm_format_info *info; + int bpp; + + if (!drm_afbc_check_offset(dev, mode_cmd)) + return ERR_PTR(-EINVAL); + + if (!drm_afbc_get_superblk_wh(mode_cmd->modifier[0], &w, &h)) + return ERR_PTR(-EINVAL); + + if (w != 16 || h != 16) { + DRM_DEV_ERROR(dev->dev, + "Unsupported afbc tile w/h [%d/%d]\n", w, h); + return ERR_PTR(-EINVAL); + } + + if (!drm_afbc_check_size_align(dev, mode_cmd)) + return ERR_PTR(-EINVAL); + + if (mode_cmd->width > ROCKCHIP_MAX_AFBC_WIDTH) { + DRM_DEV_ERROR(dev->dev, + "Unsupported width %d>%d\n", + mode_cmd->width, + ROCKCHIP_MAX_AFBC_WIDTH + ); + + return ERR_PTR(-EINVAL); + } + + info = drm_get_format_info(dev, mode_cmd); + bpp = info->cpp[0] * 8; + + if (!drm_afbc_check_fb_size(mode_cmd->pitches[0], bpp, + mode_cmd->width, mode_cmd->height, w, h, obj[0]->size, + mode_cmd->offsets[0], AFBC_SUPERBLK_ALIGNMENT)) + return ERR_PTR(-EINVAL); + } + fb = kzalloc(sizeof(*fb), GFP_KERNEL); if (!fb) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index d04b3492bdac..e9ba72a4c4c6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -91,9 +91,22 @@ #define VOP_WIN_TO_INDEX(vop_win) \ ((vop_win) - (vop_win)->vop->win) +#define VOP_AFBC_SET(vop, name, v) \ + do { \ + if ((vop)->data->afbc) \ + vop_reg_set((vop), &(vop)->data->afbc->name, \ + 0, ~0, v, #name); \ + } while (0) + #define to_vop(x) container_of(x, struct vop, crtc) #define to_vop_win(x) container_of(x, struct vop_win, base) +#define AFBC_FMT_RGB565 0x0 +#define AFBC_FMT_U8U8U8U8 0x5 +#define AFBC_FMT_U8U8U8 0x4 + +#define AFBC_TILE_16x16 BIT(4) + /* * The coefficients of the following matrix are all fixed points. * The format is S2.10 for the 3x3 part of the matrix, and S9.12 for the offsets. @@ -166,6 +179,7 @@ struct vop { /* optional internal rgb encoder */ struct rockchip_rgb *rgb; + struct vop_win *afbc_win; struct vop_win win[]; }; @@ -274,6 +288,28 @@ static enum vop_data_format vop_convert_format(uint32_t format) } } +static int vop_convert_afbc_format(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ABGR8888: + return AFBC_FMT_U8U8U8U8; + case DRM_FORMAT_RGB888: + case DRM_FORMAT_BGR888: + return AFBC_FMT_U8U8U8; + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: + return AFBC_FMT_RGB565; + /* either of the below should not be reachable */ + default: + return -EINVAL; + } + + return -EINVAL; +} + static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src, uint32_t dst, bool is_horizontal, int vsu_mode, int *vskiplines) @@ -598,6 +634,15 @@ static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) vop_win_disable(vop, vop_win); } } + + if (vop->data->afbc) { + /* + * Disable AFBC and forget there was a vop window with AFBC + */ + VOP_AFBC_SET(vop, enable, 0); + vop->afbc_win = NULL; + } + spin_unlock(&vop->reg_lock); vop_cfg_done(vop); @@ -710,6 +755,34 @@ static void vop_plane_destroy(struct drm_plane *plane) drm_plane_cleanup(plane); } +static bool rockchip_mod_supported(struct drm_plane *plane, + u32 format, u64 modifier) +{ + const struct drm_format_info *info; + + if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID)) + return false; + + if (modifier == DRM_FORMAT_MOD_LINEAR) + return true; + + if (modifier != + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | + AFBC_FORMAT_MOD_SPARSE)) { + DRM_DEBUG_KMS("Unsupported format modifer 0x%llx\n", modifier); + + return false; + } + + info = drm_format_info(format); + if (info->num_planes != 1) { + DRM_DEBUG_KMS("AFBC buffers expect one plane\n"); + return false; + } + + return true; +} + static int vop_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { @@ -758,6 +831,34 @@ static int vop_plane_atomic_check(struct drm_plane *plane, return -EINVAL; } + if (fb->modifier == + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | + AFBC_FORMAT_MOD_SPARSE)) { + struct vop *vop = to_vop(crtc); + + if (!vop->data->afbc) { + DRM_ERROR("vop does not support AFBC\n"); + return -EINVAL; + } + + ret = vop_convert_afbc_format(fb->format->format); + if (ret < 0) + return ret; + + if (state->src.x1 || state->src.y1) { + DRM_ERROR("afbc does not support offset display\n"); + DRM_ERROR("xpos=%d, ypos=%d, offset=%d\n", + state->src.x1, state->src.y1, fb->offsets[0]); + return -EINVAL; + } + + if (state->rotation && state->rotation != DRM_MODE_ROTATE_0) { + DRM_ERROR("afbc does not support rotation\n"); + DRM_ERROR("rotation=%d\n", state->rotation); + return -EINVAL; + } + } + return 0; } @@ -773,6 +874,11 @@ static void vop_plane_atomic_disable(struct drm_plane *plane, spin_lock(&vop->reg_lock); vop_win_disable(vop, vop_win); + /* + * Forget about the AFBC window if it is being disabled + */ + if (vop_win == vop->afbc_win) + vop->afbc_win = NULL; spin_unlock(&vop->reg_lock); } @@ -812,6 +918,13 @@ static void vop_plane_atomic_update(struct drm_plane *plane, if (WARN_ON(!vop->is_enabled)) return; + /* + * If updating the AFBC window then assume that + * after the update there will be no AFBC window. + */ + if (vop_win == vop->afbc_win) + vop->afbc_win = NULL; + if (!state->visible) { vop_plane_atomic_disable(plane, old_state); return; @@ -846,6 +959,23 @@ static void vop_plane_atomic_update(struct drm_plane *plane, spin_lock(&vop->reg_lock); + if (fb->modifier == + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | + AFBC_FORMAT_MOD_SPARSE)) { + int afbc_format = vop_convert_afbc_format(fb->format->format); + + VOP_AFBC_SET(vop, format, afbc_format | AFBC_TILE_16x16); + VOP_AFBC_SET(vop, hreg_block_split, 0); + VOP_AFBC_SET(vop, win_sel, VOP_WIN_TO_INDEX(vop_win)); + VOP_AFBC_SET(vop, hdr_ptr, dma_addr); + VOP_AFBC_SET(vop, pic_size, act_info); + + /* + * The window being udated becomes the AFBC window + */ + vop->afbc_win = vop_win; + } + VOP_WIN_SET(vop, win, format, format); VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); @@ -1001,6 +1131,7 @@ static const struct drm_plane_funcs vop_plane_funcs = { .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, + .format_mod_supported = rockchip_mod_supported, }; static int vop_crtc_enable_vblank(struct drm_crtc *crtc) @@ -1340,6 +1471,10 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, spin_lock(&vop->reg_lock); + /* + * Enable AFBC if there is some AFBC window, disable otherwise + */ + VOP_AFBC_SET(vop, enable, vop->afbc_win != NULL); vop_cfg_done(vop); spin_unlock(&vop->reg_lock); @@ -1634,7 +1769,8 @@ static int vop_create_crtc(struct vop *vop) 0, &vop_plane_funcs, win_data->phy->data_formats, win_data->phy->nformats, - NULL, win_data->type, NULL); + win_data->phy->format_modifiers, + win_data->type, NULL); if (ret) { DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n", ret); @@ -1678,7 +1814,8 @@ static int vop_create_crtc(struct vop *vop) &vop_plane_funcs, win_data->phy->data_formats, win_data->phy->nformats, - NULL, win_data->type, NULL); + win_data->phy->format_modifiers, + win_data->type, NULL); if (ret) { DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n", ret); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 0b3d18c457b2..3f4e88a783d2 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -34,6 +34,16 @@ struct vop_reg { bool relaxed; }; +struct vop_afbc { + struct vop_reg enable; + struct vop_reg win_sel; + struct vop_reg format; + struct vop_reg hreg_block_split; + struct vop_reg pic_size; + struct vop_reg hdr_ptr; + struct vop_reg rstn; +}; + struct vop_modeset { struct vop_reg htotal_pw; struct vop_reg hact_st_end; @@ -134,6 +144,7 @@ struct vop_win_phy { const struct vop_scl_regs *scl; const uint32_t *data_formats; uint32_t nformats; + const uint64_t *format_modifiers; struct vop_reg enable; struct vop_reg gate; @@ -173,6 +184,7 @@ struct vop_data { const struct vop_misc *misc; const struct vop_modeset *modeset; const struct vop_output *output; + const struct vop_afbc *afbc; const struct vop_win_yuv2yuv_data *win_yuv2yuv; const struct vop_win_data *win; unsigned int win_size; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 7a9d979c8d5d..f0cf1b04591d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -50,6 +50,18 @@ static const uint32_t formats_win_full[] = { DRM_FORMAT_NV24, }; +static const uint64_t format_modifiers_win_full[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID, +}; + +static const uint64_t format_modifiers_win_full_afbc[] = { + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | + AFBC_FORMAT_MOD_SPARSE), + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID, +}; + static const uint32_t formats_win_lite[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, @@ -61,6 +73,11 @@ static const uint32_t formats_win_lite[] = { DRM_FORMAT_BGR565, }; +static const uint64_t format_modifiers_win_lite[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID, +}; + static const struct vop_scl_regs rk3036_win_scl = { .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), @@ -72,6 +89,7 @@ static const struct vop_win_phy rk3036_win0_data = { .scl = &rk3036_win_scl, .data_formats = formats_win_full, .nformats = ARRAY_SIZE(formats_win_full), + .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0), .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3), .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15), @@ -87,6 +105,7 @@ static const struct vop_win_phy rk3036_win0_data = { static const struct vop_win_phy rk3036_win1_data = { .data_formats = formats_win_lite, .nformats = ARRAY_SIZE(formats_win_lite), + .format_modifiers = format_modifiers_win_lite, .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1), .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6), .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19), @@ -153,6 +172,7 @@ static const struct vop_data rk3036_vop = { static const struct vop_win_phy rk3126_win1_data = { .data_formats = formats_win_lite, .nformats = ARRAY_SIZE(formats_win_lite), + .format_modifiers = format_modifiers_win_lite, .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1), .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6), .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19), @@ -234,6 +254,7 @@ static const struct vop_win_phy px30_win0_data = { .scl = &px30_win_scl, .data_formats = formats_win_full, .nformats = ARRAY_SIZE(formats_win_full), + .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(PX30_WIN0_CTRL0, 0x1, 0), .format = VOP_REG(PX30_WIN0_CTRL0, 0x7, 1), .rb_swap = VOP_REG(PX30_WIN0_CTRL0, 0x1, 12), @@ -249,6 +270,7 @@ static const struct vop_win_phy px30_win0_data = { static const struct vop_win_phy px30_win1_data = { .data_formats = formats_win_lite, .nformats = ARRAY_SIZE(formats_win_lite), + .format_modifiers = format_modifiers_win_lite, .enable = VOP_REG(PX30_WIN1_CTRL0, 0x1, 0), .format = VOP_REG(PX30_WIN1_CTRL0, 0x7, 4), .rb_swap = VOP_REG(PX30_WIN1_CTRL0, 0x1, 12), @@ -261,6 +283,7 @@ static const struct vop_win_phy px30_win1_data = { static const struct vop_win_phy px30_win2_data = { .data_formats = formats_win_lite, .nformats = ARRAY_SIZE(formats_win_lite), + .format_modifiers = format_modifiers_win_lite, .gate = VOP_REG(PX30_WIN2_CTRL0, 0x1, 4), .enable = VOP_REG(PX30_WIN2_CTRL0, 0x1, 0), .format = VOP_REG(PX30_WIN2_CTRL0, 0x3, 5), @@ -316,6 +339,7 @@ static const struct vop_win_phy rk3066_win0_data = { .scl = &rk3066_win_scl, .data_formats = formats_win_full, .nformats = ARRAY_SIZE(formats_win_full), + .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0), .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 4), .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 19), @@ -332,6 +356,7 @@ static const struct vop_win_phy rk3066_win1_data = { .scl = &rk3066_win_scl, .data_formats = formats_win_full, .nformats = ARRAY_SIZE(formats_win_full), + .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1), .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 7), .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 23), @@ -347,6 +372,7 @@ static const struct vop_win_phy rk3066_win1_data = { static const struct vop_win_phy rk3066_win2_data = { .data_formats = formats_win_lite, .nformats = ARRAY_SIZE(formats_win_lite), + .format_modifiers = format_modifiers_win_lite, .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2), .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 10), .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 27), @@ -426,6 +452,7 @@ static const struct vop_win_phy rk3188_win0_data = { .scl = &rk3188_win_scl, .data_formats = formats_win_full, .nformats = ARRAY_SIZE(formats_win_full), + .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 0), .format = VOP_REG(RK3188_SYS_CTRL, 0x7, 3), .rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 15), @@ -440,6 +467,7 @@ static const struct vop_win_phy rk3188_win0_data = { static const struct vop_win_phy rk3188_win1_data = { .data_formats = formats_win_lite, .nformats = ARRAY_SIZE(formats_win_lite), + .format_modifiers = format_modifiers_win_lite, .enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 1), .format = VOP_REG(RK3188_SYS_CTRL, 0x7, 6), .rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 19), @@ -545,6 +573,7 @@ static const struct vop_win_phy rk3288_win01_data = { .scl = &rk3288_win_full_scl, .data_formats = formats_win_full, .nformats = ARRAY_SIZE(formats_win_full), + .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), @@ -563,6 +592,7 @@ static const struct vop_win_phy rk3288_win01_data = { static const struct vop_win_phy rk3288_win23_data = { .data_formats = formats_win_lite, .nformats = ARRAY_SIZE(formats_win_lite), + .format_modifiers = format_modifiers_win_lite, .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4), .gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0), .format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1), @@ -677,6 +707,7 @@ static const struct vop_win_phy rk3368_win01_data = { .scl = &rk3288_win_full_scl, .data_formats = formats_win_full, .nformats = ARRAY_SIZE(formats_win_full), + .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0), .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1), .rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12), @@ -697,6 +728,7 @@ static const struct vop_win_phy rk3368_win01_data = { static const struct vop_win_phy rk3368_win23_data = { .data_formats = formats_win_lite, .nformats = ARRAY_SIZE(formats_win_lite), + .format_modifiers = format_modifiers_win_lite, .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0), .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4), .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5), @@ -817,6 +849,53 @@ static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = { .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9) }, { .base = 0xC0, .phy = &rk3399_yuv2yuv_win23_data }, { .base = 0x120, .phy = &rk3399_yuv2yuv_win23_data }, + +}; + +static const struct vop_win_phy rk3399_win01_data = { + .scl = &rk3288_win_full_scl, + .data_formats = formats_win_full, + .nformats = ARRAY_SIZE(formats_win_full), + .format_modifiers = format_modifiers_win_full_afbc, + .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), + .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), + .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), + .y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22), + .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), + .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), + .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), + .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), + .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), + .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), + .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), +}; + +/* + * rk3399 vop big windows register layout is same as rk3288, but we + * have a separate rk3399 win data array here so that we can advertise + * AFBC on the primary plane. + */ +static const struct vop_win_data rk3399_vop_win_data[] = { + { .base = 0x00, .phy = &rk3399_win01_data, + .type = DRM_PLANE_TYPE_PRIMARY }, + { .base = 0x40, .phy = &rk3288_win01_data, + .type = DRM_PLANE_TYPE_OVERLAY }, + { .base = 0x00, .phy = &rk3288_win23_data, + .type = DRM_PLANE_TYPE_OVERLAY }, + { .base = 0x50, .phy = &rk3288_win23_data, + .type = DRM_PLANE_TYPE_CURSOR }, +}; + +static const struct vop_afbc rk3399_vop_afbc = { + .rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3), + .enable = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0), + .win_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1), + .format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16), + .hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21), + .hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0), + .pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0), }; static const struct vop_data rk3399_vop_big = { @@ -826,9 +905,10 @@ static const struct vop_data rk3399_vop_big = { .common = &rk3288_common, .modeset = &rk3288_modeset, .output = &rk3399_output, + .afbc = &rk3399_vop_afbc, .misc = &rk3368_misc, - .win = rk3368_vop_win_data, - .win_size = ARRAY_SIZE(rk3368_vop_win_data), + .win = rk3399_vop_win_data, + .win_size = ARRAY_SIZE(rk3399_vop_win_data), .win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data, };