2 Haiku S3 Trio64 driver adapted from the X.org S3 driver.
4 Copyright 2001 Ani Joshi <ajoshi@unixbox.com>
6 Copyright 2008 Haiku, Inc. All rights reserved.
7 Distributed under the terms of the MIT license.
18 #define BASE_FREQ 14.31818 // MHz
22 Trio64_CalcClock(long freq
, int min_m
, int min_n1
, int max_n1
,
23 int min_n2
, int max_n2
, long freq_min
, long freq_max
,
24 uint8
* mdiv
, uint8
* ndiv
)
26 uint8 best_n1
= 18, best_n2
= 2, best_m
= 127;
28 double ffreq
= freq
/ 1000.0 / BASE_FREQ
;
29 double ffreq_min
= freq_min
/ 1000.0 / BASE_FREQ
;
30 double ffreq_max
= freq_max
/ 1000.0 / BASE_FREQ
;
32 if (ffreq
< ffreq_min
/ (1 << max_n2
)) {
33 TRACE("Trio64_CalcClock() invalid frequency %1.3f Mhz [freq >= %1.3f Mhz]\n",
34 ffreq
*BASE_FREQ
, ffreq_min
*BASE_FREQ
/ (1 << max_n2
));
35 ffreq
= ffreq_min
/ (1 << max_n2
);
37 if (ffreq
> ffreq_max
/ (1 << min_n2
)) {
38 TRACE("Trio64_CalcClock() invalid frequency %1.3f Mhz [freq <= %1.3f Mhz]\n",
39 ffreq
*BASE_FREQ
, ffreq_max
*BASE_FREQ
/ (1 << min_n2
));
40 ffreq
= ffreq_max
/ (1 << min_n2
);
43 double best_diff
= ffreq
;
45 for (uint8 n2
= min_n2
; n2
<= max_n2
; n2
++) {
46 for (uint8 n1
= min_n1
+ 2; n1
<= max_n1
+ 2; n1
++) {
47 int m
= (int)(ffreq
* n1
* (1 << n2
) + 0.5);
48 if (m
< min_m
+ 2 || m
> 127 + 2)
51 double div
= (double)(m
) / (double)(n1
);
52 if ((div
>= ffreq_min
) && (div
<= ffreq_max
)) {
53 double diff
= ffreq
- div
/ (1 << n2
);
56 if (diff
< best_diff
) {
67 *ndiv
= (best_n1
- 2) | (best_n2
<< 6);
69 *ndiv
= (best_n1
- 2) | (best_n2
<< 5);
76 Trio64_ModeInit(const DisplayModeEx
& mode
)
78 SharedInfo
& si
= *gInfo
.sharedInfo
;
80 TRACE("Trio64_ModeInit(%d x %d, %d KHz)\n",
81 mode
.timing
.h_display
, mode
.timing
.v_display
, mode
.timing
.pixel_clock
);
83 uint32 videoRamMB
= si
.videoMemSize
/ (1024 * 1024); // MB's of video RAM
85 WriteCrtcReg(0x38, 0x48); // unlock sys regs
86 WriteCrtcReg(0x39, 0xa5); // unlock sys regs
87 WriteSeqReg(0x08, 0x06); // unlock extended sequencer regs
89 WriteCrtcReg(0x45, 0x00, 0x01); // turn off hardware cursor
92 Trio64_CalcClock(mode
.timing
.pixel_clock
, 1, 1, 31, 0, 3, 135000, 270000,
95 // Set clock registers.
97 WriteSeqReg(0x12, sr12
);
98 WriteSeqReg(0x13, sr13
);
102 uint8 tmp
= ReadSeqReg(0x15) & ~0x21;
103 WriteSeqReg(0x15, tmp
| 0x02);
104 WriteSeqReg(0x15, tmp
| 0x22);
105 WriteSeqReg(0x15, tmp
| 0x02);
107 uint8 cr33
= ReadCrtcReg(0x33) & ~0x28;
111 if (si
.chipType
== S3_TRIO64_V2
)
133 bool bDisableAccelFuncs
= false;
135 switch (mode
.timing
.h_display
) {
155 bDisableAccelFuncs
= true; // use app_server default accel functions
159 WriteCrtcReg(0x33, cr33
);
160 WriteCrtcReg(0x50, cr50
); // set number of bits per pixel & display width
161 WriteCrtcReg(0x67, pixmux
); // set pixel format
163 WriteSeqReg(0x15, 0x00, 0x10); // turn off pixel multiplex
164 WriteSeqReg(0x18, 0x00, 0x80);
166 // Note that the 2D acceleration (drawing) functions in this accelerant work
167 // only with the display widths defined in the above switch statement. For
168 // the other widths, the default functions in the app_server will be used.
170 si
.bDisableAccelDraw
= bDisableAccelFuncs
;
172 // Set the standard CRTC vga regs.
174 uint8 crtc
[25], cr3b
, cr3c
, cr5d
, cr5e
;
176 InitCrtcTimingValues(mode
, (mode
.bpp
> 8) ? 2 : 1, crtc
, cr3b
, cr3c
, cr5d
, cr5e
);
179 WriteCrtcReg(0x11, 0x00, 0x80); // unlock CRTC reg's 0-7 by clearing bit 7 of cr11
181 for (int k
= 0; k
< (int)B_COUNT_OF(crtc
); k
++) {
182 WriteCrtcReg(k
, crtc
[k
]);
185 WriteCrtcReg(0x3b, cr3b
);
186 WriteCrtcReg(0x3c, cr3c
);
187 WriteCrtcReg(0x5d, cr5d
);
188 WriteCrtcReg(0x5e, cr5e
);
190 uint8 miscOutReg
= 0x2f;
192 if ( ! (mode
.timing
.flags
& B_POSITIVE_HSYNC
))
194 if ( ! (mode
.timing
.flags
& B_POSITIVE_VSYNC
))
197 WriteMiscOutReg(miscOutReg
);
202 else if (videoRamMB
<= 2)
207 WriteCrtcReg(0x58, cr58
| 0x10, 0x13); // enable linear addressing & set memory size
209 WriteCrtcReg(0x31, 0x08);
210 WriteCrtcReg(0x32, 0x00);
211 WriteCrtcReg(0x34, 0x10);
212 WriteCrtcReg(0x3a, 0x15);
214 WriteCrtcReg(0x51, mode
.bytesPerRow
>> 7, 0x30);
215 WriteCrtcReg(0x53, 0x18, 0x18);
218 int clock2
= mode
.timing
.pixel_clock
* (mode
.bpp
/ 8);
221 int m
= (int)((gInfo
.sharedInfo
->mclk
/ 1000.0 * .72 + 16.867) * 89.736
222 / (clock2
/ 1000.0 + 39) - 21.1543);
237 WriteCrtcReg(0x54, m
<< 3);
238 WriteCrtcReg(0x60, n
);
240 WriteCrtcReg(0x42, 0x00, 0x20); // disable interlace mode
241 WriteCrtcReg(0x66, 0x89, 0x8f);
243 WriteReg16(ADVFUNC_CNTL
, 0x0001); // enable enhanced functions
245 WriteReg16(SUBSYS_CNTL
, 0x8000); // reset graphics engine
246 WriteReg16(SUBSYS_CNTL
, 0x4000); // enable graphics engine
247 ReadReg16(SUBSYS_STAT
);
249 WriteReg16(MULTIFUNC_CNTL
, 0x5000 | 0x0004 | 0x000c);
252 WriteReg16(MULTIFUNC_CNTL
, SCISSORS_L
| 0);
253 WriteReg16(MULTIFUNC_CNTL
, SCISSORS_T
| 0);
254 WriteReg16(MULTIFUNC_CNTL
, SCISSORS_R
| (mode
.timing
.h_display
- 1));
255 WriteReg16(MULTIFUNC_CNTL
, SCISSORS_B
| ((si
.maxFrameBufferSize
/ mode
.bytesPerRow
) - 1));
257 WriteReg32(WRT_MASK
, ~0); // enable all planes
259 TRACE("Trio64_ModeInit() exit\n");
265 Trio64_SetDisplayMode(const DisplayModeEx
& mode
)
267 // The code to actually configure the display.
268 // All the error checking must be done in ProposeDisplayMode(),
269 // and assume that the mode values we get here are acceptable.
271 WriteSeqReg(0x01, 0x20, 0x20); // blank the screen
273 if ( ! Trio64_ModeInit(mode
)) {
274 TRACE("Trio64_ModeInit() failed\n");
278 Trio64_AdjustFrame(mode
);
280 WriteSeqReg(0x01, 0x00, 0x20); // unblank the screen
288 Trio64_AdjustFrame(const DisplayModeEx
& mode
)
290 // Adjust start address in frame buffer.
292 int base
= (((mode
.v_display_start
* mode
.virtual_width
+ mode
.h_display_start
)
293 * (mode
.bpp
/ 8)) >> 2) & ~1;
294 base
+= gInfo
.sharedInfo
->frameBufferOffset
;
296 WriteCrtcReg(0x0c, (base
>> 8) & 0xff);
297 WriteCrtcReg(0x0d, base
& 0xff);
298 WriteCrtcReg(0x31, base
>> 12, 0x30); // put bits 16-17 in bits 4-5 of CR31
299 WriteCrtcReg(0x51, base
>> 18, 0x03); // put bits 18-19 in bits 0-1 of CR51
304 Trio64_SetIndexedColors(uint count
, uint8 first
, uint8
* colorData
, uint32 flags
)
306 // Set the indexed color palette for 8-bit color depth mode.
308 (void)flags
; // avoid compiler warning for unused arg
310 if (gInfo
.sharedInfo
->displayMode
.space
!= B_CMAP8
)
314 WriteIndexedColor(first
++, // color index
315 colorData
[0] >> 2, // red
316 colorData
[1] >> 2, // green
317 colorData
[2] >> 2); // blue