summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/radeon.h21
-rw-r--r--src/radeon_driver.c20
2 files changed, 31 insertions, 10 deletions
diff --git a/src/radeon.h b/src/radeon.h
index b19b017e..9e70ab58 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -39,6 +39,8 @@
#include <stdlib.h> /* For abs() */
#include <unistd.h> /* For usleep() */
+#include <sys/time.h> /* For
+#include <time.h> * gettimeofday() */
#include "xf86str.h"
#include "compiler.h"
@@ -189,6 +191,8 @@ typedef struct _region {
#define RADEON_IDLE_RETRY 16 /* Fall out of idle loops after this count */
#define RADEON_TIMEOUT 2000000 /* Fall out of wait loops after this count */
+#define RADEON_VSYNC_TIMEOUT 20000 /* Maximum wait for VSYNC (in usecs) */
+
/* Buffer are aligned on 4096 byte boundaries */
#define RADEON_BUFFER_ALIGN 0x00000fff
#define RADEON_VBIOS_SIZE 0x00010000
@@ -1175,4 +1179,21 @@ static __inline__ void RADEON_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn)
#endif
}
+static __inline__ void radeon_init_timeout(struct timeval *endtime,
+ unsigned int timeout)
+{
+ gettimeofday(endtime, NULL);
+ endtime->tv_usec += timeout;
+ endtime->tv_sec += endtime->tv_usec / 1000000;
+ endtime->tv_usec %= 1000000;
+}
+
+static __inline__ int radeon_timedout(const struct timeval *endtime)
+{
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ return now.tv_sec == endtime->tv_sec ?
+ now.tv_usec > endtime->tv_usec : now.tv_sec > endtime->tv_sec;
+}
+
#endif /* _RADEON_H_ */
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 894131fa..418b39d1 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -759,7 +759,7 @@ void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn)
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
CARD32 crtc_gen_cntl;
- int i;
+ struct timeval timeout;
crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL);
if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) ||
@@ -770,10 +770,10 @@ void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn)
OUTREG(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR);
/* Wait for it to go back up */
- for (i = 0; i < RADEON_TIMEOUT/1000; i++) {
- if (INREG(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_SAVE) break;
- usleep(1);
- }
+ radeon_init_timeout(&timeout, RADEON_VSYNC_TIMEOUT);
+ while (!(INREG(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_SAVE) &&
+ !radeon_timedout(&timeout))
+ usleep(100);
}
/* Wait for vertical sync on secondary CRTC */
@@ -782,7 +782,7 @@ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn)
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
CARD32 crtc2_gen_cntl;
- int i;
+ struct timeval timeout;
crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) ||
@@ -793,10 +793,10 @@ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn)
OUTREG(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR);
/* Wait for it to go back up */
- for (i = 0; i < RADEON_TIMEOUT/1000; i++) {
- if (INREG(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_SAVE) break;
- usleep(1);
- }
+ radeon_init_timeout(&timeout, RADEON_VSYNC_TIMEOUT);
+ while (!(INREG(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_SAVE) &&
+ !radeon_timedout(&timeout))
+ usleep(100);
}