Subversion Repositories Kolibri OS

Rev

Rev 3120 | Rev 5078 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2004 serge 1
/*
2
 * Copyright 2008 Advanced Micro Devices, Inc.
3
 * Copyright 2008 Red Hat Inc.
4
 * Copyright 2009 Jerome Glisse.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
 * OTHER DEALINGS IN THE SOFTWARE.
23
 *
24
 * Authors: Dave Airlie
25
 *          Alex Deucher
26
 *          Jerome Glisse
27
 */
2997 Serge 28
#include 
29
#include 
30
#include 
2004 serge 31
#include "radeon_reg.h"
32
#include "radeon.h"
33
#include "atom.h"
34
 
2997 Serge 35
#define RADEON_WAIT_IDLE_TIMEOUT 200
36
 
2004 serge 37
 
2160 serge 38
extern int irq_override;
2004 serge 39
 
2997 Serge 40
 
41
/**
42
 * radeon_driver_irq_handler_kms - irq handler for KMS
43
 *
44
 * @DRM_IRQ_ARGS: args
45
 *
46
 * This is the irq handler for the radeon KMS driver (all asics).
47
 * radeon_irq_process is a macro that points to the per-asic
48
 * irq handler callback.
49
 */
3120 serge 50
irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
2004 serge 51
{
3120 serge 52
	struct drm_device *dev = (struct drm_device *) arg;
53
	struct radeon_device *rdev = dev->dev_private;
54
 
55
    return radeon_irq_process(rdev);
2004 serge 56
}
57
 
2997 Serge 58
/**
59
 * radeon_driver_irq_preinstall_kms - drm irq preinstall callback
60
 *
61
 * @dev: drm dev pointer
62
 *
63
 * Gets the hw ready to enable irqs (all asics).
64
 * This function disables all interrupt sources on the GPU.
65
 */
3120 serge 66
void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
2004 serge 67
{
3120 serge 68
	struct radeon_device *rdev = dev->dev_private;
2997 Serge 69
	unsigned long irqflags;
2004 serge 70
    unsigned i;
71
 
2997 Serge 72
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
2004 serge 73
    /* Disable *all* interrupts */
2997 Serge 74
	for (i = 0; i < RADEON_NUM_RINGS; i++)
75
		atomic_set(&rdev->irq.ring_int[i], 0);
76
	for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
77
		rdev->irq.hpd[i] = false;
78
	for (i = 0; i < RADEON_MAX_CRTCS; i++) {
2004 serge 79
        rdev->irq.crtc_vblank_int[i] = false;
2997 Serge 80
		atomic_set(&rdev->irq.pflip[i], 0);
81
		rdev->irq.afmt[i] = false;
2004 serge 82
    }
83
    radeon_irq_set(rdev);
2997 Serge 84
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 85
    /* Clear bits */
86
    radeon_irq_process(rdev);
87
}
88
 
2997 Serge 89
/**
90
 * radeon_driver_irq_postinstall_kms - drm irq preinstall callback
91
 *
92
 * @dev: drm dev pointer
93
 *
94
 * Handles stuff to be done after enabling irqs (all asics).
95
 * Returns 0 on success.
96
 */
3120 serge 97
int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
98
{
99
	dev->max_vblank_count = 0x001fffff;
100
	return 0;
101
}
2997 Serge 102
 
3120 serge 103
/**
104
 * radeon_driver_irq_uninstall_kms - drm irq uninstall callback
105
 *
106
 * @dev: drm dev pointer
107
 *
108
 * This function disables all interrupt sources on the GPU (all asics).
109
 */
110
void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
2004 serge 111
{
3120 serge 112
	struct radeon_device *rdev = dev->dev_private;
113
	unsigned long irqflags;
114
	unsigned i;
2004 serge 115
 
3120 serge 116
	if (rdev == NULL) {
117
		return;
118
	}
119
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
120
	/* Disable *all* interrupts */
121
	for (i = 0; i < RADEON_NUM_RINGS; i++)
122
		atomic_set(&rdev->irq.ring_int[i], 0);
123
	for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
124
		rdev->irq.hpd[i] = false;
125
	for (i = 0; i < RADEON_MAX_CRTCS; i++) {
126
		rdev->irq.crtc_vblank_int[i] = false;
127
		atomic_set(&rdev->irq.pflip[i], 0);
128
		rdev->irq.afmt[i] = false;
129
	}
3764 Serge 130
	radeon_irq_set(rdev);
3120 serge 131
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 132
}
133
 
3120 serge 134
 
135
 
2997 Serge 136
/**
137
 * radeon_irq_kms_init - init driver interrupt info
138
 *
139
 * @rdev: radeon device pointer
140
 *
141
 * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics).
142
 * Returns 0 for success, error for failure.
143
 */
2004 serge 144
int radeon_irq_kms_init(struct radeon_device *rdev)
145
{
146
    int irq_line;
147
	int r = 0;
148
 
149
    ENTER();
150
 
151
 
2997 Serge 152
	spin_lock_init(&rdev->irq.lock);
153
	/* enable msi */
154
	rdev->msi_enabled = 0;
2004 serge 155
 
156
    rdev->irq.installed = true;
3120 serge 157
	r = drm_irq_install(rdev->ddev);
2004 serge 158
    if (r) {
159
       rdev->irq.installed = false;
3120 serge 160
       FAIL();
2004 serge 161
       return r;
162
   }
163
	DRM_INFO("radeon: irq initialized.\n");
164
	return 0;
165
}
166
 
2997 Serge 167
/**
3764 Serge 168
 * radeon_irq_kms_fini - tear down driver interrupt info
2997 Serge 169
 *
170
 * @rdev: radeon device pointer
171
 *
172
 * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics).
173
 */
174
void radeon_irq_kms_fini(struct radeon_device *rdev)
175
{
176
//	drm_vblank_cleanup(rdev->ddev);
177
	if (rdev->irq.installed) {
178
//		drm_irq_uninstall(rdev->ddev);
179
		rdev->irq.installed = false;
180
//       if (rdev->msi_enabled)
181
//			pci_disable_msi(rdev->pdev);
182
	}
183
//	flush_work(&rdev->hotplug_work);
184
}
2004 serge 185
 
2997 Serge 186
/**
187
 * radeon_irq_kms_sw_irq_get - enable software interrupt
188
 *
189
 * @rdev: radeon device pointer
190
 * @ring: ring whose interrupt you want to enable
191
 *
192
 * Enables the software interrupt for a specific ring (all asics).
193
 * The software interrupt is generally used to signal a fence on
194
 * a particular ring.
195
 */
196
void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring)
2004 serge 197
{
198
	unsigned long irqflags;
199
 
2997 Serge 200
	if (!rdev->ddev->irq_enabled)
201
		return;
202
 
203
	if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) {
204
		spin_lock_irqsave(&rdev->irq.lock, irqflags);
2004 serge 205
		radeon_irq_set(rdev);
2997 Serge 206
		spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 207
	}
208
}
209
 
2997 Serge 210
/**
211
 * radeon_irq_kms_sw_irq_put - disable software interrupt
212
 *
213
 * @rdev: radeon device pointer
214
 * @ring: ring whose interrupt you want to disable
215
 *
216
 * Disables the software interrupt for a specific ring (all asics).
217
 * The software interrupt is generally used to signal a fence on
218
 * a particular ring.
219
 */
220
void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
2004 serge 221
{
222
	unsigned long irqflags;
223
 
2997 Serge 224
	if (!rdev->ddev->irq_enabled)
225
		return;
226
 
227
	if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) {
228
		spin_lock_irqsave(&rdev->irq.lock, irqflags);
2004 serge 229
		radeon_irq_set(rdev);
2997 Serge 230
		spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 231
	}
232
}
233
 
3120 serge 234
/**
235
 * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt
236
 *
237
 * @rdev: radeon device pointer
238
 * @hpd_mask: mask of hpd pins you want to enable.
239
 *
240
 * Enables the hotplug detect interrupt for a specific hpd pin (all asics).
241
 */
242
void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
243
{
244
	unsigned long irqflags;
245
	int i;
2004 serge 246
 
3120 serge 247
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
248
	for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
249
		rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i));
250
	radeon_irq_set(rdev);
251
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
252
}
253
 
254
/**
255
 * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt
256
 *
257
 * @rdev: radeon device pointer
258
 * @hpd_mask: mask of hpd pins you want to disable.
259
 *
260
 * Disables the hotplug detect interrupt for a specific hpd pin (all asics).
261
 */
262
void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
263
{
264
	unsigned long irqflags;
265
	int i;
266
 
267
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
268
	for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
269
		rdev->irq.hpd[i] &= !(hpd_mask & (1 << i));
270
	radeon_irq_set(rdev);
271
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
272
}
273
 
274
 
275
static struct drm_driver drm_driver = {
276
    .irq_preinstall = radeon_driver_irq_preinstall_kms,
277
    .irq_postinstall = radeon_driver_irq_postinstall_kms,
278
    .irq_handler = radeon_driver_irq_handler_kms
279
};
280
 
281
static struct drm_driver *driver = &drm_driver;
282
 
283
int drm_irq_install(struct drm_device *dev)
284
{
285
    unsigned long sh_flags = 0;
286
    int irq_line;
287
    int ret = 0;
288
 
289
    char *irqname;
290
 
291
    mutex_lock(&dev->struct_mutex);
292
 
293
    /* Driver must have been initialized */
294
    if (!dev->dev_private) {
295
            mutex_unlock(&dev->struct_mutex);
296
            return -EINVAL;
297
    }
298
 
299
    if (dev->irq_enabled) {
300
            mutex_unlock(&dev->struct_mutex);
301
            return -EBUSY;
302
    }
303
    dev->irq_enabled = 1;
304
    mutex_unlock(&dev->struct_mutex);
305
 
306
    irq_line   = drm_dev_to_irq(dev);
307
 
308
    DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev));
309
 
310
    /* Before installing handler */
311
    if (driver->irq_preinstall)
312
            driver->irq_preinstall(dev);
313
 
314
    ret = AttachIntHandler(irq_line, driver->irq_handler, (u32)dev);
315
 
316
    /* After installing handler */
317
    if (driver->irq_postinstall)
318
            ret = driver->irq_postinstall(dev);
319
 
320
    if (ret < 0) {
321
            DRM_ERROR(__FUNCTION__);
322
    }
323
 
324
    u16_t cmd = PciRead16(dev->pdev->busnr, dev->pdev->devfn, 4);
325
    cmd&= ~(1<<10);
326
    PciWrite16(dev->pdev->busnr, dev->pdev->devfn, 4, cmd);
327
 
328
    return ret;
329
}