]> git.hungrycats.org Git - linux/commitdiff
[ARM] Convert ARM video drivers to use (ARM extended) DMA API.
authorRussell King <rmk@flint.arm.linux.org.uk>
Mon, 29 Mar 2004 18:38:03 +0000 (19:38 +0100)
committerRussell King <rmk@flint.arm.linux.org.uk>
Mon, 29 Mar 2004 18:38:03 +0000 (19:38 +0100)
drivers/video/acornfb.c
drivers/video/acornfb.h
drivers/video/sa1100fb.c
drivers/video/sa1100fb.h

index fbe8006c6129c7d68f85e65a4d0641af1b661a04..24ab489748473718a61b082b9eafc00528740a6f 100644 (file)
@@ -29,6 +29,8 @@
 #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>
@@ -1254,6 +1256,11 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end)
        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)
 {
@@ -1263,6 +1270,8 @@ acornfb_init(void)
 
        acornfb_init_fbinfo();
 
+       current_par.dev = &acornfb_device;
+
        if (current_par.montype == -1)
                current_par.montype = acornfb_detect_monitortype();
 
@@ -1323,37 +1332,30 @@ acornfb_init(void)
 
 #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
index 060d8787960a788df9ad2849e3c6350e24576e6c..fb2a7fffe5063f6a0a96f0640d9cab77b846472d 100644 (file)
@@ -47,6 +47,7 @@ union palette {
 };
 
 struct acornfb_par {
+       struct device   *dev;
        unsigned long   screen_end;
        unsigned int    dram_size;
        unsigned int    vram_half_sam;
index 488d7bb9aae8bf614c9dd9a5727171c0b91662d7..81edff0293afa3144c1ca173a9582399a07e3538 100644 (file)
@@ -1595,12 +1595,18 @@ static int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
         * 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;
        }
 
@@ -1613,7 +1619,7 @@ static struct fb_monspecs monspecs __initdata = {
 };
 
 
-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;
@@ -1624,6 +1630,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
                return NULL;
 
        memset(fbi, 0, sizeof(struct sa1100fb_info));
+       fbi->dev = dev;
 
        strcpy(fbi->fb.fix.id, SA1100_NAME);
 
@@ -1703,7 +1710,7 @@ static int __init sa1100fb_probe(struct device *dev)
        if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
                return -EBUSY;
 
-       fbi = sa1100fb_init_fbinfo();
+       fbi = sa1100fb_init_fbinfo(dev);
        ret = -ENOMEM;
        if (!fbi)
                goto failed;
index f60a32fac414fb9110c3bdab4f6c336b63dba1a4..0b07f6ae3367c286611695c9c7950c9afd2f0d56 100644 (file)
@@ -63,6 +63,7 @@ struct sa1100fb_lcd_reg {
 
 struct sa1100fb_info {
        struct fb_info          fb;
+       struct device           *dev;
        struct sa1100fb_rgb     *rgb[NR_RGB];
 
        u_int                   max_bpp;