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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [video/] [stifb.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * linux/drivers/video/stifb.c -
3
 * Low level Frame buffer driver for HP workstations with
4
 * STI (standard text interface) video firmware.
5
 *
6
 * Copyright (C) 2001-2006 Helge Deller <deller@gmx.de>
7
 * Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
8
 *
9
 * Based on:
10
 * - linux/drivers/video/artistfb.c -- Artist frame buffer driver
11
 *      Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
12
 *   - based on skeletonfb, which was
13
 *      Created 28 Dec 1997 by Geert Uytterhoeven
14
 * - HP Xhp cfb-based X11 window driver for XFree86
15
 *      (c)Copyright 1992 Hewlett-Packard Co.
16
 *
17
 *
18
 *  The following graphics display devices (NGLE family) are supported by this driver:
19
 *
20
 *  HPA4070A    known as "HCRX", a 1280x1024 color device with 8 planes
21
 *  HPA4071A    known as "HCRX24", a 1280x1024 color device with 24 planes,
22
 *              optionally available with a hardware accelerator as HPA4071A_Z
23
 *  HPA1659A    known as "CRX", a 1280x1024 color device with 8 planes
24
 *  HPA1439A    known as "CRX24", a 1280x1024 color device with 24 planes,
25
 *              optionally available with a hardware accelerator.
26
 *  HPA1924A    known as "GRX", a 1280x1024 grayscale device with 8 planes
27
 *  HPA2269A    known as "Dual CRX", a 1280x1024 color device with 8 planes,
28
 *              implements support for two displays on a single graphics card.
29
 *  HP710C      internal graphics support optionally available on the HP9000s710 SPU,
30
 *              supports 1280x1024 color displays with 8 planes.
31
 *  HP710G      same as HP710C, 1280x1024 grayscale only
32
 *  HP710L      same as HP710C, 1024x768 color only
33
 *  HP712       internal graphics support on HP9000s712 SPU, supports 640x480,
34
 *              1024x768 or 1280x1024 color displays on 8 planes (Artist)
35
 *
36
 * This file is subject to the terms and conditions of the GNU General Public
37
 * License.  See the file COPYING in the main directory of this archive
38
 * for more details.
39
 */
40
 
41
/* TODO:
42
 *      - 1bpp mode is completely untested
43
 *      - add support for h/w acceleration
44
 *      - add hardware cursor
45
 *      - automatically disable double buffering (e.g. on RDI precisionbook laptop)
46
 */
47
 
48
 
49
/* on supported graphic devices you may:
50
 * #define FALLBACK_TO_1BPP to fall back to 1 bpp, or
51
 * #undef  FALLBACK_TO_1BPP to reject support for unsupported cards */
52
#undef FALLBACK_TO_1BPP
53
 
54
#undef DEBUG_STIFB_REGS         /* debug sti register accesses */
55
 
56
 
57
#include <linux/module.h>
58
#include <linux/kernel.h>
59
#include <linux/errno.h>
60
#include <linux/string.h>
61
#include <linux/mm.h>
62
#include <linux/slab.h>
63
#include <linux/delay.h>
64
#include <linux/fb.h>
65
#include <linux/init.h>
66
#include <linux/ioport.h>
67
 
68
#include <asm/grfioctl.h>       /* for HP-UX compatibility */
69
#include <asm/uaccess.h>
70
 
71
#include "sticore.h"
72
 
73
/* REGION_BASE(fb_info, index) returns the virtual address for region <index> */
74
#define REGION_BASE(fb_info, index) \
75
        F_EXTEND(fb_info->sti->glob_cfg->region_ptrs[index])
76
 
77
#define NGLEDEVDEPROM_CRT_REGION 1
78
 
79
#define NR_PALETTE 256
80
 
81
typedef struct {
82
        __s32   video_config_reg;
83
        __s32   misc_video_start;
84
        __s32   horiz_timing_fmt;
85
        __s32   serr_timing_fmt;
86
        __s32   vert_timing_fmt;
87
        __s32   horiz_state;
88
        __s32   vert_state;
89
        __s32   vtg_state_elements;
90
        __s32   pipeline_delay;
91
        __s32   misc_video_end;
92
} video_setup_t;
93
 
94
typedef struct {
95
        __s16   sizeof_ngle_data;
96
        __s16   x_size_visible;     /* visible screen dim in pixels  */
97
        __s16   y_size_visible;
98
        __s16   pad2[15];
99
        __s16   cursor_pipeline_delay;
100
        __s16   video_interleaves;
101
        __s32   pad3[11];
102
} ngle_rom_t;
103
 
104
struct stifb_info {
105
        struct fb_info info;
106
        unsigned int id;
107
        ngle_rom_t ngle_rom;
108
        struct sti_struct *sti;
109
        int deviceSpecificConfig;
110
        u32 pseudo_palette[16];
111
};
112
 
113
static int __initdata stifb_bpp_pref[MAX_STI_ROMS];
114
 
115
/* ------------------- chipset specific functions -------------------------- */
116
 
117
/* offsets to graphic-chip internal registers */
118
 
119
#define REG_1           0x000118
120
#define REG_2           0x000480
121
#define REG_3           0x0004a0
122
#define REG_4           0x000600
123
#define REG_6           0x000800
124
#define REG_8           0x000820
125
#define REG_9           0x000a04
126
#define REG_10          0x018000
127
#define REG_11          0x018004
128
#define REG_12          0x01800c
129
#define REG_13          0x018018
130
#define REG_14          0x01801c
131
#define REG_15          0x200000
132
#define REG_15b0        0x200000
133
#define REG_16b1        0x200005
134
#define REG_16b3        0x200007
135
#define REG_21          0x200218
136
#define REG_22          0x0005a0
137
#define REG_23          0x0005c0
138
#define REG_26          0x200118
139
#define REG_27          0x200308
140
#define REG_32          0x21003c
141
#define REG_33          0x210040
142
#define REG_34          0x200008
143
#define REG_35          0x018010
144
#define REG_38          0x210020
145
#define REG_39          0x210120
146
#define REG_40          0x210130
147
#define REG_42          0x210028
148
#define REG_43          0x21002c
149
#define REG_44          0x210030
150
#define REG_45          0x210034
151
 
152
#define READ_BYTE(fb,reg)               gsc_readb((fb)->info.fix.mmio_start + (reg))
153
#define READ_WORD(fb,reg)               gsc_readl((fb)->info.fix.mmio_start + (reg))
154
 
155
 
156
#ifndef DEBUG_STIFB_REGS
157
# define  DEBUG_OFF()
158
# define  DEBUG_ON()
159
# define WRITE_BYTE(value,fb,reg)       gsc_writeb((value),(fb)->info.fix.mmio_start + (reg))
160
# define WRITE_WORD(value,fb,reg)       gsc_writel((value),(fb)->info.fix.mmio_start + (reg))
161
#else
162
  static int debug_on = 1;
163
# define  DEBUG_OFF() debug_on=0
164
# define  DEBUG_ON()  debug_on=1
165
# define WRITE_BYTE(value,fb,reg)       do { if (debug_on) \
166
                                                printk(KERN_DEBUG "%30s: WRITE_BYTE(0x%06x) = 0x%02x (old=0x%02x)\n", \
167
                                                        __FUNCTION__, reg, value, READ_BYTE(fb,reg));             \
168
                                        gsc_writeb((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
169
# define WRITE_WORD(value,fb,reg)       do { if (debug_on) \
170
                                                printk(KERN_DEBUG "%30s: WRITE_WORD(0x%06x) = 0x%08x (old=0x%08x)\n", \
171
                                                        __FUNCTION__, reg, value, READ_WORD(fb,reg));             \
172
                                        gsc_writel((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
173
#endif /* DEBUG_STIFB_REGS */
174
 
175
 
176
#define ENABLE  1       /* for enabling/disabling screen */     
177
#define DISABLE 0
178
 
179
#define NGLE_LOCK(fb_info)      do { } while (0) 
180
#define NGLE_UNLOCK(fb_info)    do { } while (0)
181
 
182
static void
183
SETUP_HW(struct stifb_info *fb)
184
{
185
        char stat;
186
 
187
        do {
188
                stat = READ_BYTE(fb, REG_15b0);
189
                if (!stat)
190
                        stat = READ_BYTE(fb, REG_15b0);
191
        } while (stat);
192
}
193
 
194
 
195
static void
196
SETUP_FB(struct stifb_info *fb)
197
{
198
        unsigned int reg10_value = 0;
199
 
200
        SETUP_HW(fb);
201
        switch (fb->id)
202
        {
203
                case CRT_ID_VISUALIZE_EG:
204
                case S9000_ID_ARTIST:
205
                case S9000_ID_A1659A:
206
                        reg10_value = 0x13601000;
207
                        break;
208
                case S9000_ID_A1439A:
209
                        if (fb->info.var.bits_per_pixel == 32)
210
                                reg10_value = 0xBBA0A000;
211
                        else
212
                                reg10_value = 0x13601000;
213
                        break;
214
                case S9000_ID_HCRX:
215
                        if (fb->info.var.bits_per_pixel == 32)
216
                                reg10_value = 0xBBA0A000;
217
                        else
218
                                reg10_value = 0x13602000;
219
                        break;
220
                case S9000_ID_TIMBER:
221
                case CRX24_OVERLAY_PLANES:
222
                        reg10_value = 0x13602000;
223
                        break;
224
        }
225
        if (reg10_value)
226
                WRITE_WORD(reg10_value, fb, REG_10);
227
        WRITE_WORD(0x83000300, fb, REG_14);
228
        SETUP_HW(fb);
229
        WRITE_BYTE(1, fb, REG_16b1);
230
}
231
 
232
static void
233
START_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb)
234
{
235
        SETUP_HW(fb);
236
        WRITE_WORD(0xBBE0F000, fb, REG_10);
237
        WRITE_WORD(0x03000300, fb, REG_14);
238
        WRITE_WORD(~0, fb, REG_13);
239
}
240
 
241
static void
242
WRITE_IMAGE_COLOR(struct stifb_info *fb, int index, int color)
243
{
244
        SETUP_HW(fb);
245
        WRITE_WORD(((0x100+index)<<2), fb, REG_3);
246
        WRITE_WORD(color, fb, REG_4);
247
}
248
 
249
static void
250
FINISH_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb)
251
{
252
        WRITE_WORD(0x400, fb, REG_2);
253
        if (fb->info.var.bits_per_pixel == 32) {
254
                WRITE_WORD(0x83000100, fb, REG_1);
255
        } else {
256
                if (fb->id == S9000_ID_ARTIST || fb->id == CRT_ID_VISUALIZE_EG)
257
                        WRITE_WORD(0x80000100, fb, REG_26);
258
                else
259
                        WRITE_WORD(0x80000100, fb, REG_1);
260
        }
261
        SETUP_FB(fb);
262
}
263
 
264
static void
265
SETUP_RAMDAC(struct stifb_info *fb)
266
{
267
        SETUP_HW(fb);
268
        WRITE_WORD(0x04000000, fb, 0x1020);
269
        WRITE_WORD(0xff000000, fb, 0x1028);
270
}
271
 
272
static void
273
CRX24_SETUP_RAMDAC(struct stifb_info *fb)
274
{
275
        SETUP_HW(fb);
276
        WRITE_WORD(0x04000000, fb, 0x1000);
277
        WRITE_WORD(0x02000000, fb, 0x1004);
278
        WRITE_WORD(0xff000000, fb, 0x1008);
279
        WRITE_WORD(0x05000000, fb, 0x1000);
280
        WRITE_WORD(0x02000000, fb, 0x1004);
281
        WRITE_WORD(0x03000000, fb, 0x1008);
282
}
283
 
284
#if 0
285
static void
286
HCRX_SETUP_RAMDAC(struct stifb_info *fb)
287
{
288
        WRITE_WORD(0xffffffff, fb, REG_32);
289
}
290
#endif
291
 
292
static void
293
CRX24_SET_OVLY_MASK(struct stifb_info *fb)
294
{
295
        SETUP_HW(fb);
296
        WRITE_WORD(0x13a02000, fb, REG_11);
297
        WRITE_WORD(0x03000300, fb, REG_14);
298
        WRITE_WORD(0x000017f0, fb, REG_3);
299
        WRITE_WORD(0xffffffff, fb, REG_13);
300
        WRITE_WORD(0xffffffff, fb, REG_22);
301
        WRITE_WORD(0x00000000, fb, REG_23);
302
}
303
 
304
static void
305
ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
306
{
307
        unsigned int value = enable ? 0x43000000 : 0x03000000;
308
        SETUP_HW(fb);
309
        WRITE_WORD(0x06000000,  fb, 0x1030);
310
        WRITE_WORD(value,       fb, 0x1038);
311
}
312
 
313
static void
314
CRX24_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
315
{
316
        unsigned int value = enable ? 0x10000000 : 0x30000000;
317
        SETUP_HW(fb);
318
        WRITE_WORD(0x01000000,  fb, 0x1000);
319
        WRITE_WORD(0x02000000,  fb, 0x1004);
320
        WRITE_WORD(value,       fb, 0x1008);
321
}
322
 
323
static void
324
ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
325
{
326
        u32 DregsMiscVideo = REG_21;
327
        u32 DregsMiscCtl = REG_27;
328
 
329
        SETUP_HW(fb);
330
        if (enable) {
331
          WRITE_WORD(READ_WORD(fb, DregsMiscVideo) | 0x0A000000, fb, DregsMiscVideo);
332
          WRITE_WORD(READ_WORD(fb, DregsMiscCtl)   | 0x00800000, fb, DregsMiscCtl);
333
        } else {
334
          WRITE_WORD(READ_WORD(fb, DregsMiscVideo) & ~0x0A000000, fb, DregsMiscVideo);
335
          WRITE_WORD(READ_WORD(fb, DregsMiscCtl)   & ~0x00800000, fb, DregsMiscCtl);
336
        }
337
}
338
 
339
#define GET_ROMTABLE_INDEX(fb) \
340
        (READ_BYTE(fb, REG_16b3) - 1)
341
 
342
#define HYPER_CONFIG_PLANES_24 0x00000100
343
 
344
#define IS_24_DEVICE(fb) \
345
        (fb->deviceSpecificConfig & HYPER_CONFIG_PLANES_24)
346
 
347
#define IS_888_DEVICE(fb) \
348
        (!(IS_24_DEVICE(fb)))
349
 
350
#define GET_FIFO_SLOTS(fb, cnt, numslots)       \
351
{       while (cnt < numslots)                  \
352
                cnt = READ_WORD(fb, REG_34);    \
353
        cnt -= numslots;                        \
354
}
355
 
356
#define     IndexedDcd  0        /* Pixel data is indexed (pseudo) color */
357
#define     Otc04       2       /* Pixels in each longword transfer (4) */
358
#define     Otc32       5       /* Pixels in each longword transfer (32) */
359
#define     Ots08       3       /* Each pixel is size (8)d transfer (1) */
360
#define     OtsIndirect 6       /* Each bit goes through FG/BG color(8) */
361
#define     AddrLong    5       /* FB address is Long aligned (pixel) */
362
#define     BINovly     0x2     /* 8 bit overlay */
363
#define     BINapp0I    0x0     /* Application Buffer 0, Indexed */
364
#define     BINapp1I    0x1     /* Application Buffer 1, Indexed */
365
#define     BINapp0F8   0xa     /* Application Buffer 0, Fractional 8-8-8 */
366
#define     BINattr     0xd     /* Attribute Bitmap */
367
#define     RopSrc      0x3
368
#define     BitmapExtent08  3   /* Each write hits ( 8) bits in depth */
369
#define     BitmapExtent32  5   /* Each write hits (32) bits in depth */
370
#define     DataDynamic     0   /* Data register reloaded by direct access */
371
#define     MaskDynamic     1   /* Mask register reloaded by direct access */
372
#define     MaskOtc         0   /* Mask contains Object Count valid bits */
373
 
374
#define MaskAddrOffset(offset) (offset)
375
#define StaticReg(en) (en)
376
#define BGx(en) (en)
377
#define FGx(en) (en)
378
 
379
#define BAJustPoint(offset) (offset)
380
#define BAIndexBase(base) (base)
381
#define BA(F,C,S,A,J,B,I) \
382
        (((F)<<31)|((C)<<27)|((S)<<24)|((A)<<21)|((J)<<16)|((B)<<12)|(I))
383
 
384
#define IBOvals(R,M,X,S,D,L,B,F) \
385
        (((R)<<8)|((M)<<16)|((X)<<24)|((S)<<29)|((D)<<28)|((L)<<31)|((B)<<1)|(F))
386
 
387
#define NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, val) \
388
        WRITE_WORD(val, fb, REG_14)
389
 
390
#define NGLE_QUICK_SET_DST_BM_ACCESS(fb, val) \
391
        WRITE_WORD(val, fb, REG_11)
392
 
393
#define NGLE_QUICK_SET_CTL_PLN_REG(fb, val) \
394
        WRITE_WORD(val, fb, REG_12)
395
 
396
#define NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, plnmsk32) \
397
        WRITE_WORD(plnmsk32, fb, REG_13)
398
 
399
#define NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, fg32) \
400
        WRITE_WORD(fg32, fb, REG_35)
401
 
402
#define NGLE_SET_TRANSFERDATA(fb, val) \
403
        WRITE_WORD(val, fb, REG_8)
404
 
405
#define NGLE_SET_DSTXY(fb, val) \
406
        WRITE_WORD(val, fb, REG_6)
407
 
408
#define NGLE_LONG_FB_ADDRESS(fbaddrbase, x, y) (                \
409
        (u32) (fbaddrbase) +                                    \
410
            (   (unsigned int)  ( (y) << 13      ) |            \
411
                (unsigned int)  ( (x) << 2       )      )       \
412
        )
413
 
414
#define NGLE_BINC_SET_DSTADDR(fb, addr) \
415
        WRITE_WORD(addr, fb, REG_3)
416
 
417
#define NGLE_BINC_SET_SRCADDR(fb, addr) \
418
        WRITE_WORD(addr, fb, REG_2)
419
 
420
#define NGLE_BINC_SET_DSTMASK(fb, mask) \
421
        WRITE_WORD(mask, fb, REG_22)
422
 
423
#define NGLE_BINC_WRITE32(fb, data32) \
424
        WRITE_WORD(data32, fb, REG_23)
425
 
426
#define START_COLORMAPLOAD(fb, cmapBltCtlData32) \
427
        WRITE_WORD((cmapBltCtlData32), fb, REG_38)
428
 
429
#define SET_LENXY_START_RECFILL(fb, lenxy) \
430
        WRITE_WORD(lenxy, fb, REG_9)
431
 
432
static void
433
HYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
434
{
435
        u32 DregsHypMiscVideo = REG_33;
436
        unsigned int value;
437
        SETUP_HW(fb);
438
        value = READ_WORD(fb, DregsHypMiscVideo);
439
        if (enable)
440
                value |= 0x0A000000;
441
        else
442
                value &= ~0x0A000000;
443
        WRITE_WORD(value, fb, DregsHypMiscVideo);
444
}
445
 
446
 
447
/* BufferNumbers used by SETUP_ATTR_ACCESS() */
448
#define BUFF0_CMAP0     0x00001e02
449
#define BUFF1_CMAP0     0x02001e02
450
#define BUFF1_CMAP3     0x0c001e02
451
#define ARTIST_CMAP0    0x00000102
452
#define HYPER_CMAP8     0x00000100
453
#define HYPER_CMAP24    0x00000800
454
 
455
static void
456
SETUP_ATTR_ACCESS(struct stifb_info *fb, unsigned BufferNumber)
457
{
458
        SETUP_HW(fb);
459
        WRITE_WORD(0x2EA0D000, fb, REG_11);
460
        WRITE_WORD(0x23000302, fb, REG_14);
461
        WRITE_WORD(BufferNumber, fb, REG_12);
462
        WRITE_WORD(0xffffffff, fb, REG_8);
463
}
464
 
465
static void
466
SET_ATTR_SIZE(struct stifb_info *fb, int width, int height)
467
{
468
        /* REG_6 seems to have special values when run on a
469
           RDI precisionbook parisc laptop (INTERNAL_EG_DX1024 or
470
           INTERNAL_EG_X1024).  The values are:
471
                0x2f0: internal (LCD) & external display enabled
472
                0x2a0: external display only
473
                0x000: zero on standard artist graphic cards
474
        */
475
        WRITE_WORD(0x00000000, fb, REG_6);
476
        WRITE_WORD((width<<16) | height, fb, REG_9);
477
        WRITE_WORD(0x05000000, fb, REG_6);
478
        WRITE_WORD(0x00040001, fb, REG_9);
479
}
480
 
481
static void
482
FINISH_ATTR_ACCESS(struct stifb_info *fb)
483
{
484
        SETUP_HW(fb);
485
        WRITE_WORD(0x00000000, fb, REG_12);
486
}
487
 
488
static void
489
elkSetupPlanes(struct stifb_info *fb)
490
{
491
        SETUP_RAMDAC(fb);
492
        SETUP_FB(fb);
493
}
494
 
495
static void
496
ngleSetupAttrPlanes(struct stifb_info *fb, int BufferNumber)
497
{
498
        SETUP_ATTR_ACCESS(fb, BufferNumber);
499
        SET_ATTR_SIZE(fb, fb->info.var.xres, fb->info.var.yres);
500
        FINISH_ATTR_ACCESS(fb);
501
        SETUP_FB(fb);
502
}
503
 
504
 
505
static void
506
rattlerSetupPlanes(struct stifb_info *fb)
507
{
508
        CRX24_SETUP_RAMDAC(fb);
509
 
510
        /* replacement for: SETUP_FB(fb, CRX24_OVERLAY_PLANES); */
511
        WRITE_WORD(0x83000300, fb, REG_14);
512
        SETUP_HW(fb);
513
        WRITE_BYTE(1, fb, REG_16b1);
514
 
515
        fb_memset((void*)fb->info.fix.smem_start, 0xff,
516
                fb->info.var.yres*fb->info.fix.line_length);
517
 
518
        CRX24_SET_OVLY_MASK(fb);
519
        SETUP_FB(fb);
520
}
521
 
522
 
523
#define HYPER_CMAP_TYPE                         0
524
#define NGLE_CMAP_INDEXED0_TYPE                 0
525
#define NGLE_CMAP_OVERLAY_TYPE                  3
526
 
527
/* typedef of LUT (Colormap) BLT Control Register */
528
typedef union   /* Note assumption that fields are packed left-to-right */
529
{       u32 all;
530
        struct
531
        {
532
                unsigned enable              :  1;
533
                unsigned waitBlank           :  1;
534
                unsigned reserved1           :  4;
535
                unsigned lutOffset           : 10;   /* Within destination LUT */
536
                unsigned lutType             :  2;   /* Cursor, image, overlay */
537
                unsigned reserved2           :  4;
538
                unsigned length              : 10;
539
        } fields;
540
} NgleLutBltCtl;
541
 
542
 
543
#if 0
544
static NgleLutBltCtl
545
setNgleLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length)
546
{
547
        NgleLutBltCtl lutBltCtl;
548
 
549
        /* set enable, zero reserved fields */
550
        lutBltCtl.all           = 0x80000000;
551
        lutBltCtl.fields.length = length;
552
 
553
        switch (fb->id)
554
        {
555
        case S9000_ID_A1439A:           /* CRX24 */
556
                if (fb->var.bits_per_pixel == 8) {
557
                        lutBltCtl.fields.lutType = NGLE_CMAP_OVERLAY_TYPE;
558
                        lutBltCtl.fields.lutOffset = 0;
559
                } else {
560
                        lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
561
                        lutBltCtl.fields.lutOffset = 0 * 256;
562
                }
563
                break;
564
 
565
        case S9000_ID_ARTIST:
566
                lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
567
                lutBltCtl.fields.lutOffset = 0 * 256;
568
                break;
569
 
570
        default:
571
                lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE;
572
                lutBltCtl.fields.lutOffset = 0;
573
                break;
574
        }
575
 
576
        /* Offset points to start of LUT.  Adjust for within LUT */
577
        lutBltCtl.fields.lutOffset += offsetWithinLut;
578
 
579
        return lutBltCtl;
580
}
581
#endif
582
 
583
static NgleLutBltCtl
584
setHyperLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length)
585
{
586
        NgleLutBltCtl lutBltCtl;
587
 
588
        /* set enable, zero reserved fields */
589
        lutBltCtl.all = 0x80000000;
590
 
591
        lutBltCtl.fields.length = length;
592
        lutBltCtl.fields.lutType = HYPER_CMAP_TYPE;
593
 
594
        /* Expect lutIndex to be 0 or 1 for image cmaps, 2 or 3 for overlay cmaps */
595
        if (fb->info.var.bits_per_pixel == 8)
596
                lutBltCtl.fields.lutOffset = 2 * 256;
597
        else
598
                lutBltCtl.fields.lutOffset = 0 * 256;
599
 
600
        /* Offset points to start of LUT.  Adjust for within LUT */
601
        lutBltCtl.fields.lutOffset += offsetWithinLut;
602
 
603
        return lutBltCtl;
604
}
605
 
606
 
607
static void hyperUndoITE(struct stifb_info *fb)
608
{
609
        int nFreeFifoSlots = 0;
610
        u32 fbAddr;
611
 
612
        NGLE_LOCK(fb);
613
 
614
        GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1);
615
        WRITE_WORD(0xffffffff, fb, REG_32);
616
 
617
        /* Write overlay transparency mask so only entry 255 is transparent */
618
 
619
        /* Hardware setup for full-depth write to "magic" location */
620
        GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7);
621
        NGLE_QUICK_SET_DST_BM_ACCESS(fb,
622
                BA(IndexedDcd, Otc04, Ots08, AddrLong,
623
                BAJustPoint(0), BINovly, BAIndexBase(0)));
624
        NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
625
                IBOvals(RopSrc, MaskAddrOffset(0),
626
                BitmapExtent08, StaticReg(0),
627
                DataDynamic, MaskOtc, BGx(0), FGx(0)));
628
 
629
        /* Now prepare to write to the "magic" location */
630
        fbAddr = NGLE_LONG_FB_ADDRESS(0, 1532, 0);
631
        NGLE_BINC_SET_DSTADDR(fb, fbAddr);
632
        NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffff);
633
        NGLE_BINC_SET_DSTMASK(fb, 0xffffffff);
634
 
635
        /* Finally, write a zero to clear the mask */
636
        NGLE_BINC_WRITE32(fb, 0);
637
 
638
        NGLE_UNLOCK(fb);
639
}
640
 
641
static void
642
ngleDepth8_ClearImagePlanes(struct stifb_info *fb)
643
{
644
        /* FIXME! */
645
}
646
 
647
static void
648
ngleDepth24_ClearImagePlanes(struct stifb_info *fb)
649
{
650
        /* FIXME! */
651
}
652
 
653
static void
654
ngleResetAttrPlanes(struct stifb_info *fb, unsigned int ctlPlaneReg)
655
{
656
        int nFreeFifoSlots = 0;
657
        u32 packed_dst;
658
        u32 packed_len;
659
 
660
        NGLE_LOCK(fb);
661
 
662
        GET_FIFO_SLOTS(fb, nFreeFifoSlots, 4);
663
        NGLE_QUICK_SET_DST_BM_ACCESS(fb,
664
                                     BA(IndexedDcd, Otc32, OtsIndirect,
665
                                        AddrLong, BAJustPoint(0),
666
                                        BINattr, BAIndexBase(0)));
667
        NGLE_QUICK_SET_CTL_PLN_REG(fb, ctlPlaneReg);
668
        NGLE_SET_TRANSFERDATA(fb, 0xffffffff);
669
 
670
        NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
671
                                       IBOvals(RopSrc, MaskAddrOffset(0),
672
                                               BitmapExtent08, StaticReg(1),
673
                                               DataDynamic, MaskOtc,
674
                                               BGx(0), FGx(0)));
675
        packed_dst = 0;
676
        packed_len = (fb->info.var.xres << 16) | fb->info.var.yres;
677
        GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2);
678
        NGLE_SET_DSTXY(fb, packed_dst);
679
        SET_LENXY_START_RECFILL(fb, packed_len);
680
 
681
        /*
682
         * In order to work around an ELK hardware problem (Buffy doesn't
683
         * always flush it's buffers when writing to the attribute
684
         * planes), at least 4 pixels must be written to the attribute
685
         * planes starting at (X == 1280) and (Y != to the last Y written
686
         * by BIF):
687
         */
688
 
689
        if (fb->id == S9000_ID_A1659A) {   /* ELK_DEVICE_ID */
690
                /* It's safe to use scanline zero: */
691
                packed_dst = (1280 << 16);
692
                GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2);
693
                NGLE_SET_DSTXY(fb, packed_dst);
694
                packed_len = (4 << 16) | 1;
695
                SET_LENXY_START_RECFILL(fb, packed_len);
696
        }   /* ELK Hardware Kludge */
697
 
698
        /**** Finally, set the Control Plane Register back to zero: ****/
699
        GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1);
700
        NGLE_QUICK_SET_CTL_PLN_REG(fb, 0);
701
 
702
        NGLE_UNLOCK(fb);
703
}
704
 
705
static void
706
ngleClearOverlayPlanes(struct stifb_info *fb, int mask, int data)
707
{
708
        int nFreeFifoSlots = 0;
709
        u32 packed_dst;
710
        u32 packed_len;
711
 
712
        NGLE_LOCK(fb);
713
 
714
        /* Hardware setup */
715
        GET_FIFO_SLOTS(fb, nFreeFifoSlots, 8);
716
        NGLE_QUICK_SET_DST_BM_ACCESS(fb,
717
                                     BA(IndexedDcd, Otc04, Ots08, AddrLong,
718
                                        BAJustPoint(0), BINovly, BAIndexBase(0)));
719
 
720
        NGLE_SET_TRANSFERDATA(fb, 0xffffffff);  /* Write foreground color */
721
 
722
        NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, data);
723
        NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, mask);
724
 
725
        packed_dst = 0;
726
        packed_len = (fb->info.var.xres << 16) | fb->info.var.yres;
727
        NGLE_SET_DSTXY(fb, packed_dst);
728
 
729
        /* Write zeroes to overlay planes */
730
        NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb,
731
                                       IBOvals(RopSrc, MaskAddrOffset(0),
732
                                               BitmapExtent08, StaticReg(0),
733
                                               DataDynamic, MaskOtc, BGx(0), FGx(0)));
734
 
735
        SET_LENXY_START_RECFILL(fb, packed_len);
736
 
737
        NGLE_UNLOCK(fb);
738
}
739
 
740
static void
741
hyperResetPlanes(struct stifb_info *fb, int enable)
742
{
743
        unsigned int controlPlaneReg;
744
 
745
        NGLE_LOCK(fb);
746
 
747
        if (IS_24_DEVICE(fb))
748
                if (fb->info.var.bits_per_pixel == 32)
749
                        controlPlaneReg = 0x04000F00;
750
                else
751
                        controlPlaneReg = 0x00000F00;   /* 0x00000800 should be enought, but lets clear all 4 bits */
752
        else
753
                controlPlaneReg = 0x00000F00; /* 0x00000100 should be enought, but lets clear all 4 bits */
754
 
755
        switch (enable) {
756
        case ENABLE:
757
                /* clear screen */
758
                if (IS_24_DEVICE(fb))
759
                        ngleDepth24_ClearImagePlanes(fb);
760
                else
761
                        ngleDepth8_ClearImagePlanes(fb);
762
 
763
                /* Paint attribute planes for default case.
764
                 * On Hyperdrive, this means all windows using overlay cmap 0. */
765
                ngleResetAttrPlanes(fb, controlPlaneReg);
766
 
767
                /* clear overlay planes */
768
                ngleClearOverlayPlanes(fb, 0xff, 255);
769
 
770
                /**************************************************
771
                 ** Also need to counteract ITE settings
772
                 **************************************************/
773
                hyperUndoITE(fb);
774
                break;
775
 
776
        case DISABLE:
777
                /* clear screen */
778
                if (IS_24_DEVICE(fb))
779
                        ngleDepth24_ClearImagePlanes(fb);
780
                else
781
                        ngleDepth8_ClearImagePlanes(fb);
782
                ngleResetAttrPlanes(fb, controlPlaneReg);
783
                ngleClearOverlayPlanes(fb, 0xff, 0);
784
                break;
785
 
786
        case -1:        /* RESET */
787
                hyperUndoITE(fb);
788
                ngleResetAttrPlanes(fb, controlPlaneReg);
789
                break;
790
        }
791
 
792
        NGLE_UNLOCK(fb);
793
}
794
 
795
/* Return pointer to in-memory structure holding ELK device-dependent ROM values. */
796
 
797
static void
798
ngleGetDeviceRomData(struct stifb_info *fb)
799
{
800
#if 0
801
XXX: FIXME: !!!
802
        int     *pBytePerLongDevDepData;/* data byte == LSB */
803
        int     *pRomTable;
804
        NgleDevRomData  *pPackedDevRomData;
805
        int     sizePackedDevRomData = sizeof(*pPackedDevRomData);
806
        char    *pCard8;
807
        int     i;
808
        char    *mapOrigin = NULL;
809
 
810
        int romTableIdx;
811
 
812
        pPackedDevRomData = fb->ngle_rom;
813
 
814
        SETUP_HW(fb);
815
        if (fb->id == S9000_ID_ARTIST) {
816
                pPackedDevRomData->cursor_pipeline_delay = 4;
817
                pPackedDevRomData->video_interleaves     = 4;
818
        } else {
819
                /* Get pointer to unpacked byte/long data in ROM */
820
                pBytePerLongDevDepData = fb->sti->regions[NGLEDEVDEPROM_CRT_REGION];
821
 
822
                /* Tomcat supports several resolutions: 1280x1024, 1024x768, 640x480 */
823
                if (fb->id == S9000_ID_TOMCAT)
824
        {
825
            /*  jump to the correct ROM table  */
826
            GET_ROMTABLE_INDEX(romTableIdx);
827
            while  (romTableIdx > 0)
828
            {
829
                pCard8 = (Card8 *) pPackedDevRomData;
830
                pRomTable = pBytePerLongDevDepData;
831
                /* Pack every fourth byte from ROM into structure */
832
                for (i = 0; i < sizePackedDevRomData; i++)
833
                {
834
                    *pCard8++ = (Card8) (*pRomTable++);
835
                }
836
 
837
                pBytePerLongDevDepData = (Card32 *)
838
                        ((Card8 *) pBytePerLongDevDepData +
839
                               pPackedDevRomData->sizeof_ngle_data);
840
 
841
                romTableIdx--;
842
            }
843
        }
844
 
845
        pCard8 = (Card8 *) pPackedDevRomData;
846
 
847
        /* Pack every fourth byte from ROM into structure */
848
        for (i = 0; i < sizePackedDevRomData; i++)
849
        {
850
            *pCard8++ = (Card8) (*pBytePerLongDevDepData++);
851
        }
852
    }
853
 
854
    SETUP_FB(fb);
855
#endif
856
}
857
 
858
 
859
#define HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES     4
860
#define HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE      8
861
#define HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE           10
862
#define HYPERBOWL_MODE2_8_24                                    15
863
 
864
/* HCRX specific boot-time initialization */
865
static void __init
866
SETUP_HCRX(struct stifb_info *fb)
867
{
868
        int     hyperbowl;
869
        int     nFreeFifoSlots = 0;
870
 
871
        if (fb->id != S9000_ID_HCRX)
872
                return;
873
 
874
        /* Initialize Hyperbowl registers */
875
        GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7);
876
 
877
        if (IS_24_DEVICE(fb)) {
878
                hyperbowl = (fb->info.var.bits_per_pixel == 32) ?
879
                        HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE :
880
                        HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE;
881
 
882
                /* First write to Hyperbowl must happen twice (bug) */
883
                WRITE_WORD(hyperbowl, fb, REG_40);
884
                WRITE_WORD(hyperbowl, fb, REG_40);
885
 
886
                WRITE_WORD(HYPERBOWL_MODE2_8_24, fb, REG_39);
887
 
888
                WRITE_WORD(0x014c0148, fb, REG_42); /* Set lut 0 to be the direct color */
889
                WRITE_WORD(0x404c4048, fb, REG_43);
890
                WRITE_WORD(0x034c0348, fb, REG_44);
891
                WRITE_WORD(0x444c4448, fb, REG_45);
892
        } else {
893
                hyperbowl = HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES;
894
 
895
                /* First write to Hyperbowl must happen twice (bug) */
896
                WRITE_WORD(hyperbowl, fb, REG_40);
897
                WRITE_WORD(hyperbowl, fb, REG_40);
898
 
899
                WRITE_WORD(0x00000000, fb, REG_42);
900
                WRITE_WORD(0x00000000, fb, REG_43);
901
                WRITE_WORD(0x00000000, fb, REG_44);
902
                WRITE_WORD(0x444c4048, fb, REG_45);
903
        }
904
}
905
 
906
 
907
/* ------------------- driver specific functions --------------------------- */
908
 
909
static int
910
stifb_setcolreg(u_int regno, u_int red, u_int green,
911
              u_int blue, u_int transp, struct fb_info *info)
912
{
913
        struct stifb_info *fb = (struct stifb_info *) info;
914
        u32 color;
915
 
916
        if (regno >= NR_PALETTE)
917
                return 1;
918
 
919
        red   >>= 8;
920
        green >>= 8;
921
        blue  >>= 8;
922
 
923
        DEBUG_OFF();
924
 
925
        START_IMAGE_COLORMAP_ACCESS(fb);
926
 
927
        if (unlikely(fb->info.var.grayscale)) {
928
                /* gray = 0.30*R + 0.59*G + 0.11*B */
929
                color = ((red * 77) +
930
                         (green * 151) +
931
                         (blue * 28)) >> 8;
932
        } else {
933
                color = ((red << 16) |
934
                         (green << 8) |
935
                         (blue));
936
        }
937
 
938
        if (fb->info.fix.visual == FB_VISUAL_DIRECTCOLOR) {
939
                struct fb_var_screeninfo *var = &fb->info.var;
940
                if (regno < 16)
941
                        ((u32 *)fb->info.pseudo_palette)[regno] =
942
                                regno << var->red.offset |
943
                                regno << var->green.offset |
944
                                regno << var->blue.offset;
945
        }
946
 
947
        WRITE_IMAGE_COLOR(fb, regno, color);
948
 
949
        if (fb->id == S9000_ID_HCRX) {
950
                NgleLutBltCtl lutBltCtl;
951
 
952
                lutBltCtl = setHyperLutBltCtl(fb,
953
                                0,       /* Offset w/i LUT */
954
                                256);   /* Load entire LUT */
955
                NGLE_BINC_SET_SRCADDR(fb,
956
                                NGLE_LONG_FB_ADDRESS(0, 0x100, 0));
957
                                /* 0x100 is same as used in WRITE_IMAGE_COLOR() */
958
                START_COLORMAPLOAD(fb, lutBltCtl.all);
959
                SETUP_FB(fb);
960
        } else {
961
                /* cleanup colormap hardware */
962
                FINISH_IMAGE_COLORMAP_ACCESS(fb);
963
        }
964
 
965
        DEBUG_ON();
966
 
967
        return 0;
968
}
969
 
970
static int
971
stifb_blank(int blank_mode, struct fb_info *info)
972
{
973
        struct stifb_info *fb = (struct stifb_info *) info;
974
        int enable = (blank_mode == 0) ? ENABLE : DISABLE;
975
 
976
        switch (fb->id) {
977
        case S9000_ID_A1439A:
978
                CRX24_ENABLE_DISABLE_DISPLAY(fb, enable);
979
                break;
980
        case CRT_ID_VISUALIZE_EG:
981
        case S9000_ID_ARTIST:
982
                ARTIST_ENABLE_DISABLE_DISPLAY(fb, enable);
983
                break;
984
        case S9000_ID_HCRX:
985
                HYPER_ENABLE_DISABLE_DISPLAY(fb, enable);
986
                break;
987
        case S9000_ID_A1659A:   /* fall through */
988
        case S9000_ID_TIMBER:
989
        case CRX24_OVERLAY_PLANES:
990
        default:
991
                ENABLE_DISABLE_DISPLAY(fb, enable);
992
                break;
993
        }
994
 
995
        SETUP_FB(fb);
996
        return 0;
997
}
998
 
999
static void __init
1000
stifb_init_display(struct stifb_info *fb)
1001
{
1002
        int id = fb->id;
1003
 
1004
        SETUP_FB(fb);
1005
 
1006
        /* HCRX specific initialization */
1007
        SETUP_HCRX(fb);
1008
 
1009
        /*
1010
        if (id == S9000_ID_HCRX)
1011
                hyperInitSprite(fb);
1012
        else
1013
                ngleInitSprite(fb);
1014
        */
1015
 
1016
        /* Initialize the image planes. */
1017
        switch (id) {
1018
         case S9000_ID_HCRX:
1019
            hyperResetPlanes(fb, ENABLE);
1020
            break;
1021
         case S9000_ID_A1439A:
1022
            rattlerSetupPlanes(fb);
1023
            break;
1024
         case S9000_ID_A1659A:
1025
         case S9000_ID_ARTIST:
1026
         case CRT_ID_VISUALIZE_EG:
1027
            elkSetupPlanes(fb);
1028
            break;
1029
        }
1030
 
1031
        /* Clear attribute planes on non HCRX devices. */
1032
        switch (id) {
1033
         case S9000_ID_A1659A:
1034
         case S9000_ID_A1439A:
1035
            if (fb->info.var.bits_per_pixel == 32)
1036
                ngleSetupAttrPlanes(fb, BUFF1_CMAP3);
1037
            else {
1038
                ngleSetupAttrPlanes(fb, BUFF1_CMAP0);
1039
            }
1040
            if (id == S9000_ID_A1439A)
1041
                ngleClearOverlayPlanes(fb, 0xff, 0);
1042
            break;
1043
         case S9000_ID_ARTIST:
1044
         case CRT_ID_VISUALIZE_EG:
1045
            if (fb->info.var.bits_per_pixel == 32)
1046
                ngleSetupAttrPlanes(fb, BUFF1_CMAP3);
1047
            else {
1048
                ngleSetupAttrPlanes(fb, ARTIST_CMAP0);
1049
            }
1050
            break;
1051
        }
1052
        stifb_blank(0, (struct fb_info *)fb);    /* 0=enable screen */
1053
 
1054
        SETUP_FB(fb);
1055
}
1056
 
1057
/* ------------ Interfaces to hardware functions ------------ */
1058
 
1059
static struct fb_ops stifb_ops = {
1060
        .owner          = THIS_MODULE,
1061
        .fb_setcolreg   = stifb_setcolreg,
1062
        .fb_blank       = stifb_blank,
1063
        .fb_fillrect    = cfb_fillrect,
1064
        .fb_copyarea    = cfb_copyarea,
1065
        .fb_imageblit   = cfb_imageblit,
1066
};
1067
 
1068
 
1069
/*
1070
 *  Initialization
1071
 */
1072
 
1073
int __init
1074
stifb_init_fb(struct sti_struct *sti, int bpp_pref)
1075
{
1076
        struct fb_fix_screeninfo *fix;
1077
        struct fb_var_screeninfo *var;
1078
        struct stifb_info *fb;
1079
        struct fb_info *info;
1080
        unsigned long sti_rom_address;
1081
        char *dev_name;
1082
        int bpp, xres, yres;
1083
 
1084
        fb = kzalloc(sizeof(*fb), GFP_ATOMIC);
1085
        if (!fb) {
1086
                printk(KERN_ERR "stifb: Could not allocate stifb structure\n");
1087
                return -ENODEV;
1088
        }
1089
 
1090
        info = &fb->info;
1091
 
1092
        /* set struct to a known state */
1093
        fix = &info->fix;
1094
        var = &info->var;
1095
 
1096
        fb->sti = sti;
1097
        /* store upper 32bits of the graphics id */
1098
        fb->id = fb->sti->graphics_id[0];
1099
 
1100
        /* only supported cards are allowed */
1101
        switch (fb->id) {
1102
        case CRT_ID_VISUALIZE_EG:
1103
                /* Visualize cards can run either in "double buffer" or
1104
                  "standard" mode. Depending on the mode, the card reports
1105
                  a different device name, e.g. "INTERNAL_EG_DX1024" in double
1106
                  buffer mode and "INTERNAL_EG_X1024" in standard mode.
1107
                  Since this driver only supports standard mode, we check
1108
                  if the device name contains the string "DX" and tell the
1109
                  user how to reconfigure the card. */
1110
                if (strstr(sti->outptr.dev_name, "DX")) {
1111
                   printk(KERN_WARNING "WARNING: stifb framebuffer driver does not "
1112
                        "support '%s' in double-buffer mode.\n"
1113
                        KERN_WARNING "WARNING: Please disable the double-buffer mode "
1114
                        "in IPL menu (the PARISC-BIOS).\n",
1115
                        sti->outptr.dev_name);
1116
                   goto out_err0;
1117
                }
1118
                /* fall though */
1119
        case S9000_ID_ARTIST:
1120
        case S9000_ID_HCRX:
1121
        case S9000_ID_TIMBER:
1122
        case S9000_ID_A1659A:
1123
        case S9000_ID_A1439A:
1124
                break;
1125
        default:
1126
                printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n",
1127
                        sti->outptr.dev_name, fb->id);
1128
                goto out_err0;
1129
        }
1130
 
1131
        /* default to 8 bpp on most graphic chips */
1132
        bpp = 8;
1133
        xres = sti_onscreen_x(fb->sti);
1134
        yres = sti_onscreen_y(fb->sti);
1135
 
1136
        ngleGetDeviceRomData(fb);
1137
 
1138
        /* get (virtual) io region base addr */
1139
        fix->mmio_start = REGION_BASE(fb,2);
1140
        fix->mmio_len   = 0x400000;
1141
 
1142
        /* Reject any device not in the NGLE family */
1143
        switch (fb->id) {
1144
        case S9000_ID_A1659A:   /* CRX/A1659A */
1145
                break;
1146
        case S9000_ID_ELM:      /* GRX, grayscale but else same as A1659A */
1147
                var->grayscale = 1;
1148
                fb->id = S9000_ID_A1659A;
1149
                break;
1150
        case S9000_ID_TIMBER:   /* HP9000/710 Any (may be a grayscale device) */
1151
                dev_name = fb->sti->outptr.dev_name;
1152
                if (strstr(dev_name, "GRAYSCALE") ||
1153
                    strstr(dev_name, "Grayscale") ||
1154
                    strstr(dev_name, "grayscale"))
1155
                        var->grayscale = 1;
1156
                break;
1157
        case S9000_ID_TOMCAT:   /* Dual CRX, behaves else like a CRX */
1158
                /* FIXME: TomCat supports two heads:
1159
                 * fb.iobase = REGION_BASE(fb_info,3);
1160
                 * fb.screen_base = ioremap_nocache(REGION_BASE(fb_info,2),xxx);
1161
                 * for now we only support the left one ! */
1162
                xres = fb->ngle_rom.x_size_visible;
1163
                yres = fb->ngle_rom.y_size_visible;
1164
                fb->id = S9000_ID_A1659A;
1165
                break;
1166
        case S9000_ID_A1439A:   /* CRX24/A1439A */
1167
                bpp = 32;
1168
                break;
1169
        case S9000_ID_HCRX:     /* Hyperdrive/HCRX */
1170
                memset(&fb->ngle_rom, 0, sizeof(fb->ngle_rom));
1171
                if ((fb->sti->regions_phys[0] & 0xfc000000) ==
1172
                    (fb->sti->regions_phys[2] & 0xfc000000))
1173
                        sti_rom_address = F_EXTEND(fb->sti->regions_phys[0]);
1174
                else
1175
                        sti_rom_address = F_EXTEND(fb->sti->regions_phys[1]);
1176
 
1177
                fb->deviceSpecificConfig = gsc_readl(sti_rom_address);
1178
                if (IS_24_DEVICE(fb)) {
1179
                        if (bpp_pref == 8 || bpp_pref == 32)
1180
                                bpp = bpp_pref;
1181
                        else
1182
                                bpp = 32;
1183
                } else
1184
                        bpp = 8;
1185
                READ_WORD(fb, REG_15);
1186
                SETUP_HW(fb);
1187
                break;
1188
        case CRT_ID_VISUALIZE_EG:
1189
        case S9000_ID_ARTIST:   /* Artist */
1190
                break;
1191
        default:
1192
#ifdef FALLBACK_TO_1BPP
1193
                printk(KERN_WARNING
1194
                        "stifb: Unsupported graphics card (id=0x%08x) "
1195
                                "- now trying 1bpp mode instead\n",
1196
                        fb->id);
1197
                bpp = 1;        /* default to 1 bpp */
1198
                break;
1199
#else
1200
                printk(KERN_WARNING
1201
                        "stifb: Unsupported graphics card (id=0x%08x) "
1202
                                "- skipping.\n",
1203
                        fb->id);
1204
                goto out_err0;
1205
#endif
1206
        }
1207
 
1208
 
1209
        /* get framebuffer physical and virtual base addr & len (64bit ready) */
1210
        fix->smem_start = F_EXTEND(fb->sti->regions_phys[1]);
1211
        fix->smem_len = fb->sti->regions[1].region_desc.length * 4096;
1212
 
1213
        fix->line_length = (fb->sti->glob_cfg->total_x * bpp) / 8;
1214
        if (!fix->line_length)
1215
                fix->line_length = 2048; /* default */
1216
 
1217
        /* limit fbsize to max visible screen size */
1218
        if (fix->smem_len > yres*fix->line_length)
1219
                fix->smem_len = yres*fix->line_length;
1220
 
1221
        fix->accel = FB_ACCEL_NONE;
1222
 
1223
        switch (bpp) {
1224
            case 1:
1225
                fix->type = FB_TYPE_PLANES;     /* well, sort of */
1226
                fix->visual = FB_VISUAL_MONO10;
1227
                var->red.length = var->green.length = var->blue.length = 1;
1228
                break;
1229
            case 8:
1230
                fix->type = FB_TYPE_PACKED_PIXELS;
1231
                fix->visual = FB_VISUAL_PSEUDOCOLOR;
1232
                var->red.length = var->green.length = var->blue.length = 8;
1233
                break;
1234
            case 32:
1235
                fix->type = FB_TYPE_PACKED_PIXELS;
1236
                fix->visual = FB_VISUAL_DIRECTCOLOR;
1237
                var->red.length = var->green.length = var->blue.length = var->transp.length = 8;
1238
                var->blue.offset = 0;
1239
                var->green.offset = 8;
1240
                var->red.offset = 16;
1241
                var->transp.offset = 24;
1242
                break;
1243
            default:
1244
                break;
1245
        }
1246
 
1247
        var->xres = var->xres_virtual = xres;
1248
        var->yres = var->yres_virtual = yres;
1249
        var->bits_per_pixel = bpp;
1250
 
1251
        strcpy(fix->id, "stifb");
1252
        info->fbops = &stifb_ops;
1253
        info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len);
1254
        info->screen_size = fix->smem_len;
1255
        info->flags = FBINFO_DEFAULT;
1256
        info->pseudo_palette = &fb->pseudo_palette;
1257
 
1258
        /* This has to been done !!! */
1259
        fb_alloc_cmap(&info->cmap, NR_PALETTE, 0);
1260
        stifb_init_display(fb);
1261
 
1262
        if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) {
1263
                printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n",
1264
                                fix->smem_start, fix->smem_start+fix->smem_len);
1265
                goto out_err1;
1266
        }
1267
 
1268
        if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) {
1269
                printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n",
1270
                                fix->mmio_start, fix->mmio_start+fix->mmio_len);
1271
                goto out_err2;
1272
        }
1273
 
1274
        if (register_framebuffer(&fb->info) < 0)
1275
                goto out_err3;
1276
 
1277
        sti->info = info; /* save for unregister_framebuffer() */
1278
 
1279
        printk(KERN_INFO
1280
            "fb%d: %s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n",
1281
                fb->info.node,
1282
                fix->id,
1283
                var->xres,
1284
                var->yres,
1285
                var->bits_per_pixel,
1286
                sti->outptr.dev_name,
1287
                fb->id,
1288
                fix->mmio_start);
1289
 
1290
        return 0;
1291
 
1292
 
1293
out_err3:
1294
        release_mem_region(fix->mmio_start, fix->mmio_len);
1295
out_err2:
1296
        release_mem_region(fix->smem_start, fix->smem_len);
1297
out_err1:
1298
        iounmap(info->screen_base);
1299
        fb_dealloc_cmap(&info->cmap);
1300
out_err0:
1301
        kfree(fb);
1302
        return -ENXIO;
1303
}
1304
 
1305
static int stifb_disabled __initdata;
1306
 
1307
int __init
1308
stifb_setup(char *options);
1309
 
1310
int __init
1311
stifb_init(void)
1312
{
1313
        struct sti_struct *sti;
1314
        struct sti_struct *def_sti;
1315
        int i;
1316
 
1317
#ifndef MODULE
1318
        char *option = NULL;
1319
 
1320
        if (fb_get_options("stifb", &option))
1321
                return -ENODEV;
1322
        stifb_setup(option);
1323
#endif
1324
        if (stifb_disabled) {
1325
                printk(KERN_INFO "stifb: disabled by \"stifb=off\" kernel parameter\n");
1326
                return -ENXIO;
1327
        }
1328
 
1329
        def_sti = sti_get_rom(0);
1330
        if (def_sti) {
1331
                for (i = 1; i <= MAX_STI_ROMS; i++) {
1332
                        sti = sti_get_rom(i);
1333
                        if (!sti)
1334
                                break;
1335
                        if (sti == def_sti) {
1336
                                stifb_init_fb(sti, stifb_bpp_pref[i - 1]);
1337
                                break;
1338
                        }
1339
                }
1340
        }
1341
 
1342
        for (i = 1; i <= MAX_STI_ROMS; i++) {
1343
                sti = sti_get_rom(i);
1344
                if (!sti)
1345
                        break;
1346
                if (sti == def_sti)
1347
                        continue;
1348
                stifb_init_fb(sti, stifb_bpp_pref[i - 1]);
1349
        }
1350
        return 0;
1351
}
1352
 
1353
/*
1354
 *  Cleanup
1355
 */
1356
 
1357
static void __exit
1358
stifb_cleanup(void)
1359
{
1360
        struct sti_struct *sti;
1361
        int i;
1362
 
1363
        for (i = 1; i <= MAX_STI_ROMS; i++) {
1364
                sti = sti_get_rom(i);
1365
                if (!sti)
1366
                        break;
1367
                if (sti->info) {
1368
                        struct fb_info *info = sti->info;
1369
                        unregister_framebuffer(sti->info);
1370
                        release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
1371
                        release_mem_region(info->fix.smem_start, info->fix.smem_len);
1372
                                if (info->screen_base)
1373
                                        iounmap(info->screen_base);
1374
                        fb_dealloc_cmap(&info->cmap);
1375
                        kfree(info);
1376
                }
1377
                sti->info = NULL;
1378
        }
1379
}
1380
 
1381
int __init
1382
stifb_setup(char *options)
1383
{
1384
        int i;
1385
 
1386
        if (!options || !*options)
1387
                return 1;
1388
 
1389
        if (strncmp(options, "off", 3) == 0) {
1390
                stifb_disabled = 1;
1391
                options += 3;
1392
        }
1393
 
1394
        if (strncmp(options, "bpp", 3) == 0) {
1395
                options += 3;
1396
                for (i = 0; i < MAX_STI_ROMS; i++) {
1397
                        if (*options++ != ':')
1398
                                break;
1399
                        stifb_bpp_pref[i] = simple_strtoul(options, &options, 10);
1400
                }
1401
        }
1402
        return 1;
1403
}
1404
 
1405
__setup("stifb=", stifb_setup);
1406
 
1407
module_init(stifb_init);
1408
module_exit(stifb_cleanup);
1409
 
1410
MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
1411
MODULE_DESCRIPTION("Framebuffer driver for HP's NGLE series graphics cards in HP PARISC machines");
1412
MODULE_LICENSE("GPL v2");

powered by: WebSVN 2.1.0

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