summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hilber <sparkie@lowbyte.de>2008-08-17 08:00:00 +0000
committerPaul Menzel <paulepanter@users.sourceforge.net>2009-06-06 13:53:02 +0200
commit7dc643e908381047cdc7e82cf35a32d520e66233 (patch)
treef1cb36083cf6075ab33cea7c1da734d4b733995d
parent3842d96432266ce342e76155fe14f0e31da5aab3 (diff)
downloadxf86-video-ati-frc-7dc643e908381047cdc7e82cf35a32d520e66233.tar.gz
xf86-video-ati-frc-7dc643e908381047cdc7e82cf35a32d520e66233.tar.bz2
Widened time window for double buffer updates.
- now widened time window for double buffer updates from 20ms to 40ms. This is done via drm-ioctl() since the chip doesn't provide a native interface for this. - this greatly reduces Soft-PLLs sensitivity to any timing interference - thus we now even can fully enable live-viewing with DVB drivers and a budget card. Though DVB driver timing problems are not yet solved. - 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.c385
1 files changed, 201 insertions, 184 deletions
diff --git a/src/radeon_video.c b/src/radeon_video.c
index 5d43b15..8c5d4f6 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -16,6 +16,7 @@
#include <sys/ioctl.h>
#include <xf86drm.h>
#include <drm/radeon_drm.h>
+extern void vga_sync_fields();
#endif
#include "radeon.h"
@@ -2913,190 +2914,6 @@ RADEONDisplayVideo(
OUTREG(RADEON_OV0_SCALE_CNTL, scale_cntl);
OUTREG(RADEON_OV0_REG_LOAD_CNTL, 0);
-
-#ifdef 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
-
-/* --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
-#else
-#define SYNC_PLL_DIVIDER 25
-#endif
-
-/*
- * 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 SYNC_POINT 10000
-
-/*
- * one trim increment compensates drift speed for about 29usec/sec.
- * this represents resolution of our VCO input.
- */
-#define VBL_MIN_STEP_USEC 29
-
-/* 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
-
-/*
- * maximum absolute trim values allowed due to current
- * hardware/driver contraints.
- * this delimits 'maximum voltage' being fed into our software PLL.
- */
-#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 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
-/* --8<-- */
-
-{
- static int fd;
- static int cnt;
- 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;
- drm_radeon_setparam_t vbl_activate;
- struct timeval filter;
- struct timeval skew;
- struct timeval drift_speed;
- int tmp;
-
- if (!fd) {
- if ((fd = drmOpen("radeon", 0)) < 0) {
- ErrorF("drmOpen: %s\n", strerror(errno));
- }
- vbl_activate.param = RADEON_SETPARAM_VBLANK_CRTC;
- vbl_activate.value = DRM_RADEON_VBLANK_CRTC1;
- if (ioctl(fd, DRM_IOCTL_RADEON_SETPARAM, &vbl_activate)) {
- 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));
- }
- VBL_SUB(vsync.tv_now, vsync_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) {
-
- /*
- * toss stray intervals and reset
- */
- cnt = 0;
- ds_usecs = 0;
- sync_point_disp = 0;
- skew_prev.tv_sec = ~0;
-
- ERRORF("RESET STRAY\n");
- } 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
- 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;
- }
-#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;
- }
-#ifdef RESYNC_FIELD_POLARITY_METHOD1
- }
-#endif
- skew_prev = skew;
-/* --8<-- */
-
- }
- vsync_prev = vsync;
-}
-#endif
}
@@ -3137,6 +2954,10 @@ RADEONPutImage(
uint32_t tmp;
xf86CrtcPtr crtc;
+#ifdef SYNC_FIELDS
+ vga_sync_fields();
+#endif
+
/*
* s2offset, s3offset - byte offsets into U and V plane of the
* source where copying starts. Y plane is
@@ -4212,3 +4033,199 @@ switch(pPriv->encoding){
}
}
+#ifdef 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
+
+/* --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
+#else
+#define SYNC_PLL_DIVIDER 25
+#endif
+
+/*
+ * 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 SYNC_POINT 20000
+
+/*
+ * one trim increment compensates drift speed for about 29usec/sec.
+ * this represents resolution of our VCO input.
+ */
+#define VBL_MIN_STEP_USEC 300
+
+/* 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
+
+/*
+ * maximum absolute trim values allowed due to current
+ * hardware/driver contraints.
+ * this delimits 'maximum voltage' being fed into our software PLL.
+ */
+#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 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
+/* --8<-- */
+
+void
+vga_sync_fields()
+{
+ static int fd;
+ static int cnt;
+ 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;
+ drm_radeon_setparam_t vbl_activate;
+ struct timeval filter;
+ struct timeval skew;
+ struct timeval drift_speed;
+ int tmp;
+
+ if (!fd) {
+ if ((fd = drmOpen("radeon", 0)) < 0) {
+ ErrorF("drmOpen: %s\n", strerror(errno));
+ }
+ vbl_activate.param = RADEON_SETPARAM_VBLANK_CRTC;
+ vbl_activate.value = DRM_RADEON_VBLANK_CRTC1;
+ if (ioctl(fd, DRM_IOCTL_RADEON_SETPARAM, &vbl_activate)) {
+ 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));
+ }
+ VBL_SUB(vsync.tv_now, vsync_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) {
+
+ /*
+ * toss stray intervals and reset
+ */
+ cnt = 0;
+ ds_usecs = 0;
+ sync_point_disp = 0;
+ skew_prev.tv_sec = ~0;
+
+ ERRORF("RESET STRAY\n");
+ } 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;
+ }
+#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;
+ }
+#ifdef RESYNC_FIELD_POLARITY_METHOD1
+ }
+#endif
+ skew_prev = skew;
+/* --8<-- */
+
+ }
+ vsync_prev = vsync;
+}
+#endif
+