Rename relevant functions, sizes and offsets to PRM.IO from P.IO, in keeping with...
[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_PRMCIO1_OFFSET : NV_PRMCIO0_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_PRMCIO1_OFFSET : NV_PRMCIO0_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, NV_CIO_CRE_57, index);
134         NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_58, value);
135 }
136
137 uint8_t NVReadVgaCrtc5758(NVPtr pNv, int head, uint8_t index)
138 {
139         NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_57, index);
140         return NVReadVgaCrtc(pNv, head, NV_CIO_CRE_58);
141 }
142
143 uint8_t NVReadPRMVIO(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_PRMVIO1_OFFSET : NV_PRMVIO0_OFFSET;
147
148         DDXMMIOH("NVReadPRMVIO: 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 NVWritePRMVIO(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_PRMVIO1_OFFSET : NV_PRMVIO0_OFFSET;
156
157         DDXMMIOH("NVWritePRMVIO: 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         NVWritePRMVIO(pNv, head, VGA_SEQ_INDEX, index);
164         NVWritePRMVIO(pNv, head, VGA_SEQ_DATA, value);
165 }
166
167 uint8_t NVReadVgaSeq(NVPtr pNv, int head, uint8_t index)
168 {
169         NVWritePRMVIO(pNv, head, VGA_SEQ_INDEX, index);
170         return NVReadPRMVIO(pNv, head, VGA_SEQ_DATA);
171 }
172
173 void NVWriteVgaGr(NVPtr pNv, int head, uint8_t index, uint8_t value)
174 {
175         NVWritePRMVIO(pNv, head, VGA_GRAPH_INDEX, index);
176         NVWritePRMVIO(pNv, head, VGA_GRAPH_DATA, value);
177 }
178
179 uint8_t NVReadVgaGr(NVPtr pNv, int head, uint8_t index)
180 {
181         NVWritePRMVIO(pNv, head, VGA_GRAPH_INDEX, index);
182         return NVReadPRMVIO(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_PRMCIO1_OFFSET : NV_PRMCIO0_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_PRMCIO1_OFFSET : NV_PRMCIO0_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_PRMCIO1_OFFSET : NV_PRMCIO0_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_PRMCIO1_OFFSET : NV_PRMCIO0_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(NVPtr pNv, int head)
254 {
255         /* CR44 is always changed on CRTC0 */
256         NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_44, head * 0x3);
257 }
258
259 void NVLockVgaCrtc(NVPtr pNv, int head, bool lock)
260 {
261         uint8_t cr11;
262
263         NVWriteVgaCrtc(pNv, head, NV_CIO_SR_LOCK_INDEX, lock ? 0x99 : 0x57);
264
265         cr11 = NVReadVgaCrtc(pNv, head, NV_CIO_CR_VRE_INDEX);
266         if (lock)
267                 cr11 |= 0x80;
268         else
269                 cr11 &= ~0x80;
270         NVWriteVgaCrtc(pNv, head, NV_CIO_CR_VRE_INDEX, cr11);
271 }
272
273 void NVBlankScreen(NVPtr pNv, int head, bool blank)
274 {
275         unsigned char seq1;
276
277         if (pNv->twoHeads)
278                 NVSetOwner(pNv, head);
279
280         seq1 = NVReadVgaSeq(pNv, head, 0x1);
281
282         NVVgaSeqReset(pNv, head, true);
283         if (blank)
284                 NVWriteVgaSeq(pNv, head, 0x1, seq1 | 0x20);
285         else
286                 NVWriteVgaSeq(pNv, head, 0x1, seq1 & ~0x20);
287         NVVgaSeqReset(pNv, head, false);
288 }
289
290 void nv_fix_nv40_hw_cursor(NVPtr pNv, int head)
291 {
292         /* on some nv40 (such as the "true" (in the NV_PFB_BOOT_0 sense) nv40,
293          * the gf6800gt) a hardware bug requires a write to PRAMDAC_CURSOR_POS
294          * for changes to the CRTC CURCTL regs to take effect, whether changing
295          * the pixmap location, or just showing/hiding the cursor
296          */
297         volatile uint32_t curpos = NVReadRAMDAC(pNv, head, NV_RAMDAC_CURSOR_POS);
298         NVWriteRAMDAC(pNv, head, NV_RAMDAC_CURSOR_POS, curpos);
299 }
300
301 void nv_show_cursor(NVPtr pNv, int head, bool show)
302 {
303         int curctl1 = NVReadVgaCrtc(pNv, head, NV_CIO_CRE_HCUR_ADDR1_INDEX);
304
305         if (show)
306                 NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, curctl1 | 1);
307         else
308                 NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, curctl1 & ~1);
309
310         if (pNv->Architecture == NV_ARCH_40)
311                 nv_fix_nv40_hw_cursor(pNv, head);
312 }
313
314 int nv_decode_pll_highregs(NVPtr pNv, uint32_t pll1, uint32_t pll2, bool force_single, int refclk)
315 {
316         int M1, N1, M2 = 1, N2 = 1, log2P;
317
318         M1 = pll1 & 0xff;
319         N1 = (pll1 >> 8) & 0xff;
320         log2P = (pll1 >> 16) & 0x7; /* never more than 6, and nv30/35 only uses 3 bits */
321         if (pNv->twoStagePLL && pll2 & NV31_RAMDAC_ENABLE_VCO2 && !force_single) {
322                 M2 = pll2 & 0xff;
323                 N2 = (pll2 >> 8) & 0xff;
324         } else if (pNv->NVArch == 0x30 || pNv->NVArch == 0x35) {
325                 M1 &= 0xf; /* only 4 bits */
326                 if (pll1 & NV30_RAMDAC_ENABLE_VCO2) {
327                         M2 = (pll1 >> 4) & 0x7;
328                         N2 = ((pll2 >> 21) & 0x18) | ((pll2 >> 19) & 0x7);
329                 }
330         }
331
332         /* Avoid divide by zero if called at an inappropriate time */
333         if (!M1 || !M2)
334                 return 0;
335
336         return (N1 * N2 * refclk / (M1 * M2)) >> log2P;
337 }
338
339 static int nv_decode_pll_lowregs(uint32_t Pval, uint32_t NMNM, int refclk)
340 {
341         int M1, N1, M2 = 1, N2 = 1, log2P;
342
343         log2P = (Pval >> 16) & 0x7;
344
345         M1 = NMNM & 0xff;
346         N1 = (NMNM >> 8) & 0xff;
347         /* NVPLL and VPLLs use 1 << 8 to indicate single stage mode, MPLL uses 1 << 12 */
348         if (!(Pval & (1 << 8) || Pval & (1 << 12))) {
349                 M2 = (NMNM >> 16) & 0xff;
350                 N2 = (NMNM >> 24) & 0xff;
351         }
352
353         /* Avoid divide by zero if called at an inappropriate time */
354         if (!M1 || !M2)
355                 return 0;
356
357         return (N1 * N2 * refclk / (M1 * M2)) >> log2P;
358 }
359
360 static int nv_get_clock(ScrnInfoPtr pScrn, enum pll_types plltype)
361 {
362         NVPtr pNv = NVPTR(pScrn);
363         const uint32_t nv04_regs[MAX_PLL_TYPES] = { NV_RAMDAC_NVPLL, NV_RAMDAC_MPLL, NV_RAMDAC_VPLL, NV_RAMDAC_VPLL2 };
364         const uint32_t nv40_regs[MAX_PLL_TYPES] = { 0x4000, 0x4020, NV_RAMDAC_VPLL, NV_RAMDAC_VPLL2 };
365         uint32_t reg1;
366         struct pll_lims pll_lim;
367
368         if (plltype == MPLL && (pNv->Chipset & 0x0ff0) == CHIPSET_NFORCE) {
369                 uint32_t mpllP = (PCI_SLOT_READ_LONG(3, 0x6c) >> 8) & 0xf;
370
371                 if (!mpllP)
372                         mpllP = 4;
373                 return 400000 / mpllP;
374         } else if (plltype == MPLL && (pNv->Chipset & 0xff0) == CHIPSET_NFORCE2)
375                 return PCI_SLOT_READ_LONG(5, 0x4c) / 1000;
376
377         if (pNv->Architecture < NV_ARCH_40)
378                 reg1 = nv04_regs[plltype];
379         else
380                 reg1 = nv40_regs[plltype];
381
382         if (!get_pll_limits(pScrn, plltype, &pll_lim))
383                 return 0;
384
385         if (reg1 <= 0x405c)
386                 return nv_decode_pll_lowregs(nvReadMC(pNv, reg1), nvReadMC(pNv, reg1 + 4), pll_lim.refclk);
387         if (pNv->twoStagePLL) {
388                 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));
389
390                 return nv_decode_pll_highregs(pNv, nvReadMC(pNv, reg1), nvReadMC(pNv, reg1 + ((reg1 == NV_RAMDAC_VPLL2) ? 0x5c : 0x70)), nv40_single, pll_lim.refclk);
391         }
392         return nv_decode_pll_highregs(pNv, nvReadMC(pNv, reg1), 0, false, pll_lim.refclk);
393 }
394
395 /****************************************************************************\
396 *                                                                            *
397 * The video arbitration routines calculate some "magic" numbers.  Fixes      *
398 * the snow seen when accessing the framebuffer without it.                   *
399 * It just works (I hope).                                                    *
400 *                                                                            *
401 \****************************************************************************/
402
403 struct nv_fifo_info {
404         int graphics_lwm;
405         int video_lwm;
406         int graphics_burst_size;
407         int video_burst_size;
408         bool valid;
409 };
410
411 struct nv_sim_state {
412         int pclk_khz;
413         int mclk_khz;
414         int nvclk_khz;
415         int pix_bpp;
416         bool enable_mp;
417         bool enable_video;
418         int mem_page_miss;
419         int mem_latency;
420         int memory_type;
421         int memory_width;
422 };
423
424 static void nv4CalcArbitration(struct nv_fifo_info *fifo, struct nv_sim_state *arb)
425 {
426         int pagemiss, cas, width, video_enable, bpp;
427         int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
428         int found, mclk_extra, mclk_loop, cbs, m1, p1;
429         int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
430         int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
431         int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt, clwm;
432
433         pclk_freq = arb->pclk_khz;
434         mclk_freq = arb->mclk_khz;
435         nvclk_freq = arb->nvclk_khz;
436         pagemiss = arb->mem_page_miss;
437         cas = arb->mem_latency;
438         width = arb->memory_width >> 6;
439         video_enable = arb->enable_video;
440         bpp = arb->pix_bpp;
441         mp_enable = arb->enable_mp;
442         clwm = 0;
443         vlwm = 0;
444         cbs = 128;
445         pclks = 2;
446         nvclks = 2;
447         nvclks += 2;
448         nvclks += 1;
449         mclks = 5;
450         mclks += 3;
451         mclks += 1;
452         mclks += cas;
453         mclks += 1;
454         mclks += 1;
455         mclks += 1;
456         mclks += 1;
457         mclk_extra = 3;
458         nvclks += 2;
459         nvclks += 1;
460         nvclks += 1;
461         nvclks += 1;
462         if (mp_enable)
463                 mclks += 4;
464         nvclks += 0;
465         pclks += 0;
466         found = 0;
467         vbs = 0;
468         while (found != 1) {
469                 fifo->valid = true;
470                 found = 1;
471                 mclk_loop = mclks + mclk_extra;
472                 us_m = mclk_loop * 1000 * 1000 / mclk_freq;
473                 us_n = nvclks * 1000 * 1000 / nvclk_freq;
474                 us_p = nvclks * 1000 * 1000 / pclk_freq;
475                 if (video_enable) {
476                         video_drain_rate = pclk_freq * 2;
477                         crtc_drain_rate = pclk_freq * bpp / 8;
478                         vpagemiss = 2;
479                         vpagemiss += 1;
480                         crtpagemiss = 2;
481                         vpm_us = vpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
482                         if (nvclk_freq * 2 > mclk_freq * width)
483                                 video_fill_us = cbs * 1000 * 1000 / 16 / nvclk_freq;
484                         else
485                                 video_fill_us = cbs * 1000 * 1000 / (8 * width) / mclk_freq;
486                         us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
487                         vlwm = us_video * video_drain_rate / (1000 * 1000);
488                         vlwm++;
489                         vbs = 128;
490                         if (vlwm > 128)
491                                 vbs = 64;
492                         if (vlwm > (256 - 64))
493                                 vbs = 32;
494                         if (nvclk_freq * 2 > mclk_freq * width)
495                                 video_fill_us = vbs * 1000 * 1000 / 16 / nvclk_freq;
496                         else
497                                 video_fill_us = vbs * 1000 * 1000 / (8 * width) / mclk_freq;
498                         cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
499                         us_crt = us_video + video_fill_us + cpm_us + us_m + us_n + us_p;
500                         clwm = us_crt * crtc_drain_rate / (1000 * 1000);
501                         clwm++;
502                 } else {
503                         crtc_drain_rate = pclk_freq * bpp / 8;
504                         crtpagemiss = 2;
505                         crtpagemiss += 1;
506                         cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
507                         us_crt = cpm_us + us_m + us_n + us_p;
508                         clwm = us_crt * crtc_drain_rate / (1000 * 1000);
509                         clwm++;
510                 }
511                 m1 = clwm + cbs - 512;
512                 p1 = m1 * pclk_freq / mclk_freq;
513                 p1 = p1 * bpp / 8;
514                 if ((p1 < m1 && m1 > 0) ||
515                     (video_enable && (clwm > 511 || vlwm > 255)) ||
516                     (!video_enable && clwm > 519)) {
517                         fifo->valid = false;
518                         found = !mclk_extra;
519                         mclk_extra--;
520                 }
521                 if (clwm < 384)
522                         clwm = 384;
523                 if (vlwm < 128)
524                         vlwm = 128;
525                 fifo->graphics_lwm = clwm;
526                 fifo->graphics_burst_size = 128;
527                 fifo->video_lwm = vlwm + 15;
528                 fifo->video_burst_size = vbs;
529         }
530 }
531
532 static void nv10CalcArbitration(struct nv_fifo_info *fifo, struct nv_sim_state *arb)
533 {
534         int pagemiss, width, video_enable, bpp;
535         int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
536         int nvclk_fill;
537         int found, mclk_extra, mclk_loop, cbs, m1;
538         int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
539         int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
540         int vus_m;
541         int vpm_us, us_video, cpm_us, us_crt, clwm;
542         int clwm_rnd_down;
543         int m2us, us_pipe_min, p1clk, p2;
544         int min_mclk_extra;
545         int us_min_mclk_extra;
546
547         pclk_freq = arb->pclk_khz;      /* freq in KHz */
548         mclk_freq = arb->mclk_khz;
549         nvclk_freq = arb->nvclk_khz;
550         pagemiss = arb->mem_page_miss;
551         width = arb->memory_width / 64;
552         video_enable = arb->enable_video;
553         bpp = arb->pix_bpp;
554         mp_enable = arb->enable_mp;
555         clwm = 0;
556         cbs = 512;
557         pclks = 4;      /* lwm detect. */
558         nvclks = 3;     /* lwm -> sync. */
559         nvclks += 2;    /* fbi bus cycles (1 req + 1 busy) */
560         mclks = 1;      /* 2 edge sync.  may be very close to edge so just put one. */
561         mclks += 1;     /* arb_hp_req */
562         mclks += 5;     /* ap_hp_req   tiling pipeline */
563         mclks += 2;     /* tc_req     latency fifo */
564         mclks += 2;     /* fb_cas_n_  memory request to fbio block */
565         mclks += 7;     /* sm_d_rdv   data returned from fbio block */
566
567         /* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
568         if (arb->memory_type == 0) {
569                 if (arb->memory_width == 64)    /* 64 bit bus */
570                         mclks += 4;
571                 else
572                         mclks += 2;
573         } else if (arb->memory_width == 64)     /* 64 bit bus */
574                 mclks += 2;
575         else
576                 mclks += 1;
577
578         if (!video_enable && arb->memory_width == 128) {
579                 mclk_extra = (bpp == 32) ? 31 : 42;     /* Margin of error */
580                 min_mclk_extra = 17;
581         } else {
582                 mclk_extra = (bpp == 32) ? 8 : 4;       /* Margin of error */
583                 /* mclk_extra = 4; *//* Margin of error */
584                 min_mclk_extra = 18;
585         }
586
587         nvclks += 1;    /* 2 edge sync.  may be very close to edge so just put one. */
588         nvclks += 1;    /* fbi_d_rdv_n */
589         nvclks += 1;    /* Fbi_d_rdata */
590         nvclks += 1;    /* crtfifo load */
591
592         if (mp_enable)
593                 mclks += 4;     /* Mp can get in with a burst of 8. */
594         /* Extra clocks determined by heuristics */
595
596         nvclks += 0;
597         pclks += 0;
598         found = 0;
599         while (found != 1) {
600                 fifo->valid = true;
601                 found = 1;
602                 mclk_loop = mclks + mclk_extra;
603                 us_m = mclk_loop * 1000 * 1000 / mclk_freq;     /* Mclk latency in us */
604                 us_m_min = mclks * 1000 * 1000 / mclk_freq;     /* Minimum Mclk latency in us */
605                 us_min_mclk_extra = min_mclk_extra * 1000 * 1000 / mclk_freq;
606                 us_n = nvclks * 1000 * 1000 / nvclk_freq;       /* nvclk latency in us */
607                 us_p = pclks * 1000 * 1000 / pclk_freq; /* nvclk latency in us */
608                 us_pipe_min = us_m_min + us_n + us_p;
609
610                 vus_m = mclk_loop * 1000 * 1000 / mclk_freq;    /* Mclk latency in us */
611
612                 if (video_enable) {
613                         crtc_drain_rate = pclk_freq * bpp / 8;  /* MB/s */
614
615                         vpagemiss = 1;  /* self generating page miss */
616                         vpagemiss += 1; /* One higher priority before */
617
618                         crtpagemiss = 2;        /* self generating page miss */
619                         if (mp_enable)
620                                 crtpagemiss += 1;       /* if MA0 conflict */
621
622                         vpm_us = vpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
623
624                         us_video = vpm_us + vus_m;      /* Video has separate read return path */
625
626                         cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
627                         us_crt = us_video       /* Wait for video */
628                                  + cpm_us       /* CRT Page miss */
629                                  + us_m + us_n + us_p;  /* other latency */
630
631                         clwm = us_crt * crtc_drain_rate / (1000 * 1000);
632                         clwm++; /* fixed point <= float_point - 1.  Fixes that */
633                 } else {
634                         crtc_drain_rate = pclk_freq * bpp / 8;  /* bpp * pclk/8 */
635
636                         crtpagemiss = 1;        /* self generating page miss */
637                         crtpagemiss += 1;       /* MA0 page miss */
638                         if (mp_enable)
639                                 crtpagemiss += 1;       /* if MA0 conflict */
640                         cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
641                         us_crt = cpm_us + us_m + us_n + us_p;
642                         clwm = us_crt * crtc_drain_rate / (1000 * 1000);
643                         clwm++; /* fixed point <= float_point - 1.  Fixes that */
644
645                         /* Finally, a heuristic check when width == 64 bits */
646                         if (width == 1) {
647                                 nvclk_fill = nvclk_freq * 8;
648                                 if (crtc_drain_rate * 100 >= nvclk_fill * 102)
649                                         clwm = 0xfff;   /* Large number to fail */
650                                 else if (crtc_drain_rate * 100 >= nvclk_fill * 98) {
651                                         clwm = 1024;
652                                         cbs = 512;
653                                 }
654                         }
655                 }
656
657                 /*
658                  * Overfill check:
659                  */
660
661                 clwm_rnd_down = (clwm / 8) * 8;
662                 if (clwm_rnd_down < clwm)
663                         clwm += 8;
664
665                 m1 = clwm + cbs - 1024; /* Amount of overfill */
666                 m2us = us_pipe_min + us_min_mclk_extra;
667
668                 /* pclk cycles to drain */
669                 p1clk = m2us * pclk_freq / (1000 * 1000);
670                 p2 = p1clk * bpp / 8;   /* bytes drained. */
671
672                 if (p2 < m1 && m1 > 0) {
673                         fifo->valid = false;
674                         found = 0;
675                         if (min_mclk_extra == 0) {
676                                 if (cbs <= 32)
677                                         found = 1;      /* Can't adjust anymore! */
678                                 else
679                                         cbs = cbs / 2;  /* reduce the burst size */
680                         } else
681                                 min_mclk_extra--;
682                 } else if (clwm > 1023) {       /* Have some margin */
683                         fifo->valid = false;
684                         found = 0;
685                         if (min_mclk_extra == 0)
686                                 found = 1;      /* Can't adjust anymore! */
687                         else
688                                 min_mclk_extra--;
689                 }
690
691                 if (clwm < (1024 - cbs + 8))
692                         clwm = 1024 - cbs + 8;
693                 /*  printf("CRT LWM: prog: 0x%x, bs: 256\n", clwm); */
694                 fifo->graphics_lwm = clwm;
695                 fifo->graphics_burst_size = cbs;
696
697                 fifo->video_lwm = 1024;
698                 fifo->video_burst_size = 512;
699         }
700 }
701
702 void nv4_10UpdateArbitrationSettings(ScrnInfoPtr pScrn, int VClk, int bpp, uint8_t *burst, uint16_t *lwm)
703 {
704         NVPtr pNv = NVPTR(pScrn);
705         struct nv_fifo_info fifo_data;
706         struct nv_sim_state sim_data;
707         int MClk = nv_get_clock(pScrn, MPLL);
708         int NVClk = nv_get_clock(pScrn, NVPLL);
709         uint32_t cfg1 = nvReadFB(pNv, NV_PFB_CFG1);
710
711         sim_data.pclk_khz = VClk;
712         sim_data.mclk_khz = MClk;
713         sim_data.nvclk_khz = NVClk;
714         sim_data.pix_bpp = bpp;
715         sim_data.enable_mp = false;
716         if ((pNv->Chipset & 0xffff) == CHIPSET_NFORCE ||
717             (pNv->Chipset & 0xffff) == CHIPSET_NFORCE2) {
718                 sim_data.enable_video = false;
719                 sim_data.memory_type = (PCI_SLOT_READ_LONG(1, 0x7c) >> 12) & 1;
720                 sim_data.memory_width = 64;
721                 sim_data.mem_latency = 3;
722                 sim_data.mem_page_miss = 10;
723         } else {
724                 sim_data.enable_video = (pNv->Architecture != NV_ARCH_04);
725                 sim_data.memory_type = nvReadFB(pNv, NV_PFB_CFG0) & 0x1;
726                 sim_data.memory_width = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
727                 sim_data.mem_latency = cfg1 & 0xf;
728                 sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1);
729         }
730
731         if (pNv->Architecture == NV_ARCH_04)
732                 nv4CalcArbitration(&fifo_data, &sim_data);
733         else
734                 nv10CalcArbitration(&fifo_data, &sim_data);
735
736         if (fifo_data.valid) {
737                 int b = fifo_data.graphics_burst_size >> 4;
738                 *burst = 0;
739                 while (b >>= 1)
740                         (*burst)++;
741                 *lwm = fifo_data.graphics_lwm >> 3;
742         }
743 }
744
745 void nv30UpdateArbitrationSettings(uint8_t *burst, uint16_t *lwm)
746 {
747         unsigned int fifo_size, burst_size, graphics_lwm;
748
749         fifo_size = 2048;
750         burst_size = 512;
751         graphics_lwm = fifo_size - burst_size;
752
753         *burst = 0;
754         burst_size >>= 5;
755         while (burst_size >>= 1)
756                 (*burst)++;
757         *lwm = graphics_lwm >> 3;
758 }
759
760 /****************************************************************************\
761 *                                                                            *
762 *                          RIVA Mode State Routines                          *
763 *                                                                            *
764 \****************************************************************************/
765
766 /*
767  * Calculate the Video Clock parameters for the PLL.
768  */
769 static void CalcVClock (
770     int           clockIn,
771     int          *clockOut,
772     CARD32         *pllOut,
773     NVPtr        pNv
774 )
775 {
776     unsigned lowM, highM;
777     unsigned DeltaNew, DeltaOld;
778     unsigned VClk, Freq;
779     unsigned M, N, P;
780     
781     DeltaOld = 0xFFFFFFFF;
782
783     VClk = (unsigned)clockIn;
784     
785     if (pNv->CrystalFreqKHz == 13500) {
786         lowM  = 7;
787         highM = 13;
788     } else {
789         lowM  = 8;
790         highM = 14;
791     }
792
793     for (P = 0; P <= 4; P++) {
794         Freq = VClk << P;
795         if ((Freq >= 128000) && (Freq <= 350000)) {
796             for (M = lowM; M <= highM; M++) {
797                 N = ((VClk << P) * M) / pNv->CrystalFreqKHz;
798                 if(N <= 255) {
799                     Freq = ((pNv->CrystalFreqKHz * N) / M) >> P;
800                     if (Freq > VClk)
801                         DeltaNew = Freq - VClk;
802                     else
803                         DeltaNew = VClk - Freq;
804                     if (DeltaNew < DeltaOld) {
805                         *pllOut   = (P << 16) | (N << 8) | M;
806                         *clockOut = Freq;
807                         DeltaOld  = DeltaNew;
808                     }
809                 }
810             }
811         }
812     }
813 }
814
815 static void CalcVClock2Stage (
816     int           clockIn,
817     int          *clockOut,
818     CARD32         *pllOut,
819     CARD32         *pllBOut,
820     NVPtr        pNv
821 )
822 {
823     unsigned DeltaNew, DeltaOld;
824     unsigned VClk, Freq;
825     unsigned M, N, P;
826
827     DeltaOld = 0xFFFFFFFF;
828
829     *pllBOut = 0x80000401;  /* fixed at x4 for now */
830
831     VClk = (unsigned)clockIn;
832
833     for (P = 0; P <= 6; P++) {
834         Freq = VClk << P;
835         if ((Freq >= 400000) && (Freq <= 1000000)) {
836             for (M = 1; M <= 13; M++) {
837                 N = ((VClk << P) * M) / (pNv->CrystalFreqKHz << 2);
838                 if((N >= 5) && (N <= 255)) {
839                     Freq = (((pNv->CrystalFreqKHz << 2) * N) / M) >> P;
840                     if (Freq > VClk)
841                         DeltaNew = Freq - VClk;
842                     else
843                         DeltaNew = VClk - Freq;
844                     if (DeltaNew < DeltaOld) {
845                         *pllOut   = (P << 16) | (N << 8) | M;
846                         *clockOut = Freq;
847                         DeltaOld  = DeltaNew;
848                     }
849                 }
850             }
851         }
852     }
853 }
854
855 /*
856  * Calculate extended mode parameters (SVGA) and save in a 
857  * mode state structure.
858  */
859 void NVCalcStateExt (
860     ScrnInfoPtr pScrn,
861     RIVA_HW_STATE *state,
862     int            bpp,
863     int            width,
864     int            hDisplaySize,
865     int            height,
866     int            dotClock,
867     int            flags 
868 )
869 {
870         NVPtr pNv = NVPTR(pScrn);
871     int pixelDepth, VClk = 0;
872         CARD32 CursorStart;
873
874     /*
875      * Save mode parameters.
876      */
877     state->bpp    = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
878     state->width  = width;
879     state->height = height;
880     /*
881      * Extended RIVA registers.
882      */
883     pixelDepth = (bpp + 1)/8;
884     if(pNv->twoStagePLL)
885         CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, pNv);
886     else
887         CalcVClock(dotClock, &VClk, &state->pll, pNv);
888
889     switch (pNv->Architecture)
890     {
891         case NV_ARCH_04:
892             nv4_10UpdateArbitrationSettings(pScrn, VClk,
893                                          pixelDepth * 8, 
894                                         &(state->arbitration0),
895                                         &(state->arbitration1));
896             state->cursor0  = 0x00;
897             state->cursor1  = 0xbC;
898             if (flags & V_DBLSCAN)
899                 state->cursor1 |= 2;
900             state->cursor2  = 0x00000000;
901             state->pllsel   = 0x10000700;
902             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
903             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
904             break;
905         case NV_ARCH_10:
906         case NV_ARCH_20:
907         case NV_ARCH_30:
908         default:
909             if(((pNv->Chipset & 0xfff0) == CHIPSET_C51) ||
910                ((pNv->Chipset & 0xfff0) == CHIPSET_C512))
911             {
912                 state->arbitration0 = 128; 
913                 state->arbitration1 = 0x0480; 
914             } else if(pNv->Architecture < NV_ARCH_30) {
915                 nv4_10UpdateArbitrationSettings(pScrn, VClk,
916                                           pixelDepth * 8, 
917                                          &(state->arbitration0),
918                                          &(state->arbitration1));
919             } else {
920                 nv30UpdateArbitrationSettings(&(state->arbitration0),
921                                          &(state->arbitration1));
922             }
923             CursorStart = pNv->Cursor->offset;
924             state->cursor0  = 0x80 | (CursorStart >> 17);
925             state->cursor1  = (CursorStart >> 11) << 2;
926             state->cursor2  = CursorStart >> 24;
927             if (flags & V_DBLSCAN) 
928                 state->cursor1 |= 2;
929             state->pllsel   = 0x10000700;
930             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
931             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
932             break;
933     }
934
935     if(bpp != 8) /* DirectColor */
936         state->general |= 0x00000030;
937
938     state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
939     state->pixel    = (pixelDepth > 2) ? 3 : pixelDepth;
940 }
941
942
943 void NVLoadStateExt (
944     ScrnInfoPtr pScrn,
945     RIVA_HW_STATE *state
946 )
947 {
948     NVPtr pNv = NVPTR(pScrn);
949     CARD32 temp;
950
951     if(pNv->Architecture >= NV_ARCH_40) {
952         switch(pNv->Chipset & 0xfff0) {
953         case CHIPSET_NV44:
954         case CHIPSET_NV44A:
955         case CHIPSET_C51:
956         case CHIPSET_G70:
957         case CHIPSET_G71:
958         case CHIPSET_G72:
959         case CHIPSET_G73:
960         case CHIPSET_C512:
961              temp = nvReadCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL);
962              nvWriteCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL, temp | 0x00100000);
963              break;
964         default:
965              break;
966         };
967     }
968
969     if(pNv->Architecture >= NV_ARCH_10) {
970         if(pNv->twoHeads) {
971            NVWriteCRTC(pNv, 0, NV_CRTC_FSEL, state->head);
972            NVWriteCRTC(pNv, 1, NV_CRTC_FSEL, state->head2);
973         }
974         temp = nvReadCurRAMDAC(pNv, NV_RAMDAC_NV10_CURSYNC);
975         nvWriteCurRAMDAC(pNv, NV_RAMDAC_NV10_CURSYNC, temp | (1 << 25));
976     
977         nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
978         nvWriteVIDEO(pNv, NV_PVIDEO_INTR_EN, 0);
979         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(0), 0);
980         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(1), 0);
981         nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(0), pNv->VRAMPhysicalSize - 1);
982         nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(1), pNv->VRAMPhysicalSize - 1);
983         nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(0), pNv->VRAMPhysicalSize - 1);
984         nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(1), pNv->VRAMPhysicalSize - 1);
985         nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, 0);
986
987         nvWriteCurCRTC(pNv, NV_CRTC_CURSOR_CONFIG, state->cursorConfig);
988         nvWriteCurCRTC(pNv, NV_CRTC_0830, state->displayV - 3);
989         nvWriteCurCRTC(pNv, NV_CRTC_0834, state->displayV - 1);
990     
991         if(pNv->FlatPanel) {
992            if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
993                nvWriteCurRAMDAC(pNv, NV_RAMDAC_DITHER_NV11, state->dither);
994            } else 
995            if(pNv->twoHeads) {
996                nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_DITHER, state->dither);
997            }
998     
999            nvWriteCurVGA(pNv, NV_CIO_CRE_53, state->timingH);
1000            nvWriteCurVGA(pNv, NV_CIO_CRE_54, state->timingV);
1001            nvWriteCurVGA(pNv, NV_CIO_CRE_21, 0xfa);
1002         }
1003
1004         nvWriteCurVGA(pNv, NV_CIO_CRE_EBR_INDEX, state->extra);
1005     }
1006
1007     nvWriteCurVGA(pNv, NV_CIO_CRE_RPC0_INDEX, state->repaint0);
1008     nvWriteCurVGA(pNv, NV_CIO_CRE_RPC1_INDEX, state->repaint1);
1009     nvWriteCurVGA(pNv, NV_CIO_CRE_LSR_INDEX, state->screen);
1010     nvWriteCurVGA(pNv, NV_CIO_CRE_PIXEL_INDEX, state->pixel);
1011     nvWriteCurVGA(pNv, NV_CIO_CRE_HEB__INDEX, state->horiz);
1012     nvWriteCurVGA(pNv, NV_CIO_CRE_ENH_INDEX, state->fifo);
1013     nvWriteCurVGA(pNv, NV_CIO_CRE_FF_INDEX, state->arbitration0);
1014     nvWriteCurVGA(pNv, NV_CIO_CRE_FFLWM__INDEX, state->arbitration1);
1015     if(pNv->Architecture >= NV_ARCH_30) {
1016       nvWriteCurVGA(pNv, NV_CIO_CRE_47, state->arbitration1 >> 8);
1017     }
1018
1019     nvWriteCurVGA(pNv, NV_CIO_CRE_HCUR_ADDR0_INDEX, state->cursor0);
1020     nvWriteCurVGA(pNv, NV_CIO_CRE_HCUR_ADDR1_INDEX, state->cursor1);
1021     if(pNv->Architecture == NV_ARCH_40) {  /* HW bug */
1022        volatile CARD32 curpos = nvReadCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS);
1023        nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, curpos);
1024     }
1025     nvWriteCurVGA(pNv, NV_CIO_CRE_HCUR_ADDR2_INDEX, state->cursor2);
1026     nvWriteCurVGA(pNv, NV_CIO_CRE_ILACE__INDEX, state->interlace);
1027
1028     if(!pNv->FlatPanel) {
1029        NVWriteRAMDAC(pNv, 0, NV_RAMDAC_PLL_SELECT, state->pllsel);
1030        NVWriteRAMDAC(pNv, 0, NV_RAMDAC_VPLL, state->vpll);
1031        if(pNv->twoHeads)
1032           NVWriteRAMDAC(pNv, 0, NV_RAMDAC_VPLL2, state->vpll2);
1033        if(pNv->twoStagePLL) {
1034           NVWriteRAMDAC(pNv, 0, NV_RAMDAC_VPLL_B, state->vpllB);
1035           NVWriteRAMDAC(pNv, 0, NV_RAMDAC_VPLL2_B, state->vpll2B);
1036        }
1037     } else {
1038        nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL, state->scale);
1039        nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_HCRTC, state->crtcSync);
1040     }
1041     nvWriteCurRAMDAC(pNv, NV_RAMDAC_GENERAL_CONTROL, state->general);
1042
1043     nvWriteCurCRTC(pNv, NV_CRTC_INTR_EN_0, 0);
1044     nvWriteCurCRTC(pNv, NV_CRTC_INTR_0, NV_CRTC_INTR_VBLANK);
1045 }
1046
1047 void NVUnloadStateExt
1048 (
1049     NVPtr pNv,
1050     RIVA_HW_STATE *state
1051 )
1052 {
1053     state->repaint0     = nvReadCurVGA(pNv, NV_CIO_CRE_RPC0_INDEX);
1054     state->repaint1     = nvReadCurVGA(pNv, NV_CIO_CRE_RPC1_INDEX);
1055     state->screen       = nvReadCurVGA(pNv, NV_CIO_CRE_LSR_INDEX);
1056     state->pixel        = nvReadCurVGA(pNv, NV_CIO_CRE_PIXEL_INDEX);
1057     state->horiz        = nvReadCurVGA(pNv, NV_CIO_CRE_HEB__INDEX);
1058     state->fifo         = nvReadCurVGA(pNv, NV_CIO_CRE_ENH_INDEX);
1059     state->arbitration0 = nvReadCurVGA(pNv, NV_CIO_CRE_FF_INDEX);
1060     state->arbitration1 = nvReadCurVGA(pNv, NV_CIO_CRE_FFLWM__INDEX);
1061     if(pNv->Architecture >= NV_ARCH_30) {
1062        state->arbitration1 |= (nvReadCurVGA(pNv, NV_CIO_CRE_47) & 1) << 8;
1063     }
1064     state->cursor0      = nvReadCurVGA(pNv, NV_CIO_CRE_HCUR_ADDR0_INDEX);
1065     state->cursor1      = nvReadCurVGA(pNv, NV_CIO_CRE_HCUR_ADDR1_INDEX);
1066     state->cursor2      = nvReadCurVGA(pNv, NV_CIO_CRE_HCUR_ADDR2_INDEX);
1067     state->interlace    = nvReadCurVGA(pNv, NV_CIO_CRE_ILACE__INDEX);
1068
1069     state->vpll         = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL);
1070     if(pNv->twoHeads)
1071        state->vpll2     = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL2);
1072     if(pNv->twoStagePLL) {
1073         state->vpllB    = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL_B);
1074         state->vpll2B   = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL2_B);
1075     }
1076     state->pllsel       = NVReadRAMDAC(pNv, 0, NV_RAMDAC_PLL_SELECT);
1077     state->general      = nvReadCurRAMDAC(pNv, NV_RAMDAC_GENERAL_CONTROL);
1078     state->scale        = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL);
1079
1080     if(pNv->Architecture >= NV_ARCH_10) {
1081         if(pNv->twoHeads) {
1082            state->head     = NVReadCRTC(pNv, 0, NV_CRTC_FSEL);
1083            state->head2    = NVReadCRTC(pNv, 1, NV_CRTC_FSEL);
1084            state->crtcOwner = nvReadCurVGA(pNv, NV_CIO_CRE_44);
1085         }
1086         state->extra = nvReadCurVGA(pNv, NV_CIO_CRE_EBR_INDEX);
1087
1088         state->cursorConfig = nvReadCurCRTC(pNv, NV_CRTC_CURSOR_CONFIG);
1089
1090         if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
1091            state->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_DITHER_NV11);
1092         } else 
1093         if(pNv->twoHeads) {
1094             state->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_DITHER);
1095         }
1096
1097         if(pNv->FlatPanel) {
1098            state->timingH = nvReadCurVGA(pNv, NV_CIO_CRE_53);
1099            state->timingV = nvReadCurVGA(pNv, NV_CIO_CRE_54);
1100         }
1101     }
1102
1103     if(pNv->FlatPanel) {
1104        state->crtcSync = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_HCRTC);
1105     }
1106 }
1107
1108 void NVSetStartAddress (
1109     NVPtr   pNv,
1110     CARD32 start
1111 )
1112 {
1113     nvWriteCurCRTC(pNv, NV_CRTC_START, start);
1114 }
1115
1116 uint32_t nv_pitch_align(NVPtr pNv, uint32_t width, int bpp)
1117 {
1118         int mask;
1119
1120         if (bpp == 15)
1121                 bpp = 16;
1122         if (bpp == 24)
1123                 bpp = 8;
1124
1125         /* Alignment requirements taken from the Haiku driver */
1126         if (pNv->Architecture == NV_ARCH_04)
1127                 mask = 128 / bpp - 1;
1128         else
1129                 mask = 512 / bpp - 1;
1130
1131         return (width + mask) & ~mask;
1132 }
1133
1134 #define VGA_SEQ_PLANE_WRITE     0x02
1135 #define VGA_SEQ_MEMORY_MODE     0x04
1136 #define VGA_GFX_PLANE_READ      0x04
1137 #define VGA_GFX_MODE            0x05
1138 #define VGA_GFX_MISC            0x06
1139
1140 void nv_save_restore_vga_fonts(ScrnInfoPtr pScrn, bool save)
1141 {
1142         NVPtr pNv = NVPTR(pScrn);
1143         bool graphicsmode;
1144         uint8_t misc, gr4, gr5, gr6, seq2, seq4;
1145         int i;
1146
1147         NVSetEnablePalette(pNv, 0, true);
1148         graphicsmode = NVReadVgaAttr(pNv, 0, 0x10) & 1;
1149         NVSetEnablePalette(pNv, 0, false);
1150
1151         if (graphicsmode)       /* graphics mode => framebuffer => no need to save */
1152                 return;
1153
1154         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%sing VGA fonts\n", save ? "Sav" : "Restor");
1155         if (pNv->twoHeads)
1156                 NVBlankScreen(pNv, 1, true);
1157         NVBlankScreen(pNv, 0, true);
1158
1159         /* save control regs */
1160         misc = NVReadPRMVIO(pNv, 0, VGA_MISC_OUT_R);
1161         seq2 = NVReadVgaSeq(pNv, 0, VGA_SEQ_PLANE_WRITE);
1162         seq4 = NVReadVgaSeq(pNv, 0, VGA_SEQ_MEMORY_MODE);
1163         gr4 = NVReadVgaGr(pNv, 0, VGA_GFX_PLANE_READ);
1164         gr5 = NVReadVgaGr(pNv, 0, VGA_GFX_MODE);
1165         gr6 = NVReadVgaGr(pNv, 0, VGA_GFX_MISC);
1166
1167         NVWritePRMVIO(pNv, 0, VGA_MISC_OUT_W, 0x67);
1168         NVWriteVgaSeq(pNv, 0, VGA_SEQ_MEMORY_MODE, 0x6);
1169         NVWriteVgaGr(pNv, 0, VGA_GFX_MODE, 0x0);
1170         NVWriteVgaGr(pNv, 0, VGA_GFX_MISC, 0x5);
1171
1172         /* store font in plane 0 */
1173         NVWriteVgaSeq(pNv, 0, VGA_SEQ_PLANE_WRITE, 0x1);
1174         NVWriteVgaGr(pNv, 0, VGA_GFX_PLANE_READ, 0x0);
1175         for (i = 0; i < 16384; i++)
1176                 if (save)
1177                         pNv->saved_vga_font[0][i] = MMIO_IN32(pNv->FB_BAR, i * 4);
1178                 else
1179                         MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[0][i]);
1180
1181         /* store font in plane 1 */
1182         NVWriteVgaSeq(pNv, 0, VGA_SEQ_PLANE_WRITE, 0x2);
1183         NVWriteVgaGr(pNv, 0, VGA_GFX_PLANE_READ, 0x1);
1184         for (i = 0; i < 16384; i++)
1185                 if (save)
1186                         pNv->saved_vga_font[1][i] = MMIO_IN32(pNv->FB_BAR, i * 4);
1187                 else
1188                         MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[1][i]);
1189
1190         /* store font in plane 2 */
1191         NVWriteVgaSeq(pNv, 0, VGA_SEQ_PLANE_WRITE, 0x4);
1192         NVWriteVgaGr(pNv, 0, VGA_GFX_PLANE_READ, 0x2);
1193         for (i = 0; i < 16384; i++)
1194                 if (save)
1195                         pNv->saved_vga_font[2][i] = MMIO_IN32(pNv->FB_BAR, i * 4);
1196                 else
1197                         MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[2][i]);
1198
1199         /* store font in plane 3 */
1200         NVWriteVgaSeq(pNv, 0, VGA_SEQ_PLANE_WRITE, 0x8);
1201         NVWriteVgaGr(pNv, 0, VGA_GFX_PLANE_READ, 0x3);
1202         for (i = 0; i < 16384; i++)
1203                 if (save)
1204                         pNv->saved_vga_font[3][i] = MMIO_IN32(pNv->FB_BAR, i * 4);
1205                 else
1206                         MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[3][i]);
1207
1208         /* restore control regs */
1209         NVWritePRMVIO(pNv, 0, VGA_MISC_OUT_W, misc);
1210         NVWriteVgaGr(pNv, 0, VGA_GFX_PLANE_READ, gr4);
1211         NVWriteVgaGr(pNv, 0, VGA_GFX_MODE, gr5);
1212         NVWriteVgaGr(pNv, 0, VGA_GFX_MISC, gr6);
1213         NVWriteVgaSeq(pNv, 0, VGA_SEQ_PLANE_WRITE, seq2);
1214         NVWriteVgaSeq(pNv, 0, VGA_SEQ_MEMORY_MODE, seq4);
1215
1216         if (pNv->twoHeads)
1217                 NVBlankScreen(pNv, 1, false);
1218         NVBlankScreen(pNv, 0, false);
1219 }