On Allwinner chips with a combo D-PHY, the TCON LCD0 should fetch it
from device tree, in order to enable LVDS. Since the PHY also needs to
be powered off to disable LVDS, add a function to the quirks.

Signed-off-by: Kuba Szczodrzyński <k...@szczodrzynski.pl>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 12 ++++++++++++
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  6 ++++++
 2 files changed, 18 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 960e83c82..ccf335a61 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
@@ -183,6 +184,8 @@ static void sun4i_tcon_lvds_set_status(struct sun4i_tcon 
*tcon,
        } else {
                regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
                                   SUN4I_TCON0_LVDS_IF_EN, 0);
+               if (tcon->quirks->disable_lvds_phy)
+                       tcon->quirks->disable_lvds_phy(tcon, encoder);
        }
 }
 
@@ -1245,6 +1248,15 @@ static int sun4i_tcon_bind(struct device *dev, struct 
device *master,
                goto err_free_dclk;
        }
 
+       if (tcon->quirks->has_combo_dphy) {
+               tcon->dphy = devm_phy_get(dev, "dphy");
+               if (IS_ERR(tcon->dphy)) {
+                       dev_err(dev, "Couldn't get the combo D-PHY\n");
+                       ret = PTR_ERR(tcon->dphy);
+                       goto err_free_dclk;
+               }
+       }
+
        if (tcon->quirks->has_channel_0) {
                /*
                 * If we have an LVDS panel connected to the TCON, we should
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h 
b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index fa23aa23f..b270d1a13 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -239,6 +239,7 @@ struct sun4i_tcon_quirks {
        bool    has_channel_0;  /* a83t does not have channel 0 on second TCON 
*/
        bool    has_channel_1;  /* a33 does not have channel 1 */
        bool    has_lvds_alt;   /* Does the LVDS clock have a parent other than 
the TCON clock? */
+       bool    has_combo_dphy; /* Is the D-PHY used for LVDS output? */
        bool    needs_de_be_mux; /* sun6i needs mux to select backend */
        bool    needs_edp_reset; /* a80 edp reset needed for tcon0 access */
        bool    supports_lvds;   /* Does the TCON support an LVDS output? */
@@ -250,6 +251,8 @@ struct sun4i_tcon_quirks {
        /* handler for LVDS setup routine */
        void    (*setup_lvds_phy)(struct sun4i_tcon *tcon,
                                  const struct drm_encoder *encoder);
+       void    (*disable_lvds_phy)(struct sun4i_tcon *tcon,
+                                   const struct drm_encoder *encoder);
 };
 
 struct sun4i_tcon {
@@ -282,6 +285,9 @@ struct sun4i_tcon {
        /* Associated crtc */
        struct sun4i_crtc               *crtc;
 
+       /* Associated D-PHY */
+       struct phy                      *dphy;
+
        int                             id;
 
        /* TCON list management */
-- 
2.25.1

Reply via email to