blob: ce295f3fce7461dda03aefec1e853ace44541588 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001From 9fe77147d40e0dc58e7297e79ba8b50e13b8269d Mon Sep 17 00:00:00 2001
2From: Maxime Ripard <maxime@cerno.tech>
3Date: Thu, 19 Dec 2019 16:53:33 +0100
4Subject: [PATCH] drm/vc4: hdmi: Add PHY init and disable function
5
6The HDMI PHY in the BCM2711 HDMI controller is significantly more
7complicated to setup than in the older BCM283x SoCs.
8
9Let's add hooks to enable and disable the PHY.
10
11Signed-off-by: Maxime Ripard <maxime@cerno.tech>
12---
13 drivers/gpu/drm/vc4/Makefile | 1 +
14 drivers/gpu/drm/vc4/vc4_hdmi.c | 14 +++++++-------
15 drivers/gpu/drm/vc4/vc4_hdmi.h | 13 +++++++++++++
16 drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 25 +++++++++++++++++++++++++
17 4 files changed, 46 insertions(+), 7 deletions(-)
18 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
19
20--- a/drivers/gpu/drm/vc4/Makefile
21+++ b/drivers/gpu/drm/vc4/Makefile
22@@ -13,6 +13,7 @@ vc4-y := \
23 vc4_kms.o \
24 vc4_gem.o \
25 vc4_hdmi.o \
26+ vc4_hdmi_phy.o \
27 vc4_vec.o \
28 vc4_hvs.o \
29 vc4_irq.o \
30--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
31+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
32@@ -324,7 +324,9 @@ static void vc4_hdmi_encoder_disable(str
33
34 HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
35
36- HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
37+ if (vc4_hdmi->variant->phy_disable)
38+ vc4_hdmi->variant->phy_disable(vc4_hdmi);
39+
40 HDMI_WRITE(HDMI_VID_CTL,
41 HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
42
43@@ -384,12 +386,8 @@ static void vc4_hdmi_encoder_enable(stru
44 if (vc4_hdmi->variant->reset)
45 vc4_hdmi->variant->reset(vc4_hdmi);
46
47- /* PHY should be in reset, like
48- * vc4_hdmi_encoder_disable() does.
49- */
50- HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
51-
52- HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
53+ if (vc4_hdmi->variant->phy_init)
54+ vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
55
56 if (debug_dump_regs) {
57 struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
58@@ -1429,6 +1427,8 @@ static const struct vc4_hdmi_variant bcm
59
60 .init_resources = vc4_hdmi_init_resources,
61 .reset = vc4_hdmi_reset,
62+ .phy_init = vc4_hdmi_phy_init,
63+ .phy_disable = vc4_hdmi_phy_disable,
64 };
65
66 static const struct of_device_id vc4_hdmi_dt_match[] = {
67--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
68+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
69@@ -21,6 +21,8 @@ to_vc4_hdmi_encoder(struct drm_encoder *
70 return container_of(encoder, struct vc4_hdmi_encoder, base.base);
71 }
72
73+struct drm_display_mode;
74+
75 struct vc4_hdmi;
76 struct vc4_hdmi_register;
77
78@@ -38,6 +40,13 @@ struct vc4_hdmi_variant {
79
80 /* Callback to reset the HDMI block */
81 void (*reset)(struct vc4_hdmi *vc4_hdmi);
82+
83+ /* Callback to initialize the PHY according to the mode */
84+ void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
85+ struct drm_display_mode *mode);
86+
87+ /* Callback to disable the PHY */
88+ void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
89 };
90
91 /* HDMI audio information */
92@@ -95,4 +104,8 @@ encoder_to_vc4_hdmi(struct drm_encoder *
93 return container_of(_encoder, struct vc4_hdmi, encoder);
94 }
95
96+void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
97+ struct drm_display_mode *mode);
98+void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
99+
100 #endif /* _VC4_HDMI_H_ */
101--- /dev/null
102+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
103@@ -0,0 +1,25 @@
104+// SPDX-License-Identifier: GPL-2.0
105+/*
106+ * Copyright (C) 2015 Broadcom
107+ * Copyright (c) 2014 The Linux Foundation. All rights reserved.
108+ * Copyright (C) 2013 Red Hat
109+ * Author: Rob Clark <robdclark@gmail.com>
110+ */
111+
112+#include "vc4_hdmi.h"
113+#include "vc4_hdmi_regs.h"
114+
115+void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
116+{
117+ /* PHY should be in reset, like
118+ * vc4_hdmi_encoder_disable() does.
119+ */
120+
121+ HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
122+ HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
123+}
124+
125+void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
126+{
127+ HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
128+}