diff options
author | Antonino A. Daplas <adaplas@gmail.com> | 2005-09-09 16:04:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-09 16:58:00 -0400 |
commit | b8c909454f046b59065c6997b651fe20cd90c0f4 (patch) | |
tree | 2a8e03fe69c1b02dc610f57208d693e05b95969c | |
parent | 094bb659f53b6d90aab6067268d6d14f1f352d30 (diff) |
[PATCH] fbdev: Fix greater than 1 bit monochrome color handling
Currently, fbcon assumes that the visual FB_VISUAL_MONO* is always 1 bit.
According to Geert, there are old hardware where it's possible to have
monochrome at 8-bit, but has only 2 colors, black - 0x00 and white - 0xff.
Fix color handlers (fb_get_color_depth, and get_color) for this special case.
Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/video/console/bitblit.c | 2 | ||||
-rw-r--r-- | drivers/video/console/fbcon.c | 26 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 41 | ||||
-rw-r--r-- | drivers/video/nvidia/nvidia.c | 8 | ||||
-rw-r--r-- | include/linux/fb.h | 3 |
5 files changed, 52 insertions, 28 deletions
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 3c731577fed6..12eaf0aa87e6 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)) |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 751890a5f5f3..88bd8ef56fde 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; |
@@ -246,7 +250,6 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info, | |||
246 | * is grayscale. | 250 | * is grayscale. |
247 | */ | 251 | */ |
248 | color /= 4; | 252 | color /= 4; |
249 | break; | ||
250 | case 3: | 253 | case 3: |
251 | /* | 254 | /* |
252 | * Last 8 entries of default 16-color palette is a more intense | 255 | * Last 8 entries of default 16-color palette is a more intense |
@@ -426,7 +429,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, | |||
426 | * remove underline attribute from erase character | 429 | * remove underline attribute from erase character |
427 | * if black and white framebuffer. | 430 | * if black and white framebuffer. |
428 | */ | 431 | */ |
429 | if (fb_get_color_depth(&info->var) == 1) | 432 | if (fb_get_color_depth(&info->var, &info->fix) == 1) |
430 | erase &= ~0x400; | 433 | erase &= ~0x400; |
431 | logo_height = fb_prepare_logo(info); | 434 | logo_height = fb_prepare_logo(info); |
432 | logo_lines = (logo_height + vc->vc_font.height - 1) / | 435 | logo_lines = (logo_height + vc->vc_font.height - 1) / |
@@ -930,7 +933,7 @@ static void fbcon_init(struct vc_data *vc, int init) | |||
930 | } | 933 | } |
931 | if (p->userfont) | 934 | if (p->userfont) |
932 | charcnt = FNTCHARCNT(p->fontdata); | 935 | charcnt = FNTCHARCNT(p->fontdata); |
933 | vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1); | 936 | 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; | 937 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; |
935 | if (charcnt == 256) { | 938 | if (charcnt == 256) { |
936 | vc->vc_hi_font_mask = 0; | 939 | vc->vc_hi_font_mask = 0; |
@@ -1178,7 +1181,12 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, | |||
1178 | if (p->userfont) | 1181 | if (p->userfont) |
1179 | charcnt = FNTCHARCNT(p->fontdata); | 1182 | charcnt = FNTCHARCNT(p->fontdata); |
1180 | 1183 | ||
1181 | vc->vc_can_do_color = (fb_get_color_depth(var) != 1); | 1184 | var->activate = FB_ACTIVATE_NOW; |
1185 | info->var.activate = var->activate; | ||
1186 | info->var.yoffset = info->var.xoffset = 0; | ||
1187 | fb_set_var(info, var); | ||
1188 | |||
1189 | 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; | 1190 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; |
1183 | if (charcnt == 256) { | 1191 | if (charcnt == 256) { |
1184 | vc->vc_hi_font_mask = 0; | 1192 | vc->vc_hi_font_mask = 0; |
@@ -1967,7 +1975,7 @@ static int fbcon_switch(struct vc_data *vc) | |||
1967 | set_blitting_type(vc, info, p); | 1975 | set_blitting_type(vc, info, p); |
1968 | ((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1; | 1976 | ((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1; |
1969 | 1977 | ||
1970 | vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1); | 1978 | 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; | 1979 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; |
1972 | updatescrollmode(p, info, vc); | 1980 | updatescrollmode(p, info, vc); |
1973 | 1981 | ||
@@ -2332,7 +2340,7 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table) | |||
2332 | if (!CON_IS_VISIBLE(vc)) | 2340 | if (!CON_IS_VISIBLE(vc)) |
2333 | return 0; | 2341 | return 0; |
2334 | 2342 | ||
2335 | depth = fb_get_color_depth(&info->var); | 2343 | depth = fb_get_color_depth(&info->var, &info->fix); |
2336 | if (depth > 3) { | 2344 | if (depth > 3) { |
2337 | for (i = j = 0; i < 16; i++) { | 2345 | for (i = j = 0; i < 16; i++) { |
2338 | k = table[i]; | 2346 | k = table[i]; |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index a8eee79e117d..a815f5e2fcb5 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -62,16 +62,26 @@ int num_registered_fb; | |||
62 | * Helpers | 62 | * Helpers |
63 | */ | 63 | */ |
64 | 64 | ||
65 | int fb_get_color_depth(struct fb_var_screeninfo *var) | 65 | int fb_get_color_depth(struct fb_var_screeninfo *var, |
66 | struct fb_fix_screeninfo *fix) | ||
66 | { | 67 | { |
67 | if (var->green.length == var->blue.length && | 68 | int depth = 0; |
68 | var->green.length == var->red.length && | 69 | |
69 | !var->green.offset && !var->blue.offset && | 70 | if (fix->visual == FB_VISUAL_MONO01 || |
70 | !var->red.offset) | 71 | fix->visual == FB_VISUAL_MONO10) |
71 | return var->green.length; | 72 | depth = 1; |
72 | else | 73 | else { |
73 | return (var->green.length + var->red.length + | 74 | if (var->green.length == var->blue.length && |
74 | var->blue.length); | 75 | var->green.length == var->red.length && |
76 | var->green.offset == var->blue.offset && | ||
77 | var->green.offset == var->red.offset) | ||
78 | depth = var->green.length; | ||
79 | else | ||
80 | depth = var->green.length + var->red.length + | ||
81 | var->blue.length; | ||
82 | } | ||
83 | |||
84 | return depth; | ||
75 | } | 85 | } |
76 | EXPORT_SYMBOL(fb_get_color_depth); | 86 | EXPORT_SYMBOL(fb_get_color_depth); |
77 | 87 | ||
@@ -249,13 +259,18 @@ static void fb_set_logo(struct fb_info *info, | |||
249 | const struct linux_logo *logo, u8 *dst, | 259 | const struct linux_logo *logo, u8 *dst, |
250 | int depth) | 260 | int depth) |
251 | { | 261 | { |
252 | int i, j, k, fg = 1; | 262 | int i, j, k; |
253 | const u8 *src = logo->data; | 263 | const u8 *src = logo->data; |
254 | u8 d, xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0; | 264 | u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0; |
265 | u8 fg = 1, d; | ||
255 | 266 | ||
256 | if (fb_get_color_depth(&info->var) == 3) | 267 | if (fb_get_color_depth(&info->var, &info->fix) == 3) |
257 | fg = 7; | 268 | fg = 7; |
258 | 269 | ||
270 | if (info->fix.visual == FB_VISUAL_MONO01 || | ||
271 | info->fix.visual == FB_VISUAL_MONO10) | ||
272 | fg = ~((u8) (0xfff << info->var.green.length)); | ||
273 | |||
259 | switch (depth) { | 274 | switch (depth) { |
260 | case 4: | 275 | case 4: |
261 | for (i = 0; i < logo->height; i++) | 276 | for (i = 0; i < logo->height; i++) |
@@ -318,7 +333,7 @@ static struct logo_data { | |||
318 | 333 | ||
319 | int fb_prepare_logo(struct fb_info *info) | 334 | int fb_prepare_logo(struct fb_info *info) |
320 | { | 335 | { |
321 | int depth = fb_get_color_depth(&info->var); | 336 | int depth = fb_get_color_depth(&info->var, &info->fix); |
322 | 337 | ||
323 | memset(&fb_logo, 0, sizeof(struct logo_data)); | 338 | memset(&fb_logo, 0, sizeof(struct logo_data)); |
324 | 339 | ||
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index af99ea96012e..32952204ce33 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
@@ -658,7 +658,7 @@ static int nvidia_calc_regs(struct fb_info *info) | |||
658 | { | 658 | { |
659 | struct nvidia_par *par = info->par; | 659 | struct nvidia_par *par = info->par; |
660 | struct _riva_hw_state *state = &par->ModeReg; | 660 | struct _riva_hw_state *state = &par->ModeReg; |
661 | int i, depth = fb_get_color_depth(&info->var); | 661 | int i, depth = fb_get_color_depth(&info->var, &info->fix); |
662 | int h_display = info->var.xres / 8 - 1; | 662 | int h_display = info->var.xres / 8 - 1; |
663 | int h_start = (info->var.xres + info->var.right_margin) / 8 - 1; | 663 | int h_start = (info->var.xres + info->var.right_margin) / 8 - 1; |
664 | int h_end = (info->var.xres + info->var.right_margin + | 664 | int h_end = (info->var.xres + info->var.right_margin + |
@@ -978,6 +978,9 @@ static int nvidiafb_set_par(struct fb_info *info) | |||
978 | !par->twoHeads) | 978 | !par->twoHeads) |
979 | par->FPDither = 0; | 979 | par->FPDither = 0; |
980 | 980 | ||
981 | info->fix.visual = (info->var.bits_per_pixel == 8) ? | ||
982 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; | ||
983 | |||
981 | nvidia_init_vga(info); | 984 | nvidia_init_vga(info); |
982 | nvidia_calc_regs(info); | 985 | nvidia_calc_regs(info); |
983 | nvidia_write_regs(par); | 986 | nvidia_write_regs(par); |
@@ -992,9 +995,6 @@ static int nvidiafb_set_par(struct fb_info *info) | |||
992 | NVWriteCrtc(par, 0x11, 0x00); | 995 | NVWriteCrtc(par, 0x11, 0x00); |
993 | info->fix.line_length = (info->var.xres_virtual * | 996 | info->fix.line_length = (info->var.xres_virtual * |
994 | info->var.bits_per_pixel) >> 3; | 997 | info->var.bits_per_pixel) >> 3; |
995 | info->fix.visual = (info->var.bits_per_pixel == 8) ? | ||
996 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; | ||
997 | |||
998 | if (info->var.accel_flags) { | 998 | if (info->var.accel_flags) { |
999 | info->fbops->fb_imageblit = nvidiafb_imageblit; | 999 | info->fbops->fb_imageblit = nvidiafb_imageblit; |
1000 | info->fbops->fb_fillrect = nvidiafb_fillrect; | 1000 | info->fbops->fb_fillrect = nvidiafb_fillrect; |
diff --git a/include/linux/fb.h b/include/linux/fb.h index e3e16f43b1bb..c71a7162e098 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -823,7 +823,8 @@ extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, | |||
823 | u32 height, u32 shift_high, u32 shift_low, u32 mod); | 823 | u32 height, u32 shift_high, u32 shift_low, u32 mod); |
824 | extern void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height); | 824 | extern void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height); |
825 | extern void fb_set_suspend(struct fb_info *info, int state); | 825 | extern void fb_set_suspend(struct fb_info *info, int state); |
826 | extern int fb_get_color_depth(struct fb_var_screeninfo *var); | 826 | extern int fb_get_color_depth(struct fb_var_screeninfo *var, |
827 | struct fb_fix_screeninfo *fix); | ||
827 | extern int fb_get_options(char *name, char **option); | 828 | extern int fb_get_options(char *name, char **option); |
828 | extern int fb_new_modelist(struct fb_info *info); | 829 | extern int fb_new_modelist(struct fb_info *info); |
829 | 830 | ||