drm/msm: split out vram initialization
Subsystems (4)
PATCH 1/3 drm/msm: split out vram initialization
We'll want to extend this a bit to handle also a reserved-memory ("stolen") region, so that drm/msm can take-over bootloader splash screen. First split it out into it's own fxn to reduce noise in the following patch.
--- drivers/gpu/drm/msm/msm_drv.c | 58 +++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 24 deletions(-)
drivers/gpu/drm/msm/msm_drv.c +34 -24
@@ -182,29 +182,9 @@ static int get_mdp_ver(struct platform_device *pdev)return 4 ; } -static int msm_load (struct drm_device *dev,unsigned long flags) +static int msm_init_vram (struct drm_device *dev) { -struct platform_device *pdev = dev->platformdev; -struct msm_drm_private *priv; -struct msm_kms *kms; -int ret; - - priv =kzalloc (sizeof (*priv),GFP_KERNEL ); -if (!priv) { -dev_err (dev->dev,"failed to allocate private data\n" ); -return -ENOMEM ; - } - - dev->dev_private = priv; - - priv->wq =alloc_ordered_workqueue ("msm" ,0 ); -init_waitqueue_head (&priv->fence_event); -init_waitqueue_head (&priv->pending_crtcs_event); - -INIT_LIST_HEAD (&priv->inactive_list); -INIT_LIST_HEAD (&priv->fence_cbs); - -drm_mode_config_init (dev); +struct msm_drm_private *priv = dev->dev_private;/* if we have no IOMMU, then we need to use carveout allocator. * Grab the entire CMA chunk carved out in early startup in
@@ -232,8 +212,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)if (!p) {dev_err (dev->dev,"failed to allocate VRAM\n" ); priv->vram.paddr =0 ; - ret = -ENOMEM ; - goto fail; +return -ENOMEM ; } dev_info(dev->dev, "VRAM: %08x->%08x\n",
@@ -241,6 +220,37 @@ static int msm_load(struct drm_device *dev, unsigned long flags) (uint32_t)(priv->vram.paddr + size)); } +return 0 ; +} + +static int msm_load (struct drm_device *dev,unsigned long flags) +{ +struct platform_device *pdev = dev->platformdev; +struct msm_drm_private *priv; +struct msm_kms *kms; +int ret; + + priv =kzalloc (sizeof (*priv),GFP_KERNEL ); +if (!priv) { +dev_err (dev->dev,"failed to allocate private data\n" ); +return -ENOMEM ; + } + + dev->dev_private = priv; + + priv->wq =alloc_ordered_workqueue ("msm" ,0 ); +init_waitqueue_head (&priv->fence_event); +init_waitqueue_head (&priv->pending_crtcs_event); + +INIT_LIST_HEAD (&priv->inactive_list); +INIT_LIST_HEAD (&priv->fence_cbs); + +drm_mode_config_init (dev); + + ret =msm_init_vram (dev); +if (ret) + goto fail; +platform_set_drvdata (pdev, dev);/* Bind all our sub-components: */
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 2/3 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.
--- drivers/gpu/drm/msm/msm_drv.c | 44 +++++++++++++++++++++++++++++++++++++---- drivers/gpu/drm/msm/msm_fbdev.c | 3 ++- drivers/gpu/drm/msm/msm_gem.c | 25 ++++++++++++++++++----- drivers/gpu/drm/msm/msm_gem.h | 5 ++++- 4 files changed, 66 insertions(+), 11 deletions(-)
drivers/gpu/drm/msm/msm_drv.c +40 -4
@@ -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)
drivers/gpu/drm/msm/msm_fbdev.c +2 -1
@@ -110,7 +110,8 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, size = mode_cmd.pitches[0 ] * mode_cmd.height;DBG ("allocating %d bytes for fb %d" , size, dev->primary->index);mutex_lock (&dev->struct_mutex); - fbdev->bo =msm_gem_new (dev, size,MSM_BO_SCANOUT |MSM_BO_WC ); + fbdev->bo =msm_gem_new (dev, size,MSM_BO_SCANOUT | +MSM_BO_WC |MSM_BO_STOLEN );mutex_unlock (&dev->struct_mutex);if (IS_ERR (fbdev->bo)) { ret =PTR_ERR (fbdev->bo);
drivers/gpu/drm/msm/msm_gem.c +20 -5
@@ -32,6 +32,12 @@ static dma_addr_t physaddr(struct drm_gem_object *obj) priv->vram.paddr; } +static bool use_pages (struct drm_gem_object *obj) +{ +struct msm_gem_object *msm_obj =to_msm_bo (obj); +return !msm_obj->vram_node; +} +/* allocate pages from VRAM carveout, used when no IOMMU: */ static struct page **get_pages_vram (struct drm_gem_object *obj,int npages)
@@ -72,7 +78,7 @@ static struct page **get_pages(struct drm_gem_object *obj)struct page **p;int npages = obj->size >>PAGE_SHIFT ; -if (iommu_present (&platform_bus_type)) +if (use_pages (obj)) p =drm_gem_get_pages (obj);else p =get_pages_vram (obj, npages);
@@ -116,7 +122,7 @@ static void put_pages(struct drm_gem_object *obj)sg_free_table (msm_obj->sgt);kfree (msm_obj->sgt); -if (iommu_present (&platform_bus_type)) +if (use_pages (obj))drm_gem_put_pages (obj, msm_obj->pages, true, false);else {drm_mm_remove_node (msm_obj->vram_node);
@@ -580,6 +586,7 @@ static int msm_gem_new_impl(struct drm_device *dev,struct msm_drm_private *priv = dev->dev_private;struct msm_gem_object *msm_obj;unsigned sz; +bool use_vram = false;switch (flags &MSM_BO_CACHE_MASK ) {case MSM_BO_UNCACHED :
@@ -592,15 +599,23 @@ static int msm_gem_new_impl(struct drm_device *dev,return -EINVAL ; } - sz =sizeof (*msm_obj);if (!iommu_present (&platform_bus_type)) + use_vram = true; +else if ((flags &MSM_BO_STOLEN ) && priv->vram.size) + use_vram = true; + +if (WARN_ON (use_vram && !priv->vram.size)) +return -EINVAL ; + + sz =sizeof (*msm_obj); +if (use_vram) sz +=sizeof (struct drm_mm_node ); msm_obj =kzalloc (sz,GFP_KERNEL );if (!msm_obj)return -ENOMEM ; -if (!iommu_present (&platform_bus_type)) +if (use_vram) msm_obj->vram_node = (void *)&msm_obj[1 ]; msm_obj->flags = flags;
@@ -630,7 +645,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev,if (ret) goto fail; -if (iommu_present (&platform_bus_type)) { +if (use_pages (obj)) { ret =drm_gem_object_init (dev, obj, size);if (ret) goto fail;
drivers/gpu/drm/msm/msm_gem.h +4 -1
@@ -21,6 +21,9 @@#include <linux/reservation.h> #include "msm_drv.h" +/* Additional internal-use only BO flags: */ +#define MSM_BO_STOLEN 0x10000000/* try to use stolen/splash memory */ +struct msm_gem_object {struct drm_gem_object base;
@@ -59,7 +62,7 @@ struct msm_gem_object {struct reservation_object _resv;/* For physically contiguous buffers. Used when we don't have -* an IOMMU. +* an IOMMU. Also used for stolen/splashscreen buffer. */ struct drm_mm_node *vram_node; };
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 3/3 RFC: dts: ifc6410: add splash screen carveout
In reply to Rob ClarkAdd a reserved-memory region for bootloader splashscreen, and assign it to the display device, so that drm/msm can take over the bootloader's splashscreen.
--- arch/arm/boot/dts/qcom-apq8064-ifc6410.dts | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
arch/arm/boot/dts/qcom-apq8064-ifc6410.dts +14 -0
@@ -15,6 +15,16 @@ 0x90000000 0x70000000>; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + splashmem: framebuffer@90000000 { + reg = <0x90000000 0x800000>; + }; + }; + aliases { serial0 = &serial0; serial1 = &serial1;
@@ -183,5 +193,9 @@ }; }; + + mdp: qcom,mdp@5100000 { + memory-region = <&splashmem>; + }; }; };
Signature · 6 lines
2.1.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/3] RFC: dts: ifc6410: add splash screen carveout
Quoted 4 lines · Rob Clark
Add a reserved-memory region for bootloader splashscreen, and assign it to the display device, so that drm/msm can take over the bootloader's splashscreen.
Hi Rob,
Rather silly question - does the bootloader always use/preserve the same amount of memory regardless of the display's resolution & bpp ? If not would this patch work in such cases ?
Cheers
Emil
Re: [PATCH 3/3] RFC: dts: ifc6410: add splash screen carveout
Quoted 11 lines · Emil Velikov
Quoted 4 lines · Rob Clark
Add a reserved-memory region for bootloader splashscreen, and assign it to the display device, so that drm/msm can take over the bootloader's splashscreen.
Hi Rob,
Rather silly question - does the bootloader always use/preserve the same amount of memory regardless of the display's resolution & bpp ? If not would this patch work in such cases ?
In most cases, the bootloader puts up a splash screen on built-in lcd panel, which sort of makes the problem easier (fixed resolution). For external display, I think you just have to size it for worst-case (largest) resolution.
(ofc it is RFC since I was hoping to get comments if anyone has better suggestions.. probably should have cc'd more people ;-))
BR,
-R
Quoted 2 lines
Cheers
Emil
Re: [PATCH 3/3] RFC: dts: ifc6410: add splash screen carveout
Quoted 13 lines · Rob Clark
Quoted 11 lines · Emil Velikov
Quoted 4 lines · Rob Clark
Add a reserved-memory region for bootloader splashscreen, and assign it to the display device, so that drm/msm can take over the bootloader's splashscreen.
Hi Rob,
Rather silly question - does the bootloader always use/preserve the same amount of memory regardless of the display's resolution & bpp ? If not would this patch work in such cases ?
Quoted 8 lines
In most cases, the bootloader puts up a splash screen on built-in lcd panel, which sort of makes the problem easier (fixed resolution). For external display, I think you just have to size it for worst-case (largest) resolution.
(ofc it is RFC since I was hoping to get comments if anyone has better suggestions.. probably should have cc'd more people ;-))
I believe that Intel managed to get flicker-free boot. iirc Jess Barnes was one of the people working on it.
That said I'm not sure how much of their work is applicable in non-x86 land :-\
-Emil