Merge branch 'common/fbdev' of master.kernel.org:/pub/scm/linux/kernel/git/lethal...
authorPaul Mundt <lethal@linux-sh.org>
Tue, 29 Mar 2011 07:06:21 +0000 (16:06 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Tue, 29 Mar 2011 07:06:21 +0000 (16:06 +0900)
arch/sh/boards/mach-ap325rxa/setup.c
arch/sh/boards/mach-ecovec24/setup.c
drivers/video/sh_mobile_lcdcfb.c
drivers/video/sh_mobile_lcdcfb.h

index 3e5fc3b..d695e43 100644 (file)
@@ -156,24 +156,34 @@ static struct platform_device nand_flash_device = {
 #define PORT_DRVCRA    0xA405018A
 #define PORT_DRVCRB    0xA405018C
 
+static int ap320_wvga_set_brightness(void *board_data, int brightness)
+{
+       if (brightness) {
+               gpio_set_value(GPIO_PTS3, 0);
+               __raw_writew(0x100, FPGA_BKLREG);
+       } else {
+               __raw_writew(0, FPGA_BKLREG);
+               gpio_set_value(GPIO_PTS3, 1);
+       }
+       
+       return 0;
+}
+
+static int ap320_wvga_get_brightness(void *board_data)
+{
+       return gpio_get_value(GPIO_PTS3);
+}
+
 static void ap320_wvga_power_on(void *board_data, struct fb_info *info)
 {
        msleep(100);
 
        /* ASD AP-320/325 LCD ON */
        __raw_writew(FPGA_LCDREG_VAL, FPGA_LCDREG);
-
-       /* backlight */
-       gpio_set_value(GPIO_PTS3, 0);
-       __raw_writew(0x100, FPGA_BKLREG);
 }
 
 static void ap320_wvga_power_off(void *board_data)
 {
-       /* backlight */
-       __raw_writew(0, FPGA_BKLREG);
-       gpio_set_value(GPIO_PTS3, 1);
-
        /* ASD AP-320/325 LCD OFF */
        __raw_writew(0, FPGA_LCDREG);
 }
@@ -209,6 +219,12 @@ static struct sh_mobile_lcdc_info lcdc_info = {
                .board_cfg = {
                        .display_on = ap320_wvga_power_on,
                        .display_off = ap320_wvga_power_off,
+                       .set_brightness = ap320_wvga_set_brightness,
+                       .get_brightness = ap320_wvga_get_brightness,
+               },
+               .bl_info = {
+                       .name = "sh_mobile_lcdc_bl",
+                       .max_brightness = 1,
                },
        }
 };
index e44480c..c68e286 100644 (file)
@@ -263,6 +263,18 @@ const static struct fb_videomode ecovec_dvi_modes[] = {
        },
 };
 
+static int ecovec24_set_brightness(void *board_data, int brightness)
+{
+       gpio_set_value(GPIO_PTR1, brightness);
+
+       return 0;
+}
+
+static int ecovec24_get_brightness(void *board_data)
+{
+       return gpio_get_value(GPIO_PTR1);
+}
+
 static struct sh_mobile_lcdc_info lcdc_info = {
        .ch[0] = {
                .interface_type = RGB18,
@@ -273,6 +285,12 @@ static struct sh_mobile_lcdc_info lcdc_info = {
                        .height = 91,
                },
                .board_cfg = {
+                       .set_brightness = ecovec24_set_brightness,
+                       .get_brightness = ecovec24_get_brightness,
+               },
+               .bl_info = {
+                       .name = "sh_mobile_lcdc_bl",
+                       .max_brightness = 1,
                },
        }
 };
index 757665b..9bcc61b 100644 (file)
@@ -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);
                }
index 4635eed..f16cb56 100644 (file)
@@ -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 */
 };