Now that bit meanings are somewhat known, rework PHY initialization.
This is modelled after Linux driver.

Signed-off-by: Jernej Skrabec <jernej.skra...@siol.net>
---
 drivers/video/sunxi/sunxi_dw_hdmi.c | 411 +++++++++++++++++++---------
 1 file changed, 279 insertions(+), 132 deletions(-)

diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c 
b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 4cc175d714ea..c4cded569bfb 100644
--- a/drivers/video/sunxi/sunxi_dw_hdmi.c
+++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
@@ -18,100 +18,200 @@
 #include <linux/bitops.h>
 #include <linux/delay.h>
 
+#define SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK                BIT(0)
+#define SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK       GENMASK(15, 8)
+#define SUN8I_HDMI_PHY_DBG_CTRL_POL_NHSYNC     BIT(8)
+#define SUN8I_HDMI_PHY_DBG_CTRL_POL_NVSYNC     BIT(9)
+#define SUN8I_HDMI_PHY_DBG_CTRL_ADDR_MASK      GENMASK(23, 16)
+#define SUN8I_HDMI_PHY_DBG_CTRL_ADDR(addr)     (addr << 16)
+
+#define SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN       BIT(31)
+
+#define SUN8I_HDMI_PHY_READ_EN_MAGIC           0x54524545
+
+#define SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC                0x42494E47
+
+#define SUN8I_HDMI_PHY_ANA_CFG1_REG_SWI                BIT(31)
+#define SUN8I_HDMI_PHY_ANA_CFG1_REG_PWEND      BIT(30)
+#define SUN8I_HDMI_PHY_ANA_CFG1_REG_PWENC      BIT(29)
+#define SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW      BIT(28)
+#define SUN8I_HDMI_PHY_ANA_CFG1_REG_SVRCAL(x)  ((x) << 26)
+#define SUN8I_HDMI_PHY_ANA_CFG1_REG_SVBH(x)    ((x) << 24)
+#define SUN8I_HDMI_PHY_ANA_CFG1_AMP_OPT                BIT(23)
+#define SUN8I_HDMI_PHY_ANA_CFG1_EMP_OPT                BIT(22)
+#define SUN8I_HDMI_PHY_ANA_CFG1_AMPCK_OPT      BIT(21)
+#define SUN8I_HDMI_PHY_ANA_CFG1_EMPCK_OPT      BIT(20)
+#define SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL         BIT(19)
+#define SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG                BIT(18)
+#define SUN8I_HDMI_PHY_ANA_CFG1_REG_SCKTMDS    BIT(17)
+#define SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN     BIT(16)
+#define SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK      GENMASK(15, 12)
+#define SUN8I_HDMI_PHY_ANA_CFG1_TXEN_ALL       (0xf << 12)
+#define SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK BIT(11)
+#define SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2   BIT(10)
+#define SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1   BIT(9)
+#define SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0   BIT(8)
+#define SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDSCLK  BIT(7)
+#define SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2    BIT(6)
+#define SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1    BIT(5)
+#define SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0    BIT(4)
+#define SUN8I_HDMI_PHY_ANA_CFG1_CKEN           BIT(3)
+#define SUN8I_HDMI_PHY_ANA_CFG1_LDOEN          BIT(2)
+#define SUN8I_HDMI_PHY_ANA_CFG1_ENVBS          BIT(1)
+#define SUN8I_HDMI_PHY_ANA_CFG1_ENBI           BIT(0)
+
+#define SUN8I_HDMI_PHY_ANA_CFG2_M_EN           BIT(31)
+#define SUN8I_HDMI_PHY_ANA_CFG2_PLLDBEN                BIT(30)
+#define SUN8I_HDMI_PHY_ANA_CFG2_SEN            BIT(29)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_HPDPD      BIT(28)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_HPDEN      BIT(27)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_PLRCK      BIT(26)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_PLR(x)     ((x) << 23)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_DENCK      BIT(22)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_DEN                BIT(21)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_CD(x)      ((x) << 19)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_CKSS(x)    ((x) << 17)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK    BIT(16)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW      BIT(15)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_CSMPS(x)   ((x) << 13)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(x)     ((x) << 10)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_BOOSTCK(x) ((x) << 8)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_BOOST(x)   ((x) << 6)
+#define SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(x)   ((x) << 0)
+
+#define SUN8I_HDMI_PHY_ANA_CFG3_REG_SLOWCK(x)  ((x) << 30)
+#define SUN8I_HDMI_PHY_ANA_CFG3_REG_SLOW(x)    ((x) << 28)
+#define SUN8I_HDMI_PHY_ANA_CFG3_REG_WIRE(x)    ((x) << 18)
+#define SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(x)   ((x) << 14)
+#define SUN8I_HDMI_PHY_ANA_CFG3_REG_EMPCK(x)   ((x) << 11)
+#define SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(x)     ((x) << 7)
+#define SUN8I_HDMI_PHY_ANA_CFG3_REG_EMP(x)     ((x) << 4)
+#define SUN8I_HDMI_PHY_ANA_CFG3_SDAPD          BIT(3)
+#define SUN8I_HDMI_PHY_ANA_CFG3_SDAEN          BIT(2)
+#define SUN8I_HDMI_PHY_ANA_CFG3_SCLPD          BIT(1)
+#define SUN8I_HDMI_PHY_ANA_CFG3_SCLEN          BIT(0)
+
+#define SUN8I_HDMI_PHY_PLL_CFG1_REG_OD1                BIT(31)
+#define SUN8I_HDMI_PHY_PLL_CFG1_REG_OD         BIT(30)
+#define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN                BIT(29)
+#define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN                BIT(28)
+#define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33       BIT(27)
+#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK   BIT(26)
+#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT 26
+#define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN          BIT(25)
+#define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x)    ((x) << 22)
+#define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x)     ((x) << 20)
+#define SUN8I_HDMI_PHY_PLL_CFG1_PLLDBEN                BIT(19)
+#define SUN8I_HDMI_PHY_PLL_CFG1_CS             BIT(18)
+#define SUN8I_HDMI_PHY_PLL_CFG1_CP_S(x)                ((x) << 13)
+#define SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(x)     ((x) << 7)
+#define SUN8I_HDMI_PHY_PLL_CFG1_BWS            BIT(6)
+#define SUN8I_HDMI_PHY_PLL_CFG1_B_IN_MSK       GENMASK(5, 0)
+#define SUN8I_HDMI_PHY_PLL_CFG1_B_IN_SHIFT     0
+
+#define SUN8I_HDMI_PHY_PLL_CFG2_SV_H           BIT(31)
+#define SUN8I_HDMI_PHY_PLL_CFG2_PDCLKSEL(x)    ((x) << 29)
+#define SUN8I_HDMI_PHY_PLL_CFG2_CLKSTEP(x)     ((x) << 27)
+#define SUN8I_HDMI_PHY_PLL_CFG2_PSET(x)                ((x) << 24)
+#define SUN8I_HDMI_PHY_PLL_CFG2_PCLK_SEL       BIT(23)
+#define SUN8I_HDMI_PHY_PLL_CFG2_AUTOSYNC_DIS   BIT(22)
+#define SUN8I_HDMI_PHY_PLL_CFG2_VREG2_OUT_EN   BIT(21)
+#define SUN8I_HDMI_PHY_PLL_CFG2_VREG1_OUT_EN   BIT(20)
+#define SUN8I_HDMI_PHY_PLL_CFG2_VCOGAIN_EN     BIT(19)
+#define SUN8I_HDMI_PHY_PLL_CFG2_VCOGAIN(x)     ((x) << 16)
+#define SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(x)       ((x) << 12)
+#define SUN8I_HDMI_PHY_PLL_CFG2_VCO_RST_IN     BIT(11)
+#define SUN8I_HDMI_PHY_PLL_CFG2_SINT_FRAC      BIT(10)
+#define SUN8I_HDMI_PHY_PLL_CFG2_SDIV2          BIT(9)
+#define SUN8I_HDMI_PHY_PLL_CFG2_S(x)           ((x) << 6)
+#define SUN8I_HDMI_PHY_PLL_CFG2_S6P25_7P5      BIT(5)
+#define SUN8I_HDMI_PHY_PLL_CFG2_S5_7           BIT(4)
+#define SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK     GENMASK(3, 0)
+#define SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_SHIFT   0
+#define SUN8I_HDMI_PHY_PLL_CFG2_PREDIV(x)      (((x) - 1) << 0)
+
+#define SUN8I_HDMI_PHY_PLL_CFG3_SOUT_DIV2      BIT(0)
+
+#define SUN8I_HDMI_PHY_ANA_STS_B_OUT_SHIFT     11
+#define SUN8I_HDMI_PHY_ANA_STS_B_OUT_MSK       GENMASK(16, 11)
+#define SUN8I_HDMI_PHY_ANA_STS_RCALEND2D       BIT(7)
+#define SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK       GENMASK(5, 0)
+
 struct sunxi_dw_hdmi_priv {
        struct dw_hdmi hdmi;
        int mux;
+       uint rcal;
 };
 
 struct sunxi_hdmi_phy {
-       u32 pol;
-       u32 res1[3];
+       u32 dbg_ctrl;
+       u32 rext_ctrl;
+       u32 res1[2];
        u32 read_en;
        u32 unscramble;
        u32 res2[2];
-       u32 ctrl;
-       u32 unk1;
-       u32 unk2;
-       u32 pll;
-       u32 clk;
-       u32 unk3;
-       u32 status;
+       u32 ana_cfg1;
+       u32 ana_cfg2;
+       u32 ana_cfg3;
+       u32 pll_cfg1;
+       u32 pll_cfg2;
+       u32 pll_cfg3;
+       u32 ana_sts;
 };
 
 #define HDMI_PHY_OFFS 0x10000
 
-static int sunxi_dw_hdmi_get_divider(uint clock)
-{
-       /*
-        * Due to missing documentaion of HDMI PHY, we know correct
-        * settings only for following four PHY dividers. Select one
-        * based on clock speed.
-        */
-       if (clock <= 27000000)
-               return 11;
-       else if (clock <= 74250000)
-               return 4;
-       else if (clock <= 148500000)
-               return 2;
-       else
-               return 1;
-}
-
-static void sunxi_dw_hdmi_phy_init(struct dw_hdmi *hdmi)
+static void sunxi_dw_hdmi_phy_init(struct sunxi_dw_hdmi_priv *priv)
 {
        struct sunxi_hdmi_phy * const phy =
-               (struct sunxi_hdmi_phy *)(hdmi->ioaddr + HDMI_PHY_OFFS);
+               (struct sunxi_hdmi_phy *)(priv->hdmi.ioaddr + HDMI_PHY_OFFS);
        unsigned long tmo;
-       u32 tmp;
 
-       /*
-        * HDMI PHY settings are taken as-is from Allwinner BSP code.
-        * There is no documentation.
-        */
-       writel(0, &phy->ctrl);
-       setbits_le32(&phy->ctrl, BIT(0));
+       /* enable read access to HDMI controller */
+       writel(SUN8I_HDMI_PHY_READ_EN_MAGIC, &phy->read_en);
+       /* descramble register offsets */
+       writel(SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC, &phy->unscramble);
+
+       writel(0, &phy->ana_cfg1);
+       setbits_le32(&phy->ana_cfg1, SUN8I_HDMI_PHY_ANA_CFG1_ENBI);
        udelay(5);
-       setbits_le32(&phy->ctrl, BIT(16));
-       setbits_le32(&phy->ctrl, BIT(1));
+       setbits_le32(&phy->ana_cfg1, SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN);
+       setbits_le32(&phy->ana_cfg1, SUN8I_HDMI_PHY_ANA_CFG1_ENVBS);
        udelay(10);
-       setbits_le32(&phy->ctrl, BIT(2));
+       setbits_le32(&phy->ana_cfg1, SUN8I_HDMI_PHY_ANA_CFG1_LDOEN);
        udelay(5);
-       setbits_le32(&phy->ctrl, BIT(3));
+       setbits_le32(&phy->ana_cfg1, SUN8I_HDMI_PHY_ANA_CFG1_CKEN);
        udelay(40);
-       setbits_le32(&phy->ctrl, BIT(19));
+       setbits_le32(&phy->ana_cfg1, SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL);
        udelay(100);
-       setbits_le32(&phy->ctrl, BIT(18));
-       setbits_le32(&phy->ctrl, 7 << 4);
+       setbits_le32(&phy->ana_cfg1, SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG);
+       setbits_le32(&phy->ana_cfg1,
+                    SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 |
+                    SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 |
+                    SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2);
 
        /* Note that Allwinner code doesn't fail in case of timeout */
        tmo = timer_get_us() + 2000;
-       while ((readl(&phy->status) & 0x80) == 0) {
+       while ((readl(&phy->ana_sts) & SUN8I_HDMI_PHY_ANA_STS_RCALEND2D) == 0) {
                if (timer_get_us() > tmo) {
                        printf("Warning: HDMI PHY init timeout!\n");
                        break;
                }
        }
 
-       setbits_le32(&phy->ctrl, 0xf << 8);
-       setbits_le32(&phy->ctrl, BIT(7));
+       setbits_le32(&phy->ana_cfg1,
+                    SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 |
+                    SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 |
+                    SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 |
+                    SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK);
+       setbits_le32(&phy->ana_cfg1, SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDSCLK);
 
-       writel(0x39dc5040, &phy->pll);
-       writel(0x80084343, &phy->clk);
-       udelay(10000);
-       writel(1, &phy->unk3);
-       setbits_le32(&phy->pll, BIT(25));
-       udelay(100000);
-       tmp = (readl(&phy->status) & 0x1f800) >> 11;
-       setbits_le32(&phy->pll, BIT(31) | BIT(30));
-       setbits_le32(&phy->pll, tmp);
-       writel(0x01FF0F7F, &phy->ctrl);
-       writel(0x80639000, &phy->unk1);
-       writel(0x0F81C405, &phy->unk2);
+       /* enable DDC communication */
+       writel(SUN8I_HDMI_PHY_ANA_CFG3_SCLEN |
+              SUN8I_HDMI_PHY_ANA_CFG3_SDAEN, &phy->ana_cfg3);
 
-       /* enable read access to HDMI controller */
-       writel(0x54524545, &phy->read_en);
-       /* descramble register offsets */
-       writel(0x42494E47, &phy->unscramble);
+       priv->rcal = readl(&phy->ana_sts) & SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK;
+       priv->rcal >>= 2;
 }
 
 static void sunxi_dw_hdmi_phy_set(struct dw_hdmi *hdmi,
@@ -120,83 +220,130 @@ static void sunxi_dw_hdmi_phy_set(struct dw_hdmi *hdmi,
 {
        struct sunxi_hdmi_phy * const phy =
                (struct sunxi_hdmi_phy *)(hdmi->ioaddr + HDMI_PHY_OFFS);
-       int div = sunxi_dw_hdmi_get_divider(edid->pixelclock.typ);
-       u32 tmp;
+       struct sunxi_dw_hdmi_priv *priv =
+               container_of(hdmi, struct sunxi_dw_hdmi_priv, hdmi);
+       u32 pll_cfg1, pll_cfg2, ana_cfg1, ana_cfg2, ana_cfg3;
+       u32 tmp, b_offset = 0;
 
-       /*
-        * Unfortunately, we don't know much about those magic
-        * numbers. They are taken from Allwinner BSP driver.
-        */
-       switch (div) {
-       case 1:
-               writel(0x30dc5fc0, &phy->pll);
-               writel(0x800863C0 | (phy_div - 1), &phy->clk);
-               mdelay(10);
-               writel(0x00000001, &phy->unk3);
-               setbits_le32(&phy->pll, BIT(25));
-               mdelay(200);
-               tmp = (readl(&phy->status) & 0x1f800) >> 11;
-               setbits_le32(&phy->pll, BIT(31) | BIT(30));
-               if (tmp < 0x3d)
-                       setbits_le32(&phy->pll, tmp + 2);
-               else
-                       setbits_le32(&phy->pll, 0x3f);
-               mdelay(100);
-               writel(0x01FFFF7F, &phy->ctrl);
-               writel(0x8063b000, &phy->unk1);
-               writel(0x0F8246B5, &phy->unk2);
-               break;
-       case 2:
-               writel(0x39dc5040, &phy->pll);
-               writel(0x80084380 | (phy_div - 1), &phy->clk);
-               mdelay(10);
-               writel(0x00000001, &phy->unk3);
-               setbits_le32(&phy->pll, BIT(25));
-               mdelay(100);
-               tmp = (readl(&phy->status) & 0x1f800) >> 11;
-               setbits_le32(&phy->pll, BIT(31) | BIT(30));
-               setbits_le32(&phy->pll, tmp);
-               writel(0x01FFFF7F, &phy->ctrl);
-               writel(0x8063a800, &phy->unk1);
-               writel(0x0F81C485, &phy->unk2);
-               break;
-       case 4:
-               writel(0x39dc5040, &phy->pll);
-               writel(0x80084340 | (phy_div - 1), &phy->clk);
-               mdelay(10);
-               writel(0x00000001, &phy->unk3);
-               setbits_le32(&phy->pll, BIT(25));
-               mdelay(100);
-               tmp = (readl(&phy->status) & 0x1f800) >> 11;
-               setbits_le32(&phy->pll, BIT(31) | BIT(30));
-               setbits_le32(&phy->pll, tmp);
-               writel(0x01FFFF7F, &phy->ctrl);
-               writel(0x8063b000, &phy->unk1);
-               writel(0x0F81C405, &phy->unk2);
-               break;
-       case 11:
-               writel(0x39dc5040, &phy->pll);
-               writel(0x80084300 | (phy_div - 1), &phy->clk);
-               mdelay(10);
-               writel(0x00000001, &phy->unk3);
-               setbits_le32(&phy->pll, BIT(25));
-               mdelay(100);
-               tmp = (readl(&phy->status) & 0x1f800) >> 11;
-               setbits_le32(&phy->pll, BIT(31) | BIT(30));
-               setbits_le32(&phy->pll, tmp);
-               writel(0x01FFFF7F, &phy->ctrl);
-               writel(0x8063b000, &phy->unk1);
-               writel(0x0F81C405, &phy->unk2);
-               break;
+       /* bandwidth / frequency independent settings */
+
+       pll_cfg1 = SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN |
+                  SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN |
+                  SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(7) |
+                  SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(1) |
+                  SUN8I_HDMI_PHY_PLL_CFG1_PLLDBEN |
+                  SUN8I_HDMI_PHY_PLL_CFG1_CS |
+                  SUN8I_HDMI_PHY_PLL_CFG1_CP_S(2) |
+                  SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(63) |
+                  SUN8I_HDMI_PHY_PLL_CFG1_BWS;
+
+       pll_cfg2 = SUN8I_HDMI_PHY_PLL_CFG2_SV_H |
+                  SUN8I_HDMI_PHY_PLL_CFG2_VCOGAIN_EN |
+                  SUN8I_HDMI_PHY_PLL_CFG2_SDIV2;
+
+       ana_cfg1 = SUN8I_HDMI_PHY_ANA_CFG1_REG_SVBH(1) |
+                  SUN8I_HDMI_PHY_ANA_CFG1_AMP_OPT |
+                  SUN8I_HDMI_PHY_ANA_CFG1_EMP_OPT |
+                  SUN8I_HDMI_PHY_ANA_CFG1_AMPCK_OPT |
+                  SUN8I_HDMI_PHY_ANA_CFG1_EMPCK_OPT |
+                  SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL |
+                  SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG |
+                  SUN8I_HDMI_PHY_ANA_CFG1_REG_SCKTMDS |
+                  SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN |
+                  SUN8I_HDMI_PHY_ANA_CFG1_TXEN_ALL |
+                  SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK |
+                  SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 |
+                  SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 |
+                  SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 |
+                  SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2 |
+                  SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 |
+                  SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 |
+                  SUN8I_HDMI_PHY_ANA_CFG1_CKEN |
+                  SUN8I_HDMI_PHY_ANA_CFG1_LDOEN |
+                  SUN8I_HDMI_PHY_ANA_CFG1_ENVBS |
+                  SUN8I_HDMI_PHY_ANA_CFG1_ENBI;
+
+       ana_cfg2 = SUN8I_HDMI_PHY_ANA_CFG2_M_EN |
+                  SUN8I_HDMI_PHY_ANA_CFG2_REG_DENCK |
+                  SUN8I_HDMI_PHY_ANA_CFG2_REG_DEN |
+                  SUN8I_HDMI_PHY_ANA_CFG2_REG_CKSS(1) |
+                  SUN8I_HDMI_PHY_ANA_CFG2_REG_CSMPS(1);
+
+       ana_cfg3 = SUN8I_HDMI_PHY_ANA_CFG3_REG_WIRE(0x3e0) |
+                  SUN8I_HDMI_PHY_ANA_CFG3_SDAEN |
+                  SUN8I_HDMI_PHY_ANA_CFG3_SCLEN;
+
+       /* bandwidth / frequency dependent settings */
+       if (edid->pixelclock.typ <= 27000000) {
+               pll_cfg1 |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 |
+                           SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32);
+               pll_cfg2 |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) |
+                           SUN8I_HDMI_PHY_PLL_CFG2_S(4);
+               ana_cfg1 |= SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW;
+               ana_cfg2 |= SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4) |
+                           SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(priv->rcal);
+               ana_cfg3 |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(3) |
+                           SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(5);
+       } else if (edid->pixelclock.typ <= 74250000) {
+               pll_cfg1 |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 |
+                           SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32);
+               pll_cfg2 |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) |
+                           SUN8I_HDMI_PHY_PLL_CFG2_S(5);
+               ana_cfg1 |= SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW;
+               ana_cfg2 |= SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4) |
+                           SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(priv->rcal);
+               ana_cfg3 |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(5) |
+                           SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(7);
+       } else if (edid->pixelclock.typ <= 148500000) {
+               pll_cfg1 |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 |
+                           SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32);
+               pll_cfg2 |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) |
+                           SUN8I_HDMI_PHY_PLL_CFG2_S(6);
+               ana_cfg2 |= SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK |
+                           SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW |
+                           SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(2);
+               ana_cfg3 |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(7) |
+                           SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(9);
+       } else {
+               b_offset = 2;
+               pll_cfg1 |= SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(63);
+               pll_cfg2 |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(6) |
+                           SUN8I_HDMI_PHY_PLL_CFG2_S(7);
+               ana_cfg2 |= SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK |
+                           SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW |
+                           SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4);
+               ana_cfg3 |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(9) |
+                           SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(13) |
+                           SUN8I_HDMI_PHY_ANA_CFG3_REG_EMP(3);
        }
 
+       writel(pll_cfg1, &phy->pll_cfg1);
+       writel(pll_cfg2 | (phy_div - 1), &phy->pll_cfg2);
+       mdelay(10);
+       writel(SUN8I_HDMI_PHY_PLL_CFG3_SOUT_DIV2, &phy->pll_cfg3);
+       setbits_le32(&phy->pll_cfg1, SUN8I_HDMI_PHY_PLL_CFG1_PLLEN);
+       mdelay(100);
+       tmp = readl(&phy->ana_sts) & SUN8I_HDMI_PHY_ANA_STS_B_OUT_MSK;
+       tmp >>= SUN8I_HDMI_PHY_ANA_STS_B_OUT_SHIFT;
+       tmp = min(tmp + b_offset, (u32)0x3f);
+       setbits_le32(&phy->pll_cfg1,
+                    SUN8I_HDMI_PHY_PLL_CFG1_REG_OD1 |
+                    SUN8I_HDMI_PHY_PLL_CFG1_REG_OD);
+       setbits_le32(&phy->pll_cfg1, tmp);
+       mdelay(100);
+       writel(ana_cfg1, &phy->ana_cfg1);
+       writel(ana_cfg2, &phy->ana_cfg2);
+       writel(ana_cfg3, &phy->ana_cfg3);
+
        if (edid->flags & DISPLAY_FLAGS_VSYNC_LOW)
-               setbits_le32(&phy->pol, 0x200);
+               setbits_le32(&phy->dbg_ctrl,
+                            SUN8I_HDMI_PHY_DBG_CTRL_POL_NVSYNC);
 
        if (edid->flags & DISPLAY_FLAGS_HSYNC_LOW)
-               setbits_le32(&phy->pol, 0x100);
+               setbits_le32(&phy->dbg_ctrl,
+                            SUN8I_HDMI_PHY_DBG_CTRL_POL_NHSYNC);
 
-       setbits_le32(&phy->ctrl, 0xf << 12);
+       setbits_le32(&phy->ana_cfg1, SUN8I_HDMI_PHY_ANA_CFG1_TXEN_ALL);
 }
 
 static void sunxi_dw_hdmi_pll_set(uint clk_khz, int *phy_div)
@@ -363,7 +510,7 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
        /* Clock on */
        setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
 
-       sunxi_dw_hdmi_phy_init(&priv->hdmi);
+       sunxi_dw_hdmi_phy_init(priv);
 
        priv->mux = uc_plat->source_id;
 
-- 
2.30.1

Reply via email to