aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/aty/mach64_ct.c
diff options
context:
space:
mode:
authorVille Syrjala <syrjala@sci.fi>2006-12-08 05:40:45 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-08 11:29:07 -0500
commitefc08a75d3a2d449edab7d1bee312eaa591f7669 (patch)
treea22c27c69cb226dd6e1fc9dc4c82f57cd81f289e /drivers/video/aty/mach64_ct.c
parent4ec3fd71e4f5d1201cb7d2374ffdb4f328091fb4 (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/mach64_ct.c')
-rw-r--r--drivers/video/aty/mach64_ct.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c
index 10232cc2dc76..f3b487b8710b 100644
--- a/drivers/video/aty/mach64_ct.c
+++ b/drivers/video/aty/mach64_ct.c
@@ -398,8 +398,8 @@ static int __devinit aty_init_pll_ct(const struct fb_info *info,
398 union aty_pll *pll) 398 union aty_pll *pll)
399{ 399{
400 struct atyfb_par *par = (struct atyfb_par *) info->par; 400 struct atyfb_par *par = (struct atyfb_par *) info->par;
401 u8 mpost_div, xpost_div, sclk_post_div_real, sclk_fb_div, spll_cntl2; 401 u8 mpost_div, xpost_div, sclk_post_div_real;
402 u32 q, i, memcntl, trp; 402 u32 q, memcntl, trp;
403 u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off; 403 u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off;
404#ifdef DEBUG 404#ifdef DEBUG
405 int pllmclk, pllsclk; 405 int pllmclk, pllsclk;
@@ -575,14 +575,30 @@ static int __devinit aty_init_pll_ct(const struct fb_info *info,
575 mpost_div += (q < 32*8); 575 mpost_div += (q < 32*8);
576 } 576 }
577 sclk_post_div_real = postdividers[mpost_div]; 577 sclk_post_div_real = postdividers[mpost_div];
578 sclk_fb_div = q * sclk_post_div_real / 8; 578 pll->ct.sclk_fb_div = q * sclk_post_div_real / 8;
579 spll_cntl2 = mpost_div << 4; 579 pll->ct.spll_cntl2 = mpost_div << 4;
580#ifdef DEBUG 580#ifdef DEBUG
581 pllsclk = (1000000 * 2 * sclk_fb_div) / 581 pllsclk = (1000000 * 2 * pll->ct.sclk_fb_div) /
582 (par->ref_clk_per * pll->ct.pll_ref_div); 582 (par->ref_clk_per * pll->ct.pll_ref_div);
583 printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n", 583 printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n",
584 __FUNCTION__, pllsclk, pllsclk / sclk_post_div_real); 584 __FUNCTION__, pllsclk, pllsclk / sclk_post_div_real);
585#endif 585#endif
586 }
587
588 /* Disable the extra precision pixel clock controls since we do not use them. */
589 pll->ct.ext_vpll_cntl = aty_ld_pll_ct(EXT_VPLL_CNTL, par);
590 pll->ct.ext_vpll_cntl &= ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC);
591
592 return 0;
593}
594
595static void aty_resume_pll_ct(const struct fb_info *info,
596 union aty_pll *pll)
597{
598 struct atyfb_par *par = info->par;
599
600 if (par->mclk_per != par->xclk_per) {
601 int i;
586 /* 602 /*
587 * This disables the sclk, crashes the computer as reported: 603 * This disables the sclk, crashes the computer as reported:
588 * aty_st_pll_ct(SPLL_CNTL2, 3, info); 604 * aty_st_pll_ct(SPLL_CNTL2, 3, info);
@@ -590,8 +606,8 @@ static int __devinit aty_init_pll_ct(const struct fb_info *info,
590 * So it seems the sclk must be enabled before it is used; 606 * So it seems the sclk must be enabled before it is used;
591 * so PLL_GEN_CNTL must be programmed *after* the sclk. 607 * so PLL_GEN_CNTL must be programmed *after* the sclk.
592 */ 608 */
593 aty_st_pll_ct(SCLK_FB_DIV, sclk_fb_div, par); 609 aty_st_pll_ct(SCLK_FB_DIV, pll->ct.sclk_fb_div, par);
594 aty_st_pll_ct(SPLL_CNTL2, spll_cntl2, par); 610 aty_st_pll_ct(SPLL_CNTL2, pll->ct.spll_cntl2, par);
595 /* 611 /*
596 * The sclk has been started. However, I believe the first clock 612 * The sclk has been started. However, I believe the first clock
597 * ticks it generates are not very stable. Hope this primitive loop 613 * ticks it generates are not very stable. Hope this primitive loop
@@ -605,11 +621,7 @@ static int __devinit aty_init_pll_ct(const struct fb_info *info,
605 aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par); 621 aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
606 aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par); 622 aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par);
607 aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par); 623 aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par);
608 /* Disable the extra precision pixel clock controls since we do not use them. */ 624 aty_st_pll_ct(EXT_VPLL_CNTL, pll->ct.ext_vpll_cntl, par);
609 aty_st_pll_ct(EXT_VPLL_CNTL, aty_ld_pll_ct(EXT_VPLL_CNTL, par) &
610 ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC), par);
611
612 return 0;
613} 625}
614 626
615static int dummy(void) 627static int dummy(void)
@@ -626,5 +638,6 @@ const struct aty_pll_ops aty_pll_ct = {
626 .pll_to_var = aty_pll_to_var_ct, 638 .pll_to_var = aty_pll_to_var_ct,
627 .set_pll = aty_set_pll_ct, 639 .set_pll = aty_set_pll_ct,
628 .get_pll = aty_get_pll_ct, 640 .get_pll = aty_get_pll_ct,
629 .init_pll = aty_init_pll_ct 641 .init_pll = aty_init_pll_ct,
642 .resume_pll = aty_resume_pll_ct,
630}; 643};