diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 770 |
1 files changed, 757 insertions, 13 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index c550932a108f..05a44896dffb 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -110,7 +110,7 @@ int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) | |||
110 | if (i < 0 || i > rdev->gart.num_gpu_pages) { | 110 | if (i < 0 || i > rdev->gart.num_gpu_pages) { |
111 | return -EINVAL; | 111 | return -EINVAL; |
112 | } | 112 | } |
113 | rdev->gart.table.ram.ptr[i] = cpu_to_le32((uint32_t)addr); | 113 | rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr)); |
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
@@ -173,8 +173,12 @@ void r100_mc_setup(struct radeon_device *rdev) | |||
173 | DRM_ERROR("Failed to register debugfs file for R100 MC !\n"); | 173 | DRM_ERROR("Failed to register debugfs file for R100 MC !\n"); |
174 | } | 174 | } |
175 | /* Write VRAM size in case we are limiting it */ | 175 | /* Write VRAM size in case we are limiting it */ |
176 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); | 176 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); |
177 | tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; | 177 | /* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM, |
178 | * if the aperture is 64MB but we have 32MB VRAM | ||
179 | * we report only 32MB VRAM but we have to set MC_FB_LOCATION | ||
180 | * to 64MB, otherwise the gpu accidentially dies */ | ||
181 | tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; | ||
178 | tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); | 182 | tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); |
179 | tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); | 183 | tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); |
180 | WREG32(RADEON_MC_FB_LOCATION, tmp); | 184 | WREG32(RADEON_MC_FB_LOCATION, tmp); |
@@ -215,7 +219,6 @@ int r100_mc_init(struct radeon_device *rdev) | |||
215 | r100_pci_gart_disable(rdev); | 219 | r100_pci_gart_disable(rdev); |
216 | 220 | ||
217 | /* Setup GPU memory space */ | 221 | /* Setup GPU memory space */ |
218 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
219 | rdev->mc.gtt_location = 0xFFFFFFFFUL; | 222 | rdev->mc.gtt_location = 0xFFFFFFFFUL; |
220 | if (rdev->flags & RADEON_IS_AGP) { | 223 | if (rdev->flags & RADEON_IS_AGP) { |
221 | r = radeon_agp_init(rdev); | 224 | r = radeon_agp_init(rdev); |
@@ -753,6 +756,102 @@ int r100_cs_packet_parse(struct radeon_cs_parser *p, | |||
753 | } | 756 | } |
754 | 757 | ||
755 | /** | 758 | /** |
759 | * r100_cs_packet_next_vline() - parse userspace VLINE packet | ||
760 | * @parser: parser structure holding parsing context. | ||
761 | * | ||
762 | * Userspace sends a special sequence for VLINE waits. | ||
763 | * PACKET0 - VLINE_START_END + value | ||
764 | * PACKET0 - WAIT_UNTIL +_value | ||
765 | * RELOC (P3) - crtc_id in reloc. | ||
766 | * | ||
767 | * This function parses this and relocates the VLINE START END | ||
768 | * and WAIT UNTIL packets to the correct crtc. | ||
769 | * It also detects a switched off crtc and nulls out the | ||
770 | * wait in that case. | ||
771 | */ | ||
772 | int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) | ||
773 | { | ||
774 | struct radeon_cs_chunk *ib_chunk; | ||
775 | struct drm_mode_object *obj; | ||
776 | struct drm_crtc *crtc; | ||
777 | struct radeon_crtc *radeon_crtc; | ||
778 | struct radeon_cs_packet p3reloc, waitreloc; | ||
779 | int crtc_id; | ||
780 | int r; | ||
781 | uint32_t header, h_idx, reg; | ||
782 | |||
783 | ib_chunk = &p->chunks[p->chunk_ib_idx]; | ||
784 | |||
785 | /* parse the wait until */ | ||
786 | r = r100_cs_packet_parse(p, &waitreloc, p->idx); | ||
787 | if (r) | ||
788 | return r; | ||
789 | |||
790 | /* check its a wait until and only 1 count */ | ||
791 | if (waitreloc.reg != RADEON_WAIT_UNTIL || | ||
792 | waitreloc.count != 0) { | ||
793 | DRM_ERROR("vline wait had illegal wait until segment\n"); | ||
794 | r = -EINVAL; | ||
795 | return r; | ||
796 | } | ||
797 | |||
798 | if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) { | ||
799 | DRM_ERROR("vline wait had illegal wait until\n"); | ||
800 | r = -EINVAL; | ||
801 | return r; | ||
802 | } | ||
803 | |||
804 | /* jump over the NOP */ | ||
805 | r = r100_cs_packet_parse(p, &p3reloc, p->idx); | ||
806 | if (r) | ||
807 | return r; | ||
808 | |||
809 | h_idx = p->idx - 2; | ||
810 | p->idx += waitreloc.count; | ||
811 | p->idx += p3reloc.count; | ||
812 | |||
813 | header = ib_chunk->kdata[h_idx]; | ||
814 | crtc_id = ib_chunk->kdata[h_idx + 5]; | ||
815 | reg = ib_chunk->kdata[h_idx] >> 2; | ||
816 | mutex_lock(&p->rdev->ddev->mode_config.mutex); | ||
817 | obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); | ||
818 | if (!obj) { | ||
819 | DRM_ERROR("cannot find crtc %d\n", crtc_id); | ||
820 | r = -EINVAL; | ||
821 | goto out; | ||
822 | } | ||
823 | crtc = obj_to_crtc(obj); | ||
824 | radeon_crtc = to_radeon_crtc(crtc); | ||
825 | crtc_id = radeon_crtc->crtc_id; | ||
826 | |||
827 | if (!crtc->enabled) { | ||
828 | /* if the CRTC isn't enabled - we need to nop out the wait until */ | ||
829 | ib_chunk->kdata[h_idx + 2] = PACKET2(0); | ||
830 | ib_chunk->kdata[h_idx + 3] = PACKET2(0); | ||
831 | } else if (crtc_id == 1) { | ||
832 | switch (reg) { | ||
833 | case AVIVO_D1MODE_VLINE_START_END: | ||
834 | header &= R300_CP_PACKET0_REG_MASK; | ||
835 | header |= AVIVO_D2MODE_VLINE_START_END >> 2; | ||
836 | break; | ||
837 | case RADEON_CRTC_GUI_TRIG_VLINE: | ||
838 | header &= R300_CP_PACKET0_REG_MASK; | ||
839 | header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2; | ||
840 | break; | ||
841 | default: | ||
842 | DRM_ERROR("unknown crtc reloc\n"); | ||
843 | r = -EINVAL; | ||
844 | goto out; | ||
845 | } | ||
846 | ib_chunk->kdata[h_idx] = header; | ||
847 | ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1; | ||
848 | } | ||
849 | out: | ||
850 | mutex_unlock(&p->rdev->ddev->mode_config.mutex); | ||
851 | return r; | ||
852 | } | ||
853 | |||
854 | /** | ||
756 | * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 | 855 | * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 |
757 | * @parser: parser structure holding parsing context. | 856 | * @parser: parser structure holding parsing context. |
758 | * @data: pointer to relocation data | 857 | * @data: pointer to relocation data |
@@ -814,6 +913,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
814 | unsigned idx; | 913 | unsigned idx; |
815 | bool onereg; | 914 | bool onereg; |
816 | int r; | 915 | int r; |
916 | u32 tile_flags = 0; | ||
817 | 917 | ||
818 | ib = p->ib->ptr; | 918 | ib = p->ib->ptr; |
819 | ib_chunk = &p->chunks[p->chunk_ib_idx]; | 919 | ib_chunk = &p->chunks[p->chunk_ib_idx]; |
@@ -825,6 +925,15 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
825 | } | 925 | } |
826 | for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { | 926 | for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { |
827 | switch (reg) { | 927 | switch (reg) { |
928 | case RADEON_CRTC_GUI_TRIG_VLINE: | ||
929 | r = r100_cs_packet_parse_vline(p); | ||
930 | if (r) { | ||
931 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
932 | idx, reg); | ||
933 | r100_cs_dump_packet(p, pkt); | ||
934 | return r; | ||
935 | } | ||
936 | break; | ||
828 | /* FIXME: only allow PACKET3 blit? easier to check for out of | 937 | /* FIXME: only allow PACKET3 blit? easier to check for out of |
829 | * range access */ | 938 | * range access */ |
830 | case RADEON_DST_PITCH_OFFSET: | 939 | case RADEON_DST_PITCH_OFFSET: |
@@ -838,7 +947,20 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
838 | } | 947 | } |
839 | tmp = ib_chunk->kdata[idx] & 0x003fffff; | 948 | tmp = ib_chunk->kdata[idx] & 0x003fffff; |
840 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); | 949 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); |
841 | ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp; | 950 | |
951 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
952 | tile_flags |= RADEON_DST_TILE_MACRO; | ||
953 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { | ||
954 | if (reg == RADEON_SRC_PITCH_OFFSET) { | ||
955 | DRM_ERROR("Cannot src blit from microtiled surface\n"); | ||
956 | r100_cs_dump_packet(p, pkt); | ||
957 | return -EINVAL; | ||
958 | } | ||
959 | tile_flags |= RADEON_DST_TILE_MICRO; | ||
960 | } | ||
961 | |||
962 | tmp |= tile_flags; | ||
963 | ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp; | ||
842 | break; | 964 | break; |
843 | case RADEON_RB3D_DEPTHOFFSET: | 965 | case RADEON_RB3D_DEPTHOFFSET: |
844 | case RADEON_RB3D_COLOROFFSET: | 966 | case RADEON_RB3D_COLOROFFSET: |
@@ -869,6 +991,11 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
869 | case R300_TX_OFFSET_0+52: | 991 | case R300_TX_OFFSET_0+52: |
870 | case R300_TX_OFFSET_0+56: | 992 | case R300_TX_OFFSET_0+56: |
871 | case R300_TX_OFFSET_0+60: | 993 | case R300_TX_OFFSET_0+60: |
994 | /* rn50 has no 3D engine so fail on any 3d setup */ | ||
995 | if (ASIC_IS_RN50(p->rdev)) { | ||
996 | DRM_ERROR("attempt to use RN50 3D engine failed\n"); | ||
997 | return -EINVAL; | ||
998 | } | ||
872 | r = r100_cs_packet_next_reloc(p, &reloc); | 999 | r = r100_cs_packet_next_reloc(p, &reloc); |
873 | if (r) { | 1000 | if (r) { |
874 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | 1001 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
@@ -878,6 +1005,25 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
878 | } | 1005 | } |
879 | ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); | 1006 | ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
880 | break; | 1007 | break; |
1008 | case R300_RB3D_COLORPITCH0: | ||
1009 | case RADEON_RB3D_COLORPITCH: | ||
1010 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
1011 | if (r) { | ||
1012 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
1013 | idx, reg); | ||
1014 | r100_cs_dump_packet(p, pkt); | ||
1015 | return r; | ||
1016 | } | ||
1017 | |||
1018 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
1019 | tile_flags |= RADEON_COLOR_TILE_ENABLE; | ||
1020 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) | ||
1021 | tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; | ||
1022 | |||
1023 | tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); | ||
1024 | tmp |= tile_flags; | ||
1025 | ib[idx] = tmp; | ||
1026 | break; | ||
881 | default: | 1027 | default: |
882 | /* FIXME: we don't want to allow anyothers packet */ | 1028 | /* FIXME: we don't want to allow anyothers packet */ |
883 | break; | 1029 | break; |
@@ -1256,29 +1402,100 @@ static void r100_vram_get_type(struct radeon_device *rdev) | |||
1256 | } | 1402 | } |
1257 | } | 1403 | } |
1258 | 1404 | ||
1259 | void r100_vram_info(struct radeon_device *rdev) | 1405 | static u32 r100_get_accessible_vram(struct radeon_device *rdev) |
1260 | { | 1406 | { |
1261 | r100_vram_get_type(rdev); | 1407 | u32 aper_size; |
1408 | u8 byte; | ||
1409 | |||
1410 | aper_size = RREG32(RADEON_CONFIG_APER_SIZE); | ||
1411 | |||
1412 | /* Set HDP_APER_CNTL only on cards that are known not to be broken, | ||
1413 | * that is has the 2nd generation multifunction PCI interface | ||
1414 | */ | ||
1415 | if (rdev->family == CHIP_RV280 || | ||
1416 | rdev->family >= CHIP_RV350) { | ||
1417 | WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, | ||
1418 | ~RADEON_HDP_APER_CNTL); | ||
1419 | DRM_INFO("Generation 2 PCI interface, using max accessible memory\n"); | ||
1420 | return aper_size * 2; | ||
1421 | } | ||
1422 | |||
1423 | /* Older cards have all sorts of funny issues to deal with. First | ||
1424 | * check if it's a multifunction card by reading the PCI config | ||
1425 | * header type... Limit those to one aperture size | ||
1426 | */ | ||
1427 | pci_read_config_byte(rdev->pdev, 0xe, &byte); | ||
1428 | if (byte & 0x80) { | ||
1429 | DRM_INFO("Generation 1 PCI interface in multifunction mode\n"); | ||
1430 | DRM_INFO("Limiting VRAM to one aperture\n"); | ||
1431 | return aper_size; | ||
1432 | } | ||
1433 | |||
1434 | /* Single function older card. We read HDP_APER_CNTL to see how the BIOS | ||
1435 | * have set it up. We don't write this as it's broken on some ASICs but | ||
1436 | * we expect the BIOS to have done the right thing (might be too optimistic...) | ||
1437 | */ | ||
1438 | if (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) | ||
1439 | return aper_size * 2; | ||
1440 | return aper_size; | ||
1441 | } | ||
1442 | |||
1443 | void r100_vram_init_sizes(struct radeon_device *rdev) | ||
1444 | { | ||
1445 | u64 config_aper_size; | ||
1446 | u32 accessible; | ||
1447 | |||
1448 | config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); | ||
1262 | 1449 | ||
1263 | if (rdev->flags & RADEON_IS_IGP) { | 1450 | if (rdev->flags & RADEON_IS_IGP) { |
1264 | uint32_t tom; | 1451 | uint32_t tom; |
1265 | /* read NB_TOM to get the amount of ram stolen for the GPU */ | 1452 | /* read NB_TOM to get the amount of ram stolen for the GPU */ |
1266 | tom = RREG32(RADEON_NB_TOM); | 1453 | tom = RREG32(RADEON_NB_TOM); |
1267 | rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); | 1454 | rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); |
1268 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); | 1455 | /* for IGPs we need to keep VRAM where it was put by the BIOS */ |
1456 | rdev->mc.vram_location = (tom & 0xffff) << 16; | ||
1457 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); | ||
1458 | rdev->mc.mc_vram_size = rdev->mc.real_vram_size; | ||
1269 | } else { | 1459 | } else { |
1270 | rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); | 1460 | rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); |
1271 | /* Some production boards of m6 will report 0 | 1461 | /* Some production boards of m6 will report 0 |
1272 | * if it's 8 MB | 1462 | * if it's 8 MB |
1273 | */ | 1463 | */ |
1274 | if (rdev->mc.vram_size == 0) { | 1464 | if (rdev->mc.real_vram_size == 0) { |
1275 | rdev->mc.vram_size = 8192 * 1024; | 1465 | rdev->mc.real_vram_size = 8192 * 1024; |
1276 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); | 1466 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); |
1277 | } | 1467 | } |
1468 | /* let driver place VRAM */ | ||
1469 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
1470 | /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - | ||
1471 | * Novell bug 204882 + along with lots of ubuntu ones */ | ||
1472 | if (config_aper_size > rdev->mc.real_vram_size) | ||
1473 | rdev->mc.mc_vram_size = config_aper_size; | ||
1474 | else | ||
1475 | rdev->mc.mc_vram_size = rdev->mc.real_vram_size; | ||
1278 | } | 1476 | } |
1279 | 1477 | ||
1478 | /* work out accessible VRAM */ | ||
1479 | accessible = r100_get_accessible_vram(rdev); | ||
1480 | |||
1280 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); | 1481 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); |
1281 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); | 1482 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); |
1483 | |||
1484 | if (accessible > rdev->mc.aper_size) | ||
1485 | accessible = rdev->mc.aper_size; | ||
1486 | |||
1487 | if (rdev->mc.mc_vram_size > rdev->mc.aper_size) | ||
1488 | rdev->mc.mc_vram_size = rdev->mc.aper_size; | ||
1489 | |||
1490 | if (rdev->mc.real_vram_size > rdev->mc.aper_size) | ||
1491 | rdev->mc.real_vram_size = rdev->mc.aper_size; | ||
1492 | } | ||
1493 | |||
1494 | void r100_vram_info(struct radeon_device *rdev) | ||
1495 | { | ||
1496 | r100_vram_get_type(rdev); | ||
1497 | |||
1498 | r100_vram_init_sizes(rdev); | ||
1282 | } | 1499 | } |
1283 | 1500 | ||
1284 | 1501 | ||
@@ -1533,3 +1750,530 @@ int r100_debugfs_mc_info_init(struct radeon_device *rdev) | |||
1533 | return 0; | 1750 | return 0; |
1534 | #endif | 1751 | #endif |
1535 | } | 1752 | } |
1753 | |||
1754 | int r100_set_surface_reg(struct radeon_device *rdev, int reg, | ||
1755 | uint32_t tiling_flags, uint32_t pitch, | ||
1756 | uint32_t offset, uint32_t obj_size) | ||
1757 | { | ||
1758 | int surf_index = reg * 16; | ||
1759 | int flags = 0; | ||
1760 | |||
1761 | /* r100/r200 divide by 16 */ | ||
1762 | if (rdev->family < CHIP_R300) | ||
1763 | flags = pitch / 16; | ||
1764 | else | ||
1765 | flags = pitch / 8; | ||
1766 | |||
1767 | if (rdev->family <= CHIP_RS200) { | ||
1768 | if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) | ||
1769 | == (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) | ||
1770 | flags |= RADEON_SURF_TILE_COLOR_BOTH; | ||
1771 | if (tiling_flags & RADEON_TILING_MACRO) | ||
1772 | flags |= RADEON_SURF_TILE_COLOR_MACRO; | ||
1773 | } else if (rdev->family <= CHIP_RV280) { | ||
1774 | if (tiling_flags & (RADEON_TILING_MACRO)) | ||
1775 | flags |= R200_SURF_TILE_COLOR_MACRO; | ||
1776 | if (tiling_flags & RADEON_TILING_MICRO) | ||
1777 | flags |= R200_SURF_TILE_COLOR_MICRO; | ||
1778 | } else { | ||
1779 | if (tiling_flags & RADEON_TILING_MACRO) | ||
1780 | flags |= R300_SURF_TILE_MACRO; | ||
1781 | if (tiling_flags & RADEON_TILING_MICRO) | ||
1782 | flags |= R300_SURF_TILE_MICRO; | ||
1783 | } | ||
1784 | |||
1785 | DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1); | ||
1786 | WREG32(RADEON_SURFACE0_INFO + surf_index, flags); | ||
1787 | WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset); | ||
1788 | WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1); | ||
1789 | return 0; | ||
1790 | } | ||
1791 | |||
1792 | void r100_clear_surface_reg(struct radeon_device *rdev, int reg) | ||
1793 | { | ||
1794 | int surf_index = reg * 16; | ||
1795 | WREG32(RADEON_SURFACE0_INFO + surf_index, 0); | ||
1796 | } | ||
1797 | |||
1798 | void r100_bandwidth_update(struct radeon_device *rdev) | ||
1799 | { | ||
1800 | fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; | ||
1801 | fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; | ||
1802 | fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; | ||
1803 | uint32_t temp, data, mem_trcd, mem_trp, mem_tras; | ||
1804 | fixed20_12 memtcas_ff[8] = { | ||
1805 | fixed_init(1), | ||
1806 | fixed_init(2), | ||
1807 | fixed_init(3), | ||
1808 | fixed_init(0), | ||
1809 | fixed_init_half(1), | ||
1810 | fixed_init_half(2), | ||
1811 | fixed_init(0), | ||
1812 | }; | ||
1813 | fixed20_12 memtcas_rs480_ff[8] = { | ||
1814 | fixed_init(0), | ||
1815 | fixed_init(1), | ||
1816 | fixed_init(2), | ||
1817 | fixed_init(3), | ||
1818 | fixed_init(0), | ||
1819 | fixed_init_half(1), | ||
1820 | fixed_init_half(2), | ||
1821 | fixed_init_half(3), | ||
1822 | }; | ||
1823 | fixed20_12 memtcas2_ff[8] = { | ||
1824 | fixed_init(0), | ||
1825 | fixed_init(1), | ||
1826 | fixed_init(2), | ||
1827 | fixed_init(3), | ||
1828 | fixed_init(4), | ||
1829 | fixed_init(5), | ||
1830 | fixed_init(6), | ||
1831 | fixed_init(7), | ||
1832 | }; | ||
1833 | fixed20_12 memtrbs[8] = { | ||
1834 | fixed_init(1), | ||
1835 | fixed_init_half(1), | ||
1836 | fixed_init(2), | ||
1837 | fixed_init_half(2), | ||
1838 | fixed_init(3), | ||
1839 | fixed_init_half(3), | ||
1840 | fixed_init(4), | ||
1841 | fixed_init_half(4) | ||
1842 | }; | ||
1843 | fixed20_12 memtrbs_r4xx[8] = { | ||
1844 | fixed_init(4), | ||
1845 | fixed_init(5), | ||
1846 | fixed_init(6), | ||
1847 | fixed_init(7), | ||
1848 | fixed_init(8), | ||
1849 | fixed_init(9), | ||
1850 | fixed_init(10), | ||
1851 | fixed_init(11) | ||
1852 | }; | ||
1853 | fixed20_12 min_mem_eff; | ||
1854 | fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; | ||
1855 | fixed20_12 cur_latency_mclk, cur_latency_sclk; | ||
1856 | fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, | ||
1857 | disp_drain_rate2, read_return_rate; | ||
1858 | fixed20_12 time_disp1_drop_priority; | ||
1859 | int c; | ||
1860 | int cur_size = 16; /* in octawords */ | ||
1861 | int critical_point = 0, critical_point2; | ||
1862 | /* uint32_t read_return_rate, time_disp1_drop_priority; */ | ||
1863 | int stop_req, max_stop_req; | ||
1864 | struct drm_display_mode *mode1 = NULL; | ||
1865 | struct drm_display_mode *mode2 = NULL; | ||
1866 | uint32_t pixel_bytes1 = 0; | ||
1867 | uint32_t pixel_bytes2 = 0; | ||
1868 | |||
1869 | if (rdev->mode_info.crtcs[0]->base.enabled) { | ||
1870 | mode1 = &rdev->mode_info.crtcs[0]->base.mode; | ||
1871 | pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; | ||
1872 | } | ||
1873 | if (rdev->mode_info.crtcs[1]->base.enabled) { | ||
1874 | mode2 = &rdev->mode_info.crtcs[1]->base.mode; | ||
1875 | pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; | ||
1876 | } | ||
1877 | |||
1878 | min_mem_eff.full = rfixed_const_8(0); | ||
1879 | /* get modes */ | ||
1880 | if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { | ||
1881 | uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); | ||
1882 | mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); | ||
1883 | mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); | ||
1884 | /* check crtc enables */ | ||
1885 | if (mode2) | ||
1886 | mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); | ||
1887 | if (mode1) | ||
1888 | mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); | ||
1889 | WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); | ||
1890 | } | ||
1891 | |||
1892 | /* | ||
1893 | * determine is there is enough bw for current mode | ||
1894 | */ | ||
1895 | mclk_ff.full = rfixed_const(rdev->clock.default_mclk); | ||
1896 | temp_ff.full = rfixed_const(100); | ||
1897 | mclk_ff.full = rfixed_div(mclk_ff, temp_ff); | ||
1898 | sclk_ff.full = rfixed_const(rdev->clock.default_sclk); | ||
1899 | sclk_ff.full = rfixed_div(sclk_ff, temp_ff); | ||
1900 | |||
1901 | temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); | ||
1902 | temp_ff.full = rfixed_const(temp); | ||
1903 | mem_bw.full = rfixed_mul(mclk_ff, temp_ff); | ||
1904 | |||
1905 | pix_clk.full = 0; | ||
1906 | pix_clk2.full = 0; | ||
1907 | peak_disp_bw.full = 0; | ||
1908 | if (mode1) { | ||
1909 | temp_ff.full = rfixed_const(1000); | ||
1910 | pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ | ||
1911 | pix_clk.full = rfixed_div(pix_clk, temp_ff); | ||
1912 | temp_ff.full = rfixed_const(pixel_bytes1); | ||
1913 | peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); | ||
1914 | } | ||
1915 | if (mode2) { | ||
1916 | temp_ff.full = rfixed_const(1000); | ||
1917 | pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ | ||
1918 | pix_clk2.full = rfixed_div(pix_clk2, temp_ff); | ||
1919 | temp_ff.full = rfixed_const(pixel_bytes2); | ||
1920 | peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); | ||
1921 | } | ||
1922 | |||
1923 | mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); | ||
1924 | if (peak_disp_bw.full >= mem_bw.full) { | ||
1925 | DRM_ERROR("You may not have enough display bandwidth for current mode\n" | ||
1926 | "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); | ||
1927 | } | ||
1928 | |||
1929 | /* Get values from the EXT_MEM_CNTL register...converting its contents. */ | ||
1930 | temp = RREG32(RADEON_MEM_TIMING_CNTL); | ||
1931 | if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ | ||
1932 | mem_trcd = ((temp >> 2) & 0x3) + 1; | ||
1933 | mem_trp = ((temp & 0x3)) + 1; | ||
1934 | mem_tras = ((temp & 0x70) >> 4) + 1; | ||
1935 | } else if (rdev->family == CHIP_R300 || | ||
1936 | rdev->family == CHIP_R350) { /* r300, r350 */ | ||
1937 | mem_trcd = (temp & 0x7) + 1; | ||
1938 | mem_trp = ((temp >> 8) & 0x7) + 1; | ||
1939 | mem_tras = ((temp >> 11) & 0xf) + 4; | ||
1940 | } else if (rdev->family == CHIP_RV350 || | ||
1941 | rdev->family <= CHIP_RV380) { | ||
1942 | /* rv3x0 */ | ||
1943 | mem_trcd = (temp & 0x7) + 3; | ||
1944 | mem_trp = ((temp >> 8) & 0x7) + 3; | ||
1945 | mem_tras = ((temp >> 11) & 0xf) + 6; | ||
1946 | } else if (rdev->family == CHIP_R420 || | ||
1947 | rdev->family == CHIP_R423 || | ||
1948 | rdev->family == CHIP_RV410) { | ||
1949 | /* r4xx */ | ||
1950 | mem_trcd = (temp & 0xf) + 3; | ||
1951 | if (mem_trcd > 15) | ||
1952 | mem_trcd = 15; | ||
1953 | mem_trp = ((temp >> 8) & 0xf) + 3; | ||
1954 | if (mem_trp > 15) | ||
1955 | mem_trp = 15; | ||
1956 | mem_tras = ((temp >> 12) & 0x1f) + 6; | ||
1957 | if (mem_tras > 31) | ||
1958 | mem_tras = 31; | ||
1959 | } else { /* RV200, R200 */ | ||
1960 | mem_trcd = (temp & 0x7) + 1; | ||
1961 | mem_trp = ((temp >> 8) & 0x7) + 1; | ||
1962 | mem_tras = ((temp >> 12) & 0xf) + 4; | ||
1963 | } | ||
1964 | /* convert to FF */ | ||
1965 | trcd_ff.full = rfixed_const(mem_trcd); | ||
1966 | trp_ff.full = rfixed_const(mem_trp); | ||
1967 | tras_ff.full = rfixed_const(mem_tras); | ||
1968 | |||
1969 | /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ | ||
1970 | temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); | ||
1971 | data = (temp & (7 << 20)) >> 20; | ||
1972 | if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { | ||
1973 | if (rdev->family == CHIP_RS480) /* don't think rs400 */ | ||
1974 | tcas_ff = memtcas_rs480_ff[data]; | ||
1975 | else | ||
1976 | tcas_ff = memtcas_ff[data]; | ||
1977 | } else | ||
1978 | tcas_ff = memtcas2_ff[data]; | ||
1979 | |||
1980 | if (rdev->family == CHIP_RS400 || | ||
1981 | rdev->family == CHIP_RS480) { | ||
1982 | /* extra cas latency stored in bits 23-25 0-4 clocks */ | ||
1983 | data = (temp >> 23) & 0x7; | ||
1984 | if (data < 5) | ||
1985 | tcas_ff.full += rfixed_const(data); | ||
1986 | } | ||
1987 | |||
1988 | if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { | ||
1989 | /* on the R300, Tcas is included in Trbs. | ||
1990 | */ | ||
1991 | temp = RREG32(RADEON_MEM_CNTL); | ||
1992 | data = (R300_MEM_NUM_CHANNELS_MASK & temp); | ||
1993 | if (data == 1) { | ||
1994 | if (R300_MEM_USE_CD_CH_ONLY & temp) { | ||
1995 | temp = RREG32(R300_MC_IND_INDEX); | ||
1996 | temp &= ~R300_MC_IND_ADDR_MASK; | ||
1997 | temp |= R300_MC_READ_CNTL_CD_mcind; | ||
1998 | WREG32(R300_MC_IND_INDEX, temp); | ||
1999 | temp = RREG32(R300_MC_IND_DATA); | ||
2000 | data = (R300_MEM_RBS_POSITION_C_MASK & temp); | ||
2001 | } else { | ||
2002 | temp = RREG32(R300_MC_READ_CNTL_AB); | ||
2003 | data = (R300_MEM_RBS_POSITION_A_MASK & temp); | ||
2004 | } | ||
2005 | } else { | ||
2006 | temp = RREG32(R300_MC_READ_CNTL_AB); | ||
2007 | data = (R300_MEM_RBS_POSITION_A_MASK & temp); | ||
2008 | } | ||
2009 | if (rdev->family == CHIP_RV410 || | ||
2010 | rdev->family == CHIP_R420 || | ||
2011 | rdev->family == CHIP_R423) | ||
2012 | trbs_ff = memtrbs_r4xx[data]; | ||
2013 | else | ||
2014 | trbs_ff = memtrbs[data]; | ||
2015 | tcas_ff.full += trbs_ff.full; | ||
2016 | } | ||
2017 | |||
2018 | sclk_eff_ff.full = sclk_ff.full; | ||
2019 | |||
2020 | if (rdev->flags & RADEON_IS_AGP) { | ||
2021 | fixed20_12 agpmode_ff; | ||
2022 | agpmode_ff.full = rfixed_const(radeon_agpmode); | ||
2023 | temp_ff.full = rfixed_const_666(16); | ||
2024 | sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff); | ||
2025 | } | ||
2026 | /* TODO PCIE lanes may affect this - agpmode == 16?? */ | ||
2027 | |||
2028 | if (ASIC_IS_R300(rdev)) { | ||
2029 | sclk_delay_ff.full = rfixed_const(250); | ||
2030 | } else { | ||
2031 | if ((rdev->family == CHIP_RV100) || | ||
2032 | rdev->flags & RADEON_IS_IGP) { | ||
2033 | if (rdev->mc.vram_is_ddr) | ||
2034 | sclk_delay_ff.full = rfixed_const(41); | ||
2035 | else | ||
2036 | sclk_delay_ff.full = rfixed_const(33); | ||
2037 | } else { | ||
2038 | if (rdev->mc.vram_width == 128) | ||
2039 | sclk_delay_ff.full = rfixed_const(57); | ||
2040 | else | ||
2041 | sclk_delay_ff.full = rfixed_const(41); | ||
2042 | } | ||
2043 | } | ||
2044 | |||
2045 | mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff); | ||
2046 | |||
2047 | if (rdev->mc.vram_is_ddr) { | ||
2048 | if (rdev->mc.vram_width == 32) { | ||
2049 | k1.full = rfixed_const(40); | ||
2050 | c = 3; | ||
2051 | } else { | ||
2052 | k1.full = rfixed_const(20); | ||
2053 | c = 1; | ||
2054 | } | ||
2055 | } else { | ||
2056 | k1.full = rfixed_const(40); | ||
2057 | c = 3; | ||
2058 | } | ||
2059 | |||
2060 | temp_ff.full = rfixed_const(2); | ||
2061 | mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff); | ||
2062 | temp_ff.full = rfixed_const(c); | ||
2063 | mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff); | ||
2064 | temp_ff.full = rfixed_const(4); | ||
2065 | mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff); | ||
2066 | mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff); | ||
2067 | mc_latency_mclk.full += k1.full; | ||
2068 | |||
2069 | mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff); | ||
2070 | mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff); | ||
2071 | |||
2072 | /* | ||
2073 | HW cursor time assuming worst case of full size colour cursor. | ||
2074 | */ | ||
2075 | temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); | ||
2076 | temp_ff.full += trcd_ff.full; | ||
2077 | if (temp_ff.full < tras_ff.full) | ||
2078 | temp_ff.full = tras_ff.full; | ||
2079 | cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff); | ||
2080 | |||
2081 | temp_ff.full = rfixed_const(cur_size); | ||
2082 | cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff); | ||
2083 | /* | ||
2084 | Find the total latency for the display data. | ||
2085 | */ | ||
2086 | disp_latency_overhead.full = rfixed_const(80); | ||
2087 | disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff); | ||
2088 | mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; | ||
2089 | mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; | ||
2090 | |||
2091 | if (mc_latency_mclk.full > mc_latency_sclk.full) | ||
2092 | disp_latency.full = mc_latency_mclk.full; | ||
2093 | else | ||
2094 | disp_latency.full = mc_latency_sclk.full; | ||
2095 | |||
2096 | /* setup Max GRPH_STOP_REQ default value */ | ||
2097 | if (ASIC_IS_RV100(rdev)) | ||
2098 | max_stop_req = 0x5c; | ||
2099 | else | ||
2100 | max_stop_req = 0x7c; | ||
2101 | |||
2102 | if (mode1) { | ||
2103 | /* CRTC1 | ||
2104 | Set GRPH_BUFFER_CNTL register using h/w defined optimal values. | ||
2105 | GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] | ||
2106 | */ | ||
2107 | stop_req = mode1->hdisplay * pixel_bytes1 / 16; | ||
2108 | |||
2109 | if (stop_req > max_stop_req) | ||
2110 | stop_req = max_stop_req; | ||
2111 | |||
2112 | /* | ||
2113 | Find the drain rate of the display buffer. | ||
2114 | */ | ||
2115 | temp_ff.full = rfixed_const((16/pixel_bytes1)); | ||
2116 | disp_drain_rate.full = rfixed_div(pix_clk, temp_ff); | ||
2117 | |||
2118 | /* | ||
2119 | Find the critical point of the display buffer. | ||
2120 | */ | ||
2121 | crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency); | ||
2122 | crit_point_ff.full += rfixed_const_half(0); | ||
2123 | |||
2124 | critical_point = rfixed_trunc(crit_point_ff); | ||
2125 | |||
2126 | if (rdev->disp_priority == 2) { | ||
2127 | critical_point = 0; | ||
2128 | } | ||
2129 | |||
2130 | /* | ||
2131 | The critical point should never be above max_stop_req-4. Setting | ||
2132 | GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. | ||
2133 | */ | ||
2134 | if (max_stop_req - critical_point < 4) | ||
2135 | critical_point = 0; | ||
2136 | |||
2137 | if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { | ||
2138 | /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ | ||
2139 | critical_point = 0x10; | ||
2140 | } | ||
2141 | |||
2142 | temp = RREG32(RADEON_GRPH_BUFFER_CNTL); | ||
2143 | temp &= ~(RADEON_GRPH_STOP_REQ_MASK); | ||
2144 | temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); | ||
2145 | temp &= ~(RADEON_GRPH_START_REQ_MASK); | ||
2146 | if ((rdev->family == CHIP_R350) && | ||
2147 | (stop_req > 0x15)) { | ||
2148 | stop_req -= 0x10; | ||
2149 | } | ||
2150 | temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); | ||
2151 | temp |= RADEON_GRPH_BUFFER_SIZE; | ||
2152 | temp &= ~(RADEON_GRPH_CRITICAL_CNTL | | ||
2153 | RADEON_GRPH_CRITICAL_AT_SOF | | ||
2154 | RADEON_GRPH_STOP_CNTL); | ||
2155 | /* | ||
2156 | Write the result into the register. | ||
2157 | */ | ||
2158 | WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | | ||
2159 | (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); | ||
2160 | |||
2161 | #if 0 | ||
2162 | if ((rdev->family == CHIP_RS400) || | ||
2163 | (rdev->family == CHIP_RS480)) { | ||
2164 | /* attempt to program RS400 disp regs correctly ??? */ | ||
2165 | temp = RREG32(RS400_DISP1_REG_CNTL); | ||
2166 | temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | | ||
2167 | RS400_DISP1_STOP_REQ_LEVEL_MASK); | ||
2168 | WREG32(RS400_DISP1_REQ_CNTL1, (temp | | ||
2169 | (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | | ||
2170 | (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); | ||
2171 | temp = RREG32(RS400_DMIF_MEM_CNTL1); | ||
2172 | temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | | ||
2173 | RS400_DISP1_CRITICAL_POINT_STOP_MASK); | ||
2174 | WREG32(RS400_DMIF_MEM_CNTL1, (temp | | ||
2175 | (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | | ||
2176 | (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); | ||
2177 | } | ||
2178 | #endif | ||
2179 | |||
2180 | DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n", | ||
2181 | /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ | ||
2182 | (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); | ||
2183 | } | ||
2184 | |||
2185 | if (mode2) { | ||
2186 | u32 grph2_cntl; | ||
2187 | stop_req = mode2->hdisplay * pixel_bytes2 / 16; | ||
2188 | |||
2189 | if (stop_req > max_stop_req) | ||
2190 | stop_req = max_stop_req; | ||
2191 | |||
2192 | /* | ||
2193 | Find the drain rate of the display buffer. | ||
2194 | */ | ||
2195 | temp_ff.full = rfixed_const((16/pixel_bytes2)); | ||
2196 | disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff); | ||
2197 | |||
2198 | grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); | ||
2199 | grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); | ||
2200 | grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); | ||
2201 | grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); | ||
2202 | if ((rdev->family == CHIP_R350) && | ||
2203 | (stop_req > 0x15)) { | ||
2204 | stop_req -= 0x10; | ||
2205 | } | ||
2206 | grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); | ||
2207 | grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; | ||
2208 | grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | | ||
2209 | RADEON_GRPH_CRITICAL_AT_SOF | | ||
2210 | RADEON_GRPH_STOP_CNTL); | ||
2211 | |||
2212 | if ((rdev->family == CHIP_RS100) || | ||
2213 | (rdev->family == CHIP_RS200)) | ||
2214 | critical_point2 = 0; | ||
2215 | else { | ||
2216 | temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; | ||
2217 | temp_ff.full = rfixed_const(temp); | ||
2218 | temp_ff.full = rfixed_mul(mclk_ff, temp_ff); | ||
2219 | if (sclk_ff.full < temp_ff.full) | ||
2220 | temp_ff.full = sclk_ff.full; | ||
2221 | |||
2222 | read_return_rate.full = temp_ff.full; | ||
2223 | |||
2224 | if (mode1) { | ||
2225 | temp_ff.full = read_return_rate.full - disp_drain_rate.full; | ||
2226 | time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff); | ||
2227 | } else { | ||
2228 | time_disp1_drop_priority.full = 0; | ||
2229 | } | ||
2230 | crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; | ||
2231 | crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2); | ||
2232 | crit_point_ff.full += rfixed_const_half(0); | ||
2233 | |||
2234 | critical_point2 = rfixed_trunc(crit_point_ff); | ||
2235 | |||
2236 | if (rdev->disp_priority == 2) { | ||
2237 | critical_point2 = 0; | ||
2238 | } | ||
2239 | |||
2240 | if (max_stop_req - critical_point2 < 4) | ||
2241 | critical_point2 = 0; | ||
2242 | |||
2243 | } | ||
2244 | |||
2245 | if (critical_point2 == 0 && rdev->family == CHIP_R300) { | ||
2246 | /* some R300 cards have problem with this set to 0 */ | ||
2247 | critical_point2 = 0x10; | ||
2248 | } | ||
2249 | |||
2250 | WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | | ||
2251 | (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); | ||
2252 | |||
2253 | if ((rdev->family == CHIP_RS400) || | ||
2254 | (rdev->family == CHIP_RS480)) { | ||
2255 | #if 0 | ||
2256 | /* attempt to program RS400 disp2 regs correctly ??? */ | ||
2257 | temp = RREG32(RS400_DISP2_REQ_CNTL1); | ||
2258 | temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | | ||
2259 | RS400_DISP2_STOP_REQ_LEVEL_MASK); | ||
2260 | WREG32(RS400_DISP2_REQ_CNTL1, (temp | | ||
2261 | (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | | ||
2262 | (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); | ||
2263 | temp = RREG32(RS400_DISP2_REQ_CNTL2); | ||
2264 | temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | | ||
2265 | RS400_DISP2_CRITICAL_POINT_STOP_MASK); | ||
2266 | WREG32(RS400_DISP2_REQ_CNTL2, (temp | | ||
2267 | (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | | ||
2268 | (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); | ||
2269 | #endif | ||
2270 | WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); | ||
2271 | WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); | ||
2272 | WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); | ||
2273 | WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); | ||
2274 | } | ||
2275 | |||
2276 | DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n", | ||
2277 | (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); | ||
2278 | } | ||
2279 | } | ||