goldfish: R.I.P.
[openwrt.git] / target / linux / s3c24xx / files-2.6.30 / drivers / mfd / glamo / glamo-fb.c
index 8d1a5ed..7bb2201 100644 (file)
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/init.h>
-#include <linux/vmalloc.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/wait.h>
 #include <linux/platform_device.h>
-#include <linux/clk.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
-#include <linux/uaccess.h>
+#include <linux/mfd/glamo.h>
 
 #include <asm/div64.h>
 
 #include "glamo-regs.h"
 #include "glamo-core.h"
 
-#ifndef DEBUG
-#define GLAMO_LOG(...)
-#else
-#define GLAMO_LOG(...) \
-do { \
-       printk(KERN_DEBUG "in %s:%s:%d", __FILE__, __func__, __LINE__); \
-       printk(KERN_DEBUG __VA_ARGS__); \
-} while (0);
-#endif
-
-
-#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
+static void glamofb_program_mode(struct glamofb_handle* glamo);
 
 struct glamofb_handle {
+       struct glamo_core *core;
        struct fb_info *fb;
        struct device *dev;
        struct resource *reg;
        struct resource *fb_res;
        char __iomem *base;
-       struct glamofb_platform_data *mach_info;
+       struct glamo_fb_platform_data *mach_info;
        char __iomem *cursor_addr;
        int cursor_on;
        u_int32_t pseudo_pal[16];
        spinlock_t lock_cmd;
-       int angle;      /* Current rotation angle */
        int blank_mode;
+       int mode_set; /* 0 if the current display mode hasn't been set on the glamo */
+       int output_enabled; /* 0 if the video output is disabled */
 };
 
-/* 'sibling' spi device for lcm init */
-static struct platform_device glamo_spi_dev = {
-       .name           = "glamo-lcm-spi",
-};
+static void glamo_output_enable(struct glamofb_handle *gfb) {
+       struct glamo_core *gcore = gfb->core;
+
+       if (gfb->output_enabled)
+               return;
+
+       /* enable the pixel clock if off */
+       glamo_engine_clkreg_set(gcore,
+               GLAMO_ENGINE_LCD,
+               GLAMO_CLOCK_LCD_EN_DCLK,
+               GLAMO_CLOCK_LCD_EN_DCLK);
+
+       gfb->output_enabled = 1;
+       if (!gfb->mode_set)
+               glamofb_program_mode(gfb);
+}
+
+static void glamo_output_disable(struct glamofb_handle *gfb) {
+       struct glamo_core *gcore = gfb->core;
+
+       if (!gfb->output_enabled)
+               return;
+
+       /* enable the pixel clock if off */
+       glamo_engine_clkreg_set(gcore,
+               GLAMO_ENGINE_LCD,
+               GLAMO_CLOCK_LCD_EN_DCLK,
+               0);
+
+       gfb->output_enabled = 0;
+}
 
 
 static int reg_read(struct glamofb_handle *glamo,
@@ -129,8 +139,6 @@ static struct glamo_script glamo_regs[] = {
        /* The following values assume 640*480@16bpp */
        { GLAMO_REG_LCD_A_BASE1, 0x0000 }, /* display A base address 15:0 */
        { GLAMO_REG_LCD_A_BASE2, 0x0000 }, /* display A base address 22:16 */
-       { GLAMO_REG_LCD_B_BASE1, 0x6000 }, /* display B base address 15:0 */
-       { GLAMO_REG_LCD_B_BASE2, 0x0009 }, /* display B base address 22:16 */
        { GLAMO_REG_LCD_CURSOR_BASE1, 0xC000 }, /* cursor base address 15:0 */
        { GLAMO_REG_LCD_CURSOR_BASE2, 0x0012 }, /* cursor base address 22:16 */
        { GLAMO_REG_LCD_COMMAND2, 0x0000 }, /* display page A */
@@ -141,8 +149,8 @@ static int glamofb_run_script(struct glamofb_handle *glamo,
 {
        int i;
 
-       if (glamo->mach_info->glamo->suspending) {
-               dev_err(&glamo->mach_info->glamo->pdev->dev,
+       if (glamo->core->suspending) {
+               dev_err(&glamo->core->pdev->dev,
                                "IGNORING glamofb_run_script while "
                                                                 "suspended\n");
                return -EBUSY;
@@ -167,27 +175,18 @@ static int glamofb_check_var(struct fb_var_screeninfo *var,
 {
        struct glamofb_handle *glamo = info->par;
 
-       if (glamo->mach_info->glamo->suspending) {
-               dev_err(&glamo->mach_info->glamo->pdev->dev,
+       if (glamo->core->suspending) {
+               dev_err(&glamo->core->pdev->dev,
                                "IGNORING glamofb_check_var while "
                                                                 "suspended\n");
                return -EBUSY;
        }
 
-       if (var->yres > glamo->mach_info->yres.max)
-               var->yres = glamo->mach_info->yres.max;
-       else if (var->yres < glamo->mach_info->yres.min)
-               var->yres = glamo->mach_info->yres.min;
+       if (var->bits_per_pixel != 16)
+               var->bits_per_pixel = 16;
 
-       if (var->xres > glamo->mach_info->xres.max)
-               var->xres = glamo->mach_info->xres.max;
-       else if (var->xres < glamo->mach_info->xres.min)
-               var->xres = glamo->mach_info->xres.min;
-
-       if (var->bits_per_pixel > glamo->mach_info->bpp.max)
-               var->bits_per_pixel = glamo->mach_info->bpp.max;
-       else if (var->bits_per_pixel < glamo->mach_info->bpp.min)
-               var->bits_per_pixel = glamo->mach_info->bpp.min;
+       var->height = glamo->mach_info->height;
+       var->width = glamo->mach_info->width;
 
        /* FIXME: set rgb positions */
        switch (var->bits_per_pixel) {
@@ -259,39 +258,29 @@ static void reg_set_bit_mask(struct glamofb_handle *glamo,
 #define GLAMO_LCD_HV_RETR_DISP_START_MASK 0x03FF
 #define GLAMO_LCD_HV_RETR_DISP_END_MASK 0x03FF
 
-enum orientation {ORIENTATION_PORTRAIT, ORIENTATION_LANDSCAPE};
-
 /* the caller has to enxure lock_cmd is held and we are in cmd mode */
 static void __rotate_lcd(struct glamofb_handle *glamo, __u32 rotation)
 {
        int glamo_rot;
 
-       if (glamo->mach_info->glamo->suspending) {
-               dev_err(&glamo->mach_info->glamo->pdev->dev,
+       if (glamo->core->suspending) {
+               dev_err(&glamo->core->pdev->dev,
                                "IGNORING rotate_lcd while "
                                                                 "suspended\n");
                return;
        }
 
        switch (rotation) {
-       case FB_ROTATE_UR:
-               glamo_rot = GLAMO_LCD_ROT_MODE_0;
-               glamo->angle = 0;
-               break;
        case FB_ROTATE_CW:
                glamo_rot = GLAMO_LCD_ROT_MODE_90;
-               glamo->angle = 90;
                break;
        case FB_ROTATE_UD:
                glamo_rot = GLAMO_LCD_ROT_MODE_180;
-               glamo->angle = 180;
                break;
        case FB_ROTATE_CCW:
                glamo_rot = GLAMO_LCD_ROT_MODE_270;
-               glamo->angle = 270;
                break;
        default:
-               glamo->angle = 0;
                glamo_rot = GLAMO_LCD_ROT_MODE_0;
                break;
        }
@@ -307,194 +296,152 @@ static void __rotate_lcd(struct glamofb_handle *glamo, __u32 rotation)
                                 GLAMO_LCD_MODE1_ROTATE_EN : 0);
 }
 
-static enum orientation get_orientation(struct fb_var_screeninfo *var)
-{
-       if (var->xres <= var->yres)
-               return ORIENTATION_PORTRAIT;
-
-       return ORIENTATION_LANDSCAPE;
-}
-
-static int will_orientation_change(struct fb_var_screeninfo *var)
-{
-       enum orientation orient = get_orientation(var);
-
-       switch (orient) {
-       case ORIENTATION_LANDSCAPE:
-               if (var->rotate == FB_ROTATE_UR || var->rotate == FB_ROTATE_UD)
-                       return 1;
-               break;
-       case ORIENTATION_PORTRAIT:
-               if (var->rotate == FB_ROTATE_CW || var->rotate == FB_ROTATE_CCW)
-                       return 1;
-               break;
-       }
-       return 0;
-}
-
-static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
-                                         struct fb_var_screeninfo *var)
-{
-       int sync, bp, disp, fp, total, xres, yres, pitch;
-       int uninitialized_var(orientation_changing);
+static void glamofb_program_mode(struct glamofb_handle* gfb) {
+       int sync, bp, disp, fp, total;
        unsigned long flags;
+       struct glamo_core *gcore = gfb->core;
+       struct fb_var_screeninfo *var = &gfb->fb->var;
 
-       if (!glamo || !var)
-               return;
-
-       if (glamo->mach_info->glamo->suspending) {
-               dev_err(&glamo->mach_info->glamo->pdev->dev,
-                               "IGNORING glamofb_update_lcd_controller while "
-                                                                "suspended\n");
-               return;
-       }
+       dev_dbg(&gcore->pdev->dev,
+                         "glamofb_program_mode spin_lock_irqsave\n");
+       spin_lock_irqsave(&gfb->lock_cmd, flags);
 
-       dev_dbg(&glamo->mach_info->glamo->pdev->dev,
-                         "glamofb_update_lcd_controller spin_lock_irqsave\n");
-       spin_lock_irqsave(&glamo->lock_cmd, flags);
-
-       if (glamofb_cmd_mode(glamo, 1))
+       if (glamofb_cmd_mode(gfb, 1))
                goto out_unlock;
 
-/*     if (var->pixclock)
-               glamo_engine_reclock(glamo->mach_info->glamo,
+       if (var->pixclock)
+               glamo_engine_reclock(gcore,
                                     GLAMO_ENGINE_LCD,
-                                    var->pixclock);*/
-
-       xres = var->xres;
-       yres = var->yres;
-
-    orientation_changing = will_orientation_change(var);
-       /* Adjust the pitch according to new orientation to come. */
-       if (orientation_changing)
-               pitch = var->yres * var->bits_per_pixel / 8;
-       else
-               pitch = var->xres * var->bits_per_pixel / 8;
+                                    (1000000000UL / gfb->fb->var.pixclock) * 1000);
 
-       reg_set_bit_mask(glamo,
+       reg_set_bit_mask(gfb,
                         GLAMO_REG_LCD_WIDTH,
                         GLAMO_LCD_WIDTH_MASK,
-                        xres);
-       reg_set_bit_mask(glamo,
+                        var->xres);
+       reg_set_bit_mask(gfb,
                         GLAMO_REG_LCD_HEIGHT,
                         GLAMO_LCD_HEIGHT_MASK,
-                        yres);
-       reg_set_bit_mask(glamo,
+                        var->yres);
+       reg_set_bit_mask(gfb,
                         GLAMO_REG_LCD_PITCH,
                         GLAMO_LCD_PITCH_MASK,
-                        pitch);
+                        gfb->fb->fix.line_length);
 
        /* honour the rotation request */
-       __rotate_lcd(glamo, var->rotate);
-
-       if (orientation_changing) {
-               var->xres_virtual = yres;
-               var->xres = yres;
-               var->xres_virtual *= 2;
-               var->yres_virtual = xres;
-               var->yres = xres;
-       } else {
-               var->xres_virtual = xres;
-               var->yres_virtual = yres;
-               var->yres_virtual *= 2;
-       }
+       __rotate_lcd(gfb, var->rotate);
 
        /* update scannout timings */
        sync = 0;
        bp = sync + var->hsync_len;
        disp = bp + var->left_margin;
-       fp = disp + xres;
+       fp = disp + var->xres;
        total = fp + var->right_margin;
 
-       reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_TOTAL,
+       reg_set_bit_mask(gfb, GLAMO_REG_LCD_HORIZ_TOTAL,
                         GLAMO_LCD_HV_TOTAL_MASK, total);
-       reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_RETR_START,
+       reg_set_bit_mask(gfb, GLAMO_REG_LCD_HORIZ_RETR_START,
                         GLAMO_LCD_HV_RETR_START_MASK, sync);
-       reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_RETR_END,
+       reg_set_bit_mask(gfb, GLAMO_REG_LCD_HORIZ_RETR_END,
                         GLAMO_LCD_HV_RETR_END_MASK, bp);
-       reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_START,
+       reg_set_bit_mask(gfb, GLAMO_REG_LCD_HORIZ_DISP_START,
                          GLAMO_LCD_HV_RETR_DISP_START_MASK, disp);
-       reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_END,
+       reg_set_bit_mask(gfb, GLAMO_REG_LCD_HORIZ_DISP_END,
                         GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
 
        sync = 0;
        bp = sync + var->vsync_len;
        disp = bp + var->upper_margin;
-       fp = disp + yres;
+       fp = disp + var->yres;
        total = fp + var->lower_margin;
 
-       reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_TOTAL,
+       reg_set_bit_mask(gfb, GLAMO_REG_LCD_VERT_TOTAL,
                         GLAMO_LCD_HV_TOTAL_MASK, total);
-       reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_RETR_START,
+       reg_set_bit_mask(gfb, GLAMO_REG_LCD_VERT_RETR_START,
                          GLAMO_LCD_HV_RETR_START_MASK, sync);
-       reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_RETR_END,
+       reg_set_bit_mask(gfb, GLAMO_REG_LCD_VERT_RETR_END,
                         GLAMO_LCD_HV_RETR_END_MASK, bp);
-       reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_START,
+       reg_set_bit_mask(gfb, GLAMO_REG_LCD_VERT_DISP_START,
                         GLAMO_LCD_HV_RETR_DISP_START_MASK, disp);
-       reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_END,
+       reg_set_bit_mask(gfb, GLAMO_REG_LCD_VERT_DISP_END,
                         GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
 
-       glamofb_cmd_mode(glamo, 0);
+       glamofb_cmd_mode(gfb, 0);
+
+       gfb->mode_set = 1;
 
 out_unlock:
-       dev_dbg(&glamo->mach_info->glamo->pdev->dev,
-                     "glamofb_update_lcd_controller spin_unlock_irqrestore\n");
-       spin_unlock_irqrestore(&glamo->lock_cmd, flags);
+       dev_dbg(&gcore->pdev->dev,
+                     "glamofb_program_mode spin_unlock_irqrestore\n");
+       spin_unlock_irqrestore(&gfb->lock_cmd, flags);
 }
 
+
 static int glamofb_pan_display(struct fb_var_screeninfo *var,
                struct fb_info *info)
 {
+       return 0;
+}
+
+static struct fb_videomode *glamofb_find_mode(struct fb_info *info,
+        struct fb_var_screeninfo *var) {
        struct glamofb_handle *glamo = info->par;
-       u_int16_t page = var->yoffset / glamo->mach_info->yres.defval;
-       reg_write(glamo, GLAMO_REG_LCD_COMMAND2, page);
+       struct glamo_fb_platform_data *mach_info = glamo->mach_info;
+       struct fb_videomode *mode;
+       int i;
 
-       return 0;
+       for(i = mach_info->num_modes, mode = mach_info->modes; i > 0; --i, ++mode) {
+               if (mode->xres == var->xres &&
+                   mode->yres == var->yres)
+                       return mode;
+       }
+
+       return NULL;
 }
 
 static int glamofb_set_par(struct fb_info *info)
 {
        struct glamofb_handle *glamo = info->par;
        struct fb_var_screeninfo *var = &info->var;
+       struct fb_videomode *mode;
 
-       if (glamo->mach_info->glamo->suspending) {
-               dev_err(&glamo->mach_info->glamo->pdev->dev,
+       if (glamo->core->suspending) {
+               dev_err(&glamo->core->pdev->dev,
                                "IGNORING glamofb_set_par while "
                                                                 "suspended\n");
                return -EBUSY;
        }
 
-       switch (var->bits_per_pixel) {
-       case 16:
-               info->fix.visual = FB_VISUAL_TRUECOLOR;
-               break;
-       default:
-               printk("Smedia driver doesn't support != 16bpp\n");
+       mode = glamofb_find_mode(info, var);
+       if (!mode)
                return -EINVAL;
-       }
 
-       info->fix.line_length = (var->xres * var->bits_per_pixel) / 8;
+       fb_videomode_to_var(var, mode);
 
-       glamofb_update_lcd_controller(glamo, var);
+       info->mode = mode;
 
-       return 0;
-}
+       glamo->mode_set = 0;
 
+       switch(var->rotate) {
+       case FB_ROTATE_CW:
+       case FB_ROTATE_CCW:
+               info->fix.line_length = (var->yres * var->bits_per_pixel) / 8;
+               /* FIXME: Limit pixelclock */
+               var->pixclock *= 2;
+               break;
+       default:
+               info->fix.line_length = (var->xres * var->bits_per_pixel) / 8;
+               break;
+       }
 
-static void notify_blank(struct fb_info *info, int blank_mode)
-{
-       struct fb_event event;
+       if(glamo->output_enabled)
+               glamofb_program_mode(glamo);
 
-       event.info = info;
-       event.data = &blank_mode;
-       fb_notifier_call_chain(FB_EVENT_CONBLANK, &event);
+       return 0;
 }
 
-
 static int glamofb_blank(int blank_mode, struct fb_info *info)
 {
        struct glamofb_handle *gfb = info->par;
-       struct glamo_core *gcore = gfb->mach_info->glamo;
 
        dev_dbg(gfb->dev, "glamofb_blank(%u)\n", blank_mode);
 
@@ -505,28 +452,13 @@ static int glamofb_blank(int blank_mode, struct fb_info *info)
                 * we should already switch off pixel clock here */
                break;
        case FB_BLANK_POWERDOWN:
-               /* Simulating FB_BLANK_NORMAL allow turning off backlight */
-               if (gfb->blank_mode != FB_BLANK_NORMAL)
-                       notify_blank(info, FB_BLANK_NORMAL);
-
-               /* LCM need notification before pixel clock is stopped */
-               notify_blank(info, blank_mode);
-
                /* disable the pixel clock */
-               glamo_engine_clkreg_set(gcore, GLAMO_ENGINE_LCD,
-                                       GLAMO_CLOCK_LCD_EN_DCLK, 0);
+               glamo_output_disable(gfb);
                gfb->blank_mode = blank_mode;
                break;
        case FB_BLANK_UNBLANK:
        case FB_BLANK_NORMAL:
-               /* enable the pixel clock if off */
-               if (gfb->blank_mode == FB_BLANK_POWERDOWN)
-                       glamo_engine_clkreg_set(gcore,
-                                       GLAMO_ENGINE_LCD,
-                                       GLAMO_CLOCK_LCD_EN_DCLK,
-                                       GLAMO_CLOCK_LCD_EN_DCLK);
-
-               notify_blank(info, blank_mode);
+               glamo_output_enable(gfb);
                gfb->blank_mode = blank_mode;
                break;
        }
@@ -552,8 +484,8 @@ static int glamofb_setcolreg(unsigned regno,
        struct glamofb_handle *glamo = info->par;
        unsigned int val;
 
-       if (glamo->mach_info->glamo->suspending) {
-               dev_err(&glamo->mach_info->glamo->pdev->dev,
+       if (glamo->core->suspending) {
+               dev_err(&glamo->core->pdev->dev,
                                "IGNORING glamofb_set_par while "
                                                                 "suspended\n");
                return -EBUSY;
@@ -581,6 +513,31 @@ static int glamofb_setcolreg(unsigned regno,
        return 0;
 }
 
+static int glamofb_ioctl(struct fb_info *info, unsigned int cmd,
+                         unsigned long arg) {
+       struct glamofb_handle *gfb = (struct glamofb_handle*)info->par;
+       struct glamo_core *gcore = gfb->core;
+       int retval = -ENOTTY;
+
+       switch (cmd) {
+       case GLAMOFB_ENGINE_ENABLE:
+               retval = glamo_engine_enable(gcore, arg);
+               break;
+       case GLAMOFB_ENGINE_DISABLE:
+               retval = glamo_engine_disable(gcore, arg);
+               break;
+       case GLAMOFB_ENGINE_RESET:
+               glamo_engine_reset(gcore, arg);
+               retval = 0;
+               break;
+       default:
+               break;
+       }
+
+       return retval;
+}
+
+
 #ifdef CONFIG_MFD_GLAMO_HWACCEL
 static inline void glamofb_vsync_wait(struct glamofb_handle *glamo,
                int line, int size, int range)
@@ -721,8 +678,8 @@ int glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
 {
        int timeout = 2000000;
 
-       if (gfb->mach_info->glamo->suspending) {
-               dev_err(&gfb->mach_info->glamo->pdev->dev,
+       if (gfb->core->suspending) {
+               dev_err(&gfb->core->pdev->dev,
                                "IGNORING glamofb_cmd_mode while "
                                                                 "suspended\n");
                return -EBUSY;
@@ -733,7 +690,7 @@ int glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
                dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ",
                        __func__);
                while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
-                       /* yield() */;
+                       cpu_relax();
                if (timeout < 0) {
                        printk(KERN_ERR"*************"
                                       "glamofb cmd_queue never got empty"
@@ -752,7 +709,7 @@ int glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
                timeout = 2000000;
                while ((!reg_read(gfb, GLAMO_REG_LCD_STATUS2) & (1 << 12)) &&
                      (timeout--))
-                       /* yield() */;
+                       cpu_relax();
                if (timeout < 0) {
                        printk(KERN_ERR"*************"
                                       "glamofb lcd never idle"
@@ -785,8 +742,8 @@ int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val)
 {
        int timeout = 200000;
 
-       if (gfb->mach_info->glamo->suspending) {
-               dev_err(&gfb->mach_info->glamo->pdev->dev,
+       if (gfb->core->suspending) {
+               dev_err(&gfb->core->pdev->dev,
                                "IGNORING glamofb_cmd_write while "
                                                                 "suspended\n");
                return -EBUSY;
@@ -816,6 +773,7 @@ static struct fb_ops glamofb_ops = {
        .fb_set_par     = glamofb_set_par,
        .fb_blank       = glamofb_blank,
        .fb_setcolreg   = glamofb_setcolreg,
+       .fb_ioctl = glamofb_ioctl,
 #ifdef CONFIG_MFD_GLAMO_HWACCEL
        .fb_cursor      = glamofb_cursor,
 #endif
@@ -840,20 +798,25 @@ static int __init glamofb_probe(struct platform_device *pdev)
        int rc = -EIO;
        struct fb_info *fbinfo;
        struct glamofb_handle *glamofb;
-       struct glamofb_platform_data *mach_info = pdev->dev.platform_data;
+       struct glamo_core *core = dev_get_drvdata(pdev->dev.parent);
+       struct glamo_fb_platform_data *mach_info;
 
        printk(KERN_INFO "SMEDIA Glamo frame buffer driver (C) 2007 "
                "Openmoko, Inc.\n");
 
+       if (!core->pdata || !core->pdata->fb_data)
+               return -ENOENT;
+
+
        fbinfo = framebuffer_alloc(sizeof(struct glamofb_handle), &pdev->dev);
        if (!fbinfo)
                return -ENOMEM;
 
+
        glamofb = fbinfo->par;
        glamofb->fb = fbinfo;
        glamofb->dev = &pdev->dev;
 
-       glamofb->angle = 0;
        glamofb->blank_mode = FB_BLANK_POWERDOWN;
 
        strcpy(fbinfo->fix.id, "SMedia Glamo");
@@ -875,14 +838,14 @@ static int __init glamofb_probe(struct platform_device *pdev)
        }
 
        glamofb->reg = request_mem_region(glamofb->reg->start,
-                                         RESSIZE(glamofb->reg), pdev->name);
+                                         resource_size(glamofb->reg), pdev->name);
        if (!glamofb->reg) {
                dev_err(&pdev->dev, "failed to request mmio region\n");
                goto out_free;
        }
 
        glamofb->fb_res = request_mem_region(glamofb->fb_res->start,
-                                            mach_info->fb_mem_size,
+                                            resource_size(glamofb->fb_res),
                                             pdev->name);
        if (!glamofb->fb_res) {
                dev_err(&pdev->dev, "failed to request vram region\n");
@@ -891,16 +854,17 @@ static int __init glamofb_probe(struct platform_device *pdev)
 
        /* we want to remap only the registers required for this core
         * driver. */
-       glamofb->base = ioremap(glamofb->reg->start, RESSIZE(glamofb->reg));
+       glamofb->base = ioremap_nocache(glamofb->reg->start, resource_size(glamofb->reg));
        if (!glamofb->base) {
                dev_err(&pdev->dev, "failed to ioremap() mmio memory\n");
                goto out_release_fb;
        }
+
        fbinfo->fix.smem_start = (unsigned long) glamofb->fb_res->start;
-       fbinfo->fix.smem_len = mach_info->fb_mem_size;
+       fbinfo->fix.smem_len = (__u32) resource_size(glamofb->fb_res);
 
        fbinfo->screen_base = ioremap(glamofb->fb_res->start,
-                                      RESSIZE(glamofb->fb_res));
+                                      resource_size(glamofb->fb_res));
        if (!fbinfo->screen_base) {
                dev_err(&pdev->dev, "failed to ioremap() vram memory\n");
                goto out_release_fb;
@@ -909,48 +873,37 @@ static int __init glamofb_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, glamofb);
 
-       glamofb->mach_info = pdev->dev.platform_data;
+       mach_info = core->pdata->fb_data;
+       glamofb->core = core;
+       glamofb->mach_info = mach_info;
 
        fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
        fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
        fbinfo->fix.type_aux = 0;
        fbinfo->fix.xpanstep = 0;
-       fbinfo->fix.ypanstep = mach_info->yres.defval;
+       fbinfo->fix.ypanstep = 0;
        fbinfo->fix.ywrapstep = 0;
        fbinfo->fix.accel = FB_ACCEL_GLAMO;
 
-       fbinfo->var.nonstd = 0;
-       fbinfo->var.activate = FB_ACTIVATE_NOW;
-       fbinfo->var.height = mach_info->height;
-       fbinfo->var.width = mach_info->width;
-       fbinfo->var.accel_flags = 0;    /* FIXME */
-       fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
 
        fbinfo->fbops = &glamofb_ops;
        fbinfo->flags = FBINFO_FLAG_DEFAULT;
        fbinfo->pseudo_palette = &glamofb->pseudo_pal;
 
-       fbinfo->var.xres = mach_info->xres.defval;
-       fbinfo->var.xres_virtual = mach_info->xres.defval;
-       fbinfo->var.yres = mach_info->yres.defval;
-       fbinfo->var.yres_virtual = mach_info->yres.defval * 2;
-       fbinfo->var.bits_per_pixel = mach_info->bpp.defval;
-
-       fbinfo->var.pixclock = mach_info->pixclock;
-       fbinfo->var.left_margin = mach_info->left_margin;
-       fbinfo->var.right_margin = mach_info->right_margin;
-       fbinfo->var.upper_margin = mach_info->upper_margin;
-       fbinfo->var.lower_margin = mach_info->lower_margin;
-       fbinfo->var.hsync_len = mach_info->hsync_len;
-       fbinfo->var.vsync_len = mach_info->vsync_len;
-
-       memset(fbinfo->screen_base, 0,
-                       mach_info->xres.max *
-                       mach_info->yres.max *
-                       mach_info->bpp.max / 8);
+       fbinfo->mode = mach_info->modes;
+       fb_videomode_to_var(&fbinfo->var, fbinfo->mode);
+       fbinfo->var.bits_per_pixel = 16;
+       fbinfo->var.nonstd = 0;
+       fbinfo->var.activate = FB_ACTIVATE_NOW;
+       fbinfo->var.height = mach_info->height;
+       fbinfo->var.width = mach_info->width;
+       fbinfo->var.accel_flags = 0;
+       fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
 
-       glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
-       glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
+       glamo_engine_enable(core, GLAMO_ENGINE_LCD);
+       glamo_engine_reset(core, GLAMO_ENGINE_LCD);
+       glamofb->output_enabled = 1;
+       glamofb->mode_set = 1;
 
        dev_info(&pdev->dev, "spin_lock_init\n");
        spin_lock_init(&glamofb->lock_cmd);
@@ -959,14 +912,8 @@ static int __init glamofb_probe(struct platform_device *pdev)
        glamofb_cursor_onoff(glamofb, 1);
 #endif
 
-#ifdef CONFIG_MFD_GLAMO_FB_XGLAMO_WORKAROUND
-       /* sysfs */
-       rc = sysfs_create_group(&pdev->dev.kobj, &glamo_fb_attr_group);
-       if (rc < 0) {
-               dev_err(&pdev->dev, "cannot create sysfs group\n");
-               goto out_unmap_fb;
-       }
-#endif
+       fb_videomode_to_modelist(mach_info->modes, mach_info->num_modes,
+                                &fbinfo->modelist);
 
        rc = register_framebuffer(fbinfo);
        if (rc < 0) {
@@ -974,14 +921,6 @@ static int __init glamofb_probe(struct platform_device *pdev)
                goto out_unmap_fb;
        }
 
-       if (mach_info->spi_info) {
-               /* register the sibling spi device */
-               mach_info->spi_info->glamofb_handle = glamofb;
-               glamo_spi_dev.dev.parent = &pdev->dev;
-               glamo_spi_dev.dev.platform_data = mach_info->spi_info;
-               platform_device_register(&glamo_spi_dev);
-       }
-
        printk(KERN_INFO "fb%d: %s frame buffer device\n",
                fbinfo->node, fbinfo->fix.id);
 
@@ -991,9 +930,9 @@ out_unmap_fb:
        iounmap(fbinfo->screen_base);
        iounmap(glamofb->base);
 out_release_fb:
-       release_mem_region(glamofb->fb_res->start, RESSIZE(glamofb->fb_res));
+       release_mem_region(glamofb->fb_res->start, resource_size(glamofb->fb_res));
 out_release_reg:
-       release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg));
+       release_mem_region(glamofb->reg->start, resource_size(glamofb->reg));
 out_free:
        framebuffer_release(fbinfo);
        return rc;
@@ -1005,7 +944,7 @@ static int glamofb_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
        iounmap(glamofb->base);
-       release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg));
+       release_mem_region(glamofb->reg->start, resource_size(glamofb->reg));
        kfree(glamofb);
 
        return 0;
@@ -1013,9 +952,9 @@ static int glamofb_remove(struct platform_device *pdev)
 
 #ifdef CONFIG_PM
 
-static int glamofb_suspend(struct platform_device *pdev, pm_message_t state)
+static int glamofb_suspend(struct device *dev)
 {
-       struct glamofb_handle *gfb = platform_get_drvdata(pdev);
+       struct glamofb_handle *gfb = dev_get_drvdata(dev);
 
        /* we need to stop anything touching our framebuffer */
        fb_set_suspend(gfb->fb, 1);
@@ -1028,19 +967,16 @@ static int glamofb_suspend(struct platform_device *pdev, pm_message_t state)
        return 0;
 }
 
-static int glamofb_resume(struct platform_device *pdev)
+static int glamofb_resume(struct device *dev)
 {
-       struct glamofb_handle *gfb = platform_get_drvdata(pdev);
-       struct glamofb_platform_data *mach_info = pdev->dev.platform_data;
+       struct glamofb_handle *gfb = dev_get_drvdata(dev);
 
        /* OK let's allow framebuffer ops again */
        /* gfb->fb->screen_base = ioremap(gfb->fb_res->start,
-                                      RESSIZE(gfb->fb_res)); */
-       glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
-       glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
+                                      resource_size(gfb->fb_res)); */
+       glamo_engine_enable(gfb->core, GLAMO_ENGINE_LCD);
+       glamo_engine_reset(gfb->core, GLAMO_ENGINE_LCD);
 
-       printk(KERN_ERR"spin_lock_init\n");
-       spin_lock_init(&gfb->lock_cmd);
        glamofb_init_regs(gfb);
 #ifdef CONFIG_MFD_GLAMO_HWACCEL
        glamofb_cursor_onoff(gfb, 1);
@@ -1050,19 +986,25 @@ static int glamofb_resume(struct platform_device *pdev)
 
        return 0;
 }
+
+static struct dev_pm_ops glamofb_pm_ops = {
+       .suspend = glamofb_suspend,
+       .resume = glamofb_resume,
+};
+
+#define GLAMOFB_PM_OPS (&glamofb_pm_ops)
+
 #else
-#define glamofb_suspend NULL
-#define glamofb_resume  NULL
+#define GLAMOFB_PM_OPS NULL
 #endif
 
 static struct platform_driver glamofb_driver = {
        .probe          = glamofb_probe,
        .remove         = glamofb_remove,
-       .suspend        = glamofb_suspend,
-       .resume = glamofb_resume,
        .driver         = {
                .name   = "glamo-fb",
                .owner  = THIS_MODULE,
+               .pm     = GLAMOFB_PM_OPS
        },
 };