1 /*****************************************************************************\
2 * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
3 * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
4 \*****************************************************************************/
10 * ATTENTION: Currently we set the graphics modes by setting the registers
11 * with the beforehand dumped values of the corresponding registers. So not
12 * all graphics modes ET6x00 chips are capable of are accessible. So it would
13 * be great to implement the normal algorithm of run-time computing of the
14 * values to set the register.
18 /*****************************************************************************/
20 uint32 VisScreenWidth
;
21 uint32 VisScreenHeight
;
23 uint8 NumberGreenBits
;
25 } VIDEO_MODE_INFORMATION
;
26 /*****************************************************************************/
28 * ATTENTION: Don't forget that CRTC indexed register 0x11
29 * bit[7] write-protects some registers.
32 uint16 width
, height
, bpp
, refreshRate
;
33 uint8 clock0M
, clock0N
;
34 uint8 pci42
; /* contains MCLK divider (MDIV) */
37 {640, 480, 24, 75, 0x28, 0x22, 0x02,
38 {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
39 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 0xea, 0x0c, 0xdf, 0xf0, 0x60, 0xe7, 0x04, 0xab,
41 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
42 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
43 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
44 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
45 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
46 {640, 480, 24, 72, 0x56, 0x63, 0x00,
47 {0x63, 0x4f, 0x50, 0x86, 0x55, 0x9a, 0x06, 0x3e,
48 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0xe8, 0x0b, 0xdf, 0xf0, 0x60, 0xe7, 0xff, 0xab,
50 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
51 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
52 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
53 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
54 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
55 {640, 480, 24, 60, 0x28, 0x22, 0x02,
56 {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
57 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0xea, 0x0c, 0xdf, 0xf0, 0x60, 0xe7, 0x04, 0xab,
59 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
60 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
61 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
62 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
63 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
65 {640, 480, 16, 75, 0x56, 0x43, 0x01,
66 {0x64, 0x4f, 0x4f, 0x88, 0x54, 0x9c, 0xf2, 0x1f,
67 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0xe0, 0x03, 0xdf, 0xa0, 0x60, 0xdf, 0xf3, 0xab,
69 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
70 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
71 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
72 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
73 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
74 {640, 480, 16, 72, 0x56, 0x43, 0x01,
75 {0x63, 0x4f, 0x50, 0x86, 0x55, 0x9a, 0x06, 0x3e,
76 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0xe8, 0x0b, 0xdf, 0xa0, 0x60, 0xe7, 0xff, 0xab,
78 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
79 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
80 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
81 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
82 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
83 {640, 480, 16, 60, 0x28, 0x41, 0x01,
84 {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
85 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0xea, 0x0c, 0xdf, 0xa0, 0x60, 0xe7, 0x04, 0xab,
87 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
88 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
89 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
90 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
91 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
93 {800, 600, 24, 75, 0x79, 0x49, 0x00,
94 {0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0,
95 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x58, 0x0c, 0x57, 0x2c, 0x60, 0x57, 0x73, 0xab,
97 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
98 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
99 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
100 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
101 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
102 {800, 600, 24, 72, 0x28, 0x41, 0x00,
103 {0x7d, 0x63, 0x63, 0x81, 0x6d, 0x1c, 0x98, 0xf0,
104 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x7c, 0x02, 0x57, 0x2c, 0x60, 0x57, 0x99, 0xab,
106 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
107 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
108 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
109 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
110 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
111 {800, 600, 24, 60, 0x79, 0x49, 0x00,
112 {0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0,
113 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114 0x58, 0x0c, 0x57, 0x2c, 0x60, 0x57, 0x73, 0xab,
115 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
116 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
117 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
118 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
119 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
121 {800, 600, 16, 75, 0x51, 0x44, 0x00,
122 {0x7f, 0x63, 0x63, 0x83, 0x68, 0x12, 0x6f, 0xf0,
123 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124 0x58, 0x0b, 0x57, 0xc8, 0x60, 0x57, 0x70, 0xab,
125 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
126 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
127 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
128 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
129 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
130 {800, 600, 16, 72, 0x28, 0x41, 0x00,
131 {0x7d, 0x63, 0x63, 0x81, 0x6d, 0x1c, 0x98, 0xf0,
132 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x7c, 0x02, 0x57, 0xc8, 0x60, 0x57, 0x99, 0xab,
134 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
135 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
136 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
137 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
138 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
139 {800, 600, 16, 60, 0x79, 0x49, 0x00,
140 {0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0,
141 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x58, 0x0c, 0x57, 0xc8, 0x60, 0x57, 0x73, 0xab,
143 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
144 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
145 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
146 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
147 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
149 {1024, 768, 16, 75, 0x1f, 0x21, 0x00,
150 {0x9f, 0x7f, 0x7f, 0x83, 0x84, 0x90, 0x1e, 0xf5,
151 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x83, 0xff, 0x00, 0x60, 0xff, 0x1f, 0xab,
153 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
154 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
155 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
156 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
157 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
158 {1024, 768, 16, 70, 0x28, 0x22, 0x00,
159 {0x9f, 0x7f, 0x7f, 0x83, 0x84, 0x90, 0x1e, 0xf5,
160 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x83, 0xff, 0x00, 0x60, 0xff, 0x1f, 0xab,
162 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
163 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
164 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
165 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
166 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
167 {1024, 768, 16, 60, 0x6b, 0x44, 0x00,
168 {0xa1, 0x7f, 0x80, 0x84, 0x88, 0x99, 0x26, 0xfd,
169 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 0x08, 0x0a, 0xff, 0x00, 0x60, 0x04, 0x22, 0xab,
171 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
172 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
173 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
174 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
175 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
178 #define CLOCK0MN (sizeof(clock0MN) / sizeof(clock0MN[0]))
179 /*****************************************************************************/
180 __inline
void et6000EnableLinearMemoryMapping(uint16 pciConfigSpace
)
183 * Relocate memory via PCI Base Address 0; don't enable MMU;
184 * enable memory mapped registers; enable system linear memory mapping.
186 ioSet8(pciConfigSpace
+0x40, 0xf0, 0x0b);
188 /*****************************************************************************/
189 static void setPCIConfigSpaceRegisters41to5E(uint16 pciConfigSpace
,
190 VIDEO_MODE_INFORMATION
*mi
,
193 uint8 pci415e
[30] = {
194 0x3a, 0x00, 0x02, 0x15, 0x04, 0x40, 0x13, 0x00,
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x04, 0x00, 0x00, 0x00, 0x00, 0x00};
200 pci415e
[1] = clock0MN
[m
].pci42
;
202 for (i
=0x41; i
<0x5f; i
++) {
203 if ((i
==0x45) || ((i
>0x47)&&(i
<0x4e)) ||
204 (i
==0x4e) || ((i
>0x59)&&(i
<0x5c)))
205 continue; /* Skip absent or read-only registers */
206 ioSet8(pciConfigSpace
+i
, 0x00, pci415e
[i
-0x41]);
209 if (mi
->BitsPerPlane
== 16) {
210 if (mi
->NumberGreenBits
== 5)
211 ioSet8(pciConfigSpace
+0x58, 0xfd, 0x00); /* 16bpp is 5:5:5 */
213 ioSet8(pciConfigSpace
+0x58, 0xfd, 0x02); /* 16bpp is 5:6:5 */
216 /*****************************************************************************/
217 static void setMiscOutputRegister(VIDEO_MODE_INFORMATION
*mi
) {
219 if (mi
->VisScreenHeight
< 400)
220 MiscOutputReg
= 0x80; /* -vsync, +hsync */
221 else if (mi
->VisScreenHeight
< 480)
222 MiscOutputReg
= 0x40; /* +vsync, -hsync */
223 else if (mi
->VisScreenHeight
< 768)
224 MiscOutputReg
= 0xc0; /* -vsync, -hsync */
226 MiscOutputReg
= 0x00; /* +vsync, +hsync */
227 ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0x3f) | MiscOutputReg
);
229 /* Enable host access to display memory, color mode */
230 ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0xfc) | 0x03);
232 /*****************************************************************************/
233 static void setATC(uint8 bpp
) {
234 uint8 atc
[7] = {0x21, 0x00, 0x30, 0x00, 0x00}, atc16
= 0x80;///
235 ///uint8 atc[7] = {0x01, 0x00, 0x0f, 0x00, 0x00}, atc16 = 0x80;///zzz
236 uint8 i
, atcIndexReg
;
239 f
= ioGet8(0x3da); /* Set index/data flip-flop to index mode */
240 atcIndexReg
= ioGet8(0x3c0) & 0xe0; /* Save bits[7:5] */
242 for (i
= 0x10; i
< 0x15; i
++) {
243 f
= ioGet8(0x3da); /* Set index/data flip-flop to index mode */
244 ioSet8(0x3c0, 0x00, i
| atcIndexReg
);
245 ioSet8(0x3c0, 0x00, atc
[i
-0x10]);
256 f
= ioGet8(0x3da); /* Set index/data flip-flop to index mode */
257 ioSet8(0x3c0, 0x00, 0x16 | atcIndexReg
);
258 ioSet8(0x3c0, 0x00, atc16
);
260 /*****************************************************************************/
261 static void setTS(void) {
262 uint8 ts
[7] = {0x02, 0x01, 0x0f, 0x00, 0x0e, 0x00, 0x00};
265 for (i
= 0; i
< 7; i
++) {
266 if (i
== 5) continue; /* Skip absent register */
267 ioSet8(0x3c4, 0xf8, i
);
268 ioSet8(0x3c5, 0x00, ts
[i
]);
271 /*****************************************************************************/
272 static void setGDC(void) {
273 uint8 gdc
[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff};
276 for (i
= 0; i
< 9; i
++) {
277 ioSet8(0x3ce, 0xf0, i
);
278 ioSet8(0x3cf, 0x00, gdc
[i
]);
281 /*****************************************************************************/
282 static void setClock0RegNum(uint8 regNum
) {
283 /* Set bits[1:0] of the selected CLOCK0 PLL parameters register number */
284 ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0xf3) | ((regNum
& 0x03) << 2));
286 /* Set bit[2] of the selected CLOCK0 PLL parameters register number */
287 ioSet8(0x3d4, 0xc0, 0x34);
288 ioSet8(0x3d5, 0xfd, (regNum
& 0x04) << 1);
290 /*****************************************************************************/
291 static void setPLL(uint16 pciConfigSpace
,
292 uint32 m
) /* mode index */
295 uint8 clock0M
= 0, clock0N
= 0;
297 clock0M
= clock0MN
[m
].clock0M
;
298 clock0N
= clock0MN
[m
].clock0N
;
300 setClock0RegNum(regNum
);
301 ioSet8(pciConfigSpace
+0x67, 0x00, regNum
);
302 ioSet8(pciConfigSpace
+0x68, 0x00, regNum
);
303 ioSet8(pciConfigSpace
+0x69, 0x00, clock0M
);
304 ioSet8(pciConfigSpace
+0x69, 0x00, clock0N
);
306 /*****************************************************************************/
307 static void setCRTC(uint32 m
) /* mode index */
311 /* Unlock the write protection of several registers */
312 ioSet8(0x3d4, 0xc0, 0x11);
313 ioSet8(0x3d5, 0x7f, 0x00);
315 for (i
= 0; i
< 64; i
++) {
316 if (((i
> 0x18) && (i
< 0x33)) ||
317 ((i
> 0x35) && (i
< 0x3f)))
318 continue; /* Skip absent or read-only registers */
319 ioSet8(0x3d4, 0xc0, i
);
320 ioSet8(0x3d5, 0x00, clock0MN
[m
].crtc
[i
]);
323 /*****************************************************************************/
324 static uint32
et6000SetGraphicsMode(VIDEO_MODE_INFORMATION
*mi
,
325 uint16 pciConfigSpace
)
329 for(m
= 0; m
< CLOCK0MN
; m
++) {
330 if ((clock0MN
[m
].width
== mi
->VisScreenWidth
) &&
331 (clock0MN
[m
].height
== mi
->VisScreenHeight
) &&
332 (clock0MN
[m
].bpp
== mi
->BitsPerPlane
) &&
333 ((clock0MN
[m
].refreshRate
-1 <= mi
->Frequency
) &&
334 (clock0MN
[m
].refreshRate
+1 >= mi
->Frequency
)))
340 return B_BAD_VALUE
; /* Found no entry for requested mode */
342 et6000EnableLinearMemoryMapping(pciConfigSpace
);
343 setMiscOutputRegister(mi
);
344 ioSet8(0x3d8, 0x00, 0xa0); /* Set the KEY for color modes */
345 setPCIConfigSpaceRegisters41to5E(pciConfigSpace
, mi
, m
);
346 ioSet8(0x3c6, 0x00, 0xff); /* Set pixel mask */
347 setATC(mi
->BitsPerPlane
);
351 setPLL(pciConfigSpace
, m
);
355 /*****************************************************************************/
356 status_t
et6000SetMode(display_mode
*mode
, uint16 pciConfigSpace
) {
357 VIDEO_MODE_INFORMATION mi
;
359 mi
.VisScreenWidth
= mode
->virtual_width
;
360 mi
.VisScreenHeight
= mode
->virtual_height
;
362 switch (mode
->space
) {
365 mi
.BitsPerPlane
= 24;
366 mi
.NumberGreenBits
= 8;
370 mi
.BitsPerPlane
= 16;
371 mi
.NumberGreenBits
= 6;
375 mi
.BitsPerPlane
= 16;
376 mi
.NumberGreenBits
= 5;
382 mi
.Frequency
= (uint16
) (mode
->timing
.pixel_clock
* 1000
383 / (mode
->timing
.h_total
* mode
->timing
.v_total
));
385 return et6000SetGraphicsMode(&mi
, pciConfigSpace
);
387 /*****************************************************************************/
388 status_t
et6000ProposeMode(display_mode
*mode
, uint32 memSize
) {
392 /* Framebuffer must not overlap with the memory mapped registers */
393 if (memSize
> 0x3fe000)
396 memSize
-= ET6000_ACL_NEEDS_MEMORY
;
398 switch (mode
->space
) {
413 refreshRate
= (uint16
) (mode
->timing
.pixel_clock
* 1000
414 / (mode
->timing
.h_total
* mode
->timing
.v_total
));
416 for(m
= 0; m
< CLOCK0MN
; m
++) {
417 if ((clock0MN
[m
].width
== mode
->virtual_width
) &&
418 (clock0MN
[m
].height
== mode
->virtual_height
) &&
419 (clock0MN
[m
].bpp
== bpp
) &&
420 ((clock0MN
[m
].refreshRate
-1 <= refreshRate
) &&
421 (clock0MN
[m
].refreshRate
+1 >= refreshRate
)))
427 return B_BAD_VALUE
; /* Found no entry for requested mode */
429 if (mode
->virtual_width
* mode
->virtual_height
* bpp
/ 8 > memSize
)
430 return B_BAD_VALUE
; /* Not enough adapter onboard memory */
434 /*****************************************************************************/