diff options
author | Ville Syrjala <syrjala@sci.fi> | 2006-12-08 05:40:45 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 11:29:07 -0500 |
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); | |||
242 | */ | 242 | */ |
243 | 243 | ||
244 | static int aty_init(struct fb_info *info); | 244 | static int aty_init(struct fb_info *info); |
245 | static void aty_resume_chip(struct fb_info *info); | ||
245 | #ifdef CONFIG_ATARI | 246 | #ifdef CONFIG_ATARI |
246 | static int store_video_par(char *videopar, unsigned char m64_num); | 247 | static int store_video_par(char *videopar, unsigned char m64_num); |
247 | #endif | 248 | #endif |
@@ -1971,6 +1972,7 @@ static void atyfb_palette(int enter) | |||
1971 | 1972 | ||
1972 | #if defined(CONFIG_PM) && defined(CONFIG_PCI) | 1973 | #if defined(CONFIG_PM) && defined(CONFIG_PCI) |
1973 | 1974 | ||
1975 | #ifdef CONFIG_PPC_PMAC | ||
1974 | /* Power management routines. Those are used for PowerBook sleep. | 1976 | /* Power management routines. Those are used for PowerBook sleep. |
1975 | */ | 1977 | */ |
1976 | static int aty_power_mgmt(int sleep, struct atyfb_par *par) | 1978 | 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) | |||
2027 | 2029 | ||
2028 | return timeout ? 0 : -EIO; | 2030 | return timeout ? 0 : -EIO; |
2029 | } | 2031 | } |
2032 | #endif | ||
2030 | 2033 | ||
2031 | static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 2034 | static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) |
2032 | { | 2035 | { |
2033 | struct fb_info *info = pci_get_drvdata(pdev); | 2036 | struct fb_info *info = pci_get_drvdata(pdev); |
2034 | struct atyfb_par *par = (struct atyfb_par *) info->par; | 2037 | struct atyfb_par *par = (struct atyfb_par *) info->par; |
2035 | 2038 | ||
2036 | #ifndef CONFIG_PPC_PMAC | ||
2037 | /* HACK ALERT ! Once I find a proper way to say to each driver | ||
2038 | * individually what will happen with it's PCI slot, I'll change | ||
2039 | * that. On laptops, the AGP slot is just unclocked, so D2 is | ||
2040 | * expected, while on desktops, the card is powered off | ||
2041 | */ | ||
2042 | return 0; | ||
2043 | #endif /* CONFIG_PPC_PMAC */ | ||
2044 | |||
2045 | if (state.event == pdev->dev.power.power_state.event) | 2039 | if (state.event == pdev->dev.power.power_state.event) |
2046 | return 0; | 2040 | return 0; |
2047 | 2041 | ||
@@ -2059,6 +2053,7 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2059 | par->asleep = 1; | 2053 | par->asleep = 1; |
2060 | par->lock_blank = 1; | 2054 | par->lock_blank = 1; |
2061 | 2055 | ||
2056 | #ifdef CONFIG_PPC_PMAC | ||
2062 | /* Set chip to "suspend" mode */ | 2057 | /* Set chip to "suspend" mode */ |
2063 | if (aty_power_mgmt(1, par)) { | 2058 | if (aty_power_mgmt(1, par)) { |
2064 | par->asleep = 0; | 2059 | par->asleep = 0; |
@@ -2068,6 +2063,9 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2068 | release_console_sem(); | 2063 | release_console_sem(); |
2069 | return -EIO; | 2064 | return -EIO; |
2070 | } | 2065 | } |
2066 | #else | ||
2067 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
2068 | #endif | ||
2071 | 2069 | ||
2072 | release_console_sem(); | 2070 | release_console_sem(); |
2073 | 2071 | ||
@@ -2086,8 +2084,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev) | |||
2086 | 2084 | ||
2087 | acquire_console_sem(); | 2085 | acquire_console_sem(); |
2088 | 2086 | ||
2087 | #ifdef CONFIG_PPC_PMAC | ||
2089 | if (pdev->dev.power.power_state.event == 2) | 2088 | if (pdev->dev.power.power_state.event == 2) |
2090 | aty_power_mgmt(0, par); | 2089 | aty_power_mgmt(0, par); |
2090 | #else | ||
2091 | pci_set_power_state(pdev, PCI_D0); | ||
2092 | #endif | ||
2093 | |||
2094 | aty_resume_chip(info); | ||
2095 | |||
2091 | par->asleep = 0; | 2096 | par->asleep = 0; |
2092 | 2097 | ||
2093 | /* Restore display */ | 2098 | /* Restore display */ |
@@ -2339,7 +2344,6 @@ static int __devinit aty_init(struct fb_info *info) | |||
2339 | const char *ramname = NULL, *xtal; | 2344 | const char *ramname = NULL, *xtal; |
2340 | int gtb_memsize, has_var = 0; | 2345 | int gtb_memsize, has_var = 0; |
2341 | struct fb_var_screeninfo var; | 2346 | struct fb_var_screeninfo var; |
2342 | u32 i; | ||
2343 | 2347 | ||
2344 | init_waitqueue_head(&par->vblank.wait); | 2348 | init_waitqueue_head(&par->vblank.wait); |
2345 | spin_lock_init(&par->int_lock); | 2349 | spin_lock_init(&par->int_lock); |
@@ -2470,10 +2474,10 @@ static int __devinit aty_init(struct fb_info *info) | |||
2470 | if(par->pll_ops->get_pll) | 2474 | if(par->pll_ops->get_pll) |
2471 | par->pll_ops->get_pll(info, &saved_pll); | 2475 | par->pll_ops->get_pll(info, &saved_pll); |
2472 | 2476 | ||
2473 | i = aty_ld_le32(MEM_CNTL, par); | 2477 | par->mem_cntl = aty_ld_le32(MEM_CNTL, par); |
2474 | gtb_memsize = M64_HAS(GTB_DSP); | 2478 | gtb_memsize = M64_HAS(GTB_DSP); |
2475 | if (gtb_memsize) | 2479 | if (gtb_memsize) |
2476 | switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ | 2480 | switch (par->mem_cntl & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ |
2477 | case MEM_SIZE_512K: | 2481 | case MEM_SIZE_512K: |
2478 | info->fix.smem_len = 0x80000; | 2482 | info->fix.smem_len = 0x80000; |
2479 | break; | 2483 | break; |
@@ -2495,7 +2499,7 @@ static int __devinit aty_init(struct fb_info *info) | |||
2495 | default: | 2499 | default: |
2496 | info->fix.smem_len = 0x80000; | 2500 | info->fix.smem_len = 0x80000; |
2497 | } else | 2501 | } else |
2498 | switch (i & MEM_SIZE_ALIAS) { | 2502 | switch (par->mem_cntl & MEM_SIZE_ALIAS) { |
2499 | case MEM_SIZE_512K: | 2503 | case MEM_SIZE_512K: |
2500 | info->fix.smem_len = 0x80000; | 2504 | info->fix.smem_len = 0x80000; |
2501 | break; | 2505 | break; |
@@ -2525,20 +2529,20 @@ static int __devinit aty_init(struct fb_info *info) | |||
2525 | 2529 | ||
2526 | if (vram) { | 2530 | if (vram) { |
2527 | info->fix.smem_len = vram * 1024; | 2531 | info->fix.smem_len = vram * 1024; |
2528 | i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS); | 2532 | par->mem_cntl &= ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS); |
2529 | if (info->fix.smem_len <= 0x80000) | 2533 | if (info->fix.smem_len <= 0x80000) |
2530 | i |= MEM_SIZE_512K; | 2534 | par->mem_cntl |= MEM_SIZE_512K; |
2531 | else if (info->fix.smem_len <= 0x100000) | 2535 | else if (info->fix.smem_len <= 0x100000) |
2532 | i |= MEM_SIZE_1M; | 2536 | par->mem_cntl |= MEM_SIZE_1M; |
2533 | else if (info->fix.smem_len <= 0x200000) | 2537 | else if (info->fix.smem_len <= 0x200000) |
2534 | i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M; | 2538 | par->mem_cntl |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M; |
2535 | else if (info->fix.smem_len <= 0x400000) | 2539 | else if (info->fix.smem_len <= 0x400000) |
2536 | i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M; | 2540 | par->mem_cntl |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M; |
2537 | else if (info->fix.smem_len <= 0x600000) | 2541 | else if (info->fix.smem_len <= 0x600000) |
2538 | i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M; | 2542 | par->mem_cntl |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M; |
2539 | else | 2543 | else |
2540 | i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M; | 2544 | par->mem_cntl |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M; |
2541 | aty_st_le32(MEM_CNTL, i, par); | 2545 | aty_st_le32(MEM_CNTL, par->mem_cntl, par); |
2542 | } | 2546 | } |
2543 | 2547 | ||
2544 | /* | 2548 | /* |
@@ -2584,6 +2588,8 @@ static int __devinit aty_init(struct fb_info *info) | |||
2584 | #endif | 2588 | #endif |
2585 | if(par->pll_ops->init_pll) | 2589 | if(par->pll_ops->init_pll) |
2586 | par->pll_ops->init_pll(info, &par->pll); | 2590 | par->pll_ops->init_pll(info, &par->pll); |
2591 | if (par->pll_ops->resume_pll) | ||
2592 | par->pll_ops->resume_pll(info, &par->pll); | ||
2587 | 2593 | ||
2588 | /* | 2594 | /* |
2589 | * Last page of 8 MB (4 MB on ISA) aperture is MMIO, | 2595 | * Last page of 8 MB (4 MB on ISA) aperture is MMIO, |
@@ -2755,6 +2761,19 @@ aty_init_exit: | |||
2755 | return -1; | 2761 | return -1; |
2756 | } | 2762 | } |
2757 | 2763 | ||
2764 | static void aty_resume_chip(struct fb_info *info) | ||
2765 | { | ||
2766 | struct atyfb_par *par = info->par; | ||
2767 | |||
2768 | aty_st_le32(MEM_CNTL, par->mem_cntl, par); | ||
2769 | |||
2770 | if (par->pll_ops->resume_pll) | ||
2771 | par->pll_ops->resume_pll(info, &par->pll); | ||
2772 | |||
2773 | if (par->aux_start) | ||
2774 | aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par); | ||
2775 | } | ||
2776 | |||
2758 | #ifdef CONFIG_ATARI | 2777 | #ifdef CONFIG_ATARI |
2759 | static int __devinit store_video_par(char *video_str, unsigned char m64_num) | 2778 | static int __devinit store_video_par(char *video_str, unsigned char m64_num) |
2760 | { | 2779 | { |