diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 859 |
1 files changed, 825 insertions, 34 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index c550932a108f..90ff8e0ac04e 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); |
@@ -251,6 +254,72 @@ void r100_mc_fini(struct radeon_device *rdev) | |||
251 | 254 | ||
252 | 255 | ||
253 | /* | 256 | /* |
257 | * Interrupts | ||
258 | */ | ||
259 | int r100_irq_set(struct radeon_device *rdev) | ||
260 | { | ||
261 | uint32_t tmp = 0; | ||
262 | |||
263 | if (rdev->irq.sw_int) { | ||
264 | tmp |= RADEON_SW_INT_ENABLE; | ||
265 | } | ||
266 | if (rdev->irq.crtc_vblank_int[0]) { | ||
267 | tmp |= RADEON_CRTC_VBLANK_MASK; | ||
268 | } | ||
269 | if (rdev->irq.crtc_vblank_int[1]) { | ||
270 | tmp |= RADEON_CRTC2_VBLANK_MASK; | ||
271 | } | ||
272 | WREG32(RADEON_GEN_INT_CNTL, tmp); | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static inline uint32_t r100_irq_ack(struct radeon_device *rdev) | ||
277 | { | ||
278 | uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); | ||
279 | uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT | | ||
280 | RADEON_CRTC2_VBLANK_STAT; | ||
281 | |||
282 | if (irqs) { | ||
283 | WREG32(RADEON_GEN_INT_STATUS, irqs); | ||
284 | } | ||
285 | return irqs & irq_mask; | ||
286 | } | ||
287 | |||
288 | int r100_irq_process(struct radeon_device *rdev) | ||
289 | { | ||
290 | uint32_t status; | ||
291 | |||
292 | status = r100_irq_ack(rdev); | ||
293 | if (!status) { | ||
294 | return IRQ_NONE; | ||
295 | } | ||
296 | while (status) { | ||
297 | /* SW interrupt */ | ||
298 | if (status & RADEON_SW_INT_TEST) { | ||
299 | radeon_fence_process(rdev); | ||
300 | } | ||
301 | /* Vertical blank interrupts */ | ||
302 | if (status & RADEON_CRTC_VBLANK_STAT) { | ||
303 | drm_handle_vblank(rdev->ddev, 0); | ||
304 | } | ||
305 | if (status & RADEON_CRTC2_VBLANK_STAT) { | ||
306 | drm_handle_vblank(rdev->ddev, 1); | ||
307 | } | ||
308 | status = r100_irq_ack(rdev); | ||
309 | } | ||
310 | return IRQ_HANDLED; | ||
311 | } | ||
312 | |||
313 | u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc) | ||
314 | { | ||
315 | if (crtc == 0) | ||
316 | return RREG32(RADEON_CRTC_CRNT_FRAME); | ||
317 | else | ||
318 | return RREG32(RADEON_CRTC2_CRNT_FRAME); | ||
319 | } | ||
320 | |||
321 | |||
322 | /* | ||
254 | * Fence emission | 323 | * Fence emission |
255 | */ | 324 | */ |
256 | void r100_fence_ring_emit(struct radeon_device *rdev, | 325 | void r100_fence_ring_emit(struct radeon_device *rdev, |
@@ -719,13 +788,14 @@ int r100_cs_packet_parse(struct radeon_cs_parser *p, | |||
719 | unsigned idx) | 788 | unsigned idx) |
720 | { | 789 | { |
721 | struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; | 790 | struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; |
722 | uint32_t header = ib_chunk->kdata[idx]; | 791 | uint32_t header; |
723 | 792 | ||
724 | if (idx >= ib_chunk->length_dw) { | 793 | if (idx >= ib_chunk->length_dw) { |
725 | DRM_ERROR("Can not parse packet at %d after CS end %d !\n", | 794 | DRM_ERROR("Can not parse packet at %d after CS end %d !\n", |
726 | idx, ib_chunk->length_dw); | 795 | idx, ib_chunk->length_dw); |
727 | return -EINVAL; | 796 | return -EINVAL; |
728 | } | 797 | } |
798 | header = ib_chunk->kdata[idx]; | ||
729 | pkt->idx = idx; | 799 | pkt->idx = idx; |
730 | pkt->type = CP_PACKET_GET_TYPE(header); | 800 | pkt->type = CP_PACKET_GET_TYPE(header); |
731 | pkt->count = CP_PACKET_GET_COUNT(header); | 801 | pkt->count = CP_PACKET_GET_COUNT(header); |
@@ -753,6 +823,102 @@ int r100_cs_packet_parse(struct radeon_cs_parser *p, | |||
753 | } | 823 | } |
754 | 824 | ||
755 | /** | 825 | /** |
826 | * r100_cs_packet_next_vline() - parse userspace VLINE packet | ||
827 | * @parser: parser structure holding parsing context. | ||
828 | * | ||
829 | * Userspace sends a special sequence for VLINE waits. | ||
830 | * PACKET0 - VLINE_START_END + value | ||
831 | * PACKET0 - WAIT_UNTIL +_value | ||
832 | * RELOC (P3) - crtc_id in reloc. | ||
833 | * | ||
834 | * This function parses this and relocates the VLINE START END | ||
835 | * and WAIT UNTIL packets to the correct crtc. | ||
836 | * It also detects a switched off crtc and nulls out the | ||
837 | * wait in that case. | ||
838 | */ | ||
839 | int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) | ||
840 | { | ||
841 | struct radeon_cs_chunk *ib_chunk; | ||
842 | struct drm_mode_object *obj; | ||
843 | struct drm_crtc *crtc; | ||
844 | struct radeon_crtc *radeon_crtc; | ||
845 | struct radeon_cs_packet p3reloc, waitreloc; | ||
846 | int crtc_id; | ||
847 | int r; | ||
848 | uint32_t header, h_idx, reg; | ||
849 | |||
850 | ib_chunk = &p->chunks[p->chunk_ib_idx]; | ||
851 | |||
852 | /* parse the wait until */ | ||
853 | r = r100_cs_packet_parse(p, &waitreloc, p->idx); | ||
854 | if (r) | ||
855 | return r; | ||
856 | |||
857 | /* check its a wait until and only 1 count */ | ||
858 | if (waitreloc.reg != RADEON_WAIT_UNTIL || | ||
859 | waitreloc.count != 0) { | ||
860 | DRM_ERROR("vline wait had illegal wait until segment\n"); | ||
861 | r = -EINVAL; | ||
862 | return r; | ||
863 | } | ||
864 | |||
865 | if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) { | ||
866 | DRM_ERROR("vline wait had illegal wait until\n"); | ||
867 | r = -EINVAL; | ||
868 | return r; | ||
869 | } | ||
870 | |||
871 | /* jump over the NOP */ | ||
872 | r = r100_cs_packet_parse(p, &p3reloc, p->idx); | ||
873 | if (r) | ||
874 | return r; | ||
875 | |||
876 | h_idx = p->idx - 2; | ||
877 | p->idx += waitreloc.count; | ||
878 | p->idx += p3reloc.count; | ||
879 | |||
880 | header = ib_chunk->kdata[h_idx]; | ||
881 | crtc_id = ib_chunk->kdata[h_idx + 5]; | ||
882 | reg = ib_chunk->kdata[h_idx] >> 2; | ||
883 | mutex_lock(&p->rdev->ddev->mode_config.mutex); | ||
884 | obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); | ||
885 | if (!obj) { | ||
886 | DRM_ERROR("cannot find crtc %d\n", crtc_id); | ||
887 | r = -EINVAL; | ||
888 | goto out; | ||
889 | } | ||
890 | crtc = obj_to_crtc(obj); | ||
891 | radeon_crtc = to_radeon_crtc(crtc); | ||
892 | crtc_id = radeon_crtc->crtc_id; | ||
893 | |||
894 | if (!crtc->enabled) { | ||
895 | /* if the CRTC isn't enabled - we need to nop out the wait until */ | ||
896 | ib_chunk->kdata[h_idx + 2] = PACKET2(0); | ||
897 | ib_chunk->kdata[h_idx + 3] = PACKET2(0); | ||
898 | } else if (crtc_id == 1) { | ||
899 | switch (reg) { | ||
900 | case AVIVO_D1MODE_VLINE_START_END: | ||
901 | header &= R300_CP_PACKET0_REG_MASK; | ||
902 | header |= AVIVO_D2MODE_VLINE_START_END >> 2; | ||
903 | break; | ||
904 | case RADEON_CRTC_GUI_TRIG_VLINE: | ||
905 | header &= R300_CP_PACKET0_REG_MASK; | ||
906 | header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2; | ||
907 | break; | ||
908 | default: | ||
909 | DRM_ERROR("unknown crtc reloc\n"); | ||
910 | r = -EINVAL; | ||
911 | goto out; | ||
912 | } | ||
913 | ib_chunk->kdata[h_idx] = header; | ||
914 | ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1; | ||
915 | } | ||
916 | out: | ||
917 | mutex_unlock(&p->rdev->ddev->mode_config.mutex); | ||
918 | return r; | ||
919 | } | ||
920 | |||
921 | /** | ||
756 | * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 | 922 | * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 |
757 | * @parser: parser structure holding parsing context. | 923 | * @parser: parser structure holding parsing context. |
758 | * @data: pointer to relocation data | 924 | * @data: pointer to relocation data |
@@ -814,6 +980,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
814 | unsigned idx; | 980 | unsigned idx; |
815 | bool onereg; | 981 | bool onereg; |
816 | int r; | 982 | int r; |
983 | u32 tile_flags = 0; | ||
817 | 984 | ||
818 | ib = p->ib->ptr; | 985 | ib = p->ib->ptr; |
819 | ib_chunk = &p->chunks[p->chunk_ib_idx]; | 986 | ib_chunk = &p->chunks[p->chunk_ib_idx]; |
@@ -825,6 +992,15 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
825 | } | 992 | } |
826 | for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { | 993 | for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { |
827 | switch (reg) { | 994 | switch (reg) { |
995 | case RADEON_CRTC_GUI_TRIG_VLINE: | ||
996 | r = r100_cs_packet_parse_vline(p); | ||
997 | if (r) { | ||
998 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
999 | idx, reg); | ||
1000 | r100_cs_dump_packet(p, pkt); | ||
1001 | return r; | ||
1002 | } | ||
1003 | break; | ||
828 | /* FIXME: only allow PACKET3 blit? easier to check for out of | 1004 | /* FIXME: only allow PACKET3 blit? easier to check for out of |
829 | * range access */ | 1005 | * range access */ |
830 | case RADEON_DST_PITCH_OFFSET: | 1006 | case RADEON_DST_PITCH_OFFSET: |
@@ -838,7 +1014,20 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
838 | } | 1014 | } |
839 | tmp = ib_chunk->kdata[idx] & 0x003fffff; | 1015 | tmp = ib_chunk->kdata[idx] & 0x003fffff; |
840 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); | 1016 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); |
841 | ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp; | 1017 | |
1018 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
1019 | tile_flags |= RADEON_DST_TILE_MACRO; | ||
1020 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { | ||
1021 | if (reg == RADEON_SRC_PITCH_OFFSET) { | ||
1022 | DRM_ERROR("Cannot src blit from microtiled surface\n"); | ||
1023 | r100_cs_dump_packet(p, pkt); | ||
1024 | return -EINVAL; | ||
1025 | } | ||
1026 | tile_flags |= RADEON_DST_TILE_MICRO; | ||
1027 | } | ||
1028 | |||
1029 | tmp |= tile_flags; | ||
1030 | ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp; | ||
842 | break; | 1031 | break; |
843 | case RADEON_RB3D_DEPTHOFFSET: | 1032 | case RADEON_RB3D_DEPTHOFFSET: |
844 | case RADEON_RB3D_COLOROFFSET: | 1033 | case RADEON_RB3D_COLOROFFSET: |
@@ -869,6 +1058,11 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
869 | case R300_TX_OFFSET_0+52: | 1058 | case R300_TX_OFFSET_0+52: |
870 | case R300_TX_OFFSET_0+56: | 1059 | case R300_TX_OFFSET_0+56: |
871 | case R300_TX_OFFSET_0+60: | 1060 | case R300_TX_OFFSET_0+60: |
1061 | /* rn50 has no 3D engine so fail on any 3d setup */ | ||
1062 | if (ASIC_IS_RN50(p->rdev)) { | ||
1063 | DRM_ERROR("attempt to use RN50 3D engine failed\n"); | ||
1064 | return -EINVAL; | ||
1065 | } | ||
872 | r = r100_cs_packet_next_reloc(p, &reloc); | 1066 | r = r100_cs_packet_next_reloc(p, &reloc); |
873 | if (r) { | 1067 | if (r) { |
874 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | 1068 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
@@ -878,6 +1072,25 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
878 | } | 1072 | } |
879 | ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); | 1073 | ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
880 | break; | 1074 | break; |
1075 | case R300_RB3D_COLORPITCH0: | ||
1076 | case RADEON_RB3D_COLORPITCH: | ||
1077 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
1078 | if (r) { | ||
1079 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
1080 | idx, reg); | ||
1081 | r100_cs_dump_packet(p, pkt); | ||
1082 | return r; | ||
1083 | } | ||
1084 | |||
1085 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
1086 | tile_flags |= RADEON_COLOR_TILE_ENABLE; | ||
1087 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) | ||
1088 | tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; | ||
1089 | |||
1090 | tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); | ||
1091 | tmp |= tile_flags; | ||
1092 | ib[idx] = tmp; | ||
1093 | break; | ||
881 | default: | 1094 | default: |
882 | /* FIXME: we don't want to allow anyothers packet */ | 1095 | /* FIXME: we don't want to allow anyothers packet */ |
883 | break; | 1096 | break; |
@@ -1256,29 +1469,100 @@ static void r100_vram_get_type(struct radeon_device *rdev) | |||
1256 | } | 1469 | } |
1257 | } | 1470 | } |
1258 | 1471 | ||
1259 | void r100_vram_info(struct radeon_device *rdev) | 1472 | static u32 r100_get_accessible_vram(struct radeon_device *rdev) |
1260 | { | 1473 | { |
1261 | r100_vram_get_type(rdev); | 1474 | u32 aper_size; |
1475 | u8 byte; | ||
1476 | |||
1477 | aper_size = RREG32(RADEON_CONFIG_APER_SIZE); | ||
1478 | |||
1479 | /* Set HDP_APER_CNTL only on cards that are known not to be broken, | ||
1480 | * that is has the 2nd generation multifunction PCI interface | ||
1481 | */ | ||
1482 | if (rdev->family == CHIP_RV280 || | ||
1483 | rdev->family >= CHIP_RV350) { | ||
1484 | WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, | ||
1485 | ~RADEON_HDP_APER_CNTL); | ||
1486 | DRM_INFO("Generation 2 PCI interface, using max accessible memory\n"); | ||
1487 | return aper_size * 2; | ||
1488 | } | ||
1489 | |||
1490 | /* Older cards have all sorts of funny issues to deal with. First | ||
1491 | * check if it's a multifunction card by reading the PCI config | ||
1492 | * header type... Limit those to one aperture size | ||
1493 | */ | ||
1494 | pci_read_config_byte(rdev->pdev, 0xe, &byte); | ||
1495 | if (byte & 0x80) { | ||
1496 | DRM_INFO("Generation 1 PCI interface in multifunction mode\n"); | ||
1497 | DRM_INFO("Limiting VRAM to one aperture\n"); | ||
1498 | return aper_size; | ||
1499 | } | ||
1500 | |||
1501 | /* Single function older card. We read HDP_APER_CNTL to see how the BIOS | ||
1502 | * have set it up. We don't write this as it's broken on some ASICs but | ||
1503 | * we expect the BIOS to have done the right thing (might be too optimistic...) | ||
1504 | */ | ||
1505 | if (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) | ||
1506 | return aper_size * 2; | ||
1507 | return aper_size; | ||
1508 | } | ||
1509 | |||
1510 | void r100_vram_init_sizes(struct radeon_device *rdev) | ||
1511 | { | ||
1512 | u64 config_aper_size; | ||
1513 | u32 accessible; | ||
1514 | |||
1515 | config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); | ||
1262 | 1516 | ||
1263 | if (rdev->flags & RADEON_IS_IGP) { | 1517 | if (rdev->flags & RADEON_IS_IGP) { |
1264 | uint32_t tom; | 1518 | uint32_t tom; |
1265 | /* read NB_TOM to get the amount of ram stolen for the GPU */ | 1519 | /* read NB_TOM to get the amount of ram stolen for the GPU */ |
1266 | tom = RREG32(RADEON_NB_TOM); | 1520 | tom = RREG32(RADEON_NB_TOM); |
1267 | rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); | 1521 | rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); |
1268 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); | 1522 | /* for IGPs we need to keep VRAM where it was put by the BIOS */ |
1523 | rdev->mc.vram_location = (tom & 0xffff) << 16; | ||
1524 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); | ||
1525 | rdev->mc.mc_vram_size = rdev->mc.real_vram_size; | ||
1269 | } else { | 1526 | } else { |
1270 | rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); | 1527 | rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); |
1271 | /* Some production boards of m6 will report 0 | 1528 | /* Some production boards of m6 will report 0 |
1272 | * if it's 8 MB | 1529 | * if it's 8 MB |
1273 | */ | 1530 | */ |
1274 | if (rdev->mc.vram_size == 0) { | 1531 | if (rdev->mc.real_vram_size == 0) { |
1275 | rdev->mc.vram_size = 8192 * 1024; | 1532 | rdev->mc.real_vram_size = 8192 * 1024; |
1276 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); | 1533 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); |
1277 | } | 1534 | } |
1535 | /* let driver place VRAM */ | ||
1536 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
1537 | /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - | ||
1538 | * Novell bug 204882 + along with lots of ubuntu ones */ | ||
1539 | if (config_aper_size > rdev->mc.real_vram_size) | ||
1540 | rdev->mc.mc_vram_size = config_aper_size; | ||
1541 | else | ||
1542 | rdev->mc.mc_vram_size = rdev->mc.real_vram_size; | ||
1278 | } | 1543 | } |
1279 | 1544 | ||
1545 | /* work out accessible VRAM */ | ||
1546 | accessible = r100_get_accessible_vram(rdev); | ||
1547 | |||
1280 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); | 1548 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); |
1281 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); | 1549 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); |
1550 | |||
1551 | if (accessible > rdev->mc.aper_size) | ||
1552 | accessible = rdev->mc.aper_size; | ||
1553 | |||
1554 | if (rdev->mc.mc_vram_size > rdev->mc.aper_size) | ||
1555 | rdev->mc.mc_vram_size = rdev->mc.aper_size; | ||
1556 | |||
1557 | if (rdev->mc.real_vram_size > rdev->mc.aper_size) | ||
1558 | rdev->mc.real_vram_size = rdev->mc.aper_size; | ||
1559 | } | ||
1560 | |||
1561 | void r100_vram_info(struct radeon_device *rdev) | ||
1562 | { | ||
1563 | r100_vram_get_type(rdev); | ||
1564 | |||
1565 | r100_vram_init_sizes(rdev); | ||
1282 | } | 1566 | } |
1283 | 1567 | ||
1284 | 1568 | ||
@@ -1338,26 +1622,6 @@ void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | |||
1338 | r100_pll_errata_after_data(rdev); | 1622 | r100_pll_errata_after_data(rdev); |
1339 | } | 1623 | } |
1340 | 1624 | ||
1341 | uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) | ||
1342 | { | ||
1343 | if (reg < 0x10000) | ||
1344 | return readl(((void __iomem *)rdev->rmmio) + reg); | ||
1345 | else { | ||
1346 | writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); | ||
1347 | return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); | ||
1348 | } | ||
1349 | } | ||
1350 | |||
1351 | void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | ||
1352 | { | ||
1353 | if (reg < 0x10000) | ||
1354 | writel(v, ((void __iomem *)rdev->rmmio) + reg); | ||
1355 | else { | ||
1356 | writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); | ||
1357 | writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); | ||
1358 | } | ||
1359 | } | ||
1360 | |||
1361 | int r100_init(struct radeon_device *rdev) | 1625 | int r100_init(struct radeon_device *rdev) |
1362 | { | 1626 | { |
1363 | return 0; | 1627 | return 0; |
@@ -1533,3 +1797,530 @@ int r100_debugfs_mc_info_init(struct radeon_device *rdev) | |||
1533 | return 0; | 1797 | return 0; |
1534 | #endif | 1798 | #endif |
1535 | } | 1799 | } |
1800 | |||
1801 | int r100_set_surface_reg(struct radeon_device *rdev, int reg, | ||
1802 | uint32_t tiling_flags, uint32_t pitch, | ||
1803 | uint32_t offset, uint32_t obj_size) | ||
1804 | { | ||
1805 | int surf_index = reg * 16; | ||
1806 | int flags = 0; | ||
1807 | |||
1808 | /* r100/r200 divide by 16 */ | ||
1809 | if (rdev->family < CHIP_R300) | ||
1810 | flags = pitch / 16; | ||
1811 | else | ||
1812 | flags = pitch / 8; | ||
1813 | |||
1814 | if (rdev->family <= CHIP_RS200) { | ||
1815 | if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) | ||
1816 | == (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) | ||
1817 | flags |= RADEON_SURF_TILE_COLOR_BOTH; | ||
1818 | if (tiling_flags & RADEON_TILING_MACRO) | ||
1819 | flags |= RADEON_SURF_TILE_COLOR_MACRO; | ||
1820 | } else if (rdev->family <= CHIP_RV280) { | ||
1821 | if (tiling_flags & (RADEON_TILING_MACRO)) | ||
1822 | flags |= R200_SURF_TILE_COLOR_MACRO; | ||
1823 | if (tiling_flags & RADEON_TILING_MICRO) | ||
1824 | flags |= R200_SURF_TILE_COLOR_MICRO; | ||
1825 | } else { | ||
1826 | if (tiling_flags & RADEON_TILING_MACRO) | ||
1827 | flags |= R300_SURF_TILE_MACRO; | ||
1828 | if (tiling_flags & RADEON_TILING_MICRO) | ||
1829 | flags |= R300_SURF_TILE_MICRO; | ||
1830 | } | ||
1831 | |||
1832 | DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1); | ||
1833 | WREG32(RADEON_SURFACE0_INFO + surf_index, flags); | ||
1834 | WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset); | ||
1835 | WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1); | ||
1836 | return 0; | ||
1837 | } | ||
1838 | |||
1839 | void r100_clear_surface_reg(struct radeon_device *rdev, int reg) | ||
1840 | { | ||
1841 | int surf_index = reg * 16; | ||
1842 | WREG32(RADEON_SURFACE0_INFO + surf_index, 0); | ||
1843 | } | ||
1844 | |||
1845 | void r100_bandwidth_update(struct radeon_device *rdev) | ||
1846 | { | ||
1847 | fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; | ||
1848 | fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; | ||
1849 | fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; | ||
1850 | uint32_t temp, data, mem_trcd, mem_trp, mem_tras; | ||
1851 | fixed20_12 memtcas_ff[8] = { | ||
1852 | fixed_init(1), | ||
1853 | fixed_init(2), | ||
1854 | fixed_init(3), | ||
1855 | fixed_init(0), | ||
1856 | fixed_init_half(1), | ||
1857 | fixed_init_half(2), | ||
1858 | fixed_init(0), | ||
1859 | }; | ||
1860 | fixed20_12 memtcas_rs480_ff[8] = { | ||
1861 | fixed_init(0), | ||
1862 | fixed_init(1), | ||
1863 | fixed_init(2), | ||
1864 | fixed_init(3), | ||
1865 | fixed_init(0), | ||
1866 | fixed_init_half(1), | ||
1867 | fixed_init_half(2), | ||
1868 | fixed_init_half(3), | ||
1869 | }; | ||
1870 | fixed20_12 memtcas2_ff[8] = { | ||
1871 | fixed_init(0), | ||
1872 | fixed_init(1), | ||
1873 | fixed_init(2), | ||
1874 | fixed_init(3), | ||
1875 | fixed_init(4), | ||
1876 | fixed_init(5), | ||
1877 | fixed_init(6), | ||
1878 | fixed_init(7), | ||
1879 | }; | ||
1880 | fixed20_12 memtrbs[8] = { | ||
1881 | fixed_init(1), | ||
1882 | fixed_init_half(1), | ||
1883 | fixed_init(2), | ||
1884 | fixed_init_half(2), | ||
1885 | fixed_init(3), | ||
1886 | fixed_init_half(3), | ||
1887 | fixed_init(4), | ||
1888 | fixed_init_half(4) | ||
1889 | }; | ||
1890 | fixed20_12 memtrbs_r4xx[8] = { | ||
1891 | fixed_init(4), | ||
1892 | fixed_init(5), | ||
1893 | fixed_init(6), | ||
1894 | fixed_init(7), | ||
1895 | fixed_init(8), | ||
1896 | fixed_init(9), | ||
1897 | fixed_init(10), | ||
1898 | fixed_init(11) | ||
1899 | }; | ||
1900 | fixed20_12 min_mem_eff; | ||
1901 | fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; | ||
1902 | fixed20_12 cur_latency_mclk, cur_latency_sclk; | ||
1903 | fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, | ||
1904 | disp_drain_rate2, read_return_rate; | ||
1905 | fixed20_12 time_disp1_drop_priority; | ||
1906 | int c; | ||
1907 | int cur_size = 16; /* in octawords */ | ||
1908 | int critical_point = 0, critical_point2; | ||
1909 | /* uint32_t read_return_rate, time_disp1_drop_priority; */ | ||
1910 | int stop_req, max_stop_req; | ||
1911 | struct drm_display_mode *mode1 = NULL; | ||
1912 | struct drm_display_mode *mode2 = NULL; | ||
1913 | uint32_t pixel_bytes1 = 0; | ||
1914 | uint32_t pixel_bytes2 = 0; | ||
1915 | |||
1916 | if (rdev->mode_info.crtcs[0]->base.enabled) { | ||
1917 | mode1 = &rdev->mode_info.crtcs[0]->base.mode; | ||
1918 | pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; | ||
1919 | } | ||
1920 | if (rdev->mode_info.crtcs[1]->base.enabled) { | ||
1921 | mode2 = &rdev->mode_info.crtcs[1]->base.mode; | ||
1922 | pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; | ||
1923 | } | ||
1924 | |||
1925 | min_mem_eff.full = rfixed_const_8(0); | ||
1926 | /* get modes */ | ||
1927 | if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { | ||
1928 | uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); | ||
1929 | mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); | ||
1930 | mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); | ||
1931 | /* check crtc enables */ | ||
1932 | if (mode2) | ||
1933 | mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); | ||
1934 | if (mode1) | ||
1935 | mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); | ||
1936 | WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); | ||
1937 | } | ||
1938 | |||
1939 | /* | ||
1940 | * determine is there is enough bw for current mode | ||
1941 | */ | ||
1942 | mclk_ff.full = rfixed_const(rdev->clock.default_mclk); | ||
1943 | temp_ff.full = rfixed_const(100); | ||
1944 | mclk_ff.full = rfixed_div(mclk_ff, temp_ff); | ||
1945 | sclk_ff.full = rfixed_const(rdev->clock.default_sclk); | ||
1946 | sclk_ff.full = rfixed_div(sclk_ff, temp_ff); | ||
1947 | |||
1948 | temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); | ||
1949 | temp_ff.full = rfixed_const(temp); | ||
1950 | mem_bw.full = rfixed_mul(mclk_ff, temp_ff); | ||
1951 | |||
1952 | pix_clk.full = 0; | ||
1953 | pix_clk2.full = 0; | ||
1954 | peak_disp_bw.full = 0; | ||
1955 | if (mode1) { | ||
1956 | temp_ff.full = rfixed_const(1000); | ||
1957 | pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ | ||
1958 | pix_clk.full = rfixed_div(pix_clk, temp_ff); | ||
1959 | temp_ff.full = rfixed_const(pixel_bytes1); | ||
1960 | peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); | ||
1961 | } | ||
1962 | if (mode2) { | ||
1963 | temp_ff.full = rfixed_const(1000); | ||
1964 | pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ | ||
1965 | pix_clk2.full = rfixed_div(pix_clk2, temp_ff); | ||
1966 | temp_ff.full = rfixed_const(pixel_bytes2); | ||
1967 | peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); | ||
1968 | } | ||
1969 | |||
1970 | mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); | ||
1971 | if (peak_disp_bw.full >= mem_bw.full) { | ||
1972 | DRM_ERROR("You may not have enough display bandwidth for current mode\n" | ||
1973 | "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); | ||
1974 | } | ||
1975 | |||
1976 | /* Get values from the EXT_MEM_CNTL register...converting its contents. */ | ||
1977 | temp = RREG32(RADEON_MEM_TIMING_CNTL); | ||
1978 | if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ | ||
1979 | mem_trcd = ((temp >> 2) & 0x3) + 1; | ||
1980 | mem_trp = ((temp & 0x3)) + 1; | ||
1981 | mem_tras = ((temp & 0x70) >> 4) + 1; | ||
1982 | } else if (rdev->family == CHIP_R300 || | ||
1983 | rdev->family == CHIP_R350) { /* r300, r350 */ | ||
1984 | mem_trcd = (temp & 0x7) + 1; | ||
1985 | mem_trp = ((temp >> 8) & 0x7) + 1; | ||
1986 | mem_tras = ((temp >> 11) & 0xf) + 4; | ||
1987 | } else if (rdev->family == CHIP_RV350 || | ||
1988 | rdev->family <= CHIP_RV380) { | ||
1989 | /* rv3x0 */ | ||
1990 | mem_trcd = (temp & 0x7) + 3; | ||
1991 | mem_trp = ((temp >> 8) & 0x7) + 3; | ||
1992 | mem_tras = ((temp >> 11) & 0xf) + 6; | ||
1993 | } else if (rdev->family == CHIP_R420 || | ||
1994 | rdev->family == CHIP_R423 || | ||
1995 | rdev->family == CHIP_RV410) { | ||
1996 | /* r4xx */ | ||
1997 | mem_trcd = (temp & 0xf) + 3; | ||
1998 | if (mem_trcd > 15) | ||
1999 | mem_trcd = 15; | ||
2000 | mem_trp = ((temp >> 8) & 0xf) + 3; | ||
2001 | if (mem_trp > 15) | ||
2002 | mem_trp = 15; | ||
2003 | mem_tras = ((temp >> 12) & 0x1f) + 6; | ||
2004 | if (mem_tras > 31) | ||
2005 | mem_tras = 31; | ||
2006 | } else { /* RV200, R200 */ | ||
2007 | mem_trcd = (temp & 0x7) + 1; | ||
2008 | mem_trp = ((temp >> 8) & 0x7) + 1; | ||
2009 | mem_tras = ((temp >> 12) & 0xf) + 4; | ||
2010 | } | ||
2011 | /* convert to FF */ | ||
2012 | trcd_ff.full = rfixed_const(mem_trcd); | ||
2013 | trp_ff.full = rfixed_const(mem_trp); | ||
2014 | tras_ff.full = rfixed_const(mem_tras); | ||
2015 | |||
2016 | /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ | ||
2017 | temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); | ||
2018 | data = (temp & (7 << 20)) >> 20; | ||
2019 | if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { | ||
2020 | if (rdev->family == CHIP_RS480) /* don't think rs400 */ | ||
2021 | tcas_ff = memtcas_rs480_ff[data]; | ||
2022 | else | ||
2023 | tcas_ff = memtcas_ff[data]; | ||
2024 | } else | ||
2025 | tcas_ff = memtcas2_ff[data]; | ||
2026 | |||
2027 | if (rdev->family == CHIP_RS400 || | ||
2028 | rdev->family == CHIP_RS480) { | ||
2029 | /* extra cas latency stored in bits 23-25 0-4 clocks */ | ||
2030 | data = (temp >> 23) & 0x7; | ||
2031 | if (data < 5) | ||
2032 | tcas_ff.full += rfixed_const(data); | ||
2033 | } | ||
2034 | |||
2035 | if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { | ||
2036 | /* on the R300, Tcas is included in Trbs. | ||
2037 | */ | ||
2038 | temp = RREG32(RADEON_MEM_CNTL); | ||
2039 | data = (R300_MEM_NUM_CHANNELS_MASK & temp); | ||
2040 | if (data == 1) { | ||
2041 | if (R300_MEM_USE_CD_CH_ONLY & temp) { | ||
2042 | temp = RREG32(R300_MC_IND_INDEX); | ||
2043 | temp &= ~R300_MC_IND_ADDR_MASK; | ||
2044 | temp |= R300_MC_READ_CNTL_CD_mcind; | ||
2045 | WREG32(R300_MC_IND_INDEX, temp); | ||
2046 | temp = RREG32(R300_MC_IND_DATA); | ||
2047 | data = (R300_MEM_RBS_POSITION_C_MASK & temp); | ||
2048 | } else { | ||
2049 | temp = RREG32(R300_MC_READ_CNTL_AB); | ||
2050 | data = (R300_MEM_RBS_POSITION_A_MASK & temp); | ||
2051 | } | ||
2052 | } else { | ||
2053 | temp = RREG32(R300_MC_READ_CNTL_AB); | ||
2054 | data = (R300_MEM_RBS_POSITION_A_MASK & temp); | ||
2055 | } | ||
2056 | if (rdev->family == CHIP_RV410 || | ||
2057 | rdev->family == CHIP_R420 || | ||
2058 | rdev->family == CHIP_R423) | ||
2059 | trbs_ff = memtrbs_r4xx[data]; | ||
2060 | else | ||
2061 | trbs_ff = memtrbs[data]; | ||
2062 | tcas_ff.full += trbs_ff.full; | ||
2063 | } | ||
2064 | |||
2065 | sclk_eff_ff.full = sclk_ff.full; | ||
2066 | |||
2067 | if (rdev->flags & RADEON_IS_AGP) { | ||
2068 | fixed20_12 agpmode_ff; | ||
2069 | agpmode_ff.full = rfixed_const(radeon_agpmode); | ||
2070 | temp_ff.full = rfixed_const_666(16); | ||
2071 | sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff); | ||
2072 | } | ||
2073 | /* TODO PCIE lanes may affect this - agpmode == 16?? */ | ||
2074 | |||
2075 | if (ASIC_IS_R300(rdev)) { | ||
2076 | sclk_delay_ff.full = rfixed_const(250); | ||
2077 | } else { | ||
2078 | if ((rdev->family == CHIP_RV100) || | ||
2079 | rdev->flags & RADEON_IS_IGP) { | ||
2080 | if (rdev->mc.vram_is_ddr) | ||
2081 | sclk_delay_ff.full = rfixed_const(41); | ||
2082 | else | ||
2083 | sclk_delay_ff.full = rfixed_const(33); | ||
2084 | } else { | ||
2085 | if (rdev->mc.vram_width == 128) | ||
2086 | sclk_delay_ff.full = rfixed_const(57); | ||
2087 | else | ||
2088 | sclk_delay_ff.full = rfixed_const(41); | ||
2089 | } | ||
2090 | } | ||
2091 | |||
2092 | mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff); | ||
2093 | |||
2094 | if (rdev->mc.vram_is_ddr) { | ||
2095 | if (rdev->mc.vram_width == 32) { | ||
2096 | k1.full = rfixed_const(40); | ||
2097 | c = 3; | ||
2098 | } else { | ||
2099 | k1.full = rfixed_const(20); | ||
2100 | c = 1; | ||
2101 | } | ||
2102 | } else { | ||
2103 | k1.full = rfixed_const(40); | ||
2104 | c = 3; | ||
2105 | } | ||
2106 | |||
2107 | temp_ff.full = rfixed_const(2); | ||
2108 | mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff); | ||
2109 | temp_ff.full = rfixed_const(c); | ||
2110 | mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff); | ||
2111 | temp_ff.full = rfixed_const(4); | ||
2112 | mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff); | ||
2113 | mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff); | ||
2114 | mc_latency_mclk.full += k1.full; | ||
2115 | |||
2116 | mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff); | ||
2117 | mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff); | ||
2118 | |||
2119 | /* | ||
2120 | HW cursor time assuming worst case of full size colour cursor. | ||
2121 | */ | ||
2122 | temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); | ||
2123 | temp_ff.full += trcd_ff.full; | ||
2124 | if (temp_ff.full < tras_ff.full) | ||
2125 | temp_ff.full = tras_ff.full; | ||
2126 | cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff); | ||
2127 | |||
2128 | temp_ff.full = rfixed_const(cur_size); | ||
2129 | cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff); | ||
2130 | /* | ||
2131 | Find the total latency for the display data. | ||
2132 | */ | ||
2133 | disp_latency_overhead.full = rfixed_const(80); | ||
2134 | disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff); | ||
2135 | mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; | ||
2136 | mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; | ||
2137 | |||
2138 | if (mc_latency_mclk.full > mc_latency_sclk.full) | ||
2139 | disp_latency.full = mc_latency_mclk.full; | ||
2140 | else | ||
2141 | disp_latency.full = mc_latency_sclk.full; | ||
2142 | |||
2143 | /* setup Max GRPH_STOP_REQ default value */ | ||
2144 | if (ASIC_IS_RV100(rdev)) | ||
2145 | max_stop_req = 0x5c; | ||
2146 | else | ||
2147 | max_stop_req = 0x7c; | ||
2148 | |||
2149 | if (mode1) { | ||
2150 | /* CRTC1 | ||
2151 | Set GRPH_BUFFER_CNTL register using h/w defined optimal values. | ||
2152 | GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] | ||
2153 | */ | ||
2154 | stop_req = mode1->hdisplay * pixel_bytes1 / 16; | ||
2155 | |||
2156 | if (stop_req > max_stop_req) | ||
2157 | stop_req = max_stop_req; | ||
2158 | |||
2159 | /* | ||
2160 | Find the drain rate of the display buffer. | ||
2161 | */ | ||
2162 | temp_ff.full = rfixed_const((16/pixel_bytes1)); | ||
2163 | disp_drain_rate.full = rfixed_div(pix_clk, temp_ff); | ||
2164 | |||
2165 | /* | ||
2166 | Find the critical point of the display buffer. | ||
2167 | */ | ||
2168 | crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency); | ||
2169 | crit_point_ff.full += rfixed_const_half(0); | ||
2170 | |||
2171 | critical_point = rfixed_trunc(crit_point_ff); | ||
2172 | |||
2173 | if (rdev->disp_priority == 2) { | ||
2174 | critical_point = 0; | ||
2175 | } | ||
2176 | |||
2177 | /* | ||
2178 | The critical point should never be above max_stop_req-4. Setting | ||
2179 | GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. | ||
2180 | */ | ||
2181 | if (max_stop_req - critical_point < 4) | ||
2182 | critical_point = 0; | ||
2183 | |||
2184 | if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { | ||
2185 | /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ | ||
2186 | critical_point = 0x10; | ||
2187 | } | ||
2188 | |||
2189 | temp = RREG32(RADEON_GRPH_BUFFER_CNTL); | ||
2190 | temp &= ~(RADEON_GRPH_STOP_REQ_MASK); | ||
2191 | temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); | ||
2192 | temp &= ~(RADEON_GRPH_START_REQ_MASK); | ||
2193 | if ((rdev->family == CHIP_R350) && | ||
2194 | (stop_req > 0x15)) { | ||
2195 | stop_req -= 0x10; | ||
2196 | } | ||
2197 | temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); | ||
2198 | temp |= RADEON_GRPH_BUFFER_SIZE; | ||
2199 | temp &= ~(RADEON_GRPH_CRITICAL_CNTL | | ||
2200 | RADEON_GRPH_CRITICAL_AT_SOF | | ||
2201 | RADEON_GRPH_STOP_CNTL); | ||
2202 | /* | ||
2203 | Write the result into the register. | ||
2204 | */ | ||
2205 | WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | | ||
2206 | (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); | ||
2207 | |||
2208 | #if 0 | ||
2209 | if ((rdev->family == CHIP_RS400) || | ||
2210 | (rdev->family == CHIP_RS480)) { | ||
2211 | /* attempt to program RS400 disp regs correctly ??? */ | ||
2212 | temp = RREG32(RS400_DISP1_REG_CNTL); | ||
2213 | temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | | ||
2214 | RS400_DISP1_STOP_REQ_LEVEL_MASK); | ||
2215 | WREG32(RS400_DISP1_REQ_CNTL1, (temp | | ||
2216 | (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | | ||
2217 | (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); | ||
2218 | temp = RREG32(RS400_DMIF_MEM_CNTL1); | ||
2219 | temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | | ||
2220 | RS400_DISP1_CRITICAL_POINT_STOP_MASK); | ||
2221 | WREG32(RS400_DMIF_MEM_CNTL1, (temp | | ||
2222 | (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | | ||
2223 | (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); | ||
2224 | } | ||
2225 | #endif | ||
2226 | |||
2227 | DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n", | ||
2228 | /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ | ||
2229 | (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); | ||
2230 | } | ||
2231 | |||
2232 | if (mode2) { | ||
2233 | u32 grph2_cntl; | ||
2234 | stop_req = mode2->hdisplay * pixel_bytes2 / 16; | ||
2235 | |||
2236 | if (stop_req > max_stop_req) | ||
2237 | stop_req = max_stop_req; | ||
2238 | |||
2239 | /* | ||
2240 | Find the drain rate of the display buffer. | ||
2241 | */ | ||
2242 | temp_ff.full = rfixed_const((16/pixel_bytes2)); | ||
2243 | disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff); | ||
2244 | |||
2245 | grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); | ||
2246 | grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); | ||
2247 | grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); | ||
2248 | grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); | ||
2249 | if ((rdev->family == CHIP_R350) && | ||
2250 | (stop_req > 0x15)) { | ||
2251 | stop_req -= 0x10; | ||
2252 | } | ||
2253 | grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); | ||
2254 | grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; | ||
2255 | grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | | ||
2256 | RADEON_GRPH_CRITICAL_AT_SOF | | ||
2257 | RADEON_GRPH_STOP_CNTL); | ||
2258 | |||
2259 | if ((rdev->family == CHIP_RS100) || | ||
2260 | (rdev->family == CHIP_RS200)) | ||
2261 | critical_point2 = 0; | ||
2262 | else { | ||
2263 | temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; | ||
2264 | temp_ff.full = rfixed_const(temp); | ||
2265 | temp_ff.full = rfixed_mul(mclk_ff, temp_ff); | ||
2266 | if (sclk_ff.full < temp_ff.full) | ||
2267 | temp_ff.full = sclk_ff.full; | ||
2268 | |||
2269 | read_return_rate.full = temp_ff.full; | ||
2270 | |||
2271 | if (mode1) { | ||
2272 | temp_ff.full = read_return_rate.full - disp_drain_rate.full; | ||
2273 | time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff); | ||
2274 | } else { | ||
2275 | time_disp1_drop_priority.full = 0; | ||
2276 | } | ||
2277 | crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; | ||
2278 | crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2); | ||
2279 | crit_point_ff.full += rfixed_const_half(0); | ||
2280 | |||
2281 | critical_point2 = rfixed_trunc(crit_point_ff); | ||
2282 | |||
2283 | if (rdev->disp_priority == 2) { | ||
2284 | critical_point2 = 0; | ||
2285 | } | ||
2286 | |||
2287 | if (max_stop_req - critical_point2 < 4) | ||
2288 | critical_point2 = 0; | ||
2289 | |||
2290 | } | ||
2291 | |||
2292 | if (critical_point2 == 0 && rdev->family == CHIP_R300) { | ||
2293 | /* some R300 cards have problem with this set to 0 */ | ||
2294 | critical_point2 = 0x10; | ||
2295 | } | ||
2296 | |||
2297 | WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | | ||
2298 | (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); | ||
2299 | |||
2300 | if ((rdev->family == CHIP_RS400) || | ||
2301 | (rdev->family == CHIP_RS480)) { | ||
2302 | #if 0 | ||
2303 | /* attempt to program RS400 disp2 regs correctly ??? */ | ||
2304 | temp = RREG32(RS400_DISP2_REQ_CNTL1); | ||
2305 | temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | | ||
2306 | RS400_DISP2_STOP_REQ_LEVEL_MASK); | ||
2307 | WREG32(RS400_DISP2_REQ_CNTL1, (temp | | ||
2308 | (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | | ||
2309 | (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); | ||
2310 | temp = RREG32(RS400_DISP2_REQ_CNTL2); | ||
2311 | temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | | ||
2312 | RS400_DISP2_CRITICAL_POINT_STOP_MASK); | ||
2313 | WREG32(RS400_DISP2_REQ_CNTL2, (temp | | ||
2314 | (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | | ||
2315 | (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); | ||
2316 | #endif | ||
2317 | WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); | ||
2318 | WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); | ||
2319 | WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); | ||
2320 | WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); | ||
2321 | } | ||
2322 | |||
2323 | DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n", | ||
2324 | (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); | ||
2325 | } | ||
2326 | } | ||