Use pll_lims in getMNP_double
[nouveau] / src / nv_bios.c
1 /*
2  * Copyright 2005-2006 Erik Waling
3  * Copyright 2006 Stephane Marchesin
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 "nvreg.h"
26 #include <byteswap.h>
27
28 /* FIXME: put these somewhere */
29 #define CRTC_INDEX_COLOR (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET)
30 #define NV_VGA_CRTCX_OWNER_HEADA 0x0
31 #define NV_VGA_CRTCX_OWNER_HEADB 0x3
32 #define NV_PBUS_PCI_NV_19 0x0000184C
33 #define NV_PBUS_PCI_NV_20 0x00001850
34 #define NV_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED 0x00000000
35 #define NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED 0x00000001
36 #define NV_PEXTDEV_BOOT_0 0x00101000
37 /* undef, as we want the +0x00100000 version */
38 #undef NV_PFB_CFG0
39 #define NV_PFB_CFG0 0x00100200
40 #define NV_PFB_REFCTRL 0x00100210
41 #define NV_PFB_REFCTRL_VALID_1 0x80000000
42 #define NV_PRAMIN_ROM_OFFSET 0x00700000
43
44 #define DEBUGLEVEL 6
45
46 /* TODO: 
47  *       * PLL algorithms.
48  */
49
50 static int crtchead = 0;
51
52 /* this will need remembering across a suspend */
53 static uint32_t saved_nv_pfb_cfg0;
54
55 typedef struct {
56         Bool execute;
57         Bool repeat;
58 } init_exec_t;
59
60 static uint16_t le16_to_cpu(const uint16_t x)
61 {
62 #if X_BYTE_ORDER == X_BIG_ENDIAN
63         return bswap_16(x);
64 #else
65         return x;
66 #endif
67 }
68
69 static uint32_t le32_to_cpu(const uint32_t x)
70 {
71 #if X_BYTE_ORDER == X_BIG_ENDIAN
72         return bswap_32(x);
73 #else
74         return x;
75 #endif
76 }
77
78 static Bool nv_cksum(const uint8_t *data, unsigned int length)
79 {
80         /* there's a few checksums in the BIOS, so here's a generic checking function */
81         int i;
82         uint8_t sum = 0;
83
84         for (i = 0; i < length; i++)
85                 sum += data[i];
86
87         if (sum)
88                 return TRUE;
89
90         return FALSE;
91 }
92
93 static int NVValidVBIOS(ScrnInfoPtr pScrn, const uint8_t *data)
94 {
95         /* check for BIOS signature */
96         if (!(data[0] == 0x55 && data[1] == 0xAA)) {
97                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
98                            "... BIOS signature not found\n");
99                 return 0;
100         }
101
102         if (nv_cksum(data, data[2] * 512)) {
103                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
104                            "... BIOS checksum invalid\n");
105                 /* probably ought to set a do_not_execute flag for table parsing here,
106                  * assuming most BIOSen are valid */
107                 return 1;
108         } else
109                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "... appears to be valid\n");
110
111         return 2;
112 }
113
114 static void NVShadowVBIOS_PROM(ScrnInfoPtr pScrn, uint8_t *data)
115 {
116         NVPtr pNv = NVPTR(pScrn);
117         int i;
118
119         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
120                    "Attempting to locate BIOS image in PROM\n");
121
122         /* enable ROM access */
123         nvWriteMC(pNv, NV_PBUS_PCI_NV_20, NV_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED);
124         for (i = 0; i < NV_PROM_SIZE; i++) {
125                 /* according to nvclock, we need that to work around a 6600GT/6800LE bug */
126                 data[i] = pNv->PROM[i];
127                 data[i] = pNv->PROM[i];
128                 data[i] = pNv->PROM[i];
129                 data[i] = pNv->PROM[i];
130                 data[i] = pNv->PROM[i];
131         }
132         /* disable ROM access */
133         nvWriteMC(pNv, NV_PBUS_PCI_NV_20, NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED);
134 }
135
136 static void NVShadowVBIOS_PRAMIN(ScrnInfoPtr pScrn, uint32_t *data)
137 {
138         NVPtr pNv = NVPTR(pScrn);
139         const uint32_t *pramin = (uint32_t *)&pNv->REGS[NV_PRAMIN_ROM_OFFSET/4];
140         uint32_t old_bar0_pramin = 0;
141
142         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
143                    "Attempting to locate BIOS image in PRAMIN\n");
144
145         if (pNv->Architecture >= NV_ARCH_50) {
146                 uint32_t vbios_vram;
147
148                 vbios_vram = (pNv->REGS[0x619f04/4] & ~0xff) << 8;
149                 if (!vbios_vram) {
150                         vbios_vram = pNv->REGS[0x1700/4] << 16;
151                         vbios_vram += 0xf0000;
152                 }
153
154                 old_bar0_pramin = pNv->REGS[0x1700/4];
155                 pNv->REGS[0x1700/4] = vbios_vram >> 16;
156         }
157
158         memcpy(data, pramin, NV_PROM_SIZE);
159
160         if (pNv->Architecture >= NV_ARCH_50) {
161                 pNv->REGS[0x1700/4] = old_bar0_pramin;
162         }
163 }
164
165 static void NVVBIOS_PCIROM(ScrnInfoPtr pScrn, uint8_t *data)
166 {
167         NVPtr pNv = NVPTR(pScrn);
168
169         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
170                    "Attempting to use PCI ROM BIOS image\n");
171
172 #if XSERVER_LIBPCIACCESS
173         pci_device_read_rom(pNv->PciInfo, data);
174 #else
175         xf86ReadPciBIOS(0, pNv->PciTag, 0, data, NV_PROM_SIZE);
176 #endif
177 }
178
179 static Bool NVShadowVBIOS(ScrnInfoPtr pScrn, uint8_t *data)
180 {
181         NVShadowVBIOS_PROM(pScrn, data);
182         if (NVValidVBIOS(pScrn, data) == 2)
183                 return TRUE;
184
185         NVShadowVBIOS_PRAMIN(pScrn, (uint32_t *)data);
186         if (NVValidVBIOS(pScrn, data))
187                 return TRUE;
188
189 #ifndef __powerpc__
190         NVVBIOS_PCIROM(pScrn, data);
191         if (NVValidVBIOS(pScrn, data))
192                 return TRUE;
193 #endif
194
195         return FALSE;
196 }
197
198 typedef struct {
199         char* name;
200         uint8_t id;
201         int length;
202         int length_offset;
203         int length_multiplier;
204         Bool (*handler)(ScrnInfoPtr pScrn, bios_t *, uint16_t, init_exec_t *);
205 } init_tbl_entry_t;
206
207 typedef struct {
208         uint8_t id[2];
209         uint16_t length;
210         uint16_t offset;
211 } bit_entry_t;
212
213 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec);
214
215 #define MACRO_INDEX_SIZE        2
216 #define MACRO_SIZE              8
217 #define CONDITION_SIZE          12
218 #define IO_FLAG_CONDITION_SIZE  9 
219
220 void still_alive()
221 {
222 //      sync();
223 //      usleep(200);
224 }
225
226 static int nv_valid_reg(NVPtr pNv, uint32_t reg)
227 {
228         /* C51 has misaligned regs on purpose. Marvellous */
229         if ((reg & 0x3 && pNv->VBIOS.chip_version != 0x51) ||
230                         (reg & 0x2 && pNv->VBIOS.chip_version == 0x51)) {
231                 ErrorF("========== misaligned reg 0x%08X ==========\n", reg);
232                 return 0;
233         }
234
235         #define WITHIN(x,y,z) ((x>=y)&&(x<y+z))
236         if (WITHIN(reg,NV_PRAMIN_OFFSET,NV_PRAMIN_SIZE))
237                 return 1;
238         if (WITHIN(reg,NV_PCRTC0_OFFSET,NV_PCRTC0_SIZE))
239                 return 1;
240         if (WITHIN(reg,NV_PRAMDAC0_OFFSET,NV_PRAMDAC0_SIZE))
241                 return 1;
242         if (WITHIN(reg,NV_PFB_OFFSET,NV_PFB_SIZE))
243                 return 1;
244         if (WITHIN(reg,NV_PFIFO_OFFSET,NV_PFIFO_SIZE))
245                 return 1;
246         if (WITHIN(reg,NV_PGRAPH_OFFSET,NV_PGRAPH_SIZE))
247                 return 1;
248         if (WITHIN(reg,NV_PEXTDEV_OFFSET,NV_PEXTDEV_SIZE))
249                 return 1;
250         if (WITHIN(reg,NV_PTIMER_OFFSET,NV_PTIMER_SIZE))
251                 return 1;
252         if (WITHIN(reg,NV_PVIDEO_OFFSET,NV_PVIDEO_SIZE))
253                 return 1;
254         if (WITHIN(reg,NV_PMC_OFFSET,NV_PMC_SIZE))
255                 return 1;
256         if (WITHIN(reg,NV_FIFO_OFFSET,NV_FIFO_SIZE))
257                 return 1;
258         if (WITHIN(reg,NV_PCIO0_OFFSET,NV_PCIO0_SIZE))
259                 return 1;
260         if (WITHIN(reg,NV_PDIO0_OFFSET,NV_PDIO0_SIZE))
261                 return 1;
262         if (WITHIN(reg,NV_PVIO_OFFSET,NV_PVIO_SIZE))
263                 return 1;
264         if (WITHIN(reg,NV_PROM_OFFSET,NV_PROM_SIZE))
265                 return 1;
266         if (WITHIN(reg,NV_PRAMIN_ROM_OFFSET,NV_PROM_SIZE))
267                 return 1;
268         /* NV40+ PBUS */
269         if (WITHIN(reg,0x88000,0x1000))
270                 return 1;
271         #undef WITHIN
272
273         ErrorF("========== unknown reg 0x%08X ==========\n", reg);
274
275         return 0;
276 }
277
278 static uint32_t nv32_rd(ScrnInfoPtr pScrn, uint32_t reg)
279 {
280         NVPtr pNv = NVPTR(pScrn);
281         uint32_t data;
282
283         if (!nv_valid_reg(pNv, reg))
284                 return 0;
285
286         /* C51 sometimes uses regs with bit0 set in the address. For these
287          * cases there should exist a translation in a BIOS table to an IO
288          * port address which the BIOS uses for accessing the reg
289          *
290          * These only seem to appear for the power control regs to a flat panel
291          * and in C51 mmio traces the normal regs for 0x1308 and 0x1310 are
292          * used - hence the mask below. An S3 suspend-resume mmio trace from a
293          * C51 will be required to see if this is true for the power microcode
294          * in 0x14.., or whether the direct IO port access method is needed
295          */
296         if (reg & 0x1)
297                 reg &= ~0x1;
298
299         data = pNv->REGS[reg/4];
300
301         if (DEBUGLEVEL >= 6)
302                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
303                            "    Read:  Reg: 0x%08X, Data: 0x%08X\n", reg, data);
304
305         return data;
306 }
307
308 static int nv32_wr(ScrnInfoPtr pScrn, uint32_t reg, uint32_t data)
309 {
310         NVPtr pNv = NVPTR(pScrn);
311
312         if (!nv_valid_reg(pNv, reg))
313                 return 0;
314
315         /* see note in nv32_rd */
316         if (reg & 0x1)
317                 reg &= 0xfffffffe;
318
319         if (DEBUGLEVEL >= 8)
320                 nv32_rd(pScrn, reg);
321         if (DEBUGLEVEL >= 6)
322                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
323                            "    Write: Reg: 0x%08X, Data: 0x%08X\n", reg, data);
324
325         if (pNv->VBIOS.execute) {
326                 still_alive();
327                 pNv->REGS[reg/4] = data;
328         }
329
330         return 1;
331 }
332
333 static uint8_t nv_idx_port_rd(ScrnInfoPtr pScrn, uint16_t port, uint8_t index)
334 {
335         NVPtr pNv = NVPTR(pScrn);
336         volatile uint8_t *ptr = crtchead ? pNv->PCIO1 : pNv->PCIO0;
337         uint8_t data;
338
339         VGA_WR08(ptr, port, index);
340         data = VGA_RD08(ptr, port + 1);
341
342         if (DEBUGLEVEL >= 6)
343                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
344                            "    Indexed read:  Port: 0x%04X, Index: 0x%02X, Head: 0x%02X, Data: 0x%02X\n",
345                            port, index, crtchead, data);
346
347         return data;
348 }
349
350 static void nv_idx_port_wr(ScrnInfoPtr pScrn, uint16_t port, uint8_t index, uint8_t data)
351 {
352         NVPtr pNv = NVPTR(pScrn);
353         volatile uint8_t *ptr;
354
355         /* The current head is maintained in a file scope variable crtchead.
356          * We trap changes to CRTCX_OWNER and update the head variable
357          * and hence the register set written.
358          * As CRTCX_OWNER only exists on CRTC0, we update crtchead to head0
359          * in advance of the write, and to head1 after the write
360          */
361         if (port == CRTC_INDEX_COLOR && index == NV_VGA_CRTCX_OWNER && data != NV_VGA_CRTCX_OWNER_HEADB)
362                 crtchead = 0;
363         ptr = crtchead ? pNv->PCIO1 : pNv->PCIO0;
364
365         if (DEBUGLEVEL >= 8)
366                 nv_idx_port_rd(pScrn, port, index);
367         if (DEBUGLEVEL >= 6)
368                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
369                            "    Indexed write: Port: 0x%04X, Index: 0x%02X, Head: 0x%02X, Data: 0x%02X\n",
370                            port, index, crtchead, data);
371
372         if (pNv->VBIOS.execute) {
373                 still_alive();
374                 VGA_WR08(ptr, port, index);
375                 VGA_WR08(ptr, port + 1, data);
376         }
377
378         if (port == CRTC_INDEX_COLOR && index == NV_VGA_CRTCX_OWNER && data == NV_VGA_CRTCX_OWNER_HEADB)
379                 crtchead = 1;
380 }
381
382 #define ACCESS_UNLOCK 0
383 #define ACCESS_LOCK 1
384 static void crtc_access(ScrnInfoPtr pScrn, Bool lock)
385 {
386         NVPtr pNv = NVPTR(pScrn);
387         int savedhead = crtchead;
388         uint8_t cr11;
389
390         /* necessary external dependancy (twoHeads) */
391         if (pNv->twoHeads)
392                 nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, NV_VGA_CRTCX_OWNER, NV_VGA_CRTCX_OWNER_HEADA);
393         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, NV_VGA_CRTCX_LOCK, lock ? 0x99 : 0x57);
394         cr11 = nv_idx_port_rd(pScrn, CRTC_INDEX_COLOR, NV_VGA_CRTCX_VSYNCE);
395         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, NV_VGA_CRTCX_VSYNCE, lock ? cr11 | 0x80 : cr11 & ~0x80);
396
397         if (pNv->twoHeads) {
398                 nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, NV_VGA_CRTCX_OWNER, NV_VGA_CRTCX_OWNER_HEADB);
399                 nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, NV_VGA_CRTCX_LOCK, lock ? 0x99 : 0x57);
400                 cr11 = nv_idx_port_rd(pScrn, CRTC_INDEX_COLOR, NV_VGA_CRTCX_VSYNCE);
401                 nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, NV_VGA_CRTCX_VSYNCE, lock ? cr11 | 0x80 : cr11 & ~0x80);
402         }
403
404         crtchead = savedhead;
405 }
406
407 static Bool io_flag_condition(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, uint8_t cond)
408 {
409         /* The IO flag condition entry has 2 bytes for the CRTC port; 1 byte
410          * for the CRTC index; 1 byte for the mask to apply to the value
411          * retrieved from the CRTC; 1 byte for the shift right to apply to the
412          * masked CRTC value; 2 bytes for the offset to the flag array, to
413          * which the shifted value is added; 1 byte for the mask applied to the
414          * value read from the flag array; and 1 byte for the value to compare
415          * against the masked byte from the flag table.
416          */
417
418         uint16_t condptr = bios->io_flag_condition_tbl_ptr + cond * IO_FLAG_CONDITION_SIZE;
419         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[condptr])));
420         uint8_t crtcindex = bios->data[condptr + 2];
421         uint8_t mask = bios->data[condptr + 3];
422         uint8_t shift = bios->data[condptr + 4];
423         uint16_t flagarray = le16_to_cpu(*((uint16_t *)(&bios->data[condptr + 5])));
424         uint8_t flagarraymask = bios->data[condptr + 7];
425         uint8_t cmpval = bios->data[condptr + 8];
426         uint8_t data;
427
428         if (DEBUGLEVEL >= 6)
429                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
430                            "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, FlagArray: 0x%04X, FAMask: 0x%02X, Cmpval: 0x%02X\n",
431                            offset, crtcport, crtcindex, mask, shift, flagarray, flagarraymask, cmpval);
432
433         data = nv_idx_port_rd(pScrn, crtcport, crtcindex);
434
435         data = bios->data[flagarray + ((data & mask) >> shift)];
436         data &= flagarraymask;
437
438         if (DEBUGLEVEL >= 6)
439                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
440                            "0x%04X: Checking if 0x%02X equals 0x%02X\n",
441                            offset, data, cmpval);
442
443         if (data == cmpval)
444                 return TRUE;
445
446         return FALSE;
447 }
448
449 uint32_t getMNP_single(ScrnInfoPtr pScrn, uint32_t clk, int *bestNM, int *bestlog2P)
450 {
451         /* Find M, N and P for a single stage PLL
452          *
453          * Note that some bioses (NV3x) have lookup tables of precomputed MNP
454          * values, but we're too lazy to use those atm
455          *
456          * "clk" parameter in kHz
457          * returns calculated clock
458          */
459
460         bios_t *bios = &NVPTR(pScrn)->VBIOS;
461         int maxM = 0, M, N;
462         int maxlog2P, log2P, P;
463         int crystal = 0;
464         uint32_t minvco = bios->fminvco;
465         uint32_t maxvco = bios->fmaxvco;
466         int clkP;
467         int calcclk, delta;
468         unsigned int bestdelta = UINT_MAX;
469         uint32_t bestclk = 0;
470
471         unsigned int crystal_strap_mask = 1 << 6;
472         /* open coded pNv->twoHeads test */
473         if (bios->chip_version > 0x10 && bios->chip_version != 0x15 &&
474             bios->chip_version != 0x1a && bios->chip_version != 0x20)
475                 crystal_strap_mask |= 1 << 22;
476         switch (nv32_rd(pScrn, NV_PEXTDEV_BOOT_0) & crystal_strap_mask) {
477         case 0:
478                 maxM = 13;
479                 crystal = 13500;
480                 break;
481         case (1 << 6):
482                 maxM = 14;
483                 crystal = 14318;
484                 break;
485         case (1 << 22):
486         case (1 << 22 | 1 << 6):
487                 maxM = 14;
488                 crystal = 27000;
489                 break;
490         }
491
492         /* this division verified for nv20, nv28 (Haiku), nv34 -- nv17 is guessed */
493         /* possibly correlated with introduction of 27MHz crystal */
494         if (bios->chip_version <= 0x16 || bios->chip_version == 0x20) {
495                 if (clk > 250000)
496                         maxM = 6;
497                 if (clk > 340000)
498                         maxM = 2;
499                 maxlog2P = 4;
500         } else {
501                 if (clk > 150000)
502                         maxM = 6;
503                 if (clk > 200000)
504                         maxM = 4;
505                 if (clk > 340000)
506                         maxM = 2;
507                 maxlog2P = 5;
508         }
509
510         if ((clk << maxlog2P) < minvco) {
511                 minvco = clk << maxlog2P;
512                 maxvco = minvco * 2;
513         }
514         if (clk + clk/200 > maxvco)     /* +0.5% */
515                 maxvco = clk + clk/200;
516
517         /* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */
518         for (log2P = 0; log2P <= maxlog2P; log2P++) {
519                 P = 1 << log2P;
520                 clkP = clk * P;
521                 if (clkP < minvco)
522                         continue;
523                 if (clkP > maxvco)
524                         return bestclk;
525
526                 /* nv_hw.c in nv driver uses 7 and 8 for minM */
527                 for (M = 1; M <= maxM; M++) {
528                         /* add crystal/2 to round better */
529                         N = (clkP * M + crystal/2) / crystal;
530                         if (N > 256)    /* we lost */
531                                 goto nextP;
532
533                         /* more rounding additions */
534                         calcclk = ((N * crystal + P/2) / P + M/2) / M;
535                         delta = abs(calcclk - clk);
536                         /* we do an exhaustive search rather than terminating
537                          * on an optimality condition...
538                          */
539                         if (delta < bestdelta) {
540                                 bestdelta = delta;
541                                 bestclk = calcclk;
542                                 *bestNM = N << 8 | M;
543                                 *bestlog2P = log2P;
544                                 if (delta == 0) /* except this one */
545                                         return bestclk;
546                         }
547                 }
548 nextP:
549                 continue;
550         }
551
552         return bestclk;
553 }
554
555 uint32_t getMNP_double(ScrnInfoPtr pScrn, struct pll_lims *pll_lim, uint32_t clk, int *bestNM1, int *bestNM2, int *bestlog2P)
556 {
557         /* Find M, N and P for a two stage PLL
558          *
559          * Note that some bioses (NV30+) have lookup tables of precomputed MNP
560          * values, but we're too lazy to use those atm
561          *
562          * "clk" parameter in kHz
563          * returns calculated clock
564          */
565
566         struct pll_lims pll_lim;
567
568         if (!get_pll_limits(pScrn, reg, &pll_lim))
569                 return 0;
570
571         int crystal = 0;
572         int minvco1 = pll_lim->vco1.minfreq, maxvco1 = pll_lim->vco1.maxfreq;
573         int minvco2 = pll_lim->vco2.minfreq, maxvco2 = pll_lim->vco2.maxfreq;
574         int minU1 = pll_lim->vco1.min_inputfreq, minU2 = pll_lim->vco2.min_inputfreq;
575         int maxU1 = pll_lim->vco1.max_inputfreq, maxU2 = pll_lim->vco2.max_inputfreq;
576         int minM1 = pll_lim->vco1.min_m, maxM1 = pll_lim->vco1.max_m;
577         int minN1 = pll_lim->vco1.min_n, maxN1 = pll_lim->vco1.max_n;
578         int minM2 = pll_lim->vco2.min_m, maxM2 = pll_lim->vco2.max_m;
579         int minN2 = pll_lim->vco2.min_n, maxN2 = pll_lim->vco2.max_n;
580         int M1, N1, M2, N2, log2P;
581         int clkP, calcclk1, calcclk2, calcclkout;
582         int delta, bestdelta = INT_MAX;
583         int bestclk = 0;
584
585         if (pll_lim->refclk)
586                 crystal = pll_lim->refclk;
587         else
588                 switch (nv32_rd(pScrn, NV_PEXTDEV_BOOT_0) & (1 << 22 | 1 << 6)) {
589                 case 0:
590                         crystal = 13500;
591                         break;
592                 case (1 << 6):
593                         crystal = 14318;
594                         break;
595                 case (1 << 22):
596                         crystal = 27000;
597                         break;
598                 case (1 << 22 | 1 << 6):
599                         crystal = 25000;
600                         break;
601                 }
602
603         int vco2 = (maxvco2 - maxvco2/200) / 2;
604         for (log2P = 0; log2P < 6 && clk <= (vco2 >> log2P); log2P++) /* log2P is maximum of 6 */
605                 ;
606         clkP = clk << log2P;
607
608         if (maxvco2 < clk + clk/200)    /* +0.5% */
609                 maxvco2 = clk + clk/200;
610
611         for (M1 = minM1; M1 <= maxM1; M1++) {
612                 if (crystal/M1 < minU1)
613                         return bestclk;
614                 if (crystal/M1 > maxU1)
615                         continue;
616
617                 for (N1 = minN1; N1 <= maxN1; N1++) {
618                         calcclk1 = crystal * N1 / M1;
619                         if (calcclk1 < minvco1)
620                                 continue;
621                         if (calcclk1 > maxvco1)
622                                 break;
623
624                         for (M2 = minM2; M2 <= maxM2; M2++) {
625                                 if (calcclk1/M2 < minU2)
626                                         break;
627                                 if (calcclk1/M2 > maxU2)
628                                         continue;
629
630                                 /* add calcclk1/2 to round better */
631                                 N2 = (clkP * M2 + calcclk1/2) / calcclk1;
632                                 if (N2 < minN2)
633                                         continue;
634                                 if (N2 > maxN2)
635                                         break;
636
637                                 if (N2/M2 < 4 || N2/M2 > 10)
638                                         continue;
639
640                                 calcclk2 = calcclk1 * N2 / M2;
641                                 if (calcclk2 < minvco2)
642                                         break;
643                                 if (calcclk2 > maxvco2)
644                                         continue;
645
646                                 calcclkout = calcclk2 >> log2P;
647                                 delta = abs(calcclkout - clk);
648                                 /* we do an exhaustive search rather than terminating
649                                  * on an optimality condition...
650                                  */
651                                 if (delta < bestdelta) {
652                                         bestdelta = delta;
653                                         bestclk = calcclkout;
654                                         *bestNM1 = N1 << 8 | M1;
655                                         *bestNM2 = N2 << 8 | M2;
656                                         *bestlog2P = log2P;
657                                         if (delta == 0) /* except this one */
658                                                 return bestclk;
659                                 }
660                         }
661                 }
662         }
663
664         return bestclk;
665 }
666
667 static void setPLL_single(ScrnInfoPtr pScrn, uint32_t reg, int NM, int log2P)
668 {
669         uint32_t pll;
670
671         pll = nv32_rd(pScrn, reg);
672         if (pll == (log2P << 16 | NM))
673                 return; /* already set */
674
675 #if 0
676         //this stuff is present on my nv34 and something similar on the nv31
677         //it is not on nv20, and I don't know how useful or necessary it is
678
679         uint32_t saved_1584, shift_1584;
680         Bool frob1584 = FALSE;
681         switch (reg) {
682         case 0x680500:
683                 shift_1584 = 0;
684                 frob1584 = TRUE;
685                 break;
686         case 0x680504:
687                 shift_1584 = 4;
688                 frob1584 = TRUE;
689                 break;
690         case 0x680508:
691                 shift_1584 = 8;
692                 frob1584 = TRUE;
693                 break;
694         case 0x680520:
695                 shift_1584 = 12;
696                 frob1584 = TRUE;
697                 break;
698         }
699
700         if (frob1584) {
701                 saved_1584 = nv32_rd(pScrn, 0x00001584);
702                 nv32_wr(pScrn, 0x00001584, (saved_1584 & ~(0xf << shift_1584)) | 1 << shift_1584);
703         }
704 #endif
705
706         /* write NM first */
707         pll = (pll & 0xffff0000) | NM;
708         nv32_wr(pScrn, reg, pll);
709
710         /* wait a bit */
711         usleep(64000);
712         nv32_rd(pScrn, reg);
713
714         /* then write P as well */
715         nv32_wr(pScrn, reg, (pll & 0xfff8ffff) | log2P << 16);
716
717 #if 0
718         if (frob1584)
719                 nv32_wr(pScrn, 0x00001584, saved_1584);
720 #endif
721 }
722
723 static void setPLL_double(ScrnInfoPtr pScrn, uint32_t reg1, int NM1, int NM2, int log2P)
724 {
725         uint32_t reg2, pll1, pll2;
726
727         reg2 = reg1 + 0x70;
728         if (reg2 == 0x680590)
729                 reg2 = NV_RAMDAC_VPLL2_B;
730
731         pll1 = nv32_rd(pScrn, reg1);
732         pll2 = nv32_rd(pScrn, reg2);
733         if (pll1 == (log2P << 16 | NM1) && pll2 == (1 << 31 | NM2))
734                 return; /* already set */
735
736 #if 0
737         //this stuff is present on my nv31
738         //I don't know how useful or necessary it is
739
740         uint32_t saved_1584, shift_1584;
741         Bool frob1584 = FALSE;
742         switch (reg1) {
743         case 0x680500:
744                 shift_1584 = 0;
745                 frob1584 = TRUE;
746                 break;
747         case 0x680504:
748                 shift_1584 = 4;
749                 frob1584 = TRUE;
750                 break;
751         }
752
753         if (frob1584) {
754                 saved_1584 = nv32_rd(pScrn, 0x00001584);
755                 nv32_wr(pScrn, 0x00001584, (saved_1584 & ~(0xf << shift_1584)) | 1 << shift_1584);
756         }
757 #endif
758
759         nv32_wr(pScrn, reg2, (pll2 & 0x7fff0000) | NM2);
760         nv32_wr(pScrn, reg1, (pll1 & 0xfff80000) | log2P << 16 | NM1);
761
762 #if 0
763         if (frob1584)
764                 nv32_wr(pScrn, 0x00001584, saved_1584);
765 #endif
766 }
767
768 Bool get_pll_limits(ScrnInfoPtr pScrn, enum pll_types plltype, struct pll_lims *pll_lim);
769
770 static void setPLL(ScrnInfoPtr pScrn, bios_t *bios, uint32_t reg, uint32_t clk)
771 {
772         /* clk in kHz */
773         int NM1, NM2, log2P;
774
775         // FIXME: both getMNP versions will need some alterations for nv40 type stuff
776         if (bios->chip_version >= 0x40 || bios->chip_version == 0x31 || bios->chip_version == 0x36) {
777                 struct pll_lims pll_lim;
778                 // for NV40, pll_type will need setting
779                 get_pll_limits(pScrn, 0, &pll_lim);
780                 getMNP_double(pScrn, &pll_lim, clk, &NM1, &NM2, &log2P);
781                 setPLL_double(pScrn, reg, NM1, NM2, log2P);
782         } else {
783                 getMNP_single(pScrn, clk, &NM1, &log2P);
784                 setPLL_single(pScrn, reg, NM1, log2P);
785         }
786 }
787
788 #if 0
789 static Bool init_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
790 {
791         /* INIT_PROG   opcode: 0x31
792          * 
793          * offset      (8  bit): opcode
794          * offset + 1  (32 bit): reg
795          * offset + 5  (32 bit): and mask
796          * offset + 9  (8  bit): shift right
797          * offset + 10 (8  bit): number of configurations
798          * offset + 11 (32 bit): register
799          * offset + 15 (32 bit): configuration 1
800          * ...
801          * 
802          * Starting at offset + 15 there are "number of configurations"
803          * 32 bit values. To find out which configuration value to use
804          * read "CRTC reg" on the CRTC controller with index "CRTC index"
805          * and bitwise AND this value with "and mask" and then bit shift the
806          * result "shift right" bits to the right.
807          * Assign "register" with appropriate configuration value.
808          */
809
810         CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
811         CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
812         CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 9]));
813         CARD8 nr = *((CARD8 *) (&bios->data[offset + 10]));
814         CARD32 reg2 = *((CARD32 *) (&bios->data[offset + 11]));
815         CARD8 configuration;
816         CARD32 configval, tmp;
817
818         if (iexec->execute) {
819                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%04X\n", offset, 
820                                 reg);
821
822                 tmp = nv32_rd(pScrn, reg);
823                 configuration = (tmp & and) >> shiftr;
824
825                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONFIGURATION TO USE: 0x%02X\n", 
826                                 offset, configuration);
827
828                 if (configuration <= nr) {
829
830                         configval = 
831                                 *((CARD32 *) (&bios->data[offset + 15 + configuration * 4]));
832
833                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, 
834                                         reg2, configval);
835                         
836                         tmp = nv32_rd(pScrn, reg2);
837                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n",
838                                 offset, tmp);
839                         nv32_wr(pScrn, reg2, configval);
840                 }
841         }
842         return TRUE;
843 }
844 #endif
845
846 static Bool init_io_restrict_prog(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
847 {
848         /* INIT_IO_RESTRICT_PROG   opcode: 0x32 ('2')
849          *
850          * offset      (8  bit): opcode
851          * offset + 1  (16 bit): CRTC port
852          * offset + 3  (8  bit): CRTC index
853          * offset + 4  (8  bit): mask
854          * offset + 5  (8  bit): shift
855          * offset + 6  (8  bit): count
856          * offset + 7  (32 bit): register
857          * offset + 11 (32 bit): configuration 1
858          * ...
859          *
860          * Starting at offset + 11 there are "count" 32 bit values.
861          * To find out which value to use read index "CRTC index" on "CRTC port",
862          * AND this value with "mask" and then bit shift right "shift" bits.
863          * Read the appropriate value using this index and write to "register"
864          */
865
866         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
867         uint8_t crtcindex = bios->data[offset + 3];
868         uint8_t mask = bios->data[offset + 4];
869         uint8_t shift = bios->data[offset + 5];
870         uint8_t count = bios->data[offset + 6];
871         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 7])));
872         uint8_t config;
873         uint32_t configval;
874
875         if (!iexec->execute)
876                 return TRUE;
877
878         if (DEBUGLEVEL >= 6)
879                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
880                            "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n",
881                            offset, crtcport, crtcindex, mask, shift, count, reg);
882
883         config = (nv_idx_port_rd(pScrn, crtcport, crtcindex) & mask) >> shift;
884         if (config > count) {
885                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
886                            "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
887                            offset, config, count);
888                 return FALSE;
889         }
890
891         configval = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 11 + config * 4])));
892
893         if (DEBUGLEVEL >= 6)
894                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
895                            "0x%04X: Writing config %02X\n", offset, config);
896
897         nv32_wr(pScrn, reg, configval);
898
899         return TRUE;
900 }
901
902 static Bool init_repeat(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
903 {
904         /* INIT_REPEAT   opcode: 0x33 ('3')
905          *
906          * offset      (8 bit): opcode
907          * offset + 1  (8 bit): count
908          *
909          * Execute script following this opcode up to INIT_REPEAT_END
910          * "count" times
911          */
912
913         uint8_t count = bios->data[offset + 1];
914         uint8_t i;
915
916         /* no iexec->execute check by design */
917
918         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
919                    "0x%04X: REPEATING FOLLOWING SEGMENT %d TIMES\n",
920                    offset, count);
921
922         iexec->repeat = TRUE;
923
924         /* count - 1, as the script block will execute once when we leave this
925          * opcode -- this is compatible with bios behaviour as:
926          * a) the block is always executed at least once, even if count == 0
927          * b) the bios interpreter skips to the op following INIT_END_REPEAT,
928          * while we don't
929          */
930         for (i = 0; i < count - 1; i++)
931                 parse_init_table(pScrn, bios, offset + 2, iexec);
932
933         iexec->repeat = FALSE;
934
935         return TRUE;
936 }
937
938 static Bool init_io_restrict_pll(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
939 {
940         /* INIT_IO_RESTRICT_PLL   opcode: 0x34 ('4')
941          *
942          * offset      (8  bit): opcode
943          * offset + 1  (16 bit): CRTC port
944          * offset + 3  (8  bit): CRTC index
945          * offset + 4  (8  bit): mask
946          * offset + 5  (8  bit): shift
947          * offset + 6  (8  bit): IO flag condition index
948          * offset + 7  (8  bit): count
949          * offset + 8  (32 bit): register
950          * offset + 12 (16 bit): frequency 1
951          * ...
952          *
953          * Starting at offset + 12 there are "count" 16 bit frequencies (10kHz).
954          * Set PLL register "register" to coefficients for frequency n,
955          * selected by reading index "CRTC index" of "CRTC port" ANDed with
956          * "mask" and shifted right by "shift". If "IO flag condition index" > 0,
957          * and condition met, double frequency before setting it.
958          */
959
960         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
961         uint8_t crtcindex = bios->data[offset + 3];
962         uint8_t mask = bios->data[offset + 4];
963         uint8_t shift = bios->data[offset + 5];
964         int8_t io_flag_condition_idx = bios->data[offset + 6];
965         uint8_t count = bios->data[offset + 7];
966         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 8])));
967         uint8_t config;
968         uint16_t freq;
969
970         if (!iexec->execute)
971                 return TRUE;
972
973         if (DEBUGLEVEL >= 6)
974                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
975                            "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, IO Flag Condition: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n",
976                            offset, crtcport, crtcindex, mask, shift, io_flag_condition_idx, count, reg);
977
978         config = (nv_idx_port_rd(pScrn, crtcport, crtcindex) & mask) >> shift;
979         if (config > count) {
980                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
981                            "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
982                            offset, config, count);
983                 return FALSE;
984         }
985
986         freq = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 12 + config * 2])));
987
988         if (io_flag_condition_idx > 0) {
989                 if (io_flag_condition(pScrn, bios, offset, io_flag_condition_idx)) {
990                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
991                                    "0x%04X: CONDITION FULFILLED - FREQ DOUBLED\n", offset);
992                         freq *= 2;
993                 } else
994                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
995                                    "0x%04X: CONDITION IS NOT FULFILLED. FREQ UNCHANGED\n", offset);
996         }
997
998         if (DEBUGLEVEL >= 6)
999                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1000                            "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %d0kHz\n",
1001                            offset, reg, config, freq);
1002
1003         setPLL(pScrn, bios, reg, freq * 10);
1004
1005         return TRUE;
1006 }
1007
1008 static Bool init_end_repeat(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1009 {
1010         /* INIT_END_REPEAT   opcode: 0x36 ('6')
1011          *
1012          * offset      (8 bit): opcode
1013          *
1014          * Marks the end of the block for INIT_REPEAT to repeat
1015          */
1016
1017         /* no iexec->execute check by design */
1018
1019         /* iexec->repeat flag necessary to go past INIT_END_REPEAT opcode when
1020          * we're not in repeat mode
1021          */
1022         if (iexec->repeat)
1023                 return FALSE;
1024
1025         return TRUE;
1026 }
1027
1028 static Bool init_copy(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1029 {
1030         /* INIT_COPY   opcode: 0x37 ('7')
1031          *
1032          * offset      (8  bit): opcode
1033          * offset + 1  (32 bit): register
1034          * offset + 5  (8  bit): shift
1035          * offset + 6  (8  bit): srcmask
1036          * offset + 7  (16 bit): CRTC port
1037          * offset + 9  (8 bit): CRTC index
1038          * offset + 10  (8 bit): mask
1039          *
1040          * Read index "CRTC index" on "CRTC port", AND with "mask", OR with
1041          * (REGVAL("register") >> "shift" & "srcmask") and write-back to CRTC port
1042          */
1043
1044         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1045         uint8_t shift = bios->data[offset + 5];
1046         uint8_t srcmask = bios->data[offset + 6];
1047         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 7])));
1048         uint8_t crtcindex = bios->data[offset + 9];
1049         uint8_t mask = bios->data[offset + 10];
1050         uint32_t data;
1051         uint8_t crtcdata;
1052
1053         if (!iexec->execute)
1054                 return TRUE;
1055
1056         if (DEBUGLEVEL >= 6)
1057                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1058                            "0x%04X: Reg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%02X, Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X\n",
1059                            offset, reg, shift, srcmask, crtcport, crtcindex, mask);
1060
1061         data = nv32_rd(pScrn, reg);
1062
1063         if (shift < 0x80)
1064                 data >>= shift;
1065         else
1066                 data <<= (0x100 - shift);
1067
1068         data &= srcmask;
1069
1070         crtcdata = (nv_idx_port_rd(pScrn, crtcport, crtcindex) & mask) | (uint8_t)data;
1071         nv_idx_port_wr(pScrn, crtcport, crtcindex, crtcdata);
1072
1073         return TRUE;
1074 }
1075
1076 static Bool init_not(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1077 {
1078         /* INIT_NOT   opcode: 0x38 ('8')
1079          *
1080          * offset      (8  bit): opcode
1081          *
1082          * Invert the current execute / no-execute condition (i.e. "else")
1083          */
1084         if (iexec->execute)
1085                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1086                            "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
1087         else
1088                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1089                            "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n", offset);
1090
1091         iexec->execute = !iexec->execute;
1092         return TRUE;
1093 }
1094
1095 static Bool init_io_flag_condition(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1096 {
1097         /* INIT_IO_FLAG_CONDITION   opcode: 0x39 ('9')
1098          *
1099          * offset      (8 bit): opcode
1100          * offset + 1  (8 bit): condition number
1101          *
1102          * Check condition "condition number" in the IO flag condition table.
1103          * If condition not met skip subsequent opcodes until condition
1104          * is inverted (INIT_NOT), or we hit INIT_RESUME
1105          */
1106
1107         uint8_t cond = bios->data[offset + 1];
1108
1109         if (!iexec->execute)
1110                 return TRUE;
1111
1112         if (io_flag_condition(pScrn, bios, offset, cond))
1113                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1114                            "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n", offset);
1115         else {
1116                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1117                            "0x%04X: CONDITION IS NOT FULFILLED\n", offset);
1118                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1119                            "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
1120                 iexec->execute = FALSE;
1121         }
1122
1123         return TRUE;
1124 }
1125
1126 Bool init_idx_addr_latched(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1127 {
1128         /* INIT_INDEX_ADDRESS_LATCHED   opcode: 0x49 ('I')
1129          *
1130          * offset      (8  bit): opcode
1131          * offset + 1  (32 bit): control register
1132          * offset + 5  (32 bit): data register
1133          * offset + 9  (32 bit): mask
1134          * offset + 13 (32 bit): data
1135          * offset + 17 (8  bit): count
1136          * offset + 18 (8  bit): address 1
1137          * offset + 19 (8  bit): data 1
1138          * ...
1139          *
1140          * For each of "count" address and data pairs, write "data n" to "data register",
1141          * read the current value of "control register", and write it back once ANDed
1142          * with "mask", ORed with "data", and ORed with "address n"
1143          */
1144
1145         uint32_t controlreg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1146         uint32_t datareg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 5])));
1147         uint32_t mask = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 9])));
1148         uint32_t data = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 13])));
1149         uint8_t count = bios->data[offset + 17];
1150         uint32_t value;
1151         int i;
1152
1153         if (!iexec->execute)
1154                 return TRUE;
1155
1156         if (DEBUGLEVEL >= 6)
1157                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1158                            "0x%04X: ControlReg: 0x%08X, DataReg: 0x%08X, Mask: 0x%08X, Data: 0x%08X, Count: 0x%02X\n",
1159                            offset, controlreg, datareg, mask, data, count);
1160
1161         for (i = 0; i < count; i++) {
1162                 uint8_t instaddress = bios->data[offset + 18 + i * 2];
1163                 uint8_t instdata = bios->data[offset + 19 + i * 2];
1164
1165                 if (DEBUGLEVEL >= 6)
1166                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1167                                    "0x%04X: Address: 0x%02X, Data: 0x%02X\n", offset, instaddress, instdata);
1168
1169                 nv32_wr(pScrn, datareg, instdata);
1170                 value = (nv32_rd(pScrn, controlreg) & mask) | data | instaddress;
1171                 nv32_wr(pScrn, controlreg, value);
1172         }
1173
1174         return TRUE;
1175 }
1176
1177 static Bool init_io_restrict_pll2(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1178 {
1179         /* INIT_IO_RESTRICT_PLL2   opcode: 0x4A ('J')
1180          *
1181          * offset      (8  bit): opcode
1182          * offset + 1  (16 bit): CRTC port
1183          * offset + 3  (8  bit): CRTC index
1184          * offset + 4  (8  bit): mask
1185          * offset + 5  (8  bit): shift
1186          * offset + 6  (8  bit): count
1187          * offset + 7  (32 bit): register
1188          * offset + 11 (32 bit): frequency 1
1189          * ...
1190          *
1191          * Starting at offset + 11 there are "count" 32 bit frequencies (kHz).
1192          * Set PLL register "register" to coefficients for frequency n,
1193          * selected by reading index "CRTC index" of "CRTC port" ANDed with
1194          * "mask" and shifted right by "shift".
1195          */
1196
1197         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
1198         uint8_t crtcindex = bios->data[offset + 3];
1199         uint8_t mask = bios->data[offset + 4];
1200         uint8_t shift = bios->data[offset + 5];
1201         uint8_t count = bios->data[offset + 6];
1202         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 7])));
1203         uint8_t config;
1204         uint32_t freq;
1205
1206         if (!iexec->execute)
1207                 return TRUE;
1208
1209         if (DEBUGLEVEL >= 6)
1210                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1211                            "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n",
1212                            offset, crtcport, crtcindex, mask, shift, count, reg);
1213
1214         if (!reg)
1215                 return TRUE;
1216
1217         config = (nv_idx_port_rd(pScrn, crtcport, crtcindex) & mask) >> shift;
1218         if (config > count) {
1219                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1220                            "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
1221                            offset, config, count);
1222                 return FALSE;
1223         }
1224
1225         freq = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 11 + config * 4])));
1226
1227         if (DEBUGLEVEL >= 6)
1228                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1229                            "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %dkHz\n",
1230                            offset, reg, config, freq);
1231
1232         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
1233
1234         return TRUE;
1235 }
1236
1237 static Bool init_pll2(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1238 {
1239         /* INIT_PLL2   opcode: 0x4B ('K')
1240          *
1241          * offset      (8  bit): opcode
1242          * offset + 1  (32 bit): register
1243          * offset + 5  (32 bit): freq
1244          *
1245          * Set PLL register "register" to coefficients for frequency "freq"
1246          */
1247
1248         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1249         uint32_t freq = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 5])));
1250
1251         if (!iexec->execute)
1252                 return TRUE;
1253
1254         if (DEBUGLEVEL >= 6)
1255                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1256                            "0x%04X: Reg: 0x%04X, Freq: %dkHz\n",
1257                            offset, reg, freq);
1258
1259         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
1260
1261         return TRUE;
1262 }
1263
1264 static uint32_t get_tmds_index_reg(ScrnInfoPtr pScrn, uint8_t mlv)
1265 {
1266         /* For mlv < 0x80, it is an index into a table of TMDS base addresses
1267          * For mlv == 0x80 use the "or" value of the dcb_entry indexed by CR58 for CR57 = 0
1268          * to index a table of offsets to the basic 0x6808b0 address
1269          * For mlv == 0x81 use the "or" value of the dcb_entry indexed by CR58 for CR57 = 0
1270          * to index a table of offsets to the basic 0x6808b0 address, and then flip the offset by 8
1271          */
1272
1273         NVPtr pNv = NVPTR(pScrn);
1274         int pramdac_offset[13] = {0, 0, 0x8, 0, 0x2000, 0, 0, 0, 0x2008, 0, 0, 0, 0x2000};
1275         uint32_t pramdac_table[4] = {0x6808b0, 0x6808b8, 0x6828b0, 0x6828b8};
1276
1277         if (mlv >= 0x80) {
1278                 /* here we assume that the DCB table has already been parsed */
1279                 uint8_t dcb_entry;
1280                 int dacoffset;
1281                 /* This register needs to be written to set index for reading CR58 */
1282                 nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, 0x57, 0);
1283                 dcb_entry = nv_idx_port_rd(pScrn, CRTC_INDEX_COLOR, 0x58);
1284                 if (dcb_entry > pNv->dcb_table.entries) {
1285                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1286                                    "CR58 doesn't have a valid DCB entry currently (%02X)\n", dcb_entry);
1287                         return FALSE;
1288                 }
1289                 dacoffset = pramdac_offset[pNv->dcb_table.entry[dcb_entry].or];
1290                 if (mlv == 0x81)
1291                         dacoffset ^= 8;
1292                 return (0x6808b0 + dacoffset);
1293         } else {
1294                 if (mlv > (sizeof(pramdac_table) / sizeof(uint32_t))) {
1295                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1296                                    "Magic Lookup Value too big (%02X)\n", mlv);
1297                         return FALSE;
1298                 }
1299                 return pramdac_table[mlv];
1300         }
1301 }
1302
1303 static Bool init_tmds(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1304 {
1305         /* INIT_TMDS   opcode: 0x4F ('O')       (non-canon name)
1306          *
1307          * offset      (8 bit): opcode
1308          * offset + 1  (8 bit): magic lookup value
1309          * offset + 2  (8 bit): TMDS address
1310          * offset + 3  (8 bit): mask
1311          * offset + 4  (8 bit): data
1312          *
1313          * Read the data reg for TMDS address "TMDS address", AND it with mask
1314          * and OR it with data, then write it back
1315          * "magic lookup value" determines which TMDS base address register is used --
1316          * see get_tmds_index_reg()
1317          */
1318
1319         uint8_t mlv = bios->data[offset + 1];
1320         uint32_t tmdsaddr = bios->data[offset + 2];
1321         uint8_t mask = bios->data[offset + 3];
1322         uint8_t data = bios->data[offset + 4];
1323         uint32_t reg, value;
1324
1325         if (!iexec->execute)
1326                 return TRUE;
1327
1328         if (DEBUGLEVEL >= 6)
1329                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1330                            "0x%04X: MagicLookupValue: 0x%02X, TMDSAddr: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n",
1331                            offset, mlv, tmdsaddr, mask, data);
1332
1333         reg = get_tmds_index_reg(pScrn, mlv);
1334
1335         nv32_wr(pScrn, reg, tmdsaddr | 0x10000);
1336         value = (nv32_rd(pScrn, reg + 4) & mask) | data;
1337         nv32_wr(pScrn, reg + 4, value);
1338         nv32_wr(pScrn, reg, tmdsaddr);
1339
1340         return TRUE;
1341 }
1342
1343 Bool init_zm_tmds_group(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1344 {
1345         /* INIT_ZM_TMDS_GROUP   opcode: 0x50 ('P')      (non-canon name)
1346          *
1347          * offset      (8 bit): opcode
1348          * offset + 1  (8 bit): magic lookup value
1349          * offset + 2  (8 bit): count
1350          * offset + 3  (8 bit): addr 1
1351          * offset + 4  (8 bit): data 1
1352          * ...
1353          *
1354          * For each of "count" TMDS address and data pairs write "data n" to "addr n"
1355          * "magic lookup value" determines which TMDS base address register is used --
1356          * see get_tmds_index_reg()
1357          */
1358
1359         uint8_t mlv = bios->data[offset + 1];
1360         uint8_t count = bios->data[offset + 2];
1361         uint32_t reg;
1362         int i;
1363
1364         if (!iexec->execute)
1365                 return TRUE;
1366
1367         if (DEBUGLEVEL >= 6)
1368                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1369                            "0x%04X: MagicLookupValue: 0x%02X, Count: 0x%02X\n",
1370                            offset, mlv, count);
1371
1372         reg = get_tmds_index_reg(pScrn, mlv);
1373
1374         for (i = 0; i < count; i++) {
1375                 uint8_t tmdsaddr = bios->data[offset + 3 + i * 2];
1376                 uint8_t tmdsdata = bios->data[offset + 4 + i * 2];
1377
1378                 nv32_wr(pScrn, reg + 4, tmdsdata);
1379                 nv32_wr(pScrn, reg, tmdsaddr);
1380         }
1381
1382         return TRUE;
1383 }
1384
1385 Bool init_cr_idx_adr_latch(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1386 {
1387         /* INIT_CR_INDEX_ADDRESS_LATCHED   opcode: 0x51 ('Q')
1388          *
1389          * offset      (8 bit): opcode
1390          * offset + 1  (8 bit): CRTC index1
1391          * offset + 2  (8 bit): CRTC index2
1392          * offset + 3  (8 bit): baseaddr
1393          * offset + 4  (8 bit): count
1394          * offset + 5  (8 bit): data 1
1395          * ...
1396          *
1397          * For each of "count" address and data pairs, write "baseaddr + n" to
1398          * "CRTC index1" and "data n" to "CRTC index2"
1399          * Once complete, restore initial value read from "CRTC index1"
1400          */
1401         uint8_t crtcindex1 = bios->data[offset + 1];
1402         uint8_t crtcindex2 = bios->data[offset + 2];
1403         uint8_t baseaddr = bios->data[offset + 3];
1404         uint8_t count = bios->data[offset + 4];
1405         uint8_t oldaddr, data;
1406         int i;
1407
1408         if (!iexec->execute)
1409                 return TRUE;
1410
1411         if (DEBUGLEVEL >= 6)
1412                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1413                            "0x%04X: Index1: 0x%02X, Index2: 0x%02X, BaseAddr: 0x%02X, Count: 0x%02X\n",
1414                            offset, crtcindex1, crtcindex2, baseaddr, count);
1415
1416         oldaddr = nv_idx_port_rd(pScrn, CRTC_INDEX_COLOR, crtcindex1);
1417
1418         for (i = 0; i < count; i++) {
1419                 nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, crtcindex1, baseaddr + i);
1420
1421                 data = bios->data[offset + 5 + i];
1422                 nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, crtcindex2, data);
1423         }
1424
1425         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, crtcindex1, oldaddr);
1426
1427         return TRUE;
1428 }
1429
1430 Bool init_cr(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1431 {
1432         /* INIT_CR   opcode: 0x52 ('R')
1433          *
1434          * offset      (8  bit): opcode
1435          * offset + 1  (8  bit): CRTC index
1436          * offset + 2  (8  bit): mask
1437          * offset + 3  (8  bit): data
1438          *
1439          * Assign the value of at "CRTC index" ANDed with mask and ORed with data
1440          * back to "CRTC index"
1441          */
1442
1443         uint8_t crtcindex = bios->data[offset + 1];
1444         uint8_t mask = bios->data[offset + 2];
1445         uint8_t data = bios->data[offset + 3];
1446         uint8_t value;
1447
1448         if (!iexec->execute)
1449                 return TRUE;
1450
1451         if (DEBUGLEVEL >= 6)
1452                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1453                            "0x%04X: Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n",
1454                            offset, crtcindex, mask, data);
1455
1456         value = (nv_idx_port_rd(pScrn, CRTC_INDEX_COLOR, crtcindex) & mask) | data;
1457         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, crtcindex, value);
1458
1459         return TRUE;
1460 }
1461
1462 static Bool init_zm_cr(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1463 {
1464         /* INIT_ZM_CR   opcode: 0x53 ('S')
1465          *
1466          * offset      (8 bit): opcode
1467          * offset + 1  (8 bit): CRTC index
1468          * offset + 2  (8 bit): value
1469          *
1470          * Assign "value" to CRTC register with index "CRTC index".
1471          */
1472
1473         uint8_t crtcindex = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1474         uint8_t data = bios->data[offset + 2];
1475
1476         if (!iexec->execute)
1477                 return TRUE;
1478
1479         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, crtcindex, data);
1480
1481         return TRUE;
1482 }
1483
1484 static Bool init_zm_cr_group(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1485 {
1486         /* INIT_ZM_CR_GROUP   opcode: 0x54 ('T')
1487          *
1488          * offset      (8 bit): opcode
1489          * offset + 1  (8 bit): count
1490          * offset + 2  (8 bit): CRTC index 1
1491          * offset + 3  (8 bit): value 1
1492          * ...
1493          *
1494          * For "count", assign "value n" to CRTC register with index "CRTC index n".
1495          */
1496     
1497         uint8_t count = bios->data[offset + 1];
1498         int i;
1499
1500         if (!iexec->execute)
1501                 return TRUE;
1502
1503         for (i = 0; i < count; i++)
1504                 init_zm_cr(pScrn, bios, offset + 2 + 2 * i - 1, iexec);
1505
1506         return TRUE;
1507 }
1508
1509 static Bool init_condition_time(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1510 {
1511         /* INIT_CONDITION_TIME   opcode: 0x56 ('V')
1512          *
1513          * offset      (8 bit): opcode
1514          * offset + 1  (8 bit): condition number
1515          * offset + 2  (8 bit): retries / 50
1516          *
1517          * Check condition "condition number" in the condition table.
1518          * The condition table entry has 4 bytes for the address of the
1519          * register to check, 4 bytes for a mask and 4 for a test value.
1520          * If condition not met sleep for 2ms, and repeat upto "retries" times.
1521          * If still not met after retries, clear execution flag for this table.
1522          */
1523
1524         uint8_t cond = bios->data[offset + 1];
1525         uint16_t retries = bios->data[offset + 2];
1526         uint16_t condptr = bios->condition_tbl_ptr + cond * CONDITION_SIZE;
1527         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[condptr])));
1528         uint32_t mask = le32_to_cpu(*((uint32_t *)(&bios->data[condptr + 4])));
1529         uint32_t cmpval = le32_to_cpu(*((uint32_t *)(&bios->data[condptr + 8])));
1530         uint32_t data = 0;
1531
1532         if (!iexec->execute)
1533                 return TRUE;
1534
1535         retries *= 50;
1536
1537         if (DEBUGLEVEL >= 6)
1538                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1539                            "0x%04X: Cond: 0x%02X, Retries: 0x%02X\n", offset, cond, retries);
1540
1541         for (; retries > 0; retries--) {
1542                 data = nv32_rd(pScrn, reg) & mask;
1543
1544                 if (DEBUGLEVEL >= 6)
1545                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1546                                    "0x%04X: Checking if 0x%08X equals 0x%08X\n",
1547                                    offset, data, cmpval);
1548
1549                 if (data != cmpval) {
1550                         if (DEBUGLEVEL >= 6)
1551                                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1552                                            "0x%04X: Condition not met, sleeping for 2ms\n", offset);
1553                         usleep(2000);
1554                 } else {
1555                         if (DEBUGLEVEL >= 6)
1556                                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1557                                            "0x%04X: Condition met, continuing\n", offset);
1558                         break;
1559                 }
1560         }
1561
1562         if (data != cmpval) {
1563                 if (DEBUGLEVEL >= 6)
1564                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1565                                    "0x%04X: Condition still not met, skiping following opcodes\n", offset);
1566                 iexec->execute = FALSE;
1567         }
1568
1569         return TRUE;
1570 }
1571
1572 static Bool init_zm_reg_sequence(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1573 {
1574         /* INIT_ZM_REG_SEQUENCE   opcode: 0x58 ('X')
1575          *
1576          * offset      (8  bit): opcode
1577          * offset + 1  (32 bit): base register
1578          * offset + 5  (8  bit): count
1579          * offset + 6  (32 bit): value 1
1580          * ...
1581          *
1582          * Starting at offset + 6 there are "count" 32 bit values.
1583          * For "count" iterations set "base register" + 4 * current_iteration
1584          * to "value current_iteration"
1585          */
1586
1587         uint32_t basereg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1588         uint32_t count = bios->data[offset + 5];
1589         int i;
1590
1591         if (!iexec->execute)
1592                 return TRUE;
1593
1594         if (DEBUGLEVEL >= 6)
1595                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1596                            "0x%04X: BaseReg: 0x%08X, Count: 0x%02X\n",
1597                            offset, basereg, count);
1598
1599         for (i = 0; i < count; i++) {
1600                 uint32_t reg = basereg + i * 4;
1601                 uint32_t data = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 6 + i * 4])));
1602
1603                 nv32_wr(pScrn, reg, data);
1604         }
1605
1606         return TRUE;
1607 }
1608
1609 #if 0
1610 static Bool init_indirect_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1611 {
1612         /* INIT_INDIRECT_REG opcode: 0x5A
1613          *
1614          * offset      (8  bit): opcode
1615          * offset + 1  (32 bit): register
1616          * offset + 5  (16 bit): adress offset (in bios)
1617          *
1618          * Lookup value at offset data in the bios and write it to reg
1619          */
1620         CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1621         CARD16 data = le16_to_cpu(*((CARD16 *) (&bios->data[offset + 5])));
1622         CARD32 data2 = bios->data[data];
1623
1624         if (iexec->execute) {
1625                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1626                                 "0x%04X: REG: 0x%04X, DATA AT: 0x%04X, VALUE IS: 0x%08X\n", 
1627                                 offset, reg, data, data2);
1628
1629                 if (DEBUGLEVEL >= 6) {
1630                         CARD32 tmpval;
1631                         tmpval = nv32_rd(pScrn, reg);
1632                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
1633                 }
1634
1635                 nv32_wr(pScrn, reg, data2);
1636         }
1637         return TRUE;
1638 }
1639 #endif
1640
1641 static Bool init_sub_direct(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1642 {
1643         /* INIT_SUB_DIRECT   opcode: 0x5B ('[')
1644          *
1645          * offset      (8  bit): opcode
1646          * offset + 1  (16 bit): subroutine offset (in bios)
1647          *
1648          * Calls a subroutine that will execute commands until INIT_DONE
1649          * is found. 
1650          */
1651
1652         uint16_t sub_offset = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
1653
1654         if (!iexec->execute)
1655                 return TRUE;
1656
1657         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: EXECUTING SUB-ROUTINE AT 0x%04X\n",
1658                         offset, sub_offset);
1659
1660         parse_init_table(pScrn, bios, sub_offset, iexec);
1661
1662         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: END OF SUB-ROUTINE AT 0x%04X\n",
1663                         offset, sub_offset);
1664
1665         return TRUE;
1666 }
1667
1668 static Bool init_copy_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1669 {
1670         /* INIT_COPY_NV_REG   opcode: 0x5F ('_')
1671          *
1672          * offset      (8  bit): opcode
1673          * offset + 1  (32 bit): src reg
1674          * offset + 5  (8  bit): shift
1675          * offset + 6  (32 bit): src mask
1676          * offset + 10 (32 bit): xor
1677          * offset + 14 (32 bit): dst reg
1678          * offset + 18 (32 bit): dst mask
1679          *
1680          * Shift REGVAL("src reg") right by (signed) "shift", AND result with
1681          * "src mask", then XOR with "xor". Write this OR'd with
1682          * (REGVAL("dst reg") AND'd with "dst mask") to "dst reg"
1683          */
1684
1685         uint32_t srcreg = *((uint32_t *)(&bios->data[offset + 1]));
1686         uint8_t shift = bios->data[offset + 5];
1687         uint32_t srcmask = *((uint32_t *)(&bios->data[offset + 6]));
1688         uint32_t xor = *((uint32_t *)(&bios->data[offset + 10]));
1689         uint32_t dstreg = *((uint32_t *)(&bios->data[offset + 14]));
1690         uint32_t dstmask = *((uint32_t *)(&bios->data[offset + 18]));
1691         uint32_t srcvalue, dstvalue;
1692
1693         if (!iexec->execute)
1694                 return TRUE;
1695
1696         if (DEBUGLEVEL >= 6)
1697                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1698                            "0x%04X: SrcReg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%08X, Xor: 0x%08X, DstReg: 0x%08X, DstMask: 0x%08X\n",
1699                            offset, srcreg, shift, srcmask, xor, dstreg, dstmask);
1700
1701         srcvalue = nv32_rd(pScrn, srcreg);
1702
1703         if (shift < 0x80)
1704                 srcvalue >>= shift;
1705         else
1706                 srcvalue <<= (0x100 - shift);
1707
1708         srcvalue = (srcvalue & srcmask) ^ xor;
1709
1710         dstvalue = nv32_rd(pScrn, dstreg) & dstmask;
1711
1712         nv32_wr(pScrn, dstreg, dstvalue | srcvalue);
1713
1714         return TRUE;
1715 }
1716
1717 static Bool init_zm_index_io(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1718 {
1719         /* INIT_ZM_INDEX_IO   opcode: 0x62 ('b')
1720          *
1721          * offset      (8  bit): opcode
1722          * offset + 1  (16 bit): CRTC port
1723          * offset + 3  (8  bit): CRTC index
1724          * offset + 4  (8  bit): data
1725          *
1726          * Write "data" to index "CRTC index" of "CRTC port"
1727          */
1728         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
1729         uint8_t crtcindex = bios->data[offset + 3];
1730         uint8_t data = bios->data[offset + 4];
1731
1732         if (!iexec->execute)
1733                 return TRUE;
1734
1735         nv_idx_port_wr(pScrn, crtcport, crtcindex, data);
1736
1737         return TRUE;
1738 }
1739
1740 static Bool init_compute_mem(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1741 {
1742         /* INIT_COMPUTE_MEM   opcode: 0x63 ('c')
1743          *
1744          * offset      (8 bit): opcode
1745          *
1746          * This opcode is meant to set NV_PFB_CFG0 (0x100200) appropriately so
1747          * that the hardware can correctly calculate how much VRAM it has
1748          * (and subsequently report that value in 0x10020C)
1749          *
1750          * The implementation of this opcode in general consists of two parts:
1751          * 1) determination of the memory bus width
1752          * 2) determination of how many of the card's RAM pads have ICs attached
1753          *
1754          * 1) is done by a cunning combination of writes to offsets 0x1c and
1755          * 0x3c in the framebuffer, and seeing whether the written values are
1756          * read back correctly. This then affects bits 4-7 of NV_PFB_CFG0
1757          *
1758          * 2) is done by a cunning combination of writes to an offset slightly
1759          * less than the maximum memory reported by 0x10020C, then seeing if
1760          * the test pattern can be read back. This then affects bits 12-15 of
1761          * NV_PFB_CFG0
1762          *
1763          * In this context a "cunning combination" may include multiple reads
1764          * and writes to varying locations, often alternating the test pattern
1765          * and 0, doubtless to make sure buffers are filled, residual charges
1766          * on tracks are removed etc.
1767          *
1768          * Unfortunately, the "cunning combination"s mentioned above, and the
1769          * changes to the bits in NV_PFB_CFG0 differ with nearly every bios
1770          * trace I have.
1771          *
1772          * Therefore, we cheat and assume the value of NV_PFB_CFG0 with which
1773          * we started was correct, and use that instead
1774          */
1775
1776         /* no iexec->execute check by design */
1777
1778         /* on every card I've seen, this step gets done for us earlier in the init scripts
1779         uint8_t crdata = nv_idx_port_rd(pScrn, VGA_SEQ_INDEX, 0x01);
1780         nv_idx_port_wr(pScrn, VGA_SEQ_INDEX, 0x01, crdata | 0x20);
1781         */
1782
1783         /* this also has probably been done in the scripts, but an mmio trace of
1784          * s3 resume shows nvidia doing it anyway (unlike the VGA_SEQ_INDEX write)
1785          */
1786         nv32_wr(pScrn, NV_PFB_REFCTRL, NV_PFB_REFCTRL_VALID_1);
1787
1788         /* write back the saved configuration value */
1789         nv32_wr(pScrn, NV_PFB_CFG0, saved_nv_pfb_cfg0);
1790
1791         return TRUE;
1792 }
1793
1794 static Bool init_reset(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1795 {
1796         /* INIT_RESET   opcode: 0x65 ('e')
1797          *
1798          * offset      (8  bit): opcode
1799          * offset + 1  (32 bit): register
1800          * offset + 5  (32 bit): value1
1801          * offset + 9  (32 bit): value2
1802          *
1803          * Assign "value1" to "register", then assign "value2" to "register"
1804          */
1805
1806         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1807         uint32_t value1 = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 5])));
1808         uint32_t value2 = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 9])));
1809         uint32_t pci_nv_19, pci_nv_20;
1810
1811         /* no iexec->execute check by design */
1812
1813         pci_nv_19 = nv32_rd(pScrn, NV_PBUS_PCI_NV_19);
1814         nv32_wr(pScrn, NV_PBUS_PCI_NV_19, 0);
1815         nv32_wr(pScrn, reg, value1);
1816
1817         usleep(10);
1818
1819         nv32_wr(pScrn, reg, value2);
1820         nv32_wr(pScrn, NV_PBUS_PCI_NV_19, pci_nv_19);
1821
1822         pci_nv_20 = nv32_rd(pScrn, NV_PBUS_PCI_NV_20);
1823         pci_nv_20 &= ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED;     /* 0xfffffffe */
1824         nv32_wr(pScrn, NV_PBUS_PCI_NV_20, pci_nv_20);
1825
1826         return TRUE;
1827 }
1828
1829 #if 0
1830 static Bool init_index_io8(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1831 {
1832         /* INIT_INDEX_IO8   opcode: 0x69
1833          * 
1834          * offset      (8  bit): opcode
1835          * offset + 1  (16 bit): CRTC reg
1836          * offset + 3  (8  bit): and mask
1837          * offset + 4  (8  bit): or with
1838          * 
1839          * 
1840          */
1841
1842         NVPtr pNv = NVPTR(pScrn);
1843         volatile CARD8 *ptr = crtchead ? pNv->PCIO1 : pNv->PCIO0;
1844         CARD16 reg = le16_to_cpu(*((CARD16 *)(&bios->data[offset + 1])));
1845         CARD8 and  = *((CARD8 *)(&bios->data[offset + 3]));
1846         CARD8 or = *((CARD8 *)(&bios->data[offset + 4]));
1847         CARD8 data;
1848
1849         if (iexec->execute) {
1850                 data = (VGA_RD08(ptr, reg) & and) | or;
1851
1852                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1853                                 "0x%04X: CRTC REG: 0x%04X, VALUE: 0x%02X\n", 
1854                                 offset, reg, data);
1855                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset, 
1856                                 VGA_RD08(ptr, reg));
1857
1858 #ifdef PERFORM_WRITE
1859                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "init_index_io8 crtcreg 0x%X value 0x%X\n",reg,data);
1860                 still_alive();
1861                 VGA_WR08(ptr, reg, data);
1862 #endif
1863         }
1864         return TRUE;
1865 }
1866 #endif
1867
1868 static Bool init_sub(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1869 {
1870         /* INIT_SUB   opcode: 0x6B ('k')
1871          *
1872          * offset      (8 bit): opcode
1873          * offset + 1  (8 bit): script number
1874          *
1875          * Execute script number "script number", as a subroutine
1876          */
1877
1878         uint8_t sub = bios->data[offset + 1];
1879
1880         if (!iexec->execute)
1881                 return TRUE;
1882
1883         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1884                    "0x%04X: EXECUTING SUB-SCRIPT %d\n", offset, sub);
1885
1886         parse_init_table(pScrn, bios,
1887                          le16_to_cpu(*((uint16_t *)(&bios->data[bios->init_script_tbls_ptr + sub * 2]))),
1888                          iexec);
1889
1890         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1891                    "0x%04X: END OF SUB-SCRIPT %d\n", offset, sub);
1892
1893         return TRUE;
1894 }
1895
1896 #if 0
1897 static Bool init_ram_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1898 {
1899         /* INIT_RAM_CONDITION   opcode: 0x6D
1900          * 
1901          * offset      (8  bit): opcode
1902          * offset + 1  (8  bit): and mask
1903          * offset + 2  (8  bit): cmpval
1904          *
1905          * Test if (NV_PFB_BOOT & and mask) matches cmpval
1906          */
1907         NVPtr pNv = NVPTR(pScrn);
1908         CARD8 and = *((CARD8 *) (&bios->data[offset + 1]));
1909         CARD8 cmpval = *((CARD8 *) (&bios->data[offset + 2]));
1910         CARD32 data;
1911
1912         if (iexec->execute) {
1913                 data=(pNv->PFB[NV_PFB_BOOT/4])&and;
1914
1915                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1916                                 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1917                                 offset, data, cmpval);
1918
1919                 if (data == cmpval) {
1920                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1921                                         "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1922                                         offset);
1923                 } else {
1924                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONDITION IS NOT FULFILLED\n", offset);
1925                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1926                                         "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
1927                         iexec->execute = FALSE;     
1928                 }
1929         }
1930         return TRUE;
1931 }
1932 #endif
1933
1934 static Bool init_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1935 {
1936         /* INIT_NV_REG   opcode: 0x6E ('n')
1937          *
1938          * offset      (8  bit): opcode
1939          * offset + 1  (32 bit): register
1940          * offset + 5  (32 bit): mask
1941          * offset + 9  (32 bit): data
1942          *
1943          * Assign ((REGVAL("register") & "mask") | "data") to "register"
1944          */
1945
1946         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1947         uint32_t mask = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 5])));
1948         uint32_t data = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 9])));
1949
1950         if (!iexec->execute)
1951                 return TRUE;
1952
1953         if (DEBUGLEVEL >= 6)
1954                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1955                            "0x%04X: Reg: 0x%08X, Mask: 0x%08X, Data: 0x%08X\n",
1956                            offset, reg, mask, data);
1957
1958         nv32_wr(pScrn, reg, (nv32_rd(pScrn, reg) & mask) | data);
1959
1960         return TRUE;
1961 }
1962
1963 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1964 {
1965         /* INIT_MACRO   opcode: 0x6F ('o')
1966          *
1967          * offset      (8 bit): opcode
1968          * offset + 1  (8 bit): macro number
1969          *
1970          * Look up macro index "macro number" in the macro index table.
1971          * The macro index table entry has 1 byte for the index in the macro table,
1972          * and 1 byte for the number of times to repeat the macro.
1973          * The macro table entry has 4 bytes for the register address and
1974          * 4 bytes for the value to write to that register
1975          */
1976
1977         uint8_t macro_index_tbl_idx = bios->data[offset + 1];
1978         uint16_t tmp = bios->macro_index_tbl_ptr + (macro_index_tbl_idx * MACRO_INDEX_SIZE);
1979         uint8_t macro_tbl_idx = bios->data[tmp];
1980         uint8_t count = bios->data[tmp + 1];
1981         uint32_t reg, data;
1982         int i;
1983
1984         if (!iexec->execute)
1985                 return TRUE;
1986
1987         if (DEBUGLEVEL >= 6)
1988                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1989                            "0x%04X: Macro: 0x%02X, MacroTableIndex: 0x%02X, Count: 0x%02X\n",
1990                            offset, macro_index_tbl_idx, macro_tbl_idx, count);
1991
1992         for (i = 0; i < count; i++) {
1993                 uint16_t macroentryptr = bios->macro_tbl_ptr + (macro_tbl_idx + i) * MACRO_SIZE;
1994
1995                 reg = le32_to_cpu(*((uint32_t *)(&bios->data[macroentryptr])));
1996                 data = le32_to_cpu(*((uint32_t *)(&bios->data[macroentryptr + 4])));
1997
1998                 nv32_wr(pScrn, reg, data);
1999         }
2000
2001         return TRUE;
2002 }
2003
2004 static Bool init_done(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2005 {
2006         /* INIT_DONE   opcode: 0x71 ('q')
2007          *
2008          * offset      (8  bit): opcode
2009          *
2010          * End the current script
2011          */
2012
2013         /* mild retval abuse to stop parsing this table */
2014         return FALSE;
2015 }
2016
2017 static Bool init_resume(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2018 {
2019         /* INIT_RESUME   opcode: 0x72 ('r')
2020          *
2021          * offset      (8  bit): opcode
2022          *
2023          * End the current execute / no-execute condition
2024          */
2025
2026         if (iexec->execute)
2027                 return TRUE;
2028
2029         iexec->execute = TRUE;;
2030         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2031                    "0x%04X: ---- EXECUTING FOLLOWING COMMANDS ----\n", offset);
2032
2033         return TRUE;
2034 }
2035
2036 #if 0
2037 static Bool init_ram_condition2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
2038 {
2039         /* INIT_RAM_CONDITION2   opcode: 0x73
2040          * 
2041          * offset      (8  bit): opcode
2042          * offset + 1  (8  bit): and mask
2043          * offset + 2  (8  bit): cmpval
2044          *
2045          * Test if (NV_EXTDEV_BOOT & and mask) matches cmpval
2046          */
2047         NVPtr pNv = NVPTR(pScrn);
2048         CARD32 and = *((CARD32 *) (&bios->data[offset + 1]));
2049         CARD32 cmpval = *((CARD32 *) (&bios->data[offset + 5]));
2050         CARD32 data;
2051
2052         if (iexec->execute) {
2053                 data=(nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT))&and;
2054                 
2055                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
2056                                 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
2057                                 offset, data, cmpval);
2058
2059                 if (data == cmpval) {
2060                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
2061                                         "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
2062                                         offset);
2063                 } else {
2064                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONDITION IS NOT FULFILLED\n", offset);
2065                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
2066                                         "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
2067                         iexec->execute = FALSE;     
2068                 }
2069         }
2070         return TRUE;
2071 }
2072 #endif
2073
2074 static Bool init_time(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2075 {
2076         /* INIT_TIME   opcode: 0x74 ('t')
2077          *
2078          * offset      (8  bit): opcode
2079          * offset + 1  (16 bit): time
2080          *
2081          * Sleep for "time" microseconds.
2082          */
2083
2084         uint16_t time = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
2085
2086         if (!iexec->execute)
2087                 return TRUE;
2088
2089         if (DEBUGLEVEL >= 6)
2090                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2091                            "0x%04X: Sleeping for 0x%04X microseconds\n", offset, time);
2092
2093         usleep(time);
2094
2095         return TRUE;
2096 }
2097
2098 static Bool init_condition(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2099 {
2100         /* INIT_CONDITION   opcode: 0x75 ('u')
2101          *
2102          * offset      (8 bit): opcode
2103          * offset + 1  (8 bit): condition number
2104          *
2105          * Check condition "condition number" in the condition table.
2106          * The condition table entry has 4 bytes for the address of the
2107          * register to check, 4 bytes for a mask and 4 for a test value.
2108          * If condition not met skip subsequent opcodes until condition
2109          * is inverted (INIT_NOT), or we hit INIT_RESUME
2110          */
2111
2112         uint8_t cond = bios->data[offset + 1];
2113         uint16_t condptr = bios->condition_tbl_ptr + cond * CONDITION_SIZE;
2114         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[condptr])));
2115         uint32_t mask = le32_to_cpu(*((uint32_t *)(&bios->data[condptr + 4])));
2116         uint32_t cmpval = le32_to_cpu(*((uint32_t *)(&bios->data[condptr + 8])));
2117         uint32_t data;
2118
2119         if (!iexec->execute)
2120                 return TRUE;
2121
2122         if (DEBUGLEVEL >= 6)
2123                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2124                            "0x%04X: Cond: 0x%02X, Reg: 0x%08X, Mask: 0x%08X, Cmpval: 0x%08X\n",
2125                            offset, cond, reg, mask, cmpval);
2126
2127         data = nv32_rd(pScrn, reg) & mask;
2128
2129         if (DEBUGLEVEL >= 6)
2130                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2131                            "0x%04X: Checking if 0x%08X equals 0x%08X\n",
2132                            offset, data, cmpval);
2133
2134         if (data == cmpval) {
2135                 if (DEBUGLEVEL >= 6)
2136                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2137                                    "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n", offset);
2138         } else {
2139                 if (DEBUGLEVEL >= 6)
2140                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2141                                    "0x%04X: CONDITION IS NOT FULFILLED\n", offset);
2142                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2143                            "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
2144                 iexec->execute = FALSE;
2145         }
2146
2147         return TRUE;
2148 }
2149
2150 static Bool init_index_io(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2151 {
2152         /* INIT_INDEX_IO   opcode: 0x78 ('x')
2153          *
2154          * offset      (8  bit): opcode
2155          * offset + 1  (16 bit): CRTC port
2156          * offset + 3  (8  bit): CRTC index
2157          * offset + 4  (8  bit): mask
2158          * offset + 5  (8  bit): data
2159          *
2160          * Read value at index "CRTC index" on "CRTC port", AND with "mask", OR with "data", write-back
2161          */
2162
2163         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
2164         uint8_t crtcindex = bios->data[offset + 3];
2165         uint8_t mask = bios->data[offset + 4];
2166         uint8_t data = bios->data[offset + 5];
2167         uint8_t value;
2168
2169         if (!iexec->execute)
2170                 return TRUE;
2171
2172         if (DEBUGLEVEL >= 6)
2173                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2174                            "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n",
2175                            offset, crtcport, crtcindex, mask, data);
2176
2177         value = (nv_idx_port_rd(pScrn, crtcport, crtcindex) & mask) | data;
2178         nv_idx_port_wr(pScrn, crtcport, crtcindex, value);
2179
2180         return TRUE;
2181 }
2182
2183 static Bool init_pll(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2184 {
2185         /* INIT_PLL   opcode: 0x79 ('y')
2186          *
2187          * offset      (8  bit): opcode
2188          * offset + 1  (32 bit): register
2189          * offset + 5  (16 bit): freq
2190          *
2191          * Set PLL register "register" to coefficients for frequency (10kHz) "freq"
2192          */
2193
2194         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
2195         uint16_t freq = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 5])));
2196
2197         if (!iexec->execute)
2198                 return TRUE;
2199
2200         if (DEBUGLEVEL >= 6)
2201                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2202                            "0x%04X: Reg: 0x%08X, Freq: %d0kHz\n",
2203                            offset, reg, freq);
2204
2205         setPLL(pScrn, bios, reg, freq * 10);
2206
2207         return TRUE;
2208 }
2209
2210 static Bool init_zm_reg(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2211 {
2212         /* INIT_ZM_REG   opcode: 0x7A ('z')
2213          *
2214          * offset      (8  bit): opcode
2215          * offset + 1  (32 bit): register
2216          * offset + 5  (32 bit): value
2217          *
2218          * Assign "value" to "register"
2219          */
2220
2221         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
2222         uint32_t value = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 5])));
2223
2224         if (!iexec->execute)
2225                 return TRUE;
2226
2227         nv32_wr(pScrn, reg, value);
2228
2229         return TRUE;
2230 }
2231
2232 /* hack to avoid moving the itbl_entry array before this function */
2233 int init_ram_restrict_zm_reg_group_blocklen = 0;
2234
2235 static Bool init_ram_restrict_zm_reg_group(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2236 {
2237         /* INIT_RAM_RESTRICT_ZM_REG_GROUP   opcode: 0x8F ('')
2238          *
2239          * offset      (8  bit): opcode
2240          * offset + 1  (32 bit): reg
2241          * offset + 5  (8  bit): regincrement
2242          * offset + 6  (8  bit): count
2243          * offset + 7  (32 bit): value 1,1
2244          * ...
2245          *
2246          * Use the RAMCFG strap of PEXTDEV_BOOT as an index into the table at
2247          * ram_restrict_table_ptr. The value read from here is 'n', and
2248          * "value 1,n" gets written to "reg". This repeats "count" times and on
2249          * each iteration 'm', "reg" increases by "regincrement" and
2250          * "value m,n" is used. The extent of n is limited by a number read
2251          * from the 'M' BIT table, herein called "blocklen"
2252          */
2253
2254         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
2255         uint8_t regincrement = bios->data[offset + 5];
2256         uint8_t count = bios->data[offset + 6];
2257         uint32_t strap_ramcfg, data;
2258         uint16_t blocklen;
2259         uint8_t index;
2260         int i;
2261
2262         /* previously set by 'M' BIT table */
2263         blocklen = init_ram_restrict_zm_reg_group_blocklen;
2264
2265         if (!iexec->execute)
2266                 return TRUE;
2267
2268         if (!blocklen) {
2269                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2270                            "0x%04X: Zero block length - has the M table been parsed?\n", offset);
2271                 return FALSE;
2272         }
2273
2274         strap_ramcfg = (nv32_rd(pScrn, NV_PEXTDEV_BOOT_0) >> 2) & 0xf;
2275         index = bios->data[bios->ram_restrict_tbl_ptr + strap_ramcfg];
2276
2277         if (DEBUGLEVEL >= 6)
2278                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2279                            "0x%04X: Reg: 0x%08X, RegIncrement: 0x%02X, Count: 0x%02X, StrapRamCfg: 0x%02X, Index: 0x%02X\n",
2280                            offset, reg, regincrement, count, strap_ramcfg, index);
2281
2282         for (i = 0; i < count; i++) {
2283                 data = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 7 + index * 4 + blocklen * i])));
2284
2285                 nv32_wr(pScrn, reg, data);
2286
2287                 reg += regincrement;
2288         }
2289
2290         return TRUE;
2291 }
2292
2293 static Bool init_copy_zm_reg(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2294 {
2295         /* INIT_COPY_ZM_REG   opcode: 0x90 ('')
2296          *
2297          * offset      (8  bit): opcode
2298          * offset + 1  (32 bit): src reg
2299          * offset + 5  (32 bit): dst reg
2300          *
2301          * Put contents of "src reg" into "dst reg"
2302          */
2303
2304         uint32_t srcreg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
2305         uint32_t dstreg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 5])));
2306
2307         if (!iexec->execute)
2308                 return TRUE;
2309
2310         nv32_wr(pScrn, dstreg, nv32_rd(pScrn, srcreg));
2311
2312         return TRUE;
2313 }
2314
2315 static Bool init_zm_reg_group_addr_latched(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2316 {
2317         /* INIT_ZM_REG_GROUP_ADDRESS_LATCHED   opcode: 0x91 ('')
2318          *
2319          * offset      (8  bit): opcode
2320          * offset + 1  (32 bit): src reg
2321          * offset + 5  (8  bit): count
2322          * offset + 6  (32 bit): data 1
2323          * ...
2324          *
2325          * For each of "count" values write "data n" to "src reg"
2326          */
2327
2328         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
2329         uint8_t count = bios->data[offset + 5];
2330         int i;
2331
2332         if (!iexec->execute)
2333                 return TRUE;
2334
2335         for (i = 0; i < count; i++) {
2336                 uint32_t data = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 6 + 4 * i])));
2337                 nv32_wr(pScrn, reg, data);
2338         }
2339
2340         return TRUE;
2341 }
2342
2343 static Bool init_reserved(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2344 {
2345         /* INIT_RESERVED   opcode: 0x92 ('')
2346          *
2347          * offset      (8 bit): opcode
2348          *
2349          * Seemingly does nothing
2350          */
2351
2352         return TRUE;
2353 }
2354
2355 static init_tbl_entry_t itbl_entry[] = {
2356         /* command name                       , id  , length  , offset  , mult    , command handler                 */
2357 //      { "INIT_PROG"                         , 0x31, 15      , 10      , 4       , init_prog                       },
2358         { "INIT_IO_RESTRICT_PROG"             , 0x32, 11      , 6       , 4       , init_io_restrict_prog           },
2359         { "INIT_REPEAT"                       , 0x33, 2       , 0       , 0       , init_repeat                     },
2360         { "INIT_IO_RESTRICT_PLL"              , 0x34, 12      , 7       , 2       , init_io_restrict_pll            },
2361         { "INIT_END_REPEAT"                   , 0x36, 1       , 0       , 0       , init_end_repeat                 },
2362         { "INIT_COPY"                         , 0x37, 11      , 0       , 0       , init_copy                       },
2363         { "INIT_NOT"                          , 0x38, 1       , 0       , 0       , init_not                        },
2364         { "INIT_IO_FLAG_CONDITION"            , 0x39, 2       , 0       , 0       , init_io_flag_condition          },
2365         { "INIT_INDEX_ADDRESS_LATCHED"        , 0x49, 18      , 17      , 2       , init_idx_addr_latched           },
2366         { "INIT_IO_RESTRICT_PLL2"             , 0x4A, 11      , 6       , 4       , init_io_restrict_pll2           },
2367         { "INIT_PLL2"                         , 0x4B, 9       , 0       , 0       , init_pll2                       },
2368 /*      { "INIT_I2C_BYTE"                     , 0x4C, x       , x       , x       , init_i2c_byte                   }, */
2369 /*      { "INIT_ZM_I2C_BYTE"                  , 0x4D, x       , x       , x       , init_zm_i2c_byte                }, */
2370 /*      { "INIT_ZM_I2C"                       , 0x4E, x       , x       , x       , init_zm_i2c                     }, */
2371         { "INIT_TMDS"                         , 0x4F, 5       , 0       , 0       , init_tmds                       },
2372         { "INIT_ZM_TMDS_GROUP"                , 0x50, 3       , 2       , 2       , init_zm_tmds_group              },
2373         { "INIT_CR_INDEX_ADDRESS_LATCHED"     , 0x51, 5       , 4       , 1       , init_cr_idx_adr_latch           },
2374         { "INIT_CR"                           , 0x52, 4       , 0       , 0       , init_cr                         },
2375         { "INIT_ZM_CR"                        , 0x53, 3       , 0       , 0       , init_zm_cr                      },
2376         { "INIT_ZM_CR_GROUP"                  , 0x54, 2       , 1       , 2       , init_zm_cr_group                },
2377         { "INIT_CONDITION_TIME"               , 0x56, 3       , 0       , 0       , init_condition_time             },
2378         { "INIT_ZM_REG_SEQUENCE"              , 0x58, 6       , 5       , 4       , init_zm_reg_sequence            },
2379 //      { "INIT_INDIRECT_REG"                 , 0x5A, 7       , 0       , 0       , init_indirect_reg               },
2380         { "INIT_SUB_DIRECT"                   , 0x5B, 3       , 0       , 0       , init_sub_direct                 },
2381         { "INIT_COPY_NV_REG"                  , 0x5F, 22      , 0       , 0       , init_copy_nv_reg                },
2382         { "INIT_ZM_INDEX_IO"                  , 0x62, 5       , 0       , 0       , init_zm_index_io                },
2383         { "INIT_COMPUTE_MEM"                  , 0x63, 1       , 0       , 0       , init_compute_mem                },
2384         { "INIT_RESET"                        , 0x65, 13      , 0       , 0       , init_reset                      },
2385 /*      { "INIT_NEXT"                         , 0x66, x       , x       , x       , init_next                       }, */       
2386 /*      { "INIT_NEXT"                         , 0x67, x       , x       , x       , init_next                       }, */       
2387 /*      { "INIT_NEXT"                         , 0x68, x       , x       , x       , init_next                       }, */       
2388 //      { "INIT_INDEX_IO8"                    , 0x69, 5       , 0       , 0       , init_index_io8                  },
2389         { "INIT_SUB"                          , 0x6B, 2       , 0       , 0       , init_sub                        },
2390 //      { "INIT_RAM_CONDITION"                , 0x6D, 3       , 0       , 0       , init_ram_condition              },
2391         { "INIT_NV_REG"                       , 0x6E, 13      , 0       , 0       , init_nv_reg                     },
2392         { "INIT_MACRO"                        , 0x6F, 2       , 0       , 0       , init_macro                      },
2393         { "INIT_DONE"                         , 0x71, 1       , 0       , 0       , init_done                       },
2394         { "INIT_RESUME"                       , 0x72, 1       , 0       , 0       , init_resume                     },
2395 //      { "INIT_RAM_CONDITION2"               , 0x73, 9       , 0       , 0       , init_ram_condition2             },
2396         { "INIT_TIME"                         , 0x74, 3       , 0       , 0       , init_time                       },
2397         { "INIT_CONDITION"                    , 0x75, 2       , 0       , 0       , init_condition                  },
2398 /*      { "INIT_IO_CONDITION"                 , 0x76, x       , x       , x       , init_io_condition               }, */
2399         { "INIT_INDEX_IO"                     , 0x78, 6       , 0       , 0       , init_index_io                   },
2400         { "INIT_PLL"                          , 0x79, 7       , 0       , 0       , init_pll                        },
2401         { "INIT_ZM_REG"                       , 0x7A, 9       , 0       , 0       , init_zm_reg                     },
2402         /* INIT_RAM_RESTRICT_ZM_REG_GROUP's mult is loaded by M table in BIT */
2403         { "INIT_RAM_RESTRICT_ZM_REG_GROUP"    , 0x8F, 7       , 6       , 0       , init_ram_restrict_zm_reg_group  },
2404         { "INIT_COPY_ZM_REG"                  , 0x90, 9       , 0       , 0       , init_copy_zm_reg                },
2405         { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, 6       , 5       , 4       , init_zm_reg_group_addr_latched  },
2406         { "INIT_RESERVED"                     , 0x92, 1       , 0       , 0       , init_reserved                   },
2407         { 0                                   , 0   , 0       , 0       , 0       , 0                               }
2408 };
2409
2410 static unsigned int get_init_table_entry_length(bios_t *bios, unsigned int offset, int i)
2411 {
2412         /* Calculates the length of a given init table entry. */
2413         return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier;
2414 }
2415
2416 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec)
2417 {
2418         /* Parses all commands in a init table. */
2419
2420         /* We start out executing all commands found in the
2421          * init table. Some op codes may change the status
2422          * of this variable to SKIP, which will cause
2423          * the following op codes to perform no operation until
2424          * the value is changed back to EXECUTE.
2425          */
2426         unsigned char id;
2427         int i;
2428
2429         int count=0;
2430         /* Loop until INIT_DONE causes us to break out of the loop
2431          * (or until offset > bios length just in case... )
2432          * (and no more than 10000 iterations just in case... ) */
2433         while ((offset < bios->length) && (count++ < 10000)) {
2434                 id = bios->data[offset];
2435
2436                 /* Find matching id in itbl_entry */
2437                 for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++)
2438                         ;
2439
2440                 if (itbl_entry[i].name) {
2441                         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ (0x%02X) - %s ]\n",
2442                                    offset, itbl_entry[i].id, itbl_entry[i].name);
2443
2444                         /* execute eventual command handler */
2445                         if (itbl_entry[i].handler)
2446                                 if (!(*itbl_entry[i].handler)(pScrn, bios, offset, iexec))
2447                                         break;
2448                 } else {
2449                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2450                                    "0x%04X: Init table command not found: 0x%02X\n", offset, id);
2451                         break;
2452                 }
2453
2454                 /* Add the offset of the current command including all data
2455                  * of that command. The offset will then be pointing on the
2456                  * next op code.
2457                  */
2458                 offset += get_init_table_entry_length(bios, offset, i);
2459         }
2460 }
2461
2462 static void parse_init_tables(ScrnInfoPtr pScrn, bios_t *bios)
2463 {
2464         /* Loops and calls parse_init_table() for each present table. */
2465
2466         int i = 0;
2467         uint16_t table;
2468         init_exec_t iexec = {TRUE, FALSE};
2469
2470         while ((table = le16_to_cpu(*((uint16_t *)(&bios->data[bios->init_script_tbls_ptr + i]))))) {
2471
2472                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Parsing init table %d\n",
2473                         table, i / 2);
2474
2475                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2476                            "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n", table);
2477                 still_alive();
2478                 parse_init_table(pScrn, bios, table, &iexec);
2479                 i += 2;
2480         }
2481 }
2482
2483 void link_head_and_output(ScrnInfoPtr pScrn, int head, int dcb_entry, Bool overrideval)
2484 {
2485         /* The BIOS scripts don't do this for us, sadly
2486          * Luckily we do know the values ;-)
2487          *
2488          * head < 0 indicates we wish to force a setting with the overrideval
2489          * (for VT restore etc.)
2490          */
2491
2492         NVPtr pNv = NVPTR(pScrn);
2493         int preferred_output = (ffs(pNv->dcb_table.entry[dcb_entry].or) & OUTPUT_1) >> 1;
2494         uint8_t tmds04 = 0x80;
2495         uint32_t tmds_ctrl, tmds_ctrl2;
2496
2497         /* Bit 3 crosswires output and bus. */
2498         if (head >= 0 && head != preferred_output)
2499                 tmds04 = 0x88;
2500         if (head < 0 && overrideval)
2501                 tmds04 = 0x88;
2502
2503         if (pNv->dcb_table.entry[dcb_entry].type == OUTPUT_LVDS)
2504                 tmds04 |= 0x01;
2505
2506         tmds_ctrl = NV_PRAMDAC0_OFFSET + (preferred_output ? NV_PRAMDAC0_SIZE : 0) + NV_RAMDAC_FP_TMDS_CONTROL;
2507         tmds_ctrl2 = NV_PRAMDAC0_OFFSET + (preferred_output ? NV_PRAMDAC0_SIZE : 0) + NV_RAMDAC_FP_TMDS_CONTROL_2;
2508
2509         Bool oldexecute = pNv->VBIOS.execute;
2510         pNv->VBIOS.execute = TRUE;
2511         nv32_wr(pScrn, tmds_ctrl + 4, tmds04);
2512         nv32_wr(pScrn, tmds_ctrl, 0x04);
2513         if (pNv->dcb_table.entry[dcb_entry].type == OUTPUT_LVDS && pNv->VBIOS.fp.dual_link)
2514                 nv32_wr(pScrn, tmds_ctrl2 + 4, tmds04 ^ 0x08);
2515         else {
2516                 /* I have encountered no dvi (dual-link or not) that sets to anything else. */
2517                 /* Does this change beyond the 165 MHz boundary? */
2518                 nv32_wr(pScrn, tmds_ctrl2 + 4, 0x0);
2519         }
2520         nv32_wr(pScrn, tmds_ctrl2, 0x04);
2521         pNv->VBIOS.execute = oldexecute;
2522 }
2523
2524 static void call_lvds_manufacturer_script(ScrnInfoPtr pScrn, int head, int dcb_entry, enum LVDS_script script)
2525 {
2526         NVPtr pNv = NVPTR(pScrn);
2527         bios_t *bios = &pNv->VBIOS;
2528         init_exec_t iexec = {TRUE, FALSE};
2529
2530         uint8_t sub = bios->data[bios->fp.xlated_entry + script];
2531         uint16_t scriptofs = le16_to_cpu(*((uint16_t *)(&bios->data[bios->init_script_tbls_ptr + sub * 2])));
2532         Bool power_off_for_reset;
2533         uint16_t off_on_delay;
2534
2535         if (!bios->fp.xlated_entry || !sub || !scriptofs)
2536                 return;
2537
2538         if (script == LVDS_INIT && bios->data[scriptofs] != 'q') {
2539                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "LVDS init script not stubbed\n");
2540                 return;
2541         }
2542
2543         power_off_for_reset = bios->data[bios->fp.xlated_entry] & 1;
2544         off_on_delay = le16_to_cpu(*(uint16_t *)&bios->data[bios->fp.xlated_entry + 7]);
2545
2546         if (script == LVDS_PANEL_ON && bios->fp.reset_after_pclk_change)
2547                 call_lvds_manufacturer_script(pScrn, head, dcb_entry, LVDS_RESET);
2548         if (script == LVDS_RESET && power_off_for_reset)
2549                 call_lvds_manufacturer_script(pScrn, head, dcb_entry, LVDS_PANEL_OFF);
2550
2551         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Calling LVDS script %d:\n", script);
2552         pNv->VBIOS.execute = TRUE;
2553         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, NV_VGA_CRTCX_OWNER,
2554                    head ? NV_VGA_CRTCX_OWNER_HEADB : NV_VGA_CRTCX_OWNER_HEADA);
2555         parse_init_table(pScrn, bios, scriptofs, &iexec);
2556         pNv->VBIOS.execute = FALSE;
2557
2558         if (script == LVDS_PANEL_OFF)
2559                 usleep(off_on_delay * 1000);
2560         if (script == LVDS_RESET)
2561                 link_head_and_output(pScrn, head, dcb_entry, FALSE);
2562 }
2563
2564 static uint16_t clkcmptable(bios_t *bios, uint16_t clktable, int pxclk)
2565 {
2566         int compare_record_len, i = 0;
2567         uint16_t compareclk, scriptptr = 0;
2568
2569         if (bios->major_version < 5) /* pre BIT */
2570                 compare_record_len = 3;
2571         else
2572                 compare_record_len = 4;
2573
2574         do {
2575                 compareclk = le16_to_cpu(*((uint16_t *)&bios->data[clktable + compare_record_len * i]));
2576                 if (pxclk >= compareclk * 10) {
2577                         if (bios->major_version < 5) {
2578                                 uint8_t tmdssub = bios->data[clktable + 2 + compare_record_len * i];
2579                                 scriptptr = le16_to_cpu(*((uint16_t *)(&bios->data[bios->init_script_tbls_ptr + tmdssub * 2])));
2580                         } else
2581                                 scriptptr = le16_to_cpu(*((uint16_t *)&bios->data[clktable + 2 + compare_record_len * i]));
2582                         break;
2583                 }
2584                 i++;
2585         } while (compareclk);
2586
2587         return scriptptr;
2588 }
2589
2590 static void rundigitaloutscript(ScrnInfoPtr pScrn, uint16_t scriptptr, int head, int dcb_entry)
2591 {
2592         bios_t *bios = &NVPTR(pScrn)->VBIOS;
2593         init_exec_t iexec = {TRUE, FALSE};
2594
2595         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Parsing digital output script table\n", scriptptr);
2596         bios->execute = TRUE;
2597         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, NV_VGA_CRTCX_OWNER,
2598                         head ? NV_VGA_CRTCX_OWNER_HEADB : NV_VGA_CRTCX_OWNER_HEADA);
2599         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, 0x57, 0);
2600         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, 0x58, dcb_entry);
2601         parse_init_table(pScrn, bios, scriptptr, &iexec);
2602         bios->execute = FALSE;
2603
2604         link_head_and_output(pScrn, head, dcb_entry, FALSE);
2605 }
2606
2607 static void run_lvds_table(ScrnInfoPtr pScrn, int head, int dcb_entry, enum LVDS_script script, int pxclk)
2608 {
2609         /* The BIT LVDS table's header has the information to setup the
2610          * necessary registers. Following the standard 4 byte header are:
2611          * A bitmask byte and a dual-link transition pxclk value for use in
2612          * selecting the init script when not using straps; 4 script pointers
2613          * for panel power, selected by output and on/off; and 8 table pointers
2614          * for panel init, the needed one determined by output, and bits in the
2615          * conf byte. These tables are similar to the TMDS tables, consisting
2616          * of a list of pxclks and script pointers.
2617          */
2618
2619         NVPtr pNv = NVPTR(pScrn);
2620         bios_t *bios = &pNv->VBIOS;
2621         unsigned int fpstrapping, outputset = (pNv->dcb_table.entry[dcb_entry].or == 4) ? 1 : 0;
2622         uint16_t scriptptr = 0, clktable;
2623         uint8_t clktableptr = 0;
2624
2625         fpstrapping = (nv32_rd(pScrn, NV_PEXTDEV_BOOT_0) >> 16) & 0xf;
2626
2627         if (script == LVDS_PANEL_ON && bios->fp.reset_after_pclk_change)
2628                 run_lvds_table(pScrn, head, dcb_entry, LVDS_RESET, pxclk);
2629         /* no sign of the "panel off for reset" bit, but it's safer to assume we should */
2630         if (script == LVDS_RESET)
2631                 run_lvds_table(pScrn, head, dcb_entry, LVDS_PANEL_OFF, pxclk);
2632
2633         /* for now we assume version 3.0 table - g80 support will need some changes */
2634
2635         switch (script) {
2636         case LVDS_INIT:
2637                 return;
2638         case LVDS_BACKLIGHT_ON: // check applicability of the script for this
2639         case LVDS_PANEL_ON:
2640                 scriptptr = le16_to_cpu(*(uint16_t *)&bios->data[bios->fp.lvdsmanufacturerpointer + 7 + outputset * 2]);
2641                 break;
2642         case LVDS_BACKLIGHT_OFF:        // check applicability of the script for this
2643         case LVDS_PANEL_OFF:
2644                 scriptptr = le16_to_cpu(*(uint16_t *)&bios->data[bios->fp.lvdsmanufacturerpointer + 11 + outputset * 2]);
2645                 break;
2646         case LVDS_RESET:
2647                 if (pNv->dcb_table.entry[dcb_entry].lvdsconf.use_straps_for_mode ||
2648                         (fpstrapping != 0x0f && bios->data[bios->fp.xlated_entry + 1] != 0x0f)) {
2649                         if (bios->fp.dual_link)
2650                                 clktableptr += 2;
2651                         if (bios->fp.BITbit1)
2652                                 clktableptr++;
2653                 } else {
2654                         uint8_t fallback = bios->data[bios->fp.lvdsmanufacturerpointer + 4];
2655                         int fallbackcmpval = (pNv->dcb_table.entry[dcb_entry].or == 4) ? 4 : 1;
2656
2657                         if (pxclk >= bios->fp.duallink_transition_clk) {
2658                                 clktableptr += 2;
2659                                 fallbackcmpval *= 2;
2660                         }
2661                         if (fallbackcmpval & fallback)
2662                                 clktableptr++;
2663                 }
2664
2665                 /* adding outputset * 8 may not be correct */
2666                 clktable = le16_to_cpu(*(uint16_t *)&bios->data[bios->fp.lvdsmanufacturerpointer + 15 + clktableptr * 2 + outputset * 8]);
2667                 if (!clktable) {
2668                         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Pixel clock comparison table not found\n");
2669                         return;
2670                 }
2671                 scriptptr = clkcmptable(bios, clktable, pxclk);
2672         }
2673
2674         if (!scriptptr) {
2675                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "LVDS output init script not found\n");
2676                 return;
2677         }
2678         rundigitaloutscript(pScrn, scriptptr, head, dcb_entry);
2679 }
2680
2681 void call_lvds_script(ScrnInfoPtr pScrn, int head, int dcb_entry, enum LVDS_script script, int pxclk)
2682 {
2683         /* LVDS operations are multiplexed in an effort to present a single API
2684          * which works with two vastly differing underlying structures.
2685          * This acts as the demux
2686          */
2687
2688         bios_t *bios = &NVPTR(pScrn)->VBIOS;
2689         uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
2690
2691         if (!lvds_ver)
2692                 return;
2693
2694         if (lvds_ver < 0x30)
2695                 call_lvds_manufacturer_script(pScrn, head, dcb_entry, script);
2696         else
2697                 run_lvds_table(pScrn, head, dcb_entry, script, pxclk);
2698 }
2699
2700 struct fppointers {
2701         uint16_t fptablepointer;
2702         uint16_t fpxlatetableptr;
2703         uint16_t fpxlatemanufacturertableptr;
2704         int xlatwidth;
2705 };
2706
2707 static void parse_fp_mode_table(ScrnInfoPtr pScrn, bios_t *bios, struct fppointers *fpp)
2708 {
2709         unsigned int fpstrapping;
2710         uint8_t *fptable;
2711         uint8_t fptable_ver, headerlen = 0, recordlen, fpentries = 0xf, fpindex;
2712         int ofs;
2713         DisplayModePtr mode;
2714
2715         fpstrapping = (nv32_rd(pScrn, NV_PEXTDEV_BOOT_0) >> 16) & 0xf;
2716
2717         if (fpp->fptablepointer == 0x0 || fpp->fpxlatetableptr == 0x0) {
2718                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2719                            "Pointers to flat panel table invalid\n");
2720                 return;
2721         }
2722
2723         fptable = &bios->data[fpp->fptablepointer];
2724
2725         fptable_ver = fptable[0];
2726
2727         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2728                    "Found flat panel mode table revision %d.%d\n",
2729                    fptable_ver >> 4, fptable_ver & 0xf);
2730
2731         switch (fptable_ver) {
2732         /* BMP version 0x5.0x11 BIOSen have version 1 like tables, but no version field,
2733          * and miss one of the spread spectrum/PWM bytes.
2734          * This could affect early GF2Go parts (not seen any appropriate ROMs though).
2735          * Here we assume that a version of 0x05 matches this case (combining with a
2736          * BMP version check would be better), as the common case for the panel type
2737          * field is 0x0005, and that is in fact what we are reading the first byte of. */
2738         case 0x05:      /* some NV10, 11, 15, 16 */
2739                 recordlen = 42;
2740                 ofs = 6;
2741                 break;
2742         case 0x10:      /* some NV15/16, and NV11+ */
2743                 recordlen = 44;
2744                 ofs = 7;
2745                 break;
2746         case 0x20:      /* NV40+ */
2747                 headerlen = fptable[1];
2748                 recordlen = fptable[2];
2749                 fpentries = fptable[3];
2750                 /* fptable[4] is the minimum RAMDAC_FP_HCRTC->RAMDAC_FP_HSYNC_START gap.
2751                  * Only seen 0x4b (=75) which is what is used in nv_crtc.c anyway,
2752                  * so we're not using this table value for now
2753                  */
2754                 ofs = 0;
2755                 break;
2756         default:
2757                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2758                            "FP Table revision not currently supported\n");
2759                 return;
2760         }
2761
2762         fpindex = bios->data[fpp->fpxlatetableptr + fpstrapping * fpp->xlatwidth];
2763         if (fpindex > fpentries) {
2764                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2765                            "Bad flat panel table index\n");
2766                 return;
2767         }
2768
2769         /* reserved values - means that ddc or hard coded edid should be used */
2770         if (fpindex == 0xf && fpstrapping == 0xf) {
2771                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Ignoring FP table\n");
2772                 return;
2773         }
2774
2775         if (!(mode = xcalloc(1, sizeof(DisplayModeRec))))
2776                 return;
2777
2778         int modeofs = headerlen + recordlen * fpindex + ofs;
2779         mode->Clock = le16_to_cpu(*(uint16_t *)&fptable[modeofs]) * 10;
2780         mode->HDisplay = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 2]);
2781         mode->HSyncStart = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 10] + 1);
2782         mode->HSyncEnd = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 12] + 1);
2783         mode->HTotal = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 14] + 1);
2784         mode->VDisplay = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 16]);
2785         mode->VSyncStart = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 24] + 1);
2786         mode->VSyncEnd = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 26] + 1);
2787         mode->VTotal = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 28] + 1);
2788         mode->Flags |= (fptable[modeofs + 30] & 0x10) ? V_PHSYNC : V_NHSYNC;
2789         mode->Flags |= (fptable[modeofs + 30] & 0x1) ? V_PVSYNC : V_NVSYNC;
2790
2791         /* for version 1.0:
2792          * bytes 1-2 are "panel type", including bits on whether Colour/mono, single/dual link, and type (TFT etc.)
2793          * bytes 3-6 are bits per colour in RGBX
2794          * 11-12 is HDispEnd
2795          * 13-14 is HValid Start
2796          * 15-16 is HValid End
2797          * bytes 38-39 relate to spread spectrum settings
2798          * bytes 40-43 are something to do with PWM */
2799
2800         mode->prev = mode->next = NULL;
2801         mode->status = MODE_OK;
2802         mode->type = M_T_DRIVER | M_T_PREFERRED;
2803         xf86SetModeDefaultName(mode);
2804
2805 //      if (XF86_CRTC_CONFIG_PTR(pScrn)->debug_modes) {
2806                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2807                            "Found flat panel mode in BIOS tables:\n");
2808                 xf86PrintModeline(pScrn->scrnIndex, mode);
2809 //      }
2810
2811         bios->fp.native_mode = mode;
2812 }
2813
2814 static void parse_lvds_manufacturer_table_init(ScrnInfoPtr pScrn, bios_t *bios, struct fppointers *fpp)
2815 {
2816         /* The LVDS table changed considerably with BIT bioses. Previously
2817          * there was a header of version and record length, followed by several
2818          * records, indexed by a seperate xlat table, indexed in turn by the fp
2819          * strap in EXTDEV_BOOT. Each record had a config byte, followed by 6
2820          * script numbers for use by INIT_SUB which controlled panel init and
2821          * power, and finally a dword of ms to sleep between power off and on
2822          * operations.
2823          *
2824          * The BIT LVDS table has the typical BIT table header: version byte,
2825          * header length byte, record length byte, and a byte for the maximum
2826          * number of records that can be held in the table. At byte 5 in the
2827          * header is the dual-link transition pxclk (in 10s kHz) - if straps
2828          * are not being used for the panel, this specifies the frequency at
2829          * which modes should be set up in the dual link style.
2830          *
2831          * The table following the header serves as an integrated config and
2832          * xlat table: the records in the table are indexed by the FP strap
2833          * nibble in EXTDEV_BOOT, and each record has two bytes - the first as
2834          * a config byte, the second for indexing the fp mode table pointed to
2835          * by the BIT 'D' table
2836          */
2837
2838         unsigned int fpstrapping, lvdsmanufacturerindex = 0;
2839         uint8_t lvds_ver, headerlen, recordlen;
2840
2841         fpstrapping = (nv32_rd(pScrn, NV_PEXTDEV_BOOT_0) >> 16) & 0xf;
2842
2843         if (bios->fp.lvdsmanufacturerpointer == 0x0) {
2844                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2845                            "Pointer to LVDS manufacturer table invalid\n");
2846                 return;
2847         }
2848
2849         lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
2850
2851         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2852                    "Found LVDS manufacturer table revision %d.%d\n",
2853                    lvds_ver >> 4, lvds_ver & 0xf);
2854
2855         switch (lvds_ver) {
2856         case 0x0a:      /* pre NV40 */
2857                 lvdsmanufacturerindex = bios->data[fpp->fpxlatemanufacturertableptr + fpstrapping];
2858
2859                 headerlen = 2;
2860                 recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
2861
2862                 break;
2863         case 0x30:      /* NV4x */
2864                 lvdsmanufacturerindex = fpstrapping;
2865                 headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
2866                 if (headerlen < 0x1f) {
2867                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2868                                    "LVDS table header not understood\n");
2869                         return;
2870                 }
2871                 recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2];
2872                 break;
2873         case 0x40:      /* It changed again with gf8 :o( */
2874         default:
2875                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2876                            "LVDS table revision not currently supported\n");
2877                 return;
2878         }
2879
2880         uint16_t lvdsofs = bios->fp.xlated_entry = bios->fp.lvdsmanufacturerpointer + headerlen + recordlen * lvdsmanufacturerindex;
2881         switch (lvds_ver) {
2882         case 0x0a:
2883                 bios->fp.reset_after_pclk_change = bios->data[lvdsofs] & 2;
2884                 bios->fp.dual_link = bios->data[lvdsofs] & 4;
2885                 bios->fp.if_is_18bit = !(bios->data[lvdsofs] & 16);
2886                 break;
2887         case 0x30:
2888                 /* no sign of the "reset for panel on" bit, but it's safer to assume we should */
2889                 bios->fp.reset_after_pclk_change = TRUE;
2890                 bios->fp.dual_link = bios->data[lvdsofs] & 1;
2891                 bios->fp.BITbit1 = bios->data[lvdsofs] & 2;
2892                 /* BMP likely has something like this, but I have no dump to point to where it is */
2893                 bios->fp.duallink_transition_clk = le16_to_cpu(*(uint16_t *)&bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10;
2894                 fpp->fpxlatetableptr = bios->fp.lvdsmanufacturerpointer + headerlen + 1;
2895                 fpp->xlatwidth = recordlen;
2896                 break;
2897         }
2898 }
2899
2900 void run_tmds_table(ScrnInfoPtr pScrn, int dcb_entry, int head, int pxclk)
2901 {
2902         /* the dcb_entry parameter is the index of the appropriate DCB entry
2903          * the pxclk parameter is in kHz
2904          *
2905          * This runs the TMDS regs setting code found on BIT bios cards
2906          *
2907          * For ffs(or) == 1 use the first table, for ffs(or) == 2 and
2908          * ffs(or) == 3, use the second.
2909          */
2910
2911         NVPtr pNv = NVPTR(pScrn);
2912         bios_t *bios = &pNv->VBIOS;
2913         uint16_t clktable = 0, scriptptr;
2914
2915         if (pNv->dcb_table.entry[dcb_entry].location) /* off chip */
2916                 return;
2917
2918         switch (ffs(pNv->dcb_table.entry[dcb_entry].or)) {
2919         case 1:
2920                 clktable = bios->tmds.output0_script_ptr;
2921                 break;
2922         case 2:
2923         case 3:
2924                 clktable = bios->tmds.output1_script_ptr;
2925                 break;
2926         }
2927
2928         if (!clktable) {
2929                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Pixel clock comparison table not found\n");
2930                 return;
2931         }
2932
2933         scriptptr = clkcmptable(bios, clktable, pxclk);
2934
2935         if (!scriptptr) {
2936                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TMDS output init script not found\n");
2937                 return;
2938         }
2939
2940         rundigitaloutscript(pScrn, scriptptr, head, dcb_entry);
2941 }
2942
2943 static void parse_bios_version(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset)
2944 {
2945         /* offset + 0  (8 bits): Micro version
2946          * offset + 1  (8 bits): Minor version
2947          * offset + 2  (8 bits): Chip version
2948          * offset + 3  (8 bits): Major version
2949          */
2950
2951         bios->major_version = bios->data[offset + 3];
2952         bios->chip_version = bios->data[offset + 2];
2953         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bios version %02x.%02x.%02x.%02x\n",
2954                    bios->data[offset + 3], bios->data[offset + 2],
2955                    bios->data[offset + 1], bios->data[offset]);
2956 }
2957
2958 Bool get_pll_limits(ScrnInfoPtr pScrn, enum pll_types plltype, struct pll_lims *pll_lim)
2959 {
2960         /* PLL limits table
2961          *
2962          * Version 0x10: NV31
2963          * One byte header (version), one record of 24 bytes
2964          * Version 0x11: NV36 - Not implemented
2965          * Seems to have same record style as 0x10, but 3 records rather than 1
2966          * Version 0x20: Found on Geforce 6 cards
2967          * Trivial 4 byte BIT header. 31 (0x1f) byte record length
2968          * Version 0x21: Found on Geforce 7, 8 and some Geforce 6 cards
2969          * 5 byte header, fifth byte of unknown purpose. 35 (0x23) byte record length
2970          */
2971
2972         bios_t *bios = &NVPTR(pScrn)->VBIOS;
2973         uint8_t pll_lim_ver, headerlen, recordlen, entries;
2974         int pllindex = 0, i;
2975
2976         if (!bios->pll_limit_tbl_ptr) {
2977                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Pointer to PLL limits table invalid\n");
2978                 return FALSE;
2979         }
2980
2981         pll_lim_ver = bios->data[bios->pll_limit_tbl_ptr + 0];
2982
2983         if (DEBUGLEVEL >= 6)
2984                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2985                            "Found BIT PLL limits table version 0x%X\n", pll_lim_ver);
2986
2987         switch (pll_lim_ver) {
2988         case 0x10:
2989                 headerlen = 1;
2990                 recordlen = 0x18;
2991                 entries = 1;
2992                 pllindex = 0;
2993                 break;
2994         case 0x20:
2995         case 0x21:
2996                 headerlen = bios->data[bios->pll_limit_tbl_ptr + 1];
2997                 recordlen = bios->data[bios->pll_limit_tbl_ptr + 2];
2998                 entries = bios->data[bios->pll_limit_tbl_ptr + 3];
2999                 break;
3000         default:
3001                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3002                            "PLL limits table revision not currently supported\n");
3003                 return FALSE;
3004         }
3005
3006         /* initialize all members to zero */
3007         memset (pll_lim, 0, sizeof(struct pll_lims));
3008
3009         if (pll_lim_ver == 0x10) {
3010                 uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex;
3011
3012                 pll_lim->vco1.minfreq = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs])));
3013                 pll_lim->vco1.maxfreq = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs + 4])));
3014                 pll_lim->vco2.minfreq = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs + 8])));
3015                 pll_lim->vco2.maxfreq = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs + 12])));
3016                 pll_lim->vco1.min_inputfreq = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs + 16])));
3017                 pll_lim->vco2.min_inputfreq = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs + 20])));
3018                 pll_lim->vco1.max_inputfreq = pll_lim->vco2.max_inputfreq = INT_MAX;
3019
3020                 /* these values taken from nv31. nv30, nv36 might do better with different ones */
3021                 pll_lim->vco1.min_n = 0x1;
3022                 pll_lim->vco1.max_n = 0xff;
3023                 pll_lim->vco1.min_m = 0x1;
3024                 pll_lim->vco1.max_m = 0xd;
3025                 pll_lim->vco2.min_n = 0x4;
3026                 pll_lim->vco2.max_n = 0x46;
3027                 if (bios->chip_version == 0x30)
3028                        /* only 5 bits available for N2 on nv30 */
3029                         pll_lim->vco2.max_n = 0x1f;
3030                 if (bios->chip_version == 0x31)
3031                         /* on nv31, N2 is compared to maxN2 (0x46) and maxM2 (0x4),
3032                          * so set maxN2 to 0x4 and save a comparison
3033                          */
3034                         pll_lim->vco2.max_n = 0x4;
3035                 pll_lim->vco2.min_m = 0x1;
3036                 pll_lim->vco2.max_m = 0x4;
3037         } else {        /* ver 0x20, 0x21 */
3038                 uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen;
3039
3040                 for (i = 0; i < entries; i++) {
3041                         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs + recordlen * i])));
3042
3043                         if (plltype == VPLL1 && (reg == 0x680508 || reg == 0x4010)) {
3044                                 pllindex = i;
3045                                 break;
3046                         }
3047                         if (plltype == VPLL2 && (reg == 0x680520 || reg == 0x4018)) {
3048                                 pllindex = i;
3049                                 break;
3050                         }
3051                         if (reg == 0x0000) /* generic pll settings */
3052                                 pllindex = i;
3053                 }
3054
3055                 plloffs += recordlen * pllindex;
3056
3057                 if (DEBUGLEVEL >= 6)
3058                         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Loading PLL limits for reg 0x%08x\n",
3059                                    le32_to_cpu(*((uint32_t *)(&bios->data[plloffs]))));
3060
3061                 /* frequencies are stored in tables in MHz, kHz are more useful, so we convert */
3062
3063                 /* What output frequencies can each VCO generate? */
3064                 pll_lim->vco1.minfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 4]))) * 1000;
3065                 pll_lim->vco1.maxfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 6]))) * 1000;
3066                 pll_lim->vco2.minfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 8]))) * 1000;
3067                 pll_lim->vco2.maxfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 10]))) * 1000;
3068
3069                 /* What input frequencies do they accept (past the m-divider)? */
3070                 pll_lim->vco1.min_inputfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 12]))) * 1000;
3071                 pll_lim->vco2.min_inputfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 14]))) * 1000;
3072                 pll_lim->vco1.max_inputfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 16]))) * 1000;
3073                 pll_lim->vco2.max_inputfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 18]))) * 1000;
3074
3075                 /* What values are accepted as multiplier and divider? */
3076                 pll_lim->vco1.min_n = bios->data[plloffs + 20];
3077                 pll_lim->vco1.max_n = bios->data[plloffs + 21];
3078                 pll_lim->vco1.min_m = bios->data[plloffs + 22];
3079                 pll_lim->vco1.max_m = bios->data[plloffs + 23];
3080                 pll_lim->vco2.min_n = bios->data[plloffs + 24];
3081                 pll_lim->vco2.max_n = bios->data[plloffs + 25];
3082                 pll_lim->vco2.min_m = bios->data[plloffs + 26];
3083                 pll_lim->vco2.max_m = bios->data[plloffs + 27];
3084
3085                 pll_lim->unk1c = bios->data[plloffs + 28]; /* minP? */
3086                 pll_lim->unk1d = bios->data[plloffs + 29]; /* maxP? */
3087                 pll_lim->unk1e = bios->data[plloffs + 30];
3088
3089                 if (recordlen > 0x22)
3090                         pll_lim->refclk = le32_to_cpu(*((uint32_t *)&bios->data[plloffs + 31]));
3091         }
3092
3093 #if 1 /* for easy debugging */
3094         ErrorF("pll.vco1.minfreq: %d\n", pll_lim->vco1.minfreq);
3095         ErrorF("pll.vco1.maxfreq: %d\n", pll_lim->vco1.maxfreq);
3096         ErrorF("pll.vco2.minfreq: %d\n", pll_lim->vco2.minfreq);
3097         ErrorF("pll.vco2.maxfreq: %d\n", pll_lim->vco2.maxfreq);
3098
3099         ErrorF("pll.vco1.min_inputfreq: %d\n", pll_lim->vco1.min_inputfreq);
3100         ErrorF("pll.vco1.max_inputfreq: %d\n", pll_lim->vco1.max_inputfreq);
3101         ErrorF("pll.vco2.min_inputfreq: %d\n", pll_lim->vco2.min_inputfreq);
3102         ErrorF("pll.vco2.max_inputfreq: %d\n", pll_lim->vco2.max_inputfreq);
3103
3104         ErrorF("pll.vco1.min_n: %d\n", pll_lim->vco1.min_n);
3105         ErrorF("pll.vco1.max_n: %d\n", pll_lim->vco1.max_n);
3106         ErrorF("pll.vco1.min_m: %d\n", pll_lim->vco1.min_m);
3107         ErrorF("pll.vco1.max_m: %d\n", pll_lim->vco1.max_m);
3108         ErrorF("pll.vco2.min_n: %d\n", pll_lim->vco2.min_n);
3109         ErrorF("pll.vco2.max_n: %d\n", pll_lim->vco2.max_n);
3110         ErrorF("pll.vco2.min_m: %d\n", pll_lim->vco2.min_m);
3111         ErrorF("pll.vco2.max_m: %d\n", pll_lim->vco2.max_m);
3112
3113         ErrorF("pll.unk1c: %d\n", pll_lim->unk1c);
3114         ErrorF("pll.unk1d: %d\n", pll_lim->unk1d);
3115         ErrorF("pll.unk1e: %d\n", pll_lim->unk1e);
3116 #endif
3117
3118         return TRUE;
3119 }
3120
3121 static int parse_bit_B_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
3122 {
3123         /* offset + 0  (32 bits): BIOS version dword
3124          *
3125          * There's a bunch of bits in this table other than the bios version
3126          * that we don't use - their use currently unknown
3127          */
3128
3129         if (bitentry->length < 0x4) {
3130                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3131                            "Do not understand B table entry\n");
3132                 return 0;
3133         }
3134
3135         parse_bios_version(pScrn, bios, bitentry->offset);
3136
3137         return 1;
3138 }
3139
3140 static int parse_bit_C_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
3141 {
3142         /* offset + 8  (16 bits): PLL limits table pointer
3143          *
3144          * There's more in here, but that's unknown.
3145          */
3146
3147         if (bitentry->length < 10) {
3148                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Do not understand C table entry\n");
3149                 return 0;
3150         }
3151
3152         bios->pll_limit_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 8])));
3153
3154         return 1;
3155 }
3156
3157 static int parse_bit_display_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry, struct fppointers *fpp)
3158 {
3159         /* Parses the flat panel table segment that the bit entry points to.
3160          * Starting at bitentry->offset:
3161          *
3162          * offset + 0  (16 bits): FIXME table pointer
3163          * offset + 2  (16 bits): mode table pointer
3164          */
3165
3166         if (bitentry->length != 4) {
3167                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3168                            "Do not understand BIT display table entry\n");
3169                 return 0;
3170         }
3171
3172         fpp->fptablepointer = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 2])));
3173
3174         return 1;
3175 }
3176
3177 static unsigned int parse_bit_init_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
3178 {
3179         /* Parses the init table segment that the bit entry points to.
3180          * Starting at bitentry->offset: 
3181          * 
3182          * offset + 0  (16 bits): init script tables pointer
3183          * offset + 2  (16 bits): macro index table pointer
3184          * offset + 4  (16 bits): macro table pointer
3185          * offset + 6  (16 bits): condition table pointer
3186          * offset + 8  (16 bits): io condition table pointer
3187          * offset + 10 (16 bits): io flag condition table pointer
3188          * offset + 12 (16 bits): init function table pointer
3189          *
3190          */
3191
3192         if (bitentry->length < 14) {
3193                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3194                            "Unable to recognize BIT init table entry\n");
3195                 return 0;
3196         }
3197
3198         bios->init_script_tbls_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset])));
3199         bios->macro_index_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 2])));
3200         bios->macro_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 4])));
3201         bios->condition_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 6])));
3202         bios->io_condition_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 8])));
3203         bios->io_flag_condition_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 10])));
3204         bios->init_function_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 12])));
3205
3206         return 1;
3207 }
3208
3209 static int parse_bit_i_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
3210 {
3211         /* offset + 13 (16 bits): pointer to table containing DAC load detection comparison values
3212          *
3213          * There's other things in this table, purpose unknown
3214          */
3215
3216         uint16_t offset;
3217
3218         if (bitentry->length < 15) {
3219                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3220                            "BIT i table not long enough for DAC load detection comparison table\n");
3221                 return 0;
3222         }
3223
3224         offset = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 13])));
3225
3226         /* doesn't exist on g80 */
3227         if (!offset)
3228                 return 1;
3229
3230         /* The first value in the table, following the header, is the comparison value
3231          * Purpose of subsequent values unknown - TV load detection?
3232          */
3233
3234         uint8_t version = bios->data[offset];
3235
3236         if (version != 0x00 && version != 0x10) {
3237                 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3238                            "DAC load detection comparison table version %d.%d not known\n",
3239                            version >> 4, version & 0xf);
3240                 return 0;
3241         }
3242
3243         uint8_t headerlen = bios->data[offset + 1];
3244
3245         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3246                    "DAC load detection comparison table version %x found\n", version);
3247
3248         bios->dactestval = le32_to_cpu(*((uint32_t *)(&bios->data[offset + headerlen])));
3249
3250         return 1;
3251 }
3252
3253 static int parse_bit_lvds_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry, struct fppointers *fpp)
3254 {
3255         /* Parses the LVDS table segment that the bit entry points to.
3256          * Starting at bitentry->offset:
3257          *
3258          * offset + 0  (16 bits): LVDS strap xlate table pointer
3259          */
3260
3261         if (bitentry->length != 2) {
3262                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3263                            "Do not understand BIT LVDS table entry\n");
3264                 return 0;
3265         }
3266
3267         /* no idea if it's still called the LVDS manufacturer table, but the concept's close enough */
3268         bios->fp.lvdsmanufacturerpointer = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset])));
3269
3270         parse_lvds_manufacturer_table_init(pScrn, bios, fpp);
3271
3272         return 1;
3273 }
3274
3275 static int parse_bit_M_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
3276 {
3277         /* offset + 2  (8  bits): number of options in an INIT_RAM_RESTRICT_ZM_REG_GROUP opcode option set
3278          * offset + 3  (16 bits): pointer to strap xlate table for RAM restrict option selection
3279          *
3280          * There's a bunch of bits in this table other than the RAM restrict
3281          * stuff that we don't use - their use currently unknown
3282          */
3283
3284         int i;
3285
3286         /* Older bios versions don't have a sufficiently long table for what we want */
3287         if (bitentry->length < 0x5)
3288                 return 1;
3289
3290         /* set up multiplier for INIT_RAM_RESTRICT_ZM_REG_GROUP */
3291         for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != 0x8f); i++)
3292                 ;
3293         itbl_entry[i].length_multiplier = bios->data[bitentry->offset + 2] * 4;
3294         init_ram_restrict_zm_reg_group_blocklen = itbl_entry[i].length_multiplier;
3295
3296         bios->ram_restrict_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 3])));
3297
3298         return 1;
3299 }
3300
3301 static int parse_bit_tmds_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
3302 {
3303         /* Parses the pointer to the TMDS table
3304          *
3305          * Starting at bitentry->offset:
3306          *
3307          * offset + 0  (16 bits): TMDS table pointer
3308          *
3309          * The TMDS table is typically found just before the DCB table, with a
3310          * characteristic signature of 0x11,0x13 (1.1 being version, 0x13 being
3311          * length?)
3312          *
3313          * At offset +7 is a pointer to a script, which I don't know how to run yet
3314          * At offset +9 is a pointer to another script, likewise
3315          * Offset +11 has a pointer to a table where the first word is a pxclk
3316          * frequency and the second word a pointer to a script, which should be
3317          * run if the comparison pxclk frequency is less than the pxclk desired.
3318          * This repeats for decreasing comparison frequencies
3319          * Offset +13 has a pointer to a similar table
3320          * The selection of table (and possibly +7/+9 script) is dictated by
3321          * "or" from the DCB.
3322          */
3323
3324         uint16_t tmdstableptr, script1, script2;
3325
3326         if (bitentry->length != 2) {
3327                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3328                            "Do not understand BIT TMDS table entry\n");
3329                 return 0;
3330         }
3331
3332         tmdstableptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset])));
3333
3334         if (tmdstableptr == 0x0) {
3335                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Pointer to TMDS table invalid\n");
3336                 return 0;
3337         }
3338
3339         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found TMDS table revision %d.%d\n",
3340                    bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf);
3341
3342         /* These two scripts are odd: they don't seem to get run even when they are not stubbed */
3343         script1 = le16_to_cpu(*((uint16_t *)&bios->data[tmdstableptr + 7]));
3344         script2 = le16_to_cpu(*((uint16_t *)&bios->data[tmdstableptr + 9]));
3345         if (bios->data[script1] != 'q' || bios->data[script2] != 'q')
3346                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TMDS table script pointers not stubbed\n");
3347
3348         bios->tmds.output0_script_ptr = le16_to_cpu(*((uint16_t *)&bios->data[tmdstableptr + 11]));
3349         bios->tmds.output1_script_ptr = le16_to_cpu(*((uint16_t *)&bios->data[tmdstableptr + 13]));
3350
3351         return 1;
3352 }
3353
3354 static void parse_bit_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
3355 {
3356         bit_entry_t bitentry;
3357         char done = 0;
3358         struct fppointers fpp;
3359         NVPtr pNv = NVPTR(pScrn);
3360
3361         memset(&fpp, 0, sizeof(struct fppointers));
3362
3363         while (!done) {
3364                 bitentry.id[0] = bios->data[offset];
3365                 bitentry.id[1] = bios->data[offset + 1];
3366                 bitentry.length = le16_to_cpu(*((uint16_t *)&bios->data[offset + 2]));
3367                 bitentry.offset = le16_to_cpu(*((uint16_t *)&bios->data[offset + 4]));
3368
3369                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3370                            "0x%04X: Found BIT command with id 0x%02X (%c)\n",
3371                            offset, bitentry.id[0], bitentry.id[0]);
3372
3373                 switch (bitentry.id[0]) {
3374                 case 0:
3375                         /* id[0] = 0 and id[1] = 0 ==> end of BIT struture */
3376                         if (bitentry.id[1] == 0)
3377                                 done = 1;
3378                         break;
3379                 case 'B':
3380                         parse_bit_B_tbl_entry(pScrn, bios, &bitentry);
3381                         break;
3382                 case 'C':
3383                         parse_bit_C_tbl_entry(pScrn, bios, &bitentry);
3384                         break;
3385                 case 'D':
3386                         parse_bit_display_tbl_entry(pScrn, bios, &bitentry, &fpp);
3387                         break;
3388                 case 'I':
3389                         parse_bit_init_tbl_entry(pScrn, bios, &bitentry);
3390                         break;
3391                 case 'i':
3392                         parse_bit_i_tbl_entry(pScrn, bios, &bitentry);
3393                         break;
3394                 case 'L':
3395                         parse_bit_lvds_tbl_entry(pScrn, bios, &bitentry, &fpp);
3396                         break;
3397                 case 'M': /* memory? */
3398                         parse_bit_M_tbl_entry(pScrn, bios, &bitentry);
3399                         break;
3400                 case 'T':
3401                         parse_bit_tmds_tbl_entry(pScrn, bios, &bitentry);
3402                         break;
3403                 }
3404
3405                 offset += sizeof(bit_entry_t);
3406         }
3407
3408         /* C and M tables have to be parsed before init can run */
3409         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3410                    "Parsing previously deferred init table entry\n");
3411         parse_init_tables(pScrn, bios);
3412
3413         /* If it's not a laptop, you probably don't care about LVDS */
3414         /* FIXME: detect mobile BIOS? */
3415         if (!pNv->Mobile)
3416                 return;
3417
3418         /* Need D and L tables parsed before doing this */
3419         parse_fp_mode_table(pScrn, bios, &fpp);
3420 }
3421
3422 static void parse_bmp_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
3423 {
3424         /* Parse the BMP structure for useful things
3425          *
3426          * offset +   5: BMP major version
3427          * offset +   6: BMP minor version
3428          * offset +  10: BCD encoded BIOS version
3429          *
3430          * offset +  18: init script table pointer (for bios versions < 5.10h)
3431          * offset +  20: extra init script table pointer (for bios versions < 5.10h)
3432          *
3433          * offset +  24: FIXME
3434          * offset +  26: FIXME
3435          * offset +  28: FIXME
3436          *
3437          * offset +  54: index of I2C CRTC pair to use for CRT output
3438          * offset +  55: index of I2C CRTC pair to use for TV output
3439          * offset +  56: index of I2C CRTC pair to use for flat panel output
3440          * offset +  58: write CRTC index for I2C pair 0
3441          * offset +  59: read CRTC index for I2C pair 0
3442          * offset +  60: write CRTC index for I2C pair 1
3443          * offset +  61: read CRTC index for I2C pair 1
3444          *
3445          * offset +  67: maximum internal PLL frequency (single stage PLL)
3446          * offset +  71: minimum internal PLL frequency (single stage PLL)
3447          *
3448          * offset +  75: script table pointers, as for parse_bit_init_tbl_entry
3449          *
3450          * offset +  89: TMDS single link output A table pointer
3451          * offset +  91: TMDS single link output B table pointer
3452          * offset + 105: flat panel timings table pointer
3453          * offset + 107: flat panel strapping translation table pointer
3454          * offset + 117: LVDS manufacturer panel config table pointer
3455          * offset + 119: LVDS manufacturer strapping translation table pointer
3456          *
3457          * offset + 142: PLL limits table pointer
3458          */
3459
3460         NVPtr pNv = NVPTR(pScrn);
3461         uint16_t bmplength;
3462         struct fppointers fpp;
3463         memset(&fpp, 0, sizeof(struct fppointers));
3464
3465         uint8_t bmp_version_major = bios->data[offset + 5];
3466         uint8_t bmp_version_minor = bios->data[offset + 6];
3467
3468         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BMP version %d.%d\n",
3469                    bmp_version_major, bmp_version_minor);
3470
3471         /* version 6 could theoretically exist, but I suspect BIT happened instead */
3472         if (bmp_version_major < 2 || bmp_version_major > 5) {
3473                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "You have an unsupported BMP version. Please send in your bios\n");
3474                 return;
3475         }
3476
3477         if (bmp_version_major == 2)
3478                 bmplength = 48; /* exact for 2.01 - not sure if minor version used in versions < 5 */
3479         else if (bmp_version_major == 3)
3480                 bmplength = 54; /* guessed - mem init tables added in this version */
3481         else if (bmp_version_major == 4 || bmp_version_minor < 0x1) /* don't know if 5.0 exists... */
3482                 bmplength = 62; /* guessed - BMP I2C indices added in version 4*/
3483         else if (bmp_version_minor < 0x6)
3484                 bmplength = 67; /* exact for 5.01 */
3485         else if (bmp_version_minor < 0x10)
3486                 bmplength = 75; /* exact for 5.06 */
3487         else if (bmp_version_minor == 0x10)
3488                 bmplength = 89; /* exact for 5.10h */
3489         else if (bmp_version_minor < 0x14)
3490                 bmplength = 118; /* exact for 5.11h */
3491         else if (bmp_version_minor < 0x24) /* not sure of version where pll limits came in;
3492                                             * certainly exist by 0x24 though */
3493                 /* length not exact: this is long enough to get lvds members */
3494                 bmplength = 123;
3495         else
3496                 /* length not exact: this is long enough to get pll limit member */
3497                 bmplength = 144;
3498
3499         /* checksum */
3500         if (nv_cksum(bios->data + offset, 8)) {
3501                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad BMP checksum\n");
3502                 return;
3503         }
3504
3505         parse_bios_version(pScrn, bios, offset + 10);
3506
3507         bios->init_script_tbls_ptr = le16_to_cpu(*(uint16_t *)&bios->data[offset + 18]);
3508         bios->extra_init_script_tbl_ptr = le16_to_cpu(*(uint16_t *)&bios->data[offset + 20]);
3509
3510 #if 0
3511         // FIXME needed for pre v16? - haiku uses this in its COMPUTE_MEM on early biosen
3512         if (bmp_version_major > 2) {
3513                 uint16_t meminittbl = le16_to_cpu(*(uint16_t *)&bios->data[offset + 24]);
3514                 uint16_t sdrmemseqtbl = le16_to_cpu(*(uint16_t *)&bios->data[offset + 26]);
3515                 uint16_t ddrmemseqtbl = le16_to_cpu(*(uint16_t *)&bios->data[offset + 28]);
3516         }
3517 #endif
3518
3519         uint16_t legacy_i2c_offset = 0x48;      /* BMP version 2 & 3 */
3520         if (bmplength > 61)
3521                 legacy_i2c_offset = offset + 54;
3522         bios->legacy_i2c_indices.crt = bios->data[legacy_i2c_offset];
3523         bios->legacy_i2c_indices.tv = bios->data[legacy_i2c_offset + 1];
3524         bios->legacy_i2c_indices.panel = bios->data[legacy_i2c_offset + 2];
3525         pNv->dcb_table.i2c_write[0] = bios->data[legacy_i2c_offset + 4];
3526         pNv->dcb_table.i2c_read[0] = bios->data[legacy_i2c_offset + 5];
3527         pNv->dcb_table.i2c_write[1] = bios->data[legacy_i2c_offset + 6];
3528         pNv->dcb_table.i2c_read[1] = bios->data[legacy_i2c_offset + 7];
3529
3530         if (bmplength > 74) {
3531                 bios->fmaxvco = le32_to_cpu(*((uint32_t *)&bios->data[offset + 67]));
3532                 bios->fminvco = le32_to_cpu(*((uint32_t *)&bios->data[offset + 71]));
3533         }
3534         if (bmplength > 88) {
3535                 bit_entry_t initbitentry;
3536                 initbitentry.length = 14;
3537                 initbitentry.offset = offset + 75;
3538                 parse_bit_init_tbl_entry(pScrn, bios, &initbitentry);
3539         }
3540         if (bmplength > 92) {
3541                 bios->tmds.output0_script_ptr = le16_to_cpu(*((uint16_t *)&bios->data[offset + 89]));
3542                 bios->tmds.output1_script_ptr = le16_to_cpu(*((uint16_t *)&bios->data[offset + 91]));
3543         }
3544         if (bmplength > 108) {
3545                 fpp.fptablepointer = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 105])));
3546                 fpp.fpxlatetableptr = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 107])));
3547                 fpp.xlatwidth = 1;
3548         }
3549         if (bmplength > 120) {
3550                 bios->fp.lvdsmanufacturerpointer = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 117])));
3551                 fpp.fpxlatemanufacturertableptr = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 119])));
3552         }
3553         if (bmplength > 143)
3554                 bios->pll_limit_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 142])));
3555
3556         /* want pll_limit_tbl_ptr set (if available) before init is run */
3557         if (bmp_version_major < 5 || bmp_version_minor < 0x10) {
3558                 init_exec_t iexec = {TRUE, FALSE};
3559                 parse_init_table(pScrn, bios, bios->init_script_tbls_ptr, &iexec);
3560                 parse_init_table(pScrn, bios, bios->extra_init_script_tbl_ptr, &iexec);
3561         } else
3562                 parse_init_tables(pScrn, bios);
3563
3564         /* If it's not a laptop, you probably don't care about fptables */
3565         /* FIXME: detect mobile BIOS? */
3566         if (!pNv->Mobile)
3567                 return;
3568
3569         parse_fp_mode_table(pScrn, bios, &fpp);
3570         parse_lvds_manufacturer_table_init(pScrn, bios, &fpp);
3571         /* I've never seen a valid LVDS_INIT script, so we'll do a test for it here */
3572         call_lvds_script(pScrn, 0, 0, LVDS_INIT, 0);
3573 }
3574
3575 static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len)
3576 {
3577         int i, j;
3578
3579         for (i = 0; i <= (n - len); i++) {
3580                 for (j = 0; j < len; j++)
3581                         if (data[i + j] != str[j])
3582                                 break;
3583                 if (j == len)
3584                         return i;
3585         }
3586
3587         return 0;
3588 }
3589
3590 static Bool parse_dcb_entry(ScrnInfoPtr pScrn, uint8_t dcb_version, uint32_t conn, uint32_t conf, struct dcb_entry *entry)
3591 {
3592         NVPtr pNv = NVPTR(pScrn);
3593
3594         memset(entry, 0, sizeof (struct dcb_entry));
3595
3596         /* safe defaults for a crt */
3597         entry->type = 0;
3598         entry->i2c_index = 0;
3599         entry->heads = 1;
3600         entry->bus = 0;
3601         entry->location = 0;
3602         entry->or = 1;
3603         entry->duallink_possible = FALSE;
3604
3605         if (dcb_version >= 0x20) {
3606                 entry->type = conn & 0xf;
3607                 entry->i2c_index = (conn >> 4) & 0xf;
3608                 entry->heads = (conn >> 8) & 0xf;
3609                 entry->bus = (conn >> 16) & 0xf;
3610                 entry->location = (conn >> 20) & 0xf;
3611                 entry->or = (conn >> 24) & 0xf;
3612                 /* Normal entries consist of a single bit, but dual link has the
3613                  * adjacent more significant bit set too
3614                  */
3615                 if ((1 << (ffs(entry->or) - 1)) * 3 == entry->or)
3616                         entry->duallink_possible = TRUE;
3617
3618                 switch (entry->type) {
3619                 case OUTPUT_LVDS:
3620                         if (conf & 0xfffffffa)
3621                                 ErrorF("Unknown LVDS configuration bits, please report\n");
3622                         if (conf & 0x1)
3623                                 entry->lvdsconf.use_straps_for_mode = TRUE;
3624                         if (conf & 0x4)
3625                                 entry->lvdsconf.use_power_scripts = TRUE;
3626                         break;
3627                 }
3628         } else if (dcb_version >= 0x14 ) {
3629                 if (conn != 0xf0003f00 && conn != 0xf2204301 && conn != 0xf2045f14 && conn != 0xf2205004 && conn != 0xf4204011) {
3630                         ErrorF("Unknown DCB 1.4 / 1.5 entry, please report\n");
3631                         /* cause output setting to fail, so message is seen */
3632                         pNv->dcb_table.entries = 0;
3633                         return FALSE;
3634                 }
3635                 /* most of the below is a "best guess" atm */
3636                 entry->type = conn & 0xf;
3637                 if (entry->type == 4) { /* digital */
3638                         if (conn & 0x10)
3639                                 entry->type = OUTPUT_LVDS;
3640                         else
3641                                 /* FIXME: do we need to add a DVI-A analogue output in this case,
3642                                  * assuming this connector is DVI-I, not pure DVI-D?
3643                                  */
3644                                 entry->type = OUTPUT_TMDS;
3645                 }
3646                 /* what's in bits 5-13? could be some brooktree/chrontel/philips thing, in tv case */
3647                 entry->i2c_index = (conn >> 14) & 0xf;
3648                 /* raw heads field is in range 0-1, so move to 1-2 */
3649                 entry->heads = ((conn >> 18) & 0x7) + 1;
3650                 entry->location = (conn >> 21) & 0xf;
3651                 entry->bus = (conn >> 25) & 0x7;
3652                 /* set or to be same as heads -- hopefully safe enough */
3653                 entry->or = entry->heads;
3654
3655                 switch (entry->type) {
3656                 case OUTPUT_LVDS:
3657                         /* these are probably buried in conn's unknown bits */
3658                         entry->lvdsconf.use_straps_for_mode = TRUE;
3659                         entry->lvdsconf.use_power_scripts = TRUE;
3660                         break;
3661                 }
3662         } else if (dcb_version >= 0x12) {
3663                 /* use the defaults for a crt
3664                  * v1.2 tables often have other entries though - need a trace
3665                  */
3666                 entry->type = conn & 0xf;       // this is valid, but will probably confuse the randr stuff
3667                 entry->type = 0;
3668         } else { /* pre DCB / v1.1 - use the safe defaults for a crt */
3669                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3670                            "No information in BIOS output table; assuming a CRT output exists\n");
3671                 entry->i2c_index = pNv->VBIOS.legacy_i2c_indices.crt;
3672         }
3673
3674         pNv->dcb_table.entries++;
3675
3676         return TRUE;
3677 }
3678
3679 static void
3680 read_dcb_i2c_table(ScrnInfoPtr pScrn, bios_t *bios, uint8_t dcb_version, uint16_t i2ctabptr)
3681 {
3682         NVPtr pNv = NVPTR(pScrn);
3683         uint8_t *i2ctable;
3684         uint8_t headerlen = 0;
3685         int i2c_entries;
3686         int recordoffset = 0, rdofs = 1, wrofs = 0;
3687         int i;
3688
3689         i2c_entries = MAX_NUM_DCB_ENTRIES;
3690         memset(pNv->dcb_table.i2c_read, 0, sizeof(pNv->dcb_table.i2c_read));
3691         memset(pNv->dcb_table.i2c_write, 0, sizeof(pNv->dcb_table.i2c_write));
3692
3693         i2ctable = &bios->data[i2ctabptr];
3694
3695         if (dcb_version >= 0x30) {
3696                 if (i2ctable[0] != dcb_version) { /* necessary? */
3697                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3698                                    "DCB I2C table version mismatch (%02X vs %02X)\n",
3699                                    i2ctable[0], dcb_version);
3700                         return;
3701                 }
3702                 headerlen = i2ctable[1];
3703                 i2c_entries = i2ctable[2];
3704                 if (i2ctable[0] >= 0x40) {
3705                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3706                                    "G80 DCB I2C table detected, arrgh\n"); /* they're plain weird */
3707                         return;
3708                 }
3709         }
3710         /* it's your own fault if you call this function on a DCB 1.1 BIOS --
3711          * the below assumes DCB 1.2
3712          */
3713         if (dcb_version < 0x14) {
3714                 recordoffset = 2;
3715                 rdofs = 0;
3716                 wrofs = 1;
3717         }
3718
3719         for (i = 0; i < i2c_entries; i++)
3720                 if (i2ctable[headerlen + 4 * i + 3] != 0xff) {
3721                         pNv->dcb_table.i2c_read[i] = i2ctable[headerlen + recordoffset + rdofs + 4 * i];
3722                         pNv->dcb_table.i2c_write[i] = i2ctable[headerlen + recordoffset + wrofs + 4 * i];
3723                 }
3724 }
3725
3726 static unsigned int parse_dcb_table(ScrnInfoPtr pScrn, bios_t *bios)
3727 {
3728         NVPtr pNv = NVPTR(pScrn);
3729         uint16_t dcbptr, i2ctabptr = 0;
3730         uint8_t *dcbtable;
3731         uint8_t dcb_version, headerlen = 0x4, entries = MAX_NUM_DCB_ENTRIES;
3732         Bool configblock = TRUE;
3733         int recordlength = 8, confofs = 4;
3734         int i;
3735
3736         pNv->dcb_table.entries = 0;
3737
3738         /* get the offset from 0x36 */
3739         dcbptr = le16_to_cpu(*(uint16_t *)&bios->data[0x36]);
3740
3741         if (dcbptr == 0x0) {
3742                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3743                            "No Display Configuration Block pointer found\n");
3744                 /* this situation likely means a really old card, pre DCB, so we'll add the safe CRT entry */
3745                 parse_dcb_entry(pScrn, 0, 0, 0, &pNv->dcb_table.entry[0]);
3746                 return 1;
3747         }
3748
3749         dcbtable = &bios->data[dcbptr];
3750
3751         /* get DCB version */
3752         dcb_version = dcbtable[0];
3753         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3754                    "Display Configuration Block version %d.%d found\n",
3755                    dcb_version >> 4, dcb_version & 0xf);
3756
3757         if (dcb_version >= 0x20) { /* NV17+ */
3758                 uint32_t sig;
3759
3760                 if (dcb_version >= 0x30) { /* NV40+ */
3761                         headerlen = dcbtable[1];
3762                         entries = dcbtable[2];
3763                         i2ctabptr = le16_to_cpu(*(uint16_t *)&dcbtable[4]);
3764                         sig = le32_to_cpu(*(uint32_t *)&dcbtable[6]);
3765
3766                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3767                                    "DCB header length %02X, with %02X possible entries\n",
3768                                    headerlen, entries);
3769                 } else {
3770                         /* dcb_block_count = *(dcbtable[1]); */
3771                         i2ctabptr = le16_to_cpu(*(uint16_t *)&dcbtable[2]);
3772                         sig = le32_to_cpu(*(uint32_t *)&dcbtable[4]);
3773                         headerlen = 8;
3774                 }
3775
3776                 if (sig != 0x4edcbdcb) {
3777                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3778                                    "Bad Display Configuration Block signature (%08X)\n", sig);
3779                         return 0;
3780                 }
3781         } else if (dcb_version >= 0x14) { /* some NV15/16, and NV11+ */
3782                 char sig[8];
3783
3784                 memset(sig, 0, 8);
3785                 strncpy(sig, (char *)&dcbtable[-7], 7);
3786                 /* dcb_block_count = *(dcbtable[1]); */
3787                 i2ctabptr = le16_to_cpu(*(uint16_t *)&dcbtable[2]);
3788                 recordlength = 10;
3789                 confofs = 6;
3790
3791                 if (strcmp(sig, "DEV_REC")) {
3792                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3793                                    "Bad Display Configuration Block signature (%s)\n", sig);
3794                         return 0;
3795                 }
3796         } else if (dcb_version >= 0x12) { /* some NV6/10, and NV15+ */
3797                 /* dcb_block_count = *(dcbtable[1]); */
3798                 i2ctabptr = le16_to_cpu(*(uint16_t *)&dcbtable[2]);
3799                 configblock = FALSE;
3800         } else {        /* NV5+, maybe NV4 */
3801                 /* DCB 1.1 seems to be quite unhelpful - we'll just add the safe CRT entry */
3802                 parse_dcb_entry(pScrn, dcb_version, 0, 0, &pNv->dcb_table.entry[0]);
3803                 return 1;
3804         }
3805
3806         if (entries >= MAX_NUM_DCB_ENTRIES)
3807                 entries = MAX_NUM_DCB_ENTRIES;
3808
3809         for (i = 0; i < entries; i++) {
3810                 uint32_t connection, config = 0;
3811
3812                 connection = le32_to_cpu(*(uint32_t *)&dcbtable[headerlen + recordlength * i]);
3813                 if (configblock)
3814                         config = le32_to_cpu(*(uint32_t *)&dcbtable[headerlen + confofs + recordlength * i]);
3815
3816                 /* Should we allow discontinuous DCBs? Certainly DCB I2C tables
3817                  * can be discontinuous */
3818                 if ((connection & 0x0000000f) == 0x0000000f) /* end of records */
3819                         break;
3820
3821                 ErrorF("Raw DCB entry %d: %08x %08x\n", i, connection, config);
3822                 if (!parse_dcb_entry(pScrn, dcb_version, connection, config, &pNv->dcb_table.entry[i]))
3823                         break;
3824         }
3825
3826         read_dcb_i2c_table(pScrn, bios, dcb_version, i2ctabptr);
3827
3828         /* DCB v2.0, in particular, lists each output combination separately.
3829          * Here we merge compatible entries to have fewer outputs, with more options
3830          */
3831         for (i = 0; i < pNv->dcb_table.entries; i++) {
3832                 struct dcb_entry *ient = &pNv->dcb_table.entry[i];
3833                 int j;
3834
3835                 for (j = i + 1; j < pNv->dcb_table.entries; j++) {
3836                         struct dcb_entry *jent = &pNv->dcb_table.entry[j];
3837
3838                         if (jent->type == 100) /* already merged entry */
3839                                 continue;
3840
3841                         if (jent->i2c_index == ient->i2c_index && jent->type == ient->type && jent->location == ient->location) {
3842                                 /* only merge heads field when output field is the same --
3843                                  * we could merge output field for same heads, but dual link,
3844                                  * the resultant need to make several merging passes, and lack
3845                                  * of applicable real life cases has deterred this so far
3846                                  */
3847                                 if (jent->or == ient->or) {
3848                                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3849                                                    "Merging DCB entries %d and %d\n", i, j);
3850                                         ient->heads |= jent->heads;
3851                                         jent->type = 100; /* dummy value */
3852                                 }
3853                         }
3854                 }
3855         }
3856
3857         /* Compact entries merged into others out of dcb_table */
3858         int newentries = 0;
3859         for (i = 0; i < pNv->dcb_table.entries; i++) {
3860                 if ( pNv->dcb_table.entry[i].type == 100 )
3861                         continue;
3862
3863                 if (newentries != i)
3864                         memcpy(&pNv->dcb_table.entry[newentries], &pNv->dcb_table.entry[i], sizeof(struct dcb_entry));
3865                 newentries++;
3866         }
3867
3868         pNv->dcb_table.entries = newentries;
3869
3870         return pNv->dcb_table.entries;
3871 }
3872
3873 static void load_nv17_hw_sequencer_ucode(ScrnInfoPtr pScrn, bios_t *bios, uint16_t hwsq_offset, int entry)
3874 {
3875         /* BMP based cards, from NV17, need a microcode loading to correctly
3876          * control the GPIO etc for LVDS panels
3877          *
3878          * BIT based cards seem to do this directly in the init scripts
3879          *
3880          * The microcode entries are found by the "HWSQ" signature.
3881          * The header following has the number of entries, and the entry size
3882          *
3883          * An entry consists of a dword to write to the sequencer control reg
3884          * (0x00001304), followed by the ucode bytes, written sequentially,
3885          * starting at reg 0x00001400
3886          */
3887
3888         uint8_t bytes_to_write;
3889         int i;
3890
3891         if (bios->data[hwsq_offset] <= entry) {
3892                 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3893                            "Too few entries in HW sequencer table for requested entry\n");
3894                 return;
3895         }
3896
3897         bytes_to_write = bios->data[hwsq_offset + 1];
3898
3899         if (bytes_to_write != 36) {
3900                 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown HW sequencer entry size\n");
3901                 return;
3902         }
3903
3904         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Loading NV17 power sequencing microcode\n");
3905
3906         uint16_t hwsq_entry_offset = hwsq_offset + 2 + entry * bytes_to_write;
3907
3908         /* set sequencer control */
3909         nv32_wr(pScrn, 0x00001304, le32_to_cpu(*(uint32_t *)&bios->data[hwsq_entry_offset]));
3910         bytes_to_write -= 4;
3911
3912         /* write ucode */
3913         for (i = 0; i < bytes_to_write; i += 4)
3914                 nv32_wr(pScrn, 0x00001400 + i, le32_to_cpu(*(uint32_t *)&bios->data[hwsq_entry_offset + i + 4]));
3915
3916         /* twiddle 0x1098 */
3917         nv32_wr(pScrn, 0x00001098, nv32_rd(pScrn, 0x00001098) | 0x18);
3918 }
3919
3920 static void read_bios_edid(ScrnInfoPtr pScrn)
3921 {
3922         bios_t *bios = &NVPTR(pScrn)->VBIOS;
3923         const uint8_t edid_sig[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
3924         uint16_t offset = 0, newoffset;
3925         int searchlen = NV_PROM_SIZE, i;
3926
3927         while (searchlen) {
3928                 if (!(newoffset = findstr(&bios->data[offset], searchlen, edid_sig, 8)))
3929                         return;
3930                 offset += newoffset;
3931                 if (!nv_cksum(&bios->data[offset], EDID1_LEN))
3932                         break;
3933
3934                 searchlen -= offset;
3935                 offset++;
3936         }
3937
3938         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found EDID in BIOS\n");
3939
3940         bios->fp.edid = xalloc(EDID1_LEN);
3941         for (i = 0; i < EDID1_LEN; i++)
3942                 bios->fp.edid[i] = bios->data[offset + i];
3943 }
3944
3945 Bool NVInitVBIOS(ScrnInfoPtr pScrn)
3946 {
3947         NVPtr pNv = NVPTR(pScrn);
3948
3949         memset(&pNv->VBIOS, 0, sizeof(bios_t));
3950         pNv->VBIOS.data = xalloc(NV_PROM_SIZE);
3951
3952         if (!NVShadowVBIOS(pScrn, pNv->VBIOS.data)) {
3953                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3954                            "No valid BIOS image found\n");
3955                 xfree(pNv->VBIOS.data);
3956                 return FALSE;
3957         }
3958
3959         pNv->VBIOS.length = pNv->VBIOS.data[2] * 512;
3960         if (pNv->VBIOS.length > NV_PROM_SIZE)
3961                 pNv->VBIOS.length = NV_PROM_SIZE;
3962
3963         return TRUE;
3964 }
3965
3966 Bool NVRunVBIOSInit(ScrnInfoPtr pScrn)
3967 {
3968         NVPtr pNv = NVPTR(pScrn);
3969         const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 };
3970         const uint8_t bit_signature[] = { 'B', 'I', 'T' };
3971         int offset, ret = 0;
3972
3973         crtc_access(pScrn, ACCESS_UNLOCK);
3974
3975         if ((offset = findstr(pNv->VBIOS.data, pNv->VBIOS.length, bit_signature, sizeof(bit_signature)))) {
3976                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIT BIOS found\n");
3977                 parse_bit_structure(pScrn, &pNv->VBIOS, offset + 4);
3978         } else if ((offset = findstr(pNv->VBIOS.data, pNv->VBIOS.length, bmp_signature, sizeof(bmp_signature)))) {
3979                 const uint8_t hwsq_signature[] = { 'H', 'W', 'S', 'Q' };
3980                 int hwsq_offset;
3981
3982                 if ((hwsq_offset = findstr(pNv->VBIOS.data, pNv->VBIOS.length, hwsq_signature, sizeof(hwsq_signature))))
3983                         /* always use entry 0? */
3984                         load_nv17_hw_sequencer_ucode(pScrn, &pNv->VBIOS, hwsq_offset + sizeof(hwsq_signature), 0);
3985
3986                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BMP BIOS found\n");
3987                 parse_bmp_structure(pScrn, &pNv->VBIOS, offset);
3988         } else {
3989                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3990                            "No known BIOS signature found\n");
3991                 ret = 1;
3992         }
3993
3994         crtc_access(pScrn, ACCESS_LOCK);
3995
3996         if (ret)
3997                 return FALSE;
3998
3999         return TRUE;
4000 }
4001
4002 unsigned int NVParseBios(ScrnInfoPtr pScrn)
4003 {
4004         NVPtr pNv = NVPTR(pScrn);
4005         uint32_t saved_nv_pextdev_boot_0;
4006
4007         if (!NVInitVBIOS(pScrn))
4008                 return 0;
4009
4010         /* these will need remembering across a suspend */
4011         saved_nv_pextdev_boot_0 = nv32_rd(pScrn, NV_PEXTDEV_BOOT_0);
4012         saved_nv_pfb_cfg0 = nv32_rd(pScrn, NV_PFB_CFG0);
4013
4014         pNv->VBIOS.execute = FALSE;
4015
4016         nv32_wr(pScrn, NV_PEXTDEV_BOOT_0, saved_nv_pextdev_boot_0);
4017
4018         if (!NVRunVBIOSInit(pScrn))
4019                 return 0;
4020
4021         if (parse_dcb_table(pScrn, &pNv->VBIOS))
4022                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4023                            "Found %d entries in DCB\n", pNv->dcb_table.entries);
4024
4025         if (pNv->Mobile && !pNv->VBIOS.fp.native_mode)
4026                 read_bios_edid(pScrn);
4027
4028         return 1;
4029 }