Subversion Repositories Kolibri OS

Rev

Rev 6104 | 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
 
6104 serge 35
#include 
36
 
2997 Serge 37
#define RADEON_WAIT_IDLE_TIMEOUT 200
38
 
39
/**
40
 * radeon_driver_irq_handler_kms - irq handler for KMS
41
 *
5078 serge 42
 * @int irq, void *arg: args
2997 Serge 43
 *
44
 * This is the irq handler for the radeon KMS driver (all asics).
45
 * radeon_irq_process is a macro that points to the per-asic
46
 * irq handler callback.
47
 */
5078 serge 48
irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg)
2004 serge 49
{
3120 serge 50
	struct drm_device *dev = (struct drm_device *) arg;
51
	struct radeon_device *rdev = dev->dev_private;
52
 
53
    return radeon_irq_process(rdev);
2004 serge 54
}
55
 
2997 Serge 56
/**
57
 * radeon_driver_irq_preinstall_kms - drm irq preinstall callback
58
 *
59
 * @dev: drm dev pointer
60
 *
61
 * Gets the hw ready to enable irqs (all asics).
62
 * This function disables all interrupt sources on the GPU.
63
 */
3120 serge 64
void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
2004 serge 65
{
3120 serge 66
	struct radeon_device *rdev = dev->dev_private;
2997 Serge 67
	unsigned long irqflags;
6104 serge 68
	unsigned i;
2004 serge 69
 
2997 Serge 70
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
6104 serge 71
	/* Disable *all* interrupts */
2997 Serge 72
	for (i = 0; i < RADEON_NUM_RINGS; i++)
73
		atomic_set(&rdev->irq.ring_int[i], 0);
5078 serge 74
	rdev->irq.dpm_thermal = false;
2997 Serge 75
	for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
76
		rdev->irq.hpd[i] = false;
77
	for (i = 0; i < RADEON_MAX_CRTCS; i++) {
6104 serge 78
		rdev->irq.crtc_vblank_int[i] = false;
2997 Serge 79
		atomic_set(&rdev->irq.pflip[i], 0);
80
		rdev->irq.afmt[i] = false;
6104 serge 81
	}
82
	radeon_irq_set(rdev);
2997 Serge 83
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
6104 serge 84
	/* Clear bits */
85
	radeon_irq_process(rdev);
2004 serge 86
}
87
 
2997 Serge 88
/**
89
 * radeon_driver_irq_postinstall_kms - drm irq preinstall callback
90
 *
91
 * @dev: drm dev pointer
92
 *
93
 * Handles stuff to be done after enabling irqs (all asics).
94
 * Returns 0 on success.
95
 */
3120 serge 96
int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
97
{
6104 serge 98
	struct radeon_device *rdev = dev->dev_private;
99
 
100
	if (ASIC_IS_AVIVO(rdev))
101
		dev->max_vblank_count = 0x00ffffff;
102
	else
103
		dev->max_vblank_count = 0x001fffff;
104
 
3120 serge 105
	return 0;
106
}
2997 Serge 107
 
3120 serge 108
/**
109
 * radeon_driver_irq_uninstall_kms - drm irq uninstall callback
110
 *
111
 * @dev: drm dev pointer
112
 *
113
 * This function disables all interrupt sources on the GPU (all asics).
114
 */
115
void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
2004 serge 116
{
3120 serge 117
	struct radeon_device *rdev = dev->dev_private;
118
	unsigned long irqflags;
119
	unsigned i;
2004 serge 120
 
3120 serge 121
	if (rdev == NULL) {
122
		return;
123
	}
124
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
125
	/* Disable *all* interrupts */
126
	for (i = 0; i < RADEON_NUM_RINGS; i++)
127
		atomic_set(&rdev->irq.ring_int[i], 0);
5078 serge 128
	rdev->irq.dpm_thermal = false;
3120 serge 129
	for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
130
		rdev->irq.hpd[i] = false;
131
	for (i = 0; i < RADEON_MAX_CRTCS; i++) {
132
		rdev->irq.crtc_vblank_int[i] = false;
133
		atomic_set(&rdev->irq.pflip[i], 0);
134
		rdev->irq.afmt[i] = false;
135
	}
3764 Serge 136
	radeon_irq_set(rdev);
3120 serge 137
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 138
}
139
 
3120 serge 140
 
141
 
2997 Serge 142
/**
143
 * radeon_irq_kms_init - init driver interrupt info
144
 *
145
 * @rdev: radeon device pointer
146
 *
147
 * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics).
148
 * Returns 0 for success, error for failure.
149
 */
2004 serge 150
int radeon_irq_kms_init(struct radeon_device *rdev)
151
{
152
	int r = 0;
153
 
2997 Serge 154
	spin_lock_init(&rdev->irq.lock);
6104 serge 155
	r = drm_vblank_init(rdev->ddev, rdev->num_crtc);
156
	if (r) {
157
		return r;
158
	}
7146 serge 159
	rdev->ddev->vblank_disable_allowed = true;
160
 
2997 Serge 161
	/* enable msi */
162
	rdev->msi_enabled = 0;
2004 serge 163
 
7146 serge 164
	rdev->irq.installed = true;
5078 serge 165
	r = drm_irq_install(rdev->ddev, rdev->ddev->pdev->irq);
2004 serge 166
    if (r) {
167
       rdev->irq.installed = false;
3120 serge 168
       FAIL();
2004 serge 169
       return r;
170
   }
5078 serge 171
 
2004 serge 172
	DRM_INFO("radeon: irq initialized.\n");
173
	return 0;
174
}
175
 
2997 Serge 176
/**
3764 Serge 177
 * radeon_irq_kms_fini - tear down driver interrupt info
2997 Serge 178
 *
179
 * @rdev: radeon device pointer
180
 *
181
 * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics).
182
 */
183
void radeon_irq_kms_fini(struct radeon_device *rdev)
184
{
6104 serge 185
	drm_vblank_cleanup(rdev->ddev);
2997 Serge 186
	if (rdev->irq.installed) {
187
//		drm_irq_uninstall(rdev->ddev);
188
		rdev->irq.installed = false;
189
//       if (rdev->msi_enabled)
190
//			pci_disable_msi(rdev->pdev);
191
	}
192
}
2004 serge 193
 
2997 Serge 194
/**
195
 * radeon_irq_kms_sw_irq_get - enable software interrupt
196
 *
197
 * @rdev: radeon device pointer
198
 * @ring: ring whose interrupt you want to enable
199
 *
200
 * Enables the software interrupt for a specific ring (all asics).
201
 * The software interrupt is generally used to signal a fence on
202
 * a particular ring.
203
 */
204
void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring)
2004 serge 205
{
206
	unsigned long irqflags;
207
 
2997 Serge 208
	if (!rdev->ddev->irq_enabled)
209
		return;
210
 
211
	if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) {
212
		spin_lock_irqsave(&rdev->irq.lock, irqflags);
2004 serge 213
		radeon_irq_set(rdev);
2997 Serge 214
		spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 215
	}
216
}
217
 
2997 Serge 218
/**
5271 serge 219
 * radeon_irq_kms_sw_irq_get_delayed - enable software interrupt
220
 *
221
 * @rdev: radeon device pointer
222
 * @ring: ring whose interrupt you want to enable
223
 *
224
 * Enables the software interrupt for a specific ring (all asics).
225
 * The software interrupt is generally used to signal a fence on
226
 * a particular ring.
227
 */
228
bool radeon_irq_kms_sw_irq_get_delayed(struct radeon_device *rdev, int ring)
229
{
230
	return atomic_inc_return(&rdev->irq.ring_int[ring]) == 1;
231
}
232
 
233
/**
2997 Serge 234
 * radeon_irq_kms_sw_irq_put - disable software interrupt
235
 *
236
 * @rdev: radeon device pointer
237
 * @ring: ring whose interrupt you want to disable
238
 *
239
 * Disables the software interrupt for a specific ring (all asics).
240
 * The software interrupt is generally used to signal a fence on
241
 * a particular ring.
242
 */
243
void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
2004 serge 244
{
245
	unsigned long irqflags;
246
 
2997 Serge 247
	if (!rdev->ddev->irq_enabled)
248
		return;
249
 
250
	if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) {
251
		spin_lock_irqsave(&rdev->irq.lock, irqflags);
2004 serge 252
		radeon_irq_set(rdev);
2997 Serge 253
		spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 254
	}
255
}
256
 
3120 serge 257
/**
258
 * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt
259
 *
260
 * @rdev: radeon device pointer
261
 * @hpd_mask: mask of hpd pins you want to enable.
262
 *
263
 * Enables the hotplug detect interrupt for a specific hpd pin (all asics).
264
 */
265
void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
266
{
267
	unsigned long irqflags;
268
	int i;
2004 serge 269
 
5078 serge 270
	if (!rdev->ddev->irq_enabled)
271
		return;
272
 
3120 serge 273
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
274
	for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
275
		rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i));
276
	radeon_irq_set(rdev);
277
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
278
}
279
 
280
/**
281
 * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt
282
 *
283
 * @rdev: radeon device pointer
284
 * @hpd_mask: mask of hpd pins you want to disable.
285
 *
286
 * Disables the hotplug detect interrupt for a specific hpd pin (all asics).
287
 */
288
void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
289
{
290
	unsigned long irqflags;
291
	int i;
292
 
5078 serge 293
	if (!rdev->ddev->irq_enabled)
294
		return;
295
 
3120 serge 296
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
297
	for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
298
		rdev->irq.hpd[i] &= !(hpd_mask & (1 << i));
299
	radeon_irq_set(rdev);
300
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
301
}
302