diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-04-22 02:03:07 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2008-04-26 04:01:07 -0400 |
commit | ac741ab71bb39e6977694ac0cc26678d8673cda4 (patch) | |
tree | f82e08399a0da5accba930444744b269479185dd /drivers/char/drm/mga_irq.c | |
parent | 2c14f28be2a3f2a2e9861b156d64fbe2bc7000c3 (diff) |
drm/vbl rework: rework how the drm deals with vblank.
Other Authors: Michel Dänzer <michel@tungstengraphics.com>
mga: Ian Romanick <idr@us.ibm.com>
via: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
This re-works the DRM internals to provide a better interface for drivers
to expose vblank on multiple crtcs.
It also includes work done by Michel on making i915 triple buffering and pageflipping work properly.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/char/drm/mga_irq.c')
-rw-r--r-- | drivers/char/drm/mga_irq.c | 69 |
1 files changed, 51 insertions, 18 deletions
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c index 9302cb8f0f83..06852fb4b278 100644 --- a/drivers/char/drm/mga_irq.c +++ b/drivers/char/drm/mga_irq.c | |||
@@ -35,6 +35,20 @@ | |||
35 | #include "mga_drm.h" | 35 | #include "mga_drm.h" |
36 | #include "mga_drv.h" | 36 | #include "mga_drv.h" |
37 | 37 | ||
38 | u32 mga_get_vblank_counter(struct drm_device *dev, int crtc) | ||
39 | { | ||
40 | const drm_mga_private_t *const dev_priv = | ||
41 | (drm_mga_private_t *) dev->dev_private; | ||
42 | |||
43 | if (crtc != 0) { | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | |||
48 | return atomic_read(&dev_priv->vbl_received); | ||
49 | } | ||
50 | |||
51 | |||
38 | irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) | 52 | irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) |
39 | { | 53 | { |
40 | struct drm_device *dev = (struct drm_device *) arg; | 54 | struct drm_device *dev = (struct drm_device *) arg; |
@@ -47,9 +61,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) | |||
47 | /* VBLANK interrupt */ | 61 | /* VBLANK interrupt */ |
48 | if (status & MGA_VLINEPEN) { | 62 | if (status & MGA_VLINEPEN) { |
49 | MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); | 63 | MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); |
50 | atomic_inc(&dev->vbl_received); | 64 | atomic_inc(&dev_priv->vbl_received); |
51 | DRM_WAKEUP(&dev->vbl_queue); | 65 | drm_handle_vblank(dev, 0); |
52 | drm_vbl_send_signals(dev); | ||
53 | handled = 1; | 66 | handled = 1; |
54 | } | 67 | } |
55 | 68 | ||
@@ -78,22 +91,34 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) | |||
78 | return IRQ_NONE; | 91 | return IRQ_NONE; |
79 | } | 92 | } |
80 | 93 | ||
81 | int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) | 94 | int mga_enable_vblank(struct drm_device *dev, int crtc) |
82 | { | 95 | { |
83 | unsigned int cur_vblank; | 96 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; |
84 | int ret = 0; | ||
85 | 97 | ||
86 | /* Assume that the user has missed the current sequence number | 98 | if (crtc != 0) { |
87 | * by about a day rather than she wants to wait for years | 99 | DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", |
88 | * using vertical blanks... | 100 | crtc); |
89 | */ | 101 | return 0; |
90 | DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, | 102 | } |
91 | (((cur_vblank = atomic_read(&dev->vbl_received)) | ||
92 | - *sequence) <= (1 << 23))); | ||
93 | 103 | ||
94 | *sequence = cur_vblank; | 104 | MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); |
105 | return 0; | ||
106 | } | ||
95 | 107 | ||
96 | return ret; | 108 | |
109 | void mga_disable_vblank(struct drm_device *dev, int crtc) | ||
110 | { | ||
111 | if (crtc != 0) { | ||
112 | DRM_ERROR("tried to disable vblank on non-existent crtc %d\n", | ||
113 | crtc); | ||
114 | } | ||
115 | |||
116 | /* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have | ||
117 | * a nice hardware counter that tracks the number of refreshes when | ||
118 | * the interrupt is disabled, and the kernel doesn't know the refresh | ||
119 | * rate to calculate an estimate. | ||
120 | */ | ||
121 | /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */ | ||
97 | } | 122 | } |
98 | 123 | ||
99 | int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence) | 124 | int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence) |
@@ -125,14 +150,22 @@ void mga_driver_irq_preinstall(struct drm_device * dev) | |||
125 | MGA_WRITE(MGA_ICLEAR, ~0); | 150 | MGA_WRITE(MGA_ICLEAR, ~0); |
126 | } | 151 | } |
127 | 152 | ||
128 | void mga_driver_irq_postinstall(struct drm_device * dev) | 153 | int mga_driver_irq_postinstall(struct drm_device * dev) |
129 | { | 154 | { |
130 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; | 155 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; |
156 | int ret; | ||
157 | |||
158 | ret = drm_vblank_init(dev, 1); | ||
159 | if (ret) | ||
160 | return ret; | ||
131 | 161 | ||
132 | DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); | 162 | DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); |
133 | 163 | ||
134 | /* Turn on vertical blank interrupt and soft trap interrupt. */ | 164 | /* Turn on soft trap interrupt. Vertical blank interrupts are enabled |
135 | MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); | 165 | * in mga_enable_vblank. |
166 | */ | ||
167 | MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN); | ||
168 | return 0; | ||
136 | } | 169 | } |
137 | 170 | ||
138 | void mga_driver_irq_uninstall(struct drm_device * dev) | 171 | void mga_driver_irq_uninstall(struct drm_device * dev) |