diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2011-03-02 20:07:34 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-03-02 20:52:04 -0500 |
commit | 755d819e0cf2e09e0958c77b72aa3ce2142411c2 (patch) | |
tree | f54b56dad294141467947f6d1e1259db6c5fc027 /drivers/gpu/drm | |
parent | b9952a8ae5814b0ef2a6596c7443efd85b92e069 (diff) |
drm/radeon/kms/cayman: add asic init/startup/fini/suspend/resume functions
Cayman is different enough from evergreen to warrant it's own functions.
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/ni.c | 241 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 2 |
3 files changed, 246 insertions, 7 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 0a3d6fc13c2d..d4045223d0ff 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -1108,7 +1108,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s | |||
1108 | WREG32(VGA_RENDER_CONTROL, save->vga_render_control); | 1108 | WREG32(VGA_RENDER_CONTROL, save->vga_render_control); |
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | static void evergreen_mc_program(struct radeon_device *rdev) | 1111 | void evergreen_mc_program(struct radeon_device *rdev) |
1112 | { | 1112 | { |
1113 | struct evergreen_mc_save save; | 1113 | struct evergreen_mc_save save; |
1114 | u32 tmp; | 1114 | u32 tmp; |
@@ -2565,7 +2565,7 @@ void evergreen_irq_disable(struct radeon_device *rdev) | |||
2565 | evergreen_disable_interrupt_state(rdev); | 2565 | evergreen_disable_interrupt_state(rdev); |
2566 | } | 2566 | } |
2567 | 2567 | ||
2568 | static void evergreen_irq_suspend(struct radeon_device *rdev) | 2568 | void evergreen_irq_suspend(struct radeon_device *rdev) |
2569 | { | 2569 | { |
2570 | evergreen_irq_disable(rdev); | 2570 | evergreen_irq_disable(rdev); |
2571 | r600_rlc_stop(rdev); | 2571 | r600_rlc_stop(rdev); |
@@ -2888,7 +2888,7 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
2888 | return r; | 2888 | return r; |
2889 | } | 2889 | } |
2890 | } | 2890 | } |
2891 | r = btc_mc_load_microcode(rdev); | 2891 | r = ni_mc_load_microcode(rdev); |
2892 | if (r) { | 2892 | if (r) { |
2893 | DRM_ERROR("Failed to load MC firmware!\n"); | 2893 | DRM_ERROR("Failed to load MC firmware!\n"); |
2894 | return r; | 2894 | return r; |
@@ -2970,7 +2970,7 @@ int evergreen_resume(struct radeon_device *rdev) | |||
2970 | 2970 | ||
2971 | r = evergreen_startup(rdev); | 2971 | r = evergreen_startup(rdev); |
2972 | if (r) { | 2972 | if (r) { |
2973 | DRM_ERROR("r600 startup failed on resume\n"); | 2973 | DRM_ERROR("evergreen startup failed on resume\n"); |
2974 | return r; | 2974 | return r; |
2975 | } | 2975 | } |
2976 | 2976 | ||
@@ -3050,7 +3050,7 @@ int evergreen_init(struct radeon_device *rdev) | |||
3050 | } | 3050 | } |
3051 | /* Must be an ATOMBIOS */ | 3051 | /* Must be an ATOMBIOS */ |
3052 | if (!rdev->is_atom_bios) { | 3052 | if (!rdev->is_atom_bios) { |
3053 | dev_err(rdev->dev, "Expecting atombios for R600 GPU\n"); | 3053 | dev_err(rdev->dev, "Expecting atombios for evergreen GPU\n"); |
3054 | return -EINVAL; | 3054 | return -EINVAL; |
3055 | } | 3055 | } |
3056 | r = radeon_atombios_init(rdev); | 3056 | r = radeon_atombios_init(rdev); |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 3a3fdf5b5dd2..227173bf0127 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
@@ -36,6 +36,9 @@ | |||
36 | extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); | 36 | extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); |
37 | extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); | 37 | extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); |
38 | extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev); | 38 | extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev); |
39 | extern void evergreen_mc_program(struct radeon_device *rdev); | ||
40 | extern void evergreen_irq_suspend(struct radeon_device *rdev); | ||
41 | extern int evergreen_mc_init(struct radeon_device *rdev); | ||
39 | 42 | ||
40 | #define EVERGREEN_PFP_UCODE_SIZE 1120 | 43 | #define EVERGREEN_PFP_UCODE_SIZE 1120 |
41 | #define EVERGREEN_PM4_UCODE_SIZE 1376 | 44 | #define EVERGREEN_PM4_UCODE_SIZE 1376 |
@@ -193,7 +196,7 @@ static const u32 cayman_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { | |||
193 | {0x0000009f, 0x00976b00} | 196 | {0x0000009f, 0x00976b00} |
194 | }; | 197 | }; |
195 | 198 | ||
196 | int btc_mc_load_microcode(struct radeon_device *rdev) | 199 | int ni_mc_load_microcode(struct radeon_device *rdev) |
197 | { | 200 | { |
198 | const __be32 *fw_data; | 201 | const __be32 *fw_data; |
199 | u32 mem_type, running, blackout = 0; | 202 | u32 mem_type, running, blackout = 0; |
@@ -1129,6 +1132,12 @@ static int cayman_cp_start(struct radeon_device *rdev) | |||
1129 | return 0; | 1132 | return 0; |
1130 | } | 1133 | } |
1131 | 1134 | ||
1135 | static void cayman_cp_fini(struct radeon_device *rdev) | ||
1136 | { | ||
1137 | cayman_cp_enable(rdev, false); | ||
1138 | radeon_ring_fini(rdev); | ||
1139 | } | ||
1140 | |||
1132 | int cayman_cp_resume(struct radeon_device *rdev) | 1141 | int cayman_cp_resume(struct radeon_device *rdev) |
1133 | { | 1142 | { |
1134 | u32 tmp; | 1143 | u32 tmp; |
@@ -1346,3 +1355,233 @@ int cayman_asic_reset(struct radeon_device *rdev) | |||
1346 | return cayman_gpu_soft_reset(rdev); | 1355 | return cayman_gpu_soft_reset(rdev); |
1347 | } | 1356 | } |
1348 | 1357 | ||
1358 | static int cayman_startup(struct radeon_device *rdev) | ||
1359 | { | ||
1360 | int r; | ||
1361 | |||
1362 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { | ||
1363 | r = ni_init_microcode(rdev); | ||
1364 | if (r) { | ||
1365 | DRM_ERROR("Failed to load firmware!\n"); | ||
1366 | return r; | ||
1367 | } | ||
1368 | } | ||
1369 | r = ni_mc_load_microcode(rdev); | ||
1370 | if (r) { | ||
1371 | DRM_ERROR("Failed to load MC firmware!\n"); | ||
1372 | return r; | ||
1373 | } | ||
1374 | |||
1375 | evergreen_mc_program(rdev); | ||
1376 | r = cayman_pcie_gart_enable(rdev); | ||
1377 | if (r) | ||
1378 | return r; | ||
1379 | cayman_gpu_init(rdev); | ||
1380 | |||
1381 | #if 0 | ||
1382 | r = cayman_blit_init(rdev); | ||
1383 | if (r) { | ||
1384 | cayman_blit_fini(rdev); | ||
1385 | rdev->asic->copy = NULL; | ||
1386 | dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); | ||
1387 | } | ||
1388 | #endif | ||
1389 | |||
1390 | /* allocate wb buffer */ | ||
1391 | r = radeon_wb_init(rdev); | ||
1392 | if (r) | ||
1393 | return r; | ||
1394 | |||
1395 | /* Enable IRQ */ | ||
1396 | r = r600_irq_init(rdev); | ||
1397 | if (r) { | ||
1398 | DRM_ERROR("radeon: IH init failed (%d).\n", r); | ||
1399 | radeon_irq_kms_fini(rdev); | ||
1400 | return r; | ||
1401 | } | ||
1402 | evergreen_irq_set(rdev); | ||
1403 | |||
1404 | r = radeon_ring_init(rdev, rdev->cp.ring_size); | ||
1405 | if (r) | ||
1406 | return r; | ||
1407 | r = cayman_cp_load_microcode(rdev); | ||
1408 | if (r) | ||
1409 | return r; | ||
1410 | r = cayman_cp_resume(rdev); | ||
1411 | if (r) | ||
1412 | return r; | ||
1413 | |||
1414 | return 0; | ||
1415 | } | ||
1416 | |||
1417 | int cayman_resume(struct radeon_device *rdev) | ||
1418 | { | ||
1419 | int r; | ||
1420 | |||
1421 | /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, | ||
1422 | * posting will perform necessary task to bring back GPU into good | ||
1423 | * shape. | ||
1424 | */ | ||
1425 | /* post card */ | ||
1426 | atom_asic_init(rdev->mode_info.atom_context); | ||
1427 | |||
1428 | r = cayman_startup(rdev); | ||
1429 | if (r) { | ||
1430 | DRM_ERROR("cayman startup failed on resume\n"); | ||
1431 | return r; | ||
1432 | } | ||
1433 | |||
1434 | r = r600_ib_test(rdev); | ||
1435 | if (r) { | ||
1436 | DRM_ERROR("radeon: failled testing IB (%d).\n", r); | ||
1437 | return r; | ||
1438 | } | ||
1439 | |||
1440 | return r; | ||
1441 | |||
1442 | } | ||
1443 | |||
1444 | int cayman_suspend(struct radeon_device *rdev) | ||
1445 | { | ||
1446 | /* int r; */ | ||
1447 | |||
1448 | /* FIXME: we should wait for ring to be empty */ | ||
1449 | cayman_cp_enable(rdev, false); | ||
1450 | rdev->cp.ready = false; | ||
1451 | evergreen_irq_suspend(rdev); | ||
1452 | radeon_wb_disable(rdev); | ||
1453 | cayman_pcie_gart_disable(rdev); | ||
1454 | |||
1455 | #if 0 | ||
1456 | /* unpin shaders bo */ | ||
1457 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
1458 | if (likely(r == 0)) { | ||
1459 | radeon_bo_unpin(rdev->r600_blit.shader_obj); | ||
1460 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
1461 | } | ||
1462 | #endif | ||
1463 | return 0; | ||
1464 | } | ||
1465 | |||
1466 | /* Plan is to move initialization in that function and use | ||
1467 | * helper function so that radeon_device_init pretty much | ||
1468 | * do nothing more than calling asic specific function. This | ||
1469 | * should also allow to remove a bunch of callback function | ||
1470 | * like vram_info. | ||
1471 | */ | ||
1472 | int cayman_init(struct radeon_device *rdev) | ||
1473 | { | ||
1474 | int r; | ||
1475 | |||
1476 | /* This don't do much */ | ||
1477 | r = radeon_gem_init(rdev); | ||
1478 | if (r) | ||
1479 | return r; | ||
1480 | /* Read BIOS */ | ||
1481 | if (!radeon_get_bios(rdev)) { | ||
1482 | if (ASIC_IS_AVIVO(rdev)) | ||
1483 | return -EINVAL; | ||
1484 | } | ||
1485 | /* Must be an ATOMBIOS */ | ||
1486 | if (!rdev->is_atom_bios) { | ||
1487 | dev_err(rdev->dev, "Expecting atombios for cayman GPU\n"); | ||
1488 | return -EINVAL; | ||
1489 | } | ||
1490 | r = radeon_atombios_init(rdev); | ||
1491 | if (r) | ||
1492 | return r; | ||
1493 | |||
1494 | /* Post card if necessary */ | ||
1495 | if (!radeon_card_posted(rdev)) { | ||
1496 | if (!rdev->bios) { | ||
1497 | dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); | ||
1498 | return -EINVAL; | ||
1499 | } | ||
1500 | DRM_INFO("GPU not posted. posting now...\n"); | ||
1501 | atom_asic_init(rdev->mode_info.atom_context); | ||
1502 | } | ||
1503 | /* Initialize scratch registers */ | ||
1504 | r600_scratch_init(rdev); | ||
1505 | /* Initialize surface registers */ | ||
1506 | radeon_surface_init(rdev); | ||
1507 | /* Initialize clocks */ | ||
1508 | radeon_get_clock_info(rdev->ddev); | ||
1509 | /* Fence driver */ | ||
1510 | r = radeon_fence_driver_init(rdev); | ||
1511 | if (r) | ||
1512 | return r; | ||
1513 | /* initialize memory controller */ | ||
1514 | r = evergreen_mc_init(rdev); | ||
1515 | if (r) | ||
1516 | return r; | ||
1517 | /* Memory manager */ | ||
1518 | r = radeon_bo_init(rdev); | ||
1519 | if (r) | ||
1520 | return r; | ||
1521 | |||
1522 | r = radeon_irq_kms_init(rdev); | ||
1523 | if (r) | ||
1524 | return r; | ||
1525 | |||
1526 | rdev->cp.ring_obj = NULL; | ||
1527 | r600_ring_init(rdev, 1024 * 1024); | ||
1528 | |||
1529 | rdev->ih.ring_obj = NULL; | ||
1530 | r600_ih_ring_init(rdev, 64 * 1024); | ||
1531 | |||
1532 | r = r600_pcie_gart_init(rdev); | ||
1533 | if (r) | ||
1534 | return r; | ||
1535 | |||
1536 | rdev->accel_working = true; | ||
1537 | r = cayman_startup(rdev); | ||
1538 | if (r) { | ||
1539 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | ||
1540 | cayman_cp_fini(rdev); | ||
1541 | r600_irq_fini(rdev); | ||
1542 | radeon_wb_fini(rdev); | ||
1543 | radeon_irq_kms_fini(rdev); | ||
1544 | cayman_pcie_gart_fini(rdev); | ||
1545 | rdev->accel_working = false; | ||
1546 | } | ||
1547 | if (rdev->accel_working) { | ||
1548 | r = radeon_ib_pool_init(rdev); | ||
1549 | if (r) { | ||
1550 | DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); | ||
1551 | rdev->accel_working = false; | ||
1552 | } | ||
1553 | r = r600_ib_test(rdev); | ||
1554 | if (r) { | ||
1555 | DRM_ERROR("radeon: failed testing IB (%d).\n", r); | ||
1556 | rdev->accel_working = false; | ||
1557 | } | ||
1558 | } | ||
1559 | |||
1560 | /* Don't start up if the MC ucode is missing. | ||
1561 | * The default clocks and voltages before the MC ucode | ||
1562 | * is loaded are not suffient for advanced operations. | ||
1563 | */ | ||
1564 | if (!rdev->mc_fw) { | ||
1565 | DRM_ERROR("radeon: MC ucode required for NI+.\n"); | ||
1566 | return -EINVAL; | ||
1567 | } | ||
1568 | |||
1569 | return 0; | ||
1570 | } | ||
1571 | |||
1572 | void cayman_fini(struct radeon_device *rdev) | ||
1573 | { | ||
1574 | /* cayman_blit_fini(rdev); */ | ||
1575 | cayman_cp_fini(rdev); | ||
1576 | r600_irq_fini(rdev); | ||
1577 | radeon_wb_fini(rdev); | ||
1578 | radeon_irq_kms_fini(rdev); | ||
1579 | cayman_pcie_gart_fini(rdev); | ||
1580 | radeon_gem_fini(rdev); | ||
1581 | radeon_fence_driver_fini(rdev); | ||
1582 | radeon_bo_fini(rdev); | ||
1583 | radeon_atombios_fini(rdev); | ||
1584 | kfree(rdev->bios); | ||
1585 | rdev->bios = NULL; | ||
1586 | } | ||
1587 | |||
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 4ff28d68a498..6989e3422e87 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -1501,7 +1501,7 @@ extern void r600_hdmi_disable(struct drm_encoder *encoder); | |||
1501 | extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); | 1501 | extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); |
1502 | 1502 | ||
1503 | extern int ni_init_microcode(struct radeon_device *rdev); | 1503 | extern int ni_init_microcode(struct radeon_device *rdev); |
1504 | extern int btc_mc_load_microcode(struct radeon_device *rdev); | 1504 | extern int ni_mc_load_microcode(struct radeon_device *rdev); |
1505 | 1505 | ||
1506 | /* radeon_acpi.c */ | 1506 | /* radeon_acpi.c */ |
1507 | #if defined(CONFIG_ACPI) | 1507 | #if defined(CONFIG_ACPI) |