~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/video/igafb.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.