Cleanup of PVIDEO.
[nouveau] / src / nv_hw.c
1 /***************************************************************************\
2 |*                                                                           *|
3 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
4 |*                                                                           *|
5 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
6 |*     international laws.  Users and possessors of this source code are     *|
7 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
8 |*     use this code in individual and commercial software.                  *|
9 |*                                                                           *|
10 |*     Any use of this source code must include,  in the user documenta-     *|
11 |*     tion and  internal comments to the code,  notices to the end user     *|
12 |*     as follows:                                                           *|
13 |*                                                                           *|
14 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
15 |*                                                                           *|
16 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
17 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
18 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
19 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
20 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
21 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
22 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
23 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
24 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
25 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
26 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
27 |*                                                                           *|
28 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
29 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
30 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
31 |*     computer  software  documentation,"  as such  terms  are  used in     *|
32 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
33 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
34 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
35 |*     all U.S. Government End Users  acquire the source code  with only     *|
36 |*     those rights set forth herein.                                        *|
37 |*                                                                           *|
38  \***************************************************************************/
39 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c,v 1.21 2006/06/16 00:19:33 mvojkovi Exp $ */
40
41 #include "nv_include.h"
42 #include "nv_local.h"
43 #include "compiler.h"
44
45 uint8_t nvReadVGA(NVPtr pNv, uint8_t index)
46 {
47   volatile const uint8_t *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
48   VGA_WR08(ptr, 0x03D4, index);
49   return VGA_RD08(ptr, 0x03D5);
50 }
51
52 void nvWriteVGA(NVPtr pNv, uint8_t index, uint8_t data)
53 {
54   volatile const uint8_t *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
55   VGA_WR08(ptr, 0x03D4, index);
56   VGA_WR08(ptr, 0x03D5, data);
57 }
58
59 CARD32 nvReadRAMDAC(NVPtr pNv, uint8_t head, uint32_t ramdac_reg)
60 {
61   volatile const void *ptr = head ? pNv->PRAMDAC1 : pNv->PRAMDAC0;
62   return MMIO_IN32(ptr, ramdac_reg);
63 }
64
65 void nvWriteRAMDAC(NVPtr pNv, uint8_t head, uint32_t ramdac_reg, CARD32 val)
66 {
67   volatile const void *ptr = head ? pNv->PRAMDAC1 : pNv->PRAMDAC0;
68   MMIO_OUT32(ptr, ramdac_reg, val);
69 }
70
71 CARD32 nvReadCRTC(NVPtr pNv, uint8_t head, uint32_t reg)
72 {
73   volatile const void *ptr = head ? pNv->PCRTC1 : pNv->PCRTC0;
74   return MMIO_IN32(ptr, reg);
75 }
76
77 void nvWriteCRTC(NVPtr pNv, uint8_t head, uint32_t reg, CARD32 val)
78 {
79   volatile const void *ptr = head ? pNv->PCRTC1 : pNv->PCRTC0;
80   MMIO_OUT32(ptr, reg, val);
81 }
82
83 void NVLockUnlock (
84     NVPtr pNv,
85     Bool  Lock
86 )
87 {
88     CARD8 cr11;
89
90     nvWriteVGA(pNv, 0x1f, Lock ? 0x99 : 0x57 );
91
92     cr11 = nvReadVGA(pNv, 0x11);
93     if(Lock) cr11 |= 0x80;
94     else cr11 &= ~0x80;
95     nvWriteVGA(pNv, 0x11, cr11);
96 }
97
98 int NVShowHideCursor (
99     NVPtr pNv,
100     int   ShowHide
101 )
102 {
103     int current = pNv->CurrentState->cursor1;
104
105     pNv->CurrentState->cursor1 = (pNv->CurrentState->cursor1 & 0xFE) |
106                                  (ShowHide & 0x01);
107
108     nvWriteVGA(pNv, 0x31, pNv->CurrentState->cursor1);
109
110     if(pNv->Architecture == NV_ARCH_40) {  /* HW bug */
111        volatile CARD32 curpos = nvReadCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS);
112        nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, curpos);
113     }
114
115     return (current & 0x01);
116 }
117
118 /****************************************************************************\
119 *                                                                            *
120 * The video arbitration routines calculate some "magic" numbers.  Fixes      *
121 * the snow seen when accessing the framebuffer without it.                   *
122 * It just works (I hope).                                                    *
123 *                                                                            *
124 \****************************************************************************/
125
126 typedef struct {
127   int graphics_lwm;
128   int video_lwm;
129   int graphics_burst_size;
130   int video_burst_size;
131   int valid;
132 } nv4_fifo_info;
133
134 typedef struct {
135   int pclk_khz;
136   int mclk_khz;
137   int nvclk_khz;
138   char mem_page_miss;
139   char mem_latency;
140   int memory_width;
141   char enable_video;
142   char gr_during_vid;
143   char pix_bpp;
144   char mem_aligned;
145   char enable_mp;
146 } nv4_sim_state;
147
148 typedef struct {
149   int graphics_lwm;
150   int video_lwm;
151   int graphics_burst_size;
152   int video_burst_size;
153   int valid;
154 } nv10_fifo_info;
155
156 typedef struct {
157   int pclk_khz;
158   int mclk_khz;
159   int nvclk_khz;
160   char mem_page_miss;
161   char mem_latency;
162   int memory_type;
163   int memory_width;
164   char enable_video;
165   char gr_during_vid;
166   char pix_bpp;
167   char mem_aligned;
168   char enable_mp;
169 } nv10_sim_state;
170
171
172 static void nvGetClocks(NVPtr pNv, unsigned int *MClk, unsigned int *NVClk)
173 {
174     unsigned int pll, N, M, MB, NB, P;
175
176     if(pNv->Architecture >= NV_ARCH_40) {
177        pll = nvReadMC(pNv, 0x4020);
178        P = (pll >> 16) & 0x07;
179        pll = nvReadMC(pNv, 0x4024);
180        M = pll & 0xFF;
181        N = (pll >> 8) & 0xFF;
182        if(((pNv->Chipset & 0xfff0) == CHIPSET_G71) ||
183           ((pNv->Chipset & 0xfff0) == CHIPSET_G73))
184        {
185           MB = 1;
186           NB = 1;
187        } else {
188           MB = (pll >> 16) & 0xFF;
189           NB = (pll >> 24) & 0xFF;
190        }
191        *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
192
193        pll = nvReadMC(pNv, 0x4000);
194        P = (pll >> 16) & 0x07;  
195        pll = nvReadMC(pNv, 0x4004);
196        M = pll & 0xFF;
197        N = (pll >> 8) & 0xFF;
198        MB = (pll >> 16) & 0xFF;
199        NB = (pll >> 24) & 0xFF;
200
201        *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
202     } else
203     if(pNv->twoStagePLL) {
204        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_MPLL);
205        M = pll & 0xFF;
206        N = (pll >> 8) & 0xFF; 
207        P = (pll >> 16) & 0x0F;
208        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_MPLL_B);
209        if(pll & 0x80000000) {
210            MB = pll & 0xFF; 
211            NB = (pll >> 8) & 0xFF;
212        } else {
213            MB = 1;
214            NB = 1;
215        }
216        *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
217
218        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL);
219        M = pll & 0xFF; 
220        N = (pll >> 8) & 0xFF; 
221        P = (pll >> 16) & 0x0F;
222        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL_B);
223        if(pll & 0x80000000) {
224            MB = pll & 0xFF;
225            NB = (pll >> 8) & 0xFF;
226        } else {
227            MB = 1;
228            NB = 1;
229        }
230        *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
231     } else 
232     if(((pNv->Chipset & 0x0ff0) == CHIPSET_NV30) ||
233        ((pNv->Chipset & 0x0ff0) == CHIPSET_NV35))
234     {
235        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_MPLL);
236        M = pll & 0x0F; 
237        N = (pll >> 8) & 0xFF;
238        P = (pll >> 16) & 0x07;
239        if(pll & 0x00000080) {
240            MB = (pll >> 4) & 0x07;     
241            NB = (pll >> 19) & 0x1f;
242        } else {
243            MB = 1;
244            NB = 1;
245        }
246        *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
247
248        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL);
249        M = pll & 0x0F;
250        N = (pll >> 8) & 0xFF;
251        P = (pll >> 16) & 0x07;
252        if(pll & 0x00000080) {
253            MB = (pll >> 4) & 0x07;
254            NB = (pll >> 19) & 0x1f;
255        } else {
256            MB = 1;
257            NB = 1;
258        }
259        *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
260     } else {
261        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_MPLL);
262        M = pll & 0xFF; 
263        N = (pll >> 8) & 0xFF; 
264        P = (pll >> 16) & 0x0F;
265        *MClk = (N * pNv->CrystalFreqKHz / M) >> P;
266
267        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL);
268        M = pll & 0xFF; 
269        N = (pll >> 8) & 0xFF; 
270        P = (pll >> 16) & 0x0F;
271        *NVClk = (N * pNv->CrystalFreqKHz / M) >> P;
272     }
273
274 #if 0
275     ErrorF("NVClock = %i MHz, MEMClock = %i MHz\n", *NVClk/1000, *MClk/1000);
276 #endif
277 }
278
279
280 static void nv4CalcArbitration (
281     nv4_fifo_info *fifo,
282     nv4_sim_state *arb
283 )
284 {
285     int data, pagemiss, cas,width, video_enable, bpp;
286     int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
287     int found, mclk_extra, mclk_loop, cbs, m1, p1;
288     int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
289     int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
290     int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm;
291
292     fifo->valid = 1;
293     pclk_freq = arb->pclk_khz;
294     mclk_freq = arb->mclk_khz;
295     nvclk_freq = arb->nvclk_khz;
296     pagemiss = arb->mem_page_miss;
297     cas = arb->mem_latency;
298     width = arb->memory_width >> 6;
299     video_enable = arb->enable_video;
300     bpp = arb->pix_bpp;
301     mp_enable = arb->enable_mp;
302     clwm = 0;
303     vlwm = 0;
304     cbs = 128;
305     pclks = 2;
306     nvclks = 2;
307     nvclks += 2;
308     nvclks += 1;
309     mclks = 5;
310     mclks += 3;
311     mclks += 1;
312     mclks += cas;
313     mclks += 1;
314     mclks += 1;
315     mclks += 1;
316     mclks += 1;
317     mclk_extra = 3;
318     nvclks += 2;
319     nvclks += 1;
320     nvclks += 1;
321     nvclks += 1;
322     if (mp_enable)
323         mclks+=4;
324     nvclks += 0;
325     pclks += 0;
326     found = 0;
327     vbs = 0;
328     while (found != 1)
329     {
330         fifo->valid = 1;
331         found = 1;
332         mclk_loop = mclks+mclk_extra;
333         us_m = mclk_loop *1000*1000 / mclk_freq;
334         us_n = nvclks*1000*1000 / nvclk_freq;
335         us_p = nvclks*1000*1000 / pclk_freq;
336         if (video_enable)
337         {
338             video_drain_rate = pclk_freq * 2;
339             crtc_drain_rate = pclk_freq * bpp/8;
340             vpagemiss = 2;
341             vpagemiss += 1;
342             crtpagemiss = 2;
343             vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
344             if (nvclk_freq * 2 > mclk_freq * width)
345                 video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ;
346             else
347                 video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq;
348             us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
349             vlwm = us_video * video_drain_rate/(1000*1000);
350             vlwm++;
351             vbs = 128;
352             if (vlwm > 128) vbs = 64;
353             if (vlwm > (256-64)) vbs = 32;
354             if (nvclk_freq * 2 > mclk_freq * width)
355                 video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ;
356             else
357                 video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq;
358             cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
359             us_crt =
360             us_video
361             +video_fill_us
362             +cpm_us
363             +us_m + us_n +us_p
364             ;
365             clwm = us_crt * crtc_drain_rate/(1000*1000);
366             clwm++;
367         }
368         else
369         {
370             crtc_drain_rate = pclk_freq * bpp/8;
371             crtpagemiss = 2;
372             crtpagemiss += 1;
373             cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
374             us_crt =  cpm_us + us_m + us_n + us_p ;
375             clwm = us_crt * crtc_drain_rate/(1000*1000);
376             clwm++;
377         }
378         m1 = clwm + cbs - 512;
379         p1 = m1 * pclk_freq / mclk_freq;
380         p1 = p1 * bpp / 8;
381         if ((p1 < m1) && (m1 > 0))
382         {
383             fifo->valid = 0;
384             found = 0;
385             if (mclk_extra ==0)   found = 1;
386             mclk_extra--;
387         }
388         else if (video_enable)
389         {
390             if ((clwm > 511) || (vlwm > 255))
391             {
392                 fifo->valid = 0;
393                 found = 0;
394                 if (mclk_extra ==0)   found = 1;
395                 mclk_extra--;
396             }
397         }
398         else
399         {
400             if (clwm > 519)
401             {
402                 fifo->valid = 0;
403                 found = 0;
404                 if (mclk_extra ==0)   found = 1;
405                 mclk_extra--;
406             }
407         }
408         if (clwm < 384) clwm = 384;
409         if (vlwm < 128) vlwm = 128;
410         data = (int)(clwm);
411         fifo->graphics_lwm = data;
412         fifo->graphics_burst_size = 128;
413         data = (int)((vlwm+15));
414         fifo->video_lwm = data;
415         fifo->video_burst_size = vbs;
416     }
417 }
418
419 static void nv4UpdateArbitrationSettings (
420     unsigned      VClk, 
421     unsigned      pixelDepth, 
422     unsigned     *burst,
423     unsigned     *lwm,
424     NVPtr        pNv
425 )
426 {
427     nv4_fifo_info fifo_data;
428     nv4_sim_state sim_data;
429     unsigned int MClk, NVClk, cfg1;
430
431     nvGetClocks(pNv, &MClk, &NVClk);
432
433     cfg1 = nvReadFB(pNv, NV_PFB_CFG1);
434     sim_data.pix_bpp        = (char)pixelDepth;
435     sim_data.enable_video   = 0;
436     sim_data.enable_mp      = 0;
437     sim_data.memory_width   = (nvReadEXTDEV(pNv, 0x0000) & 0x10) ? 128 : 64;
438     sim_data.mem_latency    = (char)cfg1 & 0x0F;
439     sim_data.mem_aligned    = 1;
440     sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
441     sim_data.gr_during_vid  = 0;
442     sim_data.pclk_khz       = VClk;
443     sim_data.mclk_khz       = MClk;
444     sim_data.nvclk_khz      = NVClk;
445     nv4CalcArbitration(&fifo_data, &sim_data);
446     if (fifo_data.valid)
447     {
448         int  b = fifo_data.graphics_burst_size >> 4;
449         *burst = 0;
450         while (b >>= 1) (*burst)++;
451         *lwm   = fifo_data.graphics_lwm >> 3;
452     }
453 }
454
455 static void nv10CalcArbitration (
456     nv10_fifo_info *fifo,
457     nv10_sim_state *arb
458 )
459 {
460     int data, pagemiss, width, video_enable, bpp;
461     int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
462     int nvclk_fill;
463     int found, mclk_extra, mclk_loop, cbs, m1;
464     int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
465     int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
466     int vus_m;
467     int vpm_us, us_video, cpm_us, us_crt,clwm;
468     int clwm_rnd_down;
469     int m2us, us_pipe_min, p1clk, p2;
470     int min_mclk_extra;
471     int us_min_mclk_extra;
472
473     fifo->valid = 1;
474     pclk_freq = arb->pclk_khz; /* freq in KHz */
475     mclk_freq = arb->mclk_khz;
476     nvclk_freq = arb->nvclk_khz;
477     pagemiss = arb->mem_page_miss;
478     width = arb->memory_width/64;
479     video_enable = arb->enable_video;
480     bpp = arb->pix_bpp;
481     mp_enable = arb->enable_mp;
482     clwm = 0;
483
484     cbs = 512;
485
486     pclks = 4; /* lwm detect. */
487
488     nvclks = 3; /* lwm -> sync. */
489     nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
490
491     mclks  = 1;   /* 2 edge sync.  may be very close to edge so just put one. */
492
493     mclks += 1;   /* arb_hp_req */
494     mclks += 5;   /* ap_hp_req   tiling pipeline */
495
496     mclks += 2;    /* tc_req     latency fifo */
497     mclks += 2;    /* fb_cas_n_  memory request to fbio block */
498     mclks += 7;    /* sm_d_rdv   data returned from fbio block */
499
500     /* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
501     if (arb->memory_type == 0)
502       if (arb->memory_width == 64) /* 64 bit bus */
503         mclks += 4;
504       else
505         mclks += 2;
506     else
507       if (arb->memory_width == 64) /* 64 bit bus */
508         mclks += 2;
509       else
510         mclks += 1;
511
512     if ((!video_enable) && (arb->memory_width == 128))
513     {  
514       mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
515       min_mclk_extra = 17;
516     }
517     else
518     {
519       mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
520       /* mclk_extra = 4; */ /* Margin of error */
521       min_mclk_extra = 18;
522     }
523
524     nvclks += 1; /* 2 edge sync.  may be very close to edge so just put one. */
525     nvclks += 1; /* fbi_d_rdv_n */
526     nvclks += 1; /* Fbi_d_rdata */
527     nvclks += 1; /* crtfifo load */
528
529     if(mp_enable)
530       mclks+=4; /* Mp can get in with a burst of 8. */
531     /* Extra clocks determined by heuristics */
532
533     nvclks += 0;
534     pclks += 0;
535     found = 0;
536     while(found != 1) {
537       fifo->valid = 1;
538       found = 1;
539       mclk_loop = mclks+mclk_extra;
540       us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
541       us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
542       us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
543       us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
544       us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
545       us_pipe_min = us_m_min + us_n + us_p;
546
547       vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
548
549       if(video_enable) {
550         crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
551
552         vpagemiss = 1; /* self generating page miss */
553         vpagemiss += 1; /* One higher priority before */
554
555         crtpagemiss = 2; /* self generating page miss */
556         if(mp_enable)
557             crtpagemiss += 1; /* if MA0 conflict */
558
559         vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
560
561         us_video = vpm_us + vus_m; /* Video has separate read return path */
562
563         cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
564         us_crt =
565           us_video  /* Wait for video */
566           +cpm_us /* CRT Page miss */
567           +us_m + us_n +us_p /* other latency */
568           ;
569
570         clwm = us_crt * crtc_drain_rate/(1000*1000);
571         clwm++; /* fixed point <= float_point - 1.  Fixes that */
572       } else {
573         crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
574
575         crtpagemiss = 1; /* self generating page miss */
576         crtpagemiss += 1; /* MA0 page miss */
577         if(mp_enable)
578             crtpagemiss += 1; /* if MA0 conflict */
579         cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
580         us_crt =  cpm_us + us_m + us_n + us_p ;
581         clwm = us_crt * crtc_drain_rate/(1000*1000);
582         clwm++; /* fixed point <= float_point - 1.  Fixes that */
583
584           /* Finally, a heuristic check when width == 64 bits */
585           if(width == 1){
586               nvclk_fill = nvclk_freq * 8;
587               if(crtc_drain_rate * 100 >= nvclk_fill * 102)
588                       clwm = 0xfff; /*Large number to fail */
589
590               else if(crtc_drain_rate * 100  >= nvclk_fill * 98) {
591                   clwm = 1024;
592                   cbs = 512;
593               }
594           }
595       }
596
597
598       /*
599         Overfill check:
600
601         */
602
603       clwm_rnd_down = ((int)clwm/8)*8;
604       if (clwm_rnd_down < clwm)
605           clwm += 8;
606
607       m1 = clwm + cbs -  1024; /* Amount of overfill */
608       m2us = us_pipe_min + us_min_mclk_extra;
609
610       /* pclk cycles to drain */
611       p1clk = m2us * pclk_freq/(1000*1000); 
612       p2 = p1clk * bpp / 8; /* bytes drained. */
613
614       if((p2 < m1) && (m1 > 0)) {
615           fifo->valid = 0;
616           found = 0;
617           if(min_mclk_extra == 0)   {
618             if(cbs <= 32) {
619               found = 1; /* Can't adjust anymore! */
620             } else {
621               cbs = cbs/2;  /* reduce the burst size */
622             }
623           } else {
624             min_mclk_extra--;
625           }
626       } else {
627         if (clwm > 1023){ /* Have some margin */
628           fifo->valid = 0;
629           found = 0;
630           if(min_mclk_extra == 0)   
631               found = 1; /* Can't adjust anymore! */
632           else 
633               min_mclk_extra--;
634         }
635       }
636
637       if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
638       data = (int)(clwm);
639       /*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
640       fifo->graphics_lwm = data;   fifo->graphics_burst_size = cbs;
641
642       fifo->video_lwm = 1024;  fifo->video_burst_size = 512;
643     }
644 }
645
646 static void nv10UpdateArbitrationSettings (
647     unsigned      VClk, 
648     unsigned      pixelDepth, 
649     unsigned     *burst,
650     unsigned     *lwm,
651     NVPtr        pNv
652 )
653 {
654     nv10_fifo_info fifo_data;
655     nv10_sim_state sim_data;
656     unsigned int MClk, NVClk, cfg1;
657
658     nvGetClocks(pNv, &MClk, &NVClk);
659
660     cfg1 = nvReadFB(pNv, NV_PFB_CFG1);
661     sim_data.pix_bpp        = (char)pixelDepth;
662     sim_data.enable_video   = 1;
663     sim_data.enable_mp      = 0;
664     sim_data.memory_type    = (nvReadFB(pNv, NV_PFB_CFG0) & 0x01) ? 1 : 0;
665     sim_data.memory_width   = (nvReadEXTDEV(pNv, 0x0000) & 0x10) ? 128 : 64;
666     sim_data.mem_latency    = (char)cfg1 & 0x0F;
667     sim_data.mem_aligned    = 1;
668     sim_data.mem_page_miss  = (char)(((cfg1>>4) &0x0F) + ((cfg1>>31) & 0x01));
669     sim_data.gr_during_vid  = 0;
670     sim_data.pclk_khz       = VClk;
671     sim_data.mclk_khz       = MClk;
672     sim_data.nvclk_khz      = NVClk;
673     nv10CalcArbitration(&fifo_data, &sim_data);
674     if (fifo_data.valid) {
675         int  b = fifo_data.graphics_burst_size >> 4;
676         *burst = 0;
677         while (b >>= 1) (*burst)++;
678         *lwm   = fifo_data.graphics_lwm >> 3;
679     }
680 }
681
682
683 static void nv30UpdateArbitrationSettings (
684     NVPtr        pNv,
685     unsigned     *burst,
686     unsigned     *lwm
687 )   
688 {
689     unsigned int MClk, NVClk;
690     unsigned int fifo_size, burst_size, graphics_lwm;
691
692     fifo_size = 2048;
693     burst_size = 512;
694     graphics_lwm = fifo_size - burst_size;
695
696     nvGetClocks(pNv, &MClk, &NVClk);
697     
698     *burst = 0;
699     burst_size >>= 5;
700     while(burst_size >>= 1) (*burst)++;
701     *lwm = graphics_lwm >> 3;
702 }
703
704 static void nForceUpdateArbitrationSettings (
705     unsigned      VClk,
706     unsigned      pixelDepth,
707     unsigned     *burst,
708     unsigned     *lwm,
709     NVPtr        pNv
710 )
711 {
712     nv10_fifo_info fifo_data;
713     nv10_sim_state sim_data;
714     unsigned int M, N, P, pll, MClk, NVClk, memctrl;
715
716     if((pNv->Chipset & 0x0FF0) == CHIPSET_NFORCE) {
717        unsigned int uMClkPostDiv;
718
719        uMClkPostDiv = (pciReadLong(pciTag(0, 0, 3), 0x6C) >> 8) & 0xf;
720        if(!uMClkPostDiv) uMClkPostDiv = 4; 
721        MClk = 400000 / uMClkPostDiv;
722     } else {
723        MClk = pciReadLong(pciTag(0, 0, 5), 0x4C) / 1000;
724     }
725
726     pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL);
727     M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
728     NVClk  = (N * pNv->CrystalFreqKHz / M) >> P;
729     sim_data.pix_bpp        = (char)pixelDepth;
730     sim_data.enable_video   = 0;
731     sim_data.enable_mp      = 0;
732     sim_data.memory_type    = (pciReadLong(pciTag(0, 0, 1), 0x7C) >> 12) & 1;
733     sim_data.memory_width   = 64;
734
735     memctrl = pciReadLong(pciTag(0, 0, 3), 0x00) >> 16;
736
737     if((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
738         int dimm[3];
739
740         dimm[0] = (pciReadLong(pciTag(0, 0, 2), 0x40) >> 8) & 0x4F;
741         dimm[1] = (pciReadLong(pciTag(0, 0, 2), 0x44) >> 8) & 0x4F;
742         dimm[2] = (pciReadLong(pciTag(0, 0, 2), 0x48) >> 8) & 0x4F;
743
744         if((dimm[0] + dimm[1]) != dimm[2]) {
745              ErrorF("WARNING: "
746               "your nForce DIMMs are not arranged in optimal banks!\n");
747         } 
748     }
749
750     sim_data.mem_latency    = 3;
751     sim_data.mem_aligned    = 1;
752     sim_data.mem_page_miss  = 10;
753     sim_data.gr_during_vid  = 0;
754     sim_data.pclk_khz       = VClk;
755     sim_data.mclk_khz       = MClk;
756     sim_data.nvclk_khz      = NVClk;
757     nv10CalcArbitration(&fifo_data, &sim_data);
758     if (fifo_data.valid)
759     {
760         int  b = fifo_data.graphics_burst_size >> 4;
761         *burst = 0;
762         while (b >>= 1) (*burst)++;
763         *lwm   = fifo_data.graphics_lwm >> 3;
764     }
765 }
766
767
768 /****************************************************************************\
769 *                                                                            *
770 *                          RIVA Mode State Routines                          *
771 *                                                                            *
772 \****************************************************************************/
773
774 /*
775  * Calculate the Video Clock parameters for the PLL.
776  */
777 static void CalcVClock (
778     int           clockIn,
779     int          *clockOut,
780     CARD32         *pllOut,
781     NVPtr        pNv
782 )
783 {
784     unsigned lowM, highM;
785     unsigned DeltaNew, DeltaOld;
786     unsigned VClk, Freq;
787     unsigned M, N, P;
788     
789     DeltaOld = 0xFFFFFFFF;
790
791     VClk = (unsigned)clockIn;
792     
793     if (pNv->CrystalFreqKHz == 13500) {
794         lowM  = 7;
795         highM = 13;
796     } else {
797         lowM  = 8;
798         highM = 14;
799     }
800
801     for (P = 0; P <= 4; P++) {
802         Freq = VClk << P;
803         if ((Freq >= 128000) && (Freq <= 350000)) {
804             for (M = lowM; M <= highM; M++) {
805                 N = ((VClk << P) * M) / pNv->CrystalFreqKHz;
806                 if(N <= 255) {
807                     Freq = ((pNv->CrystalFreqKHz * N) / M) >> P;
808                     if (Freq > VClk)
809                         DeltaNew = Freq - VClk;
810                     else
811                         DeltaNew = VClk - Freq;
812                     if (DeltaNew < DeltaOld) {
813                         *pllOut   = (P << 16) | (N << 8) | M;
814                         *clockOut = Freq;
815                         DeltaOld  = DeltaNew;
816                     }
817                 }
818             }
819         }
820     }
821 }
822
823 static void CalcVClock2Stage (
824     int           clockIn,
825     int          *clockOut,
826     CARD32         *pllOut,
827     CARD32         *pllBOut,
828     NVPtr        pNv
829 )
830 {
831     unsigned DeltaNew, DeltaOld;
832     unsigned VClk, Freq;
833     unsigned M, N, P;
834
835     DeltaOld = 0xFFFFFFFF;
836
837     *pllBOut = 0x80000401;  /* fixed at x4 for now */
838
839     VClk = (unsigned)clockIn;
840
841     for (P = 0; P <= 6; P++) {
842         Freq = VClk << P;
843         if ((Freq >= 400000) && (Freq <= 1000000)) {
844             for (M = 1; M <= 13; M++) {
845                 N = ((VClk << P) * M) / (pNv->CrystalFreqKHz << 2);
846                 if((N >= 5) && (N <= 255)) {
847                     Freq = (((pNv->CrystalFreqKHz << 2) * N) / M) >> P;
848                     if (Freq > VClk)
849                         DeltaNew = Freq - VClk;
850                     else
851                         DeltaNew = VClk - Freq;
852                     if (DeltaNew < DeltaOld) {
853                         *pllOut   = (P << 16) | (N << 8) | M;
854                         *clockOut = Freq;
855                         DeltaOld  = DeltaNew;
856                     }
857                 }
858             }
859         }
860     }
861 }
862
863 /*
864  * Calculate extended mode parameters (SVGA) and save in a 
865  * mode state structure.
866  */
867 void NVCalcStateExt (
868     NVPtr pNv,
869     RIVA_HW_STATE *state,
870     int            bpp,
871     int            width,
872     int            hDisplaySize,
873     int            height,
874     int            dotClock,
875     int            flags 
876 )
877 {
878     int pixelDepth, VClk;
879         CARD32 CursorStart;
880
881     /*
882      * Save mode parameters.
883      */
884     state->bpp    = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
885     state->width  = width;
886     state->height = height;
887     /*
888      * Extended RIVA registers.
889      */
890     pixelDepth = (bpp + 1)/8;
891     if(pNv->twoStagePLL)
892         CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, pNv);
893     else
894         CalcVClock(dotClock, &VClk, &state->pll, pNv);
895
896     switch (pNv->Architecture)
897     {
898         case NV_ARCH_04:
899             nv4UpdateArbitrationSettings(VClk, 
900                                          pixelDepth * 8, 
901                                         &(state->arbitration0),
902                                         &(state->arbitration1),
903                                          pNv);
904             state->cursor0  = 0x00;
905             state->cursor1  = 0xbC;
906             if (flags & V_DBLSCAN)
907                 state->cursor1 |= 2;
908             state->cursor2  = 0x00000000;
909             state->pllsel   = 0x10000700;
910             state->config   = 0x00001114;
911             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
912             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
913             break;
914         case NV_ARCH_10:
915         case NV_ARCH_20:
916         case NV_ARCH_30:
917         default:
918             if(((pNv->Chipset & 0xfff0) == CHIPSET_C51) ||
919                ((pNv->Chipset & 0xfff0) == CHIPSET_C512))
920             {
921                 state->arbitration0 = 128; 
922                 state->arbitration1 = 0x0480; 
923             } else
924             if(((pNv->Chipset & 0xffff) == CHIPSET_NFORCE) ||
925                ((pNv->Chipset & 0xffff) == CHIPSET_NFORCE2))
926             {
927                 nForceUpdateArbitrationSettings(VClk,
928                                           pixelDepth * 8,
929                                          &(state->arbitration0),
930                                          &(state->arbitration1),
931                                           pNv);
932             } else if(pNv->Architecture < NV_ARCH_30) {
933                 nv10UpdateArbitrationSettings(VClk, 
934                                           pixelDepth * 8, 
935                                          &(state->arbitration0),
936                                          &(state->arbitration1),
937                                           pNv);
938             } else {
939                 nv30UpdateArbitrationSettings(pNv,
940                                          &(state->arbitration0),
941                                          &(state->arbitration1));
942             }
943                         CursorStart = pNv->Cursor->offset - pNv->VRAMPhysical;
944             state->cursor0  = 0x80 | (CursorStart >> 17);
945             state->cursor1  = (CursorStart >> 11) << 2;
946             state->cursor2  = CursorStart >> 24;
947             if (flags & V_DBLSCAN) 
948                 state->cursor1 |= 2;
949             state->pllsel   = 0x10000700;
950             state->config   = nvReadFB(pNv, NV_PFB_CFG0);
951             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
952             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
953             break;
954     }
955
956     if(bpp != 8) /* DirectColor */
957         state->general |= 0x00000030;
958
959     state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
960     state->pixel    = (pixelDepth > 2) ? 3 : pixelDepth;
961 }
962
963
964 void NVLoadStateExt (
965     ScrnInfoPtr pScrn,
966     RIVA_HW_STATE *state
967 )
968 {
969     NVPtr pNv = NVPTR(pScrn);
970     int i, j;
971     CARD32 temp;
972
973     if (!pNv->IRQ)
974         nvWriteMC(pNv, 0x140, 0);
975
976     nvWriteTIMER(pNv, 0x0200, 0x00000008);
977     nvWriteTIMER(pNv, 0x0210, 0x00000003);
978     /*TODO: DRM handle PTIMER interrupts */
979     nvWriteTIMER(pNv, 0x0140, 0x00000000);
980     nvWriteTIMER(pNv, 0x0100, 0xFFFFFFFF);
981
982     /* begin surfaces */
983     /* it seems those regions are equivalent to the radeon's SURFACEs. needs to go in-kernel just like the SURFACEs */
984     if(pNv->Architecture == NV_ARCH_04) {
985         nvWriteFB(pNv, NV_PFB_CFG0, state->config);
986     } else 
987     if((pNv->Architecture < NV_ARCH_40) ||
988        ((pNv->Chipset & 0xfff0) == CHIPSET_NV40))
989     {
990         for(i = 0; i < 8; i++) {
991            nvWriteFB(pNv, (NV_PFB_TILE_NV10 + (i * 0x10)), 0);
992            nvWriteFB(pNv, (NV_PFB_TILE_SIZE_NV10 + (i * 0x10)), pNv->VRAMPhysicalSize - 1);
993         }
994     } else {
995         int regions = 12;
996
997         if(((pNv->Chipset & 0xfff0) == CHIPSET_G70) ||
998            ((pNv->Chipset & 0xfff0) == CHIPSET_G71) ||
999            ((pNv->Chipset & 0xfff0) == CHIPSET_G72) ||
1000            ((pNv->Chipset & 0xfff0) == CHIPSET_G73) ||
1001            ((pNv->Chipset & 0xfff0) == CHIPSET_C512))
1002         {
1003            regions = 15;
1004         }
1005  
1006        for(i = 0; i < regions; i++) {
1007           nvWriteFB(pNv, (NV_PFB_TILE_NV40 + (i * 0x10)), 0);
1008           nvWriteFB(pNv, (NV_PFB_TILE_SIZE_NV40 + (i * 0x10)), pNv->VRAMPhysicalSize - 1);
1009        }
1010     }
1011     /* end of surfaces */
1012
1013     if(pNv->Architecture < NV_ARCH_10) {
1014        if((pNv->Chipset & 0x0fff) == CHIPSET_NV04) {
1015                    /*XXX: RAMIN access here, find out what it's for.
1016                         *     The DRM is handling RAMIN now
1017                         */
1018            pNv->PRAMIN[0x0824] |= 0x00020000;
1019            pNv->PRAMIN[0x0826] += pNv->VRAMPhysical;
1020        }
1021        nvWriteGRAPH(pNv, NV_PGRAPH_DEBUG_0, 0x000001FF);
1022        nvWriteGRAPH(pNv, NV_PGRAPH_DEBUG_0, 0x1230C000);
1023        nvWriteGRAPH(pNv, NV_PGRAPH_DEBUG_1, 0x72111101);
1024        nvWriteGRAPH(pNv, 0x0088, 0x11D5F071);
1025        nvWriteGRAPH(pNv, NV_PGRAPH_DEBUG_3, 0x0004FF31);
1026        nvWriteGRAPH(pNv, NV_PGRAPH_DEBUG_3, 0x4004FF31);
1027
1028        if (!pNv->IRQ) {
1029            nvWriteGRAPH(pNv, NV_PGRAPH_INTR_EN, 0x0);
1030            nvWriteGRAPH(pNv, NV_PGRAPH_INTR, 0xFFFFFFFF);
1031        }
1032        nvWriteGRAPH(pNv, 0x0170, 0x10010100);
1033        nvWriteGRAPH(pNv, NV_PGRAPH_SURFACE, 0xFFFFFFFF);
1034        nvWriteGRAPH(pNv, NV_PGRAPH_FIFO, 0x00000001);
1035
1036        nvWriteGRAPH(pNv, NV_PGRAPH_PATTERN_SHAPE, 0x00000000);
1037        nvWriteGRAPH(pNv, NV_PGRAPH_BETA_AND, 0xFFFFFFFF);
1038     } else {
1039        nvWriteGRAPH(pNv, NV_PGRAPH_DEBUG_0, 0xFFFFFFFF);
1040        nvWriteGRAPH(pNv, NV_PGRAPH_DEBUG_0, 0x00000000);
1041
1042        if (!pNv->IRQ) {
1043            nvWriteGRAPH(pNv, NV_PGRAPH_INTR_EN, 0x0);
1044            nvWriteGRAPH(pNv, NV_PGRAPH_INTR, 0xFFFFFFFF);
1045        }
1046        nvWriteGRAPH(pNv, NV_PGRAPH_CTX_CONTROL, 0x10010100);
1047        nvWriteGRAPH(pNv, NV_PGRAPH_STATE, 0xFFFFFFFF);
1048        nvWriteGRAPH(pNv, NV_PGRAPH_FIFO, 0x00000001);
1049        temp = nvReadGRAPH(pNv, NV_PGRAPH_SURFACE);
1050        nvWriteGRAPH(pNv, NV_PGRAPH_SURFACE, temp & 0x0007ff00);
1051        temp = nvReadGRAPH(pNv, NV_PGRAPH_SURFACE);
1052        nvWriteGRAPH(pNv, NV_PGRAPH_SURFACE, temp | 0x00020100);
1053
1054        if(pNv->Architecture == NV_ARCH_10) {
1055            nvWriteGRAPH(pNv, NV_PGRAPH_DEBUG_1, 0x00118700);
1056            nvWriteGRAPH(pNv, 0x0088, 0x24E00810);
1057            nvWriteGRAPH(pNv, NV_PGRAPH_DEBUG_3, 0x55DE0030);
1058
1059            /* nv10 second surfaces */
1060            /* this is a copy of the surfaces. What is it for ? */
1061            for(i = 0; i < 32; i++)
1062              nvWriteGRAPH(pNv, 0x0B00 + (i*4), nvReadFB(pNv, NV_PFB_TILE_NV10 + (i*4)));
1063            /* end of nv10 second surfaces */
1064
1065            nvWriteGRAPH(pNv, NV_PGRAPH_BOFFSET0, 0);
1066            nvWriteGRAPH(pNv, NV_PGRAPH_BOFFSET1, 0);
1067            nvWriteGRAPH(pNv, NV_PGRAPH_BLIMIT0, pNv->VRAMPhysicalSize - 1);
1068            nvWriteGRAPH(pNv, NV_PGRAPH_BLIMIT1, pNv->VRAMPhysicalSize - 1);
1069
1070            nvWriteGRAPH(pNv, 0x0810, 0x00000000);
1071            nvWriteGRAPH(pNv, 0x0608, 0xFFFFFFFF);
1072        } else {
1073            if(pNv->Architecture >= NV_ARCH_40) {
1074               nvWriteGRAPH(pNv, NV_PGRAPH_DEBUG_1, 0x401287c0);
1075               nvWriteGRAPH(pNv, NV_PGRAPH_DEBUG_3, 0x60de8051);
1076               nvWriteGRAPH(pNv, NV_PGRAPH_DEBUG_4, 0x00008000);
1077               nvWriteGRAPH(pNv, NV_PGRAPH_LIMIT_VIOL_PIX, 0x00be3c5f);
1078
1079               j = pNv->REGS[0x1540/4] & 0xff;
1080               if(j) {
1081                   for(i = 0; !(j & 1); j >>= 1, i++);
1082                   nvWriteGRAPH(pNv, 0x5000, i);
1083               }
1084
1085               if((pNv->Chipset & 0xfff0) == CHIPSET_NV40) {
1086                  nvWriteGRAPH(pNv, 0x09b0, 0x83280fff);
1087                  nvWriteGRAPH(pNv, 0x09b4, 0x000000a0);
1088               } else {
1089                  nvWriteGRAPH(pNv, 0x0820, 0x83280eff);
1090                  nvWriteGRAPH(pNv, 0x0824, 0x000000a0);
1091               }
1092
1093               switch(pNv->Chipset & 0xfff0) {
1094               case CHIPSET_NV40:
1095               case CHIPSET_NV45:
1096                  nvWriteGRAPH(pNv, 0x09b8, 0x0078e366);
1097                  nvWriteGRAPH(pNv, 0x09bc, 0x0000014c);
1098                  temp = nvReadFB(pNv, NV_PFB_CLOSE_PAGE2);
1099                  nvWriteFB(pNv, NV_PFB_CLOSE_PAGE2, temp & 0xffff7fff);
1100                  break;
1101               case CHIPSET_NV41:
1102               case 0x0120:
1103                  nvWriteGRAPH(pNv, 0x0828, 0x007596ff);
1104                  nvWriteGRAPH(pNv, 0x082C, 0x00000108);
1105                  break;
1106               case CHIPSET_NV44:
1107               case CHIPSET_G72:
1108               case CHIPSET_C51:
1109               case CHIPSET_C512:
1110                  nvWriteMC(pNv, 0x1700, nvReadFB(pNv, NV_PFB_020C));
1111                  nvWriteMC(pNv, 0x1704, 0);
1112                  nvWriteMC(pNv, 0x1708, 0);
1113                  nvWriteMC(pNv, 0x170C, nvReadFB(pNv, NV_PFB_020C));
1114                  nvWriteGRAPH(pNv, 0x0860, 0);
1115                  nvWriteGRAPH(pNv, 0x0864, 0);
1116                  temp = nvReadCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL);
1117                  nvWriteCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL, temp | 0x00100000);
1118                  break;
1119               case CHIPSET_NV43:
1120                  nvWriteGRAPH(pNv, 0x0828, 0x0072cb77);
1121                  nvWriteGRAPH(pNv, 0x082C, 0x00000108);
1122                  break;
1123               case CHIPSET_NV44A:
1124                  nvWriteGRAPH(pNv, 0x0860, 0);
1125                  nvWriteGRAPH(pNv, 0x0864, 0);
1126                  temp = nvReadCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL);
1127                  nvWriteCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL, temp | 0x00100000);
1128                  break;
1129               case CHIPSET_G70:
1130               case CHIPSET_G71:
1131               case CHIPSET_G73:
1132                  temp = nvReadCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL);
1133                  nvWriteCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL, temp | 0x00100000);
1134                  nvWriteGRAPH(pNv, 0x0828, 0x07830610);
1135                  nvWriteGRAPH(pNv, 0x082C, 0x0000016A);
1136                  break;
1137               default:
1138                  break;
1139               };
1140
1141               nvWriteGRAPH(pNv, 0x0b38, 0x2ffff800);
1142               nvWriteGRAPH(pNv, 0x0b3c, 0x00006000);
1143               nvWriteGRAPH(pNv, 0x032C, 0x01000000); 
1144            } else
1145            if(pNv->Architecture == NV_ARCH_30) {
1146               nvWriteGRAPH(pNv, 0x0084, 0x40108700);
1147               nvWriteGRAPH(pNv, 0x0890, 0x00140000);
1148               nvWriteGRAPH(pNv, 0x008C, 0xf00e0431);
1149               nvWriteGRAPH(pNv, 0x0090, 0x00008000);
1150               nvWriteGRAPH(pNv, 0x0610, 0xf04b1f36);
1151               nvWriteGRAPH(pNv, 0x0B80, 0x1002d888);
1152               nvWriteGRAPH(pNv, 0x0B88, 0x62ff007f);
1153            } else {
1154               nvWriteGRAPH(pNv, 0x0084, 0x00118700);
1155               nvWriteGRAPH(pNv, 0x008C, 0xF20E0431);
1156               nvWriteGRAPH(pNv, 0x0090, 0x00000000);
1157               nvWriteGRAPH(pNv, 0x009C, 0x00000040);
1158
1159               if((pNv->Chipset & 0x0ff0) >= CHIPSET_NV25) {
1160                  nvWriteGRAPH(pNv, 0x0890, 0x00080000);
1161                  nvWriteGRAPH(pNv, 0x0610, 0x304B1FB6); 
1162                  nvWriteGRAPH(pNv, 0x0B80, 0x18B82880); 
1163                  nvWriteGRAPH(pNv, 0x0B84, 0x44000000); 
1164                  nvWriteGRAPH(pNv, 0x0098, 0x40000080); 
1165                  nvWriteGRAPH(pNv, 0x0B88, 0x000000ff); 
1166               } else {
1167                  nvWriteGRAPH(pNv, 0x0880, 0x00080000);
1168                  nvWriteGRAPH(pNv, 0x0094, 0x00000005);
1169                  nvWriteGRAPH(pNv, 0x0B80, 0x45CAA208); 
1170                  nvWriteGRAPH(pNv, 0x0B84, 0x24000000);
1171                  nvWriteGRAPH(pNv, 0x0098, 0x00000040);
1172                  nvWriteGRAPH(pNv, 0x0750, 0x00E00038);
1173                  nvWriteGRAPH(pNv, 0x0754, 0x00000030);
1174                  nvWriteGRAPH(pNv, 0x0750, 0x00E10038);
1175                  nvWriteGRAPH(pNv, 0x0754, 0x00000030);
1176               }
1177            }
1178
1179            /* begin nv20+ secondr surfaces */
1180            /* again, a copy of the surfaces. */
1181            if((pNv->Architecture < NV_ARCH_40) ||
1182               ((pNv->Chipset & 0xfff0) == CHIPSET_NV40)) 
1183            {
1184               for(i = 0; i < 32; i++) {
1185                 nvWriteGRAPH(pNv, 0x0900 + i*4, nvReadFB(pNv, NV_PFB_TILE_NV10 + i*4));
1186                 nvWriteGRAPH(pNv, 0x6900 + i*4, nvReadFB(pNv, NV_PFB_TILE_NV10 + i*4));
1187               }
1188            } else {
1189               if(((pNv->Chipset & 0xfff0) == CHIPSET_G70) ||
1190                  ((pNv->Chipset & 0xfff0) == CHIPSET_G71) ||
1191                  ((pNv->Chipset & 0xfff0) == CHIPSET_G72) ||
1192                  ((pNv->Chipset & 0xfff0) == CHIPSET_G73) ||
1193                  ((pNv->Chipset & 0xfff0) == CHIPSET_C512))
1194               {
1195                  for(i = 0; i < 60; i++) {
1196                    nvWriteGRAPH(pNv, 0x0D00 + i*4, nvReadFB(pNv, NV_PFB_TILE_NV40 + i*4));
1197                    nvWriteGRAPH(pNv, 0x6900 + i*4, nvReadFB(pNv, NV_PFB_TILE_NV40 + i*4));
1198                  }
1199               } else {
1200                  for(i = 0; i < 48; i++) {
1201                    nvWriteGRAPH(pNv, 0x0900 + i*4, nvReadFB(pNv, NV_PFB_TILE_NV40 + i*4));
1202                    if(((pNv->Chipset & 0xfff0) != CHIPSET_NV44) &&
1203                       ((pNv->Chipset & 0xfff0) != CHIPSET_NV44A) &&
1204                       ((pNv->Chipset & 0xfff0) != CHIPSET_C51))
1205                    {
1206                       nvWriteGRAPH(pNv, 0x6900 + i*4, nvReadFB(pNv, NV_PFB_TILE_NV40 + i*4));
1207                    }
1208                  }
1209               }
1210            }
1211            /* end nv20+ second surfaces */
1212
1213            /* begin RAM config */
1214            if(pNv->Architecture >= NV_ARCH_40) {
1215               if((pNv->Chipset & 0xfff0) == CHIPSET_NV40) {
1216                  nvWriteGRAPH(pNv, 0x09A4, nvReadFB(pNv, NV_PFB_CFG0));
1217                  nvWriteGRAPH(pNv, 0x09A8, nvReadFB(pNv, NV_PFB_CFG1));
1218                  nvWriteGRAPH(pNv, 0x69A4, nvReadFB(pNv, NV_PFB_CFG0));
1219                  nvWriteGRAPH(pNv, 0x69A8, nvReadFB(pNv, NV_PFB_CFG1));
1220
1221                  nvWriteGRAPH(pNv, 0x0820, 0);
1222                  nvWriteGRAPH(pNv, 0x0824, 0);
1223                  nvWriteGRAPH(pNv, 0x0864, pNv->VRAMPhysicalSize - 1);
1224                  nvWriteGRAPH(pNv, 0x0868, pNv->VRAMPhysicalSize - 1);
1225               } else {
1226                  if(((pNv->Chipset & 0xfff0) == CHIPSET_G70) ||
1227                     ((pNv->Chipset & 0xfff0) == CHIPSET_G71) ||
1228                     ((pNv->Chipset & 0xfff0) == CHIPSET_G72) ||
1229                     ((pNv->Chipset & 0xfff0) == CHIPSET_G73)) 
1230                  {
1231                     nvWriteGRAPH(pNv, 0x0DF0, nvReadFB(pNv, NV_PFB_CFG0));
1232                     nvWriteGRAPH(pNv, 0x0DF4, nvReadFB(pNv, NV_PFB_CFG1));
1233                  } else {
1234                     nvWriteGRAPH(pNv, 0x09F0, nvReadFB(pNv, NV_PFB_CFG0));
1235                     nvWriteGRAPH(pNv, 0x09F4, nvReadFB(pNv, NV_PFB_CFG1));
1236                  }
1237                  nvWriteGRAPH(pNv, 0x69F0, nvReadFB(pNv, NV_PFB_CFG0));
1238                  nvWriteGRAPH(pNv, 0x69F4, nvReadFB(pNv, NV_PFB_CFG1));
1239
1240                  nvWriteGRAPH(pNv, 0x0840, 0);
1241                  nvWriteGRAPH(pNv, 0x0844, 0);
1242                  nvWriteGRAPH(pNv, 0x08a0, pNv->VRAMPhysicalSize - 1);
1243                  nvWriteGRAPH(pNv, 0x08a4, pNv->VRAMPhysicalSize - 1);
1244               }
1245            } else {
1246               nvWriteGRAPH(pNv, 0x09A4, nvReadFB(pNv, NV_PFB_CFG0));
1247               nvWriteGRAPH(pNv, 0x09A8, nvReadFB(pNv, NV_PFB_CFG1));
1248               nvWriteGRAPH(pNv, 0x0750, 0x00EA0000);
1249               nvWriteGRAPH(pNv, 0x0754, nvReadFB(pNv, NV_PFB_CFG0));
1250               nvWriteGRAPH(pNv, 0x0750, 0x00EA0004);
1251               nvWriteGRAPH(pNv, 0x0754, nvReadFB(pNv, NV_PFB_CFG1));
1252
1253               nvWriteGRAPH(pNv, 0x0820, 0);
1254               nvWriteGRAPH(pNv, 0x0824, 0);
1255               nvWriteGRAPH(pNv, 0x0864, pNv->VRAMPhysicalSize - 1);
1256               nvWriteGRAPH(pNv, 0x0868, pNv->VRAMPhysicalSize - 1);
1257            }
1258            /* end of RAM config */
1259
1260            nvWriteGRAPH(pNv, 0x0B20, 0x00000000);
1261            nvWriteGRAPH(pNv, 0x0B04, 0xFFFFFFFF);
1262        }
1263     }
1264
1265     /* begin clipping values */
1266     nvWriteGRAPH(pNv, 0x053C, 0);
1267     nvWriteGRAPH(pNv, 0x0540, 0);
1268     nvWriteGRAPH(pNv, 0x0544, 0x00007FFF);
1269     nvWriteGRAPH(pNv, 0x0548, 0x00007FFF);
1270     /* end of clipping values */
1271
1272     if(pNv->Architecture >= NV_ARCH_10) {
1273         if(pNv->twoHeads) {
1274            nvWriteCRTC(pNv, 0, NV_CRTC_HEAD_CONFIG, state->head);
1275            nvWriteCRTC(pNv, 1, NV_CRTC_HEAD_CONFIG, state->head2);
1276         }
1277         temp = nvReadCurRAMDAC(pNv, NV_RAMDAC_0404);
1278         nvWriteCurRAMDAC(pNv, NV_RAMDAC_0404, temp | (1 << 25));
1279     
1280         nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
1281         nvWriteVIDEO(pNv, NV_PVIDEO_INTR_EN, 0);
1282         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(0), 0);
1283         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(1), 0);
1284         nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(0), pNv->VRAMPhysicalSize - 1);
1285         nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(1), pNv->VRAMPhysicalSize - 1);
1286         nvWriteMC(pNv, 0x1588, 0);
1287
1288         nvWriteCurCRTC(pNv, NV_CRTC_CURSOR_CONFIG, state->cursorConfig);
1289         nvWriteCurCRTC(pNv, NV_CRTC_0830, state->displayV - 3);
1290         nvWriteCurCRTC(pNv, NV_CRTC_0834, state->displayV - 1);
1291     
1292         if(pNv->FlatPanel) {
1293            if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
1294                nvWriteCurRAMDAC(pNv, NV_RAMDAC_DITHER_NV11, state->dither);
1295            } else 
1296            if(pNv->twoHeads) {
1297                nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_DITHER, state->dither);
1298            }
1299     
1300            nvWriteVGA(pNv, 0x53, state->timingH);
1301            nvWriteVGA(pNv, 0x54, state->timingV);
1302            nvWriteVGA(pNv, 0x21, 0xfa);
1303         }
1304
1305         nvWriteVGA(pNv, 0x41, state->extra);
1306     }
1307
1308     nvWriteVGA(pNv, 0x19, state->repaint0);
1309     nvWriteVGA(pNv, 0x1A, state->repaint1);
1310     nvWriteVGA(pNv, 0x25, state->screen);
1311     nvWriteVGA(pNv, 0x28, state->pixel);
1312     nvWriteVGA(pNv, 0x2D, state->horiz);
1313     nvWriteVGA(pNv, 0x1C, state->fifo);
1314     nvWriteVGA(pNv, 0x1B, state->arbitration0);
1315     nvWriteVGA(pNv, 0x20, state->arbitration1);
1316     if(pNv->Architecture >= NV_ARCH_30) {
1317       nvWriteVGA(pNv, 0x47, state->arbitration1 >> 8);
1318     }
1319
1320     nvWriteVGA(pNv, 0x30, state->cursor0);
1321     nvWriteVGA(pNv, 0x31, state->cursor1);
1322     if(pNv->Architecture == NV_ARCH_40) {  /* HW bug */
1323        volatile CARD32 curpos = nvReadCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS);
1324        nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, curpos);
1325     }
1326     nvWriteVGA(pNv, 0x2F, state->cursor2);
1327     nvWriteVGA(pNv, 0x39, state->interlace);
1328
1329     if(!pNv->FlatPanel) {
1330        nvWriteRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT, state->pllsel);
1331        nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL, state->vpll);
1332        if(pNv->twoHeads)
1333           nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2, state->vpll2);
1334        if(pNv->twoStagePLL) {
1335           nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL_B, state->vpllB);
1336           nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2_B, state->vpll2B);
1337        }
1338     } else {
1339        nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL, state->scale);
1340        nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_HCRTC, state->crtcSync);
1341     }
1342     nvWriteCurRAMDAC(pNv, NV_RAMDAC_GENERAL_CONTROL, state->general);
1343
1344     nvWriteCurCRTC(pNv, NV_CRTC_INTR_EN_0, 0);
1345     nvWriteCurCRTC(pNv, NV_CRTC_INTR_0, NV_CRTC_INTR_VBLANK);
1346
1347     pNv->CurrentState = state;
1348 }
1349
1350 void NVUnloadStateExt
1351 (
1352     NVPtr pNv,
1353     RIVA_HW_STATE *state
1354 )
1355 {
1356     state->repaint0     = nvReadVGA(pNv, 0x19);
1357     state->repaint1     = nvReadVGA(pNv, 0x1A);
1358     state->screen       = nvReadVGA(pNv, 0x25);
1359     state->pixel        = nvReadVGA(pNv, 0x28);
1360     state->horiz        = nvReadVGA(pNv, 0x2D);
1361     state->fifo         = nvReadVGA(pNv, 0x1C);
1362     state->arbitration0 = nvReadVGA(pNv, 0x1B);
1363     state->arbitration1 = nvReadVGA(pNv, 0x20);
1364     if(pNv->Architecture >= NV_ARCH_30) {
1365        state->arbitration1 |= (nvReadVGA(pNv, 0x47) & 1) << 8;
1366     }
1367     state->cursor0      = nvReadVGA(pNv, 0x30);
1368     state->cursor1      = nvReadVGA(pNv, 0x31);
1369     state->cursor2      = nvReadVGA(pNv, 0x2F);
1370     state->interlace    = nvReadVGA(pNv, 0x39);
1371
1372     state->vpll         = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL);
1373     if(pNv->twoHeads)
1374        state->vpll2     = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL2);
1375     if(pNv->twoStagePLL) {
1376         state->vpllB    = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL_B);
1377         state->vpll2B   = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL2_B);
1378     }
1379     state->pllsel       = nvReadRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT);
1380     state->general      = nvReadCurRAMDAC(pNv, NV_RAMDAC_GENERAL_CONTROL);
1381     state->scale        = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL);
1382     state->config       = nvReadFB(pNv, NV_PFB_CFG0);
1383
1384     if(pNv->Architecture >= NV_ARCH_10) {
1385         if(pNv->twoHeads) {
1386            state->head     = nvReadCRTC(pNv, 0, NV_CRTC_HEAD_CONFIG);
1387            state->head2    = nvReadCRTC(pNv, 1, NV_CRTC_HEAD_CONFIG);
1388            state->crtcOwner = nvReadVGA(pNv, 0x44);
1389         }
1390         state->extra = nvReadVGA(pNv, 0x41);
1391
1392         state->cursorConfig = nvReadCurCRTC(pNv, NV_CRTC_CURSOR_CONFIG);
1393
1394         if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
1395            state->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_DITHER_NV11);
1396         } else 
1397         if(pNv->twoHeads) {
1398             state->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_DITHER);
1399         }
1400
1401         if(pNv->FlatPanel) {
1402            state->timingH = nvReadVGA(pNv, 0x53);
1403            state->timingV = nvReadVGA(pNv, 0x54);
1404         }
1405     }
1406
1407     if(pNv->FlatPanel) {
1408        state->crtcSync = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_HCRTC);
1409     }
1410 }
1411
1412 void NVSetStartAddress (
1413     NVPtr   pNv,
1414     CARD32 start
1415 )
1416 {
1417     nvWriteCurCRTC(pNv, NV_CRTC_START, start);
1418 }
1419
1420