diff options
author | Adam Jackson <ajax@redhat.com> | 2007-12-19 19:15:19 -0500 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2007-12-19 19:15:19 -0500 |
commit | fb7a4e24f2da3561ef81371ca4013a4f13806e91 (patch) | |
tree | 0b9456244f99be090569c69401640f3b6c34666b | |
parent | c1b0b69cc50516c3b7e881b0eb46cb3cd2e9dce6 (diff) |
Fix RN50 mode filtering.
The old code would attempt to limit the maximum pixel size of the screen
by limiting the maximum PLL frequency. This ends up confusing the PLL
computation code since sometimes your maximum freq can be lower than your
minimum freq. More to the point it's just wrong, maximum PLL frequency
isn't the same thing as maximum pixel clock, and even that isn't the same
thing as maximum scanout pixels per second.
The correct thing to do is filter by the mode's effective memory bandwidth.
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | src/radeon.h | 6 | ||||
-rw-r--r-- | src/radeon_driver.c | 46 | ||||
-rw-r--r-- | src/radeon_output.c | 13 |
4 files changed, 58 insertions, 12 deletions
diff --git a/configure.ac b/configure.ac index 1570e54c..cc4d490a 100644 --- a/configure.ac +++ b/configure.ac @@ -204,6 +204,11 @@ AC_CHECK_DECL(xf86XVFillKeyHelperDrawable, [], [#include <xf86xv.h>]) +AC_CHECK_DECL(xf86ModeBandwidth, + [AC_DEFINE(HAVE_XF86MODEBANDWIDTH, 1, [Have xf86ModeBandwidth prototype])], + [], + [#include "xf86Modes.h"]) + AC_CHECK_DECL(XSERVER_LIBPCIACCESS, [XSERVER_LIBPCIACCESS=yes],[XSERVER_LIBPCIACCESS=no], [#include "xorg-server.h"]) diff --git a/src/radeon.h b/src/radeon.h index 03db3604..801d616a 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -41,6 +41,7 @@ #include <unistd.h> /* For usleep() */ #include <sys/time.h> /* For gettimeofday() */ +#include "config.h" #include "xf86str.h" #include "compiler.h" #include "xf86fbman.h" @@ -97,6 +98,11 @@ #define MIN(a,b) ((a)>(b)?(b):(a)) #endif +#ifndef HAVE_XF86MODEBANDWIDTH +extern unsigned int xf86ModeBandwidth(DisplayModePtr mode, int depth); +#define MODE_BANDWIDTH MODE_BAD +#endif + typedef enum { OPTION_NOACCEL, OPTION_SW_CURSOR, diff --git a/src/radeon_driver.c b/src/radeon_driver.c index 25b21191..9f9fd901 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -1051,18 +1051,6 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn) info->mclk = 200.00; } - if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) { - /* Avoid RN50 corruption due to memory bandwidth starvation. - * 18 is an empirical value based on the databook and Windows driver. - * - * Empirical value changed to 24 to raise pixel clock limit and - * allow higher resolution modes on capable monitors - */ - pll->max_pll_freq = min(pll->max_pll_freq, - 24 * info->mclk * 100 / pScrn->bitsPerPixel * - info->RamWidth / 16); - } - /* card limits for computing PLLs */ pll->min_ref_div = 2; pll->max_ref_div = 0x3ff; @@ -5380,10 +5368,44 @@ Bool RADEONHandleMessage(int scrnIndex, const char* msgtype, } #endif +#ifndef HAVE_XF86MODEBANDWIDTH +/** Calculates the memory bandwidth (in MiB/sec) of a mode. */ +_X_HIDDEN unsigned int +xf86ModeBandwidth(DisplayModePtr mode, int depth) +{ + float a_active, a_total, active_percent, pixels_per_second; + int bytes_per_pixel = (depth + 7) / 8; + + if (!mode->HTotal || !mode->VTotal || !mode->Clock) + return 0; + + a_active = mode->HDisplay * mode->VDisplay; + a_total = mode->HTotal * mode->VTotal; + active_percent = a_active / a_total; + pixels_per_second = active_percent * mode->Clock * 1000.0; + + return (unsigned int)(pixels_per_second * bytes_per_pixel / (1024 * 1024)); +} +#endif + /* Used to disallow modes that are not supported by the hardware */ ModeStatus RADEONValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flag) { + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + /* + * RN50 has effective maximum mode bandwidth of about 300MiB/s. + * XXX should really do this for all chips by properly computing + * memory bandwidth and an overhead factor. + */ + if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) { + if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 300) + return MODE_BANDWIDTH; + } + /* There are problems with double scan mode at high clocks * They're likely related PLL and display buffer settings. * Disable these modes for now. diff --git a/src/radeon_output.c b/src/radeon_output.c index 9850702c..64c0438d 100644 --- a/src/radeon_output.c +++ b/src/radeon_output.c @@ -789,6 +789,19 @@ static int radeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) { RADEONOutputPrivatePtr radeon_output = output->driver_private; + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + /* + * RN50 has effective maximum mode bandwidth of about 300MiB/s. + * XXX should really do this for all chips by properly computing + * memory bandwidth and an overhead factor. + */ + if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) { + if (xf86ModeBandwidth(pMode, pScrn->bitsPerPixel) > 300) + return MODE_BANDWIDTH; + } if (radeon_output->type == OUTPUT_STV || radeon_output->type == OUTPUT_CTV) { |