aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2010-05-20 17:28:11 -0400
committerEric Anholt <eric@anholt.net>2010-05-26 17:10:01 -0400
commit7648fa99eb77a2e1a90b7beaa420e07d819b9c11 (patch)
tree29991eba782a22922441813dcc3a5cbde8377119 /drivers
parent7a772c492fcfffae812ffca78a628e76fa57fe58 (diff)
drm/i915: add power monitoring support
Add power monitoring support to the i915 driver for use by the IPS driver. Export the available power info to the IPS driver through a few new inter-driver hooks. When used together, the IPS driver and this patch can significantly increase graphics performance on Ironlake class chips. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> [anholt: Fixed 32-bit compile. stupid obfuscating div_u64()] Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c56
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c533
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h20
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c28
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h41
-rw-r--r--drivers/gpu/drm/i915/intel_display.c147
6 files changed, 772 insertions, 53 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index c864858d5064..eb11e1e049cb 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -491,11 +491,14 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
491 struct drm_device *dev = node->minor->dev; 491 struct drm_device *dev = node->minor->dev;
492 drm_i915_private_t *dev_priv = dev->dev_private; 492 drm_i915_private_t *dev_priv = dev->dev_private;
493 u16 rgvswctl = I915_READ16(MEMSWCTL); 493 u16 rgvswctl = I915_READ16(MEMSWCTL);
494 u16 rgvstat = I915_READ16(MEMSTAT_ILK);
494 495
495 seq_printf(m, "Last command: 0x%01x\n", (rgvswctl >> 13) & 0x3); 496 seq_printf(m, "Requested P-state: %d\n", (rgvswctl >> 8) & 0xf);
496 seq_printf(m, "Command status: %d\n", (rgvswctl >> 12) & 1); 497 seq_printf(m, "Requested VID: %d\n", rgvswctl & 0x3f);
497 seq_printf(m, "P%d DELAY 0x%02x\n", (rgvswctl >> 8) & 0xf, 498 seq_printf(m, "Current VID: %d\n", (rgvstat & MEMSTAT_VID_MASK) >>
498 rgvswctl & 0x3f); 499 MEMSTAT_VID_SHIFT);
500 seq_printf(m, "Current P-state: %d\n",
501 (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
499 502
500 return 0; 503 return 0;
501} 504}
@@ -510,7 +513,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
510 513
511 for (i = 0; i < 16; i++) { 514 for (i = 0; i < 16; i++) {
512 delayfreq = I915_READ(PXVFREQ_BASE + i * 4); 515 delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
513 seq_printf(m, "P%02dVIDFREQ: 0x%08x\n", i, delayfreq); 516 seq_printf(m, "P%02dVIDFREQ: 0x%08x (VID: %d)\n", i, delayfreq,
517 (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
514 } 518 }
515 519
516 return 0; 520 return 0;
@@ -543,6 +547,8 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
543 struct drm_device *dev = node->minor->dev; 547 struct drm_device *dev = node->minor->dev;
544 drm_i915_private_t *dev_priv = dev->dev_private; 548 drm_i915_private_t *dev_priv = dev->dev_private;
545 u32 rgvmodectl = I915_READ(MEMMODECTL); 549 u32 rgvmodectl = I915_READ(MEMMODECTL);
550 u32 rstdbyctl = I915_READ(MCHBAR_RENDER_STANDBY);
551 u16 crstandvid = I915_READ16(CRSTANDVID);
546 552
547 seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ? 553 seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
548 "yes" : "no"); 554 "yes" : "no");
@@ -557,9 +563,13 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
557 rgvmodectl & MEMMODE_RCLK_GATE ? "yes" : "no"); 563 rgvmodectl & MEMMODE_RCLK_GATE ? "yes" : "no");
558 seq_printf(m, "Starting frequency: P%d\n", 564 seq_printf(m, "Starting frequency: P%d\n",
559 (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT); 565 (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT);
560 seq_printf(m, "Max frequency: P%d\n", 566 seq_printf(m, "Max P-state: P%d\n",
561 (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT); 567 (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT);
562 seq_printf(m, "Min frequency: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK)); 568 seq_printf(m, "Min P-state: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK));
569 seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f));
570 seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
571 seq_printf(m, "Render standby enabled: %s\n",
572 (rstdbyctl & RCX_SW_EXIT) ? "no" : "yes");
563 573
564 return 0; 574 return 0;
565} 575}
@@ -623,6 +633,36 @@ static int i915_sr_status(struct seq_file *m, void *unused)
623 return 0; 633 return 0;
624} 634}
625 635
636static int i915_emon_status(struct seq_file *m, void *unused)
637{
638 struct drm_info_node *node = (struct drm_info_node *) m->private;
639 struct drm_device *dev = node->minor->dev;
640 drm_i915_private_t *dev_priv = dev->dev_private;
641 unsigned long temp, chipset, gfx;
642
643 temp = i915_mch_val(dev_priv);
644 chipset = i915_chipset_val(dev_priv);
645 gfx = i915_gfx_val(dev_priv);
646
647 seq_printf(m, "GMCH temp: %ld\n", temp);
648 seq_printf(m, "Chipset power: %ld\n", chipset);
649 seq_printf(m, "GFX power: %ld\n", gfx);
650 seq_printf(m, "Total power: %ld\n", chipset + gfx);
651
652 return 0;
653}
654
655static int i915_gfxec(struct seq_file *m, void *unused)
656{
657 struct drm_info_node *node = (struct drm_info_node *) m->private;
658 struct drm_device *dev = node->minor->dev;
659 drm_i915_private_t *dev_priv = dev->dev_private;
660
661 seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
662
663 return 0;
664}
665
626static int 666static int
627i915_wedged_open(struct inode *inode, 667i915_wedged_open(struct inode *inode,
628 struct file *filp) 668 struct file *filp)
@@ -745,6 +785,8 @@ static struct drm_info_list i915_debugfs_list[] = {
745 {"i915_delayfreq_table", i915_delayfreq_table, 0}, 785 {"i915_delayfreq_table", i915_delayfreq_table, 0},
746 {"i915_inttoext_table", i915_inttoext_table, 0}, 786 {"i915_inttoext_table", i915_inttoext_table, 0},
747 {"i915_drpc_info", i915_drpc_info, 0}, 787 {"i915_drpc_info", i915_drpc_info, 0},
788 {"i915_emon_status", i915_emon_status, 0},
789 {"i915_gfxec", i915_gfxec, 0},
748 {"i915_fbc_status", i915_fbc_status, 0}, 790 {"i915_fbc_status", i915_fbc_status, 0},
749 {"i915_sr_status", i915_sr_status, 0}, 791 {"i915_sr_status", i915_sr_status, 0},
750}; 792};
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 1dbed700800e..12e92f2cc3a7 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1458,14 +1458,11 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
1458 master->driver_priv = NULL; 1458 master->driver_priv = NULL;
1459} 1459}
1460 1460
1461static void i915_get_mem_freq(struct drm_device *dev) 1461static void i915_pineview_get_mem_freq(struct drm_device *dev)
1462{ 1462{
1463 drm_i915_private_t *dev_priv = dev->dev_private; 1463 drm_i915_private_t *dev_priv = dev->dev_private;
1464 u32 tmp; 1464 u32 tmp;
1465 1465
1466 if (!IS_PINEVIEW(dev))
1467 return;
1468
1469 tmp = I915_READ(CLKCFG); 1466 tmp = I915_READ(CLKCFG);
1470 1467
1471 switch (tmp & CLKCFG_FSB_MASK) { 1468 switch (tmp & CLKCFG_FSB_MASK) {
@@ -1496,6 +1493,519 @@ static void i915_get_mem_freq(struct drm_device *dev)
1496 } 1493 }
1497} 1494}
1498 1495
1496static void i915_ironlake_get_mem_freq(struct drm_device *dev)
1497{
1498 drm_i915_private_t *dev_priv = dev->dev_private;
1499 u16 ddrpll, csipll;
1500
1501 ddrpll = I915_READ16(DDRMPLL1);
1502 csipll = I915_READ16(CSIPLL0);
1503
1504 switch (ddrpll & 0xff) {
1505 case 0xc:
1506 dev_priv->mem_freq = 800;
1507 break;
1508 case 0x10:
1509 dev_priv->mem_freq = 1066;
1510 break;
1511 case 0x14:
1512 dev_priv->mem_freq = 1333;
1513 break;
1514 case 0x18:
1515 dev_priv->mem_freq = 1600;
1516 break;
1517 default:
1518 DRM_DEBUG_DRIVER("unknown memory frequency 0x%02x\n",
1519 ddrpll & 0xff);
1520 dev_priv->mem_freq = 0;
1521 break;
1522 }
1523
1524 dev_priv->r_t = dev_priv->mem_freq;
1525
1526 switch (csipll & 0x3ff) {
1527 case 0x00c:
1528 dev_priv->fsb_freq = 3200;
1529 break;
1530 case 0x00e:
1531 dev_priv->fsb_freq = 3733;
1532 break;
1533 case 0x010:
1534 dev_priv->fsb_freq = 4266;
1535 break;
1536 case 0x012:
1537 dev_priv->fsb_freq = 4800;
1538 break;
1539 case 0x014:
1540 dev_priv->fsb_freq = 5333;
1541 break;
1542 case 0x016:
1543 dev_priv->fsb_freq = 5866;
1544 break;
1545 case 0x018:
1546 dev_priv->fsb_freq = 6400;
1547 break;
1548 default:
1549 DRM_DEBUG_DRIVER("unknown fsb frequency 0x%04x\n",
1550 csipll & 0x3ff);
1551 dev_priv->fsb_freq = 0;
1552 break;
1553 }
1554
1555 if (dev_priv->fsb_freq == 3200) {
1556 dev_priv->c_m = 0;
1557 } else if (dev_priv->fsb_freq > 3200 && dev_priv->fsb_freq <= 4800) {
1558 dev_priv->c_m = 1;
1559 } else {
1560 dev_priv->c_m = 2;
1561 }
1562}
1563
1564struct v_table {
1565 u8 vid;
1566 unsigned long vd; /* in .1 mil */
1567 unsigned long vm; /* in .1 mil */
1568 u8 pvid;
1569};
1570
1571static struct v_table v_table[] = {
1572 { 0, 16125, 15000, 0x7f, },
1573 { 1, 16000, 14875, 0x7e, },
1574 { 2, 15875, 14750, 0x7d, },
1575 { 3, 15750, 14625, 0x7c, },
1576 { 4, 15625, 14500, 0x7b, },
1577 { 5, 15500, 14375, 0x7a, },
1578 { 6, 15375, 14250, 0x79, },
1579 { 7, 15250, 14125, 0x78, },
1580 { 8, 15125, 14000, 0x77, },
1581 { 9, 15000, 13875, 0x76, },
1582 { 10, 14875, 13750, 0x75, },
1583 { 11, 14750, 13625, 0x74, },
1584 { 12, 14625, 13500, 0x73, },
1585 { 13, 14500, 13375, 0x72, },
1586 { 14, 14375, 13250, 0x71, },
1587 { 15, 14250, 13125, 0x70, },
1588 { 16, 14125, 13000, 0x6f, },
1589 { 17, 14000, 12875, 0x6e, },
1590 { 18, 13875, 12750, 0x6d, },
1591 { 19, 13750, 12625, 0x6c, },
1592 { 20, 13625, 12500, 0x6b, },
1593 { 21, 13500, 12375, 0x6a, },
1594 { 22, 13375, 12250, 0x69, },
1595 { 23, 13250, 12125, 0x68, },
1596 { 24, 13125, 12000, 0x67, },
1597 { 25, 13000, 11875, 0x66, },
1598 { 26, 12875, 11750, 0x65, },
1599 { 27, 12750, 11625, 0x64, },
1600 { 28, 12625, 11500, 0x63, },
1601 { 29, 12500, 11375, 0x62, },
1602 { 30, 12375, 11250, 0x61, },
1603 { 31, 12250, 11125, 0x60, },
1604 { 32, 12125, 11000, 0x5f, },
1605 { 33, 12000, 10875, 0x5e, },
1606 { 34, 11875, 10750, 0x5d, },
1607 { 35, 11750, 10625, 0x5c, },
1608 { 36, 11625, 10500, 0x5b, },
1609 { 37, 11500, 10375, 0x5a, },
1610 { 38, 11375, 10250, 0x59, },
1611 { 39, 11250, 10125, 0x58, },
1612 { 40, 11125, 10000, 0x57, },
1613 { 41, 11000, 9875, 0x56, },
1614 { 42, 10875, 9750, 0x55, },
1615 { 43, 10750, 9625, 0x54, },
1616 { 44, 10625, 9500, 0x53, },
1617 { 45, 10500, 9375, 0x52, },
1618 { 46, 10375, 9250, 0x51, },
1619 { 47, 10250, 9125, 0x50, },
1620 { 48, 10125, 9000, 0x4f, },
1621 { 49, 10000, 8875, 0x4e, },
1622 { 50, 9875, 8750, 0x4d, },
1623 { 51, 9750, 8625, 0x4c, },
1624 { 52, 9625, 8500, 0x4b, },
1625 { 53, 9500, 8375, 0x4a, },
1626 { 54, 9375, 8250, 0x49, },
1627 { 55, 9250, 8125, 0x48, },
1628 { 56, 9125, 8000, 0x47, },
1629 { 57, 9000, 7875, 0x46, },
1630 { 58, 8875, 7750, 0x45, },
1631 { 59, 8750, 7625, 0x44, },
1632 { 60, 8625, 7500, 0x43, },
1633 { 61, 8500, 7375, 0x42, },
1634 { 62, 8375, 7250, 0x41, },
1635 { 63, 8250, 7125, 0x40, },
1636 { 64, 8125, 7000, 0x3f, },
1637 { 65, 8000, 6875, 0x3e, },
1638 { 66, 7875, 6750, 0x3d, },
1639 { 67, 7750, 6625, 0x3c, },
1640 { 68, 7625, 6500, 0x3b, },
1641 { 69, 7500, 6375, 0x3a, },
1642 { 70, 7375, 6250, 0x39, },
1643 { 71, 7250, 6125, 0x38, },
1644 { 72, 7125, 6000, 0x37, },
1645 { 73, 7000, 5875, 0x36, },
1646 { 74, 6875, 5750, 0x35, },
1647 { 75, 6750, 5625, 0x34, },
1648 { 76, 6625, 5500, 0x33, },
1649 { 77, 6500, 5375, 0x32, },
1650 { 78, 6375, 5250, 0x31, },
1651 { 79, 6250, 5125, 0x30, },
1652 { 80, 6125, 5000, 0x2f, },
1653 { 81, 6000, 4875, 0x2e, },
1654 { 82, 5875, 4750, 0x2d, },
1655 { 83, 5750, 4625, 0x2c, },
1656 { 84, 5625, 4500, 0x2b, },
1657 { 85, 5500, 4375, 0x2a, },
1658 { 86, 5375, 4250, 0x29, },
1659 { 87, 5250, 4125, 0x28, },
1660 { 88, 5125, 4000, 0x27, },
1661 { 89, 5000, 3875, 0x26, },
1662 { 90, 4875, 3750, 0x25, },
1663 { 91, 4750, 3625, 0x24, },
1664 { 92, 4625, 3500, 0x23, },
1665 { 93, 4500, 3375, 0x22, },
1666 { 94, 4375, 3250, 0x21, },
1667 { 95, 4250, 3125, 0x20, },
1668 { 96, 4125, 3000, 0x1f, },
1669 { 97, 4125, 3000, 0x1e, },
1670 { 98, 4125, 3000, 0x1d, },
1671 { 99, 4125, 3000, 0x1c, },
1672 { 100, 4125, 3000, 0x1b, },
1673 { 101, 4125, 3000, 0x1a, },
1674 { 102, 4125, 3000, 0x19, },
1675 { 103, 4125, 3000, 0x18, },
1676 { 104, 4125, 3000, 0x17, },
1677 { 105, 4125, 3000, 0x16, },
1678 { 106, 4125, 3000, 0x15, },
1679 { 107, 4125, 3000, 0x14, },
1680 { 108, 4125, 3000, 0x13, },
1681 { 109, 4125, 3000, 0x12, },
1682 { 110, 4125, 3000, 0x11, },
1683 { 111, 4125, 3000, 0x10, },
1684 { 112, 4125, 3000, 0x0f, },
1685 { 113, 4125, 3000, 0x0e, },
1686 { 114, 4125, 3000, 0x0d, },
1687 { 115, 4125, 3000, 0x0c, },
1688 { 116, 4125, 3000, 0x0b, },
1689 { 117, 4125, 3000, 0x0a, },
1690 { 118, 4125, 3000, 0x09, },
1691 { 119, 4125, 3000, 0x08, },
1692 { 120, 1125, 0, 0x07, },
1693 { 121, 1000, 0, 0x06, },
1694 { 122, 875, 0, 0x05, },
1695 { 123, 750, 0, 0x04, },
1696 { 124, 625, 0, 0x03, },
1697 { 125, 500, 0, 0x02, },
1698 { 126, 375, 0, 0x01, },
1699 { 127, 0, 0, 0x00, },
1700};
1701
1702struct cparams {
1703 int i;
1704 int t;
1705 int m;
1706 int c;
1707};
1708
1709static struct cparams cparams[] = {
1710 { 1, 1333, 301, 28664 },
1711 { 1, 1066, 294, 24460 },
1712 { 1, 800, 294, 25192 },
1713 { 0, 1333, 276, 27605 },
1714 { 0, 1066, 276, 27605 },
1715 { 0, 800, 231, 23784 },
1716};
1717
1718unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
1719{
1720 u64 total_count, diff, ret;
1721 u32 count1, count2, count3, m = 0, c = 0;
1722 unsigned long now = jiffies_to_msecs(jiffies), diff1;
1723 int i;
1724
1725 diff1 = now - dev_priv->last_time1;
1726
1727 count1 = I915_READ(DMIEC);
1728 count2 = I915_READ(DDREC);
1729 count3 = I915_READ(CSIEC);
1730
1731 total_count = count1 + count2 + count3;
1732
1733 /* FIXME: handle per-counter overflow */
1734 if (total_count < dev_priv->last_count1) {
1735 diff = ~0UL - dev_priv->last_count1;
1736 diff += total_count;
1737 } else {
1738 diff = total_count - dev_priv->last_count1;
1739 }
1740
1741 for (i = 0; i < ARRAY_SIZE(cparams); i++) {
1742 if (cparams[i].i == dev_priv->c_m &&
1743 cparams[i].t == dev_priv->r_t) {
1744 m = cparams[i].m;
1745 c = cparams[i].c;
1746 break;
1747 }
1748 }
1749
1750 div_u64(diff, diff1);
1751 ret = ((m * diff) + c);
1752 div_u64(ret, 10);
1753
1754 dev_priv->last_count1 = total_count;
1755 dev_priv->last_time1 = now;
1756
1757 return ret;
1758}
1759
1760unsigned long i915_mch_val(struct drm_i915_private *dev_priv)
1761{
1762 unsigned long m, x, b;
1763 u32 tsfs;
1764
1765 tsfs = I915_READ(TSFS);
1766
1767 m = ((tsfs & TSFS_SLOPE_MASK) >> TSFS_SLOPE_SHIFT);
1768 x = I915_READ8(TR1);
1769
1770 b = tsfs & TSFS_INTR_MASK;
1771
1772 return ((m * x) / 127) - b;
1773}
1774
1775static unsigned long pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
1776{
1777 unsigned long val = 0;
1778 int i;
1779
1780 for (i = 0; i < ARRAY_SIZE(v_table); i++) {
1781 if (v_table[i].pvid == pxvid) {
1782 if (IS_MOBILE(dev_priv->dev))
1783 val = v_table[i].vm;
1784 else
1785 val = v_table[i].vd;
1786 }
1787 }
1788
1789 return val;
1790}
1791
1792void i915_update_gfx_val(struct drm_i915_private *dev_priv)
1793{
1794 struct timespec now, diff1;
1795 u64 diff;
1796 unsigned long diffms;
1797 u32 count;
1798
1799 getrawmonotonic(&now);
1800 diff1 = timespec_sub(now, dev_priv->last_time2);
1801
1802 /* Don't divide by 0 */
1803 diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000;
1804 if (!diffms)
1805 return;
1806
1807 count = I915_READ(GFXEC);
1808
1809 if (count < dev_priv->last_count2) {
1810 diff = ~0UL - dev_priv->last_count2;
1811 diff += count;
1812 } else {
1813 diff = count - dev_priv->last_count2;
1814 }
1815
1816 dev_priv->last_count2 = count;
1817 dev_priv->last_time2 = now;
1818
1819 /* More magic constants... */
1820 diff = diff * 1181;
1821 div_u64(diff, diffms * 10);
1822 dev_priv->gfx_power = diff;
1823}
1824
1825unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
1826{
1827 unsigned long t, corr, state1, corr2, state2;
1828 u32 pxvid, ext_v;
1829
1830 pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->cur_delay * 4));
1831 pxvid = (pxvid >> 24) & 0x7f;
1832 ext_v = pvid_to_extvid(dev_priv, pxvid);
1833
1834 state1 = ext_v;
1835
1836 t = i915_mch_val(dev_priv);
1837
1838 /* Revel in the empirically derived constants */
1839
1840 /* Correction factor in 1/100000 units */
1841 if (t > 80)
1842 corr = ((t * 2349) + 135940);
1843 else if (t >= 50)
1844 corr = ((t * 964) + 29317);
1845 else /* < 50 */
1846 corr = ((t * 301) + 1004);
1847
1848 corr = corr * ((150142 * state1) / 10000 - 78642);
1849 corr /= 100000;
1850 corr2 = (corr * dev_priv->corr);
1851
1852 state2 = (corr2 * state1) / 10000;
1853 state2 /= 100; /* convert to mW */
1854
1855 i915_update_gfx_val(dev_priv);
1856
1857 return dev_priv->gfx_power + state2;
1858}
1859
1860/* Global for IPS driver to get at the current i915 device */
1861static struct drm_i915_private *i915_mch_dev;
1862/*
1863 * Lock protecting IPS related data structures
1864 * - i915_mch_dev
1865 * - dev_priv->max_delay
1866 * - dev_priv->min_delay
1867 * - dev_priv->fmax
1868 * - dev_priv->gpu_busy
1869 */
1870DEFINE_SPINLOCK(mchdev_lock);
1871
1872/**
1873 * i915_read_mch_val - return value for IPS use
1874 *
1875 * Calculate and return a value for the IPS driver to use when deciding whether
1876 * we have thermal and power headroom to increase CPU or GPU power budget.
1877 */
1878unsigned long i915_read_mch_val(void)
1879{
1880 struct drm_i915_private *dev_priv;
1881 unsigned long chipset_val, graphics_val, ret = 0;
1882
1883 spin_lock(&mchdev_lock);
1884 if (!i915_mch_dev)
1885 goto out_unlock;
1886 dev_priv = i915_mch_dev;
1887
1888 chipset_val = i915_chipset_val(dev_priv);
1889 graphics_val = i915_gfx_val(dev_priv);
1890
1891 ret = chipset_val + graphics_val;
1892
1893out_unlock:
1894 spin_unlock(&mchdev_lock);
1895
1896 return ret;
1897}
1898EXPORT_SYMBOL_GPL(i915_read_mch_val);
1899
1900/**
1901 * i915_gpu_raise - raise GPU frequency limit
1902 *
1903 * Raise the limit; IPS indicates we have thermal headroom.
1904 */
1905bool i915_gpu_raise(void)
1906{
1907 struct drm_i915_private *dev_priv;
1908 bool ret = true;
1909
1910 spin_lock(&mchdev_lock);
1911 if (!i915_mch_dev) {
1912 ret = false;
1913 goto out_unlock;
1914 }
1915 dev_priv = i915_mch_dev;
1916
1917 if (dev_priv->max_delay > dev_priv->fmax)
1918 dev_priv->max_delay--;
1919
1920out_unlock:
1921 spin_unlock(&mchdev_lock);
1922
1923 return ret;
1924}
1925EXPORT_SYMBOL_GPL(i915_gpu_raise);
1926
1927/**
1928 * i915_gpu_lower - lower GPU frequency limit
1929 *
1930 * IPS indicates we're close to a thermal limit, so throttle back the GPU
1931 * frequency maximum.
1932 */
1933bool i915_gpu_lower(void)
1934{
1935 struct drm_i915_private *dev_priv;
1936 bool ret = true;
1937
1938 spin_lock(&mchdev_lock);
1939 if (!i915_mch_dev) {
1940 ret = false;
1941 goto out_unlock;
1942 }
1943 dev_priv = i915_mch_dev;
1944
1945 if (dev_priv->max_delay < dev_priv->min_delay)
1946 dev_priv->max_delay++;
1947
1948out_unlock:
1949 spin_unlock(&mchdev_lock);
1950
1951 return ret;
1952}
1953EXPORT_SYMBOL_GPL(i915_gpu_lower);
1954
1955/**
1956 * i915_gpu_busy - indicate GPU business to IPS
1957 *
1958 * Tell the IPS driver whether or not the GPU is busy.
1959 */
1960bool i915_gpu_busy(void)
1961{
1962 struct drm_i915_private *dev_priv;
1963 bool ret = false;
1964
1965 spin_lock(&mchdev_lock);
1966 if (!i915_mch_dev)
1967 goto out_unlock;
1968 dev_priv = i915_mch_dev;
1969
1970 ret = dev_priv->busy;
1971
1972out_unlock:
1973 spin_unlock(&mchdev_lock);
1974
1975 return ret;
1976}
1977EXPORT_SYMBOL_GPL(i915_gpu_busy);
1978
1979/**
1980 * i915_gpu_turbo_disable - disable graphics turbo
1981 *
1982 * Disable graphics turbo by resetting the max frequency and setting the
1983 * current frequency to the default.
1984 */
1985bool i915_gpu_turbo_disable(void)
1986{
1987 struct drm_i915_private *dev_priv;
1988 bool ret = true;
1989
1990 spin_lock(&mchdev_lock);
1991 if (!i915_mch_dev) {
1992 ret = false;
1993 goto out_unlock;
1994 }
1995 dev_priv = i915_mch_dev;
1996
1997 dev_priv->max_delay = dev_priv->fstart;
1998
1999 if (!ironlake_set_drps(dev_priv->dev, dev_priv->fstart))
2000 ret = false;
2001
2002out_unlock:
2003 spin_unlock(&mchdev_lock);
2004
2005 return ret;
2006}
2007EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
2008
1499/** 2009/**
1500 * i915_driver_load - setup chip and create an initial config 2010 * i915_driver_load - setup chip and create an initial config
1501 * @dev: DRM device 2011 * @dev: DRM device
@@ -1616,7 +2126,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1616 goto out_workqueue_free; 2126 goto out_workqueue_free;
1617 } 2127 }
1618 2128
1619 i915_get_mem_freq(dev); 2129 if (IS_PINEVIEW(dev))
2130 i915_pineview_get_mem_freq(dev);
2131 else if (IS_IRONLAKE(dev))
2132 i915_ironlake_get_mem_freq(dev);
1620 2133
1621 /* On the 945G/GM, the chipset reports the MSI capability on the 2134 /* On the 945G/GM, the chipset reports the MSI capability on the
1622 * integrated graphics even though the support isn't actually there 2135 * integrated graphics even though the support isn't actually there
@@ -1662,6 +2175,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1662 2175
1663 setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, 2176 setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
1664 (unsigned long) dev); 2177 (unsigned long) dev);
2178
2179 spin_lock(&mchdev_lock);
2180 i915_mch_dev = dev_priv;
2181 dev_priv->mchdev_lock = &mchdev_lock;
2182 spin_unlock(&mchdev_lock);
2183
1665 return 0; 2184 return 0;
1666 2185
1667out_workqueue_free: 2186out_workqueue_free:
@@ -1683,6 +2202,10 @@ int i915_driver_unload(struct drm_device *dev)
1683 2202
1684 i915_destroy_error_state(dev); 2203 i915_destroy_error_state(dev);
1685 2204
2205 spin_lock(&mchdev_lock);
2206 i915_mch_dev = NULL;
2207 spin_unlock(&mchdev_lock);
2208
1686 destroy_workqueue(dev_priv->wq); 2209 destroy_workqueue(dev_priv->wq);
1687 del_timer_sync(&dev_priv->hangcheck_timer); 2210 del_timer_sync(&dev_priv->hangcheck_timer);
1688 2211
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6bc0fc080f2b..91b3a1c20ef8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -619,6 +619,18 @@ typedef struct drm_i915_private {
619 u8 cur_delay; 619 u8 cur_delay;
620 u8 min_delay; 620 u8 min_delay;
621 u8 max_delay; 621 u8 max_delay;
622 u8 fmax;
623 u8 fstart;
624
625 u64 last_count1;
626 unsigned long last_time1;
627 u64 last_count2;
628 struct timespec last_time2;
629 unsigned long gfx_power;
630 int c_m;
631 int r_t;
632 u8 corr;
633 spinlock_t *mchdev_lock;
622 634
623 enum no_fbc_reason no_fbc_reason; 635 enum no_fbc_reason no_fbc_reason;
624 636
@@ -802,6 +814,11 @@ extern int i915_emit_box(struct drm_device *dev,
802 struct drm_clip_rect *boxes, 814 struct drm_clip_rect *boxes,
803 int i, int DR1, int DR4); 815 int i, int DR1, int DR4);
804extern int i965_reset(struct drm_device *dev, u8 flags); 816extern int i965_reset(struct drm_device *dev, u8 flags);
817extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
818extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
819extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
820extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
821
805 822
806/* i915_irq.c */ 823/* i915_irq.c */
807void i915_hangcheck_elapsed(unsigned long data); 824void i915_hangcheck_elapsed(unsigned long data);
@@ -1005,7 +1022,7 @@ extern void g4x_disable_fbc(struct drm_device *dev);
1005extern void intel_disable_fbc(struct drm_device *dev); 1022extern void intel_disable_fbc(struct drm_device *dev);
1006extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval); 1023extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
1007extern bool intel_fbc_enabled(struct drm_device *dev); 1024extern bool intel_fbc_enabled(struct drm_device *dev);
1008 1025extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
1009extern void intel_detect_pch (struct drm_device *dev); 1026extern void intel_detect_pch (struct drm_device *dev);
1010extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); 1027extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
1011 1028
@@ -1030,6 +1047,7 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
1030#define I915_WRITE64(reg, val) writeq(val, dev_priv->regs + (reg)) 1047#define I915_WRITE64(reg, val) writeq(val, dev_priv->regs + (reg))
1031#define I915_READ64(reg) readq(dev_priv->regs + (reg)) 1048#define I915_READ64(reg) readq(dev_priv->regs + (reg))
1032#define POSTING_READ(reg) (void)I915_READ(reg) 1049#define POSTING_READ(reg) (void)I915_READ(reg)
1050#define POSTING_READ16(reg) (void)I915_READ16(reg)
1033 1051
1034#define I915_VERBOSE 0 1052#define I915_VERBOSE 0
1035 1053
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 0a3a5806a12e..b5dba4795f6f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -278,10 +278,9 @@ static void i915_handle_rps_change(struct drm_device *dev)
278{ 278{
279 drm_i915_private_t *dev_priv = dev->dev_private; 279 drm_i915_private_t *dev_priv = dev->dev_private;
280 u32 busy_up, busy_down, max_avg, min_avg; 280 u32 busy_up, busy_down, max_avg, min_avg;
281 u16 rgvswctl;
282 u8 new_delay = dev_priv->cur_delay; 281 u8 new_delay = dev_priv->cur_delay;
283 282
284 I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS) & ~MEMINT_EVAL_CHG); 283 I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG);
285 busy_up = I915_READ(RCPREVBSYTUPAVG); 284 busy_up = I915_READ(RCPREVBSYTUPAVG);
286 busy_down = I915_READ(RCPREVBSYTDNAVG); 285 busy_down = I915_READ(RCPREVBSYTDNAVG);
287 max_avg = I915_READ(RCBMAXAVG); 286 max_avg = I915_READ(RCBMAXAVG);
@@ -300,27 +299,8 @@ static void i915_handle_rps_change(struct drm_device *dev)
300 new_delay = dev_priv->min_delay; 299 new_delay = dev_priv->min_delay;
301 } 300 }
302 301
303 DRM_DEBUG("rps change requested: %d -> %d\n", 302 if (ironlake_set_drps(dev, new_delay))
304 dev_priv->cur_delay, new_delay); 303 dev_priv->cur_delay = new_delay;
305
306 rgvswctl = I915_READ(MEMSWCTL);
307 if (rgvswctl & MEMCTL_CMD_STS) {
308 DRM_ERROR("gpu busy, RCS change rejected\n");
309 return; /* still busy with another command */
310 }
311
312 /* Program the new state */
313 rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
314 (new_delay << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
315 I915_WRITE(MEMSWCTL, rgvswctl);
316 POSTING_READ(MEMSWCTL);
317
318 rgvswctl |= MEMCTL_CMD_STS;
319 I915_WRITE(MEMSWCTL, rgvswctl);
320
321 dev_priv->cur_delay = new_delay;
322
323 DRM_DEBUG("rps changed\n");
324 304
325 return; 305 return;
326} 306}
@@ -392,7 +372,7 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
392 } 372 }
393 373
394 if (de_iir & DE_PCU_EVENT) { 374 if (de_iir & DE_PCU_EVENT) {
395 I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS)); 375 I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
396 i915_handle_rps_change(dev); 376 i915_handle_rps_change(dev);
397 } 377 }
398 378
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7a726840efa7..df7224de0aed 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -838,6 +838,12 @@
838#define CLKCFG_MEM_800 (3 << 4) 838#define CLKCFG_MEM_800 (3 << 4)
839#define CLKCFG_MEM_MASK (7 << 4) 839#define CLKCFG_MEM_MASK (7 << 4)
840 840
841#define TR1 0x11006
842#define TSFS 0x11020
843#define TSFS_SLOPE_MASK 0x0000ff00
844#define TSFS_SLOPE_SHIFT 8
845#define TSFS_INTR_MASK 0x000000ff
846
841#define CRSTANDVID 0x11100 847#define CRSTANDVID 0x11100
842#define PXVFREQ_BASE 0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */ 848#define PXVFREQ_BASE 0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */
843#define PXVFREQ_PX_MASK 0x7f000000 849#define PXVFREQ_PX_MASK 0x7f000000
@@ -976,6 +982,41 @@
976#define MEMSTAT_SRC_CTL_STDBY 3 982#define MEMSTAT_SRC_CTL_STDBY 3
977#define RCPREVBSYTUPAVG 0x113b8 983#define RCPREVBSYTUPAVG 0x113b8
978#define RCPREVBSYTDNAVG 0x113bc 984#define RCPREVBSYTDNAVG 0x113bc
985#define SDEW 0x1124c
986#define CSIEW0 0x11250
987#define CSIEW1 0x11254
988#define CSIEW2 0x11258
989#define PEW 0x1125c
990#define DEW 0x11270
991#define MCHAFE 0x112c0
992#define CSIEC 0x112e0
993#define DMIEC 0x112e4
994#define DDREC 0x112e8
995#define PEG0EC 0x112ec
996#define PEG1EC 0x112f0
997#define GFXEC 0x112f4
998#define RPPREVBSYTUPAVG 0x113b8
999#define RPPREVBSYTDNAVG 0x113bc
1000#define ECR 0x11600
1001#define ECR_GPFE (1<<31)
1002#define ECR_IMONE (1<<30)
1003#define ECR_CAP_MASK 0x0000001f /* Event range, 0-31 */
1004#define OGW0 0x11608
1005#define OGW1 0x1160c
1006#define EG0 0x11610
1007#define EG1 0x11614
1008#define EG2 0x11618
1009#define EG3 0x1161c
1010#define EG4 0x11620
1011#define EG5 0x11624
1012#define EG6 0x11628
1013#define EG7 0x1162c
1014#define PXW 0x11664
1015#define PXWL 0x11680
1016#define LCFUSE02 0x116c0
1017#define LCFUSE_HIV_MASK 0x000000ff
1018#define CSIPLL0 0x12c10
1019#define DDRMPLL1 0X12c20
979#define PEG_BAND_GAP_DATA 0x14d68 1020#define PEG_BAND_GAP_DATA 0x14d68
980 1021
981/* 1022/*
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4c7c151114f7..e94d1db35364 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4459,6 +4459,8 @@ static void intel_idle_update(struct work_struct *work)
4459 4459
4460 mutex_lock(&dev->struct_mutex); 4460 mutex_lock(&dev->struct_mutex);
4461 4461
4462 i915_update_gfx_val(dev_priv);
4463
4462 if (IS_I945G(dev) || IS_I945GM(dev)) { 4464 if (IS_I945G(dev) || IS_I945GM(dev)) {
4463 DRM_DEBUG_DRIVER("enable memory self refresh on 945\n"); 4465 DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
4464 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN); 4466 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
@@ -5045,10 +5047,32 @@ err_unref:
5045 return NULL; 5047 return NULL;
5046} 5048}
5047 5049
5050bool ironlake_set_drps(struct drm_device *dev, u8 val)
5051{
5052 struct drm_i915_private *dev_priv = dev->dev_private;
5053 u16 rgvswctl;
5054
5055 rgvswctl = I915_READ16(MEMSWCTL);
5056 if (rgvswctl & MEMCTL_CMD_STS) {
5057 DRM_DEBUG("gpu busy, RCS change rejected\n");
5058 return false; /* still busy with another command */
5059 }
5060
5061 rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
5062 (val << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
5063 I915_WRITE16(MEMSWCTL, rgvswctl);
5064 POSTING_READ16(MEMSWCTL);
5065
5066 rgvswctl |= MEMCTL_CMD_STS;
5067 I915_WRITE16(MEMSWCTL, rgvswctl);
5068
5069 return true;
5070}
5071
5048void ironlake_enable_drps(struct drm_device *dev) 5072void ironlake_enable_drps(struct drm_device *dev)
5049{ 5073{
5050 struct drm_i915_private *dev_priv = dev->dev_private; 5074 struct drm_i915_private *dev_priv = dev->dev_private;
5051 u32 rgvmodectl = I915_READ(MEMMODECTL), rgvswctl; 5075 u32 rgvmodectl = I915_READ(MEMMODECTL);
5052 u8 fmax, fmin, fstart, vstart; 5076 u8 fmax, fmin, fstart, vstart;
5053 int i = 0; 5077 int i = 0;
5054 5078
@@ -5067,13 +5091,21 @@ void ironlake_enable_drps(struct drm_device *dev)
5067 fmin = (rgvmodectl & MEMMODE_FMIN_MASK); 5091 fmin = (rgvmodectl & MEMMODE_FMIN_MASK);
5068 fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >> 5092 fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
5069 MEMMODE_FSTART_SHIFT; 5093 MEMMODE_FSTART_SHIFT;
5094 fstart = fmax;
5095
5070 vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >> 5096 vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >>
5071 PXVFREQ_PX_SHIFT; 5097 PXVFREQ_PX_SHIFT;
5072 5098
5073 dev_priv->max_delay = fstart; /* can't go to fmax w/o IPS */ 5099 dev_priv->fmax = fstart; /* IPS callback will increase this */
5100 dev_priv->fstart = fstart;
5101
5102 dev_priv->max_delay = fmax;
5074 dev_priv->min_delay = fmin; 5103 dev_priv->min_delay = fmin;
5075 dev_priv->cur_delay = fstart; 5104 dev_priv->cur_delay = fstart;
5076 5105
5106 DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", fmax, fmin,
5107 fstart);
5108
5077 I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN); 5109 I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN);
5078 5110
5079 /* 5111 /*
@@ -5095,20 +5127,19 @@ void ironlake_enable_drps(struct drm_device *dev)
5095 } 5127 }
5096 msleep(1); 5128 msleep(1);
5097 5129
5098 rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) | 5130 ironlake_set_drps(dev, fstart);
5099 (fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
5100 I915_WRITE(MEMSWCTL, rgvswctl);
5101 POSTING_READ(MEMSWCTL);
5102 5131
5103 rgvswctl |= MEMCTL_CMD_STS; 5132 dev_priv->last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) +
5104 I915_WRITE(MEMSWCTL, rgvswctl); 5133 I915_READ(0x112e0);
5134 dev_priv->last_time1 = jiffies_to_msecs(jiffies);
5135 dev_priv->last_count2 = I915_READ(0x112f4);
5136 getrawmonotonic(&dev_priv->last_time2);
5105} 5137}
5106 5138
5107void ironlake_disable_drps(struct drm_device *dev) 5139void ironlake_disable_drps(struct drm_device *dev)
5108{ 5140{
5109 struct drm_i915_private *dev_priv = dev->dev_private; 5141 struct drm_i915_private *dev_priv = dev->dev_private;
5110 u32 rgvswctl; 5142 u16 rgvswctl = I915_READ16(MEMSWCTL);
5111 u8 fstart;
5112 5143
5113 /* Ack interrupts, disable EFC interrupt */ 5144 /* Ack interrupts, disable EFC interrupt */
5114 I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN); 5145 I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
@@ -5118,11 +5149,7 @@ void ironlake_disable_drps(struct drm_device *dev)
5118 I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT); 5149 I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT);
5119 5150
5120 /* Go back to the starting frequency */ 5151 /* Go back to the starting frequency */
5121 fstart = (I915_READ(MEMMODECTL) & MEMMODE_FSTART_MASK) >> 5152 ironlake_set_drps(dev, dev_priv->fstart);
5122 MEMMODE_FSTART_SHIFT;
5123 rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
5124 (fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
5125 I915_WRITE(MEMSWCTL, rgvswctl);
5126 msleep(1); 5153 msleep(1);
5127 rgvswctl |= MEMCTL_CMD_STS; 5154 rgvswctl |= MEMCTL_CMD_STS;
5128 I915_WRITE(MEMSWCTL, rgvswctl); 5155 I915_WRITE(MEMSWCTL, rgvswctl);
@@ -5130,6 +5157,92 @@ void ironlake_disable_drps(struct drm_device *dev)
5130 5157
5131} 5158}
5132 5159
5160static unsigned long intel_pxfreq(u32 vidfreq)
5161{
5162 unsigned long freq;
5163 int div = (vidfreq & 0x3f0000) >> 16;
5164 int post = (vidfreq & 0x3000) >> 12;
5165 int pre = (vidfreq & 0x7);
5166
5167 if (!pre)
5168 return 0;
5169
5170 freq = ((div * 133333) / ((1<<post) * pre));
5171
5172 return freq;
5173}
5174
5175void intel_init_emon(struct drm_device *dev)
5176{
5177 struct drm_i915_private *dev_priv = dev->dev_private;
5178 u32 lcfuse;
5179 u8 pxw[16];
5180 int i;
5181
5182 /* Disable to program */
5183 I915_WRITE(ECR, 0);
5184 POSTING_READ(ECR);
5185
5186 /* Program energy weights for various events */
5187 I915_WRITE(SDEW, 0x15040d00);
5188 I915_WRITE(CSIEW0, 0x007f0000);
5189 I915_WRITE(CSIEW1, 0x1e220004);
5190 I915_WRITE(CSIEW2, 0x04000004);
5191
5192 for (i = 0; i < 5; i++)
5193 I915_WRITE(PEW + (i * 4), 0);
5194 for (i = 0; i < 3; i++)
5195 I915_WRITE(DEW + (i * 4), 0);
5196
5197 /* Program P-state weights to account for frequency power adjustment */
5198 for (i = 0; i < 16; i++) {
5199 u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4));
5200 unsigned long freq = intel_pxfreq(pxvidfreq);
5201 unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >>
5202 PXVFREQ_PX_SHIFT;
5203 unsigned long val;
5204
5205 val = vid * vid;
5206 val *= (freq / 1000);
5207 val *= 255;
5208 val /= (127*127*900);
5209 if (val > 0xff)
5210 DRM_ERROR("bad pxval: %ld\n", val);
5211 pxw[i] = val;
5212 }
5213 /* Render standby states get 0 weight */
5214 pxw[14] = 0;
5215 pxw[15] = 0;
5216
5217 for (i = 0; i < 4; i++) {
5218 u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) |
5219 (pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]);
5220 I915_WRITE(PXW + (i * 4), val);
5221 }
5222
5223 /* Adjust magic regs to magic values (more experimental results) */
5224 I915_WRITE(OGW0, 0);
5225 I915_WRITE(OGW1, 0);
5226 I915_WRITE(EG0, 0x00007f00);
5227 I915_WRITE(EG1, 0x0000000e);
5228 I915_WRITE(EG2, 0x000e0000);
5229 I915_WRITE(EG3, 0x68000300);
5230 I915_WRITE(EG4, 0x42000000);
5231 I915_WRITE(EG5, 0x00140031);
5232 I915_WRITE(EG6, 0);
5233 I915_WRITE(EG7, 0);
5234
5235 for (i = 0; i < 8; i++)
5236 I915_WRITE(PXWL + (i * 4), 0);
5237
5238 /* Enable PMON + select events */
5239 I915_WRITE(ECR, 0x80000019);
5240
5241 lcfuse = I915_READ(LCFUSE02);
5242
5243 dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
5244}
5245
5133void intel_init_clock_gating(struct drm_device *dev) 5246void intel_init_clock_gating(struct drm_device *dev)
5134{ 5247{
5135 struct drm_i915_private *dev_priv = dev->dev_private; 5248 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5376,8 +5489,10 @@ void intel_modeset_init(struct drm_device *dev)
5376 5489
5377 intel_init_clock_gating(dev); 5490 intel_init_clock_gating(dev);
5378 5491
5379 if (IS_IRONLAKE_M(dev)) 5492 if (IS_IRONLAKE_M(dev)) {
5380 ironlake_enable_drps(dev); 5493 ironlake_enable_drps(dev);
5494 intel_init_emon(dev);
5495 }
5381 5496
5382 INIT_WORK(&dev_priv->idle_work, intel_idle_update); 5497 INIT_WORK(&dev_priv->idle_work, intel_idle_update);
5383 setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, 5498 setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,