diff options
Diffstat (limited to 'drivers/video/hpfb.c')
-rw-r--r-- | drivers/video/hpfb.c | 429 |
1 files changed, 0 insertions, 429 deletions
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c deleted file mode 100644 index a1b7e5fa9b0..00000000000 --- a/drivers/video/hpfb.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * HP300 Topcat framebuffer support (derived from macfb of all things) - * Phil Blundell <philb@gnu.org> 1998 - * DIO-II, colour map and Catseye support by - * Kars de Jong <jongk@linux-m68k.org>, May 2004. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/fb.h> -#include <linux/dio.h> - -#include <asm/io.h> -#include <asm/uaccess.h> - -static struct fb_info fb_info = { - .fix = { - .id = "HP300 ", - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_PSEUDOCOLOR, - .accel = FB_ACCEL_NONE, - } -}; - -static unsigned long fb_regs; -static unsigned char fb_bitmask; - -#define TC_NBLANK 0x4080 -#define TC_WEN 0x4088 -#define TC_REN 0x408c -#define TC_FBEN 0x4090 -#define TC_PRR 0x40ea - -/* These defines match the X window system */ -#define RR_CLEAR 0x0 -#define RR_COPY 0x3 -#define RR_NOOP 0x5 -#define RR_XOR 0x6 -#define RR_INVERT 0xa -#define RR_COPYINVERTED 0xc -#define RR_SET 0xf - -/* blitter regs */ -#define BUSY 0x4044 -#define WMRR 0x40ef -#define SOURCE_X 0x40f2 -#define SOURCE_Y 0x40f6 -#define DEST_X 0x40fa -#define DEST_Y 0x40fe -#define WHEIGHT 0x4106 -#define WWIDTH 0x4102 -#define WMOVE 0x409c - -static struct fb_var_screeninfo hpfb_defined = { - .red = { - .length = 8, - }, - .green = { - .length = 8, - }, - .blue = { - .length = 8, - }, - .activate = FB_ACTIVATE_NOW, - .height = -1, - .width = -1, - .vmode = FB_VMODE_NONINTERLACED, -}; - -static int hpfb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info) -{ - /* use MSBs */ - unsigned char _red =red>>8; - unsigned char _green=green>>8; - unsigned char _blue =blue>>8; - unsigned char _regno=regno; - - /* - * Set a single color register. The values supplied are - * already rounded down to the hardware's capabilities - * (according to the entries in the `var' structure). Return - * != 0 for invalid regno. - */ - - if (regno >= info->cmap.len) - return 1; - - while (in_be16(fb_regs + 0x6002) & 0x4) udelay(1); - - out_be16(fb_regs + 0x60ba, 0xff); - - out_be16(fb_regs + 0x60b2, _red); - out_be16(fb_regs + 0x60b4, _green); - out_be16(fb_regs + 0x60b6, _blue); - out_be16(fb_regs + 0x60b8, ~_regno); - out_be16(fb_regs + 0x60f0, 0xff); - - udelay(100); - - while (in_be16(fb_regs + 0x6002) & 0x4) udelay(1); - out_be16(fb_regs + 0x60b2, 0); - out_be16(fb_regs + 0x60b4, 0); - out_be16(fb_regs + 0x60b6, 0); - out_be16(fb_regs + 0x60b8, 0); - - return 0; -} - -/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ - -static int hpfb_blank(int blank, struct fb_info *info) -{ - out_8(fb_regs + TC_NBLANK, (blank ? 0x00 : fb_bitmask)); - - return 0; -} - -static void topcat_blit(int x0, int y0, int x1, int y1, int w, int h, int rr) -{ - if (rr >= 0) { - while (in_8(fb_regs + BUSY) & fb_bitmask) - ; - } - out_8(fb_regs + TC_FBEN, fb_bitmask); - if (rr >= 0) { - out_8(fb_regs + TC_WEN, fb_bitmask); - out_8(fb_regs + WMRR, rr); - } - out_be16(fb_regs + SOURCE_X, x0); - out_be16(fb_regs + SOURCE_Y, y0); - out_be16(fb_regs + DEST_X, x1); - out_be16(fb_regs + DEST_Y, y1); - out_be16(fb_regs + WWIDTH, w); - out_be16(fb_regs + WHEIGHT, h); - out_8(fb_regs + WMOVE, fb_bitmask); -} - -static void hpfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) -{ - topcat_blit(area->sx, area->sy, area->dx, area->dy, area->width, area->height, RR_COPY); -} - -static void hpfb_fillrect(struct fb_info *p, const struct fb_fillrect *region) -{ - u8 clr; - - clr = region->color & 0xff; - - while (in_8(fb_regs + BUSY) & fb_bitmask) - ; - - /* Foreground */ - out_8(fb_regs + TC_WEN, fb_bitmask & clr); - out_8(fb_regs + WMRR, (region->rop == ROP_COPY ? RR_SET : RR_INVERT)); - - /* Background */ - out_8(fb_regs + TC_WEN, fb_bitmask & ~clr); - out_8(fb_regs + WMRR, (region->rop == ROP_COPY ? RR_CLEAR : RR_NOOP)); - - topcat_blit(region->dx, region->dy, region->dx, region->dy, region->width, region->height, -1); -} - -static int hpfb_sync(struct fb_info *info) -{ - /* - * Since we also access the framebuffer directly, we have to wait - * until the block mover is finished - */ - while (in_8(fb_regs + BUSY) & fb_bitmask) - ; - - out_8(fb_regs + TC_WEN, fb_bitmask); - out_8(fb_regs + TC_PRR, RR_COPY); - out_8(fb_regs + TC_FBEN, fb_bitmask); - - return 0; -} - -static struct fb_ops hpfb_ops = { - .owner = THIS_MODULE, - .fb_setcolreg = hpfb_setcolreg, - .fb_blank = hpfb_blank, - .fb_fillrect = hpfb_fillrect, - .fb_copyarea = hpfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_sync = hpfb_sync, -}; - -/* Common to all HP framebuffers */ -#define HPFB_FBWMSB 0x05 /* Frame buffer width */ -#define HPFB_FBWLSB 0x07 -#define HPFB_FBHMSB 0x09 /* Frame buffer height */ -#define HPFB_FBHLSB 0x0b -#define HPFB_DWMSB 0x0d /* Display width */ -#define HPFB_DWLSB 0x0f -#define HPFB_DHMSB 0x11 /* Display height */ -#define HPFB_DHLSB 0x13 -#define HPFB_NUMPLANES 0x5b /* Number of colour planes */ -#define HPFB_FBOMSB 0x5d /* Frame buffer offset */ -#define HPFB_FBOLSB 0x5f - -static int hpfb_init_one(unsigned long phys_base, unsigned long virt_base) -{ - unsigned long fboff, fb_width, fb_height, fb_start; - int ret; - - fb_regs = virt_base; - fboff = (in_8(fb_regs + HPFB_FBOMSB) << 8) | in_8(fb_regs + HPFB_FBOLSB); - - fb_info.fix.smem_start = (in_8(fb_regs + fboff) << 16); - - if (phys_base >= DIOII_BASE) { - fb_info.fix.smem_start += phys_base; - } - - if (DIO_SECID(fb_regs) != DIO_ID2_TOPCAT) { - /* This is the magic incantation the HP X server uses to make Catseye boards work. */ - while (in_be16(fb_regs+0x4800) & 1) - ; - out_be16(fb_regs+0x4800, 0); /* Catseye status */ - out_be16(fb_regs+0x4510, 0); /* VB */ - out_be16(fb_regs+0x4512, 0); /* TCNTRL */ - out_be16(fb_regs+0x4514, 0); /* ACNTRL */ - out_be16(fb_regs+0x4516, 0); /* PNCNTRL */ - out_be16(fb_regs+0x4206, 0x90); /* RUG Command/Status */ - out_be16(fb_regs+0x60a2, 0); /* Overlay Mask */ - out_be16(fb_regs+0x60bc, 0); /* Ram Select */ - } - - /* - * Fill in the available video resolution - */ - fb_width = (in_8(fb_regs + HPFB_FBWMSB) << 8) | in_8(fb_regs + HPFB_FBWLSB); - fb_info.fix.line_length = fb_width; - fb_height = (in_8(fb_regs + HPFB_FBHMSB) << 8) | in_8(fb_regs + HPFB_FBHLSB); - fb_info.fix.smem_len = fb_width * fb_height; - fb_start = (unsigned long)ioremap_writethrough(fb_info.fix.smem_start, - fb_info.fix.smem_len); - hpfb_defined.xres = (in_8(fb_regs + HPFB_DWMSB) << 8) | in_8(fb_regs + HPFB_DWLSB); - hpfb_defined.yres = (in_8(fb_regs + HPFB_DHMSB) << 8) | in_8(fb_regs + HPFB_DHLSB); - hpfb_defined.xres_virtual = hpfb_defined.xres; - hpfb_defined.yres_virtual = hpfb_defined.yres; - hpfb_defined.bits_per_pixel = in_8(fb_regs + HPFB_NUMPLANES); - - printk(KERN_INFO "hpfb: framebuffer at 0x%lx, mapped to 0x%lx, size %dk\n", - fb_info.fix.smem_start, fb_start, fb_info.fix.smem_len/1024); - printk(KERN_INFO "hpfb: mode is %dx%dx%d, linelength=%d\n", - hpfb_defined.xres, hpfb_defined.yres, hpfb_defined.bits_per_pixel, fb_info.fix.line_length); - - /* - * Give the hardware a bit of a prod and work out how many bits per - * pixel are supported. - */ - out_8(fb_regs + TC_WEN, 0xff); - out_8(fb_regs + TC_PRR, RR_COPY); - out_8(fb_regs + TC_FBEN, 0xff); - out_8(fb_start, 0xff); - fb_bitmask = in_8(fb_start); - out_8(fb_start, 0); - - /* - * Enable reading/writing of all the planes. - */ - out_8(fb_regs + TC_WEN, fb_bitmask); - out_8(fb_regs + TC_PRR, RR_COPY); - out_8(fb_regs + TC_REN, fb_bitmask); - out_8(fb_regs + TC_FBEN, fb_bitmask); - - /* - * Clear the screen. - */ - topcat_blit(0, 0, 0, 0, fb_width, fb_height, RR_CLEAR); - - /* - * Let there be consoles.. - */ - if (DIO_SECID(fb_regs) == DIO_ID2_TOPCAT) - strcat(fb_info.fix.id, "Topcat"); - else - strcat(fb_info.fix.id, "Catseye"); - fb_info.fbops = &hpfb_ops; - fb_info.flags = FBINFO_DEFAULT; - fb_info.var = hpfb_defined; - fb_info.screen_base = (char *)fb_start; - - ret = fb_alloc_cmap(&fb_info.cmap, 1 << hpfb_defined.bits_per_pixel, 0); - if (ret < 0) - goto unmap_screen_base; - - ret = register_framebuffer(&fb_info); - if (ret < 0) - goto dealloc_cmap; - - fb_info(&fb_info, "%s frame buffer device\n", fb_info.fix.id); - - return 0; - -dealloc_cmap: - fb_dealloc_cmap(&fb_info.cmap); - -unmap_screen_base: - if (fb_info.screen_base) { - iounmap(fb_info.screen_base); - fb_info.screen_base = NULL; - } - - return ret; -} - -/* - * Check that the secondary ID indicates that we have some hope of working with this - * framebuffer. The catseye boards are pretty much like topcats and we can muddle through. - */ - -#define topcat_sid_ok(x) (((x) == DIO_ID2_LRCATSEYE) || ((x) == DIO_ID2_HRCCATSEYE) \ - || ((x) == DIO_ID2_HRMCATSEYE) || ((x) == DIO_ID2_TOPCAT)) - -/* - * Initialise the framebuffer - */ -static int hpfb_dio_probe(struct dio_dev *d, const struct dio_device_id *ent) -{ - unsigned long paddr, vaddr; - - paddr = d->resource.start; - if (!request_mem_region(d->resource.start, resource_size(&d->resource), d->name)) - return -EBUSY; - - if (d->scode >= DIOII_SCBASE) { - vaddr = (unsigned long)ioremap(paddr, resource_size(&d->resource)); - } else { - vaddr = paddr + DIO_VIRADDRBASE; - } - printk(KERN_INFO "Topcat found at DIO select code %d " - "(secondary id %02x)\n", d->scode, (d->id >> 8) & 0xff); - if (hpfb_init_one(paddr, vaddr)) { - if (d->scode >= DIOII_SCBASE) - iounmap((void *)vaddr); - return -ENOMEM; - } - return 0; -} - -static void hpfb_remove_one(struct dio_dev *d) -{ - unregister_framebuffer(&fb_info); - if (d->scode >= DIOII_SCBASE) - iounmap((void *)fb_regs); - release_mem_region(d->resource.start, resource_size(&d->resource)); - fb_dealloc_cmap(&fb_info.cmap); - if (fb_info.screen_base) - iounmap(fb_info.screen_base); -} - -static struct dio_device_id hpfb_dio_tbl[] = { - { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_LRCATSEYE) }, - { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_HRCCATSEYE) }, - { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_HRMCATSEYE) }, - { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_TOPCAT) }, - { 0 } -}; - -static struct dio_driver hpfb_driver = { - .name = "hpfb", - .id_table = hpfb_dio_tbl, - .probe = hpfb_dio_probe, - .remove = hpfb_remove_one, -}; - -int __init hpfb_init(void) -{ - unsigned int sid; - mm_segment_t fs; - unsigned char i; - int err; - - /* Topcats can be on the internal IO bus or real DIO devices. - * The internal variant sits at 0x560000; it has primary - * and secondary ID registers just like the DIO version. - * So we merge the two detection routines. - * - * Perhaps this #define should be in a global header file: - * I believe it's common to all internal fbs, not just topcat. - */ -#define INTFBVADDR 0xf0560000 -#define INTFBPADDR 0x560000 - - if (!MACH_IS_HP300) - return -ENODEV; - - if (fb_get_options("hpfb", NULL)) - return -ENODEV; - - err = dio_register_driver(&hpfb_driver); - if (err) - return err; - - fs = get_fs(); - set_fs(KERNEL_DS); - err = get_user(i, (unsigned char *)INTFBVADDR + DIO_IDOFF); - set_fs(fs); - - if (!err && (i == DIO_ID_FBUFFER) && topcat_sid_ok(sid = DIO_SECID(INTFBVADDR))) { - if (!request_mem_region(INTFBPADDR, DIO_DEVSIZE, "Internal Topcat")) - return -EBUSY; - printk(KERN_INFO "Internal Topcat found (secondary id %02x)\n", sid); - if (hpfb_init_one(INTFBPADDR, INTFBVADDR)) { - return -ENOMEM; - } - } - return 0; -} - -void __exit hpfb_cleanup_module(void) -{ - dio_unregister_driver(&hpfb_driver); -} - -module_init(hpfb_init); -module_exit(hpfb_cleanup_module); - -MODULE_LICENSE("GPL"); |