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