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

Subversion Repositories or1k

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/drivers/video/igafb.c -- Frame buffer device for IGA 1682
3
 *
4
 *      Copyright (C) 1998  Vladimir Roganov and Gleb Raiko
5
 *
6
 *  This driver is partly based on the Frame buffer device for ATI Mach64
7
 *  and partially on VESA-related code.
8
 *
9
 *      Copyright (C) 1997-1998  Geert Uytterhoeven
10
 *      Copyright (C) 1998  Bernd Harries
11
 *      Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
12
 *
13
 *  This file is subject to the terms and conditions of the GNU General Public
14
 *  License. See the file COPYING in the main directory of this archive for
15
 *  more details.
16
 */
17
 
18
/******************************************************************************
19
 
20
  TODO:
21
       Despite of IGA Card has advanced graphic acceleration,
22
       initial version is almost dummy and does not support it.
23
       Support for video modes and acceleration must be added
24
       together with accelerated X-Windows driver implementation.
25
 
26
       Most important thing at this moment is that we have working
27
       JavaEngine1  console & X  with new console interface.
28
 
29
******************************************************************************/
30
 
31
#include <linux/module.h>
32
#include <linux/kernel.h>
33
#include <linux/errno.h>
34
#include <linux/string.h>
35
#include <linux/mm.h>
36
#include <linux/tty.h>
37
#include <linux/slab.h>
38
#include <linux/vmalloc.h>
39
#include <linux/delay.h>
40
#include <linux/interrupt.h>
41
#include <linux/fb.h>
42
#include <linux/selection.h>
43
#include <linux/console.h>
44
#include <linux/init.h>
45
#include <linux/pci.h>
46
#include <linux/nvram.h>
47
#include <linux/kd.h>
48
#include <linux/vt_kern.h>
49
 
50
#include <asm/io.h>
51
 
52
#ifdef __sparc__
53
#include <asm/pbm.h>
54
#include <asm/pcic.h>
55
#endif
56
 
57
#include <video/fbcon.h>
58
#include <video/fbcon-cfb8.h>
59
#include <video/fbcon-cfb16.h>
60
#include <video/fbcon-cfb24.h>
61
#include <video/fbcon-cfb32.h>
62
 
63
#include "iga.h"
64
 
65
static char igafb_name[16] = "IGA 1682";
66
static char fontname[40] __initdata = { 0 };
67
 
68
struct pci_mmap_map {
69
    unsigned long voff;
70
    unsigned long poff;
71
    unsigned long size;
72
    unsigned long prot_flag;
73
    unsigned long prot_mask;
74
};
75
 
76
struct fb_info_iga {
77
    struct fb_info fb_info;
78
    unsigned long frame_buffer_phys;
79
    char *frame_buffer;
80
    unsigned long io_base_phys;
81
    unsigned long io_base;
82
    u32 total_vram;
83
    struct pci_mmap_map *mmap_map;
84
    struct { u_short blue, green, red, pad; } palette[256];
85
    int video_cmap_len;
86
    int currcon;
87
    struct display disp;
88
    struct display_switch dispsw;
89
    union {
90
#ifdef FBCON_HAS_CFB16
91
            u16 cfb16[16];
92
#endif
93
#ifdef FBCON_HAS_CFB24
94
            u32 cfb24[16];
95
#endif
96
#ifdef FBCON_HAS_CFB32
97
            u32 cfb32[16];
98
#endif
99
    } fbcon_cmap;
100
#ifdef __sparc__
101
    u8 open;
102
    u8 mmaped;
103
    int vtconsole;
104
    int consolecnt;
105
#endif
106
};
107
 
108
struct fb_var_screeninfo default_var = {
109
    /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
110
    640, 480, 640, 480, 0, 0, 8, 0,
111
    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
112
    0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
113
    0, FB_VMODE_NONINTERLACED
114
};
115
 
116
#ifdef __sparc__
117
struct fb_var_screeninfo default_var_1024x768 __initdata = {
118
    /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
119
    1024, 768, 1024, 768, 0, 0, 8, 0,
120
    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
121
    0, 0, -1, -1, 0, 12699, 176, 16, 28, 1, 96, 3,
122
    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
123
};
124
 
125
struct fb_var_screeninfo default_var_1152x900 __initdata = {
126
    /* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */
127
    1152, 900, 1152, 900, 0, 0, 8, 0,
128
    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
129
    0, 0, -1, -1, 0, 9091, 234, 24, 34, 3, 100, 3,
130
    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
131
};
132
 
133
struct fb_var_screeninfo default_var_1280x1024 __initdata = {
134
    /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
135
    1280, 1024, 1280, 1024, 0, 0, 8, 0,
136
    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
137
    0, 0, -1, -1, 0, 7408, 248, 16, 38, 1, 144, 3,
138
    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
139
};
140
 
141
/*
142
 *   Memory-mapped I/O functions for Sparc PCI
143
 *
144
 * On sparc we happen to access I/O with memory mapped functions too.
145
 */
146
#define pci_inb(info, reg)        readb(info->io_base+(reg))
147
#define pci_outb(info, val, reg)  writeb(val, info->io_base+(reg))
148
 
149
static inline unsigned int iga_inb(struct fb_info_iga *info,
150
                                   unsigned int reg, unsigned int idx )
151
{
152
        pci_outb(info, idx, reg);
153
        return pci_inb(info, reg + 1);
154
}
155
 
156
static inline void iga_outb(struct fb_info_iga *info, unsigned char val,
157
                            unsigned int reg, unsigned int idx )
158
{
159
        pci_outb(info, idx, reg);
160
        pci_outb(info, val, reg+1);
161
}
162
 
163
#endif /* __sparc__ */
164
 
165
/*
166
 *  Very important functionality for the JavaEngine1 computer:
167
 *  make screen border black (usign special IGA registers)
168
 */
169
static void iga_blank_border(struct fb_info_iga *info)
170
{
171
        int i;
172
 
173
#if 0
174
        /*
175
         * PROM does this for us, so keep this code as a reminder
176
         * about required read from 0x3DA and writing of 0x20 in the end.
177
         */
178
        (void) pci_inb(info, 0x3DA);            /* required for every access */
179
        pci_outb(info, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL);
180
        (void) pci_inb(info, IGA_ATTR_CTL+1);
181
        pci_outb(info, 0x38, IGA_ATTR_CTL);
182
        pci_outb(info, 0x20, IGA_ATTR_CTL);     /* re-enable visual */
183
#endif
184
        /*
185
         * This does not work as it was designed because the overscan
186
         * color is looked up in the palette. Therefore, under X11
187
         * overscan changes color.
188
         */
189
        for (i=0; i < 3; i++)
190
                iga_outb(info, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
191
}
192
 
193
 
194
/*
195
 *  Frame buffer device API
196
 */
197
 
198
static int igafb_update_var(int con, struct fb_info *info)
199
{
200
        return 0;
201
}
202
 
203
static int igafb_get_fix(struct fb_fix_screeninfo *fix, int con,
204
                         struct fb_info *info)
205
{
206
        struct fb_info_iga *fb = (struct fb_info_iga*)info;
207
 
208
        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
209
        strcpy(fix->id, igafb_name);
210
 
211
        fix->smem_start = (unsigned long) fb->frame_buffer;
212
        fix->smem_len = fb->total_vram;
213
        fix->xpanstep = 0;
214
        fix->ypanstep = 0;
215
        fix->ywrapstep = 0;
216
 
217
        fix->type = FB_TYPE_PACKED_PIXELS;
218
        fix->type_aux = 0;
219
        fix->line_length = default_var.xres * (default_var.bits_per_pixel/8);
220
        fix->visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR
221
                                                      : FB_VISUAL_DIRECTCOLOR;
222
        return 0;
223
}
224
 
225
static int igafb_get_var(struct fb_var_screeninfo *var, int con,
226
                         struct fb_info *info)
227
{
228
        if(con == -1)
229
                memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
230
        else
231
                *var = fb_display[con].var;
232
        return 0;
233
}
234
 
235
static int igafb_set_var(struct fb_var_screeninfo *var, int con,
236
                         struct fb_info *info)
237
{
238
        memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
239
        return 0;
240
}
241
 
242
#ifdef __sparc__
243
static int igafb_mmap(struct fb_info *info, struct file *file,
244
                      struct vm_area_struct *vma)
245
{
246
        struct fb_info_iga *fb = (struct fb_info_iga *)info;
247
        unsigned int size, page, map_size = 0;
248
        unsigned long map_offset = 0;
249
        int i;
250
 
251
        if (!fb->mmap_map)
252
                return -ENXIO;
253
 
254
        size = vma->vm_end - vma->vm_start;
255
 
256
        /* To stop the swapper from even considering these pages. */
257
        vma->vm_flags |= (VM_SHM | VM_LOCKED);
258
 
259
        /* Each page, see which map applies */
260
        for (page = 0; page < size; ) {
261
                map_size = 0;
262
                for (i = 0; fb->mmap_map[i].size; i++) {
263
                        unsigned long start = fb->mmap_map[i].voff;
264
                        unsigned long end = start + fb->mmap_map[i].size;
265
                        unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page;
266
 
267
                        if (start > offset)
268
                                continue;
269
                        if (offset >= end)
270
                                continue;
271
 
272
                        map_size = fb->mmap_map[i].size - (offset - start);
273
                        map_offset = fb->mmap_map[i].poff + (offset - start);
274
                        break;
275
                }
276
                if (!map_size) {
277
                        page += PAGE_SIZE;
278
                        continue;
279
                }
280
                if (page + map_size > size)
281
                        map_size = size - page;
282
 
283
                pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
284
                pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
285
 
286
                if (remap_page_range(vma->vm_start + page, map_offset,
287
                                     map_size, vma->vm_page_prot))
288
                        return -EAGAIN;
289
 
290
                page += map_size;
291
        }
292
 
293
        if (!map_size)
294
                return -EINVAL;
295
 
296
        if (!fb->mmaped) {
297
                int lastconsole = 0;
298
 
299
                if (info->display_fg)
300
                        lastconsole = info->display_fg->vc_num;
301
                fb->mmaped = 1;
302
                if (fb->consolecnt && fb_display[lastconsole].fb_info ==info) {
303
                        fb->vtconsole = lastconsole;
304
                        vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
305
                }
306
        }
307
        return 0;
308
}
309
#endif /* __sparc__ */
310
 
311
 
312
static int iga_getcolreg(unsigned regno, unsigned *red, unsigned *green,
313
                          unsigned *blue, unsigned *transp,
314
                          struct fb_info *fb_info)
315
{
316
        /*
317
         *  Read a single color register and split it into colors/transparent.
318
         *  Return != 0 for invalid regno.
319
         */
320
        struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
321
 
322
        if (regno >= info->video_cmap_len)
323
                return 1;
324
 
325
        *red    = info->palette[regno].red;
326
        *green  = info->palette[regno].green;
327
        *blue   = info->palette[regno].blue;
328
        *transp = 0;
329
        return 0;
330
}
331
 
332
static int iga_setcolreg(unsigned regno, unsigned red, unsigned green,
333
                          unsigned blue, unsigned transp,
334
                          struct fb_info *fb_info)
335
{
336
        /*
337
         *  Set a single color register. The values supplied are
338
         *  already rounded down to the hardware's capabilities
339
         *  (according to the entries in the `var' structure). Return
340
         *  != 0 for invalid regno.
341
         */
342
 
343
        struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
344
 
345
        if (regno >= info->video_cmap_len)
346
                return 1;
347
 
348
        info->palette[regno].red   = red;
349
        info->palette[regno].green = green;
350
        info->palette[regno].blue  = blue;
351
 
352
        pci_outb(info, regno, DAC_W_INDEX);
353
        pci_outb(info, red,   DAC_DATA);
354
        pci_outb(info, green, DAC_DATA);
355
        pci_outb(info, blue,  DAC_DATA);
356
 
357
        if (regno < 16) {
358
                switch (default_var.bits_per_pixel) {
359
#ifdef FBCON_HAS_CFB16
360
                case 16:
361
                        info->fbcon_cmap.cfb16[regno] =
362
                                (regno << 10) | (regno << 5) | regno;
363
                        break;
364
#endif
365
#ifdef FBCON_HAS_CFB24
366
                case 24:
367
                        info->fbcon_cmap.cfb24[regno] =
368
                                (regno << 16) | (regno << 8) | regno;
369
                break;
370
#endif
371
#ifdef FBCON_HAS_CFB32
372
                case 32:
373
                        { int i;
374
                        i = (regno << 8) | regno;
375
                        info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
376
                        }
377
                        break;
378
#endif
379
                }
380
        }
381
        return 0;
382
}
383
 
384
static void do_install_cmap(int con, struct fb_info *fb_info)
385
{
386
        struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
387
 
388
        if (con != info->currcon)
389
                return;
390
        if (fb_display[con].cmap.len)
391
                fb_set_cmap(&fb_display[con].cmap, 1,
392
                            iga_setcolreg, &info->fb_info);
393
        else
394
                fb_set_cmap(fb_default_cmap(info->video_cmap_len), 1,
395
                            iga_setcolreg, &info->fb_info);
396
}
397
 
398
static int igafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
399
                           struct fb_info *fb_info)
400
{
401
        struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
402
 
403
        if (con == info->currcon) /* current console? */
404
                return fb_get_cmap(cmap, kspc, iga_getcolreg, &info->fb_info);
405
        else if (fb_display[con].cmap.len) /* non default colormap? */
406
                fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
407
        else
408
                fb_copy_cmap(fb_default_cmap(info->video_cmap_len),
409
                     cmap, kspc ? 0 : 2);
410
        return 0;
411
}
412
 
413
static int igafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
414
                          struct fb_info *info)
415
{
416
        int err;
417
        struct fb_info_iga *fb = (struct fb_info_iga*) info;
418
 
419
        if (!fb_display[con].cmap.len) {        /* no colormap allocated? */
420
                err = fb_alloc_cmap(&fb_display[con].cmap,
421
                                    fb->video_cmap_len,0);
422
                if (err)
423
                        return err;
424
        }
425
        if (con == fb->currcon)                     /* current console? */
426
                return fb_set_cmap(cmap, kspc, iga_setcolreg, info);
427
        else
428
                fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
429
        return 0;
430
}
431
 
432
/*
433
 * Framebuffer option structure
434
 */
435
static struct fb_ops igafb_ops = {
436
        owner:          THIS_MODULE,
437
        fb_get_fix:     igafb_get_fix,
438
        fb_get_var:     igafb_get_var,
439
        fb_set_var:     igafb_set_var,
440
        fb_get_cmap:    igafb_get_cmap,
441
        fb_set_cmap:    igafb_set_cmap,
442
#ifdef __sparc__
443
        fb_mmap:        igafb_mmap,
444
#endif
445
};
446
 
447
static void igafb_set_disp(int con, struct fb_info_iga *info)
448
{
449
        struct fb_fix_screeninfo fix;
450
        struct display *display;
451
        struct display_switch *sw;
452
 
453
        if (con >= 0)
454
                display = &fb_display[con];
455
        else
456
                display = &info->disp;        /* used during initialization */
457
 
458
        igafb_get_fix(&fix, con, &info->fb_info);
459
 
460
        memset(display, 0, sizeof(struct display));
461
        display->screen_base = info->frame_buffer;
462
        display->visual = fix.visual;
463
        display->type = fix.type;
464
        display->type_aux = fix.type_aux;
465
        display->ypanstep = fix.ypanstep;
466
        display->ywrapstep = fix.ywrapstep;
467
        display->line_length = fix.line_length;
468
        display->next_line = fix.line_length;
469
        display->can_soft_blank = 0;
470
        display->inverse = 0;
471
        igafb_get_var(&display->var, -1, &info->fb_info);
472
 
473
        switch (default_var.bits_per_pixel) {
474
#ifdef FBCON_HAS_CFB8
475
        case 8:
476
                sw = &fbcon_cfb8;
477
                break;
478
#endif
479
#ifdef FBCON_HAS_CFB16
480
        case 15:
481
        case 16:
482
                sw = &fbcon_cfb16;
483
                display->dispsw_data = info->fbcon_cmap.cfb16;
484
                break;
485
#endif
486
#ifdef FBCON_HAS_CFB24
487
        case 24:
488
                sw = &fbcon_cfb24;
489
                display->dispsw_data = info->fbcon_cmap.cfb24;
490
                break;
491
#endif
492
#ifdef FBCON_HAS_CFB32
493
        case 32:
494
                sw = &fbcon_cfb32;
495
                display->dispsw_data = info->fbcon_cmap.cfb32;
496
                break;
497
#endif
498
        default:
499
                printk(KERN_WARNING "igafb_set_disp: unknown resolution %d\n",
500
                    default_var.bits_per_pixel);
501
                return;
502
        }
503
        memcpy(&info->dispsw, sw, sizeof(*sw));
504
        display->dispsw = &info->dispsw;
505
 
506
        display->scrollmode = SCROLL_YREDRAW;
507
        info->dispsw.bmove = fbcon_redraw_bmove;
508
}
509
 
510
static int igafb_switch(int con, struct fb_info *fb_info)
511
{
512
        struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
513
 
514
        /* Do we have to save the colormap? */
515
        if (fb_display[info->currcon].cmap.len)
516
                fb_get_cmap(&fb_display[info->currcon].cmap, 1,
517
                            iga_getcolreg, fb_info);
518
 
519
        info->currcon = con;
520
        /* Install new colormap */
521
        do_install_cmap(con, fb_info);
522
        igafb_update_var(con, fb_info);
523
        return 1;
524
}
525
 
526
 
527
 
528
/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
529
 
530
static void igafb_blank(int blank, struct fb_info *info)
531
{
532
        /* Not supported */
533
}
534
 
535
 
536
static int __init iga_init(struct fb_info_iga *info)
537
{
538
        char vramsz = iga_inb(info, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL)
539
                                                         & MEM_SIZE_ALIAS;
540
        switch (vramsz) {
541
        case MEM_SIZE_1M:
542
                info->total_vram = 0x100000;
543
                break;
544
        case MEM_SIZE_2M:
545
                info->total_vram = 0x200000;
546
                break;
547
        case MEM_SIZE_4M:
548
        case MEM_SIZE_RESERVED:
549
                info->total_vram = 0x400000;
550
                break;
551
        }
552
 
553
        if (default_var.bits_per_pixel > 8) {
554
                info->video_cmap_len = 16;
555
        } else {
556
                info->video_cmap_len = 256;
557
        }
558
        {
559
                int j, k;
560
                for (j = 0; j < 16; j++) {
561
                        k = color_table[j];
562
                        info->palette[j].red = default_red[k];
563
                        info->palette[j].green = default_grn[k];
564
                        info->palette[j].blue = default_blu[k];
565
                }
566
        }
567
 
568
        strcpy(info->fb_info.modename, igafb_name);
569
        info->fb_info.node = -1;
570
        info->fb_info.fbops = &igafb_ops;
571
        info->fb_info.disp = &info->disp;
572
        strcpy(info->fb_info.fontname, fontname);
573
        info->fb_info.changevar = NULL;
574
        info->fb_info.switch_con = &igafb_switch;
575
        info->fb_info.updatevar = &igafb_update_var;
576
        info->fb_info.blank = &igafb_blank;
577
        info->fb_info.flags=FBINFO_FLAG_DEFAULT;
578
 
579
        igafb_set_disp(-1, info);
580
 
581
        if (register_framebuffer(&info->fb_info) < 0)
582
                return 0;
583
 
584
        printk("fb%d: %s frame buffer device at 0x%08lx [%dMB VRAM]\n",
585
               GET_FB_IDX(info->fb_info.node), igafb_name,
586
               info->frame_buffer_phys, info->total_vram >> 20);
587
 
588
        iga_blank_border(info);
589
        return 1;
590
}
591
 
592
int __init igafb_init(void)
593
{
594
        struct pci_dev *pdev;
595
        struct fb_info_iga *info;
596
        unsigned long addr;
597
        extern int con_is_present(void);
598
        int iga2000 = 0;
599
 
600
        /* Do not attach when we have a serial console. */
601
        if (!con_is_present())
602
                return -ENXIO;
603
 
604
        pdev = pci_find_device(PCI_VENDOR_ID_INTERG,
605
                               PCI_DEVICE_ID_INTERG_1682, 0);
606
        if (pdev == NULL) {
607
                /*
608
                 * XXX We tried to use cyber2000fb.c for IGS 2000.
609
                 * But it does not initialize the chip in JavaStation-E, alas.
610
                 */
611
                pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
612
                if(pdev == NULL) {
613
                        return -ENXIO;
614
                }
615
                iga2000 = 1;
616
        }
617
 
618
        info = kmalloc(sizeof(struct fb_info_iga), GFP_ATOMIC);
619
        if (!info) {
620
                printk("igafb_init: can't alloc fb_info_iga\n");
621
                return -ENOMEM;
622
        }
623
        memset(info, 0, sizeof(struct fb_info_iga));
624
 
625
        if ((addr = pdev->resource[0].start) == 0) {
626
                printk("igafb_init: no memory start\n");
627
                kfree(info);
628
                return -ENXIO;
629
        }
630
 
631
        if ((info->frame_buffer = ioremap(addr, 1024*1024*2)) == 0) {
632
                printk("igafb_init: can't remap %lx[2M]\n", addr);
633
                kfree(info);
634
                return -ENXIO;
635
        }
636
 
637
        info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
638
 
639
#ifdef __sparc__
640
        /*
641
         * The following is sparc specific and this is why:
642
         *
643
         * IGS2000 has its I/O memory mapped and we want
644
         * to generate memory cycles on PCI, e.g. do ioremap(),
645
         * then readb/writeb() as in Documentation/IO-mapping.txt.
646
         *
647
         * IGS1682 is more traditional, it responds to PCI I/O
648
         * cycles, so we want to access it with inb()/outb().
649
         *
650
         * On sparc, PCIC converts CPU memory access within
651
         * phys window 0x3000xxxx into PCI I/O cycles. Therefore
652
         * we may use readb/writeb to access them with IGS1682.
653
         *
654
         * We do not take io_base_phys from resource[n].start
655
         * on IGS1682 because that chip is BROKEN. It does not
656
         * have a base register for I/O. We just "know" what its
657
         * I/O addresses are.
658
         */
659
        if (iga2000) {
660
                info->io_base_phys = info->frame_buffer_phys | 0x00800000;
661
        } else {
662
                info->io_base_phys = 0x30000000;        /* XXX */
663
        }
664
        if ((info->io_base = (int) ioremap(info->io_base_phys, 0x1000)) == 0) {
665
                printk("igafb_init: can't remap %lx[4K]\n", info->io_base_phys);
666
                iounmap((void *)info->frame_buffer);
667
                kfree(info);
668
                return -ENXIO;
669
        }
670
 
671
        /*
672
         * Figure mmap addresses from PCI config space.
673
         * We need two regions: for video memory and for I/O ports.
674
         * Later one can add region for video coprocessor registers.
675
         * However, mmap routine loops until size != 0, so we put
676
         * one additional region with size == 0.
677
         */
678
 
679
        info->mmap_map = kmalloc(4 * sizeof(*info->mmap_map), GFP_ATOMIC);
680
        if (!info->mmap_map) {
681
                printk("igafb_init: can't alloc mmap_map\n");
682
                iounmap((void *)info->io_base);
683
                iounmap(info->frame_buffer);
684
                kfree(info);
685
                return -ENOMEM;
686
        }
687
 
688
        memset(info->mmap_map, 0, 4 * sizeof(*info->mmap_map));
689
 
690
        /*
691
         * Set default vmode and cmode from PROM properties.
692
         */
693
        {
694
                struct pcidev_cookie *cookie = pdev->sysdata;
695
                int node = cookie->prom_node;
696
                int width = prom_getintdefault(node, "width", 1024);
697
                int height = prom_getintdefault(node, "height", 768);
698
                int depth = prom_getintdefault(node, "depth", 8);
699
                switch (width) {
700
                    case 1024:
701
                        if (height == 768)
702
                            default_var = default_var_1024x768;
703
                        break;
704
                    case 1152:
705
                        if (height == 900)
706
                            default_var = default_var_1152x900;
707
                        break;
708
                    case 1280:
709
                        if (height == 1024)
710
                            default_var = default_var_1280x1024;
711
                        break;
712
                    default:
713
                        break;
714
                }
715
 
716
                switch (depth) {
717
                    case 8:
718
                        default_var.bits_per_pixel = 8;
719
                        break;
720
                    case 16:
721
                        default_var.bits_per_pixel = 16;
722
                        break;
723
                    case 24:
724
                        default_var.bits_per_pixel = 24;
725
                        break;
726
                    case 32:
727
                        default_var.bits_per_pixel = 32;
728
                        break;
729
                    default:
730
                        break;
731
                }
732
            }
733
 
734
#endif
735
 
736
        if (!iga_init(info)) {
737
                iounmap((void *)info->io_base);
738
                iounmap(info->frame_buffer);
739
                if (info->mmap_map)
740
                        kfree(info->mmap_map);
741
                kfree(info);
742
        }
743
 
744
#ifdef __sparc__
745
            /*
746
             * Add /dev/fb mmap values.
747
             */
748
 
749
            /* First region is for video memory */
750
            info->mmap_map[0].voff = 0x0;
751
            info->mmap_map[0].poff = info->frame_buffer_phys & PAGE_MASK;
752
            info->mmap_map[0].size = info->total_vram   & PAGE_MASK;
753
            info->mmap_map[0].prot_mask = SRMMU_CACHE;
754
            info->mmap_map[0].prot_flag = SRMMU_WRITE;
755
 
756
            /* Second region is for I/O ports */
757
            info->mmap_map[1].voff = info->frame_buffer_phys & PAGE_MASK;
758
            info->mmap_map[1].poff = info->io_base_phys & PAGE_MASK;
759
            info->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */
760
            info->mmap_map[1].prot_mask = SRMMU_CACHE;
761
            info->mmap_map[1].prot_flag = SRMMU_WRITE;
762
#endif /* __sparc__ */
763
 
764
        return 0;
765
}
766
 
767
int __init igafb_setup(char *options)
768
{
769
    char *this_opt;
770
 
771
    if (!options || !*options)
772
        return 0;
773
 
774
    while ((this_opt = strsep(&options, ",")) != NULL) {
775
        if (!strncmp(this_opt, "font:", 5)) {
776
                char *p;
777
                int i;
778
 
779
                p = this_opt + 5;
780
                for (i = 0; i < sizeof(fontname) - 1; i++)
781
                        if (!*p || *p == ' ' || *p == ',')
782
                                break;
783
                memcpy(fontname, this_opt + 5, i);
784
                fontname[i] = 0;
785
        }
786
    }
787
    return 0;
788
}
789
 
790
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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