diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r420.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r420.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index c05a7270cf0c..f46502a253ec 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c | |||
@@ -30,6 +30,7 @@ | |||
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" |
34 | 35 | ||
35 | int r420_mc_init(struct radeon_device *rdev) | 36 | int r420_mc_init(struct radeon_device *rdev) |
@@ -165,6 +166,34 @@ static void r420_clock_resume(struct radeon_device *rdev) | |||
165 | WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); | 166 | WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); |
166 | } | 167 | } |
167 | 168 | ||
169 | static void r420_cp_errata_init(struct radeon_device *rdev) | ||
170 | { | ||
171 | /* RV410 and R420 can lock up if CP DMA to host memory happens | ||
172 | * while the 2D engine is busy. | ||
173 | * | ||
174 | * The proper workaround is to queue a RESYNC at the beginning | ||
175 | * of the CP init, apparently. | ||
176 | */ | ||
177 | radeon_scratch_get(rdev, &rdev->config.r300.resync_scratch); | ||
178 | radeon_ring_lock(rdev, 8); | ||
179 | radeon_ring_write(rdev, PACKET0(R300_CP_RESYNC_ADDR, 1)); | ||
180 | radeon_ring_write(rdev, rdev->config.r300.resync_scratch); | ||
181 | radeon_ring_write(rdev, 0xDEADBEEF); | ||
182 | radeon_ring_unlock_commit(rdev); | ||
183 | } | ||
184 | |||
185 | static void r420_cp_errata_fini(struct radeon_device *rdev) | ||
186 | { | ||
187 | /* Catch the RESYNC we dispatched all the way back, | ||
188 | * at the very beginning of the CP init. | ||
189 | */ | ||
190 | radeon_ring_lock(rdev, 8); | ||
191 | radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | ||
192 | radeon_ring_write(rdev, R300_RB3D_DC_FINISH); | ||
193 | radeon_ring_unlock_commit(rdev); | ||
194 | radeon_scratch_free(rdev, rdev->config.r300.resync_scratch); | ||
195 | } | ||
196 | |||
168 | static int r420_startup(struct radeon_device *rdev) | 197 | static int r420_startup(struct radeon_device *rdev) |
169 | { | 198 | { |
170 | int r; | 199 | int r; |
@@ -196,6 +225,7 @@ static int r420_startup(struct radeon_device *rdev) | |||
196 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); | 225 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); |
197 | return r; | 226 | return r; |
198 | } | 227 | } |
228 | r420_cp_errata_init(rdev); | ||
199 | r = r100_wb_init(rdev); | 229 | r = r100_wb_init(rdev); |
200 | if (r) { | 230 | if (r) { |
201 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | 231 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); |
@@ -238,6 +268,7 @@ int r420_resume(struct radeon_device *rdev) | |||
238 | 268 | ||
239 | int r420_suspend(struct radeon_device *rdev) | 269 | int r420_suspend(struct radeon_device *rdev) |
240 | { | 270 | { |
271 | r420_cp_errata_fini(rdev); | ||
241 | r100_cp_disable(rdev); | 272 | r100_cp_disable(rdev); |
242 | r100_wb_disable(rdev); | 273 | r100_wb_disable(rdev); |
243 | r100_irq_disable(rdev); | 274 | r100_irq_disable(rdev); |