Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
133 giacomo 1
/*
2
    NeoMagic chipset driver
3
        Written by Shigehiro Nomura <s.nomura@mba.nifty.ne.jp>
4
 
5
Does not support external screen.
6
 
7
Remarks:
8
Problem: The modes whose width is longer than the width of LCD panel
9
         are also reported by vgatest, but not displaying properly.
10
 --> Please do not select such modes :-)
11
 
12
Note:
13
  When use Toshiba Libretto100,110, please define "LIBRETTO100" at
14
  line 19 in src/neo.c
15
  And add the following lines to libvga.config
16
  -------------------------------------------------------------------
17
   HorizSync 31.5 70
18
   VertRefresh 50 100
19
   Modeline "800x480"   50  800  856  976 1024   480  483  490  504 +hsync
20
+vsync
21
   newmode  800 480 256       800 1
22
   newmode  800 480 32768    1600 2
23
   newmode  800 480 65536    1600 2
24
   newmode  800 480 16777216 2400 3
25
  -------------------------------------------------------------------
26
 
27
*/
28
#include <stdlib.h>
29
#include <stdio.h>              
30
#include <string.h>
31
#include <unistd.h>
32
#include "vga.h"
33
#include "libvga.h"
34
#include "driver.h"
35
#include "timing.h"
36
#include "vgaregs.h"
37
#include "interface.h"
38
#include "vgapci.h"
39
 
40
#undef NEO_PCI_BURST
41
#undef LIBRETTO100  /* Define if Toshiba Libretto100/110 */
42
 
43
#define VENDOR_ID 0x10c8   /* NeoMagic */
44
#define PCI_CHIP_NM2070         0x0001
45
#define PCI_CHIP_NM2090         0x0002
46
#define PCI_CHIP_NM2093         0x0003
47
#define PCI_CHIP_NM2097         0x0083
48
#define PCI_CHIP_NM2160         0x0004
49
#define PCI_CHIP_NM2200         0x0005
50
 
51
#define GRAX      0x3ce
52
 
53
#define NEO_EXT_CR_MAX 0x85
54
#define NEO_EXT_GR_MAX 0xC7
55
 
56
#define NEOREG_SAVE(i) (VGA_TOTAL_REGS+i)
57
#define  GeneralLockReg       NEOREG_SAVE(0)   /* GRAX(0x0a) */
58
#define  ExtCRTDispAddr       NEOREG_SAVE(1)   /* GRAX(0x0e) */
59
#define  ExtCRTOffset         NEOREG_SAVE(2)   /* GRAX(0x0f) */
60
#define  SysIfaceCntl1        NEOREG_SAVE(3)   /* GRAX(0x10) */
61
#define  SysIfaceCntl2        NEOREG_SAVE(4)   /* GRAX(0x11) */
62
#define  SingleAddrPage       NEOREG_SAVE(5)   /* GRAX(0x15) */
63
#define  DualAddrPage         NEOREG_SAVE(6)   /* GRAX(0x16) */
64
#define  PanelDispCntlReg1    NEOREG_SAVE(7)   /* GRAX(0x20) */
65
#define  PanelDispCntlReg2    NEOREG_SAVE(8)   /* GRAX(0x25) */
66
#define  PanelDispCntlReg3    NEOREG_SAVE(9)   /* GRAX(0x30) */
67
#define  PanelVertCenterReg1  NEOREG_SAVE(10)  /* GRAX(0x28) */
68
#define  PanelVertCenterReg2  NEOREG_SAVE(11)  /* GRAX(0x29) */
69
#define  PanelVertCenterReg3  NEOREG_SAVE(12)  /* GRAX(0x2a) */
70
#define  PanelVertCenterReg4  NEOREG_SAVE(13)  /* GRAX(0x32) */
71
#define  PanelVertCenterReg5  NEOREG_SAVE(14)  /* GRAX(0x37) */
72
#define  PanelHorizCenterReg1 NEOREG_SAVE(15)  /* GRAX(0x33) */
73
#define  PanelHorizCenterReg2 NEOREG_SAVE(16)  /* GRAX(0x34) */
74
#define  PanelHorizCenterReg3 NEOREG_SAVE(17)  /* GRAX(0x35) */
75
#define  PanelHorizCenterReg4 NEOREG_SAVE(18)  /* GRAX(0x36) */
76
#define  PanelHorizCenterReg5 NEOREG_SAVE(19)  /* GRAX(0x38) */
77
#define  ExtColorModeSelect   NEOREG_SAVE(20)  /* GRAX(0x90) */
78
#define  VCLK3NumeratorLow    NEOREG_SAVE(21)  /* GRAX(0x9b) */
79
#define  VCLK3NumeratorHigh   NEOREG_SAVE(22)  /* GRAX(0x8f) */
80
#define  VCLK3Denominator     NEOREG_SAVE(23)  /* GRAX(0x9f) */
81
#define  VerticalExt          NEOREG_SAVE(24)
82
#define  EXT_SAVED            NEOREG_SAVE(25)  /* EXT regs. saved ? */
83
#define   EXTCR               NEOREG_SAVE(26)              /* CR(0x00..) */
84
#define   EXTGR               (EXTCR + NEO_EXT_CR_MAX + 1) /* GR(0x00..) */
85
#define  DAC                  (EXTGR + NEO_EXT_GR_MAX + 1) /* DAC */
86
#define NEO_TOTAL_REGS  (DAC + 768)
87
 
88
#define DACDelay \
89
        { \
90
                unsigned char temp = port_in(vgaIOBase + 0x0A); \
91
                temp = port_in(vgaIOBase + 0x0A); \
92
        }
93
 
94
 
95
static int neo_init(int, int, int);
96
static void neo_unlock(void);
97
static void neo_lock(void);
98
 
99
static int neo_memory;
100
static int NeoChipset;
101
static int NeoPanelWidth, NeoPanelHeight;
102
static int neo_is_linear, neo_linear_base;
103
static int vgaIOBase;
104
 
105
static CardSpecs *cardspecs;
106
 
107
static void neo_setpage(int page)
108
{
109
#ifdef DEBUG
110
  printk(KERN_DEBUG "neo_setpage: %d\n", page);
111
#endif
112
  outb(GRAX, 0x11);
113
  outw(GRAX, ((port_in(GRAX+1) & 0xfc) << 8) | 0x11);
114
  outw(GRAX, (page << 10) | 0x15); /* set read/write bank */
115
}
116
 
117
static void neo_setrdpage(int page)
118
{
119
#ifdef DEBUG
120
  printk(KERN_DEBUG "neo_setrdpage: %d\n", page);
121
#endif
122
  outb(GRAX, 0x11);
123
  outw(GRAX, (((port_in(GRAX+1) & 0xfc) | 0x01) << 8) | 0x11);
124
  outw(GRAX, (page << 10) | 0x15); /* set read bank */
125
}
126
 
127
static void neo_setwrpage(int page)
128
{
129
#ifdef DEBUG
130
  printk(KERN_DEBUG "neo_setwrpage: %d\n", page);
131
#endif
132
  outb(GRAX, 0x11);
133
  outw(GRAX, (((port_in(GRAX+1) & 0xfc) | 0x01) << 8) | 0x11);
134
  outw(GRAX, (page << 10) | 0x16); /* set write bank */
135
}
136
 
137
static int __svgalib_neo_inlinearmode(void)
138
{
139
#ifdef DEBUG
140
  printk(KERN_DEBUG "neo_inlinearmode\n");
141
#endif
142
return neo_is_linear;
143
}
144
 
145
/* Fill in chipset specific mode information */
146
 
147
static void neo_getmodeinfo(int mode, vga_modeinfo *modeinfo)
148
{
149
#ifdef DEBUG
150
    printk(KERN_DEBUG "neo_getmodeinfo: %d\n", mode);
151
#endif
152
 
153
    if(modeinfo->colors==16)return;
154
 
155
    modeinfo->maxpixels = neo_memory*1024/modeinfo->bytesperpixel;
156
    if (NeoChipset == PCI_CHIP_NM2200)
157
      modeinfo->maxlogicalwidth = 1280;
158
    else
159
      modeinfo->maxlogicalwidth = 1024;
160
    modeinfo->startaddressrange = neo_memory * 1024 - 1;
161
    modeinfo->haveblit = 0;
162
    modeinfo->flags |= HAVE_RWPAGE;
163
 
164
#if 1
165
    if (modeinfo->bytesperpixel >= 1) {
166
        if(neo_linear_base)modeinfo->flags |= CAPABLE_LINEAR;
167
        if (__svgalib_neo_inlinearmode())
168
            modeinfo->flags |= IS_LINEAR | LINEAR_MODE;
169
    }
170
#endif
171
}
172
 
173
/* Read and save chipset-specific registers */
174
 
175
static int neo_saveregs(unsigned char regs[])
176
{
177
  int i;
178
 
179
#ifdef DEBUG
180
  printk(KERN_DEBUG "neo_saveregs\n");
181
#endif
182
  neo_unlock();
183
  outw(GRAX, 0x0015);   /* bank#0 */
184
 
185
  outb(GRAX, 0x0a); regs[GeneralLockReg] = port_in(GRAX + 1);
186
  outb(GRAX, 0x0e); regs[ExtCRTDispAddr] = port_in(GRAX + 1);
187
  outb(GRAX, 0x0f); regs[ExtCRTOffset] = port_in(GRAX + 1);
188
  outb(GRAX, 0x10); regs[SysIfaceCntl1] = port_in(GRAX + 1);
189
  outb(GRAX, 0x11); regs[SysIfaceCntl2] = port_in(GRAX + 1);
190
  outb(GRAX, 0x15); regs[SingleAddrPage] = port_in(GRAX + 1);
191
  outb(GRAX, 0x16); regs[DualAddrPage] = port_in(GRAX+1);
192
  outb(GRAX, 0x20); regs[PanelDispCntlReg1] = port_in(GRAX+1);
193
  outb(GRAX, 0x25); regs[PanelDispCntlReg2] = port_in(GRAX+1);
194
  outb(GRAX, 0x30); regs[PanelDispCntlReg3] = port_in(GRAX+1);
195
  outb(GRAX, 0x28); regs[PanelVertCenterReg1] = port_in(GRAX+1);
196
  outb(GRAX, 0x29); regs[PanelVertCenterReg2] = port_in(GRAX+1);
197
  outb(GRAX, 0x2a); regs[PanelVertCenterReg3] = port_in(GRAX+1);
198
  if (NeoChipset != PCI_CHIP_NM2070){
199
    outb(GRAX, 0x32); regs[PanelVertCenterReg4] = port_in(GRAX+1);
200
    outb(GRAX, 0x33); regs[PanelHorizCenterReg1] = port_in(GRAX+1);
201
    outb(GRAX, 0x34); regs[PanelHorizCenterReg2] = port_in(GRAX+1);
202
    outb(GRAX, 0x35); regs[PanelHorizCenterReg3] = port_in(GRAX+1);
203
  }
204
  if (NeoChipset == PCI_CHIP_NM2160){
205
    outb(GRAX, 0x36); regs[PanelHorizCenterReg4] = port_in(GRAX+1);
206
  }
207
  if (NeoChipset == PCI_CHIP_NM2200){
208
    outb(GRAX, 0x36); regs[PanelHorizCenterReg4] = port_in(GRAX+1);
209
    outb(GRAX, 0x37); regs[PanelVertCenterReg5]  = port_in(GRAX+1);
210
    outb(GRAX, 0x38); regs[PanelHorizCenterReg5] = port_in(GRAX+1);
211
  }
212
  outb(GRAX, 0x90); regs[ExtColorModeSelect] = port_in(GRAX+1);
213
  outb(GRAX, 0x9B); regs[VCLK3NumeratorLow]  = port_in(GRAX+1);
214
  if (NeoChipset == PCI_CHIP_NM2200){
215
    outb(GRAX, 0x8F); regs[VCLK3NumeratorHigh] = port_in(GRAX+1);
216
  }
217
  outb(GRAX, 0x9F); regs[VCLK3Denominator] = port_in(GRAX+1);
218
 
219
  regs[EXT_SAVED] = TRUE;
220
  outb(vgaIOBase + 4, 0x25); regs[EXTCR + 0x25] = port_in(vgaIOBase + 5);
221
  outb(vgaIOBase + 4, 0x2F); regs[EXTCR + 0x2F] = port_in(vgaIOBase + 5);
222
  for (i = 0x40; i <= 0x59; i++){
223
    outb(vgaIOBase + 4, i); regs[EXTCR + i] = port_in(vgaIOBase + 5);
224
  }
225
  for (i = 0x60; i <= 0x69; i++){
226
    outb(vgaIOBase + 4, i); regs[EXTCR + i] = port_in(vgaIOBase + 5);
227
  }
228
  for (i = 0x70; i <= NEO_EXT_CR_MAX; i++){
229
    outb(vgaIOBase + 4, i); regs[EXTCR + i] = port_in(vgaIOBase + 5);
230
  }
231
 
232
  for (i = 0x0A; i <= NEO_EXT_GR_MAX; i++){
233
    outb(GRAX, i); regs[EXTGR + i] = port_in(GRAX+1);
234
  }
235
 
236
  /* DAC */
237
  outb(0x3C6,0xFF); /* mask */
238
  outb(0x3C7,0x00); /* read address */
239
  for (i = 0; i < 768; i++){
240
    regs[DAC + i] = port_in(0x3C9);
241
    DACDelay;
242
  }
243
 
244
  return NEO_TOTAL_REGS - VGA_TOTAL_REGS;
245
}
246
 
247
/* Set chipset-specific registers */
248
 
249
static void neo_setregs(const unsigned char regs[], int mode)
250
{
251
  int i;
252
  unsigned char temp;
253
 
254
#ifdef DEBUG
255
  printk(KERN_DEBUG "neo_setregs\n");
256
#endif
257
  neo_unlock();        
258
  outw(GRAX, 0x0015);   /* bank#0 */
259
 
260
  outb(GRAX, 0x0a); outb(GRAX+1, regs[GeneralLockReg]);
261
 
262
  /* set color mode first */
263
  outb(GRAX, 0x90); temp = port_in(GRAX+1);
264
  switch (NeoChipset){
265
  case PCI_CHIP_NM2070:
266
    temp &= 0xF0; /* Save bits 7:4 */
267
    temp |= (regs[ExtColorModeSelect] & ~0xF0);
268
    break;
269
  case PCI_CHIP_NM2090: case PCI_CHIP_NM2093: case PCI_CHIP_NM2097:
270
  case PCI_CHIP_NM2160: case PCI_CHIP_NM2200:
271
    temp &= 0x70; /* Save bits 6:4 */
272
    temp |= (regs[ExtColorModeSelect] & ~0x70);
273
    break;
274
  }
275
  outb(GRAX, 0x90); outb(GRAX+1, temp);
276
 
277
  /* Disable horizontal and vertical graphics and text expansions */
278
  outb(GRAX, 0x25);
279
  temp = port_in(GRAX+1);
280
  outb(GRAX, 0x25);
281
  temp &= 0x39;
282
  outb(GRAX+1, temp);
283
 
284
  sleep(1);
285
 
286
  /* DAC */
287
  outb(0x3C6,0xFF); /* mask */
288
  outb(0x3C8,0x00); /* write address */
289
  for (i = 0; i < 768; i++){
290
    outb(0x3C9, regs[DAC + i]);
291
    DACDelay;
292
  }
293
 
294
  outb(GRAX, 0x0E); outb(GRAX+1, regs[ExtCRTDispAddr]);
295
  outb(GRAX, 0x0F); outb(GRAX+1, regs[ExtCRTOffset]);
296
  outb(GRAX, 0x10); temp = port_in(GRAX+1);
297
  temp &= 0x0F; /* Save bits 3:0 */
298
  temp |= (regs[SysIfaceCntl1] & ~0x0F);
299
  outb(GRAX, 0x10); outb(GRAX+1, temp);
300
 
301
  outb(GRAX, 0x11); outb(GRAX+1, regs[SysIfaceCntl2]);
302
  outb(GRAX, 0x15); outb(GRAX+1, regs[SingleAddrPage]);
303
  outb(GRAX, 0x16); outb(GRAX+1, regs[DualAddrPage]);
304
  outb(GRAX, 0x20); temp = port_in(GRAX+1);
305
  switch (NeoChipset){
306
  case PCI_CHIP_NM2070:
307
    temp &= 0xFC; /* Save bits 7:2 */
308
    temp |= (regs[PanelDispCntlReg1] & ~0xFC);
309
    break;
310
  case PCI_CHIP_NM2090:  case PCI_CHIP_NM2093: case PCI_CHIP_NM2097:
311
  case PCI_CHIP_NM2160:
312
    temp &= 0xDC; /* Save bits 7:6,4:2 */
313
    temp |= (regs[PanelDispCntlReg1] & ~0xDC);
314
    break;
315
  case PCI_CHIP_NM2200:
316
    temp &= 0x98; /* Save bits 7,4:3 */
317
    temp |= (regs[PanelDispCntlReg1] & ~0x98);
318
    break;
319
  }
320
  outb(GRAX, 0x20); outb(GRAX+1, temp);
321
  outb(GRAX, 0x25); temp = port_in(GRAX+1);
322
  temp &= 0x38; /* Save bits 5:3 */
323
  temp |= (regs[PanelDispCntlReg2] & ~0x38);
324
  outb(GRAX, 0x25); outb(GRAX+1, temp);
325
 
326
  if (NeoChipset != PCI_CHIP_NM2070){
327
    outb(GRAX, 0x30); temp = port_in(GRAX+1);
328
    temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */
329
    temp |= (regs[PanelDispCntlReg3] & ~0xEF);
330
    outb(GRAX, 0x30); outb(GRAX+1, temp);
331
  }
332
 
333
  outb(GRAX, 0x28); outb(GRAX+1, regs[PanelVertCenterReg1]);
334
  outb(GRAX, 0x29); outb(GRAX+1, regs[PanelVertCenterReg2]);
335
  outb(GRAX, 0x2a); outb(GRAX+1, regs[PanelVertCenterReg3]);
336
 
337
  if (NeoChipset != PCI_CHIP_NM2070){
338
    outb(GRAX, 0x32); outb(GRAX+1, regs[PanelVertCenterReg4]);
339
    outb(GRAX, 0x33); outb(GRAX+1, regs[PanelHorizCenterReg1]);
340
    outb(GRAX, 0x34); outb(GRAX+1, regs[PanelHorizCenterReg2]);
341
    outb(GRAX, 0x35); outb(GRAX+1, regs[PanelHorizCenterReg3]);
342
  }
343
 
344
  if (NeoChipset == PCI_CHIP_NM2160){
345
    outb(GRAX, 0x36); outb(GRAX+1, regs[PanelHorizCenterReg4]);
346
  }
347
 
348
  if (NeoChipset == PCI_CHIP_NM2200){
349
    outb(GRAX, 0x36); outb(GRAX+1, regs[PanelHorizCenterReg4]);
350
    outb(GRAX, 0x37); outb(GRAX+1, regs[PanelVertCenterReg5]);
351
    outb(GRAX, 0x38); outb(GRAX+1, regs[PanelHorizCenterReg5]);
352
  }
353
 
354
#if 0
355
  outb(GRAX, 0x9B); outb(GRAX+1, regs[VCLK3NumeratorLow]);
356
  if (NeoChipset == PCI_CHIP_NM2200){
357
    outb(GRAX, 0x8F); temp = port_in(GRAX+1);
358
    temp &= 0x0F; /* Save bits 3:0 */
359
    temp |= (regs[VCLK3NumeratorHigh] & ~0x0F);
360
    outb(GRAX, 0x8F); outb(GRAX+1, temp);
361
  }
362
  outb(GRAX, 0x9F); outb(GRAX+1, regs[VCLK3Denominator]);
363
#endif
364
 
365
  if (regs[EXT_SAVED]){
366
    outb(vgaIOBase + 4, 0x25); outb(vgaIOBase + 5, regs[EXTCR + 0x25]);
367
    outb(vgaIOBase + 4, 0x2F); outb(vgaIOBase + 5, regs[EXTCR + 0x2F]);
368
    for (i = 0x40; i <= 0x59; i++){
369
      outb(vgaIOBase + 4, i); outb(vgaIOBase + 5, regs[EXTCR + i]);
370
    }
371
    for (i = 0x60; i <= 0x69; i++){
372
      outb(vgaIOBase + 4, i); outb(vgaIOBase + 5, regs[EXTCR + i]);
373
    }
374
    for (i = 0x70; i <= NEO_EXT_CR_MAX; i++){
375
      outb(vgaIOBase + 4, i); outb(vgaIOBase + 5, regs[EXTCR + i]);
376
    }
377
 
378
    for (i = 0x0a; i <= 0x3f; i++){
379
      outb(GRAX, i); outb(GRAX+1, regs[EXTGR + i]);
380
    }
381
    for (i = 0x90; i <= NEO_EXT_GR_MAX; i++){
382
      outb(GRAX, i); outb(GRAX+1, regs[EXTGR + i]);
383
    }
384
  }
385
 
386
  /* Program vertical extension register */
387
  if (NeoChipset == PCI_CHIP_NM2200){
388
    outb(vgaIOBase + 4, 0x70); outb(vgaIOBase + 5, regs[VerticalExt]);
389
  }
390
}
391
 
392
#if 0
393
/*
394
 * NeoCalcVCLK --
395
 *
396
 * Determine the closest clock frequency to the one requested.
397
 */
398
#define REF_FREQ 14.31818
399
#define MAX_N 127
400
#define MAX_D 31
401
#define MAX_F 1
402
 
403
static void NeoCalcVCLK(long freq, unsigned char *moderegs)
404
{
405
    int n, d, f;
406
    double f_out;
407
    double f_diff;
408
    int n_best = 0, d_best = 0, f_best = 0;
409
    double f_best_diff = 999999.0;
410
    double f_target = freq/1000.0;
411
 
412
    for (f = 0; f <= MAX_F; f++)
413
        for (n = 0; n <= MAX_N; n++)
414
            for (d = 0; d <= MAX_D; d++) {
415
                f_out = (n+1.0)/((d+1.0)*(1<<f))*REF_FREQ;
416
                f_diff = abs(f_out-f_target);
417
                if (f_diff < f_best_diff) {
418
                    f_best_diff = f_diff;
419
                    n_best = n;
420
                    d_best = d;
421
                    f_best = f;
422
                }
423
            }
424
 
425
    if (NeoChipset == PCI_CHIP_NM2200){
426
      /* NOT_DONE:  We are trying the full range of the 2200 clock.
427
         We should be able to try n up to 2047 */
428
      moderegs[VCLK3NumeratorLow]  = n_best;
429
      moderegs[VCLK3NumeratorHigh] = (f_best << 7);
430
    } else {
431
      moderegs[VCLK3NumeratorLow]  = n_best | (f_best << 7);
432
    }
433
    moderegs[VCLK3Denominator] = d_best;
434
}
435
#endif
436
 
437
 
438
/* Return nonzero if mode is available */
439
 
440
static int neo_modeavailable(int mode)
441
{
442
    struct info *info;
443
    ModeTiming *modetiming;
444
    ModeInfo *modeinfo;
445
 
446
#ifdef DEBUG
447
    printk(KERN_DEBUG "neo_modeavaailable: %d\n", mode);
448
#endif
449
 
450
    if (IS_IN_STANDARD_VGA_DRIVER(mode))
451
        return __svgalib_vga_driverspecs.modeavailable(mode);
452
 
453
    info = &__svgalib_infotable[mode];
454
    if (neo_memory * 1024 < info->ydim * info->xbytes)
455
        return 0;
456
 
457
    modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
458
    modetiming = malloc(sizeof(ModeTiming));
459
    if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
460
        free(modetiming);
461
        free(modeinfo);
462
        return 0;
463
    }
464
    free(modetiming);
465
    free(modeinfo);
466
 
467
    return SVGADRV;
468
}
469
 
470
/* Local, called by neo_setmode(). */
471
 
472
static void neo_initializemode(unsigned char *moderegs,
473
                            ModeTiming * modetiming, ModeInfo * modeinfo, int mode)
474
{
475
  int i, hoffset, voffset;
476
 
477
#ifdef DEBUG
478
  printk(KERN_DEBUG "neo_initializemode: %d\n", mode);
479
#endif
480
  neo_saveregs(moderegs);
481
  __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo);
482
 
483
  moderegs[EXT_SAVED] = FALSE;
484
  moderegs[VGA_AR10] = 0x01;  /* Attribute 0x10 */
485
 
486
  moderegs[0x13] = modeinfo->lineWidth >> 3;
487
  moderegs[ExtCRTOffset] = modeinfo->lineWidth >> 11;
488
  switch (modeinfo->bitsPerPixel){
489
  case  8:
490
    moderegs[ExtColorModeSelect] = 0x11;
491
    break;
492
  case 15:
493
  case 16:
494
    if (modeinfo->greenWeight == 5){ /* 15bpp */
495
      for (i = 0; i < 64; i++){
496
        moderegs[DAC + i*3+0] = i << 1;
497
        moderegs[DAC + i*3+1] = i << 1;
498
        moderegs[DAC + i*3+2] = i << 1;
499
      }
500
      moderegs[ExtColorModeSelect] = 0x12;
501
    } else { /* 16bpp */
502
      for (i = 0; i < 64; i++){
503
        moderegs[DAC + i*3+0] = i << 1;
504
        moderegs[DAC + i*3+1] = i;
505
        moderegs[DAC + i*3+2] = i << 1;
506
      }
507
      moderegs[ExtColorModeSelect] = 0x13;
508
    }
509
    break;
510
  case 24:
511
    for (i = 0; i < 256; i++){
512
      moderegs[DAC + i*3+0] = i;
513
      moderegs[DAC + i*3+1] = i;
514
      moderegs[DAC + i*3+2] = i;
515
    }
516
    moderegs[ExtColorModeSelect] = 0x14;
517
    break;
518
  }
519
  moderegs[ExtCRTDispAddr] = 0x10;
520
 
521
#if 0
522
  /* Vertical Extension */
523
  moderegs[VerticalExt] = (((modetiming->CrtcVTotal -2) & 0x400) >> 10 )
524
    | (((modetiming->CrtcVDisplay -1) & 0x400) >> 9 )
525
    | (((modetiming->CrtcVSyncStart) & 0x400) >> 8 )
526
    | (((modetiming->CrtcVSyncStart) & 0x400) >> 7 );
527
#endif
528
 
529
  /* Disable read/write bursts if requested. */
530
#ifdef NEO_PCI_BURST
531
  moderegs[SysIfaceCntl1] = 0x30;
532
#else /* NEO_PCI_BURST */
533
  moderegs[SysIfaceCntl1] = 0x00;
534
#endif /* NEO_PCI_BURST */
535
 
536
  /* If they are used, enable linear addressing and/or enable MMIO. */
537
  moderegs[SysIfaceCntl2] = 0x00;
538
  moderegs[SysIfaceCntl2] |= 0x80; /* Linear */
539
#if 0
540
  moderegs[SysIfaceCntl2] |= 0x40; /* MMIO */
541
#endif
542
 
543
  moderegs[PanelDispCntlReg1] = 0x00;
544
  moderegs[PanelDispCntlReg1] |= 0x02; /* Enable internal display */
545
#if 0
546
  moderegs[PanelDispCntlReg1] |= 0x01; /* Enable external display */
547
#endif
548
 
549
  /* If we are using a fixed mode, then tell the chip we are. */
550
  switch (modetiming->HDisplay) {
551
  case 1280:
552
    moderegs[PanelDispCntlReg1] |= 0x60;
553
    break;
554
  case 1024:
555
    moderegs[PanelDispCntlReg1] |= 0x40;
556
    break;
557
  case 800:
558
    moderegs[PanelDispCntlReg1] |= 0x20;
559
    break;
560
  case 640:
561
    break;
562
  }
563
 
564
  /* Setup shadow register locking. */
565
  moderegs[GeneralLockReg] = 0x01;
566
 
567
  moderegs[PanelDispCntlReg2] = 0x00;
568
  moderegs[PanelDispCntlReg3] = 0x00;
569
 
570
  /*
571
   * If the screen is to be centerd, turn on the centering for the
572
   * various modes.
573
   */
574
  moderegs[PanelVertCenterReg1] = 0x00;
575
  moderegs[PanelVertCenterReg2] = 0x00;
576
  moderegs[PanelVertCenterReg3] = 0x00;
577
  moderegs[PanelVertCenterReg4] = 0x00;
578
  moderegs[PanelVertCenterReg5] = 0x00;
579
  moderegs[PanelHorizCenterReg1] = 0x00;
580
  moderegs[PanelHorizCenterReg2] = 0x00;
581
  moderegs[PanelHorizCenterReg3] = 0x00;
582
  moderegs[PanelHorizCenterReg4] = 0x00;
583
  moderegs[PanelHorizCenterReg5] = 0x00;
584
 
585
  if (moderegs[PanelDispCntlReg1] & 0x02){
586
    if (modetiming->HDisplay < NeoPanelWidth){
587
      moderegs[PanelDispCntlReg3] |= 0x10;
588
      hoffset = ((NeoPanelWidth - modetiming->HDisplay) >> 4) - 1;
589
      moderegs[PanelHorizCenterReg1] = hoffset;
590
      switch (modetiming->HDisplay){
591
      case  320:
592
        moderegs[PanelHorizCenterReg3] = hoffset;
593
        break;
594
      case  400:
595
        moderegs[PanelHorizCenterReg4] = hoffset;
596
        break;
597
      case  640:
598
        moderegs[PanelHorizCenterReg1] = hoffset;
599
        break;
600
      case  800:
601
        moderegs[PanelHorizCenterReg2] = hoffset;
602
        break;
603
      case 1024:
604
        moderegs[PanelHorizCenterReg5] = hoffset;
605
        break;
606
      case 1280:
607
        /* No centering in these modes. */
608
        break;
609
      }
610
    }
611
    if (modetiming->VDisplay < NeoPanelHeight){
612
      moderegs[PanelDispCntlReg2] |= 0x01;
613
      voffset = ((NeoPanelHeight - modetiming->VDisplay) >> 1) - 2;
614
      moderegs[PanelVertCenterReg2]  = voffset;
615
      switch (modetiming->VDisplay){
616
      case 240:
617
        moderegs[PanelVertCenterReg2]  = voffset;
618
        break;
619
      case 300: case 384:
620
        moderegs[PanelVertCenterReg1]  = voffset;
621
        break;
622
      case 480:
623
        moderegs[PanelVertCenterReg3]  = voffset;
624
        break;
625
      case 600:
626
        moderegs[PanelVertCenterReg4]  = voffset;
627
        break;
628
      case 768:
629
        moderegs[PanelVertCenterReg5]  = voffset;
630
        break;
631
      case 1280:
632
        /* No centering in these modes. */
633
        break;
634
      }
635
    }
636
  }
637
 
638
#if 0
639
  /*
640
   * Calculate the VCLK that most closely matches the requested dot
641
   * clock.
642
   */
643
  NeoCalcVCLK(modetiming->pixelClock, moderegs);
644
#endif
645
  /* Since we program the clocks ourselves, always use VCLK3. */
646
  moderegs[MIS] |= 0x0C;
647
 
648
  return ;
649
}
650
 
651
 
652
static int neo_setmode(int mode, int prv_mode)
653
{
654
    unsigned char *moderegs;
655
    ModeTiming *modetiming;
656
    ModeInfo *modeinfo;
657
 
658
#ifdef DEBUG
659
    printk(KERN_DEBUG "neo_setmode: %d\n", mode);
660
#endif
661
    if (IS_IN_STANDARD_VGA_DRIVER(mode)) {
662
 
663
        return __svgalib_vga_driverspecs.setmode(mode, prv_mode);
664
    }
665
    if (!neo_modeavailable(mode))
666
        return 1;
667
 
668
    modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
669
 
670
    modetiming = malloc(sizeof(ModeTiming));
671
    if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
672
        free(modetiming);
673
        free(modeinfo);
674
        return 1;
675
    }
676
 
677
    moderegs = malloc(NEO_TOTAL_REGS);
678
 
679
    neo_initializemode(moderegs, modetiming, modeinfo, mode);
680
    free(modetiming);
681
 
682
    __svgalib_setregs(moderegs);        /* Set standard regs. */
683
    neo_setregs(moderegs, mode);                /* Set extended regs. */
684
    free(moderegs);
685
 
686
    __svgalib_InitializeAcceleratorInterface(modeinfo);
687
 
688
 
689
    free(modeinfo);
690
    return 0;
691
}
692
 
693
 
694
/* Unlock chipset-specific registers */
695
 
696
static void neo_unlock(void)
697
{
698
    int temp;
699
 
700
#ifdef DEBUG
701
    printk(KERN_DEBUG "neo_unlock\n");
702
#endif
703
    outb(vgaIOBase + 4, 0x11);
704
    temp = port_in(vgaIOBase + 5);
705
    outb(vgaIOBase + 5, temp & 0x7F);
706
    outw(GRAX, 0x2609); /* Unlock NeoMagic registers */
707
}
708
 
709
static void neo_lock(void)
710
{
711
    int temp;
712
 
713
#ifdef DEBUG
714
    printk(KERN_DEBUG "neo_lock\n");
715
#endif
716
    outb(vgaIOBase + 4, 0x11);
717
    temp = port_in(vgaIOBase + 5);
718
    outb(vgaIOBase + 5, temp | 0x80);
719
    outw(GRAX, 0x0009); /* Lock NeoMagic registers */
720
}
721
 
722
 
723
/* Indentify chipset, initialize and return non-zero if detected */
724
 
725
int neo_test(void)
726
{
727
    unsigned long buf[64];
728
    int found=0;
729
 
730
    found=__svgalib_pci_find_vendor_vga(VENDOR_ID,buf,0);
731
 
732
    if (found == 0){ /* found */
733
      switch ((buf[0] >> 16) & 0xffff){
734
      case PCI_CHIP_NM2070: case PCI_CHIP_NM2090: case PCI_CHIP_NM2093:
735
      case PCI_CHIP_NM2097: case PCI_CHIP_NM2160: case PCI_CHIP_NM2200:
736
       neo_init(0,0,0);
737
       return (TRUE);
738
      }
739
    }
740
    return (FALSE);
741
}
742
 
743
 
744
/* Set display start address (not for 16 color modes) */
745
/* Cirrus supports any address in video memory (up to 2Mb) */
746
 
747
static void neo_setdisplaystart(int address)
748
{
749
  int oldExtCRTDispAddr;
750
 
751
#ifdef DEBUG
752
  printk(KERN_DEBUG "neo_setdisplaystart: 0x%x\n", address);
753
#endif
754
  address=address >> 2;
755
  outw(vgaIOBase + 4, (address & 0x00FF00) | 0x0C);
756
  outw(vgaIOBase + 4, ((address & 0x00FF) << 8) | 0x0D);
757
 
758
  outb(GRAX, 0x0E);
759
  oldExtCRTDispAddr = port_in(GRAX+1);
760
  outw(GRAX,
761
       ((((address >> 16) & 0x07) | (oldExtCRTDispAddr & 0xf8)) << 8) | 0x0E);
762
}
763
 
764
 
765
/* Set logical scanline length (usually multiple of 8) */
766
/* Cirrus supports multiples of 8, up to 4088 */
767
 
768
static void neo_setlogicalwidth(int width)
769
{  
770
    int offset = width >> 3;
771
 
772
#ifdef DEBUG
773
    printk(KERN_DEBUG "neo_setlogicalwidth: %d\n", width);
774
#endif
775
    __svgalib_outCR(0x13,offset&0xff);
776
    outb(GRAX, 0x0F);
777
    outb(GRAX+1, width >> 11);
778
}
779
 
780
static int neo_linear(int op, int param)
781
{
782
#ifdef DEBUG
783
    printk(KERN_DEBUG "neo_linear: %d\n", op);
784
#endif
785
    if (op==LINEAR_ENABLE){neo_is_linear=1; return 0;};
786
    if (op==LINEAR_DISABLE){neo_is_linear=0; return 0;};
787
    if (op==LINEAR_QUERY_BASE) return neo_linear_base;
788
    if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0;           /* No granularity or range. */
789
        else return -1;         /* Unknown function. */
790
}
791
 
792
static int neo_match_programmable_clock(int clock)
793
{
794
return clock ;
795
}
796
 
797
static int neo_map_clock(int bpp, int clock)
798
{
799
return clock ;
800
}
801
 
802
static int neo_map_horizontal_crtc(int bpp, int pixelclock, int htiming)
803
{
804
return htiming;
805
}
806
 
807
/* Function table (exported) */
808
 
809
DriverSpecs __svgalib_neo_driverspecs =
810
{
811
    neo_saveregs,
812
    neo_setregs,
813
#if 1
814
    neo_unlock,
815
    neo_lock,
816
#else
817
    0,
818
    0,
819
#endif
820
    neo_test,
821
    neo_init,
822
    neo_setpage,
823
    neo_setrdpage,
824
    neo_setwrpage,
825
    neo_setmode,
826
    neo_modeavailable,
827
    neo_setdisplaystart,
828
    neo_setlogicalwidth,
829
    neo_getmodeinfo,
830
    0,                          /* old blit funcs */
831
    0,
832
    0,
833
    0,
834
    0,
835
    0,                          /* ext_set */
836
    0,                          /* accel */
837
    neo_linear,
838
    0,                          /* accelspecs, filled in during init. */
839
    NULL,                       /* Emulation */
840
};
841
 
842
 
843
/* Initialize chipset (called after detection) */
844
 
845
static int neo_init(int force, int par1, int par2)
846
{
847
    unsigned long buf[64];
848
    int found=0;
849
    int w;
850
 
851
    vgaIOBase = (port_in(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
852
    neo_unlock();
853
    if (force) {
854
        neo_memory = par1;
855
        NeoChipset = par2;
856
    } else {
857
      neo_memory = -1;
858
      NeoChipset = -1;
859
    };
860
 
861
    found=__svgalib_pci_find_vendor_vga(VENDOR_ID,buf,0);
862
 
863
    neo_linear_base=0;
864
    if (!found){ /* found */
865
      neo_linear_base=buf[4]&0xffffff00;
866
      if (NeoChipset < 0)
867
        NeoChipset = (buf[0] >> 16) & 0xffff;
868
      if (neo_memory < 0){
869
        switch (NeoChipset){
870
        case PCI_CHIP_NM2070:
871
          neo_memory = 896;
872
          break;
873
        case PCI_CHIP_NM2090: case PCI_CHIP_NM2093: case PCI_CHIP_NM2097:
874
          neo_memory = 1152;
875
          break;
876
        case PCI_CHIP_NM2160:
877
          neo_memory = 2048;
878
          break;
879
        case PCI_CHIP_NM2200:
880
          neo_memory = 2560;
881
          break;
882
        default:
883
          neo_memory = 0;
884
        }
885
      }
886
    }
887
 
888
    if (__svgalib_driver_report) {
889
        printk(KERN_INFO "Using NeoMagic driver, %iKB.\n",neo_memory);
890
    };
891
 
892
    cardspecs = malloc(sizeof(CardSpecs));
893
    cardspecs->videoMemory = neo_memory;
894
    cardspecs->maxPixelClock4bpp = 75000;
895
    switch (NeoChipset){
896
    case PCI_CHIP_NM2070:
897
      cardspecs->maxPixelClock8bpp = 65000;
898
      cardspecs->maxPixelClock16bpp = 65000;
899
      cardspecs->maxPixelClock24bpp = 0;
900
      cardspecs->maxPixelClock32bpp = 0;
901
      break;
902
    case PCI_CHIP_NM2090: case PCI_CHIP_NM2093: case PCI_CHIP_NM2097:
903
      cardspecs->maxPixelClock8bpp = 80000;
904
      cardspecs->maxPixelClock16bpp = 80000;
905
      cardspecs->maxPixelClock24bpp = 80000;
906
      cardspecs->maxPixelClock32bpp = 0;
907
      break;
908
    case PCI_CHIP_NM2160:
909
      cardspecs->maxPixelClock8bpp = 90000;
910
      cardspecs->maxPixelClock16bpp = 90000;
911
      cardspecs->maxPixelClock24bpp = 90000;
912
      cardspecs->maxPixelClock32bpp = 0;
913
      break;
914
    case PCI_CHIP_NM2200:
915
      cardspecs->maxPixelClock8bpp = 110000;
916
      cardspecs->maxPixelClock16bpp = 110000;
917
      cardspecs->maxPixelClock24bpp = 110000;
918
      cardspecs->maxPixelClock32bpp = 0;
919
      break;
920
    }
921
 
922
    /* Determine panel width -- used in NeoValidMode. */
923
    outb(GRAX, 0x20);
924
    w = port_in(GRAX+1);
925
    switch ((w & 0x18) >> 3){
926
    case 0x00:
927
        NeoPanelWidth  = 640;
928
        NeoPanelHeight = 480;
929
        break;
930
    case 0x01:
931
        NeoPanelWidth  = 800;
932
#ifdef LIBRETTO100
933
        NeoPanelHeight = 480;
934
#else /* LIBRETTO100 */
935
        NeoPanelHeight = 600;
936
#endif /* LIBRETTO100 */
937
        break;
938
    case 0x02:
939
        NeoPanelWidth  = 1024;
940
        NeoPanelHeight = 768;
941
        break;
942
    case 0x03:
943
        NeoPanelWidth  = 1280;
944
        NeoPanelHeight = 1024;
945
        break;
946
    default :
947
        NeoPanelWidth  = 640;
948
        NeoPanelHeight = 480;
949
    }
950
 
951
        __svgalib_modeinfo_linearset |= IS_LINEAR;
952
 
953
    cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE;
954
    cardspecs->maxHorizontalCrtc = 2040;
955
    cardspecs->maxPixelClock4bpp = 0;
956
    cardspecs->nClocks =0;
957
    cardspecs->mapClock = neo_map_clock;
958
    cardspecs->mapHorizontalCrtc = neo_map_horizontal_crtc;
959
    cardspecs->matchProgrammableClock=neo_match_programmable_clock;
960
    __svgalib_driverspecs = &__svgalib_neo_driverspecs;
961
    __svgalib_banked_mem_base=0xa0000;
962
    __svgalib_banked_mem_size=0x10000;
963
    __svgalib_linear_mem_base=neo_linear_base;
964
    __svgalib_linear_mem_size=neo_memory*0x400;
965
    neo_is_linear = FALSE;
966
 
967
    sleep(4);
968
 
969
    return 0;
970
}