aboutsummaryrefslogtreecommitdiff
path: root/shared-core/mga_irq.c
diff options
context:
space:
mode:
authorIan Romanick <idr@us.ibm.com>2007-10-25 17:14:53 -0700
committerIan Romanick <idr@us.ibm.com>2007-10-25 17:14:53 -0700
commit7e9ea55a2f052cc939ba9bbf9edac39798344b7a (patch)
tree22d2a3c3596578b29b8e7064fbc5e3f5b4448879 /shared-core/mga_irq.c
parent5b726b63906419ccb3de2e065f9bf7ae875ccdf3 (diff)
Initial pass at porting MGA to vblank-rework
This is currently only compile tested.
Diffstat (limited to 'shared-core/mga_irq.c')
-rw-r--r--shared-core/mga_irq.c79
1 files changed, 56 insertions, 23 deletions
diff --git a/shared-core/mga_irq.c b/shared-core/mga_irq.c
index 490d1fbb..a49a9b6e 100644
--- a/shared-core/mga_irq.c
+++ b/shared-core/mga_irq.c
@@ -36,6 +36,20 @@
#include "mga_drm.h"
#include "mga_drv.h"
+u32 mga_get_vblank_counter(drm_device_t *dev, int crtc)
+{
+ const drm_mga_private_t *const dev_priv =
+ (drm_mga_private_t *) dev->dev_private;
+
+ if (crtc != 0) {
+ return 0;
+ }
+
+
+ return atomic_read(&dev_priv->vbl_received);
+}
+
+
irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
{
drm_device_t *dev = (drm_device_t *) arg;
@@ -48,9 +62,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
/* VBLANK interrupt */
if (status & MGA_VLINEPEN) {
MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
- atomic_inc(&dev->vbl_received);
- DRM_WAKEUP(&dev->vbl_queue);
- drm_vbl_send_signals(dev);
+ atomic_inc(&dev_priv->vbl_received);
+ drm_handle_vblank(dev, 0);
handled = 1;
}
@@ -74,30 +87,41 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
handled = 1;
}
- if ( handled ) {
- return IRQ_HANDLED;
- }
- return IRQ_NONE;
+ return (handled) ? IRQ_HANDLED : IRQ_NONE;
}
-int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+
+int mga_enable_vblank(drm_device_t *dev, int crtc)
{
- unsigned int cur_vblank;
- int ret = 0;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
- /* Assume that the user has missed the current sequence number
- * by about a day rather than she wants to wait for years
- * using vertical blanks...
- */
- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(&dev->vbl_received))
- - *sequence) <= (1 << 23)));
+ if (crtc != 0) {
+ DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+ crtc);
+ return 0;
+ }
+
+ MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+ return 0;
+}
- *sequence = cur_vblank;
- return ret;
+void mga_disable_vblank(drm_device_t *dev, int crtc)
+{
+ if (crtc != 0) {
+ DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
+ crtc);
+ }
+
+ /* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have
+ * a nice hardware counter that tracks the number of refreshes when
+ * the interrupt is disabled, and the kernel doesn't know the refresh
+ * rate to calculate an estimate.
+ */
+ /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
}
+
int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
@@ -127,16 +151,25 @@ void mga_driver_irq_preinstall(drm_device_t * dev)
MGA_WRITE(MGA_ICLEAR, ~0);
}
-void mga_driver_irq_postinstall(drm_device_t * dev)
+int mga_driver_irq_postinstall(drm_device_t * dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ int ret;
- DRM_INIT_WAITQUEUE( &dev_priv->fence_queue );
+ ret = drm_vblank_init(dev, 1);
+ if (ret)
+ return ret;
- /* Turn on vertical blank interrupt and soft trap interrupt. */
- MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+ DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
+
+ /* Turn on soft trap interrupt. Vertical blank interrupts are enabled
+ * in mga_enable_vblank.
+ */
+ MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
+ return 0;
}
+
void mga_driver_irq_uninstall(drm_device_t * dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;