Import 2.3.18pre1
[davej-history.git] / drivers / video / igafb.c
blob5ed528af2395adb9d584521226af8f894adf3b89
1 /*
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
15 * more details.
18 /******************************************************************************
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.
26 (Anyone to help with this?)
28 Most important thing at this moment is that we have working
29 JavaEngine1 console & X with new console interface.
31 ******************************************************************************/
33 #include <linux/module.h>
34 #include <linux/kernel.h>
35 #include <linux/errno.h>
36 #include <linux/string.h>
37 #include <linux/mm.h>
38 #include <linux/tty.h>
39 #include <linux/malloc.h>
40 #include <linux/vmalloc.h>
41 #include <linux/delay.h>
42 #include <linux/interrupt.h>
43 #include <linux/fb.h>
44 #include <linux/selection.h>
45 #include <linux/console.h>
46 #include <linux/init.h>
47 #include <linux/pci.h>
48 #include <linux/nvram.h>
49 #include <linux/kd.h>
50 #include <linux/vt_kern.h>
52 #include <asm/io.h>
54 #ifdef __sparc__
55 #include <asm/pbm.h>
56 #include <asm/pcic.h>
57 #endif
59 #include <video/fbcon.h>
60 #include <video/fbcon-cfb8.h>
61 #include <video/fbcon-cfb16.h>
62 #include <video/fbcon-cfb24.h>
63 #include <video/fbcon-cfb32.h>
65 #include "iga.h"
67 static char igafb_name[16] = "IGA 1682";
68 static char fontname[40] __initdata = { 0 };
70 struct pci_mmap_map {
71 unsigned long voff;
72 unsigned long poff;
73 unsigned long size;
74 unsigned long prot_flag;
75 unsigned long prot_mask;
78 struct fb_info_iga {
79 struct fb_info fb_info;
80 unsigned long frame_buffer_phys;
81 unsigned long frame_buffer;
82 unsigned long io_base_phys;
83 unsigned long io_base;
84 u32 total_vram;
85 struct pci_mmap_map *mmap_map;
86 struct { u_short blue, green, red, pad; } palette[256];
87 int video_cmap_len;
88 int currcon;
89 struct display disp;
90 struct display_switch dispsw;
91 union {
92 #ifdef FBCON_HAS_CFB16
93 u16 cfb16[16];
94 #endif
95 #ifdef FBCON_HAS_CFB24
96 u32 cfb24[16];
97 #endif
98 #ifdef FBCON_HAS_CFB32
99 u32 cfb32[16];
100 #endif
101 } fbcon_cmap;
102 #ifdef __sparc__
103 u8 open;
104 u8 mmaped;
105 int vtconsole;
106 int consolecnt;
107 #endif
110 struct fb_var_screeninfo default_var = {
111 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
112 640, 480, 640, 480, 0, 0, 8, 0,
113 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
114 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
115 0, FB_VMODE_NONINTERLACED
118 #ifdef __sparc__
119 struct fb_var_screeninfo default_var_1024x768 __initdata = {
120 /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
121 1024, 768, 1024, 768, 0, 0, 8, 0,
122 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
123 0, 0, -1, -1, 0, 12699, 176, 16, 28, 1, 96, 3,
124 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
127 struct fb_var_screeninfo default_var_1152x900 __initdata = {
128 /* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */
129 1152, 900, 1152, 900, 0, 0, 8, 0,
130 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
131 0, 0, -1, -1, 0, 9091, 234, 24, 34, 3, 100, 3,
132 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
135 struct fb_var_screeninfo default_var_1280x1024 __initdata = {
136 /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
137 1280, 1024, 1280, 1024, 0, 0, 8, 0,
138 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
139 0, 0, -1, -1, 0, 7408, 248, 16, 38, 1, 144, 3,
140 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
144 * Memory-mapped I/O functions for Sparc PCI
146 static inline unsigned char pci_inb (struct fb_info_iga *info,
147 unsigned int reg)
149 return *(volatile unsigned char*)(info->io_base + reg);
151 static inline void pci_outb (struct fb_info_iga *info, unsigned char c,
152 unsigned int reg)
154 *(volatile unsigned char*)(info->io_base + reg) = c;
156 static inline unsigned int iga_inb(struct fb_info_iga *info,
157 unsigned int reg, unsigned int idx )
159 pci_outb(info, idx, reg);
160 return pci_inb(info, reg + 1);
162 static inline void iga_outb(struct fb_info_iga *info, unsigned char val,
163 unsigned int reg, unsigned int idx )
165 pci_outb(info, idx, reg);
166 pci_outb(info, val, reg+1);
169 #endif /* __sparc__ */
172 * Very important functionality for the JavaEngine1 computer:
173 * make screen border black (usign special IGA registers)
175 static void iga_blank_border(struct fb_info_iga *info)
177 int i;
179 for (i=0; i < 3; i++)
180 iga_outb(info, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
185 * Frame buffer device API
189 * Open/Release the frame buffer device
192 static int igafb_open(struct fb_info *info, int user)
195 * Nothing, only a usage count for the moment
197 MOD_INC_USE_COUNT;
198 return(0);
201 static int igafb_release(struct fb_info *info, int user)
203 MOD_DEC_USE_COUNT;
204 return(0);
207 static int igafb_update_var(int con, struct fb_info *info)
209 return 0;
212 static int igafb_get_fix(struct fb_fix_screeninfo *fix, int con,
213 struct fb_info *info)
215 struct fb_info_iga *fb = (struct fb_info_iga*)info;
217 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
218 strcpy(fix->id, igafb_name);
220 fix->smem_start = fb->frame_buffer;
221 fix->smem_len = fb->total_vram;
222 fix->xpanstep = 0;
223 fix->ypanstep = 0;
224 fix->ywrapstep = 0;
226 fix->type = FB_TYPE_PACKED_PIXELS;
227 fix->type_aux = 0;
228 fix->line_length = default_var.xres * (default_var.bits_per_pixel/8);
229 fix->visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR
230 : FB_VISUAL_DIRECTCOLOR;
231 return 0;
234 static int igafb_get_var(struct fb_var_screeninfo *var, int con,
235 struct fb_info *info)
237 if(con == -1)
238 memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
239 else
240 *var = fb_display[con].var;
241 return 0;
244 static int igafb_set_var(struct fb_var_screeninfo *var, int con,
245 struct fb_info *info)
247 memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
248 return 0;
251 #ifdef __sparc__
252 static int igafb_mmap(struct fb_info *info, struct file *file,
253 struct vm_area_struct *vma)
255 struct fb_info_iga *fb = (struct fb_info_iga *)info;
256 unsigned int size, page, map_size = 0;
257 unsigned long map_offset = 0;
258 int i;
260 if (!fb->mmap_map)
261 return -ENXIO;
263 size = vma->vm_end - vma->vm_start;
264 if (vma->vm_offset & ~PAGE_MASK)
265 return -ENXIO;
267 /* To stop the swapper from even considering these pages. */
268 vma->vm_flags |= (VM_SHM | VM_LOCKED);
270 /* Each page, see which map applies */
271 for (page = 0; page < size; ) {
272 map_size = 0;
273 for (i = 0; fb->mmap_map[i].size; i++) {
274 unsigned long start = fb->mmap_map[i].voff;
275 unsigned long end = start + fb->mmap_map[i].size;
276 unsigned long offset = vma->vm_offset + page;
278 if (start > offset)
279 continue;
280 if (offset >= end)
281 continue;
283 map_size = fb->mmap_map[i].size - (offset - start);
284 map_offset = fb->mmap_map[i].poff + (offset - start);
285 break;
287 if (!map_size) {
288 page += PAGE_SIZE;
289 continue;
291 if (page + map_size > size)
292 map_size = size - page;
294 pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
295 pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
297 if (remap_page_range(vma->vm_start + page, map_offset,
298 map_size, vma->vm_page_prot))
299 return -EAGAIN;
301 page += map_size;
304 if (!map_size)
305 return -EINVAL;
307 vma->vm_flags |= VM_IO;
309 if (!fb->mmaped) {
310 int lastconsole = 0;
312 if (info->display_fg)
313 lastconsole = info->display_fg->vc_num;
314 fb->mmaped = 1;
315 if (fb->consolecnt && fb_display[lastconsole].fb_info ==info) {
316 fb->vtconsole = lastconsole;
317 vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
320 return 0;
322 #endif /* __sparc__ */
325 static int iga_getcolreg(unsigned regno, unsigned *red, unsigned *green,
326 unsigned *blue, unsigned *transp,
327 struct fb_info *fb_info)
330 * Read a single color register and split it into colors/transparent.
331 * Return != 0 for invalid regno.
333 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
335 if (regno >= info->video_cmap_len)
336 return 1;
338 *red = info->palette[regno].red;
339 *green = info->palette[regno].green;
340 *blue = info->palette[regno].blue;
341 *transp = 0;
342 return 0;
345 static int iga_setcolreg(unsigned regno, unsigned red, unsigned green,
346 unsigned blue, unsigned transp,
347 struct fb_info *fb_info)
350 * Set a single color register. The values supplied are
351 * already rounded down to the hardware's capabilities
352 * (according to the entries in the `var' structure). Return
353 * != 0 for invalid regno.
356 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
358 if (regno >= info->video_cmap_len)
359 return 1;
361 info->palette[regno].red = red;
362 info->palette[regno].green = green;
363 info->palette[regno].blue = blue;
365 pci_outb(info, regno, DAC_W_INDEX);
366 pci_outb(info, red, DAC_DATA);
367 pci_outb(info, green, DAC_DATA);
368 pci_outb(info, blue, DAC_DATA);
370 if (regno << 16)
371 switch (default_var.bits_per_pixel) {
372 #ifdef FBCON_HAS_CFB16
373 case 16:
374 info->fbcon_cmap.cfb16[regno] =
375 (regno << 10) | (regno << 5) | regno;
376 break;
377 #endif
378 #ifdef FBCON_HAS_CFB24
379 case 24:
380 info->fbcon_cmap.cfb24[regno] =
381 (regno << 16) | (regno << 8) | regno;
382 break;
383 #endif
384 #ifdef FBCON_HAS_CFB32
385 case 32:
386 i = (regno << 8) | regno;
387 info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
388 break;
389 #endif
391 return 0;
394 static void do_install_cmap(int con, struct fb_info *fb_info)
396 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
398 if (con != info->currcon)
399 return;
400 if (fb_display[con].cmap.len)
401 fb_set_cmap(&fb_display[con].cmap, 1,
402 iga_setcolreg, &info->fb_info);
403 else
404 fb_set_cmap(fb_default_cmap(info->video_cmap_len), 1,
405 iga_setcolreg, &info->fb_info);
408 static int igafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
409 struct fb_info *fb_info)
411 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
413 if (con == info->currcon) /* current console? */
414 return fb_get_cmap(cmap, kspc, iga_getcolreg, &info->fb_info);
415 else if (fb_display[con].cmap.len) /* non default colormap? */
416 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
417 else
418 fb_copy_cmap(fb_default_cmap(info->video_cmap_len),
419 cmap, kspc ? 0 : 2);
420 return 0;
423 static int igafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
424 struct fb_info *info)
426 int err;
427 struct fb_info_iga *fb = (struct fb_info_iga*) info;
429 if (!fb_display[con].cmap.len) { /* no colormap allocated? */
430 err = fb_alloc_cmap(&fb_display[con].cmap,
431 fb->video_cmap_len,0);
432 if (err)
433 return err;
435 if (con == fb->currcon) /* current console? */
436 return fb_set_cmap(cmap, kspc, iga_setcolreg, info);
437 else
438 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
439 return 0;
442 static int igafb_pan_display(struct fb_var_screeninfo *var, int con,
443 struct fb_info *info)
445 /* no panning */
446 return -EINVAL;
449 static int igafb_ioctl(struct inode *inode, struct file *file, u_int cmd,
450 u_long arg, int con, struct fb_info *info)
452 return -EINVAL;
456 * Framebuffer option structure
458 static struct fb_ops igafb_ops = {
459 igafb_open,
460 igafb_release,
461 igafb_get_fix,
462 igafb_get_var,
463 igafb_set_var,
464 igafb_get_cmap,
465 igafb_set_cmap,
466 igafb_pan_display,
467 igafb_ioctl,
468 #ifdef __sparc__
469 igafb_mmap
470 #else
471 NULL
472 #endif
475 static void igafb_set_disp(int con, struct fb_info_iga *info)
477 struct fb_fix_screeninfo fix;
478 struct display *display;
479 struct display_switch *sw;
481 if (con >= 0)
482 display = &fb_display[con];
483 else
484 display = &info->disp; /* used during initialization */
486 igafb_get_fix(&fix, con, &info->fb_info);
488 memset(display, 0, sizeof(struct display));
489 display->screen_base = (char*)info->frame_buffer;
490 display->visual = fix.visual;
491 display->type = fix.type;
492 display->type_aux = fix.type_aux;
493 display->ypanstep = fix.ypanstep;
494 display->ywrapstep = fix.ywrapstep;
495 display->line_length = fix.line_length;
496 display->next_line = fix.line_length;
497 display->can_soft_blank = 0;
498 display->inverse = 0;
499 igafb_get_var(&display->var, -1, &info->fb_info);
501 switch (default_var.bits_per_pixel) {
502 #ifdef FBCON_HAS_CFB8
503 case 8:
504 sw = &fbcon_cfb8;
505 break;
506 #endif
507 #ifdef FBCON_HAS_CFB16
508 case 15:
509 case 16:
510 sw = &fbcon_cfb16;
511 display->dispsw_data = fbcon_cmap.cfb16;
512 break;
513 #endif
514 #ifdef FBCON_HAS_CFB24
515 case 24:
516 sw = &fbcon_cfb24;
517 display->dispsw_data = fbcon_cmap.cfb24;
518 break;
519 #endif
520 #ifdef FBCON_HAS_CFB32
521 case 32:
522 sw = &fbcon_cfb32;
523 display->dispsw_data = fbcon_cmap.cfb32;
524 break;
525 #endif
526 default:
527 return;
529 memcpy(&info->dispsw, sw, sizeof(*sw));
530 display->dispsw = &info->dispsw;
532 display->scrollmode = SCROLL_YREDRAW;
533 info->dispsw.bmove = fbcon_redraw_bmove;
536 static int igafb_switch(int con, struct fb_info *fb_info)
538 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
540 /* Do we have to save the colormap? */
541 if (fb_display[info->currcon].cmap.len)
542 fb_get_cmap(&fb_display[info->currcon].cmap, 1,
543 iga_getcolreg, fb_info);
545 info->currcon = con;
546 /* Install new colormap */
547 do_install_cmap(con, fb_info);
548 igafb_update_var(con, fb_info);
549 return 1;
554 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
556 static void igafb_blank(int blank, struct fb_info *info)
558 /* Not supported */
562 static int __init iga_init(struct fb_info_iga *info)
564 char vramsz = iga_inb(info, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL)
565 & MEM_SIZE_ALIAS;
566 switch (vramsz) {
567 case MEM_SIZE_1M:
568 info->total_vram = 0x100000;
569 break;
570 case MEM_SIZE_2M:
571 info->total_vram = 0x200000;
572 break;
573 case MEM_SIZE_4M:
574 case MEM_SIZE_RESERVED:
575 info->total_vram = 0x400000;
576 break;
579 if (default_var.bits_per_pixel > 8) {
580 info->video_cmap_len = 16;
581 } else {
582 int i, j;
583 for(i = 0; i < 16; i++) {
584 j = color_table[i];
585 info->palette[i].red = default_red[j];
586 info->palette[i].green = default_grn[j];
587 info->palette[i].blue = default_blu[j];
589 info->video_cmap_len = 256;
592 strcpy(info->fb_info.modename, igafb_name);
593 info->fb_info.node = -1;
594 info->fb_info.fbops = &igafb_ops;
595 info->fb_info.disp = &info->disp;
596 strcpy(info->fb_info.fontname, fontname);
597 info->fb_info.changevar = NULL;
598 info->fb_info.switch_con = &igafb_switch;
599 info->fb_info.updatevar = &igafb_update_var;
600 info->fb_info.blank = &igafb_blank;
601 info->fb_info.flags=FBINFO_FLAG_DEFAULT;
604 int j, k;
605 for (j = 0; j < 16; j++) {
606 k = color_table[j];
607 info->palette[j].red = default_red[k];
608 info->palette[j].green = default_grn[k];
609 info->palette[j].blue = default_blu[k];
613 igafb_set_disp(-1, info);
615 if (register_framebuffer(&info->fb_info) < 0)
616 return 0;
618 printk("fb%d: %s frame buffer device at 0x%08lx [%dMB VRAM]\n",
619 GET_FB_IDX(info->fb_info.node), igafb_name,
620 info->frame_buffer_phys, info->total_vram >> 20);
622 iga_blank_border(info);
623 return 1;
627 int __init igafb_init(void)
629 struct pci_dev *pdev;
630 struct fb_info_iga *info;
631 unsigned long addr;
632 extern int con_is_present(void);
633 int iga2000 = 0;
635 /* Do not attach when we have a serial console. */
636 if (!con_is_present())
637 return -ENXIO;
639 pdev = pci_find_device(PCI_VENDOR_ID_INTERG,
640 PCI_DEVICE_ID_INTERG_1682, 0);
641 if (pdev == NULL) {
642 pdev = pci_find_device(PCI_VENDOR_ID_INTERG,
643 0x2000, 0);
644 if(pdev == NULL)
645 return -ENXIO;
646 iga2000 = 1;
649 info = kmalloc(sizeof(struct fb_info_iga), GFP_ATOMIC);
650 if (!info) {
651 printk("igafb_init: can't alloc fb_info_iga\n");
652 return -ENOMEM;
654 memset(info, 0, sizeof(struct fb_info_iga));
656 info->frame_buffer = pdev->resource[0].start;
657 if (!info->frame_buffer) {
658 kfree(info);
659 return -ENXIO;
662 pcibios_read_config_dword(0, pdev->devfn,
663 PCI_BASE_ADDRESS_0,
664 (unsigned int*)&addr);
665 if (!addr)
666 return -ENXIO;
667 info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
669 #ifdef __sparc__
671 info->io_base_phys = info->frame_buffer_phys;
674 * The right test would be to look if there is a base I/O address.
675 * But it appears that IGA 1682 reuses _memory_ address as a base
676 * for I/O accesses.
678 if (iga2000) {
679 info->io_base = (int) sparc_alloc_io(info->frame_buffer_phys |
680 0x00800000, NULL, 0x1000, "iga", 0, 0);
681 } else {
682 /* Obtain virtual address and correct physical by PCIC shift */
683 info->io_base = pcic_alloc_io(&info->io_base_phys);
685 if (!info->io_base) {
686 kfree(info);
687 return -ENXIO;
691 * Figure mmap addresses from PCI config space.
692 * We need two regions: for video memory and for I/O ports.
693 * Later one can add region for video coprocessor registers.
694 * However, mmap routine loops until size != 0, so we put
695 * one additional region with size == 0.
698 info->mmap_map = kmalloc(4 * sizeof(*info->mmap_map), GFP_ATOMIC);
699 if (!info->mmap_map) {
700 printk("igafb_init: can't alloc mmap_map\n");
701 /* XXX Here we left I/O allocated */
702 kfree(info);
703 return -ENOMEM;
706 memset(info->mmap_map, 0, 4 * sizeof(*info->mmap_map));
709 * Set default vmode and cmode from PROM properties.
712 struct pcidev_cookie *cookie = pdev->sysdata;
713 int node = cookie->prom_node;
714 int width = prom_getintdefault(node, "width", 1024);
715 int height = prom_getintdefault(node, "height", 768);
716 int depth = prom_getintdefault(node, "depth", 8);
717 switch (width) {
718 case 1024:
719 if (height == 768)
720 default_var = default_var_1024x768;
721 break;
722 case 1152:
723 if (height == 900)
724 default_var = default_var_1152x900;
725 break;
726 case 1280:
727 if (height == 1024)
728 default_var = default_var_1280x1024;
729 break;
730 default:
731 break;
734 switch (depth) {
735 case 8:
736 default_var.bits_per_pixel = 8;
737 break;
738 case 16:
739 default_var.bits_per_pixel = 16;
740 break;
741 case 24:
742 default_var.bits_per_pixel = 24;
743 break;
744 case 32:
745 default_var.bits_per_pixel = 32;
746 break;
747 default:
748 break;
752 #endif
753 if (!iga_init(info)) {
754 if (info->mmap_map)
755 kfree(info->mmap_map);
756 kfree(info);
759 #ifdef __sparc__
761 * Add /dev/fb mmap values.
764 /* First region is for video memory */
765 info->mmap_map[0].voff = 0x0;
766 info->mmap_map[0].poff = info->frame_buffer_phys & PAGE_MASK;
767 info->mmap_map[0].size = info->total_vram & PAGE_MASK;
768 info->mmap_map[0].prot_mask = SRMMU_CACHE;
769 info->mmap_map[0].prot_flag = SRMMU_WRITE;
771 /* Second region is for I/O ports */
772 info->mmap_map[1].voff = info->frame_buffer_phys & PAGE_MASK;
773 info->mmap_map[1].poff = info->io_base_phys & PAGE_MASK;
774 info->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */
775 info->mmap_map[1].prot_mask = SRMMU_CACHE;
776 info->mmap_map[1].prot_flag = SRMMU_WRITE;
777 #endif /* __sparc__ */
779 return 0;
782 int __init igafb_setup(char *options)
784 char *this_opt;
786 if (!options || !*options)
787 return 0;
789 for (this_opt = strtok(options, ","); this_opt;
790 this_opt = strtok(NULL, ",")) {
791 if (!strncmp(this_opt, "font:", 5)) {
792 char *p;
793 int i;
795 p = this_opt + 5;
796 for (i = 0; i < sizeof(fontname) - 1; i++)
797 if (!*p || *p == ' ' || *p == ',')
798 break;
799 memcpy(fontname, this_opt + 5, i);
800 fontname[i] = 0;
803 return 0;