Subversion Repositories Kolibri OS

Rev

Rev 5271 | 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
 
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
	}
2997 Serge 159
	/* enable msi */
160
	rdev->msi_enabled = 0;
2004 serge 161
 
162
    rdev->irq.installed = true;
5078 serge 163
	r = drm_irq_install(rdev->ddev, rdev->ddev->pdev->irq);
2004 serge 164
    if (r) {
165
       rdev->irq.installed = false;
3120 serge 166
       FAIL();
2004 serge 167
       return r;
168
   }
5078 serge 169
 
2004 serge 170
	DRM_INFO("radeon: irq initialized.\n");
171
	return 0;
172
}
173
 
2997 Serge 174
/**
3764 Serge 175
 * radeon_irq_kms_fini - tear down driver interrupt info
2997 Serge 176
 *
177
 * @rdev: radeon device pointer
178
 *
179
 * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics).
180
 */
181
void radeon_irq_kms_fini(struct radeon_device *rdev)
182
{
6104 serge 183
	drm_vblank_cleanup(rdev->ddev);
2997 Serge 184
	if (rdev->irq.installed) {
185
//		drm_irq_uninstall(rdev->ddev);
186
		rdev->irq.installed = false;
187
//       if (rdev->msi_enabled)
188
//			pci_disable_msi(rdev->pdev);
189
	}
190
}
2004 serge 191
 
2997 Serge 192
/**
193
 * radeon_irq_kms_sw_irq_get - enable software interrupt
194
 *
195
 * @rdev: radeon device pointer
196
 * @ring: ring whose interrupt you want to enable
197
 *
198
 * Enables the software interrupt for a specific ring (all asics).
199
 * The software interrupt is generally used to signal a fence on
200
 * a particular ring.
201
 */
202
void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring)
2004 serge 203
{
204
	unsigned long irqflags;
205
 
2997 Serge 206
	if (!rdev->ddev->irq_enabled)
207
		return;
208
 
209
	if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) {
210
		spin_lock_irqsave(&rdev->irq.lock, irqflags);
2004 serge 211
		radeon_irq_set(rdev);
2997 Serge 212
		spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 213
	}
214
}
215
 
2997 Serge 216
/**
5271 serge 217
 * radeon_irq_kms_sw_irq_get_delayed - enable software interrupt
218
 *
219
 * @rdev: radeon device pointer
220
 * @ring: ring whose interrupt you want to enable
221
 *
222
 * Enables the software interrupt for a specific ring (all asics).
223
 * The software interrupt is generally used to signal a fence on
224
 * a particular ring.
225
 */
226
bool radeon_irq_kms_sw_irq_get_delayed(struct radeon_device *rdev, int ring)
227
{
228
	return atomic_inc_return(&rdev->irq.ring_int[ring]) == 1;
229
}
230
 
231
/**
2997 Serge 232
 * radeon_irq_kms_sw_irq_put - disable software interrupt
233
 *
234
 * @rdev: radeon device pointer
235
 * @ring: ring whose interrupt you want to disable
236
 *
237
 * Disables the software interrupt for a specific ring (all asics).
238
 * The software interrupt is generally used to signal a fence on
239
 * a particular ring.
240
 */
241
void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
2004 serge 242
{
243
	unsigned long irqflags;
244
 
2997 Serge 245
	if (!rdev->ddev->irq_enabled)
246
		return;
247
 
248
	if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) {
249
		spin_lock_irqsave(&rdev->irq.lock, irqflags);
2004 serge 250
		radeon_irq_set(rdev);
2997 Serge 251
		spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 252
	}
253
}
254
 
3120 serge 255
/**
256
 * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt
257
 *
258
 * @rdev: radeon device pointer
259
 * @hpd_mask: mask of hpd pins you want to enable.
260
 *
261
 * Enables the hotplug detect interrupt for a specific hpd pin (all asics).
262
 */
263
void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
264
{
265
	unsigned long irqflags;
266
	int i;
2004 serge 267
 
5078 serge 268
	if (!rdev->ddev->irq_enabled)
269
		return;
270
 
3120 serge 271
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
272
	for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
273
		rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i));
274
	radeon_irq_set(rdev);
275
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
276
}
277
 
278
/**
279
 * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt
280
 *
281
 * @rdev: radeon device pointer
282
 * @hpd_mask: mask of hpd pins you want to disable.
283
 *
284
 * Disables the hotplug detect interrupt for a specific hpd pin (all asics).
285
 */
286
void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
287
{
288
	unsigned long irqflags;
289
	int i;
290
 
5078 serge 291
	if (!rdev->ddev->irq_enabled)
292
		return;
293
 
3120 serge 294
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
295
	for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
296
		rdev->irq.hpd[i] &= !(hpd_mask & (1 << i));
297
	radeon_irq_set(rdev);
298
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
299
}
300