Don't speculate on the unknown limit field, and call the others log2p, not p
[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 NVReadVGA0(NVPtr pNv, uint8_t index)
46 {
47         volatile const uint8_t *ptr = pNv->PCIO0;
48         VGA_WR08(ptr, 0x03D4, index);
49         return VGA_RD08(ptr, 0x03D5);
50 }
51
52 void NVWriteVGA0(NVPtr pNv, uint8_t index, uint8_t data)
53 {
54         volatile const uint8_t *ptr = pNv->PCIO0;
55         VGA_WR08(ptr, 0x03D4, index);
56         VGA_WR08(ptr, 0x03D5, data);
57 }
58
59 uint8_t NVReadVGA1(NVPtr pNv, uint8_t index)
60 {
61         volatile const uint8_t *ptr = pNv->PCIO1;
62         VGA_WR08(ptr, 0x03D4, index);
63         return VGA_RD08(ptr, 0x03D5);
64 }
65
66 void NVWriteVGA1(NVPtr pNv, uint8_t index, uint8_t data)
67 {
68         volatile const uint8_t *ptr = pNv->PCIO1;
69         VGA_WR08(ptr, 0x03D4, index);
70         VGA_WR08(ptr, 0x03D5, data);
71 }
72
73 uint8_t nvReadVGA(NVPtr pNv, uint8_t index)
74 {
75   volatile const uint8_t *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
76   VGA_WR08(ptr, 0x03D4, index);
77   return VGA_RD08(ptr, 0x03D5);
78 }
79
80 void nvWriteVGA(NVPtr pNv, uint8_t index, uint8_t data)
81 {
82   volatile const uint8_t *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
83 #ifdef NOUVEAU_MODESET_TRACE
84   ErrorF("nvWriteVGA: idx 0x%X data 0x%x\n", index, data);
85 #endif
86   VGA_WR08(ptr, 0x03D4, index);
87   VGA_WR08(ptr, 0x03D5, data);
88 }
89
90 CARD32 nvReadRAMDAC(NVPtr pNv, uint8_t head, uint32_t ramdac_reg)
91 {
92         volatile const void *ptr = head ? pNv->PRAMDAC1 : pNv->PRAMDAC0;
93         return MMIO_IN32(ptr, ramdac_reg);
94 }
95
96 void nvWriteRAMDAC(NVPtr pNv, uint8_t head, uint32_t ramdac_reg, CARD32 val)
97 {
98 #ifdef NOUVEAU_MODESET_TRACE
99     ErrorF("nvWriteRAMDAC, head %x, reg 0x%x val %#x\n", head, ramdac_reg, val);
100 #endif
101         volatile const void *ptr = head ? pNv->PRAMDAC1 : pNv->PRAMDAC0;
102         MMIO_OUT32(ptr, ramdac_reg, val);
103 }
104
105 CARD32 nvReadCRTC(NVPtr pNv, uint8_t head, uint32_t reg)
106 {
107   volatile const void *ptr = head ? pNv->PCRTC1 : pNv->PCRTC0;
108   return MMIO_IN32(ptr, reg);
109 }
110
111 void nvWriteCRTC(NVPtr pNv, uint8_t head, uint32_t reg, CARD32 val)
112 {
113 #ifdef NOUVEAU_MODESET_TRACE
114   ErrorF("nvWriteCRTC head %d, reg 0x%x val %#x\n", head, reg, val);
115 #endif
116   volatile const void *ptr = head ? pNv->PCRTC1 : pNv->PCRTC0;
117   MMIO_OUT32(ptr, reg, val);
118 }
119
120 void NVLockUnlock (
121     NVPtr pNv,
122     Bool  Lock
123 )
124 {
125     CARD8 cr11;
126
127     nvWriteVGA(pNv, NV_VGA_CRTCX_LOCK, Lock ? 0x99 : 0x57 );
128
129     cr11 = nvReadVGA(pNv, NV_VGA_CRTCX_VSYNCE);
130     if(Lock) cr11 |= 0x80;
131     else cr11 &= ~0x80;
132     nvWriteVGA(pNv, NV_VGA_CRTCX_VSYNCE, cr11);
133 }
134
135 int NVShowHideCursor (
136     NVPtr pNv,
137     int   ShowHide
138 )
139 {
140     int current = pNv->CurrentState->cursor1;
141
142     pNv->CurrentState->cursor1 = (pNv->CurrentState->cursor1 & 0xFE) |
143                                  (ShowHide & 0x01);
144
145     nvWriteVGA(pNv, NV_VGA_CRTCX_CURCTL1, pNv->CurrentState->cursor1);
146
147     if(pNv->Architecture == NV_ARCH_40) {  /* HW bug */
148        volatile CARD32 curpos = nvReadCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS);
149        nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, curpos);
150     }
151
152     return (current & 0x01);
153 }
154
155 /****************************************************************************\
156 *                                                                            *
157 * The video arbitration routines calculate some "magic" numbers.  Fixes      *
158 * the snow seen when accessing the framebuffer without it.                   *
159 * It just works (I hope).                                                    *
160 *                                                                            *
161 \****************************************************************************/
162
163 typedef struct {
164   int graphics_lwm;
165   int video_lwm;
166   int graphics_burst_size;
167   int video_burst_size;
168   int valid;
169 } nv4_fifo_info;
170
171 typedef struct {
172   int pclk_khz;
173   int mclk_khz;
174   int nvclk_khz;
175   char mem_page_miss;
176   char mem_latency;
177   int memory_width;
178   char enable_video;
179   char gr_during_vid;
180   char pix_bpp;
181   char mem_aligned;
182   char enable_mp;
183 } nv4_sim_state;
184
185 typedef struct {
186   int graphics_lwm;
187   int video_lwm;
188   int graphics_burst_size;
189   int video_burst_size;
190   int valid;
191 } nv10_fifo_info;
192
193 typedef struct {
194   uint32_t pclk_khz;
195   uint32_t mclk_khz;
196   uint32_t nvclk_khz;
197   uint8_t mem_page_miss;
198   uint8_t mem_latency;
199   uint32_t memory_type;
200   uint32_t memory_width;
201   uint8_t enable_video;
202   uint8_t gr_during_vid;
203   uint8_t pix_bpp;
204   uint8_t mem_aligned;
205   uint8_t enable_mp;
206 } nv10_sim_state;
207
208
209 static void nvGetClocks(NVPtr pNv, unsigned int *MClk, unsigned int *NVClk)
210 {
211         unsigned int pll, N, M, MB, NB, P;
212
213     if(pNv->Architecture >= NV_ARCH_40) {
214         Bool VCO2_off = FALSE;
215        pll = nvReadMC(pNv, 0x4020);
216        P = (pll >> 16) & 0x07;
217         /* There seem to be 2 (redundant?) switches to turn VCO2 off. */
218         if (pll & (1 << 8))
219                 VCO2_off = TRUE;
220         if (!(pll & (1 << 30))) 
221                 VCO2_off = TRUE;
222        pll = nvReadMC(pNv, 0x4024);
223        M = pll & 0xFF;
224        N = (pll >> 8) & 0xFF;
225         if (VCO2_off) {
226                 MB = 1;
227                 NB = 1;
228         } else {
229                 MB = (pll >> 16) & 0xFF;
230                 NB = (pll >> 24) & 0xFF;
231         }
232         if (!MB || !NB) {
233                 ErrorF("Something wrong with MPLL VCO2 settings, ignoring VCO2.\n");
234                 MB = 1;
235                 NB = 1;
236         }
237
238        *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
239
240         VCO2_off = FALSE; /* reset */
241
242        pll = nvReadMC(pNv, 0x4000);
243        P = (pll >> 16) & 0x07;
244         /* There seem to be 2 (redundant?) switches to turn VCO2 off. */
245         if (pll & (1 << 8))
246                 VCO2_off = TRUE;
247         if (!(pll & (1 << 30))) 
248                 VCO2_off = TRUE;
249        pll = nvReadMC(pNv, 0x4004);
250        M = pll & 0xFF;
251        N = (pll >> 8) & 0xFF;
252         if (VCO2_off) {
253                 MB = 1;
254                 NB = 1;
255         } else {
256                 MB = (pll >> 16) & 0xFF;
257                 NB = (pll >> 24) & 0xFF;
258         }
259         if (!MB || !NB) {
260                 ErrorF("Something wrong with NVPLL VCO2 settings, ignoring VCO2\n");
261                 MB = 1;
262                 NB = 1;
263         }
264
265        *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
266     } else
267     if(pNv->twoStagePLL) {
268        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_MPLL);
269        M = pll & 0xFF;
270        N = (pll >> 8) & 0xFF; 
271        P = (pll >> 16) & 0x0F;
272        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_MPLL_B);
273        if(pll & 0x80000000) {
274            MB = pll & 0xFF; 
275            NB = (pll >> 8) & 0xFF;
276        } else {
277            MB = 1;
278            NB = 1;
279        }
280        *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
281
282        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL);
283        M = pll & 0xFF; 
284        N = (pll >> 8) & 0xFF; 
285        P = (pll >> 16) & 0x0F;
286        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL_B);
287        if(pll & 0x80000000) {
288            MB = pll & 0xFF;
289            NB = (pll >> 8) & 0xFF;
290        } else {
291            MB = 1;
292            NB = 1;
293        }
294        *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
295     } else 
296     if(((pNv->Chipset & 0x0ff0) == CHIPSET_NV30) ||
297        ((pNv->Chipset & 0x0ff0) == CHIPSET_NV35))
298     {
299        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_MPLL);
300        M = pll & 0x0F; 
301        N = (pll >> 8) & 0xFF;
302        P = (pll >> 16) & 0x07;
303        if(pll & 0x00000080) {
304            MB = (pll >> 4) & 0x07;     
305            NB = (pll >> 19) & 0x1f;
306        } else {
307            MB = 1;
308            NB = 1;
309        }
310        *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
311
312        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL);
313        M = pll & 0x0F;
314        N = (pll >> 8) & 0xFF;
315        P = (pll >> 16) & 0x07;
316        if(pll & 0x00000080) {
317            MB = (pll >> 4) & 0x07;
318            NB = (pll >> 19) & 0x1f;
319        } else {
320            MB = 1;
321            NB = 1;
322        }
323        *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
324     } else {
325        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_MPLL);
326        M = pll & 0xFF; 
327        N = (pll >> 8) & 0xFF; 
328        P = (pll >> 16) & 0x0F;
329        *MClk = (N * pNv->CrystalFreqKHz / M) >> P;
330
331        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL);
332        M = pll & 0xFF; 
333        N = (pll >> 8) & 0xFF; 
334        P = (pll >> 16) & 0x0F;
335        *NVClk = (N * pNv->CrystalFreqKHz / M) >> P;
336     }
337
338 #if 0
339     ErrorF("NVClock = %i MHz, MEMClock = %i MHz\n", *NVClk/1000, *MClk/1000);
340 #endif
341 }
342
343
344 void nv4CalcArbitration (
345     nv4_fifo_info *fifo,
346     nv4_sim_state *arb
347 )
348 {
349     int data, pagemiss, cas,width, video_enable, bpp;
350     int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
351     int found, mclk_extra, mclk_loop, cbs, m1, p1;
352     int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
353     int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
354     int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm;
355
356     fifo->valid = 1;
357     pclk_freq = arb->pclk_khz;
358     mclk_freq = arb->mclk_khz;
359     nvclk_freq = arb->nvclk_khz;
360     pagemiss = arb->mem_page_miss;
361     cas = arb->mem_latency;
362     width = arb->memory_width >> 6;
363     video_enable = arb->enable_video;
364     bpp = arb->pix_bpp;
365     mp_enable = arb->enable_mp;
366     clwm = 0;
367     vlwm = 0;
368     cbs = 128;
369     pclks = 2;
370     nvclks = 2;
371     nvclks += 2;
372     nvclks += 1;
373     mclks = 5;
374     mclks += 3;
375     mclks += 1;
376     mclks += cas;
377     mclks += 1;
378     mclks += 1;
379     mclks += 1;
380     mclks += 1;
381     mclk_extra = 3;
382     nvclks += 2;
383     nvclks += 1;
384     nvclks += 1;
385     nvclks += 1;
386     if (mp_enable)
387         mclks+=4;
388     nvclks += 0;
389     pclks += 0;
390     found = 0;
391     vbs = 0;
392     while (found != 1)
393     {
394         fifo->valid = 1;
395         found = 1;
396         mclk_loop = mclks+mclk_extra;
397         us_m = mclk_loop *1000*1000 / mclk_freq;
398         us_n = nvclks*1000*1000 / nvclk_freq;
399         us_p = nvclks*1000*1000 / pclk_freq;
400         if (video_enable)
401         {
402             video_drain_rate = pclk_freq * 2;
403             crtc_drain_rate = pclk_freq * bpp/8;
404             vpagemiss = 2;
405             vpagemiss += 1;
406             crtpagemiss = 2;
407             vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
408             if (nvclk_freq * 2 > mclk_freq * width)
409                 video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ;
410             else
411                 video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq;
412             us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
413             vlwm = us_video * video_drain_rate/(1000*1000);
414             vlwm++;
415             vbs = 128;
416             if (vlwm > 128) vbs = 64;
417             if (vlwm > (256-64)) vbs = 32;
418             if (nvclk_freq * 2 > mclk_freq * width)
419                 video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ;
420             else
421                 video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq;
422             cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
423             us_crt =
424             us_video
425             +video_fill_us
426             +cpm_us
427             +us_m + us_n +us_p
428             ;
429             clwm = us_crt * crtc_drain_rate/(1000*1000);
430             clwm++;
431         }
432         else
433         {
434             crtc_drain_rate = pclk_freq * bpp/8;
435             crtpagemiss = 2;
436             crtpagemiss += 1;
437             cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
438             us_crt =  cpm_us + us_m + us_n + us_p ;
439             clwm = us_crt * crtc_drain_rate/(1000*1000);
440             clwm++;
441         }
442         m1 = clwm + cbs - 512;
443         p1 = m1 * pclk_freq / mclk_freq;
444         p1 = p1 * bpp / 8;
445         if ((p1 < m1) && (m1 > 0))
446         {
447             fifo->valid = 0;
448             found = 0;
449             if (mclk_extra ==0)   found = 1;
450             mclk_extra--;
451         }
452         else if (video_enable)
453         {
454             if ((clwm > 511) || (vlwm > 255))
455             {
456                 fifo->valid = 0;
457                 found = 0;
458                 if (mclk_extra ==0)   found = 1;
459                 mclk_extra--;
460             }
461         }
462         else
463         {
464             if (clwm > 519)
465             {
466                 fifo->valid = 0;
467                 found = 0;
468                 if (mclk_extra ==0)   found = 1;
469                 mclk_extra--;
470             }
471         }
472         if (clwm < 384) clwm = 384;
473         if (vlwm < 128) vlwm = 128;
474         data = (int)(clwm);
475         fifo->graphics_lwm = data;
476         fifo->graphics_burst_size = 128;
477         data = (int)((vlwm+15));
478         fifo->video_lwm = data;
479         fifo->video_burst_size = vbs;
480     }
481 }
482
483 void nv4UpdateArbitrationSettings (
484     unsigned      VClk, 
485     unsigned      pixelDepth, 
486     unsigned     *burst,
487     unsigned     *lwm,
488     NVPtr        pNv
489 )
490 {
491     nv4_fifo_info fifo_data;
492     nv4_sim_state sim_data;
493     unsigned int MClk, NVClk, cfg1;
494
495     nvGetClocks(pNv, &MClk, &NVClk);
496
497     cfg1 = nvReadFB(pNv, NV_PFB_CFG1);
498     sim_data.pix_bpp        = (char)pixelDepth;
499     sim_data.enable_video   = 0;
500     sim_data.enable_mp      = 0;
501     sim_data.memory_width   = (nvReadEXTDEV(pNv, 0x0000) & 0x10) ? 128 : 64;
502     sim_data.mem_latency    = (char)cfg1 & 0x0F;
503     sim_data.mem_aligned    = 1;
504     sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
505     sim_data.gr_during_vid  = 0;
506     sim_data.pclk_khz       = VClk;
507     sim_data.mclk_khz       = MClk;
508     sim_data.nvclk_khz      = NVClk;
509     nv4CalcArbitration(&fifo_data, &sim_data);
510     if (fifo_data.valid)
511     {
512         int  b = fifo_data.graphics_burst_size >> 4;
513         *burst = 0;
514         while (b >>= 1) (*burst)++;
515         *lwm   = fifo_data.graphics_lwm >> 3;
516     }
517 }
518
519 void nv10CalcArbitration (
520     nv10_fifo_info *fifo,
521     nv10_sim_state *arb
522 )
523 {
524     int data, pagemiss, width, video_enable, bpp;
525     int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
526     int nvclk_fill;
527     int found, mclk_extra, mclk_loop, cbs, m1;
528     int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
529     int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
530     int vus_m;
531     int vpm_us, us_video, cpm_us, us_crt,clwm;
532     int clwm_rnd_down;
533     int m2us, us_pipe_min, p1clk, p2;
534     int min_mclk_extra;
535     int us_min_mclk_extra;
536
537     fifo->valid = 1;
538     pclk_freq = arb->pclk_khz; /* freq in KHz */
539     mclk_freq = arb->mclk_khz;
540     nvclk_freq = arb->nvclk_khz;
541     pagemiss = arb->mem_page_miss;
542     width = arb->memory_width/64;
543     video_enable = arb->enable_video;
544     bpp = arb->pix_bpp;
545     mp_enable = arb->enable_mp;
546     clwm = 0;
547
548     cbs = 512;
549
550     pclks = 4; /* lwm detect. */
551
552     nvclks = 3; /* lwm -> sync. */
553     nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
554
555     mclks  = 1;   /* 2 edge sync.  may be very close to edge so just put one. */
556
557     mclks += 1;   /* arb_hp_req */
558     mclks += 5;   /* ap_hp_req   tiling pipeline */
559
560     mclks += 2;    /* tc_req     latency fifo */
561     mclks += 2;    /* fb_cas_n_  memory request to fbio block */
562     mclks += 7;    /* sm_d_rdv   data returned from fbio block */
563
564     /* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
565     if (arb->memory_type == 0)
566       if (arb->memory_width == 64) /* 64 bit bus */
567         mclks += 4;
568       else
569         mclks += 2;
570     else
571       if (arb->memory_width == 64) /* 64 bit bus */
572         mclks += 2;
573       else
574         mclks += 1;
575
576     if ((!video_enable) && (arb->memory_width == 128))
577     {  
578       mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
579       min_mclk_extra = 17;
580     }
581     else
582     {
583       mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
584       /* mclk_extra = 4; */ /* Margin of error */
585       min_mclk_extra = 18;
586     }
587
588     nvclks += 1; /* 2 edge sync.  may be very close to edge so just put one. */
589     nvclks += 1; /* fbi_d_rdv_n */
590     nvclks += 1; /* Fbi_d_rdata */
591     nvclks += 1; /* crtfifo load */
592
593     if(mp_enable)
594       mclks+=4; /* Mp can get in with a burst of 8. */
595     /* Extra clocks determined by heuristics */
596
597     nvclks += 0;
598     pclks += 0;
599     found = 0;
600     while(found != 1) {
601       fifo->valid = 1;
602       found = 1;
603       mclk_loop = mclks+mclk_extra;
604       us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
605       us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
606       us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
607       us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
608       us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
609       us_pipe_min = us_m_min + us_n + us_p;
610
611       vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
612
613       if(video_enable) {
614         crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
615
616         vpagemiss = 1; /* self generating page miss */
617         vpagemiss += 1; /* One higher priority before */
618
619         crtpagemiss = 2; /* self generating page miss */
620         if(mp_enable)
621             crtpagemiss += 1; /* if MA0 conflict */
622
623         vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
624
625         us_video = vpm_us + vus_m; /* Video has separate read return path */
626
627         cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
628         us_crt =
629           us_video  /* Wait for video */
630           +cpm_us /* CRT Page miss */
631           +us_m + us_n +us_p /* other latency */
632           ;
633
634         clwm = us_crt * crtc_drain_rate/(1000*1000);
635         clwm++; /* fixed point <= float_point - 1.  Fixes that */
636       } else {
637         crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
638
639         crtpagemiss = 1; /* self generating page miss */
640         crtpagemiss += 1; /* MA0 page miss */
641         if(mp_enable)
642             crtpagemiss += 1; /* if MA0 conflict */
643         cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
644         us_crt =  cpm_us + us_m + us_n + us_p ;
645         clwm = us_crt * crtc_drain_rate/(1000*1000);
646         clwm++; /* fixed point <= float_point - 1.  Fixes that */
647
648           /* Finally, a heuristic check when width == 64 bits */
649           if(width == 1){
650               nvclk_fill = nvclk_freq * 8;
651               if(crtc_drain_rate * 100 >= nvclk_fill * 102)
652                       clwm = 0xfff; /*Large number to fail */
653
654               else if(crtc_drain_rate * 100  >= nvclk_fill * 98) {
655                   clwm = 1024;
656                   cbs = 512;
657               }
658           }
659       }
660
661
662       /*
663         Overfill check:
664
665         */
666
667       clwm_rnd_down = ((int)clwm/8)*8;
668       if (clwm_rnd_down < clwm)
669           clwm += 8;
670
671       m1 = clwm + cbs -  1024; /* Amount of overfill */
672       m2us = us_pipe_min + us_min_mclk_extra;
673
674       /* pclk cycles to drain */
675       p1clk = m2us * pclk_freq/(1000*1000); 
676       p2 = p1clk * bpp / 8; /* bytes drained. */
677
678       if((p2 < m1) && (m1 > 0)) {
679           fifo->valid = 0;
680           found = 0;
681           if(min_mclk_extra == 0)   {
682             if(cbs <= 32) {
683               found = 1; /* Can't adjust anymore! */
684             } else {
685               cbs = cbs/2;  /* reduce the burst size */
686             }
687           } else {
688             min_mclk_extra--;
689           }
690       } else {
691         if (clwm > 1023){ /* Have some margin */
692           fifo->valid = 0;
693           found = 0;
694           if(min_mclk_extra == 0)   
695               found = 1; /* Can't adjust anymore! */
696           else 
697               min_mclk_extra--;
698         }
699       }
700
701       if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
702       data = (int)(clwm);
703       /*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
704       fifo->graphics_lwm = data;   fifo->graphics_burst_size = cbs;
705
706       fifo->video_lwm = 1024;  fifo->video_burst_size = 512;
707     }
708 }
709
710 void nv10UpdateArbitrationSettings (
711     unsigned      VClk, 
712     unsigned      pixelDepth, 
713     unsigned     *burst,
714     unsigned     *lwm,
715     NVPtr        pNv
716 )
717 {
718     nv10_fifo_info fifo_data;
719     nv10_sim_state sim_data;
720     unsigned int MClk, NVClk, cfg1;
721
722     nvGetClocks(pNv, &MClk, &NVClk);
723
724     cfg1 = nvReadFB(pNv, NV_PFB_CFG1);
725     sim_data.pix_bpp        = (char)pixelDepth;
726     sim_data.enable_video   = 1;
727     sim_data.enable_mp      = 0;
728     sim_data.memory_type    = (nvReadFB(pNv, NV_PFB_CFG0) & 0x01) ? 1 : 0;
729     sim_data.memory_width   = (nvReadEXTDEV(pNv, 0x0000) & 0x10) ? 128 : 64;
730     sim_data.mem_latency    = (char)cfg1 & 0x0F;
731     sim_data.mem_aligned    = 1;
732     sim_data.mem_page_miss  = (char)(((cfg1>>4) &0x0F) + ((cfg1>>31) & 0x01));
733     sim_data.gr_during_vid  = 0;
734     sim_data.pclk_khz       = VClk;
735     sim_data.mclk_khz       = MClk;
736     sim_data.nvclk_khz      = NVClk;
737     nv10CalcArbitration(&fifo_data, &sim_data);
738     if (fifo_data.valid) {
739         int  b = fifo_data.graphics_burst_size >> 4;
740         *burst = 0;
741         while (b >>= 1) (*burst)++;
742         *lwm   = fifo_data.graphics_lwm >> 3;
743     }
744 }
745
746
747 void nv30UpdateArbitrationSettings (NVPtr pNv,
748                                     unsigned     *burst,
749                                     unsigned     *lwm)   
750 {
751     unsigned int MClk, NVClk;
752     unsigned int fifo_size, burst_size, graphics_lwm;
753
754     fifo_size = 2048;
755     burst_size = 512;
756     graphics_lwm = fifo_size - burst_size;
757
758     nvGetClocks(pNv, &MClk, &NVClk);
759     
760     *burst = 0;
761     burst_size >>= 5;
762     while(burst_size >>= 1) (*burst)++;
763     *lwm = graphics_lwm >> 3;
764 }
765
766 #ifdef XSERVER_LIBPCIACCESS
767
768 struct pci_device GetDeviceByPCITAG(uint32_t bus, uint32_t dev, uint32_t func)
769 {
770         const struct pci_slot_match match[] = { {0, bus, dev, func, 0} };
771         struct pci_device_iterator *iterator;
772         struct pci_device *device;
773         
774         /* assume one device to exist */
775         iterator = pci_slot_match_iterator_create(match);
776         device = pci_device_next(iterator);
777
778         return *device;
779 }
780
781 #endif /* XSERVER_LIBPCIACCESS */
782
783 void nForceUpdateArbitrationSettings (unsigned VClk,
784                                       unsigned      pixelDepth,
785                                       unsigned     *burst,
786                                       unsigned     *lwm,
787                                       NVPtr        pNv
788 )
789 {
790     nv10_fifo_info fifo_data;
791     nv10_sim_state sim_data;
792     unsigned int M, N, P, pll, MClk, NVClk, memctrl;
793
794 #ifdef XSERVER_LIBPCIACCESS
795         struct pci_device tmp;
796 #endif /* XSERVER_LIBPCIACCESS */
797
798     if((pNv->Chipset & 0x0FF0) == CHIPSET_NFORCE) {
799        unsigned int uMClkPostDiv;
800
801 #ifdef XSERVER_LIBPCIACCESS
802         tmp = GetDeviceByPCITAG(0, 0, 3);
803         PCI_DEV_READ_LONG(&tmp, 0x6C, &(uMClkPostDiv));
804         uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
805 #else
806         uMClkPostDiv = (pciReadLong(pciTag(0, 0, 3), 0x6C) >> 8) & 0xf;
807 #endif /* XSERVER_LIBPCIACCESS */
808        if(!uMClkPostDiv) uMClkPostDiv = 4; 
809        MClk = 400000 / uMClkPostDiv;
810     } else {
811 #ifdef XSERVER_LIBPCIACCESS
812         tmp = GetDeviceByPCITAG(0, 0, 5);
813         PCI_DEV_READ_LONG(&tmp, 0x4C, &(MClk));
814         MClk /= 1000;
815 #else
816         MClk = pciReadLong(pciTag(0, 0, 5), 0x4C) / 1000;
817 #endif /* XSERVER_LIBPCIACCESS */
818     }
819
820     pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL);
821     M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
822     NVClk  = (N * pNv->CrystalFreqKHz / M) >> P;
823     sim_data.pix_bpp        = (char)pixelDepth;
824     sim_data.enable_video   = 0;
825     sim_data.enable_mp      = 0;
826 #ifdef XSERVER_LIBPCIACCESS
827         tmp = GetDeviceByPCITAG(0, 0, 1);
828         PCI_DEV_READ_LONG(&tmp, 0x7C, &(sim_data.memory_type));
829         sim_data.memory_type = (sim_data.memory_type >> 12) & 1;
830 #else
831         sim_data.memory_type = (pciReadLong(pciTag(0, 0, 1), 0x7C) >> 12) & 1;
832 #endif /* XSERVER_LIBPCIACCESS */
833     sim_data.memory_width   = 64;
834
835 #ifdef XSERVER_LIBPCIACCESS
836         /* This offset is 0, is this even usefull? */
837         tmp = GetDeviceByPCITAG(0, 0, 3);
838         PCI_DEV_READ_LONG(&tmp, 0x00, &(memctrl));
839         memctrl >>= 16;
840 #else
841         memctrl = pciReadLong(pciTag(0, 0, 3), 0x00) >> 16;
842 #endif /* XSERVER_LIBPCIACCESS */
843
844     if((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
845         uint32_t dimm[3];
846 #ifdef XSERVER_LIBPCIACCESS
847         tmp = GetDeviceByPCITAG(0, 0, 2);
848         PCI_DEV_READ_LONG(&tmp, 0x40, &(dimm[0]));
849         PCI_DEV_READ_LONG(&tmp, 0x44, &(dimm[1]));
850         PCI_DEV_READ_LONG(&tmp, 0x48, &(dimm[2]));
851         int i;
852         for (i = 0; i < 3; i++) {
853                 dimm[i] = (dimm[i] >> 8) & 0x4F;
854         }
855 #else
856         dimm[0] = (pciReadLong(pciTag(0, 0, 2), 0x40) >> 8) & 0x4F;
857         dimm[1] = (pciReadLong(pciTag(0, 0, 2), 0x44) >> 8) & 0x4F;
858         dimm[2] = (pciReadLong(pciTag(0, 0, 2), 0x48) >> 8) & 0x4F;
859 #endif
860
861         if((dimm[0] + dimm[1]) != dimm[2]) {
862              ErrorF("WARNING: "
863               "your nForce DIMMs are not arranged in optimal banks!\n");
864         } 
865     }
866
867     sim_data.mem_latency    = 3;
868     sim_data.mem_aligned    = 1;
869     sim_data.mem_page_miss  = 10;
870     sim_data.gr_during_vid  = 0;
871     sim_data.pclk_khz       = VClk;
872     sim_data.mclk_khz       = MClk;
873     sim_data.nvclk_khz      = NVClk;
874     nv10CalcArbitration(&fifo_data, &sim_data);
875     if (fifo_data.valid)
876     {
877         int  b = fifo_data.graphics_burst_size >> 4;
878         *burst = 0;
879         while (b >>= 1) (*burst)++;
880         *lwm   = fifo_data.graphics_lwm >> 3;
881     }
882 }
883
884
885 /****************************************************************************\
886 *                                                                            *
887 *                          RIVA Mode State Routines                          *
888 *                                                                            *
889 \****************************************************************************/
890
891 /*
892  * Calculate the Video Clock parameters for the PLL.
893  */
894 static void CalcVClock (
895     int           clockIn,
896     int          *clockOut,
897     CARD32         *pllOut,
898     NVPtr        pNv
899 )
900 {
901     unsigned lowM, highM;
902     unsigned DeltaNew, DeltaOld;
903     unsigned VClk, Freq;
904     unsigned M, N, P;
905     
906     DeltaOld = 0xFFFFFFFF;
907
908     VClk = (unsigned)clockIn;
909     
910     if (pNv->CrystalFreqKHz == 13500) {
911         lowM  = 7;
912         highM = 13;
913     } else {
914         lowM  = 8;
915         highM = 14;
916     }
917
918     for (P = 0; P <= 4; P++) {
919         Freq = VClk << P;
920         if ((Freq >= 128000) && (Freq <= 350000)) {
921             for (M = lowM; M <= highM; M++) {
922                 N = ((VClk << P) * M) / pNv->CrystalFreqKHz;
923                 if(N <= 255) {
924                     Freq = ((pNv->CrystalFreqKHz * N) / M) >> P;
925                     if (Freq > VClk)
926                         DeltaNew = Freq - VClk;
927                     else
928                         DeltaNew = VClk - Freq;
929                     if (DeltaNew < DeltaOld) {
930                         *pllOut   = (P << 16) | (N << 8) | M;
931                         *clockOut = Freq;
932                         DeltaOld  = DeltaNew;
933                     }
934                 }
935             }
936         }
937     }
938 }
939
940 static void CalcVClock2Stage (
941     int           clockIn,
942     int          *clockOut,
943     CARD32         *pllOut,
944     CARD32         *pllBOut,
945     NVPtr        pNv
946 )
947 {
948     unsigned DeltaNew, DeltaOld;
949     unsigned VClk, Freq;
950     unsigned M, N, P;
951
952     DeltaOld = 0xFFFFFFFF;
953
954     *pllBOut = 0x80000401;  /* fixed at x4 for now */
955
956     VClk = (unsigned)clockIn;
957
958     for (P = 0; P <= 6; P++) {
959         Freq = VClk << P;
960         if ((Freq >= 400000) && (Freq <= 1000000)) {
961             for (M = 1; M <= 13; M++) {
962                 N = ((VClk << P) * M) / (pNv->CrystalFreqKHz << 2);
963                 if((N >= 5) && (N <= 255)) {
964                     Freq = (((pNv->CrystalFreqKHz << 2) * N) / M) >> P;
965                     if (Freq > VClk)
966                         DeltaNew = Freq - VClk;
967                     else
968                         DeltaNew = VClk - Freq;
969                     if (DeltaNew < DeltaOld) {
970                         *pllOut   = (P << 16) | (N << 8) | M;
971                         *clockOut = Freq;
972                         DeltaOld  = DeltaNew;
973                     }
974                 }
975             }
976         }
977     }
978 }
979
980 /*
981  * Calculate extended mode parameters (SVGA) and save in a 
982  * mode state structure.
983  */
984 void NVCalcStateExt (
985     NVPtr pNv,
986     RIVA_HW_STATE *state,
987     int            bpp,
988     int            width,
989     int            hDisplaySize,
990     int            height,
991     int            dotClock,
992     int            flags 
993 )
994 {
995     int pixelDepth, VClk = 0;
996         CARD32 CursorStart;
997
998     /*
999      * Save mode parameters.
1000      */
1001     state->bpp    = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
1002     state->width  = width;
1003     state->height = height;
1004     /*
1005      * Extended RIVA registers.
1006      */
1007     pixelDepth = (bpp + 1)/8;
1008     if(pNv->twoStagePLL)
1009         CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, pNv);
1010     else
1011         CalcVClock(dotClock, &VClk, &state->pll, pNv);
1012
1013     switch (pNv->Architecture)
1014     {
1015         case NV_ARCH_04:
1016             nv4UpdateArbitrationSettings(VClk, 
1017                                          pixelDepth * 8, 
1018                                         &(state->arbitration0),
1019                                         &(state->arbitration1),
1020                                          pNv);
1021             state->cursor0  = 0x00;
1022             state->cursor1  = 0xbC;
1023             if (flags & V_DBLSCAN)
1024                 state->cursor1 |= 2;
1025             state->cursor2  = 0x00000000;
1026             state->pllsel   = 0x10000700;
1027             state->config   = 0x00001114;
1028             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
1029             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
1030             break;
1031         case NV_ARCH_10:
1032         case NV_ARCH_20:
1033         case NV_ARCH_30:
1034         default:
1035             if(((pNv->Chipset & 0xfff0) == CHIPSET_C51) ||
1036                ((pNv->Chipset & 0xfff0) == CHIPSET_C512))
1037             {
1038                 state->arbitration0 = 128; 
1039                 state->arbitration1 = 0x0480; 
1040             } else
1041             if(((pNv->Chipset & 0xffff) == CHIPSET_NFORCE) ||
1042                ((pNv->Chipset & 0xffff) == CHIPSET_NFORCE2))
1043             {
1044                 nForceUpdateArbitrationSettings(VClk,
1045                                           pixelDepth * 8,
1046                                          &(state->arbitration0),
1047                                          &(state->arbitration1),
1048                                           pNv);
1049             } else if(pNv->Architecture < NV_ARCH_30) {
1050                 nv10UpdateArbitrationSettings(VClk, 
1051                                           pixelDepth * 8, 
1052                                          &(state->arbitration0),
1053                                          &(state->arbitration1),
1054                                           pNv);
1055             } else {
1056                 nv30UpdateArbitrationSettings(pNv,
1057                                          &(state->arbitration0),
1058                                          &(state->arbitration1));
1059             }
1060             CursorStart = pNv->Cursor->offset;
1061             state->cursor0  = 0x80 | (CursorStart >> 17);
1062             state->cursor1  = (CursorStart >> 11) << 2;
1063             state->cursor2  = CursorStart >> 24;
1064             if (flags & V_DBLSCAN) 
1065                 state->cursor1 |= 2;
1066             state->pllsel   = 0x10000700;
1067             state->config   = nvReadFB(pNv, NV_PFB_CFG0);
1068             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
1069             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
1070             break;
1071     }
1072
1073     if(bpp != 8) /* DirectColor */
1074         state->general |= 0x00000030;
1075
1076     state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
1077     state->pixel    = (pixelDepth > 2) ? 3 : pixelDepth;
1078 }
1079
1080
1081 void NVLoadStateExt (
1082     ScrnInfoPtr pScrn,
1083     RIVA_HW_STATE *state
1084 )
1085 {
1086     NVPtr pNv = NVPTR(pScrn);
1087     CARD32 temp;
1088
1089     if(pNv->Architecture >= NV_ARCH_40) {
1090         switch(pNv->Chipset & 0xfff0) {
1091         case CHIPSET_NV44:
1092         case CHIPSET_NV44A:
1093         case CHIPSET_C51:
1094         case CHIPSET_G70:
1095         case CHIPSET_G71:
1096         case CHIPSET_G72:
1097         case CHIPSET_G73:
1098         case CHIPSET_C512:
1099              temp = nvReadCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL);
1100              nvWriteCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL, temp | 0x00100000);
1101              break;
1102         default:
1103              break;
1104         };
1105     }
1106
1107     if(pNv->Architecture >= NV_ARCH_10) {
1108         if(pNv->twoHeads) {
1109            nvWriteCRTC(pNv, 0, NV_CRTC_FSEL, state->head);
1110            nvWriteCRTC(pNv, 1, NV_CRTC_FSEL, state->head2);
1111         }
1112         temp = nvReadCurRAMDAC(pNv, NV_RAMDAC_NV10_CURSYNC);
1113         nvWriteCurRAMDAC(pNv, NV_RAMDAC_NV10_CURSYNC, temp | (1 << 25));
1114     
1115         nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
1116         nvWriteVIDEO(pNv, NV_PVIDEO_INTR_EN, 0);
1117         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(0), 0);
1118         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(1), 0);
1119         nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(0), pNv->VRAMPhysicalSize - 1);
1120         nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(1), pNv->VRAMPhysicalSize - 1);
1121         nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(0), pNv->VRAMPhysicalSize - 1);
1122         nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(1), pNv->VRAMPhysicalSize - 1);
1123         nvWriteMC(pNv, 0x1588, 0);
1124
1125         nvWriteCurCRTC(pNv, NV_CRTC_CURSOR_CONFIG, state->cursorConfig);
1126         nvWriteCurCRTC(pNv, NV_CRTC_0830, state->displayV - 3);
1127         nvWriteCurCRTC(pNv, NV_CRTC_0834, state->displayV - 1);
1128     
1129         if(pNv->FlatPanel) {
1130            if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
1131                nvWriteCurRAMDAC(pNv, NV_RAMDAC_DITHER_NV11, state->dither);
1132            } else 
1133            if(pNv->twoHeads) {
1134                nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_DITHER, state->dither);
1135            }
1136     
1137            nvWriteVGA(pNv, NV_VGA_CRTCX_FP_HTIMING, state->timingH);
1138            nvWriteVGA(pNv, NV_VGA_CRTCX_FP_VTIMING, state->timingV);
1139            nvWriteVGA(pNv, NV_VGA_CRTCX_BUFFER, 0xfa);
1140         }
1141
1142         nvWriteVGA(pNv, NV_VGA_CRTCX_EXTRA, state->extra);
1143     }
1144
1145     nvWriteVGA(pNv, NV_VGA_CRTCX_REPAINT0, state->repaint0);
1146     nvWriteVGA(pNv, NV_VGA_CRTCX_REPAINT1, state->repaint1);
1147     nvWriteVGA(pNv, NV_VGA_CRTCX_LSR, state->screen);
1148     nvWriteVGA(pNv, NV_VGA_CRTCX_PIXEL, state->pixel);
1149     nvWriteVGA(pNv, NV_VGA_CRTCX_HEB, state->horiz);
1150     nvWriteVGA(pNv, NV_VGA_CRTCX_FIFO1, state->fifo);
1151     nvWriteVGA(pNv, NV_VGA_CRTCX_FIFO0, state->arbitration0);
1152     nvWriteVGA(pNv, NV_VGA_CRTCX_FIFO_LWM, state->arbitration1);
1153     if(pNv->Architecture >= NV_ARCH_30) {
1154       nvWriteVGA(pNv, NV_VGA_CRTCX_FIFO_LWM_NV30, state->arbitration1 >> 8);
1155     }
1156
1157     nvWriteVGA(pNv, NV_VGA_CRTCX_CURCTL0, state->cursor0);
1158     nvWriteVGA(pNv, NV_VGA_CRTCX_CURCTL1, state->cursor1);
1159     if(pNv->Architecture == NV_ARCH_40) {  /* HW bug */
1160        volatile CARD32 curpos = nvReadCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS);
1161        nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, curpos);
1162     }
1163     nvWriteVGA(pNv, NV_VGA_CRTCX_CURCTL2, state->cursor2);
1164     nvWriteVGA(pNv, NV_VGA_CRTCX_INTERLACE, state->interlace);
1165
1166     if(!pNv->FlatPanel) {
1167        nvWriteRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT, state->pllsel);
1168        nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL, state->vpll);
1169        if(pNv->twoHeads)
1170           nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2, state->vpll2);
1171        if(pNv->twoStagePLL) {
1172           nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL_B, state->vpllB);
1173           nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2_B, state->vpll2B);
1174        }
1175     } else {
1176        nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL, state->scale);
1177        nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_HCRTC, state->crtcSync);
1178     }
1179     nvWriteCurRAMDAC(pNv, NV_RAMDAC_GENERAL_CONTROL, state->general);
1180
1181     nvWriteCurCRTC(pNv, NV_CRTC_INTR_EN_0, 0);
1182     nvWriteCurCRTC(pNv, NV_CRTC_INTR_0, NV_CRTC_INTR_VBLANK);
1183
1184     pNv->CurrentState = state;
1185 }
1186
1187 void NVUnloadStateExt
1188 (
1189     NVPtr pNv,
1190     RIVA_HW_STATE *state
1191 )
1192 {
1193     state->repaint0     = nvReadVGA(pNv, NV_VGA_CRTCX_REPAINT0);
1194     state->repaint1     = nvReadVGA(pNv, NV_VGA_CRTCX_REPAINT1);
1195     state->screen       = nvReadVGA(pNv, NV_VGA_CRTCX_LSR);
1196     state->pixel        = nvReadVGA(pNv, NV_VGA_CRTCX_PIXEL);
1197     state->horiz        = nvReadVGA(pNv, NV_VGA_CRTCX_HEB);
1198     state->fifo         = nvReadVGA(pNv, NV_VGA_CRTCX_FIFO1);
1199     state->arbitration0 = nvReadVGA(pNv, NV_VGA_CRTCX_FIFO0);
1200     state->arbitration1 = nvReadVGA(pNv, NV_VGA_CRTCX_FIFO_LWM);
1201     if(pNv->Architecture >= NV_ARCH_30) {
1202        state->arbitration1 |= (nvReadVGA(pNv, NV_VGA_CRTCX_FIFO_LWM_NV30) & 1) << 8;
1203     }
1204     state->cursor0      = nvReadVGA(pNv, NV_VGA_CRTCX_CURCTL0);
1205     state->cursor1      = nvReadVGA(pNv, NV_VGA_CRTCX_CURCTL1);
1206     state->cursor2      = nvReadVGA(pNv, NV_VGA_CRTCX_CURCTL2);
1207     state->interlace    = nvReadVGA(pNv, NV_VGA_CRTCX_INTERLACE);
1208
1209     state->vpll         = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL);
1210     if(pNv->twoHeads)
1211        state->vpll2     = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL2);
1212     if(pNv->twoStagePLL) {
1213         state->vpllB    = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL_B);
1214         state->vpll2B   = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL2_B);
1215     }
1216     state->pllsel       = nvReadRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT);
1217     state->general      = nvReadCurRAMDAC(pNv, NV_RAMDAC_GENERAL_CONTROL);
1218     state->scale        = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL);
1219     state->config       = nvReadFB(pNv, NV_PFB_CFG0);
1220
1221     if(pNv->Architecture >= NV_ARCH_10) {
1222         if(pNv->twoHeads) {
1223            state->head     = nvReadCRTC(pNv, 0, NV_CRTC_FSEL);
1224            state->head2    = nvReadCRTC(pNv, 1, NV_CRTC_FSEL);
1225            state->crtcOwner = nvReadVGA(pNv, NV_VGA_CRTCX_OWNER);
1226         }
1227         state->extra = nvReadVGA(pNv, NV_VGA_CRTCX_EXTRA);
1228
1229         state->cursorConfig = nvReadCurCRTC(pNv, NV_CRTC_CURSOR_CONFIG);
1230
1231         if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
1232            state->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_DITHER_NV11);
1233         } else 
1234         if(pNv->twoHeads) {
1235             state->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_DITHER);
1236         }
1237
1238         if(pNv->FlatPanel) {
1239            state->timingH = nvReadVGA(pNv, NV_VGA_CRTCX_FP_HTIMING);
1240            state->timingV = nvReadVGA(pNv, NV_VGA_CRTCX_FP_VTIMING);
1241         }
1242     }
1243
1244     if(pNv->FlatPanel) {
1245        state->crtcSync = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_HCRTC);
1246     }
1247 }
1248
1249 void NVSetStartAddress (
1250     NVPtr   pNv,
1251     CARD32 start
1252 )
1253 {
1254     nvWriteCurCRTC(pNv, NV_CRTC_START, start);
1255 }
1256
1257