diff options
Diffstat (limited to 'drivers/gpu/drm/mediatek/mtk_drm_gem.c')
-rw-r--r-- | drivers/gpu/drm/mediatek/mtk_drm_gem.c | 48 |
1 files changed, 19 insertions, 29 deletions
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c index 6190cc3b7b0d..cdd1a6e61564 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c @@ -8,11 +8,20 @@ #include <drm/drm.h> #include <drm/drm_device.h> #include <drm/drm_gem.h> +#include <drm/drm_gem_cma_helper.h> #include <drm/drm_prime.h> #include "mtk_drm_drv.h" #include "mtk_drm_gem.h" +static const struct drm_gem_object_funcs mtk_drm_gem_object_funcs = { + .free = mtk_drm_gem_free_object, + .get_sg_table = mtk_gem_prime_get_sg_table, + .vmap = mtk_drm_gem_prime_vmap, + .vunmap = mtk_drm_gem_prime_vunmap, + .vm_ops = &drm_gem_cma_vm_ops, +}; + static struct mtk_drm_gem_obj *mtk_drm_gem_init(struct drm_device *dev, unsigned long size) { @@ -25,6 +34,8 @@ static struct mtk_drm_gem_obj *mtk_drm_gem_init(struct drm_device *dev, if (!mtk_gem_obj) return ERR_PTR(-ENOMEM); + mtk_gem_obj->base.funcs = &mtk_drm_gem_object_funcs; + ret = drm_gem_object_init(dev, &mtk_gem_obj->base, size); if (ret < 0) { DRM_ERROR("failed to initialize gem object\n"); @@ -212,46 +223,28 @@ struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sg) { struct mtk_drm_gem_obj *mtk_gem; - int ret; - struct scatterlist *s; - unsigned int i; - dma_addr_t expected; - mtk_gem = mtk_drm_gem_init(dev, attach->dmabuf->size); + /* check if the entries in the sg_table are contiguous */ + if (drm_prime_get_contiguous_size(sg) < attach->dmabuf->size) { + DRM_ERROR("sg_table is not contiguous"); + return ERR_PTR(-EINVAL); + } + mtk_gem = mtk_drm_gem_init(dev, attach->dmabuf->size); if (IS_ERR(mtk_gem)) return ERR_CAST(mtk_gem); - expected = sg_dma_address(sg->sgl); - for_each_sg(sg->sgl, s, sg->nents, i) { - if (!sg_dma_len(s)) - break; - - if (sg_dma_address(s) != expected) { - DRM_ERROR("sg_table is not contiguous"); - ret = -EINVAL; - goto err_gem_free; - } - expected = sg_dma_address(s) + sg_dma_len(s); - } - mtk_gem->dma_addr = sg_dma_address(sg->sgl); mtk_gem->sg = sg; return &mtk_gem->base; - -err_gem_free: - kfree(mtk_gem); - return ERR_PTR(ret); } void *mtk_drm_gem_prime_vmap(struct drm_gem_object *obj) { struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj); struct sg_table *sgt; - struct sg_page_iter iter; unsigned int npages; - unsigned int i = 0; if (mtk_gem->kvaddr) return mtk_gem->kvaddr; @@ -265,11 +258,8 @@ void *mtk_drm_gem_prime_vmap(struct drm_gem_object *obj) if (!mtk_gem->pages) goto out; - for_each_sg_page(sgt->sgl, &iter, sgt->orig_nents, 0) { - mtk_gem->pages[i++] = sg_page_iter_page(&iter); - if (i > npages) - break; - } + drm_prime_sg_to_page_addr_arrays(sgt, mtk_gem->pages, NULL, npages); + mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); |