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