From patchwork Thu Feb 6 06:44:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962413 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id BB197C02196 for ; Thu, 6 Feb 2025 06:56:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Hb7svM5NGaJUgDwejzeozfATEsxZUDxfe8P5HH4XeBw=; b=jM0ZFkcov6pxq7 hEEwbNHki1BtztYLeIjCitBODDuUEezKeyl8GtjWIgN9tp1hs1qmXfvlJ9OrJN5HMV7qC3IzqxLdF hRPya4Jczxs961rRaOTovupXFlsBKFx7EiPyPsq/JhrC/B6S9RWHL7huB8GAPaoEeIBtO5xUndG7s lICflprtRNVmBoWX9lT8Z/KiGJlqhm3nqQ9fei0cjCiR9sl3zyJ6+yeRCoU1z558l3m3lBkRaNie7 o13YDy4w/CD8/WojUvxQ572MJL2ZlKvPzu3VMUF/scJ/CeLhks8W/obWAqe/PlUK2BVXnkMlpfbRb QGEH59LzpWHS7dvKRWwQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvol-00000005TM1-2iJO; Thu, 06 Feb 2025 06:56:55 +0000 Received: from m16.mail.163.com ([117.135.210.5]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvdp-00000005Q92-0uxu; Thu, 06 Feb 2025 06:45:40 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=mNO50 0sNfrFBXq6NhgMe/UQ/zvJtR1wiByIe/1AQOgo=; b=bU+YVAYq5Rvja1cZToram i+cYZwAJ95rUXF0tGJwONBvL5Y7fK+n0GqGuAtuBMyXmBEtdjzzh3Xoh/8JrPigK 0LLQYb8mpjQptJRDVRnlOziQphoXBsPb0CQ8OKEFz8iRFeY0Y/VakUzEw8J8/Ocj 24a8KRBAQ65XwzXsFU34ao= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-0 (Coremail) with SMTP id _____wD3fyNsWqRnb3bDKQ--.52146S3; Thu, 06 Feb 2025 14:45:05 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan Subject: [PATCH v13 01/13] drm/rockchip: vop2: use devm_regmap_field_alloc for cluster-regs Date: Thu, 6 Feb 2025 14:44:29 +0800 Message-ID: <20250206064457.11396-2-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3fyNsWqRnb3bDKQ--.52146S3 X-Coremail-Antispam: 1Uf129KBjvJXoWxGFW7GFWUWrykJr4fGF17Wrg_yoWrZr4xpF 4rCwnxuF45Grn29rykAr1DAF1Fk397ta1rCFn7uwnI9rnFgrZ7C3WDCw1jyrs0kryv9F9r tFsxt39xua4Ygr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jb9N3UUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/xtbB0h3rXmekTP7+PQAAsI X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224537_688618_BBFD63F7 X-CRM114-Status: GOOD ( 14.03 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Heiko Stuebner Right now vop2_cluster_init() copies the base vop2_cluster_regs and adapts the reg value with the current window's offset before adding the fields to the regmap. This conflicts with the notion of reg_fields being const, see https://lore.kernel.org/all/20240706-regmap-const-structs-v1-1-d08c776da787@weissschuh.net/ for reference, which now causes checkpatch to actually warn about that. So instead of creating one big copy and changing it afterwards, add the reg_fields individually using devm_regmap_field_alloc(). Functional it is the same, just that the reg_field we're handling can stay const. Signed-off-by: Heiko Stuebner Signed-off-by: Andy Yan --- (no changes since v1) drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 66 +++++++++----------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 17a98845fd31..03248ac4ba4a 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -3372,7 +3372,7 @@ static int vop2_find_rgb_encoder(struct vop2 *vop2) return -ENOENT; } -static struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = { +static const struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = { [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0), [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5), [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14), @@ -3443,28 +3443,26 @@ static struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = { static int vop2_cluster_init(struct vop2_win *win) { struct vop2 *vop2 = win->vop2; - struct reg_field *cluster_regs; - int ret, i; - - cluster_regs = kmemdup(vop2_cluster_regs, sizeof(vop2_cluster_regs), - GFP_KERNEL); - if (!cluster_regs) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(vop2_cluster_regs); i++) - if (cluster_regs[i].reg != 0xffffffff) - cluster_regs[i].reg += win->offset; + int i; - ret = devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg, - cluster_regs, - ARRAY_SIZE(vop2_cluster_regs)); + for (i = 0; i < ARRAY_SIZE(vop2_cluster_regs); i++) { + const struct reg_field field = { + .reg = (vop2_cluster_regs[i].reg != 0xffffffff) ? + vop2_cluster_regs[i].reg + win->offset : + vop2_cluster_regs[i].reg, + .lsb = vop2_cluster_regs[i].lsb, + .msb = vop2_cluster_regs[i].msb + }; - kfree(cluster_regs); + win->reg[i] = devm_regmap_field_alloc(vop2->dev, vop2->map, field); + if (IS_ERR(win->reg[i])) + return PTR_ERR(win->reg[i]); + } - return ret; + return 0; }; -static struct reg_field vop2_esmart_regs[VOP2_WIN_MAX_REG] = { +static const struct reg_field vop2_esmart_regs[VOP2_WIN_MAX_REG] = { [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0), [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5), [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12), @@ -3531,26 +3529,24 @@ static struct reg_field vop2_esmart_regs[VOP2_WIN_MAX_REG] = { static int vop2_esmart_init(struct vop2_win *win) { struct vop2 *vop2 = win->vop2; - struct reg_field *esmart_regs; - int ret, i; - - esmart_regs = kmemdup(vop2_esmart_regs, sizeof(vop2_esmart_regs), - GFP_KERNEL); - if (!esmart_regs) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(vop2_esmart_regs); i++) - if (esmart_regs[i].reg != 0xffffffff) - esmart_regs[i].reg += win->offset; + int i; - ret = devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg, - esmart_regs, - ARRAY_SIZE(vop2_esmart_regs)); + for (i = 0; i < ARRAY_SIZE(vop2_esmart_regs); i++) { + const struct reg_field field = { + .reg = (vop2_esmart_regs[i].reg != 0xffffffff) ? + vop2_esmart_regs[i].reg + win->offset : + vop2_esmart_regs[i].reg, + .lsb = vop2_esmart_regs[i].lsb, + .msb = vop2_esmart_regs[i].msb + }; - kfree(esmart_regs); + win->reg[i] = devm_regmap_field_alloc(vop2->dev, vop2->map, field); + if (IS_ERR(win->reg[i])) + return PTR_ERR(win->reg[i]); + } - return ret; -}; + return 0; +} static int vop2_win_init(struct vop2 *vop2) { From patchwork Thu Feb 6 06:44:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962335 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 2E586C0219B for ; Thu, 6 Feb 2025 06:48:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=5wzySRwqK43x9ga7ur+M7JsUyZ0yuK1o5lgtUR9iUCw=; b=Jxh6lhn1l5GJtm SV5vRbqoZyLPA2xbDftDrTgAt/mt5eEzkVSQXsonD+QJSpMAlh9J9aQqY5Lpxgoa2pF+2KMjEVGsG OZhrABFDwaADeiMUxCD4pMy39Lz4rjJGMXnM96SgeICSfizFxQpvsJ1LIuSdCKeqYuSQHJaJayxNW eH8nKEGkeCCs/aIFeUrUiFQ9ByWzicbbDM/iRjmo9WxfcX59ldeQrJNe8Gtgz6R3tR1Gp6VqYytpt NpyPgzaOXQYiBJ0Wot5FFUCR4zYEBhE13w82Qn0ZKiOtiLsXbFgEqO9hA92/13qtsDkWliJRI8cWS dwqDpaAhgNqAX2tT1vEA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvga-00000005RFT-16qz; Thu, 06 Feb 2025 06:48:28 +0000 Received: from m16.mail.163.com ([220.197.31.5]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvdo-00000005Q8T-1qVJ; Thu, 06 Feb 2025 06:45:37 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=Aj3p5 YEkL2Je1AnEdaQQ2QACpF4/wWQgDcT/1GT+BA4=; b=CPKIGk+Plw5na6v3mt06O 2UPPckbUxCBkKaVYL6zoa0SQqfUhdHKAPa2EcwoKac0jqWrJy+sznRkESXi9Hxf8 qUKArOqp1fDINFe9fGtr/bZyqYlFPR7agtltexLen63GU8y38UyFyseBebraW4pZ Yp7LSvPi1V7AbYx0KlRJPA= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-0 (Coremail) with SMTP id _____wD3fyNsWqRnb3bDKQ--.52146S4; Thu, 06 Feb 2025 14:45:06 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan Subject: [PATCH v13 02/13] drm/rockchip: vop2: Rename TRANSFORM_OFFSET to TRANSFORM_OFFS Date: Thu, 6 Feb 2025 14:44:30 +0800 Message-ID: <20250206064457.11396-3-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3fyNsWqRnb3bDKQ--.52146S4 X-Coremail-Antispam: 1Uf129KBjvJXoWxCrWxKw4rJw15Jr18uw17Wrg_yoWrCr18pr W3JayDWF4UKFs2gFWkAr15AF48Xan2y3yfGa9xJrnIqFyaga4DWwnFka4UJr4Uta4I9FZ2 q3saqrW7urW3tr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jYtC7UUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqRnrXmekUdSnkAAAs0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224536_863313_5DAF8309 X-CRM114-Status: GOOD ( 10.87 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Andy Yan This help avoid "exceeds 100 columns" warning from checkpatch Signed-off-by: Andy Yan --- (no changes since v1) drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 8 ++++---- drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 03248ac4ba4a..5ee8a7b86d0b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1517,7 +1517,7 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, transform_offset = vop2_afbc_transform_offset(pstate, half_block_en); vop2_win_write(win, VOP2_WIN_AFBC_HDR_PTR, yrgb_mst); vop2_win_write(win, VOP2_WIN_AFBC_PIC_SIZE, act_info); - vop2_win_write(win, VOP2_WIN_AFBC_TRANSFORM_OFFSET, transform_offset); + vop2_win_write(win, VOP2_WIN_AFBC_TRANSFORM_OFFS, transform_offset); vop2_win_write(win, VOP2_WIN_AFBC_PIC_OFFSET, ((src->x1 >> 16) | src->y1)); vop2_win_write(win, VOP2_WIN_AFBC_DSP_OFFSET, (dest->x1 | (dest->y1 << 16))); vop2_win_write(win, VOP2_WIN_AFBC_PIC_VIR_WIDTH, stride); @@ -1528,7 +1528,7 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, } else { if (vop2_cluster_window(win)) { vop2_win_write(win, VOP2_WIN_AFBC_ENABLE, 0); - vop2_win_write(win, VOP2_WIN_AFBC_TRANSFORM_OFFSET, 0); + vop2_win_write(win, VOP2_WIN_AFBC_TRANSFORM_OFFS, 0); } vop2_win_write(win, VOP2_WIN_YRGB_VIR, DIV_ROUND_UP(fb->pitches[0], 4)); @@ -3420,7 +3420,7 @@ static const struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = { [VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31), [VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31), [VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31), - [VOP2_WIN_AFBC_TRANSFORM_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET, 0, 31), + [VOP2_WIN_AFBC_TRANSFORM_OFFS] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFS, 0, 31), [VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0), [VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1), [VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2), @@ -3519,7 +3519,7 @@ static const struct reg_field vop2_esmart_regs[VOP2_WIN_MAX_REG] = { [VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff }, [VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff }, [VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_TRANSFORM_OFFSET] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_TRANSFORM_OFFS] = { .reg = 0xffffffff }, [VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff }, [VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff }, [VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff }, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h index 29cc7fb8f6d8..8510140b0869 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h @@ -118,7 +118,7 @@ enum vop2_win_regs { VOP2_WIN_AFBC_PIC_OFFSET, VOP2_WIN_AFBC_PIC_SIZE, VOP2_WIN_AFBC_DSP_OFFSET, - VOP2_WIN_AFBC_TRANSFORM_OFFSET, + VOP2_WIN_AFBC_TRANSFORM_OFFS, VOP2_WIN_AFBC_HDR_PTR, VOP2_WIN_AFBC_HALF_BLOCK_EN, VOP2_WIN_AFBC_ROTATE_270, @@ -335,7 +335,7 @@ enum dst_factor_mode { #define RK3568_CLUSTER_WIN_DSP_INFO 0x24 #define RK3568_CLUSTER_WIN_DSP_ST 0x28 #define RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB 0x30 -#define RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET 0x3C +#define RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFS 0x3C #define RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL 0x50 #define RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE 0x54 #define RK3568_CLUSTER_WIN_AFBCD_HDR_PTR 0x58 From patchwork Thu Feb 6 06:44:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962419 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id B4A67C02196 for ; Thu, 6 Feb 2025 07:01:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=78kfw6H8crq+EH+kq4/vFxaV3Zqzt9HPFoG+v9aQ8Vk=; b=mHa7pPIupd4NzT UkFaHHIJkjDjhW6ba/0mB34tK0LV+9N/7vb40uAStwTkF+GyPn9fKeLrK9oD0tPA7yqgznJdF//ah i/KacXS7SRVVU5/FTsYRfrOdJOGzBy1YY4yiQKF05PAQKEGOG/FDxnirAZjSiRuLMGSgBCsSXTHSG 04snC/0/jNHRwQ0e+d4jcnFI3H9SHTB2nMv8d6hQRiDty/+No8Q8MV/esinFoYA6w1Dcf+ty9Ble0 8i3I94erubgltqaOky0FHXUZwDFOFm5hk8ZZDmkJeMr5b4p7+v8Ultm53KL4HnvyNHgnCm3wYI+LG LmuOJvmO9nXHtnZMsbjQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvss-00000005U73-061t; Thu, 06 Feb 2025 07:01:10 +0000 Received: from m16.mail.163.com ([117.135.210.5]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvdo-00000005Q8R-2EdX; Thu, 06 Feb 2025 06:45:41 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=hFmd4 HsN73Oh3Zpa5Inh7xmX+U75IqXilayxiR0R9QY=; b=Od9zHSpfoGj0RPQm7xbj8 NKJD+F+LvNwKHr7zPLsFAplvLLUOmTeNRUMJwCxoWkKo5Qp1ySvgQL4AdVpeLoO9 DTeLObdX4Go/SZWKrOPhYyO7WhpgEwiZFmf6d59v5CBemxQd6nZUP+VTGpuEqULl SRqB+us0MYkpbTETVKp/+M= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-0 (Coremail) with SMTP id _____wD3fyNsWqRnb3bDKQ--.52146S5; Thu, 06 Feb 2025 14:45:07 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan , Michael Riesch Subject: [PATCH v13 03/13] drm/rockchip: vop2: Add platform specific callback Date: Thu, 6 Feb 2025 14:44:31 +0800 Message-ID: <20250206064457.11396-4-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3fyNsWqRnb3bDKQ--.52146S5 X-Coremail-Antispam: 1Uf129KBjvAXoWDtFWDJF4kJw4UJw1kXw4fKrg_yoWfZw1kKo W7uF1Fqr4Iqw1Fg39rWr17XFy7W348Can7Cr17XFnxZ39xX3yjkF92q3ZrtF17Jr15Cay5 Aws5t3WrZa1fXF4xn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UbIYCTnIWIevJa73UjIFyTuYvjxUTvtCUUUUU X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqAXrXmekT+DQdgAAsS X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224537_300666_C418E560 X-CRM114-Status: GOOD ( 17.67 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Andy Yan The VOP interface mux, overlay, background delay cycle configuration of different SOC are much different. Add platform specific callback ops to let the core driver look cleaner and more refined. Signed-off-by: Andy Yan Tested-by: Michael Riesch # on RK3568 Tested-by: Detlev Casanova --- (no changes since v8) Changes in v8: - Remove redundant blank line before drm_bus_format_enum_list - Add a blank line before DRM_ENUM_NAME_FN Changes in v7: - Fix rk3588 dp+dsi maxclk verification Changes in v2: - Add platform specific callback drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 1139 +----------------- drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 168 +++ drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 992 +++++++++++++++ 3 files changed, 1177 insertions(+), 1122 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 5ee8a7b86d0b..f7e2df1431b0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -33,7 +33,6 @@ #include #include -#include #include "rockchip_drm_gem.h" #include "rockchip_drm_vop2.h" @@ -102,143 +101,6 @@ enum vop2_afbc_format { VOP2_AFBC_FMT_INVALID = -1, }; -union vop2_alpha_ctrl { - u32 val; - struct { - /* [0:1] */ - u32 color_mode:1; - u32 alpha_mode:1; - /* [2:3] */ - u32 blend_mode:2; - u32 alpha_cal_mode:1; - /* [5:7] */ - u32 factor_mode:3; - /* [8:9] */ - u32 alpha_en:1; - u32 src_dst_swap:1; - u32 reserved:6; - /* [16:23] */ - u32 glb_alpha:8; - } bits; -}; - -struct vop2_alpha { - union vop2_alpha_ctrl src_color_ctrl; - union vop2_alpha_ctrl dst_color_ctrl; - union vop2_alpha_ctrl src_alpha_ctrl; - union vop2_alpha_ctrl dst_alpha_ctrl; -}; - -struct vop2_alpha_config { - bool src_premulti_en; - bool dst_premulti_en; - bool src_pixel_alpha_en; - bool dst_pixel_alpha_en; - u16 src_glb_alpha_value; - u16 dst_glb_alpha_value; -}; - -struct vop2_win { - struct vop2 *vop2; - struct drm_plane base; - const struct vop2_win_data *data; - struct regmap_field *reg[VOP2_WIN_MAX_REG]; - - /** - * @win_id: graphic window id, a cluster may be split into two - * graphics windows. - */ - u8 win_id; - u8 delay; - u32 offset; - - enum drm_plane_type type; -}; - -struct vop2_video_port { - struct drm_crtc crtc; - struct vop2 *vop2; - struct clk *dclk; - unsigned int id; - const struct vop2_video_port_data *data; - - struct completion dsp_hold_completion; - - /** - * @win_mask: Bitmask of windows attached to the video port; - */ - u32 win_mask; - - struct vop2_win *primary_plane; - struct drm_pending_vblank_event *event; - - unsigned int nlayers; -}; - -struct vop2 { - struct device *dev; - struct drm_device *drm; - struct vop2_video_port vps[ROCKCHIP_MAX_CRTC]; - - const struct vop2_data *data; - /* - * Number of windows that are registered as plane, may be less than the - * total number of hardware windows. - */ - u32 registered_num_wins; - - struct resource *res; - void __iomem *regs; - struct regmap *map; - - struct regmap *sys_grf; - struct regmap *vop_grf; - struct regmap *vo1_grf; - struct regmap *sys_pmu; - - /* physical map length of vop2 register */ - u32 len; - - void __iomem *lut_regs; - - /* protects crtc enable/disable */ - struct mutex vop2_lock; - - int irq; - - /* - * Some global resources are shared between all video ports(crtcs), so - * we need a ref counter here. - */ - unsigned int enable_count; - struct clk *hclk; - struct clk *aclk; - struct clk *pclk; - - /* optional internal rgb encoder */ - struct rockchip_rgb *rgb; - - /* must be put at the end of the struct */ - struct vop2_win win[]; -}; - -#define vop2_output_if_is_hdmi(x) ((x) == ROCKCHIP_VOP2_EP_HDMI0 || \ - (x) == ROCKCHIP_VOP2_EP_HDMI1) - -#define vop2_output_if_is_dp(x) ((x) == ROCKCHIP_VOP2_EP_DP0 || \ - (x) == ROCKCHIP_VOP2_EP_DP1) - -#define vop2_output_if_is_edp(x) ((x) == ROCKCHIP_VOP2_EP_EDP0 || \ - (x) == ROCKCHIP_VOP2_EP_EDP1) - -#define vop2_output_if_is_mipi(x) ((x) == ROCKCHIP_VOP2_EP_MIPI0 || \ - (x) == ROCKCHIP_VOP2_EP_MIPI1) - -#define vop2_output_if_is_lvds(x) ((x) == ROCKCHIP_VOP2_EP_LVDS0 || \ - (x) == ROCKCHIP_VOP2_EP_LVDS1) - -#define vop2_output_if_is_dpi(x) ((x) == ROCKCHIP_VOP2_EP_RGB0) - /* * bus-format types. */ @@ -272,15 +134,6 @@ static DRM_ENUM_NAME_FN(drm_get_bus_format_name, drm_bus_format_enum_list) static const struct regmap_config vop2_regmap_config; -static struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc) -{ - return container_of(crtc, struct vop2_video_port, crtc); -} - -static struct vop2_win *to_vop2_win(struct drm_plane *p) -{ - return container_of(p, struct vop2_win, base); -} static void vop2_lock(struct vop2 *vop2) { @@ -292,44 +145,6 @@ static void vop2_unlock(struct vop2 *vop2) mutex_unlock(&vop2->vop2_lock); } -static void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) -{ - regmap_write(vop2->map, offset, v); -} - -static void vop2_vp_write(struct vop2_video_port *vp, u32 offset, u32 v) -{ - regmap_write(vp->vop2->map, vp->data->offset + offset, v); -} - -static u32 vop2_readl(struct vop2 *vop2, u32 offset) -{ - u32 val; - - regmap_read(vop2->map, offset, &val); - - return val; -} - -static u32 vop2_vp_read(struct vop2_video_port *vp, u32 offset) -{ - u32 val; - - regmap_read(vp->vop2->map, vp->data->offset + offset, &val); - - return val; -} - -static void vop2_win_write(const struct vop2_win *win, unsigned int reg, u32 v) -{ - regmap_field_write(win->reg[reg], v); -} - -static bool vop2_cluster_window(const struct vop2_win *win) -{ - return win->data->feature & WIN_FEATURE_CLUSTER; -} - /* * Note: * The write mask function is documented but missing on rk3566/8, writes @@ -1724,6 +1539,7 @@ static void vop2_dither_setup(struct drm_crtc *crtc, u32 *dsp_ctrl) static void vop2_post_config(struct drm_crtc *crtc) { struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct vop2 *vop2 = vp->vop2; struct drm_display_mode *mode = &crtc->state->adjusted_mode; u16 vtotal = mode->crtc_vtotal; u16 hdisplay = mode->crtc_hdisplay; @@ -1734,18 +1550,10 @@ static void vop2_post_config(struct drm_crtc *crtc) u32 top_margin = 100, bottom_margin = 100; u16 hsize = hdisplay * (left_margin + right_margin) / 200; u16 vsize = vdisplay * (top_margin + bottom_margin) / 200; - u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; u16 hact_end, vact_end; u32 val; - u32 bg_dly; - u32 pre_scan_dly; - - bg_dly = vp->data->pre_scan_max_dly[3]; - vop2_writel(vp->vop2, RK3568_VP_BG_MIX_CTRL(vp->id), - FIELD_PREP(RK3568_VP_BG_MIX_CTRL__BG_DLY, bg_dly)); - pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len; - vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly); + vop2->ops->setup_bg_dly(vp); vsize = rounddown(vsize, 2); hsize = rounddown(hsize, 2); @@ -1781,347 +1589,6 @@ static void vop2_post_config(struct drm_crtc *crtc) vop2_vp_write(vp, RK3568_VP_DSP_BG, 0); } -static unsigned long rk3568_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags) -{ - struct vop2 *vop2 = vp->vop2; - struct drm_crtc *crtc = &vp->crtc; - u32 die, dip; - - die = vop2_readl(vop2, RK3568_DSP_IF_EN); - dip = vop2_readl(vop2, RK3568_DSP_IF_POL); - - switch (id) { - case ROCKCHIP_VOP2_EP_RGB0: - die &= ~RK3568_SYS_DSP_INFACE_EN_RGB_MUX; - die |= RK3568_SYS_DSP_INFACE_EN_RGB | - FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_RGB_MUX, vp->id); - dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; - dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); - if (polflags & POLFLAG_DCLK_INV) - regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3)); - else - regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16)); - break; - case ROCKCHIP_VOP2_EP_HDMI0: - die &= ~RK3568_SYS_DSP_INFACE_EN_HDMI_MUX; - die |= RK3568_SYS_DSP_INFACE_EN_HDMI | - FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id); - dip &= ~RK3568_DSP_IF_POL__HDMI_PIN_POL; - dip |= FIELD_PREP(RK3568_DSP_IF_POL__HDMI_PIN_POL, polflags); - break; - case ROCKCHIP_VOP2_EP_EDP0: - die &= ~RK3568_SYS_DSP_INFACE_EN_EDP_MUX; - die |= RK3568_SYS_DSP_INFACE_EN_EDP | - FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id); - dip &= ~RK3568_DSP_IF_POL__EDP_PIN_POL; - dip |= FIELD_PREP(RK3568_DSP_IF_POL__EDP_PIN_POL, polflags); - break; - case ROCKCHIP_VOP2_EP_MIPI0: - die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX; - die |= RK3568_SYS_DSP_INFACE_EN_MIPI0 | - FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX, vp->id); - dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL; - dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags); - break; - case ROCKCHIP_VOP2_EP_MIPI1: - die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX; - die |= RK3568_SYS_DSP_INFACE_EN_MIPI1 | - FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id); - dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL; - dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags); - break; - case ROCKCHIP_VOP2_EP_LVDS0: - die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX; - die |= RK3568_SYS_DSP_INFACE_EN_LVDS0 | - FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX, vp->id); - dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; - dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); - break; - case ROCKCHIP_VOP2_EP_LVDS1: - die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX; - die |= RK3568_SYS_DSP_INFACE_EN_LVDS1 | - FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX, vp->id); - dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; - dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); - break; - default: - drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); - return 0; - } - - dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD; - - vop2_writel(vop2, RK3568_DSP_IF_EN, die); - vop2_writel(vop2, RK3568_DSP_IF_POL, dip); - - return crtc->state->adjusted_mode.crtc_clock * 1000LL; -} - -/* - * calc the dclk on rk3588 - * the available div of dclk is 1, 2, 4 - */ -static unsigned long rk3588_calc_dclk(unsigned long child_clk, unsigned long max_dclk) -{ - if (child_clk * 4 <= max_dclk) - return child_clk * 4; - else if (child_clk * 2 <= max_dclk) - return child_clk * 2; - else if (child_clk <= max_dclk) - return child_clk; - else - return 0; -} - -/* - * 4 pixclk/cycle on rk3588 - * RGB/eDP/HDMI: if_pixclk >= dclk_core - * DP: dp_pixclk = dclk_out <= dclk_core - * DSI: mipi_pixclk <= dclk_out <= dclk_core - */ -static unsigned long rk3588_calc_cru_cfg(struct vop2_video_port *vp, int id, - int *dclk_core_div, int *dclk_out_div, - int *if_pixclk_div, int *if_dclk_div) -{ - struct vop2 *vop2 = vp->vop2; - struct drm_crtc *crtc = &vp->crtc; - struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; - struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); - int output_mode = vcstate->output_mode; - unsigned long v_pixclk = adjusted_mode->crtc_clock * 1000LL; /* video timing pixclk */ - unsigned long dclk_core_rate = v_pixclk >> 2; - unsigned long dclk_rate = v_pixclk; - unsigned long dclk_out_rate; - unsigned long if_pixclk_rate; - int K = 1; - - if (vop2_output_if_is_hdmi(id)) { - /* - * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate - * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate - */ - if (output_mode == ROCKCHIP_OUT_MODE_YUV420) { - dclk_rate = dclk_rate >> 1; - K = 2; - } - - if_pixclk_rate = (dclk_core_rate << 1) / K; - /* - * if_dclk_rate = dclk_core_rate / K; - * *if_pixclk_div = dclk_rate / if_pixclk_rate; - * *if_dclk_div = dclk_rate / if_dclk_rate; - */ - *if_pixclk_div = 2; - *if_dclk_div = 4; - } else if (vop2_output_if_is_edp(id)) { - /* - * edp_pixclk = edp_dclk > dclk_core - */ - if_pixclk_rate = v_pixclk / K; - dclk_rate = if_pixclk_rate * K; - /* - * *if_pixclk_div = dclk_rate / if_pixclk_rate; - * *if_dclk_div = *if_pixclk_div; - */ - *if_pixclk_div = K; - *if_dclk_div = K; - } else if (vop2_output_if_is_dp(id)) { - if (output_mode == ROCKCHIP_OUT_MODE_YUV420) - dclk_out_rate = v_pixclk >> 3; - else - dclk_out_rate = v_pixclk >> 2; - - dclk_rate = rk3588_calc_dclk(dclk_out_rate, 600000000); - if (!dclk_rate) { - drm_err(vop2->drm, "DP dclk_out_rate out of range, dclk_out_rate: %ld Hz\n", - dclk_out_rate); - return 0; - } - *dclk_out_div = dclk_rate / dclk_out_rate; - } else if (vop2_output_if_is_mipi(id)) { - if_pixclk_rate = dclk_core_rate / K; - /* - * dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 - */ - dclk_out_rate = if_pixclk_rate; - /* - * dclk_rate = N * dclk_core_rate N = (1,2,4 ), - * we get a little factor here - */ - dclk_rate = rk3588_calc_dclk(dclk_out_rate, 600000000); - if (!dclk_rate) { - drm_err(vop2->drm, "MIPI dclk out of range, dclk_out_rate: %ld Hz\n", - dclk_out_rate); - return 0; - } - *dclk_out_div = dclk_rate / dclk_out_rate; - /* - * mipi pixclk == dclk_out - */ - *if_pixclk_div = 1; - } else if (vop2_output_if_is_dpi(id)) { - dclk_rate = v_pixclk; - } - - *dclk_core_div = dclk_rate / dclk_core_rate; - *if_pixclk_div = ilog2(*if_pixclk_div); - *if_dclk_div = ilog2(*if_dclk_div); - *dclk_core_div = ilog2(*dclk_core_div); - *dclk_out_div = ilog2(*dclk_out_div); - - drm_dbg(vop2->drm, "dclk: %ld, pixclk_div: %d, dclk_div: %d\n", - dclk_rate, *if_pixclk_div, *if_dclk_div); - - return dclk_rate; -} - -/* - * MIPI port mux on rk3588: - * 0: Video Port2 - * 1: Video Port3 - * 3: Video Port 1(MIPI1 only) - */ -static u32 rk3588_get_mipi_port_mux(int vp_id) -{ - if (vp_id == 1) - return 3; - else if (vp_id == 3) - return 1; - else - return 0; -} - -static u32 rk3588_get_hdmi_pol(u32 flags) -{ - u32 val; - - val = (flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0; - val |= (flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0; - - return val; -} - -static unsigned long rk3588_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags) -{ - struct vop2 *vop2 = vp->vop2; - int dclk_core_div, dclk_out_div, if_pixclk_div, if_dclk_div; - unsigned long clock; - u32 die, dip, div, vp_clk_div, val; - - clock = rk3588_calc_cru_cfg(vp, id, &dclk_core_div, &dclk_out_div, - &if_pixclk_div, &if_dclk_div); - if (!clock) - return 0; - - vp_clk_div = FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_CORE_DIV, dclk_core_div); - vp_clk_div |= FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_OUT_DIV, dclk_out_div); - - die = vop2_readl(vop2, RK3568_DSP_IF_EN); - dip = vop2_readl(vop2, RK3568_DSP_IF_POL); - div = vop2_readl(vop2, RK3568_DSP_IF_CTRL); - - switch (id) { - case ROCKCHIP_VOP2_EP_HDMI0: - div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV; - div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV; - div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div); - div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div); - die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX; - die |= RK3588_SYS_DSP_INFACE_EN_HDMI0 | - FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id); - val = rk3588_get_hdmi_pol(polflags); - regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 1, 1)); - regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, HIWORD_UPDATE(val, 6, 5)); - break; - case ROCKCHIP_VOP2_EP_HDMI1: - div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV; - div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV; - div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV, if_dclk_div); - div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV, if_pixclk_div); - die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX; - die |= RK3588_SYS_DSP_INFACE_EN_HDMI1 | - FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id); - val = rk3588_get_hdmi_pol(polflags); - regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 4, 4)); - regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, HIWORD_UPDATE(val, 8, 7)); - break; - case ROCKCHIP_VOP2_EP_EDP0: - div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV; - div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV; - div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div); - div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div); - die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX; - die |= RK3588_SYS_DSP_INFACE_EN_EDP0 | - FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id); - regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 0, 0)); - break; - case ROCKCHIP_VOP2_EP_EDP1: - div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV; - div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV; - div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div); - div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div); - die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX; - die |= RK3588_SYS_DSP_INFACE_EN_EDP1 | - FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id); - regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 3, 3)); - break; - case ROCKCHIP_VOP2_EP_MIPI0: - div &= ~RK3588_DSP_IF_MIPI0_PCLK_DIV; - div |= FIELD_PREP(RK3588_DSP_IF_MIPI0_PCLK_DIV, if_pixclk_div); - die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX; - val = rk3588_get_mipi_port_mux(vp->id); - die |= RK3588_SYS_DSP_INFACE_EN_MIPI0 | - FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX, !!val); - break; - case ROCKCHIP_VOP2_EP_MIPI1: - div &= ~RK3588_DSP_IF_MIPI1_PCLK_DIV; - div |= FIELD_PREP(RK3588_DSP_IF_MIPI1_PCLK_DIV, if_pixclk_div); - die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX; - val = rk3588_get_mipi_port_mux(vp->id); - die |= RK3588_SYS_DSP_INFACE_EN_MIPI1 | - FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, val); - break; - case ROCKCHIP_VOP2_EP_DP0: - die &= ~RK3588_SYS_DSP_INFACE_EN_DP0_MUX; - die |= RK3588_SYS_DSP_INFACE_EN_DP0 | - FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP0_MUX, vp->id); - dip &= ~RK3588_DSP_IF_POL__DP0_PIN_POL; - dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP0_PIN_POL, polflags); - break; - case ROCKCHIP_VOP2_EP_DP1: - die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX; - die |= RK3588_SYS_DSP_INFACE_EN_MIPI1 | - FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id); - dip &= ~RK3588_DSP_IF_POL__DP1_PIN_POL; - dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP1_PIN_POL, polflags); - break; - default: - drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); - return 0; - } - - dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD; - - vop2_vp_write(vp, RK3588_VP_CLK_CTRL, vp_clk_div); - vop2_writel(vop2, RK3568_DSP_IF_EN, die); - vop2_writel(vop2, RK3568_DSP_IF_CTRL, div); - vop2_writel(vop2, RK3568_DSP_IF_POL, dip); - - return clock; -} - -static unsigned long vop2_set_intf_mux(struct vop2_video_port *vp, int ep_id, u32 polflags) -{ - struct vop2 *vop2 = vp->vop2; - - if (vop2->data->soc_id == 3566 || vop2->data->soc_id == 3568) - return rk3568_set_intf_mux(vp, ep_id, polflags); - else if (vop2->data->soc_id == 3588) - return rk3588_set_intf_mux(vp, ep_id, polflags); - else - return 0; -} - static int us_to_vertical_line(struct drm_display_mode *mode, int us) { return us * mode->clock / mode->htotal / 1000; @@ -2194,7 +1661,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, * process multi(1/2/4/8) pixels per cycle, so the dclk feed by the * system cru may be the 1/2 or 1/4 of mode->clock. */ - clock = vop2_set_intf_mux(vp, rkencoder->crtc_endpoint_id, polflags); + clock = vop2->ops->setup_intf_mux(vp, rkencoder->crtc_endpoint_id, polflags); } if (!clock) { @@ -2323,454 +1790,13 @@ static int vop2_crtc_atomic_check(struct drm_crtc *crtc, return 0; } -static bool is_opaque(u16 alpha) -{ - return (alpha >> 8) == 0xff; -} - -static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config, - struct vop2_alpha *alpha) -{ - int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1; - int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1; - int src_color_mode = alpha_config->src_premulti_en ? - ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL; - int dst_color_mode = alpha_config->dst_premulti_en ? - ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL; - - alpha->src_color_ctrl.val = 0; - alpha->dst_color_ctrl.val = 0; - alpha->src_alpha_ctrl.val = 0; - alpha->dst_alpha_ctrl.val = 0; - - if (!alpha_config->src_pixel_alpha_en) - alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; - else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en) - alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX; - else - alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; - - alpha->src_color_ctrl.bits.alpha_en = 1; - - if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) { - alpha->src_color_ctrl.bits.color_mode = src_color_mode; - alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; - } else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) { - alpha->src_color_ctrl.bits.color_mode = src_color_mode; - alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE; - } else { - alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL; - alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; - } - alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8; - alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; - alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; - - alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; - alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; - alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; - alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8; - alpha->dst_color_ctrl.bits.color_mode = dst_color_mode; - alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; - - alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; - alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode; - alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; - alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE; - - alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; - if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en) - alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX; - else - alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; - alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION; - alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; -} - -static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, u8 port_id) -{ - struct vop2_video_port *vp; - int used_layer = 0; - int i; - - for (i = 0; i < port_id; i++) { - vp = &vop2->vps[i]; - used_layer += hweight32(vp->win_mask); - } - - return used_layer; -} - -static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_win) -{ - struct vop2_alpha_config alpha_config; - struct vop2_alpha alpha; - struct drm_plane_state *bottom_win_pstate; - bool src_pixel_alpha_en = false; - u16 src_glb_alpha_val, dst_glb_alpha_val; - bool premulti_en = false; - bool swap = false; - u32 offset = 0; - - /* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */ - bottom_win_pstate = main_win->base.state; - src_glb_alpha_val = 0; - dst_glb_alpha_val = main_win->base.state->alpha; - - if (!bottom_win_pstate->fb) - return; - - alpha_config.src_premulti_en = premulti_en; - alpha_config.dst_premulti_en = false; - alpha_config.src_pixel_alpha_en = src_pixel_alpha_en; - alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ - alpha_config.src_glb_alpha_value = src_glb_alpha_val; - alpha_config.dst_glb_alpha_value = dst_glb_alpha_val; - vop2_parse_alpha(&alpha_config, &alpha); - - alpha.src_color_ctrl.bits.src_dst_swap = swap; - - switch (main_win->data->phys_id) { - case ROCKCHIP_VOP2_CLUSTER0: - offset = 0x0; - break; - case ROCKCHIP_VOP2_CLUSTER1: - offset = 0x10; - break; - case ROCKCHIP_VOP2_CLUSTER2: - offset = 0x20; - break; - case ROCKCHIP_VOP2_CLUSTER3: - offset = 0x30; - break; - } - - vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL + offset, - alpha.src_color_ctrl.val); - vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_COLOR_CTRL + offset, - alpha.dst_color_ctrl.val); - vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL + offset, - alpha.src_alpha_ctrl.val); - vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL + offset, - alpha.dst_alpha_ctrl.val); -} - -static void vop2_setup_alpha(struct vop2_video_port *vp) -{ - struct vop2 *vop2 = vp->vop2; - struct drm_framebuffer *fb; - struct vop2_alpha_config alpha_config; - struct vop2_alpha alpha; - struct drm_plane *plane; - int pixel_alpha_en; - int premulti_en, gpremulti_en = 0; - int mixer_id; - u32 offset; - bool bottom_layer_alpha_en = false; - u32 dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE; - - mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id); - alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ - - drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { - struct vop2_win *win = to_vop2_win(plane); - - if (plane->state->normalized_zpos == 0 && - !is_opaque(plane->state->alpha) && - !vop2_cluster_window(win)) { - /* - * If bottom layer have global alpha effect [except cluster layer, - * because cluster have deal with bottom layer global alpha value - * at cluster mix], bottom layer mix need deal with global alpha. - */ - bottom_layer_alpha_en = true; - dst_global_alpha = plane->state->alpha; - } - } - - drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { - struct vop2_win *win = to_vop2_win(plane); - int zpos = plane->state->normalized_zpos; - - /* - * Need to configure alpha from second layer. - */ - if (zpos == 0) - continue; - - if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) - premulti_en = 1; - else - premulti_en = 0; - - plane = &win->base; - fb = plane->state->fb; - - pixel_alpha_en = fb->format->has_alpha; - - alpha_config.src_premulti_en = premulti_en; - - if (bottom_layer_alpha_en && zpos == 1) { - gpremulti_en = premulti_en; - /* Cd = Cs + (1 - As) * Cd * Agd */ - alpha_config.dst_premulti_en = false; - alpha_config.src_pixel_alpha_en = pixel_alpha_en; - alpha_config.src_glb_alpha_value = plane->state->alpha; - alpha_config.dst_glb_alpha_value = dst_global_alpha; - } else if (vop2_cluster_window(win)) { - /* Mix output data only have pixel alpha */ - alpha_config.dst_premulti_en = true; - alpha_config.src_pixel_alpha_en = true; - alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; - alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; - } else { - /* Cd = Cs + (1 - As) * Cd */ - alpha_config.dst_premulti_en = true; - alpha_config.src_pixel_alpha_en = pixel_alpha_en; - alpha_config.src_glb_alpha_value = plane->state->alpha; - alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; - } - - vop2_parse_alpha(&alpha_config, &alpha); - - offset = (mixer_id + zpos - 1) * 0x10; - vop2_writel(vop2, RK3568_MIX0_SRC_COLOR_CTRL + offset, - alpha.src_color_ctrl.val); - vop2_writel(vop2, RK3568_MIX0_DST_COLOR_CTRL + offset, - alpha.dst_color_ctrl.val); - vop2_writel(vop2, RK3568_MIX0_SRC_ALPHA_CTRL + offset, - alpha.src_alpha_ctrl.val); - vop2_writel(vop2, RK3568_MIX0_DST_ALPHA_CTRL + offset, - alpha.dst_alpha_ctrl.val); - } - - if (vp->id == 0) { - if (bottom_layer_alpha_en) { - /* Transfer pixel alpha to hdr mix */ - alpha_config.src_premulti_en = gpremulti_en; - alpha_config.dst_premulti_en = true; - alpha_config.src_pixel_alpha_en = true; - alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; - alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; - vop2_parse_alpha(&alpha_config, &alpha); - - vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, - alpha.src_color_ctrl.val); - vop2_writel(vop2, RK3568_HDR0_DST_COLOR_CTRL, - alpha.dst_color_ctrl.val); - vop2_writel(vop2, RK3568_HDR0_SRC_ALPHA_CTRL, - alpha.src_alpha_ctrl.val); - vop2_writel(vop2, RK3568_HDR0_DST_ALPHA_CTRL, - alpha.dst_alpha_ctrl.val); - } else { - vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, 0); - } - } -} - -static void vop2_setup_layer_mixer(struct vop2_video_port *vp) -{ - struct vop2 *vop2 = vp->vop2; - struct drm_plane *plane; - u32 layer_sel = 0; - u32 port_sel; - u8 layer_id; - u8 old_layer_id; - u8 layer_sel_id; - unsigned int ofs; - u32 ovl_ctrl; - int i; - struct vop2_video_port *vp0 = &vop2->vps[0]; - struct vop2_video_port *vp1 = &vop2->vps[1]; - struct vop2_video_port *vp2 = &vop2->vps[2]; - struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); - - ovl_ctrl = vop2_readl(vop2, RK3568_OVL_CTRL); - ovl_ctrl |= RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD; - if (vcstate->yuv_overlay) - ovl_ctrl |= RK3568_OVL_CTRL__YUV_MODE(vp->id); - else - ovl_ctrl &= ~RK3568_OVL_CTRL__YUV_MODE(vp->id); - - vop2_writel(vop2, RK3568_OVL_CTRL, ovl_ctrl); - - port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL); - port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT; - - if (vp0->nlayers) - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, - vp0->nlayers - 1); - else - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, 8); - - if (vp1->nlayers) - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, - (vp0->nlayers + vp1->nlayers - 1)); - else - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8); - - if (vp2->nlayers) - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, - (vp2->nlayers + vp1->nlayers + vp0->nlayers - 1)); - else - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, 8); - - layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); - - ofs = 0; - for (i = 0; i < vp->id; i++) - ofs += vop2->vps[i].nlayers; - - drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { - struct vop2_win *win = to_vop2_win(plane); - struct vop2_win *old_win; - - layer_id = (u8)(plane->state->normalized_zpos + ofs); - - /* - * Find the layer this win bind in old state. - */ - for (old_layer_id = 0; old_layer_id < vop2->data->win_size; old_layer_id++) { - layer_sel_id = (layer_sel >> (4 * old_layer_id)) & 0xf; - if (layer_sel_id == win->data->layer_sel_id) - break; - } - - /* - * Find the win bind to this layer in old state - */ - for (i = 0; i < vop2->data->win_size; i++) { - old_win = &vop2->win[i]; - layer_sel_id = (layer_sel >> (4 * layer_id)) & 0xf; - if (layer_sel_id == old_win->data->layer_sel_id) - break; - } - - switch (win->data->phys_id) { - case ROCKCHIP_VOP2_CLUSTER0: - port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER0; - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER0, vp->id); - break; - case ROCKCHIP_VOP2_CLUSTER1: - port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER1; - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id); - break; - case ROCKCHIP_VOP2_CLUSTER2: - port_sel &= ~RK3588_OVL_PORT_SEL__CLUSTER2; - port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER2, vp->id); - break; - case ROCKCHIP_VOP2_CLUSTER3: - port_sel &= ~RK3588_OVL_PORT_SEL__CLUSTER3; - port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER3, vp->id); - break; - case ROCKCHIP_VOP2_ESMART0: - port_sel &= ~RK3568_OVL_PORT_SEL__ESMART0; - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id); - break; - case ROCKCHIP_VOP2_ESMART1: - port_sel &= ~RK3568_OVL_PORT_SEL__ESMART1; - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id); - break; - case ROCKCHIP_VOP2_ESMART2: - port_sel &= ~RK3588_OVL_PORT_SEL__ESMART2; - port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART2, vp->id); - break; - case ROCKCHIP_VOP2_ESMART3: - port_sel &= ~RK3588_OVL_PORT_SEL__ESMART3; - port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART3, vp->id); - break; - case ROCKCHIP_VOP2_SMART0: - port_sel &= ~RK3568_OVL_PORT_SEL__SMART0; - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id); - break; - case ROCKCHIP_VOP2_SMART1: - port_sel &= ~RK3568_OVL_PORT_SEL__SMART1; - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART1, vp->id); - break; - } - - layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(layer_id, 0x7); - layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(layer_id, win->data->layer_sel_id); - /* - * When we bind a window from layerM to layerN, we also need to move the old - * window on layerN to layerM to avoid one window selected by two or more layers. - */ - layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(old_layer_id, 0x7); - layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(old_layer_id, old_win->data->layer_sel_id); - } - - vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel); - vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel); -} - -static void vop2_setup_dly_for_windows(struct vop2 *vop2) -{ - struct vop2_win *win; - int i = 0; - u32 cdly = 0, sdly = 0; - - for (i = 0; i < vop2->data->win_size; i++) { - u32 dly; - - win = &vop2->win[i]; - dly = win->delay; - - switch (win->data->phys_id) { - case ROCKCHIP_VOP2_CLUSTER0: - cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_0, dly); - cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_1, dly); - break; - case ROCKCHIP_VOP2_CLUSTER1: - cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_0, dly); - cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_1, dly); - break; - case ROCKCHIP_VOP2_ESMART0: - sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART0, dly); - break; - case ROCKCHIP_VOP2_ESMART1: - sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART1, dly); - break; - case ROCKCHIP_VOP2_SMART0: - case ROCKCHIP_VOP2_ESMART2: - sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART0, dly); - break; - case ROCKCHIP_VOP2_SMART1: - case ROCKCHIP_VOP2_ESMART3: - sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART1, dly); - break; - } - } - - vop2_writel(vop2, RK3568_CLUSTER_DLY_NUM, cdly); - vop2_writel(vop2, RK3568_SMART_DLY_NUM, sdly); -} - static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state) { struct vop2_video_port *vp = to_vop2_video_port(crtc); struct vop2 *vop2 = vp->vop2; - struct drm_plane *plane; - - vp->win_mask = 0; - - drm_atomic_crtc_for_each_plane(plane, crtc) { - struct vop2_win *win = to_vop2_win(plane); - - win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT]; - - vp->win_mask |= BIT(win->data->phys_id); - if (vop2_cluster_window(win)) - vop2_setup_cluster_alpha(vop2, win); - } - - if (!vp->win_mask) - return; - - vop2_setup_layer_mixer(vp); - vop2_setup_alpha(vp); - vop2_setup_dly_for_windows(vop2); + vop2->ops->setup_overlay(vp); } static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, @@ -3372,86 +2398,18 @@ static int vop2_find_rgb_encoder(struct vop2 *vop2) return -ENOENT; } -static const struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = { - [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0), - [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5), - [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14), - [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18), - [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31), - [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31), - [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31), - [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31), - [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31), - [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19), - [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15), - [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31), - [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8), - [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9), - [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11), - [VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 0, 3), - [VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 5, 8), - /* RK3588 only, reserved bit on rk3568*/ - [VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3568_CLUSTER_CTRL, 13, 13), - - /* Scale */ - [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15), - [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31), - [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15), - [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 12, 13), - [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3), - [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28), - [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29), - - /* cluster regs */ - [VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1), - [VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0), - [VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7), - - /* afbc regs */ - [VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6), - [VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9), - [VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10), - [VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4), - [VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7), - [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8), - [VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31), - [VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31), - [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15), - [VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31), - [VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31), - [VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31), - [VOP2_WIN_AFBC_TRANSFORM_OFFS] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFS, 0, 31), - [VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0), - [VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1), - [VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2), - [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3), - [VOP2_WIN_UV_SWAP] = { .reg = 0xffffffff }, - [VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff }, - [VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff }, - [VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff }, - [VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff }, - [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff }, - [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff }, - [VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff }, - [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff }, - [VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff }, - [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff }, - [VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff }, - [VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff }, -}; - static int vop2_cluster_init(struct vop2_win *win) { struct vop2 *vop2 = win->vop2; int i; - for (i = 0; i < ARRAY_SIZE(vop2_cluster_regs); i++) { + for (i = 0; i < vop2->data->nr_cluster_regs; i++) { const struct reg_field field = { - .reg = (vop2_cluster_regs[i].reg != 0xffffffff) ? - vop2_cluster_regs[i].reg + win->offset : - vop2_cluster_regs[i].reg, - .lsb = vop2_cluster_regs[i].lsb, - .msb = vop2_cluster_regs[i].msb + .reg = (vop2->data->cluster_reg[i].reg != 0xffffffff) ? + vop2->data->cluster_reg[i].reg + win->offset : + vop2->data->cluster_reg[i].reg, + .lsb = vop2->data->cluster_reg[i].lsb, + .msb = vop2->data->cluster_reg[i].msb }; win->reg[i] = devm_regmap_field_alloc(vop2->dev, vop2->map, field); @@ -3462,82 +2420,18 @@ static int vop2_cluster_init(struct vop2_win *win) return 0; }; -static const struct reg_field vop2_esmart_regs[VOP2_WIN_MAX_REG] = { - [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0), - [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5), - [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12), - [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14), - [VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16), - [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31), - [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31), - [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28), - [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31), - [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31), - [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17), - [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15), - [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31), - [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0), - [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1), - [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3), - [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31), - [VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29), - [VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31), - [VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 4, 8), - [VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 12, 16), - /* RK3588 only, reserved register on rk3568 */ - [VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3588_SMART_AXI_CTRL, 1, 1), - - /* Scale */ - [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15), - [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31), - [VOP2_WIN_SCALE_CBCR_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0, 15), - [VOP2_WIN_SCALE_CBCR_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 16, 31), - [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1), - [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3), - [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5), - [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7), - [VOP2_WIN_CBCR_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 8, 9), - [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 10, 11), - [VOP2_WIN_CBCR_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 12, 13), - [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 14, 15), - [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17), - [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8), - [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9), - [VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10), - [VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11), - [VOP2_WIN_XMIRROR] = { .reg = 0xffffffff }, - [VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff }, - [VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_TRANSFORM_OFFS] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff }, - [VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff }, -}; - static int vop2_esmart_init(struct vop2_win *win) { struct vop2 *vop2 = win->vop2; int i; - for (i = 0; i < ARRAY_SIZE(vop2_esmart_regs); i++) { + for (i = 0; i < vop2->data->nr_smart_regs; i++) { const struct reg_field field = { - .reg = (vop2_esmart_regs[i].reg != 0xffffffff) ? - vop2_esmart_regs[i].reg + win->offset : - vop2_esmart_regs[i].reg, - .lsb = vop2_esmart_regs[i].lsb, - .msb = vop2_esmart_regs[i].msb + .reg = (vop2->data->smart_reg[i].reg != 0xffffffff) ? + vop2->data->smart_reg[i].reg + win->offset : + vop2->data->smart_reg[i].reg, + .lsb = vop2->data->smart_reg[i].lsb, + .msb = vop2->data->smart_reg[i].msb }; win->reg[i] = devm_regmap_field_alloc(vop2->dev, vop2->map, field); @@ -3623,6 +2517,7 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) vop2->dev = dev; vop2->data = vop2_data; + vop2->ops = vop2_data->ops; vop2->drm = drm; dev_set_drvdata(dev, vop2); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h index 8510140b0869..7cdef4c98bf6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h @@ -9,6 +9,7 @@ #include #include +#include #include "rockchip_drm_drv.h" #include "rockchip_drm_vop.h" @@ -58,6 +59,23 @@ enum vop2_scale_down_mode { #define VOP2_PD_DSC_4K BIT(6) #define VOP2_PD_ESMART BIT(7) +#define vop2_output_if_is_hdmi(x) ((x) == ROCKCHIP_VOP2_EP_HDMI0 || \ + (x) == ROCKCHIP_VOP2_EP_HDMI1) + +#define vop2_output_if_is_dp(x) ((x) == ROCKCHIP_VOP2_EP_DP0 || \ + (x) == ROCKCHIP_VOP2_EP_DP1) + +#define vop2_output_if_is_edp(x) ((x) == ROCKCHIP_VOP2_EP_EDP0 || \ + (x) == ROCKCHIP_VOP2_EP_EDP1) + +#define vop2_output_if_is_mipi(x) ((x) == ROCKCHIP_VOP2_EP_MIPI0 || \ + (x) == ROCKCHIP_VOP2_EP_MIPI1) + +#define vop2_output_if_is_lvds(x) ((x) == ROCKCHIP_VOP2_EP_LVDS0 || \ + (x) == ROCKCHIP_VOP2_EP_LVDS1) + +#define vop2_output_if_is_dpi(x) ((x) == ROCKCHIP_VOP2_EP_RGB0) + enum vop2_win_regs { VOP2_WIN_ENABLE, VOP2_WIN_FORMAT, @@ -162,6 +180,23 @@ struct vop2_win_data { const u8 dly[VOP2_DLY_MODE_MAX]; }; +struct vop2_win { + struct vop2 *vop2; + struct drm_plane base; + const struct vop2_win_data *data; + struct regmap_field *reg[VOP2_WIN_MAX_REG]; + + /** + * @win_id: graphic window id, a cluster may be split into two + * graphics windows. + */ + u8 win_id; + u8 delay; + u32 offset; + + enum drm_plane_type type; +}; + struct vop2_video_port_data { unsigned int id; u32 feature; @@ -172,20 +207,105 @@ struct vop2_video_port_data { unsigned int offset; }; +struct vop2_video_port { + struct drm_crtc crtc; + struct vop2 *vop2; + struct clk *dclk; + unsigned int id; + const struct vop2_video_port_data *data; + + struct completion dsp_hold_completion; + + /** + * @win_mask: Bitmask of windows attached to the video port; + */ + u32 win_mask; + + struct vop2_win *primary_plane; + struct drm_pending_vblank_event *event; + + unsigned int nlayers; +}; + +/** + * struct vop2_ops - helper operations for vop2 hardware + * + * These hooks are used by the common part of the vop2 driver to + * implement the proper behaviour of different variants. + */ +struct vop2_ops { + unsigned long (*setup_intf_mux)(struct vop2_video_port *vp, int ep_id, u32 polflags); + void (*setup_bg_dly)(struct vop2_video_port *vp); + void (*setup_overlay)(struct vop2_video_port *vp); +}; + struct vop2_data { u8 nr_vps; u64 feature; + const struct vop2_ops *ops; const struct vop2_win_data *win; const struct vop2_video_port_data *vp; + const struct reg_field *cluster_reg; + const struct reg_field *smart_reg; const struct vop2_regs_dump *regs_dump; struct vop_rect max_input; struct vop_rect max_output; + unsigned int nr_cluster_regs; + unsigned int nr_smart_regs; unsigned int win_size; unsigned int regs_dump_size; unsigned int soc_id; }; +struct vop2 { + struct device *dev; + struct drm_device *drm; + struct vop2_video_port vps[ROCKCHIP_MAX_CRTC]; + + const struct vop2_data *data; + const struct vop2_ops *ops; + /* + * Number of windows that are registered as plane, may be less than the + * total number of hardware windows. + */ + u32 registered_num_wins; + + struct resource *res; + void __iomem *regs; + struct regmap *map; + + struct regmap *sys_grf; + struct regmap *vop_grf; + struct regmap *vo1_grf; + struct regmap *sys_pmu; + + /* physical map length of vop2 register */ + u32 len; + + void __iomem *lut_regs; + + /* protects crtc enable/disable */ + struct mutex vop2_lock; + + int irq; + + /* + * Some global resources are shared between all video ports(crtcs), so + * we need a ref counter here. + */ + unsigned int enable_count; + struct clk *hclk; + struct clk *aclk; + struct clk *pclk; + + /* optional internal rgb encoder */ + struct rockchip_rgb *rgb; + + /* must be put at the end of the struct */ + struct vop2_win win[]; +}; + /* interrupt define */ #define FS_NEW_INTR BIT(4) #define ADDR_SAME_INTR BIT(5) @@ -560,4 +680,52 @@ enum vop2_layer_phy_id { extern const struct component_ops vop2_component_ops; +static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) +{ + regmap_write(vop2->map, offset, v); +} + +static inline void vop2_vp_write(struct vop2_video_port *vp, u32 offset, u32 v) +{ + regmap_write(vp->vop2->map, vp->data->offset + offset, v); +} + +static inline u32 vop2_readl(struct vop2 *vop2, u32 offset) +{ + u32 val; + + regmap_read(vop2->map, offset, &val); + + return val; +} + +static inline u32 vop2_vp_read(struct vop2_video_port *vp, u32 offset) +{ + u32 val; + + regmap_read(vp->vop2->map, vp->data->offset + offset, &val); + + return val; +} + +static inline void vop2_win_write(const struct vop2_win *win, unsigned int reg, u32 v) +{ + regmap_field_write(win->reg[reg], v); +} + +static inline bool vop2_cluster_window(const struct vop2_win *win) +{ + return win->data->feature & WIN_FEATURE_CLUSTER; +} + +static inline struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc) +{ + return container_of(crtc, struct vop2_video_port, crtc); +} + +static inline struct vop2_win *to_vop2_win(struct drm_plane *p) +{ + return container_of(p, struct vop2_win, base); +} + #endif /* _ROCKCHIP_DRM_VOP2_H */ diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 65a88f489693..9e42251ee796 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -9,12 +9,50 @@ #include #include #include +#include #include +#include #include #include #include "rockchip_drm_vop2.h" +union vop2_alpha_ctrl { + u32 val; + struct { + /* [0:1] */ + u32 color_mode:1; + u32 alpha_mode:1; + /* [2:3] */ + u32 blend_mode:2; + u32 alpha_cal_mode:1; + /* [5:7] */ + u32 factor_mode:3; + /* [8:9] */ + u32 alpha_en:1; + u32 src_dst_swap:1; + u32 reserved:6; + /* [16:23] */ + u32 glb_alpha:8; + } bits; +}; + +struct vop2_alpha { + union vop2_alpha_ctrl src_color_ctrl; + union vop2_alpha_ctrl dst_color_ctrl; + union vop2_alpha_ctrl src_alpha_ctrl; + union vop2_alpha_ctrl dst_alpha_ctrl; +}; + +struct vop2_alpha_config { + bool src_premulti_en; + bool dst_premulti_en; + bool src_pixel_alpha_en; + bool dst_pixel_alpha_en; + u16 src_glb_alpha_value; + u16 dst_glb_alpha_value; +}; + static const uint32_t formats_cluster[] = { DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, @@ -131,6 +169,138 @@ static const uint64_t format_modifiers_afbc[] = { DRM_FORMAT_MOD_INVALID, }; +static const struct reg_field rk3568_vop_cluster_regs[VOP2_WIN_MAX_REG] = { + [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0), + [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5), + [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14), + [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18), + [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31), + [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31), + [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31), + [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31), + [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31), + [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19), + [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15), + [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31), + [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8), + [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9), + [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11), + [VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 0, 3), + [VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 5, 8), + /* RK3588 only, reserved bit on rk3568*/ + [VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3568_CLUSTER_CTRL, 13, 13), + + /* Scale */ + [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15), + [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31), + [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15), + [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 12, 13), + [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3), + [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28), + [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29), + + /* cluster regs */ + [VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1), + [VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0), + [VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7), + + /* afbc regs */ + [VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6), + [VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9), + [VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10), + [VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4), + [VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7), + [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8), + [VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31), + [VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31), + [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15), + [VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31), + [VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31), + [VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31), + [VOP2_WIN_AFBC_TRANSFORM_OFFS] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFS, 0, 31), + [VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0), + [VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1), + [VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2), + [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3), + [VOP2_WIN_UV_SWAP] = { .reg = 0xffffffff }, + [VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff }, + [VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff }, + [VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff }, + [VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff }, + [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff }, + [VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff }, +}; + +static const struct reg_field rk3568_vop_smart_regs[VOP2_WIN_MAX_REG] = { + [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0), + [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5), + [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12), + [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14), + [VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16), + [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31), + [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31), + [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28), + [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31), + [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31), + [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17), + [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15), + [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31), + [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0), + [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1), + [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3), + [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31), + [VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29), + [VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31), + [VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 4, 8), + [VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 12, 16), + /* RK3588 only, reserved register on rk3568 */ + [VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3588_SMART_AXI_CTRL, 1, 1), + + /* Scale */ + [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15), + [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31), + [VOP2_WIN_SCALE_CBCR_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0, 15), + [VOP2_WIN_SCALE_CBCR_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 16, 31), + [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1), + [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3), + [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5), + [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7), + [VOP2_WIN_CBCR_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 8, 9), + [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 10, 11), + [VOP2_WIN_CBCR_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 12, 13), + [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 14, 15), + [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17), + [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8), + [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9), + [VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10), + [VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11), + [VOP2_WIN_XMIRROR] = { .reg = 0xffffffff }, + [VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff }, + [VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_TRANSFORM_OFFS] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff }, +}; + static const struct vop2_video_port_data rk3568_vop_video_ports[] = { { .id = 0, @@ -647,6 +817,813 @@ static const struct vop2_regs_dump rk3588_regs_dump[] = { }, }; +static unsigned long rk3568_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags) +{ + struct vop2 *vop2 = vp->vop2; + struct drm_crtc *crtc = &vp->crtc; + u32 die, dip; + + die = vop2_readl(vop2, RK3568_DSP_IF_EN); + dip = vop2_readl(vop2, RK3568_DSP_IF_POL); + + switch (id) { + case ROCKCHIP_VOP2_EP_RGB0: + die &= ~RK3568_SYS_DSP_INFACE_EN_RGB_MUX; + die |= RK3568_SYS_DSP_INFACE_EN_RGB | + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_RGB_MUX, vp->id); + dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; + dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); + if (polflags & POLFLAG_DCLK_INV) + regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3)); + else + regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16)); + break; + case ROCKCHIP_VOP2_EP_HDMI0: + die &= ~RK3568_SYS_DSP_INFACE_EN_HDMI_MUX; + die |= RK3568_SYS_DSP_INFACE_EN_HDMI | + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id); + dip &= ~RK3568_DSP_IF_POL__HDMI_PIN_POL; + dip |= FIELD_PREP(RK3568_DSP_IF_POL__HDMI_PIN_POL, polflags); + break; + case ROCKCHIP_VOP2_EP_EDP0: + die &= ~RK3568_SYS_DSP_INFACE_EN_EDP_MUX; + die |= RK3568_SYS_DSP_INFACE_EN_EDP | + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id); + dip &= ~RK3568_DSP_IF_POL__EDP_PIN_POL; + dip |= FIELD_PREP(RK3568_DSP_IF_POL__EDP_PIN_POL, polflags); + break; + case ROCKCHIP_VOP2_EP_MIPI0: + die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX; + die |= RK3568_SYS_DSP_INFACE_EN_MIPI0 | + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX, vp->id); + dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL; + dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags); + break; + case ROCKCHIP_VOP2_EP_MIPI1: + die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX; + die |= RK3568_SYS_DSP_INFACE_EN_MIPI1 | + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id); + dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL; + dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags); + break; + case ROCKCHIP_VOP2_EP_LVDS0: + die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX; + die |= RK3568_SYS_DSP_INFACE_EN_LVDS0 | + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX, vp->id); + dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; + dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); + break; + case ROCKCHIP_VOP2_EP_LVDS1: + die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX; + die |= RK3568_SYS_DSP_INFACE_EN_LVDS1 | + FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX, vp->id); + dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; + dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); + break; + default: + drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); + return 0; + } + + dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD; + + vop2_writel(vop2, RK3568_DSP_IF_EN, die); + vop2_writel(vop2, RK3568_DSP_IF_POL, dip); + + return crtc->state->adjusted_mode.crtc_clock * 1000LL; +} + +/* + * calc the dclk on rk3588 + * the available div of dclk is 1, 2, 4 + */ +static unsigned long rk3588_calc_dclk(unsigned long child_clk, unsigned long max_dclk) +{ + if (child_clk * 4 <= max_dclk) + return child_clk * 4; + else if (child_clk * 2 <= max_dclk) + return child_clk * 2; + else if (child_clk <= max_dclk) + return child_clk; + else + return 0; +} + +/* + * 4 pixclk/cycle on rk3588 + * RGB/eDP/HDMI: if_pixclk >= dclk_core + * DP: dp_pixclk = dclk_out <= dclk_core + * DSI: mipi_pixclk <= dclk_out <= dclk_core + */ +static unsigned long rk3588_calc_cru_cfg(struct vop2_video_port *vp, int id, + int *dclk_core_div, int *dclk_out_div, + int *if_pixclk_div, int *if_dclk_div) +{ + struct vop2 *vop2 = vp->vop2; + struct drm_crtc *crtc = &vp->crtc; + struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); + int output_mode = vcstate->output_mode; + unsigned long v_pixclk = adjusted_mode->crtc_clock * 1000LL; /* video timing pixclk */ + unsigned long dclk_core_rate = v_pixclk >> 2; + unsigned long dclk_rate = v_pixclk; + unsigned long dclk_out_rate; + unsigned long if_pixclk_rate; + int K = 1; + + if (vop2_output_if_is_hdmi(id)) { + /* + * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate + * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate + */ + if (output_mode == ROCKCHIP_OUT_MODE_YUV420) { + dclk_rate = dclk_rate >> 1; + K = 2; + } + + if_pixclk_rate = (dclk_core_rate << 1) / K; + /* + * if_dclk_rate = dclk_core_rate / K; + * *if_pixclk_div = dclk_rate / if_pixclk_rate; + * *if_dclk_div = dclk_rate / if_dclk_rate; + */ + *if_pixclk_div = 2; + *if_dclk_div = 4; + } else if (vop2_output_if_is_edp(id)) { + /* + * edp_pixclk = edp_dclk > dclk_core + */ + if_pixclk_rate = v_pixclk / K; + dclk_rate = if_pixclk_rate * K; + /* + * *if_pixclk_div = dclk_rate / if_pixclk_rate; + * *if_dclk_div = *if_pixclk_div; + */ + *if_pixclk_div = K; + *if_dclk_div = K; + } else if (vop2_output_if_is_dp(id)) { + if (output_mode == ROCKCHIP_OUT_MODE_YUV420) + dclk_out_rate = v_pixclk >> 3; + else + dclk_out_rate = v_pixclk >> 2; + + dclk_rate = rk3588_calc_dclk(dclk_out_rate, 600000000); + if (!dclk_rate) { + drm_err(vop2->drm, "DP dclk_out_rate out of range, dclk_out_rate: %ld Hz\n", + dclk_out_rate); + return 0; + } + *dclk_out_div = dclk_rate / dclk_out_rate; + } else if (vop2_output_if_is_mipi(id)) { + if_pixclk_rate = dclk_core_rate / K; + /* + * dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 + */ + dclk_out_rate = if_pixclk_rate; + /* + * dclk_rate = N * dclk_core_rate N = (1,2,4 ), + * we get a little factor here + */ + dclk_rate = rk3588_calc_dclk(dclk_out_rate, 600000000); + if (!dclk_rate) { + drm_err(vop2->drm, "MIPI dclk out of range, dclk_out_rate: %ld Hz\n", + dclk_out_rate); + return 0; + } + *dclk_out_div = dclk_rate / dclk_out_rate; + /* + * mipi pixclk == dclk_out + */ + *if_pixclk_div = 1; + } else if (vop2_output_if_is_dpi(id)) { + dclk_rate = v_pixclk; + } + + *dclk_core_div = dclk_rate / dclk_core_rate; + *if_pixclk_div = ilog2(*if_pixclk_div); + *if_dclk_div = ilog2(*if_dclk_div); + *dclk_core_div = ilog2(*dclk_core_div); + *dclk_out_div = ilog2(*dclk_out_div); + + drm_dbg(vop2->drm, "dclk: %ld, pixclk_div: %d, dclk_div: %d\n", + dclk_rate, *if_pixclk_div, *if_dclk_div); + + return dclk_rate; +} + +/* + * MIPI port mux on rk3588: + * 0: Video Port2 + * 1: Video Port3 + * 3: Video Port 1(MIPI1 only) + */ +static u32 rk3588_get_mipi_port_mux(int vp_id) +{ + if (vp_id == 1) + return 3; + else if (vp_id == 3) + return 1; + else + return 0; +} + +static u32 rk3588_get_hdmi_pol(u32 flags) +{ + u32 val; + + val = (flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0; + val |= (flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0; + + return val; +} + +static unsigned long rk3588_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags) +{ + struct vop2 *vop2 = vp->vop2; + int dclk_core_div, dclk_out_div, if_pixclk_div, if_dclk_div; + unsigned long clock; + u32 die, dip, div, vp_clk_div, val; + + clock = rk3588_calc_cru_cfg(vp, id, &dclk_core_div, &dclk_out_div, + &if_pixclk_div, &if_dclk_div); + if (!clock) + return 0; + + vp_clk_div = FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_CORE_DIV, dclk_core_div); + vp_clk_div |= FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_OUT_DIV, dclk_out_div); + + die = vop2_readl(vop2, RK3568_DSP_IF_EN); + dip = vop2_readl(vop2, RK3568_DSP_IF_POL); + div = vop2_readl(vop2, RK3568_DSP_IF_CTRL); + + switch (id) { + case ROCKCHIP_VOP2_EP_HDMI0: + div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV; + div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV; + div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div); + div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div); + die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX; + die |= RK3588_SYS_DSP_INFACE_EN_HDMI0 | + FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id); + val = rk3588_get_hdmi_pol(polflags); + regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 1, 1)); + regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, HIWORD_UPDATE(val, 6, 5)); + break; + case ROCKCHIP_VOP2_EP_HDMI1: + div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV; + div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV; + div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV, if_dclk_div); + div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV, if_pixclk_div); + die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX; + die |= RK3588_SYS_DSP_INFACE_EN_HDMI1 | + FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id); + val = rk3588_get_hdmi_pol(polflags); + regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 4, 4)); + regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, HIWORD_UPDATE(val, 8, 7)); + break; + case ROCKCHIP_VOP2_EP_EDP0: + div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV; + div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV; + div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div); + div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div); + die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX; + die |= RK3588_SYS_DSP_INFACE_EN_EDP0 | + FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id); + regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 0, 0)); + break; + case ROCKCHIP_VOP2_EP_EDP1: + div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV; + div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV; + div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div); + div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div); + die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX; + die |= RK3588_SYS_DSP_INFACE_EN_EDP1 | + FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id); + regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 3, 3)); + break; + case ROCKCHIP_VOP2_EP_MIPI0: + div &= ~RK3588_DSP_IF_MIPI0_PCLK_DIV; + div |= FIELD_PREP(RK3588_DSP_IF_MIPI0_PCLK_DIV, if_pixclk_div); + die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX; + val = rk3588_get_mipi_port_mux(vp->id); + die |= RK3588_SYS_DSP_INFACE_EN_MIPI0 | + FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX, !!val); + break; + case ROCKCHIP_VOP2_EP_MIPI1: + div &= ~RK3588_DSP_IF_MIPI1_PCLK_DIV; + div |= FIELD_PREP(RK3588_DSP_IF_MIPI1_PCLK_DIV, if_pixclk_div); + die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX; + val = rk3588_get_mipi_port_mux(vp->id); + die |= RK3588_SYS_DSP_INFACE_EN_MIPI1 | + FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, val); + break; + case ROCKCHIP_VOP2_EP_DP0: + die &= ~RK3588_SYS_DSP_INFACE_EN_DP0_MUX; + die |= RK3588_SYS_DSP_INFACE_EN_DP0 | + FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP0_MUX, vp->id); + dip &= ~RK3588_DSP_IF_POL__DP0_PIN_POL; + dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP0_PIN_POL, polflags); + break; + case ROCKCHIP_VOP2_EP_DP1: + die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX; + die |= RK3588_SYS_DSP_INFACE_EN_MIPI1 | + FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id); + dip &= ~RK3588_DSP_IF_POL__DP1_PIN_POL; + dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP1_PIN_POL, polflags); + break; + default: + drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); + return 0; + } + + dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD; + + vop2_vp_write(vp, RK3588_VP_CLK_CTRL, vp_clk_div); + vop2_writel(vop2, RK3568_DSP_IF_EN, die); + vop2_writel(vop2, RK3568_DSP_IF_CTRL, div); + vop2_writel(vop2, RK3568_DSP_IF_POL, dip); + + return clock; +} + +static bool is_opaque(u16 alpha) +{ + return (alpha >> 8) == 0xff; +} + +static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config, + struct vop2_alpha *alpha) +{ + int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1; + int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1; + int src_color_mode = alpha_config->src_premulti_en ? + ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL; + int dst_color_mode = alpha_config->dst_premulti_en ? + ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL; + + alpha->src_color_ctrl.val = 0; + alpha->dst_color_ctrl.val = 0; + alpha->src_alpha_ctrl.val = 0; + alpha->dst_alpha_ctrl.val = 0; + + if (!alpha_config->src_pixel_alpha_en) + alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; + else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en) + alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX; + else + alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; + + alpha->src_color_ctrl.bits.alpha_en = 1; + + if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) { + alpha->src_color_ctrl.bits.color_mode = src_color_mode; + alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; + } else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) { + alpha->src_color_ctrl.bits.color_mode = src_color_mode; + alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE; + } else { + alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL; + alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; + } + alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8; + alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; + alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; + + alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; + alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; + alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; + alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8; + alpha->dst_color_ctrl.bits.color_mode = dst_color_mode; + alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; + + alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; + alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode; + alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; + alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE; + + alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; + if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en) + alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX; + else + alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; + alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION; + alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; +} + +static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, u8 port_id) +{ + struct vop2_video_port *vp; + int used_layer = 0; + int i; + + for (i = 0; i < port_id; i++) { + vp = &vop2->vps[i]; + used_layer += hweight32(vp->win_mask); + } + + return used_layer; +} + +static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_win) +{ + struct vop2_alpha_config alpha_config; + struct vop2_alpha alpha; + struct drm_plane_state *bottom_win_pstate; + bool src_pixel_alpha_en = false; + u16 src_glb_alpha_val, dst_glb_alpha_val; + u32 offset = 0; + bool premulti_en = false; + bool swap = false; + + /* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */ + bottom_win_pstate = main_win->base.state; + src_glb_alpha_val = 0; + dst_glb_alpha_val = main_win->base.state->alpha; + + if (!bottom_win_pstate->fb) + return; + + alpha_config.src_premulti_en = premulti_en; + alpha_config.dst_premulti_en = false; + alpha_config.src_pixel_alpha_en = src_pixel_alpha_en; + alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ + alpha_config.src_glb_alpha_value = src_glb_alpha_val; + alpha_config.dst_glb_alpha_value = dst_glb_alpha_val; + vop2_parse_alpha(&alpha_config, &alpha); + + alpha.src_color_ctrl.bits.src_dst_swap = swap; + + switch (main_win->data->phys_id) { + case ROCKCHIP_VOP2_CLUSTER0: + offset = 0x0; + break; + case ROCKCHIP_VOP2_CLUSTER1: + offset = 0x10; + break; + case ROCKCHIP_VOP2_CLUSTER2: + offset = 0x20; + break; + case ROCKCHIP_VOP2_CLUSTER3: + offset = 0x30; + break; + } + + vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL + offset, + alpha.src_color_ctrl.val); + vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_COLOR_CTRL + offset, + alpha.dst_color_ctrl.val); + vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL + offset, + alpha.src_alpha_ctrl.val); + vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL + offset, + alpha.dst_alpha_ctrl.val); +} + +static void vop2_setup_alpha(struct vop2_video_port *vp) +{ + struct vop2 *vop2 = vp->vop2; + struct drm_framebuffer *fb; + struct vop2_alpha_config alpha_config; + struct vop2_alpha alpha; + struct drm_plane *plane; + int pixel_alpha_en; + int premulti_en, gpremulti_en = 0; + int mixer_id; + u32 offset; + bool bottom_layer_alpha_en = false; + u32 dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE; + + mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id); + alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ + + drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { + struct vop2_win *win = to_vop2_win(plane); + + if (plane->state->normalized_zpos == 0 && + !is_opaque(plane->state->alpha) && + !vop2_cluster_window(win)) { + /* + * If bottom layer have global alpha effect [except cluster layer, + * because cluster have deal with bottom layer global alpha value + * at cluster mix], bottom layer mix need deal with global alpha. + */ + bottom_layer_alpha_en = true; + dst_global_alpha = plane->state->alpha; + } + } + + drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { + struct vop2_win *win = to_vop2_win(plane); + int zpos = plane->state->normalized_zpos; + + /* + * Need to configure alpha from second layer. + */ + if (zpos == 0) + continue; + + if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) + premulti_en = 1; + else + premulti_en = 0; + + plane = &win->base; + fb = plane->state->fb; + + pixel_alpha_en = fb->format->has_alpha; + + alpha_config.src_premulti_en = premulti_en; + + if (bottom_layer_alpha_en && zpos == 1) { + gpremulti_en = premulti_en; + /* Cd = Cs + (1 - As) * Cd * Agd */ + alpha_config.dst_premulti_en = false; + alpha_config.src_pixel_alpha_en = pixel_alpha_en; + alpha_config.src_glb_alpha_value = plane->state->alpha; + alpha_config.dst_glb_alpha_value = dst_global_alpha; + } else if (vop2_cluster_window(win)) { + /* Mix output data only have pixel alpha */ + alpha_config.dst_premulti_en = true; + alpha_config.src_pixel_alpha_en = true; + alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; + alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; + } else { + /* Cd = Cs + (1 - As) * Cd */ + alpha_config.dst_premulti_en = true; + alpha_config.src_pixel_alpha_en = pixel_alpha_en; + alpha_config.src_glb_alpha_value = plane->state->alpha; + alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; + } + + vop2_parse_alpha(&alpha_config, &alpha); + + offset = (mixer_id + zpos - 1) * 0x10; + vop2_writel(vop2, RK3568_MIX0_SRC_COLOR_CTRL + offset, + alpha.src_color_ctrl.val); + vop2_writel(vop2, RK3568_MIX0_DST_COLOR_CTRL + offset, + alpha.dst_color_ctrl.val); + vop2_writel(vop2, RK3568_MIX0_SRC_ALPHA_CTRL + offset, + alpha.src_alpha_ctrl.val); + vop2_writel(vop2, RK3568_MIX0_DST_ALPHA_CTRL + offset, + alpha.dst_alpha_ctrl.val); + } + + if (vp->id == 0) { + if (bottom_layer_alpha_en) { + /* Transfer pixel alpha to hdr mix */ + alpha_config.src_premulti_en = gpremulti_en; + alpha_config.dst_premulti_en = true; + alpha_config.src_pixel_alpha_en = true; + alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; + alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; + vop2_parse_alpha(&alpha_config, &alpha); + + vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, + alpha.src_color_ctrl.val); + vop2_writel(vop2, RK3568_HDR0_DST_COLOR_CTRL, + alpha.dst_color_ctrl.val); + vop2_writel(vop2, RK3568_HDR0_SRC_ALPHA_CTRL, + alpha.src_alpha_ctrl.val); + vop2_writel(vop2, RK3568_HDR0_DST_ALPHA_CTRL, + alpha.dst_alpha_ctrl.val); + } else { + vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, 0); + } + } +} + +static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp) +{ + struct vop2 *vop2 = vp->vop2; + struct drm_plane *plane; + u32 layer_sel = 0; + u32 port_sel; + u8 layer_id; + u8 old_layer_id; + u8 layer_sel_id; + unsigned int ofs; + u32 ovl_ctrl; + int i; + struct vop2_video_port *vp0 = &vop2->vps[0]; + struct vop2_video_port *vp1 = &vop2->vps[1]; + struct vop2_video_port *vp2 = &vop2->vps[2]; + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); + + ovl_ctrl = vop2_readl(vop2, RK3568_OVL_CTRL); + ovl_ctrl |= RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD; + if (vcstate->yuv_overlay) + ovl_ctrl |= RK3568_OVL_CTRL__YUV_MODE(vp->id); + else + ovl_ctrl &= ~RK3568_OVL_CTRL__YUV_MODE(vp->id); + + vop2_writel(vop2, RK3568_OVL_CTRL, ovl_ctrl); + + port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL); + port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT; + + if (vp0->nlayers) + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, + vp0->nlayers - 1); + else + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, 8); + + if (vp1->nlayers) + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, + (vp0->nlayers + vp1->nlayers - 1)); + else + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8); + + if (vp2->nlayers) + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, + (vp2->nlayers + vp1->nlayers + vp0->nlayers - 1)); + else + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, 8); + + layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); + + ofs = 0; + for (i = 0; i < vp->id; i++) + ofs += vop2->vps[i].nlayers; + + drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { + struct vop2_win *win = to_vop2_win(plane); + struct vop2_win *old_win; + + layer_id = (u8)(plane->state->normalized_zpos + ofs); + /* + * Find the layer this win bind in old state. + */ + for (old_layer_id = 0; old_layer_id < vop2->data->win_size; old_layer_id++) { + layer_sel_id = (layer_sel >> (4 * old_layer_id)) & 0xf; + if (layer_sel_id == win->data->layer_sel_id) + break; + } + + /* + * Find the win bind to this layer in old state + */ + for (i = 0; i < vop2->data->win_size; i++) { + old_win = &vop2->win[i]; + layer_sel_id = (layer_sel >> (4 * layer_id)) & 0xf; + if (layer_sel_id == old_win->data->layer_sel_id) + break; + } + + switch (win->data->phys_id) { + case ROCKCHIP_VOP2_CLUSTER0: + port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER0; + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER0, vp->id); + break; + case ROCKCHIP_VOP2_CLUSTER1: + port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER1; + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id); + break; + case ROCKCHIP_VOP2_CLUSTER2: + port_sel &= ~RK3588_OVL_PORT_SEL__CLUSTER2; + port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER2, vp->id); + break; + case ROCKCHIP_VOP2_CLUSTER3: + port_sel &= ~RK3588_OVL_PORT_SEL__CLUSTER3; + port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER3, vp->id); + break; + case ROCKCHIP_VOP2_ESMART0: + port_sel &= ~RK3568_OVL_PORT_SEL__ESMART0; + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id); + break; + case ROCKCHIP_VOP2_ESMART1: + port_sel &= ~RK3568_OVL_PORT_SEL__ESMART1; + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id); + break; + case ROCKCHIP_VOP2_ESMART2: + port_sel &= ~RK3588_OVL_PORT_SEL__ESMART2; + port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART2, vp->id); + break; + case ROCKCHIP_VOP2_ESMART3: + port_sel &= ~RK3588_OVL_PORT_SEL__ESMART3; + port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART3, vp->id); + break; + case ROCKCHIP_VOP2_SMART0: + port_sel &= ~RK3568_OVL_PORT_SEL__SMART0; + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id); + break; + case ROCKCHIP_VOP2_SMART1: + port_sel &= ~RK3568_OVL_PORT_SEL__SMART1; + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART1, vp->id); + break; + } + + layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(layer_id, 0x7); + layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(layer_id, win->data->layer_sel_id); + /* + * When we bind a window from layerM to layerN, we also need to move the old + * window on layerN to layerM to avoid one window selected by two or more layers. + */ + layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(old_layer_id, 0x7); + layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(old_layer_id, old_win->data->layer_sel_id); + } + + vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel); + vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel); +} + +static void rk3568_vop2_setup_dly_for_windows(struct vop2_video_port *vp) +{ + struct vop2 *vop2 = vp->vop2; + struct vop2_win *win; + int i = 0; + u32 cdly = 0, sdly = 0; + + for (i = 0; i < vop2->data->win_size; i++) { + u32 dly; + + win = &vop2->win[i]; + dly = win->delay; + + switch (win->data->phys_id) { + case ROCKCHIP_VOP2_CLUSTER0: + cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_0, dly); + cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_1, dly); + break; + case ROCKCHIP_VOP2_CLUSTER1: + cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_0, dly); + cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_1, dly); + break; + case ROCKCHIP_VOP2_ESMART0: + sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART0, dly); + break; + case ROCKCHIP_VOP2_ESMART1: + sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART1, dly); + break; + case ROCKCHIP_VOP2_SMART0: + case ROCKCHIP_VOP2_ESMART2: + sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART0, dly); + break; + case ROCKCHIP_VOP2_SMART1: + case ROCKCHIP_VOP2_ESMART3: + sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART1, dly); + break; + } + } + + vop2_writel(vop2, RK3568_CLUSTER_DLY_NUM, cdly); + vop2_writel(vop2, RK3568_SMART_DLY_NUM, sdly); +} + +static void rk3568_vop2_setup_overlay(struct vop2_video_port *vp) +{ + struct vop2 *vop2 = vp->vop2; + struct drm_crtc *crtc = &vp->crtc; + struct drm_plane *plane; + + vp->win_mask = 0; + + drm_atomic_crtc_for_each_plane(plane, crtc) { + struct vop2_win *win = to_vop2_win(plane); + + win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT]; + + vp->win_mask |= BIT(win->data->phys_id); + + if (vop2_cluster_window(win)) + vop2_setup_cluster_alpha(vop2, win); + } + + if (!vp->win_mask) + return; + + rk3568_vop2_setup_layer_mixer(vp); + vop2_setup_alpha(vp); + rk3568_vop2_setup_dly_for_windows(vp); +} + +static void rk3568_vop2_setup_bg_dly(struct vop2_video_port *vp) +{ + struct drm_crtc *crtc = &vp->crtc; + struct drm_display_mode *mode = &crtc->state->adjusted_mode; + u16 hdisplay = mode->crtc_hdisplay; + u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; + u32 bg_dly; + u32 pre_scan_dly; + + bg_dly = vp->data->pre_scan_max_dly[3]; + vop2_writel(vp->vop2, RK3568_VP_BG_MIX_CTRL(vp->id), + FIELD_PREP(RK3568_VP_BG_MIX_CTRL__BG_DLY, bg_dly)); + + pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len; + vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly); +} + +static const struct vop2_ops rk3568_vop_ops = { + .setup_intf_mux = rk3568_set_intf_mux, + .setup_bg_dly = rk3568_vop2_setup_bg_dly, + .setup_overlay = rk3568_vop2_setup_overlay, +}; + +static const struct vop2_ops rk3588_vop_ops = { + .setup_intf_mux = rk3588_set_intf_mux, + .setup_bg_dly = rk3568_vop2_setup_bg_dly, + .setup_overlay = rk3568_vop2_setup_overlay, +}; + static const struct vop2_data rk3566_vop = { .feature = VOP2_FEATURE_HAS_SYS_GRF, .nr_vps = 3, @@ -655,8 +1632,13 @@ static const struct vop2_data rk3566_vop = { .vp = rk3568_vop_video_ports, .win = rk3568_vop_win_data, .win_size = ARRAY_SIZE(rk3568_vop_win_data), + .cluster_reg = rk3568_vop_cluster_regs, + .nr_cluster_regs = ARRAY_SIZE(rk3568_vop_cluster_regs), + .smart_reg = rk3568_vop_smart_regs, + .nr_smart_regs = ARRAY_SIZE(rk3568_vop_smart_regs), .regs_dump = rk3568_regs_dump, .regs_dump_size = ARRAY_SIZE(rk3568_regs_dump), + .ops = &rk3568_vop_ops, .soc_id = 3566, }; @@ -668,8 +1650,13 @@ static const struct vop2_data rk3568_vop = { .vp = rk3568_vop_video_ports, .win = rk3568_vop_win_data, .win_size = ARRAY_SIZE(rk3568_vop_win_data), + .cluster_reg = rk3568_vop_cluster_regs, + .nr_cluster_regs = ARRAY_SIZE(rk3568_vop_cluster_regs), + .smart_reg = rk3568_vop_smart_regs, + .nr_smart_regs = ARRAY_SIZE(rk3568_vop_smart_regs), .regs_dump = rk3568_regs_dump, .regs_dump_size = ARRAY_SIZE(rk3568_regs_dump), + .ops = &rk3568_vop_ops, .soc_id = 3568, }; @@ -682,8 +1669,13 @@ static const struct vop2_data rk3588_vop = { .vp = rk3588_vop_video_ports, .win = rk3588_vop_win_data, .win_size = ARRAY_SIZE(rk3588_vop_win_data), + .cluster_reg = rk3568_vop_cluster_regs, + .nr_cluster_regs = ARRAY_SIZE(rk3568_vop_cluster_regs), + .smart_reg = rk3568_vop_smart_regs, + .nr_smart_regs = ARRAY_SIZE(rk3568_vop_smart_regs), .regs_dump = rk3588_regs_dump, .regs_dump_size = ARRAY_SIZE(rk3588_regs_dump), + .ops = &rk3588_vop_ops, .soc_id = 3588, }; From patchwork Thu Feb 6 06:44:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962412 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 89836C02196 for ; Thu, 6 Feb 2025 06:55:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=7LqLMQ0IR8uerlNkR5n5P9j3Dr4UfDPYGl+yioHTkRY=; b=ALznxNaMHwn941 VbynyxHwXdGgb/7gIwpgINZgbEO146bEYcQmD58CKRX8emGL1srOBL5mbytQKmtbdhuVkAA5N37kq nrWP91b66Ws5KdrNY00/OPI6mPpUAJIrdVvCOJKNTORMkNeaYL166elw06o+qjrX+gXM2j/d6pjBJ WOQYwA7z7pe6ugX/eRbqCMC0BO8Vgox6Bx8Bh2Uyes8BDg5o6WmtHIfo7yg9ftABur4187XVuatN8 IQ42CMeOh0PGcvxQb2ktdp7FYsJ3GWK2bCWB0OGiezkELLn7dVj8RXE08X+fqUPImm3+Kd7a3PFyv Nr5rpk4YSgFaLGFp0iLw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvnO-00000005T5t-1fXR; Thu, 06 Feb 2025 06:55:30 +0000 Received: from m16.mail.163.com ([220.197.31.2]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvdo-00000005Q8Z-2fgx; Thu, 06 Feb 2025 06:45:39 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=zlwQ/ zugAITGUW6CmnYVDBT+3S9dhbJfYNreL5Qv5dI=; b=gwvHgV1GEDoW4MPcIWFbd xUFgmkDp8hac3v85fPKzST22G+7gORxQsHU1fCJVpjiXTAPevKIy2E4TnUKDikjD JY1i9W3z9H9UDjNj3NbXOAW22FsdV4KI+jJzcMzIedGZhahlr0E4JD2cex2gQsYe qWHT+2Zian5tq7qpH38GVM= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-0 (Coremail) with SMTP id _____wD3fyNsWqRnb3bDKQ--.52146S6; Thu, 06 Feb 2025 14:45:08 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan Subject: [PATCH v13 04/13] drm/rockchip: vop2: Merge vop2_cluster/esmart_init function Date: Thu, 6 Feb 2025 14:44:32 +0800 Message-ID: <20250206064457.11396-5-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3fyNsWqRnb3bDKQ--.52146S6 X-Coremail-Antispam: 1Uf129KBjvJXoWxWw4UKF17CrWktr18AFykAFb_yoW5Xr1DpF W3Jr43Xr4UGFsF9r4kJrn8uF1Fkr12yaykAa48KwnIkwnrKF9FkFn5JF10yr90krWvkFy2 yFs7K3y3ua429r7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jbb1nUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqAXrXmekT+DQdgABsT X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224536_995978_2A0F8AB0 X-CRM114-Status: GOOD ( 10.91 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Andy Yan Now these two function share the same logic, the can be merged as one. Signed-off-by: Andy Yan --- (no changes since v1) drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 42 +++++--------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index f7e2df1431b0..29a81ff152f3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -2398,18 +2398,18 @@ static int vop2_find_rgb_encoder(struct vop2 *vop2) return -ENOENT; } -static int vop2_cluster_init(struct vop2_win *win) +static int vop2_regmap_init(struct vop2_win *win, const struct reg_field *regs, + int nr_regs) { struct vop2 *vop2 = win->vop2; int i; - for (i = 0; i < vop2->data->nr_cluster_regs; i++) { + for (i = 0; i < nr_regs; i++) { const struct reg_field field = { - .reg = (vop2->data->cluster_reg[i].reg != 0xffffffff) ? - vop2->data->cluster_reg[i].reg + win->offset : - vop2->data->cluster_reg[i].reg, - .lsb = vop2->data->cluster_reg[i].lsb, - .msb = vop2->data->cluster_reg[i].msb + .reg = (regs[i].reg != 0xffffffff) ? + regs[i].reg + win->offset : regs[i].reg, + .lsb = regs[i].lsb, + .msb = regs[i].msb }; win->reg[i] = devm_regmap_field_alloc(vop2->dev, vop2->map, field); @@ -2420,28 +2420,6 @@ static int vop2_cluster_init(struct vop2_win *win) return 0; }; -static int vop2_esmart_init(struct vop2_win *win) -{ - struct vop2 *vop2 = win->vop2; - int i; - - for (i = 0; i < vop2->data->nr_smart_regs; i++) { - const struct reg_field field = { - .reg = (vop2->data->smart_reg[i].reg != 0xffffffff) ? - vop2->data->smart_reg[i].reg + win->offset : - vop2->data->smart_reg[i].reg, - .lsb = vop2->data->smart_reg[i].lsb, - .msb = vop2->data->smart_reg[i].msb - }; - - win->reg[i] = devm_regmap_field_alloc(vop2->dev, vop2->map, field); - if (IS_ERR(win->reg[i])) - return PTR_ERR(win->reg[i]); - } - - return 0; -} - static int vop2_win_init(struct vop2 *vop2) { const struct vop2_data *vop2_data = vop2->data; @@ -2458,9 +2436,11 @@ static int vop2_win_init(struct vop2 *vop2) win->win_id = i; win->vop2 = vop2; if (vop2_cluster_window(win)) - ret = vop2_cluster_init(win); + ret = vop2_regmap_init(win, vop2->data->cluster_reg, + vop2->data->nr_cluster_regs); else - ret = vop2_esmart_init(win); + ret = vop2_regmap_init(win, vop2->data->smart_reg, + vop2->data->nr_cluster_regs); if (ret) return ret; } From patchwork Thu Feb 6 06:44:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962399 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id DB3A0C02198 for ; Thu, 6 Feb 2025 06:52:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=0BXgOOslADohYTWkKRPWso1sYMmbilAg0tN5IRGukkk=; b=22Fp/WOEwbO8LC 02yT1jhWL5RZat50u0GEXRI9OVT9245PbvgoeMvlCoVQLVcze73mTNJxgUpntEPLCREAFXM+WoSn5 k3cao2eFx3g54IkgE92m6YOy4ySjkf7pccsLSeg0rMJRy3pQZa/ON8RDUjnEp3tNvB8PBEROmsDIM QzqMxi+Iw4VzQ0inHGLa+NPIrKwy2CdGnwvatzgZb0RCinHwrpgC9nzfR27F5Ca1GodC7yBT1xGqH vZ7hwCyk15mn3/ZOR/9srFLRBUrBgsMJ8aW8mcpthwNUoC+q43lg0nb6F3pU/PdlR/nBYA4/9BVAn LcJJIJ/D+D9yB/imRJeQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvkg-00000005SSe-0N8E; Thu, 06 Feb 2025 06:52:42 +0000 Received: from m16.mail.163.com ([220.197.31.4]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvdo-00000005Q8Q-1J6D; Thu, 06 Feb 2025 06:45:38 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=RBIBi lYDxeWRgNlHC/vhx3XpCGxCxrSjnVrypHsJqyM=; b=CP3z5NKm+rRTGoKowWqvq V1rp3Cal7VMwUJaGm8awwygrQXBvO80MO7qap1ZOagWZeDkTIm9M/EHVZSjHYkSu 4EfmeReuKH06P+jT5Go0+mkOMgPoJ/8ZHYQKHGaqi0Mq0j9PqGQB1sroCrf01HGR 9r9wcmB/pJzSIXUGlG9avk= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-0 (Coremail) with SMTP id _____wD3fyNsWqRnb3bDKQ--.52146S7; Thu, 06 Feb 2025 14:45:09 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan , Michael Riesch Subject: [PATCH v13 05/13] drm/rockchip: vop2: Support for different layer select configuration between VPs Date: Thu, 6 Feb 2025 14:44:33 +0800 Message-ID: <20250206064457.11396-6-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3fyNsWqRnb3bDKQ--.52146S7 X-Coremail-Antispam: 1Uf129KBjvJXoWxtrW8JF4UZF47CF4UWFy8Zrb_yoWfJw4Upa yUursIg3W5Cr45tryUJayrZr4rGwn8tay3uan3Kw1xGFn5KrWDJF4ktF95A3Z8KF93ZryU Xw1YgryDZrW7tFJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jx0eQUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqQrrXmekUdSn4wAAsU X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224536_660228_C4A0F716 X-CRM114-Status: GOOD ( 14.32 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Andy Yan In the upcoming VOP for rk3576, every VP has it's own LAYER_SEL register, and the configuration value of each VP for the same window maybe different, so extend the layer_sel_id to array, let it can descption the layer select configuration value for different VP. Signed-off-by: Andy Yan Tested-by: Michael Riesch # on RK3568 Tested-by: Detlev Casanova --- (no changes since v4) Changes in v4: - Typo fix: selet->select drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 4 +-- drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 38 ++++++++++---------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h index 7cdef4c98bf6..37cdf0ed9455 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h @@ -166,9 +166,9 @@ struct vop2_win_data { const unsigned int supported_rotations; /** - * @layer_sel_id: defined by register OVERLAY_LAYER_SEL of VOP2 + * @layer_sel_id: defined by register OVERLAY_LAYER_SEL or PORTn_LAYER_SEL */ - unsigned int layer_sel_id; + unsigned int layer_sel_id[ROCKCHIP_MAX_CRTC]; uint64_t feature; uint8_t axi_bus_id; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 9e42251ee796..8160f76de995 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -350,7 +350,8 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { .formats = formats_smart, .nformats = ARRAY_SIZE(formats_smart), .format_modifiers = format_modifiers, - .layer_sel_id = 3, + /* 0xf means this layer can't attached to this VP */ + .layer_sel_id = { 3, 3, 3, 0xf }, .supported_rotations = DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_PRIMARY, .max_upscale_factor = 8, @@ -363,7 +364,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { .nformats = ARRAY_SIZE(formats_smart), .format_modifiers = format_modifiers, .base = 0x1e00, - .layer_sel_id = 7, + .layer_sel_id = { 7, 7, 7, 0xf }, .supported_rotations = DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_PRIMARY, .max_upscale_factor = 8, @@ -376,7 +377,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { .nformats = ARRAY_SIZE(formats_rk356x_esmart), .format_modifiers = format_modifiers, .base = 0x1a00, - .layer_sel_id = 6, + .layer_sel_id = { 6, 6, 6, 0xf }, .supported_rotations = DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_PRIMARY, .max_upscale_factor = 8, @@ -389,7 +390,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { .nformats = ARRAY_SIZE(formats_rk356x_esmart), .format_modifiers = format_modifiers, .base = 0x1800, - .layer_sel_id = 2, + .layer_sel_id = { 2, 2, 2, 0xf }, .supported_rotations = DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_PRIMARY, .max_upscale_factor = 8, @@ -402,7 +403,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { .formats = formats_cluster, .nformats = ARRAY_SIZE(formats_cluster), .format_modifiers = format_modifiers_afbc, - .layer_sel_id = 0, + .layer_sel_id = { 0, 0, 0, 0xf }, .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, .max_upscale_factor = 4, @@ -417,7 +418,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { .formats = formats_cluster, .nformats = ARRAY_SIZE(formats_cluster), .format_modifiers = format_modifiers_afbc, - .layer_sel_id = 1, + .layer_sel_id = { 1, 1, 1, 0xf }, .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_OVERLAY, @@ -582,7 +583,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .formats = formats_cluster, .nformats = ARRAY_SIZE(formats_cluster), .format_modifiers = format_modifiers_afbc, - .layer_sel_id = 0, + .layer_sel_id = { 0, 0, 0, 0 }, .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, .axi_bus_id = 0, @@ -600,7 +601,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .formats = formats_cluster, .nformats = ARRAY_SIZE(formats_cluster), .format_modifiers = format_modifiers_afbc, - .layer_sel_id = 1, + .layer_sel_id = { 1, 1, 1, 1 }, .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_PRIMARY, @@ -618,7 +619,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .formats = formats_cluster, .nformats = ARRAY_SIZE(formats_cluster), .format_modifiers = format_modifiers_afbc, - .layer_sel_id = 4, + .layer_sel_id = { 4, 4, 4, 4 }, .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_PRIMARY, @@ -636,7 +637,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .formats = formats_cluster, .nformats = ARRAY_SIZE(formats_cluster), .format_modifiers = format_modifiers_afbc, - .layer_sel_id = 5, + .layer_sel_id = { 5, 5, 5, 5 }, .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_PRIMARY, @@ -654,7 +655,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .nformats = ARRAY_SIZE(formats_esmart), .format_modifiers = format_modifiers, .base = 0x1800, - .layer_sel_id = 2, + .layer_sel_id = { 2, 2, 2, 2 }, .supported_rotations = DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_OVERLAY, .axi_bus_id = 0, @@ -670,7 +671,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .nformats = ARRAY_SIZE(formats_esmart), .format_modifiers = format_modifiers, .base = 0x1a00, - .layer_sel_id = 3, + .layer_sel_id = { 3, 3, 3, 3 }, .supported_rotations = DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_OVERLAY, .axi_bus_id = 0, @@ -686,7 +687,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .formats = formats_esmart, .nformats = ARRAY_SIZE(formats_esmart), .format_modifiers = format_modifiers, - .layer_sel_id = 6, + .layer_sel_id = { 6, 6, 6, 6 }, .supported_rotations = DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_OVERLAY, .axi_bus_id = 1, @@ -702,7 +703,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .nformats = ARRAY_SIZE(formats_esmart), .format_modifiers = format_modifiers, .base = 0x1e00, - .layer_sel_id = 7, + .layer_sel_id = { 7, 7, 7, 7 }, .supported_rotations = DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_OVERLAY, .axi_bus_id = 1, @@ -1454,7 +1455,7 @@ static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp) */ for (old_layer_id = 0; old_layer_id < vop2->data->win_size; old_layer_id++) { layer_sel_id = (layer_sel >> (4 * old_layer_id)) & 0xf; - if (layer_sel_id == win->data->layer_sel_id) + if (layer_sel_id == win->data->layer_sel_id[vp->id]) break; } @@ -1464,7 +1465,7 @@ static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp) for (i = 0; i < vop2->data->win_size; i++) { old_win = &vop2->win[i]; layer_sel_id = (layer_sel >> (4 * layer_id)) & 0xf; - if (layer_sel_id == old_win->data->layer_sel_id) + if (layer_sel_id == old_win->data->layer_sel_id[vp->id]) break; } @@ -1512,13 +1513,14 @@ static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp) } layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(layer_id, 0x7); - layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(layer_id, win->data->layer_sel_id); + layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(layer_id, win->data->layer_sel_id[vp->id]); /* * When we bind a window from layerM to layerN, we also need to move the old * window on layerN to layerM to avoid one window selected by two or more layers. */ layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(old_layer_id, 0x7); - layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(old_layer_id, old_win->data->layer_sel_id); + layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(old_layer_id, + old_win->data->layer_sel_id[vp->id]); } vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel); From patchwork Thu Feb 6 06:44:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962400 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id AE709C02196 for ; Thu, 6 Feb 2025 06:54:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=h1eBM2ywERzpgThqra17S3m2SorzlrEBjMKi5OunqcU=; b=w94qVFQPu4xFgh 56TNNDvzaO9N+To44tSbpaKQALGgCgFnvGuzPQCZKwi2xJKHRktSl5BdMUC3JKDVO2a4BTIubHTVL /oZPBvdDxi0NeMoWp3zPH3t4usqv7aaJ6oky7EZ12j5tQ8t4xnOQw/b29h0jxV92YqxZQ1EZF+0ju CqCoeisnm95Hk8EpfF6RyX4NUSFfDpyp4w/FKKzfEafTNqhH3K80ZABUe6Z3yA8tBI8pnHQlaW/i4 ZObh5OCEs4kGfNPEdAVDMS1aJC31/HjBi0e1rsAMEcXVneKqfKrJY6md9nwVvzQ4nrYquDlMo4sEO YAhza9/eFq79EbeZOCIQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvm2-00000005Sqg-1TMU; Thu, 06 Feb 2025 06:54:06 +0000 Received: from m16.mail.163.com ([117.135.210.5]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvdo-00000005Q8E-1XeO; Thu, 06 Feb 2025 06:45:39 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=wpClk ZEI5D6kO/kYiTNkj5YjM1oJMKfFedcu1QFFa5U=; b=BkTcnM3dEollPgAbP/PQL eCJ49W6N9TzZU9o6Z9GTbLs/KyBd4hIZZvEWaf9g6JbNmjsG4YVyaWHZb6V91mRo O3aHIHiH2+e5BUSWiy9NOMrv1ekmFGFqSJJwceqfl8qo2D9rgxA0QZY14VMBY8kQ v00SmOGMKfxpD4i0Ahy+PM= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-0 (Coremail) with SMTP id _____wD3fyNsWqRnb3bDKQ--.52146S8; Thu, 06 Feb 2025 14:45:10 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan , Michael Riesch Subject: [PATCH v13 06/13] drm/rockchip: vop2: Introduce vop hardware version Date: Thu, 6 Feb 2025 14:44:34 +0800 Message-ID: <20250206064457.11396-7-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3fyNsWqRnb3bDKQ--.52146S8 X-Coremail-Antispam: 1Uf129KBjvJXoW3Xry3tF47Cry8WF4fWF1xXwb_yoWxKw1xpF W7Aay5WrWxGa1qgw4kJay3ZF43twn2yay7JanrGw13t3sxKr9rGan0qF1ayFZ8tr92kr4j yFs7ArW5WF4jyr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jx0eQUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/xtbB0hfrXmekTP7+nAAAsj X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224536_887404_E169EEB4 X-CRM114-Status: GOOD ( 18.46 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Andy Yan There is a version number hardcoded in the VOP VERSION_INFO register, and the version number increments sequentially based on the production order of the SOC. So using this version number to distinguish different VOP features will simplify the code. Signed-off-by: Andy Yan Tested-by: Michael Riesch # on RK3568 Tested-by: Detlev Casanova --- (no changes since v6) Changes in v6: - Add a blank line after hardware version check code Changes in v3: - Add comments for why we should treat rk3566 with special care. - Add hardware version check Changes in v2: - Introduce vop hardware version drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 26 ++++++++++++++------ drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 11 +++++++++ drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 3 +++ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 29a81ff152f3..a1a0383713b5 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -354,7 +354,7 @@ static bool vop2_output_uv_swap(u32 bus_format, u32 output_mode) static bool vop2_output_rg_swap(struct vop2 *vop2, u32 bus_format) { - if (vop2->data->soc_id == 3588) { + if (vop2->version == VOP_VERSION_RK3588) { if (bus_format == MEDIA_BUS_FMT_YUV8_1X24 || bus_format == MEDIA_BUS_FMT_YUV10_1X30) return true; @@ -407,7 +407,7 @@ static bool rockchip_vop2_mod_supported(struct drm_plane *plane, u32 format, if (modifier == DRM_FORMAT_MOD_INVALID) return false; - if (vop2->data->soc_id == 3568 || vop2->data->soc_id == 3566) { + if (vop2->version == VOP_VERSION_RK3568) { if (vop2_cluster_window(win)) { if (modifier == DRM_FORMAT_MOD_LINEAR) { drm_dbg_kms(vop2->drm, @@ -418,7 +418,7 @@ static bool rockchip_vop2_mod_supported(struct drm_plane *plane, u32 format, } if (format == DRM_FORMAT_XRGB2101010 || format == DRM_FORMAT_XBGR2101010) { - if (vop2->data->soc_id == 3588) { + if (vop2->version == VOP_VERSION_RK3588) { if (!rockchip_afbc(plane, modifier)) { drm_dbg_kms(vop2->drm, "Only support 32 bpp format with afbc\n"); return false; @@ -817,6 +817,7 @@ static void rk3588_vop2_power_domain_enable_all(struct vop2 *vop2) static void vop2_enable(struct vop2 *vop2) { int ret; + u32 version; ret = pm_runtime_resume_and_get(vop2->dev); if (ret < 0) { @@ -836,10 +837,20 @@ static void vop2_enable(struct vop2 *vop2) return; } + version = vop2_readl(vop2, RK3568_VERSION_INFO); + if (version != vop2->version) { + drm_err(vop2->drm, "Hardware version(0x%08x) mismatch\n", version); + return; + } + + /* + * rk3566 share the same vop version with rk3568, so + * wen need to use soc_id for identification here. + */ if (vop2->data->soc_id == 3566) vop2_writel(vop2, RK3568_OTP_WIN_EN, 1); - if (vop2->data->soc_id == 3588) + if (vop2->version == VOP_VERSION_RK3588) rk3588_vop2_power_domain_enable_all(vop2); vop2_writel(vop2, RK3568_REG_CFG_DONE, RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN); @@ -920,7 +931,7 @@ static void vop2_vp_dsp_lut_update_enable(struct vop2_video_port *vp) static inline bool vop2_supports_seamless_gamma_lut_update(struct vop2 *vop2) { - return (vop2->data->soc_id != 3566 && vop2->data->soc_id != 3568); + return vop2->version != VOP_VERSION_RK3568; } static bool vop2_gamma_lut_in_use(struct vop2 *vop2, struct vop2_video_port *vp) @@ -1259,7 +1270,7 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, &fb->format->format, afbc_en ? "AFBC" : "", &yrgb_mst); - if (vop2->data->soc_id > 3568) { + if (vop2->version > VOP_VERSION_RK3568) { vop2_win_write(win, VOP2_WIN_AXI_BUS_ID, win->data->axi_bus_id); vop2_win_write(win, VOP2_WIN_AXI_YRGB_R_ID, win->data->axi_yrgb_r_id); vop2_win_write(win, VOP2_WIN_AXI_UV_R_ID, win->data->axi_uv_r_id); @@ -1319,7 +1330,7 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, * this bit is gating disable, we should write 1 to * disable gating when enable afbc. */ - if (vop2->data->soc_id == 3566 || vop2->data->soc_id == 3568) + if (vop2->version == VOP_VERSION_RK3568) vop2_win_write(win, VOP2_WIN_AFBC_AUTO_GATING_EN, 0); else vop2_win_write(win, VOP2_WIN_AFBC_AUTO_GATING_EN, 1); @@ -2498,6 +2509,7 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) vop2->dev = dev; vop2->data = vop2_data; vop2->ops = vop2_data->ops; + vop2->version = vop2_data->version; vop2->drm = drm; dev_set_drvdata(dev, vop2); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h index 37cdf0ed9455..485462749121 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h @@ -13,6 +13,15 @@ #include "rockchip_drm_drv.h" #include "rockchip_drm_vop.h" +#define VOP2_VERSION(major, minor, build) ((major) << 24 | (minor) << 16 | (build)) + +/* The new SOC VOP version is bigger than the old */ +#define VOP_VERSION_RK3568 VOP2_VERSION(0x40, 0x15, 0x8023) +#define VOP_VERSION_RK3588 VOP2_VERSION(0x40, 0x17, 0x6786) +#define VOP_VERSION_RK3528 VOP2_VERSION(0x50, 0x17, 0x1263) +#define VOP_VERSION_RK3562 VOP2_VERSION(0x50, 0x17, 0x4350) +#define VOP_VERSION_RK3576 VOP2_VERSION(0x50, 0x19, 0x9765) + #define VOP2_VP_FEATURE_OUTPUT_10BIT BIT(0) #define VOP2_FEATURE_HAS_SYS_GRF BIT(0) @@ -242,6 +251,7 @@ struct vop2_ops { struct vop2_data { u8 nr_vps; u64 feature; + u32 version; const struct vop2_ops *ops; const struct vop2_win_data *win; const struct vop2_video_port_data *vp; @@ -259,6 +269,7 @@ struct vop2_data { }; struct vop2 { + u32 version; struct device *dev; struct drm_device *drm; struct vop2_video_port vps[ROCKCHIP_MAX_CRTC]; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 8160f76de995..248b9e6729e9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -1627,6 +1627,7 @@ static const struct vop2_ops rk3588_vop_ops = { }; static const struct vop2_data rk3566_vop = { + .version = VOP_VERSION_RK3568, .feature = VOP2_FEATURE_HAS_SYS_GRF, .nr_vps = 3, .max_input = { 4096, 2304 }, @@ -1645,6 +1646,7 @@ static const struct vop2_data rk3566_vop = { }; static const struct vop2_data rk3568_vop = { + .version = VOP_VERSION_RK3568, .feature = VOP2_FEATURE_HAS_SYS_GRF, .nr_vps = 3, .max_input = { 4096, 2304 }, @@ -1663,6 +1665,7 @@ static const struct vop2_data rk3568_vop = { }; static const struct vop2_data rk3588_vop = { + .version = VOP_VERSION_RK3588, .feature = VOP2_FEATURE_HAS_SYS_GRF | VOP2_FEATURE_HAS_VO1_GRF | VOP2_FEATURE_HAS_VOP_GRF | VOP2_FEATURE_HAS_SYS_PMU, .nr_vps = 4, From patchwork Thu Feb 6 06:44:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962397 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id F18C8C02196 for ; Thu, 6 Feb 2025 06:51:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=oqeczOxeM1qS41Eod55ic07HK9dzmMuIhlbCGGomaOc=; b=JLQLNQxbiqzyFq KdGweV+aX3cjJGpnCY+WTY/xzdjOw4+vnkDDDoOBpjIZgU59CSniI+wp/orlPyjrWxa1rz9ewzVps 6g1e37+2sj/jCGpV4XGh4fvfCSusD+Zz/gvTtxvx1s0t+k3ADlVKkI3Q7syT3WeN0tooblkdo1PX4 EVtF179JBmojqhC8wLpQKQ+W6JM2jPUZiFGRvrWho73GR+1aVUmGGx7/oXmQvV17JJZMg28j50GE9 vaY6TsUIerkVnqKpqM3CISvVAsZSOO1wRm/SeH0fCDJh0MAd2pDr55PjPdRa4F6TXs/YAOgxEFi9k 7MW1l+H0IG2n1vyIFv7w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvjJ-00000005S6b-43s9; Thu, 06 Feb 2025 06:51:17 +0000 Received: from m16.mail.163.com ([220.197.31.4]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvdo-00000005Q8Y-194f; Thu, 06 Feb 2025 06:45:38 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=vx4b9 04GoBOQPZxPkHCVqjXWtg+tthn2HPth/upQ9wQ=; b=B3mmsJ14PIy3npz4/mcPx y1MrNGyMUmF73io7Qx7w7+qGDcXmdRRzX7g/F5/JJcGBXLoEJS77i6XtXdZiz3nZ GV+tV8xXuuOkExMjRFEHh7d5o5eLJfnimGhHtSPRwh9Ce8gr6JFcCdI7hdhX3B1W znyZ1PVu2ZWq9gchod8eag= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-0 (Coremail) with SMTP id _____wD3fyNsWqRnb3bDKQ--.52146S9; Thu, 06 Feb 2025 14:45:11 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan , Michael Riesch Subject: [PATCH v13 07/13] drm/rockchip: vop2: Register the primary plane and overlay plane separately Date: Thu, 6 Feb 2025 14:44:35 +0800 Message-ID: <20250206064457.11396-8-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3fyNsWqRnb3bDKQ--.52146S9 X-Coremail-Antispam: 1Uf129KBjvJXoWxGFWxtw4kKr43tFyrKryxuFg_yoWrZrW3pa 13ta90qr4xWrsFgry8JF4jyFWYyan2kay7Crn8Gw1a934Sgr93ur48KF1DAF15uFnrWFya kFW3K39Y9FWj9r7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jx0eQUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqRrrXmekUdSn9gAAsR X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224536_667144_0E859E8F X-CRM114-Status: GOOD ( 15.53 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Andy Yan In the upcoming VOP of rk3576, a Window cannot attach to all Video Ports, so make sure all VP find it's suitable primary plane, then register the remain windows as overlay plane will make code easier. Signed-off-by: Andy Yan Tested-by: Michael Riesch # on RK3568 Tested-by: Detlev Casanova --- (no changes since v3) Changes in v3: - Add comments for why we should treat rk3566 with special care. drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 100 +++++++++++-------- 1 file changed, 61 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index a1a0383713b5..d3e21fb00225 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -2222,22 +2222,29 @@ static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, return 0; } -static struct vop2_video_port *find_vp_without_primary(struct vop2 *vop2) +/* + * On RK3566 these windows don't have an independent + * framebuffer. They can only share/mirror the framebuffer + * with smart0, esmart0 and cluster0 respectively. + * And RK3566 share the same vop version with Rk3568, so we + * need to use soc_id for identification here. + */ +static bool vop2_is_mirror_win(struct vop2_win *win) { - int i; - - for (i = 0; i < vop2->data->nr_vps; i++) { - struct vop2_video_port *vp = &vop2->vps[i]; - - if (!vp->crtc.port) - continue; - if (vp->primary_plane) - continue; + struct vop2 *vop2 = win->vop2; - return vp; + if (vop2->data->soc_id == 3566) { + switch (win->data->phys_id) { + case ROCKCHIP_VOP2_SMART1: + case ROCKCHIP_VOP2_ESMART1: + case ROCKCHIP_VOP2_CLUSTER1: + return true; + default: + return false; + } + } else { + return false; } - - return NULL; } static int vop2_create_crtcs(struct vop2 *vop2) @@ -2248,7 +2255,9 @@ static int vop2_create_crtcs(struct vop2 *vop2) struct drm_plane *plane; struct device_node *port; struct vop2_video_port *vp; - int i, nvp, nvps = 0; + struct vop2_win *win; + u32 possible_crtcs; + int i, j, nvp, nvps = 0; int ret; for (i = 0; i < vop2_data->nr_vps; i++) { @@ -2287,42 +2296,55 @@ static int vop2_create_crtcs(struct vop2 *vop2) } nvp = 0; - for (i = 0; i < vop2->registered_num_wins; i++) { - struct vop2_win *win = &vop2->win[i]; - u32 possible_crtcs = 0; - - if (vop2->data->soc_id == 3566) { - /* - * On RK3566 these windows don't have an independent - * framebuffer. They share the framebuffer with smart0, - * esmart0 and cluster0 respectively. - */ - switch (win->data->phys_id) { - case ROCKCHIP_VOP2_SMART1: - case ROCKCHIP_VOP2_ESMART1: - case ROCKCHIP_VOP2_CLUSTER1: + /* Register a primary plane for every crtc */ + for (i = 0; i < vop2_data->nr_vps; i++) { + vp = &vop2->vps[i]; + + if (!vp->crtc.port) + continue; + + for (j = 0; j < vop2->registered_num_wins; j++) { + win = &vop2->win[j]; + + /* Aready registered as primary plane */ + if (win->base.type == DRM_PLANE_TYPE_PRIMARY) + continue; + + if (vop2_is_mirror_win(win)) continue; - } - } - if (win->type == DRM_PLANE_TYPE_PRIMARY) { - vp = find_vp_without_primary(vop2); - if (vp) { + if (win->type == DRM_PLANE_TYPE_PRIMARY) { possible_crtcs = BIT(nvp); vp->primary_plane = win; + ret = vop2_plane_init(vop2, win, possible_crtcs); + if (ret) { + drm_err(vop2->drm, "failed to init primary plane %s: %d\n", + win->data->name, ret); + return ret; + } nvp++; - } else { - /* change the unused primary window to overlay window */ - win->type = DRM_PLANE_TYPE_OVERLAY; + break; } } + } + + /* Register all unused window as overlay plane */ + for (i = 0; i < vop2->registered_num_wins; i++) { + win = &vop2->win[i]; + + /* Aready registered as primary plane */ + if (win->base.type == DRM_PLANE_TYPE_PRIMARY) + continue; + + if (vop2_is_mirror_win(win)) + continue; - if (win->type == DRM_PLANE_TYPE_OVERLAY) - possible_crtcs = (1 << nvps) - 1; + win->type = DRM_PLANE_TYPE_OVERLAY; + possible_crtcs = (1 << nvps) - 1; ret = vop2_plane_init(vop2, win, possible_crtcs); if (ret) { - drm_err(vop2->drm, "failed to init plane %s: %d\n", + drm_err(vop2->drm, "failed to init overlay plane %s: %d\n", win->data->name, ret); return ret; } From patchwork Thu Feb 6 06:44:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962417 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 8FEDDC02196 for ; Thu, 6 Feb 2025 06:59:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=fKsOCewvUOqYFQnacMUXBYXbwcS0IFWz8lkhgoI5zE8=; b=WVEJu/EpK1r+se AcZoxzCWqdmR4yNKD4sjOIsUe6tQ8mYPEruBE0LRErwxFVWQToCGCP282KOzbxACcymYzcaBvYIwA /huU8uzXsU7hMLTH96ybeH1TJU1Y8fKOWTOgUNjmjtTSURVivEudRudNlHaedfDuZSo0BnkRh8Rbe bt5etwStshzjpE3L7tYdNhl58NyMNOOp3+QebzvuP8VZdsD0kM+UkbEqkjZAZYfkH9rmZxWJkFIBq GA+yKZQyzUoVr45sHVm1dsqj/gFHZ7jLS+epZGUtzrgQdQciez50ZqN3byjft/0Cjbg6LY45OpVt8 P5JP+u0kR5ZiOO1n/Zug==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvrT-00000005TsH-49NS; Thu, 06 Feb 2025 06:59:43 +0000 Received: from m16.mail.163.com ([117.135.210.2]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvdp-00000005Q9F-2ZFd; Thu, 06 Feb 2025 06:45:40 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=7AGmm OeGuhCMtIUi8EE6fkCLWKyUGJUyO3b2vg9gaNM=; b=nMSH32G3zGOAacQVvA49/ A22Z2fxDl6HtlcvaZTwex9INvzFAVTRs/7NArldkkC6l2KsrFBjxNowspHkSTkEL qZdZ38xp7lZRhlbUDAazPZtmq2QaFiHBnXgQqRH/EfYMQN03pQ1EfrGhTmM6Cxv9 T5CBbt3ZjBKW/OV5uZ57e0= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-0 (Coremail) with SMTP id _____wD3fyNsWqRnb3bDKQ--.52146S10; Thu, 06 Feb 2025 14:45:12 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan , Michael Riesch Subject: [PATCH v13 08/13] drm/rockchip: vop2: Set plane possible crtcs by possible vp mask Date: Thu, 6 Feb 2025 14:44:36 +0800 Message-ID: <20250206064457.11396-9-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3fyNsWqRnb3bDKQ--.52146S10 X-Coremail-Antispam: 1Uf129KBjvJXoWxtrW8JFWkXF43Zr17tw45GFg_yoWxKrWUpa yxZF13WF4fCr4agry7Ja98ZFyak39xAw4a93ZrKFsxKr15Kry7Wr1UK3Z8Cr1DWFy8Zr1j vw43trWDur17trJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jx0eQUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/xtbB0h-rXmekTP7+uAAAsP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224538_123342_26CDFEC9 X-CRM114-Status: GOOD ( 13.33 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Andy Yan In the upcoming VOP of rk3576, a window cannot attach to all Video Ports, we introduce a possible_vp_mask for every window to indicate which Video Ports this window can attach to. Signed-off-by: Andy Yan Tested-by: Michael Riesch # on RK3568 Tested-by: Detlev Casanova --- (no changes since v1) drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 18 +++++++++++++++++- drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 1 + drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 14 ++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index d3e21fb00225..6040fd2388d3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -2310,6 +2310,10 @@ static int vop2_create_crtcs(struct vop2 *vop2) if (win->base.type == DRM_PLANE_TYPE_PRIMARY) continue; + /* If this win can not attached to this VP */ + if (!(win->data->possible_vp_mask & BIT(vp->id))) + continue; + if (vop2_is_mirror_win(win)) continue; @@ -2341,7 +2345,19 @@ static int vop2_create_crtcs(struct vop2 *vop2) win->type = DRM_PLANE_TYPE_OVERLAY; - possible_crtcs = (1 << nvps) - 1; + possible_crtcs = 0; + nvp = 0; + for (j = 0; j < vop2_data->nr_vps; j++) { + vp = &vop2->vps[j]; + + if (!vp->crtc.port) + continue; + + if (win->data->possible_vp_mask & BIT(vp->id)) + possible_crtcs |= BIT(nvp); + nvp++; + } + ret = vop2_plane_init(vop2, win, possible_crtcs); if (ret) { drm_err(vop2->drm, "failed to init overlay plane %s: %d\n", diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h index 485462749121..33b21248f5cb 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h @@ -167,6 +167,7 @@ struct vop2_win_data { unsigned int phys_id; u32 base; + u32 possible_vp_mask; enum drm_plane_type type; u32 nformats; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 248b9e6729e9..47b9ac2965b0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -347,6 +347,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { .name = "Smart0-win0", .phys_id = ROCKCHIP_VOP2_SMART0, .base = 0x1c00, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), .formats = formats_smart, .nformats = ARRAY_SIZE(formats_smart), .format_modifiers = format_modifiers, @@ -360,6 +361,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { }, { .name = "Smart1-win0", .phys_id = ROCKCHIP_VOP2_SMART1, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), .formats = formats_smart, .nformats = ARRAY_SIZE(formats_smart), .format_modifiers = format_modifiers, @@ -373,6 +375,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { }, { .name = "Esmart1-win0", .phys_id = ROCKCHIP_VOP2_ESMART1, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), .formats = formats_rk356x_esmart, .nformats = ARRAY_SIZE(formats_rk356x_esmart), .format_modifiers = format_modifiers, @@ -386,6 +389,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { }, { .name = "Esmart0-win0", .phys_id = ROCKCHIP_VOP2_ESMART0, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), .formats = formats_rk356x_esmart, .nformats = ARRAY_SIZE(formats_rk356x_esmart), .format_modifiers = format_modifiers, @@ -400,6 +404,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { .name = "Cluster0-win0", .phys_id = ROCKCHIP_VOP2_CLUSTER0, .base = 0x1000, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), .formats = formats_cluster, .nformats = ARRAY_SIZE(formats_cluster), .format_modifiers = format_modifiers_afbc, @@ -415,6 +420,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { .name = "Cluster1-win0", .phys_id = ROCKCHIP_VOP2_CLUSTER1, .base = 0x1200, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), .formats = formats_cluster, .nformats = ARRAY_SIZE(formats_cluster), .format_modifiers = format_modifiers_afbc, @@ -580,6 +586,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .name = "Cluster0-win0", .phys_id = ROCKCHIP_VOP2_CLUSTER0, .base = 0x1000, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3), .formats = formats_cluster, .nformats = ARRAY_SIZE(formats_cluster), .format_modifiers = format_modifiers_afbc, @@ -598,6 +605,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .name = "Cluster1-win0", .phys_id = ROCKCHIP_VOP2_CLUSTER1, .base = 0x1200, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3), .formats = formats_cluster, .nformats = ARRAY_SIZE(formats_cluster), .format_modifiers = format_modifiers_afbc, @@ -616,6 +624,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .name = "Cluster2-win0", .phys_id = ROCKCHIP_VOP2_CLUSTER2, .base = 0x1400, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3), .formats = formats_cluster, .nformats = ARRAY_SIZE(formats_cluster), .format_modifiers = format_modifiers_afbc, @@ -634,6 +643,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .name = "Cluster3-win0", .phys_id = ROCKCHIP_VOP2_CLUSTER3, .base = 0x1600, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3), .formats = formats_cluster, .nformats = ARRAY_SIZE(formats_cluster), .format_modifiers = format_modifiers_afbc, @@ -651,6 +661,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { }, { .name = "Esmart0-win0", .phys_id = ROCKCHIP_VOP2_ESMART0, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3), .formats = formats_esmart, .nformats = ARRAY_SIZE(formats_esmart), .format_modifiers = format_modifiers, @@ -667,6 +678,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { }, { .name = "Esmart1-win0", .phys_id = ROCKCHIP_VOP2_ESMART1, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3), .formats = formats_esmart, .nformats = ARRAY_SIZE(formats_esmart), .format_modifiers = format_modifiers, @@ -684,6 +696,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .name = "Esmart2-win0", .phys_id = ROCKCHIP_VOP2_ESMART2, .base = 0x1c00, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3), .formats = formats_esmart, .nformats = ARRAY_SIZE(formats_esmart), .format_modifiers = format_modifiers, @@ -699,6 +712,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { }, { .name = "Esmart3-win0", .phys_id = ROCKCHIP_VOP2_ESMART3, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3), .formats = formats_esmart, .nformats = ARRAY_SIZE(formats_esmart), .format_modifiers = format_modifiers, From patchwork Thu Feb 6 06:44:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962334 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 785A6C02196 for ; Thu, 6 Feb 2025 06:48:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=f7dFVIgMyhhJMT05l1ft8BA3+xtMgJT0BtrTvaxLIl8=; b=nbhA/97cHPj2Qw MZz9wBpkgzbp9o2MzQf8ilbS4wA9rN5eHIJxVdguZnFVNECpVwmCTwHdV+zAcBgxzMMztA3rp/tAw qT7kmjWdRkbGxQy8lvBv4tM2IEVSci9btTJliHrvA00N8XtNUg0jk6FWlYGVtKqQSnlbsySRmC/mx NE0G9QxEjMN/i9iC4sMCxsgzfIzUMl+I3SD0EY4qfsjr9baeWBXuPR7cAhGBVLc8/qpEnm9Qj1/5k RELPuqiiIIY6WtQ3y0wgKqoY57vuXhwJP7gJAA6FdsNUp+yHWAJLh23n9k9O+5sMsxsRLTkrpeGpM TjxulKgWH9RDEEB1F1sg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvga-00000005RFc-2XW6; Thu, 06 Feb 2025 06:48:28 +0000 Received: from m16.mail.163.com ([220.197.31.4]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvdo-00000005Q8b-1OGE; Thu, 06 Feb 2025 06:45:37 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=1tK63 p6E06ruoBhr4yP+6MI3hNsxARoiIZJBTFpZRnw=; b=mh+Z0NbsIZEIqC8Im+oyF GDifm766HvFE6fJUkAt0btjpq9g8S4OaK/sLwa7Ma5ETOcIeRzqLWmpubFAPAlSV clRLrdKdklgw4DDoy2+CD4Jw9Ja6b2fULmLzR4vw070rwTShSPAOOuWRJb9j3eH3 o6FoNPOydtpbIyYo3S0jaA= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-0 (Coremail) with SMTP id _____wD3fyNsWqRnb3bDKQ--.52146S11; Thu, 06 Feb 2025 14:45:13 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan , Michael Riesch Subject: [PATCH v13 09/13] drm/rockchip: vop2: Add uv swap for cluster window Date: Thu, 6 Feb 2025 14:44:37 +0800 Message-ID: <20250206064457.11396-10-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3fyNsWqRnb3bDKQ--.52146S11 X-Coremail-Antispam: 1Uf129KBjvJXoW7tFW8Ww1kAF4UAw47JFy7ZFb_yoW8XrWfpa 13ArWqgw45Kw4Iq34kJFW5AFWSywnxKay7uws7tw1F9ry3KFyDG3Z0kFWUAr1qyFsFkF47 tF93JrW7Zr1jvrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jx0eQUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqAXrXmekT+DQ4AAAsE X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224536_681183_488F28DB X-CRM114-Status: UNSURE ( 9.16 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Andy Yan The Cluster windows of upcoming VOP on rk3576 also support linear YUV support, we need to set uv swap bit for it. As the VOP2_WIN_UV_SWA register defined on rk3568/rk3588 is 0xffffffff, so this register will not be touched on these two platforms. Signed-off-by: Andy Yan Tested-by: Michael Riesch # on RK3568 Tested-by: Detlev Casanova --- (no changes since v1) drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 6040fd2388d3..3e9581e8adab 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1373,10 +1373,8 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, rb_swap = vop2_win_rb_swap(fb->format->format); vop2_win_write(win, VOP2_WIN_RB_SWAP, rb_swap); - if (!vop2_cluster_window(win)) { - uv_swap = vop2_win_uv_swap(fb->format->format); - vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap); - } + uv_swap = vop2_win_uv_swap(fb->format->format); + vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap); if (fb->format->is_yuv) { vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4)); From patchwork Thu Feb 6 06:44:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962418 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 28751C0219B for ; Thu, 6 Feb 2025 06:59:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=lxgV2BTgdWKDxOKYO3Uqc/DSzIFFnnv5+bCj7FXsr34=; b=Gij4vbIJqLTIF6 N1dH1KXo7dKfhAr1q/dEQk0b3ANQArzB23Req1oLjkI+1RYzfdc0QFtdFNfibA21+5MPkqqykKh1B x81YKHfRLb21eVt7i703A9cPysE2hGWCYG81yllsfMZv1E9qY1ze1DFHBLydeOI1axdbLDMEN9dMi M5BUiZ3+NB3X6t39a645NPe9NFI30XhgemV+xvh6EyU6GlATAGnVG7O6UHxuGwTNwjxpYlTNUE00q Yf9djIlFXaovDzQP8tMObQJ2q5eEJm/yvi4H8iddAVmLMSm9ct6DFdYR82EfkhJhMpkYofbCfvFSR WZxneExYm2I+khAVfHKA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvrT-00000005Trv-2fXD; Thu, 06 Feb 2025 06:59:43 +0000 Received: from m16.mail.163.com ([220.197.31.3]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvdo-00000005Q8c-2fGF; Thu, 06 Feb 2025 06:45:40 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=VjpGl lgUTFnEqj9Ntfpt0RfQHFO2cLVfyWMBrZr3BPQ=; b=ldvU3xhshq4BP2idMpqDX Z6vfPZ4rIUjFN+29YLCLmpMS3Eov0a/0Ezn0rmrEMLbcU7FCO0P4nBt/c23tWjt1 G6EEpceximBzIyg/5p+7dsWBMphgR0EZ6oeakxpmXgglmUzT51NAXMBg1Dg2x1Y4 saE0xPGIQznK4p0urUIj/0= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-0 (Coremail) with SMTP id _____wD3fyNsWqRnb3bDKQ--.52146S12; Thu, 06 Feb 2025 14:45:14 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan Subject: [PATCH v13 10/13] dt-bindings: display: vop2: describe constraint SoC by SoC Date: Thu, 6 Feb 2025 14:44:38 +0800 Message-ID: <20250206064457.11396-11-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3fyNsWqRnb3bDKQ--.52146S12 X-Coremail-Antispam: 1Uf129KBjvJXoWxZF4UWFyDtF15Gry8GFykKrg_yoW5ArW5pa 97C3s8X3ykGr1UWw4ktF1fCw4SqF9xAw47Jrn7t3WxGa1qkF4UG3yagrn8Ar9xWFsFvaya kan0kw15J3y2vr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jbOz3UUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqRHrXmekUdSoNgAAsV X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224536_997670_BA266709 X-CRM114-Status: GOOD ( 10.14 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Andy Yan As more SoCs variants are introduced, each SoC brings its own unique set of constraints, describe this constraints SoC by SoC will make things easier. Signed-off-by: Andy Yan Reviewed-by: Krzysztof Kozlowski --- Changes in v13: - Add maxItems constraint for clocks - Remove constraint for interrupts in allOf block, as the current maxItems is already 1. Changes in v12: - Only change the description method for existing SoC. Changes in v11: - Remove redundant min/maxItems constraint Changes in v10: - Move interrupt-names back to top level - Add constraint of interrupts for all platform - Add constraint for all grf phandles - Reorder some properties Changes in v9: - Drop 'vop-' prefix of interrupt-names. - Add blank line between DT properties - Remove list interrupt-names in top level Changes in v8: - Fix dt_binding_check errors - ordered by soc name - Link to the previous version: https://lore.kernel.org/linux-rockchip/6pn3qjxotdtpzucpul24yro7ppddezwuizneovqvmgdwyv2j7p@ztg4mqyiqmjf/T/#u Changes in v4: - describe constraint SOC by SOC, as interrupts of rk3576 is very different from others - Drop Krzysztof's Reviewed-by, as this version changed a lot. Changes in v3: - ordered by soc name - Add description for newly added interrupt Changes in v2: - Add dt bindings .../display/rockchip/rockchip-vop2.yaml | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml index 2531726af306..32da1625c063 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml @@ -14,6 +14,7 @@ description: maintainers: - Sandy Huang - Heiko Stuebner + - Andy Yan properties: compatible: @@ -120,43 +121,54 @@ allOf: properties: compatible: contains: - const: rockchip,rk3588-vop + enum: + - rockchip,rk3566-vop + - rockchip,rk3568-vop then: properties: clocks: - minItems: 7 + maxItems: 5 + clock-names: - minItems: 7 + maxItems: 5 ports: required: - port@0 - port@1 - port@2 - - port@3 - required: - - rockchip,grf - - rockchip,vo1-grf - - rockchip,vop-grf - - rockchip,pmu - - else: - properties: rockchip,vo1-grf: false rockchip,vop-grf: false rockchip,pmu: false + - if: + properties: + compatible: + contains: + const: rockchip,rk3588-vop + then: + properties: clocks: - maxItems: 5 + minItems: 7 + maxItems: 7 + clock-names: - maxItems: 5 + minItems: 7 + maxItems: 7 ports: required: - port@0 - port@1 - port@2 + - port@3 + + required: + - rockchip,grf + - rockchip,vo1-grf + - rockchip,vop-grf + - rockchip,pmu additionalProperties: false From patchwork Thu Feb 6 06:45:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962420 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id A61A0C02196 for ; Thu, 6 Feb 2025 07:02:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=zLlDQXXbR0P5V08g5DoPPMkBRU5Qa+KPDz1X921VQ9w=; b=gTJYzERLOSXqJ7 qdQjTSlhLf56WpDR7kQhrk+uo2/ovkiapoJT/I4XOexEmFUMrnthKHjPBdkK1fSLBkVc7vIUpnJ5W D8tiWlCNXahcI3vnv1BNBBqs0KZ1oE2nDMqGBNFDAPDRZ6BiUNfk55aMIReirQgQaYT3lF2+vZDXo C2VQCPm3bS3zYs+wMjO2LakLavTtxLmmE1WbD93Jn5BO+IpiPIOICaww3mMflIhT+29HmmqKbDkeh ZGvOLr6iqRAgt0Hi1dtBpzClkBct0dw7+zHUcLHssPzVXhBpIOJUkLWQjO15OVZiaScci5Pqq0NTL HNP4qIOmJU6IFIGtVKGQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvuE-00000005USf-2HR6; Thu, 06 Feb 2025 07:02:34 +0000 Received: from m16.mail.163.com ([117.135.210.5]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfveL-00000005QMn-3Om7; Thu, 06 Feb 2025 06:46:11 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=lzjtk //Wp5baYpqeQ5ioBfQJtIBbDj1Ub/HRRw5Ccr8=; b=IQL8yQF7qePULeZ+HgTz9 r3DWeSDGg3Ey1/FeW4HmZxSVmtKc83qJr5aYeI2gBDuSRZdyOql33+YrMwspd/EO j35RQNRvfS/31sR/QDZ3nCxTixgPJELf1sCZA5YjtPpJ2Iy5VD3R98g0N7sV2dDy rPeAspJniegLE9IsicjvHM= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-3 (Coremail) with SMTP id _____wD3v+2hWqRnj+u8KQ--.33691S2; Thu, 06 Feb 2025 14:45:57 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan Subject: [PATCH v13 11/13] dt-bindings: display: vop2: Add missing rockchip,grf property for rk3566/8 Date: Thu, 6 Feb 2025 14:45:48 +0800 Message-ID: <20250206064552.11466-1-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3v+2hWqRnj+u8KQ--.33691S2 X-Coremail-Antispam: 1Uf129KBjvJXoWrZF45JFWDAryUCry8ZFykGrg_yoW8JrWDpa s3CFWDWay0gr1UXw1DtFn5Cr4vqF97Ca18KFs3JF1xt3ZIgrn8K34a9rn8XF45GFs7ZFWf ua1agryFyrn2vr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jFsjbUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqRHrXmekUdSoNgABsU X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224610_245612_1C8A75A7 X-CRM114-Status: UNSURE ( 8.50 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Andy Yan The clock polarity of RGB signal output is controlled by GRF, this property is already being used in the current device tree, but forgot to describe it as a required property in the binding file. Signed-off-by: Andy Yan Acked-by: Krzysztof Kozlowski --- Changes in v13: - Fix typo - Explain the function of this property. Changes in v12: - Split from patch 10/13 .../devicetree/bindings/display/rockchip/rockchip-vop2.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml index 32da1625c063..cf68eb911118 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml @@ -142,6 +142,9 @@ allOf: rockchip,vop-grf: false rockchip,pmu: false + required: + - rockchip,grf + - if: properties: compatible: @@ -196,6 +199,7 @@ examples: "dclk_vp1", "dclk_vp2"; power-domains = <&power RK3568_PD_VO>; + rockchip,grf = <&grf>; iommus = <&vop_mmu>; vop_out: ports { #address-cells = <1>; From patchwork Thu Feb 6 06:46:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962424 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 5FBB7C02196 for ; Thu, 6 Feb 2025 07:05:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=hGSvTOmPrzEDnnNu5VJsNAxZiJxgQ7sF5Z+mei9Xx98=; b=QV977l39dcluqP sLzXYDBJXtEVRWRzWFs1+1T5uboLGsMdFEpf18Pq0reQieWbUWAWKd/vQVChNwT5y059YpZidD68u pqV8INWNy9dtpYJ7zzicjAF5oNWr/4yFGG17hxVAEJ7ZFVq5EzXzmvIdo+5+LN8I6XtyYRriW3FjP vfeJiYPyH8vm2p181+JQxR2LFkY3w2bT/HbH3pGuKe/CZF/YSu+zkKqeHSn2ps86kXepLGTE4wTaK 9mDE2qu3LH5Mo+v8VKdB7KteJzDHXAmwmG07+gFsLc2Qh12ZcgwfaN1/ca7CRRDsJ7tyDs7ulGJ/9 jh+3JYSbdt4Fhs4h249w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvwv-00000005V1f-14TW; Thu, 06 Feb 2025 07:05:21 +0000 Received: from m16.mail.163.com ([117.135.210.5]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfved-00000005QYS-0MVB; Thu, 06 Feb 2025 06:46:28 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=iV0y9 uGnwXVK7zkkSzMw7t+xjHXK+RMqrkX1IUPW04w=; b=HpT7dBdFhbn152lcQlzvq uU72oiOuLv3ItWFl42lTdqJ3SouYqEsDgMLEVowrBw+dX5VQwINz+mKUsWwv1jEn azbSoeWMModdvmGYgR7At0GmR+cZ9HuH7nEj5HJ0jRX4FRcwu8c38uKSh6h/HlwF S3RbjyuBiJsQzsmt69zuVc= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g0-1 (Coremail) with SMTP id _____wC3162wWqRnLu9OKA--.43572S2; Thu, 06 Feb 2025 14:46:12 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan Subject: [PATCH v13 12/13] dt-bindings: display: vop2: Add rk3576 support Date: Thu, 6 Feb 2025 14:46:03 +0800 Message-ID: <20250206064607.11495-1-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wC3162wWqRnLu9OKA--.43572S2 X-Coremail-Antispam: 1Uf129KBjvJXoWxWr1kWFWUuF4UtFW5trWkZwb_yoW5uFW3pa 93C3Z5XrW8Gr1UWw4ktF1rCwnYq3Z3Ar4akrn2ya13Krsxtr48Ww4agr98Zr9xWFy2vayj 9FsYkw17G3sFvr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07UCQ6XUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqAjrXmekT+DVewAAsX X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224627_541052_5AEA5D26 X-CRM114-Status: GOOD ( 11.26 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Andy Yan Add vop found on rk3576, the main difference between rk3576 and the previous vop is that each VP has its own interrupt line. Signed-off-by: Andy Yan Reviewed-by: Krzysztof Kozlowski --- Changes in v13: - Use maxItems constraint for clocks in allOf block Changes in v12: - Split from patch 10/13 Changes in v11: - Remove redundant min/maxItems constraint Changes in v10: - Move interrupt-names back to top level - Add constraint of interrupts for all platform - Add constraint for all grf phandles - Reorder some properties Changes in v9: - Drop 'vop-' prefix of interrupt-names. - Add blank line between DT properties - Remove list interrupt-names in top level Changes in v8: - Fix dt_binding_check errors - ordered by soc name - Link to the previous version: https://lore.kernel.org/linux-rockchip/6pn3qjxotdtpzucpul24yro7ppddezwuizneovqvmgdwyv2j7p@ztg4mqyiqmjf/T/#u Changes in v4: - describe constraint SOC by SOC, as interrupts of rk3576 is very different from others - Drop Krzysztof's Reviewed-by, as this version changed a lot. Changes in v3: - ordered by soc name - Add description for newly added interrupt Changes in v2: - Add dt bindings .../display/rockchip/rockchip-vop2.yaml | 61 ++++++++++++++++++- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml index cf68eb911118..2f5745255097 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml @@ -21,6 +21,7 @@ properties: enum: - rockchip,rk3566-vop - rockchip,rk3568-vop + - rockchip,rk3576-vop - rockchip,rk3588-vop reg: @@ -38,10 +39,21 @@ properties: - const: gamma-lut interrupts: - maxItems: 1 + minItems: 1 + maxItems: 4 description: - The VOP interrupt is shared by several interrupt sources, such as - frame start (VSYNC), line flag and other status interrupts. + For VOP version under rk3576, the interrupt is shared by several interrupt + sources, such as frame start (VSYNC), line flag and other interrupt status. + For VOP version from rk3576 there is a system interrupt for bus error, and + every video port has it's independent interrupts for vsync and other video + port related error interrupts. + + interrupt-names: + items: + - const: sys + - const: vp0 + - const: vp1 + - const: vp2 # See compatible-specific constraints below. clocks: @@ -132,6 +144,11 @@ allOf: clock-names: maxItems: 5 + interrupts: + maxItems: 1 + + interrupt-names: false + ports: required: - port@0 @@ -145,6 +162,39 @@ allOf: required: - rockchip,grf + - if: + properties: + compatible: + contains: + enum: + - rockchip,rk3576-vop + then: + properties: + clocks: + maxItems: 5 + + clock-names: + maxItems: 5 + + interrupts: + minItems: 4 + + interrupt-names: + minItems: 4 + + ports: + required: + - port@0 + - port@1 + - port@2 + + rockchip,vo1-grf: false + rockchip,vop-grf: false + + required: + - rockchip,grf + - rockchip,pmu + - if: properties: compatible: @@ -160,6 +210,11 @@ allOf: minItems: 7 maxItems: 7 + interrupts: + maxItems: 1 + + interrupt-names: false + ports: required: - port@0 From patchwork Thu Feb 6 06:46:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13962425 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id BECCDC0219B for ; Thu, 6 Feb 2025 07:06:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=/sa17lUHNtFLR9sIDzG/FfapOrBdqM/RVpivPau1uTc=; b=jFeAHwb2VX2UDi 85R21Oftu92GN4Wd4OWgX2JO5b4/mjQ1Ela3RgRWNoSFwO9PFw5WTAcgrRf2NNZQeI71LjUQgihwQ D501kPDAtM6AKVp+u1Qryizlv2DkrVVs7h34AjDFyX+zC1hXLtZBhxl1k81TAGA5GgoEyKocnJqkc RN+OO7QoWkE2yK1DnVur51R/vwTXmsf+qQAFTLqXPsdzDHk7bssf+IeKXjzocXwvAEHzy7E/zwoEt TCaLt1lvNiG1JYsqOiNAB89z1DAChS8+r7u6Ii+yL+/koqhYByMczJTBzp197a315frnJf1+6w5Fq YyQ9u6AX0f90kUBfprQQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfvyG-00000005VWw-17Rc; Thu, 06 Feb 2025 07:06:44 +0000 Received: from m16.mail.163.com ([220.197.31.3]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tfveq-00000005Qj8-3bNQ; Thu, 06 Feb 2025 06:46:43 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=z5IOw biDHey3IVQH+oJPp9oxhQU0NOBRKkA5BTgLGgE=; b=G6WsrD3IGxL9FC4P3Cr4T fVY4zSHWwNbKfSGUMEM0JNG/0peTg/uQafcBCBxIoLQHUJW11XP/u3s+L0HCZdW/ GTr0ag9mLYLnFSERDkEqj5iCLdeHjUy66VxUF8vJTbzN67DezuSsJZMjOy+9cv8W gVJEds2uwEqdsv0R/HDYdE= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-2 (Coremail) with SMTP id _____wD3f2u7WqRnX92XKQ--.17001S2; Thu, 06 Feb 2025 14:46:22 +0800 (CST) From: Andy Yan To: heiko@sntech.de Cc: hjc@rock-chips.com, krzk+dt@kernel.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, derek.foreman@collabora.com, detlev.casanova@collabora.com, daniel@fooishbar.org, robh@kernel.org, sebastian.reichel@collabora.com, Andy Yan , Michael Riesch Subject: [PATCH v13 13/13] drm/rockchip: vop2: Add support for rk3576 Date: Thu, 6 Feb 2025 14:46:16 +0800 Message-ID: <20250206064618.11524-1-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206064457.11396-1-andyshrk@163.com> References: <20250206064457.11396-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3f2u7WqRnX92XKQ--.17001S2 X-Coremail-Antispam: 1Uf129KBjvAXoWDCFWxAFWrKw15KF47CFWxWFg_yoW7ZF1rWo W7CFnIvryxt34Sk395GrnrXryxWF4vkw4kur42yFy2k3y3X3y5Cr18t3ZFqF42y3y3CFWr A34vq3WrZFWrZw1xn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UbIYCTnIWIevJa73UjIFyTuYvjxU4znmDUUUU X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/xtbB0g-rXmekWosEMQAAsP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250205_224641_392571_DB4DE5E8 X-CRM114-Status: GOOD ( 24.01 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Andy Yan VOP2 on rk3576: Three video ports: VP0 Max 4096x2160 VP1 Max 2560x1600 VP2 Max 1920x1080 2 4K Cluster windows with AFBC/RFBC, line RGB and YUV 4 Esmart windows with line RGB/YUV support: Esmart0/1: 4K Esmart2/3: 2k, or worked together as a single 4K plane at shared line buffer mode. Compared to the previous VOP, another difference is that each VP has its own independent vsync interrupt number. Signed-off-by: Andy Yan Tested-by: Michael Riesch # on RK3568 Tested-by: Detlev Casanova --- (no changes since v9) Changes in v9: - Drop 'vop-' prefix of interrupt-names. Changes in v6: - More specific explanation about the AXI_BUS_ID register bit of cluster window. Changes in v5: - Add axi id configuration - Remove the non-existent CBCR scale register. Changes in v3: - Share the alpha setup function with rk3568 - recoder the code block by soc Changes in v2: - Add platform specific callback drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 144 ++- drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 87 ++ drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 951 +++++++++++++++++-- 3 files changed, 1057 insertions(+), 125 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 3e9581e8adab..f9c3591ac876 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1276,6 +1276,9 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, vop2_win_write(win, VOP2_WIN_AXI_UV_R_ID, win->data->axi_uv_r_id); } + if (vop2->version >= VOP_VERSION_RK3576) + vop2_win_write(win, VOP2_WIN_VP_SEL, vp->id); + if (vop2_cluster_window(win)) vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, half_block_en); @@ -1340,6 +1343,11 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, else vop2_win_write(win, VOP2_WIN_AFBC_BLOCK_SPLIT_EN, 0); + if (vop2->version >= VOP_VERSION_RK3576) { + vop2_win_write(win, VOP2_WIN_AFBC_PLD_OFFSET_EN, 1); + vop2_win_write(win, VOP2_WIN_AFBC_PLD_OFFSET, yrgb_mst); + } + transform_offset = vop2_afbc_transform_offset(pstate, half_block_en); vop2_win_write(win, VOP2_WIN_AFBC_HDR_PTR, yrgb_mst); vop2_win_write(win, VOP2_WIN_AFBC_PIC_SIZE, act_info); @@ -2117,6 +2125,56 @@ static const struct drm_crtc_funcs vop2_crtc_funcs = { .late_register = vop2_crtc_late_register, }; +static irqreturn_t rk3576_vp_isr(int irq, void *data) +{ + struct vop2_video_port *vp = data; + struct vop2 *vop2 = vp->vop2; + struct drm_crtc *crtc = &vp->crtc; + uint32_t irqs; + int ret = IRQ_NONE; + + /* + * The irq is shared with the iommu. If the runtime-pm state of the + * vop2-device is disabled the irq has to be targeted at the iommu. + */ + if (!pm_runtime_get_if_in_use(vop2->dev)) + return IRQ_NONE; + + irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id)); + vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs); + + if (irqs & VP_INT_DSP_HOLD_VALID) { + complete(&vp->dsp_hold_completion); + ret = IRQ_HANDLED; + } + + if (irqs & VP_INT_FS_FIELD) { + drm_crtc_handle_vblank(crtc); + spin_lock(&crtc->dev->event_lock); + if (vp->event) { + u32 val = vop2_readl(vop2, RK3568_REG_CFG_DONE); + + if (!(val & BIT(vp->id))) { + drm_crtc_send_vblank_event(crtc, vp->event); + vp->event = NULL; + drm_crtc_vblank_put(crtc); + } + } + spin_unlock(&crtc->dev->event_lock); + + ret = IRQ_HANDLED; + } + + if (irqs & VP_INT_POST_BUF_EMPTY) { + drm_err_ratelimited(vop2->drm, "POST_BUF_EMPTY irq err at vp%d\n", vp->id); + ret = IRQ_HANDLED; + } + + pm_runtime_put(vop2->dev); + + return ret; +} + static irqreturn_t vop2_isr(int irq, void *data) { struct vop2 *vop2 = data; @@ -2132,41 +2190,43 @@ static irqreturn_t vop2_isr(int irq, void *data) if (!pm_runtime_get_if_in_use(vop2->dev)) return IRQ_NONE; - for (i = 0; i < vop2_data->nr_vps; i++) { - struct vop2_video_port *vp = &vop2->vps[i]; - struct drm_crtc *crtc = &vp->crtc; - u32 irqs; + if (vop2->version < VOP_VERSION_RK3576) { + for (i = 0; i < vop2_data->nr_vps; i++) { + struct vop2_video_port *vp = &vop2->vps[i]; + struct drm_crtc *crtc = &vp->crtc; + u32 irqs; - irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id)); - vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs); + irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id)); + vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs); - if (irqs & VP_INT_DSP_HOLD_VALID) { - complete(&vp->dsp_hold_completion); - ret = IRQ_HANDLED; - } - - if (irqs & VP_INT_FS_FIELD) { - drm_crtc_handle_vblank(crtc); - spin_lock(&crtc->dev->event_lock); - if (vp->event) { - u32 val = vop2_readl(vop2, RK3568_REG_CFG_DONE); + if (irqs & VP_INT_DSP_HOLD_VALID) { + complete(&vp->dsp_hold_completion); + ret = IRQ_HANDLED; + } - if (!(val & BIT(vp->id))) { - drm_crtc_send_vblank_event(crtc, vp->event); - vp->event = NULL; - drm_crtc_vblank_put(crtc); + if (irqs & VP_INT_FS_FIELD) { + drm_crtc_handle_vblank(crtc); + spin_lock(&crtc->dev->event_lock); + if (vp->event) { + u32 val = vop2_readl(vop2, RK3568_REG_CFG_DONE); + + if (!(val & BIT(vp->id))) { + drm_crtc_send_vblank_event(crtc, vp->event); + vp->event = NULL; + drm_crtc_vblank_put(crtc); + } } - } - spin_unlock(&crtc->dev->event_lock); + spin_unlock(&crtc->dev->event_lock); - ret = IRQ_HANDLED; - } + ret = IRQ_HANDLED; + } - if (irqs & VP_INT_POST_BUF_EMPTY) { - drm_err_ratelimited(vop2->drm, - "POST_BUF_EMPTY irq err at vp%d\n", - vp->id); - ret = IRQ_HANDLED; + if (irqs & VP_INT_POST_BUF_EMPTY) { + drm_err_ratelimited(vop2->drm, + "POST_BUF_EMPTY irq err at vp%d\n", + vp->id); + ret = IRQ_HANDLED; + } } } @@ -2634,6 +2694,32 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) if (ret) return ret; + if (vop2->version >= VOP_VERSION_RK3576) { + struct drm_crtc *crtc; + + drm_for_each_crtc(crtc, drm) { + struct vop2_video_port *vp = to_vop2_video_port(crtc); + int vp_irq; + const char *irq_name = devm_kasprintf(dev, GFP_KERNEL, "vp%d", vp->id); + + if (!irq_name) + return -ENOMEM; + + vp_irq = platform_get_irq_byname(pdev, irq_name); + if (vp_irq < 0) { + DRM_DEV_ERROR(dev, "cannot find irq for vop2 vp%d\n", vp->id); + return vp_irq; + } + + ret = devm_request_irq(dev, vp_irq, rk3576_vp_isr, IRQF_SHARED, irq_name, + vp); + if (ret) { + DRM_DEV_ERROR(dev, "request irq for vop2 vp%d failed\n", vp->id); + return ret; + } + } + } + ret = vop2_find_rgb_encoder(vop2); if (ret >= 0) { vop2->rgb = rockchip_rgb_init(dev, &vop2->vps[ret].crtc, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h index 33b21248f5cb..4de6da839538 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h @@ -44,6 +44,13 @@ enum win_dly_mode { VOP2_DLY_MODE_MAX, }; +enum vop2_dly_module { + VOP2_DLY_WIN, /** Win delay cycle for this VP */ + VOP2_DLY_LAYER_MIX, /** Layer Mix delay cycle for this VP */ + VOP2_DLY_HDR_MIX, /** HDR delay cycle for this VP */ + VOP2_DLY_MAX, +}; + enum vop2_scale_up_mode { VOP2_SCALE_UP_NRST_NBOR, VOP2_SCALE_UP_BIL, @@ -140,16 +147,22 @@ enum vop2_win_regs { VOP2_WIN_AFBC_UV_SWAP, VOP2_WIN_AFBC_AUTO_GATING_EN, VOP2_WIN_AFBC_BLOCK_SPLIT_EN, + VOP2_WIN_AFBC_PLD_OFFSET_EN, VOP2_WIN_AFBC_PIC_VIR_WIDTH, VOP2_WIN_AFBC_TILE_NUM, VOP2_WIN_AFBC_PIC_OFFSET, VOP2_WIN_AFBC_PIC_SIZE, VOP2_WIN_AFBC_DSP_OFFSET, + VOP2_WIN_AFBC_PLD_OFFSET, VOP2_WIN_AFBC_TRANSFORM_OFFS, VOP2_WIN_AFBC_HDR_PTR, VOP2_WIN_AFBC_HALF_BLOCK_EN, VOP2_WIN_AFBC_ROTATE_270, VOP2_WIN_AFBC_ROTATE_90, + + VOP2_WIN_VP_SEL, + VOP2_WIN_DLY_NUM, + VOP2_WIN_MAX_REG, }; @@ -215,6 +228,10 @@ struct vop2_video_port_data { struct vop_rect max_output; const u8 pre_scan_max_dly[4]; unsigned int offset; + /** + * @pixel_rate: pixel per cycle + */ + u8 pixel_rate; }; struct vop2_video_port { @@ -372,10 +389,13 @@ enum dst_factor_mode { #define RK3568_REG_CFG_DONE 0x000 #define RK3568_VERSION_INFO 0x004 #define RK3568_SYS_AUTO_GATING_CTRL 0x008 +#define RK3576_SYS_MMU_CTRL_IMD 0x020 #define RK3568_SYS_AXI_LUT_CTRL 0x024 #define RK3568_DSP_IF_EN 0x028 +#define RK3576_SYS_PORT_CTRL_IMD 0x028 #define RK3568_DSP_IF_CTRL 0x02c #define RK3568_DSP_IF_POL 0x030 +#define RK3576_SYS_CLUSTER_PD_CTRL_IMD 0x030 #define RK3588_SYS_PD_CTRL 0x034 #define RK3568_WB_CTRL 0x40 #define RK3568_WB_XSCAL_FACTOR 0x44 @@ -395,6 +415,55 @@ enum dst_factor_mode { #define RK3568_VP_INT_CLR(vp) (0xA4 + (vp) * 0x10) #define RK3568_VP_INT_STATUS(vp) (0xA8 + (vp) * 0x10) #define RK3568_VP_INT_RAW_STATUS(vp) (0xAC + (vp) * 0x10) +#define RK3576_WB_CTRL 0x100 +#define RK3576_WB_XSCAL_FACTOR 0x104 +#define RK3576_WB_YRGB_MST 0x108 +#define RK3576_WB_CBR_MST 0x10C +#define RK3576_WB_VIR_STRIDE 0x110 +#define RK3576_WB_TIMEOUT_CTRL 0x114 +#define RK3576_MIPI0_IF_CTRL 0x180 +#define RK3576_HDMI0_IF_CTRL 0x184 +#define RK3576_EDP0_IF_CTRL 0x188 +#define RK3576_DP0_IF_CTRL 0x18C +#define RK3576_RGB_IF_CTRL 0x194 +#define RK3576_DP1_IF_CTRL 0x1A4 +#define RK3576_DP2_IF_CTRL 0x1B0 + +/* Extra OVL register definition */ +#define RK3576_SYS_EXTRA_ALPHA_CTRL 0x500 +#define RK3576_CLUSTER0_MIX_SRC_COLOR_CTRL 0x530 +#define RK3576_CLUSTER0_MIX_DST_COLOR_CTRL 0x534 +#define RK3576_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x538 +#define RK3576_CLUSTER0_MIX_DST_ALPHA_CTRL 0x53c +#define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL 0x540 +#define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL 0x544 +#define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL 0x548 +#define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL 0x54c + +/* OVL registers for Video Port definition */ +#define RK3576_OVL_CTRL(vp) (0x600 + (vp) * 0x100) +#define RK3576_OVL_LAYER_SEL(vp) (0x604 + (vp) * 0x100) +#define RK3576_OVL_MIX0_SRC_COLOR_CTRL(vp) (0x620 + (vp) * 0x100) +#define RK3576_OVL_MIX0_DST_COLOR_CTRL(vp) (0x624 + (vp) * 0x100) +#define RK3576_OVL_MIX0_SRC_ALPHA_CTRL(vp) (0x628 + (vp) * 0x100) +#define RK3576_OVL_MIX0_DST_ALPHA_CTRL(vp) (0x62C + (vp) * 0x100) +#define RK3576_OVL_MIX1_SRC_COLOR_CTRL(vp) (0x630 + (vp) * 0x100) +#define RK3576_OVL_MIX1_DST_COLOR_CTRL(vp) (0x634 + (vp) * 0x100) +#define RK3576_OVL_MIX1_SRC_ALPHA_CTRL(vp) (0x638 + (vp) * 0x100) +#define RK3576_OVL_MIX1_DST_ALPHA_CTRL(vp) (0x63C + (vp) * 0x100) +#define RK3576_OVL_MIX2_SRC_COLOR_CTRL(vp) (0x640 + (vp) * 0x100) +#define RK3576_OVL_MIX2_DST_COLOR_CTRL(vp) (0x644 + (vp) * 0x100) +#define RK3576_OVL_MIX2_SRC_ALPHA_CTRL(vp) (0x648 + (vp) * 0x100) +#define RK3576_OVL_MIX2_DST_ALPHA_CTRL(vp) (0x64C + (vp) * 0x100) +#define RK3576_EXTRA_OVL_SRC_COLOR_CTRL(vp) (0x650 + (vp) * 0x100) +#define RK3576_EXTRA_OVL_DST_COLOR_CTRL(vp) (0x654 + (vp) * 0x100) +#define RK3576_EXTRA_OVL_SRC_ALPHA_CTRL(vp) (0x658 + (vp) * 0x100) +#define RK3576_EXTRA_OVL_DST_ALPHA_CTRL(vp) (0x65C + (vp) * 0x100) +#define RK3576_OVL_HDR_SRC_COLOR_CTRL(vp) (0x660 + (vp) * 0x100) +#define RK3576_OVL_HDR_DST_COLOR_CTRL(vp) (0x664 + (vp) * 0x100) +#define RK3576_OVL_HDR_SRC_ALPHA_CTRL(vp) (0x668 + (vp) * 0x100) +#define RK3576_OVL_HDR_DST_ALPHA_CTRL(vp) (0x66C + (vp) * 0x100) +#define RK3576_OVL_BG_MIX_CTRL(vp) (0x670 + (vp) * 0x100) /* Video Port registers definition */ #define RK3568_VP0_CTRL_BASE 0x0C00 @@ -477,7 +546,11 @@ enum dst_factor_mode { #define RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET 0x68 #define RK3568_CLUSTER_WIN_AFBCD_CTRL 0x6C +#define RK3576_CLUSTER_WIN_AFBCD_PLD_PTR_OFFSET 0x78 + #define RK3568_CLUSTER_CTRL 0x100 +#define RK3576_CLUSTER_PORT_SEL_IMD 0x1F4 +#define RK3576_CLUSTER_DLY_NUM 0x1F8 /* (E)smart register definition, offset relative to window base */ #define RK3568_SMART_CTRL0 0x00 @@ -528,6 +601,9 @@ enum dst_factor_mode { #define RK3568_SMART_REGION3_SCL_FACTOR_CBR 0xC8 #define RK3568_SMART_REGION3_SCL_OFFSET 0xCC #define RK3568_SMART_COLOR_KEY_CTRL 0xD0 +#define RK3576_SMART_ALPHA_MAP 0xD8 +#define RK3576_SMART_PORT_SEL_IMD 0xF4 +#define RK3576_SMART_DLY_NUM 0xF8 /* HDR register definition */ #define RK3568_HDR_LUT_CTRL 0x2000 @@ -676,6 +752,17 @@ enum dst_factor_mode { #define POLFLAG_DCLK_INV BIT(3) +#define RK3576_OVL_CTRL__YUV_MODE BIT(0) +#define RK3576_OVL_BG_MIX_CTRL__BG_DLY GENMASK(31, 24) + +#define RK3576_DSP_IF_CFG_DONE_IMD BIT(31) +#define RK3576_DSP_IF_DCLK_SEL_OUT BIT(21) +#define RK3576_DSP_IF_PCLK_DIV BIT(20) +#define RK3576_DSP_IF_PIN_POL GENMASK(5, 4) +#define RK3576_DSP_IF_MUX GENMASK(3, 2) +#define RK3576_DSP_IF_CLK_OUT_EN BIT(1) +#define RK3576_DSP_IF_EN BIT(0) + enum vop2_layer_phy_id { ROCKCHIP_VOP2_CLUSTER0 = 0, ROCKCHIP_VOP2_CLUSTER1, diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 47b9ac2965b0..64fc26931b14 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -70,6 +70,37 @@ static const uint32_t formats_cluster[] = { DRM_FORMAT_Y210, /* yuv422_10bit non-Linear mode only */ }; +/* + * The cluster windows on rk3576 support: + * RGB: linear mode and afbc + * YUV: linear mode and rfbc + * rfbc is a rockchip defined non-linear mode, produced by + * Video decoder + */ +static const uint32_t formats_rk3576_cluster[] = { + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_BGR888, + DRM_FORMAT_RGB565, + DRM_FORMAT_BGR565, + DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */ + DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */ + DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */ + DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */ + DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */ + DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */ + DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */ + DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */ + DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */ +}; + static const uint32_t formats_esmart[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, @@ -116,6 +147,41 @@ static const uint32_t formats_rk356x_esmart[] = { DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */ }; +/* + * Add XRGB2101010/ARGB2101010ARGB1555/XRGB1555 + */ +static const uint32_t formats_rk3576_esmart[] = { + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_BGR888, + DRM_FORMAT_RGB565, + DRM_FORMAT_BGR565, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ABGR1555, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_XBGR1555, + DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */ + DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */ + DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */ + DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */ + DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */ + DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */ + DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */ + DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */ + DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */ + DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */ + DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */ + DRM_FORMAT_YUYV, /* yuv422_8bit[YUYV] linear mode */ + DRM_FORMAT_UYVY, /* yuv422_8bit[UYVY] linear mode */ +}; + static const uint32_t formats_smart[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, @@ -169,6 +235,48 @@ static const uint64_t format_modifiers_afbc[] = { DRM_FORMAT_MOD_INVALID, }; +/* used from rk3576, afbc 32*8 half mode */ +static const uint64_t format_modifiers_rk3576_afbc[] = { + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_SPARSE | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_YTR | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_CBR | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_CBR | + AFBC_FORMAT_MOD_SPARSE | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_YTR | + AFBC_FORMAT_MOD_CBR | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_YTR | + AFBC_FORMAT_MOD_CBR | + AFBC_FORMAT_MOD_SPARSE | + AFBC_FORMAT_MOD_SPLIT), + + /* SPLIT mandates SPARSE, RGB modes mandates YTR */ + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_YTR | + AFBC_FORMAT_MOD_SPARSE | + AFBC_FORMAT_MOD_SPLIT), + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID, +}; + static const struct reg_field rk3568_vop_cluster_regs[VOP2_WIN_MAX_REG] = { [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0), [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5), @@ -301,6 +409,147 @@ static const struct reg_field rk3568_vop_smart_regs[VOP2_WIN_MAX_REG] = { [VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff }, }; +static const struct reg_field rk3576_vop_cluster_regs[VOP2_WIN_MAX_REG] = { + [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0), + [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5), + [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14), + [VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 17, 17), + [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18), + [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31), + [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31), + [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31), + [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31), + [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31), + [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19), + [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15), + [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31), + [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8), + [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9), + [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11), + [VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 0, 4), + [VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 5, 9), + /* Read only bit on rk3576, writing on this bit have no effect.*/ + [VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3568_CLUSTER_CTRL, 13, 13), + + [VOP2_WIN_VP_SEL] = REG_FIELD(RK3576_CLUSTER_PORT_SEL_IMD, 0, 1), + [VOP2_WIN_DLY_NUM] = REG_FIELD(RK3576_CLUSTER_DLY_NUM, 0, 7), + + /* Scale */ + [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15), + [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31), + [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3), + [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15), + [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 22, 23), + [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28), + [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29), + + /* cluster regs */ + [VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1), + [VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0), + [VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7), + + /* afbc regs */ + [VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6), + [VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9), + [VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10), + [VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4), + [VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7), + [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8), + [VOP2_WIN_AFBC_PLD_OFFSET_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 16, 16), + [VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31), + [VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31), + [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15), + [VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31), + [VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31), + [VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31), + [VOP2_WIN_AFBC_PLD_OFFSET] = REG_FIELD(RK3576_CLUSTER_WIN_AFBCD_PLD_PTR_OFFSET, 0, 31), + [VOP2_WIN_AFBC_TRANSFORM_OFFS] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFS, 0, 31), + [VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0), + [VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1), + [VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2), + [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3), + [VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff }, + [VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff }, + [VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff }, + [VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff }, + [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff }, + [VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff }, +}; + +static const struct reg_field rk3576_vop_smart_regs[VOP2_WIN_MAX_REG] = { + [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0), + [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5), + [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12), + [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14), + [VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16), + [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31), + [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31), + [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28), + [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31), + [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31), + [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17), + [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15), + [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31), + [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0), + [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1), + [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3), + [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31), + [VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29), + [VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31), + [VOP2_WIN_VP_SEL] = REG_FIELD(RK3576_SMART_PORT_SEL_IMD, 0, 1), + [VOP2_WIN_DLY_NUM] = REG_FIELD(RK3576_SMART_DLY_NUM, 0, 7), + [VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 4, 8), + [VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 12, 16), + [VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3588_SMART_AXI_CTRL, 1, 1), + + /* Scale */ + [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15), + [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31), + [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1), + [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3), + [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5), + [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7), + [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17), + [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8), + [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9), + [VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10), + [VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11), + [VOP2_WIN_XMIRROR] = { .reg = 0xffffffff }, + + /* CBCR share the same scale factor as YRGB */ + [VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff }, + [VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff }, + [VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff}, + [VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff}, + [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff}, + + [VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff }, + [VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_TRANSFORM_OFFS] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff }, + [VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff }, +}; + static const struct vop2_video_port_data rk3568_vop_video_ports[] = { { .id = 0, @@ -355,98 +604,385 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { .layer_sel_id = { 3, 3, 3, 0xf }, .supported_rotations = DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_PRIMARY, - .max_upscale_factor = 8, - .max_downscale_factor = 8, - .dly = { 20, 47, 41 }, + .max_upscale_factor = 8, + .max_downscale_factor = 8, + .dly = { 20, 47, 41 }, + }, { + .name = "Smart1-win0", + .phys_id = ROCKCHIP_VOP2_SMART1, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), + .formats = formats_smart, + .nformats = ARRAY_SIZE(formats_smart), + .format_modifiers = format_modifiers, + .base = 0x1e00, + .layer_sel_id = { 7, 7, 7, 0xf }, + .supported_rotations = DRM_MODE_REFLECT_Y, + .type = DRM_PLANE_TYPE_PRIMARY, + .max_upscale_factor = 8, + .max_downscale_factor = 8, + .dly = { 20, 47, 41 }, + }, { + .name = "Esmart1-win0", + .phys_id = ROCKCHIP_VOP2_ESMART1, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), + .formats = formats_rk356x_esmart, + .nformats = ARRAY_SIZE(formats_rk356x_esmart), + .format_modifiers = format_modifiers, + .base = 0x1a00, + .layer_sel_id = { 6, 6, 6, 0xf }, + .supported_rotations = DRM_MODE_REFLECT_Y, + .type = DRM_PLANE_TYPE_PRIMARY, + .max_upscale_factor = 8, + .max_downscale_factor = 8, + .dly = { 20, 47, 41 }, + }, { + .name = "Esmart0-win0", + .phys_id = ROCKCHIP_VOP2_ESMART0, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), + .formats = formats_rk356x_esmart, + .nformats = ARRAY_SIZE(formats_rk356x_esmart), + .format_modifiers = format_modifiers, + .base = 0x1800, + .layer_sel_id = { 2, 2, 2, 0xf }, + .supported_rotations = DRM_MODE_REFLECT_Y, + .type = DRM_PLANE_TYPE_PRIMARY, + .max_upscale_factor = 8, + .max_downscale_factor = 8, + .dly = { 20, 47, 41 }, + }, { + .name = "Cluster0-win0", + .phys_id = ROCKCHIP_VOP2_CLUSTER0, + .base = 0x1000, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), + .formats = formats_cluster, + .nformats = ARRAY_SIZE(formats_cluster), + .format_modifiers = format_modifiers_afbc, + .layer_sel_id = { 0, 0, 0, 0xf }, + .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | + DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, + .max_upscale_factor = 4, + .max_downscale_factor = 4, + .dly = { 0, 27, 21 }, + .type = DRM_PLANE_TYPE_OVERLAY, + .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER, + }, { + .name = "Cluster1-win0", + .phys_id = ROCKCHIP_VOP2_CLUSTER1, + .base = 0x1200, + .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), + .formats = formats_cluster, + .nformats = ARRAY_SIZE(formats_cluster), + .format_modifiers = format_modifiers_afbc, + .layer_sel_id = { 1, 1, 1, 0xf }, + .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | + DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, + .type = DRM_PLANE_TYPE_OVERLAY, + .max_upscale_factor = 4, + .max_downscale_factor = 4, + .dly = { 0, 27, 21 }, + .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER, + }, +}; + +static const struct vop2_regs_dump rk3568_regs_dump[] = { + { + .name = "SYS", + .base = RK3568_REG_CFG_DONE, + .size = 0x100, + .en_reg = 0, + .en_val = 0, + .en_mask = 0 + }, { + .name = "OVL", + .base = RK3568_OVL_CTRL, + .size = 0x100, + .en_reg = 0, + .en_val = 0, + .en_mask = 0, + }, { + .name = "VP0", + .base = RK3568_VP0_CTRL_BASE, + .size = 0x100, + .en_reg = RK3568_VP_DSP_CTRL, + .en_val = 0, + .en_mask = RK3568_VP_DSP_CTRL__STANDBY, + }, { + .name = "VP1", + .base = RK3568_VP1_CTRL_BASE, + .size = 0x100, + .en_reg = RK3568_VP_DSP_CTRL, + .en_val = 0, + .en_mask = RK3568_VP_DSP_CTRL__STANDBY, + }, { + .name = "VP2", + .base = RK3568_VP2_CTRL_BASE, + .size = 0x100, + .en_reg = RK3568_VP_DSP_CTRL, + .en_val = 0, + .en_mask = RK3568_VP_DSP_CTRL__STANDBY, + + }, { + .name = "Cluster0", + .base = RK3568_CLUSTER0_CTRL_BASE, + .size = 0x110, + .en_reg = RK3568_CLUSTER_WIN_CTRL0, + .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, + .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, + }, { + .name = "Cluster1", + .base = RK3568_CLUSTER1_CTRL_BASE, + .size = 0x110, + .en_reg = RK3568_CLUSTER_WIN_CTRL0, + .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, + .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, + }, { + .name = "Esmart0", + .base = RK3568_ESMART0_CTRL_BASE, + .size = 0xf0, + .en_reg = RK3568_SMART_REGION0_CTRL, + .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, + .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, + }, { + .name = "Esmart1", + .base = RK3568_ESMART1_CTRL_BASE, + .size = 0xf0, + .en_reg = RK3568_SMART_REGION0_CTRL, + .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, + .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, + }, { + .name = "Smart0", + .base = RK3568_SMART0_CTRL_BASE, + .size = 0xf0, + .en_reg = RK3568_SMART_REGION0_CTRL, + .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, + .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, + }, { + .name = "Smart1", + .base = RK3568_SMART1_CTRL_BASE, + .size = 0xf0, + .en_reg = RK3568_SMART_REGION0_CTRL, + .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, + .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, + }, +}; + +static const struct vop2_video_port_data rk3576_vop_video_ports[] = { + { + .id = 0, + .feature = VOP2_VP_FEATURE_OUTPUT_10BIT, + .gamma_lut_len = 1024, + .cubic_lut_len = 9 * 9 * 9, /* 9x9x9 */ + .max_output = { 4096, 2304 }, + /* win layer_mix hdr */ + .pre_scan_max_dly = { 10, 8, 2, 0 }, + .offset = 0xc00, + .pixel_rate = 2, + }, { + .id = 1, + .feature = VOP2_VP_FEATURE_OUTPUT_10BIT, + .gamma_lut_len = 1024, + .cubic_lut_len = 729, /* 9x9x9 */ + .max_output = { 2560, 1600 }, + /* win layer_mix hdr */ + .pre_scan_max_dly = { 10, 6, 0, 0 }, + .offset = 0xd00, + .pixel_rate = 1, + }, { + .id = 2, + .gamma_lut_len = 1024, + .max_output = { 1920, 1080 }, + /* win layer_mix hdr */ + .pre_scan_max_dly = { 10, 6, 0, 0 }, + .offset = 0xe00, + .pixel_rate = 1, + }, +}; + +/* + * rk3576 vop with 2 cluster, 4 esmart win. + * Every cluster can work as 4K win or split into two 2K win. + * All win in cluster support AFBCD. + * + * Every esmart win support 4 Multi-region. + * + * VP0 can use Cluster0/1 and Esmart0/2 + * VP1 can use Cluster0/1 and Esmart1/3 + * VP2 can use Esmart0/1/2/3 + * + * Scale filter mode: + * + * * Cluster: + * * Support prescale down: + * * H/V: gt2/avg2 or gt4/avg4 + * * After prescale down: + * * nearest-neighbor/bilinear/multi-phase filter for scale up + * * nearest-neighbor/bilinear/multi-phase filter for scale down + * + * * Esmart: + * * Support prescale down: + * * H: gt2/avg2 or gt4/avg4 + * * V: gt2 or gt4 + * * After prescale down: + * * nearest-neighbor/bilinear/bicubic for scale up + * * nearest-neighbor/bilinear for scale down + * + * AXI config:: + * + * * Cluster0 win0: 0xa, 0xb [AXI0] + * * Cluster0 win1: 0xc, 0xd [AXI0] + * * Cluster1 win0: 0x6, 0x7 [AXI0] + * * Cluster1 win1: 0x8, 0x9 [AXI0] + * * Esmart0: 0x10, 0x11 [AXI0] + * * Esmart1: 0x12, 0x13 [AXI0] + * * Esmart2: 0xa, 0xb [AXI1] + * * Esmart3: 0xc, 0xd [AXI1] + * * Lut dma rid: 0x1, 0x2, 0x3 [AXI0] + * * DCI dma rid: 0x4 [AXI0] + * * Metadata rid: 0x5 [AXI0] + * + * * Limit: + * * (1) Cluster0/1 are fixed on AXI0 by IC design + * * (2) 0x0 and 0xf can't be used; + * * (3) 5 Bits ID for eache axi bus + * * (3) cluster and lut/dci/metadata rid must smaller than 0xf, + * * if Cluster rid is bigger than 0xf, VOP will dead at the + * * system bandwidth very terrible scene. + */ +static const struct vop2_win_data rk3576_vop_win_data[] = { + { + .name = "Cluster0-win0", + .phys_id = ROCKCHIP_VOP2_CLUSTER0, + .base = 0x1000, + .possible_vp_mask = BIT(0) | BIT(1), + .formats = formats_rk3576_cluster, + .nformats = ARRAY_SIZE(formats_rk3576_cluster), + .format_modifiers = format_modifiers_rk3576_afbc, + .layer_sel_id = { 0, 0, 0xf, 0xf }, + .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, + .type = DRM_PLANE_TYPE_PRIMARY, + .axi_bus_id = 0, + .axi_yrgb_r_id = 0xa, + .axi_uv_r_id = 0xb, + .max_upscale_factor = 4, + .max_downscale_factor = 4, + .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER, }, { - .name = "Smart1-win0", - .phys_id = ROCKCHIP_VOP2_SMART1, - .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), - .formats = formats_smart, - .nformats = ARRAY_SIZE(formats_smart), + .name = "Cluster1-win0", + .phys_id = ROCKCHIP_VOP2_CLUSTER1, + .base = 0x1200, + .possible_vp_mask = BIT(0) | BIT(1), + .formats = formats_rk3576_cluster, + .nformats = ARRAY_SIZE(formats_rk3576_cluster), + .format_modifiers = format_modifiers_rk3576_afbc, + .layer_sel_id = { 1, 1, 0xf, 0xf }, + .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, + .type = DRM_PLANE_TYPE_PRIMARY, + .axi_bus_id = 0, + .axi_yrgb_r_id = 6, + .axi_uv_r_id = 7, + .max_upscale_factor = 4, + .max_downscale_factor = 4, + .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER, + }, { + .name = "Esmart0-win0", + .phys_id = ROCKCHIP_VOP2_ESMART0, + .base = 0x1800, + .possible_vp_mask = BIT(0) | BIT(2), + .formats = formats_rk3576_esmart, + .nformats = ARRAY_SIZE(formats_rk3576_esmart), .format_modifiers = format_modifiers, - .base = 0x1e00, - .layer_sel_id = { 7, 7, 7, 0xf }, + .layer_sel_id = { 2, 0xf, 0, 0xf }, .supported_rotations = DRM_MODE_REFLECT_Y, - .type = DRM_PLANE_TYPE_PRIMARY, + .type = DRM_PLANE_TYPE_OVERLAY, + .axi_bus_id = 0, + .axi_yrgb_r_id = 0x10, + .axi_uv_r_id = 0x11, .max_upscale_factor = 8, .max_downscale_factor = 8, - .dly = { 20, 47, 41 }, }, { .name = "Esmart1-win0", .phys_id = ROCKCHIP_VOP2_ESMART1, - .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), - .formats = formats_rk356x_esmart, - .nformats = ARRAY_SIZE(formats_rk356x_esmart), - .format_modifiers = format_modifiers, .base = 0x1a00, - .layer_sel_id = { 6, 6, 6, 0xf }, + .possible_vp_mask = BIT(1) | BIT(2), + .formats = formats_rk3576_esmart, + .nformats = ARRAY_SIZE(formats_rk3576_esmart), + .format_modifiers = format_modifiers, + .layer_sel_id = { 0xf, 2, 1, 0xf }, .supported_rotations = DRM_MODE_REFLECT_Y, - .type = DRM_PLANE_TYPE_PRIMARY, + .type = DRM_PLANE_TYPE_OVERLAY, + .axi_bus_id = 0, + .axi_yrgb_r_id = 0x12, + .axi_uv_r_id = 0x13, .max_upscale_factor = 8, .max_downscale_factor = 8, - .dly = { 20, 47, 41 }, }, { - .name = "Esmart0-win0", - .phys_id = ROCKCHIP_VOP2_ESMART0, - .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), - .formats = formats_rk356x_esmart, - .nformats = ARRAY_SIZE(formats_rk356x_esmart), + .name = "Esmart2-win0", + .phys_id = ROCKCHIP_VOP2_ESMART2, + .base = 0x1c00, + .possible_vp_mask = BIT(0) | BIT(2), + .formats = formats_rk3576_esmart, + .nformats = ARRAY_SIZE(formats_rk3576_esmart), .format_modifiers = format_modifiers, - .base = 0x1800, - .layer_sel_id = { 2, 2, 2, 0xf }, + .layer_sel_id = { 3, 0xf, 2, 0xf }, .supported_rotations = DRM_MODE_REFLECT_Y, - .type = DRM_PLANE_TYPE_PRIMARY, + .type = DRM_PLANE_TYPE_OVERLAY, + .axi_bus_id = 1, + .axi_yrgb_r_id = 0x0a, + .axi_uv_r_id = 0x0b, .max_upscale_factor = 8, .max_downscale_factor = 8, - .dly = { 20, 47, 41 }, - }, { - .name = "Cluster0-win0", - .phys_id = ROCKCHIP_VOP2_CLUSTER0, - .base = 0x1000, - .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), - .formats = formats_cluster, - .nformats = ARRAY_SIZE(formats_cluster), - .format_modifiers = format_modifiers_afbc, - .layer_sel_id = { 0, 0, 0, 0xf }, - .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | - DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, - .max_upscale_factor = 4, - .max_downscale_factor = 4, - .dly = { 0, 27, 21 }, - .type = DRM_PLANE_TYPE_OVERLAY, - .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER, }, { - .name = "Cluster1-win0", - .phys_id = ROCKCHIP_VOP2_CLUSTER1, - .base = 0x1200, - .possible_vp_mask = BIT(0) | BIT(1) | BIT(2), - .formats = formats_cluster, - .nformats = ARRAY_SIZE(formats_cluster), - .format_modifiers = format_modifiers_afbc, - .layer_sel_id = { 1, 1, 1, 0xf }, - .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | - DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, + .name = "Esmart3-win0", + .phys_id = ROCKCHIP_VOP2_ESMART3, + .base = 0x1e00, + .possible_vp_mask = BIT(1) | BIT(2), + .formats = formats_rk3576_esmart, + .nformats = ARRAY_SIZE(formats_rk3576_esmart), + .format_modifiers = format_modifiers, + .layer_sel_id = { 0xf, 3, 3, 0xf }, + .supported_rotations = DRM_MODE_REFLECT_Y, .type = DRM_PLANE_TYPE_OVERLAY, - .max_upscale_factor = 4, - .max_downscale_factor = 4, - .dly = { 0, 27, 21 }, - .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER, + .axi_bus_id = 1, + .axi_yrgb_r_id = 0x0c, + .axi_uv_r_id = 0x0d, + .max_upscale_factor = 8, + .max_downscale_factor = 8, }, }; -static const struct vop2_regs_dump rk3568_regs_dump[] = { +static const struct vop2_regs_dump rk3576_regs_dump[] = { { .name = "SYS", .base = RK3568_REG_CFG_DONE, - .size = 0x100, + .size = 0x200, .en_reg = 0, .en_val = 0, .en_mask = 0 }, { - .name = "OVL", - .base = RK3568_OVL_CTRL, - .size = 0x100, + .name = "OVL_SYS", + .base = RK3576_SYS_EXTRA_ALPHA_CTRL, + .size = 0x50, + .en_reg = 0, + .en_val = 0, + .en_mask = 0, + }, { + .name = "OVL_VP0", + .base = RK3576_OVL_CTRL(0), + .size = 0x80, + .en_reg = 0, + .en_val = 0, + .en_mask = 0, + }, { + .name = "OVL_VP1", + .base = RK3576_OVL_CTRL(1), + .size = 0x80, + .en_reg = 0, + .en_val = 0, + .en_mask = 0, + }, { + .name = "OVL_VP2", + .base = RK3576_OVL_CTRL(2), + .size = 0x80, .en_reg = 0, .en_val = 0, .en_mask = 0, @@ -471,18 +1007,17 @@ static const struct vop2_regs_dump rk3568_regs_dump[] = { .en_reg = RK3568_VP_DSP_CTRL, .en_val = 0, .en_mask = RK3568_VP_DSP_CTRL__STANDBY, - }, { .name = "Cluster0", .base = RK3568_CLUSTER0_CTRL_BASE, - .size = 0x110, + .size = 0x200, .en_reg = RK3568_CLUSTER_WIN_CTRL0, .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, }, { .name = "Cluster1", .base = RK3568_CLUSTER1_CTRL_BASE, - .size = 0x110, + .size = 0x200, .en_reg = RK3568_CLUSTER_WIN_CTRL0, .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, @@ -501,15 +1036,15 @@ static const struct vop2_regs_dump rk3568_regs_dump[] = { .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, }, { - .name = "Smart0", - .base = RK3568_SMART0_CTRL_BASE, + .name = "Esmart2", + .base = RK3588_ESMART2_CTRL_BASE, .size = 0xf0, .en_reg = RK3568_SMART_REGION0_CTRL, .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, }, { - .name = "Smart1", - .base = RK3568_SMART1_CTRL_BASE, + .name = "Esmart3", + .base = RK3588_ESMART3_CTRL_BASE, .size = 0xf0, .en_reg = RK3568_SMART_REGION0_CTRL, .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, @@ -908,6 +1443,84 @@ static unsigned long rk3568_set_intf_mux(struct vop2_video_port *vp, int id, u32 return crtc->state->adjusted_mode.crtc_clock * 1000LL; } +static unsigned long rk3576_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags) +{ + struct vop2 *vop2 = vp->vop2; + struct drm_crtc *crtc = &vp->crtc; + struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); + u8 port_pix_rate = vp->data->pixel_rate; + int dclk_core_div, dclk_out_div, if_pixclk_div, if_dclk_sel; + u32 ctrl, vp_clk_div, reg, dclk_div; + unsigned long dclk_in_rate, dclk_core_rate; + + if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420 || adjusted_mode->crtc_clock > 600000) + dclk_div = 2; + else + dclk_div = 1; + + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) + dclk_core_rate = adjusted_mode->crtc_clock / 2; + else + dclk_core_rate = adjusted_mode->crtc_clock / port_pix_rate; + + dclk_in_rate = adjusted_mode->crtc_clock / dclk_div; + + dclk_core_div = dclk_in_rate > dclk_core_rate ? 1 : 0; + + if (vop2_output_if_is_edp(id)) + if_pixclk_div = port_pix_rate == 2 ? RK3576_DSP_IF_PCLK_DIV : 0; + else + if_pixclk_div = port_pix_rate == 1 ? RK3576_DSP_IF_PCLK_DIV : 0; + + if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420) { + if_dclk_sel = RK3576_DSP_IF_DCLK_SEL_OUT; + dclk_out_div = 1; + } else { + if_dclk_sel = 0; + dclk_out_div = 0; + } + + switch (id) { + case ROCKCHIP_VOP2_EP_HDMI0: + reg = RK3576_HDMI0_IF_CTRL; + break; + case ROCKCHIP_VOP2_EP_EDP0: + reg = RK3576_EDP0_IF_CTRL; + break; + case ROCKCHIP_VOP2_EP_MIPI0: + reg = RK3576_MIPI0_IF_CTRL; + break; + case ROCKCHIP_VOP2_EP_DP0: + reg = RK3576_DP0_IF_CTRL; + break; + case ROCKCHIP_VOP2_EP_DP1: + reg = RK3576_DP1_IF_CTRL; + break; + default: + drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); + return 0; + } + + ctrl = vop2_readl(vop2, reg); + ctrl &= ~RK3576_DSP_IF_DCLK_SEL_OUT; + ctrl &= ~RK3576_DSP_IF_PCLK_DIV; + ctrl &= ~RK3576_DSP_IF_MUX; + ctrl |= RK3576_DSP_IF_CFG_DONE_IMD; + ctrl |= if_dclk_sel | if_pixclk_div; + ctrl |= RK3576_DSP_IF_CLK_OUT_EN | RK3576_DSP_IF_EN; + ctrl |= FIELD_PREP(RK3576_DSP_IF_MUX, vp->id); + ctrl |= FIELD_PREP(RK3576_DSP_IF_PIN_POL, polflags); + vop2_writel(vop2, reg, ctrl); + + vp_clk_div = FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_CORE_DIV, dclk_core_div); + vp_clk_div |= FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_OUT_DIV, dclk_out_div); + + vop2_vp_write(vp, RK3588_VP_CLK_CTRL, vp_clk_div); + + return dclk_in_rate * 1000LL; +} + /* * calc the dclk on rk3588 * the available div of dclk is 1, 2, 4 @@ -1246,6 +1859,7 @@ static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_wi struct drm_plane_state *bottom_win_pstate; bool src_pixel_alpha_en = false; u16 src_glb_alpha_val, dst_glb_alpha_val; + u32 src_color_ctrl_reg, dst_color_ctrl_reg, src_alpha_ctrl_reg, dst_alpha_ctrl_reg; u32 offset = 0; bool premulti_en = false; bool swap = false; @@ -1283,14 +1897,22 @@ static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_wi break; } - vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL + offset, - alpha.src_color_ctrl.val); - vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_COLOR_CTRL + offset, - alpha.dst_color_ctrl.val); - vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL + offset, - alpha.src_alpha_ctrl.val); - vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL + offset, - alpha.dst_alpha_ctrl.val); + if (vop2->version <= VOP_VERSION_RK3588) { + src_color_ctrl_reg = RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL; + dst_color_ctrl_reg = RK3568_CLUSTER0_MIX_DST_COLOR_CTRL; + src_alpha_ctrl_reg = RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL; + dst_alpha_ctrl_reg = RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL; + } else { + src_color_ctrl_reg = RK3576_CLUSTER0_MIX_SRC_COLOR_CTRL; + dst_color_ctrl_reg = RK3576_CLUSTER0_MIX_DST_COLOR_CTRL; + src_alpha_ctrl_reg = RK3576_CLUSTER0_MIX_SRC_ALPHA_CTRL; + dst_alpha_ctrl_reg = RK3576_CLUSTER0_MIX_DST_ALPHA_CTRL; + } + + vop2_writel(vop2, src_color_ctrl_reg + offset, alpha.src_color_ctrl.val); + vop2_writel(vop2, dst_color_ctrl_reg + offset, alpha.dst_color_ctrl.val); + vop2_writel(vop2, src_alpha_ctrl_reg + offset, alpha.src_alpha_ctrl.val); + vop2_writel(vop2, dst_alpha_ctrl_reg + offset, alpha.dst_alpha_ctrl.val); } static void vop2_setup_alpha(struct vop2_video_port *vp) @@ -1303,11 +1925,16 @@ static void vop2_setup_alpha(struct vop2_video_port *vp) int pixel_alpha_en; int premulti_en, gpremulti_en = 0; int mixer_id; + u32 src_color_ctrl_reg, dst_color_ctrl_reg, src_alpha_ctrl_reg, dst_alpha_ctrl_reg; u32 offset; bool bottom_layer_alpha_en = false; u32 dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE; - mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id); + if (vop2->version <= VOP_VERSION_RK3588) + mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id); + else + mixer_id = 0; + alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { @@ -1326,6 +1953,18 @@ static void vop2_setup_alpha(struct vop2_video_port *vp) } } + if (vop2->version <= VOP_VERSION_RK3588) { + src_color_ctrl_reg = RK3568_MIX0_SRC_COLOR_CTRL; + dst_color_ctrl_reg = RK3568_MIX0_DST_COLOR_CTRL; + src_alpha_ctrl_reg = RK3568_MIX0_SRC_ALPHA_CTRL; + dst_alpha_ctrl_reg = RK3568_MIX0_DST_ALPHA_CTRL; + } else { + src_color_ctrl_reg = RK3576_OVL_MIX0_SRC_COLOR_CTRL(vp->id); + dst_color_ctrl_reg = RK3576_OVL_MIX0_DST_COLOR_CTRL(vp->id); + src_alpha_ctrl_reg = RK3576_OVL_MIX0_SRC_ALPHA_CTRL(vp->id); + dst_alpha_ctrl_reg = RK3576_OVL_MIX0_DST_ALPHA_CTRL(vp->id); + } + drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { struct vop2_win *win = to_vop2_win(plane); int zpos = plane->state->normalized_zpos; @@ -1372,17 +2011,26 @@ static void vop2_setup_alpha(struct vop2_video_port *vp) vop2_parse_alpha(&alpha_config, &alpha); offset = (mixer_id + zpos - 1) * 0x10; - vop2_writel(vop2, RK3568_MIX0_SRC_COLOR_CTRL + offset, - alpha.src_color_ctrl.val); - vop2_writel(vop2, RK3568_MIX0_DST_COLOR_CTRL + offset, - alpha.dst_color_ctrl.val); - vop2_writel(vop2, RK3568_MIX0_SRC_ALPHA_CTRL + offset, - alpha.src_alpha_ctrl.val); - vop2_writel(vop2, RK3568_MIX0_DST_ALPHA_CTRL + offset, - alpha.dst_alpha_ctrl.val); + + vop2_writel(vop2, src_color_ctrl_reg + offset, alpha.src_color_ctrl.val); + vop2_writel(vop2, dst_color_ctrl_reg + offset, alpha.dst_color_ctrl.val); + vop2_writel(vop2, src_alpha_ctrl_reg + offset, alpha.src_alpha_ctrl.val); + vop2_writel(vop2, dst_alpha_ctrl_reg + offset, alpha.dst_alpha_ctrl.val); } if (vp->id == 0) { + if (vop2->version <= VOP_VERSION_RK3588) { + src_color_ctrl_reg = RK3568_HDR0_SRC_COLOR_CTRL; + dst_color_ctrl_reg = RK3568_HDR0_DST_COLOR_CTRL; + src_alpha_ctrl_reg = RK3568_HDR0_SRC_ALPHA_CTRL; + dst_alpha_ctrl_reg = RK3568_HDR0_DST_ALPHA_CTRL; + } else { + src_color_ctrl_reg = RK3576_OVL_HDR_SRC_COLOR_CTRL(vp->id); + dst_color_ctrl_reg = RK3576_OVL_HDR_DST_COLOR_CTRL(vp->id); + src_alpha_ctrl_reg = RK3576_OVL_HDR_SRC_ALPHA_CTRL(vp->id); + dst_alpha_ctrl_reg = RK3576_OVL_HDR_DST_ALPHA_CTRL(vp->id); + } + if (bottom_layer_alpha_en) { /* Transfer pixel alpha to hdr mix */ alpha_config.src_premulti_en = gpremulti_en; @@ -1390,18 +2038,15 @@ static void vop2_setup_alpha(struct vop2_video_port *vp) alpha_config.src_pixel_alpha_en = true; alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; + vop2_parse_alpha(&alpha_config, &alpha); - vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, - alpha.src_color_ctrl.val); - vop2_writel(vop2, RK3568_HDR0_DST_COLOR_CTRL, - alpha.dst_color_ctrl.val); - vop2_writel(vop2, RK3568_HDR0_SRC_ALPHA_CTRL, - alpha.src_alpha_ctrl.val); - vop2_writel(vop2, RK3568_HDR0_DST_ALPHA_CTRL, - alpha.dst_alpha_ctrl.val); + vop2_writel(vop2, src_color_ctrl_reg, alpha.src_color_ctrl.val); + vop2_writel(vop2, dst_color_ctrl_reg, alpha.dst_color_ctrl.val); + vop2_writel(vop2, src_alpha_ctrl_reg, alpha.src_alpha_ctrl.val); + vop2_writel(vop2, dst_alpha_ctrl_reg, alpha.dst_alpha_ctrl.val); } else { - vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, 0); + vop2_writel(vop2, src_color_ctrl_reg, 0); } } } @@ -1611,6 +2256,72 @@ static void rk3568_vop2_setup_overlay(struct vop2_video_port *vp) rk3568_vop2_setup_dly_for_windows(vp); } +static void rk3576_vop2_setup_layer_mixer(struct vop2_video_port *vp) +{ + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); + struct vop2 *vop2 = vp->vop2; + struct drm_plane *plane; + u32 layer_sel = 0xffff; /* 0xf means this layer is disabled */ + u32 ovl_ctrl; + + ovl_ctrl = vop2_readl(vop2, RK3576_OVL_CTRL(vp->id)); + if (vcstate->yuv_overlay) + ovl_ctrl |= RK3576_OVL_CTRL__YUV_MODE; + else + ovl_ctrl &= ~RK3576_OVL_CTRL__YUV_MODE; + + vop2_writel(vop2, RK3576_OVL_CTRL(vp->id), ovl_ctrl); + + drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { + struct vop2_win *win = to_vop2_win(plane); + + layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos, + 0xf); + layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos, + win->data->layer_sel_id[vp->id]); + } + + vop2_writel(vop2, RK3576_OVL_LAYER_SEL(vp->id), layer_sel); +} + +static void rk3576_vop2_setup_dly_for_windows(struct vop2_video_port *vp) +{ + struct drm_plane *plane; + struct vop2_win *win; + + drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { + win = to_vop2_win(plane); + vop2_win_write(win, VOP2_WIN_DLY_NUM, 0); + } +} + +static void rk3576_vop2_setup_overlay(struct vop2_video_port *vp) +{ + struct vop2 *vop2 = vp->vop2; + struct drm_crtc *crtc = &vp->crtc; + struct drm_plane *plane; + + vp->win_mask = 0; + + drm_atomic_crtc_for_each_plane(plane, crtc) { + struct vop2_win *win = to_vop2_win(plane); + + win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT]; + + vp->win_mask |= BIT(win->data->phys_id); + + if (vop2_cluster_window(win)) + vop2_setup_cluster_alpha(vop2, win); + } + + if (!vp->win_mask) + return; + + rk3576_vop2_setup_layer_mixer(vp); + vop2_setup_alpha(vp); + rk3576_vop2_setup_dly_for_windows(vp); +} + static void rk3568_vop2_setup_bg_dly(struct vop2_video_port *vp) { struct drm_crtc *crtc = &vp->crtc; @@ -1628,12 +2339,38 @@ static void rk3568_vop2_setup_bg_dly(struct vop2_video_port *vp) vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly); } +static void rk3576_vop2_setup_bg_dly(struct vop2_video_port *vp) +{ + struct drm_crtc *crtc = &vp->crtc; + struct drm_display_mode *mode = &crtc->state->adjusted_mode; + u16 hdisplay = mode->crtc_hdisplay; + u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; + u32 bg_dly; + u32 pre_scan_dly; + + bg_dly = vp->data->pre_scan_max_dly[VOP2_DLY_WIN] + + vp->data->pre_scan_max_dly[VOP2_DLY_LAYER_MIX] + + vp->data->pre_scan_max_dly[VOP2_DLY_HDR_MIX]; + + vop2_writel(vp->vop2, RK3576_OVL_BG_MIX_CTRL(vp->id), + FIELD_PREP(RK3576_OVL_BG_MIX_CTRL__BG_DLY, bg_dly)); + + pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len; + vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly); +} + static const struct vop2_ops rk3568_vop_ops = { .setup_intf_mux = rk3568_set_intf_mux, .setup_bg_dly = rk3568_vop2_setup_bg_dly, .setup_overlay = rk3568_vop2_setup_overlay, }; +static const struct vop2_ops rk3576_vop_ops = { + .setup_intf_mux = rk3576_set_intf_mux, + .setup_bg_dly = rk3576_vop2_setup_bg_dly, + .setup_overlay = rk3576_vop2_setup_overlay, +}; + static const struct vop2_ops rk3588_vop_ops = { .setup_intf_mux = rk3588_set_intf_mux, .setup_bg_dly = rk3568_vop2_setup_bg_dly, @@ -1678,6 +2415,25 @@ static const struct vop2_data rk3568_vop = { .soc_id = 3568, }; +static const struct vop2_data rk3576_vop = { + .version = VOP_VERSION_RK3576, + .feature = VOP2_FEATURE_HAS_SYS_PMU, + .nr_vps = 3, + .max_input = { 4096, 4320 }, + .max_output = { 4096, 4320 }, + .vp = rk3576_vop_video_ports, + .win = rk3576_vop_win_data, + .win_size = ARRAY_SIZE(rk3576_vop_win_data), + .cluster_reg = rk3576_vop_cluster_regs, + .nr_cluster_regs = ARRAY_SIZE(rk3576_vop_cluster_regs), + .smart_reg = rk3576_vop_smart_regs, + .nr_smart_regs = ARRAY_SIZE(rk3576_vop_smart_regs), + .regs_dump = rk3576_regs_dump, + .regs_dump_size = ARRAY_SIZE(rk3576_regs_dump), + .ops = &rk3576_vop_ops, + .soc_id = 3576, +}; + static const struct vop2_data rk3588_vop = { .version = VOP_VERSION_RK3588, .feature = VOP2_FEATURE_HAS_SYS_GRF | VOP2_FEATURE_HAS_VO1_GRF | @@ -1705,6 +2461,9 @@ static const struct of_device_id vop2_dt_match[] = { }, { .compatible = "rockchip,rk3568-vop", .data = &rk3568_vop, + }, { + .compatible = "rockchip,rk3576-vop", + .data = &rk3576_vop, }, { .compatible = "rockchip,rk3588-vop", .data = &rk3588_vop