Two comments inline - this looks good to me, but i'll need to apply it
to see whats up with GX.   Next step is to toss it into the playground,
I guess to get some miles on it before Andres pulls it in.

On 19/09/07 18:59 -0400, Bernardo Innocenti wrote:
> diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
> index 61d7659..a2ecb1d 100644
> --- a/drivers/video/fbmem.c
> +++ b/drivers/video/fbmem.c
> @@ -736,49 +736,43 @@ static void try_to_load(int fb)
>  #endif /* CONFIG_KMOD */
>  
>  int
> -fb_powerup(struct fb_info *info)
> +fb_power(struct fb_info *info, int state)
>  {
>       int ret = 0;
>  
> -     if (!info || info->state == FBINFO_STATE_RUNNING)
> -             return 0;
> -
> -     if (info->fbops->fb_powerup)
> -             ret = info->fbops->fb_powerup(info);
> -
> -     if (!ret) {
> -             acquire_console_sem();
> -             fb_set_suspend(info, 0);
> -             release_console_sem();
> -     }
> +     /* Maybe unwise */
> +     if (!info)
> +             return -EINVAL;
>  
> -     return ret;
> -}
> +     if (state < 0 || state > 3)
> +             return -EINVAL;
>  
> -int
> -fb_powerdown(struct fb_info *info)
> -{
> -     int ret = 0;
> +     acquire_console_sem();
>  
> -     if (!info || info->state == FBINFO_STATE_SUSPENDED)
> -             return 0;
> +     /* Powerup? */
> +     if (state < 3) {
>  
> -     /* Tell everybody that the fbdev is going down */
> -     acquire_console_sem();
> -     fb_set_suspend(info, 1);
> -     release_console_sem();
> +             if (info->fbops->fb_power) {
> +                     ret = info->fbops->fb_power(info, state);
> +                     if (!ret)
> +                             fb_set_suspend(info, 0);
> +             }
> +     }
> +     /* Powerdown? */
> +     else {
> +             /* Tell everybody that the fbdev is going down */
> +             fb_set_suspend(info, 1);
>  
> -     if (info->fbops->fb_powerdown)
> -             ret = info->fbops->fb_powerdown(info);
> +             if (info->fbops->fb_power)
> +                     ret = info->fbops->fb_power(info, state);
>  
> -     /* If the power down failed, then un-notify */
> +             /* If the power down failed, then un-notify */
> +             if (ret)
> +                     fb_set_suspend(info, 0);
>  
> -     if (ret) {
> -             acquire_console_sem();
> -             fb_set_suspend(info, 0);
> -             release_console_sem();
>       }
>  
> +     release_console_sem();
>       return ret;
>  }
>  
> @@ -1474,10 +1468,10 @@ void fb_set_suspend(struct fb_info *info, int state)
>       struct fb_event event;
>  
>       event.info = info;
> -     if (state) {
> +     if (state && info->state != FBINFO_STATE_SUSPENDED) {
>               fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
>               info->state = FBINFO_STATE_SUSPENDED;
> -     } else {
> +     } else if (info->state != FBINFO_STATE_RUNNING) {
>               info->state = FBINFO_STATE_RUNNING;
>               fb_notifier_call_chain(FB_EVENT_RESUME, &event);
>       }


What is this for?  fb_set_suspend() is a pre-existing API function - we want
to make sure we don't break the intended functionality.

> diff --git a/drivers/video/geode/geodefb.h b/drivers/video/geode/geodefb.h
> index 0214d11..cd1ce6e 100644
> --- a/drivers/video/geode/geodefb.h
> +++ b/drivers/video/geode/geodefb.h
> @@ -12,12 +12,14 @@
>  #ifndef __GEODEFB_H__
>  #define __GEODEFB_H__
>  
> -#define FB_POWER_STATE_OFF      0
> -#define FB_POWER_STATE_SUSPEND  1
> -#define FB_POWER_STATE_ON       2
> -
>  struct geodefb_info;
>  
> +/* For geodefb_par->power_state */
> +#define FB_POWER_STATE_OFF      3
> +#define FB_POWER_STATE_SUSPEND  2
> +#define FB_POWER_STATE_UNUSED   1 /* Reserved */
> +#define FB_POWER_STATE_ON       0
> +
>  struct geode_dc_ops {
>       void (*set_mode)(struct fb_info *);
>       void (*set_palette_reg)(struct fb_info *, unsigned, unsigned, unsigned, 
> unsigned);
> @@ -42,7 +44,8 @@ struct geodefb_par {
>       struct geode_dc_ops  *dc_ops;
>       struct geode_vid_ops *vid_ops;
>  
> -     int state;
> +     /* See FB_POWER_STATE_* definitions above */
> +     int power_state;
>  };
>  
>  #endif /* !__GEODEFB_H__ */
> diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
> index 3eabc53..cd43c8e 100644
> --- a/drivers/video/geode/gxfb_core.c
> +++ b/drivers/video/geode/gxfb_core.c
> @@ -383,8 +383,7 @@ static struct fb_ops gxfb_ops = {
>       .fb_fillrect    = cfb_fillrect,
>       .fb_copyarea    = cfb_copyarea,
>       .fb_imageblit   = cfb_imageblit,
> -     .fb_powerdown   = gxfb_powerdown,
> -     .fb_powerup     = gxfb_powerup,
> +     .fb_power       = gxfb_power,
>  };
>  
>  static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
> @@ -452,13 +451,13 @@ static int gxfb_suspend(struct pci_dev *pdev,  
> pm_message_t state)
>               return 0;
>  
>       if (state.event == PM_EVENT_SUSPEND) {
> -      
> +
>               acquire_console_sem();
> -             gxfb_powerdown(info);
> +             gxfb_power(info, 3);
>  
> -             par->state = FB_POWER_STATE_OFF;
> +             par->power_state = FB_POWER_STATE_OFF;
>               fb_set_suspend(info, 1);
> -             
> +
>               release_console_sem();
>       }
>  
> @@ -471,10 +470,10 @@ static int gxfb_resume(struct pci_dev *pdev)
>       struct fb_info *info = pci_get_drvdata(pdev);
>  
>       acquire_console_sem();
> -     
> +
>       /* Turn the engine completely on */
>  
> -     if (gxfb_powerup(info))
> +     if (gxfb_power(info, 0))
>         printk(KERN_ERR "gxfb:  Powerup failed\n");
>  
>       fb_set_suspend(info, 0);
> @@ -557,7 +556,7 @@ static int __init gxfb_probe(struct pci_dev *pdev,
>       gxfb_set_par(gxfb_info);
>  
>       /* We are powered up */
> -     par->state = FB_POWER_STATE_ON;
> +     par->power_state = FB_POWER_STATE_ON;
>  
>  
>       console_event_register(&gxfb_console_notifier);
> diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
> index 28d8ff3..f886efd 100644
> --- a/drivers/video/geode/lxfb.h
> +++ b/drivers/video/geode/lxfb.h
> @@ -25,8 +25,7 @@ void lx_set_mode(struct fb_info *);
>  void lx_get_gamma(struct fb_info *, unsigned int *, int);
>  void lx_set_gamma(struct fb_info *, unsigned int *, int);
>  unsigned int lx_framebuffer_size(void);
> -int lx_shutdown(struct fb_info *);
> -int lx_powerup(struct fb_info *);
> +int lx_power(struct fb_info *, int level);
>  int lx_blank_display(struct fb_info *, int);
>  void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
>                       unsigned int, unsigned int);
> diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c
> index 29197e2..b4019d5 100644
> --- a/drivers/video/geode/lxfb_core.c
> +++ b/drivers/video/geode/lxfb_core.c
> @@ -302,8 +302,7 @@ static struct fb_ops lxfb_ops = {
>       .fb_fillrect    = cfb_fillrect,
>       .fb_copyarea    = cfb_copyarea,
>       .fb_imageblit   = cfb_imageblit,
> -     .fb_powerdown   = lx_shutdown,
> -     .fb_powerup     = lx_powerup,
> +     .fb_power       = lx_power,
>  };
>  
>  static struct fb_info * __init lxfb_init_fbinfo(struct device *dev)
> @@ -356,8 +355,9 @@ static int lxfb_suspend(struct pci_dev *pdev,  
> pm_message_t state)
>  
>       if (state.event == PM_EVENT_SUSPEND) {
>  
> +             /* Turn the engine completely off */
>               acquire_console_sem();
> -             lx_shutdown(info);
> +             lx_power(info, 3);
>               fb_set_suspend(info, 1);
>               release_console_sem();
>       }
> @@ -370,11 +370,9 @@ static int lxfb_resume(struct pci_dev *pdev)
>  {
>       struct fb_info *info = pci_get_drvdata(pdev);
>  
> -     acquire_console_sem();
> -
>       /* Turn the engine completely on */
> -
> -     lx_powerup(info);
> +     acquire_console_sem();
> +     lx_power(info, 0);
>       fb_set_suspend(info, 0);
>       release_console_sem();
>  
> diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c
> index b2ecb4d..b380238 100644
> --- a/drivers/video/geode/lxfb_ops.c
> +++ b/drivers/video/geode/lxfb_ops.c
> @@ -829,33 +829,42 @@ static void lx_restore_regs(struct fb_info *info, 
> struct geoderegs *regs)
>       writel(regs->dc.r.dcfg, par->dc_regs + 0x08);
>  }
>  
> -static int lx_power_on = 1;
> +/*
> + * Level can be:
> + *  0 - fully powered on
> + *  1 - reserved/undefined
> + *  2 - power save (preserving state)
> + *  3 - fully powered off
> + */
> +static int lx_power_state = 0;
>  
> -int lx_shutdown(struct fb_info *info)
> +int lx_power(struct fb_info *info, int state)
>  {
>       struct lxfb_par *par = info->par;
>  
> -     if (lx_power_on == 0)
> -             return 0;
> -
> -     writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
> -     lx_save_regs(info, &saved_regs);
> -     lx_graphics_disable(info);
> +     if (state < 0 || state > 3)
> +             return -EINVAL;
>  
> -     lx_power_on = 0;
> -     return 0;
> -}
> +     /* Going into power save */
> +     if (state >= 2 && lx_power_state < 2)
> +             lx_graphics_disable(info);
>  
> -int lx_powerup(struct fb_info *info)
> -{
> -     struct lxfb_par *par = info->par;
> +     /* Powering down */
> +     if (state >= 3 && lx_power_state < 3) {
> +             writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
> +             lx_save_regs(info, &saved_regs);
> +     }
>  
> -     if (lx_power_on == 1)
> -             return 0;
> +     /* Restoring from power save */
> +     if (state < 3 && lx_power_state >= 3) {
> +             lx_restore_regs(info, &saved_regs);
> +             writel(0, par->dc_regs + DC_UNLOCK);
> +     }
>  
> -     lx_restore_regs(info, &saved_regs);
> -     writel(0, par->dc_regs + DC_UNLOCK);
> +     /* Powering up */
> +     if (state < 2 && lx_power_state >= 2)
> +             lx_graphics_enable(info);
>  
> -     lx_power_on = 1;
> +     lx_power_state = state;
>       return 0;
>  }
> diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c
> index e282e74..7999f05 100644
> --- a/drivers/video/geode/video_gx.c
> +++ b/drivers/video/geode/video_gx.c
> @@ -348,46 +348,46 @@ static void gx_configure_display(struct fb_info *info)
>               gx_configure_tft(info);
>  }
>  
> -int gxfb_powerdown(struct fb_info *info) 
> +int gxfb_power(struct fb_info *info, int state)
>  {
>       struct geodefb_par *par = info->par;
>  
> -     /* We're already suspended */
> -
> -     if (par->state != FB_POWER_STATE_ON)
> +     /* No state change */
> +     if (par->power_state == state)
>               return 0;
>  
> -     /* Save the registers */
> -     gx_save_regs(info, &gx_saved_regs);
> -
> -     /* Shut down the engine */
> -
> -     writel(gx_saved_regs.vp.r.vcfg & ~0x01, par->vid_regs + GX_VCFG);
> -     writel(gx_saved_regs.vp.r.dcfg & ~0x0F, par->vid_regs + GX_DCFG);
> +     /* Going into power save */
> +     if (state >= FB_POWER_STATE_SUSPEND && par->power_state < 
> FB_POWER_STATE_SUSPEND) {
> +             /* Shut down the engine */
> +             writel(gx_saved_regs.vp.r.vcfg & ~0x01, par->vid_regs + 
> GX_VCFG);
> +             writel(gx_saved_regs.vp.r.dcfg & ~0x0F, par->vid_regs + 
> GX_DCFG);
>  
> -     /* Turn off the flat panel unless we are attached to a DCON */
> -     if (!olpc_has_dcon())
> -             writel(gx_saved_regs.fp.r.pm & ~GX_FP_PM_P, par->vid_regs + 
> GX_FP_PM);
> +             /* Turn off the flat panel unless we are attached to a DCON */
> +             if (!olpc_has_dcon())
> +                     writel(gx_saved_regs.fp.r.pm & ~GX_FP_PM_P, 
> par->vid_regs + GX_FP_PM);
>  
> -     writel(0x4758, par->dc_regs + DC_UNLOCK);
> +             writel(0x4758, par->dc_regs + DC_UNLOCK);
>  
> -     writel(gx_saved_regs.dc.r.gcfg & ~0x0F,
> -            par->dc_regs + DC_GENERAL_CFG);
> +             writel(gx_saved_regs.dc.r.gcfg & ~0x0F,
> +             par->dc_regs + DC_GENERAL_CFG);
>  
> -     writel(gx_saved_regs.dc.r.dcfg & ~0x19,
> -            par->dc_regs + DC_DISPLAY_CFG);
> -     
> -     par->state = FB_POWER_STATE_SUSPEND;
> +             writel(gx_saved_regs.dc.r.dcfg & ~0x19,
> +             par->dc_regs + DC_DISPLAY_CFG);
> +     }
>  
> -     return 0;
> -}
> +     /* Powering down */
> +     if (state >= FB_POWER_STATE_OFF && par->power_state < 
> FB_POWER_STATE_OFF) {
> +             /* Save the registers */
> +             gx_save_regs(info, &gx_saved_regs);
> +     }
>  
> -int gxfb_powerup(struct fb_info *info)
> -{
> -     struct geodefb_par *par = info->par;
> -     u32 val;
> +     /* Restoring from power save */
> +     if (state < FB_POWER_STATE_OFF && par->power_state >= 
> FB_POWER_STATE_OFF) {
> +             gx_restore_regs(info, &gx_saved_regs);
> +     }
>  
> -     if (par->state == FB_POWER_STATE_SUSPEND) {
> +     if (state < FB_POWER_STATE_SUSPEND && par->power_state >= 
> FB_POWER_STATE_SUSPEND) {
> +             u32 val;
>  
>               writel(gx_saved_regs.dc.r.dcfg,
>                      par->dc_regs + DC_DISPLAY_CFG);
> @@ -402,43 +402,30 @@ int gxfb_powerup(struct fb_info *info)
>                       writel(gx_saved_regs.fp.r.pm, par->vid_regs + GX_FP_PM);
>                       mdelay(64);
>               }
> -     }
>  
> -     /* If the panel is currently on its way up, then wait up to 100ms
> -        for it */
> -     
> -     if (readl(par->vid_regs + GX_FP_PM) & 0x08) {
> -             int i;
> -             
> -             for(i = 0; i < 10; i++) {
> -                     if (readl(par->vid_regs + GX_FP_PM) & 0x01)
> -                             break;
> -
> -                     mdelay(10);
> -             }
> +             /* If the panel is currently on its way up, then wait up to 
> 100ms for it */
> +             if (readl(par->vid_regs + GX_FP_PM) & 0x08) {
> +                     int i;
>  
> -             if (i == 10) 
> -                     printk(KERN_ERR "gxfb:  Panel power up timed out\n");
> -     }
> +                     for(i = 0; i < 10; i++) {
> +                             if (readl(par->vid_regs + GX_FP_PM) & 0x01)
> +                                     break;
>  
> -     if (par->state == FB_POWER_STATE_ON)
> -             return 0;
> -     
> -     switch(par->state) {
> -     case FB_POWER_STATE_OFF:
> -             gx_restore_regs(info, &gx_saved_regs);
> -             break;
> +                             mdelay(10);
> +                     }
> +
> +                     if (i == 10)
> +                             printk(KERN_ERR "gxfb:  Panel power up timed 
> out\n");
> +             }
>  
> -     case FB_POWER_STATE_SUSPEND:
>               /* Do this because it will turn on the FIFO which will
> -                start the line count */
> +                start the line count */
>               writel(gx_saved_regs.dc.r.gcfg,
>                      par->dc_regs + DC_GENERAL_CFG);
>               writel(0x0, par->dc_regs + DC_UNLOCK);
> -             break;
>       }
>  
> -     par->state = FB_POWER_STATE_ON;
> +     par->power_state = state;
>       return 0;
>  }
>  
> diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h
> index c57b36b..f9efaa7 100644
> --- a/drivers/video/geode/video_gx.h
> +++ b/drivers/video/geode/video_gx.h
> @@ -81,8 +81,7 @@ extern struct geode_vid_ops gx_vid_ops;
>  #  define MSR_GLCP_DOTPLL_BYPASS             (0x0000000000008000ull)
>  #  define MSR_GLCP_DOTPLL_LOCK                       (0x0000000002000000ull)
>  
> -int gxfb_powerdown(struct fb_info *info);
> -int gxfb_powerup(struct fb_info *info);
> +int gxfb_power(struct fb_info *info, int state);
>  
>  void gx_set_dclk_frequency(struct fb_info *info);
>  unsigned int gx_get_dclk(struct fb_info *info);
> diff --git a/drivers/video/olpc_dcon.c b/drivers/video/olpc_dcon.c
> index 47ade47..bb421f0 100644
> --- a/drivers/video/olpc_dcon.c
> +++ b/drivers/video/olpc_dcon.c
> @@ -210,13 +210,13 @@ static void dcon_source_switch(struct work_struct *work)
>  
>               /*
>                * Ideally we'd like to disable interrupts here so that the
> -              * fb_powerup and DCON turn on happen at a known time value;
> +              * fb_power() and DCON turn on happen at a known time value;
>                * however, we can't do that right now with fb_set_suspend
>                * messing with semaphores.
>                *
>                * For now, we just hope..
>                */
> -             if (fb_powerup(fbinfo)) {
> +             if (fb_power(fbinfo, 0)) {
>                       printk(KERN_ERR "olpc-dcon:  Failed to enter CPU 
> mode\n");
>                       dcon_pending = DCON_SOURCE_DCON;
>                       return;
> @@ -250,8 +250,8 @@ static void dcon_source_switch(struct work_struct *work)
>               if (!dcon_switched)
>                       printk(KERN_ERR "olpc-dcon: Timeout entering DCON mode; 
> expect a screen glitch.\n");
>  
> -             /* Turn off the graphics engine completely */
> -             fb_powerdown(fbinfo);
> +             /* Turn off the video engine only */
> +             fb_power(fbinfo, 2);
>  
>               printk(KERN_INFO "olpc-dcon: The DCON has control\n");
>               break;
> diff --git a/include/linux/fb.h b/include/linux/fb.h
> index 5a82c83..0acbd27 100644
> --- a/include/linux/fb.h
> +++ b/include/linux/fb.h
> @@ -661,11 +661,8 @@ struct fb_ops {
>       /* restore saved state */
>       void (*fb_restore_state)(struct fb_info *info);
>  
> -     /* Shut down the graphics engine to save power */
> -     int (*fb_powerdown)(struct fb_info *info);
> -
> -     /* Power it back up */
> -     int (*fb_powerup)(struct fb_info *info);
> +     /* Change the power state of the graphics engine (0 = fully on, 3 = 
> fully off */
> +     int (*fb_power)(struct fb_info *info, int state);
>  
>       /* get capability given var */
>       void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
> diff --git a/include/linux/vt.h b/include/linux/vt.h
> index ba806e8..d8c5d65 100644
> --- a/include/linux/vt.h
> +++ b/include/linux/vt.h
> @@ -6,8 +6,8 @@
>   * resizing).
>   */
>  #define MIN_NR_CONSOLES 1       /* must be at least 1 */
> -#define MAX_NR_CONSOLES      63      /* serial lines start at 64 */
> -#define MAX_NR_USER_CONSOLES 63      /* must be root to allocate above this 
> */
> +#define MAX_NR_CONSOLES      15      /* serial lines start at 64 */
> +#define MAX_NR_USER_CONSOLES 15      /* must be root to allocate above this 
> */
>               /* Note: the ioctl VT_GETSTATE does not work for
>                  consoles 16 and higher (since it returns a short) */
>  

Ugh! What is this?  I don't think you meant this to be in here.. :)

-- 
Jordan Crouse
Systems Software Development Engineer 
Advanced Micro Devices, Inc.


_______________________________________________
Devel mailing list
[email protected]
http://lists.laptop.org/listinfo/devel

Reply via email to