summaryrefslogtreecommitdiff
path: root/linux-core/drm_agpsupport.c
diff options
context:
space:
mode:
authorNian Wu <nian.wu@intel.com>2006-11-09 21:21:17 -0800
committerNian Wu <nian.wu@intel.com>2006-11-09 21:21:17 -0800
commit14e3f2711e90fe9a9c315d96abd4c7681539936a (patch)
tree6a562d9035e56671eb7905bac1f3829597f109a9 /linux-core/drm_agpsupport.c
parente2ea72187e470c2c13adbd3fba4177bd4a0ecc37 (diff)
parentd51e1bb56ca2f7858cdeac6f61a7b747c1e15b1e (diff)
Merge branch 'master' into crestline
Conflicts: shared-core/i915_dma.c
Diffstat (limited to 'linux-core/drm_agpsupport.c')
-rw-r--r--linux-core/drm_agpsupport.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c
index dce27cdf..a5f1f9ee 100644
--- a/linux-core/drm_agpsupport.c
+++ b/linux-core/drm_agpsupport.c
@@ -552,4 +552,162 @@ int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
return agp_unbind_memory(handle);
}
+
+
+/*
+ * AGP ttm backend interface.
+ */
+
+#ifndef AGP_USER_TYPES
+#define AGP_USER_TYPES (1 << 16)
+#define AGP_USER_MEMORY (AGP_USER_TYPES)
+#define AGP_USER_CACHED_MEMORY (AGP_USER_TYPES + 1)
+#endif
+
+static int drm_agp_needs_unbind_cache_adjust(drm_ttm_backend_t *backend) {
+ return ((backend->flags & DRM_BE_FLAG_BOUND_CACHED) ? 0 : 1);
+}
+
+
+static int drm_agp_populate(drm_ttm_backend_t *backend, unsigned long num_pages,
+ struct page **pages) {
+
+ drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private;
+ struct page **cur_page, **last_page = pages + num_pages;
+ DRM_AGP_MEM *mem;
+
+ if (drm_alloc_memctl(num_pages * sizeof(void *)))
+ return -1;
+
+ DRM_DEBUG("drm_agp_populate_ttm\n");
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11)
+ mem = drm_agp_allocate_memory(num_pages, agp_priv->alloc_type);
+#else
+ mem = drm_agp_allocate_memory(agp_priv->bridge, num_pages, agp_priv->alloc_type);
+#endif
+ if (!mem) {
+ drm_free_memctl(num_pages *sizeof(void *));
+ return -1;
+ }
+
+ DRM_DEBUG("Current page count is %ld\n", (long) mem->page_count);
+ mem->page_count = 0;
+ for (cur_page = pages; cur_page < last_page; ++cur_page) {
+ mem->memory[mem->page_count++] = phys_to_gart(page_to_phys(*cur_page));
+ }
+ agp_priv->mem = mem;
+ return 0;
+}
+
+static int drm_agp_bind_ttm(drm_ttm_backend_t *backend,
+ unsigned long offset,
+ int cached)
+{
+ drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private;
+ DRM_AGP_MEM *mem = agp_priv->mem;
+ int ret;
+
+ DRM_DEBUG("drm_agp_bind_ttm\n");
+ DRM_MASK_VAL(backend->flags, DRM_BE_FLAG_BOUND_CACHED,
+ (cached) ? DRM_BE_FLAG_BOUND_CACHED : 0);
+ mem->is_flushed = TRUE;
+ mem->type = (cached) ? agp_priv->cached_type : agp_priv->uncached_type;
+ ret = drm_agp_bind_memory(mem, offset);
+ if (ret) {
+ DRM_ERROR("AGP Bind memory failed\n");
+ }
+ return ret;
+}
+
+static int drm_agp_unbind_ttm(drm_ttm_backend_t *backend) {
+
+ drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private;
+
+ DRM_DEBUG("drm_agp_unbind_ttm\n");
+ if (agp_priv->mem->is_bound)
+ return drm_agp_unbind_memory(agp_priv->mem);
+ else
+ return 0;
+}
+
+static void drm_agp_clear_ttm(drm_ttm_backend_t *backend) {
+
+ drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private;
+ DRM_AGP_MEM *mem = agp_priv->mem;
+
+ DRM_DEBUG("drm_agp_clear_ttm\n");
+ if (mem) {
+ unsigned long num_pages = mem->page_count;
+ backend->unbind(backend);
+ agp_free_memory(mem);
+ drm_free_memctl(num_pages *sizeof(void *));
+ }
+
+ agp_priv->mem = NULL;
+}
+
+static void drm_agp_destroy_ttm(drm_ttm_backend_t *backend) {
+
+ drm_agp_ttm_priv *agp_priv;
+
+ if (backend) {
+ DRM_DEBUG("drm_agp_destroy_ttm\n");
+ agp_priv = (drm_agp_ttm_priv *) backend->private;
+ if (agp_priv) {
+ if (agp_priv->mem) {
+ backend->clear(backend);
+ }
+ drm_ctl_free(agp_priv, sizeof(*agp_priv), DRM_MEM_MAPPINGS);
+ backend->private = NULL;
+ }
+ if (backend->flags & DRM_BE_FLAG_NEEDS_FREE) {
+ drm_ctl_free(backend, sizeof(*backend), DRM_MEM_MAPPINGS);
+ }
+ }
+}
+
+
+drm_ttm_backend_t *drm_agp_init_ttm(struct drm_device *dev,
+ drm_ttm_backend_t *backend)
+{
+
+ drm_ttm_backend_t *agp_be;
+ drm_agp_ttm_priv *agp_priv;
+
+ agp_be = (backend != NULL) ? backend:
+ drm_ctl_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS);
+
+ if (!agp_be)
+ return NULL;
+
+ agp_priv = drm_ctl_calloc(1, sizeof(*agp_priv), DRM_MEM_MAPPINGS);
+
+ if (!agp_priv) {
+ drm_ctl_free(agp_be, sizeof(*agp_be), DRM_MEM_MAPPINGS);
+ return NULL;
+ }
+
+ agp_priv->mem = NULL;
+ agp_priv->alloc_type = AGP_USER_MEMORY;
+ agp_priv->cached_type = AGP_USER_CACHED_MEMORY;
+ agp_priv->uncached_type = AGP_USER_MEMORY;
+ agp_priv->bridge = dev->agp->bridge;
+ agp_priv->populated = FALSE;
+ agp_be->aperture_base = dev->agp->agp_info.aper_base;
+ agp_be->private = (void *) agp_priv;
+ agp_be->needs_ub_cache_adjust = drm_agp_needs_unbind_cache_adjust;
+ agp_be->populate = drm_agp_populate;
+ agp_be->clear = drm_agp_clear_ttm;
+ agp_be->bind = drm_agp_bind_ttm;
+ agp_be->unbind = drm_agp_unbind_ttm;
+ agp_be->destroy = drm_agp_destroy_ttm;
+ DRM_MASK_VAL(agp_be->flags, DRM_BE_FLAG_NEEDS_FREE,
+ (backend == NULL) ? DRM_BE_FLAG_NEEDS_FREE : 0);
+ DRM_MASK_VAL(agp_be->flags, DRM_BE_FLAG_CBA,
+ (dev->agp->cant_use_aperture) ? DRM_BE_FLAG_CBA : 0);
+ agp_be->drm_map_type = _DRM_AGP;
+ return agp_be;
+}
+EXPORT_SYMBOL(drm_agp_init_ttm);
+
#endif /* __OS_HAS_AGP */