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 74 static void 75 dwc_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 91 static void 92 dwc_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 106 static void 107 dwc_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 114 static void 115 dwc_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 183 static void 184 dwc_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 194 static void 195 dwc_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 205 static void 206 dwc_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 216 static void 217 dwc_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 227 static void 228 dwc_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 238 static void 239 dwc_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 249 static inline void 250 dwc_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 261 static void 262 dwc_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 276 static int 277 dwc_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 387 static void 388 dwc_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 404 static void 405 dwc_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 437 static void 438 dwc_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 501 static void 502 dwc_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 580 static void 581 dwc_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 605 static void 606 dwc_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 631 static int 632 dwc_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 653 static int 654 hdmi_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 709 static void 710 dwc_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 727 int 728 dwc_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 753 out: 754 755 if (err != 0) { 756 free(sc->sc_edid, M_DEVBUF); 757 sc->sc_edid = NULL; 758 } 759 760 return (err); 761 } 762 763 static int 764 dwc_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 799 static void 800 dwc_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 824 int 825 dwc_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 843 int 844 dwc_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