drm/msm: add support for "stolen" mem

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>
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index b250610..0c38f34 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -182,21 +182,57 @@
 	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 @@
 				(uint32_t)(priv->vram.paddr + size));
 	}
 
-	return 0;
+	return ret;
 }
 
 static int msm_load(struct drm_device *dev, unsigned long flags)