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