aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/drm/r300_cmdbuf.c15
-rw-r--r--drivers/char/drm/radeon_cp.c143
-rw-r--r--drivers/char/drm/radeon_drm.h1
-rw-r--r--drivers/char/drm/radeon_drv.h10
-rw-r--r--drivers/char/drm/radeon_state.c58
5 files changed, 163 insertions, 64 deletions
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index 9fbadb965858..20b6cb39213d 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -242,8 +242,10 @@ static __inline__ int r300_check_range(unsigned reg, int count)
242 return 0; 242 return 0;
243} 243}
244 244
245 /* we expect offsets passed to the framebuffer to be either within video memory or 245/*
246 within AGP space */ 246 * we expect offsets passed to the framebuffer to be either within video
247 * memory or within AGP space
248 */
247static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, 249static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
248 u32 offset) 250 u32 offset)
249{ 251{
@@ -251,11 +253,11 @@ static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
251 but this value is not being kept. 253 but this value is not being kept.
252 This code is correct for now (does the same thing as the 254 This code is correct for now (does the same thing as the
253 code that sets MC_FB_LOCATION) in radeon_cp.c */ 255 code that sets MC_FB_LOCATION) in radeon_cp.c */
254 if ((offset >= dev_priv->fb_location) && 256 if (offset >= dev_priv->fb_location &&
255 (offset < dev_priv->gart_vm_start)) 257 offset < (dev_priv->fb_location + dev_priv->fb_size))
256 return 0; 258 return 0;
257 if ((offset >= dev_priv->gart_vm_start) && 259 if (offset >= dev_priv->gart_vm_start &&
258 (offset < dev_priv->gart_vm_start + dev_priv->gart_size)) 260 offset < (dev_priv->gart_vm_start + dev_priv->gart_size))
259 return 0; 261 return 0;
260 return 1; 262 return 1;
261} 263}
@@ -490,6 +492,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
490 492
491 return 0; 493 return 0;
492} 494}
495
493static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, 496static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
494 drm_radeon_kcmd_buffer_t *cmdbuf) 497 drm_radeon_kcmd_buffer_t *cmdbuf)
495{ 498{
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 9bb8ae0c1c27..cc4942a112cb 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -1118,14 +1118,20 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
1118{ 1118{
1119 u32 ring_start, cur_read_ptr; 1119 u32 ring_start, cur_read_ptr;
1120 u32 tmp; 1120 u32 tmp;
1121 1121
1122 /* Initialize the memory controller */ 1122 /* Initialize the memory controller. With new memory map, the fb location
1123 RADEON_WRITE(RADEON_MC_FB_LOCATION, 1123 * is not changed, it should have been properly initialized already. Part
1124 ((dev_priv->gart_vm_start - 1) & 0xffff0000) 1124 * of the problem is that the code below is bogus, assuming the GART is
1125 | (dev_priv->fb_location >> 16)); 1125 * always appended to the fb which is not necessarily the case
1126 */
1127 if (!dev_priv->new_memmap)
1128 RADEON_WRITE(RADEON_MC_FB_LOCATION,
1129 ((dev_priv->gart_vm_start - 1) & 0xffff0000)
1130 | (dev_priv->fb_location >> 16));
1126 1131
1127#if __OS_HAS_AGP 1132#if __OS_HAS_AGP
1128 if (dev_priv->flags & CHIP_IS_AGP) { 1133 if (dev_priv->flags & CHIP_IS_AGP) {
1134 RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
1129 RADEON_WRITE(RADEON_MC_AGP_LOCATION, 1135 RADEON_WRITE(RADEON_MC_AGP_LOCATION,
1130 (((dev_priv->gart_vm_start - 1 + 1136 (((dev_priv->gart_vm_start - 1 +
1131 dev_priv->gart_size) & 0xffff0000) | 1137 dev_priv->gart_size) & 0xffff0000) |
@@ -1153,8 +1159,6 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
1153 1159
1154#if __OS_HAS_AGP 1160#if __OS_HAS_AGP
1155 if (dev_priv->flags & CHIP_IS_AGP) { 1161 if (dev_priv->flags & CHIP_IS_AGP) {
1156 /* set RADEON_AGP_BASE here instead of relying on X from user space */
1157 RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
1158 RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, 1162 RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
1159 dev_priv->ring_rptr->offset 1163 dev_priv->ring_rptr->offset
1160 - dev->agp->base + dev_priv->gart_vm_start); 1164 - dev->agp->base + dev_priv->gart_vm_start);
@@ -1174,6 +1178,17 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
1174 entry->handle + tmp_ofs); 1178 entry->handle + tmp_ofs);
1175 } 1179 }
1176 1180
1181 /* Set ring buffer size */
1182#ifdef __BIG_ENDIAN
1183 RADEON_WRITE(RADEON_CP_RB_CNTL,
1184 dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
1185#else
1186 RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
1187#endif
1188
1189 /* Start with assuming that writeback doesn't work */
1190 dev_priv->writeback_works = 0;
1191
1177 /* Initialize the scratch register pointer. This will cause 1192 /* Initialize the scratch register pointer. This will cause
1178 * the scratch register values to be written out to memory 1193 * the scratch register values to be written out to memory
1179 * whenever they are updated. 1194 * whenever they are updated.
@@ -1190,28 +1205,9 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
1190 1205
1191 RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); 1206 RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
1192 1207
1193 /* Writeback doesn't seem to work everywhere, test it first */ 1208 /* Turn on bus mastering */
1194 DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0); 1209 tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
1195 RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); 1210 RADEON_WRITE(RADEON_BUS_CNTL, tmp);
1196
1197 for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
1198 if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==
1199 0xdeadbeef)
1200 break;
1201 DRM_UDELAY(1);
1202 }
1203
1204 if (tmp < dev_priv->usec_timeout) {
1205 dev_priv->writeback_works = 1;
1206 DRM_DEBUG("writeback test succeeded, tmp=%d\n", tmp);
1207 } else {
1208 dev_priv->writeback_works = 0;
1209 DRM_DEBUG("writeback test failed\n");
1210 }
1211 if (radeon_no_wb == 1) {
1212 dev_priv->writeback_works = 0;
1213 DRM_DEBUG("writeback forced off\n");
1214 }
1215 1211
1216 dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; 1212 dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
1217 RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); 1213 RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
@@ -1223,26 +1219,45 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
1223 dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; 1219 dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
1224 RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear); 1220 RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
1225 1221
1226 /* Set ring buffer size */
1227#ifdef __BIG_ENDIAN
1228 RADEON_WRITE(RADEON_CP_RB_CNTL,
1229 dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
1230#else
1231 RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
1232#endif
1233
1234 radeon_do_wait_for_idle(dev_priv); 1222 radeon_do_wait_for_idle(dev_priv);
1235 1223
1236 /* Turn on bus mastering */
1237 tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
1238 RADEON_WRITE(RADEON_BUS_CNTL, tmp);
1239
1240 /* Sync everything up */ 1224 /* Sync everything up */
1241 RADEON_WRITE(RADEON_ISYNC_CNTL, 1225 RADEON_WRITE(RADEON_ISYNC_CNTL,
1242 (RADEON_ISYNC_ANY2D_IDLE3D | 1226 (RADEON_ISYNC_ANY2D_IDLE3D |
1243 RADEON_ISYNC_ANY3D_IDLE2D | 1227 RADEON_ISYNC_ANY3D_IDLE2D |
1244 RADEON_ISYNC_WAIT_IDLEGUI | 1228 RADEON_ISYNC_WAIT_IDLEGUI |
1245 RADEON_ISYNC_CPSCRATCH_IDLEGUI)); 1229 RADEON_ISYNC_CPSCRATCH_IDLEGUI));
1230
1231}
1232
1233static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
1234{
1235 u32 tmp;
1236
1237 /* Writeback doesn't seem to work everywhere, test it here and possibly
1238 * enable it if it appears to work
1239 */
1240 DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);
1241 RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
1242
1243 for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
1244 if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==
1245 0xdeadbeef)
1246 break;
1247 DRM_UDELAY(1);
1248 }
1249
1250 if (tmp < dev_priv->usec_timeout) {
1251 dev_priv->writeback_works = 1;
1252 DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
1253 } else {
1254 dev_priv->writeback_works = 0;
1255 DRM_INFO("writeback test failed\n");
1256 }
1257 if (radeon_no_wb == 1) {
1258 dev_priv->writeback_works = 0;
1259 DRM_INFO("writeback forced off\n");
1260 }
1246} 1261}
1247 1262
1248/* Enable or disable PCI-E GART on the chip */ 1263/* Enable or disable PCI-E GART on the chip */
@@ -1496,6 +1511,9 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1496 1511
1497 dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION) 1512 dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION)
1498 & 0xffff) << 16; 1513 & 0xffff) << 16;
1514 dev_priv->fb_size =
1515 ((RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff0000u) + 0x10000)
1516 - dev_priv->fb_location;
1499 1517
1500 dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | 1518 dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
1501 ((dev_priv->front_offset 1519 ((dev_priv->front_offset
@@ -1510,8 +1528,46 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1510 + dev_priv->fb_location) >> 10)); 1528 + dev_priv->fb_location) >> 10));
1511 1529
1512 dev_priv->gart_size = init->gart_size; 1530 dev_priv->gart_size = init->gart_size;
1513 dev_priv->gart_vm_start = dev_priv->fb_location 1531
1514 + RADEON_READ(RADEON_CONFIG_APER_SIZE); 1532 /* New let's set the memory map ... */
1533 if (dev_priv->new_memmap) {
1534 u32 base = 0;
1535
1536 DRM_INFO("Setting GART location based on new memory map\n");
1537
1538 /* If using AGP, try to locate the AGP aperture at the same
1539 * location in the card and on the bus, though we have to
1540 * align it down.
1541 */
1542#if __OS_HAS_AGP
1543 if (dev_priv->flags & CHIP_IS_AGP) {
1544 base = dev->agp->base;
1545 /* Check if valid */
1546 if ((base + dev_priv->gart_size) > dev_priv->fb_location &&
1547 base < (dev_priv->fb_location + dev_priv->fb_size)) {
1548 DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
1549 dev->agp->base);
1550 base = 0;
1551 }
1552 }
1553#endif
1554 /* If not or if AGP is at 0 (Macs), try to put it elsewhere */
1555 if (base == 0) {
1556 base = dev_priv->fb_location + dev_priv->fb_size;
1557 if (((base + dev_priv->gart_size) & 0xfffffffful)
1558 < base)
1559 base = dev_priv->fb_location
1560 - dev_priv->gart_size;
1561 }
1562 dev_priv->gart_vm_start = base & 0xffc00000u;
1563 if (dev_priv->gart_vm_start != base)
1564 DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
1565 base, dev_priv->gart_vm_start);
1566 } else {
1567 DRM_INFO("Setting GART location based on old memory map\n");
1568 dev_priv->gart_vm_start = dev_priv->fb_location +
1569 RADEON_READ(RADEON_CONFIG_APER_SIZE);
1570 }
1515 1571
1516#if __OS_HAS_AGP 1572#if __OS_HAS_AGP
1517 if (dev_priv->flags & CHIP_IS_AGP) 1573 if (dev_priv->flags & CHIP_IS_AGP)
@@ -1596,6 +1652,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1596 dev_priv->last_buf = 0; 1652 dev_priv->last_buf = 0;
1597 1653
1598 radeon_do_engine_reset(dev); 1654 radeon_do_engine_reset(dev);
1655 radeon_test_writeback(dev_priv);
1599 1656
1600 return 0; 1657 return 0;
1601} 1658}
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index 9c177a6b2a4c..bb63e6806fd1 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -697,6 +697,7 @@ typedef struct drm_radeon_setparam {
697#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ 697#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */
698#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ 698#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */
699#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ 699#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
700#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */
700 701
701/* 1.14: Clients can allocate/free a surface 702/* 1.14: Clients can allocate/free a surface
702 */ 703 */
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 1f7d2ab8c4fc..a0c198895a27 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -38,7 +38,7 @@
38 38
39#define DRIVER_NAME "radeon" 39#define DRIVER_NAME "radeon"
40#define DRIVER_DESC "ATI Radeon" 40#define DRIVER_DESC "ATI Radeon"
41#define DRIVER_DATE "20051229" 41#define DRIVER_DATE "20060225"
42 42
43/* Interface history: 43/* Interface history:
44 * 44 *
@@ -91,9 +91,10 @@
91 * 1.20- Add support for r300 texrect 91 * 1.20- Add support for r300 texrect
92 * 1.21- Add support for card type getparam 92 * 1.21- Add support for card type getparam
93 * 1.22- Add support for texture cache flushes (R300_TX_CNTL) 93 * 1.22- Add support for texture cache flushes (R300_TX_CNTL)
94 * 1.23- Add new radeon memory map work from benh
94 */ 95 */
95#define DRIVER_MAJOR 1 96#define DRIVER_MAJOR 1
96#define DRIVER_MINOR 22 97#define DRIVER_MINOR 23
97#define DRIVER_PATCHLEVEL 0 98#define DRIVER_PATCHLEVEL 0
98 99
99/* 100/*
@@ -138,7 +139,8 @@ enum radeon_chip_flags {
138 CHIP_IS_PCIE = 0x00200000UL, 139 CHIP_IS_PCIE = 0x00200000UL,
139}; 140};
140 141
141#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 ) 142#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \
143 DRM_READ32( (dev_priv)->ring_rptr, 0 ) : RADEON_READ(RADEON_CP_RB_RPTR))
142#define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) ) 144#define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
143 145
144typedef struct drm_radeon_freelist { 146typedef struct drm_radeon_freelist {
@@ -199,6 +201,8 @@ typedef struct drm_radeon_private {
199 drm_radeon_sarea_t *sarea_priv; 201 drm_radeon_sarea_t *sarea_priv;
200 202
201 u32 fb_location; 203 u32 fb_location;
204 u32 fb_size;
205 int new_memmap;
202 206
203 int gart_size; 207 int gart_size;
204 u32 gart_vm_start; 208 u32 gart_vm_start;
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 7bc27516d425..56e56b873616 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -45,22 +45,53 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
45 u32 off = *offset; 45 u32 off = *offset;
46 struct drm_radeon_driver_file_fields *radeon_priv; 46 struct drm_radeon_driver_file_fields *radeon_priv;
47 47
48 if (off >= dev_priv->fb_location && 48 /* Hrm ... the story of the offset ... So this function converts
49 off < (dev_priv->gart_vm_start + dev_priv->gart_size)) 49 * the various ideas of what userland clients might have for an
50 return 0; 50 * offset in the card address space into an offset into the card
51 51 * address space :) So with a sane client, it should just keep
52 radeon_priv = filp_priv->driver_priv; 52 * the value intact and just do some boundary checking. However,
53 off += radeon_priv->radeon_fb_delta; 53 * not all clients are sane. Some older clients pass us 0 based
54 * offsets relative to the start of the framebuffer and some may
55 * assume the AGP aperture it appended to the framebuffer, so we
56 * try to detect those cases and fix them up.
57 *
58 * Note: It might be a good idea here to make sure the offset lands
59 * in some "allowed" area to protect things like the PCIE GART...
60 */
54 61
55 DRM_DEBUG("offset fixed up to 0x%x\n", off); 62 /* First, the best case, the offset already lands in either the
63 * framebuffer or the GART mapped space
64 */
65 if ((off >= dev_priv->fb_location &&
66 off < (dev_priv->fb_location + dev_priv->fb_size)) ||
67 (off >= dev_priv->gart_vm_start &&
68 off < (dev_priv->gart_vm_start + dev_priv->gart_size)))
69 return 0;
56 70
57 if (off < dev_priv->fb_location || 71 /* Ok, that didn't happen... now check if we have a zero based
58 off >= (dev_priv->gart_vm_start + dev_priv->gart_size)) 72 * offset that fits in the framebuffer + gart space, apply the
59 return DRM_ERR(EINVAL); 73 * magic offset we get from SETPARAM or calculated from fb_location
74 */
75 if (off < (dev_priv->fb_size + dev_priv->gart_size)) {
76 radeon_priv = filp_priv->driver_priv;
77 off += radeon_priv->radeon_fb_delta;
78 }
60 79
61 *offset = off; 80 /* Finally, assume we aimed at a GART offset if beyond the fb */
81 if (off > (dev_priv->fb_location + dev_priv->fb_size))
82 off = off - (dev_priv->fb_location + dev_priv->fb_size) +
83 dev_priv->gart_vm_start;
62 84
63 return 0; 85 /* Now recheck and fail if out of bounds */
86 if ((off >= dev_priv->fb_location &&
87 off < (dev_priv->fb_location + dev_priv->fb_size)) ||
88 (off >= dev_priv->gart_vm_start &&
89 off < (dev_priv->gart_vm_start + dev_priv->gart_size))) {
90 DRM_DEBUG("offset fixed up to 0x%x\n", off);
91 *offset = off;
92 return 0;
93 }
94 return DRM_ERR(EINVAL);
64} 95}
65 96
66static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * 97static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
@@ -3012,6 +3043,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
3012 case RADEON_SETPARAM_PCIGART_LOCATION: 3043 case RADEON_SETPARAM_PCIGART_LOCATION:
3013 dev_priv->pcigart_offset = sp.value; 3044 dev_priv->pcigart_offset = sp.value;
3014 break; 3045 break;
3046 case RADEON_SETPARAM_NEW_MEMMAP:
3047 dev_priv->new_memmap = sp.value;
3048 break;
3015 default: 3049 default:
3016 DRM_DEBUG("Invalid parameter %d\n", sp.param); 3050 DRM_DEBUG("Invalid parameter %d\n", sp.param);
3017 return DRM_ERR(EINVAL); 3051 return DRM_ERR(EINVAL);