diff options
author | Thomas Hilber <sparkie@lowbyte.de> | 2008-08-19 08:00:00 +0000 |
---|---|---|
committer | Paul Menzel <paulepanter@users.sourceforge.net> | 2009-06-06 13:58:59 +0200 |
commit | b8c0813de7b39749d40d96f48067df29df0316d7 (patch) | |
tree | 5dc8964ce61fe49fc9d0421036e3ef9019aa09af | |
parent | 7dc643e908381047cdc7e82cf35a32d520e66233 (diff) | |
download | xf86-video-ati-frc-b8c0813de7b39749d40d96f48067df29df0316d7.tar.gz xf86-video-ati-frc-b8c0813de7b39749d40d96f48067df29df0316d7.tar.bz2 |
Rename options, rename every 1/25 s, graphic.
- frame rate now adapted every 1/25 second instead of only once per
second as before. This should make rate adaptions invisible even
if they change by large values
- implemented a simple graphic which should give you a better
overview of how regularly frame updates are issued from your decoder.
And how the Soft-PLL copes with these updates
- automatic sync of initial field polarity now has been removed. It's
now part of 40ms double buffer update improvement (see vers. 0.0.4)
- simplified/changed interface to DRM-module
Signed-off-by: Thomas Hilber <sparkie@lowbyte.de>
Signed-off-by: Paul Menzel <paulepanter@users.sourceforge.net>
-rw-r--r-- | src/radeon_video.c | 226 |
1 files changed, 123 insertions, 103 deletions
diff --git a/src/radeon_video.c b/src/radeon_video.c index 8c5d4f6..618c572 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -8,9 +8,9 @@ #include <stdio.h> #include <math.h> -#define SYNC_FIELDS +#define VGA_SYNC_FIELDS -#ifdef SYNC_FIELDS +#ifdef VGA_SYNC_FIELDS #define _RADEON_COMMON_H_ #include <errno.h> #include <sys/ioctl.h> @@ -2954,7 +2954,7 @@ RADEONPutImage( uint32_t tmp; xf86CrtcPtr crtc; -#ifdef SYNC_FIELDS +#ifdef VGA_SYNC_FIELDS vga_sync_fields(); #endif @@ -4033,26 +4033,25 @@ switch(pPriv->encoding){ } } -#ifdef SYNC_FIELDS +#ifdef VGA_SYNC_FIELDS /* * prefilter to prevent stray updates. * our software PLL will not try to lock for these. */ -#define SYNC_FRAME_CYCLE 40000 -#define SYNC_FIELD_CYCLE 20000 -#define SYNC_CATCH_RANGE 10000 +#define SYF_FRAME_CYCLE 40000 +#define SYF_CATCH_RANGE 18000 -/* --8<-- */ +/* --- 8< --- */ /* * 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 SYNC_PLL_DIVIDER 1 +#define SYF_PLL_DIVIDER 10 #else -#define SYNC_PLL_DIVIDER 25 +#define SYF_PLL_DIVIDER 25 #endif /* @@ -4060,47 +4059,33 @@ switch(pPriv->encoding){ * buffer updates. * this lowers sensivity to jitter of our software PLL phase comparator. */ -#define SYNC_POINT 20000 +#define SYF_SYNC_POINT 20000 /* * 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 VBL_MIN_STEP_USEC 300 +#define SYF_MIN_STEP_USEC 100 + +/* + * factor weighting drift against sync point displacement + * when calculating overall compensation + */ +#define SYF_DISP_DRIFT_FACTOR 1 /* NOT CURRENTLY USED * to allow for smooth adaption also on slower devices we delimit maximum * trim change per step size. * this implements some kind of low pass filter for our VCO input. */ -#define VBL_MAX_TRIM_REL 1000 +#define SYF_MAX_TRIM_REL 1000 /* * maximum absolute trim values allowed due to current * hardware/driver contraints. - * this delimits 'maximum voltage' being fed into our software PLL. + * this delimits 'maximum voltage' controlling our VCO. */ -#define VBL_MAX_TRIM_ABS 37 -#define VBL_MIN_TRIM_ABS 37 -#define VBL_RSYNC_FPOLAR 140 - -/* - * field polarity correction is clearly a task of the calling layer - * but for the moment we want to provide an all-in-one solution - * - * METHOD1 (fast): - * tries to resynchronize field polarity in one fell swoop - * by heavily incrementing the frame rate for a moment. - * this effectively drops a field. - * - * METHOD2 (slow): - * continuously increments frame rate until a field - * has been skipped. - * - * at most one of both methods is allowed at any time - */ -//#define RESYNC_FIELD_POLARITY_METHOD1 -//#define RESYNC_FIELD_POLARITY_METHOD2 +#define SYF_MAX_TRIM_ABS 37 //#define DEBUG #ifdef DEBUG @@ -4115,18 +4100,46 @@ switch(pPriv->encoding){ #else #define B(a) (a) #endif -/* --8<-- */ + +#define USE_METER +#ifdef USE_METER +#define OUT_ERRORF(...) +#define OUT_GRAPHIC meter_out +#else +#define OUT_ERRORF ErrorF +#define OUT_GRAPHIC(...) +#endif + +void +meter_out(val, symb) +{ + static char meter[81]; + + if (!symb) { + ErrorF("%s\n", meter); + memset(meter, '-', 80); + return; + } + val /= 500; + val = min(val, 39); + val = max(val, -40); + meter[40 + val] = symb; +} + +/* --- 8< --- */ void vga_sync_fields() { static int fd; static int cnt; + static int trim; static int ds_usecs; static int sync_point_disp; static struct timeval skew_prev; - static drm_radeon_vsync_t vsync_prev; - drm_radeon_vsync_t vsync; + static drm_radeon_syncf_t syncf_prev; + + drm_radeon_syncf_t syncf; drm_radeon_setparam_t vbl_activate; struct timeval filter; struct timeval skew; @@ -4143,89 +4156,96 @@ vga_sync_fields() ErrorF("DRM_IOCTL_RADEON_SETPARAM: %s\n", strerror(errno)); } } - vsync.trim = 0; - if (ioctl(fd, DRM_IOCTL_RADEON_VSYNC, &vsync)) { - ErrorF("DRM_IOCTL_RADEON_VSYNC: %s\n", strerror(errno)); + syncf.trim = 0; + if (ioctl(fd, DRM_IOCTL_RADEON_SYNCF, &syncf)) { + ErrorF("DRM_IOCTL_RADEON_SYNCF: %s\n", strerror(errno)); } - VBL_SUB(vsync.tv_now, vsync_prev.tv_now, filter); + VSF_SUB(syncf.tv_now, syncf_prev.tv_now, filter); if (filter.tv_sec - || filter.tv_usec > SYNC_FRAME_CYCLE + SYNC_CATCH_RANGE - || filter.tv_usec < SYNC_FRAME_CYCLE - SYNC_CATCH_RANGE) { + || 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\n"); + ErrorF("RESET STRAY: %10d.%06d\n", (int)filter.tv_sec, (int)filter.tv_usec); } else { -/* --8<-- */ -#ifdef RESYNC_FIELD_POLARITY_METHOD1 - if (vsync.vbls & 1 && B(1)) { - ErrorF(" <- resyncing field polarity M1 ->\n"); - vsync.trim = VBL_TEMPLATE | VBL_SET_TRIM | VBL_DEC_RATE | VBL_RSYNC_FPOLAR; - if (ioctl(fd, DRM_IOCTL_RADEON_VSYNC, &vsync)) { - ErrorF("DRM_IOCTL_RADEON_VSYNC: %s\n", strerror(errno)); exit(-1); - } - VBL_SUB(vsync.tv_now, vsync.tv_vbl, skew); - } else { -#endif - if (vsync.vbls & 1) { - struct drm_wait_vblank_request vbr; - - vbr.type = _DRM_VBLANK_ABSOLUTE; - vbr.sequence = vsync.vbls + 1; - vbr.signal = 0; - if (ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbr)) { - ErrorF("DRM_IOCTL_WAIT_VBLANK: %s\n", strerror(errno)); - } - } - VBL_SUB(vsync.tv_now, vsync.tv_vbl, skew) - if (skew_prev.tv_sec != ~0) { - sync_point_disp += skew.tv_usec - SYNC_POINT; - VBL_SUB(skew, skew_prev, drift_speed); - VBL_TV2USEC(drift_speed, tmp); - ds_usecs += tmp; - ++cnt; - } - if (skew_prev.tv_sec != ~0 && !(cnt % SYNC_PLL_DIVIDER)) { - sync_point_disp /= SYNC_PLL_DIVIDER; -#ifdef RESYNC_FIELD_POLARITY_METHOD2 - if (vsync.vbls & 1 && B(1)) { - ErrorF(" <- resyncing field polarity M2 ->\n"); - sync_point_disp = sync_point_disp < 0 ? SYNC_POINT : -SYNC_POINT; - } +/* --- 8< --- */ +#ifndef STANDALONE + if (syncf.vbls & 1) { + struct drm_wait_vblank_request vbr; +loop: + vbr.type = _DRM_VBLANK_ABSOLUTE; + 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; + } + } #endif - ErrorF("sync point displacement: %10d\n", sync_point_disp); - ErrorF("drift speed: %10d %s\n", ds_usecs, abs(ds_usecs) > 10000 ? "excessive drift speed" : ""); - if (B(1)) { - int trim = (ds_usecs + sync_point_disp) / VBL_MIN_STEP_USEC; - ErrorF("overall compensation: %10d %s\n", trim, abs(trim) <= 1 ? "completed" : ""); - trim = max(trim, -VBL_MAX_TRIM_REL); - trim = min(trim, VBL_MAX_TRIM_REL); - trim += (vsync.trim & 0xff) * (vsync.trim & VBL_INC_RATE ? -1 : 1); - trim = max(trim, -VBL_MIN_TRIM_ABS); - trim = min(trim, VBL_MAX_TRIM_ABS); - vsync.trim = VBL_TEMPLATE | VBL_SET_TRIM | (trim >= 0 ? VBL_DEC_RATE | trim : VBL_INC_RATE | -trim); - if (ioctl(fd, DRM_IOCTL_RADEON_VSYNC, &vsync)) { - ErrorF("DRM_IOCTL_RADEON_VSYNC: %s\n", strerror(errno)); exit(-1); - } - } - sync_point_disp = 0; - ds_usecs = 0; + VSF_SUB(syncf.tv_now, syncf.tv_vbl, skew) + if (skew_prev.tv_sec != ~0) { + sync_point_disp += skew.tv_usec - SYF_SYNC_POINT; + VSF_SUB(skew, skew_prev, drift_speed); + VSF_TV2USEC(drift_speed, tmp); + ds_usecs += tmp; + ++cnt; + } + 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); } -#ifdef RESYNC_FIELD_POLARITY_METHOD1 + sync_point_disp = 0; + ds_usecs = 0; } -#endif + 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<-- */ +/* --- 8< --- */ } - vsync_prev = vsync; + syncf_prev = syncf; } + #endif |