mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-06 04:48:22 +02:00
Merge branch 'vblank-rework' into vblank
This commit is contained in:
commit
7f2a1cf275
5 changed files with 54 additions and 15 deletions
|
|
@ -832,6 +832,7 @@ typedef struct drm_device {
|
|||
/* for wraparound handling */
|
||||
u32 *vblank_offset; /* used to track how many vblanks */
|
||||
u32 *vblank_premodeset; /* were lost during modeset */
|
||||
struct timer_list vblank_disable_timer;
|
||||
|
||||
unsigned long max_vblank_count; /**< size of vblank counter register */
|
||||
spinlock_t tasklet_lock; /**< For drm_locked_tasklet */
|
||||
|
|
|
|||
|
|
@ -77,10 +77,22 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void vblank_disable_fn(unsigned long arg)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)arg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->num_crtcs; i++)
|
||||
if (atomic_read(&dev->vblank_refcount[i]) == 0)
|
||||
dev->driver->disable_vblank(dev, i);
|
||||
}
|
||||
|
||||
int drm_vblank_init(drm_device_t *dev, int num_crtcs)
|
||||
{
|
||||
int i, ret = -ENOMEM;
|
||||
|
||||
setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,\
|
||||
(unsigned long)dev);
|
||||
spin_lock_init(&dev->vbl_lock);
|
||||
atomic_set(&dev->vbl_signal_pending, 0);
|
||||
dev->num_crtcs = num_crtcs;
|
||||
|
|
@ -374,9 +386,10 @@ EXPORT_SYMBOL(drm_vblank_get);
|
|||
*/
|
||||
void drm_vblank_put(drm_device_t *dev, int crtc)
|
||||
{
|
||||
/* Last user can disable interrupts */
|
||||
/* Last user schedules interrupt disable */
|
||||
if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
|
||||
dev->driver->disable_vblank(dev, crtc);
|
||||
mod_timer(&dev->vblank_disable_timer,
|
||||
round_jiffies_relative(DRM_HZ));
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_put);
|
||||
|
||||
|
|
|
|||
|
|
@ -31,17 +31,6 @@
|
|||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
#define IS_I965G(dev) (dev->pci_device == 0x2972 || \
|
||||
dev->pci_device == 0x2982 || \
|
||||
dev->pci_device == 0x2992 || \
|
||||
dev->pci_device == 0x29A2 || \
|
||||
dev->pci_device == 0x2A02 || \
|
||||
dev->pci_device == 0x2A12)
|
||||
|
||||
#define IS_G33(dev) (dev->pci_device == 0x29C2 || \
|
||||
dev->pci_device == 0x29B2 || \
|
||||
dev->pci_device == 0x29D2)
|
||||
|
||||
/* Really want an OS-independent resettable timer. Would like to have
|
||||
* this loop run for (eg) 3 sec, but have the timer reset every time
|
||||
* the head pointer changes, so that EBUSY only happens if the ring
|
||||
|
|
|
|||
|
|
@ -396,4 +396,17 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
|
|||
|
||||
#define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hw_status_page))[5])
|
||||
#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg])
|
||||
|
||||
#define IS_I965G(dev) (dev->pci_device == 0x2972 || \
|
||||
dev->pci_device == 0x2982 || \
|
||||
dev->pci_device == 0x2992 || \
|
||||
dev->pci_device == 0x29A2 || \
|
||||
dev->pci_device == 0x2A02 || \
|
||||
dev->pci_device == 0x2A12)
|
||||
|
||||
#define IS_G33(dev) (dev->pci_device == 0x29C2 || \
|
||||
dev->pci_device == 0x29B2 || \
|
||||
dev->pci_device == 0x29D2)
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -285,6 +285,9 @@ u32 i915_get_vblank_counter(drm_device_t *dev, int crtc)
|
|||
unsigned long low_frame = crtc ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
|
||||
u32 high1, high2, low, count;
|
||||
|
||||
if (!IS_I965G(dev))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* High & low register fields aren't synchronized, so make sure
|
||||
* we get a low value that's stable across two reads of the high
|
||||
|
|
@ -315,7 +318,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
|
||||
|
||||
temp = I915_READ16(I915REG_INT_IDENTITY_R);
|
||||
temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG);
|
||||
|
||||
#if 0
|
||||
DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
|
||||
|
|
@ -324,7 +326,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
return IRQ_NONE;
|
||||
|
||||
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
|
||||
(void) I915_READ16(I915REG_INT_IDENTITY_R);
|
||||
(void) I915_READ16(I915REG_INT_IDENTITY_R); /* Flush posted write */
|
||||
|
||||
temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG | VSYNC_PIPEA_FLAG |
|
||||
VSYNC_PIPEB_FLAG);
|
||||
|
||||
dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
|
||||
|
|
@ -335,6 +340,13 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
#endif
|
||||
}
|
||||
|
||||
if (!IS_I965G(dev)) {
|
||||
if (temp & VSYNC_PIPEA_FLAG)
|
||||
atomic_inc(&dev->_vblank_count[0]);
|
||||
if (temp & VSYNC_PIPEB_FLAG)
|
||||
atomic_inc(&dev->_vblank_count[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use drm_update_vblank_counter here to deal with potential lost
|
||||
* interrupts
|
||||
|
|
@ -482,6 +494,9 @@ int i915_enable_vblank(drm_device_t *dev, int crtc)
|
|||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
if (!IS_I965G(dev))
|
||||
return 0;
|
||||
|
||||
switch (crtc) {
|
||||
case 0:
|
||||
dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
|
||||
|
|
@ -504,6 +519,9 @@ void i915_disable_vblank(drm_device_t *dev, int crtc)
|
|||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
if (!IS_I965G(dev))
|
||||
return;
|
||||
|
||||
switch (crtc) {
|
||||
case 0:
|
||||
dev_priv->irq_enable_reg &= ~VSYNC_PIPEA_FLAG;
|
||||
|
|
@ -763,6 +781,11 @@ int i915_driver_irq_postinstall(drm_device_t * dev)
|
|||
|
||||
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
|
||||
|
||||
if (!IS_I965G(dev)) {
|
||||
dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG;
|
||||
I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
|
||||
}
|
||||
|
||||
i915_enable_interrupt(dev);
|
||||
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue