aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2009-10-18 21:09:33 -0400
committerEric Anholt <eric@anholt.net>2009-10-23 14:31:08 -0400
commit0e442c60dd39ac6924b11a20497734bd2303744c (patch)
treec10ec9cbb7b5c408189c6490064140435aa190d8 /drivers
parentd54e9d28241fd52cca3df4f6bc2054a30d453fed (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.h12
-rw-r--r--drivers/gpu/drm/i915/intel_display.c80
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};
2146static 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};
2146static struct intel_watermark_params i945_wm_info = { 2153static 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
2436static void g4x_update_wm(struct drm_device *dev, int unused, int unused2, 2443static 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
2449static void i965_update_wm(struct drm_device *dev, int unused, int unused2, 2513static void i965_update_wm(struct drm_device *dev, int unused, int unused2,