1 /* 2 * Copyright (C) 2012 Avionic Design GmbH 3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9 10 #include <linux/module.h> 11 #include <linux/of_address.h> 12 #include <linux/of_platform.h> 13 14 #include <linux/dma-mapping.h> 15 #include <asm/dma-iommu.h> 16 17 #include "drm.h" 18 19 #define DRIVER_NAME "tegra" 20 #define DRIVER_DESC "NVIDIA Tegra graphics" 21 #define DRIVER_DATE "20120330" 22 #define DRIVER_MAJOR 0 23 #define DRIVER_MINOR 0 24 #define DRIVER_PATCHLEVEL 0 25 26 static int tegra_drm_load(struct drm_device *drm, unsigned long flags) 27 { 28 struct device *dev = drm->dev; 29 struct host1x *host1x; 30 int err; 31 32 host1x = dev_get_drvdata(dev); 33 drm->dev_private = host1x; 34 host1x->drm = drm; 35 36 drm_mode_config_init(drm); 37 38 err = host1x_drm_init(host1x, drm); 39 if (err < 0) 40 return err; 41 42 err = drm_vblank_init(drm, drm->mode_config.num_crtc); 43 if (err < 0) 44 return err; 45 46 err = tegra_drm_fb_init(drm); 47 if (err < 0) 48 return err; 49 50 drm_kms_helper_poll_init(drm); 51 52 return 0; 53 } 54 55 static int tegra_drm_unload(struct drm_device *drm) 56 { 57 drm_kms_helper_poll_fini(drm); 58 tegra_drm_fb_exit(drm); 59 60 drm_mode_config_cleanup(drm); 61 62 return 0; 63 } 64 65 static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp) 66 { 67 return 0; 68 } 69 70 static void tegra_drm_lastclose(struct drm_device *drm) 71 { 72 struct host1x *host1x = drm->dev_private; 73 74 drm_fbdev_cma_restore_mode(host1x->fbdev); 75 } 76 77 static struct drm_ioctl_desc tegra_drm_ioctls[] = { 78 }; 79 80 static const struct file_operations tegra_drm_fops = { 81 .owner = THIS_MODULE, 82 .open = drm_open, 83 .release = drm_release, 84 .unlocked_ioctl = drm_ioctl, 85 .mmap = drm_gem_cma_mmap, 86 .poll = drm_poll, 87 .fasync = drm_fasync, 88 .read = drm_read, 89 #ifdef CONFIG_COMPAT 90 .compat_ioctl = drm_compat_ioctl, 91 #endif 92 .llseek = noop_llseek, 93 }; 94 95 static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe) 96 { 97 struct drm_crtc *crtc; 98 99 list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) { 100 struct tegra_dc *dc = to_tegra_dc(crtc); 101 102 if (dc->pipe == pipe) 103 return crtc; 104 } 105 106 return NULL; 107 } 108 109 static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc) 110 { 111 /* TODO: implement real hardware counter using syncpoints */ 112 return drm_vblank_count(dev, crtc); 113 } 114 115 static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe) 116 { 117 struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); 118 struct tegra_dc *dc = to_tegra_dc(crtc); 119 120 if (!crtc) 121 return -ENODEV; 122 123 tegra_dc_enable_vblank(dc); 124 125 return 0; 126 } 127 128 static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe) 129 { 130 struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); 131 struct tegra_dc *dc = to_tegra_dc(crtc); 132 133 if (crtc) 134 tegra_dc_disable_vblank(dc); 135 } 136 137 static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file) 138 { 139 struct drm_crtc *crtc; 140 141 list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) 142 tegra_dc_cancel_page_flip(crtc, file); 143 } 144 145 #ifdef CONFIG_DEBUG_FS 146 static int tegra_debugfs_framebuffers(struct seq_file *s, void *data) 147 { 148 struct drm_info_node *node = (struct drm_info_node *)s->private; 149 struct drm_device *drm = node->minor->dev; 150 struct drm_framebuffer *fb; 151 152 mutex_lock(&drm->mode_config.fb_lock); 153 154 list_for_each_entry(fb, &drm->mode_config.fb_list, head) { 155 seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n", 156 fb->base.id, fb->width, fb->height, fb->depth, 157 fb->bits_per_pixel, 158 atomic_read(&fb->refcount.refcount)); 159 } 160 161 mutex_unlock(&drm->mode_config.fb_lock); 162 163 return 0; 164 } 165 166 static struct drm_info_list tegra_debugfs_list[] = { 167 { "framebuffers", tegra_debugfs_framebuffers, 0 }, 168 }; 169 170 static int tegra_debugfs_init(struct drm_minor *minor) 171 { 172 return drm_debugfs_create_files(tegra_debugfs_list, 173 ARRAY_SIZE(tegra_debugfs_list), 174 minor->debugfs_root, minor); 175 } 176 177 static void tegra_debugfs_cleanup(struct drm_minor *minor) 178 { 179 drm_debugfs_remove_files(tegra_debugfs_list, 180 ARRAY_SIZE(tegra_debugfs_list), minor); 181 } 182 #endif 183 184 struct drm_driver tegra_drm_driver = { 185 .driver_features = DRIVER_BUS_PLATFORM | DRIVER_MODESET | DRIVER_GEM, 186 .load = tegra_drm_load, 187 .unload = tegra_drm_unload, 188 .open = tegra_drm_open, 189 .preclose = tegra_drm_preclose, 190 .lastclose = tegra_drm_lastclose, 191 192 .get_vblank_counter = tegra_drm_get_vblank_counter, 193 .enable_vblank = tegra_drm_enable_vblank, 194 .disable_vblank = tegra_drm_disable_vblank, 195 196 #if defined(CONFIG_DEBUG_FS) 197 .debugfs_init = tegra_debugfs_init, 198 .debugfs_cleanup = tegra_debugfs_cleanup, 199 #endif 200 201 .gem_free_object = drm_gem_cma_free_object, 202 .gem_vm_ops = &drm_gem_cma_vm_ops, 203 .dumb_create = drm_gem_cma_dumb_create, 204 .dumb_map_offset = drm_gem_cma_dumb_map_offset, 205 .dumb_destroy = drm_gem_cma_dumb_destroy, 206 207 .ioctls = tegra_drm_ioctls, 208 .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls), 209 .fops = &tegra_drm_fops, 210 211 .name = DRIVER_NAME, 212 .desc = DRIVER_DESC, 213 .date = DRIVER_DATE, 214 .major = DRIVER_MAJOR, 215 .minor = DRIVER_MINOR, 216 .patchlevel = DRIVER_PATCHLEVEL, 217 }; 218