diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 40 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 425 |
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 | ||
1085 | static 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 | ||
36 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type); | 37 | bool intel_pipe_has_type (struct drm_crtc *crtc, int type); |
38 | static void intel_update_watermarks(struct drm_device *dev); | ||
37 | 39 | ||
38 | typedef struct { | 40 | typedef 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 | ||
1591 | struct 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 */ | ||
1600 | static 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 | }; | ||
1607 | static 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 | }; | ||
1614 | static 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 | }; | ||
1621 | static 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 | }; | ||
1628 | static 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 | }; | ||
1635 | static 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 | }; | ||
1642 | static 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 | }; | ||
1649 | static 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 | |||
1657 | static 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 | |||
1675 | struct 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 | |||
1685 | static 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 | |||
1711 | static 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 | |||
1733 | static 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 | |||
1745 | static 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 | |||
1805 | const static int latency_ns = 5000; /* default for non-igd platforms */ | ||
1806 | |||
1807 | |||
1808 | static 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 | |||
1819 | static 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 | |||
1901 | static 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 | */ | ||
1953 | static 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 | |||
1588 | static int intel_crtc_mode_set(struct drm_crtc *crtc, | 2005 | static 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; |