1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2018 Google, Inc.
3b8e80941Smrg * Copyright © 2015 Intel Corporation
4b8e80941Smrg *
5b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
7b8e80941Smrg * to deal in the Software without restriction, including without limitation
8b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
10b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
11b8e80941Smrg *
12b8e80941Smrg * The above copyright notice and this permission notice (including the next
13b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
14b8e80941Smrg * Software.
15b8e80941Smrg *
16b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22b8e80941Smrg * DEALINGS IN THE SOFTWARE.
23b8e80941Smrg */
24b8e80941Smrg
25b8e80941Smrg#include "tu_private.h"
26b8e80941Smrg
27b8e80941Smrg#include <errno.h>
28b8e80941Smrg#include <fcntl.h>
29b8e80941Smrg#include <stdint.h>
30b8e80941Smrg#include <sys/ioctl.h>
31b8e80941Smrg#include <xf86drm.h>
32b8e80941Smrg
33b8e80941Smrg#include "drm/msm_drm.h"
34b8e80941Smrg
35b8e80941Smrgstatic int
36b8e80941Smrgtu_drm_get_param(const struct tu_physical_device *dev,
37b8e80941Smrg                 uint32_t param,
38b8e80941Smrg                 uint64_t *value)
39b8e80941Smrg{
40b8e80941Smrg   /* Technically this requires a pipe, but the kernel only supports one pipe
41b8e80941Smrg    * anyway at the time of writing and most of these are clearly pipe
42b8e80941Smrg    * independent. */
43b8e80941Smrg   struct drm_msm_param req = {
44b8e80941Smrg      .pipe = MSM_PIPE_3D0,
45b8e80941Smrg      .param = param,
46b8e80941Smrg   };
47b8e80941Smrg
48b8e80941Smrg   int ret = drmCommandWriteRead(dev->local_fd, DRM_MSM_GET_PARAM, &req,
49b8e80941Smrg                                 sizeof(req));
50b8e80941Smrg   if (ret)
51b8e80941Smrg      return ret;
52b8e80941Smrg
53b8e80941Smrg   *value = req.value;
54b8e80941Smrg
55b8e80941Smrg   return 0;
56b8e80941Smrg}
57b8e80941Smrg
58b8e80941Smrgint
59b8e80941Smrgtu_drm_get_gpu_id(const struct tu_physical_device *dev, uint32_t *id)
60b8e80941Smrg{
61b8e80941Smrg   uint64_t value;
62b8e80941Smrg   int ret = tu_drm_get_param(dev, MSM_PARAM_GPU_ID, &value);
63b8e80941Smrg   if (ret)
64b8e80941Smrg      return ret;
65b8e80941Smrg
66b8e80941Smrg   *id = value;
67b8e80941Smrg   return 0;
68b8e80941Smrg}
69b8e80941Smrg
70b8e80941Smrgint
71b8e80941Smrgtu_drm_get_gmem_size(const struct tu_physical_device *dev, uint32_t *size)
72b8e80941Smrg{
73b8e80941Smrg   uint64_t value;
74b8e80941Smrg   int ret = tu_drm_get_param(dev, MSM_PARAM_GMEM_SIZE, &value);
75b8e80941Smrg   if (ret)
76b8e80941Smrg      return ret;
77b8e80941Smrg
78b8e80941Smrg   *size = value;
79b8e80941Smrg   return 0;
80b8e80941Smrg}
81b8e80941Smrg
82b8e80941Smrgint
83b8e80941Smrgtu_drm_submitqueue_new(const struct tu_device *dev,
84b8e80941Smrg                       int priority,
85b8e80941Smrg                       uint32_t *queue_id)
86b8e80941Smrg{
87b8e80941Smrg   struct drm_msm_submitqueue req = {
88b8e80941Smrg      .flags = 0,
89b8e80941Smrg      .prio = priority,
90b8e80941Smrg   };
91b8e80941Smrg
92b8e80941Smrg   int ret = drmCommandWriteRead(dev->physical_device->local_fd,
93b8e80941Smrg                                 DRM_MSM_SUBMITQUEUE_NEW, &req, sizeof(req));
94b8e80941Smrg   if (ret)
95b8e80941Smrg      return ret;
96b8e80941Smrg
97b8e80941Smrg   *queue_id = req.id;
98b8e80941Smrg   return 0;
99b8e80941Smrg}
100b8e80941Smrg
101b8e80941Smrgvoid
102b8e80941Smrgtu_drm_submitqueue_close(const struct tu_device *dev, uint32_t queue_id)
103b8e80941Smrg{
104b8e80941Smrg   drmCommandWrite(dev->physical_device->local_fd, DRM_MSM_SUBMITQUEUE_CLOSE,
105b8e80941Smrg                   &queue_id, sizeof(uint32_t));
106b8e80941Smrg}
107b8e80941Smrg
108b8e80941Smrg/**
109b8e80941Smrg * Return gem handle on success. Return 0 on failure.
110b8e80941Smrg */
111b8e80941Smrguint32_t
112b8e80941Smrgtu_gem_new(const struct tu_device *dev, uint64_t size, uint32_t flags)
113b8e80941Smrg{
114b8e80941Smrg   struct drm_msm_gem_new req = {
115b8e80941Smrg      .size = size,
116b8e80941Smrg      .flags = flags,
117b8e80941Smrg   };
118b8e80941Smrg
119b8e80941Smrg   int ret = drmCommandWriteRead(dev->physical_device->local_fd,
120b8e80941Smrg                                 DRM_MSM_GEM_NEW, &req, sizeof(req));
121b8e80941Smrg   if (ret)
122b8e80941Smrg      return 0;
123b8e80941Smrg
124b8e80941Smrg   return req.handle;
125b8e80941Smrg}
126b8e80941Smrg
127b8e80941Smrguint32_t
128b8e80941Smrgtu_gem_import_dmabuf(const struct tu_device *dev, int prime_fd, uint64_t size)
129b8e80941Smrg{
130b8e80941Smrg   /* lseek() to get the real size */
131b8e80941Smrg   off_t real_size = lseek(prime_fd, 0, SEEK_END);
132b8e80941Smrg   lseek(prime_fd, 0, SEEK_SET);
133b8e80941Smrg   if (real_size < 0 || (uint64_t) real_size < size)
134b8e80941Smrg      return 0;
135b8e80941Smrg
136b8e80941Smrg   uint32_t gem_handle;
137b8e80941Smrg   int ret = drmPrimeFDToHandle(dev->physical_device->local_fd, prime_fd,
138b8e80941Smrg                                &gem_handle);
139b8e80941Smrg   if (ret)
140b8e80941Smrg      return 0;
141b8e80941Smrg
142b8e80941Smrg   return gem_handle;
143b8e80941Smrg}
144b8e80941Smrg
145b8e80941Smrgint
146b8e80941Smrgtu_gem_export_dmabuf(const struct tu_device *dev, uint32_t gem_handle)
147b8e80941Smrg{
148b8e80941Smrg   int prime_fd;
149b8e80941Smrg   int ret = drmPrimeHandleToFD(dev->physical_device->local_fd, gem_handle,
150b8e80941Smrg                                DRM_CLOEXEC, &prime_fd);
151b8e80941Smrg
152b8e80941Smrg   return ret == 0 ? prime_fd : -1;
153b8e80941Smrg}
154b8e80941Smrg
155b8e80941Smrgvoid
156b8e80941Smrgtu_gem_close(const struct tu_device *dev, uint32_t gem_handle)
157b8e80941Smrg{
158b8e80941Smrg   struct drm_gem_close req = {
159b8e80941Smrg      .handle = gem_handle,
160b8e80941Smrg   };
161b8e80941Smrg
162b8e80941Smrg   drmIoctl(dev->physical_device->local_fd, DRM_IOCTL_GEM_CLOSE, &req);
163b8e80941Smrg}
164b8e80941Smrg
165b8e80941Smrg/** Return UINT64_MAX on error. */
166b8e80941Smrgstatic uint64_t
167b8e80941Smrgtu_gem_info(const struct tu_device *dev, uint32_t gem_handle, uint32_t info)
168b8e80941Smrg{
169b8e80941Smrg   struct drm_msm_gem_info req = {
170b8e80941Smrg      .handle = gem_handle,
171b8e80941Smrg      .info = info,
172b8e80941Smrg   };
173b8e80941Smrg
174b8e80941Smrg   int ret = drmCommandWriteRead(dev->physical_device->local_fd,
175b8e80941Smrg                                 DRM_MSM_GEM_INFO, &req, sizeof(req));
176b8e80941Smrg   if (ret == -1)
177b8e80941Smrg      return UINT64_MAX;
178b8e80941Smrg
179b8e80941Smrg   return req.value;
180b8e80941Smrg}
181b8e80941Smrg
182b8e80941Smrg/** Return UINT64_MAX on error. */
183b8e80941Smrguint64_t
184b8e80941Smrgtu_gem_info_offset(const struct tu_device *dev, uint32_t gem_handle)
185b8e80941Smrg{
186b8e80941Smrg   return tu_gem_info(dev, gem_handle, MSM_INFO_GET_OFFSET);
187b8e80941Smrg}
188b8e80941Smrg
189b8e80941Smrg/** Return UINT64_MAX on error. */
190b8e80941Smrguint64_t
191b8e80941Smrgtu_gem_info_iova(const struct tu_device *dev, uint32_t gem_handle)
192b8e80941Smrg{
193b8e80941Smrg   return tu_gem_info(dev, gem_handle, MSM_INFO_GET_IOVA);
194b8e80941Smrg}
195