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 which_io
;
118 * bw2_blank - Optional function. Blanks the display.
119 * @blank_mode: the blank mode we want.
120 * @info: frame buffer structure that represents a single frame buffer
123 bw2_blank(int blank
, struct fb_info
*info
)
125 struct bw2_par
*par
= (struct bw2_par
*) info
->par
;
126 struct bw2_regs __iomem
*regs
= par
->regs
;
130 spin_lock_irqsave(&par
->lock
, flags
);
133 case FB_BLANK_UNBLANK
: /* Unblanking */
134 val
= sbus_readb(®s
->control
);
135 val
|= BWTWO_CTL_ENABLE_VIDEO
;
136 sbus_writeb(val
, ®s
->control
);
137 par
->flags
&= ~BW2_FLAG_BLANKED
;
140 case FB_BLANK_NORMAL
: /* Normal blanking */
141 case FB_BLANK_VSYNC_SUSPEND
: /* VESA blank (vsync off) */
142 case FB_BLANK_HSYNC_SUSPEND
: /* VESA blank (hsync off) */
143 case FB_BLANK_POWERDOWN
: /* Poweroff */
144 val
= sbus_readb(®s
->control
);
145 val
&= ~BWTWO_CTL_ENABLE_VIDEO
;
146 sbus_writeb(val
, ®s
->control
);
147 par
->flags
|= BW2_FLAG_BLANKED
;
151 spin_unlock_irqrestore(&par
->lock
, flags
);
156 static struct sbus_mmap_map bw2_mmap_map
[] = {
158 .size
= SBUS_MMAP_FBSIZE(1)
163 static int bw2_mmap(struct fb_info
*info
, struct vm_area_struct
*vma
)
165 struct bw2_par
*par
= (struct bw2_par
*)info
->par
;
167 return sbusfb_mmap_helper(bw2_mmap_map
,
168 info
->fix
.smem_start
, info
->fix
.smem_len
,
173 static int bw2_ioctl(struct fb_info
*info
, unsigned int cmd
, unsigned long arg
)
175 return sbusfb_ioctl_helper(cmd
, arg
, info
,
176 FBTYPE_SUN2BW
, 1, info
->fix
.smem_len
);
183 static void __devinit
bw2_init_fix(struct fb_info
*info
, int linebytes
)
185 strlcpy(info
->fix
.id
, "bwtwo", sizeof(info
->fix
.id
));
187 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
188 info
->fix
.visual
= FB_VISUAL_MONO01
;
190 info
->fix
.line_length
= linebytes
;
192 info
->fix
.accel
= FB_ACCEL_SUN_BWTWO
;
195 static u8 bw2regs_1600
[] __devinitdata
= {
196 0x14, 0x8b, 0x15, 0x28, 0x16, 0x03, 0x17, 0x13,
197 0x18, 0x7b, 0x19, 0x05, 0x1a, 0x34, 0x1b, 0x2e,
198 0x1c, 0x00, 0x1d, 0x0a, 0x1e, 0xff, 0x1f, 0x01,
202 static u8 bw2regs_ecl
[] __devinitdata
= {
203 0x14, 0x65, 0x15, 0x1e, 0x16, 0x04, 0x17, 0x0c,
204 0x18, 0x5e, 0x19, 0x03, 0x1a, 0xa7, 0x1b, 0x23,
205 0x1c, 0x00, 0x1d, 0x08, 0x1e, 0xff, 0x1f, 0x01,
209 static u8 bw2regs_analog
[] __devinitdata
= {
210 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x03, 0x17, 0x13,
211 0x18, 0xb0, 0x19, 0x03, 0x1a, 0xa6, 0x1b, 0x22,
212 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
216 static u8 bw2regs_76hz
[] __devinitdata
= {
217 0x14, 0xb7, 0x15, 0x27, 0x16, 0x03, 0x17, 0x0f,
218 0x18, 0xae, 0x19, 0x03, 0x1a, 0xae, 0x1b, 0x2a,
219 0x1c, 0x01, 0x1d, 0x09, 0x1e, 0xff, 0x1f, 0x01,
223 static u8 bw2regs_66hz
[] __devinitdata
= {
224 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x04, 0x17, 0x14,
225 0x18, 0xae, 0x19, 0x03, 0x1a, 0xa8, 0x1b, 0x24,
226 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
230 static int __devinit
bw2_do_default_mode(struct bw2_par
*par
,
231 struct fb_info
*info
,
237 status
= sbus_readb(&par
->regs
->status
);
238 mon
= status
& BWTWO_SR_RES_MASK
;
239 switch (status
& BWTWO_SR_ID_MASK
) {
240 case BWTWO_SR_ID_MONO_ECL
:
241 if (mon
== BWTWO_SR_1600_1280
) {
243 info
->var
.xres
= info
->var
.xres_virtual
= 1600;
244 info
->var
.yres
= info
->var
.yres_virtual
= 1280;
245 *linebytes
= 1600 / 8;
250 case BWTWO_SR_ID_MONO
:
254 case BWTWO_SR_ID_MSYNC
:
255 if (mon
== BWTWO_SR_1152_900_76_A
||
256 mon
== BWTWO_SR_1152_900_76_B
)
262 case BWTWO_SR_ID_NOCONN
:
266 printk(KERN_ERR
"bw2: can't handle SR %02x\n",
270 for ( ; *p
; p
+= 2) {
271 u8 __iomem
*regp
= &((u8 __iomem
*)par
->regs
)[p
[0]];
272 sbus_writeb(p
[1], regp
);
277 static int __devinit
bw2_probe(struct of_device
*op
, const struct of_device_id
*match
)
279 struct device_node
*dp
= op
->node
;
280 struct fb_info
*info
;
284 info
= framebuffer_alloc(sizeof(struct bw2_par
), &op
->dev
);
291 spin_lock_init(&par
->lock
);
293 info
->fix
.smem_start
= op
->resource
[0].start
;
294 par
->which_io
= op
->resource
[0].flags
& IORESOURCE_BITS
;
296 sbusfb_fill_var(&info
->var
, dp
, 1);
297 linebytes
= of_getintprop_default(dp
, "linebytes",
300 info
->var
.red
.length
= info
->var
.green
.length
=
301 info
->var
.blue
.length
= info
->var
.bits_per_pixel
;
302 info
->var
.red
.offset
= info
->var
.green
.offset
=
303 info
->var
.blue
.offset
= 0;
305 par
->regs
= of_ioremap(&op
->resource
[0], BWTWO_REGISTER_OFFSET
,
306 sizeof(struct bw2_regs
), "bw2 regs");
310 if (!of_find_property(dp
, "width", NULL
)) {
311 err
= bw2_do_default_mode(par
, info
, &linebytes
);
316 info
->fix
.smem_len
= PAGE_ALIGN(linebytes
* info
->var
.yres
);
318 info
->flags
= FBINFO_DEFAULT
;
319 info
->fbops
= &bw2_ops
;
321 info
->screen_base
= of_ioremap(&op
->resource
[0], 0,
322 info
->fix
.smem_len
, "bw2 ram");
323 if (!info
->screen_base
)
326 bw2_blank(FB_BLANK_UNBLANK
, info
);
328 bw2_init_fix(info
, linebytes
);
330 err
= register_framebuffer(info
);
332 goto out_unmap_screen
;
334 dev_set_drvdata(&op
->dev
, info
);
336 printk(KERN_INFO
"%s: bwtwo at %lx:%lx\n",
337 dp
->full_name
, par
->which_io
, info
->fix
.smem_start
);
342 of_iounmap(&op
->resource
[0], info
->screen_base
, info
->fix
.smem_len
);
345 of_iounmap(&op
->resource
[0], par
->regs
, sizeof(struct bw2_regs
));
348 framebuffer_release(info
);
354 static int __devexit
bw2_remove(struct of_device
*op
)
356 struct fb_info
*info
= dev_get_drvdata(&op
->dev
);
357 struct bw2_par
*par
= info
->par
;
359 unregister_framebuffer(info
);
361 of_iounmap(&op
->resource
[0], par
->regs
, sizeof(struct bw2_regs
));
362 of_iounmap(&op
->resource
[0], info
->screen_base
, info
->fix
.smem_len
);
364 framebuffer_release(info
);
366 dev_set_drvdata(&op
->dev
, NULL
);
371 static const struct of_device_id bw2_match
[] = {
377 MODULE_DEVICE_TABLE(of
, bw2_match
);
379 static struct of_platform_driver bw2_driver
= {
381 .match_table
= bw2_match
,
383 .remove
= __devexit_p(bw2_remove
),
386 static int __init
bw2_init(void)
388 if (fb_get_options("bw2fb", NULL
))
391 return of_register_driver(&bw2_driver
, &of_bus_type
);
394 static void __exit
bw2_exit(void)
396 of_unregister_driver(&bw2_driver
);
399 module_init(bw2_init
);
400 module_exit(bw2_exit
);
402 MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets");
403 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
404 MODULE_VERSION("2.0");
405 MODULE_LICENSE("GPL");