diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-12-04 15:12:21 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-12-07 19:48:07 -0500 |
commit | e0df1ac5c2cf346f4cc335025734978a4d747aa0 (patch) | |
tree | 5728691bd5bb9a5a06c1d8517515dfcd9fd67dd0 /drivers/gpu | |
parent | dcfdd4083509f9c46b1e92c58c062d50da50580e (diff) |
drm/radeon/kms: add hpd support for r6xx/r7xx/rs780/rs880 asics
This just adds the functionality, it's not hooked up
yet.
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 508 |
1 files changed, 485 insertions, 23 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 94e7fd2f59e9..f60689602082 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -74,6 +74,281 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev); | |||
74 | void r600_gpu_init(struct radeon_device *rdev); | 74 | void r600_gpu_init(struct radeon_device *rdev); |
75 | void r600_fini(struct radeon_device *rdev); | 75 | void r600_fini(struct radeon_device *rdev); |
76 | 76 | ||
77 | /* hpd for digital panel detect/disconnect */ | ||
78 | bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) | ||
79 | { | ||
80 | bool connected = false; | ||
81 | |||
82 | if (ASIC_IS_DCE3(rdev)) { | ||
83 | switch (hpd) { | ||
84 | case RADEON_HPD_1: | ||
85 | if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE) | ||
86 | connected = true; | ||
87 | break; | ||
88 | case RADEON_HPD_2: | ||
89 | if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE) | ||
90 | connected = true; | ||
91 | break; | ||
92 | case RADEON_HPD_3: | ||
93 | if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE) | ||
94 | connected = true; | ||
95 | break; | ||
96 | case RADEON_HPD_4: | ||
97 | if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE) | ||
98 | connected = true; | ||
99 | break; | ||
100 | /* DCE 3.2 */ | ||
101 | case RADEON_HPD_5: | ||
102 | if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE) | ||
103 | connected = true; | ||
104 | break; | ||
105 | case RADEON_HPD_6: | ||
106 | if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE) | ||
107 | connected = true; | ||
108 | break; | ||
109 | default: | ||
110 | break; | ||
111 | } | ||
112 | } else { | ||
113 | switch (hpd) { | ||
114 | case RADEON_HPD_1: | ||
115 | if (RREG32(DC_HOT_PLUG_DETECT1_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) | ||
116 | connected = true; | ||
117 | break; | ||
118 | case RADEON_HPD_2: | ||
119 | if (RREG32(DC_HOT_PLUG_DETECT2_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) | ||
120 | connected = true; | ||
121 | break; | ||
122 | case RADEON_HPD_3: | ||
123 | if (RREG32(DC_HOT_PLUG_DETECT3_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) | ||
124 | connected = true; | ||
125 | break; | ||
126 | default: | ||
127 | break; | ||
128 | } | ||
129 | } | ||
130 | return connected; | ||
131 | } | ||
132 | |||
133 | void r600_hpd_set_polarity(struct radeon_device *rdev, | ||
134 | enum radeon_hpd_id hpd) | ||
135 | { | ||
136 | u32 tmp; | ||
137 | bool connected = r600_hpd_sense(rdev, hpd); | ||
138 | |||
139 | if (ASIC_IS_DCE3(rdev)) { | ||
140 | switch (hpd) { | ||
141 | case RADEON_HPD_1: | ||
142 | tmp = RREG32(DC_HPD1_INT_CONTROL); | ||
143 | if (connected) | ||
144 | tmp &= ~DC_HPDx_INT_POLARITY; | ||
145 | else | ||
146 | tmp |= DC_HPDx_INT_POLARITY; | ||
147 | WREG32(DC_HPD1_INT_CONTROL, tmp); | ||
148 | break; | ||
149 | case RADEON_HPD_2: | ||
150 | tmp = RREG32(DC_HPD2_INT_CONTROL); | ||
151 | if (connected) | ||
152 | tmp &= ~DC_HPDx_INT_POLARITY; | ||
153 | else | ||
154 | tmp |= DC_HPDx_INT_POLARITY; | ||
155 | WREG32(DC_HPD2_INT_CONTROL, tmp); | ||
156 | break; | ||
157 | case RADEON_HPD_3: | ||
158 | tmp = RREG32(DC_HPD3_INT_CONTROL); | ||
159 | if (connected) | ||
160 | tmp &= ~DC_HPDx_INT_POLARITY; | ||
161 | else | ||
162 | tmp |= DC_HPDx_INT_POLARITY; | ||
163 | WREG32(DC_HPD3_INT_CONTROL, tmp); | ||
164 | break; | ||
165 | case RADEON_HPD_4: | ||
166 | tmp = RREG32(DC_HPD4_INT_CONTROL); | ||
167 | if (connected) | ||
168 | tmp &= ~DC_HPDx_INT_POLARITY; | ||
169 | else | ||
170 | tmp |= DC_HPDx_INT_POLARITY; | ||
171 | WREG32(DC_HPD4_INT_CONTROL, tmp); | ||
172 | break; | ||
173 | case RADEON_HPD_5: | ||
174 | tmp = RREG32(DC_HPD5_INT_CONTROL); | ||
175 | if (connected) | ||
176 | tmp &= ~DC_HPDx_INT_POLARITY; | ||
177 | else | ||
178 | tmp |= DC_HPDx_INT_POLARITY; | ||
179 | WREG32(DC_HPD5_INT_CONTROL, tmp); | ||
180 | break; | ||
181 | /* DCE 3.2 */ | ||
182 | case RADEON_HPD_6: | ||
183 | tmp = RREG32(DC_HPD6_INT_CONTROL); | ||
184 | if (connected) | ||
185 | tmp &= ~DC_HPDx_INT_POLARITY; | ||
186 | else | ||
187 | tmp |= DC_HPDx_INT_POLARITY; | ||
188 | WREG32(DC_HPD6_INT_CONTROL, tmp); | ||
189 | break; | ||
190 | default: | ||
191 | break; | ||
192 | } | ||
193 | } else { | ||
194 | switch (hpd) { | ||
195 | case RADEON_HPD_1: | ||
196 | tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL); | ||
197 | if (connected) | ||
198 | tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; | ||
199 | else | ||
200 | tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; | ||
201 | WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); | ||
202 | break; | ||
203 | case RADEON_HPD_2: | ||
204 | tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL); | ||
205 | if (connected) | ||
206 | tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; | ||
207 | else | ||
208 | tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; | ||
209 | WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); | ||
210 | break; | ||
211 | case RADEON_HPD_3: | ||
212 | tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL); | ||
213 | if (connected) | ||
214 | tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; | ||
215 | else | ||
216 | tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; | ||
217 | WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); | ||
218 | break; | ||
219 | default: | ||
220 | break; | ||
221 | } | ||
222 | } | ||
223 | } | ||
224 | |||
225 | void r600_hpd_init(struct radeon_device *rdev) | ||
226 | { | ||
227 | struct drm_device *dev = rdev->ddev; | ||
228 | struct drm_connector *connector; | ||
229 | |||
230 | if (ASIC_IS_DCE3(rdev)) { | ||
231 | u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa); | ||
232 | if (ASIC_IS_DCE32(rdev)) | ||
233 | tmp |= DC_HPDx_EN; | ||
234 | |||
235 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
236 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
237 | switch (radeon_connector->hpd.hpd) { | ||
238 | case RADEON_HPD_1: | ||
239 | WREG32(DC_HPD1_CONTROL, tmp); | ||
240 | rdev->irq.hpd[0] = true; | ||
241 | break; | ||
242 | case RADEON_HPD_2: | ||
243 | WREG32(DC_HPD2_CONTROL, tmp); | ||
244 | rdev->irq.hpd[1] = true; | ||
245 | break; | ||
246 | case RADEON_HPD_3: | ||
247 | WREG32(DC_HPD3_CONTROL, tmp); | ||
248 | rdev->irq.hpd[2] = true; | ||
249 | break; | ||
250 | case RADEON_HPD_4: | ||
251 | WREG32(DC_HPD4_CONTROL, tmp); | ||
252 | rdev->irq.hpd[3] = true; | ||
253 | break; | ||
254 | /* DCE 3.2 */ | ||
255 | case RADEON_HPD_5: | ||
256 | WREG32(DC_HPD5_CONTROL, tmp); | ||
257 | rdev->irq.hpd[4] = true; | ||
258 | break; | ||
259 | case RADEON_HPD_6: | ||
260 | WREG32(DC_HPD6_CONTROL, tmp); | ||
261 | rdev->irq.hpd[5] = true; | ||
262 | break; | ||
263 | default: | ||
264 | break; | ||
265 | } | ||
266 | } | ||
267 | } else { | ||
268 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
269 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
270 | switch (radeon_connector->hpd.hpd) { | ||
271 | case RADEON_HPD_1: | ||
272 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); | ||
273 | rdev->irq.hpd[0] = true; | ||
274 | break; | ||
275 | case RADEON_HPD_2: | ||
276 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); | ||
277 | rdev->irq.hpd[1] = true; | ||
278 | break; | ||
279 | case RADEON_HPD_3: | ||
280 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); | ||
281 | rdev->irq.hpd[2] = true; | ||
282 | break; | ||
283 | default: | ||
284 | break; | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | r600_irq_set(rdev); | ||
289 | } | ||
290 | |||
291 | void r600_hpd_fini(struct radeon_device *rdev) | ||
292 | { | ||
293 | struct drm_device *dev = rdev->ddev; | ||
294 | struct drm_connector *connector; | ||
295 | |||
296 | if (ASIC_IS_DCE3(rdev)) { | ||
297 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
298 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
299 | switch (radeon_connector->hpd.hpd) { | ||
300 | case RADEON_HPD_1: | ||
301 | WREG32(DC_HPD1_CONTROL, 0); | ||
302 | rdev->irq.hpd[0] = false; | ||
303 | break; | ||
304 | case RADEON_HPD_2: | ||
305 | WREG32(DC_HPD2_CONTROL, 0); | ||
306 | rdev->irq.hpd[1] = false; | ||
307 | break; | ||
308 | case RADEON_HPD_3: | ||
309 | WREG32(DC_HPD3_CONTROL, 0); | ||
310 | rdev->irq.hpd[2] = false; | ||
311 | break; | ||
312 | case RADEON_HPD_4: | ||
313 | WREG32(DC_HPD4_CONTROL, 0); | ||
314 | rdev->irq.hpd[3] = false; | ||
315 | break; | ||
316 | /* DCE 3.2 */ | ||
317 | case RADEON_HPD_5: | ||
318 | WREG32(DC_HPD5_CONTROL, 0); | ||
319 | rdev->irq.hpd[4] = false; | ||
320 | break; | ||
321 | case RADEON_HPD_6: | ||
322 | WREG32(DC_HPD6_CONTROL, 0); | ||
323 | rdev->irq.hpd[5] = false; | ||
324 | break; | ||
325 | default: | ||
326 | break; | ||
327 | } | ||
328 | } | ||
329 | } else { | ||
330 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
331 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
332 | switch (radeon_connector->hpd.hpd) { | ||
333 | case RADEON_HPD_1: | ||
334 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); | ||
335 | rdev->irq.hpd[0] = false; | ||
336 | break; | ||
337 | case RADEON_HPD_2: | ||
338 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); | ||
339 | rdev->irq.hpd[1] = false; | ||
340 | break; | ||
341 | case RADEON_HPD_3: | ||
342 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); | ||
343 | rdev->irq.hpd[2] = false; | ||
344 | break; | ||
345 | default: | ||
346 | break; | ||
347 | } | ||
348 | } | ||
349 | } | ||
350 | } | ||
351 | |||
77 | /* | 352 | /* |
78 | * R600 PCIE GART | 353 | * R600 PCIE GART |
79 | */ | 354 | */ |
@@ -2060,6 +2335,42 @@ static void r600_disable_interrupts(struct radeon_device *rdev) | |||
2060 | rdev->ih.rptr = 0; | 2335 | rdev->ih.rptr = 0; |
2061 | } | 2336 | } |
2062 | 2337 | ||
2338 | static void r600_disable_interrupt_state(struct radeon_device *rdev) | ||
2339 | { | ||
2340 | u32 tmp; | ||
2341 | |||
2342 | WREG32(CP_INT_CNTL, 0); | ||
2343 | WREG32(GRBM_INT_CNTL, 0); | ||
2344 | WREG32(DxMODE_INT_MASK, 0); | ||
2345 | if (ASIC_IS_DCE3(rdev)) { | ||
2346 | WREG32(DCE3_DACA_AUTODETECT_INT_CONTROL, 0); | ||
2347 | WREG32(DCE3_DACB_AUTODETECT_INT_CONTROL, 0); | ||
2348 | tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; | ||
2349 | WREG32(DC_HPD1_INT_CONTROL, tmp); | ||
2350 | tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY; | ||
2351 | WREG32(DC_HPD2_INT_CONTROL, tmp); | ||
2352 | tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY; | ||
2353 | WREG32(DC_HPD3_INT_CONTROL, tmp); | ||
2354 | tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY; | ||
2355 | WREG32(DC_HPD4_INT_CONTROL, tmp); | ||
2356 | if (ASIC_IS_DCE32(rdev)) { | ||
2357 | tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY; | ||
2358 | WREG32(DC_HPD5_INT_CONTROL, 0); | ||
2359 | tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY; | ||
2360 | WREG32(DC_HPD6_INT_CONTROL, 0); | ||
2361 | } | ||
2362 | } else { | ||
2363 | WREG32(DACA_AUTODETECT_INT_CONTROL, 0); | ||
2364 | WREG32(DACB_AUTODETECT_INT_CONTROL, 0); | ||
2365 | tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; | ||
2366 | WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, 0); | ||
2367 | tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; | ||
2368 | WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, 0); | ||
2369 | tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; | ||
2370 | WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, 0); | ||
2371 | } | ||
2372 | } | ||
2373 | |||
2063 | int r600_irq_init(struct radeon_device *rdev) | 2374 | int r600_irq_init(struct radeon_device *rdev) |
2064 | { | 2375 | { |
2065 | int ret = 0; | 2376 | int ret = 0; |
@@ -2122,9 +2433,7 @@ int r600_irq_init(struct radeon_device *rdev) | |||
2122 | WREG32(IH_CNTL, ih_cntl); | 2433 | WREG32(IH_CNTL, ih_cntl); |
2123 | 2434 | ||
2124 | /* force the active interrupt state to all disabled */ | 2435 | /* force the active interrupt state to all disabled */ |
2125 | WREG32(CP_INT_CNTL, 0); | 2436 | r600_disable_interrupt_state(rdev); |
2126 | WREG32(GRBM_INT_CNTL, 0); | ||
2127 | WREG32(DxMODE_INT_MASK, 0); | ||
2128 | 2437 | ||
2129 | /* enable irqs */ | 2438 | /* enable irqs */ |
2130 | r600_enable_interrupts(rdev); | 2439 | r600_enable_interrupts(rdev); |
@@ -2141,13 +2450,29 @@ void r600_irq_fini(struct radeon_device *rdev) | |||
2141 | 2450 | ||
2142 | int r600_irq_set(struct radeon_device *rdev) | 2451 | int r600_irq_set(struct radeon_device *rdev) |
2143 | { | 2452 | { |
2144 | uint32_t cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; | 2453 | u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; |
2145 | uint32_t mode_int = 0; | 2454 | u32 mode_int = 0; |
2455 | u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; | ||
2146 | 2456 | ||
2147 | /* don't enable anything if the ih is disabled */ | 2457 | /* don't enable anything if the ih is disabled */ |
2148 | if (!rdev->ih.enabled) | 2458 | if (!rdev->ih.enabled) |
2149 | return 0; | 2459 | return 0; |
2150 | 2460 | ||
2461 | if (ASIC_IS_DCE3(rdev)) { | ||
2462 | hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; | ||
2463 | hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; | ||
2464 | hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; | ||
2465 | hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN; | ||
2466 | if (ASIC_IS_DCE32(rdev)) { | ||
2467 | hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; | ||
2468 | hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; | ||
2469 | } | ||
2470 | } else { | ||
2471 | hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN; | ||
2472 | hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN; | ||
2473 | hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN; | ||
2474 | } | ||
2475 | |||
2151 | if (rdev->irq.sw_int) { | 2476 | if (rdev->irq.sw_int) { |
2152 | DRM_DEBUG("r600_irq_set: sw int\n"); | 2477 | DRM_DEBUG("r600_irq_set: sw int\n"); |
2153 | cp_int_cntl |= RB_INT_ENABLE; | 2478 | cp_int_cntl |= RB_INT_ENABLE; |
@@ -2160,39 +2485,137 @@ int r600_irq_set(struct radeon_device *rdev) | |||
2160 | DRM_DEBUG("r600_irq_set: vblank 1\n"); | 2485 | DRM_DEBUG("r600_irq_set: vblank 1\n"); |
2161 | mode_int |= D2MODE_VBLANK_INT_MASK; | 2486 | mode_int |= D2MODE_VBLANK_INT_MASK; |
2162 | } | 2487 | } |
2488 | if (rdev->irq.hpd[0]) { | ||
2489 | DRM_DEBUG("r600_irq_set: hpd 1\n"); | ||
2490 | hpd1 |= DC_HPDx_INT_EN; | ||
2491 | } | ||
2492 | if (rdev->irq.hpd[1]) { | ||
2493 | DRM_DEBUG("r600_irq_set: hpd 2\n"); | ||
2494 | hpd2 |= DC_HPDx_INT_EN; | ||
2495 | } | ||
2496 | if (rdev->irq.hpd[2]) { | ||
2497 | DRM_DEBUG("r600_irq_set: hpd 3\n"); | ||
2498 | hpd3 |= DC_HPDx_INT_EN; | ||
2499 | } | ||
2500 | if (rdev->irq.hpd[3]) { | ||
2501 | DRM_DEBUG("r600_irq_set: hpd 4\n"); | ||
2502 | hpd4 |= DC_HPDx_INT_EN; | ||
2503 | } | ||
2504 | if (rdev->irq.hpd[4]) { | ||
2505 | DRM_DEBUG("r600_irq_set: hpd 5\n"); | ||
2506 | hpd5 |= DC_HPDx_INT_EN; | ||
2507 | } | ||
2508 | if (rdev->irq.hpd[5]) { | ||
2509 | DRM_DEBUG("r600_irq_set: hpd 6\n"); | ||
2510 | hpd6 |= DC_HPDx_INT_EN; | ||
2511 | } | ||
2163 | 2512 | ||
2164 | WREG32(CP_INT_CNTL, cp_int_cntl); | 2513 | WREG32(CP_INT_CNTL, cp_int_cntl); |
2165 | WREG32(DxMODE_INT_MASK, mode_int); | 2514 | WREG32(DxMODE_INT_MASK, mode_int); |
2515 | if (ASIC_IS_DCE3(rdev)) { | ||
2516 | WREG32(DC_HPD1_INT_CONTROL, hpd1); | ||
2517 | WREG32(DC_HPD2_INT_CONTROL, hpd2); | ||
2518 | WREG32(DC_HPD3_INT_CONTROL, hpd3); | ||
2519 | WREG32(DC_HPD4_INT_CONTROL, hpd4); | ||
2520 | if (ASIC_IS_DCE32(rdev)) { | ||
2521 | WREG32(DC_HPD5_INT_CONTROL, hpd5); | ||
2522 | WREG32(DC_HPD6_INT_CONTROL, hpd6); | ||
2523 | } | ||
2524 | } else { | ||
2525 | WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); | ||
2526 | WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); | ||
2527 | WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3); | ||
2528 | } | ||
2166 | 2529 | ||
2167 | return 0; | 2530 | return 0; |
2168 | } | 2531 | } |
2169 | 2532 | ||
2170 | static inline void r600_irq_ack(struct radeon_device *rdev, u32 disp_int) | 2533 | static inline void r600_irq_ack(struct radeon_device *rdev, |
2534 | u32 *disp_int, | ||
2535 | u32 *disp_int_cont, | ||
2536 | u32 *disp_int_cont2) | ||
2171 | { | 2537 | { |
2538 | u32 tmp; | ||
2539 | |||
2540 | if (ASIC_IS_DCE3(rdev)) { | ||
2541 | *disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); | ||
2542 | *disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); | ||
2543 | *disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); | ||
2544 | } else { | ||
2545 | *disp_int = RREG32(DISP_INTERRUPT_STATUS); | ||
2546 | *disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); | ||
2547 | *disp_int_cont2 = 0; | ||
2548 | } | ||
2172 | 2549 | ||
2173 | if (disp_int & LB_D1_VBLANK_INTERRUPT) | 2550 | if (*disp_int & LB_D1_VBLANK_INTERRUPT) |
2174 | WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); | 2551 | WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); |
2175 | if (disp_int & LB_D1_VLINE_INTERRUPT) | 2552 | if (*disp_int & LB_D1_VLINE_INTERRUPT) |
2176 | WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK); | 2553 | WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK); |
2177 | if (disp_int & LB_D2_VBLANK_INTERRUPT) | 2554 | if (*disp_int & LB_D2_VBLANK_INTERRUPT) |
2178 | WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); | 2555 | WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); |
2179 | if (disp_int & LB_D2_VLINE_INTERRUPT) | 2556 | if (*disp_int & LB_D2_VLINE_INTERRUPT) |
2180 | WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK); | 2557 | WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK); |
2181 | 2558 | if (*disp_int & DC_HPD1_INTERRUPT) { | |
2559 | if (ASIC_IS_DCE3(rdev)) { | ||
2560 | tmp = RREG32(DC_HPD1_INT_CONTROL); | ||
2561 | tmp |= DC_HPDx_INT_ACK; | ||
2562 | WREG32(DC_HPD1_INT_CONTROL, tmp); | ||
2563 | } else { | ||
2564 | tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL); | ||
2565 | tmp |= DC_HPDx_INT_ACK; | ||
2566 | WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); | ||
2567 | } | ||
2568 | } | ||
2569 | if (*disp_int & DC_HPD2_INTERRUPT) { | ||
2570 | if (ASIC_IS_DCE3(rdev)) { | ||
2571 | tmp = RREG32(DC_HPD2_INT_CONTROL); | ||
2572 | tmp |= DC_HPDx_INT_ACK; | ||
2573 | WREG32(DC_HPD2_INT_CONTROL, tmp); | ||
2574 | } else { | ||
2575 | tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL); | ||
2576 | tmp |= DC_HPDx_INT_ACK; | ||
2577 | WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); | ||
2578 | } | ||
2579 | } | ||
2580 | if (*disp_int_cont & DC_HPD3_INTERRUPT) { | ||
2581 | if (ASIC_IS_DCE3(rdev)) { | ||
2582 | tmp = RREG32(DC_HPD3_INT_CONTROL); | ||
2583 | tmp |= DC_HPDx_INT_ACK; | ||
2584 | WREG32(DC_HPD3_INT_CONTROL, tmp); | ||
2585 | } else { | ||
2586 | tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL); | ||
2587 | tmp |= DC_HPDx_INT_ACK; | ||
2588 | WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); | ||
2589 | } | ||
2590 | } | ||
2591 | if (*disp_int_cont & DC_HPD4_INTERRUPT) { | ||
2592 | tmp = RREG32(DC_HPD4_INT_CONTROL); | ||
2593 | tmp |= DC_HPDx_INT_ACK; | ||
2594 | WREG32(DC_HPD4_INT_CONTROL, tmp); | ||
2595 | } | ||
2596 | if (ASIC_IS_DCE32(rdev)) { | ||
2597 | if (*disp_int_cont2 & DC_HPD5_INTERRUPT) { | ||
2598 | tmp = RREG32(DC_HPD5_INT_CONTROL); | ||
2599 | tmp |= DC_HPDx_INT_ACK; | ||
2600 | WREG32(DC_HPD5_INT_CONTROL, tmp); | ||
2601 | } | ||
2602 | if (*disp_int_cont2 & DC_HPD6_INTERRUPT) { | ||
2603 | tmp = RREG32(DC_HPD5_INT_CONTROL); | ||
2604 | tmp |= DC_HPDx_INT_ACK; | ||
2605 | WREG32(DC_HPD6_INT_CONTROL, tmp); | ||
2606 | } | ||
2607 | } | ||
2182 | } | 2608 | } |
2183 | 2609 | ||
2184 | void r600_irq_disable(struct radeon_device *rdev) | 2610 | void r600_irq_disable(struct radeon_device *rdev) |
2185 | { | 2611 | { |
2186 | u32 disp_int; | 2612 | u32 disp_int, disp_int_cont, disp_int_cont2; |
2187 | 2613 | ||
2188 | r600_disable_interrupts(rdev); | 2614 | r600_disable_interrupts(rdev); |
2189 | /* Wait and acknowledge irq */ | 2615 | /* Wait and acknowledge irq */ |
2190 | mdelay(1); | 2616 | mdelay(1); |
2191 | if (ASIC_IS_DCE3(rdev)) | 2617 | r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2); |
2192 | disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); | 2618 | r600_disable_interrupt_state(rdev); |
2193 | else | ||
2194 | disp_int = RREG32(DISP_INTERRUPT_STATUS); | ||
2195 | r600_irq_ack(rdev, disp_int); | ||
2196 | } | 2619 | } |
2197 | 2620 | ||
2198 | static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) | 2621 | static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) |
@@ -2249,7 +2672,7 @@ int r600_irq_process(struct radeon_device *rdev) | |||
2249 | u32 rptr = rdev->ih.rptr; | 2672 | u32 rptr = rdev->ih.rptr; |
2250 | u32 src_id, src_data; | 2673 | u32 src_id, src_data; |
2251 | u32 last_entry = rdev->ih.ring_size - 16; | 2674 | u32 last_entry = rdev->ih.ring_size - 16; |
2252 | u32 ring_index, disp_int; | 2675 | u32 ring_index, disp_int, disp_int_cont, disp_int_cont2; |
2253 | unsigned long flags; | 2676 | unsigned long flags; |
2254 | 2677 | ||
2255 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); | 2678 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); |
@@ -2267,11 +2690,7 @@ int r600_irq_process(struct radeon_device *rdev) | |||
2267 | 2690 | ||
2268 | restart_ih: | 2691 | restart_ih: |
2269 | /* display interrupts */ | 2692 | /* display interrupts */ |
2270 | if (ASIC_IS_DCE3(rdev)) | 2693 | r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2); |
2271 | disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); | ||
2272 | else | ||
2273 | disp_int = RREG32(DISP_INTERRUPT_STATUS); | ||
2274 | r600_irq_ack(rdev, disp_int); | ||
2275 | 2694 | ||
2276 | rdev->ih.wptr = wptr; | 2695 | rdev->ih.wptr = wptr; |
2277 | while (rptr != wptr) { | 2696 | while (rptr != wptr) { |
@@ -2321,6 +2740,49 @@ restart_ih: | |||
2321 | break; | 2740 | break; |
2322 | } | 2741 | } |
2323 | break; | 2742 | break; |
2743 | case 19: /* HPD/DAC hotplug */ | ||
2744 | switch (src_data) { | ||
2745 | case 0: | ||
2746 | if (disp_int & DC_HPD1_INTERRUPT) { | ||
2747 | disp_int &= ~DC_HPD1_INTERRUPT; | ||
2748 | DRM_INFO("IH: HPD1\n"); | ||
2749 | } | ||
2750 | break; | ||
2751 | case 1: | ||
2752 | if (disp_int & DC_HPD2_INTERRUPT) { | ||
2753 | disp_int &= ~DC_HPD2_INTERRUPT; | ||
2754 | DRM_INFO("IH: HPD2\n"); | ||
2755 | } | ||
2756 | break; | ||
2757 | case 4: | ||
2758 | if (disp_int_cont & DC_HPD3_INTERRUPT) { | ||
2759 | disp_int_cont &= ~DC_HPD3_INTERRUPT; | ||
2760 | DRM_INFO("IH: HPD3\n"); | ||
2761 | } | ||
2762 | break; | ||
2763 | case 5: | ||
2764 | if (disp_int_cont & DC_HPD4_INTERRUPT) { | ||
2765 | disp_int_cont &= ~DC_HPD4_INTERRUPT; | ||
2766 | DRM_INFO("IH: HPD4\n"); | ||
2767 | } | ||
2768 | break; | ||
2769 | case 10: | ||
2770 | if (disp_int_cont2 & DC_HPD5_INTERRUPT) { | ||
2771 | disp_int_cont &= ~DC_HPD5_INTERRUPT; | ||
2772 | DRM_INFO("IH: HPD5\n"); | ||
2773 | } | ||
2774 | break; | ||
2775 | case 12: | ||
2776 | if (disp_int_cont2 & DC_HPD6_INTERRUPT) { | ||
2777 | disp_int_cont &= ~DC_HPD6_INTERRUPT; | ||
2778 | DRM_INFO("IH: HPD6\n"); | ||
2779 | } | ||
2780 | break; | ||
2781 | default: | ||
2782 | DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); | ||
2783 | break; | ||
2784 | } | ||
2785 | break; | ||
2324 | case 176: /* CP_INT in ring buffer */ | 2786 | case 176: /* CP_INT in ring buffer */ |
2325 | case 177: /* CP_INT in IB1 */ | 2787 | case 177: /* CP_INT in IB1 */ |
2326 | case 178: /* CP_INT in IB2 */ | 2788 | case 178: /* CP_INT in IB2 */ |