2 * linux/drivers/video/pmag-aa-fb.c
3 * Copyright 2002 Karsten Merker <merker@debian.org>
5 * PMAG-AA TurboChannel framebuffer card support ... derived from
6 * pmag-ba-fb.c, which is Copyright (C) 1999, 2000, 2001 by
7 * Michael Engel <engel@unix-ag.org>, Karsten Merker <merker@debian.org>
8 * and Harald Koerfgen <hkoerfg@web.de>, which itself is derived from
9 * "HP300 Topcat framebuffer support (derived from macfb of all things)
10 * Phil Blundell <philb@gnu.org> 1998"
11 * Copyright (c) 2016 Maciej W. Rozycki
13 * This file is subject to the terms and conditions of the GNU General
14 * Public License. See the file COPYING in the main directory of this
15 * archive for more details.
17 * 2002-09-28 Karsten Merker <merker@linuxtag.org>
18 * Version 0.01: First try to get a PMAG-AA running.
20 * 2003-02-24 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
21 * Version 0.02: Major code cleanup.
23 * 2003-09-21 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
24 * Hardware cursor support.
26 * 2016-02-21 Maciej W. Rozycki <macro@linux-mips.org>
27 * Version 0.03: Rewritten for the new FB and TC APIs.
30 #include <linux/compiler.h>
31 #include <linux/errno.h>
33 #include <linux/init.h>
35 #include <linux/kernel.h>
36 #include <linux/module.h>
38 #include <linux/timer.h>
43 /* Version information */
44 #define DRIVER_VERSION "0.03"
45 #define DRIVER_AUTHOR "Karsten Merker <merker@linuxtag.org>"
46 #define DRIVER_DESCRIPTION "PMAG-AA Framebuffer Driver"
49 * Bt455 RAM DAC register base offset (rel. to TC slot base address).
51 #define PMAG_AA_BT455_OFFSET 0x100000
54 * Bt431 cursor generator offset (rel. to TC slot base address).
56 #define PMAG_AA_BT431_OFFSET 0x180000
59 * Begin of PMAG-AA framebuffer memory relative to TC slot address,
60 * resolution is 1280x1024x1 (8 bits deep, but only LSB is used).
62 #define PMAG_AA_ONBOARD_FBMEM_OFFSET 0x200000
66 struct bt455_regs __iomem
*bt455
;
67 struct bt431_regs __iomem
*bt431
;
70 static const struct fb_var_screeninfo aafb_defined
= {
80 .activate
= FB_ACTIVATE_NOW
,
81 .accel_flags
= FB_ACCEL_NONE
,
89 .sync
= FB_SYNC_ON_GREEN
,
90 .vmode
= FB_VMODE_NONINTERLACED
,
93 static const struct fb_fix_screeninfo aafb_fix
= {
95 .smem_len
= (2048 * 1024),
96 .type
= FB_TYPE_PACKED_PIXELS
,
97 .visual
= FB_VISUAL_MONO10
,
101 .mmio_len
= PMAG_AA_ONBOARD_FBMEM_OFFSET
- PMAG_AA_BT455_OFFSET
,
104 static int aafb_cursor(struct fb_info
*info
, struct fb_cursor
*cursor
)
106 struct aafb_par
*par
= info
->par
;
108 if (cursor
->image
.height
> BT431_CURSOR_SIZE
||
109 cursor
->image
.width
> BT431_CURSOR_SIZE
) {
110 bt431_erase_cursor(par
->bt431
);
115 bt431_erase_cursor(par
->bt431
);
117 if (cursor
->set
& FB_CUR_SETPOS
)
118 bt431_position_cursor(par
->bt431
,
119 cursor
->image
.dx
, cursor
->image
.dy
);
120 if (cursor
->set
& FB_CUR_SETCMAP
) {
121 u8 fg
= cursor
->image
.fg_color
? 0xf : 0x0;
122 u8 bg
= cursor
->image
.bg_color
? 0xf : 0x0;
124 bt455_write_cmap_entry(par
->bt455
, 8, bg
);
125 bt455_write_cmap_next(par
->bt455
, bg
);
126 bt455_write_ovly_next(par
->bt455
, fg
);
128 if (cursor
->set
& (FB_CUR_SETSIZE
| FB_CUR_SETSHAPE
| FB_CUR_SETIMAGE
))
129 bt431_set_cursor(par
->bt431
,
130 cursor
->image
.data
, cursor
->mask
, cursor
->rop
,
131 cursor
->image
.width
, cursor
->image
.height
);
134 bt431_enable_cursor(par
->bt431
);
139 /* 0 unblanks, any other blanks. */
141 static int aafb_blank(int blank
, struct fb_info
*info
)
143 struct aafb_par
*par
= info
->par
;
144 u8 val
= blank
? 0x00 : 0x0f;
146 bt455_write_cmap_entry(par
->bt455
, 1, val
);
150 static struct fb_ops aafb_ops
= {
151 .owner
= THIS_MODULE
,
152 .fb_blank
= aafb_blank
,
153 .fb_fillrect
= cfb_fillrect
,
154 .fb_copyarea
= cfb_copyarea
,
155 .fb_imageblit
= cfb_imageblit
,
156 .fb_cursor
= aafb_cursor
,
159 static int pmagaafb_probe(struct device
*dev
)
161 struct tc_dev
*tdev
= to_tc_dev(dev
);
162 resource_size_t start
, len
;
163 struct fb_info
*info
;
164 struct aafb_par
*par
;
167 info
= framebuffer_alloc(sizeof(struct aafb_par
), dev
);
169 printk(KERN_ERR
"%s: Cannot allocate memory\n", dev_name(dev
));
174 dev_set_drvdata(dev
, info
);
176 info
->fbops
= &aafb_ops
;
177 info
->fix
= aafb_fix
;
178 info
->var
= aafb_defined
;
179 info
->flags
= FBINFO_DEFAULT
;
181 /* Request the I/O MEM resource. */
182 start
= tdev
->resource
.start
;
183 len
= tdev
->resource
.end
- start
+ 1;
184 if (!request_mem_region(start
, len
, dev_name(dev
))) {
185 printk(KERN_ERR
"%s: Cannot reserve FB region\n",
191 /* MMIO mapping setup. */
192 info
->fix
.mmio_start
= start
+ PMAG_AA_BT455_OFFSET
;
193 par
->mmio
= ioremap_nocache(info
->fix
.mmio_start
, info
->fix
.mmio_len
);
195 printk(KERN_ERR
"%s: Cannot map MMIO\n", dev_name(dev
));
199 par
->bt455
= par
->mmio
- PMAG_AA_BT455_OFFSET
+ PMAG_AA_BT455_OFFSET
;
200 par
->bt431
= par
->mmio
- PMAG_AA_BT455_OFFSET
+ PMAG_AA_BT431_OFFSET
;
202 /* Frame buffer mapping setup. */
203 info
->fix
.smem_start
= start
+ PMAG_AA_ONBOARD_FBMEM_OFFSET
;
204 info
->screen_base
= ioremap_nocache(info
->fix
.smem_start
,
206 if (!info
->screen_base
) {
207 printk(KERN_ERR
"%s: Cannot map FB\n", dev_name(dev
));
211 info
->screen_size
= info
->fix
.smem_len
;
214 bt455_write_cmap_entry(par
->bt455
, 0, 0x0);
215 bt455_write_cmap_next(par
->bt455
, 0xf);
217 /* Init hardware cursor. */
218 bt431_erase_cursor(par
->bt431
);
219 bt431_init_cursor(par
->bt431
);
221 err
= register_framebuffer(info
);
223 printk(KERN_ERR
"%s: Cannot register framebuffer\n",
230 pr_info("fb%d: %s frame buffer device at %s\n",
231 info
->node
, info
->fix
.id
, dev_name(dev
));
237 iounmap(info
->screen_base
);
243 release_mem_region(start
, len
);
246 framebuffer_release(info
);
250 static int pmagaafb_remove(struct device
*dev
)
252 struct tc_dev
*tdev
= to_tc_dev(dev
);
253 struct fb_info
*info
= dev_get_drvdata(dev
);
254 struct aafb_par
*par
= info
->par
;
255 resource_size_t start
, len
;
258 unregister_framebuffer(info
);
259 iounmap(info
->screen_base
);
261 start
= tdev
->resource
.start
;
262 len
= tdev
->resource
.end
- start
+ 1;
263 release_mem_region(start
, len
);
264 framebuffer_release(info
);
269 * Initialise the framebuffer.
271 static const struct tc_device_id pmagaafb_tc_table
[] = {
272 { "DEC ", "PMAG-AA " },
275 MODULE_DEVICE_TABLE(tc
, pmagaafb_tc_table
);
277 static struct tc_driver pmagaafb_driver
= {
278 .id_table
= pmagaafb_tc_table
,
282 .probe
= pmagaafb_probe
,
283 .remove
= pmagaafb_remove
,
287 static int __init
pmagaafb_init(void)
290 if (fb_get_options("pmagaafb", NULL
))
293 return tc_register_driver(&pmagaafb_driver
);
296 static void __exit
pmagaafb_exit(void)
298 tc_unregister_driver(&pmagaafb_driver
);
301 module_init(pmagaafb_init
);
302 module_exit(pmagaafb_exit
);
304 MODULE_AUTHOR(DRIVER_AUTHOR
);
305 MODULE_DESCRIPTION(DRIVER_DESCRIPTION
);
306 MODULE_LICENSE("GPL");