]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */ |
2 | /* | |
3 | * Copyright 1996-1997 David J. McKay | |
4 | * | |
5 | * Permission is hereby granted, free of charge, to any person obtaining a | |
6 | * copy of this software and associated documentation files (the "Software"), | |
7 | * to deal in the Software without restriction, including without limitation | |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
9 | * and/or sell copies of the Software, and to permit persons to whom the | |
10 | * Software is furnished to do so, subject to the following conditions: | |
11 | * | |
12 | * The above copyright notice and this permission notice shall be included in | |
13 | * all copies or substantial portions of the Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
19 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | |
20 | * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
21 | * SOFTWARE. | |
22 | */ | |
23 | ||
24 | /* | |
25 | * GPL licensing note -- nVidia is allowing a liberal interpretation of | |
26 | * the documentation restriction above, to merely say that this nVidia's | |
27 | * copyright and disclaimer should be included with all code derived | |
28 | * from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 | |
29 | */ | |
30 | ||
31 | /* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen | |
32 | <jpaana@s2.org> */ | |
33 | ||
34 | /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_setup.c,v 1.18 2002/08/0 | |
35 | 5 20:47:06 mvojkovi Exp $ */ | |
36 | ||
37 | #include <linux/delay.h> | |
38 | #include <linux/pci.h> | |
39 | #include <linux/pci_ids.h> | |
40 | #include "nv_type.h" | |
41 | #include "rivafb.h" | |
42 | #include "nvreg.h" | |
43 | ||
1da177e4 LT |
44 | #define PFX "rivafb: " |
45 | ||
46 | static inline unsigned char MISCin(struct riva_par *par) | |
47 | { | |
48 | return (VGA_RD08(par->riva.PVIO, 0x3cc)); | |
49 | } | |
50 | ||
51 | static Bool | |
52 | riva_is_connected(struct riva_par *par, Bool second) | |
53 | { | |
54 | volatile U032 __iomem *PRAMDAC = par->riva.PRAMDAC0; | |
55 | U032 reg52C, reg608; | |
56 | Bool present; | |
57 | ||
58 | if(second) PRAMDAC += 0x800; | |
59 | ||
60 | reg52C = NV_RD32(PRAMDAC, 0x052C); | |
61 | reg608 = NV_RD32(PRAMDAC, 0x0608); | |
62 | ||
63 | NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000); | |
64 | ||
65 | NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE); | |
66 | mdelay(1); | |
67 | NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1); | |
68 | ||
69 | NV_WR32(par->riva.PRAMDAC0, 0x0610, 0x94050140); | |
70 | NV_WR32(par->riva.PRAMDAC0, 0x0608, 0x00001000); | |
71 | ||
72 | mdelay(1); | |
73 | ||
74 | present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? TRUE : FALSE; | |
75 | ||
76 | NV_WR32(par->riva.PRAMDAC0, 0x0608, | |
77 | NV_RD32(par->riva.PRAMDAC0, 0x0608) & 0x0000EFFF); | |
78 | ||
79 | NV_WR32(PRAMDAC, 0x052C, reg52C); | |
80 | NV_WR32(PRAMDAC, 0x0608, reg608); | |
81 | ||
82 | return present; | |
83 | } | |
84 | ||
85 | static void | |
86 | riva_override_CRTC(struct riva_par *par) | |
87 | { | |
88 | printk(KERN_INFO PFX | |
89 | "Detected CRTC controller %i being used\n", | |
90 | par->SecondCRTC ? 1 : 0); | |
91 | ||
92 | if(par->forceCRTC != -1) { | |
93 | printk(KERN_INFO PFX | |
94 | "Forcing usage of CRTC %i\n", par->forceCRTC); | |
95 | par->SecondCRTC = par->forceCRTC; | |
96 | } | |
97 | } | |
98 | ||
99 | static void | |
100 | riva_is_second(struct riva_par *par) | |
101 | { | |
102 | if (par->FlatPanel == 1) { | |
103 | switch(par->Chipset & 0xffff) { | |
104 | case 0x0174: | |
105 | case 0x0175: | |
106 | case 0x0176: | |
107 | case 0x0177: | |
108 | case 0x0179: | |
109 | case 0x017C: | |
110 | case 0x017D: | |
111 | case 0x0186: | |
112 | case 0x0187: | |
113 | /* this might not be a good default for the chips below */ | |
114 | case 0x0286: | |
115 | case 0x028C: | |
116 | case 0x0316: | |
117 | case 0x0317: | |
118 | case 0x031A: | |
119 | case 0x031B: | |
120 | case 0x031C: | |
121 | case 0x031D: | |
122 | case 0x031E: | |
123 | case 0x031F: | |
124 | case 0x0324: | |
125 | case 0x0325: | |
126 | case 0x0328: | |
127 | case 0x0329: | |
128 | case 0x032C: | |
129 | case 0x032D: | |
130 | par->SecondCRTC = TRUE; | |
131 | break; | |
132 | default: | |
133 | par->SecondCRTC = FALSE; | |
134 | break; | |
135 | } | |
136 | } else { | |
137 | if(riva_is_connected(par, 0)) { | |
138 | ||
139 | if (NV_RD32(par->riva.PRAMDAC0, 0x0000052C) & 0x100) | |
140 | par->SecondCRTC = TRUE; | |
141 | else | |
142 | par->SecondCRTC = FALSE; | |
143 | } else | |
144 | if (riva_is_connected(par, 1)) { | |
145 | if(NV_RD32(par->riva.PRAMDAC0, 0x0000252C) & 0x100) | |
146 | par->SecondCRTC = TRUE; | |
147 | else | |
148 | par->SecondCRTC = FALSE; | |
149 | } else /* default */ | |
150 | par->SecondCRTC = FALSE; | |
151 | } | |
152 | riva_override_CRTC(par); | |
153 | } | |
154 | ||
155 | unsigned long riva_get_memlen(struct riva_par *par) | |
156 | { | |
157 | RIVA_HW_INST *chip = &par->riva; | |
158 | unsigned long memlen = 0; | |
159 | unsigned int chipset = par->Chipset; | |
160 | struct pci_dev* dev; | |
7d345b22 | 161 | u32 amt; |
1da177e4 LT |
162 | |
163 | switch (chip->Architecture) { | |
164 | case NV_ARCH_03: | |
165 | if (NV_RD32(chip->PFB, 0x00000000) & 0x00000020) { | |
166 | if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20) | |
167 | && ((NV_RD32(chip->PMC, 0x00000000)&0x0F)>=0x02)) { | |
168 | /* | |
169 | * SDRAM 128 ZX. | |
170 | */ | |
171 | switch (NV_RD32(chip->PFB,0x00000000) & 0x03) { | |
172 | case 2: | |
173 | memlen = 1024 * 4; | |
174 | break; | |
175 | case 1: | |
176 | memlen = 1024 * 2; | |
177 | break; | |
178 | default: | |
179 | memlen = 1024 * 8; | |
180 | break; | |
181 | } | |
182 | } else { | |
183 | memlen = 1024 * 8; | |
184 | } | |
185 | } else { | |
186 | /* | |
187 | * SGRAM 128. | |
188 | */ | |
189 | switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003) { | |
190 | case 0: | |
191 | memlen = 1024 * 8; | |
192 | break; | |
193 | case 2: | |
194 | memlen = 1024 * 4; | |
195 | break; | |
196 | default: | |
197 | memlen = 1024 * 2; | |
198 | break; | |
199 | } | |
200 | } | |
201 | break; | |
202 | case NV_ARCH_04: | |
203 | if (NV_RD32(chip->PFB, 0x00000000) & 0x00000100) { | |
204 | memlen = ((NV_RD32(chip->PFB, 0x00000000)>>12)&0x0F) * | |
205 | 1024 * 2 + 1024 * 2; | |
206 | } else { | |
207 | switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003) { | |
208 | case 0: | |
209 | memlen = 1024 * 32; | |
210 | break; | |
211 | case 1: | |
212 | memlen = 1024 * 4; | |
213 | break; | |
214 | case 2: | |
215 | memlen = 1024 * 8; | |
216 | break; | |
217 | case 3: | |
218 | default: | |
219 | memlen = 1024 * 16; | |
220 | break; | |
221 | } | |
222 | } | |
223 | break; | |
224 | case NV_ARCH_10: | |
225 | case NV_ARCH_20: | |
226 | case NV_ARCH_30: | |
227 | if(chipset == NV_CHIP_IGEFORCE2) { | |
228 | ||
d3736340 | 229 | dev = pci_get_bus_and_slot(0, 1); |
1da177e4 | 230 | pci_read_config_dword(dev, 0x7C, &amt); |
d3736340 | 231 | pci_dev_put(dev); |
1da177e4 LT |
232 | memlen = (((amt >> 6) & 31) + 1) * 1024; |
233 | } else if (chipset == NV_CHIP_0x01F0) { | |
d3736340 | 234 | dev = pci_get_bus_and_slot(0, 1); |
1da177e4 | 235 | pci_read_config_dword(dev, 0x84, &amt); |
d3736340 | 236 | pci_dev_put(dev); |
1da177e4 LT |
237 | memlen = (((amt >> 4) & 127) + 1) * 1024; |
238 | } else { | |
239 | switch ((NV_RD32(chip->PFB, 0x0000020C) >> 20) & | |
240 | 0x000000FF){ | |
241 | case 0x02: | |
242 | memlen = 1024 * 2; | |
243 | break; | |
244 | case 0x04: | |
245 | memlen = 1024 * 4; | |
246 | break; | |
247 | case 0x08: | |
248 | memlen = 1024 * 8; | |
249 | break; | |
250 | case 0x10: | |
251 | memlen = 1024 * 16; | |
252 | break; | |
253 | case 0x20: | |
254 | memlen = 1024 * 32; | |
255 | break; | |
256 | case 0x40: | |
257 | memlen = 1024 * 64; | |
258 | break; | |
259 | case 0x80: | |
260 | memlen = 1024 * 128; | |
261 | break; | |
262 | default: | |
263 | memlen = 1024 * 16; | |
264 | break; | |
265 | } | |
266 | } | |
267 | break; | |
268 | } | |
269 | return memlen; | |
270 | } | |
271 | ||
272 | unsigned long riva_get_maxdclk(struct riva_par *par) | |
273 | { | |
274 | RIVA_HW_INST *chip = &par->riva; | |
275 | unsigned long dclk = 0; | |
276 | ||
277 | switch (chip->Architecture) { | |
278 | case NV_ARCH_03: | |
279 | if (NV_RD32(chip->PFB, 0x00000000) & 0x00000020) { | |
280 | if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20) | |
281 | && ((NV_RD32(chip->PMC,0x00000000)&0x0F) >= 0x02)) { | |
282 | /* | |
283 | * SDRAM 128 ZX. | |
284 | */ | |
285 | dclk = 800000; | |
286 | } else { | |
287 | dclk = 1000000; | |
288 | } | |
289 | } else { | |
290 | /* | |
291 | * SGRAM 128. | |
292 | */ | |
293 | dclk = 1000000; | |
294 | } | |
295 | break; | |
296 | case NV_ARCH_04: | |
297 | case NV_ARCH_10: | |
298 | case NV_ARCH_20: | |
299 | case NV_ARCH_30: | |
300 | switch ((NV_RD32(chip->PFB, 0x00000000) >> 3) & 0x00000003) { | |
301 | case 3: | |
302 | dclk = 800000; | |
303 | break; | |
304 | default: | |
305 | dclk = 1000000; | |
306 | break; | |
307 | } | |
308 | break; | |
309 | } | |
310 | return dclk; | |
311 | } | |
312 | ||
313 | void | |
314 | riva_common_setup(struct riva_par *par) | |
315 | { | |
316 | par->riva.EnableIRQ = 0; | |
317 | par->riva.PRAMDAC0 = | |
318 | (volatile U032 __iomem *)(par->ctrl_base + 0x00680000); | |
319 | par->riva.PFB = | |
320 | (volatile U032 __iomem *)(par->ctrl_base + 0x00100000); | |
321 | par->riva.PFIFO = | |
322 | (volatile U032 __iomem *)(par->ctrl_base + 0x00002000); | |
323 | par->riva.PGRAPH = | |
324 | (volatile U032 __iomem *)(par->ctrl_base + 0x00400000); | |
325 | par->riva.PEXTDEV = | |
326 | (volatile U032 __iomem *)(par->ctrl_base + 0x00101000); | |
327 | par->riva.PTIMER = | |
328 | (volatile U032 __iomem *)(par->ctrl_base + 0x00009000); | |
329 | par->riva.PMC = | |
330 | (volatile U032 __iomem *)(par->ctrl_base + 0x00000000); | |
331 | par->riva.FIFO = | |
332 | (volatile U032 __iomem *)(par->ctrl_base + 0x00800000); | |
333 | par->riva.PCIO0 = par->ctrl_base + 0x00601000; | |
334 | par->riva.PDIO0 = par->ctrl_base + 0x00681000; | |
335 | par->riva.PVIO = par->ctrl_base + 0x000C0000; | |
336 | ||
337 | par->riva.IO = (MISCin(par) & 0x01) ? 0x3D0 : 0x3B0; | |
338 | ||
339 | if (par->FlatPanel == -1) { | |
340 | switch (par->Chipset & 0xffff) { | |
341 | case 0x0112: /* known laptop chips */ | |
342 | case 0x0174: | |
343 | case 0x0175: | |
344 | case 0x0176: | |
345 | case 0x0177: | |
346 | case 0x0179: | |
347 | case 0x017C: | |
348 | case 0x017D: | |
349 | case 0x0186: | |
350 | case 0x0187: | |
351 | case 0x0286: | |
352 | case 0x028C: | |
353 | case 0x0316: | |
354 | case 0x0317: | |
355 | case 0x031A: | |
356 | case 0x031B: | |
357 | case 0x031C: | |
358 | case 0x031D: | |
359 | case 0x031E: | |
360 | case 0x031F: | |
361 | case 0x0324: | |
362 | case 0x0325: | |
363 | case 0x0328: | |
364 | case 0x0329: | |
365 | case 0x032C: | |
366 | case 0x032D: | |
367 | printk(KERN_INFO PFX | |
368 | "On a laptop. Assuming Digital Flat Panel\n"); | |
369 | par->FlatPanel = 1; | |
370 | break; | |
371 | default: | |
372 | break; | |
373 | } | |
374 | } | |
375 | ||
376 | switch (par->Chipset & 0x0ff0) { | |
377 | case 0x0110: | |
378 | if (par->Chipset == NV_CHIP_GEFORCE2_GO) | |
379 | par->SecondCRTC = TRUE; | |
380 | #if defined(__powerpc__) | |
381 | if (par->FlatPanel == 1) | |
382 | par->SecondCRTC = TRUE; | |
383 | #endif | |
384 | riva_override_CRTC(par); | |
385 | break; | |
386 | case 0x0170: | |
387 | case 0x0180: | |
388 | case 0x01F0: | |
389 | case 0x0250: | |
390 | case 0x0280: | |
391 | case 0x0300: | |
392 | case 0x0310: | |
393 | case 0x0320: | |
394 | case 0x0330: | |
395 | case 0x0340: | |
396 | riva_is_second(par); | |
397 | break; | |
398 | default: | |
399 | break; | |
400 | } | |
401 | ||
402 | if (par->SecondCRTC) { | |
403 | par->riva.PCIO = par->riva.PCIO0 + 0x2000; | |
404 | par->riva.PCRTC = par->riva.PCRTC0 + 0x800; | |
405 | par->riva.PRAMDAC = par->riva.PRAMDAC0 + 0x800; | |
406 | par->riva.PDIO = par->riva.PDIO0 + 0x2000; | |
407 | } else { | |
408 | par->riva.PCIO = par->riva.PCIO0; | |
409 | par->riva.PCRTC = par->riva.PCRTC0; | |
410 | par->riva.PRAMDAC = par->riva.PRAMDAC0; | |
411 | par->riva.PDIO = par->riva.PDIO0; | |
412 | } | |
413 | ||
414 | if (par->FlatPanel == -1) { | |
415 | /* Fix me, need x86 DDC code */ | |
416 | par->FlatPanel = 0; | |
417 | } | |
418 | par->riva.flatPanel = (par->FlatPanel > 0) ? TRUE : FALSE; | |
419 | ||
420 | RivaGetConfig(&par->riva, par->Chipset); | |
421 | } | |
422 |