diff options
Diffstat (limited to 'drivers/video/aty')
-rw-r--r-- | drivers/video/aty/aty128fb.c | 44 | ||||
-rw-r--r-- | drivers/video/aty/atyfb_base.c | 42 | ||||
-rw-r--r-- | drivers/video/aty/mach64_ct.c | 11 | ||||
-rw-r--r-- | drivers/video/aty/radeon_base.c | 10 | ||||
-rw-r--r-- | drivers/video/aty/radeon_i2c.c | 1 | ||||
-rw-r--r-- | drivers/video/aty/radeon_pm.c | 137 | ||||
-rw-r--r-- | drivers/video/aty/radeonfb.h | 2 |
7 files changed, 132 insertions, 115 deletions
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index db16112cf19..35e8eb02b9e 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1475,7 +1475,7 @@ static int aty128fb_set_par(struct fb_info *info) aty128_set_pll(&par->pll, par); aty128_set_fifo(&par->fifo_reg, par); - config = aty_ld_le32(CONFIG_CNTL) & ~3; + config = aty_ld_le32(CNFG_CNTL) & ~3; #if defined(__BIG_ENDIAN) if (par->crtc.bpp == 32) @@ -1484,7 +1484,7 @@ static int aty128fb_set_par(struct fb_info *info) config |= 1; /* make aperture do 16 bit swapping */ #endif - aty_st_le32(CONFIG_CNTL, config); + aty_st_le32(CNFG_CNTL, config); aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */ info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3; @@ -1853,13 +1853,14 @@ static void aty128_bl_exit(struct backlight_device *bd) * Initialisation */ -#ifdef CONFIG_PPC_PMAC +#ifdef CONFIG_PPC_PMAC__disabled static void aty128_early_resume(void *data) { struct aty128fb_par *par = data; if (try_acquire_console_sem()) return; + pci_restore_state(par->pdev); aty128_do_resume(par->pdev); release_console_sem(); } @@ -1875,7 +1876,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i u32 dac; /* Get the chip revision */ - chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; + chip_rev = (aty_ld_le32(CNFG_CNTL) >> 16) & 0x1F; strcpy(video_card, "Rage128 XX "); video_card[8] = ent->device >> 8; @@ -1907,7 +1908,14 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i /* Indicate sleep capability */ if (par->chip_gen == rage_M3) { pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1); +#if 0 /* Disable the early video resume hack for now as it's causing problems, among + * others we now rely on the PCI core restoring the config space for us, which + * isn't the case with that hack, and that code path causes various things to + * be called with interrupts off while they shouldn't. I'm leaving the code in + * as it can be useful for debugging purposes + */ pmac_set_early_video_resume(aty128_early_resume, par); +#endif } /* Find default mode */ @@ -2057,7 +2065,7 @@ static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_ /* Grab memory size from the card */ // How does this relate to the resource length from the PCI hardware? - par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; + par->vram_size = aty_ld_le32(CNFG_MEMSIZE) & 0x03FFFFFF; /* Virtualize the framebuffer */ info->screen_base = ioremap(fb_addr, par->vram_size); @@ -2365,7 +2373,6 @@ static void fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx static void aty128_set_suspend(struct aty128fb_par *par, int suspend) { u32 pmgt; - u16 pwr_command; struct pci_dev *pdev = par->pdev; if (!par->pm_reg) @@ -2374,6 +2381,8 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend) /* Set the chip into the appropriate suspend mode (we use D2, * D3 would require a complete re-initialisation of the chip, * including PCI config registers, clocks, AGP configuration, ...) + * + * For resume, the core will have already brought us back to D0 */ if (suspend) { /* Make sure CRTC2 is reset. Remove that the day we decide to @@ -2391,17 +2400,9 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend) aty_st_le32(BUS_CNTL1, 0x00000010); aty_st_le32(MEM_POWER_MISC, 0x0c830000); mdelay(100); - pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); + /* Switch PCI power management to D2 */ - pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL, - (pwr_command & ~PCI_PM_CTRL_STATE_MASK) | 2); - pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); - } else { - /* Switch back PCI power management to D0 */ - mdelay(100); - pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL, 0); - pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); - mdelay(100); + pci_set_power_state(pdev, PCI_D2); } } @@ -2410,6 +2411,12 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state) struct fb_info *info = pci_get_drvdata(pdev); struct aty128fb_par *par = info->par; + /* Because we may change PCI D state ourselves, we need to + * first save the config space content so the core can + * restore it properly on resume. + */ + pci_save_state(pdev); + /* We don't do anything but D2, for now we return 0, but * we may want to change that. How do we know if the BIOS * can properly take care of D3 ? Also, with swsusp, we @@ -2476,6 +2483,11 @@ static int aty128_do_resume(struct pci_dev *pdev) if (pdev->dev.power.power_state.event == PM_EVENT_ON) return 0; + /* PCI state will have been restored by the core, so + * we should be in D0 now with our config space fully + * restored + */ + /* Wakeup chip */ aty128_set_suspend(par, 0); par->asleep = 0; diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index cc6b470073d..1207c208a30 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -135,7 +135,7 @@ #if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT) static const u32 lt_lcd_regs[] = { - CONFIG_PANEL_LG, + CNFG_PANEL_LG, LCD_GEN_CNTL_LG, DSTN_CONTROL_LG, HFB_PITCH_ADDR_LG, @@ -446,7 +446,7 @@ static int __devinit correct_chipset(struct atyfb_par *par) par->pll_limits.ecp_max = aty_chips[i].ecp_max; par->features = aty_chips[i].features; - chip_id = aty_ld_le32(CONFIG_CHIP_ID, par); + chip_id = aty_ld_le32(CNFG_CHIP_ID, par); type = chip_id & CFG_CHIP_TYPE; rev = (chip_id & CFG_CHIP_REV) >> 24; @@ -629,7 +629,7 @@ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc) crtc->lcd_index = aty_ld_le32(LCD_INDEX, par); aty_st_le32(LCD_INDEX, crtc->lcd_index, par); } - crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par); + crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par); crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par); @@ -676,7 +676,7 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par); /* update non-shadow registers first */ - aty_st_lcd(CONFIG_PANEL, crtc->lcd_config_panel, par); + aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par); aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl & ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); @@ -858,7 +858,7 @@ static int aty_var_to_crtc(const struct fb_info *info, if (!M64_HAS(MOBIL_BUS)) crtc->lcd_index |= CRTC2_DISPLAY_DIS; - crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par) | 0x4000; + crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par) | 0x4000; crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT; crtc->lcd_gen_cntl &= @@ -1978,7 +1978,7 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par) return timeout ? 0 : -EIO; } -#endif +#endif /* CONFIG_PPC_PMAC */ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) { @@ -2002,9 +2002,15 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) par->asleep = 1; par->lock_blank = 1; + /* Because we may change PCI D state ourselves, we need to + * first save the config space content so the core can + * restore it properly on resume. + */ + pci_save_state(pdev); + #ifdef CONFIG_PPC_PMAC /* Set chip to "suspend" mode */ - if (aty_power_mgmt(1, par)) { + if (machine_is(powermac) && aty_power_mgmt(1, par)) { par->asleep = 0; par->lock_blank = 0; atyfb_blank(FB_BLANK_UNBLANK, info); @@ -2047,11 +2053,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev) acquire_console_sem(); + /* PCI state will have been restored by the core, so + * we should be in D0 now with our config space fully + * restored + */ + #ifdef CONFIG_PPC_PMAC - if (pdev->dev.power.power_state.event == 2) + if (machine_is(powermac) && + pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) aty_power_mgmt(0, par); -#else - pci_set_power_state(pdev, PCI_D0); #endif aty_resume_chip(info); @@ -2254,7 +2264,7 @@ static int __devinit aty_init(struct fb_info *info) if (!M64_HAS(INTEGRATED)) { u32 stat0; u8 dac_type, dac_subtype, clk_type; - stat0 = aty_ld_le32(CONFIG_STAT0, par); + stat0 = aty_ld_le32(CNFG_STAT0, par); par->bus_type = (stat0 >> 0) & 0x07; par->ram_type = (stat0 >> 3) & 0x07; ramname = aty_gx_ram[par->ram_type]; @@ -2324,7 +2334,7 @@ static int __devinit aty_init(struct fb_info *info) par->dac_ops = &aty_dac_ct; par->pll_ops = &aty_pll_ct; par->bus_type = PCI; - par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07); + par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07); ramname = aty_ct_ram[par->ram_type]; /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM) @@ -2433,7 +2443,7 @@ static int __devinit aty_init(struct fb_info *info) } if (M64_HAS(MAGIC_VRAM_SIZE)) { - if (aty_ld_le32(CONFIG_STAT1, par) & 0x40000000) + if (aty_ld_le32(CNFG_STAT1, par) & 0x40000000) info->fix.smem_len += 0x400000; } @@ -2946,7 +2956,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, * Fix PROMs idea of MEM_CNTL settings... */ mem = aty_ld_le32(MEM_CNTL, par); - chip_id = aty_ld_le32(CONFIG_CHIP_ID, par); + chip_id = aty_ld_le32(CNFG_CHIP_ID, par); if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) { switch (mem & 0x0f) { case 3: @@ -2964,7 +2974,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, default: break; } - if ((aty_ld_le32(CONFIG_STAT0, par) & 7) >= SDRAM) + if ((aty_ld_le32(CNFG_STAT0, par) & 7) >= SDRAM) mem &= ~(0x00700000); } mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */ @@ -3572,7 +3582,7 @@ static int __init atyfb_atari_probe(void) } /* Fake pci_id for correct_chipset() */ - switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) { + switch (aty_ld_le32(CNFG_CHIP_ID, par) & CFG_CHIP_TYPE) { case 0x00d7: par->pci_id = PCI_CHIP_MACH64GX; break; diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c index c50c7cf26fe..2745b853948 100644 --- a/drivers/video/aty/mach64_ct.c +++ b/drivers/video/aty/mach64_ct.c @@ -8,6 +8,9 @@ #include <asm/io.h> #include <video/mach64.h> #include "atyfb.h" +#ifdef CONFIG_PPC +#include <asm/machdep.h> +#endif #undef DEBUG @@ -536,6 +539,14 @@ static int __devinit aty_init_pll_ct(const struct fb_info *info, pll->ct.xclk_post_div_real = postdividers[xpost_div]; pll->ct.mclk_fb_div = q * pll->ct.xclk_post_div_real / 8; +#ifdef CONFIG_PPC + if (machine_is(powermac)) { + /* Override PLL_EXT_CNTL & 0x07. */ + pll->ct.xclk_post_div = xpost_div; + pll->ct.xclk_ref_div = 1; + } +#endif + #ifdef DEBUG pllmclk = (1000000 * pll->ct.mclk_fb_mult * pll->ct.mclk_fb_div) / (par->ref_clk_per * pll->ct.pll_ref_div); diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index d0f1a7fc2c9..16bb7e3c031 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -1936,8 +1936,8 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo) OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B); mdelay(100); - aper_base = INREG(CONFIG_APER_0_BASE); - aper_size = INREG(CONFIG_APER_SIZE); + aper_base = INREG(CNFG_APER_0_BASE); + aper_size = INREG(CNFG_APER_SIZE); #ifdef SET_MC_FB_FROM_APERTURE /* Set framebuffer to be at the same address as set in PCI BAR */ @@ -2024,11 +2024,11 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo) ~CRTC_H_CUTOFF_ACTIVE_EN); } } else { - tmp = INREG(CONFIG_MEMSIZE); + tmp = INREG(CNFG_MEMSIZE); } /* mem size is bits [28:0], mask off the rest */ - rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK; + rinfo->video_ram = tmp & CNFG_MEMSIZE_MASK; /* * Hack to get around some busted production M6's @@ -2228,7 +2228,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev, */ rinfo->errata = 0; if (rinfo->family == CHIP_FAMILY_R300 && - (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) + (INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) == CFG_ATI_REV_A11) rinfo->errata |= CHIP_ERRATA_R300_CG; diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c index 2c5567175dc..359fc64e761 100644 --- a/drivers/video/aty/radeon_i2c.c +++ b/drivers/video/aty/radeon_i2c.c @@ -72,7 +72,6 @@ static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name) snprintf(chan->adapter.name, sizeof(chan->adapter.name), "radeonfb %s", name); chan->adapter.owner = THIS_MODULE; - chan->adapter.id = I2C_HW_B_RADEON; chan->adapter.algo_data = &chan->algo; chan->adapter.dev.parent = &chan->rinfo->pdev->dev; chan->algo.setsda = radeon_gpio_setsda; diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 675abdafc2d..c6d7cc76516 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -333,7 +333,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) if (!rinfo->has_CRTC2) { tmp = INPLL(pllSCLK_CNTL); - if ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13) + if ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13) tmp &= ~(SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_RB); tmp &= ~(SCLK_CNTL__FORCE_HDP | SCLK_CNTL__FORCE_DISP1 | SCLK_CNTL__FORCE_TOP | SCLK_CNTL__FORCE_SE | @@ -468,9 +468,9 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/ if ((rinfo->family == CHIP_FAMILY_RV250 && - ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) || + ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) || ((rinfo->family == CHIP_FAMILY_RV100) && - ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) { + ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) { tmp |= SCLK_CNTL__FORCE_CP; tmp |= SCLK_CNTL__FORCE_VIP; } @@ -486,7 +486,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) /* RV200::A11 A12 RV250::A11 A12 */ if (((rinfo->family == CHIP_FAMILY_RV200) || (rinfo->family == CHIP_FAMILY_RV250)) && - ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) + ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) tmp |= SCLK_MORE_CNTL__FORCEON; OUTPLL(pllSCLK_MORE_CNTL, tmp); @@ -497,7 +497,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) /* RV200::A11 A12, RV250::A11 A12 */ if (((rinfo->family == CHIP_FAMILY_RV200) || (rinfo->family == CHIP_FAMILY_RV250)) && - ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) { + ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) { tmp = INPLL(pllPLL_PWRMGT_CNTL); tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE; OUTPLL(pllPLL_PWRMGT_CNTL, tmp); @@ -702,7 +702,7 @@ static void radeon_pm_restore_regs(struct radeonfb_info *rinfo) OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]); OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]); OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]); - OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); + OUTREG(CNFG_MEMSIZE, rinfo->video_ram); OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]); OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]); @@ -1723,7 +1723,7 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo) OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]); OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]); OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]); - OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); + OUTREG(CNFG_MEMSIZE, rinfo->video_ram); OUTREG(BUS_CNTL, rinfo->save_regs[36]); OUTREG(BUS_CNTL1, rinfo->save_regs[14]); OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]); @@ -1961,7 +1961,7 @@ static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo) OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/); OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/); OUTREG(MC_IND_INDEX, 0); - OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); + OUTREG(CNFG_MEMSIZE, rinfo->video_ram); mdelay(20); } @@ -2361,7 +2361,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249); OUTREG(MC_IND_INDEX, 0); - OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); + OUTREG(CNFG_MEMSIZE, rinfo->video_ram); radeon_pm_full_reset_sdram(rinfo); @@ -2507,11 +2507,28 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) #endif /* CONFIG_PPC_OF */ -static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) +static void radeonfb_whack_power_state(struct radeonfb_info *rinfo, pci_power_t state) { u16 pwr_cmd; + + for (;;) { + pci_read_config_word(rinfo->pdev, + rinfo->pm_reg+PCI_PM_CTRL, + &pwr_cmd); + if (pwr_cmd & 2) + break; + pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2; + pci_write_config_word(rinfo->pdev, + rinfo->pm_reg+PCI_PM_CTRL, + pwr_cmd); + msleep(500); + } + rinfo->pdev->current_state = state; +} + +static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) +{ u32 tmp; - int i; if (!rinfo->pm_reg) return; @@ -2557,32 +2574,19 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) } } - for (i = 0; i < 64; ++i) - pci_read_config_dword(rinfo->pdev, i * 4, - &rinfo->cfg_save[i]); - /* Switch PCI power management to D2. */ pci_disable_device(rinfo->pdev); - for (;;) { - pci_read_config_word( - rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, - &pwr_cmd); - if (pwr_cmd & 2) - break; - pci_write_config_word( - rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, - (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2); - mdelay(500); - } + pci_save_state(rinfo->pdev); + /* The chip seems to need us to whack the PM register + * repeatedly until it sticks. We do that -prior- to + * calling pci_set_power_state() + */ + radeonfb_whack_power_state(rinfo, PCI_D2); + pci_set_power_state(rinfo->pdev, PCI_D2); } else { printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", pci_name(rinfo->pdev)); - /* Switch back PCI powermanagment to D0 */ - mdelay(200); - pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0); - mdelay(500); - if (rinfo->family <= CHIP_FAMILY_RV250) { /* Reset the SDRAM controller */ radeon_pm_full_reset_sdram(rinfo); @@ -2598,37 +2602,10 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) } } -static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo) -{ - int i; - static u32 radeon_cfg_after_resume[64]; - - for (i = 0; i < 64; ++i) - pci_read_config_dword(rinfo->pdev, i * 4, - &radeon_cfg_after_resume[i]); - - if (radeon_cfg_after_resume[PCI_BASE_ADDRESS_0/4] - == rinfo->cfg_save[PCI_BASE_ADDRESS_0/4]) - return 0; /* assume everything is ok */ - - for (i = PCI_BASE_ADDRESS_0/4; i < 64; ++i) { - if (radeon_cfg_after_resume[i] != rinfo->cfg_save[i]) - pci_write_config_dword(rinfo->pdev, i * 4, - rinfo->cfg_save[i]); - } - pci_write_config_word(rinfo->pdev, PCI_CACHE_LINE_SIZE, - rinfo->cfg_save[PCI_CACHE_LINE_SIZE/4]); - pci_write_config_word(rinfo->pdev, PCI_COMMAND, - rinfo->cfg_save[PCI_COMMAND/4]); - return 1; -} - - int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) { struct fb_info *info = pci_get_drvdata(pdev); struct radeonfb_info *rinfo = info->par; - int i; if (mesg.event == pdev->dev.power.power_state.event) return 0; @@ -2674,6 +2651,11 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) pmac_suspend_agp_for_card(pdev); #endif /* CONFIG_PPC_PMAC */ + /* It's unclear whether or when the generic code will do that, so let's + * do it ourselves. We save state before we do any power management + */ + pci_save_state(pdev); + /* If we support wakeup from poweroff, we save all regs we can including cfg * space */ @@ -2698,9 +2680,6 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) mdelay(20); OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON)); } - // FIXME: Use PCI layer - for (i = 0; i < 64; ++i) - pci_read_config_dword(pdev, i * 4, &rinfo->cfg_save[i]); pci_disable_device(pdev); } /* If we support D2, we go to it (should be fixed later with a flag forcing @@ -2717,6 +2696,13 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) return 0; } +static int radeon_check_power_loss(struct radeonfb_info *rinfo) +{ + return rinfo->save_regs[4] != INPLL(CLK_PIN_CNTL) || + rinfo->save_regs[2] != INPLL(MCLK_CNTL) || + rinfo->save_regs[3] != INPLL(SCLK_CNTL); +} + int radeonfb_pci_resume(struct pci_dev *pdev) { struct fb_info *info = pci_get_drvdata(pdev); @@ -2735,20 +2721,13 @@ int radeonfb_pci_resume(struct pci_dev *pdev) printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n", pci_name(pdev), pdev->dev.power.power_state.event); - - if (pci_enable_device(pdev)) { - rc = -ENODEV; - printk(KERN_ERR "radeonfb (%s): can't enable PCI device !\n", - pci_name(pdev)); - goto bail; - } - pci_set_master(pdev); - + /* PCI state will have been restored by the core, so + * we should be in D0 now with our config space fully + * restored + */ if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { - /* Wakeup chip. Check from config space if we were powered off - * (todo: additionally, check CLK_PIN_CNTL too) - */ - if ((rinfo->pm_mode & radeon_pm_off) && radeon_restore_pci_cfg(rinfo)) { + /* Wakeup chip */ + if ((rinfo->pm_mode & radeon_pm_off) && radeon_check_power_loss(rinfo)) { if (rinfo->reinit_func != NULL) rinfo->reinit_func(rinfo); else { @@ -2807,12 +2786,13 @@ int radeonfb_pci_resume(struct pci_dev *pdev) return rc; } -#ifdef CONFIG_PPC_OF +#ifdef CONFIG_PPC_OF__disabled static void radeonfb_early_resume(void *data) { struct radeonfb_info *rinfo = data; rinfo->no_schedule = 1; + pci_restore_state(rinfo->pdev); radeonfb_pci_resume(rinfo->pdev); rinfo->no_schedule = 0; } @@ -2879,7 +2859,14 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis */ if (rinfo->pm_mode != radeon_pm_none) { pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, rinfo->of_node, 0, 1); +#if 0 /* Disable the early video resume hack for now as it's causing problems, among + * others we now rely on the PCI core restoring the config space for us, which + * isn't the case with that hack, and that code path causes various things to + * be called with interrupts off while they shouldn't. I'm leaving the code in + * as it can be useful for debugging purposes + */ pmac_set_early_video_resume(radeonfb_early_resume, rinfo); +#endif } #if 0 diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 3ea1b00fdd2..7351e66c7f5 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -361,8 +361,6 @@ struct radeonfb_info { #ifdef CONFIG_FB_RADEON_I2C struct radeon_i2c_chan i2c[4]; #endif - - u32 cfg_save[64]; }; |