diff --git a/src/ast_drv.c b/src/ast_drv.c index 01c3751f9df0882e788853fa8c95b8781627438f..ea6e913ebbb840244a76624146c0c7d55a711592 100644 --- a/src/ast_drv.c +++ b/src/ast_drv.c @@ -226,11 +226,30 @@ static struct pci_driver ast_pci_driver = { DEFINE_DRM_GEM_FOPS(ast_fops); +#define DRM_AST_VRAM_TYPE_DEVICE 0x0 +#define DRM_IOCTL_AST_VRAM_TYPE_DEVICE DRM_IO(DRM_COMMAND_BASE\ + + DRM_AST_VRAM_TYPE_DEVICE) + +static int ast_ioctl_check_5c01_device(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct ast_private *priv = to_ast_private(dev); + + return priv->is_5c01_device ? 1 : 0; +} + +static const struct drm_ioctl_desc ast_ioctls[] = { + /* for test, none so far */ + DRM_IOCTL_DEF_DRV(AST_VRAM_TYPE_DEVICE, ast_ioctl_check_5c01_device, + DRM_AUTH|DRM_UNLOCKED), +}; + static struct drm_driver driver = { .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET, - + .ioctls = ast_ioctls, + .num_ioctls = ARRAY_SIZE(ast_ioctls), .fops = &ast_fops, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/src/ast_drv.h b/src/ast_drv.h index 4d7c12e64d3bc6cf764e7d1c3a3457d93d534c91..666515f3d580fcb15b16d7c0dfa22cabed296e6c 100644 --- a/src/ast_drv.h +++ b/src/ast_drv.h @@ -128,6 +128,7 @@ struct ast_private { struct drm_plane primary_plane; struct drm_plane cursor_plane; + bool is_5c01_device; bool support_wide_screen; bool support_newvga_mode; bool RefCLK25MHz; diff --git a/src/ast_mm.c b/src/ast_mm.c index 9186ec3ebbe0934ee96dc75308f28d23a53802a6..ce12dcb5c8a43bada22c347b234e1805bf36d945 100644 --- a/src/ast_mm.c +++ b/src/ast_mm.c @@ -74,6 +74,52 @@ static u32 ast_get_vram_size(struct ast_private *ast) return vram_size; } +static int ast_driver_io_mem_reserve(struct ttm_bo_device *bdev, + struct ttm_resource *mem) +{ + struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bdev); + size_t bus_size = (size_t)mem->num_pages << PAGE_SHIFT; + + switch (mem->mem_type) { + case TTM_PL_SYSTEM: /* nothing to do */ + break; + case TTM_PL_VRAM: + mem->bus.offset = (mem->start << PAGE_SHIFT) + vmm->vram_base; + mem->bus.is_iomem = true; + + mem->placement = TTM_PL_FLAG_UNCACHED; + mem->bus.addr = ioremap(mem->bus.offset, bus_size); + + if (!mem->bus.addr) + return -ENOMEM; + + break; + default: + return -EINVAL; + } + + return 0; +} + +static bool ast_pci_host_is_5c01(struct pci_bus *bus) +{ + struct pci_bus *child = bus; + struct pci_dev *root = NULL; + + while (child) { + if (child->parent->parent) + child = child->parent; + else + break; + } + + root = child->self; + + if ((root->vendor == 0x1db7) && (root->device == 0x5c01)) + return true; + return false; +} + static void ast_mm_release(struct drm_device *dev, void *ptr) { struct ast_private *ast = to_ast_private(dev); @@ -88,6 +134,7 @@ int ast_mm_init(struct ast_private *ast) u32 vram_size; int ret; struct drm_device *dev = ast->dev; + struct pci_dev *pdev = to_pci_dev(dev->dev); vram_size = ast_get_vram_size(ast); @@ -98,6 +145,13 @@ int ast_mm_init(struct ast_private *ast) return ret; } + if (ast_pci_host_is_5c01(pdev->bus) && dev->vram_mm->bdev.driver) { + ast->is_5c01_device = true; + dev->vram_mm->bdev.driver->io_mem_reserve = ast_driver_io_mem_reserve; + } else { + ast->is_5c01_device = false; + } + arch_io_reserve_memtype_wc(pci_resource_start(dev->pdev, 0), pci_resource_len(dev->pdev, 0)); ast->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),