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