diff options
Diffstat (limited to 'drivers/gpu/drm/cirrus/cirrus_main.c')
-rw-r--r-- | drivers/gpu/drm/cirrus/cirrus_main.c | 328 |
1 files changed, 0 insertions, 328 deletions
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c deleted file mode 100644 index 57f8fe6d020b..000000000000 --- a/drivers/gpu/drm/cirrus/cirrus_main.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright 2012 Red Hat - * - * This file is subject to the terms and conditions of the GNU General - * Public License version 2. See the file COPYING in the main - * directory of this archive for more details. - * - * Authors: Matthew Garrett - * Dave Airlie - */ -#include <drm/drmP.h> -#include <drm/drm_crtc_helper.h> -#include <drm/drm_gem_framebuffer_helper.h> - -#include "cirrus_drv.h" - -static const struct drm_framebuffer_funcs cirrus_fb_funcs = { - .create_handle = drm_gem_fb_create_handle, - .destroy = drm_gem_fb_destroy, -}; - -int cirrus_framebuffer_init(struct drm_device *dev, - struct drm_framebuffer *gfb, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj) -{ - int ret; - - drm_helper_mode_fill_fb_struct(dev, gfb, mode_cmd); - gfb->obj[0] = obj; - ret = drm_framebuffer_init(dev, gfb, &cirrus_fb_funcs); - if (ret) { - DRM_ERROR("drm_framebuffer_init failed: %d\n", ret); - return ret; - } - return 0; -} - -static struct drm_framebuffer * -cirrus_user_framebuffer_create(struct drm_device *dev, - struct drm_file *filp, - const struct drm_mode_fb_cmd2 *mode_cmd) -{ - struct cirrus_device *cdev = dev->dev_private; - struct drm_gem_object *obj; - struct drm_framebuffer *fb; - u32 bpp; - int ret; - - bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8; - - if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height, - bpp, mode_cmd->pitches[0])) - return ERR_PTR(-EINVAL); - - obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]); - if (obj == NULL) - return ERR_PTR(-ENOENT); - - fb = kzalloc(sizeof(*fb), GFP_KERNEL); - if (!fb) { - drm_gem_object_put_unlocked(obj); - return ERR_PTR(-ENOMEM); - } - - ret = cirrus_framebuffer_init(dev, fb, mode_cmd, obj); - if (ret) { - drm_gem_object_put_unlocked(obj); - kfree(fb); - return ERR_PTR(ret); - } - return fb; -} - -static const struct drm_mode_config_funcs cirrus_mode_funcs = { - .fb_create = cirrus_user_framebuffer_create, -}; - -/* Unmap the framebuffer from the core and release the memory */ -static void cirrus_vram_fini(struct cirrus_device *cdev) -{ - iounmap(cdev->rmmio); - cdev->rmmio = NULL; - if (cdev->mc.vram_base) - release_mem_region(cdev->mc.vram_base, cdev->mc.vram_size); -} - -/* Map the framebuffer from the card and configure the core */ -static int cirrus_vram_init(struct cirrus_device *cdev) -{ - /* BAR 0 is VRAM */ - cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0); - cdev->mc.vram_size = pci_resource_len(cdev->dev->pdev, 0); - - if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size, - "cirrusdrmfb_vram")) { - DRM_ERROR("can't reserve VRAM\n"); - return -ENXIO; - } - - return 0; -} - -/* - * Our emulated hardware has two sets of memory. One is video RAM and can - * simply be used as a linear framebuffer - the other provides mmio access - * to the display registers. The latter can also be accessed via IO port - * access, but we map the range and use mmio to program them instead - */ - -int cirrus_device_init(struct cirrus_device *cdev, - struct drm_device *ddev, - struct pci_dev *pdev, uint32_t flags) -{ - int ret; - - cdev->dev = ddev; - cdev->flags = flags; - - /* Hardcode the number of CRTCs to 1 */ - cdev->num_crtc = 1; - - /* BAR 0 is the framebuffer, BAR 1 contains registers */ - cdev->rmmio_base = pci_resource_start(cdev->dev->pdev, 1); - cdev->rmmio_size = pci_resource_len(cdev->dev->pdev, 1); - - if (!request_mem_region(cdev->rmmio_base, cdev->rmmio_size, - "cirrusdrmfb_mmio")) { - DRM_ERROR("can't reserve mmio registers\n"); - return -ENOMEM; - } - - cdev->rmmio = ioremap(cdev->rmmio_base, cdev->rmmio_size); - - if (cdev->rmmio == NULL) - return -ENOMEM; - - ret = cirrus_vram_init(cdev); - if (ret) { - release_mem_region(cdev->rmmio_base, cdev->rmmio_size); - return ret; - } - - return 0; -} - -void cirrus_device_fini(struct cirrus_device *cdev) -{ - release_mem_region(cdev->rmmio_base, cdev->rmmio_size); - cirrus_vram_fini(cdev); -} - -/* - * Functions here will be called by the core once it's bound the driver to - * a PCI device - */ - -int cirrus_driver_load(struct drm_device *dev, unsigned long flags) -{ - struct cirrus_device *cdev; - int r; - - cdev = kzalloc(sizeof(struct cirrus_device), GFP_KERNEL); - if (cdev == NULL) - return -ENOMEM; - dev->dev_private = (void *)cdev; - - r = cirrus_device_init(cdev, dev, dev->pdev, flags); - if (r) { - dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r); - goto out; - } - - r = cirrus_mm_init(cdev); - if (r) { - dev_err(&dev->pdev->dev, "fatal err on mm init\n"); - goto out; - } - - /* - * cirrus_modeset_init() is initializing/registering the emulated fbdev - * and DRM internals can access/test some of the fields in - * mode_config->funcs as part of the fbdev registration process. - * Make sure dev->mode_config.funcs is properly set to avoid - * dereferencing a NULL pointer. - * FIXME: mode_config.funcs assignment should probably be done in - * cirrus_modeset_init() (that's a common pattern seen in other DRM - * drivers). - */ - dev->mode_config.funcs = &cirrus_mode_funcs; - r = cirrus_modeset_init(cdev); - if (r) { - dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r); - goto out; - } - - return 0; -out: - cirrus_driver_unload(dev); - return r; -} - -void cirrus_driver_unload(struct drm_device *dev) -{ - struct cirrus_device *cdev = dev->dev_private; - - if (cdev == NULL) - return; - cirrus_modeset_fini(cdev); - cirrus_mm_fini(cdev); - cirrus_device_fini(cdev); - kfree(cdev); - dev->dev_private = NULL; -} - -int cirrus_gem_create(struct drm_device *dev, - u32 size, bool iskernel, - struct drm_gem_object **obj) -{ - struct cirrus_bo *cirrusbo; - int ret; - - *obj = NULL; - - size = roundup(size, PAGE_SIZE); - if (size == 0) - return -EINVAL; - - ret = cirrus_bo_create(dev, size, 0, 0, &cirrusbo); - if (ret) { - if (ret != -ERESTARTSYS) - DRM_ERROR("failed to allocate GEM object\n"); - return ret; - } - *obj = &cirrusbo->gem; - return 0; -} - -int cirrus_dumb_create(struct drm_file *file, - struct drm_device *dev, - struct drm_mode_create_dumb *args) -{ - int ret; - struct drm_gem_object *gobj; - u32 handle; - - args->pitch = args->width * ((args->bpp + 7) / 8); - args->size = args->pitch * args->height; - - ret = cirrus_gem_create(dev, args->size, false, - &gobj); - if (ret) - return ret; - - ret = drm_gem_handle_create(file, gobj, &handle); - drm_gem_object_put_unlocked(gobj); - if (ret) - return ret; - - args->handle = handle; - return 0; -} - -static void cirrus_bo_unref(struct cirrus_bo **bo) -{ - struct ttm_buffer_object *tbo; - - if ((*bo) == NULL) - return; - - tbo = &((*bo)->bo); - ttm_bo_put(tbo); - *bo = NULL; -} - -void cirrus_gem_free_object(struct drm_gem_object *obj) -{ - struct cirrus_bo *cirrus_bo = gem_to_cirrus_bo(obj); - - cirrus_bo_unref(&cirrus_bo); -} - - -static inline u64 cirrus_bo_mmap_offset(struct cirrus_bo *bo) -{ - return drm_vma_node_offset_addr(&bo->bo.vma_node); -} - -int -cirrus_dumb_mmap_offset(struct drm_file *file, - struct drm_device *dev, - uint32_t handle, - uint64_t *offset) -{ - struct drm_gem_object *obj; - struct cirrus_bo *bo; - - obj = drm_gem_object_lookup(file, handle); - if (obj == NULL) - return -ENOENT; - - bo = gem_to_cirrus_bo(obj); - *offset = cirrus_bo_mmap_offset(bo); - - drm_gem_object_put_unlocked(obj); - - return 0; -} - -bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height, - int bpp, int pitch) -{ - const int max_pitch = 0x1FF << 3; /* (4096 - 1) & ~111b bytes */ - const int max_size = cdev->mc.vram_size; - - if (bpp > cirrus_bpp) - return false; - if (bpp > 32) - return false; - - if (pitch > max_pitch) - return false; - - if (pitch * height > max_size) - return false; - - return true; -} |