diff options
author | Inki Dae <inki.dae@samsung.com> | 2012-04-23 08:01:28 -0400 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2012-05-08 05:46:32 -0400 |
commit | b2df26c10b16afe2eed904f2b85a4d2047531d30 (patch) | |
tree | 7defbfd77192157460c0d212a308d83d4358274c /drivers | |
parent | c01d73faad2f775036f0b37c753254479b79cbe6 (diff) |
drm/exynos: added drm prime feature.
this patch adds exynos specific codes for DRM Prime feature.
with this patch, user application can get file descriptor
from gem handle through DRM_IOCTL_PRIME_HANDLE_TO_FD ioctl
command(export) and also gem handle from file descriptor
through DRM_IOCTL_PRIME_FD_TO_HANLDE(import) ioctl command.
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/exynos/Kconfig | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_buf.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 272 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_dmabuf.h | 39 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.h | 8 |
8 files changed, 353 insertions, 9 deletions
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 3343ac437fe5..135b61801e83 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig | |||
@@ -10,6 +10,12 @@ config DRM_EXYNOS | |||
10 | Choose this option if you have a Samsung SoC EXYNOS chipset. | 10 | Choose this option if you have a Samsung SoC EXYNOS chipset. |
11 | If M is selected the module will be called exynosdrm. | 11 | If M is selected the module will be called exynosdrm. |
12 | 12 | ||
13 | config DRM_EXYNOS_DMABUF | ||
14 | bool "EXYNOS DRM DMABUF" | ||
15 | depends on DRM_EXYNOS | ||
16 | help | ||
17 | Choose this option if you want to use DMABUF feature for DRM. | ||
18 | |||
13 | config DRM_EXYNOS_FIMD | 19 | config DRM_EXYNOS_FIMD |
14 | bool "Exynos DRM FIMD" | 20 | bool "Exynos DRM FIMD" |
15 | depends on DRM_EXYNOS && !FB_S3C | 21 | depends on DRM_EXYNOS && !FB_S3C |
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 9e0bff8badf9..353e1b7c2e3c 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile | |||
@@ -8,6 +8,7 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \ | |||
8 | exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \ | 8 | exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \ |
9 | exynos_drm_plane.o | 9 | exynos_drm_plane.o |
10 | 10 | ||
11 | exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o | ||
11 | exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o | 12 | exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o |
12 | exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o \ | 13 | exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o \ |
13 | exynos_ddc.o exynos_hdmiphy.o \ | 14 | exynos_ddc.o exynos_hdmiphy.o \ |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c index de8d2090bce3..b3cb0a69fbf2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c | |||
@@ -35,7 +35,7 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, | |||
35 | unsigned int flags, struct exynos_drm_gem_buf *buf) | 35 | unsigned int flags, struct exynos_drm_gem_buf *buf) |
36 | { | 36 | { |
37 | dma_addr_t start_addr; | 37 | dma_addr_t start_addr; |
38 | unsigned int npages, page_size, i = 0; | 38 | unsigned int npages, i = 0; |
39 | struct scatterlist *sgl; | 39 | struct scatterlist *sgl; |
40 | int ret = 0; | 40 | int ret = 0; |
41 | 41 | ||
@@ -53,13 +53,13 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, | |||
53 | 53 | ||
54 | if (buf->size >= SZ_1M) { | 54 | if (buf->size >= SZ_1M) { |
55 | npages = buf->size >> SECTION_SHIFT; | 55 | npages = buf->size >> SECTION_SHIFT; |
56 | page_size = SECTION_SIZE; | 56 | buf->page_size = SECTION_SIZE; |
57 | } else if (buf->size >= SZ_64K) { | 57 | } else if (buf->size >= SZ_64K) { |
58 | npages = buf->size >> 16; | 58 | npages = buf->size >> 16; |
59 | page_size = SZ_64K; | 59 | buf->page_size = SZ_64K; |
60 | } else { | 60 | } else { |
61 | npages = buf->size >> PAGE_SHIFT; | 61 | npages = buf->size >> PAGE_SHIFT; |
62 | page_size = PAGE_SIZE; | 62 | buf->page_size = PAGE_SIZE; |
63 | } | 63 | } |
64 | 64 | ||
65 | buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); | 65 | buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); |
@@ -96,9 +96,9 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, | |||
96 | 96 | ||
97 | while (i < npages) { | 97 | while (i < npages) { |
98 | buf->pages[i] = phys_to_page(start_addr); | 98 | buf->pages[i] = phys_to_page(start_addr); |
99 | sg_set_page(sgl, buf->pages[i], page_size, 0); | 99 | sg_set_page(sgl, buf->pages[i], buf->page_size, 0); |
100 | sg_dma_address(sgl) = start_addr; | 100 | sg_dma_address(sgl) = start_addr; |
101 | start_addr += page_size; | 101 | start_addr += buf->page_size; |
102 | sgl = sg_next(sgl); | 102 | sgl = sg_next(sgl); |
103 | i++; | 103 | i++; |
104 | } | 104 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c new file mode 100644 index 000000000000..274909271c36 --- /dev/null +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | |||
@@ -0,0 +1,272 @@ | |||
1 | /* exynos_drm_dmabuf.c | ||
2 | * | ||
3 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
4 | * Author: Inki Dae <inki.dae@samsung.com> | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
7 | * copy of this software and associated documentation files (the "Software"), | ||
8 | * to deal in the Software without restriction, including without limitation | ||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
11 | * Software is furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice (including the next | ||
14 | * paragraph) shall be included in all copies or substantial portions of the | ||
15 | * Software. | ||
16 | * | ||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
20 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
23 | * OTHER DEALINGS IN THE SOFTWARE. | ||
24 | */ | ||
25 | |||
26 | #include "drmP.h" | ||
27 | #include "drm.h" | ||
28 | #include "exynos_drm_drv.h" | ||
29 | #include "exynos_drm_gem.h" | ||
30 | |||
31 | #include <linux/dma-buf.h> | ||
32 | |||
33 | static struct sg_table *exynos_pages_to_sg(struct page **pages, int nr_pages, | ||
34 | unsigned int page_size) | ||
35 | { | ||
36 | struct sg_table *sgt = NULL; | ||
37 | struct scatterlist *sgl; | ||
38 | int i, ret; | ||
39 | |||
40 | sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); | ||
41 | if (!sgt) | ||
42 | goto out; | ||
43 | |||
44 | ret = sg_alloc_table(sgt, nr_pages, GFP_KERNEL); | ||
45 | if (ret) | ||
46 | goto err_free_sgt; | ||
47 | |||
48 | if (page_size < PAGE_SIZE) | ||
49 | page_size = PAGE_SIZE; | ||
50 | |||
51 | for_each_sg(sgt->sgl, sgl, nr_pages, i) | ||
52 | sg_set_page(sgl, pages[i], page_size, 0); | ||
53 | |||
54 | return sgt; | ||
55 | |||
56 | err_free_sgt: | ||
57 | kfree(sgt); | ||
58 | sgt = NULL; | ||
59 | out: | ||
60 | return NULL; | ||
61 | } | ||
62 | |||
63 | static struct sg_table * | ||
64 | exynos_gem_map_dma_buf(struct dma_buf_attachment *attach, | ||
65 | enum dma_data_direction dir) | ||
66 | { | ||
67 | struct exynos_drm_gem_obj *gem_obj = attach->dmabuf->priv; | ||
68 | struct drm_device *dev = gem_obj->base.dev; | ||
69 | struct exynos_drm_gem_buf *buf; | ||
70 | struct sg_table *sgt = NULL; | ||
71 | unsigned int npages; | ||
72 | int nents; | ||
73 | |||
74 | DRM_DEBUG_PRIME("%s\n", __FILE__); | ||
75 | |||
76 | mutex_lock(&dev->struct_mutex); | ||
77 | |||
78 | buf = gem_obj->buffer; | ||
79 | |||
80 | /* there should always be pages allocated. */ | ||
81 | if (!buf->pages) { | ||
82 | DRM_ERROR("pages is null.\n"); | ||
83 | goto err_unlock; | ||
84 | } | ||
85 | |||
86 | npages = buf->size / buf->page_size; | ||
87 | |||
88 | sgt = exynos_pages_to_sg(buf->pages, npages, buf->page_size); | ||
89 | nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir); | ||
90 | |||
91 | DRM_DEBUG_PRIME("npages = %d buffer size = 0x%lx page_size = 0x%lx\n", | ||
92 | npages, buf->size, buf->page_size); | ||
93 | |||
94 | err_unlock: | ||
95 | mutex_unlock(&dev->struct_mutex); | ||
96 | return sgt; | ||
97 | } | ||
98 | |||
99 | static void exynos_gem_unmap_dma_buf(struct dma_buf_attachment *attach, | ||
100 | struct sg_table *sgt, | ||
101 | enum dma_data_direction dir) | ||
102 | { | ||
103 | dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir); | ||
104 | sg_free_table(sgt); | ||
105 | kfree(sgt); | ||
106 | sgt = NULL; | ||
107 | } | ||
108 | |||
109 | static void exynos_dmabuf_release(struct dma_buf *dmabuf) | ||
110 | { | ||
111 | struct exynos_drm_gem_obj *exynos_gem_obj = dmabuf->priv; | ||
112 | |||
113 | DRM_DEBUG_PRIME("%s\n", __FILE__); | ||
114 | |||
115 | /* | ||
116 | * exynos_dmabuf_release() call means that file object's | ||
117 | * f_count is 0 and it calls drm_gem_object_handle_unreference() | ||
118 | * to drop the references that these values had been increased | ||
119 | * at drm_prime_handle_to_fd() | ||
120 | */ | ||
121 | if (exynos_gem_obj->base.export_dma_buf == dmabuf) { | ||
122 | exynos_gem_obj->base.export_dma_buf = NULL; | ||
123 | |||
124 | /* | ||
125 | * drop this gem object refcount to release allocated buffer | ||
126 | * and resources. | ||
127 | */ | ||
128 | drm_gem_object_unreference_unlocked(&exynos_gem_obj->base); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | static void *exynos_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, | ||
133 | unsigned long page_num) | ||
134 | { | ||
135 | /* TODO */ | ||
136 | |||
137 | return NULL; | ||
138 | } | ||
139 | |||
140 | static void exynos_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf, | ||
141 | unsigned long page_num, | ||
142 | void *addr) | ||
143 | { | ||
144 | /* TODO */ | ||
145 | } | ||
146 | |||
147 | static void *exynos_gem_dmabuf_kmap(struct dma_buf *dma_buf, | ||
148 | unsigned long page_num) | ||
149 | { | ||
150 | /* TODO */ | ||
151 | |||
152 | return NULL; | ||
153 | } | ||
154 | |||
155 | static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf, | ||
156 | unsigned long page_num, void *addr) | ||
157 | { | ||
158 | /* TODO */ | ||
159 | } | ||
160 | |||
161 | static struct dma_buf_ops exynos_dmabuf_ops = { | ||
162 | .map_dma_buf = exynos_gem_map_dma_buf, | ||
163 | .unmap_dma_buf = exynos_gem_unmap_dma_buf, | ||
164 | .kmap = exynos_gem_dmabuf_kmap, | ||
165 | .kmap_atomic = exynos_gem_dmabuf_kmap_atomic, | ||
166 | .kunmap = exynos_gem_dmabuf_kunmap, | ||
167 | .kunmap_atomic = exynos_gem_dmabuf_kunmap_atomic, | ||
168 | .release = exynos_dmabuf_release, | ||
169 | }; | ||
170 | |||
171 | struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev, | ||
172 | struct drm_gem_object *obj, int flags) | ||
173 | { | ||
174 | struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); | ||
175 | |||
176 | return dma_buf_export(exynos_gem_obj, &exynos_dmabuf_ops, | ||
177 | exynos_gem_obj->base.size, 0600); | ||
178 | } | ||
179 | |||
180 | struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, | ||
181 | struct dma_buf *dma_buf) | ||
182 | { | ||
183 | struct dma_buf_attachment *attach; | ||
184 | struct sg_table *sgt; | ||
185 | struct scatterlist *sgl; | ||
186 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
187 | struct exynos_drm_gem_buf *buffer; | ||
188 | struct page *page; | ||
189 | int ret, i = 0; | ||
190 | |||
191 | DRM_DEBUG_PRIME("%s\n", __FILE__); | ||
192 | |||
193 | /* is this one of own objects? */ | ||
194 | if (dma_buf->ops == &exynos_dmabuf_ops) { | ||
195 | struct drm_gem_object *obj; | ||
196 | |||
197 | exynos_gem_obj = dma_buf->priv; | ||
198 | obj = &exynos_gem_obj->base; | ||
199 | |||
200 | /* is it from our device? */ | ||
201 | if (obj->dev == drm_dev) { | ||
202 | drm_gem_object_reference(obj); | ||
203 | return obj; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | attach = dma_buf_attach(dma_buf, drm_dev->dev); | ||
208 | if (IS_ERR(attach)) | ||
209 | return ERR_PTR(-EINVAL); | ||
210 | |||
211 | |||
212 | sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); | ||
213 | if (IS_ERR(sgt)) { | ||
214 | ret = PTR_ERR(sgt); | ||
215 | goto err_buf_detach; | ||
216 | } | ||
217 | |||
218 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); | ||
219 | if (!buffer) { | ||
220 | DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n"); | ||
221 | ret = -ENOMEM; | ||
222 | goto err_unmap_attach; | ||
223 | } | ||
224 | |||
225 | buffer->pages = kzalloc(sizeof(*page) * sgt->nents, GFP_KERNEL); | ||
226 | if (!buffer->pages) { | ||
227 | DRM_ERROR("failed to allocate pages.\n"); | ||
228 | ret = -ENOMEM; | ||
229 | goto err_free_buffer; | ||
230 | } | ||
231 | |||
232 | exynos_gem_obj = exynos_drm_gem_init(drm_dev, dma_buf->size); | ||
233 | if (!exynos_gem_obj) { | ||
234 | ret = -ENOMEM; | ||
235 | goto err_free_pages; | ||
236 | } | ||
237 | |||
238 | sgl = sgt->sgl; | ||
239 | buffer->dma_addr = sg_dma_address(sgl); | ||
240 | |||
241 | while (i < sgt->nents) { | ||
242 | buffer->pages[i] = sg_page(sgl); | ||
243 | buffer->size += sg_dma_len(sgl); | ||
244 | sgl = sg_next(sgl); | ||
245 | i++; | ||
246 | } | ||
247 | |||
248 | exynos_gem_obj->buffer = buffer; | ||
249 | buffer->sgt = sgt; | ||
250 | exynos_gem_obj->base.import_attach = attach; | ||
251 | |||
252 | DRM_DEBUG_PRIME("dma_addr = 0x%x, size = 0x%lx\n", buffer->dma_addr, | ||
253 | buffer->size); | ||
254 | |||
255 | return &exynos_gem_obj->base; | ||
256 | |||
257 | err_free_pages: | ||
258 | kfree(buffer->pages); | ||
259 | buffer->pages = NULL; | ||
260 | err_free_buffer: | ||
261 | kfree(buffer); | ||
262 | buffer = NULL; | ||
263 | err_unmap_attach: | ||
264 | dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); | ||
265 | err_buf_detach: | ||
266 | dma_buf_detach(dma_buf, attach); | ||
267 | return ERR_PTR(ret); | ||
268 | } | ||
269 | |||
270 | MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); | ||
271 | MODULE_DESCRIPTION("Samsung SoC DRM DMABUF Module"); | ||
272 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h new file mode 100644 index 000000000000..662a8f98ccdb --- /dev/null +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* exynos_drm_dmabuf.h | ||
2 | * | ||
3 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
4 | * Author: Inki Dae <inki.dae@samsung.com> | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
7 | * copy of this software and associated documentation files (the "Software"), | ||
8 | * to deal in the Software without restriction, including without limitation | ||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
11 | * Software is furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice (including the next | ||
14 | * paragraph) shall be included in all copies or substantial portions of the | ||
15 | * Software. | ||
16 | * | ||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
20 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
23 | * OTHER DEALINGS IN THE SOFTWARE. | ||
24 | */ | ||
25 | |||
26 | #ifndef _EXYNOS_DRM_DMABUF_H_ | ||
27 | #define _EXYNOS_DRM_DMABUF_H_ | ||
28 | |||
29 | #ifdef CONFIG_DRM_EXYNOS_DMABUF | ||
30 | struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev, | ||
31 | struct drm_gem_object *obj, int flags); | ||
32 | |||
33 | struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, | ||
34 | struct dma_buf *dma_buf); | ||
35 | #else | ||
36 | #define exynos_dmabuf_prime_export NULL | ||
37 | #define exynos_dmabuf_prime_import NULL | ||
38 | #endif | ||
39 | #endif | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index a6819b5f8428..f58a487e4425 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include "exynos_drm_gem.h" | 39 | #include "exynos_drm_gem.h" |
40 | #include "exynos_drm_plane.h" | 40 | #include "exynos_drm_plane.h" |
41 | #include "exynos_drm_vidi.h" | 41 | #include "exynos_drm_vidi.h" |
42 | #include "exynos_drm_dmabuf.h" | ||
42 | 43 | ||
43 | #define DRIVER_NAME "exynos" | 44 | #define DRIVER_NAME "exynos" |
44 | #define DRIVER_DESC "Samsung SoC DRM" | 45 | #define DRIVER_DESC "Samsung SoC DRM" |
@@ -149,6 +150,8 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) | |||
149 | { | 150 | { |
150 | DRM_DEBUG_DRIVER("%s\n", __FILE__); | 151 | DRM_DEBUG_DRIVER("%s\n", __FILE__); |
151 | 152 | ||
153 | drm_prime_init_file_private(&file->prime); | ||
154 | |||
152 | return exynos_drm_subdrv_open(dev, file); | 155 | return exynos_drm_subdrv_open(dev, file); |
153 | } | 156 | } |
154 | 157 | ||
@@ -170,6 +173,7 @@ static void exynos_drm_preclose(struct drm_device *dev, | |||
170 | e->base.destroy(&e->base); | 173 | e->base.destroy(&e->base); |
171 | } | 174 | } |
172 | } | 175 | } |
176 | drm_prime_destroy_file_private(&file->prime); | ||
173 | spin_unlock_irqrestore(&dev->event_lock, flags); | 177 | spin_unlock_irqrestore(&dev->event_lock, flags); |
174 | 178 | ||
175 | exynos_drm_subdrv_close(dev, file); | 179 | exynos_drm_subdrv_close(dev, file); |
@@ -225,7 +229,7 @@ static const struct file_operations exynos_drm_driver_fops = { | |||
225 | 229 | ||
226 | static struct drm_driver exynos_drm_driver = { | 230 | static struct drm_driver exynos_drm_driver = { |
227 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM | | 231 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM | |
228 | DRIVER_MODESET | DRIVER_GEM, | 232 | DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, |
229 | .load = exynos_drm_load, | 233 | .load = exynos_drm_load, |
230 | .unload = exynos_drm_unload, | 234 | .unload = exynos_drm_unload, |
231 | .open = exynos_drm_open, | 235 | .open = exynos_drm_open, |
@@ -241,6 +245,10 @@ static struct drm_driver exynos_drm_driver = { | |||
241 | .dumb_create = exynos_drm_gem_dumb_create, | 245 | .dumb_create = exynos_drm_gem_dumb_create, |
242 | .dumb_map_offset = exynos_drm_gem_dumb_map_offset, | 246 | .dumb_map_offset = exynos_drm_gem_dumb_map_offset, |
243 | .dumb_destroy = exynos_drm_gem_dumb_destroy, | 247 | .dumb_destroy = exynos_drm_gem_dumb_destroy, |
248 | .prime_handle_to_fd = drm_gem_prime_handle_to_fd, | ||
249 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, | ||
250 | .gem_prime_export = exynos_dmabuf_prime_export, | ||
251 | .gem_prime_import = exynos_dmabuf_prime_import, | ||
244 | .ioctls = exynos_ioctls, | 252 | .ioctls = exynos_ioctls, |
245 | .fops = &exynos_drm_driver_fops, | 253 | .fops = &exynos_drm_driver_fops, |
246 | .name = DRIVER_NAME, | 254 | .name = DRIVER_NAME, |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index e8ab3beb4510..31bb85f5d274 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c | |||
@@ -96,7 +96,7 @@ out: | |||
96 | return roundup(size, PAGE_SIZE); | 96 | return roundup(size, PAGE_SIZE); |
97 | } | 97 | } |
98 | 98 | ||
99 | static struct page **exynos_gem_get_pages(struct drm_gem_object *obj, | 99 | struct page **exynos_gem_get_pages(struct drm_gem_object *obj, |
100 | gfp_t gfpmask) | 100 | gfp_t gfpmask) |
101 | { | 101 | { |
102 | struct inode *inode; | 102 | struct inode *inode; |
@@ -196,6 +196,7 @@ static int exynos_drm_gem_get_pages(struct drm_gem_object *obj) | |||
196 | } | 196 | } |
197 | 197 | ||
198 | npages = obj->size >> PAGE_SHIFT; | 198 | npages = obj->size >> PAGE_SHIFT; |
199 | buf->page_size = PAGE_SIZE; | ||
199 | 200 | ||
200 | buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); | 201 | buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); |
201 | if (!buf->sgt) { | 202 | if (!buf->sgt) { |
@@ -308,7 +309,7 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj) | |||
308 | exynos_gem_obj = NULL; | 309 | exynos_gem_obj = NULL; |
309 | } | 310 | } |
310 | 311 | ||
311 | static struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev, | 312 | struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev, |
312 | unsigned long size) | 313 | unsigned long size) |
313 | { | 314 | { |
314 | struct exynos_drm_gem_obj *exynos_gem_obj; | 315 | struct exynos_drm_gem_obj *exynos_gem_obj; |
@@ -612,8 +613,17 @@ int exynos_drm_gem_init_object(struct drm_gem_object *obj) | |||
612 | 613 | ||
613 | void exynos_drm_gem_free_object(struct drm_gem_object *obj) | 614 | void exynos_drm_gem_free_object(struct drm_gem_object *obj) |
614 | { | 615 | { |
616 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
617 | struct exynos_drm_gem_buf *buf; | ||
618 | |||
615 | DRM_DEBUG_KMS("%s\n", __FILE__); | 619 | DRM_DEBUG_KMS("%s\n", __FILE__); |
616 | 620 | ||
621 | exynos_gem_obj = to_exynos_gem_obj(obj); | ||
622 | buf = exynos_gem_obj->buffer; | ||
623 | |||
624 | if (obj->import_attach) | ||
625 | drm_prime_gem_destroy(obj, buf->sgt); | ||
626 | |||
617 | exynos_drm_gem_destroy(to_exynos_gem_obj(obj)); | 627 | exynos_drm_gem_destroy(to_exynos_gem_obj(obj)); |
618 | } | 628 | } |
619 | 629 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index 4ed842039505..efc82527b272 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h | |||
@@ -40,6 +40,7 @@ | |||
40 | * device address with IOMMU. | 40 | * device address with IOMMU. |
41 | * @sgt: sg table to transfer page data. | 41 | * @sgt: sg table to transfer page data. |
42 | * @pages: contain all pages to allocated memory region. | 42 | * @pages: contain all pages to allocated memory region. |
43 | * @page_size: could be 4K, 64K or 1MB. | ||
43 | * @size: size of allocated memory region. | 44 | * @size: size of allocated memory region. |
44 | */ | 45 | */ |
45 | struct exynos_drm_gem_buf { | 46 | struct exynos_drm_gem_buf { |
@@ -47,6 +48,7 @@ struct exynos_drm_gem_buf { | |||
47 | dma_addr_t dma_addr; | 48 | dma_addr_t dma_addr; |
48 | struct sg_table *sgt; | 49 | struct sg_table *sgt; |
49 | struct page **pages; | 50 | struct page **pages; |
51 | unsigned long page_size; | ||
50 | unsigned long size; | 52 | unsigned long size; |
51 | }; | 53 | }; |
52 | 54 | ||
@@ -74,9 +76,15 @@ struct exynos_drm_gem_obj { | |||
74 | unsigned int flags; | 76 | unsigned int flags; |
75 | }; | 77 | }; |
76 | 78 | ||
79 | struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask); | ||
80 | |||
77 | /* destroy a buffer with gem object */ | 81 | /* destroy a buffer with gem object */ |
78 | void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj); | 82 | void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj); |
79 | 83 | ||
84 | /* create a private gem object and initialize it. */ | ||
85 | struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev, | ||
86 | unsigned long size); | ||
87 | |||
80 | /* create a new buffer with gem object */ | 88 | /* create a new buffer with gem object */ |
81 | struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, | 89 | struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, |
82 | unsigned int flags, | 90 | unsigned int flags, |