1/* 2 * Copyright 2012 Red Hat 3 * 4 * This file is subject to the terms and conditions of the GNU General 5 * Public License version 2. See the file COPYING in the main 6 * directory of this archive for more details. 7 * 8 * Authors: Matthew Garrett 9 * Dave Airlie 10 */ 11#include <drm/drmP.h> 12#include <drm/drm_crtc_helper.h> 13 14#include "cirrus_drv.h" 15 16 17static void cirrus_user_framebuffer_destroy(struct drm_framebuffer *fb) 18{ 19 struct cirrus_framebuffer *cirrus_fb = to_cirrus_framebuffer(fb); 20 if (cirrus_fb->obj) 21 drm_gem_object_unreference_unlocked(cirrus_fb->obj); 22 drm_framebuffer_cleanup(fb); 23 kfree(fb); 24} 25 26static const struct drm_framebuffer_funcs cirrus_fb_funcs = { 27 .destroy = cirrus_user_framebuffer_destroy, 28}; 29 30int cirrus_framebuffer_init(struct drm_device *dev, 31 struct cirrus_framebuffer *gfb, 32 struct drm_mode_fb_cmd2 *mode_cmd, 33 struct drm_gem_object *obj) 34{ 35 int ret; 36 37 drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd); 38 gfb->obj = obj; 39 ret = drm_framebuffer_init(dev, &gfb->base, &cirrus_fb_funcs); 40 if (ret) { 41 DRM_ERROR("drm_framebuffer_init failed: %d\n", ret); 42 return ret; 43 } 44 return 0; 45} 46 47static struct drm_framebuffer * 48cirrus_user_framebuffer_create(struct drm_device *dev, 49 struct drm_file *filp, 50 struct drm_mode_fb_cmd2 *mode_cmd) 51{ 52 struct drm_gem_object *obj; 53 struct cirrus_framebuffer *cirrus_fb; 54 int ret; 55 u32 bpp, depth; 56 57 drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); 58 /* cirrus can't handle > 24bpp framebuffers at all */ 59 if (bpp > 24) 60 return ERR_PTR(-EINVAL); 61 62 obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]); 63 if (obj == NULL) 64 return ERR_PTR(-ENOENT); 65 66 cirrus_fb = kzalloc(sizeof(*cirrus_fb), GFP_KERNEL); 67 if (!cirrus_fb) { 68 drm_gem_object_unreference_unlocked(obj); 69 return ERR_PTR(-ENOMEM); 70 } 71 72 ret = cirrus_framebuffer_init(dev, cirrus_fb, mode_cmd, obj); 73 if (ret) { 74 drm_gem_object_unreference_unlocked(obj); 75 kfree(cirrus_fb); 76 return ERR_PTR(ret); 77 } 78 return &cirrus_fb->base; 79} 80 81static const struct drm_mode_config_funcs cirrus_mode_funcs = { 82 .fb_create = cirrus_user_framebuffer_create, 83}; 84 85/* Unmap the framebuffer from the core and release the memory */ 86static void cirrus_vram_fini(struct cirrus_device *cdev) 87{ 88 iounmap(cdev->rmmio); 89 cdev->rmmio = NULL; 90 if (cdev->mc.vram_base) 91 release_mem_region(cdev->mc.vram_base, cdev->mc.vram_size); 92} 93 94/* Map the framebuffer from the card and configure the core */ 95static int cirrus_vram_init(struct cirrus_device *cdev) 96{ 97 /* BAR 0 is VRAM */ 98 cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0); 99 /* We have 4MB of VRAM */ 100 cdev->mc.vram_size = 4 * 1024 * 1024; 101 102 if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size, 103 "cirrusdrmfb_vram")) { 104 DRM_ERROR("can't reserve VRAM\n"); 105 return -ENXIO; 106 } 107 108 return 0; 109} 110 111/* 112 * Our emulated hardware has two sets of memory. One is video RAM and can 113 * simply be used as a linear framebuffer - the other provides mmio access 114 * to the display registers. The latter can also be accessed via IO port 115 * access, but we map the range and use mmio to program them instead 116 */ 117 118int cirrus_device_init(struct cirrus_device *cdev, 119 struct drm_device *ddev, 120 struct pci_dev *pdev, uint32_t flags) 121{ 122 int ret; 123 124 cdev->dev = ddev; 125 cdev->flags = flags; 126 127 /* Hardcode the number of CRTCs to 1 */ 128 cdev->num_crtc = 1; 129 130 /* BAR 0 is the framebuffer, BAR 1 contains registers */ 131 cdev->rmmio_base = pci_resource_start(cdev->dev->pdev, 1); 132 cdev->rmmio_size = pci_resource_len(cdev->dev->pdev, 1); 133 134 if (!request_mem_region(cdev->rmmio_base, cdev->rmmio_size, 135 "cirrusdrmfb_mmio")) { 136 DRM_ERROR("can't reserve mmio registers\n"); 137 return -ENOMEM; 138 } 139 140 cdev->rmmio = ioremap(cdev->rmmio_base, cdev->rmmio_size); 141 142 if (cdev->rmmio == NULL) 143 return -ENOMEM; 144 145 ret = cirrus_vram_init(cdev); 146 if (ret) { 147 release_mem_region(cdev->rmmio_base, cdev->rmmio_size); 148 return ret; 149 } 150 151 return 0; 152} 153 154void cirrus_device_fini(struct cirrus_device *cdev) 155{ 156 release_mem_region(cdev->rmmio_base, cdev->rmmio_size); 157 cirrus_vram_fini(cdev); 158} 159 160/* 161 * Functions here will be called by the core once it's bound the driver to 162 * a PCI device 163 */ 164 165int cirrus_driver_load(struct drm_device *dev, unsigned long flags) 166{ 167 struct cirrus_device *cdev; 168 int r; 169 170 cdev = kzalloc(sizeof(struct cirrus_device), GFP_KERNEL); 171 if (cdev == NULL) 172 return -ENOMEM; 173 dev->dev_private = (void *)cdev; 174 175 r = cirrus_device_init(cdev, dev, dev->pdev, flags); 176 if (r) { 177 dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r); 178 goto out; 179 } 180 181 r = cirrus_mm_init(cdev); 182 if (r) 183 dev_err(&dev->pdev->dev, "fatal err on mm init\n"); 184 185 r = cirrus_modeset_init(cdev); 186 if (r) 187 dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r); 188 189 dev->mode_config.funcs = (void *)&cirrus_mode_funcs; 190out: 191 if (r) 192 cirrus_driver_unload(dev); 193 return r; 194} 195 196int cirrus_driver_unload(struct drm_device *dev) 197{ 198 struct cirrus_device *cdev = dev->dev_private; 199 200 if (cdev == NULL) 201 return 0; 202 cirrus_modeset_fini(cdev); 203 cirrus_mm_fini(cdev); 204 cirrus_device_fini(cdev); 205 kfree(cdev); 206 dev->dev_private = NULL; 207 return 0; 208} 209 210int cirrus_gem_create(struct drm_device *dev, 211 u32 size, bool iskernel, 212 struct drm_gem_object **obj) 213{ 214 struct cirrus_bo *cirrusbo; 215 int ret; 216 217 *obj = NULL; 218 219 size = roundup(size, PAGE_SIZE); 220 if (size == 0) 221 return -EINVAL; 222 223 ret = cirrus_bo_create(dev, size, 0, 0, &cirrusbo); 224 if (ret) { 225 if (ret != -ERESTARTSYS) 226 DRM_ERROR("failed to allocate GEM object\n"); 227 return ret; 228 } 229 *obj = &cirrusbo->gem; 230 return 0; 231} 232 233int cirrus_dumb_create(struct drm_file *file, 234 struct drm_device *dev, 235 struct drm_mode_create_dumb *args) 236{ 237 int ret; 238 struct drm_gem_object *gobj; 239 u32 handle; 240 241 args->pitch = args->width * ((args->bpp + 7) / 8); 242 args->size = args->pitch * args->height; 243 244 ret = cirrus_gem_create(dev, args->size, false, 245 &gobj); 246 if (ret) 247 return ret; 248 249 ret = drm_gem_handle_create(file, gobj, &handle); 250 drm_gem_object_unreference_unlocked(gobj); 251 if (ret) 252 return ret; 253 254 args->handle = handle; 255 return 0; 256} 257 258static void cirrus_bo_unref(struct cirrus_bo **bo) 259{ 260 struct ttm_buffer_object *tbo; 261 262 if ((*bo) == NULL) 263 return; 264 265 tbo = &((*bo)->bo); 266 ttm_bo_unref(&tbo); 267 *bo = NULL; 268} 269 270void cirrus_gem_free_object(struct drm_gem_object *obj) 271{ 272 struct cirrus_bo *cirrus_bo = gem_to_cirrus_bo(obj); 273 274 cirrus_bo_unref(&cirrus_bo); 275} 276 277 278static inline u64 cirrus_bo_mmap_offset(struct cirrus_bo *bo) 279{ 280 return drm_vma_node_offset_addr(&bo->bo.vma_node); 281} 282 283int 284cirrus_dumb_mmap_offset(struct drm_file *file, 285 struct drm_device *dev, 286 uint32_t handle, 287 uint64_t *offset) 288{ 289 struct drm_gem_object *obj; 290 int ret; 291 struct cirrus_bo *bo; 292 293 mutex_lock(&dev->struct_mutex); 294 obj = drm_gem_object_lookup(dev, file, handle); 295 if (obj == NULL) { 296 ret = -ENOENT; 297 goto out_unlock; 298 } 299 300 bo = gem_to_cirrus_bo(obj); 301 *offset = cirrus_bo_mmap_offset(bo); 302 303 drm_gem_object_unreference(obj); 304 ret = 0; 305out_unlock: 306 mutex_unlock(&dev->struct_mutex); 307 return ret; 308 309} 310