aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/aty/radeon_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/aty/radeon_pm.c')
-rw-r--r--drivers/video/aty/radeon_pm.c119
1 files changed, 53 insertions, 66 deletions
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index c4ac2a032fcb..c6d7cc76516f 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -2507,11 +2507,28 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
2507 2507
2508#endif /* CONFIG_PPC_OF */ 2508#endif /* CONFIG_PPC_OF */
2509 2509
2510static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) 2510static void radeonfb_whack_power_state(struct radeonfb_info *rinfo, pci_power_t state)
2511{ 2511{
2512 u16 pwr_cmd; 2512 u16 pwr_cmd;
2513
2514 for (;;) {
2515 pci_read_config_word(rinfo->pdev,
2516 rinfo->pm_reg+PCI_PM_CTRL,
2517 &pwr_cmd);
2518 if (pwr_cmd & 2)
2519 break;
2520 pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2;
2521 pci_write_config_word(rinfo->pdev,
2522 rinfo->pm_reg+PCI_PM_CTRL,
2523 pwr_cmd);
2524 msleep(500);
2525 }
2526 rinfo->pdev->current_state = state;
2527}
2528
2529static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
2530{
2513 u32 tmp; 2531 u32 tmp;
2514 int i;
2515 2532
2516 if (!rinfo->pm_reg) 2533 if (!rinfo->pm_reg)
2517 return; 2534 return;
@@ -2557,32 +2574,19 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
2557 } 2574 }
2558 } 2575 }
2559 2576
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. */ 2577 /* Switch PCI power management to D2. */
2565 pci_disable_device(rinfo->pdev); 2578 pci_disable_device(rinfo->pdev);
2566 for (;;) { 2579 pci_save_state(rinfo->pdev);
2567 pci_read_config_word( 2580 /* The chip seems to need us to whack the PM register
2568 rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 2581 * repeatedly until it sticks. We do that -prior- to
2569 &pwr_cmd); 2582 * calling pci_set_power_state()
2570 if (pwr_cmd & 2) 2583 */
2571 break; 2584 radeonfb_whack_power_state(rinfo, PCI_D2);
2572 pci_write_config_word( 2585 pci_set_power_state(rinfo->pdev, PCI_D2);
2573 rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
2574 (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2);
2575 mdelay(500);
2576 }
2577 } else { 2586 } else {
2578 printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", 2587 printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
2579 pci_name(rinfo->pdev)); 2588 pci_name(rinfo->pdev));
2580 2589
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) { 2590 if (rinfo->family <= CHIP_FAMILY_RV250) {
2587 /* Reset the SDRAM controller */ 2591 /* Reset the SDRAM controller */
2588 radeon_pm_full_reset_sdram(rinfo); 2592 radeon_pm_full_reset_sdram(rinfo);
@@ -2598,37 +2602,10 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
2598 } 2602 }
2599} 2603}
2600 2604
2601static 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
2627int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) 2605int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
2628{ 2606{
2629 struct fb_info *info = pci_get_drvdata(pdev); 2607 struct fb_info *info = pci_get_drvdata(pdev);
2630 struct radeonfb_info *rinfo = info->par; 2608 struct radeonfb_info *rinfo = info->par;
2631 int i;
2632 2609
2633 if (mesg.event == pdev->dev.power.power_state.event) 2610 if (mesg.event == pdev->dev.power.power_state.event)
2634 return 0; 2611 return 0;
@@ -2674,6 +2651,11 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
2674 pmac_suspend_agp_for_card(pdev); 2651 pmac_suspend_agp_for_card(pdev);
2675#endif /* CONFIG_PPC_PMAC */ 2652#endif /* CONFIG_PPC_PMAC */
2676 2653
2654 /* It's unclear whether or when the generic code will do that, so let's
2655 * do it ourselves. We save state before we do any power management
2656 */
2657 pci_save_state(pdev);
2658
2677 /* If we support wakeup from poweroff, we save all regs we can including cfg 2659 /* If we support wakeup from poweroff, we save all regs we can including cfg
2678 * space 2660 * space
2679 */ 2661 */
@@ -2698,9 +2680,6 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
2698 mdelay(20); 2680 mdelay(20);
2699 OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON)); 2681 OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON));
2700 } 2682 }
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); 2683 pci_disable_device(pdev);
2705 } 2684 }
2706 /* If we support D2, we go to it (should be fixed later with a flag forcing 2685 /* 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)
2717 return 0; 2696 return 0;
2718} 2697}
2719 2698
2699static int radeon_check_power_loss(struct radeonfb_info *rinfo)
2700{
2701 return rinfo->save_regs[4] != INPLL(CLK_PIN_CNTL) ||
2702 rinfo->save_regs[2] != INPLL(MCLK_CNTL) ||
2703 rinfo->save_regs[3] != INPLL(SCLK_CNTL);
2704}
2705
2720int radeonfb_pci_resume(struct pci_dev *pdev) 2706int radeonfb_pci_resume(struct pci_dev *pdev)
2721{ 2707{
2722 struct fb_info *info = pci_get_drvdata(pdev); 2708 struct fb_info *info = pci_get_drvdata(pdev);
@@ -2735,20 +2721,13 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
2735 printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n", 2721 printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n",
2736 pci_name(pdev), pdev->dev.power.power_state.event); 2722 pci_name(pdev), pdev->dev.power.power_state.event);
2737 2723
2738 2724 /* PCI state will have been restored by the core, so
2739 if (pci_enable_device(pdev)) { 2725 * we should be in D0 now with our config space fully
2740 rc = -ENODEV; 2726 * restored
2741 printk(KERN_ERR "radeonfb (%s): can't enable PCI device !\n", 2727 */
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) { 2728 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
2748 /* Wakeup chip. Check from config space if we were powered off 2729 /* Wakeup chip */
2749 * (todo: additionally, check CLK_PIN_CNTL too) 2730 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) 2731 if (rinfo->reinit_func != NULL)
2753 rinfo->reinit_func(rinfo); 2732 rinfo->reinit_func(rinfo);
2754 else { 2733 else {
@@ -2807,12 +2786,13 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
2807 return rc; 2786 return rc;
2808} 2787}
2809 2788
2810#ifdef CONFIG_PPC_OF 2789#ifdef CONFIG_PPC_OF__disabled
2811static void radeonfb_early_resume(void *data) 2790static void radeonfb_early_resume(void *data)
2812{ 2791{
2813 struct radeonfb_info *rinfo = data; 2792 struct radeonfb_info *rinfo = data;
2814 2793
2815 rinfo->no_schedule = 1; 2794 rinfo->no_schedule = 1;
2795 pci_restore_state(rinfo->pdev);
2816 radeonfb_pci_resume(rinfo->pdev); 2796 radeonfb_pci_resume(rinfo->pdev);
2817 rinfo->no_schedule = 0; 2797 rinfo->no_schedule = 0;
2818} 2798}
@@ -2879,7 +2859,14 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis
2879 */ 2859 */
2880 if (rinfo->pm_mode != radeon_pm_none) { 2860 if (rinfo->pm_mode != radeon_pm_none) {
2881 pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, rinfo->of_node, 0, 1); 2861 pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, rinfo->of_node, 0, 1);
2862#if 0 /* Disable the early video resume hack for now as it's causing problems, among
2863 * others we now rely on the PCI core restoring the config space for us, which
2864 * isn't the case with that hack, and that code path causes various things to
2865 * be called with interrupts off while they shouldn't. I'm leaving the code in
2866 * as it can be useful for debugging purposes
2867 */
2882 pmac_set_early_video_resume(radeonfb_early_resume, rinfo); 2868 pmac_set_early_video_resume(radeonfb_early_resume, rinfo);
2869#endif
2883 } 2870 }
2884 2871
2885#if 0 2872#if 0