Rev 1986 | Rev 2005 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1986 | Rev 2004 | ||
---|---|---|---|
Line 287... | Line 287... | ||
287 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
287 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
288 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
288 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
289 | switch (radeon_connector->hpd.hpd) { |
289 | switch (radeon_connector->hpd.hpd) { |
290 | case RADEON_HPD_1: |
290 | case RADEON_HPD_1: |
291 | WREG32(DC_HPD1_CONTROL, tmp); |
291 | WREG32(DC_HPD1_CONTROL, tmp); |
292 | // rdev->irq.hpd[0] = true; |
292 | rdev->irq.hpd[0] = true; |
293 | break; |
293 | break; |
294 | case RADEON_HPD_2: |
294 | case RADEON_HPD_2: |
295 | WREG32(DC_HPD2_CONTROL, tmp); |
295 | WREG32(DC_HPD2_CONTROL, tmp); |
296 | // rdev->irq.hpd[1] = true; |
296 | rdev->irq.hpd[1] = true; |
297 | break; |
297 | break; |
298 | case RADEON_HPD_3: |
298 | case RADEON_HPD_3: |
299 | WREG32(DC_HPD3_CONTROL, tmp); |
299 | WREG32(DC_HPD3_CONTROL, tmp); |
300 | // rdev->irq.hpd[2] = true; |
300 | rdev->irq.hpd[2] = true; |
301 | break; |
301 | break; |
302 | case RADEON_HPD_4: |
302 | case RADEON_HPD_4: |
303 | WREG32(DC_HPD4_CONTROL, tmp); |
303 | WREG32(DC_HPD4_CONTROL, tmp); |
304 | // rdev->irq.hpd[3] = true; |
304 | rdev->irq.hpd[3] = true; |
305 | break; |
305 | break; |
306 | /* DCE 3.2 */ |
306 | /* DCE 3.2 */ |
307 | case RADEON_HPD_5: |
307 | case RADEON_HPD_5: |
308 | WREG32(DC_HPD5_CONTROL, tmp); |
308 | WREG32(DC_HPD5_CONTROL, tmp); |
309 | // rdev->irq.hpd[4] = true; |
309 | rdev->irq.hpd[4] = true; |
310 | break; |
310 | break; |
311 | case RADEON_HPD_6: |
311 | case RADEON_HPD_6: |
312 | WREG32(DC_HPD6_CONTROL, tmp); |
312 | WREG32(DC_HPD6_CONTROL, tmp); |
313 | // rdev->irq.hpd[5] = true; |
313 | rdev->irq.hpd[5] = true; |
314 | break; |
314 | break; |
315 | default: |
315 | default: |
316 | break; |
316 | break; |
317 | } |
317 | } |
318 | } |
318 | } |
Line 320... | Line 320... | ||
320 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
320 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
321 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
321 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
322 | switch (radeon_connector->hpd.hpd) { |
322 | switch (radeon_connector->hpd.hpd) { |
323 | case RADEON_HPD_1: |
323 | case RADEON_HPD_1: |
324 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
324 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
325 | // rdev->irq.hpd[0] = true; |
325 | rdev->irq.hpd[0] = true; |
326 | break; |
326 | break; |
327 | case RADEON_HPD_2: |
327 | case RADEON_HPD_2: |
328 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
328 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
329 | // rdev->irq.hpd[1] = true; |
329 | rdev->irq.hpd[1] = true; |
330 | break; |
330 | break; |
331 | case RADEON_HPD_3: |
331 | case RADEON_HPD_3: |
332 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
332 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
333 | // rdev->irq.hpd[2] = true; |
333 | rdev->irq.hpd[2] = true; |
334 | break; |
334 | break; |
335 | default: |
335 | default: |
336 | break; |
336 | break; |
337 | } |
337 | } |
338 | } |
338 | } |
339 | } |
339 | } |
340 | // if (rdev->irq.installed) |
340 | if (rdev->irq.installed) |
341 | // r600_irq_set(rdev); |
341 | r600_irq_set(rdev); |
342 | } |
342 | } |
Line 343... | Line 343... | ||
343 | 343 | ||
344 | void r600_hpd_fini(struct radeon_device *rdev) |
344 | void r600_hpd_fini(struct radeon_device *rdev) |
345 | { |
345 | { |
Line 350... | Line 350... | ||
350 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
350 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
351 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
351 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
352 | switch (radeon_connector->hpd.hpd) { |
352 | switch (radeon_connector->hpd.hpd) { |
353 | case RADEON_HPD_1: |
353 | case RADEON_HPD_1: |
354 | WREG32(DC_HPD1_CONTROL, 0); |
354 | WREG32(DC_HPD1_CONTROL, 0); |
355 | // rdev->irq.hpd[0] = false; |
355 | rdev->irq.hpd[0] = false; |
356 | break; |
356 | break; |
357 | case RADEON_HPD_2: |
357 | case RADEON_HPD_2: |
358 | WREG32(DC_HPD2_CONTROL, 0); |
358 | WREG32(DC_HPD2_CONTROL, 0); |
359 | // rdev->irq.hpd[1] = false; |
359 | rdev->irq.hpd[1] = false; |
360 | break; |
360 | break; |
361 | case RADEON_HPD_3: |
361 | case RADEON_HPD_3: |
362 | WREG32(DC_HPD3_CONTROL, 0); |
362 | WREG32(DC_HPD3_CONTROL, 0); |
363 | // rdev->irq.hpd[2] = false; |
363 | rdev->irq.hpd[2] = false; |
364 | break; |
364 | break; |
365 | case RADEON_HPD_4: |
365 | case RADEON_HPD_4: |
366 | WREG32(DC_HPD4_CONTROL, 0); |
366 | WREG32(DC_HPD4_CONTROL, 0); |
367 | // rdev->irq.hpd[3] = false; |
367 | rdev->irq.hpd[3] = false; |
368 | break; |
368 | break; |
369 | /* DCE 3.2 */ |
369 | /* DCE 3.2 */ |
370 | case RADEON_HPD_5: |
370 | case RADEON_HPD_5: |
371 | WREG32(DC_HPD5_CONTROL, 0); |
371 | WREG32(DC_HPD5_CONTROL, 0); |
372 | // rdev->irq.hpd[4] = false; |
372 | rdev->irq.hpd[4] = false; |
373 | break; |
373 | break; |
374 | case RADEON_HPD_6: |
374 | case RADEON_HPD_6: |
375 | WREG32(DC_HPD6_CONTROL, 0); |
375 | WREG32(DC_HPD6_CONTROL, 0); |
376 | // rdev->irq.hpd[5] = false; |
376 | rdev->irq.hpd[5] = false; |
377 | break; |
377 | break; |
378 | default: |
378 | default: |
379 | break; |
379 | break; |
380 | } |
380 | } |
381 | } |
381 | } |
Line 383... | Line 383... | ||
383 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
383 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
384 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
384 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
385 | switch (radeon_connector->hpd.hpd) { |
385 | switch (radeon_connector->hpd.hpd) { |
386 | case RADEON_HPD_1: |
386 | case RADEON_HPD_1: |
387 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); |
387 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); |
388 | // rdev->irq.hpd[0] = false; |
388 | rdev->irq.hpd[0] = false; |
389 | break; |
389 | break; |
390 | case RADEON_HPD_2: |
390 | case RADEON_HPD_2: |
391 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); |
391 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); |
392 | // rdev->irq.hpd[1] = false; |
392 | rdev->irq.hpd[1] = false; |
393 | break; |
393 | break; |
394 | case RADEON_HPD_3: |
394 | case RADEON_HPD_3: |
395 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); |
395 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); |
396 | // rdev->irq.hpd[2] = false; |
396 | rdev->irq.hpd[2] = false; |
397 | break; |
397 | break; |
398 | default: |
398 | default: |
399 | break; |
399 | break; |
400 | } |
400 | } |
401 | } |
401 | } |
Line 1953... | Line 1953... | ||
1953 | 1953 | ||
1954 | if (r600_debugfs_mc_info_init(rdev)) { |
1954 | if (r600_debugfs_mc_info_init(rdev)) { |
1955 | DRM_ERROR("Failed to register debugfs file for mc !\n"); |
1955 | DRM_ERROR("Failed to register debugfs file for mc !\n"); |
1956 | } |
1956 | } |
1957 | /* This don't do much */ |
1957 | /* This don't do much */ |
1958 | // r = radeon_gem_init(rdev); |
1958 | r = radeon_gem_init(rdev); |
1959 | // if (r) |
1959 | if (r) |
1960 | // return r; |
1960 | return r; |
1961 | /* Read BIOS */ |
1961 | /* Read BIOS */ |
1962 | if (!radeon_get_bios(rdev)) { |
1962 | if (!radeon_get_bios(rdev)) { |
1963 | if (ASIC_IS_AVIVO(rdev)) |
1963 | if (ASIC_IS_AVIVO(rdev)) |
1964 | return -EINVAL; |
1964 | return -EINVAL; |
Line 1985... | Line 1985... | ||
1985 | /* Initialize surface registers */ |
1985 | /* Initialize surface registers */ |
1986 | radeon_surface_init(rdev); |
1986 | radeon_surface_init(rdev); |
1987 | /* Initialize clocks */ |
1987 | /* Initialize clocks */ |
1988 | radeon_get_clock_info(rdev->ddev); |
1988 | radeon_get_clock_info(rdev->ddev); |
1989 | /* Fence driver */ |
1989 | /* Fence driver */ |
1990 | // r = radeon_fence_driver_init(rdev); |
1990 | r = radeon_fence_driver_init(rdev); |
1991 | // if (r) |
1991 | if (r) |
1992 | // return r; |
1992 | return r; |
1993 | if (rdev->flags & RADEON_IS_AGP) { |
1993 | if (rdev->flags & RADEON_IS_AGP) { |
1994 | r = radeon_agp_init(rdev); |
1994 | r = radeon_agp_init(rdev); |
1995 | if (r) |
1995 | if (r) |
1996 | radeon_agp_disable(rdev); |
1996 | radeon_agp_disable(rdev); |
1997 | } |
1997 | } |
Line 2001... | Line 2001... | ||
2001 | /* Memory manager */ |
2001 | /* Memory manager */ |
2002 | r = radeon_bo_init(rdev); |
2002 | r = radeon_bo_init(rdev); |
2003 | if (r) |
2003 | if (r) |
2004 | return r; |
2004 | return r; |
Line 2005... | Line 2005... | ||
2005 | 2005 | ||
2006 | // r = radeon_irq_kms_init(rdev); |
2006 | r = radeon_irq_kms_init(rdev); |
2007 | // if (r) |
2007 | if (r) |
Line 2008... | Line 2008... | ||
2008 | // return r; |
2008 | return r; |
2009 | 2009 | ||
Line 2010... | Line 2010... | ||
2010 | rdev->cp.ring_obj = NULL; |
2010 | rdev->cp.ring_obj = NULL; |
2011 | r600_ring_init(rdev, 1024 * 1024); |
2011 | r600_ring_init(rdev, 1024 * 1024); |
Line 2012... | Line 2012... | ||
2012 | 2012 | ||
2013 | // rdev->ih.ring_obj = NULL; |
2013 | rdev->ih.ring_obj = NULL; |
2014 | // r600_ih_ring_init(rdev, 64 * 1024); |
2014 | r600_ih_ring_init(rdev, 64 * 1024); |
Line 2037... | Line 2037... | ||
2037 | // if (r) { |
2037 | // if (r) { |
2038 | // DRM_ERROR("radeon: failled testing IB (%d).\n", r); |
2038 | // DRM_ERROR("radeon: failled testing IB (%d).\n", r); |
2039 | // rdev->accel_working = false; |
2039 | // rdev->accel_working = false; |
2040 | // } |
2040 | // } |
2041 | } |
2041 | } |
- | 2042 | if (r) |
|
- | 2043 | return r; /* TODO error handling */ |
|
2042 | return 0; |
2044 | return 0; |
2043 | } |
2045 | } |
Line -... | Line 2046... | ||
- | 2046 | ||
- | 2047 | /* |
|
- | 2048 | * CS stuff |
|
- | 2049 | */ |
|
- | 2050 | void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) |
|
- | 2051 | { |
|
- | 2052 | /* FIXME: implement */ |
|
- | 2053 | radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); |
|
- | 2054 | radeon_ring_write(rdev, |
|
- | 2055 | #ifdef __BIG_ENDIAN |
|
- | 2056 | (2 << 0) | |
|
- | 2057 | #endif |
|
- | 2058 | (ib->gpu_addr & 0xFFFFFFFC)); |
|
- | 2059 | radeon_ring_write(rdev, upper_32_bits(ib->gpu_addr) & 0xFF); |
|
- | 2060 | radeon_ring_write(rdev, ib->length_dw); |
|
- | 2061 | } |
|
- | 2062 | ||
- | 2063 | int r600_ib_test(struct radeon_device *rdev) |
|
- | 2064 | { |
|
- | 2065 | struct radeon_ib *ib; |
|
- | 2066 | uint32_t scratch; |
|
- | 2067 | uint32_t tmp = 0; |
|
- | 2068 | unsigned i; |
|
- | 2069 | int r; |
|
- | 2070 | ||
- | 2071 | r = radeon_scratch_get(rdev, &scratch); |
|
- | 2072 | if (r) { |
|
- | 2073 | DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r); |
|
- | 2074 | return r; |
|
- | 2075 | } |
|
- | 2076 | WREG32(scratch, 0xCAFEDEAD); |
|
- | 2077 | r = radeon_ib_get(rdev, &ib); |
|
- | 2078 | if (r) { |
|
- | 2079 | DRM_ERROR("radeon: failed to get ib (%d).\n", r); |
|
- | 2080 | return r; |
|
- | 2081 | } |
|
- | 2082 | ib->ptr[0] = PACKET3(PACKET3_SET_CONFIG_REG, 1); |
|
- | 2083 | ib->ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); |
|
- | 2084 | ib->ptr[2] = 0xDEADBEEF; |
|
- | 2085 | ib->ptr[3] = PACKET2(0); |
|
- | 2086 | ib->ptr[4] = PACKET2(0); |
|
- | 2087 | ib->ptr[5] = PACKET2(0); |
|
- | 2088 | ib->ptr[6] = PACKET2(0); |
|
- | 2089 | ib->ptr[7] = PACKET2(0); |
|
- | 2090 | ib->ptr[8] = PACKET2(0); |
|
- | 2091 | ib->ptr[9] = PACKET2(0); |
|
- | 2092 | ib->ptr[10] = PACKET2(0); |
|
- | 2093 | ib->ptr[11] = PACKET2(0); |
|
- | 2094 | ib->ptr[12] = PACKET2(0); |
|
- | 2095 | ib->ptr[13] = PACKET2(0); |
|
- | 2096 | ib->ptr[14] = PACKET2(0); |
|
- | 2097 | ib->ptr[15] = PACKET2(0); |
|
- | 2098 | ib->length_dw = 16; |
|
- | 2099 | r = radeon_ib_schedule(rdev, ib); |
|
- | 2100 | if (r) { |
|
- | 2101 | radeon_scratch_free(rdev, scratch); |
|
- | 2102 | radeon_ib_free(rdev, &ib); |
|
- | 2103 | DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); |
|
- | 2104 | return r; |
|
- | 2105 | } |
|
- | 2106 | r = radeon_fence_wait(ib->fence, false); |
|
- | 2107 | if (r) { |
|
- | 2108 | DRM_ERROR("radeon: fence wait failed (%d).\n", r); |
|
- | 2109 | return r; |
|
- | 2110 | } |
|
- | 2111 | for (i = 0; i < rdev->usec_timeout; i++) { |
|
- | 2112 | tmp = RREG32(scratch); |
|
- | 2113 | if (tmp == 0xDEADBEEF) |
|
- | 2114 | break; |
|
- | 2115 | DRM_UDELAY(1); |
|
- | 2116 | } |
|
- | 2117 | if (i < rdev->usec_timeout) { |
|
- | 2118 | DRM_INFO("ib test succeeded in %u usecs\n", i); |
|
- | 2119 | } else { |
|
- | 2120 | DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n", |
|
- | 2121 | scratch, tmp); |
|
- | 2122 | r = -EINVAL; |
|
- | 2123 | } |
|
- | 2124 | radeon_scratch_free(rdev, scratch); |
|
- | 2125 | radeon_ib_free(rdev, &ib); |
|
- | 2126 | return r; |
|
- | 2127 | } |
|
- | 2128 | ||
- | 2129 | /* |
|
- | 2130 | * Interrupts |
|
- | 2131 | * |
|
- | 2132 | * Interrupts use a ring buffer on r6xx/r7xx hardware. It works pretty |
|
- | 2133 | * the same as the CP ring buffer, but in reverse. Rather than the CPU |
|
- | 2134 | * writing to the ring and the GPU consuming, the GPU writes to the ring |
|
- | 2135 | * and host consumes. As the host irq handler processes interrupts, it |
|
- | 2136 | * increments the rptr. When the rptr catches up with the wptr, all the |
|
- | 2137 | * current interrupts have been processed. |
|
- | 2138 | */ |
|
- | 2139 | ||
- | 2140 | void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size) |
|
- | 2141 | { |
|
- | 2142 | u32 rb_bufsz; |
|
- | 2143 | ||
- | 2144 | /* Align ring size */ |
|
- | 2145 | rb_bufsz = drm_order(ring_size / 4); |
|
- | 2146 | ring_size = (1 << rb_bufsz) * 4; |
|
- | 2147 | rdev->ih.ring_size = ring_size; |
|
- | 2148 | rdev->ih.ptr_mask = rdev->ih.ring_size - 1; |
|
- | 2149 | rdev->ih.rptr = 0; |
|
- | 2150 | } |
|
- | 2151 | ||
- | 2152 | static int r600_ih_ring_alloc(struct radeon_device *rdev) |
|
- | 2153 | { |
|
- | 2154 | int r; |
|
- | 2155 | ||
- | 2156 | /* Allocate ring buffer */ |
|
- | 2157 | if (rdev->ih.ring_obj == NULL) { |
|
- | 2158 | r = radeon_bo_create(rdev, rdev->ih.ring_size, |
|
- | 2159 | PAGE_SIZE, true, |
|
- | 2160 | RADEON_GEM_DOMAIN_GTT, |
|
- | 2161 | &rdev->ih.ring_obj); |
|
- | 2162 | if (r) { |
|
- | 2163 | DRM_ERROR("radeon: failed to create ih ring buffer (%d).\n", r); |
|
- | 2164 | return r; |
|
- | 2165 | } |
|
- | 2166 | r = radeon_bo_reserve(rdev->ih.ring_obj, false); |
|
- | 2167 | if (unlikely(r != 0)) |
|
- | 2168 | return r; |
|
- | 2169 | r = radeon_bo_pin(rdev->ih.ring_obj, |
|
- | 2170 | RADEON_GEM_DOMAIN_GTT, |
|
- | 2171 | &rdev->ih.gpu_addr); |
|
- | 2172 | if (r) { |
|
- | 2173 | radeon_bo_unreserve(rdev->ih.ring_obj); |
|
- | 2174 | DRM_ERROR("radeon: failed to pin ih ring buffer (%d).\n", r); |
|
- | 2175 | return r; |
|
- | 2176 | } |
|
- | 2177 | r = radeon_bo_kmap(rdev->ih.ring_obj, |
|
- | 2178 | (void **)&rdev->ih.ring); |
|
- | 2179 | radeon_bo_unreserve(rdev->ih.ring_obj); |
|
- | 2180 | if (r) { |
|
- | 2181 | DRM_ERROR("radeon: failed to map ih ring buffer (%d).\n", r); |
|
- | 2182 | return r; |
|
- | 2183 | } |
|
- | 2184 | } |
|
- | 2185 | return 0; |
|
- | 2186 | } |
|
- | 2187 | ||
- | 2188 | static void r600_ih_ring_fini(struct radeon_device *rdev) |
|
- | 2189 | { |
|
- | 2190 | int r; |
|
- | 2191 | if (rdev->ih.ring_obj) { |
|
- | 2192 | r = radeon_bo_reserve(rdev->ih.ring_obj, false); |
|
- | 2193 | if (likely(r == 0)) { |
|
- | 2194 | radeon_bo_kunmap(rdev->ih.ring_obj); |
|
- | 2195 | radeon_bo_unpin(rdev->ih.ring_obj); |
|
- | 2196 | radeon_bo_unreserve(rdev->ih.ring_obj); |
|
- | 2197 | } |
|
- | 2198 | radeon_bo_unref(&rdev->ih.ring_obj); |
|
- | 2199 | rdev->ih.ring = NULL; |
|
- | 2200 | rdev->ih.ring_obj = NULL; |
|
- | 2201 | } |
|
- | 2202 | } |
|
- | 2203 | ||
- | 2204 | void r600_rlc_stop(struct radeon_device *rdev) |
|
- | 2205 | { |
|
- | 2206 | ||
- | 2207 | if ((rdev->family >= CHIP_RV770) && |
|
- | 2208 | (rdev->family <= CHIP_RV740)) { |
|
- | 2209 | /* r7xx asics need to soft reset RLC before halting */ |
|
- | 2210 | WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC); |
|
- | 2211 | RREG32(SRBM_SOFT_RESET); |
|
- | 2212 | udelay(15000); |
|
- | 2213 | WREG32(SRBM_SOFT_RESET, 0); |
|
- | 2214 | RREG32(SRBM_SOFT_RESET); |
|
- | 2215 | } |
|
- | 2216 | ||
- | 2217 | WREG32(RLC_CNTL, 0); |
|
- | 2218 | } |
|
- | 2219 | ||
- | 2220 | static void r600_rlc_start(struct radeon_device *rdev) |
|
- | 2221 | { |
|
- | 2222 | WREG32(RLC_CNTL, RLC_ENABLE); |
|
- | 2223 | } |
|
- | 2224 | ||
- | 2225 | static int r600_rlc_init(struct radeon_device *rdev) |
|
- | 2226 | { |
|
- | 2227 | u32 i; |
|
- | 2228 | const __be32 *fw_data; |
|
- | 2229 | ||
- | 2230 | if (!rdev->rlc_fw) |
|
- | 2231 | return -EINVAL; |
|
- | 2232 | ||
- | 2233 | r600_rlc_stop(rdev); |
|
- | 2234 | ||
- | 2235 | WREG32(RLC_HB_BASE, 0); |
|
- | 2236 | WREG32(RLC_HB_CNTL, 0); |
|
- | 2237 | WREG32(RLC_HB_RPTR, 0); |
|
- | 2238 | WREG32(RLC_HB_WPTR, 0); |
|
- | 2239 | if (rdev->family <= CHIP_CAICOS) { |
|
- | 2240 | WREG32(RLC_HB_WPTR_LSB_ADDR, 0); |
|
- | 2241 | WREG32(RLC_HB_WPTR_MSB_ADDR, 0); |
|
- | 2242 | } |
|
- | 2243 | WREG32(RLC_MC_CNTL, 0); |
|
- | 2244 | WREG32(RLC_UCODE_CNTL, 0); |
|
- | 2245 | ||
- | 2246 | fw_data = (const __be32 *)rdev->rlc_fw->data; |
|
- | 2247 | if (rdev->family >= CHIP_CAYMAN) { |
|
- | 2248 | for (i = 0; i < CAYMAN_RLC_UCODE_SIZE; i++) { |
|
- | 2249 | WREG32(RLC_UCODE_ADDR, i); |
|
- | 2250 | WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); |
|
- | 2251 | } |
|
- | 2252 | } else if (rdev->family >= CHIP_CEDAR) { |
|
- | 2253 | for (i = 0; i < EVERGREEN_RLC_UCODE_SIZE; i++) { |
|
- | 2254 | WREG32(RLC_UCODE_ADDR, i); |
|
- | 2255 | WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); |
|
- | 2256 | } |
|
- | 2257 | } else if (rdev->family >= CHIP_RV770) { |
|
- | 2258 | for (i = 0; i < R700_RLC_UCODE_SIZE; i++) { |
|
- | 2259 | WREG32(RLC_UCODE_ADDR, i); |
|
- | 2260 | WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); |
|
- | 2261 | } |
|
- | 2262 | } else { |
|
- | 2263 | for (i = 0; i < RLC_UCODE_SIZE; i++) { |
|
- | 2264 | WREG32(RLC_UCODE_ADDR, i); |
|
- | 2265 | WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); |
|
- | 2266 | } |
|
- | 2267 | } |
|
- | 2268 | WREG32(RLC_UCODE_ADDR, 0); |
|
- | 2269 | ||
- | 2270 | r600_rlc_start(rdev); |
|
- | 2271 | ||
- | 2272 | return 0; |
|
- | 2273 | } |
|
- | 2274 | ||
- | 2275 | static void r600_enable_interrupts(struct radeon_device *rdev) |
|
- | 2276 | { |
|
- | 2277 | u32 ih_cntl = RREG32(IH_CNTL); |
|
- | 2278 | u32 ih_rb_cntl = RREG32(IH_RB_CNTL); |
|
- | 2279 | ||
- | 2280 | ih_cntl |= ENABLE_INTR; |
|
- | 2281 | ih_rb_cntl |= IH_RB_ENABLE; |
|
- | 2282 | WREG32(IH_CNTL, ih_cntl); |
|
- | 2283 | WREG32(IH_RB_CNTL, ih_rb_cntl); |
|
- | 2284 | rdev->ih.enabled = true; |
|
- | 2285 | } |
|
- | 2286 | ||
- | 2287 | void r600_disable_interrupts(struct radeon_device *rdev) |
|
- | 2288 | { |
|
- | 2289 | u32 ih_rb_cntl = RREG32(IH_RB_CNTL); |
|
- | 2290 | u32 ih_cntl = RREG32(IH_CNTL); |
|
- | 2291 | ||
- | 2292 | ih_rb_cntl &= ~IH_RB_ENABLE; |
|
- | 2293 | ih_cntl &= ~ENABLE_INTR; |
|
- | 2294 | WREG32(IH_RB_CNTL, ih_rb_cntl); |
|
- | 2295 | WREG32(IH_CNTL, ih_cntl); |
|
- | 2296 | /* set rptr, wptr to 0 */ |
|
- | 2297 | WREG32(IH_RB_RPTR, 0); |
|
- | 2298 | WREG32(IH_RB_WPTR, 0); |
|
- | 2299 | rdev->ih.enabled = false; |
|
- | 2300 | rdev->ih.wptr = 0; |
|
- | 2301 | rdev->ih.rptr = 0; |
|
- | 2302 | } |
|
2044 | 2303 | ||
2045 | static void r600_disable_interrupt_state(struct radeon_device *rdev) |
2304 | static void r600_disable_interrupt_state(struct radeon_device *rdev) |
2046 | { |
2305 | { |
Line 2047... | Line 2306... | ||
2047 | u32 tmp; |
2306 | u32 tmp; |
Line 2078... | Line 2337... | ||
2078 | tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; |
2337 | tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; |
2079 | WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); |
2338 | WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); |
2080 | } |
2339 | } |
2081 | } |
2340 | } |
Line -... | Line 2341... | ||
- | 2341 | ||
- | 2342 | int r600_irq_init(struct radeon_device *rdev) |
|
- | 2343 | { |
|
- | 2344 | int ret = 0; |
|
- | 2345 | int rb_bufsz; |
|
- | 2346 | u32 interrupt_cntl, ih_cntl, ih_rb_cntl; |
|
- | 2347 | ||
- | 2348 | /* allocate ring */ |
|
- | 2349 | ret = r600_ih_ring_alloc(rdev); |
|
- | 2350 | if (ret) |
|
- | 2351 | return ret; |
|
- | 2352 | ||
- | 2353 | /* disable irqs */ |
|
- | 2354 | r600_disable_interrupts(rdev); |
|
- | 2355 | ||
- | 2356 | /* init rlc */ |
|
- | 2357 | ret = r600_rlc_init(rdev); |
|
- | 2358 | if (ret) { |
|
- | 2359 | r600_ih_ring_fini(rdev); |
|
- | 2360 | return ret; |
|
- | 2361 | } |
|
- | 2362 | ||
- | 2363 | /* setup interrupt control */ |
|
- | 2364 | /* set dummy read address to ring address */ |
|
- | 2365 | WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8); |
|
- | 2366 | interrupt_cntl = RREG32(INTERRUPT_CNTL); |
|
- | 2367 | /* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi |
|
- | 2368 | * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN |
|
- | 2369 | */ |
|
- | 2370 | interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE; |
|
- | 2371 | /* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */ |
|
- | 2372 | interrupt_cntl &= ~IH_REQ_NONSNOOP_EN; |
|
- | 2373 | WREG32(INTERRUPT_CNTL, interrupt_cntl); |
|
- | 2374 | ||
- | 2375 | WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8); |
|
- | 2376 | rb_bufsz = drm_order(rdev->ih.ring_size / 4); |
|
- | 2377 | ||
- | 2378 | ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | |
|
- | 2379 | IH_WPTR_OVERFLOW_CLEAR | |
|
- | 2380 | (rb_bufsz << 1)); |
|
- | 2381 | ||
- | 2382 | if (rdev->wb.enabled) |
|
- | 2383 | ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE; |
|
- | 2384 | ||
- | 2385 | /* set the writeback address whether it's enabled or not */ |
|
- | 2386 | WREG32(IH_RB_WPTR_ADDR_LO, (rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFFFFFFFC); |
|
- | 2387 | WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFF); |
|
- | 2388 | ||
- | 2389 | WREG32(IH_RB_CNTL, ih_rb_cntl); |
|
- | 2390 | ||
- | 2391 | /* set rptr, wptr to 0 */ |
|
- | 2392 | WREG32(IH_RB_RPTR, 0); |
|
- | 2393 | WREG32(IH_RB_WPTR, 0); |
|
- | 2394 | ||
- | 2395 | /* Default settings for IH_CNTL (disabled at first) */ |
|
- | 2396 | ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10); |
|
- | 2397 | /* RPTR_REARM only works if msi's are enabled */ |
|
- | 2398 | if (rdev->msi_enabled) |
|
- | 2399 | ih_cntl |= RPTR_REARM; |
|
- | 2400 | ||
- | 2401 | #ifdef __BIG_ENDIAN |
|
- | 2402 | ih_cntl |= IH_MC_SWAP(IH_MC_SWAP_32BIT); |
|
- | 2403 | #endif |
|
- | 2404 | WREG32(IH_CNTL, ih_cntl); |
|
- | 2405 | ||
- | 2406 | /* force the active interrupt state to all disabled */ |
|
- | 2407 | if (rdev->family >= CHIP_CEDAR) |
|
- | 2408 | evergreen_disable_interrupt_state(rdev); |
|
- | 2409 | else |
|
- | 2410 | r600_disable_interrupt_state(rdev); |
|
- | 2411 | ||
- | 2412 | /* enable irqs */ |
|
- | 2413 | r600_enable_interrupts(rdev); |
|
- | 2414 | ||
- | 2415 | return ret; |
|
- | 2416 | } |
|
- | 2417 | int r600_irq_set(struct radeon_device *rdev) |
|
- | 2418 | { |
|
- | 2419 | u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; |
|
- | 2420 | u32 mode_int = 0; |
|
- | 2421 | u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; |
|
- | 2422 | u32 grbm_int_cntl = 0; |
|
- | 2423 | u32 hdmi1, hdmi2; |
|
- | 2424 | u32 d1grph = 0, d2grph = 0; |
|
- | 2425 | ||
Line -... | Line 2426... | ||
- | 2426 | ENTER(); |
|
- | 2427 | ||
- | 2428 | if (!rdev->irq.installed) { |
|
- | 2429 | WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); |
|
- | 2430 | return -EINVAL; |
|
- | 2431 | } |
|
- | 2432 | /* don't enable anything if the ih is disabled */ |
|
- | 2433 | if (!rdev->ih.enabled) { |
|
- | 2434 | r600_disable_interrupts(rdev); |
|
- | 2435 | /* force the active interrupt state to all disabled */ |
|
- | 2436 | r600_disable_interrupt_state(rdev); |
|
Line -... | Line 2437... | ||
- | 2437 | return 0; |
|
- | 2438 | } |
|
- | 2439 | ||
- | 2440 | hdmi1 = RREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN; |
|
- | 2441 | if (ASIC_IS_DCE3(rdev)) { |
|
- | 2442 | hdmi2 = RREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN; |
|
- | 2443 | hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; |
|
- | 2444 | hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; |
|
- | 2445 | hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; |
|
- | 2446 | hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN; |
|
- | 2447 | if (ASIC_IS_DCE32(rdev)) { |
|
- | 2448 | hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; |
|
- | 2449 | hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; |
|
- | 2450 | } |
|
- | 2451 | } else { |
|
- | 2452 | hdmi2 = RREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN; |
|
- | 2453 | hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN; |
|
- | 2454 | hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN; |
|
- | 2455 | hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN; |
|
- | 2456 | } |
|
- | 2457 | ||
- | 2458 | if (rdev->irq.sw_int) { |
|
- | 2459 | DRM_DEBUG("r600_irq_set: sw int\n"); |
|
- | 2460 | cp_int_cntl |= RB_INT_ENABLE; |
|
- | 2461 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; |
|
- | 2462 | } |
|
- | 2463 | if (rdev->irq.crtc_vblank_int[0] || |
|
- | 2464 | rdev->irq.pflip[0]) { |
|
- | 2465 | DRM_DEBUG("r600_irq_set: vblank 0\n"); |
|
- | 2466 | mode_int |= D1MODE_VBLANK_INT_MASK; |
|
- | 2467 | } |
|
- | 2468 | if (rdev->irq.crtc_vblank_int[1] || |
|
- | 2469 | rdev->irq.pflip[1]) { |
|
- | 2470 | DRM_DEBUG("r600_irq_set: vblank 1\n"); |
|
- | 2471 | mode_int |= D2MODE_VBLANK_INT_MASK; |
|
- | 2472 | } |
|
- | 2473 | if (rdev->irq.hpd[0]) { |
|
- | 2474 | DRM_DEBUG("r600_irq_set: hpd 1\n"); |
|
- | 2475 | hpd1 |= DC_HPDx_INT_EN; |
|
- | 2476 | } |
|
- | 2477 | if (rdev->irq.hpd[1]) { |
|
- | 2478 | DRM_DEBUG("r600_irq_set: hpd 2\n"); |
|
- | 2479 | hpd2 |= DC_HPDx_INT_EN; |
|
- | 2480 | } |
|
- | 2481 | if (rdev->irq.hpd[2]) { |
|
- | 2482 | DRM_DEBUG("r600_irq_set: hpd 3\n"); |
|
- | 2483 | hpd3 |= DC_HPDx_INT_EN; |
|
- | 2484 | } |
|
- | 2485 | if (rdev->irq.hpd[3]) { |
|
- | 2486 | DRM_DEBUG("r600_irq_set: hpd 4\n"); |
|
- | 2487 | hpd4 |= DC_HPDx_INT_EN; |
|
- | 2488 | } |
|
- | 2489 | if (rdev->irq.hpd[4]) { |
|
- | 2490 | DRM_DEBUG("r600_irq_set: hpd 5\n"); |
|
- | 2491 | hpd5 |= DC_HPDx_INT_EN; |
|
- | 2492 | } |
|
- | 2493 | if (rdev->irq.hpd[5]) { |
|
- | 2494 | DRM_DEBUG("r600_irq_set: hpd 6\n"); |
|
- | 2495 | hpd6 |= DC_HPDx_INT_EN; |
|
- | 2496 | } |
|
- | 2497 | if (rdev->irq.hdmi[0]) { |
|
- | 2498 | DRM_DEBUG("r600_irq_set: hdmi 1\n"); |
|
- | 2499 | hdmi1 |= R600_HDMI_INT_EN; |
|
- | 2500 | } |
|
- | 2501 | if (rdev->irq.hdmi[1]) { |
|
- | 2502 | DRM_DEBUG("r600_irq_set: hdmi 2\n"); |
|
- | 2503 | hdmi2 |= R600_HDMI_INT_EN; |
|
- | 2504 | } |
|
- | 2505 | if (rdev->irq.gui_idle) { |
|
- | 2506 | DRM_DEBUG("gui idle\n"); |
|
- | 2507 | grbm_int_cntl |= GUI_IDLE_INT_ENABLE; |
|
- | 2508 | } |
|
- | 2509 | ||
- | 2510 | WREG32(CP_INT_CNTL, cp_int_cntl); |
|
- | 2511 | WREG32(DxMODE_INT_MASK, mode_int); |
|
- | 2512 | WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph); |
|
- | 2513 | WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph); |
|
- | 2514 | WREG32(GRBM_INT_CNTL, grbm_int_cntl); |
|
- | 2515 | WREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, hdmi1); |
|
- | 2516 | if (ASIC_IS_DCE3(rdev)) { |
|
- | 2517 | WREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, hdmi2); |
|
- | 2518 | WREG32(DC_HPD1_INT_CONTROL, hpd1); |
|
- | 2519 | WREG32(DC_HPD2_INT_CONTROL, hpd2); |
|
- | 2520 | WREG32(DC_HPD3_INT_CONTROL, hpd3); |
|
- | 2521 | WREG32(DC_HPD4_INT_CONTROL, hpd4); |
|
- | 2522 | if (ASIC_IS_DCE32(rdev)) { |
|
- | 2523 | WREG32(DC_HPD5_INT_CONTROL, hpd5); |
|
- | 2524 | WREG32(DC_HPD6_INT_CONTROL, hpd6); |
|
- | 2525 | } |
|
- | 2526 | } else { |
|
- | 2527 | WREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, hdmi2); |
|
- | 2528 | WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); |
|
Line -... | Line 2529... | ||
- | 2529 | WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); |
|
Line -... | Line 2530... | ||
- | 2530 | WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3); |
|
- | 2531 | } |
|
Line -... | Line 2532... | ||
- | 2532 | ||
- | 2533 | LEAVE(); |
|
- | 2534 | ||
Line -... | Line 2535... | ||
- | 2535 | return 0; |
|
- | 2536 | } |
|
- | 2537 | ||
- | 2538 | static inline void r600_irq_ack(struct radeon_device *rdev) |
|
- | 2539 | { |
|
- | 2540 | u32 tmp; |
|
- | 2541 | ||
- | 2542 | if (ASIC_IS_DCE3(rdev)) { |
|
- | 2543 | rdev->irq.stat_regs.r600.disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); |
|
- | 2544 | rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); |
|
- | 2545 | rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); |
|
- | 2546 | } else { |
|
- | 2547 | rdev->irq.stat_regs.r600.disp_int = RREG32(DISP_INTERRUPT_STATUS); |
|
- | 2548 | rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); |
|
- | 2549 | rdev->irq.stat_regs.r600.disp_int_cont2 = 0; |
|
- | 2550 | } |
|
- | 2551 | rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS); |
|
- | 2552 | rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS); |
|
- | 2553 | ||
- | 2554 | if (rdev->irq.stat_regs.r600.d1grph_int & DxGRPH_PFLIP_INT_OCCURRED) |
|
- | 2555 | WREG32(D1GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR); |
|
- | 2556 | if (rdev->irq.stat_regs.r600.d2grph_int & DxGRPH_PFLIP_INT_OCCURRED) |
|
- | 2557 | WREG32(D2GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR); |
|
- | 2558 | if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) |
|
- | 2559 | WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); |
|
- | 2560 | if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) |
|
- | 2561 | WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK); |
|
- | 2562 | if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) |
|
- | 2563 | WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); |
|
- | 2564 | if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) |
|
- | 2565 | WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK); |
|
- | 2566 | if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { |
|
- | 2567 | if (ASIC_IS_DCE3(rdev)) { |
|
- | 2568 | tmp = RREG32(DC_HPD1_INT_CONTROL); |
|
- | 2569 | tmp |= DC_HPDx_INT_ACK; |
|
- | 2570 | WREG32(DC_HPD1_INT_CONTROL, tmp); |
|
- | 2571 | } else { |
|
- | 2572 | tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL); |
|
- | 2573 | tmp |= DC_HPDx_INT_ACK; |
|
- | 2574 | WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); |
|
- | 2575 | } |
|
- | 2576 | } |
|
- | 2577 | if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { |
|
- | 2578 | if (ASIC_IS_DCE3(rdev)) { |
|
- | 2579 | tmp = RREG32(DC_HPD2_INT_CONTROL); |
|
- | 2580 | tmp |= DC_HPDx_INT_ACK; |
|
- | 2581 | WREG32(DC_HPD2_INT_CONTROL, tmp); |
|
- | 2582 | } else { |
|
- | 2583 | tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL); |
|
- | 2584 | tmp |= DC_HPDx_INT_ACK; |
|
- | 2585 | WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); |
|
- | 2586 | } |
|
- | 2587 | } |
|
- | 2588 | if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { |
|
- | 2589 | if (ASIC_IS_DCE3(rdev)) { |
|
- | 2590 | tmp = RREG32(DC_HPD3_INT_CONTROL); |
|
- | 2591 | tmp |= DC_HPDx_INT_ACK; |
|
- | 2592 | WREG32(DC_HPD3_INT_CONTROL, tmp); |
|
- | 2593 | } else { |
|
- | 2594 | tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL); |
|
- | 2595 | tmp |= DC_HPDx_INT_ACK; |
|
- | 2596 | WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); |
|
- | 2597 | } |
|
- | 2598 | } |
|
- | 2599 | if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { |
|
- | 2600 | tmp = RREG32(DC_HPD4_INT_CONTROL); |
|
- | 2601 | tmp |= DC_HPDx_INT_ACK; |
|
- | 2602 | WREG32(DC_HPD4_INT_CONTROL, tmp); |
|
- | 2603 | } |
|
- | 2604 | if (ASIC_IS_DCE32(rdev)) { |
|
- | 2605 | if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { |
|
- | 2606 | tmp = RREG32(DC_HPD5_INT_CONTROL); |
|
- | 2607 | tmp |= DC_HPDx_INT_ACK; |
|
- | 2608 | WREG32(DC_HPD5_INT_CONTROL, tmp); |
|
- | 2609 | } |
|
- | 2610 | if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { |
|
- | 2611 | tmp = RREG32(DC_HPD5_INT_CONTROL); |
|
- | 2612 | tmp |= DC_HPDx_INT_ACK; |
|
- | 2613 | WREG32(DC_HPD6_INT_CONTROL, tmp); |
|
- | 2614 | } |
|
- | 2615 | } |
|
- | 2616 | if (RREG32(R600_HDMI_BLOCK1 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) { |
|
- | 2617 | WREG32_P(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK); |
|
- | 2618 | } |
|
- | 2619 | if (ASIC_IS_DCE3(rdev)) { |
|
- | 2620 | if (RREG32(R600_HDMI_BLOCK3 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) { |
|
- | 2621 | WREG32_P(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK); |
|
- | 2622 | } |
|
- | 2623 | } else { |
|
- | 2624 | if (RREG32(R600_HDMI_BLOCK2 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) { |
|
- | 2625 | WREG32_P(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK); |
|
- | 2626 | } |
|
- | 2627 | } |
|
- | 2628 | } |
|
- | 2629 | ||
- | 2630 | static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) |
|
- | 2631 | { |
|
- | 2632 | u32 wptr, tmp; |
|
- | 2633 | ||
- | 2634 | if (rdev->wb.enabled) |
|
- | 2635 | wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]); |
|
- | 2636 | else |
|
- | 2637 | wptr = RREG32(IH_RB_WPTR); |
|
- | 2638 | ||
- | 2639 | if (wptr & RB_OVERFLOW) { |
|
- | 2640 | /* When a ring buffer overflow happen start parsing interrupt |
|
- | 2641 | * from the last not overwritten vector (wptr + 16). Hopefully |
|
- | 2642 | * this should allow us to catchup. |
|
- | 2643 | */ |
|
- | 2644 | dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n", |
|
- | 2645 | wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask); |
|
- | 2646 | rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask; |
|
- | 2647 | tmp = RREG32(IH_RB_CNTL); |
|
- | 2648 | tmp |= IH_WPTR_OVERFLOW_CLEAR; |
|
- | 2649 | WREG32(IH_RB_CNTL, tmp); |
|
- | 2650 | } |
|
- | 2651 | return (wptr & rdev->ih.ptr_mask); |
|
- | 2652 | } |
|
- | 2653 | ||
- | 2654 | /* r600 IV Ring |
|
- | 2655 | * Each IV ring entry is 128 bits: |
|
- | 2656 | * [7:0] - interrupt source id |
|
- | 2657 | * [31:8] - reserved |
|
- | 2658 | * [59:32] - interrupt source data |
|
- | 2659 | * [127:60] - reserved |
|
- | 2660 | * |
|
- | 2661 | * The basic interrupt vector entries |
|
- | 2662 | * are decoded as follows: |
|
- | 2663 | * src_id src_data description |
|
- | 2664 | * 1 0 D1 Vblank |
|
- | 2665 | * 1 1 D1 Vline |
|
- | 2666 | * 5 0 D2 Vblank |
|
- | 2667 | * 5 1 D2 Vline |
|
- | 2668 | * 19 0 FP Hot plug detection A |
|
- | 2669 | * 19 1 FP Hot plug detection B |
|
- | 2670 | * 19 2 DAC A auto-detection |
|
- | 2671 | * 19 3 DAC B auto-detection |
|
- | 2672 | * 21 4 HDMI block A |
|
- | 2673 | * 21 5 HDMI block B |
|
- | 2674 | * 176 - CP_INT RB |
|
- | 2675 | * 177 - CP_INT IB1 |
|
- | 2676 | * 178 - CP_INT IB2 |
|
- | 2677 | * 181 - EOP Interrupt |
|
- | 2678 | * 233 - GUI Idle |
|
- | 2679 | * |
|
- | 2680 | * Note, these are based on r600 and may need to be |
|
- | 2681 | * adjusted or added to on newer asics |
|
- | 2682 | */ |
|
- | 2683 | ||
- | 2684 | int r600_irq_process(struct radeon_device *rdev) |
|
- | 2685 | { |
|
- | 2686 | u32 wptr; |
|
- | 2687 | u32 rptr; |
|
- | 2688 | u32 src_id, src_data; |
|
- | 2689 | u32 ring_index; |
|
- | 2690 | unsigned long flags; |
|
- | 2691 | bool queue_hotplug = false; |
|
- | 2692 | ||
- | 2693 | if (!rdev->ih.enabled || rdev->shutdown) |
|
- | 2694 | return IRQ_NONE; |
|
- | 2695 | ||
- | 2696 | wptr = r600_get_ih_wptr(rdev); |
|
- | 2697 | rptr = rdev->ih.rptr; |
|
- | 2698 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); |
|
- | 2699 | ||
- | 2700 | spin_lock_irqsave(&rdev->ih.lock, flags); |
|
- | 2701 | ||
- | 2702 | if (rptr == wptr) { |
|
- | 2703 | spin_unlock_irqrestore(&rdev->ih.lock, flags); |
|
- | 2704 | return IRQ_NONE; |
|
- | 2705 | } |
|
- | 2706 | ||
- | 2707 | restart_ih: |
|
- | 2708 | /* display interrupts */ |
|
- | 2709 | r600_irq_ack(rdev); |
|
- | 2710 | ||
- | 2711 | rdev->ih.wptr = wptr; |
|
- | 2712 | while (rptr != wptr) { |
|
- | 2713 | /* wptr/rptr are in bytes! */ |
|
- | 2714 | ring_index = rptr / 4; |
|
- | 2715 | src_id = le32_to_cpu(rdev->ih.ring[ring_index]) & 0xff; |
|
- | 2716 | src_data = le32_to_cpu(rdev->ih.ring[ring_index + 1]) & 0xfffffff; |
|
- | 2717 | ||
- | 2718 | switch (src_id) { |
|
- | 2719 | case 1: /* D1 vblank/vline */ |
|
- | 2720 | switch (src_data) { |
|
- | 2721 | case 0: /* D1 vblank */ |
|
- | 2722 | if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) { |
|
- | 2723 | if (rdev->irq.crtc_vblank_int[0]) { |
|
- | 2724 | // drm_handle_vblank(rdev->ddev, 0); |
|
- | 2725 | rdev->pm.vblank_sync = true; |
|
- | 2726 | // wake_up(&rdev->irq.vblank_queue); |
|
- | 2727 | } |
|
- | 2728 | // if (rdev->irq.pflip[0]) |
|
- | 2729 | // radeon_crtc_handle_flip(rdev, 0); |
|
- | 2730 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; |
|
- | 2731 | DRM_DEBUG("IH: D1 vblank\n"); |
|
- | 2732 | } |
|
- | 2733 | break; |
|
- | 2734 | case 1: /* D1 vline */ |
|
- | 2735 | if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) { |
|
- | 2736 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; |
|
- | 2737 | DRM_DEBUG("IH: D1 vline\n"); |
|
- | 2738 | } |
|
- | 2739 | break; |
|
- | 2740 | default: |
|
- | 2741 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
|
- | 2742 | break; |
|
- | 2743 | } |
|
- | 2744 | break; |
|
- | 2745 | case 5: /* D2 vblank/vline */ |
|
- | 2746 | switch (src_data) { |
|
- | 2747 | case 0: /* D2 vblank */ |
|
- | 2748 | if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) { |
|
- | 2749 | if (rdev->irq.crtc_vblank_int[1]) { |
|
- | 2750 | // drm_handle_vblank(rdev->ddev, 1); |
|
- | 2751 | rdev->pm.vblank_sync = true; |
|
- | 2752 | // wake_up(&rdev->irq.vblank_queue); |
|
- | 2753 | } |
|
- | 2754 | // if (rdev->irq.pflip[1]) |
|
- | 2755 | // radeon_crtc_handle_flip(rdev, 1); |
|
- | 2756 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; |
|
- | 2757 | DRM_DEBUG("IH: D2 vblank\n"); |
|
- | 2758 | } |
|
- | 2759 | break; |
|
- | 2760 | case 1: /* D1 vline */ |
|
- | 2761 | if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) { |
|
- | 2762 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; |
|
- | 2763 | DRM_DEBUG("IH: D2 vline\n"); |
|
- | 2764 | } |
|
- | 2765 | break; |
|
- | 2766 | default: |
|
- | 2767 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
|
- | 2768 | break; |
|
- | 2769 | } |
|
- | 2770 | break; |
|
- | 2771 | case 19: /* HPD/DAC hotplug */ |
|
- | 2772 | switch (src_data) { |
|
- | 2773 | case 0: |
|
- | 2774 | if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { |
|
- | 2775 | rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; |
|
- | 2776 | queue_hotplug = true; |
|
- | 2777 | DRM_DEBUG("IH: HPD1\n"); |
|
- | 2778 | } |
|
- | 2779 | break; |
|
- | 2780 | case 1: |
|
- | 2781 | if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { |
|
- | 2782 | rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; |
|
- | 2783 | queue_hotplug = true; |
|
- | 2784 | DRM_DEBUG("IH: HPD2\n"); |
|
- | 2785 | } |
|
- | 2786 | break; |
|
- | 2787 | case 4: |
|
- | 2788 | if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { |
|
- | 2789 | rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; |
|
- | 2790 | queue_hotplug = true; |
|
- | 2791 | DRM_DEBUG("IH: HPD3\n"); |
|
- | 2792 | } |
|
- | 2793 | break; |
|
- | 2794 | case 5: |
|
- | 2795 | if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { |
|
- | 2796 | rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; |
|
- | 2797 | queue_hotplug = true; |
|
- | 2798 | DRM_DEBUG("IH: HPD4\n"); |
|
- | 2799 | } |
|
- | 2800 | break; |
|
- | 2801 | case 10: |
|
- | 2802 | if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { |
|
- | 2803 | rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; |
|
- | 2804 | queue_hotplug = true; |
|
- | 2805 | DRM_DEBUG("IH: HPD5\n"); |
|
- | 2806 | } |
|
- | 2807 | break; |
|
- | 2808 | case 12: |
|
- | 2809 | if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { |
|
- | 2810 | rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; |
|
- | 2811 | queue_hotplug = true; |
|
- | 2812 | DRM_DEBUG("IH: HPD6\n"); |
|
- | 2813 | } |
|
- | 2814 | break; |
|
- | 2815 | default: |
|
- | 2816 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
|
- | 2817 | break; |
|
- | 2818 | } |
|
- | 2819 | break; |
|
- | 2820 | case 21: /* HDMI */ |
|
- | 2821 | DRM_DEBUG("IH: HDMI: 0x%x\n", src_data); |
|
- | 2822 | // r600_audio_schedule_polling(rdev); |
|
- | 2823 | break; |
|
- | 2824 | case 176: /* CP_INT in ring buffer */ |
|
- | 2825 | case 177: /* CP_INT in IB1 */ |
|
- | 2826 | case 178: /* CP_INT in IB2 */ |
|
- | 2827 | DRM_DEBUG("IH: CP int: 0x%08x\n", src_data); |
|
- | 2828 | // radeon_fence_process(rdev); |
|
- | 2829 | break; |
|
- | 2830 | case 181: /* CP EOP event */ |
|
- | 2831 | DRM_DEBUG("IH: CP EOP\n"); |
|
- | 2832 | // radeon_fence_process(rdev); |
|
- | 2833 | break; |
|
- | 2834 | case 233: /* GUI IDLE */ |
|
- | 2835 | DRM_DEBUG("IH: GUI idle\n"); |
|
- | 2836 | rdev->pm.gui_idle = true; |
|
- | 2837 | // wake_up(&rdev->irq.idle_queue); |
|
- | 2838 | break; |
|
- | 2839 | default: |
|
- | 2840 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
|
- | 2841 | break; |
|
- | 2842 | } |
|
- | 2843 | ||
- | 2844 | /* wptr/rptr are in bytes! */ |
|
- | 2845 | rptr += 16; |
|
- | 2846 | rptr &= rdev->ih.ptr_mask; |
|
- | 2847 | } |
|
- | 2848 | /* make sure wptr hasn't changed while processing */ |
|
- | 2849 | wptr = r600_get_ih_wptr(rdev); |
|
- | 2850 | if (wptr != rdev->ih.wptr) |
|
- | 2851 | goto restart_ih; |
|
Line 2082... | Line 2852... | ||
2082 | 2852 | // if (queue_hotplug) |
|
2083 | 2853 | // schedule_work(&rdev->hotplug_work); |
|
2084 | 2854 | rdev->ih.rptr = rptr; |
|
2085 | 2855 | WREG32(IH_RB_RPTR, rdev->ih.rptr); |