Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Add support for internal DesignWare HDMI PHYs



details:   https://anonhg.NetBSD.org/src/rev/f80ffb90c4e3
branches:  trunk
changeset: 460908:f80ffb90c4e3
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sat Nov 09 23:27:50 2019 +0000

description:
Add support for internal DesignWare HDMI PHYs

diffstat:

 sys/conf/files           |    3 +-
 sys/dev/ic/dw_hdmi.c     |   72 +++++++-
 sys/dev/ic/dw_hdmi.h     |   34 +++-
 sys/dev/ic/dw_hdmi_phy.c |  401 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 497 insertions(+), 13 deletions(-)

diffs (truncated from 631 to 300 lines):

diff -r c65f9901bd51 -r f80ffb90c4e3 sys/conf/files
--- a/sys/conf/files    Sat Nov 09 22:05:50 2019 +0000
+++ b/sys/conf/files    Sat Nov 09 23:27:50 2019 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files,v 1.1241 2019/11/05 20:19:17 maxv Exp $
+#      $NetBSD: files,v 1.1242 2019/11/09 23:27:50 jmcneill Exp $
 #      @(#)files.newconf       7.5 (Berkeley) 5/10/93
 
 version        20171118
@@ -1497,6 +1497,7 @@
 # Designware HDMI TX
 device dwhdmi: edid, videomode, drmkms, drmkms_i2c
 file   dev/ic/dw_hdmi.c                dwhdmi
+file   dev/ic/dw_hdmi_phy.c            dwhdmi
 
 #
 # File systems
diff -r c65f9901bd51 -r f80ffb90c4e3 sys/dev/ic/dw_hdmi.c
--- a/sys/dev/ic/dw_hdmi.c      Sat Nov 09 22:05:50 2019 +0000
+++ b/sys/dev/ic/dw_hdmi.c      Sat Nov 09 23:27:50 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dw_hdmi.c,v 1.1 2019/01/30 01:19:49 jmcneill Exp $ */
+/* $NetBSD: dw_hdmi.c,v 1.2 2019/11/09 23:27:50 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dw_hdmi.c,v 1.1 2019/01/30 01:19:49 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dw_hdmi.c,v 1.2 2019/11/09 23:27:50 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -50,6 +50,10 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_edid.h>
 
+#define        HDMI_DESIGN_ID          0x0000
+#define        HDMI_REVISION_ID        0x0001
+#define        HDMI_CONFIG2_ID         0x0006
+
 #define        HDMI_IH_I2CM_STAT0      0x0105
 #define         HDMI_IH_I2CM_STAT0_DONE                __BIT(1)
 #define         HDMI_IH_I2CM_STAT0_ERROR               __BIT(0)
@@ -128,6 +132,23 @@
 #define        HDMI_FC_CH2PREAM        0x1016
 #define         HDMI_FC_CH2PREAM_DEFAULT               0x21
 
+#define        HDMI_PHY_CONF0          0x3000
+#define         HDMI_PHY_CONF0_PDZ                     __BIT(7)
+#define         HDMI_PHY_CONF0_ENTMDS                  __BIT(6)
+#define         HDMI_PHY_CONF0_SVSRET                  __BIT(5)
+#define         HDMI_PHY_CONF0_PDDQ                    __BIT(4)
+#define         HDMI_PHY_CONF0_TXPWRON                 __BIT(3)
+#define         HDMI_PHY_CONF0_ENHPDRXSENSE            __BIT(2)
+#define         HDMI_PHY_CONF0_SELDATAENPOL            __BIT(1)
+#define         HDMI_PHY_CONF0_SELDIPIF                __BIT(0)
+#define        HDMI_PHY_STAT0          0x3004
+#define         HDMI_PHY_STAT0_RX_SENSE_3              __BIT(7)
+#define         HDMI_PHY_STAT0_RX_SENSE_2              __BIT(6)
+#define         HDMI_PHY_STAT0_RX_SENSE_1              __BIT(5)
+#define         HDMI_PHY_STAT0_RX_SENSE_0              __BIT(4)
+#define         HDMI_PHY_STAT0_HPD                     __BIT(1)
+#define         HDMI_PHY_STAT0_TX_PHY_LOCK             __BIT(0)
+
 #define        HDMI_MC_CLKDIS          0x4001
 #define         HDMI_MC_CLKDIS_HDCPCLK_DISABLE         __BIT(6)
 #define         HDMI_MC_CLKDIS_CECCLK_DISABLE          __BIT(5)
@@ -143,6 +164,8 @@
 #define         HDMI_MC_SWRSTZREQ_PIXELSWRST_REQ       __BIT(0)
 #define        HDMI_MC_FLOWCTRL        0x4004
 #define        HDMI_MC_PHYRSTZ         0x4005
+#define         HDMI_MC_PHYRSTZ_ASSERT                 __BIT(0)
+#define         HDMI_MC_PHYRSTZ_DEASSERT               0
 #define        HDMI_MC_LOCKONCLOCK     0x4006
 #define        HDMI_MC_HEACPHY_RST     0x4007
 
@@ -412,7 +435,7 @@
 {
        struct dwhdmi_connector *dwhdmi_connector = &sc->sc_connector;
        uint8_t val;
-       u_int n;
+       u_int n, iter;
 
        /* Bypass colour space converter */
        dwhdmi_write(sc, HDMI_MC_FLOWCTRL, 0);
@@ -430,8 +453,10 @@
        val = 0xff & ~HDMI_MC_SWRSTZREQ_TMDSSWRST_REQ;
        dwhdmi_write(sc, HDMI_MC_SWRSTZREQ, val);
 
+       iter = sc->sc_version == 0x130a ? 4 : 1;
+
        val = dwhdmi_read(sc, HDMI_FC_INVIDCONF);
-       for (n = 0; n < 4; n++)
+       for (n = 0; n < iter; n++)
                dwhdmi_write(sc, HDMI_FC_INVIDCONF, val);
 }
 
@@ -479,7 +504,7 @@
 
        memset(edid, 0, sizeof(edid));
        for (block = 0; block < 4; block++) {
-               error = ddc_read_edid_block(&sc->sc_ic,
+               error = ddc_read_edid_block(sc->sc_ic,
                    &edid[block * EDID_LENGTH], EDID_LENGTH, block);
                if (error != 0)
                        break;
@@ -624,7 +649,7 @@
 int
 dwhdmi_attach(struct dwhdmi_softc *sc)
 {
-       struct i2c_controller *ic = &sc->sc_ic;
+       uint8_t val;
 
        if (sc->sc_reg_width != 1 && sc->sc_reg_width != 4) {
                aprint_error_dev(sc->sc_dev, "unsupported register width %d\n", sc->sc_reg_width);
@@ -633,10 +658,37 @@
 
        mutex_init(&sc->sc_ic_lock, MUTEX_DEFAULT, IPL_NONE);
 
-       ic->ic_cookie = sc;
-       ic->ic_acquire_bus = dwhdmi_ddc_acquire_bus;
-       ic->ic_release_bus = dwhdmi_ddc_release_bus;
-       ic->ic_exec = dwhdmi_ddc_exec;
+       sc->sc_version = dwhdmi_read(sc, HDMI_DESIGN_ID);
+       sc->sc_version <<= 8;
+       sc->sc_version |= dwhdmi_read(sc, HDMI_REVISION_ID);
+
+       sc->sc_phytype = dwhdmi_read(sc, HDMI_CONFIG2_ID);
+
+       aprint_normal_dev(sc->sc_dev, "version %x.%03x, phytype 0x%02x\n",
+           sc->sc_version >> 12, sc->sc_version & 0xfff,
+           sc->sc_phytype);
+
+       /*
+        * If a DDC i2c bus tag is provided by the caller, use it. Otherwise,
+        * use the I2C master built-in to DWC HDMI.
+        */
+       if (sc->sc_ic == NULL) {
+               struct i2c_controller *ic = &sc->sc_ic_builtin;
+               ic->ic_cookie = sc;
+               ic->ic_acquire_bus = dwhdmi_ddc_acquire_bus;
+               ic->ic_release_bus = dwhdmi_ddc_release_bus;
+               ic->ic_exec = dwhdmi_ddc_exec;
+               sc->sc_ic = ic;
+       }
+
+       /*
+        * Enable HPD on internal PHY
+        */
+       if ((sc->sc_flags & DWHDMI_USE_INTERNAL_PHY) != 0) {
+               val = dwhdmi_read(sc, HDMI_PHY_CONF0);
+               val |= HDMI_PHY_CONF0_ENHPDRXSENSE;
+               dwhdmi_write(sc, HDMI_PHY_CONF0, val);
+       }
 
        return 0;
 }
diff -r c65f9901bd51 -r f80ffb90c4e3 sys/dev/ic/dw_hdmi.h
--- a/sys/dev/ic/dw_hdmi.h      Sat Nov 09 22:05:50 2019 +0000
+++ b/sys/dev/ic/dw_hdmi.h      Sat Nov 09 23:27:50 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dw_hdmi.h,v 1.1 2019/01/30 01:19:49 jmcneill Exp $ */
+/* $NetBSD: dw_hdmi.h,v 1.2 2019/11/09 23:27:50 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -44,20 +44,43 @@
        bool                    monitor_audio;
 };
 
+struct dwhdmi_phy_config {
+       u_int                   pixel_clock;
+       uint32_t                sym;
+       uint32_t                term;
+       uint32_t                vlev;
+};
+
+struct dwhdmi_mpll_config {
+       u_int                   pixel_clock;
+       uint32_t                cpce;
+       uint32_t                gmp;
+       uint32_t                curr;
+};
+
 struct dwhdmi_softc {
        device_t                sc_dev;
        bus_space_tag_t         sc_bst;
        bus_space_handle_t      sc_bsh;
        u_int                   sc_reg_width;
+       u_int                   sc_flags;
+#define        DWHDMI_USE_INTERNAL_PHY __BIT(0)
 
-       struct i2c_controller   sc_ic;
+       u_int                   sc_phytype;
+       u_int                   sc_version;
+
+       i2c_tag_t               sc_ic;
        kmutex_t                sc_ic_lock;
+       struct i2c_controller   sc_ic_builtin;
 
        struct dwhdmi_connector sc_connector;
        struct drm_bridge       sc_bridge;
 
        struct drm_display_mode sc_curmode;
 
+       const struct dwhdmi_mpll_config *sc_mpll_config;
+       const struct dwhdmi_phy_config *sc_phy_config;
+
        enum drm_connector_status (*sc_detect)(struct dwhdmi_softc *, bool);
        void                    (*sc_enable)(struct dwhdmi_softc *);
        void                    (*sc_disable)(struct dwhdmi_softc *);
@@ -74,4 +97,11 @@
 uint8_t                dwhdmi_read(struct dwhdmi_softc *, bus_size_t);
 void           dwhdmi_write(struct dwhdmi_softc *, bus_size_t, uint8_t);
 
+enum drm_connector_status dwhdmi_phy_detect(struct dwhdmi_softc *, bool);
+void           dwhdmi_phy_enable(struct dwhdmi_softc *);
+void           dwhdmi_phy_disable(struct dwhdmi_softc *);
+void           dwhdmi_phy_mode_set(struct dwhdmi_softc *,
+                                   struct drm_display_mode *,
+                                   struct drm_display_mode *);
+
 #endif /* !_DEV_IC_DWHDMI_H */
diff -r c65f9901bd51 -r f80ffb90c4e3 sys/dev/ic/dw_hdmi_phy.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/ic/dw_hdmi_phy.c  Sat Nov 09 23:27:50 2019 +0000
@@ -0,0 +1,401 @@
+/* $NetBSD: dw_hdmi_phy.c,v 1.1 2019/11/09 23:27:50 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo%freebsd.org@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: dw_hdmi_phy.c,v 1.1 2019/11/09 23:27:50 jmcneill Exp $");
+
+#include <sys/param.h>
+
+#include <drm/drmP.h>
+
+#include <dev/ic/dw_hdmi.h>
+
+#define        HDMI_IH_PHY_STAT0                       0x0104
+#define          HDMI_IH_PHY_STAT0_HPD (1 << 0)
+#define        HDMI_IH_I2CMPHY_STAT0                   0x0108
+#define          HDMI_IH_I2CMPHY_STAT0_DONE            (1 << 1)
+#define          HDMI_IH_I2CMPHY_STAT0_ERROR           (1 << 0)
+
+#define        HDMI_PHY_CONF0                          0x3000
+#define          HDMI_PHY_CONF0_PDZ_MASK                       0x80
+#define          HDMI_PHY_CONF0_PDZ_OFFSET             7
+#define          HDMI_PHY_CONF0_ENTMDS_MASK            0x40
+#define          HDMI_PHY_CONF0_ENTMDS_OFFSET          6
+#define          HDMI_PHY_CONF0_SVSRET_MASK            0x20
+#define          HDMI_PHY_CONF0_SVSRET_OFFSET                  5
+#define          HDMI_PHY_CONF0_GEN2_PDDQ_MASK         0x10
+#define          HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET               4
+#define          HDMI_PHY_CONF0_GEN2_TXPWRON_MASK      0x8
+#define          HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET    3
+#define          HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK 0x4
+#define          HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET       2
+#define          HDMI_PHY_CONF0_SELDATAENPOL_MASK      0x2
+#define          HDMI_PHY_CONF0_SELDATAENPOL_OFFSET    1
+#define          HDMI_PHY_CONF0_SELDIPIF_MASK          0x1
+#define          HDMI_PHY_CONF0_SELDIPIF_OFFSET                0
+#define        HDMI_PHY_TST0                           0x3001
+#define          HDMI_PHY_TST0_TSTCLR_MASK             0x20
+#define          HDMI_PHY_TST0_TSTCLR_OFFSET           5
+#define          HDMI_PHY_TST0_TSTEN_MASK              0x10
+#define          HDMI_PHY_TST0_TSTEN_OFFSET            4
+#define          HDMI_PHY_TST0_TSTCLK_MASK             0x1
+#define          HDMI_PHY_TST0_TSTCLK_OFFSET           0
+#define        HDMI_PHY_TST1                           0x3002
+#define        HDMI_PHY_TST2                           0x3003
+#define        HDMI_PHY_STAT0                          0x3004



Home | Main Index | Thread Index | Old Index