aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/console
diff options
context:
space:
mode:
authorAntonino A. Daplas <adaplas@gmail.com>2007-07-17 07:05:28 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-17 13:23:11 -0400
commit623e71b035cb5271028500720b3622ba76db42bb (patch)
tree651cd606c57b1e1322f92e0406d744a2b341da7e /drivers/video/console
parent317b3c2167f5326a7de30a1abe50c9897da7a0e3 (diff)
fbcon: allow fbcon to use the primary display driver
Allow fbcon to select the primary display adapter using the fb_is_primary_device() arch-specific helper. If a a primary adapter is detected, fbcon will unbind the old adapter from the VT layer, then rebind using the new adapter. This requires that bind_/unbind_con_driver() be made public. Because this feature may produce unexpected behavior (from the user's POV), this must be explicitly enabled in Kconfig. [akpm@linux-foundation.org: export unbind_con_driver] Signed-off-by: Antonino Daplas <adaplas@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/console')
-rw-r--r--drivers/video/console/Kconfig20
-rw-r--r--drivers/video/console/fbcon.c80
2 files changed, 93 insertions, 7 deletions
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index d3b8a6be2916..160f55f7ac96 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -118,6 +118,26 @@ config FRAMEBUFFER_CONSOLE
118 help 118 help
119 Low-level framebuffer-based console driver. 119 Low-level framebuffer-based console driver.
120 120
121config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
122 bool "Map the console to the primary display device"
123 depends on FRAMEBUFFER_CONSOLE && VT_HW_CONSOLE_BINDING
124 default n
125 ---help---
126 If this option is selected, the framebuffer console will
127 automatically select the primary display device (if the architecture
128 supports this feature). Otherwise, the framebuffer console will
129 always select the first framebuffer driver that is loaded. The latter
130 is the default behavior.
131
132 You can always override the automatic selection of the primary device
133 by using the fbcon=map: boot option.
134
135 To select this feature, "Support for binding and unbinding console
136 drivers", under "Device Drivers"->"Character Devices" must be set to
137 y.
138
139 If unsure, select n.
140
121config FRAMEBUFFER_CONSOLE_ROTATION 141config FRAMEBUFFER_CONSOLE_ROTATION
122 bool "Framebuffer Console Rotation" 142 bool "Framebuffer Console Rotation"
123 depends on FRAMEBUFFER_CONSOLE 143 depends on FRAMEBUFFER_CONSOLE
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 7f4ed792307c..7ba21eb1676c 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -75,6 +75,7 @@
75#include <linux/init.h> 75#include <linux/init.h>
76#include <linux/interrupt.h> 76#include <linux/interrupt.h>
77#include <linux/crc32.h> /* For counting font checksums */ 77#include <linux/crc32.h> /* For counting font checksums */
78#include <asm/fb.h>
78#include <asm/irq.h> 79#include <asm/irq.h>
79#include <asm/system.h> 80#include <asm/system.h>
80#include <asm/uaccess.h> 81#include <asm/uaccess.h>
@@ -125,6 +126,8 @@ static int first_fb_vc;
125static int last_fb_vc = MAX_NR_CONSOLES - 1; 126static int last_fb_vc = MAX_NR_CONSOLES - 1;
126static int fbcon_is_default = 1; 127static int fbcon_is_default = 1;
127static int fbcon_has_exited; 128static int fbcon_has_exited;
129static int primary_device = -1;
130static int map_override;
128 131
129/* font data */ 132/* font data */
130static char fontname[40]; 133static char fontname[40];
@@ -497,13 +500,17 @@ static int __init fb_console_setup(char *this_opt)
497 500
498 if (!strncmp(options, "map:", 4)) { 501 if (!strncmp(options, "map:", 4)) {
499 options += 4; 502 options += 4;
500 if (*options) 503 if (*options) {
501 for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) { 504 for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) {
502 if (!options[j]) 505 if (!options[j])
503 j = 0; 506 j = 0;
504 con2fb_map_boot[i] = 507 con2fb_map_boot[i] =
505 (options[j++]-'0') % FB_MAX; 508 (options[j++]-'0') % FB_MAX;
506 } 509 }
510
511 map_override = 1;
512 }
513
507 return 1; 514 return 1;
508 } 515 }
509 516
@@ -3004,9 +3011,9 @@ static int fbcon_mode_deleted(struct fb_info *info,
3004 return found; 3011 return found;
3005} 3012}
3006 3013
3007static int fbcon_fb_unregistered(int idx) 3014static int fbcon_fb_unregistered(struct fb_info *info)
3008{ 3015{
3009 int i; 3016 int i, idx = info->node;
3010 3017
3011 for (i = first_fb_vc; i <= last_fb_vc; i++) { 3018 for (i = first_fb_vc; i <= last_fb_vc; i++) {
3012 if (con2fb_map[i] == idx) 3019 if (con2fb_map[i] == idx)
@@ -3034,12 +3041,70 @@ static int fbcon_fb_unregistered(int idx)
3034 if (!num_registered_fb) 3041 if (!num_registered_fb)
3035 unregister_con_driver(&fb_con); 3042 unregister_con_driver(&fb_con);
3036 3043
3044
3045 if (primary_device == idx)
3046 primary_device = -1;
3047
3048 return 0;
3049}
3050
3051#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
3052static int fbcon_select_primary(struct fb_info *info)
3053{
3054 int ret = 0;
3055
3056 if (!map_override && primary_device == -1 &&
3057 fb_is_primary_device(info)) {
3058 int i, err;
3059
3060 printk(KERN_INFO "fbcon: %s is primary device\n",
3061 info->fix.id);
3062 primary_device = info->node;
3063
3064 if (!con_is_bound(&fb_con))
3065 goto done;
3066
3067 printk(KERN_INFO "fbcon: Unbinding old driver\n");
3068 unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
3069 fbcon_is_default);
3070 info_idx = primary_device;
3071
3072 for (i = first_fb_vc; i <= last_fb_vc; i++) {
3073 con2fb_map_boot[i] = primary_device;
3074 con2fb_map[i] = primary_device;
3075 }
3076
3077 printk(KERN_INFO "fbcon: Selecting new driver\n");
3078 err = bind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
3079 fbcon_is_default);
3080
3081 if (err) {
3082 for (i = first_fb_vc; i <= last_fb_vc; i++)
3083 con2fb_map[i] = -1;
3084
3085 info_idx = -1;
3086 }
3087
3088 ret = 1;
3089 }
3090
3091done:
3092 return ret;
3093}
3094#else
3095static inline int fbcon_select_primary(struct fb_info *info)
3096{
3037 return 0; 3097 return 0;
3038} 3098}
3099#endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */
3039 3100
3040static int fbcon_fb_registered(int idx) 3101static int fbcon_fb_registered(struct fb_info *info)
3041{ 3102{
3042 int ret = 0, i; 3103 int ret = 0, i, idx = info->node;
3104
3105 if (fbcon_select_primary(info))
3106 goto done;
3107
3043 3108
3044 if (info_idx == -1) { 3109 if (info_idx == -1) {
3045 for (i = first_fb_vc; i <= last_fb_vc; i++) { 3110 for (i = first_fb_vc; i <= last_fb_vc; i++) {
@@ -3059,6 +3124,7 @@ static int fbcon_fb_registered(int idx)
3059 } 3124 }
3060 } 3125 }
3061 3126
3127done:
3062 return ret; 3128 return ret;
3063} 3129}
3064 3130
@@ -3182,10 +3248,10 @@ static int fbcon_event_notify(struct notifier_block *self,
3182 ret = fbcon_mode_deleted(info, mode); 3248 ret = fbcon_mode_deleted(info, mode);
3183 break; 3249 break;
3184 case FB_EVENT_FB_REGISTERED: 3250 case FB_EVENT_FB_REGISTERED:
3185 ret = fbcon_fb_registered(info->node); 3251 ret = fbcon_fb_registered(info);
3186 break; 3252 break;
3187 case FB_EVENT_FB_UNREGISTERED: 3253 case FB_EVENT_FB_UNREGISTERED:
3188 ret = fbcon_fb_unregistered(info->node); 3254 ret = fbcon_fb_unregistered(info);
3189 break; 3255 break;
3190 case FB_EVENT_SET_CONSOLE_MAP: 3256 case FB_EVENT_SET_CONSOLE_MAP:
3191 con2fb = event->data; 3257 con2fb = event->data;