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