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