2 * linux/drivers/video/igafb.c -- Frame buffer device for IGA 1682
4 * Copyright (C) 1998 Vladimir Roganov and Gleb Raiko
6 * This driver is partly based on the Frame buffer device for ATI Mach64
7 * and partially on VESA-related code.
9 * Copyright (C) 1997-1998 Geert Uytterhoeven
10 * Copyright (C) 1998 Bernd Harries
11 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
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
18 /******************************************************************************
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.
26 Most important thing at this moment is that we have working
27 JavaEngine1 console & X with new console interface.
29 ******************************************************************************/
31 #include <linux/module.h>
32 #include <linux/kernel.h>
33 #include <linux/errno.h>
34 #include <linux/string.h>
36 #include <linux/tty.h>
37 #include <linux/malloc.h>
38 #include <linux/vmalloc.h>
39 #include <linux/delay.h>
40 #include <linux/interrupt.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>
48 #include <linux/vt_kern.h>
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>
65 static char igafb_name
[16] = "IGA 1682";
66 static char fontname
[40] __initdata
= { 0 };
72 unsigned long prot_flag
;
73 unsigned long prot_mask
;
77 struct fb_info fb_info
;
78 unsigned long frame_buffer_phys
;
80 unsigned long io_base_phys
;
81 unsigned long io_base
;
83 struct pci_mmap_map
*mmap_map
;
84 struct { u_short blue
, green
, red
, pad
; } palette
[256];
88 struct display_switch dispsw
;
90 #ifdef FBCON_HAS_CFB16
93 #ifdef FBCON_HAS_CFB24
96 #ifdef FBCON_HAS_CFB32
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
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
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
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
142 * Memory-mapped I/O functions for Sparc PCI
144 * On sparc we happen to access I/O with memory mapped functions too.
146 #define pci_inb(info, reg) readb(info->io_base+(reg))
147 #define pci_outb(info, val, reg) writeb(val, info->io_base+(reg))
149 static inline unsigned int iga_inb(struct fb_info_iga
*info
,
150 unsigned int reg
, unsigned int idx
)
152 pci_outb(info
, idx
, reg
);
153 return pci_inb(info
, reg
+ 1);
156 static inline void iga_outb(struct fb_info_iga
*info
, unsigned char val
,
157 unsigned int reg
, unsigned int idx
)
159 pci_outb(info
, idx
, reg
);
160 pci_outb(info
, val
, reg
+1);
163 #endif /* __sparc__ */
166 * Very important functionality for the JavaEngine1 computer:
167 * make screen border black (usign special IGA registers)
169 static void iga_blank_border(struct fb_info_iga
*info
)
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.
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 */
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.
189 for (i
=0; i
< 3; i
++)
190 iga_outb(info
, 0, IGA_EXT_CNTRL
, IGA_IDX_OVERSCAN_COLOR
+ i
);
195 * Frame buffer device API
198 static int igafb_update_var(int con
, struct fb_info
*info
)
203 static int igafb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
204 struct fb_info
*info
)
206 struct fb_info_iga
*fb
= (struct fb_info_iga
*)info
;
208 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
209 strcpy(fix
->id
, igafb_name
);
211 fix
->smem_start
= (unsigned long) fb
->frame_buffer
;
212 fix
->smem_len
= fb
->total_vram
;
217 fix
->type
= FB_TYPE_PACKED_PIXELS
;
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
;
225 static int igafb_get_var(struct fb_var_screeninfo
*var
, int con
,
226 struct fb_info
*info
)
229 memcpy(var
, &default_var
, sizeof(struct fb_var_screeninfo
));
231 *var
= fb_display
[con
].var
;
235 static int igafb_set_var(struct fb_var_screeninfo
*var
, int con
,
236 struct fb_info
*info
)
238 memcpy(var
, &default_var
, sizeof(struct fb_var_screeninfo
));
243 static int igafb_mmap(struct fb_info
*info
, struct file
*file
,
244 struct vm_area_struct
*vma
)
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;
254 size
= vma
->vm_end
- vma
->vm_start
;
256 /* To stop the swapper from even considering these pages. */
257 vma
->vm_flags
|= (VM_SHM
| VM_LOCKED
);
259 /* Each page, see which map applies */
260 for (page
= 0; page
< size
; ) {
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
;
272 map_size
= fb
->mmap_map
[i
].size
- (offset
- start
);
273 map_offset
= fb
->mmap_map
[i
].poff
+ (offset
- start
);
280 if (page
+ map_size
> size
)
281 map_size
= size
- page
;
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
;
286 if (remap_page_range(vma
->vm_start
+ page
, map_offset
,
287 map_size
, vma
->vm_page_prot
))
296 vma
->vm_flags
|= VM_IO
;
301 if (info
->display_fg
)
302 lastconsole
= info
->display_fg
->vc_num
;
304 if (fb
->consolecnt
&& fb_display
[lastconsole
].fb_info
==info
) {
305 fb
->vtconsole
= lastconsole
;
306 vt_cons
[lastconsole
]->vc_mode
= KD_GRAPHICS
;
311 #endif /* __sparc__ */
314 static int iga_getcolreg(unsigned regno
, unsigned *red
, unsigned *green
,
315 unsigned *blue
, unsigned *transp
,
316 struct fb_info
*fb_info
)
319 * Read a single color register and split it into colors/transparent.
320 * Return != 0 for invalid regno.
322 struct fb_info_iga
*info
= (struct fb_info_iga
*) fb_info
;
324 if (regno
>= info
->video_cmap_len
)
327 *red
= info
->palette
[regno
].red
;
328 *green
= info
->palette
[regno
].green
;
329 *blue
= info
->palette
[regno
].blue
;
334 static int iga_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
335 unsigned blue
, unsigned transp
,
336 struct fb_info
*fb_info
)
339 * Set a single color register. The values supplied are
340 * already rounded down to the hardware's capabilities
341 * (according to the entries in the `var' structure). Return
342 * != 0 for invalid regno.
345 struct fb_info_iga
*info
= (struct fb_info_iga
*) fb_info
;
347 if (regno
>= info
->video_cmap_len
)
350 info
->palette
[regno
].red
= red
;
351 info
->palette
[regno
].green
= green
;
352 info
->palette
[regno
].blue
= blue
;
354 pci_outb(info
, regno
, DAC_W_INDEX
);
355 pci_outb(info
, red
, DAC_DATA
);
356 pci_outb(info
, green
, DAC_DATA
);
357 pci_outb(info
, blue
, DAC_DATA
);
360 switch (default_var
.bits_per_pixel
) {
361 #ifdef FBCON_HAS_CFB16
363 info
->fbcon_cmap
.cfb16
[regno
] =
364 (regno
<< 10) | (regno
<< 5) | regno
;
367 #ifdef FBCON_HAS_CFB24
369 info
->fbcon_cmap
.cfb24
[regno
] =
370 (regno
<< 16) | (regno
<< 8) | regno
;
373 #ifdef FBCON_HAS_CFB32
376 i
= (regno
<< 8) | regno
;
377 info
->fbcon_cmap
.cfb32
[regno
] = (i
<< 16) | i
;
386 static void do_install_cmap(int con
, struct fb_info
*fb_info
)
388 struct fb_info_iga
*info
= (struct fb_info_iga
*) fb_info
;
390 if (con
!= info
->currcon
)
392 if (fb_display
[con
].cmap
.len
)
393 fb_set_cmap(&fb_display
[con
].cmap
, 1,
394 iga_setcolreg
, &info
->fb_info
);
396 fb_set_cmap(fb_default_cmap(info
->video_cmap_len
), 1,
397 iga_setcolreg
, &info
->fb_info
);
400 static int igafb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
401 struct fb_info
*fb_info
)
403 struct fb_info_iga
*info
= (struct fb_info_iga
*) fb_info
;
405 if (con
== info
->currcon
) /* current console? */
406 return fb_get_cmap(cmap
, kspc
, iga_getcolreg
, &info
->fb_info
);
407 else if (fb_display
[con
].cmap
.len
) /* non default colormap? */
408 fb_copy_cmap(&fb_display
[con
].cmap
, cmap
, kspc
? 0 : 2);
410 fb_copy_cmap(fb_default_cmap(info
->video_cmap_len
),
415 static int igafb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
416 struct fb_info
*info
)
419 struct fb_info_iga
*fb
= (struct fb_info_iga
*) info
;
421 if (!fb_display
[con
].cmap
.len
) { /* no colormap allocated? */
422 err
= fb_alloc_cmap(&fb_display
[con
].cmap
,
423 fb
->video_cmap_len
,0);
427 if (con
== fb
->currcon
) /* current console? */
428 return fb_set_cmap(cmap
, kspc
, iga_setcolreg
, info
);
430 fb_copy_cmap(cmap
, &fb_display
[con
].cmap
, kspc
? 0 : 1);
435 * Framebuffer option structure
437 static struct fb_ops igafb_ops
= {
439 fb_get_fix
: igafb_get_fix
,
440 fb_get_var
: igafb_get_var
,
441 fb_set_var
: igafb_set_var
,
442 fb_get_cmap
: igafb_get_cmap
,
443 fb_set_cmap
: igafb_set_cmap
,
449 static void igafb_set_disp(int con
, struct fb_info_iga
*info
)
451 struct fb_fix_screeninfo fix
;
452 struct display
*display
;
453 struct display_switch
*sw
;
456 display
= &fb_display
[con
];
458 display
= &info
->disp
; /* used during initialization */
460 igafb_get_fix(&fix
, con
, &info
->fb_info
);
462 memset(display
, 0, sizeof(struct display
));
463 display
->screen_base
= info
->frame_buffer
;
464 display
->visual
= fix
.visual
;
465 display
->type
= fix
.type
;
466 display
->type_aux
= fix
.type_aux
;
467 display
->ypanstep
= fix
.ypanstep
;
468 display
->ywrapstep
= fix
.ywrapstep
;
469 display
->line_length
= fix
.line_length
;
470 display
->next_line
= fix
.line_length
;
471 display
->can_soft_blank
= 0;
472 display
->inverse
= 0;
473 igafb_get_var(&display
->var
, -1, &info
->fb_info
);
475 switch (default_var
.bits_per_pixel
) {
476 #ifdef FBCON_HAS_CFB8
481 #ifdef FBCON_HAS_CFB16
485 display
->dispsw_data
= info
->fbcon_cmap
.cfb16
;
488 #ifdef FBCON_HAS_CFB24
491 display
->dispsw_data
= info
->fbcon_cmap
.cfb24
;
494 #ifdef FBCON_HAS_CFB32
497 display
->dispsw_data
= info
->fbcon_cmap
.cfb32
;
501 printk(KERN_WARNING
"igafb_set_disp: unknown resolution %d\n",
502 default_var
.bits_per_pixel
);
505 memcpy(&info
->dispsw
, sw
, sizeof(*sw
));
506 display
->dispsw
= &info
->dispsw
;
508 display
->scrollmode
= SCROLL_YREDRAW
;
509 info
->dispsw
.bmove
= fbcon_redraw_bmove
;
512 static int igafb_switch(int con
, struct fb_info
*fb_info
)
514 struct fb_info_iga
*info
= (struct fb_info_iga
*) fb_info
;
516 /* Do we have to save the colormap? */
517 if (fb_display
[info
->currcon
].cmap
.len
)
518 fb_get_cmap(&fb_display
[info
->currcon
].cmap
, 1,
519 iga_getcolreg
, fb_info
);
522 /* Install new colormap */
523 do_install_cmap(con
, fb_info
);
524 igafb_update_var(con
, fb_info
);
530 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
532 static void igafb_blank(int blank
, struct fb_info
*info
)
538 static int __init
iga_init(struct fb_info_iga
*info
)
540 char vramsz
= iga_inb(info
, IGA_EXT_CNTRL
, IGA_IDX_EXT_BUS_CNTL
)
544 info
->total_vram
= 0x100000;
547 info
->total_vram
= 0x200000;
550 case MEM_SIZE_RESERVED
:
551 info
->total_vram
= 0x400000;
555 if (default_var
.bits_per_pixel
> 8) {
556 info
->video_cmap_len
= 16;
558 info
->video_cmap_len
= 256;
562 for (j
= 0; j
< 16; j
++) {
564 info
->palette
[j
].red
= default_red
[k
];
565 info
->palette
[j
].green
= default_grn
[k
];
566 info
->palette
[j
].blue
= default_blu
[k
];
570 strcpy(info
->fb_info
.modename
, igafb_name
);
571 info
->fb_info
.node
= -1;
572 info
->fb_info
.fbops
= &igafb_ops
;
573 info
->fb_info
.disp
= &info
->disp
;
574 strcpy(info
->fb_info
.fontname
, fontname
);
575 info
->fb_info
.changevar
= NULL
;
576 info
->fb_info
.switch_con
= &igafb_switch
;
577 info
->fb_info
.updatevar
= &igafb_update_var
;
578 info
->fb_info
.blank
= &igafb_blank
;
579 info
->fb_info
.flags
=FBINFO_FLAG_DEFAULT
;
581 igafb_set_disp(-1, info
);
583 if (register_framebuffer(&info
->fb_info
) < 0)
586 printk("fb%d: %s frame buffer device at 0x%08lx [%dMB VRAM]\n",
587 GET_FB_IDX(info
->fb_info
.node
), igafb_name
,
588 info
->frame_buffer_phys
, info
->total_vram
>> 20);
590 iga_blank_border(info
);
594 int __init
igafb_init(void)
596 struct pci_dev
*pdev
;
597 struct fb_info_iga
*info
;
599 extern int con_is_present(void);
602 /* Do not attach when we have a serial console. */
603 if (!con_is_present())
606 pdev
= pci_find_device(PCI_VENDOR_ID_INTERG
,
607 PCI_DEVICE_ID_INTERG_1682
, 0);
610 * XXX We tried to use cyber2000fb.c for IGS 2000.
611 * But it does not initialize the chip in JavaStation-E, alas.
613 pdev
= pci_find_device(PCI_VENDOR_ID_INTERG
, 0x2000, 0);
620 info
= kmalloc(sizeof(struct fb_info_iga
), GFP_ATOMIC
);
622 printk("igafb_init: can't alloc fb_info_iga\n");
625 memset(info
, 0, sizeof(struct fb_info_iga
));
627 if ((addr
= pdev
->resource
[0].start
) == 0) {
628 printk("igafb_init: no memory start\n");
633 if ((info
->frame_buffer
= ioremap(addr
, 1024*1024*2)) == 0) {
634 printk("igafb_init: can't remap %lx[2M]\n", addr
);
639 info
->frame_buffer_phys
= addr
& PCI_BASE_ADDRESS_MEM_MASK
;
643 * The following is sparc specific and this is why:
645 * IGS2000 has its I/O memory mapped and we want
646 * to generate memory cycles on PCI, e.g. do ioremap(),
647 * then readb/writeb() as in Documentation/IO-mapping.txt.
649 * IGS1682 is more traditional, it responds to PCI I/O
650 * cycles, so we want to access it with inb()/outb().
652 * On sparc, PCIC converts CPU memory access within
653 * phys window 0x3000xxxx into PCI I/O cycles. Therefore
654 * we may use readb/writeb to access them with IGS1682.
656 * We do not take io_base_phys from resource[n].start
657 * on IGS1682 because that chip is BROKEN. It does not
658 * have a base register for I/O. We just "know" what its
662 info
->io_base_phys
= info
->frame_buffer_phys
| 0x00800000;
664 info
->io_base_phys
= 0x30000000; /* XXX */
666 if ((info
->io_base
= (int) ioremap(info
->io_base_phys
, 0x1000)) == 0) {
667 printk("igafb_init: can't remap %lx[4K]\n", info
->io_base_phys
);
668 iounmap((void *)info
->frame_buffer
);
674 * Figure mmap addresses from PCI config space.
675 * We need two regions: for video memory and for I/O ports.
676 * Later one can add region for video coprocessor registers.
677 * However, mmap routine loops until size != 0, so we put
678 * one additional region with size == 0.
681 info
->mmap_map
= kmalloc(4 * sizeof(*info
->mmap_map
), GFP_ATOMIC
);
682 if (!info
->mmap_map
) {
683 printk("igafb_init: can't alloc mmap_map\n");
684 iounmap((void *)info
->io_base
);
685 iounmap(info
->frame_buffer
);
690 memset(info
->mmap_map
, 0, 4 * sizeof(*info
->mmap_map
));
693 * Set default vmode and cmode from PROM properties.
696 struct pcidev_cookie
*cookie
= pdev
->sysdata
;
697 int node
= cookie
->prom_node
;
698 int width
= prom_getintdefault(node
, "width", 1024);
699 int height
= prom_getintdefault(node
, "height", 768);
700 int depth
= prom_getintdefault(node
, "depth", 8);
704 default_var
= default_var_1024x768
;
708 default_var
= default_var_1152x900
;
712 default_var
= default_var_1280x1024
;
720 default_var
.bits_per_pixel
= 8;
723 default_var
.bits_per_pixel
= 16;
726 default_var
.bits_per_pixel
= 24;
729 default_var
.bits_per_pixel
= 32;
738 if (!iga_init(info
)) {
739 iounmap((void *)info
->io_base
);
740 iounmap(info
->frame_buffer
);
742 kfree(info
->mmap_map
);
748 * Add /dev/fb mmap values.
751 /* First region is for video memory */
752 info
->mmap_map
[0].voff
= 0x0;
753 info
->mmap_map
[0].poff
= info
->frame_buffer_phys
& PAGE_MASK
;
754 info
->mmap_map
[0].size
= info
->total_vram
& PAGE_MASK
;
755 info
->mmap_map
[0].prot_mask
= SRMMU_CACHE
;
756 info
->mmap_map
[0].prot_flag
= SRMMU_WRITE
;
758 /* Second region is for I/O ports */
759 info
->mmap_map
[1].voff
= info
->frame_buffer_phys
& PAGE_MASK
;
760 info
->mmap_map
[1].poff
= info
->io_base_phys
& PAGE_MASK
;
761 info
->mmap_map
[1].size
= PAGE_SIZE
* 2; /* X wants 2 pages */
762 info
->mmap_map
[1].prot_mask
= SRMMU_CACHE
;
763 info
->mmap_map
[1].prot_flag
= SRMMU_WRITE
;
764 #endif /* __sparc__ */
769 int __init
igafb_setup(char *options
)
773 if (!options
|| !*options
)
776 for (this_opt
= strtok(options
, ","); this_opt
;
777 this_opt
= strtok(NULL
, ",")) {
778 if (!strncmp(this_opt
, "font:", 5)) {
783 for (i
= 0; i
< sizeof(fontname
) - 1; i
++)
784 if (!*p
|| *p
== ' ' || *p
== ',')
786 memcpy(fontname
, this_opt
+ 5, i
);