aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_pm.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2013-12-05 08:51:38 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-12-17 07:17:56 -0500
commit96f90c5421aaaba35ffd931728fabeb8f6cd8471 (patch)
tree3842175affd2c8cb7c6cc37250656824f5f24ff2 /drivers/gpu/drm/i915/intel_pm.c
parent017636cc09e2c58bc493cc1fe74d858f50d173af (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.c656
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
968static 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};
975static 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};
982static 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};
989static 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
997static 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};
1004static 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};
1011static 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};
1018static 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 */
1717static 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 */
1764static 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
1817static 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
1901static 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
2004static 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
2127static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev, 1651static 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
3061static bool
3062sandybridge_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
3093static bool
3094sandybridge_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
3137static 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
3223static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) 2585static 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");