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.14-rc6 371 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_put_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(dev, &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_put_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_put_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 if (!mem) 149 return -ENOMEM; 150 151 mdev->mc.vram_size = mga_probe_vram(mdev, mem); 152 153 pci_iounmap(mdev->dev->pdev, mem); 154 155 return 0; 156} 157 158static int mgag200_device_init(struct drm_device *dev, 159 uint32_t flags) 160{ 161 struct mga_device *mdev = dev->dev_private; 162 int ret, option; 163 164 mdev->type = flags; 165 166 /* Hardcode the number of CRTCs to 1 */ 167 mdev->num_crtc = 1; 168 169 pci_read_config_dword(dev->pdev, PCI_MGA_OPTION, &option); 170 mdev->has_sdram = !(option & (1 << 14)); 171 172 /* BAR 0 is the framebuffer, BAR 1 contains registers */ 173 mdev->rmmio_base = pci_resource_start(mdev->dev->pdev, 1); 174 mdev->rmmio_size = pci_resource_len(mdev->dev->pdev, 1); 175 176 if (!devm_request_mem_region(mdev->dev->dev, mdev->rmmio_base, mdev->rmmio_size, 177 "mgadrmfb_mmio")) { 178 DRM_ERROR("can't reserve mmio registers\n"); 179 return -ENOMEM; 180 } 181 182 mdev->rmmio = pcim_iomap(dev->pdev, 1, 0); 183 if (mdev->rmmio == NULL) 184 return -ENOMEM; 185 186 /* stash G200 SE model number for later use */ 187 if (IS_G200_SE(mdev)) 188 mdev->unique_rev_id = RREG32(0x1e24); 189 190 ret = mga_vram_init(mdev); 191 if (ret) 192 return ret; 193 194 mdev->bpp_shifts[0] = 0; 195 mdev->bpp_shifts[1] = 1; 196 mdev->bpp_shifts[2] = 0; 197 mdev->bpp_shifts[3] = 2; 198 return 0; 199} 200 201/* 202 * Functions here will be called by the core once it's bound the driver to 203 * a PCI device 204 */ 205 206 207int mgag200_driver_load(struct drm_device *dev, unsigned long flags) 208{ 209 struct mga_device *mdev; 210 int r; 211 212 mdev = devm_kzalloc(dev->dev, sizeof(struct mga_device), GFP_KERNEL); 213 if (mdev == NULL) 214 return -ENOMEM; 215 dev->dev_private = (void *)mdev; 216 mdev->dev = dev; 217 218 r = mgag200_device_init(dev, flags); 219 if (r) { 220 dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r); 221 return r; 222 } 223 r = mgag200_mm_init(mdev); 224 if (r) 225 goto err_mm; 226 227 drm_mode_config_init(dev); 228 dev->mode_config.funcs = (void *)&mga_mode_funcs; 229 if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024)) 230 dev->mode_config.preferred_depth = 16; 231 else 232 dev->mode_config.preferred_depth = 24; 233 dev->mode_config.prefer_shadow = 1; 234 235 r = mgag200_modeset_init(mdev); 236 if (r) { 237 dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r); 238 goto err_modeset; 239 } 240 241 /* Make small buffers to store a hardware cursor (double buffered icon updates) */ 242 mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0, 243 &mdev->cursor.pixels_1); 244 mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0, 245 &mdev->cursor.pixels_2); 246 if (!mdev->cursor.pixels_2 || !mdev->cursor.pixels_1) { 247 mdev->cursor.pixels_1 = NULL; 248 mdev->cursor.pixels_2 = NULL; 249 dev_warn(&dev->pdev->dev, 250 "Could not allocate space for cursors. Not doing hardware cursors.\n"); 251 } else { 252 mdev->cursor.pixels_current = mdev->cursor.pixels_1; 253 mdev->cursor.pixels_prev = mdev->cursor.pixels_2; 254 } 255 256 return 0; 257 258err_modeset: 259 drm_mode_config_cleanup(dev); 260 mgag200_mm_fini(mdev); 261err_mm: 262 dev->dev_private = NULL; 263 264 return r; 265} 266 267void mgag200_driver_unload(struct drm_device *dev) 268{ 269 struct mga_device *mdev = dev->dev_private; 270 271 if (mdev == NULL) 272 return; 273 mgag200_modeset_fini(mdev); 274 mgag200_fbdev_fini(mdev); 275 drm_mode_config_cleanup(dev); 276 mgag200_mm_fini(mdev); 277 dev->dev_private = NULL; 278} 279 280int mgag200_gem_create(struct drm_device *dev, 281 u32 size, bool iskernel, 282 struct drm_gem_object **obj) 283{ 284 struct mgag200_bo *astbo; 285 int ret; 286 287 *obj = NULL; 288 289 size = roundup(size, PAGE_SIZE); 290 if (size == 0) 291 return -EINVAL; 292 293 ret = mgag200_bo_create(dev, size, 0, 0, &astbo); 294 if (ret) { 295 if (ret != -ERESTARTSYS) 296 DRM_ERROR("failed to allocate GEM object\n"); 297 return ret; 298 } 299 *obj = &astbo->gem; 300 return 0; 301} 302 303int mgag200_dumb_create(struct drm_file *file, 304 struct drm_device *dev, 305 struct drm_mode_create_dumb *args) 306{ 307 int ret; 308 struct drm_gem_object *gobj; 309 u32 handle; 310 311 args->pitch = args->width * ((args->bpp + 7) / 8); 312 args->size = args->pitch * args->height; 313 314 ret = mgag200_gem_create(dev, args->size, false, 315 &gobj); 316 if (ret) 317 return ret; 318 319 ret = drm_gem_handle_create(file, gobj, &handle); 320 drm_gem_object_put_unlocked(gobj); 321 if (ret) 322 return ret; 323 324 args->handle = handle; 325 return 0; 326} 327 328static void mgag200_bo_unref(struct mgag200_bo **bo) 329{ 330 struct ttm_buffer_object *tbo; 331 332 if ((*bo) == NULL) 333 return; 334 335 tbo = &((*bo)->bo); 336 ttm_bo_unref(&tbo); 337 *bo = NULL; 338} 339 340void mgag200_gem_free_object(struct drm_gem_object *obj) 341{ 342 struct mgag200_bo *mgag200_bo = gem_to_mga_bo(obj); 343 344 mgag200_bo_unref(&mgag200_bo); 345} 346 347 348static inline u64 mgag200_bo_mmap_offset(struct mgag200_bo *bo) 349{ 350 return drm_vma_node_offset_addr(&bo->bo.vma_node); 351} 352 353int 354mgag200_dumb_mmap_offset(struct drm_file *file, 355 struct drm_device *dev, 356 uint32_t handle, 357 uint64_t *offset) 358{ 359 struct drm_gem_object *obj; 360 struct mgag200_bo *bo; 361 362 obj = drm_gem_object_lookup(file, handle); 363 if (obj == NULL) 364 return -ENOENT; 365 366 bo = gem_to_mga_bo(obj); 367 *offset = mgag200_bo_mmap_offset(bo); 368 369 drm_gem_object_put_unlocked(obj); 370 return 0; 371}