Date: Tue, 23 Mar 2010 23:10:17 +0000 (UTC) From: Jung-uk Kim <jkim@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r205564 - head/sys/dev/fb Message-ID: <201003232310.o2NNAHAD016763@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jkim Date: Tue Mar 23 23:10:17 2010 New Revision: 205564 URL: http://svn.freebsd.org/changeset/base/205564 Log: Be extremely careful when we determine bytes per scan line information. First, we compare mode table data against minimum value. If the mode table does not make sense, we set the minimum in the mode info. When we actually set the mode, we try VESA BIOS function and compare it against the previous value. If it makes more sense, update the information. Modified: head/sys/dev/fb/vesa.c Modified: head/sys/dev/fb/vesa.c ============================================================================== --- head/sys/dev/fb/vesa.c Tue Mar 23 23:09:38 2010 (r205563) +++ head/sys/dev/fb/vesa.c Tue Mar 23 23:10:17 2010 (r205564) @@ -188,9 +188,7 @@ static int vesa_bios_load_palette2(int s #define STATE_ALL (STATE_HW | STATE_DATA | STATE_DAC | STATE_REG) static ssize_t vesa_bios_state_buf_size(void); static int vesa_bios_save_restore(int code, void *p, size_t size); -#if 0 static int vesa_bios_get_line_length(void); -#endif static int vesa_bios_set_line_length(int pixel, int *bytes, int *lines); #if 0 static int vesa_bios_get_start(int *x, int *y); @@ -199,6 +197,7 @@ static int vesa_bios_set_start(int x, in static int vesa_map_gen_mode_num(int type, int color, int mode); static int vesa_translate_flags(u_int16_t vflags); static int vesa_translate_mmodel(u_int8_t vmodel); +static int vesa_get_bpscanline(struct vesa_mode *vmode); static int vesa_bios_init(void); static void vesa_clear_modes(video_info_t *info, int color); @@ -558,7 +557,6 @@ vesa_bios_save_restore(int code, void *p return (regs.R_AX != 0x004f); } -#if 0 static int vesa_bios_get_line_length(void) { @@ -575,7 +573,6 @@ vesa_bios_get_line_length(void) return (regs.R_BX); } -#endif static int vesa_bios_set_line_length(int pixel, int *bytes, int *lines) @@ -709,6 +706,43 @@ vesa_translate_mmodel(u_int8_t vmodel) return (V_INFO_MM_OTHER); } +static int +vesa_get_bpscanline(struct vesa_mode *vmode) +{ + int bpsl; + + if ((vmode->v_modeattr & V_MODEGRAPHICS) != 0) { + /* Find the minimum length. */ + switch (vmode->v_bpp / vmode->v_planes) { + case 1: + bpsl = vmode->v_width / 8; + break; + case 2: + bpsl = vmode->v_width / 4; + break; + case 4: + bpsl = vmode->v_width / 2; + break; + default: + bpsl = vmode->v_width * ((vmode->v_bpp + 7) / 8); + bpsl /= vmode->v_planes; + break; + } + + /* Use VBE 3.0 information if it looks sane. */ + if ((vmode->v_modeattr & V_MODELFB) != 0 && + vesa_adp_info->v_version >= 0x0300 && + vmode->v_linbpscanline > bpsl) + return (vmode->v_linbpscanline); + + /* Return the minimum if the mode table looks absurd. */ + if (vmode->v_bpscanline < bpsl) + return (bpsl); + } + + return (vmode->v_bpscanline); +} + #define VESA_MAXSTR 256 #define VESA_STRCPY(dst, src) do { \ @@ -733,7 +767,6 @@ vesa_bios_init(void) void *vmbuf; uint32_t offs; uint16_t vers; - int bpsl; int is_via_cle266; int modes; int i; @@ -858,9 +891,7 @@ vesa_bios_init(void) } #endif - bpsl = (vmode.v_modeattr & V_MODELFB) != 0 && vers >= 0x0300 ? - vmode.v_linbpscanline : vmode.v_bpscanline; - bsize = bpsl * vmode.v_height; + bsize = vesa_get_bpscanline(&vmode) * vmode.v_height; if ((vmode.v_modeattr & V_MODEGRAPHICS) != 0) bsize *= vmode.v_planes; @@ -1181,6 +1212,7 @@ static int vesa_set_mode(video_adapter_t *adp, int mode) { video_info_t info; + int bpsl; if (adp != vesa_adp) return ((*prevvidsw->set_mode)(adp, mode)); @@ -1257,6 +1289,20 @@ vesa_set_mode(video_adapter_t *adp, int (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0; vesa_adp->va_crtc_addr = (vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC; + + vesa_adp->va_line_width = info.vi_buffer_size / info.vi_height; + if ((info.vi_flags & V_INFO_GRAPHICS) != 0) + vesa_adp->va_line_width /= info.vi_planes; + + /* If VBE function returns bigger bytes per scan line, use it. */ + bpsl = vesa_bios_get_line_length(); + if (bpsl > vesa_adp->va_line_width) { + vesa_adp->va_line_width = bpsl; + info.vi_buffer_size = bpsl * info.vi_height; + if ((info.vi_flags & V_INFO_GRAPHICS) != 0) + info.vi_buffer_size *= info.vi_planes; + } + if (info.vi_flags & V_INFO_LINEAR) { #if VESA_DEBUG > 1 printf("VESA: setting up LFB\n"); @@ -1275,9 +1321,6 @@ vesa_set_mode(video_adapter_t *adp, int } vesa_adp->va_buffer_size = info.vi_buffer_size; vesa_adp->va_window_orig = 0; - vesa_adp->va_line_width = info.vi_buffer_size / info.vi_height; - if ((info.vi_flags & V_INFO_GRAPHICS) != 0) - vesa_adp->va_line_width /= info.vi_planes; vesa_adp->va_disp_start.x = 0; vesa_adp->va_disp_start.y = 0; #if VESA_DEBUG > 0
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201003232310.o2NNAHAD016763>