[POWERPC] XilinxFB: Allow fixed framebuffer base address
authorGrant Likely <grant.likely@secretlab.ca>
Wed, 10 Oct 2007 18:31:56 +0000 (04:31 +1000)
committerPaul Mackerras <paulus@samba.org>
Fri, 12 Oct 2007 04:05:17 +0000 (14:05 +1000)
Allow a fixed framebuffer address to be assigned to the framebuffer device
instead of allocating the framebuffer from the consistent memory pool.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Paul Mackerras <paulus@samba.org>
drivers/video/xilinxfb.c
include/linux/xilinxfb.h

index c617412..6ef99b2 100644 (file)
@@ -117,6 +117,7 @@ struct xilinxfb_drvdata {
 
        void            *fb_virt;       /* virt. address of the frame buffer */
        dma_addr_t      fb_phys;        /* phys. address of the frame buffer */
+       int             fb_alloced;     /* Flag, was the fb memory alloced? */
 
        u32             reg_ctrl_default;
 
@@ -235,8 +236,15 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr,
        }
 
        /* Allocate the framebuffer memory */
-       drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(fbsize),
-                               &drvdata->fb_phys, GFP_KERNEL);
+       if (pdata->fb_phys) {
+               drvdata->fb_phys = pdata->fb_phys;
+               drvdata->fb_virt = ioremap(pdata->fb_phys, fbsize);
+       } else {
+               drvdata->fb_alloced = 1;
+               drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(fbsize),
+                                       &drvdata->fb_phys, GFP_KERNEL);
+       }
+
        if (!drvdata->fb_virt) {
                dev_err(dev, "Could not allocate frame buffer memory\n");
                rc = -ENOMEM;
@@ -300,8 +308,9 @@ err_regfb:
        fb_dealloc_cmap(&drvdata->info.cmap);
 
 err_cmap:
-       dma_free_coherent(dev, PAGE_ALIGN(fbsize), drvdata->fb_virt,
-               drvdata->fb_phys);
+       if (drvdata->fb_alloced)
+               dma_free_coherent(dev, PAGE_ALIGN(fbsize), drvdata->fb_virt,
+                       drvdata->fb_phys);
        /* Turn off the display */
        xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
 
@@ -330,8 +339,9 @@ static int xilinxfb_release(struct device *dev)
 
        fb_dealloc_cmap(&drvdata->info.cmap);
 
-       dma_free_coherent(dev, PAGE_ALIGN(drvdata->info.fix.smem_len),
-                         drvdata->fb_virt, drvdata->fb_phys);
+       if (drvdata->fb_alloced)
+               dma_free_coherent(dev, PAGE_ALIGN(drvdata->info.fix.smem_len),
+                                 drvdata->fb_virt, drvdata->fb_phys);
 
        /* Turn off the display */
        xilinx_fb_out_be32(drvdata, REG_CTRL, 0);
index 199a1ee..f2463f5 100644 (file)
@@ -20,6 +20,11 @@ struct xilinxfb_platform_data {
        u32 screen_width_mm;
        u32 xres, yres;         /* resolution of screen in pixels */
        u32 xvirt, yvirt;       /* resolution of memory buffer */
+
+       /* Physical address of framebuffer memory; If non-zero, driver
+        * will use provided memory address instead of allocating one from
+        * the consistent pool. */
+       u32 fb_phys;
 };
 
 #endif  /* __XILINXFB_H__ */