aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/console/fbcon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/console/fbcon.c')
-rw-r--r--drivers/video/console/fbcon.c80
1 files changed, 73 insertions, 7 deletions
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;