diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r420.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r420.c | 123 |
1 files changed, 75 insertions, 48 deletions
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 1cefdbcc0850..c2bda4ad62e7 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c | |||
@@ -26,34 +26,20 @@ | |||
26 | * Jerome Glisse | 26 | * Jerome Glisse |
27 | */ | 27 | */ |
28 | #include <linux/seq_file.h> | 28 | #include <linux/seq_file.h> |
29 | #include <linux/slab.h> | ||
29 | #include "drmP.h" | 30 | #include "drmP.h" |
30 | #include "radeon_reg.h" | 31 | #include "radeon_reg.h" |
31 | #include "radeon.h" | 32 | #include "radeon.h" |
33 | #include "radeon_asic.h" | ||
32 | #include "atom.h" | 34 | #include "atom.h" |
35 | #include "r100d.h" | ||
33 | #include "r420d.h" | 36 | #include "r420d.h" |
37 | #include "r420_reg_safe.h" | ||
34 | 38 | ||
35 | int r420_mc_init(struct radeon_device *rdev) | 39 | static void r420_set_reg_safe(struct radeon_device *rdev) |
36 | { | 40 | { |
37 | int r; | 41 | rdev->config.r300.reg_safe_bm = r420_reg_safe_bm; |
38 | 42 | rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r420_reg_safe_bm); | |
39 | /* Setup GPU memory space */ | ||
40 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
41 | rdev->mc.gtt_location = 0xFFFFFFFFUL; | ||
42 | if (rdev->flags & RADEON_IS_AGP) { | ||
43 | r = radeon_agp_init(rdev); | ||
44 | if (r) { | ||
45 | printk(KERN_WARNING "[drm] Disabling AGP\n"); | ||
46 | rdev->flags &= ~RADEON_IS_AGP; | ||
47 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | ||
48 | } else { | ||
49 | rdev->mc.gtt_location = rdev->mc.agp_base; | ||
50 | } | ||
51 | } | ||
52 | r = radeon_mc_setup(rdev); | ||
53 | if (r) { | ||
54 | return r; | ||
55 | } | ||
56 | return 0; | ||
57 | } | 43 | } |
58 | 44 | ||
59 | void r420_pipes_init(struct radeon_device *rdev) | 45 | void r420_pipes_init(struct radeon_device *rdev) |
@@ -63,7 +49,8 @@ void r420_pipes_init(struct radeon_device *rdev) | |||
63 | unsigned num_pipes; | 49 | unsigned num_pipes; |
64 | 50 | ||
65 | /* GA_ENHANCE workaround TCL deadlock issue */ | 51 | /* GA_ENHANCE workaround TCL deadlock issue */ |
66 | WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); | 52 | WREG32(R300_GA_ENHANCE, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL | |
53 | (1 << 2) | (1 << 3)); | ||
67 | /* add idle wait as per freedesktop.org bug 24041 */ | 54 | /* add idle wait as per freedesktop.org bug 24041 */ |
68 | if (r100_gui_wait_for_idle(rdev)) { | 55 | if (r100_gui_wait_for_idle(rdev)) { |
69 | printk(KERN_WARNING "Failed to wait GUI idle while " | 56 | printk(KERN_WARNING "Failed to wait GUI idle while " |
@@ -72,6 +59,12 @@ void r420_pipes_init(struct radeon_device *rdev) | |||
72 | /* get max number of pipes */ | 59 | /* get max number of pipes */ |
73 | gb_pipe_select = RREG32(0x402C); | 60 | gb_pipe_select = RREG32(0x402C); |
74 | num_pipes = ((gb_pipe_select >> 12) & 3) + 1; | 61 | num_pipes = ((gb_pipe_select >> 12) & 3) + 1; |
62 | |||
63 | /* SE chips have 1 pipe */ | ||
64 | if ((rdev->pdev->device == 0x5e4c) || | ||
65 | (rdev->pdev->device == 0x5e4f)) | ||
66 | num_pipes = 1; | ||
67 | |||
75 | rdev->num_gb_pipes = num_pipes; | 68 | rdev->num_gb_pipes = num_pipes; |
76 | tmp = 0; | 69 | tmp = 0; |
77 | switch (num_pipes) { | 70 | switch (num_pipes) { |
@@ -91,17 +84,17 @@ void r420_pipes_init(struct radeon_device *rdev) | |||
91 | tmp = (7 << 1); | 84 | tmp = (7 << 1); |
92 | break; | 85 | break; |
93 | } | 86 | } |
94 | WREG32(0x42C8, (1 << num_pipes) - 1); | 87 | WREG32(R500_SU_REG_DEST, (1 << num_pipes) - 1); |
95 | /* Sub pixel 1/12 so we can have 4K rendering according to doc */ | 88 | /* Sub pixel 1/12 so we can have 4K rendering according to doc */ |
96 | tmp |= (1 << 4) | (1 << 0); | 89 | tmp |= R300_TILE_SIZE_16 | R300_ENABLE_TILING; |
97 | WREG32(0x4018, tmp); | 90 | WREG32(R300_GB_TILE_CONFIG, tmp); |
98 | if (r100_gui_wait_for_idle(rdev)) { | 91 | if (r100_gui_wait_for_idle(rdev)) { |
99 | printk(KERN_WARNING "Failed to wait GUI idle while " | 92 | printk(KERN_WARNING "Failed to wait GUI idle while " |
100 | "programming pipes. Bad things might happen.\n"); | 93 | "programming pipes. Bad things might happen.\n"); |
101 | } | 94 | } |
102 | 95 | ||
103 | tmp = RREG32(0x170C); | 96 | tmp = RREG32(R300_DST_PIPE_CONFIG); |
104 | WREG32(0x170C, tmp | (1 << 31)); | 97 | WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG); |
105 | 98 | ||
106 | WREG32(R300_RB2D_DSTCACHE_MODE, | 99 | WREG32(R300_RB2D_DSTCACHE_MODE, |
107 | RREG32(R300_RB2D_DSTCACHE_MODE) | | 100 | RREG32(R300_RB2D_DSTCACHE_MODE) | |
@@ -165,10 +158,41 @@ static void r420_clock_resume(struct radeon_device *rdev) | |||
165 | WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); | 158 | WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); |
166 | } | 159 | } |
167 | 160 | ||
161 | static void r420_cp_errata_init(struct radeon_device *rdev) | ||
162 | { | ||
163 | /* RV410 and R420 can lock up if CP DMA to host memory happens | ||
164 | * while the 2D engine is busy. | ||
165 | * | ||
166 | * The proper workaround is to queue a RESYNC at the beginning | ||
167 | * of the CP init, apparently. | ||
168 | */ | ||
169 | radeon_scratch_get(rdev, &rdev->config.r300.resync_scratch); | ||
170 | radeon_ring_lock(rdev, 8); | ||
171 | radeon_ring_write(rdev, PACKET0(R300_CP_RESYNC_ADDR, 1)); | ||
172 | radeon_ring_write(rdev, rdev->config.r300.resync_scratch); | ||
173 | radeon_ring_write(rdev, 0xDEADBEEF); | ||
174 | radeon_ring_unlock_commit(rdev); | ||
175 | } | ||
176 | |||
177 | static void r420_cp_errata_fini(struct radeon_device *rdev) | ||
178 | { | ||
179 | /* Catch the RESYNC we dispatched all the way back, | ||
180 | * at the very beginning of the CP init. | ||
181 | */ | ||
182 | radeon_ring_lock(rdev, 8); | ||
183 | radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | ||
184 | radeon_ring_write(rdev, R300_RB3D_DC_FINISH); | ||
185 | radeon_ring_unlock_commit(rdev); | ||
186 | radeon_scratch_free(rdev, rdev->config.r300.resync_scratch); | ||
187 | } | ||
188 | |||
168 | static int r420_startup(struct radeon_device *rdev) | 189 | static int r420_startup(struct radeon_device *rdev) |
169 | { | 190 | { |
170 | int r; | 191 | int r; |
171 | 192 | ||
193 | /* set common regs */ | ||
194 | r100_set_common_regs(rdev); | ||
195 | /* program mc */ | ||
172 | r300_mc_program(rdev); | 196 | r300_mc_program(rdev); |
173 | /* Resume clock */ | 197 | /* Resume clock */ |
174 | r420_clock_resume(rdev); | 198 | r420_clock_resume(rdev); |
@@ -186,14 +210,15 @@ static int r420_startup(struct radeon_device *rdev) | |||
186 | } | 210 | } |
187 | r420_pipes_init(rdev); | 211 | r420_pipes_init(rdev); |
188 | /* Enable IRQ */ | 212 | /* Enable IRQ */ |
189 | rdev->irq.sw_int = true; | ||
190 | r100_irq_set(rdev); | 213 | r100_irq_set(rdev); |
214 | rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); | ||
191 | /* 1M ring buffer */ | 215 | /* 1M ring buffer */ |
192 | r = r100_cp_init(rdev, 1024 * 1024); | 216 | r = r100_cp_init(rdev, 1024 * 1024); |
193 | if (r) { | 217 | if (r) { |
194 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); | 218 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); |
195 | return r; | 219 | return r; |
196 | } | 220 | } |
221 | r420_cp_errata_init(rdev); | ||
197 | r = r100_wb_init(rdev); | 222 | r = r100_wb_init(rdev); |
198 | if (r) { | 223 | if (r) { |
199 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | 224 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); |
@@ -229,12 +254,14 @@ int r420_resume(struct radeon_device *rdev) | |||
229 | } | 254 | } |
230 | /* Resume clock after posting */ | 255 | /* Resume clock after posting */ |
231 | r420_clock_resume(rdev); | 256 | r420_clock_resume(rdev); |
232 | 257 | /* Initialize surface registers */ | |
258 | radeon_surface_init(rdev); | ||
233 | return r420_startup(rdev); | 259 | return r420_startup(rdev); |
234 | } | 260 | } |
235 | 261 | ||
236 | int r420_suspend(struct radeon_device *rdev) | 262 | int r420_suspend(struct radeon_device *rdev) |
237 | { | 263 | { |
264 | r420_cp_errata_fini(rdev); | ||
238 | r100_cp_disable(rdev); | 265 | r100_cp_disable(rdev); |
239 | r100_wb_disable(rdev); | 266 | r100_wb_disable(rdev); |
240 | r100_irq_disable(rdev); | 267 | r100_irq_disable(rdev); |
@@ -247,6 +274,7 @@ int r420_suspend(struct radeon_device *rdev) | |||
247 | 274 | ||
248 | void r420_fini(struct radeon_device *rdev) | 275 | void r420_fini(struct radeon_device *rdev) |
249 | { | 276 | { |
277 | radeon_pm_fini(rdev); | ||
250 | r100_cp_fini(rdev); | 278 | r100_cp_fini(rdev); |
251 | r100_wb_fini(rdev); | 279 | r100_wb_fini(rdev); |
252 | r100_ib_fini(rdev); | 280 | r100_ib_fini(rdev); |
@@ -258,7 +286,7 @@ void r420_fini(struct radeon_device *rdev) | |||
258 | radeon_agp_fini(rdev); | 286 | radeon_agp_fini(rdev); |
259 | radeon_irq_kms_fini(rdev); | 287 | radeon_irq_kms_fini(rdev); |
260 | radeon_fence_driver_fini(rdev); | 288 | radeon_fence_driver_fini(rdev); |
261 | radeon_object_fini(rdev); | 289 | radeon_bo_fini(rdev); |
262 | if (rdev->is_atom_bios) { | 290 | if (rdev->is_atom_bios) { |
263 | radeon_atombios_fini(rdev); | 291 | radeon_atombios_fini(rdev); |
264 | } else { | 292 | } else { |
@@ -301,25 +329,22 @@ int r420_init(struct radeon_device *rdev) | |||
301 | RREG32(R_0007C0_CP_STAT)); | 329 | RREG32(R_0007C0_CP_STAT)); |
302 | } | 330 | } |
303 | /* check if cards are posted or not */ | 331 | /* check if cards are posted or not */ |
304 | if (!radeon_card_posted(rdev) && rdev->bios) { | 332 | if (radeon_boot_test_post_card(rdev) == false) |
305 | DRM_INFO("GPU not posted. posting now...\n"); | 333 | return -EINVAL; |
306 | if (rdev->is_atom_bios) { | 334 | |
307 | atom_asic_init(rdev->mode_info.atom_context); | ||
308 | } else { | ||
309 | radeon_combios_asic_init(rdev->ddev); | ||
310 | } | ||
311 | } | ||
312 | /* Initialize clocks */ | 335 | /* Initialize clocks */ |
313 | radeon_get_clock_info(rdev->ddev); | 336 | radeon_get_clock_info(rdev->ddev); |
314 | /* Initialize power management */ | 337 | /* Initialize power management */ |
315 | radeon_pm_init(rdev); | 338 | radeon_pm_init(rdev); |
316 | /* Get vram informations */ | 339 | /* initialize AGP */ |
317 | r300_vram_info(rdev); | 340 | if (rdev->flags & RADEON_IS_AGP) { |
318 | /* Initialize memory controller (also test AGP) */ | 341 | r = radeon_agp_init(rdev); |
319 | r = r420_mc_init(rdev); | 342 | if (r) { |
320 | if (r) { | 343 | radeon_agp_disable(rdev); |
321 | return r; | 344 | } |
322 | } | 345 | } |
346 | /* initialize memory controller */ | ||
347 | r300_mc_init(rdev); | ||
323 | r420_debugfs(rdev); | 348 | r420_debugfs(rdev); |
324 | /* Fence driver */ | 349 | /* Fence driver */ |
325 | r = radeon_fence_driver_init(rdev); | 350 | r = radeon_fence_driver_init(rdev); |
@@ -331,10 +356,13 @@ int r420_init(struct radeon_device *rdev) | |||
331 | return r; | 356 | return r; |
332 | } | 357 | } |
333 | /* Memory manager */ | 358 | /* Memory manager */ |
334 | r = radeon_object_init(rdev); | 359 | r = radeon_bo_init(rdev); |
335 | if (r) { | 360 | if (r) { |
336 | return r; | 361 | return r; |
337 | } | 362 | } |
363 | if (rdev->family == CHIP_R420) | ||
364 | r100_enable_bm(rdev); | ||
365 | |||
338 | if (rdev->flags & RADEON_IS_PCIE) { | 366 | if (rdev->flags & RADEON_IS_PCIE) { |
339 | r = rv370_pcie_gart_init(rdev); | 367 | r = rv370_pcie_gart_init(rdev); |
340 | if (r) | 368 | if (r) |
@@ -345,22 +373,21 @@ int r420_init(struct radeon_device *rdev) | |||
345 | if (r) | 373 | if (r) |
346 | return r; | 374 | return r; |
347 | } | 375 | } |
348 | r300_set_reg_safe(rdev); | 376 | r420_set_reg_safe(rdev); |
349 | rdev->accel_working = true; | 377 | rdev->accel_working = true; |
350 | r = r420_startup(rdev); | 378 | r = r420_startup(rdev); |
351 | if (r) { | 379 | if (r) { |
352 | /* Somethings want wront with the accel init stop accel */ | 380 | /* Somethings want wront with the accel init stop accel */ |
353 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 381 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
354 | r420_suspend(rdev); | ||
355 | r100_cp_fini(rdev); | 382 | r100_cp_fini(rdev); |
356 | r100_wb_fini(rdev); | 383 | r100_wb_fini(rdev); |
357 | r100_ib_fini(rdev); | 384 | r100_ib_fini(rdev); |
385 | radeon_irq_kms_fini(rdev); | ||
358 | if (rdev->flags & RADEON_IS_PCIE) | 386 | if (rdev->flags & RADEON_IS_PCIE) |
359 | rv370_pcie_gart_fini(rdev); | 387 | rv370_pcie_gart_fini(rdev); |
360 | if (rdev->flags & RADEON_IS_PCI) | 388 | if (rdev->flags & RADEON_IS_PCI) |
361 | r100_pci_gart_fini(rdev); | 389 | r100_pci_gart_fini(rdev); |
362 | radeon_agp_fini(rdev); | 390 | radeon_agp_fini(rdev); |
363 | radeon_irq_kms_fini(rdev); | ||
364 | rdev->accel_working = false; | 391 | rdev->accel_working = false; |
365 | } | 392 | } |
366 | return 0; | 393 | return 0; |