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