From patchwork Wed Feb 12 09:34:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13971404 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 37A44C0219E for ; Wed, 12 Feb 2025 09:40:56 +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=a5T8HFLl7sIWEfi6f6/5GvwrQREuzTN5EVNj4AR2eR4=; b=W6t2qxQrsLrvRX HdZFDDDHTD0cOQkZ5H0MsaAnzVswJtp6pNVp7MQBUVP1x7Pa5d7NJ5mg3Rskjtbf0tZ17I8AL0jlp w0aO6e7DmNHDpgEhtuJdvZt9wTxjRnR8v1IlII6o9WmtntLddWsZpipVv7r31lyINGSsvweKszRJN RBHG0gXMh54ANISK9t3d2stbjNCRmQiLfo6xXb+lduTlO2gNiJJPpgdb1tAlD6TvBqI2CiETAqfH8 P4UDxkX7uCPhtU6Tx2FADGI2ChjqKMaQrxljmWlvHUFQiaOzcvXC1smQ3sUIZmEa7rv+Sgfj9W5IH ReKJb56qXugirVwaq4gA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9Eg-00000006pPo-16GL; Wed, 12 Feb 2025 09:40:50 +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 1ti9A6-00000006npb-3WIY; Wed, 12 Feb 2025 09:36:08 +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=l6drU h2vkH8RFHOt/j1F+EFHKFzeB3WYinyBTPKLRVM=; b=R1e0waUINkeu1t+TME29x E7wim2L2w4DbmO5N68XLALovPgsE0pJGrzV/vqNvFRaTclSTulCOsg0tBZIklQtc QdqHg7rUNULf8eq5NsDR1uIaAYPr8jP4Fdc5Q72l0yO6b0mHpC3aC0JZ0plG7+3m lMNpfRbTitAkTPJRROolO0= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g0-1 (Coremail) with SMTP id _____wBnG9Fja6xn14FuLQ--.33700S3; Wed, 12 Feb 2025 17:35:36 +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 v14 01/13] drm/rockchip: vop2: use devm_regmap_field_alloc for cluster-regs Date: Wed, 12 Feb 2025 17:34:56 +0800 Message-ID: <20250212093530.52961-2-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wBnG9Fja6xn14FuLQ--.33700S3 X-Coremail-Antispam: 1Uf129KBjvJXoWxGFW7GFWUWrykJr4fGF17Wrg_yoWrZr4xpF 4rCwnxuF45Grn29rWkArn8AF1Fk39rta1rCFn7uwnI9r1qgr97C3Wqk3Wjyrs0kryv9FZr tFs8t3y3ua4Ygr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07Uu6wtUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqQjxXmesZ5VJpgABsZ X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013607_275621_F90A81E6 X-CRM114-Status: GOOD ( 14.27 ) 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 afc946ead870..ebc9cb93073c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -3400,7 +3400,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), @@ -3471,28 +3471,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), @@ -3559,26 +3557,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 Wed Feb 12 09:34:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13971412 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 0D857C021A1 for ; Wed, 12 Feb 2025 09:52:23 +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=0sf/hp2HtSpxIxTQucycqCp0rXWyryL+AWJZUE3kXx0=; b=qkwiPyT+FUV1uQ BkW3Q46GNejgPKcuKjhiXtlVycR70DIylGGwCmx7+prZsCjmXcx6RMKhYgxhjEBd4VgHewNzxz/0w GgRgzVM0Pfg7zM5Zcii31fXe/PzMmQTy7mLhy23bvbKYRPVhLHOJ/5UB2a5kkFuR/wQsuFKNgn6vs uUDuzq3Mr7EsdOzZ3aW4Th8agspwL982PWyr28XU7y9+Ve9VOOTEkJRO21VKKyJO8L/TJH/Bn92Np wnobuA3yR/aq5cHkAzgcTySmVf0NMZwr1zWH4VZWvKFNiXOQZbjy1CTCnLZGJhp/KhAekT8ESdhHv l1ZleYuweMSBXG7kE8gA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9Pn-00000006rwn-0nHb; Wed, 12 Feb 2025 09:52:19 +0000 Received: from m16.mail.163.com ([117.135.210.4]) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9AU-00000006o3K-2iau; Wed, 12 Feb 2025 09:36:32 +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=E49mb M8Y56MagZCzjfVLDOWNTUIqbd/u7olBPvb7dv0=; b=PY6H+C1wTH948HCsVaQ2D Ud2InDLN9wC8gpamSiJfdOX/JrlVKnvkMQxwtn5ozj9rGTURWtnZk0T7FTBnpbId LE5uAZVmDnuNlW9KVeZOkwUmnHDZZzUj+MaPCd6LDiHDFLW8VzuEnr3tNRwvJwra gguPS2eaFOEx7/YezWvvZo= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g0-1 (Coremail) with SMTP id _____wBnG9Fja6xn14FuLQ--.33700S4; Wed, 12 Feb 2025 17:35:37 +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 v14 02/13] drm/rockchip: vop2: Rename TRANSFORM_OFFSET to TRANSFORM_OFFS Date: Wed, 12 Feb 2025 17:34:57 +0800 Message-ID: <20250212093530.52961-3-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wBnG9Fja6xn14FuLQ--.33700S4 X-Coremail-Antispam: 1Uf129KBjvJXoWxCrWxKw4rJFWDCryxAr43KFg_yoWrCr18pr W3JayDWF4UKFs2qFWkAr15AF48Jan2k3yfGa9xJrnIqFyaga4DWw12ka4UJr47ta4I9FZ2 q3saqrW7urW3tr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07j1jgxUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/xtbB0gzxXmesX27xyQAAsz X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013631_025087_CD09FFC8 X-CRM114-Status: GOOD ( 11.27 ) 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 ebc9cb93073c..8e1b742a7550 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1524,7 +1524,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); @@ -1535,7 +1535,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)); @@ -3448,7 +3448,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), @@ -3547,7 +3547,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 Wed Feb 12 09:34:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13971408 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 D0CE6C0219E for ; Wed, 12 Feb 2025 09:46:38 +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=O6I75v4iTEfbkrW7bo+kjjRUF8AHoUDmSIq0oSQQ3N8=; b=Nn1d7lGDPDCqk3 CDcxLbcEDXdWgnJP7p4jxl+vr7wHUJxj0r+OY3pqtaQS3n0qCs2R7Fza4vj7YoQMn0mCaU7BR4Di4 KCjDLLsdFz8PzhtQWrMrA1gJawKglspdX6/gS2B3kbX3iDlZKH62/5Hrgv2DhT8z86z4XVCFAAqtE ymaA4bj8N3wJjmDxobbaYb+iWWveqSHZjD06GWdwu/HaR2vjqb5Qusxh67o8Pi0pY9JO+JuBf9MA4 bOVOIMooulql5ge+iozSONCJXLgw7X+/VadJ9v6xh3i7IbFA8qEFZpjpLkWi7PXWn2wDxXwQ16MAY 2gzVNO47DwKj4ZU6+R1w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9KE-00000006qbz-3YfB; Wed, 12 Feb 2025 09:46: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 1ti9AA-00000006nsa-0jMv; Wed, 12 Feb 2025 09:36:14 +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=nTlkX UspyF7h8nCK7Q8bZnNRnF8+53wahEdXBzRIbUc=; b=lnfc9XheMDe5Pp4WfnlpZ yO8aIm8M5z/ViscpwTxZME4WiBFqAB5JAz5DLvpPc80cQl63zHSCalzoyby7AypD 06I+sngepFrX8daYwKlPXT/R7ojxdH4vDHEp0YbhdFUzc+Nm4IqtYOsnT8a6WPTV +p4mSUJNyyy4JWlrVsPdkQ= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g0-1 (Coremail) with SMTP id _____wBnG9Fja6xn14FuLQ--.33700S5; Wed, 12 Feb 2025 17:35:38 +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 v14 03/13] drm/rockchip: vop2: Add platform specific callback Date: Wed, 12 Feb 2025 17:34:58 +0800 Message-ID: <20250212093530.52961-4-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wBnG9Fja6xn14FuLQ--.33700S5 X-Coremail-Antispam: 1Uf129KBjvAXoWDtFWDGFW5tw13tr15Jw1rtFb_yoWfur17Jo W7uF1Fqr4Iqw1rKrZrWr17XFy7W348Can7Cr12qFnxZ39xX3yjkF92q3ZrtF17Jr15Cay5 Aws5t3WrZa1fXFs7n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UbIYCTnIWIevJa73UjIFyTuYvjxUat8nUUUUU X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqAHxXmesZw5TqAAAsf X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013611_063683_3F15E349 X-CRM114-Status: GOOD ( 18.49 ) 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 --- Changes in v14: - Rebase on drm-misc-next 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 | 1141 +----------------- drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 170 +++ drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 992 +++++++++++++++ 3 files changed, 1179 insertions(+), 1124 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 8e1b742a7550..a0d961cb5d21 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,147 +101,8 @@ 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; - struct clk *dclk_src; - 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; - struct clk *pll_hdmiphy0; - - /* optional internal rgb encoder */ - struct rockchip_rgb *rgb; - - /* must be put at the end of the struct */ - struct vop2_win win[]; -}; - #define VOP2_MAX_DCLK_RATE 600000000 -#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. */ @@ -276,15 +136,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) { @@ -296,44 +147,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 @@ -1731,6 +1544,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; @@ -1741,18 +1555,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); @@ -1788,347 +1594,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; @@ -2201,7 +1666,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) { @@ -2351,454 +1816,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, @@ -3400,86 +2424,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); @@ -3490,82 +2446,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); @@ -3651,6 +2543,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..06af94d4edf0 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,107 @@ struct vop2_video_port_data { unsigned int offset; }; +struct vop2_video_port { + struct drm_crtc crtc; + struct vop2 *vop2; + struct clk *dclk; + struct clk *dclk_src; + 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; + struct clk *pll_hdmiphy0; + + /* 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 +682,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..1bfec7d839cf 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 Wed Feb 12 09:34:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13971403 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 EFC8AC02198 for ; Wed, 12 Feb 2025 09:39: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=DsPYfcDL62HYCYPLUhecKJFhkPwvlxWg1b7VqDhsIRc=; b=DBjcKqG1ihxBgl qdlCQ6lIlG96bV+hWH/h4vrJbyoSjsRWjrA+pIY2EQR84FwRgBOjH0Y0QCcEuFUPYtxi49sVadC24 LAhtKjTTRpED2YZ63kltAk+WojR4EBfas8zcNvb1SAChFggdNB7MR2+ya2iF0AkvBdMEWo8DW4xjF zUs7plAYQvDj14AkDJ2MAjpRJqzoftCETZGLWQQhGuc7M1nUQXI+/MIFlQZcIqQyGn7Xa9sOgBw8q XagnEON5WfLMVNHun1+EX1CSzW6M6VGiQA0m0gN8qYxFMte7EHJy7I6SReLYtLLPLQtkiOuv2bToa wr5b8b/mmonrciXDGKGw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9DH-00000006p0c-41KE; Wed, 12 Feb 2025 09:39:23 +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 1ti9A6-00000006npM-3XLp; Wed, 12 Feb 2025 09:36:08 +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=URKKB 59F/q0mF1SZHAnHb3HC+RFEwqYwuY5f1Lrg/6M=; b=W/U9ojoUFD0Ezbx44WQ/c fKXXxs2TX+q25TzBRH44cdTzvhaA/Am+offgB53//E35EP1B1IMmj84wXor7DtIT FiXioG43/NdbFBT/jpkhk5IUB+T8WyYjZlr2nWgpYak9cknqUP++SEShDrUSVfk7 7tMAa8HZ8n++HHv5NK5cEQ= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g0-1 (Coremail) with SMTP id _____wBnG9Fja6xn14FuLQ--.33700S6; Wed, 12 Feb 2025 17:35:39 +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 v14 04/13] drm/rockchip: vop2: Merge vop2_cluster/esmart_init function Date: Wed, 12 Feb 2025 17:34:59 +0800 Message-ID: <20250212093530.52961-5-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wBnG9Fja6xn14FuLQ--.33700S6 X-Coremail-Antispam: 1Uf129KBjvJXoWxWw4UKF17CrWktr18AFykAFb_yoW5Xr1DpF W3Gr43Wr4UGrsFgr4kJrn8uF1Fkr12yaykAa48KwnIkwnrKF9FkFn5JF10yr90krWv9Fy2 yFs5K3y5ua4j9r7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07UZ6pPUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqAHxXmesZw5TqAABse X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013607_264471_AAACF679 X-CRM114-Status: GOOD ( 11.34 ) 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 a0d961cb5d21..844df4001159 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -2424,18 +2424,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); @@ -2446,28 +2446,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; @@ -2484,9 +2462,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 Wed Feb 12 09:35:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13971410 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 1A9B0C02198 for ; Wed, 12 Feb 2025 09:49:30 +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=YKEV3JboDr6ET9G9ngv5Jbi94THbm2CQNXQgD3YHvJk=; b=zGM1XSbGuBGITN 1kHVA3oKG81U/fM5UwL41t4fqTRCzFWGWozu3VGekSiCya8k7VFXCeaM53pdr/haLbxTyNFgsNmzW yHns+wFwutzp7DFrcrSo7T+wVtcN1g02p61tvpH8/yKQQV98oEfgWsdNDXd75dCoGUql2FKZ0aC9O hrp/Ee00i5Dy5TUgKjHoCY3tqzS+V3LBHQb4BNwVowymQm2zYnVH0rhQbmNFmxx4DyAN+GnCsPR4q c9JMULtoy0GDm6TZQSTtPxEisqfyo8koVu+wIlG9UX1ywe0GKlhzaOoZadx0D/rM3rydw2FlMwZ4e Fgsapqd1mNh8Sl7PGXmQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9N0-00000006rE3-1Fq6; Wed, 12 Feb 2025 09:49:26 +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 1ti9AK-00000006o0V-3RQs; Wed, 12 Feb 2025 09:36:22 +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=T5ruw RVxHIjZehEkkgO20WLgxfZhJzxAJ3w42ZFAuPo=; b=pMUpb8x05MI9iIHjctG0F JY7KOodLS4LvQRoCg/p5sLcG5Z2O+Bd7YD+aRAC+a3rWLlPVtjhJqiys7fZst1eq Zkt7Lf7c42li5U89WokiYi6o81QoPdmsdsvq2blRuIJbQXmzQN++35TbI7HAF23E tJS1ZHvSxJoq5S+XX9icbU= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g0-1 (Coremail) with SMTP id _____wBnG9Fja6xn14FuLQ--.33700S7; Wed, 12 Feb 2025 17:35:40 +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 v14 05/13] drm/rockchip: vop2: Support for different layer select configuration between VPs Date: Wed, 12 Feb 2025 17:35:00 +0800 Message-ID: <20250212093530.52961-6-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wBnG9Fja6xn14FuLQ--.33700S7 X-Coremail-Antispam: 1Uf129KBjvJXoWxtrW8JF4UZF47CF4UWFy8Zrb_yoWfJw4Upa yUursIg3W5Cr45tryUJay8Zr4rGwn8tay3uan3Kw1xGFn5KrWDJF4ktF95A3Z8KF93ZryU Xw1YgryDZrW7tFJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jFFALUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/xtbB0hTxXmesX27yBwAAsm X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013621_179370_70D318CC X-CRM114-Status: GOOD ( 14.74 ) 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 06af94d4edf0..9e2cf1ab869d 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 1bfec7d839cf..c1b49a01a2ba 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 Wed Feb 12 09:35:01 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13971405 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 4DF50C02198 for ; Wed, 12 Feb 2025 09:45:13 +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=F2nNWKMZjZZ9eLmQeAiexQP9nqh9z6ILC++4y8G7Q5g=; b=djPwM3y8vJDu3b yYCiLesaAViDhdcqCi7RQzXjVqCgC/hDh1XK0vwEQvDHH03llZOoE/3nbIVX6UGGMibn3SqeTopfd j2SHU2HndhFHGENyJnQ3CzCuCs29FSpmzXIGxdKtqO9P55LX7SKsCRxd21AZcZMKvVra8IgoTybMF SUCXrK+48cKBUFquKMoZEyHE2m5+C5wzpjmyowsD8ou/JMKjf51Wav8gS2ZJZNq9y2DKWeqQuiUHe wWnIA6yrnRVrwbGigLiomgHnoOuIkvUxSackNtH1MdVEHSQ8YeXagPS0u6wal1fuwSc2+lxzO4jTg jd70a38Nwxz39bJ/+4iA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9Ir-00000006qEb-0RjN; Wed, 12 Feb 2025 09:45:09 +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 1ti9A8-00000006npw-0LCv; Wed, 12 Feb 2025 09:36:09 +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=Ung3T E5+Pw1IVFWddIyTCDXDUdff897UQnrStYM2ux8=; b=WTcmYjZ+Vrb5oHurO+c4M ZHfE6sa+zx76HinDujuxWAnalvgZX79SSQGVjBU+Oq5KJolJI/kMJzKyEMXS5v9f iVDoxNlnjO8Q955FDF7nId0DPsNQ0RpeclBP0AAZuim/5OhmmaFwzlr84tOpY+NV hZfc7D3QPeF8M3Tuq+kFQY= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g0-1 (Coremail) with SMTP id _____wBnG9Fja6xn14FuLQ--.33700S8; Wed, 12 Feb 2025 17:35:41 +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 v14 06/13] drm/rockchip: vop2: Introduce vop hardware version Date: Wed, 12 Feb 2025 17:35:01 +0800 Message-ID: <20250212093530.52961-7-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wBnG9Fja6xn14FuLQ--.33700S8 X-Coremail-Antispam: 1Uf129KBjvJXoW3Xry3tF47Cry8WF4fWF1xXwb_yoWxKw1xpF W7Aay5WrW8Ga1qgw4kAFW3ZF4aywn2yayxJanrGw1ft3sxKryDG3Z0qF1ayFZ8tr92kr4j yFs7ArW5Wr42yr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jFFALUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqA-xXmesZw5T5AAAsd X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013608_425150_50046C0B X-CRM114-Status: GOOD ( 18.98 ) 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 844df4001159..a7c26ef18b85 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -356,7 +356,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; @@ -409,7 +409,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, @@ -420,7 +420,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; @@ -819,6 +819,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) { @@ -838,10 +839,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); @@ -922,7 +933,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) @@ -1264,7 +1275,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); @@ -1324,7 +1335,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); @@ -2524,6 +2535,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 9e2cf1ab869d..a9bcaa6e27f6 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) @@ -243,6 +252,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; @@ -260,6 +270,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 c1b49a01a2ba..68bcd50c9af4 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 Wed Feb 12 09:35:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13971413 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 8CE3EC02198 for ; Wed, 12 Feb 2025 09:53:50 +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=4IiO+8cOVjvf0iiCuRWZK5UHWwJJ8c+wlTCiF8BcuXg=; b=WHKCkMNQ2h9/zk x+o0750y+yOTRHXChrKgrlBPFMOglnc+irFa8xzDB4q1QPcQsubvPvrGeguqQx1Gswy0OyhWJypoi CCuR/R2PVdb2ljbddJJmZLavCDnShyUxByoQxrZTpWwZEHQD3DoZOzDpad0p225jau/CUD4IDJlNJ T419gnUhPQAByoTWi+xpcwMLoAsR6dFE5m5ZDCKLDQeojK6sI5jajFxX4PfJBOcqOcAzQutxwtNgy PRj9hbk3DoX8l1vuiZZGKsEsVZGBqVAsM+sVhCU9YcoRhF1jFlpjr+siL9B3DUvo6L+8jPqd0Z3Hh 6fSQJo4cZ24FFQCa/YZg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9RA-00000006sBx-1JoS; Wed, 12 Feb 2025 09:53:44 +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 1ti9AW-00000006o4S-1LOu; Wed, 12 Feb 2025 09:36:34 +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=B+2D+ j5/r7swNWHTHahxPbClGVc2AFfDHnl7wLwAR1c=; b=j05U+FMjCi0ZZKnJBfDIR wqgACpxPvsylBpVRBOvPl3TwC3cgp/iwHRBQPyC3VZ2Bi3+3wguLKAKl2L77v9fC rBRIAnGDw5ep2p5Ibfq/CyKJ9r3Ws/qGcV5Ogy8rZT9K2m9jgGHL0Mw3Upxj0nf3 tv+7xvjwkIrjYvwoI9+wpo= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g0-1 (Coremail) with SMTP id _____wBnG9Fja6xn14FuLQ--.33700S9; Wed, 12 Feb 2025 17:35:42 +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 v14 07/13] drm/rockchip: vop2: Register the primary plane and overlay plane separately Date: Wed, 12 Feb 2025 17:35:02 +0800 Message-ID: <20250212093530.52961-8-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wBnG9Fja6xn14FuLQ--.33700S9 X-Coremail-Antispam: 1Uf129KBjvJXoWxGFWxtw4ktFWktrWkZr4DCFg_yoWrZrW3pa 13ta98tr47WF42gry8JF4UAFWYyan2kay7Crn8Gw1a934fKr93ur48KF1DAF1ruFnrWFya kFW3K39Y9FWj9r7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jFFALUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/xtbB0hHxXmesX27yJQAAsB X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013632_668864_9D8D4231 X-CRM114-Status: GOOD ( 15.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 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 a7c26ef18b85..d6f22c17b0f9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -2248,22 +2248,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) @@ -2274,7 +2281,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++) { @@ -2313,42 +2322,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 (win->type == DRM_PLANE_TYPE_PRIMARY) { - vp = find_vp_without_primary(vop2); - if (vp) { + if (vop2_is_mirror_win(win)) + continue; + + 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 Wed Feb 12 09:35: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: 13971409 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 BE19EC02198 for ; Wed, 12 Feb 2025 09:48:03 +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=iPNvMyoh04TvdoClPv/g3+xnCWidgrt+uxu5raHW2L0=; b=Rv+vM85VDkoJVk vAVW1/N/ZddSLmTDGYWdnq7f51QqnWEB0KYOxq6aae+PgVwCm/kgetVgDb+YQIIYWggvXdoJjEauT zL84AibeVEds2DgAaYVNxZRR1ZJ9p2CZbbpv1PSSq8uvtp0bJNKee9dBpT/JxXXReBvfaGD6I1V4O Y/PtDlAd6euO23N2B+tt6rP0rCZkVyf/whmQrY+AvRwNdW83JDv858GEJg6ZOdrz6Q4wENxISqxts DVC7SSDzeGxwxKl614BWytPOHSMt2EFaBR+ASQJ7f3C04Lp9ioj6OvaHOldDvQ4yJlfmFG43SgPMi ZK0J+FSfybZ1UW4HjN2g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9Lc-00000006qrx-1ANj; Wed, 12 Feb 2025 09:48:00 +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 1ti9AH-00000006nyx-0vxY; Wed, 12 Feb 2025 09:36:18 +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=BKUGH SluIIQMXpbpm6ZoH1kQLhLzzE153adLP7RA+Bc=; b=jBug8AYFCy3FFyGN9h1Ea 4J+9rkr4BytTa3sQ/bP7YTyx8HiFaTMFIbu7UtLqOdObpZJJuOmSNs0FHUbRh6us z/DPUnyRqQVeetRHr6jvyGaguwQ6hGaL/wKVkS48yGRKKpFRv6aXKY0Fz0NP6pwN rk3AMBvqcca3dYBIqDAiJM= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g0-1 (Coremail) with SMTP id _____wBnG9Fja6xn14FuLQ--.33700S10; Wed, 12 Feb 2025 17:35:43 +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 v14 08/13] drm/rockchip: vop2: Set plane possible crtcs by possible vp mask Date: Wed, 12 Feb 2025 17:35:03 +0800 Message-ID: <20250212093530.52961-9-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wBnG9Fja6xn14FuLQ--.33700S10 X-Coremail-Antispam: 1Uf129KBjvJXoWxtrW8JFWkXF43Zr17tw45GFg_yoWxKrWUpa yxZr13WF4fCr4agry7Ja98ZFyak3sxAw4a93ZrKFsxKr13Kry7Wr1UK3Z8Cr1DWFyxZr1j vw43tryDurnrtrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jFFALUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqArxXmesZw5UBAAAs- X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013617_651358_A46FE94C X-CRM114-Status: GOOD ( 13.84 ) 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 d6f22c17b0f9..4a9a397dc06b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -2336,6 +2336,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; @@ -2367,7 +2371,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 a9bcaa6e27f6..da0846dfeb2a 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 68bcd50c9af4..bca4cba6ea5c 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 Wed Feb 12 09:35:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13971406 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 64DC9C021A1 for ; Wed, 12 Feb 2025 09:45:14 +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=WG+rke4Ow6CILUcY+a2LLB00PBnMCi/iFHDm4Vbp62Y=; b=vHweZY1W1kuXa7 13pCV8awlHKVGZn2BbIHqNZixcVe3t9bXcVtLzBIzOvvoE+kLEhfMLGQyYsvGOPUASODboBZUmA9a qy4CHWF+uzxlwWx68/yL73IbxH1+ZeFBVTZ2pSe4JN806Waxcx0QcmzoopqU3+bGAUSfcW4CWlr/D /GnwRGQoJG5052eWB3eK4P5C0rLWr1t2kNwWs1LldDw9aNKfvYCmxnONS5/H7fkKbtCkP8qz/sz1M XCW1dT7KxnXQbDoBHzq/dQ3coQ2TFI58gE/Qly6kQwa9uqQOFtzlFHRyHIbjZ7SsbF87rH5XovTkJ yElgFBTQJMdoGiztP0Aw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9Iq-00000006qEP-3CDT; Wed, 12 Feb 2025 09:45:08 +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 1ti9A8-00000006nqx-0MTz; Wed, 12 Feb 2025 09:36:09 +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=sk//P HbsneId3/RrJkXkBvt5LOhcReSat+OU/V8Rlq4=; b=XB5vHdJGwBXy9rgHKzuy3 3+kwqjaKuMiGvjI6VzROLhs3S+2vS4YVyeFY3ChcG9a3Ydbn2fldt6iMl3r/Z/H+ aBHJ3CTTSftCAPtARBco5Y2gk270iHZI2K0Ovh4IY6eDhabg3NLGdn6RlgvHung2 Zj7RuoQMGFyBSHCS2Z79V0= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g0-1 (Coremail) with SMTP id _____wBnG9Fja6xn14FuLQ--.33700S11; Wed, 12 Feb 2025 17:35:44 +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 v14 09/13] drm/rockchip: vop2: Add uv swap for cluster window Date: Wed, 12 Feb 2025 17:35:04 +0800 Message-ID: <20250212093530.52961-10-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wBnG9Fja6xn14FuLQ--.33700S11 X-Coremail-Antispam: 1Uf129KBjvJXoW7tFW8Ww1kAF4UAw47JFy7ZFb_yoW8XrWfpr 43ArWqgw43Kr4Iq34kJFW5ZFWftwnxKayxZws7tw1F9FyagFyDKwnYkFWUArnFyanFka17 tF93JrW7Zr1jvrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jFc_-UUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqArxXmesZw5UBAABs+ X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013608_439850_993BFAB7 X-CRM114-Status: UNSURE ( 9.56 ) 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 4a9a397dc06b..80a15288b805 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1378,10 +1378,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 Wed Feb 12 09:35:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13971411 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 9FD9DC021A1 for ; Wed, 12 Feb 2025 09:50:56 +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=5N8x2C3xvY6WcpQ0dS427+T705UTNuUeKtp88z/5R4E=; b=U51/hD9sEeLXkR zhm49AOQ+NMNKXTYDXkMyZ1osde+RtkZtLU6H4BawUP8RcWnJY2eO1NCL4ZpGF2KwoUYVpkD5nLKa 28IJF6tlHEXXXH5/YvJAiHS2ddw6lxmCuUIZd5yKEBVf1ra+pn0tEcu9W07FZ2Eet8oxsjH4eGYo4 C998vlu/VOhr2EIfoBU1Tu98RtI0vWHqBxJVCVYGEVh7ovUzqtq9jVREDfoz02YXGR+AUWkJP5QNT +8HpTOSzupvTSA9Q84OxigOlBRyeJcxsUa9E7y3MYb879Dox5uiWopy9qv6KkW7XtjVDfRY8+dlYY gIpz9tlhkeZ45tALLkFQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9OP-00000006rcE-1aE3; Wed, 12 Feb 2025 09:50:53 +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 1ti9AM-00000006o0t-23ty; Wed, 12 Feb 2025 09:36:24 +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=Zg81E ugW+SQhF7AGfomh7BYRKj3sSMrCnBpJRgio1wY=; b=FiJTvakzKzORNU7dsV0p2 uo9l2TgbODrV/COpbaiQ+mqVeDEcJR3pt39mPyYbEjFvaiLAboMuphHohl+kEHrc 2AeVmjyeELuUIuIiVDp76bOgiia17862/09bFrir/Lh3ZxAFC6i45m8/0oz5UPS2 J1n0/O/BMQToiX5KaTJnwQ= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g0-1 (Coremail) with SMTP id _____wBnG9Fja6xn14FuLQ--.33700S12; Wed, 12 Feb 2025 17:35:45 +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 , Krzysztof Kozlowski Subject: [PATCH v14 10/13] dt-bindings: display: vop2: describe constraint SoC by SoC Date: Wed, 12 Feb 2025 17:35:05 +0800 Message-ID: <20250212093530.52961-11-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wBnG9Fja6xn14FuLQ--.33700S12 X-Coremail-Antispam: 1Uf129KBjvJXoWxZF4UWFyDtryDuw43JFyftFb_yoW5ur1Dpa 97Cas8X3ykGr1UWw4ktF1fCw4SqF9xJw4UJrn7t3W7Ga1DKF4UG3ySgwn8Ar9xWF42vaya 9a15Cr15Jw42vr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07UZvttUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqArxXmesZw5UBAACs9 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013622_856293_425731D0 X-CRM114-Status: GOOD ( 10.92 ) 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 v14: - Set maxItems constraint of clocks for rk3588 to 9 as a recently merged patch added two optional clocks[0]: [0]https://patchwork.freedesktop.org/patch/msgid/20250204-vop2-hdmi0-disp-modes-v3-1-d71c6a196e58@collabora.com 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 46d956e63338..a5771edd83b5 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: @@ -124,43 +125,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: 9 + clock-names: - maxItems: 5 + minItems: 7 + maxItems: 9 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 Wed Feb 12 09:36:13 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13971414 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 B455AC02198 for ; Wed, 12 Feb 2025 09:55:17 +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=15Q0zF6XRhMDM4xLuctA3s0e1NZWzzHYLXJgqOO6QQo=; b=rPdUjS/e/895EC 587Mwd9xjWhgvpWVCuYS+o11P6of5Oi6ZUi8+PA/NRwdRHYKcK2OrJl/a0jQMwaPfjxhEsJSwFBMc f97vUCanZ3CihVhJUZ7J2bjIkNIsewhCisVkeo5EcX7joDbAs5RNWHPnXCDSzJZj1fAjbVeA6A4Ci PmNVl1qfwrOTqk+0UOIUST9zW0GXC02LdRFJ5oQBOKw1jqY7bdt49gq7uFhdYK/ExYd6wYomAFmZO G/2ZUkmloyZ9IR0nL/FjbWPD46VxUJH1KpvxbcGvvFXVcPYwAg9MABXgX5ePtlq+2NalLb0QCBA2l 4r9CC/i8s4N0YSoWqc5g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9SY-00000006slC-1M8q; Wed, 12 Feb 2025 09:55: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 1ti9Ai-00000006o9w-0GLq; Wed, 12 Feb 2025 09:36:45 +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=x5wpq KJUmSg4bQV96jwM4c9cPSXvq7N01GUYeXUKlfk=; b=okQKh0iUdQ64yIaPM7a99 ar3uuLYT3C/HzkwQg6KkU2k8fCAs6ZdJaVh0VU7ua7cQ5XwN6Ja/bxUTJSGyIQNN zm30Rq9gxGIU6p5kURX/GPghC5NO5Nxha0P/0RvORO0HPPqjAVF43d8NZqOmNu2Y xLB0t8dgwxlGX/3sSMFT04= Received: from ProDesk.. (unknown []) by gzga-smtp-mtada-g1-4 (Coremail) with SMTP id _____wBn8FORa6xniPPgLA--.46093S2; Wed, 12 Feb 2025 17:36:20 +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 , Krzysztof Kozlowski Subject: [PATCH v14 11/13] dt-bindings: display: vop2: Add missing rockchip,grf property for rk3566/8 Date: Wed, 12 Feb 2025 17:36:13 +0800 Message-ID: <20250212093615.53023-1-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: _____wBn8FORa6xniPPgLA--.46093S2 X-Coremail-Antispam: 1Uf129KBjvJXoW7tF4fZw43KFWxury3JF43KFg_yoW8Gr43pa 93CFWDWay0gr12qw1DtFn5Cr4v9F97Ca1UJFs3G3WIywnIgFn8Ka4agrn8XF4UGF4xZFWf ua1Ygry5trs2vr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jnhL8UUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqRrxXmesZ5VM2gAAsz X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013644_483663_DD54AADB X-CRM114-Status: UNSURE ( 8.84 ) 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 --- (no changes since v13) Changes in v13: - typo fix - 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 a5771edd83b5..083eadcf0588 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml @@ -146,6 +146,9 @@ allOf: rockchip,vop-grf: false rockchip,pmu: false + required: + - rockchip,grf + - if: properties: compatible: @@ -200,6 +203,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 Wed Feb 12 09:36:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Yan X-Patchwork-Id: 13971415 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 B92C6C0219E for ; Wed, 12 Feb 2025 09:58:06 +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=8tGTTKZ1m60KuK2bUhoqapOSACojj+/wRkexWcl7aQw=; b=N7KCtvr4aaGrOV /tjb9+ngKJ7SoZLRII3k4DxTE2D8bqHm7GsUlWa0ihR6ZDNpCp96tTjsEAuMMXPusOUEq372z5eN3 5k0gt13nAO2Cks7Aa/CTWNl0CC/sg7Y3lZLmuaDNWQYzXis96fcjcYHVeOvNpiRKPZfijzApPzD6k Lpy8JZ5A4mwEvPqWF7gWrBRtwour4k6Yd7qJtmWfXzti9Eiu/1RIl7fb6oRw29F2LjBojw/MrreI1 1FPnZsY/OushoN+lMifHWoFPUsz4lD/pgX5mNA7U0VO82Vwx1dv1xE9hVWaMZr132elhA0+B5RRY2 8I2yZKa/Ampfn+DCG8Hg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9VK-00000006tI7-23pS; Wed, 12 Feb 2025 09:58:02 +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 1ti9Al-00000006oC4-1SvF; Wed, 12 Feb 2025 09:36:48 +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=iEV3o ojg3U2eJSaxG1OETOyVCd9PZzwbh6RS1wsZRok=; b=pYffVqzPO7vxb43DrFOZ3 XkwSxFscVztob7o0EuU1YvVKZ4V27YVZhe6qr7BXmAS4Tmdl+mdCdzZU2EKCWEL2 Jf+wZxM+XvLhYS5l1oshjc6i3+wDNyg5o8LWSJ/nCU15CMK/2GW2+/bN8an/NGBG 6eHtnPhF/yHELxxGYpO0Ks= Received: from ProDesk.. (unknown []) by gzsmtp4 (Coremail) with SMTP id PygvCgDH3wCda6xn73YTCQ--.34396S2; Wed, 12 Feb 2025 17:36:33 +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 , Krzysztof Kozlowski Subject: [PATCH v14 12/13] dt-bindings: display: vop2: Add rk3576 support Date: Wed, 12 Feb 2025 17:36:25 +0800 Message-ID: <20250212093628.53052-1-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: PygvCgDH3wCda6xn73YTCQ--.34396S2 X-Coremail-Antispam: 1Uf129KBjvJXoWxWr1kWFWUuF4UtFW5trWkZwb_yoW5tF4fpa 93Cas8XrW8Gr1UWw1ktF1rCwnYq3Z3Aw1Ykrn7Ka13KrsxtF48Ww4agrn8Zr9xWFy2vayj 9F4Fkw17G3sFvr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07UBMKtUUUUU= X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqBXxXmesZw5XnwAAs4 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013647_700683_4ABB03A4 X-CRM114-Status: GOOD ( 11.41 ) 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 --- (no changes since v13) 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 083eadcf0588..f546d481b7e5 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: @@ -136,6 +148,11 @@ allOf: clock-names: maxItems: 5 + interrupts: + maxItems: 1 + + interrupt-names: false + ports: required: - port@0 @@ -149,6 +166,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: @@ -164,6 +214,11 @@ allOf: minItems: 7 maxItems: 9 + interrupts: + maxItems: 1 + + interrupt-names: false + ports: required: - port@0 From patchwork Wed Feb 12 09:36: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: 13971416 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 754B0C021A0 for ; Wed, 12 Feb 2025 09:59: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=C62H4OoP9tkWiP58ptLuvaR6NiWHYYd0v/991GddCRE=; b=jCQMD+bDg3rOgB G4a1NSWtUMTrAJtySuMfsx7965eDMghBEPSfiaXw4ppDzRTye1wsC2yErkrK4gJpO/GhY7biOyozd FA3emri4iP69HC5SZXlJq9iqmNQJl//gQnyZDoXCYNT/zDnKm5pPLoioXXZCJigeP/43QKV+UhX06 FE3rYO3JCI5UR13yTIAQOE22XymfUhS7ax/CH41SbxaXxSVV/LQiZLDn/Kz3oE/UAKUx6A1jNd5yO gJquoOgUXJH9Tu/ZWHkFWyGsHvlaC0mIybK+GNaWOLSkS1KpkNujD6Byt+BXzxYNfTv959efzwWCR HpkWLDLcw7H1A+XR3j2w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1ti9Wi-00000006tXv-2iDc; Wed, 12 Feb 2025 09:59:28 +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 1ti9B9-00000006oKN-3cAK; Wed, 12 Feb 2025 09:37:15 +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=iNxCs 9zshT9+P/CBkTqMvX3FXxgjE3ranzeslXIl/9c=; b=K72s4CEDsWxR8j+l0Dz1D TQsAZesfTtD+sNSC/w0OB4Z6RMtgnSRvr/TPYxAIwICZrDwRQFpjGyDgoxeFD8Fr sTRKk7e7eTSu3cd0jIE3LfUgbE/zGVFw3hJR0NMapWqFV7UyYLkOe4BeJTZDG5uH BZf7Pt+EeVHquTiDwzyQ0E= Received: from ProDesk.. (unknown []) by gzsmtp2 (Coremail) with SMTP id PSgvCgD3X_Sqa6xnpUjUHQ--.30734S2; Wed, 12 Feb 2025 17:36:45 +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 v14 13/13] drm/rockchip: vop2: Add support for rk3576 Date: Wed, 12 Feb 2025 17:36:38 +0800 Message-ID: <20250212093641.53081-1-andyshrk@163.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250212093530.52961-1-andyshrk@163.com> References: <20250212093530.52961-1-andyshrk@163.com> MIME-Version: 1.0 X-CM-TRANSID: PSgvCgD3X_Sqa6xnpUjUHQ--.30734S2 X-Coremail-Antispam: 1Uf129KBjvAXoWDCFW3Jry5CFyDAw4UXw4ruFg_yoW7ZF1rWo W7CFnIvryxt34Sk395GrnrXryxWF4vkw4kur42yFy2k3y3X3y5Cr18t3ZFqF42yw43CFWr A34vq3WrZFWrZw1xn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UbIYCTnIWIevJa73UjIFyTuYvjxU2q2NDUUUU X-Originating-IP: [58.22.7.114] X-CM-SenderInfo: 5dqg52xkunqiywtou0bp/1tbiqB-xXmesZw5YYAABsD X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250212_013712_487899_C50D4C64 X-CRM114-Status: GOOD ( 24.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 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 80a15288b805..fadf0fdbff2c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1281,6 +1281,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); @@ -1345,6 +1348,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); @@ -2143,6 +2151,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; @@ -2158,41 +2216,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; + } } } @@ -2666,6 +2726,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 da0846dfeb2a..08d9fda2fb31 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 { @@ -374,10 +391,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 @@ -397,6 +417,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 @@ -479,7 +548,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 @@ -530,6 +603,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 @@ -678,6 +754,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 bca4cba6ea5c..8f849a6d40bf 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