From: Colin Cross Date: Wed, 20 Oct 2010 04:09:29 +0000 (-0700) Subject: [ARM] tegra: Add function to copy framebuffer contents X-Git-Tag: firefly_0821_release~9833^2~147^2~3 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=00eb0f29e9e3c9882b334a7fffa13f63085e8117;p=firefly-linux-kernel-4.4.55.git [ARM] tegra: Add function to copy framebuffer contents Due to conflicting restrictions on the location of the framebuffer between the bootloader and the protected aperture, the framebuffer is likely to need to be moved during boot. This patch provides tegra_move_framebuffer, which can handle move the framebuffer from lowmem, highmem, or unmapped memory into unmapped memory. Change-Id: Ic37e5e337cd3129065fe56fd7777a86d06ad69ac --- diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h index 086ec70c470d..c47a21f71260 100644 --- a/arch/arm/mach-tegra/board.h +++ b/arch/arm/mach-tegra/board.h @@ -30,6 +30,8 @@ void __init tegra_init_clock(void); void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size, unsigned long fb2_size); void __init tegra_protected_aperture_init(unsigned long aperture); +void tegra_move_framebuffer(unsigned long to, unsigned long from, + unsigned long size); extern unsigned long tegra_bootloader_fb_start; extern unsigned long tegra_bootloader_fb_size; diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 28b1e9ae7396..09fdecfc2456 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -144,6 +145,58 @@ void __init tegra_protected_aperture_init(unsigned long aperture) #endif } +/* + * Due to conflicting restrictions on the placement of the framebuffer, + * the bootloader is likely to leave the framebuffer pointed at a location + * in memory that is outside the grhost aperture. This function will move + * the framebuffer contents from a physical address that is anywher (lowmem, + * highmem, or outside the memory map) to a physical address that is outside + * the memory map. + */ +void tegra_move_framebuffer(unsigned long to, unsigned long from, + unsigned long size) +{ + struct page *page; + void __iomem *to_io; + void *from_virt; + unsigned long i; + + BUG_ON(PAGE_ALIGN((unsigned long)to) != (unsigned long)to); + BUG_ON(PAGE_ALIGN(from) != from); + BUG_ON(PAGE_ALIGN(size) != size); + + to_io = ioremap(to, size); + if (!to_io) { + pr_err("%s: Failed to map target framebuffer\n", __func__); + return; + } + + pr_info("%s: %08lx %08lx %08lx %p", __func__, to, from, size, to_io); + + if (pfn_valid(page_to_pfn(phys_to_page(from)))) { + for (i = 0 ; i < size; i += PAGE_SIZE) { + page = phys_to_page(from + i); + from_virt = kmap(page); + memcpy_toio(to_io + i, from_virt, PAGE_SIZE); + kunmap(page); + } + } else { + void __iomem *from_io = ioremap(from, size); + if (!from_io) { + pr_err("%s: Failed to map source framebuffer\n", + __func__); + goto out; + } + + for (i = 0; i < size; i+= 4) + writel(readl(from_io + i), to_io + i); + + iounmap(from_io); + } +out: + iounmap(to_io); +} + void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size, unsigned long fb2_size) {