blob: f1dcdd086886d2fd6dc29bf73a0c54bd1a057030 [file] [log] [blame]
Inki Dae1c248b72011-10-04 19:19:01 +09001/* exynos_drm_gem.c
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * Author: Inki Dae <inki.dae@samsung.com>
5 *
Inki Daed81aecb2012-12-18 02:30:17 +09006 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
Inki Dae1c248b72011-10-04 19:19:01 +090010 */
11
David Howells760285e2012-10-02 18:01:07 +010012#include <drm/drmP.h>
David Herrmann0de23972013-07-24 21:07:52 +020013#include <drm/drm_vma_manager.h>
Inki Dae1c248b72011-10-04 19:19:01 +090014
Inki Dae2b358922012-03-16 18:47:05 +090015#include <linux/shmem_fs.h>
Joonyoung Shim01ed50d2015-08-16 14:33:08 +090016#include <linux/dma-buf.h>
Inki Dae1c248b72011-10-04 19:19:01 +090017#include <drm/exynos_drm.h>
18
19#include "exynos_drm_drv.h"
20#include "exynos_drm_gem.h"
Vikas Sajjan3fec4532013-08-23 12:05:06 +053021#include "exynos_drm_iommu.h"
Inki Dae1c248b72011-10-04 19:19:01 +090022
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090023static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090024{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090025 struct drm_device *dev = exynos_gem->base.dev;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090026 enum dma_attr attr;
27 unsigned int nr_pages;
28
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090029 if (exynos_gem->dma_addr) {
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090030 DRM_DEBUG_KMS("already allocated.\n");
31 return 0;
32 }
33
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090034 init_dma_attrs(&exynos_gem->dma_attrs);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090035
36 /*
37 * if EXYNOS_BO_CONTIG, fully physically contiguous memory
38 * region will be allocated else physically contiguous
39 * as possible.
40 */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090041 if (!(exynos_gem->flags & EXYNOS_BO_NONCONTIG))
42 dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &exynos_gem->dma_attrs);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090043
44 /*
45 * if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping
46 * else cachable mapping.
47 */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090048 if (exynos_gem->flags & EXYNOS_BO_WC ||
49 !(exynos_gem->flags & EXYNOS_BO_CACHABLE))
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090050 attr = DMA_ATTR_WRITE_COMBINE;
51 else
52 attr = DMA_ATTR_NON_CONSISTENT;
53
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090054 dma_set_attr(attr, &exynos_gem->dma_attrs);
55 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &exynos_gem->dma_attrs);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090056
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090057 nr_pages = exynos_gem->size >> PAGE_SHIFT;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090058
59 if (!is_drm_iommu_supported(dev)) {
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090060 exynos_gem->pages = drm_calloc_large(nr_pages,
61 sizeof(struct page *));
62 if (!exynos_gem->pages) {
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090063 DRM_ERROR("failed to allocate pages.\n");
64 return -ENOMEM;
65 }
Joonyoung Shim333e8e52015-09-16 14:29:34 +090066 }
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090067
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090068 exynos_gem->cookie = dma_alloc_attrs(dev->dev, exynos_gem->size,
69 &exynos_gem->dma_addr, GFP_KERNEL,
70 &exynos_gem->dma_attrs);
71 if (!exynos_gem->cookie) {
Joonyoung Shim333e8e52015-09-16 14:29:34 +090072 DRM_ERROR("failed to allocate buffer.\n");
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090073 if (exynos_gem->pages)
74 drm_free_large(exynos_gem->pages);
Joonyoung Shim333e8e52015-09-16 14:29:34 +090075 return -ENOMEM;
76 }
77
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090078 if (exynos_gem->pages) {
Joonyoung Shim333e8e52015-09-16 14:29:34 +090079 dma_addr_t start_addr;
80 unsigned int i = 0;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090081
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090082 start_addr = exynos_gem->dma_addr;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090083 while (i < nr_pages) {
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090084 exynos_gem->pages[i] =
85 pfn_to_page(dma_to_pfn(dev->dev, start_addr));
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090086 start_addr += PAGE_SIZE;
87 i++;
88 }
89 } else {
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090090 exynos_gem->pages = exynos_gem->cookie;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090091 }
92
93 DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090094 (unsigned long)exynos_gem->dma_addr, exynos_gem->size);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +090095
96 return 0;
97}
98
Joonyoung Shim813fd67b2015-10-02 09:33:47 +090099static void exynos_drm_free_buf(struct exynos_drm_gem *exynos_gem)
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900100{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900101 struct drm_device *dev = exynos_gem->base.dev;
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900102
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900103 if (!exynos_gem->dma_addr) {
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900104 DRM_DEBUG_KMS("dma_addr is invalid.\n");
105 return;
106 }
107
108 DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900109 (unsigned long)exynos_gem->dma_addr, exynos_gem->size);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900110
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900111 dma_free_attrs(dev->dev, exynos_gem->size, exynos_gem->cookie,
112 (dma_addr_t)exynos_gem->dma_addr,
113 &exynos_gem->dma_attrs);
Joonyoung Shim333e8e52015-09-16 14:29:34 +0900114
115 if (!is_drm_iommu_supported(dev))
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900116 drm_free_large(exynos_gem->pages);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900117}
118
Joonyoung Shim23648392011-12-13 14:39:13 +0900119static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
120 struct drm_file *file_priv,
121 unsigned int *handle)
Inki Dae1c248b72011-10-04 19:19:01 +0900122{
Inki Dae1c248b72011-10-04 19:19:01 +0900123 int ret;
124
Inki Dae1c248b72011-10-04 19:19:01 +0900125 /*
126 * allocate a id of idr table where the obj is registered
127 * and handle has the id what user can see.
128 */
129 ret = drm_gem_handle_create(file_priv, obj, handle);
130 if (ret)
Joonyoung Shim23648392011-12-13 14:39:13 +0900131 return ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900132
133 DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle);
134
135 /* drop reference from allocate - handle holds it now. */
136 drm_gem_object_unreference_unlocked(obj);
137
Joonyoung Shim23648392011-12-13 14:39:13 +0900138 return 0;
139}
Inki Dae1c248b72011-10-04 19:19:01 +0900140
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900141void exynos_drm_gem_destroy(struct exynos_drm_gem *exynos_gem)
Joonyoung Shim23648392011-12-13 14:39:13 +0900142{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900143 struct drm_gem_object *obj = &exynos_gem->base;
Joonyoung Shim23648392011-12-13 14:39:13 +0900144
Daniel Vettera8e11d12013-08-15 00:02:37 +0200145 DRM_DEBUG_KMS("handle count = %d\n", obj->handle_count);
Joonyoung Shim23648392011-12-13 14:39:13 +0900146
Inki Daec374e732012-06-12 16:52:54 +0900147 /*
148 * do not release memory region from exporter.
149 *
150 * the region will be released by exporter
151 * once dmabuf's refcount becomes 0.
152 */
153 if (obj->import_attach)
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900154 drm_prime_gem_destroy(obj, exynos_gem->sgt);
Joonyoung Shim7c935372015-09-16 14:14:54 +0900155 else
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900156 exynos_drm_free_buf(exynos_gem);
Inki Daec374e732012-06-12 16:52:54 +0900157
Joonyoung Shim23648392011-12-13 14:39:13 +0900158 /* release file pointer to gem object. */
Inki Dae1c248b72011-10-04 19:19:01 +0900159 drm_gem_object_release(obj);
160
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900161 kfree(exynos_gem);
Joonyoung Shim23648392011-12-13 14:39:13 +0900162}
163
Inki Daea4f19aa2013-03-11 21:15:59 +0900164unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
165 unsigned int gem_handle,
166 struct drm_file *file_priv)
167{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900168 struct exynos_drm_gem *exynos_gem;
Inki Daea4f19aa2013-03-11 21:15:59 +0900169 struct drm_gem_object *obj;
170
171 obj = drm_gem_object_lookup(dev, file_priv, gem_handle);
172 if (!obj) {
173 DRM_ERROR("failed to lookup gem object.\n");
174 return 0;
175 }
176
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900177 exynos_gem = to_exynos_gem(obj);
Inki Daea4f19aa2013-03-11 21:15:59 +0900178
179 drm_gem_object_unreference_unlocked(obj);
180
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900181 return exynos_gem->size;
Inki Daea4f19aa2013-03-11 21:15:59 +0900182}
183
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900184static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,
185 unsigned long size)
Joonyoung Shim23648392011-12-13 14:39:13 +0900186{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900187 struct exynos_drm_gem *exynos_gem;
Joonyoung Shim23648392011-12-13 14:39:13 +0900188 struct drm_gem_object *obj;
189 int ret;
190
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900191 exynos_gem = kzalloc(sizeof(*exynos_gem), GFP_KERNEL);
192 if (!exynos_gem)
Joonyoung Shim5f3f4262015-07-28 17:53:22 +0900193 return ERR_PTR(-ENOMEM);
Joonyoung Shim23648392011-12-13 14:39:13 +0900194
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900195 exynos_gem->size = size;
196 obj = &exynos_gem->base;
Joonyoung Shim23648392011-12-13 14:39:13 +0900197
198 ret = drm_gem_object_init(dev, obj, size);
199 if (ret < 0) {
200 DRM_ERROR("failed to initialize gem object\n");
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900201 kfree(exynos_gem);
Joonyoung Shim5f3f4262015-07-28 17:53:22 +0900202 return ERR_PTR(ret);
Joonyoung Shim23648392011-12-13 14:39:13 +0900203 }
204
Joonyoung Shim48cf53f2015-07-28 17:53:23 +0900205 ret = drm_gem_create_mmap_offset(obj);
206 if (ret < 0) {
207 drm_gem_object_release(obj);
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900208 kfree(exynos_gem);
Joonyoung Shim48cf53f2015-07-28 17:53:23 +0900209 return ERR_PTR(ret);
210 }
211
Joonyoung Shim23648392011-12-13 14:39:13 +0900212 DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
213
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900214 return exynos_gem;
Inki Dae1c248b72011-10-04 19:19:01 +0900215}
216
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900217struct exynos_drm_gem *exynos_drm_gem_create(struct drm_device *dev,
218 unsigned int flags,
219 unsigned long size)
Inki Daef088d5a2011-11-12 14:51:23 +0900220{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900221 struct exynos_drm_gem *exynos_gem;
Inki Dae2b358922012-03-16 18:47:05 +0900222 int ret;
Inki Daef088d5a2011-11-12 14:51:23 +0900223
Joonyoung Shimc4130bc2015-08-16 14:15:06 +0900224 if (flags & ~(EXYNOS_BO_MASK)) {
225 DRM_ERROR("invalid flags.\n");
226 return ERR_PTR(-EINVAL);
227 }
228
Inki Daedcf9af82012-04-03 21:27:58 +0900229 if (!size) {
230 DRM_ERROR("invalid size.\n");
231 return ERR_PTR(-EINVAL);
232 }
Inki Daef088d5a2011-11-12 14:51:23 +0900233
Joonyoung Shimeb57da82015-07-28 17:53:27 +0900234 size = roundup(size, PAGE_SIZE);
Inki Daedcf9af82012-04-03 21:27:58 +0900235
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900236 exynos_gem = exynos_drm_gem_init(dev, size);
237 if (IS_ERR(exynos_gem))
238 return exynos_gem;
Inki Dae2b358922012-03-16 18:47:05 +0900239
240 /* set memory type and cache attribute from user side. */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900241 exynos_gem->flags = flags;
Inki Dae2b358922012-03-16 18:47:05 +0900242
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900243 ret = exynos_drm_alloc_buf(exynos_gem);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900244 if (ret < 0) {
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900245 drm_gem_object_release(&exynos_gem->base);
246 kfree(exynos_gem);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900247 return ERR_PTR(ret);
248 }
Inki Daef088d5a2011-11-12 14:51:23 +0900249
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900250 return exynos_gem;
Inki Daef088d5a2011-11-12 14:51:23 +0900251}
252
Inki Dae1c248b72011-10-04 19:19:01 +0900253int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900254 struct drm_file *file_priv)
Inki Dae1c248b72011-10-04 19:19:01 +0900255{
256 struct drm_exynos_gem_create *args = data;
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900257 struct exynos_drm_gem *exynos_gem;
Joonyoung Shim23648392011-12-13 14:39:13 +0900258 int ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900259
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900260 exynos_gem = exynos_drm_gem_create(dev, args->flags, args->size);
261 if (IS_ERR(exynos_gem))
262 return PTR_ERR(exynos_gem);
Inki Dae1c248b72011-10-04 19:19:01 +0900263
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900264 ret = exynos_drm_gem_handle_create(&exynos_gem->base, file_priv,
265 &args->handle);
Joonyoung Shim23648392011-12-13 14:39:13 +0900266 if (ret) {
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900267 exynos_drm_gem_destroy(exynos_gem);
Joonyoung Shim23648392011-12-13 14:39:13 +0900268 return ret;
269 }
270
Inki Dae1c248b72011-10-04 19:19:01 +0900271 return 0;
272}
273
Inki Daed87342c2012-11-03 21:53:24 -0700274dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev,
Inki Daef0b1bda2012-03-16 18:47:06 +0900275 unsigned int gem_handle,
Inki Daed87342c2012-11-03 21:53:24 -0700276 struct drm_file *filp)
Inki Daef0b1bda2012-03-16 18:47:06 +0900277{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900278 struct exynos_drm_gem *exynos_gem;
Inki Daef0b1bda2012-03-16 18:47:06 +0900279 struct drm_gem_object *obj;
280
Inki Daed87342c2012-11-03 21:53:24 -0700281 obj = drm_gem_object_lookup(dev, filp, gem_handle);
Inki Daef0b1bda2012-03-16 18:47:06 +0900282 if (!obj) {
283 DRM_ERROR("failed to lookup gem object.\n");
284 return ERR_PTR(-EINVAL);
285 }
286
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900287 exynos_gem = to_exynos_gem(obj);
Inki Daef0b1bda2012-03-16 18:47:06 +0900288
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900289 return &exynos_gem->dma_addr;
Inki Daef0b1bda2012-03-16 18:47:06 +0900290}
291
292void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
293 unsigned int gem_handle,
Inki Daed87342c2012-11-03 21:53:24 -0700294 struct drm_file *filp)
Inki Daef0b1bda2012-03-16 18:47:06 +0900295{
Inki Daef0b1bda2012-03-16 18:47:06 +0900296 struct drm_gem_object *obj;
297
Inki Daed87342c2012-11-03 21:53:24 -0700298 obj = drm_gem_object_lookup(dev, filp, gem_handle);
Inki Daef0b1bda2012-03-16 18:47:06 +0900299 if (!obj) {
300 DRM_ERROR("failed to lookup gem object.\n");
301 return;
302 }
303
Inki Daef0b1bda2012-03-16 18:47:06 +0900304 drm_gem_object_unreference_unlocked(obj);
305
306 /*
307 * decrease obj->refcount one more time because we has already
308 * increased it at exynos_drm_gem_get_dma_addr().
309 */
310 drm_gem_object_unreference_unlocked(obj);
311}
312
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900313static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900314 struct vm_area_struct *vma)
Inki Dae1c248b72011-10-04 19:19:01 +0900315{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900316 struct drm_device *drm_dev = exynos_gem->base.dev;
Inki Dae0519f9a2012-10-20 07:53:42 -0700317 unsigned long vm_size;
Inki Dae5b07c662012-11-08 21:52:54 +0900318 int ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900319
Inki Dae832316c2014-09-18 14:19:01 +0900320 vma->vm_flags &= ~VM_PFNMAP;
321 vma->vm_pgoff = 0;
Inki Dae1c248b72011-10-04 19:19:01 +0900322
Inki Dae0519f9a2012-10-20 07:53:42 -0700323 vm_size = vma->vm_end - vma->vm_start;
Inki Dae2b358922012-03-16 18:47:05 +0900324
Inki Dae1c248b72011-10-04 19:19:01 +0900325 /* check if user-requested size is valid. */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900326 if (vm_size > exynos_gem->size)
Inki Dae1c248b72011-10-04 19:19:01 +0900327 return -EINVAL;
328
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900329 ret = dma_mmap_attrs(drm_dev->dev, vma, exynos_gem->pages,
330 exynos_gem->dma_addr, exynos_gem->size,
331 &exynos_gem->dma_attrs);
Inki Dae5b07c662012-11-08 21:52:54 +0900332 if (ret < 0) {
333 DRM_ERROR("failed to mmap.\n");
334 return ret;
335 }
336
Inki Dae1c248b72011-10-04 19:19:01 +0900337 return 0;
338}
339
Inki Dae40cd7e02012-05-04 15:51:17 +0900340int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
341 struct drm_file *file_priv)
Joonyoung Shimb4cfd4d2015-09-16 14:29:35 +0900342{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900343 struct exynos_drm_gem *exynos_gem;
Inki Dae40cd7e02012-05-04 15:51:17 +0900344 struct drm_exynos_gem_info *args = data;
345 struct drm_gem_object *obj;
346
347 mutex_lock(&dev->struct_mutex);
348
349 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
350 if (!obj) {
351 DRM_ERROR("failed to lookup gem object.\n");
352 mutex_unlock(&dev->struct_mutex);
353 return -EINVAL;
354 }
355
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900356 exynos_gem = to_exynos_gem(obj);
Inki Dae40cd7e02012-05-04 15:51:17 +0900357
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900358 args->flags = exynos_gem->flags;
359 args->size = exynos_gem->size;
Inki Dae40cd7e02012-05-04 15:51:17 +0900360
361 drm_gem_object_unreference(obj);
362 mutex_unlock(&dev->struct_mutex);
363
364 return 0;
365}
366
Inki Dae2a3098f2012-11-04 05:48:52 -0800367int exynos_gem_map_sgt_with_dma(struct drm_device *drm_dev,
368 struct sg_table *sgt,
369 enum dma_data_direction dir)
370{
371 int nents;
372
373 mutex_lock(&drm_dev->struct_mutex);
374
375 nents = dma_map_sg(drm_dev->dev, sgt->sgl, sgt->nents, dir);
376 if (!nents) {
377 DRM_ERROR("failed to map sgl with dma.\n");
378 mutex_unlock(&drm_dev->struct_mutex);
379 return nents;
380 }
381
382 mutex_unlock(&drm_dev->struct_mutex);
383 return 0;
384}
385
386void exynos_gem_unmap_sgt_from_dma(struct drm_device *drm_dev,
387 struct sg_table *sgt,
388 enum dma_data_direction dir)
389{
390 dma_unmap_sg(drm_dev->dev, sgt->sgl, sgt->nents, dir);
391}
392
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900393void exynos_drm_gem_free_object(struct drm_gem_object *obj)
Inki Dae1c248b72011-10-04 19:19:01 +0900394{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900395 exynos_drm_gem_destroy(to_exynos_gem(obj));
Inki Dae1c248b72011-10-04 19:19:01 +0900396}
397
398int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900399 struct drm_device *dev,
400 struct drm_mode_create_dumb *args)
Inki Dae1c248b72011-10-04 19:19:01 +0900401{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900402 struct exynos_drm_gem *exynos_gem;
Joonyoung Shim333e8e52015-09-16 14:29:34 +0900403 unsigned int flags;
Joonyoung Shim23648392011-12-13 14:39:13 +0900404 int ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900405
Inki Dae1c248b72011-10-04 19:19:01 +0900406 /*
Masanari Iidac6b78bc2013-10-24 16:02:57 +0900407 * allocate memory to be used for framebuffer.
Inki Dae1c248b72011-10-04 19:19:01 +0900408 * - this callback would be called by user application
409 * with DRM_IOCTL_MODE_CREATE_DUMB command.
410 */
411
Cooper Yuan3fd6b692012-06-29 11:49:45 +0900412 args->pitch = args->width * ((args->bpp + 7) / 8);
Inki Dae7da59072012-08-17 15:24:03 +0900413 args->size = args->pitch * args->height;
Inki Dae1c248b72011-10-04 19:19:01 +0900414
Joonyoung Shim333e8e52015-09-16 14:29:34 +0900415 if (is_drm_iommu_supported(dev))
416 flags = EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC;
417 else
418 flags = EXYNOS_BO_CONTIG | EXYNOS_BO_WC;
Vikas Sajjan3fec4532013-08-23 12:05:06 +0530419
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900420 exynos_gem = exynos_drm_gem_create(dev, flags, args->size);
421 if (IS_ERR(exynos_gem)) {
Rahul Sharma122beea2014-05-07 17:21:29 +0530422 dev_warn(dev->dev, "FB allocation failed.\n");
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900423 return PTR_ERR(exynos_gem);
Rahul Sharma122beea2014-05-07 17:21:29 +0530424 }
Inki Dae1c248b72011-10-04 19:19:01 +0900425
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900426 ret = exynos_drm_gem_handle_create(&exynos_gem->base, file_priv,
427 &args->handle);
Joonyoung Shim23648392011-12-13 14:39:13 +0900428 if (ret) {
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900429 exynos_drm_gem_destroy(exynos_gem);
Joonyoung Shim23648392011-12-13 14:39:13 +0900430 return ret;
431 }
432
Inki Dae1c248b72011-10-04 19:19:01 +0900433 return 0;
434}
435
436int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
Joonyoung Shimee5e7702011-12-13 14:20:23 +0900437 struct drm_device *dev, uint32_t handle,
438 uint64_t *offset)
Inki Dae1c248b72011-10-04 19:19:01 +0900439{
Inki Dae1c248b72011-10-04 19:19:01 +0900440 struct drm_gem_object *obj;
Joonyoung Shim2d91cf12011-12-13 14:32:24 +0900441 int ret = 0;
Inki Dae1c248b72011-10-04 19:19:01 +0900442
Inki Dae1c248b72011-10-04 19:19:01 +0900443 mutex_lock(&dev->struct_mutex);
444
445 /*
446 * get offset of memory allocated for drm framebuffer.
447 * - this callback would be called by user application
448 * with DRM_IOCTL_MODE_MAP_DUMB command.
449 */
450
451 obj = drm_gem_object_lookup(dev, file_priv, handle);
452 if (!obj) {
453 DRM_ERROR("failed to lookup gem object.\n");
Joonyoung Shim2d91cf12011-12-13 14:32:24 +0900454 ret = -EINVAL;
455 goto unlock;
Inki Dae1c248b72011-10-04 19:19:01 +0900456 }
457
David Herrmann0de23972013-07-24 21:07:52 +0200458 *offset = drm_vma_node_offset_addr(&obj->vma_node);
Inki Dae1c248b72011-10-04 19:19:01 +0900459 DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
460
Joonyoung Shim2d91cf12011-12-13 14:32:24 +0900461 drm_gem_object_unreference(obj);
462unlock:
Inki Dae1c248b72011-10-04 19:19:01 +0900463 mutex_unlock(&dev->struct_mutex);
Joonyoung Shim2d91cf12011-12-13 14:32:24 +0900464 return ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900465}
466
467int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
468{
469 struct drm_gem_object *obj = vma->vm_private_data;
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900470 struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
Joonyoung Shim0e9a2ee2015-07-28 17:53:19 +0900471 unsigned long pfn;
Inki Dae1c248b72011-10-04 19:19:01 +0900472 pgoff_t page_offset;
473 int ret;
474
475 page_offset = ((unsigned long)vmf->virtual_address -
476 vma->vm_start) >> PAGE_SHIFT;
477
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900478 if (page_offset >= (exynos_gem->size >> PAGE_SHIFT)) {
Joonyoung Shim0e9a2ee2015-07-28 17:53:19 +0900479 DRM_ERROR("invalid page offset\n");
480 ret = -EINVAL;
481 goto out;
482 }
Inki Dae1c248b72011-10-04 19:19:01 +0900483
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900484 pfn = page_to_pfn(exynos_gem->pages[page_offset]);
Joonyoung Shim0e9a2ee2015-07-28 17:53:19 +0900485 ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
486
487out:
Joonyoung Shim23597e22015-07-28 17:53:17 +0900488 switch (ret) {
489 case 0:
490 case -ERESTARTSYS:
491 case -EINTR:
492 return VM_FAULT_NOPAGE;
493 case -ENOMEM:
494 return VM_FAULT_OOM;
495 default:
496 return VM_FAULT_SIGBUS;
497 }
Inki Dae1c248b72011-10-04 19:19:01 +0900498}
499
500int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
501{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900502 struct exynos_drm_gem *exynos_gem;
Inki Daec01d73fa2012-04-23 19:26:34 +0900503 struct drm_gem_object *obj;
Inki Dae1c248b72011-10-04 19:19:01 +0900504 int ret;
505
Inki Dae1c248b72011-10-04 19:19:01 +0900506 /* set vm_area_struct. */
507 ret = drm_gem_mmap(filp, vma);
508 if (ret < 0) {
509 DRM_ERROR("failed to mmap.\n");
510 return ret;
511 }
512
Inki Daec01d73fa2012-04-23 19:26:34 +0900513 obj = vma->vm_private_data;
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900514 exynos_gem = to_exynos_gem(obj);
Inki Daec01d73fa2012-04-23 19:26:34 +0900515
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900516 DRM_DEBUG_KMS("flags = 0x%x\n", exynos_gem->flags);
Joonyoung Shim211b8872015-08-16 14:16:49 +0900517
518 /* non-cachable as default. */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900519 if (exynos_gem->flags & EXYNOS_BO_CACHABLE)
Joonyoung Shim211b8872015-08-16 14:16:49 +0900520 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900521 else if (exynos_gem->flags & EXYNOS_BO_WC)
Joonyoung Shim211b8872015-08-16 14:16:49 +0900522 vma->vm_page_prot =
523 pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
524 else
525 vma->vm_page_prot =
526 pgprot_noncached(vm_get_page_prot(vma->vm_flags));
Inki Daec01d73fa2012-04-23 19:26:34 +0900527
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900528 ret = exynos_drm_gem_mmap_buffer(exynos_gem, vma);
Inki Dae832316c2014-09-18 14:19:01 +0900529 if (ret)
530 goto err_close_vm;
531
532 return ret;
533
534err_close_vm:
535 drm_gem_vm_close(vma);
Inki Dae832316c2014-09-18 14:19:01 +0900536
Inki Dae1c248b72011-10-04 19:19:01 +0900537 return ret;
538}
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900539
540/* low-level interface prime helpers */
541struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj)
542{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900543 struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900544 int npages;
545
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900546 npages = exynos_gem->size >> PAGE_SHIFT;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900547
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900548 return drm_prime_pages_to_sg(exynos_gem->pages, npages);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900549}
550
551struct drm_gem_object *
552exynos_drm_gem_prime_import_sg_table(struct drm_device *dev,
553 struct dma_buf_attachment *attach,
554 struct sg_table *sgt)
555{
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900556 struct exynos_drm_gem *exynos_gem;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900557 int npages;
558 int ret;
559
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900560 exynos_gem = exynos_drm_gem_init(dev, attach->dmabuf->size);
561 if (IS_ERR(exynos_gem)) {
562 ret = PTR_ERR(exynos_gem);
Inki Dae50002d42015-08-31 01:11:53 +0900563 return ERR_PTR(ret);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900564 }
565
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900566 exynos_gem->dma_addr = sg_dma_address(sgt->sgl);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900567
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900568 npages = exynos_gem->size >> PAGE_SHIFT;
569 exynos_gem->pages = drm_malloc_ab(npages, sizeof(struct page *));
570 if (!exynos_gem->pages) {
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900571 ret = -ENOMEM;
572 goto err;
573 }
574
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900575 ret = drm_prime_sg_to_page_addr_arrays(sgt, exynos_gem->pages, NULL,
576 npages);
Joonyoung Shim2a8cb482015-08-16 14:38:49 +0900577 if (ret < 0)
578 goto err_free_large;
579
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900580 exynos_gem->sgt = sgt;
Joonyoung Shim7c935372015-09-16 14:14:54 +0900581
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900582 if (sgt->nents == 1) {
583 /* always physically continuous memory if sgt->nents is 1. */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900584 exynos_gem->flags |= EXYNOS_BO_CONTIG;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900585 } else {
586 /*
587 * this case could be CONTIG or NONCONTIG type but for now
588 * sets NONCONTIG.
589 * TODO. we have to find a way that exporter can notify
590 * the type of its own buffer to importer.
591 */
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900592 exynos_gem->flags |= EXYNOS_BO_NONCONTIG;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900593 }
594
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900595 return &exynos_gem->base;
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900596
597err_free_large:
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900598 drm_free_large(exynos_gem->pages);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900599err:
Joonyoung Shim813fd67b2015-10-02 09:33:47 +0900600 drm_gem_object_release(&exynos_gem->base);
601 kfree(exynos_gem);
Joonyoung Shim01ed50d2015-08-16 14:33:08 +0900602 return ERR_PTR(ret);
603}
604
605void *exynos_drm_gem_prime_vmap(struct drm_gem_object *obj)
606{
607 return NULL;
608}
609
610void exynos_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
611{
612 /* Nothing to do */
613}