1 // SPDX-License-Identifier: GPL-2.0-only
2 /* bw2.c: BWTWO frame buffer driver
4 * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
5 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
6 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
7 * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
9 * Driver layout based loosely on tgafb.c, see that file for credits.
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
16 #include <linux/delay.h>
17 #include <linux/init.h>
21 #include <linux/platform_device.h>
32 static int bw2_blank(int, struct fb_info *);
34 static int bw2_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma);
35 static int bw2_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);
38 * Frame buffer operations
41 static const struct fb_ops bw2_ops = {
43 FB_DEFAULT_SBUS_OPS(bw2),
44 .fb_blank = bw2_blank,
47 /* OBio addresses for the bwtwo registers */
48 #define BWTWO_REGISTER_OFFSET 0x400000
68 u8 v_blank_start_high;
73 u8 xfer_holdoff_start;
77 /* Status Register Constants */
78 #define BWTWO_SR_RES_MASK 0x70
79 #define BWTWO_SR_1600_1280 0x50
80 #define BWTWO_SR_1152_900_76_A 0x40
81 #define BWTWO_SR_1152_900_76_B 0x60
82 #define BWTWO_SR_ID_MASK 0x0f
83 #define BWTWO_SR_ID_MONO 0x02
84 #define BWTWO_SR_ID_MONO_ECL 0x03
85 #define BWTWO_SR_ID_MSYNC 0x04
86 #define BWTWO_SR_ID_NOCONN 0x0a
88 /* Control Register Constants */
89 #define BWTWO_CTL_ENABLE_INTS 0x80
90 #define BWTWO_CTL_ENABLE_VIDEO 0x40
91 #define BWTWO_CTL_ENABLE_TIMING 0x20
92 #define BWTWO_CTL_ENABLE_CURCMP 0x10
93 #define BWTWO_CTL_XTAL_MASK 0x0C
94 #define BWTWO_CTL_DIVISOR_MASK 0x03
96 /* Status Register Constants */
97 #define BWTWO_STAT_PENDING_INT 0x80
98 #define BWTWO_STAT_MSENSE_MASK 0x70
99 #define BWTWO_STAT_ID_MASK 0x0f
103 struct bw2_regs __iomem *regs;
106 #define BW2_FLAG_BLANKED 0x00000001
108 unsigned long which_io;
112 * bw2_blank - Optional function. Blanks the display.
113 * @blank: the blank mode we want.
114 * @info: frame buffer structure that represents a single frame buffer
117 bw2_blank(int blank, struct fb_info *info)
119 struct bw2_par *par = (struct bw2_par *) info->par;
120 struct bw2_regs __iomem *regs = par->regs;
124 spin_lock_irqsave(&par->lock, flags);
127 case FB_BLANK_UNBLANK: /* Unblanking */
128 val = sbus_readb(®s->control);
129 val |= BWTWO_CTL_ENABLE_VIDEO;
130 sbus_writeb(val, ®s->control);
131 par->flags &= ~BW2_FLAG_BLANKED;
134 case FB_BLANK_NORMAL: /* Normal blanking */
135 case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
136 case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
137 case FB_BLANK_POWERDOWN: /* Poweroff */
138 val = sbus_readb(®s->control);
139 val &= ~BWTWO_CTL_ENABLE_VIDEO;
140 sbus_writeb(val, ®s->control);
141 par->flags |= BW2_FLAG_BLANKED;
145 spin_unlock_irqrestore(&par->lock, flags);
150 static struct sbus_mmap_map bw2_mmap_map[] = {
152 .size = SBUS_MMAP_FBSIZE(1)
157 static int bw2_sbusfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
159 struct bw2_par *par = (struct bw2_par *)info->par;
161 return sbusfb_mmap_helper(bw2_mmap_map,
162 info->fix.smem_start, info->fix.smem_len,
167 static int bw2_sbusfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
169 return sbusfb_ioctl_helper(cmd, arg, info,
170 FBTYPE_SUN2BW, 1, info->fix.smem_len);
177 static void bw2_init_fix(struct fb_info *info, int linebytes)
179 strscpy(info->fix.id, "bwtwo", sizeof(info->fix.id));
181 info->fix.type = FB_TYPE_PACKED_PIXELS;
182 info->fix.visual = FB_VISUAL_MONO01;
184 info->fix.line_length = linebytes;
186 info->fix.accel = FB_ACCEL_SUN_BWTWO;
189 static u8 bw2regs_1600[] = {
190 0x14, 0x8b, 0x15, 0x28, 0x16, 0x03, 0x17, 0x13,
191 0x18, 0x7b, 0x19, 0x05, 0x1a, 0x34, 0x1b, 0x2e,
192 0x1c, 0x00, 0x1d, 0x0a, 0x1e, 0xff, 0x1f, 0x01,
196 static u8 bw2regs_ecl[] = {
197 0x14, 0x65, 0x15, 0x1e, 0x16, 0x04, 0x17, 0x0c,
198 0x18, 0x5e, 0x19, 0x03, 0x1a, 0xa7, 0x1b, 0x23,
199 0x1c, 0x00, 0x1d, 0x08, 0x1e, 0xff, 0x1f, 0x01,
203 static u8 bw2regs_analog[] = {
204 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x03, 0x17, 0x13,
205 0x18, 0xb0, 0x19, 0x03, 0x1a, 0xa6, 0x1b, 0x22,
206 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
210 static u8 bw2regs_76hz[] = {
211 0x14, 0xb7, 0x15, 0x27, 0x16, 0x03, 0x17, 0x0f,
212 0x18, 0xae, 0x19, 0x03, 0x1a, 0xae, 0x1b, 0x2a,
213 0x1c, 0x01, 0x1d, 0x09, 0x1e, 0xff, 0x1f, 0x01,
217 static u8 bw2regs_66hz[] = {
218 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x04, 0x17, 0x14,
219 0x18, 0xae, 0x19, 0x03, 0x1a, 0xa8, 0x1b, 0x24,
220 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01,
224 static int bw2_do_default_mode(struct bw2_par *par, struct fb_info *info,
230 status = sbus_readb(&par->regs->status);
231 mon = status & BWTWO_SR_RES_MASK;
232 switch (status & BWTWO_SR_ID_MASK) {
233 case BWTWO_SR_ID_MONO_ECL:
234 if (mon == BWTWO_SR_1600_1280) {
236 info->var.xres = info->var.xres_virtual = 1600;
237 info->var.yres = info->var.yres_virtual = 1280;
238 *linebytes = 1600 / 8;
243 case BWTWO_SR_ID_MONO:
247 case BWTWO_SR_ID_MSYNC:
248 if (mon == BWTWO_SR_1152_900_76_A ||
249 mon == BWTWO_SR_1152_900_76_B)
255 case BWTWO_SR_ID_NOCONN:
259 printk(KERN_ERR "bw2: can't handle SR %02x\n",
263 for ( ; *p; p += 2) {
264 u8 __iomem *regp = &((u8 __iomem *)par->regs)[p[0]];
265 sbus_writeb(p[1], regp);
270 static int bw2_probe(struct platform_device *op)
272 struct device_node *dp = op->dev.of_node;
273 struct fb_info *info;
277 info = framebuffer_alloc(sizeof(struct bw2_par), &op->dev);
284 spin_lock_init(&par->lock);
286 info->fix.smem_start = op->resource[0].start;
287 par->which_io = op->resource[0].flags & IORESOURCE_BITS;
289 sbusfb_fill_var(&info->var, dp, 1);
290 linebytes = of_getintprop_default(dp, "linebytes",
293 info->var.red.length = info->var.green.length =
294 info->var.blue.length = info->var.bits_per_pixel;
295 info->var.red.offset = info->var.green.offset =
296 info->var.blue.offset = 0;
298 par->regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET,
299 sizeof(struct bw2_regs), "bw2 regs");
303 if (!of_property_present(dp, "width")) {
304 err = bw2_do_default_mode(par, info, &linebytes);
309 info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
311 info->fbops = &bw2_ops;
313 info->screen_base = of_ioremap(&op->resource[0], 0,
314 info->fix.smem_len, "bw2 ram");
315 if (!info->screen_base) {
320 bw2_blank(FB_BLANK_UNBLANK, info);
322 bw2_init_fix(info, linebytes);
324 err = register_framebuffer(info);
326 goto out_unmap_screen;
328 dev_set_drvdata(&op->dev, info);
330 printk(KERN_INFO "%pOF: bwtwo at %lx:%lx\n",
331 dp, par->which_io, info->fix.smem_start);
336 of_iounmap(&op->resource[0], info->screen_base, info->fix.smem_len);
339 of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
342 framebuffer_release(info);
348 static void bw2_remove(struct platform_device *op)
350 struct fb_info *info = dev_get_drvdata(&op->dev);
351 struct bw2_par *par = info->par;
353 unregister_framebuffer(info);
355 of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
356 of_iounmap(&op->resource[0], info->screen_base, info->fix.smem_len);
358 framebuffer_release(info);
361 static const struct of_device_id bw2_match[] = {
367 MODULE_DEVICE_TABLE(of, bw2_match);
369 static struct platform_driver bw2_driver = {
372 .of_match_table = bw2_match,
375 .remove_new = bw2_remove,
378 static int __init bw2_init(void)
380 if (fb_get_options("bw2fb", NULL))
383 return platform_driver_register(&bw2_driver);
386 static void __exit bw2_exit(void)
388 platform_driver_unregister(&bw2_driver);
391 module_init(bw2_init);
392 module_exit(bw2_exit);
394 MODULE_DESCRIPTION("framebuffer driver for BWTWO chipsets");
395 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
396 MODULE_VERSION("2.0");
397 MODULE_LICENSE("GPL");