Skip to content

Commit

Permalink
Merge remote branch 'airlied/drm-next' into drm-intel-next
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric Anholt committed Nov 5, 2009
2 parents 43bcd61 + 4fe9676 commit 5b8f0be
Show file tree
Hide file tree
Showing 41 changed files with 1,118 additions and 619 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/drm_fb_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@ int drm_fb_helper_set_par(struct fb_info *info)

if (crtc->fb == fb_helper->crtc_info[i].mode_set.fb) {
mutex_lock(&dev->mode_config.mutex);
ret = crtc->funcs->set_config(&fb_helper->crtc_info->mode_set);
ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
mutex_unlock(&dev->mode_config.mutex);
if (ret)
return ret;
Expand Down
98 changes: 96 additions & 2 deletions drivers/gpu/drm/drm_fops.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ static int drm_open_helper(struct inode *inode, struct file *filp,

INIT_LIST_HEAD(&priv->lhead);
INIT_LIST_HEAD(&priv->fbs);
INIT_LIST_HEAD(&priv->event_list);
init_waitqueue_head(&priv->event_wait);
priv->event_space = 4096; /* set aside 4k for event buffer */

if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_open(dev, priv);
Expand Down Expand Up @@ -413,6 +416,30 @@ static void drm_master_release(struct drm_device *dev, struct file *filp)
}
}

static void drm_events_release(struct drm_file *file_priv)
{
struct drm_device *dev = file_priv->minor->dev;
struct drm_pending_event *e, *et;
struct drm_pending_vblank_event *v, *vt;
unsigned long flags;

spin_lock_irqsave(&dev->event_lock, flags);

/* Remove pending flips */
list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link)
if (v->base.file_priv == file_priv) {
list_del(&v->base.link);
drm_vblank_put(dev, v->pipe);
v->base.destroy(&v->base);
}

/* Remove unconsumed events */
list_for_each_entry_safe(e, et, &file_priv->event_list, link)
e->destroy(e);

spin_unlock_irqrestore(&dev->event_lock, flags);
}

/**
* Release file.
*
Expand Down Expand Up @@ -451,6 +478,8 @@ int drm_release(struct inode *inode, struct file *filp)
if (file_priv->minor->master)
drm_master_release(dev, filp);

drm_events_release(file_priv);

if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_release(dev, file_priv);

Expand Down Expand Up @@ -544,9 +573,74 @@ int drm_release(struct inode *inode, struct file *filp)
}
EXPORT_SYMBOL(drm_release);

/** No-op. */
static bool
drm_dequeue_event(struct drm_file *file_priv,
size_t total, size_t max, struct drm_pending_event **out)
{
struct drm_device *dev = file_priv->minor->dev;
struct drm_pending_event *e;
unsigned long flags;
bool ret = false;

spin_lock_irqsave(&dev->event_lock, flags);

*out = NULL;
if (list_empty(&file_priv->event_list))
goto out;
e = list_first_entry(&file_priv->event_list,
struct drm_pending_event, link);
if (e->event->length + total > max)
goto out;

file_priv->event_space += e->event->length;
list_del(&e->link);
*out = e;
ret = true;

out:
spin_unlock_irqrestore(&dev->event_lock, flags);
return ret;
}

ssize_t drm_read(struct file *filp, char __user *buffer,
size_t count, loff_t *offset)
{
struct drm_file *file_priv = filp->private_data;
struct drm_pending_event *e;
size_t total;
ssize_t ret;

ret = wait_event_interruptible(file_priv->event_wait,
!list_empty(&file_priv->event_list));
if (ret < 0)
return ret;

total = 0;
while (drm_dequeue_event(file_priv, total, count, &e)) {
if (copy_to_user(buffer + total,
e->event, e->event->length)) {
total = -EFAULT;
break;
}

total += e->event->length;
e->destroy(e);
}

return total;
}
EXPORT_SYMBOL(drm_read);

unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
{
return 0;
struct drm_file *file_priv = filp->private_data;
unsigned int mask = 0;

poll_wait(filp, &file_priv->event_wait, wait);

if (!list_empty(&file_priv->event_list))
mask |= POLLIN | POLLRDNORM;

return mask;
}
EXPORT_SYMBOL(drm_poll);
95 changes: 95 additions & 0 deletions drivers/gpu/drm/drm_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,62 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
return ret;
}

static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
union drm_wait_vblank *vblwait,
struct drm_file *file_priv)
{
struct drm_pending_vblank_event *e;
struct timeval now;
unsigned long flags;
unsigned int seq;

e = kzalloc(sizeof *e, GFP_KERNEL);
if (e == NULL)
return -ENOMEM;

e->pipe = pipe;
e->event.base.type = DRM_EVENT_VBLANK;
e->event.base.length = sizeof e->event;
e->event.user_data = vblwait->request.signal;
e->base.event = &e->event.base;
e->base.file_priv = file_priv;
e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;

do_gettimeofday(&now);
spin_lock_irqsave(&dev->event_lock, flags);

if (file_priv->event_space < sizeof e->event) {
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(e);
return -ENOMEM;
}

file_priv->event_space -= sizeof e->event;
seq = drm_vblank_count(dev, pipe);
if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) &&
(seq - vblwait->request.sequence) <= (1 << 23)) {
vblwait->request.sequence = seq + 1;
}

DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n",
vblwait->request.sequence, seq, pipe);

e->event.sequence = vblwait->request.sequence;
if ((seq - vblwait->request.sequence) <= (1 << 23)) {
e->event.tv_sec = now.tv_sec;
e->event.tv_usec = now.tv_usec;
drm_vblank_put(dev, e->pipe);
list_add_tail(&e->base.link, &e->base.file_priv->event_list);
wake_up_interruptible(&e->base.file_priv->event_wait);
} else {
list_add_tail(&e->base.link, &dev->vblank_event_list);
}

spin_unlock_irqrestore(&dev->event_lock, flags);

return 0;
}

/**
* Wait for VBLANK.
*
Expand Down Expand Up @@ -609,6 +665,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
goto done;
}

if (flags & _DRM_VBLANK_EVENT)
return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);

if ((flags & _DRM_VBLANK_NEXTONMISS) &&
(seq - vblwait->request.sequence) <= (1<<23)) {
vblwait->request.sequence = seq + 1;
Expand Down Expand Up @@ -641,6 +700,38 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
return ret;
}

void drm_handle_vblank_events(struct drm_device *dev, int crtc)
{
struct drm_pending_vblank_event *e, *t;
struct timeval now;
unsigned long flags;
unsigned int seq;

do_gettimeofday(&now);
seq = drm_vblank_count(dev, crtc);

spin_lock_irqsave(&dev->event_lock, flags);

list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
if (e->pipe != crtc)
continue;
if ((seq - e->event.sequence) > (1<<23))
continue;

DRM_DEBUG("vblank event on %d, current %d\n",
e->event.sequence, seq);

e->event.sequence = seq;
e->event.tv_sec = now.tv_sec;
e->event.tv_usec = now.tv_usec;
drm_vblank_put(dev, e->pipe);
list_move_tail(&e->base.link, &e->base.file_priv->event_list);
wake_up_interruptible(&e->base.file_priv->event_wait);
}

spin_unlock_irqrestore(&dev->event_lock, flags);
}

/**
* drm_handle_vblank - handle a vblank event
* @dev: DRM device
Expand All @@ -651,7 +742,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
*/
void drm_handle_vblank(struct drm_device *dev, int crtc)
{
if (!dev->num_crtcs)
return;

atomic_inc(&dev->_vblank_count[crtc]);
DRM_WAKEUP(&dev->vbl_queue[crtc]);
drm_handle_vblank_events(dev, crtc);
}
EXPORT_SYMBOL(drm_handle_vblank);
2 changes: 2 additions & 0 deletions drivers/gpu/drm/drm_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,11 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
INIT_LIST_HEAD(&dev->ctxlist);
INIT_LIST_HEAD(&dev->vmalist);
INIT_LIST_HEAD(&dev->maplist);
INIT_LIST_HEAD(&dev->vblank_event_list);

spin_lock_init(&dev->count_lock);
spin_lock_init(&dev->drw_lock);
spin_lock_init(&dev->event_lock);
init_timer(&dev->timer);
mutex_init(&dev->struct_mutex);
mutex_init(&dev->ctxlist_mutex);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ static struct drm_driver driver = {
.mmap = drm_gem_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
.read = drm_read,
#ifdef CONFIG_COMPAT
.compat_ioctl = i915_compat_ioctl,
#endif
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/radeon/atombios.h
Original file line number Diff line number Diff line change
Expand Up @@ -2314,7 +2314,7 @@ typedef struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT {
UCHAR ucSS_Step;
UCHAR ucSS_Delay;
UCHAR ucSS_Id;
UCHAR ucRecommandedRef_Div;
UCHAR ucRecommendedRef_Div;
UCHAR ucSS_Range; /* it was reserved for V11 */
} ATOM_SPREAD_SPECTRUM_ASSIGNMENT;

Expand Down
Loading

0 comments on commit 5b8f0be

Please sign in to comment.