1 /* exynos_drm_fb.c 2 * 3 * Copyright (c) 2011 Samsung Electronics Co., Ltd. 4 * Authors: 5 * Inki Dae <inki.dae@samsung.com> 6 * Joonyoung Shim <jy0922.shim@samsung.com> 7 * Seung-Woo Kim <sw0312.kim@samsung.com> 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the next 17 * paragraph) shall be included in all copies or substantial portions of the 18 * Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 * OTHER DEALINGS IN THE SOFTWARE. 27 */ 28 29 #include "drmP.h" 30 #include "drm_crtc.h" 31 #include "drm_crtc_helper.h" 32 33 #include "exynos_drm_fb.h" 34 #include "exynos_drm_buf.h" 35 #include "exynos_drm_gem.h" 36 37 #define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb) 38 39 /* 40 * exynos specific framebuffer structure. 41 * 42 * @fb: drm framebuffer obejct. 43 * @exynos_gem_obj: exynos specific gem object containing a gem object. 44 * @entry: pointer to exynos drm buffer entry object. 45 * - containing only the information to physically continuous memory 46 * region allocated at default framebuffer creation. 47 */ 48 struct exynos_drm_fb { 49 struct drm_framebuffer fb; 50 struct exynos_drm_gem_obj *exynos_gem_obj; 51 struct exynos_drm_buf_entry *entry; 52 }; 53 54 static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) 55 { 56 struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); 57 58 DRM_DEBUG_KMS("%s\n", __FILE__); 59 60 drm_framebuffer_cleanup(fb); 61 62 /* 63 * default framebuffer has no gem object so 64 * a buffer of the default framebuffer should be released at here. 65 */ 66 if (!exynos_fb->exynos_gem_obj && exynos_fb->entry) 67 exynos_drm_buf_destroy(fb->dev, exynos_fb->entry); 68 69 kfree(exynos_fb); 70 exynos_fb = NULL; 71 } 72 73 static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb, 74 struct drm_file *file_priv, 75 unsigned int *handle) 76 { 77 struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); 78 79 DRM_DEBUG_KMS("%s\n", __FILE__); 80 81 return drm_gem_handle_create(file_priv, 82 &exynos_fb->exynos_gem_obj->base, handle); 83 } 84 85 static int exynos_drm_fb_dirty(struct drm_framebuffer *fb, 86 struct drm_file *file_priv, unsigned flags, 87 unsigned color, struct drm_clip_rect *clips, 88 unsigned num_clips) 89 { 90 DRM_DEBUG_KMS("%s\n", __FILE__); 91 92 /* TODO */ 93 94 return 0; 95 } 96 97 static struct drm_framebuffer_funcs exynos_drm_fb_funcs = { 98 .destroy = exynos_drm_fb_destroy, 99 .create_handle = exynos_drm_fb_create_handle, 100 .dirty = exynos_drm_fb_dirty, 101 }; 102 103 static struct drm_framebuffer * 104 exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev, 105 struct drm_mode_fb_cmd *mode_cmd) 106 { 107 struct exynos_drm_fb *exynos_fb; 108 struct drm_framebuffer *fb; 109 struct exynos_drm_gem_obj *exynos_gem_obj = NULL; 110 struct drm_gem_object *obj; 111 unsigned int size; 112 int ret; 113 114 DRM_DEBUG_KMS("%s\n", __FILE__); 115 116 mode_cmd->pitch = max(mode_cmd->pitch, 117 mode_cmd->width * (mode_cmd->bpp >> 3)); 118 119 DRM_LOG_KMS("drm fb create(%dx%d)\n", 120 mode_cmd->width, mode_cmd->height); 121 122 exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); 123 if (!exynos_fb) { 124 DRM_ERROR("failed to allocate exynos drm framebuffer.\n"); 125 return ERR_PTR(-ENOMEM); 126 } 127 128 fb = &exynos_fb->fb; 129 ret = drm_framebuffer_init(dev, fb, &exynos_drm_fb_funcs); 130 if (ret) { 131 DRM_ERROR("failed to initialize framebuffer.\n"); 132 goto err_init; 133 } 134 135 DRM_LOG_KMS("create: fb id: %d\n", fb->base.id); 136 137 size = mode_cmd->pitch * mode_cmd->height; 138 139 /* 140 * mode_cmd->handle could be NULL at booting time or 141 * with user request. if NULL, a new buffer or a gem object 142 * would be allocated. 143 */ 144 if (!mode_cmd->handle) { 145 if (!file_priv) { 146 struct exynos_drm_buf_entry *entry; 147 148 /* 149 * in case that file_priv is NULL, it allocates 150 * only buffer and this buffer would be used 151 * for default framebuffer. 152 */ 153 entry = exynos_drm_buf_create(dev, size); 154 if (IS_ERR(entry)) { 155 ret = PTR_ERR(entry); 156 goto err_buffer; 157 } 158 159 exynos_fb->entry = entry; 160 161 DRM_LOG_KMS("default fb: paddr = 0x%lx, size = 0x%x\n", 162 (unsigned long)entry->paddr, size); 163 164 goto out; 165 } else { 166 exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, 167 size, 168 &mode_cmd->handle); 169 if (IS_ERR(exynos_gem_obj)) { 170 ret = PTR_ERR(exynos_gem_obj); 171 goto err_buffer; 172 } 173 } 174 } else { 175 obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); 176 if (!obj) { 177 DRM_ERROR("failed to lookup gem object.\n"); 178 goto err_buffer; 179 } 180 181 exynos_gem_obj = to_exynos_gem_obj(obj); 182 183 drm_gem_object_unreference_unlocked(obj); 184 } 185 186 /* 187 * if got a exynos_gem_obj from either a handle or 188 * a new creation then exynos_fb->exynos_gem_obj is NULL 189 * so that default framebuffer has no its own gem object, 190 * only its own buffer object. 191 */ 192 exynos_fb->entry = exynos_gem_obj->entry; 193 194 DRM_LOG_KMS("paddr = 0x%lx, size = 0x%x, gem object = 0x%x\n", 195 (unsigned long)exynos_fb->entry->paddr, size, 196 (unsigned int)&exynos_gem_obj->base); 197 198 out: 199 exynos_fb->exynos_gem_obj = exynos_gem_obj; 200 201 drm_helper_mode_fill_fb_struct(fb, mode_cmd); 202 203 return fb; 204 205 err_buffer: 206 drm_framebuffer_cleanup(fb); 207 208 err_init: 209 kfree(exynos_fb); 210 211 return ERR_PTR(ret); 212 } 213 214 struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev, 215 struct drm_file *file_priv, 216 struct drm_mode_fb_cmd *mode_cmd) 217 { 218 DRM_DEBUG_KMS("%s\n", __FILE__); 219 220 return exynos_drm_fb_init(file_priv, dev, mode_cmd); 221 } 222 223 struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb) 224 { 225 struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); 226 struct exynos_drm_buf_entry *entry; 227 228 DRM_DEBUG_KMS("%s\n", __FILE__); 229 230 entry = exynos_fb->entry; 231 if (!entry) 232 return NULL; 233 234 DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n", 235 (unsigned long)entry->vaddr, 236 (unsigned long)entry->paddr); 237 238 return entry; 239 } 240 241 static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { 242 .fb_create = exynos_drm_fb_create, 243 }; 244 245 void exynos_drm_mode_config_init(struct drm_device *dev) 246 { 247 dev->mode_config.min_width = 0; 248 dev->mode_config.min_height = 0; 249 250 /* 251 * set max width and height as default value(4096x4096). 252 * this value would be used to check framebuffer size limitation 253 * at drm_mode_addfb(). 254 */ 255 dev->mode_config.max_width = 4096; 256 dev->mode_config.max_height = 4096; 257 258 dev->mode_config.funcs = &exynos_drm_mode_config_funcs; 259 } 260 261 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); 262 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); 263 MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>"); 264 MODULE_DESCRIPTION("Samsung SoC DRM FB Driver"); 265 MODULE_LICENSE("GPL"); 266