dw_hdmi_phy.c revision 1.2 1 1.2 jmcneill /* $NetBSD: dw_hdmi_phy.c,v 1.2 2019/11/10 10:36:01 jmcneill Exp $ */
2 1.1 jmcneill
3 1.1 jmcneill /*-
4 1.1 jmcneill * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo (at) freebsd.org>
5 1.1 jmcneill * All rights reserved.
6 1.1 jmcneill *
7 1.1 jmcneill * Redistribution and use in source and binary forms, with or without
8 1.1 jmcneill * modification, are permitted provided that the following conditions
9 1.1 jmcneill * are met:
10 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright
11 1.1 jmcneill * notice, this list of conditions and the following disclaimer.
12 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the
14 1.1 jmcneill * documentation and/or other materials provided with the distribution.
15 1.1 jmcneill *
16 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 1.1 jmcneill * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 1.1 jmcneill * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 1.1 jmcneill * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 1.1 jmcneill * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 1.1 jmcneill * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 1.1 jmcneill * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 1.1 jmcneill * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 1.1 jmcneill * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.1 jmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.1 jmcneill * SUCH DAMAGE.
27 1.1 jmcneill */
28 1.1 jmcneill
29 1.1 jmcneill #include <sys/cdefs.h>
30 1.2 jmcneill __KERNEL_RCSID(0, "$NetBSD: dw_hdmi_phy.c,v 1.2 2019/11/10 10:36:01 jmcneill Exp $");
31 1.1 jmcneill
32 1.1 jmcneill #include <sys/param.h>
33 1.1 jmcneill
34 1.1 jmcneill #include <drm/drmP.h>
35 1.1 jmcneill
36 1.1 jmcneill #include <dev/ic/dw_hdmi.h>
37 1.1 jmcneill
38 1.1 jmcneill #define HDMI_IH_PHY_STAT0 0x0104
39 1.1 jmcneill #define HDMI_IH_PHY_STAT0_HPD (1 << 0)
40 1.1 jmcneill #define HDMI_IH_I2CMPHY_STAT0 0x0108
41 1.1 jmcneill #define HDMI_IH_I2CMPHY_STAT0_DONE (1 << 1)
42 1.1 jmcneill #define HDMI_IH_I2CMPHY_STAT0_ERROR (1 << 0)
43 1.1 jmcneill
44 1.1 jmcneill #define HDMI_PHY_CONF0 0x3000
45 1.1 jmcneill #define HDMI_PHY_CONF0_PDZ_MASK 0x80
46 1.1 jmcneill #define HDMI_PHY_CONF0_PDZ_OFFSET 7
47 1.1 jmcneill #define HDMI_PHY_CONF0_ENTMDS_MASK 0x40
48 1.1 jmcneill #define HDMI_PHY_CONF0_ENTMDS_OFFSET 6
49 1.1 jmcneill #define HDMI_PHY_CONF0_SVSRET_MASK 0x20
50 1.1 jmcneill #define HDMI_PHY_CONF0_SVSRET_OFFSET 5
51 1.1 jmcneill #define HDMI_PHY_CONF0_GEN2_PDDQ_MASK 0x10
52 1.1 jmcneill #define HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET 4
53 1.1 jmcneill #define HDMI_PHY_CONF0_GEN2_TXPWRON_MASK 0x8
54 1.1 jmcneill #define HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET 3
55 1.1 jmcneill #define HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK 0x4
56 1.1 jmcneill #define HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET 2
57 1.1 jmcneill #define HDMI_PHY_CONF0_SELDATAENPOL_MASK 0x2
58 1.1 jmcneill #define HDMI_PHY_CONF0_SELDATAENPOL_OFFSET 1
59 1.1 jmcneill #define HDMI_PHY_CONF0_SELDIPIF_MASK 0x1
60 1.1 jmcneill #define HDMI_PHY_CONF0_SELDIPIF_OFFSET 0
61 1.1 jmcneill #define HDMI_PHY_TST0 0x3001
62 1.1 jmcneill #define HDMI_PHY_TST0_TSTCLR_MASK 0x20
63 1.1 jmcneill #define HDMI_PHY_TST0_TSTCLR_OFFSET 5
64 1.1 jmcneill #define HDMI_PHY_TST0_TSTEN_MASK 0x10
65 1.1 jmcneill #define HDMI_PHY_TST0_TSTEN_OFFSET 4
66 1.1 jmcneill #define HDMI_PHY_TST0_TSTCLK_MASK 0x1
67 1.1 jmcneill #define HDMI_PHY_TST0_TSTCLK_OFFSET 0
68 1.1 jmcneill #define HDMI_PHY_TST1 0x3002
69 1.1 jmcneill #define HDMI_PHY_TST2 0x3003
70 1.1 jmcneill #define HDMI_PHY_STAT0 0x3004
71 1.1 jmcneill #define HDMI_PHY_STAT0_RX_SENSE3 0x80
72 1.1 jmcneill #define HDMI_PHY_STAT0_RX_SENSE2 0x40
73 1.1 jmcneill #define HDMI_PHY_STAT0_RX_SENSE1 0x20
74 1.1 jmcneill #define HDMI_PHY_STAT0_RX_SENSE0 0x10
75 1.1 jmcneill #define HDMI_PHY_STAT0_RX_SENSE 0xf0
76 1.1 jmcneill #define HDMI_PHY_STAT0_HPD 0x02
77 1.1 jmcneill #define HDMI_PHY_TX_PHY_LOCK 0x01
78 1.1 jmcneill #define HDMI_PHY_INT0 0x3005
79 1.1 jmcneill #define HDMI_PHY_MASK0 0x3006
80 1.1 jmcneill #define HDMI_PHY_POL0 0x3007
81 1.1 jmcneill #define HDMI_PHY_POL0_HPD 0x02
82 1.1 jmcneill
83 1.1 jmcneill /* HDMI Master PHY Registers */
84 1.1 jmcneill #define HDMI_PHY_I2CM_SLAVE_ADDR 0x3020
85 1.1 jmcneill #define HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 0x69
86 1.1 jmcneill #define HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY 0x49
87 1.1 jmcneill #define HDMI_PHY_I2CM_ADDRESS_ADDR 0x3021
88 1.1 jmcneill #define HDMI_PHY_I2CM_DATAO_1_ADDR 0x3022
89 1.1 jmcneill #define HDMI_PHY_I2CM_DATAO_0_ADDR 0x3023
90 1.1 jmcneill #define HDMI_PHY_I2CM_DATAI_1_ADDR 0x3024
91 1.1 jmcneill #define HDMI_PHY_I2CM_DATAI_0_ADDR 0x3025
92 1.1 jmcneill #define HDMI_PHY_I2CM_OPERATION_ADDR 0x3026
93 1.1 jmcneill #define HDMI_PHY_I2CM_OPERATION_ADDR_WRITE 0x10
94 1.1 jmcneill #define HDMI_PHY_I2CM_OPERATION_ADDR_READ 0x1
95 1.1 jmcneill #define HDMI_PHY_I2CM_INT_ADDR 0x3027
96 1.1 jmcneill #define HDMI_PHY_I2CM_CTLINT_ADDR 0x3028
97 1.1 jmcneill #define HDMI_PHY_I2CM_DIV_ADDR 0x3029
98 1.1 jmcneill #define HDMI_PHY_I2CM_SOFTRSTZ_ADDR 0x302a
99 1.1 jmcneill #define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR 0x302b
100 1.1 jmcneill #define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR 0x302c
101 1.1 jmcneill #define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR 0x302d
102 1.1 jmcneill #define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR 0x302e
103 1.1 jmcneill #define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR 0x302f
104 1.1 jmcneill #define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR 0x3030
105 1.1 jmcneill #define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR 0x3031
106 1.1 jmcneill #define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR 0x3032
107 1.1 jmcneill
108 1.1 jmcneill #define HDMI_MC_FLOWCTRL 0x4004
109 1.1 jmcneill #define HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK 0x1
110 1.1 jmcneill #define HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH 0x1
111 1.1 jmcneill #define HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS 0x0
112 1.1 jmcneill #define HDMI_MC_PHYRSTZ 0x4005
113 1.1 jmcneill #define HDMI_MC_PHYRSTZ_ASSERT 0x0
114 1.1 jmcneill #define HDMI_MC_PHYRSTZ_DEASSERT 0x1
115 1.1 jmcneill #define HDMI_MC_HEACPHY_RST 0x4007
116 1.1 jmcneill #define HDMI_MC_HEACPHY_RST_ASSERT 0x1
117 1.1 jmcneill #define HDMI_MC_HEACPHY_RST_DEASSERT 0x0
118 1.1 jmcneill
119 1.1 jmcneill /* HDMI PHY register with access through I2C */
120 1.1 jmcneill #define HDMI_PHY_I2C_CKCALCTRL 0x5
121 1.1 jmcneill #define CKCALCTRL_OVERRIDE (1 << 15)
122 1.1 jmcneill #define HDMI_PHY_I2C_CPCE_CTRL 0x6
123 1.1 jmcneill #define CPCE_CTRL_45_25 ((3 << 7) | (3 << 5))
124 1.1 jmcneill #define CPCE_CTRL_92_50 ((2 << 7) | (2 << 5))
125 1.1 jmcneill #define CPCE_CTRL_185 ((1 << 7) | (1 << 5))
126 1.1 jmcneill #define CPCE_CTRL_370 ((0 << 7) | (0 << 5))
127 1.1 jmcneill #define HDMI_PHY_I2C_CKSYMTXCTRL 0x9
128 1.1 jmcneill #define CKSYMTXCTRL_OVERRIDE (1 << 15)
129 1.1 jmcneill #define CKSYMTXCTRL_TX_SYMON (1 << 3)
130 1.1 jmcneill #define CKSYMTXCTRL_TX_TRAON (1 << 2)
131 1.1 jmcneill #define CKSYMTXCTRL_TX_TRBON (1 << 1)
132 1.1 jmcneill #define CKSYMTXCTRL_TX_CK_SYMON (1 << 0)
133 1.1 jmcneill #define HDMI_PHY_I2C_VLEVCTRL 0x0E
134 1.1 jmcneill #define HDMI_PHY_I2C_CURRCTRL 0x10
135 1.1 jmcneill #define HDMI_PHY_I2C_PLLPHBYCTRL 0x13
136 1.1 jmcneill #define VLEVCTRL_TX_LVL(x) ((x) << 5)
137 1.1 jmcneill #define VLEVCTRL_CK_LVL(x) (x)
138 1.1 jmcneill #define HDMI_PHY_I2C_GMPCTRL 0x15
139 1.1 jmcneill #define GMPCTRL_45_25 0x00
140 1.1 jmcneill #define GMPCTRL_92_50 0x05
141 1.1 jmcneill #define GMPCTRL_185 0x0a
142 1.1 jmcneill #define GMPCTRL_370 0x0f
143 1.1 jmcneill #define HDMI_PHY_I2C_MSM_CTRL 0x17
144 1.1 jmcneill #define MSM_CTRL_FB_CLK (0x3 << 1)
145 1.1 jmcneill #define HDMI_PHY_I2C_TXTERM 0x19
146 1.1 jmcneill #define TXTERM_133 0x5
147 1.1 jmcneill
148 1.1 jmcneill static void
149 1.1 jmcneill dwhdmi_phy_wait_i2c_done(struct dwhdmi_softc *sc, int msec)
150 1.1 jmcneill {
151 1.1 jmcneill uint8_t val;
152 1.1 jmcneill
153 1.1 jmcneill val = dwhdmi_read(sc, HDMI_IH_I2CMPHY_STAT0) &
154 1.1 jmcneill (HDMI_IH_I2CMPHY_STAT0_DONE | HDMI_IH_I2CMPHY_STAT0_ERROR);
155 1.1 jmcneill while (val == 0) {
156 1.1 jmcneill delay(1000);
157 1.1 jmcneill msec -= 10;
158 1.1 jmcneill if (msec <= 0)
159 1.1 jmcneill return;
160 1.1 jmcneill val = dwhdmi_read(sc, HDMI_IH_I2CMPHY_STAT0) &
161 1.1 jmcneill (HDMI_IH_I2CMPHY_STAT0_DONE | HDMI_IH_I2CMPHY_STAT0_ERROR);
162 1.1 jmcneill }
163 1.1 jmcneill }
164 1.1 jmcneill
165 1.1 jmcneill static void
166 1.1 jmcneill dwhdmi_phy_i2c_write(struct dwhdmi_softc *sc, unsigned short data,
167 1.1 jmcneill unsigned char addr)
168 1.1 jmcneill {
169 1.1 jmcneill
170 1.1 jmcneill /* clear DONE and ERROR flags */
171 1.1 jmcneill dwhdmi_write(sc, HDMI_IH_I2CMPHY_STAT0,
172 1.1 jmcneill HDMI_IH_I2CMPHY_STAT0_DONE | HDMI_IH_I2CMPHY_STAT0_ERROR);
173 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_I2CM_ADDRESS_ADDR, addr);
174 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_I2CM_DATAO_1_ADDR, ((data >> 8) & 0xff));
175 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_I2CM_DATAO_0_ADDR, ((data >> 0) & 0xff));
176 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_I2CM_OPERATION_ADDR, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE);
177 1.1 jmcneill dwhdmi_phy_wait_i2c_done(sc, 1000);
178 1.1 jmcneill }
179 1.1 jmcneill
180 1.1 jmcneill static void
181 1.1 jmcneill dwhdmi_phy_enable_power(struct dwhdmi_softc *sc, uint8_t enable)
182 1.1 jmcneill {
183 1.1 jmcneill uint8_t reg;
184 1.1 jmcneill
185 1.1 jmcneill reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
186 1.1 jmcneill reg &= ~HDMI_PHY_CONF0_PDZ_MASK;
187 1.1 jmcneill reg |= (enable << HDMI_PHY_CONF0_PDZ_OFFSET);
188 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
189 1.1 jmcneill }
190 1.1 jmcneill
191 1.1 jmcneill static void
192 1.1 jmcneill dwhdmi_phy_enable_tmds(struct dwhdmi_softc *sc, uint8_t enable)
193 1.1 jmcneill {
194 1.1 jmcneill uint8_t reg;
195 1.1 jmcneill
196 1.1 jmcneill reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
197 1.1 jmcneill reg &= ~HDMI_PHY_CONF0_ENTMDS_MASK;
198 1.1 jmcneill reg |= (enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
199 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
200 1.1 jmcneill }
201 1.1 jmcneill
202 1.1 jmcneill static void
203 1.1 jmcneill dwhdmi_phy_gen2_pddq(struct dwhdmi_softc *sc, uint8_t enable)
204 1.1 jmcneill {
205 1.1 jmcneill uint8_t reg;
206 1.1 jmcneill
207 1.1 jmcneill reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
208 1.1 jmcneill reg &= ~HDMI_PHY_CONF0_GEN2_PDDQ_MASK;
209 1.1 jmcneill reg |= (enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
210 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
211 1.1 jmcneill }
212 1.1 jmcneill
213 1.1 jmcneill static void
214 1.1 jmcneill dwhdmi_phy_gen2_txpwron(struct dwhdmi_softc *sc, uint8_t enable)
215 1.1 jmcneill {
216 1.1 jmcneill uint8_t reg;
217 1.1 jmcneill
218 1.1 jmcneill reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
219 1.1 jmcneill reg &= ~HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
220 1.1 jmcneill reg |= (enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
221 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
222 1.1 jmcneill }
223 1.1 jmcneill
224 1.1 jmcneill static void
225 1.1 jmcneill dwhdmi_phy_sel_data_en_pol(struct dwhdmi_softc *sc, uint8_t enable)
226 1.1 jmcneill {
227 1.1 jmcneill uint8_t reg;
228 1.1 jmcneill
229 1.1 jmcneill reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
230 1.1 jmcneill reg &= ~HDMI_PHY_CONF0_SELDATAENPOL_MASK;
231 1.1 jmcneill reg |= (enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
232 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
233 1.1 jmcneill }
234 1.1 jmcneill
235 1.1 jmcneill static void
236 1.1 jmcneill dwhdmi_phy_sel_interface_control(struct dwhdmi_softc *sc, uint8_t enable)
237 1.1 jmcneill {
238 1.1 jmcneill uint8_t reg;
239 1.1 jmcneill
240 1.1 jmcneill reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
241 1.1 jmcneill reg &= ~HDMI_PHY_CONF0_SELDIPIF_MASK;
242 1.1 jmcneill reg |= (enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
243 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
244 1.1 jmcneill }
245 1.1 jmcneill
246 1.1 jmcneill static void
247 1.1 jmcneill dwhdmi_phy_enable_svsret(struct dwhdmi_softc *sc, uint8_t enable)
248 1.1 jmcneill {
249 1.1 jmcneill uint8_t reg;
250 1.1 jmcneill
251 1.1 jmcneill reg = dwhdmi_read(sc, HDMI_PHY_CONF0);
252 1.1 jmcneill reg &= ~HDMI_PHY_CONF0_SVSRET_MASK;
253 1.1 jmcneill reg |= (enable << HDMI_PHY_CONF0_SVSRET_OFFSET);
254 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_CONF0, reg);
255 1.1 jmcneill }
256 1.1 jmcneill
257 1.1 jmcneill static inline void
258 1.1 jmcneill dwhdmi_phy_test_clear(struct dwhdmi_softc *sc, unsigned char bit)
259 1.1 jmcneill {
260 1.1 jmcneill uint8_t val;
261 1.1 jmcneill
262 1.1 jmcneill val = dwhdmi_read(sc, HDMI_PHY_TST0);
263 1.1 jmcneill val &= ~HDMI_PHY_TST0_TSTCLR_MASK;
264 1.1 jmcneill val |= (bit << HDMI_PHY_TST0_TSTCLR_OFFSET) &
265 1.1 jmcneill HDMI_PHY_TST0_TSTCLR_MASK;
266 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_TST0, val);
267 1.1 jmcneill }
268 1.1 jmcneill
269 1.1 jmcneill static int
270 1.1 jmcneill dwhdmi_phy_configure(struct dwhdmi_softc *sc, struct drm_display_mode *mode)
271 1.1 jmcneill {
272 1.1 jmcneill const struct dwhdmi_mpll_config *mpll_conf;
273 1.1 jmcneill const struct dwhdmi_phy_config *phy_conf;
274 1.1 jmcneill uint8_t val;
275 1.1 jmcneill uint8_t msec;
276 1.1 jmcneill
277 1.1 jmcneill dwhdmi_write(sc, HDMI_MC_FLOWCTRL, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS);
278 1.1 jmcneill
279 1.1 jmcneill /* gen2 tx power off */
280 1.1 jmcneill dwhdmi_phy_gen2_txpwron(sc, 0);
281 1.1 jmcneill
282 1.1 jmcneill /* gen2 pddq */
283 1.1 jmcneill dwhdmi_phy_gen2_pddq(sc, 1);
284 1.1 jmcneill
285 1.1 jmcneill /* PHY reset */
286 1.1 jmcneill dwhdmi_write(sc, HDMI_MC_PHYRSTZ, HDMI_MC_PHYRSTZ_DEASSERT);
287 1.1 jmcneill dwhdmi_write(sc, HDMI_MC_PHYRSTZ, HDMI_MC_PHYRSTZ_ASSERT);
288 1.1 jmcneill
289 1.1 jmcneill dwhdmi_write(sc, HDMI_MC_HEACPHY_RST, HDMI_MC_HEACPHY_RST_ASSERT);
290 1.1 jmcneill
291 1.1 jmcneill dwhdmi_phy_test_clear(sc, 1);
292 1.1 jmcneill dwhdmi_write(sc, HDMI_PHY_I2CM_SLAVE_ADDR, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2);
293 1.1 jmcneill dwhdmi_phy_test_clear(sc, 0);
294 1.1 jmcneill
295 1.1 jmcneill /*
296 1.1 jmcneill * Following initialization are for 8bit per color case
297 1.1 jmcneill */
298 1.1 jmcneill
299 1.1 jmcneill /*
300 1.1 jmcneill * PLL/MPLL config
301 1.1 jmcneill */
302 1.1 jmcneill for (mpll_conf = &sc->sc_mpll_config[0]; mpll_conf->pixel_clock != 0; mpll_conf++)
303 1.2 jmcneill if (mode->clock <= mpll_conf->pixel_clock)
304 1.1 jmcneill break;
305 1.1 jmcneill
306 1.1 jmcneill dwhdmi_phy_i2c_write(sc, mpll_conf->cpce, HDMI_PHY_I2C_CPCE_CTRL);
307 1.1 jmcneill dwhdmi_phy_i2c_write(sc, mpll_conf->gmp, HDMI_PHY_I2C_GMPCTRL);
308 1.1 jmcneill dwhdmi_phy_i2c_write(sc, mpll_conf->curr, HDMI_PHY_I2C_CURRCTRL);
309 1.1 jmcneill
310 1.1 jmcneill for (phy_conf = &sc->sc_phy_config[0]; phy_conf->pixel_clock != 0; phy_conf++)
311 1.2 jmcneill if (mode->clock <= phy_conf->pixel_clock)
312 1.1 jmcneill break;
313 1.1 jmcneill
314 1.1 jmcneill dwhdmi_phy_i2c_write(sc, 0x0000, HDMI_PHY_I2C_PLLPHBYCTRL);
315 1.1 jmcneill dwhdmi_phy_i2c_write(sc, MSM_CTRL_FB_CLK, HDMI_PHY_I2C_MSM_CTRL);
316 1.1 jmcneill
317 1.1 jmcneill dwhdmi_phy_i2c_write(sc, phy_conf->term, HDMI_PHY_I2C_TXTERM);
318 1.1 jmcneill dwhdmi_phy_i2c_write(sc, phy_conf->sym, HDMI_PHY_I2C_CKSYMTXCTRL);
319 1.1 jmcneill dwhdmi_phy_i2c_write(sc, phy_conf->vlev, HDMI_PHY_I2C_VLEVCTRL);
320 1.1 jmcneill
321 1.1 jmcneill /* REMOVE CLK TERM */
322 1.1 jmcneill dwhdmi_phy_i2c_write(sc, CKCALCTRL_OVERRIDE, HDMI_PHY_I2C_CKCALCTRL);
323 1.1 jmcneill
324 1.1 jmcneill dwhdmi_phy_enable_power(sc, 1);
325 1.1 jmcneill
326 1.1 jmcneill /* toggle TMDS enable */
327 1.1 jmcneill dwhdmi_phy_enable_tmds(sc, 0);
328 1.1 jmcneill dwhdmi_phy_enable_tmds(sc, 1);
329 1.1 jmcneill
330 1.1 jmcneill /* gen2 tx power on */
331 1.1 jmcneill dwhdmi_phy_gen2_txpwron(sc, 1);
332 1.1 jmcneill dwhdmi_phy_gen2_pddq(sc, 0);
333 1.1 jmcneill
334 1.1 jmcneill switch (sc->sc_phytype) {
335 1.1 jmcneill case 0xb2: /* MHL PHY HEAC */
336 1.1 jmcneill case 0xc2: /* MHL PHY */
337 1.1 jmcneill case 0xf3: /* HDMI 2.0 TX PHY */
338 1.1 jmcneill dwhdmi_phy_enable_svsret(sc, 1);
339 1.1 jmcneill break;
340 1.1 jmcneill }
341 1.1 jmcneill
342 1.1 jmcneill /*Wait for PHY PLL lock */
343 1.1 jmcneill msec = 4;
344 1.1 jmcneill val = dwhdmi_read(sc, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
345 1.1 jmcneill while (val == 0) {
346 1.1 jmcneill delay(1000);
347 1.1 jmcneill if (msec-- == 0) {
348 1.1 jmcneill device_printf(sc->sc_dev, "PHY PLL not locked\n");
349 1.1 jmcneill return (-1);
350 1.1 jmcneill }
351 1.1 jmcneill val = dwhdmi_read(sc, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
352 1.1 jmcneill }
353 1.1 jmcneill
354 1.1 jmcneill return (0);
355 1.1 jmcneill }
356 1.1 jmcneill
357 1.1 jmcneill static void
358 1.1 jmcneill dwhdmi_phy_init(struct dwhdmi_softc *sc, struct drm_display_mode *mode)
359 1.1 jmcneill {
360 1.1 jmcneill int i;
361 1.1 jmcneill
362 1.1 jmcneill /* HDMI Phy spec says to do the phy initialization sequence twice */
363 1.1 jmcneill for (i = 0 ; i < 2 ; i++) {
364 1.1 jmcneill dwhdmi_phy_sel_data_en_pol(sc, 1);
365 1.1 jmcneill dwhdmi_phy_sel_interface_control(sc, 0);
366 1.1 jmcneill dwhdmi_phy_enable_tmds(sc, 0);
367 1.1 jmcneill dwhdmi_phy_enable_power(sc, 0);
368 1.1 jmcneill
369 1.1 jmcneill /* Enable CSC */
370 1.1 jmcneill dwhdmi_phy_configure(sc, mode);
371 1.1 jmcneill }
372 1.1 jmcneill }
373 1.1 jmcneill
374 1.1 jmcneill enum drm_connector_status
375 1.1 jmcneill dwhdmi_phy_detect(struct dwhdmi_softc *sc, bool force)
376 1.1 jmcneill {
377 1.1 jmcneill uint8_t val;
378 1.1 jmcneill
379 1.1 jmcneill val = dwhdmi_read(sc, HDMI_PHY_STAT0);
380 1.1 jmcneill
381 1.1 jmcneill return ((val & HDMI_PHY_STAT0_HPD) != 0) ?
382 1.1 jmcneill connector_status_connected :
383 1.1 jmcneill connector_status_disconnected;
384 1.1 jmcneill }
385 1.1 jmcneill
386 1.1 jmcneill void
387 1.1 jmcneill dwhdmi_phy_enable(struct dwhdmi_softc *sc)
388 1.1 jmcneill {
389 1.1 jmcneill }
390 1.1 jmcneill
391 1.1 jmcneill void
392 1.1 jmcneill dwhdmi_phy_disable(struct dwhdmi_softc *sc)
393 1.1 jmcneill {
394 1.1 jmcneill }
395 1.1 jmcneill
396 1.1 jmcneill void
397 1.1 jmcneill dwhdmi_phy_mode_set(struct dwhdmi_softc *sc,
398 1.1 jmcneill struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode)
399 1.1 jmcneill {
400 1.1 jmcneill dwhdmi_phy_init(sc, adjusted_mode);
401 1.1 jmcneill }
402