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