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 21ea1f5729SLucas Stach #include "etnaviv_cmdbuf.h" 22a8c21a54SThe etnaviv authors #include "etnaviv_drv.h" 23a8c21a54SThe etnaviv authors #include "etnaviv_gpu.h" 24a8c21a54SThe etnaviv authors #include "etnaviv_gem.h" 25a8c21a54SThe etnaviv authors #include "etnaviv_mmu.h" 269e2c2e27SChristian Gmeiner #include "etnaviv_perfmon.h" 27a8c21a54SThe etnaviv authors 28a8c21a54SThe etnaviv authors #ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING 29a8c21a54SThe etnaviv authors static bool reglog; 30a8c21a54SThe etnaviv authors MODULE_PARM_DESC(reglog, "Enable register read/write logging"); 31a8c21a54SThe etnaviv authors module_param(reglog, bool, 0600); 32a8c21a54SThe etnaviv authors #else 33a8c21a54SThe etnaviv authors #define reglog 0 34a8c21a54SThe etnaviv authors #endif 35a8c21a54SThe etnaviv authors 36a8c21a54SThe etnaviv authors void __iomem *etnaviv_ioremap(struct platform_device *pdev, const char *name, 37a8c21a54SThe etnaviv authors const char *dbgname) 38a8c21a54SThe etnaviv authors { 39a8c21a54SThe etnaviv authors struct resource *res; 40a8c21a54SThe etnaviv authors void __iomem *ptr; 41a8c21a54SThe etnaviv authors 42a8c21a54SThe etnaviv authors if (name) 43a8c21a54SThe etnaviv authors res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); 44a8c21a54SThe etnaviv authors else 45a8c21a54SThe etnaviv authors res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 46a8c21a54SThe etnaviv authors 47a8c21a54SThe etnaviv authors ptr = devm_ioremap_resource(&pdev->dev, res); 48a8c21a54SThe etnaviv authors if (IS_ERR(ptr)) { 49a8c21a54SThe etnaviv authors dev_err(&pdev->dev, "failed to ioremap %s: %ld\n", name, 50a8c21a54SThe etnaviv authors PTR_ERR(ptr)); 51a8c21a54SThe etnaviv authors return ptr; 52a8c21a54SThe etnaviv authors } 53a8c21a54SThe etnaviv authors 54a8c21a54SThe etnaviv authors if (reglog) 55a8c21a54SThe etnaviv authors dev_printk(KERN_DEBUG, &pdev->dev, "IO:region %s 0x%p %08zx\n", 56a8c21a54SThe etnaviv authors dbgname, ptr, (size_t)resource_size(res)); 57a8c21a54SThe etnaviv authors 58a8c21a54SThe etnaviv authors return ptr; 59a8c21a54SThe etnaviv authors } 60a8c21a54SThe etnaviv authors 61a8c21a54SThe etnaviv authors void etnaviv_writel(u32 data, void __iomem *addr) 62a8c21a54SThe etnaviv authors { 63a8c21a54SThe etnaviv authors if (reglog) 64a8c21a54SThe etnaviv authors printk(KERN_DEBUG "IO:W %p %08x\n", addr, data); 65a8c21a54SThe etnaviv authors 66a8c21a54SThe etnaviv authors writel(data, addr); 67a8c21a54SThe etnaviv authors } 68a8c21a54SThe etnaviv authors 69a8c21a54SThe etnaviv authors u32 etnaviv_readl(const void __iomem *addr) 70a8c21a54SThe etnaviv authors { 71a8c21a54SThe etnaviv authors u32 val = readl(addr); 72a8c21a54SThe etnaviv authors 73a8c21a54SThe etnaviv authors if (reglog) 74a8c21a54SThe etnaviv authors printk(KERN_DEBUG "IO:R %p %08x\n", addr, val); 75a8c21a54SThe etnaviv authors 76a8c21a54SThe etnaviv authors return val; 77a8c21a54SThe etnaviv authors } 78a8c21a54SThe etnaviv authors 79a8c21a54SThe etnaviv authors /* 80a8c21a54SThe etnaviv authors * DRM operations: 81a8c21a54SThe etnaviv authors */ 82a8c21a54SThe etnaviv authors 83a8c21a54SThe etnaviv authors 84a8c21a54SThe etnaviv authors static void load_gpu(struct drm_device *dev) 85a8c21a54SThe etnaviv authors { 86a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 87a8c21a54SThe etnaviv authors unsigned int i; 88a8c21a54SThe etnaviv authors 89a8c21a54SThe etnaviv authors for (i = 0; i < ETNA_MAX_PIPES; i++) { 90a8c21a54SThe etnaviv authors struct etnaviv_gpu *g = priv->gpu[i]; 91a8c21a54SThe etnaviv authors 92a8c21a54SThe etnaviv authors if (g) { 93a8c21a54SThe etnaviv authors int ret; 94a8c21a54SThe etnaviv authors 95a8c21a54SThe etnaviv authors ret = etnaviv_gpu_init(g); 96c1c77b0eSLucas Stach if (ret) 97a8c21a54SThe etnaviv authors priv->gpu[i] = NULL; 98a8c21a54SThe etnaviv authors } 99a8c21a54SThe etnaviv authors } 100a8c21a54SThe etnaviv authors } 101a8c21a54SThe etnaviv authors 102a8c21a54SThe etnaviv authors static int etnaviv_open(struct drm_device *dev, struct drm_file *file) 103a8c21a54SThe etnaviv authors { 104e93b6deeSLucas Stach struct etnaviv_drm_private *priv = dev->dev_private; 105a8c21a54SThe etnaviv authors struct etnaviv_file_private *ctx; 106e93b6deeSLucas Stach int i; 107a8c21a54SThe etnaviv authors 108a8c21a54SThe etnaviv authors ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 109a8c21a54SThe etnaviv authors if (!ctx) 110a8c21a54SThe etnaviv authors return -ENOMEM; 111a8c21a54SThe etnaviv authors 112e93b6deeSLucas Stach for (i = 0; i < ETNA_MAX_PIPES; i++) { 113e93b6deeSLucas Stach struct etnaviv_gpu *gpu = priv->gpu[i]; 114e93b6deeSLucas Stach 115e93b6deeSLucas Stach if (gpu) { 116e93b6deeSLucas Stach drm_sched_entity_init(&gpu->sched, 117e93b6deeSLucas Stach &ctx->sched_entity[i], 118e93b6deeSLucas Stach &gpu->sched.sched_rq[DRM_SCHED_PRIORITY_NORMAL], 119e93b6deeSLucas Stach 32, NULL); 120e93b6deeSLucas Stach } 121e93b6deeSLucas Stach } 122e93b6deeSLucas Stach 123a8c21a54SThe etnaviv authors file->driver_priv = ctx; 124a8c21a54SThe etnaviv authors 125a8c21a54SThe etnaviv authors return 0; 126a8c21a54SThe etnaviv authors } 127a8c21a54SThe etnaviv authors 128fda8fa5bSDaniel Vetter static void etnaviv_postclose(struct drm_device *dev, struct drm_file *file) 129a8c21a54SThe etnaviv authors { 130a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 131a8c21a54SThe etnaviv authors struct etnaviv_file_private *ctx = file->driver_priv; 132a8c21a54SThe etnaviv authors unsigned int i; 133a8c21a54SThe etnaviv authors 134a8c21a54SThe etnaviv authors for (i = 0; i < ETNA_MAX_PIPES; i++) { 135a8c21a54SThe etnaviv authors struct etnaviv_gpu *gpu = priv->gpu[i]; 136a8c21a54SThe etnaviv authors 137a8c21a54SThe etnaviv authors if (gpu) { 138a8c21a54SThe etnaviv authors mutex_lock(&gpu->lock); 139a8c21a54SThe etnaviv authors if (gpu->lastctx == ctx) 140a8c21a54SThe etnaviv authors gpu->lastctx = NULL; 141a8c21a54SThe etnaviv authors mutex_unlock(&gpu->lock); 142e93b6deeSLucas Stach 143e93b6deeSLucas Stach drm_sched_entity_fini(&gpu->sched, 144e93b6deeSLucas Stach &ctx->sched_entity[i]); 145a8c21a54SThe etnaviv authors } 146a8c21a54SThe etnaviv authors } 147a8c21a54SThe etnaviv authors 148a8c21a54SThe etnaviv authors kfree(ctx); 149a8c21a54SThe etnaviv authors } 150a8c21a54SThe etnaviv authors 151a8c21a54SThe etnaviv authors /* 152a8c21a54SThe etnaviv authors * DRM debugfs: 153a8c21a54SThe etnaviv authors */ 154a8c21a54SThe etnaviv authors 155a8c21a54SThe etnaviv authors #ifdef CONFIG_DEBUG_FS 156a8c21a54SThe etnaviv authors static int etnaviv_gem_show(struct drm_device *dev, struct seq_file *m) 157a8c21a54SThe etnaviv authors { 158a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 159a8c21a54SThe etnaviv authors 160a8c21a54SThe etnaviv authors etnaviv_gem_describe_objects(priv, m); 161a8c21a54SThe etnaviv authors 162a8c21a54SThe etnaviv authors return 0; 163a8c21a54SThe etnaviv authors } 164a8c21a54SThe etnaviv authors 165a8c21a54SThe etnaviv authors static int etnaviv_mm_show(struct drm_device *dev, struct seq_file *m) 166a8c21a54SThe etnaviv authors { 167b5c3714fSDaniel Vetter struct drm_printer p = drm_seq_file_printer(m); 168a8c21a54SThe etnaviv authors 169a8c21a54SThe etnaviv authors read_lock(&dev->vma_offset_manager->vm_lock); 170b5c3714fSDaniel Vetter drm_mm_print(&dev->vma_offset_manager->vm_addr_space_mm, &p); 171a8c21a54SThe etnaviv authors read_unlock(&dev->vma_offset_manager->vm_lock); 172a8c21a54SThe etnaviv authors 173b5c3714fSDaniel Vetter return 0; 174a8c21a54SThe etnaviv authors } 175a8c21a54SThe etnaviv authors 176a8c21a54SThe etnaviv authors static int etnaviv_mmu_show(struct etnaviv_gpu *gpu, struct seq_file *m) 177a8c21a54SThe etnaviv authors { 178b5c3714fSDaniel Vetter struct drm_printer p = drm_seq_file_printer(m); 179b5c3714fSDaniel Vetter 180a8c21a54SThe etnaviv authors seq_printf(m, "Active Objects (%s):\n", dev_name(gpu->dev)); 181a8c21a54SThe etnaviv authors 182a8c21a54SThe etnaviv authors mutex_lock(&gpu->mmu->lock); 183b5c3714fSDaniel Vetter drm_mm_print(&gpu->mmu->mm, &p); 184a8c21a54SThe etnaviv authors mutex_unlock(&gpu->mmu->lock); 185a8c21a54SThe etnaviv authors 186a8c21a54SThe etnaviv authors return 0; 187a8c21a54SThe etnaviv authors } 188a8c21a54SThe etnaviv authors 189a8c21a54SThe etnaviv authors static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, struct seq_file *m) 190a8c21a54SThe etnaviv authors { 1912f9225dbSLucas Stach struct etnaviv_cmdbuf *buf = &gpu->buffer; 192a8c21a54SThe etnaviv authors u32 size = buf->size; 193a8c21a54SThe etnaviv authors u32 *ptr = buf->vaddr; 194a8c21a54SThe etnaviv authors u32 i; 195a8c21a54SThe etnaviv authors 196a8c21a54SThe etnaviv authors seq_printf(m, "virt %p - phys 0x%llx - free 0x%08x\n", 1979912b4dbSLucas Stach buf->vaddr, (u64)etnaviv_cmdbuf_get_pa(buf), 1989912b4dbSLucas Stach size - buf->user_size); 199a8c21a54SThe etnaviv authors 200a8c21a54SThe etnaviv authors for (i = 0; i < size / 4; i++) { 201a8c21a54SThe etnaviv authors if (i && !(i % 4)) 202a8c21a54SThe etnaviv authors seq_puts(m, "\n"); 203a8c21a54SThe etnaviv authors if (i % 4 == 0) 204a8c21a54SThe etnaviv authors seq_printf(m, "\t0x%p: ", ptr + i); 205a8c21a54SThe etnaviv authors seq_printf(m, "%08x ", *(ptr + i)); 206a8c21a54SThe etnaviv authors } 207a8c21a54SThe etnaviv authors seq_puts(m, "\n"); 208a8c21a54SThe etnaviv authors } 209a8c21a54SThe etnaviv authors 210a8c21a54SThe etnaviv authors static int etnaviv_ring_show(struct etnaviv_gpu *gpu, struct seq_file *m) 211a8c21a54SThe etnaviv authors { 212a8c21a54SThe etnaviv authors seq_printf(m, "Ring Buffer (%s): ", dev_name(gpu->dev)); 213a8c21a54SThe etnaviv authors 214a8c21a54SThe etnaviv authors mutex_lock(&gpu->lock); 215a8c21a54SThe etnaviv authors etnaviv_buffer_dump(gpu, m); 216a8c21a54SThe etnaviv authors mutex_unlock(&gpu->lock); 217a8c21a54SThe etnaviv authors 218a8c21a54SThe etnaviv authors return 0; 219a8c21a54SThe etnaviv authors } 220a8c21a54SThe etnaviv authors 221a8c21a54SThe etnaviv authors static int show_unlocked(struct seq_file *m, void *arg) 222a8c21a54SThe etnaviv authors { 223a8c21a54SThe etnaviv authors struct drm_info_node *node = (struct drm_info_node *) m->private; 224a8c21a54SThe etnaviv authors struct drm_device *dev = node->minor->dev; 225a8c21a54SThe etnaviv authors int (*show)(struct drm_device *dev, struct seq_file *m) = 226a8c21a54SThe etnaviv authors node->info_ent->data; 227a8c21a54SThe etnaviv authors 228a8c21a54SThe etnaviv authors return show(dev, m); 229a8c21a54SThe etnaviv authors } 230a8c21a54SThe etnaviv authors 231a8c21a54SThe etnaviv authors static int show_each_gpu(struct seq_file *m, void *arg) 232a8c21a54SThe etnaviv authors { 233a8c21a54SThe etnaviv authors struct drm_info_node *node = (struct drm_info_node *) m->private; 234a8c21a54SThe etnaviv authors struct drm_device *dev = node->minor->dev; 235a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 236a8c21a54SThe etnaviv authors struct etnaviv_gpu *gpu; 237a8c21a54SThe etnaviv authors int (*show)(struct etnaviv_gpu *gpu, struct seq_file *m) = 238a8c21a54SThe etnaviv authors node->info_ent->data; 239a8c21a54SThe etnaviv authors unsigned int i; 240a8c21a54SThe etnaviv authors int ret = 0; 241a8c21a54SThe etnaviv authors 242a8c21a54SThe etnaviv authors for (i = 0; i < ETNA_MAX_PIPES; i++) { 243a8c21a54SThe etnaviv authors gpu = priv->gpu[i]; 244a8c21a54SThe etnaviv authors if (!gpu) 245a8c21a54SThe etnaviv authors continue; 246a8c21a54SThe etnaviv authors 247a8c21a54SThe etnaviv authors ret = show(gpu, m); 248a8c21a54SThe etnaviv authors if (ret < 0) 249a8c21a54SThe etnaviv authors break; 250a8c21a54SThe etnaviv authors } 251a8c21a54SThe etnaviv authors 252a8c21a54SThe etnaviv authors return ret; 253a8c21a54SThe etnaviv authors } 254a8c21a54SThe etnaviv authors 255a8c21a54SThe etnaviv authors static struct drm_info_list etnaviv_debugfs_list[] = { 256a8c21a54SThe etnaviv authors {"gpu", show_each_gpu, 0, etnaviv_gpu_debugfs}, 257a8c21a54SThe etnaviv authors {"gem", show_unlocked, 0, etnaviv_gem_show}, 258a8c21a54SThe etnaviv authors { "mm", show_unlocked, 0, etnaviv_mm_show }, 259a8c21a54SThe etnaviv authors {"mmu", show_each_gpu, 0, etnaviv_mmu_show}, 260a8c21a54SThe etnaviv authors {"ring", show_each_gpu, 0, etnaviv_ring_show}, 261a8c21a54SThe etnaviv authors }; 262a8c21a54SThe etnaviv authors 263a8c21a54SThe etnaviv authors static int etnaviv_debugfs_init(struct drm_minor *minor) 264a8c21a54SThe etnaviv authors { 265a8c21a54SThe etnaviv authors struct drm_device *dev = minor->dev; 266a8c21a54SThe etnaviv authors int ret; 267a8c21a54SThe etnaviv authors 268a8c21a54SThe etnaviv authors ret = drm_debugfs_create_files(etnaviv_debugfs_list, 269a8c21a54SThe etnaviv authors ARRAY_SIZE(etnaviv_debugfs_list), 270a8c21a54SThe etnaviv authors minor->debugfs_root, minor); 271a8c21a54SThe etnaviv authors 272a8c21a54SThe etnaviv authors if (ret) { 273a8c21a54SThe etnaviv authors dev_err(dev->dev, "could not install etnaviv_debugfs_list\n"); 274a8c21a54SThe etnaviv authors return ret; 275a8c21a54SThe etnaviv authors } 276a8c21a54SThe etnaviv authors 277a8c21a54SThe etnaviv authors return ret; 278a8c21a54SThe etnaviv authors } 279a8c21a54SThe etnaviv authors #endif 280a8c21a54SThe etnaviv authors 281a8c21a54SThe etnaviv authors /* 282a8c21a54SThe etnaviv authors * DRM ioctls: 283a8c21a54SThe etnaviv authors */ 284a8c21a54SThe etnaviv authors 285a8c21a54SThe etnaviv authors static int etnaviv_ioctl_get_param(struct drm_device *dev, void *data, 286a8c21a54SThe etnaviv authors struct drm_file *file) 287a8c21a54SThe etnaviv authors { 288a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 289a8c21a54SThe etnaviv authors struct drm_etnaviv_param *args = data; 290a8c21a54SThe etnaviv authors struct etnaviv_gpu *gpu; 291a8c21a54SThe etnaviv authors 292a8c21a54SThe etnaviv authors if (args->pipe >= ETNA_MAX_PIPES) 293a8c21a54SThe etnaviv authors return -EINVAL; 294a8c21a54SThe etnaviv authors 295a8c21a54SThe etnaviv authors gpu = priv->gpu[args->pipe]; 296a8c21a54SThe etnaviv authors if (!gpu) 297a8c21a54SThe etnaviv authors return -ENXIO; 298a8c21a54SThe etnaviv authors 299a8c21a54SThe etnaviv authors return etnaviv_gpu_get_param(gpu, args->param, &args->value); 300a8c21a54SThe etnaviv authors } 301a8c21a54SThe etnaviv authors 302a8c21a54SThe etnaviv authors static int etnaviv_ioctl_gem_new(struct drm_device *dev, void *data, 303a8c21a54SThe etnaviv authors struct drm_file *file) 304a8c21a54SThe etnaviv authors { 305a8c21a54SThe etnaviv authors struct drm_etnaviv_gem_new *args = data; 306a8c21a54SThe etnaviv authors 307a8c21a54SThe etnaviv authors if (args->flags & ~(ETNA_BO_CACHED | ETNA_BO_WC | ETNA_BO_UNCACHED | 308a8c21a54SThe etnaviv authors ETNA_BO_FORCE_MMU)) 309a8c21a54SThe etnaviv authors return -EINVAL; 310a8c21a54SThe etnaviv authors 311a8c21a54SThe etnaviv authors return etnaviv_gem_new_handle(dev, file, args->size, 312a8c21a54SThe etnaviv authors args->flags, &args->handle); 313a8c21a54SThe etnaviv authors } 314a8c21a54SThe etnaviv authors 315a8c21a54SThe etnaviv authors #define TS(t) ((struct timespec){ \ 316a8c21a54SThe etnaviv authors .tv_sec = (t).tv_sec, \ 317a8c21a54SThe etnaviv authors .tv_nsec = (t).tv_nsec \ 318a8c21a54SThe etnaviv authors }) 319a8c21a54SThe etnaviv authors 320a8c21a54SThe etnaviv authors static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data, 321a8c21a54SThe etnaviv authors struct drm_file *file) 322a8c21a54SThe etnaviv authors { 323a8c21a54SThe etnaviv authors struct drm_etnaviv_gem_cpu_prep *args = data; 324a8c21a54SThe etnaviv authors struct drm_gem_object *obj; 325a8c21a54SThe etnaviv authors int ret; 326a8c21a54SThe etnaviv authors 327a8c21a54SThe etnaviv authors if (args->op & ~(ETNA_PREP_READ | ETNA_PREP_WRITE | ETNA_PREP_NOSYNC)) 328a8c21a54SThe etnaviv authors return -EINVAL; 329a8c21a54SThe etnaviv authors 330a8ad0bd8SChris Wilson obj = drm_gem_object_lookup(file, args->handle); 331a8c21a54SThe etnaviv authors if (!obj) 332a8c21a54SThe etnaviv authors return -ENOENT; 333a8c21a54SThe etnaviv authors 334a8c21a54SThe etnaviv authors ret = etnaviv_gem_cpu_prep(obj, args->op, &TS(args->timeout)); 335a8c21a54SThe etnaviv authors 33623d1dd03SCihangir Akturk drm_gem_object_put_unlocked(obj); 337a8c21a54SThe etnaviv authors 338a8c21a54SThe etnaviv authors return ret; 339a8c21a54SThe etnaviv authors } 340a8c21a54SThe etnaviv authors 341a8c21a54SThe etnaviv authors static int etnaviv_ioctl_gem_cpu_fini(struct drm_device *dev, void *data, 342a8c21a54SThe etnaviv authors struct drm_file *file) 343a8c21a54SThe etnaviv authors { 344a8c21a54SThe etnaviv authors struct drm_etnaviv_gem_cpu_fini *args = data; 345a8c21a54SThe etnaviv authors struct drm_gem_object *obj; 346a8c21a54SThe etnaviv authors int ret; 347a8c21a54SThe etnaviv authors 348a8c21a54SThe etnaviv authors if (args->flags) 349a8c21a54SThe etnaviv authors return -EINVAL; 350a8c21a54SThe etnaviv authors 351a8ad0bd8SChris Wilson obj = drm_gem_object_lookup(file, args->handle); 352a8c21a54SThe etnaviv authors if (!obj) 353a8c21a54SThe etnaviv authors return -ENOENT; 354a8c21a54SThe etnaviv authors 355a8c21a54SThe etnaviv authors ret = etnaviv_gem_cpu_fini(obj); 356a8c21a54SThe etnaviv authors 35723d1dd03SCihangir Akturk drm_gem_object_put_unlocked(obj); 358a8c21a54SThe etnaviv authors 359a8c21a54SThe etnaviv authors return ret; 360a8c21a54SThe etnaviv authors } 361a8c21a54SThe etnaviv authors 362a8c21a54SThe etnaviv authors static int etnaviv_ioctl_gem_info(struct drm_device *dev, void *data, 363a8c21a54SThe etnaviv authors struct drm_file *file) 364a8c21a54SThe etnaviv authors { 365a8c21a54SThe etnaviv authors struct drm_etnaviv_gem_info *args = data; 366a8c21a54SThe etnaviv authors struct drm_gem_object *obj; 367a8c21a54SThe etnaviv authors int ret; 368a8c21a54SThe etnaviv authors 369a8c21a54SThe etnaviv authors if (args->pad) 370a8c21a54SThe etnaviv authors return -EINVAL; 371a8c21a54SThe etnaviv authors 372a8ad0bd8SChris Wilson obj = drm_gem_object_lookup(file, args->handle); 373a8c21a54SThe etnaviv authors if (!obj) 374a8c21a54SThe etnaviv authors return -ENOENT; 375a8c21a54SThe etnaviv authors 376a8c21a54SThe etnaviv authors ret = etnaviv_gem_mmap_offset(obj, &args->offset); 37723d1dd03SCihangir Akturk drm_gem_object_put_unlocked(obj); 378a8c21a54SThe etnaviv authors 379a8c21a54SThe etnaviv authors return ret; 380a8c21a54SThe etnaviv authors } 381a8c21a54SThe etnaviv authors 382a8c21a54SThe etnaviv authors static int etnaviv_ioctl_wait_fence(struct drm_device *dev, void *data, 383a8c21a54SThe etnaviv authors struct drm_file *file) 384a8c21a54SThe etnaviv authors { 385a8c21a54SThe etnaviv authors struct drm_etnaviv_wait_fence *args = data; 386a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 387a8c21a54SThe etnaviv authors struct timespec *timeout = &TS(args->timeout); 388a8c21a54SThe etnaviv authors struct etnaviv_gpu *gpu; 389a8c21a54SThe etnaviv authors 390a8c21a54SThe etnaviv authors if (args->flags & ~(ETNA_WAIT_NONBLOCK)) 391a8c21a54SThe etnaviv authors return -EINVAL; 392a8c21a54SThe etnaviv authors 393a8c21a54SThe etnaviv authors if (args->pipe >= ETNA_MAX_PIPES) 394a8c21a54SThe etnaviv authors return -EINVAL; 395a8c21a54SThe etnaviv authors 396a8c21a54SThe etnaviv authors gpu = priv->gpu[args->pipe]; 397a8c21a54SThe etnaviv authors if (!gpu) 398a8c21a54SThe etnaviv authors return -ENXIO; 399a8c21a54SThe etnaviv authors 400a8c21a54SThe etnaviv authors if (args->flags & ETNA_WAIT_NONBLOCK) 401a8c21a54SThe etnaviv authors timeout = NULL; 402a8c21a54SThe etnaviv authors 403a8c21a54SThe etnaviv authors return etnaviv_gpu_wait_fence_interruptible(gpu, args->fence, 404a8c21a54SThe etnaviv authors timeout); 405a8c21a54SThe etnaviv authors } 406a8c21a54SThe etnaviv authors 407a8c21a54SThe etnaviv authors static int etnaviv_ioctl_gem_userptr(struct drm_device *dev, void *data, 408a8c21a54SThe etnaviv authors struct drm_file *file) 409a8c21a54SThe etnaviv authors { 410a8c21a54SThe etnaviv authors struct drm_etnaviv_gem_userptr *args = data; 411a8c21a54SThe etnaviv authors int access; 412a8c21a54SThe etnaviv authors 413a8c21a54SThe etnaviv authors if (args->flags & ~(ETNA_USERPTR_READ|ETNA_USERPTR_WRITE) || 414a8c21a54SThe etnaviv authors args->flags == 0) 415a8c21a54SThe etnaviv authors return -EINVAL; 416a8c21a54SThe etnaviv authors 417a8c21a54SThe etnaviv authors if (offset_in_page(args->user_ptr | args->user_size) || 418a8c21a54SThe etnaviv authors (uintptr_t)args->user_ptr != args->user_ptr || 419a8c21a54SThe etnaviv authors (u32)args->user_size != args->user_size || 420a8c21a54SThe etnaviv authors args->user_ptr & ~PAGE_MASK) 421a8c21a54SThe etnaviv authors return -EINVAL; 422a8c21a54SThe etnaviv authors 423a8c21a54SThe etnaviv authors if (args->flags & ETNA_USERPTR_WRITE) 424a8c21a54SThe etnaviv authors access = VERIFY_WRITE; 425a8c21a54SThe etnaviv authors else 426a8c21a54SThe etnaviv authors access = VERIFY_READ; 427a8c21a54SThe etnaviv authors 428a8c21a54SThe etnaviv authors if (!access_ok(access, (void __user *)(unsigned long)args->user_ptr, 429a8c21a54SThe etnaviv authors args->user_size)) 430a8c21a54SThe etnaviv authors return -EFAULT; 431a8c21a54SThe etnaviv authors 432a8c21a54SThe etnaviv authors return etnaviv_gem_new_userptr(dev, file, args->user_ptr, 433a8c21a54SThe etnaviv authors args->user_size, args->flags, 434a8c21a54SThe etnaviv authors &args->handle); 435a8c21a54SThe etnaviv authors } 436a8c21a54SThe etnaviv authors 437a8c21a54SThe etnaviv authors static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data, 438a8c21a54SThe etnaviv authors struct drm_file *file) 439a8c21a54SThe etnaviv authors { 440a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = dev->dev_private; 441a8c21a54SThe etnaviv authors struct drm_etnaviv_gem_wait *args = data; 442a8c21a54SThe etnaviv authors struct timespec *timeout = &TS(args->timeout); 443a8c21a54SThe etnaviv authors struct drm_gem_object *obj; 444a8c21a54SThe etnaviv authors struct etnaviv_gpu *gpu; 445a8c21a54SThe etnaviv authors int ret; 446a8c21a54SThe etnaviv authors 447a8c21a54SThe etnaviv authors if (args->flags & ~(ETNA_WAIT_NONBLOCK)) 448a8c21a54SThe etnaviv authors return -EINVAL; 449a8c21a54SThe etnaviv authors 450a8c21a54SThe etnaviv authors if (args->pipe >= ETNA_MAX_PIPES) 451a8c21a54SThe etnaviv authors return -EINVAL; 452a8c21a54SThe etnaviv authors 453a8c21a54SThe etnaviv authors gpu = priv->gpu[args->pipe]; 454a8c21a54SThe etnaviv authors if (!gpu) 455a8c21a54SThe etnaviv authors return -ENXIO; 456a8c21a54SThe etnaviv authors 457a8ad0bd8SChris Wilson obj = drm_gem_object_lookup(file, args->handle); 458a8c21a54SThe etnaviv authors if (!obj) 459a8c21a54SThe etnaviv authors return -ENOENT; 460a8c21a54SThe etnaviv authors 461a8c21a54SThe etnaviv authors if (args->flags & ETNA_WAIT_NONBLOCK) 462a8c21a54SThe etnaviv authors timeout = NULL; 463a8c21a54SThe etnaviv authors 464a8c21a54SThe etnaviv authors ret = etnaviv_gem_wait_bo(gpu, obj, timeout); 465a8c21a54SThe etnaviv authors 46623d1dd03SCihangir Akturk drm_gem_object_put_unlocked(obj); 467a8c21a54SThe etnaviv authors 468a8c21a54SThe etnaviv authors return ret; 469a8c21a54SThe etnaviv authors } 470a8c21a54SThe etnaviv authors 4719e2c2e27SChristian Gmeiner static int etnaviv_ioctl_pm_query_dom(struct drm_device *dev, void *data, 4729e2c2e27SChristian Gmeiner struct drm_file *file) 4739e2c2e27SChristian Gmeiner { 4749e2c2e27SChristian Gmeiner struct etnaviv_drm_private *priv = dev->dev_private; 4759e2c2e27SChristian Gmeiner struct drm_etnaviv_pm_domain *args = data; 4769e2c2e27SChristian Gmeiner struct etnaviv_gpu *gpu; 4779e2c2e27SChristian Gmeiner 4789e2c2e27SChristian Gmeiner if (args->pipe >= ETNA_MAX_PIPES) 4799e2c2e27SChristian Gmeiner return -EINVAL; 4809e2c2e27SChristian Gmeiner 4819e2c2e27SChristian Gmeiner gpu = priv->gpu[args->pipe]; 4829e2c2e27SChristian Gmeiner if (!gpu) 4839e2c2e27SChristian Gmeiner return -ENXIO; 4849e2c2e27SChristian Gmeiner 4859e2c2e27SChristian Gmeiner return etnaviv_pm_query_dom(gpu, args); 4869e2c2e27SChristian Gmeiner } 4879e2c2e27SChristian Gmeiner 4889e2c2e27SChristian Gmeiner static int etnaviv_ioctl_pm_query_sig(struct drm_device *dev, void *data, 4899e2c2e27SChristian Gmeiner struct drm_file *file) 4909e2c2e27SChristian Gmeiner { 4919e2c2e27SChristian Gmeiner struct etnaviv_drm_private *priv = dev->dev_private; 4929e2c2e27SChristian Gmeiner struct drm_etnaviv_pm_signal *args = data; 4939e2c2e27SChristian Gmeiner struct etnaviv_gpu *gpu; 4949e2c2e27SChristian Gmeiner 4959e2c2e27SChristian Gmeiner if (args->pipe >= ETNA_MAX_PIPES) 4969e2c2e27SChristian Gmeiner return -EINVAL; 4979e2c2e27SChristian Gmeiner 4989e2c2e27SChristian Gmeiner gpu = priv->gpu[args->pipe]; 4999e2c2e27SChristian Gmeiner if (!gpu) 5009e2c2e27SChristian Gmeiner return -ENXIO; 5019e2c2e27SChristian Gmeiner 5029e2c2e27SChristian Gmeiner return etnaviv_pm_query_sig(gpu, args); 5039e2c2e27SChristian Gmeiner } 5049e2c2e27SChristian Gmeiner 505a8c21a54SThe etnaviv authors static const struct drm_ioctl_desc etnaviv_ioctls[] = { 506a8c21a54SThe etnaviv authors #define ETNA_IOCTL(n, func, flags) \ 507a8c21a54SThe etnaviv authors DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags) 508a8c21a54SThe etnaviv authors ETNA_IOCTL(GET_PARAM, get_param, DRM_AUTH|DRM_RENDER_ALLOW), 509a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_NEW, gem_new, DRM_AUTH|DRM_RENDER_ALLOW), 510a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_INFO, gem_info, DRM_AUTH|DRM_RENDER_ALLOW), 511a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_CPU_PREP, gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW), 512a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_CPU_FINI, gem_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW), 513a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_SUBMIT, gem_submit, DRM_AUTH|DRM_RENDER_ALLOW), 514a8c21a54SThe etnaviv authors ETNA_IOCTL(WAIT_FENCE, wait_fence, DRM_AUTH|DRM_RENDER_ALLOW), 515a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_USERPTR, gem_userptr, DRM_AUTH|DRM_RENDER_ALLOW), 516a8c21a54SThe etnaviv authors ETNA_IOCTL(GEM_WAIT, gem_wait, DRM_AUTH|DRM_RENDER_ALLOW), 5179e2c2e27SChristian Gmeiner ETNA_IOCTL(PM_QUERY_DOM, pm_query_dom, DRM_AUTH|DRM_RENDER_ALLOW), 5189e2c2e27SChristian Gmeiner ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_AUTH|DRM_RENDER_ALLOW), 519a8c21a54SThe etnaviv authors }; 520a8c21a54SThe etnaviv authors 521a8c21a54SThe etnaviv authors static const struct vm_operations_struct vm_ops = { 522a8c21a54SThe etnaviv authors .fault = etnaviv_gem_fault, 523a8c21a54SThe etnaviv authors .open = drm_gem_vm_open, 524a8c21a54SThe etnaviv authors .close = drm_gem_vm_close, 525a8c21a54SThe etnaviv authors }; 526a8c21a54SThe etnaviv authors 527a8c21a54SThe etnaviv authors static const struct file_operations fops = { 528a8c21a54SThe etnaviv authors .owner = THIS_MODULE, 529a8c21a54SThe etnaviv authors .open = drm_open, 530a8c21a54SThe etnaviv authors .release = drm_release, 531a8c21a54SThe etnaviv authors .unlocked_ioctl = drm_ioctl, 532a8c21a54SThe etnaviv authors .compat_ioctl = drm_compat_ioctl, 533a8c21a54SThe etnaviv authors .poll = drm_poll, 534a8c21a54SThe etnaviv authors .read = drm_read, 535a8c21a54SThe etnaviv authors .llseek = no_llseek, 536a8c21a54SThe etnaviv authors .mmap = etnaviv_gem_mmap, 537a8c21a54SThe etnaviv authors }; 538a8c21a54SThe etnaviv authors 539a8c21a54SThe etnaviv authors static struct drm_driver etnaviv_drm_driver = { 540e1f96ef4SShawn Guo .driver_features = DRIVER_GEM | 541a8c21a54SThe etnaviv authors DRIVER_PRIME | 542a8c21a54SThe etnaviv authors DRIVER_RENDER, 543a8c21a54SThe etnaviv authors .open = etnaviv_open, 544fda8fa5bSDaniel Vetter .postclose = etnaviv_postclose, 5451d657c58SDaniel Vetter .gem_free_object_unlocked = etnaviv_gem_free_object, 546a8c21a54SThe etnaviv authors .gem_vm_ops = &vm_ops, 547a8c21a54SThe etnaviv authors .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 548a8c21a54SThe etnaviv authors .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 549a8c21a54SThe etnaviv authors .gem_prime_export = drm_gem_prime_export, 550a8c21a54SThe etnaviv authors .gem_prime_import = drm_gem_prime_import, 5518555137eSEric Anholt .gem_prime_res_obj = etnaviv_gem_prime_res_obj, 552a8c21a54SThe etnaviv authors .gem_prime_pin = etnaviv_gem_prime_pin, 553a8c21a54SThe etnaviv authors .gem_prime_unpin = etnaviv_gem_prime_unpin, 554a8c21a54SThe etnaviv authors .gem_prime_get_sg_table = etnaviv_gem_prime_get_sg_table, 555a8c21a54SThe etnaviv authors .gem_prime_import_sg_table = etnaviv_gem_prime_import_sg_table, 556a8c21a54SThe etnaviv authors .gem_prime_vmap = etnaviv_gem_prime_vmap, 557a8c21a54SThe etnaviv authors .gem_prime_vunmap = etnaviv_gem_prime_vunmap, 5585688e57eSLucas Stach .gem_prime_mmap = etnaviv_gem_prime_mmap, 559a8c21a54SThe etnaviv authors #ifdef CONFIG_DEBUG_FS 560a8c21a54SThe etnaviv authors .debugfs_init = etnaviv_debugfs_init, 561a8c21a54SThe etnaviv authors #endif 562a8c21a54SThe etnaviv authors .ioctls = etnaviv_ioctls, 563a8c21a54SThe etnaviv authors .num_ioctls = DRM_ETNAVIV_NUM_IOCTLS, 564a8c21a54SThe etnaviv authors .fops = &fops, 565a8c21a54SThe etnaviv authors .name = "etnaviv", 566a8c21a54SThe etnaviv authors .desc = "etnaviv DRM", 567a8c21a54SThe etnaviv authors .date = "20151214", 568a8c21a54SThe etnaviv authors .major = 1, 569a7cfa565SLucas Stach .minor = 2, 570a8c21a54SThe etnaviv authors }; 571a8c21a54SThe etnaviv authors 572a8c21a54SThe etnaviv authors /* 573a8c21a54SThe etnaviv authors * Platform driver: 574a8c21a54SThe etnaviv authors */ 575a8c21a54SThe etnaviv authors static int etnaviv_bind(struct device *dev) 576a8c21a54SThe etnaviv authors { 577a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv; 578a8c21a54SThe etnaviv authors struct drm_device *drm; 579a8c21a54SThe etnaviv authors int ret; 580a8c21a54SThe etnaviv authors 581a8c21a54SThe etnaviv authors drm = drm_dev_alloc(&etnaviv_drm_driver, dev); 5820f288605STom Gundersen if (IS_ERR(drm)) 5830f288605STom Gundersen return PTR_ERR(drm); 584a8c21a54SThe etnaviv authors 585a8c21a54SThe etnaviv authors priv = kzalloc(sizeof(*priv), GFP_KERNEL); 586a8c21a54SThe etnaviv authors if (!priv) { 587a8c21a54SThe etnaviv authors dev_err(dev, "failed to allocate private data\n"); 588a8c21a54SThe etnaviv authors ret = -ENOMEM; 589a8c21a54SThe etnaviv authors goto out_unref; 590a8c21a54SThe etnaviv authors } 591a8c21a54SThe etnaviv authors drm->dev_private = priv; 592a8c21a54SThe etnaviv authors 593a8c21a54SThe etnaviv authors mutex_init(&priv->gem_lock); 594a8c21a54SThe etnaviv authors INIT_LIST_HEAD(&priv->gem_list); 595a8c21a54SThe etnaviv authors priv->num_gpus = 0; 596a8c21a54SThe etnaviv authors 597a8c21a54SThe etnaviv authors dev_set_drvdata(dev, drm); 598a8c21a54SThe etnaviv authors 599a8c21a54SThe etnaviv authors ret = component_bind_all(dev, drm); 600a8c21a54SThe etnaviv authors if (ret < 0) 601a8c21a54SThe etnaviv authors goto out_bind; 602a8c21a54SThe etnaviv authors 603a8c21a54SThe etnaviv authors load_gpu(drm); 604a8c21a54SThe etnaviv authors 605a8c21a54SThe etnaviv authors ret = drm_dev_register(drm, 0); 606a8c21a54SThe etnaviv authors if (ret) 607a8c21a54SThe etnaviv authors goto out_register; 608a8c21a54SThe etnaviv authors 609a8c21a54SThe etnaviv authors return 0; 610a8c21a54SThe etnaviv authors 611a8c21a54SThe etnaviv authors out_register: 612a8c21a54SThe etnaviv authors component_unbind_all(dev, drm); 613a8c21a54SThe etnaviv authors out_bind: 614a8c21a54SThe etnaviv authors kfree(priv); 615a8c21a54SThe etnaviv authors out_unref: 616a8c21a54SThe etnaviv authors drm_dev_unref(drm); 617a8c21a54SThe etnaviv authors 618a8c21a54SThe etnaviv authors return ret; 619a8c21a54SThe etnaviv authors } 620a8c21a54SThe etnaviv authors 621a8c21a54SThe etnaviv authors static void etnaviv_unbind(struct device *dev) 622a8c21a54SThe etnaviv authors { 623a8c21a54SThe etnaviv authors struct drm_device *drm = dev_get_drvdata(dev); 624a8c21a54SThe etnaviv authors struct etnaviv_drm_private *priv = drm->dev_private; 625a8c21a54SThe etnaviv authors 626a8c21a54SThe etnaviv authors drm_dev_unregister(drm); 627a8c21a54SThe etnaviv authors 628a8c21a54SThe etnaviv authors component_unbind_all(dev, drm); 629a8c21a54SThe etnaviv authors 630a8c21a54SThe etnaviv authors drm->dev_private = NULL; 631a8c21a54SThe etnaviv authors kfree(priv); 632a8c21a54SThe etnaviv authors 633ecdfcebbSDaniel Vetter drm_dev_unref(drm); 634a8c21a54SThe etnaviv authors } 635a8c21a54SThe etnaviv authors 636a8c21a54SThe etnaviv authors static const struct component_master_ops etnaviv_master_ops = { 637a8c21a54SThe etnaviv authors .bind = etnaviv_bind, 638a8c21a54SThe etnaviv authors .unbind = etnaviv_unbind, 639a8c21a54SThe etnaviv authors }; 640a8c21a54SThe etnaviv authors 641a8c21a54SThe etnaviv authors static int compare_of(struct device *dev, void *data) 642a8c21a54SThe etnaviv authors { 643a8c21a54SThe etnaviv authors struct device_node *np = data; 644a8c21a54SThe etnaviv authors 645a8c21a54SThe etnaviv authors return dev->of_node == np; 646a8c21a54SThe etnaviv authors } 647a8c21a54SThe etnaviv authors 648a8c21a54SThe etnaviv authors static int compare_str(struct device *dev, void *data) 649a8c21a54SThe etnaviv authors { 650a8c21a54SThe etnaviv authors return !strcmp(dev_name(dev), data); 651a8c21a54SThe etnaviv authors } 652a8c21a54SThe etnaviv authors 653a8c21a54SThe etnaviv authors static int etnaviv_pdev_probe(struct platform_device *pdev) 654a8c21a54SThe etnaviv authors { 655a8c21a54SThe etnaviv authors struct device *dev = &pdev->dev; 656a8c21a54SThe etnaviv authors struct device_node *node = dev->of_node; 657a8c21a54SThe etnaviv authors struct component_match *match = NULL; 658a8c21a54SThe etnaviv authors 659a8c21a54SThe etnaviv authors dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 660a8c21a54SThe etnaviv authors 661a8c21a54SThe etnaviv authors if (node) { 662a8c21a54SThe etnaviv authors struct device_node *core_node; 663a8c21a54SThe etnaviv authors int i; 664a8c21a54SThe etnaviv authors 665a8c21a54SThe etnaviv authors for (i = 0; ; i++) { 666a8c21a54SThe etnaviv authors core_node = of_parse_phandle(node, "cores", i); 667a8c21a54SThe etnaviv authors if (!core_node) 668a8c21a54SThe etnaviv authors break; 669a8c21a54SThe etnaviv authors 67097ac0e47SRussell King drm_of_component_match_add(&pdev->dev, &match, 67197ac0e47SRussell King compare_of, core_node); 672a8c21a54SThe etnaviv authors of_node_put(core_node); 673a8c21a54SThe etnaviv authors } 674a8c21a54SThe etnaviv authors } else if (dev->platform_data) { 675a8c21a54SThe etnaviv authors char **names = dev->platform_data; 676a8c21a54SThe etnaviv authors unsigned i; 677a8c21a54SThe etnaviv authors 678a8c21a54SThe etnaviv authors for (i = 0; names[i]; i++) 679a8c21a54SThe etnaviv authors component_match_add(dev, &match, compare_str, names[i]); 680a8c21a54SThe etnaviv authors } 681a8c21a54SThe etnaviv authors 682a8c21a54SThe etnaviv authors return component_master_add_with_match(dev, &etnaviv_master_ops, match); 683a8c21a54SThe etnaviv authors } 684a8c21a54SThe etnaviv authors 685a8c21a54SThe etnaviv authors static int etnaviv_pdev_remove(struct platform_device *pdev) 686a8c21a54SThe etnaviv authors { 687a8c21a54SThe etnaviv authors component_master_del(&pdev->dev, &etnaviv_master_ops); 688a8c21a54SThe etnaviv authors 689a8c21a54SThe etnaviv authors return 0; 690a8c21a54SThe etnaviv authors } 691a8c21a54SThe etnaviv authors 692a8c21a54SThe etnaviv authors static const struct of_device_id dt_match[] = { 693a8c21a54SThe etnaviv authors { .compatible = "fsl,imx-gpu-subsystem" }, 694a8c21a54SThe etnaviv authors { .compatible = "marvell,dove-gpu-subsystem" }, 695a8c21a54SThe etnaviv authors {} 696a8c21a54SThe etnaviv authors }; 697a8c21a54SThe etnaviv authors MODULE_DEVICE_TABLE(of, dt_match); 698a8c21a54SThe etnaviv authors 699a8c21a54SThe etnaviv authors static struct platform_driver etnaviv_platform_driver = { 700a8c21a54SThe etnaviv authors .probe = etnaviv_pdev_probe, 701a8c21a54SThe etnaviv authors .remove = etnaviv_pdev_remove, 702a8c21a54SThe etnaviv authors .driver = { 703a8c21a54SThe etnaviv authors .name = "etnaviv", 704a8c21a54SThe etnaviv authors .of_match_table = dt_match, 705a8c21a54SThe etnaviv authors }, 706a8c21a54SThe etnaviv authors }; 707a8c21a54SThe etnaviv authors 708a8c21a54SThe etnaviv authors static int __init etnaviv_init(void) 709a8c21a54SThe etnaviv authors { 710a8c21a54SThe etnaviv authors int ret; 711a8c21a54SThe etnaviv authors 712a8c21a54SThe etnaviv authors etnaviv_validate_init(); 713a8c21a54SThe etnaviv authors 714a8c21a54SThe etnaviv authors ret = platform_driver_register(&etnaviv_gpu_driver); 715a8c21a54SThe etnaviv authors if (ret != 0) 716a8c21a54SThe etnaviv authors return ret; 717a8c21a54SThe etnaviv authors 718a8c21a54SThe etnaviv authors ret = platform_driver_register(&etnaviv_platform_driver); 719a8c21a54SThe etnaviv authors if (ret != 0) 720a8c21a54SThe etnaviv authors platform_driver_unregister(&etnaviv_gpu_driver); 721a8c21a54SThe etnaviv authors 722a8c21a54SThe etnaviv authors return ret; 723a8c21a54SThe etnaviv authors } 724a8c21a54SThe etnaviv authors module_init(etnaviv_init); 725a8c21a54SThe etnaviv authors 726a8c21a54SThe etnaviv authors static void __exit etnaviv_exit(void) 727a8c21a54SThe etnaviv authors { 728a8c21a54SThe etnaviv authors platform_driver_unregister(&etnaviv_gpu_driver); 729a8c21a54SThe etnaviv authors platform_driver_unregister(&etnaviv_platform_driver); 730a8c21a54SThe etnaviv authors } 731a8c21a54SThe etnaviv authors module_exit(etnaviv_exit); 732a8c21a54SThe etnaviv authors 733a8c21a54SThe etnaviv authors MODULE_AUTHOR("Christian Gmeiner <christian.gmeiner@gmail.com>"); 734a8c21a54SThe etnaviv authors MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>"); 735a8c21a54SThe etnaviv authors MODULE_AUTHOR("Lucas Stach <l.stach@pengutronix.de>"); 736a8c21a54SThe etnaviv authors MODULE_DESCRIPTION("etnaviv DRM Driver"); 737a8c21a54SThe etnaviv authors MODULE_LICENSE("GPL v2"); 738a8c21a54SThe etnaviv authors MODULE_ALIAS("platform:etnaviv"); 739