* Tomi Valkeinen <tomi.valkeinen@xxxxxxxxx> [090805 17:19]: > Add a Video RAM manager for OMAP 2 and 3 platforms. VRAM manager is used > to allocate large continuous blocks of SDRAM or SRAM. The features VRAM > manager has that are missing from dma_alloc_* functions are: > > - Support for OMAP2's SRAM > - Allocate without ioremapping > - Allocate at defined physical addresses > - Allows larger VRAM area and larger allocations > > The upcoming DSS2 uses VRAM manager. > > VRAM area size can be defined in kernel config, board file or with > kernel boot parameters. Board file definition overrides kernel config, > and boot parameter overrides kernel config and board file. > > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@xxxxxxxxx> > --- > arch/arm/mach-omap2/io.c | 2 + > arch/arm/plat-omap/Kconfig | 3 + > arch/arm/plat-omap/Makefile | 1 + > arch/arm/plat-omap/include/mach/vram.h | 63 +++ > arch/arm/plat-omap/sram.c | 8 + > arch/arm/plat-omap/vram.c | 655 ++++++++++++++++++++++++++++++++ > 6 files changed, 732 insertions(+), 0 deletions(-) > create mode 100644 arch/arm/plat-omap/include/mach/vram.h > create mode 100644 arch/arm/plat-omap/vram.c Can you place vram.c under drivers/video/omap? > > diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c > index 7a54e12..e37f736 100644 > --- a/arch/arm/mach-omap2/io.c > +++ b/arch/arm/mach-omap2/io.c > @@ -32,6 +32,7 @@ > #include <mach/sram.h> > #include <mach/sdrc.h> > #include <mach/gpmc.h> > +#include <mach/vram.h> > > #ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdev is ready */ > #include "clock.h" > @@ -240,6 +241,7 @@ void __init omap2_map_common_io(void) > omap2_check_revision(); > omap_sram_init(); > omapfb_reserve_sdram(); > + omap_vram_reserve_sdram(); > } > > /* > diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig > index efe85d0..ca06037 100644 > --- a/arch/arm/plat-omap/Kconfig > +++ b/arch/arm/plat-omap/Kconfig > @@ -183,6 +183,9 @@ config OMAP_SERIAL_WAKE > to data on the serial RX line. This allows you to wake the > system from serial console. > > +config OMAP2_VRAM > + bool > + > endmenu > > endif > diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile > index a832795..0472bbe 100644 > --- a/arch/arm/plat-omap/Makefile > +++ b/arch/arm/plat-omap/Makefile > @@ -25,3 +25,4 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y) > # OMAP mailbox framework > obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o > > +obj-$(CONFIG_OMAP2_VRAM) += vram.o > diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h > new file mode 100644 > index 0000000..fe72f81 > --- /dev/null > +++ b/arch/arm/plat-omap/include/mach/vram.h > @@ -0,0 +1,63 @@ > +/* > + * VRAM manager for OMAP > + * > + * Copyright (C) 2009 Nokia Corporation > + * Author: Tomi Valkeinen <tomi.valkeinen@xxxxxxxxx> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, but > + * WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program; if not, write to the Free Software Foundation, Inc., > + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. > + */ > + > +#ifndef __OMAP_VRAM_H__ > +#define __OMAP_VRAM_H__ > + > +#include <linux/autoconf.h> > +#include <linux/types.h> > + > +#define OMAP_VRAM_MEMTYPE_SDRAM 0 > +#define OMAP_VRAM_MEMTYPE_SRAM 1 > +#define OMAP_VRAM_MEMTYPE_MAX 1 > + > +extern int omap_vram_add_region(unsigned long paddr, size_t size); > +extern int omap_vram_free(unsigned long paddr, size_t size); > +extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr); > +extern int omap_vram_reserve(unsigned long paddr, size_t size); > +extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram, > + unsigned long *largest_free_block); > + > +#ifdef CONFIG_OMAP2_VRAM > +extern void omap_vram_set_sdram_vram(u32 size, u32 start); > +extern void omap_vram_set_sram_vram(u32 size, u32 start); > + > +extern void omap_vram_reserve_sdram(void); > +extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, > + unsigned long sram_vstart, > + unsigned long sram_size, > + unsigned long pstart_avail, > + unsigned long size_avail); > +#else > +static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { } > +static inline void omap_vram_set_sram_vram(u32 size, u32 start) { } > + > +static inline void omap_vram_reserve_sdram(void) { } > +static inline unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, > + unsigned long sram_vstart, > + unsigned long sram_size, > + unsigned long pstart_avail, > + unsigned long size_avail) > +{ > + return 0; > +} > +#endif > + > +#endif > diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c > index 4ea7380..944bf69 100644 > --- a/arch/arm/plat-omap/sram.c > +++ b/arch/arm/plat-omap/sram.c > @@ -28,6 +28,7 @@ > #include <mach/sram.h> > #include <mach/board.h> > #include <mach/cpu.h> > +#include <mach/vram.h> > > #include <mach/control.h> > > @@ -185,6 +186,13 @@ void __init omap_detect_sram(void) > omap_sram_start + SRAM_BOOTLOADER_SZ, > omap_sram_size - SRAM_BOOTLOADER_SZ); > omap_sram_size -= reserved; > + > + reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base, > + omap_sram_size, > + omap_sram_start + SRAM_BOOTLOADER_SZ, > + omap_sram_size - SRAM_BOOTLOADER_SZ); > + omap_sram_size -= reserved; > + > omap_sram_ceil = omap_sram_base + omap_sram_size; > } > > diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c > new file mode 100644 > index 0000000..634ce23 > --- /dev/null > +++ b/arch/arm/plat-omap/vram.c > @@ -0,0 +1,655 @@ > +/* > + * VRAM manager for OMAP > + * > + * Copyright (C) 2009 Nokia Corporation > + * Author: Tomi Valkeinen <tomi.valkeinen@xxxxxxxxx> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, but > + * WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program; if not, write to the Free Software Foundation, Inc., > + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. > + */ > + > +/*#define DEBUG*/ > + > +#include <linux/kernel.h> > +#include <linux/mm.h> > +#include <linux/list.h> > +#include <linux/seq_file.h> > +#include <linux/bootmem.h> > +#include <linux/completion.h> > +#include <linux/debugfs.h> > +#include <linux/jiffies.h> > +#include <linux/module.h> > + > +#include <asm/setup.h> > + > +#include <mach/sram.h> > +#include <mach/vram.h> > +#include <mach/dma.h> > + > +#ifdef DEBUG > +#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__) > +#else > +#define DBG(format, ...) > +#endif > + > +#define OMAP2_SRAM_START 0x40200000 > +/* Maximum size, in reality this is smaller if SRAM is partially locked. */ > +#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */ > + > +/* postponed regions are used to temporarily store region information at boot > + * time when we cannot yet allocate the region list */ > +#define MAX_POSTPONED_REGIONS 10 > + > +static bool vram_initialized; > +static int postponed_cnt; > +static struct { > + unsigned long paddr; > + size_t size; > +} postponed_regions[MAX_POSTPONED_REGIONS]; > + > +struct vram_alloc { > + struct list_head list; > + unsigned long paddr; > + unsigned pages; > +}; > + > +struct vram_region { > + struct list_head list; > + struct list_head alloc_list; > + unsigned long paddr; > + unsigned pages; > +}; > + > +static DEFINE_MUTEX(region_mutex); > +static LIST_HEAD(region_list); > + > +static inline int region_mem_type(unsigned long paddr) > +{ > + if (paddr >= OMAP2_SRAM_START && > + paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE) > + return OMAP_VRAM_MEMTYPE_SRAM; > + else > + return OMAP_VRAM_MEMTYPE_SDRAM; > +} > + > +static struct vram_region *omap_vram_create_region(unsigned long paddr, > + unsigned pages) > +{ > + struct vram_region *rm; > + > + rm = kzalloc(sizeof(*rm), GFP_KERNEL); > + > + if (rm) { > + INIT_LIST_HEAD(&rm->alloc_list); > + rm->paddr = paddr; > + rm->pages = pages; > + } > + > + return rm; > +} > + > +#if 0 > +static void omap_vram_free_region(struct vram_region *vr) > +{ > + list_del(&vr->list); > + kfree(vr); > +} > +#endif > + > +static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr, > + unsigned long paddr, unsigned pages) > +{ > + struct vram_alloc *va; > + struct vram_alloc *new; > + > + new = kzalloc(sizeof(*va), GFP_KERNEL); > + > + if (!new) > + return NULL; > + > + new->paddr = paddr; > + new->pages = pages; > + > + list_for_each_entry(va, &vr->alloc_list, list) { > + if (va->paddr > new->paddr) > + break; > + } > + > + list_add_tail(&new->list, &va->list); > + > + return new; > +} > + > +static void omap_vram_free_allocation(struct vram_alloc *va) > +{ > + list_del(&va->list); > + kfree(va); > +} > + > +int omap_vram_add_region(unsigned long paddr, size_t size) > +{ > + struct vram_region *rm; > + unsigned pages; > + > + if (vram_initialized) { > + DBG("adding region paddr %08lx size %d\n", > + paddr, size); > + > + size &= PAGE_MASK; > + pages = size >> PAGE_SHIFT; > + > + rm = omap_vram_create_region(paddr, pages); > + if (rm == NULL) > + return -ENOMEM; > + > + list_add(&rm->list, ®ion_list); > + } else { > + if (postponed_cnt == MAX_POSTPONED_REGIONS) > + return -ENOMEM; > + > + postponed_regions[postponed_cnt].paddr = paddr; > + postponed_regions[postponed_cnt].size = size; > + > + ++postponed_cnt; > + } > + return 0; > +} > + > +int omap_vram_free(unsigned long paddr, size_t size) > +{ > + struct vram_region *rm; > + struct vram_alloc *alloc; > + unsigned start, end; > + > + DBG("free mem paddr %08lx size %d\n", paddr, size); > + > + size = PAGE_ALIGN(size); > + > + mutex_lock(®ion_mutex); > + > + list_for_each_entry(rm, ®ion_list, list) { > + list_for_each_entry(alloc, &rm->alloc_list, list) { > + start = alloc->paddr; > + end = alloc->paddr + (alloc->pages >> PAGE_SHIFT); > + > + if (start >= paddr && end < paddr + size) > + goto found; > + } > + } > + > + mutex_unlock(®ion_mutex); > + return -EINVAL; > + > +found: > + omap_vram_free_allocation(alloc); > + > + mutex_unlock(®ion_mutex); > + return 0; > +} > +EXPORT_SYMBOL(omap_vram_free); > + > +static int _omap_vram_reserve(unsigned long paddr, unsigned pages) > +{ > + struct vram_region *rm; > + struct vram_alloc *alloc; > + size_t size; > + > + size = pages << PAGE_SHIFT; > + > + list_for_each_entry(rm, ®ion_list, list) { > + unsigned long start, end; > + > + DBG("checking region %lx %d\n", rm->paddr, rm->pages); > + > + if (region_mem_type(rm->paddr) != region_mem_type(paddr)) > + continue; > + > + start = rm->paddr; > + end = start + (rm->pages << PAGE_SHIFT) - 1; > + if (start > paddr || end < paddr + size - 1) > + continue; > + > + DBG("block ok, checking allocs\n"); > + > + list_for_each_entry(alloc, &rm->alloc_list, list) { > + end = alloc->paddr - 1; > + > + if (start <= paddr && end >= paddr + size - 1) > + goto found; > + > + start = alloc->paddr + (alloc->pages << PAGE_SHIFT); > + } > + > + end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1; > + > + if (!(start <= paddr && end >= paddr + size - 1)) > + continue; > +found: > + DBG("found area start %lx, end %lx\n", start, end); > + > + if (omap_vram_create_allocation(rm, paddr, pages) == NULL) > + return -ENOMEM; > + > + return 0; > + } > + > + return -ENOMEM; > +} > + > +int omap_vram_reserve(unsigned long paddr, size_t size) > +{ > + unsigned pages; > + int r; > + > + DBG("reserve mem paddr %08lx size %d\n", paddr, size); > + > + size = PAGE_ALIGN(size); > + pages = size >> PAGE_SHIFT; > + > + mutex_lock(®ion_mutex); > + > + r = _omap_vram_reserve(paddr, pages); > + > + mutex_unlock(®ion_mutex); > + > + return r; > +} > +EXPORT_SYMBOL(omap_vram_reserve); > + > +static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data) > +{ > + struct completion *compl = data; > + complete(compl); > +} > + > +static int _omap_vram_clear(u32 paddr, unsigned pages) > +{ > + struct completion compl; > + unsigned elem_count; > + unsigned frame_count; > + int r; > + int lch; > + > + init_completion(&compl); > + > + r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA", > + _omap_vram_dma_cb, > + &compl, &lch); > + if (r) { > + pr_err("VRAM: request_dma failed for memory clear\n"); > + return -EBUSY; > + } > + > + elem_count = pages * PAGE_SIZE / 4; > + frame_count = 1; > + > + omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32, > + elem_count, frame_count, > + OMAP_DMA_SYNC_ELEMENT, > + 0, 0); > + > + omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC, > + paddr, 0, 0); > + > + omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000); > + > + omap_start_dma(lch); > + > + if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) { > + omap_stop_dma(lch); > + pr_err("VRAM: dma timeout while clearing memory\n"); > + r = -EIO; > + goto err; > + } > + > + r = 0; > +err: > + omap_free_dma(lch); > + > + return r; > +} > + > +static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr) > +{ > + struct vram_region *rm; > + struct vram_alloc *alloc; > + > + list_for_each_entry(rm, ®ion_list, list) { > + unsigned long start, end; > + > + DBG("checking region %lx %d\n", rm->paddr, rm->pages); > + > + if (region_mem_type(rm->paddr) != mtype) > + continue; > + > + start = rm->paddr; > + > + list_for_each_entry(alloc, &rm->alloc_list, list) { > + end = alloc->paddr; > + > + if (end - start >= pages << PAGE_SHIFT) > + goto found; > + > + start = alloc->paddr + (alloc->pages << PAGE_SHIFT); > + } > + > + end = rm->paddr + (rm->pages << PAGE_SHIFT); > +found: > + if (end - start < pages << PAGE_SHIFT) > + continue; > + > + DBG("found %lx, end %lx\n", start, end); > + > + alloc = omap_vram_create_allocation(rm, start, pages); > + if (alloc == NULL) > + return -ENOMEM; > + > + *paddr = start; > + > + _omap_vram_clear(start, pages); > + > + return 0; > + } > + > + return -ENOMEM; > +} > + > +int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr) > +{ > + unsigned pages; > + int r; > + > + BUG_ON(mtype > OMAP_VRAM_MEMTYPE_MAX || !size); > + > + DBG("alloc mem type %d size %d\n", mtype, size); > + > + size = PAGE_ALIGN(size); > + pages = size >> PAGE_SHIFT; > + > + mutex_lock(®ion_mutex); > + > + r = _omap_vram_alloc(mtype, pages, paddr); > + > + mutex_unlock(®ion_mutex); > + > + return r; > +} > +EXPORT_SYMBOL(omap_vram_alloc); > + > +void omap_vram_get_info(unsigned long *vram, > + unsigned long *free_vram, > + unsigned long *largest_free_block) > +{ > + struct vram_region *vr; > + struct vram_alloc *va; > + > + *vram = 0; > + *free_vram = 0; > + *largest_free_block = 0; > + > + mutex_lock(®ion_mutex); > + > + list_for_each_entry(vr, ®ion_list, list) { > + unsigned free; > + unsigned long pa; > + > + pa = vr->paddr; > + *vram += vr->pages << PAGE_SHIFT; > + > + list_for_each_entry(va, &vr->alloc_list, list) { > + free = va->paddr - pa; > + *free_vram += free; > + if (free > *largest_free_block) > + *largest_free_block = free; > + pa = va->paddr + (va->pages << PAGE_SHIFT); > + } > + > + free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa; > + *free_vram += free; > + if (free > *largest_free_block) > + *largest_free_block = free; > + } > + > + mutex_unlock(®ion_mutex); > +} > +EXPORT_SYMBOL(omap_vram_get_info); > + > +#if defined(CONFIG_DEBUG_FS) > +static int vram_debug_show(struct seq_file *s, void *unused) > +{ > + struct vram_region *vr; > + struct vram_alloc *va; > + unsigned size; > + > + mutex_lock(®ion_mutex); > + > + list_for_each_entry(vr, ®ion_list, list) { > + size = vr->pages << PAGE_SHIFT; > + seq_printf(s, "%08lx-%08lx (%d bytes)\n", > + vr->paddr, vr->paddr + size - 1, > + size); > + > + list_for_each_entry(va, &vr->alloc_list, list) { > + size = va->pages << PAGE_SHIFT; > + seq_printf(s, " %08lx-%08lx (%d bytes)\n", > + va->paddr, va->paddr + size - 1, > + size); > + } > + } > + > + mutex_unlock(®ion_mutex); > + > + return 0; > +} > + > +static int vram_debug_open(struct inode *inode, struct file *file) > +{ > + return single_open(file, vram_debug_show, inode->i_private); > +} > + > +static const struct file_operations vram_debug_fops = { > + .open = vram_debug_open, > + .read = seq_read, > + .llseek = seq_lseek, > + .release = single_release, > +}; > + > +static int __init omap_vram_create_debugfs(void) > +{ > + struct dentry *d; > + > + d = debugfs_create_file("vram", S_IRUGO, NULL, > + NULL, &vram_debug_fops); > + if (IS_ERR(d)) > + return PTR_ERR(d); > + > + return 0; > +} > +#endif > + > +static __init int omap_vram_init(void) > +{ > + int i; > + > + vram_initialized = 1; > + > + for (i = 0; i < postponed_cnt; i++) > + omap_vram_add_region(postponed_regions[i].paddr, > + postponed_regions[i].size); > + > +#ifdef CONFIG_DEBUG_FS > + if (omap_vram_create_debugfs()) > + pr_err("VRAM: Failed to create debugfs file\n"); > +#endif > + > + return 0; > +} > + > +arch_initcall(omap_vram_init); > + > +/* boottime vram alloc stuff */ > + > +/* set from board file */ > +static u32 omap_vram_sram_start __initdata; > +static u32 omap_vram_sram_size __initdata; > + > +/* set from board file */ > +static u32 omap_vram_sdram_start __initdata; > +static u32 omap_vram_sdram_size __initdata; > + > +/* set from kernel cmdline */ > +static u32 omap_vram_def_sdram_size __initdata; > +static u32 omap_vram_def_sdram_start __initdata; > + > +static void __init omap_vram_early_vram(char **p) > +{ > + omap_vram_def_sdram_size = memparse(*p, p); > + if (**p == ',') > + omap_vram_def_sdram_start = simple_strtoul((*p) + 1, p, 16); > +} > +__early_param("vram=", omap_vram_early_vram); > + > +/* > + * Called from map_io. We need to call to this early enough so that we > + * can reserve the fixed SDRAM regions before VM could get hold of them. > + */ > +void __init omap_vram_reserve_sdram(void) > +{ > + struct bootmem_data *bdata; > + unsigned long sdram_start, sdram_size; > + u32 paddr; > + u32 size = 0; > + > + /* cmdline arg overrides the board file definition */ > + if (omap_vram_def_sdram_size) { > + size = omap_vram_def_sdram_size; > + paddr = omap_vram_def_sdram_start; > + } > + > + if (!size) { > + size = omap_vram_sdram_size; > + paddr = omap_vram_sdram_start; > + } > + > +#ifdef CONFIG_OMAP2_VRAM_SIZE > + if (!size) { > + size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024; > + paddr = 0; > + } > +#endif > + > + if (!size) > + return; > + > + size = PAGE_ALIGN(size); > + > + bdata = NODE_DATA(0)->bdata; > + sdram_start = bdata->node_min_pfn << PAGE_SHIFT; > + sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; > + > + if (paddr) { > + if ((paddr & ~PAGE_MASK) || paddr < sdram_start || > + paddr + size > sdram_start + sdram_size) { > + pr_err("Illegal SDRAM region for VRAM\n"); > + return; > + } > + > + if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) { > + pr_err("FB: failed to reserve VRAM\n"); > + return; > + } > + } else { > + if (size > sdram_size) { > + pr_err("Illegal SDRAM size for VRAM\n"); > + return; > + } > + > + paddr = virt_to_phys(alloc_bootmem_pages(size)); > + BUG_ON(paddr & ~PAGE_MASK); > + } > + > + omap_vram_add_region(paddr, size); > + > + pr_info("Reserving %u bytes SDRAM for VRAM\n", size); > +} > + > +/* > + * Called at sram init time, before anything is pushed to the SRAM stack. > + * Because of the stack scheme, we will allocate everything from the > + * start of the lowest address region to the end of SRAM. This will also > + * include padding for page alignment and possible holes between regions. > + * > + * As opposed to the SDRAM case, we'll also do any dynamic allocations at > + * this point, since the driver built as a module would have problem with > + * freeing / reallocating the regions. > + */ > +unsigned long __init omap_vram_reserve_sram(unsigned long sram_pstart, > + unsigned long sram_vstart, > + unsigned long sram_size, > + unsigned long pstart_avail, > + unsigned long size_avail) > +{ > + unsigned long pend_avail; > + unsigned long reserved; > + u32 paddr; > + u32 size; > + > + paddr = omap_vram_sram_start; > + size = omap_vram_sram_size; > + > + if (!size) > + return 0; > + > + reserved = 0; > + pend_avail = pstart_avail + size_avail; > + > + if (!paddr) { > + /* Dynamic allocation */ > + if ((size_avail & PAGE_MASK) < size) { > + pr_err("Not enough SRAM for VRAM\n"); > + return 0; > + } > + size_avail = (size_avail - size) & PAGE_MASK; > + paddr = pstart_avail + size_avail; > + } > + > + if (paddr < sram_pstart || > + paddr + size > sram_pstart + sram_size) { > + pr_err("Illegal SRAM region for VRAM\n"); > + return 0; > + } > + > + /* Reserve everything above the start of the region. */ > + if (pend_avail - paddr > reserved) > + reserved = pend_avail - paddr; > + size_avail = pend_avail - reserved - pstart_avail; > + > + omap_vram_add_region(paddr, size); > + > + if (reserved) > + pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved); > + > + return reserved; > +} > + > +void __init omap_vram_set_sdram_vram(u32 size, u32 start) > +{ > + omap_vram_sdram_start = start; > + omap_vram_sdram_size = size; > +} > + > +void __init omap_vram_set_sram_vram(u32 size, u32 start) > +{ > + omap_vram_sram_start = start; > + omap_vram_sram_size = size; > +} > -- > 1.6.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html