1a8c21a54SThe etnaviv authors /* 2a8c21a54SThe etnaviv authors * Copyright (C) 2015 Etnaviv Project 3a8c21a54SThe etnaviv authors * 4a8c21a54SThe etnaviv authors * This program is free software; you can redistribute it and/or modify it 5a8c21a54SThe etnaviv authors * under the terms of the GNU General Public License version 2 as published by 6a8c21a54SThe etnaviv authors * the Free Software Foundation. 7a8c21a54SThe etnaviv authors * 8a8c21a54SThe etnaviv authors * This program is distributed in the hope that it will be useful, but WITHOUT 9a8c21a54SThe etnaviv authors * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10a8c21a54SThe etnaviv authors * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11a8c21a54SThe etnaviv authors * more details. 12a8c21a54SThe etnaviv authors * 13a8c21a54SThe etnaviv authors * You should have received a copy of the GNU General Public License along with 14a8c21a54SThe etnaviv authors * this program. If not, see <http://www.gnu.org/licenses/>. 15a8c21a54SThe etnaviv authors */ 16a8c21a54SThe etnaviv authors 17a8c21a54SThe etnaviv authors #include <linux/component.h> 18a8c21a54SThe etnaviv authors #include <linux/of_platform.h> 1997ac0e47SRussell King #include <drm/drm_of.h> 20a8c21a54SThe etnaviv authors 21a8c21a54SThe etnaviv authors #include "etnaviv_drv.h" 22a8c21a54SThe etnaviv authors #include "etnaviv_gpu.h" 23a8c21a54SThe etnaviv authors #include "etnaviv_gem.h" 24a8c21a54SThe etnaviv authors #include "etnaviv_mmu.h" 25a8c21a54SThe etnaviv authors #include "etnaviv_gem.h" 26a8c21a54SThe etnaviv authors 27a8c21a54SThe etnaviv authors #ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING 28a8c21a54SThe etnaviv authors static bool reglog; 29a8c21a54SThe etnaviv authors MODULE_PARM_DESC(reglog, "Enable register read/write logging"); 30a8c21a54SThe etnaviv authors module_param(reglog, bool, 0600); 31a8c21a54SThe etnaviv authors #else 32a8c21a54SThe etnaviv authors #define reglog 0 33a8c21a54SThe etnaviv authors #endif 34a8c21a54SThe etnaviv authors 35a8c21a54SThe etnaviv authors void __iomem *etnaviv_ioremap(struct platform_device *pdev, const char *name, 36a8c21a54SThe etnaviv authors const char *dbgname) 37a8c21a54SThe etnaviv authors { 38a8c21a54SThe etnaviv authors struct resource *res; 39a8c21a54SThe etnaviv authors void __iomem *ptr; 40a8c21a54SThe etnaviv authors 41a8c21a54SThe etnaviv authors if (name) 42a8c21a54SThe etnaviv authors res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); 43a8c21a54SThe etnaviv authors else 44a8c21a54SThe etnaviv authors res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 45a8c21a54SThe etnaviv authors 46a8c21a54SThe etnaviv authors ptr = devm_ioremap_resource(&pdev->dev, res); 47a8c21a54SThe etnaviv authors if (IS_ERR(ptr)) { 48a8c21a54SThe etnaviv authors dev_err(&pdev->dev, "failed to ioremap %s: %ld\n", name, 49a8c21a54SThe etnaviv authors PTR_ERR(ptr)); 50a8c21a54SThe etnaviv authors return ptr; 51a8c21a54SThe etnaviv authors } 52a8c21a54SThe etnaviv authors 53a8c21a54SThe etnaviv authors if (reglog) 54a8c21a54SThe etnaviv authors dev_printk(KERN_DEBUG, &pdev->dev, "IO:region %s 0x%p %08zx\n", 55a8c21a54SThe etnaviv authors dbgname, ptr, (size_t)resource_size(res)); 56a8c21a54SThe etnaviv authors 57a8c21a54SThe etnaviv authors return ptr; 58a8c21a54SThe etnaviv authors } 59a8c21a54SThe etnaviv authors 60a8c21a54SThe etnaviv authors void etnaviv_writel(u32 data, void __iomem *addr) 61a8c21a54SThe etnaviv authors { 62a8c21a54SThe etnaviv authors if (reglog) 63a8c21a54SThe etnaviv authors printk(KERN_DEBUG "IO:W %p %08x\n", addr, data); 64a8c21a54SThe etnaviv authors 65a8c21a54SThe etnaviv authors writel(data, addr); 66a8c21a54SThe etnaviv authors } 67a8c21a54SThe etnaviv authors 68a8c21a54SThe etnaviv authors u32 etnaviv_readl(const void __iomem *addr) 69a8c21a54SThe etnaviv authors { 70a8c21a54SThe etnaviv authors u32 val = readl(addr); 71a8c21a54SThe etnaviv authors 72a8c21a54SThe etnaviv authors if (reglog) 73a8c21a54SThe etnaviv authors printk(KERN_DEBUG "IO:R %p %08x\n", addr, val); 74a8c21a54SThe etnaviv authors 75a8c21a54SThe etnaviv authors return val; 76a8c21a54SThe etnaviv authors } 77a8c21a54SThe etnaviv authors 78a8c21a54SThe etnaviv authors /* 79a8c21a54SThe etnaviv authors * DRM operations: 80a8c21a54SThe etnaviv authors */ 81a8c21a54SThe etnaviv authors 82a8c21a54SThe etnaviv authors 83a8c21a54SThe etnaviv authors static void load_gpu(struct drm_device *dev) 84a8c21a54SThe etnaviv authors { 85a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 86a8c21a54SThe etnaviv authors unsigned int i; 87a8c21a54SThe etnaviv authors 88a8c21a54SThe etnaviv authors for (i = 0; i < ETNA_MAX_PIPES; i++) { 89a8c21a54SThe etnaviv authors struct etnaviv_gpu *g = priv->gpu[i]; 90a8c21a54SThe etnaviv authors 91a8c21a54SThe etnaviv authors if (g) { 92a8c21a54SThe etnaviv authors int ret; 93a8c21a54SThe etnaviv authors 94a8c21a54SThe etnaviv authors ret = etnaviv_gpu_init(g); 95c1c77b0eSLucas Stach if (ret) 96a8c21a54SThe etnaviv authors priv->gpu[i] = NULL; 97a8c21a54SThe etnaviv authors } 98a8c21a54SThe etnaviv authors } 99a8c21a54SThe etnaviv authors } 100a8c21a54SThe etnaviv authors 101a8c21a54SThe etnaviv authors static int etnaviv_open(struct drm_device *dev, struct drm_file *file) 102a8c21a54SThe etnaviv authors { 103a8c21a54SThe etnaviv authors struct etnaviv_file_private *ctx; 104a8c21a54SThe etnaviv authors 105a8c21a54SThe etnaviv authors ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 106a8c21a54SThe etnaviv authors if (!ctx) 107a8c21a54SThe etnaviv authors return -ENOMEM; 108a8c21a54SThe etnaviv authors 109a8c21a54SThe etnaviv authors file->driver_priv = ctx; 110a8c21a54SThe etnaviv authors 111a8c21a54SThe etnaviv authors return 0; 112a8c21a54SThe etnaviv authors } 113a8c21a54SThe etnaviv authors 114a8c21a54SThe etnaviv authors static void etnaviv_preclose(struct drm_device *dev, struct drm_file *file) 115a8c21a54SThe etnaviv authors { 116a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 117a8c21a54SThe etnaviv authors struct etnaviv_file_private *ctx = file->driver_priv; 118a8c21a54SThe etnaviv authors unsigned int i; 119a8c21a54SThe etnaviv authors 120a8c21a54SThe etnaviv authors for (i = 0; i < ETNA_MAX_PIPES; i++) { 121a8c21a54SThe etnaviv authors struct etnaviv_gpu *gpu = priv->gpu[i]; 122a8c21a54SThe etnaviv authors 123a8c21a54SThe etnaviv authors if (gpu) { 124a8c21a54SThe etnaviv authors mutex_lock(&gpu->lock); 125a8c21a54SThe etnaviv authors if (gpu->lastctx == ctx) 126a8c21a54SThe etnaviv authors gpu->lastctx = NULL; 127a8c21a54SThe etnaviv authors mutex_unlock(&gpu->lock); 128a8c21a54SThe etnaviv authors } 129a8c21a54SThe etnaviv authors } 130a8c21a54SThe etnaviv authors 131a8c21a54SThe etnaviv authors kfree(ctx); 132a8c21a54SThe etnaviv authors } 133a8c21a54SThe etnaviv authors 134a8c21a54SThe etnaviv authors /* 135a8c21a54SThe etnaviv authors * DRM debugfs: 136a8c21a54SThe etnaviv authors */ 137a8c21a54SThe etnaviv authors 138a8c21a54SThe etnaviv authors #ifdef CONFIG_DEBUG_FS 139a8c21a54SThe etnaviv authors static int etnaviv_gem_show(struct drm_device *dev, struct seq_file *m) 140a8c21a54SThe etnaviv authors { 141a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 142a8c21a54SThe etnaviv authors 143a8c21a54SThe etnaviv authors etnaviv_gem_describe_objects(priv, m); 144a8c21a54SThe etnaviv authors 145a8c21a54SThe etnaviv authors return 0; 146a8c21a54SThe etnaviv authors } 147a8c21a54SThe etnaviv authors 148a8c21a54SThe etnaviv authors static int etnaviv_mm_show(struct drm_device *dev, struct seq_file *m) 149a8c21a54SThe etnaviv authors { 150a8c21a54SThe etnaviv authors int ret; 151a8c21a54SThe etnaviv authors 152a8c21a54SThe etnaviv authors read_lock(&dev->vma_offset_manager->vm_lock); 153a8c21a54SThe etnaviv authors ret = drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm); 154a8c21a54SThe etnaviv authors read_unlock(&dev->vma_offset_manager->vm_lock); 155a8c21a54SThe etnaviv authors 156a8c21a54SThe etnaviv authors return ret; 157a8c21a54SThe etnaviv authors } 158a8c21a54SThe etnaviv authors 159a8c21a54SThe etnaviv authors static int etnaviv_mmu_show(struct etnaviv_gpu *gpu, struct seq_file *m) 160a8c21a54SThe etnaviv authors { 161a8c21a54SThe etnaviv authors seq_printf(m, "Active Objects (%s):\n", dev_name(gpu->dev)); 162a8c21a54SThe etnaviv authors 163a8c21a54SThe etnaviv authors mutex_lock(&gpu->mmu->lock); 164a8c21a54SThe etnaviv authors drm_mm_dump_table(m, &gpu->mmu->mm); 165a8c21a54SThe etnaviv authors mutex_unlock(&gpu->mmu->lock); 166a8c21a54SThe etnaviv authors 167a8c21a54SThe etnaviv authors return 0; 168a8c21a54SThe etnaviv authors } 169a8c21a54SThe etnaviv authors 170a8c21a54SThe etnaviv authors static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, struct seq_file *m) 171a8c21a54SThe etnaviv authors { 172a8c21a54SThe etnaviv authors struct etnaviv_cmdbuf *buf = gpu->buffer; 173a8c21a54SThe etnaviv authors u32 size = buf->size; 174a8c21a54SThe etnaviv authors u32 *ptr = buf->vaddr; 175a8c21a54SThe etnaviv authors u32 i; 176a8c21a54SThe etnaviv authors 177a8c21a54SThe etnaviv authors seq_printf(m, "virt %p - phys 0x%llx - free 0x%08x\n", 178a8c21a54SThe etnaviv authors buf->vaddr, (u64)buf->paddr, size - buf->user_size); 179a8c21a54SThe etnaviv authors 180a8c21a54SThe etnaviv authors for (i = 0; i < size / 4; i++) { 181a8c21a54SThe etnaviv authors if (i && !(i % 4)) 182a8c21a54SThe etnaviv authors seq_puts(m, "\n"); 183a8c21a54SThe etnaviv authors if (i % 4 == 0) 184a8c21a54SThe etnaviv authors seq_printf(m, "\t0x%p: ", ptr + i); 185a8c21a54SThe etnaviv authors seq_printf(m, "%08x ", *(ptr + i)); 186a8c21a54SThe etnaviv authors } 187a8c21a54SThe etnaviv authors seq_puts(m, "\n"); 188a8c21a54SThe etnaviv authors } 189a8c21a54SThe etnaviv authors 190a8c21a54SThe etnaviv authors static int etnaviv_ring_show(struct etnaviv_gpu *gpu, struct seq_file *m) 191a8c21a54SThe etnaviv authors { 192a8c21a54SThe etnaviv authors seq_printf(m, "Ring Buffer (%s): ", dev_name(gpu->dev)); 193a8c21a54SThe etnaviv authors 194a8c21a54SThe etnaviv authors mutex_lock(&gpu->lock); 195a8c21a54SThe etnaviv authors etnaviv_buffer_dump(gpu, m); 196a8c21a54SThe etnaviv authors mutex_unlock(&gpu->lock); 197a8c21a54SThe etnaviv authors 198a8c21a54SThe etnaviv authors return 0; 199a8c21a54SThe etnaviv authors } 200a8c21a54SThe etnaviv authors 201a8c21a54SThe etnaviv authors static int show_unlocked(struct seq_file *m, void *arg) 202a8c21a54SThe etnaviv authors { 203a8c21a54SThe etnaviv authors struct drm_info_node *node = (struct drm_info_node *) m->private; 204a8c21a54SThe etnaviv authors struct drm_device *dev = node->minor->dev; 205a8c21a54SThe etnaviv authors int (*show)(struct drm_device *dev, struct seq_file *m) = 206a8c21a54SThe etnaviv authors node->info_ent->data; 207a8c21a54SThe etnaviv authors 208a8c21a54SThe etnaviv authors return show(dev, m); 209a8c21a54SThe etnaviv authors } 210a8c21a54SThe etnaviv authors 211a8c21a54SThe etnaviv authors static int show_each_gpu(struct seq_file *m, void *arg) 212a8c21a54SThe etnaviv authors { 213a8c21a54SThe etnaviv authors struct drm_info_node *node = (struct drm_info_node *) m->private; 214a8c21a54SThe etnaviv authors struct drm_device *dev = node->minor->dev; 215a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 216a8c21a54SThe etnaviv authors struct etnaviv_gpu *gpu; 217a8c21a54SThe etnaviv authors int (*show)(struct etnaviv_gpu *gpu, struct seq_file *m) = 218a8c21a54SThe etnaviv authors node->info_ent->data; 219a8c21a54SThe etnaviv authors unsigned int i; 220a8c21a54SThe etnaviv authors int ret = 0; 221a8c21a54SThe etnaviv authors 222a8c21a54SThe etnaviv authors for (i = 0; i < ETNA_MAX_PIPES; i++) { 223a8c21a54SThe etnaviv authors gpu = priv->gpu[i]; 224a8c21a54SThe etnaviv authors if (!gpu) 225a8c21a54SThe etnaviv authors continue; 226a8c21a54SThe etnaviv authors 227a8c21a54SThe etnaviv authors ret = show(gpu, m); 228a8c21a54SThe etnaviv authors if (ret < 0) 229a8c21a54SThe etnaviv authors break; 230a8c21a54SThe etnaviv authors } 231a8c21a54SThe etnaviv authors 232a8c21a54SThe etnaviv authors return ret; 233a8c21a54SThe etnaviv authors } 234a8c21a54SThe etnaviv authors 235a8c21a54SThe etnaviv authors static struct drm_info_list etnaviv_debugfs_list[] = { 236a8c21a54SThe etnaviv authors {"gpu", show_each_gpu, 0, etnaviv_gpu_debugfs}, 237a8c21a54SThe etnaviv authors {"gem", show_unlocked, 0, etnaviv_gem_show}, 238a8c21a54SThe etnaviv authors { "mm", show_unlocked, 0, etnaviv_mm_show }, 239a8c21a54SThe etnaviv authors {"mmu", show_each_gpu, 0, etnaviv_mmu_show}, 240a8c21a54SThe etnaviv authors {"ring", show_each_gpu, 0, etnaviv_ring_show}, 241a8c21a54SThe etnaviv authors }; 242a8c21a54SThe etnaviv authors 243a8c21a54SThe etnaviv authors static int etnaviv_debugfs_init(struct drm_minor *minor) 244a8c21a54SThe etnaviv authors { 245a8c21a54SThe etnaviv authors struct drm_device *dev = minor->dev; 246a8c21a54SThe etnaviv authors int ret; 247a8c21a54SThe etnaviv authors 248a8c21a54SThe etnaviv authors ret = drm_debugfs_create_files(etnaviv_debugfs_list, 249a8c21a54SThe etnaviv authors ARRAY_SIZE(etnaviv_debugfs_list), 250a8c21a54SThe etnaviv authors minor->debugfs_root, minor); 251a8c21a54SThe etnaviv authors 252a8c21a54SThe etnaviv authors if (ret) { 253a8c21a54SThe etnaviv authors dev_err(dev->dev, "could not install etnaviv_debugfs_list\n"); 254a8c21a54SThe etnaviv authors return ret; 255a8c21a54SThe etnaviv authors } 256a8c21a54SThe etnaviv authors 257a8c21a54SThe etnaviv authors return ret; 258a8c21a54SThe etnaviv authors } 259a8c21a54SThe etnaviv authors 260a8c21a54SThe etnaviv authors static void etnaviv_debugfs_cleanup(struct drm_minor *minor) 261a8c21a54SThe etnaviv authors { 262a8c21a54SThe etnaviv authors drm_debugfs_remove_files(etnaviv_debugfs_list, 263a8c21a54SThe etnaviv authors ARRAY_SIZE(etnaviv_debugfs_list), minor); 264a8c21a54SThe etnaviv authors } 265a8c21a54SThe etnaviv authors #endif 266a8c21a54SThe etnaviv authors 267a8c21a54SThe etnaviv authors /* 268a8c21a54SThe etnaviv authors * DRM ioctls: 269a8c21a54SThe etnaviv authors */ 270a8c21a54SThe etnaviv authors 271a8c21a54SThe etnaviv authors static int etnaviv_ioctl_get_param(struct drm_device *dev, void *data, 272a8c21a54SThe etnaviv authors struct drm_file *file) 273a8c21a54SThe etnaviv authors { 274a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 275a8c21a54SThe etnaviv authors struct drm_etnaviv_param *args = data; 276a8c21a54SThe etnaviv authors struct etnaviv_gpu *gpu; 277a8c21a54SThe etnaviv authors 278a8c21a54SThe etnaviv authors if (args->pipe >= ETNA_MAX_PIPES) 279a8c21a54SThe etnaviv authors return -EINVAL; 280a8c21a54SThe etnaviv authors 281a8c21a54SThe etnaviv authors gpu = priv->gpu[args->pipe]; 282a8c21a54SThe etnaviv authors if (!gpu) 283a8c21a54SThe etnaviv authors return -ENXIO; 284a8c21a54SThe etnaviv authors 285a8c21a54SThe etnaviv authors return etnaviv_gpu_get_param(gpu, args->param, &args->value); 286a8c21a54SThe etnaviv authors } 287a8c21a54SThe etnaviv authors 288a8c21a54SThe etnaviv authors static int etnaviv_ioctl_gem_new(struct drm_device *dev, void *data, 289a8c21a54SThe etnaviv authors struct drm_file *file) 290a8c21a54SThe etnaviv authors { 291a8c21a54SThe etnaviv authors struct drm_etnaviv_gem_new *args = data; 292a8c21a54SThe etnaviv authors 293a8c21a54SThe etnaviv authors if (args->flags & ~(ETNA_BO_CACHED | ETNA_BO_WC | ETNA_BO_UNCACHED | 294a8c21a54SThe etnaviv authors ETNA_BO_FORCE_MMU)) 295a8c21a54SThe etnaviv authors return -EINVAL; 296a8c21a54SThe etnaviv authors 297a8c21a54SThe etnaviv authors return etnaviv_gem_new_handle(dev, file, args->size, 298a8c21a54SThe etnaviv authors args->flags, &args->handle); 299a8c21a54SThe etnaviv authors } 300a8c21a54SThe etnaviv authors 301a8c21a54SThe etnaviv authors #define TS(t) ((struct timespec){ \ 302a8c21a54SThe etnaviv authors .tv_sec = (t).tv_sec, \ 303a8c21a54SThe etnaviv authors .tv_nsec = (t).tv_nsec \ 304a8c21a54SThe etnaviv authors }) 305a8c21a54SThe etnaviv authors 306a8c21a54SThe etnaviv authors static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data, 307a8c21a54SThe etnaviv authors struct drm_file *file) 308a8c21a54SThe etnaviv authors { 309a8c21a54SThe etnaviv authors struct drm_etnaviv_gem_cpu_prep *args = data; 310a8c21a54SThe etnaviv authors struct drm_gem_object *obj; 311a8c21a54SThe etnaviv authors int ret; 312a8c21a54SThe etnaviv authors 313a8c21a54SThe etnaviv authors if (args->op & ~(ETNA_PREP_READ | ETNA_PREP_WRITE | ETNA_PREP_NOSYNC)) 314a8c21a54SThe etnaviv authors return -EINVAL; 315a8c21a54SThe etnaviv authors 316a8ad0bd8SChris Wilson obj = drm_gem_object_lookup(file, args->handle); 317a8c21a54SThe etnaviv authors if (!obj) 318a8c21a54SThe etnaviv authors return -ENOENT; 319a8c21a54SThe etnaviv authors 320a8c21a54SThe etnaviv authors ret = etnaviv_gem_cpu_prep(obj, args->op, &TS(args->timeout)); 321a8c21a54SThe etnaviv authors 322a8c21a54SThe etnaviv authors drm_gem_object_unreference_unlocked(obj); 323a8c21a54SThe etnaviv authors 324a8c21a54SThe etnaviv authors return ret; 325a8c21a54SThe etnaviv authors } 326a8c21a54SThe etnaviv authors 327a8c21a54SThe etnaviv authors static int etnaviv_ioctl_gem_cpu_fini(struct drm_device *dev, void *data, 328a8c21a54SThe etnaviv authors struct drm_file *file) 329a8c21a54SThe etnaviv authors { 330a8c21a54SThe etnaviv authors struct drm_etnaviv_gem_cpu_fini *args = data; 331a8c21a54SThe etnaviv authors struct drm_gem_object *obj; 332a8c21a54SThe etnaviv authors int ret; 333a8c21a54SThe etnaviv authors 334a8c21a54SThe etnaviv authors if (args->flags) 335a8c21a54SThe etnaviv authors return -EINVAL; 336a8c21a54SThe etnaviv authors 337a8ad0bd8SChris Wilson obj = drm_gem_object_lookup(file, args->handle); 338a8c21a54SThe etnaviv authors if (!obj) 339a8c21a54SThe etnaviv authors return -ENOENT; 340a8c21a54SThe etnaviv authors 341a8c21a54SThe etnaviv authors ret = etnaviv_gem_cpu_fini(obj); 342a8c21a54SThe etnaviv authors 343a8c21a54SThe etnaviv authors drm_gem_object_unreference_unlocked(obj); 344a8c21a54SThe etnaviv authors 345a8c21a54SThe etnaviv authors return ret; 346a8c21a54SThe etnaviv authors } 347a8c21a54SThe etnaviv authors 348a8c21a54SThe etnaviv authors static int etnaviv_ioctl_gem_info(struct drm_device *dev, void *data, 349a8c21a54SThe etnaviv authors struct drm_file *file) 350a8c21a54SThe etnaviv authors { 351a8c21a54SThe etnaviv authors struct drm_etnaviv_gem_info *args = data; 352a8c21a54SThe etnaviv authors struct drm_gem_object *obj; 353a8c21a54SThe etnaviv authors int ret; 354a8c21a54SThe etnaviv authors 355a8c21a54SThe etnaviv authors if (args->pad) 356a8c21a54SThe etnaviv authors return -EINVAL; 357a8c21a54SThe etnaviv authors 358a8ad0bd8SChris Wilson obj = drm_gem_object_lookup(file, args->handle); 359a8c21a54SThe etnaviv authors if (!obj) 360a8c21a54SThe etnaviv authors return -ENOENT; 361a8c21a54SThe etnaviv authors 362a8c21a54SThe etnaviv authors ret = etnaviv_gem_mmap_offset(obj, &args->offset); 363a8c21a54SThe etnaviv authors drm_gem_object_unreference_unlocked(obj); 364a8c21a54SThe etnaviv authors 365a8c21a54SThe etnaviv authors return ret; 366a8c21a54SThe etnaviv authors } 367a8c21a54SThe etnaviv authors 368a8c21a54SThe etnaviv authors static int etnaviv_ioctl_wait_fence(struct drm_device *dev, void *data, 369a8c21a54SThe etnaviv authors struct drm_file *file) 370a8c21a54SThe etnaviv authors { 371a8c21a54SThe etnaviv authors struct drm_etnaviv_wait_fence *args = data; 372a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 373a8c21a54SThe etnaviv authors struct timespec *timeout = &TS(args->timeout); 374a8c21a54SThe etnaviv authors struct etnaviv_gpu *gpu; 375a8c21a54SThe etnaviv authors 376a8c21a54SThe etnaviv authors if (args->flags & ~(ETNA_WAIT_NONBLOCK)) 377a8c21a54SThe etnaviv authors return -EINVAL; 378a8c21a54SThe etnaviv authors 379a8c21a54SThe etnaviv authors if (args->pipe >= ETNA_MAX_PIPES) 380a8c21a54SThe etnaviv authors return -EINVAL; 381a8c21a54SThe etnaviv authors 382a8c21a54SThe etnaviv authors gpu = priv->gpu[args->pipe]; 383a8c21a54SThe etnaviv authors if (!gpu) 384a8c21a54SThe etnaviv authors return -ENXIO; 385a8c21a54SThe etnaviv authors 386a8c21a54SThe etnaviv authors if (args->flags & ETNA_WAIT_NONBLOCK) 387a8c21a54SThe etnaviv authors timeout = NULL; 388a8c21a54SThe etnaviv authors 389a8c21a54SThe etnaviv authors return etnaviv_gpu_wait_fence_interruptible(gpu, args->fence, 390a8c21a54SThe etnaviv authors timeout); 391a8c21a54SThe etnaviv authors } 392a8c21a54SThe etnaviv authors 393a8c21a54SThe etnaviv authors static int etnaviv_ioctl_gem_userptr(struct drm_device *dev, void *data, 394a8c21a54SThe etnaviv authors struct drm_file *file) 395a8c21a54SThe etnaviv authors { 396a8c21a54SThe etnaviv authors struct drm_etnaviv_gem_userptr *args = data; 397a8c21a54SThe etnaviv authors int access; 398a8c21a54SThe etnaviv authors 399a8c21a54SThe etnaviv authors if (args->flags & ~(ETNA_USERPTR_READ|ETNA_USERPTR_WRITE) || 400a8c21a54SThe etnaviv authors args->flags == 0) 401a8c21a54SThe etnaviv authors return -EINVAL; 402a8c21a54SThe etnaviv authors 403a8c21a54SThe etnaviv authors if (offset_in_page(args->user_ptr | args->user_size) || 404a8c21a54SThe etnaviv authors (uintptr_t)args->user_ptr != args->user_ptr || 405a8c21a54SThe etnaviv authors (u32)args->user_size != args->user_size || 406a8c21a54SThe etnaviv authors args->user_ptr & ~PAGE_MASK) 407a8c21a54SThe etnaviv authors return -EINVAL; 408a8c21a54SThe etnaviv authors 409a8c21a54SThe etnaviv authors if (args->flags & ETNA_USERPTR_WRITE) 410a8c21a54SThe etnaviv authors access = VERIFY_WRITE; 411a8c21a54SThe etnaviv authors else 412a8c21a54SThe etnaviv authors access = VERIFY_READ; 413a8c21a54SThe etnaviv authors 414a8c21a54SThe etnaviv authors if (!access_ok(access, (void __user *)(unsigned long)args->user_ptr, 415a8c21a54SThe etnaviv authors args->user_size)) 416a8c21a54SThe etnaviv authors return -EFAULT; 417a8c21a54SThe etnaviv authors 418a8c21a54SThe etnaviv authors return etnaviv_gem_new_userptr(dev, file, args->user_ptr, 419a8c21a54SThe etnaviv authors args->user_size, args->flags, 420a8c21a54SThe etnaviv authors &args->handle); 421a8c21a54SThe etnaviv authors } 422a8c21a54SThe etnaviv authors 423a8c21a54SThe etnaviv authors static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data, 424a8c21a54SThe etnaviv authors struct drm_file *file) 425a8c21a54SThe etnaviv authors { 426a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 427a8c21a54SThe etnaviv authors struct drm_etnaviv_gem_wait *args = data; 428a8c21a54SThe etnaviv authors struct timespec *timeout = &TS(args->timeout); 429a8c21a54SThe etnaviv authors struct drm_gem_object *obj; 430a8c21a54SThe etnaviv authors struct etnaviv_gpu *gpu; 431a8c21a54SThe etnaviv authors int ret; 432a8c21a54SThe etnaviv authors 433a8c21a54SThe etnaviv authors if (args->flags & ~(ETNA_WAIT_NONBLOCK)) 434a8c21a54SThe etnaviv authors return -EINVAL; 435a8c21a54SThe etnaviv authors 436a8c21a54SThe etnaviv authors if (args->pipe >= ETNA_MAX_PIPES) 437a8c21a54SThe etnaviv authors return -EINVAL; 438a8c21a54SThe etnaviv authors 439a8c21a54SThe etnaviv authors gpu = priv->gpu[args->pipe]; 440a8c21a54SThe etnaviv authors if (!gpu) 441a8c21a54SThe etnaviv authors return -ENXIO; 442a8c21a54SThe etnaviv authors 443a8ad0bd8SChris Wilson obj = drm_gem_object_lookup(file, args->handle); 444a8c21a54SThe etnaviv authors if (!obj) 445a8c21a54SThe etnaviv authors return -ENOENT; 446a8c21a54SThe etnaviv authors 447a8c21a54SThe etnaviv authors if (args->flags & ETNA_WAIT_NONBLOCK) 448a8c21a54SThe etnaviv authors timeout = NULL; 449a8c21a54SThe etnaviv authors 450a8c21a54SThe etnaviv authors ret = etnaviv_gem_wait_bo(gpu, obj, timeout); 451a8c21a54SThe etnaviv authors 452a8c21a54SThe etnaviv authors drm_gem_object_unreference_unlocked(obj); 453a8c21a54SThe etnaviv authors 454a8c21a54SThe etnaviv authors return ret; 455a8c21a54SThe etnaviv authors } 456a8c21a54SThe etnaviv authors 457a8c21a54SThe etnaviv authors static const struct drm_ioctl_desc etnaviv_ioctls[] = { 458a8c21a54SThe etnaviv authors #define ETNA_IOCTL(n, func, flags) \ 459a8c21a54SThe etnaviv authors DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags) 460a8c21a54SThe etnaviv authors ETNA_IOCTL(GET_PARAM, get_param, DRM_AUTH|DRM_RENDER_ALLOW), 461a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_NEW, gem_new, DRM_AUTH|DRM_RENDER_ALLOW), 462a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_INFO, gem_info, DRM_AUTH|DRM_RENDER_ALLOW), 463a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_CPU_PREP, gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW), 464a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_CPU_FINI, gem_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW), 465a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_SUBMIT, gem_submit, DRM_AUTH|DRM_RENDER_ALLOW), 466a8c21a54SThe etnaviv authors ETNA_IOCTL(WAIT_FENCE, wait_fence, DRM_AUTH|DRM_RENDER_ALLOW), 467a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_USERPTR, gem_userptr, DRM_AUTH|DRM_RENDER_ALLOW), 468a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_WAIT, gem_wait, DRM_AUTH|DRM_RENDER_ALLOW), 469a8c21a54SThe etnaviv authors }; 470a8c21a54SThe etnaviv authors 471a8c21a54SThe etnaviv authors static const struct vm_operations_struct vm_ops = { 472a8c21a54SThe etnaviv authors .fault = etnaviv_gem_fault, 473a8c21a54SThe etnaviv authors .open = drm_gem_vm_open, 474a8c21a54SThe etnaviv authors .close = drm_gem_vm_close, 475a8c21a54SThe etnaviv authors }; 476a8c21a54SThe etnaviv authors 477a8c21a54SThe etnaviv authors static const struct file_operations fops = { 478a8c21a54SThe etnaviv authors .owner = THIS_MODULE, 479a8c21a54SThe etnaviv authors .open = drm_open, 480a8c21a54SThe etnaviv authors .release = drm_release, 481a8c21a54SThe etnaviv authors .unlocked_ioctl = drm_ioctl, 482a8c21a54SThe etnaviv authors .compat_ioctl = drm_compat_ioctl, 483a8c21a54SThe etnaviv authors .poll = drm_poll, 484a8c21a54SThe etnaviv authors .read = drm_read, 485a8c21a54SThe etnaviv authors .llseek = no_llseek, 486a8c21a54SThe etnaviv authors .mmap = etnaviv_gem_mmap, 487a8c21a54SThe etnaviv authors }; 488a8c21a54SThe etnaviv authors 489a8c21a54SThe etnaviv authors static struct drm_driver etnaviv_drm_driver = { 490e1f96ef4SShawn Guo .driver_features = DRIVER_GEM | 491a8c21a54SThe etnaviv authors DRIVER_PRIME | 492a8c21a54SThe etnaviv authors DRIVER_RENDER, 493a8c21a54SThe etnaviv authors .open = etnaviv_open, 494a8c21a54SThe etnaviv authors .preclose = etnaviv_preclose, 4951d657c58SDaniel Vetter .gem_free_object_unlocked = etnaviv_gem_free_object, 496a8c21a54SThe etnaviv authors .gem_vm_ops = &vm_ops, 497a8c21a54SThe etnaviv authors .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 498a8c21a54SThe etnaviv authors .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 499a8c21a54SThe etnaviv authors .gem_prime_export = drm_gem_prime_export, 500a8c21a54SThe etnaviv authors .gem_prime_import = drm_gem_prime_import, 501a8c21a54SThe etnaviv authors .gem_prime_pin = etnaviv_gem_prime_pin, 502a8c21a54SThe etnaviv authors .gem_prime_unpin = etnaviv_gem_prime_unpin, 503a8c21a54SThe etnaviv authors .gem_prime_get_sg_table = etnaviv_gem_prime_get_sg_table, 504a8c21a54SThe etnaviv authors .gem_prime_import_sg_table = etnaviv_gem_prime_import_sg_table, 505a8c21a54SThe etnaviv authors .gem_prime_vmap = etnaviv_gem_prime_vmap, 506a8c21a54SThe etnaviv authors .gem_prime_vunmap = etnaviv_gem_prime_vunmap, 5075688e57eSLucas Stach .gem_prime_mmap = etnaviv_gem_prime_mmap, 508a8c21a54SThe etnaviv authors #ifdef CONFIG_DEBUG_FS 509a8c21a54SThe etnaviv authors .debugfs_init = etnaviv_debugfs_init, 510a8c21a54SThe etnaviv authors .debugfs_cleanup = etnaviv_debugfs_cleanup, 511a8c21a54SThe etnaviv authors #endif 512a8c21a54SThe etnaviv authors .ioctls = etnaviv_ioctls, 513a8c21a54SThe etnaviv authors .num_ioctls = DRM_ETNAVIV_NUM_IOCTLS, 514a8c21a54SThe etnaviv authors .fops = &fops, 515a8c21a54SThe etnaviv authors .name = "etnaviv", 516a8c21a54SThe etnaviv authors .desc = "etnaviv DRM", 517a8c21a54SThe etnaviv authors .date = "20151214", 518a8c21a54SThe etnaviv authors .major = 1, 519a8c21a54SThe etnaviv authors .minor = 0, 520a8c21a54SThe etnaviv authors }; 521a8c21a54SThe etnaviv authors 522a8c21a54SThe etnaviv authors /* 523a8c21a54SThe etnaviv authors * Platform driver: 524a8c21a54SThe etnaviv authors */ 525a8c21a54SThe etnaviv authors static int etnaviv_bind(struct device *dev) 526a8c21a54SThe etnaviv authors { 527a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv; 528a8c21a54SThe etnaviv authors struct drm_device *drm; 529a8c21a54SThe etnaviv authors int ret; 530a8c21a54SThe etnaviv authors 531a8c21a54SThe etnaviv authors drm = drm_dev_alloc(&etnaviv_drm_driver, dev); 5320f288605STom Gundersen if (IS_ERR(drm)) 5330f288605STom Gundersen return PTR_ERR(drm); 534a8c21a54SThe etnaviv authors 535a8c21a54SThe etnaviv authors priv = kzalloc(sizeof(*priv), GFP_KERNEL); 536a8c21a54SThe etnaviv authors if (!priv) { 537a8c21a54SThe etnaviv authors dev_err(dev, "failed to allocate private data\n"); 538a8c21a54SThe etnaviv authors ret = -ENOMEM; 539a8c21a54SThe etnaviv authors goto out_unref; 540a8c21a54SThe etnaviv authors } 541a8c21a54SThe etnaviv authors drm->dev_private = priv; 542a8c21a54SThe etnaviv authors 543a8c21a54SThe etnaviv authors priv->wq = alloc_ordered_workqueue("etnaviv", 0); 544a8c21a54SThe etnaviv authors if (!priv->wq) { 545a8c21a54SThe etnaviv authors ret = -ENOMEM; 546a8c21a54SThe etnaviv authors goto out_wq; 547a8c21a54SThe etnaviv authors } 548a8c21a54SThe etnaviv authors 549a8c21a54SThe etnaviv authors mutex_init(&priv->gem_lock); 550a8c21a54SThe etnaviv authors INIT_LIST_HEAD(&priv->gem_list); 551a8c21a54SThe etnaviv authors priv->num_gpus = 0; 552a8c21a54SThe etnaviv authors 553a8c21a54SThe etnaviv authors dev_set_drvdata(dev, drm); 554a8c21a54SThe etnaviv authors 555a8c21a54SThe etnaviv authors ret = component_bind_all(dev, drm); 556a8c21a54SThe etnaviv authors if (ret < 0) 557a8c21a54SThe etnaviv authors goto out_bind; 558a8c21a54SThe etnaviv authors 559a8c21a54SThe etnaviv authors load_gpu(drm); 560a8c21a54SThe etnaviv authors 561a8c21a54SThe etnaviv authors ret = drm_dev_register(drm, 0); 562a8c21a54SThe etnaviv authors if (ret) 563a8c21a54SThe etnaviv authors goto out_register; 564a8c21a54SThe etnaviv authors 565a8c21a54SThe etnaviv authors return 0; 566a8c21a54SThe etnaviv authors 567a8c21a54SThe etnaviv authors out_register: 568a8c21a54SThe etnaviv authors component_unbind_all(dev, drm); 569a8c21a54SThe etnaviv authors out_bind: 570a8c21a54SThe etnaviv authors flush_workqueue(priv->wq); 571a8c21a54SThe etnaviv authors destroy_workqueue(priv->wq); 572a8c21a54SThe etnaviv authors out_wq: 573a8c21a54SThe etnaviv authors kfree(priv); 574a8c21a54SThe etnaviv authors out_unref: 575a8c21a54SThe etnaviv authors drm_dev_unref(drm); 576a8c21a54SThe etnaviv authors 577a8c21a54SThe etnaviv authors return ret; 578a8c21a54SThe etnaviv authors } 579a8c21a54SThe etnaviv authors 580a8c21a54SThe etnaviv authors static void etnaviv_unbind(struct device *dev) 581a8c21a54SThe etnaviv authors { 582a8c21a54SThe etnaviv authors struct drm_device *drm = dev_get_drvdata(dev); 583a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = drm->dev_private; 584a8c21a54SThe etnaviv authors 585a8c21a54SThe etnaviv authors drm_dev_unregister(drm); 586a8c21a54SThe etnaviv authors 587a8c21a54SThe etnaviv authors flush_workqueue(priv->wq); 588a8c21a54SThe etnaviv authors destroy_workqueue(priv->wq); 589a8c21a54SThe etnaviv authors 590a8c21a54SThe etnaviv authors component_unbind_all(dev, drm); 591a8c21a54SThe etnaviv authors 592a8c21a54SThe etnaviv authors drm->dev_private = NULL; 593a8c21a54SThe etnaviv authors kfree(priv); 594a8c21a54SThe etnaviv authors 595ecdfcebbSDaniel Vetter drm_dev_unref(drm); 596a8c21a54SThe etnaviv authors } 597a8c21a54SThe etnaviv authors 598a8c21a54SThe etnaviv authors static const struct component_master_ops etnaviv_master_ops = { 599a8c21a54SThe etnaviv authors .bind = etnaviv_bind, 600a8c21a54SThe etnaviv authors .unbind = etnaviv_unbind, 601a8c21a54SThe etnaviv authors }; 602a8c21a54SThe etnaviv authors 603a8c21a54SThe etnaviv authors static int compare_of(struct device *dev, void *data) 604a8c21a54SThe etnaviv authors { 605a8c21a54SThe etnaviv authors struct device_node *np = data; 606a8c21a54SThe etnaviv authors 607a8c21a54SThe etnaviv authors return dev->of_node == np; 608a8c21a54SThe etnaviv authors } 609a8c21a54SThe etnaviv authors 610a8c21a54SThe etnaviv authors static int compare_str(struct device *dev, void *data) 611a8c21a54SThe etnaviv authors { 612a8c21a54SThe etnaviv authors return !strcmp(dev_name(dev), data); 613a8c21a54SThe etnaviv authors } 614a8c21a54SThe etnaviv authors 615a8c21a54SThe etnaviv authors static int etnaviv_pdev_probe(struct platform_device *pdev) 616a8c21a54SThe etnaviv authors { 617a8c21a54SThe etnaviv authors struct device *dev = &pdev->dev; 618a8c21a54SThe etnaviv authors struct device_node *node = dev->of_node; 619a8c21a54SThe etnaviv authors struct component_match *match = NULL; 620a8c21a54SThe etnaviv authors 621a8c21a54SThe etnaviv authors dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 622a8c21a54SThe etnaviv authors 623a8c21a54SThe etnaviv authors if (node) { 624a8c21a54SThe etnaviv authors struct device_node *core_node; 625a8c21a54SThe etnaviv authors int i; 626a8c21a54SThe etnaviv authors 627a8c21a54SThe etnaviv authors for (i = 0; ; i++) { 628a8c21a54SThe etnaviv authors core_node = of_parse_phandle(node, "cores", i); 629a8c21a54SThe etnaviv authors if (!core_node) 630a8c21a54SThe etnaviv authors break; 631a8c21a54SThe etnaviv authors 63297ac0e47SRussell King drm_of_component_match_add(&pdev->dev, &match, 63397ac0e47SRussell King compare_of, core_node); 634a8c21a54SThe etnaviv authors of_node_put(core_node); 635a8c21a54SThe etnaviv authors } 636a8c21a54SThe etnaviv authors } else if (dev->platform_data) { 637a8c21a54SThe etnaviv authors char **names = dev->platform_data; 638a8c21a54SThe etnaviv authors unsigned i; 639a8c21a54SThe etnaviv authors 640a8c21a54SThe etnaviv authors for (i = 0; names[i]; i++) 641a8c21a54SThe etnaviv authors component_match_add(dev, &match, compare_str, names[i]); 642a8c21a54SThe etnaviv authors } 643a8c21a54SThe etnaviv authors 644a8c21a54SThe etnaviv authors return component_master_add_with_match(dev, &etnaviv_master_ops, match); 645a8c21a54SThe etnaviv authors } 646a8c21a54SThe etnaviv authors 647a8c21a54SThe etnaviv authors static int etnaviv_pdev_remove(struct platform_device *pdev) 648a8c21a54SThe etnaviv authors { 649a8c21a54SThe etnaviv authors component_master_del(&pdev->dev, &etnaviv_master_ops); 650a8c21a54SThe etnaviv authors 651a8c21a54SThe etnaviv authors return 0; 652a8c21a54SThe etnaviv authors } 653a8c21a54SThe etnaviv authors 654a8c21a54SThe etnaviv authors static const struct of_device_id dt_match[] = { 655a8c21a54SThe etnaviv authors { .compatible = "fsl,imx-gpu-subsystem" }, 656a8c21a54SThe etnaviv authors { .compatible = "marvell,dove-gpu-subsystem" }, 657a8c21a54SThe etnaviv authors {} 658a8c21a54SThe etnaviv authors }; 659a8c21a54SThe etnaviv authors MODULE_DEVICE_TABLE(of, dt_match); 660a8c21a54SThe etnaviv authors 661a8c21a54SThe etnaviv authors static struct platform_driver etnaviv_platform_driver = { 662a8c21a54SThe etnaviv authors .probe = etnaviv_pdev_probe, 663a8c21a54SThe etnaviv authors .remove = etnaviv_pdev_remove, 664a8c21a54SThe etnaviv authors .driver = { 665a8c21a54SThe etnaviv authors .name = "etnaviv", 666a8c21a54SThe etnaviv authors .of_match_table = dt_match, 667a8c21a54SThe etnaviv authors }, 668a8c21a54SThe etnaviv authors }; 669a8c21a54SThe etnaviv authors 670a8c21a54SThe etnaviv authors static int __init etnaviv_init(void) 671a8c21a54SThe etnaviv authors { 672a8c21a54SThe etnaviv authors int ret; 673a8c21a54SThe etnaviv authors 674a8c21a54SThe etnaviv authors etnaviv_validate_init(); 675a8c21a54SThe etnaviv authors 676a8c21a54SThe etnaviv authors ret = platform_driver_register(&etnaviv_gpu_driver); 677a8c21a54SThe etnaviv authors if (ret != 0) 678a8c21a54SThe etnaviv authors return ret; 679a8c21a54SThe etnaviv authors 680a8c21a54SThe etnaviv authors ret = platform_driver_register(&etnaviv_platform_driver); 681a8c21a54SThe etnaviv authors if (ret != 0) 682a8c21a54SThe etnaviv authors platform_driver_unregister(&etnaviv_gpu_driver); 683a8c21a54SThe etnaviv authors 684a8c21a54SThe etnaviv authors return ret; 685a8c21a54SThe etnaviv authors } 686a8c21a54SThe etnaviv authors module_init(etnaviv_init); 687a8c21a54SThe etnaviv authors 688a8c21a54SThe etnaviv authors static void __exit etnaviv_exit(void) 689a8c21a54SThe etnaviv authors { 690a8c21a54SThe etnaviv authors platform_driver_unregister(&etnaviv_gpu_driver); 691a8c21a54SThe etnaviv authors platform_driver_unregister(&etnaviv_platform_driver); 692a8c21a54SThe etnaviv authors } 693a8c21a54SThe etnaviv authors module_exit(etnaviv_exit); 694a8c21a54SThe etnaviv authors 695a8c21a54SThe etnaviv authors MODULE_AUTHOR("Christian Gmeiner <christian.gmeiner@gmail.com>"); 696a8c21a54SThe etnaviv authors MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>"); 697a8c21a54SThe etnaviv authors MODULE_AUTHOR("Lucas Stach <l.stach@pengutronix.de>"); 698a8c21a54SThe etnaviv authors MODULE_DESCRIPTION("etnaviv DRM Driver"); 699a8c21a54SThe etnaviv authors MODULE_LICENSE("GPL v2"); 700a8c21a54SThe etnaviv authors MODULE_ALIAS("platform:etnaviv"); 701