2 * linux/drivers/video/offb.c -- Open Firmware based frame buffer device
4 * Copyright (C) 1997 Geert Uytterhoeven
6 * This driver is partly based on the PowerMac console driver:
8 * Copyright (C) 1996 Paul Mackerras
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
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>
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>
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>
35 #include <asm/bootx.h>
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>
44 static int currcon
= 0;
46 /* Supported palette hacks */
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 */
57 struct fb_fix_screeninfo fix
;
58 struct fb_var_screeninfo var
;
60 struct { u_char red
, green
, blue
, pad
; } palette
[256];
61 volatile unsigned char *cmap_adr
;
62 volatile unsigned char *cmap_data
;
65 #ifdef FBCON_HAS_CFB16
68 #ifdef FBCON_HAS_CFB32
75 #define mach_eieio() eieio()
77 #define mach_eieio() do {} while (0)
82 * Interface used by the world
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
);
98 extern boot_infos_t
*boot_infos
;
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
);
106 * Interface to the low level console driver
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
);
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
);
125 static struct fb_ops offb_ops
= {
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
,
135 * Get the Fixed Part of the Display
138 static int offb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
139 struct fb_info
*info
)
141 struct fb_info_offb
*info2
= (struct fb_info_offb
*)info
;
143 memcpy(fix
, &info2
->fix
, sizeof(struct fb_fix_screeninfo
));
149 * Get the User Defined Part of the Display
152 static int offb_get_var(struct fb_var_screeninfo
*var
, int con
,
153 struct fb_info
*info
)
155 struct fb_info_offb
*info2
= (struct fb_info_offb
*)info
;
157 memcpy(var
, &info2
->var
, sizeof(struct fb_var_screeninfo
));
163 * Set the User Defined Part of the Display
166 static int offb_set_var(struct fb_var_screeninfo
*var
, int con
,
167 struct fb_info
*info
)
169 struct display
*display
;
170 unsigned int oldbpp
= 0;
172 int activate
= var
->activate
;
173 struct fb_info_offb
*info2
= (struct fb_info_offb
*)info
;
176 display
= &fb_display
[con
];
178 display
= &info2
->disp
; /* used during initialization */
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
||
185 (var
->vmode
& FB_VMODE_MASK
) != FB_VMODE_NONINTERLACED
)
187 memcpy(var
, &info2
->var
, sizeof(struct fb_var_screeninfo
));
189 if ((activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
) {
190 oldbpp
= display
->var
.bits_per_pixel
;
193 if ((oldbpp
!= var
->bits_per_pixel
) || (display
->cmap
.len
== 0)) {
194 if ((err
= fb_alloc_cmap(&display
->cmap
, 0, 0)))
196 do_install_cmap(con
, info
);
206 static int offb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
207 struct fb_info
*info
)
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);
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);
225 static int offb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
226 struct fb_info
*info
)
228 struct fb_info_offb
*info2
= (struct fb_info_offb
*)info
;
231 if (!info2
->cmap_adr
)
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)))
239 if (con
== currcon
) /* current console? */
240 return fb_set_cmap(cmap
, kspc
, offb_setcolreg
, info
);
242 fb_copy_cmap(cmap
, &fb_display
[con
].cmap
, kspc
? 0 : 1);
251 int __init
offb_init(void)
253 struct device_node
*dp
;
255 struct device_node
*displays
= find_type_devices("display");
256 struct device_node
*macos_display
= NULL
;
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
) {
265 * Grrr... It looks like the MacOS ATI driver
266 * munges the assigned-addresses property (but
267 * the AAPL,address value is OK).
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
);
273 dp
->addrs
[0].address
= *ap
;
274 dp
->addrs
[0].size
= 0x01000000;
279 * The LTPro on the Lombard powerbook has no addresses
280 * on the display nodes, they are on their parent.
282 if (dp
->n_addrs
== 0 && device_is_compatible(dp
, "ATY,264LTPro")) {
284 unsigned int *ap
= (unsigned int *)
285 get_property(dp
, "AAPL,address", &na
);
287 for (na
/= sizeof(unsigned int); na
> 0; --na
, ++ap
)
288 if (*ap
<= addr
&& addr
< *ap
+ 0x1000000)
293 * See if the display address is in one of the address
294 * ranges for this display.
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
)
301 if (i
< dp
->n_addrs
) {
303 printk(KERN_INFO
"MacOS display is %s\n", dp
->full_name
);
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
);
318 for (dpy
= 0; dpy
< prom_num_displays
; dpy
++) {
319 if ((dp
= find_path_device(prom_display_paths
[dpy
])))
320 offb_init_nodriver(dp
);
326 static void __init
offb_init_nodriver(struct device_node
*dp
)
330 int width
= 640, height
= 480, depth
= 8, pitch
;
331 unsigned *up
, address
;
333 if ((pp
= (int *)get_property(dp
, "depth", &len
)) != NULL
334 && len
== sizeof(int))
336 if ((pp
= (int *)get_property(dp
, "width", &len
)) != NULL
337 && len
== sizeof(int))
339 if ((pp
= (int *)get_property(dp
, "height", &len
)) != NULL
340 && len
== sizeof(int))
342 if ((pp
= (int *)get_property(dp
, "linebytes", &len
)) != NULL
343 && len
== sizeof(int)) {
349 if ((up
= (unsigned *)get_property(dp
, "address", &len
)) != NULL
350 && len
== sizeof(unsigned))
351 address
= (u_long
)*up
;
353 for (i
= 0; i
< dp
->n_addrs
; ++i
)
354 if (dp
->addrs
[i
].size
>= pitch
*height
*depth
/8)
356 if (i
>= dp
->n_addrs
) {
357 printk(KERN_ERR
"no framebuffer address found for %s\n", dp
->full_name
);
361 address
= (u_long
)dp
->addrs
[i
].address
;
363 /* kludge for valkyrie */
364 if (strcmp(dp
->name
, "valkyrie") == 0)
367 offb_init_fb(dp
->name
, dp
->full_name
, width
, height
, depth
,
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
)
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;
385 if (!request_mem_region(res_start
, res_size
, "offb"))
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
);
396 info
= kmalloc(sizeof(struct fb_info_offb
), GFP_ATOMIC
);
398 release_mem_region(res_start
, res_size
);
401 memset(info
, 0, sizeof(*info
));
407 strcpy(fix
->id
, "OFfb ");
408 strncat(fix
->id
, name
, sizeof(fix
->id
));
409 fix
->id
[sizeof(fix
->id
)-1] = '\0';
411 var
->xres
= var
->xres_virtual
= width
;
412 var
->yres
= var
->yres_virtual
= height
;
413 fix
->line_length
= pitch
;
415 fix
->smem_start
= address
;
416 fix
->smem_len
= pitch
* height
;
417 fix
->type
= FB_TYPE_PACKED_PIXELS
;
420 info
->cmap_type
= cmap_unknown
;
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
;
442 fix
->visual
= info
->cmap_adr
? FB_VISUAL_PSEUDOCOLOR
443 : FB_VISUAL_STATIC_PSEUDOCOLOR
;
446 fix
->visual
= /*info->cmap_adr ? FB_VISUAL_DIRECTCOLOR
447 : */FB_VISUAL_TRUECOLOR
;
449 var
->xoffset
= var
->yoffset
= 0;
450 var
->bits_per_pixel
= depth
;
453 var
->bits_per_pixel
= 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;
463 case 16: /* RGB 555 */
464 var
->bits_per_pixel
= 16;
465 var
->red
.offset
= 10;
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;
474 case 32: /* RGB 888 */
475 var
->bits_per_pixel
= 32;
476 var
->red
.offset
= 16;
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;
486 var
->red
.msb_right
= var
->green
.msb_right
= var
->blue
.msb_right
= var
->transp
.msb_right
= 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;
496 var
->vmode
= FB_VMODE_NONINTERLACED
;
499 disp
->cmap
.start
= 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
;
511 disp
->line_length
= fix
->line_length
;
512 disp
->can_soft_blank
= info
->cmap_adr
? 1 : 0;
515 #ifdef FBCON_HAS_CFB8
517 disp
->dispsw
= &fbcon_cfb8
;
520 #ifdef FBCON_HAS_CFB16
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);
531 info
->fbcon_cmap
.cfb16
[i
] =
532 (i
<< 10) | (i
<< 5) | i
;
535 #ifdef FBCON_HAS_CFB32
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) |
546 info
->fbcon_cmap
.cfb32
[i
] =
547 (i
<< 16) | (i
<< 8) | i
;
551 disp
->dispsw
= &fbcon_dummy
;
554 disp
->scrollmode
= SCROLL_YREDRAW
;
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
;
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
];
574 offb_set_var(var
, -1, &info
->info
);
576 if (register_framebuffer(&info
->info
) < 0) {
578 release_mem_region(res_start
, res_size
);
582 printk(KERN_INFO
"fb%d: Open Firmware frame buffer device on %s\n",
583 GET_FB_IDX(info
->info
.node
), full_name
);
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;
604 console_fb_info
= &info
->info
;
606 #endif /* CONFIG_FB_COMPAT_XPMAC) */
610 static int offbcon_switch(int con
, struct fb_info
*info
)
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
);
617 /* Install new colormap */
618 do_install_cmap(con
, info
);
623 * Update the `var' structure (called by fbcon.c)
626 static int offbcon_updatevar(int con
, struct fb_info
*info
)
636 static void offbcon_blank(int blank
, struct fb_info
*info
)
638 struct fb_info_offb
*info2
= (struct fb_info_offb
*)info
;
641 if (!info2
->cmap_adr
)
645 for (i
= 0; i
< 256; i
++) {
646 switch(info2
->cmap_type
) {
648 *info2
->cmap_adr
= i
;
650 for (j
= 0; j
< 3; j
++) {
651 *info2
->cmap_data
= 0;
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);
660 /* Set palette index & data */
661 out_8(info2
->cmap_adr
+ 0xb0, i
);
662 out_le32((unsigned *)(info2
->cmap_adr
+ 0xb4), 0);
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);
675 do_install_cmap(currcon
, info
);
679 * Read a single color register and split it into
680 * colors/transparent. Return != 0 for invalid regno.
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
)
686 struct fb_info_offb
*info2
= (struct fb_info_offb
*)info
;
688 if (!info2
->cmap_adr
|| regno
> 255)
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
;
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.
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
)
708 struct fb_info_offb
*info2
= (struct fb_info_offb
*)info
;
710 if (!info2
->cmap_adr
|| regno
> 255)
717 info2
->palette
[regno
].red
= red
;
718 info2
->palette
[regno
].green
= green
;
719 info2
->palette
[regno
].blue
= blue
;
721 switch(info2
->cmap_type
) {
723 *info2
->cmap_adr
= regno
;
725 *info2
->cmap_data
= red
;
727 *info2
->cmap_data
= green
;
729 *info2
->cmap_data
= blue
;
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);
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
));
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
));
754 switch (info2
->var
.bits_per_pixel
) {
755 #ifdef FBCON_HAS_CFB16
757 info2
->fbcon_cmap
.cfb16
[regno
] = (regno
<< 10) | (regno
<< 5) | regno
;
760 #ifdef FBCON_HAS_CFB32
763 int i
= (regno
<< 8) | regno
;
764 info2
->fbcon_cmap
.cfb32
[regno
] = (i
<< 16) | i
;
774 static void do_install_cmap(int con
, struct fb_info
*info
)
778 if (fb_display
[con
].cmap
.len
)
779 fb_set_cmap(&fb_display
[con
].cmap
, 1, offb_setcolreg
, info
);
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
);