diff options
author | Thomas Hilber <sparkie@lowbyte.de> | 2008-09-08 08:00:00 +0000 |
---|---|---|
committer | Paul Menzel <paulepanter@users.sourceforge.net> | 2009-06-06 14:07:37 +0200 |
commit | 35f3c6dda578d8ab5dad07961df34ff5c12a6ecb (patch) | |
tree | 5b130373127248e74145eec822eb238f171acc32 | |
parent | ec3ed33f683232528711a706b7a454780e9bbbfe (diff) | |
download | xf86-video-ati-frc-35f3c6dda578d8ab5dad07961df34ff5c12a6ecb.tar.gz xf86-video-ati-frc-35f3c6dda578d8ab5dad07961df34ff5c12a6ecb.tar.bz2 |
Workaround for sporadically lost interrupts.
- implemented a workaround for sporadically lost interrupts on
Radeon type hardware
Signed-off-by: Thomas Hilber <sparkie@lowbyte.de>
Signed-off-by: Paul Menzel <paulepanter@users.sourceforge.net>
-rw-r--r-- | src/radeon_video.c | 191 |
1 files changed, 101 insertions, 90 deletions
diff --git a/src/radeon_video.c b/src/radeon_video.c index 2cf5836..dd2bb73 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -4035,41 +4035,47 @@ switch(pPriv->encoding){ #ifdef VGA_SYNC_FIELDS +/* --- 8< --- */ /* * prefilter to prevent stray updates. * our software PLL will not try to lock for these. */ -#define SYF_FRAME_CYCLE 40000 #define SYF_CATCH_RANGE 18000 -/* --- 8< --- */ +/* + * updates outside time window defined by this + * value spawn warnings when in debug mode + */ +#define SYF_STRAY_WARN 10000 + /* * we average 25 frames to yield a cycle time of * about one second for analysis of frame rate data. * this serves as frequency divider for our software PLL. */ -#ifdef STANDALONE -#define SYF_PLL_DIVIDER 10 -#else #define SYF_PLL_DIVIDER 25 -#endif + +/* + * frame cycle duration in usecs for 25 fps + */ +#define SYF_FRAME_CYCLE 40000 /* * offset in usecs from double buffer switch where we try to place double * buffer updates. * this lowers sensivity to jitter of our software PLL phase comparator. */ -#define SYF_SYNC_POINT 20000 +#define SYF_SYNC_POINT (SYF_FRAME_CYCLE >> 1) /* * one trim increment compensates drift speed for about 29usec/sec. - * this represents resolution of our VCO input. + * this represents resolution of our VCO input. */ #define SYF_MIN_STEP_USEC 100 /* * factor weighting drift against sync point displacement - * when calculating overall compensation + * when calculating overall compensation */ #define SYF_DISP_DRIFT_FACTOR 1 @@ -4087,45 +4093,44 @@ switch(pPriv->encoding){ */ #define SYF_MAX_TRIM_ABS 37 -//#define DEBUG +#define DEBUG #ifdef DEBUG #define ERRORF ErrorF #else #define ERRORF(...) #endif -#ifdef STANDALONE -#define ErrorF printf -#define B(a) (*(argv + (a)) ? *(argv + (a)) : 0) -#else -#define B(a) (a) -#endif - #define USE_METER #ifdef USE_METER -#define OUT_ERRORF(...) #define OUT_GRAPHIC meter_out #else -#define OUT_ERRORF ErrorF #define OUT_GRAPHIC(...) #endif +#ifdef STANDALONE +#define ErrorF printf +#define B(a) (*(argv + (a)) ? *(argv + (a)) : 0) +#else +#define B(a) (a) +#endif + void -meter_out(val, symb) +meter_out(val, symb) { static char meter[81]; + static char headr[81] = "|<- -20ms 0 +20ms ->|"; - if (!symb) { - ErrorF("%s\n", meter); - memset(meter, '-', 80); - return; + if (!symb || symb == 1) { + if (!symb) ErrorF("%s", headr); + if (symb == 1) ErrorF("%s", meter); + memset(meter, '-', 80); + return; } val /= 500; val = min(val, 39); val = max(val, -40); meter[40 + val] = symb; } - /* --- 8< --- */ void @@ -4133,17 +4138,17 @@ vga_sync_fields() { static int fd; static int cnt; + static int sum; static int trim; static int ds_usecs; static int sync_point_disp; static struct timeval skew_prev; static drm_radeon_syncf_t syncf_prev; - drm_radeon_syncf_t syncf; - drm_radeon_setparam_t vbl_activate; - struct timeval filter; struct timeval skew; struct timeval drift_speed; + drm_radeon_syncf_t syncf; + drm_radeon_setparam_t vbl_activate; int tmp; if (!fd) { @@ -4156,29 +4161,43 @@ vga_sync_fields() ErrorF("DRM_IOCTL_RADEON_SETPARAM: %s\n", strerror(errno)); } } - syncf.trim = 0; - if (ioctl(fd, DRM_IOCTL_RADEON_SYNCF, &syncf)) { - ErrorF("DRM_IOCTL_RADEON_SYNCF: %s\n", strerror(errno)); - } - VSF_SUB(syncf.tv_now, syncf_prev.tv_now, filter); - syncf_prev = syncf; - if (filter.tv_sec - || filter.tv_usec > SYF_FRAME_CYCLE + SYF_CATCH_RANGE - || filter.tv_usec < SYF_FRAME_CYCLE - SYF_CATCH_RANGE) { - - /* - * toss stray intervals and reset - */ - cnt = 0; - trim = 0; - ds_usecs = 0; - sync_point_disp = 0; - skew_prev.tv_sec = ~0; - - ErrorF("RESET STRAY: %10d.%06d\n", (int)filter.tv_sec, (int)filter.tv_usec); - } else { /* --- 8< --- */ + syncf.trim = 0; + if (ioctl(fd, DRM_IOCTL_RADEON_SYNCF, &syncf)) { + ErrorF("DRM_IOCTL_RADEON_SYNCF: %s\n", strerror(errno)); + } + VSF_SUB(syncf.tv_now, syncf_prev.tv_now, drift_speed); + VSF_TV2USEC(drift_speed, tmp); +#ifdef STANDALONE + if (syncf_prev.tv_now.tv_sec) { + usleepv += SYF_FRAME_CYCLE - tmp; + } +#endif + syncf_prev = syncf; + if (tmp < SYF_FRAME_CYCLE - SYF_CATCH_RANGE || tmp > SYF_FRAME_CYCLE + SYF_CATCH_RANGE) { + + /* + * toss stray intervals and reset + */ + cnt = 0; + sum = 0; + trim = 0; + ds_usecs = 0; + sync_point_disp = 0; + skew_prev.tv_sec = ~0; + OUT_GRAPHIC(0, 0); + ErrorF(" R %11d\n", tmp); +#ifdef STANDALONE + goto main_loop_end; +#else + return; +#endif + } + if (tmp < SYF_FRAME_CYCLE - SYF_STRAY_WARN || tmp > SYF_FRAME_CYCLE + SYF_STRAY_WARN) { + OUT_GRAPHIC(0, 0); + ErrorF(" W %11d\n", tmp); + } #ifndef STANDALONE if (syncf.vbls & 1) { struct drm_wait_vblank_request vbr; @@ -4187,16 +4206,17 @@ loop: vbr.sequence = syncf.vbls + 1; vbr.signal = 0; if (ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbr)) { - ErrorF("DRM_IOCTL_WAIT_VBLANK: %s\n", strerror(errno)); - } - if (((struct drm_wait_vblank_reply *)&vbr)->sequence < syncf.vbls + 1) { - /* AFTER EINTR */ - goto loop; - } +// ErrorF("DRM_IOCTL_WAIT_VBLANK: %s\n", strerror(errno)); + } + if (((struct drm_wait_vblank_reply *)&vbr)->sequence < syncf.vbls + 1) { + /* AFTER EINTR */ + goto loop; + } } #endif VSF_SUB(syncf.tv_now, syncf.tv_vbl, skew) if (skew_prev.tv_sec != ~0) { + sum += tmp; sync_point_disp += skew.tv_usec - SYF_SYNC_POINT; VSF_SUB(skew, skew_prev, drift_speed); VSF_TV2USEC(drift_speed, tmp); @@ -4205,47 +4225,38 @@ loop: } if (skew_prev.tv_sec != ~0 && !(cnt % SYF_PLL_DIVIDER)) { sync_point_disp /= SYF_PLL_DIVIDER; - ERRORF("\n"); - ERRORF("tv now: %10d.%06d\n", (int)syncf.tv_now.tv_sec, (int)syncf.tv_now.tv_usec); - ERRORF("tv vbl: %10d.%06d\n", (int)syncf.tv_vbl.tv_sec, (int)syncf.tv_vbl.tv_usec); - ERRORF("vbls: %10d\n", syncf.vbls); - ERRORF("trim: 0x%08x\n", syncf.trim); - OUT_ERRORF("sync point displacement: %10d\n", sync_point_disp); - OUT_ERRORF("drift speed: %10d %s\n", ds_usecs, abs(ds_usecs) > 15000 ? "excessive drift speed" : ""); - OUT_GRAPHIC(0, '+'); - OUT_GRAPHIC(sync_point_disp, '|'); - OUT_GRAPHIC(ds_usecs, '*'); - OUT_GRAPHIC(0, 0); - if (B(1)) { - trim = (ds_usecs + sync_point_disp / SYF_DISP_DRIFT_FACTOR) / SYF_MIN_STEP_USEC; - OUT_ERRORF("overall compensation: %10d %s\n", trim, abs(trim) <= 1 ? "completed" : ""); - trim = max(trim, -SYF_MAX_TRIM_REL); - trim = min(trim, SYF_MAX_TRIM_REL); - ERRORF("o. c. clipped: %10d\n", trim); - } + OUT_GRAPHIC(0, '+'); + OUT_GRAPHIC(sync_point_disp, '|'); + OUT_GRAPHIC(ds_usecs, '*'); + OUT_GRAPHIC(0, 1); + + trim = (ds_usecs + sync_point_disp / SYF_DISP_DRIFT_FACTOR) / SYF_MIN_STEP_USEC; + trim = max(trim, -SYF_MAX_TRIM_REL); + trim = min(trim, SYF_MAX_TRIM_REL); + ERRORF("%7d %7d [%3d%+4d] %7d\n", ds_usecs, sync_point_disp, (char)(syncf.trim & 0xff), trim, sum); + sync_point_disp = 0; ds_usecs = 0; + sum = 0; + } + if (B(1) && trim) { + tmp = (char)(syncf.trim & 0xff); + if (trim > 0) { + tmp = min(tmp + 1, SYF_MAX_TRIM_ABS); + --trim; + } else { + tmp = max(tmp - 1, -SYF_MAX_TRIM_ABS); + ++trim; + } + syncf.trim = VSF_SET_TRIM | VSF_TEMPLATE | tmp & 0xff; + /*ErrorF("*trim: 0x%08x\n", syncf.trim);*/ + if (ioctl(fd, DRM_IOCTL_RADEON_SYNCF, &syncf)) { + ErrorF("DRM_IOCTL_RADEON_SYNCF: %s\n", strerror(errno)); + } } - if (trim) { - tmp = (char)(syncf.trim & 0xff); - if (trim > 0) { - tmp = min(tmp + 1, SYF_MAX_TRIM_ABS); - --trim; - } else { - tmp = max(tmp - 1, -SYF_MAX_TRIM_ABS); - ++trim; - } - syncf.trim = VSF_SET_TRIM | VSF_TEMPLATE | tmp & 0xff; - ERRORF("*trim: 0x%08x\n", syncf.trim); - if (ioctl(fd, DRM_IOCTL_RADEON_SYNCF, &syncf)) { - ErrorF("DRM_IOCTL_RADEON_SYNCF: %s\n", strerror(errno)); - } - } skew_prev = skew; /* --- 8< --- */ - } } - #endif |