1f29dbc25Smrg/* Copyright (c) 2005 Advanced Micro Devices, Inc.
2f29dbc25Smrg *
3f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy
4f29dbc25Smrg * of this software and associated documentation files (the "Software"), to
5f29dbc25Smrg * deal in the Software without restriction, including without limitation the
6f29dbc25Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7f29dbc25Smrg * sell copies of the Software, and to permit persons to whom the Software is
8f29dbc25Smrg * furnished to do so, subject to the following conditions:
9f29dbc25Smrg *
10f29dbc25Smrg * The above copyright notice and this permission notice shall be included in
11f29dbc25Smrg * all copies or substantial portions of the Software.
12f29dbc25Smrg *
13f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19f29dbc25Smrg * IN THE SOFTWARE.
20f29dbc25Smrg *
21f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
22f29dbc25Smrg * contributors may be used to endorse or promote products derived from this
23f29dbc25Smrg * software without specific prior written permission.
24f29dbc25Smrg * */
25f29dbc25Smrg
26f29dbc25Smrg/*
27f29dbc25Smrg * This file contains routines to set modes using the VGA registers.
28f29dbc25Smrg * Since this file is for the first generation graphics unit, it interfaces
29f29dbc25Smrg * to SoftVGA registers.  It works for both VSA1 and VSA2.
30f29dbc25Smrg * */
31f29dbc25Smrg
32f29dbc25Smrg/* SoftVGA Extended CRTC register indices and bit definitions */
33f29dbc25Smrg
34f29dbc25Smrg#define CRTC_EXTENDED_REGISTER_LOCK		0x30
35f29dbc25Smrg#define CRTC_MODE_SWITCH_CONTROL		0x3F
36f29dbc25Smrg
37f29dbc25Smrg/* BIT DEFINITIONS */
38f29dbc25Smrg
39f29dbc25Smrg#define CRTC_BIT_16BPP					0x01
40f29dbc25Smrg#define CRTC_BIT_555					0x02
41f29dbc25Smrg
42f29dbc25Smrg/* LOCAL ROUTINE DEFINITIONS */
43f29dbc25Smrg
44f29dbc25Smrgint gu1_detect_vsa2(void);
45f29dbc25Smrg
46f29dbc25Smrg/*---------------------------------*/
47f29dbc25Smrg/*  MODE TABLES FOR VGA REGISTERS  */
48f29dbc25Smrg/*---------------------------------*/
49f29dbc25Smrg
50f29dbc25Smrg/* FOR SoftVGA, the CRTC_EXTENDED_ADDRESS_CONTROL (0x43) is always equal to
51f29dbc25Smrg * 0x03 for a packed linear frame buffer organization.  The
52f29dbc25Smrg * CRTC_EXTENDED_DAC_CONTROL (0x4B) is always equal to 0x03 to work with
53f29dbc25Smrg * older versions of VSA1 (that needed to specify 8 or 16 bit bus to an
54f29dbc25Smrg * external RAMDAC.  This is not used in VSA2.  The clock frequency is
55f29dbc25Smrg * specified in register 0x4D if clock control (0x4C) is set to 0x80.
56f29dbc25Smrg * Higher resolutions (1280x1024) use the CRTC_EXTENDED_VERTICAL_TIMING
57f29dbc25Smrg * register (index 0x41).
58f29dbc25Smrg */
59f29dbc25Smrg
60f29dbc25Smrggfx_vga_struct gfx_vga_modes[] = {
61f29dbc25Smrg/*--------------------------------------------------------------------------*/
62f29dbc25Smrg    {
6304007ebaSmrg     640, 480, 60,              /* 640x480                                                              */
6404007ebaSmrg     25,                        /* 25 MHz clock = 60 Hz refresh rate    */
6504007ebaSmrg     0xE3,                      /* miscOutput register                                  */
6604007ebaSmrg     {
6704007ebaSmrg      0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E,
6804007ebaSmrg      /* standard CRTC                                                */
6904007ebaSmrg      0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7004007ebaSmrg      0xEA, 0x0C, 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3, 0xFF},
7104007ebaSmrg     {
7204007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
7304007ebaSmrg      /* extended CRTC                                                */
7404007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00}
7504007ebaSmrg     },
76f29dbc25Smrg/*--------------------------------------------------------------------------*/
77f29dbc25Smrg    {
7804007ebaSmrg     640, 480, 72,              /* 640x480 */
7904007ebaSmrg     29,                        /* 29 MHz clock = 72 Hz refresh rate */
8004007ebaSmrg     0xE3,                      /* miscOutput register */
8104007ebaSmrg     {
8204007ebaSmrg      0x63, 0x4f, 0x50, 0x86, 0x55, 0x99, 0x06, 0x3e,
8304007ebaSmrg      /* standard CRTC */
8404007ebaSmrg      0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8504007ebaSmrg      0xe9, 0x0c, 0xdf, 0x00, 0x00, 0xe7, 0x00, 0xe3, 0xff},
8604007ebaSmrg     {
8704007ebaSmrg      0x6D, 0x00, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00,
8804007ebaSmrg      /* extended CRTC */
8904007ebaSmrg      0x00, 0x00, 0x01, 0x08, 0x80, 0x1F, 0x00, 0x4B}
9004007ebaSmrg     },
91f29dbc25Smrg/*--------------------------------------------------------------------------*/
92f29dbc25Smrg    {
9304007ebaSmrg     640, 480, 75,              /* 640x480 */
9404007ebaSmrg     31,
9504007ebaSmrg     /* 31.5 MHz clock = 75 Hz refresh rate */
9604007ebaSmrg     0xE3,                      /* miscOutput register */
9704007ebaSmrg     {
9804007ebaSmrg      0x64, 0x4F, 0x4F, 0x88, 0x54, 0x9B, 0xF2, 0x1F,
9904007ebaSmrg      /* standard CRTC */
10004007ebaSmrg      0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10104007ebaSmrg      0xE1, 0x04, 0xDF, 0x50, 0x00, 0xDF, 0xF3, 0xE3, 0xFF},
10204007ebaSmrg     {
10304007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
10404007ebaSmrg      /* extended CRTC */
10504007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x80, 0x1F, 0x00, 0x00}
10604007ebaSmrg     },
107f29dbc25Smrg/*--------------------------------------------------------------------------*/
108f29dbc25Smrg    {
10904007ebaSmrg     800, 600, 60,              /* 800x600 */
11004007ebaSmrg     40,                        /* 40 MHz clock = 60 Hz refresh rate */
11104007ebaSmrg     0x23,                      /* miscOutput register */
11204007ebaSmrg     {
11304007ebaSmrg      0x7F, 0x63, 0x64, 0x82, 0x6B, 0x1B, 0x72, 0xF0,
11404007ebaSmrg      /* standard CRTC */
11504007ebaSmrg      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11604007ebaSmrg      0x59, 0x0D, 0x57, 0x64, 0x00, 0x57, 0x73, 0xE3, 0xFF},
11704007ebaSmrg     {
11804007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
11904007ebaSmrg      /* extended CRTC */
12004007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x80, 0x28, 0x00, 0x00}
12104007ebaSmrg     },
122f29dbc25Smrg/*--------------------------------------------------------------------------*/
123f29dbc25Smrg    {
12404007ebaSmrg     800, 600, 72,              /* 800x600 */
12504007ebaSmrg     47,                        /* 47 MHz clock = 72 Hz refresh rate */
12604007ebaSmrg     0x2B,                      /* miscOutput register */
12704007ebaSmrg     {
12804007ebaSmrg      0x7D, 0x63, 0x63, 0x81, 0x6D, 0x1B, 0x98, 0xF0,
12904007ebaSmrg      /* standard CRTC */
13004007ebaSmrg      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13104007ebaSmrg      0x7D, 0x03, 0x57, 0x00, 0x00, 0x57, 0x9A, 0xE3, 0xFF},
13204007ebaSmrg     {
13304007ebaSmrg      0x6F, 0x00, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00,
13404007ebaSmrg      /* extended CRTC */
13504007ebaSmrg      0x00, 0x00, 0x01, 0x08, 0x80, 0x32, 0x00, 0x4B}
13604007ebaSmrg     },
137f29dbc25Smrg/*--------------------------------------------------------------------------*/
138f29dbc25Smrg    {
13904007ebaSmrg     800, 600, 75,              /* 800x600 */
14004007ebaSmrg     49,
14104007ebaSmrg     /* 49.5 MHz clock = 75 Hz refresh rate */
14204007ebaSmrg     0x23,                      /* miscOutput register */
14304007ebaSmrg     {
14404007ebaSmrg      0x7F, 0x63, 0x63, 0x83, 0x68, 0x11, 0x6F, 0xF0,
14504007ebaSmrg      /* standard CRTC */
14604007ebaSmrg      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14704007ebaSmrg      0x59, 0x1C, 0x57, 0x64, 0x00, 0x57, 0x70, 0xE3, 0xFF},
14804007ebaSmrg     {
14904007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
15004007ebaSmrg      /* extended CRTC */
15104007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x80, 0x31, 0x00, 0x00}
15204007ebaSmrg     },
153f29dbc25Smrg/*--------------------------------------------------------------------------*/
154f29dbc25Smrg    {
15504007ebaSmrg     1024, 768, 60,             /* 1024x768 */
15604007ebaSmrg     65,                        /* 65 MHz clock = 60 Hz refresh rate */
15704007ebaSmrg     0xE3,                      /* miscOutput register */
15804007ebaSmrg     {
15904007ebaSmrg      0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xF5,
16004007ebaSmrg      /* standard CRTC */
16104007ebaSmrg      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
16204007ebaSmrg      0x04, 0x0A, 0xFF, 0x80, 0x00, 0xFF, 0x25, 0xE3, 0xFF},
16304007ebaSmrg     {
16404007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
16504007ebaSmrg      /* extended CRTC */
16604007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x80, 0x41, 0x00, 0x00}
16704007ebaSmrg     },
168f29dbc25Smrg/*--------------------------------------------------------------------------*/
169f29dbc25Smrg    {
17004007ebaSmrg     1024, 768, 70,             /* 1024x768 */
17104007ebaSmrg     76,                        /* 76 MHz clock = 70 Hz refresh rate */
17204007ebaSmrg     0x2B,                      /* miscOutput register */
17304007ebaSmrg     {
17404007ebaSmrg      0xA1, 0x7F, 0x7F, 0x85, 0x85, 0x95, 0x24, 0xF5,
17504007ebaSmrg      /* standard CRTC */
17604007ebaSmrg      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17704007ebaSmrg      0x03, 0x09, 0xFF, 0x00, 0x00, 0xFF, 0x26, 0xE3, 0xFF},
17804007ebaSmrg     {
17904007ebaSmrg      0x62, 0x00, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00,
18004007ebaSmrg      /* extended CRTC */
18104007ebaSmrg      0x00, 0x00, 0x01, 0x02, 0x80, 0x4B, 0x00, 0x4B}
18204007ebaSmrg     },
183f29dbc25Smrg/*--------------------------------------------------------------------------*/
184f29dbc25Smrg    {
18504007ebaSmrg     1024, 768, 75,             /* 1024x768 */
18604007ebaSmrg     79,                        /* 79 MHz clock = 75 Hz refresh rate */
18704007ebaSmrg     0xE3,                      /* miscOutput register */
18804007ebaSmrg     {
18904007ebaSmrg      0x9F, 0x7F, 0x7F, 0x83, 0x84, 0x8F, 0x1E, 0xF5,
19004007ebaSmrg      /* standard CRTC */
19104007ebaSmrg      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19204007ebaSmrg      0x01, 0x04, 0xFF, 0x80, 0x00, 0xFF, 0x1F, 0xE3, 0xFF},
19304007ebaSmrg     {
19404007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
19504007ebaSmrg      /* extended CRTC */
19604007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x80, 0x4F, 0x00, 0x00}
19704007ebaSmrg     },
198f29dbc25Smrg/*--------------------------------------------------------------------------*/
199f29dbc25Smrg    {
20004007ebaSmrg     1280, 1024, 60,            /* 1280x1024 */
20104007ebaSmrg     108,
20204007ebaSmrg     /* 108 MHz clock = 60 Hz refresh rate */
20304007ebaSmrg     0x23,                      /* miscOutput register */
20404007ebaSmrg     {
20504007ebaSmrg      0xCF, 0x9F, 0xA0, 0x92, 0xAA, 0x19, 0x28, 0x52,
20604007ebaSmrg      /* standard CRTC */
20704007ebaSmrg      0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20804007ebaSmrg      0x01, 0x04, 0xFF, 0xA0, 0x00, 0x00, 0x29, 0xE3, 0xFF},
20904007ebaSmrg     {
21004007ebaSmrg      0x00, 0x51, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
21104007ebaSmrg      /* extended CRTC */
21204007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x80, 0x6C, 0x00, 0x00}
21304007ebaSmrg     },
214f29dbc25Smrg/*--------------------------------------------------------------------------*/
215f29dbc25Smrg    {
21604007ebaSmrg     1280, 1024, 75,            /* 1280x1024 */
21704007ebaSmrg     135,
21804007ebaSmrg     /* 135 MHz clock = 75 Hz refresh rate */
21904007ebaSmrg     0x23,                      /* miscOutput register */
22004007ebaSmrg     {
22104007ebaSmrg      0xCE, 0x9F, 0x9F, 0x92, 0xA4, 0x15, 0x28, 0x52,
22204007ebaSmrg      /* standard CRTC */
22304007ebaSmrg      0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22404007ebaSmrg      0x01, 0x04, 0xFF, 0xA0, 0x00, 0x00, 0x29, 0xE3, 0xFF},
22504007ebaSmrg     {
22604007ebaSmrg      0x00, 0x51, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
22704007ebaSmrg      /* extended CRTC */
22804007ebaSmrg      0x00, 0x00, 0x00, 0x03, 0x80, 0x87, 0x00, 0x00}
22904007ebaSmrg     },
230f29dbc25Smrg/*--------------------------------------------------------------------------*/
231f29dbc25Smrg    {
23204007ebaSmrg     1280, 1024, 85,            /* 1280x1024 */
23304007ebaSmrg     159,
23404007ebaSmrg     /* 159 MHz clock = 85 Hz refresh rate */
23504007ebaSmrg     0x2B,                      /* miscOutput register */
23604007ebaSmrg     {
23704007ebaSmrg      0xD3, 0x9F, 0xA0, 0x98, 0xA8, 0x9C, 0x2E, 0x5A,
23804007ebaSmrg      /* standard CRTC */
23904007ebaSmrg      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24004007ebaSmrg      0x01, 0x04, 0xFF, 0x00, 0x00, 0xFF, 0x30, 0xE3, 0xFF},
24104007ebaSmrg     {
24204007ebaSmrg      0x6B, 0x41, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00,
24304007ebaSmrg      /* extended CRTC */
24404007ebaSmrg      0x00, 0x00, 0x01, 0x00, 0x80, 0x9D, 0x00, 0x4B}
24504007ebaSmrg     },
246f29dbc25Smrg/*--------------------------------------------------------------------------*/
247f29dbc25Smrg};
248f29dbc25Smrg
249f29dbc25Smrg#define GFX_VGA_MODES sizeof(gfx_vga_modes)/sizeof(gfx_vga_struct)
250f29dbc25Smrg
251f29dbc25Smrg/*----------------------------------------------------------------------------
252f29dbc25Smrg * gfx_get_softvga_active
253f29dbc25Smrg *
254f29dbc25Smrg * This returns the active status of SoftVGA
255f29dbc25Smrg *----------------------------------------------------------------------------
256f29dbc25Smrg */
257f29dbc25Smrgint
258f29dbc25Smrggfx_get_softvga_active(void)
259f29dbc25Smrg{
260f29dbc25Smrg    unsigned short crtcindex, crtcdata;
261f29dbc25Smrg
262f29dbc25Smrg    if (gu1_detect_vsa2())
263f29dbc25Smrg        return (gfx_get_vsa2_softvga_enable());
264f29dbc25Smrg
265f29dbc25Smrg    crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
266f29dbc25Smrg    crtcdata = crtcindex + 1;
267f29dbc25Smrg
268f29dbc25Smrg    OUTB(crtcindex, CRTC_MODE_SWITCH_CONTROL);
269f29dbc25Smrg    return (INB(crtcdata) & 0x1);
270f29dbc25Smrg}
271f29dbc25Smrg
272f29dbc25Smrg/*----------------------------------------------------------------------------
273f29dbc25Smrg * gfx_vga_test_pci
274f29dbc25Smrg *
275f29dbc25Smrg * This routine looks for the VGA PCI header.  It checks to see that bit 1
276f29dbc25Smrg * of the command register is writable to know that SoftVGA is trapping
277f29dbc25Smrg * the PCI config cuscles.  If SoftVGA is not emulating the header, the
278f29dbc25Smrg * hardware will still respond with the proper device ID, etc.
279f29dbc25Smrg *
280f29dbc25Smrg * We need to know that SoftVGA is really there so that we can set the
281f29dbc25Smrg * command register and have the proper effect (enable trapping of VGA).
282f29dbc25Smrg * Otherwise, if we enable VGA via the PCI header, trapping really won't be
283f29dbc25Smrg * enabled and the VGA register writes will go out to the external card.
284f29dbc25Smrg *----------------------------------------------------------------------------
285f29dbc25Smrg */
286f29dbc25Smrgint
287f29dbc25Smrggfx_vga_test_pci(void)
288f29dbc25Smrg{
289f29dbc25Smrg    int softvga = 1;
290f29dbc25Smrg    unsigned long value;
291f29dbc25Smrg
292f29dbc25Smrg    value = gfx_pci_config_read(0x80009400);
293f29dbc25Smrg    if ((value & 0x0000FFFF) != 0x1078)
294f29dbc25Smrg        softvga = 0;
295f29dbc25Smrg    else {
296f29dbc25Smrg        value = gfx_pci_config_read(0x80009404);
297f29dbc25Smrg        gfx_pci_config_write(0x80009404, value | 0x02);
298f29dbc25Smrg        if (!(gfx_pci_config_read(0x80009404) & 0x02))
299f29dbc25Smrg            softvga = 0;
300f29dbc25Smrg        gfx_pci_config_write(0x80009404, value);
301f29dbc25Smrg    }
302f29dbc25Smrg    return (softvga);
303f29dbc25Smrg}
304f29dbc25Smrg
305f29dbc25Smrg/*----------------------------------------------------------------------------
306f29dbc25Smrg * gfx_vga_get_pci_command
307f29dbc25Smrg *
308f29dbc25Smrg * This routine returns the value of the PCI command register.
309f29dbc25Smrg *----------------------------------------------------------------------------
310f29dbc25Smrg */
311f29dbc25Smrgunsigned char
312f29dbc25Smrggfx_vga_get_pci_command(void)
313f29dbc25Smrg{
314f29dbc25Smrg    unsigned long value;
315f29dbc25Smrg
316f29dbc25Smrg    value = gfx_pci_config_read(0x80009404);
31704007ebaSmrg    return ((unsigned char) value);
318f29dbc25Smrg}
319f29dbc25Smrg
320f29dbc25Smrg/*----------------------------------------------------------------------------
321f29dbc25Smrg * gfx_vga_set_pci_command
322f29dbc25Smrg *
323f29dbc25Smrg * This routine writes the value of the PCI command register.  It is used
324f29dbc25Smrg * to enable or disable SoftVGA.
325f29dbc25Smrg *
326f29dbc25Smrg *    Bit 0: Enable VGA IO
327f29dbc25Smrg *    Bit 1: Enable VGA memory
328f29dbc25Smrg *----------------------------------------------------------------------------
329f29dbc25Smrg */
330f29dbc25Smrgint
331f29dbc25Smrggfx_vga_set_pci_command(unsigned char command)
332f29dbc25Smrg{
333f29dbc25Smrg    unsigned long value;
334f29dbc25Smrg
335f29dbc25Smrg    value = gfx_pci_config_read(0x80009404) & 0xFFFFFF00;
33604007ebaSmrg    value |= (unsigned long) command;
337f29dbc25Smrg    gfx_pci_config_write(0x80009404, value);
338f29dbc25Smrg    return (GFX_STATUS_OK);
339f29dbc25Smrg}
340f29dbc25Smrg
341f29dbc25Smrg/*----------------------------------------------------------------------------
342f29dbc25Smrg * gfx_vga_seq_reset
343f29dbc25Smrg *
344f29dbc25Smrg * This routine enables or disables SoftVGA.  It is used to make SoftVGA
345f29dbc25Smrg * "be quiet" and not interfere with any of the direct hardware access from
346f29dbc25Smrg * Durango.  For VSA1, the sequencer is reset to stop text redraws.  VSA2 may
347f29dbc25Smrg * provide a better way to have SoftVGA sit in the background.
348f29dbc25Smrg *----------------------------------------------------------------------------
349f29dbc25Smrg */
350f29dbc25Smrgint
351f29dbc25Smrggfx_vga_seq_reset(int reset)
352f29dbc25Smrg{
353f29dbc25Smrg    OUTB(0x3C4, 0);
35404007ebaSmrg    OUTB(0x3C5, (unsigned char) (reset ? 0x00 : 0x03));
355f29dbc25Smrg    return (GFX_STATUS_OK);
356f29dbc25Smrg}
357f29dbc25Smrg
358f29dbc25Smrg/*----------------------------------------------------------------------------
359f29dbc25Smrg * gfx_vga_set_graphics_bits
360f29dbc25Smrg *
361f29dbc25Smrg * This routine sets the standard VGA sequencer, graphics controller, and
362f29dbc25Smrg * attribute registers to appropriate values for a graphics mode (packed,
363f29dbc25Smrg * 8 BPP or greater).  This is also known as "VESA" modes.  The timings for
364f29dbc25Smrg * a particular mode are handled by the CRTC registers, which are set by
365f29dbc25Smrg * the "gfx_vga_restore" routine.   Most OSs that use VGA to set modes save
366f29dbc25Smrg * and restore the standard VGA registers themselves, which is why these
367f29dbc25Smrg * registers are not part of the save/restore paradigm.
368f29dbc25Smrg *----------------------------------------------------------------------------
369f29dbc25Smrg */
370f29dbc25Smrgint
371f29dbc25Smrggfx_vga_set_graphics_bits(void)
372f29dbc25Smrg{
373f29dbc25Smrg    /* SET GRAPHICS BIT IN GRAPHICS CONTROLLER REG 0x06 */
374f29dbc25Smrg
375f29dbc25Smrg    OUTB(0x3CE, 0x06);
376f29dbc25Smrg    OUTB(0x3CF, 0x01);
377f29dbc25Smrg
378f29dbc25Smrg    /* SET GRAPHICS BIT IN ATTRIBUTE CONTROLLER REG 0x10 */
379f29dbc25Smrg
38004007ebaSmrg    INB(0x3BA);                 /* Reset flip-flop */
381f29dbc25Smrg    INB(0x3DA);
382f29dbc25Smrg    OUTB(0x3C0, 0x10);
383f29dbc25Smrg    OUTB(0x3C0, 0x01);
384f29dbc25Smrg    return (GFX_STATUS_OK);
385f29dbc25Smrg}
386f29dbc25Smrg
387f29dbc25Smrg/*----------------------------------------------------------------------------
388f29dbc25Smrg * gfx_vga_mode
389f29dbc25Smrg *
390f29dbc25Smrg * This routine searches the VGA mode table for a match of the specified
391f29dbc25Smrg * mode and then fills in the VGA structure with the associated VGA register
392f29dbc25Smrg * values.  The "gfx_vga_restore" routine can then be called to actually
393f29dbc25Smrg * set the mode.
394f29dbc25Smrg *----------------------------------------------------------------------------
395f29dbc25Smrg */
396f29dbc25Smrgint
397f29dbc25Smrggfx_vga_mode(gfx_vga_struct * vga, int xres, int yres, int bpp, int hz)
398f29dbc25Smrg{
399f29dbc25Smrg    unsigned int i;
400f29dbc25Smrg    unsigned short pitch;
401f29dbc25Smrg
402f29dbc25Smrg    for (i = 0; i < GFX_VGA_MODES; i++) {
403f29dbc25Smrg        if ((gfx_vga_modes[i].xsize == xres) &&
404f29dbc25Smrg            (gfx_vga_modes[i].ysize == yres) && (gfx_vga_modes[i].hz == hz)) {
405f29dbc25Smrg            /* COPY ENTIRE STRUCTURE FROM THE TABLE */
406f29dbc25Smrg
407f29dbc25Smrg            *vga = gfx_vga_modes[i];
408f29dbc25Smrg
409f29dbc25Smrg            /* SET PITCH TO 1K OR 2K */
410f29dbc25Smrg            /* CRTC_EXTENDED_OFFSET index is 0x45, so offset = 0x05 */
411f29dbc25Smrg
41204007ebaSmrg            pitch = (unsigned short) xres;
413f29dbc25Smrg            if (bpp > 8)
414f29dbc25Smrg                pitch <<= 1;
415f29dbc25Smrg            if (pitch <= 1024)
416f29dbc25Smrg                pitch = 1024 >> 3;
417f29dbc25Smrg            else
418f29dbc25Smrg                pitch = 2048 >> 3;
41904007ebaSmrg            vga->stdCRTCregs[0x13] = (unsigned char) pitch;
42004007ebaSmrg            vga->extCRTCregs[0x05] = (unsigned char) ((pitch >> 8) & 0x03);
421f29dbc25Smrg
422f29dbc25Smrg            /* SET PROPER COLOR DEPTH VALUE */
423f29dbc25Smrg            /* CRTC_EXTENDED_COLOR_CONTROL index is 0x46, so offset = 0x06 */
424f29dbc25Smrg
425f29dbc25Smrg            switch (bpp) {
426f29dbc25Smrg            case 15:
427f29dbc25Smrg                vga->extCRTCregs[0x06] = CRTC_BIT_16BPP | CRTC_BIT_555;
428f29dbc25Smrg                break;
429f29dbc25Smrg            case 16:
430f29dbc25Smrg                vga->extCRTCregs[0x06] = CRTC_BIT_16BPP;
431f29dbc25Smrg                break;
432f29dbc25Smrg            default:
433f29dbc25Smrg                vga->extCRTCregs[0x06] = 0;
434f29dbc25Smrg                break;
435f29dbc25Smrg            }
436f29dbc25Smrg            return (GFX_STATUS_OK);
437f29dbc25Smrg        }
438f29dbc25Smrg    }
439f29dbc25Smrg    return (GFX_STATUS_UNSUPPORTED);
440f29dbc25Smrg}
441f29dbc25Smrg
442f29dbc25Smrg/*----------------------------------------------------------------------------
443f29dbc25Smrg * gfx_vga_pitch
444f29dbc25Smrg *
445f29dbc25Smrg * This routine updates the VGA regisers in the specified VGA structure for
446f29dbc25Smrg * the specified pitch.  It does not program the hardware.
447f29dbc25Smrg *----------------------------------------------------------------------------
448f29dbc25Smrg */
449f29dbc25Smrgint
450f29dbc25Smrggfx_vga_pitch(gfx_vga_struct * vga, unsigned short pitch)
451f29dbc25Smrg{
452f29dbc25Smrg    pitch >>= 3;
45304007ebaSmrg    vga->stdCRTCregs[0x13] = (unsigned char) pitch;
45404007ebaSmrg    vga->extCRTCregs[0x05] = (unsigned char) ((pitch >> 8) & 0x03);
455f29dbc25Smrg    return (0);
456f29dbc25Smrg}
457f29dbc25Smrg
458f29dbc25Smrg/*----------------------------------------------------------------------------
459f29dbc25Smrg * gfx_vga_save
460f29dbc25Smrg *
461f29dbc25Smrg * This routine saves the state of the VGA registers into the specified
462f29dbc25Smrg * structure.  Flags indicate what portions of the register state need to
463f29dbc25Smrg * be saved.
464f29dbc25Smrg *----------------------------------------------------------------------------
465f29dbc25Smrg */
466f29dbc25Smrgint
467f29dbc25Smrggfx_vga_save(gfx_vga_struct * vga, int flags)
468f29dbc25Smrg{
469f29dbc25Smrg    int i;
470f29dbc25Smrg    unsigned short crtcindex, crtcdata;
471f29dbc25Smrg
472f29dbc25Smrg    crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
473f29dbc25Smrg    crtcdata = crtcindex + 1;
474f29dbc25Smrg
475f29dbc25Smrg    /* CHECK MISCELLANEOUS OUTPUT FLAG */
476f29dbc25Smrg
477f29dbc25Smrg    if (flags & GFX_VGA_FLAG_MISC_OUTPUT) {
478f29dbc25Smrg        /* SAVE MISCCELLANEOUS OUTPUT REGISTER */
479f29dbc25Smrg
480f29dbc25Smrg        vga->miscOutput = INB(0x3CC);
481f29dbc25Smrg    }
482f29dbc25Smrg
483f29dbc25Smrg    /* CHECK STANDARD CRTC FLAG */
484f29dbc25Smrg
485f29dbc25Smrg    if (flags & GFX_VGA_FLAG_STD_CRTC) {
486f29dbc25Smrg        /* SAVE STANDARD CRTC REGISTERS */
487f29dbc25Smrg
488f29dbc25Smrg        for (i = 0; i < GFX_STD_CRTC_REGS; i++) {
48904007ebaSmrg            OUTB(crtcindex, (unsigned char) i);
490f29dbc25Smrg            vga->stdCRTCregs[i] = INB(crtcdata);
491f29dbc25Smrg        }
492f29dbc25Smrg    }
493f29dbc25Smrg
494f29dbc25Smrg    /* CHECK EXTENDED CRTC FLAG */
495f29dbc25Smrg
496f29dbc25Smrg    if (flags & GFX_VGA_FLAG_EXT_CRTC) {
497f29dbc25Smrg        /* SAVE EXTENDED CRTC REGISTERS */
498f29dbc25Smrg
499f29dbc25Smrg        for (i = 0; i < GFX_EXT_CRTC_REGS; i++) {
50004007ebaSmrg            OUTB(crtcindex, (unsigned char) (0x40 + i));
501f29dbc25Smrg            vga->extCRTCregs[i] = INB(crtcdata);
502f29dbc25Smrg        }
503f29dbc25Smrg    }
504f29dbc25Smrg    return (0);
505f29dbc25Smrg}
506f29dbc25Smrg
507f29dbc25Smrg/*----------------------------------------------------------------------------
508f29dbc25Smrg * gfx_vga_clear_extended
509f29dbc25Smrg *
510f29dbc25Smrg * This routine clears the extended SoftVGA register values to have SoftVGA
511f29dbc25Smrg * behave like standard VGA.
512f29dbc25Smrg *----------------------------------------------------------------------------
513f29dbc25Smrg */
514f29dbc25Smrgvoid
515f29dbc25Smrggfx_vga_clear_extended(void)
516f29dbc25Smrg{
517f29dbc25Smrg    int i;
518f29dbc25Smrg    unsigned short crtcindex, crtcdata;
519f29dbc25Smrg
520f29dbc25Smrg    crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
521f29dbc25Smrg    crtcdata = crtcindex + 1;
522f29dbc25Smrg
523f29dbc25Smrg    OUTB(crtcindex, 0x30);
524f29dbc25Smrg    OUTB(crtcdata, 0x57);
525f29dbc25Smrg    OUTB(crtcdata, 0x4C);
526f29dbc25Smrg    for (i = 0x40; i <= 0x4F; i++) {
52704007ebaSmrg        OUTB(crtcindex, (unsigned char) i);
528f29dbc25Smrg        OUTB(crtcdata, 0);
529f29dbc25Smrg    }
530f29dbc25Smrg    OUTB(crtcindex, 0x30);
531f29dbc25Smrg    OUTB(crtcdata, 0x00);
532f29dbc25Smrg}
533f29dbc25Smrg
534f29dbc25Smrg/*----------------------------------------------------------------------------
535f29dbc25Smrg * gfx_vga_restore
536f29dbc25Smrg *
537f29dbc25Smrg * This routine restores the state of the VGA registers from the specified
538f29dbc25Smrg * structure.  Flags indicate what portions of the register state need to
539f29dbc25Smrg * be saved.
540f29dbc25Smrg *----------------------------------------------------------------------------
541f29dbc25Smrg */
542f29dbc25Smrgint
543f29dbc25Smrggfx_vga_restore(gfx_vga_struct * vga, int flags)
544f29dbc25Smrg{
545f29dbc25Smrg    int i;
546f29dbc25Smrg    unsigned short crtcindex, crtcdata;
547f29dbc25Smrg
548f29dbc25Smrg    crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
549f29dbc25Smrg    crtcdata = crtcindex + 1;
550f29dbc25Smrg
551f29dbc25Smrg    /* CHECK MISCELLANEOUS OUTPUT FLAG */
552f29dbc25Smrg
553f29dbc25Smrg    if (flags & GFX_VGA_FLAG_MISC_OUTPUT) {
554f29dbc25Smrg        /* RESTORE MISCELLANEOUS OUTPUT REGISTER VALUE */
555f29dbc25Smrg
556f29dbc25Smrg        OUTB(0x3C2, vga->miscOutput);
557f29dbc25Smrg    }
558f29dbc25Smrg
559f29dbc25Smrg    /* CHECK STANDARD CRTC FLAG */
560f29dbc25Smrg
561f29dbc25Smrg    if (flags & GFX_VGA_FLAG_STD_CRTC) {
562f29dbc25Smrg        /* UNLOCK STANDARD CRTC REGISTERS */
563f29dbc25Smrg
564f29dbc25Smrg        OUTB(crtcindex, 0x11);
565f29dbc25Smrg        OUTB(crtcdata, 0);
566f29dbc25Smrg
567f29dbc25Smrg        /* RESTORE STANDARD CRTC REGISTERS */
568f29dbc25Smrg
569f29dbc25Smrg        for (i = 0; i < GFX_STD_CRTC_REGS; i++) {
57004007ebaSmrg            OUTB(crtcindex, (unsigned char) i);
571f29dbc25Smrg            OUTB(crtcdata, vga->stdCRTCregs[i]);
572f29dbc25Smrg        }
573f29dbc25Smrg    }
574f29dbc25Smrg
575f29dbc25Smrg    /* CHECK EXTENDED CRTC FLAG */
576f29dbc25Smrg
577f29dbc25Smrg    if (flags & GFX_VGA_FLAG_EXT_CRTC) {
578f29dbc25Smrg        /* UNLOCK EXTENDED CRTC REGISTERS */
579f29dbc25Smrg
580f29dbc25Smrg        OUTB(crtcindex, 0x30);
581f29dbc25Smrg        OUTB(crtcdata, 0x57);
582f29dbc25Smrg        OUTB(crtcdata, 0x4C);
583f29dbc25Smrg
584f29dbc25Smrg        /* RESTORE EXTENDED CRTC REGISTERS */
585f29dbc25Smrg
586f29dbc25Smrg        for (i = 0; i < GFX_EXT_CRTC_REGS; i++) {
58704007ebaSmrg            OUTB(crtcindex, (unsigned char) (0x40 + i));
588f29dbc25Smrg            OUTB(crtcdata, vga->extCRTCregs[i]);
589f29dbc25Smrg        }
590f29dbc25Smrg
591f29dbc25Smrg        /* LOCK EXTENDED CRTC REGISTERS */
592f29dbc25Smrg
593f29dbc25Smrg        OUTB(crtcindex, 0x30);
594f29dbc25Smrg        OUTB(crtcdata, 0x00);
595f29dbc25Smrg
596f29dbc25Smrg        /* CHECK IF DIRECT FRAME BUFFER MODE (VESA MODE) */
597f29dbc25Smrg
598f29dbc25Smrg        if (vga->extCRTCregs[0x03] & 1) {
599f29dbc25Smrg            /* SET BORDER COLOR TO BLACK */
600f29dbc25Smrg            /* This really should be another thing saved/restored, but */
601f29dbc25Smrg            /* Durango currently doesn't do the attr controller registers. */
602f29dbc25Smrg
60304007ebaSmrg            INB(0x3BA);         /* Reset flip-flop */
604f29dbc25Smrg            INB(0x3DA);
605f29dbc25Smrg            OUTB(0x3C0, 0x11);
606f29dbc25Smrg            OUTB(0x3C0, 0x00);
607f29dbc25Smrg        }
608f29dbc25Smrg    }
609f29dbc25Smrg    return (0);
610f29dbc25Smrg}
611f29dbc25Smrg
612f29dbc25Smrg/*----------------------------------------------------------------------------
613f29dbc25Smrg * gfx_vga_mode_switch
614f29dbc25Smrg *
615f29dbc25Smrg * This routine programs the SoftVGA register to indicate that a mode switch
616f29dbc25Smrg * is in progress.  This results in a cleaner mode switch since SoftVGA will
617f29dbc25Smrg * not validate the hardware with intermediate values.
618f29dbc25Smrg *----------------------------------------------------------------------------
619f29dbc25Smrg */
620f29dbc25Smrgint
621f29dbc25Smrggfx_vga_mode_switch(int active)
622f29dbc25Smrg{
623f29dbc25Smrg    unsigned short crtcindex, crtcdata;
624f29dbc25Smrg
625f29dbc25Smrg    crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
626f29dbc25Smrg    crtcdata = crtcindex + 1;
627f29dbc25Smrg
628f29dbc25Smrg    /* UNLOCK EXTENDED CRTC REGISTERS */
629f29dbc25Smrg
630f29dbc25Smrg    OUTB(crtcindex, CRTC_EXTENDED_REGISTER_LOCK);
631f29dbc25Smrg    OUTB(crtcdata, 0x57);
632f29dbc25Smrg    OUTB(crtcdata, 0x4C);
633f29dbc25Smrg
634f29dbc25Smrg    /* SIGNAL THE BEGINNING OR END OF THE MODE SWITCH */
635f29dbc25Smrg    /* SoftVGA will hold off validating the back end hardware. */
636f29dbc25Smrg
637f29dbc25Smrg    OUTB(crtcindex, CRTC_MODE_SWITCH_CONTROL);
638f29dbc25Smrg    active = active ? 1 : 0;
63904007ebaSmrg    OUTB(crtcdata, (unsigned char) active);
640f29dbc25Smrg
641f29dbc25Smrg    /* WAIT UNTIL SOFTVGA HAS VALIDATED MODE IF ENDING MODE SWITCH */
642f29dbc25Smrg    /* This is for VSA1 only, where SoftVGA waits until the next */
643f29dbc25Smrg    /* vertical blank to validate the hardware state. */
644f29dbc25Smrg
645f29dbc25Smrg    if ((!active) && (!(gu1_detect_vsa2()))) {
646f29dbc25Smrg        OUTB(crtcindex, 0x33);
64704007ebaSmrg        while (INB(crtcdata) & 0x80);
648f29dbc25Smrg    }
649f29dbc25Smrg
650f29dbc25Smrg    /* LOCK EXTENDED CRTC REGISTERS */
651f29dbc25Smrg
652f29dbc25Smrg    OUTB(crtcindex, CRTC_EXTENDED_REGISTER_LOCK);
653f29dbc25Smrg    OUTB(crtcdata, 0x00);
654f29dbc25Smrg    return (0);
655f29dbc25Smrg}
656f29dbc25Smrg
657f29dbc25Smrg/*----------------------------------------------------------------------------
658f29dbc25Smrg * gu1_detect_vsa2
659f29dbc25Smrg *
660f29dbc25Smrg * This routine detects if VSA2 is present.  The interface to SoftVGA
661f29dbc25Smrg * changed slightly.
662f29dbc25Smrg *----------------------------------------------------------------------------
663f29dbc25Smrg */
664f29dbc25Smrgint
665f29dbc25Smrggu1_detect_vsa2(void)
666f29dbc25Smrg{
667f29dbc25Smrg    unsigned short crtcindex, crtcdata;
668f29dbc25Smrg
669f29dbc25Smrg    crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
670f29dbc25Smrg    crtcdata = crtcindex + 1;
671f29dbc25Smrg    OUTB(crtcindex, 0x35);
672f29dbc25Smrg    if (INB(crtcdata) != 'C')
673f29dbc25Smrg        return (0);
674f29dbc25Smrg    OUTB(crtcindex, 0x36);
675f29dbc25Smrg    if (INB(crtcdata) != 'X')
676f29dbc25Smrg        return (0);
677f29dbc25Smrg    return (1);
678f29dbc25Smrg}
679f29dbc25Smrg
680f29dbc25Smrg/* END OF FILE */
681