123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- /*
- * linux/drivers/video/pmag-aa-fb.c
- * Copyright 2002 Karsten Merker <merker@debian.org>
- *
- * PMAG-AA TurboChannel framebuffer card support ... derived from
- * pmag-ba-fb.c, which is Copyright (C) 1999, 2000, 2001 by
- * Michael Engel <engel@unix-ag.org>, Karsten Merker <merker@debian.org>
- * and Harald Koerfgen <hkoerfg@web.de>, which itself is derived from
- * "HP300 Topcat framebuffer support (derived from macfb of all things)
- * Phil Blundell <philb@gnu.org> 1998"
- * Copyright (c) 2016 Maciej W. Rozycki
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
- *
- * 2002-09-28 Karsten Merker <merker@linuxtag.org>
- * Version 0.01: First try to get a PMAG-AA running.
- *
- * 2003-02-24 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
- * Version 0.02: Major code cleanup.
- *
- * 2003-09-21 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
- * Hardware cursor support.
- *
- * 2016-02-21 Maciej W. Rozycki <macro@linux-mips.org>
- * Version 0.03: Rewritten for the new FB and TC APIs.
- */
- #include <linux/compiler.h>
- #include <linux/errno.h>
- #include <linux/fb.h>
- #include <linux/init.h>
- #include <linux/io.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/tc.h>
- #include <linux/timer.h>
- #include "bt455.h"
- #include "bt431.h"
- /* Version information */
- #define DRIVER_VERSION "0.03"
- #define DRIVER_AUTHOR "Karsten Merker <merker@linuxtag.org>"
- #define DRIVER_DESCRIPTION "PMAG-AA Framebuffer Driver"
- /*
- * Bt455 RAM DAC register base offset (rel. to TC slot base address).
- */
- #define PMAG_AA_BT455_OFFSET 0x100000
- /*
- * Bt431 cursor generator offset (rel. to TC slot base address).
- */
- #define PMAG_AA_BT431_OFFSET 0x180000
- /*
- * Begin of PMAG-AA framebuffer memory relative to TC slot address,
- * resolution is 1280x1024x1 (8 bits deep, but only LSB is used).
- */
- #define PMAG_AA_ONBOARD_FBMEM_OFFSET 0x200000
- struct aafb_par {
- void __iomem *mmio;
- struct bt455_regs __iomem *bt455;
- struct bt431_regs __iomem *bt431;
- };
- static struct fb_var_screeninfo aafb_defined = {
- .xres = 1280,
- .yres = 1024,
- .xres_virtual = 2048,
- .yres_virtual = 1024,
- .bits_per_pixel = 8,
- .grayscale = 1,
- .red.length = 0,
- .green.length = 1,
- .blue.length = 0,
- .activate = FB_ACTIVATE_NOW,
- .accel_flags = FB_ACCEL_NONE,
- .pixclock = 7645,
- .left_margin = 224,
- .right_margin = 32,
- .upper_margin = 33,
- .lower_margin = 3,
- .hsync_len = 160,
- .vsync_len = 3,
- .sync = FB_SYNC_ON_GREEN,
- .vmode = FB_VMODE_NONINTERLACED,
- };
- static struct fb_fix_screeninfo aafb_fix = {
- .id = "PMAG-AA",
- .smem_len = (2048 * 1024),
- .type = FB_TYPE_PACKED_PIXELS,
- .visual = FB_VISUAL_MONO10,
- .ypanstep = 1,
- .ywrapstep = 1,
- .line_length = 2048,
- .mmio_len = PMAG_AA_ONBOARD_FBMEM_OFFSET - PMAG_AA_BT455_OFFSET,
- };
- static int aafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
- {
- struct aafb_par *par = info->par;
- if (cursor->image.height > BT431_CURSOR_SIZE ||
- cursor->image.width > BT431_CURSOR_SIZE) {
- bt431_erase_cursor(par->bt431);
- return -EINVAL;
- }
- if (!cursor->enable)
- bt431_erase_cursor(par->bt431);
- if (cursor->set & FB_CUR_SETPOS)
- bt431_position_cursor(par->bt431,
- cursor->image.dx, cursor->image.dy);
- if (cursor->set & FB_CUR_SETCMAP) {
- u8 fg = cursor->image.fg_color ? 0xf : 0x0;
- u8 bg = cursor->image.bg_color ? 0xf : 0x0;
- bt455_write_cmap_entry(par->bt455, 8, bg);
- bt455_write_cmap_next(par->bt455, bg);
- bt455_write_ovly_next(par->bt455, fg);
- }
- if (cursor->set & (FB_CUR_SETSIZE | FB_CUR_SETSHAPE | FB_CUR_SETIMAGE))
- bt431_set_cursor(par->bt431,
- cursor->image.data, cursor->mask, cursor->rop,
- cursor->image.width, cursor->image.height);
- if (cursor->enable)
- bt431_enable_cursor(par->bt431);
- return 0;
- }
- /* 0 unblanks, any other blanks. */
- static int aafb_blank(int blank, struct fb_info *info)
- {
- struct aafb_par *par = info->par;
- u8 val = blank ? 0x00 : 0x0f;
- bt455_write_cmap_entry(par->bt455, 1, val);
- return 0;
- }
- static struct fb_ops aafb_ops = {
- .owner = THIS_MODULE,
- .fb_blank = aafb_blank,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_cursor = aafb_cursor,
- };
- static int pmagaafb_probe(struct device *dev)
- {
- struct tc_dev *tdev = to_tc_dev(dev);
- resource_size_t start, len;
- struct fb_info *info;
- struct aafb_par *par;
- int err;
- info = framebuffer_alloc(sizeof(struct aafb_par), dev);
- if (!info) {
- printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev));
- return -ENOMEM;
- }
- par = info->par;
- dev_set_drvdata(dev, info);
- info->fbops = &aafb_ops;
- info->fix = aafb_fix;
- info->var = aafb_defined;
- info->flags = FBINFO_DEFAULT;
- /* Request the I/O MEM resource. */
- start = tdev->resource.start;
- len = tdev->resource.end - start + 1;
- if (!request_mem_region(start, len, dev_name(dev))) {
- printk(KERN_ERR "%s: Cannot reserve FB region\n",
- dev_name(dev));
- err = -EBUSY;
- goto err_alloc;
- }
- /* MMIO mapping setup. */
- info->fix.mmio_start = start + PMAG_AA_BT455_OFFSET;
- par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
- if (!par->mmio) {
- printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev));
- err = -ENOMEM;
- goto err_resource;
- }
- par->bt455 = par->mmio - PMAG_AA_BT455_OFFSET + PMAG_AA_BT455_OFFSET;
- par->bt431 = par->mmio - PMAG_AA_BT455_OFFSET + PMAG_AA_BT431_OFFSET;
- /* Frame buffer mapping setup. */
- info->fix.smem_start = start + PMAG_AA_ONBOARD_FBMEM_OFFSET;
- info->screen_base = ioremap_nocache(info->fix.smem_start,
- info->fix.smem_len);
- if (!info->screen_base) {
- printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev));
- err = -ENOMEM;
- goto err_mmio_map;
- }
- info->screen_size = info->fix.smem_len;
- /* Init colormap. */
- bt455_write_cmap_entry(par->bt455, 0, 0x0);
- bt455_write_cmap_next(par->bt455, 0xf);
- /* Init hardware cursor. */
- bt431_erase_cursor(par->bt431);
- bt431_init_cursor(par->bt431);
- err = register_framebuffer(info);
- if (err < 0) {
- printk(KERN_ERR "%s: Cannot register framebuffer\n",
- dev_name(dev));
- goto err_smem_map;
- }
- get_device(dev);
- pr_info("fb%d: %s frame buffer device at %s\n",
- info->node, info->fix.id, dev_name(dev));
- return 0;
- err_smem_map:
- iounmap(info->screen_base);
- err_mmio_map:
- iounmap(par->mmio);
- err_resource:
- release_mem_region(start, len);
- err_alloc:
- framebuffer_release(info);
- return err;
- }
- static int __exit pmagaafb_remove(struct device *dev)
- {
- struct tc_dev *tdev = to_tc_dev(dev);
- struct fb_info *info = dev_get_drvdata(dev);
- struct aafb_par *par = info->par;
- resource_size_t start, len;
- put_device(dev);
- unregister_framebuffer(info);
- iounmap(info->screen_base);
- iounmap(par->mmio);
- start = tdev->resource.start;
- len = tdev->resource.end - start + 1;
- release_mem_region(start, len);
- framebuffer_release(info);
- return 0;
- }
- /*
- * Initialise the framebuffer.
- */
- static const struct tc_device_id pmagaafb_tc_table[] = {
- { "DEC ", "PMAG-AA " },
- { }
- };
- MODULE_DEVICE_TABLE(tc, pmagaafb_tc_table);
- static struct tc_driver pmagaafb_driver = {
- .id_table = pmagaafb_tc_table,
- .driver = {
- .name = "pmagaafb",
- .bus = &tc_bus_type,
- .probe = pmagaafb_probe,
- .remove = __exit_p(pmagaafb_remove),
- },
- };
- static int __init pmagaafb_init(void)
- {
- #ifndef MODULE
- if (fb_get_options("pmagaafb", NULL))
- return -ENXIO;
- #endif
- return tc_register_driver(&pmagaafb_driver);
- }
- static void __exit pmagaafb_exit(void)
- {
- tc_unregister_driver(&pmagaafb_driver);
- }
- module_init(pmagaafb_init);
- module_exit(pmagaafb_exit);
- MODULE_AUTHOR(DRIVER_AUTHOR);
- MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
- MODULE_LICENSE("GPL");
|