diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2013-12-05 08:51:38 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-12-17 07:17:56 -0500 |
commit | 96f90c5421aaaba35ffd931728fabeb8f6cd8471 (patch) | |
tree | 3842175affd2c8cb7c6cc37250656824f5f24ff2 /drivers/gpu/drm/i915/intel_pm.c | |
parent | 017636cc09e2c58bc493cc1fe74d858f50d173af (diff) |
drm/i915: Move ILK/SNB/IVB over to the HSW WM code
The new HSW watermark code can now handle ILK/SNB/IVB as well, so
switch them over. Kill the old code.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 656 |
1 files changed, 11 insertions, 645 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e321fbc28a0b..7e028341b2f5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -965,65 +965,6 @@ static const struct intel_watermark_params i830_wm_info = { | |||
965 | I830_FIFO_LINE_SIZE | 965 | I830_FIFO_LINE_SIZE |
966 | }; | 966 | }; |
967 | 967 | ||
968 | static const struct intel_watermark_params ironlake_display_wm_info = { | ||
969 | ILK_DISPLAY_FIFO, | ||
970 | ILK_DISPLAY_MAXWM, | ||
971 | ILK_DISPLAY_DFTWM, | ||
972 | 2, | ||
973 | ILK_FIFO_LINE_SIZE | ||
974 | }; | ||
975 | static const struct intel_watermark_params ironlake_cursor_wm_info = { | ||
976 | ILK_CURSOR_FIFO, | ||
977 | ILK_CURSOR_MAXWM, | ||
978 | ILK_CURSOR_DFTWM, | ||
979 | 2, | ||
980 | ILK_FIFO_LINE_SIZE | ||
981 | }; | ||
982 | static const struct intel_watermark_params ironlake_display_srwm_info = { | ||
983 | ILK_DISPLAY_SR_FIFO, | ||
984 | ILK_DISPLAY_MAX_SRWM, | ||
985 | ILK_DISPLAY_DFT_SRWM, | ||
986 | 2, | ||
987 | ILK_FIFO_LINE_SIZE | ||
988 | }; | ||
989 | static const struct intel_watermark_params ironlake_cursor_srwm_info = { | ||
990 | ILK_CURSOR_SR_FIFO, | ||
991 | ILK_CURSOR_MAX_SRWM, | ||
992 | ILK_CURSOR_DFT_SRWM, | ||
993 | 2, | ||
994 | ILK_FIFO_LINE_SIZE | ||
995 | }; | ||
996 | |||
997 | static const struct intel_watermark_params sandybridge_display_wm_info = { | ||
998 | SNB_DISPLAY_FIFO, | ||
999 | SNB_DISPLAY_MAXWM, | ||
1000 | SNB_DISPLAY_DFTWM, | ||
1001 | 2, | ||
1002 | SNB_FIFO_LINE_SIZE | ||
1003 | }; | ||
1004 | static const struct intel_watermark_params sandybridge_cursor_wm_info = { | ||
1005 | SNB_CURSOR_FIFO, | ||
1006 | SNB_CURSOR_MAXWM, | ||
1007 | SNB_CURSOR_DFTWM, | ||
1008 | 2, | ||
1009 | SNB_FIFO_LINE_SIZE | ||
1010 | }; | ||
1011 | static const struct intel_watermark_params sandybridge_display_srwm_info = { | ||
1012 | SNB_DISPLAY_SR_FIFO, | ||
1013 | SNB_DISPLAY_MAX_SRWM, | ||
1014 | SNB_DISPLAY_DFT_SRWM, | ||
1015 | 2, | ||
1016 | SNB_FIFO_LINE_SIZE | ||
1017 | }; | ||
1018 | static const struct intel_watermark_params sandybridge_cursor_srwm_info = { | ||
1019 | SNB_CURSOR_SR_FIFO, | ||
1020 | SNB_CURSOR_MAX_SRWM, | ||
1021 | SNB_CURSOR_DFT_SRWM, | ||
1022 | 2, | ||
1023 | SNB_FIFO_LINE_SIZE | ||
1024 | }; | ||
1025 | |||
1026 | |||
1027 | /** | 968 | /** |
1028 | * intel_calculate_wm - calculate watermark level | 969 | * intel_calculate_wm - calculate watermark level |
1029 | * @clock_in_khz: pixel clock | 970 | * @clock_in_khz: pixel clock |
@@ -1707,423 +1648,6 @@ static void i830_update_wm(struct drm_crtc *unused_crtc) | |||
1707 | I915_WRITE(FW_BLC, fwater_lo); | 1648 | I915_WRITE(FW_BLC, fwater_lo); |
1708 | } | 1649 | } |
1709 | 1650 | ||
1710 | /* | ||
1711 | * Check the wm result. | ||
1712 | * | ||
1713 | * If any calculated watermark values is larger than the maximum value that | ||
1714 | * can be programmed into the associated watermark register, that watermark | ||
1715 | * must be disabled. | ||
1716 | */ | ||
1717 | static bool ironlake_check_srwm(struct drm_device *dev, int level, | ||
1718 | int fbc_wm, int display_wm, int cursor_wm, | ||
1719 | const struct intel_watermark_params *display, | ||
1720 | const struct intel_watermark_params *cursor) | ||
1721 | { | ||
1722 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1723 | |||
1724 | DRM_DEBUG_KMS("watermark %d: display plane %d, fbc lines %d," | ||
1725 | " cursor %d\n", level, display_wm, fbc_wm, cursor_wm); | ||
1726 | |||
1727 | if (fbc_wm > SNB_FBC_MAX_SRWM) { | ||
1728 | DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n", | ||
1729 | fbc_wm, SNB_FBC_MAX_SRWM, level); | ||
1730 | |||
1731 | /* fbc has it's own way to disable FBC WM */ | ||
1732 | I915_WRITE(DISP_ARB_CTL, | ||
1733 | I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS); | ||
1734 | return false; | ||
1735 | } else if (INTEL_INFO(dev)->gen >= 6) { | ||
1736 | /* enable FBC WM (except on ILK, where it must remain off) */ | ||
1737 | I915_WRITE(DISP_ARB_CTL, | ||
1738 | I915_READ(DISP_ARB_CTL) & ~DISP_FBC_WM_DIS); | ||
1739 | } | ||
1740 | |||
1741 | if (display_wm > display->max_wm) { | ||
1742 | DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n", | ||
1743 | display_wm, SNB_DISPLAY_MAX_SRWM, level); | ||
1744 | return false; | ||
1745 | } | ||
1746 | |||
1747 | if (cursor_wm > cursor->max_wm) { | ||
1748 | DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n", | ||
1749 | cursor_wm, SNB_CURSOR_MAX_SRWM, level); | ||
1750 | return false; | ||
1751 | } | ||
1752 | |||
1753 | if (!(fbc_wm || display_wm || cursor_wm)) { | ||
1754 | DRM_DEBUG_KMS("latency %d is 0, disabling wm%d+\n", level, level); | ||
1755 | return false; | ||
1756 | } | ||
1757 | |||
1758 | return true; | ||
1759 | } | ||
1760 | |||
1761 | /* | ||
1762 | * Compute watermark values of WM[1-3], | ||
1763 | */ | ||
1764 | static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, | ||
1765 | int latency_ns, | ||
1766 | const struct intel_watermark_params *display, | ||
1767 | const struct intel_watermark_params *cursor, | ||
1768 | int *fbc_wm, int *display_wm, int *cursor_wm) | ||
1769 | { | ||
1770 | struct drm_crtc *crtc; | ||
1771 | const struct drm_display_mode *adjusted_mode; | ||
1772 | unsigned long line_time_us; | ||
1773 | int hdisplay, htotal, pixel_size, clock; | ||
1774 | int line_count, line_size; | ||
1775 | int small, large; | ||
1776 | int entries; | ||
1777 | |||
1778 | if (!latency_ns) { | ||
1779 | *fbc_wm = *display_wm = *cursor_wm = 0; | ||
1780 | return false; | ||
1781 | } | ||
1782 | |||
1783 | crtc = intel_get_crtc_for_plane(dev, plane); | ||
1784 | adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; | ||
1785 | clock = adjusted_mode->crtc_clock; | ||
1786 | htotal = adjusted_mode->htotal; | ||
1787 | hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; | ||
1788 | pixel_size = crtc->fb->bits_per_pixel / 8; | ||
1789 | |||
1790 | line_time_us = (htotal * 1000) / clock; | ||
1791 | line_count = (latency_ns / line_time_us + 1000) / 1000; | ||
1792 | line_size = hdisplay * pixel_size; | ||
1793 | |||
1794 | /* Use the minimum of the small and large buffer method for primary */ | ||
1795 | small = ((clock * pixel_size / 1000) * latency_ns) / 1000; | ||
1796 | large = line_count * line_size; | ||
1797 | |||
1798 | entries = DIV_ROUND_UP(min(small, large), display->cacheline_size); | ||
1799 | *display_wm = entries + display->guard_size; | ||
1800 | |||
1801 | /* | ||
1802 | * Spec says: | ||
1803 | * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2 | ||
1804 | */ | ||
1805 | *fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2; | ||
1806 | |||
1807 | /* calculate the self-refresh watermark for display cursor */ | ||
1808 | entries = line_count * pixel_size * 64; | ||
1809 | entries = DIV_ROUND_UP(entries, cursor->cacheline_size); | ||
1810 | *cursor_wm = entries + cursor->guard_size; | ||
1811 | |||
1812 | return ironlake_check_srwm(dev, level, | ||
1813 | *fbc_wm, *display_wm, *cursor_wm, | ||
1814 | display, cursor); | ||
1815 | } | ||
1816 | |||
1817 | static void ironlake_update_wm(struct drm_crtc *crtc) | ||
1818 | { | ||
1819 | struct drm_device *dev = crtc->dev; | ||
1820 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1821 | int fbc_wm, plane_wm, cursor_wm; | ||
1822 | unsigned int enabled; | ||
1823 | |||
1824 | enabled = 0; | ||
1825 | if (g4x_compute_wm0(dev, PIPE_A, | ||
1826 | &ironlake_display_wm_info, | ||
1827 | dev_priv->wm.pri_latency[0] * 100, | ||
1828 | &ironlake_cursor_wm_info, | ||
1829 | dev_priv->wm.cur_latency[0] * 100, | ||
1830 | &plane_wm, &cursor_wm)) { | ||
1831 | I915_WRITE(WM0_PIPEA_ILK, | ||
1832 | (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); | ||
1833 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" | ||
1834 | " plane %d, " "cursor: %d\n", | ||
1835 | plane_wm, cursor_wm); | ||
1836 | enabled |= 1 << PIPE_A; | ||
1837 | } | ||
1838 | |||
1839 | if (g4x_compute_wm0(dev, PIPE_B, | ||
1840 | &ironlake_display_wm_info, | ||
1841 | dev_priv->wm.pri_latency[0] * 100, | ||
1842 | &ironlake_cursor_wm_info, | ||
1843 | dev_priv->wm.cur_latency[0] * 100, | ||
1844 | &plane_wm, &cursor_wm)) { | ||
1845 | I915_WRITE(WM0_PIPEB_ILK, | ||
1846 | (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); | ||
1847 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" | ||
1848 | " plane %d, cursor: %d\n", | ||
1849 | plane_wm, cursor_wm); | ||
1850 | enabled |= 1 << PIPE_B; | ||
1851 | } | ||
1852 | |||
1853 | /* | ||
1854 | * Calculate and update the self-refresh watermark only when one | ||
1855 | * display plane is used. | ||
1856 | */ | ||
1857 | I915_WRITE(WM3_LP_ILK, 0); | ||
1858 | I915_WRITE(WM2_LP_ILK, 0); | ||
1859 | I915_WRITE(WM1_LP_ILK, 0); | ||
1860 | |||
1861 | if (!single_plane_enabled(enabled)) | ||
1862 | return; | ||
1863 | enabled = ffs(enabled) - 1; | ||
1864 | |||
1865 | /* WM1 */ | ||
1866 | if (!ironlake_compute_srwm(dev, 1, enabled, | ||
1867 | dev_priv->wm.pri_latency[1] * 500, | ||
1868 | &ironlake_display_srwm_info, | ||
1869 | &ironlake_cursor_srwm_info, | ||
1870 | &fbc_wm, &plane_wm, &cursor_wm)) | ||
1871 | return; | ||
1872 | |||
1873 | I915_WRITE(WM1_LP_ILK, | ||
1874 | WM1_LP_SR_EN | | ||
1875 | (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) | | ||
1876 | (fbc_wm << WM1_LP_FBC_SHIFT) | | ||
1877 | (plane_wm << WM1_LP_SR_SHIFT) | | ||
1878 | cursor_wm); | ||
1879 | |||
1880 | /* WM2 */ | ||
1881 | if (!ironlake_compute_srwm(dev, 2, enabled, | ||
1882 | dev_priv->wm.pri_latency[2] * 500, | ||
1883 | &ironlake_display_srwm_info, | ||
1884 | &ironlake_cursor_srwm_info, | ||
1885 | &fbc_wm, &plane_wm, &cursor_wm)) | ||
1886 | return; | ||
1887 | |||
1888 | I915_WRITE(WM2_LP_ILK, | ||
1889 | WM2_LP_EN | | ||
1890 | (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) | | ||
1891 | (fbc_wm << WM1_LP_FBC_SHIFT) | | ||
1892 | (plane_wm << WM1_LP_SR_SHIFT) | | ||
1893 | cursor_wm); | ||
1894 | |||
1895 | /* | ||
1896 | * WM3 is unsupported on ILK, probably because we don't have latency | ||
1897 | * data for that power state | ||
1898 | */ | ||
1899 | } | ||
1900 | |||
1901 | static void sandybridge_update_wm(struct drm_crtc *crtc) | ||
1902 | { | ||
1903 | struct drm_device *dev = crtc->dev; | ||
1904 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1905 | int latency = dev_priv->wm.pri_latency[0] * 100; /* In unit 0.1us */ | ||
1906 | u32 val; | ||
1907 | int fbc_wm, plane_wm, cursor_wm; | ||
1908 | unsigned int enabled; | ||
1909 | |||
1910 | enabled = 0; | ||
1911 | if (g4x_compute_wm0(dev, PIPE_A, | ||
1912 | &sandybridge_display_wm_info, latency, | ||
1913 | &sandybridge_cursor_wm_info, latency, | ||
1914 | &plane_wm, &cursor_wm)) { | ||
1915 | val = I915_READ(WM0_PIPEA_ILK); | ||
1916 | val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); | ||
1917 | I915_WRITE(WM0_PIPEA_ILK, val | | ||
1918 | ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); | ||
1919 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" | ||
1920 | " plane %d, " "cursor: %d\n", | ||
1921 | plane_wm, cursor_wm); | ||
1922 | enabled |= 1 << PIPE_A; | ||
1923 | } | ||
1924 | |||
1925 | if (g4x_compute_wm0(dev, PIPE_B, | ||
1926 | &sandybridge_display_wm_info, latency, | ||
1927 | &sandybridge_cursor_wm_info, latency, | ||
1928 | &plane_wm, &cursor_wm)) { | ||
1929 | val = I915_READ(WM0_PIPEB_ILK); | ||
1930 | val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); | ||
1931 | I915_WRITE(WM0_PIPEB_ILK, val | | ||
1932 | ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); | ||
1933 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" | ||
1934 | " plane %d, cursor: %d\n", | ||
1935 | plane_wm, cursor_wm); | ||
1936 | enabled |= 1 << PIPE_B; | ||
1937 | } | ||
1938 | |||
1939 | /* | ||
1940 | * Calculate and update the self-refresh watermark only when one | ||
1941 | * display plane is used. | ||
1942 | * | ||
1943 | * SNB support 3 levels of watermark. | ||
1944 | * | ||
1945 | * WM1/WM2/WM2 watermarks have to be enabled in the ascending order, | ||
1946 | * and disabled in the descending order | ||
1947 | * | ||
1948 | */ | ||
1949 | I915_WRITE(WM3_LP_ILK, 0); | ||
1950 | I915_WRITE(WM2_LP_ILK, 0); | ||
1951 | I915_WRITE(WM1_LP_ILK, 0); | ||
1952 | |||
1953 | if (!single_plane_enabled(enabled) || | ||
1954 | dev_priv->sprite_scaling_enabled) | ||
1955 | return; | ||
1956 | enabled = ffs(enabled) - 1; | ||
1957 | |||
1958 | /* WM1 */ | ||
1959 | if (!ironlake_compute_srwm(dev, 1, enabled, | ||
1960 | dev_priv->wm.pri_latency[1] * 500, | ||
1961 | &sandybridge_display_srwm_info, | ||
1962 | &sandybridge_cursor_srwm_info, | ||
1963 | &fbc_wm, &plane_wm, &cursor_wm)) | ||
1964 | return; | ||
1965 | |||
1966 | I915_WRITE(WM1_LP_ILK, | ||
1967 | WM1_LP_SR_EN | | ||
1968 | (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) | | ||
1969 | (fbc_wm << WM1_LP_FBC_SHIFT) | | ||
1970 | (plane_wm << WM1_LP_SR_SHIFT) | | ||
1971 | cursor_wm); | ||
1972 | |||
1973 | /* WM2 */ | ||
1974 | if (!ironlake_compute_srwm(dev, 2, enabled, | ||
1975 | dev_priv->wm.pri_latency[2] * 500, | ||
1976 | &sandybridge_display_srwm_info, | ||
1977 | &sandybridge_cursor_srwm_info, | ||
1978 | &fbc_wm, &plane_wm, &cursor_wm)) | ||
1979 | return; | ||
1980 | |||
1981 | I915_WRITE(WM2_LP_ILK, | ||
1982 | WM2_LP_EN | | ||
1983 | (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) | | ||
1984 | (fbc_wm << WM1_LP_FBC_SHIFT) | | ||
1985 | (plane_wm << WM1_LP_SR_SHIFT) | | ||
1986 | cursor_wm); | ||
1987 | |||
1988 | /* WM3 */ | ||
1989 | if (!ironlake_compute_srwm(dev, 3, enabled, | ||
1990 | dev_priv->wm.pri_latency[3] * 500, | ||
1991 | &sandybridge_display_srwm_info, | ||
1992 | &sandybridge_cursor_srwm_info, | ||
1993 | &fbc_wm, &plane_wm, &cursor_wm)) | ||
1994 | return; | ||
1995 | |||
1996 | I915_WRITE(WM3_LP_ILK, | ||
1997 | WM3_LP_EN | | ||
1998 | (dev_priv->wm.pri_latency[3] << WM1_LP_LATENCY_SHIFT) | | ||
1999 | (fbc_wm << WM1_LP_FBC_SHIFT) | | ||
2000 | (plane_wm << WM1_LP_SR_SHIFT) | | ||
2001 | cursor_wm); | ||
2002 | } | ||
2003 | |||
2004 | static void ivybridge_update_wm(struct drm_crtc *crtc) | ||
2005 | { | ||
2006 | struct drm_device *dev = crtc->dev; | ||
2007 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
2008 | int latency = dev_priv->wm.pri_latency[0] * 100; /* In unit 0.1us */ | ||
2009 | u32 val; | ||
2010 | int fbc_wm, plane_wm, cursor_wm; | ||
2011 | int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm; | ||
2012 | unsigned int enabled; | ||
2013 | |||
2014 | enabled = 0; | ||
2015 | if (g4x_compute_wm0(dev, PIPE_A, | ||
2016 | &sandybridge_display_wm_info, latency, | ||
2017 | &sandybridge_cursor_wm_info, latency, | ||
2018 | &plane_wm, &cursor_wm)) { | ||
2019 | val = I915_READ(WM0_PIPEA_ILK); | ||
2020 | val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); | ||
2021 | I915_WRITE(WM0_PIPEA_ILK, val | | ||
2022 | ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); | ||
2023 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" | ||
2024 | " plane %d, " "cursor: %d\n", | ||
2025 | plane_wm, cursor_wm); | ||
2026 | enabled |= 1 << PIPE_A; | ||
2027 | } | ||
2028 | |||
2029 | if (g4x_compute_wm0(dev, PIPE_B, | ||
2030 | &sandybridge_display_wm_info, latency, | ||
2031 | &sandybridge_cursor_wm_info, latency, | ||
2032 | &plane_wm, &cursor_wm)) { | ||
2033 | val = I915_READ(WM0_PIPEB_ILK); | ||
2034 | val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); | ||
2035 | I915_WRITE(WM0_PIPEB_ILK, val | | ||
2036 | ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); | ||
2037 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" | ||
2038 | " plane %d, cursor: %d\n", | ||
2039 | plane_wm, cursor_wm); | ||
2040 | enabled |= 1 << PIPE_B; | ||
2041 | } | ||
2042 | |||
2043 | if (g4x_compute_wm0(dev, PIPE_C, | ||
2044 | &sandybridge_display_wm_info, latency, | ||
2045 | &sandybridge_cursor_wm_info, latency, | ||
2046 | &plane_wm, &cursor_wm)) { | ||
2047 | val = I915_READ(WM0_PIPEC_IVB); | ||
2048 | val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); | ||
2049 | I915_WRITE(WM0_PIPEC_IVB, val | | ||
2050 | ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); | ||
2051 | DRM_DEBUG_KMS("FIFO watermarks For pipe C -" | ||
2052 | " plane %d, cursor: %d\n", | ||
2053 | plane_wm, cursor_wm); | ||
2054 | enabled |= 1 << PIPE_C; | ||
2055 | } | ||
2056 | |||
2057 | /* | ||
2058 | * Calculate and update the self-refresh watermark only when one | ||
2059 | * display plane is used. | ||
2060 | * | ||
2061 | * SNB support 3 levels of watermark. | ||
2062 | * | ||
2063 | * WM1/WM2/WM2 watermarks have to be enabled in the ascending order, | ||
2064 | * and disabled in the descending order | ||
2065 | * | ||
2066 | */ | ||
2067 | I915_WRITE(WM3_LP_ILK, 0); | ||
2068 | I915_WRITE(WM2_LP_ILK, 0); | ||
2069 | I915_WRITE(WM1_LP_ILK, 0); | ||
2070 | |||
2071 | if (!single_plane_enabled(enabled) || | ||
2072 | dev_priv->sprite_scaling_enabled) | ||
2073 | return; | ||
2074 | enabled = ffs(enabled) - 1; | ||
2075 | |||
2076 | /* WM1 */ | ||
2077 | if (!ironlake_compute_srwm(dev, 1, enabled, | ||
2078 | dev_priv->wm.pri_latency[1] * 500, | ||
2079 | &sandybridge_display_srwm_info, | ||
2080 | &sandybridge_cursor_srwm_info, | ||
2081 | &fbc_wm, &plane_wm, &cursor_wm)) | ||
2082 | return; | ||
2083 | |||
2084 | I915_WRITE(WM1_LP_ILK, | ||
2085 | WM1_LP_SR_EN | | ||
2086 | (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) | | ||
2087 | (fbc_wm << WM1_LP_FBC_SHIFT) | | ||
2088 | (plane_wm << WM1_LP_SR_SHIFT) | | ||
2089 | cursor_wm); | ||
2090 | |||
2091 | /* WM2 */ | ||
2092 | if (!ironlake_compute_srwm(dev, 2, enabled, | ||
2093 | dev_priv->wm.pri_latency[2] * 500, | ||
2094 | &sandybridge_display_srwm_info, | ||
2095 | &sandybridge_cursor_srwm_info, | ||
2096 | &fbc_wm, &plane_wm, &cursor_wm)) | ||
2097 | return; | ||
2098 | |||
2099 | I915_WRITE(WM2_LP_ILK, | ||
2100 | WM2_LP_EN | | ||
2101 | (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) | | ||
2102 | (fbc_wm << WM1_LP_FBC_SHIFT) | | ||
2103 | (plane_wm << WM1_LP_SR_SHIFT) | | ||
2104 | cursor_wm); | ||
2105 | |||
2106 | /* WM3, note we have to correct the cursor latency */ | ||
2107 | if (!ironlake_compute_srwm(dev, 3, enabled, | ||
2108 | dev_priv->wm.pri_latency[3] * 500, | ||
2109 | &sandybridge_display_srwm_info, | ||
2110 | &sandybridge_cursor_srwm_info, | ||
2111 | &fbc_wm, &plane_wm, &ignore_cursor_wm) || | ||
2112 | !ironlake_compute_srwm(dev, 3, enabled, | ||
2113 | dev_priv->wm.cur_latency[3] * 500, | ||
2114 | &sandybridge_display_srwm_info, | ||
2115 | &sandybridge_cursor_srwm_info, | ||
2116 | &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm)) | ||
2117 | return; | ||
2118 | |||
2119 | I915_WRITE(WM3_LP_ILK, | ||
2120 | WM3_LP_EN | | ||
2121 | (dev_priv->wm.pri_latency[3] << WM1_LP_LATENCY_SHIFT) | | ||
2122 | (fbc_wm << WM1_LP_FBC_SHIFT) | | ||
2123 | (plane_wm << WM1_LP_SR_SHIFT) | | ||
2124 | cursor_wm); | ||
2125 | } | ||
2126 | |||
2127 | static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev, | 1651 | static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev, |
2128 | struct drm_crtc *crtc) | 1652 | struct drm_crtc *crtc) |
2129 | { | 1653 | { |
@@ -3058,168 +2582,6 @@ static void haswell_update_sprite_wm(struct drm_plane *plane, | |||
3058 | haswell_update_wm(crtc); | 2582 | haswell_update_wm(crtc); |
3059 | } | 2583 | } |
3060 | 2584 | ||
3061 | static bool | ||
3062 | sandybridge_compute_sprite_wm(struct drm_device *dev, int plane, | ||
3063 | uint32_t sprite_width, int pixel_size, | ||
3064 | const struct intel_watermark_params *display, | ||
3065 | int display_latency_ns, int *sprite_wm) | ||
3066 | { | ||
3067 | struct drm_crtc *crtc; | ||
3068 | int clock; | ||
3069 | int entries, tlb_miss; | ||
3070 | |||
3071 | crtc = intel_get_crtc_for_plane(dev, plane); | ||
3072 | if (!intel_crtc_active(crtc)) { | ||
3073 | *sprite_wm = display->guard_size; | ||
3074 | return false; | ||
3075 | } | ||
3076 | |||
3077 | clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; | ||
3078 | |||
3079 | /* Use the small buffer method to calculate the sprite watermark */ | ||
3080 | entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; | ||
3081 | tlb_miss = display->fifo_size*display->cacheline_size - | ||
3082 | sprite_width * 8; | ||
3083 | if (tlb_miss > 0) | ||
3084 | entries += tlb_miss; | ||
3085 | entries = DIV_ROUND_UP(entries, display->cacheline_size); | ||
3086 | *sprite_wm = entries + display->guard_size; | ||
3087 | if (*sprite_wm > (int)display->max_wm) | ||
3088 | *sprite_wm = display->max_wm; | ||
3089 | |||
3090 | return true; | ||
3091 | } | ||
3092 | |||
3093 | static bool | ||
3094 | sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane, | ||
3095 | uint32_t sprite_width, int pixel_size, | ||
3096 | const struct intel_watermark_params *display, | ||
3097 | int latency_ns, int *sprite_wm) | ||
3098 | { | ||
3099 | struct drm_crtc *crtc; | ||
3100 | unsigned long line_time_us; | ||
3101 | int clock; | ||
3102 | int line_count, line_size; | ||
3103 | int small, large; | ||
3104 | int entries; | ||
3105 | |||
3106 | if (!latency_ns) { | ||
3107 | *sprite_wm = 0; | ||
3108 | return false; | ||
3109 | } | ||
3110 | |||
3111 | crtc = intel_get_crtc_for_plane(dev, plane); | ||
3112 | clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; | ||
3113 | if (!clock) { | ||
3114 | *sprite_wm = 0; | ||
3115 | return false; | ||
3116 | } | ||
3117 | |||
3118 | line_time_us = (sprite_width * 1000) / clock; | ||
3119 | if (!line_time_us) { | ||
3120 | *sprite_wm = 0; | ||
3121 | return false; | ||
3122 | } | ||
3123 | |||
3124 | line_count = (latency_ns / line_time_us + 1000) / 1000; | ||
3125 | line_size = sprite_width * pixel_size; | ||
3126 | |||
3127 | /* Use the minimum of the small and large buffer method for primary */ | ||
3128 | small = ((clock * pixel_size / 1000) * latency_ns) / 1000; | ||
3129 | large = line_count * line_size; | ||
3130 | |||
3131 | entries = DIV_ROUND_UP(min(small, large), display->cacheline_size); | ||
3132 | *sprite_wm = entries + display->guard_size; | ||
3133 | |||
3134 | return *sprite_wm > 0x3ff ? false : true; | ||
3135 | } | ||
3136 | |||
3137 | static void sandybridge_update_sprite_wm(struct drm_plane *plane, | ||
3138 | struct drm_crtc *crtc, | ||
3139 | uint32_t sprite_width, int pixel_size, | ||
3140 | bool enabled, bool scaled) | ||
3141 | { | ||
3142 | struct drm_device *dev = plane->dev; | ||
3143 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
3144 | int pipe = to_intel_plane(plane)->pipe; | ||
3145 | int latency = dev_priv->wm.spr_latency[0] * 100; /* In unit 0.1us */ | ||
3146 | u32 val; | ||
3147 | int sprite_wm, reg; | ||
3148 | int ret; | ||
3149 | |||
3150 | if (!enabled) | ||
3151 | return; | ||
3152 | |||
3153 | switch (pipe) { | ||
3154 | case 0: | ||
3155 | reg = WM0_PIPEA_ILK; | ||
3156 | break; | ||
3157 | case 1: | ||
3158 | reg = WM0_PIPEB_ILK; | ||
3159 | break; | ||
3160 | case 2: | ||
3161 | reg = WM0_PIPEC_IVB; | ||
3162 | break; | ||
3163 | default: | ||
3164 | return; /* bad pipe */ | ||
3165 | } | ||
3166 | |||
3167 | ret = sandybridge_compute_sprite_wm(dev, pipe, sprite_width, pixel_size, | ||
3168 | &sandybridge_display_wm_info, | ||
3169 | latency, &sprite_wm); | ||
3170 | if (!ret) { | ||
3171 | DRM_DEBUG_KMS("failed to compute sprite wm for pipe %c\n", | ||
3172 | pipe_name(pipe)); | ||
3173 | return; | ||
3174 | } | ||
3175 | |||
3176 | val = I915_READ(reg); | ||
3177 | val &= ~WM0_PIPE_SPRITE_MASK; | ||
3178 | I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT)); | ||
3179 | DRM_DEBUG_KMS("sprite watermarks For pipe %c - %d\n", pipe_name(pipe), sprite_wm); | ||
3180 | |||
3181 | |||
3182 | ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, | ||
3183 | pixel_size, | ||
3184 | &sandybridge_display_srwm_info, | ||
3185 | dev_priv->wm.spr_latency[1] * 500, | ||
3186 | &sprite_wm); | ||
3187 | if (!ret) { | ||
3188 | DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %c\n", | ||
3189 | pipe_name(pipe)); | ||
3190 | return; | ||
3191 | } | ||
3192 | I915_WRITE(WM1S_LP_ILK, sprite_wm); | ||
3193 | |||
3194 | /* Only IVB has two more LP watermarks for sprite */ | ||
3195 | if (!IS_IVYBRIDGE(dev)) | ||
3196 | return; | ||
3197 | |||
3198 | ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, | ||
3199 | pixel_size, | ||
3200 | &sandybridge_display_srwm_info, | ||
3201 | dev_priv->wm.spr_latency[2] * 500, | ||
3202 | &sprite_wm); | ||
3203 | if (!ret) { | ||
3204 | DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %c\n", | ||
3205 | pipe_name(pipe)); | ||
3206 | return; | ||
3207 | } | ||
3208 | I915_WRITE(WM2S_LP_IVB, sprite_wm); | ||
3209 | |||
3210 | ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, | ||
3211 | pixel_size, | ||
3212 | &sandybridge_display_srwm_info, | ||
3213 | dev_priv->wm.spr_latency[3] * 500, | ||
3214 | &sprite_wm); | ||
3215 | if (!ret) { | ||
3216 | DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %c\n", | ||
3217 | pipe_name(pipe)); | ||
3218 | return; | ||
3219 | } | ||
3220 | I915_WRITE(WM3S_LP_IVB, sprite_wm); | ||
3221 | } | ||
3222 | |||
3223 | static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) | 2585 | static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) |
3224 | { | 2586 | { |
3225 | struct drm_device *dev = crtc->dev; | 2587 | struct drm_device *dev = crtc->dev; |
@@ -6184,9 +5546,11 @@ void intel_init_pm(struct drm_device *dev) | |||
6184 | if (IS_GEN5(dev)) { | 5546 | if (IS_GEN5(dev)) { |
6185 | if (dev_priv->wm.pri_latency[1] && | 5547 | if (dev_priv->wm.pri_latency[1] && |
6186 | dev_priv->wm.spr_latency[1] && | 5548 | dev_priv->wm.spr_latency[1] && |
6187 | dev_priv->wm.cur_latency[1]) | 5549 | dev_priv->wm.cur_latency[1]) { |
6188 | dev_priv->display.update_wm = ironlake_update_wm; | 5550 | dev_priv->display.update_wm = haswell_update_wm; |
6189 | else { | 5551 | dev_priv->display.update_sprite_wm = |
5552 | haswell_update_sprite_wm; | ||
5553 | } else { | ||
6190 | DRM_DEBUG_KMS("Failed to get proper latency. " | 5554 | DRM_DEBUG_KMS("Failed to get proper latency. " |
6191 | "Disable CxSR\n"); | 5555 | "Disable CxSR\n"); |
6192 | dev_priv->display.update_wm = NULL; | 5556 | dev_priv->display.update_wm = NULL; |
@@ -6196,8 +5560,9 @@ void intel_init_pm(struct drm_device *dev) | |||
6196 | if (dev_priv->wm.pri_latency[0] && | 5560 | if (dev_priv->wm.pri_latency[0] && |
6197 | dev_priv->wm.spr_latency[0] && | 5561 | dev_priv->wm.spr_latency[0] && |
6198 | dev_priv->wm.cur_latency[0]) { | 5562 | dev_priv->wm.cur_latency[0]) { |
6199 | dev_priv->display.update_wm = sandybridge_update_wm; | 5563 | dev_priv->display.update_wm = haswell_update_wm; |
6200 | dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; | 5564 | dev_priv->display.update_sprite_wm = |
5565 | haswell_update_sprite_wm; | ||
6201 | } else { | 5566 | } else { |
6202 | DRM_DEBUG_KMS("Failed to read display plane latency. " | 5567 | DRM_DEBUG_KMS("Failed to read display plane latency. " |
6203 | "Disable CxSR\n"); | 5568 | "Disable CxSR\n"); |
@@ -6208,8 +5573,9 @@ void intel_init_pm(struct drm_device *dev) | |||
6208 | if (dev_priv->wm.pri_latency[0] && | 5573 | if (dev_priv->wm.pri_latency[0] && |
6209 | dev_priv->wm.spr_latency[0] && | 5574 | dev_priv->wm.spr_latency[0] && |
6210 | dev_priv->wm.cur_latency[0]) { | 5575 | dev_priv->wm.cur_latency[0]) { |
6211 | dev_priv->display.update_wm = ivybridge_update_wm; | 5576 | dev_priv->display.update_wm = haswell_update_wm; |
6212 | dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; | 5577 | dev_priv->display.update_sprite_wm = |
5578 | haswell_update_sprite_wm; | ||
6213 | } else { | 5579 | } else { |
6214 | DRM_DEBUG_KMS("Failed to read display plane latency. " | 5580 | DRM_DEBUG_KMS("Failed to read display plane latency. " |
6215 | "Disable CxSR\n"); | 5581 | "Disable CxSR\n"); |