diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2010-03-24 13:36:43 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-04-08 20:16:04 -0400 |
commit | fe251e2fffa1ebc17c8e6e895b0374ae4e732fa5 (patch) | |
tree | 995060a10005d4a284bebcd0412fabfd0805de89 /drivers/gpu/drm/radeon/evergreen.c | |
parent | 32fcdbf4084544c3d8fa413004d57e5dc6f2eefe (diff) |
drm/radeon/kms/evergreen: setup and enable the CP
The command processor (CP) fetches command buffers and
feeds the GPU. This patch requires the evergreen
family me and pfp ucode files.
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/evergreen.c')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 117 |
1 files changed, 96 insertions, 21 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 26b219bb1388..57fe569682df 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -32,6 +32,9 @@ | |||
32 | #include "avivod.h" | 32 | #include "avivod.h" |
33 | #include "evergreen_reg.h" | 33 | #include "evergreen_reg.h" |
34 | 34 | ||
35 | #define EVERGREEN_PFP_UCODE_SIZE 1120 | ||
36 | #define EVERGREEN_PM4_UCODE_SIZE 1376 | ||
37 | |||
35 | static void evergreen_gpu_init(struct radeon_device *rdev); | 38 | static void evergreen_gpu_init(struct radeon_device *rdev); |
36 | void evergreen_fini(struct radeon_device *rdev); | 39 | void evergreen_fini(struct radeon_device *rdev); |
37 | 40 | ||
@@ -418,23 +421,91 @@ static void evergreen_mc_program(struct radeon_device *rdev) | |||
418 | rv515_vga_render_disable(rdev); | 421 | rv515_vga_render_disable(rdev); |
419 | } | 422 | } |
420 | 423 | ||
421 | #if 0 | ||
422 | /* | 424 | /* |
423 | * CP. | 425 | * CP. |
424 | */ | 426 | */ |
425 | static void evergreen_cp_stop(struct radeon_device *rdev) | ||
426 | { | ||
427 | /* XXX */ | ||
428 | } | ||
429 | |||
430 | 427 | ||
431 | static int evergreen_cp_load_microcode(struct radeon_device *rdev) | 428 | static int evergreen_cp_load_microcode(struct radeon_device *rdev) |
432 | { | 429 | { |
433 | /* XXX */ | 430 | const __be32 *fw_data; |
431 | int i; | ||
432 | |||
433 | if (!rdev->me_fw || !rdev->pfp_fw) | ||
434 | return -EINVAL; | ||
434 | 435 | ||
436 | r700_cp_stop(rdev); | ||
437 | WREG32(CP_RB_CNTL, RB_NO_UPDATE | (15 << 8) | (3 << 0)); | ||
438 | |||
439 | fw_data = (const __be32 *)rdev->pfp_fw->data; | ||
440 | WREG32(CP_PFP_UCODE_ADDR, 0); | ||
441 | for (i = 0; i < EVERGREEN_PFP_UCODE_SIZE; i++) | ||
442 | WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); | ||
443 | WREG32(CP_PFP_UCODE_ADDR, 0); | ||
444 | |||
445 | fw_data = (const __be32 *)rdev->me_fw->data; | ||
446 | WREG32(CP_ME_RAM_WADDR, 0); | ||
447 | for (i = 0; i < EVERGREEN_PM4_UCODE_SIZE; i++) | ||
448 | WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); | ||
449 | |||
450 | WREG32(CP_PFP_UCODE_ADDR, 0); | ||
451 | WREG32(CP_ME_RAM_WADDR, 0); | ||
452 | WREG32(CP_ME_RAM_RADDR, 0); | ||
435 | return 0; | 453 | return 0; |
436 | } | 454 | } |
455 | |||
456 | int evergreen_cp_resume(struct radeon_device *rdev) | ||
457 | { | ||
458 | u32 tmp; | ||
459 | u32 rb_bufsz; | ||
460 | int r; | ||
461 | |||
462 | /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ | ||
463 | WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | | ||
464 | SOFT_RESET_PA | | ||
465 | SOFT_RESET_SH | | ||
466 | SOFT_RESET_VGT | | ||
467 | SOFT_RESET_SX)); | ||
468 | RREG32(GRBM_SOFT_RESET); | ||
469 | mdelay(15); | ||
470 | WREG32(GRBM_SOFT_RESET, 0); | ||
471 | RREG32(GRBM_SOFT_RESET); | ||
472 | |||
473 | /* Set ring buffer size */ | ||
474 | rb_bufsz = drm_order(rdev->cp.ring_size / 8); | ||
475 | tmp = RB_NO_UPDATE | (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; | ||
476 | #ifdef __BIG_ENDIAN | ||
477 | tmp |= BUF_SWAP_32BIT; | ||
437 | #endif | 478 | #endif |
479 | WREG32(CP_RB_CNTL, tmp); | ||
480 | WREG32(CP_SEM_WAIT_TIMER, 0x4); | ||
481 | |||
482 | /* Set the write pointer delay */ | ||
483 | WREG32(CP_RB_WPTR_DELAY, 0); | ||
484 | |||
485 | /* Initialize the ring buffer's read and write pointers */ | ||
486 | WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA); | ||
487 | WREG32(CP_RB_RPTR_WR, 0); | ||
488 | WREG32(CP_RB_WPTR, 0); | ||
489 | WREG32(CP_RB_RPTR_ADDR, rdev->cp.gpu_addr & 0xFFFFFFFF); | ||
490 | WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->cp.gpu_addr)); | ||
491 | mdelay(1); | ||
492 | WREG32(CP_RB_CNTL, tmp); | ||
493 | |||
494 | WREG32(CP_RB_BASE, rdev->cp.gpu_addr >> 8); | ||
495 | WREG32(CP_DEBUG, (1 << 27) | (1 << 28)); | ||
496 | |||
497 | rdev->cp.rptr = RREG32(CP_RB_RPTR); | ||
498 | rdev->cp.wptr = RREG32(CP_RB_WPTR); | ||
499 | |||
500 | r600_cp_start(rdev); | ||
501 | rdev->cp.ready = true; | ||
502 | r = radeon_ring_test(rdev); | ||
503 | if (r) { | ||
504 | rdev->cp.ready = false; | ||
505 | return r; | ||
506 | } | ||
507 | return 0; | ||
508 | } | ||
438 | 509 | ||
439 | /* | 510 | /* |
440 | * Core functions | 511 | * Core functions |
@@ -1138,15 +1209,15 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
1138 | { | 1209 | { |
1139 | int r; | 1210 | int r; |
1140 | 1211 | ||
1141 | #if 0 | 1212 | /* XXX until interrupts are supported */ |
1142 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { | 1213 | if (!rdev->me_fw || !rdev->pfp_fw /*|| !rdev->rlc_fw*/) { |
1143 | r = r600_init_microcode(rdev); | 1214 | r = r600_init_microcode(rdev); |
1144 | if (r) { | 1215 | if (r) { |
1145 | DRM_ERROR("Failed to load firmware!\n"); | 1216 | DRM_ERROR("Failed to load firmware!\n"); |
1146 | return r; | 1217 | return r; |
1147 | } | 1218 | } |
1148 | } | 1219 | } |
1149 | #endif | 1220 | |
1150 | evergreen_mc_program(rdev); | 1221 | evergreen_mc_program(rdev); |
1151 | if (rdev->flags & RADEON_IS_AGP) { | 1222 | if (rdev->flags & RADEON_IS_AGP) { |
1152 | evergreen_agp_enable(rdev); | 1223 | evergreen_agp_enable(rdev); |
@@ -1184,6 +1255,7 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
1184 | return r; | 1255 | return r; |
1185 | } | 1256 | } |
1186 | r600_irq_set(rdev); | 1257 | r600_irq_set(rdev); |
1258 | #endif | ||
1187 | 1259 | ||
1188 | r = radeon_ring_init(rdev, rdev->cp.ring_size); | 1260 | r = radeon_ring_init(rdev, rdev->cp.ring_size); |
1189 | if (r) | 1261 | if (r) |
@@ -1191,12 +1263,12 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
1191 | r = evergreen_cp_load_microcode(rdev); | 1263 | r = evergreen_cp_load_microcode(rdev); |
1192 | if (r) | 1264 | if (r) |
1193 | return r; | 1265 | return r; |
1194 | r = r600_cp_resume(rdev); | 1266 | r = evergreen_cp_resume(rdev); |
1195 | if (r) | 1267 | if (r) |
1196 | return r; | 1268 | return r; |
1197 | /* write back buffer are not vital so don't worry about failure */ | 1269 | /* write back buffer are not vital so don't worry about failure */ |
1198 | r600_wb_enable(rdev); | 1270 | r600_wb_enable(rdev); |
1199 | #endif | 1271 | |
1200 | return 0; | 1272 | return 0; |
1201 | } | 1273 | } |
1202 | 1274 | ||
@@ -1221,13 +1293,13 @@ int evergreen_resume(struct radeon_device *rdev) | |||
1221 | DRM_ERROR("r600 startup failed on resume\n"); | 1293 | DRM_ERROR("r600 startup failed on resume\n"); |
1222 | return r; | 1294 | return r; |
1223 | } | 1295 | } |
1224 | #if 0 | 1296 | |
1225 | r = r600_ib_test(rdev); | 1297 | r = r600_ib_test(rdev); |
1226 | if (r) { | 1298 | if (r) { |
1227 | DRM_ERROR("radeon: failled testing IB (%d).\n", r); | 1299 | DRM_ERROR("radeon: failled testing IB (%d).\n", r); |
1228 | return r; | 1300 | return r; |
1229 | } | 1301 | } |
1230 | #endif | 1302 | |
1231 | return r; | 1303 | return r; |
1232 | 1304 | ||
1233 | } | 1305 | } |
@@ -1236,12 +1308,11 @@ int evergreen_suspend(struct radeon_device *rdev) | |||
1236 | { | 1308 | { |
1237 | #if 0 | 1309 | #if 0 |
1238 | int r; | 1310 | int r; |
1239 | 1311 | #endif | |
1240 | /* FIXME: we should wait for ring to be empty */ | 1312 | /* FIXME: we should wait for ring to be empty */ |
1241 | r700_cp_stop(rdev); | 1313 | r700_cp_stop(rdev); |
1242 | rdev->cp.ready = false; | 1314 | rdev->cp.ready = false; |
1243 | r600_wb_disable(rdev); | 1315 | r600_wb_disable(rdev); |
1244 | #endif | ||
1245 | 1316 | ||
1246 | evergreen_pcie_gart_disable(rdev); | 1317 | evergreen_pcie_gart_disable(rdev); |
1247 | #if 0 | 1318 | #if 0 |
@@ -1348,10 +1419,10 @@ int evergreen_init(struct radeon_device *rdev) | |||
1348 | r = radeon_irq_kms_init(rdev); | 1419 | r = radeon_irq_kms_init(rdev); |
1349 | if (r) | 1420 | if (r) |
1350 | return r; | 1421 | return r; |
1351 | 1422 | #endif | |
1352 | rdev->cp.ring_obj = NULL; | 1423 | rdev->cp.ring_obj = NULL; |
1353 | r600_ring_init(rdev, 1024 * 1024); | 1424 | r600_ring_init(rdev, 1024 * 1024); |
1354 | 1425 | #if 0 | |
1355 | rdev->ih.ring_obj = NULL; | 1426 | rdev->ih.ring_obj = NULL; |
1356 | r600_ih_ring_init(rdev, 64 * 1024); | 1427 | r600_ih_ring_init(rdev, 64 * 1024); |
1357 | #endif | 1428 | #endif |
@@ -1362,9 +1433,13 @@ int evergreen_init(struct radeon_device *rdev) | |||
1362 | rdev->accel_working = false; | 1433 | rdev->accel_working = false; |
1363 | r = evergreen_startup(rdev); | 1434 | r = evergreen_startup(rdev); |
1364 | if (r) { | 1435 | if (r) { |
1365 | evergreen_suspend(rdev); | 1436 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
1366 | /*r600_wb_fini(rdev);*/ | 1437 | r700_cp_fini(rdev); |
1367 | /*radeon_ring_fini(rdev);*/ | 1438 | r600_wb_fini(rdev); |
1439 | #if 0 | ||
1440 | r600_irq_fini(rdev); | ||
1441 | radeon_irq_kms_fini(rdev); | ||
1442 | #endif | ||
1368 | evergreen_pcie_gart_fini(rdev); | 1443 | evergreen_pcie_gart_fini(rdev); |
1369 | rdev->accel_working = false; | 1444 | rdev->accel_working = false; |
1370 | } | 1445 | } |