drm/exynos: add exynos drm specific fb_mmap function
authorPrathyush K <prathyush.k@samsung.com>
Mon, 19 Nov 2012 08:25:28 +0000 (13:55 +0530)
committerInki Dae <inki.dae@samsung.com>
Wed, 5 Dec 2012 05:39:20 +0000 (14:39 +0900)
Changelog v3:

Passing the actual buffer size instead of vm_size to dma_mmap_attrs.

Changelog v2:

Extracting the private data from fb_info structure to obtain the exynos
gem buffer structure. Now, dma address is obtained from the exynos gem
buffer structure and not from smem_start. Also calling dma_mmap_attrs
(instead of dma_mmap_writecombine) with the same attributes used
during allocation.

Changelog v1:

This patch adds a exynos drm specific implementation of fb_mmap
which supports mapping a non-contiguous buffer to user space.

This new function does not assume that the frame buffer is contiguous
and calls dma_mmap_writecombine for mapping the buffer to user space.
dma_mmap_writecombine will be able to map a contiguous buffer as well
as non-contig buffer depending on whether an IOMMU mapping is created
for drm or not.

Signed-off-by: Prathyush K <prathyush.k@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
drivers/gpu/drm/exynos/exynos_drm_fbdev.c

index e7466c4414cb8f04e8b462ce98a28dbe6a539b5e..151c4c9c50c7bd36d51aefd901857bc8a8f82e9e 100644 (file)
@@ -46,8 +46,38 @@ struct exynos_drm_fbdev {
        struct exynos_drm_gem_obj       *exynos_gem_obj;
 };
 
+static int exynos_drm_fb_mmap(struct fb_info *info,
+                       struct vm_area_struct *vma)
+{
+       struct drm_fb_helper *helper = info->par;
+       struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(helper);
+       struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj;
+       struct exynos_drm_gem_buf *buffer = exynos_gem_obj->buffer;
+       unsigned long vm_size;
+       int ret;
+
+       DRM_DEBUG_KMS("%s\n", __func__);
+
+       vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
+
+       vm_size = vma->vm_end - vma->vm_start;
+
+       if (vm_size > buffer->size)
+               return -EINVAL;
+
+       ret = dma_mmap_attrs(helper->dev->dev, vma, buffer->kvaddr,
+               buffer->dma_addr, buffer->size, &buffer->dma_attrs);
+       if (ret < 0) {
+               DRM_ERROR("failed to mmap.\n");
+               return ret;
+       }
+
+       return 0;
+}
+
 static struct fb_ops exynos_drm_fb_ops = {
        .owner          = THIS_MODULE,
+       .fb_mmap        = exynos_drm_fb_mmap,
        .fb_fillrect    = cfb_fillrect,
        .fb_copyarea    = cfb_copyarea,
        .fb_imageblit   = cfb_imageblit,