aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/video/fbdev.c4
-rw-r--r--drivers/char/vt.c8
-rw-r--r--drivers/video/console/Kconfig20
-rw-r--r--drivers/video/console/fbcon.c80
-rw-r--r--include/linux/vt_kern.h4
5 files changed, 102 insertions, 14 deletions
diff --git a/arch/i386/video/fbdev.c b/arch/i386/video/fbdev.c
index 7fc712c46a64..48fb38d7d2c0 100644
--- a/arch/i386/video/fbdev.c
+++ b/arch/i386/video/fbdev.c
@@ -13,13 +13,11 @@
13 13
14int fb_is_primary_device(struct fb_info *info) 14int fb_is_primary_device(struct fb_info *info)
15{ 15{
16 struct device *device; 16 struct device *device = info->device;
17 struct pci_dev *pci_dev = NULL; 17 struct pci_dev *pci_dev = NULL;
18 struct resource *res = NULL; 18 struct resource *res = NULL;
19 int retval = 0; 19 int retval = 0;
20 20
21 device = info->device;
22
23 if (device) 21 if (device)
24 pci_dev = to_pci_dev(device); 22 pci_dev = to_pci_dev(device);
25 23
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 349673d432f1..8a389b314624 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2869,8 +2869,7 @@ int __init vty_init(void)
2869 2869
2870static struct class *vtconsole_class; 2870static struct class *vtconsole_class;
2871 2871
2872static int bind_con_driver(const struct consw *csw, int first, int last, 2872int bind_con_driver(const struct consw *csw, int first, int last, int deflt)
2873 int deflt)
2874{ 2873{
2875 struct module *owner = csw->owner; 2874 struct module *owner = csw->owner;
2876 const char *desc = NULL; 2875 const char *desc = NULL;
@@ -2969,6 +2968,7 @@ err:
2969 module_put(owner); 2968 module_put(owner);
2970 return retval; 2969 return retval;
2971}; 2970};
2971EXPORT_SYMBOL(bind_con_driver);
2972 2972
2973#ifdef CONFIG_VT_HW_CONSOLE_BINDING 2973#ifdef CONFIG_VT_HW_CONSOLE_BINDING
2974static int con_is_graphics(const struct consw *csw, int first, int last) 2974static int con_is_graphics(const struct consw *csw, int first, int last)
@@ -2987,8 +2987,7 @@ static int con_is_graphics(const struct consw *csw, int first, int last)
2987 return retval; 2987 return retval;
2988} 2988}
2989 2989
2990static int unbind_con_driver(const struct consw *csw, int first, int last, 2990int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
2991 int deflt)
2992{ 2991{
2993 struct module *owner = csw->owner; 2992 struct module *owner = csw->owner;
2994 const struct consw *defcsw = NULL; 2993 const struct consw *defcsw = NULL;
@@ -3073,6 +3072,7 @@ err:
3073 return retval; 3072 return retval;
3074 3073
3075} 3074}
3075EXPORT_SYMBOL(unbind_con_driver);
3076 3076
3077static int vt_bind(struct con_driver *con) 3077static int vt_bind(struct con_driver *con)
3078{ 3078{
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;
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index d961635d0e61..0d034d89ee8a 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -75,6 +75,10 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
75int vt_waitactive(int vt); 75int vt_waitactive(int vt);
76void change_console(struct vc_data *new_vc); 76void change_console(struct vc_data *new_vc);
77void reset_vc(struct vc_data *vc); 77void reset_vc(struct vc_data *vc);
78extern int bind_con_driver(const struct consw *csw, int first, int last,
79 int deflt);
80extern int unbind_con_driver(const struct consw *csw, int first, int last,
81 int deflt);
78 82
79/* 83/*
80 * vc_screen.c shares this temporary buffer with the console write code so that 84 * vc_screen.c shares this temporary buffer with the console write code so that