Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.10-rc1 370 lines 8.4 kB view raw
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 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 const 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 const 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(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 unsigned int vram_size; 86 87 /* Probe */ 88 orig = ioread16(mem); 89 iowrite16(0, mem); 90 91 vram_size = mdev->mc.vram_window; 92 93 if ((mdev->type == G200_EW3) && (vram_size >= 0x1000000)) { 94 vram_size = vram_size - 0x400000; 95 } 96 97 for (offset = 0x100000; offset < vram_size; offset += 0x4000) { 98 orig1 = ioread8(mem + offset); 99 orig2 = ioread8(mem + offset + 0x100); 100 101 iowrite16(0xaa55, mem + offset); 102 iowrite16(0xaa55, mem + offset + 0x100); 103 104 test1 = ioread16(mem + offset); 105 test2 = ioread16(mem); 106 107 iowrite16(orig1, mem + offset); 108 iowrite16(orig2, mem + offset + 0x100); 109 110 if (test1 != 0xaa55) { 111 break; 112 } 113 114 if (test2) { 115 break; 116 } 117 } 118 119 iowrite16(orig, mem); 120 return offset - 65536; 121} 122 123/* Map the framebuffer from the card and configure the core */ 124static int mga_vram_init(struct mga_device *mdev) 125{ 126 void __iomem *mem; 127 struct apertures_struct *aper = alloc_apertures(1); 128 if (!aper) 129 return -ENOMEM; 130 131 /* BAR 0 is VRAM */ 132 mdev->mc.vram_base = pci_resource_start(mdev->dev->pdev, 0); 133 mdev->mc.vram_window = pci_resource_len(mdev->dev->pdev, 0); 134 135 aper->ranges[0].base = mdev->mc.vram_base; 136 aper->ranges[0].size = mdev->mc.vram_window; 137 138 drm_fb_helper_remove_conflicting_framebuffers(aper, "mgafb", true); 139 kfree(aper); 140 141 if (!devm_request_mem_region(mdev->dev->dev, mdev->mc.vram_base, mdev->mc.vram_window, 142 "mgadrmfb_vram")) { 143 DRM_ERROR("can't reserve VRAM\n"); 144 return -ENXIO; 145 } 146 147 mem = pci_iomap(mdev->dev->pdev, 0, 0); 148 149 mdev->mc.vram_size = mga_probe_vram(mdev, mem); 150 151 pci_iounmap(mdev->dev->pdev, mem); 152 153 return 0; 154} 155 156static int mgag200_device_init(struct drm_device *dev, 157 uint32_t flags) 158{ 159 struct mga_device *mdev = dev->dev_private; 160 int ret, option; 161 162 mdev->type = flags; 163 164 /* Hardcode the number of CRTCs to 1 */ 165 mdev->num_crtc = 1; 166 167 pci_read_config_dword(dev->pdev, PCI_MGA_OPTION, &option); 168 mdev->has_sdram = !(option & (1 << 14)); 169 170 /* BAR 0 is the framebuffer, BAR 1 contains registers */ 171 mdev->rmmio_base = pci_resource_start(mdev->dev->pdev, 1); 172 mdev->rmmio_size = pci_resource_len(mdev->dev->pdev, 1); 173 174 if (!devm_request_mem_region(mdev->dev->dev, mdev->rmmio_base, mdev->rmmio_size, 175 "mgadrmfb_mmio")) { 176 DRM_ERROR("can't reserve mmio registers\n"); 177 return -ENOMEM; 178 } 179 180 mdev->rmmio = pcim_iomap(dev->pdev, 1, 0); 181 if (mdev->rmmio == NULL) 182 return -ENOMEM; 183 184 /* stash G200 SE model number for later use */ 185 if (IS_G200_SE(mdev)) 186 mdev->unique_rev_id = RREG32(0x1e24); 187 188 ret = mga_vram_init(mdev); 189 if (ret) 190 return ret; 191 192 mdev->bpp_shifts[0] = 0; 193 mdev->bpp_shifts[1] = 1; 194 mdev->bpp_shifts[2] = 0; 195 mdev->bpp_shifts[3] = 2; 196 return 0; 197} 198 199/* 200 * Functions here will be called by the core once it's bound the driver to 201 * a PCI device 202 */ 203 204 205int mgag200_driver_load(struct drm_device *dev, unsigned long flags) 206{ 207 struct mga_device *mdev; 208 int r; 209 210 mdev = devm_kzalloc(dev->dev, sizeof(struct mga_device), GFP_KERNEL); 211 if (mdev == NULL) 212 return -ENOMEM; 213 dev->dev_private = (void *)mdev; 214 mdev->dev = dev; 215 216 r = mgag200_device_init(dev, flags); 217 if (r) { 218 dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r); 219 return r; 220 } 221 r = mgag200_mm_init(mdev); 222 if (r) 223 goto err_mm; 224 225 drm_mode_config_init(dev); 226 dev->mode_config.funcs = (void *)&mga_mode_funcs; 227 if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024)) 228 dev->mode_config.preferred_depth = 16; 229 else 230 dev->mode_config.preferred_depth = 24; 231 dev->mode_config.prefer_shadow = 1; 232 233 r = mgag200_modeset_init(mdev); 234 if (r) { 235 dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r); 236 goto err_modeset; 237 } 238 239 /* Make small buffers to store a hardware cursor (double buffered icon updates) */ 240 mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0, 241 &mdev->cursor.pixels_1); 242 mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0, 243 &mdev->cursor.pixels_2); 244 if (!mdev->cursor.pixels_2 || !mdev->cursor.pixels_1) { 245 mdev->cursor.pixels_1 = NULL; 246 mdev->cursor.pixels_2 = NULL; 247 dev_warn(&dev->pdev->dev, 248 "Could not allocate space for cursors. Not doing hardware cursors.\n"); 249 } else { 250 mdev->cursor.pixels_current = mdev->cursor.pixels_1; 251 mdev->cursor.pixels_prev = mdev->cursor.pixels_2; 252 } 253 254 return 0; 255 256err_modeset: 257 drm_mode_config_cleanup(dev); 258 mgag200_mm_fini(mdev); 259err_mm: 260 dev->dev_private = NULL; 261 262 return r; 263} 264 265int mgag200_driver_unload(struct drm_device *dev) 266{ 267 struct mga_device *mdev = dev->dev_private; 268 269 if (mdev == NULL) 270 return 0; 271 mgag200_modeset_fini(mdev); 272 mgag200_fbdev_fini(mdev); 273 drm_mode_config_cleanup(dev); 274 mgag200_mm_fini(mdev); 275 dev->dev_private = NULL; 276 return 0; 277} 278 279int mgag200_gem_create(struct drm_device *dev, 280 u32 size, bool iskernel, 281 struct drm_gem_object **obj) 282{ 283 struct mgag200_bo *astbo; 284 int ret; 285 286 *obj = NULL; 287 288 size = roundup(size, PAGE_SIZE); 289 if (size == 0) 290 return -EINVAL; 291 292 ret = mgag200_bo_create(dev, size, 0, 0, &astbo); 293 if (ret) { 294 if (ret != -ERESTARTSYS) 295 DRM_ERROR("failed to allocate GEM object\n"); 296 return ret; 297 } 298 *obj = &astbo->gem; 299 return 0; 300} 301 302int mgag200_dumb_create(struct drm_file *file, 303 struct drm_device *dev, 304 struct drm_mode_create_dumb *args) 305{ 306 int ret; 307 struct drm_gem_object *gobj; 308 u32 handle; 309 310 args->pitch = args->width * ((args->bpp + 7) / 8); 311 args->size = args->pitch * args->height; 312 313 ret = mgag200_gem_create(dev, args->size, false, 314 &gobj); 315 if (ret) 316 return ret; 317 318 ret = drm_gem_handle_create(file, gobj, &handle); 319 drm_gem_object_unreference_unlocked(gobj); 320 if (ret) 321 return ret; 322 323 args->handle = handle; 324 return 0; 325} 326 327static void mgag200_bo_unref(struct mgag200_bo **bo) 328{ 329 struct ttm_buffer_object *tbo; 330 331 if ((*bo) == NULL) 332 return; 333 334 tbo = &((*bo)->bo); 335 ttm_bo_unref(&tbo); 336 *bo = NULL; 337} 338 339void mgag200_gem_free_object(struct drm_gem_object *obj) 340{ 341 struct mgag200_bo *mgag200_bo = gem_to_mga_bo(obj); 342 343 mgag200_bo_unref(&mgag200_bo); 344} 345 346 347static inline u64 mgag200_bo_mmap_offset(struct mgag200_bo *bo) 348{ 349 return drm_vma_node_offset_addr(&bo->bo.vma_node); 350} 351 352int 353mgag200_dumb_mmap_offset(struct drm_file *file, 354 struct drm_device *dev, 355 uint32_t handle, 356 uint64_t *offset) 357{ 358 struct drm_gem_object *obj; 359 struct mgag200_bo *bo; 360 361 obj = drm_gem_object_lookup(file, handle); 362 if (obj == NULL) 363 return -ENOENT; 364 365 bo = gem_to_mga_bo(obj); 366 *offset = mgag200_bo_mmap_offset(bo); 367 368 drm_gem_object_unreference_unlocked(obj); 369 return 0; 370}