aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_pm.c
diff options
context:
space:
mode:
authorPaulo Zanoni <paulo.r.zanoni@intel.com>2013-05-31 09:19:21 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-05-31 14:54:14 -0400
commit861f3389c6627460bcd19d1442eb650001f15c9b (patch)
treefb2be86c06a1e89467d336c0a4620477b7af095d /drivers/gpu/drm/i915/intel_pm.c
parentcca32e9ad372172c808b93eebff536459ce37d85 (diff)
drm/i915: add support for 5/6 data buffer partitioning on Haswell
Now we compute the results for both 1/2 and 5/6 partitioning and then use hsw_find_best_result to choose which one to use. With this patch, Haswell watermarks support should be in good shape. The only improvement we're missing is the case where the primary plane is disabled: we always assume it's enabled, so we take it into consideration when calculating the watermarks. v2: - Check the latency when finding the best result Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c64
1 files changed, 53 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 1373552732e6..b676b578f70f 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2335,7 +2335,8 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
2335static void hsw_compute_wm_parameters(struct drm_device *dev, 2335static void hsw_compute_wm_parameters(struct drm_device *dev,
2336 struct hsw_pipe_wm_parameters *params, 2336 struct hsw_pipe_wm_parameters *params,
2337 uint32_t *wm, 2337 uint32_t *wm,
2338 struct hsw_wm_maximums *lp_max_1_2) 2338 struct hsw_wm_maximums *lp_max_1_2,
2339 struct hsw_wm_maximums *lp_max_5_6)
2339{ 2340{
2340 struct drm_i915_private *dev_priv = dev->dev_private; 2341 struct drm_i915_private *dev_priv = dev->dev_private;
2341 struct drm_crtc *crtc; 2342 struct drm_crtc *crtc;
@@ -2391,15 +2392,17 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
2391 } 2392 }
2392 2393
2393 if (pipes_active > 1) { 2394 if (pipes_active > 1) {
2394 lp_max_1_2->pri = sprites_enabled ? 128 : 256; 2395 lp_max_1_2->pri = lp_max_5_6->pri = sprites_enabled ? 128 : 256;
2395 lp_max_1_2->spr = 128; 2396 lp_max_1_2->spr = lp_max_5_6->spr = 128;
2396 lp_max_1_2->cur = 64; 2397 lp_max_1_2->cur = lp_max_5_6->cur = 64;
2397 } else { 2398 } else {
2398 lp_max_1_2->pri = sprites_enabled ? 384 : 768; 2399 lp_max_1_2->pri = sprites_enabled ? 384 : 768;
2400 lp_max_5_6->pri = sprites_enabled ? 128 : 768;
2399 lp_max_1_2->spr = 384; 2401 lp_max_1_2->spr = 384;
2400 lp_max_1_2->cur = 255; 2402 lp_max_5_6->spr = 640;
2403 lp_max_1_2->cur = lp_max_5_6->cur = 255;
2401 } 2404 }
2402 lp_max_1_2->fbc = 15; 2405 lp_max_1_2->fbc = lp_max_5_6->fbc = 15;
2403} 2406}
2404 2407
2405static void hsw_compute_wm_results(struct drm_device *dev, 2408static void hsw_compute_wm_results(struct drm_device *dev,
@@ -2457,6 +2460,32 @@ static void hsw_compute_wm_results(struct drm_device *dev,
2457 } 2460 }
2458} 2461}
2459 2462
2463/* Find the result with the highest level enabled. Check for enable_fbc_wm in
2464 * case both are at the same level. Prefer r1 in case they're the same. */
2465struct hsw_wm_values *hsw_find_best_result(struct hsw_wm_values *r1,
2466 struct hsw_wm_values *r2)
2467{
2468 int i, val_r1 = 0, val_r2 = 0;
2469
2470 for (i = 0; i < 3; i++) {
2471 if (r1->wm_lp[i] & WM3_LP_EN)
2472 val_r1 = r1->wm_lp[i] & WM1_LP_LATENCY_MASK;
2473 if (r2->wm_lp[i] & WM3_LP_EN)
2474 val_r2 = r2->wm_lp[i] & WM1_LP_LATENCY_MASK;
2475 }
2476
2477 if (val_r1 == val_r2) {
2478 if (r2->enable_fbc_wm && !r1->enable_fbc_wm)
2479 return r2;
2480 else
2481 return r1;
2482 } else if (val_r1 > val_r2) {
2483 return r1;
2484 } else {
2485 return r2;
2486 }
2487}
2488
2460/* 2489/*
2461 * The spec says we shouldn't write when we don't need, because every write 2490 * The spec says we shouldn't write when we don't need, because every write
2462 * causes WMs to be re-evaluated, expending some power. 2491 * causes WMs to be re-evaluated, expending some power.
@@ -2557,14 +2586,27 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
2557static void haswell_update_wm(struct drm_device *dev) 2586static void haswell_update_wm(struct drm_device *dev)
2558{ 2587{
2559 struct drm_i915_private *dev_priv = dev->dev_private; 2588 struct drm_i915_private *dev_priv = dev->dev_private;
2560 struct hsw_wm_maximums lp_max_1_2; 2589 struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
2561 struct hsw_pipe_wm_parameters params[3]; 2590 struct hsw_pipe_wm_parameters params[3];
2562 struct hsw_wm_values results; 2591 struct hsw_wm_values results_1_2, results_5_6, *best_results;
2563 uint32_t wm[5]; 2592 uint32_t wm[5];
2593 enum hsw_data_buf_partitioning partitioning;
2594
2595 hsw_compute_wm_parameters(dev, params, wm, &lp_max_1_2, &lp_max_5_6);
2596
2597 hsw_compute_wm_results(dev, params, wm, &lp_max_1_2, &results_1_2);
2598 if (lp_max_1_2.pri != lp_max_5_6.pri) {
2599 hsw_compute_wm_results(dev, params, wm, &lp_max_5_6,
2600 &results_5_6);
2601 best_results = hsw_find_best_result(&results_1_2, &results_5_6);
2602 } else {
2603 best_results = &results_1_2;
2604 }
2605
2606 partitioning = (best_results == &results_1_2) ?
2607 HSW_DATA_BUF_PART_1_2 : HSW_DATA_BUF_PART_5_6;
2564 2608
2565 hsw_compute_wm_parameters(dev, params, wm, &lp_max_1_2); 2609 hsw_write_wm_values(dev_priv, best_results, partitioning);
2566 hsw_compute_wm_results(dev, params, wm, &lp_max_1_2, &results);
2567 hsw_write_wm_values(dev_priv, &results, HSW_DATA_BUF_PART_1_2);
2568} 2610}
2569 2611
2570static void haswell_update_sprite_wm(struct drm_device *dev, int pipe, 2612static void haswell_update_sprite_wm(struct drm_device *dev, int pipe,