diff options
author | Ville Syrjala <syrjala@sci.fi> | 2006-12-08 02:40:45 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 08:29:07 -0800 |
commit | efc08a75d3a2d449edab7d1bee312eaa591f7669 (patch) | |
tree | a22c27c69cb226dd6e1fc9dc4c82f57cd81f289e /drivers/video/aty/atyfb_base.c | |
parent | 4ec3fd71e4f5d1201cb7d2374ffdb4f328091fb4 (diff) |
[PATCH] atyfb: Improve power management
Some register were only set in aty_init() which is not called on resume. I
added the aty_resume_chip() function to reset those registers on resume.
Susped-to-ram now works on a HP Omnibook 6000 with acpi_sleep=s3_bios.
Signed-off-by: Ville Syrjala <syrjala@sci.fi>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/video/aty/atyfb_base.c')
-rw-r--r-- | drivers/video/aty/atyfb_base.c | 61 |
1 files changed, 40 insertions, 21 deletions
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index a9c73c257f3a..176f9b85cdbe 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -242,6 +242,7 @@ static int atyfb_sync(struct fb_info *info); */ static int aty_init(struct fb_info *info); +static void aty_resume_chip(struct fb_info *info); #ifdef CONFIG_ATARI static int store_video_par(char *videopar, unsigned char m64_num); #endif @@ -1971,6 +1972,7 @@ static void atyfb_palette(int enter) #if defined(CONFIG_PM) && defined(CONFIG_PCI) +#ifdef CONFIG_PPC_PMAC /* Power management routines. Those are used for PowerBook sleep. */ static int aty_power_mgmt(int sleep, struct atyfb_par *par) @@ -2027,21 +2029,13 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par) return timeout ? 0 : -EIO; } +#endif static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct fb_info *info = pci_get_drvdata(pdev); struct atyfb_par *par = (struct atyfb_par *) info->par; -#ifndef CONFIG_PPC_PMAC - /* HACK ALERT ! Once I find a proper way to say to each driver - * individually what will happen with it's PCI slot, I'll change - * that. On laptops, the AGP slot is just unclocked, so D2 is - * expected, while on desktops, the card is powered off - */ - return 0; -#endif /* CONFIG_PPC_PMAC */ - if (state.event == pdev->dev.power.power_state.event) return 0; @@ -2059,6 +2053,7 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) par->asleep = 1; par->lock_blank = 1; +#ifdef CONFIG_PPC_PMAC /* Set chip to "suspend" mode */ if (aty_power_mgmt(1, par)) { par->asleep = 0; @@ -2068,6 +2063,9 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) release_console_sem(); return -EIO; } +#else + pci_set_power_state(pdev, pci_choose_state(pdev, state)); +#endif release_console_sem(); @@ -2086,8 +2084,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev) acquire_console_sem(); +#ifdef CONFIG_PPC_PMAC if (pdev->dev.power.power_state.event == 2) aty_power_mgmt(0, par); +#else + pci_set_power_state(pdev, PCI_D0); +#endif + + aty_resume_chip(info); + par->asleep = 0; /* Restore display */ @@ -2339,7 +2344,6 @@ static int __devinit aty_init(struct fb_info *info) const char *ramname = NULL, *xtal; int gtb_memsize, has_var = 0; struct fb_var_screeninfo var; - u32 i; init_waitqueue_head(&par->vblank.wait); spin_lock_init(&par->int_lock); @@ -2470,10 +2474,10 @@ static int __devinit aty_init(struct fb_info *info) if(par->pll_ops->get_pll) par->pll_ops->get_pll(info, &saved_pll); - i = aty_ld_le32(MEM_CNTL, par); + par->mem_cntl = aty_ld_le32(MEM_CNTL, par); gtb_memsize = M64_HAS(GTB_DSP); if (gtb_memsize) - switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ + switch (par->mem_cntl & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ case MEM_SIZE_512K: info->fix.smem_len = 0x80000; break; @@ -2495,7 +2499,7 @@ static int __devinit aty_init(struct fb_info *info) default: info->fix.smem_len = 0x80000; } else - switch (i & MEM_SIZE_ALIAS) { + switch (par->mem_cntl & MEM_SIZE_ALIAS) { case MEM_SIZE_512K: info->fix.smem_len = 0x80000; break; @@ -2525,20 +2529,20 @@ static int __devinit aty_init(struct fb_info *info) if (vram) { info->fix.smem_len = vram * 1024; - i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS); + par->mem_cntl &= ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS); if (info->fix.smem_len <= 0x80000) - i |= MEM_SIZE_512K; + par->mem_cntl |= MEM_SIZE_512K; else if (info->fix.smem_len <= 0x100000) - i |= MEM_SIZE_1M; + par->mem_cntl |= MEM_SIZE_1M; else if (info->fix.smem_len <= 0x200000) - i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M; + par->mem_cntl |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M; else if (info->fix.smem_len <= 0x400000) - i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M; + par->mem_cntl |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M; else if (info->fix.smem_len <= 0x600000) - i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M; + par->mem_cntl |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M; else - i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M; - aty_st_le32(MEM_CNTL, i, par); + par->mem_cntl |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M; + aty_st_le32(MEM_CNTL, par->mem_cntl, par); } /* @@ -2584,6 +2588,8 @@ static int __devinit aty_init(struct fb_info *info) #endif if(par->pll_ops->init_pll) par->pll_ops->init_pll(info, &par->pll); + if (par->pll_ops->resume_pll) + par->pll_ops->resume_pll(info, &par->pll); /* * Last page of 8 MB (4 MB on ISA) aperture is MMIO, @@ -2755,6 +2761,19 @@ aty_init_exit: return -1; } +static void aty_resume_chip(struct fb_info *info) +{ + struct atyfb_par *par = info->par; + + aty_st_le32(MEM_CNTL, par->mem_cntl, par); + + if (par->pll_ops->resume_pll) + par->pll_ops->resume_pll(info, &par->pll); + + if (par->aux_start) + aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par); +} + #ifdef CONFIG_ATARI static int __devinit store_video_par(char *video_str, unsigned char m64_num) { |