Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3df64d7b authored by CK Hu's avatar CK Hu
Browse files

drm/mediatek: Implement gem prime vmap/vunmap function



For some application which need kernel virtual address, such as fbcon,
implement these function to map/unmap kernel virtual address of prime
buffer.

Signed-off-by: default avatarCK Hu <ck.hu@mediatek.com>
parent 9e98c678
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -341,6 +341,8 @@ static struct drm_driver mtk_drm_driver = {
	.gem_prime_get_sg_table = mtk_gem_prime_get_sg_table,
	.gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
	.gem_prime_mmap = mtk_drm_gem_mmap_buf,
	.gem_prime_vmap = mtk_drm_gem_prime_vmap,
	.gem_prime_vunmap = mtk_drm_gem_prime_vunmap,
	.fops = &mtk_drm_fops,

	.name = DRIVER_NAME,
+46 −0
Original line number Diff line number Diff line
@@ -241,3 +241,49 @@ struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
	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;

	sgt = mtk_gem_prime_get_sg_table(obj);
	if (IS_ERR(sgt))
		return NULL;

	npages = obj->size >> PAGE_SHIFT;
	mtk_gem->pages = kcalloc(npages, sizeof(*mtk_gem->pages), GFP_KERNEL);
	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;
	}
	mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP,
			       pgprot_writecombine(PAGE_KERNEL));

out:
	kfree((void *)sgt);

	return mtk_gem->kvaddr;
}

void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
{
	struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj);

	if (!mtk_gem->pages)
		return;

	vunmap(vaddr);
	mtk_gem->kvaddr = 0;
	kfree((void *)mtk_gem->pages);
}
+3 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ struct mtk_drm_gem_obj {
	dma_addr_t		dma_addr;
	unsigned long		dma_attrs;
	struct sg_table		*sg;
	struct page		**pages;
};

#define to_mtk_gem_obj(x)	container_of(x, struct mtk_drm_gem_obj, base)
@@ -52,5 +53,7 @@ int mtk_drm_gem_mmap_buf(struct drm_gem_object *obj,
struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj);
struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
			struct dma_buf_attachment *attach, struct sg_table *sg);
void *mtk_drm_gem_prime_vmap(struct drm_gem_object *obj);
void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);

#endif