[PATCH 14/19] video: sunxi: dw-hdmi: rework PHY initialization
Jernej Skrabec
jernej.skrabec at siol.net
Tue Feb 23 21:46:26 CET 2021
Now that bit meanings are somewhat known, rework PHY initialization.
This is modelled after Linux driver.
Signed-off-by: Jernej Skrabec <jernej.skrabec at 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
More information about the U-Boot
mailing list