1/* 2 * Copyright 2010 Matt Turner. 3 * Copyright 2012 Red Hat 4 * 5 * This file is subject to the terms and conditions of the GNU General 6 * Public License version 2. See the file COPYING in the main 7 * directory of this archive for more details. 8 * 9 * Authors: Matthew Garrett 10 * Matt Turner 11 * Dave Airlie 12 */ 13#include <drm/drmP.h> 14#include <drm/drm_crtc_helper.h> 15#include "mgag200_drv.h" 16 17static void mga_user_framebuffer_destroy(struct drm_framebuffer *fb) 18{ 19 struct mga_framebuffer *mga_fb = to_mga_framebuffer(fb); 20 if (mga_fb->obj) 21 drm_gem_object_unreference_unlocked(mga_fb->obj); 22 drm_framebuffer_cleanup(fb); 23 kfree(fb); 24} 25 26static const struct drm_framebuffer_funcs mga_fb_funcs = { 27 .destroy = mga_user_framebuffer_destroy, 28}; 29 30int mgag200_framebuffer_init(struct drm_device *dev, 31 struct mga_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, &mga_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 * 48mgag200_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 mga_framebuffer *mga_fb; 54 int ret; 55 56 obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]); 57 if (obj == NULL) 58 return ERR_PTR(-ENOENT); 59 60 mga_fb = kzalloc(sizeof(*mga_fb), GFP_KERNEL); 61 if (!mga_fb) { 62 drm_gem_object_unreference_unlocked(obj); 63 return ERR_PTR(-ENOMEM); 64 } 65 66 ret = mgag200_framebuffer_init(dev, mga_fb, mode_cmd, obj); 67 if (ret) { 68 drm_gem_object_unreference_unlocked(obj); 69 kfree(mga_fb); 70 return ERR_PTR(ret); 71 } 72 return &mga_fb->base; 73} 74 75static const struct drm_mode_config_funcs mga_mode_funcs = { 76 .fb_create = mgag200_user_framebuffer_create, 77}; 78 79static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem) 80{ 81 int offset; 82 int orig; 83 int test1, test2; 84 int orig1, orig2; 85 86 /* Probe */ 87 orig = ioread16(mem); 88 iowrite16(0, mem); 89 90 for (offset = 0x100000; offset < mdev->mc.vram_window; offset += 0x4000) { 91 orig1 = ioread8(mem + offset); 92 orig2 = ioread8(mem + offset + 0x100); 93 94 iowrite16(0xaa55, mem + offset); 95 iowrite16(0xaa55, mem + offset + 0x100); 96 97 test1 = ioread16(mem + offset); 98 test2 = ioread16(mem); 99 100 iowrite16(orig1, mem + offset); 101 iowrite16(orig2, mem + offset + 0x100); 102 103 if (test1 != 0xaa55) { 104 break; 105 } 106 107 if (test2) { 108 break; 109 } 110 } 111 112 iowrite16(orig, mem); 113 return offset - 65536; 114} 115 116/* Map the framebuffer from the card and configure the core */ 117static int mga_vram_init(struct mga_device *mdev) 118{ 119 void __iomem *mem; 120 struct apertures_struct *aper = alloc_apertures(1); 121 if (!aper) 122 return -ENOMEM; 123 124 /* BAR 0 is VRAM */ 125 mdev->mc.vram_base = pci_resource_start(mdev->dev->pdev, 0); 126 mdev->mc.vram_window = pci_resource_len(mdev->dev->pdev, 0); 127 128 aper->ranges[0].base = mdev->mc.vram_base; 129 aper->ranges[0].size = mdev->mc.vram_window; 130 131 remove_conflicting_framebuffers(aper, "mgafb", true); 132 kfree(aper); 133 134 if (!devm_request_mem_region(mdev->dev->dev, mdev->mc.vram_base, mdev->mc.vram_window, 135 "mgadrmfb_vram")) { 136 DRM_ERROR("can't reserve VRAM\n"); 137 return -ENXIO; 138 } 139 140 mem = pci_iomap(mdev->dev->pdev, 0, 0); 141 142 mdev->mc.vram_size = mga_probe_vram(mdev, mem); 143 144 pci_iounmap(mdev->dev->pdev, mem); 145 146 return 0; 147} 148 149static int mgag200_device_init(struct drm_device *dev, 150 uint32_t flags) 151{ 152 struct mga_device *mdev = dev->dev_private; 153 int ret, option; 154 155 mdev->type = flags; 156 157 /* Hardcode the number of CRTCs to 1 */ 158 mdev->num_crtc = 1; 159 160 pci_read_config_dword(dev->pdev, PCI_MGA_OPTION, &option); 161 mdev->has_sdram = !(option & (1 << 14)); 162 163 /* BAR 0 is the framebuffer, BAR 1 contains registers */ 164 mdev->rmmio_base = pci_resource_start(mdev->dev->pdev, 1); 165 mdev->rmmio_size = pci_resource_len(mdev->dev->pdev, 1); 166 167 if (!devm_request_mem_region(mdev->dev->dev, mdev->rmmio_base, mdev->rmmio_size, 168 "mgadrmfb_mmio")) { 169 DRM_ERROR("can't reserve mmio registers\n"); 170 return -ENOMEM; 171 } 172 173 mdev->rmmio = pcim_iomap(dev->pdev, 1, 0); 174 if (mdev->rmmio == NULL) 175 return -ENOMEM; 176 177 /* stash G200 SE model number for later use */ 178 if (IS_G200_SE(mdev)) 179 mdev->unique_rev_id = RREG32(0x1e24); 180 181 ret = mga_vram_init(mdev); 182 if (ret) 183 return ret; 184 185 mdev->bpp_shifts[0] = 0; 186 mdev->bpp_shifts[1] = 1; 187 mdev->bpp_shifts[2] = 0; 188 mdev->bpp_shifts[3] = 2; 189 return 0; 190} 191 192/* 193 * Functions here will be called by the core once it's bound the driver to 194 * a PCI device 195 */ 196 197 198int mgag200_driver_load(struct drm_device *dev, unsigned long flags) 199{ 200 struct mga_device *mdev; 201 int r; 202 203 mdev = devm_kzalloc(dev->dev, sizeof(struct mga_device), GFP_KERNEL); 204 if (mdev == NULL) 205 return -ENOMEM; 206 dev->dev_private = (void *)mdev; 207 mdev->dev = dev; 208 209 r = mgag200_device_init(dev, flags); 210 if (r) { 211 dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r); 212 return r; 213 } 214 r = mgag200_mm_init(mdev); 215 if (r) 216 goto out; 217 218 drm_mode_config_init(dev); 219 dev->mode_config.funcs = (void *)&mga_mode_funcs; 220 if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024)) 221 dev->mode_config.preferred_depth = 16; 222 else 223 dev->mode_config.preferred_depth = 24; 224 dev->mode_config.prefer_shadow = 1; 225 226 r = mgag200_modeset_init(mdev); 227 if (r) { 228 dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r); 229 goto out; 230 } 231 232 /* Make small buffers to store a hardware cursor (double buffered icon updates) */ 233 mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0, 234 &mdev->cursor.pixels_1); 235 mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0, 236 &mdev->cursor.pixels_2); 237 if (!mdev->cursor.pixels_2 || !mdev->cursor.pixels_1) 238 goto cursor_nospace; 239 mdev->cursor.pixels_current = mdev->cursor.pixels_1; 240 mdev->cursor.pixels_prev = mdev->cursor.pixels_2; 241 goto cursor_done; 242 cursor_nospace: 243 mdev->cursor.pixels_1 = NULL; 244 mdev->cursor.pixels_2 = NULL; 245 dev_warn(&dev->pdev->dev, "Could not allocate space for cursors. Not doing hardware cursors.\n"); 246 cursor_done: 247 248out: 249 if (r) 250 mgag200_driver_unload(dev); 251 return r; 252} 253 254int mgag200_driver_unload(struct drm_device *dev) 255{ 256 struct mga_device *mdev = dev->dev_private; 257 258 if (mdev == NULL) 259 return 0; 260 mgag200_modeset_fini(mdev); 261 mgag200_fbdev_fini(mdev); 262 drm_mode_config_cleanup(dev); 263 mgag200_mm_fini(mdev); 264 dev->dev_private = NULL; 265 return 0; 266} 267 268int mgag200_gem_create(struct drm_device *dev, 269 u32 size, bool iskernel, 270 struct drm_gem_object **obj) 271{ 272 struct mgag200_bo *astbo; 273 int ret; 274 275 *obj = NULL; 276 277 size = roundup(size, PAGE_SIZE); 278 if (size == 0) 279 return -EINVAL; 280 281 ret = mgag200_bo_create(dev, size, 0, 0, &astbo); 282 if (ret) { 283 if (ret != -ERESTARTSYS) 284 DRM_ERROR("failed to allocate GEM object\n"); 285 return ret; 286 } 287 *obj = &astbo->gem; 288 return 0; 289} 290 291int mgag200_dumb_create(struct drm_file *file, 292 struct drm_device *dev, 293 struct drm_mode_create_dumb *args) 294{ 295 int ret; 296 struct drm_gem_object *gobj; 297 u32 handle; 298 299 args->pitch = args->width * ((args->bpp + 7) / 8); 300 args->size = args->pitch * args->height; 301 302 ret = mgag200_gem_create(dev, args->size, false, 303 &gobj); 304 if (ret) 305 return ret; 306 307 ret = drm_gem_handle_create(file, gobj, &handle); 308 drm_gem_object_unreference_unlocked(gobj); 309 if (ret) 310 return ret; 311 312 args->handle = handle; 313 return 0; 314} 315 316static void mgag200_bo_unref(struct mgag200_bo **bo) 317{ 318 struct ttm_buffer_object *tbo; 319 320 if ((*bo) == NULL) 321 return; 322 323 tbo = &((*bo)->bo); 324 ttm_bo_unref(&tbo); 325 *bo = NULL; 326} 327 328void mgag200_gem_free_object(struct drm_gem_object *obj) 329{ 330 struct mgag200_bo *mgag200_bo = gem_to_mga_bo(obj); 331 332 mgag200_bo_unref(&mgag200_bo); 333} 334 335 336static inline u64 mgag200_bo_mmap_offset(struct mgag200_bo *bo) 337{ 338 return drm_vma_node_offset_addr(&bo->bo.vma_node); 339} 340 341int 342mgag200_dumb_mmap_offset(struct drm_file *file, 343 struct drm_device *dev, 344 uint32_t handle, 345 uint64_t *offset) 346{ 347 struct drm_gem_object *obj; 348 int ret; 349 struct mgag200_bo *bo; 350 351 mutex_lock(&dev->struct_mutex); 352 obj = drm_gem_object_lookup(dev, file, handle); 353 if (obj == NULL) { 354 ret = -ENOENT; 355 goto out_unlock; 356 } 357 358 bo = gem_to_mga_bo(obj); 359 *offset = mgag200_bo_mmap_offset(bo); 360 361 drm_gem_object_unreference(obj); 362 ret = 0; 363out_unlock: 364 mutex_unlock(&dev->struct_mutex); 365 return ret; 366 367} 368