diff options
author | Jerome Glisse <jglisse@redhat.com> | 2009-07-13 15:04:08 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-07-29 01:45:09 -0400 |
commit | c93bb85b5cba3e3a06f2cad8e9bc5c23d3d10aac (patch) | |
tree | 3168bee69e08dcb1f0f509b03ea1693a688d34ef /drivers/gpu/drm/radeon/r100.c | |
parent | e024e11070a0a0dc7163ce1ec2da354a638bdbed (diff) |
drm/radeon/kms: fix bandwidth computation on avivo hardware
Fix bandwidth computation and crtc priority in memory controller
so that crtc memory request are fullfill in time to avoid display
artifact.
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 483 |
1 files changed, 483 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 69bd7cb59972..0e00fef0b84f 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -1784,3 +1784,486 @@ void r100_clear_surface_reg(struct radeon_device *rdev, int reg) | |||
1784 | int surf_index = reg * 16; | 1784 | int surf_index = reg * 16; |
1785 | WREG32(RADEON_SURFACE0_INFO + surf_index, 0); | 1785 | WREG32(RADEON_SURFACE0_INFO + surf_index, 0); |
1786 | } | 1786 | } |
1787 | |||
1788 | void r100_bandwidth_update(struct radeon_device *rdev) | ||
1789 | { | ||
1790 | fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; | ||
1791 | fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; | ||
1792 | fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; | ||
1793 | uint32_t temp, data, mem_trcd, mem_trp, mem_tras; | ||
1794 | fixed20_12 memtcas_ff[8] = { | ||
1795 | fixed_init(1), | ||
1796 | fixed_init(2), | ||
1797 | fixed_init(3), | ||
1798 | fixed_init(0), | ||
1799 | fixed_init_half(1), | ||
1800 | fixed_init_half(2), | ||
1801 | fixed_init(0), | ||
1802 | }; | ||
1803 | fixed20_12 memtcas_rs480_ff[8] = { | ||
1804 | fixed_init(0), | ||
1805 | fixed_init(1), | ||
1806 | fixed_init(2), | ||
1807 | fixed_init(3), | ||
1808 | fixed_init(0), | ||
1809 | fixed_init_half(1), | ||
1810 | fixed_init_half(2), | ||
1811 | fixed_init_half(3), | ||
1812 | }; | ||
1813 | fixed20_12 memtcas2_ff[8] = { | ||
1814 | fixed_init(0), | ||
1815 | fixed_init(1), | ||
1816 | fixed_init(2), | ||
1817 | fixed_init(3), | ||
1818 | fixed_init(4), | ||
1819 | fixed_init(5), | ||
1820 | fixed_init(6), | ||
1821 | fixed_init(7), | ||
1822 | }; | ||
1823 | fixed20_12 memtrbs[8] = { | ||
1824 | fixed_init(1), | ||
1825 | fixed_init_half(1), | ||
1826 | fixed_init(2), | ||
1827 | fixed_init_half(2), | ||
1828 | fixed_init(3), | ||
1829 | fixed_init_half(3), | ||
1830 | fixed_init(4), | ||
1831 | fixed_init_half(4) | ||
1832 | }; | ||
1833 | fixed20_12 memtrbs_r4xx[8] = { | ||
1834 | fixed_init(4), | ||
1835 | fixed_init(5), | ||
1836 | fixed_init(6), | ||
1837 | fixed_init(7), | ||
1838 | fixed_init(8), | ||
1839 | fixed_init(9), | ||
1840 | fixed_init(10), | ||
1841 | fixed_init(11) | ||
1842 | }; | ||
1843 | fixed20_12 min_mem_eff; | ||
1844 | fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; | ||
1845 | fixed20_12 cur_latency_mclk, cur_latency_sclk; | ||
1846 | fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, | ||
1847 | disp_drain_rate2, read_return_rate; | ||
1848 | fixed20_12 time_disp1_drop_priority; | ||
1849 | int c; | ||
1850 | int cur_size = 16; /* in octawords */ | ||
1851 | int critical_point = 0, critical_point2; | ||
1852 | /* uint32_t read_return_rate, time_disp1_drop_priority; */ | ||
1853 | int stop_req, max_stop_req; | ||
1854 | struct drm_display_mode *mode1 = NULL; | ||
1855 | struct drm_display_mode *mode2 = NULL; | ||
1856 | uint32_t pixel_bytes1 = 0; | ||
1857 | uint32_t pixel_bytes2 = 0; | ||
1858 | |||
1859 | if (rdev->mode_info.crtcs[0]->base.enabled) { | ||
1860 | mode1 = &rdev->mode_info.crtcs[0]->base.mode; | ||
1861 | pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; | ||
1862 | } | ||
1863 | if (rdev->mode_info.crtcs[1]->base.enabled) { | ||
1864 | mode2 = &rdev->mode_info.crtcs[1]->base.mode; | ||
1865 | pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; | ||
1866 | } | ||
1867 | |||
1868 | min_mem_eff.full = rfixed_const_8(0); | ||
1869 | /* get modes */ | ||
1870 | if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { | ||
1871 | uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); | ||
1872 | mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); | ||
1873 | mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); | ||
1874 | /* check crtc enables */ | ||
1875 | if (mode2) | ||
1876 | mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); | ||
1877 | if (mode1) | ||
1878 | mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); | ||
1879 | WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); | ||
1880 | } | ||
1881 | |||
1882 | /* | ||
1883 | * determine is there is enough bw for current mode | ||
1884 | */ | ||
1885 | mclk_ff.full = rfixed_const(rdev->clock.default_mclk); | ||
1886 | temp_ff.full = rfixed_const(100); | ||
1887 | mclk_ff.full = rfixed_div(mclk_ff, temp_ff); | ||
1888 | sclk_ff.full = rfixed_const(rdev->clock.default_sclk); | ||
1889 | sclk_ff.full = rfixed_div(sclk_ff, temp_ff); | ||
1890 | |||
1891 | temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); | ||
1892 | temp_ff.full = rfixed_const(temp); | ||
1893 | mem_bw.full = rfixed_mul(mclk_ff, temp_ff); | ||
1894 | |||
1895 | pix_clk.full = 0; | ||
1896 | pix_clk2.full = 0; | ||
1897 | peak_disp_bw.full = 0; | ||
1898 | if (mode1) { | ||
1899 | temp_ff.full = rfixed_const(1000); | ||
1900 | pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ | ||
1901 | pix_clk.full = rfixed_div(pix_clk, temp_ff); | ||
1902 | temp_ff.full = rfixed_const(pixel_bytes1); | ||
1903 | peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); | ||
1904 | } | ||
1905 | if (mode2) { | ||
1906 | temp_ff.full = rfixed_const(1000); | ||
1907 | pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ | ||
1908 | pix_clk2.full = rfixed_div(pix_clk2, temp_ff); | ||
1909 | temp_ff.full = rfixed_const(pixel_bytes2); | ||
1910 | peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); | ||
1911 | } | ||
1912 | |||
1913 | mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); | ||
1914 | if (peak_disp_bw.full >= mem_bw.full) { | ||
1915 | DRM_ERROR("You may not have enough display bandwidth for current mode\n" | ||
1916 | "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); | ||
1917 | } | ||
1918 | |||
1919 | /* Get values from the EXT_MEM_CNTL register...converting its contents. */ | ||
1920 | temp = RREG32(RADEON_MEM_TIMING_CNTL); | ||
1921 | if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ | ||
1922 | mem_trcd = ((temp >> 2) & 0x3) + 1; | ||
1923 | mem_trp = ((temp & 0x3)) + 1; | ||
1924 | mem_tras = ((temp & 0x70) >> 4) + 1; | ||
1925 | } else if (rdev->family == CHIP_R300 || | ||
1926 | rdev->family == CHIP_R350) { /* r300, r350 */ | ||
1927 | mem_trcd = (temp & 0x7) + 1; | ||
1928 | mem_trp = ((temp >> 8) & 0x7) + 1; | ||
1929 | mem_tras = ((temp >> 11) & 0xf) + 4; | ||
1930 | } else if (rdev->family == CHIP_RV350 || | ||
1931 | rdev->family <= CHIP_RV380) { | ||
1932 | /* rv3x0 */ | ||
1933 | mem_trcd = (temp & 0x7) + 3; | ||
1934 | mem_trp = ((temp >> 8) & 0x7) + 3; | ||
1935 | mem_tras = ((temp >> 11) & 0xf) + 6; | ||
1936 | } else if (rdev->family == CHIP_R420 || | ||
1937 | rdev->family == CHIP_R423 || | ||
1938 | rdev->family == CHIP_RV410) { | ||
1939 | /* r4xx */ | ||
1940 | mem_trcd = (temp & 0xf) + 3; | ||
1941 | if (mem_trcd > 15) | ||
1942 | mem_trcd = 15; | ||
1943 | mem_trp = ((temp >> 8) & 0xf) + 3; | ||
1944 | if (mem_trp > 15) | ||
1945 | mem_trp = 15; | ||
1946 | mem_tras = ((temp >> 12) & 0x1f) + 6; | ||
1947 | if (mem_tras > 31) | ||
1948 | mem_tras = 31; | ||
1949 | } else { /* RV200, R200 */ | ||
1950 | mem_trcd = (temp & 0x7) + 1; | ||
1951 | mem_trp = ((temp >> 8) & 0x7) + 1; | ||
1952 | mem_tras = ((temp >> 12) & 0xf) + 4; | ||
1953 | } | ||
1954 | /* convert to FF */ | ||
1955 | trcd_ff.full = rfixed_const(mem_trcd); | ||
1956 | trp_ff.full = rfixed_const(mem_trp); | ||
1957 | tras_ff.full = rfixed_const(mem_tras); | ||
1958 | |||
1959 | /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ | ||
1960 | temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); | ||
1961 | data = (temp & (7 << 20)) >> 20; | ||
1962 | if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { | ||
1963 | if (rdev->family == CHIP_RS480) /* don't think rs400 */ | ||
1964 | tcas_ff = memtcas_rs480_ff[data]; | ||
1965 | else | ||
1966 | tcas_ff = memtcas_ff[data]; | ||
1967 | } else | ||
1968 | tcas_ff = memtcas2_ff[data]; | ||
1969 | |||
1970 | if (rdev->family == CHIP_RS400 || | ||
1971 | rdev->family == CHIP_RS480) { | ||
1972 | /* extra cas latency stored in bits 23-25 0-4 clocks */ | ||
1973 | data = (temp >> 23) & 0x7; | ||
1974 | if (data < 5) | ||
1975 | tcas_ff.full += rfixed_const(data); | ||
1976 | } | ||
1977 | |||
1978 | if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { | ||
1979 | /* on the R300, Tcas is included in Trbs. | ||
1980 | */ | ||
1981 | temp = RREG32(RADEON_MEM_CNTL); | ||
1982 | data = (R300_MEM_NUM_CHANNELS_MASK & temp); | ||
1983 | if (data == 1) { | ||
1984 | if (R300_MEM_USE_CD_CH_ONLY & temp) { | ||
1985 | temp = RREG32(R300_MC_IND_INDEX); | ||
1986 | temp &= ~R300_MC_IND_ADDR_MASK; | ||
1987 | temp |= R300_MC_READ_CNTL_CD_mcind; | ||
1988 | WREG32(R300_MC_IND_INDEX, temp); | ||
1989 | temp = RREG32(R300_MC_IND_DATA); | ||
1990 | data = (R300_MEM_RBS_POSITION_C_MASK & temp); | ||
1991 | } else { | ||
1992 | temp = RREG32(R300_MC_READ_CNTL_AB); | ||
1993 | data = (R300_MEM_RBS_POSITION_A_MASK & temp); | ||
1994 | } | ||
1995 | } else { | ||
1996 | temp = RREG32(R300_MC_READ_CNTL_AB); | ||
1997 | data = (R300_MEM_RBS_POSITION_A_MASK & temp); | ||
1998 | } | ||
1999 | if (rdev->family == CHIP_RV410 || | ||
2000 | rdev->family == CHIP_R420 || | ||
2001 | rdev->family == CHIP_R423) | ||
2002 | trbs_ff = memtrbs_r4xx[data]; | ||
2003 | else | ||
2004 | trbs_ff = memtrbs[data]; | ||
2005 | tcas_ff.full += trbs_ff.full; | ||
2006 | } | ||
2007 | |||
2008 | sclk_eff_ff.full = sclk_ff.full; | ||
2009 | |||
2010 | if (rdev->flags & RADEON_IS_AGP) { | ||
2011 | fixed20_12 agpmode_ff; | ||
2012 | agpmode_ff.full = rfixed_const(radeon_agpmode); | ||
2013 | temp_ff.full = rfixed_const_666(16); | ||
2014 | sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff); | ||
2015 | } | ||
2016 | /* TODO PCIE lanes may affect this - agpmode == 16?? */ | ||
2017 | |||
2018 | if (ASIC_IS_R300(rdev)) { | ||
2019 | sclk_delay_ff.full = rfixed_const(250); | ||
2020 | } else { | ||
2021 | if ((rdev->family == CHIP_RV100) || | ||
2022 | rdev->flags & RADEON_IS_IGP) { | ||
2023 | if (rdev->mc.vram_is_ddr) | ||
2024 | sclk_delay_ff.full = rfixed_const(41); | ||
2025 | else | ||
2026 | sclk_delay_ff.full = rfixed_const(33); | ||
2027 | } else { | ||
2028 | if (rdev->mc.vram_width == 128) | ||
2029 | sclk_delay_ff.full = rfixed_const(57); | ||
2030 | else | ||
2031 | sclk_delay_ff.full = rfixed_const(41); | ||
2032 | } | ||
2033 | } | ||
2034 | |||
2035 | mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff); | ||
2036 | |||
2037 | if (rdev->mc.vram_is_ddr) { | ||
2038 | if (rdev->mc.vram_width == 32) { | ||
2039 | k1.full = rfixed_const(40); | ||
2040 | c = 3; | ||
2041 | } else { | ||
2042 | k1.full = rfixed_const(20); | ||
2043 | c = 1; | ||
2044 | } | ||
2045 | } else { | ||
2046 | k1.full = rfixed_const(40); | ||
2047 | c = 3; | ||
2048 | } | ||
2049 | |||
2050 | temp_ff.full = rfixed_const(2); | ||
2051 | mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff); | ||
2052 | temp_ff.full = rfixed_const(c); | ||
2053 | mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff); | ||
2054 | temp_ff.full = rfixed_const(4); | ||
2055 | mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff); | ||
2056 | mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff); | ||
2057 | mc_latency_mclk.full += k1.full; | ||
2058 | |||
2059 | mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff); | ||
2060 | mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff); | ||
2061 | |||
2062 | /* | ||
2063 | HW cursor time assuming worst case of full size colour cursor. | ||
2064 | */ | ||
2065 | temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); | ||
2066 | temp_ff.full += trcd_ff.full; | ||
2067 | if (temp_ff.full < tras_ff.full) | ||
2068 | temp_ff.full = tras_ff.full; | ||
2069 | cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff); | ||
2070 | |||
2071 | temp_ff.full = rfixed_const(cur_size); | ||
2072 | cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff); | ||
2073 | /* | ||
2074 | Find the total latency for the display data. | ||
2075 | */ | ||
2076 | disp_latency_overhead.full = rfixed_const(80); | ||
2077 | disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff); | ||
2078 | mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; | ||
2079 | mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; | ||
2080 | |||
2081 | if (mc_latency_mclk.full > mc_latency_sclk.full) | ||
2082 | disp_latency.full = mc_latency_mclk.full; | ||
2083 | else | ||
2084 | disp_latency.full = mc_latency_sclk.full; | ||
2085 | |||
2086 | /* setup Max GRPH_STOP_REQ default value */ | ||
2087 | if (ASIC_IS_RV100(rdev)) | ||
2088 | max_stop_req = 0x5c; | ||
2089 | else | ||
2090 | max_stop_req = 0x7c; | ||
2091 | |||
2092 | if (mode1) { | ||
2093 | /* CRTC1 | ||
2094 | Set GRPH_BUFFER_CNTL register using h/w defined optimal values. | ||
2095 | GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] | ||
2096 | */ | ||
2097 | stop_req = mode1->hdisplay * pixel_bytes1 / 16; | ||
2098 | |||
2099 | if (stop_req > max_stop_req) | ||
2100 | stop_req = max_stop_req; | ||
2101 | |||
2102 | /* | ||
2103 | Find the drain rate of the display buffer. | ||
2104 | */ | ||
2105 | temp_ff.full = rfixed_const((16/pixel_bytes1)); | ||
2106 | disp_drain_rate.full = rfixed_div(pix_clk, temp_ff); | ||
2107 | |||
2108 | /* | ||
2109 | Find the critical point of the display buffer. | ||
2110 | */ | ||
2111 | crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency); | ||
2112 | crit_point_ff.full += rfixed_const_half(0); | ||
2113 | |||
2114 | critical_point = rfixed_trunc(crit_point_ff); | ||
2115 | |||
2116 | if (rdev->disp_priority == 2) { | ||
2117 | critical_point = 0; | ||
2118 | } | ||
2119 | |||
2120 | /* | ||
2121 | The critical point should never be above max_stop_req-4. Setting | ||
2122 | GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. | ||
2123 | */ | ||
2124 | if (max_stop_req - critical_point < 4) | ||
2125 | critical_point = 0; | ||
2126 | |||
2127 | if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { | ||
2128 | /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ | ||
2129 | critical_point = 0x10; | ||
2130 | } | ||
2131 | |||
2132 | temp = RREG32(RADEON_GRPH_BUFFER_CNTL); | ||
2133 | temp &= ~(RADEON_GRPH_STOP_REQ_MASK); | ||
2134 | temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); | ||
2135 | temp &= ~(RADEON_GRPH_START_REQ_MASK); | ||
2136 | if ((rdev->family == CHIP_R350) && | ||
2137 | (stop_req > 0x15)) { | ||
2138 | stop_req -= 0x10; | ||
2139 | } | ||
2140 | temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); | ||
2141 | temp |= RADEON_GRPH_BUFFER_SIZE; | ||
2142 | temp &= ~(RADEON_GRPH_CRITICAL_CNTL | | ||
2143 | RADEON_GRPH_CRITICAL_AT_SOF | | ||
2144 | RADEON_GRPH_STOP_CNTL); | ||
2145 | /* | ||
2146 | Write the result into the register. | ||
2147 | */ | ||
2148 | WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | | ||
2149 | (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); | ||
2150 | |||
2151 | #if 0 | ||
2152 | if ((rdev->family == CHIP_RS400) || | ||
2153 | (rdev->family == CHIP_RS480)) { | ||
2154 | /* attempt to program RS400 disp regs correctly ??? */ | ||
2155 | temp = RREG32(RS400_DISP1_REG_CNTL); | ||
2156 | temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | | ||
2157 | RS400_DISP1_STOP_REQ_LEVEL_MASK); | ||
2158 | WREG32(RS400_DISP1_REQ_CNTL1, (temp | | ||
2159 | (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | | ||
2160 | (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); | ||
2161 | temp = RREG32(RS400_DMIF_MEM_CNTL1); | ||
2162 | temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | | ||
2163 | RS400_DISP1_CRITICAL_POINT_STOP_MASK); | ||
2164 | WREG32(RS400_DMIF_MEM_CNTL1, (temp | | ||
2165 | (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | | ||
2166 | (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); | ||
2167 | } | ||
2168 | #endif | ||
2169 | |||
2170 | DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n", | ||
2171 | /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ | ||
2172 | (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); | ||
2173 | } | ||
2174 | |||
2175 | if (mode2) { | ||
2176 | u32 grph2_cntl; | ||
2177 | stop_req = mode2->hdisplay * pixel_bytes2 / 16; | ||
2178 | |||
2179 | if (stop_req > max_stop_req) | ||
2180 | stop_req = max_stop_req; | ||
2181 | |||
2182 | /* | ||
2183 | Find the drain rate of the display buffer. | ||
2184 | */ | ||
2185 | temp_ff.full = rfixed_const((16/pixel_bytes2)); | ||
2186 | disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff); | ||
2187 | |||
2188 | grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); | ||
2189 | grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); | ||
2190 | grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); | ||
2191 | grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); | ||
2192 | if ((rdev->family == CHIP_R350) && | ||
2193 | (stop_req > 0x15)) { | ||
2194 | stop_req -= 0x10; | ||
2195 | } | ||
2196 | grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); | ||
2197 | grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; | ||
2198 | grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | | ||
2199 | RADEON_GRPH_CRITICAL_AT_SOF | | ||
2200 | RADEON_GRPH_STOP_CNTL); | ||
2201 | |||
2202 | if ((rdev->family == CHIP_RS100) || | ||
2203 | (rdev->family == CHIP_RS200)) | ||
2204 | critical_point2 = 0; | ||
2205 | else { | ||
2206 | temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; | ||
2207 | temp_ff.full = rfixed_const(temp); | ||
2208 | temp_ff.full = rfixed_mul(mclk_ff, temp_ff); | ||
2209 | if (sclk_ff.full < temp_ff.full) | ||
2210 | temp_ff.full = sclk_ff.full; | ||
2211 | |||
2212 | read_return_rate.full = temp_ff.full; | ||
2213 | |||
2214 | if (mode1) { | ||
2215 | temp_ff.full = read_return_rate.full - disp_drain_rate.full; | ||
2216 | time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff); | ||
2217 | } else { | ||
2218 | time_disp1_drop_priority.full = 0; | ||
2219 | } | ||
2220 | crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; | ||
2221 | crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2); | ||
2222 | crit_point_ff.full += rfixed_const_half(0); | ||
2223 | |||
2224 | critical_point2 = rfixed_trunc(crit_point_ff); | ||
2225 | |||
2226 | if (rdev->disp_priority == 2) { | ||
2227 | critical_point2 = 0; | ||
2228 | } | ||
2229 | |||
2230 | if (max_stop_req - critical_point2 < 4) | ||
2231 | critical_point2 = 0; | ||
2232 | |||
2233 | } | ||
2234 | |||
2235 | if (critical_point2 == 0 && rdev->family == CHIP_R300) { | ||
2236 | /* some R300 cards have problem with this set to 0 */ | ||
2237 | critical_point2 = 0x10; | ||
2238 | } | ||
2239 | |||
2240 | WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | | ||
2241 | (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); | ||
2242 | |||
2243 | if ((rdev->family == CHIP_RS400) || | ||
2244 | (rdev->family == CHIP_RS480)) { | ||
2245 | #if 0 | ||
2246 | /* attempt to program RS400 disp2 regs correctly ??? */ | ||
2247 | temp = RREG32(RS400_DISP2_REQ_CNTL1); | ||
2248 | temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | | ||
2249 | RS400_DISP2_STOP_REQ_LEVEL_MASK); | ||
2250 | WREG32(RS400_DISP2_REQ_CNTL1, (temp | | ||
2251 | (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | | ||
2252 | (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); | ||
2253 | temp = RREG32(RS400_DISP2_REQ_CNTL2); | ||
2254 | temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | | ||
2255 | RS400_DISP2_CRITICAL_POINT_STOP_MASK); | ||
2256 | WREG32(RS400_DISP2_REQ_CNTL2, (temp | | ||
2257 | (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | | ||
2258 | (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); | ||
2259 | #endif | ||
2260 | WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); | ||
2261 | WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); | ||
2262 | WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); | ||
2263 | WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); | ||
2264 | } | ||
2265 | |||
2266 | DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n", | ||
2267 | (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); | ||
2268 | } | ||
2269 | } | ||