Rev 2160 | Rev 3120 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2160 | Rev 2997 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright 2008 Advanced Micro Devices, Inc. |
2 | * Copyright 2008 Advanced Micro Devices, Inc. |
3 | * Copyright 2008 Red Hat Inc. |
3 | * Copyright 2008 Red Hat Inc. |
4 | * Copyright 2009 Jerome Glisse. |
4 | * Copyright 2009 Jerome Glisse. |
5 | * |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the "Software"), |
7 | * copy of this software and associated documentation files (the "Software"), |
8 | * to deal in the Software without restriction, including without limitation |
8 | * to deal in the Software without restriction, including without limitation |
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
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 |
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: |
11 | * Software is furnished to do so, subject to the following conditions: |
12 | * |
12 | * |
13 | * The above copyright notice and this permission notice shall be included in |
13 | * The above copyright notice and this permission notice shall be included in |
14 | * all copies or substantial portions of the Software. |
14 | * all copies or substantial portions of the Software. |
15 | * |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
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, |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
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 |
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, |
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 |
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
22 | * OTHER DEALINGS IN THE SOFTWARE. |
22 | * OTHER DEALINGS IN THE SOFTWARE. |
23 | * |
23 | * |
24 | * Authors: Dave Airlie |
24 | * Authors: Dave Airlie |
25 | * Alex Deucher |
25 | * Alex Deucher |
26 | * Jerome Glisse |
26 | * Jerome Glisse |
27 | */ |
27 | */ |
28 | #include "drmP.h" |
28 | #include |
29 | #include "drm_crtc_helper.h" |
29 | #include |
30 | #include "radeon_drm.h" |
30 | #include |
31 | #include "radeon_reg.h" |
31 | #include "radeon_reg.h" |
32 | #include "radeon.h" |
32 | #include "radeon.h" |
33 | #include "atom.h" |
33 | #include "atom.h" |
- | 34 | ||
- | 35 | #define RADEON_WAIT_IDLE_TIMEOUT 200 |
|
34 | 36 | ||
35 | struct radeon_device *main_device; |
37 | struct radeon_device *main_device; |
36 | 38 | ||
37 | extern int irq_override; |
39 | extern int irq_override; |
- | 40 | ||
- | 41 | ||
- | 42 | /** |
|
- | 43 | * radeon_driver_irq_handler_kms - irq handler for KMS |
|
- | 44 | * |
|
- | 45 | * @DRM_IRQ_ARGS: args |
|
- | 46 | * |
|
- | 47 | * This is the irq handler for the radeon KMS driver (all asics). |
|
- | 48 | * radeon_irq_process is a macro that points to the per-asic |
|
- | 49 | * irq handler callback. |
|
38 | 50 | */ |
|
39 | void irq_handler_kms() |
51 | void irq_handler_kms() |
40 | { |
- | |
41 | // dbgprintf("%s\n",__FUNCTION__); |
52 | { |
42 | radeon_irq_process(main_device); |
53 | radeon_irq_process(main_device); |
43 | } |
54 | } |
- | 55 | ||
- | 56 | /** |
|
- | 57 | * radeon_driver_irq_preinstall_kms - drm irq preinstall callback |
|
- | 58 | * |
|
44 | 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. |
|
45 | 63 | */ |
|
46 | static void radeon_irq_preinstall(struct radeon_device *rdev) |
64 | void radeon_irq_preinstall_kms(struct radeon_device *rdev) |
- | 65 | { |
|
47 | { |
66 | unsigned long irqflags; |
- | 67 | unsigned i; |
|
48 | unsigned i; |
68 | |
49 | - | ||
50 | /* Disable *all* interrupts */ |
- | |
51 | rdev->irq.sw_int = false; |
69 | spin_lock_irqsave(&rdev->irq.lock, irqflags); |
52 | rdev->irq.gui_idle = false; |
70 | /* Disable *all* interrupts */ |
53 | for (i = 0; i < rdev->num_crtc; i++) |
71 | for (i = 0; i < RADEON_NUM_RINGS; i++) |
54 | rdev->irq.crtc_vblank_int[i] = false; |
72 | atomic_set(&rdev->irq.ring_int[i], 0); |
- | 73 | for (i = 0; i < RADEON_MAX_HPD_PINS; i++) |
|
55 | for (i = 0; i < 6; i++) { |
74 | rdev->irq.hpd[i] = false; |
- | 75 | for (i = 0; i < RADEON_MAX_CRTCS; i++) { |
|
- | 76 | rdev->irq.crtc_vblank_int[i] = false; |
|
56 | rdev->irq.hpd[i] = false; |
77 | atomic_set(&rdev->irq.pflip[i], 0); |
57 | rdev->irq.pflip[i] = false; |
78 | rdev->irq.afmt[i] = false; |
- | 79 | } |
|
58 | } |
80 | radeon_irq_set(rdev); |
59 | radeon_irq_set(rdev); |
81 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); |
60 | /* Clear bits */ |
82 | /* Clear bits */ |
61 | radeon_irq_process(rdev); |
83 | radeon_irq_process(rdev); |
62 | } |
84 | } |
- | 85 | ||
- | 86 | /** |
|
- | 87 | * radeon_driver_irq_postinstall_kms - drm irq preinstall callback |
|
- | 88 | * |
|
- | 89 | * @dev: drm dev pointer |
|
- | 90 | * |
|
- | 91 | * Handles stuff to be done after enabling irqs (all asics). |
|
- | 92 | * Returns 0 on success. |
|
- | 93 | */ |
|
63 | 94 | ||
64 | int radeon_driver_irq_postinstall(struct radeon_device *rdev) |
95 | int radeon_driver_irq_postinstall_kms(struct radeon_device *rdev) |
65 | { |
96 | { |
66 | // struct radeon_device *rdev = dev->dev_private; |
97 | // struct radeon_device *rdev = dev->dev_private; |
67 | 98 | ||
68 | // dev->max_vblank_count = 0x001fffff; |
99 | // dev->max_vblank_count = 0x001fffff; |
69 | rdev->irq.sw_int = true; |
- | |
- | 100 | ||
70 | radeon_irq_set(rdev); |
101 | radeon_irq_set(rdev); |
71 | return 0; |
102 | return 0; |
72 | } |
103 | } |
- | 104 | ||
- | 105 | /** |
|
- | 106 | * radeon_irq_kms_init - init driver interrupt info |
|
- | 107 | * |
|
- | 108 | * @rdev: radeon device pointer |
|
- | 109 | * |
|
- | 110 | * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics). |
|
- | 111 | * Returns 0 for success, error for failure. |
|
73 | 112 | */ |
|
74 | int radeon_irq_kms_init(struct radeon_device *rdev) |
113 | int radeon_irq_kms_init(struct radeon_device *rdev) |
75 | { |
- | |
76 | int i; |
114 | { |
77 | int irq_line; |
115 | int irq_line; |
78 | int r = 0; |
116 | int r = 0; |
79 | 117 | ||
80 | ENTER(); |
118 | ENTER(); |
81 | 119 | ||
82 | // INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); |
120 | // INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); |
- | 121 | // INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); |
|
83 | 122 | ||
84 | spin_lock_init(&rdev->irq.sw_lock); |
- | |
85 | for (i = 0; i < rdev->num_crtc; i++) |
- | |
86 | spin_lock_init(&rdev->irq.pflip_lock[i]); |
123 | spin_lock_init(&rdev->irq.lock); |
87 | // r = drm_vblank_init(rdev->ddev, rdev->num_crtc); |
124 | // r = drm_vblank_init(rdev->ddev, rdev->num_crtc); |
88 | // if (r) { |
125 | // if (r) { |
89 | // return r; |
126 | // return r; |
90 | // } |
127 | // } |
91 | - | ||
- | 128 | /* enable msi */ |
|
92 | rdev->msi_enabled = 0; |
129 | rdev->msi_enabled = 0; |
- | 130 | ||
- | 131 | // if (radeon_msi_ok(rdev)) { |
|
- | 132 | // int ret = pci_enable_msi(rdev->pdev); |
|
- | 133 | // if (!ret) { |
|
- | 134 | // rdev->msi_enabled = 1; |
|
- | 135 | // dev_info(rdev->dev, "radeon: using MSI.\n"); |
|
- | 136 | // } |
|
- | 137 | // } |
|
93 | rdev->irq.installed = true; |
138 | rdev->irq.installed = true; |
94 | main_device = rdev; |
139 | main_device = rdev; |
95 | 140 | ||
96 | radeon_irq_preinstall(rdev); |
141 | radeon_irq_preinstall_kms(rdev); |
97 | 142 | ||
98 | if (irq_override) |
143 | if (irq_override) |
99 | irq_line = irq_override; |
144 | irq_line = irq_override; |
100 | else |
145 | else |
101 | irq_line = rdev->pdev->irq; |
146 | irq_line = rdev->pdev->irq; |
102 | 147 | ||
103 | dbgprintf("%s install irq %d\n", __FUNCTION__, irq_line); |
148 | dbgprintf("%s install irq %d\n", __FUNCTION__, irq_line); |
104 | 149 | ||
105 | AttachIntHandler(irq_line, irq_handler_kms, 2); |
150 | AttachIntHandler(irq_line, irq_handler_kms, 2); |
106 | 151 | ||
107 | // r = drm_irq_install(rdev->ddev); |
152 | // r = drm_irq_install(rdev->ddev); |
108 | 153 | ||
109 | r = radeon_driver_irq_postinstall(rdev); |
154 | r = radeon_driver_irq_postinstall_kms(rdev); |
110 | if (r) { |
155 | if (r) { |
111 | rdev->irq.installed = false; |
156 | rdev->irq.installed = false; |
112 | LEAVE(); |
157 | LEAVE(); |
113 | return r; |
158 | return r; |
114 | } |
159 | } |
115 | - | ||
116 | DRM_INFO("radeon: irq initialized.\n"); |
160 | DRM_INFO("radeon: irq initialized.\n"); |
117 | return 0; |
161 | return 0; |
118 | } |
162 | } |
- | 163 | ||
- | 164 | /** |
|
- | 165 | * radeon_irq_kms_fini - tear down driver interrrupt info |
|
- | 166 | * |
|
- | 167 | * @rdev: radeon device pointer |
|
- | 168 | * |
|
- | 169 | * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). |
|
- | 170 | */ |
|
- | 171 | void radeon_irq_kms_fini(struct radeon_device *rdev) |
|
- | 172 | { |
|
- | 173 | // drm_vblank_cleanup(rdev->ddev); |
|
- | 174 | if (rdev->irq.installed) { |
|
- | 175 | // drm_irq_uninstall(rdev->ddev); |
|
- | 176 | rdev->irq.installed = false; |
|
- | 177 | // if (rdev->msi_enabled) |
|
- | 178 | // pci_disable_msi(rdev->pdev); |
|
- | 179 | } |
|
- | 180 | // flush_work(&rdev->hotplug_work); |
|
- | 181 | } |
|
- | 182 | ||
- | 183 | /** |
|
- | 184 | * radeon_irq_kms_sw_irq_get - enable software interrupt |
|
- | 185 | * |
|
- | 186 | * @rdev: radeon device pointer |
|
- | 187 | * @ring: ring whose interrupt you want to enable |
|
- | 188 | * |
|
- | 189 | * Enables the software interrupt for a specific ring (all asics). |
|
- | 190 | * The software interrupt is generally used to signal a fence on |
|
119 | 191 | * a particular ring. |
|
120 | 192 | */ |
|
121 | void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev) |
193 | void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) |
122 | { |
194 | { |
123 | unsigned long irqflags; |
195 | unsigned long irqflags; |
124 | 196 | ||
- | 197 | if (!rdev->ddev->irq_enabled) |
|
- | 198 | return; |
|
125 | spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); |
199 | |
126 | if (rdev->ddev->irq_enabled && (++rdev->irq.sw_refcount == 1)) { |
200 | if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) { |
127 | rdev->irq.sw_int = true; |
201 | spin_lock_irqsave(&rdev->irq.lock, irqflags); |
- | 202 | radeon_irq_set(rdev); |
|
128 | radeon_irq_set(rdev); |
203 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); |
129 | } |
- | |
130 | spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); |
204 | } |
- | 205 | } |
|
- | 206 | ||
- | 207 | /** |
|
- | 208 | * radeon_irq_kms_sw_irq_put - disable software interrupt |
|
- | 209 | * |
|
- | 210 | * @rdev: radeon device pointer |
|
- | 211 | * @ring: ring whose interrupt you want to disable |
|
- | 212 | * |
|
- | 213 | * Disables the software interrupt for a specific ring (all asics). |
|
- | 214 | * The software interrupt is generally used to signal a fence on |
|
131 | } |
215 | * a particular ring. |
132 | 216 | */ |
|
133 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev) |
217 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) |
134 | { |
218 | { |
135 | unsigned long irqflags; |
219 | unsigned long irqflags; |
136 | 220 | ||
137 | spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); |
221 | if (!rdev->ddev->irq_enabled) |
- | 222 | return; |
|
138 | BUG_ON(rdev->ddev->irq_enabled && rdev->irq.sw_refcount <= 0); |
223 | |
139 | if (rdev->ddev->irq_enabled && (--rdev->irq.sw_refcount == 0)) { |
224 | if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) { |
140 | rdev->irq.sw_int = false; |
225 | spin_lock_irqsave(&rdev->irq.lock, irqflags); |
- | 226 | radeon_irq_set(rdev); |
|
141 | radeon_irq_set(rdev); |
227 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); |
142 | } |
- | |
143 | spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); |
228 | } |
144 | }=>>>> |
229 | }>>> |