diff options
| -rw-r--r-- | drivers/video/aty/radeon_pm.c | 85 | ||||
| -rw-r--r-- | drivers/video/aty/radeonfb.h | 2 |
2 files changed, 20 insertions, 67 deletions
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index c4ac2a032fcb..ca5f0dc28546 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c | |||
| @@ -2509,9 +2509,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) | |||
| 2509 | 2509 | ||
| 2510 | static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) | 2510 | static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) |
| 2511 | { | 2511 | { |
| 2512 | u16 pwr_cmd; | ||
| 2513 | u32 tmp; | 2512 | u32 tmp; |
| 2514 | int i; | ||
| 2515 | 2513 | ||
| 2516 | if (!rinfo->pm_reg) | 2514 | if (!rinfo->pm_reg) |
| 2517 | return; | 2515 | return; |
| @@ -2557,32 +2555,14 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) | |||
| 2557 | } | 2555 | } |
| 2558 | } | 2556 | } |
| 2559 | 2557 | ||
| 2560 | for (i = 0; i < 64; ++i) | ||
| 2561 | pci_read_config_dword(rinfo->pdev, i * 4, | ||
| 2562 | &rinfo->cfg_save[i]); | ||
| 2563 | |||
| 2564 | /* Switch PCI power management to D2. */ | 2558 | /* Switch PCI power management to D2. */ |
| 2565 | pci_disable_device(rinfo->pdev); | 2559 | pci_disable_device(rinfo->pdev); |
| 2566 | for (;;) { | 2560 | pci_save_state(rinfo->pdev); |
| 2567 | pci_read_config_word( | 2561 | pci_set_power_state(rinfo->pdev, PCI_D2); |
| 2568 | rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, | ||
| 2569 | &pwr_cmd); | ||
| 2570 | if (pwr_cmd & 2) | ||
| 2571 | break; | ||
| 2572 | pci_write_config_word( | ||
| 2573 | rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, | ||
| 2574 | (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2); | ||
| 2575 | mdelay(500); | ||
| 2576 | } | ||
| 2577 | } else { | 2562 | } else { |
| 2578 | printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", | 2563 | printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", |
| 2579 | pci_name(rinfo->pdev)); | 2564 | pci_name(rinfo->pdev)); |
| 2580 | 2565 | ||
| 2581 | /* Switch back PCI powermanagment to D0 */ | ||
| 2582 | mdelay(200); | ||
| 2583 | pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0); | ||
| 2584 | mdelay(500); | ||
| 2585 | |||
| 2586 | if (rinfo->family <= CHIP_FAMILY_RV250) { | 2566 | if (rinfo->family <= CHIP_FAMILY_RV250) { |
| 2587 | /* Reset the SDRAM controller */ | 2567 | /* Reset the SDRAM controller */ |
| 2588 | radeon_pm_full_reset_sdram(rinfo); | 2568 | radeon_pm_full_reset_sdram(rinfo); |
| @@ -2598,37 +2578,10 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) | |||
| 2598 | } | 2578 | } |
| 2599 | } | 2579 | } |
| 2600 | 2580 | ||
| 2601 | static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo) | ||
| 2602 | { | ||
| 2603 | int i; | ||
| 2604 | static u32 radeon_cfg_after_resume[64]; | ||
| 2605 | |||
| 2606 | for (i = 0; i < 64; ++i) | ||
| 2607 | pci_read_config_dword(rinfo->pdev, i * 4, | ||
| 2608 | &radeon_cfg_after_resume[i]); | ||
| 2609 | |||
| 2610 | if (radeon_cfg_after_resume[PCI_BASE_ADDRESS_0/4] | ||
| 2611 | == rinfo->cfg_save[PCI_BASE_ADDRESS_0/4]) | ||
| 2612 | return 0; /* assume everything is ok */ | ||
| 2613 | |||
| 2614 | for (i = PCI_BASE_ADDRESS_0/4; i < 64; ++i) { | ||
| 2615 | if (radeon_cfg_after_resume[i] != rinfo->cfg_save[i]) | ||
| 2616 | pci_write_config_dword(rinfo->pdev, i * 4, | ||
| 2617 | rinfo->cfg_save[i]); | ||
| 2618 | } | ||
| 2619 | pci_write_config_word(rinfo->pdev, PCI_CACHE_LINE_SIZE, | ||
| 2620 | rinfo->cfg_save[PCI_CACHE_LINE_SIZE/4]); | ||
| 2621 | pci_write_config_word(rinfo->pdev, PCI_COMMAND, | ||
| 2622 | rinfo->cfg_save[PCI_COMMAND/4]); | ||
| 2623 | return 1; | ||
| 2624 | } | ||
| 2625 | |||
| 2626 | |||
| 2627 | int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) | 2581 | int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) |
| 2628 | { | 2582 | { |
| 2629 | struct fb_info *info = pci_get_drvdata(pdev); | 2583 | struct fb_info *info = pci_get_drvdata(pdev); |
| 2630 | struct radeonfb_info *rinfo = info->par; | 2584 | struct radeonfb_info *rinfo = info->par; |
| 2631 | int i; | ||
| 2632 | 2585 | ||
| 2633 | if (mesg.event == pdev->dev.power.power_state.event) | 2586 | if (mesg.event == pdev->dev.power.power_state.event) |
| 2634 | return 0; | 2587 | return 0; |
| @@ -2674,6 +2627,11 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) | |||
| 2674 | pmac_suspend_agp_for_card(pdev); | 2627 | pmac_suspend_agp_for_card(pdev); |
| 2675 | #endif /* CONFIG_PPC_PMAC */ | 2628 | #endif /* CONFIG_PPC_PMAC */ |
| 2676 | 2629 | ||
| 2630 | /* It's unclear whether or when the generic code will do that, so let's | ||
| 2631 | * do it ourselves. We save state before we do any power management | ||
| 2632 | */ | ||
| 2633 | pci_save_state(pdev); | ||
| 2634 | |||
| 2677 | /* If we support wakeup from poweroff, we save all regs we can including cfg | 2635 | /* If we support wakeup from poweroff, we save all regs we can including cfg |
| 2678 | * space | 2636 | * space |
| 2679 | */ | 2637 | */ |
| @@ -2698,9 +2656,6 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) | |||
| 2698 | mdelay(20); | 2656 | mdelay(20); |
| 2699 | OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON)); | 2657 | OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON)); |
| 2700 | } | 2658 | } |
| 2701 | // FIXME: Use PCI layer | ||
| 2702 | for (i = 0; i < 64; ++i) | ||
| 2703 | pci_read_config_dword(pdev, i * 4, &rinfo->cfg_save[i]); | ||
| 2704 | pci_disable_device(pdev); | 2659 | pci_disable_device(pdev); |
| 2705 | } | 2660 | } |
| 2706 | /* If we support D2, we go to it (should be fixed later with a flag forcing | 2661 | /* 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) | |||
| 2717 | return 0; | 2672 | return 0; |
| 2718 | } | 2673 | } |
| 2719 | 2674 | ||
| 2675 | static int radeon_check_power_loss(struct radeonfb_info *rinfo) | ||
| 2676 | { | ||
| 2677 | return rinfo->save_regs[4] != INPLL(CLK_PIN_CNTL) || | ||
| 2678 | rinfo->save_regs[2] != INPLL(MCLK_CNTL) || | ||
| 2679 | rinfo->save_regs[3] != INPLL(SCLK_CNTL); | ||
| 2680 | } | ||
| 2681 | |||
| 2720 | int radeonfb_pci_resume(struct pci_dev *pdev) | 2682 | int radeonfb_pci_resume(struct pci_dev *pdev) |
| 2721 | { | 2683 | { |
| 2722 | struct fb_info *info = pci_get_drvdata(pdev); | 2684 | struct fb_info *info = pci_get_drvdata(pdev); |
| @@ -2735,20 +2697,13 @@ int radeonfb_pci_resume(struct pci_dev *pdev) | |||
| 2735 | printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n", | 2697 | printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n", |
| 2736 | pci_name(pdev), pdev->dev.power.power_state.event); | 2698 | pci_name(pdev), pdev->dev.power.power_state.event); |
| 2737 | 2699 | ||
| 2738 | 2700 | /* PCI state will have been restored by the core, so | |
| 2739 | if (pci_enable_device(pdev)) { | 2701 | * we should be in D0 now with our config space fully |
| 2740 | rc = -ENODEV; | 2702 | * restored |
| 2741 | printk(KERN_ERR "radeonfb (%s): can't enable PCI device !\n", | 2703 | */ |
| 2742 | pci_name(pdev)); | ||
| 2743 | goto bail; | ||
| 2744 | } | ||
| 2745 | pci_set_master(pdev); | ||
| 2746 | |||
| 2747 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { | 2704 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { |
| 2748 | /* Wakeup chip. Check from config space if we were powered off | 2705 | /* Wakeup chip */ |
| 2749 | * (todo: additionally, check CLK_PIN_CNTL too) | 2706 | if ((rinfo->pm_mode & radeon_pm_off) && radeon_check_power_loss(rinfo)) { |
| 2750 | */ | ||
| 2751 | if ((rinfo->pm_mode & radeon_pm_off) && radeon_restore_pci_cfg(rinfo)) { | ||
| 2752 | if (rinfo->reinit_func != NULL) | 2707 | if (rinfo->reinit_func != NULL) |
| 2753 | rinfo->reinit_func(rinfo); | 2708 | rinfo->reinit_func(rinfo); |
| 2754 | else { | 2709 | else { |
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 3ea1b00fdd22..7351e66c7f54 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h | |||
| @@ -361,8 +361,6 @@ struct radeonfb_info { | |||
| 361 | #ifdef CONFIG_FB_RADEON_I2C | 361 | #ifdef CONFIG_FB_RADEON_I2C |
| 362 | struct radeon_i2c_chan i2c[4]; | 362 | struct radeon_i2c_chan i2c[4]; |
| 363 | #endif | 363 | #endif |
| 364 | |||
| 365 | u32 cfg_save[64]; | ||
| 366 | }; | 364 | }; |
| 367 | 365 | ||
| 368 | 366 | ||
