Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 174485
b: refs/heads/master
c: d91d8a3
h: refs/heads/master
i:
  174483: e7f0d52
v: v3
  • Loading branch information
Kristian Høgsberg authored and Dave Airlie committed Nov 18, 2009
1 parent e58ac25 commit 903d8af
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: dad07ca71719598bc990dbdbeda763d15a10e98b
refs/heads/master: d91d8a3f88059d93e34ac70d059153ec69a9ffc7
69 changes: 69 additions & 0 deletions trunk/drivers/gpu/drm/drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2478,3 +2478,72 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
mutex_unlock(&dev->mode_config.mutex);
return ret;
}

int drm_mode_page_flip_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_mode_crtc_page_flip *page_flip = data;
struct drm_mode_object *obj;
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
struct drm_pending_vblank_event *e = NULL;
unsigned long flags;
int ret = -EINVAL;

if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
page_flip->reserved != 0)
return -EINVAL;

mutex_lock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj)
goto out;
crtc = obj_to_crtc(obj);

if (crtc->funcs->page_flip == NULL)
goto out;

obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB);
if (!obj)
goto out;
fb = obj_to_fb(obj);

if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
ret = -ENOMEM;
spin_lock_irqsave(&dev->event_lock, flags);
if (file_priv->event_space < sizeof e->event) {
spin_unlock_irqrestore(&dev->event_lock, flags);
goto out;
}
file_priv->event_space -= sizeof e->event;
spin_unlock_irqrestore(&dev->event_lock, flags);

e = kzalloc(sizeof *e, GFP_KERNEL);
if (e == NULL) {
spin_lock_irqsave(&dev->event_lock, flags);
file_priv->event_space += sizeof e->event;
spin_unlock_irqrestore(&dev->event_lock, flags);
goto out;
}

e->event.base.type = DRM_EVENT_VBLANK;
e->event.base.length = sizeof e->event;
e->event.user_data = page_flip->user_data;
e->base.event = &e->event.base;
e->base.file_priv = file_priv;
e->base.destroy =
(void (*) (struct drm_pending_event *)) kfree;
}

ret = crtc->funcs->page_flip(crtc, fb, e);
if (ret) {
spin_lock_irqsave(&dev->event_lock, flags);
file_priv->event_space += sizeof e->event;
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(e);
}

out:
mutex_unlock(&dev->mode_config.mutex);
return ret;
}
1 change: 1 addition & 0 deletions trunk/drivers/gpu/drm/drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
};

#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
Expand Down
1 change: 1 addition & 0 deletions trunk/include/drm/drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,7 @@ struct drm_gem_open {
#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int)
#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)

/**
* Device specific ioctls should only be in their respective headers
Expand Down
16 changes: 16 additions & 0 deletions trunk/include/drm/drm_crtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ struct drm_property {
struct drm_crtc;
struct drm_connector;
struct drm_encoder;
struct drm_pending_vblank_event;

/**
* drm_crtc_funcs - control CRTCs for a given device
Expand Down Expand Up @@ -333,6 +334,19 @@ struct drm_crtc_funcs {
void (*destroy)(struct drm_crtc *crtc);

int (*set_config)(struct drm_mode_set *set);

/*
* Flip to the given framebuffer. This implements the page
* flip ioctl descibed in drm_mode.h, specifically, the
* implementation must return immediately and block all
* rendering to the current fb until the flip has completed.
* If userspace set the event flag in the ioctl, the event
* argument will point to an event to send back when the flip
* completes, otherwise it will be NULL.
*/
int (*page_flip)(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event);
};

/**
Expand Down Expand Up @@ -756,6 +770,8 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev,
extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern bool drm_detect_hdmi_monitor(struct edid *edid);
extern int drm_mode_page_flip_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
int hdisplay, int vdisplay, int vrefresh,
bool reduced, bool interlaced, bool margins);
Expand Down
33 changes: 33 additions & 0 deletions trunk/include/drm/drm_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,4 +268,37 @@ struct drm_mode_crtc_lut {
__u64 blue;
};

#define DRM_MODE_PAGE_FLIP_EVENT 0x01
#define DRM_MODE_PAGE_FLIP_FLAGS DRM_MODE_PAGE_FLIP_EVENT

/*
* Request a page flip on the specified crtc.
*
* This ioctl will ask KMS to schedule a page flip for the specified
* crtc. Once any pending rendering targeting the specified fb (as of
* ioctl time) has completed, the crtc will be reprogrammed to display
* that fb after the next vertical refresh. The ioctl returns
* immediately, but subsequent rendering to the current fb will block
* in the execbuffer ioctl until the page flip happens. If a page
* flip is already pending as the ioctl is called, EBUSY will be
* returned.
*
* The ioctl supports one flag, DRM_MODE_PAGE_FLIP_EVENT, which will
* request that drm sends back a vblank event (see drm.h: struct
* drm_event_vblank) when the page flip is done. The user_data field
* passed in with this ioctl will be returned as the user_data field
* in the vblank event struct.
*
* The reserved field must be zero until we figure out something
* clever to use it for.
*/

struct drm_mode_crtc_page_flip {
__u32 crtc_id;
__u32 fb_id;
__u32 flags;
__u32 reserved;
__u64 user_data;
};

#endif

0 comments on commit 903d8af

Please sign in to comment.