xref: /openbsd-src/sys/dev/ic/dwhdmiphy.c (revision 7137d9bb155774a6d8722e4853eceeb2045bcd3d)
1*7137d9bbSderaadt /* $OpenBSD: dwhdmiphy.c,v 1.3 2020/06/30 02:19:12 deraadt Exp $ */
26a2cdf39Skettenis /* $NetBSD: dw_hdmi_phy.c,v 1.2 2019/11/10 10:36:01 jmcneill Exp $ */
36a2cdf39Skettenis 
46a2cdf39Skettenis /*-
56a2cdf39Skettenis  * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org>
66a2cdf39Skettenis  * All rights reserved.
76a2cdf39Skettenis  *
86a2cdf39Skettenis  * Redistribution and use in source and binary forms, with or without
96a2cdf39Skettenis  * modification, are permitted provided that the following conditions
106a2cdf39Skettenis  * are met:
116a2cdf39Skettenis  * 1. Redistributions of source code must retain the above copyright
126a2cdf39Skettenis  *    notice, this list of conditions and the following disclaimer.
136a2cdf39Skettenis  * 2. Redistributions in binary form must reproduce the above copyright
146a2cdf39Skettenis  *    notice, this list of conditions and the following disclaimer in the
156a2cdf39Skettenis  *    documentation and/or other materials provided with the distribution.
166a2cdf39Skettenis  *
176a2cdf39Skettenis  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
186a2cdf39Skettenis  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
196a2cdf39Skettenis  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
206a2cdf39Skettenis  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
216a2cdf39Skettenis  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
226a2cdf39Skettenis  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
236a2cdf39Skettenis  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
246a2cdf39Skettenis  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
256a2cdf39Skettenis  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
266a2cdf39Skettenis  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
276a2cdf39Skettenis  * SUCH DAMAGE.
286a2cdf39Skettenis  */
296a2cdf39Skettenis 
306a2cdf39Skettenis #include <sys/param.h>
316a2cdf39Skettenis 
326a2cdf39Skettenis #include <dev/ic/dwhdmi.h>
336a2cdf39Skettenis 
346a2cdf39Skettenis #define	HDMI_IH_PHY_STAT0                       0x0104
356a2cdf39Skettenis #define	  HDMI_IH_PHY_STAT0_HPD (1 << 0)
366a2cdf39Skettenis #define	HDMI_IH_I2CMPHY_STAT0                   0x0108
376a2cdf39Skettenis #define	  HDMI_IH_I2CMPHY_STAT0_DONE            (1 << 1)
386a2cdf39Skettenis #define	  HDMI_IH_I2CMPHY_STAT0_ERROR           (1 << 0)
396a2cdf39Skettenis 
406a2cdf39Skettenis #define	HDMI_PHY_CONF0				0x3000
416a2cdf39Skettenis #define	  HDMI_PHY_CONF0_PDZ_MASK			0x80
426a2cdf39Skettenis #define	  HDMI_PHY_CONF0_PDZ_OFFSET		7
436a2cdf39Skettenis #define	  HDMI_PHY_CONF0_ENTMDS_MASK		0x40
446a2cdf39Skettenis #define	  HDMI_PHY_CONF0_ENTMDS_OFFSET		6
456a2cdf39Skettenis #define	  HDMI_PHY_CONF0_SVSRET_MASK		0x20
466a2cdf39Skettenis #define	  HDMI_PHY_CONF0_SVSRET_OFFSET			5
476a2cdf39Skettenis #define	  HDMI_PHY_CONF0_GEN2_PDDQ_MASK		0x10
486a2cdf39Skettenis #define	  HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET		4
496a2cdf39Skettenis #define	  HDMI_PHY_CONF0_GEN2_TXPWRON_MASK	0x8
506a2cdf39Skettenis #define	  HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET	3
516a2cdf39Skettenis #define	  HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK	0x4
526a2cdf39Skettenis #define	  HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET	2
536a2cdf39Skettenis #define	  HDMI_PHY_CONF0_SELDATAENPOL_MASK	0x2
546a2cdf39Skettenis #define	  HDMI_PHY_CONF0_SELDATAENPOL_OFFSET	1
556a2cdf39Skettenis #define	  HDMI_PHY_CONF0_SELDIPIF_MASK		0x1
566a2cdf39Skettenis #define	  HDMI_PHY_CONF0_SELDIPIF_OFFSET		0
576a2cdf39Skettenis #define	HDMI_PHY_TST0				0x3001
586a2cdf39Skettenis #define	  HDMI_PHY_TST0_TSTCLR_MASK		0x20
596a2cdf39Skettenis #define	  HDMI_PHY_TST0_TSTCLR_OFFSET		5
606a2cdf39Skettenis #define	  HDMI_PHY_TST0_TSTEN_MASK		0x10
616a2cdf39Skettenis #define	  HDMI_PHY_TST0_TSTEN_OFFSET		4
626a2cdf39Skettenis #define	  HDMI_PHY_TST0_TSTCLK_MASK		0x1
636a2cdf39Skettenis #define	  HDMI_PHY_TST0_TSTCLK_OFFSET		0
646a2cdf39Skettenis #define	HDMI_PHY_TST1				0x3002
656a2cdf39Skettenis #define	HDMI_PHY_TST2				0x3003
666a2cdf39Skettenis #define	HDMI_PHY_STAT0				0x3004
676a2cdf39Skettenis #define	  HDMI_PHY_STAT0_RX_SENSE3		0x80
686a2cdf39Skettenis #define	  HDMI_PHY_STAT0_RX_SENSE2		0x40
696a2cdf39Skettenis #define	  HDMI_PHY_STAT0_RX_SENSE1		0x20
706a2cdf39Skettenis #define	  HDMI_PHY_STAT0_RX_SENSE0		0x10
716a2cdf39Skettenis #define	  HDMI_PHY_STAT0_RX_SENSE		0xf0
726a2cdf39Skettenis #define	  HDMI_PHY_STAT0_HPD			0x02
736a2cdf39Skettenis #define	  HDMI_PHY_TX_PHY_LOCK			0x01
746a2cdf39Skettenis #define	HDMI_PHY_INT0				0x3005
756a2cdf39Skettenis #define	HDMI_PHY_MASK0				0x3006
766a2cdf39Skettenis #define	HDMI_PHY_POL0				0x3007
776a2cdf39Skettenis #define	  HDMI_PHY_POL0_HPD			0x02
786a2cdf39Skettenis 
796a2cdf39Skettenis /* HDMI Master PHY Registers */
806a2cdf39Skettenis #define	HDMI_PHY_I2CM_SLAVE_ADDR		0x3020
816a2cdf39Skettenis #define	  HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2	0x69
826a2cdf39Skettenis #define	  HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY	0x49
836a2cdf39Skettenis #define	HDMI_PHY_I2CM_ADDRESS_ADDR		0x3021
846a2cdf39Skettenis #define	HDMI_PHY_I2CM_DATAO_1_ADDR		0x3022
856a2cdf39Skettenis #define	HDMI_PHY_I2CM_DATAO_0_ADDR		0x3023
866a2cdf39Skettenis #define	HDMI_PHY_I2CM_DATAI_1_ADDR		0x3024
876a2cdf39Skettenis #define	HDMI_PHY_I2CM_DATAI_0_ADDR		0x3025
886a2cdf39Skettenis #define	HDMI_PHY_I2CM_OPERATION_ADDR		0x3026
896a2cdf39Skettenis #define	  HDMI_PHY_I2CM_OPERATION_ADDR_WRITE    0x10
906a2cdf39Skettenis #define	  HDMI_PHY_I2CM_OPERATION_ADDR_READ     0x1
916a2cdf39Skettenis #define	HDMI_PHY_I2CM_INT_ADDR			0x3027
926a2cdf39Skettenis #define	HDMI_PHY_I2CM_CTLINT_ADDR		0x3028
936a2cdf39Skettenis #define	HDMI_PHY_I2CM_DIV_ADDR			0x3029
946a2cdf39Skettenis #define	HDMI_PHY_I2CM_SOFTRSTZ_ADDR		0x302a
956a2cdf39Skettenis #define	HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR	0x302b
966a2cdf39Skettenis #define	HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR	0x302c
976a2cdf39Skettenis #define	HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR	0x302d
986a2cdf39Skettenis #define	HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR	0x302e
996a2cdf39Skettenis #define	HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR	0x302f
1006a2cdf39Skettenis #define	HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR	0x3030
1016a2cdf39Skettenis #define	HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR	0x3031
1026a2cdf39Skettenis #define	HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR	0x3032
1036a2cdf39Skettenis 
1046a2cdf39Skettenis #define	HDMI_MC_FLOWCTRL                        0x4004
1056a2cdf39Skettenis #define	  HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK                0x1
1066a2cdf39Skettenis #define	  HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH 0x1
1076a2cdf39Skettenis #define	  HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS  0x0
1086a2cdf39Skettenis #define	HDMI_MC_PHYRSTZ                         0x4005
1096a2cdf39Skettenis #define	  HDMI_MC_PHYRSTZ_ASSERT                        0x0
1106a2cdf39Skettenis #define	  HDMI_MC_PHYRSTZ_DEASSERT              0x1
1116a2cdf39Skettenis #define	HDMI_MC_HEACPHY_RST                     0x4007
1126a2cdf39Skettenis #define	  HDMI_MC_HEACPHY_RST_ASSERT            0x1
1136a2cdf39Skettenis #define	  HDMI_MC_HEACPHY_RST_DEASSERT          0x0
1146a2cdf39Skettenis 
1156a2cdf39Skettenis /* HDMI PHY register with access through I2C */
1166a2cdf39Skettenis #define	HDMI_PHY_I2C_CKCALCTRL	0x5
1176a2cdf39Skettenis #define	  CKCALCTRL_OVERRIDE	(1 << 15)
1186a2cdf39Skettenis #define	HDMI_PHY_I2C_CPCE_CTRL	0x6
1196a2cdf39Skettenis #define	  CPCE_CTRL_45_25		((3 << 7) | (3 << 5))
1206a2cdf39Skettenis #define	  CPCE_CTRL_92_50		((2 << 7) | (2 << 5))
1216a2cdf39Skettenis #define	  CPCE_CTRL_185		((1 << 7) | (1 << 5))
1226a2cdf39Skettenis #define	  CPCE_CTRL_370		((0 << 7) | (0 << 5))
1236a2cdf39Skettenis #define	HDMI_PHY_I2C_CKSYMTXCTRL	0x9
1246a2cdf39Skettenis #define	  CKSYMTXCTRL_OVERRIDE	(1 << 15)
1256a2cdf39Skettenis #define	  CKSYMTXCTRL_TX_SYMON	(1 << 3)
1266a2cdf39Skettenis #define	  CKSYMTXCTRL_TX_TRAON	(1 << 2)
1276a2cdf39Skettenis #define	  CKSYMTXCTRL_TX_TRBON	(1 << 1)
1286a2cdf39Skettenis #define	  CKSYMTXCTRL_TX_CK_SYMON	(1 << 0)
1296a2cdf39Skettenis #define	HDMI_PHY_I2C_VLEVCTRL		0x0E
1306a2cdf39Skettenis #define	HDMI_PHY_I2C_CURRCTRL		0x10
1316a2cdf39Skettenis #define	HDMI_PHY_I2C_PLLPHBYCTRL	0x13
1326a2cdf39Skettenis #define	  VLEVCTRL_TX_LVL(x)	((x) << 5)
1336a2cdf39Skettenis #define	  VLEVCTRL_CK_LVL(x)	(x)
1346a2cdf39Skettenis #define	HDMI_PHY_I2C_GMPCTRL	0x15
1356a2cdf39Skettenis #define	  GMPCTRL_45_25		0x00
1366a2cdf39Skettenis #define	  GMPCTRL_92_50		0x05
1376a2cdf39Skettenis #define	  GMPCTRL_185		0x0a
1386a2cdf39Skettenis #define	  GMPCTRL_370		0x0f
1396a2cdf39Skettenis #define	HDMI_PHY_I2C_MSM_CTRL	0x17
1406a2cdf39Skettenis #define	  MSM_CTRL_FB_CLK		(0x3 << 1)
1416a2cdf39Skettenis #define	HDMI_PHY_I2C_TXTERM	0x19
1426a2cdf39Skettenis #define	  TXTERM_133		0x5
1436a2cdf39Skettenis 
1446a2cdf39Skettenis void
dwhdmi_phy_wait_i2c_done(struct dwhdmi_softc * sc,int msec)1456a2cdf39Skettenis dwhdmi_phy_wait_i2c_done(struct dwhdmi_softc *sc, int msec)
1466a2cdf39Skettenis {
1476a2cdf39Skettenis 	uint8_t val;
1486a2cdf39Skettenis 
1496a2cdf39Skettenis 	val = dwhdmi_read(sc, HDMI_IH_I2CMPHY_STAT0) &
1506a2cdf39Skettenis 	    (HDMI_IH_I2CMPHY_STAT0_DONE | HDMI_IH_I2CMPHY_STAT0_ERROR);
1516a2cdf39Skettenis 	while (val == 0) {
1526a2cdf39Skettenis 		delay(1000);
1536a2cdf39Skettenis 		msec -= 10;
1546a2cdf39Skettenis 		if (msec <= 0)
1556a2cdf39Skettenis 			return;
1566a2cdf39Skettenis 		val = dwhdmi_read(sc, HDMI_IH_I2CMPHY_STAT0) &
1576a2cdf39Skettenis 		    (HDMI_IH_I2CMPHY_STAT0_DONE | HDMI_IH_I2CMPHY_STAT0_ERROR);
1586a2cdf39Skettenis 	}
1596a2cdf39Skettenis }
1606a2cdf39Skettenis 
1616a2cdf39Skettenis void
dwhdmi_phy_i2c_write(struct dwhdmi_softc * sc,unsigned short data,unsigned char addr)1626a2cdf39Skettenis dwhdmi_phy_i2c_write(struct dwhdmi_softc *sc, unsigned short data,
1636a2cdf39Skettenis     unsigned char addr)
1646a2cdf39Skettenis {
1656a2cdf39Skettenis 
1666a2cdf39Skettenis 	/* clear DONE and ERROR flags */
1676a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_IH_I2CMPHY_STAT0,
1686a2cdf39Skettenis 	    HDMI_IH_I2CMPHY_STAT0_DONE | HDMI_IH_I2CMPHY_STAT0_ERROR);
1696a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_I2CM_ADDRESS_ADDR, addr);
1706a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_I2CM_DATAO_1_ADDR, ((data >> 8) & 0xff));
1716a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_I2CM_DATAO_0_ADDR, ((data >> 0) & 0xff));
1726a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_I2CM_OPERATION_ADDR, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE);
1736a2cdf39Skettenis 	dwhdmi_phy_wait_i2c_done(sc, 1000);
1746a2cdf39Skettenis }
1756a2cdf39Skettenis 
1766a2cdf39Skettenis void
dwhdmi_phy_enable_power(struct dwhdmi_softc * sc,uint8_t enable)1776a2cdf39Skettenis dwhdmi_phy_enable_power(struct dwhdmi_softc *sc, uint8_t enable)
1786a2cdf39Skettenis {
1796a2cdf39Skettenis 	uint8_t reg;
1806a2cdf39Skettenis 
1816a2cdf39Skettenis 	reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
1826a2cdf39Skettenis 	reg &= ~HDMI_PHY_CONF0_PDZ_MASK;
1836a2cdf39Skettenis 	reg |= (enable << HDMI_PHY_CONF0_PDZ_OFFSET);
1846a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
1856a2cdf39Skettenis }
1866a2cdf39Skettenis 
1876a2cdf39Skettenis void
dwhdmi_phy_enable_tmds(struct dwhdmi_softc * sc,uint8_t enable)1886a2cdf39Skettenis dwhdmi_phy_enable_tmds(struct dwhdmi_softc *sc, uint8_t enable)
1896a2cdf39Skettenis {
1906a2cdf39Skettenis 	uint8_t reg;
1916a2cdf39Skettenis 
1926a2cdf39Skettenis 	reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
1936a2cdf39Skettenis 	reg &= ~HDMI_PHY_CONF0_ENTMDS_MASK;
1946a2cdf39Skettenis 	reg |= (enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
1956a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
1966a2cdf39Skettenis }
1976a2cdf39Skettenis 
1986a2cdf39Skettenis void
dwhdmi_phy_gen2_pddq(struct dwhdmi_softc * sc,uint8_t enable)1996a2cdf39Skettenis dwhdmi_phy_gen2_pddq(struct dwhdmi_softc *sc, uint8_t enable)
2006a2cdf39Skettenis {
2016a2cdf39Skettenis 	uint8_t reg;
2026a2cdf39Skettenis 
2036a2cdf39Skettenis 	reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
2046a2cdf39Skettenis 	reg &= ~HDMI_PHY_CONF0_GEN2_PDDQ_MASK;
2056a2cdf39Skettenis 	reg |= (enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
2066a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
2076a2cdf39Skettenis }
2086a2cdf39Skettenis 
2096a2cdf39Skettenis void
dwhdmi_phy_gen2_txpwron(struct dwhdmi_softc * sc,uint8_t enable)2106a2cdf39Skettenis dwhdmi_phy_gen2_txpwron(struct dwhdmi_softc *sc, uint8_t enable)
2116a2cdf39Skettenis {
2126a2cdf39Skettenis 	uint8_t reg;
2136a2cdf39Skettenis 
2146a2cdf39Skettenis 	reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
2156a2cdf39Skettenis 	reg &= ~HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
2166a2cdf39Skettenis 	reg |= (enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
2176a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
2186a2cdf39Skettenis }
2196a2cdf39Skettenis 
2206a2cdf39Skettenis void
dwhdmi_phy_sel_data_en_pol(struct dwhdmi_softc * sc,uint8_t enable)2216a2cdf39Skettenis dwhdmi_phy_sel_data_en_pol(struct dwhdmi_softc *sc, uint8_t enable)
2226a2cdf39Skettenis {
2236a2cdf39Skettenis 	uint8_t reg;
2246a2cdf39Skettenis 
2256a2cdf39Skettenis 	reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
2266a2cdf39Skettenis 	reg &= ~HDMI_PHY_CONF0_SELDATAENPOL_MASK;
2276a2cdf39Skettenis 	reg |= (enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
2286a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
2296a2cdf39Skettenis }
2306a2cdf39Skettenis 
2316a2cdf39Skettenis void
dwhdmi_phy_sel_interface_control(struct dwhdmi_softc * sc,uint8_t enable)2326a2cdf39Skettenis dwhdmi_phy_sel_interface_control(struct dwhdmi_softc *sc, uint8_t enable)
2336a2cdf39Skettenis {
2346a2cdf39Skettenis 	uint8_t reg;
2356a2cdf39Skettenis 
2366a2cdf39Skettenis 	reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
2376a2cdf39Skettenis 	reg &= ~HDMI_PHY_CONF0_SELDIPIF_MASK;
2386a2cdf39Skettenis 	reg |= (enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
2396a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
2406a2cdf39Skettenis }
2416a2cdf39Skettenis 
2426a2cdf39Skettenis void
dwhdmi_phy_enable_svsret(struct dwhdmi_softc * sc,uint8_t enable)2436a2cdf39Skettenis dwhdmi_phy_enable_svsret(struct dwhdmi_softc *sc, uint8_t enable)
2446a2cdf39Skettenis {
2456a2cdf39Skettenis 	uint8_t reg;
2466a2cdf39Skettenis 
2476a2cdf39Skettenis 	reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
2486a2cdf39Skettenis 	reg &= ~HDMI_PHY_CONF0_SVSRET_MASK;
2496a2cdf39Skettenis 	reg |= (enable << HDMI_PHY_CONF0_SVSRET_OFFSET);
2506a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
2516a2cdf39Skettenis }
2526a2cdf39Skettenis 
2536a2cdf39Skettenis void
dwhdmi_phy_test_clear(struct dwhdmi_softc * sc,unsigned char bit)2546a2cdf39Skettenis dwhdmi_phy_test_clear(struct dwhdmi_softc *sc, unsigned char bit)
2556a2cdf39Skettenis {
2566a2cdf39Skettenis 	uint8_t val;
2576a2cdf39Skettenis 
2586a2cdf39Skettenis 	val = dwhdmi_read(sc, HDMI_PHY_TST0);
2596a2cdf39Skettenis 	val &= ~HDMI_PHY_TST0_TSTCLR_MASK;
2606a2cdf39Skettenis 	val |= (bit << HDMI_PHY_TST0_TSTCLR_OFFSET) &
2616a2cdf39Skettenis 		HDMI_PHY_TST0_TSTCLR_MASK;
2626a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_TST0, val);
2636a2cdf39Skettenis }
2646a2cdf39Skettenis 
2656a2cdf39Skettenis int
dwhdmi_phy_configure(struct dwhdmi_softc * sc,const struct drm_display_mode * mode)266*7137d9bbSderaadt dwhdmi_phy_configure(struct dwhdmi_softc *sc, const struct drm_display_mode *mode)
2676a2cdf39Skettenis {
2686a2cdf39Skettenis 	const struct dwhdmi_mpll_config *mpll_conf;
2696a2cdf39Skettenis 	const struct dwhdmi_phy_config *phy_conf;
2706a2cdf39Skettenis 	uint8_t val;
2716a2cdf39Skettenis 	uint8_t msec;
2726a2cdf39Skettenis 
2736a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_MC_FLOWCTRL, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS);
2746a2cdf39Skettenis 
2756a2cdf39Skettenis 	/* gen2 tx power off */
2766a2cdf39Skettenis 	dwhdmi_phy_gen2_txpwron(sc, 0);
2776a2cdf39Skettenis 
2786a2cdf39Skettenis 	/* gen2 pddq */
2796a2cdf39Skettenis 	dwhdmi_phy_gen2_pddq(sc, 1);
2806a2cdf39Skettenis 
2816a2cdf39Skettenis 	/* PHY reset */
2826a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_MC_PHYRSTZ, HDMI_MC_PHYRSTZ_DEASSERT);
2836a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_MC_PHYRSTZ, HDMI_MC_PHYRSTZ_ASSERT);
2846a2cdf39Skettenis 
2856a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_MC_HEACPHY_RST, HDMI_MC_HEACPHY_RST_ASSERT);
2866a2cdf39Skettenis 
2876a2cdf39Skettenis 	dwhdmi_phy_test_clear(sc, 1);
2886a2cdf39Skettenis 	dwhdmi_write(sc, HDMI_PHY_I2CM_SLAVE_ADDR, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2);
2896a2cdf39Skettenis 	dwhdmi_phy_test_clear(sc, 0);
2906a2cdf39Skettenis 
2916a2cdf39Skettenis 	/*
2926a2cdf39Skettenis 	 * Following initialization are for 8bit per color case
2936a2cdf39Skettenis 	 */
2946a2cdf39Skettenis 
2956a2cdf39Skettenis 	/*
2966a2cdf39Skettenis 	 * PLL/MPLL config
2976a2cdf39Skettenis 	 */
2986a2cdf39Skettenis 	for (mpll_conf = &sc->sc_mpll_config[0]; mpll_conf->pixel_clock != 0; mpll_conf++)
2996a2cdf39Skettenis 		if (mode->clock <= mpll_conf->pixel_clock)
3006a2cdf39Skettenis 			break;
3016a2cdf39Skettenis 
3026a2cdf39Skettenis 	dwhdmi_phy_i2c_write(sc, mpll_conf->cpce, HDMI_PHY_I2C_CPCE_CTRL);
3036a2cdf39Skettenis 	dwhdmi_phy_i2c_write(sc, mpll_conf->gmp, HDMI_PHY_I2C_GMPCTRL);
3046a2cdf39Skettenis 	dwhdmi_phy_i2c_write(sc, mpll_conf->curr, HDMI_PHY_I2C_CURRCTRL);
3056a2cdf39Skettenis 
3066a2cdf39Skettenis 	for (phy_conf = &sc->sc_phy_config[0]; phy_conf->pixel_clock != 0; phy_conf++)
3076a2cdf39Skettenis 		if (mode->clock <= phy_conf->pixel_clock)
3086a2cdf39Skettenis 			break;
3096a2cdf39Skettenis 
3106a2cdf39Skettenis 	dwhdmi_phy_i2c_write(sc, 0x0000, HDMI_PHY_I2C_PLLPHBYCTRL);
3116a2cdf39Skettenis 	dwhdmi_phy_i2c_write(sc, MSM_CTRL_FB_CLK, HDMI_PHY_I2C_MSM_CTRL);
3126a2cdf39Skettenis 
3136a2cdf39Skettenis 	dwhdmi_phy_i2c_write(sc, phy_conf->term, HDMI_PHY_I2C_TXTERM);
3146a2cdf39Skettenis 	dwhdmi_phy_i2c_write(sc, phy_conf->sym, HDMI_PHY_I2C_CKSYMTXCTRL);
3156a2cdf39Skettenis 	dwhdmi_phy_i2c_write(sc, phy_conf->vlev, HDMI_PHY_I2C_VLEVCTRL);
3166a2cdf39Skettenis 
3176a2cdf39Skettenis 	/* REMOVE CLK TERM */
3186a2cdf39Skettenis 	dwhdmi_phy_i2c_write(sc, CKCALCTRL_OVERRIDE, HDMI_PHY_I2C_CKCALCTRL);
3196a2cdf39Skettenis 
3206a2cdf39Skettenis 	dwhdmi_phy_enable_power(sc, 1);
3216a2cdf39Skettenis 
3226a2cdf39Skettenis 	/* toggle TMDS enable */
3236a2cdf39Skettenis 	dwhdmi_phy_enable_tmds(sc, 0);
3246a2cdf39Skettenis 	dwhdmi_phy_enable_tmds(sc, 1);
3256a2cdf39Skettenis 
3266a2cdf39Skettenis 	/* gen2 tx power on */
3276a2cdf39Skettenis 	dwhdmi_phy_gen2_txpwron(sc, 1);
3286a2cdf39Skettenis 	dwhdmi_phy_gen2_pddq(sc, 0);
3296a2cdf39Skettenis 
3306a2cdf39Skettenis 	switch (sc->sc_phytype) {
3316a2cdf39Skettenis 	case 0xb2:	/* MHL PHY HEAC */
3326a2cdf39Skettenis 	case 0xc2:	/* MHL PHY */
3336a2cdf39Skettenis 	case 0xf3:	/* HDMI 2.0 TX PHY */
3346a2cdf39Skettenis 		dwhdmi_phy_enable_svsret(sc, 1);
3356a2cdf39Skettenis 		break;
3366a2cdf39Skettenis 	}
3376a2cdf39Skettenis 
3386a2cdf39Skettenis 	/*Wait for PHY PLL lock */
3396a2cdf39Skettenis 	msec = 4;
3406a2cdf39Skettenis 	val = dwhdmi_read(sc, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
3416a2cdf39Skettenis 	while (val == 0) {
3426a2cdf39Skettenis 		delay(1000);
3436a2cdf39Skettenis 		if (msec-- == 0) {
3446a2cdf39Skettenis 			printf("%s: PHY PLL not locked\n",
3456a2cdf39Skettenis 			    sc->sc_dev.dv_xname);
3466a2cdf39Skettenis 			return (-1);
3476a2cdf39Skettenis 		}
3486a2cdf39Skettenis 		val = dwhdmi_read(sc, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
3496a2cdf39Skettenis 	}
3506a2cdf39Skettenis 
3516a2cdf39Skettenis 	return (0);
3526a2cdf39Skettenis }
3536a2cdf39Skettenis 
3546a2cdf39Skettenis void
dwhdmi_phy_init(struct dwhdmi_softc * sc,const struct drm_display_mode * mode)355*7137d9bbSderaadt dwhdmi_phy_init(struct dwhdmi_softc *sc, const struct drm_display_mode *mode)
3566a2cdf39Skettenis {
3576a2cdf39Skettenis 	int i;
3586a2cdf39Skettenis 
3596a2cdf39Skettenis 	/* HDMI Phy spec says to do the phy initialization sequence twice */
3606a2cdf39Skettenis 	for (i = 0 ; i < 2 ; i++) {
3616a2cdf39Skettenis 		dwhdmi_phy_sel_data_en_pol(sc, 1);
3626a2cdf39Skettenis 		dwhdmi_phy_sel_interface_control(sc, 0);
3636a2cdf39Skettenis 		dwhdmi_phy_enable_tmds(sc, 0);
3646a2cdf39Skettenis 		dwhdmi_phy_enable_power(sc, 0);
3656a2cdf39Skettenis 
3666a2cdf39Skettenis 		/* Enable CSC */
3676a2cdf39Skettenis 		dwhdmi_phy_configure(sc, mode);
3686a2cdf39Skettenis 	}
3696a2cdf39Skettenis }
3706a2cdf39Skettenis 
3716a2cdf39Skettenis enum drm_connector_status
dwhdmi_phy_detect(struct dwhdmi_softc * sc,int force)3726a2cdf39Skettenis dwhdmi_phy_detect(struct dwhdmi_softc *sc, int force)
3736a2cdf39Skettenis {
3746a2cdf39Skettenis 	uint8_t val;
3756a2cdf39Skettenis 
3766a2cdf39Skettenis 	val = dwhdmi_read(sc, HDMI_PHY_STAT0);
3776a2cdf39Skettenis 
3786a2cdf39Skettenis 	return ((val & HDMI_PHY_STAT0_HPD) != 0) ?
3796a2cdf39Skettenis 	    connector_status_connected :
3806a2cdf39Skettenis 	    connector_status_disconnected;
3816a2cdf39Skettenis }
3826a2cdf39Skettenis 
3836a2cdf39Skettenis void
dwhdmi_phy_enable(struct dwhdmi_softc * sc)3846a2cdf39Skettenis dwhdmi_phy_enable(struct dwhdmi_softc *sc)
3856a2cdf39Skettenis {
3866a2cdf39Skettenis }
3876a2cdf39Skettenis 
3886a2cdf39Skettenis void
dwhdmi_phy_disable(struct dwhdmi_softc * sc)3896a2cdf39Skettenis dwhdmi_phy_disable(struct dwhdmi_softc *sc)
3906a2cdf39Skettenis {
3916a2cdf39Skettenis }
3926a2cdf39Skettenis 
3936a2cdf39Skettenis void
dwhdmi_phy_mode_set(struct dwhdmi_softc * sc,const struct drm_display_mode * mode,const struct drm_display_mode * adjusted_mode)3946a2cdf39Skettenis dwhdmi_phy_mode_set(struct dwhdmi_softc *sc,
395*7137d9bbSderaadt     const struct drm_display_mode *mode, const struct drm_display_mode *adjusted_mode)
3966a2cdf39Skettenis {
3976a2cdf39Skettenis 	dwhdmi_phy_init(sc, adjusted_mode);
3986a2cdf39Skettenis }
399