aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2011-03-02 20:07:34 -0500
committerDave Airlie <airlied@redhat.com>2011-03-02 20:52:04 -0500
commit755d819e0cf2e09e0958c77b72aa3ce2142411c2 (patch)
treef54b56dad294141467947f6d1e1259db6c5fc027 /drivers/gpu/drm/radeon
parentb9952a8ae5814b0ef2a6596c7443efd85b92e069 (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/radeon')
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c10
-rw-r--r--drivers/gpu/drm/radeon/ni.c241
-rw-r--r--drivers/gpu/drm/radeon/radeon.h2
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
1111static void evergreen_mc_program(struct radeon_device *rdev) 1111void 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
2568static void evergreen_irq_suspend(struct radeon_device *rdev) 2568void 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 @@
36extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); 36extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save);
37extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); 37extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save);
38extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev); 38extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev);
39extern void evergreen_mc_program(struct radeon_device *rdev);
40extern void evergreen_irq_suspend(struct radeon_device *rdev);
41extern 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
196int btc_mc_load_microcode(struct radeon_device *rdev) 199int 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
1135static void cayman_cp_fini(struct radeon_device *rdev)
1136{
1137 cayman_cp_enable(rdev, false);
1138 radeon_ring_fini(rdev);
1139}
1140
1132int cayman_cp_resume(struct radeon_device *rdev) 1141int 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
1358static 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
1417int 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
1444int 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 */
1472int 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
1572void 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);
1501extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); 1501extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
1502 1502
1503extern int ni_init_microcode(struct radeon_device *rdev); 1503extern int ni_init_microcode(struct radeon_device *rdev);
1504extern int btc_mc_load_microcode(struct radeon_device *rdev); 1504extern 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)