cirrus_main.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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. #include <drm/drm_gem_framebuffer_helper.h>
  14. #include "cirrus_drv.h"
  15. static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
  16. .create_handle = drm_gem_fb_create_handle,
  17. .destroy = drm_gem_fb_destroy,
  18. };
  19. int cirrus_framebuffer_init(struct drm_device *dev,
  20. struct drm_framebuffer *gfb,
  21. const struct drm_mode_fb_cmd2 *mode_cmd,
  22. struct drm_gem_object *obj)
  23. {
  24. int ret;
  25. drm_helper_mode_fill_fb_struct(dev, gfb, mode_cmd);
  26. gfb->obj[0] = obj;
  27. ret = drm_framebuffer_init(dev, gfb, &cirrus_fb_funcs);
  28. if (ret) {
  29. DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
  30. return ret;
  31. }
  32. return 0;
  33. }
  34. static struct drm_framebuffer *
  35. cirrus_user_framebuffer_create(struct drm_device *dev,
  36. struct drm_file *filp,
  37. const struct drm_mode_fb_cmd2 *mode_cmd)
  38. {
  39. struct cirrus_device *cdev = dev->dev_private;
  40. struct drm_gem_object *obj;
  41. struct drm_framebuffer *fb;
  42. u32 bpp;
  43. int ret;
  44. bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8;
  45. if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
  46. bpp, mode_cmd->pitches[0]))
  47. return ERR_PTR(-EINVAL);
  48. obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
  49. if (obj == NULL)
  50. return ERR_PTR(-ENOENT);
  51. fb = kzalloc(sizeof(*fb), GFP_KERNEL);
  52. if (!fb) {
  53. drm_gem_object_put_unlocked(obj);
  54. return ERR_PTR(-ENOMEM);
  55. }
  56. ret = cirrus_framebuffer_init(dev, fb, mode_cmd, obj);
  57. if (ret) {
  58. drm_gem_object_put_unlocked(obj);
  59. kfree(fb);
  60. return ERR_PTR(ret);
  61. }
  62. return fb;
  63. }
  64. static const struct drm_mode_config_funcs cirrus_mode_funcs = {
  65. .fb_create = cirrus_user_framebuffer_create,
  66. };
  67. /* Unmap the framebuffer from the core and release the memory */
  68. static void cirrus_vram_fini(struct cirrus_device *cdev)
  69. {
  70. iounmap(cdev->rmmio);
  71. cdev->rmmio = NULL;
  72. if (cdev->mc.vram_base)
  73. release_mem_region(cdev->mc.vram_base, cdev->mc.vram_size);
  74. }
  75. /* Map the framebuffer from the card and configure the core */
  76. static int cirrus_vram_init(struct cirrus_device *cdev)
  77. {
  78. /* BAR 0 is VRAM */
  79. cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0);
  80. cdev->mc.vram_size = pci_resource_len(cdev->dev->pdev, 0);
  81. if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size,
  82. "cirrusdrmfb_vram")) {
  83. DRM_ERROR("can't reserve VRAM\n");
  84. return -ENXIO;
  85. }
  86. return 0;
  87. }
  88. /*
  89. * Our emulated hardware has two sets of memory. One is video RAM and can
  90. * simply be used as a linear framebuffer - the other provides mmio access
  91. * to the display registers. The latter can also be accessed via IO port
  92. * access, but we map the range and use mmio to program them instead
  93. */
  94. int cirrus_device_init(struct cirrus_device *cdev,
  95. struct drm_device *ddev,
  96. struct pci_dev *pdev, uint32_t flags)
  97. {
  98. int ret;
  99. cdev->dev = ddev;
  100. cdev->flags = flags;
  101. /* Hardcode the number of CRTCs to 1 */
  102. cdev->num_crtc = 1;
  103. /* BAR 0 is the framebuffer, BAR 1 contains registers */
  104. cdev->rmmio_base = pci_resource_start(cdev->dev->pdev, 1);
  105. cdev->rmmio_size = pci_resource_len(cdev->dev->pdev, 1);
  106. if (!request_mem_region(cdev->rmmio_base, cdev->rmmio_size,
  107. "cirrusdrmfb_mmio")) {
  108. DRM_ERROR("can't reserve mmio registers\n");
  109. return -ENOMEM;
  110. }
  111. cdev->rmmio = ioremap(cdev->rmmio_base, cdev->rmmio_size);
  112. if (cdev->rmmio == NULL)
  113. return -ENOMEM;
  114. ret = cirrus_vram_init(cdev);
  115. if (ret) {
  116. release_mem_region(cdev->rmmio_base, cdev->rmmio_size);
  117. return ret;
  118. }
  119. return 0;
  120. }
  121. void cirrus_device_fini(struct cirrus_device *cdev)
  122. {
  123. release_mem_region(cdev->rmmio_base, cdev->rmmio_size);
  124. cirrus_vram_fini(cdev);
  125. }
  126. /*
  127. * Functions here will be called by the core once it's bound the driver to
  128. * a PCI device
  129. */
  130. int cirrus_driver_load(struct drm_device *dev, unsigned long flags)
  131. {
  132. struct cirrus_device *cdev;
  133. int r;
  134. cdev = kzalloc(sizeof(struct cirrus_device), GFP_KERNEL);
  135. if (cdev == NULL)
  136. return -ENOMEM;
  137. dev->dev_private = (void *)cdev;
  138. r = cirrus_device_init(cdev, dev, dev->pdev, flags);
  139. if (r) {
  140. dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r);
  141. goto out;
  142. }
  143. r = cirrus_mm_init(cdev);
  144. if (r) {
  145. dev_err(&dev->pdev->dev, "fatal err on mm init\n");
  146. goto out;
  147. }
  148. /*
  149. * cirrus_modeset_init() is initializing/registering the emulated fbdev
  150. * and DRM internals can access/test some of the fields in
  151. * mode_config->funcs as part of the fbdev registration process.
  152. * Make sure dev->mode_config.funcs is properly set to avoid
  153. * dereferencing a NULL pointer.
  154. * FIXME: mode_config.funcs assignment should probably be done in
  155. * cirrus_modeset_init() (that's a common pattern seen in other DRM
  156. * drivers).
  157. */
  158. dev->mode_config.funcs = &cirrus_mode_funcs;
  159. r = cirrus_modeset_init(cdev);
  160. if (r) {
  161. dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r);
  162. goto out;
  163. }
  164. return 0;
  165. out:
  166. cirrus_driver_unload(dev);
  167. return r;
  168. }
  169. void cirrus_driver_unload(struct drm_device *dev)
  170. {
  171. struct cirrus_device *cdev = dev->dev_private;
  172. if (cdev == NULL)
  173. return;
  174. cirrus_modeset_fini(cdev);
  175. cirrus_mm_fini(cdev);
  176. cirrus_device_fini(cdev);
  177. kfree(cdev);
  178. dev->dev_private = NULL;
  179. }
  180. int cirrus_gem_create(struct drm_device *dev,
  181. u32 size, bool iskernel,
  182. struct drm_gem_object **obj)
  183. {
  184. struct cirrus_bo *cirrusbo;
  185. int ret;
  186. *obj = NULL;
  187. size = roundup(size, PAGE_SIZE);
  188. if (size == 0)
  189. return -EINVAL;
  190. ret = cirrus_bo_create(dev, size, 0, 0, &cirrusbo);
  191. if (ret) {
  192. if (ret != -ERESTARTSYS)
  193. DRM_ERROR("failed to allocate GEM object\n");
  194. return ret;
  195. }
  196. *obj = &cirrusbo->gem;
  197. return 0;
  198. }
  199. int cirrus_dumb_create(struct drm_file *file,
  200. struct drm_device *dev,
  201. struct drm_mode_create_dumb *args)
  202. {
  203. int ret;
  204. struct drm_gem_object *gobj;
  205. u32 handle;
  206. args->pitch = args->width * ((args->bpp + 7) / 8);
  207. args->size = args->pitch * args->height;
  208. ret = cirrus_gem_create(dev, args->size, false,
  209. &gobj);
  210. if (ret)
  211. return ret;
  212. ret = drm_gem_handle_create(file, gobj, &handle);
  213. drm_gem_object_put_unlocked(gobj);
  214. if (ret)
  215. return ret;
  216. args->handle = handle;
  217. return 0;
  218. }
  219. static void cirrus_bo_unref(struct cirrus_bo **bo)
  220. {
  221. struct ttm_buffer_object *tbo;
  222. if ((*bo) == NULL)
  223. return;
  224. tbo = &((*bo)->bo);
  225. ttm_bo_put(tbo);
  226. *bo = NULL;
  227. }
  228. void cirrus_gem_free_object(struct drm_gem_object *obj)
  229. {
  230. struct cirrus_bo *cirrus_bo = gem_to_cirrus_bo(obj);
  231. cirrus_bo_unref(&cirrus_bo);
  232. }
  233. static inline u64 cirrus_bo_mmap_offset(struct cirrus_bo *bo)
  234. {
  235. return drm_vma_node_offset_addr(&bo->bo.vma_node);
  236. }
  237. int
  238. cirrus_dumb_mmap_offset(struct drm_file *file,
  239. struct drm_device *dev,
  240. uint32_t handle,
  241. uint64_t *offset)
  242. {
  243. struct drm_gem_object *obj;
  244. struct cirrus_bo *bo;
  245. obj = drm_gem_object_lookup(file, handle);
  246. if (obj == NULL)
  247. return -ENOENT;
  248. bo = gem_to_cirrus_bo(obj);
  249. *offset = cirrus_bo_mmap_offset(bo);
  250. drm_gem_object_put_unlocked(obj);
  251. return 0;
  252. }
  253. bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
  254. int bpp, int pitch)
  255. {
  256. const int max_pitch = 0x1FF << 3; /* (4096 - 1) & ~111b bytes */
  257. const int max_size = cdev->mc.vram_size;
  258. if (bpp > cirrus_bpp)
  259. return false;
  260. if (bpp > 32)
  261. return false;
  262. if (pitch > max_pitch)
  263. return false;
  264. if (pitch * height > max_size)
  265. return false;
  266. return true;
  267. }