xref: /freebsd/sys/dev/hdmi/dwc_hdmi.c (revision 63d1fd5970ec814904aa0f4580b10a0d302d08b2)
1 /*-
2  * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 /*
31  * HDMI core module
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/malloc.h>
39 #include <sys/bus.h>
40 #include <sys/rman.h>
41 
42 #include <machine/bus.h>
43 
44 #include <dev/videomode/videomode.h>
45 #include <dev/videomode/edidvar.h>
46 
47 #include <dev/iicbus/iicbus.h>
48 #include <dev/iicbus/iiconf.h>
49 
50 #include <dev/hdmi/dwc_hdmi.h>
51 #include <dev/hdmi/dwc_hdmireg.h>
52 
53 #include "hdmi_if.h"
54 
55 #define	I2C_DDC_ADDR	(0x50 << 1)
56 #define	I2C_DDC_SEGADDR	(0x30 << 1)
57 #define	EDID_LENGTH	0x80
58 
59 #define	EXT_TAG			0x00
60 #define	CEA_TAG_ID		0x02
61 #define	CEA_DTD			0x03
62 #define	DTD_BASIC_AUDIO		(1 << 6)
63 #define	CEA_REV			0x02
64 #define	CEA_DATA_OFF		0x03
65 #define	CEA_DATA_START		4
66 #define	BLOCK_TAG(x)		(((x) >> 5) & 0x7)
67 #define	BLOCK_TAG_VSDB		3
68 #define	BLOCK_LEN(x)		((x) & 0x1f)
69 #define	HDMI_VSDB_MINLEN	5
70 #define	HDMI_OUI		"\x03\x0c\x00"
71 #define	HDMI_OUI_LEN		3
72 
73 static void
74 dwc_hdmi_phy_wait_i2c_done(struct dwc_hdmi_softc *sc, int msec)
75 {
76 	uint8_t val;
77 
78 	val = RD1(sc, HDMI_IH_I2CMPHY_STAT0) &
79 	    (HDMI_IH_I2CMPHY_STAT0_DONE | HDMI_IH_I2CMPHY_STAT0_ERROR);
80 	while (val == 0) {
81 		pause("HDMI_PHY", hz/100);
82 		msec -= 10;
83 		if (msec <= 0)
84 			return;
85 		val = RD1(sc, HDMI_IH_I2CMPHY_STAT0) &
86 		    (HDMI_IH_I2CMPHY_STAT0_DONE | HDMI_IH_I2CMPHY_STAT0_ERROR);
87 	}
88 }
89 
90 static void
91 dwc_hdmi_phy_i2c_write(struct dwc_hdmi_softc *sc, unsigned short data,
92     unsigned char addr)
93 {
94 
95 	/* clear DONE and ERROR flags */
96 	WR1(sc, HDMI_IH_I2CMPHY_STAT0,
97 	    HDMI_IH_I2CMPHY_STAT0_DONE | HDMI_IH_I2CMPHY_STAT0_ERROR);
98 	WR1(sc, HDMI_PHY_I2CM_ADDRESS_ADDR, addr);
99 	WR1(sc, HDMI_PHY_I2CM_DATAO_1_ADDR, ((data >> 8) & 0xff));
100 	WR1(sc, HDMI_PHY_I2CM_DATAO_0_ADDR, ((data >> 0) & 0xff));
101 	WR1(sc, HDMI_PHY_I2CM_OPERATION_ADDR, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE);
102 	dwc_hdmi_phy_wait_i2c_done(sc, 1000);
103 }
104 
105 static void
106 dwc_hdmi_disable_overflow_interrupts(struct dwc_hdmi_softc *sc)
107 {
108 	WR1(sc, HDMI_IH_MUTE_FC_STAT2, HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK);
109 	WR1(sc, HDMI_FC_MASK2,
110 	    HDMI_FC_MASK2_LOW_PRI | HDMI_FC_MASK2_HIGH_PRI);
111 }
112 
113 static void
114 dwc_hdmi_av_composer(struct dwc_hdmi_softc *sc)
115 {
116 	uint8_t inv_val;
117 	int is_dvi;
118 	int hblank, vblank, hsync_len, hfp, vfp;
119 
120 	/* Set up HDMI_FC_INVIDCONF */
121 	inv_val = ((sc->sc_mode.flags & VID_PVSYNC) ?
122 		HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
123 		HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
124 
125 	inv_val |= ((sc->sc_mode.flags & VID_PHSYNC) ?
126 		HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
127 		HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
128 
129 	inv_val |= HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH;
130 
131 	inv_val |= ((sc->sc_mode.flags & VID_INTERLACE) ?
132 			HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
133 			HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW);
134 
135 	inv_val |= ((sc->sc_mode.flags & VID_INTERLACE) ?
136 		HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
137 		HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE);
138 
139 	/* TODO: implement HDMI part */
140 	is_dvi = sc->sc_has_audio == 0;
141 	inv_val |= (is_dvi ?
142 		HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE :
143 		HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE);
144 
145 	WR1(sc, HDMI_FC_INVIDCONF, inv_val);
146 
147 	/* Set up horizontal active pixel region width */
148 	WR1(sc, HDMI_FC_INHACTV1, sc->sc_mode.hdisplay >> 8);
149 	WR1(sc, HDMI_FC_INHACTV0, sc->sc_mode.hdisplay);
150 
151 	/* Set up vertical blanking pixel region width */
152 	WR1(sc, HDMI_FC_INVACTV1, sc->sc_mode.vdisplay >> 8);
153 	WR1(sc, HDMI_FC_INVACTV0, sc->sc_mode.vdisplay);
154 
155 	/* Set up horizontal blanking pixel region width */
156 	hblank = sc->sc_mode.htotal - sc->sc_mode.hdisplay;
157 	WR1(sc, HDMI_FC_INHBLANK1, hblank >> 8);
158 	WR1(sc, HDMI_FC_INHBLANK0, hblank);
159 
160 	/* Set up vertical blanking pixel region width */
161 	vblank = sc->sc_mode.vtotal - sc->sc_mode.vdisplay;
162 	WR1(sc, HDMI_FC_INVBLANK, vblank);
163 
164 	/* Set up HSYNC active edge delay width (in pixel clks) */
165 	hfp = sc->sc_mode.hsync_start - sc->sc_mode.hdisplay;
166 	WR1(sc, HDMI_FC_HSYNCINDELAY1, hfp >> 8);
167 	WR1(sc, HDMI_FC_HSYNCINDELAY0, hfp);
168 
169 	/* Set up VSYNC active edge delay (in pixel clks) */
170 	vfp = sc->sc_mode.vsync_start - sc->sc_mode.vdisplay;
171 	WR1(sc, HDMI_FC_VSYNCINDELAY, vfp);
172 
173 	hsync_len = (sc->sc_mode.hsync_end - sc->sc_mode.hsync_start);
174 	/* Set up HSYNC active pulse width (in pixel clks) */
175 	WR1(sc, HDMI_FC_HSYNCINWIDTH1, hsync_len >> 8);
176 	WR1(sc, HDMI_FC_HSYNCINWIDTH0, hsync_len);
177 
178 	/* Set up VSYNC active edge delay (in pixel clks) */
179 	WR1(sc, HDMI_FC_VSYNCINWIDTH, (sc->sc_mode.vsync_end - sc->sc_mode.vsync_start));
180 }
181 
182 static void
183 dwc_hdmi_phy_enable_power(struct dwc_hdmi_softc *sc, uint8_t enable)
184 {
185 	uint8_t reg;
186 
187 	reg = RD1(sc, HDMI_PHY_CONF0);
188 	reg &= ~HDMI_PHY_CONF0_PDZ_MASK;
189 	reg |= (enable << HDMI_PHY_CONF0_PDZ_OFFSET);
190 	WR1(sc, HDMI_PHY_CONF0, reg);
191 }
192 
193 static void
194 dwc_hdmi_phy_enable_tmds(struct dwc_hdmi_softc *sc, uint8_t enable)
195 {
196 	uint8_t reg;
197 
198 	reg = RD1(sc, HDMI_PHY_CONF0);
199 	reg &= ~HDMI_PHY_CONF0_ENTMDS_MASK;
200 	reg |= (enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
201 	WR1(sc, HDMI_PHY_CONF0, reg);
202 }
203 
204 static void
205 dwc_hdmi_phy_gen2_pddq(struct dwc_hdmi_softc *sc, uint8_t enable)
206 {
207 	uint8_t reg;
208 
209 	reg = RD1(sc, HDMI_PHY_CONF0);
210 	reg &= ~HDMI_PHY_CONF0_GEN2_PDDQ_MASK;
211 	reg |= (enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
212 	WR1(sc, HDMI_PHY_CONF0, reg);
213 }
214 
215 static void
216 dwc_hdmi_phy_gen2_txpwron(struct dwc_hdmi_softc *sc, uint8_t enable)
217 {
218 	uint8_t reg;
219 
220 	reg = RD1(sc, HDMI_PHY_CONF0);
221 	reg &= ~HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
222 	reg |= (enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
223 	WR1(sc, HDMI_PHY_CONF0, reg);
224 }
225 
226 static void
227 dwc_hdmi_phy_sel_data_en_pol(struct dwc_hdmi_softc *sc, uint8_t enable)
228 {
229 	uint8_t reg;
230 
231 	reg = RD1(sc, HDMI_PHY_CONF0);
232 	reg &= ~HDMI_PHY_CONF0_SELDATAENPOL_MASK;
233 	reg |= (enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
234 	WR1(sc, HDMI_PHY_CONF0, reg);
235 }
236 
237 static void
238 dwc_hdmi_phy_sel_interface_control(struct dwc_hdmi_softc *sc, uint8_t enable)
239 {
240 	uint8_t reg;
241 
242 	reg = RD1(sc, HDMI_PHY_CONF0);
243 	reg &= ~HDMI_PHY_CONF0_SELDIPIF_MASK;
244 	reg |= (enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
245 	WR1(sc, HDMI_PHY_CONF0, reg);
246 }
247 
248 static inline void
249 dwc_hdmi_phy_test_clear(struct dwc_hdmi_softc *sc, unsigned char bit)
250 {
251 	uint8_t val;
252 
253 	val = RD1(sc, HDMI_PHY_TST0);
254 	val &= ~HDMI_PHY_TST0_TSTCLR_MASK;
255 	val |= (bit << HDMI_PHY_TST0_TSTCLR_OFFSET) &
256 		HDMI_PHY_TST0_TSTCLR_MASK;
257 	WR1(sc, HDMI_PHY_TST0, val);
258 }
259 
260 static void
261 dwc_hdmi_clear_overflow(struct dwc_hdmi_softc *sc)
262 {
263 	int count;
264 	uint8_t val;
265 
266 	/* TMDS software reset */
267 	WR1(sc, HDMI_MC_SWRSTZ, (uint8_t)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ);
268 
269 	val = RD1(sc, HDMI_FC_INVIDCONF);
270 
271 	for (count = 0 ; count < 4 ; count++)
272 		WR1(sc, HDMI_FC_INVIDCONF, val);
273 }
274 
275 static int
276 dwc_hdmi_phy_configure(struct dwc_hdmi_softc *sc)
277 {
278 	uint8_t val;
279 	uint8_t msec;
280 
281 	WR1(sc, HDMI_MC_FLOWCTRL, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS);
282 
283 	/* gen2 tx power off */
284 	dwc_hdmi_phy_gen2_txpwron(sc, 0);
285 
286 	/* gen2 pddq */
287 	dwc_hdmi_phy_gen2_pddq(sc, 1);
288 
289 	/* PHY reset */
290 	WR1(sc, HDMI_MC_PHYRSTZ, HDMI_MC_PHYRSTZ_DEASSERT);
291 	WR1(sc, HDMI_MC_PHYRSTZ, HDMI_MC_PHYRSTZ_ASSERT);
292 
293 	WR1(sc, HDMI_MC_HEACPHY_RST, HDMI_MC_HEACPHY_RST_ASSERT);
294 
295 	dwc_hdmi_phy_test_clear(sc, 1);
296 	WR1(sc, HDMI_PHY_I2CM_SLAVE_ADDR, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2);
297 	dwc_hdmi_phy_test_clear(sc, 0);
298 
299 	/*
300 	 * Following initialization are for 8bit per color case
301 	 */
302 
303 	/*
304 	 * PLL/MPLL config, see section 24.7.22 in TRM
305 	 *  config, see section 24.7.22
306 	 */
307 	if (sc->sc_mode.dot_clock*1000 <= 45250000) {
308 		dwc_hdmi_phy_i2c_write(sc, CPCE_CTRL_45_25, HDMI_PHY_I2C_CPCE_CTRL);
309 		dwc_hdmi_phy_i2c_write(sc, GMPCTRL_45_25, HDMI_PHY_I2C_GMPCTRL);
310 	} else if (sc->sc_mode.dot_clock*1000 <= 92500000) {
311 		dwc_hdmi_phy_i2c_write(sc, CPCE_CTRL_92_50, HDMI_PHY_I2C_CPCE_CTRL);
312 		dwc_hdmi_phy_i2c_write(sc, GMPCTRL_92_50, HDMI_PHY_I2C_GMPCTRL);
313 	} else if (sc->sc_mode.dot_clock*1000 <= 185000000) {
314 		dwc_hdmi_phy_i2c_write(sc, CPCE_CTRL_185, HDMI_PHY_I2C_CPCE_CTRL);
315 		dwc_hdmi_phy_i2c_write(sc, GMPCTRL_185, HDMI_PHY_I2C_GMPCTRL);
316 	} else {
317 		dwc_hdmi_phy_i2c_write(sc, CPCE_CTRL_370, HDMI_PHY_I2C_CPCE_CTRL);
318 		dwc_hdmi_phy_i2c_write(sc, GMPCTRL_370, HDMI_PHY_I2C_GMPCTRL);
319 	}
320 
321 	/*
322 	 * Values described in TRM section 34.9.2 PLL/MPLL Generic
323 	 *    Configuration Settings. Table 34-23.
324 	 */
325 	if (sc->sc_mode.dot_clock*1000 <= 54000000) {
326 		dwc_hdmi_phy_i2c_write(sc, 0x091c, HDMI_PHY_I2C_CURRCTRL);
327 	} else if (sc->sc_mode.dot_clock*1000 <= 58400000) {
328 		dwc_hdmi_phy_i2c_write(sc, 0x091c, HDMI_PHY_I2C_CURRCTRL);
329 	} else if (sc->sc_mode.dot_clock*1000 <= 72000000) {
330 		dwc_hdmi_phy_i2c_write(sc, 0x06dc, HDMI_PHY_I2C_CURRCTRL);
331 	} else if (sc->sc_mode.dot_clock*1000 <= 74250000) {
332 		dwc_hdmi_phy_i2c_write(sc, 0x06dc, HDMI_PHY_I2C_CURRCTRL);
333 	} else if (sc->sc_mode.dot_clock*1000 <= 118800000) {
334 		dwc_hdmi_phy_i2c_write(sc, 0x091c, HDMI_PHY_I2C_CURRCTRL);
335 	} else if (sc->sc_mode.dot_clock*1000 <= 216000000) {
336 		dwc_hdmi_phy_i2c_write(sc, 0x06dc, HDMI_PHY_I2C_CURRCTRL);
337 	} else {
338 		panic("Unsupported mode\n");
339 	}
340 
341 	dwc_hdmi_phy_i2c_write(sc, 0x0000, HDMI_PHY_I2C_PLLPHBYCTRL);
342 	dwc_hdmi_phy_i2c_write(sc, MSM_CTRL_FB_CLK, HDMI_PHY_I2C_MSM_CTRL);
343 	/* RESISTANCE TERM 133 Ohm */
344 	dwc_hdmi_phy_i2c_write(sc, TXTERM_133, HDMI_PHY_I2C_TXTERM);
345 
346 	/* REMOVE CLK TERM */
347 	dwc_hdmi_phy_i2c_write(sc, CKCALCTRL_OVERRIDE, HDMI_PHY_I2C_CKCALCTRL);
348 
349 	if (sc->sc_mode.dot_clock*1000 > 148500000) {
350 		dwc_hdmi_phy_i2c_write(sc,CKSYMTXCTRL_OVERRIDE | CKSYMTXCTRL_TX_SYMON |
351 		    CKSYMTXCTRL_TX_TRBON | CKSYMTXCTRL_TX_CK_SYMON, HDMI_PHY_I2C_CKSYMTXCTRL);
352 		dwc_hdmi_phy_i2c_write(sc, VLEVCTRL_TX_LVL(9) | VLEVCTRL_CK_LVL(9),
353 		    HDMI_PHY_I2C_VLEVCTRL);
354 	} else {
355 		dwc_hdmi_phy_i2c_write(sc,CKSYMTXCTRL_OVERRIDE | CKSYMTXCTRL_TX_SYMON |
356 		    CKSYMTXCTRL_TX_TRAON | CKSYMTXCTRL_TX_CK_SYMON, HDMI_PHY_I2C_CKSYMTXCTRL);
357 		dwc_hdmi_phy_i2c_write(sc, VLEVCTRL_TX_LVL(13) | VLEVCTRL_CK_LVL(13),
358 		    HDMI_PHY_I2C_VLEVCTRL);
359 	}
360 
361 	dwc_hdmi_phy_enable_power(sc, 1);
362 
363 	/* toggle TMDS enable */
364 	dwc_hdmi_phy_enable_tmds(sc, 0);
365 	dwc_hdmi_phy_enable_tmds(sc, 1);
366 
367 	/* gen2 tx power on */
368 	dwc_hdmi_phy_gen2_txpwron(sc, 1);
369 	dwc_hdmi_phy_gen2_pddq(sc, 0);
370 
371 	/*Wait for PHY PLL lock */
372 	msec = 4;
373 	val = RD1(sc, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
374 	while (val == 0) {
375 		DELAY(1000);
376 		if (msec-- == 0) {
377 			device_printf(sc->sc_dev, "PHY PLL not locked\n");
378 			return (-1);
379 		}
380 		val = RD1(sc, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
381 	}
382 
383 	return true;
384 }
385 
386 static void
387 dwc_hdmi_phy_init(struct dwc_hdmi_softc *sc)
388 {
389 	int i;
390 
391 	/* HDMI Phy spec says to do the phy initialization sequence twice */
392 	for (i = 0 ; i < 2 ; i++) {
393 		dwc_hdmi_phy_sel_data_en_pol(sc, 1);
394 		dwc_hdmi_phy_sel_interface_control(sc, 0);
395 		dwc_hdmi_phy_enable_tmds(sc, 0);
396 		dwc_hdmi_phy_enable_power(sc, 0);
397 
398 		/* Enable CSC */
399 		dwc_hdmi_phy_configure(sc);
400 	}
401 }
402 
403 static void
404 dwc_hdmi_enable_video_path(struct dwc_hdmi_softc *sc)
405 {
406 	uint8_t clkdis;
407 
408 	/*
409 	 * Control period timing
410 	 * Values are minimal according to HDMI spec 1.4a
411 	 */
412 	WR1(sc, HDMI_FC_CTRLDUR, 12);
413 	WR1(sc, HDMI_FC_EXCTRLDUR, 32);
414 	WR1(sc, HDMI_FC_EXCTRLSPAC, 1);
415 
416 	/*
417 	 * Bits to fill data lines not used to transmit preamble
418 	 * for channels 0, 1, and 2 respectively
419 	 */
420 	WR1(sc, HDMI_FC_CH0PREAM, 0x0B);
421 	WR1(sc, HDMI_FC_CH1PREAM, 0x16);
422 	WR1(sc, HDMI_FC_CH2PREAM, 0x21);
423 
424 	/* Save CEC clock */
425 	clkdis = RD1(sc, HDMI_MC_CLKDIS) & HDMI_MC_CLKDIS_CECCLK_DISABLE;
426 	clkdis |= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
427 
428 	/* Enable pixel clock and tmds data path */
429 	clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
430 	WR1(sc, HDMI_MC_CLKDIS, clkdis);
431 
432 	clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
433 	WR1(sc, HDMI_MC_CLKDIS, clkdis);
434 }
435 
436 static void
437 dwc_hdmi_configure_audio(struct dwc_hdmi_softc *sc)
438 {
439 	unsigned int n;
440 	uint8_t val;
441 
442 	if (sc->sc_has_audio == 0)
443 		return;
444 
445 	/* The following values are for 48 kHz */
446 	switch (sc->sc_mode.dot_clock) {
447 	case 25170:
448 		n = 6864;
449 		break;
450 	case 27020:
451 		n = 6144;
452 		break;
453 	case 74170:
454 		n = 11648;
455 		break;
456 	case 148350:
457 		n = 5824;
458 		break;
459 	default:
460 		n = 6144;
461 		break;
462 	}
463 
464 	WR1(sc, HDMI_AUD_N1, (n >> 0) & 0xff);
465 	WR1(sc, HDMI_AUD_N2, (n >> 8) & 0xff);
466 	WR1(sc, HDMI_AUD_N3, (n >> 16) & 0xff);
467 
468 	val = RD1(sc, HDMI_AUD_CTS3);
469 	val &= ~(HDMI_AUD_CTS3_N_SHIFT_MASK | HDMI_AUD_CTS3_CTS_MANUAL);
470 	WR1(sc, HDMI_AUD_CTS3, val);
471 
472 	val = RD1(sc, HDMI_AUD_CONF0);
473 	val &= ~HDMI_AUD_CONF0_INTERFACE_MASK;
474 	val |= HDMI_AUD_CONF0_INTERFACE_IIS;
475 	val &= ~HDMI_AUD_CONF0_I2SINEN_MASK;
476 	val |= HDMI_AUD_CONF0_I2SINEN_CH2;
477 	WR1(sc, HDMI_AUD_CONF0, val);
478 
479 	val = RD1(sc, HDMI_AUD_CONF1);
480 	val &= ~HDMI_AUD_CONF1_DATAMODE_MASK;
481 	val |= HDMI_AUD_CONF1_DATAMODE_IIS;
482 	val &= ~HDMI_AUD_CONF1_DATWIDTH_MASK;
483 	val |= HDMI_AUD_CONF1_DATWIDTH_16BIT;
484 	WR1(sc, HDMI_AUD_CONF1, val);
485 
486 	WR1(sc, HDMI_AUD_INPUTCLKFS, HDMI_AUD_INPUTCLKFS_64);
487 
488 	WR1(sc, HDMI_FC_AUDICONF0, 1 << 4);	/* CC=1 */
489 	WR1(sc, HDMI_FC_AUDICONF1, 0);
490 	WR1(sc, HDMI_FC_AUDICONF2, 0);		/* CA=0 */
491 	WR1(sc, HDMI_FC_AUDICONF3, 0);
492 	WR1(sc, HDMI_FC_AUDSV, 0xee);		/* channels valid */
493 
494 	/* Enable audio clock */
495 	val = RD1(sc, HDMI_MC_CLKDIS);
496 	val &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
497 	WR1(sc, HDMI_MC_CLKDIS, val);
498 }
499 
500 static void
501 dwc_hdmi_video_packetize(struct dwc_hdmi_softc *sc)
502 {
503 	unsigned int color_depth = 0;
504 	unsigned int remap_size = HDMI_VP_REMAP_YCC422_16BIT;
505 	unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
506 	uint8_t val;
507 
508 	output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
509 	color_depth = 4;
510 
511 	/* set the packetizer registers */
512 	val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
513 		HDMI_VP_PR_CD_COLOR_DEPTH_MASK);
514 	WR1(sc, HDMI_VP_PR_CD, val);
515 
516 	val = RD1(sc, HDMI_VP_STUFF);
517 	val &= ~HDMI_VP_STUFF_PR_STUFFING_MASK;
518 	val |= HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE;
519 	WR1(sc, HDMI_VP_STUFF, val);
520 
521 	val = RD1(sc, HDMI_VP_CONF);
522 	val &= ~(HDMI_VP_CONF_PR_EN_MASK |
523 		HDMI_VP_CONF_BYPASS_SELECT_MASK);
524 	val |= HDMI_VP_CONF_PR_EN_DISABLE |
525 		HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
526 	WR1(sc, HDMI_VP_CONF, val);
527 
528 	val = RD1(sc, HDMI_VP_STUFF);
529 	val &= ~HDMI_VP_STUFF_IDEFAULT_PHASE_MASK;
530 	val |= 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET;
531 	WR1(sc, HDMI_VP_STUFF, val);
532 
533 	WR1(sc, HDMI_VP_REMAP, remap_size);
534 
535 	if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
536 		val = RD1(sc, HDMI_VP_CONF);
537 		val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
538 			HDMI_VP_CONF_PP_EN_ENMASK |
539 			HDMI_VP_CONF_YCC422_EN_MASK);
540 		val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
541 			HDMI_VP_CONF_PP_EN_ENABLE |
542 			HDMI_VP_CONF_YCC422_EN_DISABLE;
543 		WR1(sc, HDMI_VP_CONF, val);
544 	} else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
545 		val = RD1(sc, HDMI_VP_CONF);
546 		val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
547 			HDMI_VP_CONF_PP_EN_ENMASK |
548 			HDMI_VP_CONF_YCC422_EN_MASK);
549 		val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
550 			HDMI_VP_CONF_PP_EN_DISABLE |
551 			HDMI_VP_CONF_YCC422_EN_ENABLE;
552 		WR1(sc, HDMI_VP_CONF, val);
553 	} else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
554 		val = RD1(sc, HDMI_VP_CONF);
555 		val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
556 			HDMI_VP_CONF_PP_EN_ENMASK |
557 			HDMI_VP_CONF_YCC422_EN_MASK);
558 		val |= HDMI_VP_CONF_BYPASS_EN_ENABLE |
559 			HDMI_VP_CONF_PP_EN_DISABLE |
560 			HDMI_VP_CONF_YCC422_EN_DISABLE;
561 		WR1(sc, HDMI_VP_CONF, val);
562 	} else {
563 		return;
564 	}
565 
566 	val = RD1(sc, HDMI_VP_STUFF);
567 	val &= ~(HDMI_VP_STUFF_PP_STUFFING_MASK |
568 		HDMI_VP_STUFF_YCC422_STUFFING_MASK);
569 	val |= HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
570 		HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE;
571 	WR1(sc, HDMI_VP_STUFF, val);
572 
573 	val = RD1(sc, HDMI_VP_CONF);
574 	val &= ~HDMI_VP_CONF_OUTPUT_SELECTOR_MASK;
575 	val |= output_select;
576 	WR1(sc, HDMI_VP_CONF, val);
577 }
578 
579 static void
580 dwc_hdmi_video_sample(struct dwc_hdmi_softc *sc)
581 {
582 	int color_format;
583 	uint8_t val;
584 
585 	color_format = 0x01;
586 	val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
587 		((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
588 		HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
589 	WR1(sc, HDMI_TX_INVID0, val);
590 
591 	/* Enable TX stuffing: When DE is inactive, fix the output data to 0 */
592 	val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
593 		HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
594 		HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
595 	WR1(sc, HDMI_TX_INSTUFFING, val);
596 	WR1(sc, HDMI_TX_GYDATA0, 0x0);
597 	WR1(sc, HDMI_TX_GYDATA1, 0x0);
598 	WR1(sc, HDMI_TX_RCRDATA0, 0x0);
599 	WR1(sc, HDMI_TX_RCRDATA1, 0x0);
600 	WR1(sc, HDMI_TX_BCBDATA0, 0x0);
601 	WR1(sc, HDMI_TX_BCBDATA1, 0x0);
602 }
603 
604 static void
605 dwc_hdmi_tx_hdcp_config(struct dwc_hdmi_softc *sc)
606 {
607 	uint8_t de, val;
608 
609 	de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH;
610 
611 	/* Disable RX detect */
612 	val = RD1(sc, HDMI_A_HDCPCFG0);
613 	val &= ~HDMI_A_HDCPCFG0_RXDETECT_MASK;
614 	val |= HDMI_A_HDCPCFG0_RXDETECT_DISABLE;
615 	WR1(sc, HDMI_A_HDCPCFG0, val);
616 
617 	/* Set polarity */
618 	val = RD1(sc, HDMI_A_VIDPOLCFG);
619 	val &= ~HDMI_A_VIDPOLCFG_DATAENPOL_MASK;
620 	val |= de;
621 	WR1(sc, HDMI_A_VIDPOLCFG, val);
622 
623 	/* Disable encryption */
624 	val = RD1(sc, HDMI_A_HDCPCFG1);
625 	val &= ~HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK;
626 	val |= HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE;
627 	WR1(sc, HDMI_A_HDCPCFG1, val);
628 }
629 
630 static int
631 dwc_hdmi_set_mode(struct dwc_hdmi_softc *sc)
632 {
633 
634 	/* XXX */
635 	sc->sc_has_audio = 1;
636 
637 	dwc_hdmi_disable_overflow_interrupts(sc);
638 	dwc_hdmi_av_composer(sc);
639 	dwc_hdmi_phy_init(sc);
640 	dwc_hdmi_enable_video_path(sc);
641 	dwc_hdmi_configure_audio(sc);
642 	/* TODO:  dwc_hdmi_config_avi(sc); */
643 	dwc_hdmi_video_packetize(sc);
644 	/* TODO:  dwc_hdmi_video_csc(sc); */
645 	dwc_hdmi_video_sample(sc);
646 	dwc_hdmi_tx_hdcp_config(sc);
647 	dwc_hdmi_clear_overflow(sc);
648 
649 	return (0);
650 }
651 
652 static int
653 hdmi_edid_read(struct dwc_hdmi_softc *sc, int block, uint8_t **edid,
654     uint32_t *edid_len)
655 {
656 	device_t i2c_dev;
657 	int result;
658 	uint8_t addr = block & 1 ? EDID_LENGTH : 0;
659 	uint8_t segment = block >> 1;
660 	struct iic_msg msg[] = {
661 		{ I2C_DDC_SEGADDR, IIC_M_WR, 1, &segment },
662 		{ I2C_DDC_ADDR, IIC_M_WR, 1, &addr },
663 		{ I2C_DDC_ADDR, IIC_M_RD, EDID_LENGTH, sc->sc_edid }
664 	};
665 
666 	*edid = NULL;
667 	*edid_len = 0;
668 	i2c_dev = NULL;
669 
670 	if (sc->sc_get_i2c_dev != NULL)
671 		i2c_dev = sc->sc_get_i2c_dev(sc->sc_dev);
672 	if (!i2c_dev) {
673 		device_printf(sc->sc_dev, "no DDC device found\n");
674 		return (ENXIO);
675 	}
676 
677 	if (bootverbose)
678 		device_printf(sc->sc_dev,
679 		    "reading EDID from %s, block %d, addr %02x\n",
680 		    device_get_nameunit(i2c_dev), block, I2C_DDC_ADDR/2);
681 
682 	result = iicbus_request_bus(i2c_dev, sc->sc_dev, IIC_INTRWAIT);
683 
684 	if (result) {
685 		device_printf(sc->sc_dev, "failed to request i2c bus: %d\n", result);
686 		return (result);
687 	}
688 
689 	result = iicbus_transfer(i2c_dev, msg, 3);
690 	iicbus_release_bus(i2c_dev, sc->sc_dev);
691 
692 	if (result) {
693 		device_printf(sc->sc_dev, "i2c transfer failed: %d\n", result);
694 		return (result);
695 	} else {
696 		*edid_len = sc->sc_edid_len;
697 		*edid = sc->sc_edid;
698 	}
699 
700 	return (result);
701 }
702 
703 static void
704 dwc_hdmi_detect_cable(void *arg)
705 {
706 	struct dwc_hdmi_softc *sc;
707 	uint32_t stat;
708 
709 	sc = arg;
710 
711 	stat = RD1(sc, HDMI_IH_PHY_STAT0);
712 	if ((stat & HDMI_IH_PHY_STAT0_HPD) != 0) {
713 		EVENTHANDLER_INVOKE(hdmi_event, sc->sc_dev,
714 		    HDMI_EVENT_CONNECTED);
715 	}
716 
717 	/* Finished with the interrupt hook */
718 	config_intrhook_disestablish(&sc->sc_mode_hook);
719 }
720 
721 int
722 dwc_hdmi_init(device_t dev)
723 {
724 	struct dwc_hdmi_softc *sc;
725 	int err;
726 
727 	sc = device_get_softc(dev);
728 	err = 0;
729 
730 	sc->sc_edid = malloc(EDID_LENGTH, M_DEVBUF, M_WAITOK | M_ZERO);
731 	sc->sc_edid_len = EDID_LENGTH;
732 
733 	device_printf(sc->sc_dev, "HDMI controller %02x:%02x:%02x:%02x\n",
734 	    RD1(sc, HDMI_DESIGN_ID), RD1(sc, HDMI_REVISION_ID),
735 	    RD1(sc, HDMI_PRODUCT_ID0), RD1(sc, HDMI_PRODUCT_ID1));
736 
737 	WR1(sc, HDMI_PHY_POL0, HDMI_PHY_POL0_HPD);
738 	WR1(sc, HDMI_IH_PHY_STAT0, HDMI_IH_PHY_STAT0_HPD);
739 
740 	sc->sc_mode_hook.ich_func = dwc_hdmi_detect_cable;
741 	sc->sc_mode_hook.ich_arg = sc;
742 	if (config_intrhook_establish(&sc->sc_mode_hook) != 0) {
743 		err = ENOMEM;
744 		goto out;
745 	}
746 
747 out:
748 
749 	if (err != 0) {
750 		free(sc->sc_edid, M_DEVBUF);
751 		sc->sc_edid = NULL;
752 	}
753 
754 	return (err);
755 }
756 
757 static int
758 dwc_hdmi_detect_hdmi_vsdb(uint8_t *edid)
759 {
760 	int off, p, btag, blen;
761 
762 	if (edid[EXT_TAG] != CEA_TAG_ID)
763 		return (0);
764 
765 	off = edid[CEA_DATA_OFF];
766 
767 	/* CEA data block collection starts at byte 4 */
768 	if (off <= CEA_DATA_START)
769 		return (0);
770 
771 	/* Parse the CEA data blocks */
772 	for (p = CEA_DATA_START; p < off;) {
773 		btag = BLOCK_TAG(edid[p]);
774 		blen = BLOCK_LEN(edid[p]);
775 
776 		/* Make sure the length is sane */
777 		if (p + blen + 1 > off)
778 			break;
779 
780 		/* Look for a VSDB with the HDMI 24-bit IEEE registration ID */
781 		if (btag == BLOCK_TAG_VSDB && blen >= HDMI_VSDB_MINLEN &&
782 		    memcmp(&edid[p + 1], HDMI_OUI, HDMI_OUI_LEN) == 0)
783 			return (1);
784 
785 		/* Next data block */
786 		p += (1 + blen);
787 	}
788 
789 	/* Not found */
790 	return (0);
791 }
792 
793 static void
794 dwc_hdmi_detect_hdmi(struct dwc_hdmi_softc *sc)
795 {
796 	uint8_t *edid;
797 	uint32_t edid_len;
798 	int block;
799 
800 	sc->sc_has_audio = 0;
801 
802 	/* Scan through extension blocks, looking for a CEA-861 block */
803 	for (block = 1; block <= sc->sc_edid_info.edid_ext_block_count;
804 	    block++) {
805 		if (hdmi_edid_read(sc, block, &edid, &edid_len) != 0)
806 			return;
807 		if (dwc_hdmi_detect_hdmi_vsdb(edid) != 0) {
808 			if (bootverbose)
809 				device_printf(sc->sc_dev,
810 				    "enabling audio support\n");
811 			sc->sc_has_audio =
812 			    (edid[CEA_DTD] & DTD_BASIC_AUDIO) != 0;
813 			return;
814 		}
815 	}
816 }
817 
818 int
819 dwc_hdmi_get_edid(device_t dev, uint8_t **edid, uint32_t *edid_len)
820 {
821 	struct dwc_hdmi_softc *sc;
822 	int error;
823 
824 	sc = device_get_softc(dev);
825 
826 	memset(&sc->sc_edid_info, 0, sizeof(sc->sc_edid_info));
827 
828 	error = hdmi_edid_read(sc, 0, edid, edid_len);
829 	if (error != 0)
830 		return (error);
831 
832 	edid_parse(*edid, &sc->sc_edid_info);
833 
834 	return (0);
835 }
836 
837 int
838 dwc_hdmi_set_videomode(device_t dev, const struct videomode *mode)
839 {
840 	struct dwc_hdmi_softc *sc;
841 
842 	sc = device_get_softc(dev);
843 	memcpy(&sc->sc_mode, mode, sizeof(*mode));
844 
845 	dwc_hdmi_detect_hdmi(sc);
846 
847 	dwc_hdmi_set_mode(sc);
848 
849 	return (0);
850 }
851