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

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

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

  1 /*
  2  *  linux/drivers/video/offb.c -- Open Firmware based frame buffer device
  3  *
  4  *      Copyright (C) 1997 Geert Uytterhoeven
  5  *
  6  *  This driver is partly based on the PowerMac console driver:
  7  *
  8  *      Copyright (C) 1996 Paul Mackerras
  9  *
 10  *  This file is subject to the terms and conditions of the GNU General Public
 11  *  License. See the file COPYING in the main directory of this archive for
 12  *  more details.
 13  */
 14 
 15 #include <linux/config.h>
 16 #include <linux/module.h>
 17 #include <linux/kernel.h>
 18 #include <linux/errno.h>
 19 #include <linux/string.h>
 20 #include <linux/mm.h>
 21 #include <linux/tty.h>
 22 #include <linux/malloc.h>
 23 #include <linux/vmalloc.h>
 24 #include <linux/delay.h>
 25 #include <linux/interrupt.h>
 26 #include <linux/fb.h>
 27 #include <linux/selection.h>
 28 #include <linux/init.h>
 29 #include <linux/ioport.h>
 30 #ifdef CONFIG_FB_COMPAT_XPMAC
 31 #include <asm/vc_ioctl.h>
 32 #endif
 33 #include <asm/io.h>
 34 #include <asm/prom.h>
 35 #include <asm/bootx.h>
 36 
 37 #include <video/fbcon.h>
 38 #include <video/fbcon-cfb8.h>
 39 #include <video/fbcon-cfb16.h>
 40 #include <video/fbcon-cfb32.h>
 41 #include <video/macmodes.h>
 42 
 43 
 44 static int currcon = 0;
 45 
 46 /* Supported palette hacks */
 47 enum {
 48         cmap_unknown,
 49         cmap_m64,       /* ATI Mach64 */
 50         cmap_r128,      /* ATI Rage128 */
 51         cmap_M3A,       /* ATI Rage Mobility M3 Head A */
 52         cmap_M3B        /* ATI Rage Mobility M3 Head B */
 53 };
 54 
 55 struct fb_info_offb {
 56     struct fb_info info;
 57     struct fb_fix_screeninfo fix;
 58     struct fb_var_screeninfo var;
 59     struct display disp;
 60     struct { u_char red, green, blue, pad; } palette[256];
 61     volatile unsigned char *cmap_adr;
 62     volatile unsigned char *cmap_data;
 63     int cmap_type;
 64     union {
 65 #ifdef FBCON_HAS_CFB16
 66         u16 cfb16[16];
 67 #endif
 68 #ifdef FBCON_HAS_CFB32
 69         u32 cfb32[16];
 70 #endif
 71     } fbcon_cmap;
 72 };
 73 
 74 #ifdef __powerpc__
 75 #define mach_eieio()    eieio()
 76 #else
 77 #define mach_eieio()    do {} while (0)
 78 #endif
 79 
 80 
 81     /*
 82      *  Interface used by the world
 83      */
 84 
 85 int offb_init(void);
 86 
 87 static int offb_get_fix(struct fb_fix_screeninfo *fix, int con,
 88                         struct fb_info *info);
 89 static int offb_get_var(struct fb_var_screeninfo *var, int con,
 90                         struct fb_info *info);
 91 static int offb_set_var(struct fb_var_screeninfo *var, int con,
 92                         struct fb_info *info);
 93 static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
 94                         struct fb_info *info);
 95 static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
 96                         struct fb_info *info);
 97 
 98 extern boot_infos_t *boot_infos;
 99 
100 static void offb_init_nodriver(struct device_node *);
101 static void offb_init_fb(const char *name, const char *full_name, int width,
102                       int height, int depth, int pitch, unsigned long address,
103                       struct device_node *dp);
104 
105     /*
106      *  Interface to the low level console driver
107      */
108 
109 static int offbcon_switch(int con, struct fb_info *info);
110 static int offbcon_updatevar(int con, struct fb_info *info);
111 static void offbcon_blank(int blank, struct fb_info *info);
112 
113 
114     /*
115      *  Internal routines
116      */
117 
118 static int offb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
119                          u_int *transp, struct fb_info *info);
120 static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
121                          u_int transp, struct fb_info *info);
122 static void do_install_cmap(int con, struct fb_info *info);
123 
124 
125 static struct fb_ops offb_ops = {
126         owner:          THIS_MODULE,
127         fb_get_fix:     offb_get_fix,
128         fb_get_var:     offb_get_var,
129         fb_set_var:     offb_set_var,
130         fb_get_cmap:    offb_get_cmap,
131         fb_set_cmap:    offb_set_cmap,
132 };
133 
134     /*
135      *  Get the Fixed Part of the Display
136      */
137 
138 static int offb_get_fix(struct fb_fix_screeninfo *fix, int con,
139                         struct fb_info *info)
140 {
141     struct fb_info_offb *info2 = (struct fb_info_offb *)info;
142 
143     memcpy(fix, &info2->fix, sizeof(struct fb_fix_screeninfo));
144     return 0;
145 }
146 
147 
148     /*
149      *  Get the User Defined Part of the Display
150      */
151 
152 static int offb_get_var(struct fb_var_screeninfo *var, int con,
153                         struct fb_info *info)
154 {
155     struct fb_info_offb *info2 = (struct fb_info_offb *)info;
156 
157     memcpy(var, &info2->var, sizeof(struct fb_var_screeninfo));
158     return 0;
159 }
160 
161 
162     /*
163      *  Set the User Defined Part of the Display
164      */
165 
166 static int offb_set_var(struct fb_var_screeninfo *var, int con,
167                         struct fb_info *info)
168 {
169     struct display *display;
170     unsigned int oldbpp = 0;
171     int err;
172     int activate = var->activate;
173     struct fb_info_offb *info2 = (struct fb_info_offb *)info;
174 
175     if (con >= 0)
176         display = &fb_display[con];
177     else
178         display = &info2->disp; /* used during initialization */
179 
180     if (var->xres > info2->var.xres || var->yres > info2->var.yres ||
181         var->xres_virtual > info2->var.xres_virtual ||
182         var->yres_virtual > info2->var.yres_virtual ||
183         var->bits_per_pixel > info2->var.bits_per_pixel ||
184         var->nonstd ||
185         (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
186         return -EINVAL;
187     memcpy(var, &info2->var, sizeof(struct fb_var_screeninfo));
188 
189     if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
190         oldbpp = display->var.bits_per_pixel;
191         display->var = *var;
192     }
193     if ((oldbpp != var->bits_per_pixel) || (display->cmap.len == 0)) {
194         if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
195             return err;
196         do_install_cmap(con, info);
197     }
198     return 0;
199 }
200 
201 
202     /*
203      *  Get the Colormap
204      */
205 
206 static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
207                          struct fb_info *info)
208 {
209     if (con == currcon) /* current console? */
210         return fb_get_cmap(cmap, kspc, offb_getcolreg, info);
211     else if (fb_display[con].cmap.len) /* non default colormap? */
212         fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
213     else
214     {
215         int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
216         fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
217     }
218     return 0;
219 }
220 
221     /*
222      *  Set the Colormap
223      */
224 
225 static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
226                          struct fb_info *info)
227 {
228     struct fb_info_offb *info2 = (struct fb_info_offb *)info;
229     int err;
230 
231     if (!info2->cmap_adr)
232         return -ENOSYS;
233 
234     if (!fb_display[con].cmap.len) {    /* no colormap allocated? */
235         int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
236         if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
237             return err;
238     }
239     if (con == currcon)                 /* current console? */
240         return fb_set_cmap(cmap, kspc, offb_setcolreg, info);
241     else
242         fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
243     return 0;
244 }
245 
246 
247     /*
248      *  Initialisation
249      */
250 
251 int __init offb_init(void)
252 {
253     struct device_node *dp;
254     unsigned int dpy;
255     struct device_node *displays = find_type_devices("display");
256     struct device_node *macos_display = NULL;
257 
258     /* If we're booted from BootX... */
259     if (prom_num_displays == 0 && boot_infos != 0) {
260         unsigned long addr = (unsigned long) boot_infos->dispDeviceBase;
261         /* find the device node corresponding to the macos display */
262         for (dp = displays; dp != NULL; dp = dp->next) {
263             int i;
264             /*
265              * Grrr...  It looks like the MacOS ATI driver
266              * munges the assigned-addresses property (but
267              * the AAPL,address value is OK).
268              */
269             if (strncmp(dp->name, "ATY,", 4) == 0 && dp->n_addrs == 1) {
270                 unsigned int *ap = (unsigned int *)
271                     get_property(dp, "AAPL,address", NULL);
272                 if (ap != NULL) {
273                     dp->addrs[0].address = *ap;
274                     dp->addrs[0].size = 0x01000000;
275                 }
276             }
277 
278             /*
279              * The LTPro on the Lombard powerbook has no addresses
280              * on the display nodes, they are on their parent.
281              */
282             if (dp->n_addrs == 0 && device_is_compatible(dp, "ATY,264LTPro")) {
283                 int na;
284                 unsigned int *ap = (unsigned int *)
285                     get_property(dp, "AAPL,address", &na);
286                 if (ap != 0)
287                     for (na /= sizeof(unsigned int); na > 0; --na, ++ap)
288                         if (*ap <= addr && addr < *ap + 0x1000000)
289                             goto foundit;
290             }
291 
292             /*
293              * See if the display address is in one of the address
294              * ranges for this display.
295              */
296             for (i = 0; i < dp->n_addrs; ++i) {
297                 if (dp->addrs[i].address <= addr
298                     && addr < dp->addrs[i].address + dp->addrs[i].size)
299                     break;
300             }
301             if (i < dp->n_addrs) {
302             foundit:
303                 printk(KERN_INFO "MacOS display is %s\n", dp->full_name);
304                 macos_display = dp;
305                 break;
306             }
307         }
308 
309         /* initialize it */
310         offb_init_fb(macos_display? macos_display->name: "MacOS display",
311                      macos_display? macos_display->full_name: "MacOS display",
312                      boot_infos->dispDeviceRect[2],
313                      boot_infos->dispDeviceRect[3],
314                      boot_infos->dispDeviceDepth,
315                      boot_infos->dispDeviceRowBytes, addr, NULL);
316     }
317 
318     for (dpy = 0; dpy < prom_num_displays; dpy++) {
319         if ((dp = find_path_device(prom_display_paths[dpy])))
320             offb_init_nodriver(dp);
321     }
322     return 0;
323 }
324 
325 
326 static void __init offb_init_nodriver(struct device_node *dp)
327 {
328     int *pp, i;
329     unsigned int len;
330     int width = 640, height = 480, depth = 8, pitch;
331     unsigned *up, address;
332 
333     if ((pp = (int *)get_property(dp, "depth", &len)) != NULL
334         && len == sizeof(int))
335         depth = *pp;
336     if ((pp = (int *)get_property(dp, "width", &len)) != NULL
337         && len == sizeof(int))
338         width = *pp;
339     if ((pp = (int *)get_property(dp, "height", &len)) != NULL
340         && len == sizeof(int))
341         height = *pp;
342     if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL
343         && len == sizeof(int)) {
344         pitch = *pp;
345         if (pitch == 1)
346             pitch = 0x1000;
347     } else
348         pitch = width;
349     if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL
350         && len == sizeof(unsigned))
351         address = (u_long)*up;
352     else {
353         for (i = 0; i < dp->n_addrs; ++i)
354             if (dp->addrs[i].size >= pitch*height*depth/8)
355                 break;
356         if (i >= dp->n_addrs) {
357             printk(KERN_ERR "no framebuffer address found for %s\n", dp->full_name);
358             return;
359         }
360 
361         address = (u_long)dp->addrs[i].address;
362 
363         /* kludge for valkyrie */
364         if (strcmp(dp->name, "valkyrie") == 0) 
365             address += 0x1000;
366     }
367     offb_init_fb(dp->name, dp->full_name, width, height, depth,
368                  pitch, address, dp);
369     
370 }
371 
372 static void __init offb_init_fb(const char *name, const char *full_name,
373                                     int width, int height, int depth,
374                                     int pitch, unsigned long address,
375                                     struct device_node *dp)
376 {
377     int i;
378     struct fb_fix_screeninfo *fix;
379     struct fb_var_screeninfo *var;
380     struct display *disp;
381     struct fb_info_offb *info;
382     unsigned long res_start = address;
383     unsigned long res_size = pitch*height*depth/8;
384 
385     if (!request_mem_region(res_start, res_size, "offb"))
386         return;
387 
388     printk(KERN_INFO "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n",
389            width, height, name, address, depth, pitch);
390     if (depth != 8 && depth != 16 && depth != 32) {
391         printk(KERN_ERR "%s: can't use depth = %d\n", full_name, depth);
392         release_mem_region(res_start, res_size);
393         return;
394     }
395 
396     info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC);
397     if (info == 0) {
398         release_mem_region(res_start, res_size);
399         return;
400     }
401     memset(info, 0, sizeof(*info));
402 
403     fix = &info->fix;
404     var = &info->var;
405     disp = &info->disp;
406 
407     strcpy(fix->id, "OFfb ");
408     strncat(fix->id, name, sizeof(fix->id));
409     fix->id[sizeof(fix->id)-1] = '\0';
410 
411     var->xres = var->xres_virtual = width;
412     var->yres = var->yres_virtual = height;
413     fix->line_length = pitch;
414 
415     fix->smem_start = address;
416     fix->smem_len = pitch * height;
417     fix->type = FB_TYPE_PACKED_PIXELS;
418     fix->type_aux = 0;
419 
420     info->cmap_type = cmap_unknown;
421     if (depth == 8)
422     {
423         /* XXX kludge for ati */
424         if (dp && !strncmp(name, "ATY,Rage128", 11)) {
425                 unsigned long regbase = dp->addrs[2].address;
426                 info->cmap_adr = ioremap(regbase, 0x1FFF);
427                 info->cmap_type = cmap_r128;
428         } else if (dp && !strncmp(name, "ATY,RageM3pA", 12)) {
429                 unsigned long regbase = dp->parent->addrs[2].address;
430                 info->cmap_adr = ioremap(regbase, 0x1FFF);
431                 info->cmap_type = cmap_M3A;
432         } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
433                 unsigned long regbase = dp->parent->addrs[2].address;
434                 info->cmap_adr = ioremap(regbase, 0x1FFF);
435                 info->cmap_type = cmap_M3B;
436         } else if (!strncmp(name, "ATY,", 4)) {
437                 unsigned long base = address & 0xff000000UL;
438                 info->cmap_adr = ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
439                 info->cmap_data = info->cmap_adr + 1;
440                 info->cmap_type = cmap_m64;
441         }
442         fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR
443                                      : FB_VISUAL_STATIC_PSEUDOCOLOR;
444     }
445     else
446         fix->visual = /*info->cmap_adr ? FB_VISUAL_DIRECTCOLOR
447                                      : */FB_VISUAL_TRUECOLOR;
448 
449     var->xoffset = var->yoffset = 0;
450     var->bits_per_pixel = depth;
451     switch (depth) {
452         case 8:
453             var->bits_per_pixel = 8;
454             var->red.offset = 0;
455             var->red.length = 8;
456             var->green.offset = 0;
457             var->green.length = 8;
458             var->blue.offset = 0;
459             var->blue.length = 8;
460             var->transp.offset = 0;
461             var->transp.length = 0;
462             break;
463         case 16:        /* RGB 555 */
464             var->bits_per_pixel = 16;
465             var->red.offset = 10;
466             var->red.length = 5;
467             var->green.offset = 5;
468             var->green.length = 5;
469             var->blue.offset = 0;
470             var->blue.length = 5;
471             var->transp.offset = 0;
472             var->transp.length = 0;
473             break;
474         case 32:        /* RGB 888 */
475             var->bits_per_pixel = 32;
476             var->red.offset = 16;
477             var->red.length = 8;
478             var->green.offset = 8;
479             var->green.length = 8;
480             var->blue.offset = 0;
481             var->blue.length = 8;
482             var->transp.offset = 24;
483             var->transp.length = 8;
484             break;
485     }
486     var->red.msb_right = var->green.msb_right = var->blue.msb_right = var->transp.msb_right = 0;
487     var->grayscale = 0;
488     var->nonstd = 0;
489     var->activate = 0;
490     var->height = var->width = -1;
491     var->pixclock = 10000;
492     var->left_margin = var->right_margin = 16;
493     var->upper_margin = var->lower_margin = 16;
494     var->hsync_len = var->vsync_len = 8;
495     var->sync = 0;
496     var->vmode = FB_VMODE_NONINTERLACED;
497 
498     disp->var = *var;
499     disp->cmap.start = 0;
500     disp->cmap.len = 0;
501     disp->cmap.red = NULL;
502     disp->cmap.green = NULL;
503     disp->cmap.blue = NULL;
504     disp->cmap.transp = NULL;
505     disp->screen_base = ioremap(address, fix->smem_len);
506     disp->visual = fix->visual;
507     disp->type = fix->type;
508     disp->type_aux = fix->type_aux;
509     disp->ypanstep = 0;
510     disp->ywrapstep = 0;
511     disp->line_length = fix->line_length;
512     disp->can_soft_blank = info->cmap_adr ? 1 : 0;
513     disp->inverse = 0;
514     switch (depth) {
515 #ifdef FBCON_HAS_CFB8
516         case 8:
517             disp->dispsw = &fbcon_cfb8;
518             break;
519 #endif
520 #ifdef FBCON_HAS_CFB16
521         case 16:
522             disp->dispsw = &fbcon_cfb16;
523             disp->dispsw_data = info->fbcon_cmap.cfb16;
524             for (i = 0; i < 16; i++)
525                 if (fix->visual == FB_VISUAL_TRUECOLOR)
526                     info->fbcon_cmap.cfb16[i] =
527                             (((default_blu[i] >> 3) & 0x1f) << 10) |
528                             (((default_grn[i] >> 3) & 0x1f) << 5) |
529                             ((default_red[i] >> 3) & 0x1f);
530                 else
531                     info->fbcon_cmap.cfb16[i] =
532                             (i << 10) | (i << 5) | i;
533             break;
534 #endif
535 #ifdef FBCON_HAS_CFB32
536         case 32:
537             disp->dispsw = &fbcon_cfb32;
538             disp->dispsw_data = info->fbcon_cmap.cfb32;
539             for (i = 0; i < 16; i++)
540                 if (fix->visual == FB_VISUAL_TRUECOLOR)
541                     info->fbcon_cmap.cfb32[i] =
542                         (default_blu[i] << 16) |
543                         (default_grn[i] << 8) |
544                         default_red[i];
545                 else
546                     info->fbcon_cmap.cfb32[i] =
547                             (i << 16) | (i << 8) | i;
548             break;
549 #endif
550         default:
551             disp->dispsw = &fbcon_dummy;
552     }
553 
554     disp->scrollmode = SCROLL_YREDRAW;
555 
556     strcpy(info->info.modename, "OFfb ");
557     strncat(info->info.modename, full_name, sizeof(info->info.modename));
558     info->info.node = -1;
559     info->info.fbops = &offb_ops;
560     info->info.disp = disp;
561     info->info.fontname[0] = '\0';
562     info->info.changevar = NULL;
563     info->info.switch_con = &offbcon_switch;
564     info->info.updatevar = &offbcon_updatevar;
565     info->info.blank = &offbcon_blank;
566     info->info.flags = FBINFO_FLAG_DEFAULT;
567 
568     for (i = 0; i < 16; i++) {
569         int j = color_table[i];
570         info->palette[i].red = default_red[j];
571         info->palette[i].green = default_grn[j];
572         info->palette[i].blue = default_blu[j];
573     }
574     offb_set_var(var, -1, &info->info);
575 
576     if (register_framebuffer(&info->info) < 0) {
577         kfree(info);
578         release_mem_region(res_start, res_size);
579         return;
580     }
581 
582     printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n",
583            GET_FB_IDX(info->info.node), full_name);
584 
585 #ifdef CONFIG_FB_COMPAT_XPMAC
586     if (!console_fb_info) {
587         display_info.height = var->yres;
588         display_info.width = var->xres;
589         display_info.depth = depth;
590         display_info.pitch = fix->line_length;
591         display_info.mode = 0;
592         strncpy(display_info.name, name, sizeof(display_info.name));
593         display_info.fb_address = address;
594         display_info.cmap_adr_address = 0;
595         display_info.cmap_data_address = 0;
596         display_info.disp_reg_address = 0;
597         /* XXX kludge for ati */
598         if (info->cmap_type == cmap_m64) {
599             unsigned long base = address & 0xff000000UL;
600             display_info.disp_reg_address = base + 0x7ffc00;
601             display_info.cmap_adr_address = base + 0x7ffcc0;
602             display_info.cmap_data_address = base + 0x7ffcc1;
603         }
604         console_fb_info = &info->info;
605     }
606 #endif /* CONFIG_FB_COMPAT_XPMAC) */
607 }
608 
609 
610 static int offbcon_switch(int con, struct fb_info *info)
611 {
612     /* Do we have to save the colormap? */
613     if (fb_display[currcon].cmap.len)
614         fb_get_cmap(&fb_display[currcon].cmap, 1, offb_getcolreg, info);
615 
616     currcon = con;
617     /* Install new colormap */
618     do_install_cmap(con, info);
619     return 0;
620 }
621 
622     /*
623      *  Update the `var' structure (called by fbcon.c)
624      */
625 
626 static int offbcon_updatevar(int con, struct fb_info *info)
627 {
628     /* Nothing */
629     return 0;
630 }
631 
632     /*
633      *  Blank the display.
634      */
635 
636 static void offbcon_blank(int blank, struct fb_info *info)
637 {
638     struct fb_info_offb *info2 = (struct fb_info_offb *)info;
639     int i, j;
640 
641     if (!info2->cmap_adr)
642         return;
643 
644     if (blank)
645         for (i = 0; i < 256; i++) {
646             switch(info2->cmap_type) {
647             case cmap_m64:
648                 *info2->cmap_adr = i;
649                 mach_eieio();
650                 for (j = 0; j < 3; j++) {
651                     *info2->cmap_data = 0;
652                     mach_eieio();
653                 }
654                 break;
655             case cmap_M3A:
656                 /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
657                 out_le32((unsigned *)(info2->cmap_adr + 0x58),
658                         in_le32((unsigned *)(info2->cmap_adr + 0x58)) & ~0x20);
659             case cmap_r128:
660                 /* Set palette index & data */
661                 out_8(info2->cmap_adr + 0xb0, i);
662                 out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0);
663                 break;
664             case cmap_M3B:
665                 /* Set PALETTE_ACCESS_CNTL in DAC_CNTL */
666                 out_le32((unsigned *)(info2->cmap_adr + 0x58),
667                         in_le32((unsigned *)(info2->cmap_adr + 0x58)) | 0x20);
668                 /* Set palette index & data */
669                 out_8(info2->cmap_adr + 0xb0, i);
670                 out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0);
671                 break;
672             }
673         }
674     else
675         do_install_cmap(currcon, info);
676 }
677 
678     /*
679      *  Read a single color register and split it into
680      *  colors/transparent. Return != 0 for invalid regno.
681      */
682 
683 static int offb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
684                           u_int *transp, struct fb_info *info)
685 {
686     struct fb_info_offb *info2 = (struct fb_info_offb *)info;
687 
688     if (!info2->cmap_adr || regno > 255)
689         return 1;
690     
691     *red = (info2->palette[regno].red<<8) | info2->palette[regno].red;
692     *green = (info2->palette[regno].green<<8) | info2->palette[regno].green;
693     *blue = (info2->palette[regno].blue<<8) | info2->palette[regno].blue;
694     *transp = 0;
695     return 0;
696 }
697 
698 
699     /*
700      *  Set a single color register. The values supplied are already
701      *  rounded down to the hardware's capabilities (according to the
702      *  entries in the var structure). Return != 0 for invalid regno.
703      */
704 
705 static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
706                          u_int transp, struct fb_info *info)
707 {
708     struct fb_info_offb *info2 = (struct fb_info_offb *)info;
709         
710     if (!info2->cmap_adr || regno > 255)
711         return 1;
712 
713     red >>= 8;
714     green >>= 8;
715     blue >>= 8;
716 
717     info2->palette[regno].red = red;
718     info2->palette[regno].green = green;
719     info2->palette[regno].blue = blue;
720 
721     switch(info2->cmap_type) {
722     case cmap_m64:
723         *info2->cmap_adr = regno;
724         mach_eieio();
725         *info2->cmap_data = red;
726         mach_eieio();
727         *info2->cmap_data = green;
728         mach_eieio();
729         *info2->cmap_data = blue;
730         mach_eieio();
731         break;
732     case cmap_M3A:
733         /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
734         out_le32((unsigned *)(info2->cmap_adr + 0x58),
735                 in_le32((unsigned *)(info2->cmap_adr + 0x58)) & ~0x20);
736     case cmap_r128:
737         /* Set palette index & data */
738         out_8(info2->cmap_adr + 0xb0, regno);
739         out_le32((unsigned *)(info2->cmap_adr + 0xb4),
740                 (red << 16 | green << 8 | blue));
741         break;
742     case cmap_M3B:
743         /* Set PALETTE_ACCESS_CNTL in DAC_CNTL */
744         out_le32((unsigned *)(info2->cmap_adr + 0x58),
745                 in_le32((unsigned *)(info2->cmap_adr + 0x58)) | 0x20);
746         /* Set palette index & data */
747         out_8(info2->cmap_adr + 0xb0, regno);
748         out_le32((unsigned *)(info2->cmap_adr + 0xb4),
749                 (red << 16 | green << 8 | blue));
750         break;
751     }
752 
753     if (regno < 16)
754         switch (info2->var.bits_per_pixel) {
755 #ifdef FBCON_HAS_CFB16
756             case 16:
757                 info2->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno;
758                 break;
759 #endif
760 #ifdef FBCON_HAS_CFB32
761             case 32:
762             {
763                 int i = (regno << 8) | regno;
764                 info2->fbcon_cmap.cfb32[regno] = (i << 16) | i;
765                 break;
766             }
767 #endif
768        }
769 
770     return 0;
771 }
772 
773 
774 static void do_install_cmap(int con, struct fb_info *info)
775 {
776     if (con != currcon)
777         return;
778     if (fb_display[con].cmap.len)
779         fb_set_cmap(&fb_display[con].cmap, 1, offb_setcolreg, info);
780     else
781     {
782         int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
783         fb_set_cmap(fb_default_cmap(size), 1, offb_setcolreg, info);
784     }
785 }
786 

~ [ 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.