diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-10-18 21:09:33 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-10-23 14:31:08 -0400 |
commit | 0e442c60dd39ac6924b11a20497734bd2303744c (patch) | |
tree | c10ec9cbb7b5c408189c6490064140435aa190d8 /drivers | |
parent | d54e9d28241fd52cca3df4f6bc2054a30d453fed (diff) |
drm/i915: add FIFO watermark support for G4x
Turns out G4x needs to have sensible watermarks set, especially for
self-refresh enabled modes. Add support for it.
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Tested-by: Dirk Hohndel <hohndel@infradead.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 80 |
2 files changed, 84 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 78f336e00836..1687edf68795 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -1799,17 +1799,29 @@ | |||
1799 | #define DSPARB_AEND_SHIFT 0 | 1799 | #define DSPARB_AEND_SHIFT 0 |
1800 | 1800 | ||
1801 | #define DSPFW1 0x70034 | 1801 | #define DSPFW1 0x70034 |
1802 | #define DSPFW_SR_SHIFT 23 | ||
1803 | #define DSPFW_CURSORB_SHIFT 16 | ||
1804 | #define DSPFW_PLANEB_SHIFT 8 | ||
1802 | #define DSPFW2 0x70038 | 1805 | #define DSPFW2 0x70038 |
1806 | #define DSPFW_CURSORA_MASK 0x00003f00 | ||
1807 | #define DSPFW_CURSORA_SHIFT 16 | ||
1803 | #define DSPFW3 0x7003c | 1808 | #define DSPFW3 0x7003c |
1809 | #define DSPFW_HPLL_SR_EN (1<<31) | ||
1810 | #define DSPFW_CURSOR_SR_SHIFT 24 | ||
1804 | #define IGD_SELF_REFRESH_EN (1<<30) | 1811 | #define IGD_SELF_REFRESH_EN (1<<30) |
1805 | 1812 | ||
1806 | /* FIFO watermark sizes etc */ | 1813 | /* FIFO watermark sizes etc */ |
1814 | #define G4X_FIFO_LINE_SIZE 64 | ||
1807 | #define I915_FIFO_LINE_SIZE 64 | 1815 | #define I915_FIFO_LINE_SIZE 64 |
1808 | #define I830_FIFO_LINE_SIZE 32 | 1816 | #define I830_FIFO_LINE_SIZE 32 |
1817 | |||
1818 | #define G4X_FIFO_SIZE 127 | ||
1809 | #define I945_FIFO_SIZE 127 /* 945 & 965 */ | 1819 | #define I945_FIFO_SIZE 127 /* 945 & 965 */ |
1810 | #define I915_FIFO_SIZE 95 | 1820 | #define I915_FIFO_SIZE 95 |
1811 | #define I855GM_FIFO_SIZE 127 /* In cachelines */ | 1821 | #define I855GM_FIFO_SIZE 127 /* In cachelines */ |
1812 | #define I830_FIFO_SIZE 95 | 1822 | #define I830_FIFO_SIZE 95 |
1823 | |||
1824 | #define G4X_MAX_WM 0x3f | ||
1813 | #define I915_MAX_WM 0x3f | 1825 | #define I915_MAX_WM 0x3f |
1814 | 1826 | ||
1815 | #define IGD_DISPLAY_FIFO 512 /* in 64byte unit */ | 1827 | #define IGD_DISPLAY_FIFO 512 /* in 64byte unit */ |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e189fd6dedcf..47d6ff058991 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -2143,6 +2143,13 @@ static struct intel_watermark_params igd_cursor_hplloff_wm = { | |||
2143 | IGD_CURSOR_GUARD_WM, | 2143 | IGD_CURSOR_GUARD_WM, |
2144 | IGD_FIFO_LINE_SIZE | 2144 | IGD_FIFO_LINE_SIZE |
2145 | }; | 2145 | }; |
2146 | static struct intel_watermark_params g4x_wm_info = { | ||
2147 | G4X_FIFO_SIZE, | ||
2148 | G4X_MAX_WM, | ||
2149 | G4X_MAX_WM, | ||
2150 | 2, | ||
2151 | G4X_FIFO_LINE_SIZE, | ||
2152 | }; | ||
2146 | static struct intel_watermark_params i945_wm_info = { | 2153 | static struct intel_watermark_params i945_wm_info = { |
2147 | I945_FIFO_SIZE, | 2154 | I945_FIFO_SIZE, |
2148 | I915_MAX_WM, | 2155 | I915_MAX_WM, |
@@ -2433,17 +2440,74 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane) | |||
2433 | return size; | 2440 | return size; |
2434 | } | 2441 | } |
2435 | 2442 | ||
2436 | static void g4x_update_wm(struct drm_device *dev, int unused, int unused2, | 2443 | static void g4x_update_wm(struct drm_device *dev, int planea_clock, |
2437 | int unused3, int unused4) | 2444 | int planeb_clock, int sr_hdisplay, int pixel_size) |
2438 | { | 2445 | { |
2439 | struct drm_i915_private *dev_priv = dev->dev_private; | 2446 | struct drm_i915_private *dev_priv = dev->dev_private; |
2440 | u32 fw_blc_self = I915_READ(FW_BLC_SELF); | 2447 | int total_size, cacheline_size; |
2448 | int planea_wm, planeb_wm, cursora_wm, cursorb_wm, cursor_sr; | ||
2449 | struct intel_watermark_params planea_params, planeb_params; | ||
2450 | unsigned long line_time_us; | ||
2451 | int sr_clock, sr_entries = 0, entries_required; | ||
2441 | 2452 | ||
2442 | if (i915_powersave) | 2453 | /* Create copies of the base settings for each pipe */ |
2443 | fw_blc_self |= FW_BLC_SELF_EN; | 2454 | planea_params = planeb_params = g4x_wm_info; |
2444 | else | 2455 | |
2445 | fw_blc_self &= ~FW_BLC_SELF_EN; | 2456 | /* Grab a couple of global values before we overwrite them */ |
2446 | I915_WRITE(FW_BLC_SELF, fw_blc_self); | 2457 | total_size = planea_params.fifo_size; |
2458 | cacheline_size = planea_params.cacheline_size; | ||
2459 | |||
2460 | /* | ||
2461 | * Note: we need to make sure we don't overflow for various clock & | ||
2462 | * latency values. | ||
2463 | * clocks go from a few thousand to several hundred thousand. | ||
2464 | * latency is usually a few thousand | ||
2465 | */ | ||
2466 | entries_required = ((planea_clock / 1000) * pixel_size * latency_ns) / | ||
2467 | 1000; | ||
2468 | entries_required /= G4X_FIFO_LINE_SIZE; | ||
2469 | planea_wm = entries_required + planea_params.guard_size; | ||
2470 | |||
2471 | entries_required = ((planeb_clock / 1000) * pixel_size * latency_ns) / | ||
2472 | 1000; | ||
2473 | entries_required /= G4X_FIFO_LINE_SIZE; | ||
2474 | planeb_wm = entries_required + planeb_params.guard_size; | ||
2475 | |||
2476 | cursora_wm = cursorb_wm = 16; | ||
2477 | cursor_sr = 32; | ||
2478 | |||
2479 | DRM_DEBUG("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); | ||
2480 | |||
2481 | /* Calc sr entries for one plane configs */ | ||
2482 | if (sr_hdisplay && (!planea_clock || !planeb_clock)) { | ||
2483 | /* self-refresh has much higher latency */ | ||
2484 | const static int sr_latency_ns = 12000; | ||
2485 | |||
2486 | sr_clock = planea_clock ? planea_clock : planeb_clock; | ||
2487 | line_time_us = ((sr_hdisplay * 1000) / sr_clock); | ||
2488 | |||
2489 | /* Use ns/us then divide to preserve precision */ | ||
2490 | sr_entries = (((sr_latency_ns / line_time_us) + 1) * | ||
2491 | pixel_size * sr_hdisplay) / 1000; | ||
2492 | sr_entries = roundup(sr_entries / cacheline_size, 1); | ||
2493 | DRM_DEBUG("self-refresh entries: %d\n", sr_entries); | ||
2494 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); | ||
2495 | } | ||
2496 | |||
2497 | DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n", | ||
2498 | planea_wm, planeb_wm, sr_entries); | ||
2499 | |||
2500 | planea_wm &= 0x3f; | ||
2501 | planeb_wm &= 0x3f; | ||
2502 | |||
2503 | I915_WRITE(DSPFW1, (sr_entries << DSPFW_SR_SHIFT) | | ||
2504 | (cursorb_wm << DSPFW_CURSORB_SHIFT) | | ||
2505 | (planeb_wm << DSPFW_PLANEB_SHIFT) | planea_wm); | ||
2506 | I915_WRITE(DSPFW2, (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) | | ||
2507 | (cursora_wm << DSPFW_CURSORA_SHIFT)); | ||
2508 | /* HPLL off in SR has some issues on G4x... disable it */ | ||
2509 | I915_WRITE(DSPFW3, (I915_READ(DSPFW3) & ~DSPFW_HPLL_SR_EN) | | ||
2510 | (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); | ||
2447 | } | 2511 | } |
2448 | 2512 | ||
2449 | static void i965_update_wm(struct drm_device *dev, int unused, int unused2, | 2513 | static void i965_update_wm(struct drm_device *dev, int unused, int unused2, |