diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 199 |
1 files changed, 145 insertions, 54 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3e1c78162119..73e7b9cecac8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "intel_drv.h" | 29 | #include "intel_drv.h" |
30 | #include "i915_drm.h" | 30 | #include "i915_drm.h" |
31 | #include "i915_drv.h" | 31 | #include "i915_drv.h" |
32 | #include "intel_dp.h" | ||
32 | 33 | ||
33 | #include "drm_crtc_helper.h" | 34 | #include "drm_crtc_helper.h" |
34 | 35 | ||
@@ -127,19 +128,6 @@ struct intel_limit { | |||
127 | #define I9XX_P2_LVDS_FAST 7 | 128 | #define I9XX_P2_LVDS_FAST 7 |
128 | #define I9XX_P2_LVDS_SLOW_LIMIT 112000 | 129 | #define I9XX_P2_LVDS_SLOW_LIMIT 112000 |
129 | 130 | ||
130 | #define INTEL_LIMIT_I8XX_DVO_DAC 0 | ||
131 | #define INTEL_LIMIT_I8XX_LVDS 1 | ||
132 | #define INTEL_LIMIT_I9XX_SDVO_DAC 2 | ||
133 | #define INTEL_LIMIT_I9XX_LVDS 3 | ||
134 | #define INTEL_LIMIT_G4X_SDVO 4 | ||
135 | #define INTEL_LIMIT_G4X_HDMI_DAC 5 | ||
136 | #define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6 | ||
137 | #define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7 | ||
138 | #define INTEL_LIMIT_IGD_SDVO_DAC 8 | ||
139 | #define INTEL_LIMIT_IGD_LVDS 9 | ||
140 | #define INTEL_LIMIT_IGDNG_SDVO_DAC 10 | ||
141 | #define INTEL_LIMIT_IGDNG_LVDS 11 | ||
142 | |||
143 | /*The parameter is for SDVO on G4x platform*/ | 131 | /*The parameter is for SDVO on G4x platform*/ |
144 | #define G4X_DOT_SDVO_MIN 25000 | 132 | #define G4X_DOT_SDVO_MIN 25000 |
145 | #define G4X_DOT_SDVO_MAX 270000 | 133 | #define G4X_DOT_SDVO_MAX 270000 |
@@ -218,6 +206,25 @@ struct intel_limit { | |||
218 | #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 | 206 | #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 |
219 | #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 | 207 | #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 |
220 | 208 | ||
209 | /*The parameter is for DISPLAY PORT on G4x platform*/ | ||
210 | #define G4X_DOT_DISPLAY_PORT_MIN 161670 | ||
211 | #define G4X_DOT_DISPLAY_PORT_MAX 227000 | ||
212 | #define G4X_N_DISPLAY_PORT_MIN 1 | ||
213 | #define G4X_N_DISPLAY_PORT_MAX 2 | ||
214 | #define G4X_M_DISPLAY_PORT_MIN 97 | ||
215 | #define G4X_M_DISPLAY_PORT_MAX 108 | ||
216 | #define G4X_M1_DISPLAY_PORT_MIN 0x10 | ||
217 | #define G4X_M1_DISPLAY_PORT_MAX 0x12 | ||
218 | #define G4X_M2_DISPLAY_PORT_MIN 0x05 | ||
219 | #define G4X_M2_DISPLAY_PORT_MAX 0x06 | ||
220 | #define G4X_P_DISPLAY_PORT_MIN 10 | ||
221 | #define G4X_P_DISPLAY_PORT_MAX 20 | ||
222 | #define G4X_P1_DISPLAY_PORT_MIN 1 | ||
223 | #define G4X_P1_DISPLAY_PORT_MAX 2 | ||
224 | #define G4X_P2_DISPLAY_PORT_SLOW 10 | ||
225 | #define G4X_P2_DISPLAY_PORT_FAST 10 | ||
226 | #define G4X_P2_DISPLAY_PORT_LIMIT 0 | ||
227 | |||
221 | /* IGDNG */ | 228 | /* IGDNG */ |
222 | /* as we calculate clock using (register_value + 2) for | 229 | /* as we calculate clock using (register_value + 2) for |
223 | N/M1/M2, so here the range value for them is (actual_value-2). | 230 | N/M1/M2, so here the range value for them is (actual_value-2). |
@@ -256,8 +263,11 @@ static bool | |||
256 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 263 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
257 | int target, int refclk, intel_clock_t *best_clock); | 264 | int target, int refclk, intel_clock_t *best_clock); |
258 | 265 | ||
259 | static const intel_limit_t intel_limits[] = { | 266 | static bool |
260 | { /* INTEL_LIMIT_I8XX_DVO_DAC */ | 267 | intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, |
268 | int target, int refclk, intel_clock_t *best_clock); | ||
269 | |||
270 | static const intel_limit_t intel_limits_i8xx_dvo = { | ||
261 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | 271 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, |
262 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | 272 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, |
263 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, | 273 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, |
@@ -269,8 +279,9 @@ static const intel_limit_t intel_limits[] = { | |||
269 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 279 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
270 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, | 280 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, |
271 | .find_pll = intel_find_best_PLL, | 281 | .find_pll = intel_find_best_PLL, |
272 | }, | 282 | }; |
273 | { /* INTEL_LIMIT_I8XX_LVDS */ | 283 | |
284 | static const intel_limit_t intel_limits_i8xx_lvds = { | ||
274 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | 285 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, |
275 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | 286 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, |
276 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, | 287 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, |
@@ -282,8 +293,9 @@ static const intel_limit_t intel_limits[] = { | |||
282 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 293 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
283 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, | 294 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, |
284 | .find_pll = intel_find_best_PLL, | 295 | .find_pll = intel_find_best_PLL, |
285 | }, | 296 | }; |
286 | { /* INTEL_LIMIT_I9XX_SDVO_DAC */ | 297 | |
298 | static const intel_limit_t intel_limits_i9xx_sdvo = { | ||
287 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 299 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
288 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, | 300 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, |
289 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, | 301 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, |
@@ -295,8 +307,9 @@ static const intel_limit_t intel_limits[] = { | |||
295 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 307 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
296 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 308 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
297 | .find_pll = intel_find_best_PLL, | 309 | .find_pll = intel_find_best_PLL, |
298 | }, | 310 | }; |
299 | { /* INTEL_LIMIT_I9XX_LVDS */ | 311 | |
312 | static const intel_limit_t intel_limits_i9xx_lvds = { | ||
300 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 313 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
301 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, | 314 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, |
302 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, | 315 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, |
@@ -311,9 +324,10 @@ static const intel_limit_t intel_limits[] = { | |||
311 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 324 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
312 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, | 325 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, |
313 | .find_pll = intel_find_best_PLL, | 326 | .find_pll = intel_find_best_PLL, |
314 | }, | 327 | }; |
328 | |||
315 | /* below parameter and function is for G4X Chipset Family*/ | 329 | /* below parameter and function is for G4X Chipset Family*/ |
316 | { /* INTEL_LIMIT_G4X_SDVO */ | 330 | static const intel_limit_t intel_limits_g4x_sdvo = { |
317 | .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, | 331 | .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, |
318 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, | 332 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, |
319 | .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, | 333 | .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, |
@@ -327,8 +341,9 @@ static const intel_limit_t intel_limits[] = { | |||
327 | .p2_fast = G4X_P2_SDVO_FAST | 341 | .p2_fast = G4X_P2_SDVO_FAST |
328 | }, | 342 | }, |
329 | .find_pll = intel_g4x_find_best_PLL, | 343 | .find_pll = intel_g4x_find_best_PLL, |
330 | }, | 344 | }; |
331 | { /* INTEL_LIMIT_G4X_HDMI_DAC */ | 345 | |
346 | static const intel_limit_t intel_limits_g4x_hdmi = { | ||
332 | .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, | 347 | .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, |
333 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, | 348 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, |
334 | .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, | 349 | .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, |
@@ -342,8 +357,9 @@ static const intel_limit_t intel_limits[] = { | |||
342 | .p2_fast = G4X_P2_HDMI_DAC_FAST | 357 | .p2_fast = G4X_P2_HDMI_DAC_FAST |
343 | }, | 358 | }, |
344 | .find_pll = intel_g4x_find_best_PLL, | 359 | .find_pll = intel_g4x_find_best_PLL, |
345 | }, | 360 | }; |
346 | { /* INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS */ | 361 | |
362 | static const intel_limit_t intel_limits_g4x_single_channel_lvds = { | ||
347 | .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, | 363 | .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, |
348 | .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, | 364 | .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, |
349 | .vco = { .min = G4X_VCO_MIN, | 365 | .vco = { .min = G4X_VCO_MIN, |
@@ -365,8 +381,9 @@ static const intel_limit_t intel_limits[] = { | |||
365 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST | 381 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST |
366 | }, | 382 | }, |
367 | .find_pll = intel_g4x_find_best_PLL, | 383 | .find_pll = intel_g4x_find_best_PLL, |
368 | }, | 384 | }; |
369 | { /* INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS */ | 385 | |
386 | static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { | ||
370 | .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, | 387 | .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, |
371 | .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, | 388 | .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, |
372 | .vco = { .min = G4X_VCO_MIN, | 389 | .vco = { .min = G4X_VCO_MIN, |
@@ -388,8 +405,32 @@ static const intel_limit_t intel_limits[] = { | |||
388 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST | 405 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST |
389 | }, | 406 | }, |
390 | .find_pll = intel_g4x_find_best_PLL, | 407 | .find_pll = intel_g4x_find_best_PLL, |
391 | }, | 408 | }; |
392 | { /* INTEL_LIMIT_IGD_SDVO */ | 409 | |
410 | static const intel_limit_t intel_limits_g4x_display_port = { | ||
411 | .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN, | ||
412 | .max = G4X_DOT_DISPLAY_PORT_MAX }, | ||
413 | .vco = { .min = G4X_VCO_MIN, | ||
414 | .max = G4X_VCO_MAX}, | ||
415 | .n = { .min = G4X_N_DISPLAY_PORT_MIN, | ||
416 | .max = G4X_N_DISPLAY_PORT_MAX }, | ||
417 | .m = { .min = G4X_M_DISPLAY_PORT_MIN, | ||
418 | .max = G4X_M_DISPLAY_PORT_MAX }, | ||
419 | .m1 = { .min = G4X_M1_DISPLAY_PORT_MIN, | ||
420 | .max = G4X_M1_DISPLAY_PORT_MAX }, | ||
421 | .m2 = { .min = G4X_M2_DISPLAY_PORT_MIN, | ||
422 | .max = G4X_M2_DISPLAY_PORT_MAX }, | ||
423 | .p = { .min = G4X_P_DISPLAY_PORT_MIN, | ||
424 | .max = G4X_P_DISPLAY_PORT_MAX }, | ||
425 | .p1 = { .min = G4X_P1_DISPLAY_PORT_MIN, | ||
426 | .max = G4X_P1_DISPLAY_PORT_MAX}, | ||
427 | .p2 = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT, | ||
428 | .p2_slow = G4X_P2_DISPLAY_PORT_SLOW, | ||
429 | .p2_fast = G4X_P2_DISPLAY_PORT_FAST }, | ||
430 | .find_pll = intel_find_pll_g4x_dp, | ||
431 | }; | ||
432 | |||
433 | static const intel_limit_t intel_limits_igd_sdvo = { | ||
393 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, | 434 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, |
394 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, | 435 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, |
395 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, | 436 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, |
@@ -401,8 +442,9 @@ static const intel_limit_t intel_limits[] = { | |||
401 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 442 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
402 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 443 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
403 | .find_pll = intel_find_best_PLL, | 444 | .find_pll = intel_find_best_PLL, |
404 | }, | 445 | }; |
405 | { /* INTEL_LIMIT_IGD_LVDS */ | 446 | |
447 | static const intel_limit_t intel_limits_igd_lvds = { | ||
406 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 448 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
407 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, | 449 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, |
408 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, | 450 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, |
@@ -415,8 +457,9 @@ static const intel_limit_t intel_limits[] = { | |||
415 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 457 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
416 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, | 458 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, |
417 | .find_pll = intel_find_best_PLL, | 459 | .find_pll = intel_find_best_PLL, |
418 | }, | 460 | }; |
419 | { /* INTEL_LIMIT_IGDNG_SDVO_DAC */ | 461 | |
462 | static const intel_limit_t intel_limits_igdng_sdvo = { | ||
420 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, | 463 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, |
421 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, | 464 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, |
422 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, | 465 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, |
@@ -429,8 +472,9 @@ static const intel_limit_t intel_limits[] = { | |||
429 | .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, | 472 | .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, |
430 | .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, | 473 | .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, |
431 | .find_pll = intel_igdng_find_best_PLL, | 474 | .find_pll = intel_igdng_find_best_PLL, |
432 | }, | 475 | }; |
433 | { /* INTEL_LIMIT_IGDNG_LVDS */ | 476 | |
477 | static const intel_limit_t intel_limits_igdng_lvds = { | ||
434 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, | 478 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, |
435 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, | 479 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, |
436 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, | 480 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, |
@@ -443,16 +487,15 @@ static const intel_limit_t intel_limits[] = { | |||
443 | .p2_slow = IGDNG_P2_LVDS_SLOW, | 487 | .p2_slow = IGDNG_P2_LVDS_SLOW, |
444 | .p2_fast = IGDNG_P2_LVDS_FAST }, | 488 | .p2_fast = IGDNG_P2_LVDS_FAST }, |
445 | .find_pll = intel_igdng_find_best_PLL, | 489 | .find_pll = intel_igdng_find_best_PLL, |
446 | }, | ||
447 | }; | 490 | }; |
448 | 491 | ||
449 | static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) | 492 | static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) |
450 | { | 493 | { |
451 | const intel_limit_t *limit; | 494 | const intel_limit_t *limit; |
452 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 495 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
453 | limit = &intel_limits[INTEL_LIMIT_IGDNG_LVDS]; | 496 | limit = &intel_limits_igdng_lvds; |
454 | else | 497 | else |
455 | limit = &intel_limits[INTEL_LIMIT_IGDNG_SDVO_DAC]; | 498 | limit = &intel_limits_igdng_sdvo; |
456 | 499 | ||
457 | return limit; | 500 | return limit; |
458 | } | 501 | } |
@@ -467,19 +510,19 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) | |||
467 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == | 510 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == |
468 | LVDS_CLKB_POWER_UP) | 511 | LVDS_CLKB_POWER_UP) |
469 | /* LVDS with dual channel */ | 512 | /* LVDS with dual channel */ |
470 | limit = &intel_limits | 513 | limit = &intel_limits_g4x_dual_channel_lvds; |
471 | [INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS]; | ||
472 | else | 514 | else |
473 | /* LVDS with dual channel */ | 515 | /* LVDS with dual channel */ |
474 | limit = &intel_limits | 516 | limit = &intel_limits_g4x_single_channel_lvds; |
475 | [INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS]; | ||
476 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || | 517 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || |
477 | intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { | 518 | intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { |
478 | limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC]; | 519 | limit = &intel_limits_g4x_hdmi; |
479 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { | 520 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { |
480 | limit = &intel_limits[INTEL_LIMIT_G4X_SDVO]; | 521 | limit = &intel_limits_g4x_sdvo; |
522 | } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) { | ||
523 | limit = &intel_limits_g4x_display_port; | ||
481 | } else /* The option is for other outputs */ | 524 | } else /* The option is for other outputs */ |
482 | limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; | 525 | limit = &intel_limits_i9xx_sdvo; |
483 | 526 | ||
484 | return limit; | 527 | return limit; |
485 | } | 528 | } |
@@ -495,19 +538,19 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) | |||
495 | limit = intel_g4x_limit(crtc); | 538 | limit = intel_g4x_limit(crtc); |
496 | } else if (IS_I9XX(dev) && !IS_IGD(dev)) { | 539 | } else if (IS_I9XX(dev) && !IS_IGD(dev)) { |
497 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 540 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
498 | limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; | 541 | limit = &intel_limits_i9xx_lvds; |
499 | else | 542 | else |
500 | limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; | 543 | limit = &intel_limits_i9xx_sdvo; |
501 | } else if (IS_IGD(dev)) { | 544 | } else if (IS_IGD(dev)) { |
502 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 545 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
503 | limit = &intel_limits[INTEL_LIMIT_IGD_LVDS]; | 546 | limit = &intel_limits_igd_lvds; |
504 | else | 547 | else |
505 | limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC]; | 548 | limit = &intel_limits_igd_sdvo; |
506 | } else { | 549 | } else { |
507 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 550 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
508 | limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS]; | 551 | limit = &intel_limits_i8xx_lvds; |
509 | else | 552 | else |
510 | limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC]; | 553 | limit = &intel_limits_i8xx_dvo; |
511 | } | 554 | } |
512 | return limit; | 555 | return limit; |
513 | } | 556 | } |
@@ -764,6 +807,35 @@ out: | |||
764 | return found; | 807 | return found; |
765 | } | 808 | } |
766 | 809 | ||
810 | /* DisplayPort has only two frequencies, 162MHz and 270MHz */ | ||
811 | static bool | ||
812 | intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
813 | int target, int refclk, intel_clock_t *best_clock) | ||
814 | { | ||
815 | intel_clock_t clock; | ||
816 | if (target < 200000) { | ||
817 | clock.dot = 161670; | ||
818 | clock.p = 20; | ||
819 | clock.p1 = 2; | ||
820 | clock.p2 = 10; | ||
821 | clock.n = 0x01; | ||
822 | clock.m = 97; | ||
823 | clock.m1 = 0x10; | ||
824 | clock.m2 = 0x05; | ||
825 | } else { | ||
826 | clock.dot = 270000; | ||
827 | clock.p = 10; | ||
828 | clock.p1 = 1; | ||
829 | clock.p2 = 10; | ||
830 | clock.n = 0x02; | ||
831 | clock.m = 108; | ||
832 | clock.m1 = 0x12; | ||
833 | clock.m2 = 0x06; | ||
834 | } | ||
835 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); | ||
836 | return true; | ||
837 | } | ||
838 | |||
767 | void | 839 | void |
768 | intel_wait_for_vblank(struct drm_device *dev) | 840 | intel_wait_for_vblank(struct drm_device *dev) |
769 | { | 841 | { |
@@ -1541,7 +1613,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1541 | intel_clock_t clock; | 1613 | intel_clock_t clock; |
1542 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; | 1614 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; |
1543 | bool ok, is_sdvo = false, is_dvo = false; | 1615 | bool ok, is_sdvo = false, is_dvo = false; |
1544 | bool is_crt = false, is_lvds = false, is_tv = false; | 1616 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; |
1545 | struct drm_mode_config *mode_config = &dev->mode_config; | 1617 | struct drm_mode_config *mode_config = &dev->mode_config; |
1546 | struct drm_connector *connector; | 1618 | struct drm_connector *connector; |
1547 | const intel_limit_t *limit; | 1619 | const intel_limit_t *limit; |
@@ -1585,6 +1657,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1585 | case INTEL_OUTPUT_ANALOG: | 1657 | case INTEL_OUTPUT_ANALOG: |
1586 | is_crt = true; | 1658 | is_crt = true; |
1587 | break; | 1659 | break; |
1660 | case INTEL_OUTPUT_DISPLAYPORT: | ||
1661 | is_dp = true; | ||
1662 | break; | ||
1588 | } | 1663 | } |
1589 | 1664 | ||
1590 | num_outputs++; | 1665 | num_outputs++; |
@@ -1600,6 +1675,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1600 | } else { | 1675 | } else { |
1601 | refclk = 48000; | 1676 | refclk = 48000; |
1602 | } | 1677 | } |
1678 | |||
1603 | 1679 | ||
1604 | /* | 1680 | /* |
1605 | * Returns a set of divisors for the desired target clock with the given | 1681 | * Returns a set of divisors for the desired target clock with the given |
@@ -1662,6 +1738,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1662 | else if (IS_IGDNG(dev)) | 1738 | else if (IS_IGDNG(dev)) |
1663 | dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; | 1739 | dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; |
1664 | } | 1740 | } |
1741 | if (is_dp) | ||
1742 | dpll |= DPLL_DVO_HIGH_SPEED; | ||
1665 | 1743 | ||
1666 | /* compute bitmask from p1 value */ | 1744 | /* compute bitmask from p1 value */ |
1667 | if (IS_IGD(dev)) | 1745 | if (IS_IGD(dev)) |
@@ -1809,6 +1887,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1809 | I915_WRITE(lvds_reg, lvds); | 1887 | I915_WRITE(lvds_reg, lvds); |
1810 | I915_READ(lvds_reg); | 1888 | I915_READ(lvds_reg); |
1811 | } | 1889 | } |
1890 | if (is_dp) | ||
1891 | intel_dp_set_m_n(crtc, mode, adjusted_mode); | ||
1812 | 1892 | ||
1813 | I915_WRITE(fp_reg, fp); | 1893 | I915_WRITE(fp_reg, fp); |
1814 | I915_WRITE(dpll_reg, dpll); | 1894 | I915_WRITE(dpll_reg, dpll); |
@@ -2475,6 +2555,8 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
2475 | found = intel_sdvo_init(dev, SDVOB); | 2555 | found = intel_sdvo_init(dev, SDVOB); |
2476 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | 2556 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) |
2477 | intel_hdmi_init(dev, SDVOB); | 2557 | intel_hdmi_init(dev, SDVOB); |
2558 | if (!found && SUPPORTS_INTEGRATED_DP(dev)) | ||
2559 | intel_dp_init(dev, DP_B); | ||
2478 | } | 2560 | } |
2479 | 2561 | ||
2480 | /* Before G4X SDVOC doesn't have its own detect register */ | 2562 | /* Before G4X SDVOC doesn't have its own detect register */ |
@@ -2487,7 +2569,11 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
2487 | found = intel_sdvo_init(dev, SDVOC); | 2569 | found = intel_sdvo_init(dev, SDVOC); |
2488 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | 2570 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) |
2489 | intel_hdmi_init(dev, SDVOC); | 2571 | intel_hdmi_init(dev, SDVOC); |
2572 | if (!found && SUPPORTS_INTEGRATED_DP(dev)) | ||
2573 | intel_dp_init(dev, DP_C); | ||
2490 | } | 2574 | } |
2575 | if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) | ||
2576 | intel_dp_init(dev, DP_D); | ||
2491 | } else | 2577 | } else |
2492 | intel_dvo_init(dev); | 2578 | intel_dvo_init(dev); |
2493 | 2579 | ||
@@ -2530,6 +2616,11 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
2530 | (1 << 1)); | 2616 | (1 << 1)); |
2531 | clone_mask = (1 << INTEL_OUTPUT_TVOUT); | 2617 | clone_mask = (1 << INTEL_OUTPUT_TVOUT); |
2532 | break; | 2618 | break; |
2619 | case INTEL_OUTPUT_DISPLAYPORT: | ||
2620 | crtc_mask = ((1 << 0) | | ||
2621 | (1 << 1)); | ||
2622 | clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT); | ||
2623 | break; | ||
2533 | } | 2624 | } |
2534 | encoder->possible_crtcs = crtc_mask; | 2625 | encoder->possible_crtcs = crtc_mask; |
2535 | encoder->possible_clones = intel_connector_clones(dev, clone_mask); | 2626 | encoder->possible_clones = intel_connector_clones(dev, clone_mask); |