| .. | .. |
|---|
| 76 | 76 | #include <linux/init.h> |
|---|
| 77 | 77 | #include <linux/interrupt.h> |
|---|
| 78 | 78 | #include <linux/crc32.h> /* For counting font checksums */ |
|---|
| 79 | +#include <linux/uaccess.h> |
|---|
| 79 | 80 | #include <asm/fb.h> |
|---|
| 80 | 81 | #include <asm/irq.h> |
|---|
| 81 | 82 | |
|---|
| .. | .. |
|---|
| 87 | 88 | # define DPRINTK(fmt, args...) |
|---|
| 88 | 89 | #endif |
|---|
| 89 | 90 | |
|---|
| 91 | +/* |
|---|
| 92 | + * FIXME: Locking |
|---|
| 93 | + * |
|---|
| 94 | + * - fbcon state itself is protected by the console_lock, and the code does a |
|---|
| 95 | + * pretty good job at making sure that lock is held everywhere it's needed. |
|---|
| 96 | + * |
|---|
| 97 | + * - access to the registered_fb array is entirely unprotected. This should use |
|---|
| 98 | + * proper object lifetime handling, i.e. get/put_fb_info. This also means |
|---|
| 99 | + * switching from indices to proper pointers for fb_info everywhere. |
|---|
| 100 | + * |
|---|
| 101 | + * - fbcon doesn't bother with fb_lock/unlock at all. This is buggy, since it |
|---|
| 102 | + * means concurrent access to the same fbdev from both fbcon and userspace |
|---|
| 103 | + * will blow up. To fix this all fbcon calls from fbmem.c need to be moved out |
|---|
| 104 | + * of fb_lock/unlock protected sections, since otherwise we'll recurse and |
|---|
| 105 | + * deadlock eventually. Aside: Due to these deadlock issues the fbdev code in |
|---|
| 106 | + * fbmem.c cannot use locking asserts, and there's lots of callers which get |
|---|
| 107 | + * the rules wrong, e.g. fbsysfs.c entirely missed fb_lock/unlock calls too. |
|---|
| 108 | + */ |
|---|
| 109 | + |
|---|
| 90 | 110 | enum { |
|---|
| 91 | 111 | FBCON_LOGO_CANSHOW = -1, /* the logo can be shown */ |
|---|
| 92 | 112 | FBCON_LOGO_DRAW = -2, /* draw the logo to a console */ |
|---|
| 93 | 113 | FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */ |
|---|
| 94 | 114 | }; |
|---|
| 95 | 115 | |
|---|
| 96 | | -static struct display fb_display[MAX_NR_CONSOLES]; |
|---|
| 116 | +static struct fbcon_display fb_display[MAX_NR_CONSOLES]; |
|---|
| 97 | 117 | |
|---|
| 98 | 118 | static signed char con2fb_map[MAX_NR_CONSOLES]; |
|---|
| 99 | 119 | static signed char con2fb_map_boot[MAX_NR_CONSOLES]; |
|---|
| .. | .. |
|---|
| 103 | 123 | enums. */ |
|---|
| 104 | 124 | static int logo_shown = FBCON_LOGO_CANSHOW; |
|---|
| 105 | 125 | /* console mappings */ |
|---|
| 106 | | -static int first_fb_vc; |
|---|
| 107 | | -static int last_fb_vc = MAX_NR_CONSOLES - 1; |
|---|
| 126 | +static unsigned int first_fb_vc; |
|---|
| 127 | +static unsigned int last_fb_vc = MAX_NR_CONSOLES - 1; |
|---|
| 108 | 128 | static int fbcon_is_default = 1; |
|---|
| 109 | | -static int fbcon_has_exited; |
|---|
| 110 | 129 | static int primary_device = -1; |
|---|
| 111 | 130 | static int fbcon_has_console_bind; |
|---|
| 112 | 131 | |
|---|
| .. | .. |
|---|
| 144 | 163 | |
|---|
| 145 | 164 | #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row) |
|---|
| 146 | 165 | |
|---|
| 147 | | -static int fbcon_set_origin(struct vc_data *); |
|---|
| 148 | | - |
|---|
| 149 | 166 | static int fbcon_cursor_noblink; |
|---|
| 150 | 167 | |
|---|
| 151 | 168 | #define divides(a, b) ((!(a) || (b)%(a)) ? 0 : 1) |
|---|
| .. | .. |
|---|
| 177 | 194 | static __inline__ void ywrap_down(struct vc_data *vc, int count); |
|---|
| 178 | 195 | static __inline__ void ypan_up(struct vc_data *vc, int count); |
|---|
| 179 | 196 | static __inline__ void ypan_down(struct vc_data *vc, int count); |
|---|
| 180 | | -static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx, |
|---|
| 197 | +static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx, |
|---|
| 181 | 198 | int dy, int dx, int height, int width, u_int y_break); |
|---|
| 182 | 199 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, |
|---|
| 183 | 200 | int unit); |
|---|
| 184 | | -static void fbcon_redraw_move(struct vc_data *vc, struct display *p, |
|---|
| 201 | +static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p, |
|---|
| 185 | 202 | int line, int count, int dy); |
|---|
| 186 | 203 | static void fbcon_modechanged(struct fb_info *info); |
|---|
| 187 | 204 | static void fbcon_set_all_vcs(struct fb_info *info); |
|---|
| .. | .. |
|---|
| 212 | 229 | fb_info = registered_fb[con2fb_map[ops->currcon]]; |
|---|
| 213 | 230 | |
|---|
| 214 | 231 | if (info == fb_info) { |
|---|
| 215 | | - struct display *p = &fb_display[ops->currcon]; |
|---|
| 232 | + struct fbcon_display *p = &fb_display[ops->currcon]; |
|---|
| 216 | 233 | |
|---|
| 217 | 234 | if (rotate < 4) |
|---|
| 218 | 235 | p->con_rotate = rotate; |
|---|
| .. | .. |
|---|
| 227 | 244 | { |
|---|
| 228 | 245 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 229 | 246 | struct vc_data *vc; |
|---|
| 230 | | - struct display *p; |
|---|
| 247 | + struct fbcon_display *p; |
|---|
| 231 | 248 | int i; |
|---|
| 232 | 249 | |
|---|
| 233 | 250 | if (!ops || ops->currcon < 0 || rotate > 3) |
|---|
| .. | .. |
|---|
| 276 | 293 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 277 | 294 | |
|---|
| 278 | 295 | return (info->state != FBINFO_STATE_RUNNING || |
|---|
| 279 | | - vc->vc_mode != KD_TEXT || ops->graphics) && |
|---|
| 280 | | - !vt_force_oops_output(vc); |
|---|
| 296 | + vc->vc_mode != KD_TEXT || ops->graphics); |
|---|
| 281 | 297 | } |
|---|
| 282 | 298 | |
|---|
| 283 | 299 | static int get_color(struct vc_data *vc, struct fb_info *info, |
|---|
| .. | .. |
|---|
| 456 | 472 | options += 3; |
|---|
| 457 | 473 | if (*options) |
|---|
| 458 | 474 | first_fb_vc = simple_strtoul(options, &options, 10) - 1; |
|---|
| 459 | | - if (first_fb_vc < 0) |
|---|
| 475 | + if (first_fb_vc >= MAX_NR_CONSOLES) |
|---|
| 460 | 476 | first_fb_vc = 0; |
|---|
| 461 | 477 | if (*options++ == '-') |
|---|
| 462 | 478 | last_fb_vc = simple_strtoul(options, &options, 10) - 1; |
|---|
| 479 | + if (last_fb_vc < first_fb_vc || last_fb_vc >= MAX_NR_CONSOLES) |
|---|
| 480 | + last_fb_vc = MAX_NR_CONSOLES - 1; |
|---|
| 463 | 481 | fbcon_is_default = 0; |
|---|
| 464 | 482 | continue; |
|---|
| 465 | 483 | } |
|---|
| .. | .. |
|---|
| 485 | 503 | continue; |
|---|
| 486 | 504 | } |
|---|
| 487 | 505 | #endif |
|---|
| 506 | + |
|---|
| 507 | + if (!strncmp(options, "logo-pos:", 9)) { |
|---|
| 508 | + options += 9; |
|---|
| 509 | + if (!strcmp(options, "center")) |
|---|
| 510 | + fb_center_logo = true; |
|---|
| 511 | + continue; |
|---|
| 512 | + } |
|---|
| 513 | + |
|---|
| 514 | + if (!strncmp(options, "logo-count:", 11)) { |
|---|
| 515 | + options += 11; |
|---|
| 516 | + if (*options) |
|---|
| 517 | + fb_logo_count = simple_strtol(options, &options, 0); |
|---|
| 518 | + continue; |
|---|
| 519 | + } |
|---|
| 488 | 520 | } |
|---|
| 489 | 521 | return 1; |
|---|
| 490 | 522 | } |
|---|
| .. | .. |
|---|
| 577 | 609 | if (scr_readw(r) != vc->vc_video_erase_char) |
|---|
| 578 | 610 | break; |
|---|
| 579 | 611 | if (r != q && new_rows >= rows + logo_lines) { |
|---|
| 580 | | - save = kmalloc(array3_size(logo_lines, new_cols, 2), |
|---|
| 612 | + save = kzalloc(array3_size(logo_lines, new_cols, 2), |
|---|
| 581 | 613 | GFP_KERNEL); |
|---|
| 582 | 614 | if (save) { |
|---|
| 583 | 615 | int i = cols < new_cols ? cols : new_cols; |
|---|
| 584 | | - scr_memsetw(save, erase, logo_lines * new_cols * 2); |
|---|
| 616 | + scr_memsetw(save, erase, array3_size(logo_lines, new_cols, 2)); |
|---|
| 585 | 617 | r = q - step; |
|---|
| 586 | 618 | for (cnt = 0; cnt < logo_lines; cnt++, r += i) |
|---|
| 587 | 619 | scr_memcpyw(save + cnt * new_cols, r, 2 * i); |
|---|
| .. | .. |
|---|
| 597 | 629 | } |
|---|
| 598 | 630 | if (!save) { |
|---|
| 599 | 631 | int lines; |
|---|
| 600 | | - if (vc->vc_y + logo_lines >= rows) |
|---|
| 601 | | - lines = rows - vc->vc_y - 1; |
|---|
| 632 | + if (vc->state.y + logo_lines >= rows) |
|---|
| 633 | + lines = rows - vc->state.y - 1; |
|---|
| 602 | 634 | else |
|---|
| 603 | 635 | lines = logo_lines; |
|---|
| 604 | | - vc->vc_y += lines; |
|---|
| 636 | + vc->state.y += lines; |
|---|
| 605 | 637 | vc->vc_pos += lines * vc->vc_size_row; |
|---|
| 606 | 638 | } |
|---|
| 607 | 639 | } |
|---|
| .. | .. |
|---|
| 618 | 650 | q = (unsigned short *) (vc->vc_origin + |
|---|
| 619 | 651 | vc->vc_size_row * |
|---|
| 620 | 652 | rows); |
|---|
| 621 | | - scr_memcpyw(q, save, logo_lines * new_cols * 2); |
|---|
| 622 | | - vc->vc_y += logo_lines; |
|---|
| 653 | + scr_memcpyw(q, save, array3_size(logo_lines, new_cols, 2)); |
|---|
| 654 | + vc->state.y += logo_lines; |
|---|
| 623 | 655 | vc->vc_pos += logo_lines * vc->vc_size_row; |
|---|
| 624 | 656 | kfree(save); |
|---|
| 625 | 657 | } |
|---|
| 658 | + |
|---|
| 659 | + if (logo_shown == FBCON_LOGO_DONTSHOW) |
|---|
| 660 | + return; |
|---|
| 626 | 661 | |
|---|
| 627 | 662 | if (logo_lines > vc->vc_bottom) { |
|---|
| 628 | 663 | logo_shown = FBCON_LOGO_CANSHOW; |
|---|
| 629 | 664 | printk(KERN_INFO |
|---|
| 630 | 665 | "fbcon_init: disable boot-logo (boot-logo bigger than screen).\n"); |
|---|
| 631 | | - } else if (logo_shown != FBCON_LOGO_DONTSHOW) { |
|---|
| 666 | + } else { |
|---|
| 632 | 667 | logo_shown = FBCON_LOGO_DRAW; |
|---|
| 633 | 668 | vc->vc_top = logo_lines; |
|---|
| 634 | 669 | } |
|---|
| .. | .. |
|---|
| 812 | 847 | int oldidx = con2fb_map[unit]; |
|---|
| 813 | 848 | struct fb_info *info = registered_fb[newidx]; |
|---|
| 814 | 849 | struct fb_info *oldinfo = NULL; |
|---|
| 815 | | - int found, err = 0; |
|---|
| 850 | + int found, err = 0; |
|---|
| 816 | 851 | |
|---|
| 817 | 852 | WARN_CONSOLE_UNLOCKED(); |
|---|
| 818 | 853 | |
|---|
| .. | .. |
|---|
| 834 | 869 | |
|---|
| 835 | 870 | con2fb_map[unit] = newidx; |
|---|
| 836 | 871 | if (!err && !found) |
|---|
| 837 | | - err = con2fb_acquire_newinfo(vc, info, unit, oldidx); |
|---|
| 838 | | - |
|---|
| 872 | + err = con2fb_acquire_newinfo(vc, info, unit, oldidx); |
|---|
| 839 | 873 | |
|---|
| 840 | 874 | /* |
|---|
| 841 | 875 | * If old fb is not mapped to any of the consoles, |
|---|
| 842 | 876 | * fbcon should release it. |
|---|
| 843 | 877 | */ |
|---|
| 844 | | - if (!err && oldinfo && !search_fb_in_map(oldidx)) |
|---|
| 845 | | - err = con2fb_release_oldinfo(vc, oldinfo, info, unit, oldidx, |
|---|
| 846 | | - found); |
|---|
| 878 | + if (!err && oldinfo && !search_fb_in_map(oldidx)) |
|---|
| 879 | + err = con2fb_release_oldinfo(vc, oldinfo, info, unit, oldidx, |
|---|
| 880 | + found); |
|---|
| 847 | 881 | |
|---|
| 848 | | - if (!err) { |
|---|
| 849 | | - int show_logo = (fg_console == 0 && !user && |
|---|
| 850 | | - logo_shown != FBCON_LOGO_DONTSHOW); |
|---|
| 882 | + if (!err) { |
|---|
| 883 | + int show_logo = (fg_console == 0 && !user && |
|---|
| 884 | + logo_shown != FBCON_LOGO_DONTSHOW); |
|---|
| 851 | 885 | |
|---|
| 852 | | - if (!found) |
|---|
| 853 | | - fbcon_add_cursor_timer(info); |
|---|
| 854 | | - con2fb_map_boot[unit] = newidx; |
|---|
| 855 | | - con2fb_init_display(vc, info, unit, show_logo); |
|---|
| 886 | + if (!found) |
|---|
| 887 | + fbcon_add_cursor_timer(info); |
|---|
| 888 | + con2fb_map_boot[unit] = newidx; |
|---|
| 889 | + con2fb_init_display(vc, info, unit, show_logo); |
|---|
| 856 | 890 | } |
|---|
| 857 | 891 | |
|---|
| 858 | 892 | if (!search_fb_in_map(info_idx)) |
|---|
| 859 | 893 | info_idx = newidx; |
|---|
| 860 | 894 | |
|---|
| 861 | | - return err; |
|---|
| 895 | + return err; |
|---|
| 862 | 896 | } |
|---|
| 863 | 897 | |
|---|
| 864 | 898 | /* |
|---|
| 865 | 899 | * Low Level Operations |
|---|
| 866 | 900 | */ |
|---|
| 867 | 901 | /* NOTE: fbcon cannot be __init: it may be called from do_take_over_console later */ |
|---|
| 868 | | -static int var_to_display(struct display *disp, |
|---|
| 902 | +static int var_to_display(struct fbcon_display *disp, |
|---|
| 869 | 903 | struct fb_var_screeninfo *var, |
|---|
| 870 | 904 | struct fb_info *info) |
|---|
| 871 | 905 | { |
|---|
| .. | .. |
|---|
| 890 | 924 | } |
|---|
| 891 | 925 | |
|---|
| 892 | 926 | static void display_to_var(struct fb_var_screeninfo *var, |
|---|
| 893 | | - struct display *disp) |
|---|
| 927 | + struct fbcon_display *disp) |
|---|
| 894 | 928 | { |
|---|
| 895 | 929 | fb_videomode_to_var(var, disp->mode); |
|---|
| 896 | 930 | var->xres_virtual = disp->xres_virtual; |
|---|
| .. | .. |
|---|
| 911 | 945 | static const char *fbcon_startup(void) |
|---|
| 912 | 946 | { |
|---|
| 913 | 947 | const char *display_desc = "frame buffer device"; |
|---|
| 914 | | - struct display *p = &fb_display[fg_console]; |
|---|
| 948 | + struct fbcon_display *p = &fb_display[fg_console]; |
|---|
| 915 | 949 | struct vc_data *vc = vc_cons[fg_console].d; |
|---|
| 916 | 950 | const struct font_desc *font = NULL; |
|---|
| 917 | 951 | struct module *owner; |
|---|
| .. | .. |
|---|
| 990 | 1024 | info->var.bits_per_pixel); |
|---|
| 991 | 1025 | |
|---|
| 992 | 1026 | fbcon_add_cursor_timer(info); |
|---|
| 993 | | - fbcon_has_exited = 0; |
|---|
| 994 | 1027 | return display_desc; |
|---|
| 995 | 1028 | } |
|---|
| 996 | 1029 | |
|---|
| 997 | 1030 | static void fbcon_init(struct vc_data *vc, int init) |
|---|
| 998 | 1031 | { |
|---|
| 999 | | - struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1032 | + struct fb_info *info; |
|---|
| 1000 | 1033 | struct fbcon_ops *ops; |
|---|
| 1001 | 1034 | struct vc_data **default_mode = vc->vc_display_fg; |
|---|
| 1002 | 1035 | struct vc_data *svc = *default_mode; |
|---|
| 1003 | | - struct display *t, *p = &fb_display[vc->vc_num]; |
|---|
| 1036 | + struct fbcon_display *t, *p = &fb_display[vc->vc_num]; |
|---|
| 1004 | 1037 | int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256; |
|---|
| 1005 | 1038 | int cap, ret; |
|---|
| 1006 | 1039 | |
|---|
| 1007 | | - if (info_idx == -1 || info == NULL) |
|---|
| 1040 | + if (WARN_ON(info_idx == -1)) |
|---|
| 1008 | 1041 | return; |
|---|
| 1009 | 1042 | |
|---|
| 1043 | + if (con2fb_map[vc->vc_num] == -1) |
|---|
| 1044 | + con2fb_map[vc->vc_num] = info_idx; |
|---|
| 1045 | + |
|---|
| 1046 | + info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1010 | 1047 | cap = info->flags; |
|---|
| 1048 | + |
|---|
| 1049 | + if (logo_shown < 0 && console_loglevel <= CONSOLE_LOGLEVEL_QUIET) |
|---|
| 1050 | + logo_shown = FBCON_LOGO_DONTSHOW; |
|---|
| 1011 | 1051 | |
|---|
| 1012 | 1052 | if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW || |
|---|
| 1013 | 1053 | (info->fix.type == FB_TYPE_TEXT)) |
|---|
| .. | .. |
|---|
| 1053 | 1093 | if (p->userfont) |
|---|
| 1054 | 1094 | charcnt = FNTCHARCNT(p->fontdata); |
|---|
| 1055 | 1095 | |
|---|
| 1056 | | - vc->vc_panic_force_write = !!(info->flags & FBINFO_CAN_FORCE_OUTPUT); |
|---|
| 1057 | 1096 | vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); |
|---|
| 1058 | 1097 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; |
|---|
| 1059 | 1098 | if (charcnt == 256) { |
|---|
| .. | .. |
|---|
| 1110 | 1149 | |
|---|
| 1111 | 1150 | ops->graphics = 0; |
|---|
| 1112 | 1151 | |
|---|
| 1152 | +#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION |
|---|
| 1113 | 1153 | if ((cap & FBINFO_HWACCEL_COPYAREA) && |
|---|
| 1114 | 1154 | !(cap & FBINFO_HWACCEL_DISABLED)) |
|---|
| 1115 | 1155 | p->scrollmode = SCROLL_MOVE; |
|---|
| 1116 | 1156 | else /* default to something safe */ |
|---|
| 1117 | 1157 | p->scrollmode = SCROLL_REDRAW; |
|---|
| 1158 | +#endif |
|---|
| 1118 | 1159 | |
|---|
| 1119 | 1160 | /* |
|---|
| 1120 | 1161 | * ++guenther: console.c:vc_allocate() relies on initializing |
|---|
| .. | .. |
|---|
| 1138 | 1179 | ops->p = &fb_display[fg_console]; |
|---|
| 1139 | 1180 | } |
|---|
| 1140 | 1181 | |
|---|
| 1141 | | -static void fbcon_free_font(struct display *p, bool freefont) |
|---|
| 1182 | +static void fbcon_free_font(struct fbcon_display *p, bool freefont) |
|---|
| 1142 | 1183 | { |
|---|
| 1143 | 1184 | if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) |
|---|
| 1144 | 1185 | kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); |
|---|
| .. | .. |
|---|
| 1150 | 1191 | |
|---|
| 1151 | 1192 | static void fbcon_deinit(struct vc_data *vc) |
|---|
| 1152 | 1193 | { |
|---|
| 1153 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 1194 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 1154 | 1195 | struct fb_info *info; |
|---|
| 1155 | 1196 | struct fbcon_ops *ops; |
|---|
| 1156 | 1197 | int idx; |
|---|
| .. | .. |
|---|
| 1226 | 1267 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1227 | 1268 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 1228 | 1269 | |
|---|
| 1229 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 1270 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 1230 | 1271 | u_int y_break; |
|---|
| 1231 | 1272 | |
|---|
| 1232 | 1273 | if (fbcon_is_inactive(vc, info)) |
|---|
| .. | .. |
|---|
| 1262 | 1303 | int count, int ypos, int xpos) |
|---|
| 1263 | 1304 | { |
|---|
| 1264 | 1305 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1265 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 1306 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 1266 | 1307 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 1267 | 1308 | |
|---|
| 1268 | 1309 | if (!fbcon_is_inactive(vc, info)) |
|---|
| .. | .. |
|---|
| 1299 | 1340 | if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1) |
|---|
| 1300 | 1341 | return; |
|---|
| 1301 | 1342 | |
|---|
| 1302 | | - if (vc->vc_cursor_type & 0x10) |
|---|
| 1343 | + if (vc->vc_cursor_type & CUR_SW) |
|---|
| 1303 | 1344 | fbcon_del_cursor_timer(info); |
|---|
| 1304 | 1345 | else |
|---|
| 1305 | 1346 | fbcon_add_cursor_timer(info); |
|---|
| .. | .. |
|---|
| 1320 | 1361 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, |
|---|
| 1321 | 1362 | int unit) |
|---|
| 1322 | 1363 | { |
|---|
| 1323 | | - struct display *p, *t; |
|---|
| 1364 | + struct fbcon_display *p, *t; |
|---|
| 1324 | 1365 | struct vc_data **default_mode, *vc; |
|---|
| 1325 | 1366 | struct vc_data *svc; |
|---|
| 1326 | 1367 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| .. | .. |
|---|
| 1387 | 1428 | { |
|---|
| 1388 | 1429 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1389 | 1430 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 1390 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 1431 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 1391 | 1432 | |
|---|
| 1392 | 1433 | p->yscroll += count; |
|---|
| 1393 | 1434 | if (p->yscroll >= p->vrows) /* Deal with wrap */ |
|---|
| .. | .. |
|---|
| 1406 | 1447 | { |
|---|
| 1407 | 1448 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1408 | 1449 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 1409 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 1450 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 1410 | 1451 | |
|---|
| 1411 | 1452 | p->yscroll -= count; |
|---|
| 1412 | 1453 | if (p->yscroll < 0) /* Deal with wrap */ |
|---|
| .. | .. |
|---|
| 1424 | 1465 | static __inline__ void ypan_up(struct vc_data *vc, int count) |
|---|
| 1425 | 1466 | { |
|---|
| 1426 | 1467 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1427 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 1468 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 1428 | 1469 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 1429 | 1470 | |
|---|
| 1430 | 1471 | p->yscroll += count; |
|---|
| .. | .. |
|---|
| 1449 | 1490 | { |
|---|
| 1450 | 1491 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1451 | 1492 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 1452 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 1493 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 1453 | 1494 | |
|---|
| 1454 | 1495 | p->yscroll += count; |
|---|
| 1455 | 1496 | |
|---|
| .. | .. |
|---|
| 1472 | 1513 | static __inline__ void ypan_down(struct vc_data *vc, int count) |
|---|
| 1473 | 1514 | { |
|---|
| 1474 | 1515 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1475 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 1516 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 1476 | 1517 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 1477 | 1518 | |
|---|
| 1478 | 1519 | p->yscroll -= count; |
|---|
| .. | .. |
|---|
| 1497 | 1538 | { |
|---|
| 1498 | 1539 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1499 | 1540 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 1500 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 1541 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 1501 | 1542 | |
|---|
| 1502 | 1543 | p->yscroll -= count; |
|---|
| 1503 | 1544 | |
|---|
| .. | .. |
|---|
| 1517 | 1558 | scrollback_current = 0; |
|---|
| 1518 | 1559 | } |
|---|
| 1519 | 1560 | |
|---|
| 1520 | | -static void fbcon_redraw_move(struct vc_data *vc, struct display *p, |
|---|
| 1561 | +static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p, |
|---|
| 1521 | 1562 | int line, int count, int dy) |
|---|
| 1522 | 1563 | { |
|---|
| 1523 | 1564 | unsigned short *s = (unsigned short *) |
|---|
| .. | .. |
|---|
| 1552 | 1593 | } |
|---|
| 1553 | 1594 | |
|---|
| 1554 | 1595 | static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info, |
|---|
| 1555 | | - struct display *p, int line, int count, int ycount) |
|---|
| 1596 | + struct fbcon_display *p, int line, int count, int ycount) |
|---|
| 1556 | 1597 | { |
|---|
| 1557 | 1598 | int offset = ycount * vc->vc_cols; |
|---|
| 1558 | 1599 | unsigned short *d = (unsigned short *) |
|---|
| .. | .. |
|---|
| 1601 | 1642 | } |
|---|
| 1602 | 1643 | } |
|---|
| 1603 | 1644 | |
|---|
| 1604 | | -static void fbcon_redraw(struct vc_data *vc, struct display *p, |
|---|
| 1645 | +static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p, |
|---|
| 1605 | 1646 | int line, int count, int offset) |
|---|
| 1606 | 1647 | { |
|---|
| 1607 | 1648 | unsigned short *d = (unsigned short *) |
|---|
| .. | .. |
|---|
| 1660 | 1701 | enum con_scroll dir, unsigned int count) |
|---|
| 1661 | 1702 | { |
|---|
| 1662 | 1703 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1663 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 1704 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 1664 | 1705 | int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK; |
|---|
| 1665 | 1706 | |
|---|
| 1666 | 1707 | if (fbcon_is_inactive(vc, info)) |
|---|
| .. | .. |
|---|
| 1678 | 1719 | case SM_UP: |
|---|
| 1679 | 1720 | if (count > vc->vc_rows) /* Maximum realistic size */ |
|---|
| 1680 | 1721 | count = vc->vc_rows; |
|---|
| 1681 | | - if (logo_shown >= 0) |
|---|
| 1682 | | - goto redraw_up; |
|---|
| 1683 | | - switch (p->scrollmode) { |
|---|
| 1722 | + switch (fb_scrollmode(p)) { |
|---|
| 1684 | 1723 | case SCROLL_MOVE: |
|---|
| 1685 | 1724 | fbcon_redraw_blit(vc, info, p, t, b - t - count, |
|---|
| 1686 | 1725 | count); |
|---|
| .. | .. |
|---|
| 1691 | 1730 | vc->vc_video_erase_char, |
|---|
| 1692 | 1731 | vc->vc_size_row * count); |
|---|
| 1693 | 1732 | return true; |
|---|
| 1694 | | - break; |
|---|
| 1695 | 1733 | |
|---|
| 1696 | 1734 | case SCROLL_WRAP_MOVE: |
|---|
| 1697 | 1735 | if (b - t - count > 3 * vc->vc_rows >> 2) { |
|---|
| .. | .. |
|---|
| 1769 | 1807 | case SM_DOWN: |
|---|
| 1770 | 1808 | if (count > vc->vc_rows) /* Maximum realistic size */ |
|---|
| 1771 | 1809 | count = vc->vc_rows; |
|---|
| 1772 | | - if (logo_shown >= 0) |
|---|
| 1773 | | - goto redraw_down; |
|---|
| 1774 | | - switch (p->scrollmode) { |
|---|
| 1810 | + switch (fb_scrollmode(p)) { |
|---|
| 1775 | 1811 | case SCROLL_MOVE: |
|---|
| 1776 | 1812 | fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, |
|---|
| 1777 | 1813 | -count); |
|---|
| .. | .. |
|---|
| 1782 | 1818 | vc->vc_video_erase_char, |
|---|
| 1783 | 1819 | vc->vc_size_row * count); |
|---|
| 1784 | 1820 | return true; |
|---|
| 1785 | | - break; |
|---|
| 1786 | 1821 | |
|---|
| 1787 | 1822 | case SCROLL_WRAP_MOVE: |
|---|
| 1788 | 1823 | if (b - t - count > 3 * vc->vc_rows >> 2) { |
|---|
| .. | .. |
|---|
| 1862 | 1897 | int height, int width) |
|---|
| 1863 | 1898 | { |
|---|
| 1864 | 1899 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1865 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 1900 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 1866 | 1901 | |
|---|
| 1867 | 1902 | if (fbcon_is_inactive(vc, info)) |
|---|
| 1868 | 1903 | return; |
|---|
| .. | .. |
|---|
| 1881 | 1916 | p->vrows - p->yscroll); |
|---|
| 1882 | 1917 | } |
|---|
| 1883 | 1918 | |
|---|
| 1884 | | -static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx, |
|---|
| 1919 | +static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx, |
|---|
| 1885 | 1920 | int dy, int dx, int height, int width, u_int y_break) |
|---|
| 1886 | 1921 | { |
|---|
| 1887 | 1922 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| .. | .. |
|---|
| 1923 | 1958 | height, width); |
|---|
| 1924 | 1959 | } |
|---|
| 1925 | 1960 | |
|---|
| 1926 | | -static void updatescrollmode(struct display *p, |
|---|
| 1961 | +static void updatescrollmode_accel(struct fbcon_display *p, |
|---|
| 1927 | 1962 | struct fb_info *info, |
|---|
| 1928 | 1963 | struct vc_data *vc) |
|---|
| 1929 | 1964 | { |
|---|
| 1965 | +#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION |
|---|
| 1930 | 1966 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 1931 | | - int fh = vc->vc_font.height; |
|---|
| 1932 | 1967 | int cap = info->flags; |
|---|
| 1933 | 1968 | u16 t = 0; |
|---|
| 1934 | 1969 | int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep, |
|---|
| .. | .. |
|---|
| 1949 | 1984 | int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && |
|---|
| 1950 | 1985 | !(cap & FBINFO_HWACCEL_DISABLED); |
|---|
| 1951 | 1986 | |
|---|
| 1952 | | - p->vrows = vyres/fh; |
|---|
| 1953 | | - if (yres > (fh * (vc->vc_rows + 1))) |
|---|
| 1954 | | - p->vrows -= (yres - (fh * vc->vc_rows)) / fh; |
|---|
| 1955 | | - if ((yres % fh) && (vyres % fh < yres % fh)) |
|---|
| 1956 | | - p->vrows--; |
|---|
| 1957 | | - |
|---|
| 1958 | 1987 | if (good_wrap || good_pan) { |
|---|
| 1959 | 1988 | if (reading_fast || fast_copyarea) |
|---|
| 1960 | 1989 | p->scrollmode = good_wrap ? |
|---|
| .. | .. |
|---|
| 1968 | 1997 | else |
|---|
| 1969 | 1998 | p->scrollmode = SCROLL_REDRAW; |
|---|
| 1970 | 1999 | } |
|---|
| 2000 | +#endif |
|---|
| 2001 | +} |
|---|
| 2002 | + |
|---|
| 2003 | +static void updatescrollmode(struct fbcon_display *p, |
|---|
| 2004 | + struct fb_info *info, |
|---|
| 2005 | + struct vc_data *vc) |
|---|
| 2006 | +{ |
|---|
| 2007 | + struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 2008 | + int fh = vc->vc_font.height; |
|---|
| 2009 | + int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); |
|---|
| 2010 | + int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual, |
|---|
| 2011 | + info->var.xres_virtual); |
|---|
| 2012 | + |
|---|
| 2013 | + p->vrows = vyres/fh; |
|---|
| 2014 | + if (yres > (fh * (vc->vc_rows + 1))) |
|---|
| 2015 | + p->vrows -= (yres - (fh * vc->vc_rows)) / fh; |
|---|
| 2016 | + if ((yres % fh) && (vyres % fh < yres % fh)) |
|---|
| 2017 | + p->vrows--; |
|---|
| 2018 | + |
|---|
| 2019 | + /* update scrollmode in case hardware acceleration is used */ |
|---|
| 2020 | + updatescrollmode_accel(p, info, vc); |
|---|
| 1971 | 2021 | } |
|---|
| 1972 | 2022 | |
|---|
| 1973 | 2023 | #define PITCH(w) (((w) + 7) >> 3) |
|---|
| .. | .. |
|---|
| 1978 | 2028 | { |
|---|
| 1979 | 2029 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 1980 | 2030 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 1981 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 2031 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 1982 | 2032 | struct fb_var_screeninfo var = info->var; |
|---|
| 1983 | 2033 | int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh; |
|---|
| 1984 | 2034 | |
|---|
| .. | .. |
|---|
| 2041 | 2091 | { |
|---|
| 2042 | 2092 | struct fb_info *info, *old_info = NULL; |
|---|
| 2043 | 2093 | struct fbcon_ops *ops; |
|---|
| 2044 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 2094 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 2045 | 2095 | struct fb_var_screeninfo var; |
|---|
| 2046 | 2096 | int i, ret, prev_console, charcnt = 256; |
|---|
| 2047 | 2097 | |
|---|
| .. | .. |
|---|
| 2128 | 2178 | |
|---|
| 2129 | 2179 | updatescrollmode(p, info, vc); |
|---|
| 2130 | 2180 | |
|---|
| 2131 | | - switch (p->scrollmode) { |
|---|
| 2181 | + switch (fb_scrollmode(p)) { |
|---|
| 2132 | 2182 | case SCROLL_WRAP_MOVE: |
|---|
| 2133 | 2183 | scrollback_phys_max = p->vrows - vc->vc_rows; |
|---|
| 2134 | 2184 | break; |
|---|
| .. | .. |
|---|
| 2171 | 2221 | static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info, |
|---|
| 2172 | 2222 | int blank) |
|---|
| 2173 | 2223 | { |
|---|
| 2174 | | - struct fb_event event; |
|---|
| 2175 | | - |
|---|
| 2176 | 2224 | if (blank) { |
|---|
| 2177 | 2225 | unsigned short charmask = vc->vc_hi_font_mask ? |
|---|
| 2178 | 2226 | 0x1ff : 0xff; |
|---|
| .. | .. |
|---|
| 2183 | 2231 | fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols); |
|---|
| 2184 | 2232 | vc->vc_video_erase_char = oldc; |
|---|
| 2185 | 2233 | } |
|---|
| 2186 | | - |
|---|
| 2187 | | - |
|---|
| 2188 | | - if (!lock_fb_info(info)) |
|---|
| 2189 | | - return; |
|---|
| 2190 | | - event.info = info; |
|---|
| 2191 | | - event.data = ␣ |
|---|
| 2192 | | - fb_notifier_call_chain(FB_EVENT_CONBLANK, &event); |
|---|
| 2193 | | - unlock_fb_info(info); |
|---|
| 2194 | 2234 | } |
|---|
| 2195 | 2235 | |
|---|
| 2196 | 2236 | static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) |
|---|
| .. | .. |
|---|
| 2204 | 2244 | ops->graphics = 1; |
|---|
| 2205 | 2245 | |
|---|
| 2206 | 2246 | if (!blank) { |
|---|
| 2207 | | - var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; |
|---|
| 2247 | + var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE | |
|---|
| 2248 | + FB_ACTIVATE_KD_TEXT; |
|---|
| 2208 | 2249 | fb_set_var(info, &var); |
|---|
| 2209 | 2250 | ops->graphics = 0; |
|---|
| 2210 | 2251 | ops->var = info->var; |
|---|
| .. | .. |
|---|
| 2217 | 2258 | fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); |
|---|
| 2218 | 2259 | ops->cursor_flash = (!blank); |
|---|
| 2219 | 2260 | |
|---|
| 2220 | | - if (!(info->flags & FBINFO_MISC_USEREVENT)) |
|---|
| 2221 | | - if (fb_blank(info, blank)) |
|---|
| 2222 | | - fbcon_generic_blank(vc, info, blank); |
|---|
| 2261 | + if (fb_blank(info, blank)) |
|---|
| 2262 | + fbcon_generic_blank(vc, info, blank); |
|---|
| 2223 | 2263 | } |
|---|
| 2224 | 2264 | |
|---|
| 2225 | 2265 | if (!blank) |
|---|
| .. | .. |
|---|
| 2388 | 2428 | { |
|---|
| 2389 | 2429 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
|---|
| 2390 | 2430 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 2391 | | - struct display *p = &fb_display[vc->vc_num]; |
|---|
| 2431 | + struct fbcon_display *p = &fb_display[vc->vc_num]; |
|---|
| 2392 | 2432 | int resize; |
|---|
| 2393 | 2433 | int cnt; |
|---|
| 2394 | 2434 | char *old_data = NULL; |
|---|
| .. | .. |
|---|
| 2431 | 2471 | |
|---|
| 2432 | 2472 | static int fbcon_copy_font(struct vc_data *vc, int con) |
|---|
| 2433 | 2473 | { |
|---|
| 2434 | | - struct display *od = &fb_display[con]; |
|---|
| 2474 | + struct fbcon_display *od = &fb_display[con]; |
|---|
| 2435 | 2475 | struct console_font *f = &vc->vc_font; |
|---|
| 2436 | 2476 | |
|---|
| 2437 | 2477 | if (od->fontdata == f->data) |
|---|
| .. | .. |
|---|
| 2468 | 2508 | if (charcount != 256 && charcount != 512) |
|---|
| 2469 | 2509 | return -EINVAL; |
|---|
| 2470 | 2510 | |
|---|
| 2511 | + /* font bigger than screen resolution ? */ |
|---|
| 2512 | + if (w > FBCON_SWAP(info->var.rotate, info->var.xres, info->var.yres) || |
|---|
| 2513 | + h > FBCON_SWAP(info->var.rotate, info->var.yres, info->var.xres)) |
|---|
| 2514 | + return -EINVAL; |
|---|
| 2515 | + |
|---|
| 2516 | + if (font->width > 32 || font->height > 32) |
|---|
| 2517 | + return -EINVAL; |
|---|
| 2518 | + |
|---|
| 2471 | 2519 | /* Make sure drawing engine can handle the font */ |
|---|
| 2472 | | - if (!(info->pixmap.blit_x & (1 << (font->width - 1))) || |
|---|
| 2473 | | - !(info->pixmap.blit_y & (1 << (font->height - 1)))) |
|---|
| 2520 | + if (!(info->pixmap.blit_x & BIT(font->width - 1)) || |
|---|
| 2521 | + !(info->pixmap.blit_y & BIT(font->height - 1))) |
|---|
| 2474 | 2522 | return -EINVAL; |
|---|
| 2475 | 2523 | |
|---|
| 2476 | 2524 | /* Make sure driver can handle the font length */ |
|---|
| .. | .. |
|---|
| 2574 | 2622 | fb_set_cmap(&palette_cmap, info); |
|---|
| 2575 | 2623 | } |
|---|
| 2576 | 2624 | |
|---|
| 2577 | | -static u16 *fbcon_screen_pos(struct vc_data *vc, int offset) |
|---|
| 2625 | +static u16 *fbcon_screen_pos(const struct vc_data *vc, int offset) |
|---|
| 2578 | 2626 | { |
|---|
| 2579 | 2627 | return (u16 *) (vc->vc_origin + offset); |
|---|
| 2580 | 2628 | } |
|---|
| .. | .. |
|---|
| 2621 | 2669 | } |
|---|
| 2622 | 2670 | } |
|---|
| 2623 | 2671 | |
|---|
| 2624 | | -static int fbcon_set_origin(struct vc_data *vc) |
|---|
| 2625 | | -{ |
|---|
| 2626 | | - return 0; |
|---|
| 2627 | | -} |
|---|
| 2628 | | - |
|---|
| 2629 | | -static void fbcon_suspended(struct fb_info *info) |
|---|
| 2672 | +void fbcon_suspended(struct fb_info *info) |
|---|
| 2630 | 2673 | { |
|---|
| 2631 | 2674 | struct vc_data *vc = NULL; |
|---|
| 2632 | 2675 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| .. | .. |
|---|
| 2639 | 2682 | fbcon_cursor(vc, CM_ERASE); |
|---|
| 2640 | 2683 | } |
|---|
| 2641 | 2684 | |
|---|
| 2642 | | -static void fbcon_resumed(struct fb_info *info) |
|---|
| 2685 | +void fbcon_resumed(struct fb_info *info) |
|---|
| 2643 | 2686 | { |
|---|
| 2644 | 2687 | struct vc_data *vc; |
|---|
| 2645 | 2688 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| .. | .. |
|---|
| 2655 | 2698 | { |
|---|
| 2656 | 2699 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 2657 | 2700 | struct vc_data *vc; |
|---|
| 2658 | | - struct display *p; |
|---|
| 2701 | + struct fbcon_display *p; |
|---|
| 2659 | 2702 | int rows, cols; |
|---|
| 2660 | 2703 | |
|---|
| 2661 | 2704 | if (!ops || ops->currcon < 0) |
|---|
| .. | .. |
|---|
| 2693 | 2736 | { |
|---|
| 2694 | 2737 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 2695 | 2738 | struct vc_data *vc; |
|---|
| 2696 | | - struct display *p; |
|---|
| 2739 | + struct fbcon_display *p; |
|---|
| 2697 | 2740 | int i, rows, cols, fg = -1; |
|---|
| 2698 | 2741 | |
|---|
| 2699 | 2742 | if (!ops || ops->currcon < 0) |
|---|
| .. | .. |
|---|
| 2724 | 2767 | fbcon_modechanged(info); |
|---|
| 2725 | 2768 | } |
|---|
| 2726 | 2769 | |
|---|
| 2727 | | -static int fbcon_mode_deleted(struct fb_info *info, |
|---|
| 2728 | | - struct fb_videomode *mode) |
|---|
| 2770 | + |
|---|
| 2771 | +void fbcon_update_vcs(struct fb_info *info, bool all) |
|---|
| 2772 | +{ |
|---|
| 2773 | + if (all) |
|---|
| 2774 | + fbcon_set_all_vcs(info); |
|---|
| 2775 | + else |
|---|
| 2776 | + fbcon_modechanged(info); |
|---|
| 2777 | +} |
|---|
| 2778 | +EXPORT_SYMBOL(fbcon_update_vcs); |
|---|
| 2779 | + |
|---|
| 2780 | +/* let fbcon check if it supports a new screen resolution */ |
|---|
| 2781 | +int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var) |
|---|
| 2782 | +{ |
|---|
| 2783 | + struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 2784 | + struct vc_data *vc; |
|---|
| 2785 | + unsigned int i; |
|---|
| 2786 | + |
|---|
| 2787 | + WARN_CONSOLE_UNLOCKED(); |
|---|
| 2788 | + |
|---|
| 2789 | + if (!ops) |
|---|
| 2790 | + return 0; |
|---|
| 2791 | + |
|---|
| 2792 | + /* prevent setting a screen size which is smaller than font size */ |
|---|
| 2793 | + for (i = first_fb_vc; i <= last_fb_vc; i++) { |
|---|
| 2794 | + vc = vc_cons[i].d; |
|---|
| 2795 | + if (!vc || vc->vc_mode != KD_TEXT || |
|---|
| 2796 | + registered_fb[con2fb_map[i]] != info) |
|---|
| 2797 | + continue; |
|---|
| 2798 | + |
|---|
| 2799 | + if (vc->vc_font.width > FBCON_SWAP(var->rotate, var->xres, var->yres) || |
|---|
| 2800 | + vc->vc_font.height > FBCON_SWAP(var->rotate, var->yres, var->xres)) |
|---|
| 2801 | + return -EINVAL; |
|---|
| 2802 | + } |
|---|
| 2803 | + |
|---|
| 2804 | + return 0; |
|---|
| 2805 | +} |
|---|
| 2806 | +EXPORT_SYMBOL_GPL(fbcon_modechange_possible); |
|---|
| 2807 | + |
|---|
| 2808 | +int fbcon_mode_deleted(struct fb_info *info, |
|---|
| 2809 | + struct fb_videomode *mode) |
|---|
| 2729 | 2810 | { |
|---|
| 2730 | 2811 | struct fb_info *fb_info; |
|---|
| 2731 | | - struct display *p; |
|---|
| 2812 | + struct fbcon_display *p; |
|---|
| 2732 | 2813 | int i, j, found = 0; |
|---|
| 2733 | 2814 | |
|---|
| 2734 | 2815 | /* before deletion, ensure that mode is not in use */ |
|---|
| .. | .. |
|---|
| 2751 | 2832 | } |
|---|
| 2752 | 2833 | |
|---|
| 2753 | 2834 | #ifdef CONFIG_VT_HW_CONSOLE_BINDING |
|---|
| 2754 | | -static int fbcon_unbind(void) |
|---|
| 2835 | +static void fbcon_unbind(void) |
|---|
| 2755 | 2836 | { |
|---|
| 2756 | 2837 | int ret; |
|---|
| 2757 | 2838 | |
|---|
| .. | .. |
|---|
| 2760 | 2841 | |
|---|
| 2761 | 2842 | if (!ret) |
|---|
| 2762 | 2843 | fbcon_has_console_bind = 0; |
|---|
| 2763 | | - |
|---|
| 2764 | | - return ret; |
|---|
| 2765 | 2844 | } |
|---|
| 2766 | 2845 | #else |
|---|
| 2767 | | -static inline int fbcon_unbind(void) |
|---|
| 2768 | | -{ |
|---|
| 2769 | | - return -EINVAL; |
|---|
| 2770 | | -} |
|---|
| 2846 | +static inline void fbcon_unbind(void) {} |
|---|
| 2771 | 2847 | #endif /* CONFIG_VT_HW_CONSOLE_BINDING */ |
|---|
| 2772 | 2848 | |
|---|
| 2773 | 2849 | /* called with console_lock held */ |
|---|
| 2774 | | -static int fbcon_fb_unbind(int idx) |
|---|
| 2850 | +void fbcon_fb_unbind(struct fb_info *info) |
|---|
| 2775 | 2851 | { |
|---|
| 2776 | 2852 | int i, new_idx = -1, ret = 0; |
|---|
| 2853 | + int idx = info->node; |
|---|
| 2777 | 2854 | |
|---|
| 2778 | 2855 | WARN_CONSOLE_UNLOCKED(); |
|---|
| 2779 | 2856 | |
|---|
| 2780 | 2857 | if (!fbcon_has_console_bind) |
|---|
| 2781 | | - return 0; |
|---|
| 2858 | + return; |
|---|
| 2782 | 2859 | |
|---|
| 2783 | 2860 | for (i = first_fb_vc; i <= last_fb_vc; i++) { |
|---|
| 2784 | 2861 | if (con2fb_map[i] != idx && |
|---|
| .. | .. |
|---|
| 2811 | 2888 | idx, 0); |
|---|
| 2812 | 2889 | if (ret) { |
|---|
| 2813 | 2890 | con2fb_map[i] = idx; |
|---|
| 2814 | | - return ret; |
|---|
| 2891 | + return; |
|---|
| 2815 | 2892 | } |
|---|
| 2816 | 2893 | } |
|---|
| 2817 | 2894 | } |
|---|
| 2818 | 2895 | } |
|---|
| 2819 | | - ret = fbcon_unbind(); |
|---|
| 2896 | + fbcon_unbind(); |
|---|
| 2820 | 2897 | } |
|---|
| 2821 | | - |
|---|
| 2822 | | - return ret; |
|---|
| 2823 | 2898 | } |
|---|
| 2824 | 2899 | |
|---|
| 2825 | 2900 | /* called with console_lock held */ |
|---|
| 2826 | | -static int fbcon_fb_unregistered(struct fb_info *info) |
|---|
| 2901 | +void fbcon_fb_unregistered(struct fb_info *info) |
|---|
| 2827 | 2902 | { |
|---|
| 2828 | 2903 | int i, idx; |
|---|
| 2829 | 2904 | |
|---|
| 2830 | 2905 | WARN_CONSOLE_UNLOCKED(); |
|---|
| 2831 | 2906 | |
|---|
| 2832 | 2907 | if (deferred_takeover) |
|---|
| 2833 | | - return 0; |
|---|
| 2908 | + return; |
|---|
| 2834 | 2909 | |
|---|
| 2835 | 2910 | idx = info->node; |
|---|
| 2836 | 2911 | for (i = first_fb_vc; i <= last_fb_vc; i++) { |
|---|
| .. | .. |
|---|
| 2859 | 2934 | |
|---|
| 2860 | 2935 | if (!num_registered_fb) |
|---|
| 2861 | 2936 | do_unregister_con_driver(&fb_con); |
|---|
| 2862 | | - |
|---|
| 2863 | | - return 0; |
|---|
| 2864 | 2937 | } |
|---|
| 2865 | 2938 | |
|---|
| 2866 | | -/* called with console_lock held */ |
|---|
| 2867 | | -static void fbcon_remap_all(int idx) |
|---|
| 2939 | +void fbcon_remap_all(struct fb_info *info) |
|---|
| 2868 | 2940 | { |
|---|
| 2869 | | - int i; |
|---|
| 2941 | + int i, idx = info->node; |
|---|
| 2870 | 2942 | |
|---|
| 2871 | | - WARN_CONSOLE_UNLOCKED(); |
|---|
| 2872 | | - |
|---|
| 2943 | + console_lock(); |
|---|
| 2873 | 2944 | if (deferred_takeover) { |
|---|
| 2874 | 2945 | for (i = first_fb_vc; i <= last_fb_vc; i++) |
|---|
| 2875 | 2946 | con2fb_map_boot[i] = idx; |
|---|
| 2876 | 2947 | fbcon_map_override(); |
|---|
| 2948 | + console_unlock(); |
|---|
| 2877 | 2949 | return; |
|---|
| 2878 | 2950 | } |
|---|
| 2879 | 2951 | |
|---|
| .. | .. |
|---|
| 2886 | 2958 | first_fb_vc + 1, last_fb_vc + 1); |
|---|
| 2887 | 2959 | info_idx = idx; |
|---|
| 2888 | 2960 | } |
|---|
| 2961 | + console_unlock(); |
|---|
| 2889 | 2962 | } |
|---|
| 2890 | 2963 | |
|---|
| 2891 | 2964 | #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY |
|---|
| .. | .. |
|---|
| 2919 | 2992 | #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */ |
|---|
| 2920 | 2993 | |
|---|
| 2921 | 2994 | /* called with console_lock held */ |
|---|
| 2922 | | -static int fbcon_fb_registered(struct fb_info *info) |
|---|
| 2995 | +int fbcon_fb_registered(struct fb_info *info) |
|---|
| 2923 | 2996 | { |
|---|
| 2924 | 2997 | int ret = 0, i, idx; |
|---|
| 2925 | 2998 | |
|---|
| .. | .. |
|---|
| 2953 | 3026 | return ret; |
|---|
| 2954 | 3027 | } |
|---|
| 2955 | 3028 | |
|---|
| 2956 | | -static void fbcon_fb_blanked(struct fb_info *info, int blank) |
|---|
| 3029 | +void fbcon_fb_blanked(struct fb_info *info, int blank) |
|---|
| 2957 | 3030 | { |
|---|
| 2958 | 3031 | struct fbcon_ops *ops = info->fbcon_par; |
|---|
| 2959 | 3032 | struct vc_data *vc; |
|---|
| .. | .. |
|---|
| 2975 | 3048 | ops->blank_state = blank; |
|---|
| 2976 | 3049 | } |
|---|
| 2977 | 3050 | |
|---|
| 2978 | | -static void fbcon_new_modelist(struct fb_info *info) |
|---|
| 3051 | +void fbcon_new_modelist(struct fb_info *info) |
|---|
| 2979 | 3052 | { |
|---|
| 2980 | 3053 | int i; |
|---|
| 2981 | 3054 | struct vc_data *vc; |
|---|
| .. | .. |
|---|
| 2996 | 3069 | } |
|---|
| 2997 | 3070 | } |
|---|
| 2998 | 3071 | |
|---|
| 2999 | | -static void fbcon_get_requirement(struct fb_info *info, |
|---|
| 3000 | | - struct fb_blit_caps *caps) |
|---|
| 3072 | +void fbcon_get_requirement(struct fb_info *info, |
|---|
| 3073 | + struct fb_blit_caps *caps) |
|---|
| 3001 | 3074 | { |
|---|
| 3002 | 3075 | struct vc_data *vc; |
|---|
| 3003 | | - struct display *p; |
|---|
| 3076 | + struct fbcon_display *p; |
|---|
| 3004 | 3077 | |
|---|
| 3005 | 3078 | if (caps->flags) { |
|---|
| 3006 | 3079 | int i, charcnt; |
|---|
| .. | .. |
|---|
| 3032 | 3105 | } |
|---|
| 3033 | 3106 | } |
|---|
| 3034 | 3107 | |
|---|
| 3035 | | -static int fbcon_event_notify(struct notifier_block *self, |
|---|
| 3036 | | - unsigned long action, void *data) |
|---|
| 3108 | +int fbcon_set_con2fb_map_ioctl(void __user *argp) |
|---|
| 3037 | 3109 | { |
|---|
| 3038 | | - struct fb_event *event = data; |
|---|
| 3039 | | - struct fb_info *info = event->info; |
|---|
| 3040 | | - struct fb_videomode *mode; |
|---|
| 3041 | | - struct fb_con2fbmap *con2fb; |
|---|
| 3042 | | - struct fb_blit_caps *caps; |
|---|
| 3043 | | - int idx, ret = 0; |
|---|
| 3110 | + struct fb_con2fbmap con2fb; |
|---|
| 3111 | + int ret; |
|---|
| 3044 | 3112 | |
|---|
| 3045 | | - /* |
|---|
| 3046 | | - * ignore all events except driver registration and deregistration |
|---|
| 3047 | | - * if fbcon is not active |
|---|
| 3048 | | - */ |
|---|
| 3049 | | - if (fbcon_has_exited && !(action == FB_EVENT_FB_REGISTERED || |
|---|
| 3050 | | - action == FB_EVENT_FB_UNREGISTERED)) |
|---|
| 3051 | | - goto done; |
|---|
| 3052 | | - |
|---|
| 3053 | | - switch(action) { |
|---|
| 3054 | | - case FB_EVENT_SUSPEND: |
|---|
| 3055 | | - fbcon_suspended(info); |
|---|
| 3056 | | - break; |
|---|
| 3057 | | - case FB_EVENT_RESUME: |
|---|
| 3058 | | - fbcon_resumed(info); |
|---|
| 3059 | | - break; |
|---|
| 3060 | | - case FB_EVENT_MODE_CHANGE: |
|---|
| 3061 | | - fbcon_modechanged(info); |
|---|
| 3062 | | - break; |
|---|
| 3063 | | - case FB_EVENT_MODE_CHANGE_ALL: |
|---|
| 3064 | | - fbcon_set_all_vcs(info); |
|---|
| 3065 | | - break; |
|---|
| 3066 | | - case FB_EVENT_MODE_DELETE: |
|---|
| 3067 | | - mode = event->data; |
|---|
| 3068 | | - ret = fbcon_mode_deleted(info, mode); |
|---|
| 3069 | | - break; |
|---|
| 3070 | | - case FB_EVENT_FB_UNBIND: |
|---|
| 3071 | | - idx = info->node; |
|---|
| 3072 | | - ret = fbcon_fb_unbind(idx); |
|---|
| 3073 | | - break; |
|---|
| 3074 | | - case FB_EVENT_FB_REGISTERED: |
|---|
| 3075 | | - ret = fbcon_fb_registered(info); |
|---|
| 3076 | | - break; |
|---|
| 3077 | | - case FB_EVENT_FB_UNREGISTERED: |
|---|
| 3078 | | - ret = fbcon_fb_unregistered(info); |
|---|
| 3079 | | - break; |
|---|
| 3080 | | - case FB_EVENT_SET_CONSOLE_MAP: |
|---|
| 3081 | | - /* called with console lock held */ |
|---|
| 3082 | | - con2fb = event->data; |
|---|
| 3083 | | - ret = set_con2fb_map(con2fb->console - 1, |
|---|
| 3084 | | - con2fb->framebuffer, 1); |
|---|
| 3085 | | - break; |
|---|
| 3086 | | - case FB_EVENT_GET_CONSOLE_MAP: |
|---|
| 3087 | | - con2fb = event->data; |
|---|
| 3088 | | - con2fb->framebuffer = con2fb_map[con2fb->console - 1]; |
|---|
| 3089 | | - break; |
|---|
| 3090 | | - case FB_EVENT_BLANK: |
|---|
| 3091 | | - fbcon_fb_blanked(info, *(int *)event->data); |
|---|
| 3092 | | - break; |
|---|
| 3093 | | - case FB_EVENT_NEW_MODELIST: |
|---|
| 3094 | | - fbcon_new_modelist(info); |
|---|
| 3095 | | - break; |
|---|
| 3096 | | - case FB_EVENT_GET_REQ: |
|---|
| 3097 | | - caps = event->data; |
|---|
| 3098 | | - fbcon_get_requirement(info, caps); |
|---|
| 3099 | | - break; |
|---|
| 3100 | | - case FB_EVENT_REMAP_ALL_CONSOLE: |
|---|
| 3101 | | - idx = info->node; |
|---|
| 3102 | | - fbcon_remap_all(idx); |
|---|
| 3103 | | - break; |
|---|
| 3113 | + if (copy_from_user(&con2fb, argp, sizeof(con2fb))) |
|---|
| 3114 | + return -EFAULT; |
|---|
| 3115 | + if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) |
|---|
| 3116 | + return -EINVAL; |
|---|
| 3117 | + if (con2fb.framebuffer >= FB_MAX) |
|---|
| 3118 | + return -EINVAL; |
|---|
| 3119 | + if (!registered_fb[con2fb.framebuffer]) |
|---|
| 3120 | + request_module("fb%d", con2fb.framebuffer); |
|---|
| 3121 | + if (!registered_fb[con2fb.framebuffer]) { |
|---|
| 3122 | + return -EINVAL; |
|---|
| 3104 | 3123 | } |
|---|
| 3105 | | -done: |
|---|
| 3124 | + |
|---|
| 3125 | + console_lock(); |
|---|
| 3126 | + ret = set_con2fb_map(con2fb.console - 1, |
|---|
| 3127 | + con2fb.framebuffer, 1); |
|---|
| 3128 | + console_unlock(); |
|---|
| 3129 | + |
|---|
| 3106 | 3130 | return ret; |
|---|
| 3131 | +} |
|---|
| 3132 | + |
|---|
| 3133 | +int fbcon_get_con2fb_map_ioctl(void __user *argp) |
|---|
| 3134 | +{ |
|---|
| 3135 | + struct fb_con2fbmap con2fb; |
|---|
| 3136 | + |
|---|
| 3137 | + if (copy_from_user(&con2fb, argp, sizeof(con2fb))) |
|---|
| 3138 | + return -EFAULT; |
|---|
| 3139 | + if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) |
|---|
| 3140 | + return -EINVAL; |
|---|
| 3141 | + |
|---|
| 3142 | + console_lock(); |
|---|
| 3143 | + con2fb.framebuffer = con2fb_map[con2fb.console - 1]; |
|---|
| 3144 | + console_unlock(); |
|---|
| 3145 | + |
|---|
| 3146 | + return copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; |
|---|
| 3107 | 3147 | } |
|---|
| 3108 | 3148 | |
|---|
| 3109 | 3149 | /* |
|---|
| .. | .. |
|---|
| 3127 | 3167 | .con_font_default = fbcon_set_def_font, |
|---|
| 3128 | 3168 | .con_font_copy = fbcon_copy_font, |
|---|
| 3129 | 3169 | .con_set_palette = fbcon_set_palette, |
|---|
| 3130 | | - .con_set_origin = fbcon_set_origin, |
|---|
| 3131 | 3170 | .con_invert_region = fbcon_invert_region, |
|---|
| 3132 | 3171 | .con_screen_pos = fbcon_screen_pos, |
|---|
| 3133 | 3172 | .con_getxy = fbcon_getxy, |
|---|
| 3134 | 3173 | .con_resize = fbcon_resize, |
|---|
| 3135 | 3174 | .con_debug_enter = fbcon_debug_enter, |
|---|
| 3136 | 3175 | .con_debug_leave = fbcon_debug_leave, |
|---|
| 3137 | | -}; |
|---|
| 3138 | | - |
|---|
| 3139 | | -static struct notifier_block fbcon_event_notifier = { |
|---|
| 3140 | | - .notifier_call = fbcon_event_notify, |
|---|
| 3141 | 3176 | }; |
|---|
| 3142 | 3177 | |
|---|
| 3143 | 3178 | static ssize_t store_rotate(struct device *device, |
|---|
| .. | .. |
|---|
| 3147 | 3182 | struct fb_info *info; |
|---|
| 3148 | 3183 | int rotate, idx; |
|---|
| 3149 | 3184 | char **last = NULL; |
|---|
| 3150 | | - |
|---|
| 3151 | | - if (fbcon_has_exited) |
|---|
| 3152 | | - return count; |
|---|
| 3153 | 3185 | |
|---|
| 3154 | 3186 | console_lock(); |
|---|
| 3155 | 3187 | idx = con2fb_map[fg_console]; |
|---|
| .. | .. |
|---|
| 3173 | 3205 | int rotate, idx; |
|---|
| 3174 | 3206 | char **last = NULL; |
|---|
| 3175 | 3207 | |
|---|
| 3176 | | - if (fbcon_has_exited) |
|---|
| 3177 | | - return count; |
|---|
| 3178 | | - |
|---|
| 3179 | 3208 | console_lock(); |
|---|
| 3180 | 3209 | idx = con2fb_map[fg_console]; |
|---|
| 3181 | 3210 | |
|---|
| .. | .. |
|---|
| 3196 | 3225 | struct fb_info *info; |
|---|
| 3197 | 3226 | int rotate = 0, idx; |
|---|
| 3198 | 3227 | |
|---|
| 3199 | | - if (fbcon_has_exited) |
|---|
| 3200 | | - return 0; |
|---|
| 3201 | | - |
|---|
| 3202 | 3228 | console_lock(); |
|---|
| 3203 | 3229 | idx = con2fb_map[fg_console]; |
|---|
| 3204 | 3230 | |
|---|
| .. | .. |
|---|
| 3218 | 3244 | struct fb_info *info; |
|---|
| 3219 | 3245 | struct fbcon_ops *ops; |
|---|
| 3220 | 3246 | int idx, blink = -1; |
|---|
| 3221 | | - |
|---|
| 3222 | | - if (fbcon_has_exited) |
|---|
| 3223 | | - return 0; |
|---|
| 3224 | 3247 | |
|---|
| 3225 | 3248 | console_lock(); |
|---|
| 3226 | 3249 | idx = con2fb_map[fg_console]; |
|---|
| .. | .. |
|---|
| 3247 | 3270 | struct fb_info *info; |
|---|
| 3248 | 3271 | int blink, idx; |
|---|
| 3249 | 3272 | char **last = NULL; |
|---|
| 3250 | | - |
|---|
| 3251 | | - if (fbcon_has_exited) |
|---|
| 3252 | | - return count; |
|---|
| 3253 | 3273 | |
|---|
| 3254 | 3274 | console_lock(); |
|---|
| 3255 | 3275 | idx = con2fb_map[fg_console]; |
|---|
| .. | .. |
|---|
| 3314 | 3334 | |
|---|
| 3315 | 3335 | console_lock(); |
|---|
| 3316 | 3336 | |
|---|
| 3337 | + deferred_takeover = false; |
|---|
| 3338 | + logo_shown = FBCON_LOGO_DONTSHOW; |
|---|
| 3339 | + |
|---|
| 3317 | 3340 | for_each_registered_fb(i) |
|---|
| 3318 | 3341 | fbcon_fb_registered(registered_fb[i]); |
|---|
| 3319 | 3342 | |
|---|
| .. | .. |
|---|
| 3331 | 3354 | pr_info("fbcon: Taking over console\n"); |
|---|
| 3332 | 3355 | |
|---|
| 3333 | 3356 | dummycon_unregister_output_notifier(&fbcon_output_nb); |
|---|
| 3334 | | - deferred_takeover = false; |
|---|
| 3335 | | - logo_shown = FBCON_LOGO_DONTSHOW; |
|---|
| 3336 | 3357 | |
|---|
| 3337 | 3358 | /* We may get called in atomic context */ |
|---|
| 3338 | 3359 | schedule_work(&fbcon_deferred_takeover_work); |
|---|
| .. | .. |
|---|
| 3373 | 3394 | struct fb_info *info; |
|---|
| 3374 | 3395 | int i, j, mapped; |
|---|
| 3375 | 3396 | |
|---|
| 3376 | | - if (fbcon_has_exited) |
|---|
| 3377 | | - return; |
|---|
| 3378 | | - |
|---|
| 3379 | 3397 | #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER |
|---|
| 3380 | 3398 | if (deferred_takeover) { |
|---|
| 3381 | 3399 | dummycon_unregister_output_notifier(&fbcon_output_nb); |
|---|
| .. | .. |
|---|
| 3397 | 3415 | for (j = first_fb_vc; j <= last_fb_vc; j++) { |
|---|
| 3398 | 3416 | if (con2fb_map[j] == i) { |
|---|
| 3399 | 3417 | mapped = 1; |
|---|
| 3400 | | - break; |
|---|
| 3418 | + con2fb_map[j] = -1; |
|---|
| 3401 | 3419 | } |
|---|
| 3402 | 3420 | } |
|---|
| 3403 | 3421 | |
|---|
| .. | .. |
|---|
| 3420 | 3438 | info->queue.func = NULL; |
|---|
| 3421 | 3439 | } |
|---|
| 3422 | 3440 | } |
|---|
| 3423 | | - |
|---|
| 3424 | | - fbcon_has_exited = 1; |
|---|
| 3425 | 3441 | } |
|---|
| 3426 | 3442 | |
|---|
| 3427 | 3443 | void __init fb_console_init(void) |
|---|
| .. | .. |
|---|
| 3429 | 3445 | int i; |
|---|
| 3430 | 3446 | |
|---|
| 3431 | 3447 | console_lock(); |
|---|
| 3432 | | - fb_register_client(&fbcon_event_notifier); |
|---|
| 3433 | 3448 | fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL, |
|---|
| 3434 | 3449 | "fbcon"); |
|---|
| 3435 | 3450 | |
|---|
| .. | .. |
|---|
| 3465 | 3480 | void __exit fb_console_exit(void) |
|---|
| 3466 | 3481 | { |
|---|
| 3467 | 3482 | console_lock(); |
|---|
| 3468 | | - fb_unregister_client(&fbcon_event_notifier); |
|---|
| 3469 | 3483 | fbcon_deinit_device(); |
|---|
| 3470 | 3484 | device_destroy(fb_class, MKDEV(0, 0)); |
|---|
| 3471 | 3485 | fbcon_exit(); |
|---|