From 4e9d215bdfe72588cbacdb17ab9b60a42a43aefb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 3 Jun 2007 16:28:21 +1000 Subject: radeon: add support for vblank on crtc2 This add support for CRTC2 vblank on radeon similiar to the i915 support --- shared-core/radeon_irq.c | 87 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 9 deletions(-) (limited to 'shared-core/radeon_irq.c') diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c index 3ff0baa2..41e3bde3 100644 --- a/shared-core/radeon_irq.c +++ b/shared-core/radeon_irq.c @@ -72,8 +72,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) /* Only consider the bits we're interested in - others could be used * outside the DRM */ - stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | - RADEON_CRTC_VBLANK_STAT)); + stat = radeon_acknowledge_irqs(dev_priv, dev_priv->irq_enable_reg); if (!stat) return IRQ_NONE; @@ -83,8 +82,22 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) } /* VBLANK interrupt */ - if (stat & RADEON_CRTC_VBLANK_STAT) { - atomic_inc(&dev->vbl_received); + if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) { + int vblank_crtc = dev_priv->vblank_crtc; + + if ((vblank_crtc & + (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) == + (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { + if (stat & RADEON_CRTC_VBLANK_STAT) + atomic_inc(&dev->vbl_received); + if (stat & RADEON_CRTC2_VBLANK_STAT) + atomic_inc(&dev->vbl_received2); + } else if (((stat & RADEON_CRTC_VBLANK_STAT) && + (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) || + ((stat & RADEON_CRTC2_VBLANK_STAT) && + (vblank_crtc & DRM_RADEON_VBLANK_CRTC2))) + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); } @@ -127,7 +140,8 @@ static int radeon_wait_irq(drm_device_t * dev, int swi_nr) return ret; } -int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) +int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence, + atomic_t *counter) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; @@ -148,7 +162,7 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) * using vertical blanks... */ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(&dev->vbl_received)) + (((cur_vblank = atomic_read(counter)) - *sequence) <= (1 << 23))); *sequence = cur_vblank; @@ -156,6 +170,16 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) return ret; } +int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) +{ + return radeon_driver_vblank_do_wait(dev, sequence, &dev->vbl_received); +} + +int radeon_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence) +{ + return radeon_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2); +} + /* Needs the lock as it touches the ring. */ int radeon_irq_emit(DRM_IOCTL_ARGS) @@ -204,6 +228,21 @@ int radeon_irq_wait(DRM_IOCTL_ARGS) return radeon_wait_irq(dev, irqwait.irq_seq); } +static void radeon_enable_interrupt(drm_device_t *dev) +{ + drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; + + dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE; + if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1) + dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK; + + if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2) + dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK; + + RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); + dev_priv->irq_enabled = 1; +} + /* drm_dma.h hooks */ void radeon_driver_irq_preinstall(drm_device_t * dev) @@ -227,9 +266,7 @@ void radeon_driver_irq_postinstall(drm_device_t * dev) atomic_set(&dev_priv->swi_emitted, 0); DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); - /* Turn on SW and VBL ints */ - RADEON_WRITE(RADEON_GEN_INT_CNTL, - RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE); + radeon_enable_interrupt(dev); } void radeon_driver_irq_uninstall(drm_device_t * dev) @@ -239,6 +276,38 @@ void radeon_driver_irq_uninstall(drm_device_t * dev) if (!dev_priv) return; + dev_priv->irq_enabled = 0; + /* Disable *all* interrupts */ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); } + + +int radeon_vblank_crtc_get(drm_device_t *dev) +{ + drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; + u32 flag; + u32 value; + + flag = RADEON_READ(RADEON_GEN_INT_CNTL); + value = 0; + + if (flag & RADEON_CRTC_VBLANK_MASK) + value |= DRM_RADEON_VBLANK_CRTC1; + + if (flag & RADEON_CRTC2_VBLANK_MASK) + value |= DRM_RADEON_VBLANK_CRTC2; + return value; +} + +int radeon_vblank_crtc_set(drm_device_t *dev, int64_t value) +{ + drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; + if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { + DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value); + return DRM_ERR(EINVAL); + } + dev_priv->vblank_crtc = (unsigned int)value; + radeon_enable_interrupt(dev); + return 0; +} -- cgit v1.2.3 From a05d4fecd3307aa2f2f27531e7ff0b1985ef5c56 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 3 Jun 2007 18:30:52 +1000 Subject: radeon: refine irq acking for vbl on crtc 2 --- shared-core/radeon_irq.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'shared-core/radeon_irq.c') diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c index 41e3bde3..5151b4d6 100644 --- a/shared-core/radeon_irq.c +++ b/shared-core/radeon_irq.c @@ -141,19 +141,29 @@ static int radeon_wait_irq(drm_device_t * dev, int swi_nr) } int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence, - atomic_t *counter) + int crtc) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; unsigned int cur_vblank; int ret = 0; - + int ack = 0; + atomic_t *counter; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } - radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT); + if (crtc == DRM_RADEON_VBLANK_CRTC1) { + counter = &dev->vbl_received; + ack |= RADEON_CRTC_VBLANK_STAT; + } else if (crtc == DRM_RADEON_VBLANK_CRTC2) { + counter = &dev->vbl_received2; + ack |= RADEON_CRTC2_VBLANK_STAT; + } else + return DRM_ERR(EINVAL); + + radeon_acknowledge_irqs(dev_priv, ack); dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; @@ -172,12 +182,12 @@ int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence, int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) { - return radeon_driver_vblank_do_wait(dev, sequence, &dev->vbl_received); + return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1); } int radeon_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence) { - return radeon_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2); + return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2); } /* Needs the lock as it touches the ring. -- cgit v1.2.3 From 068ffc1e1bf5607f836839a1fc621a95547251e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 22 Jun 2007 11:55:26 +0200 Subject: radeon: Acknowledge all interrupts we're interested in. Failure to do so was probably the root cause of fd.o bug 11287. --- shared-core/radeon_irq.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'shared-core/radeon_irq.c') diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c index 5151b4d6..a4be86e3 100644 --- a/shared-core/radeon_irq.c +++ b/shared-core/radeon_irq.c @@ -72,10 +72,14 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) /* Only consider the bits we're interested in - others could be used * outside the DRM */ - stat = radeon_acknowledge_irqs(dev_priv, dev_priv->irq_enable_reg); + stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | + RADEON_CRTC_VBLANK_STAT | + RADEON_CRTC2_VBLANK_STAT)); if (!stat) return IRQ_NONE; + stat &= dev_priv->irq_enable_reg; + /* SW interrupt */ if (stat & RADEON_SW_INT_TEST) { DRM_WAKEUP(&dev_priv->swi_queue); @@ -265,7 +269,8 @@ void radeon_driver_irq_preinstall(drm_device_t * dev) /* Clear bits if they're already high */ radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | - RADEON_CRTC_VBLANK_STAT)); + RADEON_CRTC_VBLANK_STAT | + RADEON_CRTC2_VBLANK_STAT)); } void radeon_driver_irq_postinstall(drm_device_t * dev) -- cgit v1.2.3