diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/ni.c')
-rw-r--r-- | drivers/gpu/drm/radeon/ni.c | 241 |
1 files changed, 240 insertions, 1 deletions
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 | |||