|
@@ -2509,9 +2509,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
|
|
|
|
|
|
static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
|
|
|
{
|
|
|
- u16 pwr_cmd;
|
|
|
u32 tmp;
|
|
|
- int i;
|
|
|
|
|
|
if (!rinfo->pm_reg)
|
|
|
return;
|
|
@@ -2557,32 +2555,14 @@ 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);
|
|
|
+ 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 +2578,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 +2627,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 +2656,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 +2672,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 +2697,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 {
|