Move cursor show/hide funcs to nv_hw, document nv40 bug, and set curctl2 before apply...
[nouveau] / src / nv_hw.c
1 /*
2  * Copyright 1993-2003 NVIDIA, Corporation
3  * Copyright 2008 Stuart Bennett
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23
24 #include "nv_include.h"
25
26 uint32_t NVRead(NVPtr pNv, uint32_t reg)
27 {
28         DDXMMIOW("NVRead: reg %08x val %08x\n", reg, (uint32_t)NV_RD32(pNv->REGS, reg));
29         return NV_RD32(pNv->REGS, reg);
30 }
31
32 void NVWrite(NVPtr pNv, uint32_t reg, uint32_t val)
33 {
34         DDXMMIOW("NVWrite: reg %08x val %08x\n", reg, NV_WR32(pNv->REGS, reg, val));
35 }
36
37 uint32_t NVReadCRTC(NVPtr pNv, int head, uint32_t reg)
38 {
39         if (head)
40                 reg += NV_PCRTC0_SIZE;
41         DDXMMIOH("NVReadCRTC: head %d reg %08x val %08x\n", head, reg, (uint32_t)NV_RD32(pNv->REGS, reg));
42         return NV_RD32(pNv->REGS, reg);
43 }
44
45 void NVWriteCRTC(NVPtr pNv, int head, uint32_t reg, uint32_t val)
46 {
47         if (head)
48                 reg += NV_PCRTC0_SIZE;
49         DDXMMIOH("NVWriteCRTC: head %d reg %08x val %08x\n", head, reg, val);
50         NV_WR32(pNv->REGS, reg, val);
51 }
52
53 uint32_t NVReadRAMDAC(NVPtr pNv, int head, uint32_t reg)
54 {
55         if (head)
56                 reg += NV_PRAMDAC0_SIZE;
57         DDXMMIOH("NVReadRamdac: head %d reg %08x val %08x\n", head, reg, (uint32_t)NV_RD32(pNv->REGS, reg));
58         return NV_RD32(pNv->REGS, reg);
59 }
60
61 void NVWriteRAMDAC(NVPtr pNv, int head, uint32_t reg, uint32_t val)
62 {
63         if (head)
64                 reg += NV_PRAMDAC0_SIZE;
65         DDXMMIOH("NVWriteRamdac: head %d reg %08x val %08x\n", head, reg, val);
66         NV_WR32(pNv->REGS, reg, val);
67 }
68
69 uint8_t nv_read_tmds(NVPtr pNv, int or, int dl, uint8_t address)
70 {
71         int ramdac = (or & OUTPUT_C) >> 2;
72
73         NVWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL + dl * 8,
74                       NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | address);
75         return NVReadRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA + dl * 8);
76 }
77
78 int nv_get_digital_bound_head(NVPtr pNv, int or)
79 {
80         /* special case of nv_read_tmds to find crtc associated with an output.
81          * this does not give a correct answer for off-chip dvi, but there's no
82          * use for such an answer anyway
83          */
84         int ramdac = (or & OUTPUT_C) >> 2;
85
86         NVWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL,
87                       NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | 0x4);
88         return (((NVReadRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA) & 0x8) >> 3) ^ ramdac);
89 }
90
91 void nv_write_tmds(NVPtr pNv, int or, int dl, uint8_t address, uint8_t data)
92 {
93         int ramdac = (or & OUTPUT_C) >> 2;
94
95         NVWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA + dl * 8, data);
96         NVWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL + dl * 8, address);
97 }
98
99 void NVWriteVgaCrtc(NVPtr pNv, int head, uint8_t index, uint8_t value)
100 {
101         uint32_t mmiobase = head ? NV_PCIO1_OFFSET : NV_PCIO0_OFFSET;
102
103         DDXMMIOH("NVWriteVgaCrtc: head %d index 0x%02x data 0x%02x\n", head, index, value);
104         NV_WR08(pNv->REGS, CRTC_INDEX_COLOR + mmiobase, index);
105         NV_WR08(pNv->REGS, CRTC_DATA_COLOR + mmiobase, value);
106 }
107
108 uint8_t NVReadVgaCrtc(NVPtr pNv, int head, uint8_t index)
109 {
110         uint32_t mmiobase = head ? NV_PCIO1_OFFSET : NV_PCIO0_OFFSET;
111
112         NV_WR08(pNv->REGS, CRTC_INDEX_COLOR + mmiobase, index);
113         DDXMMIOH("NVReadVgaCrtc: head %d index 0x%02x data 0x%02x\n", head, index, NV_RD08(pNv->REGS, CRTC_DATA_COLOR + mmiobase));
114         return NV_RD08(pNv->REGS, CRTC_DATA_COLOR + mmiobase);
115 }
116
117 /* CR57 and CR58 are a fun pair of regs. CR57 provides an index (0-0xf) for CR58
118  * I suspect they in fact do nothing, but are merely a way to carry useful
119  * per-head variables around
120  *
121  * Known uses:
122  * CR57         CR58
123  * 0x00         index to the appropriate dcb entry (or 7f for inactive)
124  * 0x02         dcb entry's "or" value (or 00 for inactive)
125  * 0x03         bit0 set for dual link (LVDS, possibly elsewhere too)
126  * 0x08 or 0x09 pxclk in MHz
127  * 0x0f         laptop panel info -     low nibble for PEXTDEV_BOOT_0 strap
128  *                                      high nibble for xlat strap value
129  */
130
131 void NVWriteVgaCrtc5758(NVPtr pNv, int head, uint8_t index, uint8_t value)
132 {
133         NVWriteVgaCrtc(pNv, head, 0x57, index);
134         NVWriteVgaCrtc(pNv, head, 0x58, value);
135 }
136
137 uint8_t NVReadVgaCrtc5758(NVPtr pNv, int head, uint8_t index)
138 {
139         NVWriteVgaCrtc(pNv, head, 0x57, index);
140         return NVReadVgaCrtc(pNv, head, 0x58);
141 }
142
143 uint8_t NVReadPVIO(NVPtr pNv, int head, uint16_t port)
144 {
145         /* Only NV4x have two pvio ranges */
146         uint32_t mmiobase = (head && pNv->Architecture == NV_ARCH_40) ? NV_PVIO1_OFFSET : NV_PVIO0_OFFSET;
147
148         DDXMMIOH("NVReadPVIO: head %d reg %08x val %02x\n", head, port + mmiobase, NV_RD08(pNv->REGS, port + mmiobase));
149         return NV_RD08(pNv->REGS, port + mmiobase);
150 }
151
152 void NVWritePVIO(NVPtr pNv, int head, uint16_t port, uint8_t value)
153 {
154         /* Only NV4x have two pvio ranges */
155         uint32_t mmiobase = (head && pNv->Architecture == NV_ARCH_40) ? NV_PVIO1_OFFSET : NV_PVIO0_OFFSET;
156
157         DDXMMIOH("NVWritePVIO: head %d reg %08x val %02x\n", head, port + mmiobase, value);
158         NV_WR08(pNv->REGS, port + mmiobase, value);
159 }
160
161 void NVWriteVgaSeq(NVPtr pNv, int head, uint8_t index, uint8_t value)
162 {
163         NVWritePVIO(pNv, head, VGA_SEQ_INDEX, index);
164         NVWritePVIO(pNv, head, VGA_SEQ_DATA, value);
165 }
166
167 uint8_t NVReadVgaSeq(NVPtr pNv, int head, uint8_t index)
168 {
169         NVWritePVIO(pNv, head, VGA_SEQ_INDEX, index);
170         return NVReadPVIO(pNv, head, VGA_SEQ_DATA);
171 }
172
173 void NVWriteVgaGr(NVPtr pNv, int head, uint8_t index, uint8_t value)
174 {
175         NVWritePVIO(pNv, head, VGA_GRAPH_INDEX, index);
176         NVWritePVIO(pNv, head, VGA_GRAPH_DATA, value);
177 }
178
179 uint8_t NVReadVgaGr(NVPtr pNv, int head, uint8_t index)
180 {
181         NVWritePVIO(pNv, head, VGA_GRAPH_INDEX, index);
182         return NVReadPVIO(pNv, head, VGA_GRAPH_DATA);
183 }
184
185 #define CRTC_IN_STAT_1 0x3da
186
187 void NVSetEnablePalette(NVPtr pNv, int head, bool enable)
188 {
189         uint32_t mmiobase = head ? NV_PCIO1_OFFSET : NV_PCIO0_OFFSET;
190
191         VGA_RD08(pNv->REGS, CRTC_IN_STAT_1 + mmiobase);
192         VGA_WR08(pNv->REGS, VGA_ATTR_INDEX + mmiobase, enable ? 0 : 0x20);
193 }
194
195 static bool NVGetEnablePalette(NVPtr pNv, int head)
196 {
197         uint32_t mmiobase = head ? NV_PCIO1_OFFSET : NV_PCIO0_OFFSET;
198
199         VGA_RD08(pNv->REGS, CRTC_IN_STAT_1 + mmiobase);
200         return !(VGA_RD08(pNv->REGS, VGA_ATTR_INDEX + mmiobase) & 0x20);
201 }
202
203 void NVWriteVgaAttr(NVPtr pNv, int head, uint8_t index, uint8_t value)
204 {
205         uint32_t mmiobase = head ? NV_PCIO1_OFFSET : NV_PCIO0_OFFSET;
206
207         if (NVGetEnablePalette(pNv, head))
208                 index &= ~0x20;
209         else
210                 index |= 0x20;
211
212         NV_RD08(pNv->REGS, CRTC_IN_STAT_1 + mmiobase);
213         DDXMMIOH("NVWriteVgaAttr: head %d index 0x%02x data 0x%02x\n", head, index, value);
214         NV_WR08(pNv->REGS, VGA_ATTR_INDEX + mmiobase, index);
215         NV_WR08(pNv->REGS, VGA_ATTR_DATA_W + mmiobase, value);
216 }
217
218 uint8_t NVReadVgaAttr(NVPtr pNv, int head, uint8_t index)
219 {
220         uint32_t mmiobase = head ? NV_PCIO1_OFFSET : NV_PCIO0_OFFSET;
221
222         if (NVGetEnablePalette(pNv, head))
223                 index &= ~0x20;
224         else
225                 index |= 0x20;
226
227         NV_RD08(pNv->REGS, CRTC_IN_STAT_1 + mmiobase);
228         NV_WR08(pNv->REGS, VGA_ATTR_INDEX + mmiobase, index);
229         DDXMMIOH("NVReadVgaAttr: head %d index 0x%02x data 0x%02x\n", head, index, NV_RD08(pNv->REGS, VGA_ATTR_DATA_R + mmiobase));
230         return NV_RD08(pNv->REGS, VGA_ATTR_DATA_R + mmiobase);
231 }
232
233 void NVVgaSeqReset(NVPtr pNv, int head, bool start)
234 {
235         NVWriteVgaSeq(pNv, head, 0x0, start ? 0x1 : 0x3);
236 }
237
238 void NVVgaProtect(NVPtr pNv, int head, bool protect)
239 {
240         uint8_t seq1 = NVReadVgaSeq(pNv, head, 0x1);
241
242         if (protect) {
243                 NVVgaSeqReset(pNv, head, true);
244                 NVWriteVgaSeq(pNv, head, 0x01, seq1 | 0x20);
245         } else {
246                 /* Reenable sequencer, then turn on screen */
247                 NVWriteVgaSeq(pNv, head, 0x01, seq1 & ~0x20);   /* reenable display */
248                 NVVgaSeqReset(pNv, head, false);
249         }
250         NVSetEnablePalette(pNv, head, protect);
251 }
252
253 void NVSetOwner(ScrnInfoPtr pScrn, int head)
254 {
255         NVPtr pNv = NVPTR(pScrn);
256         /* CRTCX_OWNER is always changed on CRTC0 */
257         NVWriteVgaCrtc(pNv, 0, NV_VGA_CRTCX_OWNER, head * 0x3);
258
259         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting owner: 0x%X.\n", head * 0x3);
260 }
261
262 void NVLockVgaCrtc(NVPtr pNv, int head, bool lock)
263 {
264         uint8_t cr11;
265
266         NVWriteVgaCrtc(pNv, head, NV_VGA_CRTCX_LOCK, lock ? 0x99 : 0x57);
267
268         cr11 = NVReadVgaCrtc(pNv, head, NV_VGA_CRTCX_VSYNCE);
269         if (lock)
270                 cr11 |= 0x80;
271         else
272                 cr11 &= ~0x80;
273         NVWriteVgaCrtc(pNv, head, NV_VGA_CRTCX_VSYNCE, cr11);
274 }
275
276 void NVBlankScreen(ScrnInfoPtr pScrn, int head, bool blank)
277 {
278         unsigned char seq1;
279         NVPtr pNv = NVPTR(pScrn);
280
281         if (pNv->twoHeads)
282                 NVSetOwner(pScrn, head);
283
284         seq1 = NVReadVgaSeq(pNv, head, 0x1);
285
286         NVVgaSeqReset(pNv, head, TRUE);
287         if (blank)
288                 NVWriteVgaSeq(pNv, head, 0x1, seq1 | 0x20);
289         else
290                 NVWriteVgaSeq(pNv, head, 0x1, seq1 & ~0x20);
291         NVVgaSeqReset(pNv, head, FALSE);
292 }
293
294 void nv_fix_nv40_hw_cursor(NVPtr pNv, int head)
295 {
296         /* on some nv40 (such as the "true" (in the NV_PFB_BOOT_0 sense) nv40,
297          * the gf6800gt) a hardware bug requires a write to PRAMDAC_CURSOR_POS
298          * for changes to the CRTC CURCTL regs to take effect, whether changing
299          * the pixmap location, or just showing/hiding the cursor
300          */
301         volatile uint32_t curpos = NVReadRAMDAC(pNv, head, NV_RAMDAC_CURSOR_POS);
302         NVWriteRAMDAC(pNv, head, NV_RAMDAC_CURSOR_POS, curpos);
303 }
304
305 void nv_show_cursor(NVPtr pNv, int head, bool show)
306 {
307         int curctl1 = NVReadVgaCrtc(pNv, head, NV_VGA_CRTCX_CURCTL1);
308
309         if (show)
310                 NVWriteVgaCrtc(pNv, head, NV_VGA_CRTCX_CURCTL1, curctl1 | 1);
311         else
312                 NVWriteVgaCrtc(pNv, head, NV_VGA_CRTCX_CURCTL1, curctl1 & ~1);
313
314         if (pNv->Architecture == NV_ARCH_40)
315                 nv_fix_nv40_hw_cursor(pNv, head);
316 }
317
318 int nv_decode_pll_highregs(NVPtr pNv, uint32_t pll1, uint32_t pll2, bool force_single, int refclk)
319 {
320         int M1, N1, M2 = 1, N2 = 1, log2P;
321
322         M1 = pll1 & 0xff;
323         N1 = (pll1 >> 8) & 0xff;
324         log2P = (pll1 >> 16) & 0x7; /* never more than 6, and nv30/35 only uses 3 bits */
325         if (pNv->twoStagePLL && pll2 & NV31_RAMDAC_ENABLE_VCO2 && !force_single) {
326                 M2 = pll2 & 0xff;
327                 N2 = (pll2 >> 8) & 0xff;
328         } else if (pNv->NVArch == 0x30 || pNv->NVArch == 0x35) {
329                 M1 &= 0xf; /* only 4 bits */
330                 if (pll1 & NV30_RAMDAC_ENABLE_VCO2) {
331                         M2 = (pll1 >> 4) & 0x7;
332                         N2 = ((pll2 >> 21) & 0x18) | ((pll2 >> 19) & 0x7);
333                 }
334         }
335
336         /* Avoid divide by zero if called at an inappropriate time */
337         if (!M1 || !M2)
338                 return 0;
339
340         return (N1 * N2 * refclk / (M1 * M2)) >> log2P;
341 }
342
343 static int nv_decode_pll_lowregs(uint32_t Pval, uint32_t NMNM, int refclk)
344 {
345         int M1, N1, M2 = 1, N2 = 1, log2P;
346
347         log2P = (Pval >> 16) & 0x7;
348
349         M1 = NMNM & 0xff;
350         N1 = (NMNM >> 8) & 0xff;
351         /* NVPLL and VPLLs use 1 << 8 to indicate single stage mode, MPLL uses 1 << 12 */
352         if (!(Pval & (1 << 8) || Pval & (1 << 12))) {
353                 M2 = (NMNM >> 16) & 0xff;
354                 N2 = (NMNM >> 24) & 0xff;
355         }
356
357         /* Avoid divide by zero if called at an inappropriate time */
358         if (!M1 || !M2)
359                 return 0;
360
361         return (N1 * N2 * refclk / (M1 * M2)) >> log2P;
362 }
363
364 static int nv_get_clock(ScrnInfoPtr pScrn, enum pll_types plltype)
365 {
366         NVPtr pNv = NVPTR(pScrn);
367         const uint32_t nv04_regs[MAX_PLL_TYPES] = { NV_RAMDAC_NVPLL, NV_RAMDAC_MPLL, NV_RAMDAC_VPLL, NV_RAMDAC_VPLL2 };
368         const uint32_t nv40_regs[MAX_PLL_TYPES] = { 0x4000, 0x4020, NV_RAMDAC_VPLL, NV_RAMDAC_VPLL2 };
369         uint32_t reg1;
370         struct pll_lims pll_lim;
371
372         if (plltype == MPLL && (pNv->Chipset & 0x0ff0) == CHIPSET_NFORCE) {
373                 uint32_t mpllP = (PCI_SLOT_READ_LONG(3, 0x6c) >> 8) & 0xf;
374
375                 if (!mpllP)
376                         mpllP = 4;
377                 return 400000 / mpllP;
378         } else if (plltype == MPLL && (pNv->Chipset & 0xff0) == CHIPSET_NFORCE2)
379                 return PCI_SLOT_READ_LONG(5, 0x4c) / 1000;
380
381         if (pNv->Architecture < NV_ARCH_40)
382                 reg1 = nv04_regs[plltype];
383         else
384                 reg1 = nv40_regs[plltype];
385
386         if (!get_pll_limits(pScrn, plltype, &pll_lim))
387                 return 0;
388
389         if (reg1 <= 0x405c)
390                 return nv_decode_pll_lowregs(nvReadMC(pNv, reg1), nvReadMC(pNv, reg1 + 4), pll_lim.refclk);
391         if (pNv->twoStagePLL) {
392                 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));
393
394                 return nv_decode_pll_highregs(pNv, nvReadMC(pNv, reg1), nvReadMC(pNv, reg1 + ((reg1 == NV_RAMDAC_VPLL2) ? 0x5c : 0x70)), nv40_single, pll_lim.refclk);
395         }
396         return nv_decode_pll_highregs(pNv, nvReadMC(pNv, reg1), 0, false, pll_lim.refclk);
397 }
398
399 /****************************************************************************\
400 *                                                                            *
401 * The video arbitration routines calculate some "magic" numbers.  Fixes      *
402 * the snow seen when accessing the framebuffer without it.                   *
403 * It just works (I hope).                                                    *
404 *                                                                            *
405 \****************************************************************************/
406
407 struct nv_fifo_info {
408         int graphics_lwm;
409         int video_lwm;
410         int graphics_burst_size;
411         int video_burst_size;
412         bool valid;
413 };
414
415 struct nv_sim_state {
416         int pclk_khz;
417         int mclk_khz;
418         int nvclk_khz;
419         int pix_bpp;
420         bool enable_mp;
421         bool enable_video;
422         int mem_page_miss;
423         int mem_latency;
424         int memory_type;
425         int memory_width;
426 };
427
428 static void nv4CalcArbitration(struct nv_fifo_info *fifo, struct nv_sim_state *arb)
429 {
430         int pagemiss, cas, width, video_enable, bpp;
431         int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
432         int found, mclk_extra, mclk_loop, cbs, m1, p1;
433         int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
434         int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
435         int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt, clwm;
436
437         pclk_freq = arb->pclk_khz;
438         mclk_freq = arb->mclk_khz;
439         nvclk_freq = arb->nvclk_khz;
440         pagemiss = arb->mem_page_miss;
441         cas = arb->mem_latency;
442         width = arb->memory_width >> 6;
443         video_enable = arb->enable_video;
444         bpp = arb->pix_bpp;
445         mp_enable = arb->enable_mp;
446         clwm = 0;
447         vlwm = 0;
448         cbs = 128;
449         pclks = 2;
450         nvclks = 2;
451         nvclks += 2;
452         nvclks += 1;
453         mclks = 5;
454         mclks += 3;
455         mclks += 1;
456         mclks += cas;
457         mclks += 1;
458         mclks += 1;
459         mclks += 1;
460         mclks += 1;
461         mclk_extra = 3;
462         nvclks += 2;
463         nvclks += 1;
464         nvclks += 1;
465         nvclks += 1;
466         if (mp_enable)
467                 mclks += 4;
468         nvclks += 0;
469         pclks += 0;
470         found = 0;
471         vbs = 0;
472         while (found != 1) {
473                 fifo->valid = true;
474                 found = 1;
475                 mclk_loop = mclks + mclk_extra;
476                 us_m = mclk_loop * 1000 * 1000 / mclk_freq;
477                 us_n = nvclks * 1000 * 1000 / nvclk_freq;
478                 us_p = nvclks * 1000 * 1000 / pclk_freq;
479                 if (video_enable) {
480                         video_drain_rate = pclk_freq * 2;
481                         crtc_drain_rate = pclk_freq * bpp / 8;
482                         vpagemiss = 2;
483                         vpagemiss += 1;
484                         crtpagemiss = 2;
485                         vpm_us = vpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
486                         if (nvclk_freq * 2 > mclk_freq * width)
487                                 video_fill_us = cbs * 1000 * 1000 / 16 / nvclk_freq;
488                         else
489                                 video_fill_us = cbs * 1000 * 1000 / (8 * width) / mclk_freq;
490                         us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
491                         vlwm = us_video * video_drain_rate / (1000 * 1000);
492                         vlwm++;
493                         vbs = 128;
494                         if (vlwm > 128)
495                                 vbs = 64;
496                         if (vlwm > (256 - 64))
497                                 vbs = 32;
498                         if (nvclk_freq * 2 > mclk_freq * width)
499                                 video_fill_us = vbs * 1000 * 1000 / 16 / nvclk_freq;
500                         else
501                                 video_fill_us = vbs * 1000 * 1000 / (8 * width) / mclk_freq;
502                         cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
503                         us_crt = us_video + video_fill_us + cpm_us + us_m + us_n + us_p;
504                         clwm = us_crt * crtc_drain_rate / (1000 * 1000);
505                         clwm++;
506                 } else {
507                         crtc_drain_rate = pclk_freq * bpp / 8;
508                         crtpagemiss = 2;
509                         crtpagemiss += 1;
510                         cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
511                         us_crt = cpm_us + us_m + us_n + us_p;
512                         clwm = us_crt * crtc_drain_rate / (1000 * 1000);
513                         clwm++;
514                 }
515                 m1 = clwm + cbs - 512;
516                 p1 = m1 * pclk_freq / mclk_freq;
517                 p1 = p1 * bpp / 8;
518                 if ((p1 < m1 && m1 > 0) ||
519                     (video_enable && (clwm > 511 || vlwm > 255)) ||
520                     (!video_enable && clwm > 519)) {
521                         fifo->valid = false;
522                         found = !mclk_extra;
523                         mclk_extra--;
524                 }
525                 if (clwm < 384)
526                         clwm = 384;
527                 if (vlwm < 128)
528                         vlwm = 128;
529                 fifo->graphics_lwm = clwm;
530                 fifo->graphics_burst_size = 128;
531                 fifo->video_lwm = vlwm + 15;
532                 fifo->video_burst_size = vbs;
533         }
534 }
535
536 static void nv10CalcArbitration(struct nv_fifo_info *fifo, struct nv_sim_state *arb)
537 {
538         int pagemiss, width, video_enable, bpp;
539         int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
540         int nvclk_fill;
541         int found, mclk_extra, mclk_loop, cbs, m1;
542         int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
543         int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
544         int vus_m;
545         int vpm_us, us_video, cpm_us, us_crt, clwm;
546         int clwm_rnd_down;
547         int m2us, us_pipe_min, p1clk, p2;
548         int min_mclk_extra;
549         int us_min_mclk_extra;
550
551         pclk_freq = arb->pclk_khz;      /* freq in KHz */
552         mclk_freq = arb->mclk_khz;
553         nvclk_freq = arb->nvclk_khz;
554         pagemiss = arb->mem_page_miss;
555         width = arb->memory_width / 64;
556         video_enable = arb->enable_video;
557         bpp = arb->pix_bpp;
558         mp_enable = arb->enable_mp;
559         clwm = 0;
560         cbs = 512;
561         pclks = 4;      /* lwm detect. */
562         nvclks = 3;     /* lwm -> sync. */
563         nvclks += 2;    /* fbi bus cycles (1 req + 1 busy) */
564         mclks = 1;      /* 2 edge sync.  may be very close to edge so just put one. */
565         mclks += 1;     /* arb_hp_req */
566         mclks += 5;     /* ap_hp_req   tiling pipeline */
567         mclks += 2;     /* tc_req     latency fifo */
568         mclks += 2;     /* fb_cas_n_  memory request to fbio block */
569         mclks += 7;     /* sm_d_rdv   data returned from fbio block */
570
571         /* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
572         if (arb->memory_type == 0) {
573                 if (arb->memory_width == 64)    /* 64 bit bus */
574                         mclks += 4;
575                 else
576                         mclks += 2;
577         } else if (arb->memory_width == 64)     /* 64 bit bus */
578                 mclks += 2;
579         else
580                 mclks += 1;
581
582         if (!video_enable && arb->memory_width == 128) {
583                 mclk_extra = (bpp == 32) ? 31 : 42;     /* Margin of error */
584                 min_mclk_extra = 17;
585         } else {
586                 mclk_extra = (bpp == 32) ? 8 : 4;       /* Margin of error */
587                 /* mclk_extra = 4; *//* Margin of error */
588                 min_mclk_extra = 18;
589         }
590
591         nvclks += 1;    /* 2 edge sync.  may be very close to edge so just put one. */
592         nvclks += 1;    /* fbi_d_rdv_n */
593         nvclks += 1;    /* Fbi_d_rdata */
594         nvclks += 1;    /* crtfifo load */
595
596         if (mp_enable)
597                 mclks += 4;     /* Mp can get in with a burst of 8. */
598         /* Extra clocks determined by heuristics */
599
600         nvclks += 0;
601         pclks += 0;
602         found = 0;
603         while (found != 1) {
604                 fifo->valid = true;
605                 found = 1;
606                 mclk_loop = mclks + mclk_extra;
607                 us_m = mclk_loop * 1000 * 1000 / mclk_freq;     /* Mclk latency in us */
608                 us_m_min = mclks * 1000 * 1000 / mclk_freq;     /* Minimum Mclk latency in us */
609                 us_min_mclk_extra = min_mclk_extra * 1000 * 1000 / mclk_freq;
610                 us_n = nvclks * 1000 * 1000 / nvclk_freq;       /* nvclk latency in us */
611                 us_p = pclks * 1000 * 1000 / pclk_freq; /* nvclk latency in us */
612                 us_pipe_min = us_m_min + us_n + us_p;
613
614                 vus_m = mclk_loop * 1000 * 1000 / mclk_freq;    /* Mclk latency in us */
615
616                 if (video_enable) {
617                         crtc_drain_rate = pclk_freq * bpp / 8;  /* MB/s */
618
619                         vpagemiss = 1;  /* self generating page miss */
620                         vpagemiss += 1; /* One higher priority before */
621
622                         crtpagemiss = 2;        /* self generating page miss */
623                         if (mp_enable)
624                                 crtpagemiss += 1;       /* if MA0 conflict */
625
626                         vpm_us = vpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
627
628                         us_video = vpm_us + vus_m;      /* Video has separate read return path */
629
630                         cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
631                         us_crt = us_video       /* Wait for video */
632                                  + cpm_us       /* CRT Page miss */
633                                  + us_m + us_n + us_p;  /* other latency */
634
635                         clwm = us_crt * crtc_drain_rate / (1000 * 1000);
636                         clwm++; /* fixed point <= float_point - 1.  Fixes that */
637                 } else {
638                         crtc_drain_rate = pclk_freq * bpp / 8;  /* bpp * pclk/8 */
639
640                         crtpagemiss = 1;        /* self generating page miss */
641                         crtpagemiss += 1;       /* MA0 page miss */
642                         if (mp_enable)
643                                 crtpagemiss += 1;       /* if MA0 conflict */
644                         cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
645                         us_crt = cpm_us + us_m + us_n + us_p;
646                         clwm = us_crt * crtc_drain_rate / (1000 * 1000);
647                         clwm++; /* fixed point <= float_point - 1.  Fixes that */
648
649                         /* Finally, a heuristic check when width == 64 bits */
650                         if (width == 1) {
651                                 nvclk_fill = nvclk_freq * 8;
652                                 if (crtc_drain_rate * 100 >= nvclk_fill * 102)
653                                         clwm = 0xfff;   /* Large number to fail */
654                                 else if (crtc_drain_rate * 100 >= nvclk_fill * 98) {
655                                         clwm = 1024;
656                                         cbs = 512;
657                                 }
658                         }
659                 }
660
661                 /*
662                  * Overfill check:
663                  */
664
665                 clwm_rnd_down = (clwm / 8) * 8;
666                 if (clwm_rnd_down < clwm)
667                         clwm += 8;
668
669                 m1 = clwm + cbs - 1024; /* Amount of overfill */
670                 m2us = us_pipe_min + us_min_mclk_extra;
671
672                 /* pclk cycles to drain */
673                 p1clk = m2us * pclk_freq / (1000 * 1000);
674                 p2 = p1clk * bpp / 8;   /* bytes drained. */
675
676                 if (p2 < m1 && m1 > 0) {
677                         fifo->valid = false;
678                         found = 0;
679                         if (min_mclk_extra == 0) {
680                                 if (cbs <= 32)
681                                         found = 1;      /* Can't adjust anymore! */
682                                 else
683                                         cbs = cbs / 2;  /* reduce the burst size */
684                         } else
685                                 min_mclk_extra--;
686                 } else if (clwm > 1023) {       /* Have some margin */
687                         fifo->valid = false;
688                         found = 0;
689                         if (min_mclk_extra == 0)
690                                 found = 1;      /* Can't adjust anymore! */
691                         else
692                                 min_mclk_extra--;
693                 }
694
695                 if (clwm < (1024 - cbs + 8))
696                         clwm = 1024 - cbs + 8;
697                 /*  printf("CRT LWM: prog: 0x%x, bs: 256\n", clwm); */
698                 fifo->graphics_lwm = clwm;
699                 fifo->graphics_burst_size = cbs;
700
701                 fifo->video_lwm = 1024;
702                 fifo->video_burst_size = 512;
703         }
704 }
705
706 void nv4_10UpdateArbitrationSettings(ScrnInfoPtr pScrn, int VClk, int bpp, uint8_t *burst, uint16_t *lwm)
707 {
708         NVPtr pNv = NVPTR(pScrn);
709         struct nv_fifo_info fifo_data;
710         struct nv_sim_state sim_data;
711         int MClk = nv_get_clock(pScrn, MPLL);
712         int NVClk = nv_get_clock(pScrn, NVPLL);
713         uint32_t cfg1 = nvReadFB(pNv, NV_PFB_CFG1);
714
715         sim_data.pclk_khz = VClk;
716         sim_data.mclk_khz = MClk;
717         sim_data.nvclk_khz = NVClk;
718         sim_data.pix_bpp = bpp;
719         sim_data.enable_mp = false;
720         if ((pNv->Chipset & 0xffff) == CHIPSET_NFORCE ||
721             (pNv->Chipset & 0xffff) == CHIPSET_NFORCE2) {
722                 sim_data.enable_video = false;
723                 sim_data.memory_type = (PCI_SLOT_READ_LONG(1, 0x7c) >> 12) & 1;
724                 sim_data.memory_width = 64;
725                 sim_data.mem_latency = 3;
726                 sim_data.mem_page_miss = 10;
727         } else {
728                 sim_data.enable_video = (pNv->Architecture != NV_ARCH_04);
729                 sim_data.memory_type = nvReadFB(pNv, NV_PFB_CFG0) & 0x1;
730                 sim_data.memory_width = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
731                 sim_data.mem_latency = cfg1 & 0xf;
732                 sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1);
733         }
734
735         if (pNv->Architecture == NV_ARCH_04)
736                 nv4CalcArbitration(&fifo_data, &sim_data);
737         else
738                 nv10CalcArbitration(&fifo_data, &sim_data);
739
740         if (fifo_data.valid) {
741                 int b = fifo_data.graphics_burst_size >> 4;
742                 *burst = 0;
743                 while (b >>= 1)
744                         (*burst)++;
745                 *lwm = fifo_data.graphics_lwm >> 3;
746         }
747 }
748
749 void nv30UpdateArbitrationSettings(uint8_t *burst, uint16_t *lwm)
750 {
751         unsigned int fifo_size, burst_size, graphics_lwm;
752
753         fifo_size = 2048;
754         burst_size = 512;
755         graphics_lwm = fifo_size - burst_size;
756
757         *burst = 0;
758         burst_size >>= 5;
759         while (burst_size >>= 1)
760                 (*burst)++;
761         *lwm = graphics_lwm >> 3;
762 }
763
764 /****************************************************************************\
765 *                                                                            *
766 *                          RIVA Mode State Routines                          *
767 *                                                                            *
768 \****************************************************************************/
769
770 /*
771  * Calculate the Video Clock parameters for the PLL.
772  */
773 static void CalcVClock (
774     int           clockIn,
775     int          *clockOut,
776     CARD32         *pllOut,
777     NVPtr        pNv
778 )
779 {
780     unsigned lowM, highM;
781     unsigned DeltaNew, DeltaOld;
782     unsigned VClk, Freq;
783     unsigned M, N, P;
784     
785     DeltaOld = 0xFFFFFFFF;
786
787     VClk = (unsigned)clockIn;
788     
789     if (pNv->CrystalFreqKHz == 13500) {
790         lowM  = 7;
791         highM = 13;
792     } else {
793         lowM  = 8;
794         highM = 14;
795     }
796
797     for (P = 0; P <= 4; P++) {
798         Freq = VClk << P;
799         if ((Freq >= 128000) && (Freq <= 350000)) {
800             for (M = lowM; M <= highM; M++) {
801                 N = ((VClk << P) * M) / pNv->CrystalFreqKHz;
802                 if(N <= 255) {
803                     Freq = ((pNv->CrystalFreqKHz * N) / M) >> P;
804                     if (Freq > VClk)
805                         DeltaNew = Freq - VClk;
806                     else
807                         DeltaNew = VClk - Freq;
808                     if (DeltaNew < DeltaOld) {
809                         *pllOut   = (P << 16) | (N << 8) | M;
810                         *clockOut = Freq;
811                         DeltaOld  = DeltaNew;
812                     }
813                 }
814             }
815         }
816     }
817 }
818
819 static void CalcVClock2Stage (
820     int           clockIn,
821     int          *clockOut,
822     CARD32         *pllOut,
823     CARD32         *pllBOut,
824     NVPtr        pNv
825 )
826 {
827     unsigned DeltaNew, DeltaOld;
828     unsigned VClk, Freq;
829     unsigned M, N, P;
830
831     DeltaOld = 0xFFFFFFFF;
832
833     *pllBOut = 0x80000401;  /* fixed at x4 for now */
834
835     VClk = (unsigned)clockIn;
836
837     for (P = 0; P <= 6; P++) {
838         Freq = VClk << P;
839         if ((Freq >= 400000) && (Freq <= 1000000)) {
840             for (M = 1; M <= 13; M++) {
841                 N = ((VClk << P) * M) / (pNv->CrystalFreqKHz << 2);
842                 if((N >= 5) && (N <= 255)) {
843                     Freq = (((pNv->CrystalFreqKHz << 2) * N) / M) >> P;
844                     if (Freq > VClk)
845                         DeltaNew = Freq - VClk;
846                     else
847                         DeltaNew = VClk - Freq;
848                     if (DeltaNew < DeltaOld) {
849                         *pllOut   = (P << 16) | (N << 8) | M;
850                         *clockOut = Freq;
851                         DeltaOld  = DeltaNew;
852                     }
853                 }
854             }
855         }
856     }
857 }
858
859 /*
860  * Calculate extended mode parameters (SVGA) and save in a 
861  * mode state structure.
862  */
863 void NVCalcStateExt (
864     ScrnInfoPtr pScrn,
865     RIVA_HW_STATE *state,
866     int            bpp,
867     int            width,
868     int            hDisplaySize,
869     int            height,
870     int            dotClock,
871     int            flags 
872 )
873 {
874         NVPtr pNv = NVPTR(pScrn);
875     int pixelDepth, VClk = 0;
876         CARD32 CursorStart;
877
878     /*
879      * Save mode parameters.
880      */
881     state->bpp    = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
882     state->width  = width;
883     state->height = height;
884     /*
885      * Extended RIVA registers.
886      */
887     pixelDepth = (bpp + 1)/8;
888     if(pNv->twoStagePLL)
889         CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, pNv);
890     else
891         CalcVClock(dotClock, &VClk, &state->pll, pNv);
892
893     switch (pNv->Architecture)
894     {
895         case NV_ARCH_04:
896             nv4_10UpdateArbitrationSettings(pScrn, VClk,
897                                          pixelDepth * 8, 
898                                         &(state->arbitration0),
899                                         &(state->arbitration1));
900             state->cursor0  = 0x00;
901             state->cursor1  = 0xbC;
902             if (flags & V_DBLSCAN)
903                 state->cursor1 |= 2;
904             state->cursor2  = 0x00000000;
905             state->pllsel   = 0x10000700;
906             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
907             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
908             break;
909         case NV_ARCH_10:
910         case NV_ARCH_20:
911         case NV_ARCH_30:
912         default:
913             if(((pNv->Chipset & 0xfff0) == CHIPSET_C51) ||
914                ((pNv->Chipset & 0xfff0) == CHIPSET_C512))
915             {
916                 state->arbitration0 = 128; 
917                 state->arbitration1 = 0x0480; 
918             } else if(pNv->Architecture < NV_ARCH_30) {
919                 nv4_10UpdateArbitrationSettings(pScrn, VClk,
920                                           pixelDepth * 8, 
921                                          &(state->arbitration0),
922                                          &(state->arbitration1));
923             } else {
924                 nv30UpdateArbitrationSettings(&(state->arbitration0),
925                                          &(state->arbitration1));
926             }
927             CursorStart = pNv->Cursor->offset;
928             state->cursor0  = 0x80 | (CursorStart >> 17);
929             state->cursor1  = (CursorStart >> 11) << 2;
930             state->cursor2  = CursorStart >> 24;
931             if (flags & V_DBLSCAN) 
932                 state->cursor1 |= 2;
933             state->pllsel   = 0x10000700;
934             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
935             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
936             break;
937     }
938
939     if(bpp != 8) /* DirectColor */
940         state->general |= 0x00000030;
941
942     state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
943     state->pixel    = (pixelDepth > 2) ? 3 : pixelDepth;
944 }
945
946
947 void NVLoadStateExt (
948     ScrnInfoPtr pScrn,
949     RIVA_HW_STATE *state
950 )
951 {
952     NVPtr pNv = NVPTR(pScrn);
953     CARD32 temp;
954
955     if(pNv->Architecture >= NV_ARCH_40) {
956         switch(pNv->Chipset & 0xfff0) {
957         case CHIPSET_NV44:
958         case CHIPSET_NV44A:
959         case CHIPSET_C51:
960         case CHIPSET_G70:
961         case CHIPSET_G71:
962         case CHIPSET_G72:
963         case CHIPSET_G73:
964         case CHIPSET_C512:
965              temp = nvReadCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL);
966              nvWriteCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL, temp | 0x00100000);
967              break;
968         default:
969              break;
970         };
971     }
972
973     if(pNv->Architecture >= NV_ARCH_10) {
974         if(pNv->twoHeads) {
975            NVWriteCRTC(pNv, 0, NV_CRTC_FSEL, state->head);
976            NVWriteCRTC(pNv, 1, NV_CRTC_FSEL, state->head2);
977         }
978         temp = nvReadCurRAMDAC(pNv, NV_RAMDAC_NV10_CURSYNC);
979         nvWriteCurRAMDAC(pNv, NV_RAMDAC_NV10_CURSYNC, temp | (1 << 25));
980     
981         nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
982         nvWriteVIDEO(pNv, NV_PVIDEO_INTR_EN, 0);
983         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(0), 0);
984         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(1), 0);
985         nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(0), pNv->VRAMPhysicalSize - 1);
986         nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(1), pNv->VRAMPhysicalSize - 1);
987         nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(0), pNv->VRAMPhysicalSize - 1);
988         nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(1), pNv->VRAMPhysicalSize - 1);
989         nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, 0);
990
991         nvWriteCurCRTC(pNv, NV_CRTC_CURSOR_CONFIG, state->cursorConfig);
992         nvWriteCurCRTC(pNv, NV_CRTC_0830, state->displayV - 3);
993         nvWriteCurCRTC(pNv, NV_CRTC_0834, state->displayV - 1);
994     
995         if(pNv->FlatPanel) {
996            if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
997                nvWriteCurRAMDAC(pNv, NV_RAMDAC_DITHER_NV11, state->dither);
998            } else 
999            if(pNv->twoHeads) {
1000                nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_DITHER, state->dither);
1001            }
1002     
1003            nvWriteCurVGA(pNv, NV_VGA_CRTCX_FP_HTIMING, state->timingH);
1004            nvWriteCurVGA(pNv, NV_VGA_CRTCX_FP_VTIMING, state->timingV);
1005            nvWriteCurVGA(pNv, NV_VGA_CRTCX_BUFFER, 0xfa);
1006         }
1007
1008         nvWriteCurVGA(pNv, NV_VGA_CRTCX_EXTRA, state->extra);
1009     }
1010
1011     nvWriteCurVGA(pNv, NV_VGA_CRTCX_REPAINT0, state->repaint0);
1012     nvWriteCurVGA(pNv, NV_VGA_CRTCX_REPAINT1, state->repaint1);
1013     nvWriteCurVGA(pNv, NV_VGA_CRTCX_LSR, state->screen);
1014     nvWriteCurVGA(pNv, NV_VGA_CRTCX_PIXEL, state->pixel);
1015     nvWriteCurVGA(pNv, NV_VGA_CRTCX_HEB, state->horiz);
1016     nvWriteCurVGA(pNv, NV_VGA_CRTCX_FIFO1, state->fifo);
1017     nvWriteCurVGA(pNv, NV_VGA_CRTCX_FIFO0, state->arbitration0);
1018     nvWriteCurVGA(pNv, NV_VGA_CRTCX_FIFO_LWM, state->arbitration1);
1019     if(pNv->Architecture >= NV_ARCH_30) {
1020       nvWriteCurVGA(pNv, NV_VGA_CRTCX_FIFO_LWM_NV30, state->arbitration1 >> 8);
1021     }
1022
1023     nvWriteCurVGA(pNv, NV_VGA_CRTCX_CURCTL0, state->cursor0);
1024     nvWriteCurVGA(pNv, NV_VGA_CRTCX_CURCTL1, state->cursor1);
1025     if(pNv->Architecture == NV_ARCH_40) {  /* HW bug */
1026        volatile CARD32 curpos = nvReadCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS);
1027        nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, curpos);
1028     }
1029     nvWriteCurVGA(pNv, NV_VGA_CRTCX_CURCTL2, state->cursor2);
1030     nvWriteCurVGA(pNv, NV_VGA_CRTCX_INTERLACE, state->interlace);
1031
1032     if(!pNv->FlatPanel) {
1033        NVWriteRAMDAC(pNv, 0, NV_RAMDAC_PLL_SELECT, state->pllsel);
1034        NVWriteRAMDAC(pNv, 0, NV_RAMDAC_VPLL, state->vpll);
1035        if(pNv->twoHeads)
1036           NVWriteRAMDAC(pNv, 0, NV_RAMDAC_VPLL2, state->vpll2);
1037        if(pNv->twoStagePLL) {
1038           NVWriteRAMDAC(pNv, 0, NV_RAMDAC_VPLL_B, state->vpllB);
1039           NVWriteRAMDAC(pNv, 0, NV_RAMDAC_VPLL2_B, state->vpll2B);
1040        }
1041     } else {
1042        nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL, state->scale);
1043        nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_HCRTC, state->crtcSync);
1044     }
1045     nvWriteCurRAMDAC(pNv, NV_RAMDAC_GENERAL_CONTROL, state->general);
1046
1047     nvWriteCurCRTC(pNv, NV_CRTC_INTR_EN_0, 0);
1048     nvWriteCurCRTC(pNv, NV_CRTC_INTR_0, NV_CRTC_INTR_VBLANK);
1049 }
1050
1051 void NVUnloadStateExt
1052 (
1053     NVPtr pNv,
1054     RIVA_HW_STATE *state
1055 )
1056 {
1057     state->repaint0     = nvReadCurVGA(pNv, NV_VGA_CRTCX_REPAINT0);
1058     state->repaint1     = nvReadCurVGA(pNv, NV_VGA_CRTCX_REPAINT1);
1059     state->screen       = nvReadCurVGA(pNv, NV_VGA_CRTCX_LSR);
1060     state->pixel        = nvReadCurVGA(pNv, NV_VGA_CRTCX_PIXEL);
1061     state->horiz        = nvReadCurVGA(pNv, NV_VGA_CRTCX_HEB);
1062     state->fifo         = nvReadCurVGA(pNv, NV_VGA_CRTCX_FIFO1);
1063     state->arbitration0 = nvReadCurVGA(pNv, NV_VGA_CRTCX_FIFO0);
1064     state->arbitration1 = nvReadCurVGA(pNv, NV_VGA_CRTCX_FIFO_LWM);
1065     if(pNv->Architecture >= NV_ARCH_30) {
1066        state->arbitration1 |= (nvReadCurVGA(pNv, NV_VGA_CRTCX_FIFO_LWM_NV30) & 1) << 8;
1067     }
1068     state->cursor0      = nvReadCurVGA(pNv, NV_VGA_CRTCX_CURCTL0);
1069     state->cursor1      = nvReadCurVGA(pNv, NV_VGA_CRTCX_CURCTL1);
1070     state->cursor2      = nvReadCurVGA(pNv, NV_VGA_CRTCX_CURCTL2);
1071     state->interlace    = nvReadCurVGA(pNv, NV_VGA_CRTCX_INTERLACE);
1072
1073     state->vpll         = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL);
1074     if(pNv->twoHeads)
1075        state->vpll2     = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL2);
1076     if(pNv->twoStagePLL) {
1077         state->vpllB    = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL_B);
1078         state->vpll2B   = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL2_B);
1079     }
1080     state->pllsel       = NVReadRAMDAC(pNv, 0, NV_RAMDAC_PLL_SELECT);
1081     state->general      = nvReadCurRAMDAC(pNv, NV_RAMDAC_GENERAL_CONTROL);
1082     state->scale        = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL);
1083
1084     if(pNv->Architecture >= NV_ARCH_10) {
1085         if(pNv->twoHeads) {
1086            state->head     = NVReadCRTC(pNv, 0, NV_CRTC_FSEL);
1087            state->head2    = NVReadCRTC(pNv, 1, NV_CRTC_FSEL);
1088            state->crtcOwner = nvReadCurVGA(pNv, NV_VGA_CRTCX_OWNER);
1089         }
1090         state->extra = nvReadCurVGA(pNv, NV_VGA_CRTCX_EXTRA);
1091
1092         state->cursorConfig = nvReadCurCRTC(pNv, NV_CRTC_CURSOR_CONFIG);
1093
1094         if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
1095            state->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_DITHER_NV11);
1096         } else 
1097         if(pNv->twoHeads) {
1098             state->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_DITHER);
1099         }
1100
1101         if(pNv->FlatPanel) {
1102            state->timingH = nvReadCurVGA(pNv, NV_VGA_CRTCX_FP_HTIMING);
1103            state->timingV = nvReadCurVGA(pNv, NV_VGA_CRTCX_FP_VTIMING);
1104         }
1105     }
1106
1107     if(pNv->FlatPanel) {
1108        state->crtcSync = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_HCRTC);
1109     }
1110 }
1111
1112 void NVSetStartAddress (
1113     NVPtr   pNv,
1114     CARD32 start
1115 )
1116 {
1117     nvWriteCurCRTC(pNv, NV_CRTC_START, start);
1118 }
1119
1120 uint32_t nv_pitch_align(NVPtr pNv, uint32_t width, int bpp)
1121 {
1122         int mask;
1123
1124         if (bpp == 15)
1125                 bpp = 16;
1126         if (bpp == 24)
1127                 bpp = 8;
1128
1129         /* Alignment requirements taken from the Haiku driver */
1130         if (pNv->Architecture == NV_ARCH_04)
1131                 mask = 128 / bpp - 1;
1132         else
1133                 mask = 512 / bpp - 1;
1134
1135         return (width + mask) & ~mask;
1136 }
1137
1138 #define VGA_SEQ_PLANE_WRITE     0x02
1139 #define VGA_SEQ_MEMORY_MODE     0x04
1140 #define VGA_GFX_PLANE_READ      0x04
1141 #define VGA_GFX_MODE            0x05
1142 #define VGA_GFX_MISC            0x06
1143
1144 void nv_save_restore_vga_fonts(ScrnInfoPtr pScrn, bool save)
1145 {
1146         NVPtr pNv = NVPTR(pScrn);
1147         bool graphicsmode;
1148         uint8_t misc, gr4, gr5, gr6, seq2, seq4;
1149         int i;
1150
1151         NVSetEnablePalette(pNv, 0, true);
1152         graphicsmode = NVReadVgaAttr(pNv, 0, 0x10) & 1;
1153         NVSetEnablePalette(pNv, 0, false);
1154
1155         if (graphicsmode)       /* graphics mode => framebuffer => no need to save */
1156                 return;
1157
1158         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%sing VGA fonts\n", save ? "Sav" : "Restor");
1159         if (pNv->twoHeads)
1160                 NVBlankScreen(pScrn, 1, true);
1161         NVBlankScreen(pScrn, 0, true);
1162
1163         /* save control regs */
1164         misc = NVReadPVIO(pNv, 0, VGA_MISC_OUT_R);
1165         seq2 = NVReadVgaSeq(pNv, 0, VGA_SEQ_PLANE_WRITE);
1166         seq4 = NVReadVgaSeq(pNv, 0, VGA_SEQ_MEMORY_MODE);
1167         gr4 = NVReadVgaGr(pNv, 0, VGA_GFX_PLANE_READ);
1168         gr5 = NVReadVgaGr(pNv, 0, VGA_GFX_MODE);
1169         gr6 = NVReadVgaGr(pNv, 0, VGA_GFX_MISC);
1170
1171         NVWritePVIO(pNv, 0, VGA_MISC_OUT_W, 0x67);
1172         NVWriteVgaSeq(pNv, 0, VGA_SEQ_MEMORY_MODE, 0x6);
1173         NVWriteVgaGr(pNv, 0, VGA_GFX_MODE, 0x0);
1174         NVWriteVgaGr(pNv, 0, VGA_GFX_MISC, 0x5);
1175
1176         /* store font in plane 0 */
1177         NVWriteVgaSeq(pNv, 0, VGA_SEQ_PLANE_WRITE, 0x1);
1178         NVWriteVgaGr(pNv, 0, VGA_GFX_PLANE_READ, 0x0);
1179         for (i = 0; i < 16384; i++)
1180                 if (save)
1181                         pNv->saved_vga_font[0][i] = MMIO_IN32(pNv->FB_BAR, i * 4);
1182                 else
1183                         MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[0][i]);
1184
1185         /* store font in plane 1 */
1186         NVWriteVgaSeq(pNv, 0, VGA_SEQ_PLANE_WRITE, 0x2);
1187         NVWriteVgaGr(pNv, 0, VGA_GFX_PLANE_READ, 0x1);
1188         for (i = 0; i < 16384; i++)
1189                 if (save)
1190                         pNv->saved_vga_font[1][i] = MMIO_IN32(pNv->FB_BAR, i * 4);
1191                 else
1192                         MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[1][i]);
1193
1194         /* store font in plane 2 */
1195         NVWriteVgaSeq(pNv, 0, VGA_SEQ_PLANE_WRITE, 0x4);
1196         NVWriteVgaGr(pNv, 0, VGA_GFX_PLANE_READ, 0x2);
1197         for (i = 0; i < 16384; i++)
1198                 if (save)
1199                         pNv->saved_vga_font[2][i] = MMIO_IN32(pNv->FB_BAR, i * 4);
1200                 else
1201                         MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[2][i]);
1202
1203         /* store font in plane 3 */
1204         NVWriteVgaSeq(pNv, 0, VGA_SEQ_PLANE_WRITE, 0x8);
1205         NVWriteVgaGr(pNv, 0, VGA_GFX_PLANE_READ, 0x3);
1206         for (i = 0; i < 16384; i++)
1207                 if (save)
1208                         pNv->saved_vga_font[3][i] = MMIO_IN32(pNv->FB_BAR, i * 4);
1209                 else
1210                         MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[3][i]);
1211
1212         /* restore control regs */
1213         NVWritePVIO(pNv, 0, VGA_MISC_OUT_W, misc);
1214         NVWriteVgaGr(pNv, 0, VGA_GFX_PLANE_READ, gr4);
1215         NVWriteVgaGr(pNv, 0, VGA_GFX_MODE, gr5);
1216         NVWriteVgaGr(pNv, 0, VGA_GFX_MISC, gr6);
1217         NVWriteVgaSeq(pNv, 0, VGA_SEQ_PLANE_WRITE, seq2);
1218         NVWriteVgaSeq(pNv, 0, VGA_SEQ_MEMORY_MODE, seq4);
1219
1220         if (pNv->twoHeads)
1221                 NVBlankScreen(pScrn, 1, false);
1222         NVBlankScreen(pScrn, 0, false);
1223 }