.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2015 MediaTek Inc. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of the GNU General Public License version 2 as |
---|
6 | | - * published by the Free Software Foundation. |
---|
7 | | - * |
---|
8 | | - * This program is distributed in the hope that it will be useful, |
---|
9 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
11 | | - * GNU General Public License for more details. |
---|
12 | 4 | */ |
---|
13 | 5 | |
---|
14 | | -#include <drm/drmP.h> |
---|
15 | | -#include <drm/drm_gem.h> |
---|
16 | 6 | #include <linux/dma-buf.h> |
---|
| 7 | + |
---|
| 8 | +#include <drm/drm.h> |
---|
| 9 | +#include <drm/drm_device.h> |
---|
| 10 | +#include <drm/drm_gem.h> |
---|
| 11 | +#include <drm/drm_prime.h> |
---|
17 | 12 | |
---|
18 | 13 | #include "mtk_drm_drv.h" |
---|
19 | 14 | #include "mtk_drm_gem.h" |
---|
.. | .. |
---|
122 | 117 | goto err_handle_create; |
---|
123 | 118 | |
---|
124 | 119 | /* drop reference from allocate - handle holds it now. */ |
---|
125 | | - drm_gem_object_put_unlocked(&mtk_gem->base); |
---|
| 120 | + drm_gem_object_put(&mtk_gem->base); |
---|
126 | 121 | |
---|
127 | 122 | return 0; |
---|
128 | 123 | |
---|
.. | .. |
---|
144 | 139 | * VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap(). |
---|
145 | 140 | */ |
---|
146 | 141 | vma->vm_flags &= ~VM_PFNMAP; |
---|
147 | | - vma->vm_pgoff = 0; |
---|
148 | 142 | |
---|
149 | 143 | ret = dma_mmap_attrs(priv->dma_dev, vma, mtk_gem->cookie, |
---|
150 | 144 | mtk_gem->dma_addr, obj->size, mtk_gem->dma_attrs); |
---|
151 | | - if (ret) |
---|
152 | | - drm_gem_vm_close(vma); |
---|
153 | 145 | |
---|
154 | 146 | return ret; |
---|
155 | 147 | } |
---|
.. | .. |
---|
175 | 167 | return ret; |
---|
176 | 168 | |
---|
177 | 169 | obj = vma->vm_private_data; |
---|
| 170 | + |
---|
| 171 | + /* |
---|
| 172 | + * Set vm_pgoff (used as a fake buffer offset by DRM) to 0 and map the |
---|
| 173 | + * whole buffer from the start. |
---|
| 174 | + */ |
---|
| 175 | + vma->vm_pgoff = 0; |
---|
178 | 176 | |
---|
179 | 177 | return mtk_drm_gem_object_mmap(obj, vma); |
---|
180 | 178 | } |
---|
.. | .. |
---|
212 | 210 | struct dma_buf_attachment *attach, struct sg_table *sg) |
---|
213 | 211 | { |
---|
214 | 212 | struct mtk_drm_gem_obj *mtk_gem; |
---|
215 | | - int ret; |
---|
216 | | - struct scatterlist *s; |
---|
217 | | - unsigned int i; |
---|
218 | | - dma_addr_t expected; |
---|
| 213 | + |
---|
| 214 | + /* check if the entries in the sg_table are contiguous */ |
---|
| 215 | + if (drm_prime_get_contiguous_size(sg) < attach->dmabuf->size) { |
---|
| 216 | + DRM_ERROR("sg_table is not contiguous"); |
---|
| 217 | + return ERR_PTR(-EINVAL); |
---|
| 218 | + } |
---|
219 | 219 | |
---|
220 | 220 | mtk_gem = mtk_drm_gem_init(dev, attach->dmabuf->size); |
---|
221 | | - |
---|
222 | 221 | if (IS_ERR(mtk_gem)) |
---|
223 | 222 | return ERR_CAST(mtk_gem); |
---|
224 | | - |
---|
225 | | - expected = sg_dma_address(sg->sgl); |
---|
226 | | - for_each_sg(sg->sgl, s, sg->nents, i) { |
---|
227 | | - if (sg_dma_address(s) != expected) { |
---|
228 | | - DRM_ERROR("sg_table is not contiguous"); |
---|
229 | | - ret = -EINVAL; |
---|
230 | | - goto err_gem_free; |
---|
231 | | - } |
---|
232 | | - expected = sg_dma_address(s) + sg_dma_len(s); |
---|
233 | | - } |
---|
234 | 223 | |
---|
235 | 224 | mtk_gem->dma_addr = sg_dma_address(sg->sgl); |
---|
236 | 225 | mtk_gem->sg = sg; |
---|
237 | 226 | |
---|
238 | 227 | return &mtk_gem->base; |
---|
| 228 | +} |
---|
239 | 229 | |
---|
240 | | -err_gem_free: |
---|
241 | | - kfree(mtk_gem); |
---|
242 | | - return ERR_PTR(ret); |
---|
| 230 | +void *mtk_drm_gem_prime_vmap(struct drm_gem_object *obj) |
---|
| 231 | +{ |
---|
| 232 | + struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj); |
---|
| 233 | + struct sg_table *sgt; |
---|
| 234 | + unsigned int npages; |
---|
| 235 | + |
---|
| 236 | + if (mtk_gem->kvaddr) |
---|
| 237 | + return mtk_gem->kvaddr; |
---|
| 238 | + |
---|
| 239 | + sgt = mtk_gem_prime_get_sg_table(obj); |
---|
| 240 | + if (IS_ERR(sgt)) |
---|
| 241 | + return NULL; |
---|
| 242 | + |
---|
| 243 | + npages = obj->size >> PAGE_SHIFT; |
---|
| 244 | + mtk_gem->pages = kcalloc(npages, sizeof(*mtk_gem->pages), GFP_KERNEL); |
---|
| 245 | + if (!mtk_gem->pages) |
---|
| 246 | + goto out; |
---|
| 247 | + |
---|
| 248 | + drm_prime_sg_to_page_addr_arrays(sgt, mtk_gem->pages, NULL, npages); |
---|
| 249 | + |
---|
| 250 | + mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP, |
---|
| 251 | + pgprot_writecombine(PAGE_KERNEL)); |
---|
| 252 | + if (!mtk_gem->kvaddr) { |
---|
| 253 | + kfree(sgt); |
---|
| 254 | + kfree(mtk_gem->pages); |
---|
| 255 | + return NULL; |
---|
| 256 | + } |
---|
| 257 | +out: |
---|
| 258 | + kfree(sgt); |
---|
| 259 | + |
---|
| 260 | + return mtk_gem->kvaddr; |
---|
| 261 | +} |
---|
| 262 | + |
---|
| 263 | +void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) |
---|
| 264 | +{ |
---|
| 265 | + struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj); |
---|
| 266 | + |
---|
| 267 | + if (!mtk_gem->pages) |
---|
| 268 | + return; |
---|
| 269 | + |
---|
| 270 | + vunmap(vaddr); |
---|
| 271 | + mtk_gem->kvaddr = NULL; |
---|
| 272 | + kfree(mtk_gem->pages); |
---|
243 | 273 | } |
---|