Import 2.3.13
[davej-history.git] / drivers / video / macfb.c
blob0f1a54592719d07cb702fc4d65fc22d992f43d73
1 /*
2 * We've been given MAC frame buffer info by the booter. Now go set it up
3 */
5 #include <linux/module.h>
6 #include <linux/kernel.h>
7 #include <linux/sched.h>
8 #include <linux/errno.h>
9 #include <linux/string.h>
10 #include <linux/mm.h>
11 #include <linux/tty.h>
12 #include <linux/malloc.h>
13 #include <linux/delay.h>
14 #include <linux/nubus.h>
15 #include <linux/init.h>
17 #include <asm/setup.h>
18 #include <asm/bootinfo.h>
19 #include <asm/uaccess.h>
20 #include <asm/pgtable.h>
21 #include <asm/irq.h>
22 #include <asm/macintosh.h>
23 #include <linux/fb.h>
25 #include <video/fbcon.h>
26 /* conditionalize these ?? */
27 #include <video/fbcon-mfb.h>
28 #include <video/fbcon-cfb2.h>
29 #include <video/fbcon-cfb4.h>
30 #include <video/fbcon-cfb8.h>
32 #define arraysize(x) (sizeof(x)/sizeof(*(x)))
34 static struct fb_var_screeninfo macfb_defined={
35 0,0,0,0, /* W,H, W, H (virtual) load xres,xres_virtual*/
36 0,0, /* virtual -> visible no offset */
37 8, /* depth -> load bits_per_pixel */
38 0, /* greyscale ? */
39 {0,0,0}, /* R */
40 {0,0,0}, /* G */
41 {0,0,0}, /* B */
42 {0,0,0}, /* transparency */
43 0, /* standard pixel format */
44 FB_ACTIVATE_NOW,
45 274,195, /* 14" monitor *Mikael Nykvist's anyway* */
46 0, /* The only way to accelerate a mac is .. */
47 0L,0L,0L,0L,0L,
48 0L,0L,0, /* No sync info */
49 FB_VMODE_NONINTERLACED,
50 {0,0,0,0,0,0}
53 #define NUM_TOTAL_MODES 1
54 #define NUM_PREDEF_MODES 1
56 static struct display disp;
57 static struct fb_info fb_info;
59 static int inverse = 0;
61 struct macfb_par
63 void *unused;
66 static int currcon = 0;
67 static int current_par_valid = 0;
68 struct macfb_par current_par;
70 static int mac_xres,mac_yres,mac_depth, mac_xbytes, mac_vxres;
71 static unsigned long mac_videobase;
72 static unsigned long mac_videosize;
75 * Open/Release the frame buffer device
78 static int macfb_open(struct fb_info *info, int user)
81 * Nothing, only a usage count for the moment
83 MOD_INC_USE_COUNT;
84 return(0);
87 static int macfb_release(struct fb_info *info, int user)
89 MOD_DEC_USE_COUNT;
90 return(0);
93 static void macfb_encode_var(struct fb_var_screeninfo *var,
94 struct macfb_par *par)
96 memset(var, 0, sizeof(struct fb_var_screeninfo));
97 var->xres=mac_xres;
98 var->yres=mac_yres;
99 var->xres_virtual=mac_vxres;
100 var->yres_virtual=var->yres;
101 var->xoffset=0;
102 var->yoffset=0;
103 var->bits_per_pixel = mac_depth;
104 var->grayscale=0;
105 var->transp.offset=0;
106 var->transp.length=0;
107 var->transp.msb_right=0;
108 var->nonstd=0;
109 var->activate=0;
110 var->height= -1;
111 var->width= -1;
112 var->vmode=FB_VMODE_NONINTERLACED;
113 var->pixclock=0;
114 var->sync=0;
115 var->left_margin=0;
116 var->right_margin=0;
117 var->upper_margin=0;
118 var->lower_margin=0;
119 var->hsync_len=0;
120 var->vsync_len=0;
121 return;
125 static void macfb_get_par(struct macfb_par *par)
127 *par=current_par;
130 static void macfb_set_par(struct macfb_par *par)
132 current_par_valid=1;
135 static int fb_update_var(int con, struct fb_info *info)
137 return 0;
140 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
142 struct macfb_par par;
144 macfb_get_par(&par);
145 macfb_encode_var(var, &par);
146 return 0;
149 extern int console_loglevel;
151 static void macfb_encode_fix(struct fb_fix_screeninfo *fix,
152 struct macfb_par *par)
154 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
155 strcpy(fix->id,"Macintosh");
158 * fbmem.c accepts non page aligned mappings now!
160 fix->smem_start=(char *)mac_videobase;
161 fix->smem_len=mac_videosize;
162 fix->type = FB_TYPE_PACKED_PIXELS;
163 if (mac_depth == 1)
164 fix->visual = FB_VISUAL_MONO01;
165 else
166 fix->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
167 fix->xpanstep=0;
168 fix->ypanstep=0;
169 fix->ywrapstep=0;
170 fix->line_length=mac_xbytes;
171 return;
174 static int macfb_get_fix(struct fb_fix_screeninfo *fix, int con,
175 struct fb_info *info)
177 struct macfb_par par;
178 macfb_get_par(&par);
179 macfb_encode_fix(fix, &par);
180 return 0;
183 static int macfb_get_var(struct fb_var_screeninfo *var, int con,
184 struct fb_info *info)
186 struct macfb_par par;
187 if(con==-1)
189 macfb_get_par(&par);
190 macfb_encode_var(var, &par);
192 else
193 *var=fb_display[con].var;
194 return 0;
197 static void macfb_set_disp(int con)
199 struct fb_fix_screeninfo fix;
200 struct display *display;
202 if (con >= 0)
203 display = &fb_display[con];
204 else
205 display = &disp; /* used during initialization */
207 macfb_get_fix(&fix, con, 0);
209 display->screen_base = fix.smem_start;
210 display->visual = fix.visual;
211 display->type = fix.type;
212 display->type_aux = fix.type_aux;
213 display->ypanstep = fix.ypanstep;
214 display->ywrapstep = fix.ywrapstep;
215 display->line_length = fix.line_length;
216 display->next_line = fix.line_length;
217 display->can_soft_blank = 0;
218 display->inverse =
219 (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
221 switch (mac_depth) {
222 #ifdef FBCON_HAS_MFB
223 case 1:
224 display->dispsw = &fbcon_mfb;
225 break;
226 #endif
227 #ifdef FBCON_HAS_CFB2
228 case 2:
229 display->dispsw = &fbcon_cfb2;
230 break;
231 #endif
232 #ifdef FBCON_HAS_CFB4
233 case 4:
234 display->dispsw = &fbcon_cfb4;
235 break;
236 #endif
237 #ifdef FBCON_HAS_CFB8
238 case 8:
239 display->dispsw = &fbcon_cfb8;
240 break;
241 #endif
242 default:
243 display->dispsw = &fbcon_dummy;
244 break;
248 static int macfb_set_var(struct fb_var_screeninfo *var, int con,
249 struct fb_info *info)
251 int err;
253 if ((err=do_fb_set_var(var, 1)))
254 return err;
255 return 0;
259 * Color map handling - hardcoded maps!!
261 * 2.0 color map primitives, copied from atafb.c
265 * should be kmalloc'ed on request
267 static short red256[256], green256[256], blue256[256];
269 static short red16[]=
270 { 0x0000,0x0000,0x0000,0x0000,0x8080,0x8080,0x8080,0xc0c0,
271 0x8080,0x0000,0x0000,0x0000,0xffff,0xffff,0xffff,0xffff};
272 static short green16[]=
273 { 0x0000,0x0000,0x8080,0x8080,0x0000,0x0000,0x8080,0xc0c0,
274 0x8080,0x0000,0xffff,0xffff,0x0000,0x0000,0xffff,0xffff};
275 static short blue16[]=
276 { 0x0000,0x8080,0x0000,0x8080,0x0000,0x8080,0x0000,0xc0c0,
277 0x8080,0xffff,0x0000,0xffff,0x0000,0xffff,0x0000,0xffff};
279 static short red4[]=
280 { 0x0000,0x8080,0xffff,0xffff};
281 static short green4[]=
282 { 0x0000,0x8080,0x0000,0xffff};
283 static short blue4[]=
284 { 0x0000,0x8080,0x0000,0xffff};
286 static short red2[]=
287 { 0x0000,0xffff};
288 static short green2[]=
289 { 0x0000,0xffff};
290 static short blue2[]=
291 { 0x0000,0xffff};
293 struct fb_cmap default_256_colors = { 0, 256, red256, green256, blue256, NULL };
294 struct fb_cmap default_16_colors = { 0, 16, red16, green16, blue16, NULL };
295 struct fb_cmap default_4_colors = { 0, 4, red4, green4, blue4, NULL };
296 struct fb_cmap default_2_colors = { 0, 2, red2, green2, blue2, NULL };
298 static int mac_set_cmap256(struct fb_cmap* cmap)
300 int i,start;
301 unsigned short *red,*green,*blue;
302 unsigned short cval[] = {0xffff, 0xcccc, 0x9999,
303 0x6666, 0x3333, 0x0000 };
304 unsigned short gval[] = {0x0a0a, 0x1414, 0x1e1e,
305 0x2828, 0x3232, 0x3c3c,
306 0x4646, 0x5050, 0x5a5a,
307 0x6464, 0x6e6e, 0x7878,
308 0x8282, 0x8c8c, 0x9696,
309 0xa0a0, 0xaaaa, 0xb4b4,
310 0xbebe, 0xc8c8, 0xd2d2,
311 0xdcdc, 0xe6e6, 0xf0f0};
313 red=cmap->red;
314 green=cmap->green;
315 blue=cmap->blue;
316 start=cmap->start;
318 if (start < 0)
319 return -EINVAL;
320 if (cmap->len < 255)
321 return -EINVAL;
322 /* 16 ANSI colors */
323 for (i=0 ; i < 16 ; i++) {
324 *red++ = red16[i];
325 *green++ = green16[i];
326 *blue++ = blue16[i];
328 /* 216 colors (6x6x6) map) */
329 for (i=16 ; i < 232 ; i++) {
330 *red++ = cval[(i-16)/36];
331 *green++ = cval[((i-16)/6)%6];
332 *blue++ = cval[(i-16)%6];
334 /* 24 grays */
335 for (i=232 ; i < 256 ; i++) {
336 *red = *green = *blue = gval[i-232];
337 red++;
338 green++;
339 blue++;
341 return 0;
344 static struct fb_cmap * mac_get_default_cmap(int bpp)
346 if (bpp == 1)
347 return &default_2_colors;
348 if (bpp == 2)
349 return &default_4_colors;
350 if (bpp == 4)
351 return &default_16_colors;
352 return &default_256_colors;
355 static void memcpy_fs(int fsfromto, void *to, void *from, int len)
357 switch (fsfromto) {
358 case 0:
359 memcpy(to, from, len);
360 return;
361 case 1:
362 copy_from_user(to, from, len);
363 return;
364 case 2:
365 copy_to_user(to, from, len);
366 return;
370 static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
372 int size;
373 int tooff=0, fromoff=0;
375 if (to->start > from->start)
376 fromoff=to->start-from->start;
377 else
378 tooff=from->start-to->start;
379 size=to->len-tooff;
380 if (size > from->len-fromoff)
381 size=from->len-fromoff;
382 if (size < 0)
383 return;
384 size*=sizeof(unsigned short);
385 memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
386 memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
387 memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
388 if (from->transp && to->transp)
389 memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
392 static int macfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
393 struct fb_info *info)
395 #if 0
396 printk("macfb_get_cmap: not supported!\n");
397 /* interferes with X11 */
398 if (console_loglevel < 7)
399 return -EINVAL;
400 if (con == currcon) /* current console? */
401 return fb_get_cmap(cmap, kspc, 0 /*offb_getcolreg*/, info);
402 else if (fb_display[con].cmap.len) /* non default colormap? */
403 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
404 else
405 fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel),
406 cmap, kspc ? 0 : 2);
407 #endif
408 copy_cmap(mac_get_default_cmap(fb_display[con].var.bits_per_pixel),
409 cmap, kspc ? 0 : 2);
410 return 0;
414 static int macfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
415 struct fb_info *info)
417 #if 0
418 printk("macfb_set_cmap: not supported!\n");
419 if (console_loglevel < 7)
420 return -EINVAL;
421 if (!fb_display[con].cmap.len) { /* no colormap allocated? */
422 if ((err = fb_alloc_cmap(&fb_display[con].cmap,
423 1<<fb_display[con].var.bits_per_pixel, 0)))
424 return err;
426 if (con == currcon) /* current console? */
427 return fb_set_cmap(cmap, kspc, 1 /*offb_setcolreg*/, info);
428 else
429 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
430 #endif
431 return 0;
434 static int macfb_pan_display(struct fb_var_screeninfo *var, int con,
435 struct fb_info *info)
437 /* no panning */
438 printk("macfb_pan: not supported!\n");
439 return -EINVAL;
442 static int macfb_ioctl(struct inode *inode, struct file *file,
443 unsigned int cmd, unsigned long arg, int con,
444 struct fb_info *info)
446 printk("macfb_ioctl: not supported!\n");
447 return -EINVAL;
450 static struct fb_ops macfb_ops = {
451 macfb_open,
452 macfb_release,
453 macfb_get_fix,
454 macfb_get_var,
455 macfb_set_var,
456 macfb_get_cmap,
457 macfb_set_cmap,
458 macfb_pan_display,
459 macfb_ioctl
462 void macfb_setup(char *options, int *ints)
464 char *this_opt;
466 fb_info.fontname[0] = '\0';
468 if (!options || !*options)
469 return;
471 for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
472 if (!*this_opt) continue;
474 if (! strcmp(this_opt, "inverse"))
475 inverse=1;
476 else if (!strncmp(this_opt, "font:", 5)) {
477 strcpy(fb_info.fontname, this_opt+5);
478 printk("macfb_setup: option %s\n", this_opt);
483 static int macfb_switch(int con, struct fb_info *info)
485 do_fb_set_var(&fb_display[con].var,1);
486 currcon=con;
487 return 0;
490 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
492 static void macfb_blank(int blank, struct fb_info *info)
494 /* Not supported */
498 * Nubus call back. This will give us our board identity and also
499 * other useful info we need later
502 static int nubus_video_card(struct nubus_device_specifier *ns, int slot, struct nubus_type *nt)
504 if(nt->category==NUBUS_CAT_DISPLAY)
505 return 0;
506 /* Claim all video cards. We don't yet do driver specifics though. */
507 return -ENODEV;
510 static struct nubus_device_specifier nb_video={
511 nubus_video_card,
512 NULL
515 void __init macfb_init(void)
517 /* nubus_remap the video .. */
519 if (!MACH_IS_MAC)
520 return;
522 mac_xres=mac_bi_data.dimensions&0xFFFF;
523 mac_yres=(mac_bi_data.dimensions&0xFFFF0000)>>16;
524 mac_depth=mac_bi_data.videodepth;
525 mac_xbytes=mac_bi_data.videorow;
526 mac_vxres = (mac_xbytes/mac_depth)*8;
527 mac_videosize=mac_xbytes*mac_yres;
528 mac_videobase=mac_bi_data.videoaddr;
530 printk("macfb_init: xres %d yres %d bpp %d addr %lx size %ld \n",
531 mac_xres, mac_yres, mac_depth, mac_videobase, mac_videosize);
534 * Fill in the available video resolution
537 macfb_defined.xres=mac_xres;
538 macfb_defined.yres=mac_yres;
539 macfb_defined.xres_virtual=mac_vxres;
540 macfb_defined.yres_virtual=mac_yres;
541 macfb_defined.bits_per_pixel=mac_depth;
545 * Let there be consoles..
547 strcpy(fb_info.modename, "Macintosh Builtin ");
548 fb_info.changevar = NULL;
549 fb_info.node = -1;
550 fb_info.fbops = &macfb_ops;
551 fb_info.disp=&disp;
552 fb_info.switch_con=&macfb_switch;
553 fb_info.updatevar=&fb_update_var;
554 fb_info.blank=&macfb_blank;
555 fb_info.flags = FBINFO_FLAG_DEFAULT;
556 do_fb_set_var(&macfb_defined,1);
558 macfb_get_var(&disp.var, -1, &fb_info);
559 macfb_set_disp(-1);
562 * Fill in the 8 bit color table if required
564 if (mac_depth == 8)
565 mac_set_cmap256(&default_256_colors);
568 * Register the nubus hook
571 register_nubus_device(&nb_video);
573 if (register_framebuffer(&fb_info) < 0)
575 return;
578 printk("fb%d: %s frame buffer device using %ldK of video memory\n",
579 GET_FB_IDX(fb_info.node), fb_info.modename, mac_videosize>>10);
582 #if 0
584 * These two auxiliary debug functions should go away ASAP. Only usage:
585 * before the console output is up (after head.S come some other crucial
586 * setup routines :-)
588 * Now in debug.c ...
590 #endif