1 /* 2 * Copyright © 2012, 2013 Thierry Reding 3 * Copyright © 2013 Erik Faye-Lund 4 * Copyright © 2014-2021 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 25 #ifdef HAVE_CONFIG_H 26 # include "config.h" 27 #endif 28 29 #include <errno.h> 30 #include <string.h> 31 32 #include <sys/ioctl.h> 33 34 #include "private.h" 35 36 drm_public int 37 drm_tegra_channel_open(struct drm_tegra *drm, 38 enum drm_tegra_class client, 39 struct drm_tegra_channel **channelp) 40 { 41 struct drm_tegra_channel_open args; 42 struct drm_tegra_channel *channel; 43 enum host1x_class class; 44 int err; 45 46 switch (client) { 47 case DRM_TEGRA_HOST1X: 48 class = HOST1X_CLASS_HOST1X; 49 break; 50 51 case DRM_TEGRA_GR2D: 52 class = HOST1X_CLASS_GR2D; 53 break; 54 55 case DRM_TEGRA_GR3D: 56 class = HOST1X_CLASS_GR3D; 57 break; 58 59 case DRM_TEGRA_VIC: 60 class = HOST1X_CLASS_VIC; 61 break; 62 63 default: 64 return -EINVAL; 65 } 66 67 channel = calloc(1, sizeof(*channel)); 68 if (!channel) 69 return -ENOMEM; 70 71 channel->drm = drm; 72 73 memset(&args, 0, sizeof(args)); 74 args.host1x_class = class; 75 76 err = ioctl(drm->fd, DRM_IOCTL_TEGRA_CHANNEL_OPEN, &args); 77 if (err < 0) { 78 free(channel); 79 return -errno; 80 } 81 82 channel->context = args.context; 83 channel->version = args.version; 84 channel->capabilities = args.capabilities; 85 channel->class = class; 86 87 switch (channel->version) { 88 case 0x20: 89 case 0x30: 90 case 0x35: 91 case 0x40: 92 case 0x21: 93 channel->cond_shift = 8; 94 break; 95 96 case 0x18: 97 case 0x19: 98 channel->cond_shift = 10; 99 break; 100 101 default: 102 return -ENOTSUP; 103 } 104 105 *channelp = channel; 106 107 return 0; 108 } 109 110 drm_public int drm_tegra_channel_close(struct drm_tegra_channel *channel) 111 { 112 struct drm_tegra_channel_close args; 113 struct drm_tegra *drm; 114 int err; 115 116 if (!channel) 117 return -EINVAL; 118 119 drm = channel->drm; 120 121 memset(&args, 0, sizeof(args)); 122 args.context = channel->context; 123 124 err = ioctl(drm->fd, DRM_IOCTL_TEGRA_CHANNEL_CLOSE, &args); 125 if (err < 0) 126 return -errno; 127 128 free(channel); 129 130 return 0; 131 } 132 133 drm_public unsigned int 134 drm_tegra_channel_get_version(struct drm_tegra_channel *channel) 135 { 136 return channel->version; 137 } 138 139 drm_public int 140 drm_tegra_channel_map(struct drm_tegra_channel *channel, 141 struct drm_tegra_bo *bo, uint32_t flags, 142 struct drm_tegra_mapping **mapp) 143 { 144 struct drm_tegra *drm = channel->drm; 145 struct drm_tegra_channel_map args; 146 struct drm_tegra_mapping *map; 147 int err; 148 149 if (!drm || !bo || !mapp) 150 return -EINVAL; 151 152 map = calloc(1, sizeof(*map)); 153 if (!map) 154 return -ENOMEM; 155 156 memset(&args, 0, sizeof(args)); 157 args.context = channel->context; 158 args.handle = bo->handle; 159 args.flags = flags; 160 161 err = ioctl(drm->fd, DRM_IOCTL_TEGRA_CHANNEL_MAP, &args); 162 if (err < 0) { 163 free(map); 164 return -errno; 165 } 166 167 map->channel = channel; 168 map->id = args.mapping; 169 *mapp = map; 170 171 return 0; 172 } 173 174 drm_public int 175 drm_tegra_channel_unmap(struct drm_tegra_mapping *map) 176 { 177 struct drm_tegra_channel *channel = map->channel; 178 struct drm_tegra *drm = channel->drm; 179 struct drm_tegra_channel_unmap args; 180 int err; 181 182 if (!channel || !map) 183 return -EINVAL; 184 185 memset(&args, 0, sizeof(args)); 186 args.context = channel->context; 187 args.mapping = map->id; 188 189 err = ioctl(drm->fd, DRM_IOCTL_TEGRA_CHANNEL_UNMAP, &args); 190 if (err < 0) 191 return -errno; 192 193 free(map); 194 return 0; 195 } 196