Subversion Repositories Kolibri OS

Rev

Rev 3764 | 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
 
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
 *
5078 serge 44
 * @int irq, void *arg: args
2997 Serge 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
 */
5078 serge 50
irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg)
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);
5078 serge 76
	rdev->irq.dpm_thermal = false;
2997 Serge 77
	for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
78
		rdev->irq.hpd[i] = false;
79
	for (i = 0; i < RADEON_MAX_CRTCS; i++) {
2004 serge 80
        rdev->irq.crtc_vblank_int[i] = false;
2997 Serge 81
		atomic_set(&rdev->irq.pflip[i], 0);
82
		rdev->irq.afmt[i] = false;
2004 serge 83
    }
84
    radeon_irq_set(rdev);
2997 Serge 85
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 86
    /* Clear bits */
87
    radeon_irq_process(rdev);
88
}
89
 
2997 Serge 90
/**
91
 * radeon_driver_irq_postinstall_kms - drm irq preinstall callback
92
 *
93
 * @dev: drm dev pointer
94
 *
95
 * Handles stuff to be done after enabling irqs (all asics).
96
 * Returns 0 on success.
97
 */
3120 serge 98
int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
99
{
100
	dev->max_vblank_count = 0x001fffff;
101
	return 0;
102
}
2997 Serge 103
 
3120 serge 104
/**
105
 * radeon_driver_irq_uninstall_kms - drm irq uninstall callback
106
 *
107
 * @dev: drm dev pointer
108
 *
109
 * This function disables all interrupt sources on the GPU (all asics).
110
 */
111
void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
2004 serge 112
{
3120 serge 113
	struct radeon_device *rdev = dev->dev_private;
114
	unsigned long irqflags;
115
	unsigned i;
2004 serge 116
 
3120 serge 117
	if (rdev == NULL) {
118
		return;
119
	}
120
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
121
	/* Disable *all* interrupts */
122
	for (i = 0; i < RADEON_NUM_RINGS; i++)
123
		atomic_set(&rdev->irq.ring_int[i], 0);
5078 serge 124
	rdev->irq.dpm_thermal = false;
3120 serge 125
	for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
126
		rdev->irq.hpd[i] = false;
127
	for (i = 0; i < RADEON_MAX_CRTCS; i++) {
128
		rdev->irq.crtc_vblank_int[i] = false;
129
		atomic_set(&rdev->irq.pflip[i], 0);
130
		rdev->irq.afmt[i] = false;
131
	}
3764 Serge 132
	radeon_irq_set(rdev);
3120 serge 133
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 134
}
135
 
3120 serge 136
 
137
 
2997 Serge 138
/**
139
 * radeon_irq_kms_init - init driver interrupt info
140
 *
141
 * @rdev: radeon device pointer
142
 *
143
 * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics).
144
 * Returns 0 for success, error for failure.
145
 */
2004 serge 146
int radeon_irq_kms_init(struct radeon_device *rdev)
147
{
148
	int r = 0;
149
 
2997 Serge 150
	spin_lock_init(&rdev->irq.lock);
151
	/* enable msi */
152
	rdev->msi_enabled = 0;
2004 serge 153
 
154
    rdev->irq.installed = true;
5078 serge 155
	r = drm_irq_install(rdev->ddev, rdev->ddev->pdev->irq);
2004 serge 156
    if (r) {
157
       rdev->irq.installed = false;
3120 serge 158
       FAIL();
2004 serge 159
       return r;
160
   }
5078 serge 161
 
2004 serge 162
	DRM_INFO("radeon: irq initialized.\n");
163
	return 0;
164
}
165
 
2997 Serge 166
/**
3764 Serge 167
 * radeon_irq_kms_fini - tear down driver interrupt info
2997 Serge 168
 *
169
 * @rdev: radeon device pointer
170
 *
171
 * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics).
172
 */
173
void radeon_irq_kms_fini(struct radeon_device *rdev)
174
{
175
//	drm_vblank_cleanup(rdev->ddev);
176
	if (rdev->irq.installed) {
177
//		drm_irq_uninstall(rdev->ddev);
178
		rdev->irq.installed = false;
179
//       if (rdev->msi_enabled)
180
//			pci_disable_msi(rdev->pdev);
181
	}
182
}
2004 serge 183
 
2997 Serge 184
/**
185
 * radeon_irq_kms_sw_irq_get - enable software interrupt
186
 *
187
 * @rdev: radeon device pointer
188
 * @ring: ring whose interrupt you want to enable
189
 *
190
 * Enables the software interrupt for a specific ring (all asics).
191
 * The software interrupt is generally used to signal a fence on
192
 * a particular ring.
193
 */
194
void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring)
2004 serge 195
{
196
	unsigned long irqflags;
197
 
2997 Serge 198
	if (!rdev->ddev->irq_enabled)
199
		return;
200
 
201
	if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) {
202
		spin_lock_irqsave(&rdev->irq.lock, irqflags);
2004 serge 203
		radeon_irq_set(rdev);
2997 Serge 204
		spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 205
	}
206
}
207
 
2997 Serge 208
/**
209
 * radeon_irq_kms_sw_irq_put - disable software interrupt
210
 *
211
 * @rdev: radeon device pointer
212
 * @ring: ring whose interrupt you want to disable
213
 *
214
 * Disables the software interrupt for a specific ring (all asics).
215
 * The software interrupt is generally used to signal a fence on
216
 * a particular ring.
217
 */
218
void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
2004 serge 219
{
220
	unsigned long irqflags;
221
 
2997 Serge 222
	if (!rdev->ddev->irq_enabled)
223
		return;
224
 
225
	if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) {
226
		spin_lock_irqsave(&rdev->irq.lock, irqflags);
2004 serge 227
		radeon_irq_set(rdev);
2997 Serge 228
		spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
2004 serge 229
	}
230
}
231
 
3120 serge 232
/**
233
 * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt
234
 *
235
 * @rdev: radeon device pointer
236
 * @hpd_mask: mask of hpd pins you want to enable.
237
 *
238
 * Enables the hotplug detect interrupt for a specific hpd pin (all asics).
239
 */
240
void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
241
{
242
	unsigned long irqflags;
243
	int i;
2004 serge 244
 
5078 serge 245
	if (!rdev->ddev->irq_enabled)
246
		return;
247
 
3120 serge 248
	spin_lock_irqsave(&rdev->irq.lock, irqflags);
249
	for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
250
		rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i));
251
	radeon_irq_set(rdev);
252
	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
253
}
254
 
255
/**
256
 * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt
257
 *
258
 * @rdev: radeon device pointer
259
 * @hpd_mask: mask of hpd pins you want to disable.
260
 *
261
 * Disables the hotplug detect interrupt for a specific hpd pin (all asics).
262
 */
263
void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
264
{
265
	unsigned long irqflags;
266
	int i;
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