diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 356 |
1 files changed, 234 insertions, 122 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 002612fae717..b27202d23ebc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -70,8 +70,6 @@ struct intel_limit { | |||
70 | intel_p2_t p2; | 70 | intel_p2_t p2; |
71 | bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, | 71 | bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, |
72 | int, int, intel_clock_t *); | 72 | int, int, intel_clock_t *); |
73 | bool (* find_reduced_pll)(const intel_limit_t *, struct drm_crtc *, | ||
74 | int, int, intel_clock_t *); | ||
75 | }; | 73 | }; |
76 | 74 | ||
77 | #define I8XX_DOT_MIN 25000 | 75 | #define I8XX_DOT_MIN 25000 |
@@ -242,41 +240,91 @@ struct intel_limit { | |||
242 | #define IRONLAKE_DOT_MAX 350000 | 240 | #define IRONLAKE_DOT_MAX 350000 |
243 | #define IRONLAKE_VCO_MIN 1760000 | 241 | #define IRONLAKE_VCO_MIN 1760000 |
244 | #define IRONLAKE_VCO_MAX 3510000 | 242 | #define IRONLAKE_VCO_MAX 3510000 |
245 | #define IRONLAKE_N_MIN 1 | ||
246 | #define IRONLAKE_N_MAX 5 | ||
247 | #define IRONLAKE_M_MIN 79 | ||
248 | #define IRONLAKE_M_MAX 118 | ||
249 | #define IRONLAKE_M1_MIN 12 | 243 | #define IRONLAKE_M1_MIN 12 |
250 | #define IRONLAKE_M1_MAX 23 | 244 | #define IRONLAKE_M1_MAX 22 |
251 | #define IRONLAKE_M2_MIN 5 | 245 | #define IRONLAKE_M2_MIN 5 |
252 | #define IRONLAKE_M2_MAX 9 | 246 | #define IRONLAKE_M2_MAX 9 |
253 | #define IRONLAKE_P_SDVO_DAC_MIN 5 | ||
254 | #define IRONLAKE_P_SDVO_DAC_MAX 80 | ||
255 | #define IRONLAKE_P_LVDS_MIN 28 | ||
256 | #define IRONLAKE_P_LVDS_MAX 112 | ||
257 | #define IRONLAKE_P1_MIN 1 | ||
258 | #define IRONLAKE_P1_MAX 8 | ||
259 | #define IRONLAKE_P2_SDVO_DAC_SLOW 10 | ||
260 | #define IRONLAKE_P2_SDVO_DAC_FAST 5 | ||
261 | #define IRONLAKE_P2_LVDS_SLOW 14 /* single channel */ | ||
262 | #define IRONLAKE_P2_LVDS_FAST 7 /* double channel */ | ||
263 | #define IRONLAKE_P2_DOT_LIMIT 225000 /* 225Mhz */ | 247 | #define IRONLAKE_P2_DOT_LIMIT 225000 /* 225Mhz */ |
264 | 248 | ||
265 | #define IRONLAKE_P_DISPLAY_PORT_MIN 10 | 249 | /* We have parameter ranges for different type of outputs. */ |
266 | #define IRONLAKE_P_DISPLAY_PORT_MAX 20 | 250 | |
267 | #define IRONLAKE_P2_DISPLAY_PORT_FAST 10 | 251 | /* DAC & HDMI Refclk 120Mhz */ |
268 | #define IRONLAKE_P2_DISPLAY_PORT_SLOW 10 | 252 | #define IRONLAKE_DAC_N_MIN 1 |
269 | #define IRONLAKE_P2_DISPLAY_PORT_LIMIT 0 | 253 | #define IRONLAKE_DAC_N_MAX 5 |
270 | #define IRONLAKE_P1_DISPLAY_PORT_MIN 1 | 254 | #define IRONLAKE_DAC_M_MIN 79 |
271 | #define IRONLAKE_P1_DISPLAY_PORT_MAX 2 | 255 | #define IRONLAKE_DAC_M_MAX 127 |
256 | #define IRONLAKE_DAC_P_MIN 5 | ||
257 | #define IRONLAKE_DAC_P_MAX 80 | ||
258 | #define IRONLAKE_DAC_P1_MIN 1 | ||
259 | #define IRONLAKE_DAC_P1_MAX 8 | ||
260 | #define IRONLAKE_DAC_P2_SLOW 10 | ||
261 | #define IRONLAKE_DAC_P2_FAST 5 | ||
262 | |||
263 | /* LVDS single-channel 120Mhz refclk */ | ||
264 | #define IRONLAKE_LVDS_S_N_MIN 1 | ||
265 | #define IRONLAKE_LVDS_S_N_MAX 3 | ||
266 | #define IRONLAKE_LVDS_S_M_MIN 79 | ||
267 | #define IRONLAKE_LVDS_S_M_MAX 118 | ||
268 | #define IRONLAKE_LVDS_S_P_MIN 28 | ||
269 | #define IRONLAKE_LVDS_S_P_MAX 112 | ||
270 | #define IRONLAKE_LVDS_S_P1_MIN 2 | ||
271 | #define IRONLAKE_LVDS_S_P1_MAX 8 | ||
272 | #define IRONLAKE_LVDS_S_P2_SLOW 14 | ||
273 | #define IRONLAKE_LVDS_S_P2_FAST 14 | ||
274 | |||
275 | /* LVDS dual-channel 120Mhz refclk */ | ||
276 | #define IRONLAKE_LVDS_D_N_MIN 1 | ||
277 | #define IRONLAKE_LVDS_D_N_MAX 3 | ||
278 | #define IRONLAKE_LVDS_D_M_MIN 79 | ||
279 | #define IRONLAKE_LVDS_D_M_MAX 127 | ||
280 | #define IRONLAKE_LVDS_D_P_MIN 14 | ||
281 | #define IRONLAKE_LVDS_D_P_MAX 56 | ||
282 | #define IRONLAKE_LVDS_D_P1_MIN 2 | ||
283 | #define IRONLAKE_LVDS_D_P1_MAX 8 | ||
284 | #define IRONLAKE_LVDS_D_P2_SLOW 7 | ||
285 | #define IRONLAKE_LVDS_D_P2_FAST 7 | ||
286 | |||
287 | /* LVDS single-channel 100Mhz refclk */ | ||
288 | #define IRONLAKE_LVDS_S_SSC_N_MIN 1 | ||
289 | #define IRONLAKE_LVDS_S_SSC_N_MAX 2 | ||
290 | #define IRONLAKE_LVDS_S_SSC_M_MIN 79 | ||
291 | #define IRONLAKE_LVDS_S_SSC_M_MAX 126 | ||
292 | #define IRONLAKE_LVDS_S_SSC_P_MIN 28 | ||
293 | #define IRONLAKE_LVDS_S_SSC_P_MAX 112 | ||
294 | #define IRONLAKE_LVDS_S_SSC_P1_MIN 2 | ||
295 | #define IRONLAKE_LVDS_S_SSC_P1_MAX 8 | ||
296 | #define IRONLAKE_LVDS_S_SSC_P2_SLOW 14 | ||
297 | #define IRONLAKE_LVDS_S_SSC_P2_FAST 14 | ||
298 | |||
299 | /* LVDS dual-channel 100Mhz refclk */ | ||
300 | #define IRONLAKE_LVDS_D_SSC_N_MIN 1 | ||
301 | #define IRONLAKE_LVDS_D_SSC_N_MAX 3 | ||
302 | #define IRONLAKE_LVDS_D_SSC_M_MIN 79 | ||
303 | #define IRONLAKE_LVDS_D_SSC_M_MAX 126 | ||
304 | #define IRONLAKE_LVDS_D_SSC_P_MIN 14 | ||
305 | #define IRONLAKE_LVDS_D_SSC_P_MAX 42 | ||
306 | #define IRONLAKE_LVDS_D_SSC_P1_MIN 2 | ||
307 | #define IRONLAKE_LVDS_D_SSC_P1_MAX 6 | ||
308 | #define IRONLAKE_LVDS_D_SSC_P2_SLOW 7 | ||
309 | #define IRONLAKE_LVDS_D_SSC_P2_FAST 7 | ||
310 | |||
311 | /* DisplayPort */ | ||
312 | #define IRONLAKE_DP_N_MIN 1 | ||
313 | #define IRONLAKE_DP_N_MAX 2 | ||
314 | #define IRONLAKE_DP_M_MIN 81 | ||
315 | #define IRONLAKE_DP_M_MAX 90 | ||
316 | #define IRONLAKE_DP_P_MIN 10 | ||
317 | #define IRONLAKE_DP_P_MAX 20 | ||
318 | #define IRONLAKE_DP_P2_FAST 10 | ||
319 | #define IRONLAKE_DP_P2_SLOW 10 | ||
320 | #define IRONLAKE_DP_P2_LIMIT 0 | ||
321 | #define IRONLAKE_DP_P1_MIN 1 | ||
322 | #define IRONLAKE_DP_P1_MAX 2 | ||
272 | 323 | ||
273 | static bool | 324 | static bool |
274 | intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 325 | intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
275 | int target, int refclk, intel_clock_t *best_clock); | 326 | int target, int refclk, intel_clock_t *best_clock); |
276 | static bool | 327 | static bool |
277 | intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
278 | int target, int refclk, intel_clock_t *best_clock); | ||
279 | static bool | ||
280 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 328 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
281 | int target, int refclk, intel_clock_t *best_clock); | 329 | int target, int refclk, intel_clock_t *best_clock); |
282 | 330 | ||
@@ -299,7 +347,6 @@ static const intel_limit_t intel_limits_i8xx_dvo = { | |||
299 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 347 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
300 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, | 348 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, |
301 | .find_pll = intel_find_best_PLL, | 349 | .find_pll = intel_find_best_PLL, |
302 | .find_reduced_pll = intel_find_best_reduced_PLL, | ||
303 | }; | 350 | }; |
304 | 351 | ||
305 | static const intel_limit_t intel_limits_i8xx_lvds = { | 352 | static const intel_limit_t intel_limits_i8xx_lvds = { |
@@ -314,7 +361,6 @@ static const intel_limit_t intel_limits_i8xx_lvds = { | |||
314 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 361 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
315 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, | 362 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, |
316 | .find_pll = intel_find_best_PLL, | 363 | .find_pll = intel_find_best_PLL, |
317 | .find_reduced_pll = intel_find_best_reduced_PLL, | ||
318 | }; | 364 | }; |
319 | 365 | ||
320 | static const intel_limit_t intel_limits_i9xx_sdvo = { | 366 | static const intel_limit_t intel_limits_i9xx_sdvo = { |
@@ -329,7 +375,6 @@ static const intel_limit_t intel_limits_i9xx_sdvo = { | |||
329 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 375 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
330 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 376 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
331 | .find_pll = intel_find_best_PLL, | 377 | .find_pll = intel_find_best_PLL, |
332 | .find_reduced_pll = intel_find_best_reduced_PLL, | ||
333 | }; | 378 | }; |
334 | 379 | ||
335 | static const intel_limit_t intel_limits_i9xx_lvds = { | 380 | static const intel_limit_t intel_limits_i9xx_lvds = { |
@@ -347,7 +392,6 @@ static const intel_limit_t intel_limits_i9xx_lvds = { | |||
347 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 392 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
348 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, | 393 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, |
349 | .find_pll = intel_find_best_PLL, | 394 | .find_pll = intel_find_best_PLL, |
350 | .find_reduced_pll = intel_find_best_reduced_PLL, | ||
351 | }; | 395 | }; |
352 | 396 | ||
353 | /* below parameter and function is for G4X Chipset Family*/ | 397 | /* below parameter and function is for G4X Chipset Family*/ |
@@ -365,7 +409,6 @@ static const intel_limit_t intel_limits_g4x_sdvo = { | |||
365 | .p2_fast = G4X_P2_SDVO_FAST | 409 | .p2_fast = G4X_P2_SDVO_FAST |
366 | }, | 410 | }, |
367 | .find_pll = intel_g4x_find_best_PLL, | 411 | .find_pll = intel_g4x_find_best_PLL, |
368 | .find_reduced_pll = intel_g4x_find_best_PLL, | ||
369 | }; | 412 | }; |
370 | 413 | ||
371 | static const intel_limit_t intel_limits_g4x_hdmi = { | 414 | static const intel_limit_t intel_limits_g4x_hdmi = { |
@@ -382,7 +425,6 @@ static const intel_limit_t intel_limits_g4x_hdmi = { | |||
382 | .p2_fast = G4X_P2_HDMI_DAC_FAST | 425 | .p2_fast = G4X_P2_HDMI_DAC_FAST |
383 | }, | 426 | }, |
384 | .find_pll = intel_g4x_find_best_PLL, | 427 | .find_pll = intel_g4x_find_best_PLL, |
385 | .find_reduced_pll = intel_g4x_find_best_PLL, | ||
386 | }; | 428 | }; |
387 | 429 | ||
388 | static const intel_limit_t intel_limits_g4x_single_channel_lvds = { | 430 | static const intel_limit_t intel_limits_g4x_single_channel_lvds = { |
@@ -407,7 +449,6 @@ static const intel_limit_t intel_limits_g4x_single_channel_lvds = { | |||
407 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST | 449 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST |
408 | }, | 450 | }, |
409 | .find_pll = intel_g4x_find_best_PLL, | 451 | .find_pll = intel_g4x_find_best_PLL, |
410 | .find_reduced_pll = intel_g4x_find_best_PLL, | ||
411 | }; | 452 | }; |
412 | 453 | ||
413 | static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { | 454 | static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { |
@@ -432,7 +473,6 @@ static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { | |||
432 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST | 473 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST |
433 | }, | 474 | }, |
434 | .find_pll = intel_g4x_find_best_PLL, | 475 | .find_pll = intel_g4x_find_best_PLL, |
435 | .find_reduced_pll = intel_g4x_find_best_PLL, | ||
436 | }; | 476 | }; |
437 | 477 | ||
438 | static const intel_limit_t intel_limits_g4x_display_port = { | 478 | static const intel_limit_t intel_limits_g4x_display_port = { |
@@ -470,7 +510,6 @@ static const intel_limit_t intel_limits_pineview_sdvo = { | |||
470 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 510 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
471 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 511 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
472 | .find_pll = intel_find_best_PLL, | 512 | .find_pll = intel_find_best_PLL, |
473 | .find_reduced_pll = intel_find_best_reduced_PLL, | ||
474 | }; | 513 | }; |
475 | 514 | ||
476 | static const intel_limit_t intel_limits_pineview_lvds = { | 515 | static const intel_limit_t intel_limits_pineview_lvds = { |
@@ -486,36 +525,80 @@ static const intel_limit_t intel_limits_pineview_lvds = { | |||
486 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 525 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
487 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, | 526 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, |
488 | .find_pll = intel_find_best_PLL, | 527 | .find_pll = intel_find_best_PLL, |
489 | .find_reduced_pll = intel_find_best_reduced_PLL, | ||
490 | }; | 528 | }; |
491 | 529 | ||
492 | static const intel_limit_t intel_limits_ironlake_sdvo = { | 530 | static const intel_limit_t intel_limits_ironlake_dac = { |
531 | .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, | ||
532 | .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, | ||
533 | .n = { .min = IRONLAKE_DAC_N_MIN, .max = IRONLAKE_DAC_N_MAX }, | ||
534 | .m = { .min = IRONLAKE_DAC_M_MIN, .max = IRONLAKE_DAC_M_MAX }, | ||
535 | .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, | ||
536 | .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, | ||
537 | .p = { .min = IRONLAKE_DAC_P_MIN, .max = IRONLAKE_DAC_P_MAX }, | ||
538 | .p1 = { .min = IRONLAKE_DAC_P1_MIN, .max = IRONLAKE_DAC_P1_MAX }, | ||
539 | .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, | ||
540 | .p2_slow = IRONLAKE_DAC_P2_SLOW, | ||
541 | .p2_fast = IRONLAKE_DAC_P2_FAST }, | ||
542 | .find_pll = intel_g4x_find_best_PLL, | ||
543 | }; | ||
544 | |||
545 | static const intel_limit_t intel_limits_ironlake_single_lvds = { | ||
546 | .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, | ||
547 | .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, | ||
548 | .n = { .min = IRONLAKE_LVDS_S_N_MIN, .max = IRONLAKE_LVDS_S_N_MAX }, | ||
549 | .m = { .min = IRONLAKE_LVDS_S_M_MIN, .max = IRONLAKE_LVDS_S_M_MAX }, | ||
550 | .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, | ||
551 | .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, | ||
552 | .p = { .min = IRONLAKE_LVDS_S_P_MIN, .max = IRONLAKE_LVDS_S_P_MAX }, | ||
553 | .p1 = { .min = IRONLAKE_LVDS_S_P1_MIN, .max = IRONLAKE_LVDS_S_P1_MAX }, | ||
554 | .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, | ||
555 | .p2_slow = IRONLAKE_LVDS_S_P2_SLOW, | ||
556 | .p2_fast = IRONLAKE_LVDS_S_P2_FAST }, | ||
557 | .find_pll = intel_g4x_find_best_PLL, | ||
558 | }; | ||
559 | |||
560 | static const intel_limit_t intel_limits_ironlake_dual_lvds = { | ||
561 | .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, | ||
562 | .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, | ||
563 | .n = { .min = IRONLAKE_LVDS_D_N_MIN, .max = IRONLAKE_LVDS_D_N_MAX }, | ||
564 | .m = { .min = IRONLAKE_LVDS_D_M_MIN, .max = IRONLAKE_LVDS_D_M_MAX }, | ||
565 | .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, | ||
566 | .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, | ||
567 | .p = { .min = IRONLAKE_LVDS_D_P_MIN, .max = IRONLAKE_LVDS_D_P_MAX }, | ||
568 | .p1 = { .min = IRONLAKE_LVDS_D_P1_MIN, .max = IRONLAKE_LVDS_D_P1_MAX }, | ||
569 | .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, | ||
570 | .p2_slow = IRONLAKE_LVDS_D_P2_SLOW, | ||
571 | .p2_fast = IRONLAKE_LVDS_D_P2_FAST }, | ||
572 | .find_pll = intel_g4x_find_best_PLL, | ||
573 | }; | ||
574 | |||
575 | static const intel_limit_t intel_limits_ironlake_single_lvds_100m = { | ||
493 | .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, | 576 | .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, |
494 | .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, | 577 | .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, |
495 | .n = { .min = IRONLAKE_N_MIN, .max = IRONLAKE_N_MAX }, | 578 | .n = { .min = IRONLAKE_LVDS_S_SSC_N_MIN, .max = IRONLAKE_LVDS_S_SSC_N_MAX }, |
496 | .m = { .min = IRONLAKE_M_MIN, .max = IRONLAKE_M_MAX }, | 579 | .m = { .min = IRONLAKE_LVDS_S_SSC_M_MIN, .max = IRONLAKE_LVDS_S_SSC_M_MAX }, |
497 | .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, | 580 | .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, |
498 | .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, | 581 | .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, |
499 | .p = { .min = IRONLAKE_P_SDVO_DAC_MIN, .max = IRONLAKE_P_SDVO_DAC_MAX }, | 582 | .p = { .min = IRONLAKE_LVDS_S_SSC_P_MIN, .max = IRONLAKE_LVDS_S_SSC_P_MAX }, |
500 | .p1 = { .min = IRONLAKE_P1_MIN, .max = IRONLAKE_P1_MAX }, | 583 | .p1 = { .min = IRONLAKE_LVDS_S_SSC_P1_MIN,.max = IRONLAKE_LVDS_S_SSC_P1_MAX }, |
501 | .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, | 584 | .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, |
502 | .p2_slow = IRONLAKE_P2_SDVO_DAC_SLOW, | 585 | .p2_slow = IRONLAKE_LVDS_S_SSC_P2_SLOW, |
503 | .p2_fast = IRONLAKE_P2_SDVO_DAC_FAST }, | 586 | .p2_fast = IRONLAKE_LVDS_S_SSC_P2_FAST }, |
504 | .find_pll = intel_g4x_find_best_PLL, | 587 | .find_pll = intel_g4x_find_best_PLL, |
505 | }; | 588 | }; |
506 | 589 | ||
507 | static const intel_limit_t intel_limits_ironlake_lvds = { | 590 | static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = { |
508 | .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, | 591 | .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, |
509 | .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, | 592 | .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, |
510 | .n = { .min = IRONLAKE_N_MIN, .max = IRONLAKE_N_MAX }, | 593 | .n = { .min = IRONLAKE_LVDS_D_SSC_N_MIN, .max = IRONLAKE_LVDS_D_SSC_N_MAX }, |
511 | .m = { .min = IRONLAKE_M_MIN, .max = IRONLAKE_M_MAX }, | 594 | .m = { .min = IRONLAKE_LVDS_D_SSC_M_MIN, .max = IRONLAKE_LVDS_D_SSC_M_MAX }, |
512 | .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, | 595 | .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, |
513 | .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, | 596 | .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, |
514 | .p = { .min = IRONLAKE_P_LVDS_MIN, .max = IRONLAKE_P_LVDS_MAX }, | 597 | .p = { .min = IRONLAKE_LVDS_D_SSC_P_MIN, .max = IRONLAKE_LVDS_D_SSC_P_MAX }, |
515 | .p1 = { .min = IRONLAKE_P1_MIN, .max = IRONLAKE_P1_MAX }, | 598 | .p1 = { .min = IRONLAKE_LVDS_D_SSC_P1_MIN,.max = IRONLAKE_LVDS_D_SSC_P1_MAX }, |
516 | .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, | 599 | .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, |
517 | .p2_slow = IRONLAKE_P2_LVDS_SLOW, | 600 | .p2_slow = IRONLAKE_LVDS_D_SSC_P2_SLOW, |
518 | .p2_fast = IRONLAKE_P2_LVDS_FAST }, | 601 | .p2_fast = IRONLAKE_LVDS_D_SSC_P2_FAST }, |
519 | .find_pll = intel_g4x_find_best_PLL, | 602 | .find_pll = intel_g4x_find_best_PLL, |
520 | }; | 603 | }; |
521 | 604 | ||
@@ -524,34 +607,53 @@ static const intel_limit_t intel_limits_ironlake_display_port = { | |||
524 | .max = IRONLAKE_DOT_MAX }, | 607 | .max = IRONLAKE_DOT_MAX }, |
525 | .vco = { .min = IRONLAKE_VCO_MIN, | 608 | .vco = { .min = IRONLAKE_VCO_MIN, |
526 | .max = IRONLAKE_VCO_MAX}, | 609 | .max = IRONLAKE_VCO_MAX}, |
527 | .n = { .min = IRONLAKE_N_MIN, | 610 | .n = { .min = IRONLAKE_DP_N_MIN, |
528 | .max = IRONLAKE_N_MAX }, | 611 | .max = IRONLAKE_DP_N_MAX }, |
529 | .m = { .min = IRONLAKE_M_MIN, | 612 | .m = { .min = IRONLAKE_DP_M_MIN, |
530 | .max = IRONLAKE_M_MAX }, | 613 | .max = IRONLAKE_DP_M_MAX }, |
531 | .m1 = { .min = IRONLAKE_M1_MIN, | 614 | .m1 = { .min = IRONLAKE_M1_MIN, |
532 | .max = IRONLAKE_M1_MAX }, | 615 | .max = IRONLAKE_M1_MAX }, |
533 | .m2 = { .min = IRONLAKE_M2_MIN, | 616 | .m2 = { .min = IRONLAKE_M2_MIN, |
534 | .max = IRONLAKE_M2_MAX }, | 617 | .max = IRONLAKE_M2_MAX }, |
535 | .p = { .min = IRONLAKE_P_DISPLAY_PORT_MIN, | 618 | .p = { .min = IRONLAKE_DP_P_MIN, |
536 | .max = IRONLAKE_P_DISPLAY_PORT_MAX }, | 619 | .max = IRONLAKE_DP_P_MAX }, |
537 | .p1 = { .min = IRONLAKE_P1_DISPLAY_PORT_MIN, | 620 | .p1 = { .min = IRONLAKE_DP_P1_MIN, |
538 | .max = IRONLAKE_P1_DISPLAY_PORT_MAX}, | 621 | .max = IRONLAKE_DP_P1_MAX}, |
539 | .p2 = { .dot_limit = IRONLAKE_P2_DISPLAY_PORT_LIMIT, | 622 | .p2 = { .dot_limit = IRONLAKE_DP_P2_LIMIT, |
540 | .p2_slow = IRONLAKE_P2_DISPLAY_PORT_SLOW, | 623 | .p2_slow = IRONLAKE_DP_P2_SLOW, |
541 | .p2_fast = IRONLAKE_P2_DISPLAY_PORT_FAST }, | 624 | .p2_fast = IRONLAKE_DP_P2_FAST }, |
542 | .find_pll = intel_find_pll_ironlake_dp, | 625 | .find_pll = intel_find_pll_ironlake_dp, |
543 | }; | 626 | }; |
544 | 627 | ||
545 | static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) | 628 | static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) |
546 | { | 629 | { |
630 | struct drm_device *dev = crtc->dev; | ||
631 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
547 | const intel_limit_t *limit; | 632 | const intel_limit_t *limit; |
548 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 633 | int refclk = 120; |
549 | limit = &intel_limits_ironlake_lvds; | 634 | |
550 | else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || | 635 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { |
636 | if (dev_priv->lvds_use_ssc && dev_priv->lvds_ssc_freq == 100) | ||
637 | refclk = 100; | ||
638 | |||
639 | if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == | ||
640 | LVDS_CLKB_POWER_UP) { | ||
641 | /* LVDS dual channel */ | ||
642 | if (refclk == 100) | ||
643 | limit = &intel_limits_ironlake_dual_lvds_100m; | ||
644 | else | ||
645 | limit = &intel_limits_ironlake_dual_lvds; | ||
646 | } else { | ||
647 | if (refclk == 100) | ||
648 | limit = &intel_limits_ironlake_single_lvds_100m; | ||
649 | else | ||
650 | limit = &intel_limits_ironlake_single_lvds; | ||
651 | } | ||
652 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || | ||
551 | HAS_eDP) | 653 | HAS_eDP) |
552 | limit = &intel_limits_ironlake_display_port; | 654 | limit = &intel_limits_ironlake_display_port; |
553 | else | 655 | else |
554 | limit = &intel_limits_ironlake_sdvo; | 656 | limit = &intel_limits_ironlake_dac; |
555 | 657 | ||
556 | return limit; | 658 | return limit; |
557 | } | 659 | } |
@@ -768,46 +870,6 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
768 | return (err != target); | 870 | return (err != target); |
769 | } | 871 | } |
770 | 872 | ||
771 | |||
772 | static bool | ||
773 | intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
774 | int target, int refclk, intel_clock_t *best_clock) | ||
775 | |||
776 | { | ||
777 | struct drm_device *dev = crtc->dev; | ||
778 | intel_clock_t clock; | ||
779 | int err = target; | ||
780 | bool found = false; | ||
781 | |||
782 | memcpy(&clock, best_clock, sizeof(intel_clock_t)); | ||
783 | |||
784 | for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { | ||
785 | for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) { | ||
786 | /* m1 is always 0 in Pineview */ | ||
787 | if (clock.m2 >= clock.m1 && !IS_PINEVIEW(dev)) | ||
788 | break; | ||
789 | for (clock.n = limit->n.min; clock.n <= limit->n.max; | ||
790 | clock.n++) { | ||
791 | int this_err; | ||
792 | |||
793 | intel_clock(dev, refclk, &clock); | ||
794 | |||
795 | if (!intel_PLL_is_valid(crtc, &clock)) | ||
796 | continue; | ||
797 | |||
798 | this_err = abs(clock.dot - target); | ||
799 | if (this_err < err) { | ||
800 | *best_clock = clock; | ||
801 | err = this_err; | ||
802 | found = true; | ||
803 | } | ||
804 | } | ||
805 | } | ||
806 | } | ||
807 | |||
808 | return found; | ||
809 | } | ||
810 | |||
811 | static bool | 873 | static bool |
812 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 874 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
813 | int target, int refclk, intel_clock_t *best_clock) | 875 | int target, int refclk, intel_clock_t *best_clock) |
@@ -969,6 +1031,8 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | |||
969 | 1031 | ||
970 | /* enable it... */ | 1032 | /* enable it... */ |
971 | fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC; | 1033 | fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC; |
1034 | if (IS_I945GM(dev)) | ||
1035 | fbc_ctl |= FBC_C3_IDLE; /* 945 needs special SR handling */ | ||
972 | fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; | 1036 | fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; |
973 | fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; | 1037 | fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; |
974 | if (obj_priv->tiling_mode != I915_TILING_NONE) | 1038 | if (obj_priv->tiling_mode != I915_TILING_NONE) |
@@ -1262,7 +1326,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
1262 | return ret; | 1326 | return ret; |
1263 | } | 1327 | } |
1264 | 1328 | ||
1265 | ret = i915_gem_object_set_to_gtt_domain(obj, 1); | 1329 | ret = i915_gem_object_set_to_display_plane(obj); |
1266 | if (ret != 0) { | 1330 | if (ret != 0) { |
1267 | i915_gem_object_unpin(obj); | 1331 | i915_gem_object_unpin(obj); |
1268 | mutex_unlock(&dev->struct_mutex); | 1332 | mutex_unlock(&dev->struct_mutex); |
@@ -1693,6 +1757,7 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
1693 | case DRM_MODE_DPMS_OFF: | 1757 | case DRM_MODE_DPMS_OFF: |
1694 | DRM_DEBUG_KMS("crtc %d dpms off\n", pipe); | 1758 | DRM_DEBUG_KMS("crtc %d dpms off\n", pipe); |
1695 | 1759 | ||
1760 | drm_vblank_off(dev, pipe); | ||
1696 | /* Disable display plane */ | 1761 | /* Disable display plane */ |
1697 | temp = I915_READ(dspcntr_reg); | 1762 | temp = I915_READ(dspcntr_reg); |
1698 | if ((temp & DISPLAY_PLANE_ENABLE) != 0) { | 1763 | if ((temp & DISPLAY_PLANE_ENABLE) != 0) { |
@@ -2574,6 +2639,10 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock, | |||
2574 | sr_entries = roundup(sr_entries / cacheline_size, 1); | 2639 | sr_entries = roundup(sr_entries / cacheline_size, 1); |
2575 | DRM_DEBUG("self-refresh entries: %d\n", sr_entries); | 2640 | DRM_DEBUG("self-refresh entries: %d\n", sr_entries); |
2576 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); | 2641 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); |
2642 | } else { | ||
2643 | /* Turn off self refresh if both pipes are enabled */ | ||
2644 | I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) | ||
2645 | & ~FW_BLC_SELF_EN); | ||
2577 | } | 2646 | } |
2578 | 2647 | ||
2579 | DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n", | 2648 | DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n", |
@@ -2617,6 +2686,10 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, | |||
2617 | srwm = 1; | 2686 | srwm = 1; |
2618 | srwm &= 0x3f; | 2687 | srwm &= 0x3f; |
2619 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); | 2688 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); |
2689 | } else { | ||
2690 | /* Turn off self refresh if both pipes are enabled */ | ||
2691 | I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) | ||
2692 | & ~FW_BLC_SELF_EN); | ||
2620 | } | 2693 | } |
2621 | 2694 | ||
2622 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n", | 2695 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n", |
@@ -2685,6 +2758,10 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, | |||
2685 | if (srwm < 0) | 2758 | if (srwm < 0) |
2686 | srwm = 1; | 2759 | srwm = 1; |
2687 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f)); | 2760 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f)); |
2761 | } else { | ||
2762 | /* Turn off self refresh if both pipes are enabled */ | ||
2763 | I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) | ||
2764 | & ~FW_BLC_SELF_EN); | ||
2688 | } | 2765 | } |
2689 | 2766 | ||
2690 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", | 2767 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", |
@@ -2910,10 +2987,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
2910 | return -EINVAL; | 2987 | return -EINVAL; |
2911 | } | 2988 | } |
2912 | 2989 | ||
2913 | if (is_lvds && limit->find_reduced_pll && | 2990 | if (is_lvds && dev_priv->lvds_downclock_avail) { |
2914 | dev_priv->lvds_downclock_avail) { | 2991 | has_reduced_clock = limit->find_pll(limit, crtc, |
2915 | memcpy(&reduced_clock, &clock, sizeof(intel_clock_t)); | ||
2916 | has_reduced_clock = limit->find_reduced_pll(limit, crtc, | ||
2917 | dev_priv->lvds_downclock, | 2992 | dev_priv->lvds_downclock, |
2918 | refclk, | 2993 | refclk, |
2919 | &reduced_clock); | 2994 | &reduced_clock); |
@@ -2981,6 +3056,21 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
2981 | temp |= PIPE_8BPC; | 3056 | temp |= PIPE_8BPC; |
2982 | else | 3057 | else |
2983 | temp |= PIPE_6BPC; | 3058 | temp |= PIPE_6BPC; |
3059 | } else if (is_edp) { | ||
3060 | switch (dev_priv->edp_bpp/3) { | ||
3061 | case 8: | ||
3062 | temp |= PIPE_8BPC; | ||
3063 | break; | ||
3064 | case 10: | ||
3065 | temp |= PIPE_10BPC; | ||
3066 | break; | ||
3067 | case 6: | ||
3068 | temp |= PIPE_6BPC; | ||
3069 | break; | ||
3070 | case 12: | ||
3071 | temp |= PIPE_12BPC; | ||
3072 | break; | ||
3073 | } | ||
2984 | } else | 3074 | } else |
2985 | temp |= PIPE_8BPC; | 3075 | temp |= PIPE_8BPC; |
2986 | I915_WRITE(pipeconf_reg, temp); | 3076 | I915_WRITE(pipeconf_reg, temp); |
@@ -3991,7 +4081,8 @@ static void intel_crtc_destroy(struct drm_crtc *crtc) | |||
3991 | struct intel_unpin_work { | 4081 | struct intel_unpin_work { |
3992 | struct work_struct work; | 4082 | struct work_struct work; |
3993 | struct drm_device *dev; | 4083 | struct drm_device *dev; |
3994 | struct drm_gem_object *obj; | 4084 | struct drm_gem_object *old_fb_obj; |
4085 | struct drm_gem_object *pending_flip_obj; | ||
3995 | struct drm_pending_vblank_event *event; | 4086 | struct drm_pending_vblank_event *event; |
3996 | int pending; | 4087 | int pending; |
3997 | }; | 4088 | }; |
@@ -4002,8 +4093,9 @@ static void intel_unpin_work_fn(struct work_struct *__work) | |||
4002 | container_of(__work, struct intel_unpin_work, work); | 4093 | container_of(__work, struct intel_unpin_work, work); |
4003 | 4094 | ||
4004 | mutex_lock(&work->dev->struct_mutex); | 4095 | mutex_lock(&work->dev->struct_mutex); |
4005 | i915_gem_object_unpin(work->obj); | 4096 | i915_gem_object_unpin(work->old_fb_obj); |
4006 | drm_gem_object_unreference(work->obj); | 4097 | drm_gem_object_unreference(work->pending_flip_obj); |
4098 | drm_gem_object_unreference(work->old_fb_obj); | ||
4007 | mutex_unlock(&work->dev->struct_mutex); | 4099 | mutex_unlock(&work->dev->struct_mutex); |
4008 | kfree(work); | 4100 | kfree(work); |
4009 | } | 4101 | } |
@@ -4026,6 +4118,12 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe) | |||
4026 | spin_lock_irqsave(&dev->event_lock, flags); | 4118 | spin_lock_irqsave(&dev->event_lock, flags); |
4027 | work = intel_crtc->unpin_work; | 4119 | work = intel_crtc->unpin_work; |
4028 | if (work == NULL || !work->pending) { | 4120 | if (work == NULL || !work->pending) { |
4121 | if (work && !work->pending) { | ||
4122 | obj_priv = work->pending_flip_obj->driver_private; | ||
4123 | DRM_DEBUG_DRIVER("flip finish: %p (%d) not pending?\n", | ||
4124 | obj_priv, | ||
4125 | atomic_read(&obj_priv->pending_flip)); | ||
4126 | } | ||
4029 | spin_unlock_irqrestore(&dev->event_lock, flags); | 4127 | spin_unlock_irqrestore(&dev->event_lock, flags); |
4030 | return; | 4128 | return; |
4031 | } | 4129 | } |
@@ -4046,8 +4144,11 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe) | |||
4046 | 4144 | ||
4047 | spin_unlock_irqrestore(&dev->event_lock, flags); | 4145 | spin_unlock_irqrestore(&dev->event_lock, flags); |
4048 | 4146 | ||
4049 | obj_priv = work->obj->driver_private; | 4147 | obj_priv = work->pending_flip_obj->driver_private; |
4050 | if (atomic_dec_and_test(&obj_priv->pending_flip)) | 4148 | |
4149 | /* Initial scanout buffer will have a 0 pending flip count */ | ||
4150 | if ((atomic_read(&obj_priv->pending_flip) == 0) || | ||
4151 | atomic_dec_and_test(&obj_priv->pending_flip)) | ||
4051 | DRM_WAKEUP(&dev_priv->pending_flip_queue); | 4152 | DRM_WAKEUP(&dev_priv->pending_flip_queue); |
4052 | schedule_work(&work->work); | 4153 | schedule_work(&work->work); |
4053 | } | 4154 | } |
@@ -4060,8 +4161,11 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane) | |||
4060 | unsigned long flags; | 4161 | unsigned long flags; |
4061 | 4162 | ||
4062 | spin_lock_irqsave(&dev->event_lock, flags); | 4163 | spin_lock_irqsave(&dev->event_lock, flags); |
4063 | if (intel_crtc->unpin_work) | 4164 | if (intel_crtc->unpin_work) { |
4064 | intel_crtc->unpin_work->pending = 1; | 4165 | intel_crtc->unpin_work->pending = 1; |
4166 | } else { | ||
4167 | DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n"); | ||
4168 | } | ||
4065 | spin_unlock_irqrestore(&dev->event_lock, flags); | 4169 | spin_unlock_irqrestore(&dev->event_lock, flags); |
4066 | } | 4170 | } |
4067 | 4171 | ||
@@ -4077,7 +4181,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
4077 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 4181 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
4078 | struct intel_unpin_work *work; | 4182 | struct intel_unpin_work *work; |
4079 | unsigned long flags; | 4183 | unsigned long flags; |
4080 | int ret; | 4184 | int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC; |
4185 | int ret, pipesrc; | ||
4081 | RING_LOCALS; | 4186 | RING_LOCALS; |
4082 | 4187 | ||
4083 | work = kzalloc(sizeof *work, GFP_KERNEL); | 4188 | work = kzalloc(sizeof *work, GFP_KERNEL); |
@@ -4089,12 +4194,13 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
4089 | work->event = event; | 4194 | work->event = event; |
4090 | work->dev = crtc->dev; | 4195 | work->dev = crtc->dev; |
4091 | intel_fb = to_intel_framebuffer(crtc->fb); | 4196 | intel_fb = to_intel_framebuffer(crtc->fb); |
4092 | work->obj = intel_fb->obj; | 4197 | work->old_fb_obj = intel_fb->obj; |
4093 | INIT_WORK(&work->work, intel_unpin_work_fn); | 4198 | INIT_WORK(&work->work, intel_unpin_work_fn); |
4094 | 4199 | ||
4095 | /* We borrow the event spin lock for protecting unpin_work */ | 4200 | /* We borrow the event spin lock for protecting unpin_work */ |
4096 | spin_lock_irqsave(&dev->event_lock, flags); | 4201 | spin_lock_irqsave(&dev->event_lock, flags); |
4097 | if (intel_crtc->unpin_work) { | 4202 | if (intel_crtc->unpin_work) { |
4203 | DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); | ||
4098 | spin_unlock_irqrestore(&dev->event_lock, flags); | 4204 | spin_unlock_irqrestore(&dev->event_lock, flags); |
4099 | kfree(work); | 4205 | kfree(work); |
4100 | mutex_unlock(&dev->struct_mutex); | 4206 | mutex_unlock(&dev->struct_mutex); |
@@ -4108,19 +4214,24 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
4108 | 4214 | ||
4109 | ret = intel_pin_and_fence_fb_obj(dev, obj); | 4215 | ret = intel_pin_and_fence_fb_obj(dev, obj); |
4110 | if (ret != 0) { | 4216 | if (ret != 0) { |
4217 | DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n", | ||
4218 | obj->driver_private); | ||
4111 | kfree(work); | 4219 | kfree(work); |
4220 | intel_crtc->unpin_work = NULL; | ||
4112 | mutex_unlock(&dev->struct_mutex); | 4221 | mutex_unlock(&dev->struct_mutex); |
4113 | return ret; | 4222 | return ret; |
4114 | } | 4223 | } |
4115 | 4224 | ||
4116 | /* Reference the old fb object for the scheduled work. */ | 4225 | /* Reference the objects for the scheduled work. */ |
4117 | drm_gem_object_reference(work->obj); | 4226 | drm_gem_object_reference(work->old_fb_obj); |
4227 | drm_gem_object_reference(obj); | ||
4118 | 4228 | ||
4119 | crtc->fb = fb; | 4229 | crtc->fb = fb; |
4120 | i915_gem_object_flush_write_domain(obj); | 4230 | i915_gem_object_flush_write_domain(obj); |
4121 | drm_vblank_get(dev, intel_crtc->pipe); | 4231 | drm_vblank_get(dev, intel_crtc->pipe); |
4122 | obj_priv = obj->driver_private; | 4232 | obj_priv = obj->driver_private; |
4123 | atomic_inc(&obj_priv->pending_flip); | 4233 | atomic_inc(&obj_priv->pending_flip); |
4234 | work->pending_flip_obj = obj; | ||
4124 | 4235 | ||
4125 | BEGIN_LP_RING(4); | 4236 | BEGIN_LP_RING(4); |
4126 | OUT_RING(MI_DISPLAY_FLIP | | 4237 | OUT_RING(MI_DISPLAY_FLIP | |
@@ -4128,7 +4239,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
4128 | OUT_RING(fb->pitch); | 4239 | OUT_RING(fb->pitch); |
4129 | if (IS_I965G(dev)) { | 4240 | if (IS_I965G(dev)) { |
4130 | OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); | 4241 | OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); |
4131 | OUT_RING((fb->width << 16) | fb->height); | 4242 | pipesrc = I915_READ(pipesrc_reg); |
4243 | OUT_RING(pipesrc & 0x0fff0fff); | ||
4132 | } else { | 4244 | } else { |
4133 | OUT_RING(obj_priv->gtt_offset); | 4245 | OUT_RING(obj_priv->gtt_offset); |
4134 | OUT_RING(MI_NOOP); | 4246 | OUT_RING(MI_NOOP); |