drm/exynos: consider no iommu support to console framebuffer
authorInki Dae <inki.dae@samsung.com>
Fri, 21 Dec 2012 08:59:20 +0000 (17:59 +0900)
committerInki Dae <inki.dae@samsung.com>
Fri, 4 Jan 2013 06:54:32 +0000 (15:54 +0900)
This patch considers no iommu support to kernel space mapping
of console framebuffer.

Without iommu, we get physical address instead of device address
after dma_alloc_attrs function is called. So we should consider
the case without iommu when it maps console framebuffer with
kernel space.

Changelog v2:
- calll vunmap function only with iommu support.

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 f433eb7533a97e9550f86f2f94c4f5fa173d0427..eae064a3ee3072029a46d7e9ae2fdd4bc5ae1eee 100644 (file)
@@ -34,6 +34,7 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_gem.h"
+#include "exynos_drm_iommu.h"
 
 #define MAX_CONNECTOR          4
 #define PREFERRED_BPP          32
@@ -111,9 +112,18 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
 
        /* map pages with kernel virtual space. */
        if (!buffer->kvaddr) {
-               unsigned int nr_pages = buffer->size >> PAGE_SHIFT;
-               buffer->kvaddr = vmap(buffer->pages, nr_pages, VM_MAP,
+               if (is_drm_iommu_supported(dev)) {
+                       unsigned int nr_pages = buffer->size >> PAGE_SHIFT;
+
+                       buffer->kvaddr = vmap(buffer->pages, nr_pages, VM_MAP,
                                        pgprot_writecombine(PAGE_KERNEL));
+               } else {
+                       phys_addr_t dma_addr = buffer->dma_addr;
+                       if (dma_addr)
+                               buffer->kvaddr = phys_to_virt(dma_addr);
+                       else
+                               buffer->kvaddr = (void __iomem *)NULL;
+               }
                if (!buffer->kvaddr) {
                        DRM_ERROR("failed to map pages to kernel space.\n");
                        return -EIO;
@@ -128,8 +138,12 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
 
        dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr;
        fbi->screen_base = buffer->kvaddr + offset;
-       fbi->fix.smem_start = (unsigned long)
+       if (is_drm_iommu_supported(dev))
+               fbi->fix.smem_start = (unsigned long)
                        (page_to_phys(sg_page(buffer->sgt->sgl)) + offset);
+       else
+               fbi->fix.smem_start = (unsigned long)buffer->dma_addr;
+
        fbi->screen_size = size;
        fbi->fix.smem_len = size;
 
@@ -320,7 +334,7 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev,
        struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj;
        struct drm_framebuffer *fb;
 
-       if (exynos_gem_obj->buffer->kvaddr)
+       if (is_drm_iommu_supported(dev) && exynos_gem_obj->buffer->kvaddr)
                vunmap(exynos_gem_obj->buffer->kvaddr);
 
        /* release drm framebuffer and real buffer */