diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/rv770.c')
-rw-r--r-- | drivers/gpu/drm/radeon/rv770.c | 196 |
1 files changed, 195 insertions, 1 deletions
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 4dfead8cee33..3a264aa3a79a 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
@@ -41,6 +41,41 @@ | |||
41 | 41 | ||
42 | static void rv770_gpu_init(struct radeon_device *rdev); | 42 | static void rv770_gpu_init(struct radeon_device *rdev); |
43 | void rv770_fini(struct radeon_device *rdev); | 43 | void rv770_fini(struct radeon_device *rdev); |
44 | static void rv770_pcie_gen2_enable(struct radeon_device *rdev); | ||
45 | |||
46 | u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | ||
47 | { | ||
48 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | ||
49 | u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); | ||
50 | |||
51 | /* Lock the graphics update lock */ | ||
52 | tmp |= AVIVO_D1GRPH_UPDATE_LOCK; | ||
53 | WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); | ||
54 | |||
55 | /* update the scanout addresses */ | ||
56 | if (radeon_crtc->crtc_id) { | ||
57 | WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); | ||
58 | WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); | ||
59 | } else { | ||
60 | WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); | ||
61 | WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); | ||
62 | } | ||
63 | WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | ||
64 | (u32)crtc_base); | ||
65 | WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | ||
66 | (u32)crtc_base); | ||
67 | |||
68 | /* Wait for update_pending to go high. */ | ||
69 | while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); | ||
70 | DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); | ||
71 | |||
72 | /* Unlock the lock, so double-buffering can take place inside vblank */ | ||
73 | tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; | ||
74 | WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); | ||
75 | |||
76 | /* Return current update_pending status: */ | ||
77 | return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; | ||
78 | } | ||
44 | 79 | ||
45 | /* get temperature in millidegrees */ | 80 | /* get temperature in millidegrees */ |
46 | u32 rv770_get_temp(struct radeon_device *rdev) | 81 | u32 rv770_get_temp(struct radeon_device *rdev) |
@@ -489,6 +524,49 @@ static u32 r700_get_tile_pipe_to_backend_map(struct radeon_device *rdev, | |||
489 | return backend_map; | 524 | return backend_map; |
490 | } | 525 | } |
491 | 526 | ||
527 | static void rv770_program_channel_remap(struct radeon_device *rdev) | ||
528 | { | ||
529 | u32 tcp_chan_steer, mc_shared_chremap, tmp; | ||
530 | bool force_no_swizzle; | ||
531 | |||
532 | switch (rdev->family) { | ||
533 | case CHIP_RV770: | ||
534 | case CHIP_RV730: | ||
535 | force_no_swizzle = false; | ||
536 | break; | ||
537 | case CHIP_RV710: | ||
538 | case CHIP_RV740: | ||
539 | default: | ||
540 | force_no_swizzle = true; | ||
541 | break; | ||
542 | } | ||
543 | |||
544 | tmp = RREG32(MC_SHARED_CHMAP); | ||
545 | switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { | ||
546 | case 0: | ||
547 | case 1: | ||
548 | default: | ||
549 | /* default mapping */ | ||
550 | mc_shared_chremap = 0x00fac688; | ||
551 | break; | ||
552 | case 2: | ||
553 | case 3: | ||
554 | if (force_no_swizzle) | ||
555 | mc_shared_chremap = 0x00fac688; | ||
556 | else | ||
557 | mc_shared_chremap = 0x00bbc298; | ||
558 | break; | ||
559 | } | ||
560 | |||
561 | if (rdev->family == CHIP_RV740) | ||
562 | tcp_chan_steer = 0x00ef2a60; | ||
563 | else | ||
564 | tcp_chan_steer = 0x00fac688; | ||
565 | |||
566 | WREG32(TCP_CHAN_STEER, tcp_chan_steer); | ||
567 | WREG32(MC_SHARED_CHREMAP, mc_shared_chremap); | ||
568 | } | ||
569 | |||
492 | static void rv770_gpu_init(struct radeon_device *rdev) | 570 | static void rv770_gpu_init(struct radeon_device *rdev) |
493 | { | 571 | { |
494 | int i, j, num_qd_pipes; | 572 | int i, j, num_qd_pipes; |
@@ -688,6 +766,8 @@ static void rv770_gpu_init(struct radeon_device *rdev) | |||
688 | WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); | 766 | WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); |
689 | WREG32(HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); | 767 | WREG32(HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); |
690 | 768 | ||
769 | rv770_program_channel_remap(rdev); | ||
770 | |||
691 | WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); | 771 | WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); |
692 | WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); | 772 | WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); |
693 | WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); | 773 | WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); |
@@ -956,6 +1036,45 @@ static void rv770_vram_scratch_fini(struct radeon_device *rdev) | |||
956 | radeon_bo_unref(&rdev->vram_scratch.robj); | 1036 | radeon_bo_unref(&rdev->vram_scratch.robj); |
957 | } | 1037 | } |
958 | 1038 | ||
1039 | void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) | ||
1040 | { | ||
1041 | u64 size_bf, size_af; | ||
1042 | |||
1043 | if (mc->mc_vram_size > 0xE0000000) { | ||
1044 | /* leave room for at least 512M GTT */ | ||
1045 | dev_warn(rdev->dev, "limiting VRAM\n"); | ||
1046 | mc->real_vram_size = 0xE0000000; | ||
1047 | mc->mc_vram_size = 0xE0000000; | ||
1048 | } | ||
1049 | if (rdev->flags & RADEON_IS_AGP) { | ||
1050 | size_bf = mc->gtt_start; | ||
1051 | size_af = 0xFFFFFFFF - mc->gtt_end + 1; | ||
1052 | if (size_bf > size_af) { | ||
1053 | if (mc->mc_vram_size > size_bf) { | ||
1054 | dev_warn(rdev->dev, "limiting VRAM\n"); | ||
1055 | mc->real_vram_size = size_bf; | ||
1056 | mc->mc_vram_size = size_bf; | ||
1057 | } | ||
1058 | mc->vram_start = mc->gtt_start - mc->mc_vram_size; | ||
1059 | } else { | ||
1060 | if (mc->mc_vram_size > size_af) { | ||
1061 | dev_warn(rdev->dev, "limiting VRAM\n"); | ||
1062 | mc->real_vram_size = size_af; | ||
1063 | mc->mc_vram_size = size_af; | ||
1064 | } | ||
1065 | mc->vram_start = mc->gtt_end; | ||
1066 | } | ||
1067 | mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; | ||
1068 | dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", | ||
1069 | mc->mc_vram_size >> 20, mc->vram_start, | ||
1070 | mc->vram_end, mc->real_vram_size >> 20); | ||
1071 | } else { | ||
1072 | radeon_vram_location(rdev, &rdev->mc, 0); | ||
1073 | rdev->mc.gtt_base_align = 0; | ||
1074 | radeon_gtt_location(rdev, mc); | ||
1075 | } | ||
1076 | } | ||
1077 | |||
959 | int rv770_mc_init(struct radeon_device *rdev) | 1078 | int rv770_mc_init(struct radeon_device *rdev) |
960 | { | 1079 | { |
961 | u32 tmp; | 1080 | u32 tmp; |
@@ -996,7 +1115,7 @@ int rv770_mc_init(struct radeon_device *rdev) | |||
996 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); | 1115 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); |
997 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 1116 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
998 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | 1117 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; |
999 | r600_vram_gtt_location(rdev, &rdev->mc); | 1118 | r700_vram_gtt_location(rdev, &rdev->mc); |
1000 | radeon_update_bandwidth_info(rdev); | 1119 | radeon_update_bandwidth_info(rdev); |
1001 | 1120 | ||
1002 | return 0; | 1121 | return 0; |
@@ -1006,6 +1125,9 @@ static int rv770_startup(struct radeon_device *rdev) | |||
1006 | { | 1125 | { |
1007 | int r; | 1126 | int r; |
1008 | 1127 | ||
1128 | /* enable pcie gen2 link */ | ||
1129 | rv770_pcie_gen2_enable(rdev); | ||
1130 | |||
1009 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { | 1131 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { |
1010 | r = r600_init_microcode(rdev); | 1132 | r = r600_init_microcode(rdev); |
1011 | if (r) { | 1133 | if (r) { |
@@ -1244,3 +1366,75 @@ void rv770_fini(struct radeon_device *rdev) | |||
1244 | rdev->bios = NULL; | 1366 | rdev->bios = NULL; |
1245 | radeon_dummy_page_fini(rdev); | 1367 | radeon_dummy_page_fini(rdev); |
1246 | } | 1368 | } |
1369 | |||
1370 | static void rv770_pcie_gen2_enable(struct radeon_device *rdev) | ||
1371 | { | ||
1372 | u32 link_width_cntl, lanes, speed_cntl, tmp; | ||
1373 | u16 link_cntl2; | ||
1374 | |||
1375 | if (rdev->flags & RADEON_IS_IGP) | ||
1376 | return; | ||
1377 | |||
1378 | if (!(rdev->flags & RADEON_IS_PCIE)) | ||
1379 | return; | ||
1380 | |||
1381 | /* x2 cards have a special sequence */ | ||
1382 | if (ASIC_IS_X2(rdev)) | ||
1383 | return; | ||
1384 | |||
1385 | /* advertise upconfig capability */ | ||
1386 | link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); | ||
1387 | link_width_cntl &= ~LC_UPCONFIGURE_DIS; | ||
1388 | WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); | ||
1389 | link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); | ||
1390 | if (link_width_cntl & LC_RENEGOTIATION_SUPPORT) { | ||
1391 | lanes = (link_width_cntl & LC_LINK_WIDTH_RD_MASK) >> LC_LINK_WIDTH_RD_SHIFT; | ||
1392 | link_width_cntl &= ~(LC_LINK_WIDTH_MASK | | ||
1393 | LC_RECONFIG_ARC_MISSING_ESCAPE); | ||
1394 | link_width_cntl |= lanes | LC_RECONFIG_NOW | | ||
1395 | LC_RENEGOTIATE_EN | LC_UPCONFIGURE_SUPPORT; | ||
1396 | WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); | ||
1397 | } else { | ||
1398 | link_width_cntl |= LC_UPCONFIGURE_DIS; | ||
1399 | WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); | ||
1400 | } | ||
1401 | |||
1402 | speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); | ||
1403 | if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) && | ||
1404 | (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { | ||
1405 | |||
1406 | tmp = RREG32(0x541c); | ||
1407 | WREG32(0x541c, tmp | 0x8); | ||
1408 | WREG32(MM_CFGREGS_CNTL, MM_WR_TO_CFG_EN); | ||
1409 | link_cntl2 = RREG16(0x4088); | ||
1410 | link_cntl2 &= ~TARGET_LINK_SPEED_MASK; | ||
1411 | link_cntl2 |= 0x2; | ||
1412 | WREG16(0x4088, link_cntl2); | ||
1413 | WREG32(MM_CFGREGS_CNTL, 0); | ||
1414 | |||
1415 | speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); | ||
1416 | speed_cntl &= ~LC_TARGET_LINK_SPEED_OVERRIDE_EN; | ||
1417 | WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); | ||
1418 | |||
1419 | speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); | ||
1420 | speed_cntl |= LC_CLR_FAILED_SPD_CHANGE_CNT; | ||
1421 | WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); | ||
1422 | |||
1423 | speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); | ||
1424 | speed_cntl &= ~LC_CLR_FAILED_SPD_CHANGE_CNT; | ||
1425 | WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); | ||
1426 | |||
1427 | speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); | ||
1428 | speed_cntl |= LC_GEN2_EN_STRAP; | ||
1429 | WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl); | ||
1430 | |||
1431 | } else { | ||
1432 | link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); | ||
1433 | /* XXX: only disable it if gen1 bridge vendor == 0x111d or 0x1106 */ | ||
1434 | if (1) | ||
1435 | link_width_cntl |= LC_UPCONFIGURE_DIS; | ||
1436 | else | ||
1437 | link_width_cntl &= ~LC_UPCONFIGURE_DIS; | ||
1438 | WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); | ||
1439 | } | ||
1440 | } | ||