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/slab.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))
299 if (info->display_fg)
300 lastconsole = info->display_fg->vc_num;
302 if (fb->consolecnt && fb_display[lastconsole].fb_info ==info) {
303 fb->vtconsole = lastconsole;
304 vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
309 #endif /* __sparc__ */
312 static int iga_getcolreg(unsigned regno, unsigned *red, unsigned *green,
313 unsigned *blue, unsigned *transp,
314 struct fb_info *fb_info)
317 * Read a single color register and split it into colors/transparent.
318 * Return != 0 for invalid regno.
320 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
322 if (regno >= info->video_cmap_len)
325 *red = info->palette[regno].red;
326 *green = info->palette[regno].green;
327 *blue = info->palette[regno].blue;
332 static int iga_setcolreg(unsigned regno, unsigned red, unsigned green,
333 unsigned blue, unsigned transp,
334 struct fb_info *fb_info)
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.
343 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
345 if (regno >= info->video_cmap_len)
348 info->palette[regno].red = red;
349 info->palette[regno].green = green;
350 info->palette[regno].blue = blue;
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);
358 switch (default_var.bits_per_pixel) {
359 #ifdef FBCON_HAS_CFB16
361 info->fbcon_cmap.cfb16[regno] =
362 (regno << 10) | (regno << 5) | regno;
365 #ifdef FBCON_HAS_CFB24
367 info->fbcon_cmap.cfb24[regno] =
368 (regno << 16) | (regno << 8) | regno;
371 #ifdef FBCON_HAS_CFB32
374 i = (regno << 8) | regno;
375 info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
384 static void do_install_cmap(int con, struct fb_info *fb_info)
386 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
388 if (con != info->currcon)
390 if (fb_display[con].cmap.len)
391 fb_set_cmap(&fb_display[con].cmap, 1,
392 iga_setcolreg, &info->fb_info);
394 fb_set_cmap(fb_default_cmap(info->video_cmap_len), 1,
395 iga_setcolreg, &info->fb_info);
398 static int igafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
399 struct fb_info *fb_info)
401 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
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);
408 fb_copy_cmap(fb_default_cmap(info->video_cmap_len),
413 static int igafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
414 struct fb_info *info)
417 struct fb_info_iga *fb = (struct fb_info_iga*) info;
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);
425 if (con == fb->currcon) /* current console? */
426 return fb_set_cmap(cmap, kspc, iga_setcolreg, info);
428 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
433 * Framebuffer option structure
435 static struct fb_ops igafb_ops = {
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,
447 static void igafb_set_disp(int con, struct fb_info_iga *info)
449 struct fb_fix_screeninfo fix;
450 struct display *display;
451 struct display_switch *sw;
454 display = &fb_display[con];
456 display = &info->disp; /* used during initialization */
458 igafb_get_fix(&fix, con, &info->fb_info);
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);
473 switch (default_var.bits_per_pixel) {
474 #ifdef FBCON_HAS_CFB8
479 #ifdef FBCON_HAS_CFB16
483 display->dispsw_data = info->fbcon_cmap.cfb16;
486 #ifdef FBCON_HAS_CFB24
489 display->dispsw_data = info->fbcon_cmap.cfb24;
492 #ifdef FBCON_HAS_CFB32
495 display->dispsw_data = info->fbcon_cmap.cfb32;
499 printk(KERN_WARNING "igafb_set_disp: unknown resolution %d\n",
500 default_var.bits_per_pixel);
503 memcpy(&info->dispsw, sw, sizeof(*sw));
504 display->dispsw = &info->dispsw;
506 display->scrollmode = SCROLL_YREDRAW;
507 info->dispsw.bmove = fbcon_redraw_bmove;
510 static int igafb_switch(int con, struct fb_info *fb_info)
512 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
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);
520 /* Install new colormap */
521 do_install_cmap(con, fb_info);
522 igafb_update_var(con, fb_info);
528 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
530 static void igafb_blank(int blank, struct fb_info *info)
536 static int __init iga_init(struct fb_info_iga *info)
538 char vramsz = iga_inb(info, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL)
542 info->total_vram = 0x100000;
545 info->total_vram = 0x200000;
548 case MEM_SIZE_RESERVED:
549 info->total_vram = 0x400000;
553 if (default_var.bits_per_pixel > 8) {
554 info->video_cmap_len = 16;
556 info->video_cmap_len = 256;
560 for (j = 0; j < 16; 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];
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;
579 igafb_set_disp(-1, info);
581 if (register_framebuffer(&info->fb_info) < 0)
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);
588 iga_blank_border(info);
592 int __init igafb_init(void)
594 struct pci_dev *pdev;
595 struct fb_info_iga *info;
597 extern int con_is_present(void);
600 /* Do not attach when we have a serial console. */
601 if (!con_is_present())
604 pdev = pci_find_device(PCI_VENDOR_ID_INTERG,
605 PCI_DEVICE_ID_INTERG_1682, 0);
608 * XXX We tried to use cyber2000fb.c for IGS 2000.
609 * But it does not initialize the chip in JavaStation-E, alas.
611 pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
618 info = kmalloc(sizeof(struct fb_info_iga), GFP_ATOMIC);
620 printk("igafb_init: can't alloc fb_info_iga\n");
623 memset(info, 0, sizeof(struct fb_info_iga));
625 if ((addr = pdev->resource[0].start) == 0) {
626 printk("igafb_init: no memory start\n");
631 if ((info->frame_buffer = ioremap(addr, 1024*1024*2)) == 0) {
632 printk("igafb_init: can't remap %lx[2M]\n", addr);
637 info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
641 * The following is sparc specific and this is why:
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.
647 * IGS1682 is more traditional, it responds to PCI I/O
648 * cycles, so we want to access it with inb()/outb().
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.
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
660 info->io_base_phys = info->frame_buffer_phys | 0x00800000;
662 info->io_base_phys = 0x30000000; /* XXX */
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);
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.
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);
688 memset(info->mmap_map, 0, 4 * sizeof(*info->mmap_map));
691 * Set default vmode and cmode from PROM properties.
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);
702 default_var = default_var_1024x768;
706 default_var = default_var_1152x900;
710 default_var = default_var_1280x1024;
718 default_var.bits_per_pixel = 8;
721 default_var.bits_per_pixel = 16;
724 default_var.bits_per_pixel = 24;
727 default_var.bits_per_pixel = 32;
736 if (!iga_init(info)) {
737 iounmap((void *)info->io_base);
738 iounmap(info->frame_buffer);
740 kfree(info->mmap_map);
746 * Add /dev/fb mmap values.
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;
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__ */
767 int __init igafb_setup(char *options)
771 if (!options || !*options)
774 while ((this_opt = strsep(&options, ",")) != NULL) {
775 if (!strncmp(this_opt, "font:", 5)) {
780 for (i = 0; i < sizeof(fontname) - 1; i++)
781 if (!*p || *p == ' ' || *p == ',')
783 memcpy(fontname, this_opt + 5, i);
790 MODULE_LICENSE("GPL");