1 /*
2  * Copyright (c) 1993-2003 NVIDIA, Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include "nv_local.h"
29 #include "compiler.h"
30 #include "nv_include.h"
31 
32 
NVLockUnlock(NVPtr pNv,Bool Lock)33 void NVLockUnlock (
34     NVPtr pNv,
35     Bool  Lock
36 )
37 {
38     CARD8 cr11;
39 
40     VGA_WR08(pNv->PCIO, 0x3D4, 0x1F);
41     VGA_WR08(pNv->PCIO, 0x3D5, Lock ? 0x99 : 0x57);
42 
43     VGA_WR08(pNv->PCIO, 0x3D4, 0x11);
44     cr11 = VGA_RD08(pNv->PCIO, 0x3D5);
45     if(Lock) cr11 |= 0x80;
46     else cr11 &= ~0x80;
47     VGA_WR08(pNv->PCIO, 0x3D5, cr11);
48 }
49 
NVShowHideCursor(NVPtr pNv,int ShowHide)50 int NVShowHideCursor (
51     NVPtr pNv,
52     int   ShowHide
53 )
54 {
55     int current = pNv->CurrentState->cursor1;
56 
57     pNv->CurrentState->cursor1 = (pNv->CurrentState->cursor1 & 0xFE) |
58                                  (ShowHide & 0x01);
59     VGA_WR08(pNv->PCIO, 0x3D4, 0x31);
60     VGA_WR08(pNv->PCIO, 0x3D5, pNv->CurrentState->cursor1);
61 
62     if(pNv->Architecture == NV_ARCH_40) {  /* HW bug */
63        volatile CARD32 curpos = pNv->PRAMDAC[0x0300/4];
64        pNv->PRAMDAC[0x0300/4] = curpos;
65     }
66 
67     return (current & 0x01);
68 }
69 
70 /****************************************************************************\
71 *                                                                            *
72 * The video arbitration routines calculate some "magic" numbers.  Fixes      *
73 * the snow seen when accessing the framebuffer without it.                   *
74 * It just works (I hope).                                                    *
75 *                                                                            *
76 \****************************************************************************/
77 
78 typedef struct {
79   int graphics_lwm;
80   int video_lwm;
81   int graphics_burst_size;
82   int video_burst_size;
83   int valid;
84 } nv4_fifo_info;
85 
86 typedef struct {
87   int pclk_khz;
88   int mclk_khz;
89   int nvclk_khz;
90   char mem_page_miss;
91   char mem_latency;
92   int memory_width;
93   char enable_video;
94   char gr_during_vid;
95   char pix_bpp;
96   char mem_aligned;
97   char enable_mp;
98 } nv4_sim_state;
99 
100 typedef struct {
101   int graphics_lwm;
102   int video_lwm;
103   int graphics_burst_size;
104   int video_burst_size;
105   int valid;
106 } nv10_fifo_info;
107 
108 typedef struct {
109   int pclk_khz;
110   int mclk_khz;
111   int nvclk_khz;
112   char mem_page_miss;
113   char mem_latency;
114   int memory_type;
115   int memory_width;
116   char enable_video;
117   char gr_during_vid;
118   char pix_bpp;
119   char mem_aligned;
120   char enable_mp;
121 } nv10_sim_state;
122 
123 
nvGetClocks(NVPtr pNv,unsigned int * MClk,unsigned int * NVClk)124 static void nvGetClocks(NVPtr pNv, unsigned int *MClk, unsigned int *NVClk)
125 {
126     unsigned int pll, N, M, MB, NB, P;
127 
128     if(pNv->Architecture >= NV_ARCH_40) {
129        pll = pNv->PMC[0x4020/4];
130        P = (pll >> 16) & 0x07;
131        pll = pNv->PMC[0x4024/4];
132        M = pll & 0xFF;
133        N = (pll >> 8) & 0xFF;
134        if(((pNv->Chipset & 0xfff0) == 0x0290) ||
135           ((pNv->Chipset & 0xfff0) == 0x0390))
136        {
137           MB = 1;
138           NB = 1;
139        } else {
140           MB = (pll >> 16) & 0xFF;
141           NB = (pll >> 24) & 0xFF;
142        }
143        *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
144 
145        pll = pNv->PMC[0x4000/4];
146        P = (pll >> 16) & 0x07;
147        pll = pNv->PMC[0x4004/4];
148        M = pll & 0xFF;
149        N = (pll >> 8) & 0xFF;
150        MB = (pll >> 16) & 0xFF;
151        NB = (pll >> 24) & 0xFF;
152 
153        *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
154     } else
155     if(pNv->twoStagePLL) {
156        pll = pNv->PRAMDAC0[0x0504/4];
157        M = pll & 0xFF;
158        N = (pll >> 8) & 0xFF;
159        P = (pll >> 16) & 0x0F;
160        pll = pNv->PRAMDAC0[0x0574/4];
161        if(pll & 0x80000000) {
162            MB = pll & 0xFF;
163            NB = (pll >> 8) & 0xFF;
164        } else {
165            MB = 1;
166            NB = 1;
167        }
168        *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
169 
170        pll = pNv->PRAMDAC0[0x0500/4];
171        M = pll & 0xFF;
172        N = (pll >> 8) & 0xFF;
173        P = (pll >> 16) & 0x0F;
174        pll = pNv->PRAMDAC0[0x0570/4];
175        if(pll & 0x80000000) {
176            MB = pll & 0xFF;
177            NB = (pll >> 8) & 0xFF;
178        } else {
179            MB = 1;
180            NB = 1;
181        }
182        *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
183     } else
184     if(((pNv->Chipset & 0x0ff0) == 0x0300) ||
185        ((pNv->Chipset & 0x0ff0) == 0x0330))
186     {
187        pll = pNv->PRAMDAC0[0x0504/4];
188        M = pll & 0x0F;
189        N = (pll >> 8) & 0xFF;
190        P = (pll >> 16) & 0x07;
191        if(pll & 0x00000080) {
192            MB = (pll >> 4) & 0x07;
193            NB = (pll >> 19) & 0x1f;
194        } else {
195            MB = 1;
196            NB = 1;
197        }
198        *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
199 
200        pll = pNv->PRAMDAC0[0x0500/4];
201        M = pll & 0x0F;
202        N = (pll >> 8) & 0xFF;
203        P = (pll >> 16) & 0x07;
204        if(pll & 0x00000080) {
205            MB = (pll >> 4) & 0x07;
206            NB = (pll >> 19) & 0x1f;
207        } else {
208            MB = 1;
209            NB = 1;
210        }
211        *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
212     } else {
213        pll = pNv->PRAMDAC0[0x0504/4];
214        M = pll & 0xFF;
215        N = (pll >> 8) & 0xFF;
216        P = (pll >> 16) & 0x0F;
217        *MClk = (N * pNv->CrystalFreqKHz / M) >> P;
218 
219        pll = pNv->PRAMDAC0[0x0500/4];
220        M = pll & 0xFF;
221        N = (pll >> 8) & 0xFF;
222        P = (pll >> 16) & 0x0F;
223        *NVClk = (N * pNv->CrystalFreqKHz / M) >> P;
224     }
225 
226 #if 0
227     ErrorF("NVClock = %i MHz, MEMClock = %i MHz\n", *NVClk/1000, *MClk/1000);
228 #endif
229 }
230 
231 
nv4CalcArbitration(nv4_fifo_info * fifo,nv4_sim_state * arb)232 static void nv4CalcArbitration (
233     nv4_fifo_info *fifo,
234     nv4_sim_state *arb
235 )
236 {
237     int data, pagemiss, cas,width, video_enable, bpp;
238     int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
239     int found, mclk_extra, mclk_loop, cbs, m1, p1;
240     int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
241     int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
242     int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm;
243 
244     fifo->valid = 1;
245     pclk_freq = arb->pclk_khz;
246     mclk_freq = arb->mclk_khz;
247     nvclk_freq = arb->nvclk_khz;
248     pagemiss = arb->mem_page_miss;
249     cas = arb->mem_latency;
250     width = arb->memory_width >> 6;
251     video_enable = arb->enable_video;
252     bpp = arb->pix_bpp;
253     mp_enable = arb->enable_mp;
254     clwm = 0;
255     vlwm = 0;
256     cbs = 128;
257     pclks = 2;
258     nvclks = 2;
259     nvclks += 2;
260     nvclks += 1;
261     mclks = 5;
262     mclks += 3;
263     mclks += 1;
264     mclks += cas;
265     mclks += 1;
266     mclks += 1;
267     mclks += 1;
268     mclks += 1;
269     mclk_extra = 3;
270     nvclks += 2;
271     nvclks += 1;
272     nvclks += 1;
273     nvclks += 1;
274     if (mp_enable)
275         mclks+=4;
276     nvclks += 0;
277     pclks += 0;
278     found = 0;
279     vbs = 0;
280     while (found != 1)
281     {
282         fifo->valid = 1;
283         found = 1;
284         mclk_loop = mclks+mclk_extra;
285         us_m = mclk_loop *1000*1000 / mclk_freq;
286         us_n = nvclks*1000*1000 / nvclk_freq;
287         us_p = nvclks*1000*1000 / pclk_freq;
288         if (video_enable)
289         {
290             video_drain_rate = pclk_freq * 2;
291             crtc_drain_rate = pclk_freq * bpp/8;
292             vpagemiss = 2;
293             vpagemiss += 1;
294             crtpagemiss = 2;
295             vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
296             if (nvclk_freq * 2 > mclk_freq * width)
297                 video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ;
298             else
299                 video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq;
300             us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
301             vlwm = us_video * video_drain_rate/(1000*1000);
302             vlwm++;
303             vbs = 128;
304             if (vlwm > 128) vbs = 64;
305             if (vlwm > (256-64)) vbs = 32;
306             if (nvclk_freq * 2 > mclk_freq * width)
307                 video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ;
308             else
309                 video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq;
310             cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
311             us_crt =
312             us_video
313             +video_fill_us
314             +cpm_us
315             +us_m + us_n +us_p
316             ;
317             clwm = us_crt * crtc_drain_rate/(1000*1000);
318             clwm++;
319         }
320         else
321         {
322             crtc_drain_rate = pclk_freq * bpp/8;
323             crtpagemiss = 2;
324             crtpagemiss += 1;
325             cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
326             us_crt =  cpm_us + us_m + us_n + us_p ;
327             clwm = us_crt * crtc_drain_rate/(1000*1000);
328             clwm++;
329         }
330         m1 = clwm + cbs - 512;
331         p1 = m1 * pclk_freq / mclk_freq;
332         p1 = p1 * bpp / 8;
333         if ((p1 < m1) && (m1 > 0))
334         {
335             fifo->valid = 0;
336             found = 0;
337             if (mclk_extra ==0)   found = 1;
338             mclk_extra--;
339         }
340         else if (video_enable)
341         {
342             if ((clwm > 511) || (vlwm > 255))
343             {
344                 fifo->valid = 0;
345                 found = 0;
346                 if (mclk_extra ==0)   found = 1;
347                 mclk_extra--;
348             }
349         }
350         else
351         {
352             if (clwm > 519)
353             {
354                 fifo->valid = 0;
355                 found = 0;
356                 if (mclk_extra ==0)   found = 1;
357                 mclk_extra--;
358             }
359         }
360         if (clwm < 384) clwm = 384;
361         if (vlwm < 128) vlwm = 128;
362         data = (int)(clwm);
363         fifo->graphics_lwm = data;
364         fifo->graphics_burst_size = 128;
365         data = (int)((vlwm+15));
366         fifo->video_lwm = data;
367         fifo->video_burst_size = vbs;
368     }
369 }
370 
nv4UpdateArbitrationSettings(unsigned VClk,unsigned pixelDepth,unsigned * burst,unsigned * lwm,NVPtr pNv)371 static void nv4UpdateArbitrationSettings (
372     unsigned      VClk,
373     unsigned      pixelDepth,
374     unsigned     *burst,
375     unsigned     *lwm,
376     NVPtr        pNv
377 )
378 {
379     nv4_fifo_info fifo_data;
380     nv4_sim_state sim_data;
381     unsigned int MClk, NVClk, cfg1;
382 
383     nvGetClocks(pNv, &MClk, &NVClk);
384 
385     cfg1 = pNv->PFB[0x00000204/4];
386     sim_data.pix_bpp        = (char)pixelDepth;
387     sim_data.enable_video   = 0;
388     sim_data.enable_mp      = 0;
389     sim_data.memory_width   = (pNv->PEXTDEV[0x0000/4] & 0x10) ? 128 : 64;
390     sim_data.mem_latency    = (char)cfg1 & 0x0F;
391     sim_data.mem_aligned    = 1;
392     sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
393     sim_data.gr_during_vid  = 0;
394     sim_data.pclk_khz       = VClk;
395     sim_data.mclk_khz       = MClk;
396     sim_data.nvclk_khz      = NVClk;
397     nv4CalcArbitration(&fifo_data, &sim_data);
398     if (fifo_data.valid)
399     {
400         int  b = fifo_data.graphics_burst_size >> 4;
401         *burst = 0;
402         while (b >>= 1) (*burst)++;
403         *lwm   = fifo_data.graphics_lwm >> 3;
404     }
405 }
406 
nv10CalcArbitration(nv10_fifo_info * fifo,nv10_sim_state * arb)407 static void nv10CalcArbitration (
408     nv10_fifo_info *fifo,
409     nv10_sim_state *arb
410 )
411 {
412     int data, pagemiss, width, video_enable, bpp;
413     int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
414     int nvclk_fill;
415     int found, mclk_extra, mclk_loop, cbs, m1;
416     int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
417     int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
418     int vus_m;
419     int vpm_us, us_video, cpm_us, us_crt,clwm;
420     int clwm_rnd_down;
421     int m2us, us_pipe_min, p1clk, p2;
422     int min_mclk_extra;
423     int us_min_mclk_extra;
424 
425     fifo->valid = 1;
426     pclk_freq = arb->pclk_khz; /* freq in KHz */
427     mclk_freq = arb->mclk_khz;
428     nvclk_freq = arb->nvclk_khz;
429     pagemiss = arb->mem_page_miss;
430     width = arb->memory_width/64;
431     video_enable = arb->enable_video;
432     bpp = arb->pix_bpp;
433     mp_enable = arb->enable_mp;
434     clwm = 0;
435 
436     cbs = 512;
437 
438     pclks = 4; /* lwm detect. */
439 
440     nvclks = 3; /* lwm -> sync. */
441     nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
442 
443     mclks  = 1;   /* 2 edge sync.  may be very close to edge so just put one. */
444 
445     mclks += 1;   /* arb_hp_req */
446     mclks += 5;   /* ap_hp_req   tiling pipeline */
447 
448     mclks += 2;    /* tc_req     latency fifo */
449     mclks += 2;    /* fb_cas_n_  memory request to fbio block */
450     mclks += 7;    /* sm_d_rdv   data returned from fbio block */
451 
452     /* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
453     if (arb->memory_type == 0)
454       if (arb->memory_width == 64) /* 64 bit bus */
455         mclks += 4;
456       else
457         mclks += 2;
458     else
459       if (arb->memory_width == 64) /* 64 bit bus */
460         mclks += 2;
461       else
462         mclks += 1;
463 
464     if ((!video_enable) && (arb->memory_width == 128))
465     {
466       mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
467       min_mclk_extra = 17;
468     }
469     else
470     {
471       mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
472       /* mclk_extra = 4; */ /* Margin of error */
473       min_mclk_extra = 18;
474     }
475 
476     nvclks += 1; /* 2 edge sync.  may be very close to edge so just put one. */
477     nvclks += 1; /* fbi_d_rdv_n */
478     nvclks += 1; /* Fbi_d_rdata */
479     nvclks += 1; /* crtfifo load */
480 
481     if(mp_enable)
482       mclks+=4; /* Mp can get in with a burst of 8. */
483     /* Extra clocks determined by heuristics */
484 
485     nvclks += 0;
486     pclks += 0;
487     found = 0;
488     while(found != 1) {
489       fifo->valid = 1;
490       found = 1;
491       mclk_loop = mclks+mclk_extra;
492       us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
493       us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
494       us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
495       us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
496       us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
497       us_pipe_min = us_m_min + us_n + us_p;
498 
499       vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
500 
501       if(video_enable) {
502         crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
503 
504         vpagemiss = 1; /* self generating page miss */
505         vpagemiss += 1; /* One higher priority before */
506 
507         crtpagemiss = 2; /* self generating page miss */
508         if(mp_enable)
509             crtpagemiss += 1; /* if MA0 conflict */
510 
511         vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
512 
513         us_video = vpm_us + vus_m; /* Video has separate read return path */
514 
515         cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
516         us_crt =
517           us_video  /* Wait for video */
518           +cpm_us /* CRT Page miss */
519           +us_m + us_n +us_p /* other latency */
520           ;
521 
522         clwm = us_crt * crtc_drain_rate/(1000*1000);
523         clwm++; /* fixed point <= float_point - 1.  Fixes that */
524       } else {
525         crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
526 
527         crtpagemiss = 1; /* self generating page miss */
528         crtpagemiss += 1; /* MA0 page miss */
529         if(mp_enable)
530             crtpagemiss += 1; /* if MA0 conflict */
531         cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
532         us_crt =  cpm_us + us_m + us_n + us_p ;
533         clwm = us_crt * crtc_drain_rate/(1000*1000);
534         clwm++; /* fixed point <= float_point - 1.  Fixes that */
535 
536           /* Finally, a heuristic check when width == 64 bits */
537           if(width == 1){
538               nvclk_fill = nvclk_freq * 8;
539               if(crtc_drain_rate * 100 >= nvclk_fill * 102)
540                       clwm = 0xfff; /*Large number to fail */
541 
542               else if(crtc_drain_rate * 100  >= nvclk_fill * 98) {
543                   clwm = 1024;
544                   cbs = 512;
545               }
546           }
547       }
548 
549 
550       /*
551         Overfill check:
552 
553         */
554 
555       clwm_rnd_down = ((int)clwm/8)*8;
556       if (clwm_rnd_down < clwm)
557           clwm += 8;
558 
559       m1 = clwm + cbs -  1024; /* Amount of overfill */
560       m2us = us_pipe_min + us_min_mclk_extra;
561 
562       /* pclk cycles to drain */
563       p1clk = m2us * pclk_freq/(1000*1000);
564       p2 = p1clk * bpp / 8; /* bytes drained. */
565 
566       if((p2 < m1) && (m1 > 0)) {
567           fifo->valid = 0;
568           found = 0;
569           if(min_mclk_extra == 0)   {
570             if(cbs <= 32) {
571               found = 1; /* Can't adjust anymore! */
572             } else {
573               cbs = cbs/2;  /* reduce the burst size */
574             }
575           } else {
576             min_mclk_extra--;
577           }
578       } else {
579         if (clwm > 1023){ /* Have some margin */
580           fifo->valid = 0;
581           found = 0;
582           if(min_mclk_extra == 0)
583               found = 1; /* Can't adjust anymore! */
584           else
585               min_mclk_extra--;
586         }
587       }
588 
589       if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
590       data = (int)(clwm);
591       /*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
592       fifo->graphics_lwm = data;   fifo->graphics_burst_size = cbs;
593 
594       fifo->video_lwm = 1024;  fifo->video_burst_size = 512;
595     }
596 }
597 
nv10UpdateArbitrationSettings(unsigned VClk,unsigned pixelDepth,unsigned * burst,unsigned * lwm,NVPtr pNv)598 static void nv10UpdateArbitrationSettings (
599     unsigned      VClk,
600     unsigned      pixelDepth,
601     unsigned     *burst,
602     unsigned     *lwm,
603     NVPtr        pNv
604 )
605 {
606     nv10_fifo_info fifo_data;
607     nv10_sim_state sim_data;
608     unsigned int MClk, NVClk, cfg1;
609 
610     nvGetClocks(pNv, &MClk, &NVClk);
611 
612     cfg1 = pNv->PFB[0x0204/4];
613     sim_data.pix_bpp        = (char)pixelDepth;
614     sim_data.enable_video   = 1;
615     sim_data.enable_mp      = 0;
616     sim_data.memory_type    = (pNv->PFB[0x0200/4] & 0x01) ? 1 : 0;
617     sim_data.memory_width   = (pNv->PEXTDEV[0x0000/4] & 0x10) ? 128 : 64;
618     sim_data.mem_latency    = (char)cfg1 & 0x0F;
619     sim_data.mem_aligned    = 1;
620     sim_data.mem_page_miss  = (char)(((cfg1>>4) &0x0F) + ((cfg1>>31) & 0x01));
621     sim_data.gr_during_vid  = 0;
622     sim_data.pclk_khz       = VClk;
623     sim_data.mclk_khz       = MClk;
624     sim_data.nvclk_khz      = NVClk;
625     nv10CalcArbitration(&fifo_data, &sim_data);
626     if (fifo_data.valid) {
627         int  b = fifo_data.graphics_burst_size >> 4;
628         *burst = 0;
629         while (b >>= 1) (*burst)++;
630         *lwm   = fifo_data.graphics_lwm >> 3;
631     }
632 }
633 
634 
nv30UpdateArbitrationSettings(NVPtr pNv,unsigned * burst,unsigned * lwm)635 static void nv30UpdateArbitrationSettings (
636     NVPtr        pNv,
637     unsigned     *burst,
638     unsigned     *lwm
639 )
640 {
641     unsigned int MClk, NVClk;
642     unsigned int fifo_size, burst_size, graphics_lwm;
643 
644     fifo_size = 2048;
645     burst_size = 512;
646     graphics_lwm = fifo_size - burst_size;
647 
648     nvGetClocks(pNv, &MClk, &NVClk);
649 
650     *burst = 0;
651     burst_size >>= 5;
652     while(burst_size >>= 1) (*burst)++;
653     *lwm = graphics_lwm >> 3;
654 }
655 
656 #if XSERVER_LIBPCIACCESS
657 static inline uint32_t
pciaccessReadLong(struct pci_device * const dev,pciaddr_t offset)658 pciaccessReadLong(struct pci_device *const dev, pciaddr_t offset) {
659     uint32_t tmp;
660     pci_device_cfg_read_u32(dev, &tmp, offset);
661     return tmp;
662 }
663 #endif
664 
nForceUpdateArbitrationSettings(unsigned VClk,unsigned pixelDepth,unsigned * burst,unsigned * lwm,NVPtr pNv)665 static void nForceUpdateArbitrationSettings (
666     unsigned      VClk,
667     unsigned      pixelDepth,
668     unsigned     *burst,
669     unsigned     *lwm,
670     NVPtr        pNv
671 )
672 {
673 #if XSERVER_LIBPCIACCESS
674     struct pci_device *const dev1 = pci_device_find_by_slot(0, 0, 0, 1);
675     struct pci_device *const dev2 = pci_device_find_by_slot(0, 0, 0, 2);
676     struct pci_device *const dev3 = pci_device_find_by_slot(0, 0, 0, 3);
677     struct pci_device *const dev5 = pci_device_find_by_slot(0, 0, 0, 5);
678 #   define READ_LONG(num, offset) pciaccessReadLong(dev##num, (offset))
679 #else
680     #define READ_LONG(num, offset) pciReadLong(pciTag(0, 0, num), (offset))
681 #endif
682     nv10_fifo_info fifo_data;
683     nv10_sim_state sim_data;
684     unsigned int M, N, P, pll, MClk, NVClk, memctrl;
685 
686     if((pNv->Chipset & 0x0FF0) == 0x01A0) {
687        unsigned int uMClkPostDiv;
688 
689        uMClkPostDiv = (READ_LONG(3, 0x6C) >> 8) & 0xf;
690        if(!uMClkPostDiv) uMClkPostDiv = 4;
691        MClk = 400000 / uMClkPostDiv;
692     } else {
693        MClk = READ_LONG(5, 0x4C) / 1000;
694     }
695 
696     pll = pNv->PRAMDAC0[0x0500/4];
697     M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
698     NVClk  = (N * pNv->CrystalFreqKHz / M) >> P;
699     sim_data.pix_bpp        = (char)pixelDepth;
700     sim_data.enable_video   = 0;
701     sim_data.enable_mp      = 0;
702     sim_data.memory_type    = (READ_LONG(1, 0x7C) >> 12) & 1;
703     sim_data.memory_width   = 64;
704 
705     memctrl = READ_LONG(3, 0x00) >> 16;
706 
707     if((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
708         int dimm[3];
709 
710         dimm[0] = (READ_LONG(2, 0x40) >> 8) & 0x4F;
711         dimm[1] = (READ_LONG(2, 0x44) >> 8) & 0x4F;
712         dimm[2] = (READ_LONG(2, 0x48) >> 8) & 0x4F;
713 
714         if((dimm[0] + dimm[1]) != dimm[2]) {
715              ErrorF("WARNING: "
716               "your nForce DIMMs are not arranged in optimal banks!\n");
717         }
718     }
719 
720     sim_data.mem_latency    = 3;
721     sim_data.mem_aligned    = 1;
722     sim_data.mem_page_miss  = 10;
723     sim_data.gr_during_vid  = 0;
724     sim_data.pclk_khz       = VClk;
725     sim_data.mclk_khz       = MClk;
726     sim_data.nvclk_khz      = NVClk;
727     nv10CalcArbitration(&fifo_data, &sim_data);
728     if (fifo_data.valid)
729     {
730         int  b = fifo_data.graphics_burst_size >> 4;
731         *burst = 0;
732         while (b >>= 1) (*burst)++;
733         *lwm   = fifo_data.graphics_lwm >> 3;
734     }
735 
736 #undef READ_LONG
737 }
738 
739 
740 /****************************************************************************\
741 *                                                                            *
742 *                          RIVA Mode State Routines                          *
743 *                                                                            *
744 \****************************************************************************/
745 
746 /*
747  * Calculate the Video Clock parameters for the PLL.
748  */
CalcVClock(int clockIn,int * clockOut,U032 * pllOut,NVPtr pNv)749 static void CalcVClock (
750     int           clockIn,
751     int          *clockOut,
752     U032         *pllOut,
753     NVPtr        pNv
754 )
755 {
756     unsigned lowM, highM;
757     unsigned DeltaNew, DeltaOld;
758     unsigned VClk, Freq;
759     unsigned M, N, P;
760 
761     DeltaOld = 0xFFFFFFFF;
762 
763     VClk = (unsigned)clockIn;
764 
765     if (pNv->CrystalFreqKHz == 13500) {
766         lowM  = 7;
767         highM = 13;
768     } else {
769         lowM  = 8;
770         highM = 14;
771     }
772 
773     for (P = 0; P <= 4; P++) {
774         Freq = VClk << P;
775         if ((Freq >= 128000) && (Freq <= 350000)) {
776             for (M = lowM; M <= highM; M++) {
777                 N = ((VClk << P) * M) / pNv->CrystalFreqKHz;
778                 if(N <= 255) {
779                     Freq = ((pNv->CrystalFreqKHz * N) / M) >> P;
780                     if (Freq > VClk)
781                         DeltaNew = Freq - VClk;
782                     else
783                         DeltaNew = VClk - Freq;
784                     if (DeltaNew < DeltaOld) {
785                         *pllOut   = (P << 16) | (N << 8) | M;
786                         *clockOut = Freq;
787                         DeltaOld  = DeltaNew;
788                     }
789                 }
790             }
791         }
792     }
793 }
794 
CalcVClock2Stage(int clockIn,int * clockOut,U032 * pllOut,U032 * pllBOut,NVPtr pNv)795 static void CalcVClock2Stage (
796     int           clockIn,
797     int          *clockOut,
798     U032         *pllOut,
799     U032         *pllBOut,
800     NVPtr        pNv
801 )
802 {
803     unsigned DeltaNew, DeltaOld;
804     unsigned VClk, Freq;
805     unsigned M, N, P;
806 
807     DeltaOld = 0xFFFFFFFF;
808 
809     *pllBOut = 0x80000401;  /* fixed at x4 for now */
810 
811     VClk = (unsigned)clockIn;
812 
813     for (P = 0; P <= 6; P++) {
814         Freq = VClk << P;
815         if ((Freq >= 400000) && (Freq <= 1000000)) {
816             for (M = 1; M <= 13; M++) {
817                 N = ((VClk << P) * M) / (pNv->CrystalFreqKHz << 2);
818                 if((N >= 5) && (N <= 255)) {
819                     Freq = (((pNv->CrystalFreqKHz << 2) * N) / M) >> P;
820                     if (Freq > VClk)
821                         DeltaNew = Freq - VClk;
822                     else
823                         DeltaNew = VClk - Freq;
824                     if (DeltaNew < DeltaOld) {
825                         *pllOut   = (P << 16) | (N << 8) | M;
826                         *clockOut = Freq;
827                         DeltaOld  = DeltaNew;
828                     }
829                 }
830             }
831         }
832     }
833 }
834 
835 /*
836  * Calculate extended mode parameters (SVGA) and save in a
837  * mode state structure.
838  */
NVCalcStateExt(NVPtr pNv,RIVA_HW_STATE * state,int bpp,int width,int hDisplaySize,int height,int dotClock,int flags)839 void NVCalcStateExt (
840     NVPtr pNv,
841     RIVA_HW_STATE *state,
842     int            bpp,
843     int            width,
844     int            hDisplaySize,
845     int            height,
846     int            dotClock,
847     int		   flags
848 )
849 {
850     int pixelDepth, VClk = 0;
851     /*
852      * Save mode parameters.
853      */
854     state->bpp    = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
855     state->width  = width;
856     state->height = height;
857     /*
858      * Extended RIVA registers.
859      */
860     pixelDepth = (bpp + 1)/8;
861     if(pNv->twoStagePLL)
862         CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, pNv);
863     else
864         CalcVClock(dotClock, &VClk, &state->pll, pNv);
865 
866     switch (pNv->Architecture)
867     {
868         case NV_ARCH_04:
869             nv4UpdateArbitrationSettings(VClk,
870                                          pixelDepth * 8,
871                                         &(state->arbitration0),
872                                         &(state->arbitration1),
873                                          pNv);
874             state->cursor0  = 0x00;
875             state->cursor1  = 0xbC;
876 	    if (flags & V_DBLSCAN)
877 		state->cursor1 |= 2;
878             state->cursor2  = 0x00000000;
879             state->pllsel   = 0x10000700;
880             state->config   = 0x00001114;
881             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
882             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
883             break;
884         case NV_ARCH_40:
885             if(!pNv->FlatPanel)
886                 state->control = pNv->PRAMDAC0[0x0580/4] & 0xeffffeff;
887             /* fallthrough */
888         case NV_ARCH_10:
889         case NV_ARCH_20:
890         case NV_ARCH_30:
891         default:
892             if(((pNv->Chipset & 0xfff0) == 0x0240) ||
893                ((pNv->Chipset & 0xfff0) == 0x03D0) ||
894                ((pNv->Chipset & 0xfff0) == 0x0530))
895             {
896                 state->arbitration0 = 128;
897                 state->arbitration1 = 0x0480;
898             } else
899             if(((pNv->Chipset & 0xffff) == 0x01A0) ||
900                ((pNv->Chipset & 0xffff) == 0x01f0))
901             {
902                 nForceUpdateArbitrationSettings(VClk,
903                                           pixelDepth * 8,
904                                          &(state->arbitration0),
905                                          &(state->arbitration1),
906                                           pNv);
907             } else if(pNv->Architecture < NV_ARCH_30) {
908                 nv10UpdateArbitrationSettings(VClk,
909                                           pixelDepth * 8,
910                                          &(state->arbitration0),
911                                          &(state->arbitration1),
912                                           pNv);
913             } else {
914                 nv30UpdateArbitrationSettings(pNv,
915                                          &(state->arbitration0),
916                                          &(state->arbitration1));
917             }
918             state->cursor0  = 0x80 | (pNv->CursorStart >> 17);
919             state->cursor1  = (pNv->CursorStart >> 11) << 2;
920 	    state->cursor2  = pNv->CursorStart >> 24;
921 	    if (flags & V_DBLSCAN)
922 		state->cursor1 |= 2;
923             state->pllsel   = 0x10000700;
924             state->config   = pNv->PFB[0x00000200/4];
925             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
926             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
927             break;
928     }
929 
930     if(bpp != 8) /* DirectColor */
931 	state->general |= 0x00000030;
932 
933     state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
934     state->pixel    = (pixelDepth > 2) ? 3 : pixelDepth;
935 }
936 
937 
NVLoadStateExt(NVPtr pNv,RIVA_HW_STATE * state)938 void NVLoadStateExt (
939     NVPtr pNv,
940     RIVA_HW_STATE *state
941 )
942 {
943     int i, j;
944 
945     pNv->PMC[0x0140/4] = 0x00000000;
946     pNv->PMC[0x0200/4] = 0xFFFF00FF;
947     pNv->PMC[0x0200/4] = 0xFFFFFFFF;
948 
949     pNv->PTIMER[0x0200] = 0x00000008;
950     pNv->PTIMER[0x0210] = 0x00000003;
951     pNv->PTIMER[0x0140] = 0x00000000;
952     pNv->PTIMER[0x0100] = 0xFFFFFFFF;
953 
954     if(pNv->Architecture == NV_ARCH_04) {
955         if (state)
956             pNv->PFB[0x0200/4] = state->config;
957     } else
958     if((pNv->Architecture < NV_ARCH_40) ||
959        ((pNv->Chipset & 0xfff0) == 0x0040))
960     {
961         for(i = 0; i < 8; i++) {
962            pNv->PFB[(0x0240 + (i * 0x10))/4] = 0;
963            pNv->PFB[(0x0244 + (i * 0x10))/4] = pNv->FbMapSize - 1;
964         }
965     } else {
966         int regions = 12;
967 
968         if(((pNv->Chipset & 0xfff0) == 0x0090) ||
969            ((pNv->Chipset & 0xfff0) == 0x01D0) ||
970            ((pNv->Chipset & 0xfff0) == 0x0290) ||
971            ((pNv->Chipset & 0xfff0) == 0x0390) ||
972            ((pNv->Chipset & 0xfff0) == 0x03D0))
973         {
974            regions = 15;
975         }
976 
977        for(i = 0; i < regions; i++) {
978           pNv->PFB[(0x0600 + (i * 0x10))/4] = 0;
979           pNv->PFB[(0x0604 + (i * 0x10))/4] = pNv->FbMapSize - 1;
980        }
981     }
982 
983     if(pNv->Architecture >= NV_ARCH_40) {
984        pNv->PRAMIN[0x0000] = 0x80000010;
985        pNv->PRAMIN[0x0001] = 0x00101202;
986        pNv->PRAMIN[0x0002] = 0x80000011;
987        pNv->PRAMIN[0x0003] = 0x00101204;
988        pNv->PRAMIN[0x0004] = 0x80000012;
989        pNv->PRAMIN[0x0005] = 0x00101206;
990        pNv->PRAMIN[0x0006] = 0x80000013;
991        pNv->PRAMIN[0x0007] = 0x00101208;
992        pNv->PRAMIN[0x0008] = 0x80000014;
993        pNv->PRAMIN[0x0009] = 0x0010120A;
994        pNv->PRAMIN[0x000A] = 0x80000015;
995        pNv->PRAMIN[0x000B] = 0x0010120C;
996        pNv->PRAMIN[0x000C] = 0x80000016;
997        pNv->PRAMIN[0x000D] = 0x0010120E;
998        pNv->PRAMIN[0x000E] = 0x80000017;
999        pNv->PRAMIN[0x000F] = 0x00101210;
1000        pNv->PRAMIN[0x0800] = 0x00003000;
1001        pNv->PRAMIN[0x0801] = pNv->FbMapSize - 1;
1002        pNv->PRAMIN[0x0802] = 0x00000002;
1003        pNv->PRAMIN[0x0808] = 0x02080062;
1004        pNv->PRAMIN[0x0809] = 0x00000000;
1005        pNv->PRAMIN[0x080A] = 0x00001200;
1006        pNv->PRAMIN[0x080B] = 0x00001200;
1007        pNv->PRAMIN[0x080C] = 0x00000000;
1008        pNv->PRAMIN[0x080D] = 0x00000000;
1009        pNv->PRAMIN[0x0810] = 0x02080043;
1010        pNv->PRAMIN[0x0811] = 0x00000000;
1011        pNv->PRAMIN[0x0812] = 0x00000000;
1012        pNv->PRAMIN[0x0813] = 0x00000000;
1013        pNv->PRAMIN[0x0814] = 0x00000000;
1014        pNv->PRAMIN[0x0815] = 0x00000000;
1015        pNv->PRAMIN[0x0818] = 0x02080044;
1016        pNv->PRAMIN[0x0819] = 0x02000000;
1017        pNv->PRAMIN[0x081A] = 0x00000000;
1018        pNv->PRAMIN[0x081B] = 0x00000000;
1019        pNv->PRAMIN[0x081C] = 0x00000000;
1020        pNv->PRAMIN[0x081D] = 0x00000000;
1021        pNv->PRAMIN[0x0820] = 0x02080019;
1022        pNv->PRAMIN[0x0821] = 0x00000000;
1023        pNv->PRAMIN[0x0822] = 0x00000000;
1024        pNv->PRAMIN[0x0823] = 0x00000000;
1025        pNv->PRAMIN[0x0824] = 0x00000000;
1026        pNv->PRAMIN[0x0825] = 0x00000000;
1027        pNv->PRAMIN[0x0828] = 0x020A005C;
1028        pNv->PRAMIN[0x0829] = 0x00000000;
1029        pNv->PRAMIN[0x082A] = 0x00000000;
1030        pNv->PRAMIN[0x082B] = 0x00000000;
1031        pNv->PRAMIN[0x082C] = 0x00000000;
1032        pNv->PRAMIN[0x082D] = 0x00000000;
1033        pNv->PRAMIN[0x0830] = 0x0208009F;
1034        pNv->PRAMIN[0x0831] = 0x00000000;
1035        pNv->PRAMIN[0x0832] = 0x00001200;
1036        pNv->PRAMIN[0x0833] = 0x00001200;
1037        pNv->PRAMIN[0x0834] = 0x00000000;
1038        pNv->PRAMIN[0x0835] = 0x00000000;
1039        pNv->PRAMIN[0x0838] = 0x0208004A;
1040        pNv->PRAMIN[0x0839] = 0x02000000;
1041        pNv->PRAMIN[0x083A] = 0x00000000;
1042        pNv->PRAMIN[0x083B] = 0x00000000;
1043        pNv->PRAMIN[0x083C] = 0x00000000;
1044        pNv->PRAMIN[0x083D] = 0x00000000;
1045        pNv->PRAMIN[0x0840] = 0x02080077;
1046        pNv->PRAMIN[0x0841] = 0x00000000;
1047        pNv->PRAMIN[0x0842] = 0x00001200;
1048        pNv->PRAMIN[0x0843] = 0x00001200;
1049        pNv->PRAMIN[0x0844] = 0x00000000;
1050        pNv->PRAMIN[0x0845] = 0x00000000;
1051        pNv->PRAMIN[0x084C] = 0x00003002;
1052        pNv->PRAMIN[0x084D] = 0x00007FFF;
1053        pNv->PRAMIN[0x084E] = pNv->FbUsableSize | 0x00000002;
1054 
1055 #if X_BYTE_ORDER == X_BIG_ENDIAN
1056        pNv->PRAMIN[0x080A] |= 0x01000000;
1057        pNv->PRAMIN[0x0812] |= 0x01000000;
1058        pNv->PRAMIN[0x081A] |= 0x01000000;
1059        pNv->PRAMIN[0x0822] |= 0x01000000;
1060        pNv->PRAMIN[0x082A] |= 0x01000000;
1061        pNv->PRAMIN[0x0832] |= 0x01000000;
1062        pNv->PRAMIN[0x083A] |= 0x01000000;
1063        pNv->PRAMIN[0x0842] |= 0x01000000;
1064        pNv->PRAMIN[0x0819] = 0x01000000;
1065        pNv->PRAMIN[0x0839] = 0x01000000;
1066 #endif
1067     } else {
1068        pNv->PRAMIN[0x0000] = 0x80000010;
1069        pNv->PRAMIN[0x0001] = 0x80011201;
1070        pNv->PRAMIN[0x0002] = 0x80000011;
1071        pNv->PRAMIN[0x0003] = 0x80011202;
1072        pNv->PRAMIN[0x0004] = 0x80000012;
1073        pNv->PRAMIN[0x0005] = 0x80011203;
1074        pNv->PRAMIN[0x0006] = 0x80000013;
1075        pNv->PRAMIN[0x0007] = 0x80011204;
1076        pNv->PRAMIN[0x0008] = 0x80000014;
1077        pNv->PRAMIN[0x0009] = 0x80011205;
1078        pNv->PRAMIN[0x000A] = 0x80000015;
1079        pNv->PRAMIN[0x000B] = 0x80011206;
1080        pNv->PRAMIN[0x000C] = 0x80000016;
1081        pNv->PRAMIN[0x000D] = 0x80011207;
1082        pNv->PRAMIN[0x000E] = 0x80000017;
1083        pNv->PRAMIN[0x000F] = 0x80011208;
1084        pNv->PRAMIN[0x0800] = 0x00003000;
1085        pNv->PRAMIN[0x0801] = pNv->FbMapSize - 1;
1086        pNv->PRAMIN[0x0802] = 0x00000002;
1087        pNv->PRAMIN[0x0803] = 0x00000002;
1088        if(pNv->Architecture >= NV_ARCH_10)
1089           pNv->PRAMIN[0x0804] = 0x01008062;
1090        else
1091           pNv->PRAMIN[0x0804] = 0x01008042;
1092        pNv->PRAMIN[0x0805] = 0x00000000;
1093        pNv->PRAMIN[0x0806] = 0x12001200;
1094        pNv->PRAMIN[0x0807] = 0x00000000;
1095        pNv->PRAMIN[0x0808] = 0x01008043;
1096        pNv->PRAMIN[0x0809] = 0x00000000;
1097        pNv->PRAMIN[0x080A] = 0x00000000;
1098        pNv->PRAMIN[0x080B] = 0x00000000;
1099        pNv->PRAMIN[0x080C] = 0x01008044;
1100        pNv->PRAMIN[0x080D] = 0x00000002;
1101        pNv->PRAMIN[0x080E] = 0x00000000;
1102        pNv->PRAMIN[0x080F] = 0x00000000;
1103        pNv->PRAMIN[0x0810] = 0x01008019;
1104        pNv->PRAMIN[0x0811] = 0x00000000;
1105        pNv->PRAMIN[0x0812] = 0x00000000;
1106        pNv->PRAMIN[0x0813] = 0x00000000;
1107        pNv->PRAMIN[0x0814] = 0x0100A05C;
1108        pNv->PRAMIN[0x0815] = 0x00000000;
1109        pNv->PRAMIN[0x0816] = 0x00000000;
1110        pNv->PRAMIN[0x0817] = 0x00000000;
1111        if(pNv->WaitVSyncPossible)
1112           pNv->PRAMIN[0x0818] = 0x0100809F;
1113        else
1114           pNv->PRAMIN[0x0818] = 0x0100805F;
1115        pNv->PRAMIN[0x0819] = 0x00000000;
1116        pNv->PRAMIN[0x081A] = 0x12001200;
1117        pNv->PRAMIN[0x081B] = 0x00000000;
1118        pNv->PRAMIN[0x081C] = 0x0100804A;
1119        pNv->PRAMIN[0x081D] = 0x00000002;
1120        pNv->PRAMIN[0x081E] = 0x00000000;
1121        pNv->PRAMIN[0x081F] = 0x00000000;
1122        pNv->PRAMIN[0x0820] = 0x01018077;
1123        pNv->PRAMIN[0x0821] = 0x00000000;
1124        pNv->PRAMIN[0x0822] = 0x12001200;
1125        pNv->PRAMIN[0x0823] = 0x00000000;
1126        pNv->PRAMIN[0x0824] = 0x00003002;
1127        pNv->PRAMIN[0x0825] = 0x00007FFF;
1128        pNv->PRAMIN[0x0826] = pNv->FbUsableSize | 0x00000002;
1129        pNv->PRAMIN[0x0827] = 0x00000002;
1130 
1131 #if X_BYTE_ORDER == X_BIG_ENDIAN
1132        pNv->PRAMIN[0x0804] |= 0x00080000;
1133        pNv->PRAMIN[0x0808] |= 0x00080000;
1134        pNv->PRAMIN[0x080C] |= 0x00080000;
1135        pNv->PRAMIN[0x0810] |= 0x00080000;
1136        pNv->PRAMIN[0x0814] |= 0x00080000;
1137        pNv->PRAMIN[0x0818] |= 0x00080000;
1138        pNv->PRAMIN[0x081C] |= 0x00080000;
1139        pNv->PRAMIN[0x0820] |= 0x00080000;
1140        pNv->PRAMIN[0x080D] = 0x00000001;
1141        pNv->PRAMIN[0x081D] = 0x00000001;
1142 #endif
1143     }
1144 
1145     if(pNv->Architecture < NV_ARCH_10) {
1146        if((pNv->Chipset & 0x0fff) == 0x0020) {
1147            pNv->PRAMIN[0x0824] |= 0x00020000;
1148            pNv->PRAMIN[0x0826] += pNv->FbAddress;
1149        }
1150        pNv->PGRAPH[0x0080/4] = 0x000001FF;
1151        pNv->PGRAPH[0x0080/4] = 0x1230C000;
1152        pNv->PGRAPH[0x0084/4] = 0x72111101;
1153        pNv->PGRAPH[0x0088/4] = 0x11D5F071;
1154        pNv->PGRAPH[0x008C/4] = 0x0004FF31;
1155        pNv->PGRAPH[0x008C/4] = 0x4004FF31;
1156 
1157        pNv->PGRAPH[0x0140/4] = 0x00000000;
1158        pNv->PGRAPH[0x0100/4] = 0xFFFFFFFF;
1159        pNv->PGRAPH[0x0170/4] = 0x10010100;
1160        pNv->PGRAPH[0x0710/4] = 0xFFFFFFFF;
1161        pNv->PGRAPH[0x0720/4] = 0x00000001;
1162 
1163        pNv->PGRAPH[0x0810/4] = 0x00000000;
1164        pNv->PGRAPH[0x0608/4] = 0xFFFFFFFF;
1165     } else {
1166        pNv->PGRAPH[0x0080/4] = 0xFFFFFFFF;
1167        pNv->PGRAPH[0x0080/4] = 0x00000000;
1168 
1169        pNv->PGRAPH[0x0140/4] = 0x00000000;
1170        pNv->PGRAPH[0x0100/4] = 0xFFFFFFFF;
1171        pNv->PGRAPH[0x0144/4] = 0x10010100;
1172        pNv->PGRAPH[0x0714/4] = 0xFFFFFFFF;
1173        pNv->PGRAPH[0x0720/4] = 0x00000001;
1174        pNv->PGRAPH[0x0710/4] &= 0x0007ff00;
1175        pNv->PGRAPH[0x0710/4] |= 0x00020100;
1176 
1177        if(pNv->Architecture == NV_ARCH_10) {
1178            pNv->PGRAPH[0x0084/4] = 0x00118700;
1179            pNv->PGRAPH[0x0088/4] = 0x24E00810;
1180            pNv->PGRAPH[0x008C/4] = 0x55DE0030;
1181 
1182            for(i = 0; i < 32; i++)
1183              pNv->PGRAPH[(0x0B00/4) + i] = pNv->PFB[(0x0240/4) + i];
1184 
1185            pNv->PGRAPH[0x640/4] = 0;
1186            pNv->PGRAPH[0x644/4] = 0;
1187            pNv->PGRAPH[0x684/4] = pNv->FbMapSize - 1;
1188            pNv->PGRAPH[0x688/4] = pNv->FbMapSize - 1;
1189 
1190            pNv->PGRAPH[0x0810/4] = 0x00000000;
1191            pNv->PGRAPH[0x0608/4] = 0xFFFFFFFF;
1192        } else {
1193            if(pNv->Architecture >= NV_ARCH_40) {
1194               pNv->PGRAPH[0x0084/4] = 0x401287c0;
1195               pNv->PGRAPH[0x008C/4] = 0x60de8051;
1196               pNv->PGRAPH[0x0090/4] = 0x00008000;
1197               pNv->PGRAPH[0x0610/4] = 0x00be3c5f;
1198               pNv->PGRAPH[0x0bc4/4] |= 0x00008000;
1199 
1200               j = pNv->REGS[0x1540/4] & 0xff;
1201               if(j) {
1202                   for(i = 0; !(j & 1); j >>= 1, i++);
1203                   pNv->PGRAPH[0x5000/4] = i;
1204               }
1205 
1206               if((pNv->Chipset & 0xfff0) == 0x0040) {
1207                  pNv->PGRAPH[0x09b0/4] = 0x83280fff;
1208                  pNv->PGRAPH[0x09b4/4] = 0x000000a0;
1209               } else {
1210                  pNv->PGRAPH[0x0820/4] = 0x83280eff;
1211                  pNv->PGRAPH[0x0824/4] = 0x000000a0;
1212               }
1213 
1214               switch(pNv->Chipset & 0xfff0) {
1215               case 0x0040:
1216               case 0x0210:
1217                  pNv->PGRAPH[0x09b8/4] = 0x0078e366;
1218                  pNv->PGRAPH[0x09bc/4] = 0x0000014c;
1219                  pNv->PFB[0x033C/4] &= 0xffff7fff;
1220                  break;
1221               case 0x00C0:
1222               case 0x0120:
1223                  pNv->PGRAPH[0x0828/4] = 0x007596ff;
1224                  pNv->PGRAPH[0x082C/4] = 0x00000108;
1225                  break;
1226               case 0x0160:
1227               case 0x01D0:
1228               case 0x0240:
1229               case 0x03D0:
1230               case 0x0530:
1231                  pNv->PMC[0x1700/4] = pNv->PFB[0x020C/4];
1232                  pNv->PMC[0x1704/4] = 0;
1233                  pNv->PMC[0x1708/4] = 0;
1234                  pNv->PMC[0x170C/4] = pNv->PFB[0x020C/4];
1235                  pNv->PGRAPH[0x0860/4] = 0;
1236                  pNv->PGRAPH[0x0864/4] = 0;
1237                  pNv->PRAMDAC[0x0608/4] |= 0x00100000;
1238                  break;
1239               case 0x0140:
1240                  pNv->PGRAPH[0x0828/4] = 0x0072cb77;
1241                  pNv->PGRAPH[0x082C/4] = 0x00000108;
1242                  break;
1243               case 0x0220:
1244                  pNv->PGRAPH[0x0860/4] = 0;
1245                  pNv->PGRAPH[0x0864/4] = 0;
1246                  pNv->PRAMDAC[0x0608/4] |= 0x00100000;
1247                  break;
1248               case 0x0090:
1249               case 0x0290:
1250               case 0x0390:
1251                  pNv->PRAMDAC[0x0608/4] |= 0x00100000;
1252                  pNv->PGRAPH[0x0828/4] = 0x07830610;
1253                  pNv->PGRAPH[0x082C/4] = 0x0000016A;
1254                  break;
1255               default:
1256                  break;
1257               };
1258 
1259               pNv->PGRAPH[0x0b38/4] = 0x2ffff800;
1260               pNv->PGRAPH[0x0b3c/4] = 0x00006000;
1261               pNv->PGRAPH[0x032C/4] = 0x01000000;
1262               pNv->PGRAPH[0x0220/4] = 0x00001200;
1263            } else
1264            if(pNv->Architecture == NV_ARCH_30) {
1265               pNv->PGRAPH[0x0084/4] = 0x40108700;
1266               pNv->PGRAPH[0x0890/4] = 0x00140000;
1267               pNv->PGRAPH[0x008C/4] = 0xf00e0431;
1268               pNv->PGRAPH[0x0090/4] = 0x00008000;
1269               pNv->PGRAPH[0x0610/4] = 0xf04b1f36;
1270               pNv->PGRAPH[0x0B80/4] = 0x1002d888;
1271               pNv->PGRAPH[0x0B88/4] = 0x62ff007f;
1272            } else {
1273               pNv->PGRAPH[0x0084/4] = 0x00118700;
1274               pNv->PGRAPH[0x008C/4] = 0xF20E0431;
1275               pNv->PGRAPH[0x0090/4] = 0x00000000;
1276               pNv->PGRAPH[0x009C/4] = 0x00000040;
1277 
1278               if((pNv->Chipset & 0x0ff0) >= 0x0250) {
1279                  pNv->PGRAPH[0x0890/4] = 0x00080000;
1280                  pNv->PGRAPH[0x0610/4] = 0x304B1FB6;
1281                  pNv->PGRAPH[0x0B80/4] = 0x18B82880;
1282                  pNv->PGRAPH[0x0B84/4] = 0x44000000;
1283                  pNv->PGRAPH[0x0098/4] = 0x40000080;
1284                  pNv->PGRAPH[0x0B88/4] = 0x000000ff;
1285               } else {
1286                  pNv->PGRAPH[0x0880/4] = 0x00080000;
1287                  pNv->PGRAPH[0x0094/4] = 0x00000005;
1288                  pNv->PGRAPH[0x0B80/4] = 0x45CAA208;
1289                  pNv->PGRAPH[0x0B84/4] = 0x24000000;
1290                  pNv->PGRAPH[0x0098/4] = 0x00000040;
1291                  pNv->PGRAPH[0x0750/4] = 0x00E00038;
1292                  pNv->PGRAPH[0x0754/4] = 0x00000030;
1293                  pNv->PGRAPH[0x0750/4] = 0x00E10038;
1294                  pNv->PGRAPH[0x0754/4] = 0x00000030;
1295               }
1296            }
1297 
1298            if((pNv->Architecture < NV_ARCH_40) ||
1299               ((pNv->Chipset & 0xfff0) == 0x0040))
1300            {
1301               for(i = 0; i < 32; i++) {
1302                 pNv->PGRAPH[(0x0900/4) + i] = pNv->PFB[(0x0240/4) + i];
1303                 pNv->PGRAPH[(0x6900/4) + i] = pNv->PFB[(0x0240/4) + i];
1304               }
1305            } else {
1306               if(((pNv->Chipset & 0xfff0) == 0x0090) ||
1307                  ((pNv->Chipset & 0xfff0) == 0x01D0) ||
1308                  ((pNv->Chipset & 0xfff0) == 0x0290) ||
1309                  ((pNv->Chipset & 0xfff0) == 0x0390) ||
1310                  ((pNv->Chipset & 0xfff0) == 0x03D0))
1311               {
1312                  for(i = 0; i < 60; i++) {
1313                    pNv->PGRAPH[(0x0D00/4) + i] = pNv->PFB[(0x0600/4) + i];
1314                    pNv->PGRAPH[(0x6900/4) + i] = pNv->PFB[(0x0600/4) + i];
1315                  }
1316               } else {
1317                  for(i = 0; i < 48; i++) {
1318                    pNv->PGRAPH[(0x0900/4) + i] = pNv->PFB[(0x0600/4) + i];
1319                    if(((pNv->Chipset & 0xfff0) != 0x0160) &&
1320                       ((pNv->Chipset & 0xfff0) != 0x0220) &&
1321                       ((pNv->Chipset & 0xfff0) != 0x0240) &&
1322                       ((pNv->Chipset & 0xfff0) != 0x0530))
1323                    {
1324                       pNv->PGRAPH[(0x6900/4) + i] = pNv->PFB[(0x0600/4) + i];
1325                    }
1326                  }
1327               }
1328            }
1329 
1330            if(pNv->Architecture >= NV_ARCH_40) {
1331               if((pNv->Chipset & 0xfff0) == 0x0040) {
1332                  pNv->PGRAPH[0x09A4/4] = pNv->PFB[0x0200/4];
1333                  pNv->PGRAPH[0x09A8/4] = pNv->PFB[0x0204/4];
1334                  pNv->PGRAPH[0x69A4/4] = pNv->PFB[0x0200/4];
1335                  pNv->PGRAPH[0x69A8/4] = pNv->PFB[0x0204/4];
1336 
1337                  pNv->PGRAPH[0x0820/4] = 0;
1338                  pNv->PGRAPH[0x0824/4] = 0;
1339                  pNv->PGRAPH[0x0864/4] = pNv->FbMapSize - 1;
1340                  pNv->PGRAPH[0x0868/4] = pNv->FbMapSize - 1;
1341               } else {
1342                  if(((pNv->Chipset & 0xfff0) == 0x0090) ||
1343                     ((pNv->Chipset & 0xfff0) == 0x01D0) ||
1344                     ((pNv->Chipset & 0xfff0) == 0x0290) ||
1345                     ((pNv->Chipset & 0xfff0) == 0x0390))
1346                  {
1347                     pNv->PGRAPH[0x0DF0/4] = pNv->PFB[0x0200/4];
1348                     pNv->PGRAPH[0x0DF4/4] = pNv->PFB[0x0204/4];
1349                  } else {
1350                     pNv->PGRAPH[0x09F0/4] = pNv->PFB[0x0200/4];
1351                     pNv->PGRAPH[0x09F4/4] = pNv->PFB[0x0204/4];
1352                  }
1353                  pNv->PGRAPH[0x69F0/4] = pNv->PFB[0x0200/4];
1354                  pNv->PGRAPH[0x69F4/4] = pNv->PFB[0x0204/4];
1355 
1356                  pNv->PGRAPH[0x0840/4] = 0;
1357                  pNv->PGRAPH[0x0844/4] = 0;
1358                  pNv->PGRAPH[0x08a0/4] = pNv->FbMapSize - 1;
1359                  pNv->PGRAPH[0x08a4/4] = pNv->FbMapSize - 1;
1360               }
1361            } else {
1362               pNv->PGRAPH[0x09A4/4] = pNv->PFB[0x0200/4];
1363               pNv->PGRAPH[0x09A8/4] = pNv->PFB[0x0204/4];
1364               pNv->PGRAPH[0x0750/4] = 0x00EA0000;
1365               pNv->PGRAPH[0x0754/4] = pNv->PFB[0x0200/4];
1366               pNv->PGRAPH[0x0750/4] = 0x00EA0004;
1367               pNv->PGRAPH[0x0754/4] = pNv->PFB[0x0204/4];
1368 
1369               pNv->PGRAPH[0x0820/4] = 0;
1370               pNv->PGRAPH[0x0824/4] = 0;
1371               pNv->PGRAPH[0x0864/4] = pNv->FbMapSize - 1;
1372               pNv->PGRAPH[0x0868/4] = pNv->FbMapSize - 1;
1373            }
1374 
1375            pNv->PGRAPH[0x0B20/4] = 0x00000000;
1376            pNv->PGRAPH[0x0B04/4] = 0xFFFFFFFF;
1377        }
1378     }
1379     pNv->PGRAPH[0x053C/4] = 0;
1380     pNv->PGRAPH[0x0540/4] = 0;
1381     pNv->PGRAPH[0x0544/4] = 0x00007FFF;
1382     pNv->PGRAPH[0x0548/4] = 0x00007FFF;
1383 
1384     pNv->PFIFO[0x0140] = 0x00000000;
1385     pNv->PFIFO[0x0141] = 0x00000001;
1386     pNv->PFIFO[0x0480] = 0x00000000;
1387     pNv->PFIFO[0x0494] = 0x00000000;
1388     if(pNv->Architecture >= NV_ARCH_40)
1389        pNv->PFIFO[0x0481] = 0x00010000;
1390     else
1391        pNv->PFIFO[0x0481] = 0x00000100;
1392     pNv->PFIFO[0x0490] = 0x00000000;
1393     pNv->PFIFO[0x0491] = 0x00000000;
1394     if(pNv->Architecture >= NV_ARCH_40)
1395        pNv->PFIFO[0x048B] = 0x00001213;
1396     else
1397        pNv->PFIFO[0x048B] = 0x00001209;
1398     pNv->PFIFO[0x0400] = 0x00000000;
1399     pNv->PFIFO[0x0414] = 0x00000000;
1400     pNv->PFIFO[0x0084] = 0x03000100;
1401     pNv->PFIFO[0x0085] = 0x00000110;
1402     pNv->PFIFO[0x0086] = 0x00000112;
1403     pNv->PFIFO[0x0143] = 0x0000FFFF;
1404     pNv->PFIFO[0x0496] = 0x0000FFFF;
1405     pNv->PFIFO[0x0050] = 0x00000000;
1406     pNv->PFIFO[0x0040] = 0xFFFFFFFF;
1407     pNv->PFIFO[0x0415] = 0x00000001;
1408     pNv->PFIFO[0x048C] = 0x00000000;
1409     pNv->PFIFO[0x04A0] = 0x00000000;
1410 #if X_BYTE_ORDER == X_BIG_ENDIAN
1411     pNv->PFIFO[0x0489] = 0x800F0078;
1412 #else
1413     pNv->PFIFO[0x0489] = 0x000F0078;
1414 #endif
1415     pNv->PFIFO[0x0488] = 0x00000001;
1416     pNv->PFIFO[0x0480] = 0x00000001;
1417     pNv->PFIFO[0x0494] = 0x00000001;
1418     pNv->PFIFO[0x0495] = 0x00000001;
1419     pNv->PFIFO[0x0140] = 0x00000001;
1420 
1421     if(!state) {
1422         pNv->CurrentState = NULL;
1423         return;
1424     }
1425 
1426     if(pNv->Architecture >= NV_ARCH_10) {
1427         if(pNv->twoHeads) {
1428            pNv->PCRTC0[0x0860/4] = state->head;
1429            pNv->PCRTC0[0x2860/4] = state->head2;
1430         }
1431         pNv->PRAMDAC[0x0404/4] |= (1 << 25);
1432 
1433         pNv->PMC[0x8704/4] = 1;
1434         pNv->PMC[0x8140/4] = 0;
1435         pNv->PMC[0x8920/4] = 0;
1436         pNv->PMC[0x8924/4] = 0;
1437         pNv->PMC[0x8908/4] = pNv->FbMapSize - 1;
1438         pNv->PMC[0x890C/4] = pNv->FbMapSize - 1;
1439         pNv->PMC[0x1588/4] = 0;
1440 
1441         pNv->PCRTC[0x0810/4] = state->cursorConfig;
1442         pNv->PCRTC[0x0830/4] = state->displayV - 3;
1443         pNv->PCRTC[0x0834/4] = state->displayV - 1;
1444 
1445         if(pNv->FlatPanel) {
1446            if((pNv->Chipset & 0x0ff0) == 0x0110) {
1447                pNv->PRAMDAC[0x0528/4] = state->dither;
1448            } else
1449            if(pNv->twoHeads) {
1450                pNv->PRAMDAC[0x083C/4] = state->dither;
1451            }
1452 
1453            VGA_WR08(pNv->PCIO, 0x03D4, 0x53);
1454            VGA_WR08(pNv->PCIO, 0x03D5, state->timingH);
1455            VGA_WR08(pNv->PCIO, 0x03D4, 0x54);
1456            VGA_WR08(pNv->PCIO, 0x03D5, state->timingV);
1457            VGA_WR08(pNv->PCIO, 0x03D4, 0x21);
1458            VGA_WR08(pNv->PCIO, 0x03D5, 0xfa);
1459         }
1460 
1461         VGA_WR08(pNv->PCIO, 0x03D4, 0x41);
1462         VGA_WR08(pNv->PCIO, 0x03D5, state->extra);
1463     }
1464 
1465     VGA_WR08(pNv->PCIO, 0x03D4, 0x19);
1466     VGA_WR08(pNv->PCIO, 0x03D5, state->repaint0);
1467     VGA_WR08(pNv->PCIO, 0x03D4, 0x1A);
1468     VGA_WR08(pNv->PCIO, 0x03D5, state->repaint1);
1469     VGA_WR08(pNv->PCIO, 0x03D4, 0x25);
1470     VGA_WR08(pNv->PCIO, 0x03D5, state->screen);
1471     VGA_WR08(pNv->PCIO, 0x03D4, 0x28);
1472     VGA_WR08(pNv->PCIO, 0x03D5, state->pixel);
1473     VGA_WR08(pNv->PCIO, 0x03D4, 0x2D);
1474     VGA_WR08(pNv->PCIO, 0x03D5, state->horiz);
1475     VGA_WR08(pNv->PCIO, 0x03D4, 0x1C);
1476     VGA_WR08(pNv->PCIO, 0x03D5, state->fifo);
1477     VGA_WR08(pNv->PCIO, 0x03D4, 0x1B);
1478     VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration0);
1479     VGA_WR08(pNv->PCIO, 0x03D4, 0x20);
1480     VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration1);
1481     if(pNv->Architecture >= NV_ARCH_30) {
1482       VGA_WR08(pNv->PCIO, 0x03D4, 0x47);
1483       VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration1 >> 8);
1484     }
1485     VGA_WR08(pNv->PCIO, 0x03D4, 0x30);
1486     VGA_WR08(pNv->PCIO, 0x03D5, state->cursor0);
1487     VGA_WR08(pNv->PCIO, 0x03D4, 0x31);
1488     VGA_WR08(pNv->PCIO, 0x03D5, state->cursor1);
1489     VGA_WR08(pNv->PCIO, 0x03D4, 0x2F);
1490     VGA_WR08(pNv->PCIO, 0x03D5, state->cursor2);
1491     VGA_WR08(pNv->PCIO, 0x03D4, 0x39);
1492     VGA_WR08(pNv->PCIO, 0x03D5, state->interlace);
1493 
1494     if(!pNv->FlatPanel) {
1495        if(pNv->Architecture >= NV_ARCH_40) {
1496            pNv->PRAMDAC0[0x0580/4] = state->control;
1497        }
1498 
1499        pNv->PRAMDAC0[0x050C/4] = state->pllsel;
1500        pNv->PRAMDAC0[0x0508/4] = state->vpll;
1501        if(pNv->twoHeads)
1502           pNv->PRAMDAC0[0x0520/4] = state->vpll2;
1503        if(pNv->twoStagePLL) {
1504           pNv->PRAMDAC0[0x0578/4] = state->vpllB;
1505           pNv->PRAMDAC0[0x057C/4] = state->vpll2B;
1506        }
1507     } else {
1508        pNv->PRAMDAC[0x0848/4] = state->scale;
1509        pNv->PRAMDAC[0x0828/4] = state->crtcSync;
1510        pNv->PRAMDAC[0x0808/4] = state->crtcVSync;
1511     }
1512     pNv->PRAMDAC[0x0600/4] = state->general;
1513 
1514     pNv->PCRTC[0x0140/4] = 0;
1515     pNv->PCRTC[0x0100/4] = 1;
1516 
1517     pNv->CurrentState = state;
1518 }
1519 
NVUnloadStateExt(NVPtr pNv,RIVA_HW_STATE * state)1520 void NVUnloadStateExt
1521 (
1522     NVPtr pNv,
1523     RIVA_HW_STATE *state
1524 )
1525 {
1526     VGA_WR08(pNv->PCIO, 0x03D4, 0x19);
1527     state->repaint0     = VGA_RD08(pNv->PCIO, 0x03D5);
1528     VGA_WR08(pNv->PCIO, 0x03D4, 0x1A);
1529     state->repaint1     = VGA_RD08(pNv->PCIO, 0x03D5);
1530     VGA_WR08(pNv->PCIO, 0x03D4, 0x25);
1531     state->screen       = VGA_RD08(pNv->PCIO, 0x03D5);
1532     VGA_WR08(pNv->PCIO, 0x03D4, 0x28);
1533     state->pixel        = VGA_RD08(pNv->PCIO, 0x03D5);
1534     VGA_WR08(pNv->PCIO, 0x03D4, 0x2D);
1535     state->horiz        = VGA_RD08(pNv->PCIO, 0x03D5);
1536     VGA_WR08(pNv->PCIO, 0x03D4, 0x1C);
1537     state->fifo         = VGA_RD08(pNv->PCIO, 0x03D5);
1538     VGA_WR08(pNv->PCIO, 0x03D4, 0x1B);
1539     state->arbitration0 = VGA_RD08(pNv->PCIO, 0x03D5);
1540     VGA_WR08(pNv->PCIO, 0x03D4, 0x20);
1541     state->arbitration1 = VGA_RD08(pNv->PCIO, 0x03D5);
1542     if(pNv->Architecture >= NV_ARCH_30) {
1543        VGA_WR08(pNv->PCIO, 0x03D4, 0x47);
1544        state->arbitration1 |= (VGA_RD08(pNv->PCIO, 0x03D5) & 1) << 8;
1545     }
1546     VGA_WR08(pNv->PCIO, 0x03D4, 0x30);
1547     state->cursor0      = VGA_RD08(pNv->PCIO, 0x03D5);
1548     VGA_WR08(pNv->PCIO, 0x03D4, 0x31);
1549     state->cursor1      = VGA_RD08(pNv->PCIO, 0x03D5);
1550     VGA_WR08(pNv->PCIO, 0x03D4, 0x2F);
1551     state->cursor2      = VGA_RD08(pNv->PCIO, 0x03D5);
1552     VGA_WR08(pNv->PCIO, 0x03D4, 0x39);
1553     state->interlace    = VGA_RD08(pNv->PCIO, 0x03D5);
1554     state->vpll         = pNv->PRAMDAC0[0x0508/4];
1555     if(pNv->twoHeads)
1556        state->vpll2     = pNv->PRAMDAC0[0x0520/4];
1557     if(pNv->twoStagePLL) {
1558         state->vpllB    = pNv->PRAMDAC0[0x0578/4];
1559         state->vpll2B   = pNv->PRAMDAC0[0x057C/4];
1560     }
1561     state->pllsel       = pNv->PRAMDAC0[0x050C/4];
1562     state->general      = pNv->PRAMDAC[0x0600/4];
1563     state->scale        = pNv->PRAMDAC[0x0848/4];
1564     state->config       = pNv->PFB[0x0200/4];
1565 
1566     if(pNv->Architecture >= NV_ARCH_40 && !pNv->FlatPanel) {
1567         state->control  = pNv->PRAMDAC0[0x0580/4];
1568     }
1569 
1570     if(pNv->Architecture >= NV_ARCH_10) {
1571         if(pNv->twoHeads) {
1572            state->head     = pNv->PCRTC0[0x0860/4];
1573            state->head2    = pNv->PCRTC0[0x2860/4];
1574            VGA_WR08(pNv->PCIO, 0x03D4, 0x44);
1575            state->crtcOwner = VGA_RD08(pNv->PCIO, 0x03D5);
1576         }
1577         VGA_WR08(pNv->PCIO, 0x03D4, 0x41);
1578         state->extra = VGA_RD08(pNv->PCIO, 0x03D5);
1579         state->cursorConfig = pNv->PCRTC[0x0810/4];
1580 
1581         if((pNv->Chipset & 0x0ff0) == 0x0110) {
1582            state->dither = pNv->PRAMDAC[0x0528/4];
1583         } else
1584         if(pNv->twoHeads) {
1585             state->dither = pNv->PRAMDAC[0x083C/4];
1586         }
1587 
1588         if(pNv->FlatPanel) {
1589            VGA_WR08(pNv->PCIO, 0x03D4, 0x53);
1590            state->timingH = VGA_RD08(pNv->PCIO, 0x03D5);
1591            VGA_WR08(pNv->PCIO, 0x03D4, 0x54);
1592            state->timingV = VGA_RD08(pNv->PCIO, 0x03D5);
1593         }
1594     }
1595 
1596     if(pNv->FlatPanel) {
1597        state->crtcSync = pNv->PRAMDAC[0x0828/4];
1598        state->crtcVSync = pNv->PRAMDAC[0x0808/4];
1599     }
1600 }
1601 
NVSetStartAddress(NVPtr pNv,CARD32 start)1602 void NVSetStartAddress (
1603     NVPtr   pNv,
1604     CARD32 start
1605 )
1606 {
1607     if (pNv->VBEDualhead) {
1608         pNv->PCRTC0[0x800/4] = start;
1609         pNv->PCRTC0[0x2800/4] = start + pNv->vbeCRTC1Offset;
1610     } else {
1611         pNv->PCRTC[0x800/4] = start;
1612     }
1613 }
1614