diff options
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 79 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r300.c | 51 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r300_reg.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_fb.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_gem.c | 41 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_kms.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_object.c | 130 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_ttm.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo_vm.c | 3 | ||||
-rw-r--r-- | include/drm/radeon_drm.h | 23 | ||||
-rw-r--r-- | include/drm/ttm/ttm_bo_driver.h | 15 |
17 files changed, 427 insertions, 19 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index e64a199b5ee1..eac26cdb5dae 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -327,7 +327,7 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
327 | struct drm_gem_object *obj; | 327 | struct drm_gem_object *obj; |
328 | struct drm_radeon_gem_object *obj_priv; | 328 | struct drm_radeon_gem_object *obj_priv; |
329 | uint64_t fb_location; | 329 | uint64_t fb_location; |
330 | uint32_t fb_format, fb_pitch_pixels; | 330 | uint32_t fb_format, fb_pitch_pixels, tiling_flags; |
331 | 331 | ||
332 | if (!crtc->fb) | 332 | if (!crtc->fb) |
333 | return -EINVAL; | 333 | return -EINVAL; |
@@ -364,7 +364,14 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
364 | return -EINVAL; | 364 | return -EINVAL; |
365 | } | 365 | } |
366 | 366 | ||
367 | /* TODO tiling */ | 367 | radeon_object_get_tiling_flags(obj->driver_private, |
368 | &tiling_flags, NULL); | ||
369 | if (tiling_flags & RADEON_TILING_MACRO) | ||
370 | fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE; | ||
371 | |||
372 | if (tiling_flags & RADEON_TILING_MICRO) | ||
373 | fb_format |= AVIVO_D1GRPH_TILED; | ||
374 | |||
368 | if (radeon_crtc->crtc_id == 0) | 375 | if (radeon_crtc->crtc_id == 0) |
369 | WREG32(AVIVO_D1VGA_CONTROL, 0); | 376 | WREG32(AVIVO_D1VGA_CONTROL, 0); |
370 | else | 377 | else |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 0d05909f03f6..69bd7cb59972 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -909,6 +909,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
909 | unsigned idx; | 909 | unsigned idx; |
910 | bool onereg; | 910 | bool onereg; |
911 | int r; | 911 | int r; |
912 | u32 tile_flags = 0; | ||
912 | 913 | ||
913 | ib = p->ib->ptr; | 914 | ib = p->ib->ptr; |
914 | ib_chunk = &p->chunks[p->chunk_ib_idx]; | 915 | ib_chunk = &p->chunks[p->chunk_ib_idx]; |
@@ -942,7 +943,20 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
942 | } | 943 | } |
943 | tmp = ib_chunk->kdata[idx] & 0x003fffff; | 944 | tmp = ib_chunk->kdata[idx] & 0x003fffff; |
944 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); | 945 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); |
945 | ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp; | 946 | |
947 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
948 | tile_flags |= RADEON_DST_TILE_MACRO; | ||
949 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { | ||
950 | if (reg == RADEON_SRC_PITCH_OFFSET) { | ||
951 | DRM_ERROR("Cannot src blit from microtiled surface\n"); | ||
952 | r100_cs_dump_packet(p, pkt); | ||
953 | return -EINVAL; | ||
954 | } | ||
955 | tile_flags |= RADEON_DST_TILE_MICRO; | ||
956 | } | ||
957 | |||
958 | tmp |= tile_flags; | ||
959 | ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp; | ||
946 | break; | 960 | break; |
947 | case RADEON_RB3D_DEPTHOFFSET: | 961 | case RADEON_RB3D_DEPTHOFFSET: |
948 | case RADEON_RB3D_COLOROFFSET: | 962 | case RADEON_RB3D_COLOROFFSET: |
@@ -987,6 +1001,25 @@ static int r100_packet0_check(struct radeon_cs_parser *p, | |||
987 | } | 1001 | } |
988 | ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); | 1002 | ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
989 | break; | 1003 | break; |
1004 | case R300_RB3D_COLORPITCH0: | ||
1005 | case RADEON_RB3D_COLORPITCH: | ||
1006 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
1007 | if (r) { | ||
1008 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
1009 | idx, reg); | ||
1010 | r100_cs_dump_packet(p, pkt); | ||
1011 | return r; | ||
1012 | } | ||
1013 | |||
1014 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
1015 | tile_flags |= RADEON_COLOR_TILE_ENABLE; | ||
1016 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) | ||
1017 | tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; | ||
1018 | |||
1019 | tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); | ||
1020 | tmp |= tile_flags; | ||
1021 | ib[idx] = tmp; | ||
1022 | break; | ||
990 | default: | 1023 | default: |
991 | /* FIXME: we don't want to allow anyothers packet */ | 1024 | /* FIXME: we don't want to allow anyothers packet */ |
992 | break; | 1025 | break; |
@@ -1707,3 +1740,47 @@ int r100_debugfs_mc_info_init(struct radeon_device *rdev) | |||
1707 | return 0; | 1740 | return 0; |
1708 | #endif | 1741 | #endif |
1709 | } | 1742 | } |
1743 | |||
1744 | int r100_set_surface_reg(struct radeon_device *rdev, int reg, | ||
1745 | uint32_t tiling_flags, uint32_t pitch, | ||
1746 | uint32_t offset, uint32_t obj_size) | ||
1747 | { | ||
1748 | int surf_index = reg * 16; | ||
1749 | int flags = 0; | ||
1750 | |||
1751 | /* r100/r200 divide by 16 */ | ||
1752 | if (rdev->family < CHIP_R300) | ||
1753 | flags = pitch / 16; | ||
1754 | else | ||
1755 | flags = pitch / 8; | ||
1756 | |||
1757 | if (rdev->family <= CHIP_RS200) { | ||
1758 | if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) | ||
1759 | == (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) | ||
1760 | flags |= RADEON_SURF_TILE_COLOR_BOTH; | ||
1761 | if (tiling_flags & RADEON_TILING_MACRO) | ||
1762 | flags |= RADEON_SURF_TILE_COLOR_MACRO; | ||
1763 | } else if (rdev->family <= CHIP_RV280) { | ||
1764 | if (tiling_flags & (RADEON_TILING_MACRO)) | ||
1765 | flags |= R200_SURF_TILE_COLOR_MACRO; | ||
1766 | if (tiling_flags & RADEON_TILING_MICRO) | ||
1767 | flags |= R200_SURF_TILE_COLOR_MICRO; | ||
1768 | } else { | ||
1769 | if (tiling_flags & RADEON_TILING_MACRO) | ||
1770 | flags |= R300_SURF_TILE_MACRO; | ||
1771 | if (tiling_flags & RADEON_TILING_MICRO) | ||
1772 | flags |= R300_SURF_TILE_MICRO; | ||
1773 | } | ||
1774 | |||
1775 | DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1); | ||
1776 | WREG32(RADEON_SURFACE0_INFO + surf_index, flags); | ||
1777 | WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset); | ||
1778 | WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1); | ||
1779 | return 0; | ||
1780 | } | ||
1781 | |||
1782 | void r100_clear_surface_reg(struct radeon_device *rdev, int reg) | ||
1783 | { | ||
1784 | int surf_index = reg * 16; | ||
1785 | WREG32(RADEON_SURFACE0_INFO + surf_index, 0); | ||
1786 | } | ||
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 0e0e094da503..28e5777658be 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "drm.h" | 30 | #include "drm.h" |
31 | #include "radeon_reg.h" | 31 | #include "radeon_reg.h" |
32 | #include "radeon.h" | 32 | #include "radeon.h" |
33 | #include "radeon_drm.h" | ||
33 | 34 | ||
34 | /* r300,r350,rv350,rv370,rv380 depends on : */ | 35 | /* r300,r350,rv350,rv370,rv380 depends on : */ |
35 | void r100_hdp_reset(struct radeon_device *rdev); | 36 | void r100_hdp_reset(struct radeon_device *rdev); |
@@ -1023,7 +1024,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, | |||
1023 | struct radeon_cs_reloc *reloc; | 1024 | struct radeon_cs_reloc *reloc; |
1024 | struct r300_cs_track *track; | 1025 | struct r300_cs_track *track; |
1025 | volatile uint32_t *ib; | 1026 | volatile uint32_t *ib; |
1026 | uint32_t tmp; | 1027 | uint32_t tmp, tile_flags = 0; |
1027 | unsigned i; | 1028 | unsigned i; |
1028 | int r; | 1029 | int r; |
1029 | 1030 | ||
@@ -1052,7 +1053,19 @@ static int r300_packet0_check(struct radeon_cs_parser *p, | |||
1052 | } | 1053 | } |
1053 | tmp = ib_chunk->kdata[idx] & 0x003fffff; | 1054 | tmp = ib_chunk->kdata[idx] & 0x003fffff; |
1054 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); | 1055 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); |
1055 | ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp; | 1056 | |
1057 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
1058 | tile_flags |= RADEON_DST_TILE_MACRO; | ||
1059 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { | ||
1060 | if (reg == RADEON_SRC_PITCH_OFFSET) { | ||
1061 | DRM_ERROR("Cannot src blit from microtiled surface\n"); | ||
1062 | r100_cs_dump_packet(p, pkt); | ||
1063 | return -EINVAL; | ||
1064 | } | ||
1065 | tile_flags |= RADEON_DST_TILE_MICRO; | ||
1066 | } | ||
1067 | tmp |= tile_flags; | ||
1068 | ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp; | ||
1056 | break; | 1069 | break; |
1057 | case R300_RB3D_COLOROFFSET0: | 1070 | case R300_RB3D_COLOROFFSET0: |
1058 | case R300_RB3D_COLOROFFSET1: | 1071 | case R300_RB3D_COLOROFFSET1: |
@@ -1141,6 +1154,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p, | |||
1141 | /* RB3D_COLORPITCH1 */ | 1154 | /* RB3D_COLORPITCH1 */ |
1142 | /* RB3D_COLORPITCH2 */ | 1155 | /* RB3D_COLORPITCH2 */ |
1143 | /* RB3D_COLORPITCH3 */ | 1156 | /* RB3D_COLORPITCH3 */ |
1157 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
1158 | if (r) { | ||
1159 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
1160 | idx, reg); | ||
1161 | r100_cs_dump_packet(p, pkt); | ||
1162 | return r; | ||
1163 | } | ||
1164 | |||
1165 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
1166 | tile_flags |= R300_COLOR_TILE_ENABLE; | ||
1167 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) | ||
1168 | tile_flags |= R300_COLOR_MICROTILE_ENABLE; | ||
1169 | |||
1170 | tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); | ||
1171 | tmp |= tile_flags; | ||
1172 | ib[idx] = tmp; | ||
1173 | |||
1144 | i = (reg - 0x4E38) >> 2; | 1174 | i = (reg - 0x4E38) >> 2; |
1145 | track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE; | 1175 | track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE; |
1146 | switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) { | 1176 | switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) { |
@@ -1196,6 +1226,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p, | |||
1196 | break; | 1226 | break; |
1197 | case 0x4F24: | 1227 | case 0x4F24: |
1198 | /* ZB_DEPTHPITCH */ | 1228 | /* ZB_DEPTHPITCH */ |
1229 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
1230 | if (r) { | ||
1231 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
1232 | idx, reg); | ||
1233 | r100_cs_dump_packet(p, pkt); | ||
1234 | return r; | ||
1235 | } | ||
1236 | |||
1237 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
1238 | tile_flags |= R300_DEPTHMACROTILE_ENABLE; | ||
1239 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) | ||
1240 | tile_flags |= R300_DEPTHMICROTILE_TILED;; | ||
1241 | |||
1242 | tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); | ||
1243 | tmp |= tile_flags; | ||
1244 | ib[idx] = tmp; | ||
1245 | |||
1199 | track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC; | 1246 | track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC; |
1200 | break; | 1247 | break; |
1201 | case 0x4104: | 1248 | case 0x4104: |
diff --git a/drivers/gpu/drm/radeon/r300_reg.h b/drivers/gpu/drm/radeon/r300_reg.h index 70f48609515e..4b7afef35a65 100644 --- a/drivers/gpu/drm/radeon/r300_reg.h +++ b/drivers/gpu/drm/radeon/r300_reg.h | |||
@@ -27,7 +27,9 @@ | |||
27 | #ifndef _R300_REG_H_ | 27 | #ifndef _R300_REG_H_ |
28 | #define _R300_REG_H_ | 28 | #define _R300_REG_H_ |
29 | 29 | ||
30 | 30 | #define R300_SURF_TILE_MACRO (1<<16) | |
31 | #define R300_SURF_TILE_MICRO (2<<16) | ||
32 | #define R300_SURF_TILE_BOTH (3<<16) | ||
31 | 33 | ||
32 | 34 | ||
33 | #define R300_MC_INIT_MISC_LAT_TIMER 0x180 | 35 | #define R300_MC_INIT_MISC_LAT_TIMER 0x180 |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 7f007185e7f7..af12a2fe3221 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -201,6 +201,14 @@ int radeon_fence_wait_last(struct radeon_device *rdev); | |||
201 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); | 201 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); |
202 | void radeon_fence_unref(struct radeon_fence **fence); | 202 | void radeon_fence_unref(struct radeon_fence **fence); |
203 | 203 | ||
204 | /* | ||
205 | * Tiling registers | ||
206 | */ | ||
207 | struct radeon_surface_reg { | ||
208 | struct radeon_object *robj; | ||
209 | }; | ||
210 | |||
211 | #define RADEON_GEM_MAX_SURFACES 8 | ||
204 | 212 | ||
205 | /* | 213 | /* |
206 | * Radeon buffer. | 214 | * Radeon buffer. |
@@ -213,6 +221,7 @@ struct radeon_object_list { | |||
213 | uint64_t gpu_offset; | 221 | uint64_t gpu_offset; |
214 | unsigned rdomain; | 222 | unsigned rdomain; |
215 | unsigned wdomain; | 223 | unsigned wdomain; |
224 | uint32_t tiling_flags; | ||
216 | }; | 225 | }; |
217 | 226 | ||
218 | int radeon_object_init(struct radeon_device *rdev); | 227 | int radeon_object_init(struct radeon_device *rdev); |
@@ -242,8 +251,15 @@ void radeon_object_list_clean(struct list_head *head); | |||
242 | int radeon_object_fbdev_mmap(struct radeon_object *robj, | 251 | int radeon_object_fbdev_mmap(struct radeon_object *robj, |
243 | struct vm_area_struct *vma); | 252 | struct vm_area_struct *vma); |
244 | unsigned long radeon_object_size(struct radeon_object *robj); | 253 | unsigned long radeon_object_size(struct radeon_object *robj); |
245 | 254 | void radeon_object_clear_surface_reg(struct radeon_object *robj); | |
246 | 255 | int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved, | |
256 | bool force_drop); | ||
257 | void radeon_object_set_tiling_flags(struct radeon_object *robj, | ||
258 | uint32_t tiling_flags, uint32_t pitch); | ||
259 | void radeon_object_get_tiling_flags(struct radeon_object *robj, uint32_t *tiling_flags, uint32_t *pitch); | ||
260 | void radeon_bo_move_notify(struct ttm_buffer_object *bo, | ||
261 | struct ttm_mem_reg *mem); | ||
262 | void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); | ||
247 | /* | 263 | /* |
248 | * GEM objects. | 264 | * GEM objects. |
249 | */ | 265 | */ |
@@ -535,6 +551,11 @@ struct radeon_asic { | |||
535 | void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock); | 551 | void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock); |
536 | void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); | 552 | void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); |
537 | void (*set_clock_gating)(struct radeon_device *rdev, int enable); | 553 | void (*set_clock_gating)(struct radeon_device *rdev, int enable); |
554 | |||
555 | int (*set_surface_reg)(struct radeon_device *rdev, int reg, | ||
556 | uint32_t tiling_flags, uint32_t pitch, | ||
557 | uint32_t offset, uint32_t obj_size); | ||
558 | int (*clear_surface_reg)(struct radeon_device *rdev, int reg); | ||
538 | }; | 559 | }; |
539 | 560 | ||
540 | union radeon_asic_config { | 561 | union radeon_asic_config { |
@@ -568,6 +589,10 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
568 | int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, | 589 | int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, |
569 | struct drm_file *filp); | 590 | struct drm_file *filp); |
570 | int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); | 591 | int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); |
592 | int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, | ||
593 | struct drm_file *filp); | ||
594 | int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, | ||
595 | struct drm_file *filp); | ||
571 | 596 | ||
572 | 597 | ||
573 | /* | 598 | /* |
@@ -627,6 +652,7 @@ struct radeon_device { | |||
627 | bool shutdown; | 652 | bool shutdown; |
628 | bool suspend; | 653 | bool suspend; |
629 | bool need_dma32; | 654 | bool need_dma32; |
655 | struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES]; | ||
630 | }; | 656 | }; |
631 | 657 | ||
632 | int radeon_device_init(struct radeon_device *rdev, | 658 | int radeon_device_init(struct radeon_device *rdev, |
@@ -801,5 +827,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) | |||
801 | #define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e)) | 827 | #define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e)) |
802 | #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l)) | 828 | #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l)) |
803 | #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e)) | 829 | #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e)) |
830 | #define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s))) | ||
831 | #define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r))) | ||
804 | 832 | ||
805 | #endif | 833 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index e2e567395df8..dd903d329406 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
@@ -71,6 +71,10 @@ int r100_copy_blit(struct radeon_device *rdev, | |||
71 | uint64_t dst_offset, | 71 | uint64_t dst_offset, |
72 | unsigned num_pages, | 72 | unsigned num_pages, |
73 | struct radeon_fence *fence); | 73 | struct radeon_fence *fence); |
74 | int r100_set_surface_reg(struct radeon_device *rdev, int reg, | ||
75 | uint32_t tiling_flags, uint32_t pitch, | ||
76 | uint32_t offset, uint32_t obj_size); | ||
77 | int r100_clear_surface_reg(struct radeon_device *rdev, int reg); | ||
74 | 78 | ||
75 | static struct radeon_asic r100_asic = { | 79 | static struct radeon_asic r100_asic = { |
76 | .init = &r100_init, | 80 | .init = &r100_init, |
@@ -100,6 +104,8 @@ static struct radeon_asic r100_asic = { | |||
100 | .set_memory_clock = NULL, | 104 | .set_memory_clock = NULL, |
101 | .set_pcie_lanes = NULL, | 105 | .set_pcie_lanes = NULL, |
102 | .set_clock_gating = &radeon_legacy_set_clock_gating, | 106 | .set_clock_gating = &radeon_legacy_set_clock_gating, |
107 | .set_surface_reg = r100_set_surface_reg, | ||
108 | .clear_surface_reg = r100_clear_surface_reg, | ||
103 | }; | 109 | }; |
104 | 110 | ||
105 | 111 | ||
@@ -128,6 +134,7 @@ int r300_copy_dma(struct radeon_device *rdev, | |||
128 | uint64_t dst_offset, | 134 | uint64_t dst_offset, |
129 | unsigned num_pages, | 135 | unsigned num_pages, |
130 | struct radeon_fence *fence); | 136 | struct radeon_fence *fence); |
137 | |||
131 | static struct radeon_asic r300_asic = { | 138 | static struct radeon_asic r300_asic = { |
132 | .init = &r300_init, | 139 | .init = &r300_init, |
133 | .errata = &r300_errata, | 140 | .errata = &r300_errata, |
@@ -156,6 +163,8 @@ static struct radeon_asic r300_asic = { | |||
156 | .set_memory_clock = NULL, | 163 | .set_memory_clock = NULL, |
157 | .set_pcie_lanes = &rv370_set_pcie_lanes, | 164 | .set_pcie_lanes = &rv370_set_pcie_lanes, |
158 | .set_clock_gating = &radeon_legacy_set_clock_gating, | 165 | .set_clock_gating = &radeon_legacy_set_clock_gating, |
166 | .set_surface_reg = r100_set_surface_reg, | ||
167 | .clear_surface_reg = r100_clear_surface_reg, | ||
159 | }; | 168 | }; |
160 | 169 | ||
161 | /* | 170 | /* |
@@ -193,6 +202,8 @@ static struct radeon_asic r420_asic = { | |||
193 | .set_memory_clock = &radeon_atom_set_memory_clock, | 202 | .set_memory_clock = &radeon_atom_set_memory_clock, |
194 | .set_pcie_lanes = &rv370_set_pcie_lanes, | 203 | .set_pcie_lanes = &rv370_set_pcie_lanes, |
195 | .set_clock_gating = &radeon_atom_set_clock_gating, | 204 | .set_clock_gating = &radeon_atom_set_clock_gating, |
205 | .set_surface_reg = r100_set_surface_reg, | ||
206 | .clear_surface_reg = r100_clear_surface_reg, | ||
196 | }; | 207 | }; |
197 | 208 | ||
198 | 209 | ||
@@ -237,6 +248,8 @@ static struct radeon_asic rs400_asic = { | |||
237 | .set_memory_clock = NULL, | 248 | .set_memory_clock = NULL, |
238 | .set_pcie_lanes = NULL, | 249 | .set_pcie_lanes = NULL, |
239 | .set_clock_gating = &radeon_legacy_set_clock_gating, | 250 | .set_clock_gating = &radeon_legacy_set_clock_gating, |
251 | .set_surface_reg = r100_set_surface_reg, | ||
252 | .clear_surface_reg = r100_clear_surface_reg, | ||
240 | }; | 253 | }; |
241 | 254 | ||
242 | 255 | ||
@@ -322,6 +335,8 @@ static struct radeon_asic rs690_asic = { | |||
322 | .set_memory_clock = &radeon_atom_set_memory_clock, | 335 | .set_memory_clock = &radeon_atom_set_memory_clock, |
323 | .set_pcie_lanes = NULL, | 336 | .set_pcie_lanes = NULL, |
324 | .set_clock_gating = &radeon_atom_set_clock_gating, | 337 | .set_clock_gating = &radeon_atom_set_clock_gating, |
338 | .set_surface_reg = r100_set_surface_reg, | ||
339 | .clear_surface_reg = r100_clear_surface_reg, | ||
325 | }; | 340 | }; |
326 | 341 | ||
327 | 342 | ||
@@ -367,6 +382,8 @@ static struct radeon_asic rv515_asic = { | |||
367 | .set_memory_clock = &radeon_atom_set_memory_clock, | 382 | .set_memory_clock = &radeon_atom_set_memory_clock, |
368 | .set_pcie_lanes = &rv370_set_pcie_lanes, | 383 | .set_pcie_lanes = &rv370_set_pcie_lanes, |
369 | .set_clock_gating = &radeon_atom_set_clock_gating, | 384 | .set_clock_gating = &radeon_atom_set_clock_gating, |
385 | .set_surface_reg = r100_set_surface_reg, | ||
386 | .clear_surface_reg = r100_clear_surface_reg, | ||
370 | }; | 387 | }; |
371 | 388 | ||
372 | 389 | ||
@@ -405,6 +422,8 @@ static struct radeon_asic r520_asic = { | |||
405 | .set_memory_clock = &radeon_atom_set_memory_clock, | 422 | .set_memory_clock = &radeon_atom_set_memory_clock, |
406 | .set_pcie_lanes = &rv370_set_pcie_lanes, | 423 | .set_pcie_lanes = &rv370_set_pcie_lanes, |
407 | .set_clock_gating = &radeon_atom_set_clock_gating, | 424 | .set_clock_gating = &radeon_atom_set_clock_gating, |
425 | .set_surface_reg = r100_set_surface_reg, | ||
426 | .clear_surface_reg = r100_clear_surface_reg, | ||
408 | }; | 427 | }; |
409 | 428 | ||
410 | /* | 429 | /* |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index cdef6eb01baf..f23083bbba3f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -48,6 +48,8 @@ static void radeon_surface_init(struct radeon_device *rdev) | |||
48 | i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), | 48 | i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), |
49 | 0); | 49 | 0); |
50 | } | 50 | } |
51 | /* enable surfaces */ | ||
52 | WREG32(RADEON_SURFACE_CNTL, 0); | ||
51 | } | 53 | } |
52 | } | 54 | } |
53 | 55 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 260870a29d83..36d2f5588f20 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
@@ -471,10 +471,10 @@ static struct notifier_block paniced = { | |||
471 | .notifier_call = radeonfb_panic, | 471 | .notifier_call = radeonfb_panic, |
472 | }; | 472 | }; |
473 | 473 | ||
474 | static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp) | 474 | static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled) |
475 | { | 475 | { |
476 | int aligned = width; | 476 | int aligned = width; |
477 | int align_large = (ASIC_IS_AVIVO(rdev)); | 477 | int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; |
478 | int pitch_mask = 0; | 478 | int pitch_mask = 0; |
479 | 479 | ||
480 | switch (bpp / 8) { | 480 | switch (bpp / 8) { |
@@ -512,12 +512,13 @@ int radeonfb_create(struct radeon_device *rdev, | |||
512 | u64 fb_gpuaddr; | 512 | u64 fb_gpuaddr; |
513 | void *fbptr = NULL; | 513 | void *fbptr = NULL; |
514 | unsigned long tmp; | 514 | unsigned long tmp; |
515 | bool fb_tiled = false; /* useful for testing */ | ||
515 | 516 | ||
516 | mode_cmd.width = surface_width; | 517 | mode_cmd.width = surface_width; |
517 | mode_cmd.height = surface_height; | 518 | mode_cmd.height = surface_height; |
518 | mode_cmd.bpp = 32; | 519 | mode_cmd.bpp = 32; |
519 | /* need to align pitch with crtc limits */ | 520 | /* need to align pitch with crtc limits */ |
520 | mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp) * ((mode_cmd.bpp + 1) / 8); | 521 | mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8); |
521 | mode_cmd.depth = 24; | 522 | mode_cmd.depth = 24; |
522 | 523 | ||
523 | size = mode_cmd.pitch * mode_cmd.height; | 524 | size = mode_cmd.pitch * mode_cmd.height; |
@@ -535,6 +536,8 @@ int radeonfb_create(struct radeon_device *rdev, | |||
535 | } | 536 | } |
536 | robj = gobj->driver_private; | 537 | robj = gobj->driver_private; |
537 | 538 | ||
539 | if (fb_tiled) | ||
540 | radeon_object_set_tiling_flags(robj, RADEON_TILING_MACRO|RADEON_TILING_SURFACE, mode_cmd.pitch); | ||
538 | mutex_lock(&rdev->ddev->struct_mutex); | 541 | mutex_lock(&rdev->ddev->struct_mutex); |
539 | fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj); | 542 | fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj); |
540 | if (fb == NULL) { | 543 | if (fb == NULL) { |
@@ -563,6 +566,9 @@ int radeonfb_create(struct radeon_device *rdev, | |||
563 | } | 566 | } |
564 | rfbdev = info->par; | 567 | rfbdev = info->par; |
565 | 568 | ||
569 | if (fb_tiled) | ||
570 | radeon_object_check_tiling(robj, 0, 0); | ||
571 | |||
566 | ret = radeon_object_kmap(robj, &fbptr); | 572 | ret = radeon_object_kmap(robj, &fbptr); |
567 | if (ret) { | 573 | if (ret) { |
568 | goto out_unref; | 574 | goto out_unref; |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index eb516034235d..12542087b298 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
@@ -285,3 +285,44 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, | |||
285 | mutex_unlock(&dev->struct_mutex); | 285 | mutex_unlock(&dev->struct_mutex); |
286 | return r; | 286 | return r; |
287 | } | 287 | } |
288 | |||
289 | int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, | ||
290 | struct drm_file *filp) | ||
291 | { | ||
292 | struct drm_radeon_gem_set_tiling *args = data; | ||
293 | struct drm_gem_object *gobj; | ||
294 | struct radeon_object *robj; | ||
295 | int r = 0; | ||
296 | |||
297 | DRM_DEBUG("%d \n", args->handle); | ||
298 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | ||
299 | if (gobj == NULL) | ||
300 | return -EINVAL; | ||
301 | robj = gobj->driver_private; | ||
302 | radeon_object_set_tiling_flags(robj, args->tiling_flags, args->pitch); | ||
303 | mutex_lock(&dev->struct_mutex); | ||
304 | drm_gem_object_unreference(gobj); | ||
305 | mutex_unlock(&dev->struct_mutex); | ||
306 | return r; | ||
307 | } | ||
308 | |||
309 | int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, | ||
310 | struct drm_file *filp) | ||
311 | { | ||
312 | struct drm_radeon_gem_get_tiling *args = data; | ||
313 | struct drm_gem_object *gobj; | ||
314 | struct radeon_object *robj; | ||
315 | int r = 0; | ||
316 | |||
317 | DRM_DEBUG("\n"); | ||
318 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | ||
319 | if (gobj == NULL) | ||
320 | return -EINVAL; | ||
321 | robj = gobj->driver_private; | ||
322 | radeon_object_get_tiling_flags(robj, &args->tiling_flags, | ||
323 | &args->pitch); | ||
324 | mutex_lock(&dev->struct_mutex); | ||
325 | drm_gem_object_unreference(gobj); | ||
326 | mutex_unlock(&dev->struct_mutex); | ||
327 | return r; | ||
328 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 4612a7c146d1..937a2f1cdb46 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
@@ -291,5 +291,7 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = { | |||
291 | DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH), | 291 | DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH), |
292 | DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH), | 292 | DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH), |
293 | DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH), | 293 | DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH), |
294 | DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH), | ||
295 | DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH), | ||
294 | }; | 296 | }; |
295 | int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms); | 297 | int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms); |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 14c1a5107fc9..0613790e2a5b 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c | |||
@@ -235,6 +235,7 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
235 | uint64_t base; | 235 | uint64_t base; |
236 | uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0; | 236 | uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0; |
237 | uint32_t crtc_pitch, pitch_pixels; | 237 | uint32_t crtc_pitch, pitch_pixels; |
238 | uint32_t tiling_flags; | ||
238 | 239 | ||
239 | DRM_DEBUG("\n"); | 240 | DRM_DEBUG("\n"); |
240 | 241 | ||
@@ -258,8 +259,12 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
258 | (crtc->fb->bits_per_pixel * 8)); | 259 | (crtc->fb->bits_per_pixel * 8)); |
259 | crtc_pitch |= crtc_pitch << 16; | 260 | crtc_pitch |= crtc_pitch << 16; |
260 | 261 | ||
261 | /* TODO tiling */ | 262 | radeon_object_get_tiling_flags(obj->driver_private, |
262 | if (0) { | 263 | &tiling_flags, NULL); |
264 | if (tiling_flags & RADEON_TILING_MICRO) | ||
265 | DRM_ERROR("trying to scanout microtiled buffer\n"); | ||
266 | |||
267 | if (tiling_flags & RADEON_TILING_MACRO) { | ||
263 | if (ASIC_IS_R300(rdev)) | 268 | if (ASIC_IS_R300(rdev)) |
264 | crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | | 269 | crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | |
265 | R300_CRTC_MICRO_TILE_BUFFER_DIS | | 270 | R300_CRTC_MICRO_TILE_BUFFER_DIS | |
@@ -275,15 +280,13 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
275 | crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; | 280 | crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; |
276 | } | 281 | } |
277 | 282 | ||
278 | 283 | if (tiling_flags & RADEON_TILING_MACRO) { | |
279 | /* TODO more tiling */ | ||
280 | if (0) { | ||
281 | if (ASIC_IS_R300(rdev)) { | 284 | if (ASIC_IS_R300(rdev)) { |
282 | crtc_tile_x0_y0 = x | (y << 16); | 285 | crtc_tile_x0_y0 = x | (y << 16); |
283 | base &= ~0x7ff; | 286 | base &= ~0x7ff; |
284 | } else { | 287 | } else { |
285 | int byteshift = crtc->fb->bits_per_pixel >> 4; | 288 | int byteshift = crtc->fb->bits_per_pixel >> 4; |
286 | int tile_addr = (((y >> 3) * crtc->fb->width + x) >> (8 - byteshift)) << 11; | 289 | int tile_addr = (((y >> 3) * pitch_pixels + x) >> (8 - byteshift)) << 11; |
287 | base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); | 290 | base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); |
288 | crtc_offset_cntl |= (y % 16); | 291 | crtc_offset_cntl |= (y % 16); |
289 | } | 292 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index bac0d06c52ac..d5b1fd562d88 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
@@ -44,6 +44,9 @@ struct radeon_object { | |||
44 | uint64_t gpu_addr; | 44 | uint64_t gpu_addr; |
45 | void *kptr; | 45 | void *kptr; |
46 | bool is_iomem; | 46 | bool is_iomem; |
47 | uint32_t tiling_flags; | ||
48 | uint32_t pitch; | ||
49 | int surface_reg; | ||
47 | }; | 50 | }; |
48 | 51 | ||
49 | int radeon_ttm_init(struct radeon_device *rdev); | 52 | int radeon_ttm_init(struct radeon_device *rdev); |
@@ -70,6 +73,7 @@ static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj) | |||
70 | 73 | ||
71 | robj = container_of(tobj, struct radeon_object, tobj); | 74 | robj = container_of(tobj, struct radeon_object, tobj); |
72 | list_del_init(&robj->list); | 75 | list_del_init(&robj->list); |
76 | radeon_object_clear_surface_reg(robj); | ||
73 | kfree(robj); | 77 | kfree(robj); |
74 | } | 78 | } |
75 | 79 | ||
@@ -141,6 +145,7 @@ int radeon_object_create(struct radeon_device *rdev, | |||
141 | } | 145 | } |
142 | robj->rdev = rdev; | 146 | robj->rdev = rdev; |
143 | robj->gobj = gobj; | 147 | robj->gobj = gobj; |
148 | robj->surface_reg = -1; | ||
144 | INIT_LIST_HEAD(&robj->list); | 149 | INIT_LIST_HEAD(&robj->list); |
145 | 150 | ||
146 | flags = radeon_object_flags_from_domain(domain); | 151 | flags = radeon_object_flags_from_domain(domain); |
@@ -435,6 +440,7 @@ int radeon_object_list_validate(struct list_head *head, void *fence) | |||
435 | radeon_object_gpu_addr(robj); | 440 | radeon_object_gpu_addr(robj); |
436 | } | 441 | } |
437 | lobj->gpu_offset = robj->gpu_addr; | 442 | lobj->gpu_offset = robj->gpu_addr; |
443 | lobj->tiling_flags = robj->tiling_flags; | ||
438 | if (fence) { | 444 | if (fence) { |
439 | old_fence = (struct radeon_fence *)robj->tobj.sync_obj; | 445 | old_fence = (struct radeon_fence *)robj->tobj.sync_obj; |
440 | robj->tobj.sync_obj = radeon_fence_ref(fence); | 446 | robj->tobj.sync_obj = radeon_fence_ref(fence); |
@@ -479,3 +485,127 @@ unsigned long radeon_object_size(struct radeon_object *robj) | |||
479 | { | 485 | { |
480 | return robj->tobj.num_pages << PAGE_SHIFT; | 486 | return robj->tobj.num_pages << PAGE_SHIFT; |
481 | } | 487 | } |
488 | |||
489 | int radeon_object_get_surface_reg(struct radeon_object *robj) | ||
490 | { | ||
491 | struct radeon_device *rdev = robj->rdev; | ||
492 | struct radeon_surface_reg *reg; | ||
493 | struct radeon_object *old_object; | ||
494 | int steal; | ||
495 | int i; | ||
496 | |||
497 | if (!robj->tiling_flags) | ||
498 | return 0; | ||
499 | |||
500 | if (robj->surface_reg >= 0) { | ||
501 | reg = &rdev->surface_regs[robj->surface_reg]; | ||
502 | i = robj->surface_reg; | ||
503 | goto out; | ||
504 | } | ||
505 | |||
506 | steal = -1; | ||
507 | for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) { | ||
508 | |||
509 | reg = &rdev->surface_regs[i]; | ||
510 | if (!reg->robj) | ||
511 | break; | ||
512 | |||
513 | old_object = reg->robj; | ||
514 | if (old_object->pin_count == 0) | ||
515 | steal = i; | ||
516 | } | ||
517 | |||
518 | /* if we are all out */ | ||
519 | if (i == RADEON_GEM_MAX_SURFACES) { | ||
520 | if (steal == -1) | ||
521 | return -ENOMEM; | ||
522 | /* find someone with a surface reg and nuke their BO */ | ||
523 | reg = &rdev->surface_regs[steal]; | ||
524 | old_object = reg->robj; | ||
525 | /* blow away the mapping */ | ||
526 | DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object); | ||
527 | ttm_bo_unmap_virtual(&old_object->tobj); | ||
528 | old_object->surface_reg = -1; | ||
529 | i = steal; | ||
530 | } | ||
531 | |||
532 | robj->surface_reg = i; | ||
533 | reg->robj = robj; | ||
534 | |||
535 | out: | ||
536 | radeon_set_surface_reg(rdev, i, robj->tiling_flags, robj->pitch, | ||
537 | robj->tobj.mem.mm_node->start << PAGE_SHIFT, | ||
538 | robj->tobj.num_pages << PAGE_SHIFT); | ||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | void radeon_object_clear_surface_reg(struct radeon_object *robj) | ||
543 | { | ||
544 | struct radeon_device *rdev = robj->rdev; | ||
545 | struct radeon_surface_reg *reg; | ||
546 | |||
547 | if (robj->surface_reg == -1) | ||
548 | return; | ||
549 | |||
550 | reg = &rdev->surface_regs[robj->surface_reg]; | ||
551 | radeon_clear_surface_reg(rdev, robj->surface_reg); | ||
552 | |||
553 | reg->robj = NULL; | ||
554 | robj->surface_reg = -1; | ||
555 | } | ||
556 | |||
557 | void radeon_object_set_tiling_flags(struct radeon_object *robj, | ||
558 | uint32_t tiling_flags, uint32_t pitch) | ||
559 | { | ||
560 | robj->tiling_flags = tiling_flags; | ||
561 | robj->pitch = pitch; | ||
562 | } | ||
563 | |||
564 | void radeon_object_get_tiling_flags(struct radeon_object *robj, | ||
565 | uint32_t *tiling_flags, | ||
566 | uint32_t *pitch) | ||
567 | { | ||
568 | if (tiling_flags) | ||
569 | *tiling_flags = robj->tiling_flags; | ||
570 | if (pitch) | ||
571 | *pitch = robj->pitch; | ||
572 | } | ||
573 | |||
574 | int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved, | ||
575 | bool force_drop) | ||
576 | { | ||
577 | if (!(robj->tiling_flags & RADEON_TILING_SURFACE)) | ||
578 | return 0; | ||
579 | |||
580 | if (force_drop) { | ||
581 | radeon_object_clear_surface_reg(robj); | ||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | if (robj->tobj.mem.mem_type != TTM_PL_VRAM) { | ||
586 | if (!has_moved) | ||
587 | return 0; | ||
588 | |||
589 | if (robj->surface_reg >= 0) | ||
590 | radeon_object_clear_surface_reg(robj); | ||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | if ((robj->surface_reg >= 0) && !has_moved) | ||
595 | return 0; | ||
596 | |||
597 | return radeon_object_get_surface_reg(robj); | ||
598 | } | ||
599 | |||
600 | void radeon_bo_move_notify(struct ttm_buffer_object *bo, | ||
601 | struct ttm_mem_reg *mem) | ||
602 | { | ||
603 | struct radeon_object *robj = container_of(bo, struct radeon_object, tobj); | ||
604 | radeon_object_check_tiling(robj, 0, 1); | ||
605 | } | ||
606 | |||
607 | void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) | ||
608 | { | ||
609 | struct radeon_object *robj = container_of(bo, struct radeon_object, tobj); | ||
610 | radeon_object_check_tiling(robj, 0, 0); | ||
611 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 4ca9aa9203d0..37e1cbcce3a9 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c | |||
@@ -429,6 +429,8 @@ static struct ttm_bo_driver radeon_bo_driver = { | |||
429 | .sync_obj_flush = &radeon_sync_obj_flush, | 429 | .sync_obj_flush = &radeon_sync_obj_flush, |
430 | .sync_obj_unref = &radeon_sync_obj_unref, | 430 | .sync_obj_unref = &radeon_sync_obj_unref, |
431 | .sync_obj_ref = &radeon_sync_obj_ref, | 431 | .sync_obj_ref = &radeon_sync_obj_ref, |
432 | .move_notify = &radeon_bo_move_notify, | ||
433 | .fault_reserve_notify = &radeon_bo_fault_reserve_notify, | ||
432 | }; | 434 | }; |
433 | 435 | ||
434 | int radeon_ttm_init(struct radeon_device *rdev) | 436 | int radeon_ttm_init(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index e55e7972c897..6538d4236989 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #define TTM_BO_HASH_ORDER 13 | 43 | #define TTM_BO_HASH_ORDER 13 |
44 | 44 | ||
45 | static int ttm_bo_setup_vm(struct ttm_buffer_object *bo); | 45 | static int ttm_bo_setup_vm(struct ttm_buffer_object *bo); |
46 | static void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); | ||
47 | static int ttm_bo_swapout(struct ttm_mem_shrink *shrink); | 46 | static int ttm_bo_swapout(struct ttm_mem_shrink *shrink); |
48 | 47 | ||
49 | static inline uint32_t ttm_bo_type_flags(unsigned type) | 48 | static inline uint32_t ttm_bo_type_flags(unsigned type) |
@@ -307,6 +306,9 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, | |||
307 | 306 | ||
308 | } | 307 | } |
309 | 308 | ||
309 | if (bdev->driver->move_notify) | ||
310 | bdev->driver->move_notify(bo, mem); | ||
311 | |||
310 | if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) && | 312 | if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) && |
311 | !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) | 313 | !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) |
312 | ret = ttm_bo_move_ttm(bo, evict, no_wait, mem); | 314 | ret = ttm_bo_move_ttm(bo, evict, no_wait, mem); |
@@ -1451,6 +1453,7 @@ void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) | |||
1451 | 1453 | ||
1452 | unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1); | 1454 | unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1); |
1453 | } | 1455 | } |
1456 | EXPORT_SYMBOL(ttm_bo_unmap_virtual); | ||
1454 | 1457 | ||
1455 | static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo) | 1458 | static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo) |
1456 | { | 1459 | { |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 40b75032ea47..41c907f6c560 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c | |||
@@ -101,6 +101,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
101 | return VM_FAULT_NOPAGE; | 101 | return VM_FAULT_NOPAGE; |
102 | } | 102 | } |
103 | 103 | ||
104 | if (bdev->driver->fault_reserve_notify) | ||
105 | bdev->driver->fault_reserve_notify(bo); | ||
106 | |||
104 | /* | 107 | /* |
105 | * Wait for buffer data in transit, due to a pipelined | 108 | * Wait for buffer data in transit, due to a pipelined |
106 | * move. | 109 | * move. |
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 41862e9a4c20..af4b4826997e 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h | |||
@@ -506,6 +506,8 @@ typedef struct { | |||
506 | #define DRM_RADEON_GEM_WAIT_IDLE 0x24 | 506 | #define DRM_RADEON_GEM_WAIT_IDLE 0x24 |
507 | #define DRM_RADEON_CS 0x26 | 507 | #define DRM_RADEON_CS 0x26 |
508 | #define DRM_RADEON_INFO 0x27 | 508 | #define DRM_RADEON_INFO 0x27 |
509 | #define DRM_RADEON_GEM_SET_TILING 0x28 | ||
510 | #define DRM_RADEON_GEM_GET_TILING 0x29 | ||
509 | 511 | ||
510 | #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) | 512 | #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) |
511 | #define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) | 513 | #define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) |
@@ -544,7 +546,8 @@ typedef struct { | |||
544 | #define DRM_IOCTL_RADEON_GEM_WAIT_IDLE DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle) | 546 | #define DRM_IOCTL_RADEON_GEM_WAIT_IDLE DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle) |
545 | #define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs) | 547 | #define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs) |
546 | #define DRM_IOCTL_RADEON_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info) | 548 | #define DRM_IOCTL_RADEON_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info) |
547 | 549 | #define DRM_IOCTL_RADEON_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_TILING, struct drm_radeon_gem_set_tiling) | |
550 | #define DRM_IOCTL_RADEON_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_GET_TILING, struct drm_radeon_gem_get_tiling) | ||
548 | 551 | ||
549 | typedef struct drm_radeon_init { | 552 | typedef struct drm_radeon_init { |
550 | enum { | 553 | enum { |
@@ -796,6 +799,24 @@ struct drm_radeon_gem_create { | |||
796 | uint32_t flags; | 799 | uint32_t flags; |
797 | }; | 800 | }; |
798 | 801 | ||
802 | #define RADEON_TILING_MACRO 0x1 | ||
803 | #define RADEON_TILING_MICRO 0x2 | ||
804 | #define RADEON_TILING_SWAP 0x4 | ||
805 | #define RADEON_TILING_SURFACE 0x8 /* this object requires a surface | ||
806 | * when mapped - i.e. front buffer */ | ||
807 | |||
808 | struct drm_radeon_gem_set_tiling { | ||
809 | uint32_t handle; | ||
810 | uint32_t tiling_flags; | ||
811 | uint32_t pitch; | ||
812 | }; | ||
813 | |||
814 | struct drm_radeon_gem_get_tiling { | ||
815 | uint32_t handle; | ||
816 | uint32_t tiling_flags; | ||
817 | uint32_t pitch; | ||
818 | }; | ||
819 | |||
799 | struct drm_radeon_gem_mmap { | 820 | struct drm_radeon_gem_mmap { |
800 | uint32_t handle; | 821 | uint32_t handle; |
801 | uint32_t pad; | 822 | uint32_t pad; |
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index ea83dd23a4d7..a68829db381a 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h | |||
@@ -354,6 +354,14 @@ struct ttm_bo_driver { | |||
354 | int (*sync_obj_flush) (void *sync_obj, void *sync_arg); | 354 | int (*sync_obj_flush) (void *sync_obj, void *sync_arg); |
355 | void (*sync_obj_unref) (void **sync_obj); | 355 | void (*sync_obj_unref) (void **sync_obj); |
356 | void *(*sync_obj_ref) (void *sync_obj); | 356 | void *(*sync_obj_ref) (void *sync_obj); |
357 | |||
358 | /* hook to notify driver about a driver move so it | ||
359 | * can do tiling things */ | ||
360 | void (*move_notify)(struct ttm_buffer_object *bo, | ||
361 | struct ttm_mem_reg *new_mem); | ||
362 | /* notify the driver we are taking a fault on this BO | ||
363 | * and have reserved it */ | ||
364 | void (*fault_reserve_notify)(struct ttm_buffer_object *bo); | ||
357 | }; | 365 | }; |
358 | 366 | ||
359 | #define TTM_NUM_MEM_TYPES 8 | 367 | #define TTM_NUM_MEM_TYPES 8 |
@@ -654,6 +662,13 @@ extern int ttm_bo_device_init(struct ttm_bo_device *bdev, | |||
654 | uint64_t file_page_offset, bool need_dma32); | 662 | uint64_t file_page_offset, bool need_dma32); |
655 | 663 | ||
656 | /** | 664 | /** |
665 | * ttm_bo_unmap_virtual | ||
666 | * | ||
667 | * @bo: tear down the virtual mappings for this BO | ||
668 | */ | ||
669 | extern void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); | ||
670 | |||
671 | /** | ||
657 | * ttm_bo_reserve: | 672 | * ttm_bo_reserve: |
658 | * | 673 | * |
659 | * @bo: A pointer to a struct ttm_buffer_object. | 674 | * @bo: A pointer to a struct ttm_buffer_object. |