Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier...
[safe/jmp/linux-2.6] / drivers / video / omap / omapfb_main.c
index 51a138b..0d0c8c8 100644 (file)
 #include <mach/dma.h>
 #include <mach/omapfb.h>
 
+#include "lcdc.h"
+#include "dispc.h"
+
 #define MODULE_NAME    "omapfb"
 
 static unsigned int    def_accel;
 static unsigned long   def_vram[OMAPFB_PLANE_NUM];
-static int             def_vram_cnt;
+static unsigned int    def_vram_cnt;
 static unsigned long   def_vxres;
 static unsigned long   def_vyres;
 static unsigned int    def_rotate;
@@ -64,6 +67,7 @@ static struct caps_table_struct ctrl_caps[] = {
        { OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" },
        { OMAPFB_CAPS_WINDOW_SCALE,   "scale window" },
        { OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" },
+       { OMAPFB_CAPS_WINDOW_ROTATE,  "rotate window" },
        { OMAPFB_CAPS_SET_BACKLIGHT,  "backlight setting" },
 };
 
@@ -84,12 +88,10 @@ static struct caps_table_struct color_caps[] = {
  * LCD panel
  * ---------------------------------------------------------------------------
  */
-extern struct lcd_ctrl omap1_int_ctrl;
-extern struct lcd_ctrl omap2_int_ctrl;
 extern struct lcd_ctrl hwa742_ctrl;
 extern struct lcd_ctrl blizzard_ctrl;
 
-static struct lcd_ctrl *ctrls[] = {
+static const struct lcd_ctrl *ctrls[] = {
 #ifdef CONFIG_ARCH_OMAP1
        &omap1_int_ctrl,
 #else
@@ -214,6 +216,15 @@ static int ctrl_change_mode(struct fb_info *fbi)
                                 offset, var->xres_virtual,
                                 plane->info.pos_x, plane->info.pos_y,
                                 var->xres, var->yres, plane->color_mode);
+       if (r < 0)
+               return r;
+
+       if (fbdev->ctrl->set_rotate != NULL) {
+               r = fbdev->ctrl->set_rotate(var->rotate);
+               if (r < 0)
+                       return r;
+       }
+
        if (fbdev->ctrl->set_scale != NULL)
                r = fbdev->ctrl->set_scale(plane->idx,
                                   var->xres, var->yres,
@@ -337,7 +348,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
 
        omapfb_rqueue_lock(fbdev);
        switch (blank) {
-       case VESA_NO_BLANKING:
+       case FB_BLANK_UNBLANK:
                if (fbdev->state == OMAPFB_SUSPENDED) {
                        if (fbdev->ctrl->resume)
                                fbdev->ctrl->resume();
@@ -348,7 +359,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
                                do_update = 1;
                }
                break;
-       case VESA_POWERDOWN:
+       case FB_BLANK_POWERDOWN:
                if (fbdev->state == OMAPFB_ACTIVE) {
                        fbdev->panel->disable(fbdev->panel);
                        if (fbdev->ctrl->suspend)
@@ -382,7 +393,7 @@ static void omapfb_sync(struct fb_info *fbi)
  * Set fb_info.fix fields and also updates fbdev.
  * When calling this fb_info.var must be set up already.
  */
-static void set_fb_fix(struct fb_info *fbi)
+static void set_fb_fix(struct fb_info *fbi, int from_init)
 {
        struct fb_fix_screeninfo *fix = &fbi->fix;
        struct fb_var_screeninfo *var = &fbi->var;
@@ -391,9 +402,17 @@ static void set_fb_fix(struct fb_info *fbi)
        int bpp;
 
        rg = &plane->fbdev->mem_desc.region[plane->idx];
-       fbi->screen_base        = (char __iomem *)rg->vaddr;
-       fix->smem_start         = rg->paddr;
-       fix->smem_len           = rg->size;
+       fbi->screen_base        = rg->vaddr;
+
+       if (!from_init) {
+               mutex_lock(&fbi->mm_lock);
+               fix->smem_start         = rg->paddr;
+               fix->smem_len           = rg->size;
+               mutex_unlock(&fbi->mm_lock);
+       } else {
+               fix->smem_start         = rg->paddr;
+               fix->smem_len           = rg->size;
+       }
 
        fix->type = FB_TYPE_PACKED_PIXELS;
        bpp = var->bits_per_pixel;
@@ -551,7 +570,6 @@ static int set_fb_var(struct fb_info *fbi,
                var->xoffset = var->xres_virtual - var->xres;
        if (var->yres + var->yoffset > var->yres_virtual)
                var->yoffset = var->yres_virtual - var->yres;
-       line_size = var->xres * bpp / 8;
 
        if (plane->color_mode == OMAPFB_COLOR_RGB444) {
                var->red.offset   = 8; var->red.length   = 4;
@@ -597,7 +615,7 @@ static void omapfb_rotate(struct fb_info *fbi, int rotate)
        struct omapfb_device *fbdev = plane->fbdev;
 
        omapfb_rqueue_lock(fbdev);
-       if (cpu_is_omap15xx() && rotate != fbi->var.rotate) {
+       if (rotate != fbi->var.rotate) {
                struct fb_var_screeninfo *new_var = &fbdev->new_var;
 
                memcpy(new_var, &fbi->var, sizeof(*new_var));
@@ -692,7 +710,7 @@ static int omapfb_set_par(struct fb_info *fbi)
        int r = 0;
 
        omapfb_rqueue_lock(fbdev);
-       set_fb_fix(fbi);
+       set_fb_fix(fbi, 0);
        r = ctrl_change_mode(fbi);
        omapfb_rqueue_unlock(fbdev);
 
@@ -704,28 +722,42 @@ int omapfb_update_window_async(struct fb_info *fbi,
                                void (*callback)(void *),
                                void *callback_data)
 {
+       int xres, yres;
        struct omapfb_plane_struct *plane = fbi->par;
        struct omapfb_device *fbdev = plane->fbdev;
-       struct fb_var_screeninfo *var;
+       struct fb_var_screeninfo *var = &fbi->var;
+
+       switch (var->rotate) {
+       case 0:
+       case 180:
+               xres = fbdev->panel->x_res;
+               yres = fbdev->panel->y_res;
+               break;
+       case 90:
+       case 270:
+               xres = fbdev->panel->y_res;
+               yres = fbdev->panel->x_res;
+               break;
+       default:
+               return -EINVAL;
+       }
 
-       var = &fbi->var;
-       if (win->x >= var->xres || win->y >= var->yres ||
-           win->out_x > var->xres || win->out_y >= var->yres)
+       if (win->x >= xres || win->y >= yres ||
+           win->out_x > xres || win->out_y > yres)
                return -EINVAL;
 
        if (!fbdev->ctrl->update_window ||
            fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
                return -ENODEV;
 
-       if (win->x + win->width >= var->xres)
-               win->width = var->xres - win->x;
-       if (win->y + win->height >= var->yres)
-               win->height = var->yres - win->y;
-       /* The out sizes should be cropped to the LCD size */
-       if (win->out_x + win->out_width > fbdev->panel->x_res)
-               win->out_width = fbdev->panel->x_res - win->out_x;
-       if (win->out_y + win->out_height > fbdev->panel->y_res)
-               win->out_height = fbdev->panel->y_res - win->out_y;
+       if (win->x + win->width > xres)
+               win->width = xres - win->x;
+       if (win->y + win->height > yres)
+               win->height = yres - win->y;
+       if (win->out_x + win->out_width > xres)
+               win->out_width = xres - win->out_x;
+       if (win->out_y + win->out_height > yres)
+               win->out_height = yres - win->out_y;
        if (!win->width || !win->height || !win->out_width || !win->out_height)
                return 0;
 
@@ -740,7 +772,7 @@ static int omapfb_update_win(struct fb_info *fbi,
        int ret;
 
        omapfb_rqueue_lock(plane->fbdev);
-       ret = omapfb_update_window_async(fbi, win, NULL, 0);
+       ret = omapfb_update_window_async(fbi, win, NULL, NULL);
        omapfb_rqueue_unlock(plane->fbdev);
 
        return ret;
@@ -768,7 +800,7 @@ static int omapfb_update_full_screen(struct fb_info *fbi)
        win.format = 0;
 
        omapfb_rqueue_lock(fbdev);
-       r = fbdev->ctrl->update_window(fbi, &win, NULL, 0);
+       r = fbdev->ctrl->update_window(fbi, &win, NULL, NULL);
        omapfb_rqueue_unlock(fbdev);
 
        return r;
@@ -878,15 +910,17 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
                if (old_size != size) {
                        if (size) {
                                memcpy(&fbi->var, new_var, sizeof(fbi->var));
-                               set_fb_fix(fbi);
+                               set_fb_fix(fbi, 0);
                        } else {
                                /*
                                 * Set these explicitly to indicate that the
                                 * plane memory is dealloce'd, the other
                                 * screen parameters in var / fix are invalid.
                                 */
+                               mutex_lock(&fbi->mm_lock);
                                fbi->fix.smem_start = 0;
                                fbi->fix.smem_len = 0;
+                               mutex_unlock(&fbi->mm_lock);
                        }
                }
        }
@@ -1047,7 +1081,7 @@ void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
                win.height = 2;
                win.out_width = 2;
                win.out_height = 2;
-               fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, 0);
+               fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, NULL);
        }
        omapfb_rqueue_unlock(fbdev);
 }
@@ -1249,7 +1283,7 @@ static struct fb_ops omapfb_ops = {
 static ssize_t omapfb_show_caps_num(struct device *dev,
                                    struct device_attribute *attr, char *buf)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
        int plane;
        size_t size;
        struct omapfb_caps caps;
@@ -1269,7 +1303,7 @@ static ssize_t omapfb_show_caps_num(struct device *dev,
 static ssize_t omapfb_show_caps_text(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
        int i;
        struct omapfb_caps caps;
        int plane;
@@ -1316,7 +1350,7 @@ static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL);
 static ssize_t omapfb_show_panel_name(struct device *dev,
                                      struct device_attribute *attr, char *buf)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
 
        return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name);
 }
@@ -1325,7 +1359,7 @@ static ssize_t omapfb_show_bklight_level(struct device *dev,
                                         struct device_attribute *attr,
                                         char *buf)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
        int r;
 
        if (fbdev->panel->get_bklight_level) {
@@ -1340,7 +1374,7 @@ static ssize_t omapfb_store_bklight_level(struct device *dev,
                                          struct device_attribute *attr,
                                          const char *buf, size_t size)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
        int r;
 
        if (fbdev->panel->set_bklight_level) {
@@ -1359,7 +1393,7 @@ static ssize_t omapfb_store_bklight_level(struct device *dev,
 static ssize_t omapfb_show_bklight_max(struct device *dev,
                                       struct device_attribute *attr, char *buf)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
        int r;
 
        if (fbdev->panel->get_bklight_level) {
@@ -1392,7 +1426,7 @@ static struct attribute_group panel_attr_grp = {
 static ssize_t omapfb_show_ctrl_name(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
 
        return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name);
 }
@@ -1476,7 +1510,7 @@ static int fbinfo_init(struct omapfb_device *fbdev, struct fb_info *info)
        var->bits_per_pixel = fbdev->panel->bpp;
 
        set_fb_var(info, var);
-       set_fb_fix(info);
+       set_fb_fix(info, 1);
 
        r = fb_alloc_cmap(&info->cmap, 16, 0);
        if (r != 0)
@@ -1694,8 +1728,8 @@ static int omapfb_do_probe(struct platform_device *pdev,
 
        pr_info("omapfb: configured for panel %s\n", fbdev->panel->name);
 
-       def_vxres = def_vxres ? : fbdev->panel->x_res;
-       def_vyres = def_vyres ? : fbdev->panel->y_res;
+       def_vxres = def_vxres ? def_vxres : fbdev->panel->x_res;
+       def_vyres = def_vyres ? def_vyres : fbdev->panel->y_res;
 
        init_state++;
 
@@ -1817,8 +1851,8 @@ static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg)
 {
        struct omapfb_device *fbdev = platform_get_drvdata(pdev);
 
-       omapfb_blank(VESA_POWERDOWN, fbdev->fb_info[0]);
-
+       if (fbdev != NULL)
+               omapfb_blank(FB_BLANK_POWERDOWN, fbdev->fb_info[0]);
        return 0;
 }
 
@@ -1827,7 +1861,8 @@ static int omapfb_resume(struct platform_device *pdev)
 {
        struct omapfb_device *fbdev = platform_get_drvdata(pdev);
 
-       omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info[0]);
+       if (fbdev != NULL)
+               omapfb_blank(FB_BLANK_UNBLANK, fbdev->fb_info[0]);
        return 0;
 }