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.c155
1 files changed, 97 insertions, 58 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 0b742497055e..4b7be685c160 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -194,7 +194,8 @@ static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
194 int line, int count, int dy); 194 int line, int count, int dy);
195static void fbcon_modechanged(struct fb_info *info); 195static void fbcon_modechanged(struct fb_info *info);
196static void fbcon_set_all_vcs(struct fb_info *info); 196static void fbcon_set_all_vcs(struct fb_info *info);
197 197static void fbcon_start(void);
198static void fbcon_exit(void);
198static struct class_device *fbcon_class_device; 199static struct class_device *fbcon_class_device;
199 200
200#ifdef CONFIG_MAC 201#ifdef CONFIG_MAC
@@ -391,15 +392,18 @@ static void fb_flashcursor(void *private)
391 int c; 392 int c;
392 int mode; 393 int mode;
393 394
394 if (ops->currcon != -1) 395 acquire_console_sem();
396 if (ops && ops->currcon != -1)
395 vc = vc_cons[ops->currcon].d; 397 vc = vc_cons[ops->currcon].d;
396 398
397 if (!vc || !CON_IS_VISIBLE(vc) || 399 if (!vc || !CON_IS_VISIBLE(vc) ||
398 fbcon_is_inactive(vc, info) || 400 fbcon_is_inactive(vc, info) ||
399 registered_fb[con2fb_map[vc->vc_num]] != info || 401 registered_fb[con2fb_map[vc->vc_num]] != info ||
400 vc_cons[ops->currcon].d->vc_deccm != 1) 402 vc_cons[ops->currcon].d->vc_deccm != 1) {
403 release_console_sem();
401 return; 404 return;
402 acquire_console_sem(); 405 }
406
403 p = &fb_display[vc->vc_num]; 407 p = &fb_display[vc->vc_num];
404 c = scr_readw((u16 *) vc->vc_pos); 408 c = scr_readw((u16 *) vc->vc_pos);
405 mode = (!ops->cursor_flash || ops->cursor_state.enable) ? 409 mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
@@ -2101,12 +2105,11 @@ static int fbcon_switch(struct vc_data *vc)
2101 if (info->fbops->fb_set_par) 2105 if (info->fbops->fb_set_par)
2102 info->fbops->fb_set_par(info); 2106 info->fbops->fb_set_par(info);
2103 2107
2104 if (old_info != info) { 2108 if (old_info != info)
2105 fbcon_del_cursor_timer(old_info); 2109 fbcon_del_cursor_timer(old_info);
2106 fbcon_add_cursor_timer(info);
2107 }
2108 } 2110 }
2109 2111
2112 fbcon_add_cursor_timer(info);
2110 set_blitting_type(vc, info); 2113 set_blitting_type(vc, info);
2111 ops->cursor_reset = 1; 2114 ops->cursor_reset = 1;
2112 2115
@@ -2847,7 +2850,8 @@ static int fbcon_fb_registered(int idx)
2847 ret = fbcon_takeover(1); 2850 ret = fbcon_takeover(1);
2848 } else { 2851 } else {
2849 for (i = 0; i < MAX_NR_CONSOLES; i++) { 2852 for (i = 0; i < MAX_NR_CONSOLES; i++) {
2850 if (con2fb_map_boot[i] == idx) 2853 if (con2fb_map_boot[i] == idx &&
2854 con2fb_map[i] == -1)
2851 set_con2fb_map(i, idx, 0); 2855 set_con2fb_map(i, idx, 0);
2852 } 2856 }
2853 } 2857 }
@@ -3046,9 +3050,32 @@ err:
3046 return snprintf(buf, PAGE_SIZE, "%d\n", rotate); 3050 return snprintf(buf, PAGE_SIZE, "%d\n", rotate);
3047} 3051}
3048 3052
3053static ssize_t store_attach(struct class_device *class_device,
3054 const char *buf, size_t count)
3055{
3056 if (info_idx == -1)
3057 fbcon_start();
3058
3059 return count;
3060}
3061
3062static ssize_t store_detach(struct class_device *class_device,
3063 const char *buf, size_t count)
3064{
3065 if (info_idx != -1) {
3066 fbcon_exit();
3067 give_up_console(&fb_con);
3068 }
3069
3070 info_idx = -1;
3071 return count;
3072}
3073
3049static struct class_device_attribute class_device_attrs[] = { 3074static struct class_device_attribute class_device_attrs[] = {
3050 __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate), 3075 __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
3051 __ATTR(rotate_all, S_IWUSR, NULL, store_rotate_all), 3076 __ATTR(rotate_all, S_IWUSR, NULL, store_rotate_all),
3077 __ATTR(attach, S_IWUSR, NULL, store_attach),
3078 __ATTR(detach, S_IWUSR, NULL, store_detach),
3052}; 3079};
3053 3080
3054static int fbcon_init_class_device(void) 3081static int fbcon_init_class_device(void)
@@ -3061,67 +3088,31 @@ static int fbcon_init_class_device(void)
3061 return 0; 3088 return 0;
3062} 3089}
3063 3090
3064static int __init fb_console_init(void) 3091static void fbcon_start(void)
3065{ 3092{
3066 int i; 3093 if (num_registered_fb) {
3067 3094 int i;
3068 acquire_console_sem();
3069 fb_register_client(&fbcon_event_notifier);
3070 release_console_sem();
3071
3072 fbcon_class_device =
3073 class_device_create(fb_class, NULL,
3074 MKDEV(FB_MAJOR, FB_MAX), NULL,
3075 "fbcon");
3076 if (IS_ERR(fbcon_class_device)) {
3077 printk(KERN_WARNING "Unable to create class_device "
3078 "for fbcon; errno = %ld\n",
3079 PTR_ERR(fbcon_class_device));
3080 fbcon_class_device = NULL;
3081 } else
3082 fbcon_init_class_device();
3083 3095
3084 for (i = 0; i < MAX_NR_CONSOLES; i++) 3096 acquire_console_sem();
3085 con2fb_map[i] = -1;
3086 3097
3087 if (num_registered_fb) {
3088 for (i = 0; i < FB_MAX; i++) { 3098 for (i = 0; i < FB_MAX; i++) {
3089 if (registered_fb[i] != NULL) { 3099 if (registered_fb[i] != NULL) {
3090 info_idx = i; 3100 info_idx = i;
3091 break; 3101 break;
3092 } 3102 }
3093 } 3103 }
3104
3105 release_console_sem();
3094 fbcon_takeover(0); 3106 fbcon_takeover(0);
3095 } 3107 }
3096
3097 return 0;
3098}
3099
3100module_init(fb_console_init);
3101
3102#ifdef MODULE
3103
3104static void __exit fbcon_deinit_class_device(void)
3105{
3106 int i;
3107
3108 for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
3109 class_device_remove_file(fbcon_class_device,
3110 &class_device_attrs[i]);
3111} 3108}
3112 3109
3113static void __exit fbcon_exit(void) 3110static void fbcon_exit(void)
3114{ 3111{
3115 struct fb_info *info; 3112 struct fb_info *info;
3116 int i, j, mapped; 3113 int i, j, mapped;
3117 3114
3118 for (i = 0; i < FB_MAX; i++) { 3115 acquire_console_sem();
3119 info = registered_fb[i];
3120
3121 if (info && info->fbcon_par)
3122 fbcon_del_cursor_timer(info);
3123 }
3124
3125#ifdef CONFIG_ATARI 3116#ifdef CONFIG_ATARI
3126 free_irq(IRQ_AUTO_4, fbcon_vbl_handler); 3117 free_irq(IRQ_AUTO_4, fbcon_vbl_handler);
3127#endif 3118#endif
@@ -3131,6 +3122,7 @@ static void __exit fbcon_exit(void)
3131#endif 3122#endif
3132 3123
3133 kfree((void *)softback_buf); 3124 kfree((void *)softback_buf);
3125 softback_buf = 0UL;
3134 3126
3135 for (i = 0; i < FB_MAX; i++) { 3127 for (i = 0; i < FB_MAX; i++) {
3136 mapped = 0; 3128 mapped = 0;
@@ -3150,22 +3142,69 @@ static void __exit fbcon_exit(void)
3150 if (info->fbops->fb_release) 3142 if (info->fbops->fb_release)
3151 info->fbops->fb_release(info, 0); 3143 info->fbops->fb_release(info, 0);
3152 module_put(info->fbops->owner); 3144 module_put(info->fbops->owner);
3153 kfree(info->fbcon_par); 3145
3154 info->fbcon_par = NULL; 3146 if (info->fbcon_par) {
3147 fbcon_del_cursor_timer(info);
3148 kfree(info->fbcon_par);
3149 info->fbcon_par = NULL;
3150 }
3151
3152 if (info->queue.func == fb_flashcursor)
3153 info->queue.func = NULL;
3154
3155 } 3155 }
3156 } 3156 }
3157 3157
3158 fbcon_deinit_class_device(); 3158 release_console_sem();
3159 class_device_destroy(fb_class, MKDEV(FB_MAJOR, FB_MAX)); 3159}
3160
3161static int __init fb_console_init(void)
3162{
3163 int i;
3164
3165 acquire_console_sem();
3166 fb_register_client(&fbcon_event_notifier);
3167 fbcon_class_device =
3168 class_device_create(fb_class, NULL,
3169 MKDEV(FB_MAJOR, FB_MAX), NULL,
3170 "fbcon");
3171
3172 if (IS_ERR(fbcon_class_device)) {
3173 printk(KERN_WARNING "Unable to create class_device "
3174 "for fbcon; errno = %ld\n",
3175 PTR_ERR(fbcon_class_device));
3176 fbcon_class_device = NULL;
3177 } else
3178 fbcon_init_class_device();
3179
3180 for (i = 0; i < MAX_NR_CONSOLES; i++)
3181 con2fb_map[i] = -1;
3182
3183 release_console_sem();
3184 fbcon_start();
3185 return 0;
3186}
3187
3188module_init(fb_console_init);
3189
3190#ifdef MODULE
3191
3192static void fbcon_deinit_class_device(void)
3193{
3194 int i;
3195
3196 for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
3197 class_device_remove_file(fbcon_class_device,
3198 &class_device_attrs[i]);
3160} 3199}
3161 3200
3162static void __exit fb_console_exit(void) 3201static void __exit fb_console_exit(void)
3163{ 3202{
3164 acquire_console_sem(); 3203 acquire_console_sem();
3165 fb_unregister_client(&fbcon_event_notifier); 3204 fb_unregister_client(&fbcon_event_notifier);
3166 fbcon_exit(); 3205 fbcon_deinit_class_device();
3206 class_device_destroy(fb_class, MKDEV(FB_MAJOR, FB_MAX));
3167 release_console_sem(); 3207 release_console_sem();
3168 give_up_console(&fb_con);
3169} 3208}
3170 3209
3171module_exit(fb_console_exit); 3210module_exit(fb_console_exit);