aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_cp.c
diff options
context:
space:
mode:
authorDavid Miller <davem@davemloft.net>2009-02-14 04:51:07 -0500
committerDave Airlie <airlied@redhat.com>2009-03-13 00:24:02 -0400
commit6abf6bb0ff90bb77f9429bd0d90fc841c358daf3 (patch)
treebb291ce9a51dc8f8df33db5774d089ee8907ad33 /drivers/gpu/drm/radeon/radeon_cp.c
parente8a894372b4ea05dc266ba7d7a7634315b6230e8 (diff)
drm: radeon: Use surface for PCI GART table.
This allocates a physical surface for the PCI GART table, this way no matter what other surface configurations exist the GART table will always be seen by the hardware properly. We encode the file pointer of the virtual surface allocate using a special cookie value, called PCIGART_FILE_PRIV. On the last close, we release that surface. Just to be doubly safe, we run the pcigart table setup with the main surface control register clear. Based upon ideas from David Airlie and Ben Benjamin Herrenschmidt. Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_cp.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_cp.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index 4a56e7d626a6..a18b3688a7f0 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -919,6 +919,46 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
919 } 919 }
920} 920}
921 921
922static int radeon_setup_pcigart_surface(drm_radeon_private_t *dev_priv)
923{
924 struct drm_ati_pcigart_info *gart_info = &dev_priv->gart_info;
925 struct radeon_virt_surface *vp;
926 int i;
927
928 for (i = 0; i < RADEON_MAX_SURFACES * 2; i++) {
929 if (!dev_priv->virt_surfaces[i].file_priv ||
930 dev_priv->virt_surfaces[i].file_priv == PCIGART_FILE_PRIV)
931 break;
932 }
933 if (i >= 2 * RADEON_MAX_SURFACES)
934 return -ENOMEM;
935 vp = &dev_priv->virt_surfaces[i];
936
937 for (i = 0; i < RADEON_MAX_SURFACES; i++) {
938 struct radeon_surface *sp = &dev_priv->surfaces[i];
939 if (sp->refcount)
940 continue;
941
942 vp->surface_index = i;
943 vp->lower = gart_info->bus_addr;
944 vp->upper = vp->lower + gart_info->table_size;
945 vp->flags = 0;
946 vp->file_priv = PCIGART_FILE_PRIV;
947
948 sp->refcount = 1;
949 sp->lower = vp->lower;
950 sp->upper = vp->upper;
951 sp->flags = 0;
952
953 RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, sp->flags);
954 RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * i, sp->lower);
955 RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * i, sp->upper);
956 return 0;
957 }
958
959 return -ENOMEM;
960}
961
922static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, 962static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
923 struct drm_file *file_priv) 963 struct drm_file *file_priv)
924{ 964{
@@ -1212,6 +1252,9 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
1212 } else 1252 } else
1213#endif 1253#endif
1214 { 1254 {
1255 u32 sctrl;
1256 int ret;
1257
1215 dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); 1258 dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
1216 /* if we have an offset set from userspace */ 1259 /* if we have an offset set from userspace */
1217 if (dev_priv->pcigart_offset_set) { 1260 if (dev_priv->pcigart_offset_set) {
@@ -1253,12 +1296,25 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
1253 } 1296 }
1254 } 1297 }
1255 1298
1256 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { 1299 sctrl = RADEON_READ(RADEON_SURFACE_CNTL);
1300 RADEON_WRITE(RADEON_SURFACE_CNTL, 0);
1301 ret = drm_ati_pcigart_init(dev, &dev_priv->gart_info);
1302 RADEON_WRITE(RADEON_SURFACE_CNTL, sctrl);
1303
1304 if (!ret) {
1257 DRM_ERROR("failed to init PCI GART!\n"); 1305 DRM_ERROR("failed to init PCI GART!\n");
1258 radeon_do_cleanup_cp(dev); 1306 radeon_do_cleanup_cp(dev);
1259 return -ENOMEM; 1307 return -ENOMEM;
1260 } 1308 }
1261 1309
1310 ret = radeon_setup_pcigart_surface(dev_priv);
1311 if (ret) {
1312 DRM_ERROR("failed to setup GART surface!\n");
1313 drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info);
1314 radeon_do_cleanup_cp(dev);
1315 return ret;
1316 }
1317
1262 /* Turn on PCI GART */ 1318 /* Turn on PCI GART */
1263 radeon_set_pcigart(dev_priv, 1); 1319 radeon_set_pcigart(dev_priv, 1);
1264 } 1320 }