aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/console
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-09-14 08:12:20 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-09-14 08:12:20 -0400
commit165415f700b0c77fa1f8db6198f48582639adf78 (patch)
tree088e305b0b5b0c6753072e13be1177824c3ed59d /drivers/video/console
parentc324b44c34050cf2a9b58830e11c974806bd85d8 (diff)
parent2f4ba45a75d6383b4a1201169a808ffea416ffa0 (diff)
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/video/console')
-rw-r--r--drivers/video/console/Kconfig2
-rw-r--r--drivers/video/console/Makefile4
-rw-r--r--drivers/video/console/bitblit.c148
-rw-r--r--drivers/video/console/fbcon.c185
-rw-r--r--drivers/video/console/fbcon.h3
-rw-r--r--drivers/video/console/vgacon.c71
6 files changed, 303 insertions, 110 deletions
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 5fe182d6e4ab..eb83a7874c71 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -137,7 +137,7 @@ config FONT_8x8
137 137
138config FONT_8x16 138config FONT_8x16
139 bool "VGA 8x16 font" if FONTS 139 bool "VGA 8x16 font" if FONTS
140 depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y 140 depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || USB_SISUSBVGA_CON
141 default y if !SPARC32 && !SPARC64 && !FONTS 141 default y if !SPARC32 && !SPARC64 && !FONTS
142 help 142 help
143 This is the "high resolution" font for the VGA frame buffer (the one 143 This is the "high resolution" font for the VGA frame buffer (the one
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index b562f6bb9d31..42c7b8dcd220 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -33,6 +33,10 @@ endif
33 33
34obj-$(CONFIG_FB_STI) += sticore.o font.o 34obj-$(CONFIG_FB_STI) += sticore.o font.o
35 35
36ifeq ($(CONFIG_USB_SISUSBVGA_CON),y)
37obj-$(CONFIG_USB_SISUSBVGA) += font.o
38endif
39
36# Targets that kbuild needs to know about 40# Targets that kbuild needs to know about
37targets := promcon_tbl.c 41targets := promcon_tbl.c
38 42
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 3c731577fed6..9f70e512b88b 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -39,7 +39,7 @@ static inline int get_attribute(struct fb_info *info, u16 c)
39{ 39{
40 int attribute = 0; 40 int attribute = 0;
41 41
42 if (fb_get_color_depth(&info->var) == 1) { 42 if (fb_get_color_depth(&info->var, &info->fix) == 1) {
43 if (attr_underline(c)) 43 if (attr_underline(c))
44 attribute |= FBCON_ATTRIBUTE_UNDERLINE; 44 attribute |= FBCON_ATTRIBUTE_UNDERLINE;
45 if (attr_reverse(c)) 45 if (attr_reverse(c))
@@ -103,42 +103,104 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy,
103 info->fbops->fb_fillrect(info, &region); 103 info->fbops->fb_fillrect(info, &region);
104} 104}
105 105
106static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
107 const u16 *s, u32 attr, u32 cnt,
108 u32 d_pitch, u32 s_pitch, u32 cellsize,
109 struct fb_image *image, u8 *buf, u8 *dst)
110{
111 u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
112 u32 idx = vc->vc_font.width >> 3;
113 u8 *src;
114
115 while (cnt--) {
116 src = vc->vc_font.data + (scr_readw(s++)&
117 charmask)*cellsize;
118
119 if (attr) {
120 update_attr(buf, src, attr, vc);
121 src = buf;
122 }
123
124 if (likely(idx == 1))
125 __fb_pad_aligned_buffer(dst, d_pitch, src, idx,
126 image->height);
127 else
128 fb_pad_aligned_buffer(dst, d_pitch, src, idx,
129 image->height);
130
131 dst += s_pitch;
132 }
133
134 info->fbops->fb_imageblit(info, image);
135}
136
137static inline void bit_putcs_unaligned(struct vc_data *vc,
138 struct fb_info *info, const u16 *s,
139 u32 attr, u32 cnt, u32 d_pitch,
140 u32 s_pitch, u32 cellsize,
141 struct fb_image *image, u8 *buf,
142 u8 *dst)
143{
144 u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
145 u32 shift_low = 0, mod = vc->vc_font.width % 8;
146 u32 shift_high = 8;
147 u32 idx = vc->vc_font.width >> 3;
148 u8 *src;
149
150 while (cnt--) {
151 src = vc->vc_font.data + (scr_readw(s++)&
152 charmask)*cellsize;
153
154 if (attr) {
155 update_attr(buf, src, attr, vc);
156 src = buf;
157 }
158
159 fb_pad_unaligned_buffer(dst, d_pitch, src, idx,
160 image->height, shift_high,
161 shift_low, mod);
162 shift_low += mod;
163 dst += (shift_low >= 8) ? s_pitch : s_pitch - 1;
164 shift_low &= 7;
165 shift_high = 8 - shift_low;
166 }
167
168 info->fbops->fb_imageblit(info, image);
169
170}
171
106static void bit_putcs(struct vc_data *vc, struct fb_info *info, 172static void bit_putcs(struct vc_data *vc, struct fb_info *info,
107 const unsigned short *s, int count, int yy, int xx, 173 const unsigned short *s, int count, int yy, int xx,
108 int fg, int bg) 174 int fg, int bg)
109{ 175{
110 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
111 unsigned int width = (vc->vc_font.width + 7) >> 3;
112 unsigned int cellsize = vc->vc_font.height * width;
113 unsigned int maxcnt = info->pixmap.size/cellsize;
114 unsigned int scan_align = info->pixmap.scan_align - 1;
115 unsigned int buf_align = info->pixmap.buf_align - 1;
116 unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
117 unsigned int shift_high = 8, pitch, cnt, size, k;
118 unsigned int idx = vc->vc_font.width >> 3;
119 unsigned int attribute = get_attribute(info, scr_readw(s));
120 struct fb_image image; 176 struct fb_image image;
121 u8 *src, *dst, *buf = NULL; 177 u32 width = (vc->vc_font.width + 7)/8;
122 178 u32 cellsize = width * vc->vc_font.height;
123 if (attribute) { 179 u32 maxcnt = info->pixmap.size/cellsize;
124 buf = kmalloc(cellsize, GFP_KERNEL); 180 u32 scan_align = info->pixmap.scan_align - 1;
125 if (!buf) 181 u32 buf_align = info->pixmap.buf_align - 1;
126 return; 182 u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
127 } 183 u32 attribute = get_attribute(info, scr_readw(s));
184 u8 *dst, *buf = NULL;
128 185
129 image.fg_color = fg; 186 image.fg_color = fg;
130 image.bg_color = bg; 187 image.bg_color = bg;
131
132 image.dx = xx * vc->vc_font.width; 188 image.dx = xx * vc->vc_font.width;
133 image.dy = yy * vc->vc_font.height; 189 image.dy = yy * vc->vc_font.height;
134 image.height = vc->vc_font.height; 190 image.height = vc->vc_font.height;
135 image.depth = 1; 191 image.depth = 1;
136 192
193 if (attribute) {
194 buf = kmalloc(cellsize, GFP_KERNEL);
195 if (!buf)
196 return;
197 }
198
137 while (count) { 199 while (count) {
138 if (count > maxcnt) 200 if (count > maxcnt)
139 cnt = k = maxcnt; 201 cnt = maxcnt;
140 else 202 else
141 cnt = k = count; 203 cnt = count;
142 204
143 image.width = vc->vc_font.width * cnt; 205 image.width = vc->vc_font.width * cnt;
144 pitch = ((image.width + 7) >> 3) + scan_align; 206 pitch = ((image.width + 7) >> 3) + scan_align;
@@ -147,41 +209,18 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
147 size &= ~buf_align; 209 size &= ~buf_align;
148 dst = fb_get_buffer_offset(info, &info->pixmap, size); 210 dst = fb_get_buffer_offset(info, &info->pixmap, size);
149 image.data = dst; 211 image.data = dst;
150 if (mod) { 212
151 while (k--) { 213 if (!mod)
152 src = vc->vc_font.data + (scr_readw(s++)& 214 bit_putcs_aligned(vc, info, s, attribute, cnt, pitch,
153 charmask)*cellsize; 215 width, cellsize, &image, buf, dst);
154 216 else
155 if (attribute) { 217 bit_putcs_unaligned(vc, info, s, attribute, cnt,
156 update_attr(buf, src, attribute, vc); 218 pitch, width, cellsize, &image,
157 src = buf; 219 buf, dst);
158 } 220
159
160 fb_pad_unaligned_buffer(dst, pitch, src, idx,
161 image.height, shift_high,
162 shift_low, mod);
163 shift_low += mod;
164 dst += (shift_low >= 8) ? width : width - 1;
165 shift_low &= 7;
166 shift_high = 8 - shift_low;
167 }
168 } else {
169 while (k--) {
170 src = vc->vc_font.data + (scr_readw(s++)&
171 charmask)*cellsize;
172
173 if (attribute) {
174 update_attr(buf, src, attribute, vc);
175 src = buf;
176 }
177
178 fb_pad_aligned_buffer(dst, pitch, src, idx, image.height);
179 dst += width;
180 }
181 }
182 info->fbops->fb_imageblit(info, &image);
183 image.dx += cnt * vc->vc_font.width; 221 image.dx += cnt * vc->vc_font.width;
184 count -= cnt; 222 count -= cnt;
223 s += cnt;
185 } 224 }
186 225
187 /* buf is always NULL except when in monochrome mode, so in this case 226 /* buf is always NULL except when in monochrome mode, so in this case
@@ -189,6 +228,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
189 NULL pointers just fine */ 228 NULL pointers just fine */
190 if (unlikely(buf)) 229 if (unlikely(buf))
191 kfree(buf); 230 kfree(buf);
231
192} 232}
193 233
194static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, 234static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 35c88bd7ba5e..2e93224d2d55 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -214,7 +214,7 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
214static inline int get_color(struct vc_data *vc, struct fb_info *info, 214static inline int get_color(struct vc_data *vc, struct fb_info *info,
215 u16 c, int is_fg) 215 u16 c, int is_fg)
216{ 216{
217 int depth = fb_get_color_depth(&info->var); 217 int depth = fb_get_color_depth(&info->var, &info->fix);
218 int color = 0; 218 int color = 0;
219 219
220 if (console_blanked) { 220 if (console_blanked) {
@@ -230,9 +230,13 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
230 switch (depth) { 230 switch (depth) {
231 case 1: 231 case 1:
232 { 232 {
233 int col = ~(0xfff << (max(info->var.green.length,
234 max(info->var.red.length,
235 info->var.blue.length)))) & 0xff;
236
233 /* 0 or 1 */ 237 /* 0 or 1 */
234 int fg = (info->fix.visual != FB_VISUAL_MONO01) ? 1 : 0; 238 int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0;
235 int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : 1; 239 int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col;
236 240
237 if (console_blanked) 241 if (console_blanked)
238 fg = bg; 242 fg = bg;
@@ -243,9 +247,25 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
243 case 2: 247 case 2:
244 /* 248 /*
245 * Scale down 16-colors to 4 colors. Default 4-color palette 249 * Scale down 16-colors to 4 colors. Default 4-color palette
246 * is grayscale. 250 * is grayscale. However, simply dividing the values by 4
251 * will not work, as colors 1, 2 and 3 will be scaled-down
252 * to zero rendering them invisible. So empirically convert
253 * colors to a sane 4-level grayscale.
247 */ 254 */
248 color /= 4; 255 switch (color) {
256 case 0:
257 color = 0; /* black */
258 break;
259 case 1 ... 6:
260 color = 2; /* white */
261 break;
262 case 7 ... 8:
263 color = 1; /* gray */
264 break;
265 default:
266 color = 3; /* intense white */
267 break;
268 }
249 break; 269 break;
250 case 3: 270 case 3:
251 /* 271 /*
@@ -311,6 +331,35 @@ static void cursor_timer_handler(unsigned long dev_addr)
311 mod_timer(&ops->cursor_timer, jiffies + HZ/5); 331 mod_timer(&ops->cursor_timer, jiffies + HZ/5);
312} 332}
313 333
334static void fbcon_add_cursor_timer(struct fb_info *info)
335{
336 struct fbcon_ops *ops = info->fbcon_par;
337
338 if ((!info->queue.func || info->queue.func == fb_flashcursor) &&
339 !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) {
340 if (!info->queue.func)
341 INIT_WORK(&info->queue, fb_flashcursor, info);
342
343 init_timer(&ops->cursor_timer);
344 ops->cursor_timer.function = cursor_timer_handler;
345 ops->cursor_timer.expires = jiffies + HZ / 5;
346 ops->cursor_timer.data = (unsigned long ) info;
347 add_timer(&ops->cursor_timer);
348 ops->flags |= FBCON_FLAGS_CURSOR_TIMER;
349 }
350}
351
352static void fbcon_del_cursor_timer(struct fb_info *info)
353{
354 struct fbcon_ops *ops = info->fbcon_par;
355
356 if (info->queue.func == fb_flashcursor &&
357 ops->flags & FBCON_FLAGS_CURSOR_TIMER) {
358 del_timer_sync(&ops->cursor_timer);
359 ops->flags &= ~FBCON_FLAGS_CURSOR_TIMER;
360 }
361}
362
314#ifndef MODULE 363#ifndef MODULE
315static int __init fb_console_setup(char *this_opt) 364static int __init fb_console_setup(char *this_opt)
316{ 365{
@@ -426,7 +475,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
426 * remove underline attribute from erase character 475 * remove underline attribute from erase character
427 * if black and white framebuffer. 476 * if black and white framebuffer.
428 */ 477 */
429 if (fb_get_color_depth(&info->var) == 1) 478 if (fb_get_color_depth(&info->var, &info->fix) == 1)
430 erase &= ~0x400; 479 erase &= ~0x400;
431 logo_height = fb_prepare_logo(info); 480 logo_height = fb_prepare_logo(info);
432 logo_lines = (logo_height + vc->vc_font.height - 1) / 481 logo_lines = (logo_height + vc->vc_font.height - 1) /
@@ -563,9 +612,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
563 } 612 }
564 613
565 if (!err) { 614 if (!err) {
566 if (oldinfo->queue.func == fb_flashcursor) 615 fbcon_del_cursor_timer(oldinfo);
567 del_timer_sync(&ops->cursor_timer);
568
569 kfree(ops->cursor_state.mask); 616 kfree(ops->cursor_state.mask);
570 kfree(ops->cursor_data); 617 kfree(ops->cursor_data);
571 kfree(oldinfo->fbcon_par); 618 kfree(oldinfo->fbcon_par);
@@ -576,22 +623,6 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
576 return err; 623 return err;
577} 624}
578 625
579static void con2fb_init_newinfo(struct fb_info *info)
580{
581 if (!info->queue.func || info->queue.func == fb_flashcursor) {
582 struct fbcon_ops *ops = info->fbcon_par;
583
584 if (!info->queue.func)
585 INIT_WORK(&info->queue, fb_flashcursor, info);
586
587 init_timer(&ops->cursor_timer);
588 ops->cursor_timer.function = cursor_timer_handler;
589 ops->cursor_timer.expires = jiffies + HZ / 5;
590 ops->cursor_timer.data = (unsigned long ) info;
591 add_timer(&ops->cursor_timer);
592 }
593}
594
595static void con2fb_init_display(struct vc_data *vc, struct fb_info *info, 626static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
596 int unit, int show_logo) 627 int unit, int show_logo)
597{ 628{
@@ -675,7 +706,7 @@ static int set_con2fb_map(int unit, int newidx, int user)
675 logo_shown != FBCON_LOGO_DONTSHOW); 706 logo_shown != FBCON_LOGO_DONTSHOW);
676 707
677 if (!found) 708 if (!found)
678 con2fb_init_newinfo(info); 709 fbcon_add_cursor_timer(info);
679 con2fb_map_boot[unit] = newidx; 710 con2fb_map_boot[unit] = newidx;
680 con2fb_init_display(vc, info, unit, show_logo); 711 con2fb_init_display(vc, info, unit, show_logo);
681 } 712 }
@@ -878,18 +909,7 @@ static const char *fbcon_startup(void)
878 } 909 }
879#endif /* CONFIG_MAC */ 910#endif /* CONFIG_MAC */
880 911
881 /* Initialize the work queue. If the driver provides its 912 fbcon_add_cursor_timer(info);
882 * own work queue this means it will use something besides
883 * default timer to flash the cursor. */
884 if (!info->queue.func) {
885 INIT_WORK(&info->queue, fb_flashcursor, info);
886
887 init_timer(&ops->cursor_timer);
888 ops->cursor_timer.function = cursor_timer_handler;
889 ops->cursor_timer.expires = jiffies + HZ / 5;
890 ops->cursor_timer.data = (unsigned long ) info;
891 add_timer(&ops->cursor_timer);
892 }
893 return display_desc; 913 return display_desc;
894} 914}
895 915
@@ -930,7 +950,7 @@ static void fbcon_init(struct vc_data *vc, int init)
930 } 950 }
931 if (p->userfont) 951 if (p->userfont)
932 charcnt = FNTCHARCNT(p->fontdata); 952 charcnt = FNTCHARCNT(p->fontdata);
933 vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1); 953 vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
934 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; 954 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
935 if (charcnt == 256) { 955 if (charcnt == 256) {
936 vc->vc_hi_font_mask = 0; 956 vc->vc_hi_font_mask = 0;
@@ -1178,7 +1198,12 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
1178 if (p->userfont) 1198 if (p->userfont)
1179 charcnt = FNTCHARCNT(p->fontdata); 1199 charcnt = FNTCHARCNT(p->fontdata);
1180 1200
1181 vc->vc_can_do_color = (fb_get_color_depth(var) != 1); 1201 var->activate = FB_ACTIVATE_NOW;
1202 info->var.activate = var->activate;
1203 info->var.yoffset = info->var.xoffset = 0;
1204 fb_set_var(info, var);
1205
1206 vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
1182 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; 1207 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
1183 if (charcnt == 256) { 1208 if (charcnt == 256) {
1184 vc->vc_hi_font_mask = 0; 1209 vc->vc_hi_font_mask = 0;
@@ -1898,7 +1923,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
1898 1923
1899static int fbcon_switch(struct vc_data *vc) 1924static int fbcon_switch(struct vc_data *vc)
1900{ 1925{
1901 struct fb_info *info; 1926 struct fb_info *info, *old_info = NULL;
1902 struct display *p = &fb_display[vc->vc_num]; 1927 struct display *p = &fb_display[vc->vc_num];
1903 struct fb_var_screeninfo var; 1928 struct fb_var_screeninfo var;
1904 int i, prev_console; 1929 int i, prev_console;
@@ -1931,7 +1956,8 @@ static int fbcon_switch(struct vc_data *vc)
1931 } 1956 }
1932 1957
1933 prev_console = ((struct fbcon_ops *)info->fbcon_par)->currcon; 1958 prev_console = ((struct fbcon_ops *)info->fbcon_par)->currcon;
1934 1959 if (prev_console != -1)
1960 old_info = registered_fb[con2fb_map[prev_console]];
1935 /* 1961 /*
1936 * FIXME: If we have multiple fbdev's loaded, we need to 1962 * FIXME: If we have multiple fbdev's loaded, we need to
1937 * update all info->currcon. Perhaps, we can place this 1963 * update all info->currcon. Perhaps, we can place this
@@ -1959,15 +1985,17 @@ static int fbcon_switch(struct vc_data *vc)
1959 info->var.yoffset = info->var.xoffset = p->yscroll = 0; 1985 info->var.yoffset = info->var.xoffset = p->yscroll = 0;
1960 fb_set_var(info, &var); 1986 fb_set_var(info, &var);
1961 1987
1962 if (prev_console != -1 && 1988 if (old_info != NULL && old_info != info) {
1963 registered_fb[con2fb_map[prev_console]] != info && 1989 if (info->fbops->fb_set_par)
1964 info->fbops->fb_set_par) 1990 info->fbops->fb_set_par(info);
1965 info->fbops->fb_set_par(info); 1991 fbcon_del_cursor_timer(old_info);
1992 fbcon_add_cursor_timer(info);
1993 }
1966 1994
1967 set_blitting_type(vc, info, p); 1995 set_blitting_type(vc, info, p);
1968 ((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1; 1996 ((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1;
1969 1997
1970 vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1); 1998 vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
1971 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; 1999 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
1972 updatescrollmode(p, info, vc); 2000 updatescrollmode(p, info, vc);
1973 2001
@@ -2048,11 +2076,16 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
2048 fbcon_generic_blank(vc, info, blank); 2076 fbcon_generic_blank(vc, info, blank);
2049 } 2077 }
2050 2078
2051 if (!blank) 2079 if (!blank)
2052 update_screen(vc); 2080 update_screen(vc);
2053 } 2081 }
2054 2082
2055 return 0; 2083 if (!blank)
2084 fbcon_add_cursor_timer(info);
2085 else
2086 fbcon_del_cursor_timer(info);
2087
2088 return 0;
2056} 2089}
2057 2090
2058static void fbcon_free_font(struct display *p) 2091static void fbcon_free_font(struct display *p)
@@ -2332,7 +2365,7 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
2332 if (!CON_IS_VISIBLE(vc)) 2365 if (!CON_IS_VISIBLE(vc))
2333 return 0; 2366 return 0;
2334 2367
2335 depth = fb_get_color_depth(&info->var); 2368 depth = fb_get_color_depth(&info->var, &info->fix);
2336 if (depth > 3) { 2369 if (depth > 3) {
2337 for (i = j = 0; i < 16; i++) { 2370 for (i = j = 0; i < 16; i++) {
2338 k = table[i]; 2371 k = table[i];
@@ -2593,6 +2626,51 @@ static void fbcon_modechanged(struct fb_info *info)
2593 } 2626 }
2594} 2627}
2595 2628
2629static void fbcon_set_all_vcs(struct fb_info *info)
2630{
2631 struct fbcon_ops *ops = info->fbcon_par;
2632 struct vc_data *vc;
2633 struct display *p;
2634 int i, rows, cols;
2635
2636 if (!ops || ops->currcon < 0)
2637 return;
2638
2639 for (i = 0; i < MAX_NR_CONSOLES; i++) {
2640 vc = vc_cons[i].d;
2641 if (!vc || vc->vc_mode != KD_TEXT ||
2642 registered_fb[con2fb_map[i]] != info)
2643 continue;
2644
2645 p = &fb_display[vc->vc_num];
2646
2647 info->var.xoffset = info->var.yoffset = p->yscroll = 0;
2648 var_to_display(p, &info->var, info);
2649 cols = info->var.xres / vc->vc_font.width;
2650 rows = info->var.yres / vc->vc_font.height;
2651 vc_resize(vc, cols, rows);
2652
2653 if (CON_IS_VISIBLE(vc)) {
2654 updatescrollmode(p, info, vc);
2655 scrollback_max = 0;
2656 scrollback_current = 0;
2657 update_var(vc->vc_num, info);
2658 fbcon_set_palette(vc, color_table);
2659 update_screen(vc);
2660 if (softback_buf) {
2661 int l = fbcon_softback_size / vc->vc_size_row;
2662 if (l > 5)
2663 softback_end = softback_buf + l * vc->vc_size_row;
2664 else {
2665 /* Smaller scrollback makes no sense, and 0
2666 would screw the operation totally */
2667 softback_top = 0;
2668 }
2669 }
2670 }
2671 }
2672}
2673
2596static int fbcon_mode_deleted(struct fb_info *info, 2674static int fbcon_mode_deleted(struct fb_info *info,
2597 struct fb_videomode *mode) 2675 struct fb_videomode *mode)
2598{ 2676{
@@ -2708,6 +2786,9 @@ static int fbcon_event_notify(struct notifier_block *self,
2708 case FB_EVENT_MODE_CHANGE: 2786 case FB_EVENT_MODE_CHANGE:
2709 fbcon_modechanged(info); 2787 fbcon_modechanged(info);
2710 break; 2788 break;
2789 case FB_EVENT_MODE_CHANGE_ALL:
2790 fbcon_set_all_vcs(info);
2791 break;
2711 case FB_EVENT_MODE_DELETE: 2792 case FB_EVENT_MODE_DELETE:
2712 mode = event->data; 2793 mode = event->data;
2713 ret = fbcon_mode_deleted(info, mode); 2794 ret = fbcon_mode_deleted(info, mode);
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 5d377860bce2..08befafe11d1 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -18,7 +18,8 @@
18 18
19#include <asm/io.h> 19#include <asm/io.h>
20 20
21#define FBCON_FLAGS_INIT 1 21#define FBCON_FLAGS_INIT 1
22#define FBCON_FLAGS_CURSOR_TIMER 2
22 23
23 /* 24 /*
24 * This is the interface between the low-level console driver and the 25 * This is the interface between the low-level console driver and the
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index d27fa91e5886..0705cd741411 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -497,6 +497,57 @@ static void vgacon_cursor(struct vc_data *c, int mode)
497 } 497 }
498} 498}
499 499
500static int vgacon_doresize(struct vc_data *c,
501 unsigned int width, unsigned int height)
502{
503 unsigned long flags;
504 unsigned int scanlines = height * c->vc_font.height;
505 u8 scanlines_lo, r7, vsync_end, mode;
506
507 spin_lock_irqsave(&vga_lock, flags);
508
509 outb_p(VGA_CRTC_MODE, vga_video_port_reg);
510 mode = inb_p(vga_video_port_val);
511
512 if (mode & 0x04)
513 scanlines >>= 1;
514
515 scanlines -= 1;
516 scanlines_lo = scanlines & 0xff;
517
518 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
519 r7 = inb_p(vga_video_port_val) & ~0x42;
520
521 if (scanlines & 0x100)
522 r7 |= 0x02;
523 if (scanlines & 0x200)
524 r7 |= 0x40;
525
526 /* deprotect registers */
527 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
528 vsync_end = inb_p(vga_video_port_val);
529 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
530 outb_p(vsync_end & ~0x80, vga_video_port_val);
531
532 outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
533 outb_p(width - 1, vga_video_port_val);
534 outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
535 outb_p(width >> 1, vga_video_port_val);
536
537 outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
538 outb_p(scanlines_lo, vga_video_port_val);
539 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
540 outb_p(r7,vga_video_port_val);
541
542 /* reprotect registers */
543 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
544 outb_p(vsync_end, vga_video_port_val);
545
546 spin_unlock_irqrestore(&vga_lock, flags);
547
548 return 0;
549}
550
500static int vgacon_switch(struct vc_data *c) 551static int vgacon_switch(struct vc_data *c)
501{ 552{
502 /* 553 /*
@@ -510,9 +561,13 @@ static int vgacon_switch(struct vc_data *c)
510 /* We can only copy out the size of the video buffer here, 561 /* We can only copy out the size of the video buffer here,
511 * otherwise we get into VGA BIOS */ 562 * otherwise we get into VGA BIOS */
512 563
513 if (!vga_is_gfx) 564 if (!vga_is_gfx) {
514 scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, 565 scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
515 c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size); 566 c->vc_screenbuf_size > vga_vram_size ?
567 vga_vram_size : c->vc_screenbuf_size);
568 vgacon_doresize(c, c->vc_cols, c->vc_rows);
569 }
570
516 return 0; /* Redrawing not needed */ 571 return 0; /* Redrawing not needed */
517} 572}
518 573
@@ -962,6 +1017,17 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font)
962 1017
963#endif 1018#endif
964 1019
1020static int vgacon_resize(struct vc_data *c, unsigned int width,
1021 unsigned int height)
1022{
1023 if (width % 2 || width > ORIG_VIDEO_COLS || height > ORIG_VIDEO_LINES)
1024 return -EINVAL;
1025
1026 if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
1027 vgacon_doresize(c, width, height);
1028 return 0;
1029}
1030
965static int vgacon_scrolldelta(struct vc_data *c, int lines) 1031static int vgacon_scrolldelta(struct vc_data *c, int lines)
966{ 1032{
967 if (!lines) /* Turn scrollback off */ 1033 if (!lines) /* Turn scrollback off */
@@ -1103,6 +1169,7 @@ const struct consw vga_con = {
1103 .con_blank = vgacon_blank, 1169 .con_blank = vgacon_blank,
1104 .con_font_set = vgacon_font_set, 1170 .con_font_set = vgacon_font_set,
1105 .con_font_get = vgacon_font_get, 1171 .con_font_get = vgacon_font_get,
1172 .con_resize = vgacon_resize,
1106 .con_set_palette = vgacon_set_palette, 1173 .con_set_palette = vgacon_set_palette,
1107 .con_scrolldelta = vgacon_scrolldelta, 1174 .con_scrolldelta = vgacon_scrolldelta,
1108 .con_set_origin = vgacon_set_origin, 1175 .con_set_origin = vgacon_set_origin,