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 inode *, struct file *, unsigned int,
40 unsigned long, struct fb_info *);
43 * Frame buffer operations
46 static struct fb_ops bw2_ops = {
48 .fb_blank = bw2_blank,
49 .fb_fillrect = cfb_fillrect,
50 .fb_copyarea = cfb_copyarea,
51 .fb_imageblit = cfb_imageblit,
53 .fb_ioctl = bw2_ioctl,
55 .fb_compat_ioctl = sbusfb_compat_ioctl,
59 /* OBio addresses for the bwtwo registers */
60 #define BWTWO_REGISTER_OFFSET 0x400000
64 volatile u32 color_map;
73 volatile u8 cursor_start;
74 volatile u8 cursor_end;
75 volatile u8 h_blank_start;
76 volatile u8 h_blank_end;
77 volatile u8 h_sync_start;
78 volatile u8 h_sync_end;
79 volatile u8 comp_sync_end;
80 volatile u8 v_blank_start_high;
81 volatile u8 v_blank_start_low;
82 volatile u8 v_blank_end;
83 volatile u8 v_sync_start;
84 volatile u8 v_sync_end;
85 volatile u8 xfer_holdoff_start;
86 volatile u8 xfer_holdoff_end;
89 /* Status Register Constants */
90 #define BWTWO_SR_RES_MASK 0x70
91 #define BWTWO_SR_1600_1280 0x50
92 #define BWTWO_SR_1152_900_76_A 0x40
93 #define BWTWO_SR_1152_900_76_B 0x60
94 #define BWTWO_SR_ID_MASK 0x0f
95 #define BWTWO_SR_ID_MONO 0x02
96 #define BWTWO_SR_ID_MONO_ECL 0x03
97 #define BWTWO_SR_ID_MSYNC 0x04
98 #define BWTWO_SR_ID_NOCONN 0x0a
100 /* Control Register Constants */
101 #define BWTWO_CTL_ENABLE_INTS 0x80
102 #define BWTWO_CTL_ENABLE_VIDEO 0x40
103 #define BWTWO_CTL_ENABLE_TIMING 0x20
104 #define BWTWO_CTL_ENABLE_CURCMP 0x10
105 #define BWTWO_CTL_XTAL_MASK 0x0C
106 #define BWTWO_CTL_DIVISOR_MASK 0x03
108 /* Status Register Constants */
109 #define BWTWO_STAT_PENDING_INT 0x80
110 #define BWTWO_STAT_MSENSE_MASK 0x70
111 #define BWTWO_STAT_ID_MASK 0x0f
115 struct bw2_regs __iomem *regs;
118 #define BW2_FLAG_BLANKED 0x00000001
120 unsigned long physbase;
121 unsigned long fbsize;
123 struct sbus_dev *sdev;
124 struct list_head list;
128 * bw2_blank - Optional function. Blanks the display.
129 * @blank_mode: the blank mode we want.
130 * @info: frame buffer structure that represents a single frame buffer
133 bw2_blank(int blank, struct fb_info *info)
135 struct bw2_par *par = (struct bw2_par *) info->par;
136 struct bw2_regs __iomem *regs = par->regs;
140 spin_lock_irqsave(&par->lock, flags);
143 case FB_BLANK_UNBLANK: /* Unblanking */
144 val = sbus_readb(®s->control);
145 val |= BWTWO_CTL_ENABLE_VIDEO;
146 sbus_writeb(val, ®s->control);
147 par->flags &= ~BW2_FLAG_BLANKED;
150 case FB_BLANK_NORMAL: /* Normal blanking */
151 case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
152 case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
153 case FB_BLANK_POWERDOWN: /* Poweroff */
154 val = sbus_readb(®s->control);
155 val &= ~BWTWO_CTL_ENABLE_VIDEO;
156 sbus_writeb(val, ®s->control);
157 par->flags |= BW2_FLAG_BLANKED;
161 spin_unlock_irqrestore(&par->lock, flags);
166 static struct sbus_mmap_map bw2_mmap_map[] = {
168 .size = SBUS_MMAP_FBSIZE(1)
173 static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
175 struct bw2_par *par = (struct bw2_par *)info->par;
177 return sbusfb_mmap_helper(bw2_mmap_map,
178 par->physbase, par->fbsize,
180 par->sdev->reg_addrs[0].which_io :
185 static int bw2_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
186 unsigned long arg, struct fb_info *info)
188 struct bw2_par *par = (struct bw2_par *) info->par;
190 return sbusfb_ioctl_helper(cmd, arg, info,
191 FBTYPE_SUN2BW, 1, par->fbsize);
199 bw2_init_fix(struct fb_info *info, int linebytes)
201 strlcpy(info->fix.id, "bwtwo", sizeof(info->fix.id));
203 info->fix.type = FB_TYPE_PACKED_PIXELS;
204 info->fix.visual = FB_VISUAL_MONO01;
206 info->fix.line_length = linebytes;
208 info->fix.accel = FB_ACCEL_SUN_BWTWO;
211 static u8 bw2regs_1600[] __initdata = {
212 0x14, 0x8b, 0x15, 0x28, 0x16, 0x03, 0x17, 0x13,
213 0x18, 0x7b, 0x19, 0x05, 0x1a, 0x34, 0x1b, 0x2e,
214 0x1c, 0x00, 0x1d, 0x0a, 0x1e, 0xff, 0x1f, 0x01,
218 static u8 bw2regs_ecl[] __initdata = {
219 0x14, 0x65, 0x15, 0x1e, 0x16, 0x04, 0x17, 0x0c,
220 0x18, 0x5e, 0x19, 0x03, 0x1a, 0xa7, 0x1b, 0x23,
221 0x1c, 0x00, 0x1d, 0x08, 0x1e, 0xff, 0x1f, 0x01,
225 static u8 bw2regs_analog[] __initdata = {
226 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x03, 0x17, 0x13,
227 0x18, 0xb0, 0x19, 0x03, 0x1a, 0xa6, 0x1b, 0x22,
228 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
232 static u8 bw2regs_76hz[] __initdata = {
233 0x14, 0xb7, 0x15, 0x27, 0x16, 0x03, 0x17, 0x0f,
234 0x18, 0xae, 0x19, 0x03, 0x1a, 0xae, 0x1b, 0x2a,
235 0x1c, 0x01, 0x1d, 0x09, 0x1e, 0xff, 0x1f, 0x01,
239 static u8 bw2regs_66hz[] __initdata = {
240 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x04, 0x17, 0x14,
241 0x18, 0xae, 0x19, 0x03, 0x1a, 0xa8, 0x1b, 0x24,
242 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
246 static void bw2_do_default_mode(struct bw2_par *par, struct fb_info *info,
252 status = sbus_readb(&par->regs->status);
253 mon = status & BWTWO_SR_RES_MASK;
254 switch (status & BWTWO_SR_ID_MASK) {
255 case BWTWO_SR_ID_MONO_ECL:
256 if (mon == BWTWO_SR_1600_1280) {
258 info->var.xres = info->var.xres_virtual = 1600;
259 info->var.yres = info->var.yres_virtual = 1280;
260 *linebytes = 1600 / 8;
265 case BWTWO_SR_ID_MONO:
269 case BWTWO_SR_ID_MSYNC:
270 if (mon == BWTWO_SR_1152_900_76_A ||
271 mon == BWTWO_SR_1152_900_76_B)
277 case BWTWO_SR_ID_NOCONN:
281 prom_printf("bw2: can't handle SR %02x\n",
285 for ( ; *p; p += 2) {
286 u8 __iomem *regp = &((u8 __iomem *)par->regs)[p[0]];
287 sbus_writeb(p[1], regp);
294 struct list_head list;
296 static LIST_HEAD(bw2_list);
298 static void bw2_init_one(struct sbus_dev *sdev)
300 struct all_info *all;
301 struct resource *resp;
307 all = kmalloc(sizeof(*all), GFP_KERNEL);
309 printk(KERN_ERR "bw2: Cannot allocate memory.\n");
312 memset(all, 0, sizeof(*all));
314 INIT_LIST_HEAD(&all->list);
316 spin_lock_init(&all->par.lock);
317 all->par.sdev = sdev;
321 all->par.physbase = sun4_bwtwo_physaddr;
322 res.start = sun4_bwtwo_physaddr;
323 res.end = res.start + BWTWO_REGISTER_OFFSET + sizeof(struct bw2_regs) - 1;
324 res.flags = IORESOURCE_IO;
326 all->info.var.xres = all->info.var.xres_virtual = 1152;
327 all->info.var.yres = all->info.var.yres_virtual = 900;
328 all->info.var.bits_per_pixel = 1;
329 linebytes = 1152 / 8;
335 all->par.physbase = sdev->reg_addrs[0].phys_addr;
336 resp = &sdev->resource[0];
337 sbusfb_fill_var(&all->info.var, (sdev ? sdev->prom_node : 0), 1);
338 linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
342 all->info.var.red.length = all->info.var.green.length =
343 all->info.var.blue.length = all->info.var.bits_per_pixel;
344 all->info.var.red.offset = all->info.var.green.offset =
345 all->info.var.blue.offset = 0;
347 all->par.regs = sbus_ioremap(resp, BWTWO_REGISTER_OFFSET,
348 sizeof(struct bw2_regs), "bw2 regs");
350 if (sdev && !prom_getbool(sdev->prom_node, "width"))
351 bw2_do_default_mode(&all->par, &all->info, &linebytes);
353 all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
355 all->info.flags = FBINFO_DEFAULT;
356 all->info.fbops = &bw2_ops;
357 #if defined(CONFIG_SPARC32)
359 all->info.screen_base = (char __iomem *)
360 prom_getintdefault(sdev->prom_node, "address", 0);
362 if (!all->info.screen_base)
363 all->info.screen_base =
364 sbus_ioremap(resp, 0, all->par.fbsize, "bw2 ram");
365 all->info.par = &all->par;
367 bw2_blank(0, &all->info);
369 bw2_init_fix(&all->info, linebytes);
371 if (register_framebuffer(&all->info) < 0) {
372 printk(KERN_ERR "bw2: Could not register framebuffer.\n");
377 list_add(&all->list, &bw2_list);
379 printk("bw2: bwtwo at %lx:%lx\n",
380 (long) (sdev ? sdev->reg_addrs[0].which_io : 0),
381 (long) all->par.physbase);
384 int __init bw2_init(void)
386 struct sbus_bus *sbus;
387 struct sbus_dev *sdev;
389 if (fb_get_options("bw2fb", NULL))
395 for_all_sbusdev(sdev, sbus) {
396 if (!strcmp(sdev->prom_name, "bwtwo"))
403 void __exit bw2_exit(void)
405 struct list_head *pos, *tmp;
407 list_for_each_safe(pos, tmp, &bw2_list) {
408 struct all_info *all = list_entry(pos, typeof(*all), list);
410 unregister_framebuffer(&all->info);
418 /* No cmdline options yet... */
422 module_init(bw2_init);
425 module_exit(bw2_exit);
428 MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets");
429 MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
430 MODULE_LICENSE("GPL");