1/* 2 * Copyright © 2012 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * Authors: 24 * Eugeni Dodonov <eugeni.dodonov@intel.com> 25 * 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD$"); 30 31#include <dev/drm2/drmP.h> 32#include <dev/drm2/drm.h> 33#include <dev/drm2/i915/i915_drm.h> 34#include <dev/drm2/i915/i915_drv.h> 35#include <dev/drm2/i915/intel_drv.h> 36 37/* HDMI/DVI modes ignore everything but the last 2 items. So we share 38 * them for both DP and FDI transports, allowing those ports to 39 * automatically adapt to HDMI connections as well 40 */ 41static const u32 hsw_ddi_translations_dp[] = { 42 0x00FFFFFF, 0x0006000E, /* DP parameters */ 43 0x00D75FFF, 0x0005000A, 44 0x00C30FFF, 0x00040006, 45 0x80AAAFFF, 0x000B0000, 46 0x00FFFFFF, 0x0005000A, 47 0x00D75FFF, 0x000C0004, 48 0x80C30FFF, 0x000B0000, 49 0x00FFFFFF, 0x00040006, 50 0x80D75FFF, 0x000B0000, 51 0x00FFFFFF, 0x00040006 /* HDMI parameters */ 52}; 53 54static const u32 hsw_ddi_translations_fdi[] = { 55 0x00FFFFFF, 0x0007000E, /* FDI parameters */ 56 0x00D75FFF, 0x000F000A, 57 0x00C30FFF, 0x00060006, 58 0x00AAAFFF, 0x001E0000, 59 0x00FFFFFF, 0x000F000A, 60 0x00D75FFF, 0x00160004, 61 0x00C30FFF, 0x001E0000, 62 0x00FFFFFF, 0x00060006, 63 0x00D75FFF, 0x001E0000, 64 0x00FFFFFF, 0x00040006 /* HDMI parameters */ 65}; 66 67/* On Haswell, DDI port buffers must be programmed with correct values 68 * in advance. The buffer values are different for FDI and DP modes, 69 * but the HDMI/DVI fields are shared among those. So we program the DDI 70 * in either FDI or DP modes only, as HDMI connections will work with both 71 * of those 72 */ 73static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, bool use_fdi_mode) 74{ 75 struct drm_i915_private *dev_priv = dev->dev_private; 76 u32 reg; 77 int i; 78 const u32 *ddi_translations = ((use_fdi_mode) ? 79 hsw_ddi_translations_fdi : 80 hsw_ddi_translations_dp); 81 82 DRM_DEBUG_DRIVER("Initializing DDI buffers for port %c in %s mode\n", 83 port_name(port), 84 use_fdi_mode ? "FDI" : "DP"); 85 86 if (use_fdi_mode && (port != PORT_E)) 87 DRM_DEBUG_KMS("Programming port %c in FDI mode, this probably will not work.\n", 88 port_name(port)); 89 90 for (i=0, reg=DDI_BUF_TRANS(port); i < DRM_ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { 91 I915_WRITE(reg, ddi_translations[i]); 92 reg += 4; 93 } 94} 95 96/* Program DDI buffers translations for DP. By default, program ports A-D in DP 97 * mode and port E for FDI. 98 */ 99void intel_prepare_ddi(struct drm_device *dev) 100{ 101 int port; 102 103 if (IS_HASWELL(dev)) { 104 for (port = PORT_A; port < PORT_E; port++) 105 intel_prepare_ddi_buffers(dev, port, false); 106 107 /* DDI E is the suggested one to work in FDI mode, so program is as such by 108 * default. It will have to be re-programmed in case a digital DP output 109 * will be detected on it 110 */ 111 intel_prepare_ddi_buffers(dev, PORT_E, true); 112 } 113} 114 115static const long hsw_ddi_buf_ctl_values[] = { 116 DDI_BUF_EMP_400MV_0DB_HSW, 117 DDI_BUF_EMP_400MV_3_5DB_HSW, 118 DDI_BUF_EMP_400MV_6DB_HSW, 119 DDI_BUF_EMP_400MV_9_5DB_HSW, 120 DDI_BUF_EMP_600MV_0DB_HSW, 121 DDI_BUF_EMP_600MV_3_5DB_HSW, 122 DDI_BUF_EMP_600MV_6DB_HSW, 123 DDI_BUF_EMP_800MV_0DB_HSW, 124 DDI_BUF_EMP_800MV_3_5DB_HSW 125}; 126 127 128/* Starting with Haswell, different DDI ports can work in FDI mode for 129 * connection to the PCH-located connectors. For this, it is necessary to train 130 * both the DDI port and PCH receiver for the desired DDI buffer settings. 131 * 132 * The recommended port to work in FDI mode is DDI E, which we use here. Also, 133 * please note that when FDI mode is active on DDI E, it shares 2 lines with 134 * DDI A (which is used for eDP) 135 */ 136 137void hsw_fdi_link_train(struct drm_crtc *crtc) 138{ 139 struct drm_device *dev = crtc->dev; 140 struct drm_i915_private *dev_priv = dev->dev_private; 141 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 142 int pipe = intel_crtc->pipe; 143 u32 reg, temp, i; 144 145 /* Configure CPU PLL, wait for warmup */ 146 I915_WRITE(SPLL_CTL, 147 SPLL_PLL_ENABLE | 148 SPLL_PLL_FREQ_1350MHz | 149 SPLL_PLL_SCC); 150 151 /* Use SPLL to drive the output when in FDI mode */ 152 I915_WRITE(PORT_CLK_SEL(PORT_E), 153 PORT_CLK_SEL_SPLL); 154 I915_WRITE(PIPE_CLK_SEL(pipe), 155 PIPE_CLK_SEL_PORT(PORT_E)); 156 157 DELAY(20); 158 159 /* Start the training iterating through available voltages and emphasis */ 160 for (i=0; i < DRM_ARRAY_SIZE(hsw_ddi_buf_ctl_values); i++) { 161 /* Configure DP_TP_CTL with auto-training */ 162 I915_WRITE(DP_TP_CTL(PORT_E), 163 DP_TP_CTL_FDI_AUTOTRAIN | 164 DP_TP_CTL_ENHANCED_FRAME_ENABLE | 165 DP_TP_CTL_LINK_TRAIN_PAT1 | 166 DP_TP_CTL_ENABLE); 167 168 /* Configure and enable DDI_BUF_CTL for DDI E with next voltage */ 169 temp = I915_READ(DDI_BUF_CTL(PORT_E)); 170 temp = (temp & ~DDI_BUF_EMP_MASK); 171 I915_WRITE(DDI_BUF_CTL(PORT_E), 172 temp | 173 DDI_BUF_CTL_ENABLE | 174 DDI_PORT_WIDTH_X2 | 175 hsw_ddi_buf_ctl_values[i]); 176 177 DELAY(600); 178 179 /* Enable CPU FDI Receiver with auto-training */ 180 reg = FDI_RX_CTL(pipe); 181 I915_WRITE(reg, 182 I915_READ(reg) | 183 FDI_LINK_TRAIN_AUTO | 184 FDI_RX_ENABLE | 185 FDI_LINK_TRAIN_PATTERN_1_CPT | 186 FDI_RX_ENHANCE_FRAME_ENABLE | 187 FDI_PORT_WIDTH_2X_LPT | 188 FDI_RX_PLL_ENABLE); 189 POSTING_READ(reg); 190 DELAY(100); 191 192 temp = I915_READ(DP_TP_STATUS(PORT_E)); 193 if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) { 194 DRM_DEBUG_DRIVER("BUF_CTL training done on %d step\n", i); 195 196 /* Enable normal pixel sending for FDI */ 197 I915_WRITE(DP_TP_CTL(PORT_E), 198 DP_TP_CTL_FDI_AUTOTRAIN | 199 DP_TP_CTL_LINK_TRAIN_NORMAL | 200 DP_TP_CTL_ENHANCED_FRAME_ENABLE | 201 DP_TP_CTL_ENABLE); 202 203 /* Enable PIPE_DDI_FUNC_CTL for the pipe to work in FDI mode */ 204 temp = I915_READ(DDI_FUNC_CTL(pipe)); 205 temp &= ~PIPE_DDI_PORT_MASK; 206 temp |= PIPE_DDI_SELECT_PORT(PORT_E) | 207 PIPE_DDI_MODE_SELECT_FDI | 208 PIPE_DDI_FUNC_ENABLE | 209 PIPE_DDI_PORT_WIDTH_X2; 210 I915_WRITE(DDI_FUNC_CTL(pipe), 211 temp); 212 break; 213 } else { 214 DRM_ERROR("Error training BUF_CTL %d\n", i); 215 216 /* Disable DP_TP_CTL and FDI_RX_CTL) and retry */ 217 I915_WRITE(DP_TP_CTL(PORT_E), 218 I915_READ(DP_TP_CTL(PORT_E)) & 219 ~DP_TP_CTL_ENABLE); 220 I915_WRITE(FDI_RX_CTL(pipe), 221 I915_READ(FDI_RX_CTL(pipe)) & 222 ~FDI_RX_PLL_ENABLE); 223 continue; 224 } 225 } 226 227 DRM_DEBUG_KMS("FDI train done.\n"); 228} 229 230/* For DDI connections, it is possible to support different outputs over the 231 * same DDI port, such as HDMI or DP or even VGA via FDI. So we don't know by 232 * the time the output is detected what exactly is on the other end of it. This 233 * function aims at providing support for this detection and proper output 234 * configuration. 235 */ 236void intel_ddi_init(struct drm_device *dev, enum port port) 237{ 238 /* For now, we don't do any proper output detection and assume that we 239 * handle HDMI only */ 240 241 switch(port){ 242 case PORT_A: 243 /* We don't handle eDP and DP yet */ 244 DRM_DEBUG_DRIVER("Found digital output on DDI port A\n"); 245 break; 246 /* Assume that the ports B, C and D are working in HDMI mode for now */ 247 case PORT_B: 248 case PORT_C: 249 case PORT_D: 250 intel_hdmi_init(dev, DDI_BUF_CTL(port)); 251 break; 252 default: 253 DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n", 254 port); 255 break; 256 } 257} 258 259/* WRPLL clock dividers */ 260struct wrpll_tmds_clock { 261 u32 clock; 262 u16 p; /* Post divider */ 263 u16 n2; /* Feedback divider */ 264 u16 r2; /* Reference divider */ 265}; 266 267/* Table of matching values for WRPLL clocks programming for each frequency */ 268static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = { 269 {19750, 38, 25, 18}, 270 {20000, 48, 32, 18}, 271 {21000, 36, 21, 15}, 272 {21912, 42, 29, 17}, 273 {22000, 36, 22, 15}, 274 {23000, 36, 23, 15}, 275 {23500, 40, 40, 23}, 276 {23750, 26, 16, 14}, 277 {23750, 26, 16, 14}, 278 {24000, 36, 24, 15}, 279 {25000, 36, 25, 15}, 280 {25175, 26, 40, 33}, 281 {25200, 30, 21, 15}, 282 {26000, 36, 26, 15}, 283 {27000, 30, 21, 14}, 284 {27027, 18, 100, 111}, 285 {27500, 30, 29, 19}, 286 {28000, 34, 30, 17}, 287 {28320, 26, 30, 22}, 288 {28322, 32, 42, 25}, 289 {28750, 24, 23, 18}, 290 {29000, 30, 29, 18}, 291 {29750, 32, 30, 17}, 292 {30000, 30, 25, 15}, 293 {30750, 30, 41, 24}, 294 {31000, 30, 31, 18}, 295 {31500, 30, 28, 16}, 296 {32000, 30, 32, 18}, 297 {32500, 28, 32, 19}, 298 {33000, 24, 22, 15}, 299 {34000, 28, 30, 17}, 300 {35000, 26, 32, 19}, 301 {35500, 24, 30, 19}, 302 {36000, 26, 26, 15}, 303 {36750, 26, 46, 26}, 304 {37000, 24, 23, 14}, 305 {37762, 22, 40, 26}, 306 {37800, 20, 21, 15}, 307 {38000, 24, 27, 16}, 308 {38250, 24, 34, 20}, 309 {39000, 24, 26, 15}, 310 {40000, 24, 32, 18}, 311 {40500, 20, 21, 14}, 312 {40541, 22, 147, 89}, 313 {40750, 18, 19, 14}, 314 {41000, 16, 17, 14}, 315 {41500, 22, 44, 26}, 316 {41540, 22, 44, 26}, 317 {42000, 18, 21, 15}, 318 {42500, 22, 45, 26}, 319 {43000, 20, 43, 27}, 320 {43163, 20, 24, 15}, 321 {44000, 18, 22, 15}, 322 {44900, 20, 108, 65}, 323 {45000, 20, 25, 15}, 324 {45250, 20, 52, 31}, 325 {46000, 18, 23, 15}, 326 {46750, 20, 45, 26}, 327 {47000, 20, 40, 23}, 328 {48000, 18, 24, 15}, 329 {49000, 18, 49, 30}, 330 {49500, 16, 22, 15}, 331 {50000, 18, 25, 15}, 332 {50500, 18, 32, 19}, 333 {51000, 18, 34, 20}, 334 {52000, 18, 26, 15}, 335 {52406, 14, 34, 25}, 336 {53000, 16, 22, 14}, 337 {54000, 16, 24, 15}, 338 {54054, 16, 173, 108}, 339 {54500, 14, 24, 17}, 340 {55000, 12, 22, 18}, 341 {56000, 14, 45, 31}, 342 {56250, 16, 25, 15}, 343 {56750, 14, 25, 17}, 344 {57000, 16, 27, 16}, 345 {58000, 16, 43, 25}, 346 {58250, 16, 38, 22}, 347 {58750, 16, 40, 23}, 348 {59000, 14, 26, 17}, 349 {59341, 14, 40, 26}, 350 {59400, 16, 44, 25}, 351 {60000, 16, 32, 18}, 352 {60500, 12, 39, 29}, 353 {61000, 14, 49, 31}, 354 {62000, 14, 37, 23}, 355 {62250, 14, 42, 26}, 356 {63000, 12, 21, 15}, 357 {63500, 14, 28, 17}, 358 {64000, 12, 27, 19}, 359 {65000, 14, 32, 19}, 360 {65250, 12, 29, 20}, 361 {65500, 12, 32, 22}, 362 {66000, 12, 22, 15}, 363 {66667, 14, 38, 22}, 364 {66750, 10, 21, 17}, 365 {67000, 14, 33, 19}, 366 {67750, 14, 58, 33}, 367 {68000, 14, 30, 17}, 368 {68179, 14, 46, 26}, 369 {68250, 14, 46, 26}, 370 {69000, 12, 23, 15}, 371 {70000, 12, 28, 18}, 372 {71000, 12, 30, 19}, 373 {72000, 12, 24, 15}, 374 {73000, 10, 23, 17}, 375 {74000, 12, 23, 14}, 376 {74176, 8, 100, 91}, 377 {74250, 10, 22, 16}, 378 {74481, 12, 43, 26}, 379 {74500, 10, 29, 21}, 380 {75000, 12, 25, 15}, 381 {75250, 10, 39, 28}, 382 {76000, 12, 27, 16}, 383 {77000, 12, 53, 31}, 384 {78000, 12, 26, 15}, 385 {78750, 12, 28, 16}, 386 {79000, 10, 38, 26}, 387 {79500, 10, 28, 19}, 388 {80000, 12, 32, 18}, 389 {81000, 10, 21, 14}, 390 {81081, 6, 100, 111}, 391 {81624, 8, 29, 24}, 392 {82000, 8, 17, 14}, 393 {83000, 10, 40, 26}, 394 {83950, 10, 28, 18}, 395 {84000, 10, 28, 18}, 396 {84750, 6, 16, 17}, 397 {85000, 6, 17, 18}, 398 {85250, 10, 30, 19}, 399 {85750, 10, 27, 17}, 400 {86000, 10, 43, 27}, 401 {87000, 10, 29, 18}, 402 {88000, 10, 44, 27}, 403 {88500, 10, 41, 25}, 404 {89000, 10, 28, 17}, 405 {89012, 6, 90, 91}, 406 {89100, 10, 33, 20}, 407 {90000, 10, 25, 15}, 408 {91000, 10, 32, 19}, 409 {92000, 10, 46, 27}, 410 {93000, 10, 31, 18}, 411 {94000, 10, 40, 23}, 412 {94500, 10, 28, 16}, 413 {95000, 10, 44, 25}, 414 {95654, 10, 39, 22}, 415 {95750, 10, 39, 22}, 416 {96000, 10, 32, 18}, 417 {97000, 8, 23, 16}, 418 {97750, 8, 42, 29}, 419 {98000, 8, 45, 31}, 420 {99000, 8, 22, 15}, 421 {99750, 8, 34, 23}, 422 {100000, 6, 20, 18}, 423 {100500, 6, 19, 17}, 424 {101000, 6, 37, 33}, 425 {101250, 8, 21, 14}, 426 {102000, 6, 17, 15}, 427 {102250, 6, 25, 22}, 428 {103000, 8, 29, 19}, 429 {104000, 8, 37, 24}, 430 {105000, 8, 28, 18}, 431 {106000, 8, 22, 14}, 432 {107000, 8, 46, 29}, 433 {107214, 8, 27, 17}, 434 {108000, 8, 24, 15}, 435 {108108, 8, 173, 108}, 436 {109000, 6, 23, 19}, 437 {109000, 6, 23, 19}, 438 {110000, 6, 22, 18}, 439 {110013, 6, 22, 18}, 440 {110250, 8, 49, 30}, 441 {110500, 8, 36, 22}, 442 {111000, 8, 23, 14}, 443 {111264, 8, 150, 91}, 444 {111375, 8, 33, 20}, 445 {112000, 8, 63, 38}, 446 {112500, 8, 25, 15}, 447 {113100, 8, 57, 34}, 448 {113309, 8, 42, 25}, 449 {114000, 8, 27, 16}, 450 {115000, 6, 23, 18}, 451 {116000, 8, 43, 25}, 452 {117000, 8, 26, 15}, 453 {117500, 8, 40, 23}, 454 {118000, 6, 38, 29}, 455 {119000, 8, 30, 17}, 456 {119500, 8, 46, 26}, 457 {119651, 8, 39, 22}, 458 {120000, 8, 32, 18}, 459 {121000, 6, 39, 29}, 460 {121250, 6, 31, 23}, 461 {121750, 6, 23, 17}, 462 {122000, 6, 42, 31}, 463 {122614, 6, 30, 22}, 464 {123000, 6, 41, 30}, 465 {123379, 6, 37, 27}, 466 {124000, 6, 51, 37}, 467 {125000, 6, 25, 18}, 468 {125250, 4, 13, 14}, 469 {125750, 4, 27, 29}, 470 {126000, 6, 21, 15}, 471 {127000, 6, 24, 17}, 472 {127250, 6, 41, 29}, 473 {128000, 6, 27, 19}, 474 {129000, 6, 43, 30}, 475 {129859, 4, 25, 26}, 476 {130000, 6, 26, 18}, 477 {130250, 6, 42, 29}, 478 {131000, 6, 32, 22}, 479 {131500, 6, 38, 26}, 480 {131850, 6, 41, 28}, 481 {132000, 6, 22, 15}, 482 {132750, 6, 28, 19}, 483 {133000, 6, 34, 23}, 484 {133330, 6, 37, 25}, 485 {134000, 6, 61, 41}, 486 {135000, 6, 21, 14}, 487 {135250, 6, 167, 111}, 488 {136000, 6, 62, 41}, 489 {137000, 6, 35, 23}, 490 {138000, 6, 23, 15}, 491 {138500, 6, 40, 26}, 492 {138750, 6, 37, 24}, 493 {139000, 6, 34, 22}, 494 {139050, 6, 34, 22}, 495 {139054, 6, 34, 22}, 496 {140000, 6, 28, 18}, 497 {141000, 6, 36, 23}, 498 {141500, 6, 22, 14}, 499 {142000, 6, 30, 19}, 500 {143000, 6, 27, 17}, 501 {143472, 4, 17, 16}, 502 {144000, 6, 24, 15}, 503 {145000, 6, 29, 18}, 504 {146000, 6, 47, 29}, 505 {146250, 6, 26, 16}, 506 {147000, 6, 49, 30}, 507 {147891, 6, 23, 14}, 508 {148000, 6, 23, 14}, 509 {148250, 6, 28, 17}, 510 {148352, 4, 100, 91}, 511 {148500, 6, 33, 20}, 512 {149000, 6, 48, 29}, 513 {150000, 6, 25, 15}, 514 {151000, 4, 19, 17}, 515 {152000, 6, 27, 16}, 516 {152280, 6, 44, 26}, 517 {153000, 6, 34, 20}, 518 {154000, 6, 53, 31}, 519 {155000, 6, 31, 18}, 520 {155250, 6, 50, 29}, 521 {155750, 6, 45, 26}, 522 {156000, 6, 26, 15}, 523 {157000, 6, 61, 35}, 524 {157500, 6, 28, 16}, 525 {158000, 6, 65, 37}, 526 {158250, 6, 44, 25}, 527 {159000, 6, 53, 30}, 528 {159500, 6, 39, 22}, 529 {160000, 6, 32, 18}, 530 {161000, 4, 31, 26}, 531 {162000, 4, 18, 15}, 532 {162162, 4, 131, 109}, 533 {162500, 4, 53, 44}, 534 {163000, 4, 29, 24}, 535 {164000, 4, 17, 14}, 536 {165000, 4, 22, 18}, 537 {166000, 4, 32, 26}, 538 {167000, 4, 26, 21}, 539 {168000, 4, 46, 37}, 540 {169000, 4, 104, 83}, 541 {169128, 4, 64, 51}, 542 {169500, 4, 39, 31}, 543 {170000, 4, 34, 27}, 544 {171000, 4, 19, 15}, 545 {172000, 4, 51, 40}, 546 {172750, 4, 32, 25}, 547 {172800, 4, 32, 25}, 548 {173000, 4, 41, 32}, 549 {174000, 4, 49, 38}, 550 {174787, 4, 22, 17}, 551 {175000, 4, 35, 27}, 552 {176000, 4, 30, 23}, 553 {177000, 4, 38, 29}, 554 {178000, 4, 29, 22}, 555 {178500, 4, 37, 28}, 556 {179000, 4, 53, 40}, 557 {179500, 4, 73, 55}, 558 {180000, 4, 20, 15}, 559 {181000, 4, 55, 41}, 560 {182000, 4, 31, 23}, 561 {183000, 4, 42, 31}, 562 {184000, 4, 30, 22}, 563 {184750, 4, 26, 19}, 564 {185000, 4, 37, 27}, 565 {186000, 4, 51, 37}, 566 {187000, 4, 36, 26}, 567 {188000, 4, 32, 23}, 568 {189000, 4, 21, 15}, 569 {190000, 4, 38, 27}, 570 {190960, 4, 41, 29}, 571 {191000, 4, 41, 29}, 572 {192000, 4, 27, 19}, 573 {192250, 4, 37, 26}, 574 {193000, 4, 20, 14}, 575 {193250, 4, 53, 37}, 576 {194000, 4, 23, 16}, 577 {194208, 4, 23, 16}, 578 {195000, 4, 26, 18}, 579 {196000, 4, 45, 31}, 580 {197000, 4, 35, 24}, 581 {197750, 4, 41, 28}, 582 {198000, 4, 22, 15}, 583 {198500, 4, 25, 17}, 584 {199000, 4, 28, 19}, 585 {200000, 4, 37, 25}, 586 {201000, 4, 61, 41}, 587 {202000, 4, 112, 75}, 588 {202500, 4, 21, 14}, 589 {203000, 4, 146, 97}, 590 {204000, 4, 62, 41}, 591 {204750, 4, 44, 29}, 592 {205000, 4, 38, 25}, 593 {206000, 4, 29, 19}, 594 {207000, 4, 23, 15}, 595 {207500, 4, 40, 26}, 596 {208000, 4, 37, 24}, 597 {208900, 4, 48, 31}, 598 {209000, 4, 48, 31}, 599 {209250, 4, 31, 20}, 600 {210000, 4, 28, 18}, 601 {211000, 4, 25, 16}, 602 {212000, 4, 22, 14}, 603 {213000, 4, 30, 19}, 604 {213750, 4, 38, 24}, 605 {214000, 4, 46, 29}, 606 {214750, 4, 35, 22}, 607 {215000, 4, 43, 27}, 608 {216000, 4, 24, 15}, 609 {217000, 4, 37, 23}, 610 {218000, 4, 42, 26}, 611 {218250, 4, 42, 26}, 612 {218750, 4, 34, 21}, 613 {219000, 4, 47, 29}, 614 {219000, 4, 47, 29}, 615 {220000, 4, 44, 27}, 616 {220640, 4, 49, 30}, 617 {220750, 4, 36, 22}, 618 {221000, 4, 36, 22}, 619 {222000, 4, 23, 14}, 620 {222525, 4, 28, 17}, 621 {222750, 4, 33, 20}, 622 {227000, 4, 37, 22}, 623 {230250, 4, 29, 17}, 624 {233500, 4, 38, 22}, 625 {235000, 4, 40, 23}, 626 {238000, 4, 30, 17}, 627 {241500, 2, 17, 19}, 628 {245250, 2, 20, 22}, 629 {247750, 2, 22, 24}, 630 {253250, 2, 15, 16}, 631 {256250, 2, 18, 19}, 632 {262500, 2, 31, 32}, 633 {267250, 2, 66, 67}, 634 {268500, 2, 94, 95}, 635 {270000, 2, 14, 14}, 636 {272500, 2, 77, 76}, 637 {273750, 2, 57, 56}, 638 {280750, 2, 24, 23}, 639 {281250, 2, 23, 22}, 640 {286000, 2, 17, 16}, 641 {291750, 2, 26, 24}, 642 {296703, 2, 56, 51}, 643 {297000, 2, 22, 20}, 644 {298000, 2, 21, 19}, 645}; 646 647void intel_ddi_mode_set(struct drm_encoder *encoder, 648 struct drm_display_mode *mode, 649 struct drm_display_mode *adjusted_mode) 650{ 651 struct drm_device *dev = encoder->dev; 652 struct drm_i915_private *dev_priv = dev->dev_private; 653 struct drm_crtc *crtc = encoder->crtc; 654 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 655 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); 656 int port = intel_hdmi->ddi_port; 657 int pipe = intel_crtc->pipe; 658 int p, n2, r2, valid=0; 659 u32 temp, i; 660 661 /* On Haswell, we need to enable the clocks and prepare DDI function to 662 * work in HDMI mode for this pipe. 663 */ 664 DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe)); 665 666 for (i=0; i < DRM_ARRAY_SIZE(wrpll_tmds_clock_table); i++) { 667 if (crtc->mode.clock == wrpll_tmds_clock_table[i].clock) { 668 p = wrpll_tmds_clock_table[i].p; 669 n2 = wrpll_tmds_clock_table[i].n2; 670 r2 = wrpll_tmds_clock_table[i].r2; 671 672 DRM_DEBUG_KMS("WR PLL clock: found settings for %dKHz refresh rate: p=%d, n2=%d, r2=%d\n", 673 crtc->mode.clock, 674 p, n2, r2); 675 676 valid = 1; 677 break; 678 } 679 } 680 681 if (!valid) { 682 DRM_ERROR("Unable to find WR PLL clock settings for %dKHz refresh rate\n", 683 crtc->mode.clock); 684 return; 685 } 686 687 /* Enable LCPLL if disabled */ 688 temp = I915_READ(LCPLL_CTL); 689 if (temp & LCPLL_PLL_DISABLE) 690 I915_WRITE(LCPLL_CTL, 691 temp & ~LCPLL_PLL_DISABLE); 692 693 /* Configure WR PLL 1, program the correct divider values for 694 * the desired frequency and wait for warmup */ 695 I915_WRITE(WRPLL_CTL1, 696 WRPLL_PLL_ENABLE | 697 WRPLL_PLL_SELECT_LCPLL_2700 | 698 WRPLL_DIVIDER_REFERENCE(r2) | 699 WRPLL_DIVIDER_FEEDBACK(n2) | 700 WRPLL_DIVIDER_POST(p)); 701 702 DELAY(20); 703 704 /* Use WRPLL1 clock to drive the output to the port, and tell the pipe to use 705 * this port for connection. 706 */ 707 I915_WRITE(PORT_CLK_SEL(port), 708 PORT_CLK_SEL_WRPLL1); 709 I915_WRITE(PIPE_CLK_SEL(pipe), 710 PIPE_CLK_SEL_PORT(port)); 711 712 DELAY(20); 713 714 if (intel_hdmi->has_audio) { 715 /* Proper support for digital audio needs a new logic and a new set 716 * of registers, so we leave it for future patch bombing. 717 */ 718 DRM_DEBUG_DRIVER("HDMI audio on pipe %c not yet supported on DDI\n", 719 pipe_name(intel_crtc->pipe)); 720 } 721 722 /* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */ 723 temp = I915_READ(DDI_FUNC_CTL(pipe)); 724 temp &= ~PIPE_DDI_PORT_MASK; 725 temp &= ~PIPE_DDI_BPC_12; 726 temp |= PIPE_DDI_SELECT_PORT(port) | 727 PIPE_DDI_MODE_SELECT_HDMI | 728 ((intel_crtc->bpp > 24) ? 729 PIPE_DDI_BPC_12 : 730 PIPE_DDI_BPC_8) | 731 PIPE_DDI_FUNC_ENABLE; 732 733 I915_WRITE(DDI_FUNC_CTL(pipe), temp); 734 735 intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); 736 intel_hdmi_set_spd_infoframe(encoder); 737} 738 739void intel_ddi_dpms(struct drm_encoder *encoder, int mode) 740{ 741 struct drm_device *dev = encoder->dev; 742 struct drm_i915_private *dev_priv = dev->dev_private; 743 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); 744 int port = intel_hdmi->ddi_port; 745 u32 temp; 746 747 temp = I915_READ(DDI_BUF_CTL(port)); 748 749 if (mode != DRM_MODE_DPMS_ON) { 750 temp &= ~DDI_BUF_CTL_ENABLE; 751 } else { 752 temp |= DDI_BUF_CTL_ENABLE; 753 } 754 755 /* Enable DDI_BUF_CTL. In HDMI/DVI mode, the port width, 756 * and swing/emphasis values are ignored so nothing special needs 757 * to be done besides enabling the port. 758 */ 759 I915_WRITE(DDI_BUF_CTL(port), 760 temp); 761} 762