~ubuntu-branches/ubuntu/trusty/xserver-xorg-video-nouveau/trusty

« back to all changes in this revision

Viewing changes to src/nv_hw.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Lamb
  • Date: 2008-07-06 20:26:53 UTC
  • Revision ID: james.westby@ubuntu.com-20080706202653-e99oiii765j3a0qn
Tags: upstream-0.0.10~git+20080706+b1f3169
ImportĀ upstreamĀ versionĀ 0.0.10~git+20080706+b1f3169

Show diffs side-by-side

added added

removed removed

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