1 /* 2 * Copyright (c) 2015 Google, Inc 3 * Copyright 2014 Rockchip Inc. 4 * Copyright 2017 Jernej Skrabec <jernej.skrabec@siol.net> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <fdtdec.h> 11 #include <asm/io.h> 12 #include "dw_hdmi.h" 13 14 struct tmds_n_cts { 15 u32 tmds; 16 u32 cts; 17 u32 n; 18 }; 19 20 static const struct tmds_n_cts n_cts_table[] = { 21 { 22 .tmds = 25175000, .n = 6144, .cts = 25175, 23 }, { 24 .tmds = 25200000, .n = 6144, .cts = 25200, 25 }, { 26 .tmds = 27000000, .n = 6144, .cts = 27000, 27 }, { 28 .tmds = 27027000, .n = 6144, .cts = 27027, 29 }, { 30 .tmds = 40000000, .n = 6144, .cts = 40000, 31 }, { 32 .tmds = 54000000, .n = 6144, .cts = 54000, 33 }, { 34 .tmds = 54054000, .n = 6144, .cts = 54054, 35 }, { 36 .tmds = 65000000, .n = 6144, .cts = 65000, 37 }, { 38 .tmds = 74176000, .n = 11648, .cts = 140625, 39 }, { 40 .tmds = 74250000, .n = 6144, .cts = 74250, 41 }, { 42 .tmds = 83500000, .n = 6144, .cts = 83500, 43 }, { 44 .tmds = 106500000, .n = 6144, .cts = 106500, 45 }, { 46 .tmds = 108000000, .n = 6144, .cts = 108000, 47 }, { 48 .tmds = 148352000, .n = 5824, .cts = 140625, 49 }, { 50 .tmds = 148500000, .n = 6144, .cts = 148500, 51 }, { 52 .tmds = 297000000, .n = 5120, .cts = 247500, 53 } 54 }; 55 56 static void hdmi_write(struct dw_hdmi *hdmi, u8 val, int offset) 57 { 58 switch (hdmi->reg_io_width) { 59 case 1: 60 writeb(val, hdmi->ioaddr + offset); 61 break; 62 case 4: 63 writel(val, hdmi->ioaddr + (offset << 2)); 64 break; 65 default: 66 debug("reg_io_width has unsupported width!\n"); 67 break; 68 } 69 } 70 71 static u8 hdmi_read(struct dw_hdmi *hdmi, int offset) 72 { 73 switch (hdmi->reg_io_width) { 74 case 1: 75 return readb(hdmi->ioaddr + offset); 76 case 4: 77 return readl(hdmi->ioaddr + (offset << 2)); 78 default: 79 debug("reg_io_width has unsupported width!\n"); 80 break; 81 } 82 83 return 0; 84 } 85 86 static void hdmi_mod(struct dw_hdmi *hdmi, unsigned reg, u8 mask, u8 data) 87 { 88 u8 val = hdmi_read(hdmi, reg) & ~mask; 89 90 val |= data & mask; 91 hdmi_write(hdmi, val, reg); 92 } 93 94 static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi, u32 n, u32 cts) 95 { 96 uint cts3; 97 uint n3; 98 99 /* first set ncts_atomic_write (if present) */ 100 n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE; 101 hdmi_write(hdmi, n3, HDMI_AUD_N3); 102 103 /* set cts_manual (if present) */ 104 cts3 = HDMI_AUD_CTS3_CTS_MANUAL; 105 106 cts3 |= HDMI_AUD_CTS3_N_SHIFT_1 << HDMI_AUD_CTS3_N_SHIFT_OFFSET; 107 cts3 |= (cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK; 108 109 /* write cts values; cts3 must be written first */ 110 hdmi_write(hdmi, cts3, HDMI_AUD_CTS3); 111 hdmi_write(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2); 112 hdmi_write(hdmi, cts & 0xff, HDMI_AUD_CTS1); 113 114 /* write n values; n1 must be written last */ 115 n3 |= (n >> 16) & HDMI_AUD_N3_AUDN19_16_MASK; 116 hdmi_write(hdmi, n3, HDMI_AUD_N3); 117 hdmi_write(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2); 118 hdmi_write(hdmi, n & 0xff, HDMI_AUD_N3); 119 120 hdmi_write(hdmi, HDMI_AUD_INPUTCLKFS_128, HDMI_AUD_INPUTCLKFS); 121 } 122 123 static int hdmi_lookup_n_cts(u32 pixel_clk) 124 { 125 int i; 126 127 for (i = 0; i < ARRAY_SIZE(n_cts_table); i++) 128 if (pixel_clk <= n_cts_table[i].tmds) 129 break; 130 131 if (i >= ARRAY_SIZE(n_cts_table)) 132 return -1; 133 134 return i; 135 } 136 137 static void hdmi_audio_set_samplerate(struct dw_hdmi *hdmi, u32 pixel_clk) 138 { 139 u32 clk_n, clk_cts; 140 int index; 141 142 index = hdmi_lookup_n_cts(pixel_clk); 143 if (index == -1) { 144 debug("audio not supported for pixel clk %d\n", pixel_clk); 145 return; 146 } 147 148 clk_n = n_cts_table[index].n; 149 clk_cts = n_cts_table[index].cts; 150 hdmi_set_clock_regenerator(hdmi, clk_n, clk_cts); 151 } 152 153 /* 154 * this submodule is responsible for the video data synchronization. 155 * for example, for rgb 4:4:4 input, the data map is defined as 156 * pin{47~40} <==> r[7:0] 157 * pin{31~24} <==> g[7:0] 158 * pin{15~8} <==> b[7:0] 159 */ 160 static void hdmi_video_sample(struct dw_hdmi *hdmi) 161 { 162 u32 color_format = 0x01; 163 uint val; 164 165 val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE | 166 ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) & 167 HDMI_TX_INVID0_VIDEO_MAPPING_MASK); 168 169 hdmi_write(hdmi, val, HDMI_TX_INVID0); 170 171 /* enable tx stuffing: when de is inactive, fix the output data to 0 */ 172 val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE | 173 HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE | 174 HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE; 175 hdmi_write(hdmi, val, HDMI_TX_INSTUFFING); 176 hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA0); 177 hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA1); 178 hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA0); 179 hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA1); 180 hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA0); 181 hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA1); 182 } 183 184 static void hdmi_video_packetize(struct dw_hdmi *hdmi) 185 { 186 u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; 187 u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT; 188 u32 color_depth = 0; 189 uint val, vp_conf; 190 191 /* set the packetizer registers */ 192 val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) & 193 HDMI_VP_PR_CD_COLOR_DEPTH_MASK) | 194 ((0 << HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) & 195 HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK); 196 hdmi_write(hdmi, val, HDMI_VP_PR_CD); 197 198 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PR_STUFFING_MASK, 199 HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE); 200 201 /* data from pixel repeater block */ 202 vp_conf = HDMI_VP_CONF_PR_EN_DISABLE | 203 HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER; 204 205 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_PR_EN_MASK | 206 HDMI_VP_CONF_BYPASS_SELECT_MASK, vp_conf); 207 208 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, 209 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET); 210 211 hdmi_write(hdmi, remap_size, HDMI_VP_REMAP); 212 213 vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE | 214 HDMI_VP_CONF_PP_EN_DISABLE | 215 HDMI_VP_CONF_YCC422_EN_DISABLE; 216 217 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_BYPASS_EN_MASK | 218 HDMI_VP_CONF_PP_EN_ENMASK | HDMI_VP_CONF_YCC422_EN_MASK, 219 vp_conf); 220 221 hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PP_STUFFING_MASK | 222 HDMI_VP_STUFF_YCC422_STUFFING_MASK, 223 HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE | 224 HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE); 225 226 hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK, 227 output_select); 228 } 229 230 static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, uint bit) 231 { 232 hdmi_mod(hdmi, HDMI_PHY_TST0, HDMI_PHY_TST0_TSTCLR_MASK, 233 bit << HDMI_PHY_TST0_TSTCLR_OFFSET); 234 } 235 236 static int hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, u32 msec) 237 { 238 ulong start; 239 u32 val; 240 241 start = get_timer(0); 242 do { 243 val = hdmi_read(hdmi, HDMI_IH_I2CMPHY_STAT0); 244 if (val & 0x3) { 245 hdmi_write(hdmi, val, HDMI_IH_I2CMPHY_STAT0); 246 return 0; 247 } 248 249 udelay(100); 250 } while (get_timer(start) < msec); 251 252 return 1; 253 } 254 255 static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, uint data, uint addr) 256 { 257 hdmi_write(hdmi, 0xff, HDMI_IH_I2CMPHY_STAT0); 258 hdmi_write(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR); 259 hdmi_write(hdmi, (u8)(data >> 8), HDMI_PHY_I2CM_DATAO_1_ADDR); 260 hdmi_write(hdmi, (u8)(data >> 0), HDMI_PHY_I2CM_DATAO_0_ADDR); 261 hdmi_write(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE, 262 HDMI_PHY_I2CM_OPERATION_ADDR); 263 264 hdmi_phy_wait_i2c_done(hdmi, 1000); 265 } 266 267 static void hdmi_phy_enable_power(struct dw_hdmi *hdmi, uint enable) 268 { 269 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_PDZ_MASK, 270 enable << HDMI_PHY_CONF0_PDZ_OFFSET); 271 } 272 273 static void hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, uint enable) 274 { 275 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_ENTMDS_MASK, 276 enable << HDMI_PHY_CONF0_ENTMDS_OFFSET); 277 } 278 279 static void hdmi_phy_enable_spare(struct dw_hdmi *hdmi, uint enable) 280 { 281 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SPARECTRL_MASK, 282 enable << HDMI_PHY_CONF0_SPARECTRL_OFFSET); 283 } 284 285 static void hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, uint enable) 286 { 287 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_GEN2_PDDQ_MASK, 288 enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET); 289 } 290 291 static void hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, uint enable) 292 { 293 hdmi_mod(hdmi, HDMI_PHY_CONF0, 294 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK, 295 enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET); 296 } 297 298 static void hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, uint enable) 299 { 300 hdmi_mod(hdmi, HDMI_PHY_CONF0, 301 HDMI_PHY_CONF0_SELDATAENPOL_MASK, 302 enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET); 303 } 304 305 static void hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, 306 uint enable) 307 { 308 hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SELDIPIF_MASK, 309 enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET); 310 } 311 312 static int hdmi_phy_configure(struct dw_hdmi *hdmi, u32 mpixelclock) 313 { 314 ulong start; 315 uint i, val; 316 317 if (!hdmi->mpll_cfg || !hdmi->phy_cfg) 318 return -1; 319 320 /* gen2 tx power off */ 321 hdmi_phy_gen2_txpwron(hdmi, 0); 322 323 /* gen2 pddq */ 324 hdmi_phy_gen2_pddq(hdmi, 1); 325 326 /* phy reset */ 327 hdmi_write(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ); 328 hdmi_write(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ); 329 hdmi_write(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST); 330 331 hdmi_phy_test_clear(hdmi, 1); 332 hdmi_write(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, 333 HDMI_PHY_I2CM_SLAVE_ADDR); 334 hdmi_phy_test_clear(hdmi, 0); 335 336 /* pll/mpll cfg - always match on final entry */ 337 for (i = 0; hdmi->mpll_cfg[i].mpixelclock != (~0ul); i++) 338 if (mpixelclock <= hdmi->mpll_cfg[i].mpixelclock) 339 break; 340 341 hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].cpce, PHY_OPMODE_PLLCFG); 342 hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].gmp, PHY_PLLGMPCTRL); 343 hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].curr, PHY_PLLCURRCTRL); 344 345 hdmi_phy_i2c_write(hdmi, 0x0000, PHY_PLLPHBYCTRL); 346 hdmi_phy_i2c_write(hdmi, 0x0006, PHY_PLLCLKBISTPHASE); 347 348 for (i = 0; hdmi->phy_cfg[i].mpixelclock != (~0ul); i++) 349 if (mpixelclock <= hdmi->phy_cfg[i].mpixelclock) 350 break; 351 352 /* 353 * resistance term 133ohm cfg 354 * preemp cgf 0.00 355 * tx/ck lvl 10 356 */ 357 hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].term, PHY_TXTERM); 358 hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].sym_ctr, PHY_CKSYMTXCTRL); 359 hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].vlev_ctr, PHY_VLEVCTRL); 360 361 /* remove clk term */ 362 hdmi_phy_i2c_write(hdmi, 0x8000, PHY_CKCALCTRL); 363 364 hdmi_phy_enable_power(hdmi, 1); 365 366 /* toggle tmds enable */ 367 hdmi_phy_enable_tmds(hdmi, 0); 368 hdmi_phy_enable_tmds(hdmi, 1); 369 370 /* gen2 tx power on */ 371 hdmi_phy_gen2_txpwron(hdmi, 1); 372 hdmi_phy_gen2_pddq(hdmi, 0); 373 374 hdmi_phy_enable_spare(hdmi, 1); 375 376 /* wait for phy pll lock */ 377 start = get_timer(0); 378 do { 379 val = hdmi_read(hdmi, HDMI_PHY_STAT0); 380 if (!(val & HDMI_PHY_TX_PHY_LOCK)) 381 return 0; 382 383 udelay(100); 384 } while (get_timer(start) < 5); 385 386 return -1; 387 } 388 389 static void hdmi_av_composer(struct dw_hdmi *hdmi, 390 const struct display_timing *edid) 391 { 392 bool mdataenablepolarity = true; 393 uint inv_val; 394 uint hbl; 395 uint vbl; 396 397 hbl = edid->hback_porch.typ + edid->hfront_porch.typ + 398 edid->hsync_len.typ; 399 vbl = edid->vback_porch.typ + edid->vfront_porch.typ + 400 edid->vsync_len.typ; 401 402 /* set up hdmi_fc_invidconf */ 403 inv_val = HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE; 404 405 inv_val |= (edid->flags & DISPLAY_FLAGS_HSYNC_HIGH ? 406 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH : 407 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW); 408 409 inv_val |= (edid->flags & DISPLAY_FLAGS_VSYNC_HIGH ? 410 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH : 411 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW); 412 413 inv_val |= (mdataenablepolarity ? 414 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH : 415 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW); 416 417 /* 418 * TODO(sjg@chromium.org>: Need to check for HDMI / DVI 419 * inv_val |= (edid->hdmi_monitor_detected ? 420 * HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE : 421 * HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE); 422 */ 423 inv_val |= HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE; 424 425 inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW; 426 427 inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE; 428 429 hdmi_write(hdmi, inv_val, HDMI_FC_INVIDCONF); 430 431 /* set up horizontal active pixel width */ 432 hdmi_write(hdmi, edid->hactive.typ >> 8, HDMI_FC_INHACTV1); 433 hdmi_write(hdmi, edid->hactive.typ, HDMI_FC_INHACTV0); 434 435 /* set up vertical active lines */ 436 hdmi_write(hdmi, edid->vactive.typ >> 8, HDMI_FC_INVACTV1); 437 hdmi_write(hdmi, edid->vactive.typ, HDMI_FC_INVACTV0); 438 439 /* set up horizontal blanking pixel region width */ 440 hdmi_write(hdmi, hbl >> 8, HDMI_FC_INHBLANK1); 441 hdmi_write(hdmi, hbl, HDMI_FC_INHBLANK0); 442 443 /* set up vertical blanking pixel region width */ 444 hdmi_write(hdmi, vbl, HDMI_FC_INVBLANK); 445 446 /* set up hsync active edge delay width (in pixel clks) */ 447 hdmi_write(hdmi, edid->hfront_porch.typ >> 8, HDMI_FC_HSYNCINDELAY1); 448 hdmi_write(hdmi, edid->hfront_porch.typ, HDMI_FC_HSYNCINDELAY0); 449 450 /* set up vsync active edge delay (in lines) */ 451 hdmi_write(hdmi, edid->vfront_porch.typ, HDMI_FC_VSYNCINDELAY); 452 453 /* set up hsync active pulse width (in pixel clks) */ 454 hdmi_write(hdmi, edid->hsync_len.typ >> 8, HDMI_FC_HSYNCINWIDTH1); 455 hdmi_write(hdmi, edid->hsync_len.typ, HDMI_FC_HSYNCINWIDTH0); 456 457 /* set up vsync active edge delay (in lines) */ 458 hdmi_write(hdmi, edid->vsync_len.typ, HDMI_FC_VSYNCINWIDTH); 459 } 460 461 /* hdmi initialization step b.4 */ 462 static void hdmi_enable_video_path(struct dw_hdmi *hdmi) 463 { 464 uint clkdis; 465 466 /* control period minimum duration */ 467 hdmi_write(hdmi, 12, HDMI_FC_CTRLDUR); 468 hdmi_write(hdmi, 32, HDMI_FC_EXCTRLDUR); 469 hdmi_write(hdmi, 1, HDMI_FC_EXCTRLSPAC); 470 471 /* set to fill tmds data channels */ 472 hdmi_write(hdmi, 0x0b, HDMI_FC_CH0PREAM); 473 hdmi_write(hdmi, 0x16, HDMI_FC_CH1PREAM); 474 hdmi_write(hdmi, 0x21, HDMI_FC_CH2PREAM); 475 476 hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS, 477 HDMI_MC_FLOWCTRL); 478 479 /* enable pixel clock and tmds data path */ 480 clkdis = 0x7f; 481 clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE; 482 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS); 483 484 clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE; 485 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS); 486 487 clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE; 488 hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS); 489 } 490 491 /* workaround to clear the overflow condition */ 492 static void hdmi_clear_overflow(struct dw_hdmi *hdmi) 493 { 494 uint val, count; 495 496 /* tmds software reset */ 497 hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ); 498 499 val = hdmi_read(hdmi, HDMI_FC_INVIDCONF); 500 501 for (count = 0; count < 4; count++) 502 hdmi_write(hdmi, val, HDMI_FC_INVIDCONF); 503 } 504 505 static void hdmi_audio_set_format(struct dw_hdmi *hdmi) 506 { 507 hdmi_write(hdmi, HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_IN_EN_0, 508 HDMI_AUD_CONF0); 509 510 511 hdmi_write(hdmi, HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE | 512 HDMI_AUD_CONF1_I2S_WIDTH_16BIT, HDMI_AUD_CONF1); 513 514 hdmi_write(hdmi, 0x00, HDMI_AUD_CONF2); 515 } 516 517 static void hdmi_audio_fifo_reset(struct dw_hdmi *hdmi) 518 { 519 hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_II2SSWRST_REQ, HDMI_MC_SWRSTZ); 520 hdmi_write(hdmi, HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST, HDMI_AUD_CONF0); 521 522 hdmi_write(hdmi, 0x00, HDMI_AUD_INT); 523 hdmi_write(hdmi, 0x00, HDMI_AUD_INT1); 524 } 525 526 static int hdmi_get_plug_in_status(struct dw_hdmi *hdmi) 527 { 528 uint val = hdmi_read(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD; 529 530 return !!val; 531 } 532 533 static int hdmi_ddc_wait_i2c_done(struct dw_hdmi *hdmi, int msec) 534 { 535 u32 val; 536 ulong start; 537 538 start = get_timer(0); 539 do { 540 val = hdmi_read(hdmi, HDMI_IH_I2CM_STAT0); 541 if (val & 0x2) { 542 hdmi_write(hdmi, val, HDMI_IH_I2CM_STAT0); 543 return 0; 544 } 545 546 udelay(100); 547 } while (get_timer(start) < msec); 548 549 return 1; 550 } 551 552 static void hdmi_ddc_reset(struct dw_hdmi *hdmi) 553 { 554 hdmi_mod(hdmi, HDMI_I2CM_SOFTRSTZ, HDMI_I2CM_SOFTRSTZ_MASK, 0); 555 } 556 557 static int hdmi_read_edid(struct dw_hdmi *hdmi, int block, u8 *buff) 558 { 559 int shift = (block % 2) * 0x80; 560 int edid_read_err = 0; 561 u32 trytime = 5; 562 u32 n; 563 564 /* set ddc i2c clk which devided from ddc_clk to 100khz */ 565 hdmi_write(hdmi, hdmi->i2c_clk_high, HDMI_I2CM_SS_SCL_HCNT_0_ADDR); 566 hdmi_write(hdmi, hdmi->i2c_clk_low, HDMI_I2CM_SS_SCL_LCNT_0_ADDR); 567 hdmi_mod(hdmi, HDMI_I2CM_DIV, HDMI_I2CM_DIV_FAST_STD_MODE, 568 HDMI_I2CM_DIV_STD_MODE); 569 570 hdmi_write(hdmi, HDMI_I2CM_SLAVE_DDC_ADDR, HDMI_I2CM_SLAVE); 571 hdmi_write(hdmi, HDMI_I2CM_SEGADDR_DDC, HDMI_I2CM_SEGADDR); 572 hdmi_write(hdmi, block >> 1, HDMI_I2CM_SEGPTR); 573 574 while (trytime--) { 575 edid_read_err = 0; 576 577 for (n = 0; n < HDMI_EDID_BLOCK_SIZE; n++) { 578 hdmi_write(hdmi, shift + n, HDMI_I2CM_ADDRESS); 579 580 if (block == 0) 581 hdmi_write(hdmi, HDMI_I2CM_OP_RD8, 582 HDMI_I2CM_OPERATION); 583 else 584 hdmi_write(hdmi, HDMI_I2CM_OP_RD8_EXT, 585 HDMI_I2CM_OPERATION); 586 587 if (hdmi_ddc_wait_i2c_done(hdmi, 10)) { 588 hdmi_ddc_reset(hdmi); 589 edid_read_err = 1; 590 break; 591 } 592 593 buff[n] = hdmi_read(hdmi, HDMI_I2CM_DATAI); 594 } 595 596 if (!edid_read_err) 597 break; 598 } 599 600 return edid_read_err; 601 } 602 603 static const u8 pre_buf[] = { 604 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 605 0x04, 0x69, 0xfa, 0x23, 0xc8, 0x28, 0x01, 0x00, 606 0x10, 0x17, 0x01, 0x03, 0x80, 0x33, 0x1d, 0x78, 607 0x2a, 0xd9, 0x45, 0xa2, 0x55, 0x4d, 0xa0, 0x27, 608 0x12, 0x50, 0x54, 0xb7, 0xef, 0x00, 0x71, 0x4f, 609 0x81, 0x40, 0x81, 0x80, 0x95, 0x00, 0xb3, 0x00, 610 0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x00, 0x02, 0x3a, 611 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, 612 0x45, 0x00, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e, 613 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x34, 0x4c, 614 0x4d, 0x54, 0x46, 0x30, 0x37, 0x35, 0x39, 0x37, 615 0x36, 0x0a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32, 616 0x4b, 0x18, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20, 617 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 618 0x00, 0x41, 0x53, 0x55, 0x53, 0x20, 0x56, 0x53, 619 0x32, 0x33, 0x38, 0x0a, 0x20, 0x20, 0x01, 0xb0, 620 0x02, 0x03, 0x22, 0x71, 0x4f, 0x01, 0x02, 0x03, 621 0x11, 0x12, 0x13, 0x04, 0x14, 0x05, 0x0e, 0x0f, 622 0x1d, 0x1e, 0x1f, 0x10, 0x23, 0x09, 0x17, 0x07, 623 0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0c, 0x00, 624 0x10, 0x00, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 625 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xfd, 0x1e, 626 0x11, 0x00, 0x00, 0x18, 0x01, 0x1d, 0x00, 0x72, 627 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 628 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e, 0x01, 0x1d, 629 0x00, 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28, 630 0x55, 0x40, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e, 631 0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20, 632 0x0c, 0x40, 0x55, 0x00, 0xfd, 0x1e, 0x11, 0x00, 633 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9, 636 }; 637 638 int dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint mpixelclock) 639 { 640 int i, ret; 641 642 /* hdmi phy spec says to do the phy initialization sequence twice */ 643 for (i = 0; i < 2; i++) { 644 hdmi_phy_sel_data_en_pol(hdmi, 1); 645 hdmi_phy_sel_interface_control(hdmi, 0); 646 hdmi_phy_enable_tmds(hdmi, 0); 647 hdmi_phy_enable_power(hdmi, 0); 648 649 ret = hdmi_phy_configure(hdmi, mpixelclock); 650 if (ret) { 651 debug("hdmi phy config failure %d\n", ret); 652 return ret; 653 } 654 } 655 656 return 0; 657 } 658 659 int dw_hdmi_phy_wait_for_hpd(struct dw_hdmi *hdmi) 660 { 661 ulong start; 662 663 start = get_timer(0); 664 do { 665 if (hdmi_get_plug_in_status(hdmi)) 666 return 0; 667 udelay(100); 668 } while (get_timer(start) < 300); 669 670 return -1; 671 } 672 673 void dw_hdmi_phy_init(struct dw_hdmi *hdmi) 674 { 675 /* enable phy i2cm done irq */ 676 hdmi_write(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL, 677 HDMI_PHY_I2CM_INT_ADDR); 678 679 /* enable phy i2cm nack & arbitration error irq */ 680 hdmi_write(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL | 681 HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL, 682 HDMI_PHY_I2CM_CTLINT_ADDR); 683 684 /* enable cable hot plug irq */ 685 hdmi_write(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0); 686 687 /* clear hotplug interrupts */ 688 hdmi_write(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0); 689 } 690 691 int dw_hdmi_read_edid(struct dw_hdmi *hdmi, u8 *buf, int buf_size) 692 { 693 u32 edid_size = HDMI_EDID_BLOCK_SIZE; 694 int ret; 695 696 if (0) { 697 edid_size = sizeof(pre_buf); 698 memcpy(buf, pre_buf, edid_size); 699 } else { 700 ret = hdmi_read_edid(hdmi, 0, buf); 701 if (ret) { 702 debug("failed to read edid.\n"); 703 return -1; 704 } 705 706 if (buf[0x7e] != 0) { 707 hdmi_read_edid(hdmi, 1, buf + HDMI_EDID_BLOCK_SIZE); 708 edid_size += HDMI_EDID_BLOCK_SIZE; 709 } 710 } 711 712 return edid_size; 713 } 714 715 int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid) 716 { 717 int ret; 718 719 debug("hdmi, mode info : clock %d hdis %d vdis %d\n", 720 edid->pixelclock.typ, edid->hactive.typ, edid->vactive.typ); 721 722 hdmi_av_composer(hdmi, edid); 723 724 ret = hdmi->phy_set(hdmi, edid->pixelclock.typ); 725 if (ret) 726 return ret; 727 728 hdmi_enable_video_path(hdmi); 729 730 hdmi_audio_fifo_reset(hdmi); 731 hdmi_audio_set_format(hdmi); 732 hdmi_audio_set_samplerate(hdmi, edid->pixelclock.typ); 733 734 hdmi_video_packetize(hdmi); 735 hdmi_video_sample(hdmi); 736 737 hdmi_clear_overflow(hdmi); 738 739 return 0; 740 } 741 742 void dw_hdmi_init(struct dw_hdmi *hdmi) 743 { 744 uint ih_mute; 745 746 /* 747 * boot up defaults are: 748 * hdmi_ih_mute = 0x03 (disabled) 749 * hdmi_ih_mute_* = 0x00 (enabled) 750 * 751 * disable top level interrupt bits in hdmi block 752 */ 753 ih_mute = /*hdmi_read(hdmi, HDMI_IH_MUTE) |*/ 754 HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT | 755 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT; 756 757 hdmi_write(hdmi, ih_mute, HDMI_IH_MUTE); 758 759 /* enable i2c master done irq */ 760 hdmi_write(hdmi, ~0x04, HDMI_I2CM_INT); 761 762 /* enable i2c client nack % arbitration error irq */ 763 hdmi_write(hdmi, ~0x44, HDMI_I2CM_CTLINT); 764 } 765