diff options
Diffstat (limited to 'drivers/video/omap/omapfb_main.c')
-rw-r--r-- | drivers/video/omap/omapfb_main.c | 86 |
1 files changed, 58 insertions, 28 deletions
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 8862233d57b..0d0c8c8b9b5 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -67,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" }, }; @@ -215,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, @@ -383,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; @@ -393,10 +403,16 @@ static void set_fb_fix(struct fb_info *fbi) rg = &plane->fbdev->mem_desc.region[plane->idx]; fbi->screen_base = rg->vaddr; - mutex_lock(&fbi->mm_lock); - fix->smem_start = rg->paddr; - fix->smem_len = rg->size; - mutex_unlock(&fbi->mm_lock); + + 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; @@ -554,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; @@ -600,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)); @@ -695,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); @@ -707,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; - var = &fbi->var; - if (win->x >= var->xres || win->y >= var->yres || - win->out_x > var->xres || win->out_y >= var->yres) + 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; + } + + 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; @@ -881,7 +910,7 @@ 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 @@ -1481,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) @@ -1699,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++; @@ -1822,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(FB_BLANK_POWERDOWN, fbdev->fb_info[0]); - + if (fbdev != NULL) + omapfb_blank(FB_BLANK_POWERDOWN, fbdev->fb_info[0]); return 0; } @@ -1832,7 +1861,8 @@ static int omapfb_resume(struct platform_device *pdev) { struct omapfb_device *fbdev = platform_get_drvdata(pdev); - omapfb_blank(FB_BLANK_UNBLANK, fbdev->fb_info[0]); + if (fbdev != NULL) + omapfb_blank(FB_BLANK_UNBLANK, fbdev->fb_info[0]); return 0; } |