From patchwork Fri Apr 18 06:52:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bincai Liu X-Patchwork-Id: 14056903 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (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 EE1B1C369AB for ; Fri, 18 Apr 2025 06:53:34 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id F217010E40F; Fri, 18 Apr 2025 06:53:33 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=mediatek.com header.i=@mediatek.com header.b="MqFUuWsa"; dkim-atps=neutral Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1335010E415 for ; Fri, 18 Apr 2025 06:53:31 +0000 (UTC) X-UUID: d0e624181c2111f08eb9c36241bbb6fb-20250418 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=ZJZ9/2LTXaosBvqhgXGtFoXMiGALopKAYRwsPTF6+U8=; b=MqFUuWsah2GDZJUfO74lFA492zkmJ7rZins2i7ixMW5qF5BJMEn8JC9Uvel7ZGv1wh87qPe30NeCKAKa+SNNblLgo9L+9tflF5scaUB/X2W+DZmnYpne6cywKcx+S//OZd+zfhE6dDs2r+oYI6h8e0Ugf9JObin4pMimMBQ01oE=; X-CID-CACHE: Type:Local,Time:202504181451+08,HitQuantity:1 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.2.1, REQID:6649ec34-9e81-4dd4-b4e9-51793eaba10c, IP:0, UR L:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION:r elease,TS:0 X-CID-META: VersionHash:0ef645f, CLOUDID:705cc28d-f5b8-47d5-8cf3-b68fe7530c9a, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:81|82|102,TC:nil,Content:0|50,EDM:-3 ,IP:nil,URL:0,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV :0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 0,NGT X-CID-BAS: 0,NGT,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: d0e624181c2111f08eb9c36241bbb6fb-20250418 Received: from mtkmbs11n1.mediatek.inc [(172.21.101.185)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1439583621; Fri, 18 Apr 2025 14:53:21 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by mtkmbs10n1.mediatek.inc (172.21.101.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.39; Fri, 18 Apr 2025 14:53:19 +0800 Received: from mszsdhlt06.gcn.mediatek.inc (10.16.6.206) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1258.39 via Frontend Transport; Fri, 18 Apr 2025 14:53:19 +0800 From: Bincai Liu To: Chun-Kuang Hu , Philipp Zabel , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Chunfeng Yun , Vinod Koul , "Kishon Vijay Abraham I" , Jitao shi , CK Hu CC: , , , , , , Bincai Liu Subject: [PATCH 1/5] dt-bindings: eDP: mediatek: add eDP yaml for mt8196 Date: Fri, 18 Apr 2025 14:52:28 +0800 Message-ID: <20250418065313.8972-2-bincai.liu@mediatek.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250418065313.8972-1-bincai.liu@mediatek.com> References: <20250418065313.8972-1-bincai.liu@mediatek.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Add compatible string to support eDP for MT8196. Signed-off-by: Bincai Liu --- .../devicetree/bindings/display/mediatek/mediatek,dp.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml index 75ce92f4a5fd..26997feba66b 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml @@ -25,6 +25,7 @@ properties: - mediatek,mt8188-edp-tx - mediatek,mt8195-dp-tx - mediatek,mt8195-edp-tx + - mediatek,mt8196-edp-tx reg: maxItems: 1 @@ -98,6 +99,7 @@ allOf: enum: - mediatek,mt8188-dp-tx - mediatek,mt8195-dp-tx + - mediatek,mt8196-edp-tx then: properties: '#sound-dai-cells': false From patchwork Fri Apr 18 06:52:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bincai Liu X-Patchwork-Id: 14056902 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (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 83820C369AB for ; Fri, 18 Apr 2025 06:53:32 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id BDE3F10E40C; Fri, 18 Apr 2025 06:53:31 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=mediatek.com header.i=@mediatek.com header.b="DVghYwPv"; dkim-atps=neutral Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) by gabe.freedesktop.org (Postfix) with ESMTPS id C7C6A10E40C for ; Fri, 18 Apr 2025 06:53:28 +0000 (UTC) X-UUID: d15755c01c2111f0aae1fd9735fae912-20250418 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=5vHbr3GvKAc++MOqadyX5zM/RrrbLBRixCrpAU1xBxg=; b=DVghYwPv6s4ErKT3eyWtCWkHvfodbA5z+ISsSopyC7v7KtzbKXgaMr6I+lchnryg9vyxz4x3yNmVJTgFtsgGNk9U3ZB2Yz7+rVSQiKoBSTrYBaKJeIvi/qVU9UQxAbwYjTrbu/lxdmYXyR41GGWCq9HSswmdIB1/eRwcxJe5Awc=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.2.1, REQID:5b3f398e-e7b3-48b7-9dfa-6763e30e36da, IP:0, UR L:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION:r elease,TS:0 X-CID-META: VersionHash:0ef645f, CLOUDID:5399b9c7-16da-468a-87f7-8ca8d6b3b9f7, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:81|82|102,TC:nil,Content:0|50,EDM:-3 ,IP:nil,URL:0,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV :0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 0,NGT X-CID-BAS: 0,NGT,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: d15755c01c2111f0aae1fd9735fae912-20250418 Received: from mtkmbs09n2.mediatek.inc [(172.21.101.94)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1325768179; Fri, 18 Apr 2025 14:53:22 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by MTKMBS14N1.mediatek.inc (172.21.101.75) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.39; Fri, 18 Apr 2025 14:53:20 +0800 Received: from mszsdhlt06.gcn.mediatek.inc (10.16.6.206) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1258.39 via Frontend Transport; Fri, 18 Apr 2025 14:53:20 +0800 From: Bincai Liu To: Chun-Kuang Hu , Philipp Zabel , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Chunfeng Yun , Vinod Koul , Kishon Vijay Abraham I , Jitao shi , CK Hu CC: , , , , , , Bincai Liu Subject: [PATCH 2/5] dt-bindings: dvo: mediatek: add dvo yaml for mt8196 Date: Fri, 18 Apr 2025 14:52:29 +0800 Message-ID: <20250418065313.8972-3-bincai.liu@mediatek.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250418065313.8972-1-bincai.liu@mediatek.com> References: <20250418065313.8972-1-bincai.liu@mediatek.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Add compatible string to support dvo for MT8196. Signed-off-by: Bincai Liu --- .../devicetree/bindings/display/mediatek/mediatek,dpi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml index b659d79393a8..4f897f05cb36 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml @@ -28,6 +28,7 @@ properties: - mediatek,mt8192-dpi - mediatek,mt8195-dp-intf - mediatek,mt8195-dpi + - mediatek,mt8196-edp-dvo - items: - enum: - mediatek,mt6795-dpi From patchwork Fri Apr 18 06:52:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bincai Liu X-Patchwork-Id: 14056906 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (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 2E442C369AB for ; Fri, 18 Apr 2025 06:53:41 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8BCFD10E410; Fri, 18 Apr 2025 06:53:40 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=mediatek.com header.i=@mediatek.com header.b="HPm63S7I"; dkim-atps=neutral Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1329910E414 for ; Fri, 18 Apr 2025 06:53:31 +0000 (UTC) X-UUID: d1fa7c821c2111f08eb9c36241bbb6fb-20250418 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=0kRc9HnVrI7LEoY76FPHw3pyLR0p0iDW2wjxGdQrlbE=; b=HPm63S7IZcu0Ljx04oT/aArQ4WrN6dUvPMF7fZCfpN6FNDGXRKw5nvfc1jY9A1qdsE/ikF5cCzycWrk7BGofYv2xPDyGDs45q9zNiAlC84YnPwXduVgf2cn7yhEYJ9ypuKnsdBswzP6W2ZTDCjgzlP+xZHUgFdLc2tL2/bWzM20=; X-CID-CACHE: Type:Local,Time:202504181451+08,HitQuantity:1 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.2.1, REQID:519b2ad4-c089-444b-bce7-438696761d9b, IP:0, UR L:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION:r elease,TS:0 X-CID-META: VersionHash:0ef645f, CLOUDID:3593b9c7-16da-468a-87f7-8ca8d6b3b9f7, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:81|82|102,TC:nil,Content:0|50,EDM:-3 ,IP:nil,URL:0,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV :0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 0,NGT X-CID-BAS: 0,NGT,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: d1fa7c821c2111f08eb9c36241bbb6fb-20250418 Received: from mtkmbs13n1.mediatek.inc [(172.21.101.193)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1305190930; Fri, 18 Apr 2025 14:53:23 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by MTKMBS14N1.mediatek.inc (172.21.101.75) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.39; Fri, 18 Apr 2025 14:53:21 +0800 Received: from mszsdhlt06.gcn.mediatek.inc (10.16.6.206) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1258.39 via Frontend Transport; Fri, 18 Apr 2025 14:53:20 +0800 From: Bincai Liu To: Chun-Kuang Hu , Philipp Zabel , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Chunfeng Yun , Vinod Koul , Kishon Vijay Abraham I , Jitao shi , CK Hu CC: , , , , , , Bincai Liu Subject: [PATCH 3/5] drm/mediatek: Add dvo driver for mt8196 Date: Fri, 18 Apr 2025 14:52:30 +0800 Message-ID: <20250418065313.8972-4-bincai.liu@mediatek.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250418065313.8972-1-bincai.liu@mediatek.com> References: <20250418065313.8972-1-bincai.liu@mediatek.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Add code to support dvo for mt8196. Signed-off-by: Bincai Liu --- drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 5 +- drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 1 + drivers/gpu/drm/mediatek/mtk_dpi.c | 240 ++++++++++++++++++++---- drivers/gpu/drm/mediatek/mtk_dpi_regs.h | 66 +++++++ drivers/gpu/drm/mediatek/mtk_drm_drv.c | 5 +- drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 + 6 files changed, 284 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c index edc6417639e6..7fbb9509fb0e 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c @@ -445,6 +445,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = { [MTK_DP_INTF] = "dp-intf", [MTK_DPI] = "dpi", [MTK_DSI] = "dsi", + [MTK_DVO] = "dvo", }; struct mtk_ddp_comp_match { @@ -472,6 +473,7 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX] [DDP_COMPONENT_DSI1] = { MTK_DSI, 1, &ddp_dsi }, [DDP_COMPONENT_DSI2] = { MTK_DSI, 2, &ddp_dsi }, [DDP_COMPONENT_DSI3] = { MTK_DSI, 3, &ddp_dsi }, + [DDP_COMPONENT_DVO0] = { MTK_DVO, 0, &ddp_dpi }, [DDP_COMPONENT_GAMMA] = { MTK_DISP_GAMMA, 0, &ddp_gamma }, [DDP_COMPONENT_MERGE0] = { MTK_DISP_MERGE, 0, &ddp_merge }, [DDP_COMPONENT_MERGE1] = { MTK_DISP_MERGE, 1, &ddp_merge }, @@ -662,7 +664,8 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp, type == MTK_DISP_RDMA || type == MTK_DPI || type == MTK_DP_INTF || - type == MTK_DSI) + type == MTK_DSI || + type == MTK_DVO) return 0; priv = devm_kzalloc(comp->dev, sizeof(*priv), GFP_KERNEL); diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h index 39720b27f4e9..daa98a594acb 100644 --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h @@ -43,6 +43,7 @@ enum mtk_ddp_comp_type { MTK_DPI, MTK_DP_INTF, MTK_DSI, + MTK_DVO, MTK_DDP_COMP_TYPE_MAX, }; diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index 0f3b1ef8e497..98d385905a0e 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -62,6 +62,29 @@ enum mtk_dpi_out_color_format { MTK_DPI_COLOR_FORMAT_YCBCR_422 }; +enum mtk_dpi_golden_setting_level { + MTK_DPI_FHD_60FPS_1920 = 0, + MTK_DPI_FHD_60FPS_2180, + MTK_DPI_FHD_60FPS_2400, + MTK_DPI_FHD_60FPS_2520, + MTK_DPI_FHD_90FPS, + MTK_DPI_FHD_120FPS, + MTK_DPI_WQHD_60FPS, + MTK_DPI_WQHD_120FPS, + MTK_DPI_8K_30FPS, + MTK_DPI_GSL_MAX, +}; + +enum mtk_dpi_type { + MTK_DISP_DPI = 0, + MTK_DSIP_DVO, +}; + +struct mtk_dpi_gs_info { + u32 dpi_buf_sodi_high; + u32 dpi_buf_sodi_low; +}; + struct mtk_dpi { struct drm_encoder encoder; struct drm_bridge bridge; @@ -73,6 +96,7 @@ struct mtk_dpi { struct clk *engine_clk; struct clk *pixel_clk; struct clk *tvd_clk; + struct clk *hf_fdpi_clk; int irq; struct drm_display_mode mode; const struct mtk_dpi_conf *conf; @@ -85,6 +109,7 @@ struct mtk_dpi { struct pinctrl_state *pins_dpi; u32 output_fmt; int refcount; + enum mtk_dpi_golden_setting_level gs_level; }; static inline struct mtk_dpi *bridge_to_dpi(struct drm_bridge *b) @@ -171,6 +196,13 @@ struct mtk_dpi_conf { bool edge_cfg_in_mmsys; bool clocked_by_hdmi; bool output_1pixel; + u32 out_np_sel; + u8 dpi_ver; +}; + +static struct mtk_dpi_gs_info mtk_dpi_gs[MTK_DPI_GSL_MAX] = { + [MTK_DPI_FHD_60FPS_1920] = {6880, 511}, + [MTK_DPI_8K_30FPS] = {5255, 3899}, }; static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask) @@ -208,6 +240,86 @@ static void mtk_dpi_disable(struct mtk_dpi *dpi) mtk_dpi_mask(dpi, DPI_EN, 0, EN); } +static void mtk_dpi_irq_enable(struct mtk_dpi *dpi) +{ + mtk_dpi_mask(dpi, DPI_INTEN, INT_VDE_END_EN, INT_VDE_END_EN); +} + +static void mtk_dpi_info_queue_start(struct mtk_dpi *dpi) +{ + mtk_dpi_mask(dpi, DPI_TGEN_INFOQ_LATENCY, 0, + INFOQ_START_LATENCY_MASK | INFOQ_END_LATENCY_MASK); +} + +static void mtk_dpi_buffer_ctrl(struct mtk_dpi *dpi) +{ + mtk_dpi_mask(dpi, DPI_BUF_CON0, DISP_BUF_EN, DISP_BUF_EN); + mtk_dpi_mask(dpi, DPI_BUF_CON0, FIFO_UNDERFLOW_DONE_BLOCK, FIFO_UNDERFLOW_DONE_BLOCK); +} + +static void mtk_dpi_trailing_blank_setting(struct mtk_dpi *dpi) +{ + mtk_dpi_mask(dpi, DPI_TGEN_V_LAST_TRAILING_BLANK, 0x20, V_LAST_TRAILING_BLANK_MASK); + mtk_dpi_mask(dpi, DPI_TGEN_OUTPUT_DELAY_LINE, 0x20, EXT_TG_DLY_LINE_MASK); +} + +static void mtk_dpi_get_gs_level(struct mtk_dpi *dpi) +{ + struct drm_display_mode *mode = &dpi->mode; + enum mtk_dpi_golden_setting_level *gsl = &dpi->gs_level; + + if (mode->hdisplay == 1920 && mode->vdisplay == 1080) + *gsl = MTK_DPI_FHD_60FPS_1920; + else + *gsl = MTK_DPI_8K_30FPS; +} + +static void mtk_dpi_golden_setting(struct mtk_dpi *dpi) +{ + struct mtk_dpi_gs_info *gs_info = NULL; + + if (dpi->gs_level >= MTK_DPI_GSL_MAX) { + dev_info(dpi->dev, "%s invalid gs_level %d\n", + __func__, dpi->gs_level); + return; + } + + gs_info = &mtk_dpi_gs[dpi->gs_level]; + + mtk_dpi_mask(dpi, DPI_BUF_SODI_HIGHT, gs_info->dpi_buf_sodi_high, GENMASK(31, 0)); + mtk_dpi_mask(dpi, DPI_BUF_SODI_LOW, gs_info->dpi_buf_sodi_low, GENMASK(31, 0)); +} + +static void mtk_dpi_shadow_ctrl(struct mtk_dpi *dpi) +{ + mtk_dpi_mask(dpi, DPI_SHADOW_CTRL, 0, BYPASS_SHADOW); + mtk_dpi_mask(dpi, DPI_SHADOW_CTRL, FORCE_COMMIT, FORCE_COMMIT); +} + +static void mtk_dpi_config_timing(struct mtk_dpi *dpi, + struct mtk_dpi_sync_param *hsync, + struct mtk_dpi_sync_param *vsync) +{ + mtk_dpi_mask(dpi, DPI_TGEN_H0, + hsync->sync_width << HSYNC, + dpi->conf->dimension_mask << HSYNC); + mtk_dpi_mask(dpi, DPI_TGEN_H0, + hsync->front_porch << DPI_HFP, + dpi->conf->dimension_mask << DPI_HFP); + mtk_dpi_mask(dpi, DPI_TGEN_H1, + (hsync->back_porch + hsync->sync_width) << HSYNC2ACT, + dpi->conf->dimension_mask << HSYNC2ACT); + mtk_dpi_mask(dpi, DPI_TGEN_V0, + vsync->sync_width << VSYNC, + dpi->conf->dimension_mask << VSYNC); + mtk_dpi_mask(dpi, DPI_TGEN_V0, + vsync->front_porch << VFP, + dpi->conf->dimension_mask << VFP); + mtk_dpi_mask(dpi, DPI_TGEN_V1, + (vsync->back_porch + vsync->sync_width) << VSYNC2ACT, + dpi->conf->dimension_mask << VSYNC2ACT); +} + static void mtk_dpi_config_hsync(struct mtk_dpi *dpi, struct mtk_dpi_sync_param *sync) { @@ -296,10 +408,27 @@ static void mtk_dpi_config_interface(struct mtk_dpi *dpi, bool inter) static void mtk_dpi_config_fb_size(struct mtk_dpi *dpi, u32 width, u32 height) { - mtk_dpi_mask(dpi, DPI_SIZE, width << HSIZE, - dpi->conf->hvsize_mask << HSIZE); - mtk_dpi_mask(dpi, DPI_SIZE, height << VSIZE, - dpi->conf->hvsize_mask << VSIZE); + if (dpi->conf->dpi_ver == MTK_DSIP_DVO) { + mtk_dpi_mask(dpi, DPI_SRC_SIZE, width << SRC_HSIZE, + dpi->conf->hvsize_mask << SRC_HSIZE); + mtk_dpi_mask(dpi, DPI_SRC_SIZE, height << SRC_VSIZE, + dpi->conf->hvsize_mask << SRC_VSIZE); + + mtk_dpi_mask(dpi, DPI_PIC_SIZE, width << PIC_HSIZE, + dpi->conf->hvsize_mask << PIC_HSIZE); + mtk_dpi_mask(dpi, DPI_PIC_SIZE, height << PIC_VSIZE, + dpi->conf->hvsize_mask << PIC_VSIZE); + + mtk_dpi_mask(dpi, DPI_TGEN_H1, (width / dpi->conf->pixels_per_iter) << HACT, + dpi->conf->hvsize_mask << HACT); + mtk_dpi_mask(dpi, DPI_TGEN_V1, height << VACT, + dpi->conf->hvsize_mask << VACT); + } else { + mtk_dpi_mask(dpi, DPI_SIZE, width << HSIZE, + dpi->conf->hvsize_mask << HSIZE); + mtk_dpi_mask(dpi, DPI_SIZE, height << VSIZE, + dpi->conf->hvsize_mask << VSIZE); + } } static void mtk_dpi_config_channel_limit(struct mtk_dpi *dpi) @@ -501,6 +630,7 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi) clk_disable_unprepare(dpi->pixel_clk); clk_disable_unprepare(dpi->tvd_clk); clk_disable_unprepare(dpi->engine_clk); + clk_disable_unprepare(dpi->hf_fdpi_clk); } static int mtk_dpi_power_on(struct mtk_dpi *dpi) @@ -528,8 +658,16 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) goto err_pixel; } + ret = clk_prepare_enable(dpi->hf_fdpi_clk); + if (ret) { + dev_err(dpi->dev, "Failed to enable hf_fdpi_clk clock: %d\n", ret); + goto err_hf_fdpi_clk; + } + return 0; +err_hf_fdpi_clk: + clk_disable_unprepare(dpi->hf_fdpi_clk); err_pixel: clk_disable_unprepare(dpi->tvd_clk); err_engine: @@ -610,7 +748,6 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING; dpi_pol.vsync_pol = vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ? MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING; - /* * Depending on the IP version, we may output a different amount of * pixels for each iteration: divide the clock by this number and @@ -643,14 +780,18 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, } mtk_dpi_sw_reset(dpi, true); mtk_dpi_config_pol(dpi, &dpi_pol); + if (dpi->conf->dpi_ver == MTK_DSIP_DVO) { + mtk_dpi_irq_enable(dpi); + mtk_dpi_config_timing(dpi, &hsync, &vsync_lodd); + } else { + mtk_dpi_config_hsync(dpi, &hsync); + mtk_dpi_config_vsync_lodd(dpi, &vsync_lodd); + mtk_dpi_config_vsync_rodd(dpi, &vsync_rodd); + mtk_dpi_config_vsync_leven(dpi, &vsync_leven); + mtk_dpi_config_vsync_reven(dpi, &vsync_reven); + mtk_dpi_config_3d(dpi, !!(mode->flags & DRM_MODE_FLAG_3D_MASK)); + } - mtk_dpi_config_hsync(dpi, &hsync); - mtk_dpi_config_vsync_lodd(dpi, &vsync_lodd); - mtk_dpi_config_vsync_rodd(dpi, &vsync_rodd); - mtk_dpi_config_vsync_leven(dpi, &vsync_leven); - mtk_dpi_config_vsync_reven(dpi, &vsync_reven); - - mtk_dpi_config_3d(dpi, !!(mode->flags & DRM_MODE_FLAG_3D_MASK)); mtk_dpi_config_interface(dpi, !!(vm.flags & DISPLAY_FLAGS_INTERLACED)); if (vm.flags & DISPLAY_FLAGS_INTERLACED) @@ -658,26 +799,41 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, else mtk_dpi_config_fb_size(dpi, vm.hactive, vm.vactive); - mtk_dpi_config_channel_limit(dpi); - mtk_dpi_config_bit_num(dpi, dpi->bit_num); - mtk_dpi_config_channel_swap(dpi, dpi->channel_swap); - mtk_dpi_config_color_format(dpi, dpi->color_format); - if (dpi->conf->support_direct_pin) { - mtk_dpi_config_yc_map(dpi, dpi->yc_map); - mtk_dpi_config_2n_h_fre(dpi); - - /* DPI can connect to either an external bridge or the internal HDMI encoder */ - if (dpi->conf->output_1pixel) - mtk_dpi_mask(dpi, DPI_CON, DPI_OUTPUT_1T1P_EN, DPI_OUTPUT_1T1P_EN); - else - mtk_dpi_dual_edge(dpi); - - mtk_dpi_config_disable_edge(dpi); - } - if (dpi->conf->input_2p_en_bit) { - mtk_dpi_mask(dpi, DPI_CON, dpi->conf->input_2p_en_bit, - dpi->conf->input_2p_en_bit); + if (dpi->conf->dpi_ver == MTK_DSIP_DVO) { + mtk_dpi_info_queue_start(dpi); + mtk_dpi_buffer_ctrl(dpi); + mtk_dpi_trailing_blank_setting(dpi); + mtk_dpi_get_gs_level(dpi); + mtk_dpi_golden_setting(dpi); + mtk_dpi_shadow_ctrl(dpi); + mtk_dpi_mask(dpi, DPI_OUTPUT_SET, dpi->conf->out_np_sel, OUT_NP_SEL); + } else { + mtk_dpi_config_channel_limit(dpi); + mtk_dpi_config_bit_num(dpi, dpi->bit_num); + mtk_dpi_config_channel_swap(dpi, dpi->channel_swap); + mtk_dpi_config_color_format(dpi, dpi->color_format); + if (dpi->conf->support_direct_pin) { + mtk_dpi_config_yc_map(dpi, dpi->yc_map); + mtk_dpi_config_2n_h_fre(dpi); + + /* + * DPI can connect to either an external bridge + * or the internal HDMI encoder + */ + if (dpi->conf->output_1pixel) + mtk_dpi_mask(dpi, DPI_CON, + DPI_OUTPUT_1T1P_EN, DPI_OUTPUT_1T1P_EN); + else + mtk_dpi_dual_edge(dpi); + + mtk_dpi_config_disable_edge(dpi); + } + if (dpi->conf->input_2p_en_bit) { + mtk_dpi_mask(dpi, DPI_CON, dpi->conf->input_2p_en_bit, + dpi->conf->input_2p_en_bit); + } } + mtk_dpi_sw_reset(dpi, false); return 0; @@ -700,7 +856,7 @@ static u32 *mtk_dpi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, } output_fmts = kcalloc(dpi->conf->num_output_fmts, sizeof(*output_fmts), - GFP_KERNEL); + GFP_KERNEL); if (!output_fmts) return NULL; @@ -1173,6 +1329,20 @@ static const struct mtk_dpi_conf mt8195_dpintf_conf = { .input_2p_en_bit = DPINTF_INPUT_2P_EN, }; +static const struct mtk_dpi_conf mt8196_conf = { + .dpi_factor = dpi_factor_mt8195_dp_intf, + .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8195_dp_intf), + .out_np_sel = 0x2, + .reg_h_fre_con = 0xb0, + .max_clock_khz = 1330000, + .output_fmts = mt8195_output_fmts, + .num_output_fmts = ARRAY_SIZE(mt8195_output_fmts), + .pixels_per_iter = 4, + .dimension_mask = DPINTF_HPW_MASK, + .hvsize_mask = PIC_HSIZE_MASK, + .dpi_ver = MTK_DSIP_DVO, +}; + static int mtk_dpi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1227,6 +1397,11 @@ static int mtk_dpi_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(dpi->tvd_clk), "Failed to get tvdpll clock\n"); + dpi->hf_fdpi_clk = devm_clk_get_optional(dev, "hf_fdvo_clk"); + if (IS_ERR(dpi->hf_fdpi_clk)) + return dev_err_probe(dev, PTR_ERR(dpi->hf_fdpi_clk), + "Failed to get hf_fdpi_clk clock\n"); + dpi->irq = platform_get_irq(pdev, 0); if (dpi->irq < 0) return dpi->irq; @@ -1262,6 +1437,7 @@ static const struct of_device_id mtk_dpi_of_ids[] = { { .compatible = "mediatek,mt8192-dpi", .data = &mt8192_conf }, { .compatible = "mediatek,mt8195-dp-intf", .data = &mt8195_dpintf_conf }, { .compatible = "mediatek,mt8195-dpi", .data = &mt8195_conf }, + { .compatible = "mediatek,mt8196-edp-dvo", .data = &mt8196_conf }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, mtk_dpi_of_ids); diff --git a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h index 23eeefce8fd2..3e2a64c2bca0 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h +++ b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h @@ -16,6 +16,7 @@ #define INT_VSYNC_EN BIT(0) #define INT_VDE_EN BIT(1) #define INT_UNDERFLOW_EN BIT(2) +#define INT_VDE_END_EN BIT(4) #define DPI_INTSTA 0x0C #define INT_VSYNC_STA BIT(0) @@ -240,6 +241,71 @@ #define MATRIX_SEL_RGB_TO_JPEG 0 #define MATRIX_SEL_RGB_TO_BT601 2 +#define DPI_TGEN_INFOQ_LATENCY 0x80 +#define INFOQ_START_LATENCY 0 +#define INFOQ_START_LATENCY_MASK (0xffff << 0) +#define INFOQ_END_LATENCY 16 +#define INFOQ_END_LATENCY_MASK (0xffff << 16) + +#define DPI_BUF_CON0 0x220 +#define DISP_BUF_EN BIT(0) +#define FIFO_UNDERFLOW_DONE_BLOCK BIT(4) + +#define DPI_TGEN_V_LAST_TRAILING_BLANK 0x6c +#define V_LAST_TRAILING_BLANK 0 +#define V_LAST_TRAILING_BLANK_MASK (0xffff << 0) + +#define DPI_TGEN_OUTPUT_DELAY_LINE 0x7c +#define EXT_TG_DLY_LINE 0 +#define EXT_TG_DLY_LINE_MASK (0xffff << 0) + +#define DPI_SHADOW_CTRL 0x190 +#define FORCE_COMMIT BIT(0) +#define BYPASS_SHADOW BIT(1) +#define READ_WRK_REG BIT(2) + +#define DPI_BUF_SODI_HIGHT 0x230 +#define DPI_BUF_SODI_LOW 0x234 + +#define DPI_OUTPUT_SET 0x18 +#define OUT_NP_SEL (0x3 << 0) + +#define DPI_SRC_SIZE 0x20 +#define SRC_HSIZE 0 +#define SRC_HSIZE_MASK (0xffff << 0) +#define SRC_VSIZE 16 +#define SRC_VSIZE_MASK (0xffff << 16) + +#define DPI_PIC_SIZE 0x24 +#define PIC_HSIZE 0 +#define PIC_HSIZE_MASK (0xffff << 0) +#define PIC_VSIZE 16 +#define PIC_VSIZE_MASK (0xffff << 16) + +#define DPI_TGEN_H0 0x50 +#define DPI_HFP 0 +#define DPI_HFP_MASK (0xffff << 0) +#define HSYNC 16 +#define HSYNC_MASK (0xffff << 16) + +#define DPI_TGEN_H1 0x54 +#define HSYNC2ACT 0 +#define HSYNC2ACT_MASK (0xffff << 0) +#define HACT 16 +#define HACT_MASK (0xffff << 16) + +#define DPI_TGEN_V0 0x58 +#define VFP 0 +#define VFP_MASK (0xffff << 0) +#define VSYNC 16 +#define VSYNC_MASK (0xffff << 16) + +#define DPI_TGEN_V1 0x5c +#define VSYNC2ACT 0 +#define VSYNC2ACT_MASK (0xffff << 0) +#define VACT 16 +#define VACT_MASK (0xffff << 16) + #define DPI_PATTERN0 0xf00 #define DPI_PAT_EN BIT(0) #define DPI_PAT_SEL GENMASK(6, 4) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 74158b9d6503..870d97c023ed 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -830,6 +830,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = { .data = (void *)MTK_DSI }, { .compatible = "mediatek,mt8188-dsi", .data = (void *)MTK_DSI }, + { .compatible = "mediatek,mt8196-edp-dvo", + .data = (void *)MTK_DVO }, { } }; @@ -1176,7 +1178,8 @@ static int mtk_drm_probe(struct platform_device *pdev) comp_type == MTK_DISP_RDMA || comp_type == MTK_DP_INTF || comp_type == MTK_DPI || - comp_type == MTK_DSI) { + comp_type == MTK_DSI || + comp_type == MTK_DVO) { dev_info(dev, "Adding component match for %pOF\n", node); drm_of_component_match_add(dev, &match, component_compare_of, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h index 675cdc90a440..6d2796148813 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h @@ -79,6 +79,7 @@ extern struct platform_driver mtk_disp_ovl_driver; extern struct platform_driver mtk_disp_rdma_driver; extern struct platform_driver mtk_dpi_driver; extern struct platform_driver mtk_dsi_driver; +extern struct platform_driver mtk_dvo_driver; extern struct platform_driver mtk_ethdr_driver; extern struct platform_driver mtk_mdp_rdma_driver; extern struct platform_driver mtk_padding_driver; From patchwork Fri Apr 18 06:52:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bincai Liu X-Patchwork-Id: 14056905 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (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 F3184C369CF for ; Fri, 18 Apr 2025 06:53:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EAE7110E415; Fri, 18 Apr 2025 06:53:34 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=mediatek.com header.i=@mediatek.com header.b="S00/9365"; dkim-atps=neutral Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1258510E40F for ; Fri, 18 Apr 2025 06:53:31 +0000 (UTC) X-UUID: d23d4bfc1c2111f08eb9c36241bbb6fb-20250418 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=Hb2ki2Eohwz2X+4gaKY62ZizM+ccBdN4ZlDffGYg7mI=; b=S00/9365VNBRMfgtRESUJbZNEA30e2S/sIHlbzyJfKvutpHk8urkB0tCC8Lw2+lE9dnCvew+S47gw1OS20SbM4ekkciFwT4qTYqnHlwx0e4y1IoQlgjilaE/75y/X2ifHgSbFcq0H99di4BbFZUSO+ZfDPzligdnBOrHfFk9OeY=; X-CID-CACHE: Type:Local,Time:202504181451+08,HitQuantity:1 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.2.1, REQID:5db99941-562b-441a-89ad-5f7f4b2f2854, IP:0, UR L:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION:r elease,TS:0 X-CID-META: VersionHash:0ef645f, CLOUDID:0f823aa6-c619-47e3-a41b-90eedbf5b947, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:81|82|102,TC:nil,Content:0|50,EDM:-3 ,IP:nil,URL:0,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV :0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 0,NGT X-CID-BAS: 0,NGT,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: d23d4bfc1c2111f08eb9c36241bbb6fb-20250418 Received: from mtkmbs13n1.mediatek.inc [(172.21.101.193)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 148071058; Fri, 18 Apr 2025 14:53:23 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by mtkmbs13n1.mediatek.inc (172.21.101.193) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.39; Fri, 18 Apr 2025 14:53:22 +0800 Received: from mszsdhlt06.gcn.mediatek.inc (10.16.6.206) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1258.39 via Frontend Transport; Fri, 18 Apr 2025 14:53:21 +0800 From: Bincai Liu To: Chun-Kuang Hu , Philipp Zabel , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Chunfeng Yun , Vinod Koul , Kishon Vijay Abraham I , Jitao shi , CK Hu CC: , , , , , , Bincai Liu Subject: [PATCH 4/5] drm/mediatek: Add eDP driver for mt8196 Date: Fri, 18 Apr 2025 14:52:31 +0800 Message-ID: <20250418065313.8972-5-bincai.liu@mediatek.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250418065313.8972-1-bincai.liu@mediatek.com> References: <20250418065313.8972-1-bincai.liu@mediatek.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Add code to support eDP 1.4 driver for mt8196. Signed-off-by: Bincai Liu --- drivers/gpu/drm/mediatek/mtk_dp.c | 484 ++++++++++++++++++++++---- drivers/gpu/drm/mediatek/mtk_dp_reg.h | 126 +++++++ 2 files changed, 550 insertions(+), 60 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index b2408abb9d49..159ab5ebb9d2 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -35,6 +35,9 @@ #include "mtk_dp_reg.h" +#define EDP_VIDEO_UNMUTE 0x22 +#define EDP_VIDEO_UNMUTE_VAL 0xfefd +#define MTK_SIP_DP_CONTROL (0x82000523 | 0x40000000) #define MTK_DP_SIP_CONTROL_AARCH32 MTK_SIP_SMC_CMD(0x523) #define MTK_DP_SIP_ATF_EDP_VIDEO_UNMUTE (BIT(0) | BIT(5)) #define MTK_DP_SIP_ATF_VIDEO_UNMUTE BIT(5) @@ -51,6 +54,7 @@ #define MTK_DP_TRAIN_DOWNSCALE_RETRY 10 #define MTK_DP_VERSION 0x11 #define MTK_DP_SDP_AUI 0x4 +#define EDP_REINIT_TIMES 4 enum { MTK_DP_CAL_GLB_BIAS_TRIM = 0, @@ -102,6 +106,7 @@ struct mtk_dp { bool enabled; bool need_debounce; int irq; + int swing_value; u8 max_lanes; u8 max_linkrate; u8 rx_cap[DP_RECEIVER_CAP_SIZE]; @@ -110,6 +115,8 @@ struct mtk_dp { /* irq_thread_lock is used to protect irq_thread_handle */ spinlock_t irq_thread_lock; + struct clk *power_clk; + struct device *dev; struct drm_bridge bridge; struct drm_bridge *next_bridge; @@ -124,6 +131,7 @@ struct mtk_dp { struct platform_device *phy_dev; struct phy *phy; struct regmap *regs; + struct regmap *phy_regs; struct timer_list debounce_timer; /* For audio */ @@ -134,6 +142,9 @@ struct mtk_dp { struct device *codec_dev; /* protect the plugged_cb as it's used in both bridge ops and audio */ struct mutex update_plugged_status_lock; + /* For edp power control */ + void __iomem *pwr_regs; + u32 retry_times; }; struct mtk_dp_data { @@ -143,6 +154,7 @@ struct mtk_dp_data { bool audio_supported; bool audio_pkt_in_hblank_area; u16 audio_m_div2_bit; + u32 edp_ver; }; static const struct mtk_dp_efuse_fmt mt8188_dp_efuse_fmt[MTK_DP_CAL_MAX] = { @@ -402,6 +414,16 @@ static const struct regmap_config mtk_dp_regmap_config = { .name = "mtk-dp-registers", }; +static const struct regmap_config mtk_edp_phy_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = SEC_OFFSET + 0x90, + .name = "mtk-edp-phy-registers", +}; + +static int mtk_dp_poweron(struct mtk_dp *mtk_dp); + static struct mtk_dp *mtk_dp_from_bridge(struct drm_bridge *b) { return container_of(b, struct mtk_dp, bridge); @@ -459,6 +481,26 @@ static void mtk_dp_bulk_16bit_write(struct mtk_dp *mtk_dp, u32 offset, u8 *buf, } } +static void mtk_edp_pm_ctl(struct mtk_dp *mtk_dp, bool enable) +{ + /* DISP_EDPTX_PWR_CON udelay 10us to ensure that the power state is stable */ + udelay(10); + if (enable) { + /* Enable subsys clock, just set bit4 to 0 */ + writel(readl(mtk_dp->pwr_regs) & ~DISP_EDPTX_PWR_CLK_DIS, mtk_dp->pwr_regs); + udelay(1); + /* Subsys power-on reset, firstly set bit0 to 0 and then set bit0 to 1 */ + writel(readl(mtk_dp->pwr_regs) & ~DISP_EDPTX_PWR_RST_B, mtk_dp->pwr_regs); + udelay(1); + writel(readl(mtk_dp->pwr_regs) | DISP_EDPTX_PWR_RST_B, mtk_dp->pwr_regs); + } else { + writel(readl(mtk_dp->pwr_regs) & ~DISP_EDPTX_PWR_RST_B, mtk_dp->pwr_regs); + udelay(1); + writel(readl(mtk_dp->pwr_regs) | DISP_EDPTX_PWR_CLK_DIS, mtk_dp->pwr_regs); + } + udelay(10); +} + static void mtk_dp_msa_bypass_enable(struct mtk_dp *mtk_dp, bool enable) { u32 mask = HTOTAL_SEL_DP_ENC0_P0 | VTOTAL_SEL_DP_ENC0_P0 | @@ -514,9 +556,14 @@ static void mtk_dp_set_msa(struct mtk_dp *mtk_dp) mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_315C, vm->hsync_len, PGEN_HSYNC_PULSE_WIDTH_DP_ENC0_P0_MASK); - mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3160, - vm->hback_porch + vm->hsync_len, - PGEN_HFDE_START_DP_ENC0_P0_MASK); + if (mtk_dp->data->edp_ver) + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3160, + vm->hback_porch + vm->hsync_len + vm->hfront_porch, + PGEN_HFDE_START_DP_ENC0_P0_MASK); + else + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3160, + vm->hback_porch + vm->hsync_len, + PGEN_HFDE_START_DP_ENC0_P0_MASK); mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3164, vm->hactive, PGEN_HFDE_ACTIVE_WIDTH_DP_ENC0_P0_MASK); @@ -531,9 +578,14 @@ static void mtk_dp_set_msa(struct mtk_dp *mtk_dp) mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3170, vm->vsync_len, PGEN_VSYNC_PULSE_WIDTH_DP_ENC0_P0_MASK); - mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3174, - vm->vback_porch + vm->vsync_len, - PGEN_VFDE_START_DP_ENC0_P0_MASK); + if (mtk_dp->data->edp_ver) + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3174, + vm->vback_porch + vm->vsync_len + vm->vfront_porch, + PGEN_VFDE_START_DP_ENC0_P0_MASK); + else + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3174, + vm->vback_porch + vm->vsync_len, + PGEN_VFDE_START_DP_ENC0_P0_MASK); mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3178, vm->vactive, PGEN_VFDE_ACTIVE_WIDTH_DP_ENC0_P0_MASK); @@ -543,7 +595,7 @@ static int mtk_dp_set_color_format(struct mtk_dp *mtk_dp, enum dp_pixelformat color_format) { u32 val; - u32 misc0_color; + u32 misc0_color = 0; switch (color_format) { case DP_PIXELFORMAT_YUV422: @@ -554,6 +606,9 @@ static int mtk_dp_set_color_format(struct mtk_dp *mtk_dp, val = PIXEL_ENCODE_FORMAT_DP_ENC0_P0_RGB; misc0_color = DP_COLOR_FORMAT_RGB; break; + case DP_PIXELFORMAT_YUV420: + val = PIXEL_ENCODE_FORMAT_DP_ENC0_P0_YCBCR420; + break; default: drm_warn(mtk_dp->drm_dev, "Unsupported color format: %d\n", color_format); @@ -612,7 +667,8 @@ static void mtk_dp_setup_encoder(struct mtk_dp *mtk_dp) mtk_dp_update_bits(mtk_dp, MTK_DP_ENC1_P0_3364, FIFO_READ_START_POINT_DP_ENC1_P0_VAL << 12, FIFO_READ_START_POINT_DP_ENC1_P0_MASK); - mtk_dp_write(mtk_dp, MTK_DP_ENC1_P0_3368, DP_ENC1_P0_3368_VAL); + if (!mtk_dp->data->edp_ver) + mtk_dp_write(mtk_dp, MTK_DP_ENC1_P0_3368, DP_ENC1_P0_3368_VAL); } static void mtk_dp_pg_enable(struct mtk_dp *mtk_dp, bool enable) @@ -972,8 +1028,8 @@ static void mtk_dp_set_swing_pre_emphasis(struct mtk_dp *mtk_dp, int lane_num, u32 lane_shift = lane_num * DP_TX1_VOLT_SWING_SHIFT; dev_dbg(mtk_dp->dev, - "link training: swing_val = 0x%x, pre-emphasis = 0x%x\n", - swing_val, preemphasis); + "link training: swing_val = 0x%x, pre-emphasis = 0x%x lane_num = %d\n", + swing_val, preemphasis, lane_num); mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_SWING_EMP, swing_val << (DP_TX0_VOLT_SWING_SHIFT + lane_shift), @@ -981,6 +1037,28 @@ static void mtk_dp_set_swing_pre_emphasis(struct mtk_dp *mtk_dp, int lane_num, mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_SWING_EMP, preemphasis << (DP_TX0_PRE_EMPH_SHIFT + lane_shift), DP_TX0_PRE_EMPH_MASK << lane_shift); + if (mtk_dp->data->edp_ver && mtk_dp->phy_regs) { + /* set swing and pre */ + switch (lane_num) { + case 0: + case 1: + case 2: + case 3: + regmap_update_bits(mtk_dp->phy_regs, + PHYD_DIG_DRV_FORCE_LANE(lane_num), + EDP_TX_LN_VOLT_SWING_VAL_FLDMASK | + EDP_TX_LN_PRE_EMPH_VAL_FLDMASK, + swing_val << 1 | + preemphasis << 3); + break; + default: + break; + } + if (preemphasis != 0) + mtk_dp_update_bits(mtk_dp, RG_DSI_DEM_EN, + DSI_DE_EMPHASIS_ENABLE, + DSI_DE_EMPHASIS_ENABLE); + } } static void mtk_dp_reset_swing_pre_emphasis(struct mtk_dp *mtk_dp) @@ -1039,6 +1117,44 @@ static void mtk_dp_hwirq_enable(struct mtk_dp *mtk_dp, bool enable) static void mtk_dp_initialize_settings(struct mtk_dp *mtk_dp) { + if (mtk_dp->data->edp_ver) { + mtk_dp_update_bits(mtk_dp, REG_3F04_DP_ENC_P0_3, 0, + FRAME_START_MARKER_0_DP_ENC_P0_3_MASK); + mtk_dp_update_bits(mtk_dp, REG_3F08_DP_ENC_P0_3, + FRAME_START_MARKER_1_DP_ENC_P0_3, + FRAME_START_MARKER_1_DP_ENC_P0_3_MASK); + mtk_dp_update_bits(mtk_dp, REG_3F0C_DP_ENC_P0_3, + FRAME_END_MARKER_0_DP_ENC_P0_3, + FRAME_END_MARKER_0_DP_ENC_P0_3_MASK); + mtk_dp_update_bits(mtk_dp, REG_3F10_DP_ENC_P0_3, + FRAME_END_MARKER_1_DP_ENC_P0_3, + FRAME_END_MARKER_1_DP_ENC_P0_3_MASK); + + mtk_dp_update_bits(mtk_dp, REG_33C0_DP_ENCODER1_P0, 0, + SDP_TESTBUS_SEL_DP_ENC_MASK); + mtk_dp_update_bits(mtk_dp, REG_33C0_DP_ENCODER1_P0, + SDP_TESTBUS_SEL_BIT4_DP_ENC, + SDP_TESTBUS_SEL_BIT4_DP_ENC_MASK); + mtk_dp_update_bits(mtk_dp, REG_33C4_DP_ENCODER1_P0, + DP_TX_ENCODER_TESTBUS_SEL_DP_ENC, + DP_TX_ENCODER_TESTBUS_SEL_DP_ENC_MASK); + mtk_dp_update_bits(mtk_dp, REG_3F28_DP_ENC_P0_3, + DP_TX_SDP_PSR_AS_TESTBUS, + DP_TX_SDP_PSR_AS_TESTBUS_MASK); + mtk_dp_update_bits(mtk_dp, DP_TX_TOP_RESET_AND_PROBE, + RG_SW_RST, + RG_SW_RST_MASK); + mtk_dp_update_bits(mtk_dp, DP_TX_TOP_RESET_AND_PROBE, + RG_PROBE_LOW_SEL, + RG_PROBE_LOW_SEL_MASK); + mtk_dp_update_bits(mtk_dp, DP_TX_TOP_RESET_AND_PROBE, + RG_PROBE_LOW_HIGH_SWAP, + RG_PROBE_LOW_HIGH_SWAP_MASK); + + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_IRQ_MASK, + ENCODER_IRQ_MSK | TRANS_IRQ_MSK, + ENCODER_IRQ_MSK | TRANS_IRQ_MSK); + } mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_342C, XTAL_FREQ_DP_TRANS_P0_DEFAULT, XTAL_FREQ_DP_TRANS_P0_MASK); @@ -1057,27 +1173,34 @@ static void mtk_dp_initialize_settings(struct mtk_dp *mtk_dp) static void mtk_dp_initialize_hpd_detect_settings(struct mtk_dp *mtk_dp) { u32 val; - /* Debounce threshold */ - mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3410, - 8, HPD_DEB_THD_DP_TRANS_P0_MASK); - val = (HPD_INT_THD_DP_TRANS_P0_LOWER_500US | - HPD_INT_THD_DP_TRANS_P0_UPPER_1100US) << 4; - mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3410, - val, HPD_INT_THD_DP_TRANS_P0_MASK); + if (mtk_dp->data->edp_ver) { + mtk_dp_update_bits(mtk_dp, REG_364C_AUX_TX_P0, + HPD_INT_THD_FLDMASK_VAL << 4, + HPD_INT_THD_FLDMASK); + } else { + /* Debounce threshold */ + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3410, + 8, HPD_DEB_THD_DP_TRANS_P0_MASK); - /* - * Connect threshold 1.5ms + 5 x 0.1ms = 2ms - * Disconnect threshold 1.5ms + 5 x 0.1ms = 2ms - */ - val = (5 << 8) | (5 << 12); - mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3410, - val, - HPD_DISC_THD_DP_TRANS_P0_MASK | - HPD_CONN_THD_DP_TRANS_P0_MASK); - mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3430, - HPD_INT_THD_ECO_DP_TRANS_P0_HIGH_BOUND_EXT, - HPD_INT_THD_ECO_DP_TRANS_P0_MASK); + val = (HPD_INT_THD_DP_TRANS_P0_LOWER_500US | + HPD_INT_THD_DP_TRANS_P0_UPPER_1100US) << 4; + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3410, + val, HPD_INT_THD_DP_TRANS_P0_MASK); + + /* + * Connect threshold 1.5ms + 5 x 0.1ms = 2ms + * Disconnect threshold 1.5ms + 5 x 0.1ms = 2ms + */ + val = (5 << 8) | (5 << 12); + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3410, + val, + HPD_DISC_THD_DP_TRANS_P0_MASK | + HPD_CONN_THD_DP_TRANS_P0_MASK); + mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_3430, + HPD_INT_THD_ECO_DP_TRANS_P0_HIGH_BOUND_EXT, + HPD_INT_THD_ECO_DP_TRANS_P0_MASK); + } } static void mtk_dp_initialize_aux_settings(struct mtk_dp *mtk_dp) @@ -1088,6 +1211,10 @@ static void mtk_dp_initialize_aux_settings(struct mtk_dp *mtk_dp) AUX_TIMEOUT_THR_AUX_TX_P0_MASK); mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3658, 0, AUX_TX_OV_EN_AUX_TX_P0_MASK); + if (mtk_dp->data->edp_ver) + mtk_dp_update_bits(mtk_dp, REG_36A0_AUX_TX_P0, + DP_TX_INIT_MASK_15_TO_2, + DP_TX_INIT_MASK_15_TO_2_MASK); /* 25 for 26M */ mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3634, AUX_TX_OVER_SAMPLE_RATE_FOR_26M << 8, @@ -1104,6 +1231,46 @@ static void mtk_dp_initialize_aux_settings(struct mtk_dp *mtk_dp) mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3690, RX_REPLY_COMPLETE_MODE_AUX_TX_P0, RX_REPLY_COMPLETE_MODE_AUX_TX_P0); + + if (mtk_dp->data->edp_ver) { + /*Con Thd = 1.5ms+Vx0.1ms*/ + mtk_dp_update_bits(mtk_dp, REG_367C_AUX_TX_P0, + HPD_CONN_THD_AUX_TX_P0_FLDMASK_POS << 6, + HPD_CONN_THD_AUX_TX_P0_FLDMASK); + /*DisCon Thd = 1.5ms+Vx0.1ms*/ + mtk_dp_update_bits(mtk_dp, REG_37A0_AUX_TX_P0, + HPD_DISC_THD_AUX_TX_P0_FLDMASK_POS << 4, + HPD_DISC_THD_AUX_TX_P0_FLDMASK); + mtk_dp_update_bits(mtk_dp, REG_3FF8_DP_ENC_P0_3, + XTAL_FREQ_FOR_PSR_DP_ENC_P0_3_VALUE << 9, + XTAL_FREQ_FOR_PSR_DP_ENC_P0_3_MASK); + mtk_dp_update_bits(mtk_dp, REG_366C_AUX_TX_P0, + XTAL_FREQ_DP_TX_AUX_366C_VALUE << 8, + XTAL_FREQ_DP_TX_AUX_366C_MASK); + } +} + +static void mtk_edp_phyd_wait_aux_ldo_ready(struct mtk_dp *mtk_dp, + unsigned long wait_us) +{ + int ret = 0; + u32 val = 0x0; + u32 mask = RGS_BG_CORE_EN_READY | RGS_AUX_LDO_EN_READY; + + if (mtk_dp->phy_regs) { + ret = regmap_read_poll_timeout(mtk_dp->phy_regs, + DP_PHY_DIG_GLB_STATUS_0, + val, !!(val & mask), + wait_us / 100, wait_us); + } else { + ret = regmap_read_poll_timeout(mtk_dp->regs, + DP_PHY_DIG_GLB_STATUS_0, + val, !!(val & mask), + wait_us / 100, wait_us); + } + + if (ret) + dev_err(mtk_dp->dev, "%s AUX not ready\n", __func__); } static void mtk_dp_initialize_digital_settings(struct mtk_dp *mtk_dp) @@ -1115,15 +1282,63 @@ static void mtk_dp_initialize_digital_settings(struct mtk_dp *mtk_dp) BS2BS_MODE_DP_ENC1_P0_VAL << 12, BS2BS_MODE_DP_ENC1_P0_MASK); + if (mtk_dp->data->edp_ver) { + /* dp I-mode enable */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3000, + DP_I_MODE_ENABLE, DP_I_MODE_ENABLE); + /*symbol_cnt_reset */ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3000, + REG_BS_SYMBOL_CNT_RESET, + REG_BS_SYMBOL_CNT_RESET); + mtk_dp_update_bits(mtk_dp, REG_3368_DP_ENCODER1_P0, + VIDEO_SRAM_FIFO_CNT_RESET_SEL_VALUE, + VIDEO_SRAM_FIFO_CNT_RESET_SEL_MASK); + mtk_dp_update_bits(mtk_dp, REG_3368_DP_ENCODER1_P0, + BS_FOLLOW_SEL_DP_ENC0_P0, + BS_FOLLOW_SEL_DP_ENC0_P0); + /*[5:0]video sram start address*/ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_303C, + SRAM_START_READ_THRD_DP_ENC0_P0_VALUE, + SRAM_START_READ_THRD_DP_ENC0_P0_MASK); + /* reg_psr_patgen_avt_en disable psr pattern */ + mtk_dp_update_bits(mtk_dp, REG_3F80_DP_ENC_P0_3, + 0, PSR_PATGEN_AVT_EN_FLDMASK); + /* phy D enable */ + mtk_dp_update_bits(mtk_dp, REG_3F44_DP_ENC_P0_3, + PHY_PWR_STATE_OW_EN_DP_ENC_P0_3, + PHY_PWR_STATE_OW_EN_DP_ENC_P0_3_MASK); + mtk_dp_update_bits(mtk_dp, REG_3F44_DP_ENC_P0_3, + ALL_POWER_ON, + PHY_PWR_STATE_OW_VALUE_DP_ENC_P0_3_MASK); + mtk_edp_phyd_wait_aux_ldo_ready(mtk_dp, 100000); + mtk_dp_update_bits(mtk_dp, REG_3F44_DP_ENC_P0_3, + 0, PHY_PWR_STATE_OW_EN_DP_ENC_P0_3_MASK); + + mtk_dp_update_bits(mtk_dp, REG_3FF8_DP_ENC_P0_3, + PHY_STATE_W_1_DP_ENC_P0_3, + PHY_STATE_W_1_DP_ENC_P0_3_MASK); + /* reg_dvo_on_ow_en */ + mtk_dp_update_bits(mtk_dp, REG_3FF8_DP_ENC_P0_3, + DVO_ON_W_1_FLDMASK, + DVO_ON_W_1_FLDMASK); + } /* dp tx encoder reset all sw */ mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3004, DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0, DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0); + if (mtk_dp->data->edp_ver) { + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3004, 0, + DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0); + mtk_dp_update_bits(mtk_dp, REG_3FF8_DP_ENC_P0_3, + PHY_STATE_RESET_ALL_VALUE, + PHY_STATE_RESET_ALL_MASK); + } /* Wait for sw reset to complete */ usleep_range(1000, 5000); - mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3004, - 0, DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0); + if (!mtk_dp->data->edp_ver) + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3004, 0, + DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0); } static void mtk_dp_digital_sw_reset(struct mtk_dp *mtk_dp) @@ -1152,6 +1367,19 @@ static void mtk_dp_sdp_path_reset(struct mtk_dp *mtk_dp) static void mtk_dp_set_lanes(struct mtk_dp *mtk_dp, int lanes) { + if (mtk_dp->data->edp_ver) { + mtk_dp_update_bits(mtk_dp, REG_3F44_DP_ENC_P0_3, + PHY_PWR_STATE_OW_EN_DP_ENC_P0_3, + PHY_PWR_STATE_OW_EN_DP_ENC_P0_3_MASK); + mtk_dp_update_bits(mtk_dp, REG_3F44_DP_ENC_P0_3, + BIAS_POWER_ON, + PHY_PWR_STATE_OW_VALUE_DP_ENC_P0_3_MASK); + + mtk_edp_phyd_wait_aux_ldo_ready(mtk_dp, 100000); + + mtk_dp_update_bits(mtk_dp, REG_3F44_DP_ENC_P0_3, + 0, PHY_PWR_STATE_OW_EN_DP_ENC_P0_3_MASK); + } mtk_dp_update_bits(mtk_dp, MTK_DP_TRANS_P0_35F0, lanes == 0 ? 0 : DP_TRANS_DUMMY_RW_0, DP_TRANS_DUMMY_RW_0_MASK); @@ -1266,15 +1494,20 @@ static int mtk_dp_phy_configure(struct mtk_dp *mtk_dp, .ssc = mtk_dp->train_info.sink_ssc, } }; - - mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, DP_PWR_STATE_BANDGAP, - DP_PWR_STATE_MASK); + if (!mtk_dp->data->edp_ver) + mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, + DP_PWR_STATE_BANDGAP, DP_PWR_STATE_MASK); ret = phy_configure(mtk_dp->phy, &phy_opts); if (ret) return ret; mtk_dp_set_calibration_data(mtk_dp); + /* Turn on phy power after phy configure */ + if (mtk_dp->data->edp_ver) + mtk_dp_update_bits(mtk_dp, REG_3FF8_DP_ENC_P0_3, + PHY_STATE_W_1_DP_ENC_P0_3, + PHY_STATE_W_1_DP_ENC_P0_3_MASK); mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE, DP_PWR_STATE_BANDGAP_TPLL_LANE, DP_PWR_STATE_MASK); @@ -1326,16 +1559,20 @@ static void mtk_dp_video_mute(struct mtk_dp *mtk_dp, bool enable) struct arm_smccc_res res; u32 val = VIDEO_MUTE_SEL_DP_ENC0_P0 | (enable ? VIDEO_MUTE_SW_DP_ENC0_P0 : 0); + u32 smmc_para; mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3000, val, VIDEO_MUTE_SEL_DP_ENC0_P0 | VIDEO_MUTE_SW_DP_ENC0_P0); - - arm_smccc_smc(MTK_DP_SIP_CONTROL_AARCH32, - mtk_dp->data->smc_cmd, enable, - 0, 0, 0, 0, 0, &res); - + if (mtk_dp->data->edp_ver) { + smmc_para = (EDP_VIDEO_UNMUTE << 16) | enable; + arm_smccc_smc(MTK_SIP_DP_CONTROL, EDP_VIDEO_UNMUTE, enable, + smmc_para, EDP_VIDEO_UNMUTE_VAL, 0, 0, 0, &res); + } else { + arm_smccc_smc(MTK_DP_SIP_CONTROL_AARCH32, + mtk_dp->data->smc_cmd, enable, 0, 0, 0, 0, 0, &res); + } dev_dbg(mtk_dp->dev, "smc cmd: 0x%x, p1: %s, ret: 0x%lx-0x%lx\n", mtk_dp->data->smc_cmd, enable ? "enable" : "disable", res.a0, res.a1); } @@ -1410,6 +1647,16 @@ static void mtk_dp_power_enable(struct mtk_dp *mtk_dp) static void mtk_dp_power_disable(struct mtk_dp *mtk_dp) { mtk_dp_write(mtk_dp, MTK_DP_TOP_PWR_STATE, 0); + if (mtk_dp->data->edp_ver) { + mtk_dp_update_bits(mtk_dp, REG_3F44_DP_ENC_P0_3, + PHY_PWR_STATE_OW_EN_DP_ENC_P0_3, + PHY_PWR_STATE_OW_EN_DP_ENC_P0_3_MASK); + mtk_dp_update_bits(mtk_dp, REG_3F44_DP_ENC_P0_3, + ALL_POWER_OFF, + PHY_PWR_STATE_OW_VALUE_DP_ENC_P0_3_MASK); + mtk_dp_update_bits(mtk_dp, REG_3F44_DP_ENC_P0_3, + 0, PHY_PWR_STATE_OW_EN_DP_ENC_P0_3_MASK); + } mtk_dp_update_bits(mtk_dp, MTK_DP_0034, DA_CKM_CKTX0_EN_FORCE_EN, DA_CKM_CKTX0_EN_FORCE_EN); @@ -1424,9 +1671,13 @@ static void mtk_dp_initialize_priv_data(struct mtk_dp *mtk_dp) { bool plugged_in = (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP); - mtk_dp->train_info.link_rate = DP_LINK_BW_5_4; + if (mtk_dp->data->edp_ver) + mtk_dp->train_info.link_rate = DP_LINK_BW_8_1; + else + mtk_dp->train_info.link_rate = DP_LINK_BW_5_4; mtk_dp->train_info.lane_count = mtk_dp->max_lanes; mtk_dp->train_info.cable_plugged_in = plugged_in; + mtk_dp->train_info.sink_ssc = false; mtk_dp->info.format = DP_PIXELFORMAT_RGB; memset(&mtk_dp->info.vm, 0, sizeof(struct videomode)); @@ -1545,11 +1796,15 @@ static void mtk_dp_train_update_swing_pre(struct mtk_dp *mtk_dp, int lanes, int index = lane / 2; int shift = lane % 2 ? DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : 0; - swing = (dpcd_adjust_req[index] >> shift) & - DP_ADJUST_VOLTAGE_SWING_LANE0_MASK; + if (mtk_dp->swing_value != 0) { + swing = mtk_dp->swing_value; + } else { + swing = (dpcd_adjust_req[index] >> shift) & + DP_ADJUST_VOLTAGE_SWING_LANE0_MASK; + } preemphasis = ((dpcd_adjust_req[index] >> shift) & - DP_ADJUST_PRE_EMPHASIS_LANE0_MASK) >> - DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT; + DP_ADJUST_PRE_EMPHASIS_LANE0_MASK) >> + DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT; val = swing << DP_TRAIN_VOLTAGE_SWING_SHIFT | preemphasis << DP_TRAIN_PRE_EMPHASIS_SHIFT; @@ -1969,6 +2224,11 @@ static void mtk_dp_init_port(struct mtk_dp *mtk_dp) mtk_dp_initialize_hpd_detect_settings(mtk_dp); mtk_dp_digital_sw_reset(mtk_dp); + + if (mtk_dp->data->edp_ver) + mtk_dp_update_bits(mtk_dp, EDP_TX_TOP_CLKGEN_0, + EDP_TX_TOP_CLKGEN_REST_VALUE, + EDP_TX_TOP_CLKGEN_REST_MASK); } static irqreturn_t mtk_dp_hpd_event_thread(int hpd, void *dev) @@ -2047,9 +2307,15 @@ static int mtk_dp_wait_hpd_asserted(struct drm_dp_aux *mtk_aux, unsigned long wa u32 val; int ret; - ret = regmap_read_poll_timeout(mtk_dp->regs, MTK_DP_TRANS_P0_3414, - val, !!(val & HPD_DB_DP_TRANS_P0_MASK), - wait_us / 100, wait_us); + if (mtk_dp->data->edp_ver) + ret = regmap_read_poll_timeout(mtk_dp->regs, REG_364C_AUX_TX_P0, + val, !!(val & HPD_STATUS_DP_AUX_TX_P0_MASK), + wait_us / 100, wait_us); + else + ret = regmap_read_poll_timeout(mtk_dp->regs, MTK_DP_TRANS_P0_3414, + val, !!(val & HPD_DB_DP_TRANS_P0_MASK), + wait_us / 100, wait_us); + if (ret) { mtk_dp->train_info.cable_plugged_in = false; return ret; @@ -2072,7 +2338,10 @@ static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp, struct device_node *endpoint; struct device *dev = &pdev->dev; int ret; + int level; + struct resource *regs; void __iomem *base; + void __iomem *phy_base; u32 linkrate; int len; @@ -2084,6 +2353,22 @@ static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp, if (IS_ERR(mtk_dp->regs)) return PTR_ERR(mtk_dp->regs); + phy_base = devm_platform_ioremap_resource(pdev, 1); + if (!IS_ERR_OR_NULL(phy_base)) { + mtk_dp->phy_regs = devm_regmap_init_mmio(dev, phy_base, + &mtk_edp_phy_regmap_config); + if (IS_ERR(mtk_dp->phy_regs)) + mtk_dp->phy_regs = NULL; + } + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (!IS_ERR_OR_NULL(regs)) { + mtk_dp->pwr_regs = devm_ioremap(&pdev->dev, regs->start, 0x4); + if (IS_ERR(mtk_dp->pwr_regs)) + dev_err(dev, "Failed to get pwr_regs: %ld\n", + PTR_ERR(mtk_dp->pwr_regs)); + } + endpoint = of_graph_get_endpoint_by_regs(pdev->dev.of_node, 1, -1); len = of_property_count_elems_of_size(endpoint, "data-lanes", sizeof(u32)); @@ -2102,6 +2387,11 @@ static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp, mtk_dp->max_linkrate = drm_dp_link_rate_to_bw_code(linkrate * 100); + if (of_get_property(dev->of_node, "swing-level", &level)) { + of_property_read_u32(dev->of_node, + "swing-level", &mtk_dp->swing_value); + } + return 0; } @@ -2672,17 +2962,28 @@ static int mtk_dp_register_phy(struct mtk_dp *mtk_dp) { struct device *dev = mtk_dp->dev; - mtk_dp->phy_dev = platform_device_register_data(dev, "mediatek-dp-phy", - PLATFORM_DEVID_AUTO, - &mtk_dp->regs, - sizeof(struct regmap *)); + if (mtk_dp->phy_regs) + mtk_dp->phy_dev = platform_device_register_data(dev, + "mediatek-edp-phy", + PLATFORM_DEVID_AUTO, + &mtk_dp->phy_regs, + sizeof(struct regmap *)); + else + mtk_dp->phy_dev = platform_device_register_data(dev, + "mediatek-dp-phy", + PLATFORM_DEVID_AUTO, + &mtk_dp->regs, + sizeof(struct regmap *)); if (IS_ERR(mtk_dp->phy_dev)) return dev_err_probe(dev, PTR_ERR(mtk_dp->phy_dev), "Failed to create device mediatek-dp-phy\n"); mtk_dp_get_calibration_data(mtk_dp); - mtk_dp->phy = devm_phy_get(&mtk_dp->phy_dev->dev, "dp"); + if (mtk_dp->data->edp_ver) + mtk_dp->phy = devm_phy_get(&mtk_dp->phy_dev->dev, "edp"); + else + mtk_dp->phy = devm_phy_get(&mtk_dp->phy_dev->dev, "dp"); if (IS_ERR(mtk_dp->phy)) { platform_device_unregister(mtk_dp->phy_dev); return dev_err_probe(dev, PTR_ERR(mtk_dp->phy), "Failed to get phy\n"); @@ -2770,6 +3071,20 @@ static int mtk_dp_probe(struct platform_device *pdev) mtk_dp->aux.wait_hpd_asserted = mtk_dp_wait_hpd_asserted; drm_dp_aux_init(&mtk_dp->aux); + mtk_dp->power_clk = devm_clk_get_optional(dev, NULL); + if (IS_ERR(mtk_dp->power_clk)) { + dev_info(dev, "Failed to get optional clock power_clk\n"); + mtk_dp->power_clk = NULL; + } + + if (mtk_dp->power_clk) + clk_prepare_enable(mtk_dp->power_clk); + + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + if (mtk_dp->pwr_regs) + mtk_edp_pm_ctl(mtk_dp, true); + platform_set_drvdata(pdev, mtk_dp); if (mtk_dp->data->audio_supported) { @@ -2795,10 +3110,13 @@ static int mtk_dp_probe(struct platform_device *pdev) * properly close the eDP port to avoid stalls and then * reinitialize, reset and power on the AUX block. */ - mtk_dp_set_idle_pattern(mtk_dp, true); - mtk_dp_initialize_aux_settings(mtk_dp); - mtk_dp_power_enable(mtk_dp); - + if (mtk_dp->data->edp_ver) { + mtk_dp_poweron(mtk_dp); + } else { + mtk_dp_set_idle_pattern(mtk_dp, true); + mtk_dp_initialize_aux_settings(mtk_dp); + mtk_dp_power_enable(mtk_dp); + } /* Disable HW interrupts: we don't need any for eDP */ mtk_dp_hwirq_enable(mtk_dp, false); @@ -2835,8 +3153,8 @@ static int mtk_dp_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "Failed to add bridge\n"); } - pm_runtime_enable(dev); - pm_runtime_get_sync(dev); + dev_dbg(dev, "%s power.usage_count %d\n", + __func__, atomic_read(&dev->power.usage_count)); return 0; } @@ -2847,6 +3165,7 @@ static void mtk_dp_remove(struct platform_device *pdev) pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); + if (mtk_dp->data->bridge_type != DRM_MODE_CONNECTOR_eDP) timer_delete_sync(&mtk_dp->debounce_timer); platform_device_unregister(mtk_dp->phy_dev); @@ -2859,10 +3178,23 @@ static int mtk_dp_suspend(struct device *dev) { struct mtk_dp *mtk_dp = dev_get_drvdata(dev); + dev_dbg(mtk_dp->dev, "%s usage_count %d\n", + __func__, atomic_read(&dev->power.usage_count)); + mtk_dp_power_disable(mtk_dp); if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP) mtk_dp_hwirq_enable(mtk_dp, false); - pm_runtime_put_sync(dev); + + if (mtk_dp->power_clk) + clk_disable_unprepare(mtk_dp->power_clk); + + if (mtk_dp->pwr_regs) + mtk_edp_pm_ctl(mtk_dp, false); + + pm_runtime_force_suspend(dev); + + dev_dbg(mtk_dp->dev, "%s usage_count %d\n", __func__, + atomic_read(&dev->power.usage_count)); return 0; } @@ -2870,13 +3202,32 @@ static int mtk_dp_suspend(struct device *dev) static int mtk_dp_resume(struct device *dev) { struct mtk_dp *mtk_dp = dev_get_drvdata(dev); + int ret; - pm_runtime_get_sync(dev); + dev_dbg(mtk_dp->dev, "%s usage_count %d\n", __func__, + atomic_read(&dev->power.usage_count)); + + pm_runtime_force_resume(dev); + + if (mtk_dp->power_clk) + clk_prepare_enable(mtk_dp->power_clk); + if (mtk_dp->pwr_regs) + mtk_edp_pm_ctl(mtk_dp, true); + + ret = phy_init(mtk_dp->phy); + if (ret) { + dev_err(mtk_dp->dev, "Failed to initialize phy: %d\n", ret); + return ret; + } + mtk_dp->retry_times = 0; mtk_dp_init_port(mtk_dp); if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP) mtk_dp_hwirq_enable(mtk_dp, true); mtk_dp_power_enable(mtk_dp); + dev_dbg(mtk_dp->dev, "%s usage_count %d\n", __func__, + atomic_read(&dev->power.usage_count)); + return 0; } #endif @@ -2908,6 +3259,15 @@ static const struct mtk_dp_data mt8195_dp_data = { .audio_m_div2_bit = MT8195_AUDIO_M_CODE_MULT_DIV_SEL_DP_ENC0_P0_DIV_2, }; +static const struct mtk_dp_data mt8196_edp_data = { + .bridge_type = DRM_MODE_CONNECTOR_eDP, + .smc_cmd = MTK_DP_SIP_ATF_EDP_VIDEO_UNMUTE, + .efuse_fmt = mt8195_edp_efuse_fmt, + .audio_supported = false, + .audio_m_div2_bit = MT8195_AUDIO_M_CODE_MULT_DIV_SEL_DP_ENC0_P0_DIV_2, + .edp_ver = 1, +}; + static const struct of_device_id mtk_dp_of_match[] = { { .compatible = "mediatek,mt8188-edp-tx", @@ -2925,6 +3285,10 @@ static const struct of_device_id mtk_dp_of_match[] = { .compatible = "mediatek,mt8195-dp-tx", .data = &mt8195_dp_data, }, + { + .compatible = "mediatek,mt8196-edp-tx", + .data = &mt8196_edp_data, + }, {}, }; MODULE_DEVICE_TABLE(of, mtk_dp_of_match); diff --git a/drivers/gpu/drm/mediatek/mtk_dp_reg.h b/drivers/gpu/drm/mediatek/mtk_dp_reg.h index 8ad7a9cc259e..bacf2d239eac 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp_reg.h +++ b/drivers/gpu/drm/mediatek/mtk_dp_reg.h @@ -12,11 +12,22 @@ #define MTK_DP_HPD_CONNECT BIT(2) #define MTK_DP_HPD_INTERRUPT BIT(3) +#define MTK_EDP_HPD_DISCONNECT BIT(10) +#define MTK_EDP_HPD_CONNECT BIT(0) +#define MTK_EDP_HPD_INTERRUPT BIT(2) + /* offset: 0x0 */ #define DP_PHY_GLB_BIAS_GEN_00 0x0 #define RG_XTP_GLB_BIAS_INTR_CTRL GENMASK(20, 16) #define DP_PHY_GLB_DPAUX_TX 0x8 #define RG_CKM_PT0_CKTX_IMPSEL GENMASK(23, 20) +#define DP_TX_TOP_RESET_AND_PROBE 0x2020 +#define RG_SW_RST_MASK GENMASK(7, 0) +#define RG_SW_RST 0xff +#define RG_PROBE_LOW_SEL_MASK GENMASK(18, 16) +#define RG_PROBE_LOW_SEL BIT(16) +#define RG_PROBE_LOW_HIGH_SWAP_MASK BIT(23) +#define RG_PROBE_LOW_HIGH_SWAP BIT(23) #define MTK_DP_0034 0x34 #define DA_XTP_GLB_CKDET_EN_FORCE_VAL BIT(15) #define DA_XTP_GLB_CKDET_EN_FORCE_EN BIT(14) @@ -51,6 +62,15 @@ #define RG_XTP_GLB_CKDET_EN BIT(1) #define RG_DPAUX_RX_EN BIT(0) +/* offset: PHY_OFFSET */ +#define DP_PHY_DIG_GLB_STATUS_0 0x146c +#define RGS_BG_CORE_EN_READY BIT(0) +#define RGS_AUX_LDO_EN_READY BIT(1) + +#define MTK_EDP_PWR_DOMAIN 0x0074 +#define EDP_PWR_RST BIT(0) +#define EDP_PWR_CLK_DIS BIT(4) + /* offset: TOP_OFFSET (0x2000) */ #define MTK_DP_TOP_PWR_STATE 0x2000 #define DP_PWR_STATE_MASK GENMASK(1, 0) @@ -71,22 +91,33 @@ #define DP_TX3_PRE_EMPH_MASK GENMASK(27, 26) #define MTK_DP_TOP_RESET_AND_PROBE 0x2020 #define SW_RST_B_PHYD BIT(4) +#define DP_TX_TOP_SOFT_PROBE 0x2024 #define MTK_DP_TOP_IRQ_MASK 0x202c +#define ENCODER_IRQ_MSK BIT(0) +#define TRANS_IRQ_MSK BIT(1) #define IRQ_MASK_AUX_TOP_IRQ BIT(2) +#define IRQ_OUT_HIGH_ACTIVE_FLDMASK 0x100 #define MTK_DP_TOP_MEM_PD 0x2038 #define MEM_ISO_EN BIT(0) #define FUSE_SEL BIT(2) +#define EDP_TX_TOP_CLKGEN_0 0x2074 +#define EDP_TX_TOP_CLKGEN_REST_MASK 0xf +#define EDP_TX_TOP_CLKGEN_REST_VALUE 0xf + /* offset: ENC0_OFFSET (0x3000) */ #define MTK_DP_ENC0_P0_3000 0x3000 #define LANE_NUM_DP_ENC0_P0_MASK GENMASK(1, 0) #define VIDEO_MUTE_SW_DP_ENC0_P0 BIT(2) #define VIDEO_MUTE_SEL_DP_ENC0_P0 BIT(3) #define ENHANCED_FRAME_EN_DP_ENC0_P0 BIT(4) +#define DP_I_MODE_ENABLE BIT(6) +#define REG_BS_SYMBOL_CNT_RESET BIT(7) #define MTK_DP_ENC0_P0_3004 0x3004 #define VIDEO_M_CODE_SEL_DP_ENC0_P0_MASK BIT(8) #define DP_TX_ENCODER_4P_RESET_SW_DP_ENC0_P0 BIT(9) #define SDP_RESET_SW_DP_ENC0_P0 BIT(13) +#define DP_TX_MUX_DP_ENC0_P0 BIT(14) #define MTK_DP_ENC0_P0_3010 0x3010 #define HTOTAL_SW_DP_ENC0_P0_MASK GENMASK(15, 0) #define MTK_DP_ENC0_P0_3014 0x3014 @@ -119,10 +150,13 @@ #define VBID_AUDIO_MUTE_FLAG_SW_DP_ENC0_P0 BIT(11) #define VBID_AUDIO_MUTE_FLAG_SEL_DP_ENC0_P0 BIT(12) #define MTK_DP_ENC0_P0_3034 0x3034 +#define VIDEO_COLOR_FORMAT_DP_ENC0_P0_MASK BIT(3) +#define VIDEO_COLOR_FORMAT_DP_ENC0_P0_VALUE BIT(3) #define MTK_DP_ENC0_P0_3038 0x3038 #define VIDEO_SOURCE_SEL_DP_ENC0_P0_MASK BIT(11) #define MTK_DP_ENC0_P0_303C 0x303c #define SRAM_START_READ_THRD_DP_ENC0_P0_MASK GENMASK(5, 0) +#define SRAM_START_READ_THRD_DP_ENC0_P0_VALUE 0x8 #define VIDEO_COLOR_DEPTH_DP_ENC0_P0_MASK GENMASK(10, 8) #define VIDEO_COLOR_DEPTH_DP_ENC0_P0_16BIT (0 << 8) #define VIDEO_COLOR_DEPTH_DP_ENC0_P0_12BIT (1 << 8) @@ -139,9 +173,14 @@ #define SDP_DOWN_CNT_INIT_DP_ENC0_P0_MASK GENMASK(11, 0) #define MTK_DP_ENC0_P0_304C 0x304c #define VBID_VIDEO_MUTE_DP_ENC0_P0_MASK BIT(2) +#define VBID_VIDEO_MUTE_IDLE_PATTERN_DP_ENC0_P0_MASK BIT(3) #define SDP_VSYNC_RISING_MASK_DP_ENC0_P0_MASK BIT(8) #define MTK_DP_ENC0_P0_3064 0x3064 #define HDE_NUM_LAST_DP_ENC0_P0_MASK GENMASK(15, 0) +#define REG_3368_DP_ENCODER1_P0 0x3368 +#define VIDEO_SRAM_FIFO_CNT_RESET_SEL_MASK GENMASK(1, 0) +#define VIDEO_SRAM_FIFO_CNT_RESET_SEL_VALUE BIT(0) +#define BS_FOLLOW_SEL_DP_ENC0_P0 BIT(15) #define MTK_DP_ENC0_P0_3088 0x3088 #define AU_EN_DP_ENC0_P0 BIT(6) #define AUDIO_8CH_EN_DP_ENC0_P0_MASK BIT(7) @@ -240,6 +279,14 @@ #define SDP_ASP_INSERT_IN_HBLANK_DP_ENC1_P0_MASK BIT(12) #define SDP_DOWN_ASP_CNT_INIT_DP_ENC1_P0_MASK GENMASK(11, 0) +#define REG_33C0_DP_ENCODER1_P0 0x33c0 +#define SDP_TESTBUS_SEL_DP_ENC_MASK 0xf000 +#define SDP_TESTBUS_SEL_BIT4_DP_ENC_MASK 0x80 +#define SDP_TESTBUS_SEL_BIT4_DP_ENC 0x80 +#define REG_33C4_DP_ENCODER1_P0 0x33c4 +#define DP_TX_ENCODER_TESTBUS_SEL_DP_ENC_MASK GENMASK(6, 5) +#define DP_TX_ENCODER_TESTBUS_SEL_DP_ENC BIT(5) + #define MTK_DP_ENC1_P0_33F4 0x33f4 #define DP_ENC_DUMMY_RW_1_AUDIO_RST_EN BIT(0) #define DP_ENC_DUMMY_RW_1 BIT(9) @@ -296,9 +343,14 @@ #define DP_TRANS_DUMMY_RW_0_MASK GENMASK(3, 2) /* offset: AUX_OFFSET (0x3600) */ +#define REG_3608_AUX_TX_P0 0x3608 +#define HPD_CONNECT_EVENT BIT(0) +#define HPD_INTERRUPT_EVENT BIT(2) +#define HPD_DISCONNECT_EVENT BIT(10) #define MTK_DP_AUX_P0_360C 0x360c #define AUX_TIMEOUT_THR_AUX_TX_P0_MASK GENMASK(12, 0) #define AUX_TIMEOUT_THR_AUX_TX_P0_VAL 0x1595 +#define AUX_TIMEOUT_THR_AUX_TX_P0_VAL_1 0x1d0c #define MTK_DP_AUX_P0_3614 0x3614 #define AUX_RX_UI_CNT_THR_AUX_TX_P0_MASK GENMASK(6, 0) #define AUX_RX_UI_CNT_THR_AUX_FOR_26M 13 @@ -344,19 +396,93 @@ #define MCU_REQUEST_ADDRESS_LSB_AUX_TX_P0_MASK GENMASK(15, 0) #define MTK_DP_AUX_P0_364C 0x364c #define MCU_REQUEST_ADDRESS_MSB_AUX_TX_P0_MASK GENMASK(3, 0) +#define REG_364C_AUX_TX_P0 0x364c +#define HPD_INT_THD_FLDMASK_VAL 0x32 +#define HPD_INT_THD_FLDMASK 0x3f0 +#define HPD_STATUS_DP_AUX_TX_P0_MASK BIT(15) #define MTK_DP_AUX_P0_3650 0x3650 #define MCU_REQ_DATA_NUM_AUX_TX_P0_MASK GENMASK(15, 12) #define PHY_FIFO_RST_AUX_TX_P0_MASK BIT(9) #define MCU_ACK_TRAN_COMPLETE_AUX_TX_P0 BIT(8) #define MTK_DP_AUX_P0_3658 0x3658 #define AUX_TX_OV_EN_AUX_TX_P0_MASK BIT(0) + +#define REG_3660_AUX_TX_P0 0x3660 +#define AUX_DP_TX_INT_3660_VALUE 0xffff +#define AUX_DP_TX_INT_3660_MASK 0xffff + +#define REG_3668_AUX_TX_P0 0x3668 + +#define REG_366C_AUX_TX_P0 0x366c +#define XTAL_FREQ_DP_TX_AUX_366C_VALUE 0x68 +#define XTAL_FREQ_DP_TX_AUX_366C_MASK 0xff00 + +#define REG_367C_AUX_TX_P0 0x367c +#define HPD_CONN_THD_AUX_TX_P0_FLDMASK_POS 5 +#define HPD_CONN_THD_AUX_TX_P0_FLDMASK 0x3c0 #define MTK_DP_AUX_P0_3690 0x3690 #define RX_REPLY_COMPLETE_MODE_AUX_TX_P0 BIT(8) + +#define REG_36A0_AUX_TX_P0 0x36a0 +#define DP_TX_INIT_MASK_15_TO_2_MASK 0xfffc +#define DP_TX_INIT_MASK_15_TO_2 0xfffc #define MTK_DP_AUX_P0_3704 0x3704 #define AUX_TX_FIFO_WDATA_NEW_MODE_T_AUX_TX_P0_MASK BIT(1) #define AUX_TX_FIFO_NEW_MODE_EN_AUX_TX_P0 BIT(2) #define MTK_DP_AUX_P0_3708 0x3708 + +#define REG_37A0_AUX_TX_P0 0x37a0 +#define HPD_DISC_THD_AUX_TX_P0_FLDMASK_POS 5 +#define HPD_DISC_THD_AUX_TX_P0_FLDMASK 0xf0 + #define MTK_DP_AUX_P0_37C8 0x37c8 #define MTK_ATOP_EN_AUX_TX_P0 BIT(0) +/* offset info queue */ +#define REG_3F04_DP_ENC_P0_3 0x3f04 +#define FRAME_START_MARKER_0_DP_ENC_P0_3_MASK 0xffff +#define REG_3F08_DP_ENC_P0_3 0x3f08 +#define FRAME_START_MARKER_1_DP_ENC_P0_3_MASK BIT(3) +#define FRAME_START_MARKER_1_DP_ENC_P0_3 BIT(3) +#define REG_3F0C_DP_ENC_P0_3 0x3f0C +#define FRAME_END_MARKER_0_DP_ENC_P0_3_MASK BIT(1) +#define FRAME_END_MARKER_0_DP_ENC_P0_3 BIT(1) +#define REG_3F10_DP_ENC_P0_3 0x3f10 +#define FRAME_END_MARKER_1_DP_ENC_P0_3_MASK BIT(3) +#define FRAME_END_MARKER_1_DP_ENC_P0_3 BIT(3) +#define REG_3F28_DP_ENC_P0_3 0x3f28 +#define DP_TX_SDP_PSR_AS_TESTBUS_MASK GENMASK(5, 2) +#define DP_TX_SDP_PSR_AS_TESTBUS (0xa << 2) +#define REG_3F44_DP_ENC_P0_3 0x3f44 +#define PHY_PWR_STATE_OW_EN_DP_ENC_P0_3 BIT(2) +#define PHY_PWR_STATE_OW_EN_DP_ENC_P0_3_MASK BIT(2) +#define ALL_POWER_OFF (0x0 << 3) +#define BIAS_POWER_ON (0x1 << 3) +#define BIAS_AND_PLL_POWER_ON (0x2 << 3) +#define ALL_POWER_ON (0x3 << 3) +#define PHY_PWR_STATE_OW_VALUE_DP_ENC_P0_3_MASK GENMASK(4, 3) + +#define REG_3F80_DP_ENC_P0_3 0x3f80 +#define PSR_PATGEN_AVT_EN_FLDMASK 0x20 +#define REG_3FF8_DP_ENC_P0_3 0x3ff8 +#define PHY_STATE_RESET_ALL_MASK 0xff +#define PHY_STATE_RESET_ALL_VALUE 0xff +#define PHY_STATE_W_1_DP_ENC_P0_3 BIT(6) +#define PHY_STATE_W_1_DP_ENC_P0_3_MASK BIT(6) + +#define DVO_ON_W_1_FLDMASK 0x20 +#define XTAL_FREQ_FOR_PSR_DP_ENC_P0_3_VALUE 25 +#define XTAL_FREQ_FOR_PSR_DP_ENC_P0_3_MASK 0x3e00 + +#define DISP_EDPTX_PWR_RST_B (1 << 0) +#define DISP_EDPTX_PWR_CLK_DIS (1 << 4) + +/* offset: PHYD_OFFSET (0x1000) */ +#define PHYD_DIG_DRV_FORCE_LANE(lane) (0x1030 + 0x100 * (lane)) +#define EDP_TX_LN_VOLT_SWING_VAL_FLDMASK 0x6 +#define EDP_TX_LN_PRE_EMPH_VAL_FLDMASK 0x18 + +#define RG_DSI_DEM_EN 0x500 +#define DSI_DE_EMPHASIS_ENABLE BIT(1) + #endif /*_MTK_DP_REG_H_*/ From patchwork Fri Apr 18 06:52:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bincai Liu X-Patchwork-Id: 14056907 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (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 A2AD8C369D0 for ; Fri, 18 Apr 2025 06:53:41 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DE2F310E418; Fri, 18 Apr 2025 06:53:40 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=mediatek.com header.i=@mediatek.com header.b="RI29SC/N"; dkim-atps=neutral Received: from mailgw01.mediatek.com (unknown [60.244.123.138]) by gabe.freedesktop.org (Postfix) with ESMTPS id 632B210E40C for ; Fri, 18 Apr 2025 06:53:30 +0000 (UTC) X-UUID: d2ab9e541c2111f0aae1fd9735fae912-20250418 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=cxjQDLdx0UG7gRjGuFA0+lUdD8dcgO/jR8OOL1qmwZk=; b=RI29SC/NHo58iR/64b2d8HqYZudnXkTinpMrNfri0k8p9uMUmuA5itqSQJ/T75EWSl0QanjhClN1MyFzP5b+JSgGk2NMuvaqO/5qAyrsvnMnffoj3MoBVMg/Hfh1Ag8t/GApAvravmjwsHgjszL02qgx6razUEuyyl19XBIRdZ4=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.2.1, REQID:dcdfe057-a988-44f0-b48a-71aeabe2647f, IP:0, UR L:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION:r elease,TS:0 X-CID-META: VersionHash:0ef645f, CLOUDID:8d44668b-0afe-4897-949e-8174746b1932, B ulkID:nil,BulkQuantity:0,Recheck:0,SF:81|82|102,TC:nil,Content:0|50,EDM:-3 ,IP:nil,URL:0,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV :0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 0,NGT X-CID-BAS: 0,NGT,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: d2ab9e541c2111f0aae1fd9735fae912-20250418 Received: from mtkmbs14n1.mediatek.inc [(172.21.101.75)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1054836075; Fri, 18 Apr 2025 14:53:24 +0800 Received: from mtkmbs13n1.mediatek.inc (172.21.101.193) by mtkmbs11n2.mediatek.inc (172.21.101.187) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.39; Fri, 18 Apr 2025 14:53:23 +0800 Received: from mszsdhlt06.gcn.mediatek.inc (10.16.6.206) by mtkmbs13n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1258.39 via Frontend Transport; Fri, 18 Apr 2025 14:53:22 +0800 From: Bincai Liu To: Chun-Kuang Hu , Philipp Zabel , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Chunfeng Yun , Vinod Koul , Kishon Vijay Abraham I , Jitao shi , CK Hu CC: , , , , , , Bincai Liu Subject: [PATCH 5/5] drm/mediatek: Add eDP phy driver for mt8196 Date: Fri, 18 Apr 2025 14:52:32 +0800 Message-ID: <20250418065313.8972-6-bincai.liu@mediatek.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250418065313.8972-1-bincai.liu@mediatek.com> References: <20250418065313.8972-1-bincai.liu@mediatek.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Add code to support eDP phy for mt8196. Signed-off-by: Bincai Liu --- drivers/phy/mediatek/Makefile | 1 + drivers/phy/mediatek/phy-mtk-edp.c | 262 +++++++++++++++++++++++++++++ 2 files changed, 263 insertions(+) create mode 100644 drivers/phy/mediatek/phy-mtk-edp.c diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile index 1b8088df71e8..49d9ea42497a 100644 --- a/drivers/phy/mediatek/Makefile +++ b/drivers/phy/mediatek/Makefile @@ -4,6 +4,7 @@ # obj-$(CONFIG_PHY_MTK_DP) += phy-mtk-dp.o +obj-$(CONFIG_PHY_MTK_DP) += phy-mtk-edp.o obj-$(CONFIG_PHY_MTK_PCIE) += phy-mtk-pcie.o obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o obj-$(CONFIG_PHY_MTK_UFS) += phy-mtk-ufs.o diff --git a/drivers/phy/mediatek/phy-mtk-edp.c b/drivers/phy/mediatek/phy-mtk-edp.c new file mode 100644 index 000000000000..fadcbda55b70 --- /dev/null +++ b/drivers/phy/mediatek/phy-mtk-edp.c @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019-2022 MediaTek Inc. + * Copyright (c) 2022 BayLibre + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PHYD_OFFSET 0x0000 +#define PHYD_DIG_LAN0_OFFSET 0x1000 +#define PHYD_DIG_LAN1_OFFSET 0x1100 +#define PHYD_DIG_LAN2_OFFSET 0x1200 +#define PHYD_DIG_LAN3_OFFSET 0x1300 +#define PHYD_DIG_GLB_OFFSET 0x1400 + +#define DP_PHY_DIG_PLL_CTL_0 (PHYD_DIG_GLB_OFFSET + 0x10) +#define FORCE_PWORE_STATE_FLDMASK GENMASK(2, 0) +#define FORCE_PWORE_STATE_VALUE 0x7 + +#define IPMUX_CONTROL (PHYD_DIG_GLB_OFFSET + 0x98) +#define EDPTX_DSI_PHYD_SEL_FLDMASK 0x1 +#define EDPTX_DSI_PHYD_SEL_FLDMASK_POS 0 + +#define DP_PHY_DIG_TX_CTL_0 (PHYD_DIG_GLB_OFFSET + 0x74) +#define TX_LN_EN_FLDMASK 0xf + +#define mtk_edp_PHY_DIG_PLL_CTL_1 (PHYD_DIG_GLB_OFFSET + 0x14) +#define TPLL_SSC_EN BIT(8) + +#define mtk_edp_PHY_DIG_BIT_RATE (PHYD_DIG_GLB_OFFSET + 0x3C) +#define BIT_RATE_RBR 0x1 +#define BIT_RATE_HBR 0x4 +#define BIT_RATE_HBR2 0x7 +#define BIT_RATE_HBR3 0x9 + +#define mtk_edp_PHY_DIG_SW_RST (PHYD_DIG_GLB_OFFSET + 0x38) +#define DP_GLB_SW_RST_PHYD BIT(0) +#define DP_GLB_SW_RST_PHYD_MASK BIT(0) + +#define DRIVING_FORCE 0x30 +#define EDP_TX_LN_VOLT_SWING_VAL_FLDMASK 0x6 +#define EDP_TX_LN_VOLT_SWING_VAL_FLDMASK_POS 1 +#define EDP_TX_LN_PRE_EMPH_VAL_FLDMASK 0x18 +#define EDP_TX_LN_PRE_EMPH_VAL_FLDMASK_POS 3 + +struct mtk_edp_phy { + struct regmap *regs; +}; + +enum DPTX_LANE_NUM { + DPTX_LANE0 = 0x0, + DPTX_LANE1 = 0x1, + DPTX_LANE2 = 0x2, + DPTX_LANE3 = 0x3, + DPTX_LANE_MAX, +}; + +enum DPTX_LANE_COUNT { + DPTX_LANE_COUNT1 = 0x1, + DPTX_LANE_COUNT2 = 0x2, + DPTX_LANE_COUNT4 = 0x4, +}; + +static void mtk_edptx_phyd_reset_swing_pre(struct mtk_edp_phy *edp_phy) +{ + regmap_update_bits(edp_phy->regs, PHYD_DIG_LAN0_OFFSET + DRIVING_FORCE, + EDP_TX_LN_VOLT_SWING_VAL_FLDMASK | + EDP_TX_LN_PRE_EMPH_VAL_FLDMASK, 0x0); + regmap_update_bits(edp_phy->regs, PHYD_DIG_LAN1_OFFSET + DRIVING_FORCE, + EDP_TX_LN_VOLT_SWING_VAL_FLDMASK | + EDP_TX_LN_PRE_EMPH_VAL_FLDMASK, 0x0); + regmap_update_bits(edp_phy->regs, PHYD_DIG_LAN2_OFFSET + DRIVING_FORCE, + EDP_TX_LN_VOLT_SWING_VAL_FLDMASK | + EDP_TX_LN_PRE_EMPH_VAL_FLDMASK, 0x0); + regmap_update_bits(edp_phy->regs, PHYD_DIG_LAN3_OFFSET + DRIVING_FORCE, + EDP_TX_LN_VOLT_SWING_VAL_FLDMASK | + EDP_TX_LN_PRE_EMPH_VAL_FLDMASK, 0x0); +} + +static int mtk_edp_phy_init(struct phy *phy) +{ + struct mtk_edp_phy *edp_phy = phy_get_drvdata(phy); + + regmap_update_bits(edp_phy->regs, IPMUX_CONTROL, 0, + EDPTX_DSI_PHYD_SEL_FLDMASK); + + regmap_update_bits(edp_phy->regs, DP_PHY_DIG_PLL_CTL_0, + FORCE_PWORE_STATE_VALUE, + FORCE_PWORE_STATE_FLDMASK); + + return 0; +} + +static int mtk_edp_phy_configure(struct phy *phy, union phy_configure_opts *opts) +{ + struct mtk_edp_phy *edp_phy = phy_get_drvdata(phy); + u32 val; + + if (opts->dp.set_rate) { + switch (opts->dp.link_rate) { + case 1620: + val = BIT_RATE_RBR; + break; + case 2700: + val = BIT_RATE_HBR; + break; + case 5400: + val = BIT_RATE_HBR2; + break; + case 8100: + val = BIT_RATE_HBR3; + break; + default: + dev_err(&phy->dev, + "Implementation error, unknown linkrate %x\n", + opts->dp.link_rate); + return -EINVAL; + } + regmap_write(edp_phy->regs, mtk_edp_PHY_DIG_BIT_RATE, val); + } + + if (opts->dp.set_lanes) { + for (val = 0; val < 4; val++) { + regmap_update_bits(edp_phy->regs, DP_PHY_DIG_TX_CTL_0, + ((1 << (val + 1)) - 1), + TX_LN_EN_FLDMASK); + } + } + + if (opts->dp.set_voltages) { + switch (opts->dp.lanes) { + case DPTX_LANE_COUNT1: + regmap_update_bits(edp_phy->regs, PHYD_DIG_LAN0_OFFSET + + DRIVING_FORCE, + EDP_TX_LN_VOLT_SWING_VAL_FLDMASK | + EDP_TX_LN_PRE_EMPH_VAL_FLDMASK, + opts->dp.voltage[DPTX_LANE0] << 1 | + opts->dp.pre[DPTX_LANE0] << 3); + break; + case DPTX_LANE_COUNT2: + regmap_update_bits(edp_phy->regs, PHYD_DIG_LAN0_OFFSET + + DRIVING_FORCE, + EDP_TX_LN_VOLT_SWING_VAL_FLDMASK | + EDP_TX_LN_PRE_EMPH_VAL_FLDMASK, + opts->dp.voltage[DPTX_LANE0] << 1 | + opts->dp.pre[DPTX_LANE0] << 3); + regmap_update_bits(edp_phy->regs, PHYD_DIG_LAN1_OFFSET + + DRIVING_FORCE, + EDP_TX_LN_VOLT_SWING_VAL_FLDMASK | + EDP_TX_LN_PRE_EMPH_VAL_FLDMASK, + opts->dp.voltage[DPTX_LANE1] << 1 | + opts->dp.pre[DPTX_LANE1] << 3); + break; + case DPTX_LANE_COUNT4: + regmap_update_bits(edp_phy->regs, PHYD_DIG_LAN0_OFFSET + + DRIVING_FORCE, + EDP_TX_LN_VOLT_SWING_VAL_FLDMASK | + EDP_TX_LN_PRE_EMPH_VAL_FLDMASK, + opts->dp.voltage[DPTX_LANE0] << 1 | + opts->dp.pre[DPTX_LANE0] << 3); + regmap_update_bits(edp_phy->regs, PHYD_DIG_LAN1_OFFSET + + DRIVING_FORCE, + EDP_TX_LN_VOLT_SWING_VAL_FLDMASK | + EDP_TX_LN_PRE_EMPH_VAL_FLDMASK, + opts->dp.voltage[DPTX_LANE1] << 1 | + opts->dp.pre[DPTX_LANE1] << 3); + regmap_update_bits(edp_phy->regs, PHYD_DIG_LAN2_OFFSET + + DRIVING_FORCE, + EDP_TX_LN_VOLT_SWING_VAL_FLDMASK | + EDP_TX_LN_PRE_EMPH_VAL_FLDMASK, + opts->dp.voltage[DPTX_LANE2] << 1 | + opts->dp.pre[DPTX_LANE2] << 3); + regmap_update_bits(edp_phy->regs, PHYD_DIG_LAN3_OFFSET + + DRIVING_FORCE, + EDP_TX_LN_VOLT_SWING_VAL_FLDMASK | + EDP_TX_LN_PRE_EMPH_VAL_FLDMASK, + opts->dp.voltage[DPTX_LANE3] << 1 | + opts->dp.pre[DPTX_LANE3] << 3); + break; + default: + dev_err(&phy->dev, "Wrong lanes config: %x\n", + opts->dp.lanes); + return -EINVAL; + } + } + + regmap_update_bits(edp_phy->regs, mtk_edp_PHY_DIG_PLL_CTL_1, + TPLL_SSC_EN, opts->dp.ssc ? 0 : TPLL_SSC_EN); + + return 0; +} + +static int mtk_edp_phy_reset(struct phy *phy) +{ + struct mtk_edp_phy *edp_phy = phy_get_drvdata(phy); + + regmap_update_bits(edp_phy->regs, mtk_edp_PHY_DIG_SW_RST, + 0, DP_GLB_SW_RST_PHYD_MASK); + usleep_range(50, 200); + regmap_update_bits(edp_phy->regs, mtk_edp_PHY_DIG_SW_RST, + DP_GLB_SW_RST_PHYD, DP_GLB_SW_RST_PHYD_MASK); + regmap_update_bits(edp_phy->regs, DP_PHY_DIG_TX_CTL_0, + 0x0, TX_LN_EN_FLDMASK); + mtk_edptx_phyd_reset_swing_pre(edp_phy); + + return 0; +} + +static const struct phy_ops mtk_edp_phy_dev_ops = { + .init = mtk_edp_phy_init, + .configure = mtk_edp_phy_configure, + .reset = mtk_edp_phy_reset, + .owner = THIS_MODULE, +}; + +static int mtk_edp_phy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mtk_edp_phy *edp_phy; + struct phy *phy; + struct regmap *regs; + + regs = *(struct regmap **)dev->platform_data; + if (!regs) + return dev_err_probe(dev, -EINVAL, + "No data passed, requires struct regmap**\n"); + + edp_phy = devm_kzalloc(dev, sizeof(*edp_phy), GFP_KERNEL); + if (!edp_phy) + return -ENOMEM; + + edp_phy->regs = regs; + phy = devm_phy_create(dev, NULL, &mtk_edp_phy_dev_ops); + if (IS_ERR(phy)) + return dev_err_probe(dev, PTR_ERR(phy), + "Failed to create DP PHY\n"); + + phy_set_drvdata(phy, edp_phy); + if (!dev->of_node) + phy_create_lookup(phy, "edp", dev_name(dev)); + + return 0; +} + +struct platform_driver mtk_edp_phy_driver = { + .probe = mtk_edp_phy_probe, + .driver = { + .name = "mediatek-edp-phy", + }, +}; + +module_platform_driver(mtk_edp_phy_driver); + +MODULE_AUTHOR("Markus Schneider-Pargmann "); +MODULE_DESCRIPTION("MediaTek DP PHY Driver"); +MODULE_LICENSE("GPL");