1 /* bw2.c: BWTWO frame buffer driver
3 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
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>
20 #include <linux/of_device.h>
31 static int bw2_blank(int, struct fb_info
*);
33 static int bw2_mmap(struct fb_info
*, struct vm_area_struct
*);
34 static int bw2_ioctl(struct fb_info
*, unsigned int, unsigned long);
37 * Frame buffer operations
40 static struct fb_ops bw2_ops
= {
42 .fb_blank
= bw2_blank
,
43 .fb_fillrect
= cfb_fillrect
,
44 .fb_copyarea
= cfb_copyarea
,
45 .fb_imageblit
= cfb_imageblit
,
47 .fb_ioctl
= bw2_ioctl
,
49 .fb_compat_ioctl
= sbusfb_compat_ioctl
,
53 /* OBio addresses for the bwtwo registers */
54 #define BWTWO_REGISTER_OFFSET 0x400000
74 u8 v_blank_start_high
;
79 u8 xfer_holdoff_start
;
83 /* Status Register Constants */
84 #define BWTWO_SR_RES_MASK 0x70
85 #define BWTWO_SR_1600_1280 0x50
86 #define BWTWO_SR_1152_900_76_A 0x40
87 #define BWTWO_SR_1152_900_76_B 0x60
88 #define BWTWO_SR_ID_MASK 0x0f
89 #define BWTWO_SR_ID_MONO 0x02
90 #define BWTWO_SR_ID_MONO_ECL 0x03
91 #define BWTWO_SR_ID_MSYNC 0x04
92 #define BWTWO_SR_ID_NOCONN 0x0a
94 /* Control Register Constants */
95 #define BWTWO_CTL_ENABLE_INTS 0x80
96 #define BWTWO_CTL_ENABLE_VIDEO 0x40
97 #define BWTWO_CTL_ENABLE_TIMING 0x20
98 #define BWTWO_CTL_ENABLE_CURCMP 0x10
99 #define BWTWO_CTL_XTAL_MASK 0x0C
100 #define BWTWO_CTL_DIVISOR_MASK 0x03
102 /* Status Register Constants */
103 #define BWTWO_STAT_PENDING_INT 0x80
104 #define BWTWO_STAT_MSENSE_MASK 0x70
105 #define BWTWO_STAT_ID_MASK 0x0f
109 struct bw2_regs __iomem
*regs
;
112 #define BW2_FLAG_BLANKED 0x00000001
114 unsigned long physbase
;
115 unsigned long which_io
;
116 unsigned long fbsize
;
120 * bw2_blank - Optional function. Blanks the display.
121 * @blank_mode: the blank mode we want.
122 * @info: frame buffer structure that represents a single frame buffer
125 bw2_blank(int blank
, struct fb_info
*info
)
127 struct bw2_par
*par
= (struct bw2_par
*) info
->par
;
128 struct bw2_regs __iomem
*regs
= par
->regs
;
132 spin_lock_irqsave(&par
->lock
, flags
);
135 case FB_BLANK_UNBLANK
: /* Unblanking */
136 val
= sbus_readb(®s
->control
);
137 val
|= BWTWO_CTL_ENABLE_VIDEO
;
138 sbus_writeb(val
, ®s
->control
);
139 par
->flags
&= ~BW2_FLAG_BLANKED
;
142 case FB_BLANK_NORMAL
: /* Normal blanking */
143 case FB_BLANK_VSYNC_SUSPEND
: /* VESA blank (vsync off) */
144 case FB_BLANK_HSYNC_SUSPEND
: /* VESA blank (hsync off) */
145 case FB_BLANK_POWERDOWN
: /* Poweroff */
146 val
= sbus_readb(®s
->control
);
147 val
&= ~BWTWO_CTL_ENABLE_VIDEO
;
148 sbus_writeb(val
, ®s
->control
);
149 par
->flags
|= BW2_FLAG_BLANKED
;
153 spin_unlock_irqrestore(&par
->lock
, flags
);
158 static struct sbus_mmap_map bw2_mmap_map
[] = {
160 .size
= SBUS_MMAP_FBSIZE(1)
165 static int bw2_mmap(struct fb_info
*info
, struct vm_area_struct
*vma
)
167 struct bw2_par
*par
= (struct bw2_par
*)info
->par
;
169 return sbusfb_mmap_helper(bw2_mmap_map
,
170 par
->physbase
, par
->fbsize
,
175 static int bw2_ioctl(struct fb_info
*info
, unsigned int cmd
, unsigned long arg
)
177 struct bw2_par
*par
= (struct bw2_par
*) info
->par
;
179 return sbusfb_ioctl_helper(cmd
, arg
, info
,
180 FBTYPE_SUN2BW
, 1, par
->fbsize
);
187 static void __devinit
bw2_init_fix(struct fb_info
*info
, int linebytes
)
189 strlcpy(info
->fix
.id
, "bwtwo", sizeof(info
->fix
.id
));
191 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
192 info
->fix
.visual
= FB_VISUAL_MONO01
;
194 info
->fix
.line_length
= linebytes
;
196 info
->fix
.accel
= FB_ACCEL_SUN_BWTWO
;
199 static u8 bw2regs_1600
[] __devinitdata
= {
200 0x14, 0x8b, 0x15, 0x28, 0x16, 0x03, 0x17, 0x13,
201 0x18, 0x7b, 0x19, 0x05, 0x1a, 0x34, 0x1b, 0x2e,
202 0x1c, 0x00, 0x1d, 0x0a, 0x1e, 0xff, 0x1f, 0x01,
206 static u8 bw2regs_ecl
[] __devinitdata
= {
207 0x14, 0x65, 0x15, 0x1e, 0x16, 0x04, 0x17, 0x0c,
208 0x18, 0x5e, 0x19, 0x03, 0x1a, 0xa7, 0x1b, 0x23,
209 0x1c, 0x00, 0x1d, 0x08, 0x1e, 0xff, 0x1f, 0x01,
213 static u8 bw2regs_analog
[] __devinitdata
= {
214 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x03, 0x17, 0x13,
215 0x18, 0xb0, 0x19, 0x03, 0x1a, 0xa6, 0x1b, 0x22,
216 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
220 static u8 bw2regs_76hz
[] __devinitdata
= {
221 0x14, 0xb7, 0x15, 0x27, 0x16, 0x03, 0x17, 0x0f,
222 0x18, 0xae, 0x19, 0x03, 0x1a, 0xae, 0x1b, 0x2a,
223 0x1c, 0x01, 0x1d, 0x09, 0x1e, 0xff, 0x1f, 0x01,
227 static u8 bw2regs_66hz
[] __devinitdata
= {
228 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x04, 0x17, 0x14,
229 0x18, 0xae, 0x19, 0x03, 0x1a, 0xa8, 0x1b, 0x24,
230 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
234 static int __devinit
bw2_do_default_mode(struct bw2_par
*par
,
235 struct fb_info
*info
,
241 status
= sbus_readb(&par
->regs
->status
);
242 mon
= status
& BWTWO_SR_RES_MASK
;
243 switch (status
& BWTWO_SR_ID_MASK
) {
244 case BWTWO_SR_ID_MONO_ECL
:
245 if (mon
== BWTWO_SR_1600_1280
) {
247 info
->var
.xres
= info
->var
.xres_virtual
= 1600;
248 info
->var
.yres
= info
->var
.yres_virtual
= 1280;
249 *linebytes
= 1600 / 8;
254 case BWTWO_SR_ID_MONO
:
258 case BWTWO_SR_ID_MSYNC
:
259 if (mon
== BWTWO_SR_1152_900_76_A
||
260 mon
== BWTWO_SR_1152_900_76_B
)
266 case BWTWO_SR_ID_NOCONN
:
270 printk(KERN_ERR
"bw2: can't handle SR %02x\n",
274 for ( ; *p
; p
+= 2) {
275 u8 __iomem
*regp
= &((u8 __iomem
*)par
->regs
)[p
[0]];
276 sbus_writeb(p
[1], regp
);
281 static int __devinit
bw2_probe(struct of_device
*op
, const struct of_device_id
*match
)
283 struct device_node
*dp
= op
->node
;
284 struct fb_info
*info
;
288 info
= framebuffer_alloc(sizeof(struct bw2_par
), &op
->dev
);
295 spin_lock_init(&par
->lock
);
297 par
->physbase
= op
->resource
[0].start
;
298 par
->which_io
= op
->resource
[0].flags
& IORESOURCE_BITS
;
300 sbusfb_fill_var(&info
->var
, dp
, 1);
301 linebytes
= of_getintprop_default(dp
, "linebytes",
304 info
->var
.red
.length
= info
->var
.green
.length
=
305 info
->var
.blue
.length
= info
->var
.bits_per_pixel
;
306 info
->var
.red
.offset
= info
->var
.green
.offset
=
307 info
->var
.blue
.offset
= 0;
309 par
->regs
= of_ioremap(&op
->resource
[0], BWTWO_REGISTER_OFFSET
,
310 sizeof(struct bw2_regs
), "bw2 regs");
314 if (!of_find_property(dp
, "width", NULL
)) {
315 err
= bw2_do_default_mode(par
, info
, &linebytes
);
320 par
->fbsize
= PAGE_ALIGN(linebytes
* info
->var
.yres
);
322 info
->flags
= FBINFO_DEFAULT
;
323 info
->fbops
= &bw2_ops
;
325 info
->screen_base
= of_ioremap(&op
->resource
[0], 0,
326 par
->fbsize
, "bw2 ram");
327 if (!info
->screen_base
)
330 bw2_blank(FB_BLANK_UNBLANK
, info
);
332 bw2_init_fix(info
, linebytes
);
334 err
= register_framebuffer(info
);
336 goto out_unmap_screen
;
338 dev_set_drvdata(&op
->dev
, info
);
340 printk(KERN_INFO
"%s: bwtwo at %lx:%lx\n",
341 dp
->full_name
, par
->which_io
, par
->physbase
);
346 of_iounmap(&op
->resource
[0], info
->screen_base
, par
->fbsize
);
349 of_iounmap(&op
->resource
[0], par
->regs
, sizeof(struct bw2_regs
));
352 framebuffer_release(info
);
358 static int __devexit
bw2_remove(struct of_device
*op
)
360 struct fb_info
*info
= dev_get_drvdata(&op
->dev
);
361 struct bw2_par
*par
= info
->par
;
363 unregister_framebuffer(info
);
365 of_iounmap(&op
->resource
[0], par
->regs
, sizeof(struct bw2_regs
));
366 of_iounmap(&op
->resource
[0], info
->screen_base
, par
->fbsize
);
368 framebuffer_release(info
);
370 dev_set_drvdata(&op
->dev
, NULL
);
375 static const struct of_device_id bw2_match
[] = {
381 MODULE_DEVICE_TABLE(of
, bw2_match
);
383 static struct of_platform_driver bw2_driver
= {
385 .match_table
= bw2_match
,
387 .remove
= __devexit_p(bw2_remove
),
390 static int __init
bw2_init(void)
392 if (fb_get_options("bw2fb", NULL
))
395 return of_register_driver(&bw2_driver
, &of_bus_type
);
398 static void __exit
bw2_exit(void)
400 of_unregister_driver(&bw2_driver
);
403 module_init(bw2_init
);
404 module_exit(bw2_exit
);
406 MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets");
407 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
408 MODULE_VERSION("2.0");
409 MODULE_LICENSE("GPL");