Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
472 | giacomo | 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 <linuxcomp.h> |
||
38 | |||
39 | #include <linux/delay.h> |
||
40 | #include <linux/pci.h> |
||
41 | #include <linux/pci_ids.h> |
||
42 | #include "nv_type.h" |
||
43 | #include "rivafb.h" |
||
44 | #include "nvreg.h" |
||
45 | |||
46 | |||
47 | #ifndef CONFIG_PCI /* sanity check */ |
||
48 | #error This driver requires PCI support. |
||
49 | #endif |
||
50 | |||
51 | #define PFX "rivafb: " |
||
52 | |||
53 | static inline unsigned char MISCin(struct riva_par *par) |
||
54 | { |
||
55 | return (VGA_RD08(par->riva.PVIO, 0x3cc)); |
||
56 | } |
||
57 | |||
58 | static Bool |
||
59 | riva_is_connected(struct riva_par *par, Bool second) |
||
60 | { |
||
61 | volatile U032 *PRAMDAC = par->riva.PRAMDAC0; |
||
62 | U032 reg52C, reg608; |
||
63 | Bool present; |
||
64 | |||
65 | if(second) PRAMDAC += 0x800; |
||
66 | |||
67 | reg52C = PRAMDAC[0x052C/4]; |
||
68 | reg608 = PRAMDAC[0x0608/4]; |
||
69 | |||
70 | PRAMDAC[0x0608/4] = reg608 & ~0x00010000; |
||
71 | |||
72 | PRAMDAC[0x052C/4] = reg52C & 0x0000FEEE; |
||
73 | mdelay(1); |
||
74 | PRAMDAC[0x052C/4] |= 1; |
||
75 | |||
76 | par->riva.PRAMDAC0[0x0610/4] = 0x94050140; |
||
77 | par->riva.PRAMDAC0[0x0608/4] |= 0x00001000; |
||
78 | |||
79 | mdelay(1); |
||
80 | |||
81 | present = (PRAMDAC[0x0608/4] & (1 << 28)) ? TRUE : FALSE; |
||
82 | |||
83 | par->riva.PRAMDAC0[0x0608/4] &= 0x0000EFFF; |
||
84 | |||
85 | PRAMDAC[0x052C/4] = reg52C; |
||
86 | PRAMDAC[0x0608/4] = reg608; |
||
87 | |||
88 | return present; |
||
89 | } |
||
90 | |||
91 | static void |
||
92 | riva_override_CRTC(struct riva_par *par) |
||
93 | { |
||
94 | printk(KERN_INFO PFX |
||
95 | "Detected CRTC controller %i being used\n", |
||
96 | par->SecondCRTC ? 1 : 0); |
||
97 | |||
98 | if(par->forceCRTC != -1) { |
||
99 | printk(KERN_INFO PFX |
||
100 | "Forcing usage of CRTC %i\n", par->forceCRTC); |
||
101 | par->SecondCRTC = par->forceCRTC; |
||
102 | } |
||
103 | } |
||
104 | |||
105 | static void |
||
106 | riva_is_second(struct riva_par *par) |
||
107 | { |
||
108 | if (par->FlatPanel == 1) { |
||
109 | switch(par->Chipset) { |
||
110 | case NV_CHIP_GEFORCE4_440_GO: |
||
111 | case NV_CHIP_GEFORCE4_440_GO_M64: |
||
112 | case NV_CHIP_GEFORCE4_420_GO: |
||
113 | case NV_CHIP_GEFORCE4_420_GO_M32: |
||
114 | case NV_CHIP_QUADRO4_500_GOGL: |
||
115 | par->SecondCRTC = TRUE; |
||
116 | break; |
||
117 | default: |
||
118 | par->SecondCRTC = FALSE; |
||
119 | break; |
||
120 | } |
||
121 | } else { |
||
122 | if(riva_is_connected(par, 0)) { |
||
123 | if(par->riva.PRAMDAC0[0x0000052C/4] & 0x100) |
||
124 | par->SecondCRTC = TRUE; |
||
125 | else |
||
126 | par->SecondCRTC = FALSE; |
||
127 | } else |
||
128 | if (riva_is_connected(par, 1)) { |
||
129 | if(par->riva.PRAMDAC0[0x0000252C/4] & 0x100) |
||
130 | par->SecondCRTC = TRUE; |
||
131 | else |
||
132 | par->SecondCRTC = FALSE; |
||
133 | } else /* default */ |
||
134 | par->SecondCRTC = FALSE; |
||
135 | } |
||
136 | riva_override_CRTC(par); |
||
137 | } |
||
138 | |||
139 | unsigned long riva_get_memlen(struct riva_par *par) |
||
140 | { |
||
141 | RIVA_HW_INST *chip = &par->riva; |
||
142 | unsigned long memlen = 0; |
||
143 | unsigned int chipset = par->Chipset; |
||
144 | struct pci_dev* dev; |
||
145 | int amt; |
||
146 | |||
147 | switch (chip->Architecture) { |
||
148 | case NV_ARCH_03: |
||
149 | if (chip->PFB[0x00000000/4] & 0x00000020) { |
||
150 | if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20) |
||
151 | && ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02)) { |
||
152 | /* |
||
153 | * SDRAM 128 ZX. |
||
154 | */ |
||
155 | switch (chip->PFB[0x00000000/4] & 0x03) { |
||
156 | case 2: |
||
157 | memlen = 1024 * 4; |
||
158 | break; |
||
159 | case 1: |
||
160 | memlen = 1024 * 2; |
||
161 | break; |
||
162 | default: |
||
163 | memlen = 1024 * 8; |
||
164 | break; |
||
165 | } |
||
166 | } else { |
||
167 | memlen = 1024 * 8; |
||
168 | } |
||
169 | } else { |
||
170 | /* |
||
171 | * SGRAM 128. |
||
172 | */ |
||
173 | switch (chip->PFB[0x00000000/4] & 0x00000003) { |
||
174 | case 0: |
||
175 | memlen = 1024 * 8; |
||
176 | break; |
||
177 | case 2: |
||
178 | memlen = 1024 * 4; |
||
179 | break; |
||
180 | default: |
||
181 | memlen = 1024 * 2; |
||
182 | break; |
||
183 | } |
||
184 | } |
||
185 | break; |
||
186 | case NV_ARCH_04: |
||
187 | if (chip->PFB[0x00000000/4] & 0x00000100) { |
||
188 | memlen = ((chip->PFB[0x00000000/4] >> 12) & 0x0F) * |
||
189 | 1024 * 2 + 1024 * 2; |
||
190 | } else { |
||
191 | switch (chip->PFB[0x00000000/4] & 0x00000003) { |
||
192 | case 0: |
||
193 | memlen = 1024 * 32; |
||
194 | break; |
||
195 | case 1: |
||
196 | memlen = 1024 * 4; |
||
197 | break; |
||
198 | case 2: |
||
199 | memlen = 1024 * 8; |
||
200 | break; |
||
201 | case 3: |
||
202 | default: |
||
203 | memlen = 1024 * 16; |
||
204 | break; |
||
205 | } |
||
206 | } |
||
207 | break; |
||
208 | case NV_ARCH_10: |
||
209 | case NV_ARCH_20: |
||
210 | if(chipset == NV_CHIP_IGEFORCE2) { |
||
211 | |||
212 | dev = pci_find_slot(0, 1); |
||
213 | pci_read_config_dword(dev, 0x7C, &amt); |
||
214 | memlen = (((amt >> 6) & 31) + 1) * 1024; |
||
215 | } else if (chipset == NV_CHIP_0x01F0) { |
||
216 | dev = pci_find_slot(0, 1); |
||
217 | pci_read_config_dword(dev, 0x84, &amt); |
||
218 | memlen = (((amt >> 4) & 127) + 1) * 1024; |
||
219 | } else { |
||
220 | switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF){ |
||
221 | case 0x02: |
||
222 | memlen = 1024 * 2; |
||
223 | break; |
||
224 | case 0x04: |
||
225 | memlen = 1024 * 4; |
||
226 | break; |
||
227 | case 0x08: |
||
228 | memlen = 1024 * 8; |
||
229 | break; |
||
230 | case 0x10: |
||
231 | memlen = 1024 * 16; |
||
232 | break; |
||
233 | case 0x20: |
||
234 | memlen = 1024 * 32; |
||
235 | break; |
||
236 | case 0x40: |
||
237 | memlen = 1024 * 64; |
||
238 | break; |
||
239 | case 0x80: |
||
240 | memlen = 1024 * 128; |
||
241 | break; |
||
242 | default: |
||
243 | memlen = 1024 * 16; |
||
244 | break; |
||
245 | } |
||
246 | } |
||
247 | break; |
||
248 | } |
||
249 | return memlen; |
||
250 | } |
||
251 | |||
252 | unsigned long riva_get_maxdclk(struct riva_par *par) |
||
253 | { |
||
254 | RIVA_HW_INST *chip = &par->riva; |
||
255 | unsigned long dclk = 0; |
||
256 | |||
257 | switch (chip->Architecture) { |
||
258 | case NV_ARCH_03: |
||
259 | if (chip->PFB[0x00000000/4] & 0x00000020) { |
||
260 | if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20) |
||
261 | && ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02)) { |
||
262 | /* |
||
263 | * SDRAM 128 ZX. |
||
264 | */ |
||
265 | dclk = 800000; |
||
266 | } else { |
||
267 | dclk = 1000000; |
||
268 | } |
||
269 | } else { |
||
270 | /* |
||
271 | * SGRAM 128. |
||
272 | */ |
||
273 | dclk = 1000000; |
||
274 | } |
||
275 | break; |
||
276 | case NV_ARCH_04: |
||
277 | case NV_ARCH_10: |
||
278 | case NV_ARCH_20: |
||
279 | switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003) { |
||
280 | case 3: |
||
281 | dclk = 800000; |
||
282 | break; |
||
283 | default: |
||
284 | dclk = 1000000; |
||
285 | break; |
||
286 | } |
||
287 | break; |
||
288 | } |
||
289 | return dclk; |
||
290 | } |
||
291 | |||
292 | void |
||
293 | riva_common_setup(struct riva_par *par) |
||
294 | { |
||
295 | par->riva.EnableIRQ = 0; |
||
296 | par->riva.PRAMDAC0 = (unsigned *)(par->ctrl_base + 0x00680000); |
||
297 | par->riva.PFB = (unsigned *)(par->ctrl_base + 0x00100000); |
||
298 | par->riva.PFIFO = (unsigned *)(par->ctrl_base + 0x00002000); |
||
299 | par->riva.PGRAPH = (unsigned *)(par->ctrl_base + 0x00400000); |
||
300 | par->riva.PEXTDEV = (unsigned *)(par->ctrl_base + 0x00101000); |
||
301 | par->riva.PTIMER = (unsigned *)(par->ctrl_base + 0x00009000); |
||
302 | par->riva.PMC = (unsigned *)(par->ctrl_base + 0x00000000); |
||
303 | par->riva.FIFO = (unsigned *)(par->ctrl_base + 0x00800000); |
||
304 | par->riva.PCIO0 = (U008 *)(par->ctrl_base + 0x00601000); |
||
305 | par->riva.PDIO0 = (U008 *)(par->ctrl_base + 0x00681000); |
||
306 | par->riva.PVIO = (U008 *)(par->ctrl_base + 0x000C0000); |
||
307 | |||
308 | par->riva.IO = (MISCin(par) & 0x01) ? 0x3D0 : 0x3B0; |
||
309 | |||
310 | if (par->FlatPanel == -1) { |
||
311 | switch (par->Chipset) { |
||
312 | case NV_CHIP_GEFORCE4_440_GO: |
||
313 | case NV_CHIP_GEFORCE4_440_GO_M64: |
||
314 | case NV_CHIP_GEFORCE4_420_GO: |
||
315 | case NV_CHIP_GEFORCE4_420_GO_M32: |
||
316 | case NV_CHIP_QUADRO4_500_GOGL: |
||
317 | case NV_CHIP_GEFORCE2_GO: |
||
318 | printk(KERN_INFO PFX |
||
319 | "On a laptop. Assuming Digital Flat Panel\n"); |
||
320 | par->FlatPanel = 1; |
||
321 | break; |
||
322 | default: |
||
323 | break; |
||
324 | } |
||
325 | } |
||
326 | |||
327 | switch (par->Chipset & 0x0ff0) { |
||
328 | case 0x0110: |
||
329 | if (par->Chipset == NV_CHIP_GEFORCE2_GO) |
||
330 | par->SecondCRTC = TRUE; |
||
331 | #if defined(__powerpc__) |
||
332 | if (par->FlatPanel == 1) |
||
333 | par->SecondCRTC = TRUE; |
||
334 | #endif |
||
335 | riva_override_CRTC(par); |
||
336 | break; |
||
337 | case 0x0170: |
||
338 | case 0x0180: |
||
339 | case 0x01F0: |
||
340 | case 0x0250: |
||
341 | case 0x0280: |
||
342 | riva_is_second(par); |
||
343 | break; |
||
344 | default: |
||
345 | break; |
||
346 | } |
||
347 | |||
348 | if (par->SecondCRTC) { |
||
349 | par->riva.PCIO = par->riva.PCIO0 + 0x2000; |
||
350 | par->riva.PCRTC = par->riva.PCRTC0 + 0x800; |
||
351 | par->riva.PRAMDAC = par->riva.PRAMDAC0 + 0x800; |
||
352 | par->riva.PDIO = par->riva.PDIO0 + 0x2000; |
||
353 | } else { |
||
354 | par->riva.PCIO = par->riva.PCIO0; |
||
355 | par->riva.PCRTC = par->riva.PCRTC0; |
||
356 | par->riva.PRAMDAC = par->riva.PRAMDAC0; |
||
357 | par->riva.PDIO = par->riva.PDIO0; |
||
358 | } |
||
359 | |||
360 | if (par->FlatPanel == -1) { |
||
361 | /* Fix me, need x86 DDC code */ |
||
362 | par->FlatPanel = 0; |
||
363 | } |
||
364 | par->riva.flatPanel = (par->FlatPanel > 0) ? TRUE : FALSE; |
||
365 | } |
||
366 |