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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [video/] [igafb.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/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/slab.h>
37
#include <linux/vmalloc.h>
38
#include <linux/delay.h>
39
#include <linux/interrupt.h>
40
#include <linux/fb.h>
41
#include <linux/init.h>
42
#include <linux/pci.h>
43
#include <linux/nvram.h>
44
 
45
#include <asm/io.h>
46
 
47
#ifdef CONFIG_SPARC
48
#include <asm/prom.h>
49
#include <asm/pcic.h>
50
#endif
51
 
52
#include <video/iga.h>
53
 
54
struct pci_mmap_map {
55
    unsigned long voff;
56
    unsigned long poff;
57
    unsigned long size;
58
    unsigned long prot_flag;
59
    unsigned long prot_mask;
60
};
61
 
62
struct iga_par {
63
        struct pci_mmap_map *mmap_map;
64
        unsigned long frame_buffer_phys;
65
        unsigned long io_base;
66
};
67
 
68
struct fb_info fb_info;
69
 
70
struct fb_fix_screeninfo igafb_fix __initdata = {
71
        .id             = "IGA 1682",
72
        .type           = FB_TYPE_PACKED_PIXELS,
73
        .mmio_len       = 1000
74
};
75
 
76
struct fb_var_screeninfo default_var = {
77
        /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
78
        .xres           = 640,
79
        .yres           = 480,
80
        .xres_virtual   = 640,
81
        .yres_virtual   = 480,
82
        .bits_per_pixel = 8,
83
        .red            = {0, 8, 0 },
84
        .green          = {0, 8, 0 },
85
        .blue           = {0, 8, 0 },
86
        .height         = -1,
87
        .width          = -1,
88
        .accel_flags    = FB_ACCEL_NONE,
89
        .pixclock       = 39722,
90
        .left_margin    = 48,
91
        .right_margin   = 16,
92
        .upper_margin   = 33,
93
        .lower_margin   = 10,
94
        .hsync_len      = 96,
95
        .vsync_len      = 2,
96
        .vmode          = FB_VMODE_NONINTERLACED
97
};
98
 
99
#ifdef CONFIG_SPARC
100
struct fb_var_screeninfo default_var_1024x768 __initdata = {
101
        /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
102
        .xres           = 1024,
103
        .yres           = 768,
104
        .xres_virtual   = 1024,
105
        .yres_virtual   = 768,
106
        .bits_per_pixel = 8,
107
        .red            = {0, 8, 0 },
108
        .green          = {0, 8, 0 },
109
        .blue           = {0, 8, 0 },
110
        .height         = -1,
111
        .width          = -1,
112
        .accel_flags    = FB_ACCEL_NONE,
113
        .pixclock       = 12699,
114
        .left_margin    = 176,
115
        .right_margin   = 16,
116
        .upper_margin   = 28,
117
        .lower_margin   = 1,
118
        .hsync_len      = 96,
119
        .vsync_len      = 3,
120
        .vmode          = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
121
};
122
 
123
struct fb_var_screeninfo default_var_1152x900 __initdata = {
124
        /* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */
125
        .xres           = 1152,
126
        .yres           = 900,
127
        .xres_virtual   = 1152,
128
        .yres_virtual   = 900,
129
        .bits_per_pixel = 8,
130
        .red            = { 0, 8, 0 },
131
        .green          = { 0, 8, 0 },
132
        .blue           = { 0, 8, 0 },
133
        .height         = -1,
134
        .width          = -1,
135
        .accel_flags    = FB_ACCEL_NONE,
136
        .pixclock       = 9091,
137
        .left_margin    = 234,
138
        .right_margin   = 24,
139
        .upper_margin   = 34,
140
        .lower_margin   = 3,
141
        .hsync_len      = 100,
142
        .vsync_len      = 3,
143
        .vmode          = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
144
};
145
 
146
struct fb_var_screeninfo default_var_1280x1024 __initdata = {
147
        /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
148
        .xres           = 1280,
149
        .yres           = 1024,
150
        .xres_virtual   = 1280,
151
        .yres_virtual   = 1024,
152
        .bits_per_pixel = 8,
153
        .red            = {0, 8, 0 },
154
        .green          = {0, 8, 0 },
155
        .blue           = {0, 8, 0 },
156
        .height         = -1,
157
        .width          = -1,
158
        .accel_flags    = 0,
159
        .pixclock       = 7408,
160
        .left_margin    = 248,
161
        .right_margin   = 16,
162
        .upper_margin   = 38,
163
        .lower_margin   = 1,
164
        .hsync_len      = 144,
165
        .vsync_len      = 3,
166
        .vmode          = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
167
};
168
 
169
/*
170
 *   Memory-mapped I/O functions for Sparc PCI
171
 *
172
 * On sparc we happen to access I/O with memory mapped functions too.
173
 */
174
#define pci_inb(par, reg)        readb(par->io_base+(reg))
175
#define pci_outb(par, val, reg)  writeb(val, par->io_base+(reg))
176
 
177
static inline unsigned int iga_inb(struct iga_par *par, unsigned int reg,
178
                                   unsigned int idx)
179
{
180
        pci_outb(par, idx, reg);
181
        return pci_inb(par, reg + 1);
182
}
183
 
184
static inline void iga_outb(struct iga_par *par, unsigned char val,
185
                            unsigned int reg, unsigned int idx )
186
{
187
        pci_outb(par, idx, reg);
188
        pci_outb(par, val, reg+1);
189
}
190
 
191
#endif /* CONFIG_SPARC */
192
 
193
/*
194
 *  Very important functionality for the JavaEngine1 computer:
195
 *  make screen border black (usign special IGA registers)
196
 */
197
static void iga_blank_border(struct iga_par *par)
198
{
199
        int i;
200
#if 0
201
        /*
202
         * PROM does this for us, so keep this code as a reminder
203
         * about required read from 0x3DA and writing of 0x20 in the end.
204
         */
205
        (void) pci_inb(par, 0x3DA);             /* required for every access */
206
        pci_outb(par, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL);
207
        (void) pci_inb(par, IGA_ATTR_CTL+1);
208
        pci_outb(par, 0x38, IGA_ATTR_CTL);
209
        pci_outb(par, 0x20, IGA_ATTR_CTL);      /* re-enable visual */
210
#endif
211
        /*
212
         * This does not work as it was designed because the overscan
213
         * color is looked up in the palette. Therefore, under X11
214
         * overscan changes color.
215
         */
216
        for (i=0; i < 3; i++)
217
                iga_outb(par, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
218
}
219
 
220
#ifdef CONFIG_SPARC
221
static int igafb_mmap(struct fb_info *info,
222
                      struct vm_area_struct *vma)
223
{
224
        struct iga_par *par = (struct iga_par *)info->par;
225
        unsigned int size, page, map_size = 0;
226
        unsigned long map_offset = 0;
227
        int i;
228
 
229
        if (!par->mmap_map)
230
                return -ENXIO;
231
 
232
        size = vma->vm_end - vma->vm_start;
233
 
234
        /* Each page, see which map applies */
235
        for (page = 0; page < size; ) {
236
                map_size = 0;
237
                for (i = 0; par->mmap_map[i].size; i++) {
238
                        unsigned long start = par->mmap_map[i].voff;
239
                        unsigned long end = start + par->mmap_map[i].size;
240
                        unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page;
241
 
242
                        if (start > offset)
243
                                continue;
244
                        if (offset >= end)
245
                                continue;
246
 
247
                        map_size = par->mmap_map[i].size - (offset - start);
248
                        map_offset = par->mmap_map[i].poff + (offset - start);
249
                        break;
250
                }
251
                if (!map_size) {
252
                        page += PAGE_SIZE;
253
                        continue;
254
                }
255
                if (page + map_size > size)
256
                        map_size = size - page;
257
 
258
                pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask);
259
                pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
260
 
261
                if (remap_pfn_range(vma, vma->vm_start + page,
262
                        map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))
263
                        return -EAGAIN;
264
 
265
                page += map_size;
266
        }
267
 
268
        if (!map_size)
269
                return -EINVAL;
270
 
271
        vma->vm_flags |= VM_IO;
272
        return 0;
273
}
274
#endif /* CONFIG_SPARC */
275
 
276
static int igafb_setcolreg(unsigned regno, unsigned red, unsigned green,
277
                           unsigned blue, unsigned transp,
278
                           struct fb_info *info)
279
{
280
        /*
281
         *  Set a single color register. The values supplied are
282
         *  already rounded down to the hardware's capabilities
283
         *  (according to the entries in the `var' structure). Return
284
         *  != 0 for invalid regno.
285
         */
286
        struct iga_par *par = (struct iga_par *)info->par;
287
 
288
        if (regno >= info->cmap.len)
289
                return 1;
290
 
291
        pci_outb(par, regno, DAC_W_INDEX);
292
        pci_outb(par, red,   DAC_DATA);
293
        pci_outb(par, green, DAC_DATA);
294
        pci_outb(par, blue,  DAC_DATA);
295
 
296
        if (regno < 16) {
297
                switch (info->var.bits_per_pixel) {
298
                case 16:
299
                        ((u16*)(info->pseudo_palette))[regno] =
300
                                (regno << 10) | (regno << 5) | regno;
301
                        break;
302
                case 24:
303
                        ((u32*)(info->pseudo_palette))[regno] =
304
                                (regno << 16) | (regno << 8) | regno;
305
                break;
306
                case 32:
307
                        { int i;
308
                        i = (regno << 8) | regno;
309
                        ((u32*)(info->pseudo_palette))[regno] = (i << 16) | i;
310
                        }
311
                        break;
312
                }
313
        }
314
        return 0;
315
}
316
 
317
/*
318
 * Framebuffer option structure
319
 */
320
static struct fb_ops igafb_ops = {
321
        .owner          = THIS_MODULE,
322
        .fb_setcolreg   = igafb_setcolreg,
323
        .fb_fillrect    = cfb_fillrect,
324
        .fb_copyarea    = cfb_copyarea,
325
        .fb_imageblit   = cfb_imageblit,
326
#ifdef CONFIG_SPARC
327
        .fb_mmap        = igafb_mmap,
328
#endif
329
};
330
 
331
static int __init iga_init(struct fb_info *info, struct iga_par *par)
332
{
333
        char vramsz = iga_inb(par, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL)
334
                                                         & MEM_SIZE_ALIAS;
335
        int video_cmap_len;
336
 
337
        switch (vramsz) {
338
        case MEM_SIZE_1M:
339
                info->fix.smem_len = 0x100000;
340
                break;
341
        case MEM_SIZE_2M:
342
                info->fix.smem_len = 0x200000;
343
                break;
344
        case MEM_SIZE_4M:
345
        case MEM_SIZE_RESERVED:
346
                info->fix.smem_len = 0x400000;
347
                break;
348
        }
349
 
350
        if (info->var.bits_per_pixel > 8)
351
                video_cmap_len = 16;
352
        else
353
                video_cmap_len = 256;
354
 
355
        info->fbops = &igafb_ops;
356
        info->flags = FBINFO_DEFAULT;
357
 
358
        fb_alloc_cmap(&info->cmap, video_cmap_len, 0);
359
 
360
        if (register_framebuffer(info) < 0)
361
                return 0;
362
 
363
        printk("fb%d: %s frame buffer device at 0x%08lx [%dMB VRAM]\n",
364
               info->node, info->fix.id,
365
               par->frame_buffer_phys, info->fix.smem_len >> 20);
366
 
367
        iga_blank_border(par);
368
        return 1;
369
}
370
 
371
int __init igafb_init(void)
372
{
373
        struct fb_info *info;
374
        struct pci_dev *pdev;
375
        struct iga_par *par;
376
        unsigned long addr;
377
        int size, iga2000 = 0;
378
 
379
        if (fb_get_options("igafb", NULL))
380
                return -ENODEV;
381
 
382
        pdev = pci_get_device(PCI_VENDOR_ID_INTERG,
383
                               PCI_DEVICE_ID_INTERG_1682, 0);
384
        if (pdev == NULL) {
385
                /*
386
                 * XXX We tried to use cyber2000fb.c for IGS 2000.
387
                 * But it does not initialize the chip in JavaStation-E, alas.
388
                 */
389
                pdev = pci_get_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
390
                if(pdev == NULL) {
391
                        return -ENXIO;
392
                }
393
                iga2000 = 1;
394
        }
395
        /* We leak a reference here but as it cannot be unloaded this is
396
           fine. If you write unload code remember to free it in unload */
397
 
398
        size = sizeof(struct fb_info) + sizeof(struct iga_par) + sizeof(u32)*16;
399
 
400
        info = kzalloc(size, GFP_ATOMIC);
401
        if (!info) {
402
                printk("igafb_init: can't alloc fb_info\n");
403
                return -ENOMEM;
404
        }
405
 
406
        par = (struct iga_par *) (info + 1);
407
 
408
 
409
        if ((addr = pdev->resource[0].start) == 0) {
410
                printk("igafb_init: no memory start\n");
411
                kfree(info);
412
                return -ENXIO;
413
        }
414
 
415
        if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) {
416
                printk("igafb_init: can't remap %lx[2M]\n", addr);
417
                kfree(info);
418
                return -ENXIO;
419
        }
420
 
421
        par->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
422
 
423
#ifdef CONFIG_SPARC
424
        /*
425
         * The following is sparc specific and this is why:
426
         *
427
         * IGS2000 has its I/O memory mapped and we want
428
         * to generate memory cycles on PCI, e.g. do ioremap(),
429
         * then readb/writeb() as in Documentation/IO-mapping.txt.
430
         *
431
         * IGS1682 is more traditional, it responds to PCI I/O
432
         * cycles, so we want to access it with inb()/outb().
433
         *
434
         * On sparc, PCIC converts CPU memory access within
435
         * phys window 0x3000xxxx into PCI I/O cycles. Therefore
436
         * we may use readb/writeb to access them with IGS1682.
437
         *
438
         * We do not take io_base_phys from resource[n].start
439
         * on IGS1682 because that chip is BROKEN. It does not
440
         * have a base register for I/O. We just "know" what its
441
         * I/O addresses are.
442
         */
443
        if (iga2000) {
444
                igafb_fix.mmio_start = par->frame_buffer_phys | 0x00800000;
445
        } else {
446
                igafb_fix.mmio_start = 0x30000000;      /* XXX */
447
        }
448
        if ((par->io_base = (int) ioremap(igafb_fix.mmio_start, igafb_fix.smem_len)) == 0) {
449
                printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start);
450
                iounmap((void *)info->screen_base);
451
                kfree(info);
452
                return -ENXIO;
453
        }
454
 
455
        /*
456
         * Figure mmap addresses from PCI config space.
457
         * We need two regions: for video memory and for I/O ports.
458
         * Later one can add region for video coprocessor registers.
459
         * However, mmap routine loops until size != 0, so we put
460
         * one additional region with size == 0.
461
         */
462
 
463
        par->mmap_map = kzalloc(4 * sizeof(*par->mmap_map), GFP_ATOMIC);
464
        if (!par->mmap_map) {
465
                printk("igafb_init: can't alloc mmap_map\n");
466
                iounmap((void *)par->io_base);
467
                iounmap(info->screen_base);
468
                kfree(info);
469
                return -ENOMEM;
470
        }
471
 
472
        /*
473
         * Set default vmode and cmode from PROM properties.
474
         */
475
        {
476
                struct device_node *dp = pci_device_to_OF_node(pdev);
477
                int node = dp->node;
478
                int width = prom_getintdefault(node, "width", 1024);
479
                int height = prom_getintdefault(node, "height", 768);
480
                int depth = prom_getintdefault(node, "depth", 8);
481
                switch (width) {
482
                    case 1024:
483
                        if (height == 768)
484
                            default_var = default_var_1024x768;
485
                        break;
486
                    case 1152:
487
                        if (height == 900)
488
                            default_var = default_var_1152x900;
489
                        break;
490
                    case 1280:
491
                        if (height == 1024)
492
                            default_var = default_var_1280x1024;
493
                        break;
494
                    default:
495
                        break;
496
                }
497
 
498
                switch (depth) {
499
                    case 8:
500
                        default_var.bits_per_pixel = 8;
501
                        break;
502
                    case 16:
503
                        default_var.bits_per_pixel = 16;
504
                        break;
505
                    case 24:
506
                        default_var.bits_per_pixel = 24;
507
                        break;
508
                    case 32:
509
                        default_var.bits_per_pixel = 32;
510
                        break;
511
                    default:
512
                        break;
513
                }
514
            }
515
 
516
#endif
517
        igafb_fix.smem_start = (unsigned long) info->screen_base;
518
        igafb_fix.line_length = default_var.xres*(default_var.bits_per_pixel/8);
519
        igafb_fix.visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
520
 
521
        info->var = default_var;
522
        info->fix = igafb_fix;
523
        info->pseudo_palette = (void *)(par + 1);
524
        info->device = &pdev->dev;
525
 
526
        if (!iga_init(info, par)) {
527
                iounmap((void *)par->io_base);
528
                iounmap(info->screen_base);
529
                kfree(par->mmap_map);
530
                kfree(info);
531
        }
532
 
533
#ifdef CONFIG_SPARC
534
            /*
535
             * Add /dev/fb mmap values.
536
             */
537
 
538
            /* First region is for video memory */
539
            par->mmap_map[0].voff = 0x0;
540
            par->mmap_map[0].poff = par->frame_buffer_phys & PAGE_MASK;
541
            par->mmap_map[0].size = info->fix.smem_len & PAGE_MASK;
542
            par->mmap_map[0].prot_mask = SRMMU_CACHE;
543
            par->mmap_map[0].prot_flag = SRMMU_WRITE;
544
 
545
            /* Second region is for I/O ports */
546
            par->mmap_map[1].voff = par->frame_buffer_phys & PAGE_MASK;
547
            par->mmap_map[1].poff = info->fix.smem_start & PAGE_MASK;
548
            par->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */
549
            par->mmap_map[1].prot_mask = SRMMU_CACHE;
550
            par->mmap_map[1].prot_flag = SRMMU_WRITE;
551
#endif /* CONFIG_SPARC */
552
 
553
        return 0;
554
}
555
 
556
int __init igafb_setup(char *options)
557
{
558
    char *this_opt;
559
 
560
    if (!options || !*options)
561
        return 0;
562
 
563
    while ((this_opt = strsep(&options, ",")) != NULL) {
564
    }
565
    return 0;
566
}
567
 
568
module_init(igafb_init);
569
MODULE_LICENSE("GPL");
570
static struct pci_device_id igafb_pci_tbl[] __devinitdata = {
571
        { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
572
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
573
        { }
574
};
575
 
576
MODULE_DEVICE_TABLE(pci, igafb_pci_tbl);

powered by: WebSVN 2.1.0

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