OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [video/] [imsttfb.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  drivers/video/imsttfb.c -- frame buffer device for IMS TwinTurbo
3
 *
4
 *  This file is derived from the powermac console "imstt" driver:
5
 *  Copyright (C) 1997 Sigurdur Asgeirsson
6
 *  With additional hacking by Jeffrey Kuskin (jsk@mojave.stanford.edu)
7
 *  Modified by Danilo Beuche 1998
8
 *  Some register values added by Damien Doligez, INRIA Rocquencourt
9
 *  Various cleanups by Paul Mundt (lethal@chaoticdreams.org)
10
 *
11
 *  This file was written by Ryan Nielsen (ran@krazynet.com)
12
 *  Most of the frame buffer device stuff was copied from atyfb.c
13
 *
14
 *  This file is subject to the terms and conditions of the GNU General Public
15
 *  License. See the file COPYING in the main directory of this archive for
16
 *  more details.
17
 */
18
 
19
#include <linux/config.h>
20
#include <linux/module.h>
21
#include <linux/kernel.h>
22
#include <linux/errno.h>
23
#include <linux/string.h>
24
#include <linux/mm.h>
25
#include <linux/tty.h>
26
#include <linux/slab.h>
27
#include <linux/vmalloc.h>
28
#include <linux/delay.h>
29
#include <linux/interrupt.h>
30
#include <linux/fb.h>
31
#include <linux/console.h>
32
#include <linux/selection.h>
33
#include <linux/init.h>
34
#include <linux/pci.h>
35
#include <asm/io.h>
36
#include <asm/uaccess.h>
37
 
38
#if defined(CONFIG_PPC)
39
#include <linux/nvram.h>
40
#include <asm/prom.h>
41
#include <asm/pci-bridge.h>
42
#include <video/macmodes.h>
43
#endif
44
 
45
#include <video/fbcon.h>
46
#include <video/fbcon-cfb8.h>
47
#include <video/fbcon-cfb16.h>
48
#include <video/fbcon-cfb24.h>
49
#include <video/fbcon-cfb32.h>
50
 
51
#ifndef __powerpc__
52
#define eieio()         /* Enforce In-order Execution of I/O */
53
#endif
54
 
55
/* TwinTurbo (Cosmo) registers */
56
enum {
57
        S1SA    =  0, /* 0x00 */
58
        S2SA    =  1, /* 0x04 */
59
        SP      =  2, /* 0x08 */
60
        DSA     =  3, /* 0x0C */
61
        CNT     =  4, /* 0x10 */
62
        DP_OCTL =  5, /* 0x14 */
63
        CLR     =  6, /* 0x18 */
64
        BI      =  8, /* 0x20 */
65
        MBC     =  9, /* 0x24 */
66
        BLTCTL  = 10, /* 0x28 */
67
 
68
        /* Scan Timing Generator Registers */
69
        HES     = 12, /* 0x30 */
70
        HEB     = 13, /* 0x34 */
71
        HSB     = 14, /* 0x38 */
72
        HT      = 15, /* 0x3C */
73
        VES     = 16, /* 0x40 */
74
        VEB     = 17, /* 0x44 */
75
        VSB     = 18, /* 0x48 */
76
        VT      = 19, /* 0x4C */
77
        HCIV    = 20, /* 0x50 */
78
        VCIV    = 21, /* 0x54 */
79
        TCDR    = 22, /* 0x58 */
80
        VIL     = 23, /* 0x5C */
81
        STGCTL  = 24, /* 0x60 */
82
 
83
        /* Screen Refresh Generator Registers */
84
        SSR     = 25, /* 0x64 */
85
        HRIR    = 26, /* 0x68 */
86
        SPR     = 27, /* 0x6C */
87
        CMR     = 28, /* 0x70 */
88
        SRGCTL  = 29, /* 0x74 */
89
 
90
        /* RAM Refresh Generator Registers */
91
        RRCIV   = 30, /* 0x78 */
92
        RRSC    = 31, /* 0x7C */
93
        RRCR    = 34, /* 0x88 */
94
 
95
        /* System Registers */
96
        GIOE    = 32, /* 0x80 */
97
        GIO     = 33, /* 0x84 */
98
        SCR     = 35, /* 0x8C */
99
        SSTATUS = 36, /* 0x90 */
100
        PRC     = 37, /* 0x94 */
101
 
102
#if 0   
103
        /* PCI Registers */
104
        DVID    = 0x00000000L,
105
        SC      = 0x00000004L,
106
        CCR     = 0x00000008L,
107
        OG      = 0x0000000CL,
108
        BARM    = 0x00000010L,
109
        BARER   = 0x00000030L,
110
#endif
111
};
112
 
113
/* IBM 624 RAMDAC Direct Registers */
114
enum {
115
        PADDRW  = 0x00,
116
        PDATA   = 0x04,
117
        PPMASK  = 0x08,
118
        PADDRR  = 0x0c,
119
        PIDXLO  = 0x10,
120
        PIDXHI  = 0x14,
121
        PIDXDATA= 0x18,
122
        PIDXCTL = 0x1c
123
};
124
 
125
/* IBM 624 RAMDAC Indirect Registers */
126
enum {
127
        CLKCTL          = 0x02, /* (0x01) Miscellaneous Clock Control */
128
        SYNCCTL         = 0x03, /* (0x00) Sync Control */
129
        HSYNCPOS        = 0x04, /* (0x00) Horizontal Sync Position */
130
        PWRMNGMT        = 0x05, /* (0x00) Power Management */
131
        DACOP           = 0x06, /* (0x02) DAC Operation */
132
        PALETCTL        = 0x07, /* (0x00) Palette Control */
133
        SYSCLKCTL       = 0x08, /* (0x01) System Clock Control */
134
        PIXFMT          = 0x0a, /* () Pixel Format  [bpp >> 3 + 2] */
135
        BPP8            = 0x0b, /* () 8 Bits/Pixel Control */
136
        BPP16           = 0x0c, /* () 16 Bits/Pixel Control  [bit 1=1 for 565] */
137
        BPP24           = 0x0d, /* () 24 Bits/Pixel Control */
138
        BPP32           = 0x0e, /* () 32 Bits/Pixel Control */
139
        PIXCTL1         = 0x10, /* (0x05) Pixel PLL Control 1 */
140
        PIXCTL2         = 0x11, /* (0x00) Pixel PLL Control 2 */
141
        SYSCLKN         = 0x15, /* () System Clock N (System PLL Reference Divider) */
142
        SYSCLKM         = 0x16, /* () System Clock M (System PLL VCO Divider) */
143
        SYSCLKP         = 0x17, /* () System Clock P */
144
        SYSCLKC         = 0x18, /* () System Clock C */
145
        /*
146
         * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1)
147
         * c is charge pump bias which depends on the VCO frequency
148
         */
149
        PIXM0           = 0x20, /* () Pixel M 0 */
150
        PIXN0           = 0x21, /* () Pixel N 0 */
151
        PIXP0           = 0x22, /* () Pixel P 0 */
152
        PIXC0           = 0x23, /* () Pixel C 0 */
153
        CURSCTL         = 0x30, /* (0x00) Cursor Control */
154
        CURSXLO         = 0x31, /* () Cursor X position, low 8 bits */
155
        CURSXHI         = 0x32, /* () Cursor X position, high 8 bits */
156
        CURSYLO         = 0x33, /* () Cursor Y position, low 8 bits */
157
        CURSYHI         = 0x34, /* () Cursor Y position, high 8 bits */
158
        CURSHOTX        = 0x35, /* () Cursor Hot Spot X */
159
        CURSHOTY        = 0x36, /* () Cursor Hot Spot Y */
160
        CURSACCTL       = 0x37, /* () Advanced Cursor Control Enable */
161
        CURSACATTR      = 0x38, /* () Advanced Cursor Attribute */
162
        CURS1R          = 0x40, /* () Cursor 1 Red */
163
        CURS1G          = 0x41, /* () Cursor 1 Green */
164
        CURS1B          = 0x42, /* () Cursor 1 Blue */
165
        CURS2R          = 0x43, /* () Cursor 2 Red */
166
        CURS2G          = 0x44, /* () Cursor 2 Green */
167
        CURS2B          = 0x45, /* () Cursor 2 Blue */
168
        CURS3R          = 0x46, /* () Cursor 3 Red */
169
        CURS3G          = 0x47, /* () Cursor 3 Green */
170
        CURS3B          = 0x48, /* () Cursor 3 Blue */
171
        BORDR           = 0x60, /* () Border Color Red */
172
        BORDG           = 0x61, /* () Border Color Green */
173
        BORDB           = 0x62, /* () Border Color Blue */
174
        MISCTL1         = 0x70, /* (0x00) Miscellaneous Control 1 */
175
        MISCTL2         = 0x71, /* (0x00) Miscellaneous Control 2 */
176
        MISCTL3         = 0x72, /* (0x00) Miscellaneous Control 3 */
177
        KEYCTL          = 0x78  /* (0x00) Key Control/DB Operation */
178
};
179
 
180
/* TI TVP 3030 RAMDAC Direct Registers */
181
enum {
182
        TVPADDRW = 0x00,        /* 0  Palette/Cursor RAM Write Address/Index */
183
        TVPPDATA = 0x04,        /* 1  Palette Data RAM Data */
184
        TVPPMASK = 0x08,        /* 2  Pixel Read-Mask */
185
        TVPPADRR = 0x0c,        /* 3  Palette/Cursor RAM Read Address */
186
        TVPCADRW = 0x10,        /* 4  Cursor/Overscan Color Write Address */
187
        TVPCDATA = 0x14,        /* 5  Cursor/Overscan Color Data */
188
                                /* 6  reserved */
189
        TVPCADRR = 0x1c,        /* 7  Cursor/Overscan Color Read Address */
190
                                /* 8  reserved */
191
        TVPDCCTL = 0x24,        /* 9  Direct Cursor Control */
192
        TVPIDATA = 0x28,        /* 10 Index Data */
193
        TVPCRDAT = 0x2c,        /* 11 Cursor RAM Data */
194
        TVPCXPOL = 0x30,        /* 12 Cursor-Position X LSB */
195
        TVPCXPOH = 0x34,        /* 13 Cursor-Position X MSB */
196
        TVPCYPOL = 0x38,        /* 14 Cursor-Position Y LSB */
197
        TVPCYPOH = 0x3c,        /* 15 Cursor-Position Y MSB */
198
};
199
 
200
/* TI TVP 3030 RAMDAC Indirect Registers */
201
enum {
202
        TVPIRREV = 0x01,        /* Silicon Revision [RO] */
203
        TVPIRICC = 0x06,        /* Indirect Cursor Control      (0x00) */
204
        TVPIRBRC = 0x07,        /* Byte Router Control  (0xe4) */
205
        TVPIRLAC = 0x0f,        /* Latch Control                (0x06) */
206
        TVPIRTCC = 0x18,        /* True Color Control   (0x80) */
207
        TVPIRMXC = 0x19,        /* Multiplex Control            (0x98) */
208
        TVPIRCLS = 0x1a,        /* Clock Selection              (0x07) */
209
        TVPIRPPG = 0x1c,        /* Palette Page         (0x00) */
210
        TVPIRGEC = 0x1d,        /* General Control              (0x00) */
211
        TVPIRMIC = 0x1e,        /* Miscellaneous Control        (0x00) */
212
        TVPIRPLA = 0x2c,        /* PLL Address */
213
        TVPIRPPD = 0x2d,        /* Pixel Clock PLL Data */
214
        TVPIRMPD = 0x2e,        /* Memory Clock PLL Data */
215
        TVPIRLPD = 0x2f,        /* Loop Clock PLL Data */
216
        TVPIRCKL = 0x30,        /* Color-Key Overlay Low */
217
        TVPIRCKH = 0x31,        /* Color-Key Overlay High */
218
        TVPIRCRL = 0x32,        /* Color-Key Red Low */
219
        TVPIRCRH = 0x33,        /* Color-Key Red High */
220
        TVPIRCGL = 0x34,        /* Color-Key Green Low */
221
        TVPIRCGH = 0x35,        /* Color-Key Green High */
222
        TVPIRCBL = 0x36,        /* Color-Key Blue Low */
223
        TVPIRCBH = 0x37,        /* Color-Key Blue High */
224
        TVPIRCKC = 0x38,        /* Color-Key Control            (0x00) */
225
        TVPIRMLC = 0x39,        /* MCLK/Loop Clock Control      (0x18) */
226
        TVPIRSEN = 0x3a,        /* Sense Test                   (0x00) */
227
        TVPIRTMD = 0x3b,        /* Test Mode Data */
228
        TVPIRRML = 0x3c,        /* CRC Remainder LSB [RO] */
229
        TVPIRRMM = 0x3d,        /* CRC Remainder MSB [RO] */
230
        TVPIRRMS = 0x3e,        /* CRC  Bit Select [WO] */
231
        TVPIRDID = 0x3f,        /* Device ID [RO]               (0x30) */
232
        TVPIRRES = 0xff         /* Software Reset [WO] */
233
};
234
 
235
struct initvalues {
236
        __u8 addr, value;
237
};
238
 
239
static struct initvalues ibm_initregs[] __initdata = {
240
        { CLKCTL,       0x21 },
241
        { SYNCCTL,      0x00 },
242
        { HSYNCPOS,     0x00 },
243
        { PWRMNGMT,     0x00 },
244
        { DACOP,        0x02 },
245
        { PALETCTL,     0x00 },
246
        { SYSCLKCTL,    0x01 },
247
 
248
        /*
249
         * Note that colors in X are correct only if all video data is
250
         * passed through the palette in the DAC.  That is, "indirect
251
         * color" must be configured.  This is the case for the IBM DAC
252
         * used in the 2MB and 4MB cards, at least.
253
         */
254
        { BPP8,         0x00 },
255
        { BPP16,        0x01 },
256
        { BPP24,        0x00 },
257
        { BPP32,        0x00 },
258
 
259
        { PIXCTL1,      0x05 },
260
        { PIXCTL2,      0x00 },
261
        { SYSCLKN,      0x08 },
262
        { SYSCLKM,      0x4f },
263
        { SYSCLKP,      0x00 },
264
        { SYSCLKC,      0x00 },
265
        { CURSCTL,      0x00 },
266
        { CURSACCTL,    0x01 },
267
        { CURSACATTR,   0xa8 },
268
        { CURS1R,       0xff },
269
        { CURS1G,       0xff },
270
        { CURS1B,       0xff },
271
        { CURS2R,       0xff },
272
        { CURS2G,       0xff },
273
        { CURS2B,       0xff },
274
        { CURS3R,       0xff },
275
        { CURS3G,       0xff },
276
        { CURS3B,       0xff },
277
        { BORDR,        0xff },
278
        { BORDG,        0xff },
279
        { BORDB,        0xff },
280
        { MISCTL1,      0x01 },
281
        { MISCTL2,      0x45 },
282
        { MISCTL3,      0x00 },
283
        { KEYCTL,       0x00 }
284
};
285
 
286
static struct initvalues tvp_initregs[] __initdata = {
287
        { TVPIRICC,     0x00 },
288
        { TVPIRBRC,     0xe4 },
289
        { TVPIRLAC,     0x06 },
290
        { TVPIRTCC,     0x80 },
291
        { TVPIRMXC,     0x4d },
292
        { TVPIRCLS,     0x05 },
293
        { TVPIRPPG,     0x00 },
294
        { TVPIRGEC,     0x00 },
295
        { TVPIRMIC,     0x08 },
296
        { TVPIRCKL,     0xff },
297
        { TVPIRCKH,     0xff },
298
        { TVPIRCRL,     0xff },
299
        { TVPIRCRH,     0xff },
300
        { TVPIRCGL,     0xff },
301
        { TVPIRCGH,     0xff },
302
        { TVPIRCBL,     0xff },
303
        { TVPIRCBH,     0xff },
304
        { TVPIRCKC,     0x00 },
305
        { TVPIRPLA,     0x00 },
306
        { TVPIRPPD,     0xc0 },
307
        { TVPIRPPD,     0xd5 },
308
        { TVPIRPPD,     0xea },
309
        { TVPIRPLA,     0x00 },
310
        { TVPIRMPD,     0xb9 },
311
        { TVPIRMPD,     0x3a },
312
        { TVPIRMPD,     0xb1 },
313
        { TVPIRPLA,     0x00 },
314
        { TVPIRLPD,     0xc1 },
315
        { TVPIRLPD,     0x3d },
316
        { TVPIRLPD,     0xf3 },
317
};
318
 
319
struct imstt_regvals {
320
        __u32 pitch;
321
        __u16 hes, heb, hsb, ht, ves, veb, vsb, vt, vil;
322
        __u8 pclk_m, pclk_n, pclk_p;
323
        /* Values of the tvp which change depending on colormode x resolution */
324
        __u8 mlc[3];    /* Memory Loop Config 0x39 */
325
        __u8 lckl_p[3]; /* P value of LCKL PLL */
326
};
327
 
328
struct imstt_cursor {
329
        struct timer_list timer;
330
        int enable;
331
        int on;
332
        int vbl_cnt;
333
        int blink_rate;
334
        __u16 x, y, width, height;
335
};
336
 
337
struct fb_info_imstt {
338
        struct fb_info info;
339
        struct fb_fix_screeninfo fix;
340
        struct display disp;
341
        struct display_switch dispsw;
342
        union {
343
#ifdef FBCON_HAS_CFB16
344
                __u16 cfb16[16];
345
#endif
346
#ifdef FBCON_HAS_CFB24
347
                __u32 cfb24[16];
348
#endif
349
#ifdef FBCON_HAS_CFB32
350
                __u32 cfb32[16];
351
#endif
352
        } fbcon_cmap;
353
        struct {
354
                __u8 red, green, blue;
355
        } palette[256];
356
        struct imstt_regvals init;
357
        struct imstt_cursor cursor;
358
        unsigned long frame_buffer_phys;
359
        unsigned long board_size;
360
        __u8 *frame_buffer;
361
        unsigned long dc_regs_phys;
362
        __u32 *dc_regs;
363
        unsigned long cmap_regs_phys;
364
        __u8 *cmap_regs;
365
        __u32 total_vram;
366
        __u32 ramdac;
367
};
368
 
369
enum {
370
        IBM = 0,
371
        TVP = 1
372
};
373
 
374
#define INIT_BPP                8
375
#define INIT_XRES               640
376
#define INIT_YRES               480
377
#define CURSOR_BLINK_RATE       20
378
#define CURSOR_DRAW_DELAY       2
379
 
380
static int currcon = 0;
381
static int inverse = 0;
382
static char fontname[40] __initdata = { 0 };
383
static char curblink __initdata = 1;
384
static char noaccel __initdata = 0;
385
#if defined(CONFIG_PPC)
386
static signed char init_vmode __initdata = VMODE_NVRAM;
387
static signed char init_cmode __initdata = CMODE_NVRAM;
388
#endif
389
 
390
static struct imstt_regvals tvp_reg_init_2 = {
391
        512,
392
        0x0002, 0x0006, 0x0026, 0x0028, 0x0003, 0x0016, 0x0196, 0x0197, 0x0196,
393
        0xec, 0x2a, 0xf3,
394
        { 0x3c, 0x3b, 0x39 }, { 0xf3, 0xf3, 0xf3 }
395
};
396
 
397
static struct imstt_regvals tvp_reg_init_6 = {
398
        640,
399
        0x0004, 0x0009, 0x0031, 0x0036, 0x0003, 0x002a, 0x020a, 0x020d, 0x020a,
400
        0xef, 0x2e, 0xb2,
401
        { 0x39, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
402
};
403
 
404
static struct imstt_regvals tvp_reg_init_12 = {
405
        800,
406
        0x0005, 0x000e, 0x0040, 0x0042, 0x0003, 0x018, 0x270, 0x271, 0x270,
407
        0xf6, 0x2e, 0xf2,
408
        { 0x3a, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
409
};
410
 
411
static struct imstt_regvals tvp_reg_init_13 = {
412
        832,
413
        0x0004, 0x0011, 0x0045, 0x0048, 0x0003, 0x002a, 0x029a, 0x029b, 0x0000,
414
        0xfe, 0x3e, 0xf1,
415
        { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
416
};
417
 
418
static struct imstt_regvals tvp_reg_init_17 = {
419
        1024,
420
        0x0006, 0x0210, 0x0250, 0x0053, 0x1003, 0x0021, 0x0321, 0x0324, 0x0000,
421
        0xfc, 0x3a, 0xf1,
422
        { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
423
};
424
 
425
static struct imstt_regvals tvp_reg_init_18 = {
426
        1152,
427
        0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000,
428
        0xfd, 0x3a, 0xf1,
429
        { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
430
};
431
 
432
static struct imstt_regvals tvp_reg_init_19 = {
433
        1280,
434
        0x0009, 0x0016, 0x0066, 0x0069, 0x0003, 0x0027, 0x03e7, 0x03e8, 0x03e7,
435
        0xf7, 0x36, 0xf0,
436
        { 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
437
};
438
 
439
static struct imstt_regvals tvp_reg_init_20 = {
440
        1280,
441
        0x0009, 0x0018, 0x0068, 0x006a, 0x0003, 0x0029, 0x0429, 0x042a, 0x0000,
442
        0xf0, 0x2d, 0xf0,
443
        { 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
444
};
445
 
446
/*
447
 * PCI driver prototypes
448
 */
449
static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
450
static void imsttfb_remove(struct pci_dev *pdev);
451
 
452
static __u32
453
getclkMHz (struct fb_info_imstt *p)
454
{
455
        __u32 clk_m, clk_n, clk_p;
456
 
457
        clk_m = p->init.pclk_m;
458
        clk_n = p->init.pclk_n;
459
        clk_p = p->init.pclk_p;
460
 
461
        return 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));
462
}
463
 
464
static void
465
setclkMHz (struct fb_info_imstt *p, __u32 MHz)
466
{
467
        __u32 clk_m, clk_n, clk_p, x, stage, spilled;
468
 
469
        clk_m = clk_n = clk_p = 0;
470
        stage = spilled = 0;
471
        for (;;) {
472
                switch (stage) {
473
                        case 0:
474
                                clk_m++;
475
                                break;
476
                        case 1:
477
                                clk_n++;
478
                                break;
479
                }
480
                x = 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));
481
                if (x == MHz)
482
                        break;
483
                if (x > MHz) {
484
                        spilled = 1;
485
                        stage = 1;
486
                } else if (spilled && x < MHz) {
487
                        stage = 0;
488
                }
489
        }
490
 
491
        p->init.pclk_m = clk_m;
492
        p->init.pclk_n = clk_n;
493
        p->init.pclk_p = clk_p;
494
}
495
 
496
static struct imstt_regvals *
497
compute_imstt_regvals_ibm (struct fb_info_imstt *p, int xres, int yres)
498
{
499
        struct imstt_regvals *init = &p->init;
500
        __u32 MHz, hes, heb, veb, htp, vtp;
501
 
502
        switch (xres) {
503
                case 640:
504
                        hes = 0x0008; heb = 0x0012; veb = 0x002a; htp = 10; vtp = 2;
505
                        MHz = 30 /* .25 */ ;
506
                        break;
507
                case 832:
508
                        hes = 0x0005; heb = 0x0020; veb = 0x0028; htp = 8; vtp = 3;
509
                        MHz = 57 /* .27_ */ ;
510
                        break;
511
                case 1024:
512
                        hes = 0x000a; heb = 0x001c; veb = 0x0020; htp = 8; vtp = 3;
513
                        MHz = 80;
514
                        break;
515
                case 1152:
516
                        hes = 0x0012; heb = 0x0022; veb = 0x0031; htp = 4; vtp = 3;
517
                        MHz = 101 /* .6_ */ ;
518
                        break;
519
                case 1280:
520
                        hes = 0x0012; heb = 0x002f; veb = 0x0029; htp = 4; vtp = 1;
521
                        MHz = yres == 960 ? 126 : 135;
522
                        break;
523
                case 1600:
524
                        hes = 0x0018; heb = 0x0040; veb = 0x002a; htp = 4; vtp = 3;
525
                        MHz = 200;
526
                        break;
527
                default:
528
                        return 0;
529
        }
530
 
531
        setclkMHz(p, MHz);
532
 
533
        init->hes = hes;
534
        init->heb = heb;
535
        init->hsb = init->heb + (xres >> 3);
536
        init->ht = init->hsb + htp;
537
        init->ves = 0x0003;
538
        init->veb = veb;
539
        init->vsb = init->veb + yres;
540
        init->vt = init->vsb + vtp;
541
        init->vil = init->vsb;
542
 
543
        init->pitch = xres;
544
 
545
        return init;
546
}
547
 
548
static struct imstt_regvals *
549
compute_imstt_regvals_tvp (struct fb_info_imstt *p, int xres, int yres)
550
{
551
        struct imstt_regvals *init;
552
 
553
        switch (xres) {
554
                case 512:
555
                        init = &tvp_reg_init_2;
556
                        break;
557
                case 640:
558
                        init = &tvp_reg_init_6;
559
                        break;
560
                case 800:
561
                        init = &tvp_reg_init_12;
562
                        break;
563
                case 832:
564
                        init = &tvp_reg_init_13;
565
                        break;
566
                case 1024:
567
                        init = &tvp_reg_init_17;
568
                        break;
569
                case 1152:
570
                        init = &tvp_reg_init_18;
571
                        break;
572
                case 1280:
573
                        init = yres == 960 ? &tvp_reg_init_19 : &tvp_reg_init_20;
574
                        break;
575
                default:
576
                        return 0;
577
        }
578
        p->init = *init;
579
 
580
        return init;
581
}
582
 
583
static struct imstt_regvals *
584
compute_imstt_regvals (struct fb_info_imstt *p, u_int xres, u_int yres)
585
{
586
        if (p->ramdac == IBM)
587
                return compute_imstt_regvals_ibm(p, xres, yres);
588
        else
589
                return compute_imstt_regvals_tvp(p, xres, yres);
590
}
591
 
592
static void
593
set_imstt_regvals_ibm (struct fb_info_imstt *p, u_int bpp)
594
{
595
        struct imstt_regvals *init = &p->init;
596
        __u8 pformat = (bpp >> 3) + 2;
597
 
598
        p->cmap_regs[PIDXHI] = 0;                eieio();
599
        p->cmap_regs[PIDXLO] = PIXM0;           eieio();
600
        p->cmap_regs[PIDXDATA] = init->pclk_m;  eieio();
601
        p->cmap_regs[PIDXLO] = PIXN0;           eieio();
602
        p->cmap_regs[PIDXDATA] = init->pclk_n;  eieio();
603
        p->cmap_regs[PIDXLO] = PIXP0;           eieio();
604
        p->cmap_regs[PIDXDATA] = init->pclk_p;  eieio();
605
        p->cmap_regs[PIDXLO] = PIXC0;           eieio();
606
        p->cmap_regs[PIDXDATA] = 0x02;          eieio();
607
 
608
        p->cmap_regs[PIDXLO] = PIXFMT;          eieio();
609
        p->cmap_regs[PIDXDATA] = pformat;       eieio();
610
}
611
 
612
static void
613
set_imstt_regvals_tvp (struct fb_info_imstt *p, u_int bpp)
614
{
615
        struct imstt_regvals *init = &p->init;
616
        __u8 tcc, mxc, lckl_n, mic;
617
        __u8 mlc, lckl_p;
618
 
619
        switch (bpp) {
620
                case 8:
621
                        tcc = 0x80;
622
                        mxc = 0x4d;
623
                        lckl_n = 0xc1;
624
                        mlc = init->mlc[0];
625
                        lckl_p = init->lckl_p[0];
626
                        break;
627
                case 16:
628
                        tcc = 0x44;
629
                        mxc = 0x55;
630
                        lckl_n = 0xe1;
631
                        mlc = init->mlc[1];
632
                        lckl_p = init->lckl_p[1];
633
                        break;
634
                case 24:
635
                        tcc = 0x5e;
636
                        mxc = 0x5d;
637
                        lckl_n = 0xf1;
638
                        mlc = init->mlc[2];
639
                        lckl_p = init->lckl_p[2];
640
                        break;
641
                case 32:
642
                        tcc = 0x46;
643
                        mxc = 0x5d;
644
                        lckl_n = 0xf1;
645
                        mlc = init->mlc[2];
646
                        lckl_p = init->lckl_p[2];
647
                        break;
648
        }
649
        mic = 0x08;
650
 
651
        p->cmap_regs[TVPADDRW] = TVPIRPLA;      eieio();
652
        p->cmap_regs[TVPIDATA] = 0x00;          eieio();
653
        p->cmap_regs[TVPADDRW] = TVPIRPPD;      eieio();
654
        p->cmap_regs[TVPIDATA] = init->pclk_m;  eieio();
655
        p->cmap_regs[TVPADDRW] = TVPIRPPD;      eieio();
656
        p->cmap_regs[TVPIDATA] = init->pclk_n;  eieio();
657
        p->cmap_regs[TVPADDRW] = TVPIRPPD;      eieio();
658
        p->cmap_regs[TVPIDATA] = init->pclk_p;  eieio();
659
 
660
        p->cmap_regs[TVPADDRW] = TVPIRTCC;      eieio();
661
        p->cmap_regs[TVPIDATA] = tcc;           eieio();
662
        p->cmap_regs[TVPADDRW] = TVPIRMXC;      eieio();
663
        p->cmap_regs[TVPIDATA] = mxc;           eieio();
664
        p->cmap_regs[TVPADDRW] = TVPIRMIC;      eieio();
665
        p->cmap_regs[TVPIDATA] = mic;           eieio();
666
 
667
        p->cmap_regs[TVPADDRW] = TVPIRPLA;      eieio();
668
        p->cmap_regs[TVPIDATA] = 0x00;          eieio();
669
        p->cmap_regs[TVPADDRW] = TVPIRLPD;      eieio();
670
        p->cmap_regs[TVPIDATA] = lckl_n;        eieio();
671
 
672
        p->cmap_regs[TVPADDRW] = TVPIRPLA;      eieio();
673
        p->cmap_regs[TVPIDATA] = 0x15;          eieio();
674
        p->cmap_regs[TVPADDRW] = TVPIRMLC;      eieio();
675
        p->cmap_regs[TVPIDATA] = mlc;           eieio();
676
 
677
        p->cmap_regs[TVPADDRW] = TVPIRPLA;      eieio();
678
        p->cmap_regs[TVPIDATA] = 0x2a;          eieio();
679
        p->cmap_regs[TVPADDRW] = TVPIRLPD;      eieio();
680
        p->cmap_regs[TVPIDATA] = lckl_p;        eieio();
681
}
682
 
683
static void
684
set_imstt_regvals (struct fb_info_imstt *p, u_int bpp)
685
{
686
        struct imstt_regvals *init = &p->init;
687
        __u32 ctl, pitch, byteswap, scr;
688
 
689
        if (p->ramdac == IBM)
690
                set_imstt_regvals_ibm(p, bpp);
691
        else
692
                set_imstt_regvals_tvp(p, bpp);
693
 
694
  /*
695
   * From what I (jsk) can gather poking around with MacsBug,
696
   * bits 8 and 9 in the SCR register control endianness
697
   * correction (byte swapping).  These bits must be set according
698
   * to the color depth as follows:
699
   *     Color depth    Bit 9   Bit 8
700
   *     ==========     =====   =====
701
   *        8bpp          0       0
702
   *       16bpp          0       1
703
   *       32bpp          1       1
704
   */
705
        switch (bpp) {
706
                case 8:
707
                        ctl = 0x17b1;
708
                        pitch = init->pitch >> 2;
709
                        byteswap = 0x000;
710
                        break;
711
                case 16:
712
                        ctl = 0x17b3;
713
                        pitch = init->pitch >> 1;
714
                        byteswap = 0x100;
715
                        break;
716
                case 24:
717
                        ctl = 0x17b9;
718
                        pitch = init->pitch - (p->init.pitch >> 2);
719
                        byteswap = 0x200;
720
                        break;
721
                case 32:
722
                        ctl = 0x17b5;
723
                        pitch = init->pitch;
724
                        byteswap = 0x300;
725
                        break;
726
        }
727
        if (p->ramdac == TVP)
728
                ctl -= 0x30;
729
 
730
        out_le32(&p->dc_regs[HES], init->hes);
731
        out_le32(&p->dc_regs[HEB], init->heb);
732
        out_le32(&p->dc_regs[HSB], init->hsb);
733
        out_le32(&p->dc_regs[HT], init->ht);
734
        out_le32(&p->dc_regs[VES], init->ves);
735
        out_le32(&p->dc_regs[VEB], init->veb);
736
        out_le32(&p->dc_regs[VSB], init->vsb);
737
        out_le32(&p->dc_regs[VT], init->vt);
738
        out_le32(&p->dc_regs[VIL], init->vil);
739
        out_le32(&p->dc_regs[HCIV], 1);
740
        out_le32(&p->dc_regs[VCIV], 1);
741
        out_le32(&p->dc_regs[TCDR], 4);
742
        out_le32(&p->dc_regs[RRCIV], 1);
743
        out_le32(&p->dc_regs[RRSC], 0x980);
744
        out_le32(&p->dc_regs[RRCR], 0x11);
745
 
746
        if (p->ramdac == IBM) {
747
                out_le32(&p->dc_regs[HRIR], 0x0100);
748
                out_le32(&p->dc_regs[CMR], 0x00ff);
749
                out_le32(&p->dc_regs[SRGCTL], 0x0073);
750
        } else {
751
                out_le32(&p->dc_regs[HRIR], 0x0200);
752
                out_le32(&p->dc_regs[CMR], 0x01ff);
753
                out_le32(&p->dc_regs[SRGCTL], 0x0003);
754
        }
755
 
756
        switch (p->total_vram) {
757
                case 0x200000:
758
                        scr = 0x059d | byteswap;
759
                        break;
760
                /* case 0x400000:
761
                   case 0x800000: */
762
                default:
763
                        pitch >>= 1;
764
                        scr = 0x150dd | byteswap;
765
                        break;
766
        }
767
 
768
        out_le32(&p->dc_regs[SCR], scr);
769
        out_le32(&p->dc_regs[SPR], pitch);
770
        out_le32(&p->dc_regs[STGCTL], ctl);
771
}
772
 
773
static inline void
774
set_offset (struct display *disp, struct fb_info_imstt *p)
775
{
776
        __u32 off = disp->var.yoffset * (disp->line_length >> 3)
777
                    + ((disp->var.xoffset * (disp->var.bits_per_pixel >> 3)) >> 3);
778
        out_le32(&p->dc_regs[SSR], off);
779
}
780
 
781
static inline void
782
set_555 (struct fb_info_imstt *p)
783
{
784
        if (p->ramdac == IBM) {
785
                p->cmap_regs[PIDXHI] = 0;        eieio();
786
                p->cmap_regs[PIDXLO] = BPP16;   eieio();
787
                p->cmap_regs[PIDXDATA] = 0x01;  eieio();
788
        } else {
789
                p->cmap_regs[TVPADDRW] = TVPIRTCC;      eieio();
790
                p->cmap_regs[TVPIDATA] = 0x44;          eieio();
791
        }
792
}
793
 
794
static inline void
795
set_565 (struct fb_info_imstt *p)
796
{
797
        if (p->ramdac == IBM) {
798
                p->cmap_regs[PIDXHI] = 0;        eieio();
799
                p->cmap_regs[PIDXLO] = BPP16;   eieio();
800
                p->cmap_regs[PIDXDATA] = 0x03;  eieio();
801
        } else {
802
                p->cmap_regs[TVPADDRW] = TVPIRTCC;      eieio();
803
                p->cmap_regs[TVPIDATA] = 0x45;          eieio();
804
        }
805
}
806
 
807
static void
808
imstt_set_cursor (struct fb_info_imstt *p, int on)
809
{
810
        struct imstt_cursor *c = &p->cursor;
811
 
812
        if (p->ramdac == IBM) {
813
                p->cmap_regs[PIDXHI] = 0;        eieio();
814
                if (!on) {
815
                        p->cmap_regs[PIDXLO] = CURSCTL; eieio();
816
                        p->cmap_regs[PIDXDATA] = 0x00;  eieio();
817
                } else {
818
                        p->cmap_regs[PIDXLO] = CURSXHI;         eieio();
819
                        p->cmap_regs[PIDXDATA] = c->x >> 8;     eieio();
820
                        p->cmap_regs[PIDXLO] = CURSXLO;         eieio();
821
                        p->cmap_regs[PIDXDATA] = c->x & 0xff;   eieio();
822
                        p->cmap_regs[PIDXLO] = CURSYHI;         eieio();
823
                        p->cmap_regs[PIDXDATA] = c->y >> 8;     eieio();
824
                        p->cmap_regs[PIDXLO] = CURSYLO;         eieio();
825
                        p->cmap_regs[PIDXDATA] = c->y & 0xff;   eieio();
826
                        p->cmap_regs[PIDXLO] = CURSCTL;         eieio();
827
                        p->cmap_regs[PIDXDATA] = 0x02;          eieio();
828
                }
829
        } else {
830
                if (!on) {
831
                        p->cmap_regs[TVPADDRW] = TVPIRICC;      eieio();
832
                        p->cmap_regs[TVPIDATA] = 0x00;          eieio();
833
                } else {
834
                        __u16 x = c->x + 0x40, y = c->y + 0x40;
835
 
836
                        p->cmap_regs[TVPCXPOH] = x >> 8;        eieio();
837
                        p->cmap_regs[TVPCXPOL] = x & 0xff;      eieio();
838
                        p->cmap_regs[TVPCYPOH] = y >> 8;        eieio();
839
                        p->cmap_regs[TVPCYPOL] = y & 0xff;      eieio();
840
                        p->cmap_regs[TVPADDRW] = TVPIRICC;      eieio();
841
                        p->cmap_regs[TVPIDATA] = 0x02;          eieio();
842
                }
843
        }
844
}
845
 
846
static void
847
imsttfbcon_cursor (struct display *disp, int mode, int x, int y)
848
{
849
        struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
850
        struct imstt_cursor *c = &p->cursor;
851
 
852
        x *= fontwidth(disp);
853
        y *= fontheight(disp);
854
 
855
        if (c->x == x && c->y == y && (mode == CM_ERASE) == !c->enable)
856
                return;
857
 
858
        c->enable = 0;
859
        if (c->on)
860
                imstt_set_cursor(p, 0);
861
        c->x = x - disp->var.xoffset;
862
        c->y = y - disp->var.yoffset;
863
 
864
        switch (mode) {
865
                case CM_ERASE:
866
                        c->on = 0;
867
                        break;
868
                case CM_DRAW:
869
                case CM_MOVE:
870
                        if (c->on)
871
                                imstt_set_cursor(p, c->on);
872
                        else
873
                                c->vbl_cnt = CURSOR_DRAW_DELAY;
874
                        c->enable = 1;
875
                        break;
876
        }
877
}
878
 
879
static int
880
imsttfbcon_set_font (struct display *disp, int width, int height)
881
{
882
        struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
883
        struct imstt_cursor *c = &p->cursor;
884
        u_int x, y;
885
        __u8 fgc;
886
 
887
        if (width > 32 || height > 32)
888
                return -EINVAL;
889
 
890
        c->height = height;
891
        c->width = width;
892
 
893
        fgc = ~attr_bgcol_ec(disp, disp->conp);
894
 
895
        if (p->ramdac == IBM) {
896
                p->cmap_regs[PIDXHI] = 1;       eieio();
897
                for (x = 0; x < 0x100; x++) {
898
                        p->cmap_regs[PIDXLO] = x;       eieio();
899
                        p->cmap_regs[PIDXDATA] = 0x00;  eieio();
900
                }
901
                p->cmap_regs[PIDXHI] = 1;       eieio();
902
                for (y = 0; y < height; y++)
903
                        for (x = 0; x < width >> 2; x++) {
904
                                p->cmap_regs[PIDXLO] = x + y * 8;       eieio();
905
                                p->cmap_regs[PIDXDATA] = 0xff;          eieio();
906
                        }
907
                p->cmap_regs[PIDXHI] = 0;        eieio();
908
                p->cmap_regs[PIDXLO] = CURS1R;  eieio();
909
                p->cmap_regs[PIDXDATA] = fgc;   eieio();
910
                p->cmap_regs[PIDXLO] = CURS1G;  eieio();
911
                p->cmap_regs[PIDXDATA] = fgc;   eieio();
912
                p->cmap_regs[PIDXLO] = CURS1B;  eieio();
913
                p->cmap_regs[PIDXDATA] = fgc;   eieio();
914
                p->cmap_regs[PIDXLO] = CURS2R;  eieio();
915
                p->cmap_regs[PIDXDATA] = fgc;   eieio();
916
                p->cmap_regs[PIDXLO] = CURS2G;  eieio();
917
                p->cmap_regs[PIDXDATA] = fgc;   eieio();
918
                p->cmap_regs[PIDXLO] = CURS2B;  eieio();
919
                p->cmap_regs[PIDXDATA] = fgc;   eieio();
920
                p->cmap_regs[PIDXLO] = CURS3R;  eieio();
921
                p->cmap_regs[PIDXDATA] = fgc;   eieio();
922
                p->cmap_regs[PIDXLO] = CURS3G;  eieio();
923
                p->cmap_regs[PIDXDATA] = fgc;   eieio();
924
                p->cmap_regs[PIDXLO] = CURS3B;  eieio();
925
                p->cmap_regs[PIDXDATA] = fgc;   eieio();
926
        } else {
927
                p->cmap_regs[TVPADDRW] = TVPIRICC;      eieio();
928
                p->cmap_regs[TVPIDATA] &= 0x03;         eieio();
929
                p->cmap_regs[TVPADDRW] = 0;              eieio();
930
                for (x = 0; x < 0x200; x++) {
931
                        p->cmap_regs[TVPCRDAT] = 0x00;  eieio();
932
                }
933
                for (x = 0; x < 0x200; x++) {
934
                        p->cmap_regs[TVPCRDAT] = 0xff;  eieio();
935
                }
936
                p->cmap_regs[TVPADDRW] = TVPIRICC;      eieio();
937
                p->cmap_regs[TVPIDATA] &= 0x03;         eieio();
938
                for (y = 0; y < height; y++)
939
                        for (x = 0; x < width >> 3; x++) {
940
                                p->cmap_regs[TVPADDRW] = x + y * 8;     eieio();
941
                                p->cmap_regs[TVPCRDAT] = 0xff;          eieio();
942
                        }
943
                p->cmap_regs[TVPADDRW] = TVPIRICC;      eieio();
944
                p->cmap_regs[TVPIDATA] |= 0x08;         eieio();
945
                for (y = 0; y < height; y++)
946
                        for (x = 0; x < width >> 3; x++) {
947
                                p->cmap_regs[TVPADDRW] = x + y * 8;     eieio();
948
                                p->cmap_regs[TVPCRDAT] = 0xff;          eieio();
949
                        }
950
                p->cmap_regs[TVPCADRW] = 0x00;  eieio();
951
                for (x = 0; x < 12; x++) {
952
                        p->cmap_regs[TVPCDATA] = fgc;   eieio();
953
                }
954
        }
955
 
956
        return 1;
957
}
958
 
959
static void
960
imstt_cursor_timer_handler (unsigned long dev_addr)
961
{
962
        struct fb_info_imstt *p = (struct fb_info_imstt *)dev_addr;
963
        struct imstt_cursor *c = &p->cursor;
964
 
965
        if (!c->enable)
966
                goto out;
967
 
968
        if (c->vbl_cnt && --c->vbl_cnt == 0) {
969
                c->on ^= 1;
970
                imstt_set_cursor(p, c->on);
971
                c->vbl_cnt = c->blink_rate;
972
        }
973
 
974
out:
975
        c->timer.expires = jiffies + (HZ / 50);
976
        add_timer(&c->timer);
977
}
978
 
979
static void __init
980
imstt_cursor_init (struct fb_info_imstt *p)
981
{
982
        struct imstt_cursor *c = &p->cursor;
983
 
984
        imsttfbcon_set_font(&p->disp, fontwidth(&p->disp), fontheight(&p->disp));
985
 
986
        c->enable = 1;
987
        c->on = 1;
988
        c->x = c->y = 0;
989
        c->blink_rate = 0;
990
        c->vbl_cnt = CURSOR_DRAW_DELAY;
991
 
992
        if (curblink) {
993
                c->blink_rate = CURSOR_BLINK_RATE;
994
                init_timer(&c->timer);
995
                c->timer.expires = jiffies + (HZ / 50);
996
                c->timer.data = (unsigned long)p;
997
                c->timer.function = imstt_cursor_timer_handler;
998
                add_timer(&c->timer);
999
        }
1000
}
1001
 
1002
static void
1003
imsttfbcon_bmove (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
1004
{
1005
        struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
1006
        __u32   Bpp, line_pitch,
1007
                fb_offset_old, fb_offset_new,
1008
                sp, dp_octl, cnt, bltctl;
1009
 
1010
        Bpp = disp->var.bits_per_pixel >> 3,
1011
 
1012
        sy *= fontheight(disp);
1013
        sx *= fontwidth(disp);
1014
        sx *= Bpp;
1015
        dy *= fontheight(disp);
1016
        dx *= fontwidth(disp);
1017
        dx *= Bpp;
1018
        height *= fontheight(disp);
1019
        height--;
1020
        width *= fontwidth(disp);
1021
        width *= Bpp;
1022
        width--;
1023
 
1024
        line_pitch = disp->line_length;
1025
        bltctl = 0x05;
1026
        sp = line_pitch << 16;
1027
        cnt = height << 16;
1028
 
1029
        if (sy < dy) {
1030
                sy += height;
1031
                dy += height;
1032
                sp |= -(line_pitch) & 0xffff;
1033
                dp_octl = -(line_pitch) & 0xffff;
1034
        } else {
1035
                sp |= line_pitch;
1036
                dp_octl = line_pitch;
1037
        }
1038
        if (sx < dx) {
1039
                sx += width;
1040
                dx += width;
1041
                bltctl |= 0x80;
1042
                cnt |= -(width) & 0xffff;
1043
        } else {
1044
                cnt |= width;
1045
        }
1046
        fb_offset_old = sy * line_pitch + sx;
1047
        fb_offset_new = dy * line_pitch + dx;
1048
 
1049
        while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
1050
        out_le32(&p->dc_regs[S1SA], fb_offset_old);
1051
        out_le32(&p->dc_regs[SP], sp);
1052
        out_le32(&p->dc_regs[DSA], fb_offset_new);
1053
        out_le32(&p->dc_regs[CNT], cnt);
1054
        out_le32(&p->dc_regs[DP_OCTL], dp_octl);
1055
        out_le32(&p->dc_regs[BLTCTL], bltctl);
1056
        while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
1057
        while(in_le32(&p->dc_regs[SSTATUS]) & 0x40);
1058
}
1059
 
1060
static void
1061
imsttfbcon_clear (struct vc_data *conp, struct display *disp,
1062
                  int sy, int sx, int height, int width)
1063
{
1064
        struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
1065
        __u32 Bpp, line_pitch, bgc;
1066
 
1067
        bgc = attr_bgcol_ec(disp, conp);
1068
        bgc |= (bgc << 8);
1069
        bgc |= (bgc << 16);
1070
 
1071
        Bpp = disp->var.bits_per_pixel >> 3,
1072
        line_pitch = disp->line_length;
1073
 
1074
        sy *= fontheight(disp);
1075
        sy *= line_pitch;
1076
        sx *= fontwidth(disp);
1077
        sx *= Bpp;
1078
        height *= fontheight(disp);
1079
        height--;
1080
        width *= fontwidth(disp);
1081
        width *= Bpp;
1082
        width--;
1083
 
1084
        while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
1085
        out_le32(&p->dc_regs[DSA], sy + sx);
1086
        out_le32(&p->dc_regs[CNT], (height << 16) | width);
1087
        out_le32(&p->dc_regs[DP_OCTL], line_pitch);
1088
        out_le32(&p->dc_regs[BI], 0xffffffff);
1089
        out_le32(&p->dc_regs[MBC], 0xffffffff);
1090
        out_le32(&p->dc_regs[CLR], bgc);
1091
        out_le32(&p->dc_regs[BLTCTL], 0x840); /* 0x200000 */
1092
        while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
1093
        while(in_le32(&p->dc_regs[SSTATUS]) & 0x40);
1094
}
1095
 
1096
static void
1097
imsttfbcon_revc (struct display *disp, int sx, int sy)
1098
{
1099
        struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
1100
        __u32 Bpp, line_pitch, height, width;
1101
 
1102
        Bpp = disp->var.bits_per_pixel >> 3,
1103
        line_pitch = disp->line_length;
1104
 
1105
        height = fontheight(disp);
1106
        width = fontwidth(disp) * Bpp;
1107
        sy *= height;
1108
        sy *= line_pitch;
1109
        sx *= width;
1110
        height--;
1111
        width--;
1112
 
1113
        while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
1114
        out_le32(&p->dc_regs[DSA], sy + sx);
1115
        out_le32(&p->dc_regs[S1SA], sy + sx);
1116
        out_le32(&p->dc_regs[CNT], (height << 16) | width);
1117
        out_le32(&p->dc_regs[DP_OCTL], line_pitch);
1118
        out_le32(&p->dc_regs[SP], line_pitch);
1119
        out_le32(&p->dc_regs[BLTCTL], 0x40005);
1120
        while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
1121
        while(in_le32(&p->dc_regs[SSTATUS]) & 0x40);
1122
}
1123
 
1124
#ifdef FBCON_HAS_CFB8
1125
static struct display_switch fbcon_imstt8 = {
1126
        setup:          fbcon_cfb8_setup,
1127
        bmove:          imsttfbcon_bmove,
1128
        clear:          imsttfbcon_clear,
1129
        putc:           fbcon_cfb8_putc,
1130
        putcs:          fbcon_cfb8_putcs,
1131
        revc:           imsttfbcon_revc,
1132
        cursor:         imsttfbcon_cursor,
1133
        set_font:       imsttfbcon_set_font,
1134
        clear_margins:  fbcon_cfb8_clear_margins,
1135
        fontwidthmask:  FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
1136
};
1137
#endif
1138
#ifdef FBCON_HAS_CFB16
1139
static struct display_switch fbcon_imstt16 = {
1140
        setup:          fbcon_cfb16_setup,
1141
        bmove:          imsttfbcon_bmove,
1142
        clear:          imsttfbcon_clear,
1143
        putc:           fbcon_cfb16_putc,
1144
        putcs:          fbcon_cfb16_putcs,
1145
        revc:           imsttfbcon_revc,
1146
        cursor:         imsttfbcon_cursor,
1147
        set_font:       imsttfbcon_set_font,
1148
        clear_margins:  fbcon_cfb16_clear_margins,
1149
        fontwidthmask:  FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
1150
};
1151
#endif
1152
#ifdef FBCON_HAS_CFB24
1153
static struct display_switch fbcon_imstt24 = {
1154
        setup:          fbcon_cfb24_setup,
1155
        bmove:          imsttfbcon_bmove,
1156
        clear:          imsttfbcon_clear,
1157
        putc:           fbcon_cfb24_putc,
1158
        putcs:          fbcon_cfb24_putcs,
1159
        revc:           imsttfbcon_revc,
1160
        cursor:         imsttfbcon_cursor,
1161
        set_font:       imsttfbcon_set_font,
1162
        clear_margins:  fbcon_cfb24_clear_margins,
1163
        fontwidthmask:  FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
1164
};
1165
#endif
1166
#ifdef FBCON_HAS_CFB32
1167
static struct display_switch fbcon_imstt32 = {
1168
        setup:          fbcon_cfb32_setup,
1169
        bmove:          imsttfbcon_bmove,
1170
        clear:          imsttfbcon_clear,
1171
        putc:           fbcon_cfb32_putc,
1172
        putcs:          fbcon_cfb32_putcs,
1173
        revc:           imsttfbcon_revc,
1174
        cursor:         imsttfbcon_cursor,
1175
        set_font:       imsttfbcon_set_font,
1176
        clear_margins:  fbcon_cfb32_clear_margins,
1177
        fontwidthmask:  FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
1178
};
1179
#endif
1180
 
1181
#ifdef CONFIG_FB_COMPAT_XPMAC
1182
#include <asm/vc_ioctl.h>
1183
 
1184
extern struct vc_mode display_info;
1185
extern struct fb_info *console_fb_info;
1186
 
1187
static void
1188
set_display_info (struct display *disp)
1189
{
1190
        display_info.width = disp->var.xres;
1191
        display_info.height = disp->var.yres;
1192
        display_info.depth = disp->var.bits_per_pixel;
1193
        display_info.pitch = disp->line_length;
1194
 
1195
        switch (disp->var.xres) {
1196
                case 512:
1197
                        display_info.mode = 2;
1198
                        break;
1199
                case 640:
1200
                        display_info.mode = 6;
1201
                        break;
1202
                case 800:
1203
                        display_info.mode = 12;
1204
                        break;
1205
                case 832:
1206
                        display_info.mode = 13;
1207
                        break;
1208
                case 1024:
1209
                        display_info.mode = 17;
1210
                        break;
1211
                case 1152:
1212
                        display_info.mode = 18;
1213
                        break;
1214
                case 1280:
1215
                        display_info.mode = disp->var.yres == 960 ? 19 : 20;
1216
                        break;
1217
                default:
1218
                        display_info.mode = 0;
1219
        }
1220
}
1221
#endif
1222
 
1223
static int
1224
imsttfb_getcolreg (u_int regno, u_int *red, u_int *green,
1225
                   u_int *blue, u_int *transp, struct fb_info *info)
1226
{
1227
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
1228
 
1229
        if (regno > 255)
1230
                return 1;
1231
        *red = (p->palette[regno].red << 8) | p->palette[regno].red;
1232
        *green = (p->palette[regno].green << 8) | p->palette[regno].green;
1233
        *blue = (p->palette[regno].blue << 8) | p->palette[regno].blue;
1234
        *transp = 0;
1235
 
1236
        return 0;
1237
}
1238
 
1239
static int
1240
imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
1241
                   u_int transp, struct fb_info *info)
1242
{
1243
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
1244
        u_int bpp = fb_display[currcon].var.bits_per_pixel;
1245
 
1246
        if (regno > 255)
1247
                return 1;
1248
 
1249
        red >>= 8;
1250
        green >>= 8;
1251
        blue >>= 8;
1252
 
1253
        p->palette[regno].red = red;
1254
        p->palette[regno].green = green;
1255
        p->palette[regno].blue = blue;
1256
 
1257
        /* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */
1258
        if (0 && bpp == 16)      /* screws up X */
1259
                p->cmap_regs[PADDRW] = regno << 3;
1260
        else
1261
                p->cmap_regs[PADDRW] = regno;
1262
        eieio();
1263
 
1264
        p->cmap_regs[PDATA] = red;      eieio();
1265
        p->cmap_regs[PDATA] = green;    eieio();
1266
        p->cmap_regs[PDATA] = blue;     eieio();
1267
 
1268
        if (regno < 16)
1269
                switch (bpp) {
1270
#ifdef FBCON_HAS_CFB16
1271
                        case 16:
1272
                                p->fbcon_cmap.cfb16[regno] = (regno << (fb_display[currcon].var.green.length == 5 ? 10 : 11)) | (regno << 5) | regno;
1273
                                break;
1274
#endif
1275
#ifdef FBCON_HAS_CFB24
1276
                        case 24:
1277
                                p->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) | regno;
1278
                                break;
1279
#endif
1280
#ifdef FBCON_HAS_CFB32
1281
                        case 32: {
1282
                                int i = (regno << 8) | regno;
1283
                                p->fbcon_cmap.cfb32[regno] = (i << 16) | i;
1284
                                break;
1285
                        }
1286
#endif
1287
                }
1288
 
1289
        return 0;
1290
}
1291
 
1292
static void
1293
do_install_cmap (int con, struct fb_info *info)
1294
{
1295
        if (fb_display[con].cmap.len)
1296
                fb_set_cmap(&fb_display[con].cmap, 1, imsttfb_setcolreg, info);
1297
        else {
1298
                u_int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
1299
                fb_set_cmap(fb_default_cmap(size), 1, imsttfb_setcolreg, info);
1300
        }
1301
}
1302
 
1303
static int
1304
imsttfb_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1305
{
1306
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
1307
        struct fb_var_screeninfo *var = &fb_display[con].var;
1308
 
1309
        *fix = p->fix;
1310
        fix->visual = var->bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
1311
                                               : FB_VISUAL_DIRECTCOLOR;
1312
        fix->line_length = var->xres * (var->bits_per_pixel >> 3);
1313
 
1314
        return 0;
1315
}
1316
 
1317
static int
1318
imsttfb_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
1319
{
1320
        *var = fb_display[con].var;
1321
 
1322
        return 0;
1323
}
1324
 
1325
static void
1326
set_dispsw (struct display *disp, struct fb_info_imstt *p)
1327
{
1328
        u_int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
1329
 
1330
        if (disp->conp && disp->conp->vc_sw && disp->conp->vc_sw->con_cursor)
1331
                disp->conp->vc_sw->con_cursor(disp->conp, CM_ERASE);
1332
 
1333
        p->dispsw = fbcon_dummy;
1334
        disp->dispsw = &p->dispsw;
1335
        disp->dispsw_data = 0;
1336
        switch (disp->var.bits_per_pixel) {
1337
                case 8:
1338
                        disp->var.red.offset = 0;
1339
                        disp->var.red.length = 8;
1340
                        disp->var.green.offset = 0;
1341
                        disp->var.green.length = 8;
1342
                        disp->var.blue.offset = 0;
1343
                        disp->var.blue.length = 8;
1344
                        disp->var.transp.offset = 0;
1345
                        disp->var.transp.length = 0;
1346
#ifdef FBCON_HAS_CFB8
1347
                        p->dispsw = accel ? fbcon_imstt8 : fbcon_cfb8;
1348
#endif
1349
                        break;
1350
                case 16:        /* RGB 555 or 565 */
1351
                        if (disp->var.green.length != 6)
1352
                                disp->var.red.offset = 10;
1353
                        disp->var.red.length = 5;
1354
                        disp->var.green.offset = 5;
1355
                        if (disp->var.green.length != 6)
1356
                                disp->var.green.length = 5;
1357
                        disp->var.blue.offset = 0;
1358
                        disp->var.blue.length = 5;
1359
                        disp->var.transp.offset = 0;
1360
                        disp->var.transp.length = 0;
1361
#ifdef FBCON_HAS_CFB16
1362
                        p->dispsw = accel ? fbcon_imstt16 : fbcon_cfb16;
1363
                        disp->dispsw_data = p->fbcon_cmap.cfb16;
1364
#endif
1365
                        break;
1366
                case 24:        /* RGB 888 */
1367
                        disp->var.red.offset = 16;
1368
                        disp->var.red.length = 8;
1369
                        disp->var.green.offset = 8;
1370
                        disp->var.green.length = 8;
1371
                        disp->var.blue.offset = 0;
1372
                        disp->var.blue.length = 8;
1373
                        disp->var.transp.offset = 0;
1374
                        disp->var.transp.length = 0;
1375
#ifdef FBCON_HAS_CFB24
1376
                        p->dispsw = accel ? fbcon_imstt24 : fbcon_cfb24;
1377
                        disp->dispsw_data = p->fbcon_cmap.cfb24;
1378
#endif
1379
                        break;
1380
                case 32:        /* RGBA 8888 */
1381
                        disp->var.red.offset = 16;
1382
                        disp->var.red.length = 8;
1383
                        disp->var.green.offset = 8;
1384
                        disp->var.green.length = 8;
1385
                        disp->var.blue.offset = 0;
1386
                        disp->var.blue.length = 8;
1387
                        disp->var.transp.offset = 24;
1388
                        disp->var.transp.length = 8;
1389
#ifdef FBCON_HAS_CFB32
1390
                        p->dispsw = accel ? fbcon_imstt32 : fbcon_cfb32;
1391
                        disp->dispsw_data = p->fbcon_cmap.cfb32;
1392
#endif
1393
                        break;
1394
        }
1395
 
1396
        if (accel && p->ramdac != IBM) {
1397
                p->dispsw.cursor = 0;
1398
                p->dispsw.set_font = 0;
1399
        }
1400
 
1401
#ifdef CONFIG_FB_COMPAT_XPMAC
1402
        set_display_info(disp);
1403
#endif
1404
}
1405
 
1406
static void
1407
set_disp (struct display *disp, struct fb_info_imstt *p)
1408
{
1409
        u_int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
1410
 
1411
        disp->fb_info = &p->info;
1412
 
1413
        set_dispsw(disp, p);
1414
 
1415
        disp->visual = disp->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
1416
                                                     : FB_VISUAL_DIRECTCOLOR;
1417
        disp->screen_base = (__u8 *)p->frame_buffer;
1418
        disp->visual = p->fix.visual;
1419
        disp->type = p->fix.type;
1420
        disp->type_aux = p->fix.type_aux;
1421
        disp->line_length = disp->var.xres * (disp->var.bits_per_pixel >> 3);
1422
        disp->can_soft_blank = 1;
1423
        disp->inverse = inverse;
1424
        disp->ypanstep = 1;
1425
        disp->ywrapstep = 0;
1426
        if (accel) {
1427
                disp->scrollmode = SCROLL_YNOMOVE;
1428
                if (disp->var.yres == disp->var.yres_virtual) {
1429
                        __u32 vram = (p->total_vram - (PAGE_SIZE << 2));
1430
                        disp->var.yres_virtual = ((vram << 3) / disp->var.bits_per_pixel) / disp->var.xres_virtual;
1431
                        if (disp->var.yres_virtual < disp->var.yres)
1432
                                disp->var.yres_virtual = disp->var.yres;
1433
                }
1434
        } else {
1435
                disp->scrollmode = SCROLL_YREDRAW;
1436
        }
1437
 
1438
        disp->var.activate = 0;
1439
        disp->var.red.msb_right = 0;
1440
        disp->var.green.msb_right = 0;
1441
        disp->var.blue.msb_right = 0;
1442
        disp->var.transp.msb_right = 0;
1443
        disp->var.height = -1;
1444
        disp->var.width = -1;
1445
        disp->var.vmode = FB_VMODE_NONINTERLACED;
1446
        disp->var.left_margin = disp->var.right_margin = 16;
1447
        disp->var.upper_margin = disp->var.lower_margin = 16;
1448
        disp->var.hsync_len = disp->var.vsync_len = 8;
1449
}
1450
 
1451
static int
1452
imsttfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
1453
{
1454
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
1455
        struct display *disp;
1456
        u_int oldbpp, oldxres, oldyres, oldgreenlen, oldaccel;
1457
 
1458
        disp = &fb_display[con];
1459
 
1460
        if ((var->bits_per_pixel != 8 && var->bits_per_pixel != 16
1461
            && var->bits_per_pixel != 24 && var->bits_per_pixel != 32)
1462
            || var->xres_virtual < var->xres || var->yres_virtual < var->yres
1463
            || var->nonstd
1464
            || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
1465
                return -EINVAL;
1466
 
1467
        if ((var->xres * var->yres) * (var->bits_per_pixel >> 3) > p->total_vram
1468
            || (var->xres_virtual * var->yres_virtual) * (var->bits_per_pixel >> 3) > p->total_vram)
1469
                return -EINVAL;
1470
 
1471
        if (!((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW))
1472
                return 0;
1473
 
1474
        if (!compute_imstt_regvals(p, var->xres, var->yres))
1475
                return -EINVAL;
1476
 
1477
        oldbpp = disp->var.bits_per_pixel;
1478
        oldxres = disp->var.xres;
1479
        oldyres = disp->var.yres;
1480
        oldgreenlen = disp->var.green.length;
1481
        oldaccel = disp->var.accel_flags;
1482
 
1483
        disp->var.bits_per_pixel = var->bits_per_pixel;
1484
        disp->var.xres = var->xres;
1485
        disp->var.yres = var->yres;
1486
        disp->var.xres_virtual = var->xres_virtual;
1487
        disp->var.yres_virtual = var->yres_virtual;
1488
        disp->var.green.length = var->green.length;
1489
        disp->var.accel_flags = var->accel_flags;
1490
 
1491
        set_disp(disp, p);
1492
 
1493
        if (info->changevar)
1494
                (*info->changevar)(con);
1495
 
1496
        if (con == currcon) {
1497
                if (oldgreenlen != disp->var.green.length) {
1498
                        if (disp->var.green.length == 6)
1499
                                set_565(p);
1500
                        else
1501
                                set_555(p);
1502
                }
1503
                if (oldxres != disp->var.xres || oldyres != disp->var.yres || oldbpp != disp->var.bits_per_pixel)
1504
                        set_imstt_regvals(p, disp->var.bits_per_pixel);
1505
 
1506
        }
1507
        disp->var.pixclock = 1000000 / getclkMHz(p);
1508
 
1509
        if (oldbpp != disp->var.bits_per_pixel) {
1510
                int err = fb_alloc_cmap(&disp->cmap, 0, 0);
1511
                if (err)
1512
                        return err;
1513
                do_install_cmap(con, info);
1514
        }
1515
        *var = disp->var;
1516
 
1517
        return 0;
1518
}
1519
 
1520
static int
1521
imsttfb_pan_display (struct fb_var_screeninfo *var, int con, struct fb_info *info)
1522
{
1523
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
1524
        struct display *disp = &fb_display[con];
1525
 
1526
        if (var->xoffset + disp->var.xres > disp->var.xres_virtual
1527
            || var->yoffset + disp->var.yres > disp->var.yres_virtual)
1528
                return -EINVAL;
1529
 
1530
        disp->var.xoffset = var->xoffset;
1531
        disp->var.yoffset = var->yoffset;
1532
        if (con == currcon)
1533
                set_offset(disp, p);
1534
 
1535
        return 0;
1536
}
1537
 
1538
static int
1539
imsttfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
1540
{
1541
        if (con == currcon)     /* current console? */
1542
                return fb_get_cmap(cmap, kspc, imsttfb_getcolreg, info);
1543
        else if (fb_display[con].cmap.len)      /* non default colormap? */
1544
                fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
1545
        else {
1546
                u_int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
1547
                fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
1548
        }
1549
 
1550
        return 0;
1551
}
1552
 
1553
static int
1554
imsttfb_set_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
1555
{
1556
        int err;
1557
 
1558
        if (!fb_display[con].cmap.len) {        /* no colormap allocated? */
1559
                int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
1560
                if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
1561
                        return err;
1562
        }
1563
        if (con == currcon)                     /* current console? */
1564
                return fb_set_cmap(cmap, kspc, imsttfb_setcolreg, info);
1565
        else
1566
                fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
1567
 
1568
        return 0;
1569
}
1570
 
1571
#define FBIMSTT_SETREG          0x545401
1572
#define FBIMSTT_GETREG          0x545402
1573
#define FBIMSTT_SETCMAPREG      0x545403
1574
#define FBIMSTT_GETCMAPREG      0x545404
1575
#define FBIMSTT_SETIDXREG       0x545405
1576
#define FBIMSTT_GETIDXREG       0x545406
1577
 
1578
static int
1579
imsttfb_ioctl (struct inode *inode, struct file *file, u_int cmd,
1580
               u_long arg, int con, struct fb_info *info)
1581
{
1582
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
1583
        __u8 idx[2];
1584
        __u32 reg[2];
1585
 
1586
        switch (cmd) {
1587
                case FBIMSTT_SETREG:
1588
                        if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
1589
                                return -EFAULT;
1590
                        out_le32(&p->dc_regs[reg[0]], reg[1]);
1591
                        return 0;
1592
                case FBIMSTT_GETREG:
1593
                        if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
1594
                                return -EFAULT;
1595
                        reg[1] = in_le32(&p->dc_regs[reg[0]]);
1596
                        if (copy_to_user((void *)(arg + 4), &reg[1], 4))
1597
                                return -EFAULT;
1598
                        return 0;
1599
                case FBIMSTT_SETCMAPREG:
1600
                        if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
1601
                                return -EFAULT;
1602
                        out_le32(&((u_int *)p->cmap_regs)[reg[0]], reg[1]);
1603
                        return 0;
1604
                case FBIMSTT_GETCMAPREG:
1605
                        if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
1606
                                return -EFAULT;
1607
                        reg[1] = in_le32(&((u_int *)p->cmap_regs)[reg[0]]);
1608
                        if (copy_to_user((void *)(arg + 4), &reg[1], 4))
1609
                                return -EFAULT;
1610
                        return 0;
1611
                case FBIMSTT_SETIDXREG:
1612
                        if (copy_from_user(idx, (void *)arg, 2))
1613
                                return -EFAULT;
1614
                        p->cmap_regs[PIDXHI] = 0;                eieio();
1615
                        p->cmap_regs[PIDXLO] = idx[0];           eieio();
1616
                        p->cmap_regs[PIDXDATA] = idx[1];        eieio();
1617
                        return 0;
1618
                case FBIMSTT_GETIDXREG:
1619
                        if (copy_from_user(idx, (void *)arg, 1))
1620
                                return -EFAULT;
1621
                        p->cmap_regs[PIDXHI] = 0;                eieio();
1622
                        p->cmap_regs[PIDXLO] = idx[0];           eieio();
1623
                        idx[1] = p->cmap_regs[PIDXDATA];
1624
                        if (copy_to_user((void *)(arg + 1), &idx[1], 1))
1625
                                return -EFAULT;
1626
                        return 0;
1627
                default:
1628
                        return -ENOIOCTLCMD;
1629
        }
1630
}
1631
 
1632
static struct pci_device_id imsttfb_pci_tbl[] __devinitdata = {
1633
        { PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT128,
1634
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, IBM },
1635
        { PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT3D,
1636
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, TVP },
1637
        { 0, }
1638
};
1639
 
1640
MODULE_DEVICE_TABLE(pci, imsttfb_pci_tbl);
1641
 
1642
static struct pci_driver imsttfb_pci_driver = {
1643
        name:           "imsttfb",
1644
        id_table:       imsttfb_pci_tbl,
1645
        probe:          imsttfb_probe,
1646
        remove:         __devexit_p(imsttfb_remove),
1647
};
1648
 
1649
static struct fb_ops imsttfb_ops = {
1650
        owner:          THIS_MODULE,
1651
        fb_get_fix:     imsttfb_get_fix,
1652
        fb_get_var:     imsttfb_get_var,
1653
        fb_set_var:     imsttfb_set_var,
1654
        fb_get_cmap:    imsttfb_get_cmap,
1655
        fb_set_cmap:    imsttfb_set_cmap,
1656
        fb_pan_display: imsttfb_pan_display,
1657
        fb_ioctl:       imsttfb_ioctl,
1658
};
1659
 
1660
static int
1661
imsttfbcon_switch (int con, struct fb_info *info)
1662
{
1663
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
1664
        struct display *old = &fb_display[currcon], *new = &fb_display[con];
1665
 
1666
        if (old->cmap.len)
1667
                fb_get_cmap(&old->cmap, 1, imsttfb_getcolreg, info);
1668
 
1669
        if (old->conp && old->conp->vc_sw && old->conp->vc_sw->con_cursor)
1670
                old->conp->vc_sw->con_cursor(old->conp, CM_ERASE);
1671
 
1672
        currcon = con;
1673
 
1674
        if (old->var.xres != new->var.xres
1675
            || old->var.yres != new->var.yres
1676
            || old->var.bits_per_pixel != new->var.bits_per_pixel
1677
            || old->var.green.length != new->var.green.length
1678
            || old->var.accel_flags != new->var.accel_flags) {
1679
                set_dispsw(new, p);
1680
                if (!compute_imstt_regvals(p, new->var.xres, new->var.yres))
1681
                        return -1;
1682
                if (new->var.bits_per_pixel == 16) {
1683
                        if (new->var.green.length == 6)
1684
                                set_565(p);
1685
                        else
1686
                                set_555(p);
1687
                }
1688
                set_imstt_regvals(p, new->var.bits_per_pixel);
1689
        }
1690
        set_offset(new, p);
1691
 
1692
        imsttfbcon_set_font(new, fontwidth(new), fontheight(new));
1693
 
1694
        do_install_cmap(con, info);
1695
 
1696
        return 0;
1697
}
1698
 
1699
static int
1700
imsttfbcon_updatevar (int con, struct fb_info *info)
1701
{
1702
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
1703
        struct display *disp = &fb_display[con];
1704
 
1705
        if (con != currcon)
1706
                goto out;
1707
 
1708
        if (p->ramdac == IBM)
1709
                imsttfbcon_cursor(disp, CM_ERASE, p->cursor.x, p->cursor.y);
1710
 
1711
        set_offset(disp, p);
1712
 
1713
out:
1714
        return 0;
1715
}
1716
 
1717
static void
1718
imsttfbcon_blank (int blank, struct fb_info *info)
1719
{
1720
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
1721
        __u32 ctrl;
1722
 
1723
        ctrl = in_le32(&p->dc_regs[STGCTL]);
1724
        if (blank > 0) {
1725
                switch (blank - 1) {
1726
                        case VESA_NO_BLANKING:
1727
                        case VESA_POWERDOWN:
1728
                                ctrl &= ~0x00000380;
1729
                                if (p->ramdac == IBM) {
1730
                                        p->cmap_regs[PIDXHI] = 0;        eieio();
1731
                                        p->cmap_regs[PIDXLO] = MISCTL2; eieio();
1732
                                        p->cmap_regs[PIDXDATA] = 0x55;  eieio();
1733
                                        p->cmap_regs[PIDXLO] = MISCTL1; eieio();
1734
                                        p->cmap_regs[PIDXDATA] = 0x11;  eieio();
1735
                                        p->cmap_regs[PIDXLO] = SYNCCTL; eieio();
1736
                                        p->cmap_regs[PIDXDATA] = 0x0f;  eieio();
1737
                                        p->cmap_regs[PIDXLO] = PWRMNGMT;eieio();
1738
                                        p->cmap_regs[PIDXDATA] = 0x1f;  eieio();
1739
                                        p->cmap_regs[PIDXLO] = CLKCTL;  eieio();
1740
                                        p->cmap_regs[PIDXDATA] = 0xc0;
1741
                                }
1742
                                break;
1743
                        case VESA_VSYNC_SUSPEND:
1744
                                ctrl &= ~0x00000020;
1745
                                break;
1746
                        case VESA_HSYNC_SUSPEND:
1747
                                ctrl &= ~0x00000010;
1748
                                break;
1749
                }
1750
        } else {
1751
                if (p->ramdac == IBM) {
1752
                        ctrl |= 0x000017b0;
1753
                        p->cmap_regs[PIDXHI] = 0;        eieio();
1754
                        p->cmap_regs[PIDXLO] = CLKCTL;  eieio();
1755
                        p->cmap_regs[PIDXDATA] = 0x01;  eieio();
1756
                        p->cmap_regs[PIDXLO] = PWRMNGMT;eieio();
1757
                        p->cmap_regs[PIDXDATA] = 0x00;  eieio();
1758
                        p->cmap_regs[PIDXLO] = SYNCCTL; eieio();
1759
                        p->cmap_regs[PIDXDATA] = 0x00;  eieio();
1760
                        p->cmap_regs[PIDXLO] = MISCTL1; eieio();
1761
                        p->cmap_regs[PIDXDATA] = 0x01;  eieio();
1762
                        p->cmap_regs[PIDXLO] = MISCTL2; eieio();
1763
                        p->cmap_regs[PIDXDATA] = 0x45;  eieio();
1764
                } else
1765
                        ctrl |= 0x00001780;
1766
        }
1767
        out_le32(&p->dc_regs[STGCTL], ctrl);
1768
}
1769
 
1770
static void __init
1771
init_imstt(struct fb_info_imstt *p)
1772
{
1773
        __u32 i, tmp;
1774
        __u32 *ip, *end;
1775
 
1776
        tmp = in_le32(&p->dc_regs[PRC]);
1777
        if (p->ramdac == IBM)
1778
                p->total_vram = (tmp & 0x0004) ? 0x400000 : 0x200000;
1779
        else
1780
                p->total_vram = 0x800000;
1781
 
1782
        ip = (__u32 *)p->frame_buffer;
1783
        end = (__u32 *)(p->frame_buffer + p->total_vram);
1784
        while (ip < end)
1785
                *ip++ = 0;
1786
 
1787
        /* initialize the card */
1788
        tmp = in_le32(&p->dc_regs[STGCTL]);
1789
        out_le32(&p->dc_regs[STGCTL], tmp & ~0x1);
1790
        out_le32(&p->dc_regs[SSR], 0);
1791
 
1792
        /* set default values for DAC registers */
1793
        if (p->ramdac == IBM) {
1794
                p->cmap_regs[PPMASK] = 0xff;    eieio();
1795
                p->cmap_regs[PIDXHI] = 0;        eieio();
1796
                for (i = 0; i < sizeof(ibm_initregs) / sizeof(*ibm_initregs); i++) {
1797
                        p->cmap_regs[PIDXLO] = ibm_initregs[i].addr;    eieio();
1798
                        p->cmap_regs[PIDXDATA] = ibm_initregs[i].value; eieio();
1799
                }
1800
        } else {
1801
                for (i = 0; i < sizeof(tvp_initregs) / sizeof(*tvp_initregs); i++) {
1802
                        p->cmap_regs[TVPADDRW] = tvp_initregs[i].addr;  eieio();
1803
                        p->cmap_regs[TVPIDATA] = tvp_initregs[i].value; eieio();
1804
                }
1805
        }
1806
 
1807
#ifdef CONFIG_ALL_PPC
1808
        {
1809
                int vmode = init_vmode, cmode = init_cmode;
1810
 
1811
#ifdef CONFIG_NVRAM
1812
                /* Attempt to read vmode/cmode from NVRAM */
1813
                if (vmode == VMODE_NVRAM)
1814
                        vmode = nvram_read_byte(NV_VMODE);
1815
                if (cmode == CMODE_NVRAM)
1816
                        cmode = nvram_read_byte(NV_CMODE);
1817
#endif
1818
                /* If we didn't get something from NVRAM, pick a
1819
                 * sane default.
1820
                 */
1821
                if (vmode <= 0 || vmode > VMODE_MAX)
1822
                        vmode = VMODE_640_480_67;
1823
                if (cmode < CMODE_8 || cmode > CMODE_32)
1824
                        cmode = CMODE_8;
1825
 
1826
                if (mac_vmode_to_var(vmode, cmode, &p->disp.var)) {
1827
                        p->disp.var.xres = p->disp.var.xres_virtual = INIT_XRES;
1828
                        p->disp.var.yres = p->disp.var.yres_virtual = INIT_YRES;
1829
                        p->disp.var.bits_per_pixel = INIT_BPP;
1830
                }
1831
        }
1832
#else
1833
        p->disp.var.xres = p->disp.var.xres_virtual = INIT_XRES;
1834
        p->disp.var.yres = p->disp.var.yres_virtual = INIT_YRES;
1835
        p->disp.var.bits_per_pixel = INIT_BPP;
1836
#endif
1837
 
1838
        if ((p->disp.var.xres * p->disp.var.yres) * (p->disp.var.bits_per_pixel >> 3) > p->total_vram
1839
            || !(compute_imstt_regvals(p, p->disp.var.xres, p->disp.var.yres))) {
1840
                printk("imsttfb: %ux%ux%u not supported\n", p->disp.var.xres, p->disp.var.yres, p->disp.var.bits_per_pixel);
1841
                kfree(p);
1842
                return;
1843
        }
1844
 
1845
        sprintf(p->fix.id, "IMS TT (%s)", p->ramdac == IBM ? "IBM" : "TVP");
1846
        p->fix.smem_start = p->frame_buffer_phys;
1847
        p->fix.smem_len = p->total_vram;
1848
        p->fix.mmio_start = p->dc_regs_phys;
1849
        p->fix.mmio_len = 0x1000;
1850
        p->fix.accel = FB_ACCEL_IMS_TWINTURBO;
1851
        p->fix.type = FB_TYPE_PACKED_PIXELS;
1852
        p->fix.visual = p->disp.var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
1853
                                                        : FB_VISUAL_DIRECTCOLOR;
1854
        p->fix.line_length = p->disp.var.xres * (p->disp.var.bits_per_pixel >> 3);
1855
        p->fix.xpanstep = 8;
1856
        p->fix.ypanstep = 1;
1857
        p->fix.ywrapstep = 0;
1858
 
1859
        p->disp.var.accel_flags = noaccel ? 0 : FB_ACCELF_TEXT;
1860
        set_disp(&p->disp, p);
1861
 
1862
        if (!noaccel && p->ramdac == IBM)
1863
                imstt_cursor_init(p);
1864
        if (p->disp.var.green.length == 6)
1865
                set_565(p);
1866
        else
1867
                set_555(p);
1868
        set_imstt_regvals(p, p->disp.var.bits_per_pixel);
1869
 
1870
        p->disp.var.pixclock = 1000000 / getclkMHz(p);
1871
 
1872
        strcpy(p->info.modename, p->fix.id);
1873
        strcpy(p->info.fontname, fontname);
1874
        p->info.node = -1;
1875
        p->info.fbops = &imsttfb_ops;
1876
        p->info.disp = &p->disp;
1877
        p->info.changevar = 0;
1878
        p->info.switch_con = &imsttfbcon_switch;
1879
        p->info.updatevar = &imsttfbcon_updatevar;
1880
        p->info.blank = &imsttfbcon_blank;
1881
        p->info.flags = FBINFO_FLAG_DEFAULT;
1882
 
1883
        for (i = 0; i < 16; i++) {
1884
                u_int j = color_table[i];
1885
                p->palette[i].red = default_red[j];
1886
                p->palette[i].green = default_grn[j];
1887
                p->palette[i].blue = default_blu[j];
1888
        }
1889
 
1890
        if (register_framebuffer(&p->info) < 0) {
1891
                kfree(p);
1892
                return;
1893
        }
1894
 
1895
        i = GET_FB_IDX(p->info.node);
1896
        tmp = (in_le32(&p->dc_regs[SSTATUS]) & 0x0f00) >> 8;
1897
        printk("fb%u: %s frame buffer; %uMB vram; chip version %u\n",
1898
                i, p->fix.id, p->total_vram >> 20, tmp);
1899
 
1900
#ifdef CONFIG_FB_COMPAT_XPMAC
1901
        strncpy(display_info.name, "IMS,tt128mb", sizeof(display_info.name));
1902
        display_info.fb_address = p->frame_buffer_phys;
1903
        display_info.cmap_adr_address = p->cmap_regs_phys + PADDRW;
1904
        display_info.cmap_data_address = p->cmap_regs_phys + PDATA;
1905
        display_info.disp_reg_address = p->dc_regs_phys;
1906
        if (!console_fb_info)
1907
                console_fb_info = &p->info;
1908
#endif /* CONFIG_FB_COMPAT_XPMAC */
1909
}
1910
 
1911
static int __devinit
1912
imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1913
{
1914
        struct fb_info_imstt *p;
1915
        unsigned long addr, size;
1916
 
1917
        addr = pci_resource_start (pdev, 0);
1918
        size = pci_resource_len (pdev, 0);
1919
 
1920
        p = kmalloc(sizeof(struct fb_info_imstt), GFP_KERNEL);
1921
 
1922
        if (!p) {
1923
                printk(KERN_ERR "imsttfb: Can't allocate memory\n");
1924
                return -ENOMEM;
1925
        }
1926
 
1927
        memset(p, 0, sizeof(struct fb_info_imstt));
1928
 
1929
        if (!request_mem_region(addr, size, "imsttfb")) {
1930
                printk(KERN_ERR "imsttfb: Can't reserve memory region\n");
1931
                kfree(p);
1932
                return -ENODEV;
1933
        }
1934
 
1935
        switch (pdev->device) {
1936
                case PCI_DEVICE_ID_IMS_TT128: /* IMS,tt128mbA */
1937
                        p->ramdac = IBM;
1938
                        break;
1939
                case PCI_DEVICE_ID_IMS_TT3D:  /* IMS,tt3d */
1940
                        p->ramdac = TVP;
1941
                        break;
1942
                default:
1943
                        printk(KERN_INFO "imsttfb: Device 0x%lx unknown, "
1944
                                         "contact maintainer.\n", pdev->device);
1945
                        return -ENODEV;
1946
        }
1947
 
1948
        p->frame_buffer_phys = addr;
1949
        p->board_size = size;
1950
        p->frame_buffer = (__u8 *)ioremap(addr, p->ramdac == IBM ? 0x400000 : 0x800000);
1951
        p->dc_regs_phys = addr + 0x800000;
1952
        p->dc_regs = (__u32 *)ioremap(addr + 0x800000, 0x1000);
1953
        p->cmap_regs_phys = addr + 0x840000;
1954
        p->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
1955
 
1956
        init_imstt(p);
1957
 
1958
        pci_set_drvdata(pdev, p);
1959
 
1960
        return 0;
1961
}
1962
 
1963
static void __devexit
1964
imsttfb_remove(struct pci_dev *pdev)
1965
{
1966
        struct fb_info_imstt *p = pci_get_drvdata(pdev);
1967
 
1968
        unregister_framebuffer(&p->info);
1969
        iounmap(p->cmap_regs);
1970
        iounmap(p->dc_regs);
1971
        iounmap(p->frame_buffer);
1972
        release_mem_region(p->frame_buffer_phys, p->board_size);
1973
        kfree(p);
1974
}
1975
 
1976
#ifndef MODULE
1977
int __init
1978
imsttfb_setup(char *options)
1979
{
1980
        char *this_opt;
1981
 
1982
        if (!options || !*options)
1983
                return 0;
1984
 
1985
        while ((this_opt = strsep(&options, ",")) != NULL) {
1986
                if (!strncmp(this_opt, "font:", 5)) {
1987
                        char *p;
1988
                        int i;
1989
 
1990
                        p = this_opt + 5;
1991
                        for (i = 0; i < sizeof(fontname) - 1; i++)
1992
                                if (!*p || *p == ' ' || *p == ',')
1993
                                        break;
1994
                        memcpy(fontname, this_opt + 5, i);
1995
                        fontname[i] = 0;
1996
                } else if (!strncmp(this_opt, "noblink", 7)) {
1997
                        curblink = 0;
1998
                } else if (!strncmp(this_opt, "noaccel", 7)) {
1999
                        noaccel = 1;
2000
                } else if (!strncmp(this_opt, "inverse", 7)) {
2001
                        inverse = 1;
2002
                        fb_invert_cmaps();
2003
                }
2004
#if defined(CONFIG_PPC)
2005
                else if (!strncmp(this_opt, "vmode:", 6)) {
2006
                        int vmode = simple_strtoul(this_opt+6, NULL, 0);
2007
                        if (vmode > 0 && vmode <= VMODE_MAX)
2008
                                init_vmode = vmode;
2009
                } else if (!strncmp(this_opt, "cmode:", 6)) {
2010
                        int cmode = simple_strtoul(this_opt+6, NULL, 0);
2011
                        switch (cmode) {
2012
                                case CMODE_8:
2013
                                case 8:
2014
                                        init_cmode = CMODE_8;
2015
                                        break;
2016
                                case CMODE_16:
2017
                                case 15:
2018
                                case 16:
2019
                                        init_cmode = CMODE_16;
2020
                                        break;
2021
                                case CMODE_32:
2022
                                case 24:
2023
                                case 32:
2024
                                        init_cmode = CMODE_32;
2025
                                        break;
2026
                        }
2027
                }
2028
#endif
2029
        }
2030
        return 0;
2031
}
2032
 
2033
#endif /* MODULE */
2034
 
2035
int __init imsttfb_init(void)
2036
{
2037
        return pci_module_init(&imsttfb_pci_driver);
2038
}
2039
 
2040
static void __exit imsttfb_exit(void)
2041
{
2042
        pci_unregister_driver(&imsttfb_pci_driver);
2043
}
2044
 
2045
#ifdef MODULE
2046
MODULE_LICENSE("GPL");
2047
module_init(imsttfb_init);
2048
#endif
2049
module_exit(imsttfb_exit);
2050
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.