#include <linux/slab.h>
#include <linux/init.h>
#include <linux/fb.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
#include <asm/hardware.h>
#include <asm/io.h>
printk("acornfb: freed %dK memory\n", mb_freed);
}
+static struct device acornfb_device = {
+ .bus_id = "acornfb",
+ .coherent_dma_mask = 0xffffffff,
+};
+
int __init
acornfb_init(void)
{
acornfb_init_fbinfo();
+ current_par.dev = &acornfb_device;
+
if (current_par.montype == -1)
current_par.montype = acornfb_detect_monitortype();
#if defined(HAS_VIDC20)
if (!current_par.using_vram) {
+ dma_addr_t handle;
+ void *base;
+
/*
* RiscPC needs to allocate the DRAM memory
* for the framebuffer if we are not using
- * VRAM. Archimedes/A5000 machines use a
- * fixed address for their framebuffers.
+ * VRAM.
*/
- unsigned long page, top, base;
- int order = get_order(size);
-
- base = __get_free_pages(GFP_KERNEL, order);
- if (base == 0) {
+ base = dma_alloc_writecombine(current_par.dev, size, &handle,
+ GFP_KERNEL);
+ if (base == NULL) {
printk(KERN_ERR "acornfb: unable to allocate screen "
"memory\n");
return -ENOMEM;
}
- top = base + (PAGE_SIZE << order);
-
- /* Mark the framebuffer pages as reserved so mmap will work. */
- for (page = base; page < PAGE_ALIGN(base + size); page += PAGE_SIZE)
- SetPageReserved(virt_to_page(page));
- /* Hand back any excess pages that we allocated. */
- for (page = base + size; page < top; page += PAGE_SIZE)
- free_page(page);
- fb_info.screen_base = (char *)base;
- fb_info.fix.smem_start = virt_to_phys(fb_info.screen_base);
+ fb_info.screen_base = base;
+ fb_info.fix.smem_start = handle;
}
#endif
#if defined(HAS_VIDC)
/*
- * Free unused pages
+ * Archimedes/A5000 machines use a fixed address for their
+ * framebuffers. Free unused pages
*/
free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE);
#endif
* of the framebuffer.
*/
fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
- fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,
- &fbi->map_dma, PTE_BUFFERABLE);
+ fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
+ &fbi->map_dma, GFP_KERNEL);
if (fbi->map_cpu) {
fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE;
fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
+ /*
+ * FIXME: this is actually the wrong thing to place in
+ * smem_start. But fbdev suffers from the problem that
+ * it needs an API which doesn't exist (in this case,
+ * dma_writecombine_mmap)
+ */
fbi->fb.fix.smem_start = fbi->screen_dma;
}
};
-static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
+static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
{
struct sa1100fb_mach_info *inf;
struct sa1100fb_info *fbi;
return NULL;
memset(fbi, 0, sizeof(struct sa1100fb_info));
+ fbi->dev = dev;
strcpy(fbi->fb.fix.id, SA1100_NAME);
if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
return -EBUSY;
- fbi = sa1100fb_init_fbinfo();
+ fbi = sa1100fb_init_fbinfo(dev);
ret = -ENOMEM;
if (!fbi)
goto failed;