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