diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r420.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/r420.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index c05a7270cf0c..053404e71a9d 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c | |||
| @@ -30,7 +30,15 @@ | |||
| 30 | #include "radeon_reg.h" | 30 | #include "radeon_reg.h" |
| 31 | #include "radeon.h" | 31 | #include "radeon.h" |
| 32 | #include "atom.h" | 32 | #include "atom.h" |
| 33 | #include "r100d.h" | ||
| 33 | #include "r420d.h" | 34 | #include "r420d.h" |
| 35 | #include "r420_reg_safe.h" | ||
| 36 | |||
| 37 | static void r420_set_reg_safe(struct radeon_device *rdev) | ||
| 38 | { | ||
| 39 | rdev->config.r300.reg_safe_bm = r420_reg_safe_bm; | ||
| 40 | rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r420_reg_safe_bm); | ||
| 41 | } | ||
| 34 | 42 | ||
| 35 | int r420_mc_init(struct radeon_device *rdev) | 43 | int r420_mc_init(struct radeon_device *rdev) |
| 36 | { | 44 | { |
| @@ -165,6 +173,34 @@ static void r420_clock_resume(struct radeon_device *rdev) | |||
| 165 | WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); | 173 | WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); |
| 166 | } | 174 | } |
| 167 | 175 | ||
| 176 | static void r420_cp_errata_init(struct radeon_device *rdev) | ||
| 177 | { | ||
| 178 | /* RV410 and R420 can lock up if CP DMA to host memory happens | ||
| 179 | * while the 2D engine is busy. | ||
| 180 | * | ||
| 181 | * The proper workaround is to queue a RESYNC at the beginning | ||
| 182 | * of the CP init, apparently. | ||
| 183 | */ | ||
| 184 | radeon_scratch_get(rdev, &rdev->config.r300.resync_scratch); | ||
| 185 | radeon_ring_lock(rdev, 8); | ||
| 186 | radeon_ring_write(rdev, PACKET0(R300_CP_RESYNC_ADDR, 1)); | ||
| 187 | radeon_ring_write(rdev, rdev->config.r300.resync_scratch); | ||
| 188 | radeon_ring_write(rdev, 0xDEADBEEF); | ||
| 189 | radeon_ring_unlock_commit(rdev); | ||
| 190 | } | ||
| 191 | |||
| 192 | static void r420_cp_errata_fini(struct radeon_device *rdev) | ||
| 193 | { | ||
| 194 | /* Catch the RESYNC we dispatched all the way back, | ||
| 195 | * at the very beginning of the CP init. | ||
| 196 | */ | ||
| 197 | radeon_ring_lock(rdev, 8); | ||
| 198 | radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | ||
| 199 | radeon_ring_write(rdev, R300_RB3D_DC_FINISH); | ||
| 200 | radeon_ring_unlock_commit(rdev); | ||
| 201 | radeon_scratch_free(rdev, rdev->config.r300.resync_scratch); | ||
| 202 | } | ||
| 203 | |||
| 168 | static int r420_startup(struct radeon_device *rdev) | 204 | static int r420_startup(struct radeon_device *rdev) |
| 169 | { | 205 | { |
| 170 | int r; | 206 | int r; |
| @@ -190,12 +226,14 @@ static int r420_startup(struct radeon_device *rdev) | |||
| 190 | r420_pipes_init(rdev); | 226 | r420_pipes_init(rdev); |
| 191 | /* Enable IRQ */ | 227 | /* Enable IRQ */ |
| 192 | r100_irq_set(rdev); | 228 | r100_irq_set(rdev); |
| 229 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); | ||
| 193 | /* 1M ring buffer */ | 230 | /* 1M ring buffer */ |
| 194 | r = r100_cp_init(rdev, 1024 * 1024); | 231 | r = r100_cp_init(rdev, 1024 * 1024); |
| 195 | if (r) { | 232 | if (r) { |
| 196 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); | 233 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); |
| 197 | return r; | 234 | return r; |
| 198 | } | 235 | } |
| 236 | r420_cp_errata_init(rdev); | ||
| 199 | r = r100_wb_init(rdev); | 237 | r = r100_wb_init(rdev); |
| 200 | if (r) { | 238 | if (r) { |
| 201 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | 239 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); |
| @@ -238,6 +276,7 @@ int r420_resume(struct radeon_device *rdev) | |||
| 238 | 276 | ||
| 239 | int r420_suspend(struct radeon_device *rdev) | 277 | int r420_suspend(struct radeon_device *rdev) |
| 240 | { | 278 | { |
| 279 | r420_cp_errata_fini(rdev); | ||
| 241 | r100_cp_disable(rdev); | 280 | r100_cp_disable(rdev); |
| 242 | r100_wb_disable(rdev); | 281 | r100_wb_disable(rdev); |
| 243 | r100_irq_disable(rdev); | 282 | r100_irq_disable(rdev); |
| @@ -346,7 +385,7 @@ int r420_init(struct radeon_device *rdev) | |||
| 346 | if (r) | 385 | if (r) |
| 347 | return r; | 386 | return r; |
| 348 | } | 387 | } |
| 349 | r300_set_reg_safe(rdev); | 388 | r420_set_reg_safe(rdev); |
| 350 | rdev->accel_working = true; | 389 | rdev->accel_working = true; |
| 351 | r = r420_startup(rdev); | 390 | r = r420_startup(rdev); |
| 352 | if (r) { | 391 | if (r) { |
