gx_vga.c revision 79d5fcd7
1/* Copyright (c) 2003-2005 Advanced Micro Devices, Inc.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 *
21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
22 * contributors may be used to endorse or promote products derived from this
23 * software without specific prior written permission.
24 * */
25
26/*
27 * This file contains routines to set modes using the VGA registers.
28 * Since this file is for the first generation graphics unit, it interfaces
29 * to SoftVGA registers.  It works for both VSA1 and VSA2.
30 * */
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#include <stdlib.h>
37#include <string.h>
38
39/* VGA STRUCTURE */
40
41#define GU2_STD_CRTC_REGS 	25
42#define GU2_EXT_CRTC_REGS 	15
43#define GU2_GDC_REGS 		9
44#define GU2_SEQ_REGS		5
45
46#define GU2_VGA_FLAG_MISC_OUTPUT	0x1
47#define GU2_VGA_FLAG_STD_CRTC		0x2
48#define GU2_VGA_FLAG_EXT_CRTC		0x4
49#define GU2_VGA_FLAG_GDC			0x10
50#define GU2_VGA_FLAG_SEQ			0x20
51#define GU2_VGA_FLAG_PALETTE 		0x40
52#define GU2_VGA_FLAG_ATTR 			0x80
53
54static unsigned int GDCregs[10];
55static unsigned int SEQregs[10];
56static unsigned int palette[256];
57static unsigned int ATTRregs[32];
58static unsigned char *font_data = NULL;
59
60#define VGA_BLOCK 0x40000       /* 256 k */
61
62void gu2_vga_extcrtc(char offset, int reset);
63int gu2_get_vga_active(void);
64void gu2_vga_font_data(int flag);
65void gu2_set_vga(int reset);
66int gu2_vga_seq_blanking(void);
67int gu2_vga_attr_ctrl(int reset);
68void gu2_vga_to_gfx(void);
69void gu2_gfx_to_vga(int vga_mode);
70int gu2_vga_seq_reset(int reset);
71int gu2_vga_save(gfx_vga_struct * vga, int flags);
72void gu2_vga_clear_extended(void);
73int gu2_vga_restore(gfx_vga_struct * vga, int flags);
74
75int
76gu2_get_vga_active(void)
77{
78    int data = gfx_read_reg32(MDC_GENERAL_CFG);
79
80    if (data & MDC_GCFG_VGAE)
81        return 1;
82
83    return 0;
84}
85
86void
87gu2_vga_font_data(int flag)
88{
89    if (flag == 0) {
90        if (font_data == NULL) {
91            font_data = malloc(VGA_BLOCK);
92        }
93
94        DEBUGMSG(1, (0, X_NONE, "Saving VGA Data\n"));
95        memcpy(font_data, gfx_virt_fbptr, VGA_BLOCK);
96    }
97    else if (font_data) {
98        DEBUGMSG(1, (0, X_NONE, "Restore VGA Data\n"));
99        memcpy(gfx_virt_fbptr, font_data, VGA_BLOCK);
100        free(font_data);
101        font_data = NULL;
102    }
103}
104
105void
106gu2_set_vga(int reset)
107{
108    int data = gfx_read_reg32(MDC_GENERAL_CFG);
109
110    if (reset)
111        data |= MDC_GCFG_VGAE;
112    else
113        data &= ~MDC_GCFG_VGAE;
114
115    gfx_write_reg32(MDC_GENERAL_CFG, data);
116}
117
118int
119gu2_vga_seq_blanking(void)
120{
121    int tmp;
122
123    gfx_outb(0x3C4, 1);
124    tmp = gfx_inb(0x3C5);
125    tmp |= 0x20;
126    tmp |= tmp << 8;
127    gfx_outw(0x3C4, tmp);
128
129    gfx_delay_milliseconds(1);
130    return (GFX_STATUS_OK);
131}
132
133int
134gu2_vga_attr_ctrl(int reset)
135{
136    int tmp;
137
138    tmp = gfx_inb(0x3DA);
139    gfx_outb(0x3C0, (unsigned char) (reset ? 0x00 : 0x20));
140    if (reset)
141        tmp = gfx_inb(0x3DA);
142
143    return (GFX_STATUS_OK);
144}
145
146void
147gu2_vga_to_gfx(void)
148{
149    gu2_vga_attr_ctrl(0);
150
151    gu2_vga_seq_blanking();
152    gfx_delay_milliseconds(2);
153
154    gu2_vga_extcrtc(0x3F, 1);
155}
156
157void
158gu2_gfx_to_vga(int vga_mode)
159{
160    int tmp;
161    char sequencer;
162
163    gu2_vga_extcrtc(0x40, vga_mode);
164
165    /* clear the display blanking bit */
166    gfx_outb(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_CLK_MODE);
167    sequencer = gfx_inb(MDC_SEQUENCER_DATA);
168    sequencer &= ~MDC_CLK_MODE_SCREEN_OFF;
169    sequencer |= 1;
170    gfx_outb(MDC_SEQUENCER_DATA, sequencer);
171
172    gfx_delay_milliseconds(1);
173
174    /*restart the sequencer */
175    gfx_outw(0x3C4, 0x300);
176
177    /* turn on the attribute controller */
178    tmp = gfx_inb(0x3DA);
179    gfx_outb(0x3C0, 0x20);
180    tmp = gfx_inb(0x3DA);
181
182    gu2_vga_extcrtc(0x3F, 0);
183}
184
185/*---------------------------------------------------------------------------
186 * gfx_vga_seq_reset
187 *
188 * This routine enables or disables SoftVGA.  It is used to make SoftVGA
189 * "be quiet" and not interfere with any of the direct hardware access from
190 * Durango.  For VSA1, the sequencer is reset to stop text redraws.  VSA2 may
191 * provide a better way to have SoftVGA sit in the background.
192 *---------------------------------------------------------------------------
193 */
194int
195gu2_vga_seq_reset(int reset)
196{
197    gfx_outb(0x3C4, 0);
198    gfx_outb(0x3C5, (unsigned char) (reset ? 0x00 : 0x03));
199    return (GFX_STATUS_OK);
200}
201
202/*---------------------------------------------------------------------------
203 * gfx_vga_save
204 *
205 * This routine saves the state of the VGA registers into the specified
206 * structure.  Flags indicate what portions of the register state need to
207 * be saved.
208 *----------------------------------------------------------------------------
209 */
210int
211gu2_vga_save(gfx_vga_struct * vga, int flags)
212{
213    int i;
214    unsigned short crtcindex, crtcdata;
215
216    crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
217    crtcdata = crtcindex + 1;
218
219    /* CHECK MISCELLANEOUS OUTPUT FLAG */
220
221    if (flags & GU2_VGA_FLAG_MISC_OUTPUT) {
222        /* SAVE MISCCELLANEOUS OUTPUT REGISTER */
223        vga->miscOutput = gfx_inb(0x3CC);
224    }
225
226    /* CHECK SEQ */
227
228    if (flags & GU2_VGA_FLAG_SEQ) {
229        /* SAVE STANDARD CRTC REGISTERS */
230        for (i = 1; i < GU2_SEQ_REGS; i++) {
231            gfx_outb(0x3C4, (unsigned char) i);
232            SEQregs[i] = gfx_inb(0x3C5);
233        }
234    }
235
236    /* CHECK STANDARD CRTC FLAG */
237
238    if (flags & GU2_VGA_FLAG_STD_CRTC) {
239        /* SAVE STANDARD CRTC REGISTERS */
240        for (i = 0; i < GU2_STD_CRTC_REGS; i++) {
241            gfx_outb(crtcindex, (unsigned char) i);
242            vga->stdCRTCregs[i] = gfx_inb(crtcdata);
243        }
244    }
245
246    /* CHECK GDC */
247
248    if (flags & GU2_VGA_FLAG_GDC) {
249        /* SAVE STANDARD CRTC REGISTERS */
250        for (i = 0; i < GU2_GDC_REGS; i++) {
251            gfx_outb(0x3CE, (unsigned char) i);
252            GDCregs[i] = gfx_inb(0x3CF);
253        }
254    }
255
256    /* CHECK EXTENDED CRTC FLAG */
257
258    if (flags & GU2_VGA_FLAG_EXT_CRTC) {
259        /* SAVE EXTENDED CRTC REGISTERS */
260        for (i = 0; i < GU2_EXT_CRTC_REGS; i++) {
261            gfx_outb(crtcindex, (unsigned char) (0x40 + i));
262            vga->extCRTCregs[i] = gfx_inb(crtcdata);
263        }
264    }
265
266    if (flags & GU2_VGA_FLAG_PALETTE) {
267        /* SAVE PALETTE DATA */
268        for (i = 0; i < 0x100; i++) {
269            gfx_outb(0x3C7, i);
270            palette[i] = gfx_inb(0x3C9);
271        }
272    }
273
274    if (flags & GU2_VGA_FLAG_ATTR) {
275        /* SAVE Attribute  DATA */
276        for (i = 0; i < 21; i++) {
277            gfx_inb(0x3DA);
278            gfx_outb(0x3C0, i);
279            ATTRregs[i] = gfx_inb(0x3C1);
280        }
281    }
282
283    /* save the VGA data */
284    gu2_vga_font_data(0);
285    return (0);
286}
287
288/*----------------------------------------------------------------------------
289 * gfx_vga_clear_extended
290 *
291 * This routine clears the extended SoftVGA register values to have SoftVGA
292 * behave like standard VGA.
293 *----------------------------------------------------------------------------
294 */
295void
296gu2_vga_clear_extended(void)
297{
298    int i;
299    unsigned short crtcindex, crtcdata;
300
301    crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
302    crtcdata = crtcindex + 1;
303
304    gfx_outb(crtcindex, 0x30);
305    gfx_outb(crtcdata, 0x57);
306    gfx_outb(crtcdata, 0x4C);
307    for (i = 0x41; i <= 0x4F; i++) {
308        gfx_outb(crtcindex, (unsigned char) i);
309        gfx_outb(crtcdata, 0);
310    }
311
312    gfx_outb(crtcindex, 0x30);
313    gfx_outb(crtcdata, 0x00);
314}
315
316void
317gu2_vga_extcrtc(char offset, int reset)
318{
319    unsigned short crtcindex, crtcdata;
320
321    crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
322    crtcdata = crtcindex + 1;
323
324    /* UNLOCK EXTENDED CRTC REGISTERS */
325
326    gfx_outb(crtcindex, 0x30);
327    gfx_outb(crtcdata, 0x57);
328    gfx_outb(crtcdata, 0x4C);
329
330    /* RESTORE EXTENDED CRTC REGISTERS */
331
332    gfx_outb(crtcindex, offset);
333    gfx_outb(crtcdata, reset);
334}
335
336/*----------------------------------------------------------------------------
337 * gfx_vga_restore
338 *
339 * This routine restores the state of the VGA registers from the specified
340 * structure.  Flags indicate what portions of the register state need to
341 * be saved.
342 *----------------------------------------------------------------------------
343 */
344int
345gu2_vga_restore(gfx_vga_struct * vga, int flags)
346{
347    int i;
348    unsigned short crtcindex, crtcdata;
349
350    crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
351    crtcdata = crtcindex + 1;
352
353    /* CHECK MISCELLANEOUS OUTPUT FLAG */
354
355    if (flags & GU2_VGA_FLAG_MISC_OUTPUT) {
356        /* RESTORE MISCELLANEOUS OUTPUT REGISTER VALUE */
357        gfx_outb(0x3C2, vga->miscOutput);
358    }
359
360    /* CHECK SEQ */
361
362    if (flags & GU2_VGA_FLAG_SEQ) {
363        /* RESTORE STANDARD CRTC REGISTERS */
364        for (i = 1; i < GU2_SEQ_REGS; i++) {
365            gfx_outb(0x3C4, (unsigned char) i);
366            gfx_outb(0x3C5, SEQregs[i]);
367        }
368    }
369
370    /* CHECK STANDARD CRTC FLAG */
371
372    if (flags & GU2_VGA_FLAG_STD_CRTC) {
373        /* UNLOCK STANDARD CRTC REGISTERS */
374        gfx_outb(crtcindex, 0x11);
375        gfx_outb(crtcdata, 0);
376
377        /* RESTORE STANDARD CRTC REGISTERS */
378
379        for (i = 0; i < GU2_STD_CRTC_REGS; i++) {
380            gfx_outb(crtcindex, (unsigned char) i);
381            gfx_outb(crtcdata, vga->stdCRTCregs[i]);
382        }
383    }
384
385    /* CHECK GDC */
386
387    if (flags & GU2_VGA_FLAG_GDC) {
388        /* SAVE STANDARD CRTC REGISTERS */
389        for (i = 0; i < GU2_GDC_REGS; i++) {
390            gfx_outb(0x3CE, (unsigned char) i);
391            gfx_outb(0x3CF, GDCregs[i]);
392        }
393    }
394
395    /* CHECK EXTENDED CRTC FLAG */
396
397    if (flags & GU2_VGA_FLAG_EXT_CRTC) {
398        /* UNLOCK EXTENDED CRTC REGISTERS */
399        gfx_outb(crtcindex, 0x30);
400        gfx_outb(crtcdata, 0x57);
401        gfx_outb(crtcdata, 0x4C);
402
403        /* RESTORE EXTENDED CRTC REGISTERS */
404
405        for (i = 1; i < GU2_EXT_CRTC_REGS; i++) {
406            gfx_outb(crtcindex, (unsigned char) (0x40 + i));
407            gfx_outb(crtcdata, vga->extCRTCregs[i]);
408        }
409
410        /* LOCK EXTENDED CRTC REGISTERS */
411
412        gfx_outb(crtcindex, 0x30);
413        gfx_outb(crtcdata, 0x00);
414
415        /* CHECK IF DIRECT FRAME BUFFER MODE (VESA MODE) */
416
417        if (vga->extCRTCregs[0x03] & 1) {
418            /* SET BORDER COLOR TO BLACK */
419            /* This really should be another thing saved/restored, but */
420            /* Durango currently doesn't do the attr controller registers. */
421
422            gfx_inb(0x3BA);     /* Reset flip-flop */
423            gfx_inb(0x3DA);
424            gfx_outb(0x3C0, 0x11);
425            gfx_outb(0x3C0, 0x00);
426        }
427    }
428
429    if (flags & GU2_VGA_FLAG_PALETTE) {
430        /* RESTORE PALETTE DATA */
431        for (i = 0; i < 0x100; i++) {
432            gfx_outb(0x3C8, i);
433            gfx_outb(0x3C9, palette[i]);
434        }
435    }
436
437    if (flags & GU2_VGA_FLAG_ATTR) {
438        /* RESTORE Attribute  DATA */
439        for (i = 0; i < 21; i++) {
440            gfx_inb(0x3DA);
441            gfx_outb(0x3C0, i);
442            gfx_outb(0x3C0, ATTRregs[i]);
443        }
444        /* SAVE Attribute  DATA */
445
446        for (i = 0; i < 21; i++) {
447            gfx_inb(0x3DA);
448            gfx_outb(0x3C0, i);
449        }
450    }
451
452    /* restore the VGA data */
453    gu2_vga_font_data(1);
454
455    return (0);
456}
457
458/* END OF FILE */
459