1 /* bw2.c: BWTWO frame buffer driver
3 * Copyright (C) 2003 David S. Miller (davem@redhat.com)
4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
5 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
6 * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
8 * Driver layout based loosely on tgafb.c, see that file for credits.
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
15 #include <linux/slab.h>
16 #include <linux/delay.h>
17 #include <linux/init.h>
23 #include <asm/oplib.h>
27 #include <asm/sun4paddr.h>
36 static int bw2_blank(int, struct fb_info
*);
38 static int bw2_mmap(struct fb_info
*, struct file
*, struct vm_area_struct
*);
39 static int bw2_ioctl(struct fb_info
*, unsigned int, unsigned long);
42 * Frame buffer operations
45 static struct fb_ops bw2_ops
= {
47 .fb_blank
= bw2_blank
,
48 .fb_fillrect
= cfb_fillrect
,
49 .fb_copyarea
= cfb_copyarea
,
50 .fb_imageblit
= cfb_imageblit
,
52 .fb_ioctl
= bw2_ioctl
,
54 .fb_compat_ioctl
= sbusfb_compat_ioctl
,
58 /* OBio addresses for the bwtwo registers */
59 #define BWTWO_REGISTER_OFFSET 0x400000
63 volatile u32 color_map
;
72 volatile u8 cursor_start
;
73 volatile u8 cursor_end
;
74 volatile u8 h_blank_start
;
75 volatile u8 h_blank_end
;
76 volatile u8 h_sync_start
;
77 volatile u8 h_sync_end
;
78 volatile u8 comp_sync_end
;
79 volatile u8 v_blank_start_high
;
80 volatile u8 v_blank_start_low
;
81 volatile u8 v_blank_end
;
82 volatile u8 v_sync_start
;
83 volatile u8 v_sync_end
;
84 volatile u8 xfer_holdoff_start
;
85 volatile u8 xfer_holdoff_end
;
88 /* Status Register Constants */
89 #define BWTWO_SR_RES_MASK 0x70
90 #define BWTWO_SR_1600_1280 0x50
91 #define BWTWO_SR_1152_900_76_A 0x40
92 #define BWTWO_SR_1152_900_76_B 0x60
93 #define BWTWO_SR_ID_MASK 0x0f
94 #define BWTWO_SR_ID_MONO 0x02
95 #define BWTWO_SR_ID_MONO_ECL 0x03
96 #define BWTWO_SR_ID_MSYNC 0x04
97 #define BWTWO_SR_ID_NOCONN 0x0a
99 /* Control Register Constants */
100 #define BWTWO_CTL_ENABLE_INTS 0x80
101 #define BWTWO_CTL_ENABLE_VIDEO 0x40
102 #define BWTWO_CTL_ENABLE_TIMING 0x20
103 #define BWTWO_CTL_ENABLE_CURCMP 0x10
104 #define BWTWO_CTL_XTAL_MASK 0x0C
105 #define BWTWO_CTL_DIVISOR_MASK 0x03
107 /* Status Register Constants */
108 #define BWTWO_STAT_PENDING_INT 0x80
109 #define BWTWO_STAT_MSENSE_MASK 0x70
110 #define BWTWO_STAT_ID_MASK 0x0f
114 struct bw2_regs __iomem
*regs
;
117 #define BW2_FLAG_BLANKED 0x00000001
119 unsigned long physbase
;
120 unsigned long fbsize
;
122 struct sbus_dev
*sdev
;
126 * bw2_blank - Optional function. Blanks the display.
127 * @blank_mode: the blank mode we want.
128 * @info: frame buffer structure that represents a single frame buffer
131 bw2_blank(int blank
, struct fb_info
*info
)
133 struct bw2_par
*par
= (struct bw2_par
*) info
->par
;
134 struct bw2_regs __iomem
*regs
= par
->regs
;
138 spin_lock_irqsave(&par
->lock
, flags
);
141 case FB_BLANK_UNBLANK
: /* Unblanking */
142 val
= sbus_readb(®s
->control
);
143 val
|= BWTWO_CTL_ENABLE_VIDEO
;
144 sbus_writeb(val
, ®s
->control
);
145 par
->flags
&= ~BW2_FLAG_BLANKED
;
148 case FB_BLANK_NORMAL
: /* Normal blanking */
149 case FB_BLANK_VSYNC_SUSPEND
: /* VESA blank (vsync off) */
150 case FB_BLANK_HSYNC_SUSPEND
: /* VESA blank (hsync off) */
151 case FB_BLANK_POWERDOWN
: /* Poweroff */
152 val
= sbus_readb(®s
->control
);
153 val
&= ~BWTWO_CTL_ENABLE_VIDEO
;
154 sbus_writeb(val
, ®s
->control
);
155 par
->flags
|= BW2_FLAG_BLANKED
;
159 spin_unlock_irqrestore(&par
->lock
, flags
);
164 static struct sbus_mmap_map bw2_mmap_map
[] = {
166 .size
= SBUS_MMAP_FBSIZE(1)
171 static int bw2_mmap(struct fb_info
*info
, struct file
*file
, struct vm_area_struct
*vma
)
173 struct bw2_par
*par
= (struct bw2_par
*)info
->par
;
175 return sbusfb_mmap_helper(bw2_mmap_map
,
176 par
->physbase
, par
->fbsize
,
178 par
->sdev
->reg_addrs
[0].which_io
:
183 static int bw2_ioctl(struct fb_info
*info
, unsigned int cmd
, unsigned long arg
)
185 struct bw2_par
*par
= (struct bw2_par
*) info
->par
;
187 return sbusfb_ioctl_helper(cmd
, arg
, info
,
188 FBTYPE_SUN2BW
, 1, par
->fbsize
);
196 bw2_init_fix(struct fb_info
*info
, int linebytes
)
198 strlcpy(info
->fix
.id
, "bwtwo", sizeof(info
->fix
.id
));
200 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
201 info
->fix
.visual
= FB_VISUAL_MONO01
;
203 info
->fix
.line_length
= linebytes
;
205 info
->fix
.accel
= FB_ACCEL_SUN_BWTWO
;
208 static u8 bw2regs_1600
[] __initdata
= {
209 0x14, 0x8b, 0x15, 0x28, 0x16, 0x03, 0x17, 0x13,
210 0x18, 0x7b, 0x19, 0x05, 0x1a, 0x34, 0x1b, 0x2e,
211 0x1c, 0x00, 0x1d, 0x0a, 0x1e, 0xff, 0x1f, 0x01,
215 static u8 bw2regs_ecl
[] __initdata
= {
216 0x14, 0x65, 0x15, 0x1e, 0x16, 0x04, 0x17, 0x0c,
217 0x18, 0x5e, 0x19, 0x03, 0x1a, 0xa7, 0x1b, 0x23,
218 0x1c, 0x00, 0x1d, 0x08, 0x1e, 0xff, 0x1f, 0x01,
222 static u8 bw2regs_analog
[] __initdata
= {
223 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x03, 0x17, 0x13,
224 0x18, 0xb0, 0x19, 0x03, 0x1a, 0xa6, 0x1b, 0x22,
225 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
229 static u8 bw2regs_76hz
[] __initdata
= {
230 0x14, 0xb7, 0x15, 0x27, 0x16, 0x03, 0x17, 0x0f,
231 0x18, 0xae, 0x19, 0x03, 0x1a, 0xae, 0x1b, 0x2a,
232 0x1c, 0x01, 0x1d, 0x09, 0x1e, 0xff, 0x1f, 0x01,
236 static u8 bw2regs_66hz
[] __initdata
= {
237 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x04, 0x17, 0x14,
238 0x18, 0xae, 0x19, 0x03, 0x1a, 0xa8, 0x1b, 0x24,
239 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
243 static void bw2_do_default_mode(struct bw2_par
*par
, struct fb_info
*info
,
249 status
= sbus_readb(&par
->regs
->status
);
250 mon
= status
& BWTWO_SR_RES_MASK
;
251 switch (status
& BWTWO_SR_ID_MASK
) {
252 case BWTWO_SR_ID_MONO_ECL
:
253 if (mon
== BWTWO_SR_1600_1280
) {
255 info
->var
.xres
= info
->var
.xres_virtual
= 1600;
256 info
->var
.yres
= info
->var
.yres_virtual
= 1280;
257 *linebytes
= 1600 / 8;
262 case BWTWO_SR_ID_MONO
:
266 case BWTWO_SR_ID_MSYNC
:
267 if (mon
== BWTWO_SR_1152_900_76_A
||
268 mon
== BWTWO_SR_1152_900_76_B
)
274 case BWTWO_SR_ID_NOCONN
:
278 prom_printf("bw2: can't handle SR %02x\n",
282 for ( ; *p
; p
+= 2) {
283 u8 __iomem
*regp
= &((u8 __iomem
*)par
->regs
)[p
[0]];
284 sbus_writeb(p
[1], regp
);
291 struct list_head list
;
293 static LIST_HEAD(bw2_list
);
295 static void bw2_init_one(struct sbus_dev
*sdev
)
297 struct all_info
*all
;
298 struct resource
*resp
;
304 all
= kmalloc(sizeof(*all
), GFP_KERNEL
);
306 printk(KERN_ERR
"bw2: Cannot allocate memory.\n");
309 memset(all
, 0, sizeof(*all
));
311 INIT_LIST_HEAD(&all
->list
);
313 spin_lock_init(&all
->par
.lock
);
314 all
->par
.sdev
= sdev
;
318 all
->par
.physbase
= sun4_bwtwo_physaddr
;
319 res
.start
= sun4_bwtwo_physaddr
;
320 res
.end
= res
.start
+ BWTWO_REGISTER_OFFSET
+ sizeof(struct bw2_regs
) - 1;
321 res
.flags
= IORESOURCE_IO
;
323 all
->info
.var
.xres
= all
->info
.var
.xres_virtual
= 1152;
324 all
->info
.var
.yres
= all
->info
.var
.yres_virtual
= 900;
325 all
->info
.var
.bits_per_pixel
= 1;
326 linebytes
= 1152 / 8;
332 all
->par
.physbase
= sdev
->reg_addrs
[0].phys_addr
;
333 resp
= &sdev
->resource
[0];
334 sbusfb_fill_var(&all
->info
.var
, (sdev
? sdev
->prom_node
: 0), 1);
335 linebytes
= prom_getintdefault(sdev
->prom_node
, "linebytes",
339 all
->info
.var
.red
.length
= all
->info
.var
.green
.length
=
340 all
->info
.var
.blue
.length
= all
->info
.var
.bits_per_pixel
;
341 all
->info
.var
.red
.offset
= all
->info
.var
.green
.offset
=
342 all
->info
.var
.blue
.offset
= 0;
344 all
->par
.regs
= sbus_ioremap(resp
, BWTWO_REGISTER_OFFSET
,
345 sizeof(struct bw2_regs
), "bw2 regs");
347 if (sdev
&& !prom_getbool(sdev
->prom_node
, "width"))
348 bw2_do_default_mode(&all
->par
, &all
->info
, &linebytes
);
350 all
->par
.fbsize
= PAGE_ALIGN(linebytes
* all
->info
.var
.yres
);
352 all
->info
.flags
= FBINFO_DEFAULT
;
353 all
->info
.fbops
= &bw2_ops
;
354 #if defined(CONFIG_SPARC32)
356 all
->info
.screen_base
= (char __iomem
*)
357 prom_getintdefault(sdev
->prom_node
, "address", 0);
359 if (!all
->info
.screen_base
)
360 all
->info
.screen_base
=
361 sbus_ioremap(resp
, 0, all
->par
.fbsize
, "bw2 ram");
362 all
->info
.par
= &all
->par
;
364 bw2_blank(0, &all
->info
);
366 bw2_init_fix(&all
->info
, linebytes
);
368 if (register_framebuffer(&all
->info
) < 0) {
369 printk(KERN_ERR
"bw2: Could not register framebuffer.\n");
374 list_add(&all
->list
, &bw2_list
);
376 printk("bw2: bwtwo at %lx:%lx\n",
377 (long) (sdev
? sdev
->reg_addrs
[0].which_io
: 0),
378 (long) all
->par
.physbase
);
381 int __init
bw2_init(void)
383 struct sbus_bus
*sbus
;
384 struct sbus_dev
*sdev
;
386 if (fb_get_options("bw2fb", NULL
))
392 for_all_sbusdev(sdev
, sbus
) {
393 if (!strcmp(sdev
->prom_name
, "bwtwo"))
400 void __exit
bw2_exit(void)
402 struct list_head
*pos
, *tmp
;
404 list_for_each_safe(pos
, tmp
, &bw2_list
) {
405 struct all_info
*all
= list_entry(pos
, typeof(*all
), list
);
407 unregister_framebuffer(&all
->info
);
415 /* No cmdline options yet... */
419 module_init(bw2_init
);
422 module_exit(bw2_exit
);
425 MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets");
426 MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
427 MODULE_LICENSE("GPL");