diff options
author | Andres Salomon <dilinger@queued.net> | 2008-04-28 05:15:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-28 11:58:36 -0400 |
commit | b6f448e99ce7955b9707ed36a46cab2c6ddf7ddc (patch) | |
tree | 74ae26692c1fd713a0178faca99dea6761d442e8 | |
parent | 46fb6f110dfc3fc99f44cf701f66ea3e790b6a81 (diff) |
PM/gxfb: add hook to PM console layer that allows disabling of suspend VT switch
Prior to suspend, we allocate and switch to a new VT; after suspend, we switch
back to the original VT. This can be slow, and is completely unnecessary if
the framebuffer we're using can restore video properly.
This adds a hook that allows drivers to select whether or not to do this vt
switch, and changes the gxfb driver to call this hook. It also adds a module
param to gxfb to allow controlling of the vt switch (defaulting to no switch).
(Note: I'm not convinced that console_sem is the best way to protect this, but
we should probably have some form of locking..)
[akpm@linux-foundation.org: build fix]
Signed-off-by: Andres Salomon <dilinger@debian.org>
Cc: Jordan Crouse <jordan.crouse@amd.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | Documentation/fb/gxfb.txt | 3 | ||||
-rw-r--r-- | drivers/video/geode/gxfb_core.c | 7 | ||||
-rw-r--r-- | include/linux/suspend.h | 15 | ||||
-rw-r--r-- | kernel/power/console.c | 27 |
4 files changed, 48 insertions, 4 deletions
diff --git a/Documentation/fb/gxfb.txt b/Documentation/fb/gxfb.txt index b56096142017..2f640903bbb2 100644 --- a/Documentation/fb/gxfb.txt +++ b/Documentation/fb/gxfb.txt | |||
@@ -45,7 +45,8 @@ Accepted options: | |||
45 | mode_option - specify the video mode. Of the form | 45 | mode_option - specify the video mode. Of the form |
46 | <x>x<y>[-<bpp>][@<refresh>] | 46 | <x>x<y>[-<bpp>][@<refresh>] |
47 | vram - size of video ram (normally auto-detected) | 47 | vram - size of video ram (normally auto-detected) |
48 | 48 | vt_switch - enable vt switching during suspend/resume. The vt | |
49 | switch is slow, but harmless. | ||
49 | 50 | ||
50 | -- | 51 | -- |
51 | Andres Salomon <dilinger@debian.org> | 52 | Andres Salomon <dilinger@debian.org> |
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c index 151d964c025a..f16c21d5bc21 100644 --- a/drivers/video/geode/gxfb_core.c +++ b/drivers/video/geode/gxfb_core.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/fb.h> | 30 | #include <linux/fb.h> |
31 | #include <linux/console.h> | 31 | #include <linux/console.h> |
32 | #include <linux/suspend.h> | ||
32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
33 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
34 | #include <asm/geode.h> | 35 | #include <asm/geode.h> |
@@ -37,6 +38,7 @@ | |||
37 | 38 | ||
38 | static char *mode_option; | 39 | static char *mode_option; |
39 | static int vram; | 40 | static int vram; |
41 | static int vt_switch; | ||
40 | 42 | ||
41 | /* Modes relevant to the GX (taken from modedb.c) */ | 43 | /* Modes relevant to the GX (taken from modedb.c) */ |
42 | static const struct fb_videomode gx_modedb[] __initdata = { | 44 | static const struct fb_videomode gx_modedb[] __initdata = { |
@@ -382,6 +384,8 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i | |||
382 | gxfb_check_var(&info->var, info); | 384 | gxfb_check_var(&info->var, info); |
383 | gxfb_set_par(info); | 385 | gxfb_set_par(info); |
384 | 386 | ||
387 | pm_set_vt_switch(vt_switch); | ||
388 | |||
385 | if (register_framebuffer(info) < 0) { | 389 | if (register_framebuffer(info) < 0) { |
386 | ret = -EINVAL; | 390 | ret = -EINVAL; |
387 | goto err; | 391 | goto err; |
@@ -502,5 +506,8 @@ MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])"); | |||
502 | module_param(vram, int, 0); | 506 | module_param(vram, int, 0); |
503 | MODULE_PARM_DESC(vram, "video memory size"); | 507 | MODULE_PARM_DESC(vram, "video memory size"); |
504 | 508 | ||
509 | module_param(vt_switch, int, 0); | ||
510 | MODULE_PARM_DESC(vt_switch, "enable VT switch during suspend/resume"); | ||
511 | |||
505 | MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX"); | 512 | MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX"); |
506 | MODULE_LICENSE("GPL"); | 513 | MODULE_LICENSE("GPL"); |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 1d7d4c5797ee..a6977423baf7 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
@@ -12,11 +12,22 @@ | |||
12 | #include <asm/errno.h> | 12 | #include <asm/errno.h> |
13 | 13 | ||
14 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) | 14 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) |
15 | extern void pm_set_vt_switch(int); | ||
15 | extern int pm_prepare_console(void); | 16 | extern int pm_prepare_console(void); |
16 | extern void pm_restore_console(void); | 17 | extern void pm_restore_console(void); |
17 | #else | 18 | #else |
18 | static inline int pm_prepare_console(void) { return 0; } | 19 | static inline void pm_set_vt_switch(int do_switch) |
19 | static inline void pm_restore_console(void) {} | 20 | { |
21 | } | ||
22 | |||
23 | static inline int pm_prepare_console(void) | ||
24 | { | ||
25 | return 0; | ||
26 | } | ||
27 | |||
28 | static inline void pm_restore_console(void) | ||
29 | { | ||
30 | } | ||
20 | #endif | 31 | #endif |
21 | 32 | ||
22 | typedef int __bitwise suspend_state_t; | 33 | typedef int __bitwise suspend_state_t; |
diff --git a/kernel/power/console.c b/kernel/power/console.c index 89bcf4973ee5..b8628be2a465 100644 --- a/kernel/power/console.c +++ b/kernel/power/console.c | |||
@@ -7,17 +7,39 @@ | |||
7 | #include <linux/vt_kern.h> | 7 | #include <linux/vt_kern.h> |
8 | #include <linux/kbd_kern.h> | 8 | #include <linux/kbd_kern.h> |
9 | #include <linux/console.h> | 9 | #include <linux/console.h> |
10 | #include <linux/module.h> | ||
10 | #include "power.h" | 11 | #include "power.h" |
11 | 12 | ||
12 | #if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) | 13 | #if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) |
13 | #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) | 14 | #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) |
14 | 15 | ||
15 | static int orig_fgconsole, orig_kmsg; | 16 | static int orig_fgconsole, orig_kmsg; |
17 | static int disable_vt_switch; | ||
18 | |||
19 | /* | ||
20 | * Normally during a suspend, we allocate a new console and switch to it. | ||
21 | * When we resume, we switch back to the original console. This switch | ||
22 | * can be slow, so on systems where the framebuffer can handle restoration | ||
23 | * of video registers anyways, there's little point in doing the console | ||
24 | * switch. This function allows you to disable it by passing it '0'. | ||
25 | */ | ||
26 | void pm_set_vt_switch(int do_switch) | ||
27 | { | ||
28 | acquire_console_sem(); | ||
29 | disable_vt_switch = !do_switch; | ||
30 | release_console_sem(); | ||
31 | } | ||
32 | EXPORT_SYMBOL(pm_set_vt_switch); | ||
16 | 33 | ||
17 | int pm_prepare_console(void) | 34 | int pm_prepare_console(void) |
18 | { | 35 | { |
19 | acquire_console_sem(); | 36 | acquire_console_sem(); |
20 | 37 | ||
38 | if (disable_vt_switch) { | ||
39 | release_console_sem(); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
21 | orig_fgconsole = fg_console; | 43 | orig_fgconsole = fg_console; |
22 | 44 | ||
23 | if (vc_allocate(SUSPEND_CONSOLE)) { | 45 | if (vc_allocate(SUSPEND_CONSOLE)) { |
@@ -50,9 +72,12 @@ int pm_prepare_console(void) | |||
50 | void pm_restore_console(void) | 72 | void pm_restore_console(void) |
51 | { | 73 | { |
52 | acquire_console_sem(); | 74 | acquire_console_sem(); |
75 | if (disable_vt_switch) { | ||
76 | release_console_sem(); | ||
77 | return; | ||
78 | } | ||
53 | set_console(orig_fgconsole); | 79 | set_console(orig_fgconsole); |
54 | release_console_sem(); | 80 | release_console_sem(); |
55 | kmsg_redirect = orig_kmsg; | 81 | kmsg_redirect = orig_kmsg; |
56 | return; | ||
57 | } | 82 | } |
58 | #endif | 83 | #endif |