1 /*
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/malloc.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 vma->vm_flags |= VM_IO;
297
298 if (!fb->mmaped) {
299 int lastconsole = 0;
300
301 if (info->display_fg)
302 lastconsole = info->display_fg->vc_num;
303 fb->mmaped = 1;
304 if (fb->consolecnt && fb_display[lastconsole].fb_info ==info) {
305 fb->vtconsole = lastconsole;
306 vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
307 }
308 }
309 return 0;
310 }
311 #endif /* __sparc__ */
312
313
314 static int iga_getcolreg(unsigned regno, unsigned *red, unsigned *green,
315 unsigned *blue, unsigned *transp,
316 struct fb_info *fb_info)
317 {
318 /*
319 * Read a single color register and split it into colors/transparent.
320 * Return != 0 for invalid regno.
321 */
322 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
323
324 if (regno >= info->video_cmap_len)
325 return 1;
326
327 *red = info->palette[regno].red;
328 *green = info->palette[regno].green;
329 *blue = info->palette[regno].blue;
330 *transp = 0;
331 return 0;
332 }
333
334 static int iga_setcolreg(unsigned regno, unsigned red, unsigned green,
335 unsigned blue, unsigned transp,
336 struct fb_info *fb_info)
337 {
338 /*
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.
343 */
344
345 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
346
347 if (regno >= info->video_cmap_len)
348 return 1;
349
350 info->palette[regno].red = red;
351 info->palette[regno].green = green;
352 info->palette[regno].blue = blue;
353
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);
358
359 if (regno < 16) {
360 switch (default_var.bits_per_pixel) {
361 #ifdef FBCON_HAS_CFB16
362 case 16:
363 info->fbcon_cmap.cfb16[regno] =
364 (regno << 10) | (regno << 5) | regno;
365 break;
366 #endif
367 #ifdef FBCON_HAS_CFB24
368 case 24:
369 info->fbcon_cmap.cfb24[regno] =
370 (regno << 16) | (regno << 8) | regno;
371 break;
372 #endif
373 #ifdef FBCON_HAS_CFB32
374 case 32:
375 { int i;
376 i = (regno << 8) | regno;
377 info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
378 }
379 break;
380 #endif
381 }
382 }
383 return 0;
384 }
385
386 static void do_install_cmap(int con, struct fb_info *fb_info)
387 {
388 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
389
390 if (con != info->currcon)
391 return;
392 if (fb_display[con].cmap.len)
393 fb_set_cmap(&fb_display[con].cmap, 1,
394 iga_setcolreg, &info->fb_info);
395 else
396 fb_set_cmap(fb_default_cmap(info->video_cmap_len), 1,
397 iga_setcolreg, &info->fb_info);
398 }
399
400 static int igafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
401 struct fb_info *fb_info)
402 {
403 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
404
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);
409 else
410 fb_copy_cmap(fb_default_cmap(info->video_cmap_len),
411 cmap, kspc ? 0 : 2);
412 return 0;
413 }
414
415 static int igafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
416 struct fb_info *info)
417 {
418 int err;
419 struct fb_info_iga *fb = (struct fb_info_iga*) info;
420
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);
424 if (err)
425 return err;
426 }
427 if (con == fb->currcon) /* current console? */
428 return fb_set_cmap(cmap, kspc, iga_setcolreg, info);
429 else
430 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
431 return 0;
432 }
433
434 /*
435 * Framebuffer option structure
436 */
437 static struct fb_ops igafb_ops = {
438 owner: THIS_MODULE,
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,
444 #ifdef __sparc__
445 fb_mmap: igafb_mmap,
446 #endif
447 };
448
449 static void igafb_set_disp(int con, struct fb_info_iga *info)
450 {
451 struct fb_fix_screeninfo fix;
452 struct display *display;
453 struct display_switch *sw;
454
455 if (con >= 0)
456 display = &fb_display[con];
457 else
458 display = &info->disp; /* used during initialization */
459
460 igafb_get_fix(&fix, con, &info->fb_info);
461
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);
474
475 switch (default_var.bits_per_pixel) {
476 #ifdef FBCON_HAS_CFB8
477 case 8:
478 sw = &fbcon_cfb8;
479 break;
480 #endif
481 #ifdef FBCON_HAS_CFB16
482 case 15:
483 case 16:
484 sw = &fbcon_cfb16;
485 display->dispsw_data = info->fbcon_cmap.cfb16;
486 break;
487 #endif
488 #ifdef FBCON_HAS_CFB24
489 case 24:
490 sw = &fbcon_cfb24;
491 display->dispsw_data = info->fbcon_cmap.cfb24;
492 break;
493 #endif
494 #ifdef FBCON_HAS_CFB32
495 case 32:
496 sw = &fbcon_cfb32;
497 display->dispsw_data = info->fbcon_cmap.cfb32;
498 break;
499 #endif
500 default:
501 printk(KERN_WARNING "igafb_set_disp: unknown resolution %d\n",
502 default_var.bits_per_pixel);
503 return;
504 }
505 memcpy(&info->dispsw, sw, sizeof(*sw));
506 display->dispsw = &info->dispsw;
507
508 display->scrollmode = SCROLL_YREDRAW;
509 info->dispsw.bmove = fbcon_redraw_bmove;
510 }
511
512 static int igafb_switch(int con, struct fb_info *fb_info)
513 {
514 struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
515
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);
520
521 info->currcon = con;
522 /* Install new colormap */
523 do_install_cmap(con, fb_info);
524 igafb_update_var(con, fb_info);
525 return 1;
526 }
527
528
529
530 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
531
532 static void igafb_blank(int blank, struct fb_info *info)
533 {
534 /* Not supported */
535 }
536
537
538 static int __init iga_init(struct fb_info_iga *info)
539 {
540 char vramsz = iga_inb(info, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL)
541 & MEM_SIZE_ALIAS;
542 switch (vramsz) {
543 case MEM_SIZE_1M:
544 info->total_vram = 0x100000;
545 break;
546 case MEM_SIZE_2M:
547 info->total_vram = 0x200000;
548 break;
549 case MEM_SIZE_4M:
550 case MEM_SIZE_RESERVED:
551 info->total_vram = 0x400000;
552 break;
553 }
554
555 if (default_var.bits_per_pixel > 8) {
556 info->video_cmap_len = 16;
557 } else {
558 info->video_cmap_len = 256;
559 }
560 {
561 int j, k;
562 for (j = 0; j < 16; j++) {
563 k = color_table[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];
567 }
568 }
569
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;
580
581 igafb_set_disp(-1, info);
582
583 if (register_framebuffer(&info->fb_info) < 0)
584 return 0;
585
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);
589
590 iga_blank_border(info);
591 return 1;
592 }
593
594 int __init igafb_init(void)
595 {
596 struct pci_dev *pdev;
597 struct fb_info_iga *info;
598 unsigned long addr;
599 extern int con_is_present(void);
600 int iga2000 = 0;
601
602 /* Do not attach when we have a serial console. */
603 if (!con_is_present())
604 return -ENXIO;
605
606 pdev = pci_find_device(PCI_VENDOR_ID_INTERG,
607 PCI_DEVICE_ID_INTERG_1682, 0);
608 if (pdev == NULL) {
609 /*
610 * XXX We tried to use cyber2000fb.c for IGS 2000.
611 * But it does not initialize the chip in JavaStation-E, alas.
612 */
613 pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
614 if(pdev == NULL) {
615 return -ENXIO;
616 }
617 iga2000 = 1;
618 }
619
620 info = kmalloc(sizeof(struct fb_info_iga), GFP_ATOMIC);
621 if (!info) {
622 printk("igafb_init: can't alloc fb_info_iga\n");
623 return -ENOMEM;
624 }
625 memset(info, 0, sizeof(struct fb_info_iga));
626
627 if ((addr = pdev->resource[0].start) == 0) {
628 printk("igafb_init: no memory start\n");
629 kfree(info);
630 return -ENXIO;
631 }
632
633 if ((info->frame_buffer = ioremap(addr, 1024*1024*2)) == 0) {
634 printk("igafb_init: can't remap %lx[2M]\n", addr);
635 kfree(info);
636 return -ENXIO;
637 }
638
639 info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
640
641 #ifdef __sparc__
642 /*
643 * The following is sparc specific and this is why:
644 *
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.
648 *
649 * IGS1682 is more traditional, it responds to PCI I/O
650 * cycles, so we want to access it with inb()/outb().
651 *
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.
655 *
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
659 * I/O addresses are.
660 */
661 if (iga2000) {
662 info->io_base_phys = info->frame_buffer_phys | 0x00800000;
663 } else {
664 info->io_base_phys = 0x30000000; /* XXX */
665 }
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);
669 kfree(info);
670 return -ENXIO;
671 }
672
673 /*
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.
679 */
680
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);
686 kfree(info);
687 return -ENOMEM;
688 }
689
690 memset(info->mmap_map, 0, 4 * sizeof(*info->mmap_map));
691
692 /*
693 * Set default vmode and cmode from PROM properties.
694 */
695 {
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);
701 switch (width) {
702 case 1024:
703 if (height == 768)
704 default_var = default_var_1024x768;
705 break;
706 case 1152:
707 if (height == 900)
708 default_var = default_var_1152x900;
709 break;
710 case 1280:
711 if (height == 1024)
712 default_var = default_var_1280x1024;
713 break;
714 default:
715 break;
716 }
717
718 switch (depth) {
719 case 8:
720 default_var.bits_per_pixel = 8;
721 break;
722 case 16:
723 default_var.bits_per_pixel = 16;
724 break;
725 case 24:
726 default_var.bits_per_pixel = 24;
727 break;
728 case 32:
729 default_var.bits_per_pixel = 32;
730 break;
731 default:
732 break;
733 }
734 }
735
736 #endif
737
738 if (!iga_init(info)) {
739 iounmap((void *)info->io_base);
740 iounmap(info->frame_buffer);
741 if (info->mmap_map)
742 kfree(info->mmap_map);
743 kfree(info);
744 }
745
746 #ifdef __sparc__
747 /*
748 * Add /dev/fb mmap values.
749 */
750
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;
757
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__ */
765
766 return 0;
767 }
768
769 int __init igafb_setup(char *options)
770 {
771 char *this_opt;
772
773 if (!options || !*options)
774 return 0;
775
776 for (this_opt = strtok(options, ","); this_opt;
777 this_opt = strtok(NULL, ",")) {
778 if (!strncmp(this_opt, "font:", 5)) {
779 char *p;
780 int i;
781
782 p = this_opt + 5;
783 for (i = 0; i < sizeof(fontname) - 1; i++)
784 if (!*p || *p == ' ' || *p == ',')
785 break;
786 memcpy(fontname, this_opt + 5, i);
787 fontname[i] = 0;
788 }
789 }
790 return 0;
791 }
792
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.