This is pre8 ...
[linux-2.6/linux-mips.git] / drivers / video / chipsfb.c
blob974d2adc76d20d532a622aae9c9ce354ce619a29
1 /*
2 * drivers/video/chipsfb.c -- frame buffer device for
3 * Chips & Technologies 65550 chip.
5 * Copyright (C) 1998 Paul Mackerras
7 * This file is derived from the Powermac "chips" driver:
8 * Copyright (C) 1997 Fabio Riccardi.
9 * And from the frame buffer device for Open Firmware-initialized devices:
10 * Copyright (C) 1997 Geert Uytterhoeven.
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file COPYING in the main directory of this archive for
14 * more details.
17 #include <linux/config.h>
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/errno.h>
21 #include <linux/string.h>
22 #include <linux/mm.h>
23 #include <linux/tty.h>
24 #include <linux/malloc.h>
25 #include <linux/vmalloc.h>
26 #include <linux/delay.h>
27 #include <linux/interrupt.h>
28 #include <linux/fb.h>
29 #include <linux/selection.h>
30 #include <linux/init.h>
31 #include <linux/pci.h>
32 #ifdef CONFIG_FB_COMPAT_XPMAC
33 #include <asm/vc_ioctl.h>
34 #endif
35 #include <asm/io.h>
36 #include <asm/prom.h>
37 #include <asm/pci-bridge.h>
38 #include <linux/adb.h>
39 #include <linux/pmu.h>
41 #include <video/fbcon.h>
42 #include <video/fbcon-cfb8.h>
43 #include <video/fbcon-cfb16.h>
44 #include <video/macmodes.h>
46 static int currcon = 0;
48 struct fb_info_chips {
49 struct fb_info info;
50 struct fb_fix_screeninfo fix;
51 struct fb_var_screeninfo var;
52 struct display disp;
53 struct {
54 __u8 red, green, blue;
55 } palette[256];
56 unsigned long frame_buffer_phys;
57 __u8 *frame_buffer;
58 unsigned long blitter_regs_phys;
59 __u32 *blitter_regs;
60 unsigned long blitter_data_phys;
61 __u8 *blitter_data;
62 unsigned long io_base_phys;
63 __u8 *io_base;
64 struct fb_info_chips *next;
65 #ifdef CONFIG_PMAC_PBOOK
66 unsigned char *save_framebuffer;
67 #endif
68 #ifdef FBCON_HAS_CFB16
69 u16 fbcon_cfb16_cmap[16];
70 #endif
73 #define write_ind(num, val, ap, dp) do { \
74 out_8(p->io_base + (ap), (num)); out_8(p->io_base + (dp), (val)); \
75 } while (0)
76 #define read_ind(num, var, ap, dp) do { \
77 out_8(p->io_base + (ap), (num)); var = in_8(p->io_base + (dp)); \
78 } while (0);
80 /* extension registers */
81 #define write_xr(num, val) write_ind(num, val, 0x3d6, 0x3d7)
82 #define read_xr(num, var) read_ind(num, var, 0x3d6, 0x3d7)
83 /* flat panel registers */
84 #define write_fr(num, val) write_ind(num, val, 0x3d0, 0x3d1)
85 #define read_fr(num, var) read_ind(num, var, 0x3d0, 0x3d1)
86 /* CRTC registers */
87 #define write_cr(num, val) write_ind(num, val, 0x3d4, 0x3d5)
88 #define read_cr(num, var) read_ind(num, var, 0x3d4, 0x3d5)
89 /* graphics registers */
90 #define write_gr(num, val) write_ind(num, val, 0x3ce, 0x3cf)
91 #define read_gr(num, var) read_ind(num, var, 0x3ce, 0x3cf)
92 /* sequencer registers */
93 #define write_sr(num, val) write_ind(num, val, 0x3c4, 0x3c5)
94 #define read_sr(num, var) read_ind(num, var, 0x3c4, 0x3c5)
95 /* attribute registers - slightly strange */
96 #define write_ar(num, val) do { \
97 in_8(p->io_base + 0x3da); write_ind(num, val, 0x3c0, 0x3c0); \
98 } while (0)
99 #define read_ar(num, var) do { \
100 in_8(p->io_base + 0x3da); read_ind(num, var, 0x3c0, 0x3c1); \
101 } while (0)
103 static struct fb_info_chips *all_chips;
105 #ifdef CONFIG_PMAC_PBOOK
106 int chips_sleep_notify(struct pmu_sleep_notifier *self, int when);
107 static struct pmu_sleep_notifier chips_sleep_notifier = {
108 chips_sleep_notify, SLEEP_LEVEL_VIDEO,
110 #endif
113 * Exported functions
115 int chips_init(void);
116 void chips_of_init(struct device_node *dp);
118 static int chips_get_fix(struct fb_fix_screeninfo *fix, int con,
119 struct fb_info *info);
120 static int chips_get_var(struct fb_var_screeninfo *var, int con,
121 struct fb_info *info);
122 static int chips_set_var(struct fb_var_screeninfo *var, int con,
123 struct fb_info *info);
124 static int chips_pan_display(struct fb_var_screeninfo *var, int con,
125 struct fb_info *info);
126 static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con,
127 struct fb_info *info);
128 static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con,
129 struct fb_info *info);
130 static int chips_ioctl(struct inode *inode, struct file *file, u_int cmd,
131 u_long arg, int con, struct fb_info *info);
133 static struct fb_ops chipsfb_ops = {
134 owner: THIS_MODULE,
135 fb_get_fix: chips_get_fix,
136 fb_get_var: chips_get_var,
137 fb_set_var: chips_set_var,
138 fb_get_cmap: chips_get_cmap,
139 fb_set_cmap: chips_set_cmap,
140 fb_pan_display: chips_pan_display,
141 fb_ioctl: chips_ioctl,
144 static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green,
145 u_int *blue, u_int *transp, struct fb_info *info);
146 static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
147 u_int transp, struct fb_info *info);
148 static void do_install_cmap(int con, struct fb_info *info);
149 static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, int con, int bpp);
151 static int chips_get_fix(struct fb_fix_screeninfo *fix, int con,
152 struct fb_info *info)
154 struct fb_info_chips *cp = (struct fb_info_chips *) info;
156 *fix = cp->fix;
157 return 0;
160 static int chips_get_var(struct fb_var_screeninfo *var, int con,
161 struct fb_info *info)
163 struct fb_info_chips *cp = (struct fb_info_chips *) info;
165 *var = cp->var;
166 return 0;
169 static int chips_set_var(struct fb_var_screeninfo *var, int con,
170 struct fb_info *info)
172 struct fb_info_chips *cp = (struct fb_info_chips *) info;
173 struct display *disp = (con >= 0)? &fb_display[con]: &cp->disp;
175 if (var->xres > 800 || var->yres > 600
176 || var->xres_virtual > 800 || var->yres_virtual > 600
177 || (var->bits_per_pixel != 8 && var->bits_per_pixel != 16)
178 || var->nonstd
179 || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
180 return -EINVAL;
182 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW &&
183 var->bits_per_pixel != disp->var.bits_per_pixel) {
184 chips_set_bitdepth(cp, disp, con, var->bits_per_pixel);
187 return 0;
190 static int chips_pan_display(struct fb_var_screeninfo *var, int con,
191 struct fb_info *info)
193 if (var->xoffset != 0 || var->yoffset != 0)
194 return -EINVAL;
195 return 0;
198 static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con,
199 struct fb_info *info)
201 if (con == currcon) /* current console? */
202 return fb_get_cmap(cmap, kspc, chipsfb_getcolreg, info);
203 if (fb_display[con].cmap.len) /* non default colormap? */
204 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
205 else {
206 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
207 fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
209 return 0;
212 static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con,
213 struct fb_info *info)
215 int err;
217 if (!fb_display[con].cmap.len) { /* no colormap allocated? */
218 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
219 if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
220 return err;
222 if (con == currcon) /* current console? */
223 return fb_set_cmap(cmap, kspc, chipsfb_setcolreg, info);
224 else
225 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
226 return 0;
229 static int chips_ioctl(struct inode *inode, struct file *file, u_int cmd,
230 u_long arg, int con, struct fb_info *info)
232 return -EINVAL;
235 static int chipsfbcon_switch(int con, struct fb_info *info)
237 struct fb_info_chips *p = (struct fb_info_chips *) info;
238 int new_bpp, old_bpp;
240 /* Do we have to save the colormap? */
241 if (fb_display[currcon].cmap.len)
242 fb_get_cmap(&fb_display[currcon].cmap, 1, chipsfb_getcolreg, info);
244 new_bpp = fb_display[con].var.bits_per_pixel;
245 old_bpp = fb_display[currcon].var.bits_per_pixel;
246 currcon = con;
248 if (new_bpp != old_bpp)
249 chips_set_bitdepth(p, &fb_display[con], con, new_bpp);
251 do_install_cmap(con, info);
252 return 0;
255 static int chipsfb_updatevar(int con, struct fb_info *info)
257 return 0;
260 static void chipsfb_blank(int blank, struct fb_info *info)
262 struct fb_info_chips *p = (struct fb_info_chips *) info;
263 int i;
265 // used to disable backlight only for blank > 1, but it seems
266 // useful at blank = 1 too (saves battery, extends backlight life)
267 if (blank) {
268 pmu_enable_backlight(0);
269 /* get the palette from the chip */
270 for (i = 0; i < 256; ++i) {
271 out_8(p->io_base + 0x3c7, i);
272 udelay(1);
273 p->palette[i].red = in_8(p->io_base + 0x3c9);
274 p->palette[i].green = in_8(p->io_base + 0x3c9);
275 p->palette[i].blue = in_8(p->io_base + 0x3c9);
277 for (i = 0; i < 256; ++i) {
278 out_8(p->io_base + 0x3c8, i);
279 udelay(1);
280 out_8(p->io_base + 0x3c9, 0);
281 out_8(p->io_base + 0x3c9, 0);
282 out_8(p->io_base + 0x3c9, 0);
284 } else {
285 pmu_enable_backlight(1);
286 for (i = 0; i < 256; ++i) {
287 out_8(p->io_base + 0x3c8, i);
288 udelay(1);
289 out_8(p->io_base + 0x3c9, p->palette[i].red);
290 out_8(p->io_base + 0x3c9, p->palette[i].green);
291 out_8(p->io_base + 0x3c9, p->palette[i].blue);
296 static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green,
297 u_int *blue, u_int *transp, struct fb_info *info)
299 struct fb_info_chips *p = (struct fb_info_chips *) info;
301 if (regno > 255)
302 return 1;
303 *red = (p->palette[regno].red<<8) | p->palette[regno].red;
304 *green = (p->palette[regno].green<<8) | p->palette[regno].green;
305 *blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;
306 *transp = 0;
307 return 0;
310 static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
311 u_int transp, struct fb_info *info)
313 struct fb_info_chips *p = (struct fb_info_chips *) info;
315 if (regno > 255)
316 return 1;
317 red >>= 8;
318 green >>= 8;
319 blue >>= 8;
320 p->palette[regno].red = red;
321 p->palette[regno].green = green;
322 p->palette[regno].blue = blue;
323 out_8(p->io_base + 0x3c8, regno);
324 udelay(1);
325 out_8(p->io_base + 0x3c9, red);
326 out_8(p->io_base + 0x3c9, green);
327 out_8(p->io_base + 0x3c9, blue);
329 #ifdef FBCON_HAS_CFB16
330 if (regno < 16)
331 p->fbcon_cfb16_cmap[regno] = ((red & 0xf8) << 7)
332 | ((green & 0xf8) << 2) | ((blue & 0xf8) >> 3);
333 #endif
335 return 0;
338 static void do_install_cmap(int con, struct fb_info *info)
340 if (con != currcon)
341 return;
342 if (fb_display[con].cmap.len)
343 fb_set_cmap(&fb_display[con].cmap, 1, chipsfb_setcolreg, info);
344 else {
345 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
346 fb_set_cmap(fb_default_cmap(size), 1, chipsfb_setcolreg, info);
350 static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, int con, int bpp)
352 int err;
353 struct fb_fix_screeninfo* fix = &p->fix;
354 struct fb_var_screeninfo* var = &p->var;
356 if (bpp == 16) {
357 if (con == currcon) {
358 write_cr(0x13, 200); // Set line length (doublewords)
359 write_xr(0x81, 0x14); // 15 bit (555) color mode
360 write_xr(0x82, 0x00); // Disable palettes
361 write_xr(0x20, 0x10); // 16 bit blitter mode
364 fix->line_length = 800*2;
365 fix->visual = FB_VISUAL_TRUECOLOR;
367 var->red.offset = 10;
368 var->green.offset = 5;
369 var->blue.offset = 0;
370 var->red.length = var->green.length = var->blue.length = 5;
372 #ifdef FBCON_HAS_CFB16
373 disp->dispsw = &fbcon_cfb16;
374 disp->dispsw_data = p->fbcon_cfb16_cmap;
375 #else
376 disp->dispsw = &fbcon_dummy;
377 #endif
378 } else if (bpp == 8) {
379 if (con == currcon) {
380 write_cr(0x13, 100); // Set line length (doublewords)
381 write_xr(0x81, 0x12); // 8 bit color mode
382 write_xr(0x82, 0x08); // Graphics gamma enable
383 write_xr(0x20, 0x00); // 8 bit blitter mode
386 fix->line_length = 800;
387 fix->visual = FB_VISUAL_PSEUDOCOLOR;
389 var->red.offset = var->green.offset = var->blue.offset = 0;
390 var->red.length = var->green.length = var->blue.length = 8;
392 #ifdef FBCON_HAS_CFB8
393 disp->dispsw = &fbcon_cfb8;
394 #else
395 disp->dispsw = &fbcon_dummy;
396 #endif
399 var->bits_per_pixel = bpp;
400 disp->line_length = p->fix.line_length;
401 disp->visual = fix->visual;
402 disp->var = *var;
404 #if (defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_FB_COMPAT_XPMAC))
405 display_info.depth = bpp;
406 display_info.pitch = fix->line_length;
407 #endif
409 if (p->info.changevar)
410 (*p->info.changevar)(con);
412 if ((err = fb_alloc_cmap(&disp->cmap, 0, 0)))
413 return;
414 do_install_cmap(con, (struct fb_info *)p);
417 struct chips_init_reg {
418 unsigned char addr;
419 unsigned char data;
422 #define N_ELTS(x) (sizeof(x) / sizeof(x[0]))
424 static struct chips_init_reg chips_init_sr[] = {
425 { 0x00, 0x03 },
426 { 0x01, 0x01 },
427 { 0x02, 0x0f },
428 { 0x04, 0x0e }
431 static struct chips_init_reg chips_init_gr[] = {
432 { 0x05, 0x00 },
433 { 0x06, 0x0d },
434 { 0x08, 0xff }
437 static struct chips_init_reg chips_init_ar[] = {
438 { 0x10, 0x01 },
439 { 0x12, 0x0f },
440 { 0x13, 0x00 }
443 static struct chips_init_reg chips_init_cr[] = {
444 { 0x00, 0x7f },
445 { 0x01, 0x63 },
446 { 0x02, 0x63 },
447 { 0x03, 0x83 },
448 { 0x04, 0x66 },
449 { 0x05, 0x10 },
450 { 0x06, 0x72 },
451 { 0x07, 0x3e },
452 { 0x08, 0x00 },
453 { 0x09, 0x40 },
454 { 0x0c, 0x00 },
455 { 0x0d, 0x00 },
456 { 0x10, 0x59 },
457 { 0x11, 0x0d },
458 { 0x12, 0x57 },
459 { 0x13, 0x64 },
460 { 0x14, 0x00 },
461 { 0x15, 0x57 },
462 { 0x16, 0x73 },
463 { 0x17, 0xe3 },
464 { 0x18, 0xff },
465 { 0x30, 0x02 },
466 { 0x31, 0x02 },
467 { 0x32, 0x02 },
468 { 0x33, 0x02 },
469 { 0x40, 0x00 },
470 { 0x41, 0x00 },
471 { 0x40, 0x80 }
474 static struct chips_init_reg chips_init_fr[] = {
475 { 0x01, 0x02 },
476 { 0x03, 0x08 },
477 { 0x04, 0x81 },
478 { 0x05, 0x21 },
479 { 0x08, 0x0c },
480 { 0x0a, 0x74 },
481 { 0x0b, 0x11 },
482 { 0x10, 0x0c },
483 { 0x11, 0xe0 },
484 /* { 0x12, 0x40 }, -- 3400 needs 40, 2400 needs 48, no way to tell */
485 { 0x20, 0x63 },
486 { 0x21, 0x68 },
487 { 0x22, 0x19 },
488 { 0x23, 0x7f },
489 { 0x24, 0x68 },
490 { 0x26, 0x00 },
491 { 0x27, 0x0f },
492 { 0x30, 0x57 },
493 { 0x31, 0x58 },
494 { 0x32, 0x0d },
495 { 0x33, 0x72 },
496 { 0x34, 0x02 },
497 { 0x35, 0x22 },
498 { 0x36, 0x02 },
499 { 0x37, 0x00 }
502 static struct chips_init_reg chips_init_xr[] = {
503 { 0xce, 0x00 }, /* set default memory clock */
504 { 0xcc, 0x43 }, /* memory clock ratio */
505 { 0xcd, 0x18 },
506 { 0xce, 0xa1 },
507 { 0xc8, 0x84 },
508 { 0xc9, 0x0a },
509 { 0xca, 0x00 },
510 { 0xcb, 0x20 },
511 { 0xcf, 0x06 },
512 { 0xd0, 0x0e },
513 { 0x09, 0x01 },
514 { 0x0a, 0x02 },
515 { 0x0b, 0x01 },
516 { 0x20, 0x00 },
517 { 0x40, 0x03 },
518 { 0x41, 0x01 },
519 { 0x42, 0x00 },
520 { 0x80, 0x82 },
521 { 0x81, 0x12 },
522 { 0x82, 0x08 },
523 { 0xa0, 0x00 },
524 { 0xa8, 0x00 }
527 static void __init chips_hw_init(struct fb_info_chips *p)
529 int i;
531 for (i = 0; i < N_ELTS(chips_init_xr); ++i)
532 write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
533 out_8(p->io_base + 0x3c2, 0x29); /* set misc output reg */
534 for (i = 0; i < N_ELTS(chips_init_sr); ++i)
535 write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
536 for (i = 0; i < N_ELTS(chips_init_gr); ++i)
537 write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
538 for (i = 0; i < N_ELTS(chips_init_ar); ++i)
539 write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
540 for (i = 0; i < N_ELTS(chips_init_cr); ++i)
541 write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
542 for (i = 0; i < N_ELTS(chips_init_fr); ++i)
543 write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
546 static void __init init_chips(struct fb_info_chips *p)
548 int i;
550 strcpy(p->fix.id, "C&T 65550");
551 p->fix.smem_start = p->frame_buffer_phys;
553 // FIXME: Assumes 1MB frame buffer, but 65550 supports 1MB or 2MB.
554 // * "3500" PowerBook G3 (the original PB G3) has 2MB.
555 // * 2400 has 1MB composed of 2 Mitsubishi M5M4V4265CTP DRAM chips.
556 // Motherboard actually supports 2MB -- there are two blank locations
557 // for a second pair of DRAMs. (Thanks, Apple!)
558 // * 3400 has 1MB (I think). Don't know if it's expandable.
559 // -- Tim Seufert
560 p->fix.smem_len = 0x100000; // 1MB
561 p->fix.mmio_start = p->io_base_phys;
562 p->fix.type = FB_TYPE_PACKED_PIXELS;
563 p->fix.visual = FB_VISUAL_PSEUDOCOLOR;
564 p->fix.line_length = 800;
566 p->var.xres = 800;
567 p->var.yres = 600;
568 p->var.xres_virtual = 800;
569 p->var.yres_virtual = 600;
570 p->var.bits_per_pixel = 8;
571 p->var.red.length = p->var.green.length = p->var.blue.length = 8;
572 p->var.height = p->var.width = -1;
573 p->var.vmode = FB_VMODE_NONINTERLACED;
574 p->var.pixclock = 10000;
575 p->var.left_margin = p->var.right_margin = 16;
576 p->var.upper_margin = p->var.lower_margin = 16;
577 p->var.hsync_len = p->var.vsync_len = 8;
579 p->disp.var = p->var;
580 p->disp.cmap.red = NULL;
581 p->disp.cmap.green = NULL;
582 p->disp.cmap.blue = NULL;
583 p->disp.cmap.transp = NULL;
584 p->disp.screen_base = p->frame_buffer;
585 p->disp.visual = p->fix.visual;
586 p->disp.type = p->fix.type;
587 p->disp.type_aux = p->fix.type_aux;
588 p->disp.line_length = p->fix.line_length;
589 p->disp.can_soft_blank = 1;
590 p->disp.dispsw = &fbcon_cfb8;
591 p->disp.scrollmode = SCROLL_YREDRAW;
593 strcpy(p->info.modename, p->fix.id);
594 p->info.node = -1;
595 p->info.fbops = &chipsfb_ops;
596 p->info.disp = &p->disp;
597 p->info.fontname[0] = 0;
598 p->info.changevar = NULL;
599 p->info.switch_con = &chipsfbcon_switch;
600 p->info.updatevar = &chipsfb_updatevar;
601 p->info.blank = &chipsfb_blank;
602 p->info.flags = FBINFO_FLAG_DEFAULT;
604 for (i = 0; i < 16; ++i) {
605 int j = color_table[i];
606 p->palette[i].red = default_red[j];
607 p->palette[i].green = default_grn[j];
608 p->palette[i].blue = default_blu[j];
611 if (register_framebuffer(&p->info) < 0) {
612 kfree(p);
613 return;
616 printk("fb%d: Chips 65550 frame buffer (%dK RAM detected)\n",
617 GET_FB_IDX(p->info.node), p->fix.smem_len / 1024);
619 chips_hw_init(p);
621 #ifdef CONFIG_FB_COMPAT_XPMAC
622 if (!console_fb_info) {
623 display_info.height = p->var.yres;
624 display_info.width = p->var.xres;
625 display_info.depth = 8;
626 display_info.pitch = p->fix.line_length;
627 display_info.mode = VMODE_800_600_60;
628 strncpy(display_info.name, "chips65550",
629 sizeof(display_info.name));
630 display_info.fb_address = p->frame_buffer_phys;
631 display_info.cmap_adr_address = p->io_base_phys + 0x3c8;
632 display_info.cmap_data_address = p->io_base_phys + 0x3c9;
633 display_info.disp_reg_address = p->blitter_regs_phys;
634 console_fb_info = &p->info;
636 #endif /* CONFIG_FB_COMPAT_XPMAC */
638 #ifdef CONFIG_PMAC_PBOOK
639 if (all_chips == NULL)
640 pmu_register_sleep_notifier(&chips_sleep_notifier);
641 #endif /* CONFIG_PMAC_PBOOK */
642 p->next = all_chips;
643 all_chips = p;
646 int __init chips_init(void)
648 #ifndef CONFIG_FB_OF
649 struct device_node *dp;
651 dp = find_devices("chips65550");
652 if (dp != 0)
653 chips_of_init(dp);
654 #endif /* CONFIG_FB_OF */
655 return 0;
658 void __init chips_of_init(struct device_node *dp)
660 struct fb_info_chips *p;
661 unsigned long addr;
662 unsigned char bus, devfn;
663 unsigned short cmd;
665 if (dp->n_addrs == 0)
666 return;
667 p = kmalloc(sizeof(*p), GFP_ATOMIC);
668 if (p == 0)
669 return;
670 memset(p, 0, sizeof(*p));
671 addr = dp->addrs[0].address;
672 #ifdef __BIG_ENDIAN
673 addr += 0x800000; // Use big-endian aperture
674 #endif
675 p->frame_buffer_phys = addr;
676 p->frame_buffer = __ioremap(addr, 0x200000, _PAGE_NO_CACHE);
677 p->blitter_regs_phys = addr + 0x400000;
678 p->blitter_regs = ioremap(addr + 0x400000, 0x1000);
679 p->blitter_data_phys = addr + 0x410000;
680 p->blitter_data = ioremap(addr + 0x410000, 0x10000);
682 if (pci_device_loc(dp, &bus, &devfn) == 0) {
683 pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
684 cmd |= 3; /* enable memory and IO space */
685 pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
686 p->io_base = (__u8 *) pci_io_base(bus);
687 /* XXX really want the physical address here */
688 p->io_base_phys = (unsigned long) pci_io_base(bus);
691 /* Clear the entire framebuffer */
692 memset(p->frame_buffer, 0, 0x100000);
694 /* turn on the backlight */
695 pmu_enable_backlight(1);
697 init_chips(p);
700 #ifdef CONFIG_PMAC_PBOOK
702 * Save the contents of the frame buffer when we go to sleep,
703 * and restore it when we wake up again.
706 chips_sleep_notify(struct pmu_sleep_notifier *self, int when)
708 struct fb_info_chips *p;
710 for (p = all_chips; p != NULL; p = p->next) {
711 int nb = p->var.yres * p->fix.line_length;
713 switch (when) {
714 case PBOOK_SLEEP_REQUEST:
715 p->save_framebuffer = vmalloc(nb);
716 if (p->save_framebuffer == NULL)
717 return PBOOK_SLEEP_REFUSE;
718 break;
719 case PBOOK_SLEEP_REJECT:
720 if (p->save_framebuffer) {
721 vfree(p->save_framebuffer);
722 p->save_framebuffer = 0;
724 break;
726 case PBOOK_SLEEP_NOW:
727 chipsfb_blank(1, (struct fb_info *)p);
728 if (p->save_framebuffer)
729 memcpy(p->save_framebuffer,
730 p->frame_buffer, nb);
731 break;
732 case PBOOK_WAKE:
733 if (p->save_framebuffer) {
734 memcpy(p->frame_buffer,
735 p->save_framebuffer, nb);
736 vfree(p->save_framebuffer);
737 p->save_framebuffer = 0;
739 chipsfb_blank(0, (struct fb_info *)p);
740 break;
743 return PBOOK_SLEEP_OK;
745 #endif /* CONFIG_PMAC_PBOOK */