drm/vc4: hdmi: Add PHY init and disable function
authorMaxime Ripard <maxime@cerno.tech>
Thu, 3 Sep 2020 08:01:25 +0000 (10:01 +0200)
committerMaxime Ripard <maxime@cerno.tech>
Mon, 7 Sep 2020 16:06:04 +0000 (18:06 +0200)
The HDMI PHY in the BCM2711 HDMI controller is significantly more
complicated to setup than in the older BCM283x SoCs.

Let's add hooks to enable and disable the PHY.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Tested-by: Chanwoo Choi <cw00.choi@samsung.com>
Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Link: https://patchwork.freedesktop.org/patch/msgid/7216826284dbc60a58bdacd662805d20699e5c80.1599120059.git-series.maxime@cerno.tech
drivers/gpu/drm/vc4/Makefile
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vc4/vc4_hdmi.h
drivers/gpu/drm/vc4/vc4_hdmi_phy.c [new file with mode: 0644]

index b303703..d0163e1 100644 (file)
@@ -12,6 +12,7 @@ vc4-y := \
        vc4_kms.o \
        vc4_gem.o \
        vc4_hdmi.o \
+       vc4_hdmi_phy.o \
        vc4_vec.o \
        vc4_hvs.o \
        vc4_irq.o \
index 77971be..f3cc612 100644 (file)
@@ -321,7 +321,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 
        HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
 
-       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+       if (vc4_hdmi->variant->phy_disable)
+               vc4_hdmi->variant->phy_disable(vc4_hdmi);
+
        HDMI_WRITE(HDMI_VID_CTL,
                   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
@@ -381,12 +383,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
        if (vc4_hdmi->variant->reset)
                vc4_hdmi->variant->reset(vc4_hdmi);
 
-       /* PHY should be in reset, like
-        * vc4_hdmi_encoder_disable() does.
-        */
-       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
-
-       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
+       if (vc4_hdmi->variant->phy_init)
+               vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
 
        if (debug_dump_regs) {
                struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
@@ -1432,6 +1430,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 
        .init_resources         = vc4_hdmi_init_resources,
        .reset                  = vc4_hdmi_reset,
+       .phy_init               = vc4_hdmi_phy_init,
+       .phy_disable            = vc4_hdmi_phy_disable,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
index 17a3058..32c8016 100644 (file)
@@ -21,6 +21,8 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
        return container_of(encoder, struct vc4_hdmi_encoder, base.base);
 }
 
+struct drm_display_mode;
+
 struct vc4_hdmi;
 struct vc4_hdmi_register;
 
@@ -38,6 +40,13 @@ struct vc4_hdmi_variant {
 
        /* Callback to reset the HDMI block */
        void (*reset)(struct vc4_hdmi *vc4_hdmi);
+
+       /* Callback to initialize the PHY according to the mode */
+       void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
+                        struct drm_display_mode *mode);
+
+       /* Callback to disable the PHY */
+       void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
 };
 
 /* HDMI audio information */
@@ -95,4 +104,8 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
        return container_of(_encoder, struct vc4_hdmi, encoder);
 }
 
+void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
+                      struct drm_display_mode *mode);
+void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
+
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
new file mode 100644 (file)
index 0000000..5a17468
--- /dev/null
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2015 Broadcom
+ * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ */
+
+#include "vc4_hdmi.h"
+#include "vc4_hdmi_regs.h"
+
+void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
+{
+       /* PHY should be in reset, like
+        * vc4_hdmi_encoder_disable() does.
+        */
+
+       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
+}
+
+void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
+{
+       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+}