1 /* $id: p9100fb.c,v 1.4 1999/08/18 10:55:01 shadow Exp $
2 * p9100fb.c: P9100 frame buffer driver
4 * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
7 #include <linux/module.h>
8 #include <linux/sched.h>
9 #include <linux/kernel.h>
10 #include <linux/errno.h>
11 #include <linux/string.h>
13 #include <linux/tty.h>
14 #include <linux/malloc.h>
15 #include <linux/vmalloc.h>
16 #include <linux/delay.h>
17 #include <linux/interrupt.h>
19 #include <linux/init.h>
20 #include <linux/selection.h>
22 #include <video/sbusfb.h>
25 #include <video/fbcon-cfb8.h>
29 static struct sbus_mmap_map p9100_mmap_map
[] = {
30 #if 0 /* For now, play we're a dumb color fb */
31 { P9100_CTL_OFF
, 0x38000000, 0x2000 },
32 { P9100_CMD_OFF
, 0x38002000, 0x2000 },
33 { P9100_FB_OFF
, 0x38800000, 0x200000 },
34 { CG3_MMAP_OFFSET
, 0x38800000, SBUS_MMAP_FBSIZE(1) },
36 { CG3_MMAP_OFFSET
, 0x0, SBUS_MMAP_FBSIZE(1) },
41 #define _READCTL(member, out) \
43 struct p9100_ctrl *actual; \
44 actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \
45 out = sbus_readl(&actual-> ## member ); \
48 #define READCTL(member, out) \
50 struct p9100_ctrl *enab, *actual; \
51 actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \
52 enab = (struct p9100_ctrl *)fb->s.p9100.fbmem; \
53 out = sbus_readl(&enab-> ## member ); \
54 out = sbus_readl(&actual-> ## member ); \
57 #define WRITECTL(member, val) \
60 struct p9100_ctrl *enab, *actual; \
61 actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \
62 enab = (struct p9100_ctrl *)fb->s.p9100.fbmem; \
63 __writetmp = sbus_readl(&enab-> ## member ); \
64 sbus_writel(val, &actual-> ## member ); \
67 static void p9100_loadcmap (struct fb_info_sbusfb
*fb
, struct display
*p
, int index
, int count
)
73 spin_lock_irqsave(&fb
->lock
, flags
);
75 _READCTL(pwrup_cfg
, tmp
);
76 WRITECTL(ramdac_cmap_wridx
, (index
<< 16));
78 for (i
= index
; count
--; i
++){
79 _READCTL(pwrup_cfg
, tmp
);
80 WRITECTL(ramdac_palette_data
, (fb
->color_map
CM(i
,0) << 16));
81 _READCTL(pwrup_cfg
, tmp
);
82 WRITECTL(ramdac_palette_data
, (fb
->color_map
CM(i
,1) << 16));
83 _READCTL(pwrup_cfg
, tmp
);
84 WRITECTL(ramdac_palette_data
, (fb
->color_map
CM(i
,2) << 16));
87 spin_unlock_irqrestore(&fb
->lock
, flags
);
90 static void p9100_blank (struct fb_info_sbusfb
*fb
)
95 spin_lock_irqsave(&fb
->lock
, flags
);
96 READCTL(vid_screenpaint_timectl1
, val
);
97 val
&= ~ SCREENPAINT_TIMECTL1_ENABLE_VIDEO
;
98 WRITECTL(vid_screenpaint_timectl1
, val
);
99 spin_unlock_irqrestore(&fb
->lock
, flags
);
102 static void p9100_unblank (struct fb_info_sbusfb
*fb
)
107 spin_lock_irqsave(&fb
->lock
, flags
);
108 READCTL(vid_screenpaint_timectl1
, val
);
109 val
|= SCREENPAINT_TIMECTL1_ENABLE_VIDEO
;
110 WRITECTL(vid_screenpaint_timectl1
, val
);
111 spin_unlock_irqrestore(&fb
->lock
, flags
);
114 static void p9100_margins (struct fb_info_sbusfb
*fb
, struct display
*p
, int x_margin
, int y_margin
)
116 p
->screen_base
+= (y_margin
- fb
->y_margin
) * p
->line_length
+
117 (x_margin
- fb
->x_margin
);
120 static char idstring
[60] __initdata
= { 0 };
122 char * __init
p9100fb_init(struct fb_info_sbusfb
*fb
)
124 struct fb_fix_screeninfo
*fix
= &fb
->fix
;
125 struct display
*disp
= &fb
->disp
;
126 struct fbtype
*type
= &fb
->type
;
127 struct sbus_dev
*sdev
= fb
->sbdp
;
128 unsigned long phys
= sdev
->reg_addrs
[2].phys_addr
;
131 #ifndef FBCON_HAS_CFB8
135 /* Control regs: fb->sbdp->reg_addrs[0].phys_addr
136 * Command regs: fb->sbdp->reg_addrs[1].phys_addr
137 * Frame buffer: fb->sbdp->reg_addrs[2].phys_addr
140 if (!fb
->s
.p9100
.ctrl
) {
141 fb
->s
.p9100
.ctrl
= (struct p9100_ctrl
*)
142 sbus_ioremap(&sdev
->resource
[0], 0,
143 sdev
->reg_addrs
[0].reg_size
, "p9100 ctrl");
146 strcpy(fb
->info
.modename
, "p9100");
147 strcpy(fix
->id
, "p9100");
148 fix
->accel
= FB_ACCEL_SUN_CGTHREE
;
149 fix
->line_length
= fb
->var
.xres_virtual
;
151 disp
->scrollmode
= SCROLL_YREDRAW
;
152 if (!disp
->screen_base
)
153 disp
->screen_base
= (char *)
154 sbus_ioremap(&sdev
->resource
[2], 0,
155 type
->fb_size
, "p9100 ram");
156 fb
->s
.p9100
.fbmem
= (volatile u32
*)disp
->screen_base
;
157 disp
->screen_base
+= fix
->line_length
* fb
->y_margin
+ fb
->x_margin
;
159 READCTL(sys_config
, tmp
);
160 switch ((tmp
>> SYS_CONFIG_PIXELSIZE_SHIFT
) & 7) {
174 printk("p9100: screen depth unknown: 0x%x", tmp
);
178 fb
->dispsw
= fbcon_cfb8
;
180 fb
->margins
= p9100_margins
;
181 fb
->loadcmap
= p9100_loadcmap
;
182 fb
->blank
= p9100_blank
;
183 fb
->unblank
= p9100_unblank
;
186 fb
->mmap_map
= p9100_mmap_map
;
188 sprintf(idstring
, "%s at 0x%x", "p9100",
189 (unsigned int)disp
->screen_base
);