Commit ebf4fd17 authored by Antonino Daplas's avatar Antonino Daplas Committed by Linus Torvalds

[PATCH] fbdev: use 8-bit DAC for capable hardware

The patch adds the ability for vesafb to switch the DAC from 6-bit to 8-bit
at kernel boot.  Besides fixing the failure to draw the 224-color logo, an
8-bit DAC will also provide a wider color range for user applications.
Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 216f473e
...@@ -232,6 +232,41 @@ mopar_gr: ...@@ -232,6 +232,41 @@ mopar_gr:
xorl %eax, %eax xorl %eax, %eax
movw 18(%di), %ax movw 18(%di), %ax
movl %eax, %fs:(PARAM_LFB_SIZE) movl %eax, %fs:(PARAM_LFB_SIZE)
# switching the DAC to 8-bit is for <= 8 bpp only
movw %fs:(PARAM_LFB_DEPTH), %ax
cmpw $8, %ax
jg dac_done
# get DAC switching capability
xorl %eax, %eax
movb 10(%di), %al
testb $1, %al
jz dac_set
# attempt to switch DAC to 8-bit
movw $0x4f08, %ax
movw $0x0800, %bx
int $0x10
cmpw $0x004f, %ax
jne dac_set
movb %bh, dac_size # store actual DAC size
dac_set:
# set color size to DAC size
movb dac_size, %al
movb %al, %fs:(PARAM_LFB_COLORS+0)
movb %al, %fs:(PARAM_LFB_COLORS+2)
movb %al, %fs:(PARAM_LFB_COLORS+4)
movb %al, %fs:(PARAM_LFB_COLORS+6)
# set color offsets to 0
movb $0, %fs:(PARAM_LFB_COLORS+1)
movb $0, %fs:(PARAM_LFB_COLORS+3)
movb $0, %fs:(PARAM_LFB_COLORS+5)
movb $0, %fs:(PARAM_LFB_COLORS+7)
dac_done:
# get protected mode interface informations # get protected mode interface informations
movw $0x4f0a, %ax movw $0x4f0a, %ax
xorw %bx, %bx xorw %bx, %bx
...@@ -1929,6 +1964,7 @@ scanning: .byte 0 # Performing mode scan ...@@ -1929,6 +1964,7 @@ scanning: .byte 0 # Performing mode scan
do_restore: .byte 0 # Screen contents altered during mode change do_restore: .byte 0 # Screen contents altered during mode change
svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes
graphic_mode: .byte 0 # Graphic mode with a linear frame buffer graphic_mode: .byte 0 # Graphic mode with a linear frame buffer
dac_size: .byte 6 # DAC bit depth
# Status messages # Status messages
keymsg: .ascii "Press <RETURN> to see video modes available, " keymsg: .ascii "Press <RETURN> to see video modes available, "
......
...@@ -87,15 +87,17 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var, ...@@ -87,15 +87,17 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var,
return 0; return 0;
} }
static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue) static void vesa_setpalette(int regno, unsigned red, unsigned green,
unsigned blue, struct fb_var_screeninfo *var)
{ {
#ifdef __i386__ #ifdef __i386__
struct { u_char blue, green, red, pad; } entry; struct { u_char blue, green, red, pad; } entry;
int shift = 16 - var->green.length;
if (pmi_setpal) { if (pmi_setpal) {
entry.red = red >> 10; entry.red = red >> shift;
entry.green = green >> 10; entry.green = green >> shift;
entry.blue = blue >> 10; entry.blue = blue >> shift;
entry.pad = 0; entry.pad = 0;
__asm__ __volatile__( __asm__ __volatile__(
"call *(%%esi)" "call *(%%esi)"
...@@ -109,9 +111,9 @@ static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned bl ...@@ -109,9 +111,9 @@ static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned bl
} else { } else {
/* without protected mode interface, try VGA registers... */ /* without protected mode interface, try VGA registers... */
outb_p(regno, dac_reg); outb_p(regno, dac_reg);
outb_p(red >> 10, dac_val); outb_p(red >> shift, dac_val);
outb_p(green >> 10, dac_val); outb_p(green >> shift, dac_val);
outb_p(blue >> 10, dac_val); outb_p(blue >> shift, dac_val);
} }
#endif #endif
} }
...@@ -132,7 +134,7 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, ...@@ -132,7 +134,7 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
switch (info->var.bits_per_pixel) { switch (info->var.bits_per_pixel) {
case 8: case 8:
vesa_setpalette(regno,red,green,blue); vesa_setpalette(regno,red,green,blue, &info->var);
break; break;
case 16: case 16:
if (info->var.red.offset == 10) { if (info->var.red.offset == 10) {
...@@ -331,7 +333,6 @@ static int __init vesafb_probe(struct device *device) ...@@ -331,7 +333,6 @@ static int __init vesafb_probe(struct device *device)
vesafb_defined.left_margin = (vesafb_defined.xres / 8) & 0xf8; vesafb_defined.left_margin = (vesafb_defined.xres / 8) & 0xf8;
vesafb_defined.hsync_len = (vesafb_defined.xres / 8) & 0xf8; vesafb_defined.hsync_len = (vesafb_defined.xres / 8) & 0xf8;
if (vesafb_defined.bits_per_pixel > 8) {
vesafb_defined.red.offset = screen_info.red_pos; vesafb_defined.red.offset = screen_info.red_pos;
vesafb_defined.red.length = screen_info.red_size; vesafb_defined.red.length = screen_info.red_size;
vesafb_defined.green.offset = screen_info.green_pos; vesafb_defined.green.offset = screen_info.green_pos;
...@@ -340,8 +341,10 @@ static int __init vesafb_probe(struct device *device) ...@@ -340,8 +341,10 @@ static int __init vesafb_probe(struct device *device)
vesafb_defined.blue.length = screen_info.blue_size; vesafb_defined.blue.length = screen_info.blue_size;
vesafb_defined.transp.offset = screen_info.rsvd_pos; vesafb_defined.transp.offset = screen_info.rsvd_pos;
vesafb_defined.transp.length = screen_info.rsvd_size; vesafb_defined.transp.length = screen_info.rsvd_size;
printk(KERN_INFO "vesafb: directcolor: " printk(KERN_INFO "vesafb: %s: "
"size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
(vesafb_defined.bits_per_pixel > 8) ?
"Truecolor" : "Pseudocolor",
screen_info.rsvd_size, screen_info.rsvd_size,
screen_info.red_size, screen_info.red_size,
screen_info.green_size, screen_info.green_size,
...@@ -350,11 +353,6 @@ static int __init vesafb_probe(struct device *device) ...@@ -350,11 +353,6 @@ static int __init vesafb_probe(struct device *device)
screen_info.red_pos, screen_info.red_pos,
screen_info.green_pos, screen_info.green_pos,
screen_info.blue_pos); screen_info.blue_pos);
} else {
vesafb_defined.red.length = 6;
vesafb_defined.green.length = 6;
vesafb_defined.blue.length = 6;
}
vesafb_fix.ypanstep = ypan ? 1 : 0; vesafb_fix.ypanstep = ypan ? 1 : 0;
vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0; vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment