diff mbox

vblank problem (and proposed fix) on crtc > 1

Message ID Pine.GSO.4.62.1103031733440.8604@umail (mailing list archive)
State New, archived
Headers show

Commit Message

Ilija Hadzic March 3, 2011, 11:34 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 16d5155..3b0abae 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -668,7 +668,7 @@  int drm_wait_vblank(struct drm_device *dev, void *data,
  {
  	union drm_wait_vblank *vblwait = data;
  	int ret = 0;
-	unsigned int flags, seq, crtc;
+	unsigned int flags, seq, crtc, high_crtc;

  	if ((!drm_dev_to_irq(dev)) || (!dev->irq_enabled))
  		return -EINVAL;
@@ -677,16 +677,21 @@  int drm_wait_vblank(struct drm_device *dev, void *data,
  		return -EINVAL;

  	if (vblwait->request.type &
-	    ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
+	    ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK | 
+	      _DRM_VBLANK_HIGH_CRTC_MASK)) {
  		DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
  			  vblwait->request.type,
-			  (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
+			  (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK | 
+			   _DRM_VBLANK_HIGH_CRTC_MASK));
  		return -EINVAL;
  	}

  	flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
-	crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
-
+	high_crtc = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
+	if (high_crtc)
+		crtc = high_crtc >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
+	else
+		crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
  	if (crtc >= dev->num_crtcs)
  		return -EINVAL;

diff --git a/include/drm/drm.h b/include/drm/drm.h
index e5f7061..d950581 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -469,6 +469,8 @@  enum drm_vblank_seq_type {
  	_DRM_VBLANK_SECONDARY = 0x20000000,	/**< Secondary display controller */
  	_DRM_VBLANK_SIGNAL = 0x40000000	/**< Send signal instead of blocking, unsupported */
  };
+#define _DRM_VBLANK_HIGH_CRTC_SHIFT 16
+#define _DRM_VBLANK_HIGH_CRTC_MASK 0x001F0000

  #define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
  #define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \


------------------------------- libdrm patch -----------------------------------

diff --git a/xf86drm.h b/xf86drm.h
index 9b89f56..65a68bf 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -302,6 +302,8 @@  typedef enum {
      DRM_VBLANK_SECONDARY = 0x20000000,	/**< Secondary display controller */
      DRM_VBLANK_SIGNAL   = 0x40000000	/* Send signal instead of blocking */
  } drmVBlankSeqType;
+#define DRM_VBLANK_HIGH_CRTC_SHIFT 16
+#define DRM_VBLANK_HIGH_CRTC_MASK 0x001F0000

  typedef struct _drmVBlankReq {
  	drmVBlankSeqType type;


------------------------------- xf86-video-ati (DDX) patch ---------------------

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 66df03c..5cbe544 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -783,6 +783,7 @@  static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
      drmVBlank vbl;
      int ret;
      int crtc = radeon_dri2_drawable_crtc(draw);
+    int high_crtc = 0;

      /* Drawable not displayed, make up a value */
      if (crtc == -1) {
@@ -791,8 +792,12 @@  static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
          return TRUE;
      }
      vbl.request.type = DRM_VBLANK_RELATIVE;
-    if (crtc > 0)
+    if (crtc == 1)
          vbl.request.type |= DRM_VBLANK_SECONDARY;
+    else if (crtc > 1)
+	high_crtc = (crtc << DRM_VBLANK_HIGH_CRTC_SHIFT) &
+	    DRM_VBLANK_HIGH_CRTC_MASK;
+    vbl.request.type |= high_crtc;
      vbl.request.sequence = 0;

      ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
@@ -825,6 +830,7 @@  static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
      drmVBlank vbl;
      int ret, crtc = radeon_dri2_drawable_crtc(draw);
      CARD64 current_msc;
+    int high_crtc = 0;

      /* Truncate to match kernel interfaces; means occasional overflow
       * misses, but that's generally not a big deal */
@@ -855,8 +861,12 @@  static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,

      /* Get current count */
      vbl.request.type = DRM_VBLANK_RELATIVE;
-    if (crtc > 0)
+    if (crtc == 1)
          vbl.request.type |= DRM_VBLANK_SECONDARY;
+    else if (crtc > 1)
+	high_crtc = (crtc << DRM_VBLANK_HIGH_CRTC_SHIFT) & 
+	    DRM_VBLANK_HIGH_CRTC_MASK;
+    vbl.request.type |= high_crtc;
      vbl.request.sequence = 0;
      ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
      if (ret) {
@@ -882,8 +892,12 @@  static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
          if (current_msc >= target_msc)
              target_msc = current_msc;
          vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
-        if (crtc > 0)
+        if (crtc == 1)
              vbl.request.type |= DRM_VBLANK_SECONDARY;
+	else if (crtc > 1)
+	    high_crtc = (crtc << DRM_VBLANK_HIGH_CRTC_SHIFT) & 
+		DRM_VBLANK_HIGH_CRTC_MASK;
+	vbl.request.type |= high_crtc;
          vbl.request.sequence = target_msc;
          vbl.request.signal = (unsigned long)wait_info;
          ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
@@ -903,8 +917,12 @@  static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
       * so we queue an event that will satisfy the divisor/remainder equation.
       */
      vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
-    if (crtc > 0)
+    if (crtc == 1)
          vbl.request.type |= DRM_VBLANK_SECONDARY;
+    else if (crtc > 1)
+	high_crtc = (crtc << DRM_VBLANK_HIGH_CRTC_SHIFT) & 
+	    DRM_VBLANK_HIGH_CRTC_MASK;
+    vbl.request.type |= high_crtc;

      vbl.request.sequence = current_msc - (current_msc % divisor) +
          remainder;
@@ -1029,6 +1047,7 @@  static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
      CARD64 current_msc;
      BoxRec box;
      RegionRec region;
+    int high_crtc = 0;

      /* Truncate to match kernel interfaces; means occasional overflow
       * misses, but that's generally not a big deal */
@@ -1068,8 +1087,12 @@  static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,

      /* Get current count */
      vbl.request.type = DRM_VBLANK_RELATIVE;
-    if (crtc > 0)
+    if (crtc == 1)
          vbl.request.type |= DRM_VBLANK_SECONDARY;
+    else if (crtc > 1)
+	high_crtc = (crtc << DRM_VBLANK_HIGH_CRTC_SHIFT) & 
+	    DRM_VBLANK_HIGH_CRTC_MASK;
+    vbl.request.type |= high_crtc;
      vbl.request.sequence = 0;
      ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
      if (ret) {
@@ -1111,8 +1134,12 @@  static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
           */
          if (flip == 0)
              vbl.request.type |= DRM_VBLANK_NEXTONMISS;
-        if (crtc > 0)
+        if (crtc == 1)
              vbl.request.type |= DRM_VBLANK_SECONDARY;
+	else if (crtc > 1)
+	    high_crtc = (crtc << DRM_VBLANK_HIGH_CRTC_SHIFT) & 
+		DRM_VBLANK_HIGH_CRTC_MASK;
+	vbl.request.type |= high_crtc;

          /* If target_msc already reached or passed, set it to
           * current_msc to ensure we return a reasonable value back
@@ -1145,8 +1172,12 @@  static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
      vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
      if (flip == 0)
          vbl.request.type |= DRM_VBLANK_NEXTONMISS;
-    if (crtc > 0)
+    if (crtc == 1)
          vbl.request.type |= DRM_VBLANK_SECONDARY;
+    else if (crtc > 1)
+	high_crtc = (crtc << DRM_VBLANK_HIGH_CRTC_SHIFT) & 
+	    DRM_VBLANK_HIGH_CRTC_MASK;
+    vbl.request.type |= high_crtc;

      vbl.request.sequence = current_msc - (current_msc % divisor) +
          remainder;