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