From: "Antonino A. Daplas" 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: Antonino Daplas Signed-off-by: Andrew Morton --- 25-akpm/arch/i386/boot/video.S | 36 +++++++++++++++++++++++ 25-akpm/drivers/video/vesafb.c | 62 +++++++++++++++++++---------------------- 2 files changed, 66 insertions(+), 32 deletions(-) diff -puN arch/i386/boot/video.S~fbdev-use-8-bit-dac-for-capable-hardware arch/i386/boot/video.S --- 25/arch/i386/boot/video.S~fbdev-use-8-bit-dac-for-capable-hardware 2004-08-21 13:47:34.473374784 -0700 +++ 25-akpm/arch/i386/boot/video.S 2004-08-21 13:47:34.479373872 -0700 @@ -232,6 +232,41 @@ mopar_gr: xorl %eax, %eax movw 18(%di), %ax 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 movw $0x4f0a, %ax xorw %bx, %bx @@ -1929,6 +1964,7 @@ scanning: .byte 0 # Performing mode scan do_restore: .byte 0 # Screen contents altered during mode change svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes graphic_mode: .byte 0 # Graphic mode with a linear frame buffer +dac_size: .byte 6 # DAC bit depth # Status messages keymsg: .ascii "Press to see video modes available, " diff -puN drivers/video/vesafb.c~fbdev-use-8-bit-dac-for-capable-hardware drivers/video/vesafb.c --- 25/drivers/video/vesafb.c~fbdev-use-8-bit-dac-for-capable-hardware 2004-08-21 13:47:34.474374632 -0700 +++ 25-akpm/drivers/video/vesafb.c 2004-08-21 13:47:34.480373720 -0700 @@ -87,15 +87,17 @@ static int vesafb_pan_display(struct fb_ 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__ struct { u_char blue, green, red, pad; } entry; + int shift = 16 - var->green.length; if (pmi_setpal) { - entry.red = red >> 10; - entry.green = green >> 10; - entry.blue = blue >> 10; + entry.red = red >> shift; + entry.green = green >> shift; + entry.blue = blue >> shift; entry.pad = 0; __asm__ __volatile__( "call *(%%esi)" @@ -109,9 +111,9 @@ static void vesa_setpalette(int regno, u } else { /* without protected mode interface, try VGA registers... */ outb_p(regno, dac_reg); - outb_p(red >> 10, dac_val); - outb_p(green >> 10, dac_val); - outb_p(blue >> 10, dac_val); + outb_p(red >> shift, dac_val); + outb_p(green >> shift, dac_val); + outb_p(blue >> shift, dac_val); } #endif } @@ -132,7 +134,7 @@ static int vesafb_setcolreg(unsigned reg switch (info->var.bits_per_pixel) { case 8: - vesa_setpalette(regno,red,green,blue); + vesa_setpalette(regno,red,green,blue, &info->var); break; case 16: if (info->var.red.offset == 10) { @@ -331,30 +333,26 @@ static int __init vesafb_probe(struct de vesafb_defined.left_margin = (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.length = screen_info.red_size; - vesafb_defined.green.offset = screen_info.green_pos; - vesafb_defined.green.length = screen_info.green_size; - vesafb_defined.blue.offset = screen_info.blue_pos; - vesafb_defined.blue.length = screen_info.blue_size; - vesafb_defined.transp.offset = screen_info.rsvd_pos; - vesafb_defined.transp.length = screen_info.rsvd_size; - printk(KERN_INFO "vesafb: directcolor: " - "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", - screen_info.rsvd_size, - screen_info.red_size, - screen_info.green_size, - screen_info.blue_size, - screen_info.rsvd_pos, - screen_info.red_pos, - screen_info.green_pos, - screen_info.blue_pos); - } else { - vesafb_defined.red.length = 6; - vesafb_defined.green.length = 6; - vesafb_defined.blue.length = 6; - } + vesafb_defined.red.offset = screen_info.red_pos; + vesafb_defined.red.length = screen_info.red_size; + vesafb_defined.green.offset = screen_info.green_pos; + vesafb_defined.green.length = screen_info.green_size; + vesafb_defined.blue.offset = screen_info.blue_pos; + vesafb_defined.blue.length = screen_info.blue_size; + vesafb_defined.transp.offset = screen_info.rsvd_pos; + vesafb_defined.transp.length = screen_info.rsvd_size; + printk(KERN_INFO "vesafb: %s: " + "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.red_size, + screen_info.green_size, + screen_info.blue_size, + screen_info.rsvd_pos, + screen_info.red_pos, + screen_info.green_pos, + screen_info.blue_pos); vesafb_fix.ypanstep = ypan ? 1 : 0; vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0; _