1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2019 Google LLC
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <limits.h>
25bf215546Sopenharmony_ci#include <stdio.h>
26bf215546Sopenharmony_ci#include <stdlib.h>
27bf215546Sopenharmony_ci#include "drm-shim/drm_shim.h"
28bf215546Sopenharmony_ci#include "drm-uapi/msm_drm.h"
29bf215546Sopenharmony_ci#include <sys/ioctl.h>
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci#include "util/u_math.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_cibool drm_shim_driver_prefers_first_render_node = true;
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_cistruct msm_device_info {
36bf215546Sopenharmony_ci   uint32_t gpu_id;
37bf215546Sopenharmony_ci   uint32_t chip_id;
38bf215546Sopenharmony_ci   uint32_t gmem_size;
39bf215546Sopenharmony_ci};
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_cistatic const struct msm_device_info *device_info;
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_cistatic int
44bf215546Sopenharmony_cimsm_ioctl_noop(int fd, unsigned long request, void *arg)
45bf215546Sopenharmony_ci{
46bf215546Sopenharmony_ci   return 0;
47bf215546Sopenharmony_ci}
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_cistatic int
50bf215546Sopenharmony_cimsm_ioctl_gem_new(int fd, unsigned long request, void *arg)
51bf215546Sopenharmony_ci{
52bf215546Sopenharmony_ci   struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
53bf215546Sopenharmony_ci   struct drm_msm_gem_new *create = arg;
54bf215546Sopenharmony_ci   size_t size = ALIGN(create->size, 4096);
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci   if (!size)
57bf215546Sopenharmony_ci      return -EINVAL;
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_ci   struct shim_bo *bo = calloc(1, sizeof(*bo));
60bf215546Sopenharmony_ci   int ret;
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci   ret = drm_shim_bo_init(bo, size);
63bf215546Sopenharmony_ci   if (ret) {
64bf215546Sopenharmony_ci      free(bo);
65bf215546Sopenharmony_ci      return ret;
66bf215546Sopenharmony_ci   }
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci   create->handle = drm_shim_bo_get_handle(shim_fd, bo);
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci   drm_shim_bo_put(bo);
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   return 0;
73bf215546Sopenharmony_ci}
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_cistatic int
76bf215546Sopenharmony_cimsm_ioctl_gem_info(int fd, unsigned long request, void *arg)
77bf215546Sopenharmony_ci{
78bf215546Sopenharmony_ci   struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
79bf215546Sopenharmony_ci   struct drm_msm_gem_info *args = arg;
80bf215546Sopenharmony_ci   struct shim_bo *bo = drm_shim_bo_lookup(shim_fd, args->handle);
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   if (!bo)
83bf215546Sopenharmony_ci      return -ENOENT;
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci   switch (args->info) {
86bf215546Sopenharmony_ci   case MSM_INFO_GET_OFFSET:
87bf215546Sopenharmony_ci      args->value = drm_shim_bo_get_mmap_offset(shim_fd, bo);
88bf215546Sopenharmony_ci      break;
89bf215546Sopenharmony_ci   case MSM_INFO_GET_IOVA:
90bf215546Sopenharmony_ci      args->value = bo->mem_addr;
91bf215546Sopenharmony_ci      break;
92bf215546Sopenharmony_ci   case MSM_INFO_SET_IOVA:
93bf215546Sopenharmony_ci   case MSM_INFO_SET_NAME:
94bf215546Sopenharmony_ci      break;
95bf215546Sopenharmony_ci   default:
96bf215546Sopenharmony_ci      fprintf(stderr, "Unknown DRM_IOCTL_MSM_GEM_INFO %d\n", args->info);
97bf215546Sopenharmony_ci      drm_shim_bo_put(bo);
98bf215546Sopenharmony_ci      return -1;
99bf215546Sopenharmony_ci   }
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   drm_shim_bo_put(bo);
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   return 0;
104bf215546Sopenharmony_ci}
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_cistatic int
107bf215546Sopenharmony_cimsm_ioctl_get_param(int fd, unsigned long request, void *arg)
108bf215546Sopenharmony_ci{
109bf215546Sopenharmony_ci   struct drm_msm_param *gp = arg;
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci   switch (gp->param) {
112bf215546Sopenharmony_ci   case MSM_PARAM_GPU_ID:
113bf215546Sopenharmony_ci      gp->value = device_info->gpu_id;
114bf215546Sopenharmony_ci      return 0;
115bf215546Sopenharmony_ci   case MSM_PARAM_GMEM_SIZE:
116bf215546Sopenharmony_ci      gp->value = device_info->gmem_size;
117bf215546Sopenharmony_ci      return 0;
118bf215546Sopenharmony_ci   case MSM_PARAM_GMEM_BASE:
119bf215546Sopenharmony_ci      gp->value = 0x100000;
120bf215546Sopenharmony_ci      return 0;
121bf215546Sopenharmony_ci   case MSM_PARAM_CHIP_ID:
122bf215546Sopenharmony_ci      gp->value = device_info->chip_id;
123bf215546Sopenharmony_ci      return 0;
124bf215546Sopenharmony_ci   case MSM_PARAM_NR_RINGS:
125bf215546Sopenharmony_ci      gp->value = 1;
126bf215546Sopenharmony_ci      return 0;
127bf215546Sopenharmony_ci   case MSM_PARAM_MAX_FREQ:
128bf215546Sopenharmony_ci      gp->value = 1000000;
129bf215546Sopenharmony_ci      return 0;
130bf215546Sopenharmony_ci   case MSM_PARAM_TIMESTAMP:
131bf215546Sopenharmony_ci      gp->value = 0;
132bf215546Sopenharmony_ci      return 0;
133bf215546Sopenharmony_ci   case MSM_PARAM_PP_PGTABLE:
134bf215546Sopenharmony_ci      gp->value = 1;
135bf215546Sopenharmony_ci      return 0;
136bf215546Sopenharmony_ci   case MSM_PARAM_FAULTS:
137bf215546Sopenharmony_ci   case MSM_PARAM_SUSPENDS:
138bf215546Sopenharmony_ci      gp->value = 0;
139bf215546Sopenharmony_ci      return 0;
140bf215546Sopenharmony_ci   case MSM_PARAM_VA_START:
141bf215546Sopenharmony_ci   case MSM_PARAM_VA_SIZE:
142bf215546Sopenharmony_ci      gp->value = 0x100000000ULL;
143bf215546Sopenharmony_ci      return 0;
144bf215546Sopenharmony_ci   default:
145bf215546Sopenharmony_ci      fprintf(stderr, "Unknown DRM_IOCTL_MSM_GET_PARAM %d\n", gp->param);
146bf215546Sopenharmony_ci      return -1;
147bf215546Sopenharmony_ci   }
148bf215546Sopenharmony_ci}
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_cistatic int
151bf215546Sopenharmony_cimsm_ioctl_gem_madvise(int fd, unsigned long request, void *arg)
152bf215546Sopenharmony_ci{
153bf215546Sopenharmony_ci   struct drm_msm_gem_madvise *args = arg;
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci   args->retained = true;
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   return 0;
158bf215546Sopenharmony_ci}
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_cistatic ioctl_fn_t driver_ioctls[] = {
161bf215546Sopenharmony_ci   [DRM_MSM_GET_PARAM] = msm_ioctl_get_param,
162bf215546Sopenharmony_ci   [DRM_MSM_SET_PARAM] = msm_ioctl_noop,
163bf215546Sopenharmony_ci   [DRM_MSM_GEM_NEW] = msm_ioctl_gem_new,
164bf215546Sopenharmony_ci   [DRM_MSM_GEM_INFO] = msm_ioctl_gem_info,
165bf215546Sopenharmony_ci   [DRM_MSM_GEM_CPU_PREP] = msm_ioctl_noop,
166bf215546Sopenharmony_ci   [DRM_MSM_GEM_CPU_FINI] = msm_ioctl_noop,
167bf215546Sopenharmony_ci   [DRM_MSM_GEM_SUBMIT] = msm_ioctl_noop,
168bf215546Sopenharmony_ci   [DRM_MSM_WAIT_FENCE] = msm_ioctl_noop,
169bf215546Sopenharmony_ci   [DRM_MSM_GEM_MADVISE] = msm_ioctl_gem_madvise,
170bf215546Sopenharmony_ci   [DRM_MSM_SUBMITQUEUE_NEW] = msm_ioctl_noop,
171bf215546Sopenharmony_ci   [DRM_MSM_SUBMITQUEUE_CLOSE] = msm_ioctl_noop,
172bf215546Sopenharmony_ci   [DRM_MSM_SUBMITQUEUE_QUERY] = msm_ioctl_noop,
173bf215546Sopenharmony_ci};
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci#define CHIPID(maj, min, rev, pat)                                             \
176bf215546Sopenharmony_ci   ((maj << 24) | (min << 16) | (rev << 8) | (pat))
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_cistatic const struct msm_device_info device_infos[] = {
179bf215546Sopenharmony_ci   {
180bf215546Sopenharmony_ci      /* First entry is default */
181bf215546Sopenharmony_ci      .gpu_id = 630,
182bf215546Sopenharmony_ci      .chip_id = CHIPID(6, 3, 0, 0xff),
183bf215546Sopenharmony_ci      .gmem_size = 1024 * 1024,
184bf215546Sopenharmony_ci   },
185bf215546Sopenharmony_ci   {
186bf215546Sopenharmony_ci      .gpu_id = 200,
187bf215546Sopenharmony_ci      .chip_id = CHIPID(2, 0, 0, 0),
188bf215546Sopenharmony_ci      .gmem_size = 256 * 1024,
189bf215546Sopenharmony_ci   },
190bf215546Sopenharmony_ci   {
191bf215546Sopenharmony_ci      .gpu_id = 201,
192bf215546Sopenharmony_ci      .chip_id = CHIPID(2, 0, 0, 1),
193bf215546Sopenharmony_ci      .gmem_size = 128 * 1024,
194bf215546Sopenharmony_ci   },
195bf215546Sopenharmony_ci   {
196bf215546Sopenharmony_ci      .gpu_id = 220,
197bf215546Sopenharmony_ci      .chip_id = CHIPID(2, 2, 0, 0xff),
198bf215546Sopenharmony_ci      .gmem_size = 512 * 1024,
199bf215546Sopenharmony_ci   },
200bf215546Sopenharmony_ci   {
201bf215546Sopenharmony_ci      .gpu_id = 305,
202bf215546Sopenharmony_ci      .chip_id = CHIPID(3, 0, 5, 0xff),
203bf215546Sopenharmony_ci      .gmem_size = 256 * 1024,
204bf215546Sopenharmony_ci   },
205bf215546Sopenharmony_ci   {
206bf215546Sopenharmony_ci      .gpu_id = 307,
207bf215546Sopenharmony_ci      .chip_id = CHIPID(3, 0, 6, 0),
208bf215546Sopenharmony_ci      .gmem_size = 128 * 1024,
209bf215546Sopenharmony_ci   },
210bf215546Sopenharmony_ci   {
211bf215546Sopenharmony_ci      .gpu_id = 320,
212bf215546Sopenharmony_ci      .chip_id = CHIPID(3, 2, 0xff, 0xff),
213bf215546Sopenharmony_ci      .gmem_size = 512 * 1024,
214bf215546Sopenharmony_ci   },
215bf215546Sopenharmony_ci   {
216bf215546Sopenharmony_ci      .gpu_id = 330,
217bf215546Sopenharmony_ci      .chip_id = CHIPID(3, 3, 0, 0xff),
218bf215546Sopenharmony_ci      .gmem_size = 1024 * 1024,
219bf215546Sopenharmony_ci   },
220bf215546Sopenharmony_ci   {
221bf215546Sopenharmony_ci      .gpu_id = 420,
222bf215546Sopenharmony_ci      .chip_id = CHIPID(4, 2, 0, 0xff),
223bf215546Sopenharmony_ci      .gmem_size = 1536 * 1024,
224bf215546Sopenharmony_ci   },
225bf215546Sopenharmony_ci   {
226bf215546Sopenharmony_ci      .gpu_id = 430,
227bf215546Sopenharmony_ci      .chip_id = CHIPID(4, 3, 0, 0xff),
228bf215546Sopenharmony_ci      .gmem_size = 1536 * 1024,
229bf215546Sopenharmony_ci   },
230bf215546Sopenharmony_ci   {
231bf215546Sopenharmony_ci      .gpu_id = 510,
232bf215546Sopenharmony_ci      .chip_id = CHIPID(5, 1, 0, 0xff),
233bf215546Sopenharmony_ci      .gmem_size = 256 * 1024,
234bf215546Sopenharmony_ci   },
235bf215546Sopenharmony_ci   {
236bf215546Sopenharmony_ci      .gpu_id = 530,
237bf215546Sopenharmony_ci      .chip_id = CHIPID(5, 3, 0, 2),
238bf215546Sopenharmony_ci      .gmem_size = 1024 * 1024,
239bf215546Sopenharmony_ci   },
240bf215546Sopenharmony_ci   {
241bf215546Sopenharmony_ci      .gpu_id = 540,
242bf215546Sopenharmony_ci      .chip_id = CHIPID(5, 4, 0, 2),
243bf215546Sopenharmony_ci      .gmem_size = 1024 * 1024,
244bf215546Sopenharmony_ci   },
245bf215546Sopenharmony_ci   {
246bf215546Sopenharmony_ci      .gpu_id = 618,
247bf215546Sopenharmony_ci      .chip_id = CHIPID(6, 1, 8, 0xff),
248bf215546Sopenharmony_ci      .gmem_size = 512 * 1024,
249bf215546Sopenharmony_ci   },
250bf215546Sopenharmony_ci   {
251bf215546Sopenharmony_ci      .gpu_id = 630,
252bf215546Sopenharmony_ci      .chip_id = CHIPID(6, 3, 0, 0xff),
253bf215546Sopenharmony_ci      .gmem_size = 1024 * 1024,
254bf215546Sopenharmony_ci   },
255bf215546Sopenharmony_ci   {
256bf215546Sopenharmony_ci      .gpu_id = 660,
257bf215546Sopenharmony_ci      .chip_id = CHIPID(6, 6, 0, 0xff),
258bf215546Sopenharmony_ci      .gmem_size = 1024 * 1024 + 512 * 1024,
259bf215546Sopenharmony_ci   },
260bf215546Sopenharmony_ci};
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_cistatic void
263bf215546Sopenharmony_cimsm_driver_get_device_info(void)
264bf215546Sopenharmony_ci{
265bf215546Sopenharmony_ci   const char *env = getenv("FD_GPU_ID");
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci   if (!env) {
268bf215546Sopenharmony_ci      device_info = &device_infos[0];
269bf215546Sopenharmony_ci      return;
270bf215546Sopenharmony_ci   }
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci   int gpu_id = atoi(env);
273bf215546Sopenharmony_ci   for (int i = 0; i < ARRAY_SIZE(device_infos); i++) {
274bf215546Sopenharmony_ci      if (device_infos[i].gpu_id == gpu_id) {
275bf215546Sopenharmony_ci         device_info = &device_infos[i];
276bf215546Sopenharmony_ci         return;
277bf215546Sopenharmony_ci      }
278bf215546Sopenharmony_ci   }
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   fprintf(stderr, "FD_GPU_ID unrecognized, shim supports %d",
281bf215546Sopenharmony_ci           device_infos[0].gpu_id);
282bf215546Sopenharmony_ci   for (int i = 1; i < ARRAY_SIZE(device_infos); i++)
283bf215546Sopenharmony_ci      fprintf(stderr, ", %d", device_infos[i].gpu_id);
284bf215546Sopenharmony_ci   fprintf(stderr, "\n");
285bf215546Sopenharmony_ci   abort();
286bf215546Sopenharmony_ci}
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_civoid
289bf215546Sopenharmony_cidrm_shim_driver_init(void)
290bf215546Sopenharmony_ci{
291bf215546Sopenharmony_ci   shim_device.bus_type = DRM_BUS_PLATFORM;
292bf215546Sopenharmony_ci   shim_device.driver_name = "msm";
293bf215546Sopenharmony_ci   shim_device.driver_ioctls = driver_ioctls;
294bf215546Sopenharmony_ci   shim_device.driver_ioctl_count = ARRAY_SIZE(driver_ioctls);
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci   /* msm uses the DRM version to expose features, instead of getparam. */
297bf215546Sopenharmony_ci   shim_device.version_major = 1;
298bf215546Sopenharmony_ci   shim_device.version_minor = 9;
299bf215546Sopenharmony_ci   shim_device.version_patchlevel = 0;
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci   msm_driver_get_device_info();
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci   drm_shim_override_file("OF_FULLNAME=/rdb/msm\n"
304bf215546Sopenharmony_ci                          "OF_COMPATIBLE_N=1\n"
305bf215546Sopenharmony_ci                          "OF_COMPATIBLE_0=qcom,adreno\n",
306bf215546Sopenharmony_ci                          "/sys/dev/char/%d:%d/device/uevent", DRM_MAJOR,
307bf215546Sopenharmony_ci                          render_node_minor);
308bf215546Sopenharmony_ci}
309