Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
54 | pj | 1 | /* |
2 | Riva 128 driver - Matan Ziv-Av matan@svgalib.org |
||
3 | please report problems to me, |
||
4 | |||
5 | This driver is based on the XFREE86 nv3 driver, developed by |
||
6 | David J. Mckay. |
||
7 | |||
8 | I used the file cirrus.c in this directory as a skeleton. |
||
9 | |||
10 | there are still the following problems: |
||
11 | * no 24bit modes. (maybe the hardware does not support) |
||
12 | * pageflipping (in threeDKit) does not work. |
||
13 | * no acceleration (is there a program that uses it anyway?). |
||
14 | */ |
||
15 | |||
16 | #include <stdlib.h> |
||
17 | #include <stdio.h> /* for printf */ |
||
18 | #include <string.h> /* for memset */ |
||
19 | //#include <sys/mman.h> //SHARK |
||
20 | #include <fcntl.h> |
||
21 | #include <math.h> |
||
22 | #include <unistd.h> |
||
23 | #include "vga.h" |
||
24 | #include "libvga.h" |
||
25 | #include "driver.h" |
||
26 | |||
27 | /* New style driver interface. */ |
||
28 | #include "timing.h" |
||
29 | #include "vgaregs.h" |
||
30 | #include "interface.h" |
||
31 | #include "nv3ref.h" |
||
32 | #include "nvreg.h" |
||
33 | #include "vgapci.h" |
||
34 | |||
35 | #define REG(i) (VGA_TOTAL_REGS+i) |
||
36 | #define NV3_TOTAL_REGS (VGA_TOTAL_REGS + 24 + 40 ) |
||
37 | |||
38 | #define P_MIN 0 |
||
39 | |||
40 | #define SetBitField(value,from,to) SetBF(to,GetBF(value,from)) |
||
41 | #define SetBit(n) (1<<(n)) |
||
42 | #define Set8Bits(value) ((value)&0xff) |
||
43 | |||
44 | #define GET15BITCOLOR(r,g,b) ((((r)&0xf8)<<7)|(((g)&0xf8)<<2)|((b)>>3)) |
||
45 | |||
46 | #include "nv3io.c" |
||
47 | |||
48 | static int nv3_init(int, int, int); |
||
49 | static void nv3_unlock(void); |
||
50 | |||
51 | static int memory, chip, nvnum; |
||
52 | static int nv3_is_linear; |
||
53 | static CardSpecs *cardspecs; |
||
54 | static int PLL_INPUT_FREQ, MAXVCLOCK, M_MIN, M_MAX, P_MAX; |
||
55 | |||
56 | static unsigned long MMIOBASE, LINEARBASE; |
||
57 | |||
58 | enum { |
||
59 | Riva128 = 0, RivaTNT, GEFORCE |
||
60 | }; |
||
61 | |||
62 | static void nv3_setpage(int page) |
||
63 | { |
||
64 | __svgalib_outcrtc(0x1d,page << 1); |
||
65 | __svgalib_outcrtc(0x1e,page << 1); |
||
66 | } |
||
67 | |||
68 | static int __svgalib_nv3_inlinearmode(void) |
||
69 | { |
||
70 | return nv3_is_linear; |
||
71 | } |
||
72 | |||
73 | /* Fill in chipset specific mode information */ |
||
74 | |||
75 | static void nv3_getmodeinfo(int mode, vga_modeinfo *modeinfo) |
||
76 | { |
||
77 | |||
78 | if(modeinfo->colors==16)return; |
||
79 | |||
80 | modeinfo->maxpixels = memory*1024/modeinfo->bytesperpixel; |
||
81 | modeinfo->maxlogicalwidth = 4088; |
||
82 | modeinfo->startaddressrange = memory * 1024 - 1; |
||
83 | modeinfo->haveblit = 0; |
||
84 | modeinfo->flags &= ~HAVE_RWPAGE; |
||
85 | |||
86 | if (modeinfo->bytesperpixel >= 1) { |
||
87 | modeinfo->flags |= CAPABLE_LINEAR; |
||
88 | if (__svgalib_nv3_inlinearmode()) |
||
89 | modeinfo->flags |= IS_LINEAR | LINEAR_MODE; |
||
90 | } |
||
91 | } |
||
92 | |||
93 | /* Read and save chipset-specific registers */ |
||
94 | |||
95 | static int nv3_saveregs(unsigned char regs[]) |
||
96 | { |
||
97 | int i; |
||
98 | nv3_unlock(); /* May be locked again by other programs (e.g. X) */ |
||
99 | |||
100 | regs[REG(0)] = __svgalib_incrtc(NV_PCRTC_REPAINT0); |
||
101 | regs[REG(1)] = __svgalib_incrtc(NV_PCRTC_REPAINT1); |
||
102 | regs[REG(2)] = __svgalib_incrtc(NV_PCRTC_EXTRA); |
||
103 | regs[REG(3)] = __svgalib_incrtc(NV_PCRTC_PIXEL); |
||
104 | regs[REG(4)] = __svgalib_incrtc(NV_PCRTC_HORIZ_EXTRA); |
||
105 | regs[REG(5)] = __svgalib_incrtc(NV_PCRTC_FIFO_CONTROL); |
||
106 | regs[REG(6)] = __svgalib_incrtc(NV_PCRTC_FIFO); |
||
107 | regs[REG(7)] = __svgalib_incrtc(NV_PCRTC_SCREEN); |
||
108 | |||
109 | *(uint32_t *)(regs+REG(8)) = v_readl(NV_PFB_CONFIG_0); |
||
110 | *(uint32_t *)(regs+REG(12)) = v_readl(NV_PRAMDAC_VPLL_COEFF); |
||
111 | *(uint32_t *)(regs+REG(16)) = v_readl(NV_PRAMDAC_PLL_COEFF_SELECT); |
||
112 | *(uint32_t *)(regs+REG(20)) = v_readl(NV_PRAMDAC_GENERAL_CONTROL); |
||
113 | *(uint32_t *)(regs+REG(56)) = v_readl(NV_PRAMDAC_GRCURSOR_START_POS); |
||
114 | for(i=0x18;i<0x3A;i++)regs[84+i-0x18]=__svgalib_incrtc(i); |
||
115 | |||
116 | return NV3_TOTAL_REGS - VGA_TOTAL_REGS; |
||
117 | } |
||
118 | |||
119 | /* Set chipset-specific registers */ |
||
120 | |||
121 | static void nv3_setregs(const unsigned char regs[], int mode) |
||
122 | { |
||
123 | nv3_unlock(); /* May be locked again by other programs (eg. X) */ |
||
124 | |||
125 | __svgalib_outcrtc(NV_PCRTC_REPAINT0,regs[REG(0)]); |
||
126 | __svgalib_outcrtc(NV_PCRTC_REPAINT1,regs[REG(1)]); |
||
127 | __svgalib_outcrtc(NV_PCRTC_EXTRA,regs[REG(2)]); |
||
128 | __svgalib_outcrtc(NV_PCRTC_PIXEL,regs[REG(3)]); |
||
129 | __svgalib_outcrtc(NV_PCRTC_HORIZ_EXTRA,regs[REG(4)]); |
||
130 | __svgalib_outcrtc(NV_PCRTC_FIFO_CONTROL,regs[REG(5)]); |
||
131 | __svgalib_outcrtc(NV_PCRTC_FIFO,regs[REG(6)]); |
||
132 | if(chip>= GEFORCE) |
||
133 | __svgalib_outcrtc(NV_PCRTC_SCREEN,regs[REG(7)]); |
||
134 | |||
135 | __svgalib_outcrtc(0x1c,regs[88]); /* this enables banking at 0xa0000 */ |
||
136 | __svgalib_outcrtc(0x1d,regs[89]); |
||
137 | __svgalib_outcrtc(0x1e,regs[90]); |
||
138 | __svgalib_outcrtc(0x30,regs[108]); |
||
139 | __svgalib_outcrtc(0x31,regs[109]); |
||
140 | __svgalib_outcrtc(0x39,regs[117]); |
||
141 | |||
142 | v_writel(*(uint32_t *)(regs+REG(8)), NV_PFB_CONFIG_0); |
||
143 | |||
144 | v_writel(*(uint32_t *)(regs+REG(12)), NV_PRAMDAC_VPLL_COEFF); |
||
145 | v_writel(*(uint32_t *)(regs+REG(16)), NV_PRAMDAC_PLL_COEFF_SELECT); |
||
146 | v_writel(*(uint32_t *)(regs+REG(20)), NV_PRAMDAC_GENERAL_CONTROL); |
||
147 | v_writel(*(uint32_t *)(regs+REG(56)), NV_PRAMDAC_GRCURSOR_START_POS); |
||
148 | } |
||
149 | |||
150 | |||
151 | /* Return nonzero if mode is available */ |
||
152 | |||
153 | static int nv3_modeavailable(int mode) |
||
154 | { |
||
155 | struct info *info; |
||
156 | ModeTiming *modetiming; |
||
157 | ModeInfo *modeinfo; |
||
158 | |||
159 | printk(KERN_INFO "Test Mode...\n"); |
||
160 | |||
161 | if (IS_IN_STANDARD_VGA_DRIVER(mode)) |
||
162 | return __svgalib_vga_driverspecs.modeavailable(mode); |
||
163 | |||
164 | info = &__svgalib_infotable[mode]; |
||
165 | if (memory * 1024 < info->ydim * info->xbytes) |
||
166 | return 0; |
||
167 | |||
168 | modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); |
||
169 | |||
170 | if(modeinfo->bitsPerPixel==24) { |
||
171 | free(modeinfo); |
||
172 | return 0; |
||
173 | } |
||
174 | |||
175 | printk(KERN_INFO "Test Timing...\n"); |
||
176 | |||
177 | modetiming = malloc(sizeof(ModeTiming)); |
||
178 | |||
179 | if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { |
||
180 | printk(KERN_INFO "Test Mode Failed !\n"); |
||
181 | free(modetiming); |
||
182 | free(modeinfo); |
||
183 | return 0; |
||
184 | } |
||
185 | |||
186 | free(modetiming); |
||
187 | free(modeinfo); |
||
188 | return SVGADRV; |
||
189 | } |
||
190 | |||
191 | static int CalcVClock(int clockIn,int *clockOut,int *mOut, |
||
192 | int *nOut,int *pOut); |
||
193 | |||
194 | static int CalculateCRTC(ModeTiming *mode, ModeInfo *modeinfo, unsigned char *moderegs) |
||
195 | { |
||
196 | int bpp=modeinfo->bitsPerPixel/8, |
||
197 | horizDisplay = (mode->CrtcHDisplay/8) - 1, |
||
198 | horizStart = (mode->CrtcHSyncStart/8) - 0, |
||
199 | horizEnd = (mode->CrtcHSyncEnd/8) - 0, |
||
200 | horizTotal = (mode->CrtcHTotal/8) - 5, |
||
201 | horizBlankStart = (mode->CrtcHDisplay/8) - 1, |
||
202 | horizBlankEnd = (mode->CrtcHTotal/8) - 1, |
||
203 | vertDisplay = mode->CrtcVDisplay - 1, |
||
204 | vertStart = mode->CrtcVSyncStart - 1, |
||
205 | vertEnd = mode->CrtcVSyncEnd - 1, |
||
206 | vertTotal = mode->CrtcVTotal - 2, |
||
207 | vertBlankStart = mode->CrtcVDisplay - 1, |
||
208 | vertBlankEnd = mode->CrtcVTotal - 1; |
||
209 | |||
210 | if(mode->flags & INTERLACED) vertTotal |= 1; |
||
211 | |||
212 | /* Calculate correct value for offset register */ |
||
213 | moderegs[0x13]=((modeinfo->width/8)*bpp)&0xff; |
||
214 | |||
215 | /* Extra bits for CRTC offset register */ |
||
216 | moderegs[REG(0)]= |
||
217 | SetBitField((modeinfo->width/8)*bpp,10:8,7:5); |
||
218 | |||
219 | /* The NV3 manuals states that for native modes, there should be no |
||
220 | * borders. This code should also be tidied up to use symbolic names |
||
221 | */ |
||
222 | moderegs[0x0]=Set8Bits(horizTotal); |
||
223 | moderegs[0x1]=Set8Bits(horizDisplay); |
||
224 | moderegs[0x2]=Set8Bits(horizBlankStart); |
||
225 | moderegs[0x3]=SetBitField(horizBlankEnd,4:0,4:0) | SetBit(7); |
||
226 | moderegs[0x4]=Set8Bits(horizStart); |
||
227 | moderegs[0x5]=SetBitField(horizBlankEnd,5:5,7:7)| |
||
228 | SetBitField(horizEnd,4:0,4:0); |
||
229 | moderegs[0x6]=SetBitField(vertTotal,7:0,7:0); |
||
230 | |||
231 | moderegs[0x7]=SetBitField(vertTotal,8:8,0:0)| |
||
232 | SetBitField(vertDisplay,8:8,1:1)| |
||
233 | SetBitField(vertStart,8:8,2:2)| |
||
234 | SetBitField(vertBlankStart,8:8,3:3)| |
||
235 | SetBit(4)| |
||
236 | SetBitField(vertTotal,9:9,5:5)| |
||
237 | SetBitField(vertDisplay,9:9,6:6)| |
||
238 | SetBitField(vertStart,9:9,7:7); |
||
239 | |||
240 | moderegs[0x9]= SetBitField(vertBlankStart,9:9,5:5) | SetBit(6); |
||
241 | moderegs[0x10]= Set8Bits(vertStart); |
||
242 | moderegs[0x11]= SetBitField(vertEnd,3:0,3:0) | SetBit(5); |
||
243 | moderegs[0x12]= Set8Bits(vertDisplay); |
||
244 | moderegs[0x15]= Set8Bits(vertBlankStart); |
||
245 | moderegs[0x16]= Set8Bits(vertBlankEnd); |
||
246 | |||
247 | moderegs[REG(2)] = SetBitField(horizBlankEnd,6:6,4:4) |
||
248 | | SetBitField(vertBlankStart,10:10,3:3) |
||
249 | | SetBitField(vertStart,10:10,2:2) |
||
250 | | SetBitField(vertDisplay,10:10,1:1) |
||
251 | | SetBitField(vertTotal,10:10,0:0); |
||
252 | |||
253 | moderegs[REG(4)] = SetBitField(horizTotal,8:8,0:0) |
||
254 | | SetBitField(horizDisplay,8:8,1:1) |
||
255 | | SetBitField(horizBlankStart,8:8,2:2) |
||
256 | | SetBitField(horizStart,8:8,3:3); |
||
257 | |||
258 | moderegs[REG(7)] = SetBitField(vertTotal,11:11,0:0) |
||
259 | | SetBitField(vertDisplay,11:11,2:2) |
||
260 | | SetBitField(vertStart,11:11,4:4) |
||
261 | | SetBitField(vertBlankStart,11:11,6:6); |
||
262 | |||
263 | if(mode->flags & DOUBLESCAN) moderegs[0x9]|=0x80; |
||
264 | |||
265 | /* I think this should be SetBitField(horizTotal,8:8,0:0), but this |
||
266 | * doesn't work apparently. Why 260 ? 256 would make sense. |
||
267 | */ |
||
268 | if(mode->flags & INTERLACED) { |
||
269 | horizTotal=(horizTotal>>1)& ~1; |
||
270 | moderegs[117]=horizTotal & 0xff; |
||
271 | moderegs[REG(4)] |= SetBitField(horizTotal,8:8,4:4); |
||
272 | } else { |
||
273 | moderegs[117]=255; |
||
274 | } |
||
275 | |||
276 | return 1; |
||
277 | } |
||
278 | |||
279 | /* Set a mode */ |
||
280 | |||
281 | /* Local, called by nv3_setmode(). */ |
||
282 | |||
283 | static void nv3_initializemode(unsigned char *moderegs, |
||
284 | ModeTiming * modetiming, ModeInfo * modeinfo, int mode) |
||
285 | { |
||
286 | long k; |
||
287 | unsigned int config0=0; |
||
288 | |||
289 | int m,n,p; |
||
290 | int clockIn=modetiming->pixelClock; |
||
291 | int clockOut; |
||
292 | int pixelDepth; |
||
293 | |||
294 | nv3_saveregs(moderegs); |
||
295 | |||
296 | __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); |
||
297 | |||
298 | CalcVClock(clockIn,&clockOut,&m,&n,&p); |
||
299 | |||
300 | *(unsigned int *)(moderegs+REG(12)) = PRAMDAC_Val(VPLL_COEFF_NDIV,n) | |
||
301 | PRAMDAC_Val(VPLL_COEFF_MDIV,m) | |
||
302 | PRAMDAC_Val(VPLL_COEFF_PDIV,p); |
||
303 | |||
304 | CalculateCRTC(modetiming,modeinfo,moderegs); |
||
305 | |||
306 | moderegs[REG(1)] = PCRTC_Val(REPAINT1_LARGE_SCREEN,modetiming->CrtcHDisplay<1280); |
||
307 | |||
308 | /* The new xfree driver (from nVidia) calculates those in some |
||
309 | twisted way, but I leave it for now */ |
||
310 | moderegs[REG(5)]=0x83; |
||
311 | if(modetiming->pixelClock*modeinfo->bytesPerPixel>720000) { |
||
312 | moderegs[REG(6)]=0x2f; |
||
313 | } |
||
314 | |||
315 | /* PixelFormat controls how many bits per pixel. |
||
316 | * There is another register in the |
||
317 | * DAC which controls if mode is 5:5:5 or 5:6:5 |
||
318 | */ |
||
319 | pixelDepth=(modeinfo->bitsPerPixel+1)/8; |
||
320 | if(pixelDepth>3) pixelDepth=3; |
||
321 | moderegs[REG(3)]=pixelDepth; |
||
322 | if(modetiming->flags & TVMODE) { |
||
323 | moderegs[REG(3)]|=0x80; |
||
324 | if(modetiming->flags & TVPAL) moderegs[REG(3)]|=0x40; |
||
325 | }; |
||
326 | |||
327 | *(unsigned int *)(moderegs+REG(20))= |
||
328 | PRAMDAC_Def(GENERAL_CONTROL_IDC_MODE,GAMMA)| |
||
329 | PRAMDAC_Val(GENERAL_CONTROL_565_MODE,modeinfo->greenWeight==6)| |
||
330 | PRAMDAC_Def(GENERAL_CONTROL_TERMINATION,37OHM)| |
||
331 | ((modeinfo->bitsPerPixel>8) ? |
||
332 | PRAMDAC_Def(GENERAL_CONTROL_BPC,8BITS) : |
||
333 | PRAMDAC_Def(GENERAL_CONTROL_BPC,6BITS)) | PRAMDAC_Def(GENERAL_CONTROL_VGA_STATE,SEL); |
||
334 | /* Not sure about this */ |
||
335 | |||
336 | switch(chip){ |
||
337 | case Riva128: |
||
338 | config0=PFB_Val(CONFIG_0_RESOLUTION,((modeinfo->lineWidth+31)/32))| |
||
339 | PFB_Val(CONFIG_0_PIXEL_DEPTH,pixelDepth)| |
||
340 | PFB_Def(CONFIG_0_TILING,DISABLED); |
||
341 | k=PRAMDAC_Def(PLL_COEFF_SELECT_MPLL_SOURCE,PROG)| |
||
342 | PRAMDAC_Def(PLL_COEFF_SELECT_VPLL_SOURCE,PROG)| |
||
343 | PRAMDAC_Def(PLL_COEFF_SELECT_VCLK_RATIO,DB2); |
||
344 | moderegs[REG(1)] |= PCRTC_Def(REPAINT1_PALETTE_WIDTH,6BITS); |
||
345 | break; |
||
346 | case RivaTNT: |
||
347 | config0=0x1114; |
||
348 | k=0x10000700; |
||
349 | break; |
||
350 | case GEFORCE: |
||
351 | default: |
||
352 | config0=*(unsigned int *)(moderegs+REG(8)); |
||
353 | k=0x10000700; |
||
354 | break; |
||
355 | }; |
||
356 | |||
357 | *(unsigned int *)(moderegs+REG(16))=k; |
||
358 | *(unsigned int *)(moderegs+REG(8))=config0; |
||
359 | |||
360 | moderegs[88]=28; |
||
361 | moderegs[109]&=0xfe; /* hide cursor */ |
||
362 | |||
363 | nv3_is_linear=0; |
||
364 | |||
365 | return ; |
||
366 | } |
||
367 | |||
368 | |||
369 | int nv3_setmode(int mode, int prv_mode) |
||
370 | { |
||
371 | unsigned char *moderegs; |
||
372 | ModeTiming *modetiming; |
||
373 | ModeInfo *modeinfo; |
||
374 | int i; |
||
375 | |||
376 | if (IS_IN_STANDARD_VGA_DRIVER(mode)) { |
||
377 | |||
378 | unsigned int k; |
||
379 | |||
380 | printk(KERN_INFO "Standard VGA Mode\n"); |
||
381 | |||
382 | if(chip==Riva128) |
||
383 | v_writel(0x00000100, NV_PRAMDAC_PLL_COEFF_SELECT); |
||
384 | else v_writel(0x00000500, NV_PRAMDAC_PLL_COEFF_SELECT); |
||
385 | __svgalib_outcrtc(NV_PCRTC_REPAINT0,0); |
||
386 | __svgalib_outcrtc(NV_PCRTC_REPAINT1,0x3d); |
||
387 | __svgalib_outcrtc(NV_PCRTC_EXTRA,0); |
||
388 | __svgalib_outcrtc(NV_PCRTC_PIXEL,0); |
||
389 | __svgalib_outcrtc(NV_PCRTC_HORIZ_EXTRA,0); |
||
390 | __svgalib_outcrtc(NV_PCRTC_FIFO_CONTROL,0x83); |
||
391 | __svgalib_outcrtc(0x1c,0x18); |
||
392 | __svgalib_outcrtc(0x1d,0); |
||
393 | __svgalib_outcrtc(0x1e,0); |
||
394 | __svgalib_outcrtc(0x30,0); |
||
395 | __svgalib_outcrtc(0x31,0); |
||
396 | k = v_readl(NV_PRAMDAC_GENERAL_CONTROL); |
||
397 | k &= ~0x00100000; |
||
398 | v_writel(k, NV_PRAMDAC_GENERAL_CONTROL); |
||
399 | |||
400 | return __svgalib_vga_driverspecs.setmode(mode, prv_mode); |
||
401 | } |
||
402 | |||
403 | if (!nv3_modeavailable(mode)) |
||
404 | return 1; |
||
405 | |||
406 | printk(KERN_INFO "Mode Available !\nStart Set Mode...\n"); |
||
407 | |||
408 | modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); |
||
409 | |||
410 | modetiming = malloc(sizeof(ModeTiming)); |
||
411 | if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { |
||
412 | free(modetiming); |
||
413 | free(modeinfo); |
||
414 | return 1; |
||
415 | } |
||
416 | |||
417 | moderegs = malloc(NV3_TOTAL_REGS); |
||
418 | |||
419 | printk(KERN_INFO "Start Init Mode...\n"); |
||
420 | |||
421 | nv3_initializemode(moderegs, modetiming, modeinfo, mode); |
||
422 | free(modetiming); |
||
423 | |||
424 | __svgalib_setregs(moderegs); /* Set standard regs. */ |
||
425 | nv3_setregs(moderegs, mode); /* Set extended regs. */ |
||
426 | free(moderegs); |
||
427 | |||
428 | __svgalib_InitializeAcceleratorInterface(modeinfo); |
||
429 | |||
430 | for(i=0;i<256;i++)vga_setpalette(i,i,i,i); |
||
431 | free(modeinfo); |
||
432 | return 0; |
||
433 | } |
||
434 | |||
435 | /* Unlock chipset-specific registers */ |
||
436 | |||
437 | static void nv3_unlock(void) |
||
438 | { |
||
439 | if(chip!=Riva128) { |
||
440 | __svgalib_nv3_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); |
||
441 | __svgalib_nv3_outcrtc(0x1f, UNLOCK_EXT_MAGIC); |
||
442 | } else { |
||
443 | // __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); |
||
444 | __svgalib_outseq(LOCK_EXT_INDEX,UNLOCK_EXT_MAGIC); |
||
445 | } |
||
446 | } |
||
447 | |||
448 | /* Relock chipset-specific registers */ |
||
449 | /* (currently not used) */ |
||
450 | |||
451 | static void nv3_lock(void) |
||
452 | { |
||
453 | __svgalib_outseq(LOCK_EXT_INDEX,UNLOCK_EXT_MAGIC+1); |
||
454 | |||
455 | } |
||
456 | |||
457 | /* Indentify chipset, initialize and return non-zero if detected */ |
||
458 | |||
459 | int nv3_test(void) |
||
460 | { unsigned long buf[64]; |
||
461 | int found=0; |
||
462 | |||
463 | MMIOBASE=0; /* let nv3_init() find those */ |
||
464 | LINEARBASE=0; |
||
465 | nv3_init(0,0,0); |
||
466 | return 1; |
||
467 | } |
||
468 | |||
469 | /* No r/w paging - I guess it's possible, but is it useful? */ |
||
470 | static void nv3_setrdpage(int page) |
||
471 | { |
||
472 | } |
||
473 | static void nv3_setwrpage(int page) |
||
474 | { |
||
475 | } |
||
476 | |||
477 | /* Set display start address (not for 16 color modes) */ |
||
478 | |||
479 | static void nv3_setdisplaystart(int address) |
||
480 | { unsigned char byte; |
||
481 | int pan; |
||
482 | |||
483 | pan=(address&3)<<1; |
||
484 | address=address >> 2; |
||
485 | __svgalib_outcrtc(0x0d,address&0xff); |
||
486 | __svgalib_outcrtc(0x0c,(address>>8)&0xff); |
||
487 | byte=__svgalib_incrtc(NV_PCRTC_REPAINT0) & 0xe0; |
||
488 | __svgalib_outcrtc(NV_PCRTC_REPAINT0,((address>>16)&0x1f)|byte); |
||
489 | byte=__svgalib_incrtc(0x2D) & ~0x60; |
||
490 | __svgalib_outcrtc(0x2D,((address>>16)&0x60)|byte); |
||
491 | |||
492 | byte = __svgalib_inis1(); |
||
493 | __svgalib_outatt(0x13, pan); |
||
494 | } |
||
495 | |||
496 | /* Set logical scanline length (usually multiple of 8) */ |
||
497 | |||
498 | static void nv3_setlogicalwidth(int width) |
||
499 | { int byte ; |
||
500 | |||
501 | __svgalib_outcrtc(0x13,(width >> 3)&0xff); |
||
502 | byte=__svgalib_incrtc(NV_PCRTC_REPAINT0) & 0x1f; |
||
503 | __svgalib_outcrtc(NV_PCRTC_REPAINT0,SetBitField(width,13:11,7:5)|byte); |
||
504 | |||
505 | } |
||
506 | |||
507 | static int nv3_linear(int op, int param) |
||
508 | { |
||
509 | if (op==LINEAR_ENABLE){ nv3_is_linear=1; return 0;} |
||
510 | if (op==LINEAR_DISABLE){ nv3_is_linear=0; return 0;} |
||
511 | if (op==LINEAR_QUERY_BASE) { return LINEARBASE ;} |
||
512 | if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ |
||
513 | else return -1; /* Unknown function. */ |
||
514 | } |
||
515 | |||
516 | static int nv3_cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { |
||
517 | unsigned char *b1, *b2; |
||
518 | unsigned short *b3; |
||
519 | unsigned int i, j, k, l, c0, c1; |
||
520 | |||
521 | switch(cmd){ |
||
522 | case CURSOR_INIT: |
||
523 | return 1; |
||
524 | case CURSOR_HIDE: |
||
525 | __svgalib_outcrtc(0x31,__svgalib_incrtc(0x31)&0xfe); /* disable cursor */ |
||
526 | break; |
||
527 | case CURSOR_SHOW: |
||
528 | __svgalib_outcrtc(0x31,__svgalib_incrtc(0x31)|1); /* enable cursor */ |
||
529 | break; |
||
530 | case CURSOR_POSITION: |
||
531 | v_writel(p1+(p2<<16), NV_PRAMDAC_GRCURSOR_START_POS); |
||
532 | break; |
||
533 | case CURSOR_SELECT: |
||
534 | i=memory/2-(p1+1); |
||
535 | if (chip==Riva128) { |
||
536 | __svgalib_outcrtc(0x31,(__svgalib_incrtc(0x31)&7)|(((~i)&0x1f)<<3)); |
||
537 | } else { |
||
538 | __svgalib_outcrtc(0x31,(__svgalib_incrtc(0x31)&3)|(((~i)&0x3f)<<2)); |
||
539 | } |
||
540 | #if 0 |
||
541 | __svgalib_outcrtc(0x30,((~i)&0x3fc0)>>6); |
||
542 | #else |
||
543 | __svgalib_outcrtc(0x30,0); |
||
544 | #endif |
||
545 | break; |
||
546 | case CURSOR_IMAGE: |
||
547 | i=memory/2-(p1+1); |
||
548 | i=i*2048; |
||
549 | switch(p2) { |
||
550 | case 0: /* X11 format, 32x32 */ |
||
551 | b3=malloc(2048); |
||
552 | b1=(unsigned char *)p5; |
||
553 | b2=b1+128; |
||
554 | c0=0x8000|GET15BITCOLOR((p3>>16)&0xff,(p3>>8)&0xff,p3&0xff); |
||
555 | c1=0x8000|GET15BITCOLOR((p4>>16)&0xff,(p4>>8)&0xff,p4&0xff); |
||
556 | l=992; |
||
557 | for(k=0;k<128;k++) { |
||
558 | int cc1=*(b1+k); |
||
559 | int cc2=*(b2+k); |
||
560 | for(j=0;j<8;j++) { |
||
561 | if(!(cc2&0x80)) *(b3+l)=0; else if (cc1&0x80) |
||
562 | *(b3+l)=c1; else *(b3+l)=c0; |
||
563 | l++; |
||
564 | if((l&0x1f)==0)l-=64; |
||
565 | cc2<<=1; |
||
566 | cc1<<=1; |
||
567 | } |
||
568 | } |
||
569 | memcpy(LINEAR_POINTER+i,b3,2048); |
||
570 | free(b3); |
||
571 | break; |
||
572 | case 1: /* nvidia 1555 format 32x32 */ |
||
573 | memcpy(LINEAR_POINTER+i,p5,2048); |
||
574 | break; |
||
575 | } |
||
576 | break; |
||
577 | } |
||
578 | return 0; |
||
579 | } |
||
580 | |||
581 | static int nv3_match_programmable_clock(int clock) |
||
582 | { |
||
583 | return clock ; |
||
584 | } |
||
585 | static int nv3_map_clock(int bpp, int clock) |
||
586 | { |
||
587 | return clock ; |
||
588 | } |
||
589 | static int nv3_map_horizontal_crtc(int bpp, int pixelclock, int htiming) |
||
590 | { |
||
591 | return htiming; |
||
592 | } |
||
593 | /* Function table (exported) */ |
||
594 | |||
595 | DriverSpecs __svgalib_nv3_driverspecs = |
||
596 | { |
||
597 | nv3_saveregs, |
||
598 | nv3_setregs, |
||
599 | nv3_unlock, |
||
600 | nv3_lock, |
||
601 | nv3_test, |
||
602 | nv3_init, |
||
603 | nv3_setpage, |
||
604 | nv3_setrdpage, |
||
605 | nv3_setwrpage, |
||
606 | nv3_setmode, |
||
607 | nv3_modeavailable, |
||
608 | nv3_setdisplaystart, |
||
609 | nv3_setlogicalwidth, |
||
610 | nv3_getmodeinfo, |
||
611 | 0, /* old blit funcs */ |
||
612 | 0, |
||
613 | 0, |
||
614 | 0, |
||
615 | 0, |
||
616 | 0, /* ext_set */ |
||
617 | 0, /* accel */ |
||
618 | nv3_linear, |
||
619 | 0, /* accelspecs, filled in during init. */ |
||
620 | 0, |
||
621 | nv3_cursor |
||
622 | }; |
||
623 | |||
624 | /* Initialize chipset (called after detection) */ |
||
625 | |||
626 | static int nv3_init(int force, int par1, int par2) //SHARK |
||
627 | { |
||
628 | char *archs[3]={"Riva128", |
||
629 | "RivaTNT", |
||
630 | "GeForce"}; |
||
631 | int flags; |
||
632 | |||
633 | flags=0; |
||
634 | if(MMIOBASE==0) { |
||
635 | unsigned long buf[64]; |
||
636 | int found; |
||
637 | |||
638 | printk(KERN_INFO "Init NVidia card: scan pci bus\n"); |
||
639 | |||
640 | found=__svgalib_pci_find_vendor_vga(0x12d2,buf,0); |
||
641 | if (found) { |
||
642 | found=__svgalib_pci_find_vendor_vga(0x10de,buf,0); |
||
643 | if(found) { |
||
644 | printk(KERN_INFO "Error: NVidia card not found\n"); |
||
645 | return 0; |
||
646 | } |
||
647 | } |
||
648 | |||
649 | switch((buf[0]>>20)&0xff){ |
||
650 | case 0x1: |
||
651 | chip=Riva128; |
||
652 | nvnum=3; |
||
653 | break; |
||
654 | case 0x2: |
||
655 | case 0xA: |
||
656 | chip=RivaTNT; |
||
657 | switch((buf[0]>>16)&0xff){ |
||
658 | case 0x20: |
||
659 | nvnum=4; |
||
660 | break; |
||
661 | case 0x2c: |
||
662 | case 0x2d: |
||
663 | case 0x2e: |
||
664 | case 0x2f: |
||
665 | nvnum=6; |
||
666 | break; |
||
667 | default: |
||
668 | nvnum=5; |
||
669 | } |
||
670 | break; |
||
671 | case 0x10: |
||
672 | case 0x15: |
||
673 | chip=GEFORCE; |
||
674 | nvnum=(buf[0]>>20)&0xff; |
||
675 | break; |
||
676 | case 0x11: |
||
677 | case 0x17: |
||
678 | case 0x1A: |
||
679 | case 0x20: |
||
680 | case 0x25: |
||
681 | default: |
||
682 | flags = NO_INTERLACE; |
||
683 | chip=GEFORCE; |
||
684 | nvnum=(buf[0]>>20)&0xff; |
||
685 | break; |
||
686 | }; |
||
687 | MMIOBASE=buf[4]&0xffffff00; |
||
688 | LINEARBASE=buf[5]&0xffffff00; |
||
689 | }; |
||
690 | |||
691 | printk(KERN_INFO "NVidia card found ! BASE_ADDR: %.8x TYPE: %s (NV%.8x)\n",MMIOBASE,archs[chip],nvnum); |
||
692 | |||
693 | if (force) { |
||
694 | memory = par1; |
||
695 | chip = par2; |
||
696 | }; |
||
697 | |||
698 | __svgalib_modeinfo_linearset |= IS_LINEAR; |
||
699 | |||
700 | __svgalib_mmio_base=MMIOBASE; |
||
701 | __svgalib_mmio_size=8*1024*1024; |
||
702 | |||
703 | map_mmio(); |
||
704 | |||
705 | if(!force){ |
||
706 | int boot0; |
||
707 | |||
708 | boot0=v_readl(NV_PFB_BOOT_0); |
||
709 | switch(chip){ |
||
710 | case Riva128: |
||
711 | if(boot0&0x20)memory=8192; else memory=1024<<(boot0&3); |
||
712 | if(memory==1024)memory=8192; |
||
713 | break; |
||
714 | case RivaTNT: |
||
715 | memory=2048<<(boot0&3); |
||
716 | if(memory==2048)memory=32768; |
||
717 | break; |
||
718 | case GEFORCE: |
||
719 | memory=(v_readl(NV_PFB_BOOT_10)>>10) & 0x3fc00; |
||
720 | if(memory<8192)memory=8192; // do this later |
||
721 | break; |
||
722 | } |
||
723 | } |
||
724 | |||
725 | nv3_mapio(); |
||
726 | nv3_unlock(); |
||
727 | |||
728 | { |
||
729 | int temp; |
||
730 | |||
731 | temp=v_readl(NV_PEXTDEV_0); |
||
732 | switch(chip){ |
||
733 | case Riva128: |
||
734 | PLL_INPUT_FREQ= (temp&0x20) ? 14318 : 13500; |
||
735 | MAXVCLOCK=256000; |
||
736 | P_MAX=4;// XFree say 3, but 4 works on my Riva128 |
||
737 | if(PLL_INPUT_FREQ==13500)M_MAX=12; else M_MAX=13; |
||
738 | M_MIN=M_MAX-5; |
||
739 | break; |
||
740 | case RivaTNT: |
||
741 | PLL_INPUT_FREQ= (temp&0x40) ? 14318 : 13500; |
||
742 | MAXVCLOCK=350000; |
||
743 | P_MAX=4; |
||
744 | if(PLL_INPUT_FREQ==13500)M_MAX=13; else M_MAX=14; |
||
745 | M_MIN=M_MAX-6; |
||
746 | break; |
||
747 | case GEFORCE: |
||
748 | default: |
||
749 | PLL_INPUT_FREQ= (temp&0x40 ) ? 14318 : 13500; |
||
750 | if(nvnum==0x17 || nvnum==0x25) { |
||
751 | if(temp&0x400000) PLL_INPUT_FREQ=27000; |
||
752 | } |
||
753 | MAXVCLOCK=350000; |
||
754 | P_MAX=4; |
||
755 | if(PLL_INPUT_FREQ==13500)M_MAX=13; else M_MAX=14; |
||
756 | M_MIN=M_MAX-6; |
||
757 | break; |
||
758 | }; |
||
759 | }; |
||
760 | |||
761 | cardspecs = malloc(sizeof(CardSpecs)); |
||
762 | cardspecs->videoMemory = memory; |
||
763 | if(chip==Riva128) { |
||
764 | cardspecs->maxPixelClock4bpp = 75000; |
||
765 | cardspecs->maxPixelClock8bpp = 230000; |
||
766 | cardspecs->maxPixelClock16bpp = 230000; |
||
767 | cardspecs->maxPixelClock24bpp = 0; |
||
768 | cardspecs->maxPixelClock32bpp = 230000; |
||
769 | } else { |
||
770 | cardspecs->maxPixelClock4bpp = 75000; |
||
771 | cardspecs->maxPixelClock8bpp = 350000; |
||
772 | cardspecs->maxPixelClock16bpp = 350000; |
||
773 | cardspecs->maxPixelClock24bpp = 0; |
||
774 | cardspecs->maxPixelClock32bpp = 350000; |
||
775 | } |
||
776 | cardspecs->flags = flags | CLOCK_PROGRAMMABLE ; |
||
777 | cardspecs->maxHorizontalCrtc = 4080; |
||
778 | cardspecs->maxPixelClock4bpp = 0; |
||
779 | cardspecs->nClocks =0; |
||
780 | cardspecs->clocks = NULL; |
||
781 | cardspecs->mapClock = nv3_map_clock; |
||
782 | cardspecs->mapHorizontalCrtc = nv3_map_horizontal_crtc; |
||
783 | cardspecs->matchProgrammableClock=nv3_match_programmable_clock; |
||
784 | __svgalib_driverspecs = &__svgalib_nv3_driverspecs; |
||
785 | |||
786 | __svgalib_banked_mem_base=0xa0000; |
||
787 | __svgalib_banked_mem_size=0x10000; |
||
788 | __svgalib_linear_mem_base=LINEARBASE; |
||
789 | __svgalib_linear_mem_size=memory*0x400; |
||
790 | |||
791 | printk(KERN_INFO "NVidia Card Initialized ! LIN_ADDR:%.8x LIN_SIZE:%d\n",__svgalib_linear_mem_base,__svgalib_linear_mem_size); |
||
792 | |||
793 | sleep(4); |
||
794 | |||
795 | return 0; |
||
796 | |||
797 | } |
||
798 | |||
799 | /* |
||
800 | * Calculate the Video Clock parameters for the PLL. |
||
801 | */ |
||
802 | static int CalcVClock |
||
803 | ( |
||
804 | int clockIn, |
||
805 | int *clockOut, |
||
806 | int *mOut, |
||
807 | int *nOut, |
||
808 | int *pOut |
||
809 | ) |
||
810 | { |
||
811 | unsigned DeltaNew, DeltaOld; |
||
812 | unsigned VClk, Freq; |
||
813 | unsigned M, N, P; |
||
814 | |||
815 | DeltaOld = 0xFFFFFFFF; |
||
816 | |||
817 | VClk = (unsigned)clockIn; |
||
818 | |||
819 | for (P = 0; P <= P_MAX; P ++) |
||
820 | { |
||
821 | Freq = VClk << P; |
||
822 | if ((Freq >= 128000) && (Freq <= MAXVCLOCK)) |
||
823 | { |
||
824 | for (M = M_MIN; M <= M_MAX; M++) |
||
825 | { |
||
826 | N = ((VClk<<P) * M + PLL_INPUT_FREQ/2) / PLL_INPUT_FREQ; |
||
827 | Freq = (PLL_INPUT_FREQ * N / M) >> P; |
||
828 | if (Freq > VClk) |
||
829 | DeltaNew = Freq - VClk; |
||
830 | else |
||
831 | DeltaNew = VClk - Freq; |
||
832 | if ((DeltaNew < DeltaOld) && (N<256)) |
||
833 | { |
||
834 | *mOut = M; |
||
835 | *nOut = N; |
||
836 | *pOut = P; |
||
837 | *clockOut = Freq; |
||
838 | DeltaOld = DeltaNew; |
||
839 | } |
||
840 | } |
||
841 | } |
||
842 | } |
||
843 | return (DeltaOld != 0xFFFFFFFF); |
||
844 | } |
||
845 |