drm/msm: add support for "stolen" mem
authorRob Clark <robdclark@gmail.com>
Tue, 3 Mar 2015 20:04:25 +0000 (15:04 -0500)
committerRob Clark <robdclark@gmail.com>
Wed, 1 Apr 2015 23:29:33 +0000 (19:29 -0400)
Add support to use the VRAM carveout (if specified in dtb) for fbdev
scanout buffer.  This allows drm/msm to take over a bootloader splash-
screen, and avoids corruption on screen that results if the kernel uses
memory that is still being scanned out for itself.

Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_fbdev.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem.h

index b250610..0c38f34 100644 (file)
@@ -182,21 +182,57 @@ static int get_mdp_ver(struct platform_device *pdev)
        return 4;
 }
 
+#include <linux/of_address.h>
+
 static int msm_init_vram(struct drm_device *dev)
 {
        struct msm_drm_private *priv = dev->dev_private;
+       unsigned long size = 0;
+       int ret = 0;
+
+#ifdef CONFIG_OF
+       /* In the device-tree world, we could have a 'memory-region'
+        * phandle, which gives us a link to our "vram".  Allocating
+        * is all nicely abstracted behind the dma api, but we need
+        * to know the entire size to allocate it all in one go. There
+        * are two cases:
+        *  1) device with no IOMMU, in which case we need exclusive
+        *     access to a VRAM carveout big enough for all gpu
+        *     buffers
+        *  2) device with IOMMU, but where the bootloader puts up
+        *     a splash screen.  In this case, the VRAM carveout
+        *     need only be large enough for fbdev fb.  But we need
+        *     exclusive access to the buffer to avoid the kernel
+        *     using those pages for other purposes (which appears
+        *     as corruption on screen before we have a chance to
+        *     load and do initial modeset)
+        */
+       struct device_node *node;
+
+       node = of_parse_phandle(dev->dev->of_node, "memory-region", 0);
+       if (node) {
+               struct resource r;
+               ret = of_address_to_resource(node, 0, &r);
+               if (ret)
+                       return ret;
+               size = r.end - r.start;
+               DRM_INFO("using VRAM carveout: %lx@%08x\n", size, r.start);
+       } else
+#endif
 
        /* if we have no IOMMU, then we need to use carveout allocator.
         * Grab the entire CMA chunk carved out in early startup in
         * mach-msm:
         */
        if (!iommu_present(&platform_bus_type)) {
+               DRM_INFO("using %s VRAM carveout\n", vram);
+               size = memparse(vram, NULL);
+       }
+
+       if (size) {
                DEFINE_DMA_ATTRS(attrs);
-               unsigned long size;
                void *p;
 
-               DBG("using %s VRAM carveout", vram);
-               size = memparse(vram, NULL);
                priv->vram.size = size;
 
                drm_mm_init(&priv->vram.mm, 0, (size >> PAGE_SHIFT) - 1);
@@ -220,7 +256,7 @@ static int msm_init_vram(struct drm_device *dev)
                                (uint32_t)(priv->vram.paddr + size));
        }
 
-       return 0;
+       return ret;
 }
 
 static int msm_load(struct drm_device *dev, unsigned long flags)
Simple merge
Simple merge
Simple merge