OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [drm/] [radeon_irq.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*-
2
 *
3
 * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
4
 *
5
 * The Weather Channel (TM) funded Tungsten Graphics to develop the
6
 * initial release of the Radeon 8500 driver under the XFree86 license.
7
 * This notice must be preserved.
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a
10
 * copy of this software and associated documentation files (the "Software"),
11
 * to deal in the Software without restriction, including without limitation
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 * and/or sell copies of the Software, and to permit persons to whom the
14
 * Software is furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice (including the next
17
 * paragraph) shall be included in all copies or substantial portions of the
18
 * Software.
19
 *
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23
 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26
 * DEALINGS IN THE SOFTWARE.
27
 *
28
 * Authors:
29
 *    Keith Whitwell <keith@tungstengraphics.com>
30
 *    Michel Dänzer <michel@daenzer.net>
31
 */
32
 
33
#include "radeon.h"
34
#include "drmP.h"
35
#include "drm.h"
36
#include "radeon_drm.h"
37
#include "radeon_drv.h"
38
#include "drm_os_linux.h"
39
 
40
/* Interrupts - Used for device synchronization and flushing in the
41
 * following circumstances:
42
 *
43
 * - Exclusive FB access with hw idle:
44
 *    - Wait for GUI Idle (?) interrupt, then do normal flush.
45
 *
46
 * - Frame throttling, NV_fence:
47
 *    - Drop marker irq's into command stream ahead of time.
48
 *    - Wait on irq's with lock *not held*
49
 *    - Check each for termination condition
50
 *
51
 * - Internally in cp_getbuffer, etc:
52
 *    - as above, but wait with lock held???
53
 *
54
 * NOTE: These functions are misleadingly named -- the irq's aren't
55
 * tied to dma at all, this is just a hangover from dri prehistory.
56
 */
57
 
58
void DRM(dma_service)(int irq, void *arg, struct pt_regs *reg)
59
{
60
        drm_device_t *dev = (drm_device_t *) arg;
61
        drm_radeon_private_t *dev_priv =
62
           (drm_radeon_private_t *)dev->dev_private;
63
        u32 stat;
64
 
65
        stat = RADEON_READ(RADEON_GEN_INT_STATUS)
66
                & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT);
67
        if (!stat)
68
                return;
69
 
70
        /* SW interrupt */
71
        if (stat & RADEON_SW_INT_TEST) {
72
                wake_up_interruptible( &dev_priv->swi_queue );
73
        }
74
 
75
        /* VBLANK interrupt */
76
        if (stat & RADEON_CRTC_VBLANK_STAT) {
77
                atomic_inc(&dev->vbl_received);
78
                wake_up_interruptible(&dev->vbl_queue);
79
                DRM(vbl_send_signals)(dev);
80
        }
81
 
82
        /* Acknowledge all the bits in GEN_INT_STATUS -- seem to get
83
         * more than we asked for...
84
         */
85
        RADEON_WRITE(RADEON_GEN_INT_STATUS, stat);
86
}
87
 
88
static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv)
89
{
90
        u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS )
91
                & (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT);
92
        if (tmp)
93
                RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp );
94
}
95
 
96
int radeon_emit_irq(drm_device_t *dev)
97
{
98
        drm_radeon_private_t *dev_priv = dev->dev_private;
99
        unsigned int ret;
100
        RING_LOCALS;
101
 
102
        atomic_inc(&dev_priv->swi_emitted);
103
        ret = atomic_read(&dev_priv->swi_emitted);
104
 
105
        BEGIN_RING( 4 );
106
        OUT_RING_REG( RADEON_LAST_SWI_REG, ret );
107
        OUT_RING_REG( RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE );
108
        ADVANCE_RING();
109
        COMMIT_RING();
110
 
111
        return ret;
112
}
113
 
114
 
115
int radeon_wait_irq(drm_device_t *dev, int swi_nr)
116
{
117
        drm_radeon_private_t *dev_priv =
118
           (drm_radeon_private_t *)dev->dev_private;
119
        int ret = 0;
120
 
121
        if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr)
122
                return 0;
123
 
124
        dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
125
 
126
        /* This is a hack to work around mysterious freezes on certain
127
         * systems:
128
         */
129
        radeon_acknowledge_irqs( dev_priv );
130
 
131
        DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * HZ,
132
                     RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr );
133
 
134
        return ret;
135
}
136
 
137
int radeon_emit_and_wait_irq(drm_device_t *dev)
138
{
139
        return radeon_wait_irq( dev, radeon_emit_irq(dev) );
140
}
141
 
142
 
143
int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
144
{
145
        drm_radeon_private_t *dev_priv =
146
           (drm_radeon_private_t *)dev->dev_private;
147
        unsigned int cur_vblank;
148
        int ret = 0;
149
 
150
        if ( !dev_priv ) {
151
                DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
152
                return -EINVAL;
153
        }
154
 
155
        radeon_acknowledge_irqs( dev_priv );
156
 
157
        dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
158
 
159
        /* Assume that the user has missed the current sequence number
160
         * by about a day rather than she wants to wait for years
161
         * using vertical blanks...
162
         */
163
        DRM_WAIT_ON( ret, dev->vbl_queue, 3*HZ,
164
                     ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
165
                         - *sequence ) <= (1<<23) ) );
166
 
167
        *sequence = cur_vblank;
168
 
169
        return ret;
170
}
171
 
172
 
173
/* Needs the lock as it touches the ring.
174
 */
175
int radeon_irq_emit(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data)
176
{
177
        drm_file_t      *priv   = filp->private_data;
178
        drm_device_t    *dev    = priv->dev;
179
        drm_radeon_private_t *dev_priv = dev->dev_private;
180
        drm_radeon_irq_emit_t emit;
181
        int result;
182
 
183
        LOCK_TEST_WITH_RETURN( dev );
184
 
185
        if ( !dev_priv ) {
186
                DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
187
                return -EINVAL;
188
        }
189
 
190
        DRM_COPY_FROM_USER_IOCTL( emit, (drm_radeon_irq_emit_t *)data,
191
                                  sizeof(emit) );
192
 
193
        result = radeon_emit_irq( dev );
194
 
195
        if ( copy_to_user( emit.irq_seq, &result, sizeof(int) ) ) {
196
                DRM_ERROR( "copy_to_user\n" );
197
                return -EFAULT;
198
        }
199
 
200
        return 0;
201
}
202
 
203
 
204
/* Doesn't need the hardware lock.
205
 */
206
int radeon_irq_wait(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data)
207
{
208
        drm_file_t      *priv   = filp->private_data;
209
        drm_device_t    *dev    = priv->dev;
210
        drm_radeon_private_t *dev_priv = dev->dev_private;
211
        drm_radeon_irq_wait_t irqwait;
212
 
213
        if ( !dev_priv ) {
214
                DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
215
                return -EINVAL;
216
        }
217
 
218
        DRM_COPY_FROM_USER_IOCTL( irqwait, (drm_radeon_irq_wait_t *)data,
219
                                  sizeof(irqwait) );
220
 
221
        return radeon_wait_irq( dev, irqwait.irq_seq );
222
}
223
 
224
 
225
/* drm_dma.h hooks
226
*/
227
void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
228
        drm_radeon_private_t *dev_priv =
229
                (drm_radeon_private_t *)dev->dev_private;
230
 
231
        /* Disable *all* interrupts */
232
        RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
233
 
234
        /* Clear bits if they're already high */
235
        radeon_acknowledge_irqs( dev_priv );
236
}
237
 
238
void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
239
        drm_radeon_private_t *dev_priv =
240
                (drm_radeon_private_t *)dev->dev_private;
241
 
242
        atomic_set(&dev_priv->swi_emitted, 0);
243
        init_waitqueue_head( &dev_priv->swi_queue );
244
 
245
        /* Turn on SW and VBL ints */
246
        RADEON_WRITE( RADEON_GEN_INT_CNTL,
247
                      RADEON_CRTC_VBLANK_MASK |
248
                      RADEON_SW_INT_ENABLE );
249
}
250
 
251
void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
252
        drm_radeon_private_t *dev_priv =
253
                (drm_radeon_private_t *)dev->dev_private;
254
        if ( dev_priv ) {
255
                /* Disable *all* interrupts */
256
                RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
257
        }
258
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.