summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hilber <sparkie@lowbyte.de>2008-08-19 08:00:00 +0000
committerPaul Menzel <paulepanter@users.sourceforge.net>2009-06-06 13:58:59 +0200
commitb8c0813de7b39749d40d96f48067df29df0316d7 (patch)
tree5dc8964ce61fe49fc9d0421036e3ef9019aa09af
parent7dc643e908381047cdc7e82cf35a32d520e66233 (diff)
downloadxf86-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.c226
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