diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-09-14 08:12:20 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-14 08:12:20 -0400 |
commit | 165415f700b0c77fa1f8db6198f48582639adf78 (patch) | |
tree | 088e305b0b5b0c6753072e13be1177824c3ed59d /drivers/video/console | |
parent | c324b44c34050cf2a9b58830e11c974806bd85d8 (diff) | |
parent | 2f4ba45a75d6383b4a1201169a808ffea416ffa0 (diff) |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/video/console')
-rw-r--r-- | drivers/video/console/Kconfig | 2 | ||||
-rw-r--r-- | drivers/video/console/Makefile | 4 | ||||
-rw-r--r-- | drivers/video/console/bitblit.c | 148 | ||||
-rw-r--r-- | drivers/video/console/fbcon.c | 185 | ||||
-rw-r--r-- | drivers/video/console/fbcon.h | 3 | ||||
-rw-r--r-- | drivers/video/console/vgacon.c | 71 |
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 | ||
138 | config FONT_8x16 | 138 | config 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 | ||
34 | obj-$(CONFIG_FB_STI) += sticore.o font.o | 34 | obj-$(CONFIG_FB_STI) += sticore.o font.o |
35 | 35 | ||
36 | ifeq ($(CONFIG_USB_SISUSBVGA_CON),y) | ||
37 | obj-$(CONFIG_USB_SISUSBVGA) += font.o | ||
38 | endif | ||
39 | |||
36 | # Targets that kbuild needs to know about | 40 | # Targets that kbuild needs to know about |
37 | targets := promcon_tbl.c | 41 | targets := 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, ®ion); | 103 | info->fbops->fb_fillrect(info, ®ion); |
104 | } | 104 | } |
105 | 105 | ||
106 | static 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 | |||
137 | static 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 | |||
106 | static void bit_putcs(struct vc_data *vc, struct fb_info *info, | 172 | static 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 | ||
194 | static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, | 234 | static 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) | |||
214 | static inline int get_color(struct vc_data *vc, struct fb_info *info, | 214 | static 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 | ||
334 | static 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 | |||
352 | static 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 |
315 | static int __init fb_console_setup(char *this_opt) | 364 | static 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 | ||
579 | static 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 | |||
595 | static void con2fb_init_display(struct vc_data *vc, struct fb_info *info, | 626 | static 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 | ||
1899 | static int fbcon_switch(struct vc_data *vc) | 1924 | static 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 | ||
2058 | static void fbcon_free_font(struct display *p) | 2091 | static 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 | ||
2629 | static 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 | |||
2596 | static int fbcon_mode_deleted(struct fb_info *info, | 2674 | static 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 | ||
500 | static 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 | |||
500 | static int vgacon_switch(struct vc_data *c) | 551 | static 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 | ||
1020 | static 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 | |||
965 | static int vgacon_scrolldelta(struct vc_data *c, int lines) | 1031 | static 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, |