1 /* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */
2 /* */
3 /* This library is free software; you can redistribute it and/or */
4 /* modify it without any restrictions. This library is distributed */
5 /* in the hope that it will be useful, but without any warranty. */
6
7 /* Cirrus support Copyright (C) 1993 Harm Hanemaayer */
8
9 /*
10 * Dec 1994:
11 *
12 * Mode setting rewritten with more SVGA generalization and increased
13 * flexibility. Supports 542x/543x.
14 * Uses interfaces in timing.h and vgaregs.h. Only saves/restores
15 * extended registers that are actually changed for SVGA modes.
16 */
17
18
19 #include <stdlib.h>
20 #include <stdio.h> /* for printf */
21 #include <unistd.h>
22 #include <string.h> /* for memset */
23 #include "vga.h"
24 #include "libvga.h"
25 #include "driver.h"
26
27
28 /* Enable support for > 85 MHz dot clocks on the 5434. */
29 #define SUPPORT_5434_PALETTE_CLOCK_DOUBLING
30 /* Use the special clocking mode for all dot clocks at 256 colors, not */
31 /* just those > 85 MHz, for debugging. */
32 /* #define ALWAYS_USE_5434_PALETTE_CLOCK_DOUBLING */
33
34
35 /* New style driver interface. */
36 #include "timing.h"
37 #include "vgaregs.h"
38 #include "interface.h"
39 #include "accel.h"
40 #include "vgapci.h"
41
42
43 #define CIRRUSREG_GR(i) (VGA_TOTAL_REGS + i - VGA_GRAPHICS_COUNT)
44 #define CIRRUSREG_SR(i) (VGA_TOTAL_REGS + 5 + i - VGA_SEQUENCER_COUNT)
45 #define CIRRUSREG_CR(i) (VGA_TOTAL_REGS + 5 + 27 + i - VGA_CRTC_COUNT)
46 #define CIRRUSREG_DAC (VGA_TOTAL_REGS + 5 + 27 + 15)
47 #define CIRRUS_TOTAL_REGS (VGA_TOTAL_REGS + 5 + 27 + 15 + 1)
48
49 /* Indices into mode register array. */
50 #define CIRRUS_GRAPHICSOFFSET1 CIRRUSREG_GR(0x09)
51 #define CIRRUS_GRAPHICSOFFSET2 CIRRUSREG_GR(0x0A)
52 #define CIRRUS_GRB CIRRUSREG_GR(0x0B)
53 #define CIRRUS_SR7 CIRRUSREG_SR(0x07)
54 #define CIRRUS_VCLK3NUMERATOR CIRRUSREG_SR(0x0E)
55 #define CIRRUS_DRAMCONTROL CIRRUSREG_SR(0x0F)
56 #define CIRRUS_PERFTUNING CIRRUSREG_SR(0x16)
57 #define CIRRUS_SR17 CIRRUSREG_SR(0x17)
58 #define CIRRUS_VCLK3DENOMINATOR CIRRUSREG_SR(0x1E)
59 #define CIRRUS_MCLKREGISTER CIRRUSREG_SR(0x1F)
60 #define CIRRUS_CR19 CIRRUSREG_CR(0x19)
61 #define CIRRUS_CR1A CIRRUSREG_CR(0x1A)
62 #define CIRRUS_CR1B CIRRUSREG_CR(0x1B)
63 #define CIRRUS_CR1D CIRRUSREG_CR(0x1D)
64 #define CIRRUS_HIDDENDAC CIRRUSREG_DAC
65
66
67 /* Efficient chip type checks. */
68
69 #define CHECKCHIP1(c1) ((1 << cirrus_chiptype) & (1 << c1))
70 #define CHECKCHIP2(c1, c2) ((1 << cirrus_chiptype) & ((1 << c1) | (1 << c2)))
71 #define CHECKCHIP3(c1, c2, c3) ((1 << cirrus_chiptype) & ((1 << c1) \
72 | (1 << c2) | (1 << c3)))
73 #define CHECKCHIP4(c1, c2, c3, c4) ((1 << cirrus_chiptype) & ((1 << c1) \
74 | (1 << c2) | (1 << c3) | (1 << c4)))
75 #define CHECKCHIP5(c1, c2, c3, c4, c5) ((1 << cirrus_chiptype) & \
76 ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5)))
77 #define CHECKCHIP6(c1, c2, c3, c4, c5, c6) ((1 << cirrus_chiptype) & \
78 ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \
79 | (1 << c6)))
80 #define CHECKCHIP7(c1, c2, c3, c4, c5, c6, c7) ((1 << cirrus_chiptype) & \
81 ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \
82 | (1 << c6) | (1 << c7)))
83 #define CHECKCHIP8(c1, c2, c3, c4, c5, c6, c7, c8) ((1 << cirrus_chiptype) & \
84 ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \
85 | (1 << c6) | (1 << c7) | (1 << c8)))
86 #define CHECKCHIP9(c1, c2, c3, c4, c5, c6, c7, c8, c9) ((1 << cirrus_chiptype) & \
87 ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \
88 | (1 << c6) | (1 << c7) | (1 << c8) | (1 << c9)))
89 #define CHECKCHIPGREATEREQUAL(c) (cirrus_chiptype >= c)
90 #define CHECKCHIPNOTEQUAL(c) (cirrus_chiptype != c)
91
92 #define CHIP_HAS_CR1D() \
93 CHECKCHIP4(CLGD5429, CLGD5430, CLGD5434, CLGD5436)
94 #define CHIP_HAS_GRC_AND_GRD() \
95 CHECKCHIP4(CLGD5424, CLGD5426, CLGD5428, CLGD5429)
96 #define CHIP_HAS_GRE() \
97 CHECKCHIP5(CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436)
98 #define CHIP_HAS_GR10_AND_GR11() \
99 CHECKCHIP7(CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436)
100 #define CHIP_HAS_BLTTRANSPARENTCOLOR() \
101 CHECKCHIP2(CLGD5426, CLGD5428)
102 #define CHIP_HAS_PERFTUNINGREGISTER() \
103 CHECKCHIP7(CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436)
104 #define CHIP_HAS_MCLK_REGISTER() \
105 CHECKCHIP9(CLGD5420B, CLGD5422C, CLGD5424, CLGD5426, CLGD5428, \
106 CLGD5429, CLGD5430, CLGD5434, CLGD5436)
107 #define CHIP_HAS_32BIT_DRAM_BUS() \
108 CHECKCHIPGREATEREQUAL(CLGD5420B)
109 #define CHIP_HAS_64BIT_DRAM_BUS() \
110 CHECKCHIP3(CLGD5434, CLGD5436, CLGD7548)
111 #define CHIP_HAS_HIDDENDAC() \
112 CHECKCHIPGREATEREQUAL(CLGD5420B)
113 #define CHIP_HAS_ACCELERATION() \
114 CHECKCHIPNOTEQUAL(CLGD5420B)
115 #define CHIP_HAS_SR17() \
116 CHECKCHIPGREATEREQUAL(CLGD5422)
117 #define CHIP_USE_SR17() \
118 CHECKCHIPGREATEREQUAL(CLGD5429)
119
120
121 /* CLOCK_FACTOR is double the osc freq in kHz (osc = 14.31818 MHz) */
122 #define CLOCK_FACTOR 28636
123
124 /* clock in kHz is (numer * CLOCK_FACTOR / (denom & 0x3E)) >> (denom & 1) */
125 #define CLOCKVAL(n, d) \
126 ((((n) & 0x7F) * CLOCK_FACTOR / ((d) & 0x3E)) >> ((d) & 1))
127
128
129 static int cirrus_init(int, int, int);
130 static void cirrus_unlock(void);
131
132 void __svgalib_cirrusaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels);
133
134 static int cirrus_memory;
135 static int cirrus_chiptype;
136 static int cirrus_chiprev;
137 static int cirrus_pci_linear = 0;
138 static unsigned char actualMCLK, programmedMCLK;
139 static int DRAMbandwidth, DRAMbandwidthLimit;
140
141
142 static CardSpecs *cardspecs;
143
144 #define NU_FIXED_CLOCKS 21
145
146 /* 12.588 clock (0x33, 0x3B) replaced with 12.599 (0x2C, 0x33). */
147
148 static int cirrus_fixed_clocks[NU_FIXED_CLOCKS] =
149 {
150 12599, 18000, 19600,
151 25227, 28325, 31500, 36025, 37747, 39992, 41164,
152 45076, 49867, 64983, 72163, 75000, 80013, 85226, 89998,
153 95019, 100226, 108035
154 };
155
156 static unsigned char fixed_clock_numerator[NU_FIXED_CLOCKS] =
157 {
158 0x2C, 0x27, 0x28,
159 0x4A, 0x5B, 0x42, 0x4E, 0x3A, 0x51, 0x45,
160 0x55, 0x65, 0x76, 0x7E, 0x6E, 0x5F, 0x7D, 0x58,
161 0x49, 0x46, 0x53
162 };
163
164 static unsigned char fixed_clock_denominator[NU_FIXED_CLOCKS] =
165 {
166 0x33, 0x3e, 0x3a,
167 0x2B, 0x2F, 0x1F, 0x3E, 0x17, 0x3A, 0x30,
168 0x36, 0x3A, 0x34, 0x32, 0x2A, 0x22, 0x2A, 0x1C,
169 0x16, 0x14, 0x16
170 };
171
172 /*
173 * It looks like the 5434 palette clock doubling mode doensn't like
174 * clocks like (0x7B, 0x20), whereas (0x53, 0x16) is OK.
175 */
176
177 enum {
178 CLGD5420 = 0, CLGD7548, CLGD5420B, CLGD5422, CLGD5422C, CLGD5424, CLGD5426,
179 CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436
180 };
181
182
__svgalib_cirrus_inlinearmode(void)183 int __svgalib_cirrus_inlinearmode(void)
184 {
185 outb(SEQ_I, 0x07);
186 return (inb(SEQ_D) & 0xf0) != 0;
187 }
188
189 /* Fill in chipset specific mode information */
190
cirrus_getmodeinfo(int mode,vga_modeinfo * modeinfo)191 static void cirrus_getmodeinfo(int mode, vga_modeinfo * modeinfo)
192 {
193 if (modeinfo->bytesperpixel > 0)
194 modeinfo->maxpixels = cirrus_memory * 1024 / modeinfo->bytesperpixel;
195 else
196 /* 16-color SVGA mode */
197 /* Value taken from the air. */
198 modeinfo->maxpixels = cirrus_memory * 2048;
199 modeinfo->maxlogicalwidth = 4088;
200 #if 0
201 if (mode != G320x200x256) {
202 /* No need to check for 320x200x256, we now have a special */
203 /* SVGA-derived 320x200x256 mode that fully supports page */
204 /* flipping etc. */
205 #endif
206 modeinfo->startaddressrange = cirrus_memory * 1024 - 1;
207 modeinfo->haveblit = 0;
208 #if 0
209 } else {
210 modeinfo->startaddressrange = 0xffff;
211 modeinfo->maxpixels = 65536;
212 modeinfo->haveblit = 0;
213 }
214 #endif
215 #if 0 /* Who cares. */
216 if (cirrus_interlaced(mode))
217 modeinfo->flags |= IS_INTERLACED;
218 #endif
219 modeinfo->flags &= ~HAVE_RWPAGE;
220
221 if (modeinfo->bytesperpixel >= 1) {
222 modeinfo->flags |= CAPABLE_LINEAR;
223 if (__svgalib_cirrus_inlinearmode())
224 modeinfo->flags |= IS_LINEAR;
225 }
226 }
227
228
229 /* Read and save chipset-specific registers */
230
cirrus_saveregs(unsigned char regs[])231 static int cirrus_saveregs(unsigned char regs[])
232 {
233 /* int i; */
234
235 /* #ifdef DEBUG
236 printf("Saving Cirrus extended registers.\n");
237 #endif
238 */
239 cirrus_unlock(); /* May be locked again by other programs (e.g. X) */
240
241 #if 0
242 /* Save extended CRTC registers. */
243 for (i = 0; i < 15; i++) { /* was 4 */
244 port_out(0x18 + i, __svgalib_CRT_I);
245 regs[CIRRUSREG_CR(i)] = port_in(__svgalib_CRT_D);
246 }
247
248 /* Save extended graphics registers */
249 for (i = 0; i < 5; i++) { /* was 3 */
250 port_out(0x09 + i, GRA_I);
251 regs[CIRRUSREG_GR(i)] = port_in(GRA_D);
252 }
253
254 /* Save extended sequencer registers. */
255 for (i = 0; i < 27; i++) {
256 port_out(0x05 + i, SEQ_I);
257 regs[CIRRUSREG_SR(i)] = port_in(SEQ_D);
258 }
259 #endif
260
261 /* Save extended CRTC registers. */
262 regs[CIRRUSREG_CR(0x19)] = __svgalib_inCR(0x19);
263 regs[CIRRUSREG_CR(0x1A)] = __svgalib_inCR(0x1A);
264 regs[CIRRUSREG_CR(0x1B)] = __svgalib_inCR(0x1B);
265 if (CHIP_HAS_CR1D())
266 regs[CIRRUSREG_CR(0x1D)] = __svgalib_inCR(0x1D);
267
268 /* Save extended graphics registers. */
269 regs[CIRRUSREG_GR(0x09)] = __svgalib_inGR(0x09);
270 regs[CIRRUSREG_GR(0x0A)] = __svgalib_inGR(0x0A);
271 regs[CIRRUSREG_GR(0x0B)] = __svgalib_inGR(0x0B);
272
273 /* Save extended sequencer registers. */
274 regs[CIRRUS_SR7] = __svgalib_inSR(0x07);
275 regs[CIRRUS_VCLK3NUMERATOR] = __svgalib_inSR(0x0E);
276 regs[CIRRUS_DRAMCONTROL] = __svgalib_inSR(0x0F);
277 if (CHIP_HAS_PERFTUNINGREGISTER())
278 regs[CIRRUS_PERFTUNING] = __svgalib_inSR(0x16);
279 if (CHIP_HAS_SR17())
280 regs[CIRRUS_SR17] = __svgalib_inSR(0x17);
281 regs[CIRRUS_VCLK3DENOMINATOR] = __svgalib_inSR(0x1E);
282 if (CHIP_HAS_MCLK_REGISTER())
283 regs[CIRRUS_MCLKREGISTER] = __svgalib_inSR(0x1F);
284
285 /* Save Hicolor DAC register. */
286 if (CHIP_HAS_HIDDENDAC()) {
287 outb(0x3c6, 0);
288 outb(0x3c6, 0xff);
289 inb(0x3c6);
290 inb(0x3c6);
291 inb(0x3c6);
292 inb(0x3c6);
293 regs[CIRRUSREG_DAC] = inb(0x3c6);
294 }
295 return CIRRUS_TOTAL_REGS - VGA_TOTAL_REGS;
296 }
297
writehicolordac(unsigned char c)298 static void writehicolordac(unsigned char c)
299 {
300 outb(0x3c6, 0);
301 outb(0x3c6, 0xff);
302 inb(0x3c6);
303 inb(0x3c6);
304 inb(0x3c6);
305 inb(0x3c6);
306 outb(0x3c6, c);
307 inb(0x3c8);
308 }
309
310
311 /* Set chipset-specific registers */
312
cirrus_setregs(const unsigned char regs[],int mode)313 static void cirrus_setregs(const unsigned char regs[], int mode)
314 {
315 /* #ifdef DEBUG
316 printf("Setting Cirrus extended registers.\n");
317 #endif
318 */
319 cirrus_unlock(); /* May be locked again by other programs (eg. X) */
320
321 /* Write extended CRTC registers. */
322 __svgalib_outCR(0x19, regs[CIRRUSREG_CR(0x19)]);
323 __svgalib_outCR(0x1A, regs[CIRRUSREG_CR(0x1A)]);
324 __svgalib_outCR(0x1B, regs[CIRRUSREG_CR(0x1B)]);
325 if (CHIP_HAS_CR1D())
326 __svgalib_outCR(0x1D, regs[CIRRUSREG_CR(0x1D)]);
327
328 /* Write extended graphics registers. */
329 __svgalib_outGR(0x09, regs[CIRRUSREG_GR(0x09)]);
330 __svgalib_outGR(0x0A, regs[CIRRUSREG_GR(0x0A)]);
331 __svgalib_outGR(0x0B, regs[CIRRUSREG_GR(0x0B)]);
332 #ifdef SET_ALL
333 if (CHIP_HAS_GRC_AND_GRD()) {
334 __svgalib_outGR(0x0C, regs[CIRRUSREG_GR(0x0C)]);
335 __svgalib_outGR(0x0D, regs[CIRRUSREG_GR(0x0D)]);
336 }
337 if (CHIP_HAS_GRE())
338 __svgalib_outGR(0x0E, regs[CIRRUSREG_GR(0x0E)]);
339 if (CHIP_HAS_GR10_AND_GR11()) {
340 __svgalib_outGR(0x10, regs[CIRRUSREG_GR(0x10)]);
341 __svgalib_outGR(0x11, regs[CIRRUSREG_GR(0x11)]);
342 }
343 if (CHIP_HAS_BLT_REGISTERS()) {
344 int i;
345
346 for (i = 0x20; i <= 0x2A; i++)
347 __svgalib_outGR(i, regs[CIRRUSREG_GR(i)]);
348 for (i = 0x2C; i < 0x2E; i++)
349 __svgalib_outGR(i, regs[CIRRUSREG_GR(i)]);
350 if (CHIP_HAS_BLTWRITEMASK())
351 __svgalib_outGR(0x2D, regs[CIRRUSREG_GR(0x2D)]);
352 __svgalib_outGR(0x30, regs[CIRRUSREG_GR(0x30)]);
353 __svgalib_outGR(0x32, regs[CIRRUSREG_GR(0x32)]);
354 if (CHIP_HAS_BLTTRANSPARENTCOLOR()) {
355 __svgalib_outGR(0x34, regs[CIRRUSREG_GR(0x34)]);
356 __svgalib_outGR(0x35, regs[CIRRUSREG_GR(0x35)]);
357 __svgalib_outGR(0x38, regs[CIRRUSREG_GR(0x38)]);
358 __svgalib_outGR(0x39, regs[CIRRUSREG_GR(0x39)]);
359 }
360 }
361 #endif
362
363 /* Write Truecolor DAC register. */
364 if (CHIP_HAS_HIDDENDAC())
365 writehicolordac(regs[CIRRUS_HIDDENDAC]);
366
367 /* Write extended sequencer registers. */
368
369 /* Be careful to put the sequencer clocking mode in a safe state. */
370 __svgalib_outSR(0x07, (regs[CIRRUS_SR7] & ~0x0F) | 0x01);
371
372 __svgalib_outSR(0x0E, regs[CIRRUS_VCLK3NUMERATOR]);
373 __svgalib_outSR(0x1E, regs[CIRRUS_VCLK3DENOMINATOR]);
374 __svgalib_outSR(0x07, regs[CIRRUS_SR7]);
375 __svgalib_outSR(0x0F, regs[CIRRUS_DRAMCONTROL]);
376 if (CHIP_HAS_PERFTUNINGREGISTER())
377 __svgalib_outSR(0x16, regs[CIRRUS_PERFTUNING]);
378 if (CHIP_USE_SR17())
379 __svgalib_outSR(0x17, regs[CIRRUS_SR17]);
380 if (CHIP_HAS_MCLK_REGISTER())
381 __svgalib_outSR(0x1F, regs[CIRRUS_MCLKREGISTER]);
382 }
383
384
385 /* Return nonzero if mode is available */
386
cirrus_modeavailable(int mode)387 static int cirrus_modeavailable(int mode)
388 {
389 struct info *info;
390 ModeTiming *modetiming;
391 ModeInfo *modeinfo;
392
393 /* CLGD7548 mode 13 is broken. Remove this if when supported */
394 if (mode == G320x200x256 && cirrus_chiptype == CLGD7548)
395 return 0;
396
397 if ((mode < G640x480x256 && mode != G320x200x256)
398 || mode == G720x348x2)
399 return __svgalib_vga_driverspecs.modeavailable(mode);
400
401 info = &__svgalib_infotable[mode];
402 if (cirrus_memory * 1024 < info->ydim * info->xbytes)
403 return 0;
404
405 modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
406
407 modetiming = malloc(sizeof(ModeTiming));
408 if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
409 free(modetiming);
410 free(modeinfo);
411 return 0;
412 }
413 free(modetiming);
414 free(modeinfo);
415
416 return SVGADRV;
417 }
418
419
420 /* Set a mode */
421
422 /* Local, called by cirrus_setmode(). */
423
cirrus_initializemode(unsigned char * moderegs,ModeTiming * modetiming,ModeInfo * modeinfo)424 static void cirrus_initializemode(unsigned char *moderegs,
425 ModeTiming * modetiming, ModeInfo * modeinfo)
426 {
427
428 /* Get current values. */
429 cirrus_saveregs(moderegs);
430
431 /* Set up the standard VGA registers for a generic SVGA. */
432 __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo);
433
434 /* Set up the extended register values, including modifications */
435 /* of standard VGA registers. */
436
437 /* Graphics */
438 moderegs[CIRRUS_GRAPHICSOFFSET1] = 0; /* Reset banks. */
439 moderegs[CIRRUS_GRAPHICSOFFSET2] = 0;
440 moderegs[CIRRUS_GRB] = 0; /* 0x01 enables dual banking. */
441 if (cirrus_memory > 1024)
442 /* Enable 16K granularity. */
443 moderegs[CIRRUS_GRB] |= 0x20;
444 moderegs[VGA_SR2] = 0xFF; /* Plane mask */
445
446 /* CRTC */
447 if (modetiming->VTotal >= 1024 && !(modetiming->flags & INTERLACED))
448 /*
449 * Double the vertical timing. Used for 1280x1024 NI.
450 * The CrtcVTimings have already been adjusted
451 * by __svgalib_getmodetiming() because of the GREATER_1024_DIVIDE_VERT
452 * flag.
453 */
454 moderegs[VGA_CR17] |= 0x04;
455 moderegs[CIRRUS_CR1B] = 0x22;
456 if (cirrus_chiptype >= CLGD5434)
457 /* Clear display start bit 19. */
458 SETBITS(moderegs[CIRRUS_CR1D], 0x80, 0);
459 /* CRTC timing overflows. */
460 moderegs[CIRRUS_CR1A] = 0;
461 SETBITSFROMVALUE(moderegs[CIRRUS_CR1A], 0xC0,
462 modetiming->CrtcVSyncStart + 1, 0x300);
463 SETBITSFROMVALUE(moderegs[CIRRUS_CR1A], 0x30,
464 modetiming->CrtcHSyncEnd, (0xC0 << 3));
465 moderegs[CIRRUS_CR19] = 0; /* Interlaced end. */
466 if (modetiming->flags & INTERLACED) {
467 moderegs[CIRRUS_CR19] =
468 ((modetiming->CrtcHTotal / 8) - 5) / 2;
469 moderegs[CIRRUS_CR1A] |= 0x01;
470 }
471 /* Scanline offset */
472 if (modeinfo->bytesPerPixel == 4) {
473 /* At 32bpp the chip does an extra multiplication by two. */
474 if (cirrus_chiptype >= CLGD5436) {
475 /* Do these chipsets multiply by 4? */
476 moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 5;
477 SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10,
478 modeinfo->lineWidth, 0x2000);
479 }
480 else {
481 moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 4;
482 SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10,
483 modeinfo->lineWidth, 0x1000);
484 }
485 } else if (modeinfo->bitsPerPixel == 4)
486 /* 16 color mode (planar). */
487 moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 1;
488 else {
489 moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 3;
490 SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10,
491 modeinfo->lineWidth, 0x800);
492 }
493
494 /* Clocking */
495 moderegs[VGA_MISCOUTPUT] |= 0x0C; /* Use VCLK3. */
496 moderegs[CIRRUS_VCLK3NUMERATOR] =
497 fixed_clock_numerator[modetiming->selectedClockNo];
498 moderegs[CIRRUS_VCLK3DENOMINATOR] =
499 fixed_clock_denominator[modetiming->selectedClockNo];
500
501 /* DAC register and Sequencer Mode */
502 {
503 unsigned char DAC, SR7;
504 DAC = 0x00;
505 SR7 = 0x00;
506 if (modeinfo->bytesPerPixel > 0)
507 SR7 = 0x01; /* Packed-pixel mode. */
508 if (modeinfo->bytesPerPixel == 2) {
509 int rgbmode;
510 rgbmode = 0; /* 5-5-5 RGB. */
511 if (modeinfo->colorBits == 16)
512 rgbmode = 1; /* Add one for 5-6-5 RGB. */
513 if (cirrus_chiptype >= CLGD5426) {
514 /* Pixel clock (double edge) mode. */
515 DAC = 0xD0 + rgbmode;
516 SR7 = 0x07;
517 } else {
518 /* Single-edge (double VCLK). */
519 DAC = 0xF0 + rgbmode;
520 SR7 = 0x03;
521 }
522 }
523 if (modeinfo->bytesPerPixel >= 3) {
524 /* Set 8-8-8 RGB mode. */
525 DAC = 0xE5;
526 SR7 = 0x05;
527 if (modeinfo->bytesPerPixel == 4)
528 SR7 = 0x09;
529 }
530 #ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING
531 if (modeinfo->bytesPerPixel == 1 && (modetiming->flags & HADJUSTED)) {
532 /* Palette clock doubling mode on 5434 8bpp. */
533 DAC = 0x4A;
534 SR7 = 0x07;
535 }
536 #endif
537 moderegs[CIRRUS_HIDDENDAC] = DAC;
538 moderegs[CIRRUS_SR7] = SR7;
539 }
540
541 /* DRAM control and CRT FIFO */
542 if (cirrus_chiptype >= CLGD5422)
543 /* Enable large CRT FIFO. */
544 moderegs[CIRRUS_DRAMCONTROL] |= 0x20;
545 if (cirrus_memory == 2048 && cirrus_chiptype <= CLGD5429)
546 /* Enable DRAM Bank Select. */
547 moderegs[CIRRUS_DRAMCONTROL] |= 0x80;
548 if (cirrus_chiptype >= CLGD5424) {
549 /* CRT FIFO threshold setting. */
550 unsigned char threshold;
551 threshold = 8;
552 /* if (cirrus_chiptype >= CLGD5434)
553 threshold = 1;*/
554 /* XXX Needs more elaborate setting. */
555 SETBITS(moderegs[CIRRUS_PERFTUNING], 0x0F, threshold);
556 }
557 if (CHIP_HAS_MCLK_REGISTER())
558 if (programmedMCLK != actualMCLK
559 && modeinfo->bytesPerPixel > 0)
560 /* Program higher MCLK for packed-pixel modes. */
561 moderegs[CIRRUS_MCLKREGISTER] = programmedMCLK;
562 }
563
564
565 /* This is the clock mapping function that is put in the CardSpecs. */
566
cirrus_map_clock(int bpp,int pixelclock)567 static int cirrus_map_clock(int bpp, int pixelclock)
568 {
569 if (bpp == 24 && cirrus_chiptype < CLGD5436)
570 /* Most chips need a tripled clock for 24bpp. */
571 return pixelclock * 3;
572 if (bpp == 16 && cirrus_chiptype <= CLGD5424)
573 /* The 5422/24 need to use a doubled clock. */
574 return pixelclock * 2;
575 return pixelclock;
576 }
577
578 /* This is the horizontal CRTC mapping function in the CardSpecs. */
579
cirrus_map_horizontal_crtc(int bpp,int pixelclock,int htiming)580 static int cirrus_map_horizontal_crtc(int bpp, int pixelclock, int htiming)
581 {
582 #ifdef ALWAYS_USE_5434_PALETTE_CLOCK_DOUBLING
583 if (bpp == 8 && cirrus_chiptype >= CLGD5434)
584 #else
585 if (bpp == 8 && cirrus_chiptype >= CLGD5434 && pixelclock > 86000)
586 #endif
587 /* 5434 palette clock doubling mode; divide CRTC by 2. */
588 return htiming / 2;
589 /* Otherwise, don't change. */
590 return htiming;
591 }
592
593 static void init_acceleration_specs_for_mode(AccelSpecs * accelspecs, int bpp,
594 int width_in_pixels);
595
cirrus_setmode(int mode,int prv_mode)596 static int cirrus_setmode(int mode, int prv_mode)
597 {
598 unsigned char *moderegs;
599 ModeTiming *modetiming;
600 ModeInfo *modeinfo;
601
602 if ((mode < G640x480x256 && mode != G320x200x256)
603 || mode == G720x348x2) {
604 __svgalib_clear_accelspecs(__svgalib_driverspecs->accelspecs);
605 /* Let the standard VGA driver set standard VGA modes */
606 /* But first reset an Cirrus extended register that */
607 /* an old XFree86 Trident probe corrupts. */
608 outw(CRT_IC, 0x4a0b);
609 return __svgalib_vga_driverspecs.setmode(mode, prv_mode);
610 }
611 if (!cirrus_modeavailable(mode))
612 return 1;
613
614 modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
615
616 modetiming = malloc(sizeof(ModeTiming));
617 if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
618 free(modetiming);
619 free(modeinfo);
620 return 1;
621 }
622 moderegs = malloc(CIRRUS_TOTAL_REGS);
623
624 cirrus_initializemode(moderegs, modetiming, modeinfo);
625 free(modetiming);
626
627 __svgalib_setregs(moderegs); /* Set standard regs. */
628 cirrus_setregs(moderegs, mode); /* Set extended regs. */
629 free(moderegs);
630
631 __svgalib_InitializeAcceleratorInterface(modeinfo);
632
633 init_acceleration_specs_for_mode(__svgalib_driverspecs->accelspecs,
634 modeinfo->bitsPerPixel,
635 modeinfo->lineWidth / modeinfo->bytesPerPixel);
636
637 __svgalib_cirrusaccel_init(__svgalib_driverspecs->accelspecs,
638 modeinfo->bitsPerPixel,
639 modeinfo->lineWidth / modeinfo->bytesPerPixel);
640
641 free(modeinfo);
642 return 0;
643 }
644
645
646 /* Unlock chipset-specific registers */
647
cirrus_unlock(void)648 static void cirrus_unlock(void)
649 {
650 int vgaIOBase, temp;
651
652 /* Are we Mono or Color? */
653 vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
654
655 outb(SEQ_I, 0x06);
656 outb(SEQ_D, 0x12); /* unlock cirrus special */
657
658 /* Put the Vert. Retrace End Reg in temp */
659
660 outb(vgaIOBase + 4, 0x11);
661 temp = inb(vgaIOBase + 5);
662
663 /* Put it back with PR bit set to 0 */
664 /* This unprotects the 0-7 CRTC regs so */
665 /* they can be modified, i.e. we can set */
666 /* the timing. */
667
668 outb(vgaIOBase + 5, temp & 0x7F);
669 }
670
671
672 /* Relock chipset-specific registers */
673 /* (currently not used) */
674
cirrus_lock(void)675 static void cirrus_lock(void)
676 {
677 outb(SEQ_I, 0x06);
678 outb(SEQ_D, 0x0F); /* relock cirrus special */
679 }
680
681
682 /* Indentify chipset, initialize and return non-zero if detected */
683
cirrus_test(void)684 static int cirrus_test(void)
685 {
686 int oldlockreg;
687 int lockreg;
688
689 outb(SEQ_I, 0x06);
690 oldlockreg = inb(SEQ_D);
691
692 cirrus_unlock();
693
694 /* If it's a Cirrus at all, we should be */
695 /* able to read back the lock register */
696
697 outb(SEQ_I, 0x06);
698 lockreg = inb(SEQ_D);
699
700 /* Ok, if it's not 0x12, we're not a Cirrus542X. */
701 if (lockreg != 0x12) {
702 outb(SEQ_I, 0x06);
703 outb(SEQ_D, oldlockreg);
704 return 0;
705 }
706 /* The above check seems to be weak, so we also check the chip ID. */
707
708 outb(__svgalib_CRT_I, 0x27);
709 switch (inb(__svgalib_CRT_D) >> 2) {
710 case 0x22:
711 case 0x23:
712 case 0x24:
713 case 0x25:
714 case 0x26:
715 case 0x27: /* 5429 */
716 case 0x28: /* 5430 */
717 case 0x2A: /* 5434 */
718 case 0x2B: /* 5436 */
719 case 0x2E: /* 5446 */
720 case 0x0E: /* 7548 */
721 break;
722 default:
723 outb(SEQ_I, 0x06);
724 outb(SEQ_D, oldlockreg);
725 return 0;
726 }
727
728 if (cirrus_init(0, 0, 0))
729 return 0; /* failure */
730 return 1;
731 }
732
733
734 /* Bank switching function -- set 64K page number */
735
cirrus_setpage_2M(int page)736 static void cirrus_setpage_2M(int page)
737 {
738 /* Cirrus banking register has been set to 16K granularity */
739 outw(GRA_I, (page << 10) + 0x09);
740 }
741
cirrus_setpage(int page)742 static void cirrus_setpage(int page)
743 {
744 /* default 4K granularity */
745 outw(GRA_I, (page << 12) + 0x09);
746 }
747
748
749 /* No r/w paging */
cirrus_setrdpage(int page)750 static void cirrus_setrdpage(int page)
751 {
752 }
cirrus_setwrpage(int page)753 static void cirrus_setwrpage(int page)
754 {
755 }
756
757
758 /* Set display start address (not for 16 color modes) */
759 /* Cirrus supports any address in video memory (up to 2Mb) */
760
cirrus_setdisplaystart(int address)761 static void cirrus_setdisplaystart(int address)
762 {
763 outw(CRT_IC, 0x0d + ((address >> 2) & 0x00ff) * 256); /* sa2-sa9 */
764 outw(CRT_IC, 0x0c + ((address >> 2) & 0xff00)); /* sa10-sa17 */
765 inb(0x3da); /* set ATC to addressing mode */
766 outb(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */
767 /* Cirrus specific bits 0,1 and 18,19,20: */
768 outb(ATT_IW, (inb(ATT_R) & 0xf0) | (address & 3));
769 /* write sa0-1 to bits 0-1; other cards use bits 1-2 */
770 outb(CRT_IC, 0x1b);
771 outb(CRT_DC, (inb(CRT_DC) & 0xf2)
772 | ((address & 0x40000) >> 18) /* sa18: write to bit 0 */
773 |((address & 0x80000) >> 17) /* sa19: write to bit 2 */
774 |((address & 0x100000) >> 17)); /* sa20: write to bit 3 */
775 outb(CRT_IC, 0x1d);
776 if (cirrus_memory > 2048)
777 outb(CRT_DC, (inb(CRT_DC) & 0x7f)
778 | ((address & 0x200000) >> 14)); /* sa21: write to bit 7 */
779 }
780
781
782 /* Set logical scanline length (usually multiple of 8) */
783 /* Cirrus supports multiples of 8, up to 4088 */
784
cirrus_setlogicalwidth(int width)785 static void cirrus_setlogicalwidth(int width)
786 {
787 outw(CRT_IC, 0x13 + (width >> 3) * 256); /* lw3-lw11 */
788 outb(CRT_IC, 0x1b);
789 outb(CRT_DC, (inb(CRT_DC) & 0xef) | ((width & 0x800) >> 7));
790 /* write lw12 to bit 4 of Sequencer reg. 0x1b */
791 }
792
cirrus_setlinear(int addr)793 static void cirrus_setlinear(int addr)
794 {
795 int val;
796 outb(SEQ_I, 0x07);
797 val = inb(SEQ_D);
798 outb(SEQ_D, (val & 0x0f) | (addr << 4));
799 }
800
cirrus_linear(int op,int param)801 static int cirrus_linear(int op, int param)
802 {
803 if (op == LINEAR_ENABLE) {
804 cirrus_setlinear(0xE);
805 return 0;
806 }
807 if (op == LINEAR_DISABLE) {
808 cirrus_setlinear(0);
809 return 0;
810 }
811 if (cirrus_chiptype >= CLGD5424 && cirrus_chiptype <= CLGD5429) {
812 if (op == LINEAR_QUERY_BASE) {
813 if (param == 0)
814 return 0xE00000; /* 14MB */
815 /*
816 * Trying 64MB on a system with 16MB of memory is unsafe if the
817 * card maps at 14MB. 14 MB was not attempted because of the
818 * system memory check in vga_setlinearaddressing(). However,
819 * linear addressing is enabled when looking at 64MB, causing a
820 * clash between video card and system memory at 14MB.
821 */
822 if (__svgalib_physmem() <= 13 * 1024 * 1024) {
823 if (param == 1)
824 return 0x4000000; /* 64MB */
825 if (param == 2)
826 return 0x4E00000; /* 78MB */
827 if (param == 3)
828 return 0x2000000; /* 32MB */
829 if (param == 4)
830 return 0x3E00000; /* 62MB */
831 }
832 return -1;
833 }
834 }
835 if (cirrus_chiptype >= CLGD5430) {
836 if (op == LINEAR_QUERY_BASE) {
837 if(cirrus_pci_linear)return cirrus_pci_linear;
838 if (param == 0)
839 return 0x04000000; /* 64MB */
840 if (param == 1)
841 return 0x80000000; /* 2048MB */
842 if (param == 2)
843 return 0x02000000; /* 32MB */
844 if (param == 3)
845 return 0x08000000; /* 128MB */
846 /* While we're busy, try some common PCI */
847 /* motherboard-configured addresses as well. */
848 /* We only read, so should be safe. */
849 if (param == 4)
850 return 0xA0000000;
851 if (param == 5)
852 return 0xA8000000;
853 if (param == 6)
854 return 0xE0000000;
855 if (param == 7)
856 return 0XFE000000;
857 /*
858 * Some PCI/VL motherboards only seem to let the
859 * VL slave slot respond at addresses >= 2048MB.
860 */
861 if (param == 8)
862 return 0x84000000;
863 if (param == 9)
864 return 0x88000000;
865 return -1;
866 }
867 }
868 if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY)
869 return 0; /* No granularity or range. */
870 else
871 return -1; /* Unknown function. */
872 }
873
874
875 /* Function table (exported) */
876
877 DriverSpecs __svgalib_cirrus_driverspecs =
878 {
879 cirrus_saveregs,
880 cirrus_setregs,
881 cirrus_unlock,
882 cirrus_lock,
883 cirrus_test,
884 cirrus_init,
885 cirrus_setpage,
886 cirrus_setrdpage,
887 cirrus_setwrpage,
888 cirrus_setmode,
889 cirrus_modeavailable,
890 cirrus_setdisplaystart,
891 cirrus_setlogicalwidth,
892 cirrus_getmodeinfo,
893 0, /* old blit funcs */
894 0,
895 0,
896 0,
897 0,
898 0, /* ext_set */
899 0, /* accel */
900 cirrus_linear,
901 NULL, /* Accelspecs */
902 NULL, /* Emulation */
903 };
904
905
906 /* Initialize chipset (called after detection) */
907
908 static char *cirrus_chipname[] =
909 {
910 "5420", "7548", "5420-75QC-B", "5422", "5422-80QC-C", "5424", "5426",
911 "5428", "5429", "5430", "5434", "5436"
912 };
913
914 static unsigned char fixedMCLK[4] =
915 {0x1c, 0x19, 0x17, 0x15};
916
cirrus_init(int force,int par1,int par2)917 static int cirrus_init(int force, int par1, int par2)
918 {
919 unsigned char v;
920 cirrus_unlock();
921 if (force) {
922 cirrus_memory = par1;
923 cirrus_chiptype = par2;
924 } else {
925 unsigned char partstatus;
926 outb(__svgalib_CRT_I, 0x27);
927 cirrus_chiptype = inb(__svgalib_CRT_D) >> 2;
928 cirrus_chiprev = 0;
929 partstatus = __svgalib_inCR(0x25);
930 switch (cirrus_chiptype) {
931 case 0x22:
932 cirrus_chiptype = CLGD5420;
933 #if 0
934 /* Check for CL-GD5420-75QC-B. */
935 /* It has a Hidden-DAC register. */
936 outb(0x3C6, 0x00);
937 outb(0x3C6, 0xFF);
938 inb(0x3C6);
939 inb(0x3c6);
940 inb(0x3C6);
941 inb(0x3C6);
942 if (inb(0x3C6) != 0xFF)
943 cirrus_chiptype = CLGD5420B;
944 #endif
945 break;
946 case 0x23:
947 cirrus_chiptype = CLGD5422;
948 break;
949 case 0x24:
950 cirrus_chiptype = CLGD5426;
951 break;
952 case 0x25:
953 cirrus_chiptype = CLGD5424;
954 /*
955 * Some CL-GD5422's ID as CL-GD5424.
956 * Check for writability of GRC.
957 */
958 v = __svgalib_inGR(0x0C);
959 __svgalib_outGR(0x0C, 0x55);
960 if (__svgalib_inGR(0x0C) != 0x55)
961 cirrus_chiptype = CLGD5422;
962 __svgalib_outGR(0x0C, v);
963 break;
964 case 0x26:
965 cirrus_chiptype = CLGD5428;
966 break;
967 case 0x27:
968 cirrus_chiptype = CLGD5429;
969 break;
970 case 0x28:
971 cirrus_chiptype = CLGD5430;
972 break;
973 case 0x2A:
974 cirrus_chiptype = CLGD5434;
975 if ((partstatus & 0xC0) == 0xC0)
976 /* Rev. E, can do 60 MHz MCLK. */
977 cirrus_chiprev = 1;
978 break;
979 case 0x2B:
980 cirrus_chiptype = CLGD5436;
981 break;
982 case 0x2E:
983 /* Treat 5446 as 5436. */
984 cirrus_chiptype = CLGD5436;
985 break;
986 case 0x0E:
987 cirrus_chiptype = CLGD7548;
988 break;
989 default:
990 printf("Unknown Cirrus chip %2x.\n",
991 cirrus_chiptype);
992 return -1;
993 }
994
995 #if 0
996 if (cirrus_chiptype == CLGD5422) {
997 /* Rev. C has programmable MCLK register; */
998 /* check for it. */
999 /* This check is wrong. */
1000 if (__svgalib_inSR(0x1F) != 0xFF)
1001 cirrus_chiptype = CLGD5422C;
1002 }
1003 #endif
1004
1005 /* Now determine the amount of memory. */
1006 outb(SEQ_I, 0x0a); /* read memory register */
1007 /* This depends on the BIOS having set a scratch register. */
1008 v = inb(SEQ_D);
1009 cirrus_memory = 256 << ((v >> 3) & 3);
1010
1011 /* Determine memory the correct way for the 543x, and
1012 * for the 542x if the amount seems incorrect. */
1013 if (cirrus_chiptype >= CLGD5430 || (cirrus_memory <= 256
1014 && cirrus_chiptype != CLGD5420)) {
1015 unsigned char SRF;
1016 cirrus_memory = 512;
1017 outb(SEQ_I, 0x0f);
1018 SRF = inb(SEQ_D);
1019 if (SRF & 0x10)
1020 /* 32-bit DRAM bus. */
1021 cirrus_memory *= 2;
1022 if ((SRF & 0x18) == 0x18)
1023 /* 64-bit DRAM data bus width; assume 2MB. */
1024 /* Also indicates 2MB memory on the 5430. */
1025 cirrus_memory *= 2;
1026 if (cirrus_chiptype != CLGD5430 && (SRF & 0x80))
1027 /* If DRAM bank switching is enabled, there */
1028 /* must be twice as much memory installed. */
1029 /* (4MB on the 5434) */
1030 cirrus_memory *= 2;
1031 }
1032 }
1033 if (__svgalib_driver_report) {
1034 printf("Using Cirrus Logic GD542x/3x driver (%s, %dK).\n",
1035 cirrus_chipname[cirrus_chiptype], cirrus_memory);
1036 }
1037 if (CHIP_HAS_MCLK_REGISTER())
1038 actualMCLK = __svgalib_inSR(0x1F) & 0x3F;
1039 else {
1040 actualMCLK = fixedMCLK[__svgalib_inSR(0x0F) & 3];
1041 }
1042 programmedMCLK = actualMCLK;
1043 if (cirrus_chiptype == CLGD5434 && cirrus_chiprev > 0)
1044 /* 5434 rev. E+ supports 60 MHz in graphics modes. */
1045 programmedMCLK = 0x22;
1046 DRAMbandwidth = 14318 * (int) programmedMCLK / 16;
1047 if (cirrus_memory >= 512)
1048 /* At least 16-bit DRAM bus. */
1049 DRAMbandwidth *= 2;
1050 if (cirrus_memory >= 1024 && CHIP_HAS_32BIT_DRAM_BUS())
1051 /* At least 32-bit DRAM bus. */
1052 DRAMbandwidth *= 2;
1053 if (cirrus_memory >= 2048 && CHIP_HAS_64BIT_DRAM_BUS())
1054 /* 64-bit DRAM bus. */
1055 DRAMbandwidth *= 2;
1056 /*
1057 * Calculate highest acceptable DRAM bandwidth to be taken up
1058 * by screen refresh. Satisfies
1059 * total bandwidth >= refresh bandwidth * 1.1
1060 */
1061 DRAMbandwidthLimit = (DRAMbandwidth * 10) / 11;
1062
1063 if(cirrus_chiptype>=CLGD5430) {
1064 int i;
1065
1066 i=(__svgalib_inSR(0x17)>>3)&7;
1067 if(i==4) {
1068 unsigned long buf[64];
1069 int found, _ioperm=0;
1070
1071 if(getenv("IOPERM")==NULL) {
1072 _ioperm=1;
1073 iopl(3);
1074 };
1075 found=__svgalib_pci_find_vendor_vga(0x1013,buf,0);
1076 if(_ioperm)iopl(0);
1077 if(!found)cirrus_pci_linear=buf[4]&0xffff0000;
1078 };
1079 };
1080 /* begin: Initialize card specs. */
1081 cardspecs = malloc(sizeof(CardSpecs));
1082 cardspecs->videoMemory = cirrus_memory;
1083 /*
1084 * First determine clock limits for the chip (DAC), then
1085 * adjust them according to the available DRAM bandwidth.
1086 * For 32-bit DRAM cards the 16bpp clock limit is initially
1087 * set very high, but they are cut down by the DRAM bandwidth
1088 * check.
1089 */
1090 cardspecs->maxPixelClock4bpp = 75000; /* 5420 */
1091 cardspecs->maxPixelClock8bpp = 45000; /* 5420 */
1092 cardspecs->maxPixelClock16bpp = 0; /* 5420 */
1093 cardspecs->maxPixelClock24bpp = 0;
1094 cardspecs->maxPixelClock32bpp = 0;
1095 if (cirrus_chiptype == CLGD5420B) {
1096 /*
1097 * CL-GD5420-75QC-B
1098 * Deviating chip, may be used in cheap ISA cards.
1099 * 32-bit DRAM bus and Truecolor DAC but cannot do
1100 * LUT > 45 MHz, and maybe has less acceleration.
1101 */
1102 cardspecs->maxPixelClock16bpp = 75000 / 2;
1103 cardspecs->maxPixelClock24bpp = 25175;
1104 }
1105 if (cirrus_chiptype >= CLGD5422) {
1106 /* 5422/24/26/28 have VCLK spec of 80 MHz. */
1107 cardspecs->maxPixelClock4bpp = 80000;
1108 cardspecs->maxPixelClock8bpp = 80000;
1109 if (cirrus_chiptype >= CLGD5426)
1110 /* DRAM bandwidth will be limiting factor. */
1111 cardspecs->maxPixelClock16bpp = 80000;
1112 else
1113 /* Clock / 2 16bpp requires 32-bit DRAM bus. */
1114 if (cirrus_memory >= 1024)
1115 cardspecs->maxPixelClock16bpp = 80000 / 2;
1116 /* Clock / 3 24bpp requires 32-bit DRAM bus. */
1117 if (cirrus_memory >= 1024)
1118 cardspecs->maxPixelClock24bpp = 80000 / 3;
1119 }
1120 if (cirrus_chiptype >= CLGD5429) {
1121 /* 5429, 5430, 5434 have VCLK spec of 86 MHz. */
1122 cardspecs->maxPixelClock4bpp = 86000;
1123 cardspecs->maxPixelClock8bpp = 86000;
1124 cardspecs->maxPixelClock16bpp = 86000;
1125 if (cirrus_memory >= 1024)
1126 cardspecs->maxPixelClock24bpp = 86000 / 3;
1127 }
1128 if (cirrus_chiptype == CLGD5434) {
1129 #ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING
1130 cardspecs->maxPixelClock8bpp = 108300;
1131 if (cirrus_chiprev > 0)
1132 /* 5434 rev E+ */
1133 cardspecs->maxPixelClock8bpp = 135300;
1134 #endif
1135 if (cirrus_memory >= 2048)
1136 /* 32bpp requires 64-bit DRAM bus. */
1137 cardspecs->maxPixelClock32bpp = 86000;
1138 }
1139 if (cirrus_chiptype >=CLGD5436) {
1140 #ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING
1141 cardspecs->maxPixelClock8bpp = 135300;
1142 #endif
1143 if (cirrus_memory >= 2048)
1144 /* 32bpp requires 64-bit DRAM bus. */
1145 cardspecs->maxPixelClock32bpp = 86000;
1146 }
1147
1148 cardspecs->maxPixelClock8bpp = min(cardspecs->maxPixelClock8bpp,
1149 DRAMbandwidthLimit);
1150 cardspecs->maxPixelClock16bpp = min(cardspecs->maxPixelClock16bpp,
1151 DRAMbandwidthLimit / 2);
1152 cardspecs->maxPixelClock24bpp = min(cardspecs->maxPixelClock24bpp,
1153 DRAMbandwidthLimit / 3);
1154 cardspecs->maxPixelClock32bpp = min(cardspecs->maxPixelClock32bpp,
1155 DRAMbandwidthLimit / 4);
1156 cardspecs->flags = INTERLACE_DIVIDE_VERT | GREATER_1024_DIVIDE_VERT;
1157 /* Initialize clocks (only fixed set for now). */
1158 cardspecs->nClocks = NU_FIXED_CLOCKS;
1159 cardspecs->clocks = cirrus_fixed_clocks;
1160 cardspecs->mapClock = cirrus_map_clock;
1161 cardspecs->mapHorizontalCrtc = cirrus_map_horizontal_crtc;
1162 cardspecs->maxHorizontalCrtc = 2040;
1163 /* Disable 16-color SVGA modes (don't work correctly). */
1164 cardspecs->maxPixelClock4bpp = 0;
1165 /* end: Initialize card specs. */
1166
1167 #if 0
1168 /* begin: Initialize driver options. */
1169 register_option(5434 _VLB_ZERO_WAITSTATE);
1170 register_option(50 MHZ_MCLK);
1171 register_option(55 MHZ_MCLK);
1172 register_option(60 MHZ_MCLK);
1173 register_option(542 X_VLB_NORMAL_WAITSTATES);
1174 register_option(CRT_FIFO_CONSERVATIVE);
1175 register_option(CRT_FIFO_AGGRESSIVE);
1176 register_option(NO_ACCELERATION);
1177 register_option(NO_MMIO);
1178 /* end: Initialize driver options. */
1179 #endif
1180
1181 /* Initialize accelspecs structure. */
1182 __svgalib_cirrus_driverspecs.accelspecs = malloc(sizeof(AccelSpecs));
1183 __svgalib_clear_accelspecs(__svgalib_cirrus_driverspecs.accelspecs);
1184 __svgalib_cirrus_driverspecs.accelspecs->flags = ACCELERATE_ANY_LINEWIDTH;
1185 /* Set up the correct paging routine */
1186 if (cirrus_memory >= 2048)
1187 __svgalib_cirrus_driverspecs.__svgalib_setpage =
1188 cirrus_setpage_2M;
1189
1190 __svgalib_driverspecs = &__svgalib_cirrus_driverspecs;
1191
1192 __svgalib_banked_mem_base=0xa0000;
1193 __svgalib_banked_mem_size=0x10000;
1194 __svgalib_linear_mem_base=cirrus_pci_linear;
1195 __svgalib_linear_mem_size=cirrus_memory*0x400;
1196 __svgalib_mmio_size=32768;
1197 __svgalib_mmio_base=0xb8000;
1198 return 0;
1199 }
1200
1201
1202
1203 /* Some information on the accelerated features of the 5426,
1204 derived from the Databook.
1205
1206 port index
1207
1208 Addresses have 21 bits (2Mb of memory).
1209 GRA_I, 0x28 bits 0-7 of the destination address
1210 GRA_I, 0x29 bits 8-15
1211 GRA_I, 0x2a bits 16-20
1212
1213 GRA_I, 0x2c bits 0-7 of the source address
1214 GRA_I, 0x2d bits 8-15
1215 GRA_I, 0x2e bits 16-20
1216
1217 Maximum pitch is 4095.
1218 GRA_I, 0x24 bits 0-7 of the destination pitch (screen width)
1219 GRA_I, 0x25 bits 8-11
1220
1221 GRA_I, 0x26 bits 0-7 of the source pitch (screen width)
1222 GRA_I, 0x27 bits 8-11
1223
1224 Maximum width is 2047.
1225 GRA_I, 0x20 bits 0-7 of the box width - 1
1226 GRA_I, 0x21 bits 8-10
1227
1228 Maximum height is 1023.
1229 GRA_I, 0x22 bits 0-7 of the box height - 1
1230 GRA_I, 0x23 bits 8-9
1231
1232 GRA_I, 0x30 BLT mode
1233 bit 0: direction (0 = down, 1 = up)
1234 bit 1: destination
1235 bit 2: source (0 = video memory, 1 = system memory)
1236 bit 3: enable transparency compare
1237 bit 4: 16-bit color expand/transparency
1238 bit 6: 8x8 pattern copy
1239 bit 7: enable color expand
1240
1241 0x31 BLT status
1242 bit 0: busy
1243 bit 1: start operation (1)/suspend (0)
1244 bit 2: reset
1245 bit 3: set while blit busy/suspended
1246
1247 0x32 BLT raster operation
1248 0x00 black
1249 0x01 white
1250 0x0d copy source
1251 0xd0 copy inverted source
1252 0x0b invert destination
1253 0x05 logical AND
1254 0x6d logical OR (paint)
1255 0x59 XOR
1256
1257 0x34 BLT transparent color
1258 0x35 high byte
1259
1260 GRA_I, 0x00 background color (for color expansion)
1261 GRA_I, 0x01 foreground color
1262 GRA_I, 0x10 high byte of background color for 16-bit pixels
1263 GRA_I, 0x11 high byte of foreground color
1264
1265 GRA_I, 0x0b bit 1: enable BY8 addressing
1266 SEQ_I, 0x02 8-bit plane mask for BY8 (corresponds to 8 pixels)
1267 (write mode 1, 4, 5)
1268 SEQ_D, 0x05 bits 0-2: VGA write mode
1269 extended write mode 4: write up to 8 pixels in
1270 foreground color (BY8)
1271 extended write mode 5: write 8 pixels in foreground/
1272 background color (BY8)
1273 This may also work in normal non-BY8 packed-pixel mode.
1274
1275 When doing blits from system memory to video memory, pixel data
1276 can apparently be written to any video address in 16-bit words, with
1277 the each scanline padded to 4-byte alignment. This is handy because
1278 the chip handles line transitions and alignment automatically (and
1279 can do, for example, masking).
1280
1281 The pattern copy requires an 8x8 pattern (64 pixels) at the source
1282 address in video memory, and fills a box with specified size and
1283 destination address with the pattern. This is in fact the way to do
1284 solid fills.
1285
1286 mode pattern
1287 Color Expansion 8 bytes (monochrome bitmap)
1288 8-bit pixels 64 bytes
1289 16-bit pixels 128 bytes
1290
1291 */
1292
1293
1294
1295 /* Cirrus Logic acceleration functions implementation. */
1296
1297 /* BitBLT modes. */
1298
1299 #define FORWARDS 0x00
1300 #define BACKWARDS 0x01
1301 #define SYSTEMDEST 0x02
1302 #define SYSTEMSRC 0x04
1303 #define TRANSPARENCYCOMPARE 0x08
1304 #define PIXELWIDTH16 0x10
1305 #define PIXELWIDTH32 0x30 /* 543x only. */
1306 #define PATTERNCOPY 0x40
1307 #define COLOREXPAND 0x80
1308
1309 /* Macros for normal I/O BitBLT register access. */
1310
1311 #define SETSRCADDR(addr) \
1312 outw(GRA_I, (((addr) & 0x000000FF) << 8) | 0x2C); \
1313 outw(GRA_I, (((addr) & 0x0000FF00)) | 0x2D); \
1314 outw(GRA_I, (((addr) & 0x003F0000) >> 8) | 0x2E);
1315
1316 #define SETDESTADDR(addr) \
1317 outw(GRA_I, (((addr) & 0x000000FF) << 8) | 0x28); \
1318 outw(GRA_I, (((addr) & 0x0000FF00)) | 0x29); \
1319 outw(GRA_I, (((addr) & 0x003F0000) >> 8) | 0x2A);
1320
1321 /* Pitch: the 5426 goes up to 4095, the 5434 can do 8191. */
1322
1323 #define SETDESTPITCH(pitch) \
1324 outw(GRA_I, (((pitch) & 0x000000FF) << 8) | 0x24); \
1325 outw(GRA_I, (((pitch) & 0x00001F00)) | 0x25);
1326
1327 #define SETSRCPITCH(pitch) \
1328 outw(GRA_I, (((pitch) & 0x000000FF) << 8) | 0x26); \
1329 outw(GRA_I, (((pitch) & 0x00001F00)) | 0x27);
1330
1331 /* Width: the 5426 goes up to 2048, the 5434 can do 8192. */
1332
1333 #define SETWIDTH(width) \
1334 outw(GRA_I, ((((width) - 1) & 0x000000FF) << 8) | 0x20); \
1335 outw(GRA_I, ((((width) - 1) & 0x00001F00)) | 0x21);
1336
1337 /* Height: the 5426 goes up to 1024, the 5434 can do 2048. */
1338 /* It appears many 5434's only go up to 1024. */
1339
1340 #define SETHEIGHT(height) \
1341 outw(GRA_I, ((((height) - 1) & 0x000000FF) << 8) | 0x22); \
1342 outw(GRA_I, (((height) - 1) & 0x00000700) | 0x23);
1343
1344 #define SETBLTMODE(m) \
1345 outw(GRA_I, ((m) << 8) | 0x30);
1346
1347 #define SETBLTWRITEMASK(m) \
1348 outw(GRA_I, ((m) << 8) | 0x2F);
1349
1350 #define SETTRANSPARENCYCOLOR(c) \
1351 outw(GRA_I, ((c) << 8) | 0x34);
1352
1353 #define SETTRANSPARENCYCOLOR16(c) \
1354 outw(GRA_I, ((c) << 8) | 0x34); \
1355 outw(GRA_I, (c & 0xFF00) | 0x35);
1356
1357 #define SETTRANSPARENCYCOLORMASK16(m) \
1358 outw(GRA_I, ((m) << 8) | 0x38); \
1359 outw(GRA_I, ((m) & 0xFF00) | 0x39);
1360
1361 #define SETROP(rop) \
1362 outw(GRA_I, ((rop) << 8) | 0x32);
1363
1364 #define SETFOREGROUNDCOLOR(c) \
1365 outw(GRA_I, 0x01 + ((c) << 8));
1366
1367 #define SETBACKGROUNDCOLOR(c) \
1368 outw(GRA_I, 0x00 + ((c) << 8));
1369
1370 #define SETFOREGROUNDCOLOR16(c) \
1371 outw(GRA_I, 0x01 + ((c) << 8)); \
1372 outw(GRA_I, 0x11 + ((c) & 0xFF00));
1373
1374 #define SETBACKGROUNDCOLOR16(c) \
1375 outw(GRA_I, 0x00 + ((c) << 8)); \
1376 outw(GRA_I, 0x10 + ((c) & 0xFF00)); \
1377
1378 #define SETFOREGROUNDCOLOR32(c) \
1379 outw(GRA_I, 0x01 + ((c) << 8)); \
1380 outw(GRA_I, 0x11 + ((c) & 0xFF00)); \
1381 outw(GRA_I, 0x13 + (((c) & 0xFf0000) >> 8)); \
1382 outw(GRA_I, 0x15 + (((unsigned int)(c) & 0xFF000000) >> 16));
1383
1384 #define SETBACKGROUNDCOLOR32(c) \
1385 outw(GRA_I, 0x00 + ((c) << 8)); \
1386 outw(GRA_I, 0x10 + ((c) & 0xFF00)); \
1387 outw(GRA_I, 0x12 + (((c) & 0xFF0000) >> 8)); \
1388 outw(GRA_I, 0x14 + (((unsigned int)(c) & 0xFF000000) >> 16));
1389
1390 #define STARTBLT() { \
1391 unsigned char tmp; \
1392 outb(GRA_I, 0x31); \
1393 tmp = inb(GRA_D); \
1394 outb(GRA_D, tmp | 0x02); \
1395 }
1396
1397 #define BLTBUSY(s) { \
1398 outb(GRA_I, 0x31); \
1399 s = inb(GRA_D) & 1; \
1400 }
1401
1402 #define WAITUNTILFINISHED() \
1403 for (;;) { \
1404 int busy; \
1405 BLTBUSY(busy); \
1406 if (!busy) \
1407 break; \
1408 }
1409
1410
1411 /* Macros for memory-mapped I/O BitBLT register access. */
1412
1413 /* MMIO addresses (offset from 0xb8000). */
1414
1415 #define MMIOBACKGROUNDCOLOR 0x00
1416 #define MMIOFOREGROUNDCOLOR 0x04
1417 #define MMIOWIDTH 0x08
1418 #define MMIOHEIGHT 0x0A
1419 #define MMIODESTPITCH 0x0C
1420 #define MMIOSRCPITCH 0x0E
1421 #define MMIODESTADDR 0x10
1422 #define MMIOSRCADDR 0x14
1423 #define MMIOBLTWRITEMASK 0x17
1424 #define MMIOBLTMODE 0x18
1425 #define MMIOROP 0x1A
1426 #define MMIOBLTSTATUS 0x40
1427
1428 #define MMIOSETDESTADDR(addr) \
1429 *(unsigned int *)(MMIO_POINTER + MMIODESTADDR) = addr;
1430
1431 #define MMIOSETSRCADDR(addr) \
1432 *(unsigned int *)(MMIO_POINTER + MMIOSRCADDR) = addr;
1433
1434 /* Pitch: the 5426 goes up to 4095, the 5434 can do 8191. */
1435
1436 #define MMIOSETDESTPITCH(pitch) \
1437 *(unsigned short *)(MMIO_POINTER + MMIODESTPITCH) = pitch;
1438
1439 #define MMIOSETSRCPITCH(pitch) \
1440 *(unsigned short *)(MMIO_POINTER + MMIOSRCPITCH) = pitch;
1441
1442 /* Width: the 5426 goes up to 2048, the 5434 can do 8192. */
1443
1444 #define MMIOSETWIDTH(width) \
1445 *(unsigned short *)(MMIO_POINTER + MMIOWIDTH) = (width) - 1;
1446
1447 /* Height: the 5426 goes up to 1024, the 5434 can do 2048. */
1448
1449 #define MMIOSETHEIGHT(height) \
1450 *(unsigned short *)(MMIO_POINTER + MMIOHEIGHT) = (height) - 1;
1451
1452 #define MMIOSETBLTMODE(m) \
1453 *(unsigned char *)(MMIO_POINTER + MMIOBLTMODE) = m;
1454
1455 #define MMIOSETBLTWRITEMASK(m) \
1456 *(unsigned char *)(MMIO_POINTER + MMIOBLTWRITEMASK) = m;
1457
1458 #define MMIOSETROP(rop) \
1459 *(unsigned char *)(MMIO_POINTER + MMIOROP) = rop;
1460
1461 #define MMIOSTARTBLT() \
1462 *(unsigned char *)(MMIO_POINTER + MMIOBLTSTATUS) |= 0x02;
1463
1464 #define MMIOBLTBUSY(s) \
1465 s = *(volatile unsigned char *)(MMIO_POINTER + MMIOBLTSTATUS) & 1;
1466
1467 #define MMIOSETBACKGROUNDCOLOR(c) \
1468 *(unsigned char *)(MMIO_POINTER + MMIOBACKGROUNDCOLOR) = c;
1469
1470 #define MMIOSETFOREGROUNDCOLOR(c) \
1471 *(unsigned char *)(MMIO_POINTER + MMIOFOREGROUNDCOLOR) = c;
1472
1473 #define MMIOSETBACKGROUNDCOLOR16(c) \
1474 *(unsigned short *)(MMIO_POINTER + MMIOBACKGROUNDCOLOR) = c;
1475
1476 #define MMIOSETFOREGROUNDCOLOR16(c) \
1477 *(unsigned short *)(MMIO_POINTER + MMIOFOREGROUNDCOLOR) = c;
1478
1479 #define MMIOSETBACKGROUNDCOLOR32(c) \
1480 *(unsigned int *)(MMIO_POINTER + MMIOBACKGROUNDCOLOR) = c;
1481
1482 #define MMIOSETFOREGROUNDCOLOR32(c) \
1483 *(unsigned int *)(MMIO_POINTER + MMIOFOREGROUNDCOLOR) = c;
1484
1485 #define MMIOWAITUNTILFINISHED() \
1486 for (;;) { \
1487 int busy; \
1488 MMIOBLTBUSY(busy); \
1489 if (!busy) \
1490 break; \
1491 }
1492
1493 static int cirrus_pattern_address; /* Pattern with 1's (8 bytes) */
1494 static int cirrus_bitblt_pixelwidth;
1495 /* Foreground color is not preserved on 5420/2/4/6/8. */
1496 static int cirrus_accel_foreground_color;
1497
__svgalib_cirrusaccel_init(AccelSpecs * accelspecs,int bpp,int width_in_pixels)1498 void __svgalib_cirrusaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels)
1499 {
1500 /* [Setup accelerator screen pitch] */
1501 /* [Prepare any required off-screen space] */
1502 if (cirrus_chiptype < CLGD5426)
1503 /* No BitBLT engine. */
1504 return;
1505 if (bpp == 8)
1506 cirrus_bitblt_pixelwidth = 0;
1507 if (bpp == 16)
1508 cirrus_bitblt_pixelwidth = PIXELWIDTH16;
1509 if (bpp == 32)
1510 cirrus_bitblt_pixelwidth = PIXELWIDTH32;
1511 SETSRCPITCH(__svgalib_accel_screenpitchinbytes);
1512 SETDESTPITCH(__svgalib_accel_screenpitchinbytes);
1513 SETROP(0x0D);
1514 cirrus_pattern_address = cirrus_memory * 1024 - 8;
1515 (*__svgalib_driverspecs->__svgalib_setpage) (cirrus_pattern_address / 65536);
1516 gr_writel(0xffffffff, cirrus_pattern_address & 0xffff);
1517 gr_writel(0xffffffff, (cirrus_pattern_address & 0xffff) + 4);
1518 (*__svgalib_driverspecs->__svgalib_setpage) (0);
1519 if (cirrus_chiptype >= CLGD5429)
1520 /* Enable memory-mapped I/O. */
1521 __svgalib_outSR(0x17, __svgalib_inSR(0x17) | 0x04);
1522 }
1523
1524
1525 /*
1526 * Note: The foreground color register must always be reset to 0
1527 * on the 542x to avoid problems in normal framebuffer operation.
1528 * This is not the case on chips that support memory-mapped I/O.
1529 */
1530
1531 /*
1532 * These are two auxilliary functions to program the foreground
1533 * color depending on the current depth.
1534 */
1535
set_foreground_color(int fg)1536 static void set_foreground_color(int fg)
1537 {
1538 if (__svgalib_accel_bytesperpixel == 1) {
1539 SETFOREGROUNDCOLOR(fg);
1540 return;
1541 }
1542 if (__svgalib_accel_bytesperpixel == 2) {
1543 SETFOREGROUNDCOLOR16(fg);
1544 return;
1545 }
1546 SETFOREGROUNDCOLOR32(fg);
1547 }
1548
mmio_set_foreground_color(int fg)1549 static void mmio_set_foreground_color(int fg)
1550 {
1551 if (__svgalib_accel_bytesperpixel == 1) {
1552 MMIOSETFOREGROUNDCOLOR(fg);
1553 return;
1554 }
1555 if (__svgalib_accel_bytesperpixel == 2) {
1556 MMIOSETFOREGROUNDCOLOR16(fg);
1557 return;
1558 }
1559 MMIOSETFOREGROUNDCOLOR32(fg);
1560 }
1561
1562 #define FINISHBACKGROUNDBLITS() \
1563 if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) \
1564 WAITUNTILFINISHED();
1565
1566 #define MMIOFINISHBACKGROUNDBLITS() \
1567 if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) \
1568 MMIOWAITUNTILFINISHED();
1569
__svgalib_cirrusaccel_FillBox(int x,int y,int width,int height)1570 void __svgalib_cirrusaccel_FillBox(int x, int y, int width, int height)
1571 {
1572 int destaddr;
1573 destaddr = BLTBYTEADDRESS(x, y);
1574 width *= __svgalib_accel_bytesperpixel;
1575 FINISHBACKGROUNDBLITS();
1576 SETSRCADDR(cirrus_pattern_address);
1577 SETDESTADDR(destaddr);
1578 SETWIDTH(width);
1579 SETHEIGHT(height);
1580 set_foreground_color(cirrus_accel_foreground_color);
1581 SETBLTMODE(COLOREXPAND | PATTERNCOPY | cirrus_bitblt_pixelwidth);
1582 STARTBLT();
1583 WAITUNTILFINISHED();
1584 /* Can't easily run in background because foreground color has */
1585 /* to be restored. */
1586 SETFOREGROUNDCOLOR(0x00);
1587 }
1588
__svgalib_cirrusaccel_mmio_FillBox(int x,int y,int width,int height)1589 void __svgalib_cirrusaccel_mmio_FillBox(int x, int y, int width, int height)
1590 {
1591 int destaddr;
1592 destaddr = BLTBYTEADDRESS(x, y);
1593 width *= __svgalib_accel_bytesperpixel;
1594 MMIOFINISHBACKGROUNDBLITS();
1595 MMIOSETSRCADDR(cirrus_pattern_address);
1596 MMIOSETDESTADDR(destaddr);
1597 MMIOSETWIDTH(width);
1598 MMIOSETHEIGHT(height);
1599 MMIOSETBLTMODE(COLOREXPAND | PATTERNCOPY | cirrus_bitblt_pixelwidth);
1600 MMIOSTARTBLT();
1601 if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND))
1602 MMIOWAITUNTILFINISHED();
1603 }
1604
__svgalib_cirrusaccel_ScreenCopy(int x1,int y1,int x2,int y2,int width,int height)1605 void __svgalib_cirrusaccel_ScreenCopy(int x1, int y1, int x2, int y2, int width,
1606 int height)
1607 {
1608 int srcaddr, destaddr, dir;
1609 width *= __svgalib_accel_bytesperpixel;
1610 srcaddr = BLTBYTEADDRESS(x1, y1);
1611 destaddr = BLTBYTEADDRESS(x2, y2);
1612 dir = FORWARDS;
1613 if ((y1 < y2 || (y1 == y2 && x1 < x2))
1614 && y1 + height > y2) {
1615 srcaddr += (height - 1) * __svgalib_accel_screenpitchinbytes + width - 1;
1616 destaddr += (height - 1) * __svgalib_accel_screenpitchinbytes + width - 1;
1617 dir = BACKWARDS;
1618 }
1619 FINISHBACKGROUNDBLITS();
1620 SETSRCADDR(srcaddr);
1621 SETDESTADDR(destaddr);
1622 SETWIDTH(width);
1623 SETHEIGHT(height);
1624 SETBLTMODE(dir);
1625 STARTBLT();
1626 if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND))
1627 WAITUNTILFINISHED();
1628 }
1629
__svgalib_cirrusaccel_mmio_ScreenCopy(int x1,int y1,int x2,int y2,int width,int height)1630 void __svgalib_cirrusaccel_mmio_ScreenCopy(int x1, int y1, int x2, int y2, int width,
1631 int height)
1632 {
1633 int srcaddr, destaddr, dir;
1634 width *= __svgalib_accel_bytesperpixel;
1635 srcaddr = BLTBYTEADDRESS(x1, y1);
1636 destaddr = BLTBYTEADDRESS(x2, y2);
1637 dir = FORWARDS;
1638 if ((y1 < y2 || (y1 == y2 && x1 < x2))
1639 && y1 + height > y2) {
1640 srcaddr += (height - 1) * __svgalib_accel_screenpitchinbytes + width - 1;
1641 destaddr += (height - 1) * __svgalib_accel_screenpitchinbytes + width - 1;
1642 dir = BACKWARDS;
1643 }
1644 MMIOFINISHBACKGROUNDBLITS();
1645 MMIOSETSRCADDR(srcaddr);
1646 MMIOSETDESTADDR(destaddr);
1647 MMIOSETWIDTH(width);
1648 MMIOSETHEIGHT(height);
1649 MMIOSETBLTMODE(dir);
1650 MMIOSTARTBLT();
1651 if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND))
1652 MMIOWAITUNTILFINISHED();
1653 }
1654
__svgalib_cirrusaccel_SetFGColor(int fg)1655 void __svgalib_cirrusaccel_SetFGColor(int fg)
1656 {
1657 cirrus_accel_foreground_color = fg;
1658 }
1659
__svgalib_cirrusaccel_mmio_SetFGColor(int fg)1660 void __svgalib_cirrusaccel_mmio_SetFGColor(int fg)
1661 {
1662 MMIOFINISHBACKGROUNDBLITS();
1663 mmio_set_foreground_color(fg);
1664 }
1665
1666 static unsigned char cirrus_rop_map[] =
1667 {
1668 0x0D, /* ROP_COPY */
1669 0x6D, /* ROP_OR */
1670 0x05, /* ROP_AND */
1671 0x59, /* ROP_XOR */
1672 0x0B /* ROP_INVERT */
1673 };
1674
__svgalib_cirrusaccel_SetRasterOp(int rop)1675 void __svgalib_cirrusaccel_SetRasterOp(int rop)
1676 {
1677 FINISHBACKGROUNDBLITS();
1678 SETROP(cirrus_rop_map[rop]);
1679 }
1680
__svgalib_cirrusaccel_mmio_SetRasterOp(int rop)1681 void __svgalib_cirrusaccel_mmio_SetRasterOp(int rop)
1682 {
1683 MMIOFINISHBACKGROUNDBLITS();
1684 MMIOSETROP(cirrus_rop_map[rop]);
1685 }
1686
__svgalib_cirrusaccel_SetTransparency(int mode,int color)1687 void __svgalib_cirrusaccel_SetTransparency(int mode, int color)
1688 {
1689 FINISHBACKGROUNDBLITS();
1690 if (mode == DISABLE_TRANSPARENCY_COLOR) {
1691 /* Disable. */
1692 SETTRANSPARENCYCOLORMASK16(0xFFFF);
1693 return;
1694 }
1695 if (mode == ENABLE_TRANSPARENCY_COLOR) {
1696 if (__svgalib_accel_bytesperpixel == 1)
1697 color += color << 8;
1698 SETTRANSPARENCYCOLORMASK16(0x0000);
1699 SETTRANSPARENCYCOLOR16(color);
1700 return;
1701 }
1702 if (mode == DISABLE_BITMAP_TRANSPARENCY) {
1703 __svgalib_accel_bitmaptransparency = 0;
1704 return;
1705 }
1706 /* mode == ENABLE_BITMAP_TRANSPARENCY */
1707 __svgalib_accel_bitmaptransparency = 1;
1708 }
1709
__svgalib_cirrusaccel_Sync(void)1710 void __svgalib_cirrusaccel_Sync(void)
1711 {
1712 WAITUNTILFINISHED();
1713 }
1714
__svgalib_cirrusaccel_mmio_Sync(void)1715 void __svgalib_cirrusaccel_mmio_Sync(void)
1716 {
1717 MMIOWAITUNTILFINISHED();
1718 }
1719
1720
1721 /*
1722 * Set up accelerator interface for pixels of size bpp and scanline width
1723 * of width_in_pixels.
1724 */
1725
init_acceleration_specs_for_mode(AccelSpecs * accelspecs,int bpp,int width_in_pixels)1726 static void init_acceleration_specs_for_mode(AccelSpecs * accelspecs, int bpp,
1727 int width_in_pixels)
1728 {
1729 accelspecs->operations = 0;
1730 accelspecs->ropOperations = 0;
1731 accelspecs->transparencyOperations = 0;
1732 accelspecs->ropModes = 0;
1733 accelspecs->transparencyModes = 0;
1734 accelspecs->flags = ACCELERATE_ANY_LINEWIDTH;
1735
1736 if (cirrus_chiptype >= CLGD5426) {
1737 accelspecs->operations |= ACCELFLAG_SETMODE | ACCELFLAG_SYNC;
1738 if (bpp == 8 || bpp == 16) {
1739 /* BitBLT engine available. */
1740 accelspecs->operations |=
1741 ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR |
1742 ACCELFLAG_SCREENCOPY |
1743 ACCELFLAG_SETRASTEROP |
1744 ACCELFLAG_SETTRANSPARENCY;
1745 accelspecs->ropOperations =
1746 ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY;
1747 accelspecs->transparencyOperations =
1748 ACCELFLAG_SCREENCOPY;
1749 accelspecs->ropModes |= (1<<ROP_COPY) |
1750 (1<<ROP_OR) | (1<<ROP_AND) | (1<<ROP_XOR) | (1<<ROP_INVERT);
1751 accelspecs->transparencyModes |=
1752 (1<<ENABLE_TRANSPARENCY_COLOR) | (1<<ENABLE_BITMAP_TRANSPARENCY);
1753 }
1754 if (bpp == 24) {
1755 /* Depth-independent BitBLT functions. */
1756 accelspecs->operations |=
1757 ACCELFLAG_SCREENCOPY;
1758 accelspecs->ropOperations =
1759 ACCELFLAG_SCREENCOPY;
1760 accelspecs->ropModes |= (1<<ROP_COPY) |
1761 (1<<ROP_OR) | (1<<ROP_AND) | (1<<ROP_XOR) | (1<<ROP_INVERT);
1762 }
1763 }
1764 if (cirrus_chiptype >= CLGD5429)
1765 if (bpp == 8 || bpp == 16) {
1766 /* Newer chips don't have true color-compare. */
1767 accelspecs->operations &= ~ACCELFLAG_SETTRANSPARENCY;
1768 accelspecs->transparencyOperations = 0;
1769 accelspecs->ropModes = 0;
1770 accelspecs->transparencyModes = 0;
1771 }
1772 if (cirrus_chiptype >= CLGD5434)
1773 if (bpp == 32) {
1774 /* BitBLT engine available for 32bpp. */
1775 accelspecs->operations |=
1776 ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR |
1777 ACCELFLAG_SCREENCOPY |
1778 ACCELFLAG_SETRASTEROP |
1779 ACCELFLAG_SETTRANSPARENCY;
1780 accelspecs->ropOperations =
1781 ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY;
1782 accelspecs->ropModes |= (1<<ROP_COPY) |
1783 (1<<ROP_OR) | (1<<ROP_AND) | (1<<ROP_XOR) | (1<<ROP_INVERT);
1784 }
1785 #if 0 /* Full potential. */
1786 /* 5420 */
1787 if (bpp == 8)
1788 /* Color-expand (extended write modes). */
1789 accelspecs->operations =
1790 ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR | ACCELFLAG_DRAWHLINE |
1791 ACCELFLAG_DRAWHLINELIST;
1792 if (cirrus_chiptype >= CLGD5422)
1793 if (bpp == 16)
1794 /* Also for 16bpp. */
1795 accelspecs->operations =
1796 ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR |
1797 ACCELFLAG_DRAWHLINE | ACCELFLAG_DRAWHLINELIST;
1798 if (cirrus_chiptype >= CLGD5426 && cirrus_memory >= 1024) {
1799 if (bpp == 8 || bpp == 16) {
1800 /* BitBLT engine available. */
1801 accelspecs->operations |=
1802 ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE |
1803 ACCELFLAG_SETBGCOLOR | ACCELFLAG_SETRASTEROP |
1804 ACCELFLAG_SETTRANSPARENCY |
1805 ACCELFLAG_PUTIMAGE | ACCELFLAG_PUTBITMAP
1806 ACCELFLAG_SCREENCOPYBITMAP;
1807 accelspecs->ropOperations =
1808 ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY |
1809 ACCELFLAG_PUTIMAGE;
1810 accelspecs->transparencyOperations =
1811 ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE |
1812 ACCELFLAG_PUTBITMAP;
1813 accelspecs->ropModes |= (1<<ROP_COPY) |
1814 (1<<ROP_OR) | (1<<ROP_AND) | (1<<ROP_XOR) | (1<<ROP_INVERT);
1815 accelspecs->transparencyModes |=
1816 (1<<ENABLE_TRANSPARENCY_COLOR) | (1<<ENABLE_BITMAP_TRANSPARENCY);
1817 }
1818 if (bpp == 24) {
1819 /* Depth-independent BitBLT functions. */
1820 accelspecs->operations |=
1821 ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE;
1822 accelspecs->ropOperations =
1823 ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE;
1824 accelspecs->ropModes |= (1<<ROP_COPY) |
1825 (1<<ROP_OR) | (1<<ROP_AND) | (1<<ROP_XOR) | (1<<ROP_INVERT);
1826 /*
1827 * Possible additions: FILLBOX in bands, and
1828 * weird PutBitmap with color 0x000000 (trippling
1829 * bits with 8bpp operation).
1830 */
1831 }
1832 }
1833 if (cirrus_chiptype >= CLGD5429)
1834 if (bpp == 8 || bpp == 16) {
1835 /* Newer chips don't have true color-compare. */
1836 accelspecs->transparencyOperations = ACCELFLAG_BITMAP;
1837 }
1838 if (cirrus_chiptype >= CLGD5434)
1839 if (bpp == 32) {
1840 /* BitBLT engine available for 32bpp. */
1841 accelspecs->operations |=
1842 ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE |
1843 ACCELFLAG_SETBGCOLOR | ACCELFLAG_SETRASTEROP |
1844 ACCELFLAG_SETTRANSPARENCY |
1845 ACCELFLAG_PUTIMAGE | ACCELFLAG_PUTBITMAP
1846 ACCELFLAG_SCREENCOPYBITMAP |
1847 ACCELFLAG_DRAWHLINE | ACCELFLAG_DRAWHLINELIST;
1848 accelspecs->ropOperations =
1849 ACCELFLAG_FILLBOX |
1850 ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE;
1851 accelspecs->transparencyOperations =
1852 ACCELFLAG_PUTBITMAP;
1853 accelspecs->ropModes |= (1<<ROP_COPY) |
1854 (1<<ROP_OR) | (1<<ROP_AND) | (1<<ROP_XOR) | (1<<ROP_INVERT);
1855 accelspecs->transparencyModes |=
1856 (1<<ENABLE_TRANSPARENCY_COLOR) | (1<<ENABLE_BITMAP_TRANSPARENCY);
1857 }
1858 #endif
1859 /* Set the function pointers; availability is handled by flags. */
1860 accelspecs->FillBox = __svgalib_cirrusaccel_FillBox;
1861 accelspecs->ScreenCopy = __svgalib_cirrusaccel_ScreenCopy;
1862 accelspecs->SetFGColor = __svgalib_cirrusaccel_SetFGColor;
1863 accelspecs->SetTransparency = __svgalib_cirrusaccel_SetTransparency;
1864 accelspecs->SetRasterOp = __svgalib_cirrusaccel_SetRasterOp;
1865 accelspecs->Sync = __svgalib_cirrusaccel_Sync;
1866 if (cirrus_chiptype >= CLGD5429) {
1867 accelspecs->FillBox = __svgalib_cirrusaccel_mmio_FillBox;
1868 accelspecs->ScreenCopy = __svgalib_cirrusaccel_mmio_ScreenCopy;
1869 accelspecs->SetFGColor = __svgalib_cirrusaccel_mmio_SetFGColor;
1870 /* No mmio-version of SetTransparency. */
1871 accelspecs->SetRasterOp = __svgalib_cirrusaccel_mmio_SetRasterOp;
1872 accelspecs->Sync = __svgalib_cirrusaccel_mmio_Sync;
1873 }
1874 }
1875