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