Browse Source

drm/kernel: vblank wait on crtc > 1

Below is a patch against drm-next branch of 2.6.38-rc8+ kernel that adds
the capability to wait on vblank events for CRTCs that are greater than 1
and thus cannot be represented with primary/secondary flags in the legacy
interface. It was discussed on the dri-devel list in these two threads:

http://lists.freedesktop.org/archives/dri-devel/2011-March/009009.html
http://lists.freedesktop.org/archives/dri-devel/2011-March/009025.html

This patch extends the interface to drm_wait_vblank ioctl so that crtc>1
can be represented. It also adds a new capability to drm_getcap ioctl so
that the user space can check whether the new interface to drm_wait_vblank
is supported (and fall back to the legacy interface if not)

Signed-off-by: Ilija Hadzic <ihadzic@research.bell-labs.com>
Reviewed-by: Mario Kleiner <mario.kleiner at tuebingen.mpg.de>
Acked-by: Mario Kleiner <mario.kleiner at tuebingen.mpg.de>
Reviewed-by: Alex Deucher <alexdeucher@gmail.com>
Tested-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Ilija Hadzic 14 years ago
parent
commit
19b01b5fbf
3 changed files with 16 additions and 5 deletions
  1. 3 0
      drivers/gpu/drm/drm_ioctl.c
  2. 10 5
      drivers/gpu/drm/drm_irq.c
  3. 3 0
      include/drm/drm.h

+ 3 - 0
drivers/gpu/drm/drm_ioctl.c

@@ -280,6 +280,9 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 		if (dev->driver->dumb_create)
 			req->value = 1;
 		break;
+	case DRM_CAP_HIGH_CRTC:
+		req->value = 1;
+		break;
 	default:
 		return -EINVAL;
 	}

+ 10 - 5
drivers/gpu/drm/drm_irq.c

@@ -1125,7 +1125,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;
@@ -1134,16 +1134,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;
 

+ 3 - 0
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 | \
@@ -753,6 +755,7 @@ struct drm_event_vblank {
 };
 
 #define DRM_CAP_DUMB_BUFFER 0x1
+#define DRM_CAP_HIGH_CRTC 0x2
 
 /* typedef area */
 #ifndef __KERNEL__