diff options
Diffstat (limited to 'drivers/video/console/fbcon.c')
-rw-r--r-- | drivers/video/console/fbcon.c | 155 |
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); |
195 | static void fbcon_modechanged(struct fb_info *info); | 195 | static void fbcon_modechanged(struct fb_info *info); |
196 | static void fbcon_set_all_vcs(struct fb_info *info); | 196 | static void fbcon_set_all_vcs(struct fb_info *info); |
197 | 197 | static void fbcon_start(void); | |
198 | static void fbcon_exit(void); | ||
198 | static struct class_device *fbcon_class_device; | 199 | static 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 | ||
3053 | static 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 | |||
3062 | static 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 | |||
3049 | static struct class_device_attribute class_device_attrs[] = { | 3074 | static 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 | ||
3054 | static int fbcon_init_class_device(void) | 3081 | static 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 | ||
3064 | static int __init fb_console_init(void) | 3091 | static 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 | |||
3100 | module_init(fb_console_init); | ||
3101 | |||
3102 | #ifdef MODULE | ||
3103 | |||
3104 | static 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 | ||
3113 | static void __exit fbcon_exit(void) | 3110 | static 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 | |||
3161 | static 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 | |||
3188 | module_init(fb_console_init); | ||
3189 | |||
3190 | #ifdef MODULE | ||
3191 | |||
3192 | static 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 | ||
3162 | static void __exit fb_console_exit(void) | 3201 | static 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 | ||
3171 | module_exit(fb_console_exit); | 3210 | module_exit(fb_console_exit); |