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