diff options
author | Paulo Zanoni <paulo.r.zanoni@intel.com> | 2012-10-15 14:51:34 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-10-17 16:17:26 -0400 |
commit | d6c0d722aea21d4073629a7401d086229b582f6e (patch) | |
tree | 8eabb7d382027481dd76324e6e079502bdd40502 /drivers/gpu/drm | |
parent | 068759bd6ee26b5c69977d99611cc72b43280ab5 (diff) |
drm/i915: add basic Haswell DP link train bits
Previously, the DP register was used for everything. On Haswell, it
was split into DDI_BUF_CTL (which is the new intel_dp->DP register)
and DP_TP_CTL.
The logic behind this patch is based on a patch written by Shobhit
Kumar, but the way the code was written is very different.
Credits-to: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
[danvet: Fixup the logic error spotted by Jani Nikula.]
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 104 |
2 files changed, 102 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index fafdd9f1e80e..c31ee5bd1a56 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -4435,12 +4435,16 @@ | |||
4435 | #define DP_TP_CTL_LINK_TRAIN_MASK (7<<8) | 4435 | #define DP_TP_CTL_LINK_TRAIN_MASK (7<<8) |
4436 | #define DP_TP_CTL_LINK_TRAIN_PAT1 (0<<8) | 4436 | #define DP_TP_CTL_LINK_TRAIN_PAT1 (0<<8) |
4437 | #define DP_TP_CTL_LINK_TRAIN_PAT2 (1<<8) | 4437 | #define DP_TP_CTL_LINK_TRAIN_PAT2 (1<<8) |
4438 | #define DP_TP_CTL_LINK_TRAIN_PAT3 (4<<8) | ||
4439 | #define DP_TP_CTL_LINK_TRAIN_IDLE (2<<8) | ||
4438 | #define DP_TP_CTL_LINK_TRAIN_NORMAL (3<<8) | 4440 | #define DP_TP_CTL_LINK_TRAIN_NORMAL (3<<8) |
4441 | #define DP_TP_CTL_SCRAMBLE_DISABLE (1<<7) | ||
4439 | 4442 | ||
4440 | /* DisplayPort Transport Status */ | 4443 | /* DisplayPort Transport Status */ |
4441 | #define DP_TP_STATUS_A 0x64044 | 4444 | #define DP_TP_STATUS_A 0x64044 |
4442 | #define DP_TP_STATUS_B 0x64144 | 4445 | #define DP_TP_STATUS_B 0x64144 |
4443 | #define DP_TP_STATUS(port) _PORT(port, DP_TP_STATUS_A, DP_TP_STATUS_B) | 4446 | #define DP_TP_STATUS(port) _PORT(port, DP_TP_STATUS_A, DP_TP_STATUS_B) |
4447 | #define DP_TP_STATUS_IDLE_DONE (1<<25) | ||
4444 | #define DP_TP_STATUS_AUTOTRAIN_DONE (1<<12) | 4448 | #define DP_TP_STATUS_AUTOTRAIN_DONE (1<<12) |
4445 | 4449 | ||
4446 | /* DDI Buffer Control */ | 4450 | /* DDI Buffer Control */ |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 871bc17d221d..55f7cc0de6fa 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -1470,7 +1470,19 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) | |||
1470 | { | 1470 | { |
1471 | struct drm_device *dev = intel_dp->base.base.dev; | 1471 | struct drm_device *dev = intel_dp->base.base.dev; |
1472 | 1472 | ||
1473 | if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { | 1473 | if (IS_HASWELL(dev)) { |
1474 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { | ||
1475 | case DP_TRAIN_VOLTAGE_SWING_400: | ||
1476 | return DP_TRAIN_PRE_EMPHASIS_9_5; | ||
1477 | case DP_TRAIN_VOLTAGE_SWING_600: | ||
1478 | return DP_TRAIN_PRE_EMPHASIS_6; | ||
1479 | case DP_TRAIN_VOLTAGE_SWING_800: | ||
1480 | return DP_TRAIN_PRE_EMPHASIS_3_5; | ||
1481 | case DP_TRAIN_VOLTAGE_SWING_1200: | ||
1482 | default: | ||
1483 | return DP_TRAIN_PRE_EMPHASIS_0; | ||
1484 | } | ||
1485 | } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { | ||
1474 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { | 1486 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { |
1475 | case DP_TRAIN_VOLTAGE_SWING_400: | 1487 | case DP_TRAIN_VOLTAGE_SWING_400: |
1476 | return DP_TRAIN_PRE_EMPHASIS_6; | 1488 | return DP_TRAIN_PRE_EMPHASIS_6; |
@@ -1624,6 +1636,40 @@ intel_gen7_edp_signal_levels(uint8_t train_set) | |||
1624 | } | 1636 | } |
1625 | } | 1637 | } |
1626 | 1638 | ||
1639 | /* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */ | ||
1640 | static uint32_t | ||
1641 | intel_dp_signal_levels_hsw(uint8_t train_set) | ||
1642 | { | ||
1643 | int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | | ||
1644 | DP_TRAIN_PRE_EMPHASIS_MASK); | ||
1645 | switch (signal_levels) { | ||
1646 | case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: | ||
1647 | return DDI_BUF_EMP_400MV_0DB_HSW; | ||
1648 | case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5: | ||
1649 | return DDI_BUF_EMP_400MV_3_5DB_HSW; | ||
1650 | case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: | ||
1651 | return DDI_BUF_EMP_400MV_6DB_HSW; | ||
1652 | case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_9_5: | ||
1653 | return DDI_BUF_EMP_400MV_9_5DB_HSW; | ||
1654 | |||
1655 | case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0: | ||
1656 | return DDI_BUF_EMP_600MV_0DB_HSW; | ||
1657 | case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: | ||
1658 | return DDI_BUF_EMP_600MV_3_5DB_HSW; | ||
1659 | case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6: | ||
1660 | return DDI_BUF_EMP_600MV_6DB_HSW; | ||
1661 | |||
1662 | case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: | ||
1663 | return DDI_BUF_EMP_800MV_0DB_HSW; | ||
1664 | case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5: | ||
1665 | return DDI_BUF_EMP_800MV_3_5DB_HSW; | ||
1666 | default: | ||
1667 | DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" | ||
1668 | "0x%x\n", signal_levels); | ||
1669 | return DDI_BUF_EMP_400MV_0DB_HSW; | ||
1670 | } | ||
1671 | } | ||
1672 | |||
1627 | static uint8_t | 1673 | static uint8_t |
1628 | intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], | 1674 | intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], |
1629 | int lane) | 1675 | int lane) |
@@ -1680,8 +1726,44 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
1680 | struct drm_device *dev = intel_dp->base.base.dev; | 1726 | struct drm_device *dev = intel_dp->base.base.dev; |
1681 | struct drm_i915_private *dev_priv = dev->dev_private; | 1727 | struct drm_i915_private *dev_priv = dev->dev_private; |
1682 | int ret; | 1728 | int ret; |
1729 | uint32_t temp; | ||
1683 | 1730 | ||
1684 | if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) { | 1731 | if (IS_HASWELL(dev)) { |
1732 | temp = I915_READ(DP_TP_CTL(intel_dp->port)); | ||
1733 | |||
1734 | if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) | ||
1735 | temp |= DP_TP_CTL_SCRAMBLE_DISABLE; | ||
1736 | else | ||
1737 | temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE; | ||
1738 | |||
1739 | temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; | ||
1740 | switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { | ||
1741 | case DP_TRAINING_PATTERN_DISABLE: | ||
1742 | temp |= DP_TP_CTL_LINK_TRAIN_IDLE; | ||
1743 | I915_WRITE(DP_TP_CTL(intel_dp->port), temp); | ||
1744 | |||
1745 | if (wait_for((I915_READ(DP_TP_STATUS(intel_dp->port)) & | ||
1746 | DP_TP_STATUS_IDLE_DONE), 1)) | ||
1747 | DRM_ERROR("Timed out waiting for DP idle patterns\n"); | ||
1748 | |||
1749 | temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; | ||
1750 | temp |= DP_TP_CTL_LINK_TRAIN_NORMAL; | ||
1751 | |||
1752 | break; | ||
1753 | case DP_TRAINING_PATTERN_1: | ||
1754 | temp |= DP_TP_CTL_LINK_TRAIN_PAT1; | ||
1755 | break; | ||
1756 | case DP_TRAINING_PATTERN_2: | ||
1757 | temp |= DP_TP_CTL_LINK_TRAIN_PAT2; | ||
1758 | break; | ||
1759 | case DP_TRAINING_PATTERN_3: | ||
1760 | temp |= DP_TP_CTL_LINK_TRAIN_PAT3; | ||
1761 | break; | ||
1762 | } | ||
1763 | I915_WRITE(DP_TP_CTL(intel_dp->port), temp); | ||
1764 | |||
1765 | } else if (HAS_PCH_CPT(dev) && | ||
1766 | (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) { | ||
1685 | dp_reg_value &= ~DP_LINK_TRAIN_MASK_CPT; | 1767 | dp_reg_value &= ~DP_LINK_TRAIN_MASK_CPT; |
1686 | 1768 | ||
1687 | switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { | 1769 | switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { |
@@ -1768,8 +1850,11 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
1768 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | 1850 | uint8_t link_status[DP_LINK_STATUS_SIZE]; |
1769 | uint32_t signal_levels; | 1851 | uint32_t signal_levels; |
1770 | 1852 | ||
1771 | 1853 | if (IS_HASWELL(dev)) { | |
1772 | if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { | 1854 | signal_levels = intel_dp_signal_levels_hsw( |
1855 | intel_dp->train_set[0]); | ||
1856 | DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels; | ||
1857 | } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { | ||
1773 | signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); | 1858 | signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); |
1774 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; | 1859 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; |
1775 | } else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { | 1860 | } else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { |
@@ -1777,9 +1862,10 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
1777 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; | 1862 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; |
1778 | } else { | 1863 | } else { |
1779 | signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]); | 1864 | signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]); |
1780 | DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", signal_levels); | ||
1781 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | 1865 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; |
1782 | } | 1866 | } |
1867 | DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", | ||
1868 | signal_levels); | ||
1783 | 1869 | ||
1784 | if (!intel_dp_set_link_train(intel_dp, DP, | 1870 | if (!intel_dp_set_link_train(intel_dp, DP, |
1785 | DP_TRAINING_PATTERN_1 | | 1871 | DP_TRAINING_PATTERN_1 | |
@@ -1855,7 +1941,10 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
1855 | break; | 1941 | break; |
1856 | } | 1942 | } |
1857 | 1943 | ||
1858 | if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { | 1944 | if (IS_HASWELL(dev)) { |
1945 | signal_levels = intel_dp_signal_levels_hsw(intel_dp->train_set[0]); | ||
1946 | DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels; | ||
1947 | } else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { | ||
1859 | signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); | 1948 | signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); |
1860 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; | 1949 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; |
1861 | } else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { | 1950 | } else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { |
@@ -1902,6 +1991,9 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
1902 | ++tries; | 1991 | ++tries; |
1903 | } | 1992 | } |
1904 | 1993 | ||
1994 | if (channel_eq) | ||
1995 | DRM_DEBUG_KMS("Channel EQ done. DP Training successfull\n"); | ||
1996 | |||
1905 | intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE); | 1997 | intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE); |
1906 | } | 1998 | } |
1907 | 1999 | ||