diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 623 |
1 files changed, 566 insertions, 57 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3e1c78162119..508838ee31e0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -25,14 +25,17 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
28 | #include <linux/kernel.h> | ||
28 | #include "drmP.h" | 29 | #include "drmP.h" |
29 | #include "intel_drv.h" | 30 | #include "intel_drv.h" |
30 | #include "i915_drm.h" | 31 | #include "i915_drm.h" |
31 | #include "i915_drv.h" | 32 | #include "i915_drv.h" |
33 | #include "intel_dp.h" | ||
32 | 34 | ||
33 | #include "drm_crtc_helper.h" | 35 | #include "drm_crtc_helper.h" |
34 | 36 | ||
35 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type); | 37 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type); |
38 | static void intel_update_watermarks(struct drm_device *dev); | ||
36 | 39 | ||
37 | typedef struct { | 40 | typedef struct { |
38 | /* given values */ | 41 | /* given values */ |
@@ -127,19 +130,6 @@ struct intel_limit { | |||
127 | #define I9XX_P2_LVDS_FAST 7 | 130 | #define I9XX_P2_LVDS_FAST 7 |
128 | #define I9XX_P2_LVDS_SLOW_LIMIT 112000 | 131 | #define I9XX_P2_LVDS_SLOW_LIMIT 112000 |
129 | 132 | ||
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*/ | 133 | /*The parameter is for SDVO on G4x platform*/ |
144 | #define G4X_DOT_SDVO_MIN 25000 | 134 | #define G4X_DOT_SDVO_MIN 25000 |
145 | #define G4X_DOT_SDVO_MAX 270000 | 135 | #define G4X_DOT_SDVO_MAX 270000 |
@@ -218,6 +208,25 @@ struct intel_limit { | |||
218 | #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 | 208 | #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 |
219 | #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 | 209 | #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 |
220 | 210 | ||
211 | /*The parameter is for DISPLAY PORT on G4x platform*/ | ||
212 | #define G4X_DOT_DISPLAY_PORT_MIN 161670 | ||
213 | #define G4X_DOT_DISPLAY_PORT_MAX 227000 | ||
214 | #define G4X_N_DISPLAY_PORT_MIN 1 | ||
215 | #define G4X_N_DISPLAY_PORT_MAX 2 | ||
216 | #define G4X_M_DISPLAY_PORT_MIN 97 | ||
217 | #define G4X_M_DISPLAY_PORT_MAX 108 | ||
218 | #define G4X_M1_DISPLAY_PORT_MIN 0x10 | ||
219 | #define G4X_M1_DISPLAY_PORT_MAX 0x12 | ||
220 | #define G4X_M2_DISPLAY_PORT_MIN 0x05 | ||
221 | #define G4X_M2_DISPLAY_PORT_MAX 0x06 | ||
222 | #define G4X_P_DISPLAY_PORT_MIN 10 | ||
223 | #define G4X_P_DISPLAY_PORT_MAX 20 | ||
224 | #define G4X_P1_DISPLAY_PORT_MIN 1 | ||
225 | #define G4X_P1_DISPLAY_PORT_MAX 2 | ||
226 | #define G4X_P2_DISPLAY_PORT_SLOW 10 | ||
227 | #define G4X_P2_DISPLAY_PORT_FAST 10 | ||
228 | #define G4X_P2_DISPLAY_PORT_LIMIT 0 | ||
229 | |||
221 | /* IGDNG */ | 230 | /* IGDNG */ |
222 | /* as we calculate clock using (register_value + 2) for | 231 | /* as we calculate clock using (register_value + 2) for |
223 | N/M1/M2, so here the range value for them is (actual_value-2). | 232 | N/M1/M2, so here the range value for them is (actual_value-2). |
@@ -256,8 +265,11 @@ static bool | |||
256 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 265 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
257 | int target, int refclk, intel_clock_t *best_clock); | 266 | int target, int refclk, intel_clock_t *best_clock); |
258 | 267 | ||
259 | static const intel_limit_t intel_limits[] = { | 268 | static bool |
260 | { /* INTEL_LIMIT_I8XX_DVO_DAC */ | 269 | intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, |
270 | int target, int refclk, intel_clock_t *best_clock); | ||
271 | |||
272 | static const intel_limit_t intel_limits_i8xx_dvo = { | ||
261 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | 273 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, |
262 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | 274 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, |
263 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, | 275 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, |
@@ -269,8 +281,9 @@ static const intel_limit_t intel_limits[] = { | |||
269 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 281 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
270 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, | 282 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, |
271 | .find_pll = intel_find_best_PLL, | 283 | .find_pll = intel_find_best_PLL, |
272 | }, | 284 | }; |
273 | { /* INTEL_LIMIT_I8XX_LVDS */ | 285 | |
286 | static const intel_limit_t intel_limits_i8xx_lvds = { | ||
274 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | 287 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, |
275 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | 288 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, |
276 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, | 289 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, |
@@ -282,8 +295,9 @@ static const intel_limit_t intel_limits[] = { | |||
282 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 295 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
283 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, | 296 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, |
284 | .find_pll = intel_find_best_PLL, | 297 | .find_pll = intel_find_best_PLL, |
285 | }, | 298 | }; |
286 | { /* INTEL_LIMIT_I9XX_SDVO_DAC */ | 299 | |
300 | static const intel_limit_t intel_limits_i9xx_sdvo = { | ||
287 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 301 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
288 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, | 302 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, |
289 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, | 303 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, |
@@ -295,8 +309,9 @@ static const intel_limit_t intel_limits[] = { | |||
295 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 309 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
296 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 310 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
297 | .find_pll = intel_find_best_PLL, | 311 | .find_pll = intel_find_best_PLL, |
298 | }, | 312 | }; |
299 | { /* INTEL_LIMIT_I9XX_LVDS */ | 313 | |
314 | static const intel_limit_t intel_limits_i9xx_lvds = { | ||
300 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 315 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
301 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, | 316 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, |
302 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, | 317 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, |
@@ -311,9 +326,10 @@ static const intel_limit_t intel_limits[] = { | |||
311 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 326 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
312 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, | 327 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, |
313 | .find_pll = intel_find_best_PLL, | 328 | .find_pll = intel_find_best_PLL, |
314 | }, | 329 | }; |
330 | |||
315 | /* below parameter and function is for G4X Chipset Family*/ | 331 | /* below parameter and function is for G4X Chipset Family*/ |
316 | { /* INTEL_LIMIT_G4X_SDVO */ | 332 | static const intel_limit_t intel_limits_g4x_sdvo = { |
317 | .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, | 333 | .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, |
318 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, | 334 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, |
319 | .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, | 335 | .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, |
@@ -327,8 +343,9 @@ static const intel_limit_t intel_limits[] = { | |||
327 | .p2_fast = G4X_P2_SDVO_FAST | 343 | .p2_fast = G4X_P2_SDVO_FAST |
328 | }, | 344 | }, |
329 | .find_pll = intel_g4x_find_best_PLL, | 345 | .find_pll = intel_g4x_find_best_PLL, |
330 | }, | 346 | }; |
331 | { /* INTEL_LIMIT_G4X_HDMI_DAC */ | 347 | |
348 | static const intel_limit_t intel_limits_g4x_hdmi = { | ||
332 | .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, | 349 | .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, |
333 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, | 350 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, |
334 | .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, | 351 | .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, |
@@ -342,8 +359,9 @@ static const intel_limit_t intel_limits[] = { | |||
342 | .p2_fast = G4X_P2_HDMI_DAC_FAST | 359 | .p2_fast = G4X_P2_HDMI_DAC_FAST |
343 | }, | 360 | }, |
344 | .find_pll = intel_g4x_find_best_PLL, | 361 | .find_pll = intel_g4x_find_best_PLL, |
345 | }, | 362 | }; |
346 | { /* INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS */ | 363 | |
364 | static const intel_limit_t intel_limits_g4x_single_channel_lvds = { | ||
347 | .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, | 365 | .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, |
348 | .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, | 366 | .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, |
349 | .vco = { .min = G4X_VCO_MIN, | 367 | .vco = { .min = G4X_VCO_MIN, |
@@ -365,8 +383,9 @@ static const intel_limit_t intel_limits[] = { | |||
365 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST | 383 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST |
366 | }, | 384 | }, |
367 | .find_pll = intel_g4x_find_best_PLL, | 385 | .find_pll = intel_g4x_find_best_PLL, |
368 | }, | 386 | }; |
369 | { /* INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS */ | 387 | |
388 | static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { | ||
370 | .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, | 389 | .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, |
371 | .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, | 390 | .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, |
372 | .vco = { .min = G4X_VCO_MIN, | 391 | .vco = { .min = G4X_VCO_MIN, |
@@ -388,8 +407,32 @@ static const intel_limit_t intel_limits[] = { | |||
388 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST | 407 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST |
389 | }, | 408 | }, |
390 | .find_pll = intel_g4x_find_best_PLL, | 409 | .find_pll = intel_g4x_find_best_PLL, |
391 | }, | 410 | }; |
392 | { /* INTEL_LIMIT_IGD_SDVO */ | 411 | |
412 | static const intel_limit_t intel_limits_g4x_display_port = { | ||
413 | .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN, | ||
414 | .max = G4X_DOT_DISPLAY_PORT_MAX }, | ||
415 | .vco = { .min = G4X_VCO_MIN, | ||
416 | .max = G4X_VCO_MAX}, | ||
417 | .n = { .min = G4X_N_DISPLAY_PORT_MIN, | ||
418 | .max = G4X_N_DISPLAY_PORT_MAX }, | ||
419 | .m = { .min = G4X_M_DISPLAY_PORT_MIN, | ||
420 | .max = G4X_M_DISPLAY_PORT_MAX }, | ||
421 | .m1 = { .min = G4X_M1_DISPLAY_PORT_MIN, | ||
422 | .max = G4X_M1_DISPLAY_PORT_MAX }, | ||
423 | .m2 = { .min = G4X_M2_DISPLAY_PORT_MIN, | ||
424 | .max = G4X_M2_DISPLAY_PORT_MAX }, | ||
425 | .p = { .min = G4X_P_DISPLAY_PORT_MIN, | ||
426 | .max = G4X_P_DISPLAY_PORT_MAX }, | ||
427 | .p1 = { .min = G4X_P1_DISPLAY_PORT_MIN, | ||
428 | .max = G4X_P1_DISPLAY_PORT_MAX}, | ||
429 | .p2 = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT, | ||
430 | .p2_slow = G4X_P2_DISPLAY_PORT_SLOW, | ||
431 | .p2_fast = G4X_P2_DISPLAY_PORT_FAST }, | ||
432 | .find_pll = intel_find_pll_g4x_dp, | ||
433 | }; | ||
434 | |||
435 | static const intel_limit_t intel_limits_igd_sdvo = { | ||
393 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, | 436 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, |
394 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, | 437 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, |
395 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, | 438 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, |
@@ -401,8 +444,9 @@ static const intel_limit_t intel_limits[] = { | |||
401 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 444 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
402 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 445 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
403 | .find_pll = intel_find_best_PLL, | 446 | .find_pll = intel_find_best_PLL, |
404 | }, | 447 | }; |
405 | { /* INTEL_LIMIT_IGD_LVDS */ | 448 | |
449 | static const intel_limit_t intel_limits_igd_lvds = { | ||
406 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 450 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
407 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, | 451 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, |
408 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, | 452 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, |
@@ -415,8 +459,9 @@ static const intel_limit_t intel_limits[] = { | |||
415 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 459 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
416 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, | 460 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, |
417 | .find_pll = intel_find_best_PLL, | 461 | .find_pll = intel_find_best_PLL, |
418 | }, | 462 | }; |
419 | { /* INTEL_LIMIT_IGDNG_SDVO_DAC */ | 463 | |
464 | static const intel_limit_t intel_limits_igdng_sdvo = { | ||
420 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, | 465 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, |
421 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, | 466 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, |
422 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, | 467 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, |
@@ -429,8 +474,9 @@ static const intel_limit_t intel_limits[] = { | |||
429 | .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, | 474 | .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, |
430 | .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, | 475 | .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, |
431 | .find_pll = intel_igdng_find_best_PLL, | 476 | .find_pll = intel_igdng_find_best_PLL, |
432 | }, | 477 | }; |
433 | { /* INTEL_LIMIT_IGDNG_LVDS */ | 478 | |
479 | static const intel_limit_t intel_limits_igdng_lvds = { | ||
434 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, | 480 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, |
435 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, | 481 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, |
436 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, | 482 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, |
@@ -443,16 +489,15 @@ static const intel_limit_t intel_limits[] = { | |||
443 | .p2_slow = IGDNG_P2_LVDS_SLOW, | 489 | .p2_slow = IGDNG_P2_LVDS_SLOW, |
444 | .p2_fast = IGDNG_P2_LVDS_FAST }, | 490 | .p2_fast = IGDNG_P2_LVDS_FAST }, |
445 | .find_pll = intel_igdng_find_best_PLL, | 491 | .find_pll = intel_igdng_find_best_PLL, |
446 | }, | ||
447 | }; | 492 | }; |
448 | 493 | ||
449 | static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) | 494 | static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) |
450 | { | 495 | { |
451 | const intel_limit_t *limit; | 496 | const intel_limit_t *limit; |
452 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 497 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
453 | limit = &intel_limits[INTEL_LIMIT_IGDNG_LVDS]; | 498 | limit = &intel_limits_igdng_lvds; |
454 | else | 499 | else |
455 | limit = &intel_limits[INTEL_LIMIT_IGDNG_SDVO_DAC]; | 500 | limit = &intel_limits_igdng_sdvo; |
456 | 501 | ||
457 | return limit; | 502 | return limit; |
458 | } | 503 | } |
@@ -467,19 +512,19 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) | |||
467 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == | 512 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == |
468 | LVDS_CLKB_POWER_UP) | 513 | LVDS_CLKB_POWER_UP) |
469 | /* LVDS with dual channel */ | 514 | /* LVDS with dual channel */ |
470 | limit = &intel_limits | 515 | limit = &intel_limits_g4x_dual_channel_lvds; |
471 | [INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS]; | ||
472 | else | 516 | else |
473 | /* LVDS with dual channel */ | 517 | /* LVDS with dual channel */ |
474 | limit = &intel_limits | 518 | 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) || | 519 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || |
477 | intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { | 520 | intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { |
478 | limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC]; | 521 | limit = &intel_limits_g4x_hdmi; |
479 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { | 522 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { |
480 | limit = &intel_limits[INTEL_LIMIT_G4X_SDVO]; | 523 | limit = &intel_limits_g4x_sdvo; |
524 | } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) { | ||
525 | limit = &intel_limits_g4x_display_port; | ||
481 | } else /* The option is for other outputs */ | 526 | } else /* The option is for other outputs */ |
482 | limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; | 527 | limit = &intel_limits_i9xx_sdvo; |
483 | 528 | ||
484 | return limit; | 529 | return limit; |
485 | } | 530 | } |
@@ -495,19 +540,19 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) | |||
495 | limit = intel_g4x_limit(crtc); | 540 | limit = intel_g4x_limit(crtc); |
496 | } else if (IS_I9XX(dev) && !IS_IGD(dev)) { | 541 | } else if (IS_I9XX(dev) && !IS_IGD(dev)) { |
497 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 542 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
498 | limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; | 543 | limit = &intel_limits_i9xx_lvds; |
499 | else | 544 | else |
500 | limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; | 545 | limit = &intel_limits_i9xx_sdvo; |
501 | } else if (IS_IGD(dev)) { | 546 | } else if (IS_IGD(dev)) { |
502 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 547 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
503 | limit = &intel_limits[INTEL_LIMIT_IGD_LVDS]; | 548 | limit = &intel_limits_igd_lvds; |
504 | else | 549 | else |
505 | limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC]; | 550 | limit = &intel_limits_igd_sdvo; |
506 | } else { | 551 | } else { |
507 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 552 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
508 | limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS]; | 553 | limit = &intel_limits_i8xx_lvds; |
509 | else | 554 | else |
510 | limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC]; | 555 | limit = &intel_limits_i8xx_dvo; |
511 | } | 556 | } |
512 | return limit; | 557 | return limit; |
513 | } | 558 | } |
@@ -764,6 +809,32 @@ out: | |||
764 | return found; | 809 | return found; |
765 | } | 810 | } |
766 | 811 | ||
812 | /* DisplayPort has only two frequencies, 162MHz and 270MHz */ | ||
813 | static bool | ||
814 | intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
815 | int target, int refclk, intel_clock_t *best_clock) | ||
816 | { | ||
817 | intel_clock_t clock; | ||
818 | if (target < 200000) { | ||
819 | clock.p1 = 2; | ||
820 | clock.p2 = 10; | ||
821 | clock.n = 2; | ||
822 | clock.m1 = 23; | ||
823 | clock.m2 = 8; | ||
824 | } else { | ||
825 | clock.p1 = 1; | ||
826 | clock.p2 = 10; | ||
827 | clock.n = 1; | ||
828 | clock.m1 = 14; | ||
829 | clock.m2 = 2; | ||
830 | } | ||
831 | clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2); | ||
832 | clock.p = (clock.p1 * clock.p2); | ||
833 | clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p; | ||
834 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); | ||
835 | return true; | ||
836 | } | ||
837 | |||
767 | void | 838 | void |
768 | intel_wait_for_vblank(struct drm_device *dev) | 839 | intel_wait_for_vblank(struct drm_device *dev) |
769 | { | 840 | { |
@@ -933,7 +1004,7 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
933 | struct drm_i915_private *dev_priv = dev->dev_private; | 1004 | struct drm_i915_private *dev_priv = dev->dev_private; |
934 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1005 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
935 | int pipe = intel_crtc->pipe; | 1006 | int pipe = intel_crtc->pipe; |
936 | int plane = intel_crtc->pipe; | 1007 | int plane = intel_crtc->plane; |
937 | int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; | 1008 | int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; |
938 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | 1009 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; |
939 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; | 1010 | int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; |
@@ -1263,8 +1334,10 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
1263 | 1334 | ||
1264 | /* Give the overlay scaler a chance to enable if it's on this pipe */ | 1335 | /* Give the overlay scaler a chance to enable if it's on this pipe */ |
1265 | //intel_crtc_dpms_video(crtc, true); TODO | 1336 | //intel_crtc_dpms_video(crtc, true); TODO |
1337 | intel_update_watermarks(dev); | ||
1266 | break; | 1338 | break; |
1267 | case DRM_MODE_DPMS_OFF: | 1339 | case DRM_MODE_DPMS_OFF: |
1340 | intel_update_watermarks(dev); | ||
1268 | /* Give the overlay scaler a chance to disable if it's on this pipe */ | 1341 | /* Give the overlay scaler a chance to disable if it's on this pipe */ |
1269 | //intel_crtc_dpms_video(crtc, FALSE); TODO | 1342 | //intel_crtc_dpms_video(crtc, FALSE); TODO |
1270 | 1343 | ||
@@ -1443,7 +1516,6 @@ static int intel_get_core_clock_speed(struct drm_device *dev) | |||
1443 | return 0; /* Silence gcc warning */ | 1516 | return 0; /* Silence gcc warning */ |
1444 | } | 1517 | } |
1445 | 1518 | ||
1446 | |||
1447 | /** | 1519 | /** |
1448 | * Return the pipe currently connected to the panel fitter, | 1520 | * Return the pipe currently connected to the panel fitter, |
1449 | * or -1 if the panel fitter is not present or not in use | 1521 | * or -1 if the panel fitter is not present or not in use |
@@ -1502,7 +1574,7 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes, | |||
1502 | 1574 | ||
1503 | temp = (u64) DATA_N * pixel_clock; | 1575 | temp = (u64) DATA_N * pixel_clock; |
1504 | temp = div_u64(temp, link_clock); | 1576 | temp = div_u64(temp, link_clock); |
1505 | m_n->gmch_m = (temp * bytes_per_pixel) / nlanes; | 1577 | m_n->gmch_m = div_u64(temp * bytes_per_pixel, nlanes); |
1506 | m_n->gmch_n = DATA_N; | 1578 | m_n->gmch_n = DATA_N; |
1507 | fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); | 1579 | fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); |
1508 | 1580 | ||
@@ -1513,6 +1585,420 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes, | |||
1513 | } | 1585 | } |
1514 | 1586 | ||
1515 | 1587 | ||
1588 | struct intel_watermark_params { | ||
1589 | unsigned long fifo_size; | ||
1590 | unsigned long max_wm; | ||
1591 | unsigned long default_wm; | ||
1592 | unsigned long guard_size; | ||
1593 | unsigned long cacheline_size; | ||
1594 | }; | ||
1595 | |||
1596 | /* IGD has different values for various configs */ | ||
1597 | static struct intel_watermark_params igd_display_wm = { | ||
1598 | IGD_DISPLAY_FIFO, | ||
1599 | IGD_MAX_WM, | ||
1600 | IGD_DFT_WM, | ||
1601 | IGD_GUARD_WM, | ||
1602 | IGD_FIFO_LINE_SIZE | ||
1603 | }; | ||
1604 | static struct intel_watermark_params igd_display_hplloff_wm = { | ||
1605 | IGD_DISPLAY_FIFO, | ||
1606 | IGD_MAX_WM, | ||
1607 | IGD_DFT_HPLLOFF_WM, | ||
1608 | IGD_GUARD_WM, | ||
1609 | IGD_FIFO_LINE_SIZE | ||
1610 | }; | ||
1611 | static struct intel_watermark_params igd_cursor_wm = { | ||
1612 | IGD_CURSOR_FIFO, | ||
1613 | IGD_CURSOR_MAX_WM, | ||
1614 | IGD_CURSOR_DFT_WM, | ||
1615 | IGD_CURSOR_GUARD_WM, | ||
1616 | IGD_FIFO_LINE_SIZE, | ||
1617 | }; | ||
1618 | static struct intel_watermark_params igd_cursor_hplloff_wm = { | ||
1619 | IGD_CURSOR_FIFO, | ||
1620 | IGD_CURSOR_MAX_WM, | ||
1621 | IGD_CURSOR_DFT_WM, | ||
1622 | IGD_CURSOR_GUARD_WM, | ||
1623 | IGD_FIFO_LINE_SIZE | ||
1624 | }; | ||
1625 | static struct intel_watermark_params i945_wm_info = { | ||
1626 | I915_FIFO_LINE_SIZE, | ||
1627 | I915_MAX_WM, | ||
1628 | 1, | ||
1629 | 0, | ||
1630 | IGD_FIFO_LINE_SIZE | ||
1631 | }; | ||
1632 | static struct intel_watermark_params i915_wm_info = { | ||
1633 | I945_FIFO_SIZE, | ||
1634 | I915_MAX_WM, | ||
1635 | 1, | ||
1636 | 0, | ||
1637 | I915_FIFO_LINE_SIZE | ||
1638 | }; | ||
1639 | static struct intel_watermark_params i855_wm_info = { | ||
1640 | I855GM_FIFO_SIZE, | ||
1641 | I915_MAX_WM, | ||
1642 | 1, | ||
1643 | 0, | ||
1644 | I830_FIFO_LINE_SIZE | ||
1645 | }; | ||
1646 | static struct intel_watermark_params i830_wm_info = { | ||
1647 | I830_FIFO_SIZE, | ||
1648 | I915_MAX_WM, | ||
1649 | 1, | ||
1650 | 0, | ||
1651 | I830_FIFO_LINE_SIZE | ||
1652 | }; | ||
1653 | |||
1654 | static unsigned long intel_calculate_wm(unsigned long clock_in_khz, | ||
1655 | struct intel_watermark_params *wm, | ||
1656 | int pixel_size, | ||
1657 | unsigned long latency_ns) | ||
1658 | { | ||
1659 | unsigned long bytes_required, wm_size; | ||
1660 | |||
1661 | bytes_required = (clock_in_khz * pixel_size * latency_ns) / 1000000; | ||
1662 | bytes_required /= wm->cacheline_size; | ||
1663 | wm_size = wm->fifo_size - bytes_required - wm->guard_size; | ||
1664 | |||
1665 | if (wm_size > wm->max_wm) | ||
1666 | wm_size = wm->max_wm; | ||
1667 | if (wm_size == 0) | ||
1668 | wm_size = wm->default_wm; | ||
1669 | return wm_size; | ||
1670 | } | ||
1671 | |||
1672 | struct cxsr_latency { | ||
1673 | int is_desktop; | ||
1674 | unsigned long fsb_freq; | ||
1675 | unsigned long mem_freq; | ||
1676 | unsigned long display_sr; | ||
1677 | unsigned long display_hpll_disable; | ||
1678 | unsigned long cursor_sr; | ||
1679 | unsigned long cursor_hpll_disable; | ||
1680 | }; | ||
1681 | |||
1682 | static struct cxsr_latency cxsr_latency_table[] = { | ||
1683 | {1, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */ | ||
1684 | {1, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */ | ||
1685 | {1, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */ | ||
1686 | |||
1687 | {1, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */ | ||
1688 | {1, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */ | ||
1689 | {1, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */ | ||
1690 | |||
1691 | {1, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */ | ||
1692 | {1, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */ | ||
1693 | {1, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */ | ||
1694 | |||
1695 | {0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */ | ||
1696 | {0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */ | ||
1697 | {0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */ | ||
1698 | |||
1699 | {0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */ | ||
1700 | {0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */ | ||
1701 | {0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */ | ||
1702 | |||
1703 | {0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */ | ||
1704 | {0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */ | ||
1705 | {0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */ | ||
1706 | }; | ||
1707 | |||
1708 | static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb, | ||
1709 | int mem) | ||
1710 | { | ||
1711 | int i; | ||
1712 | struct cxsr_latency *latency; | ||
1713 | |||
1714 | if (fsb == 0 || mem == 0) | ||
1715 | return NULL; | ||
1716 | |||
1717 | for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) { | ||
1718 | latency = &cxsr_latency_table[i]; | ||
1719 | if (is_desktop == latency->is_desktop && | ||
1720 | fsb == latency->fsb_freq && mem == latency->mem_freq) | ||
1721 | break; | ||
1722 | } | ||
1723 | if (i >= ARRAY_SIZE(cxsr_latency_table)) { | ||
1724 | DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n"); | ||
1725 | return NULL; | ||
1726 | } | ||
1727 | return latency; | ||
1728 | } | ||
1729 | |||
1730 | static void igd_disable_cxsr(struct drm_device *dev) | ||
1731 | { | ||
1732 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1733 | u32 reg; | ||
1734 | |||
1735 | /* deactivate cxsr */ | ||
1736 | reg = I915_READ(DSPFW3); | ||
1737 | reg &= ~(IGD_SELF_REFRESH_EN); | ||
1738 | I915_WRITE(DSPFW3, reg); | ||
1739 | DRM_INFO("Big FIFO is disabled\n"); | ||
1740 | } | ||
1741 | |||
1742 | static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock, | ||
1743 | int pixel_size) | ||
1744 | { | ||
1745 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1746 | u32 reg; | ||
1747 | unsigned long wm; | ||
1748 | struct cxsr_latency *latency; | ||
1749 | |||
1750 | latency = intel_get_cxsr_latency(IS_IGDG(dev), dev_priv->fsb_freq, | ||
1751 | dev_priv->mem_freq); | ||
1752 | if (!latency) { | ||
1753 | DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n"); | ||
1754 | igd_disable_cxsr(dev); | ||
1755 | return; | ||
1756 | } | ||
1757 | |||
1758 | /* Display SR */ | ||
1759 | wm = intel_calculate_wm(clock, &igd_display_wm, pixel_size, | ||
1760 | latency->display_sr); | ||
1761 | reg = I915_READ(DSPFW1); | ||
1762 | reg &= 0x7fffff; | ||
1763 | reg |= wm << 23; | ||
1764 | I915_WRITE(DSPFW1, reg); | ||
1765 | DRM_DEBUG("DSPFW1 register is %x\n", reg); | ||
1766 | |||
1767 | /* cursor SR */ | ||
1768 | wm = intel_calculate_wm(clock, &igd_cursor_wm, pixel_size, | ||
1769 | latency->cursor_sr); | ||
1770 | reg = I915_READ(DSPFW3); | ||
1771 | reg &= ~(0x3f << 24); | ||
1772 | reg |= (wm & 0x3f) << 24; | ||
1773 | I915_WRITE(DSPFW3, reg); | ||
1774 | |||
1775 | /* Display HPLL off SR */ | ||
1776 | wm = intel_calculate_wm(clock, &igd_display_hplloff_wm, | ||
1777 | latency->display_hpll_disable, I915_FIFO_LINE_SIZE); | ||
1778 | reg = I915_READ(DSPFW3); | ||
1779 | reg &= 0xfffffe00; | ||
1780 | reg |= wm & 0x1ff; | ||
1781 | I915_WRITE(DSPFW3, reg); | ||
1782 | |||
1783 | /* cursor HPLL off SR */ | ||
1784 | wm = intel_calculate_wm(clock, &igd_cursor_hplloff_wm, pixel_size, | ||
1785 | latency->cursor_hpll_disable); | ||
1786 | reg = I915_READ(DSPFW3); | ||
1787 | reg &= ~(0x3f << 16); | ||
1788 | reg |= (wm & 0x3f) << 16; | ||
1789 | I915_WRITE(DSPFW3, reg); | ||
1790 | DRM_DEBUG("DSPFW3 register is %x\n", reg); | ||
1791 | |||
1792 | /* activate cxsr */ | ||
1793 | reg = I915_READ(DSPFW3); | ||
1794 | reg |= IGD_SELF_REFRESH_EN; | ||
1795 | I915_WRITE(DSPFW3, reg); | ||
1796 | |||
1797 | DRM_INFO("Big FIFO is enabled\n"); | ||
1798 | |||
1799 | return; | ||
1800 | } | ||
1801 | |||
1802 | const static int latency_ns = 5000; /* default for non-igd platforms */ | ||
1803 | |||
1804 | |||
1805 | static void i965_update_wm(struct drm_device *dev) | ||
1806 | { | ||
1807 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1808 | |||
1809 | DRM_DEBUG("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR 8\n"); | ||
1810 | |||
1811 | /* 965 has limitations... */ | ||
1812 | I915_WRITE(DSPFW1, (8 << 16) | (8 << 8) | (8 << 0)); | ||
1813 | I915_WRITE(DSPFW2, (8 << 8) | (8 << 0)); | ||
1814 | } | ||
1815 | |||
1816 | static void i9xx_update_wm(struct drm_device *dev, int planea_clock, | ||
1817 | int planeb_clock, int sr_hdisplay, int pixel_size) | ||
1818 | { | ||
1819 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1820 | uint32_t fwater_lo = I915_READ(FW_BLC) & MM_FIFO_WATERMARK; | ||
1821 | uint32_t fwater_hi = I915_READ(FW_BLC2) & LM_FIFO_WATERMARK; | ||
1822 | int bsize, asize, cwm, bwm = 1, awm = 1, srwm = 1; | ||
1823 | uint32_t dsparb = I915_READ(DSPARB); | ||
1824 | int planea_entries, planeb_entries; | ||
1825 | struct intel_watermark_params *wm_params; | ||
1826 | unsigned long line_time_us; | ||
1827 | int sr_clock, sr_entries = 0; | ||
1828 | |||
1829 | if (IS_I965GM(dev) || IS_I945GM(dev)) | ||
1830 | wm_params = &i945_wm_info; | ||
1831 | else if (IS_I9XX(dev)) | ||
1832 | wm_params = &i915_wm_info; | ||
1833 | else | ||
1834 | wm_params = &i855_wm_info; | ||
1835 | |||
1836 | planea_entries = intel_calculate_wm(planea_clock, wm_params, | ||
1837 | pixel_size, latency_ns); | ||
1838 | planeb_entries = intel_calculate_wm(planeb_clock, wm_params, | ||
1839 | pixel_size, latency_ns); | ||
1840 | |||
1841 | DRM_DEBUG("FIFO entries - A: %d, B: %d\n", planea_entries, | ||
1842 | planeb_entries); | ||
1843 | |||
1844 | if (IS_I9XX(dev)) { | ||
1845 | asize = dsparb & 0x7f; | ||
1846 | bsize = (dsparb >> DSPARB_CSTART_SHIFT) & 0x7f; | ||
1847 | } else { | ||
1848 | asize = dsparb & 0x1ff; | ||
1849 | bsize = (dsparb >> DSPARB_BEND_SHIFT) & 0x1ff; | ||
1850 | } | ||
1851 | DRM_DEBUG("FIFO size - A: %d, B: %d\n", asize, bsize); | ||
1852 | |||
1853 | /* Two extra entries for padding */ | ||
1854 | awm = asize - (planea_entries + 2); | ||
1855 | bwm = bsize - (planeb_entries + 2); | ||
1856 | |||
1857 | /* Sanity check against potentially bad FIFO allocations */ | ||
1858 | if (awm <= 0) { | ||
1859 | /* pipe is on but has too few FIFO entries */ | ||
1860 | if (planea_entries != 0) | ||
1861 | DRM_DEBUG("plane A needs more FIFO entries\n"); | ||
1862 | awm = 1; | ||
1863 | } | ||
1864 | if (bwm <= 0) { | ||
1865 | if (planeb_entries != 0) | ||
1866 | DRM_DEBUG("plane B needs more FIFO entries\n"); | ||
1867 | bwm = 1; | ||
1868 | } | ||
1869 | |||
1870 | /* | ||
1871 | * Overlay gets an aggressive default since video jitter is bad. | ||
1872 | */ | ||
1873 | cwm = 2; | ||
1874 | |||
1875 | /* Calc sr entries for one pipe configs */ | ||
1876 | if (!planea_clock || !planeb_clock) { | ||
1877 | sr_clock = planea_clock ? planea_clock : planeb_clock; | ||
1878 | line_time_us = (sr_hdisplay * 1000) / sr_clock; | ||
1879 | sr_entries = (((latency_ns / line_time_us) + 1) * pixel_size * | ||
1880 | sr_hdisplay) / 1000; | ||
1881 | sr_entries = roundup(sr_entries / wm_params->cacheline_size, 1); | ||
1882 | if (sr_entries < wm_params->fifo_size) | ||
1883 | srwm = wm_params->fifo_size - sr_entries; | ||
1884 | } | ||
1885 | |||
1886 | DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", | ||
1887 | awm, bwm, cwm, srwm); | ||
1888 | |||
1889 | fwater_lo = fwater_lo | ((bwm & 0x3f) << 16) | (awm & 0x3f); | ||
1890 | fwater_hi = fwater_hi | (cwm & 0x1f); | ||
1891 | |||
1892 | I915_WRITE(FW_BLC, fwater_lo); | ||
1893 | I915_WRITE(FW_BLC2, fwater_hi); | ||
1894 | if (IS_I9XX(dev)) | ||
1895 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f)); | ||
1896 | } | ||
1897 | |||
1898 | static void i830_update_wm(struct drm_device *dev, int planea_clock, | ||
1899 | int pixel_size) | ||
1900 | { | ||
1901 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1902 | uint32_t dsparb = I915_READ(DSPARB); | ||
1903 | uint32_t fwater_lo = I915_READ(FW_BLC) & MM_FIFO_WATERMARK; | ||
1904 | unsigned int asize, awm; | ||
1905 | int planea_entries; | ||
1906 | |||
1907 | planea_entries = intel_calculate_wm(planea_clock, &i830_wm_info, | ||
1908 | pixel_size, latency_ns); | ||
1909 | |||
1910 | asize = dsparb & 0x7f; | ||
1911 | |||
1912 | awm = asize - planea_entries; | ||
1913 | |||
1914 | fwater_lo = fwater_lo | awm; | ||
1915 | |||
1916 | I915_WRITE(FW_BLC, fwater_lo); | ||
1917 | } | ||
1918 | |||
1919 | /** | ||
1920 | * intel_update_watermarks - update FIFO watermark values based on current modes | ||
1921 | * | ||
1922 | * Calculate watermark values for the various WM regs based on current mode | ||
1923 | * and plane configuration. | ||
1924 | * | ||
1925 | * There are several cases to deal with here: | ||
1926 | * - normal (i.e. non-self-refresh) | ||
1927 | * - self-refresh (SR) mode | ||
1928 | * - lines are large relative to FIFO size (buffer can hold up to 2) | ||
1929 | * - lines are small relative to FIFO size (buffer can hold more than 2 | ||
1930 | * lines), so need to account for TLB latency | ||
1931 | * | ||
1932 | * The normal calculation is: | ||
1933 | * watermark = dotclock * bytes per pixel * latency | ||
1934 | * where latency is platform & configuration dependent (we assume pessimal | ||
1935 | * values here). | ||
1936 | * | ||
1937 | * The SR calculation is: | ||
1938 | * watermark = (trunc(latency/line time)+1) * surface width * | ||
1939 | * bytes per pixel | ||
1940 | * where | ||
1941 | * line time = htotal / dotclock | ||
1942 | * and latency is assumed to be high, as above. | ||
1943 | * | ||
1944 | * The final value programmed to the register should always be rounded up, | ||
1945 | * and include an extra 2 entries to account for clock crossings. | ||
1946 | * | ||
1947 | * We don't use the sprite, so we can ignore that. And on Crestline we have | ||
1948 | * to set the non-SR watermarks to 8. | ||
1949 | */ | ||
1950 | static void intel_update_watermarks(struct drm_device *dev) | ||
1951 | { | ||
1952 | struct drm_crtc *crtc; | ||
1953 | struct intel_crtc *intel_crtc; | ||
1954 | int sr_hdisplay = 0; | ||
1955 | unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0; | ||
1956 | int enabled = 0, pixel_size = 0; | ||
1957 | |||
1958 | if (DSPARB_HWCONTROL(dev)) | ||
1959 | return; | ||
1960 | |||
1961 | /* Get the clock config from both planes */ | ||
1962 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
1963 | intel_crtc = to_intel_crtc(crtc); | ||
1964 | if (crtc->enabled) { | ||
1965 | enabled++; | ||
1966 | if (intel_crtc->plane == 0) { | ||
1967 | DRM_DEBUG("plane A (pipe %d) clock: %d\n", | ||
1968 | intel_crtc->pipe, crtc->mode.clock); | ||
1969 | planea_clock = crtc->mode.clock; | ||
1970 | } else { | ||
1971 | DRM_DEBUG("plane B (pipe %d) clock: %d\n", | ||
1972 | intel_crtc->pipe, crtc->mode.clock); | ||
1973 | planeb_clock = crtc->mode.clock; | ||
1974 | } | ||
1975 | sr_hdisplay = crtc->mode.hdisplay; | ||
1976 | sr_clock = crtc->mode.clock; | ||
1977 | if (crtc->fb) | ||
1978 | pixel_size = crtc->fb->bits_per_pixel / 8; | ||
1979 | else | ||
1980 | pixel_size = 4; /* by default */ | ||
1981 | } | ||
1982 | } | ||
1983 | |||
1984 | if (enabled <= 0) | ||
1985 | return; | ||
1986 | |||
1987 | /* Single pipe configs can enable self refresh */ | ||
1988 | if (enabled == 1 && IS_IGD(dev)) | ||
1989 | igd_enable_cxsr(dev, sr_clock, pixel_size); | ||
1990 | else if (IS_IGD(dev)) | ||
1991 | igd_disable_cxsr(dev); | ||
1992 | |||
1993 | if (IS_I965G(dev)) | ||
1994 | i965_update_wm(dev); | ||
1995 | else if (IS_I9XX(dev) || IS_MOBILE(dev)) | ||
1996 | i9xx_update_wm(dev, planea_clock, planeb_clock, sr_hdisplay, | ||
1997 | pixel_size); | ||
1998 | else | ||
1999 | i830_update_wm(dev, planea_clock, pixel_size); | ||
2000 | } | ||
2001 | |||
1516 | static int intel_crtc_mode_set(struct drm_crtc *crtc, | 2002 | static int intel_crtc_mode_set(struct drm_crtc *crtc, |
1517 | struct drm_display_mode *mode, | 2003 | struct drm_display_mode *mode, |
1518 | struct drm_display_mode *adjusted_mode, | 2004 | struct drm_display_mode *adjusted_mode, |
@@ -1541,7 +2027,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1541 | intel_clock_t clock; | 2027 | intel_clock_t clock; |
1542 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; | 2028 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; |
1543 | bool ok, is_sdvo = false, is_dvo = false; | 2029 | bool ok, is_sdvo = false, is_dvo = false; |
1544 | bool is_crt = false, is_lvds = false, is_tv = false; | 2030 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; |
1545 | struct drm_mode_config *mode_config = &dev->mode_config; | 2031 | struct drm_mode_config *mode_config = &dev->mode_config; |
1546 | struct drm_connector *connector; | 2032 | struct drm_connector *connector; |
1547 | const intel_limit_t *limit; | 2033 | const intel_limit_t *limit; |
@@ -1585,6 +2071,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1585 | case INTEL_OUTPUT_ANALOG: | 2071 | case INTEL_OUTPUT_ANALOG: |
1586 | is_crt = true; | 2072 | is_crt = true; |
1587 | break; | 2073 | break; |
2074 | case INTEL_OUTPUT_DISPLAYPORT: | ||
2075 | is_dp = true; | ||
2076 | break; | ||
1588 | } | 2077 | } |
1589 | 2078 | ||
1590 | num_outputs++; | 2079 | num_outputs++; |
@@ -1600,6 +2089,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1600 | } else { | 2089 | } else { |
1601 | refclk = 48000; | 2090 | refclk = 48000; |
1602 | } | 2091 | } |
2092 | |||
1603 | 2093 | ||
1604 | /* | 2094 | /* |
1605 | * Returns a set of divisors for the desired target clock with the given | 2095 | * Returns a set of divisors for the desired target clock with the given |
@@ -1662,6 +2152,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1662 | else if (IS_IGDNG(dev)) | 2152 | else if (IS_IGDNG(dev)) |
1663 | dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; | 2153 | dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; |
1664 | } | 2154 | } |
2155 | if (is_dp) | ||
2156 | dpll |= DPLL_DVO_HIGH_SPEED; | ||
1665 | 2157 | ||
1666 | /* compute bitmask from p1 value */ | 2158 | /* compute bitmask from p1 value */ |
1667 | if (IS_IGD(dev)) | 2159 | if (IS_IGD(dev)) |
@@ -1809,6 +2301,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1809 | I915_WRITE(lvds_reg, lvds); | 2301 | I915_WRITE(lvds_reg, lvds); |
1810 | I915_READ(lvds_reg); | 2302 | I915_READ(lvds_reg); |
1811 | } | 2303 | } |
2304 | if (is_dp) | ||
2305 | intel_dp_set_m_n(crtc, mode, adjusted_mode); | ||
1812 | 2306 | ||
1813 | I915_WRITE(fp_reg, fp); | 2307 | I915_WRITE(fp_reg, fp); |
1814 | I915_WRITE(dpll_reg, dpll); | 2308 | I915_WRITE(dpll_reg, dpll); |
@@ -1871,6 +2365,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1871 | 2365 | ||
1872 | /* Flush the plane changes */ | 2366 | /* Flush the plane changes */ |
1873 | ret = intel_pipe_set_base(crtc, x, y, old_fb); | 2367 | ret = intel_pipe_set_base(crtc, x, y, old_fb); |
2368 | |||
2369 | intel_update_watermarks(dev); | ||
2370 | |||
1874 | drm_vblank_post_modeset(dev, pipe); | 2371 | drm_vblank_post_modeset(dev, pipe); |
1875 | 2372 | ||
1876 | return ret; | 2373 | return ret; |
@@ -2359,6 +2856,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
2359 | 2856 | ||
2360 | drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); | 2857 | drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); |
2361 | intel_crtc->pipe = pipe; | 2858 | intel_crtc->pipe = pipe; |
2859 | intel_crtc->plane = pipe; | ||
2362 | for (i = 0; i < 256; i++) { | 2860 | for (i = 0; i < 256; i++) { |
2363 | intel_crtc->lut_r[i] = i; | 2861 | intel_crtc->lut_r[i] = i; |
2364 | intel_crtc->lut_g[i] = i; | 2862 | intel_crtc->lut_g[i] = i; |
@@ -2475,6 +2973,8 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
2475 | found = intel_sdvo_init(dev, SDVOB); | 2973 | found = intel_sdvo_init(dev, SDVOB); |
2476 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | 2974 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) |
2477 | intel_hdmi_init(dev, SDVOB); | 2975 | intel_hdmi_init(dev, SDVOB); |
2976 | if (!found && SUPPORTS_INTEGRATED_DP(dev)) | ||
2977 | intel_dp_init(dev, DP_B); | ||
2478 | } | 2978 | } |
2479 | 2979 | ||
2480 | /* Before G4X SDVOC doesn't have its own detect register */ | 2980 | /* Before G4X SDVOC doesn't have its own detect register */ |
@@ -2487,7 +2987,11 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
2487 | found = intel_sdvo_init(dev, SDVOC); | 2987 | found = intel_sdvo_init(dev, SDVOC); |
2488 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | 2988 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) |
2489 | intel_hdmi_init(dev, SDVOC); | 2989 | intel_hdmi_init(dev, SDVOC); |
2990 | if (!found && SUPPORTS_INTEGRATED_DP(dev)) | ||
2991 | intel_dp_init(dev, DP_C); | ||
2490 | } | 2992 | } |
2993 | if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) | ||
2994 | intel_dp_init(dev, DP_D); | ||
2491 | } else | 2995 | } else |
2492 | intel_dvo_init(dev); | 2996 | intel_dvo_init(dev); |
2493 | 2997 | ||
@@ -2530,6 +3034,11 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
2530 | (1 << 1)); | 3034 | (1 << 1)); |
2531 | clone_mask = (1 << INTEL_OUTPUT_TVOUT); | 3035 | clone_mask = (1 << INTEL_OUTPUT_TVOUT); |
2532 | break; | 3036 | break; |
3037 | case INTEL_OUTPUT_DISPLAYPORT: | ||
3038 | crtc_mask = ((1 << 0) | | ||
3039 | (1 << 1)); | ||
3040 | clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT); | ||
3041 | break; | ||
2533 | } | 3042 | } |
2534 | encoder->possible_crtcs = crtc_mask; | 3043 | encoder->possible_crtcs = crtc_mask; |
2535 | encoder->possible_clones = intel_connector_clones(dev, clone_mask); | 3044 | encoder->possible_clones = intel_connector_clones(dev, clone_mask); |