Reset the DAC to 6-bit mode before calling the BIOS to set the screen

mode.  This works around bugs in at least 2 Intel BIOSes for our
subsequent setting of the DAC back to 8-bit mode.  The bug caused dark
(mostly 1/4-intensity) colors for all except the first setting to a
VESA graphics mode (including for settings to the current mode).

Remove restoration (with less bits) of the palette in vesa_unload()
after resetting the DAC to 6-bit mode.  Depend on the BIOS to keep
the palette consistent with the DAC for the simpler reset case like
we do everywhere else in places that are actually important.

Setting the video mode should reset everything to defaults, although
we usually don't want that.  Even the buggy BIOSes set the DAC to the
default 6-bit mode, and set the palette to a default that matches the
DAC.  We don't undo the reset for most things, but we do undo it for
the DAC (more precisely, we change to an 8-bit DAC if possible, and
this is the only way that we set to an 8-bit DAC; it is accidental
that if the DAC was in 8-bit mode from a previous mode switch then
setting it to 8-bit mode is an undo).  The buggy BIOSes are confused
by our setting of the DAC to 8-bit mode in the "undo" case.  They
should multiply palette entries by 4 to match, but they actually leave
all palette entries except #2 (green) and #248-255 (unused) untouched.
Green is mysteriously scaled from 0x2a to 0x6a, and #248-255 are scaled
correctly.

Our support for the 8-bit DAC had almost no effect except to enable
bugs.  Syscons barely supports 16 colors, so it doesn't benefit much
from having a palette with 16 million colors instead of only 256K.
Applications can manage the palette using FBIO_{GET,SET}PALETTE, but
the palette managed by this is only used in the less interesting modes
(text and non-truecolor graphics modes up to 8 bits wide), and the
kernel loses the changes on any mode switch (including to another vt
in a different mode).
This commit is contained in:
Bruce Evans 2017-04-02 08:39:32 +00:00
parent 0aecedaa83
commit 3a98d83edb

View File

@ -1322,6 +1322,16 @@ vesa_set_mode(video_adapter_t *adp, int mode)
#if VESA_DEBUG > 0
printf("VESA: about to set a VESA mode...\n");
#endif
/*
* The mode change should reset the palette format to 6 bits, so
* we must reset V_ADP_DAC8. Some BIOSes do an incomplete reset
* if we call them with an 8-bit palette, so reset directly.
*/
if (adp->va_flags & V_ADP_DAC8) {
vesa_bios_set_dac(6);
adp->va_flags &= ~V_ADP_DAC8;
}
/* don't use the linear frame buffer for text modes. XXX */
if (!(info.vi_flags & V_INFO_GRAPHICS))
info.vi_flags &= ~V_INFO_LINEAR;
@ -1331,9 +1341,6 @@ vesa_set_mode(video_adapter_t *adp, int mode)
if (vesa_bios_set_mode(mode | 0x8000))
return (1);
/* Palette format is reset by the above VBE function call. */
adp->va_flags &= ~V_ADP_DAC8;
if ((vesa_adp_info->v_flags & V_DAC8) != 0 &&
(info.vi_flags & V_INFO_GRAPHICS) != 0 &&
vesa_bios_set_dac(8) > 6)
@ -1928,7 +1935,6 @@ vesa_load(void)
static int
vesa_unload(void)
{
u_char palette[256*3];
int error;
/* if the adapter is currently in a VESA mode, don't unload */
@ -1942,10 +1948,8 @@ vesa_unload(void)
if ((error = vesa_unload_ioctl()) == 0) {
if (vesa_adp != NULL) {
if ((vesa_adp->va_flags & V_ADP_DAC8) != 0) {
vesa_bios_save_palette(0, 256, palette, 8);
vesa_bios_set_dac(6);
vesa_adp->va_flags &= ~V_ADP_DAC8;
vesa_bios_load_palette(0, 256, palette, 6);
}
vesa_adp->va_flags &= ~V_ADP_VESA;
vidsw[vesa_adp->va_index] = prevvidsw;