gx_vga.c revision f29dbc25
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    } else if (font_data) {
97	DEBUGMSG(1, (0, X_NONE, "Restore VGA Data\n"));
98	memcpy(gfx_virt_fbptr, font_data, VGA_BLOCK);
99	free(font_data);
100	font_data = NULL;
101    }
102}
103
104void
105gu2_set_vga(int reset)
106{
107    int data = gfx_read_reg32(MDC_GENERAL_CFG);
108
109    if (reset)
110	data |= MDC_GCFG_VGAE;
111    else
112	data &= ~MDC_GCFG_VGAE;
113
114    gfx_write_reg32(MDC_GENERAL_CFG, data);
115}
116
117int
118gu2_vga_seq_blanking(void)
119{
120    int tmp;
121
122    gfx_outb(0x3C4, 1);
123    tmp = gfx_inb(0x3C5);
124    tmp |= 0x20;
125    tmp |= tmp << 8;
126    gfx_outw(0x3C4, tmp);
127
128    gfx_delay_milliseconds(1);
129    return (GFX_STATUS_OK);
130}
131
132int
133gu2_vga_attr_ctrl(int reset)
134{
135    int tmp;
136
137    tmp = gfx_inb(0x3DA);
138    gfx_outb(0x3C0, (unsigned char)(reset ? 0x00 : 0x20));
139    if (reset)
140	tmp = gfx_inb(0x3DA);
141
142    return (GFX_STATUS_OK);
143}
144
145void
146gu2_vga_to_gfx(void)
147{
148    gu2_vga_attr_ctrl(0);
149
150    gu2_vga_seq_blanking();
151    gfx_delay_milliseconds(2);
152
153    gu2_vga_extcrtc(0x3F, 1);
154}
155
156void
157gu2_gfx_to_vga(int vga_mode)
158{
159    int tmp;
160    char sequencer;
161
162    gu2_vga_extcrtc(0x40, vga_mode);
163
164    /* clear the display blanking bit */
165    gfx_outb(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_CLK_MODE);
166    sequencer = gfx_inb(MDC_SEQUENCER_DATA);
167    sequencer &= ~MDC_CLK_MODE_SCREEN_OFF;
168    sequencer |= 1;
169    gfx_outb(MDC_SEQUENCER_DATA, sequencer);
170
171    gfx_delay_milliseconds(1);
172
173    /*restart the sequencer */
174    gfx_outw(0x3C4, 0x300);
175
176    /* turn on the attribute controler */
177    tmp = gfx_inb(0x3DA);
178    gfx_outb(0x3C0, 0x20);
179    tmp = gfx_inb(0x3DA);
180
181    gu2_vga_extcrtc(0x3F, 0);
182}
183
184/*---------------------------------------------------------------------------
185 * gfx_vga_seq_reset
186 *
187 * This routine enables or disables SoftVGA.  It is used to make SoftVGA
188 * "be quiet" and not interfere with any of the direct hardware access from
189 * Durango.  For VSA1, the sequencer is reset to stop text redraws.  VSA2 may
190 * provide a better way to have SoftVGA sit in the background.
191 *---------------------------------------------------------------------------
192 */
193int
194gu2_vga_seq_reset(int reset)
195{
196    gfx_outb(0x3C4, 0);
197    gfx_outb(0x3C5, (unsigned char)(reset ? 0x00 : 0x03));
198    return (GFX_STATUS_OK);
199}
200
201/*---------------------------------------------------------------------------
202 * gfx_vga_save
203 *
204 * This routine saves the state of the VGA registers into the specified
205 * structure.  Flags indicate what portions of the register state need to
206 * be saved.
207 *----------------------------------------------------------------------------
208 */
209int
210gu2_vga_save(gfx_vga_struct * vga, int flags)
211{
212    int i;
213    unsigned short crtcindex, crtcdata;
214
215    crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
216    crtcdata = crtcindex + 1;
217
218    /* CHECK MISCELLANEOUS OUTPUT FLAG */
219
220    if (flags & GU2_VGA_FLAG_MISC_OUTPUT) {
221	/* SAVE MISCCELLANEOUS OUTPUT REGISTER */
222	vga->miscOutput = gfx_inb(0x3CC);
223    }
224
225    /* CHECK SEQ */
226
227    if (flags & GU2_VGA_FLAG_SEQ) {
228	/* SAVE STANDARD CRTC REGISTERS */
229	for (i = 1; i < GU2_SEQ_REGS; i++) {
230	    gfx_outb(0x3C4, (unsigned char)i);
231	    SEQregs[i] = gfx_inb(0x3C5);
232	}
233    }
234
235    /* CHECK STANDARD CRTC FLAG */
236
237    if (flags & GU2_VGA_FLAG_STD_CRTC) {
238	/* SAVE STANDARD CRTC REGISTERS */
239	for (i = 0; i < GU2_STD_CRTC_REGS; i++) {
240	    gfx_outb(crtcindex, (unsigned char)i);
241	    vga->stdCRTCregs[i] = gfx_inb(crtcdata);
242	}
243    }
244
245    /* CHECK GDC */
246
247    if (flags & GU2_VGA_FLAG_GDC) {
248	/* SAVE STANDARD CRTC REGISTERS */
249	for (i = 0; i < GU2_GDC_REGS; i++) {
250	    gfx_outb(0x3CE, (unsigned char)i);
251	    GDCregs[i] = gfx_inb(0x3CF);
252	}
253    }
254
255    /* CHECK EXTENDED CRTC FLAG */
256
257    if (flags & GU2_VGA_FLAG_EXT_CRTC) {
258	/* SAVE EXTENDED CRTC REGISTERS */
259	for (i = 0; i < GU2_EXT_CRTC_REGS; i++) {
260	    gfx_outb(crtcindex, (unsigned char)(0x40 + i));
261	    vga->extCRTCregs[i] = gfx_inb(crtcdata);
262	}
263    }
264
265    if (flags & GU2_VGA_FLAG_PALETTE) {
266	/* SAVE PALETTE DATA */
267	for (i = 0; i < 0x100; i++) {
268	    gfx_outb(0x3C7, i);
269	    palette[i] = gfx_inb(0x3C9);
270	}
271    }
272
273    if (flags & GU2_VGA_FLAG_ATTR) {
274	/* SAVE Attribute  DATA */
275	for (i = 0; i < 21; i++) {
276	    gfx_inb(0x3DA);
277	    gfx_outb(0x3C0, i);
278	    ATTRregs[i] = gfx_inb(0x3C1);
279	}
280    }
281
282    /* save the VGA data */
283    gu2_vga_font_data(0);
284    return (0);
285}
286
287/*----------------------------------------------------------------------------
288 * gfx_vga_clear_extended
289 *
290 * This routine clears the extended SoftVGA register values to have SoftVGA
291 * behave like standard VGA.
292 *----------------------------------------------------------------------------
293 */
294void
295gu2_vga_clear_extended(void)
296{
297    int i;
298    unsigned short crtcindex, crtcdata;
299
300    crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
301    crtcdata = crtcindex + 1;
302
303    gfx_outb(crtcindex, 0x30);
304    gfx_outb(crtcdata, 0x57);
305    gfx_outb(crtcdata, 0x4C);
306    for (i = 0x41; i <= 0x4F; i++) {
307	gfx_outb(crtcindex, (unsigned char)i);
308	gfx_outb(crtcdata, 0);
309    }
310
311    gfx_outb(crtcindex, 0x30);
312    gfx_outb(crtcdata, 0x00);
313}
314
315void
316gu2_vga_extcrtc(char offset, int reset)
317{
318    unsigned short crtcindex, crtcdata;
319
320    crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
321    crtcdata = crtcindex + 1;
322
323    /* UNLOCK EXTENDED CRTC REGISTERS */
324
325    gfx_outb(crtcindex, 0x30);
326    gfx_outb(crtcdata, 0x57);
327    gfx_outb(crtcdata, 0x4C);
328
329    /* RESTORE EXTENDED CRTC REGISTERS */
330
331    gfx_outb(crtcindex, offset);
332    gfx_outb(crtcdata, reset);
333}
334
335/*----------------------------------------------------------------------------
336 * gfx_vga_restore
337 *
338 * This routine restores the state of the VGA registers from the specified
339 * structure.  Flags indicate what portions of the register state need to
340 * be saved.
341 *----------------------------------------------------------------------------
342 */
343int
344gu2_vga_restore(gfx_vga_struct * vga, int flags)
345{
346    int i;
347    unsigned short crtcindex, crtcdata;
348
349    crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
350    crtcdata = crtcindex + 1;
351
352    /* CHECK MISCELLANEOUS OUTPUT FLAG */
353
354    if (flags & GU2_VGA_FLAG_MISC_OUTPUT) {
355	/* RESTORE MISCELLANEOUS OUTPUT REGISTER VALUE */
356	gfx_outb(0x3C2, vga->miscOutput);
357    }
358
359    /* CHECK SEQ */
360
361    if (flags & GU2_VGA_FLAG_SEQ) {
362	/* RESTORE STANDARD CRTC REGISTERS */
363	for (i = 1; i < GU2_SEQ_REGS; i++) {
364	    gfx_outb(0x3C4, (unsigned char)i);
365	    gfx_outb(0x3C5, SEQregs[i]);
366	}
367    }
368
369    /* CHECK STANDARD CRTC FLAG */
370
371    if (flags & GU2_VGA_FLAG_STD_CRTC) {
372	/* UNLOCK STANDARD CRTC REGISTERS */
373	gfx_outb(crtcindex, 0x11);
374	gfx_outb(crtcdata, 0);
375
376	/* RESTORE STANDARD CRTC REGISTERS */
377
378	for (i = 0; i < GU2_STD_CRTC_REGS; i++) {
379	    gfx_outb(crtcindex, (unsigned char)i);
380	    gfx_outb(crtcdata, vga->stdCRTCregs[i]);
381	}
382    }
383
384    /* CHECK GDC */
385
386    if (flags & GU2_VGA_FLAG_GDC) {
387	/* SAVE STANDARD CRTC REGISTERS */
388	for (i = 0; i < GU2_GDC_REGS; i++) {
389	    gfx_outb(0x3CE, (unsigned char)i);
390	    gfx_outb(0x3CF, GDCregs[i]);
391	}
392    }
393
394    /* CHECK EXTENDED CRTC FLAG */
395
396    if (flags & GU2_VGA_FLAG_EXT_CRTC) {
397	/* UNLOCK EXTENDED CRTC REGISTERS */
398	gfx_outb(crtcindex, 0x30);
399	gfx_outb(crtcdata, 0x57);
400	gfx_outb(crtcdata, 0x4C);
401
402	/* RESTORE EXTENDED CRTC REGISTERS */
403
404	for (i = 1; i < GU2_EXT_CRTC_REGS; i++) {
405	    gfx_outb(crtcindex, (unsigned char)(0x40 + i));
406	    gfx_outb(crtcdata, vga->extCRTCregs[i]);
407	}
408
409	/* LOCK EXTENDED CRTC REGISTERS */
410
411	gfx_outb(crtcindex, 0x30);
412	gfx_outb(crtcdata, 0x00);
413
414	/* CHECK IF DIRECT FRAME BUFFER MODE (VESA MODE) */
415
416	if (vga->extCRTCregs[0x03] & 1) {
417	    /* SET BORDER COLOR TO BLACK */
418	    /* This really should be another thing saved/restored, but */
419	    /* Durango currently doesn't do the attr controller registers. */
420
421	    gfx_inb(0x3BA);	       /* Reset flip-flop */
422	    gfx_inb(0x3DA);
423	    gfx_outb(0x3C0, 0x11);
424	    gfx_outb(0x3C0, 0x00);
425	}
426    }
427
428    if (flags & GU2_VGA_FLAG_PALETTE) {
429	/* RESTORE PALETTE DATA */
430	for (i = 0; i < 0x100; i++) {
431	    gfx_outb(0x3C8, i);
432	    gfx_outb(0x3C9, palette[i]);
433	}
434    }
435
436    if (flags & GU2_VGA_FLAG_ATTR) {
437	/* RESTORE Attribute  DATA */
438	for (i = 0; i < 21; i++) {
439	    gfx_inb(0x3DA);
440	    gfx_outb(0x3C0, i);
441	    gfx_outb(0x3C0, ATTRregs[i]);
442	}
443	/* SAVE Attribute  DATA */
444
445	for (i = 0; i < 21; i++) {
446	    gfx_inb(0x3DA);
447	    gfx_outb(0x3C0, i);
448	}
449    }
450
451    /* restore the VGA data */
452    gu2_vga_font_data(1);
453
454    return (0);
455}
456
457/* END OF FILE */
458