1 /* 2 * Copyright (c) 2011 Samsung Electronics Co., Ltd. 3 * Authors: 4 * Inki Dae <inki.dae@samsung.com> 5 * Joonyoung Shim <jy0922.shim@samsung.com> 6 * Seung-Woo Kim <sw0312.kim@samsung.com> 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the next 16 * paragraph) shall be included in all copies or substantial portions of the 17 * Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 * OTHER DEALINGS IN THE SOFTWARE. 26 */ 27 28 #include "drmP.h" 29 #include "drm.h" 30 31 #include <drm/exynos_drm.h> 32 33 #include "exynos_drm_drv.h" 34 #include "exynos_drm_crtc.h" 35 #include "exynos_drm_fbdev.h" 36 #include "exynos_drm_fb.h" 37 #include "exynos_drm_gem.h" 38 39 #define DRIVER_NAME "exynos-drm" 40 #define DRIVER_DESC "Samsung SoC DRM" 41 #define DRIVER_DATE "20110530" 42 #define DRIVER_MAJOR 1 43 #define DRIVER_MINOR 0 44 45 static int exynos_drm_load(struct drm_device *dev, unsigned long flags) 46 { 47 struct exynos_drm_private *private; 48 int ret; 49 int nr; 50 51 DRM_DEBUG_DRIVER("%s\n", __FILE__); 52 53 private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL); 54 if (!private) { 55 DRM_ERROR("failed to allocate private\n"); 56 return -ENOMEM; 57 } 58 59 INIT_LIST_HEAD(&private->pageflip_event_list); 60 dev->dev_private = (void *)private; 61 62 drm_mode_config_init(dev); 63 64 exynos_drm_mode_config_init(dev); 65 66 /* 67 * EXYNOS4 is enough to have two CRTCs and each crtc would be used 68 * without dependency of hardware. 69 */ 70 for (nr = 0; nr < MAX_CRTC; nr++) { 71 ret = exynos_drm_crtc_create(dev, nr); 72 if (ret) 73 goto err_crtc; 74 } 75 76 ret = drm_vblank_init(dev, MAX_CRTC); 77 if (ret) 78 goto err_crtc; 79 80 /* 81 * probe sub drivers such as display controller and hdmi driver, 82 * that were registered at probe() of platform driver 83 * to the sub driver and create encoder and connector for them. 84 */ 85 ret = exynos_drm_device_register(dev); 86 if (ret) 87 goto err_vblank; 88 89 /* 90 * create and configure fb helper and also exynos specific 91 * fbdev object. 92 */ 93 ret = exynos_drm_fbdev_init(dev); 94 if (ret) { 95 DRM_ERROR("failed to initialize drm fbdev\n"); 96 goto err_drm_device; 97 } 98 99 return 0; 100 101 err_drm_device: 102 exynos_drm_device_unregister(dev); 103 err_vblank: 104 drm_vblank_cleanup(dev); 105 err_crtc: 106 drm_mode_config_cleanup(dev); 107 kfree(private); 108 109 return ret; 110 } 111 112 static int exynos_drm_unload(struct drm_device *dev) 113 { 114 DRM_DEBUG_DRIVER("%s\n", __FILE__); 115 116 exynos_drm_fbdev_fini(dev); 117 exynos_drm_device_unregister(dev); 118 drm_vblank_cleanup(dev); 119 drm_mode_config_cleanup(dev); 120 kfree(dev->dev_private); 121 122 dev->dev_private = NULL; 123 124 return 0; 125 } 126 127 static void exynos_drm_preclose(struct drm_device *dev, 128 struct drm_file *file_priv) 129 { 130 struct exynos_drm_private *dev_priv = dev->dev_private; 131 132 /* 133 * drm framework frees all events at release time, 134 * so private event list should be cleared. 135 */ 136 if (!list_empty(&dev_priv->pageflip_event_list)) 137 INIT_LIST_HEAD(&dev_priv->pageflip_event_list); 138 } 139 140 static void exynos_drm_lastclose(struct drm_device *dev) 141 { 142 DRM_DEBUG_DRIVER("%s\n", __FILE__); 143 144 exynos_drm_fbdev_restore_mode(dev); 145 } 146 147 static struct vm_operations_struct exynos_drm_gem_vm_ops = { 148 .fault = exynos_drm_gem_fault, 149 .open = drm_gem_vm_open, 150 .close = drm_gem_vm_close, 151 }; 152 153 static struct drm_ioctl_desc exynos_ioctls[] = { 154 DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl, 155 DRM_UNLOCKED | DRM_AUTH), 156 DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET, 157 exynos_drm_gem_map_offset_ioctl, DRM_UNLOCKED | 158 DRM_AUTH), 159 DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP, 160 exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH), 161 }; 162 163 static struct drm_driver exynos_drm_driver = { 164 .driver_features = DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM | 165 DRIVER_MODESET | DRIVER_GEM, 166 .load = exynos_drm_load, 167 .unload = exynos_drm_unload, 168 .preclose = exynos_drm_preclose, 169 .lastclose = exynos_drm_lastclose, 170 .get_vblank_counter = drm_vblank_count, 171 .enable_vblank = exynos_drm_crtc_enable_vblank, 172 .disable_vblank = exynos_drm_crtc_disable_vblank, 173 .gem_init_object = exynos_drm_gem_init_object, 174 .gem_free_object = exynos_drm_gem_free_object, 175 .gem_vm_ops = &exynos_drm_gem_vm_ops, 176 .dumb_create = exynos_drm_gem_dumb_create, 177 .dumb_map_offset = exynos_drm_gem_dumb_map_offset, 178 .dumb_destroy = exynos_drm_gem_dumb_destroy, 179 .ioctls = exynos_ioctls, 180 .fops = { 181 .owner = THIS_MODULE, 182 .open = drm_open, 183 .mmap = exynos_drm_gem_mmap, 184 .poll = drm_poll, 185 .read = drm_read, 186 .unlocked_ioctl = drm_ioctl, 187 .release = drm_release, 188 }, 189 .name = DRIVER_NAME, 190 .desc = DRIVER_DESC, 191 .date = DRIVER_DATE, 192 .major = DRIVER_MAJOR, 193 .minor = DRIVER_MINOR, 194 }; 195 196 static int exynos_drm_platform_probe(struct platform_device *pdev) 197 { 198 DRM_DEBUG_DRIVER("%s\n", __FILE__); 199 200 exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls); 201 202 return drm_platform_init(&exynos_drm_driver, pdev); 203 } 204 205 static int exynos_drm_platform_remove(struct platform_device *pdev) 206 { 207 DRM_DEBUG_DRIVER("%s\n", __FILE__); 208 209 drm_platform_exit(&exynos_drm_driver, pdev); 210 211 return 0; 212 } 213 214 static struct platform_driver exynos_drm_platform_driver = { 215 .probe = exynos_drm_platform_probe, 216 .remove = __devexit_p(exynos_drm_platform_remove), 217 .driver = { 218 .owner = THIS_MODULE, 219 .name = DRIVER_NAME, 220 }, 221 }; 222 223 static int __init exynos_drm_init(void) 224 { 225 DRM_DEBUG_DRIVER("%s\n", __FILE__); 226 227 return platform_driver_register(&exynos_drm_platform_driver); 228 } 229 230 static void __exit exynos_drm_exit(void) 231 { 232 DRM_DEBUG_DRIVER("%s\n", __FILE__); 233 234 platform_driver_unregister(&exynos_drm_platform_driver); 235 } 236 237 module_init(exynos_drm_init); 238 module_exit(exynos_drm_exit); 239 240 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); 241 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); 242 MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>"); 243 MODULE_DESCRIPTION("Samsung SoC DRM Driver"); 244 MODULE_LICENSE("GPL"); 245