1
0

tegra.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. * Copyright © 2012, 2013 Thierry Reding
  3. * Copyright © 2013 Erik Faye-Lund
  4. * Copyright © 2014 NVIDIA Corporation
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a
  7. * copy of this software and associated documentation files (the "Software"),
  8. * to deal in the Software without restriction, including without limitation
  9. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10. * and/or sell copies of the Software, and to permit persons to whom the
  11. * Software is furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22. * OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. #include <errno.h>
  25. #include <fcntl.h>
  26. #include <string.h>
  27. #include <unistd.h>
  28. #include <sys/mman.h>
  29. #include <xf86drm.h>
  30. #include <tegra_drm.h>
  31. #include "private.h"
  32. static void drm_tegra_bo_free(struct drm_tegra_bo *bo)
  33. {
  34. struct drm_tegra *drm = bo->drm;
  35. if (bo->map)
  36. munmap(bo->map, bo->size);
  37. drmCloseBufferHandle(drm->fd, bo->handle);
  38. free(bo);
  39. }
  40. static int drm_tegra_wrap(struct drm_tegra **drmp, int fd, bool close)
  41. {
  42. struct drm_tegra *drm;
  43. if (fd < 0 || !drmp)
  44. return -EINVAL;
  45. drm = calloc(1, sizeof(*drm));
  46. if (!drm)
  47. return -ENOMEM;
  48. drm->close = close;
  49. drm->fd = fd;
  50. *drmp = drm;
  51. return 0;
  52. }
  53. drm_public int drm_tegra_new(int fd, struct drm_tegra **drmp)
  54. {
  55. bool supported = false;
  56. drmVersionPtr version;
  57. version = drmGetVersion(fd);
  58. if (!version)
  59. return -ENOMEM;
  60. if (!strncmp(version->name, "tegra", version->name_len))
  61. supported = true;
  62. drmFreeVersion(version);
  63. if (!supported)
  64. return -ENOTSUP;
  65. return drm_tegra_wrap(drmp, fd, false);
  66. }
  67. drm_public void drm_tegra_close(struct drm_tegra *drm)
  68. {
  69. if (!drm)
  70. return;
  71. if (drm->close)
  72. close(drm->fd);
  73. free(drm);
  74. }
  75. static struct drm_tegra_bo *drm_tegra_bo_alloc(struct drm_tegra *drm,
  76. uint32_t handle,
  77. uint32_t flags,
  78. uint32_t size)
  79. {
  80. struct drm_tegra_bo *bo;
  81. bo = calloc(1, sizeof(*bo));
  82. if (!bo)
  83. return NULL;
  84. atomic_set(&bo->ref, 1);
  85. bo->handle = handle;
  86. bo->flags = flags;
  87. bo->size = size;
  88. bo->drm = drm;
  89. return bo;
  90. }
  91. drm_public int
  92. drm_tegra_bo_new(struct drm_tegra *drm, uint32_t flags, uint32_t size,
  93. struct drm_tegra_bo **bop)
  94. {
  95. struct drm_tegra_gem_create args;
  96. struct drm_tegra_bo *bo;
  97. int err;
  98. if (!drm || size == 0 || !bop)
  99. return -EINVAL;
  100. bo = drm_tegra_bo_alloc(drm, 0, flags, size);
  101. if (!bo)
  102. return -ENOMEM;
  103. memset(&args, 0, sizeof(args));
  104. args.flags = flags;
  105. args.size = size;
  106. err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_CREATE, &args,
  107. sizeof(args));
  108. if (err < 0) {
  109. err = -errno;
  110. free(bo);
  111. return err;
  112. }
  113. bo->handle = args.handle;
  114. *bop = bo;
  115. return 0;
  116. }
  117. drm_public int
  118. drm_tegra_bo_wrap(struct drm_tegra *drm, uint32_t handle, uint32_t flags,
  119. uint32_t size, struct drm_tegra_bo **bop)
  120. {
  121. struct drm_tegra_bo *bo;
  122. if (!drm || !bop)
  123. return -EINVAL;
  124. bo = drm_tegra_bo_alloc(drm, handle, flags, size);
  125. if (!bo)
  126. return -ENOMEM;
  127. *bop = bo;
  128. return 0;
  129. }
  130. drm_public struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo)
  131. {
  132. if (bo)
  133. atomic_inc(&bo->ref);
  134. return bo;
  135. }
  136. drm_public void drm_tegra_bo_unref(struct drm_tegra_bo *bo)
  137. {
  138. if (bo && atomic_dec_and_test(&bo->ref))
  139. drm_tegra_bo_free(bo);
  140. }
  141. drm_public int
  142. drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle)
  143. {
  144. if (!bo || !handle)
  145. return -EINVAL;
  146. *handle = bo->handle;
  147. return 0;
  148. }
  149. drm_public int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr)
  150. {
  151. struct drm_tegra *drm = bo->drm;
  152. if (!bo->map) {
  153. struct drm_tegra_gem_mmap args;
  154. int err;
  155. memset(&args, 0, sizeof(args));
  156. args.handle = bo->handle;
  157. err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_MMAP, &args,
  158. sizeof(args));
  159. if (err < 0)
  160. return -errno;
  161. bo->offset = args.offset;
  162. bo->map = drm_mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
  163. drm->fd, bo->offset);
  164. if (bo->map == MAP_FAILED) {
  165. bo->map = NULL;
  166. return -errno;
  167. }
  168. }
  169. if (ptr)
  170. *ptr = bo->map;
  171. return 0;
  172. }
  173. drm_public int drm_tegra_bo_unmap(struct drm_tegra_bo *bo)
  174. {
  175. if (!bo)
  176. return -EINVAL;
  177. if (!bo->map)
  178. return 0;
  179. if (munmap(bo->map, bo->size))
  180. return -errno;
  181. bo->map = NULL;
  182. return 0;
  183. }
  184. drm_public int drm_tegra_bo_get_name(struct drm_tegra_bo *bo, uint32_t *name)
  185. {
  186. struct drm_tegra *drm = bo->drm;
  187. struct drm_gem_flink args;
  188. int err;
  189. memset(&args, 0, sizeof(args));
  190. args.handle = bo->handle;
  191. err = drmIoctl(drm->fd, DRM_IOCTL_GEM_FLINK, &args);
  192. if (err < 0)
  193. return err;
  194. if (name)
  195. *name = args.name;
  196. return 0;
  197. }
  198. drm_public int
  199. drm_tegra_bo_open(struct drm_tegra *drm, uint32_t name, uint32_t flags,
  200. struct drm_tegra_bo **bop)
  201. {
  202. struct drm_gem_open args;
  203. struct drm_tegra_bo *bo;
  204. int err;
  205. bo = drm_tegra_bo_alloc(drm, 0, flags, 0);
  206. if (!bo)
  207. return -ENOMEM;
  208. memset(&args, 0, sizeof(args));
  209. args.name = name;
  210. err = drmIoctl(drm->fd, DRM_IOCTL_GEM_OPEN, &args);
  211. if (err < 0)
  212. goto free;
  213. bo->handle = args.handle;
  214. bo->size = args.size;
  215. *bop = bo;
  216. return 0;
  217. free:
  218. free(bo);
  219. return err;
  220. }
  221. drm_public int drm_tegra_bo_export(struct drm_tegra_bo *bo, uint32_t flags)
  222. {
  223. int fd, err;
  224. flags |= DRM_CLOEXEC;
  225. err = drmPrimeHandleToFD(bo->drm->fd, bo->handle, flags, &fd);
  226. if (err < 0)
  227. return err;
  228. return fd;
  229. }
  230. static ssize_t fd_get_size(int fd)
  231. {
  232. ssize_t size, offset;
  233. int err;
  234. offset = lseek(fd, 0, SEEK_CUR);
  235. if (offset < 0)
  236. return -errno;
  237. size = lseek(fd, 0, SEEK_END);
  238. if (size < 0)
  239. return -errno;
  240. err = lseek(fd, offset, SEEK_SET);
  241. if (err < 0)
  242. return -errno;
  243. return size;
  244. }
  245. drm_public int
  246. drm_tegra_bo_import(struct drm_tegra *drm, int fd, struct drm_tegra_bo **bop)
  247. {
  248. struct drm_tegra_bo *bo;
  249. ssize_t size;
  250. int err;
  251. size = fd_get_size(fd);
  252. if (size < 0)
  253. return size;
  254. bo = drm_tegra_bo_alloc(drm, 0, 0, size);
  255. if (!bo)
  256. return -ENOMEM;
  257. err = drmPrimeFDToHandle(drm->fd, fd, &bo->handle);
  258. if (err < 0)
  259. goto free;
  260. *bop = bo;
  261. return 0;
  262. free:
  263. free(bo);
  264. return err;
  265. }