diff options
author | Paul Mundt <lethal@linux-sh.org> | 2011-03-29 09:06:21 +0200 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-03-29 09:06:21 +0200 |
commit | 1fcf0069f4715f6f811466db68a547a348b4d5a9 (patch) | |
tree | 00817872a00b162b493f65e5a90212ce54ba52ef /drivers/video | |
parent | Merge branch 'viafb-next' of git://github.com/schandinat/linux-2.6 (diff) | |
parent | fbdev: sh_mobile_lcdcfb: fix module lock acquisition (diff) | |
download | linux-1fcf0069f4715f6f811466db68a547a348b4d5a9.tar.xz linux-1fcf0069f4715f6f811466db68a547a348b4d5a9.zip |
Merge branch 'common/fbdev' of master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/sh_mobile_lcdcfb.c | 52 | ||||
-rw-r--r-- | drivers/video/sh_mobile_lcdcfb.h | 1 |
2 files changed, 49 insertions, 4 deletions
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 757665bc500f..9bcc61b4ef14 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -643,7 +643,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) continue; board_cfg = &ch->cfg.board_cfg; - if (try_module_get(board_cfg->owner) && board_cfg->display_on) { + if (board_cfg->display_on && try_module_get(board_cfg->owner)) { board_cfg->display_on(board_cfg->board_data, ch->info); module_put(board_cfg->owner); } @@ -688,7 +688,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) } board_cfg = &ch->cfg.board_cfg; - if (try_module_get(board_cfg->owner) && board_cfg->display_off) { + if (board_cfg->display_off && try_module_get(board_cfg->owner)) { board_cfg->display_off(board_cfg->board_data); module_put(board_cfg->owner); } @@ -1032,6 +1032,49 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in return 0; } +/* + * Screen blanking. Behavior is as follows: + * FB_BLANK_UNBLANK: screen unblanked, clocks enabled + * FB_BLANK_NORMAL: screen blanked, clocks enabled + * FB_BLANK_VSYNC, + * FB_BLANK_HSYNC, + * FB_BLANK_POWEROFF: screen blanked, clocks disabled + */ +static int sh_mobile_lcdc_blank(int blank, struct fb_info *info) +{ + struct sh_mobile_lcdc_chan *ch = info->par; + struct sh_mobile_lcdc_priv *p = ch->lcdc; + + /* blank the screen? */ + if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) { + struct fb_fillrect rect = { + .width = info->var.xres, + .height = info->var.yres, + }; + sh_mobile_lcdc_fillrect(info, &rect); + } + /* turn clocks on? */ + if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) { + sh_mobile_lcdc_clk_on(p); + } + /* turn clocks off? */ + if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) { + /* make sure the screen is updated with the black fill before + * switching the clocks off. one vsync is not enough since + * blanking may occur in the middle of a refresh. deferred io + * mode will reenable the clocks and update the screen in time, + * so it does not need this. */ + if (!info->fbdefio) { + sh_mobile_wait_for_vsync(info); + sh_mobile_wait_for_vsync(info); + } + sh_mobile_lcdc_clk_off(p); + } + + ch->blank_status = blank; + return 0; +} + static struct fb_ops sh_mobile_lcdc_ops = { .owner = THIS_MODULE, .fb_setcolreg = sh_mobile_lcdc_setcolreg, @@ -1040,6 +1083,7 @@ static struct fb_ops sh_mobile_lcdc_ops = { .fb_fillrect = sh_mobile_lcdc_fillrect, .fb_copyarea = sh_mobile_lcdc_copyarea, .fb_imageblit = sh_mobile_lcdc_imageblit, + .fb_blank = sh_mobile_lcdc_blank, .fb_pan_display = sh_mobile_fb_pan_display, .fb_ioctl = sh_mobile_ioctl, .fb_open = sh_mobile_open, @@ -1254,7 +1298,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, switch(action) { case FB_EVENT_SUSPEND: - if (try_module_get(board_cfg->owner) && board_cfg->display_off) { + if (board_cfg->display_off && try_module_get(board_cfg->owner)) { board_cfg->display_off(board_cfg->board_data); module_put(board_cfg->owner); } @@ -1267,7 +1311,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, mutex_unlock(&ch->open_lock); /* HDMI must be enabled before LCDC configuration */ - if (try_module_get(board_cfg->owner) && board_cfg->display_on) { + if (board_cfg->display_on && try_module_get(board_cfg->owner)) { board_cfg->display_on(board_cfg->board_data, info); module_put(board_cfg->owner); } diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h index 4635eed63eee..f16cb5645a13 100644 --- a/drivers/video/sh_mobile_lcdcfb.h +++ b/drivers/video/sh_mobile_lcdcfb.h @@ -37,6 +37,7 @@ struct sh_mobile_lcdc_chan { struct completion vsync_completion; struct fb_var_screeninfo display_var; int use_count; + int blank_status; struct mutex open_lock; /* protects the use counter */ }; |