diff options
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 119 |
1 files changed, 107 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d7bb61efca2d..a4c3c5497941 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -2270,6 +2270,104 @@ static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params, | |||
2270 | params->pri_bytes_per_pixel); | 2270 | params->pri_bytes_per_pixel); |
2271 | } | 2271 | } |
2272 | 2272 | ||
2273 | static unsigned int ilk_display_fifo_size(const struct drm_device *dev) | ||
2274 | { | ||
2275 | if (INTEL_INFO(dev)->gen >= 7) | ||
2276 | return 768; | ||
2277 | else | ||
2278 | return 512; | ||
2279 | } | ||
2280 | |||
2281 | /* Calculate the maximum primary/sprite plane watermark */ | ||
2282 | static unsigned int ilk_plane_wm_max(const struct drm_device *dev, | ||
2283 | int level, | ||
2284 | unsigned int num_pipes_active, | ||
2285 | bool sprite_enabled, | ||
2286 | enum intel_ddb_partitioning ddb_partitioning, | ||
2287 | bool is_sprite) | ||
2288 | { | ||
2289 | unsigned int fifo_size = ilk_display_fifo_size(dev); | ||
2290 | unsigned int max; | ||
2291 | |||
2292 | /* if sprites aren't enabled, sprites get nothing */ | ||
2293 | if (is_sprite && !sprite_enabled) | ||
2294 | return 0; | ||
2295 | |||
2296 | /* HSW allows LP1+ watermarks even with multiple pipes */ | ||
2297 | if (level == 0 || num_pipes_active > 1) { | ||
2298 | fifo_size /= INTEL_INFO(dev)->num_pipes; | ||
2299 | |||
2300 | /* | ||
2301 | * For some reason the non self refresh | ||
2302 | * FIFO size is only half of the self | ||
2303 | * refresh FIFO size on ILK/SNB. | ||
2304 | */ | ||
2305 | if (INTEL_INFO(dev)->gen <= 6) | ||
2306 | fifo_size /= 2; | ||
2307 | } | ||
2308 | |||
2309 | if (sprite_enabled) { | ||
2310 | /* level 0 is always calculated with 1:1 split */ | ||
2311 | if (level > 0 && ddb_partitioning == INTEL_DDB_PART_5_6) { | ||
2312 | if (is_sprite) | ||
2313 | fifo_size *= 5; | ||
2314 | fifo_size /= 6; | ||
2315 | } else { | ||
2316 | fifo_size /= 2; | ||
2317 | } | ||
2318 | } | ||
2319 | |||
2320 | /* clamp to max that the registers can hold */ | ||
2321 | if (INTEL_INFO(dev)->gen >= 7) | ||
2322 | /* IVB/HSW primary/sprite plane watermarks */ | ||
2323 | max = level == 0 ? 127 : 1023; | ||
2324 | else if (!is_sprite) | ||
2325 | /* ILK/SNB primary plane watermarks */ | ||
2326 | max = level == 0 ? 127 : 511; | ||
2327 | else | ||
2328 | /* ILK/SNB sprite plane watermarks */ | ||
2329 | max = level == 0 ? 63 : 255; | ||
2330 | |||
2331 | return min(fifo_size, max); | ||
2332 | } | ||
2333 | |||
2334 | /* Calculate the maximum cursor plane watermark */ | ||
2335 | static unsigned int ilk_cursor_wm_max(const struct drm_device *dev, | ||
2336 | int level, unsigned int num_pipes_active) | ||
2337 | { | ||
2338 | /* HSW LP1+ watermarks w/ multiple pipes */ | ||
2339 | if (level > 0 && num_pipes_active > 1) | ||
2340 | return 64; | ||
2341 | |||
2342 | /* otherwise just report max that registers can hold */ | ||
2343 | if (INTEL_INFO(dev)->gen >= 7) | ||
2344 | return level == 0 ? 63 : 255; | ||
2345 | else | ||
2346 | return level == 0 ? 31 : 63; | ||
2347 | } | ||
2348 | |||
2349 | /* Calculate the maximum FBC watermark */ | ||
2350 | static unsigned int ilk_fbc_wm_max(void) | ||
2351 | { | ||
2352 | /* max that registers can hold */ | ||
2353 | return 15; | ||
2354 | } | ||
2355 | |||
2356 | static void ilk_wm_max(struct drm_device *dev, | ||
2357 | int level, | ||
2358 | unsigned int num_pipes_active, | ||
2359 | bool sprite_enabled, | ||
2360 | enum intel_ddb_partitioning ddb_partitioning, | ||
2361 | struct hsw_wm_maximums *max) | ||
2362 | { | ||
2363 | max->pri = ilk_plane_wm_max(dev, level, num_pipes_active, | ||
2364 | sprite_enabled, ddb_partitioning, false); | ||
2365 | max->spr = ilk_plane_wm_max(dev, level, num_pipes_active, | ||
2366 | sprite_enabled, ddb_partitioning, true); | ||
2367 | max->cur = ilk_cursor_wm_max(dev, level, num_pipes_active); | ||
2368 | max->fbc = ilk_fbc_wm_max(); | ||
2369 | } | ||
2370 | |||
2273 | static bool ilk_check_wm(int level, | 2371 | static bool ilk_check_wm(int level, |
2274 | const struct hsw_wm_maximums *max, | 2372 | const struct hsw_wm_maximums *max, |
2275 | struct intel_wm_level *result) | 2373 | struct intel_wm_level *result) |
@@ -2555,18 +2653,15 @@ static void hsw_compute_wm_parameters(struct drm_device *dev, | |||
2555 | sprites_enabled++; | 2653 | sprites_enabled++; |
2556 | } | 2654 | } |
2557 | 2655 | ||
2558 | if (pipes_active > 1) { | 2656 | ilk_wm_max(dev, 1, pipes_active, sprites_enabled, |
2559 | lp_max_1_2->pri = lp_max_5_6->pri = sprites_enabled ? 128 : 256; | 2657 | INTEL_DDB_PART_1_2, lp_max_1_2); |
2560 | lp_max_1_2->spr = lp_max_5_6->spr = 128; | 2658 | |
2561 | lp_max_1_2->cur = lp_max_5_6->cur = 64; | 2659 | /* 5/6 split only in single pipe config on IVB+ */ |
2562 | } else { | 2660 | if (INTEL_INFO(dev)->gen >= 7 && pipes_active <= 1) |
2563 | lp_max_1_2->pri = sprites_enabled ? 384 : 768; | 2661 | ilk_wm_max(dev, 1, pipes_active, sprites_enabled, |
2564 | lp_max_5_6->pri = sprites_enabled ? 128 : 768; | 2662 | INTEL_DDB_PART_5_6, lp_max_5_6); |
2565 | lp_max_1_2->spr = 384; | 2663 | else |
2566 | lp_max_5_6->spr = 640; | 2664 | *lp_max_5_6 = *lp_max_1_2; |
2567 | lp_max_1_2->cur = lp_max_5_6->cur = 255; | ||
2568 | } | ||
2569 | lp_max_1_2->fbc = lp_max_5_6->fbc = 15; | ||
2570 | } | 2665 | } |
2571 | 2666 | ||
2572 | static void hsw_compute_wm_results(struct drm_device *dev, | 2667 | static void hsw_compute_wm_results(struct drm_device *dev, |