diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-07 23:49:17 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-07 23:49:17 +0400 |
commit | 132452ee2368cf775ccbef9746b51e3d2ba58b85 (patch) | |
tree | 68652e7a5d11776184e7b05c04dfc94baa429f2a /drivers/video/sh_mobile_lcdcfb.c | |
parent | 174457391a83d70215d441cb3bc0aa7d7443b63e (diff) | |
parent | 97fb85076c2d3adcc559dee577e0a3bf7215d48e (diff) | |
download | linux-132452ee2368cf775ccbef9746b51e3d2ba58b85.tar.xz |
Merge branch 'fbdev-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6
* 'fbdev-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6:
efifb: Add override for 11" Macbook Air 3,1
efifb: Support overriding fields FW tells us with the DMI data.
fb: Reduce priority of resource conflict message
savagefb: Remove obsolete else clause in savage_setup_i2c_bus
savagefb: Set up I2C based on chip family instead of card id
savagefb: Replace magic register address with define
drivers/video/bfin-lq035q1-fb.c: introduce missing kfree
video: s3c-fb: fix checkpatch errors and warning
efifb: support AMD Radeon HD 6490
s3fb: fix Virge/GX2
fbcon: Remove unused 'display *p' variable from fb_flashcursor()
fbdev: sh_mobile_lcdcfb: fix module lock acquisition
fbdev: sh_mobile_lcdcfb: add blanking support
viafb: initialize margins correct
viafb: refresh rate bug collection
sh: mach-ap325rxa: move backlight control code
sh: mach-ecovec24: support for main lcd backlight
Diffstat (limited to 'drivers/video/sh_mobile_lcdcfb.c')
-rw-r--r-- | drivers/video/sh_mobile_lcdcfb.c | 52 |
1 files changed, 48 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); } |