f13b792a3a
3335. Clean up compiler warnings in lib/font/bitmap (#3411, Matt Grossman). 3334. TGA fixes, add sync on green (#3410, Matt Grossman). 3333. Fix NULL pointer dereference in libXaw (#3406, Christopher Sekiya). 3332. Add Rage128 support (#3405, Rik Faith, funded by ATI). 3331. Add MTRR support for NetBSD and OpenBSD. Add new NetBSD aperture driver (#3404, Matthieu Herrb). 3330. Xterm patch #121 (#3402, Thomas Dickey). 3329. Rendition driver bugfixes and alpha related cleanups (#3400, Dejan Ilic, Marc Langenbach, Egbert Eich). 3328. Add void input device (#3392, Frederic Lepied). 3327. Changed the Xon serial option to be able to select xon/xoff for input, output or both. Add support for Graphire models. Change wacom init phase to use new Xoff option (#3391, Frederic Lepied). 3326. Change the SwapAxes option to SwapXY in elographics/microtouch driver to match an already existing option in the Dynapro driver. Add a Focus class capability to the elographics driver (#3395, Patrick Lecoanet). 3325. Update mouse rate handling (#3388, Harald Koenig). 3324. Fix NULL pointer dereference in misprite.c (#3380, Edward Wang). 3323. Add FBDev and ShadowFB support to glint driver. Add new option "NoWriteBitmap" (#3383, Michel Daenzer). 3322. Update SuperProbe to handle S3 Savage4, Savage200 and clean up Trio3D/Savage3D detection (#3382,3384 Harald Koenig). 3321. Add new framebuffer code and tiny X DDX architecture (#3379, Keith Packard). 3320. Add DGA2 documentation (#3378, Mark Vojkovich). 3319. Update XFree86 manpage wrt -bpp/-depth/-fbbpp (#3377, Andy Isaacson). 3318. Make SuperProbe check primary cards, only (#3374, Harald Koenig). 3317. Add SilkenMouse to *BSD (#3373, Matthieu Herrb). 3316. Allow SilkenMouse to work if not all drivers of an OS support SIGIO (#3372, Keith Packard). 3315. Fix a few problems in TGA driver and add support for backing store and SilkenMouse (#3371, Matt Grossman). 3314. Add smarter scheduler (#3370, Keith Packard). 3313. Xterm patch #120 (#3369, Thomas Dickey). 3312. Enable xf86SetKbdRate function on Solaris 8 (#3364, David Holland). 3311. Fix some bugs and add acceleration to Rendition server (#3360, Dejan Ilic). 3310. Make raw DDC information available as properties in the root window (#3357, Andrew Aitchison). 3309. Fix for xf86CreateRootWindow (#3355, Andrew Aitchison). 3308. Add manpage for the chips driver (#3353, David Bateman). 3307. Update contact info (#3352, Andrew van der Stock). 3306. Add kbd rate support for Linux (#3363, Harald Koenig). 3305. Update Portuguese XKB map (#3351, Joao Esteves, Francisco Colaco). 3304. Fix text clipping in 3dfx driver (#3349, Henrik Harmsen). 3303. Fix S3 ViRGE hw cursor (#3348, Harald Koenig). 3302. Fix clipping in 3dfx driver (#3342, Daryll Strauss). 3301. Enable SilkenMouse for 3dfx driver (#3341, Henrik Harmsen). 3300. Enable SIGIO support on LynxOS (#3339, Thomas Mueller). 3299. Get TRUE defined in sigio.c. Fix xterm compile problem on ISC (#3338, Michael Rohleder). 3298. Correct DPMS suspend/standby modes for 3dfx driver (#3336, Henrik Harmsen) 3297. Xterm patch #119 (#3335, Thomas Dickey).
1299 lines
34 KiB
C
1299 lines
34 KiB
C
/*
|
|
* $Id$
|
|
*
|
|
* Copyright © 1999 Keith Packard
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of Keith Packard not be used in
|
|
* advertising or publicity pertaining to distribution of the software without
|
|
* specific, written prior permission. Keith Packard makes no
|
|
* representations about the suitability of this software for any purpose. It
|
|
* is provided "as is" without express or implied warranty.
|
|
*
|
|
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
/* $XFree86: $ */
|
|
|
|
#include "s3.h"
|
|
|
|
#define REGISTERS_OFFSET (0x1000000)
|
|
#define PACKED_OFFSET (0x8100)
|
|
|
|
/*
|
|
* Clock synthesis:
|
|
*
|
|
* f_out = f_ref * ((M + 2) / ((N + 2) * (1 << R)))
|
|
*
|
|
* Constraints:
|
|
*
|
|
* 1. 135MHz <= f_ref * ((M + 2) / (N + 2)) <= 270 MHz
|
|
* 2. N >= 1
|
|
*
|
|
* Vertical refresh rate = clock / ((hsize + hblank) * (vsize + vblank))
|
|
* Horizontal refresh rate = clock / (hsize + hblank)
|
|
*/
|
|
|
|
#define DEFAULT_S3_TIMING 1
|
|
|
|
S3Timing s3Timings[] = {
|
|
/* FP BP BLANK */
|
|
/* M N R blank bios5 */
|
|
{ 640, 480, 60,
|
|
16, 48, 160, /* horizontal 31.321 KHz */
|
|
10, 33, 45, /* vertical 59.568 Hz */
|
|
26, 0, 3, /* pixel 25.057 MHz */
|
|
},
|
|
|
|
{ 800, 600, 85,
|
|
32, 152, 248, /* horizontal 53.673 KHz */
|
|
1, 27, 31, /* vertical 85.060 Hz */
|
|
108, 5, 2, /* pixel 56.249 MHz */
|
|
},
|
|
{ 800, 600, 75,
|
|
16, 160, 256, /* horizontal 46.891 KHz */
|
|
1, 21, 25, /* vertical 75.025 Hz */
|
|
81, 4, 2, /* pixel 49.516 MHz */
|
|
},
|
|
{ 800, 600, 72,
|
|
56, 64, 240, /* horizontal 48.186 KHz */
|
|
37, 23, 66, /* vertical 72.351 Hz */
|
|
26, 0, 2, /* pixel 50.113 MHz */
|
|
},
|
|
|
|
{ 1024, 768, 85,
|
|
48, 208, 352, /* horizontal 68.676 KHz */
|
|
1, 36, 40, /* vertical 84.996 Hz */
|
|
64, 3, 1, /* pixel 94.499 MHz */
|
|
},
|
|
{ 1024, 768, 75,
|
|
16, 176, 288, /* horizontal 60.022 KHz */
|
|
1, 28, 32, /* vertical 75.028 Hz */
|
|
20, 0, 1, /* pixel 78.749 MHz */
|
|
},
|
|
{ 1024, 768, 70,
|
|
24, 144, 304, /* horizontal 56.604 KHz */
|
|
3, 29, 38, /* vertical 70.227 Hz */
|
|
40, 2, 1, /* pixel 75.170 MHz */
|
|
},
|
|
{ 1024, 768, 66,
|
|
24, 144, 304, /* horizontal 53.234 KHz */
|
|
3, 29, 38, /* vertical 66.047 Hz */
|
|
77, 6, 1, /* pixel 70.695 MHz */
|
|
},
|
|
|
|
{ 1152, 900, 85,
|
|
48, 208, 384, /* horizontal 79.900 KHz */
|
|
1, 32, 38, /* vertical 85.181 Hz */
|
|
118, 5, 1, /* pixel 122.726 MHz */
|
|
},
|
|
{ 1152, 900, 75,
|
|
32, 208, 384, /* horizontal 70.495 Khz */
|
|
1, 32, 38, /* vertical 75.154 Hz */
|
|
119, 6, 1, /* pixel 108.280 MHz */
|
|
},
|
|
{ 1152, 900, 70,
|
|
32, 208, 384, /* horizontal 65.251 KHz */
|
|
2, 32, 38, /* vertical 69.564 Hz */
|
|
12, 0, 0, /* pixel 100.226 MHz */
|
|
},
|
|
{ 1152, 900, 66,
|
|
32, 208, 384, /* horizontal 61.817 KHz */
|
|
1, 32, 38, /* vertical 65.903 Hz */
|
|
124, 17, 0, /* pixel 94.951 MHz */
|
|
},
|
|
{ 1280, 1024, 85,
|
|
16, 248, 416, /* horizontal 90.561 KHz */
|
|
1, 40, 45, /* vertical 84.717 Hz */
|
|
116, 9, 0, /* pixel 153.593 MHz */
|
|
},
|
|
{ 1280, 1024, 75,
|
|
16, 248, 408, /* horizontal 80.255 KHz */
|
|
1, 38, 42, /* vertical 75.285 Hz */
|
|
111, 4, 1, /* pixel 134.828 MHz */
|
|
},
|
|
{ 1280, 1024, 70,
|
|
32, 248, 400, /* horizontal 74.573 KHz */
|
|
0, 36, 39, /* vertical 70.153 Hz */
|
|
68, 2, 1, /* pixel 125.283 MHz */
|
|
},
|
|
{ 1280, 1024, 66,
|
|
32, 248, 400, /* horizontal 70.007 KHz */
|
|
0, 36, 39, /* vertical 65.858 Hz */
|
|
113, 5, 1, /* pixel 117.612 MHz */
|
|
},
|
|
|
|
{ 1600, 1200, 85,
|
|
64, 304, 560, /* horizontal 106.059 KHz */
|
|
1, 46, 50, /* vertical 84.847 Hz */
|
|
126, 6, 0, /* pixel 229.088 MHz */
|
|
},
|
|
{ 1600, 1200, 75,
|
|
64, 304, 560, /* horizontal 93.748 KHz */
|
|
1, 46, 50, /* vertical 74.999 Hz */
|
|
97, 5, 0, /* pixel 202.497 MHz */
|
|
},
|
|
{ 1600, 1200, 70,
|
|
56, 304, 588, /* horizontal 87.524 KHz */
|
|
1, 46, 50, /* vertical 70.019 Hz */
|
|
105, 6, 0, /* pixel 191.503 MHz */
|
|
},
|
|
{ 1600, 1200, 65,
|
|
56, 308, 524, /* horizontal 80.050 KHz */
|
|
1, 38, 42, /* vertical 64.453 Hz */
|
|
93, 6, 0, /* pixel 170.026 MHz */
|
|
},
|
|
};
|
|
|
|
#define NUM_S3_TIMINGS (sizeof (s3Timings) / sizeof (s3Timings[0]))
|
|
|
|
CARD8
|
|
_s3ReadIndexRegister (volatile CARD8 *base, CARD8 index)
|
|
{
|
|
CARD8 ret;
|
|
*base = index;
|
|
ret = *(base + 1);
|
|
DRAW_DEBUG ((DEBUG_CRTC, " 0x%3x 0x%02x -> 0x%02x",
|
|
((int) base) & 0xfff, index, ret));
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
_s3WriteIndexRegister (volatile CARD8 *base, CARD8 index, CARD8 value)
|
|
{
|
|
DRAW_DEBUG ((DEBUG_CRTC, " 0x%3x 0x%02x <- 0x%02x",
|
|
((int) base) & 0xfff, index, value));
|
|
*base = index;
|
|
*(base + 1) = value;
|
|
}
|
|
|
|
/*
|
|
* Map the S3 card and detect its configuration. Do not touch the card
|
|
*/
|
|
|
|
static void
|
|
_s3LoadCrtc (S3Ptr s3, S3Crtc *crtc)
|
|
{
|
|
crtc->h_total_0_7 = GetCrtc (s3, 0x00);
|
|
crtc->h_display_end_0_7 = GetCrtc (s3, 0x01);
|
|
crtc->h_blank_start_0_7 = GetCrtc (s3, 0x02);
|
|
crtc->_h_blank_end = GetCrtc (s3, 0x03);
|
|
crtc->h_sync_start_0_7 = GetCrtc (s3, 0x04);
|
|
crtc->_h_sync_end = GetCrtc (s3, 0x05);
|
|
crtc->v_total_0_7 = GetCrtc (s3, 0x06);
|
|
crtc->crtc_overflow = GetCrtc (s3, 0x07);
|
|
crtc->preset_row_scan = GetCrtc (s3, 0x08);
|
|
crtc->_max_scan_line = GetCrtc (s3, 0x09);
|
|
|
|
crtc->start_address_8_15 = GetCrtc (s3, 0x0c);
|
|
crtc->start_address_0_7 = GetCrtc (s3, 0x0d);
|
|
|
|
crtc->v_retrace_start_0_7 = GetCrtc (s3, 0x10);
|
|
crtc->_v_retrace_end = GetCrtc (s3, 0x11);
|
|
crtc->v_display_end_0_7 = GetCrtc (s3, 0x12);
|
|
crtc->screen_off_0_7 = GetCrtc (s3, 0x13);
|
|
|
|
crtc->v_blank_start_0_7 = GetCrtc (s3, 0x15);
|
|
crtc->v_blank_end_0_7 = GetCrtc (s3, 0x16);
|
|
|
|
crtc->line_compare_0_7 = GetCrtc (s3, 0x18);
|
|
|
|
crtc->memory_configuration = GetCrtc (s3, 0x31);
|
|
|
|
crtc->misc_1 = GetCrtc (s3, 0x3a);
|
|
crtc->h_start_fifo_fetch_0_7 = GetCrtc (s3, 0x3b);
|
|
|
|
crtc->mode_control = GetCrtc (s3, 0x42);
|
|
|
|
crtc->hardware_cursor_mode = GetCrtc (s3, 0x45);
|
|
crtc->cursor_address_8_15 = GetCrtc (s3, 0x4C);
|
|
crtc->cursor_address_0_7 = GetCrtc (s3, 0x4D);
|
|
|
|
crtc->extended_system_control_1 = GetCrtc (s3, 0x50);
|
|
crtc->extended_system_control_2 = GetCrtc (s3, 0x51);
|
|
|
|
crtc->extended_memory_control = GetCrtc (s3, 0x53);
|
|
|
|
crtc->extended_ramdac_control = GetCrtc (s3, 0x55);
|
|
|
|
crtc->extended_horizontal_overflow = GetCrtc (s3, 0x5d);
|
|
crtc->extended_vertical_overflow = GetCrtc (s3, 0x5e);
|
|
|
|
crtc->l_parm_0_7 = GetCrtc (s3, 0x62);
|
|
|
|
crtc->extended_misc_control = GetCrtc (s3, 0x65);
|
|
|
|
crtc->extended_misc_control_2 = GetCrtc (s3, 0x67);
|
|
|
|
crtc->configuration_3 = GetCrtc (s3, 0x68);
|
|
|
|
crtc->extended_system_control_3 = GetCrtc (s3, 0x69);
|
|
|
|
crtc->extended_bios_5 = GetCrtc (s3, 0x6d);
|
|
|
|
crtc->extended_sequencer_b = GetSrtc (s3, 0x0b);
|
|
crtc->extended_sequencer_d = GetSrtc (s3, 0x0d);
|
|
crtc->dclk_value_low = GetSrtc (s3, 0x12);
|
|
crtc->dclk_value_high = GetSrtc (s3, 0x13);
|
|
crtc->control_2 = GetSrtc (s3, 0x15);
|
|
crtc->ramdac_control = GetSrtc (s3, 0x18);
|
|
|
|
crtc->dclk_value_low_savage = GetSrtc (s3, 0x36);
|
|
crtc->dclk_pll_m0_savage_0_7 = GetSrtc (s3, 0x37);
|
|
crtc->dclk_pll_m1_savage_0_7 = GetSrtc (s3, 0x38);
|
|
crtc->extended_seq_39 = GetSrtc (s3, 0x39);
|
|
|
|
fprintf (stderr, "SR1A 0x%x SR1B 0x%x\n",
|
|
GetSrtc (s3, 0x1a),
|
|
GetSrtc (s3, 0x1b));
|
|
fprintf (stderr, "SR36 0x%x SR37 0x%x SR38 0x%x SR39 0x%x\n",
|
|
GetSrtc (s3, 0x36),
|
|
GetSrtc (s3, 0x37),
|
|
GetSrtc (s3, 0x38),
|
|
GetSrtc (s3, 0x39));
|
|
/* combine values */
|
|
|
|
switch (crtc_ge_screen_width(crtc)) {
|
|
case 0:
|
|
if (crtc->enable_two_page)
|
|
crtc->ge_screen_pitch = 2048;
|
|
else
|
|
crtc->ge_screen_pitch = 1024;
|
|
break;
|
|
case 1:
|
|
crtc->ge_screen_pitch = 640;
|
|
break;
|
|
case 2:
|
|
/* ignore magic 1600x1200x4 mode */
|
|
crtc->ge_screen_pitch = 800;
|
|
break;
|
|
case 3:
|
|
crtc->ge_screen_pitch = 1280;
|
|
break;
|
|
case 4:
|
|
crtc->ge_screen_pitch = 1152;
|
|
break;
|
|
case 5:
|
|
crtc->ge_screen_pitch = 0; /* reserved */
|
|
break;
|
|
case 6:
|
|
crtc->ge_screen_pitch = 1600;
|
|
break;
|
|
case 7:
|
|
crtc->ge_screen_pitch = 0; /* reserved */
|
|
break;
|
|
}
|
|
switch (crtc->pixel_length) {
|
|
case 0:
|
|
crtc->bits_per_pixel = 8;
|
|
crtc->pixel_width = (crtc_h_display_end(crtc) + 1) * 8;
|
|
break;
|
|
case 1:
|
|
crtc->bits_per_pixel = 16;
|
|
crtc->pixel_width = (crtc_h_display_end(crtc) + 1) * 4;
|
|
break;
|
|
case 3:
|
|
crtc->bits_per_pixel = 32;
|
|
crtc->pixel_width = (crtc_h_display_end(crtc) + 1) * 8;
|
|
break;
|
|
}
|
|
crtc->double_pixel_mode = 0;
|
|
switch (crtc->color_mode) {
|
|
case 0x0:
|
|
crtc->depth = 8; break;
|
|
case 0x1:
|
|
crtc->depth = 8; crtc->double_pixel_mode = 1; break;
|
|
case 0x3:
|
|
crtc->depth = 15; break;
|
|
case 0x5:
|
|
crtc->depth = 16; break;
|
|
case 0x7:
|
|
crtc->depth = 24; break; /* unused */
|
|
case 0xd:
|
|
crtc->depth = 24; break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_s3SetBlank (S3Ptr s3, Bool blank)
|
|
{
|
|
CARD8 clock_mode;
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "3c4 at 0x%x\n", &s3->crt_vga_3c4));
|
|
clock_mode = _s3ReadIndexRegister (&s3->crt_vga_3c4, 0x01);
|
|
if (blank)
|
|
clock_mode |= 0x20;
|
|
else
|
|
clock_mode &= ~0x20;
|
|
_s3WaitVRetrace (s3);
|
|
_s3WriteIndexRegister (&s3->crt_vga_3c4, 0x01, clock_mode);
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "blank is set to 0x%x", clock_mode));
|
|
}
|
|
|
|
static void
|
|
_s3SetDepth (S3Ptr s3, S3Crtc *crtc)
|
|
{
|
|
CARD8 save_3c2;
|
|
_s3SetBlank (s3, TRUE);
|
|
PutCrtc(s3, 0x38, 0x48);
|
|
PutCrtc(s3, 0x39, 0xA0);
|
|
PutCrtc(s3, 0x00, crtc->h_total_0_7);
|
|
PutCrtc(s3, 0x01, crtc->h_display_end_0_7);
|
|
PutCrtc(s3, 0x02, crtc->h_blank_start_0_7);
|
|
PutCrtc(s3, 0x03, crtc->_h_blank_end);
|
|
PutCrtc(s3, 0x04, crtc->h_sync_start_0_7);
|
|
PutCrtc(s3, 0x05, crtc->_h_sync_end);
|
|
PutCrtc(s3, 0x06, crtc->v_total_0_7);
|
|
PutCrtc(s3, 0x07, crtc->crtc_overflow);
|
|
PutCrtc(s3, 0x09, crtc->_max_scan_line);
|
|
PutCrtc(s3, 0x0c, crtc->start_address_8_15);
|
|
PutCrtc(s3, 0x0d, crtc->start_address_0_7);
|
|
PutCrtc(s3, 0x10, crtc->v_retrace_start_0_7);
|
|
PutCrtc(s3, 0x11, crtc->_v_retrace_end);
|
|
PutCrtc(s3, 0x12, crtc->v_display_end_0_7);
|
|
PutCrtc(s3, 0x13, crtc->screen_off_0_7);
|
|
PutCrtc(s3, 0x15, crtc->v_blank_start_0_7);
|
|
PutCrtc(s3, 0x16, crtc->v_blank_end_0_7);
|
|
PutCrtc(s3, 0x18, crtc->line_compare_0_7);
|
|
PutCrtc(s3, 0x31, crtc->memory_configuration);
|
|
PutCrtc(s3, 0x3a, crtc->misc_1);
|
|
PutCrtc(s3, 0x3b, crtc->h_start_fifo_fetch_0_7);
|
|
PutCrtc(s3, 0x42, crtc->mode_control);
|
|
PutCrtc(s3, 0x45, crtc->hardware_cursor_mode);
|
|
PutCrtc(s3, 0x4c, crtc->cursor_address_8_15);
|
|
PutCrtc(s3, 0x4d, crtc->cursor_address_0_7);
|
|
PutCrtc(s3, 0x50, crtc->extended_system_control_1);
|
|
PutCrtc(s3, 0x51, crtc->extended_system_control_2);
|
|
PutCrtc(s3, 0x53, crtc->extended_memory_control);
|
|
PutCrtc(s3, 0x55, crtc->extended_ramdac_control);
|
|
PutCrtc(s3, 0x5d, crtc->extended_horizontal_overflow);
|
|
PutCrtc(s3, 0x5e, crtc->extended_vertical_overflow);
|
|
PutCrtc(s3, 0x62, crtc->l_parm_0_7);
|
|
PutCrtc(s3, 0x65, crtc->extended_misc_control);
|
|
PutCrtc(s3, 0x67, crtc->extended_misc_control_2);
|
|
PutCrtc(s3, 0x68, crtc->configuration_3);
|
|
PutCrtc(s3, 0x69, crtc->extended_system_control_3);
|
|
PutCrtc(s3, 0x6d, crtc->extended_bios_5);
|
|
PutCrtc(s3, 0x39, 0x00);
|
|
PutCrtc(s3, 0x38, 0x00);
|
|
PutSrtc(s3, 0x0b, crtc->extended_sequencer_b);
|
|
PutSrtc(s3, 0x0d, crtc->extended_sequencer_d);
|
|
/*
|
|
* Move new dclk/mclk values into PLL
|
|
*/
|
|
save_3c2 = s3->crt_vga_3cc;
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "save_3c2 0x%x", save_3c2));
|
|
s3->crt_vga_3c2 = 0x0f;
|
|
|
|
PutSrtc (s3, 0x36, crtc->dclk_value_low_savage);
|
|
PutSrtc (s3, 0x37, crtc->dclk_pll_m0_savage_0_7);
|
|
PutSrtc (s3, 0x38, crtc->dclk_pll_m1_savage_0_7);
|
|
PutSrtc (s3, 0x39, crtc->extended_seq_39);
|
|
PutSrtc(s3, 0x12, crtc->dclk_value_low);
|
|
PutSrtc(s3, 0x13, crtc->dclk_value_high);
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "Set PLL load enable, frobbing clk_load..."));
|
|
crtc->dfrq_en = 1;
|
|
PutSrtc(s3, 0x15, crtc->control_2);
|
|
PutSrtc(s3, 0x18, crtc->ramdac_control);
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "Clk load frobbed, restoring 3c2 to 0x%x", save_3c2));
|
|
s3->crt_vga_3c2 = save_3c2;
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "Enabling display"));
|
|
_s3SetBlank (s3, FALSE);
|
|
}
|
|
|
|
void
|
|
_s3RestoreCrtc (S3Ptr s3, S3Crtc *crtc)
|
|
{
|
|
_s3SetDepth (s3, crtc);
|
|
}
|
|
|
|
s3Reset (S3CardInfo *s3c)
|
|
{
|
|
S3Ptr s3 = s3c->s3;
|
|
S3Save *save = &s3c->save;
|
|
CARD8 *cursor_base;
|
|
|
|
LockS3 (s3c);
|
|
|
|
_s3UnlockExt (s3);
|
|
|
|
_s3RestoreCrtc (s3, &save->crtc);
|
|
|
|
/* set foreground */
|
|
/* Reset cursor color stack pointers */
|
|
(void) GetCrtc(s3, 0x45);
|
|
PutCrtc(s3, 0x4a, save->cursor_fg);
|
|
/* XXX for deeper screens? */
|
|
|
|
/* set background */
|
|
/* Reset cursor color stack pointers */
|
|
(void) GetCrtc(s3, 0x45);
|
|
PutCrtc(s3, 0x4b, save->cursor_bg);
|
|
|
|
_s3LockExt (s3);
|
|
|
|
/* graphics engine state */
|
|
s3->alt_mix = save->alt_mix;
|
|
s3->write_mask = save->write_mask;
|
|
s3->fg = save->fg;
|
|
s3->bg = save->bg;
|
|
/* XXX should save and restore real values? */
|
|
s3->scissors_tl = 0x00000000;
|
|
s3->scissors_br = 0x0fff0fff;
|
|
|
|
_s3WriteIndexRegister (&s3->crt_vga_3c4, 0x01, save->clock_mode);
|
|
PutSrtc(s3, 0x08, save->locksrtc);
|
|
PutCrtc(s3, 0x39, save->lock2);
|
|
PutCrtc(s3, 0x38, save->lock1);
|
|
|
|
UnlockS3 (s3c);
|
|
}
|
|
|
|
void
|
|
s3Save (S3CardInfo *s3c)
|
|
{
|
|
S3Ptr s3 = s3c->s3;
|
|
S3Save *save = &s3c->save;
|
|
S3Crtc newCrtc;
|
|
CARD8 t1, t2;
|
|
CARD8 *cursor_base;
|
|
|
|
LockS3 (s3c);
|
|
|
|
save->alt_mix = s3->alt_mix;
|
|
save->write_mask = s3->write_mask;
|
|
save->fg = s3->fg;
|
|
save->bg = s3->bg;
|
|
|
|
save->lock1 = GetCrtc(s3, 0x38);
|
|
save->lock2 = GetCrtc(s3, 0x39);
|
|
save->locksrtc = GetSrtc (s3, 0x08);
|
|
|
|
/* unlock srtc registers to read them */
|
|
PutSrtc (s3, 0x08, 0x06);
|
|
|
|
save->clock_mode = _s3ReadIndexRegister (&s3->crt_vga_3c4, 0x01);
|
|
|
|
_s3UnlockExt (s3);
|
|
save->cursor_fg = GetCrtc(s3, 0x4a);
|
|
save->cursor_bg = GetCrtc(s3, 0x4b);
|
|
|
|
_s3LoadCrtc (s3, &save->crtc);
|
|
|
|
_s3LockExt (s3);
|
|
|
|
UnlockS3 (s3c);
|
|
}
|
|
Bool
|
|
s3CardInit (KdCardInfo *card)
|
|
{
|
|
S3CardInfo *s3c;
|
|
S3Ptr s3;
|
|
int size;
|
|
CARD8 *registers;
|
|
CARD32 s3FrameBuffer;
|
|
CARD32 s3Registers;
|
|
CARD8 *temp_buffer;
|
|
CARD32 max_memory;
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "s3CardInit"));
|
|
s3c = (S3CardInfo *) xalloc (sizeof (S3CardInfo));
|
|
if (!s3c)
|
|
{
|
|
DRAW_DEBUG ((DEBUG_FAILURE, "can't alloc s3 card info"));
|
|
goto bail0;
|
|
}
|
|
|
|
memset (s3c, '\0', sizeof (S3CardInfo));
|
|
|
|
card->driver = s3c;
|
|
|
|
if (card->attr.naddr > 1)
|
|
{
|
|
s3FrameBuffer = card->attr.address[1];
|
|
s3Registers = card->attr.address[0];
|
|
max_memory = 32 * 1024 * 1024;
|
|
s3c->savage = TRUE;
|
|
}
|
|
else
|
|
{
|
|
s3FrameBuffer = card->attr.address[0];
|
|
s3Registers = s3FrameBuffer + REGISTERS_OFFSET;
|
|
max_memory = 4 * 1024 * 1024;
|
|
s3c->savage = FALSE;
|
|
}
|
|
|
|
fprintf (stderr, "S3 at 0x%x/0x%x\n", s3Registers, s3FrameBuffer);
|
|
registers = KdMapDevice (s3Registers,
|
|
sizeof (S3) + PACKED_OFFSET);
|
|
if (!registers)
|
|
{
|
|
ErrorF ("Can't map s3 device\n");
|
|
goto bail2;
|
|
}
|
|
s3 = (S3Ptr) (registers + PACKED_OFFSET);
|
|
s3c->registers = registers;
|
|
s3c->s3 = s3;
|
|
|
|
#if 0
|
|
s3->crt_vga_3c3 = 1; /* wake up part from deep sleep */
|
|
s3->crt_vga_3c2 = 0x01 | 0x02 | 0x0c;
|
|
|
|
s3->crt_vga_3c4 = 0x58;
|
|
s3->crt_vga_3c5 = 0x10 | 0x3;
|
|
#endif
|
|
|
|
/*
|
|
* Can't trust S3 register value for frame buffer amount, must compute
|
|
*/
|
|
temp_buffer = KdMapDevice (s3FrameBuffer, max_memory);
|
|
|
|
s3c->memory = KdFrameBufferSize (temp_buffer, max_memory);
|
|
|
|
fprintf (stderr, "Frame buffer 0x%x\n", s3c->memory);
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "Detected frame buffer %d", s3c->memory));
|
|
|
|
KdUnmapDevice (temp_buffer, 4096 * 1024);
|
|
|
|
if (!s3c->memory)
|
|
{
|
|
ErrorF ("Can't detect s3 frame buffer at 0x%x\n", s3FrameBuffer);
|
|
goto bail3;
|
|
}
|
|
|
|
s3c->frameBuffer = KdMapDevice (s3FrameBuffer, s3c->memory);
|
|
if (!s3c->frameBuffer)
|
|
{
|
|
ErrorF ("Can't map s3 frame buffer\n");
|
|
goto bail3;
|
|
}
|
|
|
|
card->driver = s3c;
|
|
|
|
return TRUE;
|
|
bail3:
|
|
KdUnmapDevice ((void *) s3, sizeof (S3));
|
|
bail2:
|
|
bail1:
|
|
xfree (s3c);
|
|
bail0:
|
|
return FALSE;
|
|
}
|
|
|
|
Bool
|
|
s3ScreenInit (KdScreenInfo *screen)
|
|
{
|
|
KdCardInfo *card = screen->card;
|
|
S3CardInfo *s3c = (S3CardInfo *) card->driver;
|
|
S3ScreenInfo *s3s;
|
|
int screen_size;
|
|
int memory;
|
|
int requested_memory;
|
|
int v_total, h_total;
|
|
int byte_width;
|
|
int pixel_width;
|
|
int m, n, r;
|
|
int i;
|
|
S3Timing *t;
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "s3ScreenInit"));
|
|
s3s = (S3ScreenInfo *) xalloc (sizeof (S3ScreenInfo));
|
|
if (!s3s)
|
|
return FALSE;
|
|
|
|
memset (s3s, '\0', sizeof (S3ScreenInfo));
|
|
|
|
if (!screen->width || !screen->height)
|
|
{
|
|
screen->width = 800;
|
|
screen->height = 600;
|
|
screen->rate = 72;
|
|
}
|
|
if (!screen->depth)
|
|
screen->depth = 8;
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "Requested parameters %dx%dx%d",
|
|
screen->width, screen->height, screen->rate));
|
|
for (i = 0, t = s3Timings; i < NUM_S3_TIMINGS; i++, t++)
|
|
{
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "Available parameters %dx%dx%d",
|
|
t->horizontal, t->vertical, t->rate));
|
|
if (t->horizontal >= screen->width &&
|
|
t->vertical >= screen->height &&
|
|
(!screen->rate || t->rate <= screen->rate))
|
|
break;
|
|
}
|
|
if (i == NUM_S3_TIMINGS)
|
|
t = &s3Timings[DEFAULT_S3_TIMING];
|
|
screen->rate = t->rate;
|
|
screen->width = t->horizontal;
|
|
screen->height = t->vertical;
|
|
#if 0
|
|
s3GetClock (t, &m, &n, &r,
|
|
s3c->savage ? 511 : 127,
|
|
s3c->savage ? 127 : 31,
|
|
s3c->savage ? 4 : 3);
|
|
#else
|
|
s3GetClock (t, &m, &n, &r, 127, 31, 3);
|
|
#endif
|
|
#if 1
|
|
fprintf (stderr, "computed %d,%d,%d (%d) provided %d,%d,%d (%d)\n",
|
|
m, n, r, S3_CLOCK(m,n,r),
|
|
t->dac_m, t->dac_n, t->dac_r,
|
|
S3_CLOCK(t->dac_m, t->dac_n, t->dac_r));
|
|
#endif
|
|
/*
|
|
* Can only operate in pixel-doubled mode at 8 bits per pixel
|
|
*/
|
|
if (s3c->savage)
|
|
{
|
|
if (screen->depth > 16 && S3_CLOCK(m,n,r) > S3_MAX_CLOCK)
|
|
screen->depth = 16;
|
|
}
|
|
else
|
|
{
|
|
if (screen->depth > 8 && S3_CLOCK(m,n,r) > S3_MAX_CLOCK)
|
|
screen->depth = 8;
|
|
}
|
|
|
|
for (;;)
|
|
{
|
|
if (screen->depth >= 24)
|
|
{
|
|
screen->depth = 24;
|
|
screen->bitsPerPixel = 32;
|
|
}
|
|
else if (screen->depth >= 16)
|
|
{
|
|
screen->depth = 16;
|
|
screen->bitsPerPixel = 16;
|
|
}
|
|
else if (screen->depth >= 15)
|
|
{
|
|
screen->depth = 15;
|
|
screen->bitsPerPixel = 16;
|
|
}
|
|
else
|
|
{
|
|
screen->depth = 8;
|
|
screen->bitsPerPixel = 8;
|
|
}
|
|
|
|
/* Normalize width to supported values */
|
|
|
|
if (screen->width >= 1600)
|
|
screen->width = 1600;
|
|
else if (screen->width >= 1280)
|
|
screen->width = 1280;
|
|
else if (screen->width >= 1152)
|
|
screen->width = 1152;
|
|
else if (screen->width >= 1024)
|
|
screen->width = 1024;
|
|
else if (screen->width >= 800)
|
|
screen->width = 800;
|
|
else
|
|
screen->width = 640;
|
|
|
|
byte_width = screen->width * (screen->bitsPerPixel >> 3);
|
|
pixel_width = screen->width;
|
|
screen->pixelStride = pixel_width;
|
|
screen->byteStride = byte_width;
|
|
|
|
screen_size = byte_width * screen->height;
|
|
|
|
if (screen_size <= s3c->memory)
|
|
break;
|
|
|
|
/*
|
|
* Fix requested depth and geometry until it works
|
|
*/
|
|
if (screen->depth > 16)
|
|
screen->depth = 16;
|
|
else if (screen->depth > 8)
|
|
screen->depth = 8;
|
|
else if (screen->width > 1152)
|
|
{
|
|
screen->width = 1152;
|
|
screen->height = 900;
|
|
}
|
|
else if (screen->width > 1024)
|
|
{
|
|
screen->width = 1024;
|
|
screen->height = 768;
|
|
}
|
|
else if (screen->width > 800)
|
|
{
|
|
screen->width = 800;
|
|
screen->height = 600;
|
|
}
|
|
else if (screen->width > 640)
|
|
{
|
|
screen->width = 640;
|
|
screen->height = 480;
|
|
}
|
|
else
|
|
{
|
|
xfree (s3s);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
memory = s3c->memory - screen_size;
|
|
|
|
/*
|
|
* Stick frame buffer at start of memory
|
|
*/
|
|
screen->frameBuffer = s3c->frameBuffer;
|
|
|
|
/*
|
|
* Stick cursor at end of memory
|
|
*/
|
|
if (memory >= 2048)
|
|
{
|
|
s3s->cursor_base = s3c->frameBuffer + (s3c->memory - 2048);
|
|
memory -= 2048;
|
|
}
|
|
else
|
|
s3s->cursor_base = 0;
|
|
|
|
/*
|
|
* Use remaining memory for off-screen storage, but only use
|
|
* one piece (either right or bottom).
|
|
*/
|
|
if (memory >= byte_width * S3_TILE_SIZE)
|
|
{
|
|
s3s->offscreen = s3c->frameBuffer + screen_size;
|
|
s3s->offscreen_x = 0;
|
|
s3s->offscreen_y = screen_size / byte_width;
|
|
s3s->offscreen_width = pixel_width;
|
|
s3s->offscreen_height = memory / byte_width;
|
|
memory -= s3s->offscreen_height * byte_width;
|
|
}
|
|
else if (pixel_width - screen->width >= S3_TILE_SIZE)
|
|
{
|
|
s3s->offscreen = s3c->frameBuffer + screen->width;
|
|
s3s->offscreen_x = screen->width;
|
|
s3s->offscreen_y = 0;
|
|
s3s->offscreen_width = pixel_width - screen->width;
|
|
s3s->offscreen_height = screen->height;
|
|
}
|
|
else
|
|
s3s->offscreen = 0;
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "depth %d bits %d", screen->depth, screen->bitsPerPixel));
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "Screen size %dx%d memory %d",
|
|
screen->width, screen->height, s3c->memory));
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "frame buffer 0x%x cursor 0x%x offscreen 0x%x",
|
|
s3c->frameBuffer, s3s->cursor_base, s3s->offscreen));
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "offscreen %dx%d+%d+%d",
|
|
s3s->offscreen_width, s3s->offscreen_height,
|
|
s3s->offscreen_x, s3s->offscreen_y));
|
|
|
|
switch (screen->depth) {
|
|
case 8:
|
|
screen->visuals = ((1 << StaticGray) |
|
|
(1 << GrayScale) |
|
|
(1 << StaticColor) |
|
|
(1 << PseudoColor) |
|
|
(1 << TrueColor) |
|
|
(1 << DirectColor));
|
|
screen->blueMask = 0x00;
|
|
screen->greenMask = 0x00;
|
|
screen->redMask = 0x00;
|
|
break;
|
|
case 15:
|
|
screen->visuals = (1 << TrueColor);
|
|
screen->blueMask = 0x001f;
|
|
screen->greenMask = 0x03e0;
|
|
screen->redMask = 0x7c00;
|
|
break;
|
|
case 16:
|
|
screen->visuals = (1 << TrueColor);
|
|
screen->blueMask = 0x001f;
|
|
screen->greenMask = 0x07e0;
|
|
screen->redMask = 0xf800;
|
|
break;
|
|
case 24:
|
|
screen->visuals = (1 << TrueColor);
|
|
screen->blueMask = 0x0000ff;
|
|
screen->greenMask = 0x00ff00;
|
|
screen->redMask = 0xff0000;
|
|
break;
|
|
}
|
|
|
|
screen->driver = s3s;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
s3Preserve (KdCardInfo *card)
|
|
{
|
|
S3CardInfo *s3c = card->driver;
|
|
|
|
s3Save (s3c);
|
|
}
|
|
|
|
/*
|
|
* Enable the card for rendering. Manipulate the initial settings
|
|
* of the card here.
|
|
*/
|
|
void
|
|
s3Enable (ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdCardInfo *card = pScreenPriv->card;
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
s3CardInfo (pScreenPriv);
|
|
s3ScreenInfo (pScreenPriv);
|
|
|
|
S3Crtc crtcR, *crtc;
|
|
int hactive, hblank, hfp, hbp;
|
|
int vactive, vblank, vfp, vbp;
|
|
int hsize;
|
|
|
|
int h_total;
|
|
int h_display_end;
|
|
int h_blank_start;
|
|
int h_blank_end;
|
|
int h_sync_start;
|
|
int h_sync_end;
|
|
int h_screen_off;
|
|
int h_start_fifo_fetch;
|
|
|
|
int v_total;
|
|
int v_retrace_start;
|
|
int v_retrace_end;
|
|
int v_display_end;
|
|
int v_blank_start;
|
|
int v_blank_end;
|
|
|
|
int h_adjust;
|
|
int h_sync_extend_;
|
|
int h_blank_extend_;
|
|
int i;
|
|
CARD16 cursor_address;
|
|
S3Timing *t;
|
|
int m, n, r;
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "s3Enable"));
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "requested bpp %d current %d",
|
|
pScreenPriv->bitsPerPixel, s3c->save.crtc.bits_per_pixel));
|
|
|
|
for (i = 0; i < NUM_S3_TIMINGS; i++)
|
|
{
|
|
t = &s3Timings[i];
|
|
|
|
if (t->horizontal == screen->width &&
|
|
t->vertical == screen->height &&
|
|
t->rate <= screen->rate)
|
|
break;
|
|
}
|
|
if (i == NUM_S3_TIMINGS)
|
|
t = &s3Timings[DEFAULT_S3_TIMING];
|
|
|
|
hfp = t->hfp;
|
|
hbp = t->hbp;
|
|
hblank = t->hblank;
|
|
hactive = t->horizontal;
|
|
|
|
vfp = t->vfp;
|
|
vbp = t->vbp;
|
|
vblank = t->vblank;
|
|
vactive = t->vertical;
|
|
|
|
crtcR = s3c->save.crtc;
|
|
crtc = &crtcR;
|
|
|
|
#if 0
|
|
if (s3c->savage)
|
|
{
|
|
m = ((int) crtc->dclk_pll_m_savage_8 << 8) | crtc->dclk_pll_m0_savage_0_7;
|
|
n = (crtc->dclk_pll_n_savage_6 << 6) | crtc->dclk_pll_n_savage_0_5;
|
|
r = (crtc->dclk_pll_r_savage_2 << 2) | crtc->dclk_pll_r_savage_0_1;
|
|
fprintf (stderr, "old clock %d, %d, %d\n", m, n, r);
|
|
s3GetClock (t, &m, &n, &r, 127, 31, 3);
|
|
#if 0
|
|
s3GetClock (t, &m, &n, &r, 511, 127, 4);
|
|
crtc->dclk_pll_m0_savage_0_7 = m;
|
|
crtc->dclk_pll_m1_savage_0_7 = m;
|
|
crtc->dclk_pll_m_savage_8 = m >> 8;
|
|
crtc->dclk_pll_n_savage_0_5 = n;
|
|
crtc->dclk_pll_n_savage_6 = n >> 6;
|
|
crtc->dclk_pll_r_savage_0_1 = r;
|
|
crtc->dclk_pll_r_savage_2 = r >> 2;
|
|
crtc->dclk_pll_select_savage = 1;
|
|
#endif
|
|
fprintf (stderr, "new clock %d, %d, %d\n", m, n, r);
|
|
}
|
|
else
|
|
{
|
|
s3GetClock (t, &m, &n, &r, 127, 31, 3);
|
|
crtc->dclk_pll_m_trio = m;
|
|
crtc->dclk_pll_n_trio = n;
|
|
crtc->dclk_pll_r_trio = r;
|
|
}
|
|
|
|
if (!s3c->savage)
|
|
{
|
|
crtc->alt_refresh_count = 0x02;
|
|
crtc->enable_alt_refresh = 1;
|
|
}
|
|
else
|
|
{
|
|
crtc->alt_refresh_count = 1;
|
|
crtc->enable_alt_refresh = 0;
|
|
}
|
|
crtc->enable_256_or_more = 1;
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "memory_bus_size %d\n", crtc->memory_bus_size));
|
|
if (!s3c->savage)
|
|
crtc->memory_bus_size = 1;
|
|
|
|
if (!s3c->savage)
|
|
crtc->dclk_over_2 = 0;
|
|
crtc->dclk_invert = 0;
|
|
crtc->enable_clock_double = 0;
|
|
crtc->delay_blank = 0;
|
|
if (!s3c->savage)
|
|
crtc->extended_bios_5 = 0;
|
|
/*
|
|
* Compute character lengths for horizontal timing values
|
|
*/
|
|
switch (screen->bitsPerPixel) {
|
|
case 8:
|
|
hactive = screen->width / 8;
|
|
hblank /= 8;
|
|
hfp /= 8;
|
|
hbp /= 8;
|
|
h_screen_off = hactive;
|
|
crtc->pixel_length = 0;
|
|
crtc->color_mode = 0;
|
|
/*
|
|
* Set up for double-pixel mode, switch color modes,
|
|
* divide the dclk and delay h blank by 2 dclks
|
|
*/
|
|
if (S3_CLOCK(m, n, r) > S3_MAX_CLOCK)
|
|
{
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "S3 clock %g > 80MHz, using pixel double mode",
|
|
S3_CLOCK(crtc->dclk_pll_m, crtc->dclk_pll_n,
|
|
crtc->dclk_pll_r)));
|
|
crtc->color_mode = 1;
|
|
crtc->dclk_over_2 = 1;
|
|
crtc->enable_clock_double = 1;
|
|
crtc->delay_blank = 2;
|
|
crtc->extended_bios_5 = 2;
|
|
}
|
|
h_adjust = 1;
|
|
break;
|
|
case 16:
|
|
if (s3c->savage)
|
|
{
|
|
hactive = screen->width / 4;
|
|
hblank /= 4;
|
|
hfp /= 4;
|
|
hbp /= 4;
|
|
h_screen_off = hactive * 2;
|
|
crtc->pixel_length = 1;
|
|
if (S3_CLOCK(m,n,r) > S3_MAX_CLOCK)
|
|
{
|
|
if (crtc->depth == 15)
|
|
crtc->color_mode = 3;
|
|
else
|
|
crtc->color_mode = 5;
|
|
crtc->dclk_over_2 = 1;
|
|
crtc->enable_clock_double = 1;
|
|
crtc->delay_blank = 2;
|
|
}
|
|
else
|
|
{
|
|
if (crtc->depth == 15)
|
|
crtc->color_mode = 2;
|
|
else
|
|
crtc->color_mode = 4;
|
|
crtc->dclk_over_2 = 0;
|
|
crtc->enable_clock_double = 0;
|
|
}
|
|
h_adjust = 1;
|
|
}
|
|
else
|
|
{
|
|
hactive = screen->width / 4;
|
|
hblank /= 4;
|
|
hfp /= 4;
|
|
hbp /= 4;
|
|
h_screen_off = hactive;
|
|
crtc->pixel_length = 1;
|
|
crtc->extended_bios_5 = 2;
|
|
if (crtc->depth == 15)
|
|
crtc->color_mode = 3;
|
|
else
|
|
crtc->color_mode = 5;
|
|
h_adjust = 2;
|
|
}
|
|
break;
|
|
case 32:
|
|
hactive = screen->width / 8;
|
|
hblank /= 8;
|
|
hfp /= 8;
|
|
hbp /= 8;
|
|
h_screen_off = hactive * 4;
|
|
crtc->pixel_length = 3;
|
|
crtc->color_mode = 0xd;
|
|
h_adjust = 1;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* X server starts frame buffer at top of memory
|
|
*/
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "Old start address 0x%x\n",
|
|
crtc_start_address (crtc)));
|
|
crtc_set_start_address (crtc, 0);
|
|
|
|
#if 0
|
|
/*
|
|
* Compute horizontal register values from timings
|
|
*/
|
|
h_total = hactive + hblank - 5;
|
|
h_display_end = hactive - 1;
|
|
h_blank_start = h_display_end;
|
|
h_blank_end = h_blank_start + hblank - h_adjust;
|
|
h_sync_start = hactive + hfp + h_adjust;
|
|
h_sync_end = h_sync_start + hblank - hbp - hfp;
|
|
h_start_fifo_fetch = h_total - 5;
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "blank_end 0x%x sync_end 0x%x sync_start 0x%x\n",
|
|
h_blank_end, h_sync_end, h_sync_start));
|
|
|
|
if (h_blank_end - h_blank_start > 0x40)
|
|
h_blank_extend_ = 1;
|
|
else
|
|
h_blank_extend_ = 0;
|
|
|
|
if (h_sync_end - h_sync_start > 0x20)
|
|
h_sync_extend_ = 1;
|
|
else
|
|
h_sync_extend_ = 0;
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "blank_end 0x%x sync_end 0x%x extend %d\n",
|
|
h_blank_end, h_sync_end, h_sync_extend_));
|
|
|
|
crtc_set_h_total(crtc, h_total);
|
|
crtc_set_h_display_end (crtc, h_display_end);
|
|
crtc_set_h_blank_start (crtc, h_blank_start);
|
|
crtc_set_h_blank_end (crtc, h_blank_end);
|
|
crtc_set_h_sync_start (crtc, h_sync_start);
|
|
crtc_set_h_sync_end (crtc, h_sync_end);
|
|
crtc_set_screen_off (crtc, h_screen_off);
|
|
crtc_set_h_start_fifo_fetch (crtc, h_start_fifo_fetch);
|
|
crtc->h_sync_extend = h_sync_extend_;
|
|
crtc->h_blank_extend = h_blank_extend_;
|
|
|
|
|
|
v_total = vactive + vblank - 2;
|
|
v_retrace_start = vactive + vfp - 1;
|
|
v_retrace_end = v_retrace_start + vblank - vbp - 1;
|
|
v_display_end = vactive - 1;
|
|
v_blank_start = vactive - 1;
|
|
v_blank_end = v_blank_start + vblank - 1;
|
|
|
|
crtc_set_v_total(crtc, v_total);
|
|
crtc_set_v_retrace_start (crtc, v_retrace_start);
|
|
crtc->v_retrace_end_0_3 = v_retrace_end;
|
|
crtc_set_v_display_end (crtc, v_display_end);
|
|
crtc_set_v_blank_start (crtc, v_blank_start);
|
|
crtc->v_blank_end_0_7 = v_blank_end;
|
|
#endif
|
|
|
|
/*
|
|
* Set cursor
|
|
*/
|
|
if (!screen->softCursor)
|
|
{
|
|
cursor_address = (s3s->cursor_base - screen->frameBuffer) / 1024;
|
|
|
|
crtc->cursor_address_0_7 = cursor_address;
|
|
crtc->cursor_address_8_15 = cursor_address >> 8;
|
|
crtc->hardware_cursor_ms_x11 = 0;
|
|
crtc->hardware_cursor_enable = 1;
|
|
}
|
|
else
|
|
crtc->hardware_cursor_enable = 0;
|
|
|
|
/*
|
|
* Set accelerator
|
|
*/
|
|
switch (screen->width) {
|
|
case 640: crtc_set_ge_screen_width(crtc,1); break;
|
|
case 800: crtc_set_ge_screen_width(crtc,2); break;
|
|
case 1024: crtc_set_ge_screen_width(crtc,0); break;
|
|
case 1152: crtc_set_ge_screen_width(crtc,4); break;
|
|
case 1280: crtc_set_ge_screen_width(crtc,3); break;
|
|
case 1600: crtc_set_ge_screen_width(crtc,6); break;
|
|
}
|
|
|
|
/*
|
|
* Set depth values
|
|
*/
|
|
crtc->bits_per_pixel = screen->bitsPerPixel;
|
|
crtc->depth = screen->depth;
|
|
|
|
crtc->l_parm_0_7 = screen->width / 4; /* Undocumented. */
|
|
|
|
crtc->disable_v_retrace_int = 1; /* don't let retrace interrupt */
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "new h total %d display_end %d",
|
|
crtc_h_total(crtc),
|
|
crtc_h_display_end(crtc)));
|
|
DRAW_DEBUG ((DEBUG_S3INIT, " sync_start %d sync_end %d (%d)",
|
|
crtc_h_sync_start(crtc),
|
|
crtc_h_sync_end(crtc), h_sync_end));
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, " blank_start %d blank_end %d",
|
|
crtc_h_blank_start(crtc),
|
|
crtc_h_blank_end(crtc)));
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, " screen_off %d start_fifo %d",
|
|
crtc_screen_off(crtc), crtc_h_start_fifo_fetch(crtc)));
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, " active %d blank %d fp %d bp %d",
|
|
hactive, hblank, hfp, hbp));
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, "new v total %d display_end %d",
|
|
crtc_v_total(crtc),
|
|
crtc_v_display_end(crtc)));
|
|
DRAW_DEBUG ((DEBUG_S3INIT, " retrace_start %d retrace_end %d (%d)",
|
|
crtc_v_retrace_start(crtc),
|
|
crtc->v_retrace_end,
|
|
v_retrace_end));
|
|
DRAW_DEBUG ((DEBUG_S3INIT, " blank_start %d blank_end %d",
|
|
crtc_v_blank_start(crtc),
|
|
crtc->v_blank_end_0_7));
|
|
|
|
DRAW_DEBUG ((DEBUG_S3INIT, " active %d blank %d fp %d bp %d",
|
|
vactive, vblank, vfp, vbp));
|
|
|
|
/*
|
|
* Set DPMS to normal
|
|
*/
|
|
crtc->hsync_control = 0;
|
|
crtc->vsync_control = 0;
|
|
|
|
LockS3 (s3c);
|
|
_s3SetDepth (s3c->s3, crtc);
|
|
UnlockS3 (s3c);
|
|
}
|
|
|
|
void
|
|
s3Disable (ScreenPtr pScreen)
|
|
{
|
|
}
|
|
|
|
void
|
|
s3Restore (KdCardInfo *card)
|
|
{
|
|
S3CardInfo *s3c = card->driver;
|
|
|
|
s3Reset (s3c);
|
|
}
|
|
|
|
void
|
|
_s3SetSync (S3CardInfo *s3c, int hsync, int vsync)
|
|
{
|
|
/* this abuses the macros defined to access the crtc structure */
|
|
union extended_sequencer_d_u _extended_sequencer_d_u;
|
|
S3Ptr s3 = s3c->s3;
|
|
|
|
extended_sequencer_d = s3c->save.crtc.extended_sequencer_d;
|
|
hsync_control = hsync;
|
|
vsync_control = vsync;
|
|
PutSrtc (s3, 0x0d, extended_sequencer_d);
|
|
}
|
|
|
|
Bool
|
|
s3DPMS (ScreenPtr pScreen, int mode)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
s3CardInfo(pScreenPriv);
|
|
|
|
switch (mode) {
|
|
case KD_DPMS_NORMAL:
|
|
_s3SetSync (s3c, 0, 0);
|
|
_s3SetBlank (s3c->s3, FALSE);
|
|
break;
|
|
case KD_DPMS_STANDBY:
|
|
_s3SetBlank (s3c->s3, TRUE);
|
|
_s3SetSync (s3c, 1, 0);
|
|
break;
|
|
case KD_DPMS_SUSPEND:
|
|
_s3SetBlank (s3c->s3, TRUE);
|
|
_s3SetSync (s3c, 0, 1);
|
|
break;
|
|
case KD_DPMS_POWERDOWN:
|
|
_s3SetBlank (s3c->s3, TRUE);
|
|
_s3SetSync (s3c, 1, 1);
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
s3ScreenFini (KdScreenInfo *screen)
|
|
{
|
|
S3ScreenInfo *s3s = (S3ScreenInfo *) screen->driver;
|
|
|
|
xfree (s3s);
|
|
screen->driver = 0;
|
|
}
|
|
|
|
void
|
|
s3CardFini (KdCardInfo *card)
|
|
{
|
|
S3CardInfo *s3c = (S3CardInfo *) card->driver;
|
|
|
|
KdUnmapDevice (s3c->frameBuffer, s3c->memory);
|
|
KdUnmapDevice (s3c->registers, sizeof (S3) + PACKED_OFFSET);
|
|
/* DeleteCriticalSection (&s3c->lock); */
|
|
xfree (s3c);
|
|
card->driver = 0;
|
|
}
|
|
|
|
KdCardFuncs s3Funcs = {
|
|
s3CardInit,
|
|
s3ScreenInit,
|
|
s3Preserve,
|
|
s3Enable,
|
|
s3DPMS,
|
|
s3Disable,
|
|
s3Restore,
|
|
s3ScreenFini,
|
|
s3CardFini,
|
|
s3CursorInit,
|
|
s3CursorEnable,
|
|
s3CursorDisable,
|
|
s3CursorFini,
|
|
s3RecolorCursor,
|
|
s3DrawInit,
|
|
s3DrawEnable,
|
|
s3DrawDisable,
|
|
s3DrawFini,
|
|
s3GetColors,
|
|
s3PutColors,
|
|
};
|