aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorShaohua Li <shaohua.li@intel.com>2009-06-25 23:23:55 -0400
committerEric Anholt <eric@anholt.net>2009-07-01 14:16:09 -0400
commit7662c8bd6545c12ac7b2b39e4554c3ba34789c50 (patch)
treeb6bd6bc9725e355cd7e57c3183dfba99af719a5e /drivers
parent63eeaf38251183ec2b1caee11e4a2c040cb5ce6c (diff)
drm/i915: add FIFO watermark support
This patch from jbarnes and myself adds FIFO watermark control to the driver. This is needed for both power saving features on new platforms with the so-called "big FIFO" and for controlling FIFO allocation between pipes in multi-head configurations. It's also necessary infrastructure to support things like framebuffer compression and configuration supportability checks (i.e. checking a configuration against available bandwidth). Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Shaohua Li <shaohua.li@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c40
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h4
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c4
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h46
-rw-r--r--drivers/gpu/drm/i915/intel_display.c425
5 files changed, 513 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index f83364974a8a..6096600aff60 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1082,6 +1082,44 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
1082 master->driver_priv = NULL; 1082 master->driver_priv = NULL;
1083} 1083}
1084 1084
1085static void i915_get_mem_freq(struct drm_device *dev)
1086{
1087 drm_i915_private_t *dev_priv = dev->dev_private;
1088 u32 tmp;
1089
1090 if (!IS_IGD(dev))
1091 return;
1092
1093 tmp = I915_READ(CLKCFG);
1094
1095 switch (tmp & CLKCFG_FSB_MASK) {
1096 case CLKCFG_FSB_533:
1097 dev_priv->fsb_freq = 533; /* 133*4 */
1098 break;
1099 case CLKCFG_FSB_800:
1100 dev_priv->fsb_freq = 800; /* 200*4 */
1101 break;
1102 case CLKCFG_FSB_667:
1103 dev_priv->fsb_freq = 667; /* 167*4 */
1104 break;
1105 case CLKCFG_FSB_400:
1106 dev_priv->fsb_freq = 400; /* 100*4 */
1107 break;
1108 }
1109
1110 switch (tmp & CLKCFG_MEM_MASK) {
1111 case CLKCFG_MEM_533:
1112 dev_priv->mem_freq = 533;
1113 break;
1114 case CLKCFG_MEM_667:
1115 dev_priv->mem_freq = 667;
1116 break;
1117 case CLKCFG_MEM_800:
1118 dev_priv->mem_freq = 800;
1119 break;
1120 }
1121}
1122
1085/** 1123/**
1086 * i915_driver_load - setup chip and create an initial config 1124 * i915_driver_load - setup chip and create an initial config
1087 * @dev: DRM device 1125 * @dev: DRM device
@@ -1165,6 +1203,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1165 goto out_iomapfree; 1203 goto out_iomapfree;
1166 } 1204 }
1167 1205
1206 i915_get_mem_freq(dev);
1207
1168 /* On the 945G/GM, the chipset reports the MSI capability on the 1208 /* On the 945G/GM, the chipset reports the MSI capability on the
1169 * integrated graphics even though the support isn't actually there 1209 * integrated graphics even though the support isn't actually there
1170 * according to the published specs. It doesn't appear to function 1210 * according to the published specs. It doesn't appear to function
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 596e119d3e0e..47ecb617e519 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -225,6 +225,8 @@ typedef struct drm_i915_private {
225 int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ 225 int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
226 int num_fence_regs; /* 8 on pre-965, 16 otherwise */ 226 int num_fence_regs; /* 8 on pre-965, 16 otherwise */
227 227
228 unsigned int fsb_freq, mem_freq;
229
228 spinlock_t error_lock; 230 spinlock_t error_lock;
229 struct drm_i915_error_state *first_error; 231 struct drm_i915_error_state *first_error;
230 232
@@ -889,6 +891,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
889#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) 891#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev))
890#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev)) 892#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev))
891#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) 893#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev))
894/* dsparb controlled by hw only */
895#define DSPARB_HWCONTROL(dev) (IS_G4X(dev))
892 896
893#define PRIMARY_RINGBUFFER_SIZE (128*1024) 897#define PRIMARY_RINGBUFFER_SIZE (128*1024)
894 898
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 17b308592c4f..7ba23a69a0c0 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -376,11 +376,15 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
376 * Clear the PIPE(A|B)STAT regs before the IIR 376 * Clear the PIPE(A|B)STAT regs before the IIR
377 */ 377 */
378 if (pipea_stats & 0x8000ffff) { 378 if (pipea_stats & 0x8000ffff) {
379 if (pipea_stats & PIPE_FIFO_UNDERRUN_STATUS)
380 DRM_DEBUG("pipe a underrun\n");
379 I915_WRITE(PIPEASTAT, pipea_stats); 381 I915_WRITE(PIPEASTAT, pipea_stats);
380 irq_received = 1; 382 irq_received = 1;
381 } 383 }
382 384
383 if (pipeb_stats & 0x8000ffff) { 385 if (pipeb_stats & 0x8000ffff) {
386 if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS)
387 DRM_DEBUG("pipe b underrun\n");
384 I915_WRITE(PIPEBSTAT, pipeb_stats); 388 I915_WRITE(PIPEBSTAT, pipeb_stats);
385 irq_received = 1; 389 irq_received = 1;
386 } 390 }
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ad3d1b5db95e..6c0858484094 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -275,7 +275,13 @@
275#define INSTPM 0x020c0 275#define INSTPM 0x020c0
276#define ACTHD 0x020c8 276#define ACTHD 0x020c8
277#define FW_BLC 0x020d8 277#define FW_BLC 0x020d8
278#define FW_BLC2 0x020dc
278#define FW_BLC_SELF 0x020e0 /* 915+ only */ 279#define FW_BLC_SELF 0x020e0 /* 915+ only */
280#define FW_BLC_SELF_EN (1<<15)
281#define MM_BURST_LENGTH 0x00700000
282#define MM_FIFO_WATERMARK 0x0001F000
283#define LM_BURST_LENGTH 0x00000700
284#define LM_FIFO_WATERMARK 0x0000001F
279#define MI_ARB_STATE 0x020e4 /* 915+ only */ 285#define MI_ARB_STATE 0x020e4 /* 915+ only */
280#define CACHE_MODE_0 0x02120 /* 915+ only */ 286#define CACHE_MODE_0 0x02120 /* 915+ only */
281#define CM0_MASK_SHIFT 16 287#define CM0_MASK_SHIFT 16
@@ -585,17 +591,21 @@
585 591
586/* Clocking configuration register */ 592/* Clocking configuration register */
587#define CLKCFG 0x10c00 593#define CLKCFG 0x10c00
588#define CLKCFG_FSB_400 (0 << 0) /* hrawclk 100 */ 594#define CLKCFG_FSB_400 (5 << 0) /* hrawclk 100 */
589#define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */ 595#define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */
590#define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */ 596#define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */
591#define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */ 597#define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */
592#define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */ 598#define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */
593#define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */ 599#define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */
594/* this is a guess, could be 5 as well */ 600/* Note, below two are guess */
595#define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */ 601#define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */
596#define CLKCFG_FSB_1600_ALT (5 << 0) /* hrawclk 400 */ 602#define CLKCFG_FSB_1600_ALT (0 << 0) /* hrawclk 400 */
597#define CLKCFG_FSB_MASK (7 << 0) 603#define CLKCFG_FSB_MASK (7 << 0)
598 604#define CLKCFG_MEM_533 (1 << 4)
605#define CLKCFG_MEM_667 (2 << 4)
606#define CLKCFG_MEM_800 (3 << 4)
607#define CLKCFG_MEM_MASK (7 << 4)
608
599/** GM965 GM45 render standby register */ 609/** GM965 GM45 render standby register */
600#define MCHBAR_RENDER_STANDBY 0x111B8 610#define MCHBAR_RENDER_STANDBY 0x111B8
601 611
@@ -1595,6 +1605,34 @@
1595#define DSPARB_CSTART_SHIFT 7 1605#define DSPARB_CSTART_SHIFT 7
1596#define DSPARB_BSTART_MASK (0x7f) 1606#define DSPARB_BSTART_MASK (0x7f)
1597#define DSPARB_BSTART_SHIFT 0 1607#define DSPARB_BSTART_SHIFT 0
1608#define DSPARB_BEND_SHIFT 9 /* on 855 */
1609#define DSPARB_AEND_SHIFT 0
1610
1611#define DSPFW1 0x70034
1612#define DSPFW2 0x70038
1613#define DSPFW3 0x7003c
1614#define IGD_SELF_REFRESH_EN (1<<30)
1615
1616/* FIFO watermark sizes etc */
1617#define I915_FIFO_LINE_SIZE 64
1618#define I830_FIFO_LINE_SIZE 32
1619#define I945_FIFO_SIZE 127 /* 945 & 965 */
1620#define I915_FIFO_SIZE 95
1621#define I855GM_FIFO_SIZE 255
1622#define I830_FIFO_SIZE 95
1623#define I915_MAX_WM 0x3f
1624
1625#define IGD_DISPLAY_FIFO 512 /* in 64byte unit */
1626#define IGD_FIFO_LINE_SIZE 64
1627#define IGD_MAX_WM 0x1ff
1628#define IGD_DFT_WM 0x3f
1629#define IGD_DFT_HPLLOFF_WM 0
1630#define IGD_GUARD_WM 10
1631#define IGD_CURSOR_FIFO 64
1632#define IGD_CURSOR_MAX_WM 0x3f
1633#define IGD_CURSOR_DFT_WM 0
1634#define IGD_CURSOR_GUARD_WM 5
1635
1598/* 1636/*
1599 * The two pipe frame counter registers are not synchronized, so 1637 * The two pipe frame counter registers are not synchronized, so
1600 * reading a stable value is somewhat tricky. The following code 1638 * reading a stable value is somewhat tricky. The following code
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 73e7b9cecac8..a84ac05ef048 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -25,6 +25,7 @@
25 */ 25 */
26 26
27#include <linux/i2c.h> 27#include <linux/i2c.h>
28#include <linux/kernel.h>
28#include "drmP.h" 29#include "drmP.h"
29#include "intel_drv.h" 30#include "intel_drv.h"
30#include "i915_drm.h" 31#include "i915_drm.h"
@@ -34,6 +35,7 @@
34#include "drm_crtc_helper.h" 35#include "drm_crtc_helper.h"
35 36
36bool intel_pipe_has_type (struct drm_crtc *crtc, int type); 37bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
38static void intel_update_watermarks(struct drm_device *dev);
37 39
38typedef struct { 40typedef struct {
39 /* given values */ 41 /* given values */
@@ -1005,7 +1007,7 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
1005 struct drm_i915_private *dev_priv = dev->dev_private; 1007 struct drm_i915_private *dev_priv = dev->dev_private;
1006 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 1008 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1007 int pipe = intel_crtc->pipe; 1009 int pipe = intel_crtc->pipe;
1008 int plane = intel_crtc->pipe; 1010 int plane = intel_crtc->plane;
1009 int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; 1011 int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
1010 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; 1012 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
1011 int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; 1013 int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
@@ -1335,8 +1337,10 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
1335 1337
1336 /* Give the overlay scaler a chance to enable if it's on this pipe */ 1338 /* Give the overlay scaler a chance to enable if it's on this pipe */
1337 //intel_crtc_dpms_video(crtc, true); TODO 1339 //intel_crtc_dpms_video(crtc, true); TODO
1340 intel_update_watermarks(dev);
1338 break; 1341 break;
1339 case DRM_MODE_DPMS_OFF: 1342 case DRM_MODE_DPMS_OFF:
1343 intel_update_watermarks(dev);
1340 /* Give the overlay scaler a chance to disable if it's on this pipe */ 1344 /* Give the overlay scaler a chance to disable if it's on this pipe */
1341 //intel_crtc_dpms_video(crtc, FALSE); TODO 1345 //intel_crtc_dpms_video(crtc, FALSE); TODO
1342 1346
@@ -1515,7 +1519,6 @@ static int intel_get_core_clock_speed(struct drm_device *dev)
1515 return 0; /* Silence gcc warning */ 1519 return 0; /* Silence gcc warning */
1516} 1520}
1517 1521
1518
1519/** 1522/**
1520 * Return the pipe currently connected to the panel fitter, 1523 * Return the pipe currently connected to the panel fitter,
1521 * or -1 if the panel fitter is not present or not in use 1524 * or -1 if the panel fitter is not present or not in use
@@ -1585,6 +1588,420 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes,
1585} 1588}
1586 1589
1587 1590
1591struct intel_watermark_params {
1592 unsigned long fifo_size;
1593 unsigned long max_wm;
1594 unsigned long default_wm;
1595 unsigned long guard_size;
1596 unsigned long cacheline_size;
1597};
1598
1599/* IGD has different values for various configs */
1600static struct intel_watermark_params igd_display_wm = {
1601 IGD_DISPLAY_FIFO,
1602 IGD_MAX_WM,
1603 IGD_DFT_WM,
1604 IGD_GUARD_WM,
1605 IGD_FIFO_LINE_SIZE
1606};
1607static struct intel_watermark_params igd_display_hplloff_wm = {
1608 IGD_DISPLAY_FIFO,
1609 IGD_MAX_WM,
1610 IGD_DFT_HPLLOFF_WM,
1611 IGD_GUARD_WM,
1612 IGD_FIFO_LINE_SIZE
1613};
1614static struct intel_watermark_params igd_cursor_wm = {
1615 IGD_CURSOR_FIFO,
1616 IGD_CURSOR_MAX_WM,
1617 IGD_CURSOR_DFT_WM,
1618 IGD_CURSOR_GUARD_WM,
1619 IGD_FIFO_LINE_SIZE,
1620};
1621static struct intel_watermark_params igd_cursor_hplloff_wm = {
1622 IGD_CURSOR_FIFO,
1623 IGD_CURSOR_MAX_WM,
1624 IGD_CURSOR_DFT_WM,
1625 IGD_CURSOR_GUARD_WM,
1626 IGD_FIFO_LINE_SIZE
1627};
1628static struct intel_watermark_params i945_wm_info = {
1629 I915_FIFO_LINE_SIZE,
1630 I915_MAX_WM,
1631 1,
1632 0,
1633 IGD_FIFO_LINE_SIZE
1634};
1635static struct intel_watermark_params i915_wm_info = {
1636 I945_FIFO_SIZE,
1637 I915_MAX_WM,
1638 1,
1639 0,
1640 I915_FIFO_LINE_SIZE
1641};
1642static struct intel_watermark_params i855_wm_info = {
1643 I855GM_FIFO_SIZE,
1644 I915_MAX_WM,
1645 1,
1646 0,
1647 I830_FIFO_LINE_SIZE
1648};
1649static struct intel_watermark_params i830_wm_info = {
1650 I830_FIFO_SIZE,
1651 I915_MAX_WM,
1652 1,
1653 0,
1654 I830_FIFO_LINE_SIZE
1655};
1656
1657static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
1658 struct intel_watermark_params *wm,
1659 int pixel_size,
1660 unsigned long latency_ns)
1661{
1662 unsigned long bytes_required, wm_size;
1663
1664 bytes_required = (clock_in_khz * pixel_size * latency_ns) / 1000000;
1665 bytes_required /= wm->cacheline_size;
1666 wm_size = wm->fifo_size - bytes_required - wm->guard_size;
1667
1668 if (wm_size > wm->max_wm)
1669 wm_size = wm->max_wm;
1670 if (wm_size == 0)
1671 wm_size = wm->default_wm;
1672 return wm_size;
1673}
1674
1675struct cxsr_latency {
1676 int is_desktop;
1677 unsigned long fsb_freq;
1678 unsigned long mem_freq;
1679 unsigned long display_sr;
1680 unsigned long display_hpll_disable;
1681 unsigned long cursor_sr;
1682 unsigned long cursor_hpll_disable;
1683};
1684
1685static struct cxsr_latency cxsr_latency_table[] = {
1686 {1, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */
1687 {1, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */
1688 {1, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */
1689
1690 {1, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */
1691 {1, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */
1692 {1, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */
1693
1694 {1, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */
1695 {1, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */
1696 {1, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */
1697
1698 {0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */
1699 {0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */
1700 {0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */
1701
1702 {0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */
1703 {0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */
1704 {0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */
1705
1706 {0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */
1707 {0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */
1708 {0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */
1709};
1710
1711static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb,
1712 int mem)
1713{
1714 int i;
1715 struct cxsr_latency *latency;
1716
1717 if (fsb == 0 || mem == 0)
1718 return NULL;
1719
1720 for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) {
1721 latency = &cxsr_latency_table[i];
1722 if (is_desktop == latency->is_desktop &&
1723 fsb == latency->fsb_freq && mem == latency->mem_freq)
1724 break;
1725 }
1726 if (i >= ARRAY_SIZE(cxsr_latency_table)) {
1727 DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n");
1728 return NULL;
1729 }
1730 return latency;
1731}
1732
1733static void igd_disable_cxsr(struct drm_device *dev)
1734{
1735 struct drm_i915_private *dev_priv = dev->dev_private;
1736 u32 reg;
1737
1738 /* deactivate cxsr */
1739 reg = I915_READ(DSPFW3);
1740 reg &= ~(IGD_SELF_REFRESH_EN);
1741 I915_WRITE(DSPFW3, reg);
1742 DRM_INFO("Big FIFO is disabled\n");
1743}
1744
1745static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock,
1746 int pixel_size)
1747{
1748 struct drm_i915_private *dev_priv = dev->dev_private;
1749 u32 reg;
1750 unsigned long wm;
1751 struct cxsr_latency *latency;
1752
1753 latency = intel_get_cxsr_latency(IS_IGDG(dev), dev_priv->fsb_freq,
1754 dev_priv->mem_freq);
1755 if (!latency) {
1756 DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n");
1757 igd_disable_cxsr(dev);
1758 return;
1759 }
1760
1761 /* Display SR */
1762 wm = intel_calculate_wm(clock, &igd_display_wm, pixel_size,
1763 latency->display_sr);
1764 reg = I915_READ(DSPFW1);
1765 reg &= 0x7fffff;
1766 reg |= wm << 23;
1767 I915_WRITE(DSPFW1, reg);
1768 DRM_DEBUG("DSPFW1 register is %x\n", reg);
1769
1770 /* cursor SR */
1771 wm = intel_calculate_wm(clock, &igd_cursor_wm, pixel_size,
1772 latency->cursor_sr);
1773 reg = I915_READ(DSPFW3);
1774 reg &= ~(0x3f << 24);
1775 reg |= (wm & 0x3f) << 24;
1776 I915_WRITE(DSPFW3, reg);
1777
1778 /* Display HPLL off SR */
1779 wm = intel_calculate_wm(clock, &igd_display_hplloff_wm,
1780 latency->display_hpll_disable, I915_FIFO_LINE_SIZE);
1781 reg = I915_READ(DSPFW3);
1782 reg &= 0xfffffe00;
1783 reg |= wm & 0x1ff;
1784 I915_WRITE(DSPFW3, reg);
1785
1786 /* cursor HPLL off SR */
1787 wm = intel_calculate_wm(clock, &igd_cursor_hplloff_wm, pixel_size,
1788 latency->cursor_hpll_disable);
1789 reg = I915_READ(DSPFW3);
1790 reg &= ~(0x3f << 16);
1791 reg |= (wm & 0x3f) << 16;
1792 I915_WRITE(DSPFW3, reg);
1793 DRM_DEBUG("DSPFW3 register is %x\n", reg);
1794
1795 /* activate cxsr */
1796 reg = I915_READ(DSPFW3);
1797 reg |= IGD_SELF_REFRESH_EN;
1798 I915_WRITE(DSPFW3, reg);
1799
1800 DRM_INFO("Big FIFO is enabled\n");
1801
1802 return;
1803}
1804
1805const static int latency_ns = 5000; /* default for non-igd platforms */
1806
1807
1808static void i965_update_wm(struct drm_device *dev)
1809{
1810 struct drm_i915_private *dev_priv = dev->dev_private;
1811
1812 DRM_DEBUG("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR 8\n");
1813
1814 /* 965 has limitations... */
1815 I915_WRITE(DSPFW1, (8 << 16) | (8 << 8) | (8 << 0));
1816 I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
1817}
1818
1819static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
1820 int planeb_clock, int sr_hdisplay, int pixel_size)
1821{
1822 struct drm_i915_private *dev_priv = dev->dev_private;
1823 uint32_t fwater_lo = I915_READ(FW_BLC) & MM_FIFO_WATERMARK;
1824 uint32_t fwater_hi = I915_READ(FW_BLC2) & LM_FIFO_WATERMARK;
1825 int bsize, asize, cwm, bwm = 1, awm = 1, srwm = 1;
1826 uint32_t dsparb = I915_READ(DSPARB);
1827 int planea_entries, planeb_entries;
1828 struct intel_watermark_params *wm_params;
1829 unsigned long line_time_us;
1830 int sr_clock, sr_entries = 0;
1831
1832 if (IS_I965GM(dev) || IS_I945GM(dev))
1833 wm_params = &i945_wm_info;
1834 else if (IS_I9XX(dev))
1835 wm_params = &i915_wm_info;
1836 else
1837 wm_params = &i855_wm_info;
1838
1839 planea_entries = intel_calculate_wm(planea_clock, wm_params,
1840 pixel_size, latency_ns);
1841 planeb_entries = intel_calculate_wm(planeb_clock, wm_params,
1842 pixel_size, latency_ns);
1843
1844 DRM_DEBUG("FIFO entries - A: %d, B: %d\n", planea_entries,
1845 planeb_entries);
1846
1847 if (IS_I9XX(dev)) {
1848 asize = dsparb & 0x7f;
1849 bsize = (dsparb >> DSPARB_CSTART_SHIFT) & 0x7f;
1850 } else {
1851 asize = dsparb & 0x1ff;
1852 bsize = (dsparb >> DSPARB_BEND_SHIFT) & 0x1ff;
1853 }
1854 DRM_DEBUG("FIFO size - A: %d, B: %d\n", asize, bsize);
1855
1856 /* Two extra entries for padding */
1857 awm = asize - (planea_entries + 2);
1858 bwm = bsize - (planeb_entries + 2);
1859
1860 /* Sanity check against potentially bad FIFO allocations */
1861 if (awm <= 0) {
1862 /* pipe is on but has too few FIFO entries */
1863 if (planea_entries != 0)
1864 DRM_DEBUG("plane A needs more FIFO entries\n");
1865 awm = 1;
1866 }
1867 if (bwm <= 0) {
1868 if (planeb_entries != 0)
1869 DRM_DEBUG("plane B needs more FIFO entries\n");
1870 bwm = 1;
1871 }
1872
1873 /*
1874 * Overlay gets an aggressive default since video jitter is bad.
1875 */
1876 cwm = 2;
1877
1878 /* Calc sr entries for one pipe configs */
1879 if (!planea_clock || !planeb_clock) {
1880 sr_clock = planea_clock ? planea_clock : planeb_clock;
1881 line_time_us = (sr_hdisplay * 1000) / sr_clock;
1882 sr_entries = (((latency_ns / line_time_us) + 1) * pixel_size *
1883 sr_hdisplay) / 1000;
1884 sr_entries = roundup(sr_entries / wm_params->cacheline_size, 1);
1885 if (sr_entries < wm_params->fifo_size)
1886 srwm = wm_params->fifo_size - sr_entries;
1887 }
1888
1889 DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
1890 awm, bwm, cwm, srwm);
1891
1892 fwater_lo = fwater_lo | ((bwm & 0x3f) << 16) | (awm & 0x3f);
1893 fwater_hi = fwater_hi | (cwm & 0x1f);
1894
1895 I915_WRITE(FW_BLC, fwater_lo);
1896 I915_WRITE(FW_BLC2, fwater_hi);
1897 if (IS_I9XX(dev))
1898 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f));
1899}
1900
1901static void i830_update_wm(struct drm_device *dev, int planea_clock,
1902 int pixel_size)
1903{
1904 struct drm_i915_private *dev_priv = dev->dev_private;
1905 uint32_t dsparb = I915_READ(DSPARB);
1906 uint32_t fwater_lo = I915_READ(FW_BLC) & MM_FIFO_WATERMARK;
1907 unsigned int asize, awm;
1908 int planea_entries;
1909
1910 planea_entries = intel_calculate_wm(planea_clock, &i830_wm_info,
1911 pixel_size, latency_ns);
1912
1913 asize = dsparb & 0x7f;
1914
1915 awm = asize - planea_entries;
1916
1917 fwater_lo = fwater_lo | awm;
1918
1919 I915_WRITE(FW_BLC, fwater_lo);
1920}
1921
1922/**
1923 * intel_update_watermarks - update FIFO watermark values based on current modes
1924 *
1925 * Calculate watermark values for the various WM regs based on current mode
1926 * and plane configuration.
1927 *
1928 * There are several cases to deal with here:
1929 * - normal (i.e. non-self-refresh)
1930 * - self-refresh (SR) mode
1931 * - lines are large relative to FIFO size (buffer can hold up to 2)
1932 * - lines are small relative to FIFO size (buffer can hold more than 2
1933 * lines), so need to account for TLB latency
1934 *
1935 * The normal calculation is:
1936 * watermark = dotclock * bytes per pixel * latency
1937 * where latency is platform & configuration dependent (we assume pessimal
1938 * values here).
1939 *
1940 * The SR calculation is:
1941 * watermark = (trunc(latency/line time)+1) * surface width *
1942 * bytes per pixel
1943 * where
1944 * line time = htotal / dotclock
1945 * and latency is assumed to be high, as above.
1946 *
1947 * The final value programmed to the register should always be rounded up,
1948 * and include an extra 2 entries to account for clock crossings.
1949 *
1950 * We don't use the sprite, so we can ignore that. And on Crestline we have
1951 * to set the non-SR watermarks to 8.
1952 */
1953static void intel_update_watermarks(struct drm_device *dev)
1954{
1955 struct drm_crtc *crtc;
1956 struct intel_crtc *intel_crtc;
1957 int sr_hdisplay = 0;
1958 unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0;
1959 int enabled = 0, pixel_size = 0;
1960
1961 if (DSPARB_HWCONTROL(dev))
1962 return;
1963
1964 /* Get the clock config from both planes */
1965 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1966 intel_crtc = to_intel_crtc(crtc);
1967 if (crtc->enabled) {
1968 enabled++;
1969 if (intel_crtc->plane == 0) {
1970 DRM_DEBUG("plane A (pipe %d) clock: %d\n",
1971 intel_crtc->pipe, crtc->mode.clock);
1972 planea_clock = crtc->mode.clock;
1973 } else {
1974 DRM_DEBUG("plane B (pipe %d) clock: %d\n",
1975 intel_crtc->pipe, crtc->mode.clock);
1976 planeb_clock = crtc->mode.clock;
1977 }
1978 sr_hdisplay = crtc->mode.hdisplay;
1979 sr_clock = crtc->mode.clock;
1980 if (crtc->fb)
1981 pixel_size = crtc->fb->bits_per_pixel / 8;
1982 else
1983 pixel_size = 4; /* by default */
1984 }
1985 }
1986
1987 if (enabled <= 0)
1988 return;
1989
1990 /* Single pipe configs can enable self refresh */
1991 if (enabled == 1 && IS_IGD(dev))
1992 igd_enable_cxsr(dev, sr_clock, pixel_size);
1993 else if (IS_IGD(dev))
1994 igd_disable_cxsr(dev);
1995
1996 if (IS_I965G(dev))
1997 i965_update_wm(dev);
1998 else if (IS_I9XX(dev) || IS_MOBILE(dev))
1999 i9xx_update_wm(dev, planea_clock, planeb_clock, sr_hdisplay,
2000 pixel_size);
2001 else
2002 i830_update_wm(dev, planea_clock, pixel_size);
2003}
2004
1588static int intel_crtc_mode_set(struct drm_crtc *crtc, 2005static int intel_crtc_mode_set(struct drm_crtc *crtc,
1589 struct drm_display_mode *mode, 2006 struct drm_display_mode *mode,
1590 struct drm_display_mode *adjusted_mode, 2007 struct drm_display_mode *adjusted_mode,
@@ -1951,6 +2368,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
1951 2368
1952 /* Flush the plane changes */ 2369 /* Flush the plane changes */
1953 ret = intel_pipe_set_base(crtc, x, y, old_fb); 2370 ret = intel_pipe_set_base(crtc, x, y, old_fb);
2371
2372 intel_update_watermarks(dev);
2373
1954 drm_vblank_post_modeset(dev, pipe); 2374 drm_vblank_post_modeset(dev, pipe);
1955 2375
1956 return ret; 2376 return ret;
@@ -2439,6 +2859,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
2439 2859
2440 drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); 2860 drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
2441 intel_crtc->pipe = pipe; 2861 intel_crtc->pipe = pipe;
2862 intel_crtc->plane = pipe;
2442 for (i = 0; i < 256; i++) { 2863 for (i = 0; i < 256; i++) {
2443 intel_crtc->lut_r[i] = i; 2864 intel_crtc->lut_r[i] = i;
2444 intel_crtc->lut_g[i] = i; 2865 intel_crtc->lut_g[i] = i;