Thread (1 message) 1 message, 1 author, 2007-08-16

[PATCH 2/3] vmlfb: Add suspend/resume support.

DORMANTno replies

From: Michel Dänzer <hidden>
Date: 2007-08-16 15:53:08
Subsystem: framebuffer layer, the rest · Maintainers: Helge Deller, Linus Torvalds

From: Michel D������������������nzer <redacted>

Mostly restore fbdev state on resume.

Signed-off-by: Michel D������������������nzer <redacted>
---
 drivers/video/vermilion/vermilion.c |  108 ++++++++++++++++++++++++++++++++++-
 drivers/video/vermilion/vermilion.h |    5 ++
 2 files changed, 112 insertions(+), 1 deletions(-)
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c
index de531c9..af72f67 100644
--- a/drivers/video/vermilion/vermilion.c
+++ b/drivers/video/vermilion/vermilion.c
@@ -41,6 +41,10 @@
 #include <linux/mmzone.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_PM
+#include <linux/console.h>
+#endif
+
 /* #define VERMILION_DEBUG */
 
 #include "vermilion.h"
@@ -1067,11 +1071,113 @@ static struct pci_device_id vml_ids[] = {
 	{0}
 };
 
+#ifdef CONFIG_PM
+static int vmlfb_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct vml_info *vinfo = container_of(info, struct vml_info, info);
+
+	printk(KERN_DEBUG "vmlfb: suspending to state: %d\n", state.event);
+
+	acquire_console_sem();
+
+	fb_set_suspend(info, 1);
+
+	/* Blank display and LCD */
+	vmlfb_blank(FB_BLANK_POWERDOWN, info);
+
+	/* Suspend the chip */
+	if (subsys && subsys->suspend) {
+		int ret = subsys->suspend(subsys, state);
+
+		if (ret) {
+			vmlfb_blank(0, info);
+			fb_set_suspend(info, 0);
+			release_console_sem();
+			return ret;
+		}
+	}
+
+	pci_save_state(vinfo->par->gpu);
+	pci_disable_device(vinfo->par->gpu);
+	pci_set_power_state(vinfo->par->gpu,
+			    pci_choose_state(vinfo->par->gpu, state));
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	release_console_sem();
+
+	pdev->dev.power.power_state = state;
+
+	return 0;
+}
+
+static int vmlfb_resume(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct vml_info *vinfo = container_of(info, struct vml_info, info);
+
+	if (pdev->dev.power.power_state.event == PM_EVENT_ON)
+		return 0;
+
+	acquire_console_sem();
+
+	/* Wake up devices */
+	if (subsys && subsys->resume) {
+		int ret = subsys->resume(subsys);
+
+		if (ret) {
+			release_console_sem();
+			return ret;
+		}
+	}
+
+	pci_set_power_state(vinfo->par->gpu, PCI_D0);
+	pci_restore_state(vinfo->par->gpu);
+	if (pci_enable_device(vinfo->par->gpu)) {
+		release_console_sem();
+		return -1;
+	}
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	if (pci_enable_device(pdev)) {
+		release_console_sem();
+		return -1;
+	}
+
+	/* Restore display */
+	vmlfb_set_par(info);
+	fb_pan_display(info, &info->var);
+	fb_set_cmap(&info->cmap, info);
+
+	/* Refresh */
+	fb_set_suspend(info, 0);
+
+	/* Unblank */
+	vmlfb_blank(0, info);
+
+	release_console_sem();
+
+	pdev->dev.power.power_state = PMSG_ON;
+
+	printk(KERN_DEBUG "vmlfb: resumed\n");
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
 static struct pci_driver vmlfb_pci_driver = {
 	.name = "vmlfb",
 	.id_table = vml_ids,
 	.probe = vml_pci_probe,
-	.remove = __devexit_p(vml_pci_remove)
+	.remove = __devexit_p(vml_pci_remove),
+#ifdef CONFIG_PM
+	.suspend = vmlfb_suspend,
+	.resume	= vmlfb_resume,
+#endif /* CONFIG_PM */
 };
 
 static void __exit vmlfb_cleanup(void)
diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/vermilion/vermilion.h
index 1fc6695..97b6e54 100644
--- a/drivers/video/vermilion/vermilion.h
+++ b/drivers/video/vermilion/vermilion.h
@@ -247,6 +247,11 @@ struct vml_sys {
 
 	int (*set_clock) (struct vml_sys * sys, int clock);
 	int (*nearest_clock) (const struct vml_sys * sys, int clock);
+
+#ifdef CONFIG_PM
+	int (*suspend) (const struct vml_sys *sys, pm_message_t state);
+	int (*resume) (const struct vml_sys *sys);
+#endif
 };
 
 extern int vmlfb_register_subsys(struct vml_sys *sys);
-- 
1.5.2.4

Attachments

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help